diff --git a/.changeset/afraid-buckets-yell.md b/.changeset/afraid-buckets-yell.md deleted file mode 100644 index 88e94692082..00000000000 --- a/.changeset/afraid-buckets-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Exposed Confirmed state to ChainWriter GetTransactionStatus method diff --git a/.changeset/angry-fishes-ring.md b/.changeset/angry-fishes-ring.md new file mode 100644 index 00000000000..86671967372 --- /dev/null +++ b/.changeset/angry-fishes-ring.md @@ -0,0 +1,8 @@ +--- +"chainlink": minor +--- + +#internal add getNextDonId() and getNodes(bytes32[] calldata p2pIds) in CapabilitiesRegistry and define interface for node info + + +PR issue: CCIP-3569 \ No newline at end of file diff --git a/.changeset/big-dots-report.md b/.changeset/big-dots-report.md deleted file mode 100644 index 01475010f0d..00000000000 --- a/.changeset/big-dots-report.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Updated ZK overflow detection to skip transactions with non-broadcasted attempts. Delayed detection for zkEVM using the MinAttempts config. Updated XLayer to use the same detection logic as zkEVM. #internal diff --git a/.changeset/big-kiwis-cross.md b/.changeset/big-kiwis-cross.md deleted file mode 100644 index 3bc450c20e5..00000000000 --- a/.changeset/big-kiwis-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Initialize start of v2.16.0 release diff --git a/.changeset/brave-ads-explode.md b/.changeset/brave-ads-explode.md new file mode 100644 index 00000000000..4be608e2d1d --- /dev/null +++ b/.changeset/brave-ads-explode.md @@ -0,0 +1,9 @@ +--- +"chainlink": patch +--- + +Remove finality depth as the default value for minConfirmation for tx jobs. +Update the sql query for fetching pending callback transactions: +if minConfirmation is not null, we check difference if the current block - tx block > minConfirmation +else we check if the tx block is <= finalizedBlock +#updated diff --git a/.changeset/calm-badgers-jump.md b/.changeset/calm-badgers-jump.md deleted file mode 100644 index 76f6e5d3121..00000000000 --- a/.changeset/calm-badgers-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -add error handling when arbitrum sequencer is not accessible #added diff --git a/.changeset/chatty-spiders-double.md b/.changeset/chatty-spiders-double.md deleted file mode 100644 index 750a11628fe..00000000000 --- a/.changeset/chatty-spiders-double.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -remove dependency on FinalityDepth in EVM TXM code. #internal diff --git a/.changeset/chilled-months-bow.md b/.changeset/chilled-months-bow.md new file mode 100644 index 00000000000..d3bbf7f97e3 --- /dev/null +++ b/.changeset/chilled-months-bow.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added oracle support in standard capabilities diff --git a/.changeset/chilled-plants-clap.md b/.changeset/chilled-plants-clap.md new file mode 100644 index 00000000000..2a23b0960f1 --- /dev/null +++ b/.changeset/chilled-plants-clap.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +The findBroadcastedAttempts in detectStuckTransactionsHeuristic can returns uninitialized struct that potentially cause nil pointer error. Changed the return type of findBroadcastedAttempts to be pointers and added nil pointer check. #bugfix diff --git a/.changeset/chilly-cars-attend.md b/.changeset/chilly-cars-attend.md deleted file mode 100644 index 2cb8323ab3c..00000000000 --- a/.changeset/chilly-cars-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -add error handle for gnosis chiado for seen tx #added diff --git a/.changeset/chilly-crews-retire.md b/.changeset/chilly-crews-retire.md new file mode 100644 index 00000000000..28b531a9ddb --- /dev/null +++ b/.changeset/chilly-crews-retire.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added log-event-trigger LOOPP capability, using ChainReader diff --git a/.changeset/cool-mirrors-beg.md b/.changeset/cool-mirrors-beg.md deleted file mode 100644 index a030ac7e3a6..00000000000 --- a/.changeset/cool-mirrors-beg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added L3X Config diff --git a/.changeset/cuddly-colts-speak.md b/.changeset/cuddly-colts-speak.md new file mode 100644 index 00000000000..ab16cc83123 --- /dev/null +++ b/.changeset/cuddly-colts-speak.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Fix for Mercury transmitter decoding reports of a different codec version #internal diff --git a/.changeset/curly-baboons-enjoy.md b/.changeset/curly-baboons-enjoy.md new file mode 100644 index 00000000000..440f394d23b --- /dev/null +++ b/.changeset/curly-baboons-enjoy.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Added the compute unit limit estimation feature for the Solana TXM #added diff --git a/.changeset/curvy-eyes-own.md b/.changeset/curvy-eyes-own.md new file mode 100644 index 00000000000..30e72a7cf57 --- /dev/null +++ b/.changeset/curvy-eyes-own.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Update dynamic fee types to align with geth #internal diff --git a/.changeset/early-glasses-rhyme.md b/.changeset/early-glasses-rhyme.md deleted file mode 100644 index aa35bf897ea..00000000000 --- a/.changeset/early-glasses-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -use FilteredLogs in EventBinding GetLatestValue instead of manual filtering. #internal diff --git a/.changeset/early-rules-yell.md b/.changeset/early-rules-yell.md new file mode 100644 index 00000000000..718f48063e8 --- /dev/null +++ b/.changeset/early-rules-yell.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated support aptos creation in chain config UI diff --git a/.changeset/eight-radios-hear.md b/.changeset/eight-radios-hear.md deleted file mode 100644 index b422f378326..00000000000 --- a/.changeset/eight-radios-hear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added merging core/capabilities/ccip from https://github.com/smartcontractkit/ccip diff --git a/.changeset/eight-rocks-notice.md b/.changeset/eight-rocks-notice.md deleted file mode 100644 index 230abaec481..00000000000 --- a/.changeset/eight-rocks-notice.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -New Mercury v4 report schema #added diff --git a/.changeset/eighty-bulldogs-smile.md b/.changeset/eighty-bulldogs-smile.md new file mode 100644 index 00000000000..c91d0cf58b7 --- /dev/null +++ b/.changeset/eighty-bulldogs-smile.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Use ApplyDefaultsAndValidate diff --git a/.changeset/eleven-olives-accept.md b/.changeset/eleven-olives-accept.md new file mode 100644 index 00000000000..c06cd65c9fe --- /dev/null +++ b/.changeset/eleven-olives-accept.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added #fix add chain fee tests to initial deploy diff --git a/.changeset/empty-bees-fix.md b/.changeset/empty-bees-fix.md new file mode 100644 index 00000000000..e76ee621253 --- /dev/null +++ b/.changeset/empty-bees-fix.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#wip implement gateway handler that forwards outgoing request from http target capability. introduce gateway http client diff --git a/.changeset/empty-pianos-attack.md b/.changeset/empty-pianos-attack.md new file mode 100644 index 00000000000..5ec420b14ca --- /dev/null +++ b/.changeset/empty-pianos-attack.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Update gethwrapper for FeeQuoter, Internal.sol comment and byte calc update diff --git a/.changeset/fair-swans-accept.md b/.changeset/fair-swans-accept.md new file mode 100644 index 00000000000..dd834aa2d80 --- /dev/null +++ b/.changeset/fair-swans-accept.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Add support for data word detail manual input in Contract Reader for searching through EVM log event data with Contract Reader QueryKey ValueComparators. diff --git a/.changeset/fast-insects-shout.md b/.changeset/fast-insects-shout.md deleted file mode 100644 index 847fc8d057f..00000000000 --- a/.changeset/fast-insects-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Change CapabilityType to string; remove possiblity of a panic diff --git a/.changeset/few-pillows-yawn.md b/.changeset/few-pillows-yawn.md new file mode 100644 index 00000000000..ada48200d53 --- /dev/null +++ b/.changeset/few-pillows-yawn.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Add RMNRemote in the chain reader definition diff --git a/.changeset/fifty-pillows-peel.md b/.changeset/fifty-pillows-peel.md new file mode 100644 index 00000000000..711a8869aa4 --- /dev/null +++ b/.changeset/fifty-pillows-peel.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Added `EVM.HeadTracker.PersistenceEnabled` config option to disable persistence for HeadTracker. #added diff --git a/.changeset/fifty-squids-juggle.md b/.changeset/fifty-squids-juggle.md new file mode 100644 index 00000000000..5c5530bf03c --- /dev/null +++ b/.changeset/fifty-squids-juggle.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +FHE empty reward fix #internal diff --git a/.changeset/five-chicken-talk.md b/.changeset/five-chicken-talk.md new file mode 100644 index 00000000000..5f93b29364b --- /dev/null +++ b/.changeset/five-chicken-talk.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated introduce network field on chain resolver diff --git a/.changeset/flat-horses-argue.md b/.changeset/flat-horses-argue.md new file mode 100644 index 00000000000..08f151cd5aa --- /dev/null +++ b/.changeset/flat-horses-argue.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added LogPoller MaxLogsKept feature: recency count-based instead of time based log retention diff --git a/.changeset/flat-mirrors-confess.md b/.changeset/flat-mirrors-confess.md deleted file mode 100644 index 7c0a6a92a3f..00000000000 --- a/.changeset/flat-mirrors-confess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated Sync feeds-manager wsrpc proto diff --git a/.changeset/flat-spiders-sing.md b/.changeset/flat-spiders-sing.md new file mode 100644 index 00000000000..6fba341b191 --- /dev/null +++ b/.changeset/flat-spiders-sing.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Set chainType in chain client #internal diff --git a/.changeset/forty-lizards-camp.md b/.changeset/forty-lizards-camp.md new file mode 100644 index 00000000000..3e0a5a59b0e --- /dev/null +++ b/.changeset/forty-lizards-camp.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Enable rotating encryptionPublicKey in CapabilitiesRegistry contract diff --git a/.changeset/four-buses-invite.md b/.changeset/four-buses-invite.md new file mode 100644 index 00000000000..2f657dd4503 --- /dev/null +++ b/.changeset/four-buses-invite.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Introduce aptosKeys Graphql query diff --git a/.changeset/fresh-falcons-cheer.md b/.changeset/fresh-falcons-cheer.md new file mode 100644 index 00000000000..505582cc4fd --- /dev/null +++ b/.changeset/fresh-falcons-cheer.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added solana: compute unit limit configuration and transaction instruction diff --git a/.changeset/friendly-impalas-sniff.md b/.changeset/friendly-impalas-sniff.md deleted file mode 100644 index 8a041a338bc..00000000000 --- a/.changeset/friendly-impalas-sniff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added nonce validation immediately after broadcast for Hedera #internal diff --git a/.changeset/giant-pillows-sort.md b/.changeset/giant-pillows-sort.md new file mode 100644 index 00000000000..a2b44319ecb --- /dev/null +++ b/.changeset/giant-pillows-sort.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Add prometheus metrics exposing health of telemetry client diff --git a/.changeset/gorgeous-wolves-collect.md b/.changeset/gorgeous-wolves-collect.md new file mode 100644 index 00000000000..62b11100151 --- /dev/null +++ b/.changeset/gorgeous-wolves-collect.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add DA oracle type to arbitrum and zksync configs #bugfix diff --git a/.changeset/happy-adults-wash.md b/.changeset/happy-adults-wash.md deleted file mode 100644 index 738f8998b20..00000000000 --- a/.changeset/happy-adults-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal fix to keystone e2e test dispatcher to correctly mock duplicate registration error diff --git a/.changeset/healthy-flowers-nail.md b/.changeset/healthy-flowers-nail.md new file mode 100644 index 00000000000..aefc463472d --- /dev/null +++ b/.changeset/healthy-flowers-nail.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Return ErrConnectivity error when halting bumping #internal diff --git a/.changeset/hip-crabs-agree.md b/.changeset/hip-crabs-agree.md deleted file mode 100644 index 5085899e3d3..00000000000 --- a/.changeset/hip-crabs-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added Add Astar TerminallyUnderpriced error mapping diff --git a/.changeset/honest-cameras-cross.md b/.changeset/honest-cameras-cross.md new file mode 100644 index 00000000000..1da50c97bd5 --- /dev/null +++ b/.changeset/honest-cameras-cross.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Implementing evm specific token data encoder for CCIP #internal diff --git a/.changeset/itchy-bugs-clean.md b/.changeset/itchy-bugs-clean.md deleted file mode 100644 index beeed8ace1e..00000000000 --- a/.changeset/itchy-bugs-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Introduced finalized transaction state. Added a finalizer component to the TXM to mark transactions as finalized. #internal diff --git a/.changeset/khaki-pants-melt.md b/.changeset/khaki-pants-melt.md new file mode 100644 index 00000000000..133fd480f56 --- /dev/null +++ b/.changeset/khaki-pants-melt.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated Workflows Engine loop refactored diff --git a/.changeset/late-pillows-shake.md b/.changeset/late-pillows-shake.md new file mode 100644 index 00000000000..f27f09519db --- /dev/null +++ b/.changeset/late-pillows-shake.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Refactor OP oracle to accept generic DA oracle config #wip diff --git a/.changeset/lemon-apples-explain.md b/.changeset/lemon-apples-explain.md new file mode 100644 index 00000000000..75f2b874fc4 --- /dev/null +++ b/.changeset/lemon-apples-explain.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal update ccip chainreader config. diff --git a/.changeset/many-knives-play.md b/.changeset/many-knives-play.md deleted file mode 100644 index 8c1f5da1a48..00000000000 --- a/.changeset/many-knives-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated Adds DB syncing for registry syncer diff --git a/.changeset/mean-brooms-agree.md b/.changeset/mean-brooms-agree.md deleted file mode 100644 index 0dd2ba7bd33..00000000000 --- a/.changeset/mean-brooms-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Custom (30s) timeout for Hedera RPC requests with large payloads (SendTransaction, CallContext, etc.) #internal diff --git a/.changeset/metal-eels-check.md b/.changeset/metal-eels-check.md new file mode 100644 index 00000000000..387eb51fc6d --- /dev/null +++ b/.changeset/metal-eels-check.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated Consume Feeds Manager WSRPC protos from Chainlink Protos Repository. diff --git a/.changeset/metal-forks-arrive.md b/.changeset/metal-forks-arrive.md new file mode 100644 index 00000000000..21b99b3ddb1 --- /dev/null +++ b/.changeset/metal-forks-arrive.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Adds new custom calldata DA oracle #added diff --git a/.changeset/metal-meals-mix.md b/.changeset/metal-meals-mix.md new file mode 100644 index 00000000000..66ebcec9982 --- /dev/null +++ b/.changeset/metal-meals-mix.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Adjustments for usdc reader tests #internal diff --git a/.changeset/metal-pots-lie.md b/.changeset/metal-pots-lie.md new file mode 100644 index 00000000000..bfa498cd4ac --- /dev/null +++ b/.changeset/metal-pots-lie.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Registering USDC/CCTP events in the ChainReader during oracle creation #internal diff --git a/.changeset/moody-rules-agree.md b/.changeset/moody-rules-agree.md new file mode 100644 index 00000000000..ef1f3bcaf62 --- /dev/null +++ b/.changeset/moody-rules-agree.md @@ -0,0 +1,8 @@ +--- +"chainlink": patch +--- + +- register polling subscription to avoid subscription leaking when rpc client gets closed. +- add a temporary special treatment for SubscribeNewHead before we replace it with SubscribeToHeads. Add a goroutine that forwards new head from poller to caller channel. +- fix a deadlock in poller, by using a new lock for subs slice in rpc client. +#bugfix diff --git a/.changeset/moody-trains-grow.md b/.changeset/moody-trains-grow.md new file mode 100644 index 00000000000..304e91c1664 --- /dev/null +++ b/.changeset/moody-trains-grow.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added graceful shutdown for ccip oracles diff --git a/.changeset/neat-numbers-lay.md b/.changeset/neat-numbers-lay.md new file mode 100644 index 00000000000..69276e84f68 --- /dev/null +++ b/.changeset/neat-numbers-lay.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#removed Removing unreferenced unused files. diff --git a/.changeset/nervous-books-push.md b/.changeset/nervous-books-push.md new file mode 100644 index 00000000000..b0f797344e3 --- /dev/null +++ b/.changeset/nervous-books-push.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Updated QueryKey to be able to do advanced queries on contract event data words diff --git a/.changeset/new-eagles-marry.md b/.changeset/new-eagles-marry.md deleted file mode 100644 index 9577c2bbe09..00000000000 --- a/.changeset/new-eagles-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal prevent editing whether or not a DON accepts workflows diff --git a/.changeset/rich-chairs-hug.md b/.changeset/nice-cows-yell.md similarity index 50% rename from .changeset/rich-chairs-hug.md rename to .changeset/nice-cows-yell.md index 0408383bd03..1e7f045b476 100644 --- a/.changeset/rich-chairs-hug.md +++ b/.changeset/nice-cows-yell.md @@ -2,4 +2,4 @@ "chainlink": patch --- -#internal +#updated Refactors store_db diff --git a/.changeset/ninety-cougars-tease.md b/.changeset/ninety-cougars-tease.md deleted file mode 100644 index ab12a571914..00000000000 --- a/.changeset/ninety-cougars-tease.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal restore common version to head of develop diff --git a/.changeset/ninety-feet-change.md b/.changeset/ninety-feet-change.md new file mode 100644 index 00000000000..2c4cea72106 --- /dev/null +++ b/.changeset/ninety-feet-change.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated default config values for FinalityTagEnabled to match CCIP configs diff --git a/.changeset/ninety-ways-run.md b/.changeset/ninety-ways-run.md deleted file mode 100644 index 0b4508bdd24..00000000000 --- a/.changeset/ninety-ways-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal speed up keystone e2e tests diff --git a/.changeset/odd-hats-repeat.md b/.changeset/odd-hats-repeat.md deleted file mode 100644 index ce80b45caff..00000000000 --- a/.changeset/odd-hats-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal fix the mock trigger to ensure events are sent diff --git a/.changeset/old-humans-watch.md b/.changeset/old-humans-watch.md new file mode 100644 index 00000000000..e58dedcd368 --- /dev/null +++ b/.changeset/old-humans-watch.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Fix TXM flakey test #internal diff --git a/.changeset/olive-bugs-relax.md b/.changeset/olive-bugs-relax.md new file mode 100644 index 00000000000..6e681000358 --- /dev/null +++ b/.changeset/olive-bugs-relax.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +add address bytes to string modifier to chainReader. #internal diff --git a/.changeset/orange-feet-share.md b/.changeset/orange-feet-share.md new file mode 100644 index 00000000000..9583bce3d64 --- /dev/null +++ b/.changeset/orange-feet-share.md @@ -0,0 +1,25 @@ +--- +"chainlink": minor +--- + +Implemented new chain agnostic MultiNode design along with the corresponding EVM implementation. The chain agnostic components enable Multinode to be integrated with Solana and other non-EVM chains. Previously the Multinode was coupled with EVM specific actions, and was called to execute these actions direclty. With this change, the MultiNode's responsibility has been simplified to focus on RPC selection along with performing health checks. Chain specific actions will instead be executed on the RPC directly after being selected by MultiNode. The Chain Agnostic MultiNode provides improved reliability and metrics for all chain integrations using it. + +These are following main components: +Node: Common component which wraps an RPC with state information, health checks, and an alive loop to handle state changes along with maintaining chain information. +RPCClient: Chain-specific RPC wrapper which implements required interface for MultiNode along with any chain-specific functionality needed. +MultiNode: Perform RPCClient selection and performs health checks on all RPCs. +TransactionSender: Chain agnostic component which broadcasts transactions to all healthy RPCs and aggregates results. A chain-specific error classifier must be implemented. + +MultiNode picks the "best" RPC based on one of the configurable criteria: +- Priority defined in the config. +- Highest latest block. +- Round-robin within the same priority level (or using other configurable selection algorithms) + +Benefits of Chain Agnostic MultiNode: + Reliability: Improved RPC reliability scaleable to all chains + Maintainability: Can apply changes across all chain integrations through the use of common code + Extendability: Can add new health checks, RPC selection and ranking algorithms + Integration Speed: Much faster to integrate MultiNode with new chains + Reduced Generics: Significantly less bulky code! + +#updated #changed #internal diff --git a/.changeset/orange-humans-laugh.md b/.changeset/orange-humans-laugh.md new file mode 100644 index 00000000000..b9f8fa74f54 --- /dev/null +++ b/.changeset/orange-humans-laugh.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Support Zircuit fraud transactions detection and zk overflow detection #added diff --git a/.changeset/polite-crabs-pretend.md b/.changeset/polite-crabs-pretend.md deleted file mode 100644 index f8ea63b45c1..00000000000 --- a/.changeset/polite-crabs-pretend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal ensure remote target request hash is deterministic diff --git a/.changeset/polite-tips-sneeze.md b/.changeset/polite-tips-sneeze.md new file mode 100644 index 00000000000..4dc0e000046 --- /dev/null +++ b/.changeset/polite-tips-sneeze.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added keystone contract deployment diff --git a/.changeset/pretty-worms-smell.md b/.changeset/pretty-worms-smell.md new file mode 100644 index 00000000000..9633de09502 --- /dev/null +++ b/.changeset/pretty-worms-smell.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Added a custom client error message for Mantle to capture NonceTooLow error. #added diff --git a/.changeset/proud-jokes-exercise.md b/.changeset/proud-jokes-exercise.md deleted file mode 100644 index 4e36d139de5..00000000000 --- a/.changeset/proud-jokes-exercise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added Report new heads as a telemetry to OTI diff --git a/.changeset/real-doors-visit.md b/.changeset/real-doors-visit.md new file mode 100644 index 00000000000..39fa064c3a8 --- /dev/null +++ b/.changeset/real-doors-visit.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +Implement blue-green Configurator contract and retirement report handover for LLO +#added diff --git a/.changeset/red-jobs-marry.md b/.changeset/red-jobs-marry.md new file mode 100644 index 00000000000..d66ad019027 --- /dev/null +++ b/.changeset/red-jobs-marry.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Rename DA oracle consts to be more descriptive #wip diff --git a/.changeset/rude-spies-serve.md b/.changeset/rude-spies-serve.md new file mode 100644 index 00000000000..d861b5cf6ba --- /dev/null +++ b/.changeset/rude-spies-serve.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added new config field to FeeQuoter diff --git a/.changeset/seven-forks-hug.md b/.changeset/seven-forks-hug.md new file mode 100644 index 00000000000..5ddcbfe3fec --- /dev/null +++ b/.changeset/seven-forks-hug.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Add encryptionPublicKey to CapabilitiesRegistry.sol diff --git a/.changeset/seven-kiwis-run.md b/.changeset/seven-kiwis-run.md deleted file mode 100644 index 3b56117c469..00000000000 --- a/.changeset/seven-kiwis-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Added custom client error messages for Mantle to capture InsufficientEth and Fatal errors. #added diff --git a/.changeset/shy-windows-juggle.md b/.changeset/shy-windows-juggle.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/shy-windows-juggle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/silent-foxes-battle.md b/.changeset/silent-foxes-battle.md new file mode 100644 index 00000000000..f3f4b48962c --- /dev/null +++ b/.changeset/silent-foxes-battle.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Bump chainlink-solana and fix tests #internal diff --git a/.changeset/silly-lies-boil.md b/.changeset/silly-lies-boil.md new file mode 100644 index 00000000000..b2a5084a36c --- /dev/null +++ b/.changeset/silly-lies-boil.md @@ -0,0 +1,8 @@ +--- +"chainlink": minor +--- + +Make websocket URL `WSURL` for `EVM.Nodes` optional, and apply logic so that: +* If WS URL was not provided, SubscribeFilterLogs should fail with an explicit error +* If WS URL was not provided LogBroadcaster should be disabled +#nops diff --git a/.changeset/silly-starfishes-destroy.md b/.changeset/silly-starfishes-destroy.md new file mode 100644 index 00000000000..ebb552fdca2 --- /dev/null +++ b/.changeset/silly-starfishes-destroy.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal ccip contract reader config. diff --git a/.changeset/silver-pens-float.md b/.changeset/silver-pens-float.md new file mode 100644 index 00000000000..e8a135b9de4 --- /dev/null +++ b/.changeset/silver-pens-float.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal: Adding test for rmn home reader diff --git a/.changeset/six-frogs-juggle.md b/.changeset/six-frogs-juggle.md new file mode 100644 index 00000000000..2b960c4be0f --- /dev/null +++ b/.changeset/six-frogs-juggle.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added HTTP target capability and gateway connector handler diff --git a/.changeset/slimy-forks-wait.md b/.changeset/slimy-forks-wait.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/slimy-forks-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/smooth-queens-dance.md b/.changeset/smooth-queens-dance.md new file mode 100644 index 00000000000..861c5284984 --- /dev/null +++ b/.changeset/smooth-queens-dance.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Add compute capability #internal diff --git a/.changeset/stale-pugs-sin.md b/.changeset/stale-pugs-sin.md new file mode 100644 index 00000000000..58ebd2d7acd --- /dev/null +++ b/.changeset/stale-pugs-sin.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added introduce cosmosKeys and starknetKeys graphql query diff --git a/.changeset/strong-dogs-smash.md b/.changeset/strong-dogs-smash.md deleted file mode 100644 index a34a418e65d..00000000000 --- a/.changeset/strong-dogs-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -error handling for Treasure #added \ No newline at end of file diff --git a/.changeset/sweet-pumas-refuse.md b/.changeset/sweet-pumas-refuse.md deleted file mode 100644 index fd642a9c94c..00000000000 --- a/.changeset/sweet-pumas-refuse.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#bugfix Addresses 2 minor issues with the pruning of LogPoller's db tables: logs not matching any filter will now be pruned, and rows deleted are now properly reported for observability diff --git a/.changeset/tall-poems-swim.md b/.changeset/tall-poems-swim.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/tall-poems-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/tasty-walls-collect.md b/.changeset/tasty-walls-collect.md deleted file mode 100644 index eefe4441507..00000000000 --- a/.changeset/tasty-walls-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated Update Polygon configs to match PIP-35 diff --git a/.changeset/tasty-windows-own.md b/.changeset/tasty-windows-own.md deleted file mode 100644 index bd81338cb4e..00000000000 --- a/.changeset/tasty-windows-own.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix balance shutdown deadlock diff --git a/.changeset/ten-rats-tie.md b/.changeset/ten-rats-tie.md new file mode 100644 index 00000000000..f97594914cd --- /dev/null +++ b/.changeset/ten-rats-tie.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Fix testWSServer issue causing panic in testing #internal diff --git a/.changeset/thin-rings-count.md b/.changeset/thin-rings-count.md deleted file mode 100644 index 20f4b54311e..00000000000 --- a/.changeset/thin-rings-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add evm Chain Reader GetLatestValue support for filtering on indexed topic types that get hashed. diff --git a/.changeset/thirty-olives-marry.md b/.changeset/thirty-olives-marry.md deleted file mode 100644 index 8be272b9357..00000000000 --- a/.changeset/thirty-olives-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Change ChainReader Block primitive field from int to string. #internal diff --git a/.changeset/three-otters-drum.md b/.changeset/three-otters-drum.md new file mode 100644 index 00000000000..c3888df8580 --- /dev/null +++ b/.changeset/three-otters-drum.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Hedera chain type: broadcast transactions only to a single healthy RPC instead of all healthy RPCs to avoid redundant relay fees. #changed diff --git a/.changeset/tidy-apricots-care.md b/.changeset/tidy-apricots-care.md new file mode 100644 index 00000000000..60429107f11 --- /dev/null +++ b/.changeset/tidy-apricots-care.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Pass the home chain selector to the commit plugin factory diff --git a/.changeset/tough-boats-shop.md b/.changeset/tough-boats-shop.md new file mode 100644 index 00000000000..45a16fc965a --- /dev/null +++ b/.changeset/tough-boats-shop.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +start of next release diff --git a/.changeset/twelve-balloons-turn.md b/.changeset/twelve-balloons-turn.md deleted file mode 100644 index f4f0e2670e9..00000000000 --- a/.changeset/twelve-balloons-turn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal fix data race in syncer launcher diff --git a/.changeset/two-snails-mix.md b/.changeset/two-snails-mix.md new file mode 100644 index 00000000000..0fb49dce9b2 --- /dev/null +++ b/.changeset/two-snails-mix.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Rename SequenceAt to NonceAt #internal diff --git a/.changeset/violet-clouds-rhyme.md b/.changeset/violet-clouds-rhyme.md deleted file mode 100644 index b6db0e85c4f..00000000000 --- a/.changeset/violet-clouds-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Updated AutoPurge.Threshold and AutoPurge.MinAttempts configs to only be required for heuristic and added content-type header for Scroll API #internal diff --git a/.changeset/warm-houses-build.md b/.changeset/warm-houses-build.md deleted file mode 100644 index 6ce6215a88c..00000000000 --- a/.changeset/warm-houses-build.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added custom finality calculation for Astar #internal diff --git a/.changeset/weak-rabbits-sell.md b/.changeset/weak-rabbits-sell.md deleted file mode 100644 index 3f0785d3d5e..00000000000 --- a/.changeset/weak-rabbits-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal prevent reentrancy when configuring DON in Capabilities Registry diff --git a/.changeset/wild-seals-look.md b/.changeset/wild-seals-look.md deleted file mode 100644 index 3cd854f0e61..00000000000 --- a/.changeset/wild-seals-look.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Added new health check that ensures RPC provides new finalized heads at least every `NoNewFinalizedHeadsThreshold` #added diff --git a/.changeset/wise-pandas-join.md b/.changeset/wise-pandas-join.md new file mode 100644 index 00000000000..7b375b0895d --- /dev/null +++ b/.changeset/wise-pandas-join.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Fix BHE PriceMax bug #bugfix diff --git a/.changeset/yellow-cougars-act.md b/.changeset/yellow-cougars-act.md deleted file mode 100644 index 61ed62607a0..00000000000 --- a/.changeset/yellow-cougars-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added client error classification for terminally stuck transactions in the TXM #internal diff --git a/.changeset/young-mice-invent.md b/.changeset/young-mice-invent.md deleted file mode 100644 index ba9c67198aa..00000000000 --- a/.changeset/young-mice-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added CCIP plugins code from https://github.com/smartcontractkit/ccip/ #added diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c7eb22991b5..5de2604893c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,101 +5,148 @@ # Root * @smartcontractkit/foundations +.changeset @smartcontractkit/releng @smartcontractkit/foundations + # Chains /common @smartcontractkit/bix-framework /core/chains/ @smartcontractkit/bix-framework # Services -/core/services/directrequest @smartcontractkit/keepers -/core/services/feeds @smartcontractkit/FMS +/core/services/directrequest @smartcontractkit/foundations +/core/services/feeds @smartcontractkit/deployment-automation @eutopian @yevshev /core/services/synchronization/telem @smartcontractkit/realtime +/core/capabilities/ @smartcontractkit/keystone @smartcontractkit/capabilities-team +/core/capabilities/ccip @smartcontractkit/ccip-offchain # To be deprecated in Chainlink V3 /core/services/fluxmonitorv2 @smartcontractkit/foundations -/core/services/job @smartcontractkit/ccip -/core/services/keystore @smartcontractkit/keepers +/core/services/job @smartcontractkit/foundations +/core/services/keystore @smartcontractkit/foundations /core/services/ocr* @smartcontractkit/foundations /core/services/periodicbackup @smartcontractkit/foundations /core/services/pg @smartcontractkit/foundations @samsondav /core/services/pipeline @smartcontractkit/foundations @smartcontractkit/bix-framework /core/services/telemetry @smartcontractkit/realtime -/core/services/relay/evm/mercury @smartcontractkit/mercury-team +/core/services/relay/evm/mercury @smartcontractkit/data-streams-engineers /core/services/webhook @smartcontractkit/foundations @smartcontractkit/bix-framework -/core/services/llo @smartcontractkit/mercury-team +/core/services/llo @smartcontractkit/data-streams-engineers + +# CCIP +/core/services/ccip @smartcontractkit/ccip +/core/services/ocr2/plugins/ccip @smartcontractkit/ccip # VRF-related services -/core/services/vrf @smartcontractkit/vrf-team -/core/services/blockhashstore @smartcontractkit/vrf-team -/core/services/blockheaderfeeder @smartcontractkit/vrf-team -/core/services/pipeline/task.vrf.go @smartcontractkit/vrf-team -/core/services/pipeline/task.vrfv2.go @smartcontractkit/vrf-team -/core/services/pipeline/task.vrfv2plus.go @smartcontractkit/vrf-team +/core/services/vrf @smartcontractkit/dev-services +/core/services/blockhashstore @smartcontractkit/dev-services +/core/services/blockheaderfeeder @smartcontractkit/dev-services +/core/services/pipeline/task.vrf.go @smartcontractkit/dev-services +/core/services/pipeline/task.vrfv2.go @smartcontractkit/dev-services +/core/services/pipeline/task.vrfv2plus.go @smartcontractkit/dev-services # Keeper/Automation-related services -/core/services/keeper @smartcontractkit/keepers -/core/services/ocr2/plugins/ocr2keeper @smartcontractkit/keepers +/core/services/keeper @smartcontractkit/dev-services +/core/services/ocr2/plugins/ocr2keeper @smartcontractkit/dev-services # Chainlink Functions -core/services/functions @smartcontractkit/functions -core/services/ocr2/plugins/functions @smartcontractkit/functions -core/services/s4 @smartcontractkit/functions -core/service/ocr2/plugins/s4 @smartcontractkit/functions -core/services/ocr2/plugins/threshold @smartcontractkit/functions -core/services/relay/evm/functions @smartcontractkit/functions -core/services/relay/evm/functions @smartcontractkit/functions -core/scripts/functions @smartcontractkit/functions -core/scripts/gateway @smartcontractkit/functions - -# Contracts -/contracts/ @RensR - -# First we match on project names to catch files like the compilation scripts, -# gas snapshots and other files not places in the project directories. -# This could give some false positives, so afterwards we match on the project directories -# to ensure the entire directory is always owned by the correct team. - -/contracts/**/*keeper* @smartcontractkit/keepers -/contracts/**/*upkeep* @smartcontractkit/keepers -/contracts/**/*automation* @smartcontractkit/keepers -/contracts/**/*functions* @smartcontractkit/functions -/contracts/**/*llo-feeds* @smartcontrackit/mercury-team -/contracts/**/*vrf* @smartcontractkit/vrf-team +core/services/functions @smartcontractkit/dev-services +core/services/ocr2/plugins/functions @smartcontractkit/dev-services +core/services/s4 @smartcontractkit/dev-services +core/service/ocr2/plugins/s4 @smartcontractkit/dev-services +core/services/ocr2/plugins/threshold @smartcontractkit/dev-services +core/services/relay/evm/functions @smartcontractkit/dev-services +core/services/relay/evm/functions @smartcontractkit/dev-services +core/scripts/functions @smartcontractkit/dev-services +core/scripts/gateway @smartcontractkit/dev-services + +# Keystone +/core/services/registrysyncer @smartcontractkit/keystone +/core/services/workflows @smartcontractkit/keystone +/core/services/standardcapabilities @smartcontractkit/keystone +/core/scripts/keystone @smartcontractkit/keystone + +# Contracts catch all, for files not matched by the more specific patterns below +/contracts/ @RensR @matYang @RayXpub @elatoskinas + +# First we match on project names to catch files like the compilation scripts and other files +# not placed in the project directories. This could give some false positives, so afterwards +# we match on the project directories to ensure the entire directory is always owned by the +# correct team. +/contracts/**/*keeper* @smartcontractkit/dev-services +/contracts/**/*upkeep* @smartcontractkit/dev-services +/contracts/**/*automation* @smartcontractkit/dev-services +/contracts/**/*ccip* @RensR @matYang @jhweintraub @0xsuryansh @RyanRHall +/contracts/**/*functions* @smartcontractkit/dev-services /contracts/**/*l2ep* @smartcontractkit/bix-ship -# TODO: replace with a team tag when ready -/contracts/**/*keystone* @archseer @bolekk @patrick-dowell - -/contracts/src/v0.8/automation @smartcontractkit/keepers -/contracts/src/v0.8/functions @smartcontractkit/functions +/contracts/**/*llo-feeds* @smartcontractkit/data-streams-engineers +/contracts/**/*operatorforwarder* @smartcontractkit/data-feeds-engineers +/contracts/**/*vrf* @smartcontractkit/dev-services +/contracts/**/*keystone* @smartcontractkit/keystone + +/contracts/src/v0.8/automation @smartcontractkit/dev-services +/contracts/src/v0.8/ccip @RensR @matYang @jhweintraub @0xsuryansh @RyanRHall +/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 @chris-de-leon-cll -/contracts/src/v0.8/llo-feeds @smartcontractkit/mercury-team +/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 @austinborn -/contracts/src/v0.8/shared @RensR +/contracts/src/v0.8/operatorforwarder @smartcontractkit/data-feeds-engineers +/contracts/src/v0.8/shared @RensR @matYang @RayXpub @elatoskinas # 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/vrf-team - - +/contracts/src/v0.8/vrf @smartcontractkit/dev-services +/contracts/src/v0.8/keystone @smartcontractkit/keystone + +/core/gethwrappers/ccip @RensR @matYang @jhweintraub @0xsuryansh @RyanRHall +/core/gethwrappers/functions @smartcontractkit/dev-services +/core/gethwrappers/keystone @smartcontractkit/keystone +/core/gethwrappers/liquiditymanager @RensR @matYang @jhweintraub @0xsuryansh @RyanRHall +/core/gethwrappers/llo-feeds @smartcontractkit/data-streams-engineers +/core/gethwrappers/operatorforwarder @smartcontractkit/data-feeds-engineers +/core/gethwrappers/shared @RensR @matYang @RayXpub @elatoskinas + +# The following don't exist yet but should. They are already included here to allow the teams to +# set these folders up and own them immediately. +/core/gethwrappers/keeper @smartcontractkit/dev-services +/core/gethwrappers/upkeep @smartcontractkit/dev-services +/core/gethwrappers/automation @smartcontractkit/dev-services +/core/gethwrappers/l2ep @smartcontractkit/bix-ship +/core/gethwrappers/vrf @smartcontractkit/dev-services -# At the end, match any files missed by the patterns above -/contracts/scripts/native_solc_compile_all_events_mock @smartcontractkit/functions # Remove changeset files from the codeowners /contracts/.changeset +# Gas snapshots are always checked by the CI so they don't need codeowners. +/contracts/gas-snapshots + +# At the end, match any files missed by the patterns above +/contracts/scripts/native_solc_compile_all_events_mock @smartcontractkit/dev-services + +# GQL API +/core/web/resolver @smartcontractkit/deployment-automation @smartcontractkit/foundations +/core/web/schema @smartcontractkit/deployment-automation @smartcontractkit/foundations # Tests /integration-tests/ @smartcontractkit/test-tooling-team -/integration-tests/**/*keeper* @smartcontractkit/keepers -/integration-tests/**/*automation* @smartcontractkit/keepers +/integration-tests/ccip-tests @smartcontractkit/ccip-offchain +/integration-tests/**/*keeper* @smartcontractkit/dev-services +/integration-tests/**/*automation* @smartcontractkit/dev-services +/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain + +# Deployment tooling +# Initially the common structures owned by CCIP +/integration-tests/deployment @smartcontractkit/ccip @smartcontractkit/keystone +/integration-tests/deployment/ccip @smartcontractkit/ccip +/integration-tests/deployment/keystone @smartcontractkit/keystone +# TODO: As more products add their deployment logic here, add the team as an owner # CI/CD /.github/** @smartcontractkit/releng @smartcontractkit/test-tooling-team +/.github/CODEOWNERS @smartcontractkit/prodsec-public @smartcontractkit/foundations /.github/workflows/performance-tests.yml @smartcontractkit/test-tooling-team -/.github/workflows/automation-ondemand-tests.yml @smartcontractkit/keepers -/.github/workflows/automation-benchmark-tests.yml @smartcontractkit/keepers -/.github/workflows/automation-load-tests.yml @smartcontractkit/keepers -/.github/workflows/automation-nightly-tests.yml @smartcontractkit/keepers +/.github/workflows/automation-ondemand-tests.yml @smartcontractkit/dev-services +/.github/workflows/automation-benchmark-tests.yml @smartcontractkit/dev-services +/.github/workflows/automation-load-tests.yml @smartcontractkit/dev-services +/.github/workflows/automation-nightly-tests.yml @smartcontractkit/dev-services /core/chainlink.Dockerfile @smartcontractkit/prodsec-public @@ -111,8 +158,8 @@ contracts/package.json @smartcontractkit/prodsec-public contracts/pnpm.lock @smartcontractkit/prodsec-public go.mod @smartcontractkit/prodsec-public @smartcontractkit/releng @smartcontractkit/foundations go.sum @smartcontractkit/prodsec-public @smartcontractkit/releng @smartcontractkit/foundations -integration-tests/go.mod @smartcontractkit/prodsec-public -integration-tests/go.sum @smartcontractkit/prodsec-public +integration-tests/go.mod @smartcontractkit/prodsec-public @smartcontractkit/test-tooling-team @smartcontractkit/foundations +integration-tests/go.sum @smartcontractkit/prodsec-public @smartcontractkit/test-tooling-team @smartcontractkit/foundations flake.nix @smartcontractkit/prodsec-public flake.lock @smartcontractkit/prodsec-public diff --git a/.github/E2E_TESTS_ON_GITHUB_CI.md b/.github/E2E_TESTS_ON_GITHUB_CI.md new file mode 100644 index 00000000000..26d3c9daf92 --- /dev/null +++ b/.github/E2E_TESTS_ON_GITHUB_CI.md @@ -0,0 +1,90 @@ +# E2E Tests on GitHub CI + +- [E2E Tests on GitHub CI](#e2e-tests-on-github-ci) + - [Scheduled test workflows](#scheduled-test-workflows) + - [PR E2E Tests](#pr-e2e-tests) + - [Nightly E2E Tests](#nightly-e2e-tests) + - [Release E2E Tests](#release-e2e-tests) + - [Integration (smoke) Tests](#integration-smoke-tests) + - [Client Compatibility Tests](#client-compatibility-tests) + - [On-Demand Workflows](#on-demand-workflows) + - [Test workflows setup in CI](#test-workflows-setup-in-ci) + - [Configuration Overrides](#configuration-overrides) + - [Test Secrets](#test-secrets) + +E2E tests are executed on GitHub CI using the [E2E Tests Reusable Workflow](https://github.com/smartcontractkit/.github/blob/main/.github/workflows/README.md) or dedicated workflows. + +## Scheduled test workflows + +These workflows are designed to run on every commit in a PR, nightly or before release (see `triggers` in [e2e-tests.yaml](./e2e-tests.yml)). + +### PR E2E Tests + +Tests triggered on every commit in a PR to ensure changes do not introduce regressions. + +**Workflow:** [integration-tests.yml](https://github.com/smartcontractkit/chainlink/blob/develop/.github/workflows/integration-tests.yml) + +### Nightly E2E Tests + +Nightly E2E test runs. + +**Workflow:** [nightly-e2e-tests.yml](https://github.com/smartcontractkit/chainlink/blob/develop/.github/workflows/run-nightly-e2e-tests.yml) + +### Release E2E Tests + +E2E tests triggered on a release tag. + +#### Integration (smoke) Tests + +**Workflow:** [integration-tests.yml](https://github.com/smartcontractkit/chainlink/blob/develop/.github/workflows/integration-tests.yml) + +#### Client Compatibility Tests + +**Workflow:** [client-compatibility-tests.yml](https://github.com/smartcontractkit/chainlink/actions/workflows/client-compatibility-tests.yml) + +## On-Demand Workflows + +These are dispatched parametrized workflows, that may be triggered manually for specific testing needs. For more details refer [integration-tests README](../integration-tests/README.md) and [per-product test run books](../integration-tests/run-books/). + +**Examples:** + +- [Selected E2E Tests Workflow](https://github.com/smartcontractkit/chainlink/actions/workflows/run-selected-e2e-tests.yml) +- [Client Compatibility Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/client-compatibility-tests.yml) +- [Chaos Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/integration-chaos-tests.yml) +- [OCR Soak Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/on-demand-ocr-soak-test.yml) +- [On-Demand Automation Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/automation-ondemand-tests.yml) +- [CCIP Chaos Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/ccip-chaos-tests.yml) +- [CCIP Load Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/ccip-load-tests.yml) +- [VRFv2Plus Smoke Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/on-demand-vrfv2plus-smoke-tests.yml) +- [VRFv2Plus Performance Tests](https://github.com/smartcontractkit/chainlink/actions/workflows/on-demand-vrfv2plus-performance-test.yml) + +### Test workflows setup in CI + +Most workflows may be triggered with default configs. Some, nevertheless, may be overridden. + +> [!TIP] +> Use `gh` CLI commands to run workflows from local machine. + +#### Configuration Overrides + +> [!CAUTION] +> Test configurations should not keep any [sensitive data or secrets](#test-secrets). + +1. Reference sources: + 1. [Integration-Tests configurations](../integration-tests/testconfig/README.md); + 2. [CTF Test Config](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md). +2. Defaults and overrides should be stored (committed) in repository under `../integration-tests/testconfig//overrides/.toml` (see example [here](../integration-tests/testconfig/ocr2/overrides/base_sepolia.toml)). +3. Use `test_config_override_path` to point to an override config. For example: `test_config_override_path="testconfig/ocr2/overrides/base_sepolia.toml"` + +#### Test Secrets + +> [!CAUTION] +> Pay attention to never store/expose/commit your test secrets in repository. + +Test secrets allow provisioning and override the sensitive data such as EOA's private key, RPCs, Docker registry links, etc. + +Reference sources: + +1. [BASE64_CONFIG_OVERRIDE](../integration-tests/testconfig/README.md#base64_config_override). +2. [CTF Test Secrets documentation](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md#test-secrets). +3. [Guide on running GitHub workflows with your test secrets](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md#run-github-workflow-with-your-test-secrets). diff --git a/.github/actions/build-chainlink-image/action.yml b/.github/actions/build-chainlink-image/action.yml index 9cd90432e9e..0e457560bf0 100644 --- a/.github/actions/build-chainlink-image/action.yml +++ b/.github/actions/build-chainlink-image/action.yml @@ -37,7 +37,7 @@ runs: AWS_ROLE_TO_ASSUME: ${{ inputs.AWS_ROLE_TO_ASSUME }} - name: Build Image if: steps.check-image.outputs.exists != 'true' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 + uses: smartcontractkit/.github/actions/ctf-build-image@1a26fe378d7ebdc34ab1fe31ec4a6d1c376199f8 # ctf-build-image@0.0.0 with: cl_repo: smartcontractkit/chainlink cl_ref: ${{ inputs.git_commit_sha }} @@ -51,4 +51,4 @@ runs: shell: sh run: | echo "### Chainlink node image tag used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{inputs.git_commit_sha}}\`" >>$GITHUB_STEP_SUMMARY diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml index b992edfbf7d..b0e70b742d5 100644 --- a/.github/actions/build-sign-publish-chainlink/action.yml +++ b/.github/actions/build-sign-publish-chainlink/action.yml @@ -51,23 +51,11 @@ inputs: description: When set to the string boolean value of "true", the resulting build image will be signed default: "false" required: false - cosign-private-key: - description: The private key to be used with cosign to sign the image - required: false - cosign-public-key: - description: The public key to be used with cosign for verification - required: false - cosign-password: - description: The password to decrypt the cosign private key needed to sign the image - required: false - sign-method: - description: Build image will be signed using keypair or keyless methods - default: "keypair" - required: true verify-signature: description: When set to the string boolean value of "true", the resulting build image signature will be verified default: "false" required: false + outputs: docker-image-tag: description: The docker image tag that was built and pushed @@ -84,6 +72,8 @@ runs: # See https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings run: | SHARED_IMAGES=${{ inputs.ecr-hostname }}/${{ inputs.ecr-image-name }} + OIDC_ISSUER=https://token.actions.githubusercontent.com + OIDC_IDENTITY=https://github.com/smartcontractkit/chainlink/.github/workflows/build-publish.yml@${{ github.ref }} SHARED_TAG_LIST=$(cat << EOF type=ref,event=branch,suffix=${{ inputs.ecr-tag-suffix }} @@ -101,6 +91,9 @@ runs: echo "$SHARED_IMAGES" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV + echo "oidc-issuer=${OIDC_ISSUER}" >> $GITHUB_ENV + echo "oidc-identity=${OIDC_IDENTITY}" >> $GITHUB_ENV + echo "shared-tag-list<> $GITHUB_ENV echo "$SHARED_TAG_LIST" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV @@ -171,7 +164,9 @@ runs: run: | IMAGES_NAME_RAW=${{ fromJSON(steps.buildpush-root.outputs.metadata)['image.name'] }} IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1) + IMAGE_DIGEST=${{ fromJSON(steps.buildpush-root.outputs.metadata)['containerimage.digest'] }} echo "root_image_name=${IMAGE_NAME}" >> $GITHUB_ENV + echo "root_image_digest=${IMAGE_DIGEST}" >> $GITHUB_ENV - name: Generate docker metadata for non-root image id: meta-nonroot @@ -217,6 +212,7 @@ runs: IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1) IMAGE_TAG=$(echo "$IMAGES_NAME_RAW" | 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 @@ -239,74 +235,36 @@ runs: - if: inputs.sign-images == 'true' name: Install cosign - uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 with: - cosign-release: "v1.6.0" + cosign-release: "v2.4.0" - - if: inputs.sign-images == 'true' && inputs.sign-method == 'keypair' - name: Sign the published root Docker image using keypair method - shell: sh - env: - COSIGN_PASSWORD: "${{ inputs.cosign-password }}" - run: | - echo "${{ inputs.cosign-private-key }}" > cosign.key - cosign sign --key cosign.key "${{ env.root_image_name }}" - rm -f cosign.key - - - if: inputs.verify-signature == 'true' && inputs.sign-method == 'keypair' - name: Verify the signature of the published root Docker image using keypair - shell: sh - run: | - echo "${{ inputs.cosign-public-key }}" > cosign.key - cosign verify --key cosign.key "${{ env.root_image_name }}" - rm -f cosign.key - - - if: inputs.sign-images == 'true' && inputs.sign-method == 'keyless' + # This automatically signs the image with the correct OIDC provider from Github + - if: inputs.sign-images == 'true' name: Sign the published root Docker image using keyless method shell: sh - env: - COSIGN_EXPERIMENTAL: 1 run: | - cosign sign "${{ env.root_image_name }}" + cosign sign "${{ env.root_image_name }}" --yes - - if: inputs.verify-signature == 'true' && inputs.sign-method == 'keyless' + - if: inputs.verify-signature == 'true' name: Verify the signature of the published root Docker image using keyless shell: sh - env: - COSIGN_EXPERIMENTAL: 1 - run: | - cosign verify "${{ env.root_image_name }}" - - - if: inputs.sign-images == 'true' && inputs.sign-method == 'keypair' - name: Sign the published non-root Docker image using keypair method - shell: sh - env: - COSIGN_PASSWORD: "${{ inputs.cosign-password }}" - run: | - echo "${{ inputs.cosign-private-key }}" > cosign.key - cosign sign --key cosign.key "${{ env.nonroot_image_name }}" - rm -f cosign.key - - - if: inputs.verify-signature == 'true' && inputs.sign-method == 'keypair' - name: Verify the signature of the published non-root Docker image using keypair - shell: sh run: | - echo "${{ inputs.cosign-public-key }}" > cosign.key - cosign verify --key cosign.key "${{ env.nonroot_image_name }}" - rm -f cosign.key + cosign verify "${{ env.root_image_name }}" \ + --certificate-oidc-issuer ${{ env.oidc-issuer }} \ + --certificate-identity "${{ env.oidc-identity }}" - - if: inputs.sign-images == 'true' && inputs.sign-method == 'keyless' + # This automatically signs the image with the correct OIDC provider from Github + - if: inputs.sign-images == 'true' name: Sign the published non-root Docker image using keyless method shell: sh - env: - COSIGN_EXPERIMENTAL: 1 run: | - cosign sign "${{ env.nonroot_image_name }}" + cosign sign "${{ env.nonroot_image_name }}" --yes - - if: inputs.verify-signature == 'true' && inputs.sign-method == 'keyless' + - if: inputs.verify-signature == 'true' name: Verify the signature of the published non-root Docker image using keyless shell: sh - env: - COSIGN_EXPERIMENTAL: 1 run: | - cosign verify "${{ env.nonroot_image_name }}" + cosign verify "${{ env.nonroot_image_name }}" \ + --certificate-oidc-issuer ${{ env.oidc-issuer }} \ + --certificate-identity "${{ env.oidc-identity }}" diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml deleted file mode 100644 index dcc9fefda71..00000000000 --- a/.github/actions/build-test-image/action.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: Build Test Image -description: A composite action that allows building and publishing the test remote runner image - -inputs: - repository: - description: The docker repository for the image - default: chainlink-tests - required: false - tag: - description: The tag to use by default and to use for checking image existance - default: ${{ github.sha }} - required: false - other_tags: - description: Other tags to push if needed - required: false - suites: - description: The test suites to build into the image - default: chaos migration reorg smoke soak benchmark load - required: false - QA_AWS_ROLE_TO_ASSUME: - description: The AWS role to assume as the CD user, if any. Used in configuring the docker/login-action - required: true - QA_AWS_REGION: - description: The AWS region the ECR repository is located in, should only be needed for public ECR repositories, used in configuring docker/login-action - required: true - QA_AWS_ACCOUNT_NUMBER: - description: The AWS region the ECR repository is located in, should only be needed for public ECR repositories, used in configuring docker/login-action - required: true - -runs: - using: composite - steps: - - # Base Test Image Logic - - name: Get CTF Version - id: version - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 - with: - go-project-path: ./integration-tests - module-name: github.com/smartcontractkit/chainlink-testing-framework - enforce-semantic-tag: false - - name: Get CTF sha - if: steps.version.outputs.is_semantic == 'false' - id: short_sha - env: - VERSION: ${{ steps.version.outputs.version }} - shell: bash - run: | - short_sha="${VERSION##*-}" - echo "short sha is: ${short_sha}" - echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT" - - name: Checkout chainlink-testing-framework - if: steps.version.outputs.is_semantic == 'false' - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink-testing-framework - ref: main - fetch-depth: 0 - path: ctf - - name: Get long sha - if: steps.version.outputs.is_semantic == 'false' - id: long_sha - env: - SHORT_SHA: ${{ steps.short_sha.outputs.short_sha }} - shell: bash - run: | - cd ctf - long_sha=$(git rev-parse ${SHORT_SHA}) - echo "sha is: ${long_sha}" - echo "long_sha=${long_sha}" >> "$GITHUB_OUTPUT" - - name: Check if test base image exists - if: steps.version.outputs.is_semantic == 'false' - id: check-base-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - repository: test-base-image - tag: ${{ steps.long_sha.outputs.long_sha }} - AWS_REGION: ${{ inputs.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} - - name: Build Base Image - if: steps.version.outputs.is_semantic == 'false' && steps.check-base-image.outputs.exists == 'false' - uses: smartcontractkit/chainlink-github-actions/docker/build-push@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - env: - BASE_IMAGE_NAME: ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image:${{ steps.long_sha.outputs.long_sha }} - with: - tags: ${{ env.BASE_IMAGE_NAME }} - file: ctf/k8s/Dockerfile.base - AWS_REGION: ${{ inputs.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} - # End Base Image Logic - - # Test Runner Logic - - name: Check if image exists - id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - repository: ${{ inputs.repository }} - tag: ${{ inputs.tag }} - AWS_REGION: ${{ inputs.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} - - name: Build and Publish Test Runner - if: steps.check-image.outputs.exists == 'false' - uses: smartcontractkit/chainlink-github-actions/docker/build-push@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - tags: | - ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/${{ inputs.repository }}:${{ inputs.tag }} - ${{ inputs.other_tags }} - file: ./integration-tests/test.Dockerfile - build-args: | - BASE_IMAGE=${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image - IMAGE_VERSION=${{ steps.long_sha.outputs.long_sha || steps.version.outputs.version }} - SUITES="${{ inputs.suites }}" - AWS_REGION: ${{ inputs.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} - - name: Print Image Built - shell: sh - env: - INPUTS_REPOSITORY: ${{ inputs.repository }} - INPUTS_TAG: ${{ inputs.tag }} - run: | - echo "### ${INPUTS_REPOSITORY} image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${INPUTS_TAG}\`" >>$GITHUB_STEP_SUMMARY - # End Test Runner Logic diff --git a/.github/actions/delete-deployments/action.yml b/.github/actions/delete-deployments/action.yml index eaf7e0f61bd..00b092bc80f 100644 --- a/.github/actions/delete-deployments/action.yml +++ b/.github/actions/delete-deployments/action.yml @@ -33,7 +33,7 @@ runs: with: version: ^9.0.0 - - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + - uses: actions/setup-node@v4.0.4 with: node-version: "20" cache: "pnpm" diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index f3697ed7195..ba9984523da 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -2,9 +2,6 @@ name: CI lint for Golang description: Runs CI lint for Golang inputs: # general inputs - id: - description: Unique metrics collection id - required: true name: description: Name of the lint action required: true @@ -24,18 +21,14 @@ inputs: go-module-file: description: Set where the go module file is located at default: "go.sum" - # grafana inputs - gc-host: - description: "grafana hostname" - gc-basic-auth: - description: "grafana basic auth" - gc-org-id: - description: "grafana org id" runs: using: composite steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 + with: + # We only need a full clone on merge_group events for golangci-lint. + fetch-depth: ${{ github.event_name == 'merge_group' && '0' || '1' }}" - name: Setup Go uses: ./.github/actions/setup-go with: @@ -50,34 +43,31 @@ runs: working-directory: ${{ inputs.go-directory }} shell: bash run: go build ./... + - 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 + else + echo "golangci-lint-working-directory=${{ inputs.go-directory }}" | tee -a $GITHUB_OUTPUT + fi - name: golangci-lint - uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 + uses: golangci/golangci-lint-action@38e1018663fa5173f3968ea0777460d3de38f256 # v5.3.0 with: - version: v1.59.1 - # 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 + version: v1.60.3 + only-new-issues: true args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml - working-directory: ${{ inputs.go-directory }} + working-directory: ${{ steps.set-working-directory.outputs.golangci-lint-working-directory }} - name: Print lint report artifact if: failure() shell: bash run: cat ${{ inputs.go-directory }}/golangci-lint-report.xml - name: Store lint report artifact if: always() - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@v4.4.3 with: name: golangci-lint-report path: ${{ inputs.go-directory }}/golangci-lint-report.xml - - name: Collect Metrics - if: always() - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: chainlink-golang-ci-${{ inputs.id }} - basic-auth: ${{ inputs.gc-basic-auth }} - hostname: ${{ inputs.gc-host }} - org-id: ${{ inputs.gc-org-id }} - this-job-name: ${{ inputs.name }} - continue-on-error: true + retention-days: 7 diff --git a/.github/actions/goreleaser-build-sign-publish/README.md b/.github/actions/goreleaser-build-sign-publish/README.md index d6bf7e6fd4a..afea60e1203 100644 --- a/.github/actions/goreleaser-build-sign-publish/README.md +++ b/.github/actions/goreleaser-build-sign-publish/README.md @@ -21,39 +21,20 @@ jobs: permissions: id-token: write contents: read - env: - MACOS_SDK_VERSION: 12.3 steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@v4.2.1 - name: Configure aws credentials uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 with: role-to-assume: ${{ secrets.aws-role-arn }} role-duration-seconds: ${{ secrets.aws-role-dur-sec }} aws-region: ${{ secrets.aws-region }} - - name: Cache macos sdk - id: sdk-cache - uses: actions/cache@v3 - with: - path: ${{ format('MacOSX{0}.sdk', env.MAC_SDK_VERSION) }} - key: ${{ runner.OS }}-${{ env.MAC_SDK_VERSION }}-macos-sdk-cache-${{ hashFiles('**/SDKSettings.json') }} - restore-keys: | - ${{ runner.OS }}-${{ env.MAC_SDK_VERSION }}-macos-sdk-cache- - - name: Get macos sdk - if: steps.sdk-cache.outputs.cache-hit != 'true' - run: | - curl -L https://github.com/joseluisq/macosx-sdks/releases/download/${MACOS_SDK_VERSION}/MacOSX${MACOS_SDK_VERSION}.sdk.tar.xz > MacOSX${MACOS_SDK_VERSION}.sdk.tar.xz - tar -xf MacOSX${MACOS_SDK_VERSION}.sdk.tar.xz - name: Build, sign, and publish uses: ./.github/actions/goreleaser-build-sign-publish with: - enable-docker-publish: "true" - enable-goreleaser-snapshot: "false" docker-registry: ${{ secrets.aws-ecr-registry }} - goreleaser-exec: goreleaser goreleaser-config: .goreleaser.yaml - macos-sdk-dir: ${{ format('MacOSX{0}.sdk', env.MAC_SDK_VERSION) }} env: GITHUB_TOKEN: ${{ secrets.gh-token }} ``` @@ -64,29 +45,8 @@ jobs: - name: Build, sign, and publish image uses: ./.github/actions/goreleaser-build-sign-publish with: - enable-docker-publish: "true" - enable-goreleaser-snapshot: "true" - docker-registry: ${{ secrets.aws-ecr-registry }} - goreleaser-exec: goreleaser - goreleaser-config: .goreleaser.yaml -``` - -### image signing - -```yaml -- name: Build, sign, and publish - uses: ./.github/actions/goreleaser-build-sign-publish - with: - enable-docker-publish: "true" - enable-goreleaser-snapshot: "false" - enable-cosign: "true" docker-registry: ${{ secrets.aws-ecr-registry }} - goreleaser-exec: goreleaser goreleaser-config: .goreleaser.yaml - cosign-password: ${{ secrets.cosign-password }} - cosign-public-key: ${{ secrets.cosign-public-key }} - cosign-private-key: ${{ secrets.cosign-private-key }} - macos-sdk-dir: MacOSX12.3.sdk ``` ## customizing @@ -97,19 +57,10 @@ Following inputs can be used as `step.with` keys | Name | Type | Default | Description | | ---------------------------- | ------ | ------------------ | ----------------------------------------------------------------------- | -| `goreleaser-version` | String | `1.13.1` | `goreleaser` version | -| `zig-version` | String | `0.10.0` | `zig` version | -| `cosign-version` | String | `v1.13.1` | `cosign` version | -| `macos-sdk-dir` | String | `MacOSX12.3.sdk` | MacOSX sdk directory | -| `enable-docker-publish` | Bool | `true` | Enable publishing of Docker images / manifests | +| `goreleaser-version` | String | `~> v2` | `goreleaser` version | | `docker-registry` | String | `localhost:5001` | Docker registry | -| `enable-goreleaser-snapshot` | Bool | `false` | Enable goreleaser build / release snapshot | -| `goreleaser-exec` | String | `goreleaser` | The goreleaser executable, can invoke wrapper script | +| `docker-image-tag` | String | `develop` | Docker image tag | | `goreleaser-config` | String | `.goreleaser.yaml` | The goreleaser configuration yaml | -| `enable-cosign` | Bool | `false` | Enable signing of Docker images | -| `cosign-public-key` | String | `""` | The public key to be used with cosign for verification | -| `cosign-private-key` | String | `""` | The private key to be used with cosign to sign the image | -| `cosign-password-key` | String | `""` | The password to decrypt the cosign private key needed to sign the image | ## testing @@ -122,10 +73,7 @@ docker run -d --restart=always -p "127.0.0.1:5001:5000" --name registry registry - run snapshot release, publish to local docker registry ```sh -GORELEASER_EXEC=" v2" required: false goreleaser-key: description: The goreleaser key required: false - zig-version: - description: The zig version - default: 0.10.1 - required: false - cosign-version: - description: The cosign version - default: v2.2.2 - required: false - macos-sdk-dir: - description: The macos sdk directory - default: MacOSX12.3.sdk - required: false # publishing inputs - enable-docker-publish: - description: Enable publishing of docker images / manifests - default: "true" - required: false docker-registry: description: The docker registry default: localhost:5001 required: false - docker-image-name: - description: The docker image name - default: chainlink - required: false docker-image-tag: description: The docker image tag default: develop required: false # goreleaser inputs - goreleaser-exec: - description: "The goreleaser executable, can invoke wrapper script" - default: "goreleaser" + goreleaser-release-type: + description: The goreleaser release type, it can be either "nightly", "merge", "snapshot", "release" + default: "snapshot" required: false goreleaser-config: description: "The goreleaser configuration yaml" default: ".goreleaser.yaml" required: false - enable-goreleaser-snapshot: - description: Enable goreleaser build / release snapshot - default: "false" - required: false - enable-goreleaser-split: - description: Enable goreleaser split and merge builds - default: "false" - required: false - goreleaser-split-arch: - description: The architecture to split the goreleaser build - required: false - # signing inputs - enable-cosign: - description: Enable signing of docker images - default: "false" - required: false - cosign-private-key: - description: The private key to be used with cosign to sign the image - required: false - cosign-public-key: - description: The public key to be used with cosign for verification - required: false - cosign-password: - description: The password to decrypt the cosign private key needed to sign the image - required: false runs: using: composite steps: + - # We need QEMU to test the cross architecture builds after they're built. + name: Set up QEMU + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Setup docker buildx uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 - - name: Set up qemu - uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Setup go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@v5.0.2 with: go-version-file: "go.mod" - name: Setup goreleaser - uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0 + uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0 with: distribution: goreleaser-pro install-only: true version: ${{ inputs.goreleaser-version }} env: GORELEASER_KEY: ${{ inputs.goreleaser-key }} - - name: Setup zig - uses: goto-bus-stop/setup-zig@7ab2955eb728f5440978d5824358023be3a2802d # v2.2.0 - with: - version: ${{ inputs.zig-version }} - - name: Setup cosign - if: inputs.enable-cosign == 'true' - uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0 - with: - cosign-release: ${{ inputs.cosign-version }} + - name: Login to docker registry - if: inputs.enable-docker-publish == 'true' uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: registry: ${{ inputs.docker-registry }} - - name: Set goreleaser split env - if: inputs.enable-goreleaser-split == 'true' - shell: bash - run: | - echo "GOOS=linux" | tee -a $GITHUB_ENV - echo "GOARCH=${{ inputs.goreleaser-split-arch }}" | tee -a $GITHUB_ENV + + - name: Install syft + uses: anchore/sbom-action/download-syft@61119d458adab75f756bc0b9e4bde25725f86a7a # v0.17.2 + - name: Run goreleaser release shell: bash env: - ENABLE_COSIGN: ${{ inputs.enable-cosign }} - ENABLE_GORELEASER_SNAPSHOT: ${{ inputs.enable-goreleaser-snapshot }} - ENABLE_GORELEASER_SPLIT: ${{ inputs.enable-goreleaser-split }} - ENABLE_DOCKER_PUBLISH: ${{ inputs.enable-docker-publish }} + GORELEASER_CONFIG: ${{ inputs.goreleaser-config }} + RELEASE_TYPE: ${{ inputs.goreleaser-release-type }} IMAGE_PREFIX: ${{ inputs.docker-registry }} - IMAGE_NAME: ${{ inputs.docker-image-name }} IMAGE_TAG: ${{ inputs.docker-image-tag }} - GORELEASER_EXEC: ${{ inputs.goreleaser-exec }} - GORELEASER_CONFIG: ${{ inputs.goreleaser-config }} - COSIGN_PASSWORD: ${{ inputs.cosign-password }} - COSIGN_PUBLIC_KEY: ${{ inputs.cosign-public-key }} - COSIGN_PRIVATE_KEY: ${{ inputs.cosign-private-key }} - MACOS_SDK_DIR: ${{ inputs.macos-sdk-dir }} + GORELEASER_KEY: ${{ inputs.goreleaser-key }} + GITHUB_TOKEN: ${{ github.token }} run: | # https://github.com/orgs/community/discussions/24950 - ${GITHUB_ACTION_PATH}/action_utils goreleaser_release + ${GITHUB_ACTION_PATH}/release.js diff --git a/.github/actions/goreleaser-build-sign-publish/action_utils b/.github/actions/goreleaser-build-sign-publish/action_utils deleted file mode 100755 index 051e0763fbd..00000000000 --- a/.github/actions/goreleaser-build-sign-publish/action_utils +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env bash -set -x -set -euo pipefail - -ENABLE_COSIGN=${ENABLE_COSIGN:-false} -ENABLE_GORELEASER_SNAPSHOT=${ENABLE_GORELEASER_SNAPSHOT:-false} -ENABLE_GORELEASER_SPLIT=${ENABLE_GORELEASER_SPLIT:-false} -ENABLE_DOCKER_PUBLISH=${ENABLE_DOCKER_PUBLISH:-false} -COSIGN_PASSWORD=${COSIGN_PASSWORD:-""} -GORELEASER_EXEC=${GORELEASER_EXEC:-goreleaser} -GORELEASER_CONFIG=${GORELEASER_CONFIG:-.goreleaser.yaml} -IMAGE_PREFIX=${IMAGE_PREFIX:-"localhost:5001"} -DOCKER_MANIFEST_EXTRA_ARGS=${DOCKER_MANIFEST_EXTRA_ARGS:-""} - -# publish snapshot docker images -# must have label=org.opencontainers.image.revision= set -_publish_snapshot_images() { - local full_sha=$(git rev-parse HEAD) - local images=$(docker images --filter "label=org.opencontainers.image.revision=$full_sha" --format "{{.Repository}}:{{.Tag}}") - for image in $images; do - docker push "$image" - done -} - -# publish snapshot docker manifest lists -# must have label=org.opencontainers.image.revision= set -_publish_snapshot_manifests() { - local docker_manifest_extra_args=$DOCKER_MANIFEST_EXTRA_ARGS - local full_sha=$(git rev-parse HEAD) - local images=$(docker images --filter "label=org.opencontainers.image.revision=$full_sha" --format "{{.Repository}}:{{.Tag}}" | sort) - local raw_manifest_lists="" - if [[ $ENABLE_GORELEASER_SPLIT == "true" ]]; then - local arches=(${GOARCH:-""}) - else - local arches=(amd64 arm64) - fi - for image in $images; do - for arch in "${arches[@]}"; do - image=${image%"-$arch"} - done - raw_manifest_lists+="$image"$'\n' - done - local manifest_lists=$(echo "$raw_manifest_lists" | sort | uniq) - for manifest_list in $manifest_lists; do - manifests="" - for arch in "${arches[@]}"; do - archExists=$(echo "$images" | grep -c "$manifest_lists-$arch") - if [[ $archExists -ne 0 ]]; then - manifests+="$manifest_list-$arch " - fi - done - docker manifest create $manifest_list $manifests $docker_manifest_extra_args - docker manifest push "$manifest_list" - done -} - -# wrapper function to invoke goreleaser release -goreleaser_release() { - goreleaser_flags=() - - # set goreleaser flags - if [[ $ENABLE_GORELEASER_SNAPSHOT == "true" ]]; then - goreleaser_flags+=("--snapshot") - goreleaser_flags+=("--clean") - fi - if [[ $ENABLE_GORELEASER_SPLIT == "true" ]]; then - goreleaser_flags+=("--split") - fi - flags=$(printf "%s " "${goreleaser_flags[@]}") - flags=$(echo "$flags" | sed 's/ *$//') - - if [[ $ENABLE_COSIGN == "true" ]]; then - echo "$COSIGN_PUBLIC_KEY" > cosign.pub - echo "$COSIGN_PRIVATE_KEY" > cosign.key - fi - - if [[ -n $MACOS_SDK_DIR ]]; then - MACOS_SDK_DIR=$(echo "$(cd "$(dirname "$MACOS_SDK_DIR")" || exit; pwd)/$(basename "$MACOS_SDK_DIR")") - fi - - $GORELEASER_EXEC release ${flags} --config "$GORELEASER_CONFIG" "$@" - - if [[ $ENABLE_DOCKER_PUBLISH == "true" ]]; then - _publish_snapshot_images - _publish_snapshot_manifests - fi - - if [[ $ENABLE_COSIGN == "true" ]]; then - rm -rf cosign.pub - rm -rf cosign.key - fi -} - -"$@" diff --git a/.github/actions/goreleaser-build-sign-publish/release.js b/.github/actions/goreleaser-build-sign-publish/release.js new file mode 100755 index 00000000000..0dbd58ca6cf --- /dev/null +++ b/.github/actions/goreleaser-build-sign-publish/release.js @@ -0,0 +1,243 @@ +#!/usr/bin/env node +const { execSync } = require("child_process"); +const fs = require("fs"); +const path = require("path"); + +function main() { + const args = process.argv.slice(2); + const useExistingDist = args.includes("--use-existing-dist"); + const chainlinkVersion = getVersion(); + + if (!useExistingDist) { + const goreleaserConfig = mustGetEnv("GORELEASER_CONFIG"); + const releaseType = mustGetEnv("RELEASE_TYPE"); + const command = constructGoreleaserCommand( + releaseType, + chainlinkVersion, + goreleaserConfig + ); + + if (process.env.DRY_RUN) { + console.log(`Generated command: ${command}`); + console.log("Dry run enabled. Exiting without executing the command."); + return; + } else { + console.log(`Executing command: ${command}`); + execSync(command, { stdio: "inherit" }); + } + } else { + console.log( + "Skipping Goreleaser command execution as '--use-existing-dist' is set." + ); + } + + const artifacts = getArtifacts(); + const dockerImages = extractDockerImages(artifacts); + const repoSha = execSync("git rev-parse HEAD", { encoding: "utf-8" }).trim(); + + const results = dockerImages.map((image) => { + try { + console.log( + `Checking version for image: ${image}, expected version: ${chainlinkVersion}, expected SHA: ${repoSha}` + ); + const versionOutput = execSync(`docker run --rm ${image} --version`, { + encoding: "utf-8", + }); + console.log(`Output from image ${image}: ${versionOutput}`); + + const cleanedOutput = versionOutput + .replace("chainlink version ", "") + .trim(); + const [version, sha] = cleanedOutput.split("@"); + if (!version || !sha) { + throw new Error("Version or SHA not found in output."); + } + + if (sha.trim() !== repoSha) { + throw new Error(`SHA mismatch: Expected ${repoSha}, got ${sha.trim()}`); + } + if (version.trim() !== chainlinkVersion) { + throw new Error( + `Version mismatch: Expected ${chainlinkVersion}, got ${version.trim()}` + ); + } + + return { image, success: true, message: "Version check passed." }; + } catch (error) { + return { image, success: false, message: error.message }; + } + }); + + printSummary(results); + if (results.some((result) => !result.success)) { + process.exit(1); + } +} + +function printSummary(results) { + const passed = results.filter((result) => result.success); + const failed = results.filter((result) => !result.success); + + console.log("\nSummary:"); + console.log(`Total images checked: ${results.length}`); + console.log(`Passed: ${passed.length}`); + console.log(`Failed: ${failed.length}`); + + if (passed.length > 0) { + console.log("\nPassed images:"); + passed.forEach((result) => + console.log(`${result.image}:\n${result.message}`) + ); + } + + if (failed.length > 0) { + console.log("\nFailed images:"); + failed.forEach((result) => + console.log(`${result.image}:\n${result.message}`) + ); + } +} + +function getArtifacts() { + const distDir = path.resolve(process.cwd(), "dist"); + const files = []; + + function findJsonFiles(dir) { + const items = fs.readdirSync(dir, { withFileTypes: true }); + for (const item of items) { + const fullPath = path.join(dir, item.name); + if (item.isDirectory()) { + // Skip child directories if an artifacts.json exists in the current directory + const parentArtifacts = path.join(dir, "artifacts.json"); + if (fs.existsSync(parentArtifacts)) { + console.log( + `Skipping child directory: ${fullPath} because a parent artifacts.json exists at: ${parentArtifacts}` + ); + } else { + findJsonFiles(fullPath); + } + } else if (item.isFile() && item.name === "artifacts.json") { + console.log(`Found artifacts.json at: ${fullPath}`); + files.push(fullPath); + } + } + } + + findJsonFiles(distDir); + + if (files.length === 0) { + console.error("Error: No artifacts.json found in /dist."); + process.exit(1); + } + + // Merge all artifacts.json files into one + let mergedArtifacts = []; + + for (const file of files) { + const artifactsJson = JSON.parse(fs.readFileSync(file, "utf-8")); + mergedArtifacts = mergedArtifacts.concat(artifactsJson); + } + + // Remove duplicate Docker images based on the artifact name + const uniqueArtifacts = Array.from( + new Map( + mergedArtifacts.map((artifact) => [artifact.name, artifact]) + ).values() + ); + + return uniqueArtifacts; +} + +function extractDockerImages(artifacts) { + const dockerImages = artifacts + .filter( + (artifact) => + artifact.type === "Docker Image" || + artifact.type === "Published Docker Image" + ) + .map((artifact) => artifact.name); + + if (dockerImages.length === 0) { + console.error("Error: No Docker images found in artifacts.json."); + process.exit(1); + } + + console.log(`Found Docker images:\n - ${dockerImages.join("\n - ")}`); + return dockerImages; +} + +function constructGoreleaserCommand(releaseType, version, goreleaserConfig) { + const flags = []; + + checkReleaseType(releaseType); + + let subCmd = "release"; + const splitArgs = ["--split", "--clean"]; + + switch (releaseType) { + case "release": + flags.push(...splitArgs); + break; + case "nightly": + flags.push("--nightly", ...splitArgs); + break; + case "snapshot": + flags.push("--snapshot", ...splitArgs); + break; + case "merge": + flags.push("--merge"); + subCmd = "continue"; + break; + } + + const flagsStr = flags.join(" "); + if (releaseType === "merge") { + return `CHAINLINK_VERSION=${version} goreleaser ${subCmd} ${flagsStr}`; + } else { + return `CHAINLINK_VERSION=${version} goreleaser ${subCmd} --config ${goreleaserConfig} ${flagsStr}`; + } +} + +function checkReleaseType(releaseType) { + const VALID_RELEASE_TYPES = ["nightly", "merge", "snapshot", "release"]; + + if (!VALID_RELEASE_TYPES.includes(releaseType)) { + const validReleaseTypesStr = VALID_RELEASE_TYPES.join(", "); + console.error( + `Error: Invalid release type: ${releaseType}. Must be one of: ${validReleaseTypesStr}` + ); + process.exit(1); + } +} + +function mustGetEnv(key) { + const val = process.env[key]; + if (!val || val.trim() === "") { + console.error(`Error: Environment variable ${key} is not set or empty.`); + process.exit(1); + } + + return val.trim(); +} + +function getVersion() { + try { + const pkgPath = path.resolve(process.cwd(), "package.json"); + console.log("Looking for chainlink version in package.json at: ", pkgPath); + const packageJson = require(pkgPath); + if (!packageJson.version) { + console.error( + 'Error: "version" field is missing or empty in package.json.' + ); + process.exit(1); + } + console.log("Resolved version: ", packageJson.version); + + return packageJson.version; + } catch (err) { + console.error(`Error reading package.json: ${err.message}`); + process.exit(1); + } +} + +main(); diff --git a/.github/actions/setup-create-base64-config-ccip/action.yml b/.github/actions/setup-create-base64-config-ccip/action.yml deleted file mode 100644 index 88d9fe8078c..00000000000 --- a/.github/actions/setup-create-base64-config-ccip/action.yml +++ /dev/null @@ -1,187 +0,0 @@ -name: Create Base64 Config for CCIP Tests -description: A composite action that creates a base64-encoded config to be used by ccip integration tests - -inputs: - runId: - description: The run id - existingNamespace: - description: If test needs to run against already deployed namespace - testLogCollect: - description: Whether to always collect logs, even for passing tests - default: "false" - selectedNetworks: - description: The networks to run tests against - chainlinkImage: - description: The chainlink image to use - default: "public.ecr.aws/chainlink/chainlink" - chainlinkVersion: - description: The git commit sha to use for the image tag - upgradeImage: - description: The chainlink image to upgrade to - default: "" - upgradeVersion: - description: The git commit sha to use for the image tag - lokiEndpoint: - description: Loki push endpoint - lokiTenantId: - description: Loki tenant id - lokiBasicAuth: - description: Loki basic auth - logstreamLogTargets: - description: Where to send logs (e.g. file, loki) - grafanaUrl: - description: Grafana URL - grafanaDashboardUrl: - description: Grafana dashboard URL - grafanaBearerToken: - description: Grafana bearer token - customEvmNodes: - description: Custom EVM nodes to use in key=value format, where key is chain id and value is docker image to use. If they are provided the number of networksSelected must be equal to the number of customEvmNodes - evmNodeLogLevel: - description: Log level for the custom EVM nodes - default: "info" - -runs: - using: composite - steps: - - name: Prepare Base64 TOML override - shell: bash - id: base64-config-override - env: - RUN_ID: ${{ inputs.runId }} - SELECTED_NETWORKS: ${{ inputs.selectedNetworks }} - EXISTING_NAMESPACE: ${{ inputs.existingNamespace }} - TEST_LOG_COLLECT: ${{ inputs.testLogCollect }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} - UPGRADE_IMAGE: ${{ inputs.upgradeImage }} - UPGRADE_VERSION: ${{ inputs.upgradeVersion }} - LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} - LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} - LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} - LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} - GRAFANA_URL: ${{ inputs.grafanaUrl }} - GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} - GRAFANA_BEARER_TOKEN: ${{ inputs.grafanaBearerToken }} - CUSTOM_EVM_NODES: ${{ inputs.customEvmNodes }} - EVM_NODE_LOG_LEVEL: ${{ inputs.evmNodeLogLevel }} - run: | - echo ::add-mask::$CHAINLINK_IMAGE - function convert_to_toml_array() { - local IFS=',' - local input_array=($1) - local toml_array_format="[" - - for element in "${input_array[@]}"; do - toml_array_format+="\"$element\"," - done - - toml_array_format="${toml_array_format%,}]" - echo "$toml_array_format" - } - - selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") - log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") - - if [ -n "$TEST_LOG_COLLECT" ]; then - test_log_collect=true - else - test_log_collect=false - fi - - # make sure the number of networks and nodes match - IFS=',' read -r -a networks_array <<< "$SELECTED_NETWORKS" - IFS=',' read -r -a nodes_array <<< "$CUSTOM_EVM_NODES" - - networks_count=${#networks_array[@]} - nodes_count=${#nodes_array[@]} - - # Initialize or clear CONFIG_TOML environment variable - custom_nodes_toml="" - - # Check if the number of CUSTOM_EVM_NODES is zero - if [ $nodes_count -eq 0 ]; then - echo "The number of CUSTOM_EVM_NODES is zero, won't output any custom private Ethereum network configurations." - else - if [ $networks_count -ne $nodes_count ]; then - echo "The number of elements in SELECTED_NETWORKS (${networks_count}) and CUSTOM_EVM_NODES does not match (${nodes_count})." - exit 1 - else - for i in "${!networks_array[@]}"; do - IFS='=' read -r chain_id docker_image <<< "${nodes_array[i]}" - custom_nodes_toml+=" - [CCIP.Env.PrivateEthereumNetworks.${networks_array[i]}] - ethereum_version=\"\" - execution_layer=\"\" - - [CCIP.Env.PrivateEthereumNetworks.${networks_array[i]}.EthereumChainConfig] - seconds_per_slot=3 - slots_per_epoch=2 - genesis_delay=15 - validator_count=4 - chain_id=${chain_id} - addresses_to_fund=[\"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\", \"0x70997970C51812dc3A010C7d01b50e0d17dc79C8\"] - node_log_level=\"${EVM_NODES_LOG_LEVEL}\" - - [CCIP.Env.PrivateEthereumNetworks.${networks_array[i]}.EthereumChainConfig.HardForkEpochs] - Deneb=500 - - [CCIP.Env.PrivateEthereumNetworks.${networks_array[i]}.CustomDockerImages] - execution_layer=\"${docker_image}\" - " - done - fi - fi - - grafana_bearer_token="" - if [ -n "$GRAFANA_BEARER_TOKEN" ]; then - grafana_bearer_token="bearer_token_secret=\"$GRAFANA_BEARER_TOKEN\"" - fi - - cat << EOF > config.toml - [CCIP] - [CCIP.Env] - EnvToConnect="$EXISTING_NAMESPACE" - [CCIP.Env.Network] - selected_networks = $selected_networks - [CCIP.Env.NewCLCluster] - [CCIP.Env.NewCLCluster.Common] - [CCIP.Env.NewCLCluster.Common.ChainlinkImage] - image="$CHAINLINK_IMAGE" - version="$CHAINLINK_VERSION" - - [CCIP.Env.NewCLCluster.Common.ChainlinkUpgradeImage] - image="$UPGRADE_IMAGE" - version="$UPGRADE_VERSION" - - $custom_nodes_toml - - [CCIP.Env.Logging] - test_log_collect=$test_log_collect - run_id="$RUN_ID" - - [CCIP.Env.Logging.LogStream] - log_targets=$log_targets - - [CCIP.Env.Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_ENDPOINT" - basic_auth_secret="$LOKI_BASIC_AUTH" - - [CCIP.Env.Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="$GRAFANA_DASHBOARD_URL" - $grafana_bearer_token - - [CCIP.Groups.load] - TestRunName = '$EXISTING_NAMESPACE' - - [CCIP.Groups.smoke] - TestRunName = '$EXISTING_NAMESPACE' - - EOF - - BASE64_CCIP_SECRETS_CONFIG=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CCIP_SECRETS_CONFIG - echo "BASE64_CCIP_SECRETS_CONFIG=$BASE64_CCIP_SECRETS_CONFIG" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_SECRETS_CONFIG=$BASE64_CCIP_SECRETS_CONFIG" >> $GITHUB_ENV diff --git a/.github/actions/setup-create-base64-config-live-testnets/action.yml b/.github/actions/setup-create-base64-config-live-testnets/action.yml deleted file mode 100644 index 64fc134b46e..00000000000 --- a/.github/actions/setup-create-base64-config-live-testnets/action.yml +++ /dev/null @@ -1,144 +0,0 @@ -name: Create Base64 Config -description: A composite action that creates a base64-encoded config to be used by integration tests - -inputs: - runId: - description: The run id - testLogCollect: - description: Whether to always collect logs, even for passing tests - default: "false" - chainlinkImage: - description: The chainlink image to use - default: "public.ecr.aws/chainlink/chainlink" - chainlinkVersion: - description: The git commit sha to use for the image tag - chainlinkPostgresVersion: - description: The postgres version to use with the chainlink node - default: "15.6" - pyroscopeServer: - description: URL of Pyroscope server - pyroscopeEnvironment: - description: Name of Pyroscope environment - pyroscopeKey: - description: Pyroscope server key - lokiEndpoint: - description: Loki push endpoint - lokiTenantId: - description: Loki tenant id - lokiBasicAuth: - description: Loki basic auth - logstreamLogTargets: - description: Where to send logs (e.g. file, loki) - grafanaUrl: - description: Grafana URL - grafanaDashboardUrl: - description: Grafana dashboard URL - grafanaBearerToken: - description: Grafana bearer token - network: - description: Network to run tests on - httpEndpoints: - description: HTTP endpoints to use for network - wsEndpoints: - description: WS endpoints to use for network - fundingKeys: - description: Funding keys to use for network - -runs: - using: composite - steps: - - name: Prepare Base64 TOML override - shell: bash - id: base64-config-override - env: - RUN_ID: ${{ inputs.runId }} - PYROSCOPE_SERVER: ${{ inputs.pyroscopeServer }} - PYROSCOPE_ENVIRONMENT: ${{ inputs.pyroscopeEnvironment }} - PYROSCOPE_KEY: ${{ inputs.pyroscopeKey }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} - CHAINLINK_POSTGRES_VERSION: ${{ inputs.chainlinkPostgresVersion }} - LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} - LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} - LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} - LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} - GRAFANA_URL: ${{ inputs.grafanaUrl }} - GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} - GRAFANA_BEARER_TOKEN: ${{ inputs.grafanaBearerToken }} - NETWORK: ${{ inputs.network }} - HTTP_ENDPOINTS: ${{ inputs.httpEndpoints }} - WS_ENDPOINTS: ${{ inputs.wsEndpoints }} - FUNDING_KEYS: ${{ inputs.fundingKeys }} - run: | - convert_to_toml_array() { - local IFS=',' - local input_array=($1) - local toml_array_format="[" - - for element in "${input_array[@]}"; do - toml_array_format+="\"$element\"," - done - - toml_array_format="${toml_array_format%,}]" - echo "$toml_array_format" - } - - if [ -n "$PYROSCOPE_SERVER" ]; then - pyroscope_enabled=true - else - pyroscope_enabled=false - fi - - grafana_bearer_token="" - if [ -n "$GRAFANA_BEARER_TOKEN" ]; then - grafana_bearer_token="bearer_token_secret=\"$GRAFANA_BEARER_TOKEN\"" - fi - - cat << EOF > config.toml - [Common] - chainlink_node_funding=0.5 - - [ChainlinkImage] - image="$CHAINLINK_IMAGE" - version="$CHAINLINK_VERSION" - postgres_version="$CHAINLINK_POSTGRES_VERSION" - - [Pyroscope] - enabled=$pyroscope_enabled - server_url="$PYROSCOPE_SERVER" - environment="$PYROSCOPE_ENVIRONMENT" - key_secret="$PYROSCOPE_KEY" - - [Logging] - run_id="$RUN_ID" - - [Logging.LogStream] - log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") - - [Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_URL" - basic_auth_secret="$LOKI_BASIC_AUTH" - - [Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="$GRAFANA_DASHBOARD_URL" - $grafana_bearer_token - - [Network] - selected_networks=["$NETWORK"] - - [Network.RpcHttpUrls] - "$NETWORK" = $(convert_to_toml_array "$HTTP_ENDPOINTS") - - [Network.RpcWsUrls] - "$NETWORK" = $(convert_to_toml_array "$WS_ENDPOINTS") - - [Network.WalletKeys] - "$NETWORK" = $(convert_to_toml_array "$FUNDING_KEYS") - EOF - - BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - touch .root_dir diff --git a/.github/actions/setup-create-base64-upgrade-config/action.yml b/.github/actions/setup-create-base64-upgrade-config/action.yml deleted file mode 100644 index c2d0bc19f35..00000000000 --- a/.github/actions/setup-create-base64-upgrade-config/action.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: Create Base64 Upgrade Config -description: A composite action that creates a base64-encoded config to be used by Chainlink version upgrade tests - -inputs: - selectedNetworks: - description: The networks to run tests against - chainlinkImage: - description: The chainlink image to upgrade from - default: "public.ecr.aws/chainlink/chainlink" - chainlinkVersion: - description: The git commit sha to use for the image tag - chainlinkPostgresVersion: - description: The postgres version to use with the chainlink node - default: "15.6" - upgradeImage: - description: The chainlink image to upgrade to - default: "public.ecr.aws/chainlink/chainlink" - upgradeVersion: - description: The git commit sha to use for the image tag - runId: - description: The run id - testLogCollect: - description: Whether to always collect logs, even for passing tests - default: "false" - lokiEndpoint: - description: Loki push endpoint - lokiTenantId: - description: Loki tenant id - lokiBasicAuth: - description: Loki basic auth - logstreamLogTargets: - description: Where to send logs (e.g. file, loki) - grafanaUrl: - description: Grafana URL - grafanaDashboardUrl: - description: Grafana dashboard URL - grafanaBearerToken: - description: Grafana bearer token - -runs: - using: composite - steps: - - name: Prepare Base64 TOML override - shell: bash - id: base64-config-override - env: - SELECTED_NETWORKS: ${{ inputs.selectedNetworks }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} - CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} - CHAINLINK_POSTGRES_VERSION: ${{ inputs.chainlinkPostgresVersion }} - UPGRADE_IMAGE: ${{ inputs.upgradeImage }} - UPGRADE_VERSION: ${{ inputs.upgradeVersion }} - RUN_ID: ${{ inputs.runId }} - TEST_LOG_COLLECT: ${{ inputs.testLogCollect }} - LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} - LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} - LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} - LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} - GRAFANA_URL: ${{ inputs.grafanaUrl }} - GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} - GRAFANA_BEARER_TOKEN: ${{ inputs.grafanaBearerToken }} - run: | - function convert_to_toml_array() { - local IFS=',' - local input_array=($1) - local toml_array_format="[" - - for element in "${input_array[@]}"; do - toml_array_format+="\"$element\"," - done - - toml_array_format="${toml_array_format%,}]" - echo "$toml_array_format" - } - - selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") - - if [ -n "$TEST_LOG_COLLECT" ]; then - test_log_collect=true - else - test_log_collect=false - fi - - log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") - - grafana_bearer_token="" - if [ -n "$GRAFANA_BEARER_TOKEN" ]; then - grafana_bearer_token="bearer_token_secret=\"$GRAFANA_BEARER_TOKEN\"" - fi - - cat << EOF > config.toml - [Network] - selected_networks=$selected_networks - - [ChainlinkImage] - image="$CHAINLINK_IMAGE" - version="$CHAINLINK_VERSION" - postgres_version="$CHAINLINK_POSTGRES_VERSION" - - [ChainlinkUpgradeImage] - image="$UPGRADE_IMAGE" - version="$UPGRADE_VERSION" - postgres_version="$CHAINLINK_POSTGRES_VERSION" - - [Logging] - test_log_collect=$test_log_collect - run_id="$RUN_ID" - - [Logging.LogStream] - log_targets=$log_targets - - [Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_ENDPOINT" - basic_auth_secret="$LOKI_BASIC_AUTH" - - [Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="$GRAFANA_DASHBOARD_URL" - $grafana_bearer_token - EOF - - BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml index 6514f533ef0..d9a8f07bacd 100644 --- a/.github/actions/setup-go/action.yml +++ b/.github/actions/setup-go/action.yml @@ -18,7 +18,7 @@ runs: using: composite steps: - name: Set up Go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@v5.0.2 with: go-version-file: ${{ inputs.go-version-file }} cache: false @@ -40,7 +40,7 @@ runs: shell: bash run: echo "path=./${{ inputs.go-module-file }}" >> $GITHUB_OUTPUT - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + - uses: actions/cache@v4.1.1 name: Cache Go Modules with: path: | @@ -51,7 +51,7 @@ runs: restore-keys: | ${{ runner.os }}-gomod-${{ inputs.cache-version }}- - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + - uses: actions/cache@v4.1.1 if: ${{ inputs.only-modules == 'false' }} name: Cache Go Build Outputs with: diff --git a/.github/actions/setup-hardhat/action.yaml b/.github/actions/setup-hardhat/action.yaml index 189c8210024..a61e61bb5c7 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@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@v4.1.1 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@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@v4.1.1 with: path: | contracts/cache/ diff --git a/.github/actions/setup-merge-base64-config/action.yml b/.github/actions/setup-merge-base64-config/action.yml deleted file mode 100644 index 79dc8758315..00000000000 --- a/.github/actions/setup-merge-base64-config/action.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Merge Base64 Config -description: A composite action that merges user-provided Base64-encoded config with repository's secrets - -inputs: - base64Config: - description: Base64-encoded config to decode - -runs: - using: composite - steps: - - name: Install dasel - shell: bash - run: | - if ! which dasel > /dev/null; then - curl -L -o dasel "https://github.com/TomWright/dasel/releases/download/v2.6.0/dasel_linux_amd64" && chmod +x dasel && sudo mv dasel /usr/local/bin/ - else - echo "Dasel is already installed." - fi - - name: Add masks and export base64 config - shell: bash - run: | - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - decoded_toml=$(echo $BASE64_CONFIG_OVERRIDE | base64 -d) - CHAINLINK_IMAGE=$(echo "$decoded_toml" | { dasel -r toml 'ChainlinkImage.image' 2>/dev/null || echo ''; }) - echo ::add-mask::$CHAINLINK_IMAGE - CHAINLINK_VERSION=$(echo "$decoded_toml" | { dasel -r toml 'ChainlinkImage.version' 2>/dev/null || echo ''; }) - NETWORKS=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*selected_networks[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) - - if [ -n "$CHAINLINK_IMAGE" ]; then - echo "CHAINLINK_IMAGE=$CHAINLINK_IMAGE" >> $GITHUB_ENV - else - echo "No Chainlink Image found in base64-ed config" - fi - if [ -n "$CHAINLINK_VERSION" ]; then - echo "CHAINLINK_VERSION=$CHAINLINK_VERSION" >> $GITHUB_ENV - else - echo "No Chainlink Version found in base64-ed config" - fi - if [ -n "$NETWORKS" ]; then - echo "NETWORKS=$NETWORKS" >> $GITHUB_ENV - fi - - grafana_bearer_token="" - if [ -n "$GRAFANA_BEARER_TOKEN" ]; then - grafana_bearer_token="bearer_token_secret=\"$GRAFANA_BEARER_TOKEN\"" - fi - - # use Loki config from GH secrets and merge it with base64 input - cat << EOF > config.toml - [Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_URL" - basic_auth_secret="$LOKI_BASIC_AUTH" - # legacy, you only need this to access the cloud version - # bearer_token_secret="bearer_token" - - [Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="$GRAFANA_DASHBOARD_URL" - $grafana_bearer_token - EOF - - echo "$decoded_toml" >> final_config.toml - cat config.toml >> final_config.toml - BASE64_CONFIG_OVERRIDE=$(cat final_config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV \ No newline at end of file diff --git a/.github/actions/setup-nodejs/action.yaml b/.github/actions/setup-nodejs/action.yaml index e0de9b01382..f9b89392620 100644 --- a/.github/actions/setup-nodejs/action.yaml +++ b/.github/actions/setup-nodejs/action.yaml @@ -15,7 +15,7 @@ runs: with: version: ^9.0.0 - - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + - uses: actions/setup-node@v4.0.4 with: node-version: "20" cache: "pnpm" diff --git a/.github/actions/setup-parse-base64-config/action.yml b/.github/actions/setup-parse-base64-config/action.yml deleted file mode 100644 index 72e8982e6d0..00000000000 --- a/.github/actions/setup-parse-base64-config/action.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Parse Base64 Config -description: A composite action that extracts the chainlink image, version and network from a base64-encoded config - -inputs: - base64Config: - description: Base64-encoded config to decode - -runs: - using: composite - steps: - - name: Install dasel - shell: bash - run: | - if ! which dasel > /dev/null; then - curl -L -o dasel "https://github.com/TomWright/dasel/releases/download/v2.6.0/dasel_linux_amd64" && chmod +x dasel && sudo mv dasel /usr/local/bin/ - else - echo "Dasel is already installed." - fi - - name: Add masks and export base64 config - shell: bash - run: | - decoded_toml=$(echo $BASE64_CONFIG_OVERRIDE | base64 -d) - CHAINLINK_IMAGE=$(echo "$decoded_toml" | { dasel -r toml 'ChainlinkImage.image' 2>/dev/null || echo ''; }) - echo ::add-mask::$CHAINLINK_IMAGE - CHAINLINK_VERSION=$(echo "$decoded_toml" | { dasel -r toml 'ChainlinkImage.version' 2>/dev/null || echo ''; }) - NETWORKS=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*selected_networks[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) - ETH2_EL_CLIENT=$(echo "$decoded_toml" | awk -F'=' '/^[[:space:]]*execution_layer[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2}' 2>/dev/null) - - if [ -n "$CHAINLINK_IMAGE" ]; then - echo "CHAINLINK_IMAGE=$CHAINLINK_IMAGE" >> $GITHUB_ENV - else - echo "No Chainlink Image found in base64-ed config" - fi - if [ -n "$CHAINLINK_VERSION" ]; then - echo "CHAINLINK_VERSION=$CHAINLINK_VERSION" >> $GITHUB_ENV - else - echo "No Chainlink Version found in base64-ed config. Exiting" - fi - if [ -n "$NETWORKS" ]; then - echo "NETWORKS=$NETWORKS" >> $GITHUB_ENV - fi - if [ -n "$ETH2_EL_CLIENT" ]; then - echo "ETH2_EL_CLIENT=$ETH2_EL_CLIENT" >> $GITHUB_ENV - fi \ No newline at end of file diff --git a/.github/actions/setup-slither/action.yaml b/.github/actions/setup-slither/action.yaml deleted file mode 100644 index b8bef38575d..00000000000 --- a/.github/actions/setup-slither/action.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: Setup Slither -description: Installs Slither 0.10.3 for contract analysis. Requires Python 3.6 or higher. -runs: - using: composite - steps: - - name: Install Slither - shell: bash - run: | - python -m pip install --upgrade pip - pip install slither-analyzer==0.10.3 diff --git a/.github/actions/setup-solana/action.yml b/.github/actions/setup-solana/action.yml index 02a0b85ca8b..de7c4331abc 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@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + - uses: actions/cache@v4.1.1 id: cache name: Cache solana CLI with: diff --git a/.github/actions/setup-solc-select/action.yaml b/.github/actions/setup-solc-select/action.yaml deleted file mode 100644 index b74ffae018d..00000000000 --- a/.github/actions/setup-solc-select/action.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Setup Solc Select -description: Installs Solc Select, required versions and selects the version to use. Requires Python 3.6 or higher. -inputs: - to_install: - description: Comma-separated list of solc versions to install - required: true - to_use: - description: Solc version to use - required: true - -runs: - using: composite - steps: - - name: Install solc-select and solc - shell: bash - run: | - pip3 install solc-select - sudo ln -s /usr/local/bin/solc-select /usr/bin/solc-select - - IFS=',' read -ra versions <<< "${{ inputs.to_install }}" - for version in "${versions[@]}"; do - solc-select install $version - if [ $? -ne 0 ]; then - echo "Failed to install Solc $version" - exit 1 - fi - done - - solc-select install ${{ inputs.to_use }} - solc-select use ${{ inputs.to_use }} diff --git a/.github/actions/setup-wasmd/action.yml b/.github/actions/setup-wasmd/action.yml index ae31cf2395a..d95e8129260 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@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + - uses: actions/cache@v4.1.1 id: cache name: Cache wasmd-build with: diff --git a/.github/actions/validate-solidity-artifacts/action.yaml b/.github/actions/validate-solidity-artifacts/action.yaml deleted file mode 100644 index 5357a87f96b..00000000000 --- a/.github/actions/validate-solidity-artifacts/action.yaml +++ /dev/null @@ -1,115 +0,0 @@ -name: Validate Solidity Artifacts -description: Checks whether Slither reports and UML diagrams were generated for all necessary files. If not, a warning is printed in job summary, but the job is not marked as failed. -inputs: - slither_reports_path: - description: Path to the Slither reports directory (without trailing slash) - required: true - uml_diagrams_path: - description: Path to the UML diagrams directory (without trailing slash) - required: true - validate_slither_reports: - description: Whether Slither reports should be validated - required: true - validate_uml_diagrams: - description: Whether UML diagrams should be validated - required: true - sol_files: - description: Comma-separated (CSV) or space-separated (shell) list of Solidity files to check - required: true - -runs: - using: composite - steps: - - name: Transform input array - id: transform_input_array - shell: bash - run: | - is_csv_format() { - local input="$1" - if [[ "$input" =~ "," ]]; then - return 0 - else - return 1 - fi - } - - is_space_separated_string() { - local input="$1" - if [[ "$input" =~ ^[^[:space:]]+([[:space:]][^[:space:]]+)*$ ]]; then - return 0 - else - return 1 - fi - } - - array="${{ inputs.sol_files }}" - - if is_csv_format "$array"; then - echo "::debug::CSV format detected, nothing to do" - echo "sol_files=$array" >> $GITHUB_OUTPUT - exit 0 - fi - - if is_space_separated_string "$array"; then - echo "::debug::Space-separated format detected, converting to CSV" - csv_array="${array// /,}" - echo "sol_files=$csv_array" >> $GITHUB_OUTPUT - exit 0 - fi - - echo "::error::Invalid input format for sol_files. Please provide a comma-separated (CSV) or space-separated (shell) list of Solidity files" - exit 1 - - - name: Validate UML diagrams - if: ${{ inputs.validate_uml_diagrams == 'true' }} - shell: bash - run: | - echo "Validating UML diagrams" - IFS=',' read -r -a modified_files <<< "${{ steps.transform_input_array.outputs.sol_files }}" - missing_svgs=() - for file in "${modified_files[@]}"; do - svg_file="$(basename "${file%.sol}").svg" - if [ ! -f "${{ inputs.uml_diagrams_path }}/$svg_file" ]; then - echo "Error: UML diagram for $file not found" - missing_svgs+=("$file") - fi - done - - if [ ${#missing_svgs[@]} -gt 0 ]; then - echo "Error: Missing UML diagrams for files: ${missing_svgs[@]}" - echo "# Warning!" >> $GITHUB_STEP_SUMMARY - echo "## Reason: Missing UML diagrams for files:" >> $GITHUB_STEP_SUMMARY - for file in "${missing_svgs[@]}"; do - echo " $file" >> $GITHUB_STEP_SUMMARY - done - echo "## Action required: Please try to generate artifacts for them locally or using a different tool" >> $GITHUB_STEP_SUMMARY - else - echo "All UML diagrams generated successfully" - fi - - - name: Validate Slither reports - if: ${{ inputs.validate_slither_reports == 'true' }} - shell: bash - run: | - echo "Validating Slither reports" - IFS=',' read -r -a modified_files <<< "${{ steps.transform_input_array.outputs.sol_files }}" - missing_reports=() - for file in "${modified_files[@]}"; do - report_file="$(basename "${file%.sol}")-slither-report.md" - if [ ! -f "${{ inputs.slither_reports_path }}/$report_file" ]; then - echo "Error: Slither report for $file not found" - missing_reports+=("$file") - fi - done - - if [ ${#missing_reports[@]} -gt 0 ]; then - echo "Error: Missing Slither reports for files: ${missing_reports[@]}" - echo "# Warning!" >> $GITHUB_STEP_SUMMARY - echo "## Reason: Missing Slither reports for files:" >> $GITHUB_STEP_SUMMARY - for file in "${missing_reports[@]}"; do - echo " $file" >> $GITHUB_STEP_SUMMARY - done - echo "## Action required: Please try to generate artifacts for them locally" >> $GITHUB_STEP_SUMMARY - else - echo "All Slither reports generated successfully" - fi diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cea4f07b90d..d7af2d7f750 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -28,3 +28,43 @@ updates: schedule: interval: monthly open-pull-requests-limit: 0 + - package-ecosystem: gomod + directory: "/lib" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "ctf" + - package-ecosystem: gomod + directory: "/wasp" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "ctf" + - package-ecosystem: gomod + directory: "/seth" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "ctf" + - package-ecosystem: gomod + directory: "/havoc" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "ctf" + - package-ecosystem: gomod + directory: "/k8s-test-runner" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "ctf" diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index b2c9f12fcaf..3b91bd251a1 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -3,787 +3,857 @@ # Each entry in this file includes the following: # - The GitHub runner (runs_on field) that will execute tests. # - The tests that will be run by the runner. -# - The workflows (e.g., Run PR E2E Tests, Run Nightly E2E Tests) that should trigger these tests. +# - The triggers (e.g., Run PR E2E Tests, Nightly E2E Tests) that should trigger these tests. # runner-test-matrix: # START: OCR tests # Example of 1 runner for all tests in integration-tests/smoke/ocr_test.go - - id: integration-tests/smoke/ocr_test.go:* + - id: smoke/ocr_test.go:* path: integration-tests/smoke/ocr_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/ocr_test.go -timeout 30m -count=1 -test.parallel=2 -json pyroscope_env: ci-smoke-ocr-evm-simulated - # Example of 2 separate runners for the same test file but different tests. Can be used if tests if are too heavy to run on the same runner - - id: integration-tests/smoke/ocr2_test.go:^TestOCRv2Request$ - path: integration-tests/smoke/ocr2_test.go - test_env_type: docker + - id: soak/ocr_test.go:TestOCRv1Soak + path: integration-tests/soak/ocr_test.go + test_env_type: k8s-remote-runner runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ocr2_test.go -test.run ^TestOCRv2Request$ -test.parallel=1 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-ocr2-evm-simulated-nightly + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv1Soak$ -test.parallel=1 -timeout 900h -count=1 -json + test_cmd_opts: 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false + test_secrets_required: true + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/smoke/ocr2_test.go:^TestOCRv2Basic$ - path: integration-tests/smoke/ocr2_test.go - test_env_type: docker + - id: soak/ocr_test.go:TestOCRv2Soak + path: integration-tests/soak/ocr_test.go + test_env_type: k8s-remote-runner runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ocr2_test.go -test.run ^TestOCRv2Basic$ -test.parallel=1 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-ocr2-evm-simulated-nightly + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv2Soak$ -test.parallel=1 -timeout 900h -count=1 -json + test_cmd_opts: 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false + test_secrets_required: true + test_env_vars: + TEST_SUITE: soak - # Example of a configuration for running a single soak test in Kubernetes Remote Runner - - id: integration-tests/soak/ocr_test.go:^TestOCRv1Soak$ + - id: soak/ocr_test.go:TestOCRv2Soak_WemixTestnet path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv1Soak$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true - test_secrets_required: true - test_inputs: - test_suite: soak + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv2Soak$ -test.parallel=1 -timeout 900h -count=1 -json + test_config_override_path: integration-tests/testconfig/ocr2/overrides/wemix_testnet.toml + test_secrets_required: true + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRv2Soak$ + # This can be used to run a quick smoke test for OCRv2 to see if integration-tests/soak/ocr_test.go is working + - id: soak/ocr_test.go:TestOCRv2Soak_QuickSmokeTest path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv2Soak$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv2Soak$ -test.parallel=1 -timeout 900h -count=1 -json + test_config_override_path: integration-tests/testconfig/ocr2/overrides/base_sepolia_quick_smoke_test.toml test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestForwarderOCRv1Soak$ + - id: soak/ocr_test.go:TestForwarderOCRv1Soak path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestForwarderOCRv1Soak$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestForwarderOCRv1Soak$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestForwarderOCRv2Soak$ + - id: soak/ocr_test.go:TestForwarderOCRv2Soak path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestForwarderOCRv2Soak$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestForwarderOCRv2Soak$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled$ + - id: soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled$ + - id: soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRSoak_GasSpike$ + - id: soak/ocr_test.go:TestOCRSoak_GasSpike path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GasSpike$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GasSpike$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRSoak_ChangeBlockGasLimit$ + - id: soak/ocr_test.go:TestOCRSoak_ChangeBlockGasLimit path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_ChangeBlockGasLimit$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_ChangeBlockGasLimit$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRSoak_RPCDownForAllCLNodes$ + - id: soak/ocr_test.go:TestOCRSoak_RPCDownForAllCLNodes path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_RPCDownForAllCLNodes$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_RPCDownForAllCLNodes$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/soak/ocr_test.go:^TestOCRSoak_RPCDownForHalfCLNodes$ + - id: soak/ocr_test.go:TestOCRSoak_RPCDownForHalfCLNodes path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_RPCDownForHalfCLNodes$ -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true + test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_RPCDownForHalfCLNodes$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true - test_inputs: - test_suite: soak + test_env_vars: + TEST_SUITE: soak - - id: integration-tests/smoke/forwarder_ocr_test.go:* + - id: smoke/forwarder_ocr_test.go:* path: integration-tests/smoke/forwarder_ocr_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/forwarder_ocr_test.go -timeout 30m -count=1 -test.parallel=2 -json pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated - - id: integration-tests/smoke/forwarders_ocr2_test.go:* + - id: smoke/forwarders_ocr2_test.go:* path: integration-tests/smoke/forwarders_ocr2_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/forwarders_ocr2_test.go -timeout 30m -count=1 -test.parallel=2 -json pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated - - id: integration-tests/smoke/ocr2_test.go:* + - id: smoke/ocr2_test.go:* path: integration-tests/smoke/ocr2_test.go test_env_type: docker runs_on: ubuntu22.04-16cores-64GB - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/ocr2_test.go -timeout 30m -count=1 -test.parallel=6 -json pyroscope_env: ci-smoke-ocr2-evm-simulated - - - id: integration-tests/smoke/ocr2_test.go:*-plugins + test_env_vars: + E2E_TEST_CHAINLINK_VERSION: '{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}' # This is the chainlink version that has the plugins + + - id: smoke/ocr2_test.go:*-plugins path: integration-tests/smoke/ocr2_test.go test_env_type: docker runs_on: ubuntu22.04-16cores-64GB - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/ocr2_test.go -timeout 30m -count=1 -test.parallel=6 -json pyroscope_env: ci-smoke-ocr2-plugins-evm-simulated - test_inputs: - # chainlink_version: '{{ env.GITHUB_SHA_PLUGINS }}' # This is the chainlink version that has the plugins - chainlink_version: develop-plugins + test_env_vars: + E2E_TEST_CHAINLINK_VERSION: '{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}' # This is the chainlink version that has the plugins + ENABLE_OTEL_TRACES: true + + - id: chaos/ocr_chaos_test.go + path: integration-tests/chaos/ocr_chaos_test.go + test_env_type: k8s-remote-runner + runs_on: ubuntu-latest + triggers: + - Automation On Demand Tests + - E2E Chaos Tests + test_cmd: cd integration-tests/chaos && DETACH_RUNNER=false go test -test.run "^TestOCRChaos$" -v -test.parallel=10 -timeout 60m -count=1 -json + test_env_vars: + TEST_SUITE: chaos # END: OCR tests # START: Automation tests - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_0|TestAutomationBasic/registry_2_1_conditional|TestAutomationBasic/registry_2_1_logtrigger$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_0|TestAutomationBasic/registry_2_1_conditional|TestAutomationBasic/registry_2_1_logtrigger$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_0|TestAutomationBasic/registry_2_1_conditional|TestAutomationBasic/registry_2_1_logtrigger$" -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_1_with_mercury_v02|TestAutomationBasic/registry_2_1_with_mercury_v03|TestAutomationBasic/registry_2_1_with_logtrigger_and_mercury_v02$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_1_with_mercury_v02|TestAutomationBasic/registry_2_1_with_mercury_v03|TestAutomationBasic/registry_2_1_with_logtrigger_and_mercury_v02$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_1_with_mercury_v02|TestAutomationBasic/registry_2_1_with_mercury_v03|TestAutomationBasic/registry_2_1_with_logtrigger_and_mercury_v02$" -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_2_conditional|TestAutomationBasic/registry_2_2_logtrigger|TestAutomationBasic/registry_2_2_with_mercury_v02$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_2_conditional|TestAutomationBasic/registry_2_2_logtrigger|TestAutomationBasic/registry_2_2_with_mercury_v02$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_2_conditional|TestAutomationBasic/registry_2_2_logtrigger|TestAutomationBasic/registry_2_2_with_mercury_v02$" -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_2_with_mercury_v03|TestAutomationBasic/registry_2_2_with_logtrigger_and_mercury_v02$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_2_with_mercury_v03|TestAutomationBasic/registry_2_2_with_logtrigger_and_mercury_v02$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_2_with_mercury_v03|TestAutomationBasic/registry_2_2_with_logtrigger_and_mercury_v02$" -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_3_conditional_native|TestAutomationBasic/registry_2_3_conditional_link$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_3_conditional_native|TestAutomationBasic/registry_2_3_conditional_link$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests - test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_3_conditional_native|TestAutomationBasic/registry_2_3_conditional_link$" -test.parallel=3 -timeout 30m -count=1 -json + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_3_conditional_native|TestAutomationBasic/registry_2_3_conditional_link$" -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_3_logtrigger_native|TestAutomationBasic/registry_2_3_logtrigger_link$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_3_logtrigger_native|TestAutomationBasic/registry_2_3_logtrigger_link$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_3_logtrigger_native|TestAutomationBasic/registry_2_3_logtrigger_link$" -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationBasic/registry_2_3_with_mercury_v03_link|TestAutomationBasic/registry_2_3_with_logtrigger_and_mercury_v02_link$ + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_3_with_mercury_v03_link|TestAutomationBasic/registry_2_3_with_logtrigger_and_mercury_v02_link$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_3_with_mercury_v03_link|TestAutomationBasic/registry_2_3_with_logtrigger_and_mercury_v02_link$" -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestSetUpkeepTriggerConfig$ + - id: smoke/automation_test.go:^TestSetUpkeepTriggerConfig$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestSetUpkeepTriggerConfig$ -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationAddFunds$ + - id: smoke/automation_test.go:^TestAutomationAddFunds$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationAddFunds$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationPauseUnPause$ + - id: smoke/automation_test.go:^TestAutomationPauseUnPause$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationPauseUnPause$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationRegisterUpkeep$ + - id: smoke/automation_test.go:^TestAutomationRegisterUpkeep$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationRegisterUpkeep$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationPauseRegistry$ + - id: smoke/automation_test.go:^TestAutomationPauseRegistry$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationPauseRegistry$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationKeeperNodesDown$ + - id: smoke/automation_test.go:^TestAutomationKeeperNodesDown$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationKeeperNodesDown$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationPerformSimulation$ + - id: smoke/automation_test.go:^TestAutomationPerformSimulation$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationPerformSimulation$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestAutomationCheckPerformGasLimit$ + - id: smoke/automation_test.go:^TestAutomationCheckPerformGasLimit$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationCheckPerformGasLimit$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestUpdateCheckData$ + - id: smoke/automation_test.go:^TestUpdateCheckData$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestUpdateCheckData$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/automation_test.go:^TestSetOffchainConfigWithMaxGasPrice$ + - id: smoke/automation_test.go:^TestSetOffchainConfigWithMaxGasPrice$ path: integration-tests/smoke/automation_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestSetOffchainConfigWithMaxGasPrice$ -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-automation-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperBasicSmoke$ + - id: smoke/keeper_test.go:^TestKeeperBasicSmoke$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperBasicSmoke$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperBlockCountPerTurn$ + - id: smoke/keeper_test.go:^TestKeeperBlockCountPerTurn$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperBlockCountPerTurn$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperSimulation$ + - id: smoke/keeper_test.go:^TestKeeperSimulation$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperSimulation$ -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperCheckPerformGasLimit$ + - id: smoke/keeper_test.go:^TestKeeperCheckPerformGasLimit$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests - test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperCheckPerformGasLimit$ -test.parallel=3 -timeout 30m -count=1 -json + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperCheckPerformGasLimit$ -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperRegisterUpkeep$ + - id: smoke/keeper_test.go:^TestKeeperRegisterUpkeep$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperRegisterUpkeep$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperAddFunds$ + - id: smoke/keeper_test.go:^TestKeeperAddFunds$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperAddFunds$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperRemove$ + - id: smoke/keeper_test.go:^TestKeeperRemove$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperRemove$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperPauseRegistry$ + - id: smoke/keeper_test.go:^TestKeeperPauseRegistry$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperPauseRegistry$ -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperMigrateRegistry$ + - id: smoke/keeper_test.go:^TestKeeperMigrateRegistry$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperMigrateRegistry$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperNodeDown$ + - id: smoke/keeper_test.go:^TestKeeperNodeDown$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperNodeDown$ -test.parallel=3 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperPauseUnPauseUpkeep$ + - id: smoke/keeper_test.go:^TestKeeperPauseUnPauseUpkeep$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperPauseUnPauseUpkeep$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperUpdateCheckData$ + - id: smoke/keeper_test.go:^TestKeeperUpdateCheckData$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperUpdateCheckData$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/smoke/keeper_test.go:^TestKeeperJobReplacement$ + - id: smoke/keeper_test.go:^TestKeeperJobReplacement$ path: integration-tests/smoke/keeper_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperJobReplacement$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-keeper-evm-simulated - - id: integration-tests/load/automationv2_1/automationv2_1_test.go:TestLogTrigger + - id: load/automationv2_1/automationv2_1_test.go:TestLogTrigger path: integration-tests/load/automationv2_1/automationv2_1_test.go runs_on: ubuntu-latest test_env_type: k8s-remote-runner test_cmd: cd integration-tests/load/automationv2_1 && go test -test.run TestLogTrigger -test.parallel=1 -timeout 60m -count=1 -json remote_runner_memory: 4Gi - test_config_override_required: true test_secrets_required: true - test_inputs: - test_suite: automationv2_1 - workflows: - - Automation Load Test + test_env_vars: + TEST_LOG_LEVEL: info + TEST_SUITE: automationv2_1 pyroscope_env: automation-load-test - - id: integration-tests/smoke/automation_upgrade_test.go:^TestAutomationNodeUpgrade/registry_2_0 + - id: smoke/automation_upgrade_test.go:^TestAutomationNodeUpgrade/registry_2_0 path: integration-tests/smoke/automation_upgrade_test.go test_env_type: docker runs_on: ubuntu22.04-8cores-32GB - workflows: - - Run Automation Product Nightly E2E Tests + triggers: + - Automation Nightly Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationNodeUpgrade/registry_2_0 -test.parallel=1 -timeout 60m -count=1 -json - test_inputs: - chainlink_image: public.ecr.aws/chainlink/chainlink - chainlink_version: latest - chainlink_upgrade_image: '{{ env.QA_CHAINLINK_IMAGE }}' - chainlink_upgrade_version: develop + test_env_vars: + E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + E2E_TEST_CHAINLINK_VERSION: latest + E2E_TEST_CHAINLINK_UPGRADE_IMAGE: '{{ env.QA_CHAINLINK_IMAGE }}' + E2E_TEST_CHAINLINK_UPGRADE_VERSION: '{{ env.DEFAULT_CHAINLINK_UPGRADE_VERSION }}' pyroscope_env: ci-smoke-automation-upgrade-tests - - id: integration-tests/smoke/automation_upgrade_test.go:^TestAutomationNodeUpgrade/registry_2_1 + - id: smoke/automation_upgrade_test.go:^TestAutomationNodeUpgrade/registry_2_1 path: integration-tests/smoke/automation_upgrade_test.go test_env_type: docker runs_on: ubuntu22.04-8cores-32GB - workflows: - - Run Automation Product Nightly E2E Tests + triggers: + - Automation Nightly Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationNodeUpgrade/registry_2_1 -test.parallel=5 -timeout 60m -count=1 -json - test_inputs: - chainlink_image: public.ecr.aws/chainlink/chainlink - chainlink_version: latest - chainlink_upgrade_image: '{{ env.QA_CHAINLINK_IMAGE }}' - chainlink_upgrade_version: develop + test_env_vars: + E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + E2E_TEST_CHAINLINK_VERSION: latest + E2E_TEST_CHAINLINK_UPGRADE_IMAGE: '{{ env.QA_CHAINLINK_IMAGE }}' + E2E_TEST_CHAINLINK_UPGRADE_VERSION: '{{ env.DEFAULT_CHAINLINK_UPGRADE_VERSION }}' pyroscope_env: ci-smoke-automation-upgrade-tests - - id: integration-tests/smoke/automation_upgrade_test.go:^TestAutomationNodeUpgrade/registry_2_2 + - id: smoke/automation_upgrade_test.go:^TestAutomationNodeUpgrade/registry_2_2 path: integration-tests/smoke/automation_upgrade_test.go test_env_type: docker runs_on: ubuntu22.04-8cores-32GB - workflows: - - Run Automation Product Nightly E2E Tests + triggers: + - Automation Nightly Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationNodeUpgrade/registry_2_2 -test.parallel=5 -timeout 60m -count=1 -json - test_inputs: - chainlink_image: public.ecr.aws/chainlink/chainlink - chainlink_version: latest - chainlink_upgrade_image: '{{ env.QA_CHAINLINK_IMAGE }}' - chainlink_upgrade_version: develop + test_env_vars: + E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + E2E_TEST_CHAINLINK_VERSION: latest + E2E_TEST_CHAINLINK_UPGRADE_IMAGE: '{{ env.QA_CHAINLINK_IMAGE }}' + E2E_TEST_CHAINLINK_UPGRADE_VERSION: '{{ env.DEFAULT_CHAINLINK_UPGRADE_VERSION }}' pyroscope_env: ci-smoke-automation-upgrade-tests - - id: integration-tests/reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_0 + - id: reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_0 path: integration-tests/reorg/automation_reorg_test.go runs_on: ubuntu-latest test_env_type: docker - test_inputs: - test_suite: reorg - workflows: - - Run Automation On Demand Tests (TEST WORKFLOW) + test_env_vars: + TEST_SUITE: reorg + triggers: + - Automation On Demand Tests test_cmd: cd integration-tests/reorg && DETACH_RUNNER=false go test -v -test.run ^TestAutomationReorg/registry_2_0 -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-automation-on-demand-reorg - - id: integration-tests/reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_1 + - id: reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_1 path: integration-tests/reorg/automation_reorg_test.go runs_on: ubuntu-latest test_env_type: docker - test_inputs: - test_suite: reorg - workflows: - - Run Automation On Demand Tests (TEST WORKFLOW) + test_env_vars: + TEST_SUITE: reorg + triggers: + - Automation On Demand Tests test_cmd: cd integration-tests/reorg && DETACH_RUNNER=false go test -v -test.run ^TestAutomationReorg/registry_2_1 -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-automation-on-demand-reorg - - id: integration-tests/reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_2 + - id: reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_2 path: integration-tests/reorg/automation_reorg_test.go runs_on: ubuntu-latest test_env_type: docker - test_inputs: - test_suite: reorg - workflows: - - Run Automation On Demand Tests (TEST WORKFLOW) + test_env_vars: + TEST_SUITE: reorg + triggers: + - Automation On Demand Tests test_cmd: cd integration-tests/reorg && DETACH_RUNNER=false go test -v -test.run ^TestAutomationReorg/registry_2_2 -test.parallel=2 -timeout 30m -count=1 -json pyroscope_env: ci-automation-on-demand-reorg - - id: integration-tests/chaos/automation_chaos_test.go + - id: reorg/automation_reorg_test.go^TestAutomationReorg/registry_2_3 + path: integration-tests/reorg/automation_reorg_test.go + runs_on: ubuntu-latest + test_env_type: docker + test_env_vars: + TEST_SUITE: reorg + triggers: + - Automation On Demand Tests + test_cmd: cd integration-tests/reorg && DETACH_RUNNER=false go test -v -test.run ^TestAutomationReorg/registry_2_3 -test.parallel=2 -timeout 30m -count=1 -json + pyroscope_env: ci-automation-on-demand-reorg + + - id: chaos/automation_chaos_test.go path: integration-tests/chaos/automation_chaos_test.go test_env_type: k8s-remote-runner runs_on: ubuntu-latest - workflows: - - Run Automation On Demand Tests (TEST WORKFLOW) + triggers: + - Automation On Demand Tests + - E2E Chaos Tests test_cmd: cd integration-tests/chaos && DETACH_RUNNER=false go test -v -test.run ^TestAutomationChaos$ -test.parallel=20 -timeout 60m -count=1 -json pyroscope_env: ci-automation-on-demand-chaos - test_inputs: - test_suite: chaos + test_env_vars: + TEST_SUITE: chaos + + - id: benchmark/automation_test.go:TestAutomationBenchmark + path: integration-tests/benchmark/automation_test.go + test_env_type: k8s-remote-runner + remote_runner_memory: 4Gi + runs_on: ubuntu-latest + # triggers: + # - Nightly E2E Tests + test_cmd: cd integration-tests/benchmark && go test -v -test.run ^TestAutomationBenchmark$ -test.parallel=1 -timeout 30m -count=1 -json + pyroscope_env: ci-benchmark-automation-nightly + test_env_vars: + TEST_LOG_LEVEL: info + TEST_SUITE: benchmark + TEST_TYPE: benchmark - - id: integration-tests/benchmark/keeper_test.go:^TestAutomationBenchmark$ - path: integration-tests/benchmark/keeper_test.go + - id: soak/automation_test.go:TestAutomationBenchmark + path: integration-tests/benchmark/automation_test.go test_env_type: k8s-remote-runner remote_runner_memory: 4Gi runs_on: ubuntu-latest - # workflows: - # - Run Nightly E2E Tests + # triggers: + # - Nightly E2E Tests test_cmd: cd integration-tests/benchmark && go test -v -test.run ^TestAutomationBenchmark$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-benchmark-automation-nightly - test_inputs: - test_suite: benchmark + test_env_vars: + TEST_LOG_LEVEL: info + TEST_SUITE: benchmark + TEST_TYPE: soak # END: Automation tests # START: VRF tests - - id: integration-tests/smoke/vrfv2_test.go:TestVRFv2Basic + - id: smoke/vrfv2_test.go:TestVRFv2Basic path: integration-tests/smoke/vrfv2_test.go runs_on: ubuntu22.04-8cores-32GB test_env_type: docker test_cmd: cd integration-tests/smoke && go test -v -test.run TestVRFv2Basic -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true test_secrets_required: true - workflows: + triggers: - On Demand VRFV2 Smoke Test (Ethereum clients) - - id: integration-tests/load/vrfv2plus/vrfv2plus_test.go:^TestVRFV2PlusPerformance$Smoke + - id: load/vrfv2plus/vrfv2plus_test.go:^TestVRFV2PlusPerformance$Smoke path: integration-tests/load/vrfv2plus/vrfv2plus_test.go runs_on: ubuntu22.04-8cores-32GB test_env_type: docker test_cmd: cd integration-tests/load/vrfv2plus && go test -v -test.run ^TestVRFV2PlusPerformance$ -test.parallel=1 -timeout 24h -count=1 -json test_config_override_required: true test_secrets_required: true - test_inputs: - test_type: Smoke - workflows: + test_env_vars: + TEST_TYPE: Smoke + triggers: - On Demand VRFV2 Plus Performance Test - - id: integration-tests/load/vrfv2plus/vrfv2plus_test.go:^TestVRFV2PlusBHSPerformance$Smoke + - id: load/vrfv2plus/vrfv2plus_test.go:^TestVRFV2PlusBHSPerformance$Smoke path: integration-tests/load/vrfv2plus/vrfv2plus_test.go runs_on: ubuntu22.04-8cores-32GB test_env_type: docker test_cmd: cd integration-tests/load/vrfv2plus && go test -v -test.run ^TestVRFV2PlusBHSPerformance$ -test.parallel=1 -timeout 24h -count=1 -json test_config_override_required: true test_secrets_required: true - test_inputs: - test_type: Smoke - workflows: + test_env_vars: + TEST_TYPE: Smoke + triggers: - On Demand VRFV2 Plus Performance Test - - id: integration-tests/load/vrfv2/vrfv2_test.go:^TestVRFV2Performance$Smoke + - id: load/vrfv2/vrfv2_test.go:^TestVRFV2Performance$Smoke path: integration-tests/load/vrfv2/vrfv2_test.go runs_on: ubuntu22.04-8cores-32GB test_env_type: docker test_cmd: cd integration-tests/load/vrfv2 && go test -v -test.run ^TestVRFV2Performance$ -test.parallel=1 -timeout 24h -count=1 -json test_config_override_required: true test_secrets_required: true - test_inputs: - test_type: Smoke - workflows: + test_env_vars: + TEST_TYPE: Smoke + triggers: - On Demand VRFV2 Performance Test - - id: integration-tests/load/vrfv2/vrfv2_test.go:^TestVRFV2PlusBHSPerformance$Smoke + - id: load/vrfv2/vrfv2_test.go:^TestVRFV2PlusBHSPerformance$Smoke path: integration-tests/load/vrfv2/vrfv2_test.go runs_on: ubuntu22.04-8cores-32GB test_env_type: docker test_cmd: cd integration-tests/load/vrfv2 && go test -v -test.run ^TestVRFV2PlusBHSPerformance$ -test.parallel=1 -timeout 24h -count=1 -json test_config_override_required: true test_secrets_required: true - test_inputs: - test_type: Smoke - workflows: + test_env_vars: + TEST_TYPE: Smoke + triggers: - On Demand VRFV2 Performance Test - - id: integration-tests/smoke/vrfv2plus_test.go:^TestVRFv2Plus$/^Link_Billing$ - path: integration-tests/smoke/vrfv2plus_test.go - runs_on: ubuntu22.04-8cores-32GB - test_env_type: docker - test_cmd: cd integration-tests && go test -v -test.run ^TestVRFv2Plus$/^Link_Billing$ smoke/vrfv2plus_test.go -test.parallel=1 -timeout 30m -count=1 -json - test_config_override_required: true - test_secrets_required: true - workflows: - - On Demand VRFV2Plus Smoke Test (Ethereum clients) - - - id: integration-tests/smoke/vrf_test.go:* + - id: smoke/vrf_test.go:* path: integration-tests/smoke/vrf_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/vrf_test.go -timeout 30m -count=1 -test.parallel=2 -json pyroscope_env: ci-smoke-vrf-evm-simulated - - id: integration-tests/smoke/vrfv2_test.go:* + - id: smoke/vrfv2_test.go:* path: integration-tests/smoke/vrfv2_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/vrfv2_test.go -timeout 30m -count=1 -test.parallel=6 -json pyroscope_env: ci-smoke-vrf2-evm-simulated - - id: integration-tests/smoke/vrfv2plus_test.go:* + - id: smoke/vrfv2plus_test.go:* path: integration-tests/smoke/vrfv2plus_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/vrfv2plus_test.go -timeout 30m -count=1 -test.parallel=9 -json pyroscope_env: ci-smoke-vrf2plus-evm-simulated + # VRFv2Plus tests on any live testnet (test_config_override_path required) + # Tests have to run in sequence because of a single private key used + - id: TestVRFv2Plus_LiveTestnets + path: integration-tests/smoke/vrfv2plus_test.go + runs_on: ubuntu-latest + test_env_type: docker + test_cmd: cd integration-tests/smoke && go test -v -test.run "TestVRFv2Plus$/(Link_Billing|Native_Billing|Direct_Funding)|TestVRFV2PlusWithBHS" -test.parallel=1 -timeout 2h -count=1 -json + + # VRFv2Plus release tests on Sepolia testnet + - id: TestVRFv2Plus_Release_Sepolia + path: integration-tests/smoke/vrfv2plus_test.go + runs_on: ubuntu-latest + test_env_type: docker + test_cmd: cd integration-tests/smoke && go test -v -test.run "TestVRFv2Plus$/(Link_Billing|Native_Billing|Direct_Funding)|TestVRFV2PlusWithBHS" -test.parallel=1 -timeout 2h -count=1 -json + test_config_override_path: integration-tests/testconfig/vrfv2plus/overrides/new_env/sepolia_new_env_test_config.toml + triggers: + - VRF E2E Release Tests + # END: VRF tests # START: LogPoller tests - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerFewFiltersFixedDepth$ + - id: smoke/log_poller_test.go:^TestLogPollerFewFiltersFixedDepth$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerFewFiltersFixedDepth$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerFewFiltersFinalityTag$ + - id: smoke/log_poller_test.go:^TestLogPollerFewFiltersFinalityTag$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerFewFiltersFinalityTag$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerWithChaosFixedDepth$ + - id: smoke/log_poller_test.go:^TestLogPollerWithChaosFixedDepth$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerWithChaosFixedDepth$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerWithChaosFinalityTag$ + - id: smoke/log_poller_test.go:^TestLogPollerWithChaosFinalityTag$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerWithChaosFinalityTag$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerWithChaosPostgresFinalityTag$ + - id: smoke/log_poller_test.go:^TestLogPollerWithChaosPostgresFinalityTag$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerWithChaosPostgresFinalityTag$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerWithChaosPostgresFixedDepth$ + - id: smoke/log_poller_test.go:^TestLogPollerWithChaosPostgresFixedDepth$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerWithChaosPostgresFixedDepth$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerReplayFixedDepth$ + - id: smoke/log_poller_test.go:^TestLogPollerReplayFixedDepth$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerReplayFixedDepth$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated - - id: integration-tests/smoke/log_poller_test.go:^TestLogPollerReplayFinalityTag$ + - id: smoke/log_poller_test.go:^TestLogPollerReplayFinalityTag$ path: integration-tests/smoke/log_poller_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestLogPollerReplayFinalityTag$ -test.parallel=1 -timeout 30m -count=1 -json pyroscope_env: ci-smoke-log_poller-evm-simulated @@ -791,58 +861,321 @@ runner-test-matrix: # START: Other tests - - id: integration-tests/smoke/runlog_test.go:* + - id: smoke/runlog_test.go:* path: integration-tests/smoke/runlog_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/runlog_test.go -timeout 30m -count=1 -json + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/ && go test smoke/runlog_test.go -timeout 30m -test.parallel=2 -count=1 -json pyroscope_env: ci-smoke-runlog-evm-simulated - - id: integration-tests/smoke/cron_test.go:* + - id: smoke/cron_test.go:* path: integration-tests/smoke/cron_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/cron_test.go -timeout 30m -count=1 -json pyroscope_env: ci-smoke-cron-evm-simulated - - id: integration-tests/smoke/flux_test.go:* + - id: smoke/flux_test.go:* path: integration-tests/smoke/flux_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/flux_test.go -timeout 30m -count=1 -json pyroscope_env: ci-smoke-flux-evm-simulated - - id: integration-tests/smoke/reorg_above_finality_test.go:* + - id: smoke/reorg_above_finality_test.go:* path: integration-tests/smoke/reorg_above_finality_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/reorg_above_finality_test.go -timeout 30m -count=1 -json pyroscope_env: ci-smoke-reorg-above-finality-evm-simulated - - id: integration-tests/migration/upgrade_version_test.go:* + - id: migration/upgrade_version_test.go:* path: integration-tests/migration/upgrade_version_test.go test_env_type: docker runs_on: ubuntu-latest - workflows: - - Run PR E2E Tests - - Run Nightly E2E Tests + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests test_cmd: cd integration-tests/migration && go test upgrade_version_test.go -timeout 30m -count=1 -test.parallel=2 -json - test_inputs: - chainlink_image: public.ecr.aws/chainlink/chainlink - chainlink_version: '{{ env.LATEST_CHAINLINK_RELEASE_VERSION }}' - chainlink_upgrade_image: '{{ env.QA_CHAINLINK_IMAGE }}' - chainlink_upgrade_version: develop + test_env_vars: + E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + E2E_TEST_CHAINLINK_VERSION: '{{ env.LATEST_CHAINLINK_RELEASE_VERSION }}' + E2E_TEST_CHAINLINK_UPGRADE_IMAGE: '{{ env.QA_CHAINLINK_IMAGE }}' + E2E_TEST_CHAINLINK_UPGRADE_VERSION: '{{ env.DEFAULT_CHAINLINK_VERSION }}' + + - id: smoke/job_distributor_test.go:* + path: integration-tests/smoke/job_distributor_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/ && go test smoke/job_distributor_test.go -timeout 30m -count=1 -json + pyroscope_env: ci-smoke-jd-evm-simulated # END: Other tests + + # START: CCIPv1.6 tests + + - id: smoke/ccip_test.go:* + path: integration-tests/smoke/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Merge Queue E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/ && go test smoke/ccip_test.go -timeout 12m -test.parallel=1 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + E2E_JD_VERSION: 0.4.0 + + # END: CCIPv1.6 tests + + # START: CCIP tests + + - id: ccip-smoke + 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 + + - id: ccip-smoke-1.4-pools + 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 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml + + - id: ccip-smoke-usdc + 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 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/usdc_mock_deployment.toml + + - id: ccip-smoke-db-compatibility + 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 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/db-compatibility.toml + + - id: ccip-smoke-leader-lane + path: integration-tests/ccip-tests/smoke/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + # Leader lane test is flakey in Core repo - Need to fix CCIP-3074 to enable it. + triggers: + # - PR 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 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/leader-lane.toml + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPTokenPoolRateLimits$ + 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 ^TestSmokeCCIPTokenPoolRateLimits$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPMulticall$ + 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 ^TestSmokeCCIPMulticall$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas$ + 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 ^TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPOnRampLimits$ + 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 ^TestSmokeCCIPOnRampLimits$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPOffRampCapacityLimit$ + path: integration-tests/ccip-tests/smoke/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - Nightly E2E Tests + test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPOffRampCapacityLimit$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPOffRampAggRateLimit$ + path: integration-tests/ccip-tests/smoke/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - Nightly E2E Tests + test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPOffRampAggRateLimit$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPReorgBelowFinality$ + 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 ^TestSmokeCCIPReorgBelowFinality$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPReorgAboveFinalityAtDestination$ + 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 ^TestSmokeCCIPReorgAboveFinalityAtDestination$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml + + - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPReorgAboveFinalityAtSource$ + 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 ^TestSmokeCCIPReorgAboveFinalityAtSource$ -timeout 30m -count=1 -test.parallel=1 -json + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml + + - id: integration-tests/ccip-tests/load/ccip_test.go:TestLoadCCIPStableRPS + path: integration-tests/ccip-tests/load/ccip_test.go + test_env_type: k8s-remote-runner + runs_on: ubuntu-latest + test_cmd: cd integration-tests/ccip-tests/load && DETACH_RUNNER=false go test -test.run ^TestLoadCCIPStableRPS$ -timeout 70m -count=1 -test.parallel=1 -json + test_env_vars: + TEST_SUITE: ccip-load + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" + triggers: + - E2E CCIP Load Tests + test_artifacts_on_failure: + - ./integration-tests/load/logs/payload_ccip.json + + # Enable when CCIP-2277 is resolved + # + # - id: integration-tests/ccip-tests/load/ccip_test.go:TestLoadCCIPStableRPSAfterARMCurseAndUncurse + # path: integration-tests/ccip-tests/load/ccip_test.go + # test_env_type: k8s-remote-runner + # runs_on: ubuntu-latest + # test_cmd: cd integration-tests/ccip-tests/load && DETACH_RUNNER=false go test -test.run $TestLoadCCIPStableRPSAfterARMCurseAndUncurse$ -timeout 70m -count=1 -test.parallel=1 -json + # test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/load-with-arm-curse-uncurse.toml + # test_env_vars: + # E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" + # triggers: + # - E2E CCIP Load Tests + # test_artifacts_on_failure: + # - ./integration-tests/load/logs/payload_ccip.json + + - id: ccip-tests/chaos/ccip_test.go + path: integration-tests/ccip-tests/chaos/ccip_test.go + test_env_type: k8s-remote-runner + runs_on: ubuntu-latest + triggers: + - E2E CCIP Chaos Tests + test_cmd: cd integration-tests/ccip-tests/chaos && DETACH_RUNNER=false go test ccip_test.go -v -test.parallel=11 -timeout 60m -count=1 -json + test_env_vars: + TEST_SUITE: chaos + TEST_TRIGGERED_BY: ccip-cron-chaos-eth + TEST_LOG_LEVEL: debug + + - id: ccip-tests/load/ccip_test.go:^TestLoadCCIPStableWithPodChaosDiffCommitAndExec + path: integration-tests/ccip-tests/load/ccip_test.go + test_env_type: k8s-remote-runner + runs_on: ubuntu-latest + triggers: + # Disabled until CCIP-2555 is resolved + # - E2E CCIP Chaos Tests + test_cmd: cd integration-tests/ccip-tests/load && DETACH_RUNNER=false go test -run '^TestLoadCCIPStableWithPodChaosDiffCommitAndExec' -v -test.parallel=4 -timeout 120m -count=1 -json + test_env_vars: + TEST_SUITE: chaos + TEST_TRIGGERED_BY: ccip-cron-chaos-eth + TEST_LOG_LEVEL: debug + E2E_TEST_GRAFANA_DASHBOARD_URL: /d/6vjVx-1V8/ccip-long-running-tests + + # END: CCIP tests \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 291bfe4ce88..7e3ec812438 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,36 +1,16 @@ - -### Requires Dependencies - -### Resolves Dependencies - diff --git a/.github/scripts/functions.sh b/.github/scripts/functions.sh deleted file mode 100644 index 53b53392269..00000000000 --- a/.github/scripts/functions.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -# Function to convert a comma-separated list into a TOML array format. -# Usage: convert_to_toml_array "elem1,elem2,elem3" -# Effect: "a,b,c" -> ["a","b","c"] -function convert_to_toml_array() { - local IFS=',' - local input_array=($1) - local toml_array_format="[" - - for element in "${input_array[@]}"; do - toml_array_format+="\"$element\"," - done - - toml_array_format="${toml_array_format%,}]" - echo "$toml_array_format" -} \ No newline at end of file diff --git a/.github/scripts/jira/enforce-jira-issue.ts b/.github/scripts/jira/enforce-jira-issue.ts deleted file mode 100644 index e0054b25d0e..00000000000 --- a/.github/scripts/jira/enforce-jira-issue.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as core from "@actions/core"; -import jira from "jira.js"; -import { createJiraClient, parseIssueNumberFrom } from "./lib"; - -async function doesIssueExist( - client: jira.Version3Client, - issueNumber: string, - dryRun: boolean -) { - const payload = { - issueIdOrKey: issueNumber, - }; - - if (dryRun) { - core.info("Dry run enabled, skipping JIRA issue enforcement"); - return true; - } - - try { - /** - * The issue is identified by its ID or key, however, if the identifier doesn't match an issue, a case-insensitive search and check for moved issues is performed. - * If a matching issue is found its details are returned, a 302 or other redirect is not returned. The issue key returned in the response is the key of the issue found. - */ - const issue = await client.issues.getIssue(payload); - core.debug( - `JIRA issue id:${issue.id} key: ${issue.key} found while querying for ${issueNumber}` - ); - if (issue.key !== issueNumber) { - core.error( - `JIRA issue key ${issueNumber} not found, but found issue key ${issue.key} instead. This can happen if the identifier doesn't match an issue, in which case a case-insensitive search and check for moved issues is performed. Make sure the issue key is correct.` - ); - return false; - } - - return true; - } catch (e) { - core.debug(e as any); - return false; - } -} - -async function main() { - const prTitle = process.env.PR_TITLE; - const commitMessage = process.env.COMMIT_MESSAGE; - const branchName = process.env.BRANCH_NAME; - const dryRun = !!process.env.DRY_RUN; - const client = createJiraClient(); - - // Checks for the Jira issue number and exit if it can't find it - const issueNumber = parseIssueNumberFrom(prTitle, commitMessage, branchName); - if (!issueNumber) { - const msg = - "No JIRA issue number found in PR title, commit message, or branch name. This pull request must be associated with a JIRA issue."; - - core.setFailed(msg); - return; - } - - const exists = await doesIssueExist(client, issueNumber, dryRun); - if (!exists) { - core.setFailed(`JIRA issue ${issueNumber} not found, this pull request must be associated with a JIRA issue.`); - return; - } -} - -async function run() { - try { - await main(); - } catch (error) { - if (error instanceof Error) { - return core.setFailed(error.message); - } - core.setFailed(error as any); - } -} - -run(); diff --git a/.github/scripts/jira/lib.test.ts b/.github/scripts/jira/lib.test.ts deleted file mode 100644 index 9c751e84088..00000000000 --- a/.github/scripts/jira/lib.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { expect, describe, it } from "vitest"; -import { parseIssueNumberFrom, tagsToLabels } from "./lib"; - -describe("parseIssueNumberFrom", () => { - it("should return the first JIRA issue number found", () => { - let r = parseIssueNumberFrom("CORE-123", "CORE-456", "CORE-789"); - expect(r).to.equal("CORE-123"); - - r = parseIssueNumberFrom( - "2f3df5gf", - "chore/test-RE-78-branch", - "RE-78 Create new test branches" - ); - expect(r).to.equal("RE-78"); - - // handle lower case - r = parseIssueNumberFrom("core-123", "CORE-456", "CORE-789"); - expect(r).to.equal("CORE-123"); - }); - - it("works with multiline commit bodies", () => { - const r = parseIssueNumberFrom( - `This is a multiline commit body - -CORE-1011`, - "CORE-456", - "CORE-789" - ); - expect(r).to.equal("CORE-1011"); - }); - - it("should return undefined if no JIRA issue number is found", () => { - const result = parseIssueNumberFrom("No issue number"); - expect(result).to.be.undefined; - }); -}); - -describe("tagsToLabels", () => { - it("should convert an array of tags to an array of labels", () => { - const tags = ["v1.0.0", "v1.1.0"]; - const result = tagsToLabels(tags); - expect(result).to.deep.equal([ - { add: "core-release/1.0.0" }, - { add: "core-release/1.1.0" }, - ]); - }); -}); diff --git a/.github/scripts/jira/lib.ts b/.github/scripts/jira/lib.ts deleted file mode 100644 index 72f1d57966c..00000000000 --- a/.github/scripts/jira/lib.ts +++ /dev/null @@ -1,63 +0,0 @@ - -import * as core from '@actions/core' -import * as jira from 'jira.js' - -/** - * Given a list of strings, this function will return the first JIRA issue number it finds. - * - * @example parseIssueNumberFrom("CORE-123", "CORE-456", "CORE-789") => "CORE-123" - * @example parseIssueNumberFrom("2f3df5gf", "chore/test-RE-78-branch", "RE-78 Create new test branches") => "RE-78" - */ -export function parseIssueNumberFrom( - ...inputs: (string | undefined)[] -): string | undefined { - function parse(str?: string) { - const jiraIssueRegex = /[A-Z]{2,}-\d+/; - - return str?.toUpperCase().match(jiraIssueRegex)?.[0]; - } - - core.debug(`Parsing issue number from: ${inputs.join(", ")}`); - const parsed: string[] = inputs.map(parse).filter((x) => x !== undefined); - core.debug(`Found issue number: ${parsed[0]}`); - - return parsed[0]; -} - -/** - * Converts an array of tags to an array of labels. - * - * A label is a string that is formatted as `core-release/{tag}`, with the leading `v` removed from the tag. - * - * @example tagsToLabels(["v1.0.0", "v1.1.0"]) => [{ add: "core-release/1.0.0" }, { add: "core-release/1.1.0" }] - */ -export function tagsToLabels(tags: string[]) { - const labelPrefix = "core-release"; - - return tags.map((t) => ({ - add: `${labelPrefix}/${t.substring(1)}`, - })); -} - -export function createJiraClient() { - const jiraHost = process.env.JIRA_HOST; - const jiraUserName = process.env.JIRA_USERNAME; - const jiraApiToken = process.env.JIRA_API_TOKEN; - - if (!jiraHost || !jiraUserName || !jiraApiToken) { - core.setFailed( - "Error: Missing required environment variables: JIRA_HOST and JIRA_USERNAME and JIRA_API_TOKEN." - ); - process.exit(1); - } - - return new jira.Version3Client({ - host: jiraHost, - authentication: { - basic: { - email: jiraUserName, - apiToken: jiraApiToken, - }, - }, - }); -} diff --git a/.github/scripts/jira/package.json b/.github/scripts/jira/package.json deleted file mode 100644 index 95bfbb1e486..00000000000 --- a/.github/scripts/jira/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "jira", - "version": "0.1.0", - "description": "Updates Jira issue with release information like the version and tags for a PR.", - "main": "update-jira-issue.js", - "type": "module", - "private": true, - "keywords": [], - "author": "", - "license": "MIT", - "engines": { - "node": ">=18", - "pnpm": ">=9" - }, - "scripts": { - "issue:update": "tsx update-jira-issue.ts", - "issue:enforce": "tsx enforce-jira-issue.ts", - "test": "vitest" - }, - "dependencies": { - "@actions/core": "^1.10.1", - "jira.js": "^4.0.1", - "tsx": "^4.16.2" - }, - "devDependencies": { - "@types/node": "^20.14.10", - "typescript": "^5.5.3", - "vitest": "^2.0.3" - } -} diff --git a/.github/scripts/jira/pnpm-lock.yaml b/.github/scripts/jira/pnpm-lock.yaml deleted file mode 100644 index 4deeef7f339..00000000000 --- a/.github/scripts/jira/pnpm-lock.yaml +++ /dev/null @@ -1,1111 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@actions/core': - specifier: ^1.10.1 - version: 1.10.1 - jira.js: - specifier: ^4.0.1 - version: 4.0.1 - tsx: - specifier: ^4.16.2 - version: 4.16.2 - devDependencies: - '@types/node': - specifier: ^20.14.10 - version: 20.14.10 - typescript: - specifier: ^5.5.3 - version: 5.5.3 - vitest: - specifier: ^2.0.3 - version: 2.0.3(@types/node@20.14.10) - -packages: - - '@actions/core@1.10.1': - resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} - - '@actions/http-client@2.2.1': - resolution: {integrity: sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==} - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@rollup/rollup-android-arm-eabi@4.18.1': - resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.18.1': - resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.18.1': - resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.18.1': - resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-linux-arm-gnueabihf@4.18.1': - resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.18.1': - resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.18.1': - resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.18.1': - resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': - resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.18.1': - resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.18.1': - resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.18.1': - resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.18.1': - resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.18.1': - resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.18.1': - resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.18.1': - resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==} - cpu: [x64] - os: [win32] - - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - - '@types/node@20.14.10': - resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} - - '@vitest/expect@2.0.3': - resolution: {integrity: sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==} - - '@vitest/pretty-format@2.0.3': - resolution: {integrity: sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==} - - '@vitest/runner@2.0.3': - resolution: {integrity: sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==} - - '@vitest/snapshot@2.0.3': - resolution: {integrity: sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==} - - '@vitest/spy@2.0.3': - resolution: {integrity: sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==} - - '@vitest/utils@2.0.3': - resolution: {integrity: sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==} - - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - axios@1.7.2: - resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - chai@5.1.1: - resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} - engines: {node: '>=12'} - - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - - debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - follow-redirects@1.15.6: - resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - get-tsconfig@4.7.5: - resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - jira.js@4.0.1: - resolution: {integrity: sha512-2zf8LozW9rgx5wgTdGSJMhUXDK1g8a/ngm1xDWnREX/h8kuBhNkMro4XELA2XRVvaNTbRMIK3PBgOvWFDddhIw==} - - loupe@3.1.1: - resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} - - magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - - pathval@2.0.0: - resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} - engines: {node: '>= 14.16'} - - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - - postcss@8.4.39: - resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} - engines: {node: ^10 || ^12 || >=14} - - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - - rollup@4.18.1: - resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - tinybench@2.8.0: - resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} - - tinypool@1.0.0: - resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@1.2.0: - resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} - engines: {node: '>=14.0.0'} - - tinyspy@3.0.0: - resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} - engines: {node: '>=14.0.0'} - - tslib@2.6.3: - resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - - tsx@4.16.2: - resolution: {integrity: sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==} - engines: {node: '>=18.0.0'} - hasBin: true - - tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - - typescript@5.5.3: - resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - undici@5.28.4: - resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} - engines: {node: '>=14.0'} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - vite-node@2.0.3: - resolution: {integrity: sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite@5.3.3: - resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - vitest@2.0.3: - resolution: {integrity: sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.0.3 - '@vitest/ui': 2.0.3 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - -snapshots: - - '@actions/core@1.10.1': - dependencies: - '@actions/http-client': 2.2.1 - uuid: 8.3.2 - - '@actions/http-client@2.2.1': - dependencies: - tunnel: 0.0.6 - undici: 5.28.4 - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-x64@0.21.5': - optional: true - - '@fastify/busboy@2.1.1': {} - - '@jridgewell/gen-mapping@0.3.5': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@rollup/rollup-android-arm-eabi@4.18.1': - optional: true - - '@rollup/rollup-android-arm64@4.18.1': - optional: true - - '@rollup/rollup-darwin-arm64@4.18.1': - optional: true - - '@rollup/rollup-darwin-x64@4.18.1': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.18.1': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.18.1': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.18.1': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.18.1': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.18.1': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.18.1': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.18.1': - optional: true - - '@rollup/rollup-linux-x64-musl@4.18.1': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.18.1': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.18.1': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.18.1': - optional: true - - '@types/estree@1.0.5': {} - - '@types/node@20.14.10': - dependencies: - undici-types: 5.26.5 - - '@vitest/expect@2.0.3': - dependencies: - '@vitest/spy': 2.0.3 - '@vitest/utils': 2.0.3 - chai: 5.1.1 - tinyrainbow: 1.2.0 - - '@vitest/pretty-format@2.0.3': - dependencies: - tinyrainbow: 1.2.0 - - '@vitest/runner@2.0.3': - dependencies: - '@vitest/utils': 2.0.3 - pathe: 1.1.2 - - '@vitest/snapshot@2.0.3': - dependencies: - '@vitest/pretty-format': 2.0.3 - magic-string: 0.30.10 - pathe: 1.1.2 - - '@vitest/spy@2.0.3': - dependencies: - tinyspy: 3.0.0 - - '@vitest/utils@2.0.3': - dependencies: - '@vitest/pretty-format': 2.0.3 - estree-walker: 3.0.3 - loupe: 3.1.1 - tinyrainbow: 1.2.0 - - assertion-error@2.0.1: {} - - asynckit@0.4.0: {} - - axios@1.7.2: - dependencies: - follow-redirects: 1.15.6 - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - cac@6.7.14: {} - - chai@5.1.1: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.1.1 - pathval: 2.0.0 - - check-error@2.1.1: {} - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - cross-spawn@7.0.3: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - debug@4.3.5: - dependencies: - ms: 2.1.2 - - deep-eql@5.0.2: {} - - delayed-stream@1.0.0: {} - - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.5 - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - follow-redirects@1.15.6: {} - - form-data@4.0.0: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - - fsevents@2.3.3: - optional: true - - get-func-name@2.0.2: {} - - get-stream@8.0.1: {} - - get-tsconfig@4.7.5: - dependencies: - resolve-pkg-maps: 1.0.0 - - human-signals@5.0.0: {} - - is-stream@3.0.0: {} - - isexe@2.0.0: {} - - jira.js@4.0.1: - dependencies: - axios: 1.7.2 - form-data: 4.0.0 - tslib: 2.6.3 - transitivePeerDependencies: - - debug - - loupe@3.1.1: - dependencies: - get-func-name: 2.0.2 - - magic-string@0.30.10: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - merge-stream@2.0.0: {} - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mimic-fn@4.0.0: {} - - ms@2.1.2: {} - - nanoid@3.3.7: {} - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - path-key@3.1.1: {} - - path-key@4.0.0: {} - - pathe@1.1.2: {} - - pathval@2.0.0: {} - - picocolors@1.0.1: {} - - postcss@8.4.39: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - - proxy-from-env@1.1.0: {} - - resolve-pkg-maps@1.0.0: {} - - rollup@4.18.1: - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.1 - '@rollup/rollup-android-arm64': 4.18.1 - '@rollup/rollup-darwin-arm64': 4.18.1 - '@rollup/rollup-darwin-x64': 4.18.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.1 - '@rollup/rollup-linux-arm-musleabihf': 4.18.1 - '@rollup/rollup-linux-arm64-gnu': 4.18.1 - '@rollup/rollup-linux-arm64-musl': 4.18.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1 - '@rollup/rollup-linux-riscv64-gnu': 4.18.1 - '@rollup/rollup-linux-s390x-gnu': 4.18.1 - '@rollup/rollup-linux-x64-gnu': 4.18.1 - '@rollup/rollup-linux-x64-musl': 4.18.1 - '@rollup/rollup-win32-arm64-msvc': 4.18.1 - '@rollup/rollup-win32-ia32-msvc': 4.18.1 - '@rollup/rollup-win32-x64-msvc': 4.18.1 - fsevents: 2.3.3 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - siginfo@2.0.0: {} - - signal-exit@4.1.0: {} - - source-map-js@1.2.0: {} - - stackback@0.0.2: {} - - std-env@3.7.0: {} - - strip-final-newline@3.0.0: {} - - tinybench@2.8.0: {} - - tinypool@1.0.0: {} - - tinyrainbow@1.2.0: {} - - tinyspy@3.0.0: {} - - tslib@2.6.3: {} - - tsx@4.16.2: - dependencies: - esbuild: 0.21.5 - get-tsconfig: 4.7.5 - optionalDependencies: - fsevents: 2.3.3 - - tunnel@0.0.6: {} - - typescript@5.5.3: {} - - undici-types@5.26.5: {} - - undici@5.28.4: - dependencies: - '@fastify/busboy': 2.1.1 - - uuid@8.3.2: {} - - vite-node@2.0.3(@types/node@20.14.10): - dependencies: - cac: 6.7.14 - debug: 4.3.5 - pathe: 1.1.2 - tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@20.14.10) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite@5.3.3(@types/node@20.14.10): - dependencies: - esbuild: 0.21.5 - postcss: 8.4.39 - rollup: 4.18.1 - optionalDependencies: - '@types/node': 20.14.10 - fsevents: 2.3.3 - - vitest@2.0.3(@types/node@20.14.10): - dependencies: - '@ampproject/remapping': 2.3.0 - '@vitest/expect': 2.0.3 - '@vitest/pretty-format': 2.0.3 - '@vitest/runner': 2.0.3 - '@vitest/snapshot': 2.0.3 - '@vitest/spy': 2.0.3 - '@vitest/utils': 2.0.3 - chai: 5.1.1 - debug: 4.3.5 - execa: 8.0.1 - magic-string: 0.30.10 - pathe: 1.1.2 - std-env: 3.7.0 - tinybench: 2.8.0 - tinypool: 1.0.0 - tinyrainbow: 1.2.0 - vite: 5.3.3(@types/node@20.14.10) - vite-node: 2.0.3(@types/node@20.14.10) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 20.14.10 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 diff --git a/.github/scripts/jira/tsconfig.json b/.github/scripts/jira/tsconfig.json deleted file mode 100644 index 746f76774b0..00000000000 --- a/.github/scripts/jira/tsconfig.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/.github/scripts/jira/update-jira-issue.ts b/.github/scripts/jira/update-jira-issue.ts deleted file mode 100644 index 6e539c7ffa8..00000000000 --- a/.github/scripts/jira/update-jira-issue.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as core from "@actions/core"; -import jira from "jira.js"; -import { tagsToLabels, createJiraClient, parseIssueNumberFrom } from "./lib"; - -function updateJiraIssue( - client: jira.Version3Client, - issueNumber: string, - tags: string[], - fixVersionName: string, - dryRun: boolean -) { - const payload = { - issueIdOrKey: issueNumber, - update: { - labels: tagsToLabels(tags), - fixVersions: [{ set: [{ name: fixVersionName }] }], - }, - }; - - core.info( - `Updating JIRA issue ${issueNumber} with fix version ${fixVersionName} and labels [${payload.update.labels.join( - ", " - )}]` - ); - if (dryRun) { - core.info("Dry run enabled, skipping JIRA issue update"); - return; - } - - return client.issues.editIssue(payload); -} - -async function main() { - const prTitle = process.env.PR_TITLE; - const commitMessage = process.env.COMMIT_MESSAGE; - const branchName = process.env.BRANCH_NAME; - - const chainlinkVersion = process.env.CHAINLINK_VERSION; - const dryRun = !!process.env.DRY_RUN; - // tags are not getting used at the current moment so will always default to [] - const tags = process.env.FOUND_TAGS ? process.env.FOUND_TAGS.split(",") : []; - - const client = createJiraClient(); - - // Checks for the Jira issue number and exit if it can't find it - const issueNumber = parseIssueNumberFrom(prTitle, commitMessage, branchName); - if (!issueNumber) { - const msg = - "No JIRA issue number found in: PR title, commit message, or branch name. Please include the issue ID in one of these."; - - core.info(msg); - core.notice(msg); - core.setOutput("jiraComment", `> :medal_military: ${msg}`); - - return; - } - - const fixVersionName = `chainlink-v${chainlinkVersion}`; - await updateJiraIssue(client, issueNumber, tags, fixVersionName, dryRun); - - core.setOutput("jiraComment", ""); -} - -async function run() { - try { - await main(); - } catch (error) { - if (error instanceof Error) { - core.setFailed(error.message); - } - core.setFailed( - "Error: Failed to update JIRA issue with fix version and labels." - ); - } -} - -run(); diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index c21171a83db..3a07ecefaa0 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -2,100 +2,54 @@ name: Automation Benchmark Test on: workflow_dispatch: inputs: - testType: - description: Type of test to run (benchmark, soak) - required: true - default: benchmark - type: string - base64Config: - description: base64-ed config - required: true - type: string + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string + test_secrets_override_key: + description: Key to run tests with custom test secrets + required: false + type: string slackMemberID: description: Notifies test results (Not your @) required: true default: U02Q14G80TY type: string + testType: + description: Type of test to run (benchmark, soak) + required: true + default: benchmark + type: string + jobs: - automation_benchmark: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - name: Automation Benchmark Test - runs-on: ubuntu22.04-16cores-64GB - env: - SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + test_ids: '${{ inputs.testType }}/automation_test.go:TestAutomationBenchmark' + test_config_override_path: ${{ inputs.test_config_override_path }} + SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK - CHAINLINK_ENV_USER: ${{ github.actor }} - REF_NAME: ${{ github.head_ref || github.ref_name }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Get Slack config and mask base64 config - run: | - SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - echo ::add-mask::$SLACK_USER - echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV - - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Parse base64 config - uses: ./.github/actions/setup-parse-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Send details to Step Summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - - name: Build Test Image - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - suites: benchmark chaos reorg load - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - env: - DETACH_RUNNER: true - TEST_SUITE: benchmark - TEST_ARGS: -test.timeout 720h - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - TEST_TYPE: ${{ github.event.inputs.testType }} - TEST_TEST_TYPE: ${{ github.event.inputs.testType }} - RR_MEM: 4Gi - TEST_LOG_LEVEL: info - with: - test_command_to_run: cd integration-tests && go test -timeout 30m -v -run ^TestAutomationBenchmark$ ./benchmark -count=1 - test_download_vendor_packages_command: make gomod - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} - should_cleanup: false - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-benchmark-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Automation Benchmark Test - continue-on-error: true + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index 187ca3b5b66..71bfbfa029e 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -2,121 +2,49 @@ name: Automation Load Test on: workflow_dispatch: inputs: - base64Config: - description: base64-ed config - required: true - type: string + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string slackMemberID: description: Notifies test results (Not your @) required: true default: U02Q14G80TY - type: string - test_secrets_override_key: - description: 'Key to run tests with custom test secrets' - required: false - type: string + type: string jobs: - automation_load: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - name: Automation Load Test - runs-on: ubuntu22.04-16cores-64GB - env: - SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + test_ids: 'load/automationv2_1/automationv2_1_test.go:TestLogTrigger' + test_config_override_path: ${{ inputs.test_config_override_path }} + SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK - CHAINLINK_ENV_USER: ${{ github.actor }} - REF_NAME: ${{ github.head_ref || github.ref_name }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Get Slack config and mask base64 config - run: | - SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - echo ::add-mask::$SLACK_USER - echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV - - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Merge Pyrsoscope config - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: "automation-load-test" - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - run: | - decoded_toml=$(echo $BASE64_CONFIG_OVERRIDE | base64 -d) - - # use Pyroscope config from GH secrets and merge it with base64 input - cat << EOF > config.toml - server_url="$PYROSCOPE_SERVER" - environment="$PYROSCOPE_ENVIRONMENT" - key_secret="$PYROSCOPE_KEY" - EOF - - echo "$decoded_toml" >> final_config.toml - cat config.toml >> final_config.toml - BASE64_CONFIG_OVERRIDE=$(cat final_config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Parse base64 config - uses: ./.github/actions/setup-parse-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Send details to Step Summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - - name: Build Test Image - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - suites: benchmark chaos reorg load - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - env: - RR_CPU: 4000m - RR_MEM: 4Gi - DETACH_RUNNER: true - TEST_SUITE: automationv2_1 - TEST_ARGS: -test.timeout 720h - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - with: - test_command_to_run: cd integration-tests/load && go test -timeout 1h -v -run TestLogTrigger ./automationv2_1 -count=1 - test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} - test_download_vendor_packages_command: make gomod - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} - should_cleanup: false - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-load-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Automation Load Test - continue-on-error: true + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/automation-nightly-tests.yml b/.github/workflows/automation-nightly-tests.yml index f018124624a..222eac2e75b 100644 --- a/.github/workflows/automation-nightly-tests.yml +++ b/.github/workflows/automation-nightly-tests.yml @@ -7,294 +7,36 @@ on: - "*" workflow_dispatch: -env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu22.04-16cores-64GB - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-nightly-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Chainlink Image - uses: ./.github/actions/build-chainlink-image - with: - tag_suffix: "" - dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ github.sha }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - automation-upgrade-tests: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink] - env: - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: info - SELECTED_NETWORKS: "SIMULATED" - strategy: - fail-fast: false - matrix: - tests: - - name: Upgrade 2.0 - id: upgrade-2-0 - suite: smoke - nodes: 1 - os: ubuntu22.04-8cores-32GB - network: SIMULATED - command: -run ^TestAutomationNodeUpgrade/registry_2_0 ./smoke - - name: Upgrade 2.1 - id: upgrade-2-1 - suite: smoke - nodes: 5 - os: ubuntu22.04-8cores-32GB - network: SIMULATED - command: -run ^TestAutomationNodeUpgrade/registry_2_1 ./smoke - - name: Upgrade 2.2 - id: upgrade-2-2 - suite: smoke - nodes: 5 - os: ubuntu22.04-8cores-32GB - network: SIMULATED - command: -run ^TestAutomationNodeUpgrade/registry_2_2 ./smoke - runs-on: ${{ matrix.tests.os }} - name: Automation ${{ matrix.tests.name }} Test - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.head_ref || github.ref_name }} - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-upgrade-config - with: - selectedNetworks: ${{ env.SELECTED_NETWORKS }} - chainlinkImage: "public.ecr.aws/chainlink/chainlink" - chainlinkVersion: "latest" - upgradeImage: ${{ env.CHAINLINK_IMAGE }} - upgradeVersion: ${{ github.sha }} - runId: ${{ github.run_id }} - testLogCollect: "true" - lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - env: - TEST_SUITE: ${{ matrix.tests.suite }} - with: - test_command_to_run: cd ./integration-tests && go test -timeout 60m -count=1 -json -test.parallel=${{ matrix.tests.nodes }} ${{ matrix.tests.command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: 'public.ecr.aws/chainlink/chainlink' - cl_image_tag: 'latest' - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_location: ./integration-tests/${{ matrix.tests.suite }}/logs - artifacts_name: testcontainers-logs-${{ matrix.tests.name }} - publish_check_name: Automation Results ${{ matrix.tests.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Upload test log - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: failure() - with: - name: gotest-logs-${{ matrix.tests.name }} - path: /tmp/gotest.log - retention-days: 7 - continue-on-error: true - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-nightly-upgrade-tests-${{ matrix.tests.id }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Automation ${{ matrix.tests.name }} Test - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - - test-notify: - name: Start Slack Thread - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} - environment: integration - outputs: - thread_ts: ${{ steps.slack.outputs.thread_ts }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [ automation-upgrade-tests ] - steps: - - name: Debug Result - run: echo ${{ join(needs.*.result, ',') }} - - name: Main Slack Notification - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - id: slack - with: - channel-id: C03KJ5S7KEK - payload: | - { - "attachments": [ - { - "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "Automation Nightly Tests ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", - "emoji": true - } - }, - { - "type": "divider" - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" - } - } - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - - test-results: - name: Post Test Results for ${{ matrix.name }} - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: test-notify - strategy: - fail-fast: false - matrix: - name: [ Upgrade 2.0, Upgrade 2.1, Upgrade 2.2 ] - steps: - - name: Get Results - id: test-results - run: | - # I feel like there's some clever, fully jq way to do this, but I ain't got the motivation to figure it out - echo "Querying test results" - - PARSED_RESULTS=$(curl \ - -H "Authorization: Bearer ${{ github.token }}" \ - 'https://api.github.com/repos/${{github.repository}}/actions/runs/${{ github.run_id }}/jobs' \ - | jq -r --arg pattern "${{ matrix.name }} Test" '.jobs[] - | select(.name | test($pattern)) as $job - | $job.steps[] - | select(.name == "Run Tests") - | { conclusion: (if .conclusion == "success" then ":white_check_mark:" else ":x:" end), product: ("*" + ($job.name | capture($pattern).product) + "*") }') - - echo "Parsed Results:" - echo $PARSED_RESULTS - - ALL_SUCCESS=true - for row in $(echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")'); do - success=false - break - done - - echo all_success=$ALL_SUCCESS >> $GITHUB_OUTPUT - - FORMATTED_RESULTS=$(echo $PARSED_RESULTS | jq -s '[.[] - | { - conclusion: .conclusion, - product: .product - } - ] - | map("{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"\(.product): \(.conclusion)\"}}") - | join(",")') - - echo "Formatted Results:" - echo $FORMATTED_RESULTS - - # Cleans out backslashes and quotes from jq - CLEAN_RESULTS=$(echo "$FORMATTED_RESULTS" | sed 's/\\\"/"/g' | sed 's/^"//;s/"$//') - - echo "Clean Results" - echo $CLEAN_RESULTS - - echo results=$CLEAN_RESULTS >> $GITHUB_OUTPUT - - - name: Test Details - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - with: - channel-id: C03KJ5S7KEK - payload: | - { - "thread_ts": "${{ needs.test-notify.outputs.thread_ts }}", - "attachments": [ - { - "color": "${{ steps.test-results.outputs.all_success && '#2E7D32' || '#C62828' }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "${{ matrix.name }} ${{ steps.test-results.outputs.all_success && ':white_check_mark:' || ':x: Notifying <@U02Q14G80TY>'}}", - "emoji": true - } - }, - { - "type": "divider" - }, - ${{ steps.test-results.outputs.results }} - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} \ No newline at end of file + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + test_trigger: Automation Nightly Tests + chainlink_version: ${{ github.sha }} + slack_notification_after_tests: true + slack_notification_after_tests_channel_id: "#automation-test-notifications" + slack_notification_after_tests_name: Automation Nightly E2E Tests + # slack_notification_after_tests_notify_user_id_on_failure: U0XXXXXXX + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index 7514743fa88..f85a1330e6e 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -1,16 +1,17 @@ -name: Automation On Demand Tests +name: Run Automation On Demand Tests + on: workflow_dispatch: inputs: chainlinkVersionUpdate: - description: Chainlink image version to upgrade to + description: Chainlink image version to upgrade to (Leave empty to build from head/ref) required: false type: string chainlinkImageUpdate: - description: Chainlink image repo to upgrade to (Leave empty to build from head/ref) + description: Chainlink image repo to upgrade to options: - - public.ecr.aws/chainlink/chainlink - QA_ECR + - public.ecr.aws/chainlink/chainlink type: choice chainlinkVersion: description: Chainlink image version to use initially for upgrade test @@ -34,285 +35,149 @@ on: type: boolean default: false required: true - -env: - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink + with_existing_remote_runner_version: + description: 'Tag of the existing remote runner version to use (Leave empty to build from head/ref)' + required: false + type: string jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - strategy: - matrix: - image: - - name: "" - dockerfile: core/chainlink.Dockerfile - tag-suffix: "" - - name: (plugins) - dockerfile: plugins/chainlink.Dockerfile - tag-suffix: -plugins - name: Build Chainlink Image ${{ matrix.image.name }} - runs-on: ubuntu22.04-16cores-64GB + # Set tests to run based on the workflow inputs + set-tests-to-run: + name: Set tests to run + runs-on: ubuntu-latest + 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 }} steps: - - name: Collect Metrics - if: inputs.chainlinkImage == '' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-on-demand-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image ${{ matrix.image.name }} - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.head_ref || github.ref_name }} - - name: Check if image exists - if: inputs.chainlinkImage == '' - id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - repository: chainlink - tag: ${{ github.sha }}${{ matrix.image.tag-suffix }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Build Image - if: steps.check-image.outputs.exists == 'false' && inputs.chainlinkImage == '' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - cl_repo: smartcontractkit/chainlink - cl_ref: ${{ github.sha }} - cl_dockerfile: ${{ matrix.image.dockerfile }} - push_tag: ${{ env.CHAINLINK_IMAGE }}:${{ github.sha }}${{ matrix.image.tag-suffix }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Print Chainlink Image Built - if: inputs.chainlinkImage == '' - run: | - echo "### chainlink node image tag used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - build-test-image: - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Image - runs-on: ubuntu22.04-16cores-64GB - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-on-demand-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.head_ref || github.ref_name }} - - name: Build Test Image - if: inputs.enableChaos || inputs.enableReorg - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - automation-on-demand-tests: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-test-image] - env: - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: info - strategy: - fail-fast: false - matrix: - tests: - - name: chaos - id: chaos - suite: chaos - nodes: 20 - os: ubuntu-latest - enabled: ${{ inputs.enableChaos }} - pyroscope_env: ci-automation-on-demand-chaos - network: SIMULATED - command: -run ^TestAutomationChaos$ ./chaos - - name: reorg 2.0 - id: reorg-2.0 - suite: reorg - nodes: 1 - os: ubuntu-latest - enabled: ${{ inputs.enableReorg }} - pyroscope_env: ci-automation-on-demand-reorg - network: SIMULATED - command: -run ^TestAutomationReorg/registry_2_0 ./reorg - - name: reorg 2.1 - id: reorg-2.1 - suite: reorg - nodes: 2 - os: ubuntu-latest - enabled: ${{ inputs.enableReorg }} - pyroscope_env: ci-automation-on-demand-reorg - network: SIMULATED - command: -run ^TestAutomationReorg/registry_2_1 ./reorg - - name: reorg 2.2 - id: reorg-2.2 - suite: reorg - nodes: 2 - os: ubuntu-latest - enabled: ${{ inputs.enableReorg }} - pyroscope_env: ci-automation-on-demand-reorg - network: SIMULATED - command: -run ^TestAutomationReorg/registry_2_2 ./reorg - - name: reorg 2.3 - id: reorg-2.3 - suite: reorg - nodes: 2 - os: ubuntu-latest - enabled: ${{ inputs.enableReorg }} - pyroscope_env: ci-automation-on-demand-reorg - network: SIMULATED - command: -run ^TestAutomationReorg/registry_2_3 ./reorg - - name: upgrade 2.0 - id: upgrade-2.0 - type: upgrade - suite: smoke - nodes: 1 - os: ubuntu22.04-8cores-32GB - enabled: true - pyroscope_env: ci-automation-on-demand-upgrade - network: SIMULATED - command: -run ^TestAutomationNodeUpgrade/registry_2_0 ./smoke - - name: upgrade 2.1 - id: upgrade-2.1 - type: upgrade - suite: smoke - nodes: 5 - os: ubuntu22.04-8cores-32GB - enabled: true - pyroscope_env: ci-automation-on-demand-upgrade - network: SIMULATED - command: -run ^TestAutomationNodeUpgrade/registry_2_1 ./smoke - - name: upgrade 2.2 - id: upgrade-2.2 - type: upgrade - suite: smoke - nodes: 5 - os: ubuntu22.04-8cores-32GB - enabled: true - pyroscope_env: ci-automation-on-demand-upgrade - network: SIMULATED - command: -run ^TestAutomationNodeUpgrade/registry_2_2 ./smoke - runs-on: ${{ matrix.tests.os }} - name: Automation On Demand ${{ matrix.tests.name }} Test - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.head_ref || github.ref_name }} - name: Determine build to use id: determine-build shell: bash run: | if [[ "${{ inputs.chainlinkImage }}" == "QA_ECR" ]]; then - echo "image=${{ env.CHAINLINK_IMAGE }}" >>$GITHUB_OUTPUT + echo "image='{{ env.QA_CHAINLINK_IMAGE }}'" >> $GITHUB_ENV else - echo "image=${{ inputs.chainlinkImage }}" >>$GITHUB_OUTPUT + echo "image=${{ inputs.chainlinkImage }}" >> $GITHUB_ENV fi if [[ "${{ inputs.chainlinkImageUpdate }}" == "QA_ECR" ]]; then - echo "upgrade_image=${{ env.CHAINLINK_IMAGE }}" >>$GITHUB_OUTPUT + echo "upgrade_image='{{ env.QA_CHAINLINK_IMAGE }}'" >> $GITHUB_ENV else - echo "upgrade_image=${{ inputs.chainlinkImageUpdate }}" >>$GITHUB_OUTPUT + echo "upgrade_image=${{ inputs.chainlinkImageUpdate }}" >> $GITHUB_ENV fi if [[ -z "${{ inputs.chainlinkVersion }}" ]] && [[ "${{ inputs.chainlinkImage }}" == "QA_ECR" ]]; then - echo "version=${{ github.sha }}" >>$GITHUB_OUTPUT + echo "version=${{ github.sha }}" >> $GITHUB_ENV else - echo "version=${{ inputs.chainlinkVersion }}" >>$GITHUB_OUTPUT + echo "version=${{ inputs.chainlinkVersion }}" >> $GITHUB_ENV fi if [[ -z "${{ inputs.chainlinkVersionUpdate }}" ]] && [[ "${{ inputs.chainlinkImageUpdate }}" == "QA_ECR" ]]; then - echo "upgrade_version=${{ github.sha }}" >>$GITHUB_OUTPUT + echo "upgrade_version=${{ github.sha }}" >> $GITHUB_ENV else - echo "upgrade_version=${{ inputs.chainlinkVersionUpdate }}" >>$GITHUB_OUTPUT + echo "upgrade_version=${{ inputs.chainlinkVersionUpdate }}" >> $GITHUB_ENV + fi + - name: Check if chainlink image check required + id: determine-chainlink-image-check + shell: bash + run: | + chainlink_image_versions="" + if [ "${{ github.event.inputs.chainlinkImage }}" = "QA_ECR" ]; then + chainlink_image_versions+="${{ env.version }}," + fi + if [ "${{ github.event.inputs.chainlinkImageUpdate }}" = "QA_ECR" ]; then + chainlink_image_versions+="${{ env.upgrade_version }}" fi - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - if: ${{ matrix.tests.enabled == true }} - with: - test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} - test_command_to_run: cd ./integration-tests && go test -timeout 60m -count=1 -json -test.parallel=${{ matrix.tests.nodes }} ${{ matrix.tests.command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_suite: ${{ matrix.tests.suite }} - test_config_chainlink_version: ${{ steps.determine-build.outputs.version }} - test_config_chainlink_upgrade_version: ${{ steps.determine-build.outputs.upgrade_version }} - test_config_selected_networks: ${{ matrix.tests.network }} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_test_log_collect: "true" - cl_repo: ${{ steps.determine-build.outputs.image }} - cl_image_tag: ${{ steps.determine-build.outputs.version }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_location: ./integration-tests/${{ matrix.tests.suite }}/logs - publish_check_name: Automation On Demand Results ${{ matrix.tests.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - DEFAULT_CHAINLINK_IMAGE: ${{ steps.determine-build.outputs.image }} - DEFAULT_CHAINLINK_UPGRADE_IMAGE: ${{ steps.determine-build.outputs.upgrade_image }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.tests.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.tests.pyroscope_env == '' || !startsWith(github.ref, 'refs/tags/') && 'false' || 'true' }} - - - name: Upload test log - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: failure() - with: - name: test-log-${{ matrix.tests.name }} - path: /tmp/gotest.log - retention-days: 7 - continue-on-error: true - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: automation-on-demand-tests-${{ matrix.tests.id }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Automation On Demand ${{ matrix.tests.name }} Test - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true + echo "require_chainlink_image_versions_in_qa_ecr=$chainlink_image_versions" >> $GITHUB_OUTPUT + - name: Set tests to run + id: set-tests + run: | + + # Always run upgrade tests + cat > test_list.yaml <> test_list.yaml <> test_list.yaml <> $GITHUB_OUTPUT + + call-run-e2e-tests-workflow: + name: Run E2E Tests + needs: set-tests-to-run + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + test_list: ${{ needs.set-tests-to-run.outputs.test_list }} + require_chainlink_image_versions_in_qa_ecr: ${{ needs.set-tests-to-run.outputs.require_chainlink_image_versions_in_qa_ecr }} + with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} + test_log_upload_on_failure: true + test_log_upload_retention_days: 7 + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + diff --git a/.github/workflows/bash-scripts.yml b/.github/workflows/bash-scripts.yml index e9b7265c962..a55bd1f1574 100644 --- a/.github/workflows/bash-scripts.yml +++ b/.github/workflows/bash-scripts.yml @@ -11,7 +11,7 @@ jobs: bash-scripts-src: ${{ steps.bash-scripts.outputs.src }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: bash-scripts with: @@ -25,7 +25,7 @@ jobs: needs: [changes] steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Run ShellCheck if: needs.changes.outputs.bash-scripts-src == 'true' uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 diff --git a/.github/workflows/build-publish-develop-pr.yml b/.github/workflows/build-publish-develop-pr.yml index c0c3a17824b..467411ab4ea 100644 --- a/.github/workflows/build-publish-develop-pr.yml +++ b/.github/workflows/build-publish-develop-pr.yml @@ -1,11 +1,18 @@ -name: "Build and Publish Chainlink" +name: "Build and Publish GoReleaser" on: pull_request: + # The default types are opened, synchronize, and reopened + # See https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request + # We add a label trigger too, since when the build-publish label is added to a PR, we want to build and publish + types: + - opened + - synchronize + - reopened + - labeled push: branches: - develop - - "release/**" workflow_dispatch: inputs: git_ref: @@ -20,100 +27,128 @@ env: GIT_REF: ${{ github.event.inputs.git_ref || github.ref }} jobs: - goreleaser-build-publish-chainlink: - runs-on: ubuntu-20.04 + merge: + runs-on: ubuntu-latest + needs: [split, image-tag] + if: ${{ needs.image-tag.outputs.release-type == 'nightly' }} + permissions: + id-token: write + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.1 + with: + ref: ${{ env.GIT_REF }} + + - name: Configure aws credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_BUILD_PUBLISH_DEVELOP_PR }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + role-session-name: "merge" + + - uses: actions/cache/restore@v4 + with: + path: dist/linux_amd64_v1 + key: chainlink-amd64-${{ github.sha }} + fail-on-cache-miss: true + + - uses: actions/cache/restore@v4 + with: + path: dist/linux_arm64 + key: chainlink-arm64-${{ github.sha }} + fail-on-cache-miss: true + + - name: Merge images for both architectures + uses: ./.github/actions/goreleaser-build-sign-publish + with: + docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} + docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} + goreleaser-release-type: "merge" + goreleaser-config: .goreleaser.develop.yaml + goreleaser-key: ${{ secrets.GORELEASER_KEY }} + + split: + name: "split-${{ matrix.goarch }}" + needs: image-tag + runs-on: ${{ matrix.runner }} permissions: id-token: write contents: read strategy: + fail-fast: false matrix: - goarch: [amd64, arm64] + include: + - runner: ubuntu-latest + goarch: amd64 + dist_name: linux_amd64_v1 + + - runner: ubuntu-24.04-4cores-16GB-ARM + goarch: arm64 + dist_name: linux_arm64 steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: ref: ${{ env.GIT_REF }} - - # This gets the image tag and whether to publish the image based on the event type - # PR builds: pr-- (if label 'build-publish' is present publishes the image) - # develop builds: develop- - # release builds: release- - # manual builds: (if build-publish is true publishes the image) - - name: Get image tag - id: get-image-tag - run: | - short_sha=$(git rev-parse --short HEAD) - echo "build-publish=false" | tee -a $GITHUB_OUTPUT - if [[ ${{ github.event_name }} == 'push' ]]; then - if [[ ${{ github.ref_name }} == 'release/'* ]]; then - echo "image-tag=release-${short_sha}" | tee -a $GITHUB_OUTPUT - echo "build-publish=true" | tee -a $GITHUB_OUTPUT - else - echo "image-tag=develop-${short_sha}" | tee -a $GITHUB_OUTPUT - echo "build-publish=true" | tee -a $GITHUB_OUTPUT - fi - elif [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then - echo "image-tag=${short_sha}" | tee -a $GITHUB_OUTPUT - echo "build-publish=${{ github.event.inputs.build-publish }}" | tee -a $GITHUB_OUTPUT - else - if [[ ${{ github.event_name }} == "pull_request" ]]; then - echo "image-tag=pr-${{ github.event.number }}-${short_sha}" | tee -a $GITHUB_OUTPUT - if [[ ${{ contains(github.event.pull_request.labels.*.name, 'build-publish') }} == "true" ]]; then - echo "build-publish=true" | tee -a $GITHUB_OUTPUT - fi - fi - fi + fetch-depth: 0 - name: Configure aws credentials - if: steps.get-image-tag.outputs.build-publish == 'true' uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_BUILD_PUBLISH_DEVELOP_PR }} aws-region: ${{ secrets.AWS_REGION }} mask-aws-account-id: true - role-session-name: goreleaser-build-publish-chainlink + role-session-name: "split-${{ matrix.goarch }}" + + - id: cache + uses: actions/cache@v4 + with: + path: dist/${{ matrix.dist_name }} + key: chainlink-${{ matrix.goarch }}-${{ github.sha }} - - name: Build and publish images + - name: Build images for ${{ matrix.goarch }} uses: ./.github/actions/goreleaser-build-sign-publish + if: steps.cache.outputs.cache-hit != 'true' with: - enable-docker-publish: ${{ steps.get-image-tag.outputs.build-publish }} docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} - docker-image-name: chainlink - docker-image-tag: ${{ steps.get-image-tag.outputs.image-tag }} - enable-goreleaser-snapshot: "true" - enable-goreleaser-split: "true" - goreleaser-split-arch: ${{ matrix.goarch }} - goreleaser-exec: ./tools/bin/goreleaser_wrapper + docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} + goreleaser-release-type: ${{ needs.image-tag.outputs.release-type }} goreleaser-config: .goreleaser.develop.yaml goreleaser-key: ${{ secrets.GORELEASER_KEY }} - zig-version: 0.11.0 - - name: Output image name and digest - if: steps.get-image-tag.outputs.build-publish == 'true' - shell: bash + image-tag: + runs-on: ubuntu-latest + outputs: + image-tag: ${{ steps.get-image-tag.outputs.image-tag }} + release-type: ${{ steps.get-image-tag.outputs.release-type }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + + - name: Get image tag + id: get-image-tag run: | - # need to check if artifacts.json exists because goreleaser splits the build - if [[ -f dist/artifacts.json ]]; then - artifact_path="dist/artifacts.json" + short_sha=$(git rev-parse --short HEAD) + echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT + if [[ ${{ github.event_name }} == 'push' ]]; then + echo "image-tag=develop" | tee -a $GITHUB_OUTPUT + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + elif [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then + echo "image-tag=${short_sha}" | tee -a $GITHUB_OUTPUT + if [[ "${{ inputs.build-publish }}" == 'false' ]]; then + echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT + else + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + fi else - artifact_path="dist/linux_${{ matrix.goarch }}/artifacts.json" - cat dist/linux_${{ matrix.goarch }}/artifacts.json + if [[ ${{ github.event_name }} == "pull_request" ]]; then + echo "image-tag=pr-${{ github.event.number }}-${short_sha}" | tee -a $GITHUB_OUTPUT + if [[ ${{ contains(github.event.pull_request.labels.*.name, 'build-publish') }} == "true" ]]; then + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + fi + fi fi - echo "### Docker Images" | tee -a "$GITHUB_STEP_SUMMARY" - jq -r '.[] | select(.type == "Docker Image") | "`\(.goarch)-image`: \(.name)"' ${artifact_path} >> output.txt - jq -r '.[] | select(.type == "Archive") | "`\(.goarch)-digest`: \(.extra.Checksum)"' ${artifact_path} >> output.txt - while read -r line; do - echo "$line" | tee -a "$GITHUB_STEP_SUMMARY" - done < output.txt - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: goreleaser-build-publish - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: goreleaser-build-publish-chainlink (${{ matrix.goarch }}) - continue-on-error: true \ No newline at end of file diff --git a/.github/workflows/build-publish-goreleaser.yml b/.github/workflows/build-publish-goreleaser.yml new file mode 100644 index 00000000000..ca28d767398 --- /dev/null +++ b/.github/workflows/build-publish-goreleaser.yml @@ -0,0 +1,126 @@ +name: "Goreleaser Chainlink" + +on: + push: + tags: + - "goreleaser-v*" + +env: + ECR_HOSTNAME: public.ecr.aws + +jobs: + checks: + name: "Checks" + runs-on: ubuntu-20.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.1 + - name: Check for VERSION file bump on tags + # Avoids checking VERSION file bump on forks. + if: ${{ github.repository == 'smartcontractkit/chainlink' }} + uses: ./.github/actions/version-file-bump + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + # The main differences between this workflow and the develop one are: + # - Goreleaser pipeline only runs on tags + # - We only build ccip OR chainlink, not both + goreleaser-merge: + needs: [goreleaser-split] + name: merge + runs-on: ubuntu-latest + environment: build-publish + permissions: + id-token: write + contents: read + attestations: write + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.1 + with: + fetch-depth: 0 + + - name: Configure aws credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }} + role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + role-session-name: goreleaser-build-sign-publish-chainlink + + - uses: actions/cache/restore@v4 + with: + path: dist/linux_amd64_v1 + # We use ref_name here and not in develop b/c develop builds both ccip and chainlink + # whereas here we only build one or the other + key: chainlink-amd64-${{ github.sha }}-${{ github.ref_name }} + fail-on-cache-miss: true + + - uses: actions/cache/restore@v4 + with: + path: dist/linux_arm64 + key: chainlink-arm64-${{ github.sha }}-${{ github.ref_name }} + fail-on-cache-miss: true + + - name: Merge images for both architectures + id: goreleaser-build-sign-publish + uses: ./.github/actions/goreleaser-build-sign-publish + with: + docker-registry: ${{ env.ECR_HOSTNAME }} + docker-image-tag: ${{ github.ref_name }} + goreleaser-config: .goreleaser.production.yaml + goreleaser-release-type: merge + goreleaser-key: ${{ secrets.GORELEASER_KEY }} + + goreleaser-split: + name: "split-${{ matrix.goarch }}" + needs: [checks] + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest + goarch: amd64 + dist_name: linux_amd64_v1 + + - runner: ubuntu-24.04-4cores-16GB-ARM + goarch: arm64 + dist_name: linux_arm64 + environment: build-publish + permissions: + id-token: write + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.1 + with: + fetch-depth: 0 + + - name: Configure aws credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }} + role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + role-session-name: goreleaser-build-sign-publish-chainlink + + - id: cache + uses: actions/cache@v4 + with: + path: dist/${{ matrix.dist_name }} + # We use ref_name here and not in develop b/c develop builds both ccip and chainlink + # whereas here we only build one or the other + key: chainlink-${{ matrix.goarch }}-${{ github.sha }}-${{ github.ref_name }} + + - name: Build images for ${{ matrix.goarch }} + if: steps.cache.outputs.cache-hit != 'true' + uses: ./.github/actions/goreleaser-build-sign-publish + with: + docker-registry: ${{ env.ECR_HOSTNAME }} + docker-image-tag: ${{ github.ref_name }} + goreleaser-release-type: release + goreleaser-config: .goreleaser.production.yaml + goreleaser-key: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 0941455a169..3d7e925dba0 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -1,12 +1,9 @@ name: "Build, Sign and Publish Chainlink" on: - # Mimics old circleci behaviour push: tags: - "v*" - branches: - - "release/**" env: ECR_HOSTNAME: public.ecr.aws @@ -18,28 +15,28 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Check for VERSION file bump on tags # Avoids checking VERSION file bump on forks. - if: ${{ github.repository == 'smartcontractkit/chainlink' && startsWith(github.ref, 'refs/tags/v') }} + if: ${{ github.repository == 'smartcontractkit/chainlink' }} uses: ./.github/actions/version-file-bump with: github-token: ${{ secrets.GITHUB_TOKEN }} build-sign-publish-chainlink: needs: [checks] - if: ${{ ! startsWith(github.ref_name, 'release/') }} runs-on: ubuntu-20.04 environment: build-publish permissions: id-token: write - contents: read + contents: write + attestations: write outputs: docker-image-tag: ${{ steps.build-sign-publish.outputs.docker-image-tag }} docker-image-digest: ${{ steps.build-sign-publish.outputs.docker-image-digest }} steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Build, sign and publish chainlink image id: build-sign-publish @@ -51,88 +48,17 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} ecr-hostname: ${{ env.ECR_HOSTNAME }} ecr-image-name: ${{ env.ECR_IMAGE_NAME }} - sign-images: true - sign-method: "keypair" - cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }} - cosign-public-key: ${{ secrets.COSIGN_PUBLIC_KEY }} - cosign-password: ${{ secrets.COSIGN_PASSWORD }} dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} + sign-images: true verify-signature: true - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: build-chainlink-publish - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: build-sign-publish-chainlink - continue-on-error: true - - goreleaser-build-sign-publish-chainlink: - needs: [checks] - if: ${{ ! startsWith(github.ref_name, 'release/') }} - runs-on: ubuntu-20.04 - environment: build-publish - permissions: - id-token: write - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }} - role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} - aws-region: ${{ secrets.AWS_REGION }} - mask-aws-account-id: true - role-session-name: goreleaser-build-sign-publish-chainlink - - - name: Build, sign, and publish image - id: goreleaser-build-sign-publish - uses: ./.github/actions/goreleaser-build-sign-publish - with: - enable-docker-publish: "true" - docker-registry: ${{ env.ECR_HOSTNAME}} - docker-image-name: ${{ env.ECR_IMAGE_NAME }} - docker-image-tag: ${{ github.ref_name }} - goreleaser-exec: ./tools/bin/goreleaser_wrapper - goreleaser-config: .goreleaser.develop.yaml - goreleaser-key: ${{ secrets.GORELEASER_KEY }} - zig-version: 0.11.0 - enable-cosign: "true" - cosign-version: 3.4.0 - cosign-password: ${{ secrets.COSIGN_PASSWORD }} - cosign-public-key: ${{ secrets.COSIGN_PUBLIC_KEY }} - cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }} - - - name: Output image name and digest - shell: sh - run: | - artifact_path="dist/artifacts.json" - echo "### Docker Images" | tee -a "$GITHUB_STEP_SUMMARY" - jq -r '.[] | select(.type == "Docker Image") | "`\(.goarch)-image`: \(.name)"' ${artifact_path} >> output.txt - jq -r '.[] | select(.type == "Archive") | "`\(.goarch)-digest`: \(.extra.Checksum)"' ${artifact_path} >> output.txt - while read -r line; do - echo "$line" | tee -a "$GITHUB_STEP_SUMMARY" - done < output.txt - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + - name: Attest Docker image + uses: actions/attest-build-provenance@6149ea5740be74af77f260b9db67e633f6b0a9a1 # v1.4.2 with: - id: goreleaser-build-chainlink-publish - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: goreleaser-build-sign-publish-chainlink - continue-on-error: true + subject-digest: ${{ steps.build-sign-publish.outputs.docker-image-digest }} + subject-name: ${{ env.ECR_HOSTNAME }}/${{ env.ECR_IMAGE_NAME }} + push-to-registry: true # Notify Slack channel for new git tags. slack-notify: @@ -142,9 +68,9 @@ jobs: environment: build-publish steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Notify Slack - uses: smartcontractkit/.github/actions/slack-notify-git-ref@7fa90bbeff35aa6ce3a9054f542bcf10b7d47cec # slack-notify-git-ref@0.1.0 + uses: smartcontractkit/.github/actions/slack-notify-git-ref@31e00facdd8f57a2bc7868b5e4c8591bf2aa3727 # slack-notify-git-ref@0.1.2 with: slack-channel-id: ${{ secrets.SLACK_CHANNEL_RELEASE_NOTIFICATIONS }} slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN_RELENG }} # Releng Bot diff --git a/.github/workflows/ccip-chaos-tests.yml b/.github/workflows/ccip-chaos-tests.yml index 493322ae420..29d41267f1e 100644 --- a/.github/workflows/ccip-chaos-tests.yml +++ b/.github/workflows/ccip-chaos-tests.yml @@ -1,253 +1,47 @@ name: CCIP Chaos Tests on: - workflow_run: - workflows: [ CCIP Load Test ] - types: [ completed ] - branches: [ develop ] + # Disabled until TT-1771 is resolved + # workflow_run: + # workflows: [ CCIP Load Test ] + # types: [ completed ] + # branches: [ develop ] workflow_dispatch: - - # Only run 1 of this workflow at a time per PR concurrency: group: chaos-ccip-tests-chainlink-${{ github.ref }} cancel-in-progress: true -env: - # TODO: TT-1470 - Update image names as we solidify new realease strategy - CL_ECR: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests:${{ github.sha }} - MOD_CACHE_VERSION: 1 - jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu20.04-16cores-64GB - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Check if image exists - id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - with: - repository: chainlink - tag: ${{ github.sha }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Build Image - if: steps.check-image.outputs.exists == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - env: - GH_TOKEN: ${{ github.token }} - with: - cl_repo: smartcontractkit/chainlink - cl_ref: ${{ github.sha }} - push_tag: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink:${{ github.sha }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-chaos-tests-build-chainlink-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - build-test-image: - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Image - runs-on: ubuntu20.04-16cores-64GB - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-chaos-tests-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Build Test Image - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - ccip-chaos-tests: - environment: integration - permissions: - issues: read - checks: write - pull-requests: write - id-token: write - contents: read - name: CCIP Chaos Tests - runs-on: ubuntu-latest - needs: [ build-chainlink, build-test-image ] - env: - TEST_SUITE: chaos - TEST_ARGS: -test.timeout 30m - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_TRIGGERED_BY: ccip-cron-chaos-eth - TEST_LOG_LEVEL: debug - DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable - GH_TOKEN: ${{ github.token }} - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-chaos-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: CCIP Chaos Tests - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Prepare Base64 TOML override for CCIP secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - - name: Run Chaos Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 -run 'TestChaosCCIP' ./chaos 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci - test_download_vendor_packages_command: make gomod - cl_repo: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - cl_image_tag: ${{ github.sha }} - artifacts_location: ./integration-tests/chaos/logs - publish_check_name: CCIP Chaos Test Results - publish_report_paths: ./tests-chaos-report.xml - triggered_by: ${{ env.TEST_TRIGGERED_BY }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - CGO_ENABLED: "1" - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - ## Notify in slack if the job fails - - name: Notify Slack - if: failure() && github.event_name != 'workflow_dispatch' - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - with: - channel-id: "#ccip-testing" - slack-message: ":x: :mild-panic-intensifies: CCIP chaos tests failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" - ## Run Cleanup if the job succeeds - - name: cleanup - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/cleanup@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - with: - triggered_by: ${{ env.TEST_TRIGGERED_BY }} - - ccip-chaos-with-load-tests: - environment: integration - permissions: - issues: read - checks: write - pull-requests: write - id-token: write - contents: read - name: CCIP Load With Chaos Tests - if: false # Disabled until CCIP-2555 is resolved - runs-on: ubuntu-latest - needs: [ build-chainlink, build-test-image ] - env: - TEST_SUITE: load - TEST_ARGS: -test.timeout 1h - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_TRIGGERED_BY: ccip-cron-chaos-and-load-eth - TEST_LOG_LEVEL: debug - DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable - GH_TOKEN: ${{ github.token }} - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-chaos-tests-with-load-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: CCIP load with chaos test - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Prepare Base64 TOML override for CCIP secrests - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" - - name: Run Load With Chaos Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - with: - test_command_to_run: cd ./integration-tests/ccip-tests && go test -timeout 2h -count=1 -json -test.parallel 4 -run '^TestLoadCCIPStableWithPodChaosDiffCommitAndExec' ./load 2>&1 | tee /tmp/gotest.log | gotestfmt - test_download_vendor_packages_command: make gomod - cl_repo: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - cl_image_tag: ${{ github.sha }} - artifacts_location: ./integration-tests/load/logs - publish_check_name: CCIP Chaos With Load Test Results - publish_report_paths: ./tests-chaos-with-load-report.xml - triggered_by: ${{ env.TEST_TRIGGERED_BY }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - CGO_ENABLED: "1" - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - ## Notify in slack if the job fails - - name: Notify Slack - if: failure() && github.event_name != 'workflow_dispatch' - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - with: - channel-id: "#ccip-testing" - slack-message: ":x: :mild-panic-intensifies: CCIP chaos with load tests failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" - ## Run Cleanup if the job succeeds - - name: cleanup - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/cleanup@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - with: - triggered_by: ${{ env.TEST_TRIGGERED_BY }} + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + chainlink_version: ${{ github.sha }} + require_chainlink_image_versions_in_qa_ecr: ${{ github.sha }} + test_trigger: E2E CCIP Chaos Tests + test_log_level: debug + slack_notification_after_tests: on_failure + slack_notification_after_tests_channel_id: '#ccip-testing' + slack_notification_after_tests_name: CCIP Chaos E2E Tests + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/ccip-client-compatibility-tests.yml b/.github/workflows/ccip-client-compatibility-tests.yml deleted file mode 100644 index ff0e4be25c6..00000000000 --- a/.github/workflows/ccip-client-compatibility-tests.yml +++ /dev/null @@ -1,743 +0,0 @@ -name: CCIP Client Compatibility Tests -on: - schedule: - - cron: "30 5 * * TUE,FRI" # Run every Tuesday and Friday at midnight + 30min EST - push: - tags: - - "*" - merge_group: - pull_request: - workflow_dispatch: - inputs: - chainlinkVersion: - description: commit SHA or tag of the Chainlink version to test - required: true - type: string - evmImplementations: - description: comma separated list of EVM implementations to test (ignored if base64TestList is used) - required: true - type: string - default: "geth,besu,nethermind,erigon" - latestVersionsNumber: - description: how many of latest images of EVM implementations to test with (ignored if base64TestList is used) - required: true - type: number - default: 3 - base64TestList: - description: base64 encoded list of tests to run (same as base64-ed output of testlistgenerator tool) - required: false - type: string - -env: - # TODO: TT-1470 - Update image names as we solidify new realease strategy - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/ccip - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - MOD_CACHE_VERSION: 2 - -jobs: - # Build Test Dependencies - - check-dependency-bump: - name: Check for go-ethereum dependency bump - if: github.event_name == 'pull_request' || github.event_name == 'merge_queue' - runs-on: ubuntu-latest - outputs: - dependency_changed: ${{ steps.changes.outputs.dependency_changed }} - steps: - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - fetch-depth: 0 - - name: Check for go.mod changes - id: changes - run: | - git fetch origin ${{ github.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 $?) - 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}') - - echo "Base branch version: $BASE_VERSION" - echo "PR branch version: $PR_VERSION" - - echo "Dependency version changed in the PR compared to the base branch." - echo "dependency_changed=true" >> $GITHUB_OUTPUT - else - echo "No changes to ethereum/go-ethereum dependency in the PR." - echo "PR branch version: $PR_VERSION" - echo "dependency_changed=false" >> $GITHUB_OUTPUT - fi - - should-run: - if: always() - name: Check if the job should run - needs: check-dependency-bump - runs-on: ubuntu-latest - outputs: - should_run: ${{ steps.should-run.outputs.should_run }} - eth_implementations : ${{ steps.should-run.outputs.eth_implementations }} - env: - GITHUB_REF_TYPE: ${{ github.ref_type }} - steps: - - name: Check if the job should run - id: should-run - run: | - if [ "${{ needs.check-dependency-bump.outputs.dependency_changed }}" == "true" ]; then - echo "Will run tests, because go-ethereum dependency was bumped" - echo "should_run=true" >> $GITHUB_OUTPUT - elif [ "$GITHUB_EVENT_NAME" = "schedule" ]; then - echo "Will run tests, because trigger event was $GITHUB_EVENT_NAME" - echo "should_run=true" >> $GITHUB_OUTPUT - elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then - echo "Will run tests, because trigger event was $GITHUB_EVENT_NAME" - echo "should_run=true" >> $GITHUB_OUTPUT - elif [ "$GITHUB_REF_TYPE" = "tag" ]; then - echo "Will run tests, because new tag was created" - echo "should_run=true" >> $GITHUB_OUTPUT - else - echo "Will not run tests" - echo "should_run=false" >> $GITHUB_OUTPUT - fi - - select-versions: - if: always() && needs.should-run.outputs.should_run == 'true' - name: Select Versions - needs: should-run - runs-on: ubuntu-latest - env: - RELEASED_DAYS_AGO: 4 - GITHUB_REF_TYPE: ${{ github.ref_type }} - outputs: - evm_implementations : ${{ steps.select-implementations.outputs.evm_implementations }} - chainlink_version: ${{ steps.select-chainlink-version.outputs.chainlink_version }} - latest_image_count: ${{ steps.get-image-count.outputs.image_count }} - steps: - # ghlatestreleasechecker is a tool to check if new release is available for a given repo - - name: Set Up ghlatestreleasechecker - shell: bash - run: | - go install github.com/smartcontractkit/chainlink-testing-framework/tools/ghlatestreleasechecker@v1.0.0 - - name: Select EVM implementations to test - id: select-implementations - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then - echo "Checking for new releases" - implementations_arr=() - new_geth=$(ghlatestreleasechecker "ethereum/go-ethereum" $RELEASED_DAYS_AGO) - if [ "$new_geth" != "none" ]; then - echo "New geth release found: $new_geth" - implementations_arr+=("geth") - fi - new_besu=$(ghlatestreleasechecker "hyperledger/besu" $RELEASED_DAYS_AGO) - if [ "new_besu" != "none" ]; then - echo "New besu release found: $new_besu" - implementations_arr+=("besu") - fi - new_erigon=$(ghlatestreleasechecker "ledgerwatch/erigon" $RELEASED_DAYS_AGO) - if [ "new_erigon" != "none" ]; then - echo "New erigon release found: $new_erigon" - implementations_arr+=("erigon") - fi - new_nethermind=$(ghlatestreleasechecker "nethermindEth/nethermind" $RELEASED_DAYS_AGO) - if [ "new_nethermind" != "none" ]; then - echo "New nethermind release found: $new_nethermind" - implementations_arr+=("nethermind") - fi - IFS=',' - eth_implementations="${implementations_arr[*]}" - echo "Found new releases for: $eth_implementations" - echo "evm_implementations=$eth_implementations" >> $GITHUB_OUTPUT - elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then - if [ -n "${{ github.event.inputs.base64TestList }}" ]; 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 - fi - else - echo "Will test all EVM implementations" - echo "evm_implementations=geth,besu,nethermind,erigon" >> $GITHUB_OUTPUT - fi - - name: Select Chainlink CCIP version - id: select-chainlink-version - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then - echo "Fetching latest Chainlink CCIP stable version" - implementations_arr=() - # we use 100 days since we really want the latest one, and it's highly improbable there won't be a release in last 100 days - chainlink_version=$(ghlatestreleasechecker "smartcontractkit/ccip" 100) - echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT - elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then - echo "Fetching Chainlink version from input" - if [ -n "${{ github.event.inputs.chainlinkVersion }}" ]; then - echo "Chainlink version provided in input" - chainlink_version="${{ github.event.inputs.chainlinkVersion }}" - else - echo "Chainlink version not provided in input. Using latest commit SHA." - chainlink_version=${{ github.sha }} - fi - echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT - elif [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then - echo "Fetching Chainlink version from PR's head commit" - chainlink_version="${{ github.event.pull_request.head.sha }}" - echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT - 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 }}" - echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT - elif [ "$GITHUB_REF_TYPE" = "tag" ]; then - echo "Fetching Chainlink version from tag" - chainlink_version="${{ github.ref_name }}" - echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT - else - echo "Unsupported trigger event. It's probably an issue with the pipeline definition. Please reach out to the Test Tooling team." - exit 1 - fi - echo "Will use following Chainlink version: $chainlink_version" - - name: Get image count - id: get-image-count - run: | - if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then - echo "Fetching latest image count from input" - if [ -n "${{ github.event.inputs.base64TestList }}" ]; then - echo "Base64-ed Test Input provided, ignoring latest image count" - else - image_count="${{ github.event.inputs.latestVersionsNumber }}" - echo "image_count=$image_count" >> $GITHUB_OUTPUT - fi - else - echo "Fetching default latest image count" - image_count=3 - echo "image_count=$image_count" >> $GITHUB_OUTPUT - fi - echo "Will use following latest image count: $image_count" - - check-ecr-images-exist: - name: Check images used as test dependencies exist in ECR - if: always() && needs.should-run.outputs.should_run == 'true' - environment: integration - permissions: - id-token: write - contents: read - needs: [should-run] - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - mirror: - - name: ethereum/client-go - expression: '^(alltools-v|v)[0-9]\.[0-9]+\.[0-9]+$' - - name: hyperledger/besu - expression: '^[0-9]+\.[0-9]+(\.[0-9]+)?$' - page_size: 300 - - name: thorax/erigon - expression: '^v[0-9]+\.[0-9]+\.[0-9]+$' - - name: nethermind/nethermind - expression: '^[0-9]+\.[0-9]+\.[0-9]+$' - - name: tofelb/ethereum-genesis-generator - expression: '^[0-9]+\.[0-9]+\.[0-9]+(\-slots\-per\-epoch)?' - steps: - - name: Update internal ECR if the latest Ethereum client image does not exist - uses: smartcontractkit/chainlink-testing-framework/.github/actions/update-internal-mirrors@5eea86ee4f7742b4e944561a570a6b268e712d9e # v1.30.3 - with: - aws_region: ${{ secrets.QA_AWS_REGION }} - role_to_assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - aws_account_number: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - image_name: ${{matrix.mirror.name}} - expression: ${{matrix.mirror.expression}} - page_size: ${{matrix.mirror.page_size}} - - build-chainlink: - if: always() && needs.should-run.outputs.should_run == 'true' - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - needs: [should-run, select-versions] - runs-on: ubuntu-latest - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: client-compatablility-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ needs.select-versions.outputs.chainlink_version }} - - name: Build Chainlink Image - uses: ./.github/actions/build-chainlink-image - with: - tag_suffix: "" - dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ needs.select-versions.outputs.chainlink_version }} - check_image_exists: 'true' - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - get-latest-available-images: - name: Get Latest EVM Implementation's Images - if: always() && needs.should-run.outputs.should_run == 'true' - environment: integration - runs-on: ubuntu-latest - needs: [check-ecr-images-exist, should-run, select-versions] - permissions: - id-token: write - contents: read - env: - LATEST_IMAGE_COUNT: ${{ needs.select-versions.outputs.latest_image_count }} - outputs: - geth_images: ${{ env.GETH_IMAGES }} - nethermind_images: ${{ env.NETHERMIND_IMAGES }} - besu_images: ${{ env.BESU_IMAGES }} - erigon_images: ${{ env.ERIGON_IMAGES }} - steps: - # Setup AWS creds - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - aws-region: ${{ secrets.QA_AWS_REGION }} - role-to-assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - role-duration-seconds: 3600 - # Login to ECR - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 - with: - mask-password: "true" - env: - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - # ecrimagefetcher is a tool to get latest images from ECR - - name: Set Up ecrimagefetcher - shell: bash - run: | - go install github.com/smartcontractkit/chainlink-testing-framework/tools/ecrimagefetcher@v1.0.1 - - name: Get latest docker images from ECR - if: ${{ github.event.inputs.base64TestList == '' }} - env: - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - ETH_IMPLEMENTATIONS: ${{ needs.select-versions.outputs.evm_implementations }} - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - if [[ "$ETH_IMPLEMENTATIONS" == *"geth"* ]]; then - geth_images=$(ecrimagefetcher 'ethereum/client-go' '^v[0-9]+\.[0-9]+\.[0-9]+$' ${{ env.LATEST_IMAGE_COUNT }}) - echo "GETH_IMAGES=$geth_images" >> $GITHUB_ENV - echo "Geth latest images: $geth_images" - fi - - if [[ "$ETH_IMPLEMENTATIONS" == *"nethermind"* ]]; then - nethermind_images=$(ecrimagefetcher 'nethermind/nethermind' '^[0-9]+\.[0-9]+\.[0-9]+$' ${{ env.LATEST_IMAGE_COUNT }}) - echo "NETHERMIND_IMAGES=$nethermind_images" >> $GITHUB_ENV - echo "Nethermind latest images: $nethermind_images" - fi - - if [[ "$ETH_IMPLEMENTATIONS" == *"besu"* ]]; then - # 24.3.3 is ignored as it doesn't support data & input fields in eth_call - besu_images=$(ecrimagefetcher 'hyperledger/besu' '^[0-9]+\.[0-9]+(\.[0-9]+)?$' ${{ env.LATEST_IMAGE_COUNT }} ">=24.5.1") - echo "BESU_IMAGES=$besu_images" >> $GITHUB_ENV - echo "Besu latest images: $besu_images" - fi - - if [[ "$ETH_IMPLEMENTATIONS" == *"erigon"* ]]; then - # 2.60.0 and 2.60.1 are ignored as they stopped working with CL node - erigon_images=$(ecrimagefetcher 'thorax/erigon' '^v[0-9]+\.[0-9]+\.[0-9]+$' ${{ env.LATEST_IMAGE_COUNT }} "> $GITHUB_ENV - echo "Erigon latest images: $erigon_images" - fi - - # End Build Test Dependencies - - prepare-compatibility-matrix: - name: Prepare Compatibility Matrix - if: always() && needs.should-run.outputs.should_run == 'true' - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [get-latest-available-images,should-run,select-versions] - runs-on: ubuntu-latest - env: - ETH_IMPLEMENTATIONS: ${{ needs.select-versions.outputs.evm_implementations }} - BASE64_TEST_LIST: ${{ github.event.inputs.base64TestList }} - outputs: - matrix: ${{ env.JOB_MATRIX_JSON }} - steps: - - name: Decode Base64 Test List Input if Set - if: env.BASE64_TEST_LIST != '' - run: | - echo "Decoding base64 tests list from the input" - DECODED_BASE64_TEST_LIST=$(echo $BASE64_TEST_LIST | base64 -d) - echo "Decoded input:" - echo "$DECODED_BASE64_TEST_LIST" - is_valid=$(echo "$DECODED_BASE64_TEST_LIST" | jq . > /dev/null 2>&1; echo $?) - if [ "$is_valid" -ne 0 ]; then - echo "Invalid base64 input. Please provide a valid base64 encoded JSON list of tests." - echo "Here is an example of valid JSON:" - cat <> $GITHUB_ENV - # testlistgenerator is a tool that builds a matrix of tests to run - - name: Set Up testlistgenerator - if: env.BASE64_TEST_LIST == '' - shell: bash - run: | - go install github.com/smartcontractkit/chainlink-testing-framework/tools/testlistgenerator@v1.1.0 - - name: Prepare matrix input - if: env.BASE64_TEST_LIST == '' - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - if [[ "$ETH_IMPLEMENTATIONS" == *"geth"* ]]; then - echo "Will test compatibility with geth" - testlistgenerator -o compatibility_test_list.json -p ccip -r TestSmokeCCIPForBidirectionalLane -f './ccip-tests/smoke/ccip_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "ccip-geth-compatibility-test" -w "SIMULATED_1,SIMULATED_2" -c 1337,2337 -n ubuntu-latest - else - echo "Will not test compatibility with geth" - fi - - if [[ "$ETH_IMPLEMENTATIONS" == *"besu"* ]]; then - echo "Will test compatibility with besu" - testlistgenerator -o compatibility_test_list.json -p ccip -r TestSmokeCCIPForBidirectionalLane -f './ccip-tests/smoke/ccip_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "ccip-besu-compatibility-test" -w "SIMULATED_BESU_NONDEV_1,SIMULATED_BESU_NONDEV_2" -c 1337,2337 -n ubuntu-latest - else - echo "Will not test compatibility with besu" - fi - - # TODO: Waiting for CCIP-2255 to be resolved - if [[ "$ETH_IMPLEMENTATIONS" == *"erigon"* ]]; then - echo "Will test compatibility with erigon" - testlistgenerator -o compatibility_test_list.json -p ccip -r TestSmokeCCIPForBidirectionalLane -f './ccip-tests/smoke/ccip_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "ccip-erigon-compatibility-test" -w "SIMULATED_1,SIMULATED_2" -c 1337,2337 -n ubuntu-latest - else - echo "Will not test compatibility with erigon" - fi - - # TODO: uncomment when nethermind flake reason is addressed - if [[ "$ETH_IMPLEMENTATIONS" == *"nethermind"* ]]; then - echo "Will not test compatibility with nethermind due to flakiness" - # echo "Will test compatibility with nethermind" - # testlistgenerator -o compatibility_test_list.json -p ccip -r TestSmokeCCIPForBidirectionalLane -f './ccip-tests/smoke/ccip_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "ccip-nethermind-compatibility-test" -w "SIMULATED_1,SIMULATED_2" -c 1337,2337 -n ubuntu-latest - else - echo "Will not test compatibility with nethermind" - fi - - jq . compatibility_test_list.json - echo "Adding human-readable name" - jq 'map(. + {visible_name: (.docker_image | split(",")[0] | split("=")[1])})' compatibility_test_list.json > compatibility_test_list_modified.json - jq . compatibility_test_list_modified.json - JOB_MATRIX_JSON=$(jq -c . compatibility_test_list_modified.json) - echo "JOB_MATRIX_JSON=${JOB_MATRIX_JSON}" >> $GITHUB_ENV - - run-client-compatibility-matrix: - name: CCIP Compatibility with ${{ matrix.evm_node.visible_name }} - if: always() && needs.should-run.outputs.should_run == 'true' - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, prepare-compatibility-matrix, should-run, select-versions] - env: - CHAINLINK_COMMIT_SHA: ${{ needs.select-versions.outputs.chainlink_version }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - strategy: - fail-fast: false - matrix: - evm_node: ${{fromJson(needs.prepare-compatibility-matrix.outputs.matrix)}} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ needs.select-versions.outputs.chainlink_version }} - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - selectedNetworks: ${{ matrix.evm_node.networks }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ needs.select-versions.outputs.chainlink_version }} - pyroscopeServer: ${{ !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-ccip-bidirectional-lane-${{ matrix.evm_node.name }} - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL_CI }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - - name: Prepare Base64 TOML override for CCIP secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - selectedNetworks: ${{ matrix.evm_node.networks }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ needs.select-versions.outputs.chainlink_version }} - lokiEndpoint: ${{ secrets.LOKI_URL_CI }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - customEvmNodes: ${{ matrix.evm_node.docker_image }} - evmNodeLogLevel: "trace" - - name: Prepare test log name - run: | - replace_special_chars() { - if [ -z "$1" ]; then - echo "Please provide a string as an argument." - return 1 - fi - - local input_string="$1" - - # Replace '/' with '-' - local modified_string="${input_string//\//-}" - - # Replace ':' with '-' - modified_string="${modified_string//:/-}" - - # Replace '.' with '-' - modified_string="${modified_string//./-}" - - echo "$modified_string" - } - echo "TEST_LOG_NAME=$(replace_special_chars "ccip-${{ matrix.evm_node.name }}-test-logs")" >> $GITHUB_ENV - - name: Print Test details - ${{ matrix.evm_node.docker_image }} - run: | - echo "EVM Implementation Docker Image: ${{ matrix.evm_node.docker_image }}" - echo "EVM Implementation Networks: ${{ matrix.evm_node.networks }}" - echo "Test identifier: ${{ matrix.evm_node.name }}" - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=2 ${{ matrix.evm_node.run }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci - test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ needs.select-versions.outputs.chainlink_version }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ env.TEST_LOG_NAME }} - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/ccip-tests/smoke/logs/* - /tmp/gotest.log - publish_check_name: ${{ matrix.evm_node.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@1587f59bfd626b668d303abbc90fee41b12397e6 # v2.3.23 - with: - test_directories: ./integration-tests/smoke/,./integration-tests/ccip-tests/smoke/ - - start-slack-thread: - name: Start Slack Thread - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' }} - environment: integration - outputs: - thread_ts: ${{ steps.slack.outputs.thread_ts }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [run-client-compatibility-matrix,should-run,select-versions] - steps: - - name: Debug Result - run: echo ${{ join(needs.*.result, ',') }} - - name: Main Slack Notification - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - id: slack - with: - channel-id: ${{ secrets.QA_CCIP_SLACK_CHANNEL }} - payload: | - { - "attachments": [ - { - "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "CCIP Compatibility Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", - "emoji": true - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ contains(join(needs.*.result, ','), 'failure') && 'Some tests failed! Notifying ' || 'All Good!' }}" - } - }, - { - "type": "divider" - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ needs.select-versions.outputs.chainlink_version }}|${{ needs.select-versions.outputs.chainlink_version }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" - } - } - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - - parse-test-results: - name: Parse Test Results - if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [run-client-compatibility-matrix,should-run] - outputs: - base64_parsed_results: ${{ steps.get-test-results.outputs.base64_parsed_results }} - steps: - # workflowresultparser is a tool to get job results from a workflow run - - name: Set Up workflowresultparser - shell: bash - run: | - go install github.com/smartcontractkit/chainlink-testing-framework/tools/workflowresultparser@v1.0.0 - - name: Get and parse Test Results - shell: bash - id: get-test-results - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^CCIP Compatibility with (.*)$" -namedKey="CCIP" -outputFile=output.json - - echo "base64_parsed_results=$(base64 -w 0 output.json)" >> $GITHUB_OUTPUT - - display-test-results: - name: Aggregated test results - if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' && needs.parse-test-results.result == 'success' - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [start-slack-thread, should-run, select-versions, parse-test-results] - steps: - # asciitable is a tool that prints results in a nice ASCII table - - name: Set Up asciitable - shell: bash - run: | - go install github.com/smartcontractkit/chainlink-testing-framework/tools/asciitable@v1.0.2 - - name: Print aggregated test results - shell: bash - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - raw_results="$(echo ${{ needs.parse-test-results.outputs.base64_parsed_results }} | base64 -d)" - echo $raw_results > input.json - asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "CCIP" --namedKey "CCIP" - - echo - echo "AGGREGATED RESULTS" - cat output.txt - - echo "## Aggregated EVM Implementations compatibility results summary" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - cat output.txt >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - - post-test-results-to-slack: - name: Post Test Results - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' }} - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [start-slack-thread,should-run,select-versions] - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ needs.select-versions.outputs.chainlink_version }} - - name: Get test results for CCIP - id: get-product-results - shell: bash - run: | - raw_results="$(echo ${{ needs.parse-test-results.outputs.base64_parsed_results }} | base64 -d)" - product_result=$(echo "$raw_results" | jq -c "select(has(\"CCIP\")) | .CCIP[]") - if [ -n "$product_result" ]; then - base64_result=$(echo $product_result | base64 -w 0) - echo "base64_result=$base64_result" >> $GITHUB_OUTPUT - else - echo "No results found for CCIP" - echo "base64_result=" >> $GITHUB_OUTPUT - fi - - name: Post Test Results to Slack - uses: ./.github/actions/notify-slack-jobs-result - with: - github_token: ${{ github.token }} - github_repository: ${{ github.repository }} - workflow_run_id: ${{ github.run_id }} - github_job_name_regex: ^CCIP Compatibility with (.*?)$ - message_title: CCIP Compatibility Test Results - slack_channel_id: ${{ secrets.QA_CCIP_SLACK_CHANNEL }} - slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} - slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} - base64_parsed_results: ${{ steps.get-product-results.outputs.base64_result }} diff --git a/.github/workflows/ccip-live-network-tests.yml b/.github/workflows/ccip-live-network-tests.yml deleted file mode 100644 index 6649a881b97..00000000000 --- a/.github/workflows/ccip-live-network-tests.yml +++ /dev/null @@ -1,313 +0,0 @@ -name: CCIP Live Network Tests -on: - # TODO: TT-1470 - Turn back on as we solidify new realease and image strategy - # schedule: - # - cron: '0 */6 * * *' - workflow_dispatch: - inputs: - base64_test_input : # base64 encoded toml for test input - description: 'Base64 encoded toml test input' - required: false - slackMemberID: - description: 'Slack member ID to notify' - required: false - test_type: - description: 'Type of test to run' - required: false - type: choice - options: - - 'load' - - 'smoke' - -# Only run 1 of this workflow at a time per PR -concurrency: - group: live-testnet-tests - cancel-in-progress: true - -env: - # TODO: TT-1470 - Update image names as we solidify new realease strategy - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - CHAINLINK_VERSION: ${{ github.sha}} - CHAINLINK_TEST_VERSION: ${{ github.sha}} - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests:${{ github.sha }} - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - AWS_ECR_REPO_PUBLIC_REGISTRY: public.ecr.aws - -jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu20.04-16cores-64GB - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Check if image exists - id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 - with: - repository: chainlink - tag: ${{ env.CHAINLINK_VERSION }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Build Image - if: steps.check-image.outputs.exists == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 - env: - GH_TOKEN: ${{ github.token }} - with: - cl_repo: smartcontractkit/chainlink-ccip - cl_ref: ${{ env.CHAINLINK_VERSION }} - push_tag: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink:${{ env.CHAINLINK_VERSION }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-on-demand-live-testnet-tests-build-chainlink-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - build-test-image: - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Image - runs-on: ubuntu20.04-16cores-64GB - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-on-demand-live-testnet-tests-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Build Test Image - uses: ./.github/actions/build-test-image - with: - tag: ${{ env.CHAINLINK_TEST_VERSION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - ccip-load-test: - name: CCIP Load Test - environment: integration - runs-on: ubuntu-latest - strategy: - matrix: - config: [mainnet.toml] - needs: [ build-chainlink, build-test-image ] - # if the event is a scheduled event or the test type is load and no previous job failed - if: ${{ (github.event_name == 'schedule' || inputs.test_type == 'load') && !contains(needs.*.result, 'failure') }} - permissions: - issues: read - checks: write - pull-requests: write - id-token: write - contents: read - env: - CHAINLINK_ENV_USER: ${{ github.actor }} - SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} - SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} - TEST_LOG_LEVEL: info - REF_NAME: ${{ github.head_ref || github.ref_name }} - ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} - - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-on-demand-live-testnet-tests-load-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: CCIP Load Test - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Prepare Base64 TOML override - shell: bash - run: | - # this key secrets.QA_SHARED_803C_KEY has a story behind it. To know more, see CCIP-2875 and SECHD-16575 tickets. - BASE64_NETWORK_CONFIG=$(echo $BASE64_NETWORK_CONFIG | base64 -w 0 -d | sed -e 's/evm_key/${{ secrets.QA_SHARED_803C_KEY }}/g' | base64 -w 0) - echo ::add-mask::$BASE64_NETWORK_CONFIG - echo "BASE64_NETWORK_CONFIG=$BASE64_NETWORK_CONFIG" >> "$GITHUB_ENV" - SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - echo ::add-mask::$SLACK_USER - echo "SLACK_USER=$SLACK_USER" >> "$GITHUB_ENV" - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - BASE64_CCIP_CONFIG_OVERRIDE=$(jq -r '.inputs.base64_test_input' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - fi - if [[ "${{ github.event_name }}" == "schedule" ]]; then - BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ./integration-tests/ccip-tests/testconfig/override/${{ matrix.config }}) - echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "SLACK_USER=${{ secrets.QA_SLACK_USER }}" >> $GITHUB_ENV - fi - - name: step summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_TEST_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - - name: Prepare Base64 TOML override for CCIP secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 - env: - TEST_SUITE: load - TEST_ARGS: -test.timeout 900h - DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable - RR_MEM: 8Gi - RR_CPU: 4 - DETACH_RUNNER: true - TEST_TRIGGERED_BY: ccip-load-test-ci - with: - test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -json -run ^TestLoadCCIPStableRPS$ ./load 2>&1 | tee /tmp/gotest.log | gotestfmt - test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - triggered_by: ${{ env.TEST_TRIGGERED_BY }} - artifacts_location: ./integration-tests/load/logs/payload_ccip.json - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - should_cleanup: false - - ccip-smoke-test: - name: CCIP smoke Test - environment: integration - runs-on: ubuntu-latest - needs: [ build-chainlink, build-test-image ] - # if the event is a scheduled event or the test type is load and no previous job failed - if: ${{ github.event_name == 'workflow_dispatch' && inputs.test_type == 'smoke' && !contains(needs.*.result, 'failure') }} - permissions: - issues: read - checks: write - pull-requests: write - id-token: write - contents: read - env: - CHAINLINK_ENV_USER: ${{ github.actor }} - SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} - SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} - TEST_LOG_LEVEL: info - REF_NAME: ${{ github.head_ref || github.ref_name }} - ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} - - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-on-demand-live-testnet-tests-smoke-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: CCIP Smoke Test - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Prepare Base64 TOML override - shell: bash - run: | - BASE64_NETWORK_CONFIG=$(echo $BASE64_NETWORK_CONFIG | base64 -w 0 -d | sed -e 's/evm_key/${{ secrets.QA_SHARED_803C_KEY }}/g' | base64 -w 0) - echo ::add-mask::$BASE64_NETWORK_CONFIG - echo "BASE64_NETWORK_CONFIG=$BASE64_NETWORK_CONFIG" >> "$GITHUB_ENV" - SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - echo ::add-mask::$SLACK_USER - echo "SLACK_USER=$SLACK_USER" >> "$GITHUB_ENV" - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - BASE64_CCIP_CONFIG_OVERRIDE=$(jq -r '.inputs.base64_test_input' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - fi - - name: step summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_TEST_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - - name: Prepare Base64 TOML override for CCIP secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 - env: - TEST_SUITE: smoke - TEST_ARGS: -test.timeout 900h - DETACH_RUNNER: true - DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable - RR_MEM: 8Gi - RR_CPU: 4 - TEST_TRIGGERED_BY: ccip-smoke-test-ci - with: - test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -p 30 -json -run ^TestSmokeCCIPForBidirectionalLane$ ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt - test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - triggered_by: ${{ env.TEST_TRIGGERED_BY }} - artifacts_location: ./integration-tests/smoke/logs/payload_ccip.json - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - cache_key_id: ccip-smoke-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - should_cleanup: false \ No newline at end of file diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index 0d53d803d1c..038888f8049 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -1,5 +1,5 @@ name: CCIP Load Test -on: +on: push: paths: - '**/*ccip*' @@ -10,283 +10,56 @@ on: - '*' workflow_dispatch: inputs: - base64_test_input: # base64 encoded toml for test input - description: 'Base64 encoded toml test input' + test_config_override_path: + description: Path to a test config file used to override the default test config required: false + type: string + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string + chainlink_version: + description: Chainlink image version to use. Commit sha if not provided + required: false + type: string # Only run 1 of this workflow at a time per PR concurrency: group: load-ccip-tests-chainlink-${{ github.ref }} cancel-in-progress: true -env: - # TODO: TT-1470 - Update image names as we solidify new realease strategy - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - CHAINLINK_VERSION: ${{ github.sha}} - INPUT_CHAINLINK_TEST_VERSION: ${{ github.sha}} - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests:${{ github.sha }} - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - AWS_ECR_REPO_PUBLIC_REGISTRY: public.ecr.aws - MOD_CACHE_VERSION: 1 - jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu20.04-16cores-64GB - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Check if image exists - id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - with: - repository: chainlink - tag: ${{ env.CHAINLINK_VERSION }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Build Image - if: steps.check-image.outputs.exists == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - env: - GH_TOKEN: ${{ github.token }} - with: - cl_repo: smartcontractkit/chainlink - cl_ref: ${{ env.CHAINLINK_VERSION }} - push_tag: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink:${{ env.CHAINLINK_VERSION }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-load-test-build-chainlink-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - build-test-image: - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Image - runs-on: ubuntu20.04-16cores-64GB - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-load-test-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Build Test Image - uses: ./.github/actions/build-test-image - with: - tag: ${{ env.INPUT_CHAINLINK_TEST_VERSION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - ccip-load-test: - environment: integration - needs: [ build-chainlink, build-test-image ] - if: ${{ always() && !contains(needs.*.result, 'failure') }} - permissions: - issues: read - checks: write - pull-requests: write - id-token: write - contents: read - env: - CHAINLINK_ENV_USER: ${{ github.actor }} - SLACK_USER: ${{ inputs.slackMemberID }} + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + test_trigger: E2E CCIP Load Tests + test_config_override_path: ${{ inputs.test_config_override_path }} + chainlink_version: ${{ inputs.chainlink_version || github.sha }} + slack_notification_after_tests: always + slack_notification_after_tests_channel_id: '#ccip-testing' + slack_notification_after_tests_name: CCIP E2E Load Tests + test_image_suites: ccip-load + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} - SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} - TEST_LOG_LEVEL: info - REF_NAME: ${{ github.head_ref || github.ref_name }} - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} - strategy: - fail-fast: false - matrix: - type: - - name: stable-load - run: ^TestLoadCCIPStableRPS$ - os: ubuntu-latest - - name: load-with-arm-curse-uncurse - run: ^TestLoadCCIPStableRPSAfterARMCurseAndUncurse$ - config_path: ./integration-tests/ccip-tests/testconfig/tomls/load-with-arm-curse-uncurse.toml - os: ubuntu-latest - runs-on: ${{ matrix.type.os }} - name: CCIP ${{ matrix.type.name }} - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ccip-load-test-${{ matrix.type.name }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: CCIP ${{ matrix.type.name }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Sets env vars - shell: bash - run: | - # if the matrix.type.config_path is set, use it as the override config - if [ -n "${{ matrix.type.config_path }}" ]; then - echo "BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ${{ matrix.type.config_path }})" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ${{ matrix.type.config_path }})" >> $GITHUB_ENV - fi - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - BASE64_CCIP_CONFIG_OVERRIDE=$(jq -r '.inputs.base64_test_input' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - if [ -n "${BASE64_CCIP_CONFIG_OVERRIDE}" && "$BASE64_CCIP_CONFIG_OVERRIDE" != "null"]; then - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - fi - fi - - name: step summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.INPUT_CHAINLINK_TEST_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - - name: Prepare Base64 TOML override for CCIP secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 - env: - TEST_SUITE: load - TEST_ARGS: -test.timeout 900h - DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable - RR_MEM: 8Gi - RR_CPU: 4 - TEST_TRIGGERED_BY: ccip-load-test-ci-${{ matrix.type.name }} - with: - test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -json -run ${{ matrix.type.run }} ./load 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci - test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - triggered_by: ${{ env.TEST_TRIGGERED_BY }} - publish_check_name: ${{ matrix.type.name }} - artifacts_location: ./integration-tests/load/logs/payload_ccip.json - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - should_cleanup: "true" - - # Reporting Jobs - start-slack-thread: - name: Start Slack Thread - if: ${{ failure() && needs.ccip-load-test.result != 'skipped' && needs.ccip-load-test.result != 'cancelled' }} - environment: integration - outputs: - thread_ts: ${{ steps.slack.outputs.thread_ts }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [ccip-load-test] - steps: - - name: Debug Result - run: echo ${{ join(needs.*.result, ',') }} - - name: Main Slack Notification - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - id: slack - with: - channel-id: "#ccip-testing" - payload: | - { - "attachments": [ - { - "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "CCIP load tests results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", - "emoji": true - } - }, - { - "type": "divider" - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/${{contains(github.ref_name, 'release') && 'releases/tag' || 'tree'}}/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" - } - } - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - - post-test-results-to-slack: - name: Post Test Results - if: ${{ failure() && needs.start-slack-thread.result != 'skipped' && needs.start-slack-thread.result != 'cancelled' }} - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: start-slack-thread - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Post Test Results - uses: ./.github/actions/notify-slack-jobs-result - with: - github_token: ${{ github.token }} - github_repository: ${{ github.repository }} - workflow_run_id: ${{ github.run_id }} - github_job_name_regex: ^CCIP (.*)$ - message_title: CCIP Jobs - slack_channel_id: "#ccip-testing" - slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} - slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} - - # End Reporting Jobs diff --git a/.github/workflows/chain-selectors-check.yml b/.github/workflows/chain-selectors-check.yml index c2b58e68d44..01803fb8e36 100644 --- a/.github/workflows/chain-selectors-check.yml +++ b/.github/workflows/chain-selectors-check.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup Go uses: ./.github/actions/setup-go diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 5e16b90c400..dba7729c972 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: files-changed @@ -50,13 +50,8 @@ jobs: - '!core/**/*.json' - '!core/chainlink.goreleaser.Dockerfile' - '!core/chainlink.Dockerfile' - contracts: - - contracts/**/*.sol - - '!contracts/**/*.t.sol' core-changeset: - added: '.changeset/**' - contracts-changeset: - - added: 'contracts/.changeset/**' - name: Check for changeset tags for core id: changeset-tags @@ -71,7 +66,7 @@ jobs: version: ^9.0.0 - name: Setup node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@v4.0.4 if: ${{ steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true' }} with: node-version: 20 @@ -87,19 +82,34 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # we need to set the top level directory for the jira-tracing action manually + # because now we are working with two repositories and automatic detection would + # select the repository with jira-tracing and not the chainlink repository + - name: Setup git top level directory + id: find-git-top-level-dir + run: echo "top_level_dir=$(pwd)" >> $GITHUB_OUTPUT + + - name: Checkout .Github repository + uses: actions/checkout@v4.2.1 + with: + repository: smartcontractkit/.github + ref: 9aed33e5298471f20a3d630d711b96ae5538728c # jira-tracing@0.2.0 + path: ./dot_github + - name: Update Jira ticket for core id: jira if: ${{ steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true' }} shell: bash - working-directory: ./.github/scripts/jira + working-directory: ./dot_github run: | echo "COMMIT_MESSAGE=$(git log -1 --pretty=format:'%s')" >> $GITHUB_ENV - pnpm install && pnpm issue:update + pnpm install --filter jira-tracing && pnpm --filter jira-tracing issue:update env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - JIRA_HOST: ${{ secrets.JIRA_HOST }} + JIRA_HOST: ${{ vars.JIRA_HOST }} JIRA_USERNAME: ${{ secrets.JIRA_USERNAME }} JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + GIT_TOP_LEVEL_DIR: ${{ steps.find-git-top-level-dir.outputs.top_level_dir }} CHAINLINK_VERSION: ${{ steps.chainlink-version.outputs.chainlink_version }} PR_TITLE: ${{ github.event.pull_request.title }} BRANCH_NAME: ${{ github.event.pull_request.head.ref }} @@ -120,19 +130,6 @@ jobs: mode: ${{ steps.files-changed.outputs.core-changeset == 'false' && 'upsert' || 'delete' }} create_if_not_exists: ${{ steps.files-changed.outputs.core-changeset == 'false' && 'true' || 'false' }} - - name: Make a comment - uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 - if: ${{ steps.files-changed.outputs.contracts == 'true' }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - message: | - I see you updated files related to `contracts`. Please run `pnpm changeset` in the `contracts` directory to add a changeset. - reactions: eyes - comment_tag: changeset-contracts - mode: ${{ steps.files-changed.outputs.contracts-changeset == 'false' && 'upsert' || 'delete' }} - create_if_not_exists: ${{ steps.files-changed.outputs.contracts-changeset == 'false' && 'true' || 'false' }} - - name: Check for new changeset for core if: ${{ (steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true') && steps.files-changed.outputs.core-changeset == 'false' }} shell: bash @@ -140,13 +137,6 @@ jobs: echo "Please run pnpm changeset to add a changeset for core and include in the text at least one tag." exit 1 - - name: Check for new changeset for contracts - if: ${{ steps.files-changed.outputs.contracts == 'true' && steps.files-changed.outputs.contracts-changeset == 'false' }} - shell: bash - run: | - echo "Please run pnpm changeset to add a changeset for contracts." - exit 1 - - name: Make a comment uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 if: ${{ steps.files-changed.outputs.core-changeset == 'true' }} @@ -169,15 +159,3 @@ jobs: run: | echo "Please include at least one tag in the core changeset file" exit 1 - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: chainlink-changesets - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Changeset checker - continue-on-error: true diff --git a/.github/workflows/changesets-preview-pr.yml b/.github/workflows/changesets-preview-pr.yml index 94dc1635c4e..0a65f53b693 100644 --- a/.github/workflows/changesets-preview-pr.yml +++ b/.github/workflows/changesets-preview-pr.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: change @@ -34,7 +34,7 @@ jobs: version: ^9.0.0 - name: Setup node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@v4.0.4 if: steps.change.outputs.core-changeset == 'true' with: node-version: 20 diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index bb12304ef9a..8cfe3c928e8 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -14,7 +14,8 @@ on: merge_group: pull_request: schedule: - - cron: "0 0 * * *" + # Every 6 hours + - cron: "0 0,6,12,18 * * *" workflow_dispatch: inputs: distinct_run_name: @@ -37,7 +38,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -45,7 +46,9 @@ jobs: with: filters: | changes: + - 'integration-tests/deployment/**' - '!integration-tests/**' + - 'integration-tests/deployment/**' - name: Ignore Filter On Workflow Dispatch if: ${{ github.event_name == 'workflow_dispatch' }} id: ignore-filter @@ -55,10 +58,16 @@ jobs: # 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]' }} name: lint - runs-on: ubuntu22.04-8cores-32GB + 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 + runs-on: ubuntu-24.04-8cores-32GB-ARM needs: [filter] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 - name: Golang Lint uses: ./.github/actions/golangci-lint if: ${{ needs.filter.outputs.changes == 'true' }} @@ -68,8 +77,22 @@ jobs: gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + + - name: Check Time For Slack Notify + if: ${{ failure() && github.event.schedule != ''}} + id: check-time + shell: bash + run: | + # Get the current hour (24-hour format) + current_hour=$(date +"%H") + + # Check if the current hour is 00 (midnight) + if [ "$current_hour" -eq "00" ]; then + echo "midnight=true" >> $GITHUB_OUTPUT + fi + - name: Notify Slack - if: ${{ failure() && github.event.schedule != '' }} + if: ${{ failure() && github.event.schedule != '' && steps.check-time.outputs.midnight == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 env: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} @@ -89,6 +112,11 @@ jobs: - cmd: go_core_tests id: core_unit os: ubuntu22.04-32cores-128GB + printResults: true + - cmd: go_core_ccip_deployment_tests + id: core_unit + os: ubuntu22.04-32cores-128GB + printResults: true - cmd: go_core_race_tests id: core_race # use 64cores for overnight runs only due to massive number of runs from PRs @@ -106,10 +134,10 @@ jobs: contents: read steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup node if: ${{ needs.filter.outputs.changes == 'true' }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@v4.0.4 - name: Setup NodeJS if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-nodejs @@ -167,7 +195,7 @@ jobs: echo "COUNT=50" >> $GITHUB_ENV - name: Install gotestloghelper if: ${{ needs.filter.outputs.changes == 'true' }} - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/gotestloghelper@v1.1.1 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/gotestloghelper@v1.50.0 - name: Run tests if: ${{ needs.filter.outputs.changes == 'true' }} id: run-tests @@ -177,9 +205,11 @@ jobs: CL_DATABASE_URL: ${{ env.DB_URL }} run: ./tools/bin/${{ matrix.type.cmd }} ./... - name: Print Filtered Test Results - if: ${{ failure() && matrix.type.cmd == 'go_core_tests' && needs.filter.outputs.changes == 'true' && steps.run-tests.conclusion == 'failure' }} + if: ${{ failure() && needs.filter.outputs.changes == 'true' && steps.run-tests.conclusion == 'failure' }} run: | - cat output.txt | gotestloghelper -ci + if [[ "${{ matrix.type.printResults }}" == "true" ]]; then + cat output.txt | gotestloghelper -ci + fi - name: Print Races id: print-races if: ${{ failure() && matrix.type.cmd == 'go_core_race_tests' && needs.filter.outputs.changes == 'true' }} @@ -199,7 +229,7 @@ jobs: working-directory: ./.github/actions/setup-postgres - name: Store logs artifacts if: ${{ needs.filter.outputs.changes == 'true' && always() }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@v4.4.3 with: name: ${{ matrix.type.cmd }}_logs path: | @@ -208,6 +238,7 @@ jobs: ./race.* ./coverage.txt ./postgres_logs.txt + retention-days: 7 - name: Notify Slack if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.ref == 'refs/heads/develop') && needs.filter.outputs.changes == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 @@ -226,25 +257,12 @@ jobs: resultsFile='{"testType":"go","filePath":"./output.txt"}' echo "path_output=${resultsFile}" >> $GITHUB_OUTPUT fi - - name: Collect Metrics - if: ${{ needs.filter.outputs.changes == 'true' && always() }} - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ matrix.type.id }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Core Tests (${{ matrix.type.cmd }}) - test-results-file: ${{ steps.collect-path-output.outputs.path_output }} - test-results-batch-split-size: "524288" # 512KB - continue-on-error: true detect-flakey-tests: needs: [filter, core] name: Flakey Test Detection runs-on: ubuntu-latest - if: ${{ always() && github.actor != 'dependabot[bot]' }} + if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} env: CL_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable permissions: @@ -252,58 +270,45 @@ jobs: contents: read steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup node - if: ${{ needs.filter.outputs.changes == 'true' }} - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@v4.0.4 - name: Setup NodeJS - if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-nodejs with: prod: "true" - name: Setup Go - if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-go - name: Setup Postgres - if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-postgres - name: Touching core/web/assets/index.html - if: ${{ needs.filter.outputs.changes == 'true' }} run: mkdir -p core/web/assets && touch core/web/assets/index.html - name: Download Go vendor packages - if: ${{ needs.filter.outputs.changes == 'true' }} run: go mod download - name: Replace chainlink-evm deps - if: ${{ needs.filter.outputs.changes == 'true' && inputs.evm-ref != ''}} + 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 - if: ${{ needs.filter.outputs.changes == 'true' }} run: go build -o chainlink.test . - name: Setup DB - if: ${{ needs.filter.outputs.changes == 'true' }} run: ./chainlink.test local db preparetest - name: Load test outputs - if: ${{ needs.filter.outputs.changes == 'true' }} - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@v4.1.8 with: name: go_core_tests_logs path: ./artifacts - name: Delete go_core_tests_logs/coverage.txt - if: ${{ needs.filter.outputs.changes == 'true' }} 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 - if: ${{ needs.filter.outputs.changes == 'true' }} run: go build ./tools/flakeytests/cmd/runner - name: Re-run tests - if: ${{ needs.filter.outputs.changes == 'true' }} env: GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} - GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} GITHUB_EVENT_PATH: ${{ github.event_path }} GITHUB_EVENT_NAME: ${{ github.event_name }} GITHUB_REPO: ${{ github.repository }} @@ -312,21 +317,21 @@ jobs: ./runner \ -grafana_auth=$GRAFANA_INTERNAL_BASIC_AUTH \ -grafana_host=$GRAFANA_INTERNAL_HOST \ - -grafana_org_id=$GRAFANA_INTERNAL_TENANT_ID \ -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/go_core_tests*/output.txt` + `ls -R ./artifacts/output.txt` - name: Store logs artifacts - if: ${{ needs.filter.outputs.changes == 'true' && always() }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + if: ${{ always() }} + uses: actions/upload-artifact@v4.4.3 with: name: flakey_test_runner_logs path: | ./output.txt + retention-days: 7 scan: name: SonarQube Scan @@ -335,11 +340,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: fetch-depth: 0 # fetches all history for all tags and branches to provide more metadata for sonar reports - name: Download all workflow run artifacts - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@v4.1.8 - name: Check and Set SonarQube Report Paths shell: bash @@ -395,18 +400,6 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} SONAR_SCANNER_OPTS: "-Xms6g -Xmx8g" - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ci-core-sonarqube - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: SonarQube Scan - continue-on-error: true - clean: name: Clean Go Tidy & Generate if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') && github.actor != 'dependabot[bot]' }} @@ -420,7 +413,7 @@ jobs: run: | echo "## \`skip-smoke-tests\` label is active, skipping E2E smoke tests" >>$GITHUB_STEP_SUMMARY exit 0 - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 0 - name: Setup Go @@ -431,7 +424,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 - - run: | + - name: make generate + run: | make rm-mocked make generate - name: Ensure clean after generate @@ -439,14 +433,3 @@ jobs: - run: make gomodtidy - name: Ensure clean after tidy run: git diff --minimal --exit-code - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ci-core-generate - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Clean Go Tidy & Generate - continue-on-error: true diff --git a/.github/workflows/ci-protobuf.yml b/.github/workflows/ci-protobuf.yml index d832939ded9..3931ed8d302 100644 --- a/.github/workflows/ci-protobuf.yml +++ b/.github/workflows/ci-protobuf.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup buf uses: bufbuild/buf-setup-action@35c243d7f2a909b1d4e40399b348a7fdab27d78d # v1.34.0 @@ -22,15 +22,3 @@ jobs: BASE_BRANCH: ${{ github.base_ref }} with: against: "${REPO_URL}.git#branch=${BASE_BRANCH}" - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ci-protobuf - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: buf-breaking - continue-on-error: true diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml index 2c1024310f2..350811888bc 100644 --- a/.github/workflows/ci-scripts.yml +++ b/.github/workflows/ci-scripts.yml @@ -6,9 +6,17 @@ on: 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@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 - name: Golang Lint uses: ./.github/actions/golangci-lint with: @@ -24,7 +32,7 @@ jobs: test-scripts: runs-on: ubuntu-latest steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 - name: Setup Go uses: ./.github/actions/setup-go with: @@ -34,14 +42,3 @@ jobs: shell: bash working-directory: core/scripts run: go test ./... - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ci-test-scripts - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: test-scripts - continue-on-error: true diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index ff776c7906e..784d761862b 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -48,7 +48,7 @@ jobs: dependency_changed: ${{ steps.changes.outputs.dependency_changed }} steps: - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: fetch-depth: 0 - name: Check for go.mod changes @@ -98,15 +98,21 @@ jobs: id: should-run run: | if [ "${{ needs.check-dependency-bump.outputs.dependency_changed }}" == "true" ]; then + echo "## Build trigger" >> $GITHUB_STEP_SUMMARY + echo "go-ethereum dependency bump" >> $GITHUB_STEP_SUMMARY echo "Will run tests, because go-ethereum dependency was bumped" echo "should_run=true" >> $GITHUB_OUTPUT elif [ "$GITHUB_EVENT_NAME" = "schedule" ]; then + echo "## Build trigger" >> $GITHUB_STEP_SUMMARY + echo "schedule" >> $GITHUB_STEP_SUMMARY echo "Will run tests, because trigger event was $GITHUB_EVENT_NAME" echo "should_run=true" >> $GITHUB_OUTPUT elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then echo "Will run tests, because trigger event was $GITHUB_EVENT_NAME" echo "should_run=true" >> $GITHUB_OUTPUT elif [ "$GITHUB_REF_TYPE" = "tag" ]; then + echo "## Build trigger" >> $GITHUB_STEP_SUMMARY + echo "new tag" >> $GITHUB_STEP_SUMMARY echo "Will run tests, because new tag was created" echo "should_run=true" >> $GITHUB_OUTPUT else @@ -125,6 +131,7 @@ jobs: outputs: evm_implementations: ${{ steps.select-implementations.outputs.evm_implementations }} chainlink_version: ${{ steps.select-chainlink-version.outputs.chainlink_version }} + chainlink_image_version: ${{ steps.select-chainlink-version.outputs.chainlink_image_version }} latest_image_count: ${{ steps.get-image-count.outputs.image_count }} chainlink_ref_path: ${{ steps.select-chainlink-version.outputs.cl_ref_path }} steps: @@ -163,7 +170,7 @@ jobs: implementations_arr+=("nethermind") fi new_reth=$(ghlatestreleasechecker "paradigmxyz/reth" $RELEASED_DAYS_AGO) - if [ "new_reth" != "none" ]; then + if [ "$new_reth" != "none" ]; then echo "New reth release found: $new_reth" implementations_arr+=("reth") fi @@ -197,34 +204,43 @@ jobs: echo "Fetching latest Chainlink stable version" implementations_arr=() # we use 100 days since we really want the latest one, and it's highly improbable there won't be a release in last 100 days - chainlink_version=$(ghlatestreleasechecker "smartcontractkit/chainlink" 100) + chainlink_version=$(ghlatestreleasechecker "smartcontractkit/chainlink" 100) + chainlink_image_version=$chainlink_version cl_ref_path="releases" elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then echo "Fetching Chainlink version from input" if [ -n "${{ github.event.inputs.chainlinkVersion }}" ]; then echo "Chainlink version provided in input" - chainlink_version="${{ github.event.inputs.chainlinkVersion }}" + chainlink_version="${{ github.event.inputs.chainlinkVersion }}" if [[ "$chainlink_version" =~ ^[0-9a-f]{40}$ ]]; then cl_ref_path="commit" + chainlink_image_version=$chainlink_version else cl_ref_path="releases" + # strip the 'v' from the version, because we tag our Docker images without it + chainlink_image_version="${chainlink_version#v}" fi else echo "Chainlink version not provided in input. Using latest commit SHA." chainlink_version=${{ github.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_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_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 }}" + # strip the 'v' from the version, because we tag our Docker images without it + chainlink_image_version="${chainlink_version#v}" cl_ref_path="releases" else echo "Unsupported trigger event. It's probably an issue with the pipeline definition. Please reach out to the Test Tooling team." @@ -232,6 +248,8 @@ jobs: fi echo "Will use following Chainlink version: $chainlink_version" echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + echo "Will use following Chainlink Docker image version: $chainlink_image_version" + echo "chainlink_image_version=$chainlink_image_version" >> $GITHUB_OUTPUT echo "cl_ref_path=$cl_ref_path" >> $GITHUB_OUTPUT - name: Get image count id: get-image-count @@ -306,7 +324,7 @@ jobs: needs: [should-run, select-versions] steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: ref: ${{ needs.select-versions.outputs.chainlink_version }} - name: Build Chainlink Image @@ -314,20 +332,12 @@ jobs: with: tag_suffix: "" dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ needs.select-versions.outputs.chainlink_version }} + # for tagged releases Docker image version is different from the Chainlink version (v2.13.0 -> 2.13.0) + # for all other cases (PRs, commits, etc.) Docker image version is the same as the Chainlink version + git_commit_sha: ${{ needs.select-versions.outputs.chainlink_image_version }} check_image_exists: "true" AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: client-compatablility-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true get-latest-available-images: name: Get Latest EVM Implementation's Images @@ -583,7 +593,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ needs.select-versions.outputs.chainlink_version }} @@ -624,19 +634,10 @@ jobs: # comment_on_pr: false # theme: 'dark' - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 + uses: smartcontractkit/.github/actions/ctf-run-tests@b6e37806737eef87e8c9137ceeb23ef0bff8b1db # ctf-run-tests@0.1.0 with: test_command_to_run: cd ./integration-tests && touch .root_dir && go test -timeout 30m -count=1 -json ${{ matrix.evm_node.run }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_chainlink_version: ${{ needs.select-versions.outputs.chainlink_version }} - test_config_selected_networks: ${{ env.SELECTED_NETWORKS}} - test_config_logging_run_id: ${{ github.run_id }} - test_config_test_log_collect: ${{ vars.TEST_LOG_COLLECT }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_private_ethereum_network_execution_layer: ${{ matrix.evm_node.eth_implementation || 'geth' }} - test_config_private_ethereum_network_custom_docker_image: ${{ matrix.evm_node.docker_image }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ needs.select-versions.outputs.chainlink_version }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: ${{ env.TEST_LOG_NAME }} artifacts_location: | @@ -654,22 +655,30 @@ jobs: should_tidy: "false" go_coverage_src_dir: /var/tmp/go-coverage go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ci-client-compatability-${{ matrix.eth_client }}-testnet - DEFAULT_PYROSCOPE_ENABLED: "true" - - - name: Print failed test summary + env: + E2E_TEST_SELECTED_NETWORK: ${{ env.SELECTED_NETWORKS}} + E2E_TEST_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + E2E_TEST_CHAINLINK_VERSION: ${{ needs.select-versions.outputs.chainlink_image_version }} + E2E_TEST_LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + E2E_TEST_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + E2E_TEST_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + E2E_TEST_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + E2E_TEST_PYROSCOPE_SERVER_URL: ${{ secrets.QA_PYROSCOPE_INSTANCE }} + E2E_TEST_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + E2E_TEST_PYROSCOPE_ENVIRONMENT: ci-client-compatability-${{ matrix.eth_client }}-testnet + E2E_TEST_PYROSCOPE_ENABLED: "true" + E2E_TEST_LOGGING_RUN_ID: ${{ github.run_id }} + E2E_TEST_LOG_COLLECT: ${{ vars.TEST_LOG_COLLECT }} + E2E_TEST_LOG_STREAM_LOG_TARGETS: ${{ vars.LOGSTREAM_LOG_TARGETS }} + E2E_TEST_PRIVATE_ETHEREUM_EXECUTION_LAYER: ${{ matrix.evm_node.eth_implementation || 'geth' }} + E2E_TEST_PRIVATE_ETHEREUM_ETHEREUM_VERSION: auto_fill # Auto fill the version based on the docker image + E2E_TEST_PRIVATE_ETHEREUM_CUSTOM_DOCKER_IMAGE: ${{ matrix.evm_node.docker_image }} + + - name: Show Grafana url in test summary if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - + uses: smartcontractkit/.github/actions/ctf-show-grafana-in-test-summary@b6e37806737eef87e8c9137ceeb23ef0bff8b1db # ctf-show-grafana-in-test-summary@0.1.0 + start-slack-thread: name: Start Slack Thread if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') @@ -682,7 +691,7 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: [run-client-compatibility-matrix, should-run, select-versions] + needs: [run-client-compatibility-matrix, should-run, select-versions, build-chainlink, prepare-compatibility-matrix] steps: - name: Debug Result run: echo ${{ join(needs.*.result, ',') }} @@ -695,7 +704,7 @@ jobs: { "attachments": [ { - "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", + "color": "${{ (contains(join(needs.*.result, ','), 'failure') || needs.build-chainlink.result == 'failure') && '#C62828' || '#2E7D32' }}", "blocks": [ { "type": "header", @@ -709,7 +718,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "${{ contains(join(needs.*.result, ','), 'failure') && format('Some tests failed, notifying ', secrets.COMPAT_SLACK_NOTIFICATION_HANDLE) || 'All Good!' }}" + "text": "${{ needs.prepare-compatibility-matrix.result == 'failure' && 'Failed to prepare test matrix, notifying ' || needs.build-chainlink.result == 'failure' && 'Failed to build Chainlink image, notifying ' || contains(join(needs.*.result, ','), 'failure') && format('Some tests failed, notifying ', secrets.COMPAT_SLACK_NOTIFICATION_HANDLE) || 'All Good!' }}" } }, { @@ -843,7 +852,7 @@ jobs: - runlog steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: ref: ${{ needs.select-versions.outputs.chainlink_version }} - name: Get test results for ${{ matrix.product }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 88f5de5668d..70cb8e35481 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -22,11 +22,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Set up Go if: ${{ matrix.language == 'go' }} - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@v5.0.2 with: go-version-file: 'go.mod' @@ -41,15 +41,3 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@65c74964a9ed8c44ed9f19d4bbc5757a6a8e9ab9 # codeql-bundle-v2.16.1 - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: chainlink-codeql - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Analyze ${{ matrix.language }} - continue-on-error: true diff --git a/.github/workflows/crib-integration-test.yml b/.github/workflows/crib-integration-test.yml index 0dda07f285e..c0d7a19fc19 100644 --- a/.github/workflows/crib-integration-test.yml +++ b/.github/workflows/crib-integration-test.yml @@ -1,5 +1,8 @@ name: CRIB Integration Tests on: + pull_request: + paths: + - ".github/workflows/crib-integration-test.yml" schedule: - cron: "0 1 * * *" workflow_call: @@ -16,7 +19,7 @@ jobs: actions: read steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 with: @@ -73,22 +76,23 @@ jobs: echo $GITHUB_WORKSPACE - name: Deploy and validate CRIB Environment for Core - uses: smartcontractkit/.github/actions/crib-deploy-environment@9a4954089045a765eca4bac68f396b2df5a5ea25 # crib-deploy-environment@0.7.1 + uses: smartcontractkit/.github/actions/crib-deploy-environment@a4058228b4b9b6e30bb0e2b883e3b4f0cd447970 # crib-deploy-environment@2.1.0 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-stage: ${{ secrets.AWS_ACCOUNT_ID_STAGE }} ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} ingress-base-domain: ${{ secrets.INGRESS_BASE_DOMAIN_STAGE }} k8s-cluster-name: ${{ secrets.AWS_K8S_CLUSTER_NAME_STAGE }} - devspace-profiles: "local-dev-simulated-core-ocr1" + command: "core-dev-simulated-core-ocr1" crib-alert-slack-webhook: ${{ secrets.CRIB_ALERT_SLACK_WEBHOOK }} - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + product-image: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }}/chainlink + product-image-tag: develop + - uses: actions/checkout@v4.2.1 - name: Setup go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@v5.0.2 with: go-version-file: "go.mod" - name: Run CRIB integration test @@ -102,8 +106,10 @@ jobs: 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 TestCRIB + go test -v -run TestCRIBChaos - name: Destroy CRIB Environment id: destroy if: always() && steps.deploy-crib.outputs.devspace-namespace != '' diff --git a/.github/workflows/delete-deployments.yml b/.github/workflows/delete-deployments.yml index 1eb839e462e..547b29bceec 100644 --- a/.github/workflows/delete-deployments.yml +++ b/.github/workflows/delete-deployments.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Clean up integration environment uses: ./.github/actions/delete-deployments @@ -21,14 +21,3 @@ jobs: num-of-pages: 3 # We start with page 2 because usually the first 200 deployments are still active, so we cannot delete them starting-page: 2 - - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: chainlink-delete-deployments - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Clean up integration environment deployments - continue-on-error: true diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml index ede188de645..0678728f92c 100644 --- a/.github/workflows/dependency-check.yml +++ b/.github/workflows/dependency-check.yml @@ -11,7 +11,7 @@ jobs: changes: ${{ steps.changes.outputs.src }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: @@ -25,11 +25,11 @@ jobs: needs: [changes] steps: - name: Check out code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Set up Go if: needs.changes.outputs.src == 'true' - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@v5.0.2 with: go-version-file: 'go.mod' id: go @@ -43,15 +43,3 @@ jobs: uses: sonatype-nexus-community/nancy-github-action@726e338312e68ecdd4b4195765f174d3b3ce1533 # v1.0.3 with: nancyVersion: "v1.0.39" - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: dependency-vulnerability-check - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Go - continue-on-error: true diff --git a/.github/workflows/gha-workflow-validation.yml b/.github/workflows/gha-workflow-validation.yml deleted file mode 100644 index 1ec502432ca..00000000000 --- a/.github/workflows/gha-workflow-validation.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: GHA Workflow Validation - -on: - pull_request: - -jobs: - - validate-worfklow-changes: - name: Validate Workflow Changes - permissions: - contents: read - pull-requests: write - actions: read - runs-on: ubuntu-latest - steps: - - name: GHA Workflow Validator - uses: smartcontractkit/.github/actions/gha-workflow-validator@d316f66b2990ea4daa479daa3de6fc92b00f863e # gha-workflow-validator@0.2.0 - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: lint-gh-workflows - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Validate Workflow Changes - continue-on-error: true diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml index 673614bf2c2..3be161005f8 100644 --- a/.github/workflows/integration-chaos-tests.yml +++ b/.github/workflows/integration-chaos-tests.yml @@ -7,148 +7,33 @@ on: - "*" workflow_dispatch: -env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} - TEST_SUITE: chaos - TEST_ARGS: -test.timeout 1h - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Check if image exists - id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - repository: chainlink - tag: ${{ github.sha }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Build Image - if: steps.check-image.outputs.exists == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-image@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - cl_repo: smartcontractkit/chainlink - cl_ref: ${{ github.sha }} - push_tag: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink:${{ github.sha }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - name: Print Chainlink Image Built - id: push - run: | - echo "### chainlink node image tag used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: e2e-chaos-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - build-test-runner: - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Runner Image - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Build Test Image - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: e2e-chaos-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Runner Image - continue-on-error: true - - chaos-tests: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - name: EVM Pods Chaos Tests - runs-on: ubuntu-latest - needs: [build-test-runner, build-chainlink] - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: e2e-chaos-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: EVM Pods Chaos Tests - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Prepare Base64 TOML config - env: - CHAINLINK_VERSION: ${{ github.sha }} - run: | - echo ::add-mask::$CHAINLINK_IMAGE - - cat << EOF > config.toml - [Network] - selected_networks=["SIMULATED"] - - [ChainlinkImage] - image="$CHAINLINK_IMAGE" - version="$CHAINLINK_VERSION" - EOF - - BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - with: - test_command_to_run: cd integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 ./chaos 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - artifacts_location: ./integration-tests/chaos/logs - publish_check_name: EVM Pods Chaos Test Results - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Upload test log - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: failure() - with: - name: Test Results Log - path: /tmp/gotest.log - retention-days: 7 + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + chainlink_version: ${{ github.sha }} + require_chainlink_image_versions_in_qa_ecr: ${{ github.sha }} + test_trigger: E2E Chaos Tests + test_log_level: debug + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/integration-staging-tests.yml b/.github/workflows/integration-staging-tests.yml deleted file mode 100644 index d092b2bca1c..00000000000 --- a/.github/workflows/integration-staging-tests.yml +++ /dev/null @@ -1,132 +0,0 @@ -# NEEDS ADJUSTING TO TOML CONFIG BEFORE USING!! -name: E2E Functions staging tests - -on: -# TODO: enable when env will be stable -# schedule: -# - cron: "0 0 * * *" - workflow_dispatch: - inputs: - network: - description: Blockchain network (testnet) - type: choice - default: "MUMBAI" - options: - - "MUMBAI" - test_type: - description: Test type - type: choice - default: "mumbai_functions_soak_test_real" - options: - - "mumbai_functions_soak_test_http" - - "mumbai_functions_stress_test_http" - - "mumbai_functions_soak_test_only_secrets" - - "mumbai_functions_stress_test_only_secrets" - - "mumbai_functions_soak_test_real" - - "mumbai_functions_stress_test_real" -# TODO: disabled, need GATI access -# - "gateway_secrets_set_soak_test" -# - "gateway_secrets_list_soak_test" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - e2e-soak-test: - environment: sdlc - runs-on: ubuntu22.04-8cores-32GB - permissions: - contents: read - id-token: write - env: - LOKI_URL: ${{ secrets.LOKI_URL }} - LOKI_TOKEN: ${{ secrets.LOKI_TOKEN }} - SELECTED_NETWORKS: ${{ inputs.network }} - SELECTED_TEST: ${{ inputs.test_type }} - MUMBAI_URLS: ${{ secrets.FUNCTIONS_STAGING_MUMBAI_URLS }} - MUMBAI_KEYS: ${{ secrets.FUNCTIONS_STAGING_MUMBAI_KEYS }} - WASP_LOG_LEVEL: info - steps: - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Prepare Base64 TOML override - env: - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-smoke-${{ matrix.product }}-sepolia - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - run: | - convert_to_toml_array() { - local IFS=',' - local input_array=($1) - local toml_array_format="[" - - for element in "${input_array[@]}"; do - toml_array_format+="\"$element\"," - done - - toml_array_format="${toml_array_format%,}]" - echo "$toml_array_format" - } - - if [ -n "$PYROSCOPE_SERVER" ]; then - pyroscope_enabled=true - else - pyroscope_enabled=false - fi - - cat << EOF > config.toml - [Common] - chainlink_node_funding=0.5 - - [ChainlinkImage] - image="$CHAINLINK_IMAGE" - version="${{ github.sha }}" - - [Pyroscope] - enabled=$pyroscope_enabled - server_url="$PYROSCOPE_SERVER" - environment="$PYROSCOPE_ENVIRONMENT" - key_secret="$PYROSCOPE_KEY" - - [Logging] - run_id="$RUN_ID" - - [Logging.LogStream] - log_targets=$log_targets - - [Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_URL" - basic_auth_secret="$LOKI_BASIC_AUTH" - - [Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - - [Network] - selected_networks=["sepolia"] - - [Network.RpcHttpUrls] - sepolia = $(convert_to_toml_array "$SEPOLIA_HTTP_URLS") - - [Network.RpcWsUrls] - sepolia = $(convert_to_toml_array "$SEPOLIA_URLS") - - [Network.WalletKeys] - sepolia = $(convert_to_toml_array "$EVM_KEYS") - EOF - - BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Run E2E soak tests - run: | - cd integration-tests/load/functions - if [[ $SELECTED_TEST == mumbai_functions* ]]; then - go test -v -timeout 6h -run TestFunctionsLoad/$SELECTED_TEST - elif [[ $SELECTED_TEST == gateway* ]]; then - go test -v -timeout 6h -run TestGatewayLoad/$SELECTED_TEST - fi \ No newline at end of file diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml index de551fedce1..ff1ada16a13 100644 --- a/.github/workflows/integration-tests-publish.yml +++ b/.github/workflows/integration-tests-publish.yml @@ -20,18 +20,8 @@ jobs: name: Publish Integration Test Image runs-on: ubuntu22.04-16cores-64GB steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: publish-e2e-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Publish Integration Test Image - continue-on-error: true - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Setup Other Tags If Not Workflow Dispatch @@ -40,7 +30,7 @@ jobs: run: | echo "other_tags=${ECR_TAG}" >> $GITHUB_OUTPUT - name: Build Image - uses: ./.github/actions/build-test-image + uses: smartcontractkit/.github/actions/ctf-build-test-image@a5e4f4c8fbb8e15ab2ad131552eca6ac83c4f4b3 # ctf-build-test-image@0.1.0 with: other_tags: ${{ steps.tags.outputs.other_tags }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -75,18 +65,8 @@ jobs: name: Build Chainlink Image ${{ matrix.image.name }} runs-on: ubuntu22.04-8cores-32GB steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image ${{ matrix.image.name }} - continue-on-error: true - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: ref: ${{ github.sha }} - name: Build Chainlink Image diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 2b7a3b728d1..e70e9df621a 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -50,7 +50,7 @@ jobs: steps: - run: echo "${{github.event_name}}" - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} @@ -71,10 +71,10 @@ jobs: echo "should-enforce=$SHOULD_ENFORCE" >> $GITHUB_OUTPUT - name: Enforce CTF Version if: steps.condition-check.outputs.should-enforce == 'true' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/.github/actions/ctf-check-mod-version@21b0189c5fdca0318617d259634b1a91e6d80262 # ctf-check-mod-version@0.0.0 with: go-project-path: ./integration-tests - module-name: github.com/smartcontractkit/chainlink-testing-framework + module-name: github.com/smartcontractkit/chainlink-testing-framework/lib enforce-semantic-tag: "true" changes: environment: integration @@ -84,7 +84,7 @@ jobs: if: github.actor != 'dependabot[bot]' steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} @@ -92,80 +92,59 @@ jobs: id: changes with: filters: | - changes: + github_ci_changes: + - '.github/workflows/integration-tests.yml' + - '.github/workflows/run-e2e-tests-reusable-workflow.yml' + - '.github/e2e-tests.yml' + core_changes: - '**/*.go' - '**/*go.sum' - '**/*go.mod' - - '.github/workflows/integration-tests.yml' - '**/*Dockerfile' - 'core/**/migrations/*.sql' - 'core/**/config/**/*.toml' - 'integration-tests/**/*.toml' - ccip-changes: + ccip_changes: - '**/*ccip*' - '**/*ccip*/**' - name: Ignore Filter On Workflow Dispatch if: ${{ github.event_name == 'workflow_dispatch' }} id: ignore-filter run: echo "changes=true" >> $GITHUB_OUTPUT - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-check-paths - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Check Paths That Require Tests To Run - continue-on-error: true outputs: - src: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.changes }} + github_ci_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.github_ci_changes }} + core_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.core_changes }} + ccip_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.ccip_changes }} - build-lint-integration-tests: - name: Build and Lint ${{ matrix.project.name }} - runs-on: ubuntu22.04-8cores-32GB + 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 + id: e2e-tests path: ./integration-tests - cache-id: e2e + cache_id: e2e-tests - name: load id: load path: ./integration-tests/load - cache-id: load + cache_id: load steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-build-lint-${{ matrix.project.id }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build and Lint ${{ matrix.project.name }} - continue-on-error: true - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} - name: Setup Go - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 + 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: core-${{ matrix.project.cache-id }}-${{ env.MOD_CACHE_VERSION }} + cache_key_id: ${{ matrix.project.cache_id }} cache_restore_only: "true" - - name: Build Go - run: | - cd ${{ matrix.project.path }} - go build ./... - go test -run=^# ./... - name: Lint Go uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 with: @@ -196,19 +175,8 @@ jobs: runs-on: ubuntu22.04-8cores-32GB needs: [changes, enforce-ctf-version] steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image ${{ matrix.image.name }} - continue-on-error: true - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} @@ -222,7 +190,7 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} set-git-config: "true" - name: Build Chainlink Image - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + if: needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true' || github.event_name == 'workflow_dispatch' uses: ./.github/actions/build-chainlink-image with: tag_suffix: ${{ matrix.image.tag-suffix }} @@ -232,970 +200,231 @@ jobs: AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} dep_evm_sha: ${{ inputs.evm-ref }} - compare-tests: - needs: [changes] - runs-on: ubuntu-latest - name: Compare/Build Automation Test List - outputs: - automation-matrix: ${{ env.AUTOMATION_JOB_MATRIX_JSON }} - lp-matrix: ${{ env.LP_JOB_MATRIX_JSON }} - 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 - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref }} - - name: Compare Test Lists - run: | - cd ./integration-tests - ./scripts/compareTestList.sh ./smoke/automation_test.go - ./scripts/compareTestList.sh ./smoke/keeper_test.go - ./scripts/compareTestList.sh ./smoke/log_poller_test.go - - name: Build Test Matrix Lists - id: build-test-matrix-list - run: | - cd ./integration-tests - MATRIX_JSON_AUTOMATION=$(./scripts/buildTestMatrixList.sh ./smoke/automation_test.go automation ubuntu-latest 1) - MATRIX_JSON_KEEPER=$(./scripts/buildTestMatrixList.sh ./smoke/keeper_test.go keeper ubuntu-latest 1) - COMBINED_ARRAY=$(jq -c -n "$MATRIX_JSON_AUTOMATION + $MATRIX_JSON_KEEPER") - echo "combined array = ${COMBINED_ARRAY}" - echo "event name = $GITHUB_EVENT_NAME" - - LOG_POLLER_MATRIX_JSON=$(./scripts/buildTestMatrixList.sh ./smoke/log_poller_test.go log_poller ubuntu-latest 1) - echo "LP_JOB_MATRIX_JSON=${LOG_POLLER_MATRIX_JSON}" >> $GITHUB_ENV - - # if we running a PR against the develop branch we should only run the automation tests unless we are in the merge group event - if [[ "$GITHUB_EVENT_NAME" == "merge_group" ]]; then - echo "We are in a merge_group event, run both automation and keepers tests" - echo "AUTOMATION_JOB_MATRIX_JSON=${COMBINED_ARRAY}" >> $GITHUB_ENV - else - echo "we are not in a merge_group event, if this is a PR to develop run only automation tests, otherwise run everything because we could be running against a release branch" - target_branch=$(cat $GITHUB_EVENT_PATH | jq -r .pull_request.base.ref) - if [[ "$target_branch" == "develop" ]]; then - echo "only run automation tests" - echo "AUTOMATION_JOB_MATRIX_JSON=${MATRIX_JSON_AUTOMATION}" >> $GITHUB_ENV - else - echo "run both automation and keepers tests" - echo "AUTOMATION_JOB_MATRIX_JSON=${COMBINED_ARRAY}" >> $GITHUB_ENV - fi - fi - - eth-smoke-tests-matrix-automation: - if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} - environment: integration + run-core-e2e-tests-for-pr: + name: Run Core E2E Tests For PR permissions: + actions: read checks: write pull-requests: write id-token: write contents: read - needs: - [build-chainlink, changes, compare-tests, build-lint-integration-tests] - env: - SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - strategy: - fail-fast: false - matrix: - product: ${{fromJson(needs.compare-tests.outputs.automation-matrix)}} - runs-on: ${{ matrix.product.os }} - name: ETH Smoke Tests ${{ matrix.product.name }} - steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-${{ matrix.product.name }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - this-job-name: ETH Smoke Tests ${{ matrix.product.name }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Go Test Command - id: build-go-test-command - run: | - # if the matrix.product.run is set, use it for a different command - if [ "${{ matrix.product.run }}" != "" ]; then - echo "run_command=${{ matrix.product.run }} ./smoke/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" - else - echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" - fi - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - id: setup-gap - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - ## Run this step when changes that require tests to be run are made - - name: Run Tests - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_chainlink_version: ${{ inputs.evm-ref || github.sha }} - test_config_selected_networks: ${{ env.SELECTED_NETWORKS }} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_test_log_collect: ${{ vars.TEST_LOG_COLLECT }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ inputs.evm-ref || github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.product.name }}-test-artifacts - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - ./integration-tests/smoke/seth_artifacts/ - /tmp/gotest.log - publish_check_name: ${{ matrix.product.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.product.pyroscope_env == '' || !startsWith(github.ref, 'refs/tags/') && 'false' || 'true' }} - - - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - timeout-minutes: 2 - continue-on-error: true - with: - name: cl-node-coverage-data-${{ matrix.product.name }} - path: .covdata - retention-days: 1 - - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@70ccaef155381025e411cf7cd1fa5ef8f668ed75 # v2.3.25 - - eth-smoke-tests-matrix-log-poller: - if: ${{ !(contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') || github.event_name == 'workflow_dispatch') || inputs.distinct_run_name != '' }} - environment: integration + 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@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + workflow_name: Run Core E2E Tests For PR + chainlink_version: ${{ inputs.evm-ref || github.sha }} + chainlink_upgrade_version: ${{ github.sha }} + test_path: .github/e2e-tests.yml + test_trigger: PR E2E Core Tests + upload_cl_node_coverage_artifact: true + upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ + enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + + run-core-e2e-tests-for-merge-queue: + name: Run Core E2E Tests For Merge Queue permissions: + actions: read checks: write pull-requests: write id-token: write contents: read - needs: - [build-chainlink, changes, compare-tests, build-lint-integration-tests] - env: - SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - strategy: - fail-fast: false - matrix: - product: ${{fromJson(needs.compare-tests.outputs.lp-matrix)}} - runs-on: ${{ matrix.product.os }} - name: ETH Smoke Tests ${{ matrix.product.name }} - steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-${{ matrix.product.name }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ETH Smoke Tests ${{ matrix.product.name }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Go Test Command - id: build-go-test-command - run: | - # if the matrix.product.run is set, use it for a different command - if [ "${{ matrix.product.run }}" != "" ]; then - echo "run_command=${{ matrix.product.run }} ./smoke/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" - else - echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" - fi - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - id: setup-gap - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - ## Run this step when changes that require tests to be run are made - - name: Run Tests - if: needs.changes.outputs.src == 'true' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_chainlink_version: ${{ inputs.evm-ref || github.sha }} - test_config_selected_networks: ${{ env.SELECTED_NETWORKS }} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_test_log_collect: ${{ vars.TEST_LOG_COLLECT }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ inputs.evm-ref || github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.product.name }}-test-artifacts - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - ./integration-tests/smoke/seth_artifacts/ - /tmp/gotest.log - publish_check_name: ${{ matrix.product.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.product.pyroscope_env == '' || !startsWith(github.ref, 'refs/tags/') && 'false' || 'true' }} - - - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - timeout-minutes: 2 - continue-on-error: true - with: - name: cl-node-coverage-data-${{ matrix.product.name }} - path: .covdata - retention-days: 1 - - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - - eth-smoke-tests-matrix-ccip: - if: steps.changes.outputs.ccip-changes == 'true' && ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} - environment: integration + 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@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + workflow_name: Run Core E2E Tests For Merge Queue + chainlink_version: ${{ inputs.evm-ref || github.sha }} + chainlink_upgrade_version: ${{ github.sha }} + test_path: .github/e2e-tests.yml + test_trigger: Merge Queue E2E Core Tests + upload_cl_node_coverage_artifact: true + upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ + enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + # Notify Test Tooling team in slack when merge queue tests fail + slack_notification_after_tests: on_failure + slack_notification_after_tests_channel_id: "#team-test-tooling-internal" + slack_notification_after_tests_name: Core E2E Tests In Merge Queue + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + + run-ccip-e2e-tests-for-pr: + name: Run CCIP E2E Tests For PR permissions: actions: read checks: write pull-requests: write id-token: write contents: read - needs: [build-chainlink, changes, build-lint-integration-tests] - env: - SELECTED_NETWORKS: SIMULATED - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - strategy: - fail-fast: false - matrix: - product: - - name: ccip-smoke - nodes: 1 - os: ubuntu-latest - file: ccip - dir: ccip-tests/smoke - run: -run ^TestSmokeCCIPForBidirectionalLane$ - - name: ccip-smoke-1.4-pools - nodes: 1 - os: ubuntu-latest - file: ccip - dir: ccip-tests/smoke - run: -run ^TestSmokeCCIPForBidirectionalLane$ - config_path: ./integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml - - name: ccip-smoke-usdc - nodes: 1 - os: ubuntu-latest - file: ccip - dir: ccip-tests/smoke - run: -run ^TestSmokeCCIPForBidirectionalLane$ - config_path: ./integration-tests/ccip-tests/testconfig/tomls/usdc_mock_deployment.toml - - name: ccip-smoke-db-compatibility - nodes: 1 - os: ubuntu-latest - file: ccip - dir: ccip-tests/smoke - run: -run ^TestSmokeCCIPForBidirectionalLane$ - config_path: ./integration-tests/ccip-tests/testconfig/tomls/db-compatibility.toml - - name: ccip-smoke-rate-limit - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPRateLimit$ - - name: ccip-smoke-rate-limit - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPTokenPoolRateLimits$ - - name: ccip-smoke-multicall - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPMulticall$ - - name: ccip-smoke-manual-exec - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas$ - - name: ccip-smoke-on-ramp-limits - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPOnRampLimits$ - - name: ccip-smoke-off-ramp-capacity - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPOffRampCapacityLimit$ - - name: ccip-smoke-off-ramp-agg-rate-limit - nodes: 1 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPOffRampAggRateLimit$ - - name: ccip-smoke-leader-lane - nodes: 15 - dir: ccip-tests/smoke - os: ubuntu-latest - file: ccip - run: -run ^TestSmokeCCIPForBidirectionalLane$ - config_path: ./integration-tests/ccip-tests/testconfig/tomls/leader-lane.toml - runs-on: ${{ matrix.product.os }} - name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }} - steps: - # Handy for debugging resource usage - # - name: Collect Workflow Telemetry - # uses: catchpoint/workflow-telemetry-action@v2 - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-${{ matrix.product.id }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Go Test Command - id: build-go-test-command - run: | - # if dir is provided use it, otherwise use the smoke dir - if [ "${{ matrix.product.dir }}" != "" ]; then - dir=${{ matrix.product.dir }} - else - dir=smoke - fi - # if the matrix.product.run is set, use it for a different command - if [ "${{ matrix.product.run }}" != "" ]; then - echo "run_command=${{ matrix.product.run }} ./${dir}/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" - else - echo "run_command=./${dir}/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" - fi - - name: Check for "enable tracing" label - id: check-label - run: | - label=$(jq -r '.pull_request.labels[]?.name // empty' "$GITHUB_EVENT_PATH") - - if [[ -n "$label" ]]; then - if [[ "$label" == "enable tracing" ]]; then - echo "Enable tracing label found." - echo "trace=true" >> $GITHUB_OUTPUT - else - echo "Enable tracing label not found." - echo "trace=false" >> $GITHUB_OUTPUT - fi - else - echo "No labels present or labels are null." - echo "trace=false" >> $GITHUB_OUTPUT - fi - - - name: Setup Grafana and OpenTelemetry - id: docker-setup - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - # Create network - docker network create --driver bridge tracing - - # Make trace directory - cd integration-tests/smoke/ - mkdir ./traces - chmod -R 777 ./traces - - # Switch directory - cd ../../.github/tracing - - # Create a Docker volume for traces - # docker volume create otel-traces - - # Start OpenTelemetry Collector - # Note the user must be set to the same user as the runner for the trace data to be accessible - docker run -d --network=tracing --name=otel-collector \ - -v $PWD/otel-collector-ci.yaml:/etc/otel-collector.yaml \ - -v $PWD/../../integration-tests/smoke/traces:/tracing \ - --user "$(id -u):$(id -g)" \ - -p 4317:4317 otel/opentelemetry-collector:0.88.0 --config=/etc/otel-collector.yaml - - - name: Locate Docker Volume - id: locate-volume - if: false - run: | - echo "VOLUME_PATH=$(docker volume inspect --format '{{ .Mountpoint }}' otel-traces)" >> $GITHUB_OUTPUT - - - name: Show Otel-Collector Logs - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - docker logs otel-collector - - - name: Set Override Config - id: set_override_config - run: | - # if the matrix.product.config_path is set, use it as the override config - if [ "${{ matrix.product.config_path }}" != "" ]; then - echo "base_64_override=$(base64 -w 0 -i ${{ matrix.product.config_path }})" >> "$GITHUB_OUTPUT" - fi - - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - id: setup-gap - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - - name: Prepare Base64 CCIP TOML secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - selectedNetworks: SIMULATED_1,SIMULATED_2 - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - - ## Run this step when changes that require tests to be run are made - - name: Run Tests - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_chainlink_version: ${{ inputs.evm-ref || github.sha }} - test_config_selected_networks: ${{ env.SELECTED_NETWORKS }} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_test_log_collect: ${{ vars.TEST_LOG_COLLECT }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ inputs.evm-ref || github.sha }}${{ matrix.product.tag_suffix }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.product.name }}${{ matrix.product.tag_suffix }}-test-logs - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - /tmp/gotest.log - publish_check_name: ${{ matrix.product.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.product.pyroscope_env == '' || !startsWith(github.ref, 'refs/tags/') && 'false' || 'true' }} - - - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - timeout-minutes: 2 - continue-on-error: true - with: - name: cl-node-coverage-data-${{ matrix.product.name }}-${{ matrix.product.tag_suffix }} - path: .covdata - retention-days: 1 - - # Run this step when changes that do not need the test to run are made - - name: Run Setup - if: needs.changes.outputs.src == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_download_vendor_packages_command: cd ./integration-tests && go mod download - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - - - name: Show Otel-Collector Logs - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - docker logs otel-collector - - - name: Permissions on traces - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - ls -l ./integration-tests/smoke/traces - - - name: Upload Trace Data - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - with: - name: trace-data - path: ./integration-tests/smoke/traces/trace-data.json - - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directories: ./integration-tests/smoke/ - - - eth-smoke-tests-matrix: - if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} - environment: integration + 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@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + workflow_name: Run CCIP E2E Tests For PR + chainlink_version: ${{ inputs.evm-ref || github.sha }} + chainlink_upgrade_version: ${{ github.sha }} + test_path: .github/e2e-tests.yml + test_trigger: PR E2E CCIP Tests + upload_cl_node_coverage_artifact: true + upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ + enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + + run-ccip-e2e-tests-for-merge-queue: + name: Run CCIP E2E Tests For Merge Queue permissions: actions: read checks: write pull-requests: write id-token: write contents: read - needs: [build-chainlink, changes, build-lint-integration-tests] - env: - SELECTED_NETWORKS: SIMULATED - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - strategy: - fail-fast: false - matrix: - product: - - name: runlog - id: runlog - nodes: 2 - os: ubuntu-latest - pyroscope_env: "ci-smoke-runlog-evm-simulated" - - name: cron - id: cron - nodes: 2 - os: ubuntu-latest - pyroscope_env: "ci-smoke-cron-evm-simulated" - - name: flux - id: flux - nodes: 1 - os: ubuntu-latest - pyroscope_env: "ci-smoke-flux-evm-simulated" - - name: ocr - id: ocr - nodes: 2 - os: ubuntu-latest - file: ocr - pyroscope_env: ci-smoke-ocr-evm-simulated - - name: reorg_above_finality - id: reorg_above_finality - nodes: 1 - os: ubuntu-latest - file: reorg_above_finality - pyroscope_env: ci-smoke-reorg-above-finality-evm-simulated - - name: ocr2 - id: ocr2 - nodes: 6 - os: ubuntu22.04-16cores-64GB - file: ocr2 - pyroscope_env: ci-smoke-ocr2-evm-simulated - - name: ocr2 - id: ocr2-plugins - nodes: 6 - os: ubuntu22.04-16cores-64GB - pyroscope_env: ci-smoke-ocr2-plugins-evm-simulated - tag_suffix: "-plugins" - - name: vrf - id: vrf - nodes: 2 - os: ubuntu-latest - pyroscope_env: ci-smoke-vrf-evm-simulated - - name: vrfv2 - id: vrfv2 - nodes: 6 - os: ubuntu-latest - pyroscope_env: ci-smoke-vrf2-evm-simulated - - name: vrfv2plus - id: vrfv2plus - nodes: 9 - os: ubuntu-latest - pyroscope_env: ci-smoke-vrf2plus-evm-simulated - - name: forwarder_ocr - id: forwarder_ocr - nodes: 2 - os: ubuntu-latest - pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated - - name: forwarders_ocr2 - id: forwarders_ocr2 - nodes: 2 - os: ubuntu-latest - pyroscope_env: ci-smoke-forwarder-ocr-evm-simulated - runs-on: ${{ matrix.product.os }} - name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }} + 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@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + workflow_name: Run CCIP E2E Tests For Merge Queue + chainlink_version: ${{ inputs.evm-ref || github.sha }} + chainlink_upgrade_version: ${{ github.sha }} + test_path: .github/e2e-tests.yml + test_trigger: Merge Queue E2E CCIP Tests + upload_cl_node_coverage_artifact: true + upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ + enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + + 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] steps: - # Handy for debugging resource usage - # - name: Collect Workflow Telemetry - # uses: catchpoint/workflow-telemetry-action@v2 - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-${{ matrix.product.id }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ETH Smoke Tests ${{ matrix.product.name }}${{ matrix.product.tag_suffix }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Go Test Command - id: build-go-test-command + - name: Check Core test results + id: check_core_results run: | - # if dir is provided use it, otherwise use the smoke dir - if [ "${{ matrix.product.dir }}" != "" ]; then - dir=${{ matrix.product.dir }} - else - dir=smoke - fi - # if the matrix.product.run is set, use it for a different command - if [ "${{ matrix.product.run }}" != "" ]; then - echo "run_command=${{ matrix.product.run }} ./${dir}/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" - else - echo "run_command=./${dir}/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" - fi - - name: Check for "enable tracing" label - id: check-label + results='${{ needs.run-core-e2e-tests-for-pr.outputs.test_results }}' + echo "Core test results:" + echo "$results" | jq . + + node_migration_tests_failed=$(echo $results | jq '[.[] | select(.id == "integration-tests/migration/upgrade_version_test.go:*" ) | select(.result != "success")] | length > 0') + echo "node_migration_tests_failed=$node_migration_tests_failed" >> $GITHUB_OUTPUT + + - name: Check CCIP test results + id: check_ccip_results run: | - label=$(jq -r '.pull_request.labels[]?.name // empty' "$GITHUB_EVENT_PATH") - - if [[ -n "$label" ]]; then - if [[ "$label" == "enable tracing" ]]; then - echo "Enable tracing label found." - echo "trace=true" >> $GITHUB_OUTPUT - else - echo "Enable tracing label not found." - echo "trace=false" >> $GITHUB_OUTPUT - fi + if [[ '${{ needs.run-ccip-e2e-tests-for-pr.result }}' != 'skipped' ]]; then + results='${{ needs.run-ccip-e2e-tests-for-pr.outputs.test_results }}' + echo "CCIP test results:" + echo "$results" | jq . else - echo "No labels present or labels are null." - echo "trace=false" >> $GITHUB_OUTPUT + echo "CCIP tests were skipped." fi - - name: Setup Grafana and OpenTelemetry - id: docker-setup - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - # Create network - docker network create --driver bridge tracing - - # Make trace directory - cd integration-tests/smoke/ - mkdir ./traces - chmod -R 777 ./traces - - # Switch directory - cd ../../.github/tracing - - # Create a Docker volume for traces - # docker volume create otel-traces - - # Start OpenTelemetry Collector - # Note the user must be set to the same user as the runner for the trace data to be accessible - docker run -d --network=tracing --name=otel-collector \ - -v $PWD/otel-collector-ci.yaml:/etc/otel-collector.yaml \ - -v $PWD/../../integration-tests/smoke/traces:/tracing \ - --user "$(id -u):$(id -g)" \ - -p 4317:4317 otel/opentelemetry-collector:0.88.0 --config=/etc/otel-collector.yaml - - - name: Locate Docker Volume - id: locate-volume - if: false - run: | - echo "VOLUME_PATH=$(docker volume inspect --format '{{ .Mountpoint }}' otel-traces)" >> $GITHUB_OUTPUT - - - name: Show Otel-Collector Logs - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - docker logs otel-collector - - - name: Set Override Config - id: set_override_config - run: | - # if the matrix.product.config_path is set, use it as the override config - if [ "${{ matrix.product.config_path }}" != "" ]; then - echo "base_64_override=$(base64 -w 0 -i ${{ matrix.product.config_path }})" >> "$GITHUB_OUTPUT" - fi - - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - id: setup-gap - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - - name: Prepare Base64 CCIP TOML secrets - uses: ./.github/actions/setup-create-base64-config-ccip - with: - runId: ${{ github.run_id }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - selectedNetworks: SIMULATED_1,SIMULATED_2 - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - - ## Run this step when changes that require tests to be run are made - - name: Run Tests - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_chainlink_version: ${{ inputs.evm-ref || github.sha }} - test_config_selected_networks: ${{ env.SELECTED_NETWORKS }} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_test_log_collect: ${{ vars.TEST_LOG_COLLECT }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ inputs.evm-ref || github.sha }}${{ matrix.product.tag_suffix }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.product.name }}${{ matrix.product.tag_suffix }}-test-artifacts - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - ./integration-tests/smoke/seth_artifacts/ - /tmp/gotest.log - publish_check_name: ${{ matrix.product.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.product.pyroscope_env == '' || !startsWith(github.ref, 'refs/tags/') && 'false' || 'true' }} - - - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - timeout-minutes: 2 - continue-on-error: true - with: - name: cl-node-coverage-data-${{ matrix.product.name }}-${{ matrix.product.tag_suffix }} - path: .covdata - retention-days: 1 - - # Run this step when changes that do not need the test to run are made - - name: Run Setup - if: needs.changes.outputs.src == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_download_vendor_packages_command: cd ./integration-tests && go mod download - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - - - name: Show Otel-Collector Logs - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - docker logs otel-collector - - - name: Permissions on traces - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - run: | - ls -l ./integration-tests/smoke/traces - - - name: Upload Trace Data - if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + - name: Send slack notification for failed migration tests + if: steps.check_core_results.outputs.node_migration_tests_failed == 'true' && github.event_name != 'workflow_dispatch' + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + env: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} with: - name: trace-data - path: ./integration-tests/smoke/traces/trace-data.json + channel-id: "#team-test-tooling-internal" + slack-message: ":x: :mild-panic-intensifies: Node Migration Tests Failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}\n${{ format('Notifying ', secrets.GUARDIAN_SLACK_NOTIFICATION_HANDLE) }}" - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@70ccaef155381025e411cf7cd1fa5ef8f668ed75 # v2.3.25 - with: - test_directories: ./integration-tests/smoke/ + - name: Fail the job if core tests in PR not successful + if: always() && needs.run-core-e2e-tests-for-pr.result == 'failure' + run: exit 1 - ### Used to check the required checks box when the matrix completes - eth-smoke-tests: - if: always() - runs-on: ubuntu-latest - name: ETH Smoke Tests - needs: [eth-smoke-tests-matrix, eth-smoke-tests-matrix-automation, eth-smoke-tests-matrix-log-poller] - steps: - - name: Check smoke test matrix status - if: needs.eth-smoke-tests-matrix.result != 'success' || needs.eth-smoke-tests-matrix-automation.result != 'success' || needs.eth-smoke-tests-matrix-log-poller.result != 'success' - run: | - echo "ETH Smoke Tests: ${{ needs.eth-smoke-tests-matrix.result }}" - echo "Automation: ${{ needs.eth-smoke-tests-matrix-automation.result }}" - echo "Log Poller: ${{ needs.eth-smoke-tests-matrix-log-poller.result }}" - exit 1 - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-results - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ETH Smoke Tests - matrix-aggregator-status: ${{ needs.eth-smoke-tests-matrix.result }} - continue-on-error: true + - name: Fail the job if core tests in merge queue not successful + if: always() && needs.run-core-e2e-tests-for-merge-queue.result == 'failure' + run: exit 1 - eth-smoke-tests-ccip: - if: always() - runs-on: ubuntu-latest - name: ETH Smoke Tests CCIP - needs: eth-smoke-tests-matrix-ccip - steps: - - name: Check smoke test matrix status - if: needs.eth-smoke-tests-matrix-ccip.result != 'success' - run: | - echo "ETH Smoke Tests CCIP: ${{ needs.eth-smoke-tests-matrix-ccip.result }}" - exit 1 - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-results-ccip - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ETH Smoke Tests CCIP - matrix-aggregator-status: ${{ needs.eth-smoke-tests-matrix-ccip.result }} - continue-on-error: true + - 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() - needs: [eth-smoke-tests] + 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] runs-on: ubuntu-latest steps: - name: Checkout repo if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref }} @@ -1207,177 +436,25 @@ jobs: environment: integration ref: ${{ github.head_ref }} # See https://github.com/github/docs/issues/15319#issuecomment-1476705663 - - name: Collect Metrics - if: ${{ github.event_name == 'pull_request' }} - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-env-cleanup - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Clean up integration environment deployments - continue-on-error: true - - show-coverage: + show-chainlink-node-coverage: name: Show Chainlink Node Go Coverage if: always() - needs: [cleanup] + 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] runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - name: Download All Artifacts - uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6 + uses: actions/download-artifact@v4.1.8 with: - path: cl-node-coverage-data - pattern: cl-node-coverage-data-* + path: cl_node_coverage_data + pattern: cl_node_coverage_data_* merge-multiple: true - name: Show Coverage - run: go run ./integration-tests/scripts/show_coverage.go "${{ github.workspace }}/cl-node-coverage-data/*/merged" - - # Run the setup if the matrix finishes but this time save the cache if we have a cache hit miss - # this will also only run if both of the matrix jobs pass - eth-smoke-go-mod-cache: - environment: integration - needs: [eth-smoke-tests] - runs-on: ubuntu-latest - name: ETH Smoke Tests Go Mod Cache - continue-on-error: true - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Run Setup - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_download_vendor_packages_command: | - cd ./integration-tests - go mod download - # force download of test dependencies - go test -run=NonExistentTest ./smoke/... || echo "ignore expected test failure" - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "false" - - ### Migration tests - node-migration-tests: - name: Version Migration Tests - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [build-chainlink, changes] - # Only run migration tests on new tags - if: startsWith(github.ref, 'refs/tags/') - env: - SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink - UPGRADE_VERSION: ${{ inputs.evm-ref || github.sha }} - UPGRADE_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - TEST_LOG_LEVEL: debug - TEST_SUITE: migration - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-migration-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Version Migration Tests - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Get Latest Version - id: get_latest_version - run: | - untrimmed_ver=$(curl --header "Authorization: token ${{ secrets.GITHUB_TOKEN }}" --request GET https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .name) - latest_version="${untrimmed_ver:1}" - # Check if latest_version is empty - if [ -z "$latest_version" ]; then - echo "Error: The latest_version is empty. The migration tests need a verison to run." - exit 1 - fi - echo "latest_version=${latest_version}" >> "$GITHUB_OUTPUT" - - name: Name Versions - run: | - echo "Running migration tests from version '${{ steps.get_latest_version.outputs.latest_version }}' to: '${{ inputs.evm-ref || github.sha }}'" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-upgrade-config - with: - selectedNetworks: ${{ env.SELECTED_NETWORKS }} - chainlinkVersion: ${{ steps.get_latest_version.outputs.latest_version }} - upgradeVersion: ${{ env.UPGRADE_VERSION }} - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - - name: Run Migration Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 20m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ steps.get_latest_version.outputs.latest_version }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: node-migration-test-artifacts - artifacts_location: | - ./integration-tests/migration/logs - ./integration-tests/migration/db_dumps - ./integration-tests/migration/seth_artifacts - /tmp/gotest.log - publish_check_name: Node Migration Test Results - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - should_tidy: "false" - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_CHAINLINK_UPGRADE_IMAGE: ${{ env.UPGRADE_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - - - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - timeout-minutes: 2 - continue-on-error: true - with: - name: cl-node-coverage-data-migration-tests - path: .covdata - retention-days: 1 - - name: Notify Slack - if: failure() && github.event_name != 'workflow_dispatch' - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - with: - channel-id: "#team-test-tooling-internal" - slack-message: ":x: :mild-panic-intensifies: Node Migration Tests Failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}\n${{ format('Notifying ', secrets.GUARDIAN_SLACK_NOTIFICATION_HANDLE) }}" + run: go run ./integration-tests/scripts/show_coverage.go "${{ github.workspace }}/cl_node_coverage_data/*/merged" ## Solana Section get_solana_sha: @@ -1390,7 +467,7 @@ jobs: sha: ${{ steps.getsha.outputs.sha }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} @@ -1410,7 +487,7 @@ jobs: echo "short sha is: ${short_sha}" echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT" - name: Checkout solana - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink-solana ref: develop @@ -1437,7 +514,7 @@ jobs: projectserum_version: ${{ steps.psversion.outputs.projectserum_version }} steps: - name: Checkout the solana repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} @@ -1460,7 +537,7 @@ jobs: steps: - name: Check if image exists id: check-image - uses: smartcontractkit/chainlink-github-actions/docker/image-exists@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 + uses: smartcontractkit/chainlink-github-actions/docker/image-exists@0ce1e67b254a4f041e03cc6f0e3afc987b47c7bd # v2.3.30 with: repository: chainlink-solana-tests tag: ${{ needs.get_solana_sha.outputs.sha }} @@ -1484,24 +561,13 @@ jobs: get_solana_sha, ] steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-solana-build-contracts - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solana Build Artifacts - continue-on-error: true - name: Checkout the solana repo - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Build contracts - if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' uses: smartcontractkit/chainlink-solana/.github/actions/build_contract_artifacts@46b1311a5a83f33d08ffa8e1e0ab04f9ad51665d # node20 update on may 10, 2024 with: ref: ${{ needs.get_solana_sha.outputs.sha }} @@ -1527,34 +593,30 @@ jobs: env: CONTRACT_ARTIFACTS_PATH: contracts/target/deploy steps: - - name: Collect Metrics - if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-solana-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solana Build Test Image - continue-on-error: true - name: Checkout the repo - if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + 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: repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} + - name: Download Artifacts + if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + uses: actions/download-artifact@v4.1.8 + with: + name: artifacts + path: ${{ env.CONTRACT_ARTIFACTS_PATH }} - name: Build Test Image - if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' - uses: ./.github/actions/build-test-image + if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + uses: smartcontractkit/.github/actions/ctf-build-test-image@a5e4f4c8fbb8e15ab2ad131552eca6ac83c4f4b3 # ctf-build-test-image@0.1.0 with: + repository: chainlink-solana-tests tag: ${{ needs.get_solana_sha.outputs.sha }} - artifacts_path: ${{ env.CONTRACT_ARTIFACTS_PATH }} + suites: smoke QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - run: echo "this exists so we don't have to run anything else if the build is skipped" - if: needs.changes.outputs.src == 'false' || needs.solana-test-image-exists.outputs.exists == 'true' + if: needs.changes.outputs.core_changes == 'false' || needs.solana-test-image-exists.outputs.exists == 'true' solana-smoke-tests: if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} @@ -1580,26 +642,14 @@ jobs: TEST_LOG_LEVEL: debug CONTRACT_ARTIFACTS_PATH: contracts/target/deploy steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-solana-e2e-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solana Smoke Tests - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} - name: Run Setup - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 + if: needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch' + uses: smartcontractkit/.github/actions/ctf-setup-run-tests-environment@49cb1613e96c9ce17f7290e4dabd38f43aa9bd4d # ctf-setup-run-tests-environment@0.0.0 with: go_mod_path: ./integration-tests/go.mod cache_restore_only: true @@ -1611,7 +661,7 @@ jobs: QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - name: Pull Artifacts - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + if: needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch' run: | IMAGE_NAME=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} # Pull the Docker image @@ -1635,10 +685,9 @@ jobs: yarn --cwd ./gauntlet build yarn --cwd ./gauntlet gauntlet - name: Generate config overrides - run: | # https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md + run: | # https://github.com/smartcontractkit/chainlink-testing-framework/lib/blob/main/config/README.md cat << EOF > config.toml [ChainlinkImage] - image="${{ env.CHAINLINK_IMAGE }}" version="${{ inputs.evm-ref || github.sha }}" [Common] user="${{ github.actor }}" @@ -1651,8 +700,8 @@ jobs: # shellcheck disable=SC2086 echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run Tests - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 + if: needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch' + uses: smartcontractkit/.github/actions/ctf-run-tests@b8731364b119e88983e94b0c4da87fc27ddb41b8 # ctf-run-tests@0.0.0 with: test_command_to_run: export ENV_JOB_IMAGE=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} && make test_smoke test_config_override_base64: ${{ env.BASE64_CONFIG_OVERRIDE }} @@ -1675,13 +724,16 @@ jobs: run_setup: false go_coverage_src_dir: /var/tmp/go-coverage go_coverage_dest_dir: ${{ github.workspace }}/.covdata + env: + E2E_TEST_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@v4.4.3 timeout-minutes: 2 continue-on-error: true with: - name: cl-node-coverage-data-solana-tests + name: cl_node_coverage_data_solana_tests path: .covdata retention-days: 1 diff --git a/.github/workflows/lint-gh-workflows.yml b/.github/workflows/lint-gh-workflows.yml index c7727199e9a..9897c023576 100644 --- a/.github/workflows/lint-gh-workflows.yml +++ b/.github/workflows/lint-gh-workflows.yml @@ -7,17 +7,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out Code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Run actionlint uses: reviewdog/action-actionlint@c6ee1eb0a5d47b2af53a203652b5dac0b6c4016e # v1.43.0 - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: lint-gh-workflows - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Validate Github Action Workflows - continue-on-error: true diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml deleted file mode 100644 index bcf4dfea199..00000000000 --- a/.github/workflows/live-testnet-tests.yml +++ /dev/null @@ -1,1119 +0,0 @@ -# *** -# This workflow is a monstrosity of copy-paste, and that's to increase legibility in reporting and running, so the code be damned. -# I suspect this can be cleaned up significantly with some clever trickery of the GitHub actions matrices, but I am not that clever. -# We want each chain to run in parallel, but each test within the chain needs to be able to run sequentially -# (we're trying to eliminate this as a requirement, should make it a lot easier). -# Each chain can have a variety of tests to run. -# We also want reporting to be clear in the start-slack-thread and post-test-results-to-slack jobs. -# Funding address: 0xC1107e57082945E28d3202A81B1520DEA3AE6AEC -# *** - -name: Live Testnet Tests -on: - # Disable refular runs for now until we can fix some test client flakiness and improve stability - # schedule: - # - cron: "0 5 * * *" # Run every night at midnight EST - # push: - # tags: - # - "*" - workflow_dispatch: - inputs: - slack_user_id: - description: "The Slack member ID to notify" - required: true - type: string - network: - description: "The network to run tests on" - required: true - type: choice - options: - - "All" - - "Sepolia" - - "Optimism Sepolia" - - "Arbitrum Sepolia" - - "Base Sepolia" - - "Polygon Mumbai" - - "Avalanche Fuji" - - "Fantom Testnet" - - "Celo Alfajores" - - "Linea Goerli" - - "BSC Testnet" - -env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - MOD_CACHE_VERSION: 2 - CHAINLINK_NODE_FUNDING: .5 - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - LOKI_URL: ${{ secrets.LOKI_URL }} - LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - LOGSTREAM_LOG_TARGETS: loki - GRAFANA_URL: ${{ vars.GRAFANA_URL }} - RUN_ID: ${{ github.run_id }} - - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - -jobs: - - # Build Test Dependencies - - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu-latest - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: live-testnet-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Chainlink Image - uses: ./.github/actions/build-chainlink-image - with: - tag_suffix: "" - dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ github.sha }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - build-tests: - environment: integration - permissions: - id-token: write - contents: read - name: Build Tests Binary - runs-on: ubuntu-latest - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: live-testnet-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Tests Binary - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-tests@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_download_vendor_packages_command: cd ./integration-tests && go mod download - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - go_tags: embed - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - binary_name: tests - - # End Build Test Dependencies - - # Reporting Jobs - - start-slack-thread: - name: Start Slack Thread - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} - environment: integration - outputs: - thread_ts: ${{ steps.slack.outputs.thread_ts }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: [sepolia-smoke-tests, optimism-sepolia-smoke-tests, arbitrum-sepolia-smoke-tests, base-sepolia-smoke-tests, polygon-mumbai-smoke-tests, avalanche-fuji-smoke-tests, fantom-testnet-smoke-tests, celo-alfajores-smoke-tests, linea-goerli-smoke-tests, bsc-testnet-smoke-tests] - steps: - - name: Debug Result - run: echo ${{ join(needs.*.result, ',') }} - - name: Main Slack Notification - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - id: slack - with: - channel-id: ${{ secrets.QA_SLACK_CHANNEL }} - payload: | - { - "attachments": [ - { - "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "Live Smoke Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", - "emoji": true - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Notifying <@${{ inputs.slack_user_id }}>" - } - }, - { - "type": "divider" - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>\nThe funding address for all tests and networks is `0xC1107e57082945E28d3202A81B1520DEA3AE6AEC`" - } - } - ] - } - ] - } - env: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - - post-test-results-to-slack: - name: Post Test Results for ${{ matrix.network }} - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - runs-on: ubuntu-latest - needs: start-slack-thread - strategy: - fail-fast: false - matrix: - network: [Sepolia, Optimism Sepolia, Arbitrum Sepolia, Base Sepolia, Polygon Mumbai, Avalanche Fuji, Fantom Testnet, Celo Alfajores, Linea Goerli, BSC Testnet] - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Post Test Results - uses: ./.github/actions/notify-slack-jobs-result - with: - github_token: ${{ github.token }} - github_repository: ${{ github.repository }} - workflow_run_id: ${{ github.run_id }} - github_job_name_regex: ^${{ matrix.network }} (.*?) Tests$ - message_title: ${{ matrix.network }} - slack_channel_id: ${{ secrets.QA_SLACK_CHANNEL }} - slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} - slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} - - # End Reporting Jobs - - sepolia-smoke-tests: - environment: integration - if: ${{ (github.event.inputs.network == 'All' || github.event.inputs.network == 'Sepolia') }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Sepolia ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-sepolia - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "sepolia" - httpEndpoints: ${{ secrets.QA_SEPOLIA_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_SEPOLIA_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directories: "./" - - bsc-testnet-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'BSC Testnet' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: BSC Testnet ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-bsc-testnet - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "bsc_testnet" - httpEndpoints: ${{ secrets.QA_BSC_TESTNET_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_BSC_TESTNET_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - optimism-sepolia-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Optimism Sepolia' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Optimism Sepolia ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-optimism-sepolia - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "optimism_sepolia" - httpEndpoints: ${{ secrets.QA_OPTIMISM_SEPOLIA_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_OPTIMISM_SEPOLIA_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - arbitrum-sepolia-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Arbitrum Sepolia' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Arbitrum Sepolia ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-arbitrum-sepolia - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "arbitrum_sepolia" - httpEndpoints: ${{ secrets.QA_ARBITRUM_SEPOLIA_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_ARBITRUM_SEPOLIA_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - base-sepolia-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Base Sepolia' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - name: Base Sepolia ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-base-sepolia - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "base_sepolia" - httpEndpoints: ${{ secrets.QA_BASE_SEPOLIA_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_BASE_SEPOLIA_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - polygon-mumbai-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Polygon Mumbai' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Polygon Mumbai ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-polygon-mumbai - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "polygon_mumbai" - httpEndpoints: ${{ secrets.QA_POLYGON_MUMBAI_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_POLYGON_MUMBAI_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - avalanche-fuji-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Avalanche Fuji' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Avalanche Fuji ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-avalanche-fuji - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "avalanche_fuji" - httpEndpoints: ${{ secrets.QA_AVALANCHE_FUJI_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_AVALANCHE_FUJI_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - fantom-testnet-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Fantom Testnet' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - - product: Automation Conditional - test: TestAutomationBasic/registry_2_1_conditional - - product: Automation Log Trigger - test: TestAutomationBasic/registry_2_1_logtrigger - name: Fantom Testnet ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-fantom-testnet - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "fantom_testnet" - httpEndpoints: ${{ secrets.QA_FANTOM_TESTNET_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_FANTOM_TESTNET_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - celo-alfajores-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Celo Alfajores' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - name: Celo Alfajores ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-celo-alfajores - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "celo_alfajores" - httpEndpoints: ${{ secrets.QA_CELO_ALFAJORES_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_CELO_ALFAJORES_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - scroll-sepolia-smoke-tests: - if: false - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - name: Scroll Sepolia ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-scroll-sepolia - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "scroll_sepolia" - httpEndpoints: ${{ secrets.QA_SCROLL_SEPOLIA_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_SCROLL_SEPOLIA_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" - - linea-goerli-smoke-tests: - environment: integration - if: ${{ github.event.inputs.network == 'All' || github.event.inputs.network == 'Linea Goerli' }} - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - max-parallel: 1 - fail-fast: false - matrix: - include: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#example-adding-configurations - - product: OCR - test: TestOCRBasic - name: Linea Goerli ${{ matrix.product }} Tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-smoke-${{ matrix.product }}-linea-goerli - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: "linea_goerli" - httpEndpoints: ${{ secrets.QA_LINEA_GOERLI_HTTP_URLS }} - wsEndpoints: ${{ secrets.QA_LINEA_GOERLI_URLS }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.timeout 30m -test.count=1 -test.parallel=1 -test.run ${{ matrix.test }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directory: "./" diff --git a/.github/workflows/live-vrf-tests.yml b/.github/workflows/live-vrf-tests.yml deleted file mode 100644 index 28f5867954b..00000000000 --- a/.github/workflows/live-vrf-tests.yml +++ /dev/null @@ -1,193 +0,0 @@ -# Funding address: 0xC1107e57082945E28d3202A81B1520DEA3AE6AEC -name: Generic Live Smoke Tests -on: - workflow_dispatch: - inputs: - networks: - description: "Comma-separated list of networks to run on" - required: true - default: "SEPOLIA,OPTIMISM_SEPOLIA,ARBITRUM_SEPOLIA" - test_list: - description: "Comma-separated list of tests to run" - required: true - default: "TestVRFBasic,TestVRFv2Basic,TestVRFv2Plus" - -env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - MOD_CACHE_VERSION: 2 - CHAINLINK_NODE_FUNDING: .5 - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - LOKI_URL: ${{ secrets.LOKI_URL }} - LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - LOGSTREAM_LOG_TARGETS: loki - GRAFANA_URL: ${{ vars.GRAFANA_URL }} - RUN_ID: ${{ github.run_id }} - - CHAINLINK_COMMIT_SHA: ${{ github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - -jobs: - - # Build Test Dependencies - - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - name: Build Chainlink Image - runs-on: ubuntu-latest - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: live-vrf-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Chainlink Image - uses: ./.github/actions/build-chainlink-image - with: - tag_suffix: "" - dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ github.sha }} - GRAFANA_CLOUD_BASIC_AUTH: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} - GRAFANA_CLOUD_HOST: ${{ secrets.GRAFANA_CLOUD_HOST }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - build-tests: - environment: integration - permissions: - id-token: write - contents: read - name: Build Tests Binary - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.build-matrix.outputs.matrix }} - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: live-vrf-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Tests Binary - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Network Matrix - id: build-matrix - run: | - NETWORKS="[\"${{ github.event.inputs.networks }}\"]" - NETWORKS="${NETWORKS//,/\",\"}" - echo "matrix=${NETWORKS}" >> "$GITHUB_OUTPUT" - - name: Build Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-tests@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_download_vendor_packages_command: cd ./integration-tests && go mod download - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - go_tags: embed - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - binary_name: tests - - - # End Build Test Dependencies - - live-smoke-tests: - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, build-tests] - strategy: - fail-fast: false - matrix: - network: ${{fromJson(needs.build-tests.outputs.matrix)}} - name: Smoke Tests on ${{ matrix.network }} - runs-on: ubuntu-latest - steps: - - name: Build Secrets Names - id: build-secrets-names - run: | - echo "HTTP_URLS_SECRET_NAME=QA_${{ matrix.network }}_HTTP_URLS" >> $GITHUB_ENV - echo "URLS_SECRET_NAME=QA_${{ matrix.network }}_URLS" >> $GITHUB_ENV - - name: Split Test Names - id: split_list - run: | - IFS=',' read -ra ADDR <<< "${{ inputs.test_list }}" - echo "test_list=${ADDR[*]}" >> $GITHUB_ENV - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - with: - # aws inputs - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - # other inputs - duplicate-authorization-header: "true" - - name: Prepare Base64 TOML override - uses: ./.github/actions/setup-create-base64-config-live-testnets - with: - runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} - logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - network: ${{ matrix.network }} - httpEndpoints: ${{ secrets[env.HTTP_URLS_SECRET_NAME] }} - wsEndpoints: ${{ secrets[env.URLS_SECRET_NAME] }} - fundingKeys: ${{ secrets.QA_EVM_KEYS }} - - name: Download Tests Binary - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - name: tests - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests-binary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_command_to_run: ./tests -test.v -test.timeout 4h -test.count=1 -test.parallel=1 -test.run ${{ env.test_list }} - binary_name: tests - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} - artifacts_location: ./logs - token: ${{ secrets.GITHUB_TOKEN }} - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@75a9005952a9e905649cfb5a6971fd9429436acd # v2.3.25 - with: - test_directories: "./" diff --git a/.github/workflows/llm-action-error-reporter.yml b/.github/workflows/llm-action-error-reporter.yml new file mode 100644 index 00000000000..c0d01253c9f --- /dev/null +++ b/.github/workflows/llm-action-error-reporter.yml @@ -0,0 +1,23 @@ +name: LLM Action Error Reporter +on: + workflow_run: + workflows: ["CI Core", "Operator UI CI"] # This workflow will be triggered as soon as one of worfklows is completed + types: + - completed + +jobs: + analyze_logs: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + repository-projects: read + actions: read + steps: + - name: Analyze logs + uses: smartcontractkit/.github/actions/llm-action-error-reporter@d125ca9fe5e3b410de7c6db4a4ce3ed7a0728cd6 # v0.3.0 + with: + parent-workflow-conclusion: ${{ github.event.workflow_run.conclusion }} + skip-on-success: true # Skip posting comment if no errors are found + gh-token: ${{ github.token }} + openai-api-key: ${{ secrets.OPENAI_API_KEY }} \ No newline at end of file diff --git a/.github/workflows/on-demand-keeper-smoke-tests.yml b/.github/workflows/on-demand-keeper-smoke-tests.yml deleted file mode 100644 index 626daf00579..00000000000 --- a/.github/workflows/on-demand-keeper-smoke-tests.yml +++ /dev/null @@ -1,290 +0,0 @@ -name: On Demand Keeper Smoke Tests -run-name: On Demand Keeper Smoke Tests ${{ inputs.distinct_run_name && inputs.distinct_run_name || '' }} -on: - workflow_dispatch: - inputs: - distinct_run_name: - description: 'A unique identifier for this run, only use from other repos' - required: false - type: string - -# Only run 1 of this workflow at a time per PR -concurrency: - group: on-demand-keeper-smoke-tests-${{ github.ref }}-${{ inputs.distinct_run_name }} - cancel-in-progress: true - -env: - # for run-test variables and environment - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ inputs.evm-ref || github.sha }} - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - TEST_SUITE: smoke - TEST_ARGS: -test.timeout 12m - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - MOD_CACHE_VERSION: 2 - COLLECTION_ID: chainlink-e2e-tests - -jobs: - build-chainlink: - environment: integration - permissions: - id-token: write - contents: read - strategy: - matrix: - image: - - name: "" - dockerfile: core/chainlink.Dockerfile - tag-suffix: "" - name: Build Chainlink Image ${{ matrix.image.name }} - runs-on: ubuntu22.04-16cores-64GB - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-build-chainlink - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Chainlink Image ${{ matrix.image.name }} - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Chainlink Image - uses: ./.github/actions/build-chainlink-image - with: - tag_suffix: ${{ matrix.image.tag-suffix }} - dockerfile: ${{ matrix.image.dockerfile }} - git_commit_sha: ${{ inputs.evm-ref || github.sha }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - dep_evm_sha: ${{ inputs.evm-ref }} - - compare-tests: - runs-on: ubuntu-latest - name: Build Automation Test List - outputs: - automation-matrix: ${{ env.AUTOMATION_JOB_MATRIX_JSON }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref }} - - name: Compare Test Lists - run: | - cd ./integration-tests - ./scripts/compareTestList.sh ./smoke/keeper_test.go - - name: Build Test Matrix Lists - id: build-test-matrix-list - run: | - cd ./integration-tests - KEEPER_JOB_MATRIX_JSON=$(./scripts/buildTestMatrixList.sh ./smoke/keeper_test.go keeper ubuntu-latest 1) - echo "AUTOMATION_JOB_MATRIX_JSON=${KEEPER_JOB_MATRIX_JSON}" >> $GITHUB_ENV - - eth-smoke-tests-matrix-automation: - if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} - environment: integration - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - needs: [build-chainlink, compare-tests] - env: - SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - CHAINLINK_ENV_USER: ${{ github.actor }} - TEST_LOG_LEVEL: debug - strategy: - fail-fast: false - matrix: - product: ${{fromJson(needs.compare-tests.outputs.automation-matrix)}} - runs-on: ${{ matrix.product.os }} - name: ETH Smoke Tests ${{ matrix.product.name }} - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-${{ matrix.product.name }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - this-job-name: ETH Smoke Tests ${{ matrix.product.name }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Go Test Command - id: build-go-test-command - run: | - # if the matrix.product.run is set, use it for a different command - if [ "${{ matrix.product.run }}" != "" ]; then - echo "run_command=${{ matrix.product.run }} ./smoke/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" - else - echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" - fi - - ## Run this step when changes that require tests to be run are made - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_config_chainlink_version: ${{ inputs.evm-ref || github.sha }} - test_config_selected_networks: ${{ env.SELECTED_NETWORKS }} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_config_test_log_collect: ${{ vars.TEST_LOG_COLLECT }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ inputs.evm-ref || github.sha }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.product.name }}-test-logs - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - /tmp/gotest.log - publish_check_name: ${{ matrix.product.name }} - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "true" - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.product.pyroscope_env }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.product.pyroscope_env == '' || !startsWith(github.ref, 'refs/tags/') && 'false' || 'true' }} - - - name: Upload Coverage Data - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - with: - name: cl-node-coverage-data-${{ matrix.product.name }} - path: .covdata - retention-days: 1 - - - name: Print failed test summary - if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 - - ### Used to check the required checks box when the matrix completes - eth-smoke-tests: - if: always() - runs-on: ubuntu-latest - name: ETH Smoke Tests - needs: [eth-smoke-tests-matrix-automation] - steps: - - name: Check smoke test matrix status - if: needs.eth-smoke-tests-matrix-automation.result != 'success' - run: | - echo "Automation: ${{ needs.eth-smoke-tests-matrix-automation.result }}" - exit 1 - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-matrix-results - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ETH Smoke Tests - matrix-aggregator-status: ${{ needs.eth-smoke-tests-matrix.result }} - continue-on-error: true - - cleanup: - name: Clean up integration environment deployments - if: always() - needs: [eth-smoke-tests] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref }} - - - name: 🧼 Clean up Environment - if: ${{ github.event_name == 'pull_request' }} - uses: ./.github/actions/delete-deployments - with: - environment: integration - ref: ${{ github.head_ref }} # See https://github.com/github/docs/issues/15319#issuecomment-1476705663 - - - name: Collect Metrics - if: ${{ github.event_name == 'pull_request' }} - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ env.COLLECTION_ID }}-env-cleanup - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Clean up integration environment deployments - continue-on-error: true - - show-coverage: - name: Show Chainlink Node Go Coverage - if: always() - needs: [cleanup] - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Download All Artifacts - uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6 - with: - path: cl-node-coverage-data - pattern: cl-node-coverage-data-* - merge-multiple: true - - name: Show Coverage - run: go run ./integration-tests/scripts/show_coverage.go "${{ github.workspace }}/cl-node-coverage-data/*/merged" - - # Run the setup if the matrix finishes but this time save the cache if we have a cache hit miss - # this will also only run if both of the matrix jobs pass - eth-smoke-go-mod-cache: - - environment: integration - needs: [eth-smoke-tests] - runs-on: ubuntu-latest - name: ETH Smoke Tests Go Mod Cache - continue-on-error: true - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Run Setup - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-go@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 - with: - test_download_vendor_packages_command: | - cd ./integration-tests - go mod download - # force download of test dependencies - go test -run=NonExistentTest ./smoke/... || echo "ignore expected test failure" - go_mod_path: ./integration-tests/go.mod - cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "false" diff --git a/.github/workflows/on-demand-log-poller.yml b/.github/workflows/on-demand-log-poller.yml deleted file mode 100644 index 1685c7e4556..00000000000 --- a/.github/workflows/on-demand-log-poller.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: On Demand Log Poller Consistency Test -on: - workflow_dispatch: - inputs: - base64Config: - description: base64-ed config - required: true - type: string - -jobs: - test: - env: - REF_NAME: ${{ github.head_ref || github.ref_name }} - runs-on: ubuntu22.04-8cores-32GB - steps: - - name: Add masks and export base64 config - run: | - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Setup Go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 - with: - go-version-file: "integration-tests/go.mod" - cache: true - - name: Run tests - run: | - cd integration-tests - go mod download - go test -v -timeout 5h -v -count=1 -run ^TestLogPollerFewFiltersFixedDepth$ ./smoke/log_poller_test.go diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index 924b43829e5..a96c000fa44 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -3,114 +3,68 @@ on: workflow_dispatch: inputs: testToRun: - description: Select a test to run + description: Select a test to run from .github/e2e-tests.yml required: true - default: TestOCRSoak + default: soak/ocr_test.go:TestOCRv1Soak type: choice options: - - TestOCRv1Soak - - TestOCRv2Soak - - TestForwarderOCRv1Soak - - TestForwarderOCRv2Soak - - TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled - - TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled - - TestOCRSoak_GasSpike - - TestOCRSoak_ChangeBlockGasLimit - - TestOCRSoak_RPCDownForAllCLNodes - - TestOCRSoak_RPCDownForHalfCLNodes - base64Config: - description: base64-ed config + - soak/ocr_test.go:TestOCRv1Soak + - soak/ocr_test.go:TestOCRv2Soak + - soak/ocr_test.go:TestForwarderOCRv1Soak + - soak/ocr_test.go:TestForwarderOCRv2Soak + - soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled + - soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled + - soak/ocr_test.go:TestOCRSoak_GasSpike + - soak/ocr_test.go:TestOCRSoak_ChangeBlockGasLimit + - soak/ocr_test.go:TestOCRSoak_RPCDownForAllCLNodes + - soak/ocr_test.go:TestOCRSoak_RPCDownForHalfCLNodes + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string + chainlink_version: + description: Chainlink image version to use + default: develop required: true type: string slackMemberID: description: Slack Member ID (Not your @) required: true - default: U01A2B2C3D4 - type: string - test_secrets_override_key: - description: 'Key to run tests with custom test secrets' - required: false - type: string + default: U01A2B2C3D4 jobs: - ocr_soak_test: - name: OCR Soak Test - environment: integration - runs-on: ubuntu-latest - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - env: - CHAINLINK_ENV_USER: ${{ github.actor }} + run-e2e-tests-workflow: + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + with: + test_path: .github/e2e-tests.yml + test_ids: ${{ inputs.testToRun}} + test_config_override_path: ${{ inputs.test_config_override_path }} + chainlink_version: ${{ inputs.chainlink_version }} + SLACK_USER: ${{ inputs.slackMemberID }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} - TEST_LOG_LEVEL: debug - REF_NAME: ${{ github.head_ref || github.ref_name }} - ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: on-demand-ocr-soak-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ${{ inputs.network }} OCR Soak Test - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.REF_NAME }} - - name: Get Slack config and mask base64 config - run: | - SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) - echo ::add-mask::$SLACK_USER - echo SLACK_USER=$SLACK_USER >> $GITHUB_ENV - - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Parse base64 config - uses: ./.github/actions/setup-parse-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Setup Push Tag - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - - name: Build Image - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - env: - DETACH_RUNNER: true - TEST_SUITE: soak - TEST_ARGS: -test.timeout 900h -test.memprofile memprofile.out -test.cpuprofile profile.out - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ github.sha }} - # We can comment these out when we have a stable soak test and aren't worried about resource consumption - TEST_UPLOAD_CPU_PROFILE: true - TEST_UPLOAD_MEM_PROFILE: true - with: - test_command_to_run: cd ./integration-tests && go test -v -count=1 -run ^${{ github.event.inputs.testToRun }}$ ./soak - test_download_vendor_packages_command: make gomod - test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - token: ${{ secrets.GITHUB_TOKEN }} - should_cleanup: false - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} diff --git a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml deleted file mode 100644 index 6d92acd9ea8..00000000000 --- a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: On Demand VRFV2 Smoke Test (Ethereum clients) -on: - workflow_dispatch: - inputs: - base64Config: - description: base64-ed config - required: true - type: string - test_secrets_override_key: - description: 'Key to run tests with custom test secrets' - required: false - type: string - -jobs: - vrfv2_smoke_test: - name: VRFV2 Smoke Test with custom EL client client - environment: integration - runs-on: ubuntu22.04-8cores-32GB - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - env: - TEST_LOG_LEVEL: debug - REF_NAME: ${{ github.head_ref || github.ref_name }} - steps: - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Mask base64 config - run: | - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Parse base64 config - uses: ./.github/actions/setup-parse-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Send details to Step Summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - echo "### Execution client used" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.ETH2_EL_CLIENT }}\`" >>$GITHUB_STEP_SUMMARY - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run TestVRFv2Basic ./smoke/vrfv2_test.go 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: vrf-test-logs - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - should_cleanup: false - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} diff --git a/.github/workflows/on-demand-vrfv2-performance-test.yml b/.github/workflows/on-demand-vrfv2-performance-test.yml index 3d55c384580..0a9cec3db93 100644 --- a/.github/workflows/on-demand-vrfv2-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2-performance-test.yml @@ -2,10 +2,6 @@ name: On Demand VRFV2 Performance Test on: workflow_dispatch: inputs: - base64Config: - description: base64-ed config - required: true - type: string performanceTestType: description: Performance Test Type of test to run type: choice @@ -19,81 +15,85 @@ on: description: "Regex for tests to run" required: false default: "(TestVRFV2Performance)" + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false type: string - + notify_user_id_on_failure: + description: 'Enter Slack user ID to notify on test failure' + required: false + type: string + jobs: - vrfv2_performance_test: - name: VRFV2 Performance Test - environment: integration - runs-on: ubuntu22.04-8cores-32GB - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - env: - LOKI_URL: ${{ secrets.LOKI_URL }} + set-tests-to-run: + name: Set tests to run + runs-on: ubuntu-latest + outputs: + test_list: ${{ steps.set-tests.outputs.test_list }} + 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_LIST=$(jq -n -c \ + --arg test_cmd "$TEST_CMD" \ + --arg test_config_override_path "$TEST_CONFIG_OVERRIDE_PATH" \ + --arg TEST_TYPE "$TEST_TYPE" \ + '{ + "tests": [ + { + "id": "TestVRFv2Plus_Performance", + "path": "integration-tests/load/vrfv2plus/vrfv2plus_test.go", + "runs_on": "ubuntu22.04-8cores-32GB", + "test_env_type": "docker", + "test_cmd": $test_cmd, + "test_config_override_path": $test_config_override_path, + "test_env_vars": { + "TEST_TYPE": $TEST_TYPE + } + } + ] + }') + + echo "test_list=$TEST_LIST" >> $GITHUB_OUTPUT + + run-e2e-tests-workflow: + name: Run E2E Tests + needs: set-tests-to-run + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + 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 }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - TEST_TYPE: ${{ inputs.performanceTestType }} - TEST_LOG_LEVEL: debug - REF_NAME: ${{ github.head_ref || github.ref_name }} + 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 }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} - SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} - GRAFANA_URL: "http://localhost:8080/primary" - GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - WASP_LOG_LEVEL: info - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: on-demand-vrfv2-performance-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ${{ inputs.network }} VRFV2 Performance Test - continue-on-error: true - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Mask base64 config - run: | - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Merge and export base64 config - uses: ./.github/actions/setup-merge-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Send details to Step Summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - with: - test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2 - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: vrf-test-logs - artifacts_location: ./integration-tests/load/vrfv2/logs/ - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - should_cleanup: false - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} diff --git a/.github/workflows/on-demand-vrfv2-smoke-tests.yml b/.github/workflows/on-demand-vrfv2-smoke-tests.yml new file mode 100644 index 00000000000..fcb083df708 --- /dev/null +++ b/.github/workflows/on-demand-vrfv2-smoke-tests.yml @@ -0,0 +1,101 @@ +name: On Demand VRFV2 Smoke Tests +on: + workflow_dispatch: + inputs: + test_suite: + description: "Test Suite to run" + required: true + type: choice + default: "All Tests" + options: + - "All Tests" + - "Selected Tests" + test_list_regex: + description: "Regex for 'Selected Tests' to run" + required: false + default: "TestVRFv2Basic/(Request_Randomness|Direct_Funding)|TestVRFV2WithBHS" + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string + chainlink_version: + description: Chainlink image version to use + default: develop + required: false + type: string + notify_user_id_on_failure: + description: 'Enter Slack user ID to notify on test failure' + required: false + 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 }} + steps: + - name: Generate Test List JSON + id: set-tests + run: | + if [[ "${{ 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' + fi + TEST_CONFIG_OVERRIDE_PATH=${{ inputs.test_config_override_path }} + + TEST_LIST=$(jq -n -c \ + --arg test_cmd "$TEST_CMD" \ + --arg test_config_override_path "$TEST_CONFIG_OVERRIDE_PATH" \ + '{ + "tests": [ + { + "id": "TestVRFv2_Smoke", + "path": "integration-tests/smoke/vrfv2_test.go", + "runs_on": "ubuntu-latest", + "test_env_type": "docker", + "test_cmd": $test_cmd, + "test_config_override_path": $test_config_override_path + } + ] + }') + + echo "test_list=$TEST_LIST" >> $GITHUB_OUTPUT + + run-e2e-tests-workflow: + name: Run E2E Tests + needs: set-tests-to-run + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + 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 }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_NOTIFICATION_AFTER_TESTS_CHANNEL_ID: ${{ secrets.QA_VRF_SLACK_CHANNEL }} diff --git a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml deleted file mode 100644 index 1e58002fc1b..00000000000 --- a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: On Demand VRFV2Plus Smoke Test (Ethereum clients) -on: - workflow_dispatch: - inputs: - base64Config: - description: base64-ed config - required: true - type: string - test_secrets_override_key: - description: 'Key to run tests with custom test secrets' - required: false - type: string - -jobs: - vrfv2plus_smoke_test: - name: VRFV2Plus Smoke Test with custom EL client - environment: integration - runs-on: ubuntu22.04-8cores-32GB - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - env: - TEST_LOG_LEVEL: debug - REF_NAME: ${{ github.head_ref || github.ref_name }} - steps: - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Mask base64 config - run: | - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Parse base64 config - uses: ./.github/actions/setup-parse-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Send details to Step Summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - echo "### Execution client used" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.ETH2_EL_CLIENT }}\`" >>$GITHUB_STEP_SUMMARY - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run ^TestVRFv2Plus$/^Link_Billing$ ./smoke/vrfv2plus_test.go 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: vrfplus-test-logs - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - should_cleanup: false - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml index 658736ab03f..534aea3d27d 100644 --- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml @@ -2,10 +2,6 @@ name: On Demand VRFV2 Plus Performance Test on: workflow_dispatch: inputs: - base64Config: - description: base64-ed config - required: true - type: string performanceTestType: description: Performance Test Type of test to run type: string @@ -14,81 +10,91 @@ on: description: "Regex for tests to run" required: false default: "(TestVRFV2PlusPerformance)" + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string test_secrets_override_key: description: 'Key to run tests with custom test secrets' required: false type: string + chainlink_version: + description: Chainlink image version to use + default: develop + required: false + type: string + notify_user_id_on_failure: + description: 'Enter Slack user ID to notify on test failure' + required: false + type: string jobs: - vrfv2plus_performance_test: - name: VRFV2 Plus Performance Test - environment: integration - runs-on: ubuntu22.04-8cores-32GB - permissions: - checks: write - pull-requests: write - id-token: write - contents: read - env: - LOKI_URL: ${{ secrets.LOKI_URL }} + set-tests-to-run: + name: Set tests to run + runs-on: ubuntu-latest + outputs: + test_list: ${{ steps.set-tests.outputs.test_list }} + 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_LIST=$(jq -n -c \ + --arg test_cmd "$TEST_CMD" \ + --arg test_config_override_path "$TEST_CONFIG_OVERRIDE_PATH" \ + --arg TEST_TYPE "$TEST_TYPE" \ + '{ + "tests": [ + { + "id": "TestVRFv2Plus_Performance", + "path": "integration-tests/load/vrfv2plus/vrfv2plus_test.go", + "runs_on": "ubuntu-latest", + "test_env_type": "docker", + "test_cmd": $test_cmd, + "test_config_override_path": $test_config_override_path, + "test_env_vars": { + "TEST_TYPE": $TEST_TYPE + } + } + ] + }') + + echo "test_list=$TEST_LIST" >> $GITHUB_OUTPUT + + run-e2e-tests-workflow: + name: Run E2E Tests + needs: set-tests-to-run + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + 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 }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - TEST_TYPE: ${{ inputs.performanceTestType }} - TEST_LOG_LEVEL: debug - REF_NAME: ${{ github.head_ref || github.ref_name }} + 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 }} + 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 }} - GRAFANA_URL: "http://localhost:8080/primary" - GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - WASP_LOG_LEVEL: info - steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: on-demand-vrfv2-plus-performance-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: ${{ inputs.network }} VRFV2 Plus Performance Test - continue-on-error: true - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - name: Mask base64 config - run: | - BASE64_CONFIG_OVERRIDE=$(jq -r '.inputs.base64Config' $GITHUB_EVENT_PATH) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - - name: Merge and export base64 config - uses: ./.github/actions/setup-merge-base64-config - with: - base64Config: ${{ env.BASE64_CONFIG_OVERRIDE }} - - name: Send details to Step Summary - shell: bash - run: | - echo "### chainlink image used for this test run :link:" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.CHAINLINK_IMAGE }}\`" >>$GITHUB_STEP_SUMMARY - echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY - echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY - echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@2967f2287bd3f3ddbac7b476e9568993df01796e # v2.3.27 - with: - test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2plus - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: vrf-test-logs - artifacts_location: ./integration-tests/load/vrfv2plus/logs/ - token: ${{ secrets.GITHUB_TOKEN }} - go_mod_path: ./integration-tests/go.mod - should_cleanup: false - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + SLACK_CHANNEL: ${{ secrets.QA_VRF_SLACK_CHANNEL }} diff --git a/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml b/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml new file mode 100644 index 00000000000..9137cc64d98 --- /dev/null +++ b/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml @@ -0,0 +1,101 @@ +name: On Demand VRFV2 Plus Smoke Tests +on: + workflow_dispatch: + inputs: + test_suite: + description: "Test Suite to run" + required: true + type: choice + default: "All Tests" + options: + - "All Tests" + - "Selected Tests" + test_list_regex: + description: "Regex for 'Selected Tests' to run" + required: false + default: "TestVRFv2Plus$/(Link_Billing|Native_Billing|Direct_Funding)|TestVRFV2PlusWithBHS" + test_config_override_path: + description: Path to a test config file used to override the default test config + required: false + type: string + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string + chainlink_version: + description: Chainlink image version to use + default: develop + required: false + type: string + notify_user_id_on_failure: + description: 'Enter Slack user ID to notify on test failure' + required: false + 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 }} + steps: + - name: Generate Test List JSON + id: set-tests + run: | + if [[ "${{ 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' + fi + TEST_CONFIG_OVERRIDE_PATH=${{ inputs.test_config_override_path }} + + TEST_LIST=$(jq -n -c \ + --arg test_cmd "$TEST_CMD" \ + --arg test_config_override_path "$TEST_CONFIG_OVERRIDE_PATH" \ + '{ + "tests": [ + { + "id": "TestVRFv2Plus_Smoke", + "path": "integration-tests/smoke/vrfv2plus_test.go", + "runs_on": "ubuntu-latest", + "test_env_type": "docker", + "test_cmd": $test_cmd, + "test_config_override_path": $test_config_override_path + } + ] + }') + + echo "test_list=$TEST_LIST" >> $GITHUB_OUTPUT + + run-e2e-tests-workflow: + name: Run E2E Tests + needs: set-tests-to-run + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 + 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 }} + secrets: + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} + GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + 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 }} + SLACK_NOTIFICATION_AFTER_TESTS_CHANNEL_ID: ${{ secrets.QA_VRF_SLACK_CHANNEL }} diff --git a/.github/workflows/operator-ui-ci.yml b/.github/workflows/operator-ui-ci.yml index d854ef207ec..9bce18f8cff 100644 --- a/.github/workflows/operator-ui-ci.yml +++ b/.github/workflows/operator-ui-ci.yml @@ -16,17 +16,6 @@ jobs: name: Breaking Changes GQL Check runs-on: ubuntu-latest steps: - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: operator-ui-ci - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - this-job-name: Breaking Changes GQL Check - continue-on-error: true - - name: Assume role capable of dispatching action uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: @@ -43,7 +32,7 @@ jobs: url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Get operator-ui tag id: get-operator-ui-tag diff --git a/.github/workflows/run-automation-ondemand-e2e-tests.yml b/.github/workflows/run-automation-ondemand-e2e-tests.yml deleted file mode 100644 index 8dac3c56994..00000000000 --- a/.github/workflows/run-automation-ondemand-e2e-tests.yml +++ /dev/null @@ -1,171 +0,0 @@ -name: Run Automation On Demand Tests (TEST WORKFLOW) - -on: - workflow_dispatch: - inputs: - chainlinkVersionUpdate: - description: Chainlink image version to upgrade to (Leave empty to build from head/ref) - required: false - type: string - chainlinkImageUpdate: - description: Chainlink image repo to upgrade to - options: - - QA_ECR - - public.ecr.aws/chainlink/chainlink - type: choice - chainlinkVersion: - description: Chainlink image version to use initially for upgrade test - default: latest - required: true - type: string - chainlinkImage: - description: Chainlink image repo to use initially for upgrade test - required: true - options: - - public.ecr.aws/chainlink/chainlink - - QA_ECR - type: choice - enableChaos: - description: Check to enable chaos tests - type: boolean - default: false - required: true - enableReorg: - description: Check to enable reorg tests - type: boolean - 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)' - required: false - type: string - -jobs: - # Set tests to run based on the workflow inputs - set-tests-to-run: - name: Set tests to run - runs-on: ubuntu-latest - 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 }} - steps: - - name: Determine build to use - id: determine-build - shell: bash - run: | - if [[ "${{ inputs.chainlinkImage }}" == "QA_ECR" ]]; then - echo "image='{{ env.QA_CHAINLINK_IMAGE }}'" >>$GITHUB_OUTPUT - else - echo "image=${{ inputs.chainlinkImage }}" >>$GITHUB_OUTPUT - fi - if [[ "${{ inputs.chainlinkImageUpdate }}" == "QA_ECR" ]]; then - echo "upgrade_image='{{ env.QA_CHAINLINK_IMAGE }}'" >>$GITHUB_OUTPUT - else - echo "upgrade_image=${{ inputs.chainlinkImageUpdate }}" >>$GITHUB_OUTPUT - fi - if [[ -z "${{ inputs.chainlinkVersion }}" ]] && [[ "${{ inputs.chainlinkImage }}" == "QA_ECR" ]]; then - echo "version=${{ github.sha }}" >>$GITHUB_OUTPUT - else - echo "version=${{ inputs.chainlinkVersion }}" >>$GITHUB_OUTPUT - fi - if [[ -z "${{ inputs.chainlinkVersionUpdate }}" ]] && [[ "${{ inputs.chainlinkImageUpdate }}" == "QA_ECR" ]]; then - echo "upgrade_version=${{ github.sha }}" >>$GITHUB_OUTPUT - else - echo "upgrade_version=${{ inputs.chainlinkVersionUpdate }}" >>$GITHUB_OUTPUT - fi - - name: Check if chainlink image check required - id: determine-chainlink-image-check - shell: bash - run: | - chainlink_image_versions="" - if [ "${{ github.event.inputs.chainlinkImage }}" = "QA_ECR" ]; then - chainlink_image_versions+="${{ steps.determine-build.outputs.version }}," - fi - if [ "${{ github.event.inputs.chainlinkImageUpdate }}" = "QA_ECR" ]; then - chainlink_image_versions+="${{ steps.determine-build.outputs.upgrade_version }}" - fi - echo "require_chainlink_image_versions_in_qa_ecr=$chainlink_image_versions" >> $GITHUB_OUTPUT - - name: Set tests to run - id: set-tests - run: | - - # Always run upgrade tests - cat > test_list.yaml <> test_list.yaml <> test_list.yaml <> $GITHUB_OUTPUT - - call-run-e2e-tests-workflow: - name: Run E2E Tests - needs: set-tests-to-run - uses: ./.github/workflows/run-e2e-tests-reusable-workflow.yml - with: - test_list: ${{ needs.set-tests-to-run.outputs.test_list }} - require_chainlink_image_versions_in_qa_ecr: ${{ needs.set-tests-to-run.outputs.require_chainlink_image_versions_in_qa_ecr }} - with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} - test_log_upload_on_failure: true - test_log_upload_retention_days: 7 - secrets: - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - 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 }} - GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_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 }} - diff --git a/.github/workflows/run-e2e-tests-reusable-workflow.yml b/.github/workflows/run-e2e-tests-reusable-workflow.yml deleted file mode 100644 index 4c177f9a137..00000000000 --- a/.github/workflows/run-e2e-tests-reusable-workflow.yml +++ /dev/null @@ -1,740 +0,0 @@ -# This is a reusable workflow that runs E2E tests for Chainlink. -# It is not meant to be run on its own. -name: Run E2E Tests -on: - workflow_call: - inputs: - chainlink_version: - description: 'Enter Chainlink version to use for the tests. Example: "v2.10.0" or sha' - required: false - type: string - test_ids: - description: 'Run tests by test ids separated by commas. Example: "run_all_in_ocr_tests_go,run_TestOCRv2Request_in_ocr2_test_go". Check all test IDs in .github/e2e-tests.yml' - required: false - type: string - test_list: - description: 'Base64 encoded list of tests (YML objects) to run. Example in run-automation-ondemand-e2e-tests.yml' - required: false - type: string - test_workflow: - description: 'Run tests by workflow name. Example: "Run Nightly E2E Tests"' - required: false - type: string - # TODO: Uncomment once Test Config does not have any secrets. Related ticket https://smartcontract-it.atlassian.net/browse/TT-1392 - # test_config_override_base64: - # required: false - # description: The base64-encoded test config override - # type: string - enable_check_test_configurations: - description: 'Set to "true" to enable check-test-configurations job' - required: false - type: boolean - default: false - with_existing_remote_runner_version: - description: 'Use the existing remote runner version for k8s tests. Example: "d3bf5044af33e08be788a2df31c4a745cf69d787"' - required: false - type: string - require_chainlink_image_versions_in_qa_ecr: - description: 'Check Chainlink image versions to be present in QA ECR. If not, build and push the image to QA ECR. Takes comma separated list of Chainlink image versions. Example: "5733cdcda9a9fc6da6343798b119b2ae136146cd,0b7d2c497a508efa5a827714780d908b7b8eda19"' - required: false - type: string - require_chainlink_plugin_versions_in_qa_ecr: - description: 'Check Chainlink plugins versions to be present in QA ECR. If not, build and push the image to QA ECR. Takes comma separated list of Chainlink image versions. Example: "5733cdcda9a9fc6da6343798b119b2ae136146cd,0b7d2c497a508efa5a827714780d908b7b8eda19"' - required: false - type: string - slack_notification_after_tests: - description: 'Set to "true" to send a slack notification after the tests' - required: false - type: boolean - default: false - slack_notification_after_tests_channel_id: - description: 'Slack channel ID to send the notification to' - required: false - type: string - slack_notification_after_tests_name: - description: 'Name of the slack notification' - required: false - type: string - test_log_upload_on_failure: - description: 'Set to "true" to upload the test log on failure as Github artifact' - required: false - type: boolean - default: false - test_log_upload_retention_days: - description: 'Number of days to retain the test log. Default is 3 days' - required: false - type: number - default: 3 - secrets: - TEST_SECRETS_OVERRIDE_BASE64: - required: false - QA_AWS_REGION: - required: true - QA_AWS_ROLE_TO_ASSUME: - required: true - QA_AWS_ACCOUNT_NUMBER: - required: true - QA_PYROSCOPE_INSTANCE: - required: true - QA_PYROSCOPE_KEY: - required: true - QA_KUBECONFIG: - required: true - GRAFANA_INTERNAL_TENANT_ID: - required: true - GRAFANA_INTERNAL_BASIC_AUTH: - required: true - GRAFANA_INTERNAL_HOST: - required: true - GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: - required: true - GH_TOKEN: - required: true - AWS_REGION: - required: true - AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: - required: true - AWS_API_GW_HOST_GRAFANA: - required: true - SLACK_BOT_TOKEN: - required: false - -env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - QA_CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - GITHUB_SHA_PLUGINS: ${{ github.sha }}-plugins - CHAINLINK_ENV_USER: ${{ github.actor }} - CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} - SELECTED_NETWORKS: SIMULATED - MOD_CACHE_VERSION: 1 - TEST_LOG_LEVEL: debug - -jobs: - validate-inputs: - name: Validate workflow inputs - runs-on: ubuntu-latest - outputs: - require_chainlink_image_versions_in_qa_ecr_matrix: ${{ steps.set-required-chainlink-image-versions-matrix.outputs.versions }} - require_chainlink_plugin_versions_in_qa_ecr_matrix: ${{ steps.set-required-chainlink-plugin-versions-matrix.outputs.versions }} - steps: - - name: Check input conditions - run: | - if [[ "${{ inputs.test_ids }}" != "" && "${{ inputs.test_workflow }}" != "" ]]; then - echo "::error::Error: Both 'test_ids' and 'test_workflow' are provided. Please specify only one." - exit 1 - fi - if [[ "${{ secrets.TEST_SECRETS_OVERRIDE_BASE64 }}" != "" ]]; then - echo "Will run tests with custom test secrets" - fi - - name: Install jq - run: sudo apt-get install jq - - name: Create matrix for required Chainlink image versions - id: set-required-chainlink-image-versions-matrix - run: | - if [[ "${{ inputs.require_chainlink_image_versions_in_qa_ecr }}" != '' ]]; then - image_versions=$(echo "${{ inputs.require_chainlink_image_versions_in_qa_ecr }}" | jq -Rc 'split(",") | if . == [""] then [] else . end') - echo "versions=$image_versions" >> $GITHUB_OUTPUT - fi - - name: Create matrix for required Chainlink plugin versions - id: set-required-chainlink-plugin-versions-matrix - run: | - if [[ "${{ inputs.require_chainlink_plugin_versions_in_qa_ecr }}" != '' ]]; then - image_versions=$(echo "${{ inputs.require_chainlink_plugin_versions_in_qa_ecr }}" | jq -Rc 'split(",") | if . == [""] then [] else . end') - echo "versions=$image_versions" >> $GITHUB_OUTPUT - fi - - check-test-configurations: - name: Check test configurations - if: ${{ inputs.enable_check_test_configurations }} - needs: validate-inputs - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Setup Go - uses: ./.github/actions/setup-go - - name: Run Check Tests Command - run: | - cd integration-tests/ - if ! go run citool/main.go check-tests . ../.github/e2e-tests.yml; then - echo "::error::Some E2E test configurations have to be added to .github/e2e-tests.yml. This file defines Github CI configuration for each E2E test or set of E2E tests." && exit 1 - fi - - get_latest_chainlink_release_version: - name: Get latest Chainlink release version - runs-on: ubuntu-latest - environment: integration - outputs: - latest_chainlink_release_version: ${{ steps.get_latest_version.outputs.latest_version }} - steps: - - name: Get Latest Version - id: get_latest_version - run: | - untrimmed_ver=$(curl --header "Authorization: token ${{ secrets.GH_TOKEN }}" --request GET https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .name) - latest_version="${untrimmed_ver:1}" - echo "Latest Chainlink release version: $latest_version" - echo "latest_version=${latest_version}" >> "$GITHUB_OUTPUT" - # Check if latest_version is empty - if [ -z "$latest_version" ]; then - echo "Error: The latest_version is empty. The migration tests need a verison to run." - exit 1 - fi - - load-test-configurations: - name: Load test configurations - needs: [validate-inputs] - runs-on: ubuntu-latest - outputs: - run-docker-tests: ${{ steps.check-matrices.outputs.run-docker-tests }} - run-k8s-tests: ${{ steps.check-matrices.outputs.run-k8s-tests }} - docker-matrix: ${{ steps.set-docker-matrix.outputs.matrix }} - k8s-runner-matrix: ${{ steps.set-k8s-runner-matrix.outputs.matrix }} - steps: - - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Setup Go - uses: ./.github/actions/setup-go - - name: Install jq - run: sudo apt-get install jq - - name: Generate Docker Tests Matrix - id: set-docker-matrix - run: | - cd integration-tests/citool - MATRIX_JSON=$(go run main.go filter --file ${{ github.workspace }}/.github/e2e-tests.yml --test-env-type 'docker' --test-list '${{ inputs.test_list }}' --test-ids '${{ inputs.test_ids }}' --workflow '${{ inputs.test_workflow }}') - echo "Docker tests:" - echo "$MATRIX_JSON" | jq - echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT - - name: Generate K8s Tests Matrix - id: set-k8s-runner-matrix - run: | - cd integration-tests/citool - MATRIX_JSON=$(go run main.go filter --file ${{ github.workspace }}/.github/e2e-tests.yml --test-env-type 'k8s-remote-runner' --test-list '${{ inputs.test_list }}' --test-ids '${{ inputs.test_ids }}' --workflow '${{ inputs.test_workflow }}') - echo "K8s tests:" - echo "$MATRIX_JSON" | jq - echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT - - name: Check Test Matrices - id: check-matrices - run: | - DOCKER_MATRIX_EMPTY=$(echo '${{ steps.set-docker-matrix.outputs.matrix }}' | jq '.tests == null or .tests == []') - K8S_MATRIX_EMPTY=$(echo '${{ steps.set-k8s-runner-matrix.outputs.matrix }}' | jq '.tests == null or .tests == []') - - # Check if jq commands succeeded - if [ $? -ne 0 ]; then - echo "JSON parse error occurred." - exit 1 - fi - - if [[ "$DOCKER_MATRIX_EMPTY" == "true" ]]; then - echo "run-docker-tests=false" >> $GITHUB_OUTPUT - else - echo "run-docker-tests=true" >> $GITHUB_OUTPUT - fi - if [[ "$K8S_MATRIX_EMPTY" == "true" ]]; then - echo "run-k8s-tests=false" >> $GITHUB_OUTPUT - else - echo "run-k8s-tests=true" >> $GITHUB_OUTPUT - fi - - # Check if both matrices are empty - if [[ "$DOCKER_MATRIX_EMPTY" == "true" ]] && [[ "$K8S_MATRIX_EMPTY" == "true" ]]; then - echo "No tests found for inputs: '${{ toJson(inputs) }}'. Both Docker and Kubernetes tests matrices are empty" - exit 1 - fi - shell: bash - - - name: Check if test config override is required for any test - shell: bash - run: | - # Check if the test config override is provided and skip the checks if it is non-empty - # TODO: Uncomment once Test Config does not have any secrets. Related ticket https://smartcontract-it.atlassian.net/browse/TT-1392 - # if [ -n "${{ inputs.test_config_override_base64 }}" ]; then - # echo "Test config override provided. Skipping checks for tests requiring config override." - # exit 0 - # fi - - # Parse the JSON to check for test_config_override_required in Docker matrix - DOCKER_TESTS_REQUIRING_CONFIG_OVERRIDE=$(echo '${{ steps.set-docker-matrix.outputs.matrix }}' | jq 'if .tests then .tests[] | select(has("test_config_override_required") and .test_config_override_required) | .id else empty end' -r) - # Parse the JSON to check for test_config_override_required in Kubernetes matrix - K8S_TESTS_REQUIRING_CONFIG_OVERRIDE=$(echo '${{ steps.set-k8s-runner-matrix.outputs.matrix }}' | jq 'if .tests then .tests[] | select(has("test_config_override_required") and .test_config_override_required) | .id else empty end' -r) - - # Determine if any tests require a configuration override - if [ ! -z "$DOCKER_TESTS_REQUIRING_CONFIG_OVERRIDE" ] || [ ! -z "$K8S_TESTS_REQUIRING_CONFIG_OVERRIDE" ]; then - echo "Tests in .github/e2e-tests.yml requiring test config override:" - if [ ! -z "$DOCKER_TESTS_REQUIRING_CONFIG_OVERRIDE" ]; then - echo $DOCKER_TESTS_REQUIRING_CONFIG_OVERRIDE - fi - if [ ! -z "$K8S_TESTS_REQUIRING_CONFIG_OVERRIDE" ]; then - echo $K8S_TESTS_REQUIRING_CONFIG_OVERRIDE - fi - echo "::error::Error: Some of the tests require a test config override. Please see workflow logs and set 'test_config_override_base64' to run these tests." - exit 1 - else - echo "No tests require a configuration override. Proceeding without overrides." - fi - - - name: Check if test secrets are required for any test - shell: bash - run: | - # Check if the test secret key is provided and skip the checks if it is non-empty - if [ -n "${{ secrets.TEST_SECRETS_OVERRIDE_BASE64 }}" ]; then - echo "Test secret key provided. Skipping checks for tests requiring secrets." - exit 0 - fi - - # Parse the JSON to check for test_secrets_required in Docker matrix - DOCKER_TESTS_REQUIRING_SECRETS=$(echo '${{ steps.set-docker-matrix.outputs.matrix }}' | jq 'if .tests then .tests[] | select(has("test_secrets_required") and .test_secrets_required) | .id else empty end' -r) - # Parse the JSON to check for test_secrets_required in Kubernetes matrix - K8S_TESTS_REQUIRING_SECRETS=$(echo '${{ steps.set-k8s-runner-matrix.outputs.matrix }}' | jq 'if .tests then .tests[] | select(has("test_secrets_required") and .test_secrets_required) | .id else empty end' -r) - - # Determine if any tests require secrets - if [ ! -z "$DOCKER_TESTS_REQUIRING_SECRETS" ] || [ ! -z "$K8S_TESTS_REQUIRING_SECRETS" ]; then - echo "Tests in .github/e2e-tests.yml requiring custom test secrets:" - if [ ! -z "$DOCKER_TESTS_REQUIRING_SECRETS" ]; then - echo $DOCKER_TESTS_REQUIRING_SECRETS - fi - if [ ! -z "$K8S_TESTS_REQUIRING_SECRETS" ]; then - echo $K8S_TESTS_REQUIRING_SECRETS - fi - echo "::error::Error: Some of the tests require custom test secrets to run. Please see workflow logs and set 'test_secrets_override_key' to run these tests." - exit 1 - else - echo "No tests require secrets. Proceeding without additional secret setup." - fi - - # Build Chainlink images required for the tests - require-chainlink-image-versions-in-qa-ecr: - name: Build Chainlink image - needs: [validate-inputs, load-test-configurations] - if: ${{ needs.validate-inputs.outputs.require_chainlink_image_versions_in_qa_ecr_matrix != '' }} - runs-on: ubuntu-latest - environment: integration - permissions: - id-token: write - contents: read - env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - strategy: - matrix: - version: ${{ fromJson(needs.validate-inputs.outputs.require_chainlink_image_versions_in_qa_ecr_matrix) }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Build Chainlink image for ${{ matrix.version }} and push it to QA ECR - uses: ./.github/actions/build-chainlink-image - with: - dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ matrix.version }} - tag_suffix: '' - check_image_exists: 'true' - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - # Build Chainlink plugins required for the tests - require-chainlink-plugin-versions-in-qa-ecr: - name: Build Chainlink plugins - needs: [validate-inputs, load-test-configurations] - if: ${{ needs.validate-inputs.outputs.require_chainlink_plugin_versions_in_qa_ecr_matrix != '' }} - runs-on: ubuntu-latest - environment: integration - permissions: - id-token: write - contents: read - env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - strategy: - matrix: - version: ${{ fromJson(needs.validate-inputs.outputs.require_chainlink_plugin_versions_in_qa_ecr_matrix) }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Build Chainlink plugins image for ${{ matrix.version }} - uses: ./.github/actions/build-chainlink-image - with: - dockerfile: plugins/chainlink.Dockerfile - git_commit_sha: ${{ matrix.version }} - tag_suffix: '-plugins' - check_image_exists: 'true' - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - - # Run Docker tests - run-docker-tests: - name: Run ${{ matrix.tests.id }} - needs: [load-test-configurations, require-chainlink-image-versions-in-qa-ecr, require-chainlink-plugin-versions-in-qa-ecr, get_latest_chainlink_release_version] - # Run when none of the needed jobs fail or are cancelled (skipped or successful jobs are ok) - if: ${{ needs.load-test-configurations.outputs.run-docker-tests == 'true' && always() && !failure() && !cancelled() }} - runs-on: ${{ matrix.tests.runs_on }} - strategy: - fail-fast: false - matrix: ${{fromJson(needs.load-test-configurations.outputs.docker-matrix)}} - environment: integration - permissions: - actions: read - checks: write - pull-requests: write - id-token: write - contents: read - env: - LATEST_CHAINLINK_RELEASE_VERSION: ${{ needs.get_latest_chainlink_release_version.outputs.latest_chainlink_release_version }} - steps: - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: e2e_tests_${{ matrix.tests.id_sanitized }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Run E2E Tests / Run ${{ matrix.tests.id }} - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true - - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Install jq - run: sudo apt-get install -y jq - - name: Show test configuration - run: echo '${{ toJson(matrix.tests) }}' | jq . - - name: Setup Go - uses: ./.github/actions/setup-go - - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 - id: setup-gap - with: - aws-region: ${{ secrets.AWS_REGION }} - aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - duplicate-authorization-header: "true" - - - name: Run tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - env: - DETACH_RUNNER: true - with: - test_command_to_run: ${{ matrix.tests.test_cmd }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: cd ./integration-tests && go mod download - test_secrets_override_base64: ${{ secrets.TEST_SECRETS_OVERRIDE_BASE64 }} - # TODO: Uncomment once Test Config does not have any secrets. Related ticket https://smartcontract-it.atlassian.net/browse/TT-1392 - # test_config_override_base64: ${{ inputs.test_config_override_base64 }} - test_config_chainlink_version: ${{ matrix.tests.test_inputs.chainlink_version || inputs.chainlink_version || github.sha }} - test_config_chainlink_upgrade_version: ${{ matrix.tests.test_inputs.chainlink_upgrade_version }} - test_config_chainlink_postgres_version: ${{ matrix.tests.test_inputs.chainlink_postgres_version }} - test_config_selected_networks: ${{ matrix.tests.test_inputs.selected_networks || env.SELECTED_NETWORKS}} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_type: ${{ matrix.tests.test_inputs.test_type }} - test_suite: ${{ matrix.tests.test_inputs.test_suite }} - aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.tests.id_sanitized }}-test-logs - artifacts_location: | - ./integration-tests/smoke/logs/ - ./integration-tests/smoke/db_dumps/ - /tmp/gotest.log - publish_check_name: ${{ matrix.tests.id_sanitized }} - token: ${{ secrets.GH_TOKEN }} - no_cache: true # Do not restore cache since go was already configured in the previous step - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: "" - should_tidy: "false" - go_coverage_src_dir: /var/tmp/go-coverage - go_coverage_dest_dir: ${{ github.workspace }}/.covdata - DEFAULT_CHAINLINK_IMAGE: ${{ matrix.tests.test_inputs.chainlink_image || env.CHAINLINK_IMAGE }} - DEFAULT_CHAINLINK_UPGRADE_IMAGE: ${{ matrix.tests.test_inputs.chainlink_upgrade_image }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.tests.pyroscope_env != '' && secrets.QA_PYROSCOPE_INSTANCE || '' }} - DEFAULT_PYROSCOPE_KEY: ${{ matrix.tests.pyroscope_env != '' && secrets.QA_PYROSCOPE_KEY || '' }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.tests.pyroscope_env != '' && 'true' || '' }} - - - name: Upload test log as Github artifact - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: inputs.test_log_upload_on_failure && failure() - with: - name: test_log_${{ matrix.tests.id_sanitized }} - path: /tmp/gotest.log - retention-days: ${{ inputs.test_log_upload_retention_days }} - continue-on-error: true - - # Run K8s tests using old remote runner - - prepare-remote-runner-test-image: - needs: [load-test-configurations, require-chainlink-image-versions-in-qa-ecr, require-chainlink-plugin-versions-in-qa-ecr] - if: ${{ needs.load-test-configurations.outputs.run-k8s-tests == 'true' && always() && !failure() && !cancelled() }} - name: Prepare remote runner test image - runs-on: ubuntu-latest - environment: integration - permissions: - actions: read - checks: write - pull-requests: write - id-token: write - contents: read - outputs: - remote-runner-version: ${{ steps.set-remote-runner-version.outputs.remote-runner-version }} - env: - ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests - steps: - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Build Test Runner Image - uses: ./.github/actions/build-test-image - if: ${{ inputs.with_existing_remote_runner_version == '' }} - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - - name: Set Remote Runner Version - id: set-remote-runner-version - run: | - if [[ -z "${{ inputs.with_existing_remote_runner_version }}" ]]; then - echo "remote-runner-version=${{ github.sha }}" >> $GITHUB_OUTPUT - else - echo "remote-runner-version=${{ inputs.with_existing_remote_runner_version }}" >> $GITHUB_OUTPUT - fi - - run-k8s-runner-tests: - needs: [load-test-configurations, prepare-remote-runner-test-image, require-chainlink-image-versions-in-qa-ecr, require-chainlink-plugin-versions-in-qa-ecr, get_latest_chainlink_release_version] - if: ${{ needs.load-test-configurations.outputs.run-k8s-tests == 'true' && always() && !failure() && !cancelled() }} - name: Run ${{ matrix.tests.id }} - runs-on: ${{ matrix.tests.runs_on }} - strategy: - fail-fast: false - matrix: ${{fromJson(needs.load-test-configurations.outputs.k8s-runner-matrix)}} - environment: integration - permissions: - actions: read - checks: write - pull-requests: write - id-token: write - contents: read - env: - LATEST_CHAINLINK_RELEASE_VERSION: ${{ needs.get_latest_chainlink_release_version.outputs.latest_chainlink_release_version }} - steps: - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: e2e_tests_${{ matrix.tests.id_sanitized }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Run E2E Tests / Run ${{ matrix.tests.id }} - continue-on-error: true - - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Install jq - run: sudo apt-get install -y jq - - name: Show Test Configuration - run: echo '${{ toJson(matrix.tests) }}' | jq . - - name: Show Remote Runner Version - run: | - echo "Remote Runner Version: ${{ needs.prepare-remote-runner-test-image.outputs.remote-runner-version }}" - - - name: Run tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 - env: - DETACH_RUNNER: true - RR_MEM: ${{ matrix.tests.remote_runner_memory }} - TEST_ARGS: -test.timeout 900h -test.memprofile memprofile.out -test.cpuprofile profile.out - ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-tests:${{ needs.prepare-remote-runner-test-image.outputs.remote-runner-version }} - INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com - # We can comment these out when we have a stable soak test and aren't worried about resource consumption - TEST_UPLOAD_CPU_PROFILE: true - TEST_UPLOAD_MEM_PROFILE: true - TEST_LOG_LEVEL: debug - REF_NAME: ${{ github.head_ref || github.ref_name }} - with: - test_command_to_run: ${{ matrix.tests.test_cmd }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs - test_download_vendor_packages_command: make gomod - test_secrets_override_base64: ${{ secrets.TEST_SECRETS_OVERRIDE_BASE64 }} - # TODO: Uncomment once Test Config does not have any secrets. Related ticket https://smartcontract-it.atlassian.net/browse/TT-1392 - # test_config_override_base64: ${{ inputs.test_config_override_base64 }} - test_config_chainlink_version: ${{ matrix.tests.test_inputs.chainlink_version || inputs.chainlink_version || github.sha }} - test_config_chainlink_upgrade_version: ${{ matrix.tests.test_inputs.chainlink_upgrade_version }} - test_config_chainlink_postgres_version: ${{ matrix.tests.test_inputs.chainlink_postgres_version }} - test_config_selected_networks: ${{ matrix.tests.test_inputs.selected_networks || env.SELECTED_NETWORKS}} - test_config_logging_run_id: ${{ github.run_id }} - test_config_logstream_log_targets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - test_type: ${{ matrix.tests.test_inputs.test_type }} - test_suite: ${{ matrix.tests.test_inputs.test_suite }} - token: ${{ secrets.GH_TOKEN }} - should_cleanup: false - no_cache: true # Do not restore cache since go was already configured in the previous step - go_mod_path: ./integration-tests/go.mod - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - DEFAULT_CHAINLINK_IMAGE: ${{ matrix.tests.test_inputs.chainlink_image || env.CHAINLINK_IMAGE }} - DEFAULT_CHAINLINK_UPGRADE_IMAGE: ${{ matrix.tests.test_inputs.chainlink_upgrade_image }} - DEFAULT_LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: "http://localhost:8080/primary" - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - DEFAULT_GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - DEFAULT_PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} - DEFAULT_PYROSCOPE_SERVER_URL: ${{ matrix.tests.pyroscope_env != '' && secrets.QA_PYROSCOPE_INSTANCE || '' }} - DEFAULT_PYROSCOPE_KEY: ${{ matrix.tests.pyroscope_env != '' && secrets.QA_PYROSCOPE_KEY || '' }} - DEFAULT_PYROSCOPE_ENABLED: ${{ matrix.tests.pyroscope_env != '' && 'true' || '' }} - - - name: Upload test log as Github artifact - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: inputs.test_log_upload_on_failure && failure() - with: - name: test_log_${{ matrix.tests.id_sanitized }} - path: /tmp/gotest.log - retention-days: ${{ inputs.test_log_upload_retention_days }} - continue-on-error: true - - after_tests: - needs: [run-docker-tests, run-k8s-runner-tests] - if: always() - name: After tests notifications - runs-on: ubuntu-latest - steps: - - name: Determine combined test results - id: combine_results - run: | - docker_result="${{ needs.run-docker-tests.result }}" - k8s_result="${{ needs.run-k8s-runner-tests.result }}" - - function map_outcome { - case "$1" in - success|skipped) - echo "success" - ;; - cancelled) - echo "cancelled" - ;; - *) - echo "failure" - ;; - esac - } - - combined_docker_result=$(map_outcome $docker_result) - combined_k8s_result=$(map_outcome $k8s_result) - - if [[ $combined_docker_result == "failure" || $combined_k8s_result == "failure" ]]; then - echo "result=failure" >> $GITHUB_OUTPUT - elif [[ $combined_docker_result == "cancelled" || $combined_k8s_result == "cancelled" ]]; then - echo "result=cancelled" >> $GITHUB_OUTPUT - else - echo "result=success" >> $GITHUB_OUTPUT - fi - - - name: Send Slack notification - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - if: ${{ inputs.slack_notification_after_tests }} - id: slack - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - with: - channel-id: ${{ inputs.slack_notification_after_tests_channel_id }} - payload: | - { - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ inputs.slack_notification_after_tests_name }} - ${{ steps.combine_results.outputs.result == 'failure' && 'Failed :x:' || steps.combine_results.outputs.result == 'cancelled' && 'Cancelled :warning:' || 'Passed :white_check_mark:' }}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Build Details>" - } - } - ] - } - - # Run K8s tests using new remote runner - # remote-runner-k8s-tests: - # runs-on: ubuntu-latest - # container: - # image: golang:1.18 - # steps: - # - name: Checkout repository - # uses: actions/checkout@v2 - - # - name: Set up Go - # uses: actions/setup-go@v2 - # with: - # go-version: '1.18' - - # - name: Load Runner Config - # run: echo "$RUNNER_CONFIG" > runner.toml - # env: - # RUNNER_CONFIG: | - # # Runner configuration - # detached_mode = true - # debug = false - - # [[test_runs]] - # namespace = "dev-env" - # rbac_role_name = "dev-role" - # rbac_service_account_name = "dev-service-account" - # sync_value = "unique-sync-value-1" - # ttl_seconds_after_finished = 300 - # image_registry_url = "https://myregistry.dev/" - # image_name = "dev-image" - # image_tag = "v1.0.0" - # test_name = "TestMercuryLoad/all_endpoints" - # test_config_base64_env_name = "CONFIG_ENV_DEV" - # test_config_file_path = "/configs/dev/test-config.toml" - # test_config_base64 = "dGVzdCBjb25maWcgdmFsdWUgZGV2" - # test_timeout = "30m" - # resources_requests_cpu = "500m" - # resources_requests_memory = "1Gi" - # resources_limits_cpu = "1000m" - # resources_limits_memory = "2Gi" - # job_count = 2 - # chart_path = "/charts/dev" - # [envs] - # WASP_LOG_LEVEL = "info" - # TEST_LOG_LEVEL = "info" - # MERCURY_TEST_LOG_LEVEL = "info" - - # [[test_runs]] - # namespace = "prod-env" - # rbac_role_name = "prod-role" - # rbac_service_account_name = "prod-service-account" - # sync_value = "unique-sync-value-2" - # ttl_seconds_after_finished = 600 - # image_registry_url = "https://myregistry.prod/" - # image_name = "prod-image" - # image_tag = "v1.0.1" - # test_name = "TestMercuryLoad/all_endpoints" - # test_config_base64_env_name = "CONFIG_ENV_PROD" - # test_config_file_path = "/configs/prod/test-config.toml" - # test_config_base64 = "dGVzdCBjb25maWcgdmFsdWUgcHJvZA==" - # test_timeout = "45m" - # resources_requests_cpu = "800m" - # resources_requests_memory = "2Gi" - # resources_limits_cpu = "1500m" - # resources_limits_memory = "4Gi" - # job_count = 3 - # chart_path = "/charts/prod" - # [envs] - # WASP_LOG_LEVEL = "info" - # TEST_LOG_LEVEL = "info" - # MERCURY_TEST_LOG_LEVEL = "info" - - # # Schedule the tests in K8s in remote runner - # - name: Run Kubernetes Tests - # run: go run ./cmd/main.go run -c runner.toml diff --git a/.github/workflows/run-nightly-e2e-tests.yml b/.github/workflows/run-nightly-e2e-tests.yml index ab12b36555f..0637363ca76 100644 --- a/.github/workflows/run-nightly-e2e-tests.yml +++ b/.github/workflows/run-nightly-e2e-tests.yml @@ -5,21 +5,34 @@ on: # Run every night at midnight UTC (0:00 AM) - cron: '0 0 * * *' workflow_dispatch: + # Useful when running the workflow manually + inputs: + chainlink_version: + description: 'Enter Chainlink version to use for the tests. Example: "v2.10.0" or sha' + required: true + type: string + default: develop + slack_notification_after_tests: + description: 'Notify on Slack after tests' + required: false + type: string jobs: call-run-e2e-tests-workflow: name: Run E2E Tests - uses: ./.github/workflows/run-e2e-tests-reusable-workflow.yml + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 with: - chainlink_version: develop - test_workflow: Run Nightly E2E Tests - slack_notification_after_tests: true + chainlink_version: ${{ inputs.chainlink_version || 'develop' }} + test_path: .github/e2e-tests.yml + test_trigger: Nightly E2E Tests + slack_notification_after_tests: ${{ inputs.slack_notification_after_tests || 'always' }} slack_notification_after_tests_channel_id: "#team-test-tooling-internal" slack_notification_after_tests_name: Nightly E2E Tests secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} @@ -27,6 +40,9 @@ jobs: GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} 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 }} diff --git a/.github/workflows/run-selected-e2e-tests.yml b/.github/workflows/run-selected-e2e-tests.yml index ab064531fd3..b53bc756f4d 100644 --- a/.github/workflows/run-selected-e2e-tests.yml +++ b/.github/workflows/run-selected-e2e-tests.yml @@ -16,16 +16,10 @@ on: description: 'Enter the secret key to override test secrets' required: false type: string - # TODO: Uncomment once Test Config does not have any secrets. Related ticket https://smartcontract-it.atlassian.net/browse/TT-1392 - # test_config_override_base64: - # required: false - # description: The base64-encoded test config override - # type: string - enable_check_test_configurations: - description: 'Set to "true" to enable check-test-configurations job' + test_config_override_path: + description: 'Path to a test config file used to override the default test config' required: false - type: boolean - default: false + type: string with_existing_remote_runner_version: description: 'Use the existing remote runner version for k8s tests. Example: "d3bf5044af33e08be788a2df31c4a745cf69d787"' required: false @@ -41,19 +35,18 @@ run-name: ${{ inputs.workflow_run_name }} jobs: call-run-e2e-tests-workflow: name: Run E2E Tests - uses: ./.github/workflows/run-e2e-tests-reusable-workflow.yml + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@f1f2dac0a20f0e02408eb7f528c768fe95c39229 with: chainlink_version: ${{ github.event.inputs.chainlink_version }} + test_path: .github/e2e-tests.yml test_ids: ${{ github.event.inputs.test_ids }} - # TODO: Uncomment once Test Config does not have any secrets. Related ticket https://smartcontract-it.atlassian.net/browse/TT-1392 - # test_config_override_base64: ${{ github.event.inputs.test_config_override_base64 }} + test_config_override_path: ${{ github.event.inputs.test_config_override_path }} with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} - # Use fromJSON to convert string to boolean. More info: https://github.com/actions/runner/issues/2206#issuecomment-1532246677 - enable_check_test_configurations: ${{ fromJSON(github.event.inputs.enable_check_test_configurations) }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + 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 }} @@ -61,10 +54,12 @@ jobs: GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_URL: ${{ secrets.LOKI_URL }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} 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 }} - diff --git a/.github/workflows/sigscanner.yml b/.github/workflows/sigscanner.yml index 5d22f79ab55..3be733ccfa2 100644 --- a/.github/workflows/sigscanner.yml +++ b/.github/workflows/sigscanner.yml @@ -23,14 +23,3 @@ jobs: echo "❌ Commit is NOT verified" exit 1 fi - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: sigscanner - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: sigscanner-check - continue-on-error: true diff --git a/.github/workflows/solidity-foundry-artifacts.yml b/.github/workflows/solidity-foundry-artifacts.yml index 50a77e2846b..f8a57e3f1c7 100644 --- a/.github/workflows/solidity-foundry-artifacts.yml +++ b/.github/workflows/solidity-foundry-artifacts.yml @@ -18,32 +18,46 @@ on: - "shared" - "transmission" - "vrf" + commit_to_use: + type: string + description: 'commit SHA to use for artifact generation; if empty HEAD will be used' + required: false base_ref: - description: 'commit or tag to be used as base reference, when looking for modified Solidity files' + description: 'commit or tag to use as base reference, when looking for modified Solidity files' required: true + link_with_jira: + description: 'link generated artifacts with Jira issues?' + type: boolean + default: true + required: false env: FOUNDRY_PROFILE: ci + # Unfortunately, we can't use the "default" field in the inputs section, because it does not have + # access to the workflow context + head_ref: ${{ inputs.commit_to_use || github.sha }} jobs: changes: name: Detect changes runs-on: ubuntu-latest outputs: - changes: ${{ steps.changes.outputs.sol }} product_changes: ${{ steps.changes-transform.outputs.product_changes }} product_files: ${{ steps.changes-transform.outputs.product_files }} changeset_changes: ${{ steps.changes-dorny.outputs.changeset }} changeset_files: ${{ steps.changes-dorny.outputs.changeset_files }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 + with: + ref: ${{ env.head_ref }} - name: Find modified contracts uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes + id: changes-dorny with: list-files: 'csv' base: ${{ inputs.base_ref }} + # This is a valid input, see https://github.com/dorny/paths-filter/pull/226 predicate-quantifier: every filters: | ignored: &ignored @@ -61,12 +75,12 @@ jobs: - *ignored sol: - modified|added: 'contracts/src/v0.8/**/*.sol' - - *ignored + - *ignored product: &product - - modified|added: 'contracts/src/v0.8/${{ inputs.product }}/**/*.sol' + - modified|added: 'contracts/src/v0.8/${{ inputs.product }}/**/*.sol' - *ignored changeset: - - modified|added: 'contracts/.changeset/!(README)*.md' + - modified|added: 'contracts/.changeset/!(README)*.md' # Manual transformation needed, because shared contracts have a different folder structure - name: Transform modified files @@ -75,47 +89,45 @@ jobs: run: | if [ "${{ inputs.product }}" = "shared" ]; then echo "::debug:: Product is shared, transforming changes" - if [[ "${{ steps.changes.outputs.product }}" == "true" && "${{ steps.changes.outputs.other_shared }}" == "true" ]]; then + 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" echo "product_changes=true" >> $GITHUB_OUTPUT - echo "product_files=${{ steps.changes.outputs.product_files }},${{ steps.changes.outputs.other_shared_files }}" >> $GITHUB_OUTPUT - elif [[ "${{ steps.changes.outputs.product }}" == "false" && "${{ steps.changes.outputs.other_shared }}" == "true" ]]; then + echo "product_files=${{ steps.changes-dorny.outputs.product_files }},${{ steps.changes-dorny.outputs.other_shared_files }}" >> $GITHUB_OUTPUT + elif [[ "${{ steps.changes-dorny.outputs.product }}" == "false" && "${{ steps.changes-dorny.outputs.other_shared }}" == "true" ]]; then echo "::debug:: Only contracts in' interfaces' and root folders were modified" echo "product_changes=true" >> $GITHUB_OUTPUT - echo "product_files=${{ steps.changes.outputs.other_shared_files }}" >> $GITHUB_OUTPUT - elif [[ "${{ steps.changes.outputs.product }}" == "true" && "${{ steps.changes.outputs.other_shared }}" == "false" ]]; then + echo "product_files=${{ steps.changes-dorny.outputs.other_shared_files }}" >> $GITHUB_OUTPUT + elif [[ "${{ steps.changes-dorny.outputs.product }}" == "true" && "${{ steps.changes-dorny.outputs.other_shared }}" == "false" ]]; then echo "::debug:: Only contracts in 'shared' folder were modified" echo "product_changes=true" >> $GITHUB_OUTPUT - echo "product_files=${{ steps.changes.outputs.product_files }}" >> $GITHUB_OUTPUT + echo "product_files=${{ steps.changes-dorny.outputs.product_files }}" >> $GITHUB_OUTPUT else echo "::debug:: No contracts were modified" echo "product_changes=false" >> $GITHUB_OUTPUT echo "product_files=" >> $GITHUB_OUTPUT fi else - echo "product_changes=${{ steps.changes.outputs.product }}" >> $GITHUB_OUTPUT - echo "product_files=${{ steps.changes.outputs.product_files }}" >> $GITHUB_OUTPUT + echo "product_changes=${{ steps.changes-dorny.outputs.product }}" >> $GITHUB_OUTPUT + echo "product_files=${{ steps.changes-dorny.outputs.product_files }}" >> $GITHUB_OUTPUT fi - name: Check for changes outside of artifact scope uses: ./.github/actions/validate-artifact-scope - if: ${{ steps.changes.outputs.sol == 'true' }} + if: ${{ steps.changes-dorny.outputs.sol == 'true' }} with: - sol_files: ${{ steps.changes.outputs.sol_files }} + sol_files: ${{ steps.changes-dorny.outputs.sol_files }} product: ${{ inputs.product }} - gather-basic-info: - name: Gather basic info - if: ${{ needs.changes.outputs.product_changes == 'true' }} + prepare-workflow-inputs: + name: Prepare workflow inputs runs-on: ubuntu-22.04 needs: [ changes ] outputs: foundry_version: ${{ steps.extract-foundry-version.outputs.foundry-version }} + generate_code_coverage: ${{ steps.skip-code-coverage.outputs.generate_code_coverage }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 + uses: actions/checkout@v4.2.1 - name: Extract Foundry version id: extract-foundry-version @@ -123,250 +135,35 @@ jobs: with: working-directory: contracts - - name: Copy modified changesets - if: ${{ needs.changes.outputs.changeset_changes == 'true' }} - run: | - mkdir -p contracts/changesets - files="${{ needs.changes.outputs.changeset_files }}" - IFS=",' - for changeset in $files; do - echo "::debug:: Copying $changeset" - cp $changeset contracts/changesets - done - - - name: Generate basic info and modified contracts list - shell: bash - run: | - echo "Commit SHA used to generate artifacts: ${{ github.sha }}" > contracts/commit_sha_base_ref.txt - echo "Base reference SHA used to find modified contracts: ${{ inputs.base_ref }}" >> contracts/commit_sha_base_ref.txt - - IFS=',' read -r -a modified_files <<< "${{ needs.changes.outputs.product_files }}" - echo "# Modified contracts:" > contracts/modified_contracts.md - for file in "${modified_files[@]}"; do - echo " - [$file](${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/$file)" >> contracts/modified_contracts.md - echo "$file" >> contracts/modified_contracts.txt - done - - - name: Upload basic info and modified contracts list - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 - timeout-minutes: 2 - continue-on-error: true - with: - name: tmp-basic-info - path: | - contracts/modified_contracts.md - contracts/modified_contracts.txt - contracts/commit_sha_base_ref.txt - contracts/changesets - retention-days: 7 - - # some of the artifacts can only be generated on product level, and we cannot scope them to single contracts - # some product-level modifications might also require shared contracts changes, so if these happened we need to generate artifacts for shared contracts as well - coverage-and-book: - if: ${{ needs.changes.outputs.product_changes == 'true' }} - name: Generate Docs and Code Coverage reports - runs-on: ubuntu-22.04 - needs: [changes, gather-basic-info] - steps: - - name: Prepare exclusion list - id: prepare-exclusion-list - run: | - cat < coverage_exclusions.json - ["automation", "functions", "vrf"] - EOF - coverage_exclusions=$(cat coverage_exclusions.json | jq -c .) - echo "coverage_exclusions=$coverage_exclusions" >> $GITHUB_OUTPUT - - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - - - name: Create directories - shell: bash + - name: Should skip code coverage report + id: skip-code-coverage run: | - mkdir -p contracts/code-coverage - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 - with: - version: ${{ needs.gather-basic-info.outputs.foundry_version }} - - # required for code coverage report generation - - name: Setup LCOV - uses: hrishikesh-kadam/setup-lcov@f5da1b26b0dcf5d893077a3c4f29cf78079c841d # v1.0.0 - - - name: Run Forge build for product contracts - if: ${{ needs.changes.outputs.product_changes == 'true' }} - run: | - forge --version - forge build - working-directory: contracts - env: - FOUNDRY_PROFILE: ${{ inputs.product }} - - - name: Run coverage for product contracts - if: ${{ !contains(fromJson(steps.prepare-exclusion-list.outputs.coverage_exclusions), inputs.product) && needs.changes.outputs.product_changes == 'true' }} - working-directory: contracts - run: forge coverage --report lcov --report-file code-coverage/lcov.info - env: - FOUNDRY_PROFILE: ${{ inputs.product }} - - - name: Generate Code Coverage HTML report for product contracts - if: ${{ !contains(fromJson(steps.prepare-exclusion-list.outputs.coverage_exclusions), inputs.product) && needs.changes.outputs.product_changes == 'true' }} - shell: bash - working-directory: contracts - run: genhtml code-coverage/lcov.info --branch-coverage --output-directory code-coverage - - - name: Run Forge doc for product contracts - if: ${{ needs.changes.outputs.product_changes == 'true' }} - run: forge doc --build -o docs - working-directory: contracts - env: - FOUNDRY_PROFILE: ${{ inputs.product }} - - - name: Upload Artifacts for product contracts - if: ${{ needs.changes.outputs.product_changes == 'true' }} - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 - timeout-minutes: 2 - continue-on-error: true - with: - name: tmp-${{ inputs.product }}-artifacts - path: | - contracts/docs - contracts/code-coverage/lcov-.info - contracts/code-coverage - retention-days: 7 - - # Generates UML diagrams and Slither reports for modified contracts - uml-static-analysis: - if: ${{ needs.changes.outputs.product_changes == 'true' }} - name: Generate UML and Slither reports for modified contracts - runs-on: ubuntu-22.04 - needs: [changes, gather-basic-info] - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 - with: - version: ${{ needs.gather-basic-info.outputs.foundry_version }} - - - name: Install Sol2uml - run: | - npm link sol2uml --only=production - - - name: Set up Python - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 - with: - python-version: '3.8' - - - name: Install solc-select and solc - uses: ./.github/actions/setup-solc-select - with: - to_install: '0.8.19' - to_use: '0.8.19' - - - name: Install Slither - uses: ./.github/actions/setup-slither - - - name: Generate UML - shell: bash - run: | - contract_list="${{ needs.changes.outputs.product_files }}" - - # modify remappings so that solc can find dependencies - ./contracts/scripts/ci/modify_remappings.sh contracts contracts/remappings.txt - mv remappings_modified.txt remappings.txt - - ./contracts/scripts/ci/generate_uml.sh "./" "contracts/uml-diagrams" "$contract_list" - - - name: Generate Slither Markdown reports - run: | - contract_list="${{ needs.changes.outputs.product_files }}" - - echo "::debug::Processing contracts: $contract_list" - ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" contracts/configs/slither/.slither.config-artifacts.json "." "$contract_list" "contracts/slither-reports" "--solc-remaps @=contracts/node_modules/@" - - - name: Upload UMLs and Slither reports - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 - timeout-minutes: 10 - continue-on-error: true - with: - name: tmp-contracts-artifacts - path: | - contracts/uml-diagrams - contracts/slither-reports - retention-days: 7 - - - name: Validate if all Slither run for all contracts - uses: ./.github/actions/validate-solidity-artifacts - with: - validate_slither_reports: 'true' - validate_uml_diagrams: 'true' - slither_reports_path: 'contracts/slither-reports' - uml_diagrams_path: 'contracts/uml-diagrams' - sol_files: ${{ needs.changes.outputs.product_files }} - - gather-all-artifacts: - name: Gather all artifacts - if: ${{ needs.changes.outputs.product_changes == 'true' }} - runs-on: ubuntu-latest - needs: [coverage-and-book, uml-static-analysis, gather-basic-info, changes] - steps: - - name: Download all artifacts - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 - with: - path: review_artifacts - merge-multiple: true - - - name: Upload all artifacts as single package - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 - with: - name: review-artifacts-${{ inputs.product }}-${{ github.sha }} - path: review_artifacts - retention-days: 60 - - - name: Remove temporary artifacts - uses: geekyeggo/delete-artifact@24928e75e6e6590170563b8ddae9fac674508aa1 # v5.0 - with: - name: tmp-* - - - name: Print Artifact URL in job summary - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - ARTIFACTS=$(gh api -X GET repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts) - ARTIFACT_ID=$(echo "$ARTIFACTS" | jq '.artifacts[] | select(.name=="review-artifacts-${{ inputs.product }}-${{ github.sha }}") | .id') - echo "Artifact ID: $ARTIFACT_ID" - - echo "# Solidity Review Artifact Generated" >> $GITHUB_STEP_SUMMARY - echo "Base Ref used: **${{ inputs.base_ref }}**" >> $GITHUB_STEP_SUMMARY - echo "Commit SHA used: **${{ github.sha }}**" >> $GITHUB_STEP_SUMMARY - echo "[Artifact URL](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/$ARTIFACT_ID)" >> $GITHUB_STEP_SUMMARY + if [[ "${{ inputs.product }}" = "automation" || "${{ inputs.product }}" = "vrf" || "${{ inputs.product }}" = "functions" ]]; then + echo "generate_code_coverage=false" >> $GITHUB_OUTPUT + else + echo "generate_code_coverage=true" >> $GITHUB_OUTPUT + fi - notify-no-changes: - if: ${{ needs.changes.outputs.product_changes == 'false' }} - needs: [changes] - runs-on: ubuntu-latest - steps: - - name: Print warning in job summary - shell: bash - run: | - echo "# Solidity Review Artifact NOT Generated" >> $GITHUB_STEP_SUMMARY - echo "Base Ref used: **${{ inputs.base_ref }}**" >> $GITHUB_STEP_SUMMARY - echo "Commit SHA used: **${{ github.sha }}**" >> $GITHUB_STEP_SUMMARY - echo "## Reason: No modified Solidity files found for ${{ inputs.product }}" >> $GITHUB_STEP_SUMMARY - echo "* no modified Solidity files found between ${{ inputs.base_ref }} and ${{ github.sha }} commits" >> $GITHUB_STEP_SUMMARY - echo "* or they are located outside of ./contracts/src/v0.8 folder" >> $GITHUB_STEP_SUMMARY - echo "* or they were limited to test files" >> $GITHUB_STEP_SUMMARY - exit 1 + generate-artifacts: + name: Generate Solidity Review Artifacts + needs: [changes, prepare-workflow-inputs] + uses: smartcontractkit/.github/.github/workflows/solidity-review-artifacts.yml@b6e37806737eef87e8c9137ceeb23ef0bff8b1db # validate-solidity-artifacts@0.1.0 + with: + product: ${{ inputs.product }} + commit_to_use: ${{ inputs.commit_to_use }} + base_ref: ${{ inputs.base_ref }} + product_changes: ${{ needs.changes.outputs.product_changes }} + product_files: ${{ needs.changes.outputs.product_files }} + changeset_changes: ${{ needs.changes.outputs.changeset_changes }} + changeset_files: ${{ needs.changes.outputs.changeset_files }} + foundry_version: ${{ needs.prepare-workflow-inputs.outputs.foundry_version }} + contracts_directory: './contracts' + generate_code_coverage: ${{ needs.prepare-workflow-inputs.outputs.generate_code_coverage == 'true' }} + link_with_jira: ${{ inputs.link_with_jira }} + jira_host: ${{ vars.JIRA_HOST }} + install_semver: false + slither_config_file_path: 'contracts/configs/slither/.slither.config-artifacts.json' + lcov_prune_script_path: 'scripts/lcov_prune' + secrets: + jira_username: ${{ secrets.JIRA_USERNAME }} + jira_api_token: ${{ secrets.JIRA_API_TOKEN }} diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 906cb76ffe5..6b872dc2a0a 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -8,6 +8,11 @@ env: # * use the top-level matrix to decide, which checks should run for each product. # * when enabling code coverage, remember to adjust the minimum code coverage as it's set to 98.5% by default. +# This pipeline will run product tests only if product-specific contracts were modified or if broad-impact changes were made (e.g. changes to this pipeline, Foundry configuration, etc.) +# For modified contracts we use a LLM to extract new issues introduced by the changes. For new contracts full report is delivered. +# Slither has a default configuration, but also supports per-product configuration. If a product-specific configuration is not found, the default one is used. +# Changes to test files do not trigger static analysis or formatting checks. + jobs: define-matrix: name: Define test matrix @@ -23,24 +28,24 @@ jobs: cat < matrix.json [ { "name": "automation", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }}, - { "name": "ccip", "setup": { "run-coverage": true, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": true }}, + { "name": "ccip", "setup": { "run-coverage": true, "min-coverage": 98.8, "run-gas-snapshot": true, "run-forge-fmt": true }}, { "name": "functions", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, - { "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 74.1, "run-gas-snapshot": false, "run-forge-fmt": false }}, - { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 65.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 72.8, "run-gas-snapshot": false, "run-forge-fmt": false }}, + { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 61.0, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 46.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "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, "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, - { "name": "transmission", "setup": { "run-coverage": true, "min-coverage": 65.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "shared", "setup": { "run-coverage": true, "extra-coverage-params": "--no-match-path='*CallWithExactGas*'", "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 }} ] EOF - + matrix=$(cat matrix.json | jq -c .) echo "matrix=$matrix" >> $GITHUB_OUTPUT - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Extract Foundry version id: extract-foundry-version @@ -53,15 +58,17 @@ jobs: runs-on: ubuntu-latest outputs: non_src_changes: ${{ steps.changes.outputs.non_src }} - sol_modified: ${{ steps.changes.outputs.sol }} - sol_modified_files: ${{ steps.changes.outputs.sol_files }} - not_test_sol_modified: ${{ steps.changes.outputs.not_test_sol }} - not_test_sol_modified_files: ${{ steps.changes.outputs.not_test_sol_files }} + sol_modified_added: ${{ steps.changes.outputs.sol }} + sol_mod_only: ${{ steps.changes.outputs.sol_mod_only }} + sol_mod_only_files: ${{ steps.changes.outputs.sol_mod_only_files }} + not_test_sol_modified: ${{ steps.changes-non-test.outputs.not_test_sol }} + not_test_sol_modified_files: ${{ steps.changes-non-test.outputs.not_test_sol_files }} all_changes: ${{ steps.changes.outputs.changes }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + uses: actions/checkout@v4.2.1 + - name: Detect changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: list-files: 'shell' @@ -71,10 +78,13 @@ jobs: - 'contracts/foundry.toml' - 'contracts/gas-snapshots/*.gas-snapshot' - 'contracts/package.json' + - 'contracts/GNUmakefile' sol: - modified|added: 'contracts/src/v0.8/**/*.sol' + sol_mod_only: + - modified: 'contracts/src/v0.8/**/!(tests|mocks)/!(*.t).sol' not_test_sol: - - modified|added: 'contracts/src/v0.8/**/!(*.t).sol' + - modified|added: 'contracts/src/v0.8/**/!(tests|mocks)/!(*.t).sol' automation: - 'contracts/src/v0.8/automation/**/*.sol' ccip: @@ -102,8 +112,28 @@ jobs: transmission: - 'contracts/src/v0.8/transmission/**/*.sol' + - name: Detect non-test changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes-non-test + with: + list-files: 'shell' + # This is a valid input, see https://github.com/dorny/paths-filter/pull/226 + predicate-quantifier: every + filters: | + not_test_sol: + - modified|added: 'contracts/src/v0.8/**/!(*.t).sol' + - '!contracts/src/v0.8/**/test/**' + - '!contracts/src/v0.8/**/tests/**' + - '!contracts/src/v0.8/**/mock/**' + - '!contracts/src/v0.8/**/mocks/**' + - '!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/**' + tests: - if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified == 'true' }} + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} strategy: fail-fast: false matrix: @@ -119,7 +149,7 @@ jobs: if: ${{ 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: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: submodules: recursive @@ -131,6 +161,8 @@ jobs: || contains(fromJson(needs.changes.outputs.all_changes), 'shared') || needs.changes.outputs.non_src_changes == 'true' }} uses: ./.github/actions/setup-nodejs + with: + prod: "true" - name: Install Foundry if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) @@ -189,7 +221,13 @@ jobs: || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-coverage }} working-directory: contracts - run: forge coverage --report lcov + shell: bash + run: | + if [[ -n "${{ matrix.product.setup.extra-coverage-params }}" ]]; then + forge coverage --report lcov ${{ matrix.product.setup.extra-coverage-params }} + else + forge coverage --report lcov + fi env: FOUNDRY_PROFILE: ${{ matrix.product.name }} @@ -199,7 +237,6 @@ jobs: || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-coverage }} run: | - sudo apt-get install lcov ./contracts/scripts/lcov_prune ${{ matrix.product.name }} ./contracts/lcov.info ./contracts/lcov.info.pruned - name: Report code coverage for ${{ matrix.product.name }} @@ -211,115 +248,10 @@ jobs: with: update-comment: false coverage-files: ./contracts/lcov.info.pruned - minimum-coverage: ${{ matrix.product.min-coverage }} + minimum-coverage: ${{ matrix.product.setup.min-coverage }} artifact-name: code-coverage-report-${{ matrix.product.name }} working-directory: ./contracts - - name: Collect Metrics - if: ${{ 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' }} - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: ${{ matrix.product.name }}-solidity-foundry - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Foundry Tests ${{ matrix.product.name }} - continue-on-error: true - - analyze: - needs: [ changes, define-matrix ] - name: Run static analysis - if: needs.changes.outputs.not_test_sol_modified == 'true' - runs-on: ubuntu-22.04 - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - submodules: recursive - - - name: Setup NodeJS - 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 }} - - - name: Set up Python - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 - with: - python-version: '3.8' - - - name: Install solc-select and solc - uses: ./.github/actions/setup-solc-select - with: - to_install: '0.8.19' - to_use: '0.8.19' - - - name: Install Slither - uses: ./.github/actions/setup-slither - - - name: Run Slither - shell: bash - run: | - # modify remappings so that solc can find dependencies - ./contracts/scripts/ci/modify_remappings.sh contracts contracts/remappings.txt - mv remappings_modified.txt remappings.txt - - FILES="${{ needs.changes.outputs.not_test_sol_modified_files }}" - - for FILE in $FILES; do - PRODUCT=$(echo "$FILE" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1) - echo "::debug::Running Slither for $FILE in $PRODUCT" - SLITHER_CONFIG="contracts/configs/slither/.slither.config-$PRODUCT-pr.json" - if [ ! -f $SLITHER_CONFIG ]; then - echo "::debug::No Slither config found for $PRODUCT, using default" - SLITHER_CONFIG="contracts/configs/slither/.slither.config-default-pr.json" - fi - ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" "$SLITHER_CONFIG" "." "$FILE" "contracts/slither-reports" "--solc-remaps @=contracts/node_modules/@" - done - - - name: Print Slither summary - shell: bash - run: | - echo "# Static analysis results " >> $GITHUB_STEP_SUMMARY - for file in "contracts/slither-reports"/*.md; do - if [ -e "$file" ]; then - cat "$file" >> $GITHUB_STEP_SUMMARY - fi - done - - - name: Validate if all Slither run for all contracts - uses: ./.github/actions/validate-solidity-artifacts - with: - validate_slither_reports: 'true' - slither_reports_path: 'contracts/slither-reports' - sol_files: ${{ needs.changes.outputs.not_test_sol_modified_files }} - - - name: Upload Slither report - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 - timeout-minutes: 10 - continue-on-error: true - with: - name: slither-reports-${{ github.sha }} - path: | - contracts/slither-reports - retention-days: 7 - - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: solidity-foundry-slither - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Run static analysis - continue-on-error: true - solidity-forge-fmt: name: Forge fmt ${{ matrix.product.name }} if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.not_test_sol_modified == 'true' }} @@ -331,37 +263,25 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout the repo - if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + 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: submodules: recursive - name: Setup NodeJS - if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.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 }} uses: ./.github/actions/setup-nodejs - name: Install Foundry - if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.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 }} uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 with: version: ${{ needs.define-matrix.outputs.foundry-version }} - name: Run Forge fmt - if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.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 }} run: forge fmt --check id: fmt working-directory: contracts env: FOUNDRY_PROFILE: ${{ matrix.product.name }} - - - name: Collect Metrics - if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: solidity-forge-fmt-${{ matrix.product.name }} - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Forge fmt ${{ matrix.product.name }} - continue-on-error: true diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 705fad3be60..06f4ceabe58 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -19,7 +19,7 @@ jobs: changes: ${{ steps.changes.outputs.src }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Setup Hardhat @@ -49,15 +49,6 @@ jobs: - name: Run tests working-directory: contracts run: pnpm test - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: hardhat-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - continue-on-error: true solidity: needs: [changes, hardhat-test] @@ -74,14 +65,3 @@ jobs: else echo "All test jobs passed successfully" fi - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solidity - continue-on-error: true diff --git a/.github/workflows/solidity-jira.yml b/.github/workflows/solidity-jira.yml deleted file mode 100644 index 1054bfa9875..00000000000 --- a/.github/workflows/solidity-jira.yml +++ /dev/null @@ -1,100 +0,0 @@ -# This is its own independent workflow since "solidity.yml" depends on "merge_group" and "push" events. -# But for ensuring that JIRA tickets are always updated, we only care about "pull_request" events. -# -# We still need to add "merge_group" event and noop so that we'll pass required workflow checks. -# -# I didn't add this to the "changeset.yml" workflow because the "changeset" job isnt required, and we'd need to add the "merge_group" event to the "changeset.yml" workflow. -# If we made the change to make it required. -name: Solidity Jira - -on: - merge_group: - pull_request: - -defaults: - run: - shell: bash - -jobs: - skip-enforce-jira-issue: - name: Should Skip - # We want to skip merge_group events, and any release branches - # Since we only want to enforce Jira issues on pull requests related to feature branches - if: ${{ github.event_name != 'merge_group' && !startsWith(github.head_ref, 'release/') }} - outputs: - should-enforce: ${{ steps.changed_files.outputs.only_src_contracts }} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - # We don't use detect-solidity-file-changes here because we need to use the "every" predicate quantifier - - name: Filter paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changed_files - with: - list-files: "csv" - # This is a valid input, see https://github.com/dorny/paths-filter/pull/226 - predicate-quantifier: "every" - filters: | - only_src_contracts: - - contracts/**/*.sol - - '!contracts/**/*.t.sol' - - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-jira - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Should Skip - continue-on-error: true - - enforce-jira-issue: - name: Enforce Jira Issue - runs-on: ubuntu-latest - # If a needs job is skipped, this job will be skipped and counted as successful - # The job skips on merge_group events, and any release branches - # Since we only want to enforce Jira issues on pull requests related to feature branches - needs: [skip-enforce-jira-issue] - # In addition to the above conditions, we only want to running on solidity related PRs. - # - # Note: A job that is skipped will report its status as "Success". - # It will not prevent a pull request from merging, even if it is a required check. - if: ${{ needs.skip-enforce-jira-issue.outputs.should-enforce == 'true' }} - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - - - name: Setup Jira - working-directory: ./.github/scripts/jira - run: pnpm i - - - name: Enforce Jira Issue - working-directory: ./.github/scripts/jira - run: | - echo "COMMIT_MESSAGE=$(git log -1 --pretty=format:'%s')" >> $GITHUB_ENV - pnpm issue:enforce - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - JIRA_HOST: ${{ secrets.JIRA_HOST }} - JIRA_USERNAME: ${{ secrets.JIRA_USERNAME }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - PR_TITLE: ${{ github.event.pull_request.title }} - BRANCH_NAME: ${{ github.event.pull_request.head.ref }} - - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-jira - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Enforce Jira Issue - continue-on-error: true diff --git a/.github/workflows/solidity-tracability.yml b/.github/workflows/solidity-tracability.yml new file mode 100644 index 00000000000..337550c6723 --- /dev/null +++ b/.github/workflows/solidity-tracability.yml @@ -0,0 +1,191 @@ +# This workflow handles the enforcement of code Traceability via changesets and jira issue linking for our Solidity codebase. +name: Solidity Tracability + +on: + merge_group: + pull_request: + +defaults: + run: + shell: bash + +jobs: + files-changed: + # The job skips on merge_group events, and any release branches, and forks + # Since we only want to enforce Jira issues on pull requests related to feature branches + if: ${{ github.event_name != 'merge_group' && !startsWith(github.head_ref, 'release/') && github.event.pull_request.head.repo.full_name == 'smartcontractkit/chainlink' }} + name: Detect Changes + runs-on: ubuntu-latest + outputs: + source: ${{ steps.files-changed.outputs.source }} + changesets: ${{ steps.files-changed.outputs.changesets }} + changesets_files: ${{ steps.files-changed.outputs.changesets_files }} + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + + - name: Filter paths + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: files-changed + with: + list-files: "csv" + # This is a valid input, see https://github.com/dorny/paths-filter/pull/226 + predicate-quantifier: "every" + filters: | + source: + - contracts/**/*.sol + - '!contracts/**/*.t.sol' + changesets: + - added|modified: 'contracts/.changeset/**' + + enforce-traceability: + # Note: A job that is skipped will report its status as "Success". + # It will not prevent a pull request from merging, even if it is a required check. + needs: [files-changed] + # We only want to run this job if the source files have changed + if: ${{ needs.files-changed.outputs.source == 'true' }} + name: Enforce Traceability + runs-on: ubuntu-latest + permissions: + actions: read + id-token: write + contents: read + pull-requests: write + steps: + # https://github.com/planetscale/ghcommit-action/blob/c7915d6c18d5ce4eb42b0eff3f10a29fe0766e4c/README.md?plain=1#L41 + # + # Include the pull request ref in the checkout action to prevent merge commit + # https://github.com/actions/checkout?tab=readme-ov-file#checkout-pull-request-head-commit-instead-of-merge-commit + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Assume role capable of dispatching action + uses: smartcontractkit/.github/actions/setup-github-token@ef78fa97bf3c77de6563db1175422703e9e6674f # setup-github-token@0.2.1 + id: get-gh-token + with: + aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_CI_AUTO_PR_TOKEN_ISSUER_ROLE_ARN }} + aws-lambda-url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Make a comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 + with: + message: | + I see you updated files related to `contracts`. Please run `pnpm changeset` in the `contracts` directory to add a changeset. + reactions: eyes + comment_tag: changeset-contracts + # If the changeset is added, then we delete the comment, otherwise we add it. + mode: ${{ needs.files-changed.outputs.changesets == 'true' && 'delete' || 'upsert' }} + # We only create the comment if the changeset is not added + create_if_not_exists: ${{ needs.files-changed.outputs.changesets == 'true' && 'false' || 'true' }} + + - name: Check for new changeset for contracts + if: ${{ needs.files-changed.outputs.changesets == 'false' }} + shell: bash + run: | + echo "Please run pnpm changeset to add a changeset for contracts." + exit 1 + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + + - name: Checkout .Github repository + uses: actions/checkout@v4.2.1 + with: + repository: smartcontractkit/.github + ref: 9aed33e5298471f20a3d630d711b96ae5538728c # jira-tracing@0.2.0 + path: ./dot_github + + # we need to set the top level directory for the jira-tracing action manually + # because now we are working with two repositories and automatic detection would + # select the repository with jira-tracing and not the chainlink repository + - name: Setup git top level directory + id: find-git-top-level-dir + run: echo "top_level_dir=$(pwd)" >> $GITHUB_OUTPUT + + - name: Setup Jira + working-directory: ./dot_github + run: pnpm install --filter jira-tracing + + # Because of our earlier checks, we know that both the source and changeset files have changed + - name: Enforce Traceability + working-directory: ./dot_github + run: | + echo "COMMIT_MESSAGE=$(git log -1 --pretty=format:'%s')" >> $GITHUB_ENV + pnpm --filter jira-tracing issue:enforce + env: + CHANGESET_FILES: ${{ needs.files-changed.outputs.changesets_files }} + GIT_TOP_LEVEL_DIR: ${{ steps.find-git-top-level-dir.outputs.top_level_dir }} + + PR_TITLE: ${{ github.event.pull_request.title }} + BRANCH_NAME: ${{ github.event.pull_request.head.ref }} + + JIRA_HOST: ${{ vars.JIRA_HOST }} + JIRA_USERNAME: ${{ secrets.JIRA_USERNAME }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Enforce Solidity Review Jira issue + working-directory: ./dot_github + shell: bash + run: | + # we do not want to fail the workflow if there are issues with the script + if ! pnpm --filter jira-tracing issue:enforce-solidity-review; then + echo "::warning::Failed to enforce Solidity Review Jira issue, this is not a blocking issue. You can safely ignore it." + fi + env: + CHANGESET_FILES: ${{ needs.files-changed.outputs.changesets_files }} + GIT_TOP_LEVEL_DIR: ${{ steps.find-git-top-level-dir.outputs.top_level_dir }} + + SOLIDITY_REVIEW_TEMPLATE_KEY: 'TT-1756' + EXPORT_JIRA_ISSUE_KEYS: 'true' + + JIRA_HOST: ${{ vars.JIRA_HOST }} + JIRA_USERNAME: ${{ secrets.JIRA_USERNAME }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + # Commit appended changeset file back to repo + - uses: planetscale/ghcommit-action@13a844326508cdefc72235201bb0446d6d10a85f # v0.1.6 + with: + commit_message: "[Bot] Update changeset file with jira issues" + repo: ${{ github.repository }} + branch: ${{ github.head_ref }} + file_pattern: "contracts/.changeset/*" + env: + GITHUB_TOKEN: ${{ steps.get-gh-token.outputs.access-token }} + + - name: Read issue keys from env vars + shell: bash + id: read-issue-keys + run: | + # issue:enforce-solidity-review should have set two env vars with the issue keys + echo "Jira issue key related to pr: ${{ env.PR_JIRA_ISSUE_KEY }}" + echo "Jira issue key related to solidity review: ${{ env.SOLIDITY_REVIEW_JIRA_ISSUE_KEY }}" + + - name: Find traceability comment in the PR + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.0.0 + id: find-comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: 'Solidity Review Jira issue' + + - name: Create or update traceability comment in the PR + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + with: + comment-id: ${{ steps.find-comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + ## Solidity Review Jira issue + Hey! We have taken the liberty to link this PR to a Jira issue for Solidity Review. + + This is a new feature, that's currently in the pilot phase, so please make sure that the linkage is correct. In a contrary case, please update it manually in JIRA and replace Solidity Review issue key in the changeset file with the correct one. + Please reach out to the Test Tooling team and notify them about any issues you encounter. + + Any changes to the Solidity Review Jira issue should be reflected in the changeset file. If you need to update the issue key, please do so manually in the following changeset file: `${{ needs.files-changed.outputs.changesets_files }}` + + This PR has been linked to Solidity Review Jira issue: [${{ env.SOLIDITY_REVIEW_JIRA_ISSUE_KEY }}](${{ vars.JIRA_HOST }}browse/${{ env.SOLIDITY_REVIEW_JIRA_ISSUE_KEY }}) + edit-mode: replace diff --git a/.github/workflows/solidity-wrappers.yml b/.github/workflows/solidity-wrappers.yml index bbd7ac0c670..b2acdf6ca5e 100644 --- a/.github/workflows/solidity-wrappers.yml +++ b/.github/workflows/solidity-wrappers.yml @@ -2,7 +2,7 @@ name: Solidity Wrappers # This is its own workflow file rather than being merged into "solidity.yml" to avoid over complicating the conditionals # used for job execution. The jobs in "solidity.yml" are configured around push events, whereas # we only want to generate gethwrappers during pull requests. -on: +on: pull_request: types: - opened @@ -23,7 +23,7 @@ jobs: changes: ${{ steps.ch.outputs.changes }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Detect changes id: ch uses: ./.github/actions/detect-solidity-file-changes @@ -31,7 +31,7 @@ jobs: # On a pull request event, make updates to gethwrappers if there are changes. update-wrappers: needs: [changes] - if: needs.changes.outputs.changes == 'true' + if: needs.changes.outputs.changes == 'true' name: Update Wrappers permissions: actions: read @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu22.04-8cores-32GB steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup Go uses: ./.github/actions/setup-go @@ -65,20 +65,9 @@ jobs: - name: Commit any wrapper changes uses: planetscale/ghcommit-action@21a8cda29f55e5cc2cdae0cdbdd08e38dd148c25 # v0.1.37 with: - commit_message: "Update gethwrappers" + commit_message: "Update gethwrappers" repo: ${{ github.repository }} branch: ${{ github.head_ref }} file_pattern: "core/gethwrappers/**/generated/*.go core/gethwrappers/**/generated-wrapper-dependency-versions-do-not-edit.txt" env: GITHUB_TOKEN: ${{ steps.get-gh-token.outputs.access-token }} - - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-update-wrappers - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Update Wrappers - continue-on-error: true diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 10193bfc2ec..722c982b562 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -16,7 +16,7 @@ jobs: changes: ${{ steps.ch.outputs.changes }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Detect readonly solidity file changes id: ch uses: ./.github/actions/detect-solidity-readonly-file-changes @@ -28,7 +28,7 @@ jobs: changes: ${{ steps.ch.outputs.changes }} steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Detect changes id: ch uses: ./.github/actions/detect-solidity-file-changes @@ -43,7 +43,7 @@ jobs: release-version: ${{ steps.release-tag-check.outputs.release-version }} pre-release-version: ${{ steps.release-tag-check.outputs.pre-release-version }} steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 - name: Check release tag id: release-tag-check uses: smartcontractkit/chainlink-github-actions/release/release-tag-check@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 @@ -61,22 +61,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Run Prepublish test working-directory: contracts run: pnpm prepublishOnly - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-prepublish-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Prepublish Test - continue-on-error: true native-compile: needs: [changes, tag-check] @@ -85,9 +75,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Checkout diff-so-fancy - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 with: repository: so-fancy/diff-so-fancy ref: a673cb4d2707f64d92b86498a2f5f71c8e2643d5 # v1.4.3 @@ -108,16 +98,6 @@ jobs: - name: Check if Go solidity wrappers are updated if: ${{ needs.changes.outputs.changes == 'true' }} run: git diff --minimal --color --exit-code | diff-so-fancy - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-native-compile - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Native Compilation - continue-on-error: true # The if statements for steps after checkout repo is a workaround for # passing required check for PRs that don't have filtered changes. @@ -131,23 +111,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Run pnpm lint run: pnpm lint - name: Run solhint run: pnpm solhint - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-lint - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solidity Lint - continue-on-error: true prettier: defaults: @@ -159,21 +129,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Run prettier check run: pnpm prettier:check - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-prettier - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Prettier Formatting - continue-on-error: true publish-beta: name: Publish Beta NPM @@ -183,7 +143,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs @@ -202,17 +162,6 @@ jobs: publish-command: "pnpm publish-beta --no-git-checks" package-json-directory: contracts - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-publish-beta - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Publish Beta NPM - continue-on-error: true - publish-prod: name: Publish Prod NPM environment: publish-contracts @@ -223,7 +172,7 @@ jobs: contents: write steps: - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@v4.2.1 - name: Setup NodeJS uses: ./.github/actions/setup-nodejs @@ -244,14 +193,3 @@ jobs: create-github-release: false publish-command: "pnpm publish-prod --no-git-checks" package-json-directory: contracts - - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solitidy-publish-prod - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Publish Prod NPM - continue-on-error: true diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 8eb95f4147c..b2ed7ff36a2 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -18,7 +18,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 + - uses: actions/stale@v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} exempt-all-pr-assignees: true diff --git a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml index 05b7365eba1..e635ce40922 100644 --- a/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml +++ b/.github/workflows/sync-develop-from-smartcontractkit-chainlink.yml @@ -10,7 +10,7 @@ jobs: name: Sync runs-on: ubuntu-latest steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@v4.2.1 with: ref: develop if: env.GITHUB_REPOSITORY != 'smartcontractkit/chainlink' @@ -27,14 +27,3 @@ jobs: git push origin upstream/develop:develop fi if: env.GITHUB_REPOSITORY != 'smartcontractkit/chainlink' - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: sync-develop - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Sync - continue-on-error: true diff --git a/.gitignore b/.gitignore index 00962a94a39..718d4e4fe82 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ tools/clroot/db.sqlite3-wal debug.env *.txt operator_ui/install +.devenv # codeship *.aes @@ -52,6 +53,8 @@ race.* golangci-lint-output.txt /golangci-lint/ .covdata +core/services/job/testdata/wasm/testmodule.wasm +core/services/job/testdata/wasm/testmodule.br # DB state ./db/ @@ -74,7 +77,6 @@ db_dumps/ integration-tests/**/traces/ benchmark_report.csv benchmark_summary.json -integration-tests/citool/output.csv secrets.toml tmp_laneconfig/ @@ -108,3 +110,8 @@ override*.toml .venv/ ocr_soak_report.csv + +vendor/* + +*.wasm +contracts/lcov.info diff --git a/.golangci.yml b/.golangci.yml index 7155cff2d51..9e6cf25c69d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,23 +2,29 @@ run: timeout: 15m0s linters: enable: + - containedctx + - depguard + - errname + - errorlint - exhaustive - exportloopref - - revive + - fatcontext + - ginkgolinter - goimports - gosec + - loggercheck + - mirror - misspell + - noctx + - perfsprint + - prealloc + - revive - rowserrcheck - - errorlint - - unconvert + - spancheck - sqlclosecheck - - noctx - - depguard + - testifylint + - unconvert - whitespace - - containedctx - - fatcontext - - mirror - - loggercheck linters-settings: exhaustive: default-signifies-exhaustive: true @@ -58,9 +64,6 @@ linters-settings: - (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 - errorlint: - # Allow formatting of errors without %w - errorf: false revive: confidence: 0.8 rules: @@ -71,9 +74,10 @@ linters-settings: - name: error-return - name: error-strings - name: error-naming + - name: exported - name: if-return - name: increment-decrement - # - name: var-naming + - name: var-naming - name: var-declaration - name: package-comments - name: range @@ -92,7 +96,7 @@ linters-settings: - name: struct-tag # - name: string-format - name: string-of-int - # - name: range-val-address + - name: range-val-address - name: range-val-in-closure - name: modifies-value-receiver - name: modifies-parameter diff --git a/.goreleaser.develop.yaml b/.goreleaser.develop.yaml index b1f65217b8f..c633e22fe62 100644 --- a/.goreleaser.develop.yaml +++ b/.goreleaser.develop.yaml @@ -1,209 +1,308 @@ -## goreleaser <1.14.0 +version: 2 project_name: chainlink - env: - - ZIG_EXEC={{ if index .Env "ZIG_EXEC" }}{{ .Env.ZIG_EXEC }}{{ else }}zig{{ end }} - - IMAGE_PREFIX={{ if index .Env "IMAGE_PREFIX" }}{{ .Env.IMAGE_PREFIX }}{{ else }}localhost:5001{{ end }} - - IMAGE_NAME={{ if index .Env "IMAGE_NAME" }}{{ .Env.IMAGE_NAME }}{{ else }}chainlink{{ end }} - - IMAGE_TAG={{ if index .Env "IMAGE_TAG" }}{{ .Env.IMAGE_TAG }}{{ else }}develop{{ end }} - - IMAGE_LABEL_DESCRIPTION="node of the decentralized oracle network, bridging on and off-chain computation" - - IMAGE_LABEL_LICENSES="MIT" - - IMAGE_LABEL_SOURCE="https://github.com/smartcontractkit/{{ .ProjectName }}" - -before: - hooks: - - go mod tidy - - ./tools/bin/goreleaser_utils before_hook - -# See https://goreleaser.com/customization/build/ + - IMG_PRE={{ if index .Env "IMAGE_PREFIX" }}{{ .Env.IMAGE_PREFIX }}{{ else }}localhost:5001{{ end }} + - IMG_TAG={{ if index .Env "IMAGE_TAG" }}{{ .Env.IMAGE_TAG }}{{ else }}develop{{ end }} + - CGO_ENABLED=1 + - VERSION={{ if index .Env "CHAINLINK_VERSION" }}{{ .Env.CHAINLINK_VERSION }}{{ else }}v0.0.0-local{{ end }} +release: + disable: "true" builds: - - binary: chainlink - id: linux-arm64 - goos: - - linux - goarch: - - arm64 - hooks: - post: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} {{ .Os }} {{ .Arch }} - env: - - CGO_ENABLED=1 - - CC=$ZIG_EXEC cc -target aarch64-linux-gnu - - CCX=$ZIG_EXEC c++ -target aarch64-linux-gnu - flags: - - -trimpath - - -buildmode=pie - ldflags: - - -s -w -r=$ORIGIN/libs - - -X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Env.CHAINLINK_VERSION }} - - -X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }} - - binary: chainlink - id: linux-amd64 - goos: - - linux - goarch: - - amd64 - hooks: - post: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} {{ .Os }} {{ .Arch }} - env: - - CGO_ENABLED=1 - - CC=$ZIG_EXEC cc -target x86_64-linux-gnu - - CCX=$ZIG_EXEC c++ -target x86_64-linux-gnu - flags: - - -trimpath - - -buildmode=pie - ldflags: - - -s -w -r=$ORIGIN/libs - - -X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Env.CHAINLINK_VERSION }} - - -X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }} - -# See https://goreleaser.com/customization/docker/ + - targets: + - go_first_class + binary: chainlink + hooks: + post: + - cmd: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} + no_unique_dist_dir: "true" + ldflags: + - -s -w -r=$ORIGIN/libs + - -X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }} + - |- + -extldflags "-Wl,--dynamic-linker={{ if contains .Runtime.Goarch "amd64" -}} + /lib64/ld-linux-x86-64.so.2 + {{- else if contains .Runtime.Goarch "arm64" -}} + /lib/ld-linux-aarch64.so.1 + {{- end }}" + - -X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Env.VERSION }} + flags: + - -trimpath + - -buildmode=pie +archives: + - format: binary +snapshot: + version_template: '{{ .Env.VERSION }}-{{ .ShortCommit }}' +checksum: + name_template: checksums.txt dockers: - - id: linux-amd64 - dockerfile: core/chainlink.goreleaser.Dockerfile - use: buildx - goos: linux - goarch: amd64 - extra_files: - - tmp/linux_amd64/libs - - tools/bin/ldd_fix - build_flag_templates: - - "--platform=linux/amd64" - - "--pull" - - "--build-arg=CHAINLINK_USER=chainlink" - - "--build-arg=COMMIT_SHA={{ .FullCommit }}" - - "--label=org.opencontainers.image.created={{ .Date }}" - - "--label=org.opencontainers.image.description={{ .Env.IMAGE_LABEL_DESCRIPTION }}" - - "--label=org.opencontainers.image.licenses={{ .Env.IMAGE_LABEL_LICENSES }}" - - "--label=org.opencontainers.image.revision={{ .FullCommit }}" - - "--label=org.opencontainers.image.source={{ .Env.IMAGE_LABEL_SOURCE }}" - - "--label=org.opencontainers.image.title={{ .ProjectName }}" - - "--label=org.opencontainers.image.version={{ .Env.CHAINLINK_VERSION }}" - - "--label=org.opencontainers.image.url={{ .Env.IMAGE_LABEL_SOURCE }}" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-amd64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-amd64" - - id: linux-arm64 - dockerfile: core/chainlink.goreleaser.Dockerfile - use: buildx - goos: linux - goarch: arm64 - extra_files: - - tmp/linux_arm64/libs - - tools/bin/ldd_fix - build_flag_templates: - - "--platform=linux/arm64" - - "--pull" - - "--build-arg=CHAINLINK_USER=chainlink" - - "--build-arg=COMMIT_SHA={{ .FullCommit }}" - - "--label=org.opencontainers.image.created={{ .Date }}" - - "--label=org.opencontainers.image.description={{ .Env.IMAGE_LABEL_DESCRIPTION }}" - - "--label=org.opencontainers.image.licenses={{ .Env.IMAGE_LABEL_LICENSES }}" - - "--label=org.opencontainers.image.revision={{ .FullCommit }}" - - "--label=org.opencontainers.image.source={{ .Env.IMAGE_LABEL_SOURCE }}" - - "--label=org.opencontainers.image.title={{ .ProjectName }}" - - "--label=org.opencontainers.image.version={{ .Env.CHAINLINK_VERSION }}" - - "--label=org.opencontainers.image.url={{ .Env.IMAGE_LABEL_SOURCE }}" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-arm64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-arm64" - - id: linux-amd64-plugins - dockerfile: core/chainlink.goreleaser.Dockerfile - use: buildx - goos: linux - goarch: amd64 - extra_files: - - tmp/linux_amd64/libs - - tmp/linux_amd64/plugins - - tools/bin/ldd_fix - build_flag_templates: - - "--platform=linux/amd64" - - "--pull" - - "--build-arg=CHAINLINK_USER=chainlink" - - "--build-arg=COMMIT_SHA={{ .FullCommit }}" - - "--build-arg=CL_MEDIAN_CMD=chainlink-feeds" - - "--build-arg=CL_MERCURY_CMD=chainlink-mercury" - - "--build-arg=CL_SOLANA_CMD=chainlink-solana" - - "--build-arg=CL_STARKNET_CMD=chainlink-starknet" - - "--label=org.opencontainers.image.created={{ .Date }}" - - "--label=org.opencontainers.image.description={{ .Env.IMAGE_LABEL_DESCRIPTION }}" - - "--label=org.opencontainers.image.licenses={{ .Env.IMAGE_LABEL_LICENSES }}" - - "--label=org.opencontainers.image.revision={{ .FullCommit }}" - - "--label=org.opencontainers.image.source={{ .Env.IMAGE_LABEL_SOURCE }}" - - "--label=org.opencontainers.image.title={{ .ProjectName }}" - - "--label=org.opencontainers.image.version={{ .Env.CHAINLINK_VERSION }}" - - "--label=org.opencontainers.image.url={{ .Env.IMAGE_LABEL_SOURCE }}" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-plugins-amd64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-plugins-amd64" - - id: linux-arm64-plugins - dockerfile: core/chainlink.goreleaser.Dockerfile - use: buildx - goos: linux - goarch: arm64 - extra_files: - - tmp/linux_arm64/libs - - tmp/linux_arm64/plugins - - tools/bin/ldd_fix - build_flag_templates: - - "--platform=linux/arm64" - - "--pull" - - "--build-arg=CHAINLINK_USER=chainlink" - - "--build-arg=COMMIT_SHA={{ .FullCommit }}" - - "--build-arg=CL_MEDIAN_CMD=chainlink-feeds" - - "--build-arg=CL_MERCURY_CMD=chainlink-mercury" - - "--build-arg=CL_SOLANA_CMD=chainlink-solana" - - "--build-arg=CL_STARKNET_CMD=chainlink-starknet" - - "--label=org.opencontainers.image.created={{ .Date }}" - - "--label=org.opencontainers.image.description={{ .Env.IMAGE_LABEL_DESCRIPTION }}" - - "--label=org.opencontainers.image.licenses={{ .Env.IMAGE_LABEL_LICENSES }}" - - "--label=org.opencontainers.image.revision={{ .FullCommit }}" - - "--label=org.opencontainers.image.source={{ .Env.IMAGE_LABEL_SOURCE }}" - - "--label=org.opencontainers.image.title={{ .ProjectName }}" - - "--label=org.opencontainers.image.version={{ .Env.CHAINLINK_VERSION }}" - - "--label=org.opencontainers.image.url={{ .Env.IMAGE_LABEL_SOURCE }}" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-plugins-arm64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-plugins-arm64" - -# See https://goreleaser.com/customization/docker_manifest/ + - id: linux-amd64-chainlink + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMG_PRE }}/chainlink:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMG_PRE }}/chainlink:sha-{{ .ShortCommit }}-amd64' + extra_files: + - tmp/libs + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-amd64-chainlink-plugins + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMG_PRE }}/chainlink:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMG_PRE }}/chainlink:sha-{{ .ShortCommit }}-plugins-amd64' + extra_files: + - tmp/libs + - tmp/plugins + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-chainlink + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink:{{ .Env.IMG_TAG }}-arm64' + - '{{ .Env.IMG_PRE }}/chainlink:sha-{{ .ShortCommit }}-arm64' + extra_files: + - tmp/libs + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-chainlink-plugins + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink:{{ .Env.IMG_TAG }}-plugins-arm64' + - '{{ .Env.IMG_PRE }}/chainlink:sha-{{ .ShortCommit }}-plugins-arm64' + extra_files: + - tmp/libs + - tmp/plugins + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-amd64-ccip + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/ccip:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMG_PRE }}/ccip:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMG_PRE }}/ccip:sha-{{ .ShortCommit }}-amd64' + extra_files: + - tmp/libs + - ccip/config + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-amd64-ccip-plugins + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/ccip:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMG_PRE }}/ccip:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMG_PRE }}/ccip:sha-{{ .ShortCommit }}-plugins-amd64' + extra_files: + - tmp/libs + - tmp/plugins + - ccip/config + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-ccip + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/ccip:{{ .Env.IMG_TAG }}-arm64' + - '{{ .Env.IMG_PRE }}/ccip:sha-{{ .ShortCommit }}-arm64' + extra_files: + - tmp/libs + - ccip/config + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-ccip-plugins + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/ccip:{{ .Env.IMG_TAG }}-plugins-arm64' + - '{{ .Env.IMG_PRE }}/ccip:sha-{{ .ShortCommit }}-plugins-arm64' + extra_files: + - tmp/libs + - tmp/plugins + - ccip/config + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx docker_manifests: - - name_template: "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-amd64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-arm64" - - name_template: "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-amd64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-arm64" - - name_template: "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-plugins" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-plugins-amd64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:{{ .Env.IMAGE_TAG }}-plugins-arm64" - - name_template: "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-plugins" - image_templates: - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-plugins-amd64" - - "{{ .Env.IMAGE_PREFIX }}/{{ .Env.IMAGE_NAME }}:sha-{{ .ShortCommit }}-plugins-arm64" - -# See https://goreleaser.com/customization/docker_sign/ -docker_signs: - - artifacts: all - stdin: "{{ .Env.COSIGN_PASSWORD }}" - -checksum: - name_template: "checksums.txt" - -snapshot: - name_template: "{{ .Env.CHAINLINK_VERSION }}-{{ .ShortCommit }}" - -partial: - by: target - + - id: tagged-chainlink + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}-arm64' + - id: sha-chainlink + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink:sha-{{ .ShortCommit }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink:sha-{{ .ShortCommit }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink:sha-{{ .ShortCommit }}-arm64' + - id: tagged-plugins-chainlink + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}-plugins' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}-plugins-arm64' + - id: sha-plugins-chainlink + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink:sha-{{ .ShortCommit }}-plugins' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink:sha-{{ .ShortCommit }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink:sha-{{ .ShortCommit }}-plugins-arm64' + - id: tagged-ccip + name_template: '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}-arm64' + - id: sha-ccip + name_template: '{{ .Env.IMAGE_PREFIX }}/ccip:sha-{{ .ShortCommit }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/ccip:sha-{{ .ShortCommit }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/ccip:sha-{{ .ShortCommit }}-arm64' + - id: tagged-plugins-ccip + name_template: '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}-plugins' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/ccip:{{ .Env.IMG_TAG }}-plugins-arm64' + - id: sha-plugins-ccip + name_template: '{{ .Env.IMAGE_PREFIX }}/ccip:sha-{{ .ShortCommit }}-plugins' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/ccip:sha-{{ .ShortCommit }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/ccip:sha-{{ .ShortCommit }}-plugins-arm64' changelog: - sort: asc - filters: - exclude: - - "^docs:" - - "^test:" -# modelines, feel free to remove those if you don't want/use them: -# yaml-language-server: $schema=https://goreleaser.com/static/schema.json -# vim: set ts=2 sw=2 tw=0 fo=cnqoj + disable: "true" +before: + hooks: + - cmd: go mod tidy + - cmd: ./tools/bin/goreleaser_utils before_hook +partial: + by: target +nightly: + version_template: '{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}' diff --git a/.goreleaser.devspace.yaml b/.goreleaser.devspace.yaml index bca65e90454..13027590a2b 100644 --- a/.goreleaser.devspace.yaml +++ b/.goreleaser.devspace.yaml @@ -1,88 +1,102 @@ -## goreleaser <1.14.0 -project_name: chainlink-devspace - +version: 2 +project_name: chainlink env: - - ZIG_EXEC={{ if index .Env "ZIG_EXEC" }}{{ .Env.ZIG_EXEC }}{{ else }}zig{{ end }} - - IMAGE_LABEL_DESCRIPTION="node of the decentralized oracle network, bridging on and off-chain computation" - - IMAGE_LABEL_LICENSES="MIT" - - IMAGE_LABEL_SOURCE="https://github.com/smartcontractkit/{{ .ProjectName }}" - -before: - hooks: - - go mod tidy - - ./tools/bin/goreleaser_utils before_hook - -# See https://goreleaser.com/customization/build/ + - IMG_PRE={{ if index .Env "IMAGE_PREFIX" }}{{ .Env.IMAGE_PREFIX }}{{ else }}localhost:5001{{ end }} + - IMG_TAG={{ if index .Env "IMAGE_TAG" }}{{ .Env.IMAGE_TAG }}{{ else }}develop{{ end }} + - CGO_ENABLED=1 +release: + disable: "true" builds: - - binary: chainlink - id: linux-amd64 - goos: - - linux - goarch: - - amd64 - hooks: - post: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} {{ .Os }} {{ .Arch }} - env: - - CGO_ENABLED=1 - - CC=$ZIG_EXEC cc -target x86_64-linux-gnu -Wno-error=unused-command-line-argument - - CCX=$ZIG_EXEC c++ -target x86_64-linux-gnu -Wno-error=unused-command-line-argument - flags: - - -trimpath - - -buildmode=pie - ldflags: - - -s -w -r=$ORIGIN/libs - - -X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Version }} - - -X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }} - -# See https://goreleaser.com/customization/docker/ + - targets: + - go_first_class + binary: chainlink + hooks: + post: + - cmd: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} + no_unique_dist_dir: "true" + ldflags: + - -s -w -r=$ORIGIN/libs + - -X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }} + - |- + -extldflags "-Wl,--dynamic-linker={{ if contains .Runtime.Goarch "amd64" -}} + /lib64/ld-linux-x86-64.so.2 + {{- else if contains .Runtime.Goarch "arm64" -}} + /lib/ld-linux-aarch64.so.1 + {{- end }}" + - -X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Version }} + flags: + - -trimpath + - -buildmode=pie +archives: + - format: binary +snapshot: + version_template: v0.0.0-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }} +checksum: + name_template: checksums.txt dockers: - - id: linux-amd64 - dockerfile: core/chainlink.goreleaser.Dockerfile - use: buildx - goos: linux - goarch: amd64 - extra_files: - - tmp/linux_amd64/libs - - tmp/linux_amd64/plugins - - tools/bin/ldd_fix - build_flag_templates: - - "--platform=linux/amd64" - - "--pull" - - "--build-arg=CHAINLINK_USER=chainlink" - - "--build-arg=COMMIT_SHA={{ .FullCommit }}" - - "--build-arg=CL_MEDIAN_CMD=chainlink-feeds" - - "--build-arg=CL_MERCURY_CMD=chainlink-mercury" - - "--build-arg=CL_SOLANA_CMD=chainlink-solana" - - "--build-arg=CL_STARKNET_CMD=chainlink-starknet" - - "--label=org.opencontainers.image.created={{ .Date }}" - - "--label=org.opencontainers.image.description={{ .Env.IMAGE_LABEL_DESCRIPTION }}" - - "--label=org.opencontainers.image.licenses={{ .Env.IMAGE_LABEL_LICENSES }}" - - "--label=org.opencontainers.image.revision={{ .FullCommit }}" - - "--label=org.opencontainers.image.source={{ .Env.IMAGE_LABEL_SOURCE }}" - - "--label=org.opencontainers.image.title={{ .ProjectName }}" - - "--label=org.opencontainers.image.version={{ .Version }}" - - "--label=org.opencontainers.image.url={{ .Env.IMAGE_LABEL_SOURCE }}" - image_templates: - - "{{ .Env.IMAGE }}" - -# See https://goreleaser.com/customization/docker_manifest/ + - id: linux-amd64 + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMAGE }}' + extra_files: + - tmp/libs + - tmp/plugins + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + use: buildx + - id: linux-arm64 + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMAGE }}' + extra_files: + - tmp/libs + - tmp/plugins + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + use: buildx docker_manifests: - - name_template: "{{ .Env.IMAGE }}" - image_templates: - - "{{ .Env.IMAGE }}" - -checksum: - name_template: "checksums.txt" - -snapshot: - name_template: '{{ .Env.CHAINLINK_VERSION }}-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }}' - + - name_template: '{{ .Env.IMAGE }}' + image_templates: + - '{{ .Env.IMAGE }}' changelog: - sort: asc - filters: - exclude: - - "^docs:" - - "^test:" -# modelines, feel free to remove those if you don't want/use them: -# yaml-language-server: $schema=https://goreleaser.com/static/schema.json -# vim: set ts=2 sw=2 tw=0 fo=cnqoj + disable: "true" +before: + hooks: + - cmd: go mod tidy + - cmd: ./tools/bin/goreleaser_utils before_hook +partial: + by: target +nightly: + version_template: v0.0.0-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }} diff --git a/.goreleaser.production.yaml b/.goreleaser.production.yaml new file mode 100644 index 00000000000..b4e19d1b31c --- /dev/null +++ b/.goreleaser.production.yaml @@ -0,0 +1,330 @@ +version: 2 +project_name: chainlink +env: + - IMG_PRE={{ if index .Env "IMAGE_PREFIX" }}{{ .Env.IMAGE_PREFIX }}{{ else }}localhost:5001{{ end }} + - IMG_TAG={{ if index .Env "IMAGE_TAG" }}{{ .Env.IMAGE_TAG }}{{ else }}develop{{ end }} + - CGO_ENABLED=1 + - VERSION={{ if index .Env "CHAINLINK_VERSION" }}{{ .Env.CHAINLINK_VERSION }}{{ else }}v0.0.0-local{{ end }} +release: + disable: "true" +builds: + - targets: + - go_first_class + binary: chainlink + hooks: + post: + - cmd: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} + no_unique_dist_dir: "true" + ldflags: + - -s -w -r=$ORIGIN/libs + - -X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }} + - |- + -extldflags "-Wl,--dynamic-linker={{ if contains .Runtime.Goarch "amd64" -}} + /lib64/ld-linux-x86-64.so.2 + {{- else if contains .Runtime.Goarch "arm64" -}} + /lib/ld-linux-aarch64.so.1 + {{- end }}" + - -X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Env.VERSION }} + flags: + - -trimpath + - -buildmode=pie +archives: + - format: tar.gz +snapshot: + version_template: '{{ .Env.VERSION }}-{{ .ShortCommit }}' +checksum: + name_template: checksums.txt +dockers: + - id: linux-amd64-chainlink + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-amd64' + skip_push: '{{ contains .Tag "-ccip" }}' + extra_files: + - tmp/libs + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-amd64-chainlink-plugins + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-amd64' + skip_push: '{{ contains .Tag "-ccip" }}' + extra_files: + - tmp/libs + - tmp/plugins + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-chainlink + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-arm64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-arm64' + skip_push: '{{ contains .Tag "-ccip" }}' + extra_files: + - tmp/libs + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-chainlink-plugins + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-arm64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-arm64' + skip_push: '{{ contains .Tag "-ccip" }}' + extra_files: + - tmp/libs + - tmp/plugins + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-amd64-ccip + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-amd64' + skip_push: '{{ not (contains .Tag "-ccip") }}' + extra_files: + - tmp/libs + - ccip/config + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-amd64-ccip-plugins + goos: linux + goarch: amd64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-amd64' + skip_push: '{{ not (contains .Tag "-ccip") }}' + extra_files: + - tmp/libs + - tmp/plugins + - ccip/config + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-ccip + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-arm64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-arm64' + skip_push: '{{ not (contains .Tag "-ccip") }}' + extra_files: + - tmp/libs + - ccip/config + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx + - id: linux-arm64-ccip-plugins + goos: linux + goarch: arm64 + dockerfile: core/chainlink.goreleaser.Dockerfile + image_templates: + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-arm64' + - '{{ .Env.IMG_PRE }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-arm64' + skip_push: '{{ not (contains .Tag "-ccip") }}' + extra_files: + - tmp/libs + - tmp/plugins + - ccip/config + build_flag_templates: + - --platform=linux/arm64 + - --pull + - --build-arg=CHAINLINK_USER=chainlink + - --build-arg=COMMIT_SHA={{ .FullCommit }} + - --build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config + - --build-arg=CL_MEDIAN_CMD=chainlink-feeds + - --build-arg=CL_MERCURY_CMD=chainlink-mercury + - --build-arg=CL_SOLANA_CMD=chainlink-solana + - --build-arg=CL_STARKNET_CMD=chainlink-starknet + - --label=org.opencontainers.image.created={{ .Date }} + - --label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation" + - --label=org.opencontainers.image.licenses=MIT + - --label=org.opencontainers.image.revision={{ .FullCommit }} + - --label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.title=chainlink + - --label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink + - --label=org.opencontainers.image.version={{ .Env.VERSION }} + use: buildx +docker_manifests: + - id: tagged-chainlink-chainlink-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}' + skip_push: '{{ contains .Tag "-ccip" }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-arm64' + - id: sha-chainlink-chainlink-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}' + skip_push: '{{ contains .Tag "-ccip" }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-arm64' + - id: tagged-plugins-chainlink-chainlink-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins' + skip_push: '{{ contains .Tag "-ccip" }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-arm64' + - id: sha-plugins-chainlink-chainlink-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins' + skip_push: '{{ contains .Tag "-ccip" }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-arm64' + - id: tagged-chainlink-chainlink-ccip-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}' + skip_push: '{{ not (contains .Tag "-ccip") }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-arm64' + - id: sha-chainlink-chainlink-ccip-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}' + skip_push: '{{ not (contains .Tag "-ccip") }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-arm64' + - id: tagged-plugins-chainlink-chainlink-ccip-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins' + skip_push: '{{ not (contains .Tag "-ccip") }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:{{ .Env.IMG_TAG }}-plugins-arm64' + - id: sha-plugins-chainlink-chainlink-ccip-experimental-goreleaser + name_template: '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins' + skip_push: '{{ not (contains .Tag "-ccip") }}' + image_templates: + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-amd64' + - '{{ .Env.IMAGE_PREFIX }}/chainlink/chainlink-ccip-experimental-goreleaser:sha-{{ .ShortCommit }}-plugins-arm64' +changelog: + filters: + exclude: + - '^docs:' + - '^test:' + sort: asc +before: + hooks: + - cmd: go mod tidy + - cmd: ./tools/bin/goreleaser_utils before_hook +sboms: + - artifacts: archive +partial: + by: target +nightly: + version_template: '{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}' diff --git a/.mockery.yaml b/.mockery.yaml index 87c27cd46a9..711d70f59e9 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -14,9 +14,8 @@ packages: NodeSelector: sendOnlyClient: SendOnlyNode: - RPC: + RPCClient: Head: - NodeClient: PoolChainInfoProvider: github.com/smartcontractkit/chainlink/v2/common/headtracker: interfaces: @@ -54,7 +53,6 @@ packages: github.com/smartcontractkit/chainlink/v2/core/chains/evm/client: interfaces: Client: - RPCClient: github.com/smartcontractkit/chainlink/v2/core/chains/evm/config: interfaces: GasEstimator: @@ -69,6 +67,9 @@ packages: feeEstimatorClient: config: mockname: FeeEstimatorClient + feeHistoryEstimatorClient: + config: + mockname: FeeHistoryEstimatorClient EvmEstimator: github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups: interfaces: @@ -167,9 +168,9 @@ packages: ConnectionsManager: ORM: Service: - github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto: + github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager: config: - dir: "{{ .InterfaceDir }}/../mocks" + dir: "core/services/feeds/mocks" interfaces: FeedsManagerClient: github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2: @@ -209,6 +210,7 @@ packages: HttpServer: HTTPRequestHandler: WebSocketServer: + HTTPClient: github.com/smartcontractkit/chainlink/v2/core/services/job: interfaces: ServiceCtx: @@ -323,6 +325,13 @@ packages: interfaces: ExternalInitiatorManager: HTTPClient: + github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read: + config: + dir: "{{ .InterfaceDir }}/mocks" + interfaces: + Registrar: + Reader: + BatchCaller: github.com/smartcontractkit/chainlink/v2/core/sessions: interfaces: BasicAdminUsersORM: @@ -338,7 +347,6 @@ packages: Codec: config: dir: core/services/relay/evm/mocks - ChainReader: ChainWriter: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp: config: @@ -361,13 +369,6 @@ packages: outpkg: mock_contracts interfaces: EVM2EVMOffRampInterface: - github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0: - config: - dir: core/gethwrappers/ccip/mocks/v1_0_0/ - filename: evm2_evm_off_ramp_interface.go - outpkg: mock_contracts - interfaces: - EVM2EVMOffRampInterface: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store: config: dir: core/gethwrappers/ccip/mocks/ @@ -375,13 +376,13 @@ packages: outpkg: mock_contracts interfaces: CommitStoreInterface: - github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry: + github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter: config: dir: core/gethwrappers/ccip/mocks/ - filename: price_registry_interface.go + filename: fee_quoter_interface.go outpkg: mock_contracts interfaces: - PriceRegistryInterface: + FeeQuoterInterface: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface: config: dir: core/gethwrappers/ccip/mocks/ @@ -529,6 +530,11 @@ packages: PriceGetter: config: mockname: "Mock{{ .InterfaceName }}" + filename: mock.go + AllTokensPriceGetter: + config: + mockname: "Mock{{ .InterfaceName }}" + filename: all_price_getter_mock.go github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker: interfaces: CCIPTransactionStatusChecker: @@ -544,7 +550,6 @@ packages: config: filename: evm_mock.go dir: "{{ .InterfaceDir }}/rpclibmocks" - github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices: config: dir: "{{ .InterfaceDir }}/" @@ -573,4 +578,7 @@ packages: mockname: "Mock{{ .InterfaceName }}" github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer: interfaces: - ORM: \ No newline at end of file + ORM: + github.com/smartcontractkit/chainlink/v2/core/capabilities/targets: + interfaces: + ContractValueGetter: \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index 7d237b0a4a1..e957157960e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,9 +1,8 @@ -golang 1.22.5 +golang 1.22.8 mockery 2.43.2 nodejs 20.13.1 pnpm 9.4.0 postgres 15.1 helm 3.10.3 -zig 0.11.0 -golangci-lint 1.59.1 +golangci-lint 1.60.3 protoc 25.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index a521df865bd..c1a09677ba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,320 @@ # Changelog Chainlink Core -## 2.15.0 +## 2.17.0 - 2024-10-10 + +### Minor Changes + +- [#14316](https://github.com/smartcontractkit/chainlink/pull/14316) [`2a21b170f3`](https://github.com/smartcontractkit/chainlink/commit/2a21b170f38ded4cf0f15db283035e69b53aeeb9) Thanks [@graham-chainlink](https://github.com/graham-chainlink)! - #internal updated to latest operator-ui to bring in new UI changes for supporting multiple job distributors + +- [#14264](https://github.com/smartcontractkit/chainlink/pull/14264) [`33e6a0c1e4`](https://github.com/smartcontractkit/chainlink/commit/33e6a0c1e44b805064fe423b5570a40c07daed41) Thanks [@chainchad](https://github.com/chainchad)! - Bump to start the next version + +- [#14109](https://github.com/smartcontractkit/chainlink/pull/14109) [`2761cd5bc5`](https://github.com/smartcontractkit/chainlink/commit/2761cd5bc5ed91bc17d4d67265ddc8fa03b84540) Thanks [@Farber98](https://github.com/Farber98)! - FilteredLogs receive Expression instead of whole KeyFilter. #internal + +- [#14239](https://github.com/smartcontractkit/chainlink/pull/14239) [`674eac31cc`](https://github.com/smartcontractkit/chainlink/commit/674eac31cc161250fdadb838ba2a0fc7c796e932) Thanks [@bolekk](https://github.com/bolekk)! - #added Implements rate limiter for capabilities dispatcher + +- [#14470](https://github.com/smartcontractkit/chainlink/pull/14470) [`5885454e9a`](https://github.com/smartcontractkit/chainlink/commit/5885454e9a7eaa8f8c180ac3708afbdf5bdb08cd) Thanks [@austinborn](https://github.com/austinborn)! - #changed: Add new OCR3DataFeeds telemetry type for Mercury jobs + +- [#14266](https://github.com/smartcontractkit/chainlink/pull/14266) [`c323e0d600`](https://github.com/smartcontractkit/chainlink/commit/c323e0d600c659a4ea584dbae0a0db187afd51eb) Thanks [@asoliman92](https://github.com/asoliman92)! - #updated move latest capabilities code from ccip repo to chainlink repo [CCIP-2946] + + PR issue: CCIP-2946 + +- [#14197](https://github.com/smartcontractkit/chainlink/pull/14197) [`7f69993c86`](https://github.com/smartcontractkit/chainlink/commit/7f69993c8655053b7550f50b817ba9c6888037e2) Thanks [@graham-chainlink](https://github.com/graham-chainlink)! - #changed Connect to multiple feeds managers on app start instead of just one (default to first) + +- [#14373](https://github.com/smartcontractkit/chainlink/pull/14373) [`5acca3719e`](https://github.com/smartcontractkit/chainlink/commit/5acca3719ecd7a3189db3a8a8d09418ed8423016) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - This PR introduce few changes: + + - Add a new config option `EVM.NodePool.NewHeadsPollInterval` (0 by default indicate disabled), which is an interval for polling new block periodically using http client rather than subscribe to ws feed. + - Updated new head handler for polling new head over http, and register the subscription in node lifecycle logic. + - If the polling new heads is enabled, WS new heads subscription will be replaced with the new http based polling. + + Note: There will be another PR for making WS URL optional with some extra condition. + #added + +- [#14438](https://github.com/smartcontractkit/chainlink/pull/14438) [`6814bcef45`](https://github.com/smartcontractkit/chainlink/commit/6814bcef45a7157ac9835c25a9a5b95a135bdc01) Thanks [@graham-chainlink](https://github.com/graham-chainlink)! - #internal Update to latest UI - PeerId field is introduced for OCR2 bootstrap node in chain config page + +- [#14354](https://github.com/smartcontractkit/chainlink/pull/14354) [`bf6618da8a`](https://github.com/smartcontractkit/chainlink/commit/bf6618da8aa9695c747b81df172acdd43e379cb2) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - Adding feature flag for `LogBroadcaster` called `LogBroadcasterEnabled`, which is `true` by default to support backwards compatibility. + Adding `LogBroadcasterEnabled` allows certain chains to completely disable the `LogBroadcaster` feature, which is an old feature (getting replaced by logPoller) that only few products are using it: + + - OCR1 Median + - \*OCR2 Median when ChainReader is disabled + - \*pre-OCR2 Keeper + - Flux Monitor + - Direct RequestOCR1 Median + + #added + +- [#13735](https://github.com/smartcontractkit/chainlink/pull/13735) [`920413c3ce`](https://github.com/smartcontractkit/chainlink/commit/920413c3ce2ca8effc138e69ec063b0ce5e94c6b) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Added ChainWriter to ChainReader tests + +- [#14041](https://github.com/smartcontractkit/chainlink/pull/14041) [`8d818ea265`](https://github.com/smartcontractkit/chainlink/commit/8d818ea265ff08887e61ace4f83364a3ee149ef0) Thanks [@amit-momin](https://github.com/amit-momin)! - Added gas limit estimation feature to EVM gas estimators. Introduced a new config `EVM.GasEstimator.EstimateLimit` to toggle this feature. #added + +- [#14207](https://github.com/smartcontractkit/chainlink/pull/14207) [`328b62ae50`](https://github.com/smartcontractkit/chainlink/commit/328b62ae5067619e59da42f6db6703d3b327f1a2) Thanks [@ilija42](https://github.com/ilija42)! - #internal Implement EVM ChainReader ValueComparator filtering by non-indexed event data. Right now only simple non indexed data where byte offsets don't exist is supported. + + PR issue: BCFR-203 + +- [#14197](https://github.com/smartcontractkit/chainlink/pull/14197) [`7f69993c86`](https://github.com/smartcontractkit/chainlink/commit/7f69993c8655053b7550f50b817ba9c6888037e2) Thanks [@graham-chainlink](https://github.com/graham-chainlink)! - #changed Allow registration of more than 1 feeds manager on CreateFeedsManager + +- [#14394](https://github.com/smartcontractkit/chainlink/pull/14394) [`28989b30d9`](https://github.com/smartcontractkit/chainlink/commit/28989b30d94bbd3490330cd8e50e7d9223d33cff) Thanks [@ilija42](https://github.com/ilija42)! - #internal Implement LatestHead for ChainService + +- [#14234](https://github.com/smartcontractkit/chainlink/pull/14234) [`a234e14ebd`](https://github.com/smartcontractkit/chainlink/commit/a234e14ebd266269b4d5893b0d2aeeb01bc58a70) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - use new estimation for insufficient fund instead of retry to overcome gas spike #internal + +- [#14369](https://github.com/smartcontractkit/chainlink/pull/14369) [`e51472763d`](https://github.com/smartcontractkit/chainlink/commit/e51472763da4039242ebd4c3939ab44c87e595d1) Thanks [@archseer](https://github.com/archseer)! - Small fixes to multichain keyring adapter #internal + +- [#13833](https://github.com/smartcontractkit/chainlink/pull/13833) [`1ea9f79793`](https://github.com/smartcontractkit/chainlink/commit/1ea9f79793f646977b44e38a34b2e70c28b2849e) Thanks [@dimriou](https://github.com/dimriou)! - Introduce new gas estimator #internal + +- [#14110](https://github.com/smartcontractkit/chainlink/pull/14110) [`8454f46db1`](https://github.com/smartcontractkit/chainlink/commit/8454f46db1985c0a4968b4eb5e0a4a6b81dfef5c) Thanks [@jmank88](https://github.com/jmank88)! - #added Full Open Telemetry support, configurable via `Telemetry` + +- [#14504](https://github.com/smartcontractkit/chainlink/pull/14504) [`10f7aabc29`](https://github.com/smartcontractkit/chainlink/commit/10f7aabc2972615cae4edd8f3532ad6aea521cee) Thanks [@austinborn](https://github.com/austinborn)! - #bugfix Fix potential nil ptr reference for LinkFeedID and NativeFeedID in Mercury specs + #bugfix Ensure Streams PluginConfig is checked for contents correctly when validated + #changed New Feed IDs with 0x01 prefix can be parsed for Mercury report schemas + +- [#14370](https://github.com/smartcontractkit/chainlink/pull/14370) [`882cdce681`](https://github.com/smartcontractkit/chainlink/commit/882cdce6811a952a38c61c3fb88349990d635d59) Thanks [@dimriou](https://github.com/dimriou)! - Remove PriceMin and TipCapMin check from attempt builder #internal + +- [#13888](https://github.com/smartcontractkit/chainlink/pull/13888) [`37c5a2ff29`](https://github.com/smartcontractkit/chainlink/commit/37c5a2ff29ad1fe661547777e60a077430530be9) Thanks [@karen-stepanyan](https://github.com/karen-stepanyan)! - #updated mercury plugin to consider PluginConfig as optional if EnableTriggerCapability relay config is true. Then if PluginConfig is nil, skip fetching latestPrice for linkFeedId and nativeFeedId. + +### Patch Changes + +- [#14350](https://github.com/smartcontractkit/chainlink/pull/14350) [`070b272f30`](https://github.com/smartcontractkit/chainlink/commit/070b272f30054be6d4239d078121ca3b3054fc33) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#14317](https://github.com/smartcontractkit/chainlink/pull/14317) [`72f4cc8aaa`](https://github.com/smartcontractkit/chainlink/commit/72f4cc8aaa128202fd5974c6dbfb29c6beb1be12) Thanks [@ettec](https://github.com/ettec)! - #internal changes required for capability api chance to sync + +- [#14471](https://github.com/smartcontractkit/chainlink/pull/14471) [`a9a4f746bf`](https://github.com/smartcontractkit/chainlink/commit/a9a4f746bf3e18d2bf9228d591166c437d5a9e6a) Thanks [@matYang](https://github.com/matYang)! - #changed Make Mantle use default OP stack l1 gas oracle in core + +- [#14416](https://github.com/smartcontractkit/chainlink/pull/14416) [`3c5bdf8d4b`](https://github.com/smartcontractkit/chainlink/commit/3c5bdf8d4b2244b3826ab54a56ec172bb9a8459c) Thanks [@dimkouv](https://github.com/dimkouv)! - RMNCrypto evm implementation for CCIP - RMN Integration #added + +- [#14313](https://github.com/smartcontractkit/chainlink/pull/14313) [`b71e692e7b`](https://github.com/smartcontractkit/chainlink/commit/b71e692e7ba8523ec57ea5e10c5d9c6810e038e5) Thanks [@ferglor](https://github.com/ferglor)! - Use a lock to sync access to the ConfigDigest #internal + +- [#14423](https://github.com/smartcontractkit/chainlink/pull/14423) [`0187f18ba6`](https://github.com/smartcontractkit/chainlink/commit/0187f18ba62b44d4c8ff20f07ef8dfd6e0d7b451) Thanks [@asoliman92](https://github.com/asoliman92)! - #updated refactor ccip oracle creator + +- [#14314](https://github.com/smartcontractkit/chainlink/pull/14314) [`8fa3ebee3e`](https://github.com/smartcontractkit/chainlink/commit/8fa3ebee3e0ce09bf2e8270ab46c168756d25db0) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal validate capability trigger event ID before executing + +- [#14366](https://github.com/smartcontractkit/chainlink/pull/14366) [`27d5cbf578`](https://github.com/smartcontractkit/chainlink/commit/27d5cbf5787531d541ba774397b3abdfcb8b20a7) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - LogPoller polls logs even if chain have not reached finality #internal + +- [#14401](https://github.com/smartcontractkit/chainlink/pull/14401) [`f6443a14e8`](https://github.com/smartcontractkit/chainlink/commit/f6443a14e836523dfa8a78b1b98a00999832f204) Thanks [@george-dorin](https://github.com/george-dorin)! - #updated Changed TelemetryIngress.UniConn default to false + +- [#14282](https://github.com/smartcontractkit/chainlink/pull/14282) [`1a2b7b61cb`](https://github.com/smartcontractkit/chainlink/commit/1a2b7b61cbd22256e4e29e891a74228fa453fc9d) Thanks [@amit-momin](https://github.com/amit-momin)! - Updated TXM Confirmer logic to resume pending task runs with failure if transaction is terminally stuck #internal + +- [#14325](https://github.com/smartcontractkit/chainlink/pull/14325) [`b1c59ddfe3`](https://github.com/smartcontractkit/chainlink/commit/b1c59ddfe31d53be6669df8f1cf246b222fbe3b0) Thanks [@DavidOrchard](https://github.com/DavidOrchard)! - configuration updates + +- [#14486](https://github.com/smartcontractkit/chainlink/pull/14486) [`1d6a88ee73`](https://github.com/smartcontractkit/chainlink/commit/1d6a88ee7313ccb857db3995d7d6ed363d7d6589) Thanks [@simsonraj](https://github.com/simsonraj)! - #added Soneium testnet chain configs + +- [#14315](https://github.com/smartcontractkit/chainlink/pull/14315) [`adb3c95799`](https://github.com/smartcontractkit/chainlink/commit/adb3c957993f9f022db395fd54e65528631c1030) Thanks [@friedemannf](https://github.com/friedemannf)! - Handle zkEVM node level OOC error as TerminallyStuck #internal + +- [#14541](https://github.com/smartcontractkit/chainlink/pull/14541) [`d9894d129d`](https://github.com/smartcontractkit/chainlink/commit/d9894d129d12204bdb14dcb0a7ce42fd19205a6d) Thanks [@friedemannf](https://github.com/friedemannf)! - #added #nops Add Zircuit Configs + +- [#14241](https://github.com/smartcontractkit/chainlink/pull/14241) [`7c248e7c46`](https://github.com/smartcontractkit/chainlink/commit/7c248e7c466ad278b0024e4ac743813009b16805) Thanks [@cds95](https://github.com/cds95)! - #internal index don ID in ConfigSet event + +- [#14543](https://github.com/smartcontractkit/chainlink/pull/14543) [`c4fa565f54`](https://github.com/smartcontractkit/chainlink/commit/c4fa565f5441bfa997907256e1990f9be276934d) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#14129](https://github.com/smartcontractkit/chainlink/pull/14129) [`85a8d09845`](https://github.com/smartcontractkit/chainlink/commit/85a8d09845d6bd30f62b1de4bf8c62f3a77a6c8e) Thanks [@simsonraj](https://github.com/simsonraj)! - #added Hedera configs + +- [#14252](https://github.com/smartcontractkit/chainlink/pull/14252) [`8490c9610b`](https://github.com/smartcontractkit/chainlink/commit/8490c9610b1208f3efafe29587032679e5727247) Thanks [@martin-cll](https://github.com/martin-cll)! - Remove bid/ask fields for Mercury v4 schema #internal + +- [#14516](https://github.com/smartcontractkit/chainlink/pull/14516) [`0e32c07d22`](https://github.com/smartcontractkit/chainlink/commit/0e32c07d22973343e722a228ff1c3b1e8f9bc04e) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Adding USDCReaderTester contract for CCIP integration tests #internal + +- [#14345](https://github.com/smartcontractkit/chainlink/pull/14345) [`c83c68735b`](https://github.com/smartcontractkit/chainlink/commit/c83c68735bdee6bbd8510733b7415797cd08ecbd) Thanks [@makramkd](https://github.com/makramkd)! - #internal merge ccip contracts + +- [#14392](https://github.com/smartcontractkit/chainlink/pull/14392) [`3f83f9e8e6`](https://github.com/smartcontractkit/chainlink/commit/3f83f9e8e66029c78a52e2c1eeb5dfb95a615f55) Thanks [@kalverra](https://github.com/kalverra)! - #added Adds the ability to use out of order execution transactions in CCIP E2E tests + +- [#14318](https://github.com/smartcontractkit/chainlink/pull/14318) [`544ded0afa`](https://github.com/smartcontractkit/chainlink/commit/544ded0afa685de146da215a949ad08b3667bb99) Thanks [@winder](https://github.com/winder)! - #internal ccip reader nonces work. + +- [#13992](https://github.com/smartcontractkit/chainlink/pull/13992) [`c1878f7374`](https://github.com/smartcontractkit/chainlink/commit/c1878f7374b7fb2de450c83b6dcae62d2a36f3bf) Thanks [@EasterTheBunny](https://github.com/EasterTheBunny)! - #internal `ContractReader` interface update to accept `BoundContract` for all methods + +- [#14130](https://github.com/smartcontractkit/chainlink/pull/14130) [`31874ba5a4`](https://github.com/smartcontractkit/chainlink/commit/31874ba5a4abbc2dca7b985f04019485a339a71c) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Optimize HeadTracker's memory usage #internal + +- [#14474](https://github.com/smartcontractkit/chainlink/pull/14474) [`aa04bfab89`](https://github.com/smartcontractkit/chainlink/commit/aa04bfab8950f001b92635388b2fb63ab1bbcec9) Thanks [@dimkouv](https://github.com/dimkouv)! - bump chainlink-ccip #updated + +- [#14488](https://github.com/smartcontractkit/chainlink/pull/14488) [`700dd7c074`](https://github.com/smartcontractkit/chainlink/commit/700dd7c074706b1a5fa89328876bdc4f3d39e025) Thanks [@ettec](https://github.com/ettec)! - #internal add support for values.Value type in the contract reader GetLatestValue and QueryKey methods + +- [#14361](https://github.com/smartcontractkit/chainlink/pull/14361) [`3a89dceab7`](https://github.com/smartcontractkit/chainlink/commit/3a89dceab79217880625f7af75db0d798cf79488) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Use tx in insertLogsWithinTx #internal + +- [#14258](https://github.com/smartcontractkit/chainlink/pull/14258) [`7905901c40`](https://github.com/smartcontractkit/chainlink/commit/7905901c40fc6ab7c65066d02e2d63324e2d640f) Thanks [@ettec](https://github.com/ettec)! - #internal gas limit default value + +- [#14415](https://github.com/smartcontractkit/chainlink/pull/14415) [`d2d9568318`](https://github.com/smartcontractkit/chainlink/commit/d2d9568318abe0ce88bc12a1308e0e96131b0223) Thanks [@martin-cll](https://github.com/martin-cll)! - Skip telemetry for market-status bridges #internal + +- [#14484](https://github.com/smartcontractkit/chainlink/pull/14484) [`d2a01ca51b`](https://github.com/smartcontractkit/chainlink/commit/d2a01ca51bb4a7654d2ceb4f5c25f2ca2de3df11) Thanks [@ogtownsend](https://github.com/ogtownsend)! - #internal KMS client for deployment + +- [#14398](https://github.com/smartcontractkit/chainlink/pull/14398) [`52b480fcc5`](https://github.com/smartcontractkit/chainlink/commit/52b480fcc53bf0162cb3aa04cc13f946babb643a) Thanks [@bolekk](https://github.com/bolekk)! - #added [Keystone] Batch identical trigger events + +- [#14355](https://github.com/smartcontractkit/chainlink/pull/14355) [`356c70cb80`](https://github.com/smartcontractkit/chainlink/commit/356c70cb8079b1052faa45d0c53fa1d8212db355) Thanks [@samsondav](https://github.com/samsondav)! - #changed + + Productionize transmitter for LLO + + Note that some minor changes to prometheus metrics will occur in the transition to LLO. Since feed IDs no longer apply, the metrics for transmissions change as follows: + + ``` + "mercury_transmit_*" + []string{"feedID", ...}, + ``` + + Will change to: + + ``` + "llo_mercury_transmit_*" + []string{"donID", ...}, + ``` + +- [#14352](https://github.com/smartcontractkit/chainlink/pull/14352) [`718e885a53`](https://github.com/smartcontractkit/chainlink/commit/718e885a53d003e16f6bc2d1be5596e63ac88b24) Thanks [@winder](https://github.com/winder)! - #internal update chainlink-ccip version + +- [#14161](https://github.com/smartcontractkit/chainlink/pull/14161) [`2b1e8ad51b`](https://github.com/smartcontractkit/chainlink/commit/2b1e8ad51b98aa41eca78758d2041ffcd7fba94a) Thanks [@friedemannf](https://github.com/friedemannf)! - Enable FeeHistory estimator for Polygon zkEVM #nops + +- [#14367](https://github.com/smartcontractkit/chainlink/pull/14367) [`cd8be702ff`](https://github.com/smartcontractkit/chainlink/commit/cd8be702ffdaef0a9176da977411ab237e544da5) Thanks [@bolekk](https://github.com/bolekk)! - Support per-method handlers in GatewayConnector + +- [#14298](https://github.com/smartcontractkit/chainlink/pull/14298) [`85b33fd9ac`](https://github.com/smartcontractkit/chainlink/commit/85b33fd9acbd342d25bd84804d08451ab2590b97) Thanks [@AnieeG](https://github.com/AnieeG)! - moved deployments ccip tooling from ccip repo to chainlink repo #added + +- [#14281](https://github.com/smartcontractkit/chainlink/pull/14281) [`73c41d1f27`](https://github.com/smartcontractkit/chainlink/commit/73c41d1f27ac43ec6ed6a27368776b187c5e5e45) Thanks [@eutopian](https://github.com/eutopian)! - skip checking isJobManaged if the proposal in fms has already been deleted #changed + +- [#14467](https://github.com/smartcontractkit/chainlink/pull/14467) [`358fc17d5b`](https://github.com/smartcontractkit/chainlink/commit/358fc17d5b5149d962002225cee7c44215cc77d4) Thanks [@akuzni2](https://github.com/akuzni2)! - #added + + - Adds support for "tags" to Tasks that can be used generically. + - Adds a descendent task search method + - Added support in Mercury EA telemetry to utilize tags for telemetry extraction + +- [#14418](https://github.com/smartcontractkit/chainlink/pull/14418) [`a2c03fc380`](https://github.com/smartcontractkit/chainlink/commit/a2c03fc380ca5919bf2f33f771a6efd98a6f4103) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Updating CCIP OCR3 integration tests according to changes in the chainlink-ccip repo #internal + +- [#14357](https://github.com/smartcontractkit/chainlink/pull/14357) [`ac3523aaa4`](https://github.com/smartcontractkit/chainlink/commit/ac3523aaa4cee6f30b9ac0f25cc7cce559067594) Thanks [@AnieeG](https://github.com/AnieeG)! - #internal Add ccip JobType in feeds service and other jobtype validations + +- [#14461](https://github.com/smartcontractkit/chainlink/pull/14461) [`22a8c993ae`](https://github.com/smartcontractkit/chainlink/commit/22a8c993ae6ae6ee69626bd239ba2a419fbad450) Thanks [@asoliman92](https://github.com/asoliman92)! - #added feed deployment to ccip integration tests + +## 2.16.0 - 2024-09-23 + +### Minor Changes + +- [#14138](https://github.com/smartcontractkit/chainlink/pull/14138) [`69335dc6b0`](https://github.com/smartcontractkit/chainlink/commit/69335dc6b0837ba9726a2772bf1dc98174c03310) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Exposed Confirmed state to ChainWriter GetTransactionStatus method + +- [#14157](https://github.com/smartcontractkit/chainlink/pull/14157) [`1852353bbf`](https://github.com/smartcontractkit/chainlink/commit/1852353bbf6ae4726287cb376bc7a323f657c92a) Thanks [@dimriou](https://github.com/dimriou)! - Fix bhe datarace #internal + +- [#14132](https://github.com/smartcontractkit/chainlink/pull/14132) [`2e314cddf0`](https://github.com/smartcontractkit/chainlink/commit/2e314cddf0f4dbd29cad4a43926dc1a5390cc70f) Thanks [@amit-momin](https://github.com/amit-momin)! - Updated ZK overflow detection to skip transactions with non-broadcasted attempts. Delayed detection for zkEVM using the MinAttempts config. Updated XLayer to use the same detection logic as zkEVM. #internal + +- [#13948](https://github.com/smartcontractkit/chainlink/pull/13948) [`3b4c2b58c3`](https://github.com/smartcontractkit/chainlink/commit/3b4c2b58c3ebb04a2261108e758a3419de436a71) Thanks [@chainchad](https://github.com/chainchad)! - Initialize start of v2.16.0 release + +- [#14100](https://github.com/smartcontractkit/chainlink/pull/14100) [`6a9528db29`](https://github.com/smartcontractkit/chainlink/commit/6a9528db29dadd231ec592f10d655e5367301d8f) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - add error handling when arbitrum sequencer is not accessible #added + +- [#13794](https://github.com/smartcontractkit/chainlink/pull/13794) [`c330defde2`](https://github.com/smartcontractkit/chainlink/commit/c330defde2211aa4a0d8392f867400a829220b2f) Thanks [@Farber98](https://github.com/Farber98)! - remove dependency on FinalityDepth in EVM TXM code. #internal + +- [#14099](https://github.com/smartcontractkit/chainlink/pull/14099) [`1d1af81c51`](https://github.com/smartcontractkit/chainlink/commit/1d1af81c51d78a7e1406d3e182b8740a2ae43c9c) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - add error handle for gnosis chiado for seen tx #added + +- [#14039](https://github.com/smartcontractkit/chainlink/pull/14039) [`b0e31e08d5`](https://github.com/smartcontractkit/chainlink/commit/b0e31e08d5a635521afc48570a4b2a01e1daa0fb) Thanks [@huangzhen1997](https://github.com/huangzhen1997)! - Improve TXM performance by optimizing Confirmer and Finalizer queries to stop pulling EVM receipt. #internal + +- [#14096](https://github.com/smartcontractkit/chainlink/pull/14096) [`3f0fad643d`](https://github.com/smartcontractkit/chainlink/commit/3f0fad643d554d2445273a67f58974cb6a785ec4) Thanks [@Farber98](https://github.com/Farber98)! - use FilteredLogs in EventBinding GetLatestValue instead of manual filtering. #internal + +- [#14068](https://github.com/smartcontractkit/chainlink/pull/14068) [`6ab3eb5b67`](https://github.com/smartcontractkit/chainlink/commit/6ab3eb5b67739ff88d3c4cf8ea125fd8273bc2b1) Thanks [@asoliman92](https://github.com/asoliman92)! - #added merging core/capabilities/ccip from https://github.com/smartcontractkit/ccip + +- [#14095](https://github.com/smartcontractkit/chainlink/pull/14095) [`aa4e981c8f`](https://github.com/smartcontractkit/chainlink/commit/aa4e981c8f51692ae19f57569260171736a3e4d9) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - #internal Change CapabilityType to string; remove possiblity of a panic + +- [#13957](https://github.com/smartcontractkit/chainlink/pull/13957) [`20dbba8e76`](https://github.com/smartcontractkit/chainlink/commit/20dbba8e76604a2488b0717d53d706ee11b11a9c) Thanks [@amit-momin](https://github.com/amit-momin)! - Added nonce validation immediately after broadcast for Hedera #internal + +- [#13638](https://github.com/smartcontractkit/chainlink/pull/13638) [`2312827156`](https://github.com/smartcontractkit/chainlink/commit/2312827156f24fa4a6e420aec12e5a3aeac81e2b) Thanks [@amit-momin](https://github.com/amit-momin)! - Introduced finalized transaction state. Added a finalizer component to the TXM to mark transactions as finalized. #internal + +- [#14041](https://github.com/smartcontractkit/chainlink/pull/14041) [`8d818ea265`](https://github.com/smartcontractkit/chainlink/commit/8d818ea265ff08887e61ace4f83364a3ee149ef0) Thanks [@amit-momin](https://github.com/amit-momin)! - Added gas limit estimation feature to EVM gas estimators. Introduced a new config `EVM.GasEstimator.EstimateLimit` to toggle this feature. #added + +- [#14165](https://github.com/smartcontractkit/chainlink/pull/14165) [`e76463cfa9`](https://github.com/smartcontractkit/chainlink/commit/e76463cfa9a0fbe6e35a74cbb3f7d63c85efcd88) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Add hexutil Bytes encoding to batchcall data + +- [#11654](https://github.com/smartcontractkit/chainlink/pull/11654) [`bf2b72d164`](https://github.com/smartcontractkit/chainlink/commit/bf2b72d164f8cc714cfbf57df59a3f3bf952b153) Thanks [@reductionista](https://github.com/reductionista)! - #bugfix More robust error handling in LogPoller, including no more misleading CRITICAL errors emitted under non-critical conditions + +- [#13647](https://github.com/smartcontractkit/chainlink/pull/13647) [`a41b353a20`](https://github.com/smartcontractkit/chainlink/commit/a41b353a20d73aa2d3fe3e8e979a0bcacc46fafe) Thanks [@bukata-sa](https://github.com/bukata-sa)! - #added Report new heads as a telemetry to OTI + +- [#13981](https://github.com/smartcontractkit/chainlink/pull/13981) [`6ef1d6eb44`](https://github.com/smartcontractkit/chainlink/commit/6ef1d6eb449ee1dc1d7d10d50990de7da55561ee) Thanks [@amaechiokolobi](https://github.com/amaechiokolobi)! - error handling for Treasure #added + +- [#14057](https://github.com/smartcontractkit/chainlink/pull/14057) [`e0850a6a31`](https://github.com/smartcontractkit/chainlink/commit/e0850a6a31843606015d1c49d52b5a6ad8727378) Thanks [@reductionista](https://github.com/reductionista)! - #bugfix Addresses 2 minor issues with the pruning of LogPoller's db tables: logs not matching any filter will now be pruned, and rows deleted are now properly reported for observability + +- [#14146](https://github.com/smartcontractkit/chainlink/pull/14146) [`d0d2f3046d`](https://github.com/smartcontractkit/chainlink/commit/d0d2f3046d44dc929b97bfff69b2daf4de2d4c8e) Thanks [@Farber98](https://github.com/Farber98)! - remove chainReader from the Relayer struct. #internal + +- [#14016](https://github.com/smartcontractkit/chainlink/pull/14016) [`8b9f2b6b90`](https://github.com/smartcontractkit/chainlink/commit/8b9f2b6b9098e8ec2368773368239106d066e4e3) Thanks [@ilija42](https://github.com/ilija42)! - #internal Add evm Chain Reader GetLatestValue support for filtering on indexed topic types that get hashed. + +- [#14033](https://github.com/smartcontractkit/chainlink/pull/14033) [`375e17b70f`](https://github.com/smartcontractkit/chainlink/commit/375e17b70fe6f17483556a491370e72218896dbc) Thanks [@Farber98](https://github.com/Farber98)! - Change ChainReader Block primitive field from int to string. #internal + +- [#14160](https://github.com/smartcontractkit/chainlink/pull/14160) [`c98feb205d`](https://github.com/smartcontractkit/chainlink/commit/c98feb205d5eef64d71c42b43516a87b83796a1d) Thanks [@ma33r](https://github.com/ma33r)! - Edited the Optimism Stack L1 Oracle to add support for Mantle #added + +- [#13999](https://github.com/smartcontractkit/chainlink/pull/13999) [`2a032e83a5`](https://github.com/smartcontractkit/chainlink/commit/2a032e83a5e09ae128e8c751779a7d1eebb729ea) Thanks [@amit-momin](https://github.com/amit-momin)! - Updated AutoPurge.Threshold and AutoPurge.MinAttempts configs to only be required for heuristic and added content-type header for Scroll API #internal + +- [#14021](https://github.com/smartcontractkit/chainlink/pull/14021) [`bd648bd73d`](https://github.com/smartcontractkit/chainlink/commit/bd648bd73df2a1de91a463a988f4c5b61e74b240) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Added custom finality calculation for Astar #internal + +- [#14145](https://github.com/smartcontractkit/chainlink/pull/14145) [`567ce229ed`](https://github.com/smartcontractkit/chainlink/commit/567ce229ed434a74b09124feadf3265017ec5313) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - Formalize trigger API #internal + +- [#14127](https://github.com/smartcontractkit/chainlink/pull/14127) [`5e99bdb764`](https://github.com/smartcontractkit/chainlink/commit/5e99bdb764171f584df1fc6e10495c8ec0a3bb63) Thanks [@amit-momin](https://github.com/amit-momin)! - Added client error classification for terminally stuck transactions in the TXM #internal + +- [#14043](https://github.com/smartcontractkit/chainlink/pull/14043) [`55e7c8b505`](https://github.com/smartcontractkit/chainlink/commit/55e7c8b5055c975665a59199d5eda9fa21801a07) Thanks [@asoliman92](https://github.com/asoliman92)! - Added CCIP plugins code from https://github.com/smartcontractkit/ccip/ #added + +### Patch Changes + +- [#14148](https://github.com/smartcontractkit/chainlink/pull/14148) [`0ceb9b5fc6`](https://github.com/smartcontractkit/chainlink/commit/0ceb9b5fc67199b850d16b6a5ab1848327e91a5b) Thanks [@vyzaldysanchez](https://github.com/vyzaldysanchez)! - #bugfix Fixes test flake + +- [#14174](https://github.com/smartcontractkit/chainlink/pull/14174) [`b9a433bff5`](https://github.com/smartcontractkit/chainlink/commit/b9a433bff513223378b8b29c6f694446d00c345b) Thanks [@DeividasK](https://github.com/DeividasK)! - #added Allow workflows to run without external registry configured + +- [#13987](https://github.com/smartcontractkit/chainlink/pull/13987) [`c1bd103e9b`](https://github.com/smartcontractkit/chainlink/commit/c1bd103e9b134a90e0bd5f77b6e54797c7c881a8) Thanks [@KodeyThomas](https://github.com/KodeyThomas)! - #added L3X Config + +- [#14236](https://github.com/smartcontractkit/chainlink/pull/14236) [`0294e1f381`](https://github.com/smartcontractkit/chainlink/commit/0294e1f3813c0643b61af828ec438307dcab3123) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Fixed deadlock in RPCClient causing CL Node to stop performing RPC requests for the affected chain #bugfix + +- [#14206](https://github.com/smartcontractkit/chainlink/pull/14206) [`621e87538c`](https://github.com/smartcontractkit/chainlink/commit/621e87538c931d5d3996974589dc27a0ab43f758) Thanks [@bukata-sa](https://github.com/bukata-sa)! - #bugfix head reporter non-zero reporting period + +- [#13862](https://github.com/smartcontractkit/chainlink/pull/13862) [`05ef7fdbb1`](https://github.com/smartcontractkit/chainlink/commit/05ef7fdbb115f55a85bcbbc5402350818501e1f5) Thanks [@martin-cll](https://github.com/martin-cll)! - New Mercury v4 report schema #added + +- [#14112](https://github.com/smartcontractkit/chainlink/pull/14112) [`1b584366d6`](https://github.com/smartcontractkit/chainlink/commit/1b584366d6bedc114946d0c8e202e95d031d5d37) Thanks [@giogam](https://github.com/giogam)! - #updated Sync feeds-manager wsrpc proto + +- [#14246](https://github.com/smartcontractkit/chainlink/pull/14246) [`f1bc2e7ad3`](https://github.com/smartcontractkit/chainlink/commit/f1bc2e7ad3610339145930991bf6a3c9ef94fa52) Thanks [@amit-momin](https://github.com/amit-momin)! - Updated gas limit estimation feature to set From address #internal + +- [#14018](https://github.com/smartcontractkit/chainlink/pull/14018) [`82accfff5c`](https://github.com/smartcontractkit/chainlink/commit/82accfff5c445fd1d29a26607234eba73e6b30fd) Thanks [@ettec](https://github.com/ettec)! - #internal fix to keystone e2e test dispatcher to correctly mock duplicate registration error + +- [#13990](https://github.com/smartcontractkit/chainlink/pull/13990) [`98fc8813dd`](https://github.com/smartcontractkit/chainlink/commit/98fc8813dd7f46e86a15fc3e838bbb681f835d0b) Thanks [@flodesi](https://github.com/flodesi)! - #added Add Astar TerminallyUnderpriced error mapping + +- [#14179](https://github.com/smartcontractkit/chainlink/pull/14179) [`633eb41a44`](https://github.com/smartcontractkit/chainlink/commit/633eb41a4467f91506e05e7fda6873c7b34f4731) Thanks [@bukata-sa](https://github.com/bukata-sa)! - #internal log info on missed finalized head instead of returning an error + +- [#14154](https://github.com/smartcontractkit/chainlink/pull/14154) [`a937d5c577`](https://github.com/smartcontractkit/chainlink/commit/a937d5c577d8ba13dc7542a757359339442ae33f) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Separate price updates schedule for token prices in CCIP #updated + +- [#14185](https://github.com/smartcontractkit/chainlink/pull/14185) [`b563d77dd3`](https://github.com/smartcontractkit/chainlink/commit/b563d77dd30ad96253ae6586c06fd34a66d61936) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Reporting all the token prices from the job spec for CCIP #updated + +- [#13756](https://github.com/smartcontractkit/chainlink/pull/13756) [`c92a7212ee`](https://github.com/smartcontractkit/chainlink/commit/c92a7212ee77b08c40d62925216e5081278a4e3f) Thanks [@vyzaldysanchez](https://github.com/vyzaldysanchez)! - #updated Adds DB syncing for registry syncer + +- [#13876](https://github.com/smartcontractkit/chainlink/pull/13876) [`15dc74cabd`](https://github.com/smartcontractkit/chainlink/commit/15dc74cabd3a83041ca97df54ea0fbb7e76e2a0a) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Custom (30s) timeout for Hedera RPC requests with large payloads (SendTransaction, CallContext, etc.) #internal + +- [#14214](https://github.com/smartcontractkit/chainlink/pull/14214) [`32a2ccd2ba`](https://github.com/smartcontractkit/chainlink/commit/32a2ccd2ba4cbe59e46779c82ec35c909141ba2a) Thanks [@ettec](https://github.com/ettec)! - #internal allow gas limit to be specified when submitting transaction + +- [#14092](https://github.com/smartcontractkit/chainlink/pull/14092) [`3399dd6d7f`](https://github.com/smartcontractkit/chainlink/commit/3399dd6d7fee12bd8d099b74397edcc4dc56c11d) Thanks [@cds95](https://github.com/cds95)! - #internal prevent editing whether or not a DON accepts workflows + +- [#13780](https://github.com/smartcontractkit/chainlink/pull/13780) [`af335c1a52`](https://github.com/smartcontractkit/chainlink/commit/af335c1a522769c8c29858d8d6510330af3204cf) Thanks [@samsondav](https://github.com/samsondav)! - Further development of LLO plugin (parallel composition) #wip + +- [#14030](https://github.com/smartcontractkit/chainlink/pull/14030) [`d90bb66934`](https://github.com/smartcontractkit/chainlink/commit/d90bb66934a46bb1c6d376b000d860e1588d91c7) Thanks [@ettec](https://github.com/ettec)! - #internal restore common version to head of develop + +- [#14105](https://github.com/smartcontractkit/chainlink/pull/14105) [`eb31cf7970`](https://github.com/smartcontractkit/chainlink/commit/eb31cf7970bef1615b10b5a734c16879b448f30a) Thanks [@ettec](https://github.com/ettec)! - #internal speed up keystone e2e tests + +- [#14047](https://github.com/smartcontractkit/chainlink/pull/14047) [`d963b0aaac`](https://github.com/smartcontractkit/chainlink/commit/d963b0aaac2117902742cf1d6fc8471e82ae711b) Thanks [@ettec](https://github.com/ettec)! - #internal fix the mock trigger to ensure events are sent + +- [#13853](https://github.com/smartcontractkit/chainlink/pull/13853) [`0f557ae1e0`](https://github.com/smartcontractkit/chainlink/commit/0f557ae1e08040c931f6f3e5c6a96b93b1ca2182) Thanks [@flodesi](https://github.com/flodesi)! - #bugfix Bump BSC PriceMin to 3 gwei to match BSC node's required gas price. This value can be pushed back down to 1 gwei to enable cheaper transactions if the GasPrice field under the Eth.Miner header in the BSC node's config is also pushed down to 1000000000 + +- [#13935](https://github.com/smartcontractkit/chainlink/pull/13935) [`7ec99efc64`](https://github.com/smartcontractkit/chainlink/commit/7ec99efc64832750825f8bc6711fb9794d6e40df) Thanks [@ettec](https://github.com/ettec)! - #internal ensure remote target request hash is deterministic + +- [#14017](https://github.com/smartcontractkit/chainlink/pull/14017) [`1257d33913`](https://github.com/smartcontractkit/chainlink/commit/1257d33913d243c146bccbf4bda67a2bb1c7d5af) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#14053](https://github.com/smartcontractkit/chainlink/pull/14053) [`4f0f7802a8`](https://github.com/smartcontractkit/chainlink/commit/4f0f7802a884e831cd76d9578ee5c4a7134034db) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - Added custom client error messages for Mantle to capture InsufficientEth and Fatal errors. #added + +- [#14059](https://github.com/smartcontractkit/chainlink/pull/14059) [`40f4becb1e`](https://github.com/smartcontractkit/chainlink/commit/40f4becb1eab96920d8bfd59019cdb9358a94122) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#14116](https://github.com/smartcontractkit/chainlink/pull/14116) [`7fdc0c8e95`](https://github.com/smartcontractkit/chainlink/commit/7fdc0c8e95c4157dd9e3ce3f9a4efe370554a19c) Thanks [@ettec](https://github.com/ettec)! - #internal ks-404 validate ids before using as seed of transmission schedule + +- [#13993](https://github.com/smartcontractkit/chainlink/pull/13993) [`f5e0bd614a`](https://github.com/smartcontractkit/chainlink/commit/f5e0bd614a6c42d195c4ad74a10f7070970d01d5) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#14209](https://github.com/smartcontractkit/chainlink/pull/14209) [`c00ac968e6`](https://github.com/smartcontractkit/chainlink/commit/c00ac968e651fd7b09f473d20f0fe4755ba57367) Thanks [@AnieeG](https://github.com/AnieeG)! - #internal Adding deployment package as new pattern for product deployment/configuration + +- [#14183](https://github.com/smartcontractkit/chainlink/pull/14183) [`35f68c806b`](https://github.com/smartcontractkit/chainlink/commit/35f68c806b10cc0fe4a565293e32e2f5581bfeb5) Thanks [@graham-chainlink](https://github.com/graham-chainlink)! - #bugfix Fix incorrect error handling when registering a new feed manager + +- [#14212](https://github.com/smartcontractkit/chainlink/pull/14212) [`25d2961154`](https://github.com/smartcontractkit/chainlink/commit/25d29611543c3d43484c168e7efc23a7bf83f035) Thanks [@bukata-sa](https://github.com/bukata-sa)! - #internal add head report chain_id + +- [#14066](https://github.com/smartcontractkit/chainlink/pull/14066) [`98b9054397`](https://github.com/smartcontractkit/chainlink/commit/98b90543972d37e4c00196f3f00bcf5f380ea04d) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#14014](https://github.com/smartcontractkit/chainlink/pull/14014) [`c2c31c05ac`](https://github.com/smartcontractkit/chainlink/commit/c2c31c05ac3fe19d4df8313af25eb740953b935a) Thanks [@Madalosso](https://github.com/Madalosso)! - #updated Update Polygon configs to match PIP-35 + +- [#14125](https://github.com/smartcontractkit/chainlink/pull/14125) [`8fa8c3a075`](https://github.com/smartcontractkit/chainlink/commit/8fa8c3a07512bb8358abdabc3fdcc8ae310c6c1c) Thanks [@bukata-sa](https://github.com/bukata-sa)! - #bugfix balance shutdown deadlock + +- [#14181](https://github.com/smartcontractkit/chainlink/pull/14181) [`ee57b4f940`](https://github.com/smartcontractkit/chainlink/commit/ee57b4f940b8a9d9d7bba41a74e4757874755f5f) Thanks [@ettec](https://github.com/ettec)! - #internal topeerid should validate []byte length + +- [#14074](https://github.com/smartcontractkit/chainlink/pull/14074) [`a865709ea1`](https://github.com/smartcontractkit/chainlink/commit/a865709ea18bfc792db758b60de6f03e953f141f) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Simplify how token and gas prices are stored in the database - user upsert instead of insert/delete flow #db_update + +- [#14050](https://github.com/smartcontractkit/chainlink/pull/14050) [`537d2ec1ad`](https://github.com/smartcontractkit/chainlink/commit/537d2ec1ad846898f820874442c3f69915096bad) Thanks [@ettec](https://github.com/ettec)! - #internal fix data race in syncer launcher + +- [#13970](https://github.com/smartcontractkit/chainlink/pull/13970) [`cefbb09797`](https://github.com/smartcontractkit/chainlink/commit/cefbb09797249309ac18e4ef81147e30f7c24360) Thanks [@cds95](https://github.com/cds95)! - #internal prevent reentrancy when configuring DON in Capabilities Registry + +- [#13907](https://github.com/smartcontractkit/chainlink/pull/13907) [`1eaf5e087a`](https://github.com/smartcontractkit/chainlink/commit/1eaf5e087a5ac204e0b472e1c307722887104678) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Added new health check that ensures RPC provides new finalized heads at least every `NoNewFinalizedHeadsThreshold` #added + +## 2.15.0 - 2024-08-21 ### Minor Changes diff --git a/GNUmakefile b/GNUmakefile index 3b781a665d2..10ac3afcafb 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -70,6 +70,16 @@ docker: --build-arg COMMIT_SHA=$(COMMIT_SHA) \ -f core/chainlink.Dockerfile . +.PHONY: docker-ccip ## Build the chainlink docker image +docker-ccip: + docker buildx build \ + --build-arg COMMIT_SHA=$(COMMIT_SHA) \ + -f core/chainlink.Dockerfile . -t chainlink-ccip:latest + + docker buildx build \ + --build-arg COMMIT_SHA=$(COMMIT_SHA) \ + -f ccip/ccip.Dockerfile . + .PHONY: docker-plugins ## Build the chainlink-plugins docker image docker-plugins: docker buildx build \ @@ -103,6 +113,10 @@ testscripts: chainlink-test ## Install and run testscript against testdata/scrip testscripts-update: ## Update testdata/scripts/* files via testscript. make testscripts TS_FLAGS="-u" +.PHONY: start-testdb +start-testdb: + docker run --name test-db-core -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres + .PHONY: setup-testdb setup-testdb: ## Setup the test database. ./core/scripts/setup_testdb.sh @@ -128,7 +142,7 @@ presubmit: ## Format go files and imports. .PHONY: gomods gomods: ## Install gomods - go install github.com/jmank88/gomods@v0.1.3 + go install github.com/jmank88/gomods@v0.1.4 .PHONY: mockery mockery: $(mockery) ## Install mockery. @@ -160,18 +174,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.59.1 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 > ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt - - -GORELEASER_CONFIG ?= .goreleaser.yaml - -.PHONY: goreleaser-dev-build -goreleaser-dev-build: ## Run goreleaser snapshot build - ./tools/bin/goreleaser_wrapper build --snapshot --rm-dist --config ${GORELEASER_CONFIG} - -.PHONY: goreleaser-dev-release -goreleaser-dev-release: ## run goreleaser snapshot release - ./tools/bin/goreleaser_wrapper release --snapshot --rm-dist --config ${GORELEASER_CONFIG} + docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.59.1 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: @@ -179,7 +182,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/README.md b/README.md index 58e6516f4ca..e7c21c1e094 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,21 @@ External adapters are what make Chainlink easily extensible, providing simple in For more information on creating and using external adapters, please see our [external adapters page](https://docs.chain.link/docs/external-adapters). +## Verify Official Chainlink Releases + +We use `cosign` with OIDC keyless signing during the [Build, Sign and Publish Chainlink](https://github.com/smartcontractkit/chainlink/actions/workflows/build-publish.yml) workflow. + +It is encourage for any node operator building from the official Chainlink docker image to verify the tagged release version was did indeed built from this workflow. + +You will need `cosign` in order to do this verification. [Follow the instruction here to install cosign](https://docs.sigstore.dev/system_config/installation/). + +```bash +# tag is the tagged release version - ie. v2.16.0 +cosign verify public.ecr.aws/chainlink/chainlink:${tag} \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + --certificate-identity "https://github.com/smartcontractkit/chainlink/.github/workflows/build-publish.yml@refs/tags/${tag}" +``` + ## Development ### Running tests diff --git a/ccip/config/README.md b/ccip/config/README.md new file mode 100644 index 00000000000..f5cd87e688e --- /dev/null +++ b/ccip/config/README.md @@ -0,0 +1,10 @@ +# Default Configurations + +:warning: IMPORTANT :warning: + +This directory contains configs that are specific to the CCIP build. Apply changes here only if related to the CCIP. + + +All config sets **inherit** from `fallback.toml` first and overwrite +fields as necessary. Do not create a new full configuration from +scratch. diff --git a/ccip/config/evm/Arbitrum_Mainnet.toml b/ccip/config/evm/Arbitrum_Mainnet.toml new file mode 100644 index 00000000000..b81d53731fb --- /dev/null +++ b/ccip/config/evm/Arbitrum_Mainnet.toml @@ -0,0 +1,32 @@ +# Arbitrum is an L2 chain. Pending proper L2 support, for now we rely on their sequencer +ChainID = '42161' +ChainType = 'arbitrum' +FinalityTagEnabled = true +LinkContractAddress = "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4" +LogPollInterval = '1s' +# Arbitrum only emits blocks when a new tx is received, so this method of liveness detection is not useful +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 + +[GasEstimator] +Mode = 'Arbitrum' +LimitMax = 1_000_000_000 +# Arbitrum uses the suggested gas price, so we don't want to place any limits on the minimum +PriceMin = '0' +PriceDefault = '0.1 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +FeeCapDefault = '1000 gwei' +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +# Force an error if someone set GAS_UPDATER_ENABLED=true by accident; we never want to run the block history estimator on arbitrum +BlockHistorySize = 0 + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' + +[NodePool] +SyncThreshold = 10 + +[OCR2.Automation] +GasLimit = 14500000 diff --git a/ccip/config/evm/Arbitrum_Sepolia.toml b/ccip/config/evm/Arbitrum_Sepolia.toml new file mode 100644 index 00000000000..2599456c6c0 --- /dev/null +++ b/ccip/config/evm/Arbitrum_Sepolia.toml @@ -0,0 +1,30 @@ +ChainID = '421614' +ChainType = 'arbitrum' +FinalityTagEnabled = true +LinkContractAddress = '0xE4aB69C077896252FAFBD49EFD26B5D171A32410' +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 +LogPollInterval = '1s' + +[GasEstimator] +Mode = 'Arbitrum' +LimitMax = 1_000_000_000 +# Arbitrum uses the suggested gas price, so we don't want to place any limits on the minimum +PriceMin = '0' +PriceDefault = '0.1 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +FeeCapDefault = '1000 gwei' +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +# Force an error if someone set GAS_UPDATER_ENABLED=true by accident; we never want to run the block history estimator on arbitrum +BlockHistorySize = 0 + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' + +[NodePool] +SyncThreshold = 10 + +[OCR2.Automation] +GasLimit = 14500000 diff --git a/ccip/config/evm/Astar_Mainnet.toml b/ccip/config/evm/Astar_Mainnet.toml new file mode 100644 index 00000000000..87808001eb7 --- /dev/null +++ b/ccip/config/evm/Astar_Mainnet.toml @@ -0,0 +1,9 @@ +ChainID = '592' +FinalityTagEnabled = true +FinalityDepth = 100 +LogPollInterval = '6s' + +[GasEstimator] +EIP1559DynamicFees = false +PriceMax = '100000 gwei' +LimitDefault = 8000000 \ No newline at end of file diff --git a/ccip/config/evm/Astar_Shibuya.toml b/ccip/config/evm/Astar_Shibuya.toml new file mode 100644 index 00000000000..5a5df06f6f0 --- /dev/null +++ b/ccip/config/evm/Astar_Shibuya.toml @@ -0,0 +1,9 @@ +ChainID = '81' +FinalityTagEnabled = true +FinalityDepth = 100 +LogPollInterval = '6s' + +[GasEstimator] +EIP1559DynamicFees = false +PriceMax = '100000 gwei' +LimitDefault = 8000000 \ No newline at end of file diff --git a/ccip/config/evm/Avalanche_ANZ_testnet.toml b/ccip/config/evm/Avalanche_ANZ_testnet.toml new file mode 100644 index 00000000000..1242e1ec06e --- /dev/null +++ b/ccip/config/evm/Avalanche_ANZ_testnet.toml @@ -0,0 +1,22 @@ +ChainID = '76578' +FinalityDepth = 1 +FinalityTagEnabled = false +LinkContractAddress = '0x779877A7B0D9E8603169DdbD7836e478b4624789' +LogPollInterval = '3s' +MinIncomingConfirmations = 1 +# Avax subnet only emits blocks when a new tx is received, so this method of liveness detection is not useful. +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 +RPCBlockQueryDelay = 2 + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +PersistenceEnabled = false diff --git a/ccip/config/evm/Avalanche_Fuji.toml b/ccip/config/evm/Avalanche_Fuji.toml new file mode 100644 index 00000000000..91b8bf6bab8 --- /dev/null +++ b/ccip/config/evm/Avalanche_Fuji.toml @@ -0,0 +1,22 @@ +ChainID = '43113' +FinalityDepth = 1 +FinalityTagEnabled = true +LinkContractAddress = '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846' +LogPollInterval = '3s' +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '30s' +OCR.ContractConfirmations = 1 +RPCBlockQueryDelay = 2 +NoNewFinalizedHeadsThreshold = '1m' + +[GasEstimator] +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +FinalityTagBypass = false +PersistenceEnabled = false diff --git a/ccip/config/evm/Avalanche_Mainnet.toml b/ccip/config/evm/Avalanche_Mainnet.toml new file mode 100644 index 00000000000..f51af60098d --- /dev/null +++ b/ccip/config/evm/Avalanche_Mainnet.toml @@ -0,0 +1,22 @@ +ChainID = '43114' +FinalityDepth = 1 +FinalityTagEnabled = true +LinkContractAddress = '0x5947BB275c521040051D82396192181b413227A3' +LogPollInterval = '3s' +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '30s' +OCR.ContractConfirmations = 1 +RPCBlockQueryDelay = 2 +NoNewFinalizedHeadsThreshold = '1m' + +[GasEstimator] +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' + +[GasEstimator.BlockHistory] +# Average block time of 2s +BlockHistorySize = 24 + +[HeadTracker] +PersistenceEnabled = false diff --git a/ccip/config/evm/BSC_Mainnet.toml b/ccip/config/evm/BSC_Mainnet.toml new file mode 100644 index 00000000000..10f4c570bef --- /dev/null +++ b/ccip/config/evm/BSC_Mainnet.toml @@ -0,0 +1,28 @@ +# BSC uses Clique consensus with ~3s block times +# Clique offers finality within (N/2)+1 blocks where N is number of signers +# There are 21 BSC validators so theoretically finality should occur after 21/2+1 = 11 blocks +ChainID = '56' +# Keeping this >> 11 because it's not expensive and gives us a safety margin +FinalityDepth = 50 +FinalityTagEnabled = true +LinkContractAddress = '0x404460C6A5EdE2D891e8297795264fDe62ADBB75' +LogPollInterval = '3s' +NoNewHeadsThreshold = '30s' +RPCBlockQueryDelay = 2 +NoNewFinalizedHeadsThreshold = '45s' + +[GasEstimator] +PriceDefault = '5 gwei' +# 15s delay since feeds update every minute in volatile situations +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[OCR] +DatabaseTimeout = '2s' +ContractTransmitterTransmitTimeout = '2s' +ObservationGracePeriod = '500ms' + +[NodePool] +SyncThreshold = 10 diff --git a/ccip/config/evm/BSC_Testnet.toml b/ccip/config/evm/BSC_Testnet.toml new file mode 100644 index 00000000000..bb13501f1a2 --- /dev/null +++ b/ccip/config/evm/BSC_Testnet.toml @@ -0,0 +1,34 @@ +# BSC uses Clique consensus with ~3s block times +# Clique offers finality within (N/2)+1 blocks where N is number of signers +# There are 21 BSC validators so theoretically finality should occur after 21/2+1 = 11 blocks +ChainID = '97' +# Keeping this >> 11 because it's not expensive and gives us a safety margin +FinalityDepth = 50 +FinalityTagEnabled = true +LinkContractAddress = '0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06' +LogPollInterval = '3s' +NoNewHeadsThreshold = '30s' +RPCBlockQueryDelay = 2 +NoNewFinalizedHeadsThreshold = '40s' + +[GasEstimator] +PriceDefault = '5 gwei' +# 15s delay since feeds update every minute in volatile situations +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +HistoryDepth = 100 +SamplingInterval = '1s' +FinalityTagBypass = false +PersistenceEnabled = false + +[OCR] +DatabaseTimeout = '2s' +ContractTransmitterTransmitTimeout = '2s' +ObservationGracePeriod = '500ms' + +[NodePool] +SyncThreshold = 10 diff --git a/ccip/config/evm/Base_Mainnet.toml b/ccip/config/evm/Base_Mainnet.toml new file mode 100644 index 00000000000..da38182b194 --- /dev/null +++ b/ccip/config/evm/Base_Mainnet.toml @@ -0,0 +1,31 @@ +ChainID = '8453' +ChainType = 'optimismBedrock' +FinalityDepth = 200 +FinalityTagEnabled = true +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '15m' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 diff --git a/ccip/config/evm/Base_Sepolia.toml b/ccip/config/evm/Base_Sepolia.toml new file mode 100644 index 00000000000..92f7717b27d --- /dev/null +++ b/ccip/config/evm/Base_Sepolia.toml @@ -0,0 +1,32 @@ +ChainID = '84532' +ChainType = 'optimismBedrock' +FinalityDepth = 200 +FinalityTagEnabled = true +LinkContractAddress = '0xE4aB69C077896252FAFBD49EFD26B5D171A32410' +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '12m' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 60 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 diff --git a/ccip/config/evm/Blast_Mainnet.toml b/ccip/config/evm/Blast_Mainnet.toml new file mode 100644 index 00000000000..f8b501723ff --- /dev/null +++ b/ccip/config/evm/Blast_Mainnet.toml @@ -0,0 +1,34 @@ +ChainID = '81457' +FinalityDepth = 200 +FinalityTagEnabled = true +ChainType = 'optimismBedrock' +# block rate is ~2sec, so this ensures blocks are polled correctly +LogPollInterval = '2s' + +[GasEstimator] +EIP1559DynamicFees = true +BumpThreshold = 60 +BumpPercent = 20 +BumpMin = '100 wei' +PriceMax = '120 gwei' +LimitDefault = 8000000 +FeeCapDefault = '120 gwei' + +[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 + +[HeadTracker] +HistoryDepth = 300 + +[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 diff --git a/ccip/config/evm/Blast_Sepolia.toml b/ccip/config/evm/Blast_Sepolia.toml new file mode 100644 index 00000000000..96dc5c67871 --- /dev/null +++ b/ccip/config/evm/Blast_Sepolia.toml @@ -0,0 +1,34 @@ +ChainID = '168587773' +FinalityDepth = 200 +FinalityTagEnabled = true +ChainType = 'optimismBedrock' +# block rate is ~2sec, so this ensures blocks are polled correctly +LogPollInterval = '2s' + +[GasEstimator] +EIP1559DynamicFees = true +BumpThreshold = 60 +BumpPercent = 20 +BumpMin = '100 wei' +PriceMax = '120 gwei' +LimitDefault = 8000000 +FeeCapDefault = '120 gwei' + +[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 + +[HeadTracker] +HistoryDepth = 300 + +[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 diff --git a/ccip/config/evm/Celo_Mainnet.toml b/ccip/config/evm/Celo_Mainnet.toml new file mode 100644 index 00000000000..0ed08986d32 --- /dev/null +++ b/ccip/config/evm/Celo_Mainnet.toml @@ -0,0 +1,21 @@ +ChainID = '42220' +ChainType = 'celo' +FinalityDepth = 10 +LogPollInterval = '5s' +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '1m' +OCR.ContractConfirmations = 1 +NoNewFinalizedHeadsThreshold = '1m' + +[GasEstimator] +PriceDefault = '5 gwei' +PriceMax = '500 gwei' +PriceMin = '5 gwei' +BumpMin = '2 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 12 + +[HeadTracker] +HistoryDepth = 50 +PersistenceEnabled = false diff --git a/ccip/config/evm/Celo_Testnet.toml b/ccip/config/evm/Celo_Testnet.toml new file mode 100644 index 00000000000..4f457b103e0 --- /dev/null +++ b/ccip/config/evm/Celo_Testnet.toml @@ -0,0 +1,21 @@ +ChainID = '44787' +ChainType = 'celo' +FinalityDepth = 10 +LogPollInterval = '5s' +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '1m' +OCR.ContractConfirmations = 1 +NoNewFinalizedHeadsThreshold = '1m' + +[GasEstimator] +PriceDefault = '5 gwei' +PriceMax = '500 gwei' +PriceMin = '5 gwei' +BumpMin = '2 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +HistoryDepth = 50 +PersistenceEnabled = false diff --git a/ccip/config/evm/Ethereum_Mainnet.toml b/ccip/config/evm/Ethereum_Mainnet.toml new file mode 100644 index 00000000000..0bcaf35c648 --- /dev/null +++ b/ccip/config/evm/Ethereum_Mainnet.toml @@ -0,0 +1,17 @@ +ChainID = '1' +LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' +MinContractPayment = '0.1 link' +OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +FinalityTagEnabled = true +NoNewFinalizedHeadsThreshold = '9m' + +[GasEstimator] +EIP1559DynamicFees = true + +[GasEstimator.BlockHistory] +# EIP-1559 does well on a smaller block history size +BlockHistorySize = 4 +TransactionPercentile = 50 + +[OCR2.Automation] +GasLimit = 10500000 diff --git a/ccip/config/evm/Ethereum_Sepolia.toml b/ccip/config/evm/Ethereum_Sepolia.toml new file mode 100644 index 00000000000..24a0e68f77a --- /dev/null +++ b/ccip/config/evm/Ethereum_Sepolia.toml @@ -0,0 +1,17 @@ +ChainID = '11155111' +LinkContractAddress = '0x779877A7B0D9E8603169DdbD7836e478b4624789' +MinContractPayment = '0.1 link' +FinalityTagEnabled = true + +[GasEstimator] +EIP1559DynamicFees = true + +[GasEstimator.BlockHistory] +BlockHistorySize = 4 +TransactionPercentile = 50 + +[OCR2.Automation] +GasLimit = 10500000 + +[HeadTracker] +FinalityTagBypass = false diff --git a/ccip/config/evm/Fantom_Mainnet.toml b/ccip/config/evm/Fantom_Mainnet.toml new file mode 100644 index 00000000000..7e76d94278d --- /dev/null +++ b/ccip/config/evm/Fantom_Mainnet.toml @@ -0,0 +1,12 @@ +ChainID = '250' +LinkContractAddress = '0x6F43FF82CCA38001B6699a8AC47A2d0E66939407' +LogPollInterval = '1s' +NoNewHeadsThreshold = '30s' +RPCBlockQueryDelay = 2 + +[GasEstimator] +# Fantom network has been slow to include txs at times when using the BlockHistory estimator, and the recommendation is to use SuggestedPrice mode. +Mode = 'SuggestedPrice' + +[OCR2.Automation] +GasLimit = 3800000 \ No newline at end of file diff --git a/ccip/config/evm/Fantom_Testnet.toml b/ccip/config/evm/Fantom_Testnet.toml new file mode 100644 index 00000000000..5f24a76c2e7 --- /dev/null +++ b/ccip/config/evm/Fantom_Testnet.toml @@ -0,0 +1,12 @@ +ChainID = '4002' +LinkContractAddress = '0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F' +LogPollInterval = '1s' +# Fantom testnet only emits blocks when a new tx is received, so this method of liveness detection is not useful +NoNewHeadsThreshold = '0' +RPCBlockQueryDelay = 2 + +[GasEstimator] +Mode = 'SuggestedPrice' + +[OCR2.Automation] +GasLimit = 3800000 \ No newline at end of file diff --git a/ccip/config/evm/Gnosis_Chiado.toml b/ccip/config/evm/Gnosis_Chiado.toml new file mode 100644 index 00000000000..379377a2266 --- /dev/null +++ b/ccip/config/evm/Gnosis_Chiado.toml @@ -0,0 +1,10 @@ +ChainID = '10200' +# Gnoisis Finality is approx 8 minutes @ 12 blocks per minute, so 96 blocks +FinalityDepth = 100 +ChainType = 'gnosis' +LogPollInterval = '5s' +NoNewFinalizedHeadsThreshold = '2m' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMax = '500 gwei' diff --git a/ccip/config/evm/Gnosis_Mainnet.toml b/ccip/config/evm/Gnosis_Mainnet.toml new file mode 100644 index 00000000000..628646364f5 --- /dev/null +++ b/ccip/config/evm/Gnosis_Mainnet.toml @@ -0,0 +1,18 @@ +# xDai currently uses AuRa (like Parity) consensus so finality rules will be similar to parity +# See: https://www.poa.network/for-users/whitepaper/poadao-v1/proof-of-authority +# NOTE: xDai is planning to move to Honeybadger BFT which might have different finality guarantees +# https://www.xdaichain.com/for-validators/consensus/honeybadger-bft-consensus +# For worst case re-org depth on AuRa, assume 2n+2 (see: https://github.com/poanetwork/wiki/wiki/Aura-Consensus-Protocol-Audit) +# With xDai's current maximum of 19 validators then 40 blocks is the maximum possible re-org) +# The mainnet default of 50 blocks is ok here +ChainID = '100' +ChainType = 'gnosis' +LinkContractAddress = '0xE2e73A1c69ecF83F464EFCE6A5be353a37cA09b2' +LogPollInterval = '5s' +NoNewFinalizedHeadsThreshold = '2m' + +[GasEstimator] +PriceDefault = '1 gwei' +PriceMax = '500 gwei' +# 1 Gwei is the minimum accepted by the validators (unless whitelisted) +PriceMin = '1 gwei' diff --git a/ccip/config/evm/Kroma_Mainnet.toml b/ccip/config/evm/Kroma_Mainnet.toml new file mode 100644 index 00000000000..3a48aa8ae1b --- /dev/null +++ b/ccip/config/evm/Kroma_Mainnet.toml @@ -0,0 +1,27 @@ +ChainID = '255' +ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture +FinalityDepth = 400 +FinalityTagEnabled = true +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 400 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 diff --git a/ccip/config/evm/Kroma_Sepolia.toml b/ccip/config/evm/Kroma_Sepolia.toml new file mode 100644 index 00000000000..9609a09e076 --- /dev/null +++ b/ccip/config/evm/Kroma_Sepolia.toml @@ -0,0 +1,27 @@ +ChainID = '2358' +ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture +FinalityDepth = 400 +FinalityTagEnabled = true +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 400 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 diff --git a/ccip/config/evm/L3X_Mainnet.toml b/ccip/config/evm/L3X_Mainnet.toml new file mode 100644 index 00000000000..9dd33c9e15d --- /dev/null +++ b/ccip/config/evm/L3X_Mainnet.toml @@ -0,0 +1,21 @@ +ChainID = '12324' +ChainType = 'arbitrum' +FinalityTagEnabled = true +FinalityDepth = 10 +LinkContractAddress = '0x79f531a3D07214304F259DC28c7191513223bcf3' +# Produces blocks on-demand +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 +LogPollInterval = '10s' + +[GasEstimator] +Mode = 'Arbitrum' +LimitMax = 1_000_000_000 +# Arbitrum-based chains uses the suggested gas price, so we don't want to place any limits on the minimum +PriceMin = '0' +PriceDefault = '0.1 gwei' +FeeCapDefault = '1000 gwei' +BumpThreshold = 5 + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' diff --git a/ccip/config/evm/L3X_Sepolia.toml b/ccip/config/evm/L3X_Sepolia.toml new file mode 100644 index 00000000000..c0f6a60e943 --- /dev/null +++ b/ccip/config/evm/L3X_Sepolia.toml @@ -0,0 +1,21 @@ +ChainID = '12325' +ChainType = 'arbitrum' +FinalityTagEnabled = true +FinalityDepth = 10 +LinkContractAddress = '0xa71848C99155DA0b245981E5ebD1C94C4be51c43' +# Produces blocks on-demand +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 +LogPollInterval = '10s' + +[GasEstimator] +Mode = 'Arbitrum' +LimitMax = 1_000_000_000 +# Arbitrum-based chains uses the suggested gas price, so we don't want to place any limits on the minimum +PriceMin = '0' +PriceDefault = '0.1 gwei' +FeeCapDefault = '1000 gwei' +BumpThreshold = 5 + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' diff --git a/ccip/config/evm/Linea_Mainnet.toml b/ccip/config/evm/Linea_Mainnet.toml new file mode 100644 index 00000000000..94d8bedc44b --- /dev/null +++ b/ccip/config/evm/Linea_Mainnet.toml @@ -0,0 +1,17 @@ +ChainID = '59144' +# Block time 12s, finality < 60m +FinalityDepth = 300 +# Blocks are only emitted when a transaction happens / no empty blocks +NoNewHeadsThreshold = '0' + +[GasEstimator] +BumpPercent = 40 +PriceMin = '400 mwei' + +[Transactions] +# increase resend time to align with finality +ResendAfterThreshold = '3m' + +# set greater than finality depth +[HeadTracker] +HistoryDepth = 350 diff --git a/ccip/config/evm/Linea_Sepolia.toml b/ccip/config/evm/Linea_Sepolia.toml new file mode 100644 index 00000000000..ac5e18a09b6 --- /dev/null +++ b/ccip/config/evm/Linea_Sepolia.toml @@ -0,0 +1,13 @@ +ChainID = '59141' +FinalityDepth = 900 +NoNewHeadsThreshold = '0' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' + +[Transactions] +ResendAfterThreshold = '3m' + +[HeadTracker] +HistoryDepth = 1000 \ No newline at end of file diff --git a/ccip/config/evm/Mantle_Sepolia.toml b/ccip/config/evm/Mantle_Sepolia.toml new file mode 100644 index 00000000000..ee994a71826 --- /dev/null +++ b/ccip/config/evm/Mantle_Sepolia.toml @@ -0,0 +1,19 @@ +ChainID = '5003' +ChainType = 'optimismBedrock' +FinalityDepth = 500 +LogPollInterval = '2s' +NoNewHeadsThreshold = '0' +MinIncomingConfirmations = 1 + +[HeadTracker] +HistoryDepth = 600 + +[GasEstimator] +Mode = 'L2Suggested' +PriceMax = '200 gwei' +LimitDefault = 100000000 +FeeCapDefault = '200 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 200 +EIP1559FeeCapBufferBlocks = 0 \ No newline at end of file diff --git a/ccip/config/evm/Metis_Mainnet.toml b/ccip/config/evm/Metis_Mainnet.toml new file mode 100644 index 00000000000..f057400d014 --- /dev/null +++ b/ccip/config/evm/Metis_Mainnet.toml @@ -0,0 +1,21 @@ +# Metis is an L2 chain based on Optimism. +ChainID = '1088' +ChainType = 'metis' +# Sequencer offers absolute finality +FinalityDepth = 10 +FinalityTagEnabled = true +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 + +[GasEstimator] +Mode = 'SuggestedPrice' +# Metis uses the SuggestedPrice estimator; we don't want to place any limits on the minimum gas price +PriceMin = '0' + +[GasEstimator.BlockHistory] +# Force an error if someone enables the estimator by accident; we never want to run the block history estimator on metisaa +BlockHistorySize = 0 + +[NodePool] +SyncThreshold = 10 diff --git a/ccip/config/evm/Metis_Sepolia.toml b/ccip/config/evm/Metis_Sepolia.toml new file mode 100644 index 00000000000..4ff4056c75d --- /dev/null +++ b/ccip/config/evm/Metis_Sepolia.toml @@ -0,0 +1,17 @@ +ChainID = '59902' +ChainType = 'optimismBedrock' +FinalityDepth = 10 +FinalityTagEnabled = true +MinIncomingConfirmations = 1 +NoNewHeadsThreshold = '0' +OCR.ContractConfirmations = 1 + +[GasEstimator] +Mode = 'SuggestedPrice' +PriceMin = '0' + +[GasEstimator.BlockHistory] +BlockHistorySize = 0 + +[NodePool] +SyncThreshold = 10 diff --git a/ccip/config/evm/Mode_Mainnet.toml b/ccip/config/evm/Mode_Mainnet.toml new file mode 100644 index 00000000000..69a8e93fecd --- /dev/null +++ b/ccip/config/evm/Mode_Mainnet.toml @@ -0,0 +1,30 @@ +ChainID = '34443' +FinalityDepth = 200 +FinalityTagEnabled = true +ChainType = 'optimismBedrock' + +[GasEstimator] +EIP1559DynamicFees = true +BumpThreshold = 60 +BumpPercent = 20 +BumpMin = '100 wei' +PriceMax = '120 gwei' +LimitDefault = 8000000 +FeeCapDefault = '120 gwei' + +[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 + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +PollFailureThreshold = 2 +PollInterval = '3s' diff --git a/ccip/config/evm/Mode_Sepolia.toml b/ccip/config/evm/Mode_Sepolia.toml new file mode 100644 index 00000000000..f7398869beb --- /dev/null +++ b/ccip/config/evm/Mode_Sepolia.toml @@ -0,0 +1,30 @@ +ChainID = '919' +FinalityDepth = 200 +FinalityTagEnabled = true +ChainType = 'optimismBedrock' + +[GasEstimator] +EIP1559DynamicFees = true +BumpThreshold = 60 +BumpPercent = 20 +BumpMin = '100 wei' +PriceMax = '120 gwei' +LimitDefault = 8000000 +FeeCapDefault = '120 gwei' + +[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 + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +PollFailureThreshold = 2 +PollInterval = '3s' diff --git a/ccip/config/evm/OKX_Mainnet.toml b/ccip/config/evm/OKX_Mainnet.toml new file mode 100644 index 00000000000..d0b26ede2e3 --- /dev/null +++ b/ccip/config/evm/OKX_Mainnet.toml @@ -0,0 +1 @@ +ChainID = '66' diff --git a/ccip/config/evm/OKX_Testnet.toml b/ccip/config/evm/OKX_Testnet.toml new file mode 100644 index 00000000000..2587f010b18 --- /dev/null +++ b/ccip/config/evm/OKX_Testnet.toml @@ -0,0 +1 @@ +ChainID = '65' diff --git a/ccip/config/evm/Optimism_Mainnet.toml b/ccip/config/evm/Optimism_Mainnet.toml new file mode 100644 index 00000000000..b0f56a49d90 --- /dev/null +++ b/ccip/config/evm/Optimism_Mainnet.toml @@ -0,0 +1,32 @@ +ChainID = '10' +ChainType = 'optimismBedrock' +FinalityDepth = 200 +FinalityTagEnabled = true +LinkContractAddress = '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6' +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '13m' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 diff --git a/ccip/config/evm/Optimism_Sepolia.toml b/ccip/config/evm/Optimism_Sepolia.toml new file mode 100644 index 00000000000..1c71aa5dd83 --- /dev/null +++ b/ccip/config/evm/Optimism_Sepolia.toml @@ -0,0 +1,31 @@ +ChainID = '11155420' +ChainType = 'optimismBedrock' +FinalityDepth = 200 +FinalityTagEnabled = true +LogPollInterval = '2s' +NoNewHeadsThreshold = '40s' +MinIncomingConfirmations = 1 +NoNewFinalizedHeadsThreshold = '15m' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 60 + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 300 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 diff --git a/ccip/config/evm/Polygon_Amoy.toml b/ccip/config/evm/Polygon_Amoy.toml new file mode 100644 index 00000000000..b05b3053a8e --- /dev/null +++ b/ccip/config/evm/Polygon_Amoy.toml @@ -0,0 +1,28 @@ +ChainID = '80002' +FinalityDepth = 500 +LogPollInterval = '1s' +MinIncomingConfirmations = 5 +NoNewHeadsThreshold = '30s' +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 +NoNewFinalizedHeadsThreshold = '12m' + +[Transactions] +MaxQueued = 5000 + +[GasEstimator] +EIP1559DynamicFees = true +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceDefault = '25 gwei' +PriceMin = '25 gwei' +BumpMin = '20 gwei' +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +HistoryDepth = 2000 + +[NodePool] +SyncThreshold = 10 diff --git a/ccip/config/evm/Polygon_Mainnet.toml b/ccip/config/evm/Polygon_Mainnet.toml new file mode 100644 index 00000000000..bf605cab3c6 --- /dev/null +++ b/ccip/config/evm/Polygon_Mainnet.toml @@ -0,0 +1,38 @@ +# Polygon has a 1s block time and looser finality guarantees than ethereum. +ChainID = '137' +# It is quite common to see re-orgs on polygon go several hundred blocks deep. See: https://polygonscan.com/blocks_forked +FinalityDepth = 500 +FinalityTagEnabled = true +LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' +LogPollInterval = '1s' +MinIncomingConfirmations = 5 +NoNewHeadsThreshold = '30s' +# Must be set to something large here because Polygon has so many re-orgs that otherwise we are constantly refetching +RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 100 +NoNewFinalizedHeadsThreshold = '6m' + +[Transactions] +# Matic nodes under high mempool pressure are liable to drop txes, we need to ensure we keep sending them +# Since re-orgs on Polygon can be so large, we need a large safety buffer to allow time for the queue to clear down before we start dropping transactions +MaxQueued = 5000 + +[GasEstimator] +# Many Polygon RPC providers set a minimum of 30 GWei on mainnet to prevent spam +PriceDefault = '30 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +# Many Polygon RPC providers set a minimum of 30 GWei on mainnet to prevent spam +PriceMin = '30 gwei' +BumpMin = '20 gwei' +# 10s delay since feeds update every minute in volatile situations +BumpThreshold = 5 + +[GasEstimator.BlockHistory] +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 + +[NodePool] +SyncThreshold = 10 diff --git a/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Goerli.toml b/ccip/config/evm/Polygon_Zkevm_Cardona.toml similarity index 90% rename from core/chains/evm/config/toml/defaults/Polygon_Zkevm_Goerli.toml rename to ccip/config/evm/Polygon_Zkevm_Cardona.toml index 6a9b47190fd..cd91465dae6 100644 --- a/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Goerli.toml +++ b/ccip/config/evm/Polygon_Zkevm_Cardona.toml @@ -1,4 +1,4 @@ -ChainID = '1442' +ChainID = '2442' ChainType = 'zkevm' FinalityDepth = 500 NoNewHeadsThreshold = '12m' @@ -13,7 +13,7 @@ ContractConfirmations = 1 ResendAfterThreshold = '3m' [GasEstimator] -PriceMin = '50 mwei' +PriceMin = '1 mwei' BumpPercent = 40 BumpMin = '20 mwei' diff --git a/ccip/config/evm/Polygon_Zkevm_Mainnet.toml b/ccip/config/evm/Polygon_Zkevm_Mainnet.toml new file mode 100644 index 00000000000..79e0cb0fce5 --- /dev/null +++ b/ccip/config/evm/Polygon_Zkevm_Mainnet.toml @@ -0,0 +1,26 @@ +ChainID = '1101' +ChainType = 'zkevm' +FinalityDepth = 500 +NoNewHeadsThreshold = '6m' +MinIncomingConfirmations = 1 +LogPollInterval = '30s' +RPCBlockQueryDelay = 15 +RPCDefaultBatchSize = 100 + +[OCR] +ContractConfirmations = 1 + +[Transactions] +ResendAfterThreshold = '3m' + +[GasEstimator] +PriceMin = '100 mwei' +BumpPercent = 40 +BumpMin = '100 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 12 + +[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 diff --git a/ccip/config/evm/Scroll_Mainnet.toml b/ccip/config/evm/Scroll_Mainnet.toml new file mode 100644 index 00000000000..4a887b504df --- /dev/null +++ b/ccip/config/evm/Scroll_Mainnet.toml @@ -0,0 +1,22 @@ +ChainID = '534352' +FinalityDepth = 10 +FinalityTagEnabled = true +ChainType = 'scroll' +LogPollInterval = '5s' +MinIncomingConfirmations = 1 +# Scroll only emits blocks when a new tx is received, so this method of liveness detection is not useful +NoNewHeadsThreshold = '0' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '1 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +HistoryDepth = 50 + +[OCR] +ContractConfirmations = 1 diff --git a/ccip/config/evm/Scroll_Sepolia.toml b/ccip/config/evm/Scroll_Sepolia.toml new file mode 100644 index 00000000000..b2e1cfbd733 --- /dev/null +++ b/ccip/config/evm/Scroll_Sepolia.toml @@ -0,0 +1,22 @@ +ChainID = '534351' +FinalityDepth = 10 +FinalityTagEnabled = true +ChainType = 'scroll' +LogPollInterval = '5s' +MinIncomingConfirmations = 1 +# Scroll only emits blocks when a new tx is received, so this method of liveness detection is not useful +NoNewHeadsThreshold = '0' + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '1 gwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[HeadTracker] +HistoryDepth = 50 + +[OCR] +ContractConfirmations = 1 diff --git a/ccip/config/evm/Simulated.toml b/ccip/config/evm/Simulated.toml new file mode 100644 index 00000000000..e21dc0990f0 --- /dev/null +++ b/ccip/config/evm/Simulated.toml @@ -0,0 +1,25 @@ +ChainID = '1337' +FinalityDepth = 1 +MinIncomingConfirmations = 1 +MinContractPayment = '100' +NoNewHeadsThreshold = '0s' + +[Transactions] +ReaperThreshold = '0s' +ResendAfterThreshold = '0s' + +[GasEstimator] +Mode = 'FixedPrice' +PriceMin = '0' +BumpThreshold = 0 +FeeCapDefault = '100 micro' +PriceMax = '100 micro' + +[HeadTracker] +HistoryDepth = 10 +MaxBufferSize = 100 +SamplingInterval = '0s' +PersistenceEnabled = false + +[OCR] +ContractConfirmations = 1 diff --git a/ccip/config/evm/WeMix_Mainnet.toml b/ccip/config/evm/WeMix_Mainnet.toml new file mode 100644 index 00000000000..be7c278f692 --- /dev/null +++ b/ccip/config/evm/WeMix_Mainnet.toml @@ -0,0 +1,19 @@ +ChainID = '1111' +ChainType = 'wemix' +FinalityDepth = 1 +FinalityTagEnabled = true +MinIncomingConfirmations = 1 +# WeMix emits a block every 1 second, regardless of transactions +LogPollInterval = '3s' +NoNewHeadsThreshold = '30s' +NoNewFinalizedHeadsThreshold = '40s' + +[OCR] +ContractConfirmations = 1 + +[GasEstimator] +EIP1559DynamicFees = true +TipCapDefault = '100 gwei' + +[HeadTracker] +PersistenceEnabled = false diff --git a/ccip/config/evm/WeMix_Testnet.toml b/ccip/config/evm/WeMix_Testnet.toml new file mode 100644 index 00000000000..4591fc4c572 --- /dev/null +++ b/ccip/config/evm/WeMix_Testnet.toml @@ -0,0 +1,20 @@ +ChainID = '1112' +ChainType = 'wemix' +FinalityDepth = 1 +FinalityTagEnabled = true +MinIncomingConfirmations = 1 +# WeMix emits a block every 1 second, regardless of transactions +LogPollInterval = '3s' +NoNewHeadsThreshold = '30s' +NoNewFinalizedHeadsThreshold = '40s' + +[OCR] +ContractConfirmations = 1 + +[GasEstimator] +EIP1559DynamicFees = true +TipCapDefault = '100 gwei' + +[HeadTracker] +FinalityTagBypass = false +PersistenceEnabled = false diff --git a/ccip/config/evm/XLayer_Mainnet.toml b/ccip/config/evm/XLayer_Mainnet.toml new file mode 100644 index 00000000000..4096a4db244 --- /dev/null +++ b/ccip/config/evm/XLayer_Mainnet.toml @@ -0,0 +1,25 @@ +ChainID = '196' +ChainType = 'xlayer' +FinalityDepth = 500 +NoNewHeadsThreshold = '6m' +MinIncomingConfirmations = 1 +LogPollInterval = '30s' +RPCBlockQueryDelay = 15 +RPCDefaultBatchSize = 100 + +[OCR] +ContractConfirmations = 1 + +[Transactions] +ResendAfterThreshold = '3m' + +[GasEstimator] +PriceMin = '100 mwei' +BumpPercent = 40 +BumpMin = '100 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 12 + +[HeadTracker] +HistoryDepth = 2000 diff --git a/ccip/config/evm/XLayer_Sepolia.toml b/ccip/config/evm/XLayer_Sepolia.toml new file mode 100644 index 00000000000..62e2c1e8ad0 --- /dev/null +++ b/ccip/config/evm/XLayer_Sepolia.toml @@ -0,0 +1,25 @@ +ChainID = '195' +ChainType = 'xlayer' +FinalityDepth = 500 +NoNewHeadsThreshold = '12m' +MinIncomingConfirmations = 1 +LogPollInterval = '30s' +RPCBlockQueryDelay = 15 +RPCDefaultBatchSize = 100 + +[OCR] +ContractConfirmations = 1 + +[Transactions] +ResendAfterThreshold = '3m' + +[GasEstimator] +PriceMin = '1 mwei' +BumpPercent = 40 +BumpMin = '20 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 12 + +[HeadTracker] +HistoryDepth = 2000 diff --git a/ccip/config/evm/zkSync_Mainnet.toml b/ccip/config/evm/zkSync_Mainnet.toml new file mode 100644 index 00000000000..a8910a37e4a --- /dev/null +++ b/ccip/config/evm/zkSync_Mainnet.toml @@ -0,0 +1,31 @@ +ChainID = '324' +ChainType = 'zksync' +# 1200block ~ 20min concurrent with the l1_committed tag +FinalityDepth = 1200 +# 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 +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' + +[GasEstimator.BlockHistory] +# increasing this to smooth out gas estimation +BlockHistorySize = 200 + +[GasEstimator.DAOracle] +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 diff --git a/ccip/config/evm/zkSync_Sepolia.toml b/ccip/config/evm/zkSync_Sepolia.toml new file mode 100644 index 00000000000..6eb4ba4137e --- /dev/null +++ b/ccip/config/evm/zkSync_Sepolia.toml @@ -0,0 +1,31 @@ +ChainID = '300' +ChainType = 'zksync' +# 200block ~ 20min concurrent with the l1_committed tag +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 +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' + +[GasEstimator.BlockHistory] +# increasing this to smooth out gas estimation +BlockHistorySize = 200 + +[GasEstimator.DAOracle] +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 diff --git a/common/client/mock_node_client_test.go b/common/client/mock_node_client_test.go deleted file mode 100644 index 5643dcde90e..00000000000 --- a/common/client/mock_node_client_test.go +++ /dev/null @@ -1,718 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package client - -import ( - context "context" - - types "github.com/smartcontractkit/chainlink/v2/common/types" - mock "github.com/stretchr/testify/mock" -) - -// mockNodeClient is an autogenerated mock type for the NodeClient type -type mockNodeClient[CHAIN_ID types.ID, HEAD Head] struct { - mock.Mock -} - -type mockNodeClient_Expecter[CHAIN_ID types.ID, HEAD Head] struct { - mock *mock.Mock -} - -func (_m *mockNodeClient[CHAIN_ID, HEAD]) EXPECT() *mockNodeClient_Expecter[CHAIN_ID, HEAD] { - return &mockNodeClient_Expecter[CHAIN_ID, HEAD]{mock: &_m.Mock} -} - -// ChainID provides a mock function with given fields: ctx -func (_m *mockNodeClient[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 -} - -// mockNodeClient_ChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainID' -type mockNodeClient_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 *mockNodeClient_Expecter[CHAIN_ID, HEAD]) ChainID(ctx interface{}) *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_ChainID_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("ChainID", ctx)} -} - -func (_c *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD]) Return(_a0 CHAIN_ID, _a1 error) *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (CHAIN_ID, error)) *mockNodeClient_ChainID_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// ClientVersion provides a mock function with given fields: _a0 -func (_m *mockNodeClient[CHAIN_ID, HEAD]) ClientVersion(_a0 context.Context) (string, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for ClientVersion") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) string); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockNodeClient_ClientVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientVersion' -type mockNodeClient_ClientVersion_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// ClientVersion is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) ClientVersion(_a0 interface{}) *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("ClientVersion", _a0)} -} - -func (_c *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD]) Run(run func(_a0 context.Context)) *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD]) Return(_a0 string, _a1 error) *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (string, error)) *mockNodeClient_ClientVersion_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *mockNodeClient[CHAIN_ID, HEAD]) Close() { - _m.Called() -} - -// mockNodeClient_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type mockNodeClient_Close_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) Close() *mockNodeClient_Close_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_Close_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("Close")} -} - -func (_c *mockNodeClient_Close_Call[CHAIN_ID, HEAD]) Run(run func()) *mockNodeClient_Close_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeClient_Close_Call[CHAIN_ID, HEAD]) Return() *mockNodeClient_Close_Call[CHAIN_ID, HEAD] { - _c.Call.Return() - return _c -} - -func (_c *mockNodeClient_Close_Call[CHAIN_ID, HEAD]) RunAndReturn(run func()) *mockNodeClient_Close_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// Dial provides a mock function with given fields: ctx -func (_m *mockNodeClient[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 -} - -// mockNodeClient_Dial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Dial' -type mockNodeClient_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 *mockNodeClient_Expecter[CHAIN_ID, HEAD]) Dial(ctx interface{}) *mockNodeClient_Dial_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_Dial_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("Dial", ctx)} -} - -func (_c *mockNodeClient_Dial_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockNodeClient_Dial_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNodeClient_Dial_Call[CHAIN_ID, HEAD]) Return(_a0 error) *mockNodeClient_Dial_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNodeClient_Dial_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) error) *mockNodeClient_Dial_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// DialHTTP provides a mock function with given fields: -func (_m *mockNodeClient[CHAIN_ID, HEAD]) DialHTTP() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for DialHTTP") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockNodeClient_DialHTTP_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DialHTTP' -type mockNodeClient_DialHTTP_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// DialHTTP is a helper method to define mock.On call -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) DialHTTP() *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("DialHTTP")} -} - -func (_c *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD]) Run(run func()) *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD]) Return(_a0 error) *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD]) RunAndReturn(run func() error) *mockNodeClient_DialHTTP_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// DisconnectAll provides a mock function with given fields: -func (_m *mockNodeClient[CHAIN_ID, HEAD]) DisconnectAll() { - _m.Called() -} - -// mockNodeClient_DisconnectAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisconnectAll' -type mockNodeClient_DisconnectAll_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// DisconnectAll is a helper method to define mock.On call -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) DisconnectAll() *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("DisconnectAll")} -} - -func (_c *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD]) Run(run func()) *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD]) Return() *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD] { - _c.Call.Return() - return _c -} - -func (_c *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD]) RunAndReturn(run func()) *mockNodeClient_DisconnectAll_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// GetInterceptedChainInfo provides a mock function with given fields: -func (_m *mockNodeClient[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 -} - -// mockNodeClient_GetInterceptedChainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInterceptedChainInfo' -type mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// GetInterceptedChainInfo is a helper method to define mock.On call -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) GetInterceptedChainInfo() *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("GetInterceptedChainInfo")} -} - -func (_c *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]) Run(run func()) *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]) Return(latest ChainInfo, highestUserObservations ChainInfo) *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - _c.Call.Return(latest, highestUserObservations) - return _c -} - -func (_c *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD]) RunAndReturn(run func() (ChainInfo, ChainInfo)) *mockNodeClient_GetInterceptedChainInfo_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// IsSyncing provides a mock function with given fields: ctx -func (_m *mockNodeClient[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 -} - -// mockNodeClient_IsSyncing_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSyncing' -type mockNodeClient_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 *mockNodeClient_Expecter[CHAIN_ID, HEAD]) IsSyncing(ctx interface{}) *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("IsSyncing", ctx)} -} - -func (_c *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD]) Return(_a0 bool, _a1 error) *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (bool, error)) *mockNodeClient_IsSyncing_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SetAliveLoopSub provides a mock function with given fields: _a0 -func (_m *mockNodeClient[CHAIN_ID, HEAD]) SetAliveLoopSub(_a0 types.Subscription) { - _m.Called(_a0) -} - -// mockNodeClient_SetAliveLoopSub_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAliveLoopSub' -type mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// SetAliveLoopSub is a helper method to define mock.On call -// - _a0 types.Subscription -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) SetAliveLoopSub(_a0 interface{}) *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SetAliveLoopSub", _a0)} -} - -func (_c *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD]) Run(run func(_a0 types.Subscription)) *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Subscription)) - }) - return _c -} - -func (_c *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD]) Return() *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD] { - _c.Call.Return() - return _c -} - -func (_c *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(types.Subscription)) *mockNodeClient_SetAliveLoopSub_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SubscribeNewHead provides a mock function with given fields: ctx, channel -func (_m *mockNodeClient[CHAIN_ID, HEAD]) SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (types.Subscription, error) { - ret := _m.Called(ctx, channel) - - if len(ret) == 0 { - panic("no return value specified for SubscribeNewHead") - } - - var r0 types.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) (types.Subscription, error)); ok { - return rf(ctx, channel) - } - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) types.Subscription); ok { - r0 = rf(ctx, channel) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD) error); ok { - r1 = rf(ctx, channel) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockNodeClient_SubscribeNewHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeNewHead' -type mockNodeClient_SubscribeNewHead_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// SubscribeNewHead is a helper method to define mock.On call -// - ctx context.Context -// - channel chan<- HEAD -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) SubscribeNewHead(ctx interface{}, channel interface{}) *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SubscribeNewHead", ctx, channel)} -} - -func (_c *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context, channel chan<- HEAD)) *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(chan<- HEAD)) - }) - return _c -} - -func (_c *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD]) Return(s types.Subscription, err error) *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD] { - _c.Call.Return(s, err) - return _c -} - -func (_c *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context, chan<- HEAD) (types.Subscription, error)) *mockNodeClient_SubscribeNewHead_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SubscribeToFinalizedHeads provides a mock function with given fields: _a0 -func (_m *mockNodeClient[CHAIN_ID, HEAD]) SubscribeToFinalizedHeads(_a0 context.Context) (<-chan HEAD, types.Subscription, error) { - ret := _m.Called(_a0) - - 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(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) <-chan HEAD); ok { - r0 = rf(_a0) - } 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(_a0) - } 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(_a0) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// mockNodeClient_SubscribeToFinalizedHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToFinalizedHeads' -type mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// SubscribeToFinalizedHeads is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) SubscribeToFinalizedHeads(_a0 interface{}) *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SubscribeToFinalizedHeads", _a0)} -} - -func (_c *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]) Run(run func(_a0 context.Context)) *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]) Return(_a0 <-chan HEAD, _a1 types.Subscription, _a2 error) *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0, _a1, _a2) - return _c -} - -func (_c *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (<-chan HEAD, types.Subscription, error)) *mockNodeClient_SubscribeToFinalizedHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SubscribeToHeads provides a mock function with given fields: ctx -func (_m *mockNodeClient[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 -} - -// mockNodeClient_SubscribeToHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToHeads' -type mockNodeClient_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 *mockNodeClient_Expecter[CHAIN_ID, HEAD]) SubscribeToHeads(ctx interface{}) *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SubscribeToHeads", ctx)} -} - -func (_c *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]) Run(run func(ctx context.Context)) *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]) Return(ch <-chan HEAD, sub types.Subscription, err error) *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(ch, sub, err) - return _c -} - -func (_c *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD]) RunAndReturn(run func(context.Context) (<-chan HEAD, types.Subscription, error)) *mockNodeClient_SubscribeToHeads_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// SubscribersCount provides a mock function with given fields: -func (_m *mockNodeClient[CHAIN_ID, HEAD]) SubscribersCount() int32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for SubscribersCount") - } - - var r0 int32 - if rf, ok := ret.Get(0).(func() int32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int32) - } - - return r0 -} - -// mockNodeClient_SubscribersCount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribersCount' -type mockNodeClient_SubscribersCount_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// SubscribersCount is a helper method to define mock.On call -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) SubscribersCount() *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("SubscribersCount")} -} - -func (_c *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD]) Run(run func()) *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD]) Return(_a0 int32) *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD]) RunAndReturn(run func() int32) *mockNodeClient_SubscribersCount_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// UnsubscribeAllExceptAliveLoop provides a mock function with given fields: -func (_m *mockNodeClient[CHAIN_ID, HEAD]) UnsubscribeAllExceptAliveLoop() { - _m.Called() -} - -// mockNodeClient_UnsubscribeAllExceptAliveLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscribeAllExceptAliveLoop' -type mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID types.ID, HEAD Head] struct { - *mock.Call -} - -// UnsubscribeAllExceptAliveLoop is a helper method to define mock.On call -func (_e *mockNodeClient_Expecter[CHAIN_ID, HEAD]) UnsubscribeAllExceptAliveLoop() *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD] { - return &mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD]{Call: _e.mock.On("UnsubscribeAllExceptAliveLoop")} -} - -func (_c *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD]) Run(run func()) *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD]) Return() *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD] { - _c.Call.Return() - return _c -} - -func (_c *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD]) RunAndReturn(run func()) *mockNodeClient_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD] { - _c.Call.Return(run) - return _c -} - -// newMockNodeClient creates a new instance of mockNodeClient. 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 newMockNodeClient[CHAIN_ID types.ID, HEAD Head](t interface { - mock.TestingT - Cleanup(func()) -}) *mockNodeClient[CHAIN_ID, HEAD] { - mock := &mockNodeClient[CHAIN_ID, HEAD]{} - 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 index d05c2979fc1..2860f8076fd 100644 --- a/common/client/mock_node_selector_test.go +++ b/common/client/mock_node_selector_test.go @@ -8,20 +8,20 @@ import ( ) // mockNodeSelector is an autogenerated mock type for the NodeSelector type -type mockNodeSelector[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNodeSelector[CHAIN_ID types.ID, RPC interface{}] struct { mock.Mock } -type mockNodeSelector_Expecter[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNodeSelector_Expecter[CHAIN_ID types.ID, RPC interface{}] struct { mock *mock.Mock } -func (_m *mockNodeSelector[CHAIN_ID, HEAD, RPC]) EXPECT() *mockNodeSelector_Expecter[CHAIN_ID, HEAD, RPC] { - return &mockNodeSelector_Expecter[CHAIN_ID, HEAD, RPC]{mock: &_m.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, HEAD, RPC]) Name() string { +func (_m *mockNodeSelector[CHAIN_ID, RPC]) Name() string { ret := _m.Called() if len(ret) == 0 { @@ -39,46 +39,46 @@ func (_m *mockNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNodeSelector_Name_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // Name is a helper method to define mock.On call -func (_e *mockNodeSelector_Expecter[CHAIN_ID, HEAD, RPC]) Name() *mockNodeSelector_Name_Call[CHAIN_ID, HEAD, RPC] { - return &mockNodeSelector_Name_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("Name")} +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, HEAD, RPC]) Run(run func()) *mockNodeSelector_Name_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 string) *mockNodeSelector_Name_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() string) *mockNodeSelector_Name_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC] - if rf, ok := ret.Get(0).(func() Node[CHAIN_ID, HEAD, RPC]); ok { + 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, HEAD, RPC]) + r0 = ret.Get(0).(Node[CHAIN_ID, RPC]) } } @@ -86,39 +86,39 @@ func (_m *mockNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, R } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNodeSelector_Select_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // Select is a helper method to define mock.On call -func (_e *mockNodeSelector_Expecter[CHAIN_ID, HEAD, RPC]) Select() *mockNodeSelector_Select_Call[CHAIN_ID, HEAD, RPC] { - return &mockNodeSelector_Select_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("Select")} +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, HEAD, RPC]) Run(run func()) *mockNodeSelector_Select_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 Node[CHAIN_ID, HEAD, RPC]) *mockNodeSelector_Select_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() Node[CHAIN_ID, HEAD, RPC]) *mockNodeSelector_Select_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]](t interface { +func newMockNodeSelector[CHAIN_ID types.ID, RPC interface{}](t interface { mock.TestingT Cleanup(func()) -}) *mockNodeSelector[CHAIN_ID, HEAD, RPC] { - mock := &mockNodeSelector[CHAIN_ID, HEAD, RPC]{} +}) *mockNodeSelector[CHAIN_ID, RPC] { + mock := &mockNodeSelector[CHAIN_ID, RPC]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/common/client/mock_node_test.go b/common/client/mock_node_test.go index a342a533a7d..968f980b988 100644 --- a/common/client/mock_node_test.go +++ b/common/client/mock_node_test.go @@ -10,20 +10,20 @@ import ( ) // mockNode is an autogenerated mock type for the Node type -type mockNode[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode[CHAIN_ID types.ID, RPC interface{}] struct { mock.Mock } -type mockNode_Expecter[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_Expecter[CHAIN_ID types.ID, RPC interface{}] struct { mock *mock.Mock } -func (_m *mockNode[CHAIN_ID, HEAD, RPC]) EXPECT() *mockNode_Expecter[CHAIN_ID, HEAD, RPC] { - return &mockNode_Expecter[CHAIN_ID, HEAD, RPC]{mock: &_m.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, HEAD, RPC]) Close() error { +func (_m *mockNode[CHAIN_ID, RPC]) Close() error { ret := _m.Called() if len(ret) == 0 { @@ -41,34 +41,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Close() error { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_Close_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // Close is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) Close() *mockNode_Close_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_Close_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("Close")} +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, HEAD, RPC]) Run(run func()) *mockNode_Close_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 error) *mockNode_Close_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() error) *mockNode_Close_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) ConfiguredChainID() CHAIN_ID { +func (_m *mockNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID { ret := _m.Called() if len(ret) == 0 { @@ -86,34 +86,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() CHAIN_ID { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_ConfiguredChainID_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // ConfiguredChainID is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() *mockNode_ConfiguredChainID_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_ConfiguredChainID_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("ConfiguredChainID")} +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, HEAD, RPC]) Run(run func()) *mockNode_ConfiguredChainID_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 CHAIN_ID) *mockNode_ConfiguredChainID_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() CHAIN_ID) *mockNode_ConfiguredChainID_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) HighestUserObservations() ChainInfo { +func (_m *mockNode[CHAIN_ID, RPC]) HighestUserObservations() ChainInfo { ret := _m.Called() if len(ret) == 0 { @@ -131,34 +131,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) HighestUserObservations() ChainInfo { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_HighestUserObservations_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // HighestUserObservations is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) HighestUserObservations() *mockNode_HighestUserObservations_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_HighestUserObservations_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("HighestUserObservations")} +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, HEAD, RPC]) Run(run func()) *mockNode_HighestUserObservations_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 ChainInfo) *mockNode_HighestUserObservations_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() ChainInfo) *mockNode_HighestUserObservations_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Name() string { +func (_m *mockNode[CHAIN_ID, RPC]) Name() string { ret := _m.Called() if len(ret) == 0 { @@ -176,34 +176,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Name() string { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_Name_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // Name is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) Name() *mockNode_Name_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_Name_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("Name")} +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, HEAD, RPC]) Run(run func()) *mockNode_Name_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 string) *mockNode_Name_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() string) *mockNode_Name_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Order() int32 { +func (_m *mockNode[CHAIN_ID, RPC]) Order() int32 { ret := _m.Called() if len(ret) == 0 { @@ -221,34 +221,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Order() int32 { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_Order_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // Order is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) Order() *mockNode_Order_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_Order_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("Order")} +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, HEAD, RPC]) Run(run func()) *mockNode_Order_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 int32) *mockNode_Order_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() int32) *mockNode_Order_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RPC() RPC { +func (_m *mockNode[CHAIN_ID, RPC]) RPC() RPC { ret := _m.Called() if len(ret) == 0 { @@ -266,67 +266,67 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) RPC() RPC { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_RPC_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // RPC is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) RPC() *mockNode_RPC_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_RPC_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("RPC")} +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, HEAD, RPC]) Run(run func()) *mockNode_RPC_Call[CHAIN_ID, HEAD, 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, HEAD, RPC]) Return(_a0 RPC) *mockNode_RPC_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() RPC) *mockNode_RPC_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) SetPoolChainInfoProvider(_a0 PoolChainInfoProvider) { +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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // SetPoolChainInfoProvider is a helper method to define mock.On call // - _a0 PoolChainInfoProvider -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) SetPoolChainInfoProvider(_a0 interface{}) *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("SetPoolChainInfoProvider", _a0)} +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, HEAD, RPC]) Run(run func(_a0 PoolChainInfoProvider)) *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return() *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func(PoolChainInfoProvider)) *mockNode_SetPoolChainInfoProvider_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Start(_a0 context.Context) error { +func (_m *mockNode[CHAIN_ID, RPC]) Start(_a0 context.Context) error { ret := _m.Called(_a0) if len(ret) == 0 { @@ -344,35 +344,35 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Start(_a0 context.Context) error { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_Start_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // Start is a helper method to define mock.On call // - _a0 context.Context -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) Start(_a0 interface{}) *mockNode_Start_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_Start_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("Start", _a0)} +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, HEAD, RPC]) Run(run func(_a0 context.Context)) *mockNode_Start_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 error) *mockNode_Start_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func(context.Context) error) *mockNode_Start_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) State() nodeState { +func (_m *mockNode[CHAIN_ID, RPC]) State() nodeState { ret := _m.Called() if len(ret) == 0 { @@ -390,34 +390,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) State() nodeState { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_State_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // State is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) State() *mockNode_State_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_State_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("State")} +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, HEAD, RPC]) Run(run func()) *mockNode_State_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 nodeState) *mockNode_State_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() nodeState) *mockNode_State_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) StateAndLatest() (nodeState, ChainInfo) { +func (_m *mockNode[CHAIN_ID, RPC]) StateAndLatest() (nodeState, ChainInfo) { ret := _m.Called() if len(ret) == 0 { @@ -445,34 +445,34 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, ChainInfo) } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_StateAndLatest_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // StateAndLatest is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) StateAndLatest() *mockNode_StateAndLatest_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_StateAndLatest_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("StateAndLatest")} +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, HEAD, RPC]) Run(run func()) *mockNode_StateAndLatest_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 nodeState, _a1 ChainInfo) *mockNode_StateAndLatest_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() (nodeState, ChainInfo)) *mockNode_StateAndLatest_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) String() string { +func (_m *mockNode[CHAIN_ID, RPC]) String() string { ret := _m.Called() if len(ret) == 0 { @@ -490,116 +490,71 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) String() string { } // 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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_String_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // String is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) String() *mockNode_String_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_String_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("String")} +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, HEAD, RPC]) Run(run func()) *mockNode_String_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return(_a0 string) *mockNode_String_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func() string) *mockNode_String_Call[CHAIN_ID, HEAD, RPC] { - _c.Call.Return(run) - return _c -} - -// SubscribersCount provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, HEAD, RPC]) SubscribersCount() int32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for SubscribersCount") - } - - var r0 int32 - if rf, ok := ret.Get(0).(func() int32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int32) - } - - return r0 -} - -// mockNode_SubscribersCount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribersCount' -type mockNode_SubscribersCount_Call[CHAIN_ID types.ID, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { - *mock.Call -} - -// SubscribersCount is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) SubscribersCount() *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("SubscribersCount")} -} - -func (_c *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC]) Run(run func()) *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC]) Return(_a0 int32) *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC]) RunAndReturn(run func() int32) *mockNode_SubscribersCount_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() { +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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]] struct { +type mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } // UnsubscribeAllExceptAliveLoop is a helper method to define mock.On call -func (_e *mockNode_Expecter[CHAIN_ID, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD, RPC] { - return &mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD, RPC]{Call: _e.mock.On("UnsubscribeAllExceptAliveLoop")} +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, HEAD, RPC]) Run(run func()) *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) Return() *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC]) RunAndReturn(run func()) *mockNode_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, HEAD, RPC] { +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, HEAD Head, RPC NodeClient[CHAIN_ID, HEAD]](t interface { +func newMockNode[CHAIN_ID types.ID, RPC interface{}](t interface { mock.TestingT Cleanup(func()) -}) *mockNode[CHAIN_ID, HEAD, RPC] { - mock := &mockNode[CHAIN_ID, HEAD, RPC]{} +}) *mockNode[CHAIN_ID, RPC] { + mock := &mockNode[CHAIN_ID, RPC]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/common/client/mock_rpc_client_test.go b/common/client/mock_rpc_client_test.go new file mode 100644 index 00000000000..30452ded77b --- /dev/null +++ b/common/client/mock_rpc_client_test.go @@ -0,0 +1,508 @@ +// Code generated by mockery v2.43.2. 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_rpc_test.go b/common/client/mock_rpc_test.go deleted file mode 100644 index 00473c66369..00000000000 --- a/common/client/mock_rpc_test.go +++ /dev/null @@ -1,1918 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package client - -import ( - big "math/big" - - assets "github.com/smartcontractkit/chainlink-common/pkg/assets" - - context "context" - - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" - - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink/v2/common/types" -) - -// mockRPC is an autogenerated mock type for the RPC type -type mockRPC[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - mock.Mock -} - -type mockRPC_Expecter[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - mock *mock.Mock -} - -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) EXPECT() *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{mock: &_m.Mock} -} - -// BalanceAt provides a mock function with given fields: ctx, accountAddress, blockNumber -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BalanceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (*big.Int, error) { - ret := _m.Called(ctx, accountAddress, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for BalanceAt") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) (*big.Int, error)); ok { - return rf(ctx, accountAddress, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) *big.Int); ok { - r0 = rf(ctx, accountAddress, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ADDR, *big.Int) error); ok { - r1 = rf(ctx, accountAddress, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_BalanceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BalanceAt' -type mockRPC_BalanceAt_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// BalanceAt is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress ADDR -// - blockNumber *big.Int -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BalanceAt(ctx interface{}, accountAddress interface{}, blockNumber interface{}) *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("BalanceAt", ctx, accountAddress, blockNumber)} -} - -func (_c *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, accountAddress ADDR, blockNumber *big.Int)) *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR), args[2].(*big.Int)) - }) - return _c -} - -func (_c *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 *big.Int, _a1 error) *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, ADDR, *big.Int) (*big.Int, error)) *mockRPC_BalanceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// BatchCallContext provides a mock function with given fields: ctx, b -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BatchCallContext(ctx context.Context, b []BATCH_ELEM) error { - ret := _m.Called(ctx, b) - - if len(ret) == 0 { - panic("no return value specified for BatchCallContext") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []BATCH_ELEM) error); ok { - r0 = rf(ctx, b) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPC_BatchCallContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchCallContext' -type mockRPC_BatchCallContext_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// BatchCallContext is a helper method to define mock.On call -// - ctx context.Context -// - b []BATCH_ELEM -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BatchCallContext(ctx interface{}, b interface{}) *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("BatchCallContext", ctx, b)} -} - -func (_c *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, b []BATCH_ELEM)) *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]BATCH_ELEM)) - }) - return _c -} - -func (_c *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 error) *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, []BATCH_ELEM) error) *mockRPC_BatchCallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// BlockByHash provides a mock function with given fields: ctx, hash -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BlockByHash(ctx context.Context, hash BLOCK_HASH) (HEAD, error) { - ret := _m.Called(ctx, hash) - - if len(ret) == 0 { - panic("no return value specified for BlockByHash") - } - - var r0 HEAD - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, BLOCK_HASH) (HEAD, error)); ok { - return rf(ctx, hash) - } - if rf, ok := ret.Get(0).(func(context.Context, BLOCK_HASH) HEAD); ok { - r0 = rf(ctx, hash) - } else { - r0 = ret.Get(0).(HEAD) - } - - if rf, ok := ret.Get(1).(func(context.Context, BLOCK_HASH) error); ok { - r1 = rf(ctx, hash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_BlockByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByHash' -type mockRPC_BlockByHash_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// BlockByHash is a helper method to define mock.On call -// - ctx context.Context -// - hash BLOCK_HASH -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BlockByHash(ctx interface{}, hash interface{}) *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("BlockByHash", ctx, hash)} -} - -func (_c *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, hash BLOCK_HASH)) *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(BLOCK_HASH)) - }) - return _c -} - -func (_c *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 HEAD, _a1 error) *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, BLOCK_HASH) (HEAD, error)) *mockRPC_BlockByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// BlockByNumber provides a mock function with given fields: ctx, number -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BlockByNumber(ctx context.Context, number *big.Int) (HEAD, error) { - ret := _m.Called(ctx, number) - - if len(ret) == 0 { - panic("no return value specified for BlockByNumber") - } - - var r0 HEAD - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (HEAD, error)); ok { - return rf(ctx, number) - } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) HEAD); ok { - r0 = rf(ctx, number) - } else { - r0 = ret.Get(0).(HEAD) - } - - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, number) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_BlockByNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByNumber' -type mockRPC_BlockByNumber_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// BlockByNumber is a helper method to define mock.On call -// - ctx context.Context -// - number *big.Int -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) BlockByNumber(ctx interface{}, number interface{}) *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("BlockByNumber", ctx, number)} -} - -func (_c *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, number *big.Int)) *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*big.Int)) - }) - return _c -} - -func (_c *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 HEAD, _a1 error) *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, *big.Int) (HEAD, error)) *mockRPC_BlockByNumber_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// CallContext provides a mock function with given fields: ctx, result, method, args -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - var _ca []interface{} - _ca = append(_ca, ctx, result, method) - _ca = append(_ca, args...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for CallContext") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, string, ...interface{}) error); ok { - r0 = rf(ctx, result, method, args...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPC_CallContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CallContext' -type mockRPC_CallContext_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// CallContext is a helper method to define mock.On call -// - ctx context.Context -// - result interface{} -// - method string -// - args ...interface{} -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) CallContext(ctx interface{}, result interface{}, method interface{}, args ...interface{}) *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("CallContext", - append([]interface{}{ctx, result, method}, args...)...)} -} - -func (_c *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, result interface{}, method string, args ...interface{})) *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]interface{}, len(args)-3) - for i, a := range args[3:] { - if a != nil { - variadicArgs[i] = a.(interface{}) - } - } - run(args[0].(context.Context), args[1].(interface{}), args[2].(string), variadicArgs...) - }) - return _c -} - -func (_c *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 error) *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, interface{}, string, ...interface{}) error) *mockRPC_CallContext_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// CallContract provides a mock function with given fields: ctx, msg, blockNumber -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) ([]byte, error) { - ret := _m.Called(ctx, msg, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for CallContract") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, *big.Int) ([]byte, error)); ok { - return rf(ctx, msg, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, interface{}, *big.Int) []byte); ok { - r0 = rf(ctx, msg, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, interface{}, *big.Int) error); ok { - r1 = rf(ctx, msg, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_CallContract_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CallContract' -type mockRPC_CallContract_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// CallContract is a helper method to define mock.On call -// - ctx context.Context -// - msg interface{} -// - blockNumber *big.Int -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) CallContract(ctx interface{}, msg interface{}, blockNumber interface{}) *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("CallContract", ctx, msg, blockNumber)} -} - -func (_c *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, msg interface{}, blockNumber *big.Int)) *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(*big.Int)) - }) - return _c -} - -func (_c *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(rpcErr []byte, extractErr error) *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(rpcErr, extractErr) - return _c -} - -func (_c *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, interface{}, *big.Int) ([]byte, error)) *mockRPC_CallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// ChainID provides a mock function with given fields: ctx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) 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 -} - -// mockRPC_ChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainID' -type mockRPC_ChainID_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// ChainID is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) ChainID(ctx interface{}) *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("ChainID", ctx)} -} - -func (_c *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context)) *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 CHAIN_ID, _a1 error) *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (CHAIN_ID, error)) *mockRPC_ChainID_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// ClientVersion provides a mock function with given fields: _a0 -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) ClientVersion(_a0 context.Context) (string, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for ClientVersion") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) string); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_ClientVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientVersion' -type mockRPC_ClientVersion_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// ClientVersion is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) ClientVersion(_a0 interface{}) *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("ClientVersion", _a0)} -} - -func (_c *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(_a0 context.Context)) *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 string, _a1 error) *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (string, error)) *mockRPC_ClientVersion_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Close() { - _m.Called() -} - -// mockRPC_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type mockRPC_Close_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Close() *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("Close")} -} - -func (_c *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func()) *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return() *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return() - return _c -} - -func (_c *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func()) *mockRPC_Close_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// CodeAt provides a mock function with given fields: ctx, account, blockNumber -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) ([]byte, error) { - ret := _m.Called(ctx, account, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for CodeAt") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) ([]byte, error)); ok { - return rf(ctx, account, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) []byte); ok { - r0 = rf(ctx, account, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ADDR, *big.Int) error); ok { - r1 = rf(ctx, account, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_CodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CodeAt' -type mockRPC_CodeAt_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// CodeAt is a helper method to define mock.On call -// - ctx context.Context -// - account ADDR -// - blockNumber *big.Int -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) CodeAt(ctx interface{}, account interface{}, blockNumber interface{}) *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("CodeAt", ctx, account, blockNumber)} -} - -func (_c *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, account ADDR, blockNumber *big.Int)) *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR), args[2].(*big.Int)) - }) - return _c -} - -func (_c *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 []byte, _a1 error) *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, ADDR, *big.Int) ([]byte, error)) *mockRPC_CodeAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// Dial provides a mock function with given fields: ctx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) 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 -} - -// mockRPC_Dial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Dial' -type mockRPC_Dial_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// Dial is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Dial(ctx interface{}) *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("Dial", ctx)} -} - -func (_c *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context)) *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 error) *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) error) *mockRPC_Dial_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// DialHTTP provides a mock function with given fields: -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) DialHTTP() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for DialHTTP") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPC_DialHTTP_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DialHTTP' -type mockRPC_DialHTTP_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// DialHTTP is a helper method to define mock.On call -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) DialHTTP() *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("DialHTTP")} -} - -func (_c *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func()) *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 error) *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func() error) *mockRPC_DialHTTP_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// DisconnectAll provides a mock function with given fields: -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) DisconnectAll() { - _m.Called() -} - -// mockRPC_DisconnectAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisconnectAll' -type mockRPC_DisconnectAll_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// DisconnectAll is a helper method to define mock.On call -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) DisconnectAll() *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("DisconnectAll")} -} - -func (_c *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func()) *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return() *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return() - return _c -} - -func (_c *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func()) *mockRPC_DisconnectAll_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// EstimateGas provides a mock function with given fields: ctx, call -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) EstimateGas(ctx context.Context, call interface{}) (uint64, error) { - ret := _m.Called(ctx, call) - - if len(ret) == 0 { - panic("no return value specified for EstimateGas") - } - - var r0 uint64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}) (uint64, error)); ok { - return rf(ctx, call) - } - if rf, ok := ret.Get(0).(func(context.Context, interface{}) uint64); ok { - r0 = rf(ctx, call) - } else { - r0 = ret.Get(0).(uint64) - } - - if rf, ok := ret.Get(1).(func(context.Context, interface{}) error); ok { - r1 = rf(ctx, call) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_EstimateGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGas' -type mockRPC_EstimateGas_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// EstimateGas is a helper method to define mock.On call -// - ctx context.Context -// - call interface{} -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) EstimateGas(ctx interface{}, call interface{}) *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("EstimateGas", ctx, call)} -} - -func (_c *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, call interface{})) *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{})) - }) - return _c -} - -func (_c *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(gas uint64, err error) *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(gas, err) - return _c -} - -func (_c *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, interface{}) (uint64, error)) *mockRPC_EstimateGas_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// FilterEvents provides a mock function with given fields: ctx, query -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) FilterEvents(ctx context.Context, query EVENT_OPS) ([]EVENT, error) { - ret := _m.Called(ctx, query) - - if len(ret) == 0 { - panic("no return value specified for FilterEvents") - } - - var r0 []EVENT - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, EVENT_OPS) ([]EVENT, error)); ok { - return rf(ctx, query) - } - if rf, ok := ret.Get(0).(func(context.Context, EVENT_OPS) []EVENT); ok { - r0 = rf(ctx, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]EVENT) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, EVENT_OPS) error); ok { - r1 = rf(ctx, query) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_FilterEvents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterEvents' -type mockRPC_FilterEvents_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// FilterEvents is a helper method to define mock.On call -// - ctx context.Context -// - query EVENT_OPS -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) FilterEvents(ctx interface{}, query interface{}) *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("FilterEvents", ctx, query)} -} - -func (_c *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, query EVENT_OPS)) *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(EVENT_OPS)) - }) - return _c -} - -func (_c *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 []EVENT, _a1 error) *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, EVENT_OPS) ([]EVENT, error)) *mockRPC_FilterEvents_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// GetInterceptedChainInfo provides a mock function with given fields: -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) 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 -} - -// mockRPC_GetInterceptedChainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInterceptedChainInfo' -type mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// GetInterceptedChainInfo is a helper method to define mock.On call -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) GetInterceptedChainInfo() *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("GetInterceptedChainInfo")} -} - -func (_c *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func()) *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(latest ChainInfo, highestUserObservations ChainInfo) *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(latest, highestUserObservations) - return _c -} - -func (_c *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func() (ChainInfo, ChainInfo)) *mockRPC_GetInterceptedChainInfo_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// IsSyncing provides a mock function with given fields: ctx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) 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 -} - -// mockRPC_IsSyncing_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSyncing' -type mockRPC_IsSyncing_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// IsSyncing is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) IsSyncing(ctx interface{}) *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("IsSyncing", ctx)} -} - -func (_c *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context)) *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 bool, _a1 error) *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (bool, error)) *mockRPC_IsSyncing_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// LINKBalance provides a mock function with given fields: ctx, accountAddress, linkAddress -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) LINKBalance(ctx context.Context, accountAddress ADDR, linkAddress ADDR) (*assets.Link, error) { - ret := _m.Called(ctx, accountAddress, linkAddress) - - if len(ret) == 0 { - panic("no return value specified for LINKBalance") - } - - var r0 *assets.Link - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) (*assets.Link, error)); ok { - return rf(ctx, accountAddress, linkAddress) - } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) *assets.Link); ok { - r0 = rf(ctx, accountAddress, linkAddress) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*assets.Link) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ADDR, ADDR) error); ok { - r1 = rf(ctx, accountAddress, linkAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_LINKBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LINKBalance' -type mockRPC_LINKBalance_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// LINKBalance is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress ADDR -// - linkAddress ADDR -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) LINKBalance(ctx interface{}, accountAddress interface{}, linkAddress interface{}) *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("LINKBalance", ctx, accountAddress, linkAddress)} -} - -func (_c *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, accountAddress ADDR, linkAddress ADDR)) *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR), args[2].(ADDR)) - }) - return _c -} - -func (_c *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 *assets.Link, _a1 error) *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, ADDR, ADDR) (*assets.Link, error)) *mockRPC_LINKBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// LatestBlockHeight provides a mock function with given fields: _a0 -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) LatestBlockHeight(_a0 context.Context) (*big.Int, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for LatestBlockHeight") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_LatestBlockHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestBlockHeight' -type mockRPC_LatestBlockHeight_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// LatestBlockHeight is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) LatestBlockHeight(_a0 interface{}) *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("LatestBlockHeight", _a0)} -} - -func (_c *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(_a0 context.Context)) *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 *big.Int, _a1 error) *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (*big.Int, error)) *mockRPC_LatestBlockHeight_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// LatestFinalizedBlock provides a mock function with given fields: ctx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) LatestFinalizedBlock(ctx context.Context) (HEAD, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for LatestFinalizedBlock") - } - - var r0 HEAD - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (HEAD, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) HEAD); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(HEAD) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_LatestFinalizedBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestFinalizedBlock' -type mockRPC_LatestFinalizedBlock_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// LatestFinalizedBlock is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) LatestFinalizedBlock(ctx interface{}) *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("LatestFinalizedBlock", ctx)} -} - -func (_c *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context)) *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 HEAD, _a1 error) *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (HEAD, error)) *mockRPC_LatestFinalizedBlock_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// PendingCallContract provides a mock function with given fields: ctx, msg -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) PendingCallContract(ctx context.Context, msg interface{}) ([]byte, error) { - ret := _m.Called(ctx, msg) - - if len(ret) == 0 { - panic("no return value specified for PendingCallContract") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}) ([]byte, error)); ok { - return rf(ctx, msg) - } - if rf, ok := ret.Get(0).(func(context.Context, interface{}) []byte); ok { - r0 = rf(ctx, msg) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, interface{}) error); ok { - r1 = rf(ctx, msg) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_PendingCallContract_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingCallContract' -type mockRPC_PendingCallContract_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// PendingCallContract is a helper method to define mock.On call -// - ctx context.Context -// - msg interface{} -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) PendingCallContract(ctx interface{}, msg interface{}) *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("PendingCallContract", ctx, msg)} -} - -func (_c *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, msg interface{})) *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{})) - }) - return _c -} - -func (_c *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(rpcErr []byte, extractErr error) *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(rpcErr, extractErr) - return _c -} - -func (_c *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, interface{}) ([]byte, error)) *mockRPC_PendingCallContract_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// PendingSequenceAt provides a mock function with given fields: ctx, addr -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) PendingSequenceAt(ctx context.Context, addr ADDR) (SEQ, error) { - ret := _m.Called(ctx, addr) - - if len(ret) == 0 { - panic("no return value specified for PendingSequenceAt") - } - - var r0 SEQ - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR) (SEQ, error)); ok { - return rf(ctx, addr) - } - if rf, ok := ret.Get(0).(func(context.Context, ADDR) SEQ); ok { - r0 = rf(ctx, addr) - } else { - r0 = ret.Get(0).(SEQ) - } - - if rf, ok := ret.Get(1).(func(context.Context, ADDR) error); ok { - r1 = rf(ctx, addr) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_PendingSequenceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingSequenceAt' -type mockRPC_PendingSequenceAt_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// PendingSequenceAt is a helper method to define mock.On call -// - ctx context.Context -// - addr ADDR -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) PendingSequenceAt(ctx interface{}, addr interface{}) *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("PendingSequenceAt", ctx, addr)} -} - -func (_c *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, addr ADDR)) *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR)) - }) - return _c -} - -func (_c *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 SEQ, _a1 error) *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, ADDR) (SEQ, error)) *mockRPC_PendingSequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SendEmptyTransaction provides a mock function with given fields: ctx, newTxAttempt, seq, gasLimit, fee, fromAddress -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SendEmptyTransaction(ctx context.Context, newTxAttempt func(SEQ, uint32, FEE, ADDR) (interface{}, error), seq SEQ, gasLimit uint32, fee FEE, fromAddress ADDR) (string, error) { - ret := _m.Called(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - - if len(ret) == 0 { - panic("no return value specified for SendEmptyTransaction") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) (string, error)); ok { - return rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - } - if rf, ok := ret.Get(0).(func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) string); ok { - r0 = rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) error); ok { - r1 = rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_SendEmptyTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendEmptyTransaction' -type mockRPC_SendEmptyTransaction_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SendEmptyTransaction is a helper method to define mock.On call -// - ctx context.Context -// - newTxAttempt func(SEQ , uint32 , FEE , ADDR)(interface{} , error) -// - seq SEQ -// - gasLimit uint32 -// - fee FEE -// - fromAddress ADDR -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SendEmptyTransaction(ctx interface{}, newTxAttempt interface{}, seq interface{}, gasLimit interface{}, fee interface{}, fromAddress interface{}) *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SendEmptyTransaction", ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)} -} - -func (_c *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, newTxAttempt func(SEQ, uint32, FEE, ADDR) (interface{}, error), seq SEQ, gasLimit uint32, fee FEE, fromAddress ADDR)) *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(func(SEQ, uint32, FEE, ADDR) (interface{}, error)), args[2].(SEQ), args[3].(uint32), args[4].(FEE), args[5].(ADDR)) - }) - return _c -} - -func (_c *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(txhash string, err error) *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(txhash, err) - return _c -} - -func (_c *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, func(SEQ, uint32, FEE, ADDR) (interface{}, error), SEQ, uint32, FEE, ADDR) (string, error)) *mockRPC_SendEmptyTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SendTransaction provides a mock function with given fields: ctx, tx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SendTransaction(ctx context.Context, tx TX) error { - ret := _m.Called(ctx, tx) - - if len(ret) == 0 { - panic("no return value specified for SendTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, TX) error); ok { - r0 = rf(ctx, tx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPC_SendTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendTransaction' -type mockRPC_SendTransaction_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SendTransaction is a helper method to define mock.On call -// - ctx context.Context -// - tx TX -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SendTransaction(ctx interface{}, tx interface{}) *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SendTransaction", ctx, tx)} -} - -func (_c *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, tx TX)) *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(TX)) - }) - return _c -} - -func (_c *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 error) *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, TX) error) *mockRPC_SendTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SequenceAt provides a mock function with given fields: ctx, accountAddress, blockNumber -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SequenceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (SEQ, error) { - ret := _m.Called(ctx, accountAddress, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for SequenceAt") - } - - var r0 SEQ - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) (SEQ, error)); ok { - return rf(ctx, accountAddress, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, *big.Int) SEQ); ok { - r0 = rf(ctx, accountAddress, blockNumber) - } else { - r0 = ret.Get(0).(SEQ) - } - - if rf, ok := ret.Get(1).(func(context.Context, ADDR, *big.Int) error); ok { - r1 = rf(ctx, accountAddress, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_SequenceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SequenceAt' -type mockRPC_SequenceAt_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SequenceAt is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress ADDR -// - blockNumber *big.Int -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SequenceAt(ctx interface{}, accountAddress interface{}, blockNumber interface{}) *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SequenceAt", ctx, accountAddress, blockNumber)} -} - -func (_c *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, accountAddress ADDR, blockNumber *big.Int)) *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR), args[2].(*big.Int)) - }) - return _c -} - -func (_c *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 SEQ, _a1 error) *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, ADDR, *big.Int) (SEQ, error)) *mockRPC_SequenceAt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SetAliveLoopSub provides a mock function with given fields: _a0 -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SetAliveLoopSub(_a0 types.Subscription) { - _m.Called(_a0) -} - -// mockRPC_SetAliveLoopSub_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAliveLoopSub' -type mockRPC_SetAliveLoopSub_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SetAliveLoopSub is a helper method to define mock.On call -// - _a0 types.Subscription -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SetAliveLoopSub(_a0 interface{}) *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SetAliveLoopSub", _a0)} -} - -func (_c *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(_a0 types.Subscription)) *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Subscription)) - }) - return _c -} - -func (_c *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return() *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return() - return _c -} - -func (_c *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(types.Subscription)) *mockRPC_SetAliveLoopSub_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SimulateTransaction provides a mock function with given fields: ctx, tx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SimulateTransaction(ctx context.Context, tx TX) error { - ret := _m.Called(ctx, tx) - - if len(ret) == 0 { - panic("no return value specified for SimulateTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, TX) error); ok { - r0 = rf(ctx, tx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// mockRPC_SimulateTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SimulateTransaction' -type mockRPC_SimulateTransaction_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SimulateTransaction is a helper method to define mock.On call -// - ctx context.Context -// - tx TX -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SimulateTransaction(ctx interface{}, tx interface{}) *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SimulateTransaction", ctx, tx)} -} - -func (_c *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, tx TX)) *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(TX)) - }) - return _c -} - -func (_c *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 error) *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, TX) error) *mockRPC_SimulateTransaction_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SubscribeNewHead provides a mock function with given fields: ctx, channel -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (types.Subscription, error) { - ret := _m.Called(ctx, channel) - - if len(ret) == 0 { - panic("no return value specified for SubscribeNewHead") - } - - var r0 types.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) (types.Subscription, error)); ok { - return rf(ctx, channel) - } - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) types.Subscription); ok { - r0 = rf(ctx, channel) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD) error); ok { - r1 = rf(ctx, channel) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_SubscribeNewHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeNewHead' -type mockRPC_SubscribeNewHead_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SubscribeNewHead is a helper method to define mock.On call -// - ctx context.Context -// - channel chan<- HEAD -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribeNewHead(ctx interface{}, channel interface{}) *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SubscribeNewHead", ctx, channel)} -} - -func (_c *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, channel chan<- HEAD)) *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(chan<- HEAD)) - }) - return _c -} - -func (_c *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(s types.Subscription, err error) *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(s, err) - return _c -} - -func (_c *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, chan<- HEAD) (types.Subscription, error)) *mockRPC_SubscribeNewHead_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SubscribeToFinalizedHeads provides a mock function with given fields: _a0 -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribeToFinalizedHeads(_a0 context.Context) (<-chan HEAD, types.Subscription, error) { - ret := _m.Called(_a0) - - 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(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) <-chan HEAD); ok { - r0 = rf(_a0) - } 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(_a0) - } 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(_a0) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// mockRPC_SubscribeToFinalizedHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToFinalizedHeads' -type mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SubscribeToFinalizedHeads is a helper method to define mock.On call -// - _a0 context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribeToFinalizedHeads(_a0 interface{}) *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SubscribeToFinalizedHeads", _a0)} -} - -func (_c *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(_a0 context.Context)) *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 <-chan HEAD, _a1 types.Subscription, _a2 error) *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1, _a2) - return _c -} - -func (_c *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (<-chan HEAD, types.Subscription, error)) *mockRPC_SubscribeToFinalizedHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SubscribeToHeads provides a mock function with given fields: ctx -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) 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 -} - -// mockRPC_SubscribeToHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToHeads' -type mockRPC_SubscribeToHeads_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SubscribeToHeads is a helper method to define mock.On call -// - ctx context.Context -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribeToHeads(ctx interface{}) *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SubscribeToHeads", ctx)} -} - -func (_c *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context)) *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(ch <-chan HEAD, sub types.Subscription, err error) *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(ch, sub, err) - return _c -} - -func (_c *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context) (<-chan HEAD, types.Subscription, error)) *mockRPC_SubscribeToHeads_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// SubscribersCount provides a mock function with given fields: -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribersCount() int32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for SubscribersCount") - } - - var r0 int32 - if rf, ok := ret.Get(0).(func() int32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int32) - } - - return r0 -} - -// mockRPC_SubscribersCount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribersCount' -type mockRPC_SubscribersCount_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// SubscribersCount is a helper method to define mock.On call -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribersCount() *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("SubscribersCount")} -} - -func (_c *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func()) *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 int32) *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0) - return _c -} - -func (_c *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func() int32) *mockRPC_SubscribersCount_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// TokenBalance provides a mock function with given fields: ctx, accountAddress, tokenAddress -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) TokenBalance(ctx context.Context, accountAddress ADDR, tokenAddress ADDR) (*big.Int, error) { - ret := _m.Called(ctx, accountAddress, tokenAddress) - - if len(ret) == 0 { - panic("no return value specified for TokenBalance") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) (*big.Int, error)); ok { - return rf(ctx, accountAddress, tokenAddress) - } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, ADDR) *big.Int); ok { - r0 = rf(ctx, accountAddress, tokenAddress) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ADDR, ADDR) error); ok { - r1 = rf(ctx, accountAddress, tokenAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_TokenBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TokenBalance' -type mockRPC_TokenBalance_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// TokenBalance is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress ADDR -// - tokenAddress ADDR -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) TokenBalance(ctx interface{}, accountAddress interface{}, tokenAddress interface{}) *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("TokenBalance", ctx, accountAddress, tokenAddress)} -} - -func (_c *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, accountAddress ADDR, tokenAddress ADDR)) *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR), args[2].(ADDR)) - }) - return _c -} - -func (_c *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 *big.Int, _a1 error) *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, ADDR, ADDR) (*big.Int, error)) *mockRPC_TokenBalance_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// TransactionByHash provides a mock function with given fields: ctx, txHash -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) TransactionByHash(ctx context.Context, txHash TX_HASH) (TX, error) { - ret := _m.Called(ctx, txHash) - - if len(ret) == 0 { - panic("no return value specified for TransactionByHash") - } - - var r0 TX - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) (TX, error)); ok { - return rf(ctx, txHash) - } - if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) TX); ok { - r0 = rf(ctx, txHash) - } else { - r0 = ret.Get(0).(TX) - } - - if rf, ok := ret.Get(1).(func(context.Context, TX_HASH) error); ok { - r1 = rf(ctx, txHash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_TransactionByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionByHash' -type mockRPC_TransactionByHash_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// TransactionByHash is a helper method to define mock.On call -// - ctx context.Context -// - txHash TX_HASH -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) TransactionByHash(ctx interface{}, txHash interface{}) *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("TransactionByHash", ctx, txHash)} -} - -func (_c *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, txHash TX_HASH)) *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(TX_HASH)) - }) - return _c -} - -func (_c *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 TX, _a1 error) *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, TX_HASH) (TX, error)) *mockRPC_TransactionByHash_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// TransactionReceipt provides a mock function with given fields: ctx, txHash -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) TransactionReceipt(ctx context.Context, txHash TX_HASH) (TX_RECEIPT, error) { - ret := _m.Called(ctx, txHash) - - if len(ret) == 0 { - panic("no return value specified for TransactionReceipt") - } - - var r0 TX_RECEIPT - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) (TX_RECEIPT, error)); ok { - return rf(ctx, txHash) - } - if rf, ok := ret.Get(0).(func(context.Context, TX_HASH) TX_RECEIPT); ok { - r0 = rf(ctx, txHash) - } else { - r0 = ret.Get(0).(TX_RECEIPT) - } - - if rf, ok := ret.Get(1).(func(context.Context, TX_HASH) error); ok { - r1 = rf(ctx, txHash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// mockRPC_TransactionReceipt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionReceipt' -type mockRPC_TransactionReceipt_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// TransactionReceipt is a helper method to define mock.On call -// - ctx context.Context -// - txHash TX_HASH -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) TransactionReceipt(ctx interface{}, txHash interface{}) *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("TransactionReceipt", ctx, txHash)} -} - -func (_c *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func(ctx context.Context, txHash TX_HASH)) *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(TX_HASH)) - }) - return _c -} - -func (_c *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return(_a0 TX_RECEIPT, _a1 error) *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func(context.Context, TX_HASH) (TX_RECEIPT, error)) *mockRPC_TransactionReceipt_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// UnsubscribeAllExceptAliveLoop provides a mock function with given fields: -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) UnsubscribeAllExceptAliveLoop() { - _m.Called() -} - -// mockRPC_UnsubscribeAllExceptAliveLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscribeAllExceptAliveLoop' -type mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}] struct { - *mock.Call -} - -// UnsubscribeAllExceptAliveLoop is a helper method to define mock.On call -func (_e *mockRPC_Expecter[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) UnsubscribeAllExceptAliveLoop() *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - return &mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{Call: _e.mock.On("UnsubscribeAllExceptAliveLoop")} -} - -func (_c *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Run(run func()) *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Return() *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return() - return _c -} - -func (_c *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) RunAndReturn(run func()) *mockRPC_UnsubscribeAllExceptAliveLoop_Call[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - _c.Call.Return(run) - return _c -} - -// newMockRPC creates a new instance of mockRPC. 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 newMockRPC[CHAIN_ID types.ID, SEQ types.Sequence, ADDR types.Hashable, BLOCK_HASH types.Hashable, TX interface{}, TX_HASH types.Hashable, EVENT interface{}, EVENT_OPS interface{}, TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], FEE feetypes.Fee, HEAD types.Head[BLOCK_HASH], BATCH_ELEM interface{}](t interface { - mock.TestingT - Cleanup(func()) -}) *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM] { - mock := &mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]{} - 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 index a9c9f23b141..fa65a84551b 100644 --- a/common/client/mock_send_only_client_test.go +++ b/common/client/mock_send_only_client_test.go @@ -110,17 +110,17 @@ func (_c *mockSendOnlyClient_Close_Call[CHAIN_ID]) RunAndReturn(run func()) *moc return _c } -// DialHTTP provides a mock function with given fields: -func (_m *mockSendOnlyClient[CHAIN_ID]) DialHTTP() error { - ret := _m.Called() +// 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 DialHTTP") + panic("no return value specified for Dial") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -128,29 +128,30 @@ func (_m *mockSendOnlyClient[CHAIN_ID]) DialHTTP() error { return r0 } -// mockSendOnlyClient_DialHTTP_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DialHTTP' -type mockSendOnlyClient_DialHTTP_Call[CHAIN_ID types.ID] struct { +// 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 } -// DialHTTP is a helper method to define mock.On call -func (_e *mockSendOnlyClient_Expecter[CHAIN_ID]) DialHTTP() *mockSendOnlyClient_DialHTTP_Call[CHAIN_ID] { - return &mockSendOnlyClient_DialHTTP_Call[CHAIN_ID]{Call: _e.mock.On("DialHTTP")} +// 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_DialHTTP_Call[CHAIN_ID]) Run(run func()) *mockSendOnlyClient_DialHTTP_Call[CHAIN_ID] { +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() + run(args[0].(context.Context)) }) return _c } -func (_c *mockSendOnlyClient_DialHTTP_Call[CHAIN_ID]) Return(_a0 error) *mockSendOnlyClient_DialHTTP_Call[CHAIN_ID] { +func (_c *mockSendOnlyClient_Dial_Call[CHAIN_ID]) Return(_a0 error) *mockSendOnlyClient_Dial_Call[CHAIN_ID] { _c.Call.Return(_a0) return _c } -func (_c *mockSendOnlyClient_DialHTTP_Call[CHAIN_ID]) RunAndReturn(run func() error) *mockSendOnlyClient_DialHTTP_Call[CHAIN_ID] { +func (_c *mockSendOnlyClient_Dial_Call[CHAIN_ID]) RunAndReturn(run func(context.Context) error) *mockSendOnlyClient_Dial_Call[CHAIN_ID] { _c.Call.Return(run) return _c } diff --git a/common/client/mock_send_only_node_test.go b/common/client/mock_send_only_node_test.go index 53077cd49db..256faea62bc 100644 --- a/common/client/mock_send_only_node_test.go +++ b/common/client/mock_send_only_node_test.go @@ -10,11 +10,11 @@ import ( ) // mockSendOnlyNode is an autogenerated mock type for the SendOnlyNode type -type mockSendOnlyNode[CHAIN_ID types.ID, RPC sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode[CHAIN_ID types.ID, RPC interface{}] struct { mock.Mock } -type mockSendOnlyNode_Expecter[CHAIN_ID types.ID, RPC sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_Expecter[CHAIN_ID types.ID, RPC interface{}] struct { mock *mock.Mock } @@ -41,7 +41,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Close() error { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_Close_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -86,7 +86,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_ConfiguredChainID_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -131,7 +131,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Name() string { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_Name_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -176,7 +176,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) RPC() RPC { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_RPC_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -221,7 +221,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) Start(_a0 context.Context) error { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_Start_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -267,7 +267,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) State() nodeState { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_State_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -312,7 +312,7 @@ func (_m *mockSendOnlyNode[CHAIN_ID, RPC]) String() string { } // 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 sendOnlyClient[CHAIN_ID]] struct { +type mockSendOnlyNode_String_Call[CHAIN_ID types.ID, RPC interface{}] struct { *mock.Call } @@ -340,7 +340,7 @@ func (_c *mockSendOnlyNode_String_Call[CHAIN_ID, RPC]) RunAndReturn(run func() s // 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 sendOnlyClient[CHAIN_ID]](t interface { +func newMockSendOnlyNode[CHAIN_ID types.ID, RPC interface{}](t interface { mock.TestingT Cleanup(func()) }) *mockSendOnlyNode[CHAIN_ID, RPC] { diff --git a/common/client/multi_node.go b/common/client/multi_node.go index c9250a1d620..9594743f6bd 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -2,21 +2,17 @@ package client import ( "context" + "errors" "fmt" - "math" "math/big" - "slices" "sync" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/smartcontractkit/chainlink-common/pkg/assets" "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/types" ) @@ -26,11 +22,6 @@ var ( Name: "multi_node_states", Help: "The number of RPC nodes currently in the given state for the given chain", }, []string{"network", "chainId", "state"}) - // 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"}) ErroringNodeError = fmt.Errorf("no live nodes available") ) @@ -38,129 +29,57 @@ var ( // It also handles multiple node RPC connections simultaneously. type MultiNode[ CHAIN_ID types.ID, - SEQ types.Sequence, - ADDR types.Hashable, - BLOCK_HASH types.Hashable, - TX any, - TX_HASH types.Hashable, - EVENT any, - EVENT_OPS any, - TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], - FEE feetypes.Fee, - HEAD types.Head[BLOCK_HASH], - RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM], - BATCH_ELEM any, -] interface { - clientAPI[ - CHAIN_ID, - SEQ, - ADDR, - BLOCK_HASH, - TX, - TX_HASH, - EVENT, - EVENT_OPS, - TX_RECEIPT, - FEE, - HEAD, - BATCH_ELEM, - ] - Close() error - NodeStates() map[string]string - SelectNodeRPC() (RPC_CLIENT, error) - - BatchCallContextAll(ctx context.Context, b []BATCH_ELEM) error - ConfiguredChainID() CHAIN_ID -} - -type multiNode[ - CHAIN_ID types.ID, - SEQ types.Sequence, - ADDR types.Hashable, - BLOCK_HASH types.Hashable, - TX any, - TX_HASH types.Hashable, - EVENT any, - EVENT_OPS any, - TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], - FEE feetypes.Fee, - HEAD types.Head[BLOCK_HASH], - RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM], - BATCH_ELEM any, + RPC any, ] struct { services.StateMachine - nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT] - sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT] + primaryNodes []Node[CHAIN_ID, RPC] + sendOnlyNodes []SendOnlyNode[CHAIN_ID, RPC] chainID CHAIN_ID lggr logger.SugaredLogger selectionMode string - noNewHeadsThreshold time.Duration - nodeSelector NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] + nodeSelector NodeSelector[CHAIN_ID, RPC] leaseDuration time.Duration leaseTicker *time.Ticker chainFamily string reportInterval time.Duration deathDeclarationDelay time.Duration - sendTxSoftTimeout time.Duration // defines max waiting time from first response til responses evaluation activeMu sync.RWMutex - activeNode Node[CHAIN_ID, HEAD, RPC_CLIENT] + activeNode Node[CHAIN_ID, RPC] chStop services.StopChan wg sync.WaitGroup - - classifySendTxError func(tx TX, err error) SendTxReturnCode } func NewMultiNode[ CHAIN_ID types.ID, - SEQ types.Sequence, - ADDR types.Hashable, - BLOCK_HASH types.Hashable, - TX any, - TX_HASH types.Hashable, - EVENT any, - EVENT_OPS any, - TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], - FEE feetypes.Fee, - HEAD types.Head[BLOCK_HASH], - RPC_CLIENT RPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM], - BATCH_ELEM any, + RPC any, ]( lggr logger.Logger, - selectionMode string, - leaseDuration time.Duration, - noNewHeadsThreshold time.Duration, - nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT], - sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT], - chainID CHAIN_ID, - chainFamily string, - classifySendTxError func(tx TX, err error) SendTxReturnCode, - sendTxSoftTimeout time.Duration, + 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, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM] { - nodeSelector := newNodeSelector(selectionMode, nodes) +) *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 - if sendTxSoftTimeout == 0 { - sendTxSoftTimeout = QueryTimeout / 2 - } - c := &multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]{ - nodes: nodes, - sendonlys: sendonlys, + c := &MultiNode[CHAIN_ID, RPC]{ + primaryNodes: primaryNodes, + sendOnlyNodes: sendOnlyNodes, chainID: chainID, lggr: logger.Sugared(lggr).Named("MultiNode").With("chainID", chainID.String()), selectionMode: selectionMode, - noNewHeadsThreshold: noNewHeadsThreshold, nodeSelector: nodeSelector, chStop: make(services.StopChan), leaseDuration: leaseDuration, chainFamily: chainFamily, - classifySendTxError: classifySendTxError, reportInterval: reportInterval, deathDeclarationDelay: deathDeclarationDelay, - sendTxSoftTimeout: sendTxSoftTimeout, } c.lggr.Debugf("The MultiNode is configured to use NodeSelectionMode: %s", selectionMode) @@ -168,17 +87,74 @@ func NewMultiNode[ return c } -// Dial starts every node in the pool +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 { + var err error + ok := c.IfNotStopped(func() { + ctx, _ = c.chStop.Ctx(ctx) + + callsCompleted := 0 + for _, n := range c.primaryNodes { + select { + case <-ctx.Done(): + err = ctx.Err() + return + default: + if n.State() != nodeStateAlive { + continue + } + do(ctx, n.RPC(), false) + callsCompleted++ + } + } + if callsCompleted == 0 { + err = ErroringNodeError + } + + for _, n := range c.sendOnlyNodes { + select { + case <-ctx.Done(): + err = ctx.Err() + return + default: + if n.State() != nodeStateAlive { + continue + } + do(ctx, n.RPC(), true) + } + } + }) + if !ok { + return errors.New("MultiNode is stopped") + } + return err +} + +func (c *MultiNode[CHAIN_ID, RPC]) NodeStates() map[string]string { + states := map[string]string{} + for _, n := range c.primaryNodes { + states[n.String()] = n.State().String() + } + for _, n := range c.sendOnlyNodes { + states[n.String()] = 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, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) Dial(ctx context.Context) error { +func (c *MultiNode[CHAIN_ID, RPC]) Start(ctx context.Context) error { return c.StartOnce("MultiNode", func() (merr error) { - if len(c.nodes) == 0 { + 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.nodes { + 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())) } @@ -188,7 +164,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return err } } - for _, s := range c.sendonlys { + 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())) } @@ -212,18 +188,18 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } // Close tears down the MultiNode and closes all nodes -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) Close() error { +func (c *MultiNode[CHAIN_ID, RPC]) Close() error { return c.StopOnce("MultiNode", func() error { close(c.chStop) c.wg.Wait() - return services.CloseAll(services.MultiCloser(c.nodes), services.MultiCloser(c.sendonlys)) + return services.CloseAll(services.MultiCloser(c.primaryNodes), services.MultiCloser(c.sendOnlyNodes)) }) } -// SelectNodeRPC returns an RPC of an active node. If there are no active nodes it returns an error. +// 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, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SelectNodeRPC() (rpc RPC_CLIENT, err error) { +func (c *MultiNode[CHAIN_ID, RPC]) SelectRPC() (rpc RPC, err error) { n, err := c.selectNode() if err != nil { return rpc, err @@ -232,7 +208,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } // selectNode returns the active Node, if it is still nodeStateAlive, otherwise it selects a new one from the NodeSelector. -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) selectNode() (node Node[CHAIN_ID, HEAD, RPC_CLIENT], err error) { +func (c *MultiNode[CHAIN_ID, RPC]) selectNode() (node Node[CHAIN_ID, RPC], err error) { c.activeMu.RLock() node = c.activeNode c.activeMu.RUnlock() @@ -266,12 +242,12 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP // 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, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) LatestChainInfo() (int, ChainInfo) { +func (c *MultiNode[CHAIN_ID, RPC]) LatestChainInfo() (int, ChainInfo) { var nLiveNodes int ch := ChainInfo{ TotalDifficulty: big.NewInt(0), } - for _, n := range c.nodes { + for _, n := range c.primaryNodes { if s, nodeChainInfo := n.StateAndLatest(); s == nodeStateAlive { nLiveNodes++ ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) @@ -283,11 +259,11 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } // HighestUserObservations - returns highest ChainInfo ever observed by any user of the MultiNode -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) HighestUserObservations() ChainInfo { +func (c *MultiNode[CHAIN_ID, RPC]) HighestUserObservations() ChainInfo { ch := ChainInfo{ TotalDifficulty: big.NewInt(0), } - for _, n := range c.nodes { + for _, n := range c.primaryNodes { nodeChainInfo := n.HighestUserObservations() ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) @@ -296,12 +272,12 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return ch } -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) checkLease() { +func (c *MultiNode[CHAIN_ID, RPC]) checkLease() { bestNode := c.nodeSelector.Select() - for _, n := range c.nodes { + 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 && n.SubscribersCount() > 1 { + if n.State() == nodeStateAlive && n != bestNode { c.lggr.Infof("Switching to best node from %q to %q", n.String(), bestNode.String()) n.UnsubscribeAllExceptAliveLoop() } @@ -317,7 +293,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } } -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) checkLeaseLoop() { +func (c *MultiNode[CHAIN_ID, RPC]) checkLeaseLoop() { defer c.wg.Done() c.leaseTicker = time.NewTicker(c.leaseDuration) defer c.leaseTicker.Stop() @@ -332,11 +308,11 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } } -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) runLoop() { +func (c *MultiNode[CHAIN_ID, RPC]) runLoop() { defer c.wg.Done() - nodeStates := make([]nodeWithState, len(c.nodes)) - for i, n := range c.nodes { + nodeStates := make([]nodeWithState, len(c.primaryNodes)) + for i, n := range c.primaryNodes { nodeStates[i] = nodeWithState{ Node: n.String(), State: n.State().String(), @@ -365,11 +341,11 @@ type nodeWithState struct { DeadSince *time.Time } -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) report(nodesStateInfo []nodeWithState) { +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.nodes { + for i, n := range c.primaryNodes { state := n.State() counts[state]++ nodesStateInfo[i].State = state.String() @@ -391,7 +367,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP PromMultiNodeRPCNodeStates.WithLabelValues(c.chainFamily, c.chainID.String(), state.String()).Set(float64(count)) } - total := len(c.nodes) + 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 { @@ -402,463 +378,3 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP c.lggr.Errorw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) } } - -// ClientAPI methods -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) BalanceAt(ctx context.Context, account ADDR, blockNumber *big.Int) (*big.Int, error) { - n, err := c.selectNode() - if err != nil { - return nil, err - } - return n.RPC().BalanceAt(ctx, account, blockNumber) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) BatchCallContext(ctx context.Context, b []BATCH_ELEM) error { - n, err := c.selectNode() - if err != nil { - return err - } - return n.RPC().BatchCallContext(ctx, b) -} - -// BatchCallContextAll calls BatchCallContext for every single node including -// sendonlys. -// CAUTION: This should only be used for mass re-transmitting transactions, it -// might have unexpected effects to use it for anything else. -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) BatchCallContextAll(ctx context.Context, b []BATCH_ELEM) error { - var wg sync.WaitGroup - defer wg.Wait() - - main, selectionErr := c.selectNode() - var all []SendOnlyNode[CHAIN_ID, RPC_CLIENT] - for _, n := range c.nodes { - all = append(all, n) - } - all = append(all, c.sendonlys...) - for _, n := range all { - if n == main { - // main node is used at the end for the return value - continue - } - - if n.State() != nodeStateAlive { - continue - } - // Parallel call made to all other nodes with ignored return value - wg.Add(1) - go func(n SendOnlyNode[CHAIN_ID, RPC_CLIENT]) { - defer wg.Done() - err := n.RPC().BatchCallContext(ctx, b) - if err != nil { - c.lggr.Debugw("Secondary node BatchCallContext failed", "err", err) - } else { - c.lggr.Trace("Secondary node BatchCallContext success") - } - }(n) - } - - if selectionErr != nil { - return selectionErr - } - return main.RPC().BatchCallContext(ctx, b) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) BlockByHash(ctx context.Context, hash BLOCK_HASH) (h HEAD, err error) { - n, err := c.selectNode() - if err != nil { - return h, err - } - return n.RPC().BlockByHash(ctx, hash) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) BlockByNumber(ctx context.Context, number *big.Int) (h HEAD, err error) { - n, err := c.selectNode() - if err != nil { - return h, err - } - return n.RPC().BlockByNumber(ctx, number) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - n, err := c.selectNode() - if err != nil { - return err - } - return n.RPC().CallContext(ctx, result, method, args...) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) CallContract( - ctx context.Context, - attempt interface{}, - blockNumber *big.Int, -) (rpcErr []byte, extractErr error) { - n, err := c.selectNode() - if err != nil { - return rpcErr, err - } - return n.RPC().CallContract(ctx, attempt, blockNumber) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) PendingCallContract( - ctx context.Context, - attempt interface{}, -) (rpcErr []byte, extractErr error) { - n, err := c.selectNode() - if err != nil { - return rpcErr, err - } - return n.RPC().PendingCallContract(ctx, attempt) -} - -// ChainID makes a direct RPC call. In most cases it should be better to use the configured chain id instead by -// calling ConfiguredChainID. -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) ChainID(ctx context.Context) (id CHAIN_ID, err error) { - n, err := c.selectNode() - if err != nil { - return id, err - } - return n.RPC().ChainID(ctx) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) (code []byte, err error) { - n, err := c.selectNode() - if err != nil { - return code, err - } - return n.RPC().CodeAt(ctx, account, blockNumber) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) ConfiguredChainID() CHAIN_ID { - return c.chainID -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) EstimateGas(ctx context.Context, call any) (gas uint64, err error) { - n, err := c.selectNode() - if err != nil { - return gas, err - } - return n.RPC().EstimateGas(ctx, call) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) FilterEvents(ctx context.Context, query EVENT_OPS) (e []EVENT, err error) { - n, err := c.selectNode() - if err != nil { - return e, err - } - return n.RPC().FilterEvents(ctx, query) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) LatestBlockHeight(ctx context.Context) (h *big.Int, err error) { - n, err := c.selectNode() - if err != nil { - return h, err - } - return n.RPC().LatestBlockHeight(ctx) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) LINKBalance(ctx context.Context, accountAddress ADDR, linkAddress ADDR) (b *assets.Link, err error) { - n, err := c.selectNode() - if err != nil { - return b, err - } - return n.RPC().LINKBalance(ctx, accountAddress, linkAddress) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) NodeStates() (states map[string]string) { - states = make(map[string]string) - for _, n := range c.nodes { - states[n.Name()] = n.State().String() - } - for _, s := range c.sendonlys { - states[s.Name()] = s.State().String() - } - return -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) PendingSequenceAt(ctx context.Context, addr ADDR) (s SEQ, err error) { - n, err := c.selectNode() - if err != nil { - return s, err - } - return n.RPC().PendingSequenceAt(ctx, addr) -} - -type sendTxErrors map[SendTxReturnCode][]error - -// String - returns string representation of the errors map. Required by logger to properly represent the value -func (errs sendTxErrors) String() string { - return fmt.Sprint(map[SendTxReturnCode][]error(errs)) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SendEmptyTransaction( - ctx context.Context, - newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt any, err error), - seq SEQ, - gasLimit uint32, - fee FEE, - fromAddress ADDR, -) (txhash string, err error) { - n, err := c.selectNode() - if err != nil { - return txhash, err - } - return n.RPC().SendEmptyTransaction(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) -} - -type sendTxResult struct { - Err error - ResultCode SendTxReturnCode -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) broadcastTxAsync(ctx context.Context, - n SendOnlyNode[CHAIN_ID, RPC_CLIENT], tx TX) sendTxResult { - txErr := n.RPC().SendTransaction(ctx, tx) - c.lggr.Debugw("Node sent transaction", "name", n.String(), "tx", tx, "err", txErr) - resultCode := c.classifySendTxError(tx, txErr) - if !slices.Contains(sendTxSuccessfulCodes, resultCode) { - c.lggr.Warnw("RPC returned error", "name", n.String(), "tx", tx, "err", txErr) - } - - return sendTxResult{Err: txErr, ResultCode: resultCode} -} - -// collectTxResults - refer to SendTransaction comment for implementation details, -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan sendTxResult) error { - if healthyNodesNum == 0 { - return ErroringNodeError - } - // combine context and stop channel to ensure we stop, when signal received - ctx, cancel := c.chStop.Ctx(ctx) - defer cancel() - requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) - errorsByCode := sendTxErrors{} - var softTimeoutChan <-chan time.Time - var resultsCount int -loop: - for { - select { - case <-ctx.Done(): - c.lggr.Debugw("Failed to collect of the results before context was done", "tx", tx, "errorsByCode", errorsByCode) - return ctx.Err() - case result := <-txResults: - errorsByCode[result.ResultCode] = append(errorsByCode[result.ResultCode], result.Err) - resultsCount++ - if slices.Contains(sendTxSuccessfulCodes, result.ResultCode) || resultsCount >= requiredResults { - break loop - } - case <-softTimeoutChan: - c.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(c.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) - return result -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) reportSendTxAnomalies(tx TX, txResults <-chan sendTxResult) { - defer c.wg.Done() - resultsByCode := sendTxErrors{} - // txResults eventually will be closed - for txResult := range txResults { - resultsByCode[txResult.ResultCode] = append(resultsByCode[txResult.ResultCode], txResult.Err) - } - - _, criticalErr := aggregateTxResults(resultsByCode) - if criticalErr != nil { - c.lggr.Criticalw("observed invariant violation on SendTransaction", "tx", tx, "resultsByCode", resultsByCode, "err", criticalErr) - c.SvcErrBuffer.Append(criticalErr) - PromMultiNodeInvariantViolations.WithLabelValues(c.chainFamily, c.chainID.String(), criticalErr.Error()).Inc() - } -} - -func aggregateTxResults(resultsByCode sendTxErrors) (txResult error, err 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], fmt.Errorf(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 _, result := range resultsByCode { - return result[0], nil - } - - err = fmt.Errorf("expected at least one response on SendTransaction") - return err, err -} - -const sendTxQuorum = 0.7 - -// SendTransaction - broadcasts transaction to all the send-only and primary nodes regardless of their health. -// 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 (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SendTransaction(ctx context.Context, tx TX) error { - if len(c.nodes) == 0 { - return ErroringNodeError - } - - healthyNodesNum := 0 - txResults := make(chan sendTxResult, len(c.nodes)) - // Must wrap inside IfNotStopped to avoid waitgroup racing with Close - ok := c.IfNotStopped(func() { - // fire-n-forget, as sendOnlyNodes can not be trusted with result reporting - for _, n := range c.sendonlys { - if n.State() != nodeStateAlive { - continue - } - c.wg.Add(1) - go func(n SendOnlyNode[CHAIN_ID, RPC_CLIENT]) { - defer c.wg.Done() - c.broadcastTxAsync(ctx, n, tx) - }(n) - } - - var primaryBroadcastWg sync.WaitGroup - txResultsToReport := make(chan sendTxResult, len(c.nodes)) - for _, n := range c.nodes { - if n.State() != nodeStateAlive { - continue - } - - healthyNodesNum++ - primaryBroadcastWg.Add(1) - go func(n SendOnlyNode[CHAIN_ID, RPC_CLIENT]) { - defer primaryBroadcastWg.Done() - result := c.broadcastTxAsync(ctx, n, tx) - // both channels are sufficiently buffered, so we won't be locked - txResultsToReport <- result - txResults <- result - }(n) - } - - c.wg.Add(1) - go func() { - // wait for primary nodes to finish the broadcast before closing the channel - primaryBroadcastWg.Wait() - close(txResultsToReport) - close(txResults) - c.wg.Done() - }() - - c.wg.Add(1) - go c.reportSendTxAnomalies(tx, txResultsToReport) - }) - if !ok { - return fmt.Errorf("aborted while broadcasting tx - multiNode is stopped: %w", context.Canceled) - } - - return c.collectTxResults(ctx, tx, healthyNodesNum, txResults) -} - -// findFirstIn - returns first existing 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 v V - return v, false -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SequenceAt(ctx context.Context, account ADDR, blockNumber *big.Int) (s SEQ, err error) { - n, err := c.selectNode() - if err != nil { - return s, err - } - return n.RPC().SequenceAt(ctx, account, blockNumber) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SimulateTransaction(ctx context.Context, tx TX) error { - n, err := c.selectNode() - if err != nil { - return err - } - return n.RPC().SimulateTransaction(ctx, tx) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (s types.Subscription, err error) { - n, err := c.selectNode() - if err != nil { - return s, err - } - return n.RPC().SubscribeNewHead(ctx, channel) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SubscribeToHeads(ctx context.Context) (ch <-chan HEAD, sub types.Subscription, err error) { - n, err := c.selectNode() - if err != nil { - return nil, nil, err - } - return n.RPC().SubscribeToHeads(ctx) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) TokenBalance(ctx context.Context, account ADDR, tokenAddr ADDR) (b *big.Int, err error) { - n, err := c.selectNode() - if err != nil { - return b, err - } - return n.RPC().TokenBalance(ctx, account, tokenAddr) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) TransactionByHash(ctx context.Context, txHash TX_HASH) (tx TX, err error) { - n, err := c.selectNode() - if err != nil { - return tx, err - } - return n.RPC().TransactionByHash(ctx, txHash) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) TransactionReceipt(ctx context.Context, txHash TX_HASH) (txr TX_RECEIPT, err error) { - n, err := c.selectNode() - if err != nil { - return txr, err - } - return n.RPC().TransactionReceipt(ctx, txHash) -} - -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) LatestFinalizedBlock(ctx context.Context) (head HEAD, err error) { - n, err := c.selectNode() - if err != nil { - return head, err - } - - return n.RPC().LatestFinalizedBlock(ctx) -} diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index ffef0c29d56..57b849a3c0a 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -1,44 +1,38 @@ package client import ( - "context" - "errors" "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/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/common/types" ) -type multiNodeRPCClient RPC[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, - types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], any] +type multiNodeRPCClient RPCClient[types.ID, types.Head[Hashable]] type testMultiNode struct { - *multiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, - types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any] + *MultiNode[types.ID, multiNodeRPCClient] } type multiNodeOpts struct { logger logger.Logger selectionMode string leaseDuration time.Duration - noNewHeadsThreshold time.Duration - nodes []Node[types.ID, types.Head[Hashable], multiNodeRPCClient] + nodes []Node[types.ID, multiNodeRPCClient] sendonlys []SendOnlyNode[types.ID, multiNodeRPCClient] chainID types.ID chainFamily string - classifySendTxError func(tx any, err error) SendTxReturnCode - sendTxSoftTimeout time.Duration deathDeclarationDelay time.Duration } @@ -47,46 +41,32 @@ func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode { opts.logger = logger.Test(t) } - result := NewMultiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, - types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any](opts.logger, - opts.selectionMode, opts.leaseDuration, opts.noNewHeadsThreshold, opts.nodes, opts.sendonlys, - opts.chainID, opts.chainFamily, opts.classifySendTxError, opts.sendTxSoftTimeout, opts.deathDeclarationDelay) + result := NewMultiNode[types.ID, multiNodeRPCClient]( + opts.logger, opts.selectionMode, opts.leaseDuration, opts.nodes, opts.sendonlys, opts.chainID, opts.chainFamily, opts.deathDeclarationDelay) return testMultiNode{ - result.(*multiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, - types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any]), + result, } } -func newMultiNodeRPCClient(t *testing.T) *mockRPC[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, - types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], any] { - return newMockRPC[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, - types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], any](t) -} - -func newHealthyNode(t *testing.T, chainID types.ID) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] { +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, types.Head[Hashable], multiNodeRPCClient] { - node := newDialableNode(t, chainID) - node.On("State").Return(state).Maybe() - return node -} - -func newDialableNode(t *testing.T, chainID types.ID) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] { - node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) +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, types.Head[Hashable], multiNodeRPCClient] + newMockNode := newMockNode[types.ID, multiNodeRPCClient] newMockSendOnlyNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient] t.Run("Fails without nodes", func(t *testing.T) { @@ -95,7 +75,7 @@ func TestMultiNode_Dial(t *testing.T) { selectionMode: NodeSelectionModeRoundRobin, chainID: types.RandomID(), }) - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) assert.EqualError(t, err, fmt.Sprintf("no available nodes for chain %s", mn.chainID.String())) }) t.Run("Fails with wrong node's chainID", func(t *testing.T) { @@ -109,9 +89,9 @@ func TestMultiNode_Dial(t *testing.T) { mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: multiNodeChainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, }) - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) assert.EqualError(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) { @@ -119,15 +99,15 @@ func TestMultiNode_Dial(t *testing.T) { node := newMockNode(t) chainID := types.RandomID() node.On("ConfiguredChainID").Return(chainID).Once() - node.On("SetPoolChainInfoProvider", mock.Anything).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, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, }) - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) assert.EqualError(t, err, expectedError.Error()) }) @@ -137,16 +117,16 @@ func TestMultiNode_Dial(t *testing.T) { node1 := newHealthyNode(t, chainID) node2 := newMockNode(t) node2.On("ConfiguredChainID").Return(chainID).Once() - node2.On("SetPoolChainInfoProvider", mock.Anything).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, types.Head[Hashable], multiNodeRPCClient]{node1, node2}, + nodes: []Node[types.ID, multiNodeRPCClient]{node1, node2}, }) - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) assert.EqualError(t, err, expectedError.Error()) }) t.Run("Fails with wrong send only node's chainID", func(t *testing.T) { @@ -162,10 +142,10 @@ func TestMultiNode_Dial(t *testing.T) { mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: multiNodeChainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{sendOnly}, }) - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) assert.EqualError(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)) }) @@ -189,10 +169,10 @@ func TestMultiNode_Dial(t *testing.T) { mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{sendOnly1, sendOnly2}, }) - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) assert.EqualError(t, err, expectedError.Error()) }) t.Run("Starts successfully with healthy nodes", func(t *testing.T) { @@ -202,11 +182,11 @@ func TestMultiNode_Dial(t *testing.T) { mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newHealthySendOnly(t, chainID)}, }) defer func() { assert.NoError(t, mn.Close()) }() - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) require.NoError(t, err) selectedNode, err := mn.selectNode() require.NoError(t, err) @@ -225,13 +205,13 @@ func TestMultiNode_Report(t *testing.T) { mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node1, node2}, + nodes: []Node[types.ID, multiNodeRPCClient]{node1, node2}, logger: lggr, }) mn.reportInterval = tests.TestInterval mn.deathDeclarationDelay = tests.TestInterval defer func() { assert.NoError(t, mn.Close()) }() - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) require.NoError(t, err) tests.AssertLogCountEventually(t, observedLogs, "At least one primary node is dead: 1/2 nodes are alive", 2) }) @@ -243,13 +223,13 @@ func TestMultiNode_Report(t *testing.T) { mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, logger: lggr, }) mn.reportInterval = tests.TestInterval mn.deathDeclarationDelay = tests.TestInterval defer func() { assert.NoError(t, mn.Close()) }() - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) require.NoError(t, err) tests.AssertLogCountEventually(t, observedLogs, "no primary nodes available: 0/1 nodes are alive", 2) err = mn.Healthy() @@ -269,10 +249,10 @@ func TestMultiNode_CheckLease(t *testing.T) { selectionMode: NodeSelectionModeRoundRobin, chainID: chainID, logger: lggr, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, }) defer func() { assert.NoError(t, mn.Close()) }() - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) require.NoError(t, err) tests.RequireLogMessage(t, observedLogs, "Best node switching is disabled") }) @@ -285,11 +265,11 @@ func TestMultiNode_CheckLease(t *testing.T) { selectionMode: NodeSelectionModeHighestHead, chainID: chainID, logger: lggr, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node}, + nodes: []Node[types.ID, multiNodeRPCClient]{node}, leaseDuration: 0, }) defer func() { assert.NoError(t, mn.Close()) }() - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) require.NoError(t, err) tests.RequireLogMessage(t, observedLogs, "Best node switching is disabled") }) @@ -297,22 +277,21 @@ func TestMultiNode_CheckLease(t *testing.T) { t.Parallel() chainID := types.RandomID() node := newHealthyNode(t, chainID) - node.On("SubscribersCount").Return(int32(2)) node.On("UnsubscribeAllExceptAliveLoop") bestNode := newHealthyNode(t, chainID) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + 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, types.Head[Hashable], multiNodeRPCClient]{node, bestNode}, + nodes: []Node[types.ID, multiNodeRPCClient]{node, bestNode}, leaseDuration: tests.TestInterval, }) defer func() { assert.NoError(t, mn.Close()) }() mn.nodeSelector = nodeSelector - err := mn.Dial(tests.Context(t)) + err := mn.Start(tests.Context(t)) require.NoError(t, err) tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("Switching to best node from %q to %q", node.String(), bestNode.String())) tests.AssertEventually(t, func() bool { @@ -338,15 +317,15 @@ func TestMultiNode_CheckLease(t *testing.T) { expectedResult := map[string]string{} for name, state := range nodes { - node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - node.On("Name").Return(name).Once() + node := newMockNode[types.ID, multiNodeRPCClient](t) node.On("State").Return(state).Once() + node.On("String").Return(name).Once() opts.nodes = append(opts.nodes, node) sendOnly := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t) sendOnlyName := "send_only_" + name - sendOnly.On("Name").Return(sendOnlyName).Once() sendOnly.On("State").Return(state).Once() + sendOnly.On("String").Return(sendOnlyName).Once() opts.sendonlys = append(opts.sendonlys, sendOnly) expectedResult[name] = state.String() @@ -364,17 +343,17 @@ func TestMultiNode_selectNode(t *testing.T) { t.Run("Returns same node, if it's still healthy", func(t *testing.T) { t.Parallel() chainID := types.RandomID() - node1 := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + node1 := newMockNode[types.ID, multiNodeRPCClient](t) node1.On("State").Return(nodeStateAlive).Once() node1.On("String").Return("node1").Maybe() - node2 := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + node2 := newMockNode[types.ID, multiNodeRPCClient](t) node2.On("String").Return("node2").Maybe() mn := newTestMultiNode(t, multiNodeOpts{ selectionMode: NodeSelectionModeRoundRobin, chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{node1, node2}, + nodes: []Node[types.ID, multiNodeRPCClient]{node1, node2}, }) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) nodeSelector.On("Select").Return(node1).Once() mn.nodeSelector = nodeSelector prevActiveNode, err := mn.selectNode() @@ -387,17 +366,17 @@ func TestMultiNode_selectNode(t *testing.T) { t.Run("Updates node if active is not healthy", func(t *testing.T) { t.Parallel() chainID := types.RandomID() - oldBest := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + oldBest := newMockNode[types.ID, multiNodeRPCClient](t) oldBest.On("String").Return("oldBest").Maybe() - oldBest.On("UnsubscribeAllExceptAliveLoop").Once() - newBest := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + 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, types.Head[Hashable], multiNodeRPCClient]{oldBest, newBest}, + nodes: []Node[types.ID, multiNodeRPCClient]{oldBest, newBest}, }) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) nodeSelector.On("Select").Return(oldBest).Once() mn.nodeSelector = nodeSelector activeNode, err := mn.selectNode() @@ -419,7 +398,7 @@ func TestMultiNode_selectNode(t *testing.T) { chainID: chainID, logger: lggr, }) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + nodeSelector := newMockNodeSelector[types.ID, multiNodeRPCClient](t) nodeSelector.On("Select").Return(nil).Once() nodeSelector.On("Name").Return("MockedNodeSelector").Once() mn.nodeSelector = nodeSelector @@ -532,10 +511,10 @@ func TestMultiNode_ChainInfo(t *testing.T) { tc := testCases[i] t.Run(tc.Name, func(t *testing.T) { for _, params := range tc.NodeParams { - node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) + 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) - mn.nodes = append(mn.nodes, node) } nNodes, latestChainInfo := mn.LatestChainInfo() @@ -547,400 +526,3 @@ func TestMultiNode_ChainInfo(t *testing.T) { }) } } - -func TestMultiNode_BatchCallContextAll(t *testing.T) { - t.Parallel() - t.Run("Fails if failed to select active node", func(t *testing.T) { - chainID := types.RandomID() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - }) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - nodeSelector.On("Select").Return(nil).Once() - nodeSelector.On("Name").Return("MockedNodeSelector").Once() - mn.nodeSelector = nodeSelector - err := mn.BatchCallContextAll(tests.Context(t), nil) - require.EqualError(t, err, ErroringNodeError.Error()) - }) - t.Run("Returns error if RPC call fails for active node", func(t *testing.T) { - chainID := types.RandomID() - rpc := newMultiNodeRPCClient(t) - expectedError := errors.New("rpc failed to do the batch call") - rpc.On("BatchCallContext", mock.Anything, mock.Anything).Return(expectedError).Once() - node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - node.On("RPC").Return(rpc) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - nodeSelector.On("Select").Return(node).Once() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - }) - mn.nodeSelector = nodeSelector - err := mn.BatchCallContextAll(tests.Context(t), nil) - require.EqualError(t, err, expectedError.Error()) - }) - t.Run("Waits for all nodes to complete the call and logs results", func(t *testing.T) { - // setup RPCs - failedRPC := newMultiNodeRPCClient(t) - failedRPC.On("BatchCallContext", mock.Anything, mock.Anything). - Return(errors.New("rpc failed to do the batch call")).Once() - okRPC := newMultiNodeRPCClient(t) - okRPC.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Twice() - - // setup ok and failed auxiliary nodes - okNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t) - okNode.On("RPC").Return(okRPC).Once() - okNode.On("State").Return(nodeStateAlive) - failedNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - failedNode.On("RPC").Return(failedRPC).Once() - failedNode.On("State").Return(nodeStateAlive) - - // setup main node - mainNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - mainNode.On("RPC").Return(okRPC) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - nodeSelector.On("Select").Return(mainNode).Once() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: types.RandomID(), - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{failedNode, mainNode}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{okNode}, - logger: lggr, - }) - mn.nodeSelector = nodeSelector - - err := mn.BatchCallContextAll(tests.Context(t), nil) - require.NoError(t, err) - tests.RequireLogMessage(t, observedLogs, "Secondary node BatchCallContext failed") - }) - t.Run("Does not call BatchCallContext for unhealthy nodes", func(t *testing.T) { - // setup RPCs - okRPC := newMultiNodeRPCClient(t) - okRPC.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Twice() - - // setup ok and failed auxiliary nodes - healthyNode := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t) - healthyNode.On("RPC").Return(okRPC).Once() - healthyNode.On("State").Return(nodeStateAlive) - deadNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - deadNode.On("State").Return(nodeStateUnreachable) - - // setup main node - mainNode := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - mainNode.On("RPC").Return(okRPC) - nodeSelector := newMockNodeSelector[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - nodeSelector.On("Select").Return(mainNode).Once() - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: types.RandomID(), - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{deadNode, mainNode}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{healthyNode, deadNode}, - }) - mn.nodeSelector = nodeSelector - - err := mn.BatchCallContextAll(tests.Context(t), nil) - require.NoError(t, err) - }) -} - -func TestMultiNode_SendTransaction(t *testing.T) { - t.Parallel() - classifySendTxError := func(tx any, err error) SendTxReturnCode { - if err != nil { - return Fatal - } - - return Successful - } - newNodeWithState := func(t *testing.T, state nodeState, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] { - rpc := newMultiNodeRPCClient(t) - rpc.On("SendTransaction", mock.Anything, mock.Anything).Return(txErr).Run(sendTxRun).Maybe() - node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - node.On("String").Return("node name").Maybe() - node.On("RPC").Return(rpc).Maybe() - node.On("State").Return(state).Maybe() - node.On("Close").Return(nil).Once() - return node - } - - newNode := func(t *testing.T, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] { - return newNodeWithState(t, nodeStateAlive, txErr, sendTxRun) - } - newStartedMultiNode := func(t *testing.T, opts multiNodeOpts) testMultiNode { - mn := newTestMultiNode(t, opts) - err := mn.StartOnce("startedTestMultiNode", func() error { return nil }) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, mn.Close()) - }) - return mn - } - t.Run("Fails if there is no nodes available", func(t *testing.T) { - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: types.RandomID(), - }) - err := mn.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, err, ErroringNodeError.Error()) - }) - t.Run("Transaction failure happy path", func(t *testing.T) { - chainID := types.RandomID() - expectedError := errors.New("transaction failed") - mainNode := newNode(t, expectedError, nil) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{mainNode}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newNode(t, errors.New("unexpected error"), nil)}, - classifySendTxError: classifySendTxError, - logger: lggr, - }) - err := mn.SendTransaction(tests.Context(t), nil) - require.EqualError(t, err, expectedError.Error()) - 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) { - chainID := types.RandomID() - mainNode := newNode(t, nil, nil) - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{mainNode}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newNode(t, errors.New("unexpected error"), nil)}, - classifySendTxError: classifySendTxError, - logger: lggr, - }) - err := mn.SendTransaction(tests.Context(t), nil) - require.NoError(t, err) - 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) { - chainID := types.RandomID() - testContext, testCancel := context.WithCancel(tests.Context(t)) - defer testCancel() - mainNode := newNode(t, errors.New("unexpected error"), func(_ mock.Arguments) { - // block caller til end of the test - <-testContext.Done() - }) - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{mainNode}, - classifySendTxError: classifySendTxError, - }) - requestContext, cancel := context.WithCancel(tests.Context(t)) - cancel() - err := mn.SendTransaction(requestContext, nil) - require.EqualError(t, err, "context canceled") - }) - t.Run("Soft timeout stops results collection", func(t *testing.T) { - chainID := types.RandomID() - expectedError := errors.New("tmp error") - 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() - }) - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{fastNode, slowNode}, - classifySendTxError: classifySendTxError, - sendTxSoftTimeout: tests.TestInterval, - }) - err := mn.SendTransaction(tests.Context(t), nil) - require.EqualError(t, err, 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, observedLogs := logger.TestObserved(t, zap.WarnLevel) - mn := newTestMultiNode(t, multiNodeOpts{ - logger: lggr, - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{fastNode, slowNode}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{slowSendOnly}, - classifySendTxError: classifySendTxError, - sendTxSoftTimeout: tests.TestInterval, - }) - assert.NoError(t, mn.StartOnce("startedTestMultiNode", func() error { return nil })) - err := mn.SendTransaction(tests.Context(t), nil) - require.NoError(t, err) - testCancel() - require.NoError(t, mn.Close()) - tests.AssertLogEventually(t, observedLogs, "observed invariant violation on SendTransaction") - }) - t.Run("Fails when closed", func(t *testing.T) { - mn := newTestMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: types.RandomID(), - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{newNode(t, nil, nil)}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newNode(t, nil, nil)}, - classifySendTxError: classifySendTxError, - }) - err := mn.StartOnce("startedTestMultiNode", func() error { return nil }) - require.NoError(t, err) - require.NoError(t, mn.Close()) - err = mn.SendTransaction(tests.Context(t), nil) - require.EqualError(t, err, "aborted while broadcasting tx - multiNode is stopped: context canceled") - }) - t.Run("Returns error if there is no healthy primary nodes", func(t *testing.T) { - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: types.RandomID(), - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{newNodeWithState(t, nodeStateUnreachable, nil, nil)}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{newNodeWithState(t, nodeStateUnreachable, nil, nil)}, - classifySendTxError: classifySendTxError, - }) - err := mn.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, err, 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, observedLogs := logger.TestObserved(t, zap.DebugLevel) - mn := newStartedMultiNode(t, multiNodeOpts{ - selectionMode: NodeSelectionModeRoundRobin, - chainID: chainID, - nodes: []Node[types.ID, types.Head[Hashable], multiNodeRPCClient]{mainNode, unhealthyNode}, - sendonlys: []SendOnlyNode[types.ID, multiNodeRPCClient]{unhealthySendOnlyNode, newNode(t, errors.New("unexpected error"), nil)}, - classifySendTxError: classifySendTxError, - logger: lggr, - }) - err := mn.SendTransaction(tests.Context(t), nil) - require.NoError(t, err) - tests.AssertLogCountEventually(t, observedLogs, "Node sent transaction", 2) - tests.AssertLogCountEventually(t, observedLogs, "RPC returned error", 1) - }) -} - -func TestMultiNode_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 sendTxErrors - }{ - { - 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: sendTxErrors{ - Successful: {errors.New("success")}, - Fatal: {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: sendTxErrors{ - TransactionAlreadyKnown: {errors.New("tx_already_known")}, - Unsupported: {errors.New("unsupported")}, - }, - }, - { - Name: "Prefers sever error to temporary", - ExpectedTxResult: "underpriced", - ExpectedCriticalErr: "", - ResultsByCode: sendTxErrors{ - Retryable: {errors.New("retryable")}, - Underpriced: {errors.New("underpriced")}, - }, - }, - { - Name: "Returns temporary error", - ExpectedTxResult: "retryable", - ExpectedCriticalErr: "", - ResultsByCode: sendTxErrors{ - Retryable: {errors.New("retryable")}, - }, - }, - { - Name: "Insufficient funds is treated as error", - ExpectedTxResult: "", - ExpectedCriticalErr: "", - ResultsByCode: sendTxErrors{ - Successful: {nil}, - InsufficientFunds: {errors.New("insufficientFunds")}, - }, - }, - { - Name: "Logs critical error on empty ResultsByCode", - ExpectedTxResult: "expected at least one response on SendTransaction", - ExpectedCriticalErr: "expected at least one response on SendTransaction", - ResultsByCode: sendTxErrors{}, - }, - { - Name: "Zk out of counter error", - ExpectedTxResult: "not enough keccak counters to continue the execution", - ExpectedCriticalErr: "", - ResultsByCode: sendTxErrors{ - TerminallyStuck: {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 == "" { - assert.NoError(t, err) - } else { - assert.EqualError(t, txResult, 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 == "" { - assert.NoError(t, err) - } else { - assert.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/node.go b/common/client/node.go index d6543c772a8..66161ac5d5f 100644 --- a/common/client/node.go +++ b/common/client/node.go @@ -45,6 +45,7 @@ type NodeConfig interface { FinalizedBlockPollInterval() time.Duration EnforceRepeatableRead() bool DeathDeclarationDelay() time.Duration + NewHeadsPollInterval() time.Duration } type ChainConfig interface { @@ -57,8 +58,7 @@ type ChainConfig interface { type Node[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + 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 @@ -71,13 +71,15 @@ type Node[ 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 - SubscribersCount() int32 // 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 } @@ -85,19 +87,19 @@ type Node[ type node[ CHAIN_ID types.ID, HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + RPC RPCClient[CHAIN_ID, HEAD], ] struct { services.StateMachine lfcLog logger.Logger name string - id int32 + id int chainID CHAIN_ID nodePoolCfg NodeConfig chainCfg ChainConfig order int32 chainFamily string - ws url.URL + ws *url.URL http *url.URL rpc RPC @@ -110,33 +112,37 @@ type node[ stopCh services.StopChan // wg waits for subsidiary goroutines wg sync.WaitGroup + + healthCheckSubs []types.Subscription } func NewNode[ CHAIN_ID types.ID, HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + RPC RPCClient[CHAIN_ID, HEAD], ]( nodeCfg NodeConfig, chainCfg ChainConfig, lggr logger.Logger, - wsuri url.URL, + wsuri *url.URL, httpuri *url.URL, name string, - id int32, + id int, chainID CHAIN_ID, nodeOrder int32, rpc RPC, chainFamily string, -) Node[CHAIN_ID, HEAD, RPC] { +) 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.ws = wsuri n.order = nodeOrder + if wsuri != nil { + n.ws = wsuri + } if httpuri != nil { n.http = httpuri } @@ -156,7 +162,10 @@ func NewNode[ } func (n *node[CHAIN_ID, HEAD, RPC]) String() string { - s := fmt.Sprintf("(%s)%s:%s", Primary.String(), n.name, n.ws.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()) } @@ -175,12 +184,16 @@ func (n *node[CHAIN_ID, HEAD, RPC]) RPC() RPC { return n.rpc } -func (n *node[CHAIN_ID, HEAD, RPC]) SubscribersCount() int32 { - return n.rpc.SubscribersCount() +// 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.rpc.UnsubscribeAllExceptAliveLoop() + n.stateMu.Lock() + defer n.stateMu.Unlock() + n.unsubscribeAllExceptAliveLoop() } func (n *node[CHAIN_ID, HEAD, RPC]) Close() error { @@ -312,13 +325,6 @@ func (n *node[CHAIN_ID, HEAD, RPC]) verifyConn(ctx context.Context, lggr logger. return nodeStateAlive } -// disconnectAll disconnects all clients connected to the node -// WARNING: NOT THREAD-SAFE -// This must be called from within the n.stateMu lock -func (n *node[CHAIN_ID, HEAD, RPC]) disconnectAll() { - n.rpc.DisconnectAll() -} - func (n *node[CHAIN_ID, HEAD, RPC]) Order() int32 { return n.order } diff --git a/common/client/node_fsm.go b/common/client/node_fsm.go index e58de071fbc..4a80e4fae9b 100644 --- a/common/client/node_fsm.go +++ b/common/client/node_fsm.go @@ -256,7 +256,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) transitionToOutOfSync(fn func()) { } switch n.state { case nodeStateAlive: - n.disconnectAll() + n.rpc.Close() n.state = nodeStateOutOfSync default: panic(transitionFail(n.state, nodeStateOutOfSync)) @@ -281,7 +281,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) transitionToUnreachable(fn func()) { } switch n.state { case nodeStateUndialed, nodeStateDialed, nodeStateAlive, nodeStateOutOfSync, nodeStateInvalidChainID, nodeStateSyncing: - n.disconnectAll() + n.rpc.Close() n.state = nodeStateUnreachable default: panic(transitionFail(n.state, nodeStateUnreachable)) @@ -324,7 +324,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInvalidChainID(fn func()) { } switch n.state { case nodeStateDialed, nodeStateOutOfSync, nodeStateSyncing: - n.disconnectAll() + n.rpc.Close() n.state = nodeStateInvalidChainID default: panic(transitionFail(n.state, nodeStateInvalidChainID)) @@ -349,7 +349,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) transitionToSyncing(fn func()) { } switch n.state { case nodeStateDialed, nodeStateOutOfSync, nodeStateInvalidChainID: - n.disconnectAll() + n.rpc.Close() n.state = nodeStateSyncing default: panic(transitionFail(n.state, nodeStateSyncing)) diff --git a/common/client/node_fsm_test.go b/common/client/node_fsm_test.go index dc0ca0e7de8..93460d934a3 100644 --- a/common/client/node_fsm_test.go +++ b/common/client/node_fsm_test.go @@ -39,47 +39,47 @@ func TestUnit_Node_StateTransitions(t *testing.T) { t.Run("transitionToAlive", func(t *testing.T) { const destinationState = nodeStateAlive allowedStates := []nodeState{nodeStateDialed, nodeStateInvalidChainID, nodeStateSyncing} - rpc := newMockNodeClient[types.ID, Head](t) + 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 := newMockNodeClient[types.ID, Head](t) + 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 := newMockNodeClient[types.ID, Head](t) - rpc.On("DisconnectAll").Once() + 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 := newMockNodeClient[types.ID, Head](t) - rpc.On("DisconnectAll").Times(len(allowedStates)) + 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 := newMockNodeClient[types.ID, Head](t) - rpc.On("DisconnectAll").Times(len(allowedStates)) + 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 := newMockNodeClient[types.ID, Head](t) - rpc.On("DisconnectAll").Times(len(allowedStates)) + 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 := newMockNodeClient[types.ID, Head](t) - rpc.On("DisconnectAll").Once() + rpc := newMockRPCClient[types.ID, Head](t) + rpc.On("Close") node := newTestNode(t, testNodeOpts{rpc: rpc}) node.setState(nodeStateDialed) fn := new(fnMock) @@ -90,7 +90,7 @@ func TestUnit_Node_StateTransitions(t *testing.T) { }) } -func testTransition(t *testing.T, rpc *mockNodeClient[types.ID, Head], transition func(node testNode, fn func()), destinationState nodeState, allowedStates ...nodeState) { +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) diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 40d9a9ef6ef..ce508a43dde 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -103,23 +103,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { return } - // TODO: will be removed as part of merging effort with BCI-2875 - n.rpc.SetAliveLoopSub(headsSub.sub) - - defer headsSub.Unsubscribe() - - 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 - } - - defer finalizedHeadsSub.Unsubscribe() - } + defer n.unsubscribeHealthChecks() var pollCh <-chan time.Time if pollInterval > 0 { @@ -137,6 +121,17 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { 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 + } + } + localHighestChainInfo, _ := n.rpc.GetInterceptedChainInfo() var pollFailures uint32 @@ -146,13 +141,10 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { return case <-pollCh: promPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Tracew("Polling for version", "nodeState", n.getCachedState(), "pollFailures", pollFailures) - var version string - version, err = func(ctx context.Context) (string, error) { - ctx, cancel := context.WithTimeout(ctx, pollInterval) - defer cancel() - return n.RPC().ClientVersion(ctx) - }(ctx) + 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 { @@ -161,7 +153,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { } 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("Version poll successful", "nodeState", n.getCachedState(), "clientVersion", version) + lggr.Debugw("Ping successful", "nodeState", n.State()) promPoolRPCNodePollsSuccess.WithLabelValues(n.chainID.String(), n.name).Inc() pollFailures = 0 } @@ -193,7 +185,6 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { n.declareUnreachable() return } - receivedNewHead := n.onNewHead(lggr, &localHighestChainInfo, bh) if receivedNewHead && noNewHeadsTimeoutThreshold > 0 { headsSub.ResetTimer(noNewHeadsTimeoutThreshold) @@ -219,7 +210,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { return case latestFinalized, open := <-finalizedHeadsSub.Heads: if !open { - lggr.Errorw("Finalized heads subscription channel unexpectedly closed", "nodeState", n.getCachedState()) + lggr.Errorw("Finalized heads subscription channel unexpectedly closed") n.declareUnreachable() return } @@ -251,6 +242,15 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { } } +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 @@ -284,11 +284,10 @@ func (n *node[CHAIN_ID, HEAD, PRC]) registerNewSubscription(ctx context.Context, result.Errors = sub.Err() lggr.Debug("Successfully subscribed") - // TODO: will be removed as part of merging effort with BCI-2875 result.sub = sub - //n.stateMu.Lock() - //n.healthCheckSubs = append(n.healthCheckSubs, sub) - //n.stateMu.Unlock() + n.stateMu.Lock() + n.healthCheckSubs = append(n.healthCheckSubs, sub) + n.stateMu.Unlock() result.cleanUpTasks = append(result.cleanUpTasks, sub.Unsubscribe) @@ -350,6 +349,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) onNewHead(lggr logger.SugaredLogger, chainIn 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. @@ -376,12 +381,6 @@ func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSyncWithPool(localState ChainInfo) (o } } -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" -) - // 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() @@ -422,8 +421,9 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(syncIssues syncStatus) { return } + defer n.unsubscribeHealthChecks() + lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node") - defer headsSub.Unsubscribe() noNewFinalizedBlocksTimeoutThreshold := n.chainCfg.NoNewFinalizedHeadsThreshold() var finalizedHeadsSub headSubscription[HEAD] @@ -437,7 +437,6 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(syncIssues syncStatus) { } lggr.Tracew("Successfully subscribed to finalized heads feed on out-of-sync RPC node") - defer finalizedHeadsSub.Unsubscribe() } _, localHighestChainInfo := n.rpc.GetInterceptedChainInfo() diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go index 833bccf7f29..6f9b4653393 100644 --- a/common/client/node_lifecycle_test.go +++ b/common/client/node_lifecycle_test.go @@ -23,12 +23,19 @@ import ( "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).Once() + opts.rpc.On("Close").Return(nil) node.setState(nodeStateDialed) return node @@ -42,14 +49,13 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("if initial subscribe fails, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + 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("DisconnectAll").Once() 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() @@ -60,7 +66,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("if remote RPC connection is closed transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) node := newDialedNode(t, testNodeOpts{ @@ -76,9 +82,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { sub.On("Err").Return((<-chan error)(errChan)).Once() sub.On("Unsubscribe").Once() rpc.On("SubscribeToHeads", mock.Anything).Return(nil, sub, nil).Once() - rpc.On("SetAliveLoopSub", sub).Once() - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll").Once() // might be called in unreachable loop rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() node.declareAlive() @@ -87,16 +90,13 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) newSubscribedNode := func(t *testing.T, opts testNodeOpts) testNode { - sub := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() - opts.rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil) - opts.rpc.On("SetAliveLoopSub", sub).Once() + 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 := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ @@ -112,7 +112,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("stays alive while below pollFailureThreshold and resets counter on success", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const pollFailureThreshold = 3 @@ -128,17 +128,17 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { pollError := errors.New("failed to get ClientVersion") // 1. Return error several times, but below threshold - rpc.On("ClientVersion", mock.Anything).Return("", pollError).Run(func(_ mock.Arguments) { + 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("ClientVersion", mock.Anything).Return("client_version", nil).Once() + 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("ClientVersion", mock.Anything).Return("", pollError).Once() + rpc.On("Ping", mock.Anything).Return(pollError).Once() // 4. Once during the call, check if node is alive var ensuredAlive atomic.Bool - rpc.On("ClientVersion", mock.Anything).Return("client_version", nil).Run(func(_ mock.Arguments) { + rpc.On("Ping", mock.Anything).Return(nil).Run(func(_ mock.Arguments) { if ensuredAlive.Load() { return } @@ -146,15 +146,15 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { assert.Equal(t, nodeStateAlive, node.State()) }).Once() // redundant call to stay in alive state - rpc.On("ClientVersion", mock.Anything).Return("client_version", nil) + 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, "Version poll successful", 2) + 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 := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const pollFailureThreshold = 3 @@ -168,10 +168,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() pollError := errors.New("failed to get ClientVersion") - rpc.On("ClientVersion", mock.Anything).Return("", pollError) - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll").Once() - // might be called in unreachable loop + 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) @@ -181,7 +178,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("with threshold poll failures, but we are the last node alive, forcibly keeps it alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const pollFailureThreshold = 3 node := newSubscribedNode(t, testNodeOpts{ @@ -200,14 +197,14 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { node.SetPoolChainInfoProvider(poolInfo) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: 20}, ChainInfo{BlockNumber: 20}) pollError := errors.New("failed to get ClientVersion") - rpc.On("ClientVersion", mock.Anything).Return("", pollError) + 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 := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const syncThreshold = 10 node := newSubscribedNode(t, testNodeOpts{ @@ -220,6 +217,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { 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) @@ -228,14 +226,11 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { TotalDifficulty: big.NewInt(10), }).Once() node.SetPoolChainInfoProvider(poolInfo) - rpc.On("ClientVersion", mock.Anything).Return("", nil) // 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() - // disconnects all on transfer to unreachable or outOfSync - rpc.On("DisconnectAll").Maybe() - // might be called in unreachable loop + 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() @@ -244,7 +239,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("when behind more than SyncThreshold but we are the last live node, forcibly stays alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const syncThreshold = 10 node := newSubscribedNode(t, testNodeOpts{ @@ -257,6 +252,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { 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) @@ -265,13 +261,12 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { TotalDifficulty: big.NewInt(10), }).Once() node.SetPoolChainInfoProvider(poolInfo) - rpc.On("ClientVersion", mock.Anything).Return("", nil) 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 := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{ @@ -283,16 +278,16 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { 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}) - rpc.On("ClientVersion", mock.Anything).Return("", nil) node.declareAlive() - tests.AssertLogCountEventually(t, observedLogs, "Version poll successful", 2) + 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 := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{}, @@ -306,9 +301,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { assert.Equal(t, nodeStateOutOfSync, node.State()) }).Once() - // disconnects all on transfer to unreachable or outOfSync - rpc.On("DisconnectAll").Maybe() - // 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 { @@ -319,7 +311,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) 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 := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ @@ -341,21 +333,16 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState)) assert.Equal(t, nodeStateAlive, node.State()) }) - newSub := func(t *testing.T) *mocks.Subscription { - sub := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() - return sub - } + t.Run("rpc closed head channel", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + 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), newSub(t), nil).Once() - rpc.On("SetAliveLoopSub", mock.Anything).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() + }).Return((<-chan Head)(ch), sub, nil).Once() lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) node := newDialedNode(t, testNodeOpts{ lggr: lggr, @@ -366,9 +353,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() - // disconnects all on transfer to unreachable or outOfSync - rpc.On("DisconnectAll").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 channel unexpectedly closed") @@ -376,19 +360,16 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) 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 := newMockNodeClient[types.ID, Head](t) - sub := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() + rpc := newMockRPCClient[types.ID, Head](t) + sub := newSub(t) const blockNumber = 1000 const finalityDepth = 10 const expectedBlock = 990 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() 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() - rpc.On("SetAliveLoopSub", sub).Once() name := "node-" + rand.Str(5) node := newDialedNode(t, testNodeOpts{ config: testNodeConfig{}, @@ -407,13 +388,15 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { return float64(expectedBlock) == m.Gauge.GetValue() }) }) - t.Run("If fails to subscribe to latest finalized blocks, transitions to unreachable ", func(t *testing.T) { + t.Run("If fails to subscribe to latest finalized blocks, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + 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, mocks.NewSubscription(t), expectedError).Once() - lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) - node := newSubscribedNode(t, testNodeOpts{ + rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(nil, sub, expectedError).Once() + lggr, _ := logger.TestObserved(t, zap.DebugLevel) + node := newDialedNode(t, testNodeOpts{ config: testNodeConfig{ finalizedBlockPollInterval: tests.TestInterval, }, @@ -424,28 +407,24 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - // disconnects all on transfer to unreachable or outOfSync - rpc.On("DisconnectAll").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, "Failed to subscribe to finalized heads") tests.AssertEventually(t, func() bool { - return nodeStateUnreachable == node.State() + return node.State() == nodeStateUnreachable }) }) t.Run("Logs warning if latest finalized block is not valid", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + 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), newSub(t), nil).Once() + }).Return((<-chan Head)(ch), sub, nil).Once() + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), newSub(t), nil).Once() - rpc.On("SetAliveLoopSub", mock.Anything).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ config: testNodeConfig{}, @@ -461,7 +440,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("On new finalized block updates corresponding metric", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) const expectedBlock = 1101 const finalityDepth = 10 ch := make(chan Head) @@ -496,7 +475,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("If finalized heads channel is closed, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() ch := make(chan Head) close(ch) @@ -510,9 +489,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - // disconnects all on transfer to unreachable or outOfSync - rpc.On("DisconnectAll").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, "Finalized heads subscription channel unexpectedly closed") @@ -522,7 +498,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("when no new finalized heads received for threshold, transitions to out of sync", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() ch := make(chan Head, 1) ch <- head{BlockNumber: 10}.ToMockHead(t) @@ -543,9 +519,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { assert.Equal(t, nodeStateOutOfSync, node.State()) }).Once() - // disconnects all on transfer to unreachable or outOfSync - rpc.On("DisconnectAll").Maybe() - // might be called in unreachable loop 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)) @@ -557,7 +530,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) 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 := newMockNodeClient[types.ID, Head](t) + 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) @@ -584,8 +557,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { }) t.Run("If finalized subscription returns an error, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) - rpc.On("DisconnectAll").Once() + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() sub := mocks.NewSubscription(t) errCh := make(chan error, 1) @@ -602,8 +574,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - // disconnects all on transfer to unreachable or outOfSync - // might be called in unreachable loop rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() node.declareAlive() tests.AssertLogEventually(t, observedLogs, "Finalized heads subscription was terminated") @@ -637,7 +607,7 @@ func writeHeads(t *testing.T, ch chan<- Head, heads ...head) { } } -func setupRPCForAliveLoop(t *testing.T, rpc *mockNodeClient[types.ID, Head]) { +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() @@ -653,9 +623,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { newAliveNode := func(t *testing.T, opts testNodeOpts) testNode { node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil).Once() - // disconnects all on transfer to unreachable or outOfSync - opts.rpc.On("DisconnectAll") + opts.rpc.On("Close").Return(nil) node.setState(nodeStateAlive) return node } @@ -669,7 +637,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("on old blocks stays outOfSync and returns on close", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr := logger.Test(t) node := newAliveNode(t, testNodeOpts{ @@ -681,6 +649,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { 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) @@ -706,7 +675,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("if initial dial fails, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) node := newAliveNode(t, testNodeOpts{ rpc: rpc, }) @@ -715,6 +684,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { 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 @@ -722,7 +692,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("if fail to get chainID, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) node := newAliveNode(t, testNodeOpts{ rpc: rpc, }) @@ -732,6 +702,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { rpc.On("Dial", mock.Anything).Return(nil).Once() // for unreachable rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() + expectedError := errors.New("failed to get chain ID") // might be called multiple times rpc.On("ChainID", mock.Anything).Return(types.NewIDFromInt(0), expectedError) @@ -742,7 +713,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("if chainID does not match, transitions to invalidChainID", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) node := newAliveNode(t, testNodeOpts{ @@ -753,6 +724,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { // 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) @@ -762,7 +734,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("if syncing, transitions to syncing", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) node := newAliveNode(t, testNodeOpts{ rpc: rpc, @@ -773,6 +745,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { 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) @@ -782,7 +755,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("if fails to fetch syncing status, transitions to unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) node := newAliveNode(t, testNodeOpts{ rpc: rpc, @@ -793,6 +766,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { // 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() @@ -805,7 +779,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("if fails to subscribe, becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newAliveNode(t, testNodeOpts{ rpc: rpc, @@ -817,6 +791,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { 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 { @@ -825,7 +800,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("on subscription termination becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) node := newAliveNode(t, testNodeOpts{ @@ -837,6 +812,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { 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) @@ -853,7 +829,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("becomes unreachable if head channel is closed", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) node := newAliveNode(t, testNodeOpts{ @@ -865,11 +841,10 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { 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) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() + sub := newSub(t) ch := make(chan Head) rpc.On("SubscribeToHeads", mock.Anything).Run(func(args mock.Arguments) { close(ch) @@ -883,7 +858,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("becomes alive if it receives a newer head", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ @@ -916,7 +891,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("becomes alive if there is no other nodes", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ @@ -953,7 +928,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) t.Run("Stays out-of-sync if received new head, but lags behind pool", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ @@ -998,13 +973,11 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) // 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) *mockNodeClient[types.ID, Head] { - rpc := newMockNodeClient[types.ID, Head](t) + 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 := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() + sub := newSub(t) rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() return rpc } @@ -1053,6 +1026,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { sub.On("Unsubscribe").Once() rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() + // unreachable rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() node.declareOutOfSync(syncStatusNoNewHead) @@ -1076,9 +1050,8 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() - sub := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() + sub := newSub(t) + ch := make(chan Head) rpc.On("SubscribeToFinalizedHeads", mock.Anything).Run(func(args mock.Arguments) { close(ch) @@ -1168,9 +1141,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { newAliveNode := func(t *testing.T, opts testNodeOpts) testNode { node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil).Once() - // disconnects all on transfer to unreachable - opts.rpc.On("DisconnectAll") + opts.rpc.On("Close").Return(nil) node.setState(nodeStateAlive) return node @@ -1184,7 +1155,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on failed redial, keeps trying", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ @@ -1200,7 +1171,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on failed chainID verification, keep trying", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ @@ -1219,7 +1190,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on chain ID mismatch transitions to invalidChainID", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) node := newAliveNode(t, testNodeOpts{ @@ -1230,6 +1201,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { 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 @@ -1237,7 +1209,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on syncing status check failure, keeps trying", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ @@ -1258,7 +1230,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on syncing, transitions to syncing state", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newAliveNode(t, testNodeOpts{ rpc: rpc, @@ -1280,7 +1252,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on successful verification becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newAliveNode(t, testNodeOpts{ rpc: rpc, @@ -1289,10 +1261,8 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) 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(false, nil) - setupRPCForAliveLoop(t, rpc) node.declareUnreachable() @@ -1302,7 +1272,7 @@ func TestUnit_NodeLifecycle_unreachableLoop(t *testing.T) { }) t.Run("on successful verification without isSyncing becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newAliveNode(t, testNodeOpts{ rpc: rpc, @@ -1326,8 +1296,7 @@ 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).Once() - opts.rpc.On("DisconnectAll") + opts.rpc.On("Close").Return(nil) node.setState(nodeStateDialed) return node @@ -1341,7 +1310,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) t.Run("on invalid dial becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newDialedNode(t, testNodeOpts{ rpc: rpc, @@ -1350,6 +1319,8 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { 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 @@ -1357,7 +1328,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) t.Run("on failed chainID call becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ @@ -1371,6 +1342,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { // 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 { @@ -1379,7 +1351,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) t.Run("on chainID mismatch keeps trying", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) @@ -1392,6 +1364,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { 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 { @@ -1400,7 +1373,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) t.Run("on successful verification without isSyncing becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) node := newDialedNode(t, testNodeOpts{ @@ -1409,12 +1382,10 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() - rpc.On("Dial", mock.Anything).Return(nil).Once() + setupRPCForAliveLoop(t, rpc) rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil).Once() rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() - setupRPCForAliveLoop(t, rpc) - node.declareInvalidChainID() tests.AssertEventually(t, func() bool { return node.State() == nodeStateAlive @@ -1422,7 +1393,7 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) t.Run("on successful verification becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) node := newDialedNode(t, testNodeOpts{ @@ -1432,7 +1403,6 @@ func TestUnit_NodeLifecycle_invalidChainIDLoop(t *testing.T) { }) defer func() { assert.NoError(t, node.close()) }() - rpc.On("Dial", mock.Anything).Return(nil).Once() 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() @@ -1451,13 +1421,13 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { newNode := func(t *testing.T, opts testNodeOpts) testNode { node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil).Once() + opts.rpc.On("Close").Return(nil) return node } t.Run("if fails on initial dial, becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newNode(t, testNodeOpts{ @@ -1468,8 +1438,6 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { defer func() { assert.NoError(t, node.close()) }() rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")) - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll") err := node.Start(tests.Context(t)) assert.NoError(t, err) tests.AssertLogEventually(t, observedLogs, "Dial failed: Node is unreachable") @@ -1479,7 +1447,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) t.Run("if chainID verification fails, becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newNode(t, testNodeOpts{ @@ -1493,8 +1461,6 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { rpc.On("ChainID", mock.Anything).Run(func(_ mock.Arguments) { assert.Equal(t, nodeStateDialed, node.State()) }).Return(nodeChainID, errors.New("failed to get chain id")) - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll") err := node.Start(tests.Context(t)) assert.NoError(t, err) tests.AssertLogEventually(t, observedLogs, "Failed to verify chain ID for node") @@ -1504,7 +1470,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) t.Run("on chain ID mismatch transitions to invalidChainID", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) node := newNode(t, testNodeOpts{ @@ -1514,9 +1480,8 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { defer func() { assert.NoError(t, node.close()) }() rpc.On("Dial", mock.Anything).Return(nil) + rpc.On("ChainID", mock.Anything).Return(rpcChainID, nil) - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll") err := node.Start(tests.Context(t)) assert.NoError(t, err) tests.AssertEventually(t, func() bool { @@ -1525,7 +1490,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) t.Run("if syncing verification fails, becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newNode(t, testNodeOpts{ @@ -1537,13 +1502,11 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { 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")) - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll") - // fail to redial to stay in unreachable state rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")) err := node.Start(tests.Context(t)) assert.NoError(t, err) @@ -1554,7 +1517,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) t.Run("on isSyncing transitions to syncing", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) node := newNode(t, testNodeOpts{ rpc: rpc, @@ -1564,10 +1527,9 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { 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) - // disconnects all on transfer to unreachable - rpc.On("DisconnectAll") err := node.Start(tests.Context(t)) assert.NoError(t, err) tests.AssertEventually(t, func() bool { @@ -1576,7 +1538,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) t.Run("on successful verification becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newNode(t, testNodeOpts{ rpc: rpc, @@ -1585,10 +1547,8 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) 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(false, nil) - setupRPCForAliveLoop(t, rpc) err := node.Start(tests.Context(t)) @@ -1599,7 +1559,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) t.Run("on successful verification without isSyncing becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newNode(t, testNodeOpts{ rpc: rpc, @@ -1607,9 +1567,7 @@ func TestUnit_NodeLifecycle_start(t *testing.T) { }) 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) err := node.Start(tests.Context(t)) @@ -1765,8 +1723,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { newDialedNode := func(t *testing.T, opts testNodeOpts) testNode { opts.config.nodeIsSyncingEnabled = true node := newTestNode(t, opts) - opts.rpc.On("Close").Return(nil).Once() - opts.rpc.On("DisconnectAll") + opts.rpc.On("Close").Return(nil) node.setState(nodeStateDialed) return node @@ -1780,7 +1737,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) t.Run("on invalid dial becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newDialedNode(t, testNodeOpts{ rpc: rpc, @@ -1789,6 +1746,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { 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 @@ -1796,7 +1754,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) t.Run("on failed chainID call becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ @@ -1807,6 +1765,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { 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() @@ -1818,7 +1777,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) t.Run("on chainID mismatch transitions to invalidChainID", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.NewIDFromInt(10) rpcChainID := types.NewIDFromInt(11) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) @@ -1830,6 +1789,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { 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) @@ -1839,7 +1799,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) t.Run("on failed Syncing check - becomes unreachable", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ @@ -1855,6 +1815,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { 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 { @@ -1863,7 +1824,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) t.Run("on IsSyncing - keeps trying", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ @@ -1876,6 +1837,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { 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 { @@ -1884,7 +1846,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) t.Run("on successful verification becomes alive", func(t *testing.T) { t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) nodeChainID := types.RandomID() node := newDialedNode(t, testNodeOpts{ rpc: rpc, @@ -1893,6 +1855,7 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { 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() @@ -1980,7 +1943,7 @@ func TestNode_State(t *testing.T) { } for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { - rpc := newMockNodeClient[types.ID, Head](t) + rpc := newMockRPCClient[types.ID, Head](t) rpc.On("GetInterceptedChainInfo").Return(tc.NodeChainInfo, tc.PoolChainInfo).Once() node := newTestNode(t, testNodeOpts{ config: testNodeConfig{ diff --git a/common/client/node_selector.go b/common/client/node_selector.go index 4aae3734eea..372b521bb1c 100644 --- a/common/client/node_selector.go +++ b/common/client/node_selector.go @@ -15,30 +15,28 @@ const ( type NodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + RPC any, ] interface { // Select returns a Node, or nil if none can be selected. // Implementation must be thread-safe. - Select() Node[CHAIN_ID, HEAD, RPC] + Select() Node[CHAIN_ID, RPC] // Name returns the strategy name, e.g. "HighestHead" or "RoundRobin" Name() string } func newNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](selectionMode string, nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] { + RPC any, +](selectionMode string, nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { switch selectionMode { case NodeSelectionModeHighestHead: - return NewHighestHeadNodeSelector[CHAIN_ID, HEAD, RPC](nodes) + return NewHighestHeadNodeSelector[CHAIN_ID, RPC](nodes) case NodeSelectionModeRoundRobin: - return NewRoundRobinSelector[CHAIN_ID, HEAD, RPC](nodes) + return NewRoundRobinSelector[CHAIN_ID, RPC](nodes) case NodeSelectionModeTotalDifficulty: - return NewTotalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC](nodes) + return NewTotalDifficultyNodeSelector[CHAIN_ID, RPC](nodes) case NodeSelectionModePriorityLevel: - return NewPriorityLevelNodeSelector[CHAIN_ID, HEAD, RPC](nodes) + 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 index 25a931fc01b..454584a77e1 100644 --- a/common/client/node_selector_highest_head.go +++ b/common/client/node_selector_highest_head.go @@ -8,21 +8,19 @@ import ( type highestHeadNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -] []Node[CHAIN_ID, HEAD, RPC] + RPC any, +] []Node[CHAIN_ID, RPC] func NewHighestHeadNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] { - return highestHeadNodeSelector[CHAIN_ID, HEAD, RPC](nodes) + RPC any, +](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { + return highestHeadNodeSelector[CHAIN_ID, RPC](nodes) } -func (s highestHeadNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] { +func (s highestHeadNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { var highestHeadNumber int64 = math.MinInt64 - var highestHeadNodes []Node[CHAIN_ID, HEAD, RPC] + var highestHeadNodes []Node[CHAIN_ID, RPC] for _, n := range s { state, currentChainInfo := n.StateAndLatest() currentHeadNumber := currentChainInfo.BlockNumber @@ -37,6 +35,6 @@ func (s highestHeadNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HE return firstOrHighestPriority(highestHeadNodes) } -func (s highestHeadNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string { +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 index e245924589c..ebee3f403e2 100644 --- a/common/client/node_selector_highest_head_test.go +++ b/common/client/node_selector_highest_head_test.go @@ -9,19 +9,19 @@ import ( ) func TestHighestHeadNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModeHighestHead, nil) + 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 NodeClient[types.ID, Head] + type nodeClient RPCClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + var nodes []Node[types.ID, nodeClient] for i := 0; i < 3; i++ { - node := newMockNode[types.ID, Head, nodeClient](t) + node := newMockNode[types.ID, nodeClient](t) if i == 0 { // first node is out of sync node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: int64(-1)}) @@ -36,11 +36,11 @@ func TestHighestHeadNodeSelector(t *testing.T) { nodes = append(nodes, node) } - selector := newNodeSelector[types.ID, Head, nodeClient](NodeSelectionModeHighestHead, nodes) + 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, Head, nodeClient](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)) @@ -51,7 +51,7 @@ func TestHighestHeadNodeSelector(t *testing.T) { }) t.Run("another best node", func(t *testing.T) { - node := newMockNode[types.ID, Head, nodeClient](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)) @@ -62,13 +62,13 @@ func TestHighestHeadNodeSelector(t *testing.T) { }) t.Run("nodes never update latest block number", func(t *testing.T) { - node1 := newMockNode[types.ID, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2}) + selector := newNodeSelector(NodeSelectionModeHighestHead, []Node[types.ID, nodeClient]{node1, node2}) assert.Same(t, node1, selector.Select()) }) } @@ -76,11 +76,11 @@ func TestHighestHeadNodeSelector(t *testing.T) { func TestHighestHeadNodeSelector_None(t *testing.T) { t.Parallel() - type nodeClient NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + type nodeClient RPCClient[types.ID, Head] + var nodes []Node[types.ID, nodeClient] for i := 0; i < 3; i++ { - node := newMockNode[types.ID, Head, nodeClient](t) + node := newMockNode[types.ID, nodeClient](t) if i == 0 { // first node is out of sync node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: int64(-1)}) @@ -98,12 +98,12 @@ func TestHighestHeadNodeSelector_None(t *testing.T) { func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { t.Parallel() - type nodeClient NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + 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, Head, nodeClient](t) + 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) @@ -114,61 +114,61 @@ func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { }) t.Run("same head but different order", func(t *testing.T) { - node1 := newMockNode[types.ID, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2, node3} + 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, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2, node3} + 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, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2, node3, node4} + 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 index 45cc62de077..6d6784fb216 100644 --- a/common/client/node_selector_priority_level.go +++ b/common/client/node_selector_priority_level.go @@ -10,34 +10,31 @@ import ( type priorityLevelNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + RPC any, ] struct { - nodes []Node[CHAIN_ID, HEAD, RPC] + nodes []Node[CHAIN_ID, RPC] roundRobinCount []atomic.Uint32 } type nodeWithPriority[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + RPC any, ] struct { - node Node[CHAIN_ID, HEAD, RPC] + node Node[CHAIN_ID, RPC] priority int32 } func NewPriorityLevelNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] { - return &priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]{ + 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, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] { +func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { nodes := s.getHighestPriorityAliveTier() if len(nodes) == 0 { @@ -52,17 +49,17 @@ func (s priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, return nodes[idx].node } -func (s priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string { +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, HEAD, RPC]) getHighestPriorityAliveTier() []nodeWithPriority[CHAIN_ID, HEAD, RPC] { - var nodes []nodeWithPriority[CHAIN_ID, HEAD, RPC] +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, HEAD, RPC]{n, n.Order()}) + nodes = append(nodes, nodeWithPriority[CHAIN_ID, RPC]{n, n.Order()}) } } @@ -76,14 +73,13 @@ func (s priorityLevelNodeSelector[CHAIN_ID, HEAD, RPC]) getHighestPriorityAliveT // removeLowerTiers take a slice of nodeWithPriority[CHAIN_ID, BLOCK_HASH, HEAD, RPC] and keeps only the highest tier func removeLowerTiers[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []nodeWithPriority[CHAIN_ID, HEAD, RPC]) []nodeWithPriority[CHAIN_ID, HEAD, RPC] { + 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, HEAD, RPC] + var nodes2 []nodeWithPriority[CHAIN_ID, RPC] currentPriority := nodes[len(nodes)-1].priority for _, n := range nodes { @@ -98,9 +94,8 @@ func removeLowerTiers[ // nrOfPriorityTiers calculates the total number of priority tiers func nrOfPriorityTiers[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []Node[CHAIN_ID, HEAD, RPC]) int32 { + RPC any, +](nodes []Node[CHAIN_ID, RPC]) int32 { highestPriority := int32(0) for _, n := range nodes { priority := n.Order() @@ -114,11 +109,10 @@ func nrOfPriorityTiers[ // firstOrHighestPriority takes a list of nodes and returns the first one with the highest priority func firstOrHighestPriority[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []Node[CHAIN_ID, HEAD, RPC]) Node[CHAIN_ID, HEAD, RPC] { + RPC any, +](nodes []Node[CHAIN_ID, RPC]) Node[CHAIN_ID, RPC] { hp := int32(math.MaxInt32) - var node Node[CHAIN_ID, HEAD, RPC] + var node Node[CHAIN_ID, RPC] for _, n := range nodes { if n.Order() < hp { hp = n.Order() diff --git a/common/client/node_selector_priority_level_test.go b/common/client/node_selector_priority_level_test.go index 15a7a7ac60b..67aac97be1b 100644 --- a/common/client/node_selector_priority_level_test.go +++ b/common/client/node_selector_priority_level_test.go @@ -9,14 +9,14 @@ import ( ) func TestPriorityLevelNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModePriorityLevel, nil) + 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 NodeClient[types.ID, Head] + type nodeClient RPCClient[types.ID, Head] type testNode struct { order int32 state nodeState @@ -66,9 +66,9 @@ func TestPriorityLevelNodeSelector(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - var nodes []Node[types.ID, Head, nodeClient] + var nodes []Node[types.ID, nodeClient] for _, tn := range tc.nodes { - node := newMockNode[types.ID, Head, nodeClient](t) + node := newMockNode[types.ID, nodeClient](t) node.On("State").Return(tn.state) node.On("Order").Return(tn.order) nodes = append(nodes, node) diff --git a/common/client/node_selector_round_robin.go b/common/client/node_selector_round_robin.go index 5cdad7f52ee..18cea03ebd5 100644 --- a/common/client/node_selector_round_robin.go +++ b/common/client/node_selector_round_robin.go @@ -8,25 +8,23 @@ import ( type roundRobinSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], + RPC any, ] struct { - nodes []Node[CHAIN_ID, HEAD, RPC] + nodes []Node[CHAIN_ID, RPC] roundRobinCount atomic.Uint32 } func NewRoundRobinSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] { - return &roundRobinSelector[CHAIN_ID, HEAD, RPC]{ + RPC any, +](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { + return &roundRobinSelector[CHAIN_ID, RPC]{ nodes: nodes, } } -func (s *roundRobinSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] { - var liveNodes []Node[CHAIN_ID, HEAD, RPC] +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) @@ -45,6 +43,6 @@ func (s *roundRobinSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, return liveNodes[idx] } -func (s *roundRobinSelector[CHAIN_ID, HEAD, RPC]) Name() string { +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 index e5078d858f1..189b58da9ea 100644 --- a/common/client/node_selector_round_robin_test.go +++ b/common/client/node_selector_round_robin_test.go @@ -9,18 +9,18 @@ import ( ) func TestRoundRobinNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModeRoundRobin, nil) + 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 NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + type nodeClient RPCClient[types.ID, Head] + var nodes []Node[types.ID, nodeClient] for i := 0; i < 3; i++ { - node := newMockNode[types.ID, Head, nodeClient](t) + node := newMockNode[types.ID, nodeClient](t) if i == 0 { // first node is out of sync node.On("State").Return(nodeStateOutOfSync) @@ -41,11 +41,11 @@ func TestRoundRobinNodeSelector(t *testing.T) { func TestRoundRobinNodeSelector_None(t *testing.T) { t.Parallel() - type nodeClient NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + type nodeClient RPCClient[types.ID, Head] + var nodes []Node[types.ID, nodeClient] for i := 0; i < 3; i++ { - node := newMockNode[types.ID, Head, nodeClient](t) + node := newMockNode[types.ID, nodeClient](t) if i == 0 { // first node is out of sync node.On("State").Return(nodeStateOutOfSync) diff --git a/common/client/node_selector_test.go b/common/client/node_selector_test.go index 226cb67168d..f652bfc50ad 100644 --- a/common/client/node_selector_test.go +++ b/common/client/node_selector_test.go @@ -12,7 +12,7 @@ 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, Head, NodeClient[types.ID, Head]]("unknown", nil) + _ = 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 index 6b45e75528b..7defcd741ca 100644 --- a/common/client/node_selector_total_difficulty.go +++ b/common/client/node_selector_total_difficulty.go @@ -8,23 +8,21 @@ import ( type totalDifficultyNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -] []Node[CHAIN_ID, HEAD, RPC] + RPC any, +] []Node[CHAIN_ID, RPC] func NewTotalDifficultyNodeSelector[ CHAIN_ID types.ID, - HEAD Head, - RPC NodeClient[CHAIN_ID, HEAD], -](nodes []Node[CHAIN_ID, HEAD, RPC]) NodeSelector[CHAIN_ID, HEAD, RPC] { - return totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC](nodes) + RPC any, +](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { + return totalDifficultyNodeSelector[CHAIN_ID, RPC](nodes) } -func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HEAD, RPC] { +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, HEAD, RPC] - var aliveNodes []Node[CHAIN_ID, HEAD, RPC] + var nodes []Node[CHAIN_ID, RPC] + var aliveNodes []Node[CHAIN_ID, RPC] for _, n := range s { state, currentChainInfo := n.StateAndLatest() @@ -50,6 +48,6 @@ func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID return firstOrHighestPriority(nodes) } -func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Name() string { +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 index 0bc214918d7..ed45cfdf9ac 100644 --- a/common/client/node_selector_total_difficulty_test.go +++ b/common/client/node_selector_total_difficulty_test.go @@ -10,18 +10,18 @@ import ( ) func TestTotalDifficultyNodeSelectorName(t *testing.T) { - selector := newNodeSelector[types.ID, Head, NodeClient[types.ID, Head]](NodeSelectionModeTotalDifficulty, nil) + 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 NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + type nodeClient RPCClient[types.ID, Head] + var nodes []Node[types.ID, nodeClient] for i := 0; i < 3; i++ { - node := newMockNode[types.ID, Head, nodeClient](t) + node := newMockNode[types.ID, nodeClient](t) if i == 0 { // first node is out of sync node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: -1}) @@ -40,7 +40,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { assert.Same(t, nodes[2], selector.Select()) t.Run("stick to the same node", func(t *testing.T) { - node := newMockNode[types.ID, Head, nodeClient](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)) @@ -51,7 +51,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { }) t.Run("another best node", func(t *testing.T) { - node := newMockNode[types.ID, Head, nodeClient](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)) @@ -62,13 +62,13 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { }) t.Run("nodes never update latest block number", func(t *testing.T) { - node1 := newMockNode[types.ID, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2} + nodes := []Node[types.ID, nodeClient]{node1, node2} selector := newNodeSelector(NodeSelectionModeTotalDifficulty, nodes) assert.Same(t, node1, selector.Select()) @@ -78,11 +78,11 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { func TestTotalDifficultyNodeSelector_None(t *testing.T) { t.Parallel() - type nodeClient NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + type nodeClient RPCClient[types.ID, Head] + var nodes []Node[types.ID, nodeClient] for i := 0; i < 3; i++ { - node := newMockNode[types.ID, Head, nodeClient](t) + 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}) @@ -100,12 +100,12 @@ func TestTotalDifficultyNodeSelector_None(t *testing.T) { func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Parallel() - type nodeClient NodeClient[types.ID, Head] - var nodes []Node[types.ID, Head, nodeClient] + 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, Head, nodeClient](t) + 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) @@ -116,61 +116,61 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { }) t.Run("same td but different order", func(t *testing.T) { - node1 := newMockNode[types.ID, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2, node3} + 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, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2, node3} + 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, Head, nodeClient](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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient](t) + 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, Head, nodeClient]{node1, node2, node3, node4} + 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 index 3b971e84902..6d98c2d9ea4 100644 --- a/common/client/node_test.go +++ b/common/client/node_test.go @@ -20,6 +20,11 @@ type testNodeConfig struct { 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 { @@ -55,20 +60,20 @@ func (n testNodeConfig) DeathDeclarationDelay() time.Duration { } type testNode struct { - *node[types.ID, Head, NodeClient[types.ID, Head]] + *node[types.ID, Head, RPCClient[types.ID, Head]] } type testNodeOpts struct { config testNodeConfig chainConfig clientMocks.ChainConfig lggr logger.Logger - wsuri url.URL + wsuri *url.URL httpuri *url.URL name string - id int32 + id int chainID types.ID nodeOrder int32 - rpc *mockNodeClient[types.ID, Head] + rpc *mockRPCClient[types.ID, Head] chainFamily string } @@ -93,10 +98,10 @@ func newTestNode(t *testing.T, opts testNodeOpts) testNode { opts.id = 42 } - nodeI := NewNode[types.ID, Head, NodeClient[types.ID, Head]](opts.config, opts.chainConfig, opts.lggr, + 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, NodeClient[types.ID, Head]]), + nodeI.(*node[types.ID, Head, RPCClient[types.ID, Head]]), } } diff --git a/common/client/poller.go b/common/client/poller.go index d6080722c5c..eeb6c3af576 100644 --- a/common/client/poller.go +++ b/common/client/poller.go @@ -2,7 +2,6 @@ package client import ( "context" - "sync" "time" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -15,83 +14,80 @@ import ( // 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.StateMachine + services.Service + eng *services.Engine + pollingInterval time.Duration pollingFunc func(ctx context.Context) (T, error) pollingTimeout time.Duration - logger logger.Logger channel chan<- T errCh chan error - - stopCh services.StopChan - wg sync.WaitGroup } // 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, logger logger.Logger) (Poller[T], <-chan T) { +](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, lggr logger.Logger) (Poller[T], <-chan T) { channel := make(chan T) - return Poller[T]{ + p := Poller[T]{ pollingInterval: pollingInterval, pollingFunc: pollingFunc, pollingTimeout: pollingTimeout, channel: channel, - logger: logger, errCh: make(chan error), - stopCh: make(chan struct{}), - }, channel + } + 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() error { - return p.StartOnce("Poller", func() error { - p.wg.Add(1) - go p.pollingLoop() - return nil - }) +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.StopOnce("Poller", func() error { - close(p.stopCh) - p.wg.Wait() - close(p.errCh) - close(p.channel) - return nil - }) + _ = 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() { - defer p.wg.Done() - +func (p *Poller[T]) pollingLoop(ctx context.Context) { ticker := time.NewTicker(p.pollingInterval) defer ticker.Stop() for { select { - case <-p.stopCh: + case <-ctx.Done(): return case <-ticker.C: // Set polling timeout - pollingCtx, cancelPolling := p.stopCh.CtxCancel(context.WithTimeout(context.Background(), p.pollingTimeout)) + pollingCtx, cancelPolling := context.WithTimeout(ctx, p.pollingTimeout) // Execute polling function result, err := p.pollingFunc(pollingCtx) cancelPolling() if err != nil { - p.logger.Warnf("polling error: %v", err) + p.eng.Warnf("polling error: %v", err) continue } // Send result to channel or block if channel is full select { case p.channel <- result: - case <-p.stopCh: + case <-ctx.Done(): return } } diff --git a/common/client/poller_test.go b/common/client/poller_test.go index 91af579307b..930b101751c 100644 --- a/common/client/poller_test.go +++ b/common/client/poller_test.go @@ -20,20 +20,22 @@ 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() + err := poller.Start(ctx) require.NoError(t, err) - err = poller.Start() + 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{} @@ -50,7 +52,7 @@ func Test_Poller(t *testing.T) { // Create poller and start to receive data poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) - require.NoError(t, poller.Start()) + require.NoError(t, poller.Start(ctx)) defer poller.Unsubscribe() // Receive updates from the poller @@ -63,6 +65,7 @@ func Test_Poller(t *testing.T) { }) 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{} @@ -77,7 +80,7 @@ func Test_Poller(t *testing.T) { // Create poller and subscribe to receive data poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, olggr) - require.NoError(t, poller.Start()) + require.NoError(t, poller.Start(ctx)) defer poller.Unsubscribe() // Ensure that all errors were logged as expected @@ -94,6 +97,7 @@ func Test_Poller(t *testing.T) { }) 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() @@ -108,7 +112,7 @@ func Test_Poller(t *testing.T) { // Create poller and subscribe to receive data poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) - require.NoError(t, poller.Start()) + require.NoError(t, poller.Start(ctx)) defer poller.Unsubscribe() // Ensure that timeout errors were logged as expected @@ -119,6 +123,7 @@ func Test_Poller(t *testing.T) { }) 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) { @@ -137,7 +142,7 @@ func Test_Poller(t *testing.T) { // Create poller and subscribe to receive data poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) - require.NoError(t, poller.Start()) + require.NoError(t, poller.Start(ctx)) // Unsubscribe while blocked in polling function <-wait @@ -167,8 +172,9 @@ func Test_Poller_Unsubscribe(t *testing.T) { } 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() + err := poller.Start(ctx) require.NoError(t, err) <-channel @@ -177,8 +183,9 @@ func Test_Poller_Unsubscribe(t *testing.T) { }) 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() + err := poller.Start(ctx) require.NoError(t, err) poller.Unsubscribe() diff --git a/common/client/send_only_node.go b/common/client/send_only_node.go index 85e3a6fc2cc..0a1715fa191 100644 --- a/common/client/send_only_node.go +++ b/common/client/send_only_node.go @@ -17,13 +17,13 @@ type sendOnlyClient[ ] interface { Close() ChainID(context.Context) (CHAIN_ID, error) - DialHTTP() error + Dial(ctx context.Context) error } // SendOnlyNode represents one node used as a sendonly type SendOnlyNode[ CHAIN_ID types.ID, - RPC sendOnlyClient[CHAIN_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 @@ -97,7 +97,7 @@ func (s *sendOnlyNode[CHAIN_ID, RPC]) start(startCtx context.Context) { panic(fmt.Sprintf("cannot dial node with state %v", s.state)) } - err := s.rpc.DialHTTP() + 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) diff --git a/common/client/send_only_node_test.go b/common/client/send_only_node_test.go index 79f4bfd60e3..532946da48f 100644 --- a/common/client/send_only_node_test.go +++ b/common/client/send_only_node_test.go @@ -46,7 +46,7 @@ func TestStartSendOnlyNode(t *testing.T) { client := newMockSendOnlyClient[types.ID](t) client.On("Close").Once() expectedError := errors.New("some http error") - client.On("DialHTTP").Return(expectedError).Once() + 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()) }() @@ -61,7 +61,7 @@ func TestStartSendOnlyNode(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) client := newMockSendOnlyClient[types.ID](t) client.On("Close").Once() - client.On("DialHTTP").Return(nil).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()) }() @@ -76,7 +76,7 @@ func TestStartSendOnlyNode(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) client := newMockSendOnlyClient[types.ID](t) client.On("Close").Once() - client.On("DialHTTP").Return(nil) + client.On("Dial", mock.Anything).Return(nil) expectedError := errors.New("failed to get chain ID") chainID := types.RandomID() const failuresCount = 2 @@ -100,7 +100,7 @@ func TestStartSendOnlyNode(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) client := newMockSendOnlyClient[types.ID](t) client.On("Close").Once() - client.On("DialHTTP").Return(nil).Once() + client.On("Dial", mock.Anything).Return(nil).Once() configuredChainID := types.NewIDFromInt(11) rpcChainID := types.NewIDFromInt(20) const failuresCount = 2 @@ -123,7 +123,7 @@ func TestStartSendOnlyNode(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) client := newMockSendOnlyClient[types.ID](t) client.On("Close").Once() - client.On("DialHTTP").Return(nil).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) diff --git a/common/client/transaction_sender.go b/common/client/transaction_sender.go new file mode 100644 index 00000000000..9365a82b290 --- /dev/null +++ b/common/client/transaction_sender.go @@ -0,0 +1,280 @@ +package client + +import ( + "context" + "errors" + "fmt" + "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"}) +) + +// TxErrorClassifier - defines interface of a function that transforms raw RPC error into the SendTxReturnCode enum +// (e.g. Successful, Fatal, Retryable, etc.) +type TxErrorClassifier[TX any] func(tx TX, err error) SendTxReturnCode + +type sendTxResult struct { + Err error + ResultCode SendTxReturnCode +} + +const sendTxQuorum = 0.7 + +// SendTxRPCClient - defines interface of an RPC used by TransactionSender to broadcast transaction +type SendTxRPCClient[TX any] interface { + // SendTransaction errors returned should include name or other unique identifier of the RPC + SendTransaction(ctx context.Context, tx TX) error +} + +func NewTransactionSender[TX any, CHAIN_ID types.ID, RPC SendTxRPCClient[TX]]( + lggr logger.Logger, + chainID CHAIN_ID, + chainFamily string, + multiNode *MultiNode[CHAIN_ID, RPC], + txErrorClassifier TxErrorClassifier[TX], + sendTxSoftTimeout time.Duration, +) *TransactionSender[TX, CHAIN_ID, RPC] { + if sendTxSoftTimeout == 0 { + sendTxSoftTimeout = QueryTimeout / 2 + } + return &TransactionSender[TX, CHAIN_ID, RPC]{ + chainID: chainID, + chainFamily: chainFamily, + lggr: logger.Sugared(lggr).Named("TransactionSender").With("chainID", chainID.String()), + multiNode: multiNode, + txErrorClassifier: txErrorClassifier, + sendTxSoftTimeout: sendTxSoftTimeout, + chStop: make(services.StopChan), + } +} + +type TransactionSender[TX any, CHAIN_ID types.ID, RPC SendTxRPCClient[TX]] struct { + services.StateMachine + chainID CHAIN_ID + chainFamily string + lggr logger.SugaredLogger + multiNode *MultiNode[CHAIN_ID, RPC] + txErrorClassifier TxErrorClassifier[TX] + 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, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) (SendTxReturnCode, error) { + txResults := make(chan sendTxResult) + txResultsToReport := make(chan sendTxResult) + primaryNodeWg := sync.WaitGroup{} + + if txSender.State() != "Started" { + return Retryable, errors.New("TransactionSender not started") + } + + healthyNodesNum := 0 + err := txSender.multiNode.DoAll(ctx, func(ctx context.Context, rpc RPC, isSendOnly bool) { + if isSendOnly { + txSender.wg.Add(1) + go func() { + 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) + }() + return + } + + // Primary Nodes + healthyNodesNum++ + primaryNodeWg.Add(1) + go func() { + defer primaryNodeWg.Done() + result := txSender.broadcastTxAsync(ctx, rpc, tx) + select { + case <-ctx.Done(): + return + case txResults <- result: + } + + select { + case <-ctx.Done(): + return + case txResultsToReport <- result: + } + }() + }) + + // 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 { + return Retryable, err + } + + txSender.wg.Add(1) + go txSender.reportSendTxAnomalies(tx, txResultsToReport) + + return txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) +} + +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) sendTxResult { + txErr := rpc.SendTransaction(ctx, tx) + txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", txErr) + resultCode := txSender.txErrorClassifier(tx, txErr) + if !slices.Contains(sendTxSuccessfulCodes, resultCode) { + txSender.lggr.Warnw("RPC returned error", "tx", tx, "err", txErr) + } + return sendTxResult{Err: txErr, ResultCode: resultCode} +} + +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) reportSendTxAnomalies(tx TX, txResults <-chan sendTxResult) { + defer txSender.wg.Done() + resultsByCode := sendTxResults{} + // txResults eventually will be closed + for txResult := range txResults { + resultsByCode[txResult.ResultCode] = append(resultsByCode[txResult.ResultCode], txResult.Err) + } + + _, _, criticalErr := aggregateTxResults(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 map[SendTxReturnCode][]error + +func aggregateTxResults(resultsByCode sendTxResults) (returnCode SendTxReturnCode, txResult error, err error) { + severeCode, severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) + successCode, 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 successCode, successResults[0], errors.New(errMsg) + } + + // other errors are temporary - we are safe to return success + return successCode, successResults[0], nil + } + + if hasSevereErrors { + return severeCode, severeErrors[0], nil + } + + // return temporary error + for code, result := range resultsByCode { + return code, result[0], nil + } + + err = fmt.Errorf("expected at least one response on SendTransaction") + return Retryable, err, err +} + +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan sendTxResult) (SendTxReturnCode, error) { + if healthyNodesNum == 0 { + return Retryable, ErroringNodeError + } + ctx, cancel := txSender.chStop.Ctx(ctx) + defer cancel() + requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) + errorsByCode := sendTxResults{} + 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 Retryable, ctx.Err() + case result := <-txResults: + errorsByCode[result.ResultCode] = append(errorsByCode[result.ResultCode], result.Err) + resultsCount++ + if slices.Contains(sendTxSuccessfulCodes, result.ResultCode) || 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 + returnCode, result, _ := aggregateTxResults(errorsByCode) + return returnCode, result +} + +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) Start(ctx context.Context) error { + return txSender.StartOnce("TransactionSender", func() error { + return nil + }) +} + +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) Close() error { + return txSender.StopOnce("TransactionSender", func() error { + 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) (K, V, bool) { + for _, k := range keys { + if v, ok := set[k]; ok { + return k, v, true + } + } + var zeroK K + var zeroV V + return zeroK, zeroV, false +} diff --git a/common/client/transaction_sender_test.go b/common/client/transaction_sender_test.go new file mode 100644 index 00000000000..5517a0c8dda --- /dev/null +++ b/common/client/transaction_sender_test.go @@ -0,0 +1,384 @@ +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/utils/tests" + "github.com/smartcontractkit/chainlink/v2/common/types" +) + +type sendTxMultiNode struct { + *MultiNode[types.ID, SendTxRPCClient[any]] +} + +type sendTxRPC struct { + sendTxRun func(args mock.Arguments) + sendTxErr error +} + +var _ SendTxRPCClient[any] = (*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) error { + if rpc.sendTxRun != nil { + rpc.sendTxRun(mock.Arguments{ctx}) + } + return rpc.sendTxErr +} + +func newTestTransactionSender(t *testing.T, chainID types.ID, lggr logger.Logger, + nodes []Node[types.ID, SendTxRPCClient[any]], + sendOnlyNodes []SendOnlyNode[types.ID, SendTxRPCClient[any]], +) (*sendTxMultiNode, *TransactionSender[any, types.ID, SendTxRPCClient[any]]) { + mn := sendTxMultiNode{NewMultiNode[types.ID, SendTxRPCClient[any]]( + lggr, NodeSelectionModeRoundRobin, 0, nodes, sendOnlyNodes, chainID, "chainFamily", 0)} + err := mn.StartOnce("startedTestMultiNode", func() error { return nil }) + require.NoError(t, err) + + txSender := NewTransactionSender[any, types.ID, SendTxRPCClient[any]](lggr, chainID, mn.chainFamily, mn.MultiNode, classifySendTxError, tests.TestInterval) + err = txSender.Start(tests.Context(t)) + require.NoError(t, err) + + t.Cleanup(func() { + err := mn.Close() + if err != nil { + // Allow MultiNode to be closed early for testing + require.EqualError(t, err, "MultiNode has already been stopped: already stopped") + } + err = txSender.Close() + if err != nil { + // Allow TransactionSender to be closed early for testing + require.EqualError(t, err, "TransactionSender has already been stopped: already stopped") + } + }) + 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, SendTxRPCClient[any]] { + rpc := newSendTxRPC(txErr, sendTxRun) + node := newMockNode[types.ID, SendTxRPCClient[any]](t) + node.On("String").Return("node name").Maybe() + node.On("RPC").Return(rpc).Maybe() + node.On("State").Return(state).Maybe() + node.On("Close").Return(nil).Once() + return node + } + + newNode := func(t *testing.T, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, SendTxRPCClient[any]] { + return newNodeWithState(t, nodeStateAlive, txErr, sendTxRun) + } + + t.Run("Fails if there is no nodes available", func(t *testing.T) { + lggr, _ := logger.TestObserved(t, zap.DebugLevel) + _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, nil, nil) + _, err := txSender.SendTransaction(tests.Context(t), nil) + assert.EqualError(t, err, 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, SendTxRPCClient[any]]{mainNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{newNode(t, errors.New("unexpected error"), nil)}) + + result, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.ErrorIs(t, sendErr, expectedError) + require.Equal(t, Fatal, result) + 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, SendTxRPCClient[any]]{mainNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{newNode(t, errors.New("unexpected error"), nil)}) + + result, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.NoError(t, sendErr) + require.Equal(t, Successful, result) + 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.TestObserved(t, zap.DebugLevel) + + _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, + []Node[types.ID, SendTxRPCClient[any]]{mainNode}, nil) + + requestContext, cancel := context.WithCancel(tests.Context(t)) + cancel() + _, sendErr := txSender.SendTransaction(requestContext, nil) + require.EqualError(t, sendErr, "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.TestObserved(t, zap.DebugLevel) + + _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, nil) + _, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.EqualError(t, sendErr, 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) + mn, txSender := newTestTransactionSender(t, chainID, lggr, + []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{slowSendOnly}) + + rtnCode, err := txSender.SendTransaction(tests.Context(t), nil) + require.NoError(t, err) + require.Equal(t, Successful, rtnCode) + require.NoError(t, mn.Close()) + }) + t.Run("Fails when multinode is 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() + }) + + lggr, _ := logger.TestObserved(t, zap.DebugLevel) + + mn, txSender := newTestTransactionSender(t, chainID, lggr, + []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{slowSendOnly}) + + require.NoError(t, mn.Close()) + _, err := txSender.SendTransaction(tests.Context(t), nil) + require.EqualError(t, err, "MultiNode 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() + }) + + lggr, _ := logger.TestObserved(t, zap.DebugLevel) + + _, txSender := newTestTransactionSender(t, chainID, lggr, + []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{slowSendOnly}) + + require.NoError(t, txSender.Close()) + _, err := txSender.SendTransaction(tests.Context(t), nil) + require.EqualError(t, err, "TransactionSender not started") + }) + 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.TestObserved(t, zap.DebugLevel) + + _, txSender := newTestTransactionSender(t, chainID, lggr, + []Node[types.ID, SendTxRPCClient[any]]{primary}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{sendOnly}) + + _, sendErr := txSender.SendTransaction(tests.Context(t), nil) + assert.EqualError(t, sendErr, 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.TestObserved(t, zap.DebugLevel) + + _, txSender := newTestTransactionSender(t, chainID, lggr, + []Node[types.ID, SendTxRPCClient[any]]{mainNode, unhealthyNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{unhealthySendOnlyNode}) + + returnCode, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.NoError(t, sendErr) + require.Equal(t, Successful, returnCode) + }) +} + +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 + }{ + { + 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{ + Successful: {errors.New("success")}, + Fatal: {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{ + TransactionAlreadyKnown: {errors.New("tx_already_known")}, + Unsupported: {errors.New("unsupported")}, + }, + }, + { + Name: "Prefers sever error to temporary", + ExpectedTxResult: "underpriced", + ExpectedCriticalErr: "", + ResultsByCode: sendTxResults{ + Retryable: {errors.New("retryable")}, + Underpriced: {errors.New("underpriced")}, + }, + }, + { + Name: "Returns temporary error", + ExpectedTxResult: "retryable", + ExpectedCriticalErr: "", + ResultsByCode: sendTxResults{ + Retryable: {errors.New("retryable")}, + }, + }, + { + Name: "Insufficient funds is treated as error", + ExpectedTxResult: "", + ExpectedCriticalErr: "", + ResultsByCode: sendTxResults{ + Successful: {nil}, + InsufficientFunds: {errors.New("insufficientFunds")}, + }, + }, + { + Name: "Logs critical error on empty ResultsByCode", + ExpectedTxResult: "expected at least one response on SendTransaction", + ExpectedCriticalErr: "expected at least one response on SendTransaction", + ResultsByCode: sendTxResults{}, + }, + { + Name: "Zk terminally stuck", + ExpectedTxResult: "not enough keccak counters to continue the execution", + ExpectedCriticalErr: "", + ResultsByCode: sendTxResults{ + TerminallyStuck: {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 == "" { + assert.NoError(t, err) + } else { + assert.EqualError(t, txResult, 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 == "" { + assert.NoError(t, err) + } else { + assert.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 index c9b6a3580eb..38880397442 100644 --- a/common/client/types.go +++ b/common/client/types.go @@ -4,71 +4,30 @@ import ( "context" "math/big" - "github.com/smartcontractkit/chainlink-common/pkg/assets" - - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/types" ) -// RPC includes all the necessary methods for a multi-node client to interact directly with any RPC endpoint. -type RPC[ - CHAIN_ID types.ID, - SEQ types.Sequence, - ADDR types.Hashable, - BLOCK_HASH types.Hashable, - TX any, - TX_HASH types.Hashable, - EVENT any, - EVENT_OPS any, - TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], - FEE feetypes.Fee, - HEAD types.Head[BLOCK_HASH], - BATCH_ELEM any, -] interface { - NodeClient[ - CHAIN_ID, - HEAD, - ] - clientAPI[ - CHAIN_ID, - SEQ, - ADDR, - BLOCK_HASH, - TX, - TX_HASH, - EVENT, - EVENT_OPS, - TX_RECEIPT, - FEE, - HEAD, - BATCH_ELEM, - ] -} - -// Head is the interface required by the NodeClient -type Head interface { - BlockNumber() int64 - BlockDifficulty() *big.Int - IsValid() bool -} - -// NodeClient includes all the necessary RPC methods required by a node. -type NodeClient[ +// RPCClient includes all the necessary generalized RPC methods used by Node to perform health checks +type RPCClient[ CHAIN_ID types.ID, HEAD Head, ] interface { - connection[CHAIN_ID, HEAD] - - DialHTTP() error - // DisconnectAll - cancels all inflight requests, terminates all subscriptions and resets latest ChainInfo. - DisconnectAll() - Close() - ClientVersion(context.Context) (string, error) - SubscribersCount() int32 - SetAliveLoopSub(types.Subscription) - UnsubscribeAllExceptAliveLoop() + // 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) - SubscribeToFinalizedHeads(_ context.Context) (<-chan HEAD, types.Subscription, 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. @@ -82,78 +41,11 @@ type NodeClient[ GetInterceptedChainInfo() (latest, highestUserObservations ChainInfo) } -// clientAPI includes all the direct RPC methods required by the generalized common client to implement its own. -type clientAPI[ - CHAIN_ID types.ID, - SEQ types.Sequence, - ADDR types.Hashable, - BLOCK_HASH types.Hashable, - TX any, - TX_HASH types.Hashable, - EVENT any, - EVENT_OPS any, // event filter query options - TX_RECEIPT types.Receipt[TX_HASH, BLOCK_HASH], - FEE feetypes.Fee, - HEAD types.Head[BLOCK_HASH], - BATCH_ELEM any, -] interface { - connection[CHAIN_ID, HEAD] - - // Account - BalanceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (*big.Int, error) - TokenBalance(ctx context.Context, accountAddress ADDR, tokenAddress ADDR) (*big.Int, error) - SequenceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (SEQ, error) - LINKBalance(ctx context.Context, accountAddress ADDR, linkAddress ADDR) (*assets.Link, error) - PendingSequenceAt(ctx context.Context, addr ADDR) (SEQ, error) - EstimateGas(ctx context.Context, call any) (gas uint64, err error) - - // Transactions - SendTransaction(ctx context.Context, tx TX) error - SimulateTransaction(ctx context.Context, tx TX) error - TransactionByHash(ctx context.Context, txHash TX_HASH) (TX, error) - TransactionReceipt(ctx context.Context, txHash TX_HASH) (TX_RECEIPT, error) - SendEmptyTransaction( - ctx context.Context, - newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt any, err error), - seq SEQ, - gasLimit uint32, - fee FEE, - fromAddress ADDR, - ) (txhash string, err error) - - // Blocks - BlockByNumber(ctx context.Context, number *big.Int) (HEAD, error) - BlockByHash(ctx context.Context, hash BLOCK_HASH) (HEAD, error) - LatestBlockHeight(context.Context) (*big.Int, error) - LatestFinalizedBlock(ctx context.Context) (HEAD, error) - - // Events - FilterEvents(ctx context.Context, query EVENT_OPS) ([]EVENT, error) - - // Misc - BatchCallContext(ctx context.Context, b []BATCH_ELEM) error - CallContract( - ctx context.Context, - msg interface{}, - blockNumber *big.Int, - ) (rpcErr []byte, extractErr error) - PendingCallContract( - ctx context.Context, - msg interface{}, - ) (rpcErr []byte, extractErr error) - CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error - CodeAt(ctx context.Context, account ADDR, blockNumber *big.Int) ([]byte, error) -} - -type connection[ - CHAIN_ID types.ID, - HEAD Head, -] interface { - ChainID(ctx context.Context) (CHAIN_ID, error) - Dial(ctx context.Context) error - SubscribeToHeads(ctx context.Context) (ch <-chan HEAD, sub types.Subscription, err error) - // TODO: remove as part of merge with BCI-2875 - SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (s types.Subscription, err error) +// 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 diff --git a/common/fee/models.go b/common/fee/models.go index 0568a2f1433..0cc479d3560 100644 --- a/common/fee/models.go +++ b/common/fee/models.go @@ -14,6 +14,7 @@ var ( ErrBumpFeeExceedsLimit = errors.New("fee bump exceeds limit") ErrBump = errors.New("fee bump failed") ErrConnectivity = errors.New("transaction propagation issue: transactions are not being mined") + ErrFeeLimitTooLow = errors.New("provided fee limit too low") ) func IsBumpErr(err error) bool { @@ -63,7 +64,7 @@ func CalculateBumpedFee( // 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), + AddPercentage(originalFeePrice, feeBumpPercent), new(big.Int).Add(originalFeePrice, feeBumpUnits), ) } diff --git a/common/fee/utils.go b/common/fee/utils.go index 26323e11e26..3d4b001e839 100644 --- a/common/fee/utils.go +++ b/common/fee/utils.go @@ -18,7 +18,7 @@ func ApplyMultiplier(feeLimit uint64, multiplier float32) (uint64, error) { } // Returns the input value increased by the given percentage. -func addPercentage(value *big.Int, percentage uint16) *big.Int { +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)) diff --git a/common/headtracker/head_listener.go b/common/headtracker/head_listener.go index d240caab3c3..5f967706e04 100644 --- a/common/headtracker/head_listener.go +++ b/common/headtracker/head_listener.go @@ -62,7 +62,7 @@ type headListener[ client htrktypes.Client[HTH, S, ID, BLOCK_HASH] onSubscription func(context.Context) handleNewHead HeadHandler[HTH, BLOCK_HASH] - chHeaders chan HTH + chHeaders <-chan HTH headSubscription types.Subscription connected atomic.Bool receivingHeads atomic.Bool @@ -227,13 +227,10 @@ func (hl *headListener[HTH, S, ID, BLOCK_HASH]) subscribe(ctx context.Context) b } func (hl *headListener[HTH, S, ID, BLOCK_HASH]) subscribeToHead(ctx context.Context) error { - hl.chHeaders = make(chan HTH) - var err error - hl.headSubscription, err = hl.client.SubscribeNewHead(ctx, hl.chHeaders) + hl.chHeaders, hl.headSubscription, err = hl.client.SubscribeToHeads(ctx) if err != nil { - close(hl.chHeaders) - return fmt.Errorf("Client#SubscribeNewHead: %w", err) + return fmt.Errorf("Client#SubscribeToHeads: %w", err) } hl.connected.Store(true) diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go index 8546d856b67..d309ced0cda 100644 --- a/common/headtracker/head_tracker.go +++ b/common/headtracker/head_tracker.go @@ -434,10 +434,10 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) backfill(ctx context.Context, hea } if head.BlockHash() != latestFinalizedHead.BlockHash() { - const errMsg = "expected finalized block to be present in canonical chain" - ht.log.With("finalized_block_number", latestFinalizedHead.BlockNumber(), "finalized_hash", latestFinalizedHead.BlockHash(), - "canonical_chain_block_number", head.BlockNumber(), "canonical_chain_hash", head.BlockHash()).Criticalf(errMsg) - return fmt.Errorf(errMsg) + ht.log.Criticalw("Finalized block missing from conical chain", + "finalized_block_number", latestFinalizedHead.BlockNumber(), "finalized_hash", latestFinalizedHead.BlockHash(), + "canonical_chain_block_number", head.BlockNumber(), "canonical_chain_hash", head.BlockHash()) + return FinalizedMissingError[BLOCK_HASH]{latestFinalizedHead.BlockHash(), head.BlockHash()} } l = l.With("latest_finalized_block_hash", latestFinalizedHead.BlockHash(), @@ -454,6 +454,14 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) backfill(ctx context.Context, hea return } +type FinalizedMissingError[BLOCK_HASH types.Hashable] struct { + Finalized, Canonical BLOCK_HASH +} + +func (e FinalizedMissingError[BLOCK_HASH]) Error() string { + return fmt.Sprintf("finalized block %s missing from canonical chain %s", e.Finalized, e.Canonical) +} + func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) fetchAndSaveHead(ctx context.Context, n int64, hash BLOCK_HASH) (HTH, error) { ht.log.Debugw("Fetching head", "blockHeight", n, "blockHash", hash) head, err := ht.client.HeadByHash(ctx, hash) diff --git a/common/headtracker/types/client.go b/common/headtracker/types/client.go index a1e419809b5..e1b7aad08df 100644 --- a/common/headtracker/types/client.go +++ b/common/headtracker/types/client.go @@ -12,9 +12,9 @@ type Client[H types.Head[BLOCK_HASH], S types.Subscription, ID types.ID, BLOCK_H HeadByHash(ctx context.Context, hash BLOCK_HASH) (head H, err error) // ConfiguredChainID returns the chain ID that the node is configured to connect to ConfiguredChainID() (id ID) - // SubscribeNewHead is the method in which the client receives new Head. + // SubscribeToHeads is the method in which the client receives new Head. // It can be implemented differently for each chain i.e websocket, polling, etc - SubscribeNewHead(ctx context.Context, ch chan<- H) (S, error) + SubscribeToHeads(ctx context.Context) (<-chan H, S, error) // LatestFinalizedBlock - returns the latest block that was marked as finalized LatestFinalizedBlock(ctx context.Context) (head H, err error) } diff --git a/common/headtracker/types/config.go b/common/headtracker/types/config.go index 06ad93d39d2..19ec519aa35 100644 --- a/common/headtracker/types/config.go +++ b/common/headtracker/types/config.go @@ -15,4 +15,5 @@ type HeadTrackerConfig interface { SamplingInterval() time.Duration FinalityTagBypass() bool MaxAllowedFinalityDepth() uint32 + PersistenceEnabled() bool } diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index be3d3ca2f61..8ecd6dbf46b 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/client" + commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" @@ -434,7 +435,11 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand } attempt, _, _, retryable, err := eb.NewTxAttempt(ctx, *etx, eb.lggr) - if err != nil { + // 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()) + return eb.saveFatallyErroredTransaction(eb.lggr, etx), false + } else if err != nil { return fmt.Errorf("processUnstartedTxs failed on NewAttempt: %w", err), retryable } @@ -553,21 +558,33 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand eb.sequenceTracker.GenerateNextSequence(etx.FromAddress, *etx.Sequence) return err, true case client.Underpriced: - return eb.tryAgainBumpingGas(ctx, lgr, err, etx, attempt, initialBroadcastAt, retryCount+1) + 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: - // NOTE: This bails out of the entire cycle and essentially "blocks" on - // any transaction that gets insufficient_funds. This is OK if a - // transaction with a large VALUE blocks because this always comes last - // in the processing list. - // If it blocks because of a transaction that is expensive due to large - // gas limit, we could have smaller transactions "above" it that could - // theoretically be sent, but will instead be blocked. + // 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. + // The new attempt must be replaced immediately because of a database constraint. eb.SvcErrBuffer.Append(err) - fallthrough + if _, _, replaceErr := eb.replaceAttemptWithNewEstimation(ctx, lgr, etx, attempt); replaceErr != nil { + return replaceErr, true + } + return err, true case client.Retryable: return err, true case client.FeeOutOfValidRange: - return eb.tryAgainWithNewEstimation(ctx, lgr, err, etx, attempt, initialBroadcastAt) + replacementAttempt, retryable, replaceErr := eb.replaceAttemptWithNewEstimation(ctx, lgr, etx, attempt) + if replaceErr != nil { + return replaceErr, retryable + } + + 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: return err, false case client.ExceedsMaxFee: @@ -675,7 +692,8 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) next return etx, nil } -func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) tryAgainBumpingGas(ctx context.Context, lgr logger.Logger, txError error, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], initialBroadcastAt time.Time, retry int) (err error, retryable bool) { +// replaceAttemptWithBumpedGas performs the replacement of the existing tx attempt with a new bumped fee attempt. +func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) replaceAttemptWithBumpedGas(ctx context.Context, lgr logger.Logger, txError error, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) (replacedAttempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], retryable bool, err error) { // This log error is not applicable to Hedera since the action required would not be needed for its gas estimator if eb.chainType != hederaChainType { logger.With(lgr, @@ -689,37 +707,32 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) tryA attempt.TxFee, txError.Error(), eb.feeConfig.FeePriceDefault()) } - replacementAttempt, bumpedFee, bumpedFeeLimit, retryable, err := eb.NewBumpTxAttempt(ctx, etx, attempt, nil, lgr) + bumpedAttempt, bumpedFee, bumpedFeeLimit, retryable, err := eb.NewBumpTxAttempt(ctx, etx, attempt, nil, lgr) if err != nil { - return fmt.Errorf("tryAgainBumpFee failed: %w", err), retryable + return bumpedAttempt, retryable, err } - return eb.saveTryAgainAttempt(ctx, lgr, etx, attempt, replacementAttempt, initialBroadcastAt, bumpedFee, bumpedFeeLimit, retry) -} - -func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) tryAgainWithNewEstimation(ctx context.Context, lgr logger.Logger, txError error, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], initialBroadcastAt time.Time) (err error, retryable bool) { - if attempt.TxType == 0x2 { - err = fmt.Errorf("re-estimation is not supported for EIP-1559 transactions. Node returned error: %v. This is a bug", txError.Error()) - logger.Sugared(eb.lggr).AssumptionViolation(err.Error()) - return err, false + if err = eb.txStore.SaveReplacementInProgressAttempt(ctx, attempt, &bumpedAttempt); err != nil { + return bumpedAttempt, true, err } - replacementAttempt, fee, feeLimit, retryable, err := eb.NewTxAttemptWithType(ctx, etx, lgr, attempt.TxType, feetypes.OptForceRefetch) + lgr.Debugw("Bumped fee on initial send", "oldFee", attempt.TxFee.String(), "newFee", bumpedFee.String(), "newFeeLimit", bumpedFeeLimit) + return bumpedAttempt, true, err +} + +// 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) if err != nil { - return fmt.Errorf("tryAgainWithNewEstimation failed to build new attempt: %w", err), retryable + return &newEstimatedAttempt, retryable, err } - lgr.Warnw("L2 rejected transaction due to incorrect fee, re-estimated and will try again", - "etxID", etx.ID, "err", err, "newGasPrice", fee, "newGasLimit", feeLimit) - - return eb.saveTryAgainAttempt(ctx, lgr, etx, attempt, replacementAttempt, initialBroadcastAt, fee, feeLimit, 0) -} -func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) saveTryAgainAttempt(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], replacementAttempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], initialBroadcastAt time.Time, newFee FEE, newFeeLimit uint64, retry int) (err error, retyrable bool) { - if err = eb.txStore.SaveReplacementInProgressAttempt(ctx, attempt, &replacementAttempt); err != nil { - return fmt.Errorf("tryAgainWithNewFee failed: %w", err), true + if err = eb.txStore.SaveReplacementInProgressAttempt(ctx, attempt, &newEstimatedAttempt); err != nil { + return &newEstimatedAttempt, true, err } - lgr.Debugw("Bumped fee on initial send", "oldFee", attempt.TxFee.String(), "newFee", newFee.String(), "newFeeLimit", newFeeLimit) - return eb.handleInProgressTx(ctx, etx, replacementAttempt, initialBroadcastAt, retry) + + lgr.Debugw("new estimated fee on initial send", "oldFee", attempt.TxFee.String(), "newFee", fee.String(), "newFeeLimit", feeLimit) + return &newEstimatedAttempt, true, err } func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) saveFatallyErroredTransaction(lgr logger.Logger, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { @@ -743,7 +756,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) save // Now we have an errored pipeline even though the tx succeeded. This case // is relatively benign and probably nobody will ever run into it in // practice, but something to be aware of. - if etx.PipelineTaskRunID.Valid && eb.resumeCallback != nil && etx.SignalCallback { + if etx.PipelineTaskRunID.Valid && eb.resumeCallback != nil && etx.SignalCallback && !etx.CallbackCompleted { err := eb.resumeCallback(ctx, etx.PipelineTaskRunID.UUID, nil, fmt.Errorf("fatal error while sending transaction: %s", etx.Error.String)) if errors.Is(err, sql.ErrNoRows) { lgr.Debugw("callback missing or already resumed", "etxID", etx.ID) diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index d67bd451228..d2d491d794c 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -2,6 +2,7 @@ package txmgr import ( "context" + "database/sql" "encoding/hex" "errors" "fmt" @@ -346,7 +347,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) pro if ec.resumeCallback != nil { mark = time.Now() - if err := ec.ResumePendingTaskRuns(ctx, head); err != nil { + if err := ec.ResumePendingTaskRuns(ctx, head.BlockNumber(), latestFinalizedHead.BlockNumber()); err != nil { return fmt.Errorf("ResumePendingTaskRuns failed: %w", err) } @@ -514,6 +515,13 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Pro errMu.Unlock() return } + // Resume pending task runs with failure for stuck transactions + if err := ec.resumeFailedTaskRuns(ctx, tx); err != nil { + errMu.Lock() + errorList = append(errorList, fmt.Errorf("failed to resume pending task run for transaction: %w", err)) + errMu.Unlock() + return + } }(tx) } wg.Wait() @@ -584,7 +592,8 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) fet return fmt.Errorf("saveFetchedReceipts failed: %w", err) } // Save the receipts but mark the associated transactions as Fatal Error since the original transaction was purged - if err := ec.txStore.SaveFetchedReceipts(ctx, purgeReceipts, TxFatalError, ec.stuckTxDetector.StuckTxFatalError(), ec.chainID); err != nil { + stuckTxFatalErrMsg := ec.stuckTxDetector.StuckTxFatalError() + if err := ec.txStore.SaveFetchedReceipts(ctx, purgeReceipts, TxFatalError, &stuckTxFatalErrMsg, ec.chainID); err != nil { return fmt.Errorf("saveFetchedReceipts failed: %w", err) } promNumConfirmedTxs.WithLabelValues(ec.chainID.String()).Add(float64(len(receipts))) @@ -616,6 +625,24 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) sep return } +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) resumeFailedTaskRuns(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { + if !etx.PipelineTaskRunID.Valid || ec.resumeCallback == nil || !etx.SignalCallback || etx.CallbackCompleted { + return nil + } + err := ec.resumeCallback(ctx, etx.PipelineTaskRunID.UUID, nil, errors.New(ec.stuckTxDetector.StuckTxFatalError())) + if errors.Is(err, sql.ErrNoRows) { + ec.lggr.Debugw("callback missing or already resumed", "etxID", etx.ID) + } else if err != nil { + return fmt.Errorf("failed to resume pipeline: %w", err) + } else { + // Mark tx as having completed callback + if err = ec.txStore.UpdateTxCallbackCompleted(ctx, etx.PipelineTaskRunID.UUID, ec.chainID); err != nil { + return err + } + } + return nil +} + func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) getMinedSequenceForAddress(ctx context.Context, from ADDR) (SEQ, error) { return ec.client.SequenceAt(ctx, from, nil) } @@ -1121,10 +1148,11 @@ func hasReceiptInLongestChain[ } } } - if head.GetParent() == nil { + + head = head.GetParent() + if head == nil { return false } - head = head.GetParent() } } @@ -1231,8 +1259,8 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) sen } // ResumePendingTaskRuns issues callbacks to task runs that are pending waiting for receipts -func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ResumePendingTaskRuns(ctx context.Context, head types.Head[BLOCK_HASH]) error { - receiptsPlus, err := ec.txStore.FindTxesPendingCallback(ctx, head.BlockNumber(), ec.chainID) +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ResumePendingTaskRuns(ctx context.Context, latest, finalized int64) error { + receiptsPlus, err := ec.txStore.FindTxesPendingCallback(ctx, latest, finalized, ec.chainID) if err != nil { return err diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index 4467729e167..279a7252f1a 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -1096,9 +1096,9 @@ func (_c *TxStore_FindTxesByMetaFieldAndStates_Call[ADDR, CHAIN_ID, TX_HASH, BLO return _c } -// FindTxesPendingCallback provides a mock function with given fields: ctx, blockNum, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error) { - ret := _m.Called(ctx, blockNum, chainID) +// FindTxesPendingCallback provides a mock function with given fields: ctx, latest, finalized, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPendingCallback(ctx context.Context, latest int64, finalized int64, chainID CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error) { + ret := _m.Called(ctx, latest, finalized, chainID) if len(ret) == 0 { panic("no return value specified for FindTxesPendingCallback") @@ -1106,19 +1106,19 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPen var r0 []txmgrtypes.ReceiptPlus[R] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error)); ok { - return rf(ctx, blockNum, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error)); ok { + return rf(ctx, latest, finalized, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, int64, CHAIN_ID) []txmgrtypes.ReceiptPlus[R]); ok { - r0 = rf(ctx, blockNum, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, CHAIN_ID) []txmgrtypes.ReceiptPlus[R]); ok { + r0 = rf(ctx, latest, finalized, chainID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]txmgrtypes.ReceiptPlus[R]) } } - if rf, ok := ret.Get(1).(func(context.Context, int64, CHAIN_ID) error); ok { - r1 = rf(ctx, blockNum, chainID) + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, CHAIN_ID) error); ok { + r1 = rf(ctx, latest, finalized, chainID) } else { r1 = ret.Error(1) } @@ -1133,15 +1133,16 @@ type TxStore_FindTxesPendingCallback_Call[ADDR types.Hashable, CHAIN_ID types.ID // FindTxesPendingCallback is a helper method to define mock.On call // - ctx context.Context -// - blockNum int64 +// - latest int64 +// - finalized int64 // - chainID CHAIN_ID -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPendingCallback(ctx interface{}, blockNum interface{}, chainID interface{}) *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindTxesPendingCallback", ctx, blockNum, chainID)} +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPendingCallback(ctx interface{}, latest interface{}, finalized interface{}, chainID interface{}) *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindTxesPendingCallback", ctx, latest, finalized, chainID)} } -func (_c *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, blockNum int64, chainID CHAIN_ID)) *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, latest int64, finalized int64, chainID CHAIN_ID)) *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(int64), args[2].(CHAIN_ID)) + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(CHAIN_ID)) }) return _c } @@ -1151,7 +1152,7 @@ func (_c *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HA return _c } -func (_c *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, int64, CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error)) *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, int64, int64, CHAIN_ID) ([]txmgrtypes.ReceiptPlus[R], error)) *TxStore_FindTxesPendingCallback_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(run) return _c } diff --git a/common/txmgr/types/stuck_tx_detector.go b/common/txmgr/types/stuck_tx_detector.go index c4ca94b87f8..dc09eea9807 100644 --- a/common/txmgr/types/stuck_tx_detector.go +++ b/common/txmgr/types/stuck_tx_detector.go @@ -22,5 +22,5 @@ type StuckTxDetector[ // Sets the last purged block num after a transaction has been successfully purged with receipt SetPurgeBlockNum(fromAddress ADDR, blockNum int64) // Returns the error message to set in the transaction error field to mark it as terminally stuck - StuckTxFatalError() *string + StuckTxFatalError() string } diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index 5489a57e636..668b8db2049 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -34,7 +34,7 @@ type TxStore[ TransactionStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, SEQ, FEE] // Find confirmed txes beyond the minConfirmations param that require callback but have not yet been signaled - FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID CHAIN_ID) (receiptsPlus []ReceiptPlus[R], err error) + FindTxesPendingCallback(ctx context.Context, latest, finalized int64, chainID CHAIN_ID) (receiptsPlus []ReceiptPlus[R], err error) // Update tx to mark that its callback has been signaled UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error SaveFetchedReceipts(ctx context.Context, r []R, state TxState, errorMsg *string, chainID CHAIN_ID) error @@ -79,6 +79,8 @@ type TransactionStore[ // Search for Tx using the fromAddress and sequence FindTxWithSequence(ctx context.Context, fromAddress ADDR, seq SEQ) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindNextUnstartedTransactionFromAddress(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) + + // FindTransactionsConfirmedInBlockRange retrieves tx with attempts and partial receipt values for optimization purpose FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber, lowBlockNumber int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, chainID CHAIN_ID) (null.Time, error) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, chainID CHAIN_ID) (null.Int, error) diff --git a/common/types/chain.go b/common/types/chain.go index 800f0d9fdc0..bf4654142a8 100644 --- a/common/types/chain.go +++ b/common/types/chain.go @@ -1,6 +1,10 @@ package types -import "fmt" +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) // Sequence represents the base type, for any chain's sequence object. // It should be convertible to a string @@ -12,3 +16,10 @@ 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/subscription.go b/common/types/subscription.go index b9b44e41943..3c4fd4c39f1 100644 --- a/common/types/subscription.go +++ b/common/types/subscription.go @@ -5,7 +5,8 @@ package types // This is a generic interface for Subscription to represent used by clients. type Subscription interface { // Unsubscribe cancels the sending of events to the data channel - // and closes the error channel. + // and closes the error channel. Unsubscribe should be callable multiple + // times without causing an error. Unsubscribe() // Err returns the subscription error channel. The error channel receives // a value if there is an issue with the subscription (e.g. the network connection diff --git a/contracts/.changeset/chatty-keys-kneel.md b/contracts/.changeset/chatty-keys-kneel.md new file mode 100644 index 00000000000..ace3539ad87 --- /dev/null +++ b/contracts/.changeset/chatty-keys-kneel.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +#internal fixing comments and data availability bytes length calculation + + +PR issue : CCIP-3785 \ No newline at end of file diff --git a/contracts/.changeset/chilled-melons-warn.md b/contracts/.changeset/chilled-melons-warn.md new file mode 100644 index 00000000000..f94192bb60c --- /dev/null +++ b/contracts/.changeset/chilled-melons-warn.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal index don ID in ConfigSet event diff --git a/contracts/.changeset/cool-laws-drum.md b/contracts/.changeset/cool-laws-drum.md new file mode 100644 index 00000000000..f7851c3d822 --- /dev/null +++ b/contracts/.changeset/cool-laws-drum.md @@ -0,0 +1,7 @@ +--- +'@chainlink/contracts': patch +--- + +Add new Configurator contract for blue-green LLO deployments + +PR issue: MERC-5954 diff --git a/contracts/.changeset/eight-timers-sip.md b/contracts/.changeset/eight-timers-sip.md new file mode 100644 index 00000000000..3f81544e34f --- /dev/null +++ b/contracts/.changeset/eight-timers-sip.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Add new channel definitions config store contract for parallel compositions #added diff --git a/contracts/.changeset/eighty-ways-vanish.md b/contracts/.changeset/eighty-ways-vanish.md new file mode 100644 index 00000000000..3a48ca4e710 --- /dev/null +++ b/contracts/.changeset/eighty-ways-vanish.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Publish a comment in PR mentioning the actor and informing her about avilability of Slither reports. diff --git a/contracts/.changeset/few-camels-tan.md b/contracts/.changeset/few-camels-tan.md new file mode 100644 index 00000000000..ca2574171d5 --- /dev/null +++ b/contracts/.changeset/few-camels-tan.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +bump dependencies diff --git a/contracts/.changeset/few-parents-punch.md b/contracts/.changeset/few-parents-punch.md new file mode 100644 index 00000000000..88a885606bf --- /dev/null +++ b/contracts/.changeset/few-parents-punch.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +update comments + + +PR issue: SHIP-3557 diff --git a/contracts/.changeset/flat-turkeys-rule.md b/contracts/.changeset/flat-turkeys-rule.md new file mode 100644 index 00000000000..2dedbe653ed --- /dev/null +++ b/contracts/.changeset/flat-turkeys-rule.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal merge ccip contracts diff --git a/contracts/.changeset/fluffy-papayas-chew.md b/contracts/.changeset/fluffy-papayas-chew.md new file mode 100644 index 00000000000..aa7b145e8f6 --- /dev/null +++ b/contracts/.changeset/fluffy-papayas-chew.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Change Chain Reader testing contract Triggered event for easier testing of filtering by non indexed evm data. + + +PR issue: BCFR-203 diff --git a/contracts/.changeset/forty-radios-brush.md b/contracts/.changeset/forty-radios-brush.md new file mode 100644 index 00000000000..5356ffedb1b --- /dev/null +++ b/contracts/.changeset/forty-radios-brush.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +Add Configurator contract + + +PR issue: MERC-6185 diff --git a/contracts/.changeset/funny-meals-remember.md b/contracts/.changeset/funny-meals-remember.md new file mode 100644 index 00000000000..cb40a347e45 --- /dev/null +++ b/contracts/.changeset/funny-meals-remember.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Modify Contract Reader tester helper BCFR-912 diff --git a/contracts/.changeset/happy-planets-accept.md b/contracts/.changeset/happy-planets-accept.md new file mode 100644 index 00000000000..bdd21c0caef --- /dev/null +++ b/contracts/.changeset/happy-planets-accept.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +add accountStr to chainReader test contract struct in order to test the new address bytes to string modifier. #internal + + +PR issue: BCFR-147 + +Solidity Review issue: BCFR-957 \ No newline at end of file diff --git a/contracts/.changeset/heavy-balloons-cheat.md b/contracts/.changeset/heavy-balloons-cheat.md new file mode 100644 index 00000000000..a6cc994c8d3 --- /dev/null +++ b/contracts/.changeset/heavy-balloons-cheat.md @@ -0,0 +1,9 @@ +--- +'@chainlink/contracts': patch +--- + +#added Add ZKSync L2EP SequencerUptimeFeed contract +#added Add ZKSync L2EP Validator contract + + +PR issue: SHIP-3004 diff --git a/contracts/.changeset/hip-cherries-marry.md b/contracts/.changeset/hip-cherries-marry.md new file mode 100644 index 00000000000..d5928a5dbf2 --- /dev/null +++ b/contracts/.changeset/hip-cherries-marry.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': minor +--- + +Add encryptionPublicKey to CapabilitiesRegistry.sol diff --git a/contracts/.changeset/hungry-badgers-jump.md b/contracts/.changeset/hungry-badgers-jump.md new file mode 100644 index 00000000000..9fba12fb6f2 --- /dev/null +++ b/contracts/.changeset/hungry-badgers-jump.md @@ -0,0 +1,9 @@ +--- +'@chainlink/contracts': minor +--- + +#internal add getNextDonId() and getNodes(bytes32[] calldata p2pIds) in CapabilitiesRegistry and define interface for node info + + + +PR issue: CCIP-3569 \ No newline at end of file diff --git a/contracts/.changeset/itchy-deers-deny.md b/contracts/.changeset/itchy-deers-deny.md index 888d58ce311..697f451cf56 100644 --- a/contracts/.changeset/itchy-deers-deny.md +++ b/contracts/.changeset/itchy-deers-deny.md @@ -1,5 +1,5 @@ --- -"@chainlink/contracts": patch +'@chainlink/contracts': patch --- More comprehensive & product-scoped Solidity Foundry pipeline diff --git a/contracts/.changeset/loud-penguins-float.md b/contracts/.changeset/loud-penguins-float.md new file mode 100644 index 00000000000..89c43fe5a43 --- /dev/null +++ b/contracts/.changeset/loud-penguins-float.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': minor +--- + +# internal Fix: Ensure the correct timestamp is used from the oracle feed and select the most recent price between local and oracle data. diff --git a/contracts/.changeset/nasty-llamas-prove.md b/contracts/.changeset/nasty-llamas-prove.md index c3b26c9be36..dd344676808 100644 --- a/contracts/.changeset/nasty-llamas-prove.md +++ b/contracts/.changeset/nasty-llamas-prove.md @@ -3,3 +3,5 @@ --- DEVSVCS-147: add a reentrancy guard for balance monitor + +PR issue: DEVSVCS-147 diff --git a/contracts/.changeset/nice-rocks-trade.md b/contracts/.changeset/nice-rocks-trade.md new file mode 100644 index 00000000000..a60cfd4bd9b --- /dev/null +++ b/contracts/.changeset/nice-rocks-trade.md @@ -0,0 +1,9 @@ +--- +'@chainlink/contracts': patch +--- + +#internal Minor fixes and changing the order of removes/adds in feeToken config + +CCIP-3730 +CCIP-3727 +CCIP-3725 \ No newline at end of file diff --git a/contracts/.changeset/orange-plums-fold.md b/contracts/.changeset/orange-plums-fold.md new file mode 100644 index 00000000000..b6cf88c81b3 --- /dev/null +++ b/contracts/.changeset/orange-plums-fold.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +Adding USDCReaderTester contract for CCIP integration tests #internal + + +CCIP-2881 \ No newline at end of file diff --git a/contracts/.changeset/proud-pears-tie.md b/contracts/.changeset/proud-pears-tie.md new file mode 100644 index 00000000000..93fba83b558 --- /dev/null +++ b/contracts/.changeset/proud-pears-tie.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/quick-olives-accept.md b/contracts/.changeset/quick-olives-accept.md new file mode 100644 index 00000000000..31c59983e47 --- /dev/null +++ b/contracts/.changeset/quick-olives-accept.md @@ -0,0 +1,7 @@ +--- +'@chainlink/contracts': minor +--- + +#updated move latest ccip contracts code from ccip repo to chainlink repo + +PR issue: CCIP-2946 diff --git a/contracts/.changeset/quiet-lamps-walk.md b/contracts/.changeset/quiet-lamps-walk.md new file mode 100644 index 00000000000..93fba83b558 --- /dev/null +++ b/contracts/.changeset/quiet-lamps-walk.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/quiet-moles-retire.md b/contracts/.changeset/quiet-moles-retire.md new file mode 100644 index 00000000000..6351f36a16c --- /dev/null +++ b/contracts/.changeset/quiet-moles-retire.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +Use reusable workflow for Solidity Artifacts pipeline, move some actions to chainlink-github-actions repository + + +PR issue: TT-1693 diff --git a/contracts/.changeset/rich-lamps-do.md b/contracts/.changeset/rich-lamps-do.md new file mode 100644 index 00000000000..3f432d3de6b --- /dev/null +++ b/contracts/.changeset/rich-lamps-do.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +update zksync automation contract version and small fixes diff --git a/contracts/.changeset/sharp-avocados-arrive.md b/contracts/.changeset/sharp-avocados-arrive.md new file mode 100644 index 00000000000..6bfd0524a88 --- /dev/null +++ b/contracts/.changeset/sharp-avocados-arrive.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +#internal remove CCIP 1.5 + + +PR issue: CCIP-3748 \ No newline at end of file diff --git a/contracts/.changeset/silent-houses-join.md b/contracts/.changeset/silent-houses-join.md new file mode 100644 index 00000000000..4138756c78a --- /dev/null +++ b/contracts/.changeset/silent-houses-join.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Enable rotating encryptionPublicKey in CapabilitiesRegistry contract diff --git a/contracts/.changeset/strong-boats-brake.md b/contracts/.changeset/strong-boats-brake.md new file mode 100644 index 00000000000..4f1b780565f --- /dev/null +++ b/contracts/.changeset/strong-boats-brake.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +Add linkage between PR and Jira's Solidity Review issue + + +PR issue: TT-1624 diff --git a/contracts/.changeset/tall-donkeys-flow.md b/contracts/.changeset/tall-donkeys-flow.md new file mode 100644 index 00000000000..3753880baeb --- /dev/null +++ b/contracts/.changeset/tall-donkeys-flow.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Updated ChainReaderTester to include dynamic and static nested structs in TestStruct + + +PR issue: BCFR-44 + +Solidity Review issue: BCFR-957 \ No newline at end of file diff --git a/contracts/.changeset/thirty-lamps-reply.md b/contracts/.changeset/thirty-lamps-reply.md new file mode 100644 index 00000000000..d8bcf8d4e83 --- /dev/null +++ b/contracts/.changeset/thirty-lamps-reply.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +implement an auto registry for zksync with no forwarder interface change diff --git a/contracts/.changeset/tidy-kings-itch.md b/contracts/.changeset/tidy-kings-itch.md new file mode 100644 index 00000000000..e493a6cc551 --- /dev/null +++ b/contracts/.changeset/tidy-kings-itch.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal minor keystone improvements diff --git a/contracts/.changeset/tricky-cups-hammer.md b/contracts/.changeset/tricky-cups-hammer.md new file mode 100644 index 00000000000..a6e213c9be0 --- /dev/null +++ b/contracts/.changeset/tricky-cups-hammer.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +Make stalenessThreshold per dest chain and have 0 mean no staleness check. + + +PR issue: CCIP-3414 \ No newline at end of file diff --git a/contracts/.changeset/twenty-pears-battle.md b/contracts/.changeset/twenty-pears-battle.md new file mode 100644 index 00000000000..5a204f68891 --- /dev/null +++ b/contracts/.changeset/twenty-pears-battle.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +update token transfer logic in weth9 diff --git a/contracts/.changeset/unlucky-rocks-marry.md b/contracts/.changeset/unlucky-rocks-marry.md new file mode 100644 index 00000000000..723bb1e130a --- /dev/null +++ b/contracts/.changeset/unlucky-rocks-marry.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal use ERC165Checker diff --git a/contracts/.changeset/wild-tigers-know.md b/contracts/.changeset/wild-tigers-know.md new file mode 100644 index 00000000000..e7b33aeb75a --- /dev/null +++ b/contracts/.changeset/wild-tigers-know.md @@ -0,0 +1,8 @@ +--- +'@chainlink/contracts': patch +--- + +change else if to else..if.. + + +PR issue: CCIP-3726 \ No newline at end of file diff --git a/contracts/.gas-snapshot b/contracts/.gas-snapshot index 3a0354d539c..e793f8ce549 100644 --- a/contracts/.gas-snapshot +++ b/contracts/.gas-snapshot @@ -1,112 +1,142 @@ -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154832) -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178813) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24723) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145703) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94606) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92961) -CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 372302) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19273) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 169752) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239789) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 249596) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 116890) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43358) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() (gas: 343924) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 180150) -CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184135) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17602) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18498) -CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358448) -CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358414) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301229) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55174) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24895) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27669) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25108) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27408) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27047) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309679) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89807) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89935) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22944) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16231) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91264) -CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135553) -CapabilitiesRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65468) -CapabilitiesRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 64924) -CapabilitiesRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) -CapabilitiesRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) -CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36407) -CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38692) -CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 65288) -CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73533) -CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54761) -CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15647) -CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16550) -CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36122) -CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15816) -CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115151) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287716) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 561023) -CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73376) -CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75211) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25053) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18418) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385369) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18408) -CapabilitiesRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19415) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152914) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17835) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222996) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 232804) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107643) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163357) -CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 371909) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20728) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20052) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19790) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15430) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 37034) -CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256371) -CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162166) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35873) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByAnotherNodeOperatorAdmin() (gas: 29200) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 29377) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 29199) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 31326) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 29165) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470910) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341191) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 29058) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 27587) -CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162220) -KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2002057) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 128934) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 130621) -KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 359123) -KeystoneForwarder_ReportTest:test_Report_SuccessfulRetryWithMoreGas() (gas: 423982) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86348) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118486) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94516) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 75930) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 76320) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45585) -KeystoneForwarder_ReportTest:test_RevertWhen_RetryingInvalidContractTransmission() (gas: 143354) -KeystoneForwarder_ReportTest:test_RevertWhen_RetryingSuccessfulTransmission() (gas: 353272) -KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55292) -KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 56050) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20184) -KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 88057) -KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14533) -KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88766) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114570) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingZeroAddressSigner() (gas: 114225) -KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1540541) -KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1535211) -KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) -KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10978) -KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10923) -KeystoneRouter_SetConfigTest:test_RemoveForwarder_Success() (gas: 17599) -KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18552) -KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 76407) \ No newline at end of file +ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37568) +ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12963) +ArbitrumCrossDomainForwarder_Constructor:test_InitialState() (gas: 22163) +ArbitrumCrossDomainForwarder_Forward:test_Forward() (gas: 47867) +ArbitrumCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 22181) +ArbitrumCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 16056) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 41453) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19290) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18637) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13242) +ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37568) +ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12963) +ArbitrumCrossDomainGovernor_Constructor:test_InitialState() (gas: 22186) +ArbitrumCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 50003) +ArbitrumCrossDomainGovernor_Forward:test_Forward() (gas: 47896) +ArbitrumCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 24326) +ArbitrumCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 18233) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 19386) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 60874) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 63003) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 18245) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 64368) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 41453) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19290) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18637) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13242) +ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 104862) +ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_Return0WhenRoundDoesNotExistYet() (gas: 19967) +ArbitrumSequencerUptimeFeed_Constants:test_InitialState() (gas: 8518) +ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 604370) +ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574432) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 99629) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 15447) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 114625) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 114708) +ArbitrumValidator_Validate:test_PostSequencerOffline() (gas: 69086) +OptimismCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47160) +OptimismCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22160) +OptimismCrossDomainForwarder_Constructor:test_InitialState() (gas: 21998) +OptimismCrossDomainForwarder_Forward:test_Forward() (gas: 58281) +OptimismCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32560) +OptimismCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13867) +OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48933) +OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28753) +OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16448) +OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +OptimismCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47160) +OptimismCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22160) +OptimismCrossDomainGovernor_Constructor:test_InitialState() (gas: 22021) +OptimismCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47846) +OptimismCrossDomainGovernor_Forward:test_Forward() (gas: 58330) +OptimismCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32619) +OptimismCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16047) +OptimismCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29189) +OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 72942) +OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72947) +OptimismCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16059) +OptimismCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76156) +OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48933) +OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28753) +OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16448) +OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72400) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +OptimismSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22050) +OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601594) +OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574437) +OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67873) +OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13079) +OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23542) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77322) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96182) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96265) +OptimismValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18671) +OptimismValidator_Validate:test_PostSequencerOffline() (gas: 74790) +OptimismValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 74869) +OptimismValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) +ScrollCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47255) +ScrollCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22212) +ScrollCrossDomainForwarder_Constructor:test_InitialState() (gas: 21674) +ScrollCrossDomainForwarder_Forward:test_Forward() (gas: 58348) +ScrollCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32618) +ScrollCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13867) +ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48999) +ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28819) +ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16448) +ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +ScrollCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47255) +ScrollCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22212) +ScrollCrossDomainGovernor_Constructor:test_InitialState() (gas: 21697) +ScrollCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47841) +ScrollCrossDomainGovernor_Forward:test_Forward() (gas: 58392) +ScrollCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32674) +ScrollCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16044) +ScrollCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29250) +ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 73009) +ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 73014) +ScrollCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16056) +ScrollCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76224) +ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48999) +ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28819) +ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16448) +ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72423) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +ScrollSequencerUptimeFeed_Constructor:test_InitialState() (gas: 173935) +ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601594) +ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574437) +ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67919) +ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13079) +ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23542) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77368) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96228) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96311) +ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18805) +ScrollValidator_Validate:test_PostSequencerOffline() (gas: 78326) +ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78411) +ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 67166) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +ZKSyncSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22054) +ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601614) +ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574443) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 61924) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13035) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 71379) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 90241) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 90324) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithInvalidChainId() (gas: 103725) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL1BridgeAddress() (gas: 81440) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL2UpdateFeedAddress() (gas: 81497) +ZKSyncValidator_GetChainId:test_CorrectlyGetsTheChainId() (gas: 8350) +ZKSyncValidator_GetSetL2GasPerPubdataByteLimit:test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() (gas: 18915) +ZKSyncValidator_Validate:test_PostSequencerOffline() (gas: 52255) +ZKSyncValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 52355) +ZKSyncValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15644) \ No newline at end of file diff --git a/contracts/.husky/README.md b/contracts/.husky/README.md new file mode 100644 index 00000000000..846e5d3c3a3 --- /dev/null +++ b/contracts/.husky/README.md @@ -0,0 +1,37 @@ +# Husky git hooks +The folder contains [husky](https://github.com/typicode/husky) git hooks that automate pre-commit and pre-push commands. + +## Setup + +Create an `.env` file in this folder to enable hooks: + +```sh +# Can be left blank to compile everything +FOUNDRY_PROFILE=ccip +HUSKY_ENABLE_PUSH_HOOKS=true +HUSKY_ENABLE_COMMIT_HOOKS=true +UPSTREAM_BRANCH=origin/ccip-develop +``` + +```sh +# Automatically ran after pnpm install +pnpm prepare +``` + +### Script procedure + +The setup is done via the `prepare.sh` script, which installs husky and enables the hooks. + +The prepare step is skipped if we are in CI. This is checked via the `CI=true` flag, which is always set to true on GitHub actions. + +## Hooks & Scripts + +### Pre-commit +Runs [lint-staged](https://github.com/lint-staged/lint-staged), which automatically detects `.sol` file changes and applies `forge fmt` only on the changed files. + +Configured in `package.json` in the `lint-staged` field. + +### Pre-push +Runs forge build, test, solhint and optionally suggests to generate snapshots and wrappers. + +Due to a [git workflow limitation](https://stackoverflow.com/questions/21334493/git-commit-in-pre-push-hook), generating wrappers & snapshots requires resubmitting the push (via `--no-verify` or by skiping the snapshot / wrappers). diff --git a/contracts/.husky/pre-commit b/contracts/.husky/pre-commit new file mode 100644 index 00000000000..a411da15670 --- /dev/null +++ b/contracts/.husky/pre-commit @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +source contracts/.husky/.env + +# Only run hook on enabled +if ! [[ $HUSKY_ENABLE_COMMIT_HOOKS == "true" && -n $UPSTREAM_BRANCH ]]; then + exit 0 +fi + +cd contracts + +# Run lint steps +pnpm lint-staged -v diff --git a/contracts/.husky/pre-push b/contracts/.husky/pre-push new file mode 100644 index 00000000000..dfa33c39423 --- /dev/null +++ b/contracts/.husky/pre-push @@ -0,0 +1,47 @@ +#!/bin/bash +set -e + +source contracts/.husky/.env + +# Only run hook on enabled +if ! [[ $HUSKY_ENABLE_PUSH_HOOKS == "true" && -n $UPSTREAM_BRANCH ]]; then + exit 0 +fi + +# Skip on no changes +current_branch=$(git branch --show-current) +changes_root=$(git diff --name-only $UPSTREAM_BRANCH...$current_branch -- "contracts/") + +if ! [[ -n $changes_root ]]; then + echo "Pre-push hook for contracts skipped - no changes detected" + exit 0 +fi + +cd contracts + +FOUNDRY_PROFILE=$FOUNDRY_PROFILE forge build +FOUNDRY_PROFILE=$FOUNDRY_PROFILE forge test +pnpm solhint + +# Skip interactive commands if interactive mode (/dev/tty) is unavailable +# https://stackoverflow.com/a/69088164 +if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then + read -n1 -p "Re-generate snapshots & wrappers? (Y/n)" snapshot_answer < /dev/tty + echo $snapshot_answer + + if [ "$snapshot_answer" != "${snapshot_answer#[Yy]}" ] ;then + # Create gas snapshot & commit gas snapshot + make snapshot + make wrappers + + git add ./gas-snapshots + git add ../core/gethwrappers + + # Check if commit is successful (non-empty) + if git commit -m "chore: update gas snapshots and wrappers"; then + # The commit is not included - need to push again (https://stackoverflow.com/questions/21334493/git-commit-in-pre-push-hook) + printf "\033[0;31m Snapshot commit created - run git push again \033[1;33m(skip snapshot, or use the --no-verify push option)\n" + exit 1 + fi + fi +fi diff --git a/contracts/.husky/prepare.sh b/contracts/.husky/prepare.sh new file mode 100755 index 00000000000..ce10e6449e9 --- /dev/null +++ b/contracts/.husky/prepare.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e + +# Detect if in CI to skip hooks +# https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables +if [[ $CI == "true" ]]; then + exit 0 +fi + +# Skip hooks creation if unconfigured +if ! [ -f .husky/.env ]; then + printf "\033[1;33mNo .env file found in contracts/.husky, skipping hooks setup.\e[0m\n" + exit 0 +fi + +cd ../ +chmod +x ./contracts/.husky/*.sh +pnpm husky ./contracts/.husky +echo "Husky hooks prepared." diff --git a/contracts/.husky/verify-changeset.sh b/contracts/.husky/verify-changeset.sh new file mode 100755 index 00000000000..980b5e41823 --- /dev/null +++ b/contracts/.husky/verify-changeset.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +# Determine the current branch +current_branch=$(git branch --show-current) +upstream_branch="origin/ccip-develop" + +# Compare the directory against the upstream branch +changes_root=$(git diff --name-only $upstream_branch...$current_branch -- ".changeset") + +if ! [ -n "$changes_root" ]; then + printf "\033[1;33mRoot changeset changes not found, Consider running pnpm changeset in the root directory if there is significant off-chain impact.\e[0m\n" +fi + +changes_contracts=$(git diff --name-only $upstream_branch...$current_branch -- "contracts/.changeset") + +if ! [ -n "$changes_contracts" ]; then + printf "\033[0;31mContracts changeset changes not found, Make sure to run & commit \033[1;33mpnpm changeset\033[0;31m in the contracts directory.\n" + exit 1 +fi diff --git a/contracts/.solhintignore b/contracts/.solhintignore index 55d195c3059..81291fe0871 100644 --- a/contracts/.solhintignore +++ b/contracts/.solhintignore @@ -18,7 +18,6 @@ ./src/v0.8/automation/libraries/internal/Cron.sol ./src/v0.8/automation/AutomationForwarder.sol ./src/v0.8/automation/AutomationForwarderLogic.sol -./src/v0.8/automation/ZKSyncAutomationForwarder.sol ./src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol ./src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -37,8 +36,10 @@ ./src/v0.8/llo-feeds/test ./src/v0.8/vrf/testhelpers ./src/v0.8/functions/tests -./src/v0.8/ccip/test # Always ignore vendor ./src/v0.8/vendor ./node_modules/ + +# Ignore tweaked vendored contracts +./src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol \ No newline at end of file diff --git a/contracts/.tool-versions b/contracts/.tool-versions new file mode 100644 index 00000000000..dfe63496b38 --- /dev/null +++ b/contracts/.tool-versions @@ -0,0 +1 @@ +nodejs 20.13.1 diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 0ebad8446e5..4d47fa05ba5 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -43,7 +43,7 @@ mockery: $(mockery) ## Install mockery. .PHONY: foundry foundry: ## Install foundry. - foundryup --version nightly-de33b6af53005037b463318d2628b5cfcaf39916 + foundryup --version nightly-3ff3d0562215bca620e07c5c4c154eec8da0f04b .PHONY: foundry-refresh foundry-refresh: foundry @@ -88,6 +88,16 @@ wrappers-all: pnpmdep mockery abigen ## Recompiles solidity contracts and their # go_generate contains a call to compile all contracts before generating wrappers go generate ../core/gethwrappers/go_generate.go +# Use this to generate compiled JSON artifacts for gauntlet-plus-plus. +# This is currently only used for CCIP. +# example: make artifact-generate contract=LockReleaseTokenPoolAndProxy solcversion=0.8.24 artifactpath=../../gauntlet-plus-plus/packages-ethereum/operations-ccip/src/artifacts/1.5.0/lock-release-token-pool-and-proxy.json +artifact-generate: export FOUNDRY_PROFILE=ccip +.PHONY: artifact-generate +artifact-generate: + chmod +x ./scripts/generate_compiled_json_ccip.sh + ./scripts/generate_compiled_json_ccip.sh $(contract) $(solcversion) $(artifactpath) + + help: @echo "" @echo " .__ .__ .__ .__ __" diff --git a/contracts/STYLE_GUIDE.md b/contracts/STYLE_GUIDE.md index c5dc20abeab..89fe0dd5efa 100644 --- a/contracts/STYLE_GUIDE.md +++ b/contracts/STYLE_GUIDE.md @@ -16,7 +16,8 @@ We will be looking into `forge fmt`, but for now, we still use `prettier`. # Guidelines ## Code Organization -- Group functionality together. E.g. Declare structs, events, and helper functions near the functions that use them. This is helpful when reading code because the related pieces are localized. It is also consistent with inheritance and libraries, which are separate pieces of code designed for a specific goal. +- Structs, events and custom errors should be defined at the top of the contract. +- Group helper functions near the functions that use them. This is helpful when reading code because the related pieces are localized. - 🤔Why not follow the Solidity recommendation of grouping by visibility? Visibility is clearly defined next to the method signature, making it trivial to check. However, searching can be deceiving because of inherited methods. Given this inconsistency in grouping, we find it easier to read and more consistent to organize code around functionality. Additionally, we recommend testing the public interface for any Solidity contract to ensure it only exposes expected methods. - Follow the [Solidity folder structure CLIP](https://github.com/smartcontractkit/CLIPs/tree/main/clips/2023-04-13-solidity-folder-structure) @@ -33,6 +34,7 @@ We will be looking into `forge fmt`, but for now, we still use `prettier`. This will help massively during audits and onboarding new team members. - Headers should be used to group functionality, the following header style and length are recommended. - Don’t use headers for a single function, or to say “getters”. Group by functionality e.g. the `Tokens and pools`, or `fees` logic within the CCIP OnRamp. +- Comments should start with a capital letter and end with a period. ```solidity // ================================================================ @@ -219,7 +221,8 @@ The original error will not be human-readable in an off-chain explorer because i - Otherwise, Solidity contracts should have a pragma that is locked to a specific version. - Example: Most concrete contracts. - Avoid changing pragmas after the audit. Unless there is a bug that affects your contract, then you should try to stick to a known good pragma. In practice, this means we typically only support one (occasionally two) pragma for any “major”(minor by Semver naming) Solidity version. -- The current advised pragma is `0.8.19` or higher, lower versions should be avoided when starting a new project. Newer versions can be considered. +- The current advised pragma is `0.8.24`, lower versions should be avoided when starting a new project. Newer versions can be considered. + - Explicitly use the `Paris` hardfork when compiling with 0.8.24 to keep the bytecode compatible with all chains. - All contracts should have an SPDX license identifier. If unsure about which one to pick, please consult with legal. Most older contracts have been MIT, but some of the newer products have been using BUSL-1.1 @@ -263,8 +266,8 @@ contract SuperDuperAggregator is ITypeAndVersion { 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. -Solhint will complain about a public constant variable that isn’t FULL_CAPS without the solhint-disable comment. +Note that `ITypeAndVersion` should be used, not `TypeAndVersionInterface`. @@ -418,4 +421,3 @@ function setConfig(uint64 _foo, uint64 _bar, uint64 _baz) external { ``` rule: `tbd` - diff --git a/contracts/foundry.toml b/contracts/foundry.toml index c755ba6437b..1a3ca784048 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -26,7 +26,7 @@ single_line_statement_blocks = "preserve" solc_version = '0.8.24' src = 'src/v0.8/ccip' test = 'src/v0.8/ccip/test' -optimizer_runs = 3_600 +optimizer_runs = 800 evm_version = 'paris' [profile.functions] @@ -54,10 +54,10 @@ src = 'src/v0.8/automation' test = 'src/v0.8/automation/test' [profile.l2ep] +solc_version = '0.8.24' optimizer_runs = 1_000_000 src = 'src/v0.8/l2ep' test = 'src/v0.8/l2ep/test' -solc_version = '0.8.19' [profile.llo-feeds] optimizer_runs = 1_000_000 diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 5fc99a9a409..32e40e12fcd 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -1,943 +1,698 @@ -ARMProxyStandaloneTest:test_ARMCallEmptyContractRevert() (gas: 19600) -ARMProxyStandaloneTest:test_Constructor() (gas: 374544) -ARMProxyStandaloneTest:test_SetARM() (gas: 16494) -ARMProxyStandaloneTest:test_SetARMzero() (gas: 11216) -ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47793) -ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36269) -ARMProxyTest:test_ARMIsCursed_Success() (gas: 49740) -AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26920) -AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) -AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) -AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15368) -AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19696) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21281) -AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) -AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) -AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) -AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18989) -AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17479) -AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30062) -AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32071) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243525) -BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23907) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27565) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241416) -BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17633) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28537) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 55991) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 110657) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243552) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2131281) -CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9495) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70755) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363647) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488774) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453384) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37027) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61043) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60963) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11764) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8765) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 311991) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49663) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32275) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376576) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 120943) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157105) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376352) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157172) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9583) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057393) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27539) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23105) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009309) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616177) -CCIPConfig__updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9583) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851188) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068362) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068393) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) -CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9583) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184703) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344332) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20258) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267558) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14829) -CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9626) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 294893) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 298325) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 295038) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294357) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291431) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292396) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 292540) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 299420) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1160094) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291260) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsHasDuplicates_Reverts() (gas: 295907) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293229) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsNotSorted_Reverts() (gas: 295623) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302186) -CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 294539) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1215861) -CCIPConfig_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1214264) -CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9562) -CommitStore_constructor:test_Constructor_Success() (gas: 3091326) -CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) -CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) -CommitStore_report:test_InvalidInterval_Revert() (gas: 28610) -CommitStore_report:test_InvalidRootRevert() (gas: 27843) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53253) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59049) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53251) -CommitStore_report:test_Paused_Revert() (gas: 21259) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84242) -CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56313) -CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63969) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119420) -CommitStore_report:test_Unhealthy_Revert() (gas: 44751) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100758) -CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27626) -CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11325) -CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) -CommitStore_setDynamicConfig:test_InvalidCommitStoreConfig_Revert() (gas: 37263) -CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37399) -CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129098) -CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11047) -CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20642) -CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11046) -CommitStore_verify:test_Blessed_Success() (gas: 96389) -CommitStore_verify:test_NotBlessed_Success() (gas: 61374) -CommitStore_verify:test_Paused_Revert() (gas: 18496) -CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) -DefensiveExampleTest:test_Recovery() (gas: 424253) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1103438) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38157) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108343) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116811) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460560) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95542) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12463) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90385) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105586) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15719) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13057) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 298564) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 239899) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 158863) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189303) -EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 147582) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 521508) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10459) -EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 15662) -EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67195) -EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59698) -EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58778) -EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6394741) -EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 5977968) -EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106229) -EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116228) -EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106272) -EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351414) -EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159132) -EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136253) -EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136831) -EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59046) -EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227807) -EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117527) -EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77605) -EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 207057) -EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6389130) -EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47785) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5981174) -EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 157326) -EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103815) -EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101686) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 159832) -EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101585) -EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101652) -EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17280) -EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1559406) -EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 342924) -EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 260178) -EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445247) -EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6028193) -EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 27681) -EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 165181) -EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149137) -EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6807322) -EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17154) -EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18413) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249368) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20672) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 201673) -EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48860) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48381) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 232798) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 89392) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 278146) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 93615) -EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35083) -EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23907) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 451358) -EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54475) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35917) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154369) -EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35317) -EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181353) -EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190627) -EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48053) -EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 443030) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251770) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 173962) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 193657) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259648) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 129585) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 391710) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65899) -EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80955) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 535429) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 480345) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35763) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 520344) -EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 517712) -EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 487848) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 127921) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 157144) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3655340) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118224) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87461) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75600) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26461) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 163081) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 207379) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26004) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152867) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 507480) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2307925) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 209633) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 210210) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 668610) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 299477) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 160598) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24131) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 59105) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 40405) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 76130) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178951) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 278805) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215406) -EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14374) -EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11898) -EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 14054) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55771) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33781) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 238004) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246667) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 299499) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 280579) -EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176604) -EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178672) -EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141533) -EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51508) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94528) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92480) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97483) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92538) -EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 2260144) -EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 90987) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 130983) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 161753) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 161306) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 159506) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 161536) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 160928) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26206) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 134082) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24272) -EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12819) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 30695) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 15675) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 198276) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 224545) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 140840) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 162262) -EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3803257) -EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 127615) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 93044) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 282576) -EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 104423) -EVM2EVMMultiOnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 74041) -EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119755) -EVM2EVMMultiOnRamp_getFee:test_Unhealthy_Revert() (gas: 43657) -EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) -EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11356) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12956) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11313) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16287) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 58439) -EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97185) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38028) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 108191) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_revert_Revert() (gas: 116732) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 391880) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 145379) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 788000) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 176208) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29700) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63325) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 44501) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 214151) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 306912) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 127459) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 255047) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 263638) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 335707) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 314443) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17009) -EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153427) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5464875) -EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144183) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21345) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36442) -EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51701) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473575) -EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 46423) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152453) -EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 101458) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165036) -EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 177824) -EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 41317) -EVM2EVMOffRamp_execute:test_RouterYULCall_Revert() (gas: 402506) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 159387) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 174622) -EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248634) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115017) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409338) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54173) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132056) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52200) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560178) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 499424) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35442) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546987) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64045) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 123223) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 143388) -EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20582) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 281891) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20231) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 219228) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48632) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48120) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 316477) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 72423) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 231326) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 279867) -EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 261109) -EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 229397) -EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 131682) -EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38408) -EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3213556) -EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83091) -EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 483328) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186413) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 25824) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 43449) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 25927) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 188518) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187965) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2027441) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143803) -EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8871) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40429) -EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38804) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 146790) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162464) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16667) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197660) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5619710) -EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35778) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99470) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114210) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114252) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130118) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138650) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129804) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38254) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38370) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25511) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25297) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86041) -EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36457) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29037) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107526) -EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22635) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 223665) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53935) -EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25481) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59303) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179141) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177355) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137297) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3731767) -EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) -EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109258) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312351) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112319) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72181) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147614) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190454) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121245) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95324) -EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20760) -EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 21128) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78242) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234090) -EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) -EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159220) -EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117858) -EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 65663) -EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) -EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45037) -EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33041) -EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28296) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130189) -EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15260) -EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28104) -EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21248) -EVM2EVMOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 38922) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28149) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38615) -EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29527) -EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32615) -EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 134833) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143054) -EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 26543) -EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127367) -EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133251) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146341) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 140916) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297485) -EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15294) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 43376) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21646) -EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55086) -EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13464) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16449) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 13994) -EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61759) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469097) -EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57255) -EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14665) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84455) -EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60637) -EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173677) -EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190338) -EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53596) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14493) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14277) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84017) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17369) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 82980) -EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15275) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272015) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53446) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12830) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96729) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 47688) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17384) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15677) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99741) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76096) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99748) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 144569) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80259) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80446) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 95713) -EtherSenderReceiverTest_constructor:test_constructor() (gas: 17511) -EtherSenderReceiverTest_getFee:test_getFee() (gas: 27289) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20333) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16715) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16654) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25415) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25265) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17895) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26292) -LockReleaseTokenPoolAndProxy_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11058) -LockReleaseTokenPoolAndProxy_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35097) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10970) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18036) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3313980) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3310379) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) -LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17135) -LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 69142) -LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 17319) -LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3067883) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29942) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79844) -LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59464) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3064325) -LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72662) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56131) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 238673) -LockReleaseTokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17102) -LockReleaseTokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 69075) -LockReleaseTokenPool_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 17297) -LockReleaseTokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11057) -LockReleaseTokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35140) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10992) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 17926) -LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) -LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5451) -MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3552) -MerkleMultiProofTest:test_MerkleRoot256() (gas: 394876) -MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3649) -MerkleMultiProofTest:test_SpecSync_gas() (gas: 34123) -MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 33965) -MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60758) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126294) -MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63302) -MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43853) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132031) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 312057) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17717) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 75784) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 75700) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38133) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53092) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17019) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12295) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1971805) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2085252) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189450) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 59927) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50598) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78780) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263510) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54784) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 9223372036854754743) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19104) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15778) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189438) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 61662) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46683) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52371) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79845) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263724) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56541) -MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11336) -MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19124) -MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10608) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 16085) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 225643) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 200192) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 162053) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28509) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17430) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17485) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44298) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283711) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422848) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511694) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 829593) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457446) -MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12376) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2143220) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141744) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 808478) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 171331) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 30298) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254454) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861521) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475825) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42837) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48442) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76930) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 66127) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33419) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79521) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 34131) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47114) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25682) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18726) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 412349) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1426976) -NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) -NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 252566) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 254866) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 307885) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 290962) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 247990) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236024) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144774) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 186669) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 237737) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 124995) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 125923) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122899) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42823) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66548) -NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12025) -OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12171) -OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42233) -OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84124) -OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 36938) -OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24158) -OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17448) -OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26726) -OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27478) -OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21296) -OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12189) -OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12345) -OCR2Base_setOCR2Config:test_OracleOutOfRegister_Revert() (gas: 14892) -OCR2Base_setOCR2Config:test_RepeatAddress_Revert() (gas: 45442) -OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155192) -OCR2Base_setOCR2Config:test_SingerCannotBeZeroAddress_Revert() (gas: 24407) -OCR2Base_setOCR2Config:test_TooManySigners_Revert() (gas: 20508) -OCR2Base_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 47298) -OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19623) -OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37683) -OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55309) -OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20962) -OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51686) -OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) -OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) -OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 380360) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 148380) -PingPong_plumbing:test_Pausing_Success() (gas: 17803) -PingPong_startPingPong:test_StartPingPong_Success() (gas: 178340) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16719) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 16784) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16611) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16675) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40953) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12341) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 139564) -PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80002) -PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11465) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54149) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44835) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12301) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86826) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17045) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 105966) -PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110316) -PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110369) -PriceRegistry_constructor:test_Setup_Success() (gas: 4650895) -PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) -PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) -PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 95575) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14636) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20614) -PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70449) -PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) -PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45734) -PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62311) -PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84774) -PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41283) -PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34733) -PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27807) -PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 108018) -PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20359) -PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27615) -PriceRegistry_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 40668) -PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27638) -PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40015) -PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29343) -PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18203) -PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81464) -PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 55184) -PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 237926) -PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19971) -PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31775) -PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97714) -PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143193) -PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29435) -PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112283) -PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20107) -PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62956) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094532) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094490) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074609) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094264) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094468) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094280) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 61997) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61877) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 60998) -PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093992) -PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61525) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109113) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13819) -PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092670) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17360) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21454) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18551) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18075) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18452) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18569) -PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18306) -PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18852) -PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16360) -PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26236) -PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32410) -PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25848) -PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23663) -PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17320) -PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12080) -PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30637) -PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76043) -PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151521) -PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50699) -PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63882) -PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19998) -PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89162) -PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50949) -PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12362) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10572) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3916546) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10756) -PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6660) -PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6440) -PriceRegistry_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 35457) -PriceRegistry_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 90631) -PriceRegistry_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 32749) -PriceRegistry_validatePoolReturnData:test_WithSingleToken_Success() (gas: 31293) -RMN_constructor:test_Constructor_Success() (gas: 48838) -RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) -RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152152) -RMN_ownerUnbless:test_Unbless_Success() (gas: 74699) -RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 470965) -RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 397532) -RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18591) -RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357403) -RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 32980) -RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 261985) -RMN_permaBlessing:test_PermaBlessing() (gas: 202686) -RMN_setConfig:test_BlessVoterIsZeroAddress_Revert() (gas: 15494) -RMN_setConfig:test_EitherThresholdIsZero_Revert() (gas: 21095) -RMN_setConfig:test_NonOwner_Revert() (gas: 14713) -RMN_setConfig:test_RepeatedAddress_Revert() (gas: 18213) -RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104204) -RMN_setConfig:test_TotalWeightsSmallerThanEachThreshold_Revert() (gas: 30173) -RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130303) -RMN_setConfig:test_VotersLengthIsZero_Revert() (gas: 12128) -RMN_setConfig:test_WeightIsZeroAddress_Revert() (gas: 15734) -RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659123) -RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212156) -RMN_unvoteToCurse:test_InvalidCursesHash() (gas: 26364) -RMN_unvoteToCurse:test_OwnerSkips() (gas: 33753) -RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 63909) -RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47478) -RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61067) -RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 627750) -RMN_voteToBless:test_Curse_Revert() (gas: 472823) -RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 114829) -RMN_voteToBless:test_RootSuccess() (gas: 555559) -RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 96730) -RMN_voteToBless:test_UnauthorizedVoter_Revert() (gas: 17087) -RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44667) -RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98565) -RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152401) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29619) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27565) -RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81485) -RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135299) -RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1648701) -RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14019) -RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 534332) -RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 399001) -RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144225) -RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146738) -RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12600) -RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187244) -RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 472452) -RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 370468) -RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1151909) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 140968) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165087) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121305) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98247) -RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145631) -RateLimiter_constructor:test_Constructor_Success() (gas: 19650) -RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 15916) -RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22222) -RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31353) -RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20336) -RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40285) -RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15720) -RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25594) -RateLimiter_consume:test_Refill_Success() (gas: 37222) -RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18250) -RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24706) -RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38647) -RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46384) -RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38017) -RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36031) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19637) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129918) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19451) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129731) -Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) -Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) -Router_applyRampUpdates:test_OnRampDisable() (gas: 55913) -Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113861) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 200634) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128508) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215283) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66275) -Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68711) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173605) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56037) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172199) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242707) -Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) -Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174415) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 245121) -Router_constructor:test_Constructor_Success() (gas: 13074) -Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46464) -Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) -Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) -Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) -Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 17761) -Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11159) -Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 422138) -Router_recoverTokens:test_RecoverTokens_Success() (gas: 50437) -Router_routeMessage:test_AutoExec_Success() (gas: 42684) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 158002) -Router_routeMessage:test_ManualExec_Success() (gas: 35381) -Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) -Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) -Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 53540) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 416930) -SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20157) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12629) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67011) -TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11350) -TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17581) -TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39902) -TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105922) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104001) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15481) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15026) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112536) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107656) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115686) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12585) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54473) -TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19148) -TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18020) -TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35943) -TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30617) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18043) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6036775) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6282531) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6883397) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7067512) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2169749) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23280) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177516) -TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23648) -TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8363) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24765) -TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271305) -TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 541162) -TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18344) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11385) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 476472) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157074) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70676) -TokenPool_constructor:test_immutableFields_Success() (gas: 20522) -TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 273962) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276952) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289509) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349763) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276643) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253466) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304761) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 14906) -TokenPool_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 12565) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15598) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13173) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281890) -TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17109) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136351) -TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15919) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244483) -TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16303) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261100) -TokenProxy_constructor:test_Constructor() (gas: 13812) -TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) -TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) -TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15849) -TokenProxy_getFee:test_GetFee_Success() (gas: 86948) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 24960) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35312) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30063) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 132864) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477209) -USDCTokenPool_lockOrBurn:test_lockOrBurn_InvalidReceiver_Revert() (gas: 52606) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 289268) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50682) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 119185) -USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66150) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11339) -USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9876) \ No newline at end of file +ARMProxyStandaloneTest:test_ARMCallEmptyContractRevert() (gas: 19720) +ARMProxyStandaloneTest:test_Constructor() (gas: 310043) +ARMProxyStandaloneTest:test_SetARM() (gas: 16587) +ARMProxyStandaloneTest:test_SetARMzero() (gas: 11297) +ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 45120) +ARMProxyTest:test_ARMIsCursed_Success() (gas: 47070) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244065) +BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24187) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27609) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241948) +BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17851) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28783) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56259) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112372) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244092) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24189) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2108354) +CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 332601) +CCIPHome__validateConfig:test__validateConfigSmallerFChain_Success() (gas: 458549) +CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 289173) +CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() (gas: 289468) +CCIPHome__validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 292198) +CCIPHome__validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 288806) +CCIPHome__validateConfig:test__validateConfig_FChainTooHigh_Reverts() (gas: 336339) +CCIPHome__validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 290572) +CCIPHome__validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 290037) +CCIPHome__validateConfig:test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() (gas: 308628) +CCIPHome__validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1191207) +CCIPHome__validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 288900) +CCIPHome__validateConfig:test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() (gas: 289094) +CCIPHome__validateConfig:test__validateConfig_Success() (gas: 299779) +CCIPHome__validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 773087) +CCIPHome__validateConfig:test__validateConfig_ZeroP2PId_Reverts() (gas: 293437) +CCIPHome__validateConfig:test__validateConfig_ZeroSignerKey_Reverts() (gas: 293485) +CCIPHome_applyChainConfigUpdates:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 187716) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 349798) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 18043) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 272797) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14930) +CCIPHome_applyChainConfigUpdates:test_getPaginatedCCIPHomes_Success() (gas: 373719) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_DONIdMismatch_reverts() (gas: 38052) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_InnerCallReverts_reverts() (gas: 11783) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_InvalidSelector_reverts() (gas: 11038) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() (gas: 37071) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_success() (gas: 1455626) +CCIPHome_constructor:test_constructor_CapabilitiesRegistryAddressZero_reverts() (gas: 63886) +CCIPHome_constructor:test_constructor_success() (gas: 3526450) +CCIPHome_constructor:test_getCapabilityConfiguration_success() (gas: 9151) +CCIPHome_constructor:test_supportsInterface_success() (gas: 9931) +CCIPHome_getAllConfigs:test_getAllConfigs_success() (gas: 2772754) +CCIPHome_getConfigDigests:test_getConfigDigests_success() (gas: 2547429) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() (gas: 9110) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23052) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 8818) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_multiplePlugins_success() (gas: 5113562) +CCIPHome_revokeCandidate:test_revokeCandidate_CanOnlySelfCall_reverts() (gas: 9046) +CCIPHome_revokeCandidate:test_revokeCandidate_ConfigDigestMismatch_reverts() (gas: 19106) +CCIPHome_revokeCandidate:test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() (gas: 8773) +CCIPHome_revokeCandidate:test_revokeCandidate_success() (gas: 30699) +CCIPHome_setCandidate:test_setCandidate_CanOnlySelfCall_reverts() (gas: 29359) +CCIPHome_setCandidate:test_setCandidate_ConfigDigestMismatch_reverts() (gas: 1395130) +CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365381) +DefensiveExampleTest:test_HappyPath_Success() (gas: 200048) +DefensiveExampleTest:test_Recovery() (gas: 424306) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1518475) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96909) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49796) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17435) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15709) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99887) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76138) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99931) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 145010) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80373) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80560) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 96064) +EtherSenderReceiverTest_constructor:test_constructor() (gas: 17553) +EtherSenderReceiverTest_getFee:test_getFee() (gas: 27412) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20378) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16705) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16638) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25457) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25307) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17925) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25329) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26348) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16878) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16758) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16800) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41225) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12484) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140316) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162560) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12287) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11547) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54662) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45153) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12310) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 87853) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13255) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17366) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12352) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106589) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110939) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110992) +FeeQuoter_constructor:test_Setup_Success() (gas: 5020726) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68361) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29076) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96045) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14774) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20809) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 72793) +FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 26309) +FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 111759) +FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16081) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109015) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 67299) +FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33219) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78388) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39239) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34876) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27972) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 97567) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20441) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27780) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27803) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40372) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29499) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18354) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82824) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53482) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239286) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22571) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29879) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100330) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142541) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21211) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113804) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22729) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63687) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1974036) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1973994) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1954113) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1973768) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1973972) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1973784) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64690) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64570) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58894) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1973410) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61764) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116495) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14103) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1972087) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43675) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23514) +FeeQuoter_onReport:test_onReport_Success() (gas: 80116) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26882) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17427) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21545) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18636) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18154) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18513) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18636) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44725) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19936) +FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20333) +FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17904) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 122753) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42054) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28578) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29949) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76189) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28176) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26047) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19523) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12154) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23796) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28528) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74596) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145320) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50898) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63825) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20142) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89470) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 51121) +FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12437) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10655) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4001581) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10862) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6797) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6511) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209230) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135879) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107090) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144653) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214817) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423690) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268967) +HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111484) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39362) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 33172) +HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12714) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13329) +HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160900) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255982) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165921) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 154307) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463780) +HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209230) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135897) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107135) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144607) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214795) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423668) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268949) +HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111528) +HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160845) +HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165904) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2836138) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30062) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79965) +LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59620) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2832621) +LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72743) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56358) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225587) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11011) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18094) +LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10184) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83234) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55947) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60164) +LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11054) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35060) +MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5478) +MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3585) +MerkleMultiProofTest:test_MerkleRoot256() (gas: 394891) +MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3661) +MerkleMultiProofTest:test_SpecSync_gas() (gas: 34107) +MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34059) +MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60842) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126576) +MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63455) +MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44034) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 133573) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 315608) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17908) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76431) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 76392) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38736) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53912) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17109) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12436) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1958738) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2075068) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30794) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 48166) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15907) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17525) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21408) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14617) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210107) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58394) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17721) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45162) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46370) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76605) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308233) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50536) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51181) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19345) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15913) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209885) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60182) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46980) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48179) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77706) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308215) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52324) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11315) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19157) +MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10609) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18901) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 280234) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254707) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204577) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28849) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18324) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18231) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59442) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44190) +MultiOCR3Base_setOCR3Configs:test_MoreTransmittersThanSigners_Revert() (gas: 104822) +MultiOCR3Base_setOCR3Configs:test_NoTransmitters_Revert() (gas: 18886) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283736) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422361) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511918) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters_Success() (gas: 680345) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828900) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457314) +MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12437) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2141722) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141835) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807557) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158889) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112335) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254201) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861206) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475852) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42934) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48617) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 77138) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65890) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33495) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79773) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33664) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47200) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25768) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18745) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24300) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39998) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33027) +NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71901) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 186535) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 189890) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 253684) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 221424) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 60382) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153546) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166070) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195673) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139139) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 105187) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates_success() (gas: 123118) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43282) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64610) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 43102) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed_success() (gas: 45875) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate_success() (gas: 66658) +NonceManager_applyPreviousRampsUpdates:test_ZeroInput_success() (gas: 12114) +NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5917222) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626106) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166490) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 16741) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 272213) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 168572) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181027) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13463) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72746) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177991) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335638) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 278882) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169365) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189033) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 157122) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 554234) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) +OffRamp_ccipReceive:test_Reverts() (gas: 15407) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92905) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 61590) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 68151) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 64291) +OffRamp_commit:test_InvalidRootRevert() (gas: 63356) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6677970) +OffRamp_commit:test_NoConfig_Revert() (gas: 6261576) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113033) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121381) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113032) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355198) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164378) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139413) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 146578) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59858) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232042) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125387) +OffRamp_commit:test_Unhealthy_Revert() (gas: 58656) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206691) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51722) +OffRamp_constructor:test_Constructor_Success() (gas: 6222976) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135943) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103375) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101251) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161468) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101189) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101204) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) +OffRamp_execute:test_LargeBatch_Success() (gas: 3426335) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372990) +OffRamp_execute:test_MultipleReports_Success() (gas: 300979) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7086799) +OffRamp_execute:test_NoConfig_Revert() (gas: 6311274) +OffRamp_execute:test_NonArray_Revert() (gas: 27562) +OffRamp_execute:test_SingleReport_Success() (gas: 176354) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148372) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7089548) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18511) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 244079) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20781) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205116) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49306) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48750) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218006) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85296) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 274196) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91724) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28282) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22637) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 481794) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48394) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33981) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28458) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188093) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198549) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40763) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413245) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249800) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193614) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 213648) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 249550) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142163) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409313) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58315) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73890) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 583427) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 532141) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33739) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 549786) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 549800) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 460521) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135944) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165649) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3885554) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120629) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89288) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81016) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74094) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173164) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214099) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27085) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 164696) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27622) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55171) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498527) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316128) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2245200) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165525) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227144) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227706) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781362) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347321) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37656) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 104404) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 82842) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36752) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94382) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 37241) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86516) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 162381) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 23881) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 62729) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 79768) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 174513) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 176380) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 187657) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11314) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13884) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46378) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24398) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 219355) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 227977) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 295396) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 277874) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 250779) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17209) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Revert() (gas: 67048) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Success() (gas: 325706) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64956) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 12823) +OnRamp_constructor:test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() (gas: 2682420) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95269) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 93211) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98232) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93245) +OnRamp_constructor:test_Constructor_Success() (gas: 2762169) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115351) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146174) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145749) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143976) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145946) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145344) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140719) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38560) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143078) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36625) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36511) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18269) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38460) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23669) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186396) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212780) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 146978) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161083) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3615293) +OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24016) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75850) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38583) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280301) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 98597) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65467) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86990) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35092) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113770) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 17039) +OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10474) +OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35282) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11581) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13195) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() (gas: 11522) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 16850) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13243) +OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56390) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97325) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172600) +PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20240) +PingPong_plumbing:test_Pausing_Success() (gas: 17718) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 153736) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 179373) +RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() (gas: 18822) +RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() (gas: 18660) +RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() (gas: 20371) +RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_MinObserversTooHigh_reverts() (gas: 20810) +RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() (gas: 137268) +RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() (gas: 20472) +RMNHome_getConfigDigests:test_getConfigDigests_success() (gas: 1077745) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23857) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 10597) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() (gas: 10936) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_success() (gas: 1083116) +RMNHome_revokeCandidate:test_revokeCandidate_ConfigDigestMismatch_reverts() (gas: 19041) +RMNHome_revokeCandidate:test_revokeCandidate_OnlyOwner_reverts() (gas: 10963) +RMNHome_revokeCandidate:test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() (gas: 10606) +RMNHome_revokeCandidate:test_revokeCandidate_success() (gas: 28125) +RMNHome_setCandidate:test_setCandidate_ConfigDigestMismatch_reverts() (gas: 594657) +RMNHome_setCandidate:test_setCandidate_OnlyOwner_reverts() (gas: 15155) +RMNHome_setCandidate:test_setCandidate_success() (gas: 588357) +RMNHome_setDynamicConfig:test_setDynamicConfig_DigestNotFound_reverts() (gas: 30137) +RMNHome_setDynamicConfig:test_setDynamicConfig_MinObserversTooHigh_reverts() (gas: 18871) +RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 14093) +RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 103889) +RMNRemote_constructor:test_constructor_success() (gas: 8334) +RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59209) +RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154457) +RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18780) +RMNRemote_curse:test_curse_success() (gas: 149409) +RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133482) +RMNRemote_setConfig:test_setConfig_addSigner_removeSigner_success() (gas: 976479) +RMNRemote_setConfig:test_setConfig_duplicateOnChainPublicKey_reverts() (gas: 323317) +RMNRemote_setConfig:test_setConfig_invalidSignerOrder_reverts() (gas: 80181) +RMNRemote_setConfig:test_setConfig_minSignersIs0_success() (gas: 700584) +RMNRemote_setConfig:test_setConfig_minSignersTooHigh_reverts() (gas: 54024) +RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51947) +RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18726) +RMNRemote_uncurse:test_uncurse_success() (gas: 40151) +RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13673) +RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 78519) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 76314) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 83377) +RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 153002) +RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 387649) +RMNRemote_verify_withConfigSet:test_verify_minSignersIsZero_success() (gas: 184568) +RMNRemote_verify_withConfigSet:test_verify_success() (gas: 68207) +RateLimiter_constructor:test_Constructor_Success() (gas: 19734) +RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16042) +RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22435) +RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31518) +RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20381) +RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40687) +RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15800) +RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25798) +RateLimiter_consume:test_Refill_Success() (gas: 37444) +RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18388) +RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24930) +RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38944) +RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46849) +RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38506) +RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36033) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19733) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 130089) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19553) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129908) +Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89366) +Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10663332) +Router_applyRampUpdates:test_OnRampDisable() (gas: 56007) +Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12334) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131251) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 220951) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 71652) +Router_ccipSend:test_InvalidMsgValue() (gas: 32267) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 69340) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 192950) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 61388) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 191576) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226370) +Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24900) +Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44902) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 193820) +Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140512) +Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230125) +Router_constructor:test_Constructor_Success() (gas: 13076) +Router_getArmProxy:test_getArmProxy() (gas: 10573) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 51693) +Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17150) +Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10474) +Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11334) +Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20245) +Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11171) +Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 358049) +Router_recoverTokens:test_RecoverTokens_Success() (gas: 52452) +Router_routeMessage:test_routeMessage_AutoExec_Success() (gas: 43092) +Router_routeMessage:test_routeMessage_ExecutionEvent_Success() (gas: 159148) +Router_routeMessage:test_routeMessage_ManualExec_Success() (gas: 35685) +Router_routeMessage:test_routeMessage_OnlyOffRamp_Revert() (gas: 25404) +Router_routeMessage:test_routeMessage_WhenNotHealthy_Revert() (gas: 44903) +Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10976) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51163) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 44004) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12653) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67056) +TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11362) +TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17668) +TokenAdminRegistry_getPools:test_getPools_Success() (gas: 40028) +TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 106006) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104369) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15588) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15133) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 113006) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107943) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 116067) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12609) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54524) +TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19316) +TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18137) +TokenAdminRegistry_setPool:test_setPool_Success() (gas: 36135) +TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30842) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18103) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49460) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 1979946) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12107) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23476) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177881) +TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23830) +TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8375) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24867) +TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271592) +TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542403) +TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18492) +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11469) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 479143) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157400) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70484) +TokenPool_constructor:test_immutableFields_Success() (gas: 20586) +TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274175) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277296) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 290010) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 350050) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277036) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 254048) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 305084) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17165) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15294) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15649) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13219) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282125) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25704) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35481) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30213) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133508) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 478231) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268712) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50952) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98987) +USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66371) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11341) +USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10041) \ No newline at end of file diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot index 44d557ebcf3..080ae2a4263 100644 --- a/contracts/gas-snapshots/functions.gas-snapshot +++ b/contracts/gas-snapshots/functions.gas-snapshot @@ -1,69 +1,69 @@ -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 16076840) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 16076819) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 16076888) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 16076608) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 16076564) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 16076635) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 16076521) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 16076543) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 16076586) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 16076842) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 16076821) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 16076845) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 16076565) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 16076566) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 16076592) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 16076523) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 16076500) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 16076543) FunctionsBilling_Constructor:test_Constructor_Success() (gas: 17982) FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13283) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15853) -FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32450) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15876) +FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32428) FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90977) -FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 91102) +FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 91125) FunctionsBilling_GetAdminFeeJuels:test_GetAdminFeeJuels_Success() (gas: 18671) FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30750) FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41151) FunctionsBilling_GetOperationFee:test_GetOperationFeeJuels_Success() (gas: 40548) FunctionsBilling_GetWeiPerUnitLink:test_GetWeiPerUnitLink_Success() (gas: 29751) -FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70136) -FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: 108953) +FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70181) +FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: 108947) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessCoordinatorOwner() (gas: 129908) -FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 171930) -FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 145165) +FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 171924) +FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 145159) FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13320) -FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 222357) +FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 222351) FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21632) FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54099) FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8810) FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13353) FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185976) -FunctionsBilling__StartBilling:test__FulfillAndBill_HasUniqueGlobalRequestId() (gas: 524582) +FunctionsBilling__StartBilling:test__FulfillAndBill_HasUniqueGlobalRequestId() (gas: 524564) FunctionsClient_Constructor:test_Constructor_Success() (gas: 10407) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14595) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14618) FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22983) -FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55069) +FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55129) FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 15085) FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15356) FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 91691) FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15334) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515951) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515974) FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20409) FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 88970) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13915) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 513165) FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22802) -FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 150150) +FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 152650) FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 15106) -FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22916) +FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22939) FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 3089) -FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 3066) +FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 3088) FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 3068) FunctionsRouter_Constructor:test_Constructor_Success() (gas: 15107) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172475) -FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 163010) +FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 162988) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38777) -FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35900) -FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 180976) +FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35878) +FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 180951) FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28152) FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 156535) FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 335070) -FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 348695) -FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2627478) +FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 348673) +FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2627447) FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 658423) -FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 18323) +FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 18346) FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 13241) FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40193) FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13862) @@ -71,142 +71,142 @@ FunctionsRouter_GetContractById:test_GetContractById_SuccessIfRouteExists() (gas FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16417) FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24289) FunctionsRouter_GetProposedContractSet:test_GetProposedContractSet_Success() (gas: 27289) -FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28087) -FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41095) -FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24632) +FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28116) +FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41083) +FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24598) FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13361) FunctionsRouter_Pause:test_Pause_Success() (gas: 20647) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14769) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14747) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21716) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfLengthMismatch() (gas: 14670) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNewContract() (gas: 19048) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23392) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (gas: 118479) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59400) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 217996) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59391) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 217987) FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29426) FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57882) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 208451) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50953) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 208430) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50947) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25082) FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29177) FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34291) FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226324) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65918) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65909) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 36012) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29896) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57539) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27503) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57533) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27568) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35672) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40810) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 232783) -FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 214899) -FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 33531) +FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 214878) +FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 33525) FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13381) FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13337) FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77748) FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24415) FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63331) -FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13314) +FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13337) FunctionsRouter_UpdateContracts:test_UpdateContracts_Success() (gas: 39269) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60413) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 61040) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 139706) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62780) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239919) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 138033) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164977) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12933) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102428) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87272) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18100) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 96221) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15053) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102507) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89341) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20157) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218308) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 115656) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 126964) -FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 75369) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60404) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 61031) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 139697) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62771) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239898) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 138015) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 165004) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12924) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102416) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87266) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18072) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 96175) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15019) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102492) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89310) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20126) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218299) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 115649) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 126904) +FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 75326) FunctionsSubscriptions_Constructor:test_Constructor_Success() (gas: 10488) -FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28688) +FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28666) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 18038) -FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 353899) -FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17279) +FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 353898) +FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17270) FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13504) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41221) -FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 32968) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41215) +FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 32965) FunctionsSubscriptions_GetSubscriptionCount:test_GetSubscriptionCount_Success() (gas: 13305) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16570) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13465) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65968) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16613) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13459) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65953) FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15370) -FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata() (gas: 39908) -FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription() (gas: 42382) +FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata() (gas: 39883) +FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription() (gas: 42427) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink() (gas: 13419) -FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused() (gas: 47325) -FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success() (gas: 84314) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20744) +FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused() (gas: 47368) +FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success() (gas: 84308) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20723) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15686) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20859) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60119) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessSetsBalanceToZero() (gas: 57716) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15683) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20856) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60110) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessSetsBalanceToZero() (gas: 57701) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12796) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15594) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55177) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55168) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49607) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessSubOwnerRefunded() (gas: 53166) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186511) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17923) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 210) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15600) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfNoAmount() (gas: 33839) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31627) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 33935) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 31584) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17796) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203311) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27642) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57793) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15013) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119820) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17947) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20181) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68574) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83582) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17902) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 188) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15578) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfNoAmount() (gas: 33830) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31621) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 33971) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 31547) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17813) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203305) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27633) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57775) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15001) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119805) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17960) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20172) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68553) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83540) FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15577) FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41358) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30310) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 15031) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 102444) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87277) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18103) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 215863) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42066) -FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12888) -FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15684) -FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 38434) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30282) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 15064) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 102407) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87246) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18094) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 215854) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42057) +FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12891) +FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15662) +FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 38406) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfPaused() (gas: 25955) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25261) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25283) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28220) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58394) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58382) FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26462) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15759) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 153701) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15782) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 153679) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94943) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25925) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 89013) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23620) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866619) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 26026) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 28548) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946966) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104555) FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15535) FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97587) FunctionsTermsOfServiceAllowList_Constructor:test_Constructor_Success() (gas: 15345) -FunctionsTermsOfServiceAllowList_GetAllAllowedSenders:test_GetAllAllowedSenders_Success() (gas: 19243) +FunctionsTermsOfServiceAllowList_GetAllAllowedSenders:test_GetAllAllowedSenders_Success() (gas: 19221) FunctionsTermsOfServiceAllowList_GetAllowedSendersCount:test_GetAllowedSendersCount_Success() (gas: 13332) FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326576) FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16532) @@ -215,10 +215,10 @@ FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSenders FunctionsTermsOfServiceAllowList_GetBlockedSendersCount:test_GetBlockedSendersCount_Success() (gas: 13268) FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326564) FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16549) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13345) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13367) FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18580) FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16411) -FunctionsTermsOfServiceAllowList_GetMessage:test_GetMessage_Success() (gas: 11918) +FunctionsTermsOfServiceAllowList_GetMessage:test_GetMessage_Success() (gas: 11896) FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16235) FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23877) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessFalse() (gas: 15776) @@ -229,13 +229,13 @@ FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwn FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96240) FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13819) FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22824) -Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84725) -Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79140) -Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73419) -Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20717) -Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MinimumGas() (gas: 20157) -Gas_FulfillRequest_Success:test_FulfillRequest_Success_MaximumGas() (gas: 501339) -Gas_FulfillRequest_Success:test_FulfillRequest_Success_MinimumGas() (gas: 202509) -Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38524) -Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 988895) -Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 181579) \ No newline at end of file +Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 81752) +Gas_AddConsumer:test_AddConsumer_Gas() (gas: 76158) +Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73485) +Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 17589) +Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MinimumGas() (gas: 17051) +Gas_FulfillRequest_Success:test_FulfillRequest_Success_MaximumGas() (gas: 498189) +Gas_FulfillRequest_Success:test_FulfillRequest_Success_MinimumGas() (gas: 199381) +Gas_FundSubscription:test_FundSubscription_Gas() (gas: 35545) +Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 981365) +Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 178588) \ No newline at end of file diff --git a/contracts/gas-snapshots/keystone.gas-snapshot b/contracts/gas-snapshots/keystone.gas-snapshot index 49b1d4add4b..d8ba041a5df 100644 --- a/contracts/gas-snapshots/keystone.gas-snapshot +++ b/contracts/gas-snapshots/keystone.gas-snapshot @@ -1,113 +1,121 @@ -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154832) -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178813) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24723) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145703) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94606) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92961) -CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 372302) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19273) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 169752) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239789) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 249596) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 116890) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43358) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() (gas: 343924) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 180150) -CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184135) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17602) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18498) -CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358448) -CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358414) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301229) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55174) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24895) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27669) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25108) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27408) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27047) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309679) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89807) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89935) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22944) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16231) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91264) -CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135553) -CapabilitiesRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65468) -CapabilitiesRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 64924) -CapabilitiesRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) -CapabilitiesRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) -CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36407) -CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38692) -CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 65288) -CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73533) -CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54761) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154800) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 180392) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24678) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145611) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94542) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 96348) +CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 373985) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19333) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 169812) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239851) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 250973) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 116928) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43396) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() (gas: 344127) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 180188) +CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationConfigured:test_RevertWhen_MaliciousCapabilitiesConfigContractTriesToRemoveCapabilitiesFromDONNodes() (gas: 340769) +CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184201) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17624) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18542) +CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 380796) +CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 380784) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 323602) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55328) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 25090) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27844) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25258) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_EncryptionPublicKeyEmpty() (gas: 29852) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27558) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27241) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 332070) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89796) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89924) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22911) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16188) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91210) +CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135531) +CapabilitiesRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65490) +CapabilitiesRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 65060) +CapabilitiesRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11460) +CapabilitiesRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13151) +CapabilitiesRegistry_GetNextDONIdTest:test_CorrectlyFetchesNextDONId() (gas: 348178) +CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36429) +CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38714) +CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 69748) +CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesSpecificNodes() (gas: 32177) +CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 79284) +CapabilitiesRegistry_GetNodesTest:test_GetNodesByP2PIdsInvalidNode_Revers() (gas: 26249) +CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 55026) CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15647) -CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16550) -CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36122) +CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16561) +CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36157) CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15816) -CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115151) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287716) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 561023) -CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73376) -CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75211) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25053) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18418) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385369) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18408) -CapabilitiesRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19415) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152914) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17835) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222996) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 232804) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107643) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163357) -CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 371909) +CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 117736) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 288163) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 561487) +CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 77404) +CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 79239) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25008) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18373) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385467) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18363) +CapabilitiesRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9768) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19323) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152958) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17749) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222997) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 236986) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107687) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163401) +CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 373535) CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20728) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20052) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20097) CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19790) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15430) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 37034) -CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256371) -CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162166) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35873) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByAnotherNodeOperatorAdmin() (gas: 29200) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 29377) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 29199) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 31326) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 29165) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470910) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341191) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 29058) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 27587) -CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162220) -KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2003568) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 124908) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 126927) -KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 361243) -KeystoneForwarder_ReportTest:test_Report_SuccessfulRetryWithMoreGas() (gas: 501084) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15452) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 37144) +CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 261420) +CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 164875) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 36026) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByAnotherNodeOperatorAdmin() (gas: 29326) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 29504) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_EncryptionPublicKeyEmpty() (gas: 29746) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 29326) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 31452) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 29292) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 471202) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341548) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 29184) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 27739) +CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 164929) +KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2006852) +KeystoneForwarder_ReportTest:test_Report_FailedDelieryWhenReportReceiverConsumesAllGas() (gas: 1004833) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 125025) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 127239) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReportReceiverConsumesAllGasAndInterfaceCheckUsesMax() (gas: 440303) +KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 362838) +KeystoneForwarder_ReportTest:test_Report_SuccessfulRetryWithMoreGas() (gas: 510677) KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86326) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118521) -KeystoneForwarder_ReportTest:test_RevertWhen_AttemptingTransmissionWithInsufficientGas() (gas: 96279) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94516) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118476) +KeystoneForwarder_ReportTest:test_RevertWhen_AttemptingTransmissionWithInsufficientGas() (gas: 96629) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94538) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 75930) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 76298) KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45563) -KeystoneForwarder_ReportTest:test_RevertWhen_RetryingInvalidContractTransmission() (gas: 143591) -KeystoneForwarder_ReportTest:test_RevertWhen_RetryingSuccessfulTransmission() (gas: 354042) -KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55292) +KeystoneForwarder_ReportTest:test_RevertWhen_RetryingInvalidContractTransmission() (gas: 144231) +KeystoneForwarder_ReportTest:test_RevertWhen_RetryingSuccessfulTransmission() (gas: 355976) +KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55270) KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 56050) KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20184) KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 88057) -KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14533) +KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14555) KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88766) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114570) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingZeroAddressSigner() (gas: 114225) -KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1540541) -KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1535211) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114578) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingZeroAddressSigner() (gas: 114233) +KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1540687) +KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1535361) KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) -KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10978) -KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10923) -KeystoneRouter_SetConfigTest:test_RemoveForwarder_Success() (gas: 17599) -KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18552) -KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 79379) \ No newline at end of file +KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10960) +KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10950) +KeystoneRouter_SetConfigTest:test_RemoveForwarder_Success() (gas: 17603) +KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18530) +KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 80948) \ No newline at end of file diff --git a/contracts/gas-snapshots/l2ep.gas-snapshot b/contracts/gas-snapshots/l2ep.gas-snapshot index 324cacfc024..e9e5a42878b 100644 --- a/contracts/gas-snapshots/l2ep.gas-snapshot +++ b/contracts/gas-snapshots/l2ep.gas-snapshot @@ -1,146 +1,142 @@ -ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37613) +ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37586) ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12963) -ArbitrumCrossDomainForwarder_Constructor:test_InitialState() (gas: 22196) +ArbitrumCrossDomainForwarder_Constructor:test_InitialState() (gas: 22141) ArbitrumCrossDomainForwarder_Forward:test_Forward() (gas: 47867) -ArbitrumCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 22181) -ArbitrumCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 16056) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 41430) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19312) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18671) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13219) -ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37613) +ArbitrumCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 22174) +ArbitrumCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 16099) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 41453) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19290) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18659) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13242) +ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37586) ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12963) -ArbitrumCrossDomainGovernor_Constructor:test_InitialState() (gas: 22219) -ArbitrumCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 49980) +ArbitrumCrossDomainGovernor_Constructor:test_InitialState() (gas: 22164) +ArbitrumCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 50003) ArbitrumCrossDomainGovernor_Forward:test_Forward() (gas: 47918) -ArbitrumCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 24348) -ArbitrumCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 18255) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 19386) +ArbitrumCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 24296) +ArbitrumCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 18233) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 19361) ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 60874) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 62980) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 18245) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 64379) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 41430) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19312) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18671) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13219) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetAnswer() (gas: 92790) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetRoundData() (gas: 93351) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetTimestamp() (gas: 92711) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestAnswer() (gas: 90485) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRound() (gas: 90377) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRoundData() (gas: 90924) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestTimestamp() (gas: 90362) -ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 104994) -ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_Return0WhenRoundDoesNotExistYet() (gas: 20033) -ArbitrumSequencerUptimeFeed_Constants:test_InitialState() (gas: 8530) -ArbitrumSequencerUptimeFeed_GasCosts:test_GasCosts() (gas: 99865) -ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 604414) -ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574476) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 99662) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 15424) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 114647) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 114707) -ArbitrumValidator_Validate:test_PostSequencerOffline() (gas: 69086) -OptimismCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47206) -OptimismCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22160) -OptimismCrossDomainForwarder_Constructor:test_InitialState() (gas: 22031) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 63003) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 18288) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 64368) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 41453) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19290) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18659) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13242) +ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 104880) +ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_Return0WhenRoundDoesNotExistYet() (gas: 19973) +ArbitrumSequencerUptimeFeed_Constants:test_InitialState() (gas: 8496) +ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 604370) +ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574432) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 99663) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 15453) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 114637) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 114720) +ArbitrumValidator_Validate:test_PostSequencerOffline() (gas: 69068) +OptimismCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47162) +OptimismCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22163) +OptimismCrossDomainForwarder_Constructor:test_InitialState() (gas: 21976) OptimismCrossDomainForwarder_Forward:test_Forward() (gas: 58281) -OptimismCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32560) -OptimismCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13867) -OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48910) -OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28775) -OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16482) -OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11030) -OptimismCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47206) -OptimismCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22160) -OptimismCrossDomainGovernor_Constructor:test_InitialState() (gas: 22054) -OptimismCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47823) +OptimismCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32583) +OptimismCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13910) +OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48945) +OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28768) +OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +OptimismCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47162) +OptimismCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22163) +OptimismCrossDomainGovernor_Constructor:test_InitialState() (gas: 21999) +OptimismCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47846) OptimismCrossDomainGovernor_Forward:test_Forward() (gas: 58352) -OptimismCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32641) -OptimismCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16069) -OptimismCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29189) +OptimismCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32619) +OptimismCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16047) +OptimismCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29170) OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 72942) -OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72924) -OptimismCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16059) -OptimismCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76167) -OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48910) -OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28775) -OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16482) -OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11030) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetAnswer() (gas: 59785) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetRoundData() (gas: 60331) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetTimestamp() (gas: 59640) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestAnswer() (gas: 57577) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRound() (gas: 57463) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRoundData() (gas: 58005) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestTimestamp() (gas: 57430) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 71804) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17679) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17897) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17603) -OptimismSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22110) -OptimismSequencerUptimeFeed_GasCosts:test_GasCosts() (gas: 69567) -OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601843) -OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574481) -OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67230) -OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13214) -OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23632) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77137) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 97545) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 97605) -OptimismValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18695) +OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72947) +OptimismCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16102) +OptimismCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76156) +OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48945) +OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28768) +OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72382) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +OptimismSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22028) +OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601594) +OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574437) +OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67861) +OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13118) +OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23536) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77316) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96170) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96253) +OptimismValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18649) OptimismValidator_Validate:test_PostSequencerOffline() (gas: 74813) -OptimismValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 74869) +OptimismValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 74847) OptimismValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) -ScrollCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47300) -ScrollCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22212) -ScrollCrossDomainForwarder_Constructor:test_InitialState() (gas: 21707) +ScrollCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47252) +ScrollCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22215) +ScrollCrossDomainForwarder_Constructor:test_InitialState() (gas: 21652) ScrollCrossDomainForwarder_Forward:test_Forward() (gas: 58348) -ScrollCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32618) -ScrollCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13867) -ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48976) -ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28841) -ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16482) -ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11030) -ScrollCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47300) -ScrollCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22212) -ScrollCrossDomainGovernor_Constructor:test_InitialState() (gas: 21730) -ScrollCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47818) +ScrollCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32641) +ScrollCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13910) +ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 49011) +ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28828) +ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +ScrollCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47252) +ScrollCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22215) +ScrollCrossDomainGovernor_Constructor:test_InitialState() (gas: 21675) +ScrollCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47841) ScrollCrossDomainGovernor_Forward:test_Forward() (gas: 58414) -ScrollCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32696) -ScrollCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16066) -ScrollCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29250) +ScrollCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32674) +ScrollCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16044) +ScrollCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29231) ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 73009) -ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72991) -ScrollCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16056) -ScrollCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76235) -ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48976) -ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28841) -ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16482) -ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11030) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetAnswer() (gas: 57940) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetRoundData() (gas: 58476) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetTimestamp() (gas: 57795) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestAnswer() (gas: 55578) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRound() (gas: 55458) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRoundData() (gas: 56169) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestTimestamp() (gas: 55448) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 70090) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17675) +ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 73014) +ScrollCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16099) +ScrollCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76224) +ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 49011) +ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28828) +ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72405) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17599) -ScrollSequencerUptimeFeed_Constructor:test_InitialState() (gas: 103508) -ScrollSequencerUptimeFeed_GasCosts:test_GasCosts() (gas: 67258) -ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601694) -ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574481) -ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 65115) -ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13214) -ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23632) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 74720) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 93408) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 93468) -ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18829) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +ScrollSequencerUptimeFeed_Constructor:test_InitialState() (gas: 173913) +ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601594) +ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574437) +ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67907) +ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13118) +ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23536) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77362) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96216) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96299) +ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18783) ScrollValidator_Validate:test_PostSequencerOffline() (gas: 78349) -ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78411) -ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) \ No newline at end of file +ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78389) +ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 67184) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +ZKSyncSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22032) +ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601614) +ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574443) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 61936) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13064) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 71428) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 90253) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 90336) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithInvalidChainId() (gas: 103748) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL1BridgeAddress() (gas: 81463) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL2UpdateFeedAddress() (gas: 81475) +ZKSyncValidator_GetChainId:test_CorrectlyGetsTheChainId() (gas: 8350) +ZKSyncValidator_GetSetL2GasPerPubdataByteLimit:test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() (gas: 18909) +ZKSyncValidator_Validate:test_PostSequencerOffline() (gas: 52260) +ZKSyncValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 52327) +ZKSyncValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15638) \ No newline at end of file diff --git a/contracts/gas-snapshots/liquiditymanager.gas-snapshot b/contracts/gas-snapshots/liquiditymanager.gas-snapshot index 53483ed6c7c..a60f08a09b3 100644 --- a/contracts/gas-snapshots/liquiditymanager.gas-snapshot +++ b/contracts/gas-snapshots/liquiditymanager.gas-snapshot @@ -1,48 +1,48 @@ LiquidityManager__report:test_EmptyReportReverts() (gas: 11181) -LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279154) -LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206745) -LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192319) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141768) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8898695) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8893901) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8821699) -LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382897) +LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279198) +LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206764) +LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192374) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141798) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8960969) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8956109) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8883847) +LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382946) LiquidityManager_receive:test_receive_success() (gas: 21182) -LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184869) +LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184959) LiquidityManager_removeLiquidity:test_OnlyFinanceRoleReverts() (gas: 10872) -LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236342) +LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236379) LiquidityManager_setCrossChainRebalancer:test_OnlyOwnerReverts() (gas: 17005) -LiquidityManager_setCrossChainRebalancer:test_ZeroAddressReverts() (gas: 21624) +LiquidityManager_setCrossChainRebalancer:test_ZeroAddressReverts() (gas: 21669) LiquidityManager_setCrossChainRebalancer:test_ZeroChainSelectorReverts() (gas: 13099) LiquidityManager_setCrossChainRebalancer:test_setCrossChainRebalancerSuccess() (gas: 162186) LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987) LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836) -LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11052) -LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10643) -LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3436651) +LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11030) +LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10621) +LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3498784) LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925) LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389) -LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180359) -LiquidityManager_withdrawERC20:test_withdrawERC20Success() (gas: 205858) -LiquidityManager_withdrawNative:test_OnlyFinanceRoleReverts() (gas: 13046) -LiquidityManager_withdrawNative:test_withdrawNative_success() (gas: 51398) +LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180396) +LiquidityManager_withdrawERC20:test_withdrawERC20Success() (gas: 205895) +LiquidityManager_withdrawNative:test_OnlyFinanceRoleReverts() (gas: 13077) +LiquidityManager_withdrawNative:test_withdrawNative_success() (gas: 51407) OCR3Base_setOCR3Config:testFMustBePositiveReverts() (gas: 12245) OCR3Base_setOCR3Config:testFTooHighReverts() (gas: 12429) OCR3Base_setOCR3Config:testOracleOutOfRegisterReverts() (gas: 14847) -OCR3Base_setOCR3Config:testRepeatAddressReverts() (gas: 44932) -OCR3Base_setOCR3Config:testSetConfigSuccess() (gas: 154642) -OCR3Base_setOCR3Config:testSignerCannotBeZeroAddressReverts() (gas: 23712) +OCR3Base_setOCR3Config:testRepeatAddressReverts() (gas: 44954) +OCR3Base_setOCR3Config:testSetConfigSuccess() (gas: 154660) +OCR3Base_setOCR3Config:testSignerCannotBeZeroAddressReverts() (gas: 23734) OCR3Base_setOCR3Config:testTooManySignersReverts() (gas: 19832) OCR3Base_setOCR3Config:testTransmitterCannotBeZeroAddressReverts() (gas: 46539) -OCR3Base_transmit:testConfigDigestMismatchReverts() (gas: 24827) +OCR3Base_transmit:testConfigDigestMismatchReverts() (gas: 24850) OCR3Base_transmit:testForkedChainReverts() (gas: 42846) -OCR3Base_transmit:testNonIncreasingSequenceNumberReverts() (gas: 30522) -OCR3Base_transmit:testNonUniqueSignatureReverts() (gas: 60370) -OCR3Base_transmit:testSignatureOutOfRegistrationReverts() (gas: 26128) -OCR3Base_transmit:testTransmit2SignersSuccess_gas() (gas: 56783) +OCR3Base_transmit:testNonIncreasingSequenceNumberReverts() (gas: 30565) +OCR3Base_transmit:testNonUniqueSignatureReverts() (gas: 60348) +OCR3Base_transmit:testSignatureOutOfRegistrationReverts() (gas: 26106) +OCR3Base_transmit:testTransmit2SignersSuccess_gas() (gas: 56771) OCR3Base_transmit:testUnAuthorizedTransmitterReverts() (gas: 28618) -OCR3Base_transmit:testUnauthorizedSignerReverts() (gas: 44759) +OCR3Base_transmit:testUnauthorizedSignerReverts() (gas: 44737) OCR3Base_transmit:testWrongNumberOfSignaturesReverts() (gas: 25678) OptimismL1BridgeAdapter_finalizeWithdrawERC20:testFinalizeWithdrawERC20Reverts() (gas: 12932) -OptimismL1BridgeAdapter_finalizeWithdrawERC20:testfinalizeWithdrawERC20FinalizeSuccess() (gas: 16972) +OptimismL1BridgeAdapter_finalizeWithdrawERC20:testfinalizeWithdrawERC20FinalizeSuccess() (gas: 16950) OptimismL1BridgeAdapter_finalizeWithdrawERC20:testfinalizeWithdrawERC20proveWithdrawalSuccess() (gas: 20758) \ 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 89073a78468..99f2fcc3430 100644 --- a/contracts/gas-snapshots/llo-feeds.gas-snapshot +++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot @@ -1,254 +1,289 @@ -ByteUtilTest:test_readAddress() (gas: 3388) +ByteUtilTest:test_readAddress() (gas: 3366) ByteUtilTest:test_readAddressMultiWord() (gas: 3386) -ByteUtilTest:test_readAddressWithEmptyArray() (gas: 3274) +ByteUtilTest:test_readAddressWithEmptyArray() (gas: 3252) ByteUtilTest:test_readAddressWithNotEnoughBytes() (gas: 3314) ByteUtilTest:test_readUint192Max() (gas: 3326) -ByteUtilTest:test_readUint192Min() (gas: 3349) -ByteUtilTest:test_readUint192MultiWord() (gas: 3327) +ByteUtilTest:test_readUint192Min() (gas: 3327) +ByteUtilTest:test_readUint192MultiWord() (gas: 3392) ByteUtilTest:test_readUint192WithEmptyArray() (gas: 3274) ByteUtilTest:test_readUint192WithNotEnoughBytes() (gas: 3314) -ByteUtilTest:test_readUint256Max() (gas: 3343) -ByteUtilTest:test_readUint256Min() (gas: 3387) +ByteUtilTest:test_readUint256Max() (gas: 3321) +ByteUtilTest:test_readUint256Min() (gas: 3365) ByteUtilTest:test_readUint256MultiWord() (gas: 3341) -ByteUtilTest:test_readUint256WithEmptyArray() (gas: 3296) -ByteUtilTest:test_readUint256WithNotEnoughBytes() (gas: 3293) +ByteUtilTest:test_readUint256WithEmptyArray() (gas: 3274) +ByteUtilTest:test_readUint256WithNotEnoughBytes() (gas: 3271) ByteUtilTest:test_readUint32Max() (gas: 3348) ByteUtilTest:test_readUint32Min() (gas: 3328) -ByteUtilTest:test_readUint32MultiWord() (gas: 3393) -ByteUtilTest:test_readUint32WithEmptyArray() (gas: 3253) +ByteUtilTest:test_readUint32MultiWord() (gas: 3371) +ByteUtilTest:test_readUint32WithEmptyArray() (gas: 3231) ByteUtilTest:test_readUint32WithNotEnoughBytes() (gas: 3272) -ByteUtilTest:test_readZeroAddress() (gas: 3365) -DestinationFeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52669) -DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52685) -DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78876) -DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 29324) -DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 61187) -DestinationFeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 121137) -DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 29669) -DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 74797) -DestinationFeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 72796) -DestinationFeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 56334) -DestinationFeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 26411) -DestinationFeeManagerProcessFeeTest:test_addVerifier() (gas: 131079) -DestinationFeeManagerProcessFeeTest:test_addVerifierExistingAddress() (gas: 34148) -DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 17214) -DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 20152) -DestinationFeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91103) -DestinationFeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 56580) -DestinationFeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 52871) -DestinationFeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49682) -DestinationFeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 78949) -DestinationFeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 46567) -DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17582) -DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 54628) -DestinationFeeManagerProcessFeeTest:test_discountIsReturnedForLink() (gas: 49654) -DestinationFeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12231) -DestinationFeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41424) -DestinationFeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 179229) -DestinationFeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 69057) -DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 49831) -DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67769) -DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 64460) -DestinationFeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 52091) -DestinationFeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 17231) -DestinationFeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 49853) -DestinationFeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55711) -DestinationFeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 82833) -DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49700) -DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49681) -DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuote() (gas: 20150) -DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 50885) -DestinationFeeManagerProcessFeeTest:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 53172) -DestinationFeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 30937) -DestinationFeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 50887) -DestinationFeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 17220) -DestinationFeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41402) -DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51914) -DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78172) -DestinationFeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 24185) -DestinationFeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19871) -DestinationFeeManagerProcessFeeTest:test_onlyCallableByOwnerReverts() (gas: 15453) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 198072) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17415) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 218691) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 202446) -DestinationFeeManagerProcessFeeTest:test_poolIdsCannotBeZeroAddress() (gas: 115317) -DestinationFeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 121475) -DestinationFeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 29745) -DestinationFeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 165393) -DestinationFeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 30063) -DestinationFeeManagerProcessFeeTest:test_processFeeNative() (gas: 178204) -DestinationFeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 122766) -DestinationFeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 31822) -DestinationFeeManagerProcessFeeTest:test_processFeeWithDiscountEmitsEvent() (gas: 245890) -DestinationFeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 30770) -DestinationFeeManagerProcessFeeTest:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 171109) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 186069) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 135874) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 161459) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 94841) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 193032) -DestinationFeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 75084) -DestinationFeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 30006) -DestinationFeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 30056) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 35320) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 158081) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 56059) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 121473) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 38024) -DestinationFeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 230434) -DestinationFeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 264223) -DestinationFeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 81155) -DestinationFeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 247072) -DestinationFeeManagerProcessFeeTest:test_processPoolIdsPassedMismatched() (gas: 98793) -DestinationFeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 215445) -DestinationFeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 257087) +ByteUtilTest:test_readZeroAddress() (gas: 3343) +ChannelConfigStoreTest:testSetChannelDefinitions() (gas: 46905) +ChannelConfigStoreTest:testSupportsInterface() (gas: 8367) +ChannelConfigStoreTest:testTypeAndVersion() (gas: 9644) +ChannelConfigStoreTest:test_revertsIfCalledByNonOwner() (gas: 11288) +ConfiguratorPromoteStagingConfigTest:test_promotesStagingConfig() (gas: 99047) +ConfiguratorPromoteStagingConfigTest:test_revertsIfCalledByNonOwner() (gas: 10962) +ConfiguratorPromoteStagingConfigTest:test_revertsIfIsGreenProductionDoesNotMatchContractState() (gas: 13423) +ConfiguratorPromoteStagingConfigTest:test_revertsIfNoConfigHasEverBeenSetWithThisConfigId() (gas: 13419) +ConfiguratorPromoteStagingConfigTest:test_revertsIfProductionConfigDigestIsZero() (gas: 68521) +ConfiguratorPromoteStagingConfigTest:test_revertsIfStagingConfigDigestIsZero() (gas: 48258) +ConfiguratorSetProductionConfigTest:test_correctlyUpdatesTheConfig() (gas: 259776) +ConfiguratorSetProductionConfigTest:test_revertsIfCalledByNonOwner() (gas: 266559) +ConfiguratorSetProductionConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 264173) +ConfiguratorSetProductionConfigTest:test_revertsIfNotEnoughSigners() (gas: 95951) +ConfiguratorSetProductionConfigTest:test_revertsIfOnchainConfigIsInvalid() (gas: 60885) +ConfiguratorSetProductionConfigTest:test_revertsIfSetWithTooManySigners() (gas: 107412) +ConfiguratorSetProductionConfigTest:test_supportsHigherVersionsIgnoringExcessOnchainConfig() (gas: 125099) +ConfiguratorSetStagingConfigTest:test_correctlyUpdatesTheConfig() (gas: 265921) +ConfiguratorSetStagingConfigTest:test_revertsIfCalledByNonOwner() (gas: 266528) +ConfiguratorSetStagingConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 264142) +ConfiguratorSetStagingConfigTest:test_revertsIfNotEnoughSigners() (gas: 95920) +ConfiguratorSetStagingConfigTest:test_revertsIfOnchainConfigIsInvalid() (gas: 67763) +ConfiguratorSetStagingConfigTest:test_revertsIfSetWithTooManySigners() (gas: 107392) +ConfiguratorTest:testSupportsInterface() (gas: 8367) +ConfiguratorTest:testTypeAndVersion() (gas: 9683) +DestinationFeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52717) +DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52645) +DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78879) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountCantBeSetToMoreThanMaximum() (gas: 19544) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountIsOverridenByIndividualDiscountLink() (gas: 79509) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountIsOverridenByIndividualDiscountNative() (gas: 82523) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountIsUpdatedAfterBeingSetToZeroLink() (gas: 48409) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountIsUpdatedAfterBeingSetToZeroNative() (gas: 51589) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountWithLink() (gas: 51902) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountWithNative() (gas: 54892) +DestinationFeeManagerProcessFeeTest:test_GlobalDiscountWithNativeAndLink() (gas: 83739) +DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 29358) +DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 61221) +DestinationFeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 123459) +DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 29703) +DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 77115) +DestinationFeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 72819) +DestinationFeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 56357) +DestinationFeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 26434) +DestinationFeeManagerProcessFeeTest:test_addVerifier() (gas: 128921) +DestinationFeeManagerProcessFeeTest:test_addVerifierExistingAddress() (gas: 34192) +DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 19497) +DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 22502) +DestinationFeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91133) +DestinationFeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 58864) +DestinationFeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 52919) +DestinationFeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49730) +DestinationFeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 78908) +DestinationFeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 48362) +DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17516) +DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 56912) +DestinationFeeManagerProcessFeeTest:test_discountIsReturnedForLink() (gas: 49702) +DestinationFeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12253) +DestinationFeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41379) +DestinationFeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 182683) +DestinationFeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 69080) +DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 51626) +DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67777) +DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 66960) +DestinationFeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 52073) +DestinationFeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 19495) +DestinationFeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 49857) +DestinationFeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55762) +DestinationFeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 85050) +DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49726) +DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49685) +DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuote() (gas: 22456) +DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 53190) +DestinationFeeManagerProcessFeeTest:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 53194) +DestinationFeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 33198) +DestinationFeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 53170) +DestinationFeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 17152) +DestinationFeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41357) +DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51918) +DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78108) +DestinationFeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 24207) +DestinationFeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19784) +DestinationFeeManagerProcessFeeTest:test_onlyCallableByOwnerReverts() (gas: 15475) +DestinationFeeManagerProcessFeeTest:test_onlyOwnerCanSetGlobalDiscount() (gas: 19929) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 199893) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17348) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 221286) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 204214) +DestinationFeeManagerProcessFeeTest:test_poolIdsCannotBeZeroAddress() (gas: 117941) +DestinationFeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 123797) +DestinationFeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 29779) +DestinationFeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 167711) +DestinationFeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 32597) +DestinationFeeManagerProcessFeeTest:test_processFeeNative() (gas: 180526) +DestinationFeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 125088) +DestinationFeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 31856) +DestinationFeeManagerProcessFeeTest:test_processFeeWithDiscountEmitsEvent() (gas: 246054) +DestinationFeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 30804) +DestinationFeeManagerProcessFeeTest:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 173431) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 188391) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 138192) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 163781) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 97159) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 195354) +DestinationFeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 77402) +DestinationFeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 30040) +DestinationFeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 30090) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 37638) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 160403) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 58377) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 123795) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 40342) +DestinationFeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 233892) +DestinationFeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 267681) +DestinationFeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 81189) +DestinationFeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 250530) +DestinationFeeManagerProcessFeeTest:test_processPoolIdsPassedMismatched() (gas: 98827) +DestinationFeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 218606) +DestinationFeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 260283) DestinationFeeManagerProcessFeeTest:test_removeVerifierNonExistentAddress() (gas: 12822) -DestinationFeeManagerProcessFeeTest:test_removeVerifierZeroAaddress() (gas: 10678) -DestinationFeeManagerProcessFeeTest:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 13615) -DestinationFeeManagerProcessFeeTest:test_revertOnSettingAnAddressZeroVerifier() (gas: 10614) -DestinationFeeManagerProcessFeeTest:test_rewardsAreCorrectlySentToEachAssociatedPoolWhenVerifyingInBulk() (gas: 263181) -DestinationFeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 19562) +DestinationFeeManagerProcessFeeTest:test_removeVerifierZeroAaddress() (gas: 10700) +DestinationFeeManagerProcessFeeTest:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 13682) +DestinationFeeManagerProcessFeeTest:test_revertOnSettingAnAddressZeroVerifier() (gas: 10636) +DestinationFeeManagerProcessFeeTest:test_rewardsAreCorrectlySentToEachAssociatedPoolWhenVerifyingInBulk() (gas: 266620) +DestinationFeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 19540) DestinationFeeManagerProcessFeeTest:test_setRewardManagerZeroAddress() (gas: 10626) -DestinationFeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46329) -DestinationFeeManagerProcessFeeTest:test_surchargeFeeRoundsUpWhenUneven() (gas: 51261) -DestinationFeeManagerProcessFeeTest:test_surchargeIsApplied() (gas: 51165) -DestinationFeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 79356) -DestinationFeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47132) -DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49962) -DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78352) -DestinationFeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14943) -DestinationRewardManagerClaimTest:test_claimAllRecipients() (gas: 277191) -DestinationRewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154371) -DestinationRewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330208) -DestinationRewardManagerClaimTest:test_claimSingleRecipient() (gas: 89039) -DestinationRewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315411) -DestinationRewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35164) -DestinationRewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41201) -DestinationRewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86084) -DestinationRewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25050) -DestinationRewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386857) -DestinationRewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137777) -DestinationRewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 492227) -DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11503) -DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53944) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 250829) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20496) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251075) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262275) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265760) -DestinationRewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28908) -DestinationRewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25333) -DestinationRewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31402) -DestinationRewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84709) -DestinationRewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198474) -DestinationRewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280853) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512489) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283649) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293497) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263075) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154537) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132653) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106056) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579776) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64664) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13074) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12703) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22471) +DestinationFeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46285) +DestinationFeeManagerProcessFeeTest:test_surchargeFeeRoundsUpWhenUneven() (gas: 53501) +DestinationFeeManagerProcessFeeTest:test_surchargeIsApplied() (gas: 53426) +DestinationFeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 79315) +DestinationFeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 49149) +DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 52223) +DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78311) +DestinationFeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14987) +DestinationRewardManagerClaimTest:test_claimAllRecipients() (gas: 277223) +DestinationRewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154387) +DestinationRewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330244) +DestinationRewardManagerClaimTest:test_claimSingleRecipient() (gas: 89047) +DestinationRewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315447) +DestinationRewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35146) +DestinationRewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41205) +DestinationRewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86092) +DestinationRewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25054) +DestinationRewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386925) +DestinationRewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137775) +DestinationRewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 494460) +DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11517) +DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53965) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 253082) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20472) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 248942) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 264510) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 267995) +DestinationRewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 31111) +DestinationRewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 27577) +DestinationRewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 33639) +DestinationRewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 86982) +DestinationRewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 200697) +DestinationRewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280819) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512553) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283726) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293533) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263107) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154531) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132669) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106068) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579848) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64672) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13052) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12747) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22449) DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 32248) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148629) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21728) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148645) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21706) DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 27765) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391427) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137862) -DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199546) -DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219419) -DestinationRewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191707) -DestinationRewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126060) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 214117) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391495) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137860) +DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199566) +DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219439) +DestinationRewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 193870) +DestinationRewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 128245) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 213998) DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21496) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193280) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180608) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90202) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 191312) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185567) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87091) -DestinationRewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110349) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 195694) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 182793) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 92387) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 193497) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 187752) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 89299) +DestinationRewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 112534) DestinationRewardManagerSetupTest:test_addFeeManagerExistingAddress() (gas: 35281) -DestinationRewardManagerSetupTest:test_addFeeManagerZeroAddress() (gas: 10580) -DestinationRewardManagerSetupTest:test_addRemoveFeeManager() (gas: 48248) -DestinationRewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 41581) -DestinationRewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259172) -DestinationRewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59610) +DestinationRewardManagerSetupTest:test_addFeeManagerZeroAddress() (gas: 10603) +DestinationRewardManagerSetupTest:test_addRemoveFeeManager() (gas: 48231) +DestinationRewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 41559) +DestinationRewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 261361) +DestinationRewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59481) DestinationRewardManagerSetupTest:test_removeFeeManagerNonExistentAddress() (gas: 12778) -DestinationRewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17084) -DestinationRewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376674) -DestinationRewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280411) +DestinationRewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17128) +DestinationRewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376742) +DestinationRewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280465) DestinationRewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19705) -DestinationRewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 221004) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274233) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 254156) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259143) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149856) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259217) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372155) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270700) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288483) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407780) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 317945) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 377692) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 312038) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399603) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289433) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 639153) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 640232) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 661796) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 661751) -DestinationVerifierConstructorTest:test_falseIfIsNotCorrectInterface() (gas: 8719) -DestinationVerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 61121) -DestinationVerifierConstructorTest:test_trueIfIsCorrectInterface() (gas: 8604) -DestinationVerifierConstructorTest:test_typeAndVersion() (gas: 2818189) -DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsTheOwner() (gas: 1035181) +DestinationRewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 221040) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274265) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 254188) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259175) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149872) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259249) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372223) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270758) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288531) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407832) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 317985) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 377740) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 312078) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399655) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289469) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 642577) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 643680) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 665238) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 665193) +DestinationVerifierConstructorTest:test_falseIfIsNotCorrectInterface() (gas: 8481) +DestinationVerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 60885) +DestinationVerifierConstructorTest:test_trueIfIsCorrectInterface() (gas: 9361) +DestinationVerifierConstructorTest:test_typeAndVersion() (gas: 2624729) +DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsTheOwner() (gas: 862226) DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsVersion() (gas: 9841) DestinationVerifierProxyInitializeVerifierTest:test_setVerifierCalledByNoOwner() (gas: 17483) -DestinationVerifierProxyInitializeVerifierTest:test_setVerifierOk() (gas: 30622) -DestinationVerifierProxyInitializeVerifierTest:test_setVerifierWhichDoesntHonourInterface() (gas: 16851) +DestinationVerifierProxyInitializeVerifierTest:test_setVerifierOk() (gas: 27685) +DestinationVerifierProxyInitializeVerifierTest:test_setVerifierWhichDoesntHonourInterface() (gas: 16535) DestinationVerifierSetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35391) DestinationVerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15089) -DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34885) -DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15007) -DestinationVerifierSetConfigTest:test_NoDonConfigAlreadyExists() (gas: 2874492) -DestinationVerifierSetConfigTest:test_addressesAndWeightsDoNotProduceSideEffectsInDonConfigIds() (gas: 1323177) -DestinationVerifierSetConfigTest:test_donConfigIdIsSameForSignersInDifferentOrder() (gas: 1290374) -DestinationVerifierSetConfigTest:test_removeLatestConfig() (gas: 786275) +DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34939) +DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 14995) +DestinationVerifierSetConfigTest:test_NoDonConfigAlreadyExists() (gas: 2877761) +DestinationVerifierSetConfigTest:test_addressesAndWeightsDoNotProduceSideEffectsInDonConfigIds() (gas: 1323263) +DestinationVerifierSetConfigTest:test_donConfigIdIsSameForSignersInDifferentOrder() (gas: 1290458) +DestinationVerifierSetConfigTest:test_removeLatestConfig() (gas: 786139) DestinationVerifierSetConfigTest:test_removeLatestConfigWhenNoConfigShouldFail() (gas: 12870) DestinationVerifierSetConfigTest:test_revertsIfCalledByNonOwner() (gas: 174936) -DestinationVerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 171604) -DestinationVerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 168484) -DestinationVerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 11571) -DestinationVerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 17943) -DestinationVerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 324333) +DestinationVerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 171284) +DestinationVerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 168506) +DestinationVerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 11578) +DestinationVerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 17928) +DestinationVerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 324013) DestinationVerifierSetConfigTest:test_setConfigActiveUnknownDonConfigId() (gas: 13102) -DestinationVerifierSetConfigTest:test_setConfigWithActivationTime() (gas: 1088176) -DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() (gas: 1963414) -DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeNoFutureTimeShouldFail() (gas: 259797) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTime() (gas: 1088137) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() (gas: 1963051) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeNoFutureTimeShouldFail() (gas: 259477) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeTheSameAsLatestConfigShouldFail() (gas: 1283835) FeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52645) FeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52595) -FeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78808) -FeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 26974) -FeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 58904) -FeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 116750) -FeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 27389) -FeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 70364) +FeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78830) +FeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 26980) +FeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 58910) +FeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 116756) +FeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 27395) +FeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 70370) FeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 72682) FeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 56286) FeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 26387) -FeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 17190) -FeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 20128) -FeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91011) -FeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 56534) +FeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 17167) +FeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 20150) +FeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91033) +FeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 56556) FeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 52847) -FeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49636) +FeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49658) FeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 78903) FeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 46511) FeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17560) @@ -256,17 +291,17 @@ FeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 54604) FeeManagerProcessFeeTest:test_discountIsReturnedForLink() (gas: 49608) FeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12163) FeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41356) -FeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 173756) +FeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 173762) FeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 69009) -FeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 49757) +FeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 49722) FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67699) -FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 64368) +FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 64324) FeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 52045) -FeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 17207) +FeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 17165) FeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 49829) -FeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55641) -FeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 82765) -FeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49654) +FeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55618) +FeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 82787) +FeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49676) FeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49657) FeeManagerProcessFeeTest:test_getRewardWithNativeQuote() (gas: 20148) FeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 50838) @@ -275,43 +310,43 @@ FeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 30848) FeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 50863) FeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 17175) FeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41402) -FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51868) -FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78104) +FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51890) +FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78081) FeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 21895) -FeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19849) -FeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 194429) +FeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19806) +FeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 194434) FeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17413) -FeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 214755) -FeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 198803) -FeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 117088) -FeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 27462) -FeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 163205) -FeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 27827) -FeeManagerProcessFeeTest:test_processFeeNative() (gas: 173826) -FeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 118379) -FeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 29536) -FeeManagerProcessFeeTest:test_processFeeWithDiscountEmitsEvent() (gas: 241353) -FeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 28511) -FeeManagerProcessFeeTest:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 166753) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 181691) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 131466) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 157072) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 92635) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 188654) -FeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 70675) -FeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 27727) -FeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 27777) -FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 32967) -FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 153725) -FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 53795) -FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 116999) -FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 35738) -FeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 223133) -FeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 256996) -FeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 74793) -FeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 239801) -FeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 207915) -FeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 249580) +FeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 214764) +FeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 198808) +FeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 117094) +FeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 27468) +FeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 163211) +FeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 30333) +FeeManagerProcessFeeTest:test_processFeeNative() (gas: 173832) +FeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 118385) +FeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 29542) +FeeManagerProcessFeeTest:test_processFeeWithDiscountEmitsEvent() (gas: 241359) +FeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 28517) +FeeManagerProcessFeeTest:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 166759) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 181697) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 131472) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 157078) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 92641) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 188660) +FeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 70681) +FeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 27733) +FeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 27783) +FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 32973) +FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 153731) +FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 53801) +FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 117005) +FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 35744) +FeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 223139) +FeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 257002) +FeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 74799) +FeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 239807) +FeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 207930) +FeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 249586) FeeManagerProcessFeeTest:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 13613) FeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 19562) FeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46261) @@ -321,70 +356,70 @@ FeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: FeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47076) FeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49938) FeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78261) -FeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14919) -MultiVerifierBillingTests:test_multipleFeeManagersAndVerifiers() (gas: 4586990) +FeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14941) +MultiVerifierBillingTests:test_multipleFeeManagersAndVerifiers() (gas: 4598496) RewardManagerClaimTest:test_claimAllRecipients() (gas: 277131) RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154341) RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330086) RewardManagerClaimTest:test_claimSingleRecipient() (gas: 89024) RewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315289) -RewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35145) +RewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35123) RewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41182) RewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86069) RewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25031) RewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386675) -RewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137685) +RewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137663) RewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 492113) -RewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11437) -RewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53894) +RewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11451) +RewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53912) RewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 250840) RewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20475) -RewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251086) -RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262290) -RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265775) -RewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28891) -RewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25312) +RewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251064) +RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262268) +RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265753) +RewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28869) +RewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25335) RewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31397) -RewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84696) -RewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198477) -RewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280793) +RewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84740) +RewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198455) +RewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280727) RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512369) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283589) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283634) RewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293418) RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263015) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154507) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154485) RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132623) RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106022) RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579532) RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64626) -RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13051) -RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12680) -RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22448) +RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13029) +RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12724) +RewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22426) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 32225) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148553) -RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21705) +RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21683) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 27742) RewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391245) -RewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137770) +RewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137748) RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199454) RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219327) -RewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191729) +RewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191707) RewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126082) RewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 193880) RewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21452) -RewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193324) +RewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193368) RewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180630) RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90224) RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 191334) RewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185589) -RewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87113) +RewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87136) RewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110371) -RewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 21388) +RewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 21366) RewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259132) RewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59411) -RewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17038) +RewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17105) RewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376628) -RewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280487) +RewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280509) RewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19749) RewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 220972) RewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274309) @@ -393,7 +428,7 @@ RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiv RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149916) RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259293) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372109) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270780) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270802) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288575) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407876) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 318029) @@ -402,26 +437,26 @@ RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithI RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399699) RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289513) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyRemovesAMiddleDigest() (gas: 27017) -VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyRemovesTheFirstDigest() (gas: 26984) +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) -VerifierActivateConfigTest:test_revertsIfDigestIsEmpty() (gas: 10984) +VerifierActivateConfigTest:test_revertsIfDigestIsEmpty() (gas: 10962) VerifierActivateConfigTest:test_revertsIfDigestNotSet() (gas: 13394) VerifierActivateConfigTest:test_revertsIfNotOwner() (gas: 17182) VerifierActivateConfigWithDeactivatedConfigTest:test_allowsVerification() (gas: 97175) VerifierActivateFeedTest:test_revertsIfNoFeedExistsActivate() (gas: 13179) -VerifierActivateFeedTest:test_revertsIfNoFeedExistsDeactivate() (gas: 13157) +VerifierActivateFeedTest:test_revertsIfNoFeedExistsDeactivate() (gas: 13202) VerifierActivateFeedTest:test_revertsIfNotOwnerActivateFeed() (gas: 17109) VerifierActivateFeedTest:test_revertsIfNotOwnerDeactivateFeed() (gas: 17164) -VerifierBillingTests:test_rewardsAreDistributedAccordingToWeights() (gas: 1731717) -VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsMultipleWeigths() (gas: 4460715) -VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsUsingHistoricalConfigs() (gas: 2098833) -VerifierBillingTests:test_verifyWithLinkV3Report() (gas: 1591346) -VerifierBillingTests:test_verifyWithNativeERC20() (gas: 1467256) -VerifierBillingTests:test_verifyWithNativeUnwrapped() (gas: 1376447) -VerifierBillingTests:test_verifyWithNativeUnwrappedReturnsChange() (gas: 1383493) +VerifierBillingTests:test_rewardsAreDistributedAccordingToWeights() (gas: 1736225) +VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsMultipleWeigths() (gas: 4468029) +VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsUsingHistoricalConfigs() (gas: 2106504) +VerifierBillingTests:test_verifyWithLinkV3Report() (gas: 1593640) +VerifierBillingTests:test_verifyWithNativeERC20() (gas: 1467541) +VerifierBillingTests:test_verifyWithNativeUnwrapped() (gas: 1378718) +VerifierBillingTests:test_verifyWithNativeUnwrappedReturnsChange() (gas: 1385742) VerifierBulkVerifyBillingReport:test_verifyMultiVersions() (gas: 476595) VerifierBulkVerifyBillingReport:test_verifyMultiVersionsReturnsVerifiedReports() (gas: 474853) VerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 557541) @@ -432,89 +467,89 @@ VerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: VerifierConstructorTest:test_setsTheCorrectProperties() (gas: 1813269) VerifierDeactivateFeedWithVerifyTest:test_currentReportAllowsVerification() (gas: 192073) VerifierDeactivateFeedWithVerifyTest:test_currentReportFailsVerification() (gas: 113388) -VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 99624) +VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 99669) VerifierDeactivateFeedWithVerifyTest:test_previousReportFailsVerification() (gas: 69943) -VerifierInterfacesTest:test_DestinationContractInterfaces() (gas: 623467) -VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 208529) -VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 112345) -VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1485359) +VerifierInterfacesTest:test_DestinationContractInterfaces() (gas: 628150) +VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 208507) +VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 112323) +VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1485337) VerifierProxyConstructorTest:test_correctlySetsTheOwner() (gas: 1465483) -VerifierProxyConstructorTest:test_correctlySetsVersion() (gas: 9701) -VerifierProxyInitializeVerifierTest:test_revertsIfDigestAlreadySet() (gas: 54133) +VerifierProxyConstructorTest:test_correctlySetsVersion() (gas: 9767) +VerifierProxyInitializeVerifierTest:test_revertsIfDigestAlreadySet() (gas: 54117) VerifierProxyInitializeVerifierTest:test_revertsIfNotCorrectVerifier() (gas: 13613) VerifierProxyInitializeVerifierTest:test_revertsIfNotOwner() (gas: 17168) -VerifierProxyInitializeVerifierTest:test_revertsIfVerifierAlreadyInitialized() (gas: 42047) +VerifierProxyInitializeVerifierTest:test_revertsIfVerifierAlreadyInitialized() (gas: 42053) VerifierProxyInitializeVerifierTest:test_revertsIfZeroAddress() (gas: 10956) -VerifierProxyInitializeVerifierTest:test_setFeeManagerWhichDoesntHonourIERC165Interface() (gas: 13823) +VerifierProxyInitializeVerifierTest:test_setFeeManagerWhichDoesntHonourIERC165Interface() (gas: 13890) VerifierProxyInitializeVerifierTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16290) -VerifierProxyInitializeVerifierTest:test_setFeeManagerZeroAddress() (gas: 10933) +VerifierProxyInitializeVerifierTest:test_setFeeManagerZeroAddress() (gas: 10911) VerifierProxyInitializeVerifierTest:test_updatesVerifierIfVerifier() (gas: 54086) VerifierProxySetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35348) -VerifierProxySetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15069) +VerifierProxySetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15025) VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34921) -VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15020) +VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15065) VerifierProxyUnsetVerifierTest:test_revertsIfDigestDoesNotExist() (gas: 13149) VerifierProxyUnsetVerifierTest:test_revertsIfNotAdmin() (gas: 14973) VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_correctlyUnsetsVerifier() (gas: 15555) -VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17961) +VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17985) VerifierProxyVerifyTest:test_proxiesToTheCorrectVerifier() (gas: 204342) -VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 117264) -VerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 17196) -VerifierSetAccessControllerTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16571) -VerifierSetAccessControllerTest:test_successfullySetsNewFeeManager() (gas: 44855) -VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542302) -VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967768) -VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 523251) +VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 117331) +VerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 17152) +VerifierSetAccessControllerTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16272) +VerifierSetAccessControllerTest:test_successfullySetsNewFeeManager() (gas: 42214) +VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542280) +VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967835) +VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 523229) VerifierSetConfigFromSourceTest:test_revertsIfCalledByNonOwner() (gas: 183217) -VerifierSetConfigTest:test_correctlyUpdatesTheConfig() (gas: 1062438) +VerifierSetConfigTest:test_correctlyUpdatesTheConfig() (gas: 1062416) VerifierSetConfigTest:test_revertsIfCalledByNonOwner() (gas: 182986) -VerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 251561) +VerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 251595) VerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 176543) -VerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 15828) -VerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 22213) -VerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 228034) -VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542051) -VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967257) -VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 522991) +VerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 15842) +VerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 22182) +VerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 228025) +VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542029) +VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967324) +VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 522969) VerifierSupportsInterfaceTest:test_falseIfIsNotCorrectInterface() (gas: 8421) VerifierSupportsInterfaceTest:test_trueIfIsCorrectInterface() (gas: 8464) VerifierTestBillingReport:test_verifyWithLink() (gas: 275293) VerifierTestBillingReport:test_verifyWithNative() (gas: 316326) -VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 318574) +VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 318619) VerifierTestBillingReport:test_verifyWithNativeUnwrappedReturnsChange() (gas: 325642) -VerifierVerifyBulkTest:test_revertsVerifyBulkIfNoAccess() (gas: 112867) -VerifierVerifyBulkTest:test_verifyBulkSingleCaseWithSingleConfig() (gas: 745046) -VerifierVerifyBulkTest:test_verifyBulkWithSingleConfigOneVerifyFails() (gas: 698203) +VerifierVerifyBulkTest:test_revertsVerifyBulkIfNoAccess() (gas: 112855) +VerifierVerifyBulkTest:test_verifyBulkSingleCaseWithSingleConfig() (gas: 745006) +VerifierVerifyBulkTest:test_verifyBulkWithSingleConfigOneVerifyFails() (gas: 698163) VerifierVerifyMultipleConfigDigestTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 133961) -VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 189865) +VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 189843) VerifierVerifyMultipleConfigDigestTest:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 88216) VerifierVerifyMultipleConfigDigestTest:test_revertsIfVerifyingWithAnUnsetDigest() (gas: 128073) -VerifierVerifySingleConfigDigestTest:test_emitsAnEventIfReportVerified() (gas: 186956) +VerifierVerifySingleConfigDigestTest:test_emitsAnEventIfReportVerified() (gas: 186934) VerifierVerifySingleConfigDigestTest:test_returnsThePriceAndBlockNumIfReportVerified() (gas: 189847) -VerifierVerifySingleConfigDigestTest:test_revertsIfConfigDigestNotSet() (gas: 116141) -VerifierVerifySingleConfigDigestTest:test_revertsIfDuplicateSignersHaveSigned() (gas: 182326) -VerifierVerifySingleConfigDigestTest:test_revertsIfMismatchedSignatureLength() (gas: 53108) +VerifierVerifySingleConfigDigestTest:test_revertsIfConfigDigestNotSet() (gas: 116184) +VerifierVerifySingleConfigDigestTest:test_revertsIfDuplicateSignersHaveSigned() (gas: 182371) +VerifierVerifySingleConfigDigestTest:test_revertsIfMismatchedSignatureLength() (gas: 53086) VerifierVerifySingleConfigDigestTest:test_revertsIfReportHasUnconfiguredFeedID() (gas: 103987) VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedByNonProxy() (gas: 100992) -VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184077) +VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184055) VerifierVerifySingleConfigDigestTest:test_revertsIfWrongNumberOfSigners() (gas: 110042) -VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194592) -VerifierVerifyTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 861741) -VerifierVerifyTest:test_canVerifyOlderV3ReportsWithOlderConfigs() (gas: 815984) -VerifierVerifyTest:test_failToVerifyReportIfDupSigners() (gas: 450715) -VerifierVerifyTest:test_failToVerifyReportIfNoSigners() (gas: 426492) -VerifierVerifyTest:test_failToVerifyReportIfNotEnoughSigners() (gas: 434814) -VerifierVerifyTest:test_failToVerifyReportIfSignerNotInConfig() (gas: 456866) -VerifierVerifyTest:test_revertsVerifyIfNoAccess() (gas: 109465) -VerifierVerifyTest:test_rollingOutConfiguration() (gas: 1497254) -VerifierVerifyTest:test_scenarioRollingNewChainWithHistoricConfigs() (gas: 976162) -VerifierVerifyTest:test_verifyFailsWhenReportIsOlderThanConfig() (gas: 2303366) -VerifierVerifyTest:test_verifyReport() (gas: 1434811) -VerifierVerifyTest:test_verifyTooglingActiveFlagsDonConfigs() (gas: 1918797) +VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194637) +VerifierVerifyTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 862947) +VerifierVerifyTest:test_canVerifyOlderV3ReportsWithOlderConfigs() (gas: 815914) +VerifierVerifyTest:test_failToVerifyReportIfDupSigners() (gas: 450740) +VerifierVerifyTest:test_failToVerifyReportIfNoSigners() (gas: 426452) +VerifierVerifyTest:test_failToVerifyReportIfNotEnoughSigners() (gas: 434774) +VerifierVerifyTest:test_failToVerifyReportIfSignerNotInConfig() (gas: 456826) +VerifierVerifyTest:test_revertsVerifyIfNoAccess() (gas: 109453) +VerifierVerifyTest:test_rollingOutConfiguration() (gas: 1497118) +VerifierVerifyTest:test_scenarioRollingNewChainWithHistoricConfigs() (gas: 976048) +VerifierVerifyTest:test_verifyFailsWhenReportIsOlderThanConfig() (gas: 2303309) +VerifierVerifyTest:test_verifyReport() (gas: 1434779) +VerifierVerifyTest:test_verifyTooglingActiveFlagsDonConfigs() (gas: 1918758) Verifier_accessControlledVerify:testVerifyWithAccessControl_gas() (gas: 212077) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithLinkFeeSuccess_gas() (gas: 519389) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithNativeFeeSuccess_gas() (gas: 542808) -Verifier_setConfig:testSetConfigSuccess_gas() (gas: 922616) +Verifier_setConfig:testSetConfigSuccess_gas() (gas: 922625) Verifier_verify:testVerifyProxySuccess_gas() (gas: 198742) Verifier_verify:testVerifySuccess_gas() (gas: 186736) Verifier_verifyWithFee:testVerifyProxyWithLinkFeeSuccess_gas() (gas: 238899) diff --git a/contracts/gas-snapshots/operatorforwarder.gas-snapshot b/contracts/gas-snapshots/operatorforwarder.gas-snapshot index 7cfc963f74e..724b764a19d 100644 --- a/contracts/gas-snapshots/operatorforwarder.gas-snapshot +++ b/contracts/gas-snapshots/operatorforwarder.gas-snapshot @@ -1,15 +1,15 @@ FactoryTest:test_DeployNewForwarderAndTransferOwnership_Success() (gas: 1059722) FactoryTest:test_DeployNewForwarder_Success() (gas: 1048209) FactoryTest:test_DeployNewOperatorAndForwarder_Success() (gas: 4069305) -FactoryTest:test_DeployNewOperator_Success() (gas: 3020464) -ForwarderTest:test_Forward_Success(uint256) (runs: 256, μ: 226200, ~: 227289) -ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 256, μ: 257876, ~: 259120) -ForwarderTest:test_OwnerForward_Success() (gas: 30118) +FactoryTest:test_DeployNewOperator_Success() (gas: 3020509) +ForwarderTest:test_Forward_Success(uint256) (runs: 257, μ: 226966, ~: 227276) +ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 257, μ: 258642, ~: 259185) +ForwarderTest:test_OwnerForward_Success() (gas: 30090) ForwarderTest:test_SetAuthorizedSenders_Success() (gas: 160524) -ForwarderTest:test_TransferOwnershipWithMessage_Success() (gas: 35123) -OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) -OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) -OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) -OperatorTest:test_OracleRequest_Success() (gas: 250019) -OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387120, ~: 387124) -OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303611, ~: 303615) \ No newline at end of file +ForwarderTest:test_TransferOwnershipWithMessage_Success() (gas: 35141) +OperatorTest:test_CancelOracleRequest_Success() (gas: 274465) +OperatorTest:test_FulfillOracleRequest_Success() (gas: 330649) +OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246764) +OperatorTest:test_OracleRequest_Success() (gas: 250043) +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 257, μ: 387179, ~: 387183) +OperatorTest:test_SendRequest_Success(uint96) (runs: 257, μ: 303633, ~: 303636) \ No newline at end of file diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index 3cc143ecc0e..9570511e5d5 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -1,35 +1,35 @@ -AuthorizedCallers_applyAuthorizedCallerUpdates:test_AddAndRemove_Success() (gas: 125205) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyAdd_Success() (gas: 133100) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyCallableByOwner_Revert() (gas: 12350) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyRemove_Success() (gas: 45064) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_RemoveThenAdd_Success() (gas: 57241) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 32121) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64473) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_AddAndRemove_Success() (gas: 125125) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyAdd_Success() (gas: 132989) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyCallableByOwner_Revert() (gas: 12328) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyRemove_Success() (gas: 44964) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_RemoveThenAdd_Success() (gas: 57111) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 32018) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64496) AuthorizedCallers_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 64473) -AuthorizedCallers_constructor:test_constructor_Success() (gas: 720513) +AuthorizedCallers_constructor:test_constructor_Success() (gas: 720510) BurnMintERC677_approve:testApproveSuccess() (gas: 55512) BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10663) BurnMintERC677_burn:testBasicBurnSuccess() (gas: 173939) BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 47201) BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 21841) BurnMintERC677_burn:testSenderNotBurnerReverts() (gas: 13359) -BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57923) +BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57959) BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 35864) BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 21849) BurnMintERC677_burnFrom:testSenderNotBurnerReverts() (gas: 13359) -BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57949) +BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57985) BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 35880) BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 21869) BurnMintERC677_burnFromAlias:testSenderNotBurnerReverts() (gas: 13379) BurnMintERC677_constructor:testConstructorSuccess() (gas: 1672809) BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 31069) BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 121324) -BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 53460) +BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 53442) BurnMintERC677_grantRole:testGrantManySuccess() (gas: 937759) -BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 94340) +BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 94323) BurnMintERC677_increaseApproval:testIncreaseApprovalSuccess() (gas: 44076) BurnMintERC677_mint:testBasicMintSuccess() (gas: 149699) -BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50385) +BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50363) BurnMintERC677_mint:testSenderNotMinterReverts() (gas: 11195) BurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12476) BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10639) @@ -39,50 +39,50 @@ CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11559) CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15788) CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16241) -CallWithExactGas__callWithExactGas:test_callWithExactGasSuccess(bytes,bytes4) (runs: 256, μ: 15811, ~: 15752) +CallWithExactGas__callWithExactGas:test_callWithExactGasSuccess(bytes,bytes4) (runs: 257, μ: 15744, ~: 15697) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20116) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 67721) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes,bytes4) (runs: 256, μ: 16321, ~: 16262) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 67699) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes,bytes4) (runs: 257, μ: 16254, ~: 16207) 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: 13917) +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: 36752) +CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16569) +CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36711) EnumerableMapAddresses_at:testAtSuccess() (gas: 95086) -EnumerableMapAddresses_at:testBytes32AtSuccess() (gas: 94877) +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: 94278) -EnumerableMapAddresses_get:testGetSuccess() (gas: 94453) +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:testLengthSuccess() (gas: 72640) +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:testSetSuccess() (gas: 94685) +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) -EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96564) -EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 94012) -EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95879) -EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95878) -EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73011) -EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74249) -EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95428) -EnumerableMapAddresses_tryGet:testBytesTryGetSuccess() (gas: 96279) -OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1743649) -OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 298649) +OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1743682) +OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 298739) OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137957) OpStackBurnMintERC677_interfaceCompatibility:testStaticFunctionsCompatibility() (gas: 13781) OpStackBurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12752) SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySubset_Reverts() (gas: 5460) SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySuperset_Reverts() (gas: 4661) SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_HasDuplicates_Reverts() (gas: 8265) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_NotASubset_Reverts() (gas: 12487) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_NotASubset_Reverts() (gas: 12552) SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubset() (gas: 4489) SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() (gas: 1464) SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() (gas: 6172) diff --git a/contracts/gas-snapshots/transmission.gas-snapshot b/contracts/gas-snapshots/transmission.gas-snapshot index 1588faf7b9a..c8e7ad7c189 100644 --- a/contracts/gas-snapshots/transmission.gas-snapshot +++ b/contracts/gas-snapshots/transmission.gas-snapshot @@ -1,4 +1,4 @@ -EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccount() (gas: 910982) -EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() (gas: 2287249) -EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() (gas: 2877786) -EIP_712_1014_4337:testEIP712EIP4337WithExistingSmartContractAccount() (gas: 879722) \ No newline at end of file +EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccount() (gas: 911002) +EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() (gas: 2287257) +EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() (gas: 2877780) +EIP_712_1014_4337:testEIP712EIP4337WithExistingSmartContractAccount() (gas: 879760) \ No newline at end of file diff --git a/contracts/package.json b/contracts/package.json index 85bae226c43..a421925e40b 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -42,50 +42,51 @@ "@ethersproject/contracts": "~5.7.0", "@ethersproject/providers": "~5.7.2", "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", - "@nomicfoundation/hardhat-ethers": "^3.0.6", - "@nomicfoundation/hardhat-network-helpers": "^1.0.9", - "@nomicfoundation/hardhat-verify": "^2.0.7", + "@nomicfoundation/hardhat-ethers": "^3.0.8", + "@nomicfoundation/hardhat-network-helpers": "^1.0.12", + "@nomicfoundation/hardhat-verify": "^2.0.11", "@typechain/ethers-v5": "^7.2.0", "@typechain/hardhat": "^7.0.0", "@types/cbor": "~5.0.1", - "@types/chai": "^4.3.16", + "@types/chai": "^4.3.20", "@types/debug": "^4.1.12", "@types/deep-equal-in-any-order": "^1.0.3", - "@types/mocha": "^10.0.6", - "@types/node": "^20.12.12", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", + "@types/mocha": "^10.0.8", + "@types/node": "^20.16.10", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "abi-to-sol": "^0.6.6", "cbor": "^5.2.0", - "chai": "^4.3.10", - "debug": "^4.3.4", + "chai": "^4.5.0", + "debug": "^4.3.7", "deep-equal-in-any-order": "^2.0.6", - "eslint": "^8.57.0", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.1", "ethers": "~5.7.2", "hardhat": "~2.20.1", "hardhat-abi-exporter": "^2.10.1", "hardhat-ignore-warnings": "^0.2.6", "moment": "^2.30.1", - "prettier": "^3.2.5", - "prettier-plugin-solidity": "^1.3.1", - "solhint": "^5.0.1", + "prettier": "^3.3.3", + "prettier-plugin-solidity": "^1.4.1", + "solhint": "^5.0.3", "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1", "solhint-plugin-prettier": "^0.1.0", "ts-node": "^10.9.2", "typechain": "^8.2.1", - "typescript": "^5.4.5" + "typescript": "^5.6.2" }, "dependencies": { "@arbitrum/nitro-contracts": "1.1.1", "@arbitrum/token-bridge-contracts": "1.1.2", "@changesets/changelog-github": "^0.5.0", - "@changesets/cli": "~2.27.3", + "@changesets/cli": "~2.27.8", "@eth-optimism/contracts": "0.6.0", "@openzeppelin/contracts": "4.9.3", "@openzeppelin/contracts-upgradeable": "4.9.3", "@scroll-tech/contracts": "0.1.0", - "semver": "^7.6.2" + "@zksync/contracts": "git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9", + "semver": "^7.6.3" } } diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index 825715f4160..20fcd2e2eed 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^0.5.0 version: 0.5.0 '@changesets/cli': - specifier: ~2.27.3 - version: 2.27.3 + specifier: ~2.27.8 + version: 2.27.8 '@eth-optimism/contracts': specifier: 0.6.0 version: 0.6.0(ethers@5.7.2) @@ -35,9 +35,12 @@ importers: '@scroll-tech/contracts': specifier: 0.1.0 version: 0.1.0 + '@zksync/contracts': + specifier: git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9 + version: era-contracts@https://codeload.github.com/matter-labs/era-contracts/tar.gz/446d391d34bdb48255d5f8fef8a8248925fc98b9 semver: - specifier: ^7.6.2 - version: 7.6.2 + specifier: ^7.6.3 + version: 7.6.3 devDependencies: '@ethereum-waffle/mock-contract': specifier: ^3.4.4 @@ -56,28 +59,28 @@ importers: version: 5.7.2 '@nomicfoundation/hardhat-chai-matchers': specifier: ^1.0.6 - version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)))(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.6 - version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + specifier: ^3.0.8 + version: 3.0.8(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.9 - version: 1.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + specifier: ^1.0.12 + version: 1.0.12(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/hardhat-verify': - specifier: ^2.0.7 - version: 2.0.7(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + specifier: ^2.0.11 + version: 2.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@typechain/ethers-v5': specifier: ^7.2.0 - version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) + version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2) '@typechain/hardhat': specifier: ^7.0.0 - version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))(typechain@8.3.2(typescript@5.4.5)) + version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2)) '@types/cbor': specifier: ~5.0.1 version: 5.0.1 '@types/chai': - specifier: ^4.3.16 - version: 4.3.16 + specifier: ^4.3.20 + version: 4.3.20 '@types/debug': specifier: ^4.1.12 version: 4.1.12 @@ -85,17 +88,17 @@ importers: specifier: ^1.0.3 version: 1.0.3 '@types/mocha': - specifier: ^10.0.6 - version: 10.0.6 + specifier: ^10.0.8 + version: 10.0.8 '@types/node': - specifier: ^20.12.12 - version: 20.12.12 + specifier: ^20.16.10 + version: 20.16.10 '@typescript-eslint/eslint-plugin': - specifier: ^7.10.0 - version: 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.18.0 + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/parser': - specifier: ^7.10.0 - version: 7.10.0(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.18.0 + version: 7.18.0(eslint@8.57.1)(typescript@5.6.2) abi-to-sol: specifier: ^0.6.6 version: 0.6.6 @@ -103,32 +106,32 @@ importers: specifier: ^5.2.0 version: 5.2.0 chai: - specifier: ^4.3.10 - version: 4.4.1 + specifier: ^4.5.0 + version: 4.5.0 debug: - specifier: ^4.3.4 - version: 4.3.4(supports-color@8.1.1) + specifier: ^4.3.7 + version: 4.3.7 deep-equal-in-any-order: specifier: ^2.0.6 version: 2.0.6 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^8.57.1 + version: 8.57.1 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) + version: 9.1.0(eslint@8.57.1) eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) + specifier: ^5.2.1 + version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3) ethers: specifier: ~5.7.2 version: 5.7.2 hardhat: specifier: ~2.20.1 - version: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + version: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) hardhat-abi-exporter: specifier: ^2.10.1 - version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.11 @@ -136,29 +139,29 @@ importers: specifier: ^2.30.1 version: 2.30.1 prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.3.3 + version: 3.3.3 prettier-plugin-solidity: - specifier: ^1.3.1 - version: 1.3.1(prettier@3.2.5) + specifier: ^1.4.1 + version: 1.4.1(prettier@3.3.3) solhint: - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^5.0.3 + version: 5.0.3 solhint-plugin-chainlink-solidity: specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1 version: '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c' solhint-plugin-prettier: specifier: ^0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5) + version: 0.1.0(prettier-plugin-solidity@1.4.1(prettier@3.3.3))(prettier@3.3.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) + version: 10.9.2(@types/node@20.16.10)(typescript@5.6.2) typechain: specifier: ^8.2.1 - version: 8.3.2(typescript@5.4.5) + version: 8.3.2(typescript@5.6.2) typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.6.2 + version: 5.6.2 packages: @@ -192,11 +195,11 @@ packages: resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c} version: 1.2.0 - '@changesets/apply-release-plan@7.0.1': - resolution: {integrity: sha512-aPdSq/R++HOyfEeBGjEe6LNG8gs0KMSyRETD/J2092OkNq8mOioAxyKjMbvVUdzgr/HTawzMOz7lfw339KnsCA==} + '@changesets/apply-release-plan@7.0.5': + resolution: {integrity: sha512-1cWCk+ZshEkSVEZrm2fSj1Gz8sYvxgUL4Q78+1ZZqeqfuevPTPk033/yUZ3df8BKMohkqqHfzj0HOOrG0KtXTw==} - '@changesets/assemble-release-plan@6.0.0': - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + '@changesets/assemble-release-plan@6.0.4': + resolution: {integrity: sha512-nqICnvmrwWj4w2x0fOhVj2QEGdlUuwVAwESrUo5HLzWMI1rE5SWfsr9ln+rDqWB6RQ2ZyaMZHUcU7/IRaUJS+Q==} '@changesets/changelog-git@0.2.0': resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} @@ -204,42 +207,45 @@ packages: '@changesets/changelog-github@0.5.0': resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} - '@changesets/cli@2.27.3': - resolution: {integrity: sha512-ve/VpWApILlSs8cr0okNx5C2LKRawI9XZgvfmf58S8sar2nhx5DPJREFXYZBahs0FeTfvH0rdVl+nGe8QF45Ig==} + '@changesets/cli@2.27.8': + resolution: {integrity: sha512-gZNyh+LdSsI82wBSHLQ3QN5J30P4uHKJ4fXgoGwQxfXwYFTJzDdvIJasZn8rYQtmKhyQuiBj4SSnLuKlxKWq4w==} hasBin: true - '@changesets/config@3.0.0': - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + '@changesets/config@3.0.3': + resolution: {integrity: sha512-vqgQZMyIcuIpw9nqFIpTSNyc/wgm/Lu1zKN5vECy74u95Qx/Wa9g27HdgO4NkVAaq+BGA8wUc/qvbvVNs93n6A==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - '@changesets/get-dependents-graph@2.0.0': - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + '@changesets/get-dependents-graph@2.1.2': + resolution: {integrity: sha512-sgcHRkiBY9i4zWYBwlVyAjEM9sAzs4wYVwJUdnbDLnVG3QwAaia1Mk5P8M7kraTOZN+vBET7n8KyB0YXCbFRLQ==} '@changesets/get-github-info@0.6.0': resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - '@changesets/get-release-plan@4.0.0': - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + '@changesets/get-release-plan@4.0.4': + resolution: {integrity: sha512-SicG/S67JmPTrdcc9Vpu0wSQt7IiuN0dc8iR5VScnnTVPfIaLvKmEGRvIaF0kcn8u5ZqLbormZNTO77bCEvyWw==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - '@changesets/git@3.0.0': - resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + '@changesets/git@3.0.1': + resolution: {integrity: sha512-pdgHcYBLCPcLd82aRcuO0kxCDbw/yISlOtkmwmE8Odo1L6hSiZrBOsRl84eYG7DRCab/iHnOkWqExqc4wxk2LQ==} - '@changesets/logger@0.1.0': - resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} '@changesets/parse@0.4.0': resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} - '@changesets/pre@2.0.0': - resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + '@changesets/pre@2.0.1': + resolution: {integrity: sha512-vvBJ/If4jKM4tPz9JdY2kGOgWmCowUYOi5Ycv8dyLnEE8FgpYYUo1mgJZxcdtGGP3aG8rAQulGLyyXGSLkIMTQ==} + + '@changesets/read@0.6.1': + resolution: {integrity: sha512-jYMbyXQk3nwP25nRzQQGa1nKLY0KfoOV7VLgwucI0bUO8t8ZLCr6LZmgjXsiKuRDc+5A6doKPr9w2d+FEJ55zQ==} - '@changesets/read@0.6.0': - resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + '@changesets/should-skip-package@0.1.1': + resolution: {integrity: sha512-H9LjLbF6mMHLtJIc/eHR9Na+MifJ3VxtgP/Y+XLn4BF7tDTEN1HNYtH6QMcjP1uxp9sjaFYmW8xqloaCi/ckTg==} '@changesets/types@4.1.0': resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} @@ -247,8 +253,8 @@ packages: '@changesets/types@6.0.0': resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - '@changesets/write@0.3.1': - resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} + '@changesets/write@0.3.2': + resolution: {integrity: sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==} '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} @@ -268,8 +274,8 @@ packages: resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@eth-optimism/contracts@0.6.0': @@ -378,9 +384,10 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -388,6 +395,7 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead '@jridgewell/resolve-uri@3.1.1': resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} @@ -497,19 +505,19 @@ packages: ethers: ^5.0.0 hardhat: ^2.9.4 - '@nomicfoundation/hardhat-ethers@3.0.6': - resolution: {integrity: sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA==} + '@nomicfoundation/hardhat-ethers@3.0.8': + resolution: {integrity: sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==} peerDependencies: ethers: ^6.1.0 hardhat: ^2.0.0 - '@nomicfoundation/hardhat-network-helpers@1.0.10': - resolution: {integrity: sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==} + '@nomicfoundation/hardhat-network-helpers@1.0.12': + resolution: {integrity: sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==} peerDependencies: hardhat: ^2.9.5 - '@nomicfoundation/hardhat-verify@2.0.7': - resolution: {integrity: sha512-jiYHBX+K6bBN0YhwFHQ5SWWc3dQZliM3pdgpH33C7tnsVACsX1ubZn6gZ9hfwlzG0tyjFM72XQhpaXQ56cE6Ew==} + '@nomicfoundation/hardhat-verify@2.0.11': + resolution: {integrity: sha512-lGIo4dNjVQFdsiEgZp3KP6ntLiF7xJEJsbNHfSyIiFCyI0Yv0518ElsFtMC5uCuHEChiBBMrib9jWQvHHT+X3Q==} peerDependencies: hardhat: ^2.0.4 @@ -679,9 +687,6 @@ packages: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} - '@solidity-parser/parser@0.17.0': - resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} - '@solidity-parser/parser@0.18.0': resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} @@ -742,8 +747,8 @@ packages: '@types/chai-as-promised@7.1.8': resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} + '@types/chai@4.3.20': + resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -760,11 +765,8 @@ packages: '@types/lru-cache@5.1.1': resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - '@types/minimist@1.2.5': - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - - '@types/mocha@10.0.6': - resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} + '@types/mocha@10.0.8': + resolution: {integrity: sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==} '@types/ms@0.7.31': resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} @@ -772,11 +774,8 @@ packages: '@types/node@12.19.16': resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} - '@types/node@20.12.12': - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} - - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/node@20.16.10': + resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} '@types/pbkdf2@3.1.0': resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} @@ -796,8 +795,8 @@ packages: '@types/semver@7.5.0': resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} - '@typescript-eslint/eslint-plugin@7.10.0': - resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -807,8 +806,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.10.0': - resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==} + '@typescript-eslint/parser@7.18.0': + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -817,12 +816,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.10.0': - resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==} + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.10.0': - resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==} + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -831,12 +830,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.10.0': - resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==} + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.10.0': - resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==} + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -844,14 +843,14 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.10.0': - resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==} + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.10.0': - resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==} + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': @@ -975,10 +974,6 @@ packages: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} - array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.2: resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} engines: {node: '>= 0.4'} @@ -987,10 +982,6 @@ packages: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -1068,9 +1059,6 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} - brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} @@ -1122,14 +1110,6 @@ packages: camel-case@3.0.0: resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} - camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -1151,8 +1131,8 @@ packages: peerDependencies: chai: '>= 2.1.2 < 5' - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} chalk@2.4.2: @@ -1194,23 +1174,12 @@ packages: resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} engines: {node: '>=6'} - cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clone-response@1.0.2: resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - code-error-fragment@0.0.230: resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==} engines: {node: '>= 4'} @@ -1250,7 +1219,7 @@ packages: resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} @@ -1289,19 +1258,6 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - - csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - - csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - - csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} - data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -1326,13 +1282,14 @@ packages: supports-color: optional: true - decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - - decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true decamelize@4.0.0: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} @@ -1356,9 +1313,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -1428,6 +1382,10 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} + era-contracts@https://codeload.github.com/matter-labs/era-contracts/tar.gz/446d391d34bdb48255d5f8fef8a8248925fc98b9: + resolution: {tarball: https://codeload.github.com/matter-labs/era-contracts/tar.gz/446d391d34bdb48255d5f8fef8a8248925fc98b9} + version: 0.1.0 + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1484,8 +1442,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1506,8 +1464,8 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true @@ -1623,9 +1581,6 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - find-yarn-workspace-root@2.0.0: resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==} @@ -1741,6 +1696,7 @@ packages: glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} @@ -1770,10 +1726,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - hardhat-abi-exporter@2.10.1: resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} engines: {node: '>=14.14.0'} @@ -1832,10 +1784,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - hash-base@3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} engines: {node: '>=4'} @@ -1861,9 +1809,6 @@ packages: hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - http-cache-semantics@4.0.3: resolution: {integrity: sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==} @@ -1886,10 +1831,6 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1958,9 +1899,6 @@ packages: resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} hasBin: true - is-core-module@2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} - is-data-view@1.0.1: resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} engines: {node: '>= 0.4'} @@ -2013,10 +1951,6 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - is-plain-obj@2.1.0: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} @@ -2129,26 +2063,15 @@ packages: resolution: {integrity: sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==} engines: {node: '>=10.0.0'} - keyv@4.5.0: - resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - klaw-sync@6.0.0: resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} klaw@1.3.1: resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - latest-version@7.0.0: resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} engines: {node: '>=14.16'} @@ -2164,10 +2087,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} - locate-path@2.0.0: resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} engines: {node: '>=4'} @@ -2238,14 +2157,6 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - - map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} @@ -2253,10 +2164,6 @@ packages: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} - meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2273,10 +2180,6 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -2298,17 +2201,9 @@ packages: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} - minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -2325,6 +2220,10 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -2376,9 +2275,6 @@ packages: resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} engines: {node: '>=12.19'} - normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2482,6 +2378,9 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} + package-manager-detector@0.2.0: + resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==} + param-case@2.1.1: resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} @@ -2542,6 +2441,9 @@ packages: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -2550,10 +2452,6 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -2562,10 +2460,6 @@ packages: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} - preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} - engines: {node: '>=10'} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2574,8 +2468,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier-plugin-solidity@1.3.1: - resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} + prettier-plugin-solidity@1.4.1: + resolution: {integrity: sha512-Mq8EtfacVZ/0+uDKTtHZGW3Aa7vEbX/BNx63hmVg6YTiTXSiuKP0amj0G6pGwjmLaOfymWh3QgXEZkjQbU8QRg==} engines: {node: '>=16'} peerDependencies: prettier: '>=2.3.0' @@ -2585,8 +2479,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true @@ -2609,10 +2503,6 @@ packages: pure-rand@5.0.3: resolution: {integrity: sha512-9N8x1h8dptBQpHyC7aZMS+iNOAm97WMGY0AFrguU1cpfW3I5jINkWe5BIY5md0ofy+1TCIELsVcm/GJXZSaPbw==} - quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -2628,14 +2518,6 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - - read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -2648,10 +2530,6 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - reduce-flatten@2.0.0: resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} engines: {node: '>=6'} @@ -2683,9 +2561,6 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} @@ -2700,10 +2575,6 @@ packages: resolve@1.17.0: resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} - resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true - responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} @@ -2721,6 +2592,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true ripemd160@2.0.2: @@ -2778,8 +2650,8 @@ packages: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true @@ -2789,9 +2661,6 @@ packages: serialize-javascript@6.0.0: resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.1.1: resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} engines: {node: '>= 0.4'} @@ -2851,11 +2720,6 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true - snake-case@2.1.0: resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} @@ -2870,8 +2734,8 @@ packages: prettier: ^3.0.0 prettier-plugin-solidity: ^1.0.0 - solhint@5.0.1: - resolution: {integrity: sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg==} + solhint@5.0.3: + resolution: {integrity: sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ==} hasBin: true solidity-ast@0.4.56: @@ -2889,9 +2753,6 @@ packages: cpu: [x64] os: [darwin] - solidity-comments-extractor@0.0.8: - resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} - solidity-comments-freebsd-x64@0.0.2: resolution: {integrity: sha512-8Qe4mpjuAxFSwZJVk7B8gAoLCdbtS412bQzBwk63L8dmlHogvE39iT70aAk3RHUddAppT5RMBunlPUCFYJ3ZTw==} engines: {node: '>= 10'} @@ -2957,18 +2818,6 @@ packages: spawndamnit@2.0.0: resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} - spdx-correct@3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} - - spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.12: - resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} - sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -2980,9 +2829,6 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} - string-format@2.0.0: resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} @@ -3026,10 +2872,6 @@ packages: resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=} engines: {node: '>=6.5.0', npm: '>=3'} - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -3050,15 +2892,11 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - swap-case@1.1.2: resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} table-layout@1.0.2: @@ -3094,10 +2932,6 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -3136,11 +2970,6 @@ packages: tsort@0.0.1: resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true - tweetnacl-util@0.15.1: resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} @@ -3155,9 +2984,9 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} @@ -3167,18 +2996,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - type-fest@0.7.1: resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} engines: {node: '>=8'} - type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - typechain@8.3.2: resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} hasBin: true @@ -3216,8 +3037,8 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} hasBin: true @@ -3232,8 +3053,8 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} undici@5.28.4: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} @@ -3273,12 +3094,6 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - web3-utils@1.7.4: resolution: {integrity: sha512-acBdm6Evd0TEZRnChM/MCvGsMwYKmSh7OaUfNf5OKG0CIeGWD/6gqLOWIwmwSnre/2WrA1nKGId5uW2e5EfluA==} engines: {node: '>=8.0.0'} @@ -3292,13 +3107,6 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-module@2.0.0: - resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} - - which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} - which-typed-array@1.1.13: resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} engines: {node: '>= 0.4'} @@ -3327,10 +3135,6 @@ packages: workerpool@6.2.1: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3362,9 +3166,6 @@ packages: utf-8-validate: optional: true - y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3376,34 +3177,18 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - yargs-parser@20.2.4: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} engines: {node: '>=10'} - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - yargs-unparser@2.0.0: resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} engines: {node: '>=10'} - yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -3452,12 +3237,12 @@ snapshots: '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c': {} - '@changesets/apply-release-plan@7.0.1': + '@changesets/apply-release-plan@7.0.5': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.3 '@changesets/get-version-range-type': 0.4.0 - '@changesets/git': 3.0.0 + '@changesets/git': 3.0.1 + '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 detect-indent: 6.1.0 @@ -3466,16 +3251,16 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.6.2 + semver: 7.6.3 - '@changesets/assemble-release-plan@6.0.0': + '@changesets/assemble-release-plan@6.0.4': dependencies: - '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - semver: 7.6.2 + semver: 7.6.3 '@changesets/changelog-git@0.2.0': dependencies: @@ -3489,46 +3274,44 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.27.3': + '@changesets/cli@2.27.8': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/apply-release-plan': 7.0.1 - '@changesets/assemble-release-plan': 6.0.0 + '@changesets/apply-release-plan': 7.0.5 + '@changesets/assemble-release-plan': 6.0.4 '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.3 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.0 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/get-release-plan': 4.0.4 + '@changesets/git': 3.0.1 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.1 + '@changesets/read': 0.6.1 + '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 - '@changesets/write': 0.3.1 + '@changesets/write': 0.3.2 '@manypkg/get-packages': 1.1.3 '@types/semver': 7.5.0 ansi-colors: 4.1.3 - chalk: 2.4.2 ci-info: 3.9.0 enquirer: 2.3.6 external-editor: 3.1.0 fs-extra: 7.0.1 - human-id: 1.0.2 - meow: 6.1.1 + mri: 1.2.0 outdent: 0.5.0 p-limit: 2.3.0 - preferred-pm: 3.1.3 + package-manager-detector: 0.2.0 + picocolors: 1.1.0 resolve-from: 5.0.0 - semver: 7.6.2 + semver: 7.6.3 spawndamnit: 2.0.0 term-size: 2.2.1 - tty-table: 4.2.3 - '@changesets/config@3.0.0': + '@changesets/config@3.0.3': dependencies: '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/logger': 0.1.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/logger': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 @@ -3538,13 +3321,12 @@ snapshots: dependencies: extendable-error: 0.1.7 - '@changesets/get-dependents-graph@2.0.0': + '@changesets/get-dependents-graph@2.1.2': dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - chalk: 2.4.2 - fs-extra: 7.0.1 - semver: 7.6.2 + picocolors: 1.1.0 + semver: 7.6.3 '@changesets/get-github-info@0.6.0': dependencies: @@ -3553,63 +3335,62 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/get-release-plan@4.0.0': + '@changesets/get-release-plan@4.0.4': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/config': 3.0.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 + '@changesets/assemble-release-plan': 6.0.4 + '@changesets/config': 3.0.3 + '@changesets/pre': 2.0.1 + '@changesets/read': 0.6.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 '@changesets/get-version-range-type@0.4.0': {} - '@changesets/git@3.0.0': + '@changesets/git@3.0.1': dependencies: - '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 is-subdir: 1.2.0 micromatch: 4.0.5 spawndamnit: 2.0.0 - '@changesets/logger@0.1.0': + '@changesets/logger@0.1.1': dependencies: - chalk: 2.4.2 + picocolors: 1.1.0 '@changesets/parse@0.4.0': dependencies: '@changesets/types': 6.0.0 js-yaml: 3.14.1 - '@changesets/pre@2.0.0': + '@changesets/pre@2.0.1': dependencies: - '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - '@changesets/read@0.6.0': + '@changesets/read@0.6.1': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 + '@changesets/git': 3.0.1 + '@changesets/logger': 0.1.1 '@changesets/parse': 0.4.0 '@changesets/types': 6.0.0 - chalk: 2.4.2 fs-extra: 7.0.1 p-filter: 2.1.0 + picocolors: 1.1.0 + + '@changesets/should-skip-package@0.1.1': + dependencies: + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 '@changesets/types@4.1.0': {} '@changesets/types@6.0.0': {} - '@changesets/write@0.3.1': + '@changesets/write@0.3.2': dependencies: - '@babel/runtime': 7.24.0 '@changesets/types': 6.0.0 fs-extra: 7.0.1 human-id: 1.0.2 @@ -3619,9 +3400,9 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: - eslint: 8.57.0 + eslint: 8.57.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.10.0': {} @@ -3629,7 +3410,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -3640,7 +3421,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@8.57.1': {} '@eth-optimism/contracts@0.6.0(ethers@5.7.2)': dependencies: @@ -3669,7 +3450,7 @@ snapshots: '@ethersproject/transactions': 5.7.0 '@ethersproject/web': 5.7.1 bufio: 1.0.7 - chai: 4.4.1 + chai: 4.5.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -3939,10 +3720,10 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@humanwhocodes/config-array@0.11.14': + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -4020,7 +3801,7 @@ snapshots: '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 ethereum-cryptography: 0.1.3 lru-cache: 10.2.2 transitivePeerDependencies: @@ -4050,7 +3831,7 @@ snapshots: '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 '@types/debug': 4.1.12 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 ethereum-cryptography: 0.1.3 rustbn-wasm: 0.2.0 transitivePeerDependencies: @@ -4066,7 +3847,7 @@ snapshots: '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 ethereum-cryptography: 0.1.3 js-sdsl: 4.4.2 lru-cache: 10.2.2 @@ -4119,47 +3900,47 @@ snapshots: '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 ethereum-cryptography: 0.1.3 transitivePeerDependencies: - '@nomicfoundation/ethereumjs-verkle' - c-kzg - supports-color - '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)))(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: '@ethersproject/abi': 5.7.0 - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@types/chai-as-promised': 7.1.8 - chai: 4.4.1 - chai-as-promised: 7.1.1(chai@4.4.1) + chai: 4.5.0 + chai-as-promised: 7.1.1(chai@4.5.0) deep-eql: 4.1.3 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) ordinal: 1.0.3 - '@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-ethers@3.0.8(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - '@nomicfoundation/hardhat-network-helpers@1.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) - '@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 cbor: 8.1.0 chalk: 2.4.2 - debug: 4.3.4(supports-color@8.1.1) - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + debug: 4.3.7 + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) lodash.clonedeep: 4.5.0 semver: 6.3.0 table: 6.8.1 @@ -4210,10 +3991,10 @@ snapshots: '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.0 '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0 - '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) '@offchainlabs/upgrade-executor@1.1.0-beta.0': dependencies: @@ -4241,7 +4022,7 @@ snapshots: cbor: 9.0.2 chalk: 4.1.2 compare-versions: 6.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 ethereumjs-util: 7.1.5 minimist: 1.2.8 proper-lockfile: 4.1.2 @@ -4264,9 +4045,9 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@prettier/sync@0.3.0(prettier@3.2.5)': + '@prettier/sync@0.3.0(prettier@3.3.3)': dependencies: - prettier: 3.2.5 + prettier: 3.3.3 '@scroll-tech/contracts@0.1.0': {} @@ -4334,8 +4115,6 @@ snapshots: '@sindresorhus/is@4.6.0': {} - '@solidity-parser/parser@0.17.0': {} - '@solidity-parser/parser@0.18.0': {} '@szmarczak/http-timer@5.0.1': @@ -4351,7 +4130,7 @@ snapshots: '@truffle/contract-schema@3.4.10': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -4363,51 +4142,51 @@ snapshots: '@tsconfig/node16@1.0.3': {} - '@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5)': + '@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2)': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/bytes': 5.7.0 '@ethersproject/providers': 5.7.2 ethers: 5.7.2 lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.4.5) - typechain: 8.3.2(typescript@5.4.5) - typescript: 5.4.5 + ts-essentials: 7.0.3(typescript@5.6.2) + typechain: 8.3.2(typescript@5.6.2) + typescript: 5.6.2 - '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))(typechain@8.3.2(typescript@5.4.5))': + '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) + '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) - typechain: 8.3.2(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + typechain: 8.3.2(typescript@5.6.2) '@types/bn.js@4.11.6': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/bn.js@5.1.1': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/cacheable-request@6.0.2': dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/responselike': 1.0.0 '@types/cbor@5.0.1': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/chai-as-promised@7.1.8': dependencies: - '@types/chai': 4.3.16 + '@types/chai': 4.3.20 - '@types/chai@4.3.16': {} + '@types/chai@4.3.20': {} '@types/debug@4.1.12': dependencies: @@ -4419,124 +4198,120 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/lru-cache@5.1.1': {} - '@types/minimist@1.2.5': {} - - '@types/mocha@10.0.6': {} + '@types/mocha@10.0.8': {} '@types/ms@0.7.31': {} '@types/node@12.19.16': {} - '@types/node@20.12.12': + '@types/node@20.16.10': dependencies: - undici-types: 5.26.5 - - '@types/normalize-package-data@2.4.4': {} + undici-types: 6.19.8 '@types/pbkdf2@3.1.0': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/prettier@2.7.1': {} '@types/readable-stream@2.3.15': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 safe-buffer: 5.1.2 '@types/responselike@1.0.0': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/secp256k1@4.0.3': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.16.10 '@types/semver@7.5.0': {} - '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.10.0 - eslint: 8.57.0 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.4.5 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: - '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.10.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.7 + eslint: 8.57.1 optionalDependencies: - typescript: 5.4.5 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.10.0': + '@typescript-eslint/scope-manager@7.18.0': dependencies: - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/visitor-keys': 7.10.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + debug: 4.3.7 + eslint: 8.57.1 + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.4.5 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.10.0': {} + '@typescript-eslint/types@7.18.0': {} - '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.6.2)': dependencies: - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/visitor-keys': 7.10.0 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.4.5 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) - eslint: 8.57.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) + eslint: 8.57.1 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.10.0': + '@typescript-eslint/visitor-keys@7.18.0': dependencies: - '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -4550,11 +4325,11 @@ snapshots: ajv: 6.12.6 better-ajv-errors: 0.8.2(ajv@6.12.6) neodoc: 2.0.2 - semver: 7.6.2 + semver: 7.6.3 source-map-support: 0.5.21 optionalDependencies: prettier: 2.8.8 - prettier-plugin-solidity: 1.3.1(prettier@2.8.8) + prettier-plugin-solidity: 1.4.1(prettier@2.8.8) transitivePeerDependencies: - supports-color @@ -4574,7 +4349,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -4644,6 +4419,7 @@ snapshots: dependencies: call-bind: 1.0.5 is-array-buffer: 3.0.2 + optional: true array-buffer-byte-length@1.0.1: dependencies: @@ -4663,13 +4439,6 @@ snapshots: es-shim-unscopables: 1.0.2 optional: true - array.prototype.flat@1.3.2: - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - arraybuffer.prototype.slice@1.0.2: dependencies: array-buffer-byte-length: 1.0.0 @@ -4679,6 +4448,7 @@ snapshots: get-intrinsic: 1.2.2 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 + optional: true arraybuffer.prototype.slice@1.0.3: dependencies: @@ -4692,8 +4462,6 @@ snapshots: is-shared-array-buffer: 1.0.3 optional: true - arrify@1.0.1: {} - assertion-error@1.1.0: {} ast-parents@0.0.1: {} @@ -4702,7 +4470,8 @@ snapshots: at-least-node@1.0.0: {} - available-typed-arrays@1.0.5: {} + available-typed-arrays@1.0.5: + optional: true available-typed-arrays@1.0.7: dependencies: @@ -4770,10 +4539,6 @@ snapshots: dependencies: fill-range: 7.0.1 - breakword@1.0.6: - dependencies: - wcwidth: 1.0.1 - brorand@1.1.0: {} browser-stdout@1.3.1: {} @@ -4812,7 +4577,7 @@ snapshots: clone-response: 1.0.2 get-stream: 5.1.0 http-cache-semantics: 4.0.3 - keyv: 4.5.0 + keyv: 4.5.4 lowercase-keys: 2.0.0 normalize-url: 6.1.0 responselike: 2.0.1 @@ -4822,6 +4587,7 @@ snapshots: function-bind: 1.1.2 get-intrinsic: 1.2.2 set-function-length: 1.1.1 + optional: true call-bind@1.0.7: dependencies: @@ -4839,14 +4605,6 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 - camelcase-keys@6.2.2: - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - - camelcase@5.3.1: {} - camelcase@6.3.0: {} cbor@5.2.0: @@ -4863,12 +4621,12 @@ snapshots: nofilter: 3.1.0 optional: true - chai-as-promised@7.1.1(chai@4.4.1): + chai-as-promised@7.1.1(chai@4.5.0): dependencies: - chai: 4.4.1 + chai: 4.5.0 check-error: 1.0.3 - chai@4.4.1: + chai@4.5.0: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 @@ -4876,7 +4634,7 @@ snapshots: get-func-name: 2.0.2 loupe: 2.3.7 pathval: 1.1.1 - type-detect: 4.0.8 + type-detect: 4.1.0 chalk@2.4.2: dependencies: @@ -4941,30 +4699,16 @@ snapshots: cli-boxes@2.2.1: {} - cliui@6.0.0: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - cliui@7.0.4: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clone-response@1.0.2: dependencies: mimic-response: 1.0.1 - clone@1.0.4: {} - code-error-fragment@0.0.230: {} color-convert@1.9.3: @@ -5064,19 +4808,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - csv-generate@3.4.3: {} - - csv-parse@4.16.3: {} - - csv-stringify@5.6.5: {} - - csv@5.5.3: - dependencies: - csv-generate: 3.4.3 - csv-parse: 4.16.3 - csv-stringify: 5.6.5 - stream-transform: 2.1.3 - data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 @@ -5106,12 +4837,9 @@ snapshots: optionalDependencies: supports-color: 8.1.1 - decamelize-keys@1.1.1: + debug@4.3.7: dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - - decamelize@1.2.0: {} + ms: 2.1.3 decamelize@4.0.0: {} @@ -5132,10 +4860,6 @@ snapshots: deep-is@0.1.4: {} - defaults@1.0.4: - dependencies: - clone: 1.0.4 - defer-to-connect@2.0.1: {} define-data-property@1.1.1: @@ -5143,6 +4867,7 @@ snapshots: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 + optional: true define-data-property@1.1.4: dependencies: @@ -5156,6 +4881,7 @@ snapshots: define-data-property: 1.1.1 has-property-descriptors: 1.0.0 object-keys: 1.1.1 + optional: true delete-empty@3.0.0: dependencies: @@ -5208,6 +4934,8 @@ snapshots: env-paths@2.2.1: {} + era-contracts@https://codeload.github.com/matter-labs/era-contracts/tar.gz/446d391d34bdb48255d5f8fef8a8248925fc98b9: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -5253,6 +4981,7 @@ snapshots: typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.13 + optional: true es-abstract@1.23.3: dependencies: @@ -5322,6 +5051,7 @@ snapshots: get-intrinsic: 1.2.2 has-tostringtag: 1.0.0 hasown: 2.0.0 + optional: true es-set-tostringtag@2.0.3: dependencies: @@ -5333,12 +5063,14 @@ snapshots: es-shim-unscopables@1.0.2: dependencies: hasown: 2.0.0 + optional: true es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.2 is-symbol: 1.0.3 + optional: true escalade@3.1.1: {} @@ -5346,18 +5078,18 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@9.1.0(eslint@8.57.0): + eslint-config-prettier@9.1.0(eslint@8.57.1): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 - eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): + eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3): dependencies: - eslint: 8.57.0 - prettier: 3.2.5 + eslint: 8.57.1 + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.1 optionalDependencies: - eslint-config-prettier: 9.1.0(eslint@8.57.0) + eslint-config-prettier: 9.1.0(eslint@8.57.1) eslint-scope@7.2.2: dependencies: @@ -5366,20 +5098,20 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint@8.57.0: + eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -5590,11 +5322,6 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - find-yarn-workspace-root2@1.2.16: - dependencies: - micromatch: 4.0.5 - pkg-dir: 4.2.0 - find-yarn-workspace-root@2.0.0: dependencies: micromatch: 4.0.5 @@ -5609,13 +5336,14 @@ snapshots: flatted@3.3.1: {} - follow-redirects@1.15.6(debug@4.3.4): + follow-redirects@1.15.6(debug@4.3.7): optionalDependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 for-each@0.3.3: dependencies: is-callable: 1.2.7 + optional: true form-data-encoder@1.7.1: {} @@ -5653,7 +5381,8 @@ snapshots: fsevents@2.3.2: optional: true - function-bind@1.1.2: {} + function-bind@1.1.2: + optional: true function.prototype.name@1.1.6: dependencies: @@ -5661,8 +5390,10 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.22.3 functions-have-names: 1.2.3 + optional: true - functions-have-names@1.2.3: {} + functions-have-names@1.2.3: + optional: true get-caller-file@2.0.5: {} @@ -5674,6 +5405,7 @@ snapshots: has-proto: 1.0.1 has-symbols: 1.0.3 hasown: 2.0.0 + optional: true get-intrinsic@1.2.4: dependencies: @@ -5694,6 +5426,7 @@ snapshots: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 + optional: true get-symbol-description@1.0.2: dependencies: @@ -5752,19 +5485,21 @@ snapshots: globalthis@1.0.3: dependencies: define-properties: 1.2.1 + optional: true globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.1 - ignore: 5.2.4 + ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 gopd@1.0.1: dependencies: get-intrinsic: 1.2.2 + optional: true got@12.1.0: dependencies: @@ -5788,13 +5523,11 @@ snapshots: graphemer@1.4.0: {} - hard-rejection@2.1.0: {} - - hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)): + hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)): dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) hardhat-ignore-warnings@0.2.11: dependencies: @@ -5802,7 +5535,7 @@ snapshots: node-interval-tree: 2.1.2 solidity-comments: 0.0.2 - hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5): + hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -5828,7 +5561,7 @@ snapshots: chalk: 2.4.2 chokidar: 3.5.3 ci-info: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 enquirer: 2.3.6 env-paths: 2.2.1 ethereum-cryptography: 1.1.2 @@ -5847,7 +5580,7 @@ snapshots: raw-body: 2.5.1 resolve: 1.17.0 semver: 6.3.0 - solc: 0.7.3(debug@4.3.4) + solc: 0.7.3(debug@4.3.7) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 tsort: 0.0.1 @@ -5855,15 +5588,16 @@ snapshots: uuid: 8.3.2 ws: 7.5.9 optionalDependencies: - ts-node: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) - typescript: 5.4.5 + ts-node: 10.9.2(@types/node@20.16.10)(typescript@5.6.2) + typescript: 5.6.2 transitivePeerDependencies: - bufferutil - c-kzg - supports-color - utf-8-validate - has-bigints@1.0.2: {} + has-bigints@1.0.2: + optional: true has-flag@3.0.0: {} @@ -5872,32 +5606,32 @@ snapshots: has-property-descriptors@1.0.0: dependencies: get-intrinsic: 1.2.2 + optional: true has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 optional: true - has-proto@1.0.1: {} + has-proto@1.0.1: + optional: true has-proto@1.0.3: optional: true - has-symbols@1.0.3: {} + has-symbols@1.0.3: + optional: true has-tostringtag@1.0.0: dependencies: has-symbols: 1.0.3 + optional: true has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 optional: true - has@1.0.3: - dependencies: - function-bind: 1.1.2 - hash-base@3.1.0: dependencies: inherits: 2.0.4 @@ -5912,6 +5646,7 @@ snapshots: hasown@2.0.0: dependencies: function-bind: 1.1.2 + optional: true hasown@2.0.2: dependencies: @@ -5931,8 +5666,6 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - hosted-git-info@2.8.9: {} - http-cache-semantics@4.0.3: {} http-errors@2.0.0: @@ -5951,7 +5684,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -5961,8 +5694,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ignore@5.2.4: {} - ignore@5.3.1: {} immutable@4.1.0: {} @@ -5990,6 +5721,7 @@ snapshots: get-intrinsic: 1.2.2 hasown: 2.0.0 side-channel: 1.0.4 + optional: true internal-slot@1.0.7: dependencies: @@ -6007,6 +5739,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-typed-array: 1.1.12 + optional: true is-array-buffer@3.0.4: dependencies: @@ -6019,6 +5752,7 @@ snapshots: is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 + optional: true is-binary-path@2.1.0: dependencies: @@ -6028,23 +5762,22 @@ snapshots: dependencies: call-bind: 1.0.5 has-tostringtag: 1.0.0 + optional: true - is-callable@1.2.7: {} + is-callable@1.2.7: + optional: true is-ci@2.0.0: dependencies: ci-info: 2.0.0 - is-core-module@2.10.0: - dependencies: - has: 1.0.3 - is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 optional: true - is-date-object@1.0.2: {} + is-date-object@1.0.2: + optional: true is-docker@2.2.1: {} @@ -6062,7 +5795,8 @@ snapshots: dependencies: lower-case: 1.1.4 - is-negative-zero@2.0.2: {} + is-negative-zero@2.0.2: + optional: true is-negative-zero@2.0.3: optional: true @@ -6070,23 +5804,24 @@ snapshots: is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.0 + optional: true is-number@7.0.0: {} is-path-inside@3.0.3: {} - is-plain-obj@1.1.0: {} - is-plain-obj@2.1.0: {} is-regex@1.1.4: dependencies: call-bind: 1.0.5 has-tostringtag: 1.0.0 + optional: true is-shared-array-buffer@1.0.2: dependencies: call-bind: 1.0.5 + optional: true is-shared-array-buffer@1.0.3: dependencies: @@ -6096,6 +5831,7 @@ snapshots: is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 + optional: true is-subdir@1.2.0: dependencies: @@ -6104,10 +5840,12 @@ snapshots: is-symbol@1.0.3: dependencies: has-symbols: 1.0.3 + optional: true is-typed-array@1.1.12: dependencies: which-typed-array: 1.1.13 + optional: true is-typed-array@1.1.13: dependencies: @@ -6123,6 +5861,7 @@ snapshots: is-weakref@1.0.2: dependencies: call-bind: 1.0.5 + optional: true is-windows@1.0.2: {} @@ -6130,7 +5869,8 @@ snapshots: dependencies: is-docker: 2.2.1 - isarray@2.0.5: {} + isarray@2.0.5: + optional: true isexe@2.0.0: {} @@ -6186,16 +5926,10 @@ snapshots: node-gyp-build: 4.5.0 readable-stream: 3.6.0 - keyv@4.5.0: - dependencies: - json-buffer: 3.0.1 - keyv@4.5.4: dependencies: json-buffer: 3.0.1 - kind-of@6.0.3: {} - klaw-sync@6.0.0: dependencies: graceful-fs: 4.2.10 @@ -6204,8 +5938,6 @@ snapshots: optionalDependencies: graceful-fs: 4.2.10 - kleur@4.1.5: {} - latest-version@7.0.0: dependencies: package-json: 8.1.1 @@ -6219,13 +5951,6 @@ snapshots: lines-and-columns@1.2.4: {} - load-yaml-file@0.2.0: - dependencies: - graceful-fs: 4.2.10 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - locate-path@2.0.0: dependencies: p-locate: 2.0.0 @@ -6285,10 +6010,6 @@ snapshots: make-error@1.3.6: {} - map-obj@1.0.1: {} - - map-obj@4.3.0: {} - md5.js@1.3.5: dependencies: hash-base: 3.1.0 @@ -6297,20 +6018,6 @@ snapshots: memorystream@0.3.1: {} - meow@6.1.1: - dependencies: - '@types/minimist': 1.2.5 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 2.5.0 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.13.1 - yargs-parser: 18.1.3 - merge2@1.4.1: {} micromatch@4.0.5: @@ -6322,8 +6029,6 @@ snapshots: mimic-response@3.1.0: {} - min-indent@1.0.1: {} - minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -6344,16 +6049,8 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimist-options@4.1.0: - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - minimist@1.2.8: {} - mixme@0.5.10: {} - mkdirp@1.0.4: {} mnemonist@0.38.5: @@ -6386,6 +6083,8 @@ snapshots: moment@2.30.1: {} + mri@1.2.0: {} + ms@2.1.2: {} ms@2.1.3: {} @@ -6420,13 +6119,6 @@ snapshots: nofilter@3.1.0: {} - normalize-package-data@2.5.0: - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.1 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - normalize-path@3.0.0: {} normalize-url@6.1.0: {} @@ -6436,9 +6128,11 @@ snapshots: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - object-inspect@1.13.1: {} + object-inspect@1.13.1: + optional: true - object-keys@1.1.1: {} + object-keys@1.1.1: + optional: true object.assign@4.1.4: dependencies: @@ -6446,6 +6140,7 @@ snapshots: define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 + optional: true object.assign@4.1.5: dependencies: @@ -6526,7 +6221,9 @@ snapshots: got: 12.1.0 registry-auth-token: 5.0.2 registry-url: 6.0.1 - semver: 7.6.2 + semver: 7.6.3 + + package-manager-detector@0.2.0: {} param-case@2.1.1: dependencies: @@ -6595,50 +6292,39 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 + picocolors@1.1.0: {} + picomatch@2.3.1: {} pify@4.0.1: {} - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - pluralize@8.0.0: {} possible-typed-array-names@1.0.0: optional: true - preferred-pm@3.1.3: - dependencies: - find-up: 5.0.0 - find-yarn-workspace-root2: 1.2.16 - path-exists: 4.0.0 - which-pm: 2.0.0 - prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: dependencies: fast-diff: 1.2.0 - prettier-plugin-solidity@1.3.1(prettier@2.8.8): + prettier-plugin-solidity@1.4.1(prettier@2.8.8): dependencies: - '@solidity-parser/parser': 0.17.0 + '@solidity-parser/parser': 0.18.0 prettier: 2.8.8 - semver: 7.6.2 - solidity-comments-extractor: 0.0.8 + semver: 7.6.3 optional: true - prettier-plugin-solidity@1.3.1(prettier@3.2.5): + prettier-plugin-solidity@1.4.1(prettier@3.3.3): dependencies: - '@solidity-parser/parser': 0.17.0 - prettier: 3.2.5 - semver: 7.6.2 - solidity-comments-extractor: 0.0.8 + '@solidity-parser/parser': 0.18.0 + prettier: 3.3.3 + semver: 7.6.3 prettier@2.8.8: {} - prettier@3.2.5: {} + prettier@3.3.3: {} proper-lockfile@4.1.2: dependencies: @@ -6660,8 +6346,6 @@ snapshots: pure-rand@5.0.3: {} - quick-lru@4.0.1: {} - quick-lru@5.1.1: {} randombytes@2.1.0: @@ -6682,19 +6366,6 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - read-pkg-up@7.0.1: - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - - read-pkg@5.2.0: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.10 @@ -6712,11 +6383,6 @@ snapshots: dependencies: picomatch: 2.3.1 - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - reduce-flatten@2.0.0: {} regenerator-runtime@0.14.1: {} @@ -6726,6 +6392,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 set-function-name: 2.0.1 + optional: true regexp.prototype.flags@1.5.2: dependencies: @@ -6747,8 +6414,6 @@ snapshots: require-from-string@2.0.2: {} - require-main-filename@2.0.0: {} - resolve-alpn@1.2.1: {} resolve-from@4.0.0: {} @@ -6759,12 +6424,6 @@ snapshots: dependencies: path-parse: 1.0.7 - resolve@1.22.1: - dependencies: - is-core-module: 2.10.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - responselike@2.0.1: dependencies: lowercase-keys: 2.0.0 @@ -6805,6 +6464,7 @@ snapshots: get-intrinsic: 1.2.2 has-symbols: 1.0.3 isarray: 2.0.5 + optional: true safe-array-concat@1.1.2: dependencies: @@ -6823,6 +6483,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-regex: 1.1.4 + optional: true safe-regex-test@1.0.3: dependencies: @@ -6845,7 +6506,7 @@ snapshots: semver@6.3.0: {} - semver@7.6.2: {} + semver@7.6.3: {} sentence-case@2.1.1: dependencies: @@ -6856,14 +6517,13 @@ snapshots: dependencies: randombytes: 2.1.0 - set-blocking@2.0.0: {} - set-function-length@1.1.1: dependencies: define-data-property: 1.1.1 get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 + optional: true set-function-length@1.2.2: dependencies: @@ -6880,6 +6540,7 @@ snapshots: define-data-property: 1.1.1 functions-have-names: 1.2.3 has-property-descriptors: 1.0.0 + optional: true setimmediate@1.0.5: {} @@ -6909,6 +6570,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 object-inspect: 1.13.1 + optional: true signal-exit@3.0.7: {} @@ -6922,24 +6584,15 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - smartwrap@2.0.2: - dependencies: - array.prototype.flat: 1.3.2 - breakword: 1.0.6 - grapheme-splitter: 1.0.4 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 15.4.1 - snake-case@2.1.0: dependencies: no-case: 2.3.2 - solc@0.7.3(debug@4.3.4): + solc@0.7.3(debug@4.3.7): dependencies: command-exists: 1.2.9 commander: 3.0.2 - follow-redirects: 1.15.6(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.7) fs-extra: 0.30.0 js-sha3: 0.8.0 memorystream: 0.3.1 @@ -6949,14 +6602,14 @@ snapshots: transitivePeerDependencies: - debug - solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5): + solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.4.1(prettier@3.3.3))(prettier@3.3.3): dependencies: - '@prettier/sync': 0.3.0(prettier@3.2.5) - prettier: 3.2.5 + '@prettier/sync': 0.3.0(prettier@3.3.3) + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - prettier-plugin-solidity: 1.3.1(prettier@3.2.5) + prettier-plugin-solidity: 1.4.1(prettier@3.3.3) - solhint@5.0.1: + solhint@5.0.3: dependencies: '@solidity-parser/parser': 0.18.0 ajv: 6.12.6 @@ -6967,12 +6620,12 @@ snapshots: cosmiconfig: 8.2.0 fast-diff: 1.2.0 glob: 8.1.0 - ignore: 5.2.4 + ignore: 5.3.1 js-yaml: 4.1.0 latest-version: 7.0.0 lodash: 4.17.21 pluralize: 8.0.0 - semver: 7.6.2 + semver: 7.6.3 strip-ansi: 6.0.1 table: 6.8.1 text-table: 0.2.0 @@ -6990,8 +6643,6 @@ snapshots: solidity-comments-darwin-x64@0.0.2: optional: true - solidity-comments-extractor@0.0.8: {} - solidity-comments-freebsd-x64@0.0.2: optional: true @@ -7045,20 +6696,6 @@ snapshots: cross-spawn: 5.1.0 signal-exit: 3.0.7 - spdx-correct@3.1.1: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.12 - - spdx-exceptions@2.3.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.12 - - spdx-license-ids@3.0.12: {} - sprintf-js@1.0.3: {} stacktrace-parser@0.1.10: @@ -7067,10 +6704,6 @@ snapshots: statuses@2.0.1: {} - stream-transform@2.1.3: - dependencies: - mixme: 0.5.10 - string-format@2.0.0: {} string-width@4.2.3: @@ -7084,6 +6717,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 + optional: true string.prototype.trim@1.2.9: dependencies: @@ -7098,6 +6732,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 + optional: true string.prototype.trimend@1.0.8: dependencies: @@ -7111,6 +6746,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 + optional: true string.prototype.trimstart@1.0.8: dependencies: @@ -7133,10 +6769,6 @@ snapshots: dependencies: is-hex-prefixed: 1.0.0 - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -7153,14 +6785,12 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} - swap-case@1.1.2: dependencies: lower-case: 1.1.4 upper-case: 1.1.3 - synckit@0.8.8: + synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 tslib: 2.6.2 @@ -7201,11 +6831,9 @@ snapshots: tr46@0.0.3: {} - trim-newlines@3.0.1: {} - - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.6.2): dependencies: - typescript: 5.4.5 + typescript: 5.6.2 ts-command-line-args@2.5.1: dependencies: @@ -7214,25 +6842,25 @@ snapshots: command-line-usage: 6.1.3 string-format: 2.0.0 - ts-essentials@7.0.3(typescript@5.4.5): + ts-essentials@7.0.3(typescript@5.6.2): dependencies: - typescript: 5.4.5 + typescript: 5.6.2 - ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5): + ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 20.12.12 + '@types/node': 20.16.10 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.4.5 + typescript: 5.6.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 @@ -7242,16 +6870,6 @@ snapshots: tsort@0.0.1: {} - tty-table@4.2.3: - dependencies: - chalk: 4.1.2 - csv: 5.5.3 - kleur: 4.1.5 - smartwrap: 2.0.2 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 17.7.2 - tweetnacl-util@0.15.1: {} tweetnacl@1.0.3: {} @@ -7262,22 +6880,18 @@ snapshots: type-detect@4.0.8: {} - type-fest@0.13.1: {} + type-detect@4.1.0: {} type-fest@0.20.2: {} type-fest@0.21.3: {} - type-fest@0.6.0: {} - type-fest@0.7.1: {} - type-fest@0.8.1: {} - - typechain@8.3.2(typescript@5.4.5): + typechain@8.3.2(typescript@5.6.2): dependencies: '@types/prettier': 2.7.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 fs-extra: 7.0.1 glob: 7.1.7 js-sha3: 0.8.0 @@ -7285,8 +6899,8 @@ snapshots: mkdirp: 1.0.4 prettier: 2.8.8 ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.4.5) - typescript: 5.4.5 + ts-essentials: 7.0.3(typescript@5.6.2) + typescript: 5.6.2 transitivePeerDependencies: - supports-color @@ -7295,6 +6909,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-typed-array: 1.1.12 + optional: true typed-array-buffer@1.0.2: dependencies: @@ -7309,6 +6924,7 @@ snapshots: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 + optional: true typed-array-byte-length@1.0.1: dependencies: @@ -7326,6 +6942,7 @@ snapshots: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 + optional: true typed-array-byte-offset@1.0.2: dependencies: @@ -7342,6 +6959,7 @@ snapshots: call-bind: 1.0.5 for-each: 0.3.3 is-typed-array: 1.1.12 + optional: true typed-array-length@1.0.6: dependencies: @@ -7353,7 +6971,7 @@ snapshots: possible-typed-array-names: 1.0.0 optional: true - typescript@5.4.5: {} + typescript@5.6.2: {} typical@4.0.0: {} @@ -7365,8 +6983,9 @@ snapshots: has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + optional: true - undici-types@5.26.5: {} + undici-types@6.19.8: {} undici@5.28.4: dependencies: @@ -7396,15 +7015,6 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.1.1 - spdx-expression-parse: 3.0.1 - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - web3-utils@1.7.4: dependencies: bn.js: 5.2.1 @@ -7429,13 +7039,7 @@ snapshots: is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.3 - - which-module@2.0.0: {} - - which-pm@2.0.0: - dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 + optional: true which-typed-array@1.1.13: dependencies: @@ -7444,6 +7048,7 @@ snapshots: for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 + optional: true which-typed-array@1.1.15: dependencies: @@ -7473,12 +7078,6 @@ snapshots: workerpool@6.2.1: {} - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -7491,23 +7090,14 @@ snapshots: ws@7.5.9: {} - y18n@4.0.3: {} - y18n@5.0.8: {} yallist@2.1.2: {} yaml@1.10.2: {} - yargs-parser@18.1.3: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - yargs-parser@20.2.4: {} - yargs-parser@21.1.1: {} - yargs-unparser@2.0.0: dependencies: camelcase: 6.3.0 @@ -7515,20 +7105,6 @@ snapshots: flat: 5.0.2 is-plain-obj: 2.1.0 - yargs@15.4.1: - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.0 - y18n: 4.0.3 - yargs-parser: 18.1.3 - yargs@16.2.0: dependencies: cliui: 7.0.4 @@ -7539,16 +7115,6 @@ snapshots: y18n: 5.0.8 yargs-parser: 20.2.4 - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - yn@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/contracts/remappings.txt b/contracts/remappings.txt index ec64b1b2118..4ed0fcfd9a2 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -5,3 +5,4 @@ forge-std/=src/v0.8/vendor/forge-std/src/ hardhat/=node_modules/hardhat/ @eth-optimism/=node_modules/@eth-optimism/ @scroll-tech/=node_modules/@scroll-tech/ +@zksync/=node_modules/@zksync/ diff --git a/contracts/scripts/ci/find_slither_report_diff.sh b/contracts/scripts/ci/find_slither_report_diff.sh new file mode 100755 index 00000000000..d0b5238a1ac --- /dev/null +++ b/contracts/scripts/ci/find_slither_report_diff.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [[ "$#" -lt 4 ]]; then + >&2 echo "Generates a markdown file with diff in new issues detected by ChatGPT between two Slither reports." + >&2 echo "Usage: $0 [path-to-validation-prompt]" + exit 1 +fi + +if [[ -z "${OPEN_API_KEY+x}" ]]; then + >&2 echo "OPEN_API_KEY is not set." + exit 1 +fi + +first_report_path=$1 +second_report_path=$2 +new_issues_report_path=$3 +report_prompt_path=$4 +if [[ "$#" -eq 5 ]]; then + validation_prompt_path=$5 +else + validation_prompt_path="" +fi + +first_report_content=$(cat "$first_report_path" | sed 's/"//g' | sed -E 's/\\+$//g' | sed -E 's/\\+ //g') +second_report_content=$(cat "$second_report_path" | sed 's/"//g' | sed -E 's/\\+$//g' | sed -E 's/\\+ //g') +openai_prompt=$(cat "$report_prompt_path" | sed 's/"/\\"/g' | sed -E 's/\\+$//g' | sed -E 's/\\+ //g') +openai_model="gpt-4o-2024-05-13" +openai_result=$(echo '{ + "model": "'$openai_model'", + "temperature": 0.01, + "messages": [ + { + "role": "system", + "content": "'$openai_prompt' \nreport1:\n```'$first_report_content'```\nreport2:\n```'$second_report_content'```" + } + ] +}' | envsubst | curl https://api.openai.com/v1/chat/completions \ + -w "%{http_code}" \ + -o prompt_response.json \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPEN_API_KEY" \ + -d @- +) + +# throw error openai_result when is not 200 +if [ "$openai_result" != '200' ]; then + echo "::error::OpenAI API call failed with status $openai_result: $(cat prompt_response.json)" + exit 1 +fi + +# replace lines starting with ' -' (1space) with ' -' (2spaces) +response_content=$(cat prompt_response.json | jq -r '.choices[0].message.content') +new_issues_report_content=$(echo "$response_content" | sed -e 's/^ -/ -/g') +echo "$new_issues_report_content" > "$new_issues_report_path" + +if [[ -n "$validation_prompt_path" ]]; then + echo "::debug::Validating the diff report using the validation prompt" + openai_model="gpt-4-turbo-2024-04-09" + report_input=$(echo "$new_issues_report_content" | sed 's/"//g' | sed -E 's/\\+$//g' | sed -E 's/\\+ //g') + validation_prompt_content=$(cat "$validation_prompt_path" | sed 's/"/\\"/g' | sed -E 's/\\+$//g' | sed -E 's/\\+ //g') + validation_result=$(echo '{ + "model": "'$openai_model'", + "temperature": 0.01, + "messages": [ + { + "role": "system", + "content": "'$validation_prompt_content' \nreport1:\n```'$first_report_content'```\nreport2:\n```'$second_report_content'```\nnew_issues:\n```'$report_input'```" + } + ] + }' | envsubst | curl https://api.openai.com/v1/chat/completions \ + -w "%{http_code}" \ + -o prompt_validation_response.json \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPEN_API_KEY" \ + -d @- + ) + + # throw error openai_result when is not 200 + if [ "$validation_result" != '200' ]; then + echo "::error::OpenAI API call failed with status $validation_result: $(cat prompt_validation_response.json)" + exit 1 + fi + + # replace lines starting with ' -' (1space) with ' -' (2spaces) + response_content=$(cat prompt_validation_response.json | jq -r '.choices[0].message.content') + + echo "$response_content" | sed -e 's/^ -/ -/g' >> "$new_issues_report_path" + echo "" >> "$new_issues_report_path" + echo "*Confidence rating presented above is an automatic validation (self-check) of the differences between two reports generated by ChatGPT ${openai_model} model. It has a scale of 1 to 5, where 1 means that all new issues are missing and 5 that all new issues are present*." >> "$new_issues_report_path" + echo "" >> "$new_issues_report_path" + echo "*If confidence rating is low it's advised to look for differences manually by downloading Slither reports for base reference and current commit from job's artifacts*." >> "$new_issues_report_path" +fi diff --git a/contracts/scripts/ci/generate_slither_report.sh b/contracts/scripts/ci/generate_slither_report.sh deleted file mode 100755 index bc876ae1182..00000000000 --- a/contracts/scripts/ci/generate_slither_report.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -function check_chainlink_dir() { - local param_dir="chainlink" - current_dir=$(pwd) - - current_base=$(basename "$current_dir") - - if [[ "$current_base" != "$param_dir" ]]; then - >&2 echo "The script must be run from the root of $param_dir directory" - exit 1 - fi -} - -check_chainlink_dir - -if [ "$#" -lt 5 ]; then - >&2 echo "Generates Markdown Slither reports and saves them to a target directory." - >&2 echo "Usage: $0 [slither extra params]" - exit 1 -fi - -REPO_URL=$1 -CONFIG_FILE=$2 -SOURCE_DIR=$3 -FILES=${4// /} # Remove any spaces from the list of files -TARGET_DIR=$5 -SLITHER_EXTRA_PARAMS=$6 - -run_slither() { - local FILE=$1 - local TARGET_DIR=$2 - - if [[ ! -f "$FILE" ]]; then - >&2 echo "::error:File not found: $FILE" - return 1 - fi - - set +e - source ./contracts/scripts/ci/select_solc_version.sh "$FILE" - if [[ $? -ne 0 ]]; then - >&2 echo "::error::Failed to select Solc version for $FILE" - return 1 - fi - - SLITHER_OUTPUT_FILE="$TARGET_DIR/$(basename "${FILE%.sol}")-slither-report.md" - if ! output=$(slither --config-file "$CONFIG_FILE" "$FILE" --checklist --markdown-root "$REPO_URL" --fail-none $SLITHER_EXTRA_PARAMS); then - >&2 echo "::warning::Slither failed for $FILE" - return 0 - fi - set -e - output=$(echo "$output" | sed '/\*\*THIS CHECKLIST IS NOT COMPLETE\*\*. Use `--show-ignored-findings` to show all the results./d' | sed '/Summary/d') - - echo "# Summary for $FILE" > "$SLITHER_OUTPUT_FILE" - echo "$output" >> "$SLITHER_OUTPUT_FILE" - - if [[ -z "$output" ]]; then - echo "No issues found." >> "$SLITHER_OUTPUT_FILE" - fi -} - -process_files() { - local SOURCE_DIR=$1 - local TARGET_DIR=$2 - local FILES=(${3//,/ }) # Split the comma-separated list into an array - - mkdir -p "$TARGET_DIR" - - for FILE in "${FILES[@]}"; do - FILE=${FILE//\"/} - run_slither "$SOURCE_DIR/$FILE" "$TARGET_DIR" - done -} - -set +e -process_files "$SOURCE_DIR" "$TARGET_DIR" "${FILES[@]}" - -if [[ $? -ne 0 ]]; then - >&2 echo "::warning::Failed to generate some Slither reports" - exit 0 -fi - -echo "Slither reports saved in $TARGET_DIR folder" diff --git a/contracts/scripts/ci/generate_uml.sh b/contracts/scripts/ci/generate_uml.sh deleted file mode 100755 index c71d0a1ac7d..00000000000 --- a/contracts/scripts/ci/generate_uml.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -function check_chainlink_dir() { - local param_dir="chainlink" - current_dir=$(pwd) - - current_base=$(basename "$current_dir") - - if [[ "$current_base" != "$param_dir" ]]; then - >&2 echo "The script must be run from the root of $param_dir directory" - exit 1 - fi -} - -check_chainlink_dir - -if [ "$#" -lt 2 ]; then - >&2 echo "Generates UML diagrams for all contracts in a directory after flattening them to avoid call stack overflows." - >&2 echo "Usage: $0 [comma-separated list of files]" - exit 1 -fi - -SOURCE_DIR="$1" -TARGET_DIR="$2" -FILES=${3// /} # Remove any spaces from the list of files -FAILED_FILES=() - -flatten_and_generate_uml() { - local FILE=$1 - local TARGET_DIR=$2 - - set +e - FLATTENED_FILE="$TARGET_DIR/flattened_$(basename "$FILE")" - echo "::debug::Flattening $FILE to $FLATTENED_FILE" - forge flatten "$FILE" -o "$FLATTENED_FILE" --root contracts - if [[ $? -ne 0 ]]; then - >&2 echo "::error::Failed to flatten $FILE" - FAILED_FILES+=("$FILE") - return - fi - - OUTPUT_FILE=${FLATTENED_FILE//"flattened_"/""} - OUTPUT_FILE_SVG="${OUTPUT_FILE%.sol}.svg" - echo "::debug::Generating SVG UML for $FLATTENED_FILE to $OUTPUT_FILE_SVG" - sol2uml "$FLATTENED_FILE" -o "$OUTPUT_FILE_SVG" - if [[ $? -ne 0 ]]; then - >&2 echo "::error::Failed to generate UML diagram in SVG format for $FILE" - FAILED_FILES+=("$FILE") - rm "$FLATTENED_FILE" - return - fi - OUTPUT_FILE_DOT="${OUTPUT_FILE%.sol}.dot" - echo "::debug::Generating DOT UML for $FLATTENED_FILE to $OUTPUT_FILE_DOT" - sol2uml "$FLATTENED_FILE" -o "$OUTPUT_FILE_DOT" -f dot - if [[ $? -ne 0 ]]; then - >&2 echo "::error::Failed to generate UML diagram in DOT format for $FILE" - FAILED_FILES+=("$FILE") - rm "$FLATTENED_FILE" - return - fi - - rm "$FLATTENED_FILE" - set -e -} - -process_all_files_in_directory() { - local SOURCE_DIR=$1 - local TARGET_DIR=$2 - - mkdir -p "$TARGET_DIR" - - find "$SOURCE_DIR" -type f -name '*.sol' | while read -r ITEM; do - flatten_and_generate_uml "$ITEM" "$TARGET_DIR" - done -} - -process_selected_files() { - local SOURCE_DIR=$1 - local TARGET_DIR=$2 - local FILES=(${3//,/ }) # Split the comma-separated list into an array - - mkdir -p "$TARGET_DIR" - - for FILE in "${FILES[@]}"; do - FILE=${FILE//\"/} - MATCHES=($(find "$SOURCE_DIR" -type f -path "*/$FILE")) - - if [[ ${#MATCHES[@]} -gt 1 ]]; then - >&2 echo "::error:: Multiple matches found for $FILE:" - for MATCH in "${MATCHES[@]}"; do - >&2 echo " $MATCH" - done - exit 1 - elif [[ ${#MATCHES[@]} -eq 1 ]]; then - >&2 echo "::debug::File found: ${MATCHES[0]}" - flatten_and_generate_uml "${MATCHES[0]}" "$TARGET_DIR" - else - >&2 echo "::error::File $FILE does not exist within the source directory $SOURCE_DIR." - exit 1 - fi - done -} - -# if FILES is empty, process all files in the directory, otherwise process only the selected files -if [[ -z "$FILES" ]]; then - process_all_files_in_directory "$SOURCE_DIR" "$TARGET_DIR" -else - process_selected_files "$SOURCE_DIR" "$TARGET_DIR" "$FILES" -fi - -if [[ "${#FAILED_FILES[@]}" -gt 0 ]]; then - >&2 echo ":error::Failed to generate UML diagrams for ${#FAILED_FILES[@]} files:" - for FILE in "${FAILED_FILES[@]}"; do - >&2 echo " $FILE" - echo "$FILE" >> "$TARGET_DIR/uml_generation_failures.txt" - done -fi - -echo "UML diagrams saved in $TARGET_DIR folder" diff --git a/contracts/scripts/ci/modify_remappings.sh b/contracts/scripts/ci/modify_remappings.sh deleted file mode 100755 index e64ca369b0c..00000000000 --- a/contracts/scripts/ci/modify_remappings.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if [ "$#" -ne 2 ]; then - >&2 echo "Usage: $0 " - exit 1 -fi - -DIR_PREFIX=$1 -REMAPPINGS_FILE=$2 - -if [ ! -f "$REMAPPINGS_FILE" ]; then - >&2 echo "::error:: Remappings file '$REMAPPINGS_FILE' not found." - exit 1 -fi - -OUTPUT_FILE="remappings_modified.txt" - -while IFS= read -r line; do - if [[ "$line" =~ ^[^=]+= ]]; then - REMAPPED_PATH="${line#*=}" - MODIFIED_LINE="${line%=*}=${DIR_PREFIX}/${REMAPPED_PATH}" - echo "$MODIFIED_LINE" >> "$OUTPUT_FILE" - else - echo "$line" >> "$OUTPUT_FILE" - fi -done < "$REMAPPINGS_FILE" - -echo "Modified remappings have been saved to: $OUTPUT_FILE" diff --git a/contracts/scripts/ci/prompt-difference.md b/contracts/scripts/ci/prompt-difference.md new file mode 100644 index 00000000000..b7603c97482 --- /dev/null +++ b/contracts/scripts/ci/prompt-difference.md @@ -0,0 +1,21 @@ +You are a helpful expert data engineer with expertise in Blockchain and Decentralized Oracle Networks. + +Given two reports generated by Slither - a Solidity static analysis tool - provided at the bottom of the reply, your task is to help create a report for your peers with new issues introduced in the second report in order to decrease noise resulting from irrelevant changes to the report, by focusing on a single topic: **New Issues**. + +First report is provided under Heading 2 (##) called `report1` and is surrounded by triple backticks (```) to indicate the beginning and end of the report. +Second report is provided under Heading 2 (##) called `report2` and is surrounded by triple backticks (```) to indicate the beginning and end of the report. + +First report is report generated by Slither using default branch of the code repository. Second report is report generated by Slither using a feature branch of the code repository. You want to help your peers understand the impact of changes they introduced in the pull request on the codebase and whether they introduced any new issues. + +**New Issues** + +Provide a bullet point summary of new issues that were introduced in the second report. If a given issue is not present in first report, but is present in the second one, it is considered a new issue. If the count for given issue type is higher in the second report than in the first one, it is considered a new issue. +For each issue include original description text from the report together with severity level, issue ID, line number and a link to problematic line in the code. +Group the issues by their type, which is defined as Heading 2 (##). + +Output your response starting from**New Issues** in escaped, markdown text that can be sent as http body to API. Do not wrap output in code blocks. +Extract the name of the file from the first line of the report and title the new report with it in a following way: "# Slither's new issues in: " + +Remember that it might be possible that second report does not introduce any new issues. In such case, provide an empty report. + +Format **New Issues** as Heading 2 using double sharp characters (##). Otherwise, do not include any another preamble and postamble to your answer. diff --git a/contracts/scripts/ci/prompt-validation.md b/contracts/scripts/ci/prompt-validation.md new file mode 100644 index 00000000000..5fcf08e1462 --- /dev/null +++ b/contracts/scripts/ci/prompt-validation.md @@ -0,0 +1,33 @@ +You are a helpful expert data engineer with expertise in Blockchain and Decentralized Oracle Networks. + +At the bottom of the reply you will find two reports generated by Slither - a Solidity static analysis tool - and another report that contains new issues found in the second report. +Your task is to evaluate how well that new issues report shows all new issues mentioned in the second Slither report and assert its completeness. +Rate your confidence in the completeness of the new issues report on a scale from 1 to 5, where 1 means it's missing all new issues and 5 means that all new issues are present. + +First report is provided under Heading 2 (##) called `report1` and is surrounded by triple backticks (```) to indicate the beginning and end of the report. +Second report is provided under Heading 2 (##) called `report2` and is surrounded by triple backticks (```) to indicate the beginning and end of the report. +New issues report is provided under Heading 2 (##) called `new_issues` and is surrounded by triple backticks (```) to indicate the beginning and end of the report. + +Use the following steps to evaluate the new issues report: +* each report begins with a summary with types of issues found and number of issues found for each type, called "# Summary for " +* group issues by type and count for each report and calculate the expected difference in number of issues for each type for each report +* exclude all issue types, for which the count for is higher in the first report than in the second one +* for each remaining issue type, compare the number of issues found in the new issues report with the expected difference +* evaluate if the new issues report captures all new issues introduced in the second report + +Do not focus on: +* the quality of the Slither reports themselves, but rather on whether all new issues from the second report are present in the new issues report +* how well the new issues report is structured or written and how well it presents new issues + +It is crucial that you ignore all differences in the reports that are not related to new issues, such as resolved issues or issues, which count has decreased. + +If a given issue is not present in first report, but is present in the second one, it is considered a new issue. Similar behaviour is expected from the new issues report. +If the count for given issue type is higher in the second report than in the first one, it is considered a new issue. + +Your report should include only a single section titled "Confidence level". +Your evaluation of the completeness of the new issues report should be displayed as a Heading 3 using triple sharp characters (###). In a new line a brief explanation of the scale used, with minimum and maximum possible values. + +Remember that it might be possible that second report does not introduce any new issues. In such case, confidence rating should be 5. + +Output your response as escaped, markdown text that can be sent as http body to API. Do not wrap output in code blocks. Do not include any partial results or statistics regarding the number of new and resolved issues in any of the reports. +Format **Confidence level** as Heading 2 using double sharp characters (##). Otherwise, do not include any another preamble and postamble to your answer. diff --git a/contracts/scripts/ci/select_solc_version.sh b/contracts/scripts/ci/select_solc_version.sh deleted file mode 100755 index cfa13de0f60..00000000000 --- a/contracts/scripts/ci/select_solc_version.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -function check_chainlink_dir() { - local param_dir="chainlink" - current_dir=$(pwd) - - current_base=$(basename "$current_dir") - - if [[ "$current_base" != "$param_dir" ]]; then - >&2 echo "::error::The script must be run from the root of $param_dir directory" - exit 1 - fi -} - -check_chainlink_dir - -FILE="$1" - -if [[ "$#" -lt 1 ]]; then - echo "Detects the Solidity version of a file and selects the appropriate Solc version." - echo "If the version is not installed, it will be installed and selected." - echo "Will prefer to use the version from Foundry profile if it satisfies the version in the file." - echo "Usage: $0 " - exit 1 -fi - -if [[ -z "$FILE" ]]; then - >&2 echo "::error:: File not provided." - exit 1 -fi - -extract_product() { - local path=$1 - - echo "$path" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1 -} - -extract_pragma() { - local FILE=$1 - - if [[ -f "$FILE" ]]; then - SOLCVER="$(grep --no-filename '^pragma solidity' "$FILE" | cut -d' ' -f3)" - else - >&2 echo ":error::$FILE is not a file or it could not be found. Exiting." - return 1 - fi - SOLCVER="$(echo "$SOLCVER" | sed 's/[^0-9\.^]//g')" - >&2 echo "::debug::Detected Solidity version in pragma: $SOLCVER" - echo "$SOLCVER" -} - -echo "Detecting Solc version for $FILE" - -# Set FOUNDRY_PROFILE to the product name only if it is set; otherwise either already set value will be used or it will be empty -PRODUCT=$(extract_product "$FILE") -if [ -n "$PRODUCT" ]; then - FOUNDRY_PROFILE="$PRODUCT" -fi -SOLC_IN_PROFILE=$(forge config --json --root contracts | jq ".solc") -SOLC_IN_PROFILE=$(echo "$SOLC_IN_PROFILE" | tr -d "'\"") -echo "::debug::Detected Solidity version in profile: $SOLC_IN_PROFILE" - -set +e -SOLCVER=$(extract_pragma "$FILE") - -if [[ $? -ne 0 ]]; then - >&2 echo "::error:: Failed to extract the Solidity version from $FILE." - return 1 -fi - -set -e - -SOLCVER=$(echo "$SOLCVER" | tr -d "'\"") - -if [[ "$SOLC_IN_PROFILE" != "null" && -n "$SOLCVER" ]]; then - set +e - COMPAT_SOLC_VERSION=$(npx semver "$SOLC_IN_PROFILE" -r "$SOLCVER") - exit_code=$? - set -e - if [[ $exit_code -eq 0 && -n "$COMPAT_SOLC_VERSION" ]]; then - echo "::debug::Version $SOLC_IN_PROFILE satisfies the constraint $SOLCVER" - SOLC_TO_USE="$SOLC_IN_PROFILE" - else - echo "::debug::Version $SOLC_IN_PROFILE does not satisfy the constraint $SOLCVER" - SOLC_TO_USE="$SOLCVER" - fi - elif [[ "$SOLC_IN_PROFILE" != "null" && -z "$SOLCVER" ]]; then - >&2 echo "::error::No version found in the Solidity file. Exiting" - return 1 - elif [[ "$SOLC_IN_PROFILE" == "null" && -n "$SOLCVER" ]]; then - echo "::debug::Using the version from the file: $SOLCVER" - SOLC_TO_USE="$SOLCVER" - else - >&2 echo "::error::No version found in the profile or the Solidity file." - return 1 -fi - -echo "Will use $SOLC_TO_USE" -SOLC_TO_USE=$(echo "$SOLC_TO_USE" | tr -d "'\"") -SOLC_TO_USE="$(echo "$SOLC_TO_USE" | sed 's/[^0-9\.]//g')" - -INSTALLED_VERSIONS=$(solc-select versions) - -if echo "$INSTALLED_VERSIONS" | grep -q "$SOLC_TO_USE"; then - echo "::debug::Version $SOLCVER is already installed." - if echo "$INSTALLED_VERSIONS" | grep "$SOLC_TO_USE" | grep -q "current"; then - echo "::debug::Version $SOLCVER is already selected." - else - echo "::debug::Selecting $SOLC_TO_USE" - solc-select use "$SOLC_TO_USE" - fi -else - echo "::debug::Version $SOLC_TO_USE is not installed." - solc-select install "$SOLC_TO_USE" - solc-select use "$SOLC_TO_USE" -fi diff --git a/contracts/scripts/generate-zksync-automation-master-interface-v2_3.ts b/contracts/scripts/generate-zksync-automation-master-interface-v2_3.ts new file mode 100644 index 00000000000..385d1fb45b7 --- /dev/null +++ b/contracts/scripts/generate-zksync-automation-master-interface-v2_3.ts @@ -0,0 +1,58 @@ +/** + * @description this script generates a master interface for interacting with the automation registry + * @notice run this script with pnpm ts-node ./scripts/generate-zksync-automation-master-interface-v2_3.ts + */ +import { ZKSyncAutomationRegistry2_3__factory as Registry } from '../typechain/factories/ZKSyncAutomationRegistry2_3__factory' +import { ZKSyncAutomationRegistryLogicA2_3__factory as RegistryLogicA } from '../typechain/factories/ZKSyncAutomationRegistryLogicA2_3__factory' +import { ZKSyncAutomationRegistryLogicB2_3__factory as RegistryLogicB } from '../typechain/factories/ZKSyncAutomationRegistryLogicB2_3__factory' +import { ZKSyncAutomationRegistryLogicC2_3__factory as RegistryLogicC } from '../typechain/factories/ZKSyncAutomationRegistryLogicC2_3__factory' +import { utils } from 'ethers' +import fs from 'fs' +import { exec } from 'child_process' + +const dest = 'src/v0.8/automation/interfaces/zksync' +const srcDest = `${dest}/IZKSyncAutomationRegistryMaster2_3.sol` +const tmpDest = `${dest}/tmp.txt` + +const combinedABI = [] +const abiSet = new Set() +const abis = [ + Registry.abi, + RegistryLogicA.abi, + RegistryLogicB.abi, + RegistryLogicC.abi, +] + +for (const abi of abis) { + for (const entry of abi) { + const id = utils.id(JSON.stringify(entry)) + if (!abiSet.has(id)) { + abiSet.add(id) + if ( + entry.type === 'function' && + (entry.name === 'checkUpkeep' || + entry.name === 'checkCallback' || + entry.name === 'simulatePerformUpkeep') + ) { + entry.stateMutability = 'view' // override stateMutability for check / callback / simulate functions + } + combinedABI.push(entry) + } + } +} + +const checksum = utils.id(abis.join('')) + +fs.writeFileSync(`${tmpDest}`, JSON.stringify(combinedABI)) + +const cmd = ` +cat ${tmpDest} | pnpm abi-to-sol --solidity-version ^0.8.19 --license MIT > ${srcDest} IZKSyncAutomationRegistryMaster2_3; +echo "// solhint-disable \n// abi-checksum: ${checksum}" | cat - ${srcDest} > ${tmpDest} && mv ${tmpDest} ${srcDest}; +pnpm prettier --write ${srcDest}; +` + +exec(cmd) + +console.log( + 'generated new master interface for zksync automation registry v2_3', +) diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation index 29326a15c05..e189e78cb0f 100755 --- a/contracts/scripts/native_solc_compile_all_automation +++ b/contracts/scripts/native_solc_compile_all_automation @@ -93,7 +93,7 @@ compileContract automation/v2_2/AutomationUtils2_2.sol compileContract automation/interfaces/v2_2/IAutomationRegistryMaster.sol compileContract automation/chains/ArbitrumModule.sol compileContract automation/chains/ChainModuleBase.sol -compileContract automation/chains/OptimismModule.sol +compileContract automation/chains/OptimismModuleV2.sol compileContract automation/chains/ScrollModule.sol compileContract automation/interfaces/IChainModule.sol compileContract automation/interfaces/IAutomationV21PlusCommon.sol diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 1dbb70502d6..0f8fae61f76 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -8,9 +8,7 @@ echo " └─────────────────────── SOLC_VERSION="0.8.24" OPTIMIZE_RUNS=26000 -OPTIMIZE_RUNS_OFFRAMP=18000 -OPTIMIZE_RUNS_ONRAMP=4100 -OPTIMIZE_RUNS_MULTI_OFFRAMP=2500 +OPTIMIZE_RUNS_OFFRAMP=800 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" @@ -28,23 +26,16 @@ compileContract () { local optimize_runs=$OPTIMIZE_RUNS case $1 in - "ccip/offRamp/EVM2EVMOffRamp.sol") + "ccip/offRamp/OffRamp.sol") echo "OffRamp uses $OPTIMIZE_RUNS_OFFRAMP optimizer runs." optimize_runs=$OPTIMIZE_RUNS_OFFRAMP ;; - "ccip/offRamp/EVM2EVMMultiOffRamp.sol") - echo "MultiOffRamp uses $OPTIMIZE_RUNS_MULTI_OFFRAMP optimizer runs." - optimize_runs=$OPTIMIZE_RUNS_MULTI_OFFRAMP - ;; - "ccip/onRamp/EVM2EVMOnRamp.sol") - echo "OnRamp uses $OPTIMIZE_RUNS_ONRAMP optimizer runs." - optimize_runs=$OPTIMIZE_RUNS_ONRAMP - ;; 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" } @@ -52,44 +43,45 @@ compileContract () { # Solc produces and overwrites intermediary contracts. # Contracts should be ordered in reverse-import-complexity-order to minimize overwrite risks. -compileContract ccip/offRamp/EVM2EVMOffRamp.sol -compileContract ccip/offRamp/EVM2EVMMultiOffRamp.sol +compileContract ccip/offRamp/OffRamp.sol +compileContract ccip/FeeQuoter.sol +compileContract ccip/onRamp/OnRamp.sol compileContract ccip/applications/PingPongDemo.sol -compileContract ccip/applications/SelfFundedPingPong.sol compileContract ccip/applications/EtherSenderReceiver.sol -compileContract ccip/onRamp/EVM2EVMMultiOnRamp.sol -compileContract ccip/onRamp/EVM2EVMOnRamp.sol -compileContract ccip/CommitStore.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/PriceRegistry.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 + + +# Pools compileContract ccip/pools/LockReleaseTokenPool.sol compileContract ccip/pools/BurnMintTokenPool.sol compileContract ccip/pools/BurnFromMintTokenPool.sol compileContract ccip/pools/BurnWithFromMintTokenPool.sol -compileContract ccip/pools/LockReleaseTokenPoolAndProxy.sol -compileContract ccip/pools/BurnMintTokenPoolAndProxy.sol compileContract ccip/pools/TokenPool.sol -compileContract shared/token/ERC677/BurnMintERC677.sol -compileContract ccip/RMN.sol -compileContract ccip/ARMProxy.sol -compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol -compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol -compileContract ccip/capability/CCIPConfig.sol -compileContract ccip/capability/interfaces/IOCR3ConfigEncoder.sol -compileContract ccip/NonceManager.sol + # Test helpers compileContract ccip/test/helpers/BurnMintERC677Helper.sol -compileContract ccip/test/helpers/CommitStoreHelper.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/MockRMN1_0.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 # Customer contracts compileContract ccip/pools/USDC/USDCTokenPool.sol diff --git a/contracts/scripts/native_solc_compile_all_l2ep b/contracts/scripts/native_solc_compile_all_l2ep index 1b9f5fb611d..1f671158068 100755 --- a/contracts/scripts/native_solc_compile_all_l2ep +++ b/contracts/scripts/native_solc_compile_all_l2ep @@ -1,59 +1,38 @@ #!/usr/bin/env bash -########### -# Logging # -########### - set -e echo " ┌──────────────────────────────────────────────┐" echo " │ Compiling L2EP contracts... │" echo " └──────────────────────────────────────────────┘" -###################### -# Helper Variable(s) # -###################### - -export SOLC_VERSION="0.8.19" +SOLC_VERSION="0.8.24" +OPTIMIZE_RUNS=1000000 -SCRIPTPATH="$( - cd "$(dirname "$0")" >/dev/null 2>&1 - pwd -P -)" +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 ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 cd ../ && pwd -P )" -###################### -# Helper Function(s) # -###################### - compileContract() { - local optimize_runs=1000000 local version="$1" local srcpath="$2" solc \ @openzeppelin/=$ROOT/node_modules/@openzeppelin/ \ @eth-optimism/=$ROOT/node_modules/@eth-optimism/ \ @scroll-tech/=$ROOT/node_modules/@scroll-tech/ \ - --overwrite --optimize --optimize-runs $optimize_runs --metadata-hash none \ + --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ -o $ROOT/solc/v$SOLC_VERSION/l2ep/"$version" \ - --abi --bin \ - --allow-paths $ROOT/src/v0.8,$ROOT/node_modules \ + --abi --bin --allow-paths $ROOT/src/v0.8,$ROOT/node_modules \ + --evm-version paris \ $ROOT/src/v0.8/l2ep/"$srcpath" } -################# -# Version 1.0.0 # -################# - -python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt - -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION - compileContract v1_0_0 dev/arbitrum/ArbitrumValidator.sol compileContract v1_0_0 dev/arbitrum/ArbitrumSequencerUptimeFeed.sol compileContract v1_0_0 dev/arbitrum/ArbitrumCrossDomainForwarder.sol diff --git a/contracts/scripts/native_solc_compile_all_llo-feeds b/contracts/scripts/native_solc_compile_all_llo-feeds index f0224d962cc..bbcd53df900 100755 --- a/contracts/scripts/native_solc_compile_all_llo-feeds +++ b/contracts/scripts/native_solc_compile_all_llo-feeds @@ -36,13 +36,10 @@ compileContract llo-feeds/v0.4.0/DestinationVerifier.sol compileContract llo-feeds/v0.4.0/DestinationVerifierProxy.sol 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 # Test | Mocks compileContract llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol compileContract llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol - -# LLO -compileContract llo-feeds/dev/ChannelConfigStore.sol -compileContract llo-feeds/dev/ChannelVerifier.sol -compileContract llo-feeds/dev/test/mocks/ExposedChannelVerifier.sol +compileContract llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol diff --git a/contracts/scripts/native_solc_compile_all_vrf b/contracts/scripts/native_solc_compile_all_vrf index 4bfd4ecac72..88e7b3e1471 100755 --- a/contracts/scripts/native_solc_compile_all_vrf +++ b/contracts/scripts/native_solc_compile_all_vrf @@ -114,6 +114,7 @@ compileContract vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol compileContract vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol compileContract vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol compileContract vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol +compileContractAltOpts vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol 500 compileContract vrf/dev/libraries/VRFV2PlusClient.sol compileContract vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol compileContract vrf/dev/TrustedBlockhashStore.sol diff --git a/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol b/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol index cfbff1365e1..f4616ba1322 100644 --- a/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol +++ b/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol @@ -1,17 +1,20 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; +pragma solidity 0.8.19; import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; +import {GAS_BOUND_CALLER, IGasBoundCaller} from "./interfaces/zksync/IGasBoundCaller.sol"; -uint256 constant PERFORM_GAS_CUSHION = 5_000; +uint256 constant PERFORM_GAS_CUSHION = 50_000; /** - * @title AutomationForwarder is a relayer that sits between the registry and the customer's target contract + * @title ZKSyncAutomationForwarder is a relayer that sits between the registry and the customer's target contract * @dev The purpose of the forwarder is to give customers a consistent address to authorize against, * which stays consistent between migrations. The Forwarder also exposes the registry address, so that users who * want to programmatically interact with the registry (ie top up funds) can do so. */ contract ZKSyncAutomationForwarder { + error InvalidCaller(address); + /// @notice the user's target contract address address private immutable i_target; @@ -31,11 +34,14 @@ contract ZKSyncAutomationForwarder { * @param gasAmount is the amount of gas to use in the call * @param data is the 4 bytes function selector + arbitrary function data * @return success indicating whether the target call succeeded or failed + * @return gasUsed the total gas used from this forwarding call */ function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed) { - if (msg.sender != address(s_registry)) revert(); + if (msg.sender != address(s_registry)) revert InvalidCaller(msg.sender); + + uint256 g1 = gasleft(); address target = i_target; - gasUsed = gasleft(); + assembly { let g := gas() // Compute g -= PERFORM_GAS_CUSHION and check for underflow @@ -52,10 +58,18 @@ contract ZKSyncAutomationForwarder { if iszero(extcodesize(target)) { revert(0, 0) } - // call with exact gas - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) } - gasUsed = gasUsed - gasleft(); + + bytes memory returnData; + // solhint-disable-next-line avoid-low-level-calls + (success, returnData) = GAS_BOUND_CALLER.delegatecall{gas: gasAmount}( + abi.encodeWithSelector(IGasBoundCaller.gasBoundCall.selector, target, gasAmount, data) + ); + uint256 pubdataGasSpent; + if (success) { + (, pubdataGasSpent) = abi.decode(returnData, (bytes, uint256)); + } + gasUsed = g1 - gasleft() + pubdataGasSpent; return (success, gasUsed); } @@ -63,7 +77,8 @@ contract ZKSyncAutomationForwarder { return i_target; } - fallback() external { + // solhint-disable-next-line no-complex-fallback + fallback() external payable { // copy to memory for assembly access address logic = i_logic; // copied directly from OZ's Proxy contract diff --git a/contracts/src/v0.8/automation/chains/ArbitrumModule.sol b/contracts/src/v0.8/automation/chains/ArbitrumModule.sol index e27a0809b7e..2ad6fdddc8c 100644 --- a/contracts/src/v0.8/automation/chains/ArbitrumModule.sol +++ b/contracts/src/v0.8/automation/chains/ArbitrumModule.sol @@ -31,7 +31,7 @@ contract ArbitrumModule is ChainModuleBase { return ARB_SYS.arbBlockNumber(); } - function getCurrentL1Fee() external view override returns (uint256) { + function getCurrentL1Fee(uint256) external view override returns (uint256) { return ARB_GAS.getCurrentTxL1GasFees(); } diff --git a/contracts/src/v0.8/automation/chains/ChainModuleBase.sol b/contracts/src/v0.8/automation/chains/ChainModuleBase.sol index e9b082063bb..c595dbd6408 100644 --- a/contracts/src/v0.8/automation/chains/ChainModuleBase.sol +++ b/contracts/src/v0.8/automation/chains/ChainModuleBase.sol @@ -18,11 +18,11 @@ contract ChainModuleBase is IChainModule { return blockhash(n); } - function getCurrentL1Fee() external view virtual returns (uint256) { + function getCurrentL1Fee(uint256) external view virtual returns (uint256 l1Fee) { return 0; } - function getMaxL1Fee(uint256) external view virtual returns (uint256) { + function getMaxL1Fee(uint256) external view virtual returns (uint256 maxL1Fee) { return 0; } diff --git a/contracts/src/v0.8/automation/chains/OptimismModule.sol b/contracts/src/v0.8/automation/chains/OptimismModule.sol index 91c1c0ed968..7a464294963 100644 --- a/contracts/src/v0.8/automation/chains/OptimismModule.sol +++ b/contracts/src/v0.8/automation/chains/OptimismModule.sol @@ -4,6 +4,10 @@ pragma solidity 0.8.19; import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; import {ChainModuleBase} from "./ChainModuleBase.sol"; +/** + * @notice This contract is deprecated. Please use OptimismModuleV2 which utilizes the most recent offerings from OP + * and can estimate L1 fee with much lower cost. + */ contract OptimismModule is ChainModuleBase { /// @dev OP_L1_DATA_FEE_PADDING includes 80 bytes for L1 data padding for Optimism and BASE bytes private constant OP_L1_DATA_FEE_PADDING = @@ -16,11 +20,22 @@ contract OptimismModule is ChainModuleBase { uint256 private constant FIXED_GAS_OVERHEAD = 60_000; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 270; - function getCurrentL1Fee() external view override returns (uint256) { - return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(msg.data, OP_L1_DATA_FEE_PADDING)); + // @dev This will be updated to use the new function introduced by OP team + function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); } function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size + * @dev this function uses the getL1Fee function in OP gas price oracle. it estimates the exact L1 fee but it costs + * a lot of gas to call. + * @param dataSize the size of calldata + * @return l1Fee the L1 fee + */ + function _getL1Fee(uint256 dataSize) internal view returns (uint256) { // fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes. // Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes. bytes memory txCallData = new bytes(4 * dataSize); diff --git a/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol b/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol new file mode 100644 index 00000000000..772b66cdf99 --- /dev/null +++ b/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; +import {ChainModuleBase} from "./ChainModuleBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +/** + * @notice OptimismModuleV2 provides a cost-efficient way to get L1 fee on OP stack. + * After EIP-4844 is implemented in OP stack, the new OP upgrade includes a new function getL1FeeUpperBound to estimate + * the upper bound of current transaction's L1 fee. + */ +contract OptimismModuleV2 is ChainModuleBase, ConfirmedOwner { + error InvalidL1FeeCoefficient(uint8 coefficient); + event L1FeeCoefficientSet(uint8 coefficient); + + /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_GasPriceOracle precompile on Optimism. + /// @dev reference: https://community.optimism.io/docs/developers/build/transaction-fees/#estimating-the-l1-data-fee + address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + /// @dev L1 fee coefficient is used to account for the impact of data compression on the l1 fee + /// getL1FeeUpperBound returns the upper bound of l1 fee so this configurable coefficient will help + /// charge a predefined percentage of the upper bound. + uint8 private s_l1FeeCoefficient = 100; + uint256 private constant FIXED_GAS_OVERHEAD = 28_000; + uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; + + constructor() ConfirmedOwner(msg.sender) {} + + function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { + return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; + } + + function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size + * @dev this function uses the newly provided getL1FeeUpperBound function in OP gas price oracle. this helps + * estimate L1 fee with much lower cost + * @param dataSize the size of calldata + * @return l1Fee the L1 fee + */ + function _getL1Fee(uint256 dataSize) internal view returns (uint256) { + return OVM_GASPRICEORACLE.getL1FeeUpperBound(dataSize); + } + + function getGasOverhead() + external + pure + override + returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) + { + return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); + } + + /* @notice this function sets a new coefficient for L1 fee estimation. + * @dev this function can only be invoked by contract owner + * @param coefficient the new coefficient + */ + function setL1FeeCalculation(uint8 coefficient) external onlyOwner { + if (coefficient > 100) { + revert InvalidL1FeeCoefficient(coefficient); + } + + s_l1FeeCoefficient = coefficient; + + emit L1FeeCoefficientSet(coefficient); + } + + /* @notice this function returns the s_l1FeeCoefficient + * @return coefficient the current s_l1FeeCoefficient in effect + */ + function getL1FeeCoefficient() public view returns (uint256 coefficient) { + return s_l1FeeCoefficient; + } +} diff --git a/contracts/src/v0.8/automation/chains/ScrollModule.sol b/contracts/src/v0.8/automation/chains/ScrollModule.sol index 1e41ed3805f..30fdc908d49 100644 --- a/contracts/src/v0.8/automation/chains/ScrollModule.sol +++ b/contracts/src/v0.8/automation/chains/ScrollModule.sol @@ -3,8 +3,12 @@ pragma solidity 0.8.19; import {IScrollL1GasPriceOracle} from "../../vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol"; import {ChainModuleBase} from "./ChainModuleBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +contract ScrollModule is ChainModuleBase, ConfirmedOwner { + error InvalidL1FeeCoefficient(uint8 coefficient); + event L1FeeCoefficientSet(uint8 coefficient); -contract ScrollModule is ChainModuleBase { /// @dev SCROLL_L1_FEE_DATA_PADDING includes 140 bytes for L1 data padding for Scroll /// @dev according to testing, this padding allows automation registry to properly estimates L1 data fee with 3-5% buffer /// @dev this MAY NOT work for a different product and this may get out of date if transmit function is changed @@ -15,14 +19,26 @@ contract ScrollModule is ChainModuleBase { address private constant SCROLL_ORACLE_ADDR = 0x5300000000000000000000000000000000000002; IScrollL1GasPriceOracle private constant SCROLL_ORACLE = IScrollL1GasPriceOracle(SCROLL_ORACLE_ADDR); + /// @dev L1 fee coefficient can be applied to reduce possibly inflated gas cost + uint8 private s_l1FeeCoefficient = 100; uint256 private constant FIXED_GAS_OVERHEAD = 45_000; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 170; - function getCurrentL1Fee() external view override returns (uint256) { - return SCROLL_ORACLE.getL1Fee(bytes.concat(msg.data, SCROLL_L1_FEE_DATA_PADDING)); + constructor() ConfirmedOwner(msg.sender) {} + + function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { + return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; } function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size + * @param dataSize the size of calldata + * @return l1Fee the L1 fee + */ + function _getL1Fee(uint256 dataSize) internal view returns (uint256 l1Fee) { // fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes. // Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes. // this is the same as OP. @@ -38,4 +54,25 @@ contract ScrollModule is ChainModuleBase { { return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); } + + /* @notice this function sets a new coefficient for L1 fee estimation. + * @dev this function can only be invoked by contract owner + * @param coefficient the new coefficient + */ + function setL1FeeCalculation(uint8 coefficient) external onlyOwner { + if (coefficient > 100) { + revert InvalidL1FeeCoefficient(coefficient); + } + + s_l1FeeCoefficient = coefficient; + + emit L1FeeCoefficientSet(coefficient); + } + + /* @notice this function returns the s_l1FeeCoefficient + * @return coefficient the current s_l1FeeCoefficient in effect + */ + function getL1FeeCoefficient() public view returns (uint256 coefficient) { + return s_l1FeeCoefficient; + } } diff --git a/contracts/src/v0.8/automation/interfaces/IChainModule.sol b/contracts/src/v0.8/automation/interfaces/IChainModule.sol index e3a4b32c9b1..15e84f79848 100644 --- a/contracts/src/v0.8/automation/interfaces/IChainModule.sol +++ b/contracts/src/v0.8/automation/interfaces/IChainModule.sol @@ -2,26 +2,39 @@ pragma solidity ^0.8.0; interface IChainModule { - // retrieve the native block number of a chain. e.g. L2 block number on Arbitrum - function blockNumber() external view returns (uint256); + /* @notice this function provides the block number of current chain. + * @dev certain chains have its own function to retrieve block number, e.g. Arbitrum + * @return blockNumber the block number of the current chain. + */ + function blockNumber() external view returns (uint256 blockNumber); - // retrieve the native block hash of a chain. - function blockHash(uint256) external view returns (bytes32); + /* @notice this function provides the block hash of a block number. + * @dev this function can usually look back 256 blocks at most, unless otherwise specified + * @param blockNumber the block number + * @return blockHash the block hash of the input block number + */ + function blockHash(uint256 blockNumber) external view returns (bytes32 blockHash); - // retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains and - // L2 chains which don't have L1 fee component. it uses msg.data to estimate L1 data so - // it must be used with a transaction. Return value in wei. - function getCurrentL1Fee() external view returns (uint256); + /* @notice this function provides the L1 fee of current transaction. + * @dev retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should + * return 0 for L2 chains if they don't have L1 fee component. + * @param dataSize the calldata size of the current transaction + * @return l1Fee the L1 fee in wei incurred by calldata of this data size + */ + function getCurrentL1Fee(uint256 dataSize) external view returns (uint256 l1Fee); - // retrieve the L1 data fee for a L2 simulation. it should return 0 for L1 chains and - // L2 chains which don't have L1 fee component. Return value in wei. - function getMaxL1Fee(uint256 dataSize) external view returns (uint256); + /* @notice this function provides the max possible L1 fee of current transaction. + * @dev retrieve the max possible L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should + * return 0 for L2 chains if they don't have L1 fee component. + * @param dataSize the calldata size of the current transaction + * @return maxL1Fee the max possible L1 fee in wei incurred by calldata of this data size + */ + function getMaxL1Fee(uint256 dataSize) external view returns (uint256 maxL1Fee); - // Returns an upper bound on execution gas cost for one invocation of blockNumber(), - // one invocation of blockHash() and one invocation of getCurrentL1Fee(). - // Returns two values, first value indicates a fixed cost and the second value is - // the cost per msg.data byte (As some chain module's getCurrentL1Fee execution cost - // scales with calldata size) + /* @notice this function provides the overheads of calling this chain module. + * @return chainModuleFixedOverhead the fixed overhead incurred by calling this chain module + * @return chainModulePerByteOverhead the fixed overhead per byte incurred by calling this chain module with calldata + */ function getGasOverhead() external view diff --git a/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol b/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol new file mode 100644 index 00000000000..9edb541f9aa --- /dev/null +++ b/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +address constant GAS_BOUND_CALLER = address(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5); + +interface IGasBoundCaller { + function gasBoundCall(address _to, uint256 _maxTotalGas, bytes calldata _data) external payable; +} diff --git a/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol b/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol new file mode 100644 index 00000000000..c8f480065c4 --- /dev/null +++ b/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +ISystemContext constant SYSTEM_CONTEXT_CONTRACT = ISystemContext(address(0x800b)); + +interface ISystemContext { + function gasPrice() external view returns (uint256); + function gasPerPubdataByte() external view returns (uint256 gasPerPubdataByte); + function getCurrentPubdataSpent() external view returns (uint256 currentPubdataSpent); +} diff --git a/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol new file mode 100644 index 00000000000..89437215598 --- /dev/null +++ b/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol @@ -0,0 +1,441 @@ +// solhint-disable +// abi-checksum: 0x5857a77a981fcb60dbdac0700e68420cbe544249b20d9326d51c5ef8584c5dd7 +// SPDX-License-Identifier: MIT +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! +pragma solidity ^0.8.19; + +interface IZKSyncAutomationRegistryMaster2_3 { + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientBalance(uint256 available, uint256 requested); + error InsufficientLinkLiquidity(); + error InvalidDataLength(); + error InvalidFeed(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidToken(); + error InvalidTransmitter(); + error InvalidTrigger(); + error InvalidTriggerType(); + error MigrationNotPermitted(); + error MustSettleOffchain(); + error MustSettleOnchain(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyFinanceAdmin(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error TransferFailed(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + error ZeroAddressNotAllowed(); + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event BillingConfigOverridden(uint256 indexed id, ZKSyncAutomationRegistryBase2_3.BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + event BillingConfigSet(address indexed token, ZKSyncAutomationRegistryBase2_3.BillingConfig config); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event Transmitted(bytes32 configDigest, uint32 epoch); + event Unpaused(address account); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCharged(uint256 indexed id, ZKSyncAutomationRegistryBase2_3.PaymentReceipt receipt); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + fallback() external payable; + function acceptOwnership() external; + function fallbackTo() external view returns (address); + function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + function owner() external view returns (address); + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + ZKSyncAutomationRegistryBase2_3.OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + address[] memory billingTokens, + ZKSyncAutomationRegistryBase2_3.BillingConfig[] memory billingConfigs + ) external; + function transferOwnership(address to) external; + function transmit( + bytes32[3] memory reportContext, + bytes memory rawReport, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) external; + function typeAndVersion() external view returns (string memory); + + function cancelUpkeep(uint256 id) external; + function migrateUpkeeps(uint256[] memory ids, address destination) external; + function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; + function receiveUpkeeps(bytes memory encodedUpkeeps) external; + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + uint8 triggerType, + address billingToken, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) external returns (uint256 id); + + function acceptUpkeepAdmin(uint256 id) external; + function addFunds(uint256 id, uint96 amount) external payable; + function checkCallback( + uint256 id, + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ); + function checkUpkeep( + uint256 id + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ); + function executeCallback( + uint256 id, + bytes memory payload + ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function pauseUpkeep(uint256 id) external; + function removeBillingOverrides(uint256 id) external; + function setBillingOverrides( + uint256 id, + ZKSyncAutomationRegistryBase2_3.BillingOverrides memory billingOverrides + ) external; + function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; + function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; + function simulatePerformUpkeep( + uint256 id, + bytes memory performData + ) external view returns (bool success, uint256 gasUsed); + function transferUpkeepAdmin(uint256 id, address proposed) external; + function unpauseUpkeep(uint256 id) external; + function withdrawERC20Fees(address asset, address to, uint256 amount) external; + function withdrawFunds(uint256 id, address to) external; + function withdrawLink(address to, uint256 amount) external; + + function acceptPayeeship(address transmitter) external; + function disableOffchainPayments() external; + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); + function getAllowedReadOnlyAddress() external view returns (address); + function getAutomationForwarderLogic() external view returns (address); + function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); + function getBalance(uint256 id) external view returns (uint96 balance); + function getBillingConfig( + address billingToken + ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingConfig memory); + function getBillingOverrides( + uint256 upkeepID + ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingOverrides memory); + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool); + function getBillingToken(uint256 upkeepID) external view returns (address); + function getBillingTokenConfig( + address token + ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingConfig memory); + function getBillingTokens() external view returns (address[] memory); + function getCancellationDelay() external pure returns (uint256); + function getChainModule() external view returns (address chainModule); + function getConditionalGasOverhead() external pure returns (uint256); + function getConfig() external view returns (ZKSyncAutomationRegistryBase2_3.OnchainConfig memory); + function getFallbackNativePrice() external view returns (uint256); + function getFastGasFeedAddress() external view returns (address); + function getForwarder(uint256 upkeepID) external view returns (address); + function getHotVars() external view returns (ZKSyncAutomationRegistryBase2_3.HotVars memory); + function getLinkAddress() external view returns (address); + function getLinkUSDFeedAddress() external view returns (address); + function getLogGasOverhead() external pure returns (uint256); + function getMaxPaymentForGas( + uint256 id, + uint8 triggerType, + uint32 gasLimit, + address billingToken + ) external view returns (uint96 maxPayment); + function getMinBalance(uint256 id) external view returns (uint96); + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); + function getNativeUSDFeedAddress() external view returns (address); + function getNumUpkeeps() external view returns (uint256); + function getPayoutMode() external view returns (uint8); + function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); + function getPerSignerGasOverhead() external pure returns (uint256); + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); + function getReserveAmount(address billingToken) external view returns (uint256); + function getSignerInfo(address query) external view returns (bool active, uint8 index); + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); + function getStorage() external view returns (ZKSyncAutomationRegistryBase2_3.Storage memory); + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTransmittersWithPayees() + external + view + returns (ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); + function getTriggerType(uint256 upkeepId) external pure returns (uint8); + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); + function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); + function getWrappedNativeTokenAddress() external view returns (address); + function hasDedupKey(bytes32 dedupKey) external view returns (bool); + function linkAvailableForPayment() external view returns (int256); + function pause() external; + function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; + function setPayees(address[] memory payees) external; + function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; + function settleNOPsOffchain() external; + function supportsBillingToken(address token) external view returns (bool); + function transferPayeeship(address transmitter, address proposed) external; + function unpause() external; + function upkeepVersion() external pure returns (uint8); + function withdrawPayment(address from, address to) external; +} + +interface ZKSyncAutomationRegistryBase2_3 { + struct BillingOverrides { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + } + + struct BillingConfig { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + address priceFeed; + uint8 decimals; + uint256 fallbackPrice; + uint96 minSpend; + } + + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + address billingToken; + uint96 linkUSD; + uint96 nativeUSD; + uint96 billingUSD; + } + + struct OnchainConfig { + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + address transcoder; + bool reorgProtectionEnabled; + uint24 stalenessSeconds; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + address upkeepPrivilegeManager; + uint16 gasCeilingMultiplier; + address financeAdmin; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + uint256 fallbackNativePrice; + address[] registrars; + address chainModule; + } + + struct HotVars { + uint96 totalPremium; + uint32 latestEpoch; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint8 f; + bool paused; + bool reentrancyGuard; + bool reorgProtectionEnabled; + address chainModule; + } + + struct Storage { + address transcoder; + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 nonce; + address upkeepPrivilegeManager; + uint32 configCount; + uint32 latestConfigBlockNumber; + uint32 maxCheckDataSize; + address financeAdmin; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } +} + +interface IAutomationV21PlusCommon { + struct StateLegacy { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; + } + + struct OnchainConfigLegacy { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + } + + struct UpkeepInfoLegacy { + address target; + uint32 performGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformedBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; + } +} + +// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: +/* +[{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_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":"contract IERC20Metadata","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":"struct ZKSyncAutomationRegistryBase2_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":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverridesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +*/ diff --git a/contracts/src/v0.8/automation/test/WETH9.sol b/contracts/src/v0.8/automation/test/WETH9.sol index b8452d832b0..1225e6e39a8 100644 --- a/contracts/src/v0.8/automation/test/WETH9.sol +++ b/contracts/src/v0.8/automation/test/WETH9.sol @@ -53,7 +53,7 @@ contract WETH9 { revert InsufficientBalance(); } balanceOf[msg.sender] -= wad; - payable(msg.sender).transfer(wad); + payable(msg.sender).call{value: wad}(""); emit Withdrawal(msg.sender, wad); } 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 new file mode 100644 index 00000000000..cde05ab3a22 --- /dev/null +++ b/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +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 {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"; +import {ZKSyncAutomationRegistryLogicA2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol"; +import {ZKSyncAutomationRegistryLogicB2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol"; +import {ZKSyncAutomationRegistryLogicC2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol"; +import {ZKSyncAutomationRegistryBase2_3 as ZKSyncAutoBase} from "../../v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +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"; + +/** + * @title BaseTest provides basic test setup procedures and dependencies for use by other + * unit tests + */ +contract BaseTest is Test { + // test state (not exposed to derived tests) + uint256 private nonce; + + // constants + address internal constant ZERO_ADDRESS = address(0); + uint32 internal constant DEFAULT_GAS_FEE_PPB = 10_000_000; + uint24 internal constant DEFAULT_FLAT_FEE_MILLI_CENTS = 2_000; + + // config + uint8 internal constant F = 1; // number of faulty nodes + uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 + + // contracts + LinkToken internal linkToken; + ERC20Mock6Decimals internal usdToken6; + ERC20Mock internal usdToken18; + ERC20Mock internal usdToken18_2; + WETH9 internal weth; + MockV3Aggregator internal LINK_USD_FEED; + MockV3Aggregator internal NATIVE_USD_FEED; + MockV3Aggregator internal USDTOKEN_USD_FEED; + MockV3Aggregator internal FAST_GAS_FEED; + MockUpkeep internal TARGET1; + MockUpkeep internal TARGET2; + Transcoder internal TRANSCODER; + MockGasBoundCaller internal GAS_BOUND_CALLER; + MockZKSyncSystemContext internal SYSTEM_CONTEXT; + + // roles + address internal constant OWNER = address(uint160(uint256(keccak256("OWNER")))); + address internal constant UPKEEP_ADMIN = address(uint160(uint256(keccak256("UPKEEP_ADMIN")))); + address internal constant FINANCE_ADMIN = address(uint160(uint256(keccak256("FINANCE_ADMIN")))); + address internal constant STRANGER = address(uint160(uint256(keccak256("STRANGER")))); + address internal constant BROKE_USER = address(uint160(uint256(keccak256("BROKE_USER")))); // do not mint to this address + address internal constant PRIVILEGE_MANAGER = address(uint160(uint256(keccak256("PRIVILEGE_MANAGER")))); + + // nodes + uint256 internal constant SIGNING_KEY0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; + uint256 internal constant SIGNING_KEY1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; + uint256 internal constant SIGNING_KEY2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; + uint256 internal constant SIGNING_KEY3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; + address[] internal SIGNERS = new address[](4); + address[] internal TRANSMITTERS = new address[](4); + address[] internal NEW_TRANSMITTERS = new address[](4); + address[] internal PAYEES = new address[](4); + address[] internal NEW_PAYEES = new address[](4); + + function setUp() public virtual { + vm.startPrank(OWNER); + linkToken = new LinkToken(); + linkToken.grantMintRole(OWNER); + usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); + usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); + usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); + weth = new WETH9(); + + LINK_USD_FEED = new MockV3Aggregator(8, 2_000_000_000); // $20 + NATIVE_USD_FEED = new MockV3Aggregator(8, 400_000_000_000); // $4,000 + USDTOKEN_USD_FEED = new MockV3Aggregator(8, 100_000_000); // $1 + FAST_GAS_FEED = new MockV3Aggregator(0, 1_000_000_000); // 1 gwei + + TARGET1 = new MockUpkeep(); + TARGET2 = new MockUpkeep(); + + TRANSCODER = new Transcoder(); + GAS_BOUND_CALLER = new MockGasBoundCaller(); + SYSTEM_CONTEXT = new MockZKSyncSystemContext(); + + bytes memory callerCode = address(GAS_BOUND_CALLER).code; + vm.etch(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5, callerCode); + + bytes memory contextCode = address(SYSTEM_CONTEXT).code; + vm.etch(0x000000000000000000000000000000000000800B, contextCode); + + SIGNERS[0] = vm.addr(SIGNING_KEY0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 + SIGNERS[1] = vm.addr(SIGNING_KEY1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 + SIGNERS[2] = vm.addr(SIGNING_KEY2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b + SIGNERS[3] = vm.addr(SIGNING_KEY3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 + + TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER3")))); + TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER4")))); + NEW_TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + NEW_TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + NEW_TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER5")))); + NEW_TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER6")))); + + PAYEES[0] = address(100); + PAYEES[1] = address(101); + PAYEES[2] = address(102); + PAYEES[3] = address(103); + NEW_PAYEES[0] = address(100); + NEW_PAYEES[1] = address(101); + NEW_PAYEES[2] = address(106); + NEW_PAYEES[3] = address(107); + + // mint funds + vm.deal(OWNER, 100 ether); + vm.deal(UPKEEP_ADMIN, 100 ether); + vm.deal(FINANCE_ADMIN, 100 ether); + vm.deal(STRANGER, 100 ether); + + linkToken.mint(OWNER, 1000e18); + linkToken.mint(UPKEEP_ADMIN, 1000e18); + linkToken.mint(FINANCE_ADMIN, 1000e18); + linkToken.mint(STRANGER, 1000e18); + + usdToken18.mint(OWNER, 1000e18); + usdToken18.mint(UPKEEP_ADMIN, 1000e18); + usdToken18.mint(FINANCE_ADMIN, 1000e18); + usdToken18.mint(STRANGER, 1000e18); + + usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); + + usdToken6.mint(OWNER, 1000e6); + usdToken6.mint(UPKEEP_ADMIN, 1000e6); + usdToken6.mint(FINANCE_ADMIN, 1000e6); + usdToken6.mint(STRANGER, 1000e6); + + weth.mint(OWNER, 1000e18); + weth.mint(UPKEEP_ADMIN, 1000e18); + weth.mint(FINANCE_ADMIN, 1000e18); + weth.mint(STRANGER, 1000e18); + + vm.stopPrank(); + } + + /// @notice deploys the component parts of a registry, but nothing more + function deployZKSyncRegistry(ZKSyncAutoBase.PayoutMode payoutMode) internal returns (Registry) { + AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); + ZKSyncAutomationRegistryLogicC2_3 logicC2_3 = new ZKSyncAutomationRegistryLogicC2_3( + address(linkToken), + address(LINK_USD_FEED), + address(NATIVE_USD_FEED), + address(FAST_GAS_FEED), + address(forwarderLogic), + ZERO_ADDRESS, + payoutMode, + address(weth) + ); + ZKSyncAutomationRegistryLogicB2_3 logicB2_3 = new ZKSyncAutomationRegistryLogicB2_3(logicC2_3); + ZKSyncAutomationRegistryLogicA2_3 logicA2_3 = new ZKSyncAutomationRegistryLogicA2_3(logicB2_3); + return Registry(payable(address(new ZKSyncAutomationRegistry2_3(logicA2_3)))); + } + + /// @notice deploys and configures a registry, registrar, and everything needed for most tests + function deployAndConfigureZKSyncRegistryAndRegistrar( + ZKSyncAutoBase.PayoutMode payoutMode + ) internal returns (Registry, AutomationRegistrar2_3) { + Registry registry = deployZKSyncRegistry(payoutMode); + + IERC20[] memory billingTokens = new IERC20[](4); + billingTokens[0] = IERC20(address(usdToken18)); + billingTokens[1] = IERC20(address(weth)); + billingTokens[2] = IERC20(address(linkToken)); + billingTokens[3] = IERC20(address(usdToken6)); + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100e18; // 100 USD + minRegistrationFees[1] = 5e18; // 5 Native + minRegistrationFees[2] = 5e18; // 5 LINK + minRegistrationFees[3] = 100e6; // 100 USD + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 + }); + billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(NATIVE_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 5e18, // 5 Native + decimals: 18 + }); + billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 10% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(LINK_USD_FEED), + fallbackPrice: 1_000_000_000, // $10 + minSpend: 1e18, // 1 LINK + decimals: 18 + }); + billingTokenConfigs[3] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e6, // 1 USD + decimals: 6 + }); + + if (payoutMode == ZKSyncAutoBase.PayoutMode.OFF_CHAIN) { + // remove LINK as a payment method if we are settling offchain + assembly { + mstore(billingTokens, 2) + mstore(minRegistrationFees, 2) + mstore(billingTokenAddresses, 2) + mstore(billingTokenConfigs, 2) + } + } + + // deploy registrar + AutomationRegistrar2_3.InitialTriggerConfig[] + memory triggerConfigs = new AutomationRegistrar2_3.InitialTriggerConfig[](2); + triggerConfigs[0] = AutomationRegistrar2_3.InitialTriggerConfig({ + triggerType: 0, // condition + autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, + autoApproveMaxAllowed: 0 + }); + triggerConfigs[1] = AutomationRegistrar2_3.InitialTriggerConfig({ + triggerType: 1, // log + autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, + autoApproveMaxAllowed: 0 + }); + AutomationRegistrar2_3 registrar = new AutomationRegistrar2_3( + address(linkToken), + registry, + triggerConfigs, + billingTokens, + minRegistrationFees, + IWrappedNative(address(weth)) + ); + + address[] memory registrars; + registrars = new address[](1); + registrars[0] = address(registrar); + + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: address(TRANSCODER), + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + return (registry, registrar); + } + + /// @notice this function updates the billing config for the provided token on the provided registry, + /// and throws an error if the token is not found + function _updateBillingTokenConfig( + Registry registry, + address billingToken, + AutomationRegistryBase2_3.BillingConfig memory newConfig + ) internal { + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); + address[] memory billingTokens = registry.getBillingTokens(); + + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + + bool found = false; + for (uint256 i = 0; i < billingTokens.length; i++) { + if (billingTokens[i] == billingToken) { + found = true; + billingTokenConfigs[i] = newConfig; + } else { + billingTokenConfigs[i] = registry.getBillingTokenConfig(billingTokens[i]); + } + } + require(found, "could not find billing token provided on registry"); + + registry.setConfigTypeSafe( + signers, + transmitters, + f, + config, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokens, + billingTokenConfigs + ); + } + + /// @notice this function removes a billing token from the registry + function _removeBillingTokenConfig(Registry registry, address billingToken) internal { + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); + address[] memory billingTokens = registry.getBillingTokens(); + + address[] memory newBillingTokens = new address[](billingTokens.length - 1); + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length - 1); + + uint256 j = 0; + for (uint256 i = 0; i < billingTokens.length; i++) { + if (billingTokens[i] != billingToken) { + if (j == newBillingTokens.length) revert("could not find billing token provided on registry"); + newBillingTokens[j] = billingTokens[i]; + billingTokenConfigs[j] = registry.getBillingTokenConfig(billingTokens[i]); + j++; + } + } + + registry.setConfigTypeSafe( + signers, + transmitters, + f, + config, + OFFCHAIN_CONFIG_VERSION, + "", + newBillingTokens, + billingTokenConfigs + ); + } + + function _transmit(uint256 id, Registry registry, bytes4 selector) internal { + uint256[] memory ids = new uint256[](1); + ids[0] = id; + _transmit(ids, registry, selector); + } + + function _transmit(uint256[] memory ids, Registry registry, bytes4 selector) 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) { + triggers[i] = _encodeConditionalTrigger( + ZKSyncAutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) + ); + } 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]); + if (selector != bytes4(0)) { + vm.expectRevert(selector); + } + 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` + /// @param signerPrivateKeys - One or more addresses that will sign the report data + /// @return rawRs - Signature rs + /// @return rawSs - Signature ss + /// @return rawVs - Signature vs + function _signReport( + bytes memory report, + bytes32[3] memory reportContext, + uint256[] memory signerPrivateKeys + ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { + bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); + bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); + bytes memory vs = new bytes(signerPrivateKeys.length); + + bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signerPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + + return (rs, ss, bytes32(vs)); + } + + function _encodeReport(ZKSyncAutoBase.Report memory report) internal pure returns (bytes memory reportBytes) { + return abi.encode(report); + } + + function _encodeConditionalTrigger( + ZKSyncAutoBase.ConditionalTrigger memory trigger + ) internal pure returns (bytes memory triggerBytes) { + return abi.encode(trigger.blockNum, trigger.blockHash); + } + + /// @dev mints LINK to the recipient + function _mintLink(address recipient, uint256 amount) internal { + vm.prank(OWNER); + linkToken.mint(recipient, amount); + } + + /// @dev mints USDToken with 18 decimals to the recipient + function _mintERC20_18Decimals(address recipient, uint256 amount) internal { + vm.prank(OWNER); + usdToken18.mint(recipient, amount); + } + + /// @dev returns a pseudo-random 32 bytes + function _random() private returns (bytes32) { + nonce++; + return keccak256(abi.encode(block.timestamp, nonce)); + } + + /// @dev returns a pseudo-random number + function randomNumber() internal returns (uint256) { + return uint256(_random()); + } + + /// @dev returns a pseudo-random address + function randomAddress() internal returns (address) { + return address(uint160(randomNumber())); + } + + /// @dev returns a pseudo-random byte array + function randomBytes(uint256 length) internal returns (bytes memory) { + bytes memory result = new bytes(length); + bytes32 entropy; + for (uint256 i = 0; i < length; i++) { + if (i % 32 == 0) { + entropy = _random(); + } + result[i] = entropy[i % 32]; + } + return result; + } +} 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 new file mode 100644 index 00000000000..7098d9f38fa --- /dev/null +++ b/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol @@ -0,0 +1,2772 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {Vm} from "forge-std/Test.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {ZKSyncAutomationRegistryBase2_3 as AutoBase} from "../../v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol"; +import {AutomationRegistrar2_3 as Registrar} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; + +// forge test --match-path src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol --match-test + +enum Trigger { + CONDITION, + LOG +} + +contract SetUp is BaseTest { + Registry internal registry; + AutomationRegistryBase2_3.OnchainConfig internal config; + bytes internal constant offchainConfigBytes = abi.encode(1234, ZERO_ADDRESS); + + uint256 linkUpkeepID; + uint256 linkUpkeepID2; // 2 upkeeps use the same billing token (LINK) to test migration scenario + uint256 usdUpkeepID18; // 1 upkeep uses ERC20 token with 18 decimals + uint256 usdUpkeepID6; // 1 upkeep uses ERC20 token with 6 decimals + uint256 nativeUpkeepID; + + function setUp() public virtual override { + super.setUp(); + (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + config = registry.getConfig(); + + vm.startPrank(OWNER); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.startPrank(UPKEEP_ADMIN); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.startPrank(STRANGER); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.stopPrank(); + + linkUpkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + + linkUpkeepID2 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + + usdUpkeepID18 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken18), + "", + "", + "" + ); + + usdUpkeepID6 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken6), + "", + "", + "" + ); + + nativeUpkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(weth), + "", + "", + "" + ); + + vm.startPrank(OWNER); + registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); + registry.addFunds(linkUpkeepID2, registry.getMinBalanceForUpkeep(linkUpkeepID2)); + registry.addFunds(usdUpkeepID18, registry.getMinBalanceForUpkeep(usdUpkeepID18)); + registry.addFunds(usdUpkeepID6, registry.getMinBalanceForUpkeep(usdUpkeepID6)); + registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); + vm.stopPrank(); + } +} + +contract LatestConfigDetails is SetUp { + function testGet() public { + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registry.latestConfigDetails(); + assertEq(configCount, 1); + assertTrue(blockNumber > 0); + assertNotEq(configDigest, ""); + } +} + +contract CheckUpkeep is SetUp { + function testPreventExecutionOnCheckUpkeep() public { + uint256 id = 1; + bytes memory triggerData = abi.encodePacked("trigger_data"); + + // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry + // Expecting a revert since the tx.origin is not address(0) + vm.expectRevert(abi.encodeWithSelector(Registry.OnlySimulatedBackend.selector)); + registry.checkUpkeep(id, triggerData); + } +} + +contract WithdrawFunds is SetUp { + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.withdrawFunds(linkUpkeepID, STRANGER); + } + + function test_RevertsWhen_InvalidRecipient() external { + vm.expectRevert(Registry.InvalidRecipient.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); + } + + function test_RevertsWhen_UpkeepNotCanceled() external { + vm.expectRevert(Registry.UpkeepNotCanceled.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_Happy_Link() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); + uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); + + uint256 upkeepBalance = registry.getBalance(linkUpkeepID); + vm.expectEmit(); + emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); + } + + function test_Happy_USDToken() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(usdUpkeepID6); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); + uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); + + uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); + vm.expectEmit(); + emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); + + assertEq(registry.getBalance(usdUpkeepID6), 0); + assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); + } +} + +contract AddFunds is SetUp { + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + + // when msg.value is 0, it uses the ERC20 payment path + function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { + vm.startPrank(OWNER); + uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); + uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); + registry.addFunds(nativeUpkeepID, 1); + assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); + assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); + } + + // when msg.value is not 0, it uses the native payment path + function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { + uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); + uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); + registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored + assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); + assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); + } + + // it fails when the billing token is not native, but trying to pay with native + function test_RevertsWhen_NativePaymentDoesntMatchBillingToken() external { + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.addFunds{value: 1}(linkUpkeepID, 0); + } + + function test_RevertsWhen_UpkeepDoesNotExist() public { + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.addFunds(randomNumber(), 1); + } + + function test_RevertsWhen_UpkeepIsCanceled() public { + registry.cancelUpkeep(linkUpkeepID); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.addFunds(linkUpkeepID, 1); + } + + function test_anyoneCanAddFunds() public { + uint256 startAmount = registry.getBalance(linkUpkeepID); + vm.prank(UPKEEP_ADMIN); + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 1); + vm.prank(STRANGER); + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 2); + } + + function test_movesFundFromCorrectToken() public { + vm.startPrank(UPKEEP_ADMIN); + + uint256 startLINKRegistryBalance = linkToken.balanceOf(address(registry)); + uint256 startUSDRegistryBalance = usdToken18.balanceOf(address(registry)); + uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); + uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID18); + + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance); + assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance); + + registry.addFunds(usdUpkeepID18, 2); + assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance + 2); + assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance + 2); + } + + function test_emitsAnEvent() public { + vm.startPrank(UPKEEP_ADMIN); + vm.expectEmit(); + emit FundsAdded(linkUpkeepID, address(UPKEEP_ADMIN), 100); + registry.addFunds(linkUpkeepID, 100); + } +} + +contract Withdraw is SetUp { + address internal aMockAddress = randomAddress(); + + function testLinkAvailableForPaymentReturnsLinkBalance() public { + uint256 startBalance = linkToken.balanceOf(address(registry)); + int256 startLinkAvailable = registry.linkAvailableForPayment(); + + //simulate a deposit of link to the liquidity pool + _mintLink(address(registry), 1e10); + + //check there's a balance + assertEq(linkToken.balanceOf(address(registry)), startBalance + 1e10); + + //check the link available has increased by the same amount + assertEq(uint256(registry.linkAvailableForPayment()), uint256(startLinkAvailable) + 1e10); + } + + function testWithdrawLinkRevertsBecauseOnlyFinanceAdminAllowed() public { + vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); + registry.withdrawLink(aMockAddress, 1); + } + + function testWithdrawLinkRevertsBecauseOfInsufficientBalance() public { + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is 0 balance + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawLink(aMockAddress, 1); + + vm.stopPrank(); + } + + function testWithdrawLinkRevertsBecauseOfInvalidRecipient() public { + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is 0 balance + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidRecipient.selector)); + registry.withdrawLink(ZERO_ADDRESS, 1); + + vm.stopPrank(); + } + + function testWithdrawLinkSuccess() public { + //simulate a deposit of link to the liquidity pool + _mintLink(address(registry), 1e10); + uint256 startBalance = linkToken.balanceOf(address(registry)); + + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is a ton of link available + registry.withdrawLink(aMockAddress, 1); + + vm.stopPrank(); + + assertEq(linkToken.balanceOf(address(aMockAddress)), 1); + assertEq(linkToken.balanceOf(address(registry)), startBalance - 1); + } + + function test_WithdrawERC20Fees_RespectsReserveAmount() public { + assertEq(registry.getBalance(usdUpkeepID18), registry.getReserveAmount(address(usdToken18))); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); + } + + function test_WithdrawERC20Fees_RevertsWhen_AttemptingToWithdrawLINK() public { + _mintLink(address(registry), 1e10); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(Registry.InvalidToken.selector); + registry.withdrawERC20Fees(address(linkToken), FINANCE_ADMIN, 1); // should revert + registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds + } + + // default is ON_CHAIN mode + function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { + _transmit(usdUpkeepID18, registry, bytes4(0)); // adds USD token to finance withdrawable, and gives NOPs a LINK balance + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert + _mintLink(address(registry), uint256(registry.linkAvailableForPayment() * -10)); // top up LINK liquidity pool + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw + } + + function test_WithdrawERC20Fees_InOffChainMode_Happy() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw + + // recipient should get the funds + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + } + + function testWithdrawERC20FeeSuccess() public { + // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) + uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); + uint256 startAmount = usdToken18.balanceOf(address(registry)); + _mintERC20_18Decimals(address(registry), 1e10); + + // depositing shouldn't change reserve amount + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); + + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 USDToken + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); + + vm.stopPrank(); + + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + assertEq(usdToken18.balanceOf(address(registry)), startAmount + 1e10 - 1); + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); + } +} + +contract SetConfig is SetUp { + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + address module = address(new ChainModuleBase()); + + AutomationRegistryBase2_3.OnchainConfig cfg = + AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: _getRegistrars(), + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: module, + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + function testSetConfigSuccess() public { + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress = address(usdToken18); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config = registry.getBillingTokenConfig(billingTokenAddress); + assertEq(config.gasFeePPB, 5_000); + assertEq(config.flatFeeMilliCents, 20_000); + assertEq(config.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config.minSpend, 100_000); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 1); + } + + function testSetConfigMultipleBillingConfigsSuccess() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(usdToken18); + address[] memory billingTokens = new address[](2); + billingTokens[0] = billingTokenAddress1; + billingTokens[1] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config1 = registry.getBillingTokenConfig(billingTokenAddress1); + assertEq(config1.gasFeePPB, 5_001); + assertEq(config1.flatFeeMilliCents, 20_001); + assertEq(config1.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config1.fallbackPrice, 100); + assertEq(config1.minSpend, 100); + + AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); + assertEq(config2.gasFeePPB, 5_002); + assertEq(config2.flatFeeMilliCents, 20_002); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config2.fallbackPrice, 200); + assertEq(config2.minSpend, 200); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 2); + } + + function testSetConfigTwiceAndLastSetOverwrites() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + // BillingConfig1 + address billingTokenAddress1 = address(usdToken18); + address[] memory billingTokens1 = new address[](1); + billingTokens1[0] = billingTokenAddress1; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs1 = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs1[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + + // the first time uses the default onchain config with 2 registrars + bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1); + + // set config once + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling1, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig1, , , ) = registry.getState(); + assertEq(onchainConfig1.registrars.length, 2); + + // BillingConfig2 + address billingTokenAddress2 = address(usdToken18); + address[] memory billingTokens2 = new address[](1); + billingTokens2[0] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs2 = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs2[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + address[] memory newRegistrars = new address[](3); + newRegistrars[0] = address(uint160(uint256(keccak256("newRegistrar1")))); + newRegistrars[1] = address(uint160(uint256(keccak256("newRegistrar2")))); + newRegistrars[2] = address(uint160(uint256(keccak256("newRegistrar3")))); + + // new onchain config with 3 new registrars, all other fields stay the same as the default + AutomationRegistryBase2_3.OnchainConfig memory cfg2 = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: newRegistrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: module, + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + // the second time uses the new onchain config with 3 new registrars and also new billing tokens/configs + bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg2, billingTokens2, billingConfigs2); + + // set config twice + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling2, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + ( + , + IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig2, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) = registry.getState(); + + assertEq(onchainConfig2.registrars.length, 3); + for (uint256 i = 0; i < newRegistrars.length; i++) { + assertEq(newRegistrars[i], onchainConfig2.registrars[i]); + } + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); + assertEq(config2.gasFeePPB, 5_002); + assertEq(config2.flatFeeMilliCents, 20_002); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config2.fallbackPrice, 200); + assertEq(config2.minSpend, 200); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 1); + } + + function testSetConfigDuplicateBillingConfigFailure() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(linkToken); + address[] memory billingTokens = new address[](2); + billingTokens[0] = billingTokenAddress1; + billingTokens[1] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + // expect revert because of duplicate tokens + vm.expectRevert(abi.encodeWithSelector(Registry.DuplicateEntry.selector)); + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + } + + function testSetConfigRevertDueToInvalidToken() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + // deploy registry with OFF_CHAIN payout mode + registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + + function testSetConfigRevertDueToInvalidDecimals() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 6 // link token should have 18 decimals + }); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + + function testSetConfigOnTransmittersAndPayees() public { + registry.setPayees(PAYEES); + AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry + .getTransmittersWithPayees(); + assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); + + for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { + address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; + address payeeAddress = transmitterPayeeInfos[i].payeeAddress; + + address expectedTransmitter = TRANSMITTERS[i]; + address expectedPayee = PAYEES[i]; + + assertEq(transmitterAddress, expectedTransmitter); + assertEq(payeeAddress, expectedPayee); + } + } + + function testSetConfigWithNewTransmittersSuccess() public { + registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 0); + + address billingTokenAddress = address(usdToken18); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , address[] memory signers, address[] memory transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + + (configCount, blockNumber, ) = registry.latestConfigDetails(); + configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , signers, transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, NEW_TRANSMITTERS); + } + + function _getRegistrars() private pure returns (address[] memory) { + address[] memory registrars = new address[](2); + registrars[0] = address(uint160(uint256(keccak256("registrar1")))); + registrars[1] = address(uint160(uint256(keccak256("registrar2")))); + return registrars; + } + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } +} + +contract NOPsSettlement is SetUp { + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + + function testSettleNOPsOffchainRevertDueToUnauthorizedCaller() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); + registry.settleNOPsOffchain(); + } + + function testSettleNOPsOffchainRevertDueToOffchainSettlementDisabled() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + vm.prank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOnchain.selector)); + registry.settleNOPsOffchain(); + } + + function testSettleNOPsOffchainSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + uint256[] memory payments = new uint256[](TRANSMITTERS.length); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + payments[i] = 0; + } + + vm.startPrank(FINANCE_ADMIN); + vm.expectEmit(); + emit NOPsSettledOffchain(PAYEES, payments); + registry.settleNOPsOffchain(); + } + + // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same + function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + + // verify transmitters have positive balances + uint256[] memory payments = new uint256[](TRANSMITTERS.length); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertTrue(balance > 0); + assertEq(0, lastCollected); + + payments[i] = balance; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + vm.expectEmit(); + emit NOPsSettledOffchain(PAYEES, payments); + registry.settleNOPsOffchain(); + + // verify that transmitters balance has been zeroed out + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); + // should have some ERC20s in registry after transmit + uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); + + vm.startPrank(UPKEEP_ADMIN); + vm.roll(100 + block.number); + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + + uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); + + // finance admin comes to withdraw all available ERC20s + vm.startPrank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); + + uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); + + uint256 reservedLink = registry.getReserveAmount(address(linkToken)); + require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); + + // owner comes to disable offchain mode + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity + vm.startPrank(FINANCE_ADMIN); + uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); + + // reserved link amount to NOPs should stay the same after switching to onchain mode + assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); + // available ERC20 for payment should be 0 since finance admin withdrew all already + assertEq(erc20ForPayment4, 0); + } + + function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, Registrar registrar) = deployAndConfigureZKSyncRegistryAndRegistrar( + AutoBase.PayoutMode.OFF_CHAIN + ); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so TRANSMITTERS earn some rewards + _transmit(id, registry, bytes4(0)); + + // TRANSMITTERS have positive balance now + // configure the registry to use NEW_TRANSMITTERS + _configureWithNewTransmitters(registry, registrar); + + _transmit(id, registry, bytes4(0)); + + // verify all transmitters have positive balances + address[] memory expectedPayees = new address[](6); + uint256[] memory expectedPayments = new uint256[](6); + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + NEW_TRANSMITTERS[i] + ); + assertTrue(active); + assertEq(i, index); + assertTrue(lastCollected > 0); + expectedPayments[i] = balance; + expectedPayees[i] = payee; + } + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + TRANSMITTERS[i] + ); + assertFalse(active); + assertEq(i, index); + assertTrue(balance > 0); + assertTrue(lastCollected > 0); + expectedPayments[2 + i] = balance; + expectedPayees[2 + i] = payee; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + + // simply expectEmit won't work here because s_deactivatedTransmitters is an enumerable set so the order of these + // deactivated transmitters is not guaranteed. To handle this, we record logs and decode data field manually. + vm.recordLogs(); + registry.settleNOPsOffchain(); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + Vm.Log memory l = entries[0]; + assertEq(l.topics[0], keccak256("NOPsSettledOffchain(address[],uint256[])")); + (address[] memory actualPayees, uint256[] memory actualPayments) = abi.decode(l.data, (address[], uint256[])); + assertEq(actualPayees.length, 6); + assertEq(actualPayments.length, 6); + + // first 4 payees and payments are for NEW_TRANSMITTERS and they are ordered. + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + assertEq(actualPayees[i], expectedPayees[i]); + assertEq(actualPayments[i], expectedPayments[i]); + } + + // the last 2 payees and payments for TRANSMITTERS[2] and TRANSMITTERS[3] and they are not ordered + assertTrue( + (actualPayments[5] == expectedPayments[5] && + actualPayees[5] == expectedPayees[5] && + actualPayments[4] == expectedPayments[4] && + actualPayees[4] == expectedPayees[4]) || + (actualPayments[5] == expectedPayments[4] && + actualPayees[5] == expectedPayees[4] && + actualPayments[4] == expectedPayments[5] && + actualPayees[4] == expectedPayees[5]) + ); + + // verify that new transmitters balance has been zeroed out + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(NEW_TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + // verify that deactivated transmitters (TRANSMITTERS[2] and TRANSMITTERS[3]) balance has been zeroed out + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertFalse(active); + assertEq(i, index); + assertEq(0, balance); + } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); + } + + function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(bytes("Only callable by owner")); + registry.disableOffchainPayments(); + } + + function testDisableOffchainPaymentsSuccess() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + assertEq(uint8(AutoBase.PayoutMode.ON_CHAIN), registry.getPayoutMode()); + } + + function testSinglePerformAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + vm.expectEmit(); + // the upkeep spent less than minimum spending limit so upkeep admin can only withdraw upkeep balance - min spend value + emit FundsWithdrawn(id, 9.9e19, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function testMultiplePerformsAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually call transmit so transmitters earn some rewards + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry, bytes4(0)); + } + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // manually call transmit after offchain payment is disabled + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry, bytes4(0)); + } + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + uint256 balance = registry.getBalance(id); + vm.expectEmit(); + emit FundsWithdrawn(id, balance, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { + IERC20[] memory billingTokens = new IERC20[](1); + billingTokens[0] = IERC20(address(usdToken18)); + + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100e18; // 100 USD + + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 10_000_000, // 15% + flatFeeMilliCents: 2_000, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 + }); + + address[] memory registrars = new address[](1); + registrars[0] = address(registrar); + + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + + registry.setPayees(NEW_PAYEES); + } +} + +contract WithdrawPayment is SetUp { + function testWithdrawPaymentRevertDueToOffchainPayoutMode() public { + registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); + vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOffchain.selector)); + vm.prank(TRANSMITTERS[0]); + registry.withdrawPayment(TRANSMITTERS[0], TRANSMITTERS[0]); + } +} + +contract RegisterUpkeep is SetUp { + function test_RevertsWhen_Paused() public { + registry.pause(); + vm.expectRevert(Registry.RegistryPaused.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_TargetIsNotAContract() public { + vm.expectRevert(Registry.NotAContract.selector); + registry.registerUpkeep( + randomAddress(), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_CalledByNonOwner() public { + vm.prank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByOwnerOrRegistrar.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_ExecuteGasIsTooLow() public { + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.registerUpkeep( + address(TARGET1), + 2299, // 1 less than min + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_ExecuteGasIsTooHigh() public { + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas + 1, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_TheBillingTokenIsNotConfigured() public { + vm.expectRevert(Registry.InvalidToken.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + randomAddress(), + "", + "", + "" + ); + } + + function test_RevertsWhen_CheckDataIsTooLarge() public { + vm.expectRevert(Registry.CheckDataExceedsLimit.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + randomBytes(config.maxCheckDataSize + 1), + "", + "" + ); + } + + function test_Happy() public { + bytes memory checkData = randomBytes(config.maxCheckDataSize); + bytes memory trigggerConfig = randomBytes(100); + bytes memory offchainConfig = randomBytes(100); + + uint256 upkeepCount = registry.getNumUpkeeps(); + + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.LOG), + address(linkToken), + checkData, + trigggerConfig, + offchainConfig + ); + + assertEq(registry.getNumUpkeeps(), upkeepCount + 1); + assertEq(registry.getUpkeep(upkeepID).target, address(TARGET1)); + assertEq(registry.getUpkeep(upkeepID).performGas, config.maxPerformGas); + assertEq(registry.getUpkeep(upkeepID).checkData, checkData); + assertEq(registry.getUpkeep(upkeepID).balance, 0); + assertEq(registry.getUpkeep(upkeepID).admin, UPKEEP_ADMIN); + assertEq(registry.getUpkeep(upkeepID).offchainConfig, offchainConfig); + assertEq(registry.getUpkeepTriggerConfig(upkeepID), trigggerConfig); + assertEq(uint8(registry.getTriggerType(upkeepID)), uint8(Trigger.LOG)); + } +} + +contract OnTokenTransfer is SetUp { + function test_RevertsWhen_NotCalledByTheLinkToken() public { + vm.expectRevert(Registry.OnlyCallableByLINKToken.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); + } + + function test_RevertsWhen_NotCalledWithExactly32Bytes() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.InvalidDataLength.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(31)); + vm.expectRevert(Registry.InvalidDataLength.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(33)); + } + + function test_RevertsWhen_TheUpkeepIsCancelledOrDNE() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(randomNumber())); + } + + function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.InvalidToken.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID18)); + } + + function test_Happy() public { + vm.startPrank(address(linkToken)); + uint256 beforeBalance = registry.getBalance(linkUpkeepID); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); + assertEq(registry.getBalance(linkUpkeepID), beforeBalance + 100); + } +} + +contract GetMinBalanceForUpkeep is SetUp { + function test_accountsForFlatFee_with18Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken18)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID18); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID18); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } + + function test_accountsForFlatFee_with6Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken6)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID6); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID6); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } +} + +contract BillingOverrides is SetUp { + event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + + function test_RevertsWhen_NotPrivilegeManager() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_RevertsWhen_UpkeepCancelled() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(PRIVILEGE_MANAGER); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_Happy_SetBillingOverrides() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + + vm.expectEmit(); + emit BillingConfigOverridden(linkUpkeepID, billingOverrides); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_Happy_RemoveBillingOverrides() public { + vm.startPrank(PRIVILEGE_MANAGER); + + vm.expectEmit(); + emit BillingConfigOverrideRemoved(linkUpkeepID); + registry.removeBillingOverrides(linkUpkeepID); + } + + function test_Happy_MaxGasPayment_WithBillingOverrides() public { + uint96 maxPayment1 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + + // Double the two billing values + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: DEFAULT_GAS_FEE_PPB * 2, + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS * 2 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + + // maxPayment2 should be greater than maxPayment1 after the overrides + // The 2 numbers should follow this: maxPayment2 - maxPayment1 == 2 * recepit.premium + // We do not apply the exact equation since we couldn't get the receipt.premium value + uint96 maxPayment2 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + assertGt(maxPayment2, maxPayment1); + } +} + +contract Transmit is SetUp { + function test_transmitRevertWithExtraBytes() external { + bytes32[3] memory exampleReportContext = [ + bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef), + bytes32(0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890), + bytes32(0x7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456) + ]; + + bytes memory exampleRawReport = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; + + bytes32[] memory exampleRs = new bytes32[](3); + exampleRs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleRs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleRs[2] = bytes32(0x7890789078907890789078907890789078907890789078907890789078907890); + + bytes32[] memory exampleSs = new bytes32[](3); + exampleSs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleSs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleSs[2] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + + bytes32 exampleRawVs = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + + bytes memory transmitData = abi.encodeWithSelector( + registry.transmit.selector, + exampleReportContext, + exampleRawReport, + exampleRs, + exampleSs, + exampleRawVs + ); + bytes memory badTransmitData = bytes.concat(transmitData, bytes1(0x00)); // add extra data + vm.startPrank(TRANSMITTERS[0]); + (bool success, bytes memory returnData) = address(registry).call(badTransmitData); // send the bogus transmit + assertFalse(success, "Call did not revert as expected"); + assertEq(returnData, abi.encodePacked(Registry.InvalidDataLength.selector)); + vm.stopPrank(); + } + + function test_handlesMixedBatchOfBillingTokens() external { + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID18); + prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevTokenBalances = new uint256[](3); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); + prevTokenBalances[2] = weth.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](3); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); + prevReserveBalances[2] = registry.getReserveAmount(address(weth)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = linkUpkeepID; + upkeepIDs[1] = usdUpkeepID18; + upkeepIDs[2] = nativeUpkeepID; + + // withdraw-able by finance team should be 0 + require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); + require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); + + // do the thing + _transmit(upkeepIDs, registry, bytes4(0)); + + // withdraw-able by the finance team should be positive + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); + + // assert upkeep balances have decreased + require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); + require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); + 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], usdToken18.balanceOf(address(registry))); + assertEq(prevTokenBalances[2], weth.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), + "usd 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)), + "usd reserve amount should have decreased" + ); + require( + prevReserveBalances[2] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); + } + + function test_handlesInsufficientBalanceWithUSDToken18() external { + // deploy and configure a registry with ON_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + // register an upkeep and add funds + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + 1000000, + UPKEEP_ADMIN, + 0, + address(usdToken18), + "", + "", + "" + ); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(upkeepID, 1); // smaller than gasCharge + uint256 balance = registry.getBalance(upkeepID); + + // manually create a transmit + vm.recordLogs(); + _transmit(upkeepID, registry, bytes4(0)); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 3); + Vm.Log memory l1 = entries[1]; + assertEq( + l1.topics[0], + keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") + ); + ( + uint96 gasChargeInBillingToken, + uint96 premiumInBillingToken, + uint96 gasReimbursementInJuels, + uint96 premiumInJuels, + address billingToken, + uint96 linkUSD, + uint96 nativeUSD, + uint96 billingUSD + ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); + + assertEq(gasChargeInBillingToken, balance); + assertEq(gasReimbursementInJuels, (balance * billingUSD) / linkUSD); + assertEq(premiumInJuels, 0); + assertEq(premiumInBillingToken, 0); + } + + function test_handlesInsufficientBalanceWithUSDToken6() external { + // deploy and configure a registry with ON_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + // register an upkeep and add funds + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + 1000000, + UPKEEP_ADMIN, + 0, + address(usdToken6), + "", + "", + "" + ); + vm.prank(OWNER); + usdToken6.mint(UPKEEP_ADMIN, 1e20); + + vm.startPrank(UPKEEP_ADMIN); + usdToken6.approve(address(registry), 1e20); + registry.addFunds(upkeepID, 100); // this is greater than gasCharge but less than (gasCharge + premium) + uint256 balance = registry.getBalance(upkeepID); + + // manually create a transmit + vm.recordLogs(); + _transmit(upkeepID, registry, bytes4(0)); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 3); + Vm.Log memory l1 = entries[1]; + assertEq( + l1.topics[0], + keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") + ); + ( + uint96 gasChargeInBillingToken, + uint96 premiumInBillingToken, + uint96 gasReimbursementInJuels, + uint96 premiumInJuels, + address billingToken, + uint96 linkUSD, + uint96 nativeUSD, + uint96 billingUSD + ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); + + assertEq(premiumInJuels, (balance * billingUSD * 1e12) / linkUSD - gasReimbursementInJuels); // scale to 18 decimals + assertEq(premiumInBillingToken, (premiumInJuels * linkUSD + (billingUSD * 1e12 - 1)) / (billingUSD * 1e12)); + } +} + +contract MigrateReceive is SetUp { + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + + Registry newRegistry; + uint256[] idsToMigrate; + + function setUp() public override { + super.setUp(); + (newRegistry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + idsToMigrate.push(linkUpkeepID); + idsToMigrate.push(linkUpkeepID2); + idsToMigrate.push(usdUpkeepID18); + idsToMigrate.push(nativeUpkeepID); + registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); + } + + function test_RevertsWhen_PermissionsNotSet() external { + // no permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // only outgoing permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // only incoming permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // permissions opposite direction + registry.setPeerRegistryMigrationPermission(address(newRegistry), 2); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 1); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + } + + function test_RevertsWhen_ReceivingRegistryDoesNotSupportToken() external { + _removeBillingTokenConfig(newRegistry, address(weth)); + vm.expectRevert(Registry.InvalidToken.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + idsToMigrate.pop(); // remove native upkeep id + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); // should succeed now + } + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + } + + function test_Success() external { + vm.startPrank(UPKEEP_ADMIN); + + // add some changes in upkeep data to the mix + registry.pauseUpkeep(usdUpkeepID18); + registry.setUpkeepTriggerConfig(linkUpkeepID, randomBytes(100)); + registry.setUpkeepCheckData(nativeUpkeepID, randomBytes(25)); + + // record previous state + uint256[] memory prevUpkeepBalances = new uint256[](4); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); + prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID18); + prevUpkeepBalances[3] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevReserveBalances = new uint256[](3); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); + prevReserveBalances[2] = registry.getReserveAmount(address(weth)); + uint256[] memory prevTokenBalances = new uint256[](3); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); + prevTokenBalances[2] = weth.balanceOf(address(registry)); + bytes[] memory prevUpkeepData = new bytes[](4); + prevUpkeepData[0] = abi.encode(registry.getUpkeep(linkUpkeepID)); + prevUpkeepData[1] = abi.encode(registry.getUpkeep(linkUpkeepID2)); + prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID18)); + prevUpkeepData[3] = abi.encode(registry.getUpkeep(nativeUpkeepID)); + bytes[] memory prevUpkeepTriggerData = new bytes[](4); + prevUpkeepTriggerData[0] = registry.getUpkeepTriggerConfig(linkUpkeepID); + prevUpkeepTriggerData[1] = registry.getUpkeepTriggerConfig(linkUpkeepID2); + prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID18); + prevUpkeepTriggerData[3] = registry.getUpkeepTriggerConfig(nativeUpkeepID); + + // event expectations + vm.expectEmit(address(registry)); + emit UpkeepMigrated(linkUpkeepID, prevUpkeepBalances[0], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(linkUpkeepID2, prevUpkeepBalances[1], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(usdUpkeepID18, prevUpkeepBalances[2], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(nativeUpkeepID, prevUpkeepBalances[3], address(newRegistry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(linkUpkeepID, prevUpkeepBalances[0], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(linkUpkeepID2, prevUpkeepBalances[1], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(usdUpkeepID18, prevUpkeepBalances[2], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(nativeUpkeepID, prevUpkeepBalances[3], address(registry)); + + // do the thing + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // assert upkeep balances have been migrated + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(registry.getBalance(linkUpkeepID2), 0); + assertEq(registry.getBalance(usdUpkeepID18), 0); + assertEq(registry.getBalance(nativeUpkeepID), 0); + assertEq(newRegistry.getBalance(linkUpkeepID), prevUpkeepBalances[0]); + assertEq(newRegistry.getBalance(linkUpkeepID2), prevUpkeepBalances[1]); + assertEq(newRegistry.getBalance(usdUpkeepID18), prevUpkeepBalances[2]); + assertEq(newRegistry.getBalance(nativeUpkeepID), prevUpkeepBalances[3]); + + // assert reserve balances have been adjusted + assertEq( + newRegistry.getReserveAmount(address(linkToken)), + newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) + ); + assertEq(newRegistry.getReserveAmount(address(usdToken18)), newRegistry.getBalance(usdUpkeepID18)); + assertEq(newRegistry.getReserveAmount(address(weth)), newRegistry.getBalance(nativeUpkeepID)); + assertEq( + newRegistry.getReserveAmount(address(linkToken)), + prevReserveBalances[0] - registry.getReserveAmount(address(linkToken)) + ); + assertEq( + newRegistry.getReserveAmount(address(usdToken18)), + prevReserveBalances[1] - registry.getReserveAmount(address(usdToken18)) + ); + assertEq( + newRegistry.getReserveAmount(address(weth)), + prevReserveBalances[2] - registry.getReserveAmount(address(weth)) + ); + + // assert token have been transferred + assertEq( + linkToken.balanceOf(address(newRegistry)), + newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) + ); + assertEq(usdToken18.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID18)); + assertEq(weth.balanceOf(address(newRegistry)), newRegistry.getBalance(nativeUpkeepID)); + assertEq(linkToken.balanceOf(address(registry)), prevTokenBalances[0] - linkToken.balanceOf(address(newRegistry))); + assertEq( + usdToken18.balanceOf(address(registry)), + prevTokenBalances[1] - usdToken18.balanceOf(address(newRegistry)) + ); + assertEq(weth.balanceOf(address(registry)), prevTokenBalances[2] - weth.balanceOf(address(newRegistry))); + + // assert upkeep data matches + assertEq(prevUpkeepData[0], abi.encode(newRegistry.getUpkeep(linkUpkeepID))); + assertEq(prevUpkeepData[1], abi.encode(newRegistry.getUpkeep(linkUpkeepID2))); + assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID18))); + assertEq(prevUpkeepData[3], abi.encode(newRegistry.getUpkeep(nativeUpkeepID))); + assertEq(prevUpkeepTriggerData[0], newRegistry.getUpkeepTriggerConfig(linkUpkeepID)); + assertEq(prevUpkeepTriggerData[1], newRegistry.getUpkeepTriggerConfig(linkUpkeepID2)); + assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID18)); + assertEq(prevUpkeepTriggerData[3], newRegistry.getUpkeepTriggerConfig(nativeUpkeepID)); + + vm.stopPrank(); + } +} + +contract Pause is SetUp { + function test_RevertsWhen_CalledByNonOwner() external { + vm.expectRevert(bytes("Only callable by owner")); + vm.prank(STRANGER); + registry.pause(); + } + + function test_CalledByOwner_success() external { + vm.startPrank(registry.owner()); + registry.pause(); + + (IAutomationV21PlusCommon.StateLegacy memory state, , , , ) = registry.getState(); + assertTrue(state.paused); + } + + function test_revertsWhen_registerUpkeepInPausedRegistry() external { + vm.startPrank(registry.owner()); + registry.pause(); + + vm.expectRevert(Registry.RegistryPaused.selector); + uint256 id = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_revertsWhen_transmitInPausedRegistry() external { + vm.startPrank(registry.owner()); + registry.pause(); + + _transmit(usdUpkeepID18, registry, Registry.RegistryPaused.selector); + } +} + +contract Unpause is SetUp { + function test_RevertsWhen_CalledByNonOwner() external { + vm.startPrank(registry.owner()); + registry.pause(); + + vm.expectRevert(bytes("Only callable by owner")); + vm.startPrank(STRANGER); + registry.unpause(); + } + + function test_CalledByOwner_success() external { + vm.startPrank(registry.owner()); + registry.pause(); + (IAutomationV21PlusCommon.StateLegacy memory state1, , , , ) = registry.getState(); + assertTrue(state1.paused); + + registry.unpause(); + (IAutomationV21PlusCommon.StateLegacy memory state2, , , , ) = registry.getState(); + assertFalse(state2.paused); + } +} + +contract CancelUpkeep is SetUp { + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + + function test_RevertsWhen_IdIsInvalid_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + vm.expectRevert(Registry.CannotCancel.selector); + registry.cancelUpkeep(1111111); + } + + function test_RevertsWhen_IdIsInvalid_CalledByOwner() external { + vm.startPrank(registry.owner()); + vm.expectRevert(Registry.CannotCancel.selector); + registry.cancelUpkeep(1111111); + } + + function test_RevertsWhen_NotCalledByOwnerOrAdmin() external { + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByOwnerOrAdmin.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(registry.owner()); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(UPKEEP_ADMIN); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); + + // 50 is the cancellation delay + assertEq(bn + 50, maxValidBlocknumber); + } + + function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); + + // cancellation by registry owner is immediate and no cancellation delay is applied + assertEq(bn, maxValidBlocknumber); + } + + function test_CancelUpkeep_EmitEvent_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepCanceled(linkUpkeepID, uint64(bn + 50)); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_CancelUpkeep_EmitEvent_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + + vm.expectEmit(); + emit UpkeepCanceled(linkUpkeepID, uint64(bn)); + registry.cancelUpkeep(linkUpkeepID); + } +} + +contract SetPeerRegistryMigrationPermission is SetUp { + function test_SetPeerRegistryMigrationPermission_CalledByOwner() external { + address peer = randomAddress(); + vm.startPrank(registry.owner()); + + uint8 permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(0, permission); + + registry.setPeerRegistryMigrationPermission(peer, 1); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(1, permission); + + registry.setPeerRegistryMigrationPermission(peer, 2); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(2, permission); + + registry.setPeerRegistryMigrationPermission(peer, 0); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(0, permission); + } + + function test_RevertsWhen_InvalidPermission_CalledByOwner() external { + address peer = randomAddress(); + vm.startPrank(registry.owner()); + + vm.expectRevert(); + registry.setPeerRegistryMigrationPermission(peer, 100); + } + + function test_RevertsWhen_CalledByNonOwner() external { + address peer = randomAddress(); + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + registry.setPeerRegistryMigrationPermission(peer, 1); + } +} + +contract SetUpkeepPrivilegeConfig is SetUp { + function test_RevertsWhen_CalledByNonManager() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); + } + + function test_UpkeepHasEmptyConfig() external { + bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); + assertEq(cfg, bytes("")); + } + + function test_SetUpkeepPrivilegeConfig_CalledByManager() external { + vm.startPrank(PRIVILEGE_MANAGER); + + registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); + + bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); + assertEq(cfg, hex"1233"); + } +} + +contract SetAdminPrivilegeConfig is SetUp { + function test_RevertsWhen_CalledByNonManager() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setAdminPrivilegeConfig(randomAddress(), hex"1233"); + } + + function test_UpkeepHasEmptyConfig() external { + bytes memory cfg = registry.getAdminPrivilegeConfig(randomAddress()); + assertEq(cfg, bytes("")); + } + + function test_SetAdminPrivilegeConfig_CalledByManager() external { + vm.startPrank(PRIVILEGE_MANAGER); + address admin = randomAddress(); + + registry.setAdminPrivilegeConfig(admin, hex"1233"); + + bytes memory cfg = registry.getAdminPrivilegeConfig(admin); + assertEq(cfg, hex"1233"); + } +} + +contract TransferUpkeepAdmin is SetUp { + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + } + + function test_RevertsWhen_TransferToSelf() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.ValueNotChanged.selector); + registry.transferUpkeepAdmin(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_RevertsWhen_UpkeepCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + } + + function test_DoesNotChangeUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + + assertEq(registry.getUpkeep(linkUpkeepID).admin, UPKEEP_ADMIN); + } + + function test_EmitEvent_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + // transferring to the same propose admin won't yield another event + vm.recordLogs(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(0, entries.length); + } + + function test_CancelTransfer_ByTransferToEmptyAddress() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, address(0)); + registry.transferUpkeepAdmin(linkUpkeepID, address(0)); + } +} + +contract AcceptUpkeepAdmin is SetUp { + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByProposedAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByProposedAdmin.selector); + registry.acceptUpkeepAdmin(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(newAdmin); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.acceptUpkeepAdmin(linkUpkeepID); + } + + function test_UpkeepAdminChanged() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.startPrank(newAdmin); + vm.expectEmit(); + emit UpkeepAdminTransferred(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.acceptUpkeepAdmin(linkUpkeepID); + + assertEq(newAdmin, registry.getUpkeep(linkUpkeepID).admin); + } +} + +contract PauseUpkeep is SetUp { + event UpkeepPaused(uint256 indexed id); + + function test_RevertsWhen_NotCalledByUpkeepAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.pauseUpkeep(linkUpkeepID + 1); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyPaused() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.OnlyUnpausedUpkeep.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_EmitEvent_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepPaused(linkUpkeepID); + registry.pauseUpkeep(linkUpkeepID); + } +} + +contract UnpauseUpkeep is SetUp { + event UpkeepUnpaused(uint256 indexed id); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.unpauseUpkeep(linkUpkeepID + 1); + } + + function test_RevertsWhen_UpkeepIsNotPaused() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyPausedUpkeep.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_NotCalledByUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_UnpauseUpkeep_CalledByUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + uint256[] memory ids1 = registry.getActiveUpkeepIDs(0, 0); + + vm.expectEmit(); + emit UpkeepUnpaused(linkUpkeepID); + registry.unpauseUpkeep(linkUpkeepID); + + uint256[] memory ids2 = registry.getActiveUpkeepIDs(0, 0); + assertEq(ids1.length + 1, ids2.length); + } +} + +contract SetUpkeepCheckData is SetUp { + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepCheckData(linkUpkeepID + 1, hex"1234"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NewCheckDataTooLarge() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.CheckDataExceedsLimit.selector); + registry.setUpkeepCheckData(linkUpkeepID, new bytes(10_000)); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + } + + function test_UpdateOffchainConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); + } + + function test_UpdateOffchainConfigOnPausedUpkeep_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + registry.pauseUpkeep(linkUpkeepID); + + vm.expectEmit(); + emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + + assertTrue(registry.getUpkeep(linkUpkeepID).paused); + assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); + } +} + +contract SetUpkeepGasLimit is SetUp { + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepGasLimit(linkUpkeepID + 1, 1230000); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + } + + function test_RevertsWhen_NewGasLimitOutOfRange() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 300); + + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 3000000000); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + } + + function test_UpdateGasLimit_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepGasLimitSet(linkUpkeepID, 1230000); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + + assertEq(registry.getUpkeep(linkUpkeepID).performGas, 1230000); + } +} + +contract SetUpkeepOffchainConfig is SetUp { + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID + 1, hex"1233"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + } + + function test_UpdateOffchainConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepOffchainConfigSet(linkUpkeepID, hex"1234"); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeep(linkUpkeepID).offchainConfig, hex"1234"); + } +} + +contract SetUpkeepTriggerConfig is SetUp { + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID + 1, hex"1233"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + } + + function test_UpdateTriggerConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepTriggerConfigSet(linkUpkeepID, hex"1234"); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeepTriggerConfig(linkUpkeepID), hex"1234"); + } +} + +contract TransferPayeeship is SetUp { + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByPayee() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByPayee.selector); + registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); + } + + function test_RevertsWhen_TransferToSelf() external { + registry.setPayees(PAYEES); + vm.startPrank(PAYEES[0]); + + vm.expectRevert(Registry.ValueNotChanged.selector); + registry.transferPayeeship(TRANSMITTERS[0], PAYEES[0]); + } + + function test_Transfer_DoesNotChangePayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + + registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); + + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertEq(PAYEES[0], payee); + } + + function test_EmitEvent_CalledByPayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + + vm.expectEmit(); + emit PayeeshipTransferRequested(TRANSMITTERS[0], PAYEES[0], newPayee); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + // transferring to the same propose payee won't yield another event + vm.recordLogs(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(0, entries.length); + } +} + +contract AcceptPayeeship is SetUp { + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByProposedPayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByProposedPayee.selector); + registry.acceptPayeeship(TRANSMITTERS[0]); + } + + function test_PayeeChanged() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + vm.startPrank(newPayee); + vm.expectEmit(); + emit PayeeshipTransferred(TRANSMITTERS[0], PAYEES[0], newPayee); + registry.acceptPayeeship(TRANSMITTERS[0]); + + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertEq(newPayee, payee); + } +} + +contract SetPayees is SetUp { + event PayeesUpdated(address[] transmitters, address[] payees); + + function test_RevertsWhen_NotCalledByOwner() external { + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + registry.setPayees(NEW_PAYEES); + } + + function test_RevertsWhen_PayeesLengthError() external { + vm.startPrank(registry.owner()); + + address[] memory payees = new address[](5); + vm.expectRevert(Registry.ParameterLengthError.selector); + registry.setPayees(payees); + } + + function test_RevertsWhen_InvalidPayee() external { + vm.startPrank(registry.owner()); + + NEW_PAYEES[0] = address(0); + vm.expectRevert(Registry.InvalidPayee.selector); + registry.setPayees(NEW_PAYEES); + } + + function test_SetPayees_WhenExistingPayeesAreEmpty() external { + (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertEq(address(0), payee); + } + + vm.startPrank(registry.owner()); + + vm.expectEmit(); + emit PayeesUpdated(TRANSMITTERS, PAYEES); + registry.setPayees(PAYEES); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(PAYEES[i], payee); + } + } + + function test_DotNotSetPayeesToIgnoredAddress() external { + address IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + PAYEES[0] = IGNORE_ADDRESS; + + registry.setPayees(PAYEES); + (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertTrue(active); + assertEq(address(0), payee); + + (active, , , , payee) = registry.getTransmitterInfo(TRANSMITTERS[1]); + assertTrue(active); + assertEq(PAYEES[1], payee); + } +} + +contract GetActiveUpkeepIDs is SetUp { + function test_RevertsWhen_IndexOutOfRange() external { + vm.expectRevert(Registry.IndexOutOfRange.selector); + registry.getActiveUpkeepIDs(5, 0); + + vm.expectRevert(Registry.IndexOutOfRange.selector); + registry.getActiveUpkeepIDs(6, 0); + } + + function test_ReturnsAllUpkeeps_WhenMaxCountIsZero() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(0, 0); + assertEq(5, uids.length); + + uids = registry.getActiveUpkeepIDs(2, 0); + assertEq(3, uids.length); + } + + function test_ReturnsAllRemainingUpkeeps_WhenMaxCountIsTooLarge() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(2, 20); + assertEq(3, uids.length); + } + + function test_ReturnsUpkeeps_BoundByMaxCount() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(1, 2); + assertEq(2, uids.length); + assertEq(uids[0], linkUpkeepID2); + assertEq(uids[1], usdUpkeepID18); + } +} diff --git a/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol b/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol index a51f2d2af1a..8f7fa4643dd 100644 --- a/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol +++ b/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol @@ -31,6 +31,7 @@ contract LogUpkeepCounter is ILogAutomation { uint256 public previousPerformBlock; uint256 public initialBlock; uint256 public counter; + bool public autoExecution; constructor(uint256 _testRange) { testRange = _testRange; @@ -38,6 +39,7 @@ contract LogUpkeepCounter is ILogAutomation { lastBlock = block.number; initialBlock = 0; counter = 0; + autoExecution = true; } function start() public { @@ -65,16 +67,18 @@ contract LogUpkeepCounter is ILogAutomation { counter = counter + 1; previousPerformBlock = lastBlock; Log memory log = abi.decode(performData, (Log)); - if (log.topics[0] == sig1) { - emit Trigger(); - } else if (log.topics[0] == sig2) { - emit Trigger(1); - } else if (log.topics[0] == sig3) { - emit Trigger(1, 2); - } else if (log.topics[0] == sig4) { - emit Trigger(1, 2, 3); - } else { - revert("could not find matching sig"); + if (autoExecution) { + if (log.topics[0] == sig1) { + emit Trigger(); + } else if (log.topics[0] == sig2) { + emit Trigger(1); + } else if (log.topics[0] == sig3) { + emit Trigger(1, 2); + } else if (log.topics[0] == sig4) { + emit Trigger(1, 2, 3); + } else { + revert("could not find matching sig"); + } } emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter); } @@ -92,4 +96,8 @@ contract LogUpkeepCounter is ILogAutomation { initialBlock = 0; counter = 0; } + + function setAuto(bool _auto) external { + autoExecution = _auto; + } } diff --git a/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol b/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol new file mode 100644 index 00000000000..76b38776893 --- /dev/null +++ b/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +contract UpkeepCounterNew { + event PerformingUpkeep( + address indexed from, + uint256 initialTimestamp, + uint256 lastTimestamp, + uint256 previousBlock, + uint256 counter + ); + error InvalidCaller(address caller, address forwarder); + + uint256 public testRange; + uint256 public interval; + uint256 public lastTimestamp; + uint256 public previousPerformBlock; + uint256 public initialTimestamp; + uint256 public counter; + bool public useMoreCheckGas; + bool public useMorePerformGas; + bool public useMorePerformData; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + bytes public data; + bytes public dataCopy; + bool public trickSimulation = false; + address public forwarder; + + constructor() { + testRange = 1000000; + interval = 40; + previousPerformBlock = 0; + lastTimestamp = block.timestamp; + initialTimestamp = 0; + counter = 0; + useMoreCheckGas = false; + useMorePerformData = false; + useMorePerformGas = false; + checkGasToBurn = 9700000; + performGasToBurn = 7700000; + } + + function setPerformGasToBurn(uint256 _performGasToBurn) external { + performGasToBurn = _performGasToBurn; + } + + function setCheckGasToBurn(uint256 _checkGasToBurn) external { + checkGasToBurn = _checkGasToBurn; + } + + function setUseMoreCheckGas(bool _useMoreCheckGas) external { + useMoreCheckGas = _useMoreCheckGas; + } + + function setUseMorePerformGas(bool _useMorePerformGas) external { + useMorePerformGas = _useMorePerformGas; + } + + function setUseMorePerformData(bool _useMorePerformData) external { + useMorePerformData = _useMorePerformData; + } + + function setData(bytes calldata _data) external { + data = _data; + } + + function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) { + if (useMoreCheckGas) { + uint256 startGas = gasleft(); + while (startGas - gasleft() < checkGasToBurn) {} // burn gas + } + + if (useMorePerformData) { + return (eligible(), data); + } + return (eligible(), ""); + } + + function setTrickSimulation(bool _trickSimulation) external { + trickSimulation = _trickSimulation; + } + + function performUpkeep(bytes calldata performData) external { + if (trickSimulation && tx.origin == address(0)) { + return; + } + + if (msg.sender != forwarder) { + revert InvalidCaller(msg.sender, forwarder); + } + + if (useMorePerformGas) { + uint256 startGas = gasleft(); + while (startGas - gasleft() < performGasToBurn) {} // burn gas + } + + if (initialTimestamp == 0) { + initialTimestamp = block.timestamp; + } + lastTimestamp = block.timestamp; + counter = counter + 1; + dataCopy = performData; + emit PerformingUpkeep(tx.origin, initialTimestamp, lastTimestamp, previousPerformBlock, counter); + previousPerformBlock = lastTimestamp; + } + + function eligible() public view returns (bool) { + if (initialTimestamp == 0) { + return true; + } + + return (block.timestamp - initialTimestamp) < testRange && (block.timestamp - lastTimestamp) >= interval; + } + + function setSpread(uint256 _testRange, uint256 _interval) external { + testRange = _testRange; + interval = _interval; + initialTimestamp = 0; + counter = 0; + } + + function setForwarder(address _forwarder) external { + forwarder = _forwarder; + } +} diff --git a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol index 824bce711bf..9bf68fce038 100644 --- a/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol +++ b/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol @@ -72,7 +72,7 @@ contract LinkAvailableBalanceMonitor is AccessControl, AutomationCompatibleInter bytes32 private constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 private constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); - uint96 private constant DEFAULT_TOP_UP_AMOUNT_JUELS = 9000000000000000000; + uint96 private constant DEFAULT_TOP_UP_AMOUNT_JUELS = 3000000000000000000; uint96 private constant DEFAULT_MIN_BALANCE_JUELS = 1000000000000000000; IERC20 private immutable i_linkToken; diff --git a/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol b/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol index f0c703679ca..464e8746398 100644 --- a/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol +++ b/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol @@ -115,7 +115,7 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain }); uint256 blocknumber = hotVars.chainModule.blockNumber(); - uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(); + uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); for (uint256 i = 0; i < report.upkeepIds.length; i++) { upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]]; 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 6113cbf9fd1..031d7b5dfb8 100644 --- a/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol @@ -136,7 +136,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain }); uint256 blocknumber = hotVars.chainModule.blockNumber(); - uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(); + uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); for (uint256 i = 0; i < report.upkeepIds.length; i++) { upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]]; 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 fa8f06ffc02..354a6a9b475 100644 --- a/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol @@ -45,7 +45,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // These values are calibrated using hardhat tests which simulate various cases and verify that // the variables result in accurate estimation uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps - uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_500; // Fixed gas overhead for log upkeeps + uint256 internal constant REGISTRY_LOG_OVERHEAD = 123_500; // Fixed gas overhead for log upkeeps uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead 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 027fe59aca7..5d5bf23aa26 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 @@ -72,7 +72,6 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs uint16 numUpkeepsPassedChecks; uint96 totalReimbursement; uint96 totalPremium; - uint256 totalCalldataWeight; } // ================================================================ @@ -89,7 +88,6 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs bytes32[] calldata ss, bytes32 rawVs ) external override { - uint256 gasOverhead = gasleft(); // use this msg.data length check to ensure no extra data is included in the call // 4 is first 4 bytes of the keccak-256 hash of the function signature. ss.length == rs.length so use one of them // 4 + (32 * 3) + (rawReport.length + 32 + 32) + (32 * rs.length + 32 + 32) + (32 * ss.length + 32 + 32) + 32 @@ -110,7 +108,7 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs uint40 epochAndRound = uint40(uint256(reportContext[1])); uint32 epoch = uint32(epochAndRound >> 8); - _handleReport(hotVars, report, gasOverhead); + _handleReport(hotVars, report); if (epoch > hotVars.latestEpoch) { s_hotVars.latestEpoch = epoch; @@ -121,22 +119,20 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs * @notice handles the report by performing the upkeeps and updating the state * @param hotVars the hot variables of the registry * @param report the report to be handled (already verified and decoded) - * @param gasOverhead the running tally of gas overhead to be split across the upkeeps * @dev had to split this function from transmit() to avoid stack too deep errors * @dev all other internal / private functions are generally defined in the Base contract * we leave this here because it is essentially a continuation of the transmit() function, */ - function _handleReport(HotVars memory hotVars, Report memory report, uint256 gasOverhead) private { + function _handleReport(HotVars memory hotVars, Report memory report) private { UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); TransmitVars memory transmitVars = TransmitVars({ numUpkeepsPassedChecks: 0, - totalCalldataWeight: 0, totalReimbursement: 0, totalPremium: 0 }); uint256 blocknumber = hotVars.chainModule.blockNumber(); - uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(); + uint256 gasOverhead; for (uint256 i = 0; i < report.upkeepIds.length; i++) { upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]]; @@ -163,28 +159,27 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs report.performDatas[i] ); - // To split L1 fee across the upkeeps, assign a weight to this upkeep based on the length - // of the perform data and calldata overhead - upkeepTransmitInfo[i].calldataWeight = - report.performDatas[i].length + - TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD + - (TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1)); - transmitVars.totalCalldataWeight += upkeepTransmitInfo[i].calldataWeight; - - // Deduct the gasUsed by upkeep from the overhead tally - upkeeps pay for their own gas individually - gasOverhead -= upkeepTransmitInfo[i].gasUsed; - // Store last perform block number / deduping key for upkeep _updateTriggerMarker(report.upkeepIds[i], blocknumber, upkeepTransmitInfo[i]); + + if (upkeepTransmitInfo[i].triggerType == Trigger.CONDITION) { + gasOverhead += REGISTRY_CONDITIONAL_OVERHEAD; + } else if (upkeepTransmitInfo[i].triggerType == Trigger.LOG) { + gasOverhead += REGISTRY_LOG_OVERHEAD; + } else { + revert InvalidTriggerType(); + } } // No upkeeps to be performed in this report if (transmitVars.numUpkeepsPassedChecks == 0) { return; } - // This is the overall gas overhead that will be split across performed upkeeps - // Take upper bound of 16 gas per callData bytes - gasOverhead = (gasOverhead - gasleft()) + (16 * msg.data.length) + ACCOUNTING_FIXED_GAS_OVERHEAD; + gasOverhead += + 16 * + msg.data.length + + ACCOUNTING_FIXED_GAS_OVERHEAD + + (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; { @@ -200,7 +195,7 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs PaymentParams({ gasLimit: upkeepTransmitInfo[i].gasUsed, gasOverhead: gasOverhead, - l1CostWei: (l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight, + l1CostWei: 0, fastGasWei: report.fastGasWei, linkUSD: report.linkUSD, nativeUSD: nativeUSD, diff --git a/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol index 524ecacc826..41097af7f26 100644 --- a/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol @@ -34,8 +34,6 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; uint256 internal constant PERFORM_GAS_MIN = 2_300; uint256 internal constant CANCELLATION_DELAY = 50; - uint256 internal constant PERFORM_GAS_CUSHION = 5_000; - uint256 internal constant PPB_BASE = 1_000_000_000; uint32 internal constant UINT32_MAX = type(uint32).max; // The first byte of the mask can be 0, because we only ever have 31 oracles uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; @@ -47,20 +45,13 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_500; // Fixed gas overhead for log upkeeps uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f - uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead - - // The overhead (in bytes) in addition to perform data for upkeep sent in calldata - // This includes overhead for all struct encoding as well as report signatures - // There is a fixed component and a per signer component. This is calculated exactly by doing abi encoding - uint256 internal constant TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD = 932; - uint256 internal constant TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD = 64; // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the // 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 = 20_000; // Overhead per upkeep performed in batch LinkTokenInterface internal immutable i_link; AggregatorV3Interface internal immutable i_linkUSDFeed; @@ -313,7 +304,6 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { * @member performSuccess whether the perform was successful * @member triggerType the type of trigger * @member gasUsed gasUsed by this upkeep in perform - * @member calldataWeight weight assigned to this upkeep for its contribution to calldata. It is used to split L1 fee * @member dedupID unique ID used to dedup an upkeep/trigger combo */ struct UpkeepTransmitInfo { @@ -322,7 +312,6 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { bool performSuccess; Trigger triggerType; uint256 gasUsed; - uint256 calldataWeight; bytes32 dedupID; } @@ -739,7 +728,6 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { uint256 nativeUSD, IERC20 billingToken ) internal view returns (uint96) { - uint256 maxL1Fee; uint256 maxGasOverhead; { @@ -750,15 +738,8 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { } else { revert InvalidTriggerType(); } - uint256 maxCalldataSize = s_storage.maxPerformDataSize + - TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD + - (TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1)); - (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) = s_hotVars.chainModule.getGasOverhead(); - maxGasOverhead += - (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + - ((REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD + chainModulePerByteOverhead) * maxCalldataSize) + - chainModuleFixedOverhead; - maxL1Fee = hotVars.gasCeilingMultiplier * hotVars.chainModule.getMaxL1Fee(maxCalldataSize); + (uint256 chainModuleFixedOverhead, ) = s_hotVars.chainModule.getGasOverhead(); + maxGasOverhead += (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + chainModuleFixedOverhead; } BillingTokenPaymentParams memory paymentParams = _getBillingTokenPaymentParams(hotVars, billingToken); @@ -774,7 +755,7 @@ abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { PaymentParams({ gasLimit: performGas, gasOverhead: maxGasOverhead, - l1CostWei: maxL1Fee, + l1CostWei: 0, fastGasWei: fastGasWei, linkUSD: linkUSD, nativeUSD: nativeUSD, diff --git a/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol index 61d0eecfbaf..3b4b023c7a2 100644 --- a/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol @@ -222,22 +222,10 @@ contract ZKSyncAutomationRegistryLogicC2_3 is ZKSyncAutomationRegistryBase2_3 { return REGISTRY_LOG_OVERHEAD; } - function getPerPerformByteGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; - } - function getPerSignerGasOverhead() external pure returns (uint256) { return REGISTRY_PER_SIGNER_GAS_OVERHEAD; } - function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256) { - return TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD; - } - - function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256) { - return TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD; - } - function getCancellationDelay() external pure returns (uint256) { return CANCELLATION_DELAY; } diff --git a/contracts/src/v0.8/ccip/AggregateRateLimiter.sol b/contracts/src/v0.8/ccip/AggregateRateLimiter.sol deleted file mode 100644 index 7401df2ed49..00000000000 --- a/contracts/src/v0.8/ccip/AggregateRateLimiter.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; - -import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; -import {Client} from "./libraries/Client.sol"; -import {RateLimiter} from "./libraries/RateLimiter.sol"; -import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; - -/// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter -/// which permits rate limiting based on the aggregate value of a group of -/// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). -contract AggregateRateLimiter is OwnerIsCreator { - using RateLimiter for RateLimiter.TokenBucket; - using USDPriceWith18Decimals for uint224; - - error PriceNotFoundForToken(address token); - - event AdminSet(address newAdmin); - - // The address of the token limit admin that has the same permissions as the owner. - address internal s_admin; - - // The token bucket object that contains the bucket state. - RateLimiter.TokenBucket private s_rateLimiter; - - /// @param config The RateLimiter.Config - constructor(RateLimiter.Config memory config) { - s_rateLimiter = RateLimiter.TokenBucket({ - rate: config.rate, - capacity: config.capacity, - tokens: config.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: config.isEnabled - }); - } - - /// @notice Consumes value from the rate limiter bucket based on the token value given. - function _rateLimitValue(uint256 value) internal { - s_rateLimiter._consume(value, address(0)); - } - - function _getTokenValue( - Client.EVMTokenAmount memory tokenAmount, - IPriceRegistry priceRegistry - ) internal view returns (uint256) { - // not fetching validated price, as price staleness is not important for value-based rate limiting - // we only need to verify the price is not 0 - uint224 pricePerToken = priceRegistry.getTokenPrice(tokenAmount.token).value; - if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); - return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function currentRateLimiterState() external view returns (RateLimiter.TokenBucket memory) { - return s_rateLimiter._currentTokenBucketState(); - } - - /// @notice Sets the rate limited config. - /// @param config The new rate limiter config. - /// @dev should only be callable by the owner or token limit admin. - function setRateLimiterConfig(RateLimiter.Config memory config) external onlyAdminOrOwner { - s_rateLimiter._setTokenBucketConfig(config); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Gets the token limit admin address. - /// @return the token limit admin address. - function getTokenLimitAdmin() external view returns (address) { - return s_admin; - } - - /// @notice Sets the token limit admin address. - /// @param newAdmin the address of the new admin. - /// @dev setting this to address(0) indicates there is no active admin. - function setAdmin(address newAdmin) external onlyAdminOrOwner { - s_admin = newAdmin; - emit AdminSet(newAdmin); - } - - /// @notice a modifier that allows the owner or the s_tokenLimitAdmin call the functions - /// it is applied to. - modifier onlyAdminOrOwner() { - if (msg.sender != owner() && msg.sender != s_admin) revert RateLimiter.OnlyCallableByAdminOrOwner(); - _; - } -} diff --git a/contracts/src/v0.8/ccip/CommitStore.sol b/contracts/src/v0.8/ccip/CommitStore.sol deleted file mode 100644 index 27388b6dcc2..00000000000 --- a/contracts/src/v0.8/ccip/CommitStore.sol +++ /dev/null @@ -1,314 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {ICommitStore} from "./interfaces/ICommitStore.sol"; -import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; -import {IRMN} from "./interfaces/IRMN.sol"; - -import {Internal} from "./libraries/Internal.sol"; -import {MerkleMultiProof} from "./libraries/MerkleMultiProof.sol"; -import {OCR2Base} from "./ocr/OCR2Base.sol"; - -contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base { - error StaleReport(); - error PausedError(); - error InvalidInterval(Interval interval); - error InvalidRoot(); - error InvalidCommitStoreConfig(); - error CursedByRMN(); - error RootAlreadyCommitted(); - - event Paused(address account); - event Unpaused(address account); - /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. - event ReportAccepted(CommitReport report); - event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); - event RootRemoved(bytes32 root); - event SequenceNumberSet(uint64 oldSeqNum, uint64 newSeqNum); - event LatestPriceEpochAndRoundSet(uint40 oldEpochAndRound, uint40 newEpochAndRound); - - /// @notice Static commit store config - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - //solhint-disable gas-struct-packing - struct StaticConfig { - uint64 chainSelector; // ───────╮ Destination chainSelector - uint64 sourceChainSelector; // ─╯ Source chainSelector - address onRamp; // OnRamp address on the source chain - address rmnProxy; // RMN proxy address - } - - /// @notice Dynamic commit store config - struct DynamicConfig { - address priceRegistry; // Price registry address on the destination chain - } - - /// @notice a sequenceNumber interval - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct Interval { - uint64 min; // ───╮ Minimum sequence number, inclusive - uint64 max; // ───╯ Maximum sequence number, inclusive - } - - /// @notice Report that is committed by the observing DON at the committing phase - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct CommitReport { - Internal.PriceUpdates priceUpdates; - Interval interval; - bytes32 merkleRoot; - } - - // STATIC CONFIG - string public constant override typeAndVersion = "CommitStore 1.5.0-dev"; - // Chain ID of this chain - uint64 internal immutable i_chainSelector; - // Chain ID of the source chain - uint64 internal immutable i_sourceChainSelector; - // The onRamp address on the source chain - address internal immutable i_onRamp; - // The address of the rmn proxy - address internal immutable i_rmnProxy; - - // DYNAMIC CONFIG - // The dynamic commitStore config - DynamicConfig internal s_dynamicConfig; - - // STATE - // The min sequence number expected for future messages - uint64 private s_minSeqNr = 1; - /// @dev The epoch and round of the last report - uint40 private s_latestPriceEpochAndRound; - /// @dev Whether this CommitStore is paused or not - bool private s_paused = false; - // merkleRoot => timestamp when received - mapping(bytes32 merkleRoot => uint256 timestamp) private s_roots; - - /// @param staticConfig Containing the static part of the commitStore config - /// @dev When instantiating OCR2Base we set UNIQUE_REPORTS to false, which means - /// that we do not require 2f+1 signatures on a report, only f+1 to save gas. 2f+1 is required - /// only if one must strictly ensure that for a given round there is only one valid report ever generated by - /// the DON. In our case additional valid reports (i.e. approved by >= f+1 oracles) are not a problem, as they will - /// will either be ignored (reverted as an invalid interval) or will be accepted as an additional valid price update. - constructor(StaticConfig memory staticConfig) OCR2Base(false) { - if ( - staticConfig.onRamp == address(0) || staticConfig.chainSelector == 0 || staticConfig.sourceChainSelector == 0 - || staticConfig.rmnProxy == address(0) - ) revert InvalidCommitStoreConfig(); - - i_chainSelector = staticConfig.chainSelector; - i_sourceChainSelector = staticConfig.sourceChainSelector; - i_onRamp = staticConfig.onRamp; - i_rmnProxy = staticConfig.rmnProxy; - } - - // ================================================================ - // │ Verification │ - // ================================================================ - - /// @notice Returns the next expected sequence number. - /// @return the next expected sequenceNumber. - function getExpectedNextSequenceNumber() external view returns (uint64) { - return s_minSeqNr; - } - - /// @notice Sets the minimum sequence number. - /// @param minSeqNr The new minimum sequence number. - function setMinSeqNr(uint64 minSeqNr) external onlyOwner { - uint64 oldSeqNum = s_minSeqNr; - - s_minSeqNr = minSeqNr; - - emit SequenceNumberSet(oldSeqNum, minSeqNr); - } - - /// @notice Returns the epoch and round of the last price update. - /// @return the latest price epoch and round. - function getLatestPriceEpochAndRound() external view returns (uint64) { - return s_latestPriceEpochAndRound; - } - - /// @notice Sets the latest epoch and round for price update. - /// @param latestPriceEpochAndRound The new epoch and round for prices. - function setLatestPriceEpochAndRound(uint40 latestPriceEpochAndRound) external onlyOwner { - uint40 oldEpochAndRound = s_latestPriceEpochAndRound; - - s_latestPriceEpochAndRound = latestPriceEpochAndRound; - - emit LatestPriceEpochAndRoundSet(oldEpochAndRound, latestPriceEpochAndRound); - } - - /// @notice Returns the timestamp of a potentially previously committed merkle root. - /// If the root was never committed 0 will be returned. - /// @param root The merkle root to check the commit status for. - /// @return the timestamp of the committed root or zero in the case that it was never - /// committed. - function getMerkleRoot(bytes32 root) external view returns (uint256) { - return s_roots[root]; - } - - /// @notice Returns if a root is blessed or not. - /// @param root The merkle root to check the blessing status for. - /// @return whether the root is blessed or not. - function isBlessed(bytes32 root) public view returns (bool) { - return IRMN(i_rmnProxy).isBlessed(IRMN.TaggedRoot({commitStore: address(this), root: root})); - } - - /// @notice Used by the owner in case an invalid sequence of roots has been - /// posted and needs to be removed. The interval in the report is trusted. - /// @param rootToReset The roots that will be reset. This function will only - /// reset roots that are not blessed. - function resetUnblessedRoots(bytes32[] calldata rootToReset) external onlyOwner { - for (uint256 i = 0; i < rootToReset.length; ++i) { - bytes32 root = rootToReset[i]; - if (!isBlessed(root)) { - delete s_roots[root]; - emit RootRemoved(root); - } - } - } - - /// @inheritdoc ICommitStore - function verify( - bytes32[] calldata hashedLeaves, - bytes32[] calldata proofs, - uint256 proofFlagBits - ) external view override whenNotPaused returns (uint256 timestamp) { - bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits); - // Only return non-zero if present and blessed. - if (!isBlessed(root)) { - return 0; - } - return s_roots[root]; - } - - /// @inheritdoc OCR2Base - /// @dev A commitReport can have two distinct parts (batched together to amortize the cost of checking sigs): - /// 1. Price updates - /// 2. A merkle root and sequence number interval - /// Both have their own, separate, staleness checks, with price updates using the epoch and round - /// number of the latest price update. The merkle root checks for staleness based on the seqNums. - /// They need to be separate because a price report for round t+2 might be included before a report - /// containing a merkle root for round t+1. This merkle root report for round t+1 is still valid - /// and should not be rejected. When a report with a stale root but valid price updates is submitted, - /// we are OK to revert to preserve the invariant that we always revert on invalid sequence number ranges. - /// If that happens, prices will be updates in later rounds. - function _report(bytes calldata encodedReport, uint40 epochAndRound) internal override whenNotPaused { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(i_sourceChainSelector)))) revert CursedByRMN(); - - CommitReport memory report = abi.decode(encodedReport, (CommitReport)); - - // Check if the report contains price updates - if (report.priceUpdates.tokenPriceUpdates.length > 0 || report.priceUpdates.gasPriceUpdates.length > 0) { - // Check for price staleness based on the epoch and round - if (s_latestPriceEpochAndRound < epochAndRound) { - // If prices are not stale, update the latest epoch and round - s_latestPriceEpochAndRound = epochAndRound; - // And update the prices in the price registry - IPriceRegistry(s_dynamicConfig.priceRegistry).updatePrices(report.priceUpdates); - - // If there is no root, the report only contained fee updated and - // we return to not revert on the empty root check below. - if (report.merkleRoot == bytes32(0)) return; - } else { - // If prices are stale and the report doesn't contain a root, this report - // does not have any valid information and we revert. - // If it does contain a merkle root, continue to the root checking section. - if (report.merkleRoot == bytes32(0)) revert StaleReport(); - } - } - - // If we reached this section, the report should contain a valid root - if (s_minSeqNr != report.interval.min || report.interval.min > report.interval.max) { - revert InvalidInterval(report.interval); - } - - if (report.merkleRoot == bytes32(0)) revert InvalidRoot(); - // Disallow duplicate roots as that would reset the timestamp and - // delay potential manual execution. - if (s_roots[report.merkleRoot] != 0) revert RootAlreadyCommitted(); - - s_minSeqNr = report.interval.max + 1; - s_roots[report.merkleRoot] = block.timestamp; - emit ReportAccepted(report); - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Returns the static commit store config. - /// @dev RMN depends on this function, if changing, please notify the RMN maintainers. - /// @return the configuration. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - chainSelector: i_chainSelector, - sourceChainSelector: i_sourceChainSelector, - onRamp: i_onRamp, - rmnProxy: i_rmnProxy - }); - } - - /// @notice Returns the dynamic commit store config. - /// @return the configuration. - function getDynamicConfig() external view returns (DynamicConfig memory) { - return s_dynamicConfig; - } - - /// @notice Sets the dynamic config. This function is called during `setOCR2Config` flow - function _beforeSetConfig(bytes memory onchainConfig) internal override { - DynamicConfig memory dynamicConfig = abi.decode(onchainConfig, (DynamicConfig)); - - if (dynamicConfig.priceRegistry == address(0)) revert InvalidCommitStoreConfig(); - - s_dynamicConfig = dynamicConfig; - // When the OCR config changes, we reset the price epoch and round - // since epoch and rounds are scoped per config digest. - // Note that s_minSeqNr/roots do not need to be reset as the roots persist - // across reconfigurations and are de-duplicated separately. - s_latestPriceEpochAndRound = 0; - - emit ConfigSet( - StaticConfig({ - chainSelector: i_chainSelector, - sourceChainSelector: i_sourceChainSelector, - onRamp: i_onRamp, - rmnProxy: i_rmnProxy - }), - dynamicConfig - ); - } - - // ================================================================ - // │ Access and RMN │ - // ================================================================ - - /// @notice Single function to check the status of the commitStore. - function isUnpausedAndNotCursed() external view returns (bool) { - return !IRMN(i_rmnProxy).isCursed(bytes16(uint128(i_sourceChainSelector))) && !s_paused; - } - - /// @notice Modifier to make a function callable only when the contract is not paused. - modifier whenNotPaused() { - if (paused()) revert PausedError(); - _; - } - - /// @notice Returns true if the contract is paused, and false otherwise. - function paused() public view returns (bool) { - return s_paused; - } - - /// @notice Pause the contract - /// @dev only callable by the owner - function pause() external onlyOwner { - s_paused = true; - emit Paused(msg.sender); - } - - /// @notice Unpause the contract - /// @dev only callable by the owner - function unpause() external onlyOwner { - s_paused = false; - emit Unpaused(msg.sender); - } -} diff --git a/contracts/src/v0.8/ccip/PriceRegistry.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol similarity index 67% rename from contracts/src/v0.8/ccip/PriceRegistry.sol rename to contracts/src/v0.8/ccip/FeeQuoter.sol index f15232271e9..66f63c7c720 100644 --- a/contracts/src/v0.8/ccip/PriceRegistry.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -1,9 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IReceiver} from "../keystone/interfaces/IReceiver.sol"; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; +import {KeystoneFeedsPermissionHandler} from "../keystone/KeystoneFeedsPermissionHandler.sol"; +import {KeystoneFeedDefaultMetadataLib} from "../keystone/lib/KeystoneFeedDefaultMetadataLib.sol"; import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; import {AggregatorV3Interface} from "./../shared/interfaces/AggregatorV3Interface.sol"; import {Client} from "./libraries/Client.sol"; @@ -11,33 +15,22 @@ import {Internal} from "./libraries/Internal.sol"; import {Pool} from "./libraries/Pool.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; -import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; -/// @notice The PriceRegistry contract responsibility is to store the current gas price in USD for a given destination chain, -/// and the price of a token in USD allowing the owner or priceUpdater to update this value. +/// @notice The FeeQuoter contract responsibility is to: +/// - Store the current gas price in USD for a given destination chain, +/// - Store the price of a token in USD allowing the owner or priceUpdater to update this value. +/// - Manage chain specific fee calculations. /// The authorized callers in the contract represent the fee price updaters. -contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { +contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, KeystoneFeedsPermissionHandler { using EnumerableSet for EnumerableSet.AddressSet; using USDPriceWith18Decimals for uint224; - - /// @notice Token price data feed update - struct TokenPriceFeedUpdate { - address sourceToken; // Source token to update feed for - IPriceRegistry.TokenPriceFeedConfig feedConfig; // Feed config update data - } - - /// @dev Struct that contains the static configuration - /// RMN depends on this struct, if changing, please notify the RMN maintainers. - // solhint-disable-next-line gas-struct-packing - struct StaticConfig { - uint96 maxFeeJuelsPerMsg; // ─╮ Maximum fee that can be charged for a message - address linkToken; // ────────╯ LINK token address - uint32 stalenessThreshold; // The amount of time a gas price can be stale before it is considered invalid. - } + using KeystoneFeedDefaultMetadataLib for bytes; error TokenNotSupported(address token); - error ChainNotSupported(uint64 chain); + error FeeTokenNotSupported(address token); error StaleGasPrice(uint64 destChainSelector, uint256 threshold, uint256 timePassed); + error StaleKeystoneUpdate(address token, uint256 feedTimestamp, uint256 storedTimeStamp); error DataFeedValueOutOfUint224Range(); error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); error MessageGasLimitTooHigh(); @@ -51,14 +44,11 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { error MessageTooLarge(uint256 maxSize, uint256 actualSize); error UnsupportedNumberOfTokens(); - event PriceUpdaterSet(address indexed priceUpdater); - event PriceUpdaterRemoved(address indexed priceUpdater); event FeeTokenAdded(address indexed feeToken); event FeeTokenRemoved(address indexed feeToken); event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp); event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp); - event PriceFeedPerTokenUpdated(address indexed token, IPriceRegistry.TokenPriceFeedConfig priceFeedConfig); - + event PriceFeedPerTokenUpdated(address indexed token, TokenPriceFeedConfig priceFeedConfig); event TokenTransferFeeConfigUpdated( uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig ); @@ -67,6 +57,35 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { event DestChainConfigUpdated(uint64 indexed destChainSelector, DestChainConfig destChainConfig); event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + /// @dev Token price data feed configuration + struct TokenPriceFeedConfig { + address dataFeedAddress; // ─╮ AggregatorV3Interface contract (0 - feed is unset) + uint8 tokenDecimals; // ─────╯ Decimals of the token that the feed represents + } + + /// @dev Token price data feed update + struct TokenPriceFeedUpdate { + address sourceToken; // Source token to update feed for + TokenPriceFeedConfig feedConfig; // Feed config update data + } + + /// @dev Struct that contains the static configuration + /// RMN depends on this struct, if changing, please notify the RMN maintainers. + // solhint-disable-next-line gas-struct-packing + struct StaticConfig { + uint96 maxFeeJuelsPerMsg; // ─╮ Maximum fee that can be charged for a message + address linkToken; // ────────╯ LINK token address + // The amount of time a token price can be stale before it is considered invalid (gas price staleness is configured per dest chain) + uint32 tokenPriceStalenessThreshold; + } + + /// @dev The struct representing the received CCIP feed report from keystone IReceiver.onReport() + struct ReceivedCCIPFeedReport { + address token; // Token address + uint224 price; // ────╮ Price of the token in USD with 18 decimals + uint32 timestamp; // ─╯ Timestamp of the price update + } + /// @dev Struct to hold the fee & validation configs for a destination chain struct DestChainConfig { bool isEnabled; // ──────────────────────────╮ Whether this destination chain is enabled @@ -75,16 +94,16 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { 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 for passing each byte of `data` payload to receiver - uint32 destDataAvailabilityOverheadGas; // | Extra data availability gas charged on top of the message, e.g. for OCR - uint16 destGasPerDataAvailabilityByte; // | Amount of gas to charge per byte of message data that needs availability + uint32 destDataAvailabilityOverheadGas; // │ Extra data availability gas charged on top of the message, e.g. for OCR + uint16 destGasPerDataAvailabilityByte; // │ Amount of gas to charge per byte of message data that needs availability uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 // 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 the token transfer on the destination chain - uint32 defaultTokenDestBytesOverhead; // ────╮ Default extra data availability bytes charged per token transfer - uint32 defaultTxGasLimit; // │ Default gas limit for a tx + 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 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. } @@ -100,20 +119,20 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// @dev Struct to hold the transfer fee configuration for token transfers struct TokenTransferFeeConfig { - uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD - uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD - uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 - uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain - // │ Extra data availability bytes that are returned from the source pool and sent - uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees + uint32 minFeeUSDCents; // ────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD + uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD + uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 + uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain + // │ Extra data availability bytes that are returned from the source pool and sent + uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + bool isEnabled; // ───────────╯ Whether this token has custom transfer fees } /// @dev Struct to hold the token transfer fee configurations for a token, same as TokenTransferFeeConfig but with the token address included so /// that an array of these can be passed in the TokenTransferFeeConfigArgs struct to set the mapping struct TokenTransferFeeConfigSingleTokenArgs { address token; // Token address - TokenTransferFeeConfig tokenTransferFeeConfig; // struct to hold the transfer fee configuration for token transfers + TokenTransferFeeConfig tokenTransferFeeConfig; // Struct to hold the transfer fee configuration for token transfers } /// @dev Struct to hold the token transfer fee configurations for a destination chain and a set of tokens. Same as TokenTransferFeeConfigSingleTokenArgs @@ -135,11 +154,16 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// the token address included so that an array of these can be passed in the constructor and /// applyPremiumMultiplierWeiPerEthUpdates to set the mapping struct PremiumMultiplierWeiPerEthArgs { - address token; // // ───────────────────╮ Token address - uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. Should never be 0 so can be used as an isEnabled flag + address token; // // ──────────────────╮ Token address + uint64 premiumMultiplierWeiPerEth; // ─╯ Multiplier for destination chain specific premiums. } - string public constant override typeAndVersion = "PriceRegistry 1.6.0-dev"; + /// @dev The base decimals for cost calculations + uint256 public constant FEE_BASE_DECIMALS = 36; + /// @dev The decimals that Keystone reports prices in + uint256 public constant KEYSTONE_PRICE_DECIMALS = 18; + + string public constant override typeAndVersion = "FeeQuoter 1.6.0-dev"; /// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals. /// Multiple gas prices can be encoded into the same value. Each price takes {Internal.GAS_PRICE_BITS} bits. @@ -160,30 +184,27 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { mapping(address token => Internal.TimestampedPackedUint224 price) private s_usdPerToken; /// @dev Stores the price data feed configurations per token. - mapping(address token => IPriceRegistry.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; + mapping(address token => TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin - /// This should never be 0 once set, so it can be used as an isEnabled flag - mapping(address token => uint64 premiumMultiplierWeiPerEth) internal s_premiumMultiplierWeiPerEth; + mapping(address token => uint64 premiumMultiplierWeiPerEth) private s_premiumMultiplierWeiPerEth; /// @dev The destination chain specific fee configs mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfigs; /// @dev The token transfer fee config that can be set by the owner or fee admin - mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) internal + mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) private s_tokenTransferFeeConfig; - /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguation. + /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguration. uint96 internal immutable i_maxFeeJuelsPerMsg; /// @dev The link token address address internal immutable i_linkToken; - // Price updaters are allowed to update the prices. - EnumerableSet.AddressSet private s_priceUpdaters; - // Subset of tokens which prices tracked by this registry which are fee tokens. + /// @dev Subset of tokens which prices tracked by this registry which are fee tokens. EnumerableSet.AddressSet private s_feeTokens; - // The amount of time a gas price can be stale before it is considered invalid. - uint32 private immutable i_stalenessThreshold; + /// @dev The amount of time a token price can be stale before it is considered invalid. + uint32 private immutable i_tokenPriceStalenessThreshold; constructor( StaticConfig memory staticConfig, @@ -196,16 +217,16 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { ) AuthorizedCallers(priceUpdaters) { if ( staticConfig.linkToken == address(0) || staticConfig.maxFeeJuelsPerMsg == 0 - || staticConfig.stalenessThreshold == 0 + || staticConfig.tokenPriceStalenessThreshold == 0 ) { revert InvalidStaticConfig(); } i_linkToken = staticConfig.linkToken; i_maxFeeJuelsPerMsg = staticConfig.maxFeeJuelsPerMsg; - i_stalenessThreshold = staticConfig.stalenessThreshold; + i_tokenPriceStalenessThreshold = staticConfig.tokenPriceStalenessThreshold; - _applyFeeTokensUpdates(feeTokens, new address[](0)); + _applyFeeTokensUpdates(new address[](0), feeTokens); _updateTokenPriceFeeds(tokenPriceFeeds); _applyDestChainConfigUpdates(destChainConfigArgs); _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); @@ -217,27 +238,44 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // ================================================================ /// @inheritdoc IPriceRegistry - function getTokenPrice(address token) public view override returns (Internal.TimestampedPackedUint224 memory) { - IPriceRegistry.TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; + function getTokenPrice( + address token + ) public view override returns (Internal.TimestampedPackedUint224 memory) { + Internal.TimestampedPackedUint224 memory tokenPrice = s_usdPerToken[token]; + + // If the token price is not stale, return it + if (block.timestamp - tokenPrice.timestamp < i_tokenPriceStalenessThreshold) { + return tokenPrice; + } + + TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; + + // If the token price feed is not set, return the stale price if (priceFeedConfig.dataFeedAddress == address(0)) { - return s_usdPerToken[token]; + return tokenPrice; } - return _getTokenPriceFromDataFeed(priceFeedConfig); + // If the token price feed is set, retrieve the price from the feed + Internal.TimestampedPackedUint224 memory feedPrice = _getTokenPriceFromDataFeed(priceFeedConfig); + + return feedPrice.timestamp >= tokenPrice.timestamp ? feedPrice : tokenPrice; } - /// @inheritdoc IPriceRegistry - function getValidatedTokenPrice(address token) external view override returns (uint224) { + /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. + /// @param token The token to get the price for. + /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. + function getValidatedTokenPrice( + address token + ) external view returns (uint224) { return _getValidatedTokenPrice(token); } - /// @inheritdoc IPriceRegistry - function getTokenPrices(address[] calldata tokens) - external - view - override - returns (Internal.TimestampedPackedUint224[] memory) - { + /// @notice Get the `tokenPrice` for an array of tokens. + /// @param tokens The tokens to get prices for. + /// @return tokenPrices The tokenPrices for the given tokens. + function getTokenPrices( + address[] calldata tokens + ) external view returns (Internal.TimestampedPackedUint224[] memory) { uint256 length = tokens.length; Internal.TimestampedPackedUint224[] memory tokenPrices = new Internal.TimestampedPackedUint224[](length); for (uint256 i = 0; i < length; ++i) { @@ -246,49 +284,58 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { return tokenPrices; } - /// @inheritdoc IPriceRegistry - function getTokenPriceFeedConfig(address token) - external - view - override - returns (IPriceRegistry.TokenPriceFeedConfig memory) - { + /// @notice Returns the token price data feed configuration + /// @param token The token to retrieve the feed config for + /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) + function getTokenPriceFeedConfig( + address token + ) external view returns (TokenPriceFeedConfig memory) { return s_usdPriceFeedsPerToken[token]; } - /// @inheritdoc IPriceRegistry - function getDestinationChainGasPrice(uint64 destChainSelector) - external - view - override - returns (Internal.TimestampedPackedUint224 memory) - { + /// @notice Get an encoded `gasPrice` for a given destination chain ID. + /// The 224-bit result encodes necessary gas price components. + /// On L1 chains like Ethereum or Avax, the only component is the gas price. + /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. + /// On future chains, there could be more or differing price components. + /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. + /// @param destChainSelector The destination chain to get the price for. + /// @return gasPrice The encoded gasPrice for the given destination chain ID. + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view returns (Internal.TimestampedPackedUint224 memory) { return s_usdPerUnitGasByDestChainSelector[destChainSelector]; } - /// @inheritdoc IPriceRegistry + /// @notice Gets the fee token price and the gas price, both denominated in dollars. + /// @param token The source token to get the price for. + /// @param destChainSelector The destination chain to get the gas price for. + /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. + /// @return gasPriceValue The price of gas in 1e18 dollars per base unit. function getTokenAndGasPrices( address token, uint64 destChainSelector - ) public view override returns (uint224 tokenPrice, uint224 gasPriceValue) { - Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector]; - // We do allow a gas price of 0, but no stale or unset gas prices - if (gasPrice.timestamp == 0) revert ChainNotSupported(destChainSelector); - uint256 timePassed = block.timestamp - gasPrice.timestamp; - if (timePassed > i_stalenessThreshold) revert StaleGasPrice(destChainSelector, i_stalenessThreshold, timePassed); - - return (_getValidatedTokenPrice(token), gasPrice.value); + ) external view returns (uint224 tokenPrice, uint224 gasPriceValue) { + if (!s_destChainConfigs[destChainSelector].isEnabled) revert DestinationChainNotEnabled(destChainSelector); + return ( + _getValidatedTokenPrice(token), + _getValidatedGasPrice(destChainSelector, s_destChainConfigs[destChainSelector].gasPriceStalenessThreshold) + ); } - /// @inheritdoc IPriceRegistry + /// @notice Convert a given token amount to target token amount. /// @dev this function assumes that no more than 1e59 dollars are sent as payment. /// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow. /// Since there isn't even close to 1e59 dollars in the world economy this is safe. + /// @param fromToken The given token address. + /// @param fromTokenAmount The given token amount. + /// @param toToken The target token address. + /// @return toTokenAmount The target token amount. function convertTokenAmount( address fromToken, uint256 fromTokenAmount, address toToken - ) public view override returns (uint256) { + ) public view returns (uint256) { /// Example: /// fromTokenAmount: 1e18 // 1 ETH /// ETH: 2_000e18 @@ -297,10 +344,12 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { return (fromTokenAmount * _getValidatedTokenPrice(fromToken)) / _getValidatedTokenPrice(toToken); } - /// @notice Gets the token price for a given token and revert if the token is not supported + /// @notice Gets the token price for a given token and reverts if the token is not supported /// @param token The address of the token to get the price for - /// @return the token price - function _getValidatedTokenPrice(address token) internal view returns (uint224) { + /// @return tokenPriceValue The token price + function _getValidatedTokenPrice( + address token + ) internal view returns (uint224) { Internal.TimestampedPackedUint224 memory tokenPrice = getTokenPrice(token); // Token price must be set at least once if (tokenPrice.timestamp == 0 || tokenPrice.value == 0) revert TokenNotSupported(token); @@ -310,11 +359,9 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// @notice Gets the token price from a data feed address, rebased to the same units as s_usdPerToken /// @param priceFeedConfig token data feed configuration with valid data feed address (used to retrieve price & timestamp) /// @return tokenPrice data feed price answer rebased to s_usdPerToken units, with latest block timestamp - function _getTokenPriceFromDataFeed(IPriceRegistry.TokenPriceFeedConfig memory priceFeedConfig) - internal - view - returns (Internal.TimestampedPackedUint224 memory tokenPrice) - { + function _getTokenPriceFromDataFeed( + TokenPriceFeedConfig memory priceFeedConfig + ) internal view returns (Internal.TimestampedPackedUint224 memory tokenPrice) { AggregatorV3Interface dataFeedContract = AggregatorV3Interface(priceFeedConfig.dataFeedAddress); ( /* uint80 roundID */ @@ -322,38 +369,39 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { int256 dataFeedAnswer, /* uint startedAt */ , - /* uint256 updatedAt */ - , + uint256 updatedAt, /* uint80 answeredInRound */ ) = dataFeedContract.latestRoundData(); if (dataFeedAnswer < 0) { revert DataFeedValueOutOfUint224Range(); } - uint256 rebasedValue = uint256(dataFeedAnswer); - - // Rebase formula for units in smallest token denomination: usdValue * (1e18 * 1e18) / 1eTokenDecimals - // feedValue * (10 ** (18 - feedDecimals)) * (10 ** (18 - erc20Decimals)) - // feedValue * (10 ** ((18 - feedDecimals) + (18 - erc20Decimals))) - // feedValue * (10 ** (36 - feedDecimals - erc20Decimals)) - // feedValue * (10 ** (36 - (feedDecimals + erc20Decimals))) - // feedValue * (10 ** (36 - excessDecimals)) - // If excessDecimals > 36 => flip it to feedValue / (10 ** (excessDecimals - 36)) + uint224 rebasedValue = + _calculateRebasedValue(dataFeedContract.decimals(), priceFeedConfig.tokenDecimals, uint256(dataFeedAnswer)); - uint8 excessDecimals = dataFeedContract.decimals() + priceFeedConfig.tokenDecimals; - - if (excessDecimals > 36) { - rebasedValue /= 10 ** (excessDecimals - 36); - } else { - rebasedValue *= 10 ** (36 - excessDecimals); - } + // Data feed staleness is unchecked to decouple the FeeQuoter from data feed delay issues + return Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: uint32(updatedAt)}); + } - if (rebasedValue > type(uint224).max) { - revert DataFeedValueOutOfUint224Range(); + /// @dev Gets the fee token price and the gas price, both denominated in dollars. + /// @param destChainSelector The destination chain to get the gas price for. + /// @param gasPriceStalenessThreshold The amount of time a gas price can be stale before it is considered invalid. + /// @return gasPriceValue The price of gas in 1e18 dollars per base unit. + function _getValidatedGasPrice( + uint64 destChainSelector, + uint32 gasPriceStalenessThreshold + ) private view returns (uint224 gasPriceValue) { + Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector]; + // If the staleness threshold is 0, we consider the gas price to be always valid + if (gasPriceStalenessThreshold != 0) { + // We do allow a gas price of 0, but no stale or unset gas prices + uint256 timePassed = block.timestamp - gasPrice.timestamp; + if (timePassed > gasPriceStalenessThreshold) { + revert StaleGasPrice(destChainSelector, gasPriceStalenessThreshold, timePassed); + } } - // Data feed staleness is unchecked to decouple the PriceRegistry from data feed delay issues - return Internal.TimestampedPackedUint224({value: uint224(rebasedValue), timestamp: uint32(block.timestamp)}); + return gasPrice.value; } // ================================================================ @@ -366,31 +414,31 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { } /// @notice Add and remove tokens from feeTokens set. + /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. /// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens /// and can be used to calculate fees. - /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. function applyFeeTokensUpdates( - address[] memory feeTokensToAdd, - address[] memory feeTokensToRemove + address[] memory feeTokensToRemove, + address[] memory feeTokensToAdd ) external onlyOwner { - _applyFeeTokensUpdates(feeTokensToAdd, feeTokensToRemove); + _applyFeeTokensUpdates(feeTokensToRemove, feeTokensToAdd); } /// @notice Add and remove tokens from feeTokens set. + /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. /// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens /// and can be used to calculate fees. - /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. - function _applyFeeTokensUpdates(address[] memory feeTokensToAdd, address[] memory feeTokensToRemove) private { - for (uint256 i = 0; i < feeTokensToAdd.length; ++i) { - if (s_feeTokens.add(feeTokensToAdd[i])) { - emit FeeTokenAdded(feeTokensToAdd[i]); - } - } + function _applyFeeTokensUpdates(address[] memory feeTokensToRemove, address[] memory feeTokensToAdd) private { for (uint256 i = 0; i < feeTokensToRemove.length; ++i) { if (s_feeTokens.remove(feeTokensToRemove[i])) { emit FeeTokenRemoved(feeTokensToRemove[i]); } } + for (uint256 i = 0; i < feeTokensToAdd.length; ++i) { + if (s_feeTokens.add(feeTokensToAdd[i])) { + emit FeeTokenAdded(feeTokensToAdd[i]); + } + } } // ================================================================ @@ -398,8 +446,10 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // ================================================================ /// @inheritdoc IPriceRegistry - function updatePrices(Internal.PriceUpdates calldata priceUpdates) external override { - // The caller must be the fee updater + function updatePrices( + Internal.PriceUpdates calldata priceUpdates + ) external override { + // The caller must be a fee updater _validateCaller(); uint256 tokenUpdatesLength = priceUpdates.tokenPriceUpdates.length; @@ -423,28 +473,63 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// @notice Updates the USD token price feeds for given tokens /// @param tokenPriceFeedUpdates Token price feed updates to apply - function updateTokenPriceFeeds(TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates) external onlyOwner { + function updateTokenPriceFeeds( + TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates + ) external onlyOwner { _updateTokenPriceFeeds(tokenPriceFeedUpdates); } /// @notice Updates the USD token price feeds for given tokens /// @param tokenPriceFeedUpdates Token price feed updates to apply - function _updateTokenPriceFeeds(TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates) private { + function _updateTokenPriceFeeds( + TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates + ) private { for (uint256 i; i < tokenPriceFeedUpdates.length; ++i) { TokenPriceFeedUpdate memory update = tokenPriceFeedUpdates[i]; address sourceToken = update.sourceToken; - IPriceRegistry.TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; + TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; s_usdPriceFeedsPerToken[sourceToken] = tokenPriceFeedConfig; emit PriceFeedPerTokenUpdated(sourceToken, tokenPriceFeedConfig); } } + /// @notice Handles the report containing price feeds and updates the internal price storage + /// @inheritdoc IReceiver + /// @dev This function is called to process incoming price feed data. + /// @param metadata Arbitrary metadata associated with the report (not used in this implementation). + /// @param report Encoded report containing an array of `ReceivedCCIPFeedReport` structs. + function onReport(bytes calldata metadata, bytes calldata report) external { + (bytes10 workflowName, address workflowOwner, bytes2 reportName) = metadata._extractMetadataInfo(); + + _validateReportPermission(msg.sender, workflowOwner, workflowName, reportName); + + ReceivedCCIPFeedReport[] memory feeds = abi.decode(report, (ReceivedCCIPFeedReport[])); + + for (uint256 i = 0; i < feeds.length; ++i) { + uint8 tokenDecimals = s_usdPriceFeedsPerToken[feeds[i].token].tokenDecimals; + if (tokenDecimals == 0) { + revert TokenNotSupported(feeds[i].token); + } + // Keystone reports prices in USD with 18 decimals, so we passing it as 18 in the _calculateRebasedValue function + uint224 rebasedValue = _calculateRebasedValue(uint8(KEYSTONE_PRICE_DECIMALS), tokenDecimals, feeds[i].price); + + //if stale update then revert + if (feeds[i].timestamp < s_usdPerToken[feeds[i].token].timestamp) { + revert StaleKeystoneUpdate(feeds[i].token, feeds[i].timestamp, s_usdPerToken[feeds[i].token].timestamp); + } + + s_usdPerToken[feeds[i].token] = + Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: feeds[i].timestamp}); + emit UsdPerTokenUpdated(feeds[i].token, rebasedValue, feeds[i].timestamp); + } + } + // ================================================================ // │ Fee quoting │ // ================================================================ - /// @inheritdoc IPriceRegistry + /// @inheritdoc IFeeQuoter /// @dev The function should always validate message.extraArgs, message.receiver and family-specific configs function getValidatedFee( uint64 destChainSelector, @@ -452,14 +537,14 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { ) 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); - uint64 premiumMultiplierWeiPerEth = s_premiumMultiplierWeiPerEth[message.feeToken]; - // The below call asserts that feeToken is a supported token - (uint224 feeTokenPrice, uint224 packedGasPrice) = getTokenAndGasPrices(message.feeToken, destChainSelector); + uint224 feeTokenPrice = _getValidatedTokenPrice(message.feeToken); + uint224 packedGasPrice = _getValidatedGasPrice(destChainSelector, destChainConfig.gasPriceStalenessThreshold); // Calculate premiumFee in USD with 18 decimals precision first. // If message-only and no token transfers, a flat network fee is charged. @@ -500,7 +585,6 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // NOTE: when supporting non-EVM chains, revisit how generic this fee logic can be // NOTE: revisit parsing non-EVM args - uint256 executionCost = uint112(packedGasPrice) * ( destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas @@ -510,10 +594,11 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // 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 * premiumMultiplierWeiPerEth) + executionCost + dataAvailabilityCost) / feeTokenPrice; + return ((premiumFee * s_premiumMultiplierWeiPerEth[message.feeToken]) + executionCost + dataAvailabilityCost) + / feeTokenPrice; } - /// @notice Sets the fee configuration for a token + /// @notice Sets the fee configuration for a token. /// @param premiumMultiplierWeiPerEthArgs Array of PremiumMultiplierWeiPerEthArgs structs. function applyPremiumMultiplierWeiPerEthUpdates( PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs @@ -521,7 +606,7 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); } - /// @dev Set the fee config. + /// @dev Sets the fee config. /// @param premiumMultiplierWeiPerEthArgs The multiplier for destination chain specific premiums. function _applyPremiumMultiplierWeiPerEthUpdates( PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs @@ -538,7 +623,9 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// @notice Gets the fee configuration for a token. /// @param token The token to get the fee configuration for. /// @return premiumMultiplierWeiPerEth The multiplier for destination chain specific premiums. - function getPremiumMultiplierWeiPerEth(address token) external view returns (uint64 premiumMultiplierWeiPerEth) { + function getPremiumMultiplierWeiPerEth( + address token + ) external view returns (uint64 premiumMultiplierWeiPerEth) { return s_premiumMultiplierWeiPerEth[token]; } @@ -574,13 +661,13 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { if (!transferFeeConfig.isEnabled) { tokenTransferFeeUSDWei += uint256(destChainConfig.defaultTokenFeeUSDCents) * 1e16; tokenTransferGas += destChainConfig.defaultTokenDestGasOverhead; - tokenTransferBytesOverhead += destChainConfig.defaultTokenDestBytesOverhead; + tokenTransferBytesOverhead += Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES; continue; } uint256 bpsFeeUSDWei = 0; // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. - // Useful for when the PriceRegistry cannot return a valid price for the token. + // Useful for when the FeeQuoter cannot return a valid price for the token. if (transferFeeConfig.deciBps > 0) { uint224 tokenPrice = 0; if (tokenAmount.token != feeToken) { @@ -617,6 +704,39 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead); } + /// @notice calculates the rebased value for 1e18 smallest token denomination + /// @param dataFeedDecimal decimal of the data feed + /// @param tokenDecimal decimal of the token + /// @param feedValue value of the data feed + /// @return rebasedValue rebased value + function _calculateRebasedValue( + uint8 dataFeedDecimal, + uint8 tokenDecimal, + uint256 feedValue + ) internal pure returns (uint224 rebasedValue) { + // Rebase formula for units in smallest token denomination: usdValue * (1e18 * 1e18) / 1eTokenDecimals + // feedValue * (10 ** (18 - feedDecimals)) * (10 ** (18 - erc20Decimals)) + // feedValue * (10 ** ((18 - feedDecimals) + (18 - erc20Decimals))) + // feedValue * (10 ** (36 - feedDecimals - erc20Decimals)) + // feedValue * (10 ** (36 - (feedDecimals + erc20Decimals))) + // feedValue * (10 ** (36 - excessDecimals)) + // If excessDecimals > 36 => flip it to feedValue / (10 ** (excessDecimals - 36)) + uint8 excessDecimals = dataFeedDecimal + tokenDecimal; + uint256 rebasedVal; + + if (excessDecimals > FEE_BASE_DECIMALS) { + rebasedVal = feedValue / (10 ** (excessDecimals - FEE_BASE_DECIMALS)); + } else { + rebasedVal = feedValue * (10 ** (FEE_BASE_DECIMALS - excessDecimals)); + } + + if (rebasedVal > type(uint224).max) { + revert DataFeedValueOutOfUint224Range(); + } + + return uint224(rebasedVal); + } + /// @notice Returns the estimated data availability cost of the message. /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes. /// @param destChainConfig the config configured for the destination chain selector. @@ -634,8 +754,8 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { ) internal pure returns (uint256 dataAvailabilityCostUSD36Decimal) { // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. // Fixed message fields do account for the offset and length slot of the dynamic fields. - uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR. @@ -650,6 +770,7 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// @notice Gets the transfer fee config for a given token. /// @param destChainSelector The destination chain selector. /// @param token The token address. + /// @return tokenTransferFeeConfig The transfer fee config for the token. function getTokenTransferFeeConfig( uint64 destChainSelector, address token @@ -704,19 +825,19 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // ================================================================ /// @notice Validates that the destAddress matches the expected format of the family. - /// @param chainFamilySelector Tag to identify the target family - /// @param destAddress Dest address to validate - /// @dev precondition - assumes the family tag is correct and validated + /// @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 { if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { Internal._validateEVMAddress(destAddress); } } - /// @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 extra args struct (latest version) + /// @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 @@ -732,9 +853,9 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { return evmExtraArgs; } - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args + /// @dev Convert the extra args bytes into a struct. + /// @param extraArgs The extra args bytes. + /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args. /// @return EVMExtraArgs the extra args struct (latest version) function _parseUnvalidatedEVMExtraArgsFromBytes( bytes calldata extraArgs, @@ -760,11 +881,11 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { } /// @notice Validate the forwarded message to ensure it matches the configuration limits (message length, number of tokens) - /// and family-specific expectations (address format) - /// @param destChainConfig Dest chain config + /// and family-specific expectations (address format). + /// @param destChainConfig The destination chain config. /// @param dataLength The length of the data field of the message. /// @param numberOfTokens The number of tokens to be sent. - /// @param receiver Message receiver on the dest chain + /// @param receiver Message receiver on the dest chain. function _validateMessage( DestChainConfig memory destChainConfig, uint256 dataLength, @@ -779,13 +900,25 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver); } - /// @inheritdoc IPriceRegistry + /// @inheritdoc IFeeQuoter + /// @dev precondition - onRampTokenTransfers and sourceTokenAmounts lengths must be equal function processMessageArgs( uint64 destChainSelector, address feeToken, uint256 feeTokenAmount, - bytes calldata extraArgs - ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) { + bytes calldata extraArgs, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) + external + view + returns ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ) + { // Convert feeToken to link if not already in link if (feeToken == i_linkToken) { msgFeeJuels = feeTokenAmount; @@ -800,55 +933,76 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // We can parse unvalidated args since this message is called after getFee (which will already validate the params) Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; + destExecDataPerToken = _processPoolReturnData(destChainSelector, onRampTokenTransfers, sourceTokenAmounts); - return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs)); + return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs), destExecDataPerToken); } - /// @inheritdoc IPriceRegistry - /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal - function validatePoolReturnData( + /// @notice Validates pool return data + /// @param destChainSelector Destination chain selector to which the token amounts are sent to + /// @param onRampTokenTransfers Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + /// @return destExecDataPerToken Destination chain execution data + function _processPoolReturnData( uint64 destChainSelector, - Internal.RampTokenAmount[] calldata rampTokenAmounts, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view { + ) internal view returns (bytes[] memory destExecDataPerToken) { bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; - - for (uint256 i = 0; i < rampTokenAmounts.length; ++i) { + destExecDataPerToken = new bytes[](onRampTokenTransfers.length); + for (uint256 i = 0; i < onRampTokenTransfers.length; ++i) { address sourceToken = sourceTokenAmounts[i].token; // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. - uint256 destPoolDataLength = rampTokenAmounts[i].extraData.length; + uint256 destPoolDataLength = onRampTokenTransfers[i].extraData.length; if (destPoolDataLength > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { if (destPoolDataLength > s_tokenTransferFeeConfig[destChainSelector][sourceToken].destBytesOverhead) { revert SourceTokenDataTooLarge(sourceToken); } } - _validateDestFamilyAddress(chainFamilySelector, rampTokenAmounts[i].destTokenAddress); + _validateDestFamilyAddress(chainFamilySelector, onRampTokenTransfers[i].destTokenAddress); + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + s_tokenTransferFeeConfig[destChainSelector][sourceToken]; + uint32 defaultGasOverhead = s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; + // NOTE: Revisit this when adding new non-EVM chain family selector support + uint32 destGasAmount = + tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : defaultGasOverhead; + + // The user will be billed either the default or the override, so we send the exact amount that we billed for + // to the destination chain to be used for the token releaseOrMint and transfer. + destExecDataPerToken[i] = abi.encode(destGasAmount); } + return destExecDataPerToken; } // ================================================================ // │ Configs │ // ================================================================ - /// @notice Returns the configured config for the dest chain selector - /// @param destChainSelector destination chain selector to fetch config for - /// @return destChainConfig config for the dest chain - function getDestChainConfig(uint64 destChainSelector) external view returns (DestChainConfig memory) { + /// @notice Returns the configured config for the dest chain selector. + /// @param destChainSelector Destination chain selector to fetch config for. + /// @return destChainConfig Config for the destination chain. + function getDestChainConfig( + uint64 destChainSelector + ) external view returns (DestChainConfig memory) { return s_destChainConfigs[destChainSelector]; } /// @notice Updates the destination chain specific config. /// @param destChainConfigArgs Array of source chain specific configs. - function applyDestChainConfigUpdates(DestChainConfigArgs[] memory destChainConfigArgs) external onlyOwner { + function applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) external onlyOwner { _applyDestChainConfigUpdates(destChainConfigArgs); } /// @notice Internal version of applyDestChainConfigUpdates. - function _applyDestChainConfigUpdates(DestChainConfigArgs[] memory destChainConfigArgs) internal { + function _applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) internal { for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; @@ -858,13 +1012,13 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { if ( destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM - || destChainConfig.defaultTokenDestBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit ) { revert InvalidDestChainConfig(destChainSelector); } - // The chain family selector cannot be zero - indicates that it is a new chain + // If the chain family selector is zero, it indicates that the chain was never configured and we + // are adding a new chain if (s_destChainConfigs[destChainSelector].chainFamilySelector == 0) { emit DestChainAdded(destChainSelector, destChainConfig); } else { @@ -875,14 +1029,14 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { } } - /// @notice Returns the static PriceRegistry config. - /// @dev RMN depends on this function, if changing, please notify the RMN maintainers. - /// @return the configuration. + /// @notice Returns the static FeeQuoter config. + /// @dev RMN depends on this function, if updated, please notify the RMN maintainers. + /// @return staticConfig The static configuration. function getStaticConfig() external view returns (StaticConfig memory) { return StaticConfig({ maxFeeJuelsPerMsg: i_maxFeeJuelsPerMsg, linkToken: i_linkToken, - stalenessThreshold: i_stalenessThreshold + tokenPriceStalenessThreshold: i_tokenPriceStalenessThreshold }); } } diff --git a/contracts/src/v0.8/ccip/LICENSE.md b/contracts/src/v0.8/ccip/LICENSE.md index 5f2783f7a34..b2e82483e93 100644 --- a/contracts/src/v0.8/ccip/LICENSE.md +++ b/contracts/src/v0.8/ccip/LICENSE.md @@ -9,13 +9,13 @@ Parameters Licensor: SmartContract Chainlink Limited SEZC -Licensed Work: Cross-Chain Interoperability Protocol v1.4 +Licensed Work: Cross-Chain Interoperability Protocol v1.5 The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC -Additional Use Grant: Any uses listed and defined at [v1.4-CCIP-License-grants]( -./v1.4-CCIP-License-grants) +Additional Use Grant: Any uses listed and defined at [v1.5-CCIP-License-grants]( +./v1.5-CCIP-License-grants.md) -Change Date: May 23, 2027 +Change Date: Aug 16, 2028 Change License: MIT diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 2a9d087a26c..7dfcc0ef603 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "./interfaces/IMessageInterceptor.sol"; -import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; @@ -10,72 +11,73 @@ import {Client} from "./libraries/Client.sol"; import {RateLimiter} from "./libraries/RateLimiter.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; -import {EnumerableSet} from "./../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; - /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of -/// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). +/// token transfers, using a fee quoter to convert to a numeraire asset (e.g. USD). /// The contract is a standalone multi-lane message validator contract, which can be called by authorized /// ramp contracts to apply rate limit changes to lanes, and revert when the rate limits get breached. -contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { +contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, ITypeAndVersion { using RateLimiter for RateLimiter.TokenBucket; using USDPriceWith18Decimals for uint224; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableSet for EnumerableSet.AddressSet; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; error PriceNotFoundForToken(address token); error ZeroChainSelectorNotAllowed(); event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, bool isOutboundLane, RateLimiter.Config config); - event PriceRegistrySet(address newPriceRegistry); - event TokenAggregateRateLimitAdded(uint64 remoteChainSelector, bytes32 remoteToken, address localToken); + event FeeQuoterSet(address newFeeQuoter); + event TokenAggregateRateLimitAdded(uint64 remoteChainSelector, bytes remoteToken, address localToken); event TokenAggregateRateLimitRemoved(uint64 remoteChainSelector, address localToken); - /// @notice RemoteRateLimitToken struct containing the local token address with the chain selector - /// The struct is used for removals and updates, since the local -> remote token mappings are scoped per-chain + /// @notice LocalRateLimitToken struct containing the local token address with the remote chain selector. + /// The struct is used for removals and updates, since the local -> remote token mappings are scoped per-chain. struct LocalRateLimitToken { uint64 remoteChainSelector; // ────╮ Remote chain selector for which to update the rate limit token mapping address localToken; // ────────────╯ Token on the chain on which the multi-ARL is deployed } - /// @notice RateLimitToken struct containing both the local and remote token addresses + /// @notice RateLimitTokenArgs struct containing both the local and remote token addresses. struct RateLimitTokenArgs { LocalRateLimitToken localTokenArgs; // Local token update args scoped to one remote chain - bytes32 remoteToken; // Token on the remote chain (for OnRamp - dest, of OffRamp - source) + bytes remoteToken; // Token on the remote chain (for OnRamp - dest, of OffRamp - source) } - /// @notice Update args for a single rate limiter config update + /// @notice Update args for a single rate limiter config update. struct RateLimiterConfigArgs { - uint64 remoteChainSelector; // ────╮ Chain selector to set config for + uint64 remoteChainSelector; // ────╮ Remote chain selector to set config for bool isOutboundLane; // ───────────╯ If set to true, represents the outbound message lane (OnRamp), and the inbound message lane otherwise (OffRamp) RateLimiter.Config rateLimiterConfig; // Rate limiter config to set } - /// @notice Struct to store rate limit token buckets for both lane directions + /// @notice Struct to store rate limit token buckets for both lane directions. struct RateLimiterBuckets { RateLimiter.TokenBucket inboundLaneBucket; // Bucket for the inbound lane (remote -> local) RateLimiter.TokenBucket outboundLaneBucket; // Bucket for the outbound lane (local -> remote) } + string public constant override typeAndVersion = "MultiAggregateRateLimiter 1.6.0-dev"; + /// @dev Tokens that should be included in Aggregate Rate Limiting (from local chain (this chain) -> remote), /// grouped per-remote chain. - mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytes32Map tokensLocalToRemote) internal + mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytesMap tokensLocalToRemote) private s_rateLimitedTokensLocalToRemote; - /// @notice The address of the PriceRegistry used to query token values for ratelimiting - address internal s_priceRegistry; + /// @notice The address of the FeeQuoter used to query token values for ratelimiting. + address internal s_feeQuoter; /// @notice Rate limiter token bucket states per chain, with separate buckets for inbound and outbound lanes. - mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) internal s_rateLimitersByChainSelector; + mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) private s_rateLimitersByChainSelector; - /// @param priceRegistry the price registry to set - /// @param authorizedCallers the authorized callers to set - constructor(address priceRegistry, address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) { - _setPriceRegistry(priceRegistry); + /// @param feeQuoter the fee quoter to set. + /// @param authorizedCallers the authorized callers to set. + constructor(address feeQuoter, address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) { + _setFeeQuoter(feeQuoter); } /// @inheritdoc IMessageInterceptor - function onInboundMessage(Client.Any2EVMMessage memory message) external onlyAuthorizedCallers { + function onInboundMessage( + Client.Any2EVMMessage memory message + ) external onlyAuthorizedCallers { _applyRateLimit(message.sourceChainSelector, message.destTokenAmounts, false); } @@ -87,9 +89,9 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { _applyRateLimit(destChainSelector, message.tokenAmounts, true); } - /// @notice Applies the rate limit to the token bucket if enabled - /// @param remoteChainSelector The remote chain selector - /// @param tokenAmounts The tokens and amounts to rate limit + /// @notice Applies the rate limit to the token bucket if enabled. + /// @param remoteChainSelector The remote chain selector. + /// @param tokenAmounts The tokens and amounts to rate limit. /// @param isOutgoingLane if set to true, fetches the bucket for the outgoing message lane (OnRamp). function _applyRateLimit( uint64 remoteChainSelector, @@ -111,10 +113,10 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { } } - /// @param remoteChainSelector chain selector to retrieve token bucket for + /// @param remoteChainSelector chain selector to retrieve token bucket for. /// @param isOutboundLane if set to true, fetches the bucket for the outbound message lane (OnRamp). /// Otherwise fetches for the inbound message lane (OffRamp). - /// @return bucket Storage pointer to the token bucket representing a specific lane + /// @return bucket Storage pointer to the token bucket representing a specific lane. function _getTokenBucket( uint64 remoteChainSelector, bool isOutboundLane @@ -127,12 +129,15 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { } } - /// @notice Retrieves the token value for a token using the PriceRegistry - /// @return tokenValue USD value in 18 decimals - function _getTokenValue(Client.EVMTokenAmount memory tokenAmount) internal view returns (uint256) { + /// @notice Retrieves the token value for a token using the FeeQuoter. + /// @param tokenAmount The token and amount to get the value for. + /// @return tokenValue USD value in 18 decimals. + function _getTokenValue( + Client.EVMTokenAmount memory tokenAmount + ) internal view returns (uint256) { // not fetching validated price, as price staleness is not important for value-based rate limiting // we only need to verify the price is not 0 - uint224 pricePerToken = IPriceRegistry(s_priceRegistry).getTokenPrice(tokenAmount.token).value; + uint224 pricePerToken = IFeeQuoter(s_feeQuoter).getTokenPrice(tokenAmount.token).value; if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); } @@ -142,7 +147,7 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { /// @param isOutboundLane if set to true, fetches the rate limit state for the outbound message lane (OnRamp). /// Otherwise fetches for the inbound message lane (OffRamp). /// The outbound and inbound message rate limit state is completely separated. - /// @return The token bucket. + /// @return tokenBucket The token bucket. function currentRateLimiterState( uint64 remoteChainSelector, bool isOutboundLane @@ -151,9 +156,11 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { } /// @notice Applies the provided rate limiter config updates. - /// @param rateLimiterUpdates Rate limiter updates - /// @dev should only be callable by the owner - function applyRateLimiterConfigUpdates(RateLimiterConfigArgs[] memory rateLimiterUpdates) external onlyOwner { + /// @param rateLimiterUpdates Rate limiter updates. + /// @dev Only callable by the owner. + function applyRateLimiterConfigUpdates( + RateLimiterConfigArgs[] memory rateLimiterUpdates + ) external onlyOwner { for (uint256 i = 0; i < rateLimiterUpdates.length; ++i) { RateLimiterConfigArgs memory updateArgs = rateLimiterUpdates[i]; RateLimiter.Config memory configUpdate = updateArgs.rateLimiterConfig; @@ -189,24 +196,22 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { } } - /// @notice Get all tokens which are included in Aggregate Rate Limiting. - /// @param remoteChainSelector chain selector to get rate limit tokens for - /// @return localTokens The local chain representation of the tokens that are rate limited. - /// @return remoteTokens The remote representation of the tokens that are rate limited. + /// @notice Gets all tokens which are included in Aggregate Rate Limiting. /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when /// making successive calls, one should keep the block height constant to ensure a consistent result. - function getAllRateLimitTokens(uint64 remoteChainSelector) - external - view - returns (address[] memory localTokens, bytes32[] memory remoteTokens) - { + /// @param remoteChainSelector chain selector to get rate limit tokens for. + /// @return localTokens The local chain representation of the tokens that are rate limited. + /// @return remoteTokens The remote representation of the tokens that are rate limited. + function getAllRateLimitTokens( + uint64 remoteChainSelector + ) external view returns (address[] memory localTokens, bytes[] memory remoteTokens) { uint256 tokenCount = s_rateLimitedTokensLocalToRemote[remoteChainSelector].length(); localTokens = new address[](tokenCount); - remoteTokens = new bytes32[](tokenCount); + remoteTokens = new bytes[](tokenCount); for (uint256 i = 0; i < tokenCount; ++i) { - (address localToken, bytes32 remoteToken) = s_rateLimitedTokensLocalToRemote[remoteChainSelector].at(i); + (address localToken, bytes memory remoteToken) = s_rateLimitedTokensLocalToRemote[remoteChainSelector].at(i); localTokens[i] = localToken; remoteTokens[i] = remoteToken; } @@ -231,10 +236,10 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { for (uint256 i = 0; i < adds.length; ++i) { LocalRateLimitToken memory localTokenArgs = adds[i].localTokenArgs; - bytes32 remoteToken = adds[i].remoteToken; + bytes memory remoteToken = adds[i].remoteToken; address localToken = localTokenArgs.localToken; - if (localToken == address(0) || remoteToken == bytes32("")) { + if (localToken == address(0) || remoteToken.length == 0) { revert ZeroAddressNotAllowed(); } @@ -246,27 +251,31 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers { } } - /// @return priceRegistry The configured PriceRegistry address - function getPriceRegistry() external view returns (address) { - return s_priceRegistry; + /// @return feeQuoter The configured FeeQuoter address. + function getFeeQuoter() external view returns (address feeQuoter) { + return s_feeQuoter; } - /// @notice Sets the Price Registry address - /// @param newPriceRegistry the address of the new PriceRegistry - /// @dev precondition The address must be a non-zero address - function setPriceRegistry(address newPriceRegistry) external onlyOwner { - _setPriceRegistry(newPriceRegistry); + /// @notice Sets the FeeQuoter address. + /// @param newFeeQuoter the address of the new FeeQuoter. + /// @dev precondition The address must be a non-zero address. + function setFeeQuoter( + address newFeeQuoter + ) external onlyOwner { + _setFeeQuoter(newFeeQuoter); } - /// @notice Sets the Price Registry address - /// @param newPriceRegistry the address of the new PriceRegistry - /// @dev precondition The address must be a non-zero address - function _setPriceRegistry(address newPriceRegistry) internal { - if (newPriceRegistry == address(0)) { + /// @notice Sets the FeeQuoter address. + /// @param newFeeQuoter the address of the new FeeQuoter. + /// @dev precondition The address must be a non-zero address. + function _setFeeQuoter( + address newFeeQuoter + ) internal { + if (newFeeQuoter == address(0)) { revert ZeroAddressNotAllowed(); } - s_priceRegistry = newPriceRegistry; - emit PriceRegistrySet(newPriceRegistry); + s_feeQuoter = newFeeQuoter; + emit FeeQuoterSet(newFeeQuoter); } } diff --git a/contracts/src/v0.8/ccip/NonceManager.sol b/contracts/src/v0.8/ccip/NonceManager.sol index 2cfcbbe9e2b..4847ca2e4f5 100644 --- a/contracts/src/v0.8/ccip/NonceManager.sol +++ b/contracts/src/v0.8/ccip/NonceManager.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; import {INonceManager} from "./interfaces/INonceManager.sol"; @@ -8,7 +9,7 @@ import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; /// @title NonceManager /// @notice NonceManager contract that manages sender nonces for the on/off ramps -contract NonceManager is INonceManager, AuthorizedCallers { +contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion { error PreviousRampAlreadySet(); event PreviousRampsUpdated(uint64 indexed remoteChainSelector, PreviousRamps prevRamp); @@ -23,11 +24,14 @@ contract NonceManager is INonceManager, AuthorizedCallers { /// @dev Struct that contains the chain selector and the previous on/off ramps, same as PreviousRamps but with the chain selector /// so that an array of these can be passed to the applyPreviousRampsUpdates function struct PreviousRampsArgs { - uint64 remoteChainSelector; // Chain selector + uint64 remoteChainSelector; // ──╮ Chain selector + bool overrideExistingRamps; // ──╯ Whether to override existing ramps PreviousRamps prevRamps; // Previous on/off ramps } - /// @dev previous ramps + string public constant override typeAndVersion = "NonceManager 1.6.0-dev"; + + /// @dev The previous on/off ramps per chain selector mapping(uint64 chainSelector => PreviousRamps previousRamps) private s_previousRamps; /// @dev The current outbound nonce per sender used on the onramp mapping(uint64 destChainSelector => mapping(address sender => uint64 outboundNonce)) private s_outboundNonces; @@ -36,7 +40,9 @@ contract NonceManager is INonceManager, AuthorizedCallers { /// executed in the same order they are sent (assuming they are DON) mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 inboundNonce)) private s_inboundNonces; - constructor(address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) {} + constructor( + address[] memory authorizedCallers + ) AuthorizedCallers(authorizedCallers) {} /// @inheritdoc INonceManager function getIncrementedOutboundNonce( @@ -49,10 +55,10 @@ contract NonceManager is INonceManager, AuthorizedCallers { return outboundNonce; } - /// @notice Returns the outbound nonce for a given sender on a given destination chain - /// @param destChainSelector The destination chain selector - /// @param sender The sender address - /// @return The outbound nonce + /// @notice Returns the outbound nonce for a given sender on a given destination chain. + /// @param destChainSelector The destination chain selector. + /// @param sender The sender address. + /// @return outboundNonce The outbound nonce. function getOutboundNonce(uint64 destChainSelector, address sender) external view returns (uint64) { return _getOutboundNonce(destChainSelector, sender); } @@ -92,10 +98,10 @@ contract NonceManager is INonceManager, AuthorizedCallers { return true; } - /// @notice Returns the inbound nonce for a given sender on a given source chain - /// @param sourceChainSelector The source chain selector - /// @param sender The encoded sender address - /// @return The inbound nonce + /// @notice Returns the inbound nonce for a given sender on a given source chain. + /// @param sourceChainSelector The source chain selector. + /// @param sender The encoded sender address. + /// @return inboundNonce The inbound nonce. function getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) external view returns (uint64) { return _getInboundNonce(sourceChainSelector, sender); } @@ -118,17 +124,24 @@ contract NonceManager is INonceManager, AuthorizedCallers { return inboundNonce; } - /// @notice Updates the previous ramps addresses - /// @param previousRampsArgs The previous on/off ramps addresses - function applyPreviousRampsUpdates(PreviousRampsArgs[] calldata previousRampsArgs) external onlyOwner { + /// @notice Updates the previous ramps addresses. + /// @param previousRampsArgs The previous on/off ramps addresses. + function applyPreviousRampsUpdates( + PreviousRampsArgs[] calldata previousRampsArgs + ) external onlyOwner { for (uint256 i = 0; i < previousRampsArgs.length; ++i) { PreviousRampsArgs calldata previousRampsArg = previousRampsArgs[i]; PreviousRamps storage prevRamps = s_previousRamps[previousRampsArg.remoteChainSelector]; - // If the previous ramps are already set then they should not be updated + // If the previous ramps are already set then they should not be updated. + // In versions prior to the introduction of the NonceManager contract, nonces were tracked in the on/off ramps. + // This config does a 1-time migration to move the nonce from on/off ramps into NonceManager if (prevRamps.prevOnRamp != address(0) || prevRamps.prevOffRamp != address(0)) { - revert PreviousRampAlreadySet(); + // We do allow explicit overrides as an escape hatch in the case of a misconfiguration. + if (!previousRampsArg.overrideExistingRamps) { + revert PreviousRampAlreadySet(); + } } prevRamps.prevOnRamp = previousRampsArg.prevRamps.prevOnRamp; @@ -140,8 +153,10 @@ contract NonceManager is INonceManager, AuthorizedCallers { /// @notice Gets the previous onRamp address for the given chain selector /// @param chainSelector The chain selector - /// @return The previous onRamp address - function getPreviousRamps(uint64 chainSelector) external view returns (PreviousRamps memory) { + /// @return previousRamps The previous on/offRamp addresses + function getPreviousRamps( + uint64 chainSelector + ) external view returns (PreviousRamps memory) { return s_previousRamps[chainSelector]; } } diff --git a/contracts/src/v0.8/ccip/RMN.sol b/contracts/src/v0.8/ccip/RMN.sol deleted file mode 100644 index 424aad8fa57..00000000000 --- a/contracts/src/v0.8/ccip/RMN.sol +++ /dev/null @@ -1,964 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {IRMN} from "./interfaces/IRMN.sol"; - -import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; - -import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -// An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a -// remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is -// deployed, relying on isCursed(). -bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; - -// An active curse on this subject will cause isCursed() and isCursed(bytes32) to return true. Use this subject for -// issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using -// the local chain selector as a subject. -bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; - -// The curse vote address representing the owner in data structures, events and recorded votes. Remains constant, even -// if the owner changes. -address constant OWNER_CURSE_VOTE_ADDR = address(~uint160(0)); // 0xff...ff - -// The curse vote address used in an OwnerUnvoteToCurseRequest to lift a curse, if there is no active curse votes for -// the subject that we are able to unvote, but the conditions for an active curse no longer hold. -address constant LIFT_CURSE_VOTE_ADDR = address(0); - -/// @dev This contract is owned by RMN, if changing, please notify the RMN maintainers. -// solhint-disable chainlink-solidity/explicit-returns -contract RMN is IRMN, OwnerIsCreator, ITypeAndVersion { - using EnumerableSet for EnumerableSet.AddressSet; - - // STATIC CONFIG - string public constant override typeAndVersion = "RMN 1.5.0-dev"; - - uint256 private constant MAX_NUM_VOTERS = 16; - - // MAGIC VALUES - bytes28 private constant NO_VOTES_CURSES_HASH = bytes28(0); - - // DYNAMIC CONFIG - /// @notice blessVoteAddr and curseVoteAddr can't be 0. Additionally curseVoteAddr can't be LIFT_CURSE_VOTE_ADDR or - /// OWNER_CURSE_VOTE_ADDR. At least one of blessWeight & curseWeight must be non-zero, i.e., a voter could only vote - /// to bless, or only vote to curse, or both vote to bless and vote to curse. - struct Voter { - // This is the address the voter should use to call voteToBless. - address blessVoteAddr; - // This is the address the voter should use to call voteToCurse. - address curseVoteAddr; - // The weight of this voter's vote for blessing. - uint8 blessWeight; - // The weight of this voter's vote for cursing. - uint8 curseWeight; - } - - struct Config { - Voter[] voters; - // When the total weight of voters that have voted to bless a tagged root reaches - // or exceeds blessWeightThreshold, the tagged root becomes blessed. - uint16 blessWeightThreshold; - // When the total weight of voters that have voted to curse a subject reaches or - // exceeds curseWeightThreshold, the subject becomes cursed. - uint16 curseWeightThreshold; - } - - struct VersionedConfig { - Config config; - // The version is incremented every time the config changes. - // The initial configuration on the contract will have configVersion == 1. - uint32 configVersion; - // The block number at which the config was last set. Helps the offchain - // code check that the config was set in a stable block or double-check - // that it has the correct config by querying logs at that block number. - uint32 blockNumber; - } - - VersionedConfig private s_versionedConfig; - - // STATE - struct BlesserRecord { - // The config version at which this BlesserRecord was last set. A blesser - // is considered active iff this configVersion equals - // s_versionedConfig.configVersion. - uint32 configVersion; - uint8 weight; - uint8 index; - } - - mapping(address blessVoteAddr => BlesserRecord blesserRecord) private s_blesserRecords; - - struct BlessVoteProgress { - // This particular ordering saves us ~400 gas per voteToBless call, compared to the bool being at the bottom, even - // though the size of the struct is the same. - bool weightThresholdMet; - // A BlessVoteProgress is considered invalid if weightThresholdMet is false when - // s_versionedConfig.configVersion changes. we don't want old in-progress - // votes to continue when we set a new config! - // The config version at which the bless vote for a tagged root was initiated. - uint32 configVersion; - uint16 accumulatedWeight; - // Care must be taken that the bitmap has at least as many bits as MAX_NUM_VOTERS. - // uint200 is much larger than we need, but it saves us ~100 gas per voteToBless call to fill the word instead of - // using a smaller type. - // _bitmapGet(voterBitmap, i) = true indicates that the i-th voter has voted to bless - uint200 voterBitmap; - } - - mapping(bytes32 taggedRootHash => BlessVoteProgress blessVoteProgress) private s_blessVoteProgressByTaggedRootHash; - - // Any tagged root with a commit store included in s_permaBlessedCommitStores will be considered automatically - // blessed. - EnumerableSet.AddressSet private s_permaBlessedCommitStores; - - struct CurserRecord { - bool active; - uint8 weight; - mapping(bytes16 curseId => bool used) usedCurseIds; // retained across config changes - } - - mapping(address curseVoteAddr => CurserRecord curserRecord) private s_curserRecords; - - struct ConfigVersionAndCursesHash { - uint32 configVersion; // configVersion != s_versionedConfig.configVersion means no active vote - bytes28 cursesHash; // bytes28(0) means no active vote; truncated so that ConfigVersionAndCursesHash fits in a word - } - - struct CurseVoteProgress { - uint32 configVersion; // upon config change, lazy set to new config version - uint16 curseWeightThreshold; // upon config change, lazy set to new config value - uint16 accumulatedWeight; // upon config change, lazy set to 0 - // A curse becomes active after either: - // - sum([voter.weight for voter who voted in current config]) >= curseWeightThreshold - // - ownerCurse is invoked - // Once a curse is active, only the owner can lift it. - bool curseActive; // retained across config changes - mapping(address => ConfigVersionAndCursesHash) latestVoteToCurseByCurseVoteAddr; // retained across config changes - } - - mapping(bytes16 subject => CurseVoteProgress curseVoteProgress) private - s_potentiallyOutdatedCurseVoteProgressBySubject; - - // We intentionally use a struct here, even though it contains a single field, to make it obvious to future editors - // that there is space for more fields. - struct CurseHotVars { - uint64 numSubjectsCursed; // incremented by voteToCurse, ownerCurse; decremented by ownerUnvoteToCurse - } - - CurseHotVars private s_curseHotVars; - - enum RecordedCurseRelatedOpTag { - // A vote to curse, through either voteToCurse or ownerCurse. - VoteToCurse, - // An unvote to curse, through unvoteToCurse. - UnvoteToCurse, - // An unvote to curse, through ownerUnvoteToCurse, which was not forced (forceUnvote=false). - OwnerUnvoteToCurseUnforced, - // An unvote to curse, through ownerUnvoteToCurse, which was forced (forceUnvote=true). - OwnerUnvoteToCurseForced, - // A configuration change. - // - // For subjects that are not cursed when this happens, past votes do not get accounted for in the new configuration. - // If a voter votes during the new configuration, their curses hash will restart from NO_VOTES_CURSES_HASH. - // - // For subjects that are cursed when this happens, past votes get accounted for. - // If a voter votes during the new configuration, their curses hash will continue from its old value. - SetConfig - } - - /// @notice Provides the ability to quickly reconstruct the curse-related state of the contract offchain, without - /// having to replay all past events. Replaying past events often takes long, and in some cases might even be - /// infeasible due to log pruning. - /// - /// @dev We could save some gas by omitting some fields and instead using them as mapping keys, but we would lose the - /// cross-voter ordering, or cross-subject ordering, or cross-vote/unvote ordering. - struct RecordedCurseRelatedOp { - RecordedCurseRelatedOpTag tag; - uint64 blockTimestamp; - bool cursed; // whether the subject is cursed after this op; if tag in {SetConfig}, will be false - address curseVoteAddr; // if tag in {SetConfig}, will be address(0) - bytes16 subject; // if tag in {SetConfig}, will be bytes16(0) - bytes16 curseId; // if tag in {SetConfig, UnvoteToCurse, OwnerUnvoteToCurseUnforced, OwnerUnvoteToCurseForced}, will be bytes16(0) - } - - RecordedCurseRelatedOp[] private s_recordedCurseRelatedOps; - - /// @dev This function is to _ONLY_ be called in order to determine if a curse should become active upon a - /// vote-to-curse, or a curse should be deactivated upon an owner-unvote-to-curse. - /// Other reasons for a curse to be active, which are not covered here: - /// 1. Cursedness is retained from a prior config. - /// 2. The curse weight threshold was met at some point, which activated a curse, and enough voters unvoted to curse - /// such that the curse weight threshold is no longer met. - function _shouldCurseBeActive(CurseVoteProgress storage sptr_upToDateCurseVoteProgress) internal view returns (bool) { - return sptr_upToDateCurseVoteProgress.latestVoteToCurseByCurseVoteAddr[OWNER_CURSE_VOTE_ADDR].cursesHash - != NO_VOTES_CURSES_HASH - || sptr_upToDateCurseVoteProgress.accumulatedWeight >= sptr_upToDateCurseVoteProgress.curseWeightThreshold; - } - - /// @dev It might be the case that due to the lazy update of curseVoteProgress, a curse is active even though - /// _shouldCurseBeActive(curseVoteProgress) is false, i.e., the owner has no active vote to curse and the curse - /// weight threshold has not been met. - function _getUpToDateCurseVoteProgress( - uint32 configVersion, - bytes16 subject - ) internal returns (CurseVoteProgress storage) { - CurseVoteProgress storage sptr_curseVoteProgress = s_potentiallyOutdatedCurseVoteProgressBySubject[subject]; - if (configVersion != sptr_curseVoteProgress.configVersion) { - sptr_curseVoteProgress.configVersion = configVersion; - sptr_curseVoteProgress.curseWeightThreshold = s_versionedConfig.config.curseWeightThreshold; - sptr_curseVoteProgress.accumulatedWeight = 0; - - if (sptr_curseVoteProgress.curseActive) { - // If a curse was active, count past votes to curse and retain the curses hash for cursers who are part of the - // new config. - Config storage sptr_config = s_versionedConfig.config; - for (uint256 i = 0; i < sptr_config.voters.length; ++i) { - Voter storage sptr_voter = sptr_config.voters[i]; - ConfigVersionAndCursesHash storage sptr_cvch = - sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[sptr_voter.curseVoteAddr]; - if (sptr_cvch.configVersion < configVersion && sptr_cvch.cursesHash != NO_VOTES_CURSES_HASH) { - // `< configVersion` instead of `== configVersion-1`, because there might have been multiple config changes - // without a lazy update of our subject. This has the side effect of retaining votes from very old configs - // that we might not really intend to retain, but these can be removed by the owner later. - sptr_cvch.configVersion = configVersion; - sptr_curseVoteProgress.accumulatedWeight += sptr_voter.curseWeight; - } - } - // We don't need to think about OWNER_CURSE_VOTE_ADDR here, because its ConfigVersionAndCursesHash counts even - // if the configVersion is not the current config version, in contrast to regular voters. - // It's an irregularity, but it saves us > 5k gas (if the owner had previously voted) for the unlucky voter who - // enters this branch. - } else { - // If a curse was not active, we don't count past votes to curse for voters who are part of the new config. - // Their curses hash will be restart from NO_VOTES_CURSES_HASH when they vote to curse again. - // We expect that the offchain code will revote to curse in case it voted to curse, and the vote to curse was - // lost due to any reason, including a config change when the curse was not yet active. - } - } - return sptr_curseVoteProgress; - } - - // EVENTS, ERRORS - - event ConfigSet(uint32 indexed configVersion, Config config); - - error InvalidConfig(); - - event TaggedRootBlessed(uint32 indexed configVersion, IRMN.TaggedRoot taggedRoot, uint16 accumulatedWeight); - event TaggedRootBlessVotesReset(uint32 indexed configVersion, IRMN.TaggedRoot taggedRoot, bool wasBlessed); - event VotedToBless(uint32 indexed configVersion, address indexed voter, IRMN.TaggedRoot taggedRoot, uint8 weight); - - event VotedToCurse( - uint32 indexed configVersion, - address indexed voter, - bytes16 subject, - bytes16 curseId, - uint8 weight, - uint64 blockTimestamp, - bytes28 cursesHash, - uint16 accumulatedWeight - ); - event UnvotedToCurse( - uint32 indexed configVersion, - address indexed voter, - bytes16 subject, - uint8 weight, - bytes28 cursesHash, - uint16 remainingAccumulatedWeight - ); - event SkippedUnvoteToCurse(address indexed voter, bytes16 subject, bytes28 onchainCursesHash, bytes28 cursesHash); - event Cursed(uint32 indexed configVersion, bytes16 subject, uint64 blockTimestamp); - event CurseLifted(bytes16 subject); - - // These events make it easier for offchain logic to discover that it performs - // the same actions multiple times. - event AlreadyVotedToBless(uint32 indexed configVersion, address indexed voter, IRMN.TaggedRoot taggedRoot); - event AlreadyBlessed(uint32 indexed configVersion, address indexed voter, IRMN.TaggedRoot taggedRoot); - - // Emitted by ownerRemoveThenAddPermaBlessedCommitStores. - event PermaBlessedCommitStoreAdded(address commitStore); - event PermaBlessedCommitStoreRemoved(address commitStore); - - error ReusedCurseId(address voter, bytes16 curseId); - error UnauthorizedVoter(address voter); - error VoteToBlessNoop(); - error VoteToCurseNoop(); - error UnvoteToCurseNoop(); - error VoteToBlessForbiddenDuringActiveGlobalCurse(); - - /// @notice Thrown when subjects are not a strictly increasing monotone sequence. - // Prevents a subject from receiving multiple votes to curse with the same curse id. - error SubjectsMustBeStrictlyIncreasing(); - - constructor(Config memory config) { - { - // Ensure that the bitmap is large enough to hold MAX_NUM_VOTERS. - // We do this in the constructor because MAX_NUM_VOTERS is constant. - BlessVoteProgress memory vp = BlessVoteProgress({ - configVersion: 0, - voterBitmap: type(uint200).max, // will not compile if it doesn't fit - accumulatedWeight: 0, - weightThresholdMet: false - }); - assert(vp.voterBitmap >> (MAX_NUM_VOTERS - 1) >= 1); - } - _setConfig(config); - } - - function _bitmapGet(uint200 bitmap, uint8 index) internal pure returns (bool) { - assert(index < MAX_NUM_VOTERS); - return bitmap & (uint200(1) << index) != 0; - } - - function _bitmapSet(uint200 bitmap, uint8 index) internal pure returns (uint200) { - assert(index < MAX_NUM_VOTERS); - return bitmap | (uint200(1) << index); - } - - function _bitmapCount(uint200 bitmap) internal pure returns (uint8 oneBits) { - assert(bitmap < 1 << MAX_NUM_VOTERS); - // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan - for (; bitmap != 0; ++oneBits) { - bitmap &= bitmap - 1; - } - } - - function _taggedRootHash(IRMN.TaggedRoot memory taggedRoot) internal pure returns (bytes32) { - return keccak256(abi.encode(taggedRoot.commitStore, taggedRoot.root)); - } - - function _cursesHash(bytes28 prevCursesHash, bytes16 curseId) internal pure returns (bytes28) { - return bytes28(keccak256(abi.encode(prevCursesHash, curseId))); - } - - function _blockTimestamp() internal view returns (uint64) { - return uint64(block.timestamp); - } - - /// @param taggedRoots A tagged root is hashed as `keccak256(abi.encode(taggedRoot.commitStore - /// /* address */, taggedRoot.root /* bytes32 */))`. - /// @notice Tagged roots which are already (voted to be) blessed are skipped and emit corresponding events. In case - /// the call has no effect, i.e., all passed tagged roots are skipped, the function reverts with a `VoteToBlessNoop`. - function voteToBless(IRMN.TaggedRoot[] calldata taggedRoots) external { - // If we have an active global curse, something is really wrong. Let's err on the - // side of caution and not accept further blessings during this time of - // uncertainty. - if (isCursed(GLOBAL_CURSE_SUBJECT)) revert VoteToBlessForbiddenDuringActiveGlobalCurse(); - - uint32 configVersion = s_versionedConfig.configVersion; - BlesserRecord memory blesserRecord = s_blesserRecords[msg.sender]; - if (blesserRecord.configVersion != configVersion) revert UnauthorizedVoter(msg.sender); - - bool noop = true; - for (uint256 i = 0; i < taggedRoots.length; ++i) { - IRMN.TaggedRoot memory taggedRoot = taggedRoots[i]; - bytes32 taggedRootHash = _taggedRootHash(taggedRoot); - BlessVoteProgress memory voteProgress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; - if (voteProgress.weightThresholdMet) { - // We don't revert here because it's unreasonable to expect from the - // voter to know exactly when to stop voting. Most likely when they - // voted they didn't realize the threshold would be reached by the time - // their vote was counted. - // Additionally, there might be other tagged roots for which votes might - // count, and we want to allow that to happen. - emit AlreadyBlessed(configVersion, msg.sender, taggedRoot); - continue; - } else if (voteProgress.configVersion != configVersion) { - // Note that voteProgress.weightThresholdMet must be false at this point - - // If votes were received while an older config was in effect, - // invalidate them and start from scratch. - // If votes were never received, set the current config version. - voteProgress = BlessVoteProgress({ - configVersion: configVersion, - voterBitmap: 0, - accumulatedWeight: 0, - weightThresholdMet: false - }); - } else if (_bitmapGet(voteProgress.voterBitmap, blesserRecord.index)) { - // We don't revert here because there might be other tagged roots for - // which votes might count, and we want to allow that to happen. - emit AlreadyVotedToBless(configVersion, msg.sender, taggedRoot); - continue; - } - noop = false; - voteProgress.voterBitmap = _bitmapSet(voteProgress.voterBitmap, blesserRecord.index); - voteProgress.accumulatedWeight += blesserRecord.weight; - emit VotedToBless(configVersion, msg.sender, taggedRoot, blesserRecord.weight); - if (voteProgress.accumulatedWeight >= s_versionedConfig.config.blessWeightThreshold) { - voteProgress.weightThresholdMet = true; - emit TaggedRootBlessed(configVersion, taggedRoot, voteProgress.accumulatedWeight); - } - s_blessVoteProgressByTaggedRootHash[taggedRootHash] = voteProgress; - } - - if (noop) { - revert VoteToBlessNoop(); - } - } - - /// @notice Can be called by the owner to remove unintentionally voted or even blessed tagged roots in a recovery - /// scenario. The owner must ensure that there are no in-flight transactions by RMN nodes voting for any of the - /// taggedRoots before calling this function, as such in-flight transactions could lead to the roots becoming - /// re-blessed shortly after the call to this function, contrary to the original intention. - function ownerResetBlessVotes(IRMN.TaggedRoot[] calldata taggedRoots) external onlyOwner { - uint32 configVersion = s_versionedConfig.configVersion; - for (uint256 i = 0; i < taggedRoots.length; ++i) { - IRMN.TaggedRoot memory taggedRoot = taggedRoots[i]; - bytes32 taggedRootHash = _taggedRootHash(taggedRoot); - BlessVoteProgress memory voteProgress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; - delete s_blessVoteProgressByTaggedRootHash[taggedRootHash]; - bool wasBlessed = voteProgress.weightThresholdMet; - if (voteProgress.configVersion == configVersion || wasBlessed) { - emit TaggedRootBlessVotesReset(configVersion, taggedRoot, wasBlessed); - } - } - } - - struct UnvoteToCurseRequest { - bytes16 subject; - bytes28 cursesHash; - } - - // For use in internal calls. - enum Privilege { - Owner, - Voter - } - - function _authorizedUnvoteToCurse( - Privilege priv, // Privilege.Owner during an ownerUnvoteToCurse call, Privilege.Voter during a unvoteToCurse call - uint32 configVersion, - address curseVoteAddr, - UnvoteToCurseRequest memory req, - bool forceUnvote, // true only during an ownerUnvoteToCurse call, when OwnerUnvoteToCurseRequest.forceUnvote is true - CurserRecord storage sptr_curserRecord, - CurseVoteProgress storage sptr_curseVoteProgress - ) internal returns (bool unvoted, bool curseLifted) { - { - assert(priv == Privilege.Voter || priv == Privilege.Owner); // sanity check - // Check that the supplied arguments are feasible for our privilege. - if (forceUnvote || curseVoteAddr == OWNER_CURSE_VOTE_ADDR || curseVoteAddr == LIFT_CURSE_VOTE_ADDR) { - assert(priv == Privilege.Owner); - } - } - - ConfigVersionAndCursesHash memory cvch = sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; - - // First, try to unvote. - if ( - sptr_curserRecord.active && (curseVoteAddr == OWNER_CURSE_VOTE_ADDR || cvch.configVersion == configVersion) - && cvch.cursesHash != NO_VOTES_CURSES_HASH && (cvch.cursesHash == req.cursesHash || forceUnvote) - ) { - unvoted = true; - delete sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; - // Assumes: s_curserRecords[OWNER_CURSE_VOTE_ADDR].weight == 0, enforced by _setConfig - sptr_curseVoteProgress.accumulatedWeight -= sptr_curserRecord.weight; - - emit UnvotedToCurse( - configVersion, - curseVoteAddr, - req.subject, - sptr_curserRecord.weight, - req.cursesHash, - sptr_curseVoteProgress.accumulatedWeight - ); - } - - // If we have owner privilege, and the conditions for the curse to be active no longer hold, we are able to lift the - // curse. - bool shouldTryToLiftCurse = priv == Privilege.Owner && (unvoted || curseVoteAddr == LIFT_CURSE_VOTE_ADDR); - - if (shouldTryToLiftCurse && sptr_curseVoteProgress.curseActive && !_shouldCurseBeActive(sptr_curseVoteProgress)) { - curseLifted = true; - sptr_curseVoteProgress.curseActive = false; - --s_curseHotVars.numSubjectsCursed; - emit CurseLifted(req.subject); - } - - if (unvoted || curseLifted) { - RecordedCurseRelatedOpTag tag; - if (priv == Privilege.Owner) { - if (forceUnvote) { - tag = RecordedCurseRelatedOpTag.OwnerUnvoteToCurseForced; - } else { - tag = RecordedCurseRelatedOpTag.OwnerUnvoteToCurseUnforced; - } - } else if (priv == Privilege.Voter) { - tag = RecordedCurseRelatedOpTag.UnvoteToCurse; - } else { - // solhint-disable-next-line gas-custom-errors, reason-string - revert(); // assumption violation - } - s_recordedCurseRelatedOps.push( - RecordedCurseRelatedOp({ - tag: tag, - cursed: sptr_curseVoteProgress.curseActive, - curseVoteAddr: curseVoteAddr, - curseId: bytes16(0), - subject: req.subject, - blockTimestamp: _blockTimestamp() - }) - ); - } else { - emit SkippedUnvoteToCurse(curseVoteAddr, req.subject, cvch.cursesHash, req.cursesHash); - } - } - - /// @notice Can be called by a curser to remove unintentional votes to curse. - /// We expect this to be called very rarely, e.g. in case of a bug in the - /// offchain code causing false voteToCurse calls. - /// @notice Should be called from curser's corresponding curseVoteAddr. - function unvoteToCurse(UnvoteToCurseRequest[] memory unvoteToCurseRequests) external { - address curseVoteAddr = msg.sender; - CurserRecord storage sptr_curserRecord = s_curserRecords[curseVoteAddr]; - - if (!sptr_curserRecord.active) revert UnauthorizedVoter(curseVoteAddr); - - uint32 configVersion = s_versionedConfig.configVersion; - bool anyVoteWasUnvoted = false; - for (uint256 i = 0; i < unvoteToCurseRequests.length; ++i) { - UnvoteToCurseRequest memory req = unvoteToCurseRequests[i]; - CurseVoteProgress storage sptr_curseVoteProgress = _getUpToDateCurseVoteProgress(configVersion, req.subject); - (bool unvoted, bool curseLifted) = _authorizedUnvoteToCurse( - Privilege.Voter, configVersion, curseVoteAddr, req, false, sptr_curserRecord, sptr_curseVoteProgress - ); - assert(!curseLifted); // assumption violation: voters can't lift curses - anyVoteWasUnvoted = anyVoteWasUnvoted || unvoted; - } - - if (!anyVoteWasUnvoted) { - revert UnvoteToCurseNoop(); - } - } - - /// @notice A vote to curse is appropriate during unhealthy blockchain conditions - /// (eg. finality violations). - function voteToCurse(bytes16 curseId, bytes16[] memory subjects) external { - address curseVoteAddr = msg.sender; - assert(curseVoteAddr != OWNER_CURSE_VOTE_ADDR); - CurserRecord storage sptr_curserRecord = s_curserRecords[curseVoteAddr]; - if (!sptr_curserRecord.active) revert UnauthorizedVoter(curseVoteAddr); - _authorizedVoteToCurse(curseVoteAddr, curseId, subjects, sptr_curserRecord); - } - - function _authorizedVoteToCurse( - address curseVoteAddr, - bytes16 curseId, - bytes16[] memory subjects, - CurserRecord storage sptr_curserRecord - ) internal { - if (subjects.length == 0) revert VoteToCurseNoop(); - - if (sptr_curserRecord.usedCurseIds[curseId]) revert ReusedCurseId(curseVoteAddr, curseId); - sptr_curserRecord.usedCurseIds[curseId] = true; - - // NOTE: We could pack configVersion into CurserRecord that we already load in the beginning of this function to - // avoid the following extra storage read for it, but since voteToCurse is not on the hot path we'd rather keep - // things simple. - uint32 configVersion = s_versionedConfig.configVersion; - for (uint256 i = 0; i < subjects.length; ++i) { - if (i >= 1 && !(subjects[i - 1] < subjects[i])) { - // Prevents a subject from receiving multiple votes to curse with the same curse id. - revert SubjectsMustBeStrictlyIncreasing(); - } - - bytes16 subject = subjects[i]; - CurseVoteProgress storage sptr_curseVoteProgress = _getUpToDateCurseVoteProgress(configVersion, subject); - ConfigVersionAndCursesHash memory cvch = sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; - bytes28 prevCursesHash; - if ( - (curseVoteAddr != OWNER_CURSE_VOTE_ADDR && cvch.configVersion < configVersion) - || cvch.cursesHash == NO_VOTES_CURSES_HASH - ) { - // if owner's first vote, or if voter's first vote in this config version - prevCursesHash = NO_VOTES_CURSES_HASH; // start hashchain from scratch, explicit - sptr_curseVoteProgress.accumulatedWeight += sptr_curserRecord.weight; - } else { - // we've already accounted for the weight - prevCursesHash = cvch.cursesHash; - } - sptr_curseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr] = cvch = - ConfigVersionAndCursesHash({configVersion: configVersion, cursesHash: _cursesHash(prevCursesHash, curseId)}); - emit VotedToCurse( - configVersion, - curseVoteAddr, - subject, - curseId, - sptr_curserRecord.weight, - _blockTimestamp(), - cvch.cursesHash, - sptr_curseVoteProgress.accumulatedWeight - ); - - if ( - prevCursesHash == NO_VOTES_CURSES_HASH && !sptr_curseVoteProgress.curseActive - && _shouldCurseBeActive(sptr_curseVoteProgress) - ) { - sptr_curseVoteProgress.curseActive = true; - ++s_curseHotVars.numSubjectsCursed; - emit Cursed(configVersion, subject, _blockTimestamp()); - } - - s_recordedCurseRelatedOps.push( - RecordedCurseRelatedOp({ - tag: RecordedCurseRelatedOpTag.VoteToCurse, - cursed: sptr_curseVoteProgress.curseActive, - curseVoteAddr: curseVoteAddr, - curseId: curseId, - subject: subject, - blockTimestamp: _blockTimestamp() - }) - ); - } - } - - /// @notice Enables the owner to immediately have the system enter the cursed state. - function ownerCurse(bytes16 curseId, bytes16[] memory subjects) external onlyOwner { - address curseVoteAddr = OWNER_CURSE_VOTE_ADDR; - CurserRecord storage sptr_curserRecord = s_curserRecords[curseVoteAddr]; - // no need to check if sptr_curserRecord.active, we must have the onlyOwner modifier - _authorizedVoteToCurse(curseVoteAddr, curseId, subjects, sptr_curserRecord); - } - - // Set curseVoteAddr=LIFT_CURSE_VOTE_ADDR, cursesHash=bytes28(0), to reset curseActive if it can be reset. Useful if - // all voters have unvoted to curse on their own and the curse can now be lifted without any individual votes that can - // be unvoted. - // solhint-disable-next-line gas-struct-packing - struct OwnerUnvoteToCurseRequest { - address curseVoteAddr; - UnvoteToCurseRequest unit; - bool forceUnvote; - } - - /// @notice Enables the owner to remove curse votes. After the curse votes are removed, - /// this function will check whether the curse is still valid and restore the uncursed state if possible. - /// This function also enables the owner to lift a curse created through ownerCurse. - function ownerUnvoteToCurse(OwnerUnvoteToCurseRequest[] memory ownerUnvoteToCurseRequests) external onlyOwner { - bool anyCurseWasLifted = false; - bool anyVoteWasUnvoted = false; - uint32 configVersion = s_versionedConfig.configVersion; - for (uint256 i = 0; i < ownerUnvoteToCurseRequests.length; ++i) { - OwnerUnvoteToCurseRequest memory req = ownerUnvoteToCurseRequests[i]; - CurseVoteProgress storage sptr_curseVoteProgress = _getUpToDateCurseVoteProgress(configVersion, req.unit.subject); - (bool unvoted, bool curseLifted) = _authorizedUnvoteToCurse( - Privilege.Owner, - configVersion, - req.curseVoteAddr, - req.unit, - req.forceUnvote, - s_curserRecords[req.curseVoteAddr], - sptr_curseVoteProgress - ); - anyVoteWasUnvoted = anyVoteWasUnvoted || unvoted; - anyCurseWasLifted = anyCurseWasLifted || curseLifted; - } - - if (anyCurseWasLifted) { - // Invalidate all in-progress votes to bless or curse by bumping the config version. - // They might have been based on false information about the source chain - // (e.g. in case of a finality violation). - _setConfig(s_versionedConfig.config); - } - - if (!(anyVoteWasUnvoted || anyCurseWasLifted)) { - revert UnvoteToCurseNoop(); - } - } - - function setConfig(Config memory config) external onlyOwner { - _setConfig(config); - } - - /// @notice Any tagged root with a commit store included in this array will be considered automatically blessed. - function getPermaBlessedCommitStores() external view returns (address[] memory) { - return s_permaBlessedCommitStores.values(); - } - - /// @notice The ordering of parameters is important. First come the commit stores to remove, then the commit stores to - /// add. - function ownerRemoveThenAddPermaBlessedCommitStores( - address[] memory removes, - address[] memory adds - ) external onlyOwner { - for (uint256 i = 0; i < removes.length; ++i) { - if (s_permaBlessedCommitStores.remove(removes[i])) { - emit PermaBlessedCommitStoreRemoved(removes[i]); - } - } - for (uint256 i = 0; i < adds.length; ++i) { - if (s_permaBlessedCommitStores.add(adds[i])) { - emit PermaBlessedCommitStoreAdded(adds[i]); - } - } - } - - /// @inheritdoc IRMN - function isBlessed(IRMN.TaggedRoot calldata taggedRoot) external view returns (bool) { - return s_blessVoteProgressByTaggedRootHash[_taggedRootHash(taggedRoot)].weightThresholdMet - || s_permaBlessedCommitStores.contains(taggedRoot.commitStore); - } - - /// @inheritdoc IRMN - function isCursed() external view returns (bool) { - if (s_curseHotVars.numSubjectsCursed == 0) { - return false; // happy path costs a single SLOAD - } else { - return s_potentiallyOutdatedCurseVoteProgressBySubject[GLOBAL_CURSE_SUBJECT].curseActive - || s_potentiallyOutdatedCurseVoteProgressBySubject[LEGACY_CURSE_SUBJECT].curseActive; - } - } - - /// @inheritdoc IRMN - function isCursed(bytes16 subject) public view returns (bool) { - if (s_curseHotVars.numSubjectsCursed == 0) { - return false; // happy path costs a single SLOAD - } else { - return s_potentiallyOutdatedCurseVoteProgressBySubject[GLOBAL_CURSE_SUBJECT].curseActive - || s_potentiallyOutdatedCurseVoteProgressBySubject[subject].curseActive; - } - } - - /// @notice Config version might be incremented for many reasons, including - /// the lifting of a curse, or a regular config change. - function getConfigDetails() external view returns (uint32 version, uint32 blockNumber, Config memory config) { - version = s_versionedConfig.configVersion; - blockNumber = s_versionedConfig.blockNumber; - config = s_versionedConfig.config; - } - - /// @return blessVoteAddrs addresses of voters, will be empty if voting took place with an older config version - /// @return accumulatedWeight sum of weights of voters, will be zero if voting took place with an older config version - /// @return blessed will be accurate regardless of when voting took place - /// @dev This is a helper method for offchain code so efficiency is not really a concern. - function getBlessProgress(IRMN.TaggedRoot calldata taggedRoot) - external - view - returns (address[] memory blessVoteAddrs, uint16 accumulatedWeight, bool blessed) - { - bytes32 taggedRootHash = _taggedRootHash(taggedRoot); - BlessVoteProgress memory progress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; - blessed = progress.weightThresholdMet; - if (progress.configVersion == s_versionedConfig.configVersion) { - accumulatedWeight = progress.accumulatedWeight; - uint200 bitmap = progress.voterBitmap; - blessVoteAddrs = new address[](_bitmapCount(bitmap)); - Voter[] memory voters = s_versionedConfig.config.voters; - uint256 j = 0; - for (uint8 i = 0; i < voters.length; ++i) { - if (_bitmapGet(bitmap, i)) { - blessVoteAddrs[j] = voters[i].blessVoteAddr; - ++j; - } - } - } - } - - /// @return curseVoteAddrs the curseVoteAddr of each voter with an active vote to curse - /// @return cursesHashes the i-th value is the curses hash of curseVoteAddrs[i] - /// @return accumulatedWeight the accumulated weight of all voters with an active vote to curse who are part of the - /// current config - /// @return cursed might be true even if the owner has no active vote and accumulatedWeight < curseWeightThreshold, - /// due to a retained curse from a prior config - /// @dev This is a helper method for offchain code so efficiency is not really a concern. - function getCurseProgress(bytes16 subject) - external - view - returns (address[] memory curseVoteAddrs, bytes28[] memory cursesHashes, uint16 accumulatedWeight, bool cursed) - { - uint32 configVersion = s_versionedConfig.configVersion; - Config memory config = s_versionedConfig.config; - // Can't use _getUpToDateCurseVoteProgress here because we can't call a non-view function from within a view. - // So we get to repeat some accounting. - CurseVoteProgress storage outdatedCurseVoteProgress = s_potentiallyOutdatedCurseVoteProgressBySubject[subject]; - - cursed = outdatedCurseVoteProgress.curseActive; - - // See _getUpToDateCurseVoteProgress for more context. - bool shouldCountVotesFromOlderConfigs = outdatedCurseVoteProgress.configVersion < configVersion && cursed; - - // A play in two acts, because we can't push to arrays in memory, so we need to precompute the array's length. - // First act: we count the number of cursers, i.e., voters with active vote. - // Second act: push the cursers to the arrays, sum their weights. - - uint256 numCursers = 0; // we reuse this variable for writing to perserve stack space - accumulatedWeight = 0; - for (uint256 act = 1; act <= 2; ++act) { - uint256 i = config.voters.length; // not config.voters.length-1 to account for the owner - while (true) { - address curseVoteAddr; - uint8 weight; - if (i < config.voters.length) { - curseVoteAddr = config.voters[i].curseVoteAddr; - weight = config.voters[i].curseWeight; - } else { - // Allows us to include the owner's vote and curses hash in the result. - curseVoteAddr = OWNER_CURSE_VOTE_ADDR; - weight = 0; - } - - ConfigVersionAndCursesHash memory cvch = - outdatedCurseVoteProgress.latestVoteToCurseByCurseVoteAddr[curseVoteAddr]; - bool hasActiveVote = ( - shouldCountVotesFromOlderConfigs || cvch.configVersion == configVersion - || curseVoteAddr == OWNER_CURSE_VOTE_ADDR - ) && cvch.cursesHash != NO_VOTES_CURSES_HASH; - if (hasActiveVote) { - if (act == 1) { - ++numCursers; - } else if (act == 2) { - accumulatedWeight += weight; - --numCursers; - curseVoteAddrs[numCursers] = curseVoteAddr; - cursesHashes[numCursers] = cvch.cursesHash; - } else { - // solhint-disable-next-line gas-custom-errors, reason-string - revert(); // assumption violation - } - } - - if (i > 0) { - --i; - } else { - break; - } - } - - if (act == 1) { - // We are done counting at this point, initialize the arrays for the second act that follows immediately after. - curseVoteAddrs = new address[](numCursers); - cursesHashes = new bytes28[](numCursers); - } - } - } - - /// @notice Returns the number of subjects that are currently cursed. - function getCursedSubjectsCount() external view returns (uint256) { - return s_curseHotVars.numSubjectsCursed; - } - - /// @dev This is a helper method for offchain code to know what arguments to use for getRecordedCurseRelatedOps. - function getRecordedCurseRelatedOpsCount() external view returns (uint256) { - return s_recordedCurseRelatedOps.length; - } - - /// @dev This is a helper method for offchain code so efficiency is not really a concern. - /// @dev Returns s_recordedCurseRelatedOps[offset:offset+limit]. - function getRecordedCurseRelatedOps( - uint256 offset, - uint256 limit - ) external view returns (RecordedCurseRelatedOp[] memory) { - uint256 pageLen; - if (offset + limit <= s_recordedCurseRelatedOps.length) { - pageLen = limit; - } else if (offset < s_recordedCurseRelatedOps.length) { - pageLen = s_recordedCurseRelatedOps.length - offset; - } else { - pageLen = 0; - } - RecordedCurseRelatedOp[] memory page = new RecordedCurseRelatedOp[](pageLen); - for (uint256 i = 0; i < pageLen; ++i) { - page[i] = s_recordedCurseRelatedOps[offset + i]; - } - return page; - } - - function _validateConfig(Config memory config) internal pure returns (bool) { - if ( - config.voters.length == 0 || config.voters.length > MAX_NUM_VOTERS || config.blessWeightThreshold == 0 - || config.curseWeightThreshold == 0 - ) { - return false; - } - - uint256 totalBlessWeight = 0; - uint256 totalCurseWeight = 0; - address[] memory allAddrs = new address[](2 * config.voters.length); - for (uint256 i = 0; i < config.voters.length; ++i) { - Voter memory voter = config.voters[i]; - // The owner can always curse using the ownerCurse method, and is not supposed to be included in the voters list. - // Even though the intent is for the actual owner address to NOT be included in the voters list, we don't - // explicitly disallow curseVoteAddr == owner() here. Even if we did, the owner could transfer ownership of the - // contract, and so we couldn't guarantee that the owner is not eventually included in the voters list. - if ( - voter.blessVoteAddr == address(0) || voter.curseVoteAddr == address(0) - || voter.curseVoteAddr == LIFT_CURSE_VOTE_ADDR || voter.curseVoteAddr == OWNER_CURSE_VOTE_ADDR - || (voter.blessWeight == 0 && voter.curseWeight == 0) - ) { - return false; - } - allAddrs[2 * i + 0] = voter.blessVoteAddr; - allAddrs[2 * i + 1] = voter.curseVoteAddr; - totalBlessWeight += voter.blessWeight; - totalCurseWeight += voter.curseWeight; - } - for (uint256 i = 0; i < allAddrs.length; ++i) { - address allAddrs_i = allAddrs[i]; - for (uint256 j = i + 1; j < allAddrs.length; ++j) { - if (allAddrs_i == allAddrs[j]) { - return false; - } - } - } - - return totalBlessWeight >= config.blessWeightThreshold && totalCurseWeight >= config.curseWeightThreshold; - } - - function _setConfig(Config memory config) private { - if (!_validateConfig(config)) revert InvalidConfig(); - - // We can't directly assign s_versionedConfig.config to config - // because copying a memory array into storage is not supported. - { - s_versionedConfig.config.blessWeightThreshold = config.blessWeightThreshold; - s_versionedConfig.config.curseWeightThreshold = config.curseWeightThreshold; - while (s_versionedConfig.config.voters.length != 0) { - Voter memory voter = s_versionedConfig.config.voters[s_versionedConfig.config.voters.length - 1]; - delete s_blesserRecords[voter.blessVoteAddr]; - delete s_curserRecords[voter.curseVoteAddr]; // usedCurseIds mapping is retained, as intended - s_versionedConfig.config.voters.pop(); - } - for (uint256 i = 0; i < config.voters.length; ++i) { - s_versionedConfig.config.voters.push(config.voters[i]); - } - } - - ++s_versionedConfig.configVersion; - uint32 configVersion = s_versionedConfig.configVersion; - - for (uint8 i = 0; i < config.voters.length; ++i) { - Voter memory voter = config.voters[i]; - s_blesserRecords[voter.blessVoteAddr] = - BlesserRecord({configVersion: configVersion, index: i, weight: voter.blessWeight}); - { - CurserRecord storage sptr_curserRecord = s_curserRecords[voter.curseVoteAddr]; - // Solidity will not let us initialize as CurserRecord({...}) due to the nested mapping - sptr_curserRecord.active = true; - sptr_curserRecord.weight = voter.curseWeight; - } - } - { - // Initialize the owner's CurserRecord - // We could in principle perform this initialization once in the constructor instead, and save a small bit of gas. - // But configuration changes are relatively infrequent, and keeping the initialization here makes the contract's - // correctness easier to reason about. - CurserRecord storage sptr_ownerCurserRecord = s_curserRecords[OWNER_CURSE_VOTE_ADDR]; - sptr_ownerCurserRecord.active = true; // Assumed by vote/unvote-to-curse logic - sptr_ownerCurserRecord.weight = 0; // Assumed by vote/unvote-to-curse logic - } - s_versionedConfig.blockNumber = uint32(block.number); - emit ConfigSet(configVersion, config); - - s_recordedCurseRelatedOps.push( - RecordedCurseRelatedOp({ - tag: RecordedCurseRelatedOpTag.SetConfig, - blockTimestamp: _blockTimestamp(), - cursed: false, - curseVoteAddr: address(0), - curseId: bytes16(0), - subject: bytes16(0) - }) - ); - } -} diff --git a/contracts/src/v0.8/ccip/Router.sol b/contracts/src/v0.8/ccip/Router.sol index e50651bc5ba..d83216fb6f6 100644 --- a/contracts/src/v0.8/ccip/Router.sol +++ b/contracts/src/v0.8/ccip/Router.sol @@ -16,7 +16,7 @@ import {Internal} from "./libraries/Internal.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"; -import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @title Router /// @notice This is the entry point for the end user wishing to send data across chains. @@ -89,7 +89,9 @@ contract Router is IRouter, IRouterClient, ITypeAndVersion, OwnerIsCreator { } /// @notice This functionality has been removed and will revert when called. - function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory) { + function getSupportedTokens( + uint64 chainSelector + ) external view returns (address[] memory) { if (!isChainSupported(chainSelector)) { return new address[](0); } @@ -97,7 +99,9 @@ contract Router is IRouter, IRouterClient, ITypeAndVersion, OwnerIsCreator { } /// @inheritdoc IRouterClient - function isChainSupported(uint64 chainSelector) public view returns (bool) { + function isChainSupported( + uint64 chainSelector + ) public view returns (bool) { return s_onRamps[chainSelector] != address(0); } @@ -192,7 +196,9 @@ contract Router is IRouter, IRouterClient, ITypeAndVersion, OwnerIsCreator { /// @notice Sets a new wrapped native token. /// @param wrappedNative The address of the new wrapped native ERC20 token. - function setWrappedNative(address wrappedNative) external onlyOwner { + function setWrappedNative( + address wrappedNative + ) external onlyOwner { s_wrappedNative = wrappedNative; } @@ -203,7 +209,9 @@ contract Router is IRouter, IRouterClient, ITypeAndVersion, OwnerIsCreator { } /// @inheritdoc IRouter - function getOnRamp(uint64 destChainSelector) external view returns (address) { + function getOnRamp( + uint64 destChainSelector + ) external view returns (address) { return s_onRamps[destChainSelector]; } diff --git a/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol b/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol index b105cf8b00f..56f3cd1fe8d 100644 --- a/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol +++ b/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {IRouterClient} from "../interfaces/IRouterClient.sol"; @@ -53,24 +53,24 @@ contract CCIPClientExample is CCIPReceiver, OwnerIsCreator { s_chains[chainSelector] = extraArgs; } - function disableChain(uint64 chainSelector) external onlyOwner { + function disableChain( + uint64 chainSelector + ) external onlyOwner { delete s_chains[chainSelector]; } - function ccipReceive(Client.Any2EVMMessage calldata message) - external - virtual - override - onlyRouter - validChain(message.sourceChainSelector) - { + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external virtual override onlyRouter validChain(message.sourceChainSelector) { // Extremely important to ensure only router calls this. // Tokens in message if any will be transferred to this contract // TODO: Validate sender/origin chain and process message and/or tokens. _ccipReceive(message); } - function _ccipReceive(Client.Any2EVMMessage memory message) internal override { + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal override { emit MessageReceived(message.messageId); } @@ -166,7 +166,9 @@ contract CCIPClientExample is CCIPReceiver, OwnerIsCreator { emit MessageSent(messageId); } - modifier validChain(uint64 chainSelector) { + modifier validChain( + uint64 chainSelector + ) { if (s_chains[chainSelector].length == 0) revert InvalidChain(chainSelector); _; } diff --git a/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol b/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol index 7011f814de7..8caeb3fccad 100644 --- a/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol +++ b/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol @@ -1,17 +1,19 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; import {Client} from "../libraries/Client.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; /// @title CCIPReceiver - Base contract for CCIP applications that can receive messages. abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165 { address internal immutable i_ccipRouter; - constructor(address router) { + constructor( + address router + ) { if (router == address(0)) revert InvalidRouter(address(0)); i_ccipRouter = router; } @@ -26,18 +28,24 @@ abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165 { /// If this returns true, tokens are transferred and ccipReceive is called atomically. /// Additionally, if the receiver address does not have code associated with /// it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred. - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + function supportsInterface( + bytes4 interfaceId + ) public view virtual override returns (bool) { return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } /// @inheritdoc IAny2EVMMessageReceiver - function ccipReceive(Client.Any2EVMMessage calldata message) external virtual override onlyRouter { + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external virtual override onlyRouter { _ccipReceive(message); } /// @notice Override this function in your implementation. /// @param message Any2EVMMessage - function _ccipReceive(Client.Any2EVMMessage memory message) internal virtual; + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal virtual; ///////////////////////////////////////////////////////////////////// // Plumbing diff --git a/contracts/src/v0.8/ccip/applications/DefensiveExample.sol b/contracts/src/v0.8/ccip/applications/DefensiveExample.sol index 54e1e809465..dbe8550933b 100644 --- a/contracts/src/v0.8/ccip/applications/DefensiveExample.sol +++ b/contracts/src/v0.8/ccip/applications/DefensiveExample.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {IRouterClient} from "../interfaces/IRouterClient.sol"; @@ -45,12 +45,9 @@ contract DefensiveExample is CCIPClientExample { /// never revert, all errors should be handled internally in this contract. /// @param message The message to process. /// @dev Extremely important to ensure only router calls this. - function ccipReceive(Client.Any2EVMMessage calldata message) - external - override - onlyRouter - validChain(message.sourceChainSelector) - { + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external override onlyRouter validChain(message.sourceChainSelector) { try this.processMessage(message) {} catch (bytes memory err) { // Could set different error codes based on the caught error. Each could be @@ -70,11 +67,9 @@ contract DefensiveExample is CCIPClientExample { /// @dev This example just sends the tokens to the owner of this contracts. More /// interesting functions could be implemented. /// @dev It has to be external because of the try/catch. - function processMessage(Client.Any2EVMMessage calldata message) - external - onlySelf - validChain(message.sourceChainSelector) - { + function processMessage( + Client.Any2EVMMessage calldata message + ) external onlySelf validChain(message.sourceChainSelector) { // Simulate a revert if (s_simRevert) revert ErrorCase(); @@ -106,7 +101,9 @@ contract DefensiveExample is CCIPClientExample { } // An example function to demonstrate recovery - function setSimRevert(bool simRevert) external onlyOwner { + function setSimRevert( + bool simRevert + ) external onlyOwner { s_simRevert = simRevert; } diff --git a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol index ce8ed1ff7a0..5bb0193c331 100644 --- a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol +++ b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol @@ -43,7 +43,9 @@ contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { IWrappedNative public immutable i_weth; /// @param router The CCIP router address. - constructor(address router) CCIPReceiver(router) { + constructor( + address router + ) CCIPReceiver(router) { i_weth = IWrappedNative(CCIPRouter(router).getWrappedNative()); i_weth.approve(router, type(uint256).max); } @@ -115,11 +117,9 @@ contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { /// @notice Validate the message content. /// @dev Only allows a single token to be sent. Always overwritten to be address(i_weth) /// and receiver is always msg.sender. - function _validatedMessage(Client.EVM2AnyMessage calldata message) - internal - view - returns (Client.EVM2AnyMessage memory) - { + function _validatedMessage( + Client.EVM2AnyMessage calldata message + ) internal view returns (Client.EVM2AnyMessage memory) { Client.EVM2AnyMessage memory validatedMessage = message; if (validatedMessage.tokenAmounts.length != 1) { @@ -132,7 +132,9 @@ contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { return validatedMessage; } - function _validateFeeToken(Client.EVM2AnyMessage calldata message) internal view { + function _validateFeeToken( + Client.EVM2AnyMessage calldata message + ) internal view { uint256 tokenAmount = message.tokenAmounts[0].amount; if (message.feeToken != address(0)) { @@ -148,7 +150,9 @@ contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { /// @param message The CCIP message containing the wrapped ether amount and the final receiver. /// @dev The code below should never revert if the message being is valid according /// to the above _validatedMessage and _validateFeeToken functions. - function _ccipReceive(Client.Any2EVMMessage memory message) internal override { + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal override { address receiver = abi.decode(message.data, (address)); if (message.destTokenAmounts.length != 1) { diff --git a/contracts/src/v0.8/ccip/applications/PingPongDemo.sol b/contracts/src/v0.8/ccip/applications/PingPongDemo.sol index 423fdc45467..3fd3eec6eed 100644 --- a/contracts/src/v0.8/ccip/applications/PingPongDemo.sol +++ b/contracts/src/v0.8/ccip/applications/PingPongDemo.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IRouterClient} from "../interfaces/IRouterClient.sol"; @@ -14,6 +14,10 @@ import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { event Ping(uint256 pingPongCount); event Pong(uint256 pingPongCount); + event OutOfOrderExecutionChange(bool isOutOfOrder); + + // Default gas limit used for EVMExtraArgsV2 construction + uint64 private constant DEFAULT_GAS_LIMIT = 200_000; // The chain ID of the counterpart ping pong contract uint64 internal s_counterpartChainSelector; @@ -23,6 +27,8 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { bool private s_isPaused; // The fee token used to pay for CCIP transactions IERC20 internal s_feeToken; + // Allowing out of order execution + bool private s_outOfOrderExecution; constructor(address router, IERC20 feeToken) CCIPReceiver(router) { s_isPaused = false; @@ -31,7 +37,7 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { } function typeAndVersion() external pure virtual returns (string memory) { - return "PingPongDemo 1.2.0"; + return "PingPongDemo 1.5.0"; } function setCounterpart(uint64 counterpartChainSelector, address counterpartAddress) external onlyOwner { @@ -44,24 +50,29 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { _respond(1); } - function _respond(uint256 pingPongCount) internal virtual { + function _respond( + uint256 pingPongCount + ) internal virtual { if (pingPongCount & 1 == 1) { emit Ping(pingPongCount); } else { emit Pong(pingPongCount); } - bytes memory data = abi.encode(pingPongCount); Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ receiver: abi.encode(s_counterpartAddress), - data: data, + data: abi.encode(pingPongCount), tokenAmounts: new Client.EVMTokenAmount[](0), - extraArgs: "", + extraArgs: Client._argsToBytes( + Client.EVMExtraArgsV2({gasLimit: uint256(DEFAULT_GAS_LIMIT), allowOutOfOrderExecution: s_outOfOrderExecution}) + ), feeToken: address(s_feeToken) }); IRouterClient(getRouter()).ccipSend(s_counterpartChainSelector, message); } - function _ccipReceive(Client.Any2EVMMessage memory message) internal override { + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal override { uint256 pingPongCount = abi.decode(message.data, (uint256)); if (!s_isPaused) { _respond(pingPongCount + 1); @@ -76,7 +87,9 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { return s_counterpartChainSelector; } - function setCounterpartChainSelector(uint64 chainSelector) external onlyOwner { + function setCounterpartChainSelector( + uint64 chainSelector + ) external onlyOwner { s_counterpartChainSelector = chainSelector; } @@ -88,7 +101,9 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { return s_feeToken; } - function setCounterpartAddress(address addr) external onlyOwner { + function setCounterpartAddress( + address addr + ) external onlyOwner { s_counterpartAddress = addr; } @@ -96,7 +111,20 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { return s_isPaused; } - function setPaused(bool pause) external onlyOwner { + function setPaused( + bool pause + ) external onlyOwner { s_isPaused = pause; } + + function getOutOfOrderExecution() external view returns (bool) { + return s_outOfOrderExecution; + } + + function setOutOfOrderExecution( + bool outOfOrderExecution + ) external onlyOwner { + s_outOfOrderExecution = outOfOrderExecution; + emit OutOfOrderExecutionChange(outOfOrderExecution); + } } diff --git a/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol b/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol deleted file mode 100644 index 80bc7bb24ab..00000000000 --- a/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Router} from "../Router.sol"; -import {Client} from "../libraries/Client.sol"; -import {EVM2EVMOnRamp} from "../onRamp/EVM2EVMOnRamp.sol"; -import {PingPongDemo} from "./PingPongDemo.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract SelfFundedPingPong is PingPongDemo { - string public constant override typeAndVersion = "SelfFundedPingPong 1.2.0"; - - event Funded(); - event CountIncrBeforeFundingSet(uint8 countIncrBeforeFunding); - - // Defines the increase in ping pong count before self-funding is attempted. - // Set to 0 to disable auto-funding, auto-funding only works for ping-pongs that are set as NOPs in the onRamp. - uint8 private s_countIncrBeforeFunding; - - constructor(address router, IERC20 feeToken, uint8 roundTripsBeforeFunding) PingPongDemo(router, feeToken) { - // PingPong count increases by 2 for each round trip. - s_countIncrBeforeFunding = roundTripsBeforeFunding * 2; - } - - function _respond(uint256 pingPongCount) internal override { - if (pingPongCount & 1 == 1) { - emit Ping(pingPongCount); - } else { - emit Pong(pingPongCount); - } - - fundPingPong(pingPongCount); - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(s_counterpartAddress), - data: abi.encode(pingPongCount), - tokenAmounts: new Client.EVMTokenAmount[](0), - extraArgs: "", - feeToken: address(s_feeToken) - }); - Router(getRouter()).ccipSend(s_counterpartChainSelector, message); - } - - /// @notice A function that is responsible for funding this contract. - /// The contract can only be funded if it is set as a nop in the target onRamp. - /// In case your contract is not a nop you can prevent this function from being called by setting s_countIncrBeforeFunding=0. - function fundPingPong(uint256 pingPongCount) public { - // If selfFunding is disabled, or ping pong count has not reached s_countIncrPerFunding, do not attempt funding. - if (s_countIncrBeforeFunding == 0 || pingPongCount < s_countIncrBeforeFunding) return; - - // Ping pong on one side will always be even, one side will always to odd. - if (pingPongCount % s_countIncrBeforeFunding <= 1) { - EVM2EVMOnRamp(Router(getRouter()).getOnRamp(s_counterpartChainSelector)).payNops(); - emit Funded(); - } - } - - function getCountIncrBeforeFunding() external view returns (uint8) { - return s_countIncrBeforeFunding; - } - - function setCountIncrBeforeFunding(uint8 countIncrBeforeFunding) external onlyOwner { - s_countIncrBeforeFunding = countIncrBeforeFunding; - emit CountIncrBeforeFundingSet(countIncrBeforeFunding); - } -} diff --git a/contracts/src/v0.8/ccip/applications/TokenProxy.sol b/contracts/src/v0.8/ccip/applications/TokenProxy.sol deleted file mode 100644 index 6fd26c076bc..00000000000 --- a/contracts/src/v0.8/ccip/applications/TokenProxy.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IRouterClient} from "../interfaces/IRouterClient.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Client} from "../libraries/Client.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"; - -contract TokenProxy is OwnerIsCreator { - using SafeERC20 for IERC20; - - error InvalidToken(); - error NoDataAllowed(); - error GasShouldBeZero(); - - /// @notice The CCIP router contract - IRouterClient internal immutable i_ccipRouter; - /// @notice Only this token is allowed to be sent using this proxy - address internal immutable i_token; - - constructor(address router, address token) OwnerIsCreator() { - i_ccipRouter = IRouterClient(router); - i_token = token; - // Approve the router to spend an unlimited amount of tokens to reduce - // gas cost per tx. - IERC20(token).approve(router, type(uint256).max); - } - - /// @notice Simply forwards the request to the CCIP router and returns the result. - /// @param destinationChainSelector The destination chainSelector - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return fee returns execution fee for the message delivery to destination chain, - /// denominated in the feeToken specified in the message. - /// @dev Reverts with appropriate reason upon invalid message. - function getFee( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 fee) { - _validateMessage(message); - return i_ccipRouter.getFee(destinationChainSelector, message); - } - - /// @notice Validates the message content, forwards it to the CCIP router and returns the result. - function ccipSend( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external payable returns (bytes32 messageId) { - _validateMessage(message); - if (message.feeToken != address(0)) { - // This path is probably warmed up already so the extra cost isn't too bad. - uint256 feeAmount = i_ccipRouter.getFee(destinationChainSelector, message); - IERC20(message.feeToken).safeTransferFrom(msg.sender, address(this), feeAmount); - IERC20(message.feeToken).approve(address(i_ccipRouter), feeAmount); - } - - // Transfer the tokens from the sender to this contract. - IERC20(message.tokenAmounts[0].token).transferFrom(msg.sender, address(this), message.tokenAmounts[0].amount); - - return i_ccipRouter.ccipSend{value: msg.value}(destinationChainSelector, message); - } - - /// @notice Validates the message content. - /// @dev Only allows a single token to be sent, and no data. - function _validateMessage(Client.EVM2AnyMessage calldata message) internal view { - if (message.tokenAmounts.length != 1 || message.tokenAmounts[0].token != i_token) revert InvalidToken(); - if (message.data.length > 0) revert NoDataAllowed(); - - if (message.extraArgs.length == 0 || bytes4(message.extraArgs) != Client.EVM_EXTRA_ARGS_V1_TAG) { - revert GasShouldBeZero(); - } - - if (abi.decode(message.extraArgs[4:], (Client.EVMExtraArgsV1)).gasLimit != 0) revert GasShouldBeZero(); - } - - /// @notice Returns the CCIP router contract. - function getRouter() external view returns (IRouterClient) { - return i_ccipRouter; - } - - /// @notice Returns the token that this proxy is allowed to send. - function getToken() external view returns (address) { - return i_token; - } -} diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol deleted file mode 100644 index 40b7a4a2f93..00000000000 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ /dev/null @@ -1,476 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {ICapabilitiesRegistry} from "./interfaces/ICapabilitiesRegistry.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; - -import {SortedSetValidationUtil} from "../../shared/util/SortedSetValidationUtil.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {CCIPConfigTypes} from "./libraries/CCIPConfigTypes.sol"; - -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice CCIPConfig stores the configuration for the CCIP capability. -/// We have two classes of configuration: chain configuration and DON (in the CapabilitiesRegistry sense) configuration. -/// Each chain will have a single configuration which includes information like the router address. -/// Each CR DON will have up to four configurations: for each of (commit, exec), one blue and one green configuration. -/// This is done in order to achieve "blue-green" deployments. -contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator, IERC165 { - using EnumerableSet for EnumerableSet.UintSet; - - /// @notice Emitted when a chain's configuration is set. - /// @param chainSelector The chain selector. - /// @param chainConfig The chain configuration. - event ChainConfigSet(uint64 chainSelector, CCIPConfigTypes.ChainConfig chainConfig); - - /// @notice Emitted when a chain's configuration is removed. - /// @param chainSelector The chain selector. - event ChainConfigRemoved(uint64 chainSelector); - - error ChainConfigNotSetForChain(uint64 chainSelector); - error NodeNotInRegistry(bytes32 p2pId); - error OnlyCapabilitiesRegistryCanCall(); - error ChainSelectorNotFound(uint64 chainSelector); - error ChainSelectorNotSet(); - error TooManyOCR3Configs(); - error TooManySigners(); - error TooManyTransmitters(); - error TooManyBootstrapP2PIds(); - error P2PIdsLengthNotMatching(uint256 p2pIdsLength, uint256 signersLength, uint256 transmittersLength); - error NotEnoughTransmitters(uint256 got, uint256 minimum); - error FMustBePositive(); - error FChainMustBePositive(); - error FTooHigh(); - error InvalidPluginType(); - error OfframpAddressCannotBeZero(); - error InvalidConfigLength(uint256 length); - error InvalidConfigStateTransition( - CCIPConfigTypes.ConfigState currentState, CCIPConfigTypes.ConfigState proposedState - ); - error NonExistentConfigTransition(); - error WrongConfigCount(uint64 got, uint64 expected); - error WrongConfigDigest(bytes32 got, bytes32 expected); - error WrongConfigDigestBlueGreen(bytes32 got, bytes32 expected); - - /// @notice Type and version override. - string public constant override typeAndVersion = "CCIPConfig 1.6.0-dev"; - - /// @notice The canonical capabilities registry address. - address internal immutable i_capabilitiesRegistry; - - /// @notice chain configuration for each chain that CCIP is deployed on. - mapping(uint64 chainSelector => CCIPConfigTypes.ChainConfig chainConfig) internal s_chainConfigurations; - - /// @notice All chains that are configured. - EnumerableSet.UintSet internal s_remoteChainSelectors; - - /// @notice OCR3 configurations for each DON. - /// Each CR DON will have a commit and execution configuration. - /// This means that a DON can have up to 4 configurations, since we are implementing blue/green deployments. - mapping( - uint32 donId => mapping(Internal.OCRPluginType pluginType => CCIPConfigTypes.OCR3ConfigWithMeta[] ocr3Configs) - ) internal s_ocr3Configs; - - /// @notice The DONs that have been configured. - EnumerableSet.UintSet internal s_donIds; - - uint8 internal constant MAX_OCR3_CONFIGS_PER_PLUGIN = 2; - uint8 internal constant MAX_OCR3_CONFIGS_PER_DON = 4; - uint8 internal constant MAX_NUM_ORACLES = 31; - - /// @param capabilitiesRegistry the canonical capabilities registry address. - constructor(address capabilitiesRegistry) { - i_capabilitiesRegistry = capabilitiesRegistry; - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // │ Config Getters │ - // ================================================================ - - /// @notice Returns all the chain configurations. - /// @return The chain configurations. - // TODO: will this eventually hit the RPC max response size limit? - function getAllChainConfigs() external view returns (CCIPConfigTypes.ChainConfigInfo[] memory) { - uint256[] memory chainSelectors = s_remoteChainSelectors.values(); - CCIPConfigTypes.ChainConfigInfo[] memory chainConfigs = - new CCIPConfigTypes.ChainConfigInfo[](s_remoteChainSelectors.length()); - for (uint256 i = 0; i < chainSelectors.length; ++i) { - uint64 chainSelector = uint64(chainSelectors[i]); - chainConfigs[i] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: chainSelector, - chainConfig: s_chainConfigurations[chainSelector] - }); - } - return chainConfigs; - } - - /// @notice Returns the OCR configuration for the given don ID and plugin type. - /// @param donId The DON ID. - /// @param pluginType The plugin type. - /// @return The OCR3 configurations, up to 2 (blue and green). - function getOCRConfig( - uint32 donId, - Internal.OCRPluginType pluginType - ) external view returns (CCIPConfigTypes.OCR3ConfigWithMeta[] memory) { - return s_ocr3Configs[donId][pluginType]; - } - - // ================================================================ - // │ Capability Configuration │ - // ================================================================ - - /// @inheritdoc ICapabilityConfiguration - /// @dev The CCIP capability will fetch the configuration needed directly from this contract. - /// The offchain syncer will call this function, however, so its important that it doesn't revert. - function getCapabilityConfiguration(uint32 /* donId */ ) external pure override returns (bytes memory configuration) { - return bytes(""); - } - - /// @notice Called by the registry prior to the config being set for a particular DON. - function beforeCapabilityConfigSet( - bytes32[] calldata, /* nodes */ - bytes calldata config, - uint64, /* configCount */ - uint32 donId - ) external override { - if (msg.sender != i_capabilitiesRegistry) { - revert OnlyCapabilitiesRegistryCanCall(); - } - - CCIPConfigTypes.OCR3Config[] memory ocr3Configs = abi.decode(config, (CCIPConfigTypes.OCR3Config[])); - (CCIPConfigTypes.OCR3Config[] memory commitConfigs, CCIPConfigTypes.OCR3Config[] memory execConfigs) = - _groupByPluginType(ocr3Configs); - if (commitConfigs.length > 0) { - _updatePluginConfig(donId, Internal.OCRPluginType.Commit, commitConfigs); - } - if (execConfigs.length > 0) { - _updatePluginConfig(donId, Internal.OCRPluginType.Execution, execConfigs); - } - } - - function _updatePluginConfig( - uint32 donId, - Internal.OCRPluginType pluginType, - CCIPConfigTypes.OCR3Config[] memory newConfig - ) internal { - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = s_ocr3Configs[donId][pluginType]; - - // Validate the state transition being proposed, which is implicitly defined by the combination - // of lengths of the current and new configurations. - CCIPConfigTypes.ConfigState currentState = _stateFromConfigLength(currentConfig.length); - CCIPConfigTypes.ConfigState proposedState = _stateFromConfigLength(newConfig.length); - _validateConfigStateTransition(currentState, proposedState); - - // Build the new configuration with metadata and validate that the transition is valid. - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta = - _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, proposedState); - _validateConfigTransition(currentConfig, newConfigWithMeta); - - // Update contract state with new configuration if its valid. - // We won't run out of gas from this delete since the array is at most 2 elements long. - delete s_ocr3Configs[donId][pluginType]; - for (uint256 i = 0; i < newConfigWithMeta.length; ++i) { - s_ocr3Configs[donId][pluginType].push(newConfigWithMeta[i]); - } - } - - // ================================================================ - // │ Config State Machine │ - // ================================================================ - - /// @notice Determine the config state of the configuration from the length of the config. - /// @param configLen The length of the configuration. - /// @return The config state. - function _stateFromConfigLength(uint256 configLen) internal pure returns (CCIPConfigTypes.ConfigState) { - if (configLen > 2) { - revert InvalidConfigLength(configLen); - } - return CCIPConfigTypes.ConfigState(configLen); - } - - // the only valid state transitions are the following: - // init -> running (first ever config) - // running -> staging (blue/green proposal) - // staging -> running (promotion) - // everything else is invalid and should revert. - function _validateConfigStateTransition( - CCIPConfigTypes.ConfigState currentState, - CCIPConfigTypes.ConfigState newState - ) internal pure { - // Calculate the difference between the new state and the current state - int256 stateDiff = int256(uint256(newState)) - int256(uint256(currentState)); - - // Check if the state transition is valid: - // Valid transitions: - // 1. currentState -> newState (where stateDiff == 1) - // e.g., init -> running or running -> staging - // 2. staging -> running (where stateDiff == -1) - if (stateDiff == 1 || (stateDiff == -1 && currentState == CCIPConfigTypes.ConfigState.Staging)) { - return; - } - revert InvalidConfigStateTransition(currentState, newState); - } - - function _validateConfigTransition( - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig, - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta - ) internal pure { - uint256 currentConfigLen = currentConfig.length; - uint256 newConfigLen = newConfigWithMeta.length; - if (currentConfigLen == 0 && newConfigLen == 1) { - // Config counts always must start at 1 for the first ever config. - if (newConfigWithMeta[0].configCount != 1) { - revert WrongConfigCount(newConfigWithMeta[0].configCount, 1); - } - return; - } - - if (currentConfigLen == 1 && newConfigLen == 2) { - // On a blue/green proposal: - // * the config digest of the blue config must remain unchanged. - // * the green config count must be the blue config count + 1. - if (newConfigWithMeta[0].configDigest != currentConfig[0].configDigest) { - revert WrongConfigDigestBlueGreen(newConfigWithMeta[0].configDigest, currentConfig[0].configDigest); - } - if (newConfigWithMeta[1].configCount != currentConfig[0].configCount + 1) { - revert WrongConfigCount(newConfigWithMeta[1].configCount, currentConfig[0].configCount + 1); - } - return; - } - - if (currentConfigLen == 2 && newConfigLen == 1) { - // On a promotion, the green config digest must become the blue config digest. - if (newConfigWithMeta[0].configDigest != currentConfig[1].configDigest) { - revert WrongConfigDigest(newConfigWithMeta[0].configDigest, currentConfig[1].configDigest); - } - return; - } - - revert NonExistentConfigTransition(); - } - - /// @notice Computes a new configuration with metadata based on the current configuration and the new configuration. - /// @param donId The DON ID. - /// @param currentConfig The current configuration, including metadata. - /// @param newConfig The new configuration, without metadata. - /// @param currentState The current state of the configuration. - /// @param newState The new state of the configuration. - /// @return The new configuration with metadata. - function _computeNewConfigWithMeta( - uint32 donId, - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig, - CCIPConfigTypes.OCR3Config[] memory newConfig, - CCIPConfigTypes.ConfigState currentState, - CCIPConfigTypes.ConfigState newState - ) internal view returns (CCIPConfigTypes.OCR3ConfigWithMeta[] memory) { - uint64[] memory configCounts = new uint64[](newConfig.length); - - // Set config counts based on the only valid state transitions. - // Init -> Running (first ever config) - // Running -> Staging (blue/green proposal) - // Staging -> Running (promotion) - if (currentState == CCIPConfigTypes.ConfigState.Init && newState == CCIPConfigTypes.ConfigState.Running) { - // First ever config starts with config count == 1. - configCounts[0] = 1; - } else if (currentState == CCIPConfigTypes.ConfigState.Running && newState == CCIPConfigTypes.ConfigState.Staging) { - // On a blue/green proposal, the config count of the green config is the blue config count + 1. - configCounts[0] = currentConfig[0].configCount; - configCounts[1] = currentConfig[0].configCount + 1; - } else if (currentState == CCIPConfigTypes.ConfigState.Staging && newState == CCIPConfigTypes.ConfigState.Running) { - // On a promotion, the config count of the green config becomes the blue config count. - configCounts[0] = currentConfig[1].configCount; - } else { - revert InvalidConfigStateTransition(currentState, newState); - } - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta = - new CCIPConfigTypes.OCR3ConfigWithMeta[](newConfig.length); - for (uint256 i = 0; i < configCounts.length; ++i) { - _validateConfig(newConfig[i]); - newConfigWithMeta[i] = CCIPConfigTypes.OCR3ConfigWithMeta({ - config: newConfig[i], - configCount: configCounts[i], - configDigest: _computeConfigDigest(donId, configCounts[i], newConfig[i]) - }); - } - - return newConfigWithMeta; - } - - /// @notice Group the OCR3 configurations by plugin type for further processing. - /// @param ocr3Configs The OCR3 configurations to group. - function _groupByPluginType(CCIPConfigTypes.OCR3Config[] memory ocr3Configs) - internal - pure - returns (CCIPConfigTypes.OCR3Config[] memory commitConfigs, CCIPConfigTypes.OCR3Config[] memory execConfigs) - { - if (ocr3Configs.length > MAX_OCR3_CONFIGS_PER_DON) { - revert TooManyOCR3Configs(); - } - - // Declare with size 2 since we have a maximum of two configs per plugin type (blue, green). - // If we have less we will adjust the length later using mstore. - // If the caller provides more than 2 configs per plugin type, we will revert due to out of bounds - // access in the for loop below. - commitConfigs = new CCIPConfigTypes.OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); - execConfigs = new CCIPConfigTypes.OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); - uint256 commitCount; - uint256 execCount; - for (uint256 i = 0; i < ocr3Configs.length; ++i) { - if (ocr3Configs[i].pluginType == Internal.OCRPluginType.Commit) { - commitConfigs[commitCount] = ocr3Configs[i]; - ++commitCount; - } else { - execConfigs[execCount] = ocr3Configs[i]; - ++execCount; - } - } - - // Adjust the length of the arrays to the actual number of configs. - assembly { - mstore(commitConfigs, commitCount) - mstore(execConfigs, execCount) - } - - return (commitConfigs, execConfigs); - } - - function _validateConfig(CCIPConfigTypes.OCR3Config memory cfg) internal view { - if (cfg.chainSelector == 0) revert ChainSelectorNotSet(); - if (cfg.pluginType != Internal.OCRPluginType.Commit && cfg.pluginType != Internal.OCRPluginType.Execution) { - revert InvalidPluginType(); - } - // TODO: can we do more sophisticated validation than this? - if (cfg.offrampAddress.length == 0) revert OfframpAddressCannotBeZero(); - if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); - - // Some of these checks below are done in OCR2/3Base config validation, so we do them again here. - // Role DON OCR configs will have all the Role DON signers but only a subset of transmitters. - if (cfg.signers.length > MAX_NUM_ORACLES) revert TooManySigners(); - if (cfg.transmitters.length > MAX_NUM_ORACLES) revert TooManyTransmitters(); - - // We check for chain config presence above, so fChain here must be non-zero. - uint256 minTransmittersLength = 3 * s_chainConfigurations[cfg.chainSelector].fChain + 1; - if (cfg.transmitters.length < minTransmittersLength) { - revert NotEnoughTransmitters(cfg.transmitters.length, minTransmittersLength); - } - if (cfg.F == 0) revert FMustBePositive(); - if (cfg.signers.length <= 3 * cfg.F) revert FTooHigh(); - - if (cfg.p2pIds.length != cfg.signers.length || cfg.p2pIds.length != cfg.transmitters.length) { - revert P2PIdsLengthNotMatching(cfg.p2pIds.length, cfg.signers.length, cfg.transmitters.length); - } - if (cfg.bootstrapP2PIds.length > cfg.p2pIds.length) revert TooManyBootstrapP2PIds(); - - // check for duplicate p2p ids and bootstrapP2PIds. - // check that p2p ids in cfg.bootstrapP2PIds are included in cfg.p2pIds. - SortedSetValidationUtil._checkIsValidUniqueSubset(cfg.bootstrapP2PIds, cfg.p2pIds); - - // Check that the readers are in the capabilities registry. - for (uint256 i = 0; i < cfg.signers.length; ++i) { - _ensureInRegistry(cfg.p2pIds[i]); - } - } - - /// @notice Computes the digest of the provided configuration. - /// @dev In traditional OCR config digest computation, block.chainid and address(this) are used - /// in order to further domain separate the digest. We can't do that here since the digest will - /// be used on remote chains; so we use the chain selector instead of block.chainid. The don ID - /// replaces the address(this) in the traditional computation. - /// @param donId The DON ID. - /// @param configCount The configuration count. - /// @param ocr3Config The OCR3 configuration. - /// @return The computed digest. - function _computeConfigDigest( - uint32 donId, - uint64 configCount, - CCIPConfigTypes.OCR3Config memory ocr3Config - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - ocr3Config.chainSelector, - donId, - ocr3Config.pluginType, - ocr3Config.offrampAddress, - configCount, - ocr3Config.bootstrapP2PIds, - ocr3Config.p2pIds, - ocr3Config.signers, - ocr3Config.transmitters, - ocr3Config.F, - ocr3Config.offchainConfigVersion, - ocr3Config.offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x000a << (256 - 16); // 0x000a00..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - // ================================================================ - // │ Chain Configuration │ - // ================================================================ - - /// @notice Sets and/or removes chain configurations. - /// @param chainSelectorRemoves The chain configurations to remove. - /// @param chainConfigAdds The chain configurations to add. - function applyChainConfigUpdates( - uint64[] calldata chainSelectorRemoves, - CCIPConfigTypes.ChainConfigInfo[] calldata chainConfigAdds - ) external onlyOwner { - // Process removals first. - for (uint256 i = 0; i < chainSelectorRemoves.length; ++i) { - // check if the chain selector is in s_remoteChainSelectors first. - if (!s_remoteChainSelectors.contains(chainSelectorRemoves[i])) { - revert ChainSelectorNotFound(chainSelectorRemoves[i]); - } - - delete s_chainConfigurations[chainSelectorRemoves[i]]; - s_remoteChainSelectors.remove(chainSelectorRemoves[i]); - - emit ChainConfigRemoved(chainSelectorRemoves[i]); - } - - // Process additions next. - for (uint256 i = 0; i < chainConfigAdds.length; ++i) { - CCIPConfigTypes.ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; - bytes32[] memory readers = chainConfig.readers; - uint64 chainSelector = chainConfigAdds[i].chainSelector; - - // Verify that the provided readers are present in the capabilities registry. - for (uint256 j = 0; j < readers.length; j++) { - _ensureInRegistry(readers[j]); - } - - // Verify that fChain is positive. - if (chainConfig.fChain == 0) { - revert FChainMustBePositive(); - } - - s_chainConfigurations[chainSelector] = chainConfig; - s_remoteChainSelectors.add(chainSelector); - - emit ChainConfigSet(chainSelector, chainConfig); - } - } - - /// @notice Helper function to ensure that a node is in the capabilities registry. - /// @param p2pId The P2P ID of the node to check. - function _ensureInRegistry(bytes32 p2pId) internal view { - ICapabilitiesRegistry.NodeInfo memory node = ICapabilitiesRegistry(i_capabilitiesRegistry).getNode(p2pId); - if (node.p2pId == bytes32("")) { - revert NodeNotInRegistry(p2pId); - } - } -} diff --git a/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/contracts/src/v0.8/ccip/capability/CCIPHome.sol new file mode 100644 index 00000000000..c343e0200ec --- /dev/null +++ b/contracts/src/v0.8/ccip/capability/CCIPHome.sol @@ -0,0 +1,621 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; + +import {INodeInfoProvider} from "../../keystone/interfaces/INodeInfoProvider.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Internal} from "../libraries/Internal.sol"; + +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice CCIPHome stores the configuration for the CCIP capability. +/// We have two classes of configuration: chain configuration and DON (in the CapabilitiesRegistry sense) configuration. +/// Each chain will have a single configuration which includes information like the router address. +/// @dev This contract is a state machine with the following states: +/// - Init: The initial state of the contract, no config has been set, or all configs have been revoked. +/// [0, 0] +/// +/// - Candidate: A new config has been set, but it has not been promoted yet, or all active configs have been revoked. +/// [0, 1] +/// +/// - Active: A non-zero config has been promoted and is active, there is no candidate configured. +/// [1, 0] +/// +/// - ActiveAndCandidate: A non-zero config has been promoted and is active, and a new config has been set as candidate. +/// [1, 1] +/// +/// The following state transitions are allowed: +/// - Init -> Candidate: setCandidate() +/// - Candidate -> Active: promoteCandidateAndRevokeActive() +/// - Candidate -> Candidate: setCandidate() +/// - Candidate -> Init: revokeCandidate() +/// - Active -> ActiveAndCandidate: setCandidate() +/// - Active -> Init: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: revokeCandidate() +/// - ActiveAndCandidate -> ActiveAndCandidate: setCandidate() +/// +/// This means the following calls are not allowed at the following states: +/// - Init: promoteCandidateAndRevokeActive(), as there is no config to promote. +/// - Init: revokeCandidate(), as there is no config to revoke +/// - Active: revokeCandidate(), as there is no candidate to revoke +/// Note that we explicitly do allow promoteCandidateAndRevokeActive() to be called when there is an active config but +/// no candidate config. This is the only way to remove the active config. The alternative would be to set some unusable +/// config as candidate and promote that, but fully clearing it is cleaner. +/// +/// ┌─────────────┐ setCandidate ┌─────────────┐ +/// │ ├───────────────────►│ │ setCandidate +/// │ Init │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [0,0] │◄───────────────────┤ [0,1] │────────────┘ +/// │ │ ┌─────────────────┤ │ +/// └─────────────┘ │ promote- └─────────────┘ +/// ▲ │ Candidate +/// promote- │ │ +/// Candidate │ │ +/// │ │ +/// ┌──────────┴──┐ │ promote- ┌─────────────┐ +/// │ │◄─┘ Candidate OR │ Active & │ setCandidate +/// │ Active │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ +/// │ ├───────────────────►│ │ +/// └─────────────┘ setSecondary └─────────────┘ +/// +contract CCIPHome is OwnerIsCreator, ITypeAndVersion, ICapabilityConfiguration, IERC165 { + using EnumerableSet for EnumerableSet.UintSet; + + event ChainConfigRemoved(uint64 chainSelector); + event ChainConfigSet(uint64 chainSelector, ChainConfig chainConfig); + event ConfigSet(bytes32 indexed configDigest, uint32 version, OCR3Config config); + event ActiveConfigRevoked(bytes32 indexed configDigest); + event CandidateConfigRevoked(bytes32 indexed configDigest); + event ConfigPromoted(bytes32 indexed configDigest); + + error ChainSelectorNotFound(uint64 chainSelector); + error FChainMustBePositive(); + error ChainSelectorNotSet(); + error InvalidPluginType(); + error OfframpAddressCannotBeZero(); + error FChainTooHigh(uint256 fChain, uint256 FRoleDON); + error TooManySigners(); + error FTooHigh(); + error RMNHomeAddressCannotBeZero(); + error InvalidNode(OCR3Node node); + error NotEnoughTransmitters(uint256 got, uint256 minimum); + error OnlyCapabilitiesRegistryCanCall(); + error ZeroAddressNotAllowed(); + error ConfigDigestMismatch(bytes32 expectedConfigDigest, bytes32 gotConfigDigest); + error CanOnlySelfCall(); + error RevokingZeroDigestNotAllowed(); + error NoOpStateTransitionNotAllowed(); + error InvalidSelector(bytes4 selector); + error DONIdMismatch(uint32 callDonId, uint32 capabilityRegistryDonId); + + error InvalidStateTransition( + bytes32 currentActiveDigest, + bytes32 currentCandidateDigest, + bytes32 proposedActiveDigest, + bytes32 proposedCandidateDigest + ); + + /// @notice Represents an oracle node in OCR3 configs part of the role DON. + /// Every configured node should be a signer, but does not have to be a transmitter. + struct OCR3Node { + bytes32 p2pId; // Peer2Peer connection ID of the oracle + bytes signerKey; // On-chain signer public key + bytes transmitterKey; // On-chain transmitter public key. Can be set to empty bytes to represent that the node is a signer but not a transmitter. + } + + /// @notice OCR3 configuration. + /// Note that FRoleDON >= fChain, since FRoleDON represents the role DON, and fChain represents sub-committees. + /// FRoleDON values are typically identical across multiple OCR3 configs since the chains pertain to one role DON, + /// but FRoleDON values can change across OCR3 configs to indicate role DON splits. + struct OCR3Config { + Internal.OCRPluginType pluginType; // ─╮ The plugin that the configuration is for. + uint64 chainSelector; // │ The (remote) chain that the configuration is for. + uint8 FRoleDON; // │ The "big F" parameter for the role DON. + uint64 offchainConfigVersion; // ──────╯ The version of the exec offchain configuration. + bytes offrampAddress; // The remote chain offramp address. + bytes rmnHomeAddress; // The home chain RMN home address. + OCR3Node[] nodes; // Keys & IDs of nodes part of the role DON + bytes offchainConfig; // The offchain configuration for the OCR3 plugin. Protobuf encoded. + } + + struct VersionedConfig { + uint32 version; + bytes32 configDigest; + OCR3Config config; + } + + /// @notice Chain configuration. + /// Changes to chain configuration are detected out-of-band in plugins and decoded offchain. + struct ChainConfig { + bytes32[] readers; // The P2P IDs of the readers for the chain. These IDs must be registered in the capabilities registry. + uint8 fChain; // The fault tolerance parameter of the chain. + bytes config; // The chain configuration. This is kept intentionally opaque so as to add fields in the future if needed. + } + + /// @notice Chain configuration information struct used in applyChainConfigUpdates and getAllChainConfigs. + struct ChainConfigArgs { + uint64 chainSelector; + ChainConfig chainConfig; + } + + string public constant override typeAndVersion = "CCIPHome 1.6.0-dev"; + + /// @dev A prefix added to all config digests that is unique to the implementation + uint256 private constant PREFIX = 0x000a << (256 - 16); // 0x000a00..00 + bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); + /// @dev 256 is the hard limit due to the bit encoding of their indexes into a uint256. + uint256 internal constant MAX_NUM_ORACLES = 256; + + /// @notice Used for encoding the config digest prefix + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + /// @notice The max number of configs that can be active at the same time. + uint256 private constant MAX_CONCURRENT_CONFIGS = 2; + /// @notice Helper to identify the zero config digest with less casting. + bytes32 private constant ZERO_DIGEST = bytes32(uint256(0)); + + /// @dev The canonical capabilities registry address. + address internal immutable i_capabilitiesRegistry; + + /// @dev chain configuration for each chain that CCIP is deployed on. + mapping(uint64 chainSelector => ChainConfig chainConfig) private s_chainConfigurations; + + /// @dev All chains that are configured. + EnumerableSet.UintSet private s_remoteChainSelectors; + + /// @notice This array holds the configs. + /// @dev A DonID covers a single chain, and the plugin type is used to differentiate between the commit and execution + mapping(uint32 donId => mapping(Internal.OCRPluginType pluginType => VersionedConfig[MAX_CONCURRENT_CONFIGS])) private + s_configs; + + /// @notice The total number of configs ever set, used for generating the version of the configs. + /// @dev Used to ensure unique digests across all configurations. + uint32 private s_currentVersion = 0; + /// @notice The index of the active config on a per-don and per-plugin basis. + mapping(uint32 donId => mapping(Internal.OCRPluginType pluginType => uint32)) private s_activeConfigIndexes; + + /// @notice Constructor for the CCIPHome contract takes in the address of the capabilities registry. This address + /// is the only allowed caller to mutate the configuration through beforeCapabilityConfigSet. + constructor( + address capabilitiesRegistry + ) { + if (capabilitiesRegistry == address(0)) { + revert ZeroAddressNotAllowed(); + } + i_capabilitiesRegistry = capabilitiesRegistry; + } + + // ================================================================ + // │ Capability Registry │ + // ================================================================ + + /// @notice Returns the capabilities registry address. + /// @return The capabilities registry address. + function getCapabilityRegistry() external view returns (address) { + return i_capabilitiesRegistry; + } + + /// @inheritdoc IERC165 + /// @dev Required for the capabilities registry to recognize this contract. + function supportsInterface( + bytes4 interfaceId + ) external pure override returns (bool) { + return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; + } + + /// @notice Called by the registry prior to the config being set for a particular DON. + /// @dev precondition Requires destination chain config to be set + function beforeCapabilityConfigSet( + bytes32[] calldata, // nodes + bytes calldata update, + // Config count is unused because we don't want to invalidate a config on blue/green promotions so we keep track of + // the actual newly submitted configs instead of the number of config mutations. + uint64, // config count + uint32 donId + ) external override { + if (msg.sender != i_capabilitiesRegistry) { + revert OnlyCapabilitiesRegistryCanCall(); + } + + bytes4 selector = bytes4(update[:4]); + // We only allow self-calls to the following approved methods + if ( + selector != this.setCandidate.selector && selector != this.revokeCandidate.selector + && selector != this.promoteCandidateAndRevokeActive.selector + ) { + revert InvalidSelector(selector); + } + + // We validate that the call contains the correct DON ID. The DON ID is always the first function argument. + uint256 callDonId = abi.decode(update[4:36], (uint256)); + if (callDonId != donId) { + revert DONIdMismatch(uint32(callDonId), donId); + } + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory retData) = address(this).call(update); + // if not successful, revert with the original revert + if (!success) { + assembly { + revert(add(retData, 0x20), returndatasize()) + } + } + } + + /// @inheritdoc ICapabilityConfiguration + /// @dev The CCIP capability will fetch the configuration needed directly from this contract. + /// The offchain syncer will call this function, so its important that it doesn't revert. + function getCapabilityConfiguration( + uint32 /* donId */ + ) external pure override returns (bytes memory configuration) { + return bytes(""); + } + + // ================================================================ + // │ Getters │ + // ================================================================ + + /// @notice Returns the current active and candidate config digests. + /// @dev Can be bytes32(0) if no config has been set yet or it has been revoked. + /// @param donId The key of the plugin to get the config digests for. + /// @return activeConfigDigest The digest of the active config. + /// @return candidateConfigDigest The digest of the candidate config. + function getConfigDigests( + uint32 donId, + Internal.OCRPluginType pluginType + ) public view returns (bytes32 activeConfigDigest, bytes32 candidateConfigDigest) { + return ( + s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)].configDigest, + s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)].configDigest + ); + } + + /// @notice Returns the active config digest for for a given key. + /// @param donId The key of the plugin to get the config digests for. + function getActiveDigest(uint32 donId, Internal.OCRPluginType pluginType) public view returns (bytes32) { + return s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)].configDigest; + } + + /// @notice Returns the candidate config digest for for a given key. + /// @param donId The key of the plugin to get the config digests for. + function getCandidateDigest(uint32 donId, Internal.OCRPluginType pluginType) public view returns (bytes32) { + return s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)].configDigest; + } + + /// @notice The offchain code can use this to fetch an old config which might still be in use by some remotes. Use + /// in case one of the configs is too large to be returnable by one of the other getters. + /// @param donId The unique key for the DON that the configuration applies to. + /// @param configDigest The digest of the config to fetch. + /// @return versionedConfig The config and its version. + /// @return ok True if the config was found, false otherwise. + function getConfig( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes32 configDigest + ) external view returns (VersionedConfig memory versionedConfig, bool ok) { + for (uint256 i = 0; i < MAX_CONCURRENT_CONFIGS; ++i) { + // We never want to return true for a zero digest, even if the caller is asking for it, as this can expose old + // config state that is invalid. + if (s_configs[donId][pluginType][i].configDigest == configDigest && configDigest != ZERO_DIGEST) { + return (s_configs[donId][pluginType][i], true); + } + } + // versionConfig is uninitialized so it contains default values. + return (versionedConfig, false); + } + + /// @notice Returns the active and candidate configuration for a given plugin key. + /// @param donId The unique key for the DON that the configuration applies to. + /// @return activeConfig The active configuration. + /// @return candidateConfig The candidate configuration. + function getAllConfigs( + uint32 donId, + Internal.OCRPluginType pluginType + ) external view returns (VersionedConfig memory activeConfig, VersionedConfig memory candidateConfig) { + VersionedConfig memory storedActiveConfig = s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)]; + if (storedActiveConfig.configDigest != ZERO_DIGEST) { + activeConfig = storedActiveConfig; + } + + VersionedConfig memory storedCandidateConfig = s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)]; + if (storedCandidateConfig.configDigest != ZERO_DIGEST) { + candidateConfig = storedCandidateConfig; + } + + return (activeConfig, candidateConfig); + } + + // ================================================================ + // │ State transitions │ + // ================================================================ + + /// @notice Sets a new config as the candidate config. Does not influence the active config. + /// @param donId The key of the plugin to set the config for. + /// @return newConfigDigest The digest of the new config. + function setCandidate( + uint32 donId, + Internal.OCRPluginType pluginType, + OCR3Config calldata config, + bytes32 digestToOverwrite + ) external returns (bytes32 newConfigDigest) { + _onlySelfCall(); + _validateConfig(config); + + bytes32 existingDigest = getCandidateDigest(donId, pluginType); + + if (existingDigest != digestToOverwrite) { + revert ConfigDigestMismatch(existingDigest, digestToOverwrite); + } + + // are we going to overwrite a config? If so, emit an event. + if (existingDigest != ZERO_DIGEST) { + emit CandidateConfigRevoked(digestToOverwrite); + } + + uint32 newVersion = ++s_currentVersion; + newConfigDigest = _calculateConfigDigest(donId, pluginType, abi.encode(config), newVersion); + + VersionedConfig storage existingConfig = s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)]; + existingConfig.configDigest = newConfigDigest; + existingConfig.version = newVersion; + existingConfig.config = config; + + emit ConfigSet(newConfigDigest, newVersion, config); + + return newConfigDigest; + } + + /// @notice Revokes a specific config by digest. + /// @param donId The key of the plugin to revoke the config for. + /// @param configDigest The digest of the config to revoke. This is done to prevent accidental revokes. + function revokeCandidate(uint32 donId, Internal.OCRPluginType pluginType, bytes32 configDigest) external { + _onlySelfCall(); + + if (configDigest == ZERO_DIGEST) { + revert RevokingZeroDigestNotAllowed(); + } + + uint256 candidateConfigIndex = _getCandidateIndex(donId, pluginType); + if (s_configs[donId][pluginType][candidateConfigIndex].configDigest != configDigest) { + revert ConfigDigestMismatch(s_configs[donId][pluginType][candidateConfigIndex].configDigest, configDigest); + } + + emit CandidateConfigRevoked(configDigest); + // Delete only the digest, as that's what's used to determine if a config is active. This means the actual + // config stays in storage which should significantly reduce the gas cost of overwriting that storage space in + // the future. + delete s_configs[donId][pluginType][candidateConfigIndex].configDigest; + } + + /// @notice Promotes the candidate config to the active config and revokes the active config. + /// @param donId The key of the plugin to promote the config for. + /// @param digestToPromote The digest of the config to promote. + function promoteCandidateAndRevokeActive( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes32 digestToPromote, + bytes32 digestToRevoke + ) external { + _onlySelfCall(); + + if (digestToPromote == ZERO_DIGEST && digestToRevoke == ZERO_DIGEST) { + revert NoOpStateTransitionNotAllowed(); + } + + uint256 candidateConfigIndex = _getCandidateIndex(donId, pluginType); + if (s_configs[donId][pluginType][candidateConfigIndex].configDigest != digestToPromote) { + revert ConfigDigestMismatch(s_configs[donId][pluginType][candidateConfigIndex].configDigest, digestToPromote); + } + + VersionedConfig storage activeConfig = s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)]; + if (activeConfig.configDigest != digestToRevoke) { + revert ConfigDigestMismatch(activeConfig.configDigest, digestToRevoke); + } + + delete activeConfig.configDigest; + + s_activeConfigIndexes[donId][pluginType] ^= 1; + if (digestToRevoke != ZERO_DIGEST) { + emit ActiveConfigRevoked(digestToRevoke); + } + emit ConfigPromoted(digestToPromote); + } + + /// @notice Calculates the config digest for a given plugin key, static config, and version. + /// @param donId The key of the plugin to calculate the digest for. + /// @param staticConfig The static part of the config. + /// @param version The version of the config. + /// @return The calculated config digest. + function _calculateConfigDigest( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes memory staticConfig, + uint32 version + ) internal view returns (bytes32) { + return bytes32( + (PREFIX & PREFIX_MASK) + | ( + uint256( + keccak256( + bytes.concat( + abi.encode(bytes32("EVM"), block.chainid, address(this), donId, pluginType, version), staticConfig + ) + ) + ) & ~PREFIX_MASK + ) + ); + } + + function _getActiveIndex(uint32 donId, Internal.OCRPluginType pluginType) private view returns (uint32) { + return s_activeConfigIndexes[donId][pluginType]; + } + + function _getCandidateIndex(uint32 donId, Internal.OCRPluginType pluginType) private view returns (uint32) { + return s_activeConfigIndexes[donId][pluginType] ^ 1; + } + + // ================================================================ + // │ Validation │ + // ================================================================ + + function _validateConfig( + OCR3Config memory cfg + ) internal view { + if (cfg.chainSelector == 0) revert ChainSelectorNotSet(); + if (cfg.pluginType != Internal.OCRPluginType.Commit && cfg.pluginType != Internal.OCRPluginType.Execution) { + revert InvalidPluginType(); + } + if (cfg.offrampAddress.length == 0 || keccak256(cfg.offrampAddress) == EMPTY_ENCODED_ADDRESS_HASH) { + revert OfframpAddressCannotBeZero(); + } + if (cfg.rmnHomeAddress.length == 0 || keccak256(cfg.rmnHomeAddress) == EMPTY_ENCODED_ADDRESS_HASH) { + revert RMNHomeAddressCannotBeZero(); + } + if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); + + // fChain cannot exceed FRoleDON, since it is a subcommittee in the larger DON + uint256 FRoleDON = cfg.FRoleDON; + uint256 fChain = s_chainConfigurations[cfg.chainSelector].fChain; + // fChain > 0 is enforced in applyChainConfigUpdates, and the presence of a chain config is checked above + // FRoleDON != 0 because FRoleDON >= fChain is enforced here + if (fChain > FRoleDON) { + revert FChainTooHigh(fChain, FRoleDON); + } + + // len(nodes) >= 3 * FRoleDON + 1 + // len(nodes) == numberOfSigners + uint256 numberOfNodes = cfg.nodes.length; + if (numberOfNodes > MAX_NUM_ORACLES) revert TooManySigners(); + if (numberOfNodes <= 3 * FRoleDON) revert FTooHigh(); + + uint256 nonZeroTransmitters = 0; + bytes32[] memory p2pIds = new bytes32[](numberOfNodes); + for (uint256 i = 0; i < numberOfNodes; ++i) { + OCR3Node memory node = cfg.nodes[i]; + + // 3 * fChain + 1 <= nonZeroTransmitters <= 3 * FRoleDON + 1 + // Transmitters can be set to 0 since there can be more signers than transmitters, + if (node.transmitterKey.length != 0) { + nonZeroTransmitters++; + } + + // Signer key and p2pIds must always be present + if (node.signerKey.length == 0 || node.p2pId == bytes32(0)) { + revert InvalidNode(node); + } + + p2pIds[i] = node.p2pId; + } + + // We check for chain config presence above, so fChain here must be non-zero. fChain <= FRoleDON due to the checks above. + // There can be less transmitters than signers - so they can be set to zero (which indicates that a node is a signer, but not a transmitter). + uint256 minTransmittersLength = 3 * fChain + 1; + if (nonZeroTransmitters < minTransmittersLength) { + revert NotEnoughTransmitters(nonZeroTransmitters, minTransmittersLength); + } + + // Check that the readers are in the capabilities registry. + _ensureInRegistry(p2pIds); + } + + function _onlySelfCall() internal view { + if (msg.sender != address(this)) { + revert CanOnlySelfCall(); + } + } + + // ================================================================ + // │ Chain Configuration │ + // ================================================================ + + /// @notice Returns the total number of chains configured. + /// @return The total number of chains configured. + function getNumChainConfigurations() external view returns (uint256) { + return s_remoteChainSelectors.length(); + } + + /// @notice Returns all the chain configurations. + /// @param pageIndex The page index. + /// @param pageSize The page size. + /// @return paginatedChainConfigs chain configurations. + function getAllChainConfigs(uint256 pageIndex, uint256 pageSize) external view returns (ChainConfigArgs[] memory) { + uint256 numberOfChains = s_remoteChainSelectors.length(); + uint256 startIndex = pageIndex * pageSize; + + if (pageSize == 0 || startIndex >= numberOfChains) { + return new ChainConfigArgs[](0); // Return an empty array if pageSize is 0 or pageIndex is out of bounds + } + + uint256 endIndex = startIndex + pageSize; + if (endIndex > numberOfChains) { + endIndex = numberOfChains; + } + + ChainConfigArgs[] memory paginatedChainConfigs = new ChainConfigArgs[](endIndex - startIndex); + + uint256[] memory chainSelectors = s_remoteChainSelectors.values(); + for (uint256 i = startIndex; i < endIndex; ++i) { + uint64 chainSelector = uint64(chainSelectors[i]); + paginatedChainConfigs[i - startIndex] = + ChainConfigArgs({chainSelector: chainSelector, chainConfig: s_chainConfigurations[chainSelector]}); + } + + return paginatedChainConfigs; + } + + /// @notice Sets and/or removes chain configurations. + /// Does not validate that fChain <= FRoleDON and relies on OCR3Configs to be changed in case fChain becomes larger than the FRoleDON value. + /// @param chainSelectorRemoves The chain configurations to remove. + /// @param chainConfigAdds The chain configurations to add. + function applyChainConfigUpdates( + uint64[] calldata chainSelectorRemoves, + ChainConfigArgs[] calldata chainConfigAdds + ) external onlyOwner { + // Process removals first. + for (uint256 i = 0; i < chainSelectorRemoves.length; ++i) { + // check if the chain selector is in s_remoteChainSelectors first. + if (!s_remoteChainSelectors.contains(chainSelectorRemoves[i])) { + revert ChainSelectorNotFound(chainSelectorRemoves[i]); + } + + delete s_chainConfigurations[chainSelectorRemoves[i]]; + s_remoteChainSelectors.remove(chainSelectorRemoves[i]); + + emit ChainConfigRemoved(chainSelectorRemoves[i]); + } + + // Process additions next. + for (uint256 i = 0; i < chainConfigAdds.length; ++i) { + ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; + uint64 chainSelector = chainConfigAdds[i].chainSelector; + + // Verify that the provided readers are present in the capabilities registry. + _ensureInRegistry(chainConfig.readers); + + // Verify that fChain is positive. + if (chainConfig.fChain == 0) { + revert FChainMustBePositive(); + } + + s_chainConfigurations[chainSelector] = chainConfig; + s_remoteChainSelectors.add(chainSelector); + + emit ChainConfigSet(chainSelector, chainConfig); + } + } + + /// @notice Helper function to ensure that a node is in the capabilities registry. + /// @param p2pIds The P2P IDs of the node to check. + function _ensureInRegistry( + bytes32[] memory p2pIds + ) internal view { + if (p2pIds.length != 0) { + INodeInfoProvider(i_capabilitiesRegistry).getNodesByP2PIds(p2pIds); + } + } +} diff --git a/contracts/src/v0.8/ccip/capability/interfaces/IOCR3ConfigEncoder.sol b/contracts/src/v0.8/ccip/capability/interfaces/IOCR3ConfigEncoder.sol deleted file mode 100644 index 6d0b0f72a5a..00000000000 --- a/contracts/src/v0.8/ccip/capability/interfaces/IOCR3ConfigEncoder.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {CCIPConfigTypes} from "../libraries/CCIPConfigTypes.sol"; - -/// @dev This is so that we can generate gethwrappers and easily encode/decode OCR3Config -/// in the offchain integration tests. -interface IOCR3ConfigEncoder { - /// @dev Encodes an array of OCR3Config into a bytes array. For test usage only. - function exposeOCR3Config(CCIPConfigTypes.OCR3Config[] calldata config) external view returns (bytes memory); -} diff --git a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol deleted file mode 100644 index 99adef84b10..00000000000 --- a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {Internal} from "../../libraries/Internal.sol"; - -library CCIPConfigTypes { - /// @notice ConfigState indicates the state of the configuration. - /// A DON's configuration always starts out in the "Init" state - this is the starting state. - /// The only valid transition from "Init" is to the "Running" state - this is the first ever configuration. - /// The only valid transition from "Running" is to the "Staging" state - this is a blue/green proposal. - /// The only valid transition from "Staging" is back to the "Running" state - this is a promotion. - /// TODO: explain rollbacks? - enum ConfigState { - Init, - Running, - Staging - } - - /// @notice Chain configuration. - /// Changes to chain configuration are detected out-of-band in plugins and decoded offchain. - struct ChainConfig { - bytes32[] readers; // The P2P IDs of the readers for the chain. These IDs must be registered in the capabilities registry. - uint8 fChain; // The fault tolerance parameter of the chain. - bytes config; // The chain configuration. This is kept intentionally opaque so as to add fields in the future if needed. - } - - /// @notice Chain configuration information struct used in applyChainConfigUpdates and getAllChainConfigs. - struct ChainConfigInfo { - uint64 chainSelector; - ChainConfig chainConfig; - } - - /// @notice OCR3 configuration. - struct OCR3Config { - Internal.OCRPluginType pluginType; // ────────╮ The plugin that the configuration is for. - uint64 chainSelector; // | The (remote) chain that the configuration is for. - uint8 F; // | The "big F" parameter for the role DON. - uint64 offchainConfigVersion; // ─────────────╯ The version of the offchain configuration. - bytes offrampAddress; // The remote chain offramp address. - // NOTE: bootstrapP2PIds and p2pIds should be sent as sorted sets - bytes32[] bootstrapP2PIds; // The bootstrap P2P IDs of the oracles that are part of the role DON. - // len(p2pIds) == len(signers) == len(transmitters) == 3 * F + 1 - // NOTE: indexes matter here! The p2p ID at index i corresponds to the signer at index i and the transmitter at index i. - // This is crucial in order to build the oracle ID <-> peer ID mapping offchain. - bytes32[] p2pIds; // The P2P IDs of the oracles that are part of the role DON. - bytes[] signers; // The onchain signing keys of nodes in the don. - bytes[] transmitters; // The onchain transmitter keys of nodes in the don. - bytes offchainConfig; // The offchain configuration for the OCR3 protocol. Protobuf encoded. - } - - /// @notice OCR3 configuration with metadata, specifically the config count and the config digest. - struct OCR3ConfigWithMeta { - OCR3Config config; // The OCR3 configuration. - uint64 configCount; // The config count used to compute the config digest. - bytes32 configDigest; // The config digest of the OCR3 configuration. - } -} diff --git a/contracts/src/v0.8/ccip/docs/multi-chain-overview-ocr3.png b/contracts/src/v0.8/ccip/docs/multi-chain-overview-ocr3.png index 39302619cb4..c0d5e2faf7d 100644 Binary files a/contracts/src/v0.8/ccip/docs/multi-chain-overview-ocr3.png and b/contracts/src/v0.8/ccip/docs/multi-chain-overview-ocr3.png differ diff --git a/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio b/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio index 5743bf5182e..785edfc2f55 100644 --- a/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio +++ b/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio @@ -1,6 +1,6 @@ - + - + @@ -1340,7 +1340,7 @@ - + @@ -1356,7 +1356,7 @@ - + @@ -1376,10 +1376,10 @@ - + - + @@ -1388,7 +1388,7 @@ - + @@ -1426,7 +1426,7 @@ - + @@ -1496,7 +1496,7 @@ - + @@ -1617,8 +1617,8 @@ - - + + @@ -1667,10 +1667,10 @@ - + - + @@ -1789,7 +1789,7 @@ - + @@ -1810,7 +1810,7 @@ - + @@ -1862,7 +1862,7 @@ - + @@ -1880,7 +1880,7 @@ - + @@ -1908,7 +1908,7 @@ - + @@ -1926,11 +1926,8 @@ - - - - - + + @@ -1987,12 +1984,6 @@ - - - - - - @@ -2030,10 +2021,10 @@ - + - + @@ -2051,9 +2042,21 @@ - + + + + + + + + + + + + + diff --git a/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol b/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol index 6305311050d..2a38d82739e 100644 --- a/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol +++ b/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol @@ -11,5 +11,7 @@ interface IAny2EVMMessageReceiver { /// will move to a FAILED state and become available for manual execution. /// @param message CCIP Message /// @dev Note ensure you check the msg.sender is the OffRampRouter - function ccipReceive(Client.Any2EVMMessage calldata message) external; + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external; } diff --git a/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol b/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol index 1881dede2ee..f18c6a73f5e 100644 --- a/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol +++ b/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol @@ -5,5 +5,7 @@ interface IAny2EVMOffRamp { /// @notice Returns the the current nonce for a receiver. /// @param sender The sender address /// @return nonce The nonce value belonging to the sender address. - function getSenderNonce(address sender) external view returns (uint64 nonce); + function getSenderNonce( + address sender + ) external view returns (uint64 nonce); } diff --git a/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol b/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol index d657e148cb2..c2d0d6cdb2c 100644 --- a/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol +++ b/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol @@ -11,5 +11,7 @@ interface IEVM2AnyOnRamp is IEVM2AnyOnRampClient { /// @notice Get the next nonce for a given sender /// @param sender The sender to get the nonce for /// @return nonce The next nonce for the sender - function getSenderNonce(address sender) external view returns (uint64 nonce); + function getSenderNonce( + address sender + ) external view returns (uint64 nonce); } diff --git a/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol b/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol index 1744d6c2295..d2fe34721b2 100644 --- a/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol +++ b/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol @@ -23,7 +23,9 @@ interface IEVM2AnyOnRampClient { /// @notice Gets a list of all supported source chain tokens. /// @param destChainSelector The destination chain selector /// @return tokens The addresses of all tokens that this onRamp supports the given destination chain - function getSupportedTokens(uint64 destChainSelector) external view returns (address[] memory tokens); + function getSupportedTokens( + uint64 destChainSelector + ) external view returns (address[] memory tokens); /// @notice Send a message to the remote chain /// @dev only callable by the Router @@ -33,6 +35,7 @@ interface IEVM2AnyOnRampClient { /// @param message Message struct to send /// @param feeTokenAmount Amount of fee tokens for payment /// @param originalSender The original initiator of the CCIP request + /// @return messageId The message id function forwardFromRouter( uint64 destChainSelector, Client.EVM2AnyMessage memory message, diff --git a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol new file mode 100644 index 00000000000..84d430410b2 --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {IPriceRegistry} from "./IPriceRegistry.sol"; + +interface IFeeQuoter is IPriceRegistry { + /// @notice Validates the ccip message & returns the fee + /// @param destChainSelector The destination chain selector. + /// @param message The message to get quote for. + /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. + function getValidatedFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount); + + /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels + /// @notice Validates pool return data + /// @param destChainSelector destination chain selector to process + /// @param feeToken Fee token address used to pay for message fees + /// @param feeTokenAmount Fee token amount + /// @param extraArgs Message extra args that were passed in by the client + /// @param onRampTokenTransfers Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + /// @return msgFeeJuels message fee in juels + /// @return isOutOfOrderExecution true if the message should be executed out of order + /// @return convertedExtraArgs extra args converted to the latest family-specific args version + /// @return destExecDataPerToken Destination chain execution data + function processMessageArgs( + uint64 destChainSelector, + address feeToken, + uint256 feeTokenAmount, + bytes memory extraArgs, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) + external + view + returns ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ); +} diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol b/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol index c2b432426b6..0432a222df7 100644 --- a/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol +++ b/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol @@ -13,7 +13,9 @@ interface IMessageInterceptor { /// @notice Intercepts & validates the given OffRamp message. Reverts on validation failure /// @param message to validate - function onInboundMessage(Client.Any2EVMMessage memory message) external; + function onInboundMessage( + Client.Any2EVMMessage memory message + ) external; /// @notice Intercepts & validates the given OnRamp message. Reverts on validation failure /// @param destChainSelector remote destination chain selector where the message is being sent to diff --git a/contracts/src/v0.8/ccip/interfaces/INonceManager.sol b/contracts/src/v0.8/ccip/interfaces/INonceManager.sol index 52408ae4f57..3a6eff65c77 100644 --- a/contracts/src/v0.8/ccip/interfaces/INonceManager.sol +++ b/contracts/src/v0.8/ccip/interfaces/INonceManager.sol @@ -3,18 +3,18 @@ pragma solidity ^0.8.0; /// @notice Contract interface that allows managing sender nonces interface INonceManager { - /// @notice Increments the outbound nonce for a given sender on a given destination chain - /// @param destChainSelector The destination chain selector - /// @param sender The sender address - /// @return The new outbound nonce + /// @notice Increments the outbound nonce for a given sender on a given destination chain. + /// @param destChainSelector The destination chain selector. + /// @param sender The sender address. + /// @return incrementedOutboundNonce The new outbound nonce. function getIncrementedOutboundNonce(uint64 destChainSelector, address sender) external returns (uint64); - /// @notice Increments the inbound nonce for a given sender on a given source chain - /// @notice The increment is only applied if the resulting nonce matches the expectedNonce - /// @param sourceChainSelector The destination chain selector - /// @param expectedNonce The expected inbound nonce - /// @param sender The encoded sender address - /// @return True if the nonce was incremented, false otherwise + /// @notice Increments the inbound nonce for a given sender on a given source chain. + /// @notice The increment is only applied if the resulting nonce matches the expectedNonce. + /// @param sourceChainSelector The destination chain selector. + /// @param expectedNonce The expected inbound nonce. + /// @param sender The encoded sender address. + /// @return incremented True if the nonce was incremented, false otherwise. function incrementInboundNonce( uint64 sourceChainSelector, uint64 expectedNonce, diff --git a/contracts/src/v0.8/ccip/interfaces/IPool.sol b/contracts/src/v0.8/ccip/interfaces/IPool.sol index 5d5c95e03c7..3545e57fa42 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPool.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPool.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {Pool} from "../libraries/Pool.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; /// @notice Shared public interface for multiple V1 pool types. /// Each pool type handles a different child token model (lock/unlock, mint/burn.) @@ -11,25 +11,31 @@ interface IPoolV1 is IERC165 { /// @notice Lock tokens into the pool or burn the tokens. /// @param lockOrBurnIn Encoded data fields for the processing of tokens on the source chain. /// @return lockOrBurnOut Encoded data fields for the processing of tokens on the destination chain. - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut); + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut); /// @notice Releases or mints tokens to the receiver address. /// @param releaseOrMintIn All data required to release or mint tokens. /// @return releaseOrMintOut The amount of tokens released or minted on the local chain, denominated /// in the local token's decimals. - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - returns (Pool.ReleaseOrMintOutV1 memory); + /// @dev The offramp asserts that the balanceOf of the receiver has been incremented by exactly the number + /// of tokens that is returned in ReleaseOrMintOutV1.destinationAmount. If the amounts do not match, the tx reverts. + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external returns (Pool.ReleaseOrMintOutV1 memory); /// @notice Checks whether a remote chain is supported in the token pool. /// @param remoteChainSelector The selector of the remote chain. /// @return true if the given chain is a permissioned remote chain. - function isSupportedChain(uint64 remoteChainSelector) external view returns (bool); + function isSupportedChain( + uint64 remoteChainSelector + ) external view returns (bool); /// @notice Returns if the token pool supports the given token. /// @param token The address of the token. /// @return true if the token is supported by the pool. - function isSupportedToken(address token) external view returns (bool); + function isSupportedToken( + address token + ) external view returns (bool); } diff --git a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol index 8a20299371f..b20c1b7229a 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -1,39 +1,35 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; -import {Client} from "../libraries/Client.sol"; import {Internal} from "../libraries/Internal.sol"; interface IPriceRegistry { - /// @notice Token price data feed configuration - struct TokenPriceFeedConfig { - address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) - uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents - } - /// @notice Update the price for given tokens and gas prices for given chains. /// @param priceUpdates The price updates to apply. - function updatePrices(Internal.PriceUpdates memory priceUpdates) external; + function updatePrices( + Internal.PriceUpdates memory priceUpdates + ) external; /// @notice Get the `tokenPrice` for a given token. /// @param token The token to get the price for. /// @return tokenPrice The tokenPrice for the given token. - function getTokenPrice(address token) external view returns (Internal.TimestampedPackedUint224 memory); + function getTokenPrice( + address token + ) external view returns (Internal.TimestampedPackedUint224 memory); /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. /// @param token The token to get the price for. /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. - function getValidatedTokenPrice(address token) external view returns (uint224); + function getValidatedTokenPrice( + address token + ) external view returns (uint224); /// @notice Get the `tokenPrice` for an array of tokens. /// @param tokens The tokens to get prices for. /// @return tokenPrices The tokenPrices for the given tokens. - function getTokenPrices(address[] calldata tokens) external view returns (Internal.TimestampedPackedUint224[] memory); - - /// @notice Returns the token price data feed configuration - /// @param token The token to retrieve the feed config for - /// @return dataFeedAddress The token price data feed config (if feed address is 0, the feed config is disabled) - function getTokenPriceFeedConfig(address token) external view returns (TokenPriceFeedConfig memory); + function getTokenPrices( + address[] calldata tokens + ) external view returns (Internal.TimestampedPackedUint224[] memory); /// @notice Get an encoded `gasPrice` for a given destination chain ID. /// The 224-bit result encodes necessary gas price components. @@ -43,10 +39,9 @@ interface IPriceRegistry { /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. /// @param destChainSelector The destination chain to get the price for. /// @return gasPrice The encoded gasPrice for the given destination chain ID. - function getDestinationChainGasPrice(uint64 destChainSelector) - external - view - returns (Internal.TimestampedPackedUint224 memory); + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view returns (Internal.TimestampedPackedUint224 memory); /// @notice Gets the fee token price and the gas price, both denominated in dollars. /// @param token The source token to get the price for. @@ -70,40 +65,6 @@ interface IPriceRegistry { ) external view returns (uint256 toTokenAmount); /// @notice Get the list of fee tokens. - /// @return The tokens set as fee tokens. + /// @return feeTokens The tokens set as fee tokens. function getFeeTokens() external view returns (address[] memory); - - /// @notice Validates the ccip message & returns the fee - /// @param destChainSelector The destination chain selector. - /// @param message The message to get quote for. - /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. - function getValidatedFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount); - - /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels - /// @param destChainSelector destination chain selector to process - /// @param feeToken Fee token address used to pay for message fees - /// @param feeTokenAmount Fee token amount - /// @param extraArgs Message extra args that were passed in by the client - /// @return msgFeeJuels message fee in juels - /// @return isOutOfOrderExecution true if the message should be executed out of order - /// @return convertedExtraArgs extra args converted to the latest family-specific args version - function processMessageArgs( - uint64 destChainSelector, - address feeToken, - uint256 feeTokenAmount, - bytes memory extraArgs - ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs); - - /// @notice Validates pool return data - /// @param destChainSelector Destination chain selector to which the token amounts are sent to - /// @param rampTokenAmounts Token amounts with populated pool return data - /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message - function validatePoolReturnData( - uint64 destChainSelector, - Internal.RampTokenAmount[] calldata rampTokenAmounts, - Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view; } diff --git a/contracts/src/v0.8/ccip/interfaces/IRMN.sol b/contracts/src/v0.8/ccip/interfaces/IRMN.sol index a409731549f..4bd8f8348fe 100644 --- a/contracts/src/v0.8/ccip/interfaces/IRMN.sol +++ b/contracts/src/v0.8/ccip/interfaces/IRMN.sol @@ -10,12 +10,16 @@ interface IRMN { } /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. - function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool); + function isBlessed( + TaggedRoot calldata taggedRoot + ) external view returns (bool); /// @notice Iff there is an active global or legacy curse, this function returns true. function isCursed() external view returns (bool); /// @notice Iff there is an active global curse, or an active curse for `subject`, this function returns true. /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). - function isCursed(bytes16 subject) external view returns (bool); + function isCursed( + bytes16 subject + ) external view returns (bool); } diff --git a/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol b/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol new file mode 100644 index 00000000000..3754a2fe918 --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Internal} from "../libraries/Internal.sol"; + +/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. +interface IRMNRemote { + /// @notice signature components from RMN nodes + struct Signature { + bytes32 r; + bytes32 s; + } + + /// @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 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 + /// @param rawVs rmnNodes ECDSA sigs, part v bitmap + /// @dev Will revert if verification fails + function verify( + address offRampAddress, + Internal.MerkleRoot[] memory merkleRoots, + Signature[] memory signatures, + uint256 rawVs + ) external view; + + /// @notice gets the current set of cursed subjects + /// @return subjects the list of cursed subjects + function getCursedSubjects() external view returns (bytes16[] memory subjects); + + /// @notice If there is an active global or legacy curse, this function returns true. + /// @return bool true if there is an active global curse + function isCursed() external view returns (bool); + + /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. + /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + /// @return bool true if the provided subject is cured *or* if there is an active global curse + function isCursed( + bytes16 subject + ) external view returns (bool); +} diff --git a/contracts/src/v0.8/ccip/interfaces/IRouter.sol b/contracts/src/v0.8/ccip/interfaces/IRouter.sol index 7f4544fd0fa..d8f19bf5dfa 100644 --- a/contracts/src/v0.8/ccip/interfaces/IRouter.sol +++ b/contracts/src/v0.8/ccip/interfaces/IRouter.sol @@ -26,7 +26,9 @@ interface IRouter { /// @notice Returns the configured onramp for a specific destination chain. /// @param destChainSelector The destination chain Id to get the onRamp for. /// @return onRampAddress The address of the onRamp. - function getOnRamp(uint64 destChainSelector) external view returns (address onRampAddress); + function getOnRamp( + uint64 destChainSelector + ) external view returns (address onRampAddress); /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. /// @param sourceChainSelector The source chain selector to check. diff --git a/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol b/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol index 9805a41bbdc..36218b36b3e 100644 --- a/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol +++ b/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {Client} from "../libraries/Client.sol"; @@ -11,7 +11,9 @@ interface IRouterClient { /// @notice Checks if the given chain ID is supported for sending/receiving. /// @param destChainSelector The chain to check. /// @return supported is true if it is supported, false if not. - function isChainSupported(uint64 destChainSelector) external view returns (bool supported); + function isChainSupported( + uint64 destChainSelector + ) external view returns (bool supported); /// @param destinationChainSelector The destination chainSelector /// @param message The cross-chain CCIP message including data and/or tokens diff --git a/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol b/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol index 0e441229011..04bacbac5a0 100644 --- a/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol @@ -3,7 +3,9 @@ pragma solidity ^0.8.0; interface ITokenAdminRegistry { /// @notice Returns the pool for the given token. - function getPool(address token) external view returns (address); + function getPool( + address token + ) external view returns (address); /// @notice Proposes an administrator for the given token as pending administrator. /// @param localToken The token to register the administrator for. diff --git a/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol b/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol index 4225827a612..f4f824361e0 100644 --- a/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol +++ b/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol @@ -6,5 +6,7 @@ import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ interface IWrappedNative is IERC20 { function deposit() external payable; - function withdraw(uint256 wad) external; + function withdraw( + uint256 wad + ) external; } diff --git a/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol b/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol new file mode 100644 index 00000000000..a5792f19550 --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BUSL-1.1 +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 { + /// @dev the RMN Report struct is used in integration / E2E tests + function exposeRmnReport(bytes32 rmnReportVersion, RMNRemote.Report memory rmnReport) external; + + /// @dev the OCR3Config Config struct is used in integration / E2E tests + function exposeOCR3Config( + CCIPHome.OCR3Config[] calldata config + ) external view returns (bytes memory); + + /// @dev used to encode commit reports for onchain transmission. + function exposeCommitReport( + OffRamp.CommitReport memory commitReport + ) external view returns (bytes memory); +} diff --git a/contracts/src/v0.8/ccip/libraries/Client.sol b/contracts/src/v0.8/ccip/libraries/Client.sol index a985371bef1..de1f6f1580f 100644 --- a/contracts/src/v0.8/ccip/libraries/Client.sol +++ b/contracts/src/v0.8/ccip/libraries/Client.sol @@ -33,7 +33,9 @@ library Client { uint256 gasLimit; } - function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { + function _argsToBytes( + EVMExtraArgsV1 memory extraArgs + ) internal pure returns (bytes memory bts) { return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); } @@ -49,7 +51,9 @@ library Client { bool allowOutOfOrderExecution; } - function _argsToBytes(EVMExtraArgsV2 memory extraArgs) internal pure returns (bytes memory bts) { + function _argsToBytes( + EVMExtraArgsV2 memory extraArgs + ) internal pure returns (bytes memory bts) { return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs); } } diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index db2bc05ee53..f029fbcbb31 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; -import {Client} from "./Client.sol"; // Library for CCIP internal definitions common to multiple contracts. library Internal { @@ -16,6 +15,8 @@ library Internal { // malicious contracts from returning large amounts of data and causing // repeated out-of-gas scenarios. uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32; + /// @dev The expected number of bytes returned by the balanceOf function. + uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32; /// @notice A collection of token price and gas price updates. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. @@ -40,8 +41,8 @@ library Internal { /// @notice A timestamped uint224 value that can contain several tightly packed fields. struct TimestampedPackedUint224 { - uint224 value; // ───────╮ Value in uint224, packed. - uint32 timestamp; // ────╯ Timestamp of the most recent price update. + uint224 value; // ──────╮ Value in uint224, packed. + uint32 timestamp; // ───╯ Timestamp of the most recent price update. } /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices. @@ -49,11 +50,6 @@ library Internal { /// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning. uint8 public constant GAS_PRICE_BITS = 112; - struct PoolUpdate { - address token; // The IERC20 token address - address pool; // The token pool address - } - struct SourceTokenData { // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be // relied upon by the destination pool to validate the source pool. @@ -65,11 +61,12 @@ library Internal { // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead // has to be set for the specific token. bytes extraData; + uint32 destGasAmount; // The amount of gas available for the releaseOrMint and balanceOf calls on the offRamp } /// @notice Report that is submitted by the execution DON at the execution phase. (including chain selector data) /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct ExecutionReportSingleChain { + struct ExecutionReport { uint64 sourceChainSelector; // Source chain selector for which the report is submitted Any2EVMRampMessage[] messages; // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token @@ -78,92 +75,26 @@ library Internal { uint256 proofFlagBits; } - /// @notice Report that is submitted by the execution DON at the execution phase. - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct ExecutionReport { - EVM2EVMMessage[] messages; - // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token - bytes[][] offchainTokenData; - bytes32[] proofs; - uint256 proofFlagBits; - } - - /// @notice The cross chain message that gets committed to EVM chains. - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct EVM2EVMMessage { - uint64 sourceChainSelector; // ───────────╮ the chain selector of the source chain, note: not chainId - address sender; // ───────────────────────╯ sender address on the source chain - address receiver; // ─────────────────────╮ receiver address on the destination chain - uint64 sequenceNumber; // ────────────────╯ sequence number, not unique across lanes - uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution - bool strict; // ──────────────────────────╮ DEPRECATED - uint64 nonce; // │ nonce for this lane for this sender, not unique across senders/lanes - address feeToken; // ─────────────────────╯ fee token - uint256 feeTokenAmount; // fee token amount - bytes data; // arbitrary data payload supplied by the message sender - Client.EVMTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer - bytes[] sourceTokenData; // array of token data, one per token - bytes32 messageId; // a hash of the message data - } - - /// @dev EVM2EVMMessage struct has 13 fields, including 3 variable arrays. - /// Each variable array takes 1 more slot to store its length. - /// When abi encoded, excluding array contents, - /// EVM2EVMMessage takes up a fixed number of 16 lots, 32 bytes each. - /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 17. - uint256 public constant MESSAGE_FIXED_BYTES = 32 * 17; - - /// @dev Each token transfer adds 1 EVMTokenAmount and 1 bytes. - /// When abiEncoded, each EVMTokenAmount takes 2 slots, each bytes takes 2 slots, excl bytes contents - uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 4; - - /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, receiver and tokenAmounts). + /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (sender, data and tokenAmounts). /// Each variable array takes 1 more slot to store its length. /// When abi encoded, excluding array contents, /// Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each. + /// Assume 1 slot for sender /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14. - /// The fixed bytes does not cover struct data (this is represented by ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) - uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES = 32 * 14; + /// The fixed bytes does not cover struct data (this is represented by MESSAGE_FIXED_BYTES_PER_TOKEN) + uint256 public constant MESSAGE_FIXED_BYTES = 32 * 15; - /// @dev Each token transfer adds 1 RampTokenAmount - /// RampTokenAmount has 4 fields, including 3 bytes. - /// Each bytes takes 1 more slot to store its length. - /// When abi encoded, each token transfer takes up 7 slots, excl bytes contents. - uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 7; - - bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2"); - - /// @dev Used to hash messages for single-lane ramps. - /// OnRamp hash(EVM2EVMMessage) = OffRamp hash(EVM2EVMMessage) - /// The EVM2EVMMessage's messageId is expected to be the output of this hash function - /// @param original Message to hash - /// @param metadataHash Immutable metadata hash representing a lane with a fixed OnRamp - /// @return hashedMessage hashed message as a keccak256 - function _hash(EVM2EVMMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { - // Fixed-size message fields are included in nested hash to reduce stack pressure. - // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. - return keccak256( - abi.encode( - MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, - metadataHash, - keccak256( - abi.encode( - original.sender, - original.receiver, - original.sequenceNumber, - original.gasLimit, - original.strict, - original.nonce, - original.feeToken, - original.feeTokenAmount - ) - ), - keccak256(original.data), - keccak256(abi.encode(original.tokenAmounts)), - keccak256(abi.encode(original.sourceTokenData)) - ) - ); - } + /// @dev Any2EVMTokensTransfer struct bytes length + /// 0x20 + /// sourcePoolAddress_offset + /// destTokenAddress + /// destGasAmount + /// extraData_offset + /// amount + /// sourcePoolAddress_length + /// sourcePoolAddress_content // assume 1 slot + /// extraData_length // contents billed separately + uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * (4 + (3 + 2)); bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); bytes32 internal constant EVM_2_ANY_MESSAGE_HASH = keccak256("EVM2AnyMessageHashV1"); @@ -172,30 +103,25 @@ library Internal { /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId /// OnRamp hash(EVM2AnyMessage) != OffRamp hash(Any2EVMRampMessage) /// @param original OffRamp message to hash - /// @param onRamp OnRamp to hash the message with - used to compute the metadataHash + /// @param metadataHash Hash preimage to ensure global uniqueness /// @return hashedMessage hashed message as a keccak256 - function _hash(Any2EVMRampMessage memory original, bytes memory onRamp) internal pure returns (bytes32) { + function _hash(Any2EVMRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { // Fixed-size message fields are included in nested hash to reduce stack pressure. // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. return keccak256( abi.encode( MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, - // Implicit metadata hash - keccak256( - abi.encode( - ANY_2_EVM_MESSAGE_HASH, original.header.sourceChainSelector, original.header.destChainSelector, onRamp - ) - ), + metadataHash, keccak256( abi.encode( original.header.messageId, - original.sender, original.receiver, original.header.sequenceNumber, original.gasLimit, original.header.nonce ) ), + keccak256(original.sender), keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)) ) @@ -212,13 +138,13 @@ library Internal { keccak256( abi.encode( original.sender, - original.receiver, original.header.sequenceNumber, original.header.nonce, original.feeToken, original.feeTokenAmount ) ), + keccak256(original.receiver), keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)), keccak256(original.extraArgs) @@ -226,15 +152,21 @@ library Internal { ); } - /// @dev We disallow the first 1024 addresses to never allow calling precompiles. It is extremely unlikely that - /// anyone would ever be able to generate an address in this range. + /// @dev We disallow the first 1024 addresses to avoid calling into a range known for hosting precompiles. Calling + /// into precompiles probably won't cause any issues, but to be safe we can disallow this range. It is extremely + /// unlikely that anyone would ever be able to generate an address in this range. There is no official range of + /// precompiles, but EIP-7587 proposes to reserve the range 0x100 to 0x1ff. Our range is more conservative, even + /// though it might not be exhaustive for all chains, which is OK. We also disallow the zero address, which is a + /// common practice. uint256 public constant PRECOMPILE_SPACE = 1024; /// @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) { + function _validateEVMAddress( + bytes memory encodedAddress + ) internal pure returns (address) { if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress); uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256)); if (encodedAddressUint > type(uint160).max || encodedAddressUint < PRECOMPILE_SPACE) { @@ -263,12 +195,21 @@ library Internal { Execution } - /// @notice Family-agnostic token amounts used for both OnRamp & OffRamp messages - struct RampTokenAmount { - // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be + /// @notice Family-agnostic header for OnRamp & OffRamp messages. + /// The messageId is not expected to match hash(message), since it may originate from another ramp family + struct RampMessageHeader { + bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded) + uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId + uint64 destChainSelector; // │ the chain selector of the destination chain, note: not chainId + uint64 sequenceNumber; // │ sequence number, not unique across lanes + uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes + } + + struct EVM2AnyTokenTransfer { + // The source pool EVM address. This value is trusted as it was obtained through the onRamp. It can be // relied upon by the destination pool to validate the source pool. - bytes sourcePoolAddress; - // The address of the destination token, abi encoded in the case of EVM chains + address sourcePoolAddress; + // The EVM address of the destination token // This value is UNTRUSTED as any pool owner can return whatever value they want. bytes destTokenAddress; // Optional pool data to be transferred to the destination chain. Be default this is capped at @@ -276,16 +217,23 @@ library Internal { // has to be set for the specific token. bytes extraData; uint256 amount; // Amount of tokens. + // Destination chain specific execution data encoded in bytes + // for an EVM destination, it consists of the amount of gas available for the releaseOrMint + // and transfer calls made by the offRamp + bytes destExecData; } - /// @notice Family-agnostic header for OnRamp & OffRamp messages. - /// The messageId is not expected to match hash(message), since it may originate from another ramp family - struct RampMessageHeader { - bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded) - uint64 sourceChainSelector; // ───────╮ the chain selector of the source chain, note: not chainId - uint64 destChainSelector; // | the chain selector of the destination chain, note: not chainId - uint64 sequenceNumber; // │ sequence number, not unique across lanes - uint64 nonce; // ─────────────────────╯ nonce for this lane for this sender, not unique across senders/lanes + struct Any2EVMTokenTransfer { + // The source pool EVM address encoded to bytes. This value is trusted as it is obtained through the onRamp. It can be + // relied upon by the destination pool to validate the source pool. + bytes sourcePoolAddress; + address destTokenAddress; // ───╮ Address of destination token + uint32 destGasAmount; //────────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. + // Optional pool data to be transferred to the destination chain. Be default this is capped at + // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead + // has to be set for the specific token. + bytes extraData; + uint256 amount; // Amount of tokens. } /// @notice Family-agnostic message routed to an OffRamp @@ -297,7 +245,7 @@ library Internal { bytes data; // arbitrary data payload supplied by the message sender address receiver; // receiver address on the destination chain uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution - RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer + Any2EVMTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer } /// @notice Family-agnostic message emitted from the OnRamp @@ -311,9 +259,22 @@ library Internal { bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains address feeToken; // fee token uint256 feeTokenAmount; // fee token amount - RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer + uint256 feeValueJuels; // fee amount in Juels + EVM2AnyTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer } // bytes4(keccak256("CCIP ChainFamilySelector EVM")) bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + + /// @dev Struct to hold a merkle root and an 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. + // solhint-disable-next-line gas-struct-packing + struct MerkleRoot { + uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to + bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode + uint64 minSeqNr; // ──────────╮ Minimum sequence number, inclusive + uint64 maxSeqNr; // ──────────╯ Maximum sequence number, inclusive + bytes32 merkleRoot; // Merkle root covering the interval & source chain messages + } } diff --git a/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol b/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol index fed8a1165bb..95f52bdc528 100644 --- a/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol +++ b/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; library MerkleMultiProof { /// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage. diff --git a/contracts/src/v0.8/ccip/libraries/Pool.sol b/contracts/src/v0.8/ccip/libraries/Pool.sol index 3f1895dcf5a..391beb00c18 100644 --- a/contracts/src/v0.8/ccip/libraries/Pool.sol +++ b/contracts/src/v0.8/ccip/libraries/Pool.sol @@ -14,7 +14,7 @@ library Pool { // The default max number of bytes in the return data for a pool v1 lockOrBurn call. // This data can be used to send information to the destination chain token pool. Can be overwritten // in the TokenTransferFeeConfig.destBytesOverhead if more data is required. - uint256 public constant CCIP_LOCK_OR_BURN_V1_RET_BYTES = 32; + uint32 public constant CCIP_LOCK_OR_BURN_V1_RET_BYTES = 32; struct LockOrBurnInV1 { bytes receiver; // The recipient of the tokens on the destination chain, abi encoded @@ -25,7 +25,7 @@ library Pool { } struct LockOrBurnOutV1 { - // The address of the destination token pool, abi encoded in the case of EVM chains + // The address of the destination token, abi encoded in the case of EVM chains // This value is UNTRUSTED as any pool owner can return whatever value they want. bytes destTokenAddress; // Optional pool data to be transferred to the destination chain. Be default this is capped at @@ -37,8 +37,7 @@ library Pool { struct ReleaseOrMintInV1 { bytes originalSender; // The original sender of the tx on the source chain uint64 remoteChainSelector; // ─╮ The chain ID of the source chain - address receiver; // ───────────╯ The recipient of the tokens on the destination chain. This is *NOT* the address to - // send the tokens to, but the address that will receive the tokens via the offRamp. + address receiver; // ───────────╯ The recipient of the tokens on the destination chain. uint256 amount; // The amount of tokens to release or mint, denominated in the source token's decimals address localToken; // The address on this chain of the token to release or mint /// @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the diff --git a/contracts/src/v0.8/ccip/libraries/RateLimiter.sol b/contracts/src/v0.8/ccip/libraries/RateLimiter.sol index 40ac3ca213e..431b7728164 100644 --- a/contracts/src/v0.8/ccip/libraries/RateLimiter.sol +++ b/contracts/src/v0.8/ccip/libraries/RateLimiter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; /// @notice Implements Token Bucket rate limiting. /// @dev uint128 is safe for rate limiter state. @@ -85,7 +85,9 @@ library RateLimiter { /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function _currentTokenBucketState(TokenBucket memory bucket) internal view returns (TokenBucket memory) { + function _currentTokenBucketState( + TokenBucket memory bucket + ) internal view returns (TokenBucket memory) { // We update the bucket to reflect the status at the exact time of the // call. This means we might need to refill a part of the bucket based // on the time that has passed since the last update. diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index 1872ae276ce..62665f4a2a0 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; @@ -8,9 +8,9 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; /// with multiple OCR plugin support. abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; + uint256 internal constant MAX_NUM_ORACLES = 256; - /// @notice triggers a new run of the offchain reporting protocol + /// @notice Triggers a new run of the offchain reporting protocol /// @param ocrPluginType OCR plugin type for which the config was set /// @param configDigest configDigest of this configuration /// @param signers ith element is address ith oracle uses to sign a report @@ -18,7 +18,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { /// @param F maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly event ConfigSet(uint8 ocrPluginType, bytes32 configDigest, address[] signers, address[] transmitters, uint8 F); - /// @notice optionally emitted to indicate the latest configDigest and sequence number + /// @notice Optionally emitted to indicate the latest configDigest and sequence number /// for which a report was successfully transmitted. Alternatively, the contract may /// use latestConfigDigestAndEpoch with scanLogs set to false. event Transmitted(uint8 indexed ocrPluginType, bytes32 configDigest, uint64 sequenceNumber); @@ -28,7 +28,8 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { TOO_MANY_TRANSMITTERS, TOO_MANY_SIGNERS, F_TOO_HIGH, - REPEATED_ORACLE_ADDRESS + REPEATED_ORACLE_ADDRESS, + NO_TRANSMITTERS } error InvalidConfig(InvalidConfigErrorType errorType); @@ -71,14 +72,15 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { Role role; // ─────╯ Role of the address which mapped to this struct } - /// @notice OCR configuration for a single OCR plugin within a DON + /// @notice OCR configuration for a single OCR plugin within a DON. struct OCRConfig { ConfigInfo configInfo; // latest OCR config + // NOTE: len(signers) can be different from len(transmitters). There is no index relationship between the two arrays address[] signers; // addresses oracles use to sign the reports address[] transmitters; // addresses oracles use to transmit the reports } - /// @notice Args to update an OCR Config + /// @notice Args to update an OCR Config. struct OCRConfigArgs { bytes32 configDigest; // Config digest to update to uint8 ocrPluginType; // ──────────────────╮ OCR plugin type to update config for @@ -98,15 +100,15 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // See the "If we wanted to call sam" example on for example reasoning // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - /// @notice constant length component for transmit functions with no signatures. - /// The signatures are expected to match transmitPlugin(reportContext, report) + /// @notice Constant length component for transmit functions with no signatures. + /// The signatures are expected to match transmitPlugin(reportContext, report). uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES = 4 // function selector + 3 * 32 // 3 words containing reportContext + 32 // word containing start location of abiencoded report value + 32; // word containing length of report - /// @notice extra constant length component for transmit functions with signatures (relative to no signatures) - /// The signatures are expected to match transmitPlugin(reportContext, report, rs, ss, rawVs) + /// @notice Extra constant length component for transmit functions with signatures (relative to no signatures). + /// The signatures are expected to match transmitPlugin(reportContext, report, rs, ss, rawVs). uint16 private constant TRANSMIT_MSGDATA_EXTRA_CONSTANT_LENGTH_COMPONENT_FOR_SIGNATURES = 32 // word containing location start of abiencoded rs value + 32 // word containing start location of abiencoded ss value + 32 // rawVs value @@ -119,19 +121,26 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { i_chainID = block.chainid; } - /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @notice Sets offchain reporting protocol configuration incl. participating oracles. /// NOTE: The OCR3 config must be sanity-checked against the home-chain registry configuration, to ensure /// home-chain and remote-chain parity! - /// @param ocrConfigArgs OCR config update args - function setOCR3Configs(OCRConfigArgs[] memory ocrConfigArgs) external onlyOwner { + /// @param ocrConfigArgs OCR config update args. + /// @dev precondition number of transmitters should match the expected F/fChain relationship. + /// For transmitters, the function only validates that len(transmitters) > 0 && len(transmitters) <= MAX_NUM_ORACLES + /// && len(transmitters) <= len(signers) [if sig verification is enabled] + function setOCR3Configs( + OCRConfigArgs[] memory ocrConfigArgs + ) external onlyOwner { for (uint256 i; i < ocrConfigArgs.length; ++i) { _setOCR3Config(ocrConfigArgs[i]); } } - /// @notice sets offchain reporting protocol configuration incl. participating oracles for a single OCR plugin type - /// @param ocrConfigArgs OCR config update args - function _setOCR3Config(OCRConfigArgs memory ocrConfigArgs) internal { + /// @notice Sets offchain reporting protocol configuration incl. participating oracles for a single OCR plugin type. + /// @param ocrConfigArgs OCR config update args. + function _setOCR3Config( + OCRConfigArgs memory ocrConfigArgs + ) internal { if (ocrConfigArgs.F == 0) revert InvalidConfig(InvalidConfigErrorType.F_MUST_BE_POSITIVE); uint8 ocrPluginType = ocrConfigArgs.ocrPluginType; @@ -141,15 +150,15 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // If F is 0, then the config is not yet set if (configInfo.F == 0) { configInfo.isSignatureVerificationEnabled = ocrConfigArgs.isSignatureVerificationEnabled; - } else if (configInfo.isSignatureVerificationEnabled != ocrConfigArgs.isSignatureVerificationEnabled) { - revert StaticConfigCannotBeChanged(ocrPluginType); + } else { + if (configInfo.isSignatureVerificationEnabled != ocrConfigArgs.isSignatureVerificationEnabled) { + revert StaticConfigCannotBeChanged(ocrPluginType); + } } address[] memory transmitters = ocrConfigArgs.transmitters; - // Transmitters are expected to never exceed 255 (since this is bounded by MAX_NUM_ORACLES) - uint8 newTransmittersLength = uint8(transmitters.length); - - if (newTransmittersLength > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); + if (transmitters.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); + if (transmitters.length == 0) revert InvalidConfig(InvalidConfigErrorType.NO_TRANSMITTERS); _clearOracleRoles(ocrPluginType, ocrConfig.transmitters); @@ -157,13 +166,15 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { _clearOracleRoles(ocrPluginType, ocrConfig.signers); address[] memory signers = ocrConfigArgs.signers; - ocrConfig.signers = signers; - uint8 signersLength = uint8(signers.length); - configInfo.n = signersLength; + if (signers.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); + if (signers.length <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); + // NOTE: Transmitters cannot exceed signers. Transmitters do not have to be >= 3F + 1 because they can match >= 3fChain + 1, where fChain <= F. + // fChain is not represented in MultiOCR3Base - so we skip this check. + if (signers.length < transmitters.length) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); - if (signersLength > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); - if (signersLength <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); + configInfo.n = uint8(signers.length); + ocrConfig.signers = signers; _assignOracleRoles(ocrPluginType, signers, Role.Signer); } @@ -180,31 +191,33 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { _afterOCR3ConfigSet(ocrPluginType); } - /// @notice Hook that is called after a plugin's OCR3 config changes - /// @param ocrPluginType Plugin type for which the config changed - function _afterOCR3ConfigSet(uint8 ocrPluginType) internal virtual; + /// @notice Hook that is called after a plugin's OCR3 config changes. + /// @param ocrPluginType Plugin type for which the config changed. + function _afterOCR3ConfigSet( + uint8 ocrPluginType + ) internal virtual; - /// @notice Clears oracle roles for the provided oracle addresses - /// @param ocrPluginType OCR plugin type to clear roles for - /// @param oracleAddresses Oracle addresses to clear roles for + /// @notice Clears oracle roles for the provided oracle addresses. + /// @param ocrPluginType OCR plugin type to clear roles for. + /// @param oracleAddresses Oracle addresses to clear roles for. function _clearOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses) internal { for (uint256 i = 0; i < oracleAddresses.length; ++i) { delete s_oracles[ocrPluginType][oracleAddresses[i]]; } } - /// @notice Assigns oracles roles for the provided oracle addresses with uniqueness verification - /// @param ocrPluginType OCR plugin type to assign roles for - /// @param oracleAddresses Oracle addresses to assign roles to - /// @param role Role to assign + /// @notice Assigns oracles roles for the provided oracle addresses with uniqueness verification. + /// @param ocrPluginType OCR plugin type to assign roles for. + /// @param oracleAddresses Oracle addresses to assign roles to. + /// @param role Role to assign. function _assignOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses, Role role) internal { - for (uint8 i = 0; i < oracleAddresses.length; ++i) { + for (uint256 i = 0; i < oracleAddresses.length; ++i) { address oracle = oracleAddresses[i]; if (s_oracles[ocrPluginType][oracle].role != Role.Unset) { revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); } if (oracle == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[ocrPluginType][oracle] = Oracle(i, role); + s_oracles[ocrPluginType][oracle] = Oracle(uint8(i), role); } } @@ -212,9 +225,9 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { /// The function should be called after the per-DON reporting logic is completed. /// @param ocrPluginType OCR plugin type to transmit report for /// @param report serialized report, which the signatures are signing. - /// @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 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. function _transmit( uint8 ocrPluginType, // NOTE: If these parameters are changed, expectedMsgDataLength and/or @@ -280,44 +293,45 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { emit Transmitted(ocrPluginType, configDigest, uint64(uint256(reportContext[1]))); } - /// @notice verifies the signatures of a hashed report value for one OCR plugin type - /// @param ocrPluginType OCR plugin type to transmit report for - /// @param hashedReport hashed encoded packing of report + reportContext - /// @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 + /// @notice Verifies the signatures of a hashed report value for one OCR plugin type. + /// @param ocrPluginType OCR plugin type to transmit report for. + /// @param hashedReport hashed encoded packing of report + reportContext. + /// @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. function _verifySignatures( uint8 ocrPluginType, bytes32 hashedReport, bytes32[] memory rs, bytes32[] memory ss, - bytes32 rawVs // signatures + bytes32 rawVs ) internal view { - // Verify signatures attached to report - bool[MAX_NUM_ORACLES] memory signed; + // Verify signatures attached to report. Using a uint256 means we can only verify up to 256 oracles. + uint256 signed = 0; uint256 numberOfSignatures = rs.length; for (uint256 i; i < numberOfSignatures; ++i) { // Safe from ECDSA malleability here since we check for duplicate signers. address signer = ecrecover(hashedReport, uint8(rawVs[i]) + 27, rs[i], ss[i]); - // Since we disallow address(0) as a valid signer address, it can - // never have a signer role. + // Since we disallow address(0) as a valid signer address, it can never have a signer role. Oracle memory oracle = s_oracles[ocrPluginType][signer]; if (oracle.role != Role.Signer) revert UnauthorizedSigner(); - if (signed[oracle.index]) revert NonUniqueSignatures(); - signed[oracle.index] = true; + if (signed & (0x1 << oracle.index) != 0) revert NonUniqueSignatures(); + signed |= 0x1 << oracle.index; } } - /// @notice Validates that the chain ID has not diverged after deployment. Reverts if the chain IDs do not match + /// @notice Validates that the chain ID has not diverged after deployment. Reverts if the chain IDs do not match. function _whenChainNotForked() internal view { if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); } - /// @notice information about current offchain reporting protocol configuration - /// @param ocrPluginType OCR plugin type to return config details for - /// @return ocrConfig OCR config for the plugin type - function latestConfigDetails(uint8 ocrPluginType) external view returns (OCRConfig memory ocrConfig) { + /// @notice Information about current offchain reporting protocol configuration. + /// @param ocrPluginType OCR plugin type to return config details for. + /// @return ocrConfig OCR config for the plugin type. + function latestConfigDetails( + uint8 ocrPluginType + ) external view returns (OCRConfig memory ocrConfig) { return s_ocrConfigs[ocrPluginType]; } } diff --git a/contracts/src/v0.8/ccip/ocr/OCR2Abstract.sol b/contracts/src/v0.8/ccip/ocr/OCR2Abstract.sol deleted file mode 100644 index 741433bd5ad..00000000000 --- a/contracts/src/v0.8/ccip/ocr/OCR2Abstract.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /// @notice triggers a new run of the offchain reporting protocol - /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - /// @param configDigest configDigest of this configuration - /// @param configCount ordinal number of this config setting among all config settings over the life of this contract - /// @param signers ith element is address ith oracle uses to sign a report - /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param signers addresses with which oracles sign the reports - /// @param transmitters addresses oracles use to transmit the reports - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - function setOCR2Config( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /// @notice optionally emitted to indicate the latest configDigest and epoch for - /// which a report was successfully transmitted. Alternatively, the contract may - /// use latestConfigDigestAndEpoch with scanLogs set to false. - event Transmitted(bytes32 configDigest, uint32 epoch); - - /// @notice optionally returns the latest configDigest and epoch for which a - /// report was successfully transmitted. Alternatively, the contract may return - /// scanLogs set to true and use Transmitted events to provide this information - /// to offchain watchers. - /// @return scanLogs indicates whether to rely on the configDigest and epoch - /// returned or whether to scan logs for the Transmitted event instead. - /// @return configDigest - /// @return epoch - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /// @notice transmit is called to post a new report to the contract - /// @param report serialized report, which the signatures are signing. - /// @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 - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/contracts/src/v0.8/ccip/ocr/OCR2Base.sol b/contracts/src/v0.8/ccip/ocr/OCR2Base.sol deleted file mode 100644 index 52a6df2f3a2..00000000000 --- a/contracts/src/v0.8/ccip/ocr/OCR2Base.sol +++ /dev/null @@ -1,291 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/// @notice Onchain verification of reports from the offchain reporting protocol -/// @dev For details on its operation, see the offchain reporting protocol design -/// doc, which refers to this contract as simply the "contract". -abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract { - error InvalidConfig(InvalidConfigErrorType errorType); - error WrongMessageLength(uint256 expected, uint256 actual); - error ConfigDigestMismatch(bytes32 expected, bytes32 actual); - error ForkedChain(uint256 expected, uint256 actual); - error WrongNumberOfSignatures(); - error SignaturesOutOfRegistration(); - error UnauthorizedTransmitter(); - error UnauthorizedSigner(); - error NonUniqueSignatures(); - error OracleCannotBeZeroAddress(); - - enum InvalidConfigErrorType { - F_MUST_BE_POSITIVE, - TOO_MANY_SIGNERS, - F_TOO_HIGH, - REPEATED_ORACLE_ADDRESS, - NUM_SIGNERS_NOT_NUM_TRANSMITTERS - } - - // 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. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; - uint8 n; - } - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - // The current config - ConfigInfo internal s_configInfo; - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - // makes it easier for offchain systems to extract config from logs. - uint32 internal s_latestConfigBlockNumber; - - // signer OR transmitter address - mapping(address signerOrTransmitter => Oracle oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = 4 // function selector - + 32 * 3 // 3 words containing reportContext - + 32 // word containing start location of abiencoded report value - + 32 // word containing location start of abiencoded rs value - + 32 // word containing start location of abiencoded ss value - + 32 // rawVs value - + 32 // word containing length of report - + 32 // word containing length rs - + 32; // word containing length of ss - - bool internal immutable i_uniqueReports; - uint256 internal immutable i_chainID; - - constructor(bool uniqueReports) { - i_uniqueReports = uniqueReports; - i_chainID = block.chainid; - } - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); - if (f == 0) revert InvalidConfig(InvalidConfigErrorType.F_MUST_BE_POSITIVE); - if (numSigners != numTransmitters) revert InvalidConfig(InvalidConfigErrorType.NUM_SIGNERS_NOT_NUM_TRANSMITTERS); - if (numSigners <= 3 * f) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); - _; - } - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param signers addresses with which oracles sign the reports - /// @param transmitters addresses oracles use to transmit the reports - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig encoded on-chain contract configuration - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig encoded off-chain oracle configuration - function setOCR2Config( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override checkConfigValid(signers.length, transmitters.length, f) onlyOwner { - _beforeSetConfig(onchainConfig); - uint256 oldSignerLength = s_signers.length; - for (uint256 i = 0; i < oldSignerLength; ++i) { - delete s_oracles[s_signers[i]]; - delete s_oracles[s_transmitters[i]]; - } - - uint256 newSignersLength = signers.length; - for (uint256 i = 0; i < newSignersLength; ++i) { - // add new signer/transmitter addresses - address signer = signers[i]; - if (s_oracles[signer].role != Role.Unset) revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); - if (signer == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[signer] = Oracle(uint8(i), Role.Signer); - - address transmitter = transmitters[i]; - if (s_oracles[transmitter].role != Role.Unset) { - revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); - } - if (transmitter == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[transmitter] = Oracle(uint8(i), Role.Transmitter); - } - - s_signers = signers; - s_transmitters = transmitters; - - s_configInfo.f = f; - s_configInfo.n = uint8(newSignersLength); - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - ++s_configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - /// @dev Hook that is run from setOCR2Config() right after validating configuration. - /// Empty by default, please provide an implementation in a child contract if you need additional configuration processing - function _beforeSetConfig(bytes memory _onchainConfig) internal virtual; - - /// @return list of addresses permitted to transmit reports to this contract - /// @dev The list will match the order used to specify the transmitter during setConfig - function getTransmitters() external view returns (address[] memory) { - return s_transmitters; - } - - /// @notice transmit is called to post a new report to the contract - /// @param report serialized report, which the signatures are signing. - /// @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 - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - // Scoping this reduces stack pressure and gas usage - { - // report and epochAndRound - _report(report, uint40(uint256(reportContext[1]))); - } - - // 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]; - ConfigInfo memory configInfo = s_configInfo; - - if (configInfo.latestConfigDigest != configDigest) { - revert ConfigDigestMismatch(configInfo.latestConfigDigest, configDigest); - } - // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. - // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest - // calculated from chain A and so OCR reports will be valid on both forks. - if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); - - emit Transmitted(configDigest, uint32(uint256(reportContext[1]) >> 8)); - - uint256 expectedNumSignatures; - if (i_uniqueReports) { - expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1; - } else { - expectedNumSignatures = configInfo.f + 1; - } - if (rs.length != expectedNumSignatures) revert WrongNumberOfSignatures(); - if (rs.length != ss.length) revert SignaturesOutOfRegistration(); - - // Scoping this reduces stack pressure and gas usage - { - Oracle memory transmitter = s_oracles[msg.sender]; - // Check that sender is authorized to report - if (!(transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index])) { - revert UnauthorizedTransmitter(); - } - } - // Scoping this reduces stack pressure and gas usage - { - uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + report.length // one byte pure entry in _report - + rs.length * 32 // 32 bytes per entry in _rs - + ss.length * 32; // 32 bytes per entry in _ss) - if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length); - } - - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - bool[MAX_NUM_ORACLES] memory signed; - - uint256 numberOfSignatures = rs.length; - for (uint256 i = 0; i < numberOfSignatures; ++i) { - // Safe from ECDSA malleability here since we check for duplicate signers. - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - // Since we disallow address(0) as a valid signer address, it can - // never have a signer role. - Oracle memory oracle = s_oracles[signer]; - if (oracle.role != Role.Signer) revert UnauthorizedSigner(); - if (signed[oracle.index]) revert NonUniqueSignatures(); - signed[oracle.index] = true; - } - } - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - function _report(bytes calldata report, uint40 epochAndRound) internal virtual; -} diff --git a/contracts/src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol b/contracts/src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol deleted file mode 100644 index a79df8d589a..00000000000 --- a/contracts/src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/// @notice Onchain verification of reports from the offchain reporting protocol -/// @dev For details on its operation, see the offchain reporting protocol design -/// doc, which refers to this contract as simply the "contract". -/// @dev This contract does ***NOT*** check the supplied signatures on `transmit` -/// This is intentional. -abstract contract OCR2BaseNoChecks is OwnerIsCreator, OCR2Abstract { - error InvalidConfig(InvalidConfigErrorType errorType); - error WrongMessageLength(uint256 expected, uint256 actual); - error ConfigDigestMismatch(bytes32 expected, bytes32 actual); - error ForkedChain(uint256 expected, uint256 actual); - error UnauthorizedTransmitter(); - error OracleCannotBeZeroAddress(); - - enum InvalidConfigErrorType { - F_MUST_BE_POSITIVE, - TOO_MANY_TRANSMITTERS, - REPEATED_ORACLE_ADDRESS - } - - // 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. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; - uint8 n; - } - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Unused - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_transmitters - Role role; // Role of the address which mapped to this struct - } - - // The current config - ConfigInfo internal s_configInfo; - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - // makes it easier for offchain systems to extract config from logs. - uint32 internal s_latestConfigBlockNumber; - - // Transmitter address - mapping(address transmitter => Oracle oracle) internal s_oracles; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = 4 // function selector - + 32 * 3 // 3 words containing reportContext - + 32 // word containing start location of abiencoded report value - + 32 // word containing location start of abiencoded rs value - + 32 // word containing start location of abiencoded ss value - + 32 // rawVs value - + 32 // word containing length of report - + 32 // word containing length rs - + 32; // word containing length of ss - - uint256 internal immutable i_chainID; - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numTransmitters, uint256 f) { - if (numTransmitters > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); - if (f == 0) revert InvalidConfig(InvalidConfigErrorType.F_MUST_BE_POSITIVE); - _; - } - - constructor() { - i_chainID = block.chainid; - } - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param signers addresses with which oracles sign the reports - /// @param transmitters addresses oracles use to transmit the reports - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig encoded on-chain contract configuration - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig encoded off-chain oracle configuration - function setOCR2Config( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override checkConfigValid(transmitters.length, f) onlyOwner { - _beforeSetConfig(onchainConfig); - // Scoped to reduce contract size - { - uint256 oldTransmitterLength = s_transmitters.length; - for (uint256 i = 0; i < oldTransmitterLength; ++i) { - delete s_oracles[s_transmitters[i]]; - } - } - uint256 newTransmitterLength = transmitters.length; - for (uint256 i = 0; i < newTransmitterLength; ++i) { - address transmitter = transmitters[i]; - if (s_oracles[transmitter].role != Role.Unset) { - revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); - } - if (transmitter == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[transmitter] = Oracle(uint8(i), Role.Transmitter); - } - - s_transmitters = transmitters; - - s_configInfo.f = f; - s_configInfo.n = uint8(newTransmitterLength); - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - ++s_configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - /// @dev Hook that is run from setOCR2Config() right after validating configuration. - /// Empty by default, please provide an implementation in a child contract if you need additional configuration processing - function _beforeSetConfig(bytes memory _onchainConfig) internal virtual; - - /// @return list of addresses permitted to transmit reports to this contract - /// @dev The list will match the order used to specify the transmitter during setConfig - function getTransmitters() external view returns (address[] memory) { - return s_transmitters; - } - - /// @notice transmit is called to post a new report to the contract - /// @param report serialized report, which the signatures are signing. - /// @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 - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 // signatures - ) external override { - _report(report); - - // 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]; - bytes32 latestConfigDigest = s_configInfo.latestConfigDigest; - if (latestConfigDigest != configDigest) revert ConfigDigestMismatch(latestConfigDigest, configDigest); - _checkChainForked(); - - emit Transmitted(configDigest, uint32(uint256(reportContext[1]) >> 8)); - - // Scoping this reduces stack pressure and gas usage - { - Oracle memory transmitter = s_oracles[msg.sender]; - // Check that sender is authorized to report - if (!(transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index])) { - revert UnauthorizedTransmitter(); - } - } - - uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + report.length // one byte pure entry in _report - + rs.length * 32 // 32 bytes per entry in _rs - + ss.length * 32; // 32 bytes per entry in _ss) - if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length); - } - - function _checkChainForked() internal view { - // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. - // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest - // calculated from chain A and so OCR reports will be valid on both forks. - if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); - } - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - function _report(bytes calldata report) internal virtual; -} diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol deleted file mode 100644 index 1aec436ef8c..00000000000 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol +++ /dev/null @@ -1,721 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; -import {IAny2EVMOffRamp} from "../interfaces/IAny2EVMOffRamp.sol"; -import {ICommitStore} from "../interfaces/ICommitStore.sol"; -import {IPoolV1} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; -import {IRouter} from "../interfaces/IRouter.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; - -import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; -import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; -import {AggregateRateLimiter} from "../AggregateRateLimiter.sol"; -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {OCR2BaseNoChecks} from "../ocr/OCR2BaseNoChecks.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; - -/// @notice EVM2EVMOffRamp enables OCR networks to execute multiple messages -/// in an OffRamp in a single transaction. -/// @dev The EVM2EVMOnRamp, CommitStore and EVM2EVMOffRamp form an xchain upgradeable unit. Any change to one of them -/// results an onchain upgrade of all 3. -/// @dev OCR2BaseNoChecks is used to save gas, signatures are not required as the offramp can only execute -/// messages which are committed in the commitStore. We still make use of OCR2 as an executor whitelist -/// and turn-taking mechanism. -contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersion, OCR2BaseNoChecks { - using ERC165Checker for address; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - - error AlreadyAttempted(uint64 sequenceNumber); - error AlreadyExecuted(uint64 sequenceNumber); - error ZeroAddressNotAllowed(); - error CommitStoreAlreadyInUse(); - error ExecutionError(bytes err); - error InvalidSourceChain(uint64 sourceChainSelector); - error MessageTooLarge(uint256 maxSize, uint256 actualSize); - error TokenDataMismatch(uint64 sequenceNumber); - error UnexpectedTokenData(); - error UnsupportedNumberOfTokens(uint64 sequenceNumber); - error ManualExecutionNotYetEnabled(); - error ManualExecutionGasLimitMismatch(); - error InvalidManualExecutionGasLimit(uint256 index, uint256 newLimit); - error RootNotCommitted(); - error CanOnlySelfCall(); - error ReceiverError(bytes err); - error TokenHandlingError(bytes err); - error EmptyReport(); - error CursedByRMN(); - error InvalidMessageId(); - error NotACompatiblePool(address notPool); - error InvalidDataLength(uint256 expected, uint256 got); - error InvalidNewState(uint64 sequenceNumber, Internal.MessageExecutionState newState); - - /// @dev Atlas depends on this event, if changing, please notify Atlas. - event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); - event SkippedIncorrectNonce(uint64 indexed nonce, address indexed sender); - event SkippedSenderWithPreviousRampMessageInflight(uint64 indexed nonce, address indexed sender); - /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. - event ExecutionStateChanged( - uint64 indexed sequenceNumber, bytes32 indexed messageId, Internal.MessageExecutionState state, bytes returnData - ); - event TokenAggregateRateLimitAdded(address sourceToken, address destToken); - event TokenAggregateRateLimitRemoved(address sourceToken, address destToken); - event SkippedAlreadyExecutedMessage(uint64 indexed sequenceNumber); - - /// @notice Static offRamp config - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - //solhint-disable gas-struct-packing - struct StaticConfig { - address commitStore; // ────────╮ CommitStore address on the destination chain - uint64 chainSelector; // ───────╯ Destination chainSelector - uint64 sourceChainSelector; // ─╮ Source chainSelector - address onRamp; // ─────────────╯ OnRamp address on the source chain - address prevOffRamp; // Address of previous-version OffRamp - address rmnProxy; // RMN proxy address - address tokenAdminRegistry; // Token admin registry address - } - - /// @notice Dynamic offRamp config - /// @dev since OffRampConfig is part of OffRampConfigChanged event, if changing it, we should update the ABI on Atlas - struct DynamicConfig { - uint32 permissionLessExecutionThresholdSeconds; // ─╮ Waiting time before manual execution is enabled - uint32 maxDataBytes; // │ Maximum payload data size in bytes - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of ERC20 token transfers that can be included per message - address router; // ─────────────────────────────────╯ Router address - address priceRegistry; // ──────────╮ Price registry address - uint32 maxPoolReleaseOrMintGas; // │ Maximum amount of gas passed on to token pool `releaseOrMint` call - uint32 maxTokenTransferGas; // ─────╯ Maximum amount of gas passed on to token `transfer` call - } - - /// @notice RateLimitToken struct containing both the source and destination token addresses - struct RateLimitToken { - address sourceToken; - address destToken; - } - - // STATIC CONFIG - string public constant override typeAndVersion = "EVM2EVMOffRamp 1.5.0-dev"; - - /// @dev Commit store address on the destination chain - address internal immutable i_commitStore; - /// @dev ChainSelector of the source chain - uint64 internal immutable i_sourceChainSelector; - /// @dev ChainSelector of this chain - uint64 internal immutable i_chainSelector; - /// @dev OnRamp address on the source chain - address internal immutable i_onRamp; - /// @dev metadataHash is a lane-specific prefix for a message hash preimage which ensures global uniqueness. - /// Ensures that 2 identical messages sent to 2 different lanes will have a distinct hash. - /// Must match the metadataHash used in computing leaf hashes offchain for the root committed in - /// the commitStore and i_metadataHash in the onRamp. - bytes32 internal immutable i_metadataHash; - /// @dev The address of previous-version OffRamp for this lane. - /// Used to be able to provide sequencing continuity during a zero downtime upgrade. - address internal immutable i_prevOffRamp; - /// @dev The address of the RMN proxy - address internal immutable i_rmnProxy; - /// @dev The address of the token admin registry - address internal immutable i_tokenAdminRegistry; - - // DYNAMIC CONFIG - DynamicConfig internal s_dynamicConfig; - /// @dev Tokens that should be included in Aggregate Rate Limiting - /// An (address => address) map is used for backwards compatability of offchain code - EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensDestToSource; - - // STATE - /// @dev The expected nonce for a given sender. - /// Corresponds to s_senderNonce in the OnRamp, used to enforce that messages are - /// executed in the same order they are sent (assuming they are DON). Note that re-execution - /// of FAILED messages however, can be out of order. - mapping(address sender => uint64 nonce) internal s_senderNonce; - /// @dev A mapping of sequence numbers to execution state using a bitmap with each execution - /// state only taking up 2 bits of the uint256, packing 128 states into a single slot. - /// Message state is tracked to ensure message can only be executed successfully once. - mapping(uint64 seqNum => uint256 executionStateBitmap) internal s_executionStates; - - constructor( - StaticConfig memory staticConfig, - RateLimiter.Config memory rateLimiterConfig - ) OCR2BaseNoChecks() AggregateRateLimiter(rateLimiterConfig) { - if ( - staticConfig.onRamp == address(0) || staticConfig.commitStore == address(0) - || staticConfig.tokenAdminRegistry == address(0) - ) revert ZeroAddressNotAllowed(); - // Ensures we can never deploy a new offRamp that points to a commitStore that - // already has roots committed. - if (ICommitStore(staticConfig.commitStore).getExpectedNextSequenceNumber() != 1) revert CommitStoreAlreadyInUse(); - - i_commitStore = staticConfig.commitStore; - i_sourceChainSelector = staticConfig.sourceChainSelector; - i_chainSelector = staticConfig.chainSelector; - i_onRamp = staticConfig.onRamp; - i_prevOffRamp = staticConfig.prevOffRamp; - i_rmnProxy = staticConfig.rmnProxy; - i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; - - i_metadataHash = _metadataHash(Internal.EVM_2_EVM_MESSAGE_HASH); - } - - // ================================================================ - // │ Messaging │ - // ================================================================ - - // The size of the execution state in bits - uint256 private constant MESSAGE_EXECUTION_STATE_BIT_WIDTH = 2; - // The mask for the execution state bits - uint256 private constant MESSAGE_EXECUTION_STATE_MASK = (1 << MESSAGE_EXECUTION_STATE_BIT_WIDTH) - 1; - - /// @notice Returns the current execution state of a message based on its sequenceNumber. - /// @param sequenceNumber The sequence number of the message to get the execution state for. - /// @return The current execution state of the message. - /// @dev we use the literal number 128 because using a constant increased gas usage. - function getExecutionState(uint64 sequenceNumber) public view returns (Internal.MessageExecutionState) { - return Internal.MessageExecutionState( - (s_executionStates[sequenceNumber / 128] >> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH)) - & MESSAGE_EXECUTION_STATE_MASK - ); - } - - /// @notice Sets a new execution state for a given sequence number. It will overwrite any existing state. - /// @param sequenceNumber The sequence number for which the state will be saved. - /// @param newState The new value the state will be in after this function is called. - /// @dev we use the literal number 128 because using a constant increased gas usage. - function _setExecutionState(uint64 sequenceNumber, Internal.MessageExecutionState newState) internal { - uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH; - uint256 bitmap = s_executionStates[sequenceNumber / 128]; - // to unset any potential existing state we zero the bits of the section the state occupies, - // then we do an AND operation to blank out any existing state for the section. - bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset); - // Set the new state - bitmap |= uint256(newState) << offset; - - s_executionStates[sequenceNumber / 128] = bitmap; - } - - /// @inheritdoc IAny2EVMOffRamp - function getSenderNonce(address sender) external view returns (uint64 nonce) { - uint256 senderNonce = s_senderNonce[sender]; - - if (senderNonce == 0) { - if (i_prevOffRamp != address(0)) { - // If OffRamp was upgraded, check if sender has a nonce from the previous OffRamp. - return IAny2EVMOffRamp(i_prevOffRamp).getSenderNonce(sender); - } - } - return uint64(senderNonce); - } - - /// @notice Manually execute a message. - /// @param report Internal.ExecutionReport. - /// @param gasLimitOverrides New gasLimit for each message in the report. - /// @dev We permit gas limit overrides so that users may manually execute messages which failed due to - /// insufficient gas provided. - function manuallyExecute(Internal.ExecutionReport memory report, uint256[] memory gasLimitOverrides) external { - // We do this here because the other _execute path is already covered OCR2BaseXXX. - _checkChainForked(); - - uint256 numMsgs = report.messages.length; - if (numMsgs != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); - for (uint256 i = 0; i < numMsgs; ++i) { - uint256 newLimit = gasLimitOverrides[i]; - // Checks to ensure message cannot be executed with less gas than specified. - if (newLimit != 0) { - if (newLimit < report.messages[i].gasLimit) { - revert InvalidManualExecutionGasLimit(i, newLimit); - } - } - } - - _execute(report, gasLimitOverrides); - } - - /// @notice Entrypoint for execution, called by the OCR network - /// @dev Expects an encoded ExecutionReport - function _report(bytes calldata report) internal override { - _execute(abi.decode(report, (Internal.ExecutionReport)), new uint256[](0)); - } - - /// @notice Executes a report, executing each message in order. - /// @param report The execution report containing the messages and proofs. - /// @param manualExecGasLimits An array of gas limits to use for manual execution. - /// @dev If called from the DON, this array is always empty. - /// @dev If called from manual execution, this array is always same length as messages. - function _execute(Internal.ExecutionReport memory report, uint256[] memory manualExecGasLimits) internal { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(i_sourceChainSelector)))) revert CursedByRMN(); - - uint256 numMsgs = report.messages.length; - if (numMsgs == 0) revert EmptyReport(); - if (numMsgs != report.offchainTokenData.length) revert UnexpectedTokenData(); - - bytes32[] memory hashedLeaves = new bytes32[](numMsgs); - - for (uint256 i = 0; i < numMsgs; ++i) { - Internal.EVM2EVMMessage memory message = report.messages[i]; - // We do this hash here instead of in _verifyMessages to avoid two separate loops - // over the same data, which increases gas cost - hashedLeaves[i] = Internal._hash(message, i_metadataHash); - // For EVM2EVM offramps, the messageID is the leaf hash. - // Asserting that this is true ensures we don't accidentally commit and then execute - // a message with an unexpected hash. - if (hashedLeaves[i] != message.messageId) revert InvalidMessageId(); - } - - // SECURITY CRITICAL CHECK - uint256 timestampCommitted = ICommitStore(i_commitStore).verify(hashedLeaves, report.proofs, report.proofFlagBits); - if (timestampCommitted == 0) revert RootNotCommitted(); - - // Execute messages - bool manualExecution = manualExecGasLimits.length != 0; - for (uint256 i = 0; i < numMsgs; ++i) { - Internal.EVM2EVMMessage memory message = report.messages[i]; - Internal.MessageExecutionState originalState = getExecutionState(message.sequenceNumber); - if (originalState == Internal.MessageExecutionState.SUCCESS) { - // If the message has already been executed, we skip it. We want to not revert on race conditions between - // executing parties. This will allow us to open up manual exec while also attempting with the DON, without - // reverting an entire DON batch when a user manually executes while the tx is inflight. - emit SkippedAlreadyExecutedMessage(message.sequenceNumber); - continue; - } - // Two valid cases here, we either have never touched this message before, or we tried to execute - // and failed. This check protects against reentry and re-execution because the other state is - // IN_PROGRESS which should not be allowed to execute. - if ( - !( - originalState == Internal.MessageExecutionState.UNTOUCHED - || originalState == Internal.MessageExecutionState.FAILURE - ) - ) revert AlreadyExecuted(message.sequenceNumber); - - if (manualExecution) { - bool isOldCommitReport = - (block.timestamp - timestampCommitted) > s_dynamicConfig.permissionLessExecutionThresholdSeconds; - // Manually execution is fine if we previously failed or if the commit report is just too old - // Acceptable state transitions: FAILURE->SUCCESS, UNTOUCHED->SUCCESS, FAILURE->FAILURE - if (!(isOldCommitReport || originalState == Internal.MessageExecutionState.FAILURE)) { - revert ManualExecutionNotYetEnabled(); - } - - // Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override. - if (manualExecGasLimits[i] != 0) { - message.gasLimit = manualExecGasLimits[i]; - } - } else { - // DON can only execute a message once - // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE - if (originalState != Internal.MessageExecutionState.UNTOUCHED) revert AlreadyAttempted(message.sequenceNumber); - } - - if (message.nonce != 0) { - // In the scenario where we upgrade offRamps, we still want to have sequential nonces. - // Referencing the old offRamp to check the expected nonce if none is set for a - // given sender allows us to skip the current message if it would not be the next according - // to the old offRamp. This preserves sequencing between updates. - uint64 prevNonce = s_senderNonce[message.sender]; - if (prevNonce == 0) { - if (i_prevOffRamp != address(0)) { - prevNonce = IAny2EVMOffRamp(i_prevOffRamp).getSenderNonce(message.sender); - if (prevNonce + 1 != message.nonce) { - // the starting v2 onramp nonce, i.e. the 1st message nonce v2 offramp is expected to receive, - // is guaranteed to equal (largest v1 onramp nonce + 1). - // if this message's nonce isn't (v1 offramp nonce + 1), then v1 offramp nonce != largest v1 onramp nonce, - // it tells us there are still messages inflight for v1 offramp - emit SkippedSenderWithPreviousRampMessageInflight(message.nonce, message.sender); - continue; - } - // Otherwise this nonce is indeed the "transitional nonce", that is - // all messages sent to v1 ramp have been executed by the DON and the sequence can resume in V2. - // Note if first time user in V2, then prevNonce will be 0, and message.nonce = 1, so this will be a no-op. - s_senderNonce[message.sender] = prevNonce; - } - } - - // UNTOUCHED messages MUST be executed in order always IF message.nonce > 0. - if (originalState == Internal.MessageExecutionState.UNTOUCHED) { - if (prevNonce + 1 != message.nonce) { - // We skip the message if the nonce is incorrect, since message.nonce > 0. - emit SkippedIncorrectNonce(message.nonce, message.sender); - continue; - } - } - } - - // Although we expect only valid messages will be committed, we check again - // when executing as a defense in depth measure. - bytes[] memory offchainTokenData = report.offchainTokenData[i]; - _isWellFormed( - message.sequenceNumber, - message.sourceChainSelector, - message.tokenAmounts.length, - message.data.length, - offchainTokenData.length - ); - - _setExecutionState(message.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); - (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData); - _setExecutionState(message.sequenceNumber, newState); - - // Since it's hard to estimate whether manual execution will succeed, we - // revert the entire transaction if it fails. This will show the user if - // their manual exec will fail before they submit it. - if (manualExecution) { - if (newState == Internal.MessageExecutionState.FAILURE) { - if (originalState != Internal.MessageExecutionState.UNTOUCHED) { - // If manual execution fails, we revert the entire transaction, unless the originalState is UNTOUCHED as we - // would still be making progress by changing the state from UNTOUCHED to FAILURE. - revert ExecutionError(returnData); - } - } - } - - // The only valid prior states are UNTOUCHED and FAILURE (checked above) - // The only valid post states are SUCCESS and FAILURE (checked below) - if (newState != Internal.MessageExecutionState.SUCCESS) { - if (newState != Internal.MessageExecutionState.FAILURE) { - revert InvalidNewState(message.sequenceNumber, newState); - } - } - - // Nonce changes per state transition. - // These only apply for ordered messages. - // UNTOUCHED -> FAILURE nonce bump - // UNTOUCHED -> SUCCESS nonce bump - // FAILURE -> FAILURE no nonce bump - // FAILURE -> SUCCESS no nonce bump - if (message.nonce != 0) { - if (originalState == Internal.MessageExecutionState.UNTOUCHED) { - s_senderNonce[message.sender]++; - } - } - - emit ExecutionStateChanged(message.sequenceNumber, message.messageId, newState, returnData); - } - } - - /// @notice Does basic message validation. Should never fail. - /// @param sequenceNumber Sequence number of the message. - /// @param sourceChainSelector SourceChainSelector of the message. - /// @param numberOfTokens Length of tokenAmounts array in the message. - /// @param dataLength Length of data field in the message. - /// @param offchainTokenDataLength Length of offchainTokenData array. - /// @dev reverts on validation failures. - function _isWellFormed( - uint64 sequenceNumber, - uint64 sourceChainSelector, - uint256 numberOfTokens, - uint256 dataLength, - uint256 offchainTokenDataLength - ) private view { - if (sourceChainSelector != i_sourceChainSelector) revert InvalidSourceChain(sourceChainSelector); - if (numberOfTokens > uint256(s_dynamicConfig.maxNumberOfTokensPerMsg)) { - revert UnsupportedNumberOfTokens(sequenceNumber); - } - if (numberOfTokens != offchainTokenDataLength) revert TokenDataMismatch(sequenceNumber); - if (dataLength > uint256(s_dynamicConfig.maxDataBytes)) { - revert MessageTooLarge(uint256(s_dynamicConfig.maxDataBytes), dataLength); - } - } - - /// @notice Try executing a message. - /// @param message Internal.EVM2EVMMessage memory message. - /// @param offchainTokenData Data provided by the DON for token transfers. - /// @return the new state of the message, being either SUCCESS or FAILURE. - /// @return revert data in bytes if CCIP receiver reverted during execution. - function _trialExecute( - Internal.EVM2EVMMessage memory message, - bytes[] memory offchainTokenData - ) internal returns (Internal.MessageExecutionState, bytes memory) { - try this.executeSingleMessage(message, offchainTokenData) {} - catch (bytes memory err) { - if ( - ReceiverError.selector == bytes4(err) || TokenHandlingError.selector == bytes4(err) - || Internal.InvalidEVMAddress.selector == bytes4(err) || InvalidDataLength.selector == bytes4(err) - || CallWithExactGas.NoContract.selector == bytes4(err) || NotACompatiblePool.selector == bytes4(err) - ) { - // If CCIP receiver execution is not successful, bubble up receiver revert data, - // prepended by the 4 bytes of ReceiverError.selector, TokenHandlingError.selector or InvalidPoolAddress.selector. - // 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); - } - // If revert is not caused by CCIP receiver, it is unexpected, bubble up the revert. - revert ExecutionError(err); - } - // If message execution succeeded, no CCIP receiver return data is expected, return with empty bytes. - return (Internal.MessageExecutionState.SUCCESS, ""); - } - - /// @notice Execute a single message. - /// @param message The message that will be executed. - /// @param offchainTokenData Token transfer data to be passed to TokenPool. - /// @dev We make this external and callable by the contract itself, in order to try/catch - /// its execution and enforce atomicity among successful message processing and token transfer. - /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts - /// (for example smart contract wallets) without an associated message. - function executeSingleMessage(Internal.EVM2EVMMessage memory message, bytes[] memory offchainTokenData) external { - if (msg.sender != address(this)) revert CanOnlySelfCall(); - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); - if (message.tokenAmounts.length > 0) { - destTokenAmounts = _releaseOrMintTokens( - message.tokenAmounts, abi.encode(message.sender), message.receiver, message.sourceTokenData, offchainTokenData - ); - } - // There are three cases in which we skip calling the receiver: - // 1. If the message data is empty AND the gas limit is 0. - // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract - // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the - // receiver without any gas, which would revert the transaction. - // 2. If the receiver is not a contract. - // 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. - if ( - (message.data.length == 0 && message.gasLimit == 0) || message.receiver.code.length == 0 - || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) - ) return; - - (bool success, bytes memory returnData,) = IRouter(s_dynamicConfig.router).routeMessage( - Client.Any2EVMMessage({ - messageId: message.messageId, - sourceChainSelector: message.sourceChainSelector, - sender: abi.encode(message.sender), - data: message.data, - destTokenAmounts: destTokenAmounts - }), - Internal.GAS_FOR_CALL_EXACT_CHECK, - message.gasLimit, - message.receiver - ); - // If CCIP receiver execution is not successful, revert the call including token transfers - if (!success) revert ReceiverError(returnData); - } - - /// @notice creates a unique hash to be used in message hashing. - function _metadataHash(bytes32 prefix) internal view returns (bytes32) { - return keccak256(abi.encode(prefix, i_sourceChainSelector, i_chainSelector, i_onRamp)); - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Returns the static config. - /// @dev This function will always return the same struct as the contents is static and can never change. - /// RMN depends on this function, if changing, please notify the RMN maintainers. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - commitStore: i_commitStore, - chainSelector: i_chainSelector, - sourceChainSelector: i_sourceChainSelector, - onRamp: i_onRamp, - prevOffRamp: i_prevOffRamp, - rmnProxy: i_rmnProxy, - tokenAdminRegistry: i_tokenAdminRegistry - }); - } - - /// @notice Returns the current dynamic config. - /// @return The current config. - function getDynamicConfig() external view returns (DynamicConfig memory) { - return s_dynamicConfig; - } - - /// @notice Sets the dynamic config. This function is called during `setOCR2Config` flow - function _beforeSetConfig(bytes memory onchainConfig) internal override { - DynamicConfig memory dynamicConfig = abi.decode(onchainConfig, (DynamicConfig)); - - if (dynamicConfig.router == address(0)) revert ZeroAddressNotAllowed(); - - s_dynamicConfig = dynamicConfig; - - emit ConfigSet( - StaticConfig({ - commitStore: i_commitStore, - chainSelector: i_chainSelector, - sourceChainSelector: i_sourceChainSelector, - onRamp: i_onRamp, - prevOffRamp: i_prevOffRamp, - rmnProxy: i_rmnProxy, - tokenAdminRegistry: i_tokenAdminRegistry - }), - dynamicConfig - ); - } - - /// @notice Get all tokens which are included in Aggregate Rate Limiting. - /// @return sourceTokens The source representation of the tokens that are rate limited. - /// @return destTokens The destination representation of the tokens that are rate limited. - /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when - /// making successive calls, one should keep the block height constant to ensure a consistent result. - function getAllRateLimitTokens() external view returns (address[] memory sourceTokens, address[] memory destTokens) { - uint256 numRateLimitedTokens = s_rateLimitedTokensDestToSource.length(); - sourceTokens = new address[](numRateLimitedTokens); - destTokens = new address[](numRateLimitedTokens); - - for (uint256 i = 0; i < numRateLimitedTokens; ++i) { - (address destToken, address sourceToken) = s_rateLimitedTokensDestToSource.at(i); - sourceTokens[i] = sourceToken; - destTokens[i] = destToken; - } - return (sourceTokens, destTokens); - } - - /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. - /// @param removes - A list of one or more tokens to be removed. - /// @param adds - A list of one or more tokens to be added. - function updateRateLimitTokens(RateLimitToken[] memory removes, RateLimitToken[] memory adds) external onlyOwner { - for (uint256 i = 0; i < removes.length; ++i) { - if (s_rateLimitedTokensDestToSource.remove(removes[i].destToken)) { - emit TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); - } - } - - for (uint256 i = 0; i < adds.length; ++i) { - if (s_rateLimitedTokensDestToSource.set(adds[i].destToken, adds[i].sourceToken)) { - emit TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); - } - } - } - - // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @notice Uses a pool to release or mint a token to a receiver address in two steps. First, the pool is called - /// to release the tokens to the offRamp, then the offRamp calls the token contract to transfer the tokens to the - /// receiver. This is done to ensure the exact number of tokens, the pool claims to release are actually transferred. - /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the - /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by - /// registering the token on this chain, and re-trying the msg. - /// @param sourceAmount The amount of tokens to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceTokenData A struct containing the local token address, the source pool address and optional data - /// returned from the source pool. - /// @param offchainTokenData Data fetched offchain by the DON. - function _releaseOrMintToken( - uint256 sourceAmount, - bytes memory originalSender, - address receiver, - Internal.SourceTokenData memory sourceTokenData, - bytes memory offchainTokenData - ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { - // We need to safely decode the token address from the sourceTokenData, as it could be wrong, - // in which case it doesn't have to be a valid EVM address. - address localToken = Internal._validateEVMAddress(sourceTokenData.destTokenAddress); - // We check with the token admin registry if the token has a pool on this chain. - address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); - // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. - // 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 gas estimations should - // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { - revert NotACompatiblePool(localPoolAddress); - } - - // We determined that the pool address is a valid EVM address, but that does not mean the code at this - // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location - // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. - // We call the pool with exact gas to increase resistance against malicious tokens or token pools. - // We protects against return data bombs by capping the return data size at MAX_RET_BYTES. - (bool success, bytes memory returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall( - IPoolV1.releaseOrMint, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: receiver, - amount: sourceAmount, - localToken: localToken, - remoteChainSelector: i_sourceChainSelector, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ), - localPoolAddress, - s_dynamicConfig.maxPoolReleaseOrMintGas, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - // wrap and rethrow the error so we can catch it lower in the stack - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should contain only the local token amount. - if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { - revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); - } - uint256 localAmount = abi.decode(returnData, (uint256)); - // Since token pools send the tokens to the msg.sender, which is this offRamp, we need to - // transfer them to the final receiver. We use the _callWithExactGasSafeReturnData function because - // the token contracts are not considered trusted. - (success, returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall(IERC20.transfer, (receiver, localAmount)), - localToken, - s_dynamicConfig.maxTokenTransferGas, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - if (!success) revert TokenHandlingError(returnData); - - return Client.EVMTokenAmount({token: localToken, amount: localAmount}); - } - - /// @notice Uses pools to release or mint a number of different tokens to a receiver address. - /// @param sourceTokenAmounts List of tokens and amount values to be released/minted. - /// @param originalSender The message sender. - /// @param receiver The address that will receive the tokens. - /// @param encodedSourceTokenData Array of token data returned by token pools on the source chain. - /// @param offchainTokenData Array of token data fetched offchain by the DON. - /// @dev This function wrappes the token pool call in a try catch block to gracefully handle - /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error - /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. - function _releaseOrMintTokens( - Client.EVMTokenAmount[] memory sourceTokenAmounts, - bytes memory originalSender, - address receiver, - bytes[] memory encodedSourceTokenData, - bytes[] memory offchainTokenData - ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { - // Creating a copy is more gas efficient than initializing a new array. - destTokenAmounts = sourceTokenAmounts; - uint256 value = 0; - for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { - destTokenAmounts[i] = _releaseOrMintToken( - sourceTokenAmounts[i].amount, - originalSender, - receiver, - // This should never revert as the onRamp encodes the sourceTokenData struct. Only the inner components from - // this struct come from untrusted sources. - abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData)), - offchainTokenData[i] - ); - - if (s_rateLimitedTokensDestToSource.contains(destTokenAmounts[i].token)) { - value += _getTokenValue(destTokenAmounts[i], IPriceRegistry(s_dynamicConfig.priceRegistry)); - } - } - - if (value > 0) _rateLimitValue(value); - - return destTokenAmounts; - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Reverts as this contract should not access CCIP messages - function ccipReceive(Client.Any2EVMMessage calldata) external pure { - // solhint-disable-next-line - revert(); - } -} diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol similarity index 63% rename from contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol rename to contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 809e4e22a4e..e67b2a82f03 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -3,38 +3,36 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; +import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; import {IRouter} from "../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; -import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; import {Client} from "../libraries/Client.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/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.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 EVM2EVMOffRamp enables OCR networks to execute multiple messages +/// @notice OffRamp enables OCR networks to execute multiple messages /// in an OffRamp in a single transaction. -/// @dev The EVM2EVMMultiOnRamp and EVM2EVMMultiOffRamp form an xchain upgradeable unit. Any change to one of them +/// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them /// results an onchain upgrade of both contracts. -/// @dev MultiOCR3Base is used to store multiple OCR configs for both the OffRamp and the CommitStore. +/// @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 EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { +contract OffRamp is ITypeAndVersion, MultiOCR3Base { using ERC165Checker for address; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableSet for EnumerableSet.UintSet; - error AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber); - error AlreadyExecuted(uint64 sourceChainSelector, uint64 sequenceNumber); error ZeroChainSelectorNotAllowed(); error ExecutionError(bytes32 messageId, bytes err); error SourceChainNotEnabled(uint64 sourceChainSelector); @@ -42,23 +40,32 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { error UnexpectedTokenData(); error ManualExecutionNotYetEnabled(uint64 sourceChainSelector); error ManualExecutionGasLimitMismatch(); - error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, uint256 index, uint256 newLimit); + error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, bytes32 messageId, uint256 newLimit); + error InvalidManualExecutionTokenGasOverride( + bytes32 messageId, uint256 tokenIndex, uint256 oldLimit, uint256 tokenGasOverride + ); + error ManualExecutionGasAmountCountMismatch(bytes32 messageId, uint64 sequenceNumber); error RootNotCommitted(uint64 sourceChainSelector); error RootAlreadyCommitted(uint64 sourceChainSelector, bytes32 merkleRoot); error InvalidRoot(); error CanOnlySelfCall(); error ReceiverError(bytes err); error TokenHandlingError(bytes err); - error EmptyReport(); + error ReleaseOrMintBalanceMismatch(uint256 amountReleased, uint256 balancePre, uint256 balancePost); + error EmptyReport(uint64 sourceChainSelector); + error EmptyBatch(); error CursedByRMN(uint64 sourceChainSelector); error NotACompatiblePool(address notPool); error InvalidDataLength(uint256 expected, uint256 got); error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState); - error InvalidStaticConfig(uint64 sourceChainSelector); error StaleCommitReport(); - error InvalidInterval(uint64 sourceChainSelector, Interval interval); + error InvalidInterval(uint64 sourceChainSelector, uint64 min, uint64 max); error ZeroAddressNotAllowed(); error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); + error SourceChainSelectorMismatch(uint64 reportSourceChainSelector, uint64 messageSourceChainSelector); + error SignatureVerificationDisabled(); + error CommitOnRampMismatch(bytes reportOnRamp, bytes configOnRamp); + error InvalidOnRampUpdate(uint64 sourceChainSelector); /// @dev Atlas depends on this event, if changing, please notify Atlas. event StaticConfigSet(StaticConfig staticConfig); @@ -68,83 +75,80 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { uint64 indexed sourceChainSelector, uint64 indexed sequenceNumber, bytes32 indexed messageId, + bytes32 messageHash, Internal.MessageExecutionState state, - bytes returnData + bytes returnData, + uint256 gasUsed ); event SourceChainSelectorAdded(uint64 sourceChainSelector); event SourceChainConfigSet(uint64 indexed sourceChainSelector, SourceChainConfig sourceConfig); event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber); + event AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber); /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. - event CommitReportAccepted(CommitReport report); + event CommitReportAccepted(Internal.MerkleRoot[] merkleRoots, Internal.PriceUpdates priceUpdates); event RootRemoved(bytes32 root); + event SkippedReportExecution(uint64 sourceChainSelector); - /// @notice Static offRamp config + /// @dev Struct that contains the static configuration /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + /// @dev not sure why solhint complains about this, seems like a buggy detector + /// https://github.com/protofire/solhint/issues/597 + // solhint-disable-next-line gas-struct-packing struct StaticConfig { uint64 chainSelector; // ───╮ Destination chainSelector - address rmnProxy; // ───────╯ RMN proxy address + IRMNRemote rmnRemote; // ───╯ RMN Verification Contract address tokenAdminRegistry; // Token admin registry address - address nonceManager; // Address of the nonce manager + address nonceManager; // Nonce manager address } - /// @notice Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) + /// @dev Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) struct SourceChainConfig { - bool isEnabled; // ──────────╮ Flag whether the source chain is enabled or not + IRouter router; // ──────────╮ Local router to use for messages coming from this source chain + bool isEnabled; // | Flag whether the source chain is enabled or not uint64 minSeqNr; // ─────────╯ The min sequence number expected for future messages bytes onRamp; // OnRamp address on the source chain } - /// @notice SourceChainConfig update args scoped to one source chain + /// @dev Same as SourceChainConfig but with source chain selector so that an array of these + /// can be passed in the constructor and the applySourceChainConfigUpdates function. struct SourceChainConfigArgs { - uint64 sourceChainSelector; // ───╮ Source chain selector of the config to update + IRouter router; // ────────────────╮ Local router to use for messages coming from this source chain + uint64 sourceChainSelector; // | Source chain selector of the config to update bool isEnabled; // ────────────────╯ Flag whether the source chain is enabled or not bytes onRamp; // OnRamp address on the source chain } - /// @notice Dynamic offRamp config - /// @dev since OffRampConfig is part of OffRampConfigChanged event, if changing it, we should update the ABI on Atlas + /// @dev Dynamic offRamp config + /// @dev Since DynamicConfig is part of DynamicConfigSet event, if changing it, we should update the ABI on Atlas struct DynamicConfig { - address router; // ─────────────────────────────────╮ Router address - uint32 permissionLessExecutionThresholdSeconds; // │ Waiting time before manual execution is enabled - uint32 maxTokenTransferGas; // │ Maximum amount of gas passed on to token `transfer` call - uint32 maxPoolReleaseOrMintGas; // ─────────────────╯ Maximum amount of gas passed on to token pool when calling releaseOrMint - address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) - address priceRegistry; // Price registry address on the local chain + address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain + uint32 permissionLessExecutionThresholdSeconds; // ─╯ Waiting time before manual execution is enabled + address messageInterceptor; // Optional message interceptor to validate incoming messages (zero address = no interceptor) } - /// @notice a sequenceNumber interval - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct Interval { - uint64 min; // ───╮ Minimum sequence number, inclusive - uint64 max; // ───╯ Maximum sequence number, inclusive - } - - /// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport. - struct MerkleRoot { - uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to - Interval interval; // Report interval of the merkle root - bytes32 merkleRoot; // Merkle root covering the interval & source chain messages - } - - /// @notice Report that is committed by the observing DON at the committing phase + /// @dev Report that is committed by the observing DON at the committing phase /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct CommitReport { Internal.PriceUpdates priceUpdates; // Collection of gas and price updates to commit - MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit + Internal.MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit + IRMNRemote.Signature[] rmnSignatures; // RMN signatures on the merkle roots + uint256 rmnRawVs; // Raw v values of the RMN signatures } - /// @dev Struct to hold a merkle root for a source chain so that an array of these can be passed in the resetUblessedRoots function. - struct UnblessedRoot { - uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to - bytes32 merkleRoot; // Merkle root of a single remote source chain + struct GasLimitOverride { + // A value of zero in both fields signifies no override and allows the corresponding field to be overridden as valid + uint256 receiverExecutionGasLimit; // Overrides EVM2EVMMessage.gasLimit. + uint32[] tokenGasOverrides; // Overrides EVM2EVMMessage.sourceTokenData.destGasAmount, length must be same as tokenAmounts. } // STATIC CONFIG - string public constant override typeAndVersion = "EVM2EVMMultiOffRamp 1.6.0-dev"; + string public constant override typeAndVersion = "OffRamp 1.6.0-dev"; + /// @dev Hash of encoded address(0) used for empty address checks + bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); /// @dev ChainSelector of this chain uint64 internal immutable i_chainSelector; - /// @dev The address of the RMN proxy - address internal immutable i_rmnProxy; + /// @dev The RMN verification contract + IRMNRemote internal immutable i_rmnRemote; /// @dev The address of the token admin registry address internal immutable i_tokenAdminRegistry; /// @dev The address of the nonce manager @@ -153,9 +157,12 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { // DYNAMIC CONFIG DynamicConfig internal s_dynamicConfig; - /// @notice SourceConfig per chain + /// @notice Set of source chain selectors + EnumerableSet.UintSet internal s_sourceChainSelectors; + + /// @notice SourceChainConfig per chain /// (forms lane configurations from sourceChainSelector => StaticConfig.chainSelector) - mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; + mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) private s_sourceChainConfigs; // STATE /// @dev A mapping of sequence numbers (per source chain) to execution state using a bitmap with each execution @@ -164,7 +171,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => uint256 executionStateBitmap)) internal s_executionStates; - // sourceChainSelector => merkleRoot => timestamp when received + /// @notice Commit timestamp of merkle roots per source chain mapping(uint64 sourceChainSelector => mapping(bytes32 merkleRoot => uint256 timestamp)) internal s_roots; /// @dev The sequence number of the last price update uint64 private s_latestPriceSequenceNumber; @@ -175,7 +182,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { SourceChainConfigArgs[] memory sourceChainConfigs ) MultiOCR3Base() { if ( - staticConfig.rmnProxy == address(0) || staticConfig.tokenAdminRegistry == address(0) + address(staticConfig.rmnRemote) == address(0) || staticConfig.tokenAdminRegistry == address(0) || staticConfig.nonceManager == address(0) ) { revert ZeroAddressNotAllowed(); @@ -186,7 +193,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } i_chainSelector = staticConfig.chainSelector; - i_rmnProxy = staticConfig.rmnProxy; + i_rmnRemote = staticConfig.rmnRemote; i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; i_nonceManager = staticConfig.nonceManager; emit StaticConfigSet(staticConfig); @@ -196,7 +203,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } // ================================================================ - // │ Messaging │ + // │ Execution │ // ================================================================ // The size of the execution state in bits @@ -204,15 +211,11 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { // The mask for the execution state bits uint256 private constant MESSAGE_EXECUTION_STATE_MASK = (1 << MESSAGE_EXECUTION_STATE_BIT_WIDTH) - 1; - // ================================================================ - // │ Execution │ - // ================================================================ - /// @notice Returns the current execution state of a message based on its sequenceNumber. /// @param sourceChainSelector The source chain to get the execution state for /// @param sequenceNumber The sequence number of the message to get the execution state for. - /// @return The current execution state of the message. - /// @dev we use the literal number 128 because using a constant increased gas usage. + /// @return executionState The current execution state of the message. + /// @dev We use the literal number 128 because using a constant increased gas usage. function getExecutionState( uint64 sourceChainSelector, uint64 sequenceNumber @@ -229,7 +232,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @param sourceChainSelector The source chain to set the execution state for /// @param sequenceNumber The sequence number for which the state will be saved. /// @param newState The new value the state will be in after this function is called. - /// @dev we use the literal number 128 because using a constant increased gas usage. + /// @dev We use the literal number 128 because using a constant increased gas usage. function _setExecutionState( uint64 sourceChainSelector, uint64 sequenceNumber, @@ -237,7 +240,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { ) internal { uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH; uint256 bitmap = _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber); - // to unset any potential existing state we zero the bits of the section the state occupies, + // To unset any potential existing state we zero the bits of the section the state occupies, // then we do an AND operation to blank out any existing state for the section. bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset); // Set the new state @@ -265,8 +268,8 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// insufficient gas provided. /// The reports do not have to contain all the messages (they can be omitted). Multiple reports can be passed in simultaneously. function manuallyExecute( - Internal.ExecutionReportSingleChain[] memory reports, - uint256[][] memory gasLimitOverrides + Internal.ExecutionReport[] memory reports, + GasLimitOverride[][] memory gasLimitOverrides ) external { // We do this here because the other _execute path is already covered by MultiOCR3Base. _whenChainNotForked(); @@ -275,18 +278,38 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { if (numReports != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); for (uint256 reportIndex = 0; reportIndex < numReports; ++reportIndex) { - Internal.ExecutionReportSingleChain memory report = reports[reportIndex]; + Internal.ExecutionReport memory report = reports[reportIndex]; uint256 numMsgs = report.messages.length; - uint256[] memory msgGasLimitOverrides = gasLimitOverrides[reportIndex]; + GasLimitOverride[] memory msgGasLimitOverrides = gasLimitOverrides[reportIndex]; if (numMsgs != msgGasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); for (uint256 msgIndex = 0; msgIndex < numMsgs; ++msgIndex) { - uint256 newLimit = msgGasLimitOverrides[msgIndex]; + uint256 newLimit = msgGasLimitOverrides[msgIndex].receiverExecutionGasLimit; // Checks to ensure message cannot be executed with less gas than specified. + Internal.Any2EVMRampMessage memory message = report.messages[msgIndex]; if (newLimit != 0) { - if (newLimit < report.messages[msgIndex].gasLimit) { - revert InvalidManualExecutionGasLimit(report.sourceChainSelector, msgIndex, newLimit); + if (newLimit < message.gasLimit) { + revert InvalidManualExecutionGasLimit(report.sourceChainSelector, message.header.messageId, newLimit); + } + } + if (message.tokenAmounts.length != msgGasLimitOverrides[msgIndex].tokenGasOverrides.length) { + revert ManualExecutionGasAmountCountMismatch(message.header.messageId, message.header.sequenceNumber); + } + + // The gas limit can not be lowered as that could cause the message to fail. If manual execution is done + // from an UNTOUCHED state and we would allow lower gas limit, anyone could grief by executing the message with + // lower gas limit than the DON would have used. This results in the message being marked FAILURE and the DON + // would not attempt it with the correct gas limit. + for (uint256 tokenIndex = 0; tokenIndex < message.tokenAmounts.length; ++tokenIndex) { + uint256 tokenGasOverride = msgGasLimitOverrides[msgIndex].tokenGasOverrides[tokenIndex]; + if (tokenGasOverride != 0) { + uint256 destGasAmount = message.tokenAmounts[tokenIndex].destGasAmount; + if (tokenGasOverride < destGasAmount) { + revert InvalidManualExecutionTokenGasOverride( + message.header.messageId, tokenIndex, destGasAmount, tokenGasOverride + ); + } } } } @@ -299,7 +322,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// and expects the exec plugin type to be configured with no signatures. /// @param report serialized execution report function execute(bytes32[3] calldata reportContext, bytes calldata report) external { - _batchExecute(abi.decode(report, (Internal.ExecutionReportSingleChain[])), new uint256[][](0)); + _batchExecute(abi.decode(report, (Internal.ExecutionReport[])), new GasLimitOverride[][](0)); bytes32[] memory emptySigs = new bytes32[](0); _transmit(uint8(Internal.OCRPluginType.Execution), reportContext, report, emptySigs, emptySigs, bytes32("")); @@ -313,36 +336,45 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @dev The manualExecGasLimits array should either be empty, or match the length of the reports array /// @dev If called from manual execution, each inner array's length has to match the number of messages. function _batchExecute( - Internal.ExecutionReportSingleChain[] memory reports, - uint256[][] memory manualExecGasLimits + Internal.ExecutionReport[] memory reports, + GasLimitOverride[][] memory manualExecGasOverrides ) internal { - if (reports.length == 0) revert EmptyReport(); + if (reports.length == 0) revert EmptyBatch(); - bool areManualGasLimitsEmpty = manualExecGasLimits.length == 0; + bool areManualGasLimitsEmpty = manualExecGasOverrides.length == 0; // Cache array for gas savings in the loop's condition - uint256[] memory emptyGasLimits = new uint256[](0); + GasLimitOverride[] memory emptyGasLimits = new GasLimitOverride[](0); for (uint256 i = 0; i < reports.length; ++i) { - _executeSingleReport(reports[i], areManualGasLimitsEmpty ? emptyGasLimits : manualExecGasLimits[i]); + _executeSingleReport(reports[i], areManualGasLimitsEmpty ? emptyGasLimits : manualExecGasOverrides[i]); } } /// @notice Executes a report, executing each message in order. /// @param report The execution report containing the messages and proofs. - /// @param manualExecGasLimits An array of gas limits to use for manual execution. + /// @param manualExecGasExecOverrides An array of gas limits to use for manual execution. /// @dev If called from the DON, this array is always empty. /// @dev If called from manual execution, this array is always same length as messages. function _executeSingleReport( - Internal.ExecutionReportSingleChain memory report, - uint256[] memory manualExecGasLimits + Internal.ExecutionReport memory report, + GasLimitOverride[] memory manualExecGasExecOverrides ) internal { uint64 sourceChainSelector = report.sourceChainSelector; - _whenNotCursed(sourceChainSelector); + bool manualExecution = manualExecGasExecOverrides.length != 0; + if (i_rmnRemote.isCursed(bytes16(uint128(sourceChainSelector)))) { + if (manualExecution) { + // For manual execution we don't want to silently fail so we revert + revert CursedByRMN(sourceChainSelector); + } + // For DON execution we do not revert as a single lane curse can revert the entire batch + emit SkippedReportExecution(sourceChainSelector); + return; + } - SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); + bytes memory onRamp = _getEnabledSourceChainConfig(sourceChainSelector).onRamp; uint256 numMsgs = report.messages.length; - if (numMsgs == 0) revert EmptyReport(); + if (numMsgs == 0) revert EmptyReport(report.sourceChainSelector); if (numMsgs != report.offchainTokenData.length) revert UnexpectedTokenData(); bytes32[] memory hashedLeaves = new bytes32[](numMsgs); @@ -355,12 +387,28 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { if (message.header.destChainSelector != i_chainSelector) { revert InvalidMessageDestChainSelector(message.header.destChainSelector); } + // If the message source chain selector does not match the report's source chain selector and + // the root has not been committed for the report source chain selector, this will be caught by the root verification. + // This acts as an extra check. + if (message.header.sourceChainSelector != sourceChainSelector) { + revert SourceChainSelectorMismatch(sourceChainSelector, message.header.sourceChainSelector); + } - // We do this hash here instead of in _verifyMessages to avoid two separate loops + // We do this hash here instead of in _verify to avoid two separate loops // over the same data, which increases gas cost. // Hashing all of the message fields ensures that the message being executed is correct and not tampered with. // Including the known OnRamp ensures that the message originates from the correct on ramp version - hashedLeaves[i] = Internal._hash(message, sourceChainConfig.onRamp); + hashedLeaves[i] = Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); } // SECURITY CRITICAL CHECK @@ -369,19 +417,12 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { if (timestampCommitted == 0) revert RootNotCommitted(sourceChainSelector); // Execute messages - bool manualExecution = manualExecGasLimits.length != 0; for (uint256 i = 0; i < numMsgs; ++i) { + uint256 gasStart = gasleft(); Internal.Any2EVMRampMessage memory message = report.messages[i]; Internal.MessageExecutionState originalState = getExecutionState(sourceChainSelector, message.header.sequenceNumber); - if (originalState == Internal.MessageExecutionState.SUCCESS) { - // If the message has already been executed, we skip it. We want to not revert on race conditions between - // executing parties. This will allow us to open up manual exec while also attempting with the DON, without - // reverting an entire DON batch when a user manually executes while the tx is inflight. - emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber); - continue; - } // Two valid cases here, we either have never touched this message before, or we tried to execute // and failed. This check protects against reentry and re-execution because the other state is // IN_PROGRESS which should not be allowed to execute. @@ -390,35 +431,43 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { originalState == Internal.MessageExecutionState.UNTOUCHED || originalState == Internal.MessageExecutionState.FAILURE ) - ) revert AlreadyExecuted(sourceChainSelector, message.header.sequenceNumber); - + ) { + // If the message has already been executed, we skip it. We want to not revert on race conditions between + // executing parties. This will allow us to open up manual exec while also attempting with the DON, without + // reverting an entire DON batch when a user manually executes while the tx is inflight. + emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber); + continue; + } + uint32[] memory tokenGasOverrides; if (manualExecution) { + tokenGasOverrides = manualExecGasExecOverrides[i].tokenGasOverrides; bool isOldCommitReport = (block.timestamp - timestampCommitted) > s_dynamicConfig.permissionLessExecutionThresholdSeconds; // Manually execution is fine if we previously failed or if the commit report is just too old - // Acceptable state transitions: FAILURE->SUCCESS, UNTOUCHED->SUCCESS, FAILURE->FAILURE + // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE, FAILURE->SUCCESS if (!(isOldCommitReport || originalState == Internal.MessageExecutionState.FAILURE)) { revert ManualExecutionNotYetEnabled(sourceChainSelector); } // Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override. - if (manualExecGasLimits[i] != 0) { - message.gasLimit = manualExecGasLimits[i]; + if (manualExecGasExecOverrides[i].receiverExecutionGasLimit != 0) { + message.gasLimit = manualExecGasExecOverrides[i].receiverExecutionGasLimit; } } else { // DON can only execute a message once // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE if (originalState != Internal.MessageExecutionState.UNTOUCHED) { - revert AlreadyAttempted(sourceChainSelector, message.header.sequenceNumber); + emit AlreadyAttempted(sourceChainSelector, message.header.sequenceNumber); + continue; } } // Nonce changes per state transition (these only apply for ordered messages): // UNTOUCHED -> FAILURE nonce bump // UNTOUCHED -> SUCCESS nonce bump - // FAILURE -> FAILURE no nonce bump // FAILURE -> SUCCESS no nonce bump // UNTOUCHED messages MUST be executed in order always + // If nonce == 0 then out of order execution is allowed if (message.header.nonce != 0) { if (originalState == Internal.MessageExecutionState.UNTOUCHED) { // If a nonce is not incremented, that means it was skipped, and we can ignore the message @@ -438,13 +487,12 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } _setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); - - (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData); + (Internal.MessageExecutionState newState, bytes memory returnData) = + _trialExecute(message, offchainTokenData, tokenGasOverrides); _setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState); - // Since it's hard to estimate whether manual execution will succeed, we - // revert the entire transaction if it fails. This will show the user if - // their manual exec will fail before they submit it. + // Since it's hard to estimate whether manual execution will succeed, we revert the entire transaction + // if it fails. This will show the user if their manual exec will fail before they submit it. if (manualExecution) { if (newState == Internal.MessageExecutionState.FAILURE) { if (originalState != Internal.MessageExecutionState.UNTOUCHED) { @@ -464,7 +512,15 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } emit ExecutionStateChanged( - sourceChainSelector, message.header.sequenceNumber, message.header.messageId, newState, returnData + sourceChainSelector, + message.header.sequenceNumber, + message.header.messageId, + hashedLeaves[i], + newState, + returnData, + // This emit covers not only the execution through the router, but also all of the overhead in executing the + // message. This gives the most accurate representation of the gas used in the execution. + gasStart - gasleft() ); } } @@ -472,13 +528,14 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Try executing a message. /// @param message Internal.Any2EVMRampMessage memory message. /// @param offchainTokenData Data provided by the DON for token transfers. - /// @return the new state of the message, being either SUCCESS or FAILURE. - /// @return revert data in bytes if CCIP receiver reverted during execution. + /// @return executionState The new state of the message, being either SUCCESS or FAILURE. + /// @return errData Revert data in bytes if CCIP receiver reverted during execution. function _trialExecute( Internal.Any2EVMRampMessage memory message, - bytes[] memory offchainTokenData - ) internal returns (Internal.MessageExecutionState, bytes memory) { - try this.executeSingleMessage(message, offchainTokenData) {} + bytes[] memory offchainTokenData, + uint32[] memory tokenGasOverrides + ) internal returns (Internal.MessageExecutionState executionState, bytes memory) { + try this.executeSingleMessage(message, offchainTokenData, tokenGasOverrides) {} catch (bytes memory err) { // 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 @@ -488,19 +545,28 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { return (Internal.MessageExecutionState.SUCCESS, ""); } - /// @notice Execute a single message. + /// @notice Executes a single message. /// @param message The message that will be executed. /// @param offchainTokenData Token transfer data to be passed to TokenPool. /// @dev We make this external and callable by the contract itself, in order to try/catch /// its execution and enforce atomicity among successful message processing and token transfer. /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts /// (for example smart contract wallets) without an associated message. - function executeSingleMessage(Internal.Any2EVMRampMessage memory message, bytes[] memory offchainTokenData) external { + function executeSingleMessage( + Internal.Any2EVMRampMessage memory message, + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides + ) external { if (msg.sender != address(this)) revert CanOnlySelfCall(); Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); if (message.tokenAmounts.length > 0) { destTokenAmounts = _releaseOrMintTokens( - message.tokenAmounts, message.sender, message.receiver, message.header.sourceChainSelector, offchainTokenData + message.tokenAmounts, + message.sender, + message.receiver, + message.header.sourceChainSelector, + offchainTokenData, + tokenGasOverrides ); } @@ -512,9 +578,9 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { destTokenAmounts: destTokenAmounts }); - address messageValidator = s_dynamicConfig.messageValidator; - if (messageValidator != address(0)) { - try IMessageInterceptor(messageValidator).onInboundMessage(any2EvmMessage) {} + address messageInterceptor = s_dynamicConfig.messageInterceptor; + if (messageInterceptor != address(0)) { + try IMessageInterceptor(messageInterceptor).onInboundMessage(any2EvmMessage) {} catch (bytes memory err) { revert IMessageInterceptor.MessageValidationError(err); } @@ -534,13 +600,167 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) ) return; - (bool success, bytes memory returnData,) = IRouter(s_dynamicConfig.router).routeMessage( - any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver - ); + (bool success, bytes memory returnData,) = s_sourceChainConfigs[message.header.sourceChainSelector] + .router + .routeMessage(any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver); // If CCIP receiver execution is not successful, revert the call including token transfers if (!success) revert ReceiverError(returnData); } + // ================================================================ + // │ Tokens and pools │ + // ================================================================ + + /// @notice Uses a pool to release or mint a token to a receiver address, with balance checks before and after the + /// transfer. This is done to ensure the exact number of tokens the pool claims to release are actually transferred. + /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the + /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by + /// registering the token on this chain, and re-trying the msg. + /// @param sourceTokenAmount Amount and source data of the token to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceChainSelector The remote source chain selector + /// @param offchainTokenData Data fetched offchain by the DON. + /// @return destTokenAmount local token address with amount + function _releaseOrMintSingleToken( + Internal.Any2EVMTokenTransfer memory sourceTokenAmount, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + bytes memory offchainTokenData + ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { + // We need to safely decode the token address from the sourceTokenData, as it could be wrong, + // in which case it doesn't have to be a valid EVM address. + // We assume this destTokenAddress has already been fully validated by a (trusted) OnRamp. + address localToken = sourceTokenAmount.destTokenAddress; + // We check with the token admin registry if the token has a pool on this chain. + address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); + // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. + // 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 gas estimations should + // account for 90k gas overhead due to the interface check. + if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { + revert NotACompatiblePool(localPoolAddress); + } + + // We retrieve the local token balance of the receiver before the pool call. + (uint256 balancePre, uint256 gasLeft) = _getBalanceOfReceiver(receiver, localToken, sourceTokenAmount.destGasAmount); + + // We determined that the pool address is a valid EVM address, but that does not mean the code at this + // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location + // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. + // We call the pool with exact gas to increase resistance against malicious tokens or token pools. + // We protect against return data bombs by capping the return data size at MAX_RET_BYTES. + (bool success, bytes memory returnData, uint256 gasUsedReleaseOrMint) = CallWithExactGas + ._callWithExactGasSafeReturnData( + abi.encodeCall( + IPoolV1.releaseOrMint, + Pool.ReleaseOrMintInV1({ + originalSender: originalSender, + receiver: receiver, + amount: sourceTokenAmount.amount, + localToken: localToken, + remoteChainSelector: sourceChainSelector, + sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, + sourcePoolData: sourceTokenAmount.extraData, + offchainTokenData: offchainTokenData + }) + ), + localPoolAddress, + gasLeft, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + + // Wrap and rethrow the error so we can catch it lower in the stack + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should be the local token amount. + if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { + revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); + } + + uint256 localAmount = abi.decode(returnData, (uint256)); + // We don't need to do balance checks if the pool is the receiver, as they would always fail in the case + // of a lockRelease pool. + if (receiver != localPoolAddress) { + (uint256 balancePost,) = _getBalanceOfReceiver(receiver, localToken, gasLeft - gasUsedReleaseOrMint); + + // First we check if the subtraction would result in an underflow to ensure we revert with a clear error + if (balancePost < balancePre || balancePost - balancePre != localAmount) { + revert ReleaseOrMintBalanceMismatch(localAmount, balancePre, balancePost); + } + } + + return Client.EVMTokenAmount({token: localToken, amount: localAmount}); + } + + /// @notice Retrieves the balance of a receiver address for a given token. + /// @param receiver The address to check the balance of. + /// @param token The token address. + /// @param gasLimit The gas limit to use for the call. + /// @return balance The balance of the receiver. + /// @return gasLeft The gas left after the call. + function _getBalanceOfReceiver( + address receiver, + address token, + uint256 gasLimit + ) internal returns (uint256 balance, uint256 gasLeft) { + (bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( + abi.encodeCall(IERC20.balanceOf, (receiver)), + token, + gasLimit, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should contain only the balance. + if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { + revert InvalidDataLength(Internal.MAX_BALANCE_OF_RET_BYTES, returnData.length); + } + + // Return the decoded balance, which cannot fail as we checked the length, and the gas that is left + // after this call. + return (abi.decode(returnData, (uint256)), gasLimit - gasUsed); + } + + /// @notice Uses pools to release or mint a number of different tokens to a receiver address. + /// @param sourceTokenAmounts List of token amounts with source data of the tokens to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceChainSelector The remote source chain selector. + /// @param offchainTokenData Array of token data fetched offchain by the DON. + /// @param tokenGasOverrides Array of override gas limits to use for token transfers. If empty, the normal gas limit + /// as defined on the source chain is used. + /// @return destTokenAmounts local token addresses with amounts + /// @dev This function wraps the token pool call in a try catch block to gracefully handle + /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error + /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. + function _releaseOrMintTokens( + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides + ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { + destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); + bool isTokenGasOverridesEmpty = tokenGasOverrides.length == 0; + for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { + if (!isTokenGasOverridesEmpty) { + if (tokenGasOverrides[i] != 0) { + sourceTokenAmounts[i].destGasAmount = tokenGasOverrides[i]; + } + } + destTokenAmounts[i] = _releaseOrMintSingleToken( + sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] + ); + } + + return destTokenAmounts; + } + // ================================================================ // │ Commit │ // ================================================================ @@ -552,32 +772,37 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// 1. Price updates /// 2. A batch of merkle root and sequence number intervals (per-source) /// Both have their own, separate, staleness checks, with price updates using the epoch and round - /// number of the latest price update. The merkle root checks for staleness based on the seqNums. + /// number of the latest price update. The merkle root checks for staleness are based on the seqNums. /// They need to be separate because a price report for round t+2 might be included before a report /// containing a merkle root for round t+1. This merkle root report for round t+1 is still valid /// and should not be rejected. When a report with a stale root but valid price updates is submitted, /// we are OK to revert to preserve the invariant that we always revert on invalid sequence number ranges. - /// If that happens, prices will be updates in later rounds. + /// If that happens, prices will be updated in later rounds. function commit( bytes32[3] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, - bytes32 rawVs // signatures + bytes32 rawVs ) external { CommitReport memory commitReport = abi.decode(report, (CommitReport)); + // Verify RMN signatures + if (commitReport.merkleRoots.length > 0) { + i_rmnRemote.verify(address(this), commitReport.merkleRoots, commitReport.rmnSignatures, commitReport.rmnRawVs); + } + // Check if the report contains price updates if (commitReport.priceUpdates.tokenPriceUpdates.length > 0 || commitReport.priceUpdates.gasPriceUpdates.length > 0) { - uint64 sequenceNumber = uint64(uint256(reportContext[1])); + uint64 ocrSequenceNumber = uint64(uint256(reportContext[1])); // Check for price staleness based on the epoch and round - if (s_latestPriceSequenceNumber < sequenceNumber) { + if (s_latestPriceSequenceNumber < ocrSequenceNumber) { // If prices are not stale, update the latest epoch and round - s_latestPriceSequenceNumber = sequenceNumber; - // And update the prices in the price registry - IPriceRegistry(s_dynamicConfig.priceRegistry).updatePrices(commitReport.priceUpdates); + s_latestPriceSequenceNumber = ocrSequenceNumber; + // And update the prices in the fee quoter + IFeeQuoter(s_dynamicConfig.feeQuoter).updatePrices(commitReport.priceUpdates); } else { // If prices are stale and the report doesn't contain a root, this report // does not have any valid information and we revert. @@ -587,38 +812,44 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } for (uint256 i = 0; i < commitReport.merkleRoots.length; ++i) { - MerkleRoot memory root = commitReport.merkleRoots[i]; + Internal.MerkleRoot memory root = commitReport.merkleRoots[i]; uint64 sourceChainSelector = root.sourceChainSelector; - _whenNotCursed(sourceChainSelector); + if (i_rmnRemote.isCursed(bytes16(uint128(sourceChainSelector)))) { + revert CursedByRMN(sourceChainSelector); + } + SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); - // If we reached this section, the report should contain a valid root - if (sourceChainConfig.minSeqNr != root.interval.min || root.interval.min > root.interval.max) { - revert InvalidInterval(root.sourceChainSelector, root.interval); + if (keccak256(root.onRampAddress) != keccak256(sourceChainConfig.onRamp)) { + revert CommitOnRampMismatch(root.onRampAddress, sourceChainConfig.onRamp); + } + + if (sourceChainConfig.minSeqNr != root.minSeqNr || root.minSeqNr > root.maxSeqNr) { + revert InvalidInterval(root.sourceChainSelector, root.minSeqNr, root.maxSeqNr); } - // TODO: confirm how RMN offchain blessing impacts commit report bytes32 merkleRoot = root.merkleRoot; if (merkleRoot == bytes32(0)) revert InvalidRoot(); - // Disallow duplicate roots as that would reset the timestamp and + // If we reached this section, the report should contain a valid root + // We disallow duplicate roots as that would reset the timestamp and // delay potential manual execution. if (s_roots[root.sourceChainSelector][merkleRoot] != 0) { revert RootAlreadyCommitted(root.sourceChainSelector, merkleRoot); } - sourceChainConfig.minSeqNr = root.interval.max + 1; + sourceChainConfig.minSeqNr = root.maxSeqNr + 1; s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp; } - emit CommitReportAccepted(commitReport); + emit CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); _transmit(uint8(Internal.OCRPluginType.Commit), reportContext, report, rs, ss, rawVs); } /// @notice Returns the sequence number of the last price update. - /// @return the latest price update sequence number. - function getLatestPriceSequenceNumber() public view returns (uint64) { + /// @return sequenceNumber The latest price update sequence number. + function getLatestPriceSequenceNumber() external view returns (uint64) { return s_latestPriceSequenceNumber; } @@ -626,38 +857,17 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// If the root was never committed 0 will be returned. /// @param sourceChainSelector The source chain selector. /// @param root The merkle root to check the commit status for. - /// @return the timestamp of the committed root or zero in the case that it was never + /// @return timestamp The timestamp of the committed root or zero in the case that it was never /// committed. function getMerkleRoot(uint64 sourceChainSelector, bytes32 root) external view returns (uint256) { return s_roots[sourceChainSelector][root]; } - /// @notice Returns if a root is blessed or not. - /// @param root The merkle root to check the blessing status for. - /// @return whether the root is blessed or not. - function isBlessed(bytes32 root) public view returns (bool) { - // TODO: update RMN to also consider the source chain selector for blessing - return IRMN(i_rmnProxy).isBlessed(IRMN.TaggedRoot({commitStore: address(this), root: root})); - } - - /// @notice Used by the owner in case an invalid sequence of roots has been - /// posted and needs to be removed. The interval in the report is trusted. - /// @param rootToReset The roots that will be reset. This function will only - /// reset roots that are not blessed. - function resetUnblessedRoots(UnblessedRoot[] calldata rootToReset) external onlyOwner { - for (uint256 i = 0; i < rootToReset.length; ++i) { - UnblessedRoot memory root = rootToReset[i]; - if (!isBlessed(root.merkleRoot)) { - delete s_roots[root.sourceChainSelector][root.merkleRoot]; - emit RootRemoved(root.merkleRoot); - } - } - } - /// @notice Returns timestamp of when root was accepted or 0 if verification fails. /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves, /// proofs and proofFlagBits being used to get the root of the inner tree. /// This root is then used as the singular leaf of the outer tree. + /// @return timestamp The commit timestamp of the root function _verify( uint64 sourceChainSelector, bytes32[] memory hashedLeaves, @@ -665,16 +875,18 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { uint256 proofFlagBits ) internal view virtual returns (uint256 timestamp) { bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits); - // Only return non-zero if present and blessed. - if (!isBlessed(root)) { - return 0; - } return s_roots[sourceChainSelector][root]; } /// @inheritdoc MultiOCR3Base - function _afterOCR3ConfigSet(uint8 ocrPluginType) internal override { + function _afterOCR3ConfigSet( + uint8 ocrPluginType + ) internal override { if (ocrPluginType == uint8(Internal.OCRPluginType.Commit)) { + // Signature verification must be enabled for commit plugin + if (!s_ocrConfigs[ocrPluginType].configInfo.isSignatureVerificationEnabled) { + revert SignatureVerificationDisabled(); + } // When the OCR config changes, we reset the sequence number // since it is scoped per config digest. // Note that s_minSeqNr/roots do not need to be reset as the roots persist @@ -690,37 +902,56 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Returns the static config. /// @dev This function will always return the same struct as the contents is static and can never change. /// RMN depends on this function, if changing, please notify the RMN maintainers. + /// @return staticConfig The static config. function getStaticConfig() external view returns (StaticConfig memory) { return StaticConfig({ chainSelector: i_chainSelector, - rmnProxy: i_rmnProxy, + rmnRemote: i_rmnRemote, tokenAdminRegistry: i_tokenAdminRegistry, nonceManager: i_nonceManager }); } /// @notice Returns the current dynamic config. - /// @return The current config. + /// @return dynamicConfig The current dynamic config. function getDynamicConfig() external view returns (DynamicConfig memory) { return s_dynamicConfig; } /// @notice Returns the source chain config for the provided source chain selector /// @param sourceChainSelector chain to retrieve configuration for - /// @return SourceChainConfig config for the source chain - function getSourceChainConfig(uint64 sourceChainSelector) external view returns (SourceChainConfig memory) { + /// @return sourceChainConfig The config for the source chain + function getSourceChainConfig( + uint64 sourceChainSelector + ) external view returns (SourceChainConfig memory) { return s_sourceChainConfigs[sourceChainSelector]; } + /// @notice Returns all source chain configs + /// @return sourceChainConfigs The source chain configs corresponding to all the supported chain selectors + function getAllSourceChainConfigs() external view returns (uint64[] memory, SourceChainConfig[] memory) { + SourceChainConfig[] memory sourceChainConfigs = new SourceChainConfig[](s_sourceChainSelectors.length()); + uint64[] memory sourceChainSelectors = new uint64[](s_sourceChainSelectors.length()); + for (uint256 i = 0; i < s_sourceChainSelectors.length(); ++i) { + sourceChainSelectors[i] = uint64(s_sourceChainSelectors.at(i)); + sourceChainConfigs[i] = s_sourceChainConfigs[sourceChainSelectors[i]]; + } + return (sourceChainSelectors, sourceChainConfigs); + } + /// @notice Updates source configs /// @param sourceChainConfigUpdates Source chain configs - function applySourceChainConfigUpdates(SourceChainConfigArgs[] memory sourceChainConfigUpdates) external onlyOwner { + function applySourceChainConfigUpdates( + SourceChainConfigArgs[] memory sourceChainConfigUpdates + ) external onlyOwner { _applySourceChainConfigUpdates(sourceChainConfigUpdates); } /// @notice Updates source configs /// @param sourceChainConfigUpdates Source chain configs - function _applySourceChainConfigUpdates(SourceChainConfigArgs[] memory sourceChainConfigUpdates) internal { + function _applySourceChainConfigUpdates( + SourceChainConfigArgs[] memory sourceChainConfigUpdates + ) internal { for (uint256 i = 0; i < sourceChainConfigUpdates.length; ++i) { SourceChainConfigArgs memory sourceConfigUpdate = sourceChainConfigUpdates[i]; uint64 sourceChainSelector = sourceConfigUpdate.sourceChainSelector; @@ -729,39 +960,55 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { revert ZeroChainSelectorNotAllowed(); } + if (address(sourceConfigUpdate.router) == address(0)) { + revert ZeroAddressNotAllowed(); + } + SourceChainConfig storage currentConfig = s_sourceChainConfigs[sourceChainSelector]; - bytes memory currentOnRamp = currentConfig.onRamp; bytes memory newOnRamp = sourceConfigUpdate.onRamp; - // OnRamp can never be zero - if it is, then the source chain has been added for the first time - if (currentOnRamp.length == 0) { - if (newOnRamp.length == 0) { - revert ZeroAddressNotAllowed(); - } - - currentConfig.onRamp = newOnRamp; + if (currentConfig.onRamp.length == 0) { currentConfig.minSeqNr = 1; emit SourceChainSelectorAdded(sourceChainSelector); - } else if (keccak256(currentOnRamp) != keccak256(newOnRamp)) { - revert InvalidStaticConfig(sourceChainSelector); + } else { + if (currentConfig.minSeqNr != 1) { + // OnRamp updates should only happens due to a misconfiguration + // If an OnRamp is misconfigured, no reports should have been committed and no messages should have been executed + // This is enforced by the onRamp address check in the commit function + revert InvalidOnRampUpdate(sourceChainSelector); + } } - // The only dynamic config is the isEnabled flag + // OnRamp can never be zero - if it is, then the source chain has been added for the first time + if (newOnRamp.length == 0 || keccak256(newOnRamp) == EMPTY_ENCODED_ADDRESS_HASH) { + revert ZeroAddressNotAllowed(); + } + + currentConfig.onRamp = newOnRamp; currentConfig.isEnabled = sourceConfigUpdate.isEnabled; + currentConfig.router = sourceConfigUpdate.router; + + // We don't need to check the return value, as inserting the item twice has no effect. + s_sourceChainSelectors.add(sourceChainSelector); + emit SourceChainConfigSet(sourceChainSelector, currentConfig); } } /// @notice Sets the dynamic config. /// @param dynamicConfig The new dynamic config. - function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner { + function setDynamicConfig( + DynamicConfig memory dynamicConfig + ) external onlyOwner { _setDynamicConfig(dynamicConfig); } /// @notice Sets the dynamic config. /// @param dynamicConfig The dynamic config. - function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal { - if (dynamicConfig.priceRegistry == address(0) || dynamicConfig.router == address(0)) { + function _setDynamicConfig( + DynamicConfig memory dynamicConfig + ) internal { + if (dynamicConfig.feeQuoter == address(0)) { revert ZeroAddressNotAllowed(); } @@ -772,8 +1019,10 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Returns a source chain config with a check that the config is enabled /// @param sourceChainSelector Source chain selector to check for cursing - /// @return sourceChainConfig Source chain config - function _getEnabledSourceChainConfig(uint64 sourceChainSelector) internal view returns (SourceChainConfig storage) { + /// @return sourceChainConfig The source chain config storage pointer + function _getEnabledSourceChainConfig( + uint64 sourceChainSelector + ) internal view returns (SourceChainConfig storage) { SourceChainConfig storage sourceChainConfig = s_sourceChainConfigs[sourceChainSelector]; if (!sourceChainConfig.isEnabled) { revert SourceChainNotEnabled(sourceChainSelector); @@ -783,132 +1032,14 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @notice Uses a pool to release or mint a token to a receiver address in two steps. First, the pool is called - /// to release the tokens to the offRamp, then the offRamp calls the token contract to transfer the tokens to the - /// receiver. This is done to ensure the exact number of tokens, the pool claims to release are actually transferred. - /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the - /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by - /// registering the token on this chain, and re-trying the msg. - /// @param sourceTokenAmount Amount and source data of the token to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceChainSelector The remote source chain selector - /// @param offchainTokenData Data fetched offchain by the DON. - /// @return destTokenAmount local token address with amount - function _releaseOrMintSingleToken( - Internal.RampTokenAmount memory sourceTokenAmount, - bytes memory originalSender, - address receiver, - uint64 sourceChainSelector, - bytes memory offchainTokenData - ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { - // We need to safely decode the token address from the sourceTokenData, as it could be wrong, - // in which case it doesn't have to be a valid EVM address. - address localToken = Internal._validateEVMAddress(sourceTokenAmount.destTokenAddress); - // We check with the token admin registry if the token has a pool on this chain. - address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); - // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. - // 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 gas estimations should - // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { - revert NotACompatiblePool(localPoolAddress); - } - - // We determined that the pool address is a valid EVM address, but that does not mean the code at this - // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location - // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. - // We call the pool with exact gas to increase resistance against malicious tokens or token pools. - // We protects against return data bombs by capping the return data size at MAX_RET_BYTES. - (bool success, bytes memory returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall( - IPoolV1.releaseOrMint, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: receiver, - amount: sourceTokenAmount.amount, - localToken: localToken, - remoteChainSelector: sourceChainSelector, - sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, - sourcePoolData: sourceTokenAmount.extraData, - offchainTokenData: offchainTokenData - }) - ), - localPoolAddress, - s_dynamicConfig.maxPoolReleaseOrMintGas, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - // wrap and rethrow the error so we can catch it lower in the stack - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should be the local token address. - if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { - revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); - } - uint256 localAmount = abi.decode(returnData, (uint256)); - // Since token pools send the tokens to the msg.sender, which is this offRamp, we need to - // transfer them to the final receiver. We use the _callWithExactGasSafeReturnData function because - // the token contracts are not considered trusted. - (success, returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall(IERC20.transfer, (receiver, localAmount)), - localToken, - s_dynamicConfig.maxTokenTransferGas, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - if (!success) revert TokenHandlingError(returnData); - - return Client.EVMTokenAmount({token: localToken, amount: localAmount}); - } - - /// @notice Uses pools to release or mint a number of different tokens to a receiver address. - /// @param sourceTokenAmounts List of token amounts with source data of the tokens to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceChainSelector The remote source chain selector - /// @param offchainTokenData Array of token data fetched offchain by the DON. - /// @return destTokenAmounts local token addresses with amounts - /// @dev This function wrappes the token pool call in a try catch block to gracefully handle - /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error - /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. - function _releaseOrMintTokens( - Internal.RampTokenAmount[] memory sourceTokenAmounts, - bytes memory originalSender, - address receiver, - uint64 sourceChainSelector, - bytes[] memory offchainTokenData - ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { - destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); - for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { - destTokenAmounts[i] = _releaseOrMintSingleToken( - sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] - ); - } - - return destTokenAmounts; - } - - // ================================================================ - // │ Access and RMN │ + // │ Access │ // ================================================================ - /// @notice Reverts as this contract should not access CCIP messages - function ccipReceive(Client.Any2EVMMessage calldata) external pure { + /// @notice Reverts as this contract should not be able to receive CCIP messages + function ccipReceive( + Client.Any2EVMMessage calldata + ) external pure { // solhint-disable-next-line revert(); } - - /// @notice Validates that the source chain -> this chain lane, and reverts if it is cursed - /// @param sourceChainSelector Source chain selector to check for cursing - function _whenNotCursed(uint64 sourceChainSelector) internal view { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { - revert CursedByRMN(sourceChainSelector); - } - } } diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol deleted file mode 100644 index fc455cc869e..00000000000 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol +++ /dev/null @@ -1,339 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; -import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; -import {INonceManager} from "../interfaces/INonceManager.sol"; -import {IPoolV1} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.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 The EVM2EVMMultiOnRamp is a contract that handles lane-specific fee logic -/// @dev The EVM2EVMMultiOnRamp, MultiCommitStore and EVM2EVMMultiOffRamp form an xchain upgradeable unit. Any change to one of them -/// results an onchain upgrade of all 3. -contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { - using SafeERC20 for IERC20; - using USDPriceWith18Decimals for uint224; - - error CannotSendZeroTokens(); - error InvalidExtraArgsTag(); - error ExtraArgOutOfOrderExecutionMustBeTrue(); - error OnlyCallableByOwnerOrAdmin(); - error MessageGasLimitTooHigh(); - error UnsupportedToken(address token); - error MustBeCalledByRouter(); - error RouterMustSetOriginalSender(); - error InvalidConfig(); - error CursedByRMN(uint64 sourceChainSelector); - error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - - event AdminSet(address newAdmin); - event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); - event FeePaid(address indexed feeToken, uint256 feeValueJuels); - event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); - /// RMN depends on this event, if changing, please notify the RMN maintainers. - event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); - - /// @dev Struct that contains the static configuration - /// RMN depends on this struct, if changing, please notify the RMN maintainers. - // solhint-disable-next-line gas-struct-packing - struct StaticConfig { - uint64 chainSelector; // ─────╮ Source chainSelector - address rmnProxy; // ─────────╯ Address of RMN proxy - address nonceManager; // Address of the nonce manager - address tokenAdminRegistry; // Token admin registry address - } - - /// @dev Struct to contains the dynamic configuration - // solhint-disable-next-line gas-struct-packing - struct DynamicConfig { - address router; // Router address - address priceRegistry; // Price registry address - address messageValidator; // Optional message validator to validate outbound messages (zero address = no validator) - address feeAggregator; // Fee aggregator address - } - - // STATIC CONFIG - string public constant override typeAndVersion = "EVM2EVMMultiOnRamp 1.6.0-dev"; - /// @dev The chain ID of the source chain that this contract is deployed to - uint64 internal immutable i_chainSelector; - /// @dev The address of the rmn proxy - address internal immutable i_rmnProxy; - /// @dev The address of the nonce manager - address internal immutable i_nonceManager; - /// @dev The address of the token admin registry - address internal immutable i_tokenAdminRegistry; - /// @dev the maximum number of nops that can be configured at the same time. - /// Used to bound gas for loops over nops. - uint256 private constant MAX_NUMBER_OF_NOPS = 64; - - // DYNAMIC CONFIG - /// @dev The config for the onRamp - DynamicConfig internal s_dynamicConfig; - - /// @dev Last used sequence number per destination chain. - /// This is zero in the case where no messages have been sent yet. - /// 0 is not a valid sequence number for any real transaction. - mapping(uint64 destChainSelector => uint64 sequenceNumber) internal s_destChainSequenceNumbers; - - // STATE - /// @dev The amount of LINK available to pay NOPS - uint96 internal s_nopFeesJuels; - /// @dev The combined weight of all NOPs weights - uint32 internal s_nopWeightsTotal; - - constructor(StaticConfig memory staticConfig, DynamicConfig memory dynamicConfig) { - if ( - staticConfig.chainSelector == 0 || staticConfig.rmnProxy == address(0) || staticConfig.nonceManager == address(0) - || staticConfig.tokenAdminRegistry == address(0) - ) { - revert InvalidConfig(); - } - - i_chainSelector = staticConfig.chainSelector; - i_rmnProxy = staticConfig.rmnProxy; - i_nonceManager = staticConfig.nonceManager; - i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; - - _setDynamicConfig(dynamicConfig); - } - - // ================================================================ - // │ Messaging │ - // ================================================================ - - /// @notice Gets the next sequence number to be used in the onRamp - /// @param destChainSelector The destination chain selector - /// @return the next sequence number to be used - function getExpectedNextSequenceNumber(uint64 destChainSelector) external view returns (uint64) { - return s_destChainSequenceNumbers[destChainSelector] + 1; - } - - /// @inheritdoc IEVM2AnyOnRampClient - function forwardFromRouter( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message, - uint256 feeTokenAmount, - address originalSender - ) external returns (bytes32) { - // NOTE: assumes the message has already been validated through the getFee call - // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. - if (originalSender == address(0)) revert RouterMustSetOriginalSender(); - // Router address may be zero intentionally to pause. - if (msg.sender != s_dynamicConfig.router) revert MustBeCalledByRouter(); - - address messageValidator = s_dynamicConfig.messageValidator; - if (messageValidator != address(0)) { - IMessageInterceptor(messageValidator).onOutboundMessage(destChainSelector, message); - } - - // Convert message fee to juels and retrieve converted args - (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) = IPriceRegistry( - s_dynamicConfig.priceRegistry - ).processMessageArgs(destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs); - - emit FeePaid(message.feeToken, msgFeeJuels); - - Internal.EVM2AnyRampMessage memory newMessage = Internal.EVM2AnyRampMessage({ - header: Internal.RampMessageHeader({ - // Should be generated after the message is complete - messageId: "", - sourceChainSelector: i_chainSelector, - destChainSelector: destChainSelector, - // We need the next available sequence number so we increment before we use the value - sequenceNumber: ++s_destChainSequenceNumbers[destChainSelector], - // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we - // may block ordered message nonces, which is not what we want. - nonce: isOutOfOrderExecution - ? 0 - : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender) - }), - sender: originalSender, - data: message.data, - extraArgs: message.extraArgs, - receiver: message.receiver, - feeToken: message.feeToken, - feeTokenAmount: feeTokenAmount, - // Should be populated via lock / burn pool calls - tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) - }); - - // Lock the tokens as last step. TokenPools may not always be trusted. - // There should be no state changes after external call to TokenPools. - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - newMessage.tokenAmounts[i] = - _lockOrBurnSingleToken(message.tokenAmounts[i], destChainSelector, message.receiver, originalSender); - } - - // Validate pool return data after it is populated (view function - no state changes) - IPriceRegistry(s_dynamicConfig.priceRegistry).validatePoolReturnData( - destChainSelector, newMessage.tokenAmounts, message.tokenAmounts - ); - - // Override extraArgs with latest version - newMessage.extraArgs = convertedExtraArgs; - - // Hash only after all fields have been set - newMessage.header.messageId = Internal._hash( - newMessage, - // Metadata hash preimage to ensure global uniqueness, ensuring 2 identical messages sent to 2 different - // lanes will have a distinct hash. - keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))) - ); - - // Emit message request - // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this - // event in the offchain code. - emit CCIPSendRequested(destChainSelector, newMessage); - return newMessage.header.messageId; - } - - /// @notice Uses a pool to lock or burn a token - /// @param tokenAndAmount Token address and amount to lock or burn - /// @param destChainSelector Target dest chain selector of the message - /// @param receiver Message receiver - /// @param originalSender Message sender - /// @return rampTokenAndAmount Ramp token and amount data - function _lockOrBurnSingleToken( - Client.EVMTokenAmount memory tokenAndAmount, - uint64 destChainSelector, - bytes memory receiver, - address originalSender - ) internal returns (Internal.RampTokenAmount memory) { - if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); - - IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); - // We don't have to check if it supports the pool version in a non-reverting way here because - // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface - // function and not through the ERC165Checker. - if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { - revert UnsupportedToken(tokenAndAmount.token); - } - - Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: receiver, - remoteChainSelector: destChainSelector, - originalSender: originalSender, - amount: tokenAndAmount.amount, - localToken: tokenAndAmount.token - }) - ); - - // NOTE: pool data validations are outsourced to the PriceRegistry to handle family-specific logic handling - - return Internal.RampTokenAmount({ - sourcePoolAddress: abi.encode(sourcePool), - destTokenAddress: poolReturnData.destTokenAddress, - extraData: poolReturnData.destPoolData, - amount: tokenAndAmount.amount - }); - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Returns the static onRamp config. - /// @dev RMN depends on this function, if changing, please notify the RMN maintainers. - /// @return the configuration. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - chainSelector: i_chainSelector, - rmnProxy: i_rmnProxy, - nonceManager: i_nonceManager, - tokenAdminRegistry: i_tokenAdminRegistry - }); - } - - /// @notice Returns the dynamic onRamp config. - /// @return dynamicConfig the configuration. - function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig) { - return s_dynamicConfig; - } - - /// @notice Sets the dynamic configuration. - /// @param dynamicConfig The configuration. - function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner { - _setDynamicConfig(dynamicConfig); - } - - /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. - function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal { - // We permit router to be set to zero as a way to pause the contract. - if (dynamicConfig.priceRegistry == address(0) || dynamicConfig.feeAggregator == address(0)) revert InvalidConfig(); - - s_dynamicConfig = dynamicConfig; - - emit ConfigSet( - StaticConfig({ - chainSelector: i_chainSelector, - rmnProxy: i_rmnProxy, - nonceManager: i_nonceManager, - tokenAdminRegistry: i_tokenAdminRegistry - }), - dynamicConfig - ); - } - - // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRampClient - function getPoolBySourceToken(uint64, /*destChainSelector*/ IERC20 sourceToken) public view returns (IPoolV1) { - return IPoolV1(ITokenAdminRegistry(i_tokenAdminRegistry).getPool(address(sourceToken))); - } - - /// @inheritdoc IEVM2AnyOnRampClient - function getSupportedTokens(uint64 /*destChainSelector*/ ) external pure returns (address[] memory) { - revert GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - } - - // ================================================================ - // │ Fees │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRampClient - /// @dev getFee MUST revert if the feeToken is not listed in the fee token config, as the router assumes it does. - /// @param destChainSelector The destination chain selector. - /// @param message The message to get quote for. - /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. - function getFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount) { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); - - return IPriceRegistry(s_dynamicConfig.priceRegistry).getValidatedFee(destChainSelector, message); - } - - /// @notice Withdraws the outstanding fee token balances to the fee aggregator. - /// @dev This function can be permissionless as it only transfers accepted fee tokens to the fee aggregator which is a trusted address. - function withdrawFeeTokens() external { - address[] memory feeTokens = IPriceRegistry(s_dynamicConfig.priceRegistry).getFeeTokens(); - address feeAggregator = s_dynamicConfig.feeAggregator; - - for (uint256 i = 0; i < feeTokens.length; ++i) { - IERC20 feeToken = IERC20(feeTokens[i]); - uint256 feeTokenBalance = feeToken.balanceOf(address(this)); - - if (feeTokenBalance > 0) { - feeToken.safeTransfer(feeAggregator, feeTokenBalance); - - emit FeeTokenWithdrawn(feeAggregator, address(feeToken), feeTokenBalance); - } - } - } -} diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol deleted file mode 100644 index 0e978596e4c..00000000000 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol +++ /dev/null @@ -1,916 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IEVM2AnyOnRamp} from "../interfaces/IEVM2AnyOnRamp.sol"; -import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; -import {IPoolV1} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; -import {ILinkAvailable} from "../interfaces/automation/ILinkAvailable.sol"; - -import {AggregateRateLimiter} from "../AggregateRateLimiter.sol"; -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.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"; -import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; - -/// @notice The onRamp is a contract that handles lane-specific fee logic, NOP payments and -/// bridgeable token support. -/// @dev The EVM2EVMOnRamp, CommitStore and EVM2EVMOffRamp form an xchain upgradeable unit. Any change to one of them -/// results an onchain upgrade of all 3. -contract EVM2EVMOnRamp is IEVM2AnyOnRamp, ILinkAvailable, AggregateRateLimiter, ITypeAndVersion { - using SafeERC20 for IERC20; - using EnumerableMap for EnumerableMap.AddressToUintMap; - using USDPriceWith18Decimals for uint224; - - error InvalidExtraArgsTag(); - error ExtraArgOutOfOrderExecutionMustBeTrue(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrAdminOrNop(); - error InvalidWithdrawParams(); - error NoFeesToPay(); - error NoNopsToPay(); - error InsufficientBalance(); - error TooManyNops(); - error MaxFeeBalanceReached(); - error MessageTooLarge(uint256 maxSize, uint256 actualSize); - error MessageGasLimitTooHigh(); - error UnsupportedNumberOfTokens(); - error UnsupportedToken(address token); - error MustBeCalledByRouter(); - error RouterMustSetOriginalSender(); - error InvalidConfig(); - error CursedByRMN(); - error LinkBalanceNotSettled(); - error InvalidNopAddress(address nop); - error NotAFeeToken(address token); - error CannotSendZeroTokens(); - error SourceTokenDataTooLarge(address token); - error InvalidChainSelector(uint64 chainSelector); - error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); - - event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); - event NopPaid(address indexed nop, uint256 amount); - event FeeConfigSet(FeeTokenConfigArgs[] feeConfig); - event TokenTransferFeeConfigSet(TokenTransferFeeConfigArgs[] transferFeeConfig); - event TokenTransferFeeConfigDeleted(address[] tokens); - /// RMN depends on this event, if changing, please notify the RMN maintainers. - event CCIPSendRequested(Internal.EVM2EVMMessage message); - event NopsSet(uint256 nopWeightsTotal, NopAndWeight[] nopsAndWeights); - - /// @dev Struct that contains the static configuration - /// RMN depends on this struct, if changing, please notify the RMN maintainers. - //solhint-disable gas-struct-packing - struct StaticConfig { - address linkToken; // ────────╮ Link token address - uint64 chainSelector; // ─────╯ Source chainSelector - uint64 destChainSelector; // ─╮ Destination chainSelector - uint64 defaultTxGasLimit; // │ Default gas limit for a tx - uint96 maxNopFeesJuels; // ───╯ Max nop fee balance onramp can have - address prevOnRamp; // Address of previous-version OnRamp - address rmnProxy; // Address of RMN proxy - address tokenAdminRegistry; // Address of the token admin registry - } - - /// @dev Struct to contains the dynamic configuration - struct DynamicConfig { - address router; // ──────────────────────────╮ Router address - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message - uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs - uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver - uint32 destDataAvailabilityOverheadGas; // ──╯ Extra data availability gas charged on top of the message, e.g. for OCR - uint16 destGasPerDataAvailabilityByte; // ───╮ Amount of gas to charge per byte of message data that needs availability - uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 - address priceRegistry; // │ Price registry address - uint32 maxDataBytes; // │ Maximum payload data size in bytes - uint32 maxPerMsgGasLimit; // ────────────────╯ Maximum gas limit for messages targeting EVMs - // │ - // 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 the token transfer on the destination chain - // │ Default data availability bytes that are returned from the source pool and sent - uint32 defaultTokenDestBytesOverhead; // | to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - bool enforceOutOfOrder; // ──────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. - } - - /// @dev Struct to hold the execution fee configuration for a fee token - struct FeeTokenConfig { - uint32 networkFeeUSDCents; // ─────────╮ Flat network fee to charge for messages, multiples of 0.01 USD - uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. - uint64 premiumMultiplierWeiPerEth; // │ Multiplier for fee-token-specific premiums - bool enabled; // ──────────────────────╯ Whether this fee token is enabled - } - - /// @dev Struct to hold the fee configuration for a fee token, same as the FeeTokenConfig but with - /// token included so that an array of these can be passed in to setFeeTokenConfig to set the mapping - struct FeeTokenConfigArgs { - address token; // ─────────────────────╮ Token address - uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD - uint64 gasMultiplierWeiPerEth; // ─────╯ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost - uint64 premiumMultiplierWeiPerEth; // ─╮ Multiplier for fee-token-specific premiums, 1e18 based - bool enabled; // ──────────────────────╯ Whether this fee token is enabled - } - - /// @dev Struct to hold the transfer fee configuration for token transfers - struct TokenTransferFeeConfig { - uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD - uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD - uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 - uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain - // │ Extra data availability bytes that are returned from the source pool and sent - uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - bool aggregateRateLimitEnabled; // │ Whether this transfer token is to be included in Aggregate Rate Limiting - bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees - } - - /// @dev Same as TokenTransferFeeConfig - /// token included so that an array of these can be passed in to setTokenTransferFeeConfig - struct TokenTransferFeeConfigArgs { - address token; // ──────────────────╮ Token address - uint32 minFeeUSDCents; // │ Minimum fee to charge per token transfer, multiples of 0.01 USD - uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD - uint16 deciBps; // ─────────────────╯ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 - uint32 destGasOverhead; // ─────────╮ Gas charged to execute the token transfer on the destination chain - // │ Extra data availability bytes that are returned from the source pool and sent - uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - bool aggregateRateLimitEnabled; // ─╯ Whether this transfer token is to be included in Aggregate Rate Limiting - } - - /// @dev Nop address and weight, used to set the nops and their weights - struct NopAndWeight { - address nop; // ────╮ Address of the node operator - uint16 weight; // ──╯ Weight for nop rewards - } - - // STATIC CONFIG - string public constant override typeAndVersion = "EVM2EVMOnRamp 1.5.0-dev"; - /// @dev metadataHash is a lane-specific prefix for a message hash preimage which ensures global uniqueness - /// Ensures that 2 identical messages sent to 2 different lanes will have a distinct hash. - /// Must match the metadataHash used in computing leaf hashes offchain for the root committed in - /// the commitStore and i_metadataHash in the offRamp. - bytes32 internal immutable i_metadataHash; - /// @dev Default gas limit for a transactions that did not specify - /// a gas limit in the extraArgs. - uint64 internal immutable i_defaultTxGasLimit; - /// @dev Maximum nop fee that can accumulate in this onramp - uint96 internal immutable i_maxNopFeesJuels; - /// @dev The link token address - known to pay nops for their work - address internal immutable i_linkToken; - /// @dev The chain ID of the source chain that this contract is deployed to - uint64 internal immutable i_chainSelector; - /// @dev The chain ID of the destination chain - uint64 internal immutable i_destChainSelector; - /// @dev The address of previous-version OnRamp for this lane - /// Used to be able to provide sequencing continuity during a zero downtime upgrade. - address internal immutable i_prevOnRamp; - /// @dev The address of the RMN proxy - address internal immutable i_rmnProxy; - /// @dev The address of the token admin registry - address internal immutable i_tokenAdminRegistry; - /// @dev the maximum number of nops that can be configured at the same time. - /// Used to bound gas for loops over nops. - uint256 private constant MAX_NUMBER_OF_NOPS = 64; - - // DYNAMIC CONFIG - /// @dev The config for the onRamp - DynamicConfig internal s_dynamicConfig; - /// @dev (address nop => uint256 weight) - EnumerableMap.AddressToUintMap internal s_nops; - - /// @dev The execution fee token config that can be set by the owner or fee admin - mapping(address token => FeeTokenConfig feeTokenConfig) internal s_feeTokenConfig; - /// @dev The token transfer fee config that can be set by the owner or fee admin - mapping(address token => TokenTransferFeeConfig tranferFeeConfig) internal s_tokenTransferFeeConfig; - - // STATE - /// @dev The current nonce per sender. - /// The offramp has a corresponding s_senderNonce mapping to ensure messages - /// are executed in the same order they are sent. - mapping(address sender => uint64 nonce) internal s_senderNonce; - /// @dev The amount of LINK available to pay NOPS - uint96 internal s_nopFeesJuels; - /// @dev The combined weight of all NOPs weights - uint32 internal s_nopWeightsTotal; - /// @dev The last used sequence number. This is zero in the case where no - /// messages has been sent yet. 0 is not a valid sequence number for any - /// real transaction. - uint64 internal s_sequenceNumber; - - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - RateLimiter.Config memory rateLimiterConfig, - FeeTokenConfigArgs[] memory feeTokenConfigs, - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - NopAndWeight[] memory nopsAndWeights - ) AggregateRateLimiter(rateLimiterConfig) { - if ( - staticConfig.linkToken == address(0) || staticConfig.chainSelector == 0 || staticConfig.destChainSelector == 0 - || staticConfig.defaultTxGasLimit == 0 || staticConfig.rmnProxy == address(0) - || staticConfig.tokenAdminRegistry == address(0) - ) revert InvalidConfig(); - - i_metadataHash = keccak256( - abi.encode( - Internal.EVM_2_EVM_MESSAGE_HASH, staticConfig.chainSelector, staticConfig.destChainSelector, address(this) - ) - ); - i_linkToken = staticConfig.linkToken; - i_chainSelector = staticConfig.chainSelector; - i_destChainSelector = staticConfig.destChainSelector; - i_defaultTxGasLimit = staticConfig.defaultTxGasLimit; - i_maxNopFeesJuels = staticConfig.maxNopFeesJuels; - i_prevOnRamp = staticConfig.prevOnRamp; - i_rmnProxy = staticConfig.rmnProxy; - i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; - - _setDynamicConfig(dynamicConfig); - _setFeeTokenConfig(feeTokenConfigs); - _setTokenTransferFeeConfig(tokenTransferFeeConfigArgs, new address[](0)); - _setNops(nopsAndWeights); - } - - // ================================================================ - // │ Messaging │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRamp - function getExpectedNextSequenceNumber() external view returns (uint64) { - return s_sequenceNumber + 1; - } - - /// @inheritdoc IEVM2AnyOnRamp - function getSenderNonce(address sender) external view returns (uint64) { - uint256 senderNonce = s_senderNonce[sender]; - - if (i_prevOnRamp != address(0)) { - if (senderNonce == 0) { - // If OnRamp was upgraded, check if sender has a nonce from the previous OnRamp. - return IEVM2AnyOnRamp(i_prevOnRamp).getSenderNonce(sender); - } - } - return uint64(senderNonce); - } - - /// @inheritdoc IEVM2AnyOnRampClient - function forwardFromRouter( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message, - uint256 feeTokenAmount, - address originalSender - ) external returns (bytes32) { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(); - // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. - if (originalSender == address(0)) revert RouterMustSetOriginalSender(); - // Router address may be zero intentionally to pause. - if (msg.sender != s_dynamicConfig.router) revert MustBeCalledByRouter(); - if (destChainSelector != i_destChainSelector) revert InvalidChainSelector(destChainSelector); - - Client.EVMExtraArgsV2 memory extraArgs = _fromBytes(message.extraArgs); - // Validate the message with various checks - uint256 numberOfTokens = message.tokenAmounts.length; - _validateMessage(message.data.length, extraArgs.gasLimit, numberOfTokens, extraArgs.allowOutOfOrderExecution); - - // Only check token value if there are tokens - if (numberOfTokens > 0) { - uint256 value; - for (uint256 i = 0; i < numberOfTokens; ++i) { - if (message.tokenAmounts[i].amount == 0) revert CannotSendZeroTokens(); - if (s_tokenTransferFeeConfig[message.tokenAmounts[i].token].aggregateRateLimitEnabled) { - value += _getTokenValue(message.tokenAmounts[i], IPriceRegistry(s_dynamicConfig.priceRegistry)); - } - } - // Rate limit on aggregated token value - if (value > 0) _rateLimitValue(value); - } - - // Convert feeToken to link if not already in link - if (message.feeToken == i_linkToken) { - // Since there is only 1b link this is safe - s_nopFeesJuels += uint96(feeTokenAmount); - } else { - // the cast from uint256 to uint96 is considered safe, uint96 can store more than max supply of link token - s_nopFeesJuels += uint96( - IPriceRegistry(s_dynamicConfig.priceRegistry).convertTokenAmount(message.feeToken, feeTokenAmount, i_linkToken) - ); - } - if (s_nopFeesJuels > i_maxNopFeesJuels) revert MaxFeeBalanceReached(); - - if (i_prevOnRamp != address(0)) { - if (s_senderNonce[originalSender] == 0) { - // If this is first time send for a sender in new OnRamp, check if they have a nonce - // from the previous OnRamp and start from there instead of zero. - s_senderNonce[originalSender] = IEVM2AnyOnRamp(i_prevOnRamp).getSenderNonce(originalSender); - } - } - - // We need the next available sequence number so we increment before we use the value - Internal.EVM2EVMMessage memory newMessage = Internal.EVM2EVMMessage({ - sourceChainSelector: i_chainSelector, - sender: originalSender, - // EVM destination addresses should be abi encoded and therefore always 32 bytes long - // Not duplicately validated in `getFee`. Invalid address is uncommon, gas cost outweighs UX gain. - receiver: Internal._validateEVMAddress(message.receiver), - sequenceNumber: ++s_sequenceNumber, - gasLimit: extraArgs.gasLimit, - strict: false, - // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we - // may block ordered message nonces, which is not what we want. - nonce: extraArgs.allowOutOfOrderExecution ? 0 : ++s_senderNonce[originalSender], - feeToken: message.feeToken, - feeTokenAmount: feeTokenAmount, - data: message.data, - tokenAmounts: message.tokenAmounts, - sourceTokenData: new bytes[](numberOfTokens), // will be populated below - messageId: "" - }); - - // Lock the tokens as last step. TokenPools may not always be trusted. - // There should be no state changes after external call to TokenPools. - for (uint256 i = 0; i < numberOfTokens; ++i) { - Client.EVMTokenAmount memory tokenAndAmount = message.tokenAmounts[i]; - IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); - // We don't have to check if it supports the pool version in a non-reverting way here because - // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface - // function and not through the ERC165Checker. - if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { - revert UnsupportedToken(tokenAndAmount.token); - } - - Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: message.receiver, - remoteChainSelector: i_destChainSelector, - originalSender: originalSender, - amount: tokenAndAmount.amount, - localToken: tokenAndAmount.token - }) - ); - - // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the - // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both - // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. - if (poolReturnData.destPoolData.length > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - if (poolReturnData.destPoolData.length > s_tokenTransferFeeConfig[tokenAndAmount.token].destBytesOverhead) { - revert SourceTokenDataTooLarge(tokenAndAmount.token); - } - } - // We validate the token address to ensure it is a valid EVM address - Internal._validateEVMAddress(poolReturnData.destTokenAddress); - - newMessage.sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(sourcePool), - destTokenAddress: poolReturnData.destTokenAddress, - extraData: poolReturnData.destPoolData - }) - ); - } - - // Hash only after the sourceTokenData has been set - newMessage.messageId = Internal._hash(newMessage, i_metadataHash); - - // Emit message request - // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this - // event in the offchain code. - emit CCIPSendRequested(newMessage); - return newMessage.messageId; - } - - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @return The extra args struct - function _fromBytes(bytes calldata extraArgs) internal view returns (Client.EVMExtraArgsV2 memory) { - if (extraArgs.length == 0) { - return Client.EVMExtraArgsV2({gasLimit: i_defaultTxGasLimit, allowOutOfOrderExecution: false}); - } - - bytes4 extraArgsTag = bytes4(extraArgs); - if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { - return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV2)); - } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { - // EVMExtraArgsV1 originally included a second boolean (strict) field which has been deprecated. - // Clients may still include it but it will be ignored. - return Client.EVMExtraArgsV2({gasLimit: abi.decode(extraArgs[4:], (uint256)), allowOutOfOrderExecution: false}); - } - - revert InvalidExtraArgsTag(); - } - - /// @notice Validate the forwarded message with various checks. - /// @dev This function can be called multiple times during a CCIPSend, - /// only common user-driven mistakes are validated here to minimize duplicate validation cost. - /// @param dataLength The length of the data field of the message. - /// @param gasLimit The gasLimit set in message for destination execution. - /// @param numberOfTokens The number of tokens to be sent. - function _validateMessage( - uint256 dataLength, - uint256 gasLimit, - uint256 numberOfTokens, - bool allowOutOfOrderExecution - ) internal view { - uint256 maxDataBytes = uint256(s_dynamicConfig.maxDataBytes); - if (dataLength > maxDataBytes) revert MessageTooLarge(maxDataBytes, dataLength); - if (gasLimit > uint256(s_dynamicConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); - if (numberOfTokens > uint256(s_dynamicConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens(); - if (!allowOutOfOrderExecution) { - if (s_dynamicConfig.enforceOutOfOrder) { - revert ExtraArgOutOfOrderExecutionMustBeTrue(); - } - } - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Returns the static onRamp config. - /// @dev RMN depends on this function, if changing, please notify the RMN maintainers. - /// @return the configuration. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - linkToken: i_linkToken, - chainSelector: i_chainSelector, - destChainSelector: i_destChainSelector, - defaultTxGasLimit: i_defaultTxGasLimit, - maxNopFeesJuels: i_maxNopFeesJuels, - prevOnRamp: i_prevOnRamp, - rmnProxy: i_rmnProxy, - tokenAdminRegistry: i_tokenAdminRegistry - }); - } - - /// @notice Returns the dynamic onRamp config. - /// @return dynamicConfig the configuration. - function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig) { - return s_dynamicConfig; - } - - /// @notice Sets the dynamic configuration. - /// @param dynamicConfig The configuration. - function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner { - _setDynamicConfig(dynamicConfig); - } - - /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. - function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal { - // We permit router to be set to zero as a way to pause the contract. - if (dynamicConfig.priceRegistry == address(0)) revert InvalidConfig(); - if (dynamicConfig.defaultTokenDestBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - revert InvalidDestBytesOverhead(address(0), dynamicConfig.defaultTokenDestBytesOverhead); - } - - s_dynamicConfig = dynamicConfig; - - emit ConfigSet( - StaticConfig({ - linkToken: i_linkToken, - chainSelector: i_chainSelector, - destChainSelector: i_destChainSelector, - defaultTxGasLimit: i_defaultTxGasLimit, - maxNopFeesJuels: i_maxNopFeesJuels, - prevOnRamp: i_prevOnRamp, - rmnProxy: i_rmnProxy, - tokenAdminRegistry: i_tokenAdminRegistry - }), - dynamicConfig - ); - } - - // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRampClient - function getPoolBySourceToken(uint64, /*destChainSelector*/ IERC20 sourceToken) public view returns (IPoolV1) { - return IPoolV1(ITokenAdminRegistry(i_tokenAdminRegistry).getPool(address(sourceToken))); - } - - /// @inheritdoc IEVM2AnyOnRampClient - function getSupportedTokens(uint64) external pure returns (address[] memory) { - revert GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - } - - // ================================================================ - // │ Fees │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRampClient - /// @dev getFee MUST revert if the feeToken is not listed in the fee token config, as the router assumes it does. - /// @param destChainSelector The destination chain selector. - /// @param message The message to get quote for. - /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. - function getFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount) { - if (destChainSelector != i_destChainSelector) revert InvalidChainSelector(destChainSelector); - - Client.EVMExtraArgsV2 memory extraArgs = _fromBytes(message.extraArgs); - // Validate the message with various checks - _validateMessage( - message.data.length, extraArgs.gasLimit, message.tokenAmounts.length, extraArgs.allowOutOfOrderExecution - ); - - FeeTokenConfig memory feeTokenConfig = s_feeTokenConfig[message.feeToken]; - if (!feeTokenConfig.enabled) revert NotAFeeToken(message.feeToken); - - (uint224 feeTokenPrice, uint224 packedGasPrice) = - IPriceRegistry(s_dynamicConfig.priceRegistry).getTokenAndGasPrices(message.feeToken, destChainSelector); - - // Calculate premiumFee in USD with 18 decimals precision first. - // 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; - uint32 tokenTransferGas = 0; - uint32 tokenTransferBytesOverhead = 0; - if (message.tokenAmounts.length > 0) { - (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = - _getTokenTransferCost(message.feeToken, feeTokenPrice, message.tokenAmounts); - } else { - // Convert USD cents with 2 decimals to 18 decimals. - premiumFee = uint256(feeTokenConfig.networkFeeUSDCents) * 1e16; - } - - // 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; - // 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 (s_dynamicConfig.destDataAvailabilityMultiplierBps > 0) { - dataAvailabilityCost = _getDataAvailabilityCost( - // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price. - uint112(packedGasPrice >> Internal.GAS_PRICE_BITS), - message.data.length, - message.tokenAmounts.length, - tokenTransferBytesOverhead - ); - } - - // 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 - uint256 executionCost = uint112(packedGasPrice) - * ( - extraArgs.gasLimit + s_dynamicConfig.destGasOverhead - + (message.data.length * s_dynamicConfig.destGasPerPayloadByte) + tokenTransferGas - ) * feeTokenConfig.gasMultiplierWeiPerEth; - - // 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 * feeTokenConfig.premiumMultiplierWeiPerEth) + executionCost + dataAvailabilityCost) / feeTokenPrice; - } - - /// @notice Returns the estimated data availability cost of the message. - /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes. - /// @param dataAvailabilityGasPrice USD per data availability gas in 18 decimals. - /// @param messageDataLength length of the data field in the message. - /// @param numberOfTokens number of distinct token transfers in the message. - /// @param tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. - /// @return dataAvailabilityCostUSD36Decimal total data availability cost in USD with 36 decimals. - function _getDataAvailabilityCost( - uint112 dataAvailabilityGasPrice, - uint256 messageDataLength, - uint256 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) internal view returns (uint256 dataAvailabilityCostUSD36Decimal) { - // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. - // Fixed message fields do account for the offset and length slot of the dynamic fields. - uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. - // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR. - uint256 dataAvailabilityGas = (dataAvailabilityLengthBytes * s_dynamicConfig.destGasPerDataAvailabilityByte) - + s_dynamicConfig.destDataAvailabilityOverheadGas; - - // dataAvailabilityGasPrice is in 18 decimals, destDataAvailabilityMultiplierBps is in 4 decimals - // We pad 14 decimals to bring the result to 36 decimals, in line with token bps and execution fee. - return ((dataAvailabilityGas * dataAvailabilityGasPrice) * s_dynamicConfig.destDataAvailabilityMultiplierBps) * 1e14; - } - - /// @notice Returns the token transfer cost parameters. - /// A basis point fee is calculated from the USD value of each token transfer. - /// For each individual transfer, this fee is between [minFeeUSD, maxFeeUSD]. - /// Total transfer fee is the sum of each individual token transfer fee. - /// @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 feeToken address of the feeToken. - /// @param feeTokenPrice price of feeToken in USD with 18 decimals. - /// @param tokenAmounts token transfers in the message. - /// @return tokenTransferFeeUSDWei total token transfer bps fee in USD with 18 decimals. - /// @return tokenTransferGas total execution gas of the token transfers. - /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. - function _getTokenTransferCost( - address feeToken, - uint224 feeTokenPrice, - Client.EVMTokenAmount[] calldata tokenAmounts - ) internal view returns (uint256 tokenTransferFeeUSDWei, uint32 tokenTransferGas, uint32 tokenTransferBytesOverhead) { - uint256 numberOfTokens = tokenAmounts.length; - - for (uint256 i = 0; i < numberOfTokens; ++i) { - Client.EVMTokenAmount memory tokenAmount = tokenAmounts[i]; - - // Validate if the token is supported, do not calculate fee for unsupported tokens. - if (address(getPoolBySourceToken(i_destChainSelector, IERC20(tokenAmount.token))) == address(0)) { - revert UnsupportedToken(tokenAmount.token); - } - - TokenTransferFeeConfig memory transferFeeConfig = s_tokenTransferFeeConfig[tokenAmount.token]; - - // If the token has no specific overrides configured, we use the global defaults. - if (!transferFeeConfig.isEnabled) { - tokenTransferFeeUSDWei += uint256(s_dynamicConfig.defaultTokenFeeUSDCents) * 1e16; - tokenTransferGas += s_dynamicConfig.defaultTokenDestGasOverhead; - tokenTransferBytesOverhead += s_dynamicConfig.defaultTokenDestBytesOverhead; - continue; - } - - uint256 bpsFeeUSDWei = 0; - // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. - // Useful for when the PriceRegistry cannot return a valid price for the token. - if (transferFeeConfig.deciBps > 0) { - uint224 tokenPrice = 0; - if (tokenAmount.token != feeToken) { - tokenPrice = IPriceRegistry(s_dynamicConfig.priceRegistry).getValidatedTokenPrice(tokenAmount.token); - } else { - tokenPrice = feeTokenPrice; - } - - // Calculate token transfer value, then apply fee ratio - // ratio represents multiples of 0.1bps, or 1e-5 - bpsFeeUSDWei = (tokenPrice._calcUSDValueFromTokenAmount(tokenAmount.amount) * transferFeeConfig.deciBps) / 1e5; - } - - tokenTransferGas += transferFeeConfig.destGasOverhead; - tokenTransferBytesOverhead += transferFeeConfig.destBytesOverhead; - - // Bps fees should be kept within range of [minFeeUSD, maxFeeUSD]. - // Convert USD values with 2 decimals to 18 decimals. - uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16; - if (bpsFeeUSDWei < minFeeUSDWei) { - tokenTransferFeeUSDWei += minFeeUSDWei; - continue; - } - - uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16; - if (bpsFeeUSDWei > maxFeeUSDWei) { - tokenTransferFeeUSDWei += maxFeeUSDWei; - continue; - } - - tokenTransferFeeUSDWei += bpsFeeUSDWei; - } - - return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead); - } - - /// @notice Gets the fee configuration for a token - /// @param token The token to get the fee configuration for - /// @return feeTokenConfig FeeTokenConfig struct - function getFeeTokenConfig(address token) external view returns (FeeTokenConfig memory feeTokenConfig) { - return s_feeTokenConfig[token]; - } - - /// @notice Sets the fee configuration for a token - /// @param feeTokenConfigArgs Array of FeeTokenConfigArgs structs. - function setFeeTokenConfig(FeeTokenConfigArgs[] memory feeTokenConfigArgs) external { - _onlyOwnerOrAdmin(); - _setFeeTokenConfig(feeTokenConfigArgs); - } - - /// @dev Set the fee config - /// @param feeTokenConfigArgs The fee token configs. - function _setFeeTokenConfig(FeeTokenConfigArgs[] memory feeTokenConfigArgs) internal { - for (uint256 i = 0; i < feeTokenConfigArgs.length; ++i) { - FeeTokenConfigArgs memory configArg = feeTokenConfigArgs[i]; - - s_feeTokenConfig[configArg.token] = FeeTokenConfig({ - networkFeeUSDCents: configArg.networkFeeUSDCents, - gasMultiplierWeiPerEth: configArg.gasMultiplierWeiPerEth, - premiumMultiplierWeiPerEth: configArg.premiumMultiplierWeiPerEth, - enabled: configArg.enabled - }); - } - emit FeeConfigSet(feeTokenConfigArgs); - } - - /// @notice Gets the transfer fee config for a given token. - function getTokenTransferFeeConfig(address token) - external - view - returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) - { - return s_tokenTransferFeeConfig[token]; - } - - /// @notice Sets the transfer fee config. - /// @dev only callable by the owner or admin. - function setTokenTransferFeeConfig( - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - address[] memory tokensToUseDefaultFeeConfigs - ) external { - _onlyOwnerOrAdmin(); - _setTokenTransferFeeConfig(tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs); - } - - /// @notice internal helper to set the token transfer fee config. - function _setTokenTransferFeeConfig( - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - address[] memory tokensToUseDefaultFeeConfigs - ) internal { - for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { - TokenTransferFeeConfigArgs memory configArg = tokenTransferFeeConfigArgs[i]; - - if (configArg.destBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - revert InvalidDestBytesOverhead(configArg.token, configArg.destBytesOverhead); - } - - s_tokenTransferFeeConfig[configArg.token] = TokenTransferFeeConfig({ - minFeeUSDCents: configArg.minFeeUSDCents, - maxFeeUSDCents: configArg.maxFeeUSDCents, - deciBps: configArg.deciBps, - destGasOverhead: configArg.destGasOverhead, - destBytesOverhead: configArg.destBytesOverhead, - aggregateRateLimitEnabled: configArg.aggregateRateLimitEnabled, - isEnabled: true - }); - } - emit TokenTransferFeeConfigSet(tokenTransferFeeConfigArgs); - - // Remove the custom fee configs for the tokens that are in the tokensToUseDefaultFeeConfigs array - for (uint256 i = 0; i < tokensToUseDefaultFeeConfigs.length; ++i) { - delete s_tokenTransferFeeConfig[tokensToUseDefaultFeeConfigs[i]]; - } - if (tokensToUseDefaultFeeConfigs.length > 0) { - emit TokenTransferFeeConfigDeleted(tokensToUseDefaultFeeConfigs); - } - } - - // ================================================================ - // │ NOP payments │ - // ================================================================ - - /// @notice Get the total amount of fees to be paid to the Nops (in LINK) - /// @return totalNopFees - function getNopFeesJuels() external view returns (uint96) { - return s_nopFeesJuels; - } - - /// @notice Gets the Nops and their weights - /// @return nopsAndWeights Array of NopAndWeight structs - /// @return weightsTotal The sum weight of all Nops - function getNops() external view returns (NopAndWeight[] memory nopsAndWeights, uint256 weightsTotal) { - uint256 length = s_nops.length(); - nopsAndWeights = new NopAndWeight[](length); - for (uint256 i = 0; i < length; ++i) { - (address nopAddress, uint256 nopWeight) = s_nops.at(i); - nopsAndWeights[i] = NopAndWeight({nop: nopAddress, weight: uint16(nopWeight)}); - } - weightsTotal = s_nopWeightsTotal; - return (nopsAndWeights, weightsTotal); - } - - /// @notice Sets the Nops and their weights - /// @param nopsAndWeights Array of NopAndWeight structs - function setNops(NopAndWeight[] calldata nopsAndWeights) external { - _onlyOwnerOrAdmin(); - _setNops(nopsAndWeights); - } - - /// @param nopsAndWeights New set of nops and weights - /// @dev Clears existing nops, sets new nops and weights - /// @dev We permit fees to accrue before nops are configured, in which case - /// they will go to the first set of configured nops. - function _setNops(NopAndWeight[] memory nopsAndWeights) internal { - uint256 numberOfNops = nopsAndWeights.length; - if (numberOfNops > MAX_NUMBER_OF_NOPS) revert TooManyNops(); - - // Make sure all nops have been paid before removing nops - // We only have to pay when there are nops and there is enough - // outstanding NOP balance to trigger a payment. - if (s_nopWeightsTotal > 0) { - if (s_nopFeesJuels >= s_nopWeightsTotal) { - payNops(); - } - } - - // Remove all previous nops, move from end to start to avoid shifting - for (uint256 i = s_nops.length(); i > 0; --i) { - (address nop,) = s_nops.at(i - 1); - s_nops.remove(nop); - } - - // Add new - uint32 nopWeightsTotal = 0; - // nopWeightsTotal is bounded by the MAX_NUMBER_OF_NOPS and the weight of - // a single nop being of type uint16. This ensures nopWeightsTotal will - // always fit into the uint32 type. - for (uint256 i = 0; i < numberOfNops; ++i) { - // Make sure the LINK token is not a nop because the link token doesn't allow - // self transfers. If set as nop, payNops would always revert. Since setNops - // calls payNops, we can never remove the LINK token as a nop. - address nop = nopsAndWeights[i].nop; - uint16 weight = nopsAndWeights[i].weight; - if (nop == i_linkToken || nop == address(0)) revert InvalidNopAddress(nop); - s_nops.set(nop, weight); - nopWeightsTotal += weight; - } - s_nopWeightsTotal = nopWeightsTotal; - emit NopsSet(nopWeightsTotal, nopsAndWeights); - } - - /// @notice Pays the Node Ops their outstanding balances. - /// @dev some balance can remain after payments are done. This is at most the sum - /// of the weight of all nops. Since nop weights are uint16s and we can have at - /// most MAX_NUMBER_OF_NOPS NOPs, the highest possible value is 2**22 or 0.04 gjuels. - function payNops() public { - if (msg.sender != owner()) { - if (msg.sender != s_admin) { - if (!s_nops.contains(msg.sender)) { - revert OnlyCallableByOwnerOrAdminOrNop(); - } - } - } - uint256 weightsTotal = s_nopWeightsTotal; - if (weightsTotal == 0) revert NoNopsToPay(); - - uint96 totalFeesToPay = s_nopFeesJuels; - if (totalFeesToPay < weightsTotal) revert NoFeesToPay(); - if (linkAvailableForPayment() < 0) revert InsufficientBalance(); - - uint96 fundsLeft = totalFeesToPay; - uint256 numberOfNops = s_nops.length(); - for (uint256 i = 0; i < numberOfNops; ++i) { - (address nop, uint256 weight) = s_nops.at(i); - // amount can never be higher than totalFeesToPay so the cast to uint96 is safe - uint96 amount = uint96((totalFeesToPay * weight) / weightsTotal); - fundsLeft -= amount; - IERC20(i_linkToken).safeTransfer(nop, amount); - emit NopPaid(nop, amount); - } - // Some funds can remain, since this is an incredibly small - // amount we consider this OK. - s_nopFeesJuels = fundsLeft; - } - - /// @notice Allows the owner to withdraw any ERC20 token from the contract. - /// The NOP link balance is not withdrawable. - /// @param feeToken The token to withdraw - /// @param to The address to send the tokens to - function withdrawNonLinkFees(address feeToken, address to) external { - _onlyOwnerOrAdmin(); - if (to == address(0)) revert InvalidWithdrawParams(); - - // We require the link balance to be settled before allowing withdrawal of non-link fees. - int256 linkAfterNopFees = linkAvailableForPayment(); - if (linkAfterNopFees < 0) revert LinkBalanceNotSettled(); - - if (feeToken == i_linkToken) { - // Withdraw only the left over link balance - IERC20(feeToken).safeTransfer(to, uint256(linkAfterNopFees)); - } else { - // Withdrawal all non-link tokens in the contract - IERC20(feeToken).safeTransfer(to, IERC20(feeToken).balanceOf(address(this))); - } - } - - // ================================================================ - // │ Link monitoring │ - // ================================================================ - - /// @notice Calculate remaining LINK balance after paying nops - /// @dev Allow keeper to monitor funds available for paying nops - /// @return balance if nops were to be paid - function linkAvailableForPayment() public view returns (int256) { - // Since LINK caps at uint96, casting to int256 is safe - return int256(IERC20(i_linkToken).balanceOf(address(this))) - int256(uint256(s_nopFeesJuels)); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @dev Require that the sender is the owner or the fee admin - /// Not a modifier to save on contract size - function _onlyOwnerOrAdmin() internal view { - if (msg.sender != owner()) { - if (msg.sender != s_admin) { - revert OnlyCallableByOwnerOrAdmin(); - } - } - } -} diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol new file mode 100644 index 00000000000..0fff94ee4fc --- /dev/null +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; +import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; +import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; +import {INonceManager} from "../interfaces/INonceManager.sol"; +import {IPoolV1} from "../interfaces/IPool.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; +import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {Pool} from "../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.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"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice The OnRamp is a contract that handles lane-specific fee logic. +/// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them +/// results in an onchain upgrade of all 3. +contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.AddressSet; + using USDPriceWith18Decimals for uint224; + + error CannotSendZeroTokens(); + error UnsupportedToken(address token); + error MustBeCalledByRouter(); + error RouterMustSetOriginalSender(); + error InvalidConfig(); + error CursedByRMN(uint64 sourceChainSelector); + error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); + error InvalidDestChainConfig(uint64 sourceChainSelector); + error OnlyCallableByOwnerOrAllowlistAdmin(); + error SenderNotAllowed(address sender); + error InvalidAllowListRequest(uint64 destChainSelector); + error ReentrancyGuardReentrantCall(); + + event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); + event DestChainConfigSet( + uint64 indexed destChainSelector, uint64 sequenceNumber, IRouter router, bool allowlistEnabled + ); + event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); + /// RMN depends on this event, if changing, please notify the RMN maintainers. + event CCIPMessageSent( + uint64 indexed destChainSelector, uint64 indexed sequenceNumber, Internal.EVM2AnyRampMessage message + ); + event AllowListAdminSet(address indexed allowlistAdmin); + event AllowListSendersAdded(uint64 indexed destChainSelector, address[] senders); + event AllowListSendersRemoved(uint64 indexed destChainSelector, address[] senders); + + /// @dev Struct that contains the static configuration + /// RMN depends on this struct, if changing, please notify the RMN maintainers. + // solhint-disable-next-line gas-struct-packing + struct StaticConfig { + uint64 chainSelector; // ────╮ Source chain selector + IRMNRemote rmnRemote; // ────╯ RMN remote address + address nonceManager; // Nonce manager address + address tokenAdminRegistry; // Token admin registry address + } + + /// @dev Struct that contains the dynamic configuration + // solhint-disable-next-line gas-struct-packing + struct DynamicConfig { + address feeQuoter; // FeeQuoter address + bool reentrancyGuardEntered; // Reentrancy protection + address messageInterceptor; // Optional message interceptor to validate outbound messages. Zero address = no interceptor + address feeAggregator; // Fee aggregator address + address allowlistAdmin; // authorized admin to add or remove allowed senders + } + + /// @dev Struct to hold the configs for a destination chain + /// @dev sequenceNumber, allowlistEnabled, router will all be packed in 1 slot + struct DestChainConfig { + // The last used sequence number. This is zero in the case where no messages have yet been sent. + // 0 is not a valid sequence number for any real transaction. + uint64 sequenceNumber; // ──╮ The last used sequence number. + bool allowlistEnabled; // │ boolean indicator to specify if allowlist check is enabled. + IRouter router; // ─────────╯ Local router address that is allowed to send messages to the destination chain. + EnumerableSet.AddressSet allowedSendersList; // The list of addresses allowed to send messages. + } + + /// @dev Same as DestChainConfig but with the destChainSelector so that an array of these + /// can be passed in the constructor and the applyDestChainConfigUpdates function + // solhint-disable gas-struct-packing + struct DestChainConfigArgs { + uint64 destChainSelector; // ─╮ Destination chain selector + IRouter router; // │ Source router address + bool allowlistEnabled; // ────╯ Boolean indicator to specify if allowlist check is enabled + } + + /// @dev Struct to hold the allowlist configuration args per dest chain. + struct AllowlistConfigArgs { + uint64 destChainSelector; // ──╮ Destination chain selector. + bool allowlistEnabled; // ─────╯ True if the allowlist is enabled. + address[] addedAllowlistedSenders; // list of senders to be added to the allowedSendersList + address[] removedAllowlistedSenders; // list of senders to be removed from the allowedSendersList + } + + // STATIC CONFIG + string public constant override typeAndVersion = "OnRamp 1.6.0-dev"; + /// @dev The chain ID of the source chain that this contract is deployed to + uint64 private immutable i_chainSelector; + /// @dev The rmn contract + IRMNRemote private immutable i_rmnRemote; + /// @dev The address of the nonce manager + address private immutable i_nonceManager; + /// @dev The address of the token admin registry + address private immutable i_tokenAdminRegistry; + + // DYNAMIC CONFIG + /// @dev The dynamic config for the onRamp + DynamicConfig private s_dynamicConfig; + + /// @dev The destination chain specific configs + mapping(uint64 destChainSelector => DestChainConfig destChainConfig) private s_destChainConfigs; + + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + DestChainConfigArgs[] memory destChainConfigArgs + ) { + if ( + staticConfig.chainSelector == 0 || address(staticConfig.rmnRemote) == address(0) + || staticConfig.nonceManager == address(0) || staticConfig.tokenAdminRegistry == address(0) + ) { + revert InvalidConfig(); + } + + i_chainSelector = staticConfig.chainSelector; + i_rmnRemote = staticConfig.rmnRemote; + i_nonceManager = staticConfig.nonceManager; + i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; + + _setDynamicConfig(dynamicConfig); + _applyDestChainConfigUpdates(destChainConfigArgs); + } + + // ================================================================ + // │ Messaging │ + // ================================================================ + + /// @notice Gets the next sequence number to be used in the onRamp + /// @param destChainSelector The destination chain selector + /// @return nextSequenceNumber The next sequence number to be used + function getExpectedNextSequenceNumber( + uint64 destChainSelector + ) external view returns (uint64) { + return s_destChainConfigs[destChainSelector].sequenceNumber + 1; + } + + /// @inheritdoc IEVM2AnyOnRampClient + function forwardFromRouter( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message, + uint256 feeTokenAmount, + address originalSender + ) external returns (bytes32) { + // We rely on a reentrancy guard here due to the untrusted calls performed to the pools + // This enables some optimizations by not following the CEI pattern + if (s_dynamicConfig.reentrancyGuardEntered) revert ReentrancyGuardReentrantCall(); + + s_dynamicConfig.reentrancyGuardEntered = true; + + DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; + + // NOTE: assumes the message has already been validated through the getFee call + // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. + if (originalSender == address(0)) revert RouterMustSetOriginalSender(); + + if (destChainConfig.allowlistEnabled) { + if (!destChainConfig.allowedSendersList.contains(originalSender)) { + revert SenderNotAllowed(originalSender); + } + } + + // Router address may be zero intentionally to pause. + if (msg.sender != address(destChainConfig.router)) revert MustBeCalledByRouter(); + + { + // scoped to reduce stack usage + address messageInterceptor = s_dynamicConfig.messageInterceptor; + if (messageInterceptor != address(0)) { + IMessageInterceptor(messageInterceptor).onOutboundMessage(destChainSelector, message); + } + } + + Internal.EVM2AnyRampMessage memory newMessage = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + // Should be generated after the message is complete + messageId: "", + sourceChainSelector: i_chainSelector, + destChainSelector: destChainSelector, + // We need the next available sequence number so we increment before we use the value + sequenceNumber: ++destChainConfig.sequenceNumber, + // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we + // may block ordered message nonces, which is not what we want. + nonce: 0 + }), + sender: originalSender, + data: message.data, + extraArgs: "", + receiver: message.receiver, + feeToken: message.feeToken, + feeTokenAmount: feeTokenAmount, + feeValueJuels: 0, // calculated later + // Should be populated via lock / burn pool calls + tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) + }); + + // Lock / burn the tokens as last step. TokenPools may not always be trusted. + Client.EVMTokenAmount[] memory tokenAmounts = message.tokenAmounts; + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + newMessage.tokenAmounts[i] = + _lockOrBurnSingleToken(tokenAmounts[i], destChainSelector, message.receiver, originalSender); + } + + // Convert message fee to juels and retrieve converted args + // Validate pool return data after it is populated (view function - no state changes) + bool isOutOfOrderExecution; + bytes memory convertedExtraArgs; + bytes[] memory destExecDataPerToken; + (newMessage.feeValueJuels, isOutOfOrderExecution, convertedExtraArgs, destExecDataPerToken) = IFeeQuoter( + s_dynamicConfig.feeQuoter + ).processMessageArgs( + destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs, newMessage.tokenAmounts, tokenAmounts + ); + + newMessage.header.nonce = isOutOfOrderExecution + ? 0 + : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); + newMessage.extraArgs = convertedExtraArgs; + + for (uint256 i = 0; i < newMessage.tokenAmounts.length; ++i) { + newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; + } + + // Hash only after all fields have been set + newMessage.header.messageId = Internal._hash( + newMessage, + // Metadata hash preimage to ensure global uniqueness, ensuring 2 identical messages sent to 2 different + // lanes will have a distinct hash. + keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))) + ); + + // Emit message request + // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this + // event in the offchain code. + emit CCIPMessageSent(destChainSelector, newMessage.header.sequenceNumber, newMessage); + + s_dynamicConfig.reentrancyGuardEntered = false; + + return newMessage.header.messageId; + } + + /// @notice Uses a pool to lock or burn a token + /// @param tokenAndAmount Token address and amount to lock or burn + /// @param destChainSelector Target destination chain selector of the message + /// @param receiver Message receiver + /// @param originalSender Message sender + /// @return evm2AnyTokenTransfer EVM2Any token and amount data + function _lockOrBurnSingleToken( + Client.EVMTokenAmount memory tokenAndAmount, + uint64 destChainSelector, + bytes memory receiver, + address originalSender + ) internal returns (Internal.EVM2AnyTokenTransfer memory) { + if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); + + IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); + // We don't have to check if it supports the pool version in a non-reverting way here because + // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface + // function and not through the ERC165Checker. + if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { + revert UnsupportedToken(tokenAndAmount.token); + } + + Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( + Pool.LockOrBurnInV1({ + receiver: receiver, + remoteChainSelector: destChainSelector, + originalSender: originalSender, + amount: tokenAndAmount.amount, + localToken: tokenAndAmount.token + }) + ); + + // NOTE: pool data validations are outsourced to the FeeQuoter to handle family-specific logic handling + return Internal.EVM2AnyTokenTransfer({ + sourcePoolAddress: address(sourcePool), + destTokenAddress: poolReturnData.destTokenAddress, + extraData: poolReturnData.destPoolData, + amount: tokenAndAmount.amount, + destExecData: "" // This is set in the processPoolReturnData function + }); + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Returns the static onRamp config. + /// @dev RMN depends on this function, if modified, please notify the RMN maintainers. + /// @return staticConfig the static configuration. + function getStaticConfig() external view returns (StaticConfig memory) { + return StaticConfig({ + chainSelector: i_chainSelector, + rmnRemote: i_rmnRemote, + nonceManager: i_nonceManager, + tokenAdminRegistry: i_tokenAdminRegistry + }); + } + + /// @notice Returns the dynamic onRamp config. + /// @return dynamicConfig the dynamic configuration. + function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig) { + return s_dynamicConfig; + } + + /// @notice Sets the dynamic configuration. + /// @param dynamicConfig The configuration. + function setDynamicConfig( + DynamicConfig memory dynamicConfig + ) external onlyOwner { + _setDynamicConfig(dynamicConfig); + } + + /// @notice Gets the source router for a destination chain + /// @param destChainSelector The destination chain selector + /// @return router the router for the provided destination chain + function getRouter( + uint64 destChainSelector + ) external view returns (IRouter) { + return s_destChainConfigs[destChainSelector].router; + } + + /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. + function _setDynamicConfig( + DynamicConfig memory dynamicConfig + ) internal { + if ( + dynamicConfig.feeQuoter == address(0) || dynamicConfig.feeAggregator == address(0) + || dynamicConfig.reentrancyGuardEntered + ) revert InvalidConfig(); + + s_dynamicConfig = dynamicConfig; + + emit ConfigSet( + StaticConfig({ + chainSelector: i_chainSelector, + rmnRemote: i_rmnRemote, + nonceManager: i_nonceManager, + tokenAdminRegistry: i_tokenAdminRegistry + }), + dynamicConfig + ); + } + + /// @notice Updates destination chains specific configs. + /// @param destChainConfigArgs Array of destination chain specific configs. + function applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) external onlyOwner { + _applyDestChainConfigUpdates(destChainConfigArgs); + } + + /// @notice Internal version of applyDestChainConfigUpdates. + function _applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) internal { + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + + if (destChainSelector == 0) { + revert InvalidDestChainConfig(destChainSelector); + } + + DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; + // The router can be zero to pause the destination chain + destChainConfig.router = destChainConfigArg.router; + destChainConfig.allowlistEnabled = destChainConfigArg.allowlistEnabled; + + emit DestChainConfigSet( + destChainSelector, destChainConfig.sequenceNumber, destChainConfigArg.router, destChainConfig.allowlistEnabled + ); + } + } + + /// @notice get ChainConfig configured for the DestinationChainSelector + /// @param destChainSelector The destination chain selector + /// @return sequenceNumber The last used sequence number + /// @return allowlistEnabled boolean indicator to specify if allowlist check is enabled + /// @return router address of the router + function getDestChainConfig( + uint64 destChainSelector + ) public view returns (uint64 sequenceNumber, bool allowlistEnabled, address router) { + DestChainConfig storage config = s_destChainConfigs[destChainSelector]; + sequenceNumber = config.sequenceNumber; + allowlistEnabled = config.allowlistEnabled; + router = address(config.router); + return (sequenceNumber, allowlistEnabled, router); + } + + /// @notice get allowedSenders List configured for the DestinationChainSelector + /// @param destChainSelector The destination chain selector + /// @return isEnabled True if allowlist is enabled + /// @return configuredAddresses This is always populated with the list of allowed senders, even if the allowlist + /// is turned off. This is because the only way to know what addresses are configured is through this function. If + /// it would return an empty list when the allowlist is disabled, it would be impossible to know what addresses are + /// configured. + function getAllowedSendersList( + uint64 destChainSelector + ) public view returns (bool isEnabled, address[] memory configuredAddresses) { + return ( + s_destChainConfigs[destChainSelector].allowlistEnabled, + s_destChainConfigs[destChainSelector].allowedSendersList.values() + ); + } + + // ================================================================ + // │ Allowlist │ + // ================================================================ + + /// @notice Updates allowlistConfig for Senders + /// @dev configuration used to set the list of senders who are authorized to send messages + /// @param allowlistConfigArgsItems Array of AllowlistConfigArguments where each item is for a destChainSelector + function applyAllowlistUpdates( + AllowlistConfigArgs[] calldata allowlistConfigArgsItems + ) external { + if (msg.sender != owner()) { + if (msg.sender != s_dynamicConfig.allowlistAdmin) { + revert OnlyCallableByOwnerOrAllowlistAdmin(); + } + } + + for (uint256 i = 0; i < allowlistConfigArgsItems.length; ++i) { + AllowlistConfigArgs memory allowlistConfigArgs = allowlistConfigArgsItems[i]; + + DestChainConfig storage destChainConfig = s_destChainConfigs[allowlistConfigArgs.destChainSelector]; + destChainConfig.allowlistEnabled = allowlistConfigArgs.allowlistEnabled; + + if (allowlistConfigArgs.addedAllowlistedSenders.length > 0) { + if (allowlistConfigArgs.allowlistEnabled) { + for (uint256 j = 0; j < allowlistConfigArgs.addedAllowlistedSenders.length; ++j) { + address toAdd = allowlistConfigArgs.addedAllowlistedSenders[j]; + if (toAdd == address(0)) { + revert InvalidAllowListRequest(allowlistConfigArgs.destChainSelector); + } + destChainConfig.allowedSendersList.add(toAdd); + } + + emit AllowListSendersAdded(allowlistConfigArgs.destChainSelector, allowlistConfigArgs.addedAllowlistedSenders); + } else { + revert InvalidAllowListRequest(allowlistConfigArgs.destChainSelector); + } + } + + for (uint256 j = 0; j < allowlistConfigArgs.removedAllowlistedSenders.length; ++j) { + destChainConfig.allowedSendersList.remove(allowlistConfigArgs.removedAllowlistedSenders[j]); + } + + if (allowlistConfigArgs.removedAllowlistedSenders.length > 0) { + emit AllowListSendersRemoved( + allowlistConfigArgs.destChainSelector, allowlistConfigArgs.removedAllowlistedSenders + ); + } + } + } + + // ================================================================ + // │ Tokens and pools │ + // ================================================================ + + /// @inheritdoc IEVM2AnyOnRampClient + function getPoolBySourceToken(uint64, /*destChainSelector*/ IERC20 sourceToken) public view returns (IPoolV1) { + return IPoolV1(ITokenAdminRegistry(i_tokenAdminRegistry).getPool(address(sourceToken))); + } + + /// @inheritdoc IEVM2AnyOnRampClient + function getSupportedTokens( + uint64 /*destChainSelector*/ + ) external pure returns (address[] memory) { + revert GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); + } + + // ================================================================ + // │ Fees │ + // ================================================================ + + /// @inheritdoc IEVM2AnyOnRampClient + /// @dev getFee MUST revert if the feeToken is not listed in the fee token config, as the router assumes it does. + /// @param destChainSelector The destination chain selector. + /// @param message The message to get quote for. + /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. + function getFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount) { + if (i_rmnRemote.isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); + + return IFeeQuoter(s_dynamicConfig.feeQuoter).getValidatedFee(destChainSelector, message); + } + + /// @notice Withdraws the outstanding fee token balances to the fee aggregator. + /// @dev This function can be permissionless as it only transfers accepted fee tokens to the fee aggregator which is a trusted address. + function withdrawFeeTokens() external { + address[] memory feeTokens = IFeeQuoter(s_dynamicConfig.feeQuoter).getFeeTokens(); + address feeAggregator = s_dynamicConfig.feeAggregator; + + for (uint256 i = 0; i < feeTokens.length; ++i) { + IERC20 feeToken = IERC20(feeTokens[i]); + uint256 feeTokenBalance = feeToken.balanceOf(address(this)); + + if (feeTokenBalance > 0) { + feeToken.safeTransfer(feeAggregator, feeTokenBalance); + + emit FeeTokenWithdrawn(feeAggregator, address(feeToken), feeTokenBalance); + } + } + } +} diff --git a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol index de68b18a302..1ba13a49745 100644 --- a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol @@ -18,7 +18,7 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { using SafeERC20 for IBurnMintERC20; - string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0-dev"; + string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0"; constructor( IBurnMintERC20 token, @@ -32,7 +32,9 @@ contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { } /// @inheritdoc BurnMintTokenPoolAbstract - function _burn(uint256 amount) internal virtual override { + function _burn( + uint256 amount + ) internal virtual override { IBurnMintERC20(address(i_token)).burnFrom(address(this), amount); } } diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol index a8562ae4d36..33026cf0053 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol @@ -14,7 +14,7 @@ import {TokenPool} from "./TokenPool.sol"; /// If that is expected, please make sure the token's burner/minter roles are adjustable. /// @dev This contract is a variant of BurnMintTokenPool that uses `burn(amount)`. contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { - string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0-dev"; + string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0"; constructor( IBurnMintERC20 token, @@ -24,7 +24,9 @@ contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { ) TokenPool(token, allowlist, rmnProxy, router) {} /// @inheritdoc BurnMintTokenPoolAbstract - function _burn(uint256 amount) internal virtual override { + function _burn( + uint256 amount + ) internal virtual override { IBurnMintERC20(address(i_token)).burn(amount); } } diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol index 2085c9427b0..6d743ed4a9e 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol @@ -10,16 +10,15 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { /// @notice Contains the specific burn call for a pool. /// @dev overriding this method allows us to create pools with different burn signatures /// without duplicating the underlying logic. - function _burn(uint256 amount) internal virtual; + function _burn( + uint256 amount + ) internal virtual; /// @notice Burn 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) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); _burn(lockOrBurnIn.amount); @@ -31,16 +30,13 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { /// @notice Mint tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); - // Mint to the offRamp, which forwards it to the recipient - IBurnMintERC20(address(i_token)).mint(msg.sender, releaseOrMintIn.amount); + // Mint to the receiver + IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol deleted file mode 100644 index a3a7e082cc7..00000000000 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol +++ /dev/null @@ -1,62 +0,0 @@ -// 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 {LegacyPoolWrapper} from "./LegacyPoolWrapper.sol"; - -contract BurnMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper { - string public constant override typeAndVersion = "BurnMintTokenPoolAndProxy 1.5.0-dev"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) LegacyPoolWrapper(token, allowlist, rmnProxy, router) {} - - /// @notice Burn 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 (!_hasLegacyPool()) { - IBurnMintERC20(address(i_token)).burn(lockOrBurnIn.amount); - } else { - _lockOrBurnLegacy(lockOrBurnIn); - } - - emit Burned(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Mint tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { - _validateReleaseOrMint(releaseOrMintIn); - - if (!_hasLegacyPool()) { - // Mint to the offRamp, which forwards it to the recipient - IBurnMintERC20(address(i_token)).mint(msg.sender, releaseOrMintIn.amount); - } else { - _releaseOrMintLegacy(releaseOrMintIn); - } - - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } -} diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol index 33f6c43c5b0..37541bb8277 100644 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol @@ -18,8 +18,6 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { using SafeERC20 for IBurnMintERC20; - string public constant override typeAndVersion = "BurnWithFromMintTokenPool 1.5.0-dev"; - constructor( IBurnMintERC20 token, address[] memory allowlist, @@ -32,7 +30,13 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion } /// @inheritdoc BurnMintTokenPoolAbstract - function _burn(uint256 amount) internal virtual override { + function _burn( + uint256 amount + ) internal virtual override { IBurnMintERC20(address(i_token)).burn(address(this), amount); } + + function typeAndVersion() external pure virtual override returns (string memory) { + return "BurnWithFromMintTokenPool 1.5.0"; + } } diff --git a/contracts/src/v0.8/ccip/pools/LegacyPoolWrapper.sol b/contracts/src/v0.8/ccip/pools/LegacyPoolWrapper.sol deleted file mode 100644 index 125a3a28ee4..00000000000 --- a/contracts/src/v0.8/ccip/pools/LegacyPoolWrapper.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IPoolPriorTo1_5} from "../interfaces/IPoolPriorTo1_5.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"; - -abstract contract LegacyPoolWrapper is TokenPool { - using SafeERC20 for IERC20; - - event LegacyPoolChanged(IPoolPriorTo1_5 oldPool, IPoolPriorTo1_5 newPool); - - /// @dev The previous pool, if there is any. This is a property to make the older 1.0-1.4 pools - /// compatible with the current 1.5 pool. To achieve this, we set the previous pool address to the - /// currently deployed legacy pool. Then we configure this new pool as onRamp and offRamp on the legacy pools. - /// In the case of a 1.4 pool, this new pool contract has to be set to the Router as well, as it validates - /// who can call it through the router calls. This contract will always return itself as the only allowed ramp. - /// @dev Can be address(0), this would indicate that this pool is operating as a normal pool as opposed to - /// a proxy pool. - IPoolPriorTo1_5 internal s_previousPool; - - constructor( - IERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) {} - - // ================================================================ - // │ Legacy Fallbacks │ - // ================================================================ - // Legacy fallbacks for older token pools that do not implement the new interface. - - /// @notice Legacy fallback for the 1.4 token pools. - function getOnRamp(uint64) external view returns (address onRampAddress) { - return address(this); - } - - /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. - function isOffRamp(uint64 sourceChainSelector, address offRamp) external view returns (bool) { - return offRamp == address(this) || s_router.isOffRamp(sourceChainSelector, offRamp); - } - - /// @notice Configures the legacy fallback option. If the previous pool is set, this pool will act as a proxy for - /// the legacy pool. - /// @param prevPool The address of the previous pool. - function setPreviousPool(IPoolPriorTo1_5 prevPool) external onlyOwner { - IPoolPriorTo1_5 oldPrevPool = s_previousPool; - s_previousPool = prevPool; - - emit LegacyPoolChanged(oldPrevPool, prevPool); - } - - function _hasLegacyPool() internal view returns (bool) { - return address(s_previousPool) != address(0); - } - - function _lockOrBurnLegacy(Pool.LockOrBurnInV1 memory lockOrBurnIn) internal { - i_token.safeTransfer(address(s_previousPool), lockOrBurnIn.amount); - s_previousPool.lockOrBurn( - lockOrBurnIn.originalSender, lockOrBurnIn.receiver, lockOrBurnIn.amount, lockOrBurnIn.remoteChainSelector, "" - ); - } - - /// @notice This call converts the arguments from a >=1.5 pool call to those of a <1.5 pool call, and uses these - /// to call the previous pool. - /// @param releaseOrMintIn The 1.5 style release or mint arguments. - /// @dev Overwrites the receiver so the previous pool sends the tokens to the sender of this call, which is the - /// offRamp. This is due to the older pools sending funds directly to the receiver, while the new pools do a hop - /// through the offRamp to ensure the correct tokens are sent. - /// @dev Since extraData has never been used in LockRelease or MintBurn token pools, we can safely ignore it. - function _releaseOrMintLegacy(Pool.ReleaseOrMintInV1 memory releaseOrMintIn) internal { - s_previousPool.releaseOrMint( - releaseOrMintIn.originalSender, msg.sender, releaseOrMintIn.amount, releaseOrMintIn.remoteChainSelector, "" - ); - } -} diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol index 5716777fb5e..0f77304b186 100644 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol @@ -5,7 +5,6 @@ import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityC import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; import {TokenPool} from "./TokenPool.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -20,20 +19,18 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion error InsufficientLiquidity(); error LiquidityNotAccepted(); - error Unauthorized(address caller); - string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0-dev"; + event LiquidityTransferred(address indexed from, uint256 amount); + + string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0"; /// @dev Whether or not the pool accepts liquidity. /// External liquidity is not required when there is one canonical token deployed to a chain, /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant - /// balanceOf(pool) on home chain == sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold + /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold bool internal immutable i_acceptLiquidity; /// @notice The address of the rebalancer. address internal s_rebalancer; - /// @notice The address of the rate limiter admin. - /// @dev Can be address(0) if none is configured. - address internal s_rateLimitAdmin; constructor( IERC20 token, @@ -47,12 +44,9 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @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) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); emit Locked(msg.sender, lockOrBurnIn.amount); @@ -62,16 +56,13 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @notice Release tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); - // Release to the offRamp, which forwards it to the recipient - getToken().safeTransfer(msg.sender, releaseOrMintIn.amount); + // Release to the recipient + getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); @@ -79,7 +70,9 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion } // @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + function supportsInterface( + bytes4 interfaceId + ) public pure virtual override returns (bool) { return interfaceId == type(ILiquidityContainer).interfaceId || super.supportsInterface(interfaceId); } @@ -91,22 +84,12 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @notice Sets the LiquidityManager address. /// @dev Only callable by the owner. - function setRebalancer(address rebalancer) external onlyOwner { + function setRebalancer( + address rebalancer + ) external onlyOwner { s_rebalancer = rebalancer; } - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner. - /// @param rateLimitAdmin The new rate limiter admin address. - function setRateLimitAdmin(address rateLimitAdmin) external onlyOwner { - s_rateLimitAdmin = rateLimitAdmin; - } - - /// @notice Gets the rate limiter admin address. - function getRateLimitAdmin() external view returns (address) { - return s_rateLimitAdmin; - } - /// @notice Checks if the pool can accept liquidity. /// @return true if the pool can accept liquidity, false otherwise. function canAcceptLiquidity() external view returns (bool) { @@ -115,7 +98,9 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @notice Adds liquidity to the pool. The tokens should be approved first. /// @param amount The amount of liquidity to provide. - function provideLiquidity(uint256 amount) external { + function provideLiquidity( + uint256 amount + ) external { if (!i_acceptLiquidity) revert LiquidityNotAccepted(); if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); @@ -125,7 +110,9 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. /// @param amount The amount of liquidity to remove. - function withdrawLiquidity(uint256 amount) external { + function withdrawLiquidity( + uint256 amount + ) external { if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); @@ -133,19 +120,20 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion emit LiquidityRemoved(msg.sender, amount); } - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner or the rate limiter admin. NOTE: overwrites the normal - /// onlyAdmin check in the base implementation to also allow the rate limiter admin. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config. - /// @param inboundConfig The new inbound rate limiter config. - function setChainRateLimiterConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) external override { - if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); - - _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); + /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so + /// this pool will have to be set as the rebalancer in the older version of the pool. This allows it to transfer the + /// funds in the old pool to the new pool. + /// @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. Finally, the remaining liquidity can be transferred to the new pool using this function one more time. + /// @param from The address of the old pool. + /// @param amount The amount of liquidity to transfer. + function transferLiquidity(address from, uint256 amount) external onlyOwner { + LockReleaseTokenPool(from).withdrawLiquidity(amount); + + emit LiquidityTransferred(from, amount); } } diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol deleted file mode 100644 index 91766d5f26a..00000000000 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityContainer.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {LegacyPoolWrapper} from "./LegacyPoolWrapper.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 Token pool used for tokens on their native chain. This uses a lock and release mechanism. -/// Because of lock/unlock requiring liquidity, this pool contract also has function to add and remove -/// liquidity. This allows for proper bookkeeping for both user and liquidity provider balances. -/// @dev One token per LockReleaseTokenPool. -contract LockReleaseTokenPoolAndProxy is LegacyPoolWrapper, ILiquidityContainer, ITypeAndVersion { - using SafeERC20 for IERC20; - - error InsufficientLiquidity(); - error LiquidityNotAccepted(); - error Unauthorized(address caller); - - string public constant override typeAndVersion = "LockReleaseTokenPoolAndProxy 1.5.0-dev"; - - /// @dev Whether or not the pool accepts liquidity. - /// External liquidity is not required when there is one canonical token deployed to a chain, - /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant - /// balanceOf(pool) on home chain == sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold - bool internal immutable i_acceptLiquidity; - /// @notice The address of the rebalancer. - address internal s_rebalancer; - /// @notice The address of the rate limiter admin. - /// @dev Can be address(0) if none is configured. - address internal s_rateLimitAdmin; - - constructor( - IERC20 token, - address[] memory allowlist, - address rmnProxy, - bool acceptLiquidity, - address router - ) LegacyPoolWrapper(token, allowlist, rmnProxy, router) { - i_acceptLiquidity = acceptLiquidity; - } - - /// @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 (_hasLegacyPool()) { - _lockOrBurnLegacy(lockOrBurnIn); - } - - emit Locked(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Release tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { - _validateReleaseOrMint(releaseOrMintIn); - - if (!_hasLegacyPool()) { - // Release to the offRamp, which forwards it to the recipient - getToken().safeTransfer(msg.sender, releaseOrMintIn.amount); - } else { - _releaseOrMintLegacy(releaseOrMintIn); - } - - emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } - - // @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { - return interfaceId == type(ILiquidityContainer).interfaceId || super.supportsInterface(interfaceId); - } - - /// @notice Gets LiquidityManager, can be address(0) if none is configured. - /// @return The current liquidity manager. - function getRebalancer() external view returns (address) { - return s_rebalancer; - } - - /// @notice Sets the LiquidityManager address. - /// @dev Only callable by the owner. - function setRebalancer(address rebalancer) external onlyOwner { - s_rebalancer = rebalancer; - } - - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner. - /// @param rateLimitAdmin The new rate limiter admin address. - function setRateLimitAdmin(address rateLimitAdmin) external onlyOwner { - s_rateLimitAdmin = rateLimitAdmin; - } - - /// @notice Gets the rate limiter admin address. - function getRateLimitAdmin() external view returns (address) { - return s_rateLimitAdmin; - } - - /// @notice Checks if the pool can accept liquidity. - /// @return true if the pool can accept liquidity, false otherwise. - function canAcceptLiquidity() external view returns (bool) { - return i_acceptLiquidity; - } - - /// @notice Adds liquidity to the pool. The tokens should be approved first. - /// @param amount The amount of liquidity to provide. - function provideLiquidity(uint256 amount) external { - if (!i_acceptLiquidity) revert LiquidityNotAccepted(); - if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); - - i_token.safeTransferFrom(msg.sender, address(this), amount); - emit LiquidityAdded(msg.sender, amount); - } - - /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. - /// @param amount The amount of liquidity to remove. - function withdrawLiquidity(uint256 amount) external { - if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); - - if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); - i_token.safeTransfer(msg.sender, amount); - emit LiquidityRemoved(msg.sender, amount); - } - - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner or the rate limiter admin. NOTE: overwrites the normal - /// onlyAdmin check in the base implementation to also allow the rate limiter admin. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config. - /// @param inboundConfig The new inbound rate limiter config. - function setChainRateLimiterConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) external override { - if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); - - _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); - } -} diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index fb1f8c49e6f..c7e63e31e91 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -10,8 +10,8 @@ import {Pool} from "../libraries/Pool.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice Base abstract class with common functions for all token pools. /// A token pool serves as isolated place for holding tokens and token specific logic @@ -31,6 +31,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { error ChainAlreadyExists(uint64 chainSelector); error InvalidSourcePoolAddress(bytes sourcePoolAddress); error InvalidToken(address token); + error Unauthorized(address caller); event Locked(address indexed sender, uint256 amount); event Burned(address indexed sender, uint256 amount); @@ -56,7 +57,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { struct ChainUpdate { uint64 remoteChainSelector; // ──╮ Remote chain selector bool allowed; // ────────────────╯ Whether the chain should be enabled - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remove EVM chain. + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain @@ -79,7 +80,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// Only takes effect if i_allowlistEnabled is true. /// This can be used to ensure only token-issuer specified addresses can /// move tokens. - EnumerableSet.AddressSet internal s_allowList; + EnumerableSet.AddressSet internal s_allowlist; /// @dev The address of the router IRouter internal s_router; /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to @@ -87,6 +88,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @dev The chain selectors are in uint256 format because of the EnumerableSet implementation. EnumerableSet.UintSet internal s_remoteChainSelectors; mapping(uint64 remoteChainSelector => RemoteChainConfig) internal s_remoteChainConfigs; + /// @notice The address of the rate limiter admin. + /// @dev Can be address(0) if none is configured. + address internal s_rateLimitAdmin; constructor(IERC20 token, address[] memory allowlist, address rmnProxy, address router) { if (address(token) == address(0) || router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); @@ -108,7 +112,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { } /// @inheritdoc IPoolV1 - function isSupportedToken(address token) public view virtual returns (bool) { + function isSupportedToken( + address token + ) public view virtual returns (bool) { return token == address(i_token); } @@ -126,7 +132,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Sets the pool's Router /// @param newRouter The new Router - function setRouter(address newRouter) public onlyOwner { + function setRouter( + address newRouter + ) public onlyOwner { if (newRouter == address(0)) revert ZeroAddressNotAllowed(); address oldRouter = address(s_router); s_router = IRouter(newRouter); @@ -135,7 +143,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { } /// @notice Signals which version of the pool interface is supported - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + function supportsInterface( + bytes4 interfaceId + ) public pure virtual override returns (bool) { return interfaceId == Pool.CCIP_POOL_V1 || interfaceId == type(IPoolV1).interfaceId || interfaceId == type(IERC165).interfaceId; } @@ -153,7 +163,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @param lockOrBurnIn The input to validate. /// @dev This function should always be called before executing a lock or burn. Not doing so would allow /// for various exploits. - function _validateLockOrBurn(Pool.LockOrBurnInV1 memory lockOrBurnIn) internal { + function _validateLockOrBurn( + Pool.LockOrBurnInV1 memory lockOrBurnIn + ) internal { if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); _checkAllowList(lockOrBurnIn.originalSender); @@ -169,9 +181,11 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// - if the source pool is valid /// - rate limit status /// @param releaseOrMintIn The input to validate. - /// @dev This function should always be called before executing a lock or burn. Not doing so would allow + /// @dev This function should always be called before executing a release or mint. Not doing so would allow /// for various exploits. - function _validateReleaseOrMint(Pool.ReleaseOrMintInV1 memory releaseOrMintIn) internal { + function _validateReleaseOrMint( + Pool.ReleaseOrMintInV1 memory releaseOrMintIn + ) internal { if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); _onlyOffRamp(releaseOrMintIn.remoteChainSelector); @@ -194,14 +208,18 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the pool address on the remote chain. /// @param remoteChainSelector Remote chain selector. /// @dev To support non-evm chains, this value is encoded into bytes - function getRemotePool(uint64 remoteChainSelector) public view returns (bytes memory) { + function getRemotePool( + uint64 remoteChainSelector + ) public view returns (bytes memory) { return s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; } /// @notice Gets the token address on the remote chain. /// @param remoteChainSelector Remote chain selector. /// @dev To support non-evm chains, this value is encoded into bytes - function getRemoteToken(uint64 remoteChainSelector) public view returns (bytes memory) { + function getRemoteToken( + uint64 remoteChainSelector + ) public view returns (bytes memory) { return s_remoteChainConfigs[remoteChainSelector].remoteTokenAddress; } @@ -218,7 +236,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { } /// @inheritdoc IPoolV1 - function isSupportedChain(uint64 remoteChainSelector) public view returns (bool) { + function isSupportedChain( + uint64 remoteChainSelector + ) public view returns (bool) { return s_remoteChainSelectors.contains(remoteChainSelector); } @@ -239,7 +259,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @dev Only callable by the owner /// @param chains A list of chains and their new permission status & rate limits. Rate limits /// are only used when the chain is being added through `allowed` being true. - function applyChainUpdates(ChainUpdate[] calldata chains) external virtual onlyOwner { + function applyChainUpdates( + ChainUpdate[] calldata chains + ) external virtual onlyOwner { for (uint256 i = 0; i < chains.length; ++i) { ChainUpdate memory update = chains[i]; RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); @@ -297,6 +319,20 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { // │ Rate limiting │ // ================================================================ + /// @notice Sets the rate limiter admin address. + /// @dev Only callable by the owner. + /// @param rateLimitAdmin The new rate limiter admin address. + function setRateLimitAdmin( + address rateLimitAdmin + ) external onlyOwner { + s_rateLimitAdmin = rateLimitAdmin; + } + + /// @notice Gets the rate limiter admin address. + function getRateLimitAdmin() external view returns (address) { + return s_rateLimitAdmin; + } + /// @notice Consumes outbound rate limiting capacity in this pool function _consumeOutboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._consume(amount, address(i_token)); @@ -309,21 +345,17 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function getCurrentOutboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { return s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._currentTokenBucketState(); } /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function getCurrentInboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { return s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); } @@ -335,7 +367,9 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { uint64 remoteChainSelector, RateLimiter.Config memory outboundConfig, RateLimiter.Config memory inboundConfig - ) external virtual onlyOwner { + ) external { + if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); + _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); } @@ -358,14 +392,18 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender /// is a permissioned onRamp for the given chain on the Router. - function _onlyOnRamp(uint64 remoteChainSelector) internal view { + function _onlyOnRamp( + uint64 remoteChainSelector + ) internal view { if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); } /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender /// is a permissioned offRamp for the given chain on the Router. - function _onlyOffRamp(uint64 remoteChainSelector) internal view { + function _onlyOffRamp( + uint64 remoteChainSelector + ) internal view { if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); } @@ -374,15 +412,17 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { // │ Allowlist │ // ================================================================ - function _checkAllowList(address sender) internal view { + function _checkAllowList( + address sender + ) internal view { if (i_allowlistEnabled) { - if (!s_allowList.contains(sender)) { + if (!s_allowlist.contains(sender)) { revert SenderNotAllowed(sender); } } } - /// @notice Gets whether the allowList functionality is enabled. + /// @notice Gets whether the allowlist functionality is enabled. /// @return true is enabled, false if not. function getAllowListEnabled() external view returns (bool) { return i_allowlistEnabled; @@ -391,7 +431,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the allowed addresses. /// @return The allowed addresses. function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); + return s_allowlist.values(); } /// @notice Apply updates to the allow list. @@ -407,7 +447,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { for (uint256 i = 0; i < removes.length; ++i) { address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { + if (s_allowlist.remove(toRemove)) { emit AllowListRemove(toRemove); } } @@ -416,7 +456,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { if (toAdd == address(0)) { continue; } - if (s_allowList.add(toAdd)) { + if (s_allowlist.add(toAdd)) { emit AllowListAdd(toAdd); } } diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol new file mode 100644 index 00000000000..3691ef1c7b6 --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; + +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {TokenPool} from "../TokenPool.sol"; +import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; +import {USDCBridgeMigrator} from "./USDCBridgeMigrator.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"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice A token pool for USDC which uses CCTP for supported chains and Lock/Release for all others +/// @dev The functionality from LockReleaseTokenPool.sol has been duplicated due to lack of compiler support for shared +/// constructors between parents +/// @dev The primary token mechanism in this pool is Burn/Mint with CCTP, with Lock/Release as the +/// secondary, opt in mechanism for chains not currently supporting CCTP. +contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + + event LiquidityTransferred(address indexed from, uint64 indexed remoteChainSelector, uint256 amount); + event LiquidityProviderSet( + address indexed oldProvider, address indexed newProvider, uint64 indexed remoteChainSelector + ); + + event LockReleaseEnabled(uint64 indexed remoteChainSelector); + event LockReleaseDisabled(uint64 indexed remoteChainSelector); + + error LanePausedForCCTPMigration(uint64 remoteChainSelector); + error TokenLockingNotAllowedAfterMigration(uint64 remoteChainSelector); + + /// bytes4(keccak256("NO_CTTP_USE_LOCK_RELEASE")) + bytes4 public constant LOCK_RELEASE_FLAG = 0xd43c7897; + + /// @notice The address of the liquidity provider for a specific chain. + /// External liquidity is not required when there is one canonical token deployed to a chain, + /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant + /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold + mapping(uint64 remoteChainSelector => address liquidityProvider) internal s_liquidityProvider; + + constructor( + ITokenMessenger tokenMessenger, + IERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) USDCBridgeMigrator(address(token), router) {} + + // ================================================================ + // │ Incoming/Outgoing Mechanisms | + // ================================================================ + + /// @notice Locks the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { + // // If the alternative mechanism (L/R) for chains which have it enabled + if (!shouldUseLockRelease(lockOrBurnIn.remoteChainSelector)) { + return super.lockOrBurn(lockOrBurnIn); + } + + // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (s_proposedUSDCMigrationChain == lockOrBurnIn.remoteChainSelector) { + revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); + } + + return _lockReleaseOutgoingMessage(lockOrBurnIn); + } + + /// @notice Release tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + // Use CCTP Burn/Mint mechanism for chains which have it enabled. The LOCK_RELEASE_FLAG is used in sourcePoolData to + // discern this, since the source-chain will not be a hybrid-pool but a standard burn-mint. In the event of a + // stuck message after a migration has occured, and the message was not executed properly before the migration + // began, and locked tokens were not released until now, the message will already have been committed to with this + // flag so it is safe to release the tokens. The source USDC pool is trusted to send messages with the correct + // flag as well. + if (bytes4(releaseOrMintIn.sourcePoolData) != LOCK_RELEASE_FLAG) { + return super.releaseOrMint(releaseOrMintIn); + } + + return _lockReleaseIncomingMessage(releaseOrMintIn); + } + + /// @notice Contains the alternative mechanism for incoming tokens, in this implementation is "Release" incoming tokens + function _lockReleaseIncomingMessage( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) internal virtual returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + // Circle requires a supply-lock to prevent incoming messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (s_proposedUSDCMigrationChain == releaseOrMintIn.remoteChainSelector) { + revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); + } + + // Decrease internal tracking of locked tokens to ensure accurate accounting for burnLockedUSDC() migration + // If the chain has already been migrated, then this mapping would be zero, and the operation would underflow. + // This branch ensures that we're subtracting from the correct mapping. It is also safe to subtract from the + // excluded tokens mapping, as this function would only be invoked in the event of a stuck tx after a migration + if (s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] == 0) { + s_tokensExcludedFromBurn[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + } else { + s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + } + + // Release to the offRamp, which forwards it to the recipient + getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); + + emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } + + /// @notice Contains the alternative mechanism, in this implementation is "Lock" on outgoing tokens + function _lockReleaseOutgoingMessage( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) internal virtual returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + // Increase internal accounting of locked tokens for burnLockedUSDC() migration + s_lockedTokensByChainSelector[lockOrBurnIn.remoteChainSelector] += lockOrBurnIn.amount; + + emit Locked(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: abi.encode(LOCK_RELEASE_FLAG) + }); + } + + // ================================================================ + // │ Liquidity Management | + // ================================================================ + + /// @notice Gets LiquidityManager, can be address(0) if none is configured. + /// @return The current liquidity manager for the given chain selector + function getLiquidityProvider( + uint64 remoteChainSelector + ) external view returns (address) { + return s_liquidityProvider[remoteChainSelector]; + } + + /// @notice Sets the LiquidityManager address. + /// @dev Only callable by the owner. + function setLiquidityProvider(uint64 remoteChainSelector, address liquidityProvider) external onlyOwner { + address oldProvider = s_liquidityProvider[remoteChainSelector]; + + s_liquidityProvider[remoteChainSelector] = liquidityProvider; + + emit LiquidityProviderSet(oldProvider, liquidityProvider, remoteChainSelector); + } + + /// @notice Adds liquidity to the pool for a specific chain. The tokens should be approved first. + /// @dev Liquidity is expected to be added on a per chain basis. Parties are expected to provide liquidity for their + /// own chain which implements non canonical USDC and liquidity is not shared across lanes. + /// @dev Once liquidity is added, it is locked in the pool until it is removed by an incoming message on the + /// lock release mechanism. This is a hard requirement by Circle to ensure parity with the destination chain + /// supply is maintained. + /// @param amount The amount of tokens to provide as liquidity. + /// @param remoteChainSelector The chain for which liquidity is provided to. Necessary to ensure there's accurate + /// parity between locked USDC in this contract and the circulating supply on the remote chain + function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external { + if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); + + s_lockedTokensByChainSelector[remoteChainSelector] += amount; + + i_token.safeTransferFrom(msg.sender, address(this), amount); + + emit ILiquidityContainer.LiquidityAdded(msg.sender, amount); + } + + /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. + /// @param remoteChainSelector The chain where liquidity is being released. + /// @param amount The amount of liquidity to remove. + /// @dev The function should only be called if non canonical USDC on the remote chain has been burned and is not being + /// withdrawn on this chain, otherwise a mismatch may occur between locked token balance and remote circulating supply + /// which may block a potential future migration of the chain to CCTP. + function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (remoteChainSelector == s_proposedUSDCMigrationChain) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } + + s_lockedTokensByChainSelector[remoteChainSelector] -= amount; + + i_token.safeTransfer(msg.sender, amount); + + 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 { + // Prevent Liquidity Transfers when a migration is pending. This prevents requiring the new pool to manage + // token exclusions for edge-case messages and ensures that the migration is completed before any new liquidity + // is added to the pool. + if (HybridLockReleaseUSDCTokenPool(from).getCurrentProposedCCTPChainMigration() == remoteChainSelector) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } + + OwnerIsCreator(from).acceptOwnership(); + + // Withdraw all available liquidity from the old pool. + uint256 withdrawAmount = HybridLockReleaseUSDCTokenPool(from).getLockedTokensForChain(remoteChainSelector); + HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, withdrawAmount); + + s_lockedTokensByChainSelector[remoteChainSelector] += withdrawAmount; + + emit LiquidityTransferred(from, remoteChainSelector, withdrawAmount); + } + + // ================================================================ + // │ Alt Mechanism Logic | + // ================================================================ + + /// @notice Return whether a lane should use the alternative L/R mechanism in the token pool. + /// @param remoteChainSelector the remote chain the lane is interacting with + /// @return bool Return true if the alternative L/R mechanism should be used + function shouldUseLockRelease( + uint64 remoteChainSelector + ) public view virtual returns (bool) { + return s_shouldUseLockRelease[remoteChainSelector]; + } + + /// @notice Updates Updates designations for chains on whether to use primary or alt mechanism on CCIP messages + /// @param removes A list of chain selectors to disable Lock-Release, and enforce BM + /// @param adds A list of chain selectors to enable LR instead of BM + function updateChainSelectorMechanisms(uint64[] calldata removes, uint64[] calldata adds) external onlyOwner { + for (uint256 i = 0; i < removes.length; ++i) { + delete s_shouldUseLockRelease[removes[i]]; + emit LockReleaseDisabled(removes[i]); + } + + for (uint256 i = 0; i < adds.length; ++i) { + s_shouldUseLockRelease[adds[i]] = true; + emit LockReleaseEnabled(adds[i]); + } + } +} diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol new file mode 100644 index 00000000000..4737a833445 --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -0,0 +1,162 @@ +pragma solidity ^0.8.24; + +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +import {Router} from "../../Router.sol"; + +/// @notice Allows migration of a lane in a token pool from Lock/Release to CCTP supported Burn/Mint. Contract +/// functionality is based on hard requirements defined by Circle to allow for future CCTP compatibility +/// https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md +abstract contract USDCBridgeMigrator is OwnerIsCreator { + using EnumerableSet for EnumerableSet.UintSet; + + event CCTPMigrationProposed(uint64 remoteChainSelector); + event CCTPMigrationExecuted(uint64 remoteChainSelector, uint256 USDCBurned); + event CCTPMigrationCancelled(uint64 existingProposalSelector); + event CircleMigratorAddressSet(address migratorAddress); + event TokensExcludedFromBurn( + uint64 indexed remoteChainSelector, uint256 amount, uint256 burnableAmountAfterExclusion + ); + + error onlyCircle(); + error ExistingMigrationProposal(); + error NoExistingMigrationProposal(); + error NoMigrationProposalPending(); + error InvalidChainSelector(uint64 remoteChainSelector); + + IBurnMintERC20 internal immutable i_USDC; + Router internal immutable i_router; + + address internal s_circleUSDCMigrator; + uint64 internal s_proposedUSDCMigrationChain; + + mapping(uint64 chainSelector => uint256 lockedBalance) internal s_lockedTokensByChainSelector; + mapping(uint64 remoteChainSelector => uint256 excludedTokens) internal s_tokensExcludedFromBurn; + + mapping(uint64 chainSelector => bool shouldUseLockRelease) internal s_shouldUseLockRelease; + + constructor(address token, address router) { + i_USDC = IBurnMintERC20(token); + i_router = Router(router); + } + + /// @notice Burn USDC locked for a specific lane so that destination USDC can be converted from + /// non-canonical to canonical USDC. + /// @dev This function can only be called by an address specified by the owner to be controlled by circle + /// @dev proposeCCTPMigration must be called first on an approved lane to execute properly. + /// @dev This function signature should NEVER be overwritten, otherwise it will be unable to be called by + /// circle to properly migrate USDC over to CCTP. + function burnLockedUSDC() public { + if (msg.sender != s_circleUSDCMigrator) revert onlyCircle(); + if (s_proposedUSDCMigrationChain == 0) revert ExistingMigrationProposal(); + + uint64 burnChainSelector = s_proposedUSDCMigrationChain; + + // Burnable tokens is the total locked minus the amount excluded from burn + uint256 tokensToBurn = + s_lockedTokensByChainSelector[burnChainSelector] - s_tokensExcludedFromBurn[burnChainSelector]; + + // Even though USDC is a trusted call, ensure CEI by updating state first + delete s_lockedTokensByChainSelector[burnChainSelector]; + delete s_proposedUSDCMigrationChain; + + // This should only be called after this contract has been granted a "zero allowance minter role" on USDC by Circle, + // otherwise the call will revert. Executing this burn will functionally convert all USDC on the destination chain + // to canonical USDC by removing the canonical USDC backing it from circulation. + i_USDC.burn(tokensToBurn); + + // Disable L/R automatically on burned chain and enable CCTP + delete s_shouldUseLockRelease[burnChainSelector]; + + emit CCTPMigrationExecuted(burnChainSelector, tokensToBurn); + } + + /// @notice Propose a destination chain to migrate from lock/release mechanism to CCTP enabled burn/mint + /// through a Circle controlled burn. + /// @param remoteChainSelector the CCIP specific selector for the remote chain currently using a + /// non-canonical form of USDC which they wish to update to canonical. Function will revert if an existing migration + /// proposal is already in progress. + /// @dev This function can only be called by the owner + function proposeCCTPMigration( + uint64 remoteChainSelector + ) external onlyOwner { + // Prevent overwriting existing migration proposals until the current one is finished + if (s_proposedUSDCMigrationChain != 0) revert ExistingMigrationProposal(); + + s_proposedUSDCMigrationChain = remoteChainSelector; + + emit CCTPMigrationProposed(remoteChainSelector); + } + + /// @notice Cancel an existing proposal to migrate a lane to CCTP. + /// @notice This function will revert if no proposal is currently in progress. + function cancelExistingCCTPMigrationProposal() external onlyOwner { + if (s_proposedUSDCMigrationChain == 0) revert NoExistingMigrationProposal(); + + uint64 currentProposalChainSelector = s_proposedUSDCMigrationChain; + delete s_proposedUSDCMigrationChain; + + // If a migration is cancelled, the tokens excluded from burn should be reset, and must be manually + // re-excluded if the proposal is re-proposed in the future + delete s_tokensExcludedFromBurn[currentProposalChainSelector]; + + emit CCTPMigrationCancelled(currentProposalChainSelector); + } + + /// @notice retrieve the chain selector for an ongoing CCTP migration in progress. + /// @return uint64 the chain selector of the lane to be migrated. Will be zero if no proposal currently + /// exists + function getCurrentProposedCCTPChainMigration() public view returns (uint64) { + return s_proposedUSDCMigrationChain; + } + + /// @notice Set the address of the circle-controlled wallet which will execute a CCTP lane migration + /// @dev The function should only be invoked once the address has been confirmed by Circle prior to + /// chain expansion. + function setCircleMigratorAddress( + address migrator + ) external onlyOwner { + s_circleUSDCMigrator = migrator; + + emit CircleMigratorAddressSet(migrator); + } + + /// @notice Retrieve the amount of canonical USDC locked into this lane and minted on the destination + /// @param remoteChainSelector the CCIP specific destination chain implementing a mintable and + /// non-canonical form of USDC at present. + /// @return uint256 the amount of USDC locked into the specified lane. If non-zero, the number + /// should match the current circulating supply of USDC on the destination chain + function getLockedTokensForChain( + uint64 remoteChainSelector + ) public view returns (uint256) { + return s_lockedTokensByChainSelector[remoteChainSelector]; + } + + /// @notice Exclude tokens to be burned in a CCTP-migration because the amount are locked in an undelivered message. + /// @dev When a message is sitting in manual execution from the L/R chain, those tokens need to be excluded from + /// being burned in a CCTP-migration otherwise the message will never be able to be delivered due to it not having + /// an attestation on the source-chain to mint. In that instance it should use provided liquidity that was designated + /// @dev This function should ONLY be called on the home chain, where tokens are locked, NOT on the remote chain + /// and strict scrutiny should be applied to ensure that the amount of tokens excluded is accurate. + function excludeTokensFromBurn(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + s_tokensExcludedFromBurn[remoteChainSelector] += amount; + + uint256 burnableAmountAfterExclusion = + s_lockedTokensByChainSelector[remoteChainSelector] - s_tokensExcludedFromBurn[remoteChainSelector]; + + emit TokensExcludedFromBurn(remoteChainSelector, amount, burnableAmountAfterExclusion); + } + + /// @notice Get the amount of tokens excluded from being burned in a CCTP-migration + /// @dev The sum of locked tokens and excluded tokens should equal the supply of the token on the remote chain + /// @param remoteChainSelector The chain for which the excluded tokens are being queried + /// @return uint256 amount of tokens excluded from being burned in a CCTP-migration + function getExcludedTokensByChain( + uint64 remoteChainSelector + ) public view returns (uint256) { + return s_tokensExcludedFromBurn[remoteChainSelector]; + } +} diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol index 339ed09992f..addfe06da0b 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol @@ -50,7 +50,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { uint32 sourceDomain; } - string public constant override typeAndVersion = "USDCTokenPool 1.4.0"; + string public constant override typeAndVersion = "USDCTokenPool 1.5.0"; // We restrict to the first version. New pool may be required for subsequent versions. uint32 public constant SUPPORTED_USDC_VERSION = 0; @@ -94,35 +94,26 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { } /// @notice Burn the token in the pool - /// @dev Burn is not rate limited at per-pool level. Burn does not contribute to honey pot risk. - /// Benefits of rate limiting here does not justify the extra gas cost. /// @dev emits ITokenMessenger.DepositForBurn /// @dev Assumes caller has validated destinationReceiver - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); Domain memory domain = s_chainToDomain[lockOrBurnIn.remoteChainSelector]; if (!domain.enabled) revert UnknownDomain(lockOrBurnIn.remoteChainSelector); + if (lockOrBurnIn.receiver.length != 32) { revert InvalidReceiver(lockOrBurnIn.receiver); } + bytes32 decodedReceiver = abi.decode(lockOrBurnIn.receiver, (bytes32)); // Since this pool is the msg sender of the CCTP transaction, only this contract // is able to call replaceDepositForBurn. Since this contract does not implement // replaceDepositForBurn, the tokens cannot be maliciously re-routed to another address. uint64 nonce = i_tokenMessenger.depositForBurnWithCaller( - // We set the domain.allowedCaller as the receiver of the funds, as this is the token pool. Since 1.5 the - // token pools receiver the funds to hop them through the offRamps. - lockOrBurnIn.amount, - domain.domainIdentifier, - domain.allowedCaller, - address(i_token), - domain.allowedCaller + lockOrBurnIn.amount, domain.domainIdentifier, decodedReceiver, address(i_token), domain.allowedCaller ); emit Burned(msg.sender, lockOrBurnIn.amount); @@ -144,11 +135,9 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { /// for that message, including its (nonce, sourceDomain). This way, the only /// non-reverting offchainTokenData that can be supplied is a valid attestation for the /// specific message that was sent on source. - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); SourceTokenDataPayload memory sourceTokenDataPayload = abi.decode(releaseOrMintIn.sourcePoolData, (SourceTokenDataPayload)); @@ -160,8 +149,6 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { if (!i_messageTransmitter.receiveMessage(msgAndAttestation.message, msgAndAttestation.attestation)) { revert UnlockingUSDCFailed(); } - // Since the tokens are minted to the pool, the pool has to send it to the offRamp - getToken().safeTransfer(msg.sender, releaseOrMintIn.amount); emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); @@ -219,13 +206,17 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { // ================================================================ /// @notice Gets the CCTP domain for a given CCIP chain selector. - function getDomain(uint64 chainSelector) external view returns (Domain memory) { + function getDomain( + uint64 chainSelector + ) external view returns (Domain memory) { return s_chainToDomain[chainSelector]; } /// @notice Sets the CCTP domain for a CCIP chain selector. /// @dev Must verify mapping of selectors -> (domain, caller) offchain. - function setDomains(DomainUpdate[] calldata domains) external onlyOwner { + function setDomains( + DomainUpdate[] calldata domains + ) external onlyOwner { for (uint256 i = 0; i < domains.length; ++i) { DomainUpdate memory domain = domains[i]; if (domain.allowedCaller == bytes32(0) || domain.destChainSelector == 0) revert InvalidDomain(domain); diff --git a/contracts/src/v0.8/ccip/ARMProxy.sol b/contracts/src/v0.8/ccip/rmn/ARMProxy.sol similarity index 90% rename from contracts/src/v0.8/ccip/ARMProxy.sol rename to contracts/src/v0.8/ccip/rmn/ARMProxy.sol index e9ccde8680b..964582686be 100644 --- a/contracts/src/v0.8/ccip/ARMProxy.sol +++ b/contracts/src/v0.8/ccip/rmn/ARMProxy.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; /// @notice The ARMProxy serves to allow CCIP contracts /// to point to a static address for ARM queries, which saves gas @@ -16,19 +16,22 @@ contract ARMProxy is OwnerIsCreator, ITypeAndVersion { event ARMSet(address arm); // STATIC CONFIG - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables string public constant override typeAndVersion = "ARMProxy 1.0.0"; // DYNAMIC CONFIG address private s_arm; - constructor(address arm) { + constructor( + address arm + ) { setARM(arm); } /// @notice SetARM sets the ARM implementation contract address. /// @param arm The address of the arm implementation contract. - function setARM(address arm) public onlyOwner { + function setARM( + address arm + ) public onlyOwner { if (arm == address(0)) revert ZeroAddressNotAllowed(); s_arm = arm; emit ARMSet(arm); diff --git a/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol new file mode 100644 index 00000000000..978b200213d --- /dev/null +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + +/// @notice Stores the home configuration for RMN, that is referenced by CCIP oracles, RMN nodes, and the RMNRemote +/// contracts. +/// @dev This contract is a state machine with the following states: +/// - Init: The initial state of the contract, no config has been set, or all configs have been revoked. +/// [0, 0] +/// +/// - Candidate: A new config has been set, but it has not been promoted yet, or all active configs have been revoked. +/// [0, 1] +/// +/// - Active: A non-zero config has been promoted and is active, there is no candidate configured. +/// [1, 0] +/// +/// - ActiveAndCandidate: A non-zero config has been promoted and is active, and a new config has been set as candidate. +/// [1, 1] +/// +/// The following state transitions are allowed: +/// - Init -> Candidate: setCandidate() +/// - Candidate -> Active: promoteCandidateAndRevokeActive() +/// - Candidate -> Candidate: setCandidate() +/// - Candidate -> Init: revokeCandidate() +/// - Active -> ActiveAndCandidate: setCandidate() +/// - Active -> Init: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: revokeCandidate() +/// - ActiveAndCandidate -> ActiveAndCandidate: setCandidate() +/// +/// This means the following calls are not allowed at the following states: +/// - Init: promoteCandidateAndRevokeActive(), as there is no config to promote. +/// - Init: revokeCandidate(), as there is no config to revoke +/// - Active: revokeCandidate(), as there is no candidate to revoke +/// Note that we explicitly do allow promoteCandidateAndRevokeActive() to be called when there is an active config but +/// no candidate config. This is the only way to remove the active config. The alternative would be to set some unusable +/// config as candidate and promote that, but fully clearing it is cleaner. +/// +/// ┌─────────────┐ setCandidate ┌─────────────┐ +/// │ ├───────────────────►│ │ setCandidate +/// │ Init │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [0,0] │◄───────────────────┤ [0,1] │────────────┘ +/// │ │ ┌─────────────────┤ │ +/// └─────────────┘ │ promote- └─────────────┘ +/// ▲ │ Candidate +/// promote- │ │ +/// Candidate │ │ +/// │ │ +/// ┌──────────┴──┐ │ promote- ┌─────────────┐ +/// │ │◄─┘ Candidate OR │ Active & │ setCandidate +/// │ Active │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ +/// │ ├───────────────────►│ │ +/// └─────────────┘ setSecondary └─────────────┘ +/// +contract RMNHome is OwnerIsCreator, ITypeAndVersion { + event ConfigSet(bytes32 indexed configDigest, uint32 version, StaticConfig staticConfig, DynamicConfig dynamicConfig); + event ActiveConfigRevoked(bytes32 indexed configDigest); + event CandidateConfigRevoked(bytes32 indexed configDigest); + event DynamicConfigSet(bytes32 indexed configDigest, DynamicConfig dynamicConfig); + event ConfigPromoted(bytes32 indexed configDigest); + + error OutOfBoundsNodesLength(); + error DuplicatePeerId(); + error DuplicateOffchainPublicKey(); + error DuplicateSourceChain(); + error OutOfBoundsObserverNodeIndex(); + error MinObserversTooHigh(); + error ConfigDigestMismatch(bytes32 expectedConfigDigest, bytes32 gotConfigDigest); + error DigestNotFound(bytes32 configDigest); + error RevokingZeroDigestNotAllowed(); + error NoOpStateTransitionNotAllowed(); + + struct Node { + bytes32 peerId; // Used for p2p communication. + bytes32 offchainPublicKey; // Observations are signed with this public key, and are only verified offchain. + } + + struct SourceChain { + uint64 chainSelector; // ─────╮ The Source chain selector. + uint64 minObservers; // ──────╯ Required number of observers to agree on an observation for this source chain. + // ObserverNodesBitmap & (1< MAX_NODES) { + revert OutOfBoundsNodesLength(); + } + + // Ensure no peerId or offchainPublicKey is duplicated. + for (uint256 i = 0; i < staticConfig.nodes.length; ++i) { + for (uint256 j = i + 1; j < staticConfig.nodes.length; ++j) { + if (staticConfig.nodes[i].peerId == staticConfig.nodes[j].peerId) { + revert DuplicatePeerId(); + } + if (staticConfig.nodes[i].offchainPublicKey == staticConfig.nodes[j].offchainPublicKey) { + revert DuplicateOffchainPublicKey(); + } + } + } + + _validateDynamicConfig(dynamicConfig, staticConfig.nodes.length); + } + + /// @notice Validates the dynamic config. Reverts when the config is invalid. + /// @param dynamicConfig The dynamic part of the config. + /// @param numberOfNodes The number of nodes in the static config. + function _validateDynamicConfig(DynamicConfig memory dynamicConfig, uint256 numberOfNodes) internal pure { + uint256 numberOfSourceChains = dynamicConfig.sourceChains.length; + for (uint256 i = 0; i < numberOfSourceChains; ++i) { + SourceChain memory currentSourceChain = dynamicConfig.sourceChains[i]; + // Ensure the source chain is unique. + for (uint256 j = i + 1; j < numberOfSourceChains; ++j) { + if (currentSourceChain.chainSelector == dynamicConfig.sourceChains[j].chainSelector) { + revert DuplicateSourceChain(); + } + } + + // all observer node indices are valid + uint256 bitmap = currentSourceChain.observerNodesBitmap; + // Check if there are any bits set for indexes outside of the expected range. + if (bitmap & (type(uint256).max >> (256 - numberOfNodes)) != bitmap) { + revert OutOfBoundsObserverNodeIndex(); + } + + uint256 observersCount = 0; + for (; bitmap != 0; ++observersCount) { + bitmap &= bitmap - 1; + } + + // minObservers are tenable + if (currentSourceChain.minObservers > observersCount) { + revert MinObserversTooHigh(); + } + } + } +} diff --git a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol new file mode 100644 index 00000000000..6a4366e29fe --- /dev/null +++ b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {EnumerableSet} from "../../shared/enumerable/EnumerableSetWithBytes16.sol"; +import {Internal} from "../libraries/Internal.sol"; + +/// @dev An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a +/// remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is +/// deployed, relying on isCursed(). +bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; + +/// @dev An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject for +/// issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using +/// the local chain selector as a subject. +bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; + +/// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. +contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNRemote { + using EnumerableSet for EnumerableSet.Bytes16Set; + + error AlreadyCursed(bytes16 subject); + error ConfigNotSet(); + error DuplicateOnchainPublicKey(); + error InvalidSignature(); + error InvalidSignerOrder(); + error MinSignersTooHigh(); + error NotCursed(bytes16 subject); + error OutOfOrderSignatures(); + error ThresholdNotMet(); + error UnexpectedSigner(); + error ZeroValueNotAllowed(); + + event ConfigSet(uint32 indexed version, Config config); + event Cursed(bytes16[] subjects); + event Uncursed(bytes16[] subjects); + + /// @dev the configuration of an RMN signer + struct Signer { + address onchainPublicKey; // ────╮ For signing reports + uint64 nodeIndex; // ────────────╯ Maps to nodes in home chain config, should be strictly increasing + } + + /// @dev the contract config + /// @dev note: minSigners can be set to 0 to disable verification for chains without RMN support + struct Config { + bytes32 rmnHomeContractConfigDigest; // Digest of the RMNHome contract config + Signer[] signers; // List of signers + uint64 minSigners; // Threshold for the number of signers required to verify a report + } + + /// @dev part of the payload that RMN nodes sign: keccak256(abi.encode(RMN_V1_6_ANY2EVM_REPORT, report)) + /// @dev this struct is only ever abi-encoded and hashed; it is never stored + struct Report { + uint256 destChainId; // To guard against chain selector misconfiguration + uint64 destChainSelector; // ────────────╮ The chain selector of the destination chain + address rmnRemoteContractAddress; // ─────╯ The address of this contract + address offrampAddress; // The address of the offramp on the same chain as this contract + bytes32 rmnHomeContractConfigDigest; // The digest of the RMNHome contract config + Internal.MerkleRoot[] merkleRoots; // The dest lane updates + } + + /// @dev this is included in the preimage of the digest that RMN nodes sign + bytes32 private constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); + + string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; + uint64 internal immutable i_localChainSelector; + + Config private s_config; + uint32 private s_configCount; + + EnumerableSet.Bytes16Set private s_cursedSubjects; + mapping(address signer => bool exists) private s_signers; // for more gas efficient verify + + /// @param localChainSelector the chain selector of the chain this contract is deployed to + constructor( + uint64 localChainSelector + ) { + if (localChainSelector == 0) revert ZeroValueNotAllowed(); + i_localChainSelector = localChainSelector; + } + + // ================================================================ + // │ Verification │ + // ================================================================ + + /// @inheritdoc IRMNRemote + function verify( + address offrampAddress, + Internal.MerkleRoot[] calldata merkleRoots, + Signature[] calldata signatures, + uint256 rawVs + ) external view { + if (s_configCount == 0) { + revert ConfigNotSet(); + } + if (signatures.length < s_config.minSigners) revert ThresholdNotMet(); + + bytes32 digest = keccak256( + abi.encode( + RMN_V1_6_ANY2EVM_REPORT, + Report({ + destChainId: block.chainid, + destChainSelector: i_localChainSelector, + rmnRemoteContractAddress: address(this), + offrampAddress: offrampAddress, + rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, + merkleRoots: merkleRoots + }) + ) + ); + + address prevAddress; + address signerAddress; + for (uint256 i = 0; i < signatures.length; ++i) { + // The v value is bit-encoded into rawVs + signerAddress = ecrecover(digest, 27 + uint8(rawVs & 0x01 << i), signatures[i].r, signatures[i].s); + if (signerAddress == address(0)) revert InvalidSignature(); + if (prevAddress >= signerAddress) revert OutOfOrderSignatures(); + if (!s_signers[signerAddress]) revert UnexpectedSigner(); + prevAddress = signerAddress; + } + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Sets the configuration of the contract + /// @param newConfig the new configuration + /// @dev setting config is atomic; we delete all pre-existing config and set everything from scratch + function setConfig( + Config calldata newConfig + ) external onlyOwner { + // signers are in ascending order of nodeIndex + for (uint256 i = 1; i < newConfig.signers.length; ++i) { + if (!(newConfig.signers[i - 1].nodeIndex < newConfig.signers[i].nodeIndex)) { + revert InvalidSignerOrder(); + } + } + + // minSigners is tenable + if (!(newConfig.minSigners <= newConfig.signers.length)) { + revert MinSignersTooHigh(); + } + + // clear the old signers + for (uint256 i = s_config.signers.length; i > 0; --i) { + delete s_signers[s_config.signers[i - 1].onchainPublicKey]; + } + + // set the new signers + for (uint256 i = 0; i < newConfig.signers.length; ++i) { + if (s_signers[newConfig.signers[i].onchainPublicKey]) { + revert DuplicateOnchainPublicKey(); + } + s_signers[newConfig.signers[i].onchainPublicKey] = true; + } + + s_config = newConfig; + uint32 newConfigCount = ++s_configCount; + emit ConfigSet(newConfigCount, newConfig); + } + + /// @notice Returns the current configuration of the contract and a version number + /// @return version the current configs version + /// @return config the current config + function getVersionedConfig() external view returns (uint32 version, Config memory config) { + return (s_configCount, s_config); + } + + /// @notice Returns the chain selector configured at deployment time + /// @return localChainSelector the chain selector (not the chain ID) + function getLocalChainSelector() external view returns (uint64 localChainSelector) { + return i_localChainSelector; + } + + /// @notice Returns the 32 byte header used in computing the report digest + /// @return digestHeader the digest header + function getReportDigestHeader() external pure returns (bytes32 digestHeader) { + return RMN_V1_6_ANY2EVM_REPORT; + } + + // ================================================================ + // │ Cursing │ + // ================================================================ + + /// @notice Curse a single subject + /// @param subject the subject to curse + function curse( + bytes16 subject + ) external { + bytes16[] memory subjects = new bytes16[](1); + subjects[0] = subject; + curse(subjects); + } + + /// @notice Curse an array of subjects + /// @param subjects the subjects to curse + /// @dev reverts if any of the subjects are already cursed or if there is a duplicate + function curse( + bytes16[] memory subjects + ) public onlyOwner { + for (uint256 i = 0; i < subjects.length; ++i) { + if (!s_cursedSubjects.add(subjects[i])) { + revert AlreadyCursed(subjects[i]); + } + } + emit Cursed(subjects); + } + + /// @notice Uncurse a single subject + /// @param subject the subject to uncurse + function uncurse( + bytes16 subject + ) external { + bytes16[] memory subjects = new bytes16[](1); + subjects[0] = subject; + uncurse(subjects); + } + + /// @notice Uncurse an array of subjects + /// @param subjects the subjects to uncurse + /// @dev reverts if any of the subjects are not cursed or if there is a duplicate + function uncurse( + bytes16[] memory subjects + ) public onlyOwner { + for (uint256 i = 0; i < subjects.length; ++i) { + if (!s_cursedSubjects.remove(subjects[i])) { + revert NotCursed(subjects[i]); + } + } + emit Uncursed(subjects); + } + + /// @inheritdoc IRMNRemote + function getCursedSubjects() external view returns (bytes16[] memory subjects) { + return s_cursedSubjects.values(); + } + + /// @inheritdoc IRMNRemote + function isCursed() external view returns (bool) { + if (s_cursedSubjects.length() == 0) { + return false; + } + return s_cursedSubjects.contains(LEGACY_CURSE_SUBJECT) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); + } + + /// @inheritdoc IRMNRemote + function isCursed( + bytes16 subject + ) external view returns (bool) { + if (s_cursedSubjects.length() == 0) { + return false; + } + return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); + } +} diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol index ee3f3e6fd4c..ea75b4eda99 100644 --- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.24; // Imports to any non-library are not allowed due to the significant cascading // compile time increase they cause when imported into this base test. + +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; import {Internal} from "../libraries/Internal.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; import {MockRMN} from "./mocks/MockRMN.sol"; @@ -33,13 +35,13 @@ contract BaseTest is Test { // Onramp uint96 internal constant MAX_NOP_FEES_JUELS = 1e27; - uint96 internal constant MAX_MSG_FEES_JUELS = 1e18; - uint32 internal constant DEST_GAS_OVERHEAD = 350_000; + uint96 internal constant MAX_MSG_FEES_JUELS = 1_000e18; + uint32 internal constant DEST_GAS_OVERHEAD = 300_000; uint16 internal constant DEST_GAS_PER_PAYLOAD_BYTE = 16; uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; - uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 34_000; - uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 50; + uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 90_000; + uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; bool private s_baseTestInitialized; @@ -61,8 +63,6 @@ contract BaseTest is Test { // OffRamp uint32 internal constant MAX_DATA_SIZE = 30_000; uint16 internal constant MAX_TOKENS_LENGTH = 5; - uint32 internal constant MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS = 200_000; - uint32 internal constant MAX_TOKEN_POOL_TRANSFER_GAS = 50_000; uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5000; uint32 internal constant PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS = 500; uint32 internal constant MAX_GAS_LIMIT = 4_000_000; @@ -71,6 +71,10 @@ contract BaseTest is Test { address internal constant ADMIN = 0x11118e64e1FB0c487f25dD6D3601FF6aF8d32E4e; MockRMN internal s_mockRMN; + IRMNRemote internal s_mockRMNRemote; + + // nonce for pseudo-random number generation, not to be exposed to test suites + uint256 private randNonce; function setUp() public virtual { // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. @@ -86,18 +90,38 @@ contract BaseTest is Test { // Set the block time to a constant known value vm.warp(BLOCK_TIME); + // setup mock RMN & RMNRemote s_mockRMN = new MockRMN(); + s_mockRMNRemote = IRMNRemote(makeAddr("MOCK RMN REMOTE")); + vm.etch(address(s_mockRMNRemote), bytes("fake bytecode")); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + _setMockRMNGlobalCurse(false); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(false)); // no curses by defaule + } + + function _setMockRMNGlobalCurse( + bool isCursed + ) internal { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(isCursed)); + } + + function _setMockRMNChainCurse(uint64 chainSelector, bool isCursed) internal { + vm.mockCall( + address(s_mockRMNRemote), + abi.encodeWithSignature("isCursed(bytes16)", bytes16(uint128(chainSelector))), + abi.encode(isCursed) + ); } - function getOutboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { + function _getOutboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { return RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e15}); } - function getInboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { + function _getInboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { return RateLimiter.Config({isEnabled: true, capacity: 222e30, rate: 1e18}); } - function getSingleTokenPriceUpdateStruct( + function _getSingleTokenPriceUpdateStruct( address token, uint224 price ) internal pure returns (Internal.PriceUpdates memory) { @@ -110,16 +134,18 @@ contract BaseTest is Test { return priceUpdates; } - function getSingleGasPriceUpdateStruct( - uint64 chainSelector, - uint224 usdPerUnitGas - ) internal pure returns (Internal.PriceUpdates memory) { - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: chainSelector, usdPerUnitGas: usdPerUnitGas}); + /// @dev returns a pseudo-random bytes32 + function _randomBytes32() internal returns (bytes32) { + return keccak256(abi.encodePacked(++randNonce)); + } - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); + /// @dev returns a pseudo-random number + function _randomNum() internal returns (uint256) { + return uint256(_randomBytes32()); + } - return priceUpdates; + /// @dev returns a pseudo-random address + function _randomAddress() internal returns (address) { + return address(uint160(_randomNum())); } } diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index 75de4db8c5c..2ca9e2d450a 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -1,23 +1,36 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {NonceManager} from "../NonceManager.sol"; import {ICommitStore} from "../interfaces/ICommitStore.sol"; +import {IEVM2AnyOnRamp} from "../interfaces/IEVM2AnyOnRamp.sol"; + +import {NonceManager} from "../NonceManager.sol"; +import {Router} from "../Router.sol"; import {Client} from "../libraries/Client.sol"; import {Internal} from "../libraries/Internal.sol"; import {Pool} from "../libraries/Pool.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {EVM2EVMMultiOffRamp} from "../offRamp/EVM2EVMMultiOffRamp.sol"; -import {EVM2EVMMultiOnRamp} from "../onRamp/EVM2EVMMultiOnRamp.sol"; -import {EVM2EVMOnRamp} from "../onRamp/EVM2EVMOnRamp.sol"; - +import {OffRamp} from "../offRamp/OffRamp.sol"; +import {OnRamp} from "../onRamp/OnRamp.sol"; import {BaseTest} from "./BaseTest.t.sol"; -import {EVM2EVMMultiOnRampHelper} from "./helpers/EVM2EVMMultiOnRampHelper.sol"; import {EVM2EVMOffRampHelper} from "./helpers/EVM2EVMOffRampHelper.sol"; -import {EVM2EVMOnRampHelper} from "./helpers/EVM2EVMOnRampHelper.sol"; -import {MockCommitStore} from "./mocks/MockCommitStore.sol"; -import {EVM2EVMMultiOffRampSetup} from "./offRamp/EVM2EVMMultiOffRampSetup.t.sol"; -import {EVM2EVMMultiOnRampSetup} from "./onRamp/EVM2EVMMultiOnRampSetup.t.sol"; +import {OnRampHelper} from "./helpers/OnRampHelper.sol"; +import {OffRampSetup} from "./offRamp/OffRampSetup.t.sol"; +import {OnRampSetup} from "./onRamp/OnRampSetup.t.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract NonceManager_typeAndVersion is Test { + NonceManager private s_nonceManager; + + function setUp() public { + s_nonceManager = new NonceManager(new address[](0)); + } + + function test_typeAndVersion() public view { + assertEq(s_nonceManager.typeAndVersion(), "NonceManager 1.6.0-dev"); + } +} contract NonceManager_NonceIncrementation is BaseTest { NonceManager private s_nonceManager; @@ -75,13 +88,16 @@ contract NonceManager_NonceIncrementation is BaseTest { } } -contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { - function test_SingleRampUpdate() public { +contract NonceManager_applyPreviousRampsUpdates is OnRampSetup { + function test_SingleRampUpdate_success() public { address prevOnRamp = makeAddr("prevOnRamp"); address prevOffRamp = makeAddr("prevOffRamp"); NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), + overrideExistingRamps: false + }); vm.expectEmit(); emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); @@ -91,16 +107,22 @@ contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); } - function test_MultipleRampsUpdates() public { + function test_MultipleRampsUpdates_success() public { address prevOnRamp1 = makeAddr("prevOnRamp1"); address prevOnRamp2 = makeAddr("prevOnRamp2"); address prevOffRamp1 = makeAddr("prevOffRamp1"); address prevOffRamp2 = makeAddr("prevOffRamp2"); NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](2); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp1, prevOffRamp1)); - previousRamps[1] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR + 1, NonceManager.PreviousRamps(prevOnRamp2, prevOffRamp2)); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp1, prevOffRamp1), + overrideExistingRamps: false + }); + previousRamps[1] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR + 1, + prevRamps: NonceManager.PreviousRamps(prevOnRamp2, prevOffRamp2), + overrideExistingRamps: false + }); vm.expectEmit(); emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); @@ -115,7 +137,27 @@ contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { ); } - function test_ZeroInput() public { + function test_PreviousRampAlreadySet_overrideAllowed_success() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOffRamp = makeAddr("prevOffRamp"); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: true + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: true + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function test_ZeroInput_success() public { vm.recordLogs(); s_outboundNonceManager.applyPreviousRampsUpdates(new NonceManager.PreviousRampsArgs[](0)); @@ -125,13 +167,19 @@ contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { function test_PreviousRampAlreadySetOnRamp_Revert() public { NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); address prevOnRamp = makeAddr("prevOnRamp"); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, address(0))); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, address(0)), + overrideExistingRamps: false + }); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, address(0))); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, address(0)), + overrideExistingRamps: false + }); vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); @@ -140,13 +188,19 @@ contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { function test_PreviousRampAlreadySetOffRamp_Revert() public { NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(0), prevOffRamp)); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: false + }); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(0), prevOffRamp)); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: false + }); vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); @@ -156,13 +210,19 @@ contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); address prevOnRamp = makeAddr("prevOnRamp"); address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), + overrideExistingRamps: false + }); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), + overrideExistingRamps: false + }); vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); @@ -177,75 +237,30 @@ contract NonceManager_applyPreviousRampsUpdates is EVM2EVMMultiOnRampSetup { } } -contract NonceManager_OnRampUpgrade is EVM2EVMMultiOnRampSetup { +contract NonceManager_OnRampUpgrade is OnRampSetup { uint256 internal constant FEE_AMOUNT = 1234567890; - EVM2EVMOnRampHelper internal s_prevOnRamp; + OnRampHelper internal s_prevOnRamp; function setUp() public virtual override { super.setUp(); - EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeTokenConfigArgs = new EVM2EVMOnRamp.FeeTokenConfigArgs[](1); - feeTokenConfigArgs[0] = EVM2EVMOnRamp.FeeTokenConfigArgs({ - token: s_sourceFeeToken, - networkFeeUSDCents: 1_00, // 1 USD - gasMultiplierWeiPerEth: 1e18, // 1x - premiumMultiplierWeiPerEth: 5e17, // 0.5x - enabled: true - }); - - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfig = - new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](1); - - tokenTransferFeeConfig[0] = EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: s_sourceFeeToken, - minFeeUSDCents: 1_00, // 1 USD - maxFeeUSDCents: 1000_00, // 1,000 USD - deciBps: 2_5, // 2.5 bps, or 0.025% - destGasOverhead: 40_000, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), - aggregateRateLimitEnabled: true - }); - - s_prevOnRamp = new EVM2EVMOnRampHelper( - EVM2EVMOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], - chainSelector: SOURCE_CHAIN_SELECTOR, - destChainSelector: DEST_CHAIN_SELECTOR, - defaultTxGasLimit: GAS_LIMIT, - maxNopFeesJuels: MAX_NOP_FEES_JUELS, - prevOnRamp: address(0), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - EVM2EVMOnRamp.DynamicConfig({ - router: address(s_sourceRouter), - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - destGasOverhead: DEST_GAS_OVERHEAD, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - priceRegistry: address(s_priceRegistry), - maxDataBytes: MAX_DATA_SIZE, - maxPerMsgGasLimit: MAX_GAS_LIMIT, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, - enforceOutOfOrder: false - }), - RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e15}), - feeTokenConfigArgs, - tokenTransferFeeConfig, - new EVM2EVMOnRamp.NopAndWeight[](0) + (s_prevOnRamp,) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) ); + // Since the previous onRamp is not a 1.5 ramp it doesn't have the getSenderNonce function. We mock it to return 0 + vm.mockCall(address(s_prevOnRamp), abi.encodeWithSelector(IEVM2AnyOnRamp.getSenderNonce.selector), abi.encode(0)); + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(s_prevOnRamp), address(0))); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(s_prevOnRamp), address(0)), + overrideExistingRamps: false + }); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); (s_onRamp, s_metadataHash) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, address(s_sourceRouter), address(s_outboundNonceManager), address(s_tokenAdminRegistry) + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) ); vm.startPrank(address(s_sourceRouter)); @@ -255,7 +270,8 @@ contract NonceManager_OnRampUpgrade is EVM2EVMMultiOnRampSetup { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); } @@ -282,18 +298,14 @@ contract NonceManager_OnRampUpgrade is EVM2EVMMultiOnRampSetup { // new onramp nonce should start from 2, while sequence number start from 1 vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested( - DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER) - ); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); assertEq(startNonce + 2, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); // after another send, nonce should be 3, and sequence number be 2 vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested( - DEST_CHAIN_SELECTOR, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER) - ); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 2, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); assertEq(startNonce + 3, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); @@ -308,16 +320,14 @@ contract NonceManager_OnRampUpgrade is EVM2EVMMultiOnRampSetup { address newSender = address(1234567); // new onramp nonce should start from 1 for new sender vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested( - DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender) - ); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); } } -contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { +contract NonceManager_OffRampUpgrade is OffRampSetup { EVM2EVMOffRampHelper internal s_prevOffRamp; - EVM2EVMOffRampHelper[] internal s_nestedPrevOffRamps; address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_1 = abi.decode(ON_RAMP_ADDRESS_1, (address)); address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_2 = abi.decode(ON_RAMP_ADDRESS_2, (address)); @@ -326,48 +336,32 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { function setUp() public virtual override { super.setUp(); - ICommitStore mockPrevCommitStore = new MockCommitStore(); - s_prevOffRamp = _deploySingleLaneOffRamp( - mockPrevCommitStore, s_destRouter, address(0), SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1 - ); + s_prevOffRamp = new EVM2EVMOffRampHelper(); - s_nestedPrevOffRamps = new EVM2EVMOffRampHelper[](2); - s_nestedPrevOffRamps[0] = _deploySingleLaneOffRamp( - mockPrevCommitStore, s_destRouter, address(0), SOURCE_CHAIN_SELECTOR_2, SINGLE_LANE_ON_RAMP_ADDRESS_2 - ); - s_nestedPrevOffRamps[1] = _deploySingleLaneOffRamp( - mockPrevCommitStore, - s_destRouter, - address(s_nestedPrevOffRamps[0]), - SOURCE_CHAIN_SELECTOR_2, - SINGLE_LANE_ON_RAMP_ADDRESS_2 - ); + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + prevRamps: NonceManager.PreviousRamps(address(0), address(s_prevOffRamp)), + overrideExistingRamps: false + }); - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](3); - previousRamps[0] = NonceManager.PreviousRampsArgs( - SOURCE_CHAIN_SELECTOR_1, NonceManager.PreviousRamps(address(0), address(s_prevOffRamp)) - ); - previousRamps[1] = NonceManager.PreviousRampsArgs( - SOURCE_CHAIN_SELECTOR_2, NonceManager.PreviousRamps(address(0), address(s_nestedPrevOffRamps[1])) - ); - previousRamps[2] = NonceManager.PreviousRampsArgs( - SOURCE_CHAIN_SELECTOR_3, NonceManager.PreviousRamps(SINGLE_LANE_ON_RAMP_ADDRESS_3, address(0)) - ); s_inboundNonceManager.applyPreviousRampsUpdates(previousRamps); - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, isEnabled: true, onRamp: ON_RAMP_ADDRESS_1 }); - sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, isEnabled: true, onRamp: ON_RAMP_ADDRESS_2 }); - sourceChainConfigs[2] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, isEnabled: true, onRamp: ON_RAMP_ADDRESS_3 @@ -382,169 +376,149 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { function test_Upgraded_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } function test_NoPrevOffRampForChain_Success() public { - Internal.EVM2EVMMessage[] memory messages = - _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); - uint64 startNonceChain3 = - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages[0].sender)); - s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0])); + s_prevOffRamp.execute(senders); // Nonce unchanged for chain 3 - assertEq( - startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages[0].sender)) - ); + assertEq(startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0]))); Internal.Any2EVMRampMessage[] memory messagesChain3 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].header.sequenceNumber, messagesChain3[0].header.messageId, + _hashMessage(messagesChain3[0], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new uint256[](0) - ); assertEq( startNonceChain3 + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].sender) ); } function test_UpgradedSenderNoncesReadsPreviousRamp_Success() public { - Internal.EVM2EVMMessage[] memory messages = - _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); + address[] memory senders = new address[](1); + senders[0] = OWNER; - // messages contains a single message - update for the next execution - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_prevOffRamp.metadataHash()); - - assertEq( - startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) - ); - } - } - - function test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() public { - Internal.EVM2EVMMessage[] memory messages = - _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, SINGLE_LANE_ON_RAMP_ADDRESS_2); - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_2, abi.encode(messages[0].sender)); + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); for (uint64 i = 1; i < 4; ++i) { - s_nestedPrevOffRamps[0].execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); + s_prevOffRamp.execute(senders); - // messages contains a single message - update for the next execution - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_nestedPrevOffRamps[0].metadataHash()); - - // Read through prev sender nonce through prevOffRamp -> prevPrevOffRamp - assertEq( - startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_2, abi.encode(messages[0].sender)) - ); + assertEq(startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); } } function test_UpgradedNonceStartsAtV1Nonce_Success() public { - Internal.EVM2EVMMessage[] memory messages = - _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); + address[] memory senders = new address[](1); + senders[0] = OWNER; - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); - s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); + s_prevOffRamp.execute(senders); - assertEq( - startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) - ); + assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); Internal.Any2EVMRampMessage[] memory messagesMultiRamp = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messagesMultiRamp[0].header.nonce++; - messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) - ); assertEq( startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) ); messagesMultiRamp[0].header.nonce++; messagesMultiRamp[0].header.sequenceNumber++; - messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) - ); assertEq( startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) ); } function test_UpgradedNonceNewSenderStartsAtZero_Success() public { - Internal.EVM2EVMMessage[] memory messages = - _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); + address[] memory senders = new address[](1); + senders[0] = OWNER; - s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); + s_prevOffRamp.execute(senders); Internal.Any2EVMRampMessage[] memory messagesMultiRamp = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); bytes memory newSender = abi.encode(address(1234567)); messagesMultiRamp[0].sender = newSender; - messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + // new sender nonce in new offramp should go from 0 -> 1 + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - // new sender nonce in new offramp should go from 0 -> 1 - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) - ); assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 1); } @@ -555,7 +529,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { address newSender = address(1234567); messages[0].sender = abi.encode(newSender); messages[0].header.nonce = 2; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); @@ -563,87 +537,36 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { // it waits for previous offramp to execute vm.expectEmit(); emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].header.nonce, messages[0].sender); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); - Internal.EVM2EVMMessage[] memory messagesSingleLane = - _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); - - messagesSingleLane[0].nonce = 1; - messagesSingleLane[0].sender = newSender; - messagesSingleLane[0].messageId = Internal._hash(messagesSingleLane[0], s_prevOffRamp.metadataHash()); + address[] memory senders = new address[](1); + senders[0] = newSender; // previous offramp executes msg and increases nonce - s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messagesSingleLane), new uint256[](0)); - assertEq( - startNonce + 1, - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messagesSingleLane[0].sender)) - ); + s_prevOffRamp.execute(senders); + assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); messages[0].header.nonce = 2; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); // new offramp is able to execute - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); } - - function _generateSingleLaneRampReportFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (Internal.ExecutionReport memory) - { - bytes[][] memory offchainTokenData = new bytes[][](messages.length); - - for (uint256 i = 0; i < messages.length; ++i) { - offchainTokenData[i] = new bytes[](messages[i].tokenAmounts.length); - } - - return Internal.ExecutionReport({ - proofs: new bytes32[](0), - proofFlagBits: 2 ** 256 - 1, - messages: messages, - offchainTokenData: offchainTokenData - }); - } - - function _generateSingleLaneSingleBasicMessage( - uint64 sourceChainSelector, - address onRamp - ) internal view returns (Internal.EVM2EVMMessage[] memory) { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](1); - - bytes memory data = abi.encode(0); - messages[0] = Internal.EVM2EVMMessage({ - sequenceNumber: 1, - sender: OWNER, - nonce: 1, - gasLimit: GAS_LIMIT, - strict: false, - sourceChainSelector: sourceChainSelector, - receiver: address(s_receiver), - data: data, - tokenAmounts: new Client.EVMTokenAmount[](0), - sourceTokenData: new bytes[](0), - feeToken: s_destFeeToken, - feeTokenAmount: uint256(0), - messageId: "" - }); - - messages[0].messageId = Internal._hash( - messages[0], - keccak256(abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, onRamp)) - ); - - return messages; - } } diff --git a/contracts/src/v0.8/ccip/test/TokenSetup.t.sol b/contracts/src/v0.8/ccip/test/TokenSetup.t.sol index 182d92c5c94..203145881e3 100644 --- a/contracts/src/v0.8/ccip/test/TokenSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/TokenSetup.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IPoolV1} from "../interfaces/IPool.sol"; - import {BurnMintERC677} from "../../shared/token/ERC677/BurnMintERC677.sol"; import {Client} from "../libraries/Client.sol"; import {BurnMintTokenPool} from "../pools/BurnMintTokenPool.sol"; @@ -138,7 +136,7 @@ contract TokenSetup is RouterSetup { } } - function getCastedSourceEVMTokenAmountsWithZeroAmounts() + function _getCastedSourceEVMTokenAmountsWithZeroAmounts() internal view returns (Client.EVMTokenAmount[] memory tokenAmounts) @@ -147,6 +145,7 @@ contract TokenSetup is RouterSetup { for (uint256 i = 0; i < tokenAmounts.length; ++i) { tokenAmounts[i].token = s_sourceTokens[i]; } + return tokenAmounts; } function _setPool( @@ -170,8 +169,8 @@ contract TokenSetup is RouterSetup { remotePoolAddress: abi.encode(remotePoolAddress), remoteTokenAddress: abi.encode(remoteToken), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); TokenPool(pool).applyChainUpdates(chainUpdates); diff --git a/contracts/src/v0.8/ccip/test/WETH9.sol b/contracts/src/v0.8/ccip/test/WETH9.sol index fbc19ee2c4d..bfd2b5f022f 100644 --- a/contracts/src/v0.8/ccip/test/WETH9.sol +++ b/contracts/src/v0.8/ccip/test/WETH9.sol @@ -43,7 +43,9 @@ contract WETH9 { _deposit(); } - function withdraw(uint256 wad) external { + function withdraw( + uint256 wad + ) external { require(balanceOf[msg.sender] >= wad); balanceOf[msg.sender] -= wad; payable(msg.sender).transfer(wad); diff --git a/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol b/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol index 18453f9f525..c68907bb9f9 100644 --- a/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol @@ -3,11 +3,11 @@ pragma solidity ^0.8.0; import {DefensiveExample} from "../../applications/DefensiveExample.sol"; import {Client} from "../../libraries/Client.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; +import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract DefensiveExampleTest is EVM2EVMOnRampSetup { +contract DefensiveExampleTest is OnRampSetup { event MessageFailed(bytes32 indexed messageId, bytes reason); event MessageSucceeded(bytes32 indexed messageId); event MessageRecovered(bytes32 indexed messageId); @@ -16,7 +16,7 @@ contract DefensiveExampleTest is EVM2EVMOnRampSetup { uint64 internal sourceChainSelector = 7331; function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); + super.setUp(); s_receiver = new DefensiveExample(s_destRouter, IERC20(s_destFeeToken)); s_receiver.enableChain(sourceChainSelector, abi.encode("")); diff --git a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol index cfd402d9106..489ebcf8b8e 100644 --- a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol @@ -107,7 +107,9 @@ contract EtherSenderReceiverTest_validatedMessage is EtherSenderReceiverTest { uint256 internal constant amount = 100; - function test_Fuzz_validatedMessage_msgSenderOverwrite(bytes memory data) public view { + function test_Fuzz_validatedMessage_msgSenderOverwrite( + bytes memory data + ) public view { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -130,7 +132,9 @@ contract EtherSenderReceiverTest_validatedMessage is EtherSenderReceiverTest { assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); } - function test_Fuzz_validatedMessage_tokenAddressOverwrite(address token) public view { + function test_Fuzz_validatedMessage_tokenAddressOverwrite( + address token + ) public view { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ @@ -300,7 +304,9 @@ contract EtherSenderReceiverTest_ccipReceive is EtherSenderReceiverTest { error InvalidTokenAmounts(uint256 gotAmounts); error InvalidToken(address gotToken, address expectedToken); - function test_Fuzz_ccipReceive(uint256 tokenAmount) public { + function test_Fuzz_ccipReceive( + uint256 tokenAmount + ) public { // cap to 10 ether because OWNER only has 10 ether. if (tokenAmount > 10 ether) { return; diff --git a/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol b/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol index eb12e6205a4..61b0204e7d8 100644 --- a/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol @@ -4,13 +4,13 @@ import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver. import {CCIPClientExample} from "../../applications/CCIPClientExample.sol"; import {Client} from "../../libraries/Client.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; +import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; import {ERC165Checker} from - "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; + "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; -contract CCIPClientExample_sanity is EVM2EVMOnRampSetup { +contract CCIPClientExample_sanity is OnRampSetup { function test_ImmutableExamples_Success() public { CCIPClientExample exampleContract = new CCIPClientExample(s_sourceRouter, IERC20(s_sourceFeeToken)); deal(address(exampleContract), 100 ether); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol index 3297e1f4fbc..d47ba1c54fb 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol @@ -3,17 +3,17 @@ pragma solidity 0.8.24; import {PingPongDemo} from "../../applications/PingPongDemo.sol"; import {Client} from "../../libraries/Client.sol"; -import "../onRamp/EVM2EVMOnRampSetup.t.sol"; +import "../onRamp/OnRampSetup.t.sol"; // setup -contract PingPongDappSetup is EVM2EVMOnRampSetup { +contract PingPongDappSetup is OnRampSetup { PingPongDemo internal s_pingPong; IERC20 internal s_feeToken; address internal immutable i_pongContract = makeAddr("ping_pong_counterpart"); function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); + super.setUp(); s_feeToken = IERC20(s_sourceTokens[0]); s_pingPong = new PingPongDemo(address(s_sourceRouter), s_feeToken); @@ -27,42 +27,26 @@ contract PingPongDappSetup is EVM2EVMOnRampSetup { } contract PingPong_startPingPong is PingPongDappSetup { - function test_StartPingPong_Success() public { - uint256 pingPongNumber = 1; - bytes memory data = abi.encode(pingPongNumber); - - Client.EVM2AnyMessage memory sentMessage = Client.EVM2AnyMessage({ - receiver: abi.encode(i_pongContract), - data: data, - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 2e5})) - }); + uint256 internal pingPongNumber = 1; - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, sentMessage); - - Internal.EVM2EVMMessage memory message = Internal.EVM2EVMMessage({ - sequenceNumber: 1, - feeTokenAmount: expectedFee, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - sender: address(s_pingPong), - receiver: i_pongContract, - nonce: 1, - data: data, - tokenAmounts: sentMessage.tokenAmounts, - sourceTokenData: new bytes[](sentMessage.tokenAmounts.length), - gasLimit: 2e5, - feeToken: sentMessage.feeToken, - strict: false, - messageId: "" - }); - message.messageId = Internal._hash(message, s_metadataHash); + function test_StartPingPong_With_Sequenced_Ordered_Success() public { + _assertPingPongSuccess(); + } + + function test_StartPingPong_With_OOO_Success() public { + s_pingPong.setOutOfOrderExecution(true); + _assertPingPongSuccess(); + } + + function _assertPingPongSuccess() internal { vm.expectEmit(); emit PingPongDemo.Ping(pingPongNumber); - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(message); + Internal.EVM2AnyRampMessage memory message; + + vm.expectEmit(false, false, false, false); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, message); s_pingPong.startPingPong(); } @@ -92,19 +76,25 @@ contract PingPong_ccipReceive is PingPongDappSetup { } contract PingPong_plumbing is PingPongDappSetup { - function test_Fuzz_CounterPartChainSelector_Success(uint64 chainSelector) public { + function test_Fuzz_CounterPartChainSelector_Success( + uint64 chainSelector + ) public { s_pingPong.setCounterpartChainSelector(chainSelector); assertEq(s_pingPong.getCounterpartChainSelector(), chainSelector); } - function test_Fuzz_CounterPartAddress_Success(address counterpartAddress) public { + function test_Fuzz_CounterPartAddress_Success( + address counterpartAddress + ) public { s_pingPong.setCounterpartAddress(counterpartAddress); assertEq(s_pingPong.getCounterpartAddress(), counterpartAddress); } function test_Fuzz_CounterPartAddress_Success(uint64 chainSelector, address counterpartAddress) public { + s_pingPong.setCounterpartChainSelector(chainSelector); + s_pingPong.setCounterpart(chainSelector, counterpartAddress); assertEq(s_pingPong.getCounterpartAddress(), counterpartAddress); @@ -118,4 +108,15 @@ contract PingPong_plumbing is PingPongDappSetup { assertTrue(s_pingPong.isPaused()); } + + function test_OutOfOrderExecution_Success() public { + assertFalse(s_pingPong.getOutOfOrderExecution()); + + vm.expectEmit(); + emit PingPongDemo.OutOfOrderExecutionChange(true); + + s_pingPong.setOutOfOrderExecution(true); + + assertTrue(s_pingPong.getOutOfOrderExecution()); + } } diff --git a/contracts/src/v0.8/ccip/test/applications/SelfFundedPingPong.t.sol b/contracts/src/v0.8/ccip/test/applications/SelfFundedPingPong.t.sol deleted file mode 100644 index d5db9d1f9d0..00000000000 --- a/contracts/src/v0.8/ccip/test/applications/SelfFundedPingPong.t.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {SelfFundedPingPong} from "../../applications/SelfFundedPingPong.sol"; -import {Client} from "../../libraries/Client.sol"; -import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract SelfFundedPingPongDappSetup is EVM2EVMOnRampSetup { - SelfFundedPingPong internal s_pingPong; - IERC20 internal s_feeToken; - uint8 internal constant s_roundTripsBeforeFunding = 0; - - address internal immutable i_pongContract = makeAddr("ping_pong_counterpart"); - - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - - s_feeToken = IERC20(s_sourceTokens[0]); - s_pingPong = new SelfFundedPingPong(address(s_sourceRouter), s_feeToken, s_roundTripsBeforeFunding); - s_pingPong.setCounterpart(DEST_CHAIN_SELECTOR, i_pongContract); - - uint256 fundingAmount = 5e18; - - // set ping pong as an onRamp nop to make sure that funding runs - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](1); - nopsAndWeights[0] = EVM2EVMOnRamp.NopAndWeight({nop: address(s_pingPong), weight: 1}); - s_onRamp.setNops(nopsAndWeights); - - // Fund the contract with LINK tokens - s_feeToken.transfer(address(s_pingPong), fundingAmount); - } -} - -contract SelfFundedPingPong_ccipReceive is SelfFundedPingPongDappSetup { - function test_Funding_Success() public { - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: keccak256("msg id"), - sourceChainSelector: DEST_CHAIN_SELECTOR, - sender: abi.encode(i_pongContract), - data: "", - destTokenAmounts: new Client.EVMTokenAmount[](0) - }); - - uint8 countIncrBeforeFunding = 5; - - vm.expectEmit(); - emit SelfFundedPingPong.CountIncrBeforeFundingSet(countIncrBeforeFunding); - - s_pingPong.setCountIncrBeforeFunding(countIncrBeforeFunding); - - vm.startPrank(address(s_sourceRouter)); - for (uint256 pingPongNumber = 0; pingPongNumber <= countIncrBeforeFunding; ++pingPongNumber) { - message.data = abi.encode(pingPongNumber); - if (pingPongNumber == countIncrBeforeFunding - 1) { - vm.expectEmit(); - emit SelfFundedPingPong.Funded(); - vm.expectCall(address(s_onRamp), ""); - } - s_pingPong.ccipReceive(message); - } - } - - function test_FundingIfNotANop_Revert() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](0); - s_onRamp.setNops(nopsAndWeights); - - uint8 countIncrBeforeFunding = 3; - s_pingPong.setCountIncrBeforeFunding(countIncrBeforeFunding); - - vm.startPrank(address(s_sourceRouter)); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: DEST_CHAIN_SELECTOR, - sender: abi.encode(i_pongContract), - data: abi.encode(countIncrBeforeFunding), - destTokenAmounts: new Client.EVMTokenAmount[](0) - }); - - // because pingPong is not set as a nop - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdminOrNop.selector); - s_pingPong.ccipReceive(message); - } -} - -contract SelfFundedPingPong_setCountIncrBeforeFunding is SelfFundedPingPongDappSetup { - function test_setCountIncrBeforeFunding() public { - uint8 c = s_pingPong.getCountIncrBeforeFunding(); - - vm.expectEmit(); - emit SelfFundedPingPong.CountIncrBeforeFundingSet(c + 1); - - s_pingPong.setCountIncrBeforeFunding(c + 1); - uint8 c2 = s_pingPong.getCountIncrBeforeFunding(); - assertEq(c2, c + 1); - } -} diff --git a/contracts/src/v0.8/ccip/test/applications/TokenProxy.t.sol b/contracts/src/v0.8/ccip/test/applications/TokenProxy.t.sol deleted file mode 100644 index 9e78f6e369f..00000000000 --- a/contracts/src/v0.8/ccip/test/applications/TokenProxy.t.sol +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {TokenProxy} from "../../applications/TokenProxy.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract TokenProxySetup is EVM2EVMOnRampSetup { - TokenProxy internal s_tokenProxy; - IERC20 internal s_feeToken; - IERC20 internal s_transferToken; - - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - - s_feeToken = IERC20(s_sourceTokens[0]); - s_transferToken = IERC20(s_sourceTokens[1]); - s_tokenProxy = new TokenProxy(address(s_sourceRouter), address(s_transferToken)); - - s_transferToken.approve(address(s_tokenProxy), type(uint256).max); - s_feeToken.approve(address(s_tokenProxy), type(uint256).max); - } -} - -contract TokenProxy_constructor is TokenProxySetup { - function test_Constructor() public view { - assertEq(address(s_tokenProxy.getRouter()), address(s_sourceRouter)); - assertEq(address(s_tokenProxy.getToken()), address(s_transferToken)); - } -} - -contract TokenProxy_getFee is TokenProxySetup { - function test_GetFee_Success() public view { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(s_tokenProxy), - data: "", - tokenAmounts: tokens, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})) - }); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - uint256 actualFee = s_tokenProxy.getFee(DEST_CHAIN_SELECTOR, message); - assertEq(expectedFee, actualFee); - } - - // Reverts - - function test_GetFeeInvalidToken_Revert() public { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(s_tokenProxy), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})) - }); - - vm.expectRevert(TokenProxy.InvalidToken.selector); - - s_tokenProxy.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_GetFeeNoDataAllowed_Revert() public { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(s_tokenProxy), - data: "not empty", - tokenAmounts: tokens, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})) - }); - - vm.expectRevert(TokenProxy.NoDataAllowed.selector); - - s_tokenProxy.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_GetFeeGasShouldBeZero_Revert() public { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(s_tokenProxy), - data: "", - tokenAmounts: tokens, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 10})) - }); - - vm.expectRevert(TokenProxy.GasShouldBeZero.selector); - - s_tokenProxy.getFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract TokenProxy_ccipSend is TokenProxySetup { - function test_CcipSend_Success() public { - vm.pauseGasMetering(); - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = tokens; - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - - s_feeToken.approve(address(s_tokenProxy), expectedFee); - - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - msgEvent.sender = address(s_tokenProxy); - msgEvent.messageId = Internal._hash(msgEvent, s_metadataHash); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); - - vm.resumeGasMetering(); - s_tokenProxy.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_CcipSendNative_Success() public { - vm.pauseGasMetering(); - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = tokens; - message.feeToken = address(0); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - msgEvent.sender = address(s_tokenProxy); - msgEvent.feeToken = s_sourceRouter.getWrappedNative(); - msgEvent.messageId = Internal._hash(msgEvent, s_metadataHash); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); - - vm.resumeGasMetering(); - s_tokenProxy.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); - } - - // Reverts - - function test_CcipSendInsufficientAllowance_Revert() public { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = tokens; - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})); - - // Revoke allowance - s_transferToken.approve(address(s_tokenProxy), 0); - - vm.expectRevert("ERC20: insufficient allowance"); - - s_tokenProxy.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_CcipSendInvalidToken_Revert() public { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_feeToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = tokens; - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})); - - vm.expectRevert(TokenProxy.InvalidToken.selector); - - s_tokenProxy.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_CcipSendNoDataAllowed_Revert() public { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = tokens; - message.data = "not empty"; - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})); - - vm.expectRevert(TokenProxy.NoDataAllowed.selector); - - s_tokenProxy.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_CcipSendGasShouldBeZero_Revert() public { - Client.EVMTokenAmount[] memory tokens = new Client.EVMTokenAmount[](1); - tokens[0] = Client.EVMTokenAmount({token: address(s_transferToken), amount: 1e18}); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = tokens; - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1})); - - vm.expectRevert(TokenProxy.GasShouldBeZero.selector); - - s_tokenProxy.ccipSend(DEST_CHAIN_SELECTOR, message); - } -} diff --git a/contracts/src/v0.8/ccip/test/arm/ARMProxy.t.sol b/contracts/src/v0.8/ccip/test/arm/ARMProxy.t.sol deleted file mode 100644 index 24b617c82a0..00000000000 --- a/contracts/src/v0.8/ccip/test/arm/ARMProxy.t.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; - -import {ARMProxy} from "../../ARMProxy.sol"; -import {RMN} from "../../RMN.sol"; -import {MockRMN} from "../mocks/MockRMN.sol"; -import {RMNSetup, makeSubjects} from "./RMNSetup.t.sol"; - -contract ARMProxyTest is RMNSetup { - MockRMN internal s_mockRMN; - ARMProxy internal s_armProxy; - - function setUp() public virtual override { - RMNSetup.setUp(); - s_mockRMN = new MockRMN(); - s_armProxy = new ARMProxy(address(s_rmn)); - } - - function test_ARMIsCursed_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_ARMIsBlessed_Success() public { - s_armProxy.setARM(address(s_mockRMN)); - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(0), root: bytes32(0)}), true); - assertTrue(IRMN(address(s_armProxy)).isBlessed(IRMN.TaggedRoot({commitStore: address(0), root: bytes32(0)}))); - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(0), root: bytes32(0)}), false); - assertFalse(IRMN(address(s_armProxy)).isBlessed(IRMN.TaggedRoot({commitStore: address(0), root: bytes32(0)}))); - } - - function test_ARMCallRevertReasonForwarded() 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(); - } -} diff --git a/contracts/src/v0.8/ccip/test/arm/RMN.t.sol b/contracts/src/v0.8/ccip/test/arm/RMN.t.sol deleted file mode 100644 index d3237592f29..00000000000 --- a/contracts/src/v0.8/ccip/test/arm/RMN.t.sol +++ /dev/null @@ -1,1068 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; - -import {GLOBAL_CURSE_SUBJECT, LIFT_CURSE_VOTE_ADDR, OWNER_CURSE_VOTE_ADDR, RMN} from "../../RMN.sol"; -import {RMNSetup, makeCursesHash, makeSubjects} from "./RMNSetup.t.sol"; - -import {Test} from "forge-std/Test.sol"; - -bytes28 constant GARBAGE_CURSES_HASH = bytes28(keccak256("GARBAGE_CURSES_HASH")); - -contract ConfigCompare is Test { - function assertConfigEq(RMN.Config memory actualConfig, RMN.Config memory expectedConfig) public pure { - assertEq(actualConfig.voters.length, expectedConfig.voters.length); - for (uint256 i = 0; i < expectedConfig.voters.length; ++i) { - RMN.Voter memory expectedVoter = expectedConfig.voters[i]; - RMN.Voter memory actualVoter = actualConfig.voters[i]; - assertEq(actualVoter.blessVoteAddr, expectedVoter.blessVoteAddr); - assertEq(actualVoter.curseVoteAddr, expectedVoter.curseVoteAddr); - assertEq(actualVoter.blessWeight, expectedVoter.blessWeight); - assertEq(actualVoter.curseWeight, expectedVoter.curseWeight); - } - assertEq(actualConfig.blessWeightThreshold, expectedConfig.blessWeightThreshold); - assertEq(actualConfig.curseWeightThreshold, expectedConfig.curseWeightThreshold); - } -} - -contract RMN_constructor is ConfigCompare, RMNSetup { - function test_Constructor_Success() public view { - RMN.Config memory expectedConfig = rmnConstructorArgs(); - (uint32 actualVersion,, RMN.Config memory actualConfig) = s_rmn.getConfigDetails(); - assertEq(actualVersion, 1); - assertConfigEq(actualConfig, expectedConfig); - } -} - -contract RMN_voteToBless is RMNSetup { - function _getFirstBlessVoterAndWeight() internal pure returns (address, uint8) { - RMN.Config memory cfg = rmnConstructorArgs(); - return (cfg.voters[0].blessVoteAddr, cfg.voters[0].blessWeight); - } - - // Success - - function test_RootSuccess() public { - uint256 numRoots = 10; - - (address voter, uint8 voterWeight) = _getFirstBlessVoterAndWeight(); - - for (uint256 i = 1; i <= numRoots; ++i) { - vm.expectEmit(); - emit RMN.VotedToBless(1, voter, makeTaggedRoot(i), voterWeight); - } - - vm.prank(voter); - s_rmn.voteToBless(makeTaggedRootsInclusive(1, numRoots)); - - for (uint256 i = 1; i <= numRoots; ++i) { - assertFalse(s_rmn.isBlessed(makeTaggedRoot(i))); - assertEq(voterWeight, getWeightOfVotesToBlessRoot(makeTaggedRoot(i))); - assertTrue(hasVotedToBlessRoot(voter, makeTaggedRoot(1))); - } - } - - // Reverts - - function test_SenderAlreadyVoted_Revert() public { - (address voter,) = _getFirstBlessVoterAndWeight(); - - vm.startPrank(voter); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - assertTrue(hasVotedToBlessRoot(voter, makeTaggedRoot(1))); - - uint256 votesToBlessBefore = getWeightOfVotesToBlessRoot(makeTaggedRoot(1)); - vm.expectRevert(RMN.VoteToBlessNoop.selector); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - assertEq(votesToBlessBefore, getWeightOfVotesToBlessRoot(makeTaggedRoot(1))); - } - - function test_IsAlreadyBlessed_Revert() public { - RMN.Config memory cfg = rmnConstructorArgs(); - - // Bless voters 2,3,4 vote to bless - for (uint256 i = 1; i < cfg.voters.length; i++) { - vm.startPrank(cfg.voters[i].blessVoteAddr); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - } - - uint256 votesToBlessBefore = getWeightOfVotesToBlessRoot(makeTaggedRoot(1)); - vm.startPrank(cfg.voters[0].blessVoteAddr); - vm.expectRevert(RMN.VoteToBlessNoop.selector); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - assertEq(votesToBlessBefore, getWeightOfVotesToBlessRoot(makeTaggedRoot(1))); - } - - function test_Curse_Revert() public { - RMN.Config memory cfg = rmnConstructorArgs(); - - for (uint256 i = 0; i < cfg.voters.length; i++) { - vm.startPrank(cfg.voters[i].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(i), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } - - vm.startPrank(cfg.voters[0].blessVoteAddr); - vm.expectRevert(RMN.VoteToBlessForbiddenDuringActiveGlobalCurse.selector); - s_rmn.voteToBless(makeTaggedRootSingleton(12903)); - } - - function test_UnauthorizedVoter_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(RMN.UnauthorizedVoter.selector, STRANGER)); - s_rmn.voteToBless(makeTaggedRootSingleton(12321)); - } -} - -contract RMN_ownerUnbless is RMNSetup { - function test_Unbless_Success() public { - RMN.Config memory cfg = rmnConstructorArgs(); - for (uint256 i = 0; i < cfg.voters.length; ++i) { - vm.startPrank(cfg.voters[i].blessVoteAddr); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - } - assertTrue(s_rmn.isBlessed(makeTaggedRoot(1))); - - vm.startPrank(OWNER); - s_rmn.ownerResetBlessVotes(makeTaggedRootSingleton(1)); - assertFalse(s_rmn.isBlessed(makeTaggedRoot(1))); - } -} - -contract RMN_unvoteToCurse is RMNSetup { - uint256 internal s_curser; - bytes28 internal s_cursesHash; - - function setUp() public override { - RMNSetup.setUp(); - RMN.Config memory cfg = rmnConstructorArgs(); - - s_curser = 0; - vm.startPrank(cfg.voters[s_curser].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - bytes28 expectedCursesHash = makeCursesHash(makeCurseId(1)); - assertFalse(s_rmn.isCursed()); - (address[] memory cursers, bytes28[] memory cursesHashes, uint16 weight, bool cursed) = s_rmn.getCurseProgress(0); - assertEq(1, cursers.length); - assertEq(cfg.voters[s_curser].curseVoteAddr, cursers[0]); - assertEq(cfg.voters[s_curser].curseWeight, weight); - assertEq(1, cursesHashes.length); - assertEq(expectedCursesHash, cursesHashes[0]); - assertFalse(cursed); - - s_cursesHash = expectedCursesHash; - } - - function test_UnauthorizedVoter() public { - RMN.Config memory cfg = rmnConstructorArgs(); - // Someone else cannot unvote to curse on the curser's behalf. - address[] memory unauthorized = new address[](3); - unauthorized[0] = cfg.voters[s_curser].blessVoteAddr; - unauthorized[1] = cfg.voters[s_curser ^ 1].blessVoteAddr; - unauthorized[2] = OWNER; - - for (uint256 i = 0; i < unauthorized.length; ++i) { - bytes memory expectedRevert = abi.encodeWithSelector(RMN.UnauthorizedVoter.selector, unauthorized[i]); - vm.startPrank(unauthorized[i]); - { - // should fail when using the correct curses hash - RMN.UnvoteToCurseRequest[] memory reqs = new RMN.UnvoteToCurseRequest[](1); - reqs[0] = RMN.UnvoteToCurseRequest({subject: 0, cursesHash: s_cursesHash}); - vm.expectRevert(expectedRevert); - s_rmn.unvoteToCurse(reqs); - } - { - // should fail when using garbage curses hash - RMN.UnvoteToCurseRequest[] memory reqs = new RMN.UnvoteToCurseRequest[](1); - reqs[0] = RMN.UnvoteToCurseRequest({subject: 0, cursesHash: GARBAGE_CURSES_HASH}); - vm.expectRevert(expectedRevert); - s_rmn.unvoteToCurse(reqs); - } - } - } - - function test_InvalidCursesHash() public { - RMN.Config memory cfg = rmnConstructorArgs(); - vm.startPrank(cfg.voters[s_curser].curseVoteAddr); - RMN.UnvoteToCurseRequest[] memory reqs = new RMN.UnvoteToCurseRequest[](1); - reqs[0] = RMN.UnvoteToCurseRequest({subject: 0, cursesHash: GARBAGE_CURSES_HASH}); - vm.expectRevert(RMN.UnvoteToCurseNoop.selector); - s_rmn.unvoteToCurse(reqs); - } - - function test_ValidCursesHash() public { - RMN.Config memory cfg = rmnConstructorArgs(); - vm.startPrank(cfg.voters[s_curser].curseVoteAddr); - RMN.UnvoteToCurseRequest[] memory reqs = new RMN.UnvoteToCurseRequest[](1); - reqs[0] = RMN.UnvoteToCurseRequest({subject: 0, cursesHash: s_cursesHash}); - s_rmn.unvoteToCurse(reqs); // succeeds - } - - function test_OwnerSucceeds() public { - RMN.Config memory cfg = rmnConstructorArgs(); - vm.startPrank(OWNER); - RMN.OwnerUnvoteToCurseRequest[] memory reqs = new RMN.OwnerUnvoteToCurseRequest[](1); - reqs[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: cfg.voters[s_curser].curseVoteAddr, - unit: RMN.UnvoteToCurseRequest({subject: 0, cursesHash: s_cursesHash}), - forceUnvote: false - }); - s_rmn.ownerUnvoteToCurse(reqs); - } - - function test_OwnerSkips() public { - RMN.Config memory cfg = rmnConstructorArgs(); - vm.startPrank(OWNER); - RMN.OwnerUnvoteToCurseRequest[] memory reqs = new RMN.OwnerUnvoteToCurseRequest[](1); - reqs[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: cfg.voters[s_curser].curseVoteAddr, - unit: RMN.UnvoteToCurseRequest({subject: 0, cursesHash: GARBAGE_CURSES_HASH}), - forceUnvote: false - }); - - vm.expectEmit(); - emit RMN.SkippedUnvoteToCurse(cfg.voters[s_curser].curseVoteAddr, 0, s_cursesHash, GARBAGE_CURSES_HASH); - vm.expectRevert(RMN.UnvoteToCurseNoop.selector); - s_rmn.ownerUnvoteToCurse(reqs); - } - - function test_VotersCantLiftCurseButOwnerCan() public { - vm.stopPrank(); - RMN.Config memory cfg = rmnConstructorArgs(); - // s_curser has voted to curse during setUp - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(accWeight, cfg.voters[s_curser].curseWeight); - assertFalse(cursed); - assertEq(voters.length, 1); - assertEq(cursesHashes.length, 1); - assertEq(voters[0], cfg.voters[s_curser].curseVoteAddr); - assertEq(cursesHashes[0], makeCursesHash(makeCurseId(1))); - } - // everyone else votes now, same curse id, same subject - { - for (uint256 i = 0; i < cfg.voters.length; ++i) { - if (i == s_curser) continue; // already voted to curse - vm.prank(cfg.voters[i].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - } - // subject must be cursed now - { - assertTrue(s_rmn.isCursed(0)); - } - // curse progress should be as full as it can get - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - uint256 allWeights; - for (uint256 i = 0; i < cfg.voters.length; i++) { - allWeights += cfg.voters[i].curseWeight; - } - assertEq(accWeight, allWeights); - assertTrue(cursed); - assertEq(voters.length, cfg.voters.length); - assertEq(cursesHashes.length, cfg.voters.length); - for (uint256 i = 0; i < cfg.voters.length; ++i) { - assertEq(voters[i], cfg.voters[i].curseVoteAddr); - assertEq(cursesHashes[i], makeCursesHash(makeCurseId(1))); - } - } - // everyone unvotes to curse, successfully - { - for (uint256 i = 0; i < cfg.voters.length; ++i) { - vm.prank(cfg.voters[i].curseVoteAddr); - RMN.UnvoteToCurseRequest[] memory reqs = new RMN.UnvoteToCurseRequest[](1); - reqs[0] = RMN.UnvoteToCurseRequest({subject: 0, cursesHash: makeCursesHash(makeCurseId(1))}); - s_rmn.unvoteToCurse(reqs); - } - } - // curse should still be in place as only the owner can lift it - { - assertTrue(s_rmn.isCursed(0)); - } - // curse progress should be empty, expect for the cursed flag - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(accWeight, 0); - assertTrue(cursed); - assertEq(voters.length, 0); - assertEq(cursesHashes.length, 0); - } - // owner lifts curse - { - RMN.OwnerUnvoteToCurseRequest[] memory ownerReq = new RMN.OwnerUnvoteToCurseRequest[](1); - ownerReq[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: LIFT_CURSE_VOTE_ADDR, - unit: RMN.UnvoteToCurseRequest({subject: 0, cursesHash: 0}), - forceUnvote: false - }); - vm.prank(OWNER); - s_rmn.ownerUnvoteToCurse(ownerReq); - } - // curse should now be lifted - { - assertFalse(s_rmn.isCursed(0)); - } - } -} - -contract RMN_voteToCurse_2 is RMNSetup { - function initialConfig() internal pure returns (RMN.Config memory) { - RMN.Config memory cfg = RMN.Config({voters: new RMN.Voter[](3), blessWeightThreshold: 1, curseWeightThreshold: 3}); - cfg.voters[0] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_1, curseVoteAddr: CURSE_VOTER_1, blessWeight: 1, curseWeight: 1}); - cfg.voters[1] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_2, curseVoteAddr: CURSE_VOTER_2, blessWeight: 1, curseWeight: 1}); - cfg.voters[2] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_3, curseVoteAddr: CURSE_VOTER_3, blessWeight: 1, curseWeight: 1}); - return cfg; - } - - function setUp() public override { - vm.prank(OWNER); - s_rmn = new RMN(initialConfig()); - } - - function test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() public { - // vote to curse the subject from an insufficient number of voters, one voter - { - RMN.Config memory cfg = initialConfig(); - vm.prank(cfg.voters[0].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - // vote must be in place - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, 1); - assertEq(cursesHashes.length, 1); - assertEq(accWeight, 1); - assertFalse(cursed); - } - // change config to include only the first voter, i.e., initialConfig().voters[0] - { - RMN.Config memory cfg = initialConfig(); - RMN.Voter[] memory voters = cfg.voters; - assembly { - mstore(voters, 1) - } - cfg.curseWeightThreshold = 1; - vm.prank(OWNER); - s_rmn.setConfig(cfg); - } - // vote must be dropped - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, 0); - assertEq(cursesHashes.length, 0); - assertEq(accWeight, 0); - assertFalse(cursed); - } - // cause an owner curse now - { - vm.prank(OWNER); - s_rmn.ownerCurse(makeCurseId(1), makeSubjects(0)); - } - // only the owner curse must be visible - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, 1); - assertEq(voters[0], OWNER_CURSE_VOTE_ADDR); - assertEq(cursesHashes.length, 1); - assertEq(cursesHashes[0], makeCursesHash(makeCurseId(1))); - assertEq(accWeight, 0); - assertTrue(cursed); - } - } - - function test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() public { - uint256 numVotersInitially = initialConfig().voters.length; - // curse the subject with votes from all voters - { - RMN.Config memory cfg = initialConfig(); - for (uint256 i = 0; i < cfg.voters.length; ++i) { - vm.prank(cfg.voters[i].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - } - // subject is now cursed - { - assertTrue(s_rmn.isCursed(0)); - } - // throw in an owner curse - { - vm.prank(OWNER); - s_rmn.ownerCurse(makeCurseId(1), makeSubjects(0)); - } - - uint256 snapshot = vm.snapshot(); - - for (uint256 keepVoters = 1; keepVoters <= numVotersInitially; ++keepVoters) { - vm.revertTo(snapshot); - - // change config to include only the first #keepVoters voters, i.e., initialConfig().voters[0..keepVoters] - { - RMN.Config memory cfg = initialConfig(); - RMN.Voter[] memory voters = cfg.voters; - assembly { - mstore(voters, keepVoters) - } - cfg.curseWeightThreshold = uint16(keepVoters); - vm.prank(OWNER); - s_rmn.setConfig(cfg); - } - // subject is still cursed - { - assertTrue(s_rmn.isCursed(0)); - } - // all votes from the first keepVoters & owner must be present - { - (address[] memory voters, bytes28[] memory cursesHashes, uint16 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, keepVoters + 1 /* owner */ ); - assertEq(cursesHashes.length, keepVoters + 1 /* owner */ ); - assertEq(accWeight, keepVoters /* 1 per voter */ ); - assertTrue(cursed); - for (uint256 i = 0; i < keepVoters; ++i) { - assertEq(voters[i], initialConfig().voters[i].curseVoteAddr); - assertEq(cursesHashes[i], makeCursesHash(makeCurseId(1))); - } - assertEq(voters[voters.length - 1], OWNER_CURSE_VOTE_ADDR); - assertEq(cursesHashes[cursesHashes.length - 1], makeCursesHash(makeCurseId(1))); - } - // the owner unvoting for all is not enough to lift the curse, because remember that the owner has an active vote - // also - { - for (uint256 i = 0; i < keepVoters; ++i) { - RMN.OwnerUnvoteToCurseRequest[] memory ownerReq = new RMN.OwnerUnvoteToCurseRequest[](1); - ownerReq[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: initialConfig().voters[i].curseVoteAddr, - unit: RMN.UnvoteToCurseRequest({subject: 0, cursesHash: makeCursesHash(makeCurseId(1))}), - forceUnvote: false - }); - vm.prank(OWNER); - s_rmn.ownerUnvoteToCurse(ownerReq); - - assertTrue(s_rmn.isCursed(0)); - } - } - // after owner unvotes for themselves, finally, the curse will be lifted - { - RMN.OwnerUnvoteToCurseRequest[] memory ownerReq = new RMN.OwnerUnvoteToCurseRequest[](1); - ownerReq[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: OWNER_CURSE_VOTE_ADDR, - unit: RMN.UnvoteToCurseRequest({subject: 0, cursesHash: makeCursesHash(makeCurseId(1))}), - forceUnvote: false - }); - vm.prank(OWNER); - s_rmn.ownerUnvoteToCurse(ownerReq); - - assertFalse(s_rmn.isCursed(0)); - } - } - } -} - -contract RMN_voteToCurse is RMNSetup { - function _getFirstCurseVoterAndWeight() internal pure returns (address, uint8) { - RMN.Config memory cfg = rmnConstructorArgs(); - return (cfg.voters[0].curseVoteAddr, cfg.voters[0].curseWeight); - } - - // Success - - function test_CurseOnlyWhenThresholdReached_Success() public { - uint256 numSubjects = 3; - uint256 maxNumRevotes = 2; - - RMN.Config memory cfg = rmnConstructorArgs(); - bytes16[] memory subjects = new bytes16[](numSubjects); - for (uint256 i = 0; i < numSubjects; ++i) { - subjects[i] = bytes16(uint128(i)); - } - for (uint256 numRevotes = 1; numRevotes <= maxNumRevotes; ++numRevotes) { - // all voters but the last vote, but can't surpass the curse weight threshold - for (uint256 i = 0; i < cfg.voters.length - 1; ++i) { - vm.prank(cfg.voters[i].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(numRevotes), subjects); - } - // no curse is yet active, last voter also needs to vote for any curse to be active - { - // ensure every subject is not cursed - for (uint256 i = 0; i < numSubjects; ++i) { - assertFalse(s_rmn.isCursed(subjects[i])); - } - // ensure every vote has been recorded - assertEq( - s_rmn.getRecordedCurseRelatedOpsCount(), - 1 /* setConfig */ + (cfg.voters.length - 1) * numRevotes * numSubjects - ); - } - } - - // last voter now votes - vm.prank(cfg.voters[cfg.voters.length - 1].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(0), subjects); - // curses should be now active - { - // ensure every subject is now cursed - for (uint256 i = 0; i < numSubjects; ++i) { - assertTrue(s_rmn.isCursed(subjects[i])); - } - // ensure every vote has been recorded - assertEq( - s_rmn.getRecordedCurseRelatedOpsCount(), - 1 /* setConfig */ + ((cfg.voters.length - 1) * maxNumRevotes + 1) * numSubjects - ); - } - } - - function test_VoteToCurse_NoCurse_Success() public { - (address voter, uint8 weight) = _getFirstCurseVoterAndWeight(); - vm.startPrank(voter); - vm.expectEmit(); - emit RMN.VotedToCurse( - 1, // configVersion - voter, - GLOBAL_CURSE_SUBJECT, - makeCurseId(123), - weight, - 1234567890, // blockTimestamp - makeCursesHash(makeCurseId(123)), // cursesHash - weight - ); - - s_rmn.voteToCurse(makeCurseId(123), makeSubjects(GLOBAL_CURSE_SUBJECT)); - - (address[] memory voters,, uint16 votes, bool cursed) = s_rmn.getCurseProgress(GLOBAL_CURSE_SUBJECT); - assertEq(1, voters.length); - assertEq(voter, voters[0]); - assertEq(weight, votes); - assertFalse(cursed); - } - - function test_VoteToCurse_YesCurse_Success() public { - RMN.Config memory cfg = rmnConstructorArgs(); - for (uint256 i = 0; i < cfg.voters.length - 1; ++i) { - vm.startPrank(cfg.voters[i].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - - vm.expectEmit(); - emit RMN.Cursed(1, 0, uint64(block.timestamp)); - - vm.startPrank(cfg.voters[cfg.voters.length - 1].curseVoteAddr); - vm.resumeGasMetering(); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - - function test_EvenIfAlreadyCursed_Success() public { - RMN.Config memory cfg = rmnConstructorArgs(); - uint16 weightSum = 0; - for (uint256 i = 0; i < cfg.voters.length; ++i) { - vm.startPrank(cfg.voters[i].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(i), makeSubjects(0)); - weightSum += cfg.voters[i].curseWeight; - } - - // Not part of the assertion of this test but good to have as a sanity - // check. We want a curse to be active in order for the ultimate assertion - // to make sense. - assert(s_rmn.isCursed(0)); - - vm.expectEmit(); - emit RMN.VotedToCurse( - 1, // configVersion - cfg.voters[cfg.voters.length - 1].curseVoteAddr, - 0, // subject - makeCurseId(cfg.voters.length + 1), // this curse id - cfg.voters[cfg.voters.length - 1].curseWeight, - uint64(block.timestamp), // blockTimestamp - makeCursesHash(makeCurseId(cfg.voters.length - 1), makeCurseId(cfg.voters.length + 1)), // cursesHash - weightSum // accumulatedWeight - ); - // Asserts that this call to vote with a new curse id goes through with no - // reverts even when the RMN contract is cursed. - s_rmn.voteToCurse(makeCurseId(cfg.voters.length + 1), makeSubjects(0)); - } - - function test_OwnerCanCurseAndUncurse() public { - vm.startPrank(OWNER); - bytes28 expectedCursesHash = makeCursesHash(makeCurseId(0)); - vm.expectEmit(); - emit RMN.VotedToCurse( - 1, // configVersion - OWNER_CURSE_VOTE_ADDR, // owner - 0, // subject - makeCurseId(0), // curse id - 0, // weight - uint64(block.timestamp), // blockTimestamp - expectedCursesHash, // cursesHash - 0 // accumulatedWeight - ); - vm.expectEmit(); - emit RMN.Cursed( - 1, // configVersion - 0, // subject - uint64(block.timestamp) // blockTimestamp - ); - s_rmn.ownerCurse(makeCurseId(0), makeSubjects(0)); - - { - (address[] memory voters, bytes28[] memory cursesHashes, uint24 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, 1); - assertEq(voters[0], OWNER_CURSE_VOTE_ADDR /* owner */ ); - assertEq(cursesHashes.length, 1); - assertEq(cursesHashes[0], expectedCursesHash); - assertEq(accWeight, 0); - assertTrue(cursed); - } - - // ownerCurse again, should cause a vote to appear and a change in curses hash - expectedCursesHash = makeCursesHash(makeCurseId(0), makeCurseId(1)); - vm.expectEmit(); - emit RMN.VotedToCurse( - 1, // configVersion - OWNER_CURSE_VOTE_ADDR, // owner - 0, // subject - makeCurseId(1), // curse id - 0, // weight - uint64(block.timestamp), // blockTimestamp - expectedCursesHash, // cursesHash - 0 // accumulatedWeight - ); - s_rmn.ownerCurse(makeCurseId(1), makeSubjects(0)); - - { - (address[] memory voters, bytes28[] memory cursesHashes, uint24 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, 1); - assertEq(voters[0], OWNER_CURSE_VOTE_ADDR /* owner */ ); - assertEq(cursesHashes.length, 1); - assertEq(cursesHashes[0], expectedCursesHash); - assertEq(accWeight, 0); - assertTrue(cursed); - } - - RMN.OwnerUnvoteToCurseRequest[] memory unvoteReqs = new RMN.OwnerUnvoteToCurseRequest[](1); - unvoteReqs[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: OWNER_CURSE_VOTE_ADDR, - unit: RMN.UnvoteToCurseRequest({subject: 0, cursesHash: 0}), - forceUnvote: true // TODO: test with forceUnvote false also - }); - vm.expectEmit(); - emit RMN.CurseLifted(0); - s_rmn.ownerUnvoteToCurse(unvoteReqs); - { - (address[] memory voters, bytes28[] memory cursesHashes, uint24 accWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(voters.length, 0); - assertEq(cursesHashes.length, 0); - assertEq(accWeight, 0); - assertFalse(cursed); - } - } - - // Reverts - - function test_UnauthorizedVoter_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(RMN.UnauthorizedVoter.selector, STRANGER)); - s_rmn.voteToCurse(makeCurseId(12312), makeSubjects(0)); - } - - function test_ReusedCurseId_Revert() public { - (address voter,) = _getFirstCurseVoterAndWeight(); - vm.startPrank(voter); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - - vm.expectRevert(abi.encodeWithSelector(RMN.ReusedCurseId.selector, voter, makeCurseId(1))); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - - function test_RepeatedSubject_Revert() public { - (address voter,) = _getFirstCurseVoterAndWeight(); - vm.prank(voter); - - bytes16 subject = bytes16(uint128(1)); - - vm.expectRevert(RMN.SubjectsMustBeStrictlyIncreasing.selector); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(subject, subject)); - } - - function test_EmptySubjects_Revert() public { - (address voter,) = _getFirstCurseVoterAndWeight(); - vm.prank(voter); - - vm.expectRevert(RMN.VoteToCurseNoop.selector); - s_rmn.voteToCurse(makeCurseId(1), new bytes16[](0)); - } -} - -contract RMN_ownerUnvoteToCurse is RMNSetup { - // These cursers are going to curse in setUp curseCount times. - function getCursersAndCurseCounts() internal pure returns (address[] memory cursers, uint32[] memory curseCounts) { - // NOTE: Change this when changing setUp or rmnConstructorArgs. - // This is a bit ugly and error prone but if we read from storage we would - // not get an accurate gas reading for ownerUnvoteToCurse when we need it. - cursers = new address[](4); - cursers[0] = CURSE_VOTER_1; - cursers[1] = CURSE_VOTER_2; - cursers[2] = CURSE_VOTER_3; - cursers[3] = CURSE_VOTER_4; - curseCounts = new uint32[](cursers.length); - for (uint256 i = 0; i < cursers.length; ++i) { - curseCounts[i] = 1; - } - } - - function setUp() public virtual override { - RMNSetup.setUp(); - (address[] memory cursers, uint32[] memory curseCounts) = getCursersAndCurseCounts(); - for (uint256 i = 0; i < cursers.length; ++i) { - vm.startPrank(cursers[i]); - for (uint256 j = 0; j < curseCounts[i]; ++j) { - s_rmn.voteToCurse(makeCurseId(j), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } - } - } - - function ownerUnvoteToCurse() internal { - s_rmn.ownerUnvoteToCurse(makeOwnerUnvoteToCurseRequests()); - } - - function makeOwnerUnvoteToCurseRequests() internal pure returns (RMN.OwnerUnvoteToCurseRequest[] memory) { - (address[] memory cursers,) = getCursersAndCurseCounts(); - RMN.OwnerUnvoteToCurseRequest[] memory reqs = new RMN.OwnerUnvoteToCurseRequest[](cursers.length); - for (uint256 i = 0; i < cursers.length; ++i) { - reqs[i] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: cursers[i], - unit: RMN.UnvoteToCurseRequest({subject: GLOBAL_CURSE_SUBJECT, cursesHash: bytes28(0)}), - forceUnvote: true - }); - } - return reqs; - } - - // Success - - function test_OwnerUnvoteToCurseSuccess_gas() public { - vm.pauseGasMetering(); - vm.startPrank(OWNER); - - vm.expectEmit(); - emit RMN.CurseLifted(GLOBAL_CURSE_SUBJECT); - - vm.resumeGasMetering(); - ownerUnvoteToCurse(); - vm.pauseGasMetering(); - - assertFalse(s_rmn.isCursed()); - (address[] memory voters, bytes28[] memory cursesHashes, uint256 weight, bool cursed) = - s_rmn.getCurseProgress(GLOBAL_CURSE_SUBJECT); - assertEq(voters.length, 0); - assertEq(cursesHashes.length, 0); - assertEq(weight, 0); - assertFalse(cursed); - vm.resumeGasMetering(); - } - - function test_IsIdempotent() public { - vm.startPrank(OWNER); - ownerUnvoteToCurse(); - vm.expectRevert(RMN.UnvoteToCurseNoop.selector); - ownerUnvoteToCurse(); - - assertFalse(s_rmn.isCursed()); - (address[] memory voters, bytes28[] memory cursesHashes, uint256 weight, bool cursed) = - s_rmn.getCurseProgress(GLOBAL_CURSE_SUBJECT); - assertEq(voters.length, 0); - assertEq(cursesHashes.length, 0); - assertEq(weight, 0); - assertFalse(cursed); - } - - function test_CanBlessAndCurseAfterGlobalCurseIsLifted() public { - // Contract is already cursed due to setUp. - - // Owner unvotes to curse. - vm.startPrank(OWNER); - vm.expectEmit(); - emit RMN.CurseLifted(GLOBAL_CURSE_SUBJECT); - ownerUnvoteToCurse(); - - // Contract is now uncursed. - assertFalse(s_rmn.isCursed()); - - // Vote to bless should go through. - vm.startPrank(BLESS_VOTER_1); - s_rmn.voteToBless(makeTaggedRootSingleton(2387489729)); - - // Vote to curse should go through. - vm.startPrank(CURSE_VOTER_1); - s_rmn.voteToCurse(makeCurseId(73894728973), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } - - // Reverts - - function test_NonOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - ownerUnvoteToCurse(); - } - - function test_UnknownVoter_Revert() public { - vm.stopPrank(); - RMN.OwnerUnvoteToCurseRequest[] memory reqs = new RMN.OwnerUnvoteToCurseRequest[](1); - reqs[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: STRANGER, - unit: RMN.UnvoteToCurseRequest({subject: GLOBAL_CURSE_SUBJECT, cursesHash: bytes28(0)}), - forceUnvote: true - }); - - vm.prank(OWNER); - vm.expectEmit(); - emit RMN.SkippedUnvoteToCurse(STRANGER, GLOBAL_CURSE_SUBJECT, bytes28(0), bytes28(0)); - vm.expectRevert(RMN.UnvoteToCurseNoop.selector); - s_rmn.ownerUnvoteToCurse(reqs); - - // no effect on cursedness - assertTrue(s_rmn.isCursed(GLOBAL_CURSE_SUBJECT)); - } -} - -contract RMN_setConfig is ConfigCompare, RMNSetup { - /// @notice Test-specific function to use only in setConfig tests - function getDifferentConfigArgs() private pure returns (RMN.Config memory) { - RMN.Voter[] memory voters = new RMN.Voter[](2); - voters[0] = RMN.Voter({ - blessVoteAddr: BLESS_VOTER_1, - curseVoteAddr: CURSE_VOTER_1, - blessWeight: WEIGHT_1, - curseWeight: WEIGHT_1 - }); - voters[1] = RMN.Voter({ - blessVoteAddr: BLESS_VOTER_2, - curseVoteAddr: CURSE_VOTER_2, - blessWeight: WEIGHT_10, - curseWeight: WEIGHT_10 - }); - return RMN.Config({ - voters: voters, - blessWeightThreshold: WEIGHT_1 + WEIGHT_10, - curseWeightThreshold: WEIGHT_1 + WEIGHT_10 - }); - } - - function setUp() public virtual override { - RMNSetup.setUp(); - RMN.Config memory cfg = rmnConstructorArgs(); - - // Setup some partial state - vm.startPrank(cfg.voters[0].blessVoteAddr); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - vm.startPrank(cfg.voters[1].blessVoteAddr); - s_rmn.voteToBless(makeTaggedRootSingleton(1)); - vm.startPrank(cfg.voters[1].curseVoteAddr); - s_rmn.voteToCurse(makeCurseId(1), makeSubjects(0)); - } - - // Success - - event ConfigSet(uint32 indexed configVersion, RMN.Config config); - - function test_VoteToBlessByEjectedVoter_Revert() public { - // Previous config included BLESS_VOTER_4. Change to new config that doesn't. - RMN.Config memory cfg = getDifferentConfigArgs(); - vm.startPrank(OWNER); - s_rmn.setConfig(cfg); - - // BLESS_VOTER_4 is not part of cfg anymore, vote to bless should revert. - vm.startPrank(BLESS_VOTER_4); - vm.expectRevert(abi.encodeWithSelector(RMN.UnauthorizedVoter.selector, BLESS_VOTER_4)); - s_rmn.voteToBless(makeTaggedRootSingleton(2)); - } - - function test_SetConfigSuccess_gas() public { - vm.pauseGasMetering(); - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(OWNER); - vm.expectEmit(); - emit ConfigSet(2, cfg); - - (uint32 configVersionBefore,,) = s_rmn.getConfigDetails(); - vm.resumeGasMetering(); - s_rmn.setConfig(cfg); - vm.pauseGasMetering(); - // Assert VersionedConfig has changed correctly - (uint32 configVersionAfter,, RMN.Config memory configAfter) = s_rmn.getConfigDetails(); - assertEq(configVersionBefore + 1, configVersionAfter); - assertConfigEq(configAfter, cfg); - - // Assert that curse votes have been cleared - - (address[] memory curseVoters, bytes28[] memory cursesHashes, uint256 curseWeight, bool cursed) = - s_rmn.getCurseProgress(0); - assertEq(0, curseVoters.length); - assertEq(0, cursesHashes.length); - assertEq(0, curseWeight); - assertFalse(cursed); - - // Assert that good votes have been cleared - uint256 votesToBlessRoot = getWeightOfVotesToBlessRoot(makeTaggedRoot(1)); - assertEq(ZERO, votesToBlessRoot); - assertFalse(hasVotedToBlessRoot(cfg.voters[0].blessVoteAddr, makeTaggedRoot(1))); - assertFalse(hasVotedToBlessRoot(cfg.voters[1].blessVoteAddr, makeTaggedRoot(1))); - vm.resumeGasMetering(); - } - - // Reverts - - function test_NonOwner_Revert() public { - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_rmn.setConfig(cfg); - } - - function test_VotersLengthIsZero_Revert() public { - vm.startPrank(OWNER); - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig(RMN.Config({voters: new RMN.Voter[](0), blessWeightThreshold: 1, curseWeightThreshold: 1})); - } - - function test_EitherThresholdIsZero_Revert() public { - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(OWNER); - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig( - RMN.Config({voters: cfg.voters, blessWeightThreshold: ZERO, curseWeightThreshold: cfg.curseWeightThreshold}) - ); - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig( - RMN.Config({voters: cfg.voters, blessWeightThreshold: cfg.blessWeightThreshold, curseWeightThreshold: ZERO}) - ); - } - - function test_BlessVoterIsZeroAddress_Revert() public { - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(OWNER); - cfg.voters[0].blessVoteAddr = ZERO_ADDRESS; - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig(cfg); - } - - function test_WeightIsZeroAddress_Revert() public { - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(OWNER); - cfg.voters[0].blessWeight = ZERO; - cfg.voters[0].curseWeight = ZERO; - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig(cfg); - } - - function test_TotalWeightsSmallerThanEachThreshold_Revert() public { - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(OWNER); - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig( - RMN.Config({voters: cfg.voters, blessWeightThreshold: WEIGHT_40, curseWeightThreshold: cfg.curseWeightThreshold}) - ); - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig( - RMN.Config({voters: cfg.voters, blessWeightThreshold: cfg.blessWeightThreshold, curseWeightThreshold: WEIGHT_40}) - ); - } - - function test_RepeatedAddress_Revert() public { - RMN.Config memory cfg = getDifferentConfigArgs(); - - vm.startPrank(OWNER); - cfg.voters[0].blessVoteAddr = cfg.voters[1].curseVoteAddr; - vm.expectRevert(RMN.InvalidConfig.selector); - s_rmn.setConfig(cfg); - } -} - -contract RMN_permaBlessing is RMNSetup { - function addresses() private pure returns (address[] memory) { - return new address[](0); - } - - function addresses(address a) private pure returns (address[] memory) { - address[] memory arr = new address[](1); - arr[0] = a; - return arr; - } - - function addresses(address a, address b) private pure returns (address[] memory) { - address[] memory arr = new address[](2); - arr[0] = a; - arr[1] = b; - return arr; - } - - function test_PermaBlessing() public { - bytes32 SOME_ROOT = bytes32(~uint256(0)); - address COMMIT_STORE_1 = makeAddr("COMMIT_STORE_1"); - address COMMIT_STORE_2 = makeAddr("COMMIT_STORE_2"); - IRMN.TaggedRoot memory taggedRootCommitStore1 = IRMN.TaggedRoot({root: SOME_ROOT, commitStore: COMMIT_STORE_1}); - IRMN.TaggedRoot memory taggedRootCommitStore2 = IRMN.TaggedRoot({root: SOME_ROOT, commitStore: COMMIT_STORE_2}); - - assertFalse(s_rmn.isBlessed(taggedRootCommitStore1)); - assertFalse(s_rmn.isBlessed(taggedRootCommitStore2)); - assertEq(s_rmn.getPermaBlessedCommitStores(), addresses()); - - // only owner can mutate permaBlessedCommitStores - vm.prank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_rmn.ownerRemoveThenAddPermaBlessedCommitStores(addresses(), addresses(COMMIT_STORE_1)); - - vm.prank(OWNER); - s_rmn.ownerRemoveThenAddPermaBlessedCommitStores(addresses(), addresses(COMMIT_STORE_1)); - assertTrue(s_rmn.isBlessed(taggedRootCommitStore1)); - assertFalse(s_rmn.isBlessed(taggedRootCommitStore2)); - assertEq(s_rmn.getPermaBlessedCommitStores(), addresses(COMMIT_STORE_1)); - - vm.prank(OWNER); - s_rmn.ownerRemoveThenAddPermaBlessedCommitStores(addresses(COMMIT_STORE_1), addresses(COMMIT_STORE_2)); - assertFalse(s_rmn.isBlessed(taggedRootCommitStore1)); - assertTrue(s_rmn.isBlessed(taggedRootCommitStore2)); - assertEq(s_rmn.getPermaBlessedCommitStores(), addresses(COMMIT_STORE_2)); - - vm.prank(OWNER); - s_rmn.ownerRemoveThenAddPermaBlessedCommitStores(addresses(), addresses(COMMIT_STORE_1)); - assertTrue(s_rmn.isBlessed(taggedRootCommitStore1)); - assertTrue(s_rmn.isBlessed(taggedRootCommitStore2)); - assertEq(s_rmn.getPermaBlessedCommitStores(), addresses(COMMIT_STORE_2, COMMIT_STORE_1)); - - vm.prank(OWNER); - s_rmn.ownerRemoveThenAddPermaBlessedCommitStores(addresses(COMMIT_STORE_1, COMMIT_STORE_2), addresses()); - assertFalse(s_rmn.isBlessed(taggedRootCommitStore1)); - assertFalse(s_rmn.isBlessed(taggedRootCommitStore2)); - assertEq(s_rmn.getPermaBlessedCommitStores(), addresses()); - } -} - -contract RMN_getRecordedCurseRelatedOps is RMNSetup { - function test_OpsPostDeployment() public { - // The constructor call includes a setConfig, so that's the only thing we should expect to find. - assertEq(s_rmn.getRecordedCurseRelatedOpsCount(), 1); - RMN.RecordedCurseRelatedOp[] memory recordedCurseRelatedOps = s_rmn.getRecordedCurseRelatedOps(0, type(uint256).max); - assertEq(recordedCurseRelatedOps.length, 1); - assertEq(uint8(recordedCurseRelatedOps[0].tag), uint8(RMN.RecordedCurseRelatedOpTag.SetConfig)); - } -} diff --git a/contracts/src/v0.8/ccip/test/arm/RMNSetup.t.sol b/contracts/src/v0.8/ccip/test/arm/RMNSetup.t.sol deleted file mode 100644 index 8feacb95f45..00000000000 --- a/contracts/src/v0.8/ccip/test/arm/RMNSetup.t.sol +++ /dev/null @@ -1,144 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {RMN} from "../../RMN.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; - -import {Test} from "forge-std/Test.sol"; - -function makeSubjects(bytes16 a) pure returns (bytes16[] memory) { - bytes16[] memory subjects = new bytes16[](1); - subjects[0] = a; - return subjects; -} - -function makeSubjects(bytes16 a, bytes16 b) pure returns (bytes16[] memory) { - bytes16[] memory subjects = new bytes16[](2); - subjects[0] = a; - subjects[1] = b; - return subjects; -} - -// in order from earliest to latest curse ids -function makeCursesHashFromList(bytes32[] memory curseIds) pure returns (bytes28 cursesHash) { - for (uint256 i = 0; i < curseIds.length; ++i) { - cursesHash = bytes28(keccak256(abi.encode(cursesHash, curseIds[i]))); - } -} - -// hides the ugliness from tests -function makeCursesHash(bytes32 a) pure returns (bytes28) { - bytes32[] memory curseIds = new bytes32[](1); - curseIds[0] = a; - return makeCursesHashFromList(curseIds); -} - -function makeCursesHash(bytes32 a, bytes32 b) pure returns (bytes28) { - bytes32[] memory curseIds = new bytes32[](2); - curseIds[0] = a; - curseIds[1] = b; - return makeCursesHashFromList(curseIds); -} - -contract RMNSetup is Test { - // Addresses - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - address internal constant STRANGER = address(999999); - address internal constant ZERO_ADDRESS = address(0); - address internal constant BLESS_VOTER_1 = address(1); - address internal constant CURSE_VOTER_1 = address(10); - address internal constant BLESS_VOTER_2 = address(2); - address internal constant CURSE_VOTER_2 = address(12); - address internal constant BLESS_VOTER_3 = address(3); - address internal constant CURSE_VOTER_3 = address(13); - address internal constant BLESS_VOTER_4 = address(4); - address internal constant CURSE_VOTER_4 = address(14); - - // Arm - function rmnConstructorArgs() internal pure returns (RMN.Config memory) { - RMN.Voter[] memory voters = new RMN.Voter[](4); - voters[0] = RMN.Voter({ - blessVoteAddr: BLESS_VOTER_1, - curseVoteAddr: CURSE_VOTER_1, - blessWeight: WEIGHT_1, - curseWeight: WEIGHT_1 - }); - voters[1] = RMN.Voter({ - blessVoteAddr: BLESS_VOTER_2, - curseVoteAddr: CURSE_VOTER_2, - blessWeight: WEIGHT_10, - curseWeight: WEIGHT_10 - }); - voters[2] = RMN.Voter({ - blessVoteAddr: BLESS_VOTER_3, - curseVoteAddr: CURSE_VOTER_3, - blessWeight: WEIGHT_20, - curseWeight: WEIGHT_20 - }); - voters[3] = RMN.Voter({ - blessVoteAddr: BLESS_VOTER_4, - curseVoteAddr: CURSE_VOTER_4, - blessWeight: WEIGHT_40, - curseWeight: WEIGHT_40 - }); - return RMN.Config({ - voters: voters, - blessWeightThreshold: WEIGHT_10 + WEIGHT_20 + WEIGHT_40, - curseWeightThreshold: WEIGHT_1 + WEIGHT_10 + WEIGHT_20 + WEIGHT_40 - }); - } - - uint8 internal constant ZERO = 0; - uint8 internal constant WEIGHT_1 = 1; - uint8 internal constant WEIGHT_10 = 10; - uint8 internal constant WEIGHT_20 = 20; - uint8 internal constant WEIGHT_40 = 40; - - function makeTaggedRootsInclusive(uint256 from, uint256 to) internal pure returns (IRMN.TaggedRoot[] memory) { - IRMN.TaggedRoot[] memory votes = new IRMN.TaggedRoot[](to - from + 1); - for (uint256 i = from; i <= to; ++i) { - votes[i - from] = IRMN.TaggedRoot({commitStore: address(1), root: bytes32(uint256(i))}); - } - return votes; - } - - function makeTaggedRootSingleton(uint256 index) internal pure returns (IRMN.TaggedRoot[] memory) { - return makeTaggedRootsInclusive(index, index); - } - - function makeTaggedRoot(uint256 index) internal pure returns (IRMN.TaggedRoot memory) { - return makeTaggedRootSingleton(index)[0]; - } - - function makeTaggedRootHash(uint256 index) internal pure returns (bytes32) { - IRMN.TaggedRoot memory taggedRoot = makeTaggedRootSingleton(index)[0]; - return keccak256(abi.encode(taggedRoot.commitStore, taggedRoot.root)); - } - - function makeCurseId(uint256 index) internal pure returns (bytes16) { - return bytes16(uint128(index)); - } - - RMN internal s_rmn; - - function setUp() public virtual { - vm.startPrank(OWNER); - s_rmn = new RMN(rmnConstructorArgs()); - vm.stopPrank(); - } - - function hasVotedToBlessRoot(address voter, IRMN.TaggedRoot memory taggedRoot_) internal view returns (bool) { - (address[] memory voters,,) = s_rmn.getBlessProgress(taggedRoot_); - for (uint256 i = 0; i < voters.length; ++i) { - if (voters[i] == voter) { - return true; - } - } - return false; - } - - function getWeightOfVotesToBlessRoot(IRMN.TaggedRoot memory taggedRoot_) internal view returns (uint16) { - (, uint16 weight,) = s_rmn.getBlessProgress(taggedRoot_); - return weight; - } -} diff --git a/contracts/src/v0.8/ccip/test/arm/RMN_benchmark.t.sol b/contracts/src/v0.8/ccip/test/arm/RMN_benchmark.t.sol deleted file mode 100644 index 8564614a748..00000000000 --- a/contracts/src/v0.8/ccip/test/arm/RMN_benchmark.t.sol +++ /dev/null @@ -1,217 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {GLOBAL_CURSE_SUBJECT, OWNER_CURSE_VOTE_ADDR, RMN} from "../../RMN.sol"; -import {RMNSetup, makeCursesHash, makeSubjects} from "./RMNSetup.t.sol"; - -contract RMN_voteToBless_Benchmark is RMNSetup { - function test_RootSuccess_gas(uint256 n) internal { - vm.prank(BLESS_VOTER_1); - s_rmn.voteToBless(makeTaggedRootsInclusive(1, n)); - } - - function test_1RootSuccess_gas() public { - test_RootSuccess_gas(1); - } - - function test_3RootSuccess_gas() public { - test_RootSuccess_gas(3); - } - - function test_5RootSuccess_gas() public { - test_RootSuccess_gas(5); - } -} - -contract RMN_voteToBless_Blessed_Benchmark is RMN_voteToBless_Benchmark { - function setUp() public virtual override { - RMNSetup.setUp(); - vm.prank(BLESS_VOTER_2); - s_rmn.voteToBless(makeTaggedRootsInclusive(1, 1)); - vm.prank(BLESS_VOTER_3); - s_rmn.voteToBless(makeTaggedRootsInclusive(1, 1)); - } - - function test_1RootSuccessBecameBlessed_gas() public { - vm.prank(BLESS_VOTER_4); - s_rmn.voteToBless(makeTaggedRootsInclusive(1, 1)); - } -} - -abstract contract RMN_voteToCurse_Benchmark is RMNSetup { - struct PreVote { - address voter; - bytes16 subject; - } - - PreVote[] internal s_preVotes; - - function setUp() public virtual override { - // Intentionally does not inherit RMNSetup setUp(), because we set up a simpler config here. - // The only way to ensure that storage slots are cold for the actual functions to be benchmarked is to perform the - // setup in setUp(). - - RMN.Config memory cfg = RMN.Config({voters: new RMN.Voter[](3), blessWeightThreshold: 3, curseWeightThreshold: 3}); - cfg.voters[0] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_1, curseVoteAddr: CURSE_VOTER_1, blessWeight: 1, curseWeight: 1}); - cfg.voters[1] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_2, curseVoteAddr: CURSE_VOTER_2, blessWeight: 1, curseWeight: 1}); - cfg.voters[2] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_3, curseVoteAddr: CURSE_VOTER_3, blessWeight: 1, curseWeight: 1}); - vm.prank(OWNER); - s_rmn = new RMN(cfg); - - for (uint256 i = 0; i < s_preVotes.length; ++i) { - vm.prank(s_preVotes[i].voter); - s_rmn.voteToCurse(makeCurseId(i), makeSubjects(s_preVotes[i].subject)); - } - } -} - -contract RMN_voteToCurse_Benchmark_1 is RMN_voteToCurse_Benchmark { - constructor() { - // some irrelevant subject & voter so that we don't pay for the nonzero->zero SSTORE of - // s_recordedVotesToCurse.length in the benchmark below - s_preVotes.push(PreVote({voter: CURSE_VOTER_3, subject: bytes16(~uint128(0))})); - } - - function test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() public { - vm.prank(CURSE_VOTER_1); - s_rmn.voteToCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } - - function test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() public { - vm.prank(OWNER); - s_rmn.ownerCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } -} - -contract RMN_voteToCurse_Benchmark_2 is RMN_voteToCurse_Benchmark { - constructor() { - s_preVotes.push(PreVote({voter: CURSE_VOTER_1, subject: GLOBAL_CURSE_SUBJECT})); - } - - function test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() public { - vm.prank(CURSE_VOTER_1); - s_rmn.voteToCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } - - function test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() public { - vm.prank(CURSE_VOTER_2); - s_rmn.voteToCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } -} - -contract RMN_voteToCurse_Benchmark_3 is RMN_voteToCurse_Benchmark { - constructor() { - s_preVotes.push(PreVote({voter: CURSE_VOTER_1, subject: GLOBAL_CURSE_SUBJECT})); - s_preVotes.push(PreVote({voter: CURSE_VOTER_2, subject: GLOBAL_CURSE_SUBJECT})); - } - - function test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() public { - vm.prank(CURSE_VOTER_3); - s_rmn.voteToCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } -} - -contract RMN_lazyVoteToCurseUpdate_Benchmark is RMN_voteToCurse_Benchmark { - constructor() { - s_preVotes.push(PreVote({voter: CURSE_VOTER_1, subject: GLOBAL_CURSE_SUBJECT})); - s_preVotes.push(PreVote({voter: CURSE_VOTER_2, subject: GLOBAL_CURSE_SUBJECT})); - s_preVotes.push(PreVote({voter: CURSE_VOTER_3, subject: GLOBAL_CURSE_SUBJECT})); - } - - function setUp() public override { - RMN_voteToCurse_Benchmark.setUp(); // sends the prevotes - // initial config includes voters CURSE_VOTER_1, CURSE_VOTER_2, CURSE_VOTER_3 - // include a new voter in the config - { - (,, RMN.Config memory cfg) = s_rmn.getConfigDetails(); - RMN.Voter[] memory newVoters = new RMN.Voter[](cfg.voters.length + 1); - for (uint256 i = 0; i < cfg.voters.length; ++i) { - newVoters[i] = cfg.voters[i]; - } - newVoters[newVoters.length - 1] = - RMN.Voter({blessVoteAddr: BLESS_VOTER_4, curseVoteAddr: CURSE_VOTER_4, blessWeight: 1, curseWeight: 1}); - cfg.voters = newVoters; - - vm.prank(OWNER); - s_rmn.setConfig(cfg); - } - } - - function test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() public { - // send a vote as the new voter, should cause a lazy update and votes from CURSE_VOTER_1, CURSE_VOTER_2, - // CURSE_VOTER_3 to be retained, which is the worst case for the prior config - vm.prank(CURSE_VOTER_4); - s_rmn.voteToCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } -} - -contract RMN_setConfig_Benchmark is RMNSetup { - uint256 s_numVoters; - - function configWithVoters(uint256 numVoters) internal pure returns (RMN.Config memory) { - RMN.Config memory cfg = - RMN.Config({voters: new RMN.Voter[](numVoters), blessWeightThreshold: 1, curseWeightThreshold: 1}); - for (uint256 i = 1; i <= numVoters; ++i) { - cfg.voters[i - 1] = RMN.Voter({ - blessVoteAddr: address(uint160(2 * i)), - curseVoteAddr: address(uint160(2 * i + 1)), - blessWeight: 1, - curseWeight: 1 - }); - } - return cfg; - } - - function setUp() public virtual override { - vm.prank(OWNER); - s_rmn = new RMN(configWithVoters(s_numVoters)); - } -} - -contract RMN_setConfig_Benchmark_1 is RMN_setConfig_Benchmark { - constructor() { - s_numVoters = 1; - } - - function test_SetConfig_7Voters_gas() public { - vm.prank(OWNER); - s_rmn.setConfig(configWithVoters(7)); - } -} - -contract RMN_setConfig_Benchmark_2 is RMN_setConfig_Benchmark { - constructor() { - s_numVoters = 7; - } - - function test_ResetConfig_7Voters_gas() public { - vm.prank(OWNER); - s_rmn.setConfig(configWithVoters(7)); - } -} - -contract RMN_ownerUnvoteToCurse_Benchmark is RMN_setConfig_Benchmark { - constructor() { - s_numVoters = 7; - } - - function setUp() public override { - RMN_setConfig_Benchmark.setUp(); - vm.prank(OWNER); - s_rmn.ownerCurse(makeCurseId(0xffff), makeSubjects(GLOBAL_CURSE_SUBJECT)); - } - - function test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() public { - RMN.OwnerUnvoteToCurseRequest[] memory reqs = new RMN.OwnerUnvoteToCurseRequest[](1); - reqs[0] = RMN.OwnerUnvoteToCurseRequest({ - curseVoteAddr: OWNER_CURSE_VOTE_ADDR, - unit: RMN.UnvoteToCurseRequest({cursesHash: makeCursesHash(makeCurseId(0xffff)), subject: GLOBAL_CURSE_SUBJECT}), - forceUnvote: false - }); - vm.prank(OWNER); - s_rmn.ownerUnvoteToCurse(reqs); - } -} 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 ad549e6ccc2..8947a27df1d 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol @@ -30,7 +30,9 @@ contract FacadeClient { /// @dev Calls Router to initiate CCIP send. /// The expectation is that s_msg_sequence will always match the sequence in emitted CCIP messages. - function send(uint256 amount) public { + function send( + uint256 amount + ) public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0].token = address(i_sourceToken); tokenAmounts[0].amount = amount; diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol deleted file mode 100644 index 5deeda64063..00000000000 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Client} from "../../../libraries/Client.sol"; -import {Internal} from "../../../libraries/Internal.sol"; -import {EVM2EVMMultiOnRamp} from "../../../onRamp/EVM2EVMMultiOnRamp.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {EVM2EVMMultiOnRampSetup} from "../../onRamp/EVM2EVMMultiOnRampSetup.t.sol"; -import {FacadeClient} from "./FacadeClient.sol"; -import {ReentrantMaliciousTokenPool} from "./ReentrantMaliciousTokenPool.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -import {console} from "forge-std/console.sol"; - -/// @title MultiOnRampTokenPoolReentrancy -/// Attempts to perform a reentrancy exploit on Onramp with a malicious TokenPool -contract MultiOnRampTokenPoolReentrancy is EVM2EVMMultiOnRampSetup { - FacadeClient internal s_facadeClient; - ReentrantMaliciousTokenPool internal s_maliciousTokenPool; - IERC20 internal s_sourceToken; - IERC20 internal s_feeToken; - address internal immutable i_receiver = makeAddr("receiver"); - - function setUp() public virtual override { - EVM2EVMMultiOnRampSetup.setUp(); - - s_sourceToken = IERC20(s_sourceTokens[0]); - s_feeToken = IERC20(s_sourceTokens[0]); - - s_facadeClient = - 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) - ); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), - remoteTokenAddress: abi.encode(s_destTokens[0]), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - s_maliciousTokenPool.applyChainUpdates(chainUpdates); - s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); - - Internal.PoolUpdate[] memory removes = new Internal.PoolUpdate[](1); - removes[0].token = address(s_sourceToken); - removes[0].pool = address(s_sourcePoolByToken[address(s_sourceToken)]); - Internal.PoolUpdate[] memory adds = new Internal.PoolUpdate[](1); - adds[0].token = address(s_sourceToken); - adds[0].pool = address(s_maliciousTokenPool); - - s_tokenAdminRegistry.setPool(address(s_sourceToken), address(s_maliciousTokenPool)); - - s_sourceToken.transfer(address(s_facadeClient), 1e18); - s_feeToken.transfer(address(s_facadeClient), 1e18); - } - - /// @dev This test was used to showcase a reentrancy exploit on OnRamp with malicious TokenPool. - /// How it worked: OnRamp used to construct EVM2Any messages after calling TokenPool's lockOrBurn. - /// This allowed the malicious TokenPool to break message sequencing expectations as follows: - /// Any user -> Facade -> 1st call to ccipSend -> pool’s lockOrBurn —> - /// (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 moving state updates and event construction to before TokenPool calls. - /// This test is kept to verify message sequence expectations are not broken. - function test_OnRampTokenPoolReentrancy_Success() public { - uint256 amount = 1; - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0].token = address(s_sourceToken); - tokenAmounts[0].amount = amount; - - Client.EVM2AnyMessage memory message1 = Client.EVM2AnyMessage({ - receiver: abi.encode(i_receiver), - data: abi.encodePacked(uint256(1)), // message 1 contains data 1 - tokenAmounts: tokenAmounts, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), - feeToken: address(s_feeToken) - }); - - Client.EVM2AnyMessage memory message2 = Client.EVM2AnyMessage({ - receiver: abi.encode(i_receiver), - data: abi.encodePacked(uint256(2)), // message 2 contains data 2 - tokenAmounts: tokenAmounts, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), - feeToken: address(s_feeToken) - }); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message1); - assertGt(expectedFee, 0); - - // Outcome of a successful exploit: - // Message 1 event from OnRamp contains sequence/nonce 2, message 2 contains sequence/nonce 1 - // Internal.EVM2EVMMessage memory msgEvent1 = _messageToEvent(message1, 2, 2, expectedFee, address(s_facadeClient)); - // Internal.EVM2EVMMessage memory msgEvent2 = _messageToEvent(message2, 1, 1, expectedFee, address(s_facadeClient)); - - // vm.expectEmit(); - // emit CCIPSendRequested(msgEvent2); - // vm.expectEmit(); - // emit CCIPSendRequested(msgEvent1); - - // After issue is fixed, sequence now increments as expected - Internal.EVM2AnyRampMessage memory msgEvent1 = _messageToEvent(message1, 1, 1, expectedFee, address(s_facadeClient)); - Internal.EVM2AnyRampMessage memory msgEvent2 = _messageToEvent(message2, 2, 2, expectedFee, address(s_facadeClient)); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent2); - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent1); - - s_facadeClient.send(amount); - } -} 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 8fc71be8573..0c1cc714be9 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 @@ -3,17 +3,17 @@ pragma solidity 0.8.24; import {Client} from "../../../libraries/Client.sol"; import {Internal} from "../../../libraries/Internal.sol"; -import {EVM2EVMOnRamp} from "../../../onRamp/EVM2EVMOnRamp.sol"; +import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {EVM2EVMOnRampSetup} from "../../onRamp/EVM2EVMOnRampSetup.t.sol"; +import {OnRampSetup} from "../../onRamp/OnRampSetup.t.sol"; import {FacadeClient} from "./FacadeClient.sol"; import {ReentrantMaliciousTokenPool} from "./ReentrantMaliciousTokenPool.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -/// @title OnRampTokenPoolReentrancy +/// @title MultiOnRampTokenPoolReentrancy /// Attempts to perform a reentrancy exploit on Onramp with a malicious TokenPool -contract OnRampTokenPoolReentrancy is EVM2EVMOnRampSetup { +contract OnRampTokenPoolReentrancy is OnRampSetup { FacadeClient internal s_facadeClient; ReentrantMaliciousTokenPool internal s_maliciousTokenPool; IERC20 internal s_sourceToken; @@ -21,7 +21,7 @@ contract OnRampTokenPoolReentrancy is EVM2EVMOnRampSetup { address internal immutable i_receiver = makeAddr("receiver"); function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); + OnRampSetup.setUp(); s_sourceToken = IERC20(s_sourceTokens[0]); s_feeToken = IERC20(s_sourceTokens[0]); @@ -39,19 +39,12 @@ contract OnRampTokenPoolReentrancy is EVM2EVMOnRampSetup { remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), remoteTokenAddress: abi.encode(s_destTokens[0]), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_maliciousTokenPool.applyChainUpdates(chainUpdates); s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); - Internal.PoolUpdate[] memory removes = new Internal.PoolUpdate[](1); - removes[0].token = address(s_sourceToken); - removes[0].pool = address(s_sourcePoolByToken[address(s_sourceToken)]); - Internal.PoolUpdate[] memory adds = new Internal.PoolUpdate[](1); - adds[0].token = address(s_sourceToken); - adds[0].pool = address(s_maliciousTokenPool); - s_tokenAdminRegistry.setPool(address(s_sourceToken), address(s_maliciousTokenPool)); s_sourceToken.transfer(address(s_facadeClient), 1e18); @@ -59,13 +52,12 @@ contract OnRampTokenPoolReentrancy is EVM2EVMOnRampSetup { } /// @dev This test was used to showcase a reentrancy exploit on OnRamp with malicious TokenPool. - /// How it worked: OnRamp used to construct EVM2EVM messages after calling TokenPool's lockOrBurn. + /// How it worked: OnRamp used to construct EVM2Any messages after calling TokenPool's lockOrBurn. /// This allowed the malicious TokenPool to break message sequencing expectations as follows: /// Any user -> Facade -> 1st call to ccipSend -> pool’s lockOrBurn —> /// (reenter)-> Facade -> 2nd call to ccipSend - /// In this case, Facade's second call would produce an EVM2EVM msg with a lower sequence number. - /// The issue was fixed by moving state updates and event construction to before TokenPool calls. - /// This test is kept to verify message sequence expectations are not broken. + /// 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 { uint256 amount = 1; @@ -81,36 +73,10 @@ contract OnRampTokenPoolReentrancy is EVM2EVMOnRampSetup { feeToken: address(s_feeToken) }); - Client.EVM2AnyMessage memory message2 = Client.EVM2AnyMessage({ - receiver: abi.encode(i_receiver), - data: abi.encodePacked(uint256(2)), // message 2 contains data 2 - tokenAmounts: tokenAmounts, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), - feeToken: address(s_feeToken) - }); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message1); assertGt(expectedFee, 0); - // Outcome of a successful exploit: - // Message 1 event from OnRamp contains sequence/nonce 2, message 2 contains sequence/nonce 1 - // Internal.EVM2EVMMessage memory msgEvent1 = _messageToEvent(message1, 2, 2, expectedFee, address(s_facadeClient)); - // Internal.EVM2EVMMessage memory msgEvent2 = _messageToEvent(message2, 1, 1, expectedFee, address(s_facadeClient)); - - // vm.expectEmit(); - // emit CCIPSendRequested(msgEvent2); - // vm.expectEmit(); - // emit CCIPSendRequested(msgEvent1); - - // After issue is fixed, sequence now increments as expected - Internal.EVM2EVMMessage memory msgEvent1 = _messageToEvent(message1, 1, 1, expectedFee, address(s_facadeClient)); - Internal.EVM2EVMMessage memory msgEvent2 = _messageToEvent(message2, 2, 2, expectedFee, address(s_facadeClient)); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent2); - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent1); - + vm.expectRevert(OnRamp.ReentrancyGuardReentrantCall.selector); s_facadeClient.send(amount); } } 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 17c13a8148e..f50f233e737 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol @@ -8,7 +8,7 @@ import {FacadeClient} from "./FacadeClient.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract ReentrantMaliciousTokenPool is TokenPool { - address private i_facade; + address private immutable i_facade; bool private s_attacked; @@ -22,11 +22,9 @@ contract ReentrantMaliciousTokenPool is TokenPool { } /// @dev Calls into Facade to reenter Router exactly 1 time - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external override returns (Pool.LockOrBurnOutV1 memory) { if (s_attacked) { return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); @@ -34,17 +32,15 @@ contract ReentrantMaliciousTokenPool is TokenPool { s_attacked = true; + // solhint-disable-next-line check-send-result FacadeClient(i_facade).send(lockOrBurnIn.amount); emit Burned(msg.sender, lockOrBurnIn.amount); return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - pure - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol deleted file mode 100644 index 0c3108d279f..00000000000 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ /dev/null @@ -1,1681 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {Test} from "forge-std/Test.sol"; - -import {SortedSetValidationUtil} from "../../../shared/util/SortedSetValidationUtil.sol"; -import {CCIPConfig} from "../../capability/CCIPConfig.sol"; -import {ICapabilitiesRegistry} from "../../capability/interfaces/ICapabilitiesRegistry.sol"; -import {CCIPConfigTypes} from "../../capability/libraries/CCIPConfigTypes.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {CCIPConfigHelper} from "../helpers/CCIPConfigHelper.sol"; - -contract CCIPConfigSetup is Test { - address public constant OWNER = 0x82ae2B4F57CA5C1CBF8f744ADbD3697aD1a35AFe; - address public constant CAPABILITIES_REGISTRY = 0x272aF4BF7FBFc4944Ed59F914Cd864DfD912D55e; - - CCIPConfigHelper public s_ccipCC; - - function setUp() public { - changePrank(OWNER); - s_ccipCC = new CCIPConfigHelper(CAPABILITIES_REGISTRY); - } - - function _makeBytes32Array(uint256 length, uint256 seed) internal pure returns (bytes32[] memory arr) { - arr = new bytes32[](length); - for (uint256 i = 0; i < length; i++) { - arr[i] = keccak256(abi.encode(i, 1, seed)); - } - return arr; - } - - function _makeBytesArray(uint256 length, uint256 seed) internal pure returns (bytes[] memory arr) { - arr = new bytes[](length); - for (uint256 i = 0; i < length; i++) { - arr[i] = abi.encodePacked(keccak256(abi.encode(i, 1, seed))); - } - return arr; - } - - function _subset(bytes32[] memory arr, uint256 start, uint256 end) internal pure returns (bytes32[] memory) { - bytes32[] memory subset = new bytes32[](end - start); - for (uint256 i = start; i < end; i++) { - subset[i - start] = arr[i]; - } - return subset; - } - - //TODO: Use OZ's Arrays.sort when we upgrade to OZ v5 - function _sort(bytes32[] memory arr, int256 left, int256 right) private pure { - int256 i = left; - int256 j = right; - if (i == j) return; - bytes32 pivot = arr[uint256(left + (right - left) / 2)]; - while (i <= j) { - while (arr[uint256(i)] < pivot) i++; - while (pivot < arr[uint256(j)]) j--; - if (i <= j) { - (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]); - i++; - j--; - } - } - if (left < j) _sort(arr, left, j); - if (i < right) _sort(arr, i, right); - } - - function _addChainConfig(uint256 numNodes) - internal - returns (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) - { - p2pIds = _makeBytes32Array(numNodes, 0); - _sort(p2pIds, 0, int256(numNodes - 1)); - signers = _makeBytesArray(numNodes, 10); - transmitters = _makeBytesArray(numNodes, 20); - for (uint256 i = 0; i < numNodes; i++) { - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, p2pIds[i]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(signers[i]), - p2pId: p2pIds[i], - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - } - // Add chain selector for chain 1. - CCIPConfigTypes.ChainConfigInfo[] memory adds = new CCIPConfigTypes.ChainConfigInfo[](1); - adds[0] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 1, - chainConfig: CCIPConfigTypes.ChainConfig({readers: p2pIds, fChain: 1, config: bytes("config1")}) - }); - - vm.expectEmit(); - emit CCIPConfig.ChainConfigSet(1, adds[0].chainConfig); - s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); - - return (p2pIds, signers, transmitters); - } - - function test_getCapabilityConfiguration_Success() public { - bytes memory capConfig = s_ccipCC.getCapabilityConfiguration(42 /* doesn't matter, not used */ ); - assertEq(capConfig.length, 0, "capability config length must be 0"); - } -} - -contract CCIPConfig_chainConfig is CCIPConfigSetup { - // Successes. - - function test_applyChainConfigUpdates_addChainConfigs_Success() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPConfigTypes.ChainConfigInfo[] memory adds = new CCIPConfigTypes.ChainConfigInfo[](2); - adds[0] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 1, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 2, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectEmit(); - emit CCIPConfig.ChainConfigSet(1, adds[0].chainConfig); - vm.expectEmit(); - emit CCIPConfig.ChainConfigSet(2, adds[1].chainConfig); - s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); - - CCIPConfigTypes.ChainConfigInfo[] memory configs = s_ccipCC.getAllChainConfigs(); - assertEq(configs.length, 2, "chain configs length must be 2"); - assertEq(configs[0].chainSelector, 1, "chain selector must match"); - assertEq(configs[1].chainSelector, 2, "chain selector must match"); - } - - function test_applyChainConfigUpdates_removeChainConfigs_Success() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPConfigTypes.ChainConfigInfo[] memory adds = new CCIPConfigTypes.ChainConfigInfo[](2); - adds[0] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 1, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 2, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectEmit(); - emit CCIPConfig.ChainConfigSet(1, adds[0].chainConfig); - vm.expectEmit(); - emit CCIPConfig.ChainConfigSet(2, adds[1].chainConfig); - s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); - - uint64[] memory removes = new uint64[](1); - removes[0] = uint64(1); - - vm.expectEmit(); - emit CCIPConfig.ChainConfigRemoved(1); - s_ccipCC.applyChainConfigUpdates(removes, new CCIPConfigTypes.ChainConfigInfo[](0)); - } - - // Reverts. - - function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { - uint64[] memory removes = new uint64[](1); - removes[0] = uint64(1); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.ChainSelectorNotFound.selector, 1)); - s_ccipCC.applyChainConfigUpdates(removes, new CCIPConfigTypes.ChainConfigInfo[](0)); - } - - function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPConfigTypes.ChainConfigInfo[] memory adds = new CCIPConfigTypes.ChainConfigInfo[](1); - adds[0] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 1, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 1, config: abi.encode(1, 2, 3)}) - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 0, - signer: bytes32(0), - p2pId: bytes32(uint256(0)), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NodeNotInRegistry.selector, chainReaders[0])); - s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); - } - - function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPConfigTypes.ChainConfigInfo[] memory adds = new CCIPConfigTypes.ChainConfigInfo[](2); - adds[0] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 1, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPConfigTypes.ChainConfigInfo({ - chainSelector: 2, - chainConfig: CCIPConfigTypes.ChainConfig({readers: chainReaders, fChain: 0, config: bytes("config2")}) // bad fChain - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectRevert(CCIPConfig.FChainMustBePositive.selector); - s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); - } -} - -contract CCIPConfig_validateConfig is CCIPConfigSetup { - // Successes. - - function test__validateConfig_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - s_ccipCC.validateConfig(config); - } - - // Reverts. - - function test__validateConfig_ChainSelectorNotSet_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 0, // invalid - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.ChainSelectorNotSet.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: bytes(""), // invalid - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.OfframpAddressCannotBeZero.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_ChainSelectorNotFound_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 2, // not set - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.ChainSelectorNotFound.selector, 2)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_TooManySigners_Reverts() public { - // 32 > 31 (max num oracles) - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.TooManySigners.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_TooManyTransmitters_Reverts() public { - // 32 > 31 (max num oracles) - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); - - // truncate signers but keep transmitters > 31 - assembly { - mstore(signers, 30) - } - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.TooManyTransmitters.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_NotEnoughTransmitters_Reverts() public { - // 32 > 31 (max num oracles) - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(31); - - // truncate transmitters to < 3 * fChain + 1 - // since fChain is 1 in this case, we need to truncate to 3 transmitters. - assembly { - mstore(transmitters, 3) - } - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NotEnoughTransmitters.selector, 3, 4)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_FMustBePositive_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 0, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.FMustBePositive.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_FTooHigh_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 2, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.FTooHigh.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_P2PIdsLengthNotMatching_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // truncate the p2pIds length - assembly { - mstore(p2pIds, 3) - } - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert( - abi.encodeWithSelector(CCIPConfig.P2PIdsLengthNotMatching.selector, uint256(3), uint256(4), uint256(4)) - ); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_TooManyBootstrapP2PIds_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _makeBytes32Array(5, 0), // too many bootstrap p2pIds, 5 > 4 - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(CCIPConfig.TooManyBootstrapP2PIds.selector); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_NodeNotInRegistry_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - bytes32 nonExistentP2PId = keccak256("notInRegistry"); - p2pIds[0] = nonExistentP2PId; - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, nonExistentP2PId), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 0, - signer: bytes32(0), - p2pId: bytes32(uint256(0)), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NodeNotInRegistry.selector, nonExistentP2PId)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_P2PIdsNotSorted_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - //swapping two adjacent p2pIds to make it unsorted - (p2pIds[2], p2pIds[3]) = (p2pIds[3], p2pIds[2]); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, p2pIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - bytes32[] memory bootstrapP2PIds = _subset(p2pIds, 0, 2); - - //swapping bootstrapP2PIds to make it unsorted - (bootstrapP2PIds[0], bootstrapP2PIds[1]) = (bootstrapP2PIds[1], bootstrapP2PIds[0]); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: bootstrapP2PIds, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, bootstrapP2PIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_P2PIdsHasDuplicates_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - //forcing duplicate p2pIds - p2pIds[1] = p2pIds[2]; - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 2), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, p2pIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - bytes32[] memory bootstrapP2PIds = _subset(p2pIds, 0, 2); - //forcing duplicate bootstrapP2PIds - bootstrapP2PIds[1] = bootstrapP2PIds[0]; - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: bootstrapP2PIds, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, bootstrapP2PIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - //forcing invalid bootstrapP2PIds where the bootstrapP2PIds is sorted, but one of the element is not in the p2pIdsSet - bytes32[] memory bootstrapP2PIds = _subset(p2pIds, 0, 2); - p2pIds[1] = bytes32(uint256(p2pIds[0]) + 100); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: bootstrapP2PIds, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, bootstrapP2PIds, p2pIds)); - s_ccipCC.validateConfig(config); - } -} - -contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { - // Successful cases. - - function test__stateFromConfigLength_Success() public { - uint256 configLen = 0; - CCIPConfigTypes.ConfigState state = s_ccipCC.stateFromConfigLength(configLen); - assertEq(uint256(state), uint256(CCIPConfigTypes.ConfigState.Init)); - - configLen = 1; - state = s_ccipCC.stateFromConfigLength(configLen); - assertEq(uint256(state), uint256(CCIPConfigTypes.ConfigState.Running)); - - configLen = 2; - state = s_ccipCC.stateFromConfigLength(configLen); - assertEq(uint256(state), uint256(CCIPConfigTypes.ConfigState.Staging)); - } - - function test__validateConfigStateTransition_Success() public { - s_ccipCC.validateConfigStateTransition(CCIPConfigTypes.ConfigState.Init, CCIPConfigTypes.ConfigState.Running); - - s_ccipCC.validateConfigStateTransition(CCIPConfigTypes.ConfigState.Running, CCIPConfigTypes.ConfigState.Staging); - - s_ccipCC.validateConfigStateTransition(CCIPConfigTypes.ConfigState.Staging, CCIPConfigTypes.ConfigState.Running); - } - - function test__computeConfigDigest_Success() public { - // config digest must change upon: - // - ocr config change (e.g plugin type, chain selector, etc.) - // - don id change - // - config count change - bytes32[] memory p2pIds = _makeBytes32Array(4, 0); - bytes[] memory signers = _makeBytesArray(2, 10); - bytes[] memory transmitters = _makeBytesArray(2, 20); - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - uint32 donId = 1; - uint32 configCount = 1; - - bytes32 configDigest1 = s_ccipCC.computeConfigDigest(donId, configCount, config); - - donId = 2; - bytes32 configDigest2 = s_ccipCC.computeConfigDigest(donId, configCount, config); - - donId = 1; - configCount = 2; - bytes32 configDigest3 = s_ccipCC.computeConfigDigest(donId, configCount, config); - - configCount = 1; - config.pluginType = Internal.OCRPluginType.Execution; - bytes32 configDigest4 = s_ccipCC.computeConfigDigest(donId, configCount, config); - - assertNotEq(configDigest1, configDigest2, "config digests 1 and 2 must not match"); - assertNotEq(configDigest1, configDigest3, "config digests 1 and 3 must not match"); - assertNotEq(configDigest1, configDigest4, "config digests 1 and 4 must not match"); - - assertNotEq(configDigest2, configDigest3, "config digests 2 and 3 must not match"); - assertNotEq(configDigest2, configDigest4, "config digests 2 and 4 must not match"); - } - - function test_Fuzz__groupByPluginType_Success(uint256 numCommitCfgs, uint256 numExecCfgs) public { - numCommitCfgs = bound(numCommitCfgs, 0, 2); - numExecCfgs = bound(numExecCfgs, 0, 2); - - bytes32[] memory p2pIds = _makeBytes32Array(4, 0); - bytes[] memory signers = _makeBytesArray(4, 10); - bytes[] memory transmitters = _makeBytesArray(4, 20); - CCIPConfigTypes.OCR3Config[] memory cfgs = new CCIPConfigTypes.OCR3Config[](numCommitCfgs + numExecCfgs); - for (uint256 i = 0; i < numCommitCfgs; i++) { - cfgs[i] = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: abi.encode("commit", i) - }); - } - for (uint256 i = 0; i < numExecCfgs; i++) { - cfgs[numCommitCfgs + i] = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Execution, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: abi.encode("exec", numCommitCfgs + i) - }); - } - (CCIPConfigTypes.OCR3Config[] memory commitCfgs, CCIPConfigTypes.OCR3Config[] memory execCfgs) = - s_ccipCC.groupByPluginType(cfgs); - - assertEq(commitCfgs.length, numCommitCfgs, "commitCfgs length must match"); - assertEq(execCfgs.length, numExecCfgs, "execCfgs length must match"); - for (uint256 i = 0; i < commitCfgs.length; i++) { - assertEq(uint8(commitCfgs[i].pluginType), uint8(Internal.OCRPluginType.Commit), "plugin type must be commit"); - assertEq(commitCfgs[i].offchainConfig, abi.encode("commit", i), "offchain config must match"); - } - for (uint256 i = 0; i < execCfgs.length; i++) { - assertEq(uint8(execCfgs[i].pluginType), uint8(Internal.OCRPluginType.Execution), "plugin type must be execution"); - assertEq(execCfgs[i].offchainConfig, abi.encode("exec", numCommitCfgs + i), "offchain config must match"); - } - } - - function test__computeNewConfigWithMeta_InitToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](0); - CCIPConfigTypes.OCR3Config[] memory newConfig = new CCIPConfigTypes.OCR3Config[](1); - newConfig[0] = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.ConfigState currentState = CCIPConfigTypes.ConfigState.Init; - CCIPConfigTypes.ConfigState newState = CCIPConfigTypes.ConfigState.Running; - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta = - s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); - assertEq(newConfigWithMeta.length, 1, "new config with meta length must be 1"); - assertEq(newConfigWithMeta[0].configCount, uint64(1), "config count must be 1"); - assertEq(uint8(newConfigWithMeta[0].config.pluginType), uint8(newConfig[0].pluginType), "plugin type must match"); - assertEq(newConfigWithMeta[0].config.offchainConfig, newConfig[0].offchainConfig, "offchain config must match"); - assertEq( - newConfigWithMeta[0].configDigest, - s_ccipCC.computeConfigDigest(donId, 1, newConfig[0]), - "config digest must match" - ); - - // This ensures that the test case is using correct inputs. - s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); - } - - function test__computeNewConfigWithMeta_RunningToStaging_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - - CCIPConfigTypes.OCR3Config[] memory newConfig = new CCIPConfigTypes.OCR3Config[](2); - // existing blue config first. - newConfig[0] = blueConfig; - // green config next. - newConfig[1] = greenConfig; - - CCIPConfigTypes.ConfigState currentState = CCIPConfigTypes.ConfigState.Running; - CCIPConfigTypes.ConfigState newState = CCIPConfigTypes.ConfigState.Staging; - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta = - s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); - assertEq(newConfigWithMeta.length, 2, "new config with meta length must be 2"); - - assertEq(newConfigWithMeta[0].configCount, uint64(1), "config count of blue must be 1"); - assertEq( - uint8(newConfigWithMeta[0].config.pluginType), uint8(blueConfig.pluginType), "plugin type of blue must match" - ); - assertEq( - newConfigWithMeta[0].config.offchainConfig, blueConfig.offchainConfig, "offchain config of blue must match" - ); - assertEq( - newConfigWithMeta[0].configDigest, - s_ccipCC.computeConfigDigest(donId, 1, blueConfig), - "config digest of blue must match" - ); - - assertEq(newConfigWithMeta[1].configCount, uint64(2), "config count of green must be 2"); - assertEq( - uint8(newConfigWithMeta[1].config.pluginType), uint8(greenConfig.pluginType), "plugin type of green must match" - ); - assertEq( - newConfigWithMeta[1].config.offchainConfig, greenConfig.offchainConfig, "offchain config of green must match" - ); - assertEq( - newConfigWithMeta[1].configDigest, - s_ccipCC.computeConfigDigest(donId, 2, greenConfig), - "config digest of green must match" - ); - - // This ensures that the test case is using correct inputs. - s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); - } - - function test__computeNewConfigWithMeta_StagingToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - currentConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - }); - CCIPConfigTypes.OCR3Config[] memory newConfig = new CCIPConfigTypes.OCR3Config[](1); - newConfig[0] = greenConfig; - - CCIPConfigTypes.ConfigState currentState = CCIPConfigTypes.ConfigState.Staging; - CCIPConfigTypes.ConfigState newState = CCIPConfigTypes.ConfigState.Running; - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta = - s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); - - assertEq(newConfigWithMeta.length, 1, "new config with meta length must be 1"); - assertEq(newConfigWithMeta[0].configCount, uint64(2), "config count must be 2"); - assertEq(uint8(newConfigWithMeta[0].config.pluginType), uint8(greenConfig.pluginType), "plugin type must match"); - assertEq(newConfigWithMeta[0].config.offchainConfig, greenConfig.offchainConfig, "offchain config must match"); - assertEq( - newConfigWithMeta[0].configDigest, s_ccipCC.computeConfigDigest(donId, 2, greenConfig), "config digest must match" - ); - - // This ensures that the test case is using correct inputs. - s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); - } - - function test__validateConfigTransition_InitToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](0); - - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - function test__validateConfigTransition_RunningToStaging_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - newConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - function test__validateConfigTransition_StagingToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - currentConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - }); - - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - // Reverts. - - function test_Fuzz__stateFromConfigLength_Reverts(uint256 configLen) public { - vm.assume(configLen > 2); - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.InvalidConfigLength.selector, configLen)); - s_ccipCC.stateFromConfigLength(configLen); - } - - function test__groupByPluginType_threeCommitConfigs_Reverts() public { - bytes32[] memory p2pIds = _makeBytes32Array(4, 0); - bytes[] memory signers = _makeBytesArray(4, 10); - bytes[] memory transmitters = _makeBytesArray(4, 20); - CCIPConfigTypes.OCR3Config[] memory cfgs = new CCIPConfigTypes.OCR3Config[](3); - for (uint256 i = 0; i < 3; i++) { - cfgs[i] = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: abi.encode("commit", i) - }); - } - vm.expectRevert(); - s_ccipCC.groupByPluginType(cfgs); - } - - function test__groupByPluginType_threeExecutionConfigs_Reverts() public { - bytes32[] memory p2pIds = _makeBytes32Array(4, 0); - bytes[] memory signers = _makeBytesArray(4, 10); - bytes[] memory transmitters = _makeBytesArray(4, 20); - CCIPConfigTypes.OCR3Config[] memory cfgs = new CCIPConfigTypes.OCR3Config[](3); - for (uint256 i = 0; i < 3; i++) { - cfgs[i] = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Execution, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: abi.encode("exec", i) - }); - } - vm.expectRevert(); - s_ccipCC.groupByPluginType(cfgs); - } - - function test__groupByPluginType_TooManyOCR3Configs_Reverts() public { - CCIPConfigTypes.OCR3Config[] memory cfgs = new CCIPConfigTypes.OCR3Config[](5); - vm.expectRevert(CCIPConfig.TooManyOCR3Configs.selector); - s_ccipCC.groupByPluginType(cfgs); - } - - function test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() public { - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 0, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](0); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.WrongConfigCount.selector, 0, 1)); - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - function test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() public { - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 3, blueConfig) // wrong config digest (due to diff config count) - }); - newConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - }); - - vm.expectRevert( - abi.encodeWithSelector( - CCIPConfig.WrongConfigDigestBlueGreen.selector, - s_ccipCC.computeConfigDigest(donId, 3, blueConfig), - s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - ) - ); - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - function test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() public { - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - newConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 3, // wrong config count - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 3, greenConfig) - }); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.WrongConfigCount.selector, 3, 2)); - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - function test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() public { - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); - currentConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 1, - config: blueConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) - }); - currentConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - }); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - newConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ - configCount: 2, - config: greenConfig, - configDigest: s_ccipCC.computeConfigDigest(donId, 3, greenConfig) // wrong config digest - }); - - vm.expectRevert( - abi.encodeWithSelector( - CCIPConfig.WrongConfigDigest.selector, - s_ccipCC.computeConfigDigest(donId, 3, greenConfig), - s_ccipCC.computeConfigDigest(donId, 2, greenConfig) - ) - ); - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } - - function test__validateConfigTransition_NonExistentConfigTransition_Reverts() public { - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](3); - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); - vm.expectRevert(CCIPConfig.NonExistentConfigTransition.selector); - s_ccipCC.validateConfigTransition(currentConfig, newConfig); - } -} - -contract CCIPConfig__updatePluginConfig is CCIPConfigSetup { - // Successes. - - function test__updatePluginConfig_InitToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config[] memory configs = new CCIPConfigTypes.OCR3Config[](1); - configs[0] = blueConfig; - - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, configs); - - // should see the updated config in the contract state. - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfig = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 1, "don config length must be 1"); - assertEq(storedConfig[0].configCount, uint64(1), "config count must be 1"); - assertEq(uint256(storedConfig[0].config.pluginType), uint256(blueConfig.pluginType), "plugin type must match"); - } - - function test__updatePluginConfig_RunningToStaging_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // add blue config. - uint32 donId = 1; - Internal.OCRPluginType pluginType = Internal.OCRPluginType.Commit; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config[] memory startConfigs = new CCIPConfigTypes.OCR3Config[](1); - startConfigs[0] = blueConfig; - - // add blue AND green config to indicate an update. - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, startConfigs); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - CCIPConfigTypes.OCR3Config[] memory blueAndGreen = new CCIPConfigTypes.OCR3Config[](2); - blueAndGreen[0] = blueConfig; - blueAndGreen[1] = greenConfig; - - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, blueAndGreen); - - // should see the updated config in the contract state. - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfig = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 2, "don config length must be 2"); - // 0 index is blue config, 1 index is green config. - assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); - assertEq( - uint256(storedConfig[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq( - uint256(storedConfig[1].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); - assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); - } - - function test__updatePluginConfig_StagingToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // add blue config. - uint32 donId = 1; - Internal.OCRPluginType pluginType = Internal.OCRPluginType.Commit; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config[] memory startConfigs = new CCIPConfigTypes.OCR3Config[](1); - startConfigs[0] = blueConfig; - - // add blue AND green config to indicate an update. - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, startConfigs); - CCIPConfigTypes.OCR3Config memory greenConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit-new") - }); - CCIPConfigTypes.OCR3Config[] memory blueAndGreen = new CCIPConfigTypes.OCR3Config[](2); - blueAndGreen[0] = blueConfig; - blueAndGreen[1] = greenConfig; - - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, blueAndGreen); - - // should see the updated config in the contract state. - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfig = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 2, "don config length must be 2"); - // 0 index is blue config, 1 index is green config. - assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); - assertEq( - uint256(storedConfig[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq( - uint256(storedConfig[1].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); - assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); - - // promote green to blue. - CCIPConfigTypes.OCR3Config[] memory promote = new CCIPConfigTypes.OCR3Config[](1); - promote[0] = greenConfig; - - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, promote); - - // should see the updated config in the contract state. - storedConfig = s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 1, "don config length must be 1"); - assertEq(storedConfig[0].configCount, uint64(2), "config count must be 2"); - assertEq( - uint256(storedConfig[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq(storedConfig[0].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); - } - - // Reverts. - function test__updatePluginConfig_InvalidConfigLength_Reverts() public { - uint32 donId = 1; - CCIPConfigTypes.OCR3Config[] memory newConfig = new CCIPConfigTypes.OCR3Config[](3); - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.InvalidConfigLength.selector, uint256(3))); - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, newConfig); - } - - function test__updatePluginConfig_InvalidConfigStateTransition_Reverts() public { - uint32 donId = 1; - CCIPConfigTypes.OCR3Config[] memory newConfig = new CCIPConfigTypes.OCR3Config[](2); - // 0 -> 2 is an invalid state transition. - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.InvalidConfigStateTransition.selector, 0, 2)); - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, newConfig); - } -} - -contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { - // Successes. - function test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() public { - changePrank(CAPABILITIES_REGISTRY); - - CCIPConfigTypes.OCR3Config[] memory configs = new CCIPConfigTypes.OCR3Config[](0); - bytes memory encodedConfigs = abi.encode(configs); - s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encodedConfigs, 1, 1); - } - - function test_beforeCapabilityConfigSet_CommitConfigOnly_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - changePrank(CAPABILITIES_REGISTRY); - - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config[] memory configs = new CCIPConfigTypes.OCR3Config[](1); - configs[0] = blueConfig; - - bytes memory encoded = abi.encode(configs); - s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfigs = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfigs.length, 1, "config length must be 1"); - assertEq(storedConfigs[0].configCount, uint64(1), "config count must be 1"); - assertEq( - uint256(storedConfigs[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must be commit" - ); - } - - function test_beforeCapabilityConfigSet_ExecConfigOnly_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - changePrank(CAPABILITIES_REGISTRY); - - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Execution, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("exec") - }); - CCIPConfigTypes.OCR3Config[] memory configs = new CCIPConfigTypes.OCR3Config[](1); - configs[0] = blueConfig; - - bytes memory encoded = abi.encode(configs); - s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfigs = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Execution); - assertEq(storedConfigs.length, 1, "config length must be 1"); - assertEq(storedConfigs[0].configCount, uint64(1), "config count must be 1"); - assertEq( - uint256(storedConfigs[0].config.pluginType), - uint256(Internal.OCRPluginType.Execution), - "plugin type must be execution" - ); - } - - function test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - changePrank(CAPABILITIES_REGISTRY); - - uint32 donId = 1; - CCIPConfigTypes.OCR3Config memory blueCommitConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("commit") - }); - CCIPConfigTypes.OCR3Config memory blueExecConfig = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Execution, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("exec") - }); - CCIPConfigTypes.OCR3Config[] memory configs = new CCIPConfigTypes.OCR3Config[](2); - configs[0] = blueExecConfig; - configs[1] = blueCommitConfig; - - bytes memory encoded = abi.encode(configs); - s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedExecConfigs = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Execution); - assertEq(storedExecConfigs.length, 1, "config length must be 1"); - assertEq(storedExecConfigs[0].configCount, uint64(1), "config count must be 1"); - assertEq( - uint256(storedExecConfigs[0].config.pluginType), - uint256(Internal.OCRPluginType.Execution), - "plugin type must be execution" - ); - - CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedCommitConfigs = - s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedCommitConfigs.length, 1, "config length must be 1"); - assertEq(storedCommitConfigs[0].configCount, uint64(1), "config count must be 1"); - assertEq( - uint256(storedCommitConfigs[0].config.pluginType), - uint256(Internal.OCRPluginType.Commit), - "plugin type must be commit" - ); - } - - // Reverts. - - function test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() public { - bytes32[] memory nodes = new bytes32[](0); - bytes memory config = bytes(""); - uint64 configCount = 1; - uint32 donId = 1; - vm.expectRevert(CCIPConfig.OnlyCapabilitiesRegistryCanCall.selector); - s_ccipCC.beforeCapabilityConfigSet(nodes, config, configCount, donId); - } -} diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol new file mode 100644 index 00000000000..d142e5fbfed --- /dev/null +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol @@ -0,0 +1,921 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../../keystone/interfaces/ICapabilityConfiguration.sol"; +import {INodeInfoProvider} from "../../../keystone/interfaces/INodeInfoProvider.sol"; + +import {CCIPHome} from "../../capability/CCIPHome.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {CCIPHomeHelper} from "../helpers/CCIPHomeHelper.sol"; +import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; + +contract CCIPHomeTest is Test { + // address internal constant OWNER = address(0x0000000123123123123); + bytes32 internal constant ZERO_DIGEST = bytes32(uint256(0)); + address internal constant CAPABILITIES_REGISTRY = address(0x0000000123123123123); + Internal.OCRPluginType internal constant DEFAULT_PLUGIN_TYPE = Internal.OCRPluginType.Commit; + uint32 internal constant DEFAULT_DON_ID = 78978987; + + CCIPHomeHelper public s_ccipHome; + + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 private constant PREFIX = 0x000a << (256 - 16); // 0x000b00..00 + + uint64 private constant DEFAULT_CHAIN_SELECTOR = 9381579735; + + function setUp() public virtual { + s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), _getBaseChainConfigs()); + vm.startPrank(address(s_ccipHome)); + } + + function _getBaseChainConfigs() internal pure returns (CCIPHome.ChainConfigArgs[] memory) { + CCIPHome.ChainConfigArgs[] memory configs = new CCIPHome.ChainConfigArgs[](1); + CCIPHome.ChainConfig memory chainConfig = + CCIPHome.ChainConfig({readers: new bytes32[](0), fChain: 1, config: abi.encode("chainConfig")}); + configs[0] = CCIPHome.ChainConfigArgs({chainSelector: DEFAULT_CHAIN_SELECTOR, chainConfig: chainConfig}); + + return configs; + } + + function _getConfigDigest( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes memory config, + uint32 version + ) internal view returns (bytes32) { + return bytes32( + (PREFIX & PREFIX_MASK) + | ( + uint256( + keccak256( + bytes.concat( + abi.encode(bytes32("EVM"), block.chainid, address(s_ccipHome), donId, pluginType, version), config + ) + ) + ) & ~PREFIX_MASK + ) + ); + } + + function _getBaseConfig( + Internal.OCRPluginType pluginType + ) internal returns (CCIPHome.OCR3Config memory) { + CCIPHome.OCR3Node[] memory nodes = new CCIPHome.OCR3Node[](4); + bytes32[] memory p2pIds = new bytes32[](4); + for (uint256 i = 0; i < nodes.length; i++) { + p2pIds[i] = keccak256(abi.encode("p2pId", i)); + nodes[i] = CCIPHome.OCR3Node({ + p2pId: keccak256(abi.encode("p2pId", i)), + signerKey: abi.encode("signerKey"), + transmitterKey: abi.encode("transmitterKey") + }); + } + + // This is a work-around for not calling mockCall / expectCall with each scenario using _getBaseConfig + INodeInfoProvider.NodeInfo[] memory nodeInfos = new INodeInfoProvider.NodeInfo[](4); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, p2pIds), + abi.encode(nodeInfos) + ); + + return CCIPHome.OCR3Config({ + pluginType: pluginType, + chainSelector: DEFAULT_CHAIN_SELECTOR, + FRoleDON: 1, + offchainConfigVersion: 98765, + offrampAddress: abi.encode("offrampAddress"), + rmnHomeAddress: abi.encode("rmnHomeAddress"), + nodes: nodes, + offchainConfig: abi.encode("offchainConfig") + }); + } +} + +contract CCIPHome_constructor is CCIPHomeTest { + function test_constructor_success() public { + CCIPHome ccipHome = new CCIPHome(CAPABILITIES_REGISTRY); + + assertEq(address(ccipHome.getCapabilityRegistry()), CAPABILITIES_REGISTRY); + } + + function test_supportsInterface_success() public view { + assertTrue(s_ccipHome.supportsInterface(type(IERC165).interfaceId)); + assertTrue(s_ccipHome.supportsInterface(type(ICapabilityConfiguration).interfaceId)); + } + + function test_getCapabilityConfiguration_success() public view { + bytes memory config = s_ccipHome.getCapabilityConfiguration(DEFAULT_DON_ID); + assertEq(config.length, 0); + } + + function test_constructor_CapabilitiesRegistryAddressZero_reverts() public { + vm.expectRevert(CCIPHome.ZeroAddressNotAllowed.selector); + new CCIPHome(address(0)); + } +} + +contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTest { + function setUp() public virtual override { + super.setUp(); + vm.stopPrank(); + vm.startPrank(address(CAPABILITIES_REGISTRY)); + } + + function test_beforeCapabilityConfigSet_success() public { + // first set a config + bytes memory callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + // Then revoke the config + bytes32 candidateDigest = s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertNotEq(candidateDigest, ZERO_DIGEST); + + callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, candidateDigest)); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + // Then set a new config + callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + // Then promote the new config + + bytes32 newCandidateDigest = s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertNotEq(newCandidateDigest, ZERO_DIGEST); + + callData = abi.encodeCall( + CCIPHome.promoteCandidateAndRevokeActive, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, newCandidateDigest, ZERO_DIGEST) + ); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + bytes32 activeDigest = s_ccipHome.getActiveDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, newCandidateDigest); + } + + function test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() public { + bytes memory callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.stopPrank(); + + vm.expectRevert(CCIPHome.OnlyCapabilitiesRegistryCanCall.selector); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + } + + function test_beforeCapabilityConfigSet_InvalidSelector_reverts() 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 { + uint32 wrongDonId = DEFAULT_DON_ID + 1; + + bytes memory callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.DONIdMismatch.selector, DEFAULT_DON_ID, wrongDonId)); + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, wrongDonId); + } + + function test_beforeCapabilityConfigSet_InnerCallReverts_reverts() public { + bytes memory callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST)); + + vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + } +} + +contract CCIPHome_getConfigDigests is CCIPHomeTest { + function test_getConfigDigests_success() public { + (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, firstDigest); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, firstDigest, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, ZERO_DIGEST); + + bytes32 secondDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, secondDigest); + + assertEq(activeDigest, s_ccipHome.getActiveDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); + assertEq(candidateDigest, s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); + } +} + +contract CCIPHome_getAllConfigs is CCIPHomeTest { + function test_getAllConfigs_success() public { + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (CCIPHome.VersionedConfig memory activeConfig, CCIPHome.VersionedConfig memory candidateConfig) = + s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, ZERO_DIGEST); + assertEq(candidateConfig.configDigest, firstDigest); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, firstDigest, ZERO_DIGEST); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, firstDigest); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + + bytes32 secondDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, firstDigest); + assertEq(candidateConfig.configDigest, secondDigest); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID + 1, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, ZERO_DIGEST); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, Internal.OCRPluginType.Execution); + assertEq(activeConfig.configDigest, ZERO_DIGEST); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + } +} + +contract CCIPHome_setCandidate is CCIPHomeTest { + function test_setCandidate_success() public { + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + CCIPHome.VersionedConfig memory versionedConfig = + CCIPHome.VersionedConfig({version: 1, config: config, configDigest: ZERO_DIGEST}); + + versionedConfig.configDigest = + _getConfigDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, abi.encode(versionedConfig.config), versionedConfig.version); + + vm.expectEmit(); + emit CCIPHome.ConfigSet(versionedConfig.configDigest, versionedConfig.version, versionedConfig.config); + + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, versionedConfig.config, ZERO_DIGEST); + + (CCIPHome.VersionedConfig memory storedVersionedConfig, bool ok) = + s_ccipHome.getConfig(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, versionedConfig.configDigest); + assertTrue(ok); + assertEq(storedVersionedConfig.version, versionedConfig.version); + assertEq(storedVersionedConfig.configDigest, versionedConfig.configDigest); + assertEq(keccak256(abi.encode(storedVersionedConfig.config)), keccak256(abi.encode(versionedConfig.config))); + } + + function test_setCandidate_ConfigDigestMismatch_reverts() public { + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + + bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, digest, ZERO_DIGEST)); + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + vm.expectEmit(); + emit CCIPHome.CandidateConfigRevoked(digest); + + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, digest); + } + + function test_setCandidate_CanOnlySelfCall_reverts() public { + vm.stopPrank(); + + vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); + s_ccipHome.setCandidate( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST + ); + } +} + +contract CCIPHome_revokeCandidate is CCIPHomeTest { + // Sets two configs + function setUp() public virtual override { + super.setUp(); + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, digest, ZERO_DIGEST); + + config.offrampAddress = abi.encode("new_offrampAddress"); + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + } + + function test_revokeCandidate_success() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = + s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + + vm.expectEmit(); + emit CCIPHome.CandidateConfigRevoked(priorCandidateDigest); + + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest); + + (CCIPHome.VersionedConfig memory storedVersionedConfig, bool ok) = + s_ccipHome.getConfig(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest); + assertFalse(ok); + // Ensure no old data is returned, even though it's still in storage + assertEq(storedVersionedConfig.version, 0); + assertEq(storedVersionedConfig.config.chainSelector, 0); + assertEq(storedVersionedConfig.config.FRoleDON, 0); + + // Asser the active digest is unaffected but the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, priorActiveDigest); + assertEq(candidateDigest, ZERO_DIGEST); + assertTrue(candidateDigest != priorCandidateDigest); + } + + function test_revokeCandidate_ConfigDigestMismatch_reverts() public { + (, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + + bytes32 wrongDigest = keccak256("wrong_digest"); + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorCandidateDigest, wrongDigest)); + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongDigest); + } + + function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { + vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST); + } + + function test_revokeCandidate_CanOnlySelfCall_reverts() public { + vm.startPrank(address(0)); + + vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, keccak256("configDigest")); + } +} + +contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTest { + function test_promoteCandidateAndRevokeActive_multiplePlugins_success() public { + promoteCandidateAndRevokeActive(Internal.OCRPluginType.Commit); + promoteCandidateAndRevokeActive(Internal.OCRPluginType.Execution); + + // check that the two plugins have only active configs and no candidates. + (bytes32 activeDigest, bytes32 candidateDigest) = + s_ccipHome.getConfigDigests(DEFAULT_DON_ID, Internal.OCRPluginType.Commit); + assertTrue(activeDigest != ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, Internal.OCRPluginType.Execution); + assertTrue(activeDigest != ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + } + + function promoteCandidateAndRevokeActive( + Internal.OCRPluginType pluginType + ) public { + CCIPHome.OCR3Config memory config = _getBaseConfig(pluginType); + bytes32 firstConfigToPromote = s_ccipHome.setCandidate(DEFAULT_DON_ID, pluginType, config, ZERO_DIGEST); + + vm.expectEmit(); + emit CCIPHome.ConfigPromoted(firstConfigToPromote); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, pluginType, firstConfigToPromote, ZERO_DIGEST); + + // Assert the active digest is updated and the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, pluginType); + assertEq(activeDigest, firstConfigToPromote); + assertEq(candidateDigest, ZERO_DIGEST); + + // Set a new candidate to promote over a non-zero active config. + config.offchainConfig = abi.encode("new_offchainConfig_config"); + bytes32 secondConfigToPromote = s_ccipHome.setCandidate(DEFAULT_DON_ID, pluginType, config, ZERO_DIGEST); + + vm.expectEmit(); + emit CCIPHome.ActiveConfigRevoked(firstConfigToPromote); + + vm.expectEmit(); + emit CCIPHome.ConfigPromoted(secondConfigToPromote); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, pluginType, secondConfigToPromote, firstConfigToPromote); + + (CCIPHome.VersionedConfig memory activeConfig, CCIPHome.VersionedConfig memory candidateConfig) = + s_ccipHome.getAllConfigs(DEFAULT_DON_ID, pluginType); + assertEq(activeConfig.configDigest, secondConfigToPromote); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + assertEq(keccak256(abi.encode(activeConfig.config)), keccak256(abi.encode(config))); + } + + function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() 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 { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = + s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); + bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); + + vm.expectRevert( + abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongCandidateDigest) + ); + s_ccipHome.promoteCandidateAndRevokeActive( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongCandidateDigest, wrongActiveDigest + ); + + vm.expectRevert( + abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongActiveDigest) + ); + + s_ccipHome.promoteCandidateAndRevokeActive( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest, wrongActiveDigest + ); + } + + function test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() public { + vm.stopPrank(); + + vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); + s_ccipHome.promoteCandidateAndRevokeActive( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, keccak256("toPromote"), keccak256("ToRevoke") + ); + } +} + +contract CCIPHome__validateConfig is CCIPHomeTest { + function setUp() public virtual override { + s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); + } + + function _addChainConfig( + uint256 numNodes + ) internal returns (CCIPHome.OCR3Node[] memory nodes) { + return _addChainConfig(numNodes, 1); + } + + function _makeBytes32Array(uint256 length, uint256 seed) internal pure returns (bytes32[] memory arr) { + arr = new bytes32[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = keccak256(abi.encode(i, 1, seed)); + } + return arr; + } + + function _makeBytesArray(uint256 length, uint256 seed) internal pure returns (bytes[] memory arr) { + arr = new bytes[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = abi.encode(keccak256(abi.encode(i, 1, seed))); + } + return arr; + } + + function _addChainConfig(uint256 numNodes, uint8 fChain) internal returns (CCIPHome.OCR3Node[] memory nodes) { + bytes32[] memory p2pIds = _makeBytes32Array(numNodes, 0); + bytes[] memory signers = _makeBytesArray(numNodes, 10); + bytes[] memory transmitters = _makeBytesArray(numNodes, 20); + + nodes = new CCIPHome.OCR3Node[](numNodes); + INodeInfoProvider.NodeInfo[] memory nodeInfos = new INodeInfoProvider.NodeInfo[](numNodes); + for (uint256 i = 0; i < numNodes; i++) { + nodes[i] = CCIPHome.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); + nodeInfos[i] = INodeInfoProvider.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(signers[i]), + p2pId: p2pIds[i], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }); + } + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, p2pIds), + abi.encode(nodeInfos) + ); + // Add chain selector for chain 1. + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: p2pIds, fChain: fChain, config: bytes("config1")}) + }); + + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + return nodes; + } + + function _getCorrectOCR3Config(uint8 numNodes, uint8 FRoleDON) internal returns (CCIPHome.OCR3Config memory) { + CCIPHome.OCR3Node[] memory nodes = _addChainConfig(numNodes); + + return CCIPHome.OCR3Config({ + pluginType: Internal.OCRPluginType.Commit, + offrampAddress: abi.encode(keccak256(abi.encode("offramp"))), + rmnHomeAddress: abi.encode(keccak256(abi.encode("rmnHome"))), + chainSelector: 1, + nodes: nodes, + FRoleDON: FRoleDON, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + } + + function _getCorrectOCR3Config() internal returns (CCIPHome.OCR3Config memory) { + return _getCorrectOCR3Config(4, 1); + } + + // Successes. + + function test__validateConfig_Success() public { + s_ccipHome.validateConfig(_getCorrectOCR3Config()); + } + + function test__validateConfigLessTransmittersThanSigners_Success() public { + // fChain is 1, so there should be at least 4 transmitters. + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(5, 1); + config.nodes[1].transmitterKey = bytes(""); + + s_ccipHome.validateConfig(config); + } + + function test__validateConfigSmallerFChain_Success() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(11, 3); + + // Set fChain to 2 + _addChainConfig(4, 2); + + s_ccipHome.validateConfig(config); + } + + // Reverts + + function test__validateConfig_ChainSelectorNotSet_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.chainSelector = 0; // invalid + + vm.expectRevert(CCIPHome.ChainSelectorNotSet.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.offrampAddress = ""; // invalid + + vm.expectRevert(CCIPHome.OfframpAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.offrampAddress = abi.encode(address(0)); // invalid + + vm.expectRevert(CCIPHome.OfframpAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.rmnHomeAddress = ""; // invalid + + vm.expectRevert(CCIPHome.RMNHomeAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.rmnHomeAddress = abi.encode(address(0)); // invalid + + vm.expectRevert(CCIPHome.RMNHomeAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ChainSelectorNotFound_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.chainSelector = 2; // not set + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ChainSelectorNotFound.selector, 2)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_NotEnoughTransmitters_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + uint256 numberOfTransmitters = 3; + + // 32 > 31 (max num oracles) + CCIPHome.OCR3Node[] memory nodes = _addChainConfig(31); + + // truncate transmitters to < 3 * fChain + 1 + // since fChain is 1 in this case, we need to truncate to 3 transmitters. + for (uint256 i = numberOfTransmitters; i < nodes.length; ++i) { + nodes[i].transmitterKey = bytes(""); + } + + config.nodes = nodes; + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, numberOfTransmitters, 4)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[0].transmitterKey = bytes(""); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, 3, 4)); + s_ccipHome.validateConfig(config); + + // Zero out remaining transmitters to verify error changes + for (uint256 i = 1; i < config.nodes.length; ++i) { + config.nodes[i].transmitterKey = bytes(""); + } + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, 0, 4)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_TooManySigners_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes = new CCIPHome.OCR3Node[](257); + + vm.expectRevert(CCIPHome.TooManySigners.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_FChainTooHigh_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 2; // too low + + // Set fChain to 3 + _addChainConfig(4, 3); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.FChainTooHigh.selector, 3, 2)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_FMustBePositive_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 0; // not positive + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.FChainTooHigh.selector, 1, 0)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_FTooHigh_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 2; // too high + + vm.expectRevert(CCIPHome.FTooHigh.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ZeroP2PId_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[1].p2pId = bytes32(0); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidNode.selector, config.nodes[1])); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ZeroSignerKey_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[2].signerKey = bytes(""); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidNode.selector, config.nodes[2])); + s_ccipHome.validateConfig(config); + } +} + +contract CCIPHome_applyChainConfigUpdates is CCIPHomeTest { + function setUp() public virtual override { + s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); + } + + function test_applyChainConfigUpdates_addChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + INodeInfoProvider.NodeInfo[] memory nodeInfos = new INodeInfoProvider.NodeInfo[](1); + nodeInfos[0] = INodeInfoProvider.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, chainReaders), + abi.encode(nodeInfos) + ); + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + CCIPHome.ChainConfigArgs[] memory configs = s_ccipHome.getAllChainConfigs(0, 2); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); + } + + function test_getPaginatedCCIPHomes_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + INodeInfoProvider.NodeInfo[] memory nodeInfos = new INodeInfoProvider.NodeInfo[](1); + nodeInfos[0] = INodeInfoProvider.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, chainReaders), + abi.encode(nodeInfos) + ); + + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + CCIPHome.ChainConfigArgs[] memory configs = s_ccipHome.getAllChainConfigs(0, 2); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + + configs = s_ccipHome.getAllChainConfigs(0, 1); + assertEq(configs.length, 1, "chain configs length must be 1"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + + configs = s_ccipHome.getAllChainConfigs(0, 10); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + + configs = s_ccipHome.getAllChainConfigs(1, 1); + assertEq(configs.length, 1, "chain configs length must be 1"); + + configs = s_ccipHome.getAllChainConfigs(1, 2); + assertEq(configs.length, 0, "chain configs length must be 0"); + } + + function test_applyChainConfigUpdates_removeChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + + INodeInfoProvider.NodeInfo[] memory nodeInfos = new INodeInfoProvider.NodeInfo[](1); + nodeInfos[0] = INodeInfoProvider.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, chainReaders), + abi.encode(nodeInfos) + ); + + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); + + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectEmit(); + emit CCIPHome.ChainConfigRemoved(1); + s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); + + assertEq(s_ccipHome.getNumChainConfigurations(), 1, "total chain configs must be 1"); + } + + // Reverts. + + function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ChainSelectorNotFound.selector, 1)); + s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); + } + + function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: abi.encode(1, 2, 3)}) + }); + + vm.mockCallRevert( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, chainReaders), + abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, chainReaders[0]) + ); + + vm.expectRevert(abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, chainReaders[0])); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + } + + function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 0, config: bytes("config2")}) // bad fChain + }); + INodeInfoProvider.NodeInfo[] memory nodeInfos = new INodeInfoProvider.NodeInfo[](1); + nodeInfos[0] = INodeInfoProvider.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, chainReaders), + abi.encode(nodeInfos) + ); + + vm.expectRevert(CCIPHome.FChainMustBePositive.selector); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + } +} diff --git a/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol b/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol deleted file mode 100644 index 7598f9ccb69..00000000000 --- a/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol +++ /dev/null @@ -1,618 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {CommitStore} from "../../CommitStore.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; -import {RMN} from "../../RMN.sol"; -import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; -import {OCR2Abstract} from "../../ocr/OCR2Abstract.sol"; -import {CommitStoreHelper} from "../helpers/CommitStoreHelper.sol"; -import {OCR2BaseSetup} from "../ocr/OCR2Base.t.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; - -contract CommitStoreSetup is PriceRegistrySetup, OCR2BaseSetup { - CommitStoreHelper internal s_commitStore; - - function setUp() public virtual override(PriceRegistrySetup, OCR2BaseSetup) { - PriceRegistrySetup.setUp(); - OCR2BaseSetup.setUp(); - - s_commitStore = new CommitStoreHelper( - CommitStore.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: ON_RAMP_ADDRESS, - rmnProxy: address(s_mockRMN) - }) - ); - CommitStore.DynamicConfig memory dynamicConfig = - CommitStore.DynamicConfig({priceRegistry: address(s_priceRegistry)}); - s_commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = address(s_commitStore); - s_priceRegistry.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) - ); - } -} - -contract CommitStoreRealRMNSetup is PriceRegistrySetup, OCR2BaseSetup { - CommitStoreHelper internal s_commitStore; - - RMN internal s_rmn; - - address internal constant BLESS_VOTE_ADDR = address(8888); - - function setUp() public virtual override(PriceRegistrySetup, OCR2BaseSetup) { - PriceRegistrySetup.setUp(); - OCR2BaseSetup.setUp(); - - RMN.Voter[] memory voters = new RMN.Voter[](1); - voters[0] = - RMN.Voter({blessVoteAddr: BLESS_VOTE_ADDR, curseVoteAddr: address(9999), blessWeight: 1, curseWeight: 1}); - // Overwrite base mock rmn with real. - s_rmn = new RMN(RMN.Config({voters: voters, blessWeightThreshold: 1, curseWeightThreshold: 1})); - s_commitStore = new CommitStoreHelper( - CommitStore.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: ON_RAMP_ADDRESS, - rmnProxy: address(s_rmn) - }) - ); - CommitStore.DynamicConfig memory dynamicConfig = - CommitStore.DynamicConfig({priceRegistry: address(s_priceRegistry)}); - s_commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - } -} - -contract CommitStore_constructor is PriceRegistrySetup, OCR2BaseSetup { - function setUp() public virtual override(PriceRegistrySetup, OCR2BaseSetup) { - PriceRegistrySetup.setUp(); - OCR2BaseSetup.setUp(); - } - - function test_Constructor_Success() public { - CommitStore.StaticConfig memory staticConfig = CommitStore.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: 0x2C44CDDdB6a900Fa2B585dd299E03D12Fa4293Bc, - rmnProxy: address(s_mockRMN) - }); - CommitStore.DynamicConfig memory dynamicConfig = - CommitStore.DynamicConfig({priceRegistry: address(s_priceRegistry)}); - - vm.expectEmit(); - emit CommitStore.ConfigSet(staticConfig, dynamicConfig); - - CommitStore commitStore = new CommitStore(staticConfig); - commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - - CommitStore.StaticConfig memory gotStaticConfig = commitStore.getStaticConfig(); - - assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); - assertEq(staticConfig.sourceChainSelector, gotStaticConfig.sourceChainSelector); - assertEq(staticConfig.onRamp, gotStaticConfig.onRamp); - assertEq(staticConfig.rmnProxy, gotStaticConfig.rmnProxy); - - CommitStore.DynamicConfig memory gotDynamicConfig = commitStore.getDynamicConfig(); - - assertEq(dynamicConfig.priceRegistry, gotDynamicConfig.priceRegistry); - - // CommitStore initial values - assertEq(0, commitStore.getLatestPriceEpochAndRound()); - assertEq(1, commitStore.getExpectedNextSequenceNumber()); - assertEq(commitStore.typeAndVersion(), "CommitStore 1.5.0-dev"); - assertEq(OWNER, commitStore.owner()); - assertTrue(commitStore.isUnpausedAndNotCursed()); - } -} - -contract CommitStore_setMinSeqNr is CommitStoreSetup { - function test_Fuzz_SetMinSeqNr_Success(uint64 minSeqNr) public { - vm.expectEmit(); - emit CommitStore.SequenceNumberSet(s_commitStore.getExpectedNextSequenceNumber(), minSeqNr); - - s_commitStore.setMinSeqNr(minSeqNr); - - assertEq(s_commitStore.getExpectedNextSequenceNumber(), minSeqNr); - } - - // Reverts - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - s_commitStore.setMinSeqNr(6723); - } -} - -contract CommitStore_setDynamicConfig is CommitStoreSetup { - function test_Fuzz_SetDynamicConfig_Success(address priceRegistry) public { - vm.assume(priceRegistry != address(0)); - CommitStore.StaticConfig memory staticConfig = s_commitStore.getStaticConfig(); - CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: priceRegistry}); - bytes memory onchainConfig = abi.encode(dynamicConfig); - - vm.expectEmit(); - emit CommitStore.ConfigSet(staticConfig, dynamicConfig); - - uint32 configCount = 1; - - vm.expectEmit(); - emit OCR2Abstract.ConfigSet( - uint32(block.number), - getBasicConfigDigest(address(s_commitStore), s_f, configCount, onchainConfig), - configCount + 1, - s_valid_signers, - s_valid_transmitters, - s_f, - onchainConfig, - s_offchainConfigVersion, - abi.encode("") - ); - - s_commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, onchainConfig, s_offchainConfigVersion, abi.encode("") - ); - - CommitStore.DynamicConfig memory gotDynamicConfig = s_commitStore.getDynamicConfig(); - assertEq(gotDynamicConfig.priceRegistry, dynamicConfig.priceRegistry); - } - - function test_PriceEpochCleared_Success() public { - // Set latest price epoch and round to non-zero. - uint40 latestEpochAndRound = 1782155; - s_commitStore.setLatestPriceEpochAndRound(latestEpochAndRound); - assertEq(latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - - CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: address(1)}); - // New config should clear it. - s_commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - // Assert cleared. - assertEq(0, s_commitStore.getLatestPriceEpochAndRound()); - } - - // Reverts - function test_OnlyOwner_Revert() public { - CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: address(23784264)}); - - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - s_commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - } - - function test_InvalidCommitStoreConfig_Revert() public { - CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: address(0)}); - - vm.expectRevert(CommitStore.InvalidCommitStoreConfig.selector); - s_commitStore.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - } -} - -contract CommitStore_resetUnblessedRoots is CommitStoreRealRMNSetup { - function test_ResetUnblessedRoots_Success() public { - bytes32[] memory rootsToReset = new bytes32[](3); - rootsToReset[0] = "1"; - rootsToReset[1] = "2"; - rootsToReset[2] = "3"; - - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(1, 2), - merkleRoot: rootsToReset[0] - }); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - - report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(3, 4), - merkleRoot: rootsToReset[1] - }); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - - report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(5, 5), - merkleRoot: rootsToReset[2] - }); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - - IRMN.TaggedRoot[] memory blessedTaggedRoots = new IRMN.TaggedRoot[](1); - blessedTaggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_commitStore), root: rootsToReset[1]}); - - vm.startPrank(BLESS_VOTE_ADDR); - s_rmn.voteToBless(blessedTaggedRoots); - - vm.expectEmit(false, false, false, true); - emit CommitStore.RootRemoved(rootsToReset[0]); - - vm.expectEmit(false, false, false, true); - emit CommitStore.RootRemoved(rootsToReset[2]); - - vm.startPrank(OWNER); - s_commitStore.resetUnblessedRoots(rootsToReset); - - assertEq(0, s_commitStore.getMerkleRoot(rootsToReset[0])); - assertEq(BLOCK_TIME, s_commitStore.getMerkleRoot(rootsToReset[1])); - assertEq(0, s_commitStore.getMerkleRoot(rootsToReset[2])); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - bytes32[] memory rootToReset; - s_commitStore.resetUnblessedRoots(rootToReset); - } -} - -contract CommitStore_report is CommitStoreSetup { - function test_ReportOnlyRootSuccess_gas() public { - vm.pauseGasMetering(); - uint64 max1 = 931; - bytes32 root = "Only a single root"; - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(1, max1), - merkleRoot: root - }); - - vm.expectEmit(); - emit CommitStore.ReportAccepted(report); - - bytes memory encodedReport = abi.encode(report); - - vm.resumeGasMetering(); - s_commitStore.report(encodedReport, ++s_latestEpochAndRound); - vm.pauseGasMetering(); - - assertEq(max1 + 1, s_commitStore.getExpectedNextSequenceNumber()); - assertEq(block.timestamp, s_commitStore.getMerkleRoot(root)); - vm.resumeGasMetering(); - } - - function test_ReportAndPriceUpdate_Success() public { - uint64 max1 = 12; - - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - interval: CommitStore.Interval(1, max1), - merkleRoot: "test #2" - }); - - vm.expectEmit(); - emit CommitStore.ReportAccepted(report); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - - assertEq(max1 + 1, s_commitStore.getExpectedNextSequenceNumber()); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - } - - function test_StaleReportWithRoot_Success() public { - uint64 maxSeq = 12; - uint224 tokenStartPrice = - IPriceRegistry(s_commitStore.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value; - - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - interval: CommitStore.Interval(1, maxSeq), - merkleRoot: "stale report 1" - }); - - vm.expectEmit(); - emit CommitStore.ReportAccepted(report); - - s_commitStore.report(abi.encode(report), s_latestEpochAndRound); - assertEq(maxSeq + 1, s_commitStore.getExpectedNextSequenceNumber()); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - - report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(maxSeq + 1, maxSeq * 2), - merkleRoot: "stale report 2" - }); - - vm.expectEmit(); - emit CommitStore.ReportAccepted(report); - - s_commitStore.report(abi.encode(report), s_latestEpochAndRound); - assertEq(maxSeq * 2 + 1, s_commitStore.getExpectedNextSequenceNumber()); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - assertEq( - tokenStartPrice, - IPriceRegistry(s_commitStore.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value - ); - } - - function test_OnlyTokenPriceUpdates_Success() public { - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - interval: CommitStore.Interval(0, 0), - merkleRoot: "" - }); - - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - } - - function test_OnlyGasPriceUpdates_Success() public { - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - interval: CommitStore.Interval(0, 0), - merkleRoot: "" - }); - - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - } - - function test_ValidPriceUpdateThenStaleReportWithRoot_Success() public { - uint64 maxSeq = 12; - uint224 tokenPrice1 = 4e18; - uint224 tokenPrice2 = 5e18; - - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), - interval: CommitStore.Interval(0, 0), - merkleRoot: "" - }); - - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - - report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2), - interval: CommitStore.Interval(1, maxSeq), - merkleRoot: "stale report" - }); - - vm.expectEmit(); - emit CommitStore.ReportAccepted(report); - - s_commitStore.report(abi.encode(report), s_latestEpochAndRound); - - assertEq(maxSeq + 1, s_commitStore.getExpectedNextSequenceNumber()); - assertEq( - tokenPrice1, IPriceRegistry(s_commitStore.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value - ); - assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); - } - - // Reverts - - function test_Paused_Revert() public { - s_commitStore.pause(); - bytes memory report; - vm.expectRevert(CommitStore.PausedError.selector); - s_commitStore.report(report, ++s_latestEpochAndRound); - } - - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(CommitStore.CursedByRMN.selector); - bytes memory report; - s_commitStore.report(report, ++s_latestEpochAndRound); - } - - function test_InvalidRootRevert() public { - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(1, 4), - merkleRoot: bytes32(0) - }); - - vm.expectRevert(CommitStore.InvalidRoot.selector); - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - } - - function test_InvalidInterval_Revert() public { - CommitStore.Interval memory interval = CommitStore.Interval(2, 2); - CommitStore.CommitReport memory report = - CommitStore.CommitReport({priceUpdates: getEmptyPriceUpdates(), interval: interval, merkleRoot: bytes32(0)}); - - vm.expectRevert(abi.encodeWithSelector(CommitStore.InvalidInterval.selector, interval)); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - } - - function test_InvalidIntervalMinLargerThanMax_Revert() public { - CommitStore.Interval memory interval = CommitStore.Interval(1, 0); - CommitStore.CommitReport memory report = - CommitStore.CommitReport({priceUpdates: getEmptyPriceUpdates(), interval: interval, merkleRoot: bytes32(0)}); - - vm.expectRevert(abi.encodeWithSelector(CommitStore.InvalidInterval.selector, interval)); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - } - - function test_ZeroEpochAndRound_Revert() public { - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - interval: CommitStore.Interval(0, 0), - merkleRoot: bytes32(0) - }); - - vm.expectRevert(CommitStore.StaleReport.selector); - - s_commitStore.report(abi.encode(report), 0); - } - - function test_OnlyPriceUpdateStaleReport_Revert() public { - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - interval: CommitStore.Interval(0, 0), - merkleRoot: bytes32(0) - }); - - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - - vm.expectRevert(CommitStore.StaleReport.selector); - s_commitStore.report(abi.encode(report), s_latestEpochAndRound); - } - - function test_RootAlreadyCommitted_Revert() public { - CommitStore.CommitReport memory report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(1, 2), - merkleRoot: "Only a single root" - }); - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - - report = CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(3, 3), - merkleRoot: "Only a single root" - }); - - vm.expectRevert(CommitStore.RootAlreadyCommitted.selector); - - s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); - } -} - -contract CommitStore_verify is CommitStoreRealRMNSetup { - function test_NotBlessed_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - s_commitStore.report( - abi.encode( - CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(1, 2), - merkleRoot: leaves[0] - }) - ), - ++s_latestEpochAndRound - ); - bytes32[] memory proofs = new bytes32[](0); - // We have not blessed this root, should return 0. - uint256 timestamp = s_commitStore.verify(leaves, proofs, 0); - assertEq(uint256(0), timestamp); - } - - function test_Blessed_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - s_commitStore.report( - abi.encode( - CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(1, 2), - merkleRoot: leaves[0] - }) - ), - ++s_latestEpochAndRound - ); - // Bless that root. - IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); - taggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_commitStore), root: leaves[0]}); - vm.startPrank(BLESS_VOTE_ADDR); - s_rmn.voteToBless(taggedRoots); - bytes32[] memory proofs = new bytes32[](0); - uint256 timestamp = s_commitStore.verify(leaves, proofs, 0); - assertEq(BLOCK_TIME, timestamp); - } - - // Reverts - - function test_Paused_Revert() public { - s_commitStore.pause(); - - bytes32[] memory hashedLeaves = new bytes32[](0); - bytes32[] memory proofs = new bytes32[](0); - uint256 proofFlagBits = 0; - - vm.expectRevert(CommitStore.PausedError.selector); - s_commitStore.verify(hashedLeaves, proofs, proofFlagBits); - } - - function test_TooManyLeaves_Revert() public { - bytes32[] memory leaves = new bytes32[](258); - bytes32[] memory proofs = new bytes32[](0); - - vm.expectRevert(MerkleMultiProof.InvalidProof.selector); - - s_commitStore.verify(leaves, proofs, 0); - } -} - -contract CommitStore_isUnpausedAndRMNHealthy is CommitStoreSetup { - function test_RMN_Success() public { - // Test pausing - assertFalse(s_commitStore.paused()); - assertTrue(s_commitStore.isUnpausedAndNotCursed()); - s_commitStore.pause(); - assertTrue(s_commitStore.paused()); - assertFalse(s_commitStore.isUnpausedAndNotCursed()); - s_commitStore.unpause(); - assertFalse(s_commitStore.paused()); - assertTrue(s_commitStore.isUnpausedAndNotCursed()); - - // Test rmn - s_mockRMN.setGlobalCursed(true); - assertFalse(s_commitStore.isUnpausedAndNotCursed()); - s_mockRMN.setGlobalCursed(false); - // TODO: also test with s_mockRMN.setChainCursed(sourceChainSelector), - // also for other similar tests (e.g., OffRamp, OnRamp) - assertTrue(s_commitStore.isUnpausedAndNotCursed()); - - s_mockRMN.setGlobalCursed(true); - s_commitStore.pause(); - assertFalse(s_commitStore.isUnpausedAndNotCursed()); - } -} - -contract CommitStore_setLatestPriceEpochAndRound is CommitStoreSetup { - function test_SetLatestPriceEpochAndRound_Success() public { - uint40 latestRoundAndEpoch = 1782155; - - vm.expectEmit(); - emit CommitStore.LatestPriceEpochAndRoundSet( - uint40(s_commitStore.getLatestPriceEpochAndRound()), latestRoundAndEpoch - ); - - s_commitStore.setLatestPriceEpochAndRound(latestRoundAndEpoch); - - assertEq(uint40(s_commitStore.getLatestPriceEpochAndRound()), latestRoundAndEpoch); - } - - // Reverts - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - s_commitStore.setLatestPriceEpochAndRound(6723); - } -} 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 816862cbdfc..4d462adfe16 100644 --- a/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol +++ b/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol @@ -1,116 +1,305 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import "../commitStore/CommitStore.t.sol"; +import {IRMN} from "../../interfaces/IRMN.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; + +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {NonceManager} from "../../NonceManager.sol"; +import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; import "../helpers/MerkleHelper.sol"; -import "../offRamp/EVM2EVMOffRampSetup.t.sol"; -import "../onRamp/EVM2EVMOnRampSetup.t.sol"; +import "../offRamp/OffRampSetup.t.sol"; +import "../onRamp/OnRampSetup.t.sol"; + +/// @notice This E2E test implements the following scenario: +/// 1. Send multiple messages from multiple source chains to a single destination chain (2 messages from source chain 1 and 1 from +/// source chain 2). +/// 2. Commit multiple merkle roots (1 for each source chain). +/// 3. Batch execute all the committed messages. +contract E2E is OnRampSetup, OffRampSetup { + using Internal for Internal.Any2EVMRampMessage; + + Router internal s_sourceRouter2; + OnRampHelper internal s_onRamp2; + TokenAdminRegistry internal s_tokenAdminRegistry2; + NonceManager internal s_nonceManager2; + + bytes32 internal s_metadataHash2; + + mapping(address destPool => address sourcePool) internal s_sourcePoolByDestPool; + + function setUp() public virtual override(OnRampSetup, OffRampSetup) { + OnRampSetup.setUp(); + OffRampSetup.setUp(); + + // Deploy new source router for the new source chain + s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMN)); + + // Deploy new TokenAdminRegistry for the new source chain + s_tokenAdminRegistry2 = new TokenAdminRegistry(); + + // Deploy new token pools and set them on the new TokenAdminRegistry + for (uint256 i = 0; i < s_sourceTokens.length; ++i) { + address token = s_sourceTokens[i]; + address pool = address( + new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, address(s_sourceRouter2)) + ); + + s_sourcePoolByDestPool[s_destPoolBySourceToken[token]] = pool; + + _setPool( + s_tokenAdminRegistry2, token, pool, DEST_CHAIN_SELECTOR, s_destPoolByToken[s_destTokens[i]], s_destTokens[i] + ); + } + + for (uint256 i = 0; i < s_destTokens.length; ++i) { + address token = s_destTokens[i]; + address pool = s_destPoolByToken[token]; -contract E2E is EVM2EVMOnRampSetup, CommitStoreSetup, EVM2EVMOffRampSetup { - using Internal for Internal.EVM2EVMMessage; + _setPool( + s_tokenAdminRegistry2, token, pool, SOURCE_CHAIN_SELECTOR + 1, s_sourcePoolByDestPool[pool], s_sourceTokens[i] + ); + } - function setUp() public virtual override(EVM2EVMOnRampSetup, CommitStoreSetup, EVM2EVMOffRampSetup) { - EVM2EVMOnRampSetup.setUp(); - CommitStoreSetup.setUp(); - EVM2EVMOffRampSetup.setUp(); + s_nonceManager2 = new NonceManager(new address[](0)); - deployOffRamp(s_commitStore, s_destRouter, address(0)); + ( + // Deploy the new source chain onramp + // Outsource to shared helper function with OnRampSetup + s_onRamp2, + s_metadataHash2 + ) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR + 1, s_sourceRouter2, address(s_nonceManager2), address(s_tokenAdminRegistry2) + ); + + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(s_onRamp2); + s_nonceManager2.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + + // Enable destination chain on new source chain router + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + 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 + _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); + + // Enable source chains on offramp + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR, + isEnabled: true, + // Must match OnRamp address + onRamp: abi.encode(address(s_onRamp)) + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, + isEnabled: true, + onRamp: abi.encode(address(s_onRamp2)) + }); + + _setupMultipleOffRampsFromConfigs(sourceChainConfigs); } - function test_E2E_3MessagesSuccess_gas() public { + function test_E2E_3MessagesMMultiOffRampSuccess_gas() public { vm.pauseGasMetering(); - IERC20 token0 = IERC20(s_sourceTokens[0]); - IERC20 token1 = IERC20(s_sourceTokens[1]); - uint256 balance0Pre = token0.balanceOf(OWNER); - uint256 balance1Pre = token1.balanceOf(OWNER); - - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](3); - messages[0] = sendRequest(1); - messages[1] = sendRequest(2); - messages[2] = sendRequest(3); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); - // Asserts that the tokens have been sent and the fee has been paid. - assertEq(balance0Pre - messages.length * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER)); - assertEq(balance1Pre - messages.length * i_tokenAmount1, token1.balanceOf(OWNER)); - - bytes32 metaDataHash = s_offRamp.metadataHash(); - - bytes32[] memory hashedMessages = new bytes32[](3); - hashedMessages[0] = messages[0]._hash(metaDataHash); - messages[0].messageId = hashedMessages[0]; - hashedMessages[1] = messages[1]._hash(metaDataHash); - messages[1].messageId = hashedMessages[1]; - hashedMessages[2] = messages[2]._hash(metaDataHash); - messages[2].messageId = hashedMessages[2]; - - bytes32[] memory merkleRoots = new bytes32[](1); - merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages); - - address[] memory onRamps = new address[](1); - onRamps[0] = ON_RAMP_ADDRESS; - - bytes memory commitReport = abi.encode( - CommitStore.CommitReport({ - priceUpdates: getEmptyPriceUpdates(), - interval: CommitStore.Interval(messages[0].sequenceNumber, messages[2].sequenceNumber), + + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + // Scoped to sending to reduce stack pressure + { + IERC20 token0 = IERC20(s_sourceTokens[0]); + IERC20 token1 = IERC20(s_sourceTokens[1]); + + uint256 balance0Pre = token0.balanceOf(OWNER); + uint256 balance1Pre = token1.balanceOf(OWNER); + + // Send messages + messages1[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR, 1, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); + messages1[1] = _sendRequest(2, SOURCE_CHAIN_SELECTOR, 2, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); + messages2[0] = + _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); + + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); + // Asserts that the tokens have been sent and the fee has been paid. + assertEq( + balance0Pre - (messages1.length + messages2.length) * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER) + ); + assertEq(balance1Pre - (messages1.length + messages2.length) * i_tokenAmount1, token1.balanceOf(OWNER)); + } + + // Commit + + bytes32[] memory merkleRoots = new bytes32[](2); + + // Scoped to commit to reduce stack pressure + { + bytes32[] memory hashedMessages1 = new bytes32[](2); + hashedMessages1[0] = _hashMessage(messages1[0], abi.encode(address(s_onRamp))); + hashedMessages1[1] = _hashMessage(messages1[1], abi.encode(address(s_onRamp))); + bytes32[] memory hashedMessages2 = new bytes32[](1); + hashedMessages2[0] = _hashMessage(messages2[0], abi.encode(address(s_onRamp2))); + + merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); + merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); + + // TODO make these real sigs :) + IRMNRemote.Signature[] memory rmnSignatures = new IRMNRemote.Signature[](0); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR, + onRampAddress: abi.encode(address(s_onRamp)), + minSeqNr: messages1[0].header.sequenceNumber, + maxSeqNr: messages1[1].header.sequenceNumber, merkleRoot: merkleRoots[0] - }) - ); + }); + roots[1] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, + onRampAddress: abi.encode(address(s_onRamp2)), + minSeqNr: messages2[0].header.sequenceNumber, + maxSeqNr: messages2[0].header.sequenceNumber, + merkleRoot: merkleRoots[1] + }); - vm.resumeGasMetering(); - s_commitStore.report(commitReport, ++s_latestEpochAndRound); - vm.pauseGasMetering(); + OffRamp.CommitReport memory report = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: rmnSignatures, + rmnRawVs: 0 + }); - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_commitStore), root: merkleRoots[0]}), true); + vm.resumeGasMetering(); + _commit(report, ++s_latestSequenceNumber); + vm.pauseGasMetering(); + } - bytes32[] memory proofs = new bytes32[](0); - uint256 timestamp = s_commitStore.verify(merkleRoots, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); + // 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); - // We change the block time so when execute would e.g. use the current - // block time instead of the committed block time the value would be - // incorrect in the checks below. - vm.warp(BLOCK_TIME + 2000); + bytes32[] memory proofs = new bytes32[](0); + bytes32[] memory hashedLeaves = new bytes32[](1); + hashedLeaves[0] = merkleRoots[0]; - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); + uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, 2 ** 2 - 1); + assertEq(BLOCK_TIME, timestamp); + hashedLeaves[0] = merkleRoots[1]; + timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, hashedLeaves, proofs, 2 ** 2 - 1); + assertEq(BLOCK_TIME, timestamp); - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[1].sequenceNumber, messages[1].messageId, Internal.MessageExecutionState.SUCCESS, "" + // We change the block time so when execute would e.g. use the current + // block time instead of the committed block time the value would be + // incorrect in the checks below. + vm.warp(BLOCK_TIME + 2000); + } + + // Execute + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR + 1, messages2); + + vm.resumeGasMetering(); + vm.recordLogs(); + _execute(reports); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, + _hashMessage(messages1[0], abi.encode(address(s_onRamp))), + Internal.MessageExecutionState.SUCCESS, + "" ); - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[2].sequenceNumber, messages[2].messageId, Internal.MessageExecutionState.SUCCESS, "" + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, + _hashMessage(messages1[1], abi.encode(address(s_onRamp))), + Internal.MessageExecutionState.SUCCESS, + "" ); - Internal.ExecutionReport memory execReport = _generateReportFromMessages(messages); - vm.resumeGasMetering(); - s_offRamp.execute(execReport, new uint256[](0)); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR + 1, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, + _hashMessage(messages2[0], abi.encode(address(s_onRamp2))), + Internal.MessageExecutionState.SUCCESS, + "" + ); } - function sendRequest(uint64 expectedSeqNum) public returns (Internal.EVM2EVMMessage memory) { + function _sendRequest( + uint64 expectedSeqNum, + uint64 sourceChainSelector, + uint64 nonce, + bytes32 metadataHash, + Router router, + TokenAdminRegistry tokenAdminRegistry + ) public returns (Internal.Any2EVMRampMessage memory) { Client.EVM2AnyMessage memory message = _generateTokenMessage(); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + router.getFee(DEST_CHAIN_SELECTOR, message)); + IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); - IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), i_tokenAmount0 + expectedFee); - IERC20(s_sourceTokens[1]).approve(address(s_sourceRouter), i_tokenAmount1); + uint256 feeAmount = router.getFee(DEST_CHAIN_SELECTOR, message); message.receiver = abi.encode(address(s_receiver)); - Internal.EVM2EVMMessage memory msgEvent = - _messageToEvent(message, expectedSeqNum, expectedSeqNum, expectedFee, OWNER); + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( + message, + sourceChainSelector, + DEST_CHAIN_SELECTOR, + expectedSeqNum, + nonce, + feeAmount, + feeAmount, + OWNER, + metadataHash, + tokenAdminRegistry + ); vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedSeqNum, msgEvent); vm.resumeGasMetering(); - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - return msgEvent; + Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = + new Internal.Any2EVMTokenTransfer[](message.tokenAmounts.length); + + for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { + any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(msgEvent.tokenAmounts[i].sourcePoolAddress), + destTokenAddress: abi.decode(msgEvent.tokenAmounts[i].destTokenAddress, (address)), + extraData: msgEvent.tokenAmounts[i].extraData, + amount: msgEvent.tokenAmounts[i].amount, + destGasAmount: abi.decode(msgEvent.tokenAmounts[i].destExecData, (uint32)) + }); + } + + return Internal.Any2EVMRampMessage({ + header: Internal.RampMessageHeader({ + messageId: msgEvent.header.messageId, + sourceChainSelector: sourceChainSelector, + destChainSelector: DEST_CHAIN_SELECTOR, + sequenceNumber: msgEvent.header.sequenceNumber, + nonce: msgEvent.header.nonce + }), + sender: abi.encode(msgEvent.sender), + data: msgEvent.data, + receiver: abi.decode(msgEvent.receiver, (address)), + gasLimit: s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit, + tokenAmounts: any2EVMTokenTransfer + }); } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol deleted file mode 100644 index cbe8a35dce5..00000000000 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ /dev/null @@ -1,260 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {NonceManager} from "../../NonceManager.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import "../helpers/MerkleHelper.sol"; -import "../offRamp/EVM2EVMMultiOffRampSetup.t.sol"; -import "../onRamp/EVM2EVMMultiOnRampSetup.t.sol"; - -/// @notice This E2E test implements the following scenario: -/// 1. Send multiple messages from multiple source chains to a single destination chain (2 messages from source chain 1 and 1 from -/// source chain 2). -/// 2. Commit multiple merkle roots (1 for each source chain). -/// 3. Batch execute all the committed messages. -contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { - using Internal for Internal.Any2EVMRampMessage; - - Router internal s_sourceRouter2; - EVM2EVMMultiOnRampHelper internal s_onRamp2; - TokenAdminRegistry internal s_tokenAdminRegistry2; - NonceManager internal s_nonceManager2; - - bytes32 internal s_metadataHash2; - - mapping(address destPool => address sourcePool) internal s_sourcePoolByDestPool; - - function setUp() public virtual override(EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup) { - EVM2EVMMultiOnRampSetup.setUp(); - EVM2EVMMultiOffRampSetup.setUp(); - - // Deploy new source router for the new source chain - s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMN)); - - // Deploy new TokenAdminRegistry for the new source chain - s_tokenAdminRegistry2 = new TokenAdminRegistry(); - - // Deploy new token pools and set them on the new TokenAdminRegistry - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - address token = s_sourceTokens[i]; - address pool = address( - new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, address(s_sourceRouter2)) - ); - - s_sourcePoolByDestPool[s_destPoolBySourceToken[token]] = pool; - - _setPool( - s_tokenAdminRegistry2, token, pool, DEST_CHAIN_SELECTOR, s_destPoolByToken[s_destTokens[i]], s_destTokens[i] - ); - } - - for (uint256 i = 0; i < s_destTokens.length; ++i) { - address token = s_destTokens[i]; - address pool = s_destPoolByToken[token]; - - _setPool( - s_tokenAdminRegistry2, token, pool, SOURCE_CHAIN_SELECTOR + 1, s_sourcePoolByDestPool[pool], s_sourceTokens[i] - ); - } - - s_nonceManager2 = new NonceManager(new address[](0)); - - ( - // Deploy the new source chain onramp - // Outsource to shared helper function with EVM2EVMMultiOnRampSetup - s_onRamp2, - s_metadataHash2 - ) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR + 1, address(s_sourceRouter2), address(s_nonceManager2), address(s_tokenAdminRegistry2) - ); - - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(s_onRamp2); - s_nonceManager2.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) - ); - - // Enable destination chain on new source chain router - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - 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 - _deployOffRamp(s_destRouter, s_mockRMN, s_inboundNonceManager); - - // Enable source chains on offramp - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](2); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - isEnabled: true, - // Must match OnRamp address - onRamp: abi.encode(address(s_onRamp)) - }); - sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - isEnabled: true, - onRamp: abi.encode(address(s_onRamp2)) - }); - - _setupMultipleOffRampsFromConfigs(sourceChainConfigs); - } - - function test_E2E_3MessagesSuccess_gas() public { - vm.pauseGasMetering(); - IERC20 token0 = IERC20(s_sourceTokens[0]); - IERC20 token1 = IERC20(s_sourceTokens[1]); - uint256 balance0Pre = token0.balanceOf(OWNER); - uint256 balance1Pre = token1.balanceOf(OWNER); - - // Send messages - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - messages1[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR, 1, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); - messages1[1] = _sendRequest(2, SOURCE_CHAIN_SELECTOR, 2, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - messages2[0] = - _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); - // Asserts that the tokens have been sent and the fee has been paid. - assertEq( - balance0Pre - (messages1.length + messages2.length) * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER) - ); - assertEq(balance1Pre - (messages1.length + messages2.length) * i_tokenAmount1, token1.balanceOf(OWNER)); - - // Commit - bytes32[] memory hashedMessages1 = new bytes32[](2); - hashedMessages1[0] = messages1[0]._hash(abi.encode(address(s_onRamp))); - hashedMessages1[1] = messages1[1]._hash(abi.encode(address(s_onRamp))); - bytes32[] memory hashedMessages2 = new bytes32[](1); - hashedMessages2[0] = messages2[0]._hash(abi.encode(address(s_onRamp2))); - - bytes32[] memory merkleRoots = new bytes32[](2); - merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); - merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); - - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](2); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(messages1[0].header.sequenceNumber, messages1[1].header.sequenceNumber), - merkleRoot: merkleRoots[0] - }); - roots[1] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - interval: EVM2EVMMultiOffRamp.Interval(messages2[0].header.sequenceNumber, messages2[0].header.sequenceNumber), - merkleRoot: merkleRoots[1] - }); - - EVM2EVMMultiOffRamp.CommitReport memory report = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - - vm.resumeGasMetering(); - _commit(report, ++s_latestSequenceNumber); - vm.pauseGasMetering(); - - 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]; - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); - hashedLeaves[0] = merkleRoots[1]; - timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, hashedLeaves, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); - - // We change the block time so when execute would e.g. use the current - // block time instead of the committed block time the value would be - // incorrect in the checks below. - vm.warp(BLOCK_TIME + 2000); - - // Execute - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - SOURCE_CHAIN_SELECTOR, - messages1[0].header.sequenceNumber, - messages1[0].header.messageId, - Internal.MessageExecutionState.SUCCESS, - "" - ); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - SOURCE_CHAIN_SELECTOR, - messages1[1].header.sequenceNumber, - messages1[1].header.messageId, - Internal.MessageExecutionState.SUCCESS, - "" - ); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - SOURCE_CHAIN_SELECTOR + 1, - messages2[0].header.sequenceNumber, - messages2[0].header.messageId, - Internal.MessageExecutionState.SUCCESS, - "" - ); - - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR + 1, messages2); - - vm.resumeGasMetering(); - _execute(reports); - } - - function _sendRequest( - uint64 expectedSeqNum, - uint64 sourceChainSelector, - uint64 nonce, - bytes32 metadataHash, - Router router, - TokenAdminRegistry tokenAdminRegistry - ) public returns (Internal.Any2EVMRampMessage memory) { - Client.EVM2AnyMessage memory message = _generateTokenMessage(); - uint256 expectedFee = router.getFee(DEST_CHAIN_SELECTOR, message); - - IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + expectedFee); - IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); - - message.receiver = abi.encode(address(s_receiver)); - Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( - message, - sourceChainSelector, - DEST_CHAIN_SELECTOR, - expectedSeqNum, - nonce, - expectedFee, - OWNER, - metadataHash, - tokenAdminRegistry - ); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent); - - vm.resumeGasMetering(); - router.ccipSend(DEST_CHAIN_SELECTOR, message); - vm.pauseGasMetering(); - - uint256 gasLimit = s_priceRegistry.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; - - return Internal.Any2EVMRampMessage({ - header: Internal.RampMessageHeader({ - messageId: msgEvent.header.messageId, - sourceChainSelector: sourceChainSelector, - destChainSelector: DEST_CHAIN_SELECTOR, - sequenceNumber: msgEvent.header.sequenceNumber, - nonce: msgEvent.header.nonce - }), - sender: abi.encode(msgEvent.sender), - data: msgEvent.data, - receiver: abi.decode(msgEvent.receiver, (address)), - gasLimit: gasLimit, - tokenAmounts: msgEvent.tokenAmounts - }); - } -} diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol new file mode 100644 index 00000000000..36ccb14da93 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -0,0 +1,2321 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; +import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; +import {FeeQuoterFeeSetup, FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; + +import {Vm} from "forge-std/Vm.sol"; + +contract FeeQuoter_constructor is FeeQuoterSetup { + function test_Setup_Success() public virtual { + address[] memory priceUpdaters = new address[](2); + priceUpdaters[0] = STRANGER; + priceUpdaters[1] = OWNER; + address[] memory feeTokens = new address[](2); + feeTokens[0] = s_sourceTokens[0]; + feeTokens[1] = s_sourceTokens[1]; + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + tokenPriceFeedUpdates[1] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[1], s_dataFeedByToken[s_sourceTokens[1]], 6); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + tokenPriceStalenessThreshold: uint32(TWELVE_HOURS) + }); + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + priceUpdaters, + feeTokens, + tokenPriceFeedUpdates, + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + destChainConfigArgs + ); + + _assertFeeQuoterStaticConfigsEqual(s_feeQuoter.getStaticConfig(), staticConfig); + assertEq(feeTokens, s_feeQuoter.getFeeTokens()); + assertEq(priceUpdaters, s_feeQuoter.getAllAuthorizedCallers()); + assertEq(s_feeQuoter.typeAndVersion(), "FeeQuoter 1.6.0-dev"); + + _assertTokenPriceFeedConfigEquality( + tokenPriceFeedUpdates[0].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[0]) + ); + + _assertTokenPriceFeedConfigEquality( + tokenPriceFeedUpdates[1].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[1]) + ); + + assertEq( + s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].token) + ); + + assertEq( + s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].token) + ); + + FeeQuoter.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = s_feeQuoterTokenTransferFeeConfigArgs[0]; + for (uint256 i = 0; i < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++i) { + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; + + _assertTokenTransferFeeConfigEqual( + tokenFeeArgs.tokenTransferFeeConfig, + s_feeQuoter.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) + ); + } + + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + FeeQuoter.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + + _assertFeeQuoterDestChainConfigsEqual(expectedConfig, s_feeQuoter.getDestChainConfig(destChainSelector)); + } + } + + function test_InvalidStalenessThreshold_Revert() public { + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + tokenPriceStalenessThreshold: 0 + }); + + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); + + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + new address[](0), + new address[](0), + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) + ); + } + + function test_InvalidLinkTokenEqZeroAddress_Revert() public { + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: address(0), + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + tokenPriceStalenessThreshold: uint32(TWELVE_HOURS) + }); + + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); + + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + new address[](0), + new address[](0), + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) + ); + } + + function test_InvalidMaxFeeJuelsPerMsg_Revert() public { + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: 0, + tokenPriceStalenessThreshold: uint32(TWELVE_HOURS) + }); + + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); + + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + new address[](0), + new address[](0), + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) + ); + } +} + +contract FeeQuoter_getTokenPrices is FeeQuoterSetup { + function test_GetTokenPrices_Success() public view { + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + + address[] memory tokens = new address[](3); + tokens[0] = s_sourceTokens[0]; + tokens[1] = s_sourceTokens[1]; + tokens[2] = s_weth; + + Internal.TimestampedPackedUint224[] memory tokenPrices = s_feeQuoter.getTokenPrices(tokens); + + assertEq(tokenPrices.length, 3); + assertEq(tokenPrices[0].value, priceUpdates.tokenPriceUpdates[0].usdPerToken); + assertEq(tokenPrices[1].value, priceUpdates.tokenPriceUpdates[1].usdPerToken); + assertEq(tokenPrices[2].value, priceUpdates.tokenPriceUpdates[2].usdPerToken); + } +} + +contract FeeQuoter_getTokenPrice is FeeQuoterSetup { + function test_GetTokenPriceFromFeed_Success() public { + uint256 originalTimestampValue = block.timestamp; + + // Above staleness threshold + vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().tokenPriceStalenessThreshold + 1); + + address sourceToken = _initialiseSingleTokenPriceFeed(); + + vm.expectCall(s_dataFeedByToken[sourceToken], abi.encodeWithSelector(MockV3Aggregator.latestRoundData.selector)); + + Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_feeQuoter.getTokenPrice(sourceToken); + + // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer.value, uint224(1e18)); + assertEq(tokenPriceAnswer.timestamp, uint32(originalTimestampValue)); + } + + function test_GetTokenPrice_LocalMoreRecent_Success() public { + uint256 originalTimestampValue = block.timestamp; + + 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)}); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + update.tokenPriceUpdates[0].sourceToken, update.tokenPriceUpdates[0].usdPerToken, block.timestamp + ); + + s_feeQuoter.updatePrices(update); + + vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().tokenPriceStalenessThreshold + 10); + + Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); + + //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)); + } +} + +contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { + function test_GetValidatedTokenPrice_Success() public view { + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + address token = priceUpdates.tokenPriceUpdates[0].sourceToken; + + uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); + + assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); + } + + function test_GetValidatedTokenPriceFromFeed_Success() public { + uint256 originalTimestampValue = block.timestamp; + + // Right below staleness threshold + vm.warp(originalTimestampValue + TWELVE_HOURS); + + address sourceToken = _initialiseSingleTokenPriceFeed(); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); + + // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer, uint224(1e18)); + } + + function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() public { + uint256 originalTimestampValue = block.timestamp; + + // Right above staleness threshold + vm.warp(originalTimestampValue + TWELVE_HOURS + 1); + + address sourceToken = _initialiseSingleTokenPriceFeed(); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); + + // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer, uint224(1e18)); + } + + function test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is: uint224.MAX_VALUE * (10 ** (36 - 18 - 18)) + assertEq(tokenPriceAnswer, uint224(type(uint224).max)); + } + + function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 6); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 6); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e6) -> expected 1e30 + assertEq(tokenPriceAnswer, uint224(1e30)); + } + + function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 24); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 24); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e24) -> expected 1e12 + assertEq(tokenPriceAnswer, uint224(1e12)); + } + + function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer, uint224(1e18)); + } + + function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 0); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 0); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e31 (0 decimal token) - unit is (1e18 * 1e18 / 1e0) -> expected 1e36 + assertEq(tokenPriceAnswer, uint224(1e67)); + } + + function test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 20); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 20); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e20) -> expected 1e14 + assertEq(tokenPriceAnswer, uint224(1e14)); + } + + function test_StaleFeeToken_Success() public { + vm.warp(block.timestamp + TWELVE_HOURS + 1); + + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + address token = priceUpdates.tokenPriceUpdates[0].sourceToken; + + uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); + + assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); + } + + // Reverts + + function test_OverflowFeedPrice_Revert() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); + s_feeQuoter.getValidatedTokenPrice(tokenAddress); + } + + function test_UnderflowFeedPrice_Revert() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); + s_feeQuoter.getValidatedTokenPrice(tokenAddress); + } + + function test_TokenNotSupported_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); + } + + function test_TokenNotSupportedFeed_Revert() public { + address sourceToken = _initialiseSingleTokenPriceFeed(); + MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: sourceToken, usdPerToken: 0}); + + s_feeQuoter.updatePrices(priceUpdates); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, sourceToken)); + s_feeQuoter.getValidatedTokenPrice(sourceToken); + } +} + +contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { + function test_ApplyFeeTokensUpdates_Success() public { + address[] memory feeTokens = new address[](1); + feeTokens[0] = s_sourceTokens[1]; + + vm.expectEmit(); + emit FeeQuoter.FeeTokenAdded(feeTokens[0]); + + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + assertEq(s_feeQuoter.getFeeTokens().length, 3); + assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); + + // add same feeToken is no-op + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + assertEq(s_feeQuoter.getFeeTokens().length, 3); + assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); + + vm.expectEmit(); + emit FeeQuoter.FeeTokenRemoved(feeTokens[0]); + + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + assertEq(s_feeQuoter.getFeeTokens().length, 2); + + // removing already removed feeToken is no-op and does not emit an event + vm.recordLogs(); + + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + assertEq(s_feeQuoter.getFeeTokens().length, 2); + + vm.assertEq(vm.getRecordedLogs().length, 0); + + // Removing and adding the same fee token is allowed and emits both events + // Add it first + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + + vm.expectEmit(); + emit FeeQuoter.FeeTokenRemoved(feeTokens[0]); + vm.expectEmit(); + emit FeeQuoter.FeeTokenAdded(feeTokens[0]); + + s_feeQuoter.applyFeeTokensUpdates(feeTokens, feeTokens); + } + + function test_OnlyCallableByOwner_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.applyFeeTokensUpdates(new address[](0), new address[](0)); + } +} + +contract FeeQuoter_updatePrices is FeeQuoterSetup { + function test_OnlyTokenPrice_Success() public { + 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: 4e18}); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + update.tokenPriceUpdates[0].sourceToken, update.tokenPriceUpdates[0].usdPerToken, block.timestamp + ); + + s_feeQuoter.updatePrices(update); + + assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); + } + + function test_OnlyGasPrice_Success() public { + Internal.PriceUpdates memory update = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), + gasPriceUpdates: new Internal.GasPriceUpdate[](1) + }); + update.gasPriceUpdates[0] = + Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); + + vm.expectEmit(); + emit FeeQuoter.UsdPerUnitGasUpdated( + update.gasPriceUpdates[0].destChainSelector, update.gasPriceUpdates[0].usdPerUnitGas, block.timestamp + ); + + s_feeQuoter.updatePrices(update); + + assertEq( + s_feeQuoter.getDestinationChainGasPrice(DEST_CHAIN_SELECTOR).value, update.gasPriceUpdates[0].usdPerUnitGas + ); + } + + function test_UpdateMultiplePrices_Success() 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}); + tokenPriceUpdates[2] = Internal.TokenPriceUpdate({sourceToken: address(12345), usdPerToken: 1e18}); + + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](3); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2e6}); + gasPriceUpdates[1] = Internal.GasPriceUpdate({destChainSelector: SOURCE_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); + gasPriceUpdates[2] = Internal.GasPriceUpdate({destChainSelector: 12345, usdPerUnitGas: 1e18}); + + Internal.PriceUpdates memory update = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); + + for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + update.tokenPriceUpdates[i].sourceToken, update.tokenPriceUpdates[i].usdPerToken, block.timestamp + ); + } + for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { + vm.expectEmit(); + emit FeeQuoter.UsdPerUnitGasUpdated( + update.gasPriceUpdates[i].destChainSelector, update.gasPriceUpdates[i].usdPerUnitGas, block.timestamp + ); + } + + s_feeQuoter.updatePrices(update); + + for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { + assertEq( + s_feeQuoter.getTokenPrice(update.tokenPriceUpdates[i].sourceToken).value, tokenPriceUpdates[i].usdPerToken + ); + } + for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { + assertEq( + s_feeQuoter.getDestinationChainGasPrice(update.gasPriceUpdates[i].destChainSelector).value, + gasPriceUpdates[i].usdPerUnitGas + ); + } + } + + function test_UpdatableByAuthorizedCaller_Success() public { + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); + + // Revert when caller is not authorized + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_feeQuoter.updatePrices(priceUpdates); + + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = STRANGER; + vm.startPrank(OWNER); + s_feeQuoter.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) + ); + + // Stranger is now an authorized caller to update prices + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + priceUpdates.tokenPriceUpdates[0].sourceToken, priceUpdates.tokenPriceUpdates[0].usdPerToken, block.timestamp + ); + s_feeQuoter.updatePrices(priceUpdates); + + assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, priceUpdates.tokenPriceUpdates[0].usdPerToken); + + vm.startPrank(OWNER); + s_feeQuoter.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: new address[](0), removedCallers: priceUpdaters}) + ); + + // Revert when authorized caller is removed + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_feeQuoter.updatePrices(priceUpdates); + } + + // Reverts + + function test_OnlyCallableByUpdater_Revert() public { + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_feeQuoter.updatePrices(priceUpdates); + } +} + +contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { + function test_ConvertTokenAmount_Success() public view { + Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + uint256 amount = 3e16; + uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) + / uint256(initialPriceUpdates.tokenPriceUpdates[0].usdPerToken); + uint256 expected = (amount * conversionRate) / 1e18; + assertEq(s_feeQuoter.convertTokenAmount(s_weth, amount, s_sourceTokens[0]), expected); + } + + function test_Fuzz_ConvertTokenAmount_Success( + uint256 feeTokenAmount, + uint224 usdPerFeeToken, + uint160 usdPerLinkToken, + uint224 usdPerUnitGas + ) public { + vm.assume(usdPerFeeToken > 0); + vm.assume(usdPerLinkToken > 0); + // We bound the max fees to be at most uint96.max link. + feeTokenAmount = bound(feeTokenAmount, 0, (uint256(type(uint96).max) * usdPerLinkToken) / usdPerFeeToken); + + address feeToken = address(1); + address linkToken = address(2); + address[] memory feeTokens = new address[](1); + feeTokens[0] = feeToken; + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + + Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](2); + tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: feeToken, usdPerToken: usdPerFeeToken}); + tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: linkToken, usdPerToken: usdPerLinkToken}); + + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: usdPerUnitGas}); + + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); + + s_feeQuoter.updatePrices(priceUpdates); + + uint256 linkFee = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, linkToken); + assertEq(linkFee, (feeTokenAmount * usdPerFeeToken) / usdPerLinkToken); + } + + // Reverts + + function test_LinkTokenNotSupported_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.convertTokenAmount(s_sourceTokens[0], 3e16, DUMMY_CONTRACT_ADDRESS); + } +} + +contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { + function test_GetFeeTokenAndGasPrices_Success() public view { + (uint224 feeTokenPrice, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); + + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + + assertEq(feeTokenPrice, s_sourceTokenPrices[0]); + assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); + } + + function test_StalenessCheckDisabled_Success() public { + uint64 neverStaleChainSelector = 345678; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainSelector = neverStaleChainSelector; + destChainConfigArgs[0].destChainConfig.gasPriceStalenessThreshold = 0; // disables the staleness check + + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: neverStaleChainSelector, usdPerUnitGas: 999}); + + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); + s_feeQuoter.updatePrices(priceUpdates); + + // this should have no affect! But we do it anyway to make sure the staleness check is disabled + vm.warp(block.timestamp + 52_000_000 weeks); // 1M-ish years + + (, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, neverStaleChainSelector); + + assertEq(gasPrice, 999); + } + + function test_ZeroGasPrice_Success() public { + uint64 zeroGasDestChainSelector = 345678; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainSelector = zeroGasDestChainSelector; + + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: zeroGasDestChainSelector, usdPerUnitGas: 0}); + + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); + s_feeQuoter.updatePrices(priceUpdates); + + (, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, zeroGasDestChainSelector); + + assertEq(gasPrice, 0); + } + + function test_UnsupportedChain_Revert() 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 { + uint256 diff = TWELVE_HOURS + 1; + vm.warp(block.timestamp + diff); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff)); + s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR); + } +} + +contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { + function test_ZeroFeeds_Success() public { + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); + vm.recordLogs(); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + // Verify no log emissions + assertEq(logEntries.length, 0); + } + + function test_SingleFeedUpdate_Success() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken)); + + vm.expectEmit(); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + } + + function test_MultipleFeedUpdate_Success() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); + + for (uint256 i = 0; i < 2; ++i) { + tokenPriceFeedUpdates[i] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[i], s_dataFeedByToken[s_sourceTokens[i]], 18); + + _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[i].sourceToken)); + + vm.expectEmit(); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[i].sourceToken, tokenPriceFeedUpdates[i].feedConfig); + } + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[1].sourceToken), tokenPriceFeedUpdates[1].feedConfig + ); + } + + function test_FeedUnset_Success() public { + Internal.TimestampedPackedUint224 memory priceQueryInitial = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); + assertFalse(priceQueryInitial.value == 0); + assertFalse(priceQueryInitial.timestamp == 0); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + + tokenPriceFeedUpdates[0].feedConfig.dataFeedAddress = address(0); + vm.expectEmit(); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + + // Price data should remain after a feed has been set->unset + Internal.TimestampedPackedUint224 memory priceQueryPostUnsetFeed = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); + assertEq(priceQueryPostUnsetFeed.value, priceQueryInitial.value); + assertEq(priceQueryPostUnsetFeed.timestamp, priceQueryInitial.timestamp); + } + + function test_FeedNotUpdated() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + } + + // Reverts + + function test_FeedUpdatedByNonOwner_Revert() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + } +} + +contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { + function test_Fuzz_applyDestChainConfigUpdates_Success( + FeeQuoter.DestChainConfigArgs memory destChainConfigArgs + ) public { + vm.assume(destChainConfigArgs.destChainSelector != 0); + vm.assume(destChainConfigArgs.destChainConfig.maxPerMsgGasLimit != 0); + destChainConfigArgs.destChainConfig.defaultTxGasLimit = uint32( + bound( + destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit + ) + ); + destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + + bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; + + FeeQuoter.DestChainConfigArgs[] memory newDestChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + newDestChainConfigArgs[0] = destChainConfigArgs; + + if (isNewChain) { + vm.expectEmit(); + emit FeeQuoter.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); + } else { + vm.expectEmit(); + emit FeeQuoter.DestChainConfigUpdated(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); + } + + s_feeQuoter.applyDestChainConfigUpdates(newDestChainConfigArgs); + + _assertFeeQuoterDestChainConfigsEqual( + destChainConfigArgs.destChainConfig, s_feeQuoter.getDestChainConfig(destChainConfigArgs.destChainSelector) + ); + } + + function test_applyDestChainConfigUpdates_Success() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](2); + destChainConfigArgs[0] = _generateFeeQuoterDestChainConfigArgs()[0]; + destChainConfigArgs[0].destChainConfig.isEnabled = false; + destChainConfigArgs[1] = _generateFeeQuoterDestChainConfigArgs()[0]; + destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; + + vm.expectEmit(); + emit FeeQuoter.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); + vm.expectEmit(); + emit FeeQuoter.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); + + vm.recordLogs(); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + FeeQuoter.DestChainConfig memory gotDestChainConfig0 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory gotDestChainConfig1 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + + assertEq(vm.getRecordedLogs().length, 2); + _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); + _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); + } + + function test_applyDestChainConfigUpdatesZeroIntput_Success() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](0); + + vm.recordLogs(); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainConfig.defaultTxGasLimit = 0; + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + // Allow setting to the max value + destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + // Revert when exceeding max value + destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit + 1; + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainSelector = 0; + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + 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); + } +} + +contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { + function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { + uint256 dataAvailabilityCostUSD = + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; + uint256 expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + + // Test that the cost is destnation chain specific + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = + destChainConfig.destDataAvailabilityOverheadGas * 2; + destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = + destChainConfig.destGasPerDataAvailabilityByte * 2; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = + destChainConfig.destDataAvailabilityMultiplierBps * 2; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + uint256 dataAvailabilityCostUSD2 = + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; + expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD2); + assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); + } + + function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { + uint256 dataAvailabilityCostUSD = + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 dataAvailabilityLengthBytes = + Internal.MESSAGE_FIXED_BYTES + 100 + (5 * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; + uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; + uint256 expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + } + + function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + + assertEq(dataAvailabilityCostUSD, 0); + } + + function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( + uint64 messageDataLength, + uint32 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) public view { + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead + ); + + assertEq(0, dataAvailabilityCostUSD); + } + + function test_Fuzz_CalculateDataAvailabilityCost_Success( + uint64 destChainSelector, + uint32 destDataAvailabilityOverheadGas, + uint16 destGasPerDataAvailabilityByte, + uint16 destDataAvailabilityMultiplierBps, + uint112 dataAvailabilityGasPrice, + uint64 messageDataLength, + uint32 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) public { + vm.assume(destChainSelector != 0); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(destChainSelector); + destChainConfigArgs[0] = + FeeQuoter.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; + destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; + destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; + destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; + destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( + destChainConfigArgs[0].destChainSelector, + dataAvailabilityGasPrice, + messageDataLength, + numberOfTokens, + tokenTransferBytesOverhead + ); + + uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + + uint256 dataAvailabilityGas = + destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; + uint256 expectedDataAvailabilityCostUSD = + dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + } +} + +contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { + function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( + FeeQuoter.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg + ) public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; + + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth + ); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; + premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); + + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth + ); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](2); + premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; + premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); + premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); + + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth + ); + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth + ); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) + ); + assertEq( + premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(2)) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { + vm.recordLogs(); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](0)); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_OnlyCallableByOwnerOrAdmin_Revert() public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + } +} + +contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { + function test_Fuzz_ApplyTokenTransferFeeConfig_Success( + FeeQuoter.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs + ) public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(2, 2); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; + + for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { + for (uint256 j = 0; j < tokenTransferFeeConfigs.length; ++j) { + tokenTransferFeeConfigs[j].destBytesOverhead = uint32( + bound(tokenTransferFeeConfigs[j].destBytesOverhead, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, type(uint32).max) + ); + address feeToken = s_sourceTokens[j]; + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].token = feeToken; + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; + + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] + ); + } + } + + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigs[i], + s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token + ) + ); + } + } + + function test_ApplyTokenTransferFeeConfig_Success() public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 2); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 6, + maxFeeUSDCents: 7, + deciBps: 8, + destGasOverhead: 9, + destBytesOverhead: 312, + isEnabled: true + }); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 12, + maxFeeUSDCents: 13, + deciBps: 14, + destGasOverhead: 15, + destBytesOverhead: 394, + isEnabled: true + }); + + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig + ); + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig + ); + + FeeQuoter.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = + new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0); + s_feeQuoter.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); + + FeeQuoter.TokenTransferFeeConfig memory config0 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + FeeQuoter.TokenTransferFeeConfig memory config1 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token + ); + + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig, config0 + ); + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 + ); + + // Remove only the first token and validate only the first token is removed + tokensToRemove = new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](1); + tokensToRemove[0] = FeeQuoter.TokenTransferFeeConfigRemoveArgs({ + destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, + token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + }); + + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigDeleted( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + + s_feeQuoter.applyTokenTransferFeeConfigUpdates(new FeeQuoter.TokenTransferFeeConfigArgs[](0), tokensToRemove); + + config0 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + config1 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token + ); + + FeeQuoter.TokenTransferFeeConfig memory emptyConfig; + + _assertTokenTransferFeeConfigEqual(emptyConfig, config0); + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 + ); + } + + function test_ApplyTokenTransferFeeZeroInput() public { + vm.recordLogs(); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + new FeeQuoter.TokenTransferFeeConfigArgs[](0), new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_OnlyCallableByOwnerOrAdmin_Revert() public { + vm.startPrank(STRANGER); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; + + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + } + + function test_InvalidDestBytesOverhead_Revert() public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 6, + maxFeeUSDCents: 7, + deciBps: 8, + destGasOverhead: 9, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1), + isEnabled: true + }); + + vm.expectRevert( + abi.encodeWithSelector( + FeeQuoter.InvalidDestBytesOverhead.selector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead + ) + ); + + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + } +} + +contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { + using USDPriceWith18Decimals for uint224; + + function test_NoTokenTransferChargesZeroFee_Success() 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); + + assertEq(0, feeUSDWei); + assertEq(0, destGasOverhead); + assertEq(0, destBytesOverhead); + } + + function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); + + // Get config to assert it isn't set + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + assertFalse(transferFeeConfig.isEnabled); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + // Assert that the default values are used + assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); + assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); + assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); + } + + function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(_configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_FeeTokenBpsFee_Success() public view { + uint256 tokenAmount = 10000e18; + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + uint256 usdWei = _calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); + uint256 bpsUSDWei = _applyBpsRatio( + usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_CustomTokenBpsFee_Success() public view { + uint256 tokenAmount = 200000e18; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](1), + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); + + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + uint256 usdWei = _calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); + uint256 bpsUSDWei = _applyBpsRatio( + usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_ZeroFeeConfigChargesMinFee_Success() public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), + isEnabled: true + }); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + // if token charges 0 bps, it should cost minFee to transfer + assertEq( + _configUSDCentToWei( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.minFeeUSDCents + ), + feeUSDWei + ); + assertEq(0, destGasOverhead); + assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); + } + + function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { + // It shouldn't be possible to pay materially lower fees by splitting up the transfers. + // Note it is possible to pay higher fees since the minimum fees are added. + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + transfers = bound(transfers, 1, destChainConfig.maxNumberOfTokensPerMsg); + // Cap amount to avoid overflow + amount = bound(amount, 0, 1e36); + Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); + for (uint256 i = 0; i < transfers; ++i) { + multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); + } + Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); + single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); + + address feeToken = s_sourceRouter.getWrappedNative(); + + (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); + (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); + + // Note that there can be a rounding error once per split. + assertGe(feeMultipleUSDWei, (feeSingleUSDWei - destChainConfig.maxNumberOfTokensPerMsg)); + assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); + assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); + } + + function test_MixedTokenTransferFee_Success() public view { + address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; + uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; + FeeQuoter.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) + ]; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](3), + feeToken: s_sourceRouter.getWrappedNative(), + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + uint256 expectedTotalGas = 0; + uint256 expectedTotalBytes = 0; + + // Start with small token transfers, total bps fee is lower than min token transfer fee + for (uint256 i = 0; i < testTokens.length; ++i) { + message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]); + + expectedTotalGas += tokenTransferFeeConfig.destGasOverhead == 0 + ? DEFAULT_TOKEN_DEST_GAS_OVERHEAD + : tokenTransferFeeConfig.destGasOverhead; + expectedTotalBytes += tokenTransferFeeConfig.destBytesOverhead == 0 + ? DEFAULT_TOKEN_BYTES_OVERHEAD + : tokenTransferFeeConfig.destBytesOverhead; + } + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); + + uint256 expectedFeeUSDWei = 0; + for (uint256 i = 0; i < testTokens.length; ++i) { + expectedFeeUSDWei += _configUSDCentToWei( + tokenTransferFeeConfigs[i].minFeeUSDCents == 0 + ? DEFAULT_TOKEN_FEE_USD_CENTS + : tokenTransferFeeConfigs[i].minFeeUSDCents + ); + } + + assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 1"); + assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 1"); + assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 1"); + + // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee + message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); + + uint256 token0USDWei = _applyBpsRatio( + _calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps + ); + uint256 token1USDWei = _configUSDCentToWei(DEFAULT_TOKEN_FEE_USD_CENTS); + + (feeUSDWei, destGasOverhead, destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); + expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); + + assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 2"); + assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 2"); + assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 2"); + + // Set 2nd token transfer to a large amount that is higher than maxFeeUSD + message.tokenAmounts[2] = Client.EVMTokenAmount({token: testTokens[2], amount: 1e36}); + + (feeUSDWei, destGasOverhead, destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); + expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].maxFeeUSDCents); + + assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 3"); + assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 3"); + assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 3"); + } +} + +contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { + using USDPriceWith18Decimals for uint224; + + function test_EmptyMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = testTokens[i]; + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + 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 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_ZeroDataAvailabilityMultiplier_Success() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + destChainConfigArgs[0] = + FeeQuoter.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + + 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 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; + assertEq(totalPriceInFeeToken, feeAmount); + } + + function test_HighGasMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 customGasLimit = MAX_GAS_LIMIT; + uint256 customDataSize = MAX_DATA_SIZE; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: new bytes(customDataSize), + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: testTokens[i], + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) + }); + + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + 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 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_SingleTokenMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 tokenAmount = 10000e18; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + message.feeToken = testTokens[i]; + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + uint32 destBytesOverhead = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; + uint32 tokenBytesOverhead = + destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; + + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; + 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 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, + USD_PER_DATA_AVAILABILITY_GAS, + message.data.length, + message.tokenAmounts.length, + tokenBytesOverhead + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_MessageWithDataAndTokenTransfer_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 customGasLimit = 1_000_000; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](2), + feeToken: testTokens[i], + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) + }); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount + message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount + message.data = "random bits and bytes that should be factored into the cost of the message"; + + uint32 tokenGasOverhead = 0; + uint32 tokenBytesOverhead = 0; + for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { + tokenGasOverhead += + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; + uint32 destBytesOverhead = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destBytesOverhead; + 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,,) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); + uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, + USD_PER_DATA_AVAILABILITY_GAS, + message.data.length, + message.tokenAmounts.length, + tokenBytesOverhead + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message)); + } + } + + function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { + // Update config to enforce allowOutOfOrderExecution = defaultVal. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = enforce; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) + ); + + // If enforcement is on, only true should be allowed. + if (enforce && !allowOutOfOrderExecution) { + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + } + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + // Reverts + + function test_DestinationChainNotEnabled_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); + } + + function test_EnforceOutOfOrder_Revert() public { + // Update config to enforce allowOutOfOrderExecution = true. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + vm.stopPrank(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // Empty extraArgs to should revert since it enforceOutOfOrder is true. + message.extraArgs = ""; + + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_MessageTooLarge_Revert() 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)); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_TooManyTokens_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint256 tooMany = MAX_TOKENS_LENGTH + 1; + message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); + vm.expectRevert(FeeQuoter.UnsupportedNumberOfTokens.selector); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + // Asserts gasLimit must be <=maxGasLimit + function test_MessageGasLimitTooHigh_Revert() 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 { + address notAFeeToken = address(0x111111); + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); + message.feeToken = notAFeeToken; + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, notAFeeToken)); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_InvalidEVMAddress_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.receiver = abi.encode(type(uint208).max); + + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } +} + +contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { + using USDPriceWith18Decimals for uint224; + + function setUp() public virtual override { + super.setUp(); + } + + function test_processMessageArgs_WithLinkTokenAmount_Success() public view { + ( + uint256 msgFeeJuels, + /* bool isOutOfOrderExecution */ + , + /* bytes memory convertedExtraArgs */ + , + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + // LINK + s_sourceTokens[0], + MAX_MSG_FEES_JUELS, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); + } + + function test_processMessageArgs_WithConvertedTokenAmount_Success() public view { + address feeToken = s_sourceTokens[1]; + uint256 feeTokenAmount = 10_000 gwei; + uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); + + ( + uint256 msgFeeJuels, + /* bool isOutOfOrderExecution */ + , + /* bytes memory convertedExtraArgs */ + , + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + feeToken, + feeTokenAmount, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(msgFeeJuels, expectedConvertedAmount); + } + + function test_processMessageArgs_WithEmptyEVMExtraArgs_Success() public view { + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(isOutOfOrderExecution, false); + assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); + } + + function test_processMessageArgs_WithEVMExtraArgsV1_Success() public view { + bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); + + ( + /* 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) + ); + + assertEq(isOutOfOrderExecution, false); + assertEq( + convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + ); + } + + function test_processMessageArgs_WitEVMExtraArgsV2_Success() public view { + bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); + + ( + /* 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) + ); + + assertEq(isOutOfOrderExecution, true); + assertEq( + convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + ); + } + + // Reverts + + function test_processMessageArgs_MessageFeeTooHigh_Revert() public { + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + ); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + MAX_MSG_FEES_JUELS + 1, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_InvalidExtraArgs_Revert() public { + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + "abcde", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_MalformedEVMExtraArgs_Revert() public { + // abi.decode error + vm.expectRevert(); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})), + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_WithCorrectPoolReturnData_Success() public view { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + sourceTokenAmounts[1].amount = 1e18; + sourceTokenAmounts[1].token = CUSTOM_TOKEN_2; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](2); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + tokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + bytes[] memory expectedDestExecData = new bytes[](2); + expectedDestExecData[0] = abi.encode( + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead + ); + expectedDestExecData[1] = abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD); //expected return data should be abi.encoded default as isEnabled is false + + // No revert - successful + ( /* msgFeeJuels */ , /* isOutOfOrderExecution */, /* convertedExtraArgs */, bytes[] memory destExecData) = + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + for (uint256 i = 0; i < destExecData.length; ++i) { + assertEq(destExecData[i], expectedDestExecData[i]); + } + } + + function test_processMessageArgs_TokenAmountArraysMismatching_Revert() public { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + + // Revert due to index out of bounds access + vm.expectRevert(); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + MAX_MSG_FEES_JUELS, + "", + new Internal.EVM2AnyTokenTransfer[](1), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_SourceTokenDataTooLarge_Revert() public { + address sourceETH = s_sourceTokens[1]; + + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1000; + sourceTokenAmounts[0].token = sourceETH; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + + // No data set, should succeed + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set max data length, should succeed + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set data to max length +1, should revert + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set token config to allow larger data + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, + isEnabled: true + }); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set the token data larger than the configured token data, should revert + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + } + + function test_processMessageArgs_InvalidEVMAddressDestToken_Revert() public { + bytes memory nonEvmAddress = abi.encode(type(uint208).max); + + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + tokenAmounts[0].destTokenAddress = nonEvmAddress; + + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + } +} + +contract FeeQuoter_validateDestFamilyAddress is FeeQuoterSetup { + function test_ValidEVMAddress_Success() public view { + bytes memory encodedAddress = abi.encode(address(10000)); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); + } + + function test_ValidNonEVMAddress_Success() public view { + s_feeQuoter.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); + } + + // Reverts + + function test_InvalidEVMAddress_Revert() 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); + } + + function test_InvalidEVMAddressEncodePacked_Revert() 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); + } + + function test_InvalidEVMAddressPrecompiles_Revert() 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, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) + ); + } +} + +contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { + FeeQuoter.DestChainConfig private s_destChainConfig; + + function setUp() public virtual override { + super.setUp(); + s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; + } + + function test_EVMExtraArgsV1_Success() 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(expectedOutputArgs) + ); + } + + function test_EVMExtraArgsV2_Success() 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) + ); + } + + function test_EVMExtraArgsDefault_Success() 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) + ); + } + + // Reverts + + function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + // Invalidate selector + inputExtraArgs[0] = bytes1(uint8(0)); + + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_EVMExtraArgsEnforceOutOfOrder_Revert() 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); + } + + function test_EVMExtraArgsGasLimitTooHigh_Revert() 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); + } +} + +contract FeeQuoter_KeystoneSetup is FeeQuoterSetup { + address internal constant FORWARDER_1 = address(0x1); + address internal constant WORKFLOW_OWNER_1 = address(0x3); + bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; + bytes2 internal constant REPORT_NAME_1 = "01"; + address internal onReportTestToken1; + address internal onReportTestToken2; + + function setUp() public virtual override { + super.setUp(); + onReportTestToken1 = s_sourceTokens[0]; + onReportTestToken2 = _deploySourceToken("onReportTestToken2", 0, 20); + + KeystoneFeedsPermissionHandler.Permission[] memory permissions = new KeystoneFeedsPermissionHandler.Permission[](1); + permissions[0] = KeystoneFeedsPermissionHandler.Permission({ + forwarder: FORWARDER_1, + workflowOwner: WORKFLOW_OWNER_1, + workflowName: WORKFLOW_NAME_1, + reportName: REPORT_NAME_1, + isAllowed: true + }); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); + tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ + sourceToken: onReportTestToken1, + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) + }); + tokenPriceFeeds[1] = FeeQuoter.TokenPriceFeedUpdate({ + sourceToken: onReportTestToken2, + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) + }); + s_feeQuoter.setReportPermissions(permissions); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); + } +} + +contract FeeQuoter_onReport is FeeQuoter_KeystoneSetup { + function test_onReport_Success() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + report[1] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); + + uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); + uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, report[1].price); + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredToken1Price, block.timestamp); + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken2, expectedStoredToken2Price, block.timestamp); + + changePrank(FORWARDER_1); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + + vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); + vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).timestamp, report[0].timestamp); + + vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).value, expectedStoredToken2Price); + vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); + } + + function test_onReport_InvalidForwarder_Reverts() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); + + vm.expectRevert( + abi.encodeWithSelector( + KeystoneFeedsPermissionHandler.ReportForwarderUnauthorized.selector, + STRANGER, + WORKFLOW_OWNER_1, + WORKFLOW_NAME_1, + REPORT_NAME_1 + ) + ); + changePrank(STRANGER); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } + + function test_onReport_UnsupportedToken_Reverts() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); + changePrank(FORWARDER_1); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } + + function test_OnReport_StaleUpdate_Revert() public { + //Creating a correct report + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + + uint224 expectedStoredTokenPrice = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredTokenPrice, block.timestamp); + + changePrank(FORWARDER_1); + //setting the correct price and time with the correct report + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + + //create a stale report + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp - 1)}); + //expecting a revert + vm.expectRevert( + abi.encodeWithSelector( + FeeQuoter.StaleKeystoneUpdate.selector, onReportTestToken1, block.timestamp - 1, block.timestamp + ) + ); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } +} diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol new file mode 100644 index 00000000000..f1a00be78c3 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; + +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; +import {TokenSetup} from "../TokenSetup.t.sol"; +import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; + +contract FeeQuoterSetup is TokenSetup { + uint112 internal constant USD_PER_GAS = 1e6; // 0.001 gwei + uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei + + address internal constant CUSTOM_TOKEN = address(12345); + address internal constant CUSTOM_TOKEN_2 = address(bytes20(keccak256("CUSTOM_TOKEN_2"))); + + uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM + uint224 internal constant CUSTOM_TOKEN_PRICE_2 = 1e18; // $1 CUSTOM + + // Encode L1 gas price and L2 gas price into a packed price. + // L1 gas price is left-shifted to the higher-order bits. + uint224 internal constant PACKED_USD_PER_GAS = + (uint224(USD_PER_DATA_AVAILABILITY_GAS) << Internal.GAS_PRICE_BITS) + USD_PER_GAS; + + FeeQuoterHelper internal s_feeQuoter; + // Cheat to store the price updates in storage since struct arrays aren't supported. + bytes internal s_encodedInitialPriceUpdates; + address internal s_weth; + + address[] internal s_sourceFeeTokens; + uint224[] internal s_sourceTokenPrices; + address[] internal s_destFeeTokens; + uint224[] internal s_destTokenPrices; + + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] internal s_feeQuoterPremiumMultiplierWeiPerEthArgs; + FeeQuoter.TokenTransferFeeConfigArgs[] internal s_feeQuoterTokenTransferFeeConfigArgs; + + mapping(address token => address dataFeedAddress) internal s_dataFeedByToken; + + function setUp() public virtual override { + TokenSetup.setUp(); + + _deployTokenPriceDataFeed(s_sourceFeeToken, 8, 1e8); + + s_weth = s_sourceRouter.getWrappedNative(); + _deployTokenPriceDataFeed(s_weth, 8, 1e11); + + address[] memory sourceFeeTokens = new address[](3); + sourceFeeTokens[0] = s_sourceTokens[0]; + sourceFeeTokens[1] = s_sourceTokens[1]; + sourceFeeTokens[2] = s_sourceRouter.getWrappedNative(); + s_sourceFeeTokens = sourceFeeTokens; + + uint224[] memory sourceTokenPrices = new uint224[](3); + sourceTokenPrices[0] = 5e18; + sourceTokenPrices[1] = 2000e18; + sourceTokenPrices[2] = 2000e18; + s_sourceTokenPrices = sourceTokenPrices; + + address[] memory destFeeTokens = new address[](3); + destFeeTokens[0] = s_destTokens[0]; + destFeeTokens[1] = s_destTokens[1]; + destFeeTokens[2] = s_destRouter.getWrappedNative(); + s_destFeeTokens = destFeeTokens; + + uint224[] memory destTokenPrices = new uint224[](3); + destTokenPrices[0] = 5e18; + destTokenPrices[1] = 2000e18; + destTokenPrices[2] = 2000e18; + s_destTokenPrices = destTokenPrices; + + uint256 sourceTokenCount = sourceFeeTokens.length; + uint256 destTokenCount = destFeeTokens.length; + address[] memory pricedTokens = new address[](sourceTokenCount + destTokenCount); + uint224[] memory tokenPrices = new uint224[](sourceTokenCount + destTokenCount); + for (uint256 i = 0; i < sourceTokenCount; ++i) { + pricedTokens[i] = sourceFeeTokens[i]; + tokenPrices[i] = sourceTokenPrices[i]; + } + for (uint256 i = 0; i < destTokenCount; ++i) { + pricedTokens[i + sourceTokenCount] = destFeeTokens[i]; + tokenPrices[i + sourceTokenCount] = destTokenPrices[i]; + } + + Internal.PriceUpdates memory priceUpdates = _getPriceUpdatesStruct(pricedTokens, tokenPrices); + priceUpdates.gasPriceUpdates = new Internal.GasPriceUpdate[](1); + priceUpdates.gasPriceUpdates[0] = + Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: PACKED_USD_PER_GAS}); + + s_encodedInitialPriceUpdates = abi.encode(priceUpdates); + + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = OWNER; + address[] memory feeTokens = new address[](2); + feeTokens[0] = s_sourceTokens[0]; + feeTokens[1] = s_weth; + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); + + s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( + FeeQuoter.PremiumMultiplierWeiPerEthArgs({ + token: s_sourceFeeToken, + premiumMultiplierWeiPerEth: 5e17 // 0.5x + }) + ); + s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( + FeeQuoter.PremiumMultiplierWeiPerEthArgs({ + token: s_sourceRouter.getWrappedNative(), + premiumMultiplierWeiPerEth: 2e18 // 2x + }) + ); + + s_feeQuoterTokenTransferFeeConfigArgs.push(); + s_feeQuoterTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ + token: s_sourceFeeToken, + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1_00, // 1 USD + maxFeeUSDCents: 1000_00, // 1,000 USD + deciBps: 2_5, // 2.5 bps, or 0.025% + destGasOverhead: 100_000, + destBytesOverhead: 32, + isEnabled: true + }) + }) + ); + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ + token: CUSTOM_TOKEN, + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 2_00, // 1 USD + maxFeeUSDCents: 2000_00, // 1,000 USD + deciBps: 10_0, // 10 bps, or 0.1% + destGasOverhead: 95_000, + destBytesOverhead: 200, + isEnabled: true + }) + }) + ); + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ + token: CUSTOM_TOKEN_2, + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 2_00, // 1 USD + maxFeeUSDCents: 2000_00, // 1,000 USD + deciBps: 10_0, // 10 bps, or 0.1% + destGasOverhead: 1, + destBytesOverhead: 200, + isEnabled: false + }) + }) + ); + + //setting up the destination token for CUSTOM_TOKEN_2 here as it is specific to these tests + s_destTokenBySourceToken[CUSTOM_TOKEN_2] = address(bytes20(keccak256("CUSTOM_TOKEN_2_DEST"))); + + s_feeQuoter = new FeeQuoterHelper( + FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + tokenPriceStalenessThreshold: uint32(TWELVE_HOURS) + }), + priceUpdaters, + feeTokens, + tokenPriceFeedUpdates, + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + _generateFeeQuoterDestChainConfigArgs() + ); + s_feeQuoter.updatePrices(priceUpdates); + } + + function _deployTokenPriceDataFeed(address token, uint8 decimals, int256 initialAnswer) internal returns (address) { + MockV3Aggregator dataFeed = new MockV3Aggregator(decimals, initialAnswer); + s_dataFeedByToken[token] = address(dataFeed); + return address(dataFeed); + } + + function _getPriceUpdatesStruct( + address[] memory tokens, + uint224[] memory prices + ) internal pure returns (Internal.PriceUpdates memory) { + uint256 length = tokens.length; + + Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](length); + for (uint256 i = 0; i < length; ++i) { + tokenPriceUpdates[i] = Internal.TokenPriceUpdate({sourceToken: tokens[i], usdPerToken: prices[i]}); + } + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: new Internal.GasPriceUpdate[](0)}); + + return priceUpdates; + } + + function _getEmptyPriceUpdates() internal pure returns (Internal.PriceUpdates memory priceUpdates) { + return Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + } + + function _getSingleTokenPriceFeedUpdateStruct( + address sourceToken, + address dataFeedAddress, + uint8 tokenDecimals + ) internal pure returns (FeeQuoter.TokenPriceFeedUpdate memory) { + return FeeQuoter.TokenPriceFeedUpdate({ + sourceToken: sourceToken, + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) + }); + } + + function _initialiseSingleTokenPriceFeed() internal returns (address) { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + return s_sourceTokens[0]; + } + + function _generateTokenTransferFeeConfigArgs( + uint256 destChainSelectorLength, + uint256 tokenLength + ) internal pure returns (FeeQuoter.TokenTransferFeeConfigArgs[] memory) { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + new FeeQuoter.TokenTransferFeeConfigArgs[](destChainSelectorLength); + for (uint256 i = 0; i < destChainSelectorLength; ++i) { + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = + new FeeQuoter.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); + } + return tokenTransferFeeConfigArgs; + } + + function _generateFeeQuoterDestChainConfigArgs() internal pure returns (FeeQuoter.DestChainConfigArgs[] memory) { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigs = new FeeQuoter.DestChainConfigArgs[](1); + destChainConfigs[0] = FeeQuoter.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + destChainConfig: FeeQuoter.DestChainConfig({ + isEnabled: true, + maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, + destGasOverhead: DEST_GAS_OVERHEAD, + destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, + destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, + destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, + destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, + maxDataBytes: MAX_DATA_SIZE, + maxPerMsgGasLimit: MAX_GAS_LIMIT, + defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, + defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, + defaultTxGasLimit: GAS_LIMIT, + gasMultiplierWeiPerEth: 5e17, + networkFeeUSDCents: 1_00, + gasPriceStalenessThreshold: uint32(TWELVE_HOURS), + enforceOutOfOrder: false, + chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM + }) + }); + return destChainConfigs; + } + + function _assertTokenPriceFeedConfigEquality( + FeeQuoter.TokenPriceFeedConfig memory config1, + FeeQuoter.TokenPriceFeedConfig memory config2 + ) internal pure virtual { + assertEq(config1.dataFeedAddress, config2.dataFeedAddress); + assertEq(config1.tokenDecimals, config2.tokenDecimals); + } + + function _assertTokenPriceFeedConfigUnconfigured( + FeeQuoter.TokenPriceFeedConfig memory config + ) internal pure virtual { + _assertTokenPriceFeedConfigEquality( + config, FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) + ); + } + + function _assertTokenTransferFeeConfigEqual( + FeeQuoter.TokenTransferFeeConfig memory a, + FeeQuoter.TokenTransferFeeConfig memory b + ) internal pure { + assertEq(a.minFeeUSDCents, b.minFeeUSDCents); + assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); + assertEq(a.deciBps, b.deciBps); + assertEq(a.destGasOverhead, b.destGasOverhead); + assertEq(a.destBytesOverhead, b.destBytesOverhead); + assertEq(a.isEnabled, b.isEnabled); + } + + function _assertFeeQuoterStaticConfigsEqual( + FeeQuoter.StaticConfig memory a, + FeeQuoter.StaticConfig memory b + ) internal pure { + assertEq(a.linkToken, b.linkToken); + assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); + } + + function _assertFeeQuoterDestChainConfigsEqual( + FeeQuoter.DestChainConfig memory a, + FeeQuoter.DestChainConfig memory b + ) internal pure { + assertEq(a.isEnabled, b.isEnabled); + assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); + assertEq(a.maxDataBytes, b.maxDataBytes); + assertEq(a.maxPerMsgGasLimit, b.maxPerMsgGasLimit); + assertEq(a.destGasOverhead, b.destGasOverhead); + assertEq(a.destGasPerPayloadByte, b.destGasPerPayloadByte); + assertEq(a.destDataAvailabilityOverheadGas, b.destDataAvailabilityOverheadGas); + assertEq(a.destGasPerDataAvailabilityByte, b.destGasPerDataAvailabilityByte); + assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); + assertEq(a.defaultTokenFeeUSDCents, b.defaultTokenFeeUSDCents); + assertEq(a.defaultTokenDestGasOverhead, b.defaultTokenDestGasOverhead); + assertEq(a.defaultTxGasLimit, b.defaultTxGasLimit); + } +} + +contract FeeQuoterFeeSetup is FeeQuoterSetup { + uint224 internal s_feeTokenPrice; + uint224 internal s_wrappedTokenPrice; + uint224 internal s_customTokenPrice; + + address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); + + address internal s_destTokenPool = makeAddr("destTokenPool"); + address internal s_destToken = makeAddr("destToken"); + + function setUp() public virtual override { + super.setUp(); + + s_feeTokenPrice = s_sourceTokenPrices[0]; + s_wrappedTokenPrice = s_sourceTokenPrices[2]; + s_customTokenPrice = CUSTOM_TOKEN_PRICE; + + s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); + } + + function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _generateSingleTokenMessage( + address token, + uint256 amount + ) public view returns (Client.EVM2AnyMessage memory) { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); + + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 sourceChainSelector, + uint64 destChainSelector, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + uint256 feeValueJuels, + address originalSender, + bytes32 metadataHash, + TokenAdminRegistry tokenAdminRegistry + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + Client.EVMExtraArgsV2 memory extraArgs = + s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); + + Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + messageId: "", + sourceChainSelector: sourceChainSelector, + destChainSelector: destChainSelector, + sequenceNumber: seqNum, + nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce + }), + sender: originalSender, + data: message.data, + receiver: message.receiver, + extraArgs: Client._argsToBytes(extraArgs), + feeToken: message.feeToken, + feeTokenAmount: feeTokenAmount, + feeValueJuels: feeValueJuels, + tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) + }); + + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + messageEvent.tokenAmounts[i] = + _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry, DEST_CHAIN_SELECTOR); + } + + messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); + return messageEvent; + } + + function _getSourceTokenData( + Client.EVMTokenAmount memory tokenAmount, + TokenAdminRegistry tokenAdminRegistry, + uint64 destChainSelector + ) internal view returns (Internal.EVM2AnyTokenTransfer memory) { + address destToken = s_destTokenBySourceToken[tokenAmount.token]; + + uint32 expectedDestGasAmount; + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + FeeQuoter(s_feeQuoter).getTokenTransferFeeConfig(destChainSelector, tokenAmount.token); + expectedDestGasAmount = + tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD; + + return Internal.EVM2AnyTokenTransfer({ + sourcePoolAddress: tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool, + destTokenAddress: abi.encode(destToken), + extraData: "", + amount: tokenAmount.amount, + destExecData: abi.encode(expectedDestGasAmount) + }); + } + + function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { + return (tokenPrice * tokenAmount) / 1e18; + } + + function _applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { + return (tokenAmount * ratio) / 1e5; + } + + function _configUSDCentToWei( + uint256 usdCent + ) internal pure returns (uint256) { + return usdCent * 1e16; + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/AggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/AggregateRateLimiterHelper.sol deleted file mode 100644 index ced605a7524..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/AggregateRateLimiterHelper.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import "../../AggregateRateLimiter.sol"; - -contract AggregateRateLimiterHelper is AggregateRateLimiter { - constructor(RateLimiter.Config memory config) AggregateRateLimiter(config) {} - - function rateLimitValue(uint256 value) public { - _rateLimitValue(value); - } - - function getTokenValue( - Client.EVMTokenAmount memory tokenAmount, - IPriceRegistry priceRegistry - ) public view returns (uint256) { - return _getTokenValue(tokenAmount, priceRegistry); - } -} diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol index 9d2346996ae..c3f95a7e067 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol @@ -8,7 +8,9 @@ contract BurnMintERC677Helper is BurnMintERC677, IGetCCIPAdmin { constructor(string memory name, string memory symbol) BurnMintERC677(name, symbol, 18, 0) {} // Gives one full token to any given address. - function drip(address to) external { + function drip( + address to + ) external { _mint(to, 1e18); } diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol index a21fcde8357..bb1d4c9af36 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol @@ -18,12 +18,9 @@ contract BurnMintMultiTokenPool is MultiTokenPool { /// @notice Burn 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) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); IBurnMintERC20(lockOrBurnIn.localToken).burn(lockOrBurnIn.amount); @@ -38,15 +35,12 @@ contract BurnMintMultiTokenPool is MultiTokenPool { /// @notice Mint tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); - // Mint to the offRamp, which forwards it to the recipient + // Mint to the receiver IBurnMintERC20(releaseOrMintIn.localToken).mint(msg.sender, releaseOrMintIn.amount); emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol deleted file mode 100644 index 74f03890d3b..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {CCIPConfig} from "../../capability/CCIPConfig.sol"; -import {CCIPConfigTypes} from "../../capability/libraries/CCIPConfigTypes.sol"; -import {Internal} from "../../libraries/Internal.sol"; - -contract CCIPConfigHelper is CCIPConfig { - constructor(address capabilitiesRegistry) CCIPConfig(capabilitiesRegistry) {} - - function stateFromConfigLength(uint256 configLength) public pure returns (CCIPConfigTypes.ConfigState) { - return _stateFromConfigLength(configLength); - } - - function validateConfigStateTransition( - CCIPConfigTypes.ConfigState currentState, - CCIPConfigTypes.ConfigState newState - ) public pure { - _validateConfigStateTransition(currentState, newState); - } - - function validateConfigTransition( - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig, - CCIPConfigTypes.OCR3ConfigWithMeta[] memory newConfigWithMeta - ) public pure { - _validateConfigTransition(currentConfig, newConfigWithMeta); - } - - function computeNewConfigWithMeta( - uint32 donId, - CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig, - CCIPConfigTypes.OCR3Config[] memory newConfig, - CCIPConfigTypes.ConfigState currentState, - CCIPConfigTypes.ConfigState newState - ) public view returns (CCIPConfigTypes.OCR3ConfigWithMeta[] memory) { - return _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); - } - - function groupByPluginType(CCIPConfigTypes.OCR3Config[] memory ocr3Configs) - public - pure - returns (CCIPConfigTypes.OCR3Config[] memory commitConfigs, CCIPConfigTypes.OCR3Config[] memory execConfigs) - { - return _groupByPluginType(ocr3Configs); - } - - function computeConfigDigest( - uint32 donId, - uint64 configCount, - CCIPConfigTypes.OCR3Config memory ocr3Config - ) public pure returns (bytes32) { - return _computeConfigDigest(donId, configCount, ocr3Config); - } - - function validateConfig(CCIPConfigTypes.OCR3Config memory cfg) public view { - _validateConfig(cfg); - } - - function updatePluginConfig( - uint32 donId, - Internal.OCRPluginType pluginType, - CCIPConfigTypes.OCR3Config[] memory newConfig - ) public { - _updatePluginConfig(donId, pluginType, newConfig); - } -} diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol new file mode 100644 index 00000000000..0bc97c7aa5b --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {CCIPHome} from "../../capability/CCIPHome.sol"; + +contract CCIPHomeHelper is CCIPHome { + constructor( + address capabilitiesRegistry + ) CCIPHome(capabilitiesRegistry) {} + + function validateConfig( + OCR3Config memory cfg + ) external view { + return _validateConfig(cfg); + } + + function ensureInRegistry( + bytes32[] memory p2pIds + ) external view { + return _ensureInRegistry(p2pIds); + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol new file mode 100644 index 00000000000..38838f6acb2 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../libraries/Internal.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; + +/// @dev test contract to test CCIPReader functionality, never deployed to real chains. +contract CCIPReaderTester { + mapping(uint64 sourceChainSelector => OffRamp.SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; + mapping(uint64 destChainSelector => uint64 sequenceNumber) internal s_destChainSeqNrs; + mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 nonce)) internal s_senderNonce; + + /// @notice Gets the next sequence number to be used in the onRamp + /// @param destChainSelector The destination chain selector + /// @return nextSequenceNumber The next sequence number to be used + function getExpectedNextSequenceNumber( + uint64 destChainSelector + ) external view returns (uint64) { + return s_destChainSeqNrs[destChainSelector] + 1; + } + + /// @notice Sets the sequence number in the onRamp + /// @param destChainSelector The destination chain selector + /// @param sequenceNumber The sequence number + function setDestChainSeqNr(uint64 destChainSelector, uint64 sequenceNumber) external { + s_destChainSeqNrs[destChainSelector] = sequenceNumber; + } + + /// @notice Returns the inbound nonce for a given sender on a given source chain. + /// @param sourceChainSelector The source chain selector. + /// @param sender The encoded sender address. + /// @return inboundNonce The inbound nonce. + function getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) external view returns (uint64) { + return s_senderNonce[sourceChainSelector][sender]; + } + + function setInboundNonce(uint64 sourceChainSelector, uint64 testNonce, bytes calldata sender) external { + s_senderNonce[sourceChainSelector][sender] = testNonce; + } + + function getSourceChainConfig( + uint64 sourceChainSelector + ) external view returns (OffRamp.SourceChainConfig memory) { + return s_sourceChainConfigs[sourceChainSelector]; + } + + function setSourceChainConfig( + uint64 sourceChainSelector, + OffRamp.SourceChainConfig memory sourceChainConfig + ) external { + s_sourceChainConfigs[sourceChainSelector] = sourceChainConfig; + } + + function emitCCIPMessageSent(uint64 destChainSelector, Internal.EVM2AnyRampMessage memory message) external { + emit OnRamp.CCIPMessageSent(destChainSelector, message.header.sequenceNumber, message); + } + + function emitExecutionStateChanged( + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes memory returnData, + uint256 gasUsed + ) external { + emit OffRamp.ExecutionStateChanged( + sourceChainSelector, sequenceNumber, messageId, messageHash, state, returnData, gasUsed + ); + } + + function emitCommitReportAccepted( + OffRamp.CommitReport memory report + ) external { + emit OffRamp.CommitReportAccepted(report.merkleRoots, report.priceUpdates); + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/CommitStoreHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CommitStoreHelper.sol deleted file mode 100644 index c8d66b8d72f..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/CommitStoreHelper.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import "../../CommitStore.sol"; - -contract CommitStoreHelper is CommitStore { - constructor(StaticConfig memory staticConfig) CommitStore(staticConfig) {} - - /// @dev Expose _report for tests - function report(bytes calldata commitReport, uint40 epochAndRound) external { - _report(commitReport, epochAndRound); - } -} diff --git a/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol b/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol new file mode 100644 index 00000000000..617d39af5c4 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; + +contract ERC20RebasingHelper is ERC20 { + uint16 public s_multiplierPercentage = 100; + bool public s_mintShouldBurn = false; + + constructor() ERC20("Rebasing", "REB") {} + + function mint(address to, uint256 amount) external { + if (!s_mintShouldBurn) { + _mint(to, amount * s_multiplierPercentage / 100); + return; + } + _burn(to, amount * s_multiplierPercentage / 100); + } + + function setMultiplierPercentage( + uint16 multiplierPercentage + ) external { + s_multiplierPercentage = multiplierPercentage; + } + + function setMintShouldBurn( + bool mintShouldBurn + ) external { + s_mintShouldBurn = mintShouldBurn; + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol deleted file mode 100644 index 0532697d649..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import "../../onRamp/EVM2EVMMultiOnRamp.sol"; -import {IgnoreContractSize} from "./IgnoreContractSize.sol"; - -contract EVM2EVMMultiOnRampHelper is EVM2EVMMultiOnRamp, IgnoreContractSize { - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig - ) EVM2EVMMultiOnRamp(staticConfig, dynamicConfig) {} -} diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol index e328f0ade29..9f4ca68d84a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol @@ -1,59 +1,25 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import "../../offRamp/EVM2EVMOffRamp.sol"; -import {IgnoreContractSize} from "./IgnoreContractSize.sol"; +contract EVM2EVMOffRampHelper { + uint64 public s_nonce; + mapping(address sender => uint64 nonce) public s_nonces; -contract EVM2EVMOffRampHelper is EVM2EVMOffRamp, IgnoreContractSize { - constructor( - StaticConfig memory staticConfig, - RateLimiter.Config memory rateLimiterConfig - ) EVM2EVMOffRamp(staticConfig, rateLimiterConfig) {} - - function setExecutionStateHelper(uint64 sequenceNumber, Internal.MessageExecutionState state) public { - _setExecutionState(sequenceNumber, state); - } - - function getExecutionStateBitMap(uint64 bitmapIndex) public view returns (uint256) { - return s_executionStates[bitmapIndex]; - } - - function releaseOrMintToken( - uint256 sourceTokenAmount, - bytes calldata originalSender, - address receiver, - Internal.SourceTokenData calldata sourceTokenData, - bytes calldata offchainTokenData - ) external returns (Client.EVMTokenAmount memory) { - return _releaseOrMintToken(sourceTokenAmount, originalSender, receiver, sourceTokenData, offchainTokenData); - } - - function releaseOrMintTokens( - Client.EVMTokenAmount[] memory sourceTokenAmounts, - bytes calldata originalSender, - address receiver, - bytes[] calldata sourceTokenData, - bytes[] calldata offchainTokenData - ) external returns (Client.EVMTokenAmount[] memory) { - return _releaseOrMintTokens(sourceTokenAmounts, originalSender, receiver, sourceTokenData, offchainTokenData); - } - - function trialExecute( - Internal.EVM2EVMMessage memory message, - bytes[] memory offchainTokenData - ) external returns (Internal.MessageExecutionState, bytes memory) { - return _trialExecute(message, offchainTokenData); - } - - function report(bytes calldata executableMessages) external { - _report(executableMessages); + function execute( + address[] memory senders + ) external { + for (uint256 i; i < senders.length; i++) { + s_nonces[senders[i]]++; + } } - function execute(Internal.ExecutionReport memory rep, uint256[] memory manualExecGasLimits) external { - _execute(rep, manualExecGasLimits); + function metadataHash() external pure returns (bytes32) { + return 0x0; } - function metadataHash() external view returns (bytes32) { - return _metadataHash(Internal.EVM_2_EVM_MESSAGE_HASH); + function getSenderNonce( + address sender + ) external view returns (uint64 nonce) { + return s_nonces[sender]; } } diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOnRampHelper.sol deleted file mode 100644 index 5cce6aaa445..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOnRampHelper.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import "../../onRamp/EVM2EVMOnRamp.sol"; -import {IgnoreContractSize} from "./IgnoreContractSize.sol"; - -contract EVM2EVMOnRampHelper is EVM2EVMOnRamp, IgnoreContractSize { - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - RateLimiter.Config memory rateLimiterConfig, - FeeTokenConfigArgs[] memory feeTokenConfigs, - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - NopAndWeight[] memory nopsAndWeights - ) - EVM2EVMOnRamp( - staticConfig, - dynamicConfig, - rateLimiterConfig, - feeTokenConfigs, - tokenTransferFeeConfigArgs, - nopsAndWeights - ) - {} - - function getDataAvailabilityCost( - uint112 dataAvailabilityGasPrice, - uint256 messageDataLength, - uint256 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) external view returns (uint256) { - return - _getDataAvailabilityCost(dataAvailabilityGasPrice, messageDataLength, numberOfTokens, tokenTransferBytesOverhead); - } - - function getTokenTransferCost( - address feeToken, - uint224 feeTokenPrice, - Client.EVMTokenAmount[] calldata tokenAmounts - ) external view returns (uint256, uint32, uint32) { - return _getTokenTransferCost(feeToken, feeTokenPrice, tokenAmounts); - } - - function getSequenceNumber() external view returns (uint64) { - return s_sequenceNumber; - } -} diff --git a/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol index 71a5cdc7ab6..e357645bcb2 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol @@ -5,17 +5,25 @@ import {EtherSenderReceiver} from "../../applications/EtherSenderReceiver.sol"; import {Client} from "../../libraries/Client.sol"; contract EtherSenderReceiverHelper is EtherSenderReceiver { - constructor(address router) EtherSenderReceiver(router) {} + constructor( + address router + ) EtherSenderReceiver(router) {} - function validatedMessage(Client.EVM2AnyMessage calldata message) public view returns (Client.EVM2AnyMessage memory) { + function validatedMessage( + Client.EVM2AnyMessage calldata message + ) public view returns (Client.EVM2AnyMessage memory) { return _validatedMessage(message); } - function validateFeeToken(Client.EVM2AnyMessage calldata message) public payable { + function validateFeeToken( + Client.EVM2AnyMessage calldata message + ) public payable { _validateFeeToken(message); } - function publicCcipReceive(Client.Any2EVMMessage memory message) public { + function publicCcipReceive( + Client.Any2EVMMessage memory message + ) public { _ccipReceive(message); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol similarity index 86% rename from contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol rename to contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol index 8524df12ccf..e392ba05589 100644 --- a/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {PriceRegistry} from "../../PriceRegistry.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; -contract PriceRegistryHelper is PriceRegistry { +contract FeeQuoterHelper is FeeQuoter { constructor( StaticConfig memory staticConfig, address[] memory priceUpdaters, @@ -14,7 +14,7 @@ contract PriceRegistryHelper is PriceRegistry { PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, DestChainConfigArgs[] memory destChainConfigArgs ) - PriceRegistry( + FeeQuoter( staticConfig, priceUpdaters, feeTokens, @@ -69,4 +69,12 @@ contract PriceRegistryHelper is PriceRegistry { function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { _validateDestFamilyAddress(chainFamilySelector, destAddress); } + + function calculateRebasedValue( + uint8 dataFeedDecimal, + uint8 tokenDecimal, + uint256 feedValue + ) external pure returns (uint224) { + return _calculateRebasedValue(dataFeedDecimal, tokenDecimal, feedValue); + } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol index e572f798ad9..23e13aaa8bb 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: MIT -pragma solidity ^0.8.0; +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -9,6 +9,7 @@ import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { bytes public s_revertReason = ""; bytes public s_sourceTokenData = ""; + uint256 public s_releaseOrMintMultiplier = 1; constructor( IBurnMintERC20 token, @@ -17,20 +18,27 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { address router ) BurnMintTokenPool(token, allowlist, rmnProxy, router) {} - function setShouldRevert(bytes calldata revertReason) external { + function setShouldRevert( + bytes calldata revertReason + ) external { s_revertReason = revertReason; } - function setSourceTokenData(bytes calldata sourceTokenData) external { + function setSourceTokenData( + bytes calldata sourceTokenData + ) external { s_sourceTokenData = sourceTokenData; } - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function setReleaseOrMintMultiplier( + uint256 multiplier + ) external { + s_releaseOrMintMultiplier = multiplier; + } + + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); bytes memory revertReason = s_revertReason; @@ -49,12 +57,9 @@ 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) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); bytes memory revertReason = s_revertReason; @@ -63,8 +68,10 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { revert(add(32, revertReason), mload(revertReason)) } } - IBurnMintERC20(address(i_token)).mint(msg.sender, releaseOrMintIn.amount); - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + uint256 amount = releaseOrMintIn.amount * s_releaseOrMintMultiplier; + IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, amount); + + emit Minted(msg.sender, releaseOrMintIn.receiver, amount); + return Pool.ReleaseOrMintOutV1({destinationAmount: amount}); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol index ccb05681f1c..3893d082b6a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol @@ -14,7 +14,10 @@ library MerkleHelper { /// d c /// / \ /// a b - function getMerkleRoot(bytes32[] memory hashedLeaves) public pure returns (bytes32) { + function getMerkleRoot( + bytes32[] memory hashedLeaves + ) public pure returns (bytes32) { + // solhint-disable-next-line reason-string,gas-custom-errors require(hashedLeaves.length <= 256); while (hashedLeaves.length > 1) { hashedLeaves = computeNextLayer(hashedLeaves); @@ -25,7 +28,9 @@ library MerkleHelper { /// @notice Computes a single layer of a merkle proof by hashing each pair (i, i+1) for /// each i, i+2, i+4.. n. When an uneven number of leaves is supplied the last item /// is simply included as the last element in the result set and not hashed. - function computeNextLayer(bytes32[] memory layer) public pure returns (bytes32[] memory) { + function computeNextLayer( + bytes32[] memory layer + ) public pure returns (bytes32[] memory) { uint256 leavesLen = layer.length; if (leavesLen == 1) return layer; diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index 19f35df7969..68d6dc41149 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.4; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; @@ -9,56 +9,76 @@ import {Internal} from "../../libraries/Internal.sol"; /// @dev This is only deployed in tests and is not part of the production contracts. contract MessageHasher { function hash(Internal.Any2EVMRampMessage memory message, bytes memory onRamp) public pure returns (bytes32) { - return Internal._hash(message, onRamp); + return Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); } - function encodeTokenAmountsHashPreimage(Internal.RampTokenAmount[] memory rampTokenAmounts) - public - pure - returns (bytes memory) - { - return abi.encode(rampTokenAmounts); + function encodeAny2EVMTokenAmountsHashPreimage( + Internal.Any2EVMTokenTransfer[] memory tokenAmounts + ) public pure returns (bytes memory) { + return abi.encode(tokenAmounts); + } + + function encodeEVM2AnyTokenAmountsHashPreimage( + Internal.EVM2AnyTokenTransfer[] memory tokenAmount + ) public pure returns (bytes memory) { + return abi.encode(tokenAmount); } function encodeMetadataHashPreimage( bytes32 any2EVMMessageHash, uint64 sourceChainSelector, uint64 destChainSelector, - bytes memory onRamp + bytes32 onRampHash ) public pure returns (bytes memory) { - return abi.encode(any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp); + return abi.encode(any2EVMMessageHash, sourceChainSelector, destChainSelector, onRampHash); } function encodeFixedSizeFieldsHashPreimage( bytes32 messageId, - bytes memory sender, address receiver, uint64 sequenceNumber, uint256 gasLimit, uint64 nonce ) public pure returns (bytes memory) { - return abi.encode(messageId, sender, receiver, sequenceNumber, gasLimit, nonce); + return abi.encode(messageId, receiver, sequenceNumber, gasLimit, nonce); } function encodeFinalHashPreimage( bytes32 leafDomainSeparator, - bytes32 implicitMetadataHash, + bytes32 metaDataHash, bytes32 fixedSizeFieldsHash, + bytes32 senderHash, bytes32 dataHash, bytes32 tokenAmountsHash ) public pure returns (bytes memory) { - return abi.encode(leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash); + return abi.encode(leafDomainSeparator, metaDataHash, fixedSizeFieldsHash, senderHash, dataHash, tokenAmountsHash); } - function encodeEVMExtraArgsV1(Client.EVMExtraArgsV1 memory extraArgs) public pure returns (bytes memory) { + function encodeEVMExtraArgsV1( + Client.EVMExtraArgsV1 memory extraArgs + ) public pure returns (bytes memory) { return Client._argsToBytes(extraArgs); } - function encodeEVMExtraArgsV2(Client.EVMExtraArgsV2 memory extraArgs) public pure returns (bytes memory) { + function encodeEVMExtraArgsV2( + Client.EVMExtraArgsV2 memory extraArgs + ) public pure returns (bytes memory) { return Client._argsToBytes(extraArgs); } - function decodeEVMExtraArgsV1(uint256 gasLimit) public pure returns (Client.EVMExtraArgsV1 memory) { + function decodeEVMExtraArgsV1( + uint256 gasLimit + ) public pure returns (Client.EVMExtraArgsV1 memory) { return Client.EVMExtraArgsV1(gasLimit); } diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol index a54145da84e..80cdf61602b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol @@ -14,7 +14,9 @@ contract MessageInterceptorHelper is IMessageInterceptor { } /// @inheritdoc IMessageInterceptor - function onInboundMessage(Client.Any2EVMMessage memory message) external view { + function onInboundMessage( + Client.Any2EVMMessage memory message + ) external view { if (s_invalidMessageIds[message.messageId]) { revert MessageValidationError(bytes("Invalid message")); } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index d9386ca7db0..7c2e6cc8c24 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -2,16 +2,17 @@ pragma solidity 0.8.24; import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; import {Client} from "../../libraries/Client.sol"; contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( - address priceRegistry, + address feeQuoter, address[] memory authorizedCallers - ) MultiAggregateRateLimiter(priceRegistry, authorizedCallers) {} + ) MultiAggregateRateLimiter(feeQuoter, authorizedCallers) {} - function getTokenValue(Client.EVMTokenAmount memory tokenAmount) public view returns (uint256) { + function getTokenValue( + Client.EVMTokenAmount memory tokenAmount + ) public view returns (uint256) { return _getTokenValue(tokenAmount); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol index 003a5326b89..e760b79935d 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol @@ -10,7 +10,9 @@ contract MultiOCR3Helper is MultiOCR3Base { /// Defined in storage since it cannot be passed as calldata due to strict transmit checks uint8 internal s_transmitOcrPluginType; - function setTransmitOcrPluginType(uint8 ocrPluginType) external { + function setTransmitOcrPluginType( + uint8 ocrPluginType + ) external { s_transmitOcrPluginType = ocrPluginType; } @@ -39,7 +41,9 @@ contract MultiOCR3Helper is MultiOCR3Base { return "MultiOCR3BaseHelper 1.0.0"; } - function _afterOCR3ConfigSet(uint8 ocrPluginType) internal virtual override { + function _afterOCR3ConfigSet( + uint8 ocrPluginType + ) internal virtual override { emit AfterConfigSet(ocrPluginType); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol index 0f7c312f713..9def6e2794b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol @@ -10,8 +10,8 @@ import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice This contract is a proof of concept and should NOT be used in production. abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { @@ -54,7 +54,7 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { struct ChainUpdate { uint64 remoteChainSelector; // ──╮ Remote chain selector bool allowed; // ────────────────╯ Whether the chain is allowed - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remove EVM chain. + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain @@ -77,7 +77,7 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// Only takes effect if i_allowlistEnabled is true. /// This can be used to ensure only token-issuer specified addresses can /// move tokens. - EnumerableSet.AddressSet internal s_allowList; + EnumerableSet.AddressSet internal s_allowlist; /// @dev The address of the router IRouter internal s_router; /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to @@ -108,7 +108,9 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { } /// @inheritdoc IPoolV1 - function isSupportedToken(address token) public view virtual returns (bool) { + function isSupportedToken( + address token + ) public view virtual returns (bool) { return s_tokens.contains(token); } @@ -130,7 +132,9 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// @notice Sets the pool's Router /// @param newRouter The new Router - function setRouter(address newRouter) public onlyOwner { + function setRouter( + address newRouter + ) public onlyOwner { if (newRouter == address(0)) revert ZeroAddressNotAllowed(); address oldRouter = address(s_router); s_router = IRouter(newRouter); @@ -139,7 +143,9 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { } /// @notice Signals which version of the pool interface is supported - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + function supportsInterface( + bytes4 interfaceId + ) public pure virtual override returns (bool) { return interfaceId == Pool.CCIP_POOL_V1 || interfaceId == type(IPoolV1).interfaceId || interfaceId == type(IERC165).interfaceId; } @@ -157,7 +163,9 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// @param lockOrBurnIn The input to validate. /// @dev This function should always be called before executing a lock or burn. Not doing so would allow /// for various exploits. - function _validateLockOrBurn(Pool.LockOrBurnInV1 memory lockOrBurnIn) internal { + function _validateLockOrBurn( + Pool.LockOrBurnInV1 memory lockOrBurnIn + ) internal { if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); _checkAllowList(lockOrBurnIn.originalSender); @@ -175,7 +183,9 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// @param releaseOrMintIn The input to validate. /// @dev This function should always be called before executing a lock or burn. Not doing so would allow /// for various exploits. - function _validateReleaseOrMint(Pool.ReleaseOrMintInV1 memory releaseOrMintIn) internal { + function _validateReleaseOrMint( + Pool.ReleaseOrMintInV1 memory releaseOrMintIn + ) internal { if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); _onlyOffRamp(releaseOrMintIn.remoteChainSelector); @@ -226,7 +236,9 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { } /// @inheritdoc IPoolV1 - function isSupportedChain(uint64 remoteChainSelector) public view returns (bool) { + function isSupportedChain( + uint64 remoteChainSelector + ) public view returns (bool) { return s_remoteChainSelectors.contains(remoteChainSelector); } @@ -337,7 +349,7 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// @param remoteChainSelector The remote chain selector for which the rate limits apply. /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. - function setChainRateLimiterConfig( + function _setChainRateLimiterConfig( address token, uint64 remoteChainSelector, RateLimiter.Config memory outboundConfig, @@ -357,14 +369,18 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender /// is a permissioned onRamp for the given chain on the Router. - function _onlyOnRamp(uint64 remoteChainSelector) internal view { + function _onlyOnRamp( + uint64 remoteChainSelector + ) internal view { if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); } /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender /// is a permissioned offRamp for the given chain on the Router. - function _onlyOffRamp(uint64 remoteChainSelector) internal view { + function _onlyOffRamp( + uint64 remoteChainSelector + ) internal view { if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); } @@ -373,11 +389,13 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { // │ Allowlist │ // ================================================================ - function _checkAllowList(address sender) internal view { - if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); + function _checkAllowList( + address sender + ) internal view { + if (i_allowlistEnabled && !s_allowlist.contains(sender)) revert SenderNotAllowed(sender); } - /// @notice Gets whether the allowList functionality is enabled. + /// @notice Gets whether the allowlist functionality is enabled. /// @return true is enabled, false if not. function getAllowListEnabled() external view returns (bool) { return i_allowlistEnabled; @@ -386,13 +404,13 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the allowed addresses. /// @return The allowed addresses. function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); + return s_allowlist.values(); } /// @notice Apply updates to the allow list. /// @param removes The addresses to be removed. /// @param adds The addresses to be added. - /// @dev allowListing will be removed before public launch + /// @dev allowlisting will be removed before public launch function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { _applyAllowListUpdates(removes, adds); } @@ -403,7 +421,7 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { for (uint256 i = 0; i < removes.length; ++i) { address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { + if (s_allowlist.remove(toRemove)) { emit AllowListRemove(toRemove); } } @@ -412,7 +430,7 @@ abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { if (toAdd == address(0)) { continue; } - if (s_allowList.add(toAdd)) { + if (s_allowlist.add(toAdd)) { emit AllowListAdd(toAdd); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/OCR2Helper.sol b/contracts/src/v0.8/ccip/test/helpers/OCR2Helper.sol deleted file mode 100644 index cb66352ff65..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/OCR2Helper.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OCR2Base} from "../../ocr/OCR2Base.sol"; - -contract OCR2Helper is OCR2Base(false) { - function configDigestFromConfigData( - uint256 chainSelector, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) public pure returns (bytes32) { - return _configDigestFromConfigData( - chainSelector, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - function _report(bytes calldata report, uint40 epochAndRound) internal override {} - - function typeAndVersion() public pure override returns (string memory) { - return "OCR2BaseHelper 1.0.0"; - } - - function _beforeSetConfig(bytes memory _onchainConfig) internal override {} -} diff --git a/contracts/src/v0.8/ccip/test/helpers/OCR2NoChecksHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OCR2NoChecksHelper.sol deleted file mode 100644 index a1ececa326f..00000000000 --- a/contracts/src/v0.8/ccip/test/helpers/OCR2NoChecksHelper.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OCR2BaseNoChecks} from "../../ocr/OCR2BaseNoChecks.sol"; - -contract OCR2NoChecksHelper is OCR2BaseNoChecks { - function configDigestFromConfigData( - uint256 chainSelector, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) public pure returns (bytes32) { - return _configDigestFromConfigData( - chainSelector, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - function _report(bytes calldata report) internal override {} - - function typeAndVersion() public pure override returns (string memory) { - return "OCR2BaseHelper 1.0.0"; - } - - function _beforeSetConfig(bytes memory _onchainConfig) internal override {} -} diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol similarity index 69% rename from contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol rename to contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol index 581d9bd7051..40f7ccb5914 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol @@ -1,19 +1,22 @@ // SPDX-License-Identifier: BUSL-1.1 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"; import {Internal} from "../../libraries/Internal.sol"; -import {EVM2EVMMultiOffRamp} from "../../offRamp/EVM2EVMMultiOffRamp.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; import {IgnoreContractSize} from "./IgnoreContractSize.sol"; -contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { +contract OffRampHelper is OffRamp, IgnoreContractSize { + using EnumerableSet for EnumerableSet.UintSet; + mapping(uint64 sourceChainSelector => uint256 overrideTimestamp) private s_sourceChainVerificationOverride; constructor( StaticConfig memory staticConfig, DynamicConfig memory dynamicConfig, SourceChainConfigArgs[] memory sourceChainConfigs - ) EVM2EVMMultiOffRamp(staticConfig, dynamicConfig, sourceChainConfigs) {} + ) OffRamp(staticConfig, dynamicConfig, sourceChainConfigs) {} function setExecutionStateHelper( uint64 sourceChainSelector, @@ -28,7 +31,7 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { } function releaseOrMintSingleToken( - Internal.RampTokenAmount memory sourceTokenAmount, + Internal.Any2EVMTokenTransfer calldata sourceTokenAmount, bytes calldata originalSender, address receiver, uint64 sourceChainSelector, @@ -39,32 +42,36 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { } function releaseOrMintTokens( - Internal.RampTokenAmount[] memory sourceTokenAmounts, - bytes memory originalSender, + Internal.Any2EVMTokenTransfer[] calldata sourceTokenAmounts, + bytes calldata originalSender, address receiver, uint64 sourceChainSelector, - bytes[] calldata offchainTokenData + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides ) external returns (Client.EVMTokenAmount[] memory) { - return _releaseOrMintTokens(sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData); + return _releaseOrMintTokens( + sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData, tokenGasOverrides + ); } function trialExecute( Internal.Any2EVMRampMessage memory message, - bytes[] memory offchainTokenData + bytes[] memory offchainTokenData, + uint32[] memory tokenGasOverrides ) external returns (Internal.MessageExecutionState, bytes memory) { - return _trialExecute(message, offchainTokenData); + return _trialExecute(message, offchainTokenData, tokenGasOverrides); } function executeSingleReport( - Internal.ExecutionReportSingleChain memory rep, - uint256[] memory manualExecGasLimits + Internal.ExecutionReport memory rep, + GasLimitOverride[] memory manualExecGasExecOverrides ) external { - _executeSingleReport(rep, manualExecGasLimits); + _executeSingleReport(rep, manualExecGasExecOverrides); } function batchExecute( - Internal.ExecutionReportSingleChain[] memory reports, - uint256[][] memory manualExecGasLimits + Internal.ExecutionReport[] memory reports, + GasLimitOverride[][] memory manualExecGasLimits ) external { _batchExecute(reports, manualExecGasLimits); } @@ -100,4 +107,8 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { function setRootTimestamp(uint64 sourceChainSelector, bytes32 root, uint256 timestamp) external { s_roots[sourceChainSelector][root] = timestamp; } + + function getSourceChainSelectors() external view returns (uint256[] memory chainSelectors) { + return s_sourceChainSelectors.values(); + } } diff --git a/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol new file mode 100644 index 00000000000..d315a58fc5d --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {IgnoreContractSize} from "./IgnoreContractSize.sol"; + +contract OnRampHelper is OnRamp, IgnoreContractSize { + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + DestChainConfigArgs[] memory destChainConfigArgs + ) OnRamp(staticConfig, dynamicConfig, destChainConfigArgs) {} +} diff --git a/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol index 8fb96a0c1c3..6cd1c18705a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol @@ -8,7 +8,9 @@ contract RateLimiterHelper { RateLimiter.TokenBucket internal s_rateLimiter; - constructor(RateLimiter.Config memory config) { + constructor( + RateLimiter.Config memory config + ) { s_rateLimiter = RateLimiter.TokenBucket({ rate: config.rate, capacity: config.capacity, @@ -26,7 +28,9 @@ contract RateLimiterHelper { return s_rateLimiter._currentTokenBucketState(); } - function setTokenBucketConfig(RateLimiter.Config memory config) external { + function setTokenBucketConfig( + RateLimiter.Config memory config + ) external { s_rateLimiter._setTokenBucketConfig(config); } diff --git a/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol b/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol index ca53d512c0d..41e4a95b060 100644 --- a/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol +++ b/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol @@ -1,18 +1,22 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; import {Internal} from "../../libraries/Internal.sol"; -import {EVM2EVMMultiOffRamp} from "../../offRamp/EVM2EVMMultiOffRamp.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; contract ReportCodec { - event ExecuteReportDecoded(Internal.ExecutionReportSingleChain[] report); - event CommitReportDecoded(EVM2EVMMultiOffRamp.CommitReport report); + event ExecuteReportDecoded(Internal.ExecutionReport[] report); + event CommitReportDecoded(OffRamp.CommitReport report); - function decodeExecuteReport(bytes memory report) public pure returns (Internal.ExecutionReportSingleChain[] memory) { - return abi.decode(report, (Internal.ExecutionReportSingleChain[])); + function decodeExecuteReport( + bytes memory report + ) public pure returns (Internal.ExecutionReport[] memory) { + return abi.decode(report, (Internal.ExecutionReport[])); } - function decodeCommitReport(bytes memory report) public pure returns (EVM2EVMMultiOffRamp.CommitReport memory) { - return abi.decode(report, (EVM2EVMMultiOffRamp.CommitReport)); + function decodeCommitReport( + bytes memory report + ) public pure returns (OffRamp.CommitReport memory) { + return abi.decode(report, (OffRamp.CommitReport)); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol index c57bfa33119..75f6b1b85df 100644 --- a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -14,29 +14,27 @@ contract TokenPoolHelper is TokenPool { address router ) TokenPool(token, allowlist, rmnProxy, router) {} - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - view - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external view override returns (Pool.LockOrBurnOutV1 memory) { return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - pure - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } - function onlyOnRampModifier(uint64 remoteChainSelector) external view { + function onlyOnRampModifier( + uint64 remoteChainSelector + ) external view { _onlyOnRamp(remoteChainSelector); } - function onlyOffRampModifier(uint64 remoteChainSelector) external view { + function onlyOffRampModifier( + uint64 remoteChainSelector + ) external view { _onlyOffRamp(remoteChainSelector); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol new file mode 100644 index 00000000000..d1baa22de1b --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +contract USDCReaderTester { + event MessageSent(bytes); + + // emitMessageSent reflects the logic from Circle's MessageTransmitter emitting MeseageSent(bytes) events + // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L41 + // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L365 + function emitMessageSent( + uint32 version, + uint32 sourceDomain, + uint32 destinationDomain, + bytes32 recipient, + bytes32 destinationCaller, + bytes32 sender, + uint64 nonce, + bytes calldata messageBody + ) external { + bytes memory _message = + _formatMessage(version, sourceDomain, destinationDomain, nonce, sender, recipient, destinationCaller, messageBody); + emit MessageSent(_message); + } + + /** + * @notice Returns formatted (packed) message with provided fields + * It's a copy paste of the Message._formatMessage() call in MessageTransmitter.sol + * https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/Message.sol#L54C1-L65C9 + * Check the chainlink-ccip repo for the offchain implementation of matching this format + * @param _msgVersion the version of the message format + * @param _msgSourceDomain Domain of home chain + * @param _msgDestinationDomain Domain of destination chain + * @param _msgNonce Destination-specific nonce + * @param _msgSender Address of sender on source chain as bytes32 + * @param _msgRecipient Address of recipient on destination chain as bytes32 + * @param _msgDestinationCaller Address of caller on destination chain as bytes32 + * @param _msgRawBody Raw bytes of message body + * @return Formatted message + * + */ + function _formatMessage( + uint32 _msgVersion, + uint32 _msgSourceDomain, + uint32 _msgDestinationDomain, + uint64 _msgNonce, + bytes32 _msgSender, + bytes32 _msgRecipient, + bytes32 _msgDestinationCaller, + bytes memory _msgRawBody + ) internal pure returns (bytes memory) { + return abi.encodePacked( + _msgVersion, + _msgSourceDomain, + _msgDestinationDomain, + _msgNonce, + _msgSender, + _msgRecipient, + _msgDestinationCaller, + _msgRawBody + ); + } +} 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 159cd7a8514..d4102da0752 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol @@ -9,7 +9,9 @@ contract ConformingReceiver is CCIPReceiver { constructor(address router, address feeToken) CCIPReceiver(router) {} - function _ccipReceive(Client.Any2EVMMessage memory) internal virtual override { + function _ccipReceive( + Client.Any2EVMMessage memory + ) internal virtual override { emit MessageReceived(); } } 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 dd65f202dfe..b40b2c34431 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 { error ReceiveRevert(); @@ -17,33 +17,44 @@ contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 { bool public s_toRevert; bytes private s_err; - constructor(bool toRevert) { + constructor( + bool toRevert + ) { s_manager = msg.sender; s_toRevert = toRevert; } - function setRevert(bool toRevert) external { + function setRevert( + bool toRevert + ) external { s_toRevert = toRevert; } - function setErr(bytes memory err) external { + function setErr( + bytes memory err + ) external { s_err = err; } /// @notice IERC165 supports an interfaceId /// @param interfaceId The interfaceId to check /// @return true if the interfaceId is supported - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + function supportsInterface( + bytes4 interfaceId + ) public pure override returns (bool) { return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } - function ccipReceive(Client.Any2EVMMessage calldata) external override { + function ccipReceive( + Client.Any2EVMMessage calldata + ) external override { if (s_toRevert) { revert CustomError(s_err); } emit MessageReceived(); } + // solhint-disable-next-line no-complex-fallback receive() external payable { if (s_toRevert) { revert ReceiveRevert(); 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 4f56394c4e5..07e5ac8544f 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import "../../../interfaces/IAny2EVMMessageReceiver.sol"; +import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; + +import {Client} from "../../../libraries/Client.sol"; contract MaybeRevertMessageReceiverNo165 is IAny2EVMMessageReceiver { address private s_manager; @@ -9,17 +11,24 @@ contract MaybeRevertMessageReceiverNo165 is IAny2EVMMessageReceiver { event MessageReceived(); - constructor(bool toRevert) { + constructor( + bool toRevert + ) { s_manager = msg.sender; s_toRevert = toRevert; } - function setRevert(bool toRevert) external { + function setRevert( + bool toRevert + ) external { s_toRevert = toRevert; } - function ccipReceive(Client.Any2EVMMessage calldata) external override { + function ccipReceive( + Client.Any2EVMMessage calldata + ) external override { if (s_toRevert) { + // solhint-disable-next-line reason-string,gas-custom-errors revert(); } emit MessageReceived(); 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 ae8759099cd..b8aeeb027ae 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol @@ -4,37 +4,61 @@ pragma solidity 0.8.24; import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; import {Internal} from "../../../libraries/Internal.sol"; -import {EVM2EVMOffRamp} from "../../../offRamp/EVM2EVMOffRamp.sol"; +import {OffRamp} from "../../../offRamp/OffRamp.sol"; contract ReentrancyAbuser is CCIPReceiver { event ReentrancySucceeded(); + uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 144_000; + bool internal s_ReentrancyDone = false; Internal.ExecutionReport internal s_payload; - EVM2EVMOffRamp internal s_offRamp; + OffRamp internal s_offRamp; - constructor(address router, EVM2EVMOffRamp offRamp) CCIPReceiver(router) { + constructor(address router, OffRamp offRamp) CCIPReceiver(router) { s_offRamp = offRamp; } - function setPayload(Internal.ExecutionReport calldata payload) public { + function setPayload( + Internal.ExecutionReport calldata payload + ) public { s_payload = payload; } - function _ccipReceive(Client.Any2EVMMessage memory) internal override { + function _ccipReceive( + Client.Any2EVMMessage memory + ) internal override { // Use original message gas limits in manual execution - uint256 numMsgs = s_payload.messages.length; - uint256[] memory gasOverrides = new uint256[](numMsgs); - for (uint256 i = 0; i < numMsgs; ++i) { - gasOverrides[i] = 0; - } + OffRamp.GasLimitOverride[][] memory gasOverrides = _getGasLimitsFromMessages(s_payload.messages); if (!s_ReentrancyDone) { // Could do more rounds but a PoC one is enough s_ReentrancyDone = true; - s_offRamp.manuallyExecute(s_payload, gasOverrides); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](1); + reports[0] = s_payload; + + s_offRamp.manuallyExecute(reports, gasOverrides); } else { emit ReentrancySucceeded(); } } + + function _getGasLimitsFromMessages( + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (OffRamp.GasLimitOverride[][] memory) { + OffRamp.GasLimitOverride[] memory gasLimitOverrides = new OffRamp.GasLimitOverride[](messages.length); + for (uint256 i = 0; i < messages.length; ++i) { + gasLimitOverrides[i].receiverExecutionGasLimit = messages[i].gasLimit; + gasLimitOverrides[i].tokenGasOverrides = new uint32[](messages[i].tokenAmounts.length); + + for (uint256 j = 0; j < messages[i].tokenAmounts.length; ++j) { + gasLimitOverrides[i].tokenGasOverrides[j] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; + } + } + + OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); + gasOverrides[0] = gasLimitOverrides; + return gasOverrides; + } } diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol index c9e7d7e8ad6..d3d0fd320f9 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol @@ -4,33 +4,38 @@ pragma solidity ^0.8.19; import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; import {Internal} from "../../../libraries/Internal.sol"; -import {EVM2EVMMultiOffRamp} from "../../../offRamp/EVM2EVMMultiOffRamp.sol"; +import {OffRamp} from "../../../offRamp/OffRamp.sol"; contract ReentrancyAbuserMultiRamp is CCIPReceiver { event ReentrancySucceeded(); bool internal s_ReentrancyDone = false; - Internal.ExecutionReportSingleChain internal s_payload; - EVM2EVMMultiOffRamp internal s_offRamp; + Internal.ExecutionReport internal s_payload; + OffRamp internal s_offRamp; - constructor(address router, EVM2EVMMultiOffRamp offRamp) CCIPReceiver(router) { + constructor(address router, OffRamp offRamp) CCIPReceiver(router) { s_offRamp = offRamp; } - function setPayload(Internal.ExecutionReportSingleChain calldata payload) public { + function setPayload( + Internal.ExecutionReport calldata payload + ) public { s_payload = payload; } - function _ccipReceive(Client.Any2EVMMessage memory) internal override { + function _ccipReceive( + Client.Any2EVMMessage memory + ) internal override { // Use original message gas limits in manual execution uint256 numMsgs = s_payload.messages.length; - uint256[][] memory gasOverrides = new uint256[][](1); - gasOverrides[0] = new uint256[](numMsgs); + OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); + gasOverrides[0] = new OffRamp.GasLimitOverride[](numMsgs); for (uint256 i = 0; i < numMsgs; ++i) { - gasOverrides[0][i] = 0; + gasOverrides[0][i].receiverExecutionGasLimit = 0; + gasOverrides[0][i].tokenGasOverrides = new uint32[](s_payload.messages[i].tokenAmounts.length); } - Internal.ExecutionReportSingleChain[] memory batchPayload = new Internal.ExecutionReportSingleChain[](1); + Internal.ExecutionReport[] memory batchPayload = new Internal.ExecutionReport[](1); batchPayload[0] = s_payload; if (!s_ReentrancyDone) { diff --git a/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_2.sol b/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_2.sol deleted file mode 100644 index 2e7878730ea..00000000000 --- a/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_2.sol +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IPoolPriorTo1_5} from "../../interfaces/IPoolPriorTo1_5.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; - -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice Base abstract class with common functions for all token pools. -/// A token pool serves as isolated place for holding tokens and token specific logic -/// that may execute as tokens move across the bridge. -abstract contract TokenPool1_2 is IPoolPriorTo1_5, OwnerIsCreator, IERC165 { - using EnumerableSet for EnumerableSet.AddressSet; - using RateLimiter for RateLimiter.TokenBucket; - - error PermissionsError(); - error ZeroAddressNotAllowed(); - error SenderNotAllowed(address sender); - error AllowListNotEnabled(); - error NonExistentRamp(address ramp); - error BadARMSignal(); - error RampAlreadyExists(address ramp); - - event Locked(address indexed sender, uint256 amount); - event Burned(address indexed sender, uint256 amount); - event Released(address indexed sender, address indexed recipient, uint256 amount); - event Minted(address indexed sender, address indexed recipient, uint256 amount); - event OnRampAdded(address onRamp, RateLimiter.Config rateLimiterConfig); - event OnRampConfigured(address onRamp, RateLimiter.Config rateLimiterConfig); - event OnRampRemoved(address onRamp); - event OffRampAdded(address offRamp, RateLimiter.Config rateLimiterConfig); - event OffRampConfigured(address offRamp, RateLimiter.Config rateLimiterConfig); - event OffRampRemoved(address offRamp); - event AllowListAdd(address sender); - event AllowListRemove(address sender); - - struct RampUpdate { - address ramp; - bool allowed; - RateLimiter.Config rateLimiterConfig; - } - - /// @dev The bridgeable token that is managed by this pool. - IERC20 internal immutable i_token; - /// @dev The address of the arm proxy - address internal immutable i_armProxy; - /// @dev The immutable flag that indicates if the pool is access-controlled. - bool internal immutable i_allowlistEnabled; - /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. - /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can - /// move tokens. - EnumerableSet.AddressSet internal s_allowList; - - /// @dev A set of allowed onRamps. We want the whitelist to be enumerable to - /// be able to quickly determine (without parsing logs) who can access the pool. - EnumerableSet.AddressSet internal s_onRamps; - /// @dev Inbound rate limits. This allows per destination chain - /// token issuer specified rate limiting (e.g. issuers may trust chains to varying - /// degrees and prefer different limits) - mapping(address => RateLimiter.TokenBucket) internal s_onRampRateLimits; - /// @dev A set of allowed offRamps. - EnumerableSet.AddressSet internal s_offRamps; - /// @dev Outbound rate limits. Corresponds to the inbound rate limit for the pool - /// on the remote chain. - mapping(address => RateLimiter.TokenBucket) internal s_offRampRateLimits; - - constructor(IERC20 token, address[] memory allowlist, address armProxy) { - if (address(token) == address(0)) revert ZeroAddressNotAllowed(); - i_token = token; - i_armProxy = armProxy; - - // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. - i_allowlistEnabled = allowlist.length > 0; - if (i_allowlistEnabled) { - _applyAllowListUpdates(new address[](0), allowlist); - } - } - - /// @notice Get ARM proxy address - /// @return armProxy Address of arm proxy - function getArmProxy() public view returns (address armProxy) { - return i_armProxy; - } - - /// @inheritdoc IPoolPriorTo1_5 - function getToken() public view override returns (IERC20 token) { - return i_token; - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { - return interfaceId == type(IPoolPriorTo1_5).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // │ Ramp permissions │ - // ================================================================ - - /// @notice Checks whether something is a permissioned onRamp on this contract. - /// @return true if the given address is a permissioned onRamp. - function isOnRamp(address onRamp) public view returns (bool) { - return s_onRamps.contains(onRamp); - } - - /// @notice Checks whether something is a permissioned offRamp on this contract. - /// @return true if the given address is a permissioned offRamp. - function isOffRamp(address offRamp) public view returns (bool) { - return s_offRamps.contains(offRamp); - } - - /// @notice Get onRamp whitelist - /// @return list of onRamps. - function getOnRamps() public view returns (address[] memory) { - return s_onRamps.values(); - } - - /// @notice Get offRamp whitelist - /// @return list of offramps - function getOffRamps() public view returns (address[] memory) { - return s_offRamps.values(); - } - - /// @notice Sets permissions for all on and offRamps. - /// @dev Only callable by the owner - /// @param onRamps A list of onRamps and their new permission status/rate limits - /// @param offRamps A list of offRamps and their new permission status/rate limits - function applyRampUpdates(RampUpdate[] calldata onRamps, RampUpdate[] calldata offRamps) external virtual onlyOwner { - _applyRampUpdates(onRamps, offRamps); - } - - function _applyRampUpdates(RampUpdate[] calldata onRamps, RampUpdate[] calldata offRamps) internal onlyOwner { - for (uint256 i = 0; i < onRamps.length; ++i) { - RampUpdate memory update = onRamps[i]; - if (update.allowed) { - if (s_onRamps.add(update.ramp)) { - s_onRampRateLimits[update.ramp] = RateLimiter.TokenBucket({ - rate: update.rateLimiterConfig.rate, - capacity: update.rateLimiterConfig.capacity, - tokens: update.rateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.rateLimiterConfig.isEnabled - }); - emit OnRampAdded(update.ramp, update.rateLimiterConfig); - } else { - revert RampAlreadyExists(update.ramp); - } - } else { - if (s_onRamps.remove(update.ramp)) { - delete s_onRampRateLimits[update.ramp]; - emit OnRampRemoved(update.ramp); - } else { - // Cannot remove a non-existent onRamp. - revert NonExistentRamp(update.ramp); - } - } - } - - for (uint256 i = 0; i < offRamps.length; ++i) { - RampUpdate memory update = offRamps[i]; - if (update.allowed) { - if (s_offRamps.add(update.ramp)) { - s_offRampRateLimits[update.ramp] = RateLimiter.TokenBucket({ - rate: update.rateLimiterConfig.rate, - capacity: update.rateLimiterConfig.capacity, - tokens: update.rateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.rateLimiterConfig.isEnabled - }); - emit OffRampAdded(update.ramp, update.rateLimiterConfig); - } else { - revert RampAlreadyExists(update.ramp); - } - } else { - if (s_offRamps.remove(update.ramp)) { - delete s_offRampRateLimits[update.ramp]; - emit OffRampRemoved(update.ramp); - } else { - // Cannot remove a non-existent offRamp. - revert NonExistentRamp(update.ramp); - } - } - } - } - - // ================================================================ - // │ Rate limiting │ - // ================================================================ - - /// @notice Consumes outbound rate limiting capacity in this pool - function _consumeOnRampRateLimit(uint256 amount) internal { - s_onRampRateLimits[msg.sender]._consume(amount, address(i_token)); - } - - /// @notice Consumes inbound rate limiting capacity in this pool - function _consumeOffRampRateLimit(uint256 amount) internal { - s_offRampRateLimits[msg.sender]._consume(amount, address(i_token)); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function currentOnRampRateLimiterState(address onRamp) external view returns (RateLimiter.TokenBucket memory) { - return s_onRampRateLimits[onRamp]._currentTokenBucketState(); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function currentOffRampRateLimiterState(address offRamp) external view returns (RateLimiter.TokenBucket memory) { - return s_offRampRateLimits[offRamp]._currentTokenBucketState(); - } - - /// @notice Sets the onramp rate limited config. - /// @param config The new rate limiter config. - function setOnRampRateLimiterConfig(address onRamp, RateLimiter.Config memory config) external onlyOwner { - if (!isOnRamp(onRamp)) revert NonExistentRamp(onRamp); - s_onRampRateLimits[onRamp]._setTokenBucketConfig(config); - emit OnRampConfigured(onRamp, config); - } - - /// @notice Sets the offramp rate limited config. - /// @param config The new rate limiter config. - function setOffRampRateLimiterConfig(address offRamp, RateLimiter.Config memory config) external onlyOwner { - if (!isOffRamp(offRamp)) revert NonExistentRamp(offRamp); - s_offRampRateLimits[offRamp]._setTokenBucketConfig(config); - emit OffRampConfigured(offRamp, config); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Checks whether the msg.sender is a permissioned onRamp on this contract - /// @dev Reverts with a PermissionsError if check fails - modifier onlyOnRamp() { - if (!isOnRamp(msg.sender)) revert PermissionsError(); - _; - } - - /// @notice Checks whether the msg.sender is a permissioned offRamp on this contract - /// @dev Reverts with a PermissionsError if check fails - modifier onlyOffRamp() { - if (!isOffRamp(msg.sender)) revert PermissionsError(); - _; - } - - // ================================================================ - // │ Allowlist │ - // ================================================================ - - modifier checkAllowList(address sender) { - if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); - _; - } - - /// @notice Gets whether the allowList functionality is enabled. - /// @return true is enabled, false if not. - function getAllowListEnabled() external view returns (bool) { - return i_allowlistEnabled; - } - - /// @notice Gets the allowed addresses. - /// @return The allowed addresses. - function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); - } - - /// @notice Apply updates to the allow list. - /// @param removes The addresses to be removed. - /// @param adds The addresses to be added. - /// @dev allowListing will be removed before public launch - function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { - _applyAllowListUpdates(removes, adds); - } - - /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. - function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { - if (!i_allowlistEnabled) revert AllowListNotEnabled(); - - for (uint256 i = 0; i < removes.length; ++i) { - address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { - emit AllowListRemove(toRemove); - } - } - for (uint256 i = 0; i < adds.length; ++i) { - address toAdd = adds[i]; - if (toAdd == address(0)) { - continue; - } - if (s_allowList.add(toAdd)) { - emit AllowListAdd(toAdd); - } - } - } - - /// @notice Ensure that there is no active curse. - modifier whenHealthy() { - if (IRMN(i_armProxy).isCursed()) revert BadARMSignal(); - _; - } -} - -contract BurnMintTokenPool1_2 is ITypeAndVersion, TokenPool1_2 { - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override typeAndVersion = "BurnMintTokenPool 1.2.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address armProxy - ) TokenPool1_2(token, allowlist, armProxy) {} - - /// @notice Burn the token in the pool - /// @param amount Amount to burn - /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised - /// we're able to stop token movement via ARM. - function lockOrBurn( - address originalSender, - bytes calldata, - uint256 amount, - uint64, - bytes calldata - ) external virtual override onlyOnRamp checkAllowList(originalSender) whenHealthy returns (bytes memory) { - _consumeOnRampRateLimit(amount); - IBurnMintERC20(address(i_token)).burn(amount); - emit Burned(msg.sender, amount); - return ""; - } - - /// @notice Mint tokens from the pool to the recipient - /// @param receiver Recipient address - /// @param amount Amount to mint - /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised - /// we're able to stop token movement via ARM. - function releaseOrMint( - bytes memory, - address receiver, - uint256 amount, - uint64, - bytes memory - ) external virtual override whenHealthy onlyOffRamp { - _consumeOffRampRateLimit(amount); - IBurnMintERC20(address(i_token)).mint(receiver, amount); - emit Minted(msg.sender, receiver, amount); - } -} diff --git a/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol b/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol deleted file mode 100644 index 9ac5d66b1cf..00000000000 --- a/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol +++ /dev/null @@ -1,402 +0,0 @@ -// 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 {IPoolPriorTo1_5} from "../../interfaces/IPoolPriorTo1_5.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; -import {IRouter} from "../../interfaces/IRouter.sol"; - -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice Base abstract class with common functions for all token pools. -/// A token pool serves as isolated place for holding tokens and token specific logic -/// that may execute as tokens move across the bridge. -abstract contract TokenPool1_4 is IPoolPriorTo1_5, OwnerIsCreator, IERC165 { - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - using RateLimiter for RateLimiter.TokenBucket; - - error CallerIsNotARampOnRouter(address caller); - error ZeroAddressNotAllowed(); - error SenderNotAllowed(address sender); - error AllowListNotEnabled(); - error NonExistentChain(uint64 remoteChainSelector); - error ChainNotAllowed(uint64 remoteChainSelector); - error BadARMSignal(); - error ChainAlreadyExists(uint64 chainSelector); - - event Locked(address indexed sender, uint256 amount); - event Burned(address indexed sender, uint256 amount); - event Released(address indexed sender, address indexed recipient, uint256 amount); - event Minted(address indexed sender, address indexed recipient, uint256 amount); - event ChainAdded( - uint64 remoteChainSelector, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainConfigured( - uint64 remoteChainSelector, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainRemoved(uint64 remoteChainSelector); - event AllowListAdd(address sender); - event AllowListRemove(address sender); - event RouterUpdated(address oldRouter, address newRouter); - - struct ChainUpdate { - uint64 remoteChainSelector; // ──╮ Remote chain selector - bool allowed; // ────────────────╯ Whether the chain is allowed - RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain - RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - } - - /// @dev The bridgeable token that is managed by this pool. - IERC20 internal immutable i_token; - /// @dev The address of the arm proxy - address internal immutable i_armProxy; - /// @dev The immutable flag that indicates if the pool is access-controlled. - bool internal immutable i_allowlistEnabled; - /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. - /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can - /// move tokens. - EnumerableSet.AddressSet internal s_allowList; - /// @dev The address of the router - IRouter internal s_router; - /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to - /// be able to quickly determine (without parsing logs) who can access the pool. - /// @dev The chain selectors are in uin256 format because of the EnumerableSet implementation. - EnumerableSet.UintSet internal s_remoteChainSelectors; - /// @dev Outbound rate limits. Corresponds to the inbound rate limit for the pool - /// on the remote chain. - mapping(uint64 remoteChainSelector => RateLimiter.TokenBucket) internal s_outboundRateLimits; - /// @dev Inbound rate limits. This allows per destination chain - /// token issuer specified rate limiting (e.g. issuers may trust chains to varying - /// degrees and prefer different limits) - mapping(uint64 remoteChainSelector => RateLimiter.TokenBucket) internal s_inboundRateLimits; - - constructor(IERC20 token, address[] memory allowlist, address armProxy, address router) { - if (address(token) == address(0) || router == address(0)) revert ZeroAddressNotAllowed(); - i_token = token; - i_armProxy = armProxy; - s_router = IRouter(router); - - // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. - i_allowlistEnabled = allowlist.length > 0; - if (i_allowlistEnabled) { - _applyAllowListUpdates(new address[](0), allowlist); - } - } - - /// @notice Get ARM proxy address - /// @return armProxy Address of arm proxy - function getArmProxy() public view returns (address armProxy) { - return i_armProxy; - } - - /// @inheritdoc IPoolPriorTo1_5 - function getToken() public view override returns (IERC20 token) { - return i_token; - } - - /// @notice Gets the pool's Router - /// @return router The pool's Router - function getRouter() public view returns (address router) { - return address(s_router); - } - - /// @notice Sets the pool's Router - /// @param newRouter The new Router - function setRouter(address newRouter) public onlyOwner { - if (newRouter == address(0)) revert ZeroAddressNotAllowed(); - address oldRouter = address(s_router); - s_router = IRouter(newRouter); - - emit RouterUpdated(oldRouter, newRouter); - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { - return interfaceId == type(IPoolPriorTo1_5).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // │ Chain permissions │ - // ================================================================ - - /// @notice Checks whether a chain selector is permissioned on this contract. - /// @return true if the given chain selector is a permissioned remote chain. - function isSupportedChain(uint64 remoteChainSelector) public view returns (bool) { - return s_remoteChainSelectors.contains(remoteChainSelector); - } - - /// @notice Get list of allowed chains - /// @return list of chains. - function getSupportedChains() public view returns (uint64[] memory) { - uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); - uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); - for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { - chainSelectors[i] = uint64(uint256ChainSelectors[i]); - } - - return chainSelectors; - } - - /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains - /// need to be allowed on the Router to interact with this pool. - /// @dev Only callable by the owner - /// @param chains A list of chains and their new permission status & rate limits. Rate limits - /// are only used when the chain is being added through `allowed` being true. - function applyChainUpdates(ChainUpdate[] calldata chains) external virtual onlyOwner { - for (uint256 i = 0; i < chains.length; ++i) { - ChainUpdate memory update = chains[i]; - RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); - RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); - - if (update.allowed) { - // If the chain already exists, revert - if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { - revert ChainAlreadyExists(update.remoteChainSelector); - } - - s_outboundRateLimits[update.remoteChainSelector] = RateLimiter.TokenBucket({ - rate: update.outboundRateLimiterConfig.rate, - capacity: update.outboundRateLimiterConfig.capacity, - tokens: update.outboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.outboundRateLimiterConfig.isEnabled - }); - - s_inboundRateLimits[update.remoteChainSelector] = RateLimiter.TokenBucket({ - rate: update.inboundRateLimiterConfig.rate, - capacity: update.inboundRateLimiterConfig.capacity, - tokens: update.inboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.inboundRateLimiterConfig.isEnabled - }); - emit ChainAdded(update.remoteChainSelector, update.outboundRateLimiterConfig, update.inboundRateLimiterConfig); - } else { - // If the chain doesn't exist, revert - if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { - revert NonExistentChain(update.remoteChainSelector); - } - - delete s_inboundRateLimits[update.remoteChainSelector]; - delete s_outboundRateLimits[update.remoteChainSelector]; - emit ChainRemoved(update.remoteChainSelector); - } - } - } - - // ================================================================ - // │ Rate limiting │ - // ================================================================ - - /// @notice Consumes outbound rate limiting capacity in this pool - function _consumeOutboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { - s_outboundRateLimits[remoteChainSelector]._consume(amount, address(i_token)); - } - - /// @notice Consumes inbound rate limiting capacity in this pool - function _consumeInboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { - s_inboundRateLimits[remoteChainSelector]._consume(amount, address(i_token)); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentOutboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { - return s_outboundRateLimits[remoteChainSelector]._currentTokenBucketState(); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentInboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { - return s_inboundRateLimits[remoteChainSelector]._currentTokenBucketState(); - } - - /// @notice Sets the chain rate limiter config. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. - /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. - function setChainRateLimiterConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) external virtual onlyOwner { - _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); - } - - function _setRateLimitConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) internal { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - RateLimiter._validateTokenBucketConfig(outboundConfig, false); - s_outboundRateLimits[remoteChainSelector]._setTokenBucketConfig(outboundConfig); - RateLimiter._validateTokenBucketConfig(inboundConfig, false); - s_inboundRateLimits[remoteChainSelector]._setTokenBucketConfig(inboundConfig); - emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned onRamp for the given chain on the Router. - modifier onlyOnRamp(uint64 remoteChainSelector) { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); - _; - } - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned offRamp for the given chain on the Router. - modifier onlyOffRamp(uint64 remoteChainSelector) { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); - _; - } - - // ================================================================ - // │ Allowlist │ - // ================================================================ - - modifier checkAllowList(address sender) { - if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); - _; - } - - /// @notice Gets whether the allowList functionality is enabled. - /// @return true is enabled, false if not. - function getAllowListEnabled() external view returns (bool) { - return i_allowlistEnabled; - } - - /// @notice Gets the allowed addresses. - /// @return The allowed addresses. - function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); - } - - /// @notice Apply updates to the allow list. - /// @param removes The addresses to be removed. - /// @param adds The addresses to be added. - /// @dev allowListing will be removed before public launch - function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { - _applyAllowListUpdates(removes, adds); - } - - /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. - function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { - if (!i_allowlistEnabled) revert AllowListNotEnabled(); - - for (uint256 i = 0; i < removes.length; ++i) { - address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { - emit AllowListRemove(toRemove); - } - } - for (uint256 i = 0; i < adds.length; ++i) { - address toAdd = adds[i]; - if (toAdd == address(0)) { - continue; - } - if (s_allowList.add(toAdd)) { - emit AllowListAdd(toAdd); - } - } - } - - /// @notice Ensure that there is no active curse. - modifier whenHealthy() { - if (IRMN(i_armProxy).isCursed()) revert BadARMSignal(); - _; - } -} - -abstract contract BurnMintTokenPoolAbstract is TokenPool1_4 { - /// @notice Contains the specific burn call for a pool. - /// @dev overriding this method allows us to create pools with different burn signatures - /// without duplicating the underlying logic. - function _burn(uint256 amount) internal virtual; - - /// @notice Burn the token in the pool - /// @param amount Amount to burn - /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised - /// we're able to stop token movement via ARM. - function lockOrBurn( - address originalSender, - bytes calldata, - uint256 amount, - uint64 remoteChainSelector, - bytes calldata - ) - external - virtual - override - onlyOnRamp(remoteChainSelector) - checkAllowList(originalSender) - whenHealthy - returns (bytes memory) - { - _consumeOutboundRateLimit(remoteChainSelector, amount); - _burn(amount); - emit Burned(msg.sender, amount); - return ""; - } - - /// @notice Mint tokens from the pool to the recipient - /// @param receiver Recipient address - /// @param amount Amount to mint - /// @dev The whenHealthy check is important to ensure that even if a ramp is compromised - /// we're able to stop token movement via ARM. - function releaseOrMint( - bytes memory, - address receiver, - uint256 amount, - uint64 remoteChainSelector, - bytes memory - ) external virtual override whenHealthy onlyOffRamp(remoteChainSelector) { - _consumeInboundRateLimit(remoteChainSelector, amount); - IBurnMintERC20(address(i_token)).mint(receiver, amount); - emit Minted(msg.sender, receiver, amount); - } -} - -/// @notice This pool mints and burns a 3rd-party token. -/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. -/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. -/// The only way to change whitelisting mode is to deploy a new pool. -/// If that is expected, please make sure the token's burner/minter roles are adjustable. -contract BurnMintTokenPool1_4 is BurnMintTokenPoolAbstract, ITypeAndVersion { - string public constant override typeAndVersion = "BurnMintTokenPool 1.4.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address armProxy, - address router - ) TokenPool1_4(token, allowlist, armProxy, router) {} - - /// @inheritdoc BurnMintTokenPoolAbstract - function _burn(uint256 amount) internal virtual override { - IBurnMintERC20(address(i_token)).burn(amount); - } -} diff --git a/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol b/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol deleted file mode 100644 index 292ac9a3bfd..00000000000 --- a/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol +++ /dev/null @@ -1,771 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {IPoolPriorTo1_5} from "../../interfaces/IPoolPriorTo1_5.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnMintTokenPoolAndProxy} from "../../pools/BurnMintTokenPoolAndProxy.sol"; -import {LockReleaseTokenPoolAndProxy} from "../../pools/LockReleaseTokenPoolAndProxy.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; -import {EVM2EVMOnRampHelper} from "../helpers/EVM2EVMOnRampHelper.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; -import {BurnMintTokenPool1_2, TokenPool1_2} from "./BurnMintTokenPool1_2.sol"; -import {BurnMintTokenPool1_4, TokenPool1_4} from "./BurnMintTokenPool1_4.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -contract TokenPoolAndProxyMigration is EVM2EVMOnRampSetup { - BurnMintTokenPoolAndProxy internal s_newPool; - IPoolPriorTo1_5 internal s_legacyPool; - BurnMintERC677 internal s_token; - - address internal s_offRamp; - address internal s_sourcePool = makeAddr("source_pool"); - address internal s_sourceToken = makeAddr("source_token"); - uint256 internal constant AMOUNT = 1; - - function setUp() public virtual override { - super.setUp(); - // Create a system with a token and a legacy pool - s_token = new BurnMintERC677("Test", "TEST", 18, type(uint256).max); - // dealing doesn't update the total supply, meaning the first time we burn a token we underflow, which isn't - // guarded against. Then, when we mint a token, we overflow, which is guarded against and will revert. - s_token.grantMintAndBurnRoles(OWNER); - s_token.mint(OWNER, 1e18); - - s_offRamp = s_offRamps[0]; - // Approve enough for a few calls - s_token.approve(address(s_sourceRouter), AMOUNT * 100); - - // Approve infinite fee tokens - IERC20(s_sourceFeeToken).approve(address(s_sourceRouter), type(uint256).max); - } - - /// @notice This test covers the entire migration plan for 1.0-1.2 pools to 1.5 pools. For simplicity - /// we will refer to the 1.0/1.2 pools as 1.2 pools, as they are functionally the same. - function test_tokenPoolMigration_Success_1_2() public { - // ================================================================ - // | 1 1.2 prior to upgrade | - // ================================================================ - _deployPool1_2(); - - // Ensure everything works on the 1.2 pool - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 2 Deploy self serve | - // ================================================================ - _deploySelfServe(); - - // This doesn't impact the 1.2 pool, so it should still be functional - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 3 Configure new pool on old pool | - // ================================================================ - // In the 1.2 case, everything keeps working on both the 1.2 and 1.5 pools. This config can be - // done in advance of the actual swap to 1.5 lanes. - vm.startPrank(OWNER); - TokenPool1_2.RampUpdate[] memory rampUpdates = new TokenPool1_2.RampUpdate[](1); - rampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_newPool), - allowed: true, - // The rate limits should be turned off for this fake ramp, as the 1.5 pool will handle all the - // rate limiting for us. - rateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - // Since this call doesn't impact the usability of the old pool, we can do it whenever we want - BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(rampUpdates, rampUpdates); - - // Assert the 1.2 lanes still work - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 4 Update the router with to 1.5 | - // ================================================================ - - // This will stop any new messages entering the old lanes, and will direct all traffic to the - // new 1.5 lanes, and therefore to the 1.5 pools. Note that the old pools will still receive - // inflight messages, and will need to continue functioning until all of those are processed. - _fakeReleaseOrMintFromOffRamp_OLD(); - - // Everything is configured, we can now send a ccip tx to the new pool - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // ================================================================ - // | 5 Migrate to using 1.5 the pool | - // ================================================================ - // Turn off the legacy pool, this enabled the 1.5 pool logic. This should be done AFTER the new pool - // has gotten permissions to mint/burn. We see the case where that isn't done below. - vm.startPrank(OWNER); - s_newPool.setPreviousPool(IPoolPriorTo1_5(address(0))); - - // The new pool is now active, but is has not been given permissions to burn/mint yet - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, address(s_newPool))); - _ccipSend1_5(); - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, address(s_newPool))); - _fakeReleaseOrMintFromOffRamp1_5(); - - // When we do give burn/mint, the new pool is fully active - vm.startPrank(OWNER); - s_token.grantMintAndBurnRoles(address(s_newPool)); - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // Even after the pool has taken over as primary, the old pool can still process messages from the old lane - _fakeReleaseOrMintFromOffRamp_OLD(); - } - - function test_tokenPoolMigration_Success_1_4() public { - // ================================================================ - // | 1 1.4 prior to upgrade | - // ================================================================ - _deployPool1_4(); - - // Ensure everything works on the 1.4 pool - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 2 Deploy self serve | - // ================================================================ - _deploySelfServe(); - - // This doesn't impact the 1.4 pool, so it should still be functional - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 3 Configure new pool on old pool | - // | AND | - // | Update the router with to 1.5 | - // ================================================================ - // NOTE: when this call is made, the SENDING SIDE of old lanes stop working. - vm.startPrank(OWNER); - BurnMintTokenPool1_4(address(s_legacyPool)).setRouter(address(s_newPool)); - - // This will stop any new messages entering the old lanes, and will direct all traffic to the - // new 1.5 lanes, and therefore to the 1.5 pools. Note that the old pools will still receive - // inflight messages, and will need to continue functioning until all of those are processed. - _fakeReleaseOrMintFromOffRamp_OLD(); - - // Sending to the old 1.4 pool no longer works - _ccipSend_OLD_Reverts(); - - // Everything is configured, we can now send a ccip tx - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // ================================================================ - // | 4 Migrate to using 1.5 the pool | - // ================================================================ - // Turn off the legacy pool, this enabled the 1.5 pool logic. This should be done AFTER the new pool - // has gotten permissions to mint/burn. We see the case where that isn't done below. - vm.startPrank(OWNER); - s_newPool.setPreviousPool(IPoolPriorTo1_5(address(0))); - - // The new pool is now active, but is has not been given permissions to burn/mint yet - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, address(s_newPool))); - _ccipSend1_5(); - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, address(s_newPool))); - _fakeReleaseOrMintFromOffRamp1_5(); - - // When we do give burn/mint, the new pool is fully active - vm.startPrank(OWNER); - s_token.grantMintAndBurnRoles(address(s_newPool)); - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // Even after the pool has taken over as primary, the old pool can still process messages from the old lane - _fakeReleaseOrMintFromOffRamp_OLD(); - } - - function _ccipSend_OLD() internal { - // We send the funds to the pool manually, as the ramp normally does that - deal(address(s_token), address(s_legacyPool), AMOUNT); - vm.startPrank(address(s_onRamp)); - s_legacyPool.lockOrBurn(OWNER, abi.encode(OWNER), AMOUNT, DEST_CHAIN_SELECTOR, ""); - } - - function _ccipSend_OLD_Reverts() internal { - // We send the funds to the pool manually, as the ramp normally does that - deal(address(s_token), address(s_legacyPool), AMOUNT); - vm.startPrank(address(s_onRamp)); - - vm.expectRevert(abi.encodeWithSelector(TokenPool1_4.CallerIsNotARampOnRouter.selector, address(s_onRamp))); - - s_legacyPool.lockOrBurn(OWNER, abi.encode(OWNER), AMOUNT, DEST_CHAIN_SELECTOR, ""); - } - - function _ccipSend1_5() internal { - vm.startPrank(address(OWNER)); - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: address(s_token), amount: AMOUNT}); - - s_sourceRouter.ccipSend( - DEST_CHAIN_SELECTOR, - Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: "" - }) - ); - } - - function _fakeReleaseOrMintFromOffRamp1_5() internal { - // This is a fake call to simulate the release or mint from the "offRamp" - vm.startPrank(s_offRamp); - s_newPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - receiver: OWNER, - amount: AMOUNT, - localToken: address(s_token), - sourcePoolAddress: abi.encode(s_sourcePool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function _fakeReleaseOrMintFromOffRamp_OLD() internal { - // This is a fake call to simulate the release or mint from the "offRamp" - vm.startPrank(s_offRamp); - s_legacyPool.releaseOrMint(abi.encode(OWNER), OWNER, AMOUNT, SOURCE_CHAIN_SELECTOR, ""); - } - - function _deployPool1_2() internal { - vm.startPrank(OWNER); - s_legacyPool = new BurnMintTokenPool1_2(s_token, new address[](0), address(s_mockRMN)); - s_token.grantMintAndBurnRoles(address(s_legacyPool)); - - TokenPool1_2.RampUpdate[] memory onRampUpdates = new TokenPool1_2.RampUpdate[](1); - onRampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_onRamp), - allowed: true, - rateLimiterConfig: getInboundRateLimiterConfig() - }); - TokenPool1_2.RampUpdate[] memory offRampUpdates = new TokenPool1_2.RampUpdate[](1); - offRampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_offRamp), - allowed: true, - rateLimiterConfig: getInboundRateLimiterConfig() - }); - BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(onRampUpdates, offRampUpdates); - } - - function _deployPool1_4() internal { - vm.startPrank(OWNER); - s_legacyPool = new BurnMintTokenPool1_4(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_token.grantMintAndBurnRoles(address(s_legacyPool)); - - TokenPool1_4.ChainUpdate[] memory legacyChainUpdates = new TokenPool1_4.ChainUpdate[](2); - legacyChainUpdates[0] = TokenPool1_4.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - legacyChainUpdates[1] = TokenPool1_4.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - BurnMintTokenPool1_4(address(s_legacyPool)).applyChainUpdates(legacyChainUpdates); - } - - function _deploySelfServe() internal { - vm.startPrank(OWNER); - // Deploy the new pool - s_newPool = new BurnMintTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - // Set the previous pool on the new pool - s_newPool.setPreviousPool(s_legacyPool); - - // Configure the lanes just like the legacy pool - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_sourcePool), - remoteTokenAddress: abi.encode(s_sourceToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - s_newPool.applyChainUpdates(chainUpdates); - - // Register the token on the token admin registry - s_tokenAdminRegistry.proposeAdministrator(address(s_token), OWNER); - // Accept ownership of the token - s_tokenAdminRegistry.acceptAdminRole(address(s_token)); - // Set the pool on the admin registry - s_tokenAdminRegistry.setPool(address(s_token), address(s_newPool)); - } -} - -contract TokenPoolAndProxy is EVM2EVMOnRampSetup { - event Burned(address indexed sender, uint256 amount); - event Minted(address indexed sender, address indexed recipient, uint256 amount); - - IPoolV1 internal s_pool; - BurnMintERC677 internal s_token; - IPoolPriorTo1_5 internal s_legacyPool; - address internal s_fakeOffRamp = makeAddr("off_ramp"); - - address internal s_destPool = makeAddr("dest_pool"); - - function setUp() public virtual override { - super.setUp(); - s_token = BurnMintERC677(s_sourceFeeToken); - - Router.OffRamp[] memory fakeOffRamps = new Router.OffRamp[](1); - fakeOffRamps[0] = Router.OffRamp({sourceChainSelector: DEST_CHAIN_SELECTOR, offRamp: s_fakeOffRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), fakeOffRamps); - - s_token.grantMintAndBurnRoles(OWNER); - s_token.mint(OWNER, 1e18); - } - - function test_lockOrBurn_burnMint_Success() public { - s_pool = new BurnMintTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - _configurePool(); - _deployOldPool(); - _assertLockOrBurnCorrect(); - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(IPoolPriorTo1_5(address(0))); - - _assertReleaseOrMintCorrect(); - } - - function test_lockOrBurn_lockRelease_Success() public { - s_pool = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - _configurePool(); - _deployOldPool(); - _assertLockOrBurnCorrect(); - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(IPoolPriorTo1_5(address(0))); - - _assertReleaseOrMintCorrect(); - } - - function _deployOldPool() internal { - s_legacyPool = new BurnMintTokenPool1_2(s_token, new address[](0), address(s_mockRMN)); - s_token.grantMintAndBurnRoles(address(s_legacyPool)); - - TokenPool1_2.RampUpdate[] memory onRampUpdates = new TokenPool1_2.RampUpdate[](1); - onRampUpdates[0] = - TokenPool1_2.RampUpdate({ramp: address(s_pool), allowed: true, rateLimiterConfig: getInboundRateLimiterConfig()}); - TokenPool1_2.RampUpdate[] memory offRampUpdates = new TokenPool1_2.RampUpdate[](1); - offRampUpdates[0] = - TokenPool1_2.RampUpdate({ramp: address(s_pool), allowed: true, rateLimiterConfig: getInboundRateLimiterConfig()}); - BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(onRampUpdates, offRampUpdates); - } - - function _configurePool() internal { - TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); - chains[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - - BurnMintTokenPoolAndProxy(address(s_pool)).applyChainUpdates(chains); - - // CCIP Token Admin has already been registered from TokenSetup - s_tokenAdminRegistry.setPool(address(s_token), address(s_pool)); - - s_token.grantMintAndBurnRoles(address(s_pool)); - } - - function _assertLockOrBurnCorrect() internal { - uint256 amount = 1234; - vm.startPrank(address(s_onRamp)); - - // lockOrBurn, assert normal path is taken - deal(address(s_token), address(s_pool), amount); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: abi.encode(OWNER), - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: OWNER, - amount: amount, - localToken: address(s_token) - }) - ); - - // set legacy pool - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(s_legacyPool); - - // lockOrBurn, assert legacy pool is called - - vm.startPrank(address(s_onRamp)); - deal(address(s_token), address(s_pool), amount); - - vm.expectEmit(address(s_legacyPool)); - emit Burned(address(s_pool), amount); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: abi.encode(OWNER), - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: OWNER, - amount: amount, - localToken: address(s_token) - }) - ); - } - - function _assertReleaseOrMintCorrect() internal { - uint256 amount = 1234; - vm.startPrank(s_fakeOffRamp); - - // releaseOrMint, assert normal path is taken - deal(address(s_token), address(s_pool), amount); - - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - receiver: OWNER, - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: abi.encode(OWNER), - amount: amount, - localToken: address(s_token), - sourcePoolAddress: abi.encode(s_destPool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - - // set legacy pool - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(s_legacyPool); - - // releaseOrMint, assert legacy pool is called - - vm.startPrank(address(s_fakeOffRamp)); - - vm.expectEmit(address(s_legacyPool)); - emit Minted(address(s_pool), s_fakeOffRamp, amount); - - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - receiver: OWNER, - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: abi.encode(OWNER), - amount: amount, - localToken: address(s_token), - sourcePoolAddress: abi.encode(s_destPool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } -} - -//// -/// Duplicated tests from LockReleaseTokenPool.t.sol -/// - -contract LockReleaseTokenPoolAndProxySetup is RouterSetup { - IERC20 internal s_token; - LockReleaseTokenPoolAndProxy internal s_lockReleaseTokenPoolAndProxy; - LockReleaseTokenPoolAndProxy internal s_lockReleaseTokenPoolAndProxyWithAllowList; - 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); - - function setUp() public virtual override { - RouterSetup.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - s_lockReleaseTokenPoolAndProxy = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - s_allowedList.push(USER_1); - s_allowedList.push(DUMMY_CONTRACT_ADDRESS); - s_lockReleaseTokenPoolAndProxyWithAllowList = - new LockReleaseTokenPoolAndProxy(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolAddress), - remoteTokenAddress: abi.encode(address(s_token)), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - - s_lockReleaseTokenPoolAndProxy.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolAndProxyWithAllowList.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolAndProxy.setRebalancer(OWNER); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } -} - -contract LockReleaseTokenPoolAndProxy_setRebalancer is LockReleaseTokenPoolAndProxySetup { - function test_SetRebalancer_Success() public { - assertEq(address(s_lockReleaseTokenPoolAndProxy.getRebalancer()), OWNER); - s_lockReleaseTokenPoolAndProxy.setRebalancer(STRANGER); - assertEq(address(s_lockReleaseTokenPoolAndProxy.getRebalancer()), STRANGER); - } - - function test_SetRebalancer_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_lockReleaseTokenPoolAndProxy.setRebalancer(STRANGER); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity is LockReleaseTokenPoolAndProxySetup { - function test_CanAcceptLiquidity_Success() public { - assertEq(true, s_lockReleaseTokenPoolAndProxy.canAcceptLiquidity()); - - s_lockReleaseTokenPoolAndProxy = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - assertEq(false, s_lockReleaseTokenPoolAndProxy.canAcceptLiquidity()); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_provideLiquidity is LockReleaseTokenPoolAndProxySetup { - function test_Fuzz_ProvideLiquidity_Success(uint256 amount) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPoolAndProxy), amount); - - s_lockReleaseTokenPoolAndProxy.provideLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre - amount); - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPoolAndProxy)), amount); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(LockReleaseTokenPoolAndProxy.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPoolAndProxy.provideLiquidity(1); - } - - function test_Fuzz_ExceedsAllowance(uint256 amount) public { - vm.assume(amount > 0); - vm.expectRevert("ERC20: insufficient allowance"); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(amount); - } - - function test_LiquidityNotAccepted_Revert() public { - s_lockReleaseTokenPoolAndProxy = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - - vm.expectRevert(LockReleaseTokenPoolAndProxy.LiquidityNotAccepted.selector); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(1); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity is LockReleaseTokenPoolAndProxySetup { - function test_Fuzz_WithdrawalLiquidity_Success(uint256 amount) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPoolAndProxy), amount); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(amount); - - s_lockReleaseTokenPoolAndProxy.withdrawLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(LockReleaseTokenPoolAndProxy.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPoolAndProxy.withdrawLiquidity(1); - } - - function test_InsufficientLiquidity_Revert() public { - uint256 maxUint256 = 2 ** 256 - 1; - s_token.approve(address(s_lockReleaseTokenPoolAndProxy), maxUint256); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(maxUint256); - - vm.startPrank(address(s_lockReleaseTokenPoolAndProxy)); - s_token.transfer(OWNER, maxUint256); - vm.startPrank(OWNER); - - vm.expectRevert(LockReleaseTokenPoolAndProxy.InsufficientLiquidity.selector); - s_lockReleaseTokenPoolAndProxy.withdrawLiquidity(1); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_supportsInterface is LockReleaseTokenPoolAndProxySetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_lockReleaseTokenPoolAndProxy.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_lockReleaseTokenPoolAndProxy.supportsInterface(type(IERC165).interfaceId)); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig is LockReleaseTokenPoolAndProxySetup { - event ConfigChanged(RateLimiter.Config); - event ChainConfigured( - uint64 chainSelector, RateLimiter.Config outboundRateLimiterConfig, RateLimiter.Config inboundRateLimiterConfig - ); - - uint64 internal s_remoteChainSelector; - - function setUp() public virtual override { - LockReleaseTokenPoolAndProxySetup.setUp(); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - s_remoteChainSelector = 123124; - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: s_remoteChainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - s_lockReleaseTokenPoolAndProxy.applyChainUpdates(chainUpdates); - } - - function test_Fuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { - // Cap the lower bound to 4 so 4/2 is still >= 2 - vm.assume(capacity >= 4); - // Cap the lower bound to 2 so 2/2 is still >= 1 - rate = uint128(bound(rate, 2, capacity - 2)); - // Bucket updates only work on increasing time - newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); - vm.warp(newTime); - - uint256 oldOutboundTokens = - s_lockReleaseTokenPoolAndProxy.getCurrentOutboundRateLimiterState(s_remoteChainSelector).tokens; - uint256 oldInboundTokens = - s_lockReleaseTokenPoolAndProxy.getCurrentInboundRateLimiterState(s_remoteChainSelector).tokens; - - RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); - RateLimiter.Config memory newInboundConfig = - RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); - - vm.expectEmit(); - emit ConfigChanged(newOutboundConfig); - vm.expectEmit(); - emit ConfigChanged(newInboundConfig); - vm.expectEmit(); - emit ChainConfigured(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - s_lockReleaseTokenPoolAndProxy.setChainRateLimiterConfig(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); - - RateLimiter.TokenBucket memory bucket = - s_lockReleaseTokenPoolAndProxy.getCurrentOutboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newOutboundConfig.capacity); - assertEq(bucket.rate, newOutboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - - expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); - - bucket = s_lockReleaseTokenPoolAndProxy.getCurrentInboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newInboundConfig.capacity); - assertEq(bucket.rate, newInboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - } - - function test_OnlyOwnerOrRateLimitAdmin_Revert() public { - address rateLimiterAdmin = address(28973509103597907); - - s_lockReleaseTokenPoolAndProxy.setRateLimitAdmin(rateLimiterAdmin); - - vm.startPrank(rateLimiterAdmin); - - s_lockReleaseTokenPoolAndProxy.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); - - vm.startPrank(OWNER); - - s_lockReleaseTokenPoolAndProxy.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(LockReleaseTokenPoolAndProxy.Unauthorized.selector, STRANGER)); - s_lockReleaseTokenPoolAndProxy.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); - } - - function test_NonExistentChain_Revert() public { - uint64 wrongChainSelector = 9084102894; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); - s_lockReleaseTokenPoolAndProxy.setChainRateLimiterConfig( - wrongChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); - } -} - -contract LockReleaseTokenPoolAndProxy_setRateLimitAdmin is LockReleaseTokenPoolAndProxySetup { - function test_SetRateLimitAdmin_Success() public { - assertEq(address(0), s_lockReleaseTokenPoolAndProxy.getRateLimitAdmin()); - s_lockReleaseTokenPoolAndProxy.setRateLimitAdmin(OWNER); - assertEq(OWNER, s_lockReleaseTokenPoolAndProxy.getRateLimitAdmin()); - } - - // Reverts - - function test_SetRateLimitAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_lockReleaseTokenPoolAndProxy.setRateLimitAdmin(STRANGER); - } -} diff --git a/contracts/src/v0.8/ccip/test/mocks/MockCommitStore.sol b/contracts/src/v0.8/ccip/test/mocks/MockCommitStore.sol deleted file mode 100644 index aff06016fa5..00000000000 --- a/contracts/src/v0.8/ccip/test/mocks/MockCommitStore.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ICommitStore} from "../../interfaces/ICommitStore.sol"; - -contract MockCommitStore is ICommitStore { - error PausedError(); - - uint64 private s_expectedNextSequenceNumber = 1; - - bool private s_paused = false; - - /// @inheritdoc ICommitStore - function verify( - bytes32[] calldata, - bytes32[] calldata, - uint256 - ) external view whenNotPaused returns (uint256 timestamp) { - return 1; - } - - function getExpectedNextSequenceNumber() external view returns (uint64) { - return s_expectedNextSequenceNumber; - } - - function setExpectedNextSequenceNumber(uint64 nextSeqNum) external { - s_expectedNextSequenceNumber = nextSeqNum; - } - - modifier whenNotPaused() { - if (paused()) revert PausedError(); - _; - } - - function paused() public view returns (bool) { - return s_paused; - } - - function pause() external { - s_paused = true; - } -} diff --git a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol index 9fa5cd1a66d..c142cb89477 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol @@ -21,6 +21,7 @@ import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWith // This contract mocks both the ITokenMessenger and IMessageTransmitter // contracts involved with the Cross Chain Token Protocol. +// solhint-disable contract MockE2EUSDCTokenMessenger is ITokenMessenger { uint32 private immutable i_messageBodyVersion; address private immutable i_transmitter; @@ -50,8 +51,13 @@ contract MockE2EUSDCTokenMessenger is ITokenMessenger { IBurnMintERC20(burnToken).transferFrom(msg.sender, address(this), amount); IBurnMintERC20(burnToken).burn(amount); // Format message body - bytes memory _burnMessage = - abi.encodePacked(i_messageBodyVersion, burnToken, mintRecipient, amount, bytes32(uint256(uint160((msg.sender))))); + bytes memory _burnMessage = _formatMessage( + i_messageBodyVersion, + bytes32(uint256(uint160(burnToken))), + mintRecipient, + amount, + bytes32(uint256(uint160(msg.sender))) + ); s_nonce = _sendDepositForBurnMessage(destinationDomain, DESTINATION_TOKEN_MESSENGER, destinationCaller, _burnMessage); emit DepositForBurn( @@ -100,4 +106,23 @@ contract MockE2EUSDCTokenMessenger is ITokenMessenger { ); } } + + /** + * @notice Formats Burn message + * @param _version The message body version + * @param _burnToken The burn token address on source domain as bytes32 + * @param _mintRecipient The mint recipient address as bytes32 + * @param _amount The burn amount + * @param _messageSender The message sender + * @return Burn formatted message. + */ + function _formatMessage( + uint32 _version, + bytes32 _burnToken, + bytes32 _mintRecipient, + uint256 _amount, + bytes32 _messageSender + ) internal pure returns (bytes memory) { + return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + } } diff --git a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol index 8e50bedea99..4ed47b5607e 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol @@ -19,6 +19,7 @@ import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWith import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +// solhint-disable contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { // Indicated whether the receiveMessage() call should succeed. bool public s_shouldSucceed; @@ -55,15 +56,26 @@ contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { /// * destinationCaller 32 bytes32 84 /// * messageBody dynamic bytes 116 function receiveMessage(bytes calldata message, bytes calldata) external returns (bool success) { - address recipient = address(bytes20(message[64:84])); - - // We always mint 1000e18 tokens to not complicate the test. - i_token.mint(recipient, 1000e18); + // The receiver of the funds is the _mintRecipient in the following encoded format + // function _formatMessage( + // uint32 _version, 4 + // bytes32 _burnToken, 32 + // bytes32 _mintRecipient, 32, first 12 empty for EVM addresses + // uint256 _amount, + // bytes32 _messageSender + // ) internal pure returns (bytes memory) { + // return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + // } + address recipient = address(bytes20(message[116 + 36 + 12:116 + 36 + 12 + 20])); + // We always mint 1 token to not complicate the test. + i_token.mint(recipient, 1); return s_shouldSucceed; } - function setShouldSucceed(bool shouldSucceed) external { + function setShouldSucceed( + bool shouldSucceed + ) external { s_shouldSucceed = shouldSucceed; } diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol b/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol index 3f7b0200e6f..435c6697632 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {RMN} from "../../RMN.sol"; import {IRMN} from "../../interfaces/IRMN.sol"; -import {OwnerIsCreator} from "./../../../shared/access/OwnerIsCreator.sol"; /// @notice WARNING: This contract is to be only used for testing, all methods are unprotected. contract MockRMN is IRMN { @@ -19,7 +17,9 @@ contract MockRMN is IRMN { s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root] = blessed; } - function setGlobalCursed(bool cursed) external { + function setGlobalCursed( + bool cursed + ) external { s_globalCursed = cursed; } @@ -29,7 +29,9 @@ contract MockRMN is IRMN { /// @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 { + function setIsCursedRevert( + bytes calldata revertErr + ) external { s_isCursedRevert = revertErr; } @@ -42,14 +44,18 @@ contract MockRMN is IRMN { return s_globalCursed; } - function isCursed(bytes16 subject) external view returns (bool) { + 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) { + 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/MockRMN1_0.sol b/contracts/src/v0.8/ccip/test/mocks/MockRMN1_0.sol deleted file mode 100644 index 44ffc23b78f..00000000000 --- a/contracts/src/v0.8/ccip/test/mocks/MockRMN1_0.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; -import {OwnerIsCreator} from "./../../../shared/access/OwnerIsCreator.sol"; - -// Inlined from RMN 1.0 contract. -// solhint-disable gas-struct-packing -contract RMN { - struct Voter { - address blessVoteAddr; - address curseVoteAddr; - address curseUnvoteAddr; - uint8 blessWeight; - uint8 curseWeight; - } - - struct Config { - Voter[] voters; - uint16 blessWeightThreshold; - uint16 curseWeightThreshold; - } - - struct VersionedConfig { - Config config; - uint32 configVersion; - uint32 blockNumber; - } - - struct UnvoteToCurseRecord { - address curseVoteAddr; - bytes32 cursesHash; - bool forceUnvote; - } -} - -/// @dev Retained almost as-is from commit 88f285b94c23d0c684d337064758a5edde380fe2 for compatibility with offchain -/// tests and scripts. Internal structs of the RMN 1.0 contract that were depended on have been inlined. -/// @dev This contract should no longer be used for any new tests or scripts. -/// @notice WARNING: This contract is to be only used for testing, all methods are unprotected. -// TODO: remove this contract when tests and scripts are updated -contract MockRMN is IRMN, OwnerIsCreator { - error CustomError(bytes err); - - bool private s_curse; - bytes private s_err; - RMN.VersionedConfig private s_versionedConfig; - mapping(bytes16 subject => bool cursed) private s_curseBySubject; - - function isCursed() external view override returns (bool) { - if (s_err.length != 0) { - revert CustomError(s_err); - } - return s_curse; - } - - function isCursed(bytes16 subject) external view override returns (bool) { - if (s_err.length != 0) { - revert CustomError(s_err); - } - return s_curse || s_curseBySubject[subject]; - } - - function voteToCurse(bytes32) external { - s_curse = true; - } - - function voteToCurse(bytes32, bytes16 subject) external { - s_curseBySubject[subject] = true; - } - - function ownerUnvoteToCurse(RMN.UnvoteToCurseRecord[] memory) external { - s_curse = false; - } - - function ownerUnvoteToCurse(RMN.UnvoteToCurseRecord[] memory, bytes16 subject) external { - s_curseBySubject[subject] = false; - } - - function setRevert(bytes memory err) external { - s_err = err; - } - - function isBlessed(IRMN.TaggedRoot calldata) external view override returns (bool) { - return !s_curse; - } - - function getConfigDetails() external view returns (uint32 version, uint32 blockNumber, RMN.Config memory config) { - return (s_versionedConfig.configVersion, s_versionedConfig.blockNumber, s_versionedConfig.config); - } -} diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol index 87db0319514..0abe4fdb7e5 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRouter} from "../../interfaces/IRouter.sol"; @@ -12,7 +12,7 @@ import {Internal} from "../../libraries/Internal.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"; import {ERC165Checker} from - "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; + "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; contract MockCCIPRouter is IRouter, IRouterClient { using SafeERC20 for IERC20; @@ -45,8 +45,19 @@ contract MockCCIPRouter is IRouter, IRouterClient { uint256 gasLimit, address receiver ) internal returns (bool success, bytes memory retData, uint256 gasUsed) { - // Only send through the router if the receiver is a contract and implements the IAny2EVMMessageReceiver interface. - if (receiver.code.length == 0 || !receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId)) { + // There are three cases in which we skip calling the receiver: + // 1. If the message data is empty AND the gas limit is 0. + // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract + // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the + // receiver without any gas, which would revert the transaction. + // 2. If the receiver is not a contract. + // 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. + if ( + (message.data.length == 0 && gasLimit == 0) || receiver.code.length == 0 + || !receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) + ) { return (true, "", 0); } @@ -108,7 +119,9 @@ contract MockCCIPRouter is IRouter, IRouterClient { return mockMsgId; } - function _fromBytes(bytes calldata extraArgs) internal pure returns (Client.EVMExtraArgsV1 memory) { + function _fromBytes( + bytes calldata extraArgs + ) internal pure returns (Client.EVMExtraArgsV1 memory) { if (extraArgs.length == 0) { return Client.EVMExtraArgsV1({gasLimit: DEFAULT_GAS_LIMIT}); } @@ -117,12 +130,16 @@ contract MockCCIPRouter is IRouter, IRouterClient { } /// @notice Always returns true to make sure this check can be performed on any chain. - function isChainSupported(uint64) external pure returns (bool supported) { + function isChainSupported( + uint64 + ) external pure returns (bool supported) { return true; } /// @notice Returns an empty array. - function getSupportedTokens(uint64) external pure returns (address[] memory tokens) { + function getSupportedTokens( + uint64 + ) external pure returns (address[] memory tokens) { return new address[](0); } @@ -132,12 +149,16 @@ contract MockCCIPRouter is IRouter, IRouterClient { } /// @notice Sets the fees returned by getFee but is only checked when using native fee tokens - function setFee(uint256 feeAmount) external { + function setFee( + uint256 feeAmount + ) external { s_mockFeeTokenAmount = feeAmount; } /// @notice Always returns address(1234567890) - function getOnRamp(uint64 /* destChainSelector */ ) external pure returns (address onRampAddress) { + function getOnRamp( + uint64 /* destChainSelector */ + ) external pure returns (address onRampAddress) { return address(1234567890); } 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 91798b494df..6cbe7bf58f4 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 @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {Client} from "../../../libraries/Client.sol"; import {TokenSetup} from "../../TokenSetup.t.sol"; -import {IRouter, IRouterClient, MockCCIPRouter} from "../MockRouter.sol"; +import {IRouterClient, MockCCIPRouter} from "../MockRouter.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"; diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol index 5b784bf7219..2783608e68e 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol @@ -373,6 +373,48 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } + function test_SetConfigWithSignersMismatchingTransmitters_Success() public { + uint8 F = 2; + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, s_validSigners, s_partialTransmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_partialTransmitters + }); + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_validSigners, + transmitters: s_partialTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + } + function test_SetConfigWithoutSigners_Success() public { uint8 F = 1; address[] memory signers = new address[](0); @@ -530,8 +572,12 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { function test_Fuzz_SetConfig_Success(MultiOCR3Base.OCRConfigArgs memory ocrConfig, uint64 randomAddressOffset) public { // condition: cannot assume max oracle count - vm.assume(ocrConfig.transmitters.length <= 31); - vm.assume(ocrConfig.signers.length <= 31); + vm.assume(ocrConfig.transmitters.length <= 255); + vm.assume(ocrConfig.signers.length <= 255); + // condition: at least one transmitter + vm.assume(ocrConfig.transmitters.length > 0); + // condition: number of transmitters does not exceed signers + vm.assume(ocrConfig.signers.length == 0 || ocrConfig.transmitters.length <= ocrConfig.signers.length); // condition: F > 0 ocrConfig.F = uint8(bound(ocrConfig.F, 1, 3)); @@ -839,7 +885,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { function test_FTooHigh_Revert() public { address[] memory signers = new address[](0); - address[] memory transmitters = new address[](0); + address[] memory transmitters = new address[](1); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ @@ -876,9 +922,29 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } + function test_NoTransmitters_Revert() public { + address[] memory signers = new address[](0); + address[] memory transmitters = new address[](0); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(10, signers, transmitters), + F: 1, + isSignatureVerificationEnabled: false, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector(MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.NO_TRANSMITTERS) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + function test_TooManyTransmitters_Revert() public { address[] memory signers = new address[](0); - address[] memory transmitters = new address[](32); + address[] memory transmitters = new address[](257); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ @@ -899,7 +965,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { } function test_TooManySigners_Revert() public { - address[] memory signers = new address[](32); + address[] memory signers = new address[](257); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ @@ -918,4 +984,23 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ); s_multiOCR3.setOCR3Configs(ocrConfigs); } + + function test_MoreTransmittersThanSigners_Revert() public { + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, s_validSigners, s_partialTransmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: s_partialSigners, + transmitters: s_validTransmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } } diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol index 6f6219bc9b0..9cfddf0dd5c 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol @@ -84,7 +84,9 @@ contract MultiOCR3BaseSetup is BaseTest { vm.assertEq(configA.transmitters, configB.transmitters); } - function _assertOCRConfigUnconfigured(MultiOCR3Base.OCRConfig memory config) internal pure { + function _assertOCRConfigUnconfigured( + MultiOCR3Base.OCRConfig memory config + ) internal pure { assertEq(config.configInfo.configDigest, bytes32("")); assertEq(config.signers.length, 0); assertEq(config.transmitters.length, 0); diff --git a/contracts/src/v0.8/ccip/test/ocr/OCR2Base.t.sol b/contracts/src/v0.8/ccip/test/ocr/OCR2Base.t.sol deleted file mode 100644 index 7511ebdffae..00000000000 --- a/contracts/src/v0.8/ccip/test/ocr/OCR2Base.t.sol +++ /dev/null @@ -1,305 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OCR2Abstract} from "../../ocr/OCR2Abstract.sol"; -import {OCR2Base} from "../../ocr/OCR2Base.sol"; -import {OCR2Helper} from "../helpers/OCR2Helper.sol"; -import {OCR2Setup} from "./OCR2Setup.t.sol"; - -contract OCR2BaseSetup is OCR2Setup { - OCR2Helper internal s_OCR2Base; - - bytes32[] internal s_rs; - bytes32[] internal s_ss; - bytes32 internal s_rawVs; - - uint40 internal s_latestEpochAndRound; - - function setUp() public virtual override { - OCR2Setup.setUp(); - s_OCR2Base = new OCR2Helper(); - - bytes32 testReportDigest = getTestReportDigest(); - - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](2); - uint8[] memory vs = new uint8[](2); - - // Calculate signatures - (vs[0], rs[0], ss[0]) = vm.sign(PRIVATE0, testReportDigest); - (vs[1], rs[1], ss[1]) = vm.sign(PRIVATE1, testReportDigest); - - s_rs = rs; - s_ss = ss; - s_rawVs = bytes32(bytes1(vs[0] - 27)) | (bytes32(bytes1(vs[1] - 27)) >> 8); - } - - function getBasicConfigDigest(uint8 f, uint64 currentConfigCount) internal view returns (bytes32) { - bytes memory configBytes = abi.encode(""); - return s_OCR2Base.configDigestFromConfigData( - block.chainid, - address(s_OCR2Base), - currentConfigCount + 1, - s_valid_signers, - s_valid_transmitters, - f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - } - - function getTestReportDigest() internal view returns (bytes32) { - bytes32 configDigest = getBasicConfigDigest(s_f, 0); - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - return keccak256(abi.encodePacked(keccak256(REPORT), reportContext)); - } - - function getBasicConfigDigest( - address contractAddress, - uint8 f, - uint64 currentConfigCount, - bytes memory onchainConfig - ) internal view returns (bytes32) { - return s_OCR2Base.configDigestFromConfigData( - block.chainid, - contractAddress, - currentConfigCount + 1, - s_valid_signers, - s_valid_transmitters, - f, - onchainConfig, - s_offchainConfigVersion, - abi.encode("") - ); - } -} - -contract OCR2Base_transmit is OCR2BaseSetup { - bytes32 internal s_configDigest; - - function setUp() public virtual override { - OCR2BaseSetup.setUp(); - bytes memory configBytes = abi.encode(""); - - s_configDigest = getBasicConfigDigest(s_f, 0); - s_OCR2Base.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, configBytes, s_offchainConfigVersion, configBytes - ); - } - - function test_Transmit2SignersSuccess_gas() public { - vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - vm.startPrank(s_valid_transmitters[0]); - vm.resumeGasMetering(); - s_OCR2Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - // Reverts - - function test_ForkedChain_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - uint256 chain1 = block.chainid; - uint256 chain2 = chain1 + 1; - vm.chainId(chain2); - vm.expectRevert(abi.encodeWithSelector(OCR2Base.ForkedChain.selector, chain1, chain2)); - vm.startPrank(s_valid_transmitters[0]); - s_OCR2Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - function test_WrongNumberOfSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - vm.expectRevert(OCR2Base.WrongNumberOfSignatures.selector); - s_OCR2Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); - } - - function test_ConfigDigestMismatch_Revert() public { - bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - - vm.expectRevert(abi.encodeWithSelector(OCR2Base.ConfigDigestMismatch.selector, s_configDigest, configDigest)); - s_OCR2Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); - } - - function test_SignatureOutOfRegistration_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](1); - - vm.expectRevert(OCR2Base.SignaturesOutOfRegistration.selector); - s_OCR2Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } - - function test_UnAuthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](2); - - vm.expectRevert(OCR2Base.UnauthorizedTransmitter.selector); - s_OCR2Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } - - function test_NonUniqueSignature_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = s_rs; - bytes32[] memory ss = s_ss; - - rs[1] = rs[0]; - ss[1] = ss[0]; - // Need to reset the rawVs to be valid - bytes32 rawVs = bytes32(bytes1(uint8(28) - 27)) | (bytes32(bytes1(uint8(28) - 27)) >> 8); - - vm.startPrank(s_valid_transmitters[0]); - vm.expectRevert(OCR2Base.NonUniqueSignatures.selector); - s_OCR2Base.transmit(reportContext, REPORT, rs, ss, rawVs); - } - - function test_UnauthorizedSigner_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = new bytes32[](2); - rs[0] = s_configDigest; - bytes32[] memory ss = rs; - - vm.startPrank(s_valid_transmitters[0]); - vm.expectRevert(OCR2Base.UnauthorizedSigner.selector); - s_OCR2Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } -} - -contract OCR2Base_setOCR2Config is OCR2BaseSetup { - function test_SetConfigSuccess_gas() public { - vm.pauseGasMetering(); - bytes memory configBytes = abi.encode(""); - uint32 configCount = 0; - - bytes32 configDigest = getBasicConfigDigest(s_f, configCount++); - - address[] memory transmitters = s_OCR2Base.getTransmitters(); - assertEq(0, transmitters.length); - - vm.expectEmit(); - emit OCR2Abstract.ConfigSet( - 0, - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - - s_OCR2Base.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, configBytes, s_offchainConfigVersion, configBytes - ); - - transmitters = s_OCR2Base.getTransmitters(); - assertEq(s_valid_transmitters, transmitters); - - configDigest = getBasicConfigDigest(s_f, configCount++); - - vm.expectEmit(); - emit OCR2Abstract.ConfigSet( - uint32(block.number), - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - vm.resumeGasMetering(); - s_OCR2Base.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, configBytes, s_offchainConfigVersion, configBytes - ); - } - - // Reverts - function test_RepeatAddress_Revert() public { - address[] memory signers = new address[](10); - signers[0] = address(1245678); - address[] memory transmitters = new address[](10); - transmitters[0] = signers[0]; - - vm.expectRevert( - abi.encodeWithSelector(OCR2Base.InvalidConfig.selector, OCR2Base.InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS) - ); - s_OCR2Base.setOCR2Config(signers, transmitters, 2, abi.encode(""), 100, abi.encode("")); - } - - function test_SingerCannotBeZeroAddress_Revert() public { - uint256 f = 1; - address[] memory signers = new address[](3 * f + 1); - address[] memory transmitters = new address[](3 * f + 1); - for (uint160 i = 0; i < 3 * f + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - signers[0] = address(0); - - vm.expectRevert(OCR2Base.OracleCannotBeZeroAddress.selector); - s_OCR2Base.setOCR2Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); - } - - function test_TransmitterCannotBeZeroAddress_Revert() public { - uint256 f = 1; - address[] memory signers = new address[](3 * f + 1); - address[] memory transmitters = new address[](3 * f + 1); - for (uint160 i = 0; i < 3 * f + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - transmitters[0] = address(0); - - vm.expectRevert(OCR2Base.OracleCannotBeZeroAddress.selector); - s_OCR2Base.setOCR2Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); - } - - function test_OracleOutOfRegister_Revert() public { - address[] memory signers = new address[](10); - address[] memory transmitters = new address[](0); - - vm.expectRevert( - abi.encodeWithSelector( - OCR2Base.InvalidConfig.selector, OCR2Base.InvalidConfigErrorType.NUM_SIGNERS_NOT_NUM_TRANSMITTERS - ) - ); - s_OCR2Base.setOCR2Config(signers, transmitters, 2, abi.encode(""), 100, abi.encode("")); - } - - function test_FTooHigh_Revert() public { - address[] memory signers = new address[](0); - uint8 f = 1; - - vm.expectRevert(abi.encodeWithSelector(OCR2Base.InvalidConfig.selector, OCR2Base.InvalidConfigErrorType.F_TOO_HIGH)); - s_OCR2Base.setOCR2Config(signers, new address[](0), f, abi.encode(""), 100, abi.encode("")); - } - - function test_FMustBePositive_Revert() public { - uint8 f = 0; - - vm.expectRevert( - abi.encodeWithSelector(OCR2Base.InvalidConfig.selector, OCR2Base.InvalidConfigErrorType.F_MUST_BE_POSITIVE) - ); - s_OCR2Base.setOCR2Config(new address[](0), new address[](0), f, abi.encode(""), 100, abi.encode("")); - } - - function test_TooManySigners_Revert() public { - address[] memory signers = new address[](32); - - vm.expectRevert( - abi.encodeWithSelector(OCR2Base.InvalidConfig.selector, OCR2Base.InvalidConfigErrorType.TOO_MANY_SIGNERS) - ); - s_OCR2Base.setOCR2Config(signers, new address[](0), 0, abi.encode(""), 100, abi.encode("")); - } -} diff --git a/contracts/src/v0.8/ccip/test/ocr/OCR2BaseNoChecks.t.sol b/contracts/src/v0.8/ccip/test/ocr/OCR2BaseNoChecks.t.sol deleted file mode 100644 index fd4cf3fc9e7..00000000000 --- a/contracts/src/v0.8/ccip/test/ocr/OCR2BaseNoChecks.t.sol +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OCR2BaseNoChecks} from "../../ocr/OCR2BaseNoChecks.sol"; -import {OCR2NoChecksHelper} from "../helpers/OCR2NoChecksHelper.sol"; -import {OCR2Setup} from "./OCR2Setup.t.sol"; - -contract OCR2BaseNoChecksSetup is OCR2Setup { - OCR2NoChecksHelper internal s_OCR2Base; - - bytes32[] internal s_rs; - bytes32[] internal s_ss; - bytes32 internal s_rawVs; - - function setUp() public virtual override { - OCR2Setup.setUp(); - s_OCR2Base = new OCR2NoChecksHelper(); - } - - function getBasicConfigDigest(uint8 f, uint64 currentConfigCount) internal view returns (bytes32) { - bytes memory configBytes = abi.encode(""); - return s_OCR2Base.configDigestFromConfigData( - block.chainid, - address(s_OCR2Base), - currentConfigCount + 1, - s_valid_signers, - s_valid_transmitters, - f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - } -} - -contract OCR2BaseNoChecks_transmit is OCR2BaseNoChecksSetup { - bytes32 internal s_configDigest; - - function setUp() public virtual override { - OCR2BaseNoChecksSetup.setUp(); - bytes memory configBytes = abi.encode(""); - - s_configDigest = getBasicConfigDigest(s_f, 0); - s_OCR2Base.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, configBytes, s_offchainConfigVersion, configBytes - ); - } - - function test_TransmitSuccess_gas() public { - vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - vm.startPrank(s_valid_transmitters[0]); - vm.resumeGasMetering(); - s_OCR2Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - // Reverts - - function test_ForkedChain_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - uint256 chain1 = block.chainid; - uint256 chain2 = chain1 + 1; - vm.chainId(chain2); - vm.expectRevert(abi.encodeWithSelector(OCR2BaseNoChecks.ForkedChain.selector, chain1, chain2)); - vm.startPrank(s_valid_transmitters[0]); - s_OCR2Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - function test_ConfigDigestMismatch_Revert() public { - bytes32 configDigest; - - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - - vm.expectRevert( - abi.encodeWithSelector(OCR2BaseNoChecks.ConfigDigestMismatch.selector, s_configDigest, configDigest) - ); - s_OCR2Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); - } - - function test_UnAuthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = new bytes32[](3); - bytes32[] memory ss = new bytes32[](3); - - vm.expectRevert(OCR2BaseNoChecks.UnauthorizedTransmitter.selector); - s_OCR2Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } -} - -contract OCR2BaseNoChecks_setOCR2Config is OCR2BaseNoChecksSetup { - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - function test_SetConfigSuccess_gas() public { - vm.pauseGasMetering(); - bytes memory configBytes = abi.encode(""); - uint32 configCount = 0; - - bytes32 configDigest = getBasicConfigDigest(s_f, configCount++); - - address[] memory transmitters = s_OCR2Base.getTransmitters(); - assertEq(0, transmitters.length); - - vm.expectEmit(); - emit ConfigSet( - 0, - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - - s_OCR2Base.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, configBytes, s_offchainConfigVersion, configBytes - ); - - transmitters = s_OCR2Base.getTransmitters(); - assertEq(s_valid_transmitters, transmitters); - - configDigest = getBasicConfigDigest(s_f, configCount++); - - vm.expectEmit(); - emit ConfigSet( - uint32(block.number), - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - vm.resumeGasMetering(); - s_OCR2Base.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, configBytes, s_offchainConfigVersion, configBytes - ); - } - - // Reverts - function test_RepeatAddress_Revert() public { - address[] memory signers = new address[](4); - address[] memory transmitters = new address[](4); - transmitters[0] = address(1245678); - transmitters[1] = address(1245678); - transmitters[2] = address(1245678); - transmitters[3] = address(1245678); - - vm.expectRevert( - abi.encodeWithSelector( - OCR2BaseNoChecks.InvalidConfig.selector, OCR2BaseNoChecks.InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS - ) - ); - s_OCR2Base.setOCR2Config(signers, transmitters, 1, abi.encode(""), 100, abi.encode("")); - } - - function test_FMustBePositive_Revert() public { - uint8 f = 0; - - vm.expectRevert( - abi.encodeWithSelector( - OCR2BaseNoChecks.InvalidConfig.selector, OCR2BaseNoChecks.InvalidConfigErrorType.F_MUST_BE_POSITIVE - ) - ); - s_OCR2Base.setOCR2Config(new address[](0), new address[](0), f, abi.encode(""), 100, abi.encode("")); - } - - function test_TransmitterCannotBeZeroAddress_Revert() public { - uint256 f = 1; - address[] memory signers = new address[](3 * f + 1); - address[] memory transmitters = new address[](3 * f + 1); - for (uint160 i = 0; i < 3 * f + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - transmitters[0] = address(0); - - vm.expectRevert(OCR2BaseNoChecks.OracleCannotBeZeroAddress.selector); - s_OCR2Base.setOCR2Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); - } - - function test_TooManyTransmitter_Revert() public { - address[] memory transmitters = new address[](100); - - vm.expectRevert( - abi.encodeWithSelector( - OCR2BaseNoChecks.InvalidConfig.selector, OCR2BaseNoChecks.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS - ) - ); - s_OCR2Base.setOCR2Config(new address[](0), transmitters, 0, abi.encode(""), 100, abi.encode("")); - } -} diff --git a/contracts/src/v0.8/ccip/test/ocr/OCR2Setup.t.sol b/contracts/src/v0.8/ccip/test/ocr/OCR2Setup.t.sol deleted file mode 100644 index e4be8ffa29b..00000000000 --- a/contracts/src/v0.8/ccip/test/ocr/OCR2Setup.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; - -contract OCR2Setup is Test { - uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; - uint256 internal constant PRIVATE1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; - uint256 internal constant PRIVATE2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; - uint256 internal constant PRIVATE3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; - - address[] internal s_valid_signers; - address[] internal s_valid_transmitters; - - uint64 internal constant s_offchainConfigVersion = 3; - uint8 internal constant s_f = 1; - bytes internal constant REPORT = abi.encode("testReport"); - - function setUp() public virtual { - s_valid_transmitters = new address[](4); - for (uint160 i = 0; i < 4; ++i) { - s_valid_transmitters[i] = address(4 + i); - } - - s_valid_signers = new address[](4); - s_valid_signers[0] = vm.addr(PRIVATE0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 - s_valid_signers[1] = vm.addr(PRIVATE1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 - s_valid_signers[2] = vm.addr(PRIVATE2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b - s_valid_signers[3] = vm.addr(PRIVATE3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 - } -} diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol deleted file mode 100644 index e94184e3c5e..00000000000 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol +++ /dev/null @@ -1,1986 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ICommitStore} from "../../interfaces/ICommitStore.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; - -import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; - -import {GenericReceiver} from "../../../shared/test/testhelpers/GenericReceiver.sol"; -import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; -import {RMN} from "../../RMN.sol"; -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {OCR2Abstract} from "../../ocr/OCR2Abstract.sol"; -import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {ConformingReceiver} from "../helpers/receivers/ConformingReceiver.sol"; -import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {MaybeRevertMessageReceiverNo165} from "../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; -import {ReentrancyAbuser} from "../helpers/receivers/ReentrancyAbuser.sol"; -import {MockCommitStore} from "../mocks/MockCommitStore.sol"; -import {OCR2Base} from "../ocr/OCR2Base.t.sol"; -import {OCR2BaseNoChecks} from "../ocr/OCR2BaseNoChecks.t.sol"; -import {EVM2EVMOffRampSetup} from "./EVM2EVMOffRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract EVM2EVMOffRamp_constructor is EVM2EVMOffRampSetup { - function test_Constructor_Success() public { - EVM2EVMOffRamp.StaticConfig memory staticConfig = EVM2EVMOffRamp.StaticConfig({ - commitStore: address(s_mockCommitStore), - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: ON_RAMP_ADDRESS, - prevOffRamp: address(0), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }); - EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = - generateDynamicOffRampConfig(address(s_destRouter), address(s_priceRegistry)); - - s_offRamp = new EVM2EVMOffRampHelper(staticConfig, getInboundRateLimiterConfig()); - - s_offRamp.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - - // Static config - EVM2EVMOffRamp.StaticConfig memory gotStaticConfig = s_offRamp.getStaticConfig(); - assertEq(staticConfig.commitStore, gotStaticConfig.commitStore); - assertEq(staticConfig.sourceChainSelector, gotStaticConfig.sourceChainSelector); - assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); - assertEq(staticConfig.onRamp, gotStaticConfig.onRamp); - assertEq(staticConfig.prevOffRamp, gotStaticConfig.prevOffRamp); - assertEq(staticConfig.tokenAdminRegistry, gotStaticConfig.tokenAdminRegistry); - - // Dynamic config - EVM2EVMOffRamp.DynamicConfig memory gotDynamicConfig = s_offRamp.getDynamicConfig(); - _assertSameConfig(dynamicConfig, gotDynamicConfig); - - (uint32 configCount, uint32 blockNumber,) = s_offRamp.latestConfigDetails(); - assertEq(1, configCount); - assertEq(block.number, blockNumber); - - // OffRamp initial values - assertEq("EVM2EVMOffRamp 1.5.0-dev", s_offRamp.typeAndVersion()); - assertEq(OWNER, s_offRamp.owner()); - } - - // Revert - function test_ZeroOnRampAddress_Revert() public { - vm.expectRevert(EVM2EVMOffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp = new EVM2EVMOffRampHelper( - EVM2EVMOffRamp.StaticConfig({ - commitStore: address(s_mockCommitStore), - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: ZERO_ADDRESS, - prevOffRamp: address(0), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - RateLimiter.Config({isEnabled: true, rate: 1e20, capacity: 1e20}) - ); - } - - function test_CommitStoreAlreadyInUse_Revert() public { - s_mockCommitStore.setExpectedNextSequenceNumber(2); - - vm.expectRevert(EVM2EVMOffRamp.CommitStoreAlreadyInUse.selector); - - s_offRamp = new EVM2EVMOffRampHelper( - EVM2EVMOffRamp.StaticConfig({ - commitStore: address(s_mockCommitStore), - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: ON_RAMP_ADDRESS, - prevOffRamp: address(0), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - getInboundRateLimiterConfig() - ); - } -} - -contract EVM2EVMOffRamp_setDynamicConfig is EVM2EVMOffRampSetup { - function test_SetDynamicConfig_Success() public { - EVM2EVMOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); - EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(USER_3, address(s_priceRegistry)); - bytes memory onchainConfig = abi.encode(dynamicConfig); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ConfigSet(staticConfig, dynamicConfig); - - vm.expectEmit(); - uint32 configCount = 1; - emit OCR2Abstract.ConfigSet( - uint32(block.number), - getBasicConfigDigest(address(s_offRamp), s_f, configCount, onchainConfig), - configCount + 1, - s_valid_signers, - s_valid_transmitters, - s_f, - onchainConfig, - s_offchainConfigVersion, - abi.encode("") - ); - - s_offRamp.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, onchainConfig, s_offchainConfigVersion, abi.encode("") - ); - - EVM2EVMOffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); - _assertSameConfig(dynamicConfig, newConfig); - } - - function test_NonOwner_Revert() public { - vm.startPrank(STRANGER); - EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(USER_3, address(s_priceRegistry)); - - vm.expectRevert("Only callable by owner"); - - s_offRamp.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - } - - function test_RouterZeroAddress_Revert() public { - EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(ZERO_ADDRESS, ZERO_ADDRESS); - - vm.expectRevert(EVM2EVMOffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp.setOCR2Config( - s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") - ); - } -} - -contract EVM2EVMOffRamp_metadataHash is EVM2EVMOffRampSetup { - function test_MetadataHash_Success() public view { - bytes32 h = s_offRamp.metadataHash(); - assertEq( - h, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS) - ) - ); - } -} - -contract EVM2EVMOffRamp_ccipReceive is EVM2EVMOffRampSetup { - // Reverts - - function test_Reverts() public { - Client.Any2EVMMessage memory message = _convertToGeneralMessage(_generateAny2EVMMessageNoTokens(1)); - vm.expectRevert(); - s_offRamp.ccipReceive(message); - } -} - -contract EVM2EVMOffRamp_execute is EVM2EVMOffRampSetup { - error PausedError(); - - function _generateMsgWithoutTokens( - uint256 gasLimit, - bytes memory messageData - ) internal view returns (Internal.EVM2EVMMessage memory) { - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1); - message.gasLimit = gasLimit; - message.data = messageData; - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS) - ) - ); - return message; - } - - function test_Fuzz_trialExecuteWithoutTokens_Success(bytes4 funcSelector, bytes memory messageData) public { - vm.assume( - funcSelector != GenericReceiver.setRevert.selector && funcSelector != GenericReceiver.setErr.selector - && funcSelector != 0x5100fc21 && funcSelector != 0x00000000 // s_toRevert(), which is public and therefore has a function selector - ); - - // Convert bytes4 into bytes memory to use in the message - Internal.EVM2EVMMessage memory message = _generateMsgWithoutTokens(GAS_LIMIT, messageData); - - // Convert an Internal.EVM2EVMMessage into a Client.Any2EVMMessage digestable by the client - Client.Any2EVMMessage memory receivedMessage = _convertToGeneralMessage(message); - bytes memory expectedCallData = - abi.encodeWithSelector(MaybeRevertMessageReceiver.ccipReceive.selector, receivedMessage); - - vm.expectCall(address(s_receiver), expectedCallData); - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); - assertEq("", err); - } - - function test_Fuzz_trialExecuteWithTokens_Success(uint16 tokenAmount, bytes calldata messageData) public { - vm.assume(tokenAmount != 0); - - uint256[] memory amounts = new uint256[](2); - amounts[0] = uint256(tokenAmount); - amounts[1] = uint256(tokenAmount); - - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - // console.log(message.length); - message.data = messageData; - - IERC20 dstToken0 = IERC20(s_destTokens[0]); - uint256 startingBalance = dstToken0.balanceOf(message.receiver); - - vm.expectCall(s_destTokens[0], abi.encodeWithSelector(IERC20.transfer.selector, address(s_receiver), amounts[0])); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); - assertEq("", err); - - // Check that the tokens were transferred - assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver)); - } - - function test_Fuzz_getSenderNonce(uint8 trialExecutions) public { - vm.assume(trialExecutions > 1); - - Internal.EVM2EVMMessage[] memory messages; - - if (trialExecutions == 1) { - messages = new Internal.EVM2EVMMessage[](1); - messages[0] = _generateAny2EVMMessageNoTokens(0); - } else { - messages = _generateSingleBasicMessage(); - } - - // Fuzz the number of calls from the sender to ensure that getSenderNonce works - for (uint256 i = 1; i < trialExecutions; ++i) { - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - } - - messages[0].nonce = 0; - messages[0].sequenceNumber = 0; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - uint64 nonceBefore = s_offRamp.getSenderNonce(messages[0].sender); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(s_offRamp.getSenderNonce(messages[0].sender), nonceBefore, "sender nonce is not as expected"); - } - - function test_Fuzz_getSenderNonceWithPrevOffRamp_Success(uint8 trialExecutions) public { - vm.assume(trialExecutions > 1); - // Fuzz a random nonce for getSenderNonce - test_Fuzz_getSenderNonce(trialExecutions); - - address prevOffRamp = address(s_offRamp); - deployOffRamp(s_mockCommitStore, s_destRouter, prevOffRamp); - - // Make sure the off-ramp address has changed by querying the static config - assertNotEq(address(s_offRamp), prevOffRamp); - EVM2EVMOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); - assertEq(staticConfig.prevOffRamp, prevOffRamp, "Previous offRamp does not match expected address"); - - // Since i_prevOffRamp != address(0) and senderNonce == 0, there should be a call to the previous offRamp - vm.expectCall(prevOffRamp, abi.encodeWithSelector(s_offRamp.getSenderNonce.selector, OWNER)); - uint256 currentSenderNonce = s_offRamp.getSenderNonce(OWNER); - assertNotEq(currentSenderNonce, 0, "Sender nonce should not be zero"); - assertEq(currentSenderNonce, trialExecutions - 1, "Sender Nonce does not match expected trial executions"); - - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - currentSenderNonce = s_offRamp.getSenderNonce(OWNER); - assertEq(currentSenderNonce, trialExecutions - 1, "Sender Nonce on new offramp does not match expected executions"); - } - - function test_SingleMessageNoTokens_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - uint64 nonceBefore = s_offRamp.getSenderNonce(messages[0].sender); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertGt(s_offRamp.getSenderNonce(messages[0].sender), nonceBefore); - } - - function test_SingleMessageNoTokensUnordered_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].nonce = 0; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - // Nonce never increments on unordered messages. - uint64 nonceBefore = s_offRamp.getSenderNonce(messages[0].sender); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq( - s_offRamp.getSenderNonce(messages[0].sender), nonceBefore, "nonce must remain unchanged on unordered messages" - ); - - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - // Nonce never increments on unordered messages. - nonceBefore = s_offRamp.getSenderNonce(messages[0].sender); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq( - s_offRamp.getSenderNonce(messages[0].sender), nonceBefore, "nonce must remain unchanged on unordered messages" - ); - } - - function test_ReceiverError_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - bytes memory realError1 = new bytes(2); - realError1[0] = 0xbe; - realError1[1] = 0xef; - s_reverting_receiver.setErr(realError1); - - messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - EVM2EVMOffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) - ) - ); - // Nonce should increment on non-strict - assertEq(uint64(0), s_offRamp.getSenderNonce(address(OWNER))); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(uint64(1), s_offRamp.getSenderNonce(address(OWNER))); - } - - function test_StrictUntouchedToSuccess_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - messages[0].strict = true; - messages[0].receiver = address(s_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - // Nonce should increment on a strict untouched -> success. - assertEq(uint64(0), s_offRamp.getSenderNonce(address(OWNER))); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(uint64(1), s_offRamp.getSenderNonce(address(OWNER))); - } - - function test_SkippedIncorrectNonce_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - messages[0].nonce++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.SkippedIncorrectNonce(messages[0].nonce, messages[0].sender); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - function test_SkippedIncorrectNonceStillExecutes_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(); - - messages[1].nonce++; - messages[1].messageId = Internal._hash(messages[1], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - vm.expectEmit(); - emit EVM2EVMOffRamp.SkippedIncorrectNonce(messages[1].nonce, messages[1].sender); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - function test__execute_SkippedAlreadyExecutedMessage_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - vm.expectEmit(); - emit EVM2EVMOffRamp.SkippedAlreadyExecutedMessage(messages[0].sequenceNumber); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].nonce = 0; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - vm.expectEmit(); - emit EVM2EVMOffRamp.SkippedAlreadyExecutedMessage(messages[0].sequenceNumber); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - // Send a message to a contract that does not implement the CCIPReceiver interface - // This should execute successfully. - function test_SingleMessageToNonCCIPReceiver_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); - messages[0].receiver = address(newReceiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - function test_SingleMessagesNoTokensSuccess_gas() public { - vm.pauseGasMetering(); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - - vm.resumeGasMetering(); - s_offRamp.execute(report, new uint256[](0)); - } - - function test_TwoMessagesWithTokensSuccess_gas() public { - vm.pauseGasMetering(); - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(); - // Set message 1 to use another receiver to simulate more fair gas costs - messages[1].receiver = address(s_secondary_receiver); - messages[1].messageId = Internal._hash(messages[1], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[1].sequenceNumber, messages[1].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - - vm.resumeGasMetering(); - s_offRamp.execute(report, new uint256[](0)); - } - - function test_TwoMessagesWithTokensAndGE_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(); - // Set message 1 to use another receiver to simulate more fair gas costs - messages[1].receiver = address(s_secondary_receiver); - messages[1].messageId = Internal._hash(messages[1], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[1].sequenceNumber, messages[1].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - assertEq(uint64(0), s_offRamp.getSenderNonce(OWNER)); - s_offRamp.execute(_generateReportFromMessages(messages), _getGasLimitsFromMessages(messages)); - assertEq(uint64(2), s_offRamp.getSenderNonce(OWNER)); - } - - function test_Fuzz_InterleavingOrderedAndUnorderedMessages_Success(bool[7] memory orderings) public { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](orderings.length); - // number of tokens needs to be capped otherwise we hit UnsupportedNumberOfTokens. - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](3); - for (uint256 i = 0; i < 3; ++i) { - tokenAmounts[i].token = s_sourceTokens[i % s_sourceTokens.length]; - tokenAmounts[i].amount = 1e18; - } - uint64 expectedNonce = 0; - for (uint256 i = 0; i < orderings.length; ++i) { - messages[i] = _generateAny2EVMMessage(uint64(i + 1), tokenAmounts, !orderings[i]); - if (orderings[i]) { - messages[i].nonce = ++expectedNonce; - } - messages[i].messageId = Internal._hash(messages[i], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[i].sequenceNumber, messages[i].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - } - - uint64 nonceBefore = s_offRamp.getSenderNonce(OWNER); - assertEq(uint64(0), nonceBefore, "nonce before exec should be 0"); - s_offRamp.execute(_generateReportFromMessages(messages), _getGasLimitsFromMessages(messages)); - // all executions should succeed. - for (uint256 i = 0; i < orderings.length; ++i) { - assertEq( - uint256(s_offRamp.getExecutionState(messages[i].sequenceNumber)), - uint256(Internal.MessageExecutionState.SUCCESS) - ); - } - assertEq(nonceBefore + expectedNonce, s_offRamp.getSenderNonce(OWNER)); - } - - function test_InvalidSourcePoolAddress_Success() public { - address fakePoolAddress = address(0x0000000000333333); - - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(); - messages[0].sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: abi.encode(s_destTokenBySourceToken[messages[0].tokenAmounts[0].token]), - extraData: "" - }) - ); - - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - messages[1].messageId = Internal._hash(messages[1], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - EVM2EVMOffRamp.TokenHandlingError.selector, - abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, abi.encode(fakePoolAddress)) - ) - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - // Reverts - - function test_InvalidMessageId_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].nonce++; - // MessageID no longer matches hash. - Internal.ExecutionReport memory executionReport = _generateReportFromMessages(messages); - vm.expectRevert(EVM2EVMOffRamp.InvalidMessageId.selector); - s_offRamp.execute(executionReport, new uint256[](0)); - } - - function test_Paused_Revert() public { - s_mockCommitStore.pause(); - vm.expectRevert(PausedError.selector); - s_offRamp.execute(_generateReportFromMessages(_generateMessagesWithTokens()), new uint256[](0)); - } - - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(EVM2EVMOffRamp.CursedByRMN.selector); - s_offRamp.execute(_generateReportFromMessages(_generateMessagesWithTokens()), new uint256[](0)); - // Uncurse should succeed - s_mockRMN.setGlobalCursed(false); - s_offRamp.execute(_generateReportFromMessages(_generateMessagesWithTokens()), new uint256[](0)); - } - - function test_UnexpectedTokenData_Revert() public { - Internal.ExecutionReport memory report = _generateReportFromMessages(_generateSingleBasicMessage()); - report.offchainTokenData = new bytes[][](report.messages.length + 1); - - vm.expectRevert(EVM2EVMOffRamp.UnexpectedTokenData.selector); - - s_offRamp.execute(report, new uint256[](0)); - } - - function test_EmptyReport_Revert() public { - vm.expectRevert(EVM2EVMOffRamp.EmptyReport.selector); - s_offRamp.execute( - Internal.ExecutionReport({ - proofs: new bytes32[](0), - proofFlagBits: 0, - messages: new Internal.EVM2EVMMessage[](0), - offchainTokenData: new bytes[][](0) - }), - new uint256[](0) - ); - } - - function test_RootNotCommitted_Revert() public { - vm.mockCall(address(s_mockCommitStore), abi.encodeWithSelector(ICommitStore.verify.selector), abi.encode(0)); - vm.expectRevert(EVM2EVMOffRamp.RootNotCommitted.selector); - - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - s_offRamp.execute(_generateReportFromMessages(messages), _getGasLimitsFromMessages(messages)); - vm.clearMockedCalls(); - } - - function test_ManualExecutionNotYetEnabled_Revert() public { - vm.mockCall( - address(s_mockCommitStore), abi.encodeWithSelector(ICommitStore.verify.selector), abi.encode(BLOCK_TIME) - ); - vm.expectRevert(EVM2EVMOffRamp.ManualExecutionNotYetEnabled.selector); - - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - s_offRamp.execute(_generateReportFromMessages(messages), _getGasLimitsFromMessages(messages)); - vm.clearMockedCalls(); - } - - function test_InvalidSourceChain_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].sourceChainSelector = SOURCE_CHAIN_SELECTOR + 1; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.InvalidSourceChain.selector, SOURCE_CHAIN_SELECTOR + 1)); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - function test_UnsupportedNumberOfTokens_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - Client.EVMTokenAmount[] memory newTokens = new Client.EVMTokenAmount[](MAX_TOKENS_LENGTH + 1); - messages[0].tokenAmounts = newTokens; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMOffRamp.UnsupportedNumberOfTokens.selector, messages[0].sequenceNumber) - ); - s_offRamp.execute(report, new uint256[](0)); - } - - function test_TokenDataMismatch_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - - report.offchainTokenData[0] = new bytes[](messages[0].tokenAmounts.length + 1); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.TokenDataMismatch.selector, messages[0].sequenceNumber)); - s_offRamp.execute(report, new uint256[](0)); - } - - function test_MessageTooLarge_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].data = new bytes(MAX_DATA_SIZE + 1); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - Internal.ExecutionReport memory executionReport = _generateReportFromMessages(messages); - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMOffRamp.MessageTooLarge.selector, MAX_DATA_SIZE, messages[0].data.length) - ); - s_offRamp.execute(executionReport, new uint256[](0)); - } - - function test_RouterYULCall_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - // gas limit too high, Router's external call should revert - messages[0].gasLimit = 1e36; - messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - Internal.ExecutionReport memory executionReport = _generateReportFromMessages(messages); - - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMOffRamp.ExecutionError.selector, abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) - ) - ); - s_offRamp.execute(executionReport, new uint256[](0)); - } - - function test_RetryFailedMessageWithoutManualExecution_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - bytes memory realError1 = new bytes(2); - realError1[0] = 0xbe; - realError1[1] = 0xef; - s_reverting_receiver.setErr(realError1); - - messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - EVM2EVMOffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) - ) - ); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.AlreadyAttempted.selector, messages[0].sequenceNumber)); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } -} - -contract EVM2EVMOffRamp_execute_upgrade is EVM2EVMOffRampSetup { - EVM2EVMOffRampHelper internal s_prevOffRamp; - - function setUp() public virtual override { - super.setUp(); - - s_prevOffRamp = s_offRamp; - - deployOffRamp(s_mockCommitStore, s_destRouter, address(s_prevOffRamp)); - } - - function test_V2_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - } - - function test_V2SenderNoncesReadsPreviousRamp_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - uint64 startNonce = s_offRamp.getSenderNonce(messages[0].sender); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOffRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - assertEq(startNonce + i, s_offRamp.getSenderNonce(messages[0].sender)); - } - } - - function test_V2NonceStartsAtV1Nonce_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - uint64 startNonce = s_offRamp.getSenderNonce(messages[0].sender); - - s_prevOffRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - assertEq(startNonce + 1, s_offRamp.getSenderNonce(messages[0].sender)); - - messages[0].nonce++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(startNonce + 2, s_offRamp.getSenderNonce(messages[0].sender)); - - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(startNonce + 3, s_offRamp.getSenderNonce(messages[0].sender)); - } - - function test_V2NonceNewSenderStartsAtZero_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_prevOffRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - address newSender = address(1234567); - messages[0].sender = newSender; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - // new sender nonce in new offramp should go from 0 -> 1 - assertEq(s_offRamp.getSenderNonce(newSender), 0); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(s_offRamp.getSenderNonce(newSender), 1); - } - - function test_V2OffRampNonceSkipsIfMsgInFlight_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - address newSender = address(1234567); - messages[0].sender = newSender; - messages[0].nonce = 2; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - uint64 startNonce = s_offRamp.getSenderNonce(messages[0].sender); - - // new offramp sees msg nonce higher than senderNonce - // it waits for previous offramp to execute - vm.expectEmit(); - emit EVM2EVMOffRamp.SkippedSenderWithPreviousRampMessageInflight(messages[0].nonce, newSender); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(startNonce, s_offRamp.getSenderNonce(messages[0].sender)); - - messages[0].nonce = 1; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - // previous offramp executes msg and increases nonce - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - s_prevOffRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(startNonce + 1, s_offRamp.getSenderNonce(messages[0].sender)); - - messages[0].nonce = 2; - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - // new offramp is able to execute - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - assertEq(startNonce + 2, s_offRamp.getSenderNonce(messages[0].sender)); - } -} - -contract EVM2EVMOffRamp_executeSingleMessage is EVM2EVMOffRampSetup { - function setUp() public virtual override { - super.setUp(); - vm.startPrank(address(s_offRamp)); - } - - function test_executeSingleMessage_NoTokens_Success() public { - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } - - function test_executeSingleMessage_WithTokens_Success() public { - Internal.EVM2EVMMessage memory message = _generateMessagesWithTokens()[0]; - bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); - Internal.SourceTokenData memory sourceTokenData = abi.decode(message.sourceTokenData[0], (Internal.SourceTokenData)); - - vm.expectCall( - s_destPoolByToken[s_destTokens[0]], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(message.sender), - receiver: message.receiver, - amount: message.tokenAmounts[0].amount, - localToken: s_destTokenBySourceToken[message.tokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: "" - }) - ) - ); - - s_offRamp.executeSingleMessage(message, offchainTokenData); - } - - function test_executeSingleMessage_ZeroGasZeroData_Success() public { - uint256 gasLimit = 0; - Internal.EVM2EVMMessage memory message = _generateMsgWithoutTokens(gasLimit); - Client.Any2EVMMessage memory receiverMsg = _convertToGeneralMessage(message); - - // expect 0 calls to be made as no gas is provided - vm.expectCall( - address(s_destRouter), - abi.encodeCall(Router.routeMessage, (receiverMsg, Internal.GAS_FOR_CALL_EXACT_CHECK, gasLimit, message.receiver)), - 0 - ); - - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - - // Ensure we encoded it properly, and didn't simply expect the wrong call - gasLimit = 200_000; - message = _generateMsgWithoutTokens(gasLimit); - receiverMsg = _convertToGeneralMessage(message); - - vm.expectCall( - address(s_destRouter), - abi.encodeCall(Router.routeMessage, (receiverMsg, Internal.GAS_FOR_CALL_EXACT_CHECK, gasLimit, message.receiver)), - 1 - ); - - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } - - function _generateMsgWithoutTokens(uint256 gasLimit) internal view returns (Internal.EVM2EVMMessage memory) { - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1); - message.gasLimit = gasLimit; - message.data = ""; - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS) - ) - ); - return message; - } - - function test_NonContract_Success() public { - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1); - message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } - - function test_NonContractWithTokens_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - vm.expectEmit(); - emit TokenPool.Released(address(s_offRamp), STRANGER, amounts[0]); - vm.expectEmit(); - emit TokenPool.Minted(address(s_offRamp), STRANGER, amounts[1]); - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } - - // Reverts - - function test_TokenHandlingError_Revert() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - bytes memory errorMessage = "Random token pool issue"; - - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - s_maybeRevertingPool.setShouldRevert(errorMessage); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.TokenHandlingError.selector, errorMessage)); - - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } - - function test_ZeroGasDONExecution_Revert() public { - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1); - message.gasLimit = 0; - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.ReceiverError.selector, "")); - - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } - - function test_MessageSender_Revert() public { - vm.stopPrank(); - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1); - vm.expectRevert(EVM2EVMOffRamp.CanOnlySelfCall.selector); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); - } -} - -contract EVM2EVMOffRamp__report is EVM2EVMOffRampSetup { - // Asserts that execute completes - function test_Report_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - s_offRamp.report(abi.encode(report)); - } -} - -contract EVM2EVMOffRamp_manuallyExecute is EVM2EVMOffRampSetup { - function test_ManualExec_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - s_reverting_receiver.setRevert(false); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), new uint256[](messages.length)); - } - - function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - assertEq(messages[0].nonce - 1, s_offRamp.getSenderNonce(messages[0].sender)); - - s_reverting_receiver.setRevert(true); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - EVM2EVMOffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") - ) - ); - - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), new uint256[](1)); - - assertEq(messages[0].nonce, s_offRamp.getSenderNonce(messages[0].sender)); - } - - function test_ManualExecWithGasOverride_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - s_reverting_receiver.setRevert(false); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - - uint256[] memory gasLimitOverrides = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0] += 1; - - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), gasLimitOverrides); - } - - function test_LowGasLimitManualExec_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].gasLimit = 1; - messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector(EVM2EVMOffRamp.ReceiverError.selector, "") - ); - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - uint256[] memory gasLimitOverrides = new uint256[](1); - gasLimitOverrides[0] = 100_000; - - vm.expectEmit(); - emit MaybeRevertMessageReceiver.MessageReceived(); - - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, messages[0].messageId, Internal.MessageExecutionState.SUCCESS, "" - ); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), gasLimitOverrides); - } - - function test_ManualExecForkedChain_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - uint256 chain1 = block.chainid; - uint256 chain2 = chain1 + 1; - vm.chainId(chain2); - vm.expectRevert(abi.encodeWithSelector(OCR2BaseNoChecks.ForkedChain.selector, chain1, chain2)); - - s_offRamp.manuallyExecute(report, _getGasLimitsFromMessages(messages)); - } - - function test_ManualExecGasLimitMismatch_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - vm.expectRevert(EVM2EVMOffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), new uint256[](0)); - - vm.expectRevert(EVM2EVMOffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), new uint256[](messages.length - 1)); - - vm.expectRevert(EVM2EVMOffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), new uint256[](messages.length + 1)); - } - - function test_ManualExecInvalidGasLimit_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - uint256[] memory gasLimits = _getGasLimitsFromMessages(messages); - gasLimits[0]--; - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.InvalidManualExecutionGasLimit.selector, 0, gasLimits[0])); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), gasLimits); - } - - function test_ManualExecFailedTx_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - - messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0)); - - s_reverting_receiver.setRevert(true); - - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMOffRamp.ExecutionError.selector, - abi.encodeWithSelector( - EVM2EVMOffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) - ) - ) - ); - s_offRamp.manuallyExecute(_generateReportFromMessages(messages), _getGasLimitsFromMessages(messages)); - } - - function test_ReentrancyManualExecuteFails() public { - uint256 tokenAmount = 1e9; - IERC20 tokenToAbuse = IERC20(s_destFeeToken); - - // This needs to be deployed before the source chain message is sent - // because we need the address for the receiver. - ReentrancyAbuser receiver = new ReentrancyAbuser(address(s_destRouter), s_offRamp); - uint256 balancePre = tokenToAbuse.balanceOf(address(receiver)); - - // For this test any message will be flagged as correct by the - // commitStore. In a real scenario the abuser would have to actually - // send the message that they want to replay. - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(); - messages[0].tokenAmounts = new Client.EVMTokenAmount[](1); - messages[0].tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: tokenAmount}); - messages[0].receiver = address(receiver); - messages[0].sourceTokenData = new bytes[](1); - messages[0].sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), - extraData: "" - }) - ); - - messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash()); - - Internal.ExecutionReport memory report = _generateReportFromMessages(messages); - - // sets the report to be repeated on the ReentrancyAbuser to be able to replay - receiver.setPayload(report); - - // The first entry should be fine and triggers the second entry. This one fails - // but since it's an inner tx of the first one it is caught in the try-catch. - // This means the first tx is marked `FAILURE` with the error message of the second tx. - vm.expectEmit(); - emit EVM2EVMOffRamp.ExecutionStateChanged( - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - EVM2EVMOffRamp.ReceiverError.selector, - abi.encodeWithSelector(EVM2EVMOffRamp.AlreadyExecuted.selector, messages[0].sequenceNumber) - ) - ); - - s_offRamp.manuallyExecute(report, _getGasLimitsFromMessages(messages)); - - // Since the tx failed we don't release the tokens - assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre); - } -} - -contract EVM2EVMOffRamp_getExecutionState is EVM2EVMOffRampSetup { - mapping(uint64 seqNum => Internal.MessageExecutionState state) internal s_differentialExecutionState; - - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 32 - function test_Fuzz_Differential_Success(uint16[500] memory seqNums, uint8[500] memory values) public { - for (uint256 i = 0; i < seqNums.length; ++i) { - // Only use the first three slots. This makes sure existing slots get overwritten - // as the tests uses 500 sequence numbers. - uint16 seqNum = seqNums[i] % 386; - Internal.MessageExecutionState state = Internal.MessageExecutionState(values[i] % 4); - s_differentialExecutionState[seqNum] = state; - s_offRamp.setExecutionStateHelper(seqNum, state); - assertEq(uint256(state), uint256(s_offRamp.getExecutionState(seqNum))); - } - - for (uint256 i = 0; i < seqNums.length; ++i) { - uint16 seqNum = seqNums[i] % 386; - Internal.MessageExecutionState expectedState = s_differentialExecutionState[seqNum]; - assertEq(uint256(expectedState), uint256(s_offRamp.getExecutionState(seqNum))); - } - } - - function test_GetExecutionState_Success() public { - s_offRamp.setExecutionStateHelper(0, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(0), 3); - - s_offRamp.setExecutionStateHelper(1, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(0), 3 + (3 << 2)); - - s_offRamp.setExecutionStateHelper(1, Internal.MessageExecutionState.IN_PROGRESS); - assertEq(s_offRamp.getExecutionStateBitMap(0), 3 + (1 << 2)); - - s_offRamp.setExecutionStateHelper(2, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(0), 3 + (1 << 2) + (3 << 4)); - - s_offRamp.setExecutionStateHelper(127, Internal.MessageExecutionState.IN_PROGRESS); - assertEq(s_offRamp.getExecutionStateBitMap(0), 3 + (1 << 2) + (3 << 4) + (1 << 254)); - - s_offRamp.setExecutionStateHelper(128, Internal.MessageExecutionState.SUCCESS); - assertEq(s_offRamp.getExecutionStateBitMap(0), 3 + (1 << 2) + (3 << 4) + (1 << 254)); - assertEq(s_offRamp.getExecutionStateBitMap(1), 2); - - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(0))); - assertEq(uint256(Internal.MessageExecutionState.IN_PROGRESS), uint256(s_offRamp.getExecutionState(1))); - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(2))); - assertEq(uint256(Internal.MessageExecutionState.IN_PROGRESS), uint256(s_offRamp.getExecutionState(127))); - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(s_offRamp.getExecutionState(128))); - } - - function test_FillExecutionState_Success() public { - for (uint64 i = 0; i < 384; ++i) { - s_offRamp.setExecutionStateHelper(i, Internal.MessageExecutionState.FAILURE); - } - - for (uint64 i = 0; i < 384; ++i) { - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(i))); - } - - for (uint64 i = 0; i < 3; ++i) { - assertEq(type(uint256).max, s_offRamp.getExecutionStateBitMap(i)); - } - - for (uint64 i = 0; i < 384; ++i) { - s_offRamp.setExecutionStateHelper(i, Internal.MessageExecutionState.IN_PROGRESS); - } - - for (uint64 i = 0; i < 384; ++i) { - assertEq(uint256(Internal.MessageExecutionState.IN_PROGRESS), uint256(s_offRamp.getExecutionState(i))); - } - - for (uint64 i = 0; i < 3; ++i) { - // 0x555... == 0b101010101010..... - assertEq(0x5555555555555555555555555555555555555555555555555555555555555555, s_offRamp.getExecutionStateBitMap(i)); - } - } -} - -contract EVM2EVMOffRamp__trialExecute is EVM2EVMOffRampSetup { - function test_trialExecute_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - IERC20 dstToken0 = IERC20(s_destTokens[0]); - uint256 startingBalance = dstToken0.balanceOf(message.receiver); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); - assertEq("", err); - - // Check that the tokens were transferred - assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver)); - } - - function test_TokenHandlingErrorIsCaught_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - IERC20 dstToken0 = IERC20(s_destTokens[0]); - uint256 startingBalance = dstToken0.balanceOf(OWNER); - - bytes memory errorMessage = "Random token pool issue"; - - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - s_maybeRevertingPool.setShouldRevert(errorMessage); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(EVM2EVMOffRamp.TokenHandlingError.selector, errorMessage), err); - - // Expect the balance to remain the same - assertEq(startingBalance, dstToken0.balanceOf(OWNER)); - } - - function test_RateLimitError_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - bytes memory errorMessage = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); - - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - s_maybeRevertingPool.setShouldRevert(errorMessage); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(EVM2EVMOffRamp.TokenHandlingError.selector, errorMessage), err); - } - - function test_TokenPoolIsNotAContract_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 10000; - Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts); - - // Happy path, pool is correct - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); - assertEq("", err); - - // address 0 has no contract - assertEq(address(0).code.length, 0); - message.sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(address(0)), - extraData: "" - }) - ); - - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS) - ) - ); - - // Unhappy path, no revert but marked as failed. - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(address(0))), err); - - address notAContract = makeAddr("not_a_contract"); - - message.sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(notAContract), - extraData: "" - }) - ); - - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS) - ) - ); - - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); - - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(EVM2EVMOffRamp.NotACompatiblePool.selector, address(0)), err); - } -} - -contract EVM2EVMOffRamp__releaseOrMintToken is EVM2EVMOffRampSetup { - function test__releaseOrMintToken_Success() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - bytes memory originalSender = abi.encode(OWNER); - bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - - IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); - uint256 startingBalance = dstToken1.balanceOf(OWNER); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), - extraData: "" - }); - - vm.expectCall( - s_destPoolBySourceToken[token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: OWNER, - amount: amount, - localToken: s_destTokenBySourceToken[token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ) - ); - - s_offRamp.releaseOrMintToken(amount, originalSender, OWNER, sourceTokenData, offchainTokenData); - - assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); - } - - function test__releaseOrMintToken_NotACompatiblePool_Revert() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - address destToken = s_destTokenBySourceToken[token]; - vm.label(destToken, "destToken"); - bytes memory originalSender = abi.encode(OWNER); - bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(destToken), - extraData: "" - }); - - // Address(0) should always revert - address returnedPool = address(0); - - vm.mockCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), - abi.encode(returnedPool) - ); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.NotACompatiblePool.selector, returnedPool)); - - s_offRamp.releaseOrMintToken(amount, originalSender, OWNER, sourceTokenData, offchainTokenData); - - // A contract that doesn't support the interface should also revert - returnedPool = address(s_offRamp); - - vm.mockCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), - abi.encode(returnedPool) - ); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.NotACompatiblePool.selector, returnedPool)); - - s_offRamp.releaseOrMintToken(amount, originalSender, OWNER, sourceTokenData, offchainTokenData); - } - - function test__releaseOrMintToken_TokenHandlingError_revert_Revert() public { - address receiver = makeAddr("receiver"); - uint256 amount = 123123; - address token = s_sourceTokens[0]; - address destToken = s_destTokenBySourceToken[token]; - bytes memory originalSender = abi.encode(OWNER); - bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(destToken), - extraData: "" - }); - - bytes memory revertData = "call reverted :o"; - - vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.TokenHandlingError.selector, revertData)); - s_offRamp.releaseOrMintToken(amount, originalSender, receiver, sourceTokenData, offchainTokenData); - } -} - -contract EVM2EVMOffRamp__releaseOrMintTokens is EVM2EVMOffRampSetup { - function test_releaseOrMintTokens_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - IERC20 dstToken1 = IERC20(s_destFeeToken); - uint256 startingBalance = dstToken1.balanceOf(OWNER); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes memory originalSender = abi.encode(OWNER); - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); - - vm.expectCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: OWNER, - amount: srcTokenAmounts[0].amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData[0] - }) - ) - ); - - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, encodedSourceTokenData, offchainTokenData); - - assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); - } - - function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - address destToken = s_destFeeToken; - uint256 amount = 100; - uint256 destinationDenominationMultiplier = 1000; - srcTokenAmounts[0].amount = amount; - - bytes memory originalSender = abi.encode(OWNER); - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); - - // Since the pool call is mocked, we manually release funds to the offRamp - deal(destToken, address(s_offRamp), amount * destinationDenominationMultiplier); - - vm.mockCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: OWNER, - amount: amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData[0] - }) - ), - abi.encode(amount * destinationDenominationMultiplier) - ); - - Client.EVMTokenAmount[] memory destTokenAmounts = - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, encodedSourceTokenData, offchainTokenData); - - assertEq(destTokenAmounts[0].amount, amount * destinationDenominationMultiplier); - assertEq(destTokenAmounts[0].token, destToken); - } - - function test_OverValueWithARLOff_Success() public { - // Set a high price to trip the ARL - uint224 tokenPrice = 3 ** 128; - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(s_destFeeToken, tokenPrice); - s_priceRegistry.updatePrices(priceUpdates); - - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes memory originalSender = abi.encode(OWNER); - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - bytes[] memory sourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueMaxCapacityExceeded.selector, - getInboundRateLimiterConfig().capacity, - (amount1 * tokenPrice) / 1e18 - ) - ); - - // // Expect to fail from ARL - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, sourceTokenData, offchainTokenData); - - // Configure ARL off for token - EVM2EVMOffRamp.RateLimitToken[] memory removes = new EVM2EVMOffRamp.RateLimitToken[](1); - removes[0] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceFeeToken, destToken: s_destFeeToken}); - s_offRamp.updateRateLimitTokens(removes, new EVM2EVMOffRamp.RateLimitToken[](0)); - - // Expect the call now succeeds - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, sourceTokenData, offchainTokenData); - } - - // Revert - - function test_TokenHandlingError_Reverts() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - bytes memory unknownError = bytes("unknown error"); - s_maybeRevertingPool.setShouldRevert(unknownError); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.TokenHandlingError.selector, unknownError)); - - s_offRamp.releaseOrMintTokens( - srcTokenAmounts, - abi.encode(OWNER), - OWNER, - _getDefaultSourceTokenData(srcTokenAmounts), - new bytes[](srcTokenAmounts.length) - ); - } - - function test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() public { - uint256 amount = 100; - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - srcTokenAmounts[0].amount = amount; - - bytes memory originalSender = abi.encode(OWNER); - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); - - vm.mockCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: OWNER, - amount: amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData[0] - }) - ), - // Includes the amount twice, this will revert due to the return data being to long - abi.encode(amount, amount) - ); - - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMOffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64) - ); - - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, encodedSourceTokenData, offchainTokenData); - } - - function test_releaseOrMintTokens_InvalidEVMAddress_Revert() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - bytes memory originalSender = abi.encode(OWNER); - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - bytes[] memory sourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - bytes memory wrongAddress = abi.encode(address(1000), address(10000), address(10000)); - - sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[0].token]), - destTokenAddress: wrongAddress, - extraData: "" - }) - ); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, wrongAddress)); - - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, sourceTokenData, offchainTokenData); - } - - function test_RateLimitErrors_Reverts() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - bytes[] memory rateLimitErrors = new bytes[](5); - rateLimitErrors[0] = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); - rateLimitErrors[1] = - abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, uint256(100), uint256(1000)); - rateLimitErrors[2] = - abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, uint256(42), 1, s_sourceTokens[0]); - rateLimitErrors[3] = abi.encodeWithSelector( - RateLimiter.TokenMaxCapacityExceeded.selector, uint256(100), uint256(1000), s_sourceTokens[0] - ); - rateLimitErrors[4] = - abi.encodeWithSelector(RateLimiter.TokenRateLimitReached.selector, uint256(42), 1, s_sourceTokens[0]); - - for (uint256 i = 0; i < rateLimitErrors.length; ++i) { - s_maybeRevertingPool.setShouldRevert(rateLimitErrors[i]); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.TokenHandlingError.selector, rateLimitErrors[i])); - - s_offRamp.releaseOrMintTokens( - srcTokenAmounts, - abi.encode(OWNER), - OWNER, - _getDefaultSourceTokenData(srcTokenAmounts), - new bytes[](srcTokenAmounts.length) - ); - } - } - - function test__releaseOrMintTokens_NotACompatiblePool_Reverts() public { - address fakePoolAddress = makeAddr("Doesn't exist"); - - bytes[] memory sourceTokenData = new bytes[](1); - sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: abi.encode(fakePoolAddress), - extraData: "" - }) - ); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOffRamp.NotACompatiblePool.selector, address(0))); - s_offRamp.releaseOrMintTokens( - new Client.EVMTokenAmount[](1), abi.encode(makeAddr("original_sender")), OWNER, sourceTokenData, new bytes[](1) - ); - } - - function test_PriceNotFoundForToken_Reverts() public { - // Set token price to 0 - s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(s_destFeeToken, 0)); - - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes memory originalSender = abi.encode(OWNER); - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - bytes[] memory sourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, s_destFeeToken)); - - s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, sourceTokenData, offchainTokenData); - } - - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 1024 - // Uint256 gives a good range of values to test, both inside and outside of the eth address space. - function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success(uint256 destPool) public { - // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C - // triggers some Create2Deployer and causes it to fail - vm.assume(destPool != 447301751254033913445893214690834296930546521452); - bytes memory unusedVar = abi.encode(makeAddr("unused")); - bytes[] memory sourceTokenData = new bytes[](1); - sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: unusedVar, - destTokenAddress: abi.encode(destPool), - extraData: unusedVar - }) - ); - - try s_offRamp.releaseOrMintTokens(new Client.EVMTokenAmount[](1), unusedVar, OWNER, sourceTokenData, new bytes[](1)) - {} catch (bytes memory reason) { - // Any revert should be a TokenHandlingError, InvalidEVMAddress, InvalidDataLength or NoContract as those are caught by the offramp - assertTrue( - bytes4(reason) == EVM2EVMOffRamp.TokenHandlingError.selector - || bytes4(reason) == Internal.InvalidEVMAddress.selector - || bytes4(reason) == EVM2EVMOffRamp.InvalidDataLength.selector - || bytes4(reason) == CallWithExactGas.NoContract.selector - || bytes4(reason) == EVM2EVMOffRamp.NotACompatiblePool.selector, - "Expected TokenHandlingError or InvalidEVMAddress" - ); - - if (destPool > type(uint160).max) { - assertEq(reason, abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(destPool))); - } - } - } -} - -contract EVM2EVMOffRamp_getAllRateLimitTokens is EVM2EVMOffRampSetup { - function test_GetAllRateLimitTokens_Success() public view { - (address[] memory sourceTokens, address[] memory destTokens) = s_offRamp.getAllRateLimitTokens(); - - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - assertEq(s_sourceTokens[i], sourceTokens[i]); - assertEq(s_destTokens[i], destTokens[i]); - } - } -} - -contract EVM2EVMOffRamp_updateRateLimitTokens is EVM2EVMOffRampSetup { - function setUp() public virtual override { - super.setUp(); - // Clear rate limit tokens state - EVM2EVMOffRamp.RateLimitToken[] memory remove = new EVM2EVMOffRamp.RateLimitToken[](s_sourceTokens.length); - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - remove[i] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); - } - s_offRamp.updateRateLimitTokens(remove, new EVM2EVMOffRamp.RateLimitToken[](0)); - } - - function test_updateRateLimitTokens_Success() public { - EVM2EVMOffRamp.RateLimitToken[] memory adds = new EVM2EVMOffRamp.RateLimitToken[](2); - adds[0] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); - adds[1] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); - - for (uint256 i = 0; i < adds.length; ++i) { - vm.expectEmit(); - emit EVM2EVMOffRamp.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); - } - - s_offRamp.updateRateLimitTokens(new EVM2EVMOffRamp.RateLimitToken[](0), adds); - - (address[] memory sourceTokens, address[] memory destTokens) = s_offRamp.getAllRateLimitTokens(); - - for (uint256 i = 0; i < adds.length; ++i) { - assertEq(adds[i].sourceToken, sourceTokens[i]); - assertEq(adds[i].destToken, destTokens[i]); - } - } - - function test_updateRateLimitTokens_AddsAndRemoves_Success() public { - EVM2EVMOffRamp.RateLimitToken[] memory adds = new EVM2EVMOffRamp.RateLimitToken[](3); - adds[0] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); - adds[1] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); - // Add a duplicate, this should not revert the tx - adds[2] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); - - EVM2EVMOffRamp.RateLimitToken[] memory removes = new EVM2EVMOffRamp.RateLimitToken[](1); - removes[0] = adds[0]; - - for (uint256 i = 0; i < adds.length - 1; ++i) { - vm.expectEmit(); - emit EVM2EVMOffRamp.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); - } - - s_offRamp.updateRateLimitTokens(removes, adds); - - for (uint256 i = 0; i < removes.length; ++i) { - vm.expectEmit(); - emit EVM2EVMOffRamp.TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); - } - - s_offRamp.updateRateLimitTokens(removes, new EVM2EVMOffRamp.RateLimitToken[](0)); - - (address[] memory sourceTokens, address[] memory destTokens) = s_offRamp.getAllRateLimitTokens(); - - assertEq(1, sourceTokens.length); - assertEq(adds[1].sourceToken, sourceTokens[0]); - - assertEq(1, destTokens.length); - assertEq(adds[1].destToken, destTokens[0]); - } - - function test_Fuzz_UpdateRateLimitTokens(uint8 numTokens) public { - // Needs to be more than 1 so that the division doesn't round down and the even makes the comparisons simpler - vm.assume(numTokens > 1 && numTokens % 2 == 0); - - // Clear the Rate limit tokens array so the test can start from a baseline - (address[] memory sourceTokens, address[] memory destTokens) = s_offRamp.getAllRateLimitTokens(); - EVM2EVMOffRamp.RateLimitToken[] memory removes = new EVM2EVMOffRamp.RateLimitToken[](sourceTokens.length); - for (uint256 x = 0; x < removes.length; x++) { - removes[x] = EVM2EVMOffRamp.RateLimitToken({sourceToken: sourceTokens[x], destToken: destTokens[x]}); - } - s_offRamp.updateRateLimitTokens(removes, new EVM2EVMOffRamp.RateLimitToken[](0)); - - // Sanity check that the rateLimitTokens were successfully cleared - (sourceTokens, destTokens) = s_offRamp.getAllRateLimitTokens(); - assertEq(sourceTokens.length, 0, "sourceTokenLength should be zero"); - - EVM2EVMOffRamp.RateLimitToken[] memory adds = new EVM2EVMOffRamp.RateLimitToken[](numTokens); - - for (uint256 x = 0; x < numTokens; x++) { - address tokenAddr = vm.addr(x + 1); - - // Create an array of several fake tokens to add which are deployed on the same address on both chains for simplicity - adds[x] = EVM2EVMOffRamp.RateLimitToken({sourceToken: tokenAddr, destToken: tokenAddr}); - } - - // Attempt to add the tokens to the RateLimitToken Array - s_offRamp.updateRateLimitTokens(new EVM2EVMOffRamp.RateLimitToken[](0), adds); - - // Retrieve them from storage and make sure that they all match the expected adds - (sourceTokens, destTokens) = s_offRamp.getAllRateLimitTokens(); - - for (uint256 x = 0; x < sourceTokens.length; x++) { - // Check that the tokens match the ones we generated earlier - assertEq(sourceTokens[x], adds[x].sourceToken, "Source token doesn't match add"); - assertEq(destTokens[x], adds[x].sourceToken, "dest Token doesn't match add"); - } - - // Attempt to remove half of the numTokens by removing the second half of the list and copying it to a removes array - removes = new EVM2EVMOffRamp.RateLimitToken[](adds.length / 2); - - for (uint256 x = 0; x < adds.length / 2; x++) { - removes[x] = adds[x + (adds.length / 2)]; - } - - // Attempt to update again, this time adding nothing and removing the second half of the tokens - s_offRamp.updateRateLimitTokens(removes, new EVM2EVMOffRamp.RateLimitToken[](0)); - - (sourceTokens, destTokens) = s_offRamp.getAllRateLimitTokens(); - assertEq(sourceTokens.length, adds.length / 2, "Current Rate limit token length is not half of the original adds"); - for (uint256 x = 0; x < sourceTokens.length; x++) { - // Check that the tokens match the ones we generated earlier and didn't remove in the previous step - assertEq(sourceTokens[x], adds[x].sourceToken, "Source token doesn't match add after removes"); - assertEq(destTokens[x], adds[x].destToken, "dest Token doesn't match add after removes"); - } - } - - // Reverts - - function test_updateRateLimitTokens_NonOwner_Revert() public { - EVM2EVMOffRamp.RateLimitToken[] memory addsAndRemoves = new EVM2EVMOffRamp.RateLimitToken[](4); - - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - - s_offRamp.updateRateLimitTokens(addsAndRemoves, addsAndRemoves); - } -} diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol deleted file mode 100644 index 053869b88a6..00000000000 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; -import {ICommitStore} from "../../interfaces/ICommitStore.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; - -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; -import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {MockCommitStore} from "../mocks/MockCommitStore.sol"; -import {OCR2BaseSetup} from "../ocr/OCR2Base.t.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract EVM2EVMOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSetup { - MockCommitStore internal s_mockCommitStore; - IAny2EVMMessageReceiver internal s_receiver; - IAny2EVMMessageReceiver internal s_secondary_receiver; - MaybeRevertMessageReceiver internal s_reverting_receiver; - - MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; - - EVM2EVMOffRampHelper internal s_offRamp; - address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); - - function setUp() public virtual override(TokenSetup, PriceRegistrySetup, OCR2BaseSetup) { - TokenSetup.setUp(); - PriceRegistrySetup.setUp(); - OCR2BaseSetup.setUp(); - - s_mockCommitStore = new MockCommitStore(); - s_receiver = new MaybeRevertMessageReceiver(false); - s_secondary_receiver = new MaybeRevertMessageReceiver(false); - s_reverting_receiver = new MaybeRevertMessageReceiver(true); - - s_maybeRevertingPool = MaybeRevertingBurnMintTokenPool(s_destPoolByToken[s_destTokens[1]]); - - deployOffRamp(s_mockCommitStore, s_destRouter, address(0)); - } - - function deployOffRamp(ICommitStore commitStore, Router router, address prevOffRamp) internal { - s_offRamp = new EVM2EVMOffRampHelper( - EVM2EVMOffRamp.StaticConfig({ - commitStore: address(commitStore), - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRamp: ON_RAMP_ADDRESS, - prevOffRamp: prevOffRamp, - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - getInboundRateLimiterConfig() - ); - s_offRamp.setOCR2Config( - s_valid_signers, - s_valid_transmitters, - s_f, - abi.encode(generateDynamicOffRampConfig(address(router), address(s_priceRegistry))), - s_offchainConfigVersion, - abi.encode("") - ); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: address(s_offRamp)}); - offRampUpdates[1] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: address(prevOffRamp)}); - s_destRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - EVM2EVMOffRamp.RateLimitToken[] memory tokensToAdd = new EVM2EVMOffRamp.RateLimitToken[](s_sourceTokens.length); - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); - } - s_offRamp.updateRateLimitTokens(new EVM2EVMOffRamp.RateLimitToken[](0), tokensToAdd); - } - - function generateDynamicOffRampConfig( - address router, - address priceRegistry - ) internal pure returns (EVM2EVMOffRamp.DynamicConfig memory) { - return EVM2EVMOffRamp.DynamicConfig({ - permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, - router: router, - priceRegistry: priceRegistry, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - maxDataBytes: MAX_DATA_SIZE, - maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, - maxTokenTransferGas: MAX_TOKEN_POOL_TRANSFER_GAS - }); - } - - function _convertToGeneralMessage(Internal.EVM2EVMMessage memory original) - internal - view - returns (Client.Any2EVMMessage memory message) - { - uint256 numberOfTokens = original.tokenAmounts.length; - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); - - for (uint256 i = 0; i < numberOfTokens; ++i) { - Internal.SourceTokenData memory sourceTokenData = - abi.decode(original.sourceTokenData[i], (Internal.SourceTokenData)); - - address destPoolAddress = abi.decode(sourceTokenData.destTokenAddress, (address)); - TokenPool pool = TokenPool(destPoolAddress); - destTokenAmounts[i].token = address(pool.getToken()); - destTokenAmounts[i].amount = original.tokenAmounts[i].amount; - } - - return Client.Any2EVMMessage({ - messageId: original.messageId, - sourceChainSelector: original.sourceChainSelector, - sender: abi.encode(original.sender), - data: original.data, - destTokenAmounts: destTokenAmounts - }); - } - - function _generateAny2EVMMessageNoTokens(uint64 sequenceNumber) - internal - view - returns (Internal.EVM2EVMMessage memory) - { - return _generateAny2EVMMessage(sequenceNumber, new Client.EVMTokenAmount[](0), false); - } - - function _generateAny2EVMMessageWithTokens( - uint64 sequenceNumber, - uint256[] memory amounts - ) internal view returns (Internal.EVM2EVMMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - tokenAmounts[i].amount = amounts[i]; - } - return _generateAny2EVMMessage(sequenceNumber, tokenAmounts, false); - } - - function _generateAny2EVMMessage( - uint64 sequenceNumber, - Client.EVMTokenAmount[] memory tokenAmounts, - bool allowOutOfOrderExecution - ) internal view returns (Internal.EVM2EVMMessage memory) { - bytes memory data = abi.encode(0); - Internal.EVM2EVMMessage memory message = Internal.EVM2EVMMessage({ - sequenceNumber: sequenceNumber, - sender: OWNER, - nonce: allowOutOfOrderExecution ? 0 : sequenceNumber, - gasLimit: GAS_LIMIT, - strict: false, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - receiver: address(s_receiver), - data: data, - tokenAmounts: tokenAmounts, - sourceTokenData: new bytes[](tokenAmounts.length), - feeToken: s_destFeeToken, - feeTokenAmount: uint256(0), - messageId: "" - }); - - // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - message.sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[tokenAmounts[i].token]), - extraData: "" - }) - ); - } - - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS) - ) - ); - - return message; - } - - function _generateSingleBasicMessage() internal view returns (Internal.EVM2EVMMessage[] memory) { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](1); - messages[0] = _generateAny2EVMMessageNoTokens(1); - return messages; - } - - function _generateMessagesWithTokens() internal view returns (Internal.EVM2EVMMessage[] memory) { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](2); - Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - tokenAmounts[0].amount = 1e18; - tokenAmounts[1].amount = 5e18; - messages[0] = _generateAny2EVMMessage(1, tokenAmounts, false); - messages[1] = _generateAny2EVMMessage(2, tokenAmounts, false); - - return messages; - } - - function _generateReportFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (Internal.ExecutionReport memory) - { - bytes[][] memory offchainTokenData = new bytes[][](messages.length); - - for (uint256 i = 0; i < messages.length; ++i) { - offchainTokenData[i] = new bytes[](messages[i].tokenAmounts.length); - } - - return Internal.ExecutionReport({ - proofs: new bytes32[](0), - proofFlagBits: 2 ** 256 - 1, - messages: messages, - offchainTokenData: offchainTokenData - }); - } - - function _getGasLimitsFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (uint256[] memory) - { - uint256[] memory gasLimits = new uint256[](messages.length); - for (uint256 i = 0; i < messages.length; ++i) { - gasLimits[i] = messages[i].gasLimit; - } - - return gasLimits; - } - - function _assertSameConfig(EVM2EVMOffRamp.DynamicConfig memory a, EVM2EVMOffRamp.DynamicConfig memory b) public pure { - assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); - assertEq(a.router, b.router); - assertEq(a.priceRegistry, b.priceRegistry); - assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); - assertEq(a.maxDataBytes, b.maxDataBytes); - assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); - assertEq(a.maxTokenTransferGas, b.maxTokenTransferGas); - } - - function _getDefaultSourceTokenData(Client.EVMTokenAmount[] memory srcTokenAmounts) - internal - view - returns (bytes[] memory) - { - bytes[] memory sourceTokenData = new bytes[](srcTokenAmounts.length); - for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { - sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[srcTokenAmounts[i].token]), - extraData: "" - }) - ); - } - return sourceTokenData; - } -} diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol similarity index 58% rename from contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol rename to contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 43899cbfd69..c5e52db395b 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -1,88 +1,95 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {ICommitStore} from "../../interfaces/ICommitStore.sol"; +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {NonceManager} from "../../NonceManager.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; -import {RMN} from "../../RMN.sol"; -import {Router} from "../../Router.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; -import {EVM2EVMMultiOffRamp} from "../../offRamp/EVM2EVMMultiOffRamp.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; -import {EVM2EVMMultiOffRampHelper} from "../helpers/EVM2EVMMultiOffRampHelper.sol"; -import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; +import {OffRampHelper} from "../helpers/OffRampHelper.sol"; import {ConformingReceiver} from "../helpers/receivers/ConformingReceiver.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MaybeRevertMessageReceiverNo165} from "../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; import {ReentrancyAbuserMultiRamp} from "../helpers/receivers/ReentrancyAbuserMultiRamp.sol"; -import {EVM2EVMMultiOffRampSetup} from "./EVM2EVMMultiOffRampSetup.t.sol"; +import {OffRampSetup} from "./OffRampSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { +contract OffRamp_constructor is OffRampSetup { function test_Constructor_Success() public { - EVM2EVMMultiOffRamp.StaticConfig memory staticConfig = EVM2EVMMultiOffRamp.StaticConfig({ + OffRamp.StaticConfig memory staticConfig = OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }); - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - _generateDynamicMultiOffRampConfig(address(s_destRouter), address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](2); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true }); - sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, onRamp: ON_RAMP_ADDRESS_2, isEnabled: true }); - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig1 = - EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: true, minSeqNr: 1, onRamp: sourceChainConfigs[0].onRamp}); + OffRamp.SourceChainConfig memory expectedSourceChainConfig1 = OffRamp.SourceChainConfig({ + router: s_destRouter, + isEnabled: true, + minSeqNr: 1, + onRamp: sourceChainConfigs[0].onRamp + }); + + OffRamp.SourceChainConfig memory expectedSourceChainConfig2 = OffRamp.SourceChainConfig({ + router: s_destRouter, + isEnabled: true, + minSeqNr: 1, + onRamp: sourceChainConfigs[1].onRamp + }); - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig2 = - EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: true, minSeqNr: 1, onRamp: sourceChainConfigs[1].onRamp}); + uint64[] memory expectedSourceChainSelectors = new uint64[](2); + expectedSourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + expectedSourceChainSelectors[1] = SOURCE_CHAIN_SELECTOR_1 + 1; vm.expectEmit(); - emit EVM2EVMMultiOffRamp.StaticConfigSet(staticConfig); + emit OffRamp.StaticConfigSet(staticConfig); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.DynamicConfigSet(dynamicConfig); + emit OffRamp.DynamicConfigSet(dynamicConfig); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); + emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig1); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig1); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1 + 1); + emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1 + 1); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1 + 1, expectedSourceChainConfig2); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1 + 1, expectedSourceChainConfig2); - s_offRamp = new EVM2EVMMultiOffRampHelper(staticConfig, dynamicConfig, sourceChainConfigs); + s_offRamp = new OffRampHelper(staticConfig, dynamicConfig, sourceChainConfigs); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ @@ -97,13 +104,13 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { s_offRamp.setOCR3Configs(ocrConfigs); // Static config - EVM2EVMMultiOffRamp.StaticConfig memory gotStaticConfig = s_offRamp.getStaticConfig(); + OffRamp.StaticConfig memory gotStaticConfig = s_offRamp.getStaticConfig(); assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); - assertEq(staticConfig.rmnProxy, gotStaticConfig.rmnProxy); + assertEq(address(staticConfig.rmnRemote), address(gotStaticConfig.rmnRemote)); assertEq(staticConfig.tokenAdminRegistry, gotStaticConfig.tokenAdminRegistry); // Dynamic config - EVM2EVMMultiOffRamp.DynamicConfig memory gotDynamicConfig = s_offRamp.getDynamicConfig(); + OffRamp.DynamicConfig memory gotDynamicConfig = s_offRamp.getDynamicConfig(); _assertSameConfig(dynamicConfig, gotDynamicConfig); // OCR Config @@ -120,17 +127,21 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { MultiOCR3Base.OCRConfig memory gotOCRConfig = s_offRamp.latestConfigDetails(uint8(Internal.OCRPluginType.Execution)); _assertOCRConfigEquality(expectedOCRConfig, gotOCRConfig); - _assertSourceChainConfigEquality( - s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig1 - ); - _assertSourceChainConfigEquality( - s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1 + 1), expectedSourceChainConfig2 - ); + (uint64[] memory actualSourceChainSelectors, OffRamp.SourceChainConfig[] memory actualSourceChainConfigs) = + s_offRamp.getAllSourceChainConfigs(); + + _assertSourceChainConfigEquality(actualSourceChainConfigs[0], expectedSourceChainConfig1); + _assertSourceChainConfigEquality(actualSourceChainConfigs[1], expectedSourceChainConfig2); // OffRamp initial values - assertEq("EVM2EVMMultiOffRamp 1.6.0-dev", s_offRamp.typeAndVersion()); + assertEq("OffRamp 1.6.0-dev", s_offRamp.typeAndVersion()); assertEq(OWNER, s_offRamp.owner()); assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + + // assertion for source chain selector + for (uint256 i = 0; i < expectedSourceChainSelectors.length; i++) { + assertEq(expectedSourceChainSelectors[i], actualSourceChainSelectors[i]); + } } // Revert @@ -138,24 +149,24 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: new bytes(0), isEnabled: true }); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -164,42 +175,44 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = - EVM2EVMMultiOffRamp.SourceChainConfigArgs({sourceChainSelector: 0, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true}); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: 0, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroChainSelectorNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } - function test_ZeroRMNProxy_Revert() public { + function test_ZeroRMNRemote_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: ZERO_ADDRESS, + rmnRemote: IRMNRemote(ZERO_ADDRESS), tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -208,19 +221,18 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroChainSelectorNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: 0, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -229,19 +241,18 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: ZERO_ADDRESS, nonceManager: address(s_inboundNonceManager) }), - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -250,49 +261,46 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: ZERO_ADDRESS }), - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } } -contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { +contract OffRamp_setDynamicConfig is OffRampSetup { function test_SetDynamicConfig_Success() public { - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.DynamicConfigSet(dynamicConfig); + emit OffRamp.DynamicConfigSet(dynamicConfig); s_offRamp.setDynamicConfig(dynamicConfig); - EVM2EVMMultiOffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); + OffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); _assertSameConfig(dynamicConfig, newConfig); } - function test_SetDynamicConfigWithValidator_Success() public { - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); - dynamicConfig.messageValidator = address(s_inboundMessageValidator); + function test_SetDynamicConfigWithInterceptor_Success() public { + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); + dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.DynamicConfigSet(dynamicConfig); + emit OffRamp.DynamicConfigSet(dynamicConfig); s_offRamp.setDynamicConfig(dynamicConfig); - EVM2EVMMultiOffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); + OffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); _assertSameConfig(dynamicConfig, newConfig); } @@ -300,33 +308,23 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { function test_NonOwner_Revert() public { vm.startPrank(STRANGER); - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); vm.expectRevert("Only callable by owner"); s_offRamp.setDynamicConfig(dynamicConfig); } - function test_RouterZeroAddress_Revert() public { - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - _generateDynamicMultiOffRampConfig(ZERO_ADDRESS, address(s_priceRegistry)); + function test_FeeQuoterZeroAddress_Revert() public { + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(ZERO_ADDRESS); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp.setDynamicConfig(dynamicConfig); - } - - function test_PriceRegistryZeroAddress_Revert() public { - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = _generateDynamicMultiOffRampConfig(USER_3, ZERO_ADDRESS); - - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); s_offRamp.setDynamicConfig(dynamicConfig); } } -contract EVM2EVMMultiOffRamp_ccipReceive is EVM2EVMMultiOffRampSetup { +contract OffRamp_ccipReceive is OffRampSetup { // Reverts function test_Reverts() public { @@ -337,7 +335,7 @@ contract EVM2EVMMultiOffRamp_ccipReceive is EVM2EVMMultiOffRampSetup { } } -contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { +contract OffRamp_executeSingleReport is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -348,32 +346,37 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { function test_SingleMessageNoTokens_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - messages[0].header.nonce++; messages[0].header.sequenceNumber++; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } @@ -381,20 +384,23 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + // Nonce never increments on unordered messages. + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - // Nonce never increments on unordered messages. - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertEq( s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore, @@ -402,20 +408,22 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { ); messages[0].header.sequenceNumber++; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + // Nonce never increments on unordered messages. + nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - // Nonce never increments on unordered messages. - nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertEq( s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore, @@ -427,7 +435,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messagesChain1 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesChain1), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesChain1), new OffRamp.GasLimitOverride[](0) ); uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender); @@ -438,7 +446,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new OffRamp.GasLimitOverride[](0) ); assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); @@ -456,22 +464,25 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_reverting_receiver.setErr(realError1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + // Nonce should increment on non-strict + assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ReceiverError.selector, + OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) ) ); - // Nonce should increment on non-strict - assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertEq(uint64(1), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); } @@ -480,14 +491,16 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce++; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit NonceManager.SkippedIncorrectNonce( messages[0].header.sourceChainSelector, messages[0].header.nonce, messages[0].sender ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } function test_SkippedIncorrectNonceStillExecutes_Success() public { @@ -495,65 +508,75 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[1].header.nonce++; - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - SOURCE_CHAIN_SELECTOR_1, + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); - - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } function test__execute_SkippedAlreadyExecutedMessage_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].header.sourceChainSelector, + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].header.sourceChainSelector, + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } // Send a message to a contract that does not implement the CCIPReceiver interface @@ -563,18 +586,20 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); messages[0].receiver = address(newReceiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } function test_SingleMessagesNoTokensSuccess_gas() public { @@ -582,19 +607,19 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.resumeGasMetering(); + vm.recordLogs(); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.resumeGasMetering(); - s_offRamp.executeSingleReport(report, new uint256[](0)); } function test_TwoMessagesWithTokensSuccess_gas() public { @@ -603,30 +628,34 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // Set message 1 to use another receiver to simulate more fair gas costs messages[1].receiver = address(s_secondary_receiver); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.resumeGasMetering(); + vm.recordLogs(); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.resumeGasMetering(); - s_offRamp.executeSingleReport(report, new uint256[](0)); } function test_TwoMessagesWithTokensAndGE_Success() public { @@ -634,34 +663,41 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // Set message 1 to use another receiver to simulate more fair gas costs messages[1].receiver = address(s_secondary_receiver); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) + ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) - ); assertEq(uint64(2), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); } - function test_Fuzz_InterleavingOrderedAndUnorderedMessages_Success(bool[7] memory orderings) public { + function test_Fuzz_InterleavingOrderedAndUnorderedMessages_Success( + bool[7] memory orderings + ) public { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](orderings.length); // number of tokens needs to be capped otherwise we hit UnsupportedNumberOfTokens. Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](3); @@ -670,22 +706,14 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { tokenAmounts[i].amount = 1e18; } uint64 expectedNonce = 0; + for (uint256 i = 0; i < orderings.length; ++i) { messages[i] = _generateAny2EVMMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, uint64(i + 1), tokenAmounts, !orderings[i]); if (orderings[i]) { messages[i].header.nonce = ++expectedNonce; } - messages[i].header.messageId = Internal._hash(messages[i], ON_RAMP_ADDRESS_1); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - SOURCE_CHAIN_SELECTOR_1, - messages[i].header.sequenceNumber, - messages[i].header.messageId, - Internal.MessageExecutionState.SUCCESS, - "" - ); + messages[i].header.messageId = _hashMessage(messages[i], ON_RAMP_ADDRESS_1); } uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)); @@ -693,12 +721,25 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_offRamp.executeSingleReport( _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + // all executions should succeed. for (uint256 i = 0; i < orderings.length; ++i) { assertEq( uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber)), uint256(Internal.MessageExecutionState.SUCCESS) ); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[i].header.sequenceNumber, + messages[i].header.messageId, + _hashMessage(messages[i], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); } assertEq( nonceBefore + expectedNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)) @@ -712,136 +753,127 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].tokenAmounts[0].sourcePoolAddress = abi.encode(fakePoolAddress); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.TokenHandlingError.selector, + OffRamp.TokenHandlingError.selector, abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, abi.encode(fakePoolAddress)) ) ); - - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } function test_WithCurseOnAnotherSourceChain_Success() public { - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_2, true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_2, true); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); } - // Reverts + function test_Unhealthy_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); - function test_MismatchingDestChainSelector_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; - - Internal.ExecutionReportSingleChain memory executionReport = - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.InvalidMessageDestChainSelector.selector, messages[0].header.destChainSelector - ) - ); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); - } - - function test_MismatchingOnRampRoot_Revert() public { - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport( - // Root against mismatching on ramp - Internal._hash(messages[0], ON_RAMP_ADDRESS_3) - ); - _commit(commitReport, s_latestSequenceNumber); - - Internal.ExecutionReportSingleChain memory executionReport = - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); - } - - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_1)); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); - // Uncurse should succeed - s_mockRMN.setGlobalCursed(false); + + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); + vm.recordLogs(); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) + ); + + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + + // Reverts + + function test_MismatchingDestChainSelector_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); + messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; + + Internal.ExecutionReport memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.expectRevert( + abi.encodeWithSelector(OffRamp.InvalidMessageDestChainSelector.selector, messages[0].header.destChainSelector) ); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); } function test_UnhealthySingleChainCurse_Revert() public { - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, true); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_1)); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); + vm.recordLogs(); // Uncurse should succeed - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, false); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); + _assertNoEmit(OffRamp.SkippedReportExecution.selector); } function test_UnexpectedTokenData_Revert() public { - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages( + Internal.ExecutionReport memory report = _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ); report.offchainTokenData = new bytes[][](report.messages.length + 1); - vm.expectRevert(EVM2EVMMultiOffRamp.UnexpectedTokenData.selector); + vm.expectRevert(OffRamp.UnexpectedTokenData.selector); - s_offRamp.executeSingleReport(report, new uint256[](0)); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } function test_EmptyReport_Revert() public { - vm.expectRevert(EVM2EVMMultiOffRamp.EmptyReport.selector); + vm.expectRevert(abi.encodeWithSelector(OffRamp.EmptyReport.selector, SOURCE_CHAIN_SELECTOR_1)); + s_offRamp.executeSingleReport( - Internal.ExecutionReportSingleChain({ + Internal.ExecutionReport({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, proofs: new bytes32[](0), proofFlagBits: 0, messages: new Internal.Any2EVMRampMessage[](0), offchainTokenData: new bytes[][](0) }), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); } function test_RootNotCommitted_Revert() public { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -853,9 +885,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { function test_ManualExecutionNotYetEnabled_Revert() public { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, BLOCK_TIME); - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1) - ); + vm.expectRevert(abi.encodeWithSelector(OffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1)); Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -870,31 +900,35 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(newSourceChainSelector, newOnRamp); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.SourceChainNotEnabled.selector, newSourceChainSelector)); - s_offRamp.executeSingleReport(_generateReportFromMessages(newSourceChainSelector, messages), new uint256[](0)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, newSourceChainSelector)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(newSourceChainSelector, messages), new OffRamp.GasLimitOverride[](0) + ); } function test_DisabledSourceChain_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.SourceChainNotEnabled.selector, SOURCE_CHAIN_SELECTOR_2)); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, SOURCE_CHAIN_SELECTOR_2)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new OffRamp.GasLimitOverride[](0) + ); } function test_TokenDataMismatch_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); report.offchainTokenData[0] = new bytes[](messages[0].tokenAmounts.length + 1); vm.expectRevert( abi.encodeWithSelector( - EVM2EVMMultiOffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber + OffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber ) ); - s_offRamp.executeSingleReport(report, new uint256[](0)); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } function test_RouterYULCall_Revert() public { @@ -904,20 +938,20 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { // gas limit too high, Router's external call should revert messages[0].gasLimit = 1e36; messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain memory executionReport = - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) ); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); } function test_RetryFailedMessageWithoutManualExecution_Revert() public { @@ -930,45 +964,55 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_reverting_receiver.setErr(realError1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ReceiverError.selector, + OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) ) ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.AlreadyAttempted.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber - ) + // The second time should skip the msg + vm.expectEmit(); + emit OffRamp.AlreadyAttempted(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } - function _constructCommitReport(bytes32 merkleRoot) internal view returns (EVM2EVMMultiOffRamp.CommitReport memory) { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + function _constructCommitReport( + bytes32 merkleRoot + ) internal view returns (OffRamp.CommitReport memory) { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + minSeqNr: 1, + maxSeqNr: 2, merkleRoot: merkleRoot }); - return EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots + return OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); } } -contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { +contract OffRamp_executeSingleMessage is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -978,7 +1022,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { function test_executeSingleMessage_NoTokens_Success() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_executeSingleMessage_WithTokens_Success() public { @@ -994,7 +1038,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { originalSender: message.sender, receiver: message.receiver, amount: message.tokenAmounts[0].amount, - localToken: abi.decode(message.tokenAmounts[0].destTokenAddress, (address)), + localToken: message.tokenAmounts[0].destTokenAddress, remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, sourcePoolAddress: message.tokenAmounts[0].sourcePoolAddress, sourcePoolData: message.tokenAmounts[0].extraData, @@ -1003,24 +1047,24 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { ) ); - s_offRamp.executeSingleMessage(message, offchainTokenData); + s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); } - function test_executeSingleMessage_WithValidation_Success() public { + function test_executeSingleMessage_WithVInterception_Success() public { vm.stopPrank(); vm.startPrank(OWNER); - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_NonContract_Success() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_NonContractWithTokens_Success() public { @@ -1034,7 +1078,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } // Reverts @@ -1050,9 +1094,9 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, errorMessage)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage)); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_ZeroGasDONExecution_Revert() public { @@ -1060,40 +1104,40 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.gasLimit = 0; - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.ReceiverError.selector, "")); + vm.expectRevert(abi.encodeWithSelector(OffRamp.ReceiverError.selector, "")); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_MessageSender_Revert() public { vm.stopPrank(); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - vm.expectRevert(EVM2EVMMultiOffRamp.CanOnlySelfCall.selector); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + vm.expectRevert(OffRamp.CanOnlySelfCall.selector); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_executeSingleMessage_WithFailingValidation_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_inboundMessageValidator.setMessageIdValidationState(message.header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) ) ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = @@ -1102,20 +1146,20 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { // Setup the receiver to a non-CCIP Receiver, which will skip the Router call (but should still perform the validation) MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); message.receiver = address(newReceiver); - message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); - s_inboundMessageValidator.setMessageIdValidationState(message.header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) ) ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } } -contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { +contract OffRamp_batchExecute is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -1126,18 +1170,22 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { function test_SingleReport_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); - assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } @@ -1149,39 +1197,45 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); + vm.recordLogs(); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); - s_offRamp.batchExecute(reports, new uint256[][](2)); assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender), nonceBefore); } @@ -1193,39 +1247,46 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.batchExecute(reports, new uint256[][](2)); - uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); uint64 nonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messages2[0].sender); @@ -1234,52 +1295,96 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { assertGt(nonceChain3, 0); } + function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + vm.recordLogs(); + + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState,,) = abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + assertEq(logMessageId, messages2[0].header.messageId); + assertEq(logSourceChainSelector, messages2[0].header.sourceChainSelector); + assertEq(logSequenceNumber, messages2[0].header.sequenceNumber); + assertEq(logMessageId, messages2[0].header.messageId); + assertEq(logMessageHash, _hashMessage(messages2[0], ON_RAMP_ADDRESS_3)); + assertEq(logState, uint8(Internal.MessageExecutionState.SUCCESS)); + } + } + } + function test_MultipleReportsSkipDuplicate_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + + vm.recordLogs(); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - - s_offRamp.batchExecute(reports, new uint256[][](2)); - } - - // Reverts - function test_ZeroReports_Revert() public { - vm.expectRevert(EVM2EVMMultiOffRamp.EmptyReport.selector); - s_offRamp.batchExecute(new Internal.ExecutionReportSingleChain[](0), new uint256[][](1)); } - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_1)); + function test_Unhealthy_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.batchExecute( _generateBatchReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[][](1) + new OffRamp.GasLimitOverride[][](1) ); - // Uncurse should succeed - s_mockRMN.setGlobalCursed(false); + + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); + + vm.recordLogs(); s_offRamp.batchExecute( _generateBatchReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[][](1) + new OffRamp.GasLimitOverride[][](1) ); + + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + + // Reverts + function test_ZeroReports_Revert() public { + vm.expectRevert(OffRamp.EmptyBatch.selector); + s_offRamp.batchExecute(new Internal.ExecutionReport[](0), new OffRamp.GasLimitOverride[][](1)); } function test_OutOfBoundsGasLimitsAccess_Revert() public { @@ -1290,16 +1395,16 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); vm.expectRevert(); - s_offRamp.batchExecute(reports, new uint256[][](1)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](1)); } } -contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { +contract OffRamp_manuallyExecute is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -1312,55 +1417,59 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); s_reverting_receiver.setRevert(false); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](messages.length); + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - uint256[][] memory gasLimitOverrides = new uint256[][](1); - gasLimitOverrides[0] = new uint256[](messages.length); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } function test_manuallyExecute_WithGasOverride_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); s_reverting_receiver.setRevert(false); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - uint256[][] memory gasLimitOverrides = new uint256[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0] += 1; - - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); assertEq( messages[0].header.nonce - 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) @@ -1368,23 +1477,22 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { s_reverting_receiver.setRevert(true); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") + OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") ) ); - uint256[][] memory gasLimitOverrides = new uint256[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertEq( messages[0].header.nonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) ); @@ -1397,54 +1505,63 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { for (uint64 i = 0; i < 3; ++i) { messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); messages1[i].receiver = address(s_reverting_receiver); - messages1[i].header.messageId = Internal._hash(messages1[i], ON_RAMP_ADDRESS_1); + messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); } for (uint64 i = 0; i < 2; ++i) { messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); messages2[i].receiver = address(s_reverting_receiver); - messages2[i].header.messageId = Internal._hash(messages2[i], ON_RAMP_ADDRESS_3); + messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); } - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - s_offRamp.batchExecute(reports, new uint256[][](2)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); s_reverting_receiver.setRevert(false); - uint256[][] memory gasLimitOverrides = new uint256[][](2); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); for (uint256 i = 0; i < 3; ++i) { - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + gasLimitOverrides[0][i].receiverExecutionGasLimit += 1; + } + + for (uint256 i = 0; i < 2; ++i) { + gasLimitOverrides[1][i].receiverExecutionGasLimit += 1; + } + + vm.recordLogs(); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 j = 0; j < 3; ++j) { + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, - messages1[i].header.sequenceNumber, - messages1[i].header.messageId, + messages1[j].header.sequenceNumber, + messages1[j].header.messageId, + _hashMessage(messages1[j], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - gasLimitOverrides[0][i] += 1; } - for (uint256 i = 0; i < 2; ++i) { - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + for (uint256 k = 0; k < 2; ++k) { + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_3, - messages2[i].header.sequenceNumber, - messages2[i].header.messageId, + messages2[k].header.sequenceNumber, + messages2[k].header.messageId, + _hashMessage(messages2[k], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); - - gasLimitOverrides[1][i] += 1; } - - s_offRamp.manuallyExecute(reports, gasLimitOverrides); } function test_manuallyExecute_WithPartialMessages_Success() public { @@ -1453,61 +1570,70 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { for (uint64 i = 0; i < 3; ++i) { messages[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); } + messages[1].receiver = address(s_reverting_receiver); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ReceiverError.selector, + OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) ) ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[2].header.sequenceNumber, messages[2].header.messageId, + _hashMessage(messages[2], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); - s_reverting_receiver.setRevert(false); // Only the 2nd message reverted Internal.Any2EVMRampMessage[] memory newMessages = new Internal.Any2EVMRampMessage[](1); newMessages[0] = messages[1]; - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(newMessages); - gasLimitOverrides[0][0] += 1; + gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, newMessages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, - newMessages[0].header.sequenceNumber, - newMessages[0].header.messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, newMessages), gasLimitOverrides); } function test_manuallyExecute_LowGasLimit_Success() public { @@ -1515,34 +1641,38 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].gasLimit = 1; messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector(EVM2EVMMultiOffRamp.ReceiverError.selector, "") + abi.encodeWithSelector(OffRamp.ReceiverError.selector, "") ); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); - uint256[][] memory gasLimitOverrides = new uint256[][](1); - gasLimitOverrides[0] = new uint256[](1); - gasLimitOverrides[0][0] = 100_000; + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); + gasLimitOverrides[0][0].receiverExecutionGasLimit = 100_000; vm.expectEmit(); emit ConformingReceiver.MessageReceived(); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } // Reverts @@ -1551,14 +1681,13 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); uint256 chain1 = block.chainid; uint256 chain2 = chain1 + 1; vm.chainId(chain2); vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); s_offRamp.manuallyExecute(reports, gasLimitOverrides); @@ -1569,29 +1698,28 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); // No overrides for report - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new uint256[][](0)); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); // No messages - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1 message missing - gasLimitOverrides[0] = new uint256[](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1 message in excess - gasLimitOverrides[0] = new uint256[](3); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); } @@ -1603,52 +1731,104 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new uint256[][](0)); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new uint256[][](1)); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](1)); - uint256[][] memory gasLimitOverrides = new uint256[][](2); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 2nd report empty - gasLimitOverrides[0] = new uint256[](2); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](2); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1st report empty - gasLimitOverrides[0] = new uint256[](0); - gasLimitOverrides[1] = new uint256[](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](0); + gasLimitOverrides[1] = new OffRamp.GasLimitOverride[](1); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1st report oversized - gasLimitOverrides[0] = new uint256[](3); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); - vm.expectRevert(EVM2EVMMultiOffRamp.ManualExecutionGasLimitMismatch.selector); + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_ManualExecInvalidGasLimit_Revert() public { + function test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0]--; + gasLimitOverrides[0][0].receiverExecutionGasLimit--; vm.expectRevert( abi.encodeWithSelector( - EVM2EVMMultiOffRamp.InvalidManualExecutionGasLimit.selector, SOURCE_CHAIN_SELECTOR_1, 0, gasLimitOverrides[0][0] + OffRamp.InvalidManualExecutionGasLimit.selector, + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.messageId, + gasLimitOverrides[0][0].receiverExecutionGasLimit + ) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + // empty tokenGasOverride array provided + vm.expectRevert( + abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + + //trying with excesss elements tokenGasOverride array provided + gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](3); + vm.expectRevert( + abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_InvalidTokenGasOverride_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + uint32[] memory tokenGasOverrides = new uint32[](2); + tokenGasOverrides[0] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD; + tokenGasOverrides[1] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD - 1; //invalid token gas override value + gasLimitOverrides[0][0].tokenGasOverrides = tokenGasOverrides; + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidManualExecutionTokenGasOverride.selector, + messages[0].header.messageId, + 1, + DEFAULT_TOKEN_DEST_GAS_OVERHEAD, + tokenGasOverrides[1] ) ); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); @@ -1659,21 +1839,23 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); s_reverting_receiver.setRevert(true); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); vm.expectRevert( abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ExecutionError.selector, + OffRamp.ExecutionError.selector, messages[0].header.messageId, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ReceiverError.selector, + OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) ) ) @@ -1681,7 +1863,7 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_manuallyExecute_ReentrancyFails() public { + function test_manuallyExecute_ReentrancyFails_Success() public { uint256 tokenAmount = 1e9; IERC20 tokenToAbuse = IERC20(s_destFeeToken); @@ -1695,53 +1877,105 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { // send the message that they want to replay. Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].tokenAmounts = new Internal.RampTokenAmount[](1); - messages[0].tokenAmounts[0] = Internal.RampTokenAmount({ + messages[0].tokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + messages[0].tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), + destTokenAddress: s_destTokenBySourceToken[s_sourceFeeToken], extraData: "", - amount: tokenAmount + amount: tokenAmount, + destGasAmount: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS }); messages[0].receiver = address(receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); // sets the report to be repeated on the ReentrancyAbuser to be able to replay receiver.setPayload(report); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](messages[0].tokenAmounts.length); - // The first entry should be fine and triggers the second entry. This one fails - // but since it's an inner tx of the first one it is caught in the try-catch. - // This means the first tx is marked `FAILURE` with the error message of the second tx. + // The first entry should be fine and triggers the second entry which is skipped. Due to the reentrancy + // the second completes first, so we expect the skip event before the success event. vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.ReceiverError.selector, - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.AlreadyExecuted.selector, - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber - ) - ) + emit OffRamp.SkippedAlreadyExecutedMessage( + messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber ); + vm.recordLogs(); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); // Since the tx failed we don't release the tokens - assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre); + assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre + tokenAmount); + } + + function test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); + + for (uint64 i = 0; i < 3; ++i) { + messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); + messages1[i].receiver = address(s_reverting_receiver); + messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); + } + + for (uint64 i = 0; i < 2; ++i) { + messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); + messages2[i].receiver = address(s_reverting_receiver); + messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); + } + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_3, true); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_3)); + + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } + + function test_manuallyExecute_SourceChainSelectorMismatch_Revert() 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); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.SourceChainSelectorMismatch.selector, SOURCE_CHAIN_SELECTOR_3, SOURCE_CHAIN_SELECTOR_1 + ) + ); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); } } -contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { +contract OffRamp_execute is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -1752,24 +1986,25 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { function test_SingleReport_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + + _execute(reports); + + assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - _execute(reports); } function test_MultipleReports_Success() public { @@ -1780,47 +2015,53 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - _execute(reports); } function test_LargeBatch_Success() public { - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](10); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](10); for (uint64 i = 0; i < reports.length; ++i) { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1 + i * 3); @@ -1830,29 +2071,33 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { reports[i] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); } + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + for (uint64 i = 0; i < reports.length; ++i) { for (uint64 j = 0; j < reports[i].messages.length; ++j) { - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, reports[i].messages[j].header.sourceChainSelector, reports[i].messages[j].header.sequenceNumber, reports[i].messages[j].header.messageId, + _hashMessage(reports[i].messages[j], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); } } - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - _execute(reports); } function test_MultipleReportsWithPartialValidationFailures_Success() public { - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -1861,18 +2106,29 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + + s_inboundMessageInterceptor.setMessageIdValidationState(messages1[0].header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(messages2[0].header.messageId, true); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + _execute(reports); - s_inboundMessageValidator.setMessageIdValidationState(messages1[0].header.messageId, true); - s_inboundMessageValidator.setMessageIdValidationState(messages2[0].header.messageId, true); + Vm.Log[] memory logs = vm.getRecordedLogs(); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1880,33 +2136,28 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { ) ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( + assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) ) ); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - _execute(reports); } // Reverts @@ -1916,8 +2167,7 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); s_offRamp.execute(reportContext, abi.encode(reports)); @@ -1929,8 +2179,7 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; @@ -1948,16 +2197,15 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { ocrPluginType: uint8(Internal.OCRPluginType.Commit), configDigest: s_configDigestCommit, F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, + isSignatureVerificationEnabled: true, + signers: s_validSigners, transmitters: s_validTransmitters }); s_offRamp.setOCR3Configs(ocrConfigs); Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; @@ -1985,24 +2233,23 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.expectRevert(); _execute(reports); } function test_ZeroReports_Revert() public { - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](0); + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](0); - vm.expectRevert(EVM2EVMMultiOffRamp.EmptyReport.selector); + vm.expectRevert(OffRamp.EmptyBatch.selector); _execute(reports); } function test_IncorrectArrayType_Revert() public { bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - uint256[] memory wrongData = new uint256[](1); + uint256[] memory wrongData = new uint256[](2); wrongData[0] = 1; vm.startPrank(s_validTransmitters[0]); @@ -2015,7 +2262,7 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.startPrank(s_validTransmitters[0]); vm.expectRevert(); @@ -2023,7 +2270,7 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { } } -contract EVM2EVMMultiOffRamp_getExecutionState is EVM2EVMMultiOffRampSetup { +contract OffRamp_getExecutionState is OffRampSetup { mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => Internal.MessageExecutionState state)) internal s_differentialExecutionState; @@ -2175,7 +2422,7 @@ contract EVM2EVMMultiOffRamp_getExecutionState is EVM2EVMMultiOffRampSetup { } } -contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { +contract OffRamp_trialExecute is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -2192,7 +2439,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { uint256 startingBalance = dstToken0.balanceOf(message.receiver); (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); assertEq("", err); @@ -2215,9 +2462,9 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, errorMessage), err); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); // Expect the balance to remain the same assertEq(startingBalance, dstToken0.balanceOf(OWNER)); @@ -2235,9 +2482,9 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, errorMessage), err); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); } // TODO test actual pool exists but isn't compatible instead of just no pool @@ -2249,7 +2496,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { // Happy path, pool is correct (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); assertEq("", err); @@ -2257,40 +2504,42 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { // address 0 has no contract assertEq(address(0).code.length, 0); - message.tokenAmounts[0] = Internal.RampTokenAmount({ + message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(address(0)), + destTokenAddress: address(0), extraData: "", - amount: message.tokenAmounts[0].amount + amount: message.tokenAmounts[0].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); - message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); // Unhappy path, no revert but marked as failed. - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(address(0))), err); + assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); address notAContract = makeAddr("not_a_contract"); - message.tokenAmounts[0] = Internal.RampTokenAmount({ + message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(notAContract), + destTokenAddress: notAContract, extraData: "", - amount: message.tokenAmounts[0].amount + amount: message.tokenAmounts[0].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); - message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, address(0)), err); + assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); } } -contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSetup { +contract OffRamp_releaseOrMintSingleToken is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -2305,11 +2554,12 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); uint256 startingBalance = dstToken1.balanceOf(OWNER); - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", - amount: amount + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); vm.expectCall( @@ -2334,6 +2584,105 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); } + function test_releaseOrMintToken_InvalidDataLength_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + // Mock the call so returns 2 slots of data + vm.mockCall( + s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), abi.encode(0, 0) + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Internal.MAX_BALANCE_OF_RET_BYTES, 64)); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); + } + + function test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + bytes memory revertData = "failed to balanceOf"; + + // Mock the call so returns 2 slots of data + vm.mockCallRevert( + s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); + } + + function test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + uint256 mockedStaticBalance = 50000; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + vm.mockCall( + s_destTokenBySourceToken[token], + abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), + abi.encode(mockedStaticBalance) + ); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.ReleaseOrMintBalanceMismatch.selector, amount, mockedStaticBalance, mockedStaticBalance + ) + ); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); + } + + function test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + uint256 mockedStaticBalance = 50000; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + // This should make the call fail if it does not skip the check + vm.mockCall( + s_destTokenBySourceToken[token], + abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), + abi.encode(mockedStaticBalance) + ); + + s_offRamp.releaseOrMintSingleToken( + tokenAmount, abi.encode(OWNER), s_destPoolBySourceToken[token], SOURCE_CHAIN_SELECTOR, "" + ); + } + function test__releaseOrMintSingleToken_NotACompatiblePool_Revert() public { uint256 amount = 123123; address token = s_sourceTokens[0]; @@ -2342,11 +2691,12 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(destToken), + destTokenAddress: destToken, extraData: "", - amount: amount + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); // Address(0) should always revert @@ -2358,7 +2708,7 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet abi.encode(returnedPool) ); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, returnedPool)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, returnedPool)); s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); @@ -2371,12 +2721,12 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet abi.encode(returnedPool) ); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, returnedPool)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, returnedPool)); s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); } - function test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() public { + function test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() public { address receiver = makeAddr("receiver"); uint256 amount = 123123; address token = s_sourceTokens[0]; @@ -2384,32 +2734,33 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(destToken), + destTokenAddress: destToken, extraData: "", - amount: amount + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); bytes memory revertData = "call reverted :o"; vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, revertData)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); s_offRamp.releaseOrMintSingleToken( tokenAmount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); } } -contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { +contract OffRamp_releaseOrMintTokens is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); } function test_releaseOrMintTokens_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); IERC20 dstToken1 = IERC20(s_destFeeToken); uint256 startingBalance = dstToken1.balanceOf(OWNER); uint256 amount1 = 100; @@ -2418,7 +2769,7 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2438,78 +2789,101 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) ); assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); } - function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - address destToken = s_destFeeToken; - uint256 amount = 100; - uint256 destinationDenominationMultiplier = 1000; - srcTokenAmounts[0].amount = amount; + function test_releaseOrMintTokens_WithGasOverride_Success() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + IERC20 dstToken1 = IERC20(s_destFeeToken); + uint256 startingBalance = dstToken1.balanceOf(OWNER); + uint256 amount1 = 100; + srcTokenAmounts[0].amount = amount1; bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + offchainTokenData[0] = abi.encode(0x12345678); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - - // Since the pool call is mocked, we manually release funds to the offRamp - deal(destToken, address(s_offRamp), amount * destinationDenominationMultiplier); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - vm.mockCall( + vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], abi.encodeWithSelector( LockReleaseTokenPool.releaseOrMint.selector, Pool.ReleaseOrMintInV1({ originalSender: abi.encode(OWNER), receiver: OWNER, - amount: amount, + amount: srcTokenAmounts[0].amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, sourcePoolData: sourceTokenAmounts[0].extraData, offchainTokenData: offchainTokenData[0] }) - ), - abi.encode(amount * destinationDenominationMultiplier) + ) ); - Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + uint32[] memory gasOverrides = new uint32[](sourceTokenAmounts.length); + for (uint256 i = 0; i < gasOverrides.length; i++) { + gasOverrides[i] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; + } + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, gasOverrides ); - assertEq(destTokenAmounts[0].amount, amount * destinationDenominationMultiplier); - assertEq(destTokenAmounts[0].token, destToken); + assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); + } + + function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + uint256 amount = 100; + uint256 destinationDenominationMultiplier = 1000; + srcTokenAmounts[1].amount = amount; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + address pool = s_destPoolBySourceToken[srcTokenAmounts[1].token]; + address destToken = s_destTokenBySourceToken[srcTokenAmounts[1].token]; + + MaybeRevertingBurnMintTokenPool(pool).setReleaseOrMintMultiplier(destinationDenominationMultiplier); + + Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) + ); + assertEq(destTokenAmounts[1].amount, amount * destinationDenominationMultiplier); + assertEq(destTokenAmounts[1].token, destToken); } // Revert function test_TokenHandlingError_Reverts() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); bytes memory unknownError = bytes("unknown error"); s_maybeRevertingPool.setShouldRevert(unknownError); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, unknownError)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, unknownError)); s_offRamp.releaseOrMintTokens( _getDefaultSourceTokenData(srcTokenAmounts), abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, - new bytes[](srcTokenAmounts.length) + new bytes[](srcTokenAmounts.length), + new uint32[](0) ); } function test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() public { uint256 amount = 100; - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); srcTokenAmounts[0].amount = amount; bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.mockCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2530,28 +2904,10 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { abi.encode(amount, amount) ); - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64) - ); - - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData - ); - } - - function test_releaseOrMintTokens_InvalidEVMAddress_Revert() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - bytes memory wrongAddress = abi.encode(address(1000), address(10000), address(10000)); - - sourceTokenAmounts[0].destTokenAddress = wrongAddress; - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, wrongAddress)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64)); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) ); } @@ -2559,27 +2915,30 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); - Internal.RampTokenAmount[] memory sourceTokenAmounts = new Internal.RampTokenAmount[](1); - sourceTokenAmounts[0] = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: abi.encode(s_offRamp), + destTokenAddress: address(s_offRamp), extraData: "", - amount: 1 + amount: 1, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, address(0))); - s_offRamp.releaseOrMintTokens(sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0))); + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) + ); } function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount1 = 100; srcTokenAmounts[0].amount = amount1; bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2599,50 +2958,51 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ); vm.expectRevert(); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData, new uint32[](0) ); } /// forge-config: default.fuzz.runs = 32 /// forge-config: ccip.fuzz.runs = 1024 // Uint256 gives a good range of values to test, both inside and outside of the eth address space. - function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success(uint256 destPool) public { + function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success( + address destPool + ) public { // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C // triggers some Create2Deployer and causes it to fail - vm.assume(destPool != 447301751254033913445893214690834296930546521452); + vm.assume(destPool != 0x4e59b44847b379578588920cA78FbF26c0B4956C); bytes memory unusedVar = abi.encode(makeAddr("unused")); - Internal.RampTokenAmount[] memory sourceTokenAmounts = new Internal.RampTokenAmount[](1); - sourceTokenAmounts[0] = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: unusedVar, - destTokenAddress: abi.encode(destPool), + destTokenAddress: destPool, extraData: unusedVar, - amount: 1 + amount: 1, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); try s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1) + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) ) {} catch (bytes memory reason) { // Any revert should be a TokenHandlingError, InvalidEVMAddress, InvalidDataLength or NoContract as those are caught by the offramp assertTrue( - bytes4(reason) == EVM2EVMMultiOffRamp.TokenHandlingError.selector - || bytes4(reason) == Internal.InvalidEVMAddress.selector - || bytes4(reason) == EVM2EVMMultiOffRamp.InvalidDataLength.selector + bytes4(reason) == OffRamp.TokenHandlingError.selector || bytes4(reason) == Internal.InvalidEVMAddress.selector + || bytes4(reason) == OffRamp.InvalidDataLength.selector || bytes4(reason) == CallWithExactGas.NoContract.selector - || bytes4(reason) == EVM2EVMMultiOffRamp.NotACompatiblePool.selector, + || bytes4(reason) == OffRamp.NotACompatiblePool.selector, "Expected TokenHandlingError or InvalidEVMAddress" ); - if (destPool > type(uint160).max) { + if (uint160(destPool) > type(uint160).max) { assertEq(reason, abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(destPool))); } } } } -contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRampSetup { +contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { function test_ApplyZeroUpdates_Success() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); vm.recordLogs(); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); @@ -2651,26 +3011,26 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 0); - // assertEq(s_offRamp.getSourceChainSelectors().length, 0); + assertEq(s_offRamp.getSourceChainSelectors().length, 0); } function test_AddNewChain_Success() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true }); - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = - EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); + OffRamp.SourceChainConfig memory expectedSourceChainConfig = + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); + emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); @@ -2678,9 +3038,9 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam } function test_ReplaceExistingChain_Success() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true @@ -2689,11 +3049,11 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); sourceChainConfigs[0].isEnabled = false; - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = - EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: false, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); + OffRamp.SourceChainConfig memory expectedSourceChainConfig = + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: false, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); vm.recordLogs(); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); @@ -2704,46 +3064,45 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); - // uint64[] memory resultSourceChainSelectors = s_offRamp.getSourceChainSelectors(); - // assertEq(resultSourceChainSelectors.length, 1); - // assertEq(resultSourceChainSelectors[0], SOURCE_CHAIN_SELECTOR_1); + uint256[] memory resultSourceChainSelectors = s_offRamp.getSourceChainSelectors(); + assertEq(resultSourceChainSelectors.length, 1); } function test_AddMultipleChains_Success() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: abi.encode(ON_RAMP_ADDRESS_1, 0), isEnabled: true }); - sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, onRamp: abi.encode(ON_RAMP_ADDRESS_1, 1), isEnabled: false }); - sourceChainConfigs[2] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 2, onRamp: abi.encode(ON_RAMP_ADDRESS_1, 2), isEnabled: true }); - EVM2EVMMultiOffRamp.SourceChainConfig[] memory expectedSourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfig[](3); + OffRamp.SourceChainConfig[] memory expectedSourceChainConfigs = new OffRamp.SourceChainConfig[](3); for (uint256 i = 0; i < 3; ++i) { - expectedSourceChainConfigs[i] = EVM2EVMMultiOffRamp.SourceChainConfig({ + expectedSourceChainConfigs[i] = OffRamp.SourceChainConfig({ + router: s_destRouter, isEnabled: sourceChainConfigs[i].isEnabled, minSeqNr: 1, onRamp: abi.encode(ON_RAMP_ADDRESS_1, i) }); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(sourceChainConfigs[i].sourceChainSelector); + emit OffRamp.SourceChainSelectorAdded(sourceChainConfigs[i].sourceChainSelector); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainConfigSet( - sourceChainConfigs[i].sourceChainSelector, expectedSourceChainConfigs[i] - ); + emit OffRamp.SourceChainConfigSet(sourceChainConfigs[i].sourceChainSelector, expectedSourceChainConfigs[i]); } s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); @@ -2756,15 +3115,16 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam } function test_Fuzz_applySourceChainConfigUpdate_Success( - EVM2EVMMultiOffRamp.SourceChainConfigArgs memory sourceChainConfigArgs + OffRamp.SourceChainConfigArgs memory sourceChainConfigArgs ) public { // Skip invalid inputs vm.assume(sourceChainConfigArgs.sourceChainSelector != 0); vm.assume(sourceChainConfigArgs.onRamp.length != 0); + vm.assume(address(sourceChainConfigArgs.router) != address(0)); - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](2); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true @@ -2777,7 +3137,8 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam sourceChainConfigs[1].onRamp = sourceChainConfigs[0].onRamp; } - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = EVM2EVMMultiOffRamp.SourceChainConfig({ + OffRamp.SourceChainConfig memory expectedSourceChainConfig = OffRamp.SourceChainConfig({ + router: sourceChainConfigArgs.router, isEnabled: sourceChainConfigArgs.isEnabled, minSeqNr: 1, onRamp: sourceChainConfigArgs.onRamp @@ -2785,11 +3146,11 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam if (isNewChain) { vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(sourceChainConfigArgs.sourceChainSelector); + emit OffRamp.SourceChainSelectorAdded(sourceChainConfigArgs.sourceChainSelector); } vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SourceChainConfigSet(sourceChainConfigArgs.sourceChainSelector, expectedSourceChainConfig); + emit OffRamp.SourceChainConfigSet(sourceChainConfigArgs.sourceChainSelector, expectedSourceChainConfig); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); @@ -2798,35 +3159,76 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam ); } + function test_ReplaceExistingChainOnRamp_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet( + SOURCE_CHAIN_SELECTOR_1, + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_2}) + ); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + // Reverts function test_ZeroOnRampAddress_Revert() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: new bytes(0), isEnabled: true }); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].onRamp = abi.encode(address(0)); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + + function test_RouterAddress_Revert() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: IRouter(address(0)), + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } function test_ZeroSourceChainSelector_Revert() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = - EVM2EVMMultiOffRamp.SourceChainConfigArgs({sourceChainSelector: 0, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true}); + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: 0, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); - vm.expectRevert(EVM2EVMMultiOffRamp.ZeroChainSelectorNotAllowed.selector); + vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_ReplaceExistingChainOnRamp_Revert() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + function test_InvalidOnRampUpdate_Revert() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true @@ -2834,14 +3236,36 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "test #2" + }); + + _commit( + OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }), + s_latestSequenceNumber + ); + + vm.stopPrank(); + vm.startPrank(OWNER); + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidStaticConfig.selector, SOURCE_CHAIN_SELECTOR_1)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidOnRampUpdate.selector, SOURCE_CHAIN_SELECTOR_1)); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } } -contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { +contract OffRamp_commit is OffRampSetup { uint64 internal s_maxInterval = 12; function setUp() public virtual override { @@ -2852,10 +3276,10 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { } function test_ReportAndPriceUpdate_Success() public { - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + OffRamp.CommitReport memory commitReport = _constructCommitReport(); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -2870,18 +3294,24 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { uint64 max1 = 931; bytes32 root = "Only a single root"; - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, max1), + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: max1, merkleRoot: root }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -2895,20 +3325,25 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { function test_StaleReportWithRoot_Success() public { uint64 maxSeq = 12; - uint224 tokenStartPrice = - IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value; + uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, maxSeq), + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: maxSeq, merkleRoot: "stale report 1" }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -2918,11 +3353,12 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - commitReport.merkleRoots[0].interval = EVM2EVMMultiOffRamp.Interval(maxSeq + 1, maxSeq * 2); + commitReport.merkleRoots[0].minSeqNr = maxSeq + 1; + commitReport.merkleRoots[0].maxSeqNr = maxSeq * 2; commitReport.merkleRoots[0].merkleRoot = "stale report 2"; vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -2931,20 +3367,23 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { assertEq(maxSeq * 2 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - assertEq( - tokenStartPrice, IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value - ); + assertEq(tokenStartPrice, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); } function test_OnlyTokenPriceUpdates_Success() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -2955,14 +3394,19 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { } function test_OnlyGasPriceUpdates_Success() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -2972,14 +3416,16 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { } function test_PriceSequenceNumberCleared_Success() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); _commit(commitReport, s_latestSequenceNumber); assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); @@ -3014,7 +3460,7 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { // The same sequence number can be reported again vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); _commit(commitReport, s_latestSequenceNumber); } @@ -3023,14 +3469,16 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { uint64 maxSeq = 12; uint224 tokenPrice1 = 4e18; uint224 tokenPrice2 = 5e18; - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), - merkleRoots: roots + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3038,17 +3486,19 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { _commit(commitReport, s_latestSequenceNumber); assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, maxSeq), + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: maxSeq, merkleRoot: "stale report" }); - commitReport.priceUpdates = getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); + commitReport.priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); commitReport.merkleRoots = roots; vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3056,16 +3506,14 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { _commit(commitReport, s_latestSequenceNumber); assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq( - tokenPrice1, IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value - ); + assertEq(tokenPrice1, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } // Reverts function test_UnauthorizedTransmitter_Revert() public { - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + OffRamp.CommitReport memory commitReport = _constructCommitReport(); bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber)), s_configDigestCommit]; @@ -3080,7 +3528,7 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { function test_NoConfig_Revert() public { _redeployOffRampWithNoOCRConfigs(); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + OffRamp.CommitReport memory commitReport = _constructCommitReport(); bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -3105,7 +3553,7 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { }); s_offRamp.setOCR3Configs(ocrConfigs); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + OffRamp.CommitReport memory commitReport = _constructCommitReport(); bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -3116,314 +3564,235 @@ contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_WrongConfigWithoutSigners_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); + function test_FailedRMNVerification_Reverts() public { + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + OffRamp.CommitReport memory commitReport = _constructCommitReport(); vm.expectRevert(); _commit(commitReport, s_latestSequenceNumber); } function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), - merkleRoot: "Only a single root" + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); _commit(commitReport, s_latestSequenceNumber); } function test_InvalidRootRevert() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, 4), + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 4, merkleRoot: bytes32(0) }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); - vm.expectRevert(EVM2EVMMultiOffRamp.InvalidRoot.selector); + vm.expectRevert(OffRamp.InvalidRoot.selector); _commit(commitReport, s_latestSequenceNumber); } function test_InvalidInterval_Revert() public { - EVM2EVMMultiOffRamp.Interval memory interval = EVM2EVMMultiOffRamp.Interval(2, 2); - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: interval, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 2, + maxSeqNr: 2, merkleRoot: bytes32(0) }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, interval) + abi.encodeWithSelector( + OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr + ) ); _commit(commitReport, s_latestSequenceNumber); } function test_InvalidIntervalMinLargerThanMax_Revert() public { s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR); - EVM2EVMMultiOffRamp.Interval memory interval = EVM2EVMMultiOffRamp.Interval(1, 0); - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: interval, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 0, merkleRoot: bytes32(0) }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, interval) + abi.encodeWithSelector( + OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr + ) ); _commit(commitReport, s_latestSequenceNumber); } function test_ZeroEpochAndRound_Revert() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); - vm.expectRevert(EVM2EVMMultiOffRamp.StaleCommitReport.selector); + vm.expectRevert(OffRamp.StaleCommitReport.selector); _commit(commitReport, 0); } function test_OnlyPriceUpdateStaleReport_Revert() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); _commit(commitReport, s_latestSequenceNumber); - vm.expectRevert(EVM2EVMMultiOffRamp.StaleCommitReport.selector); + vm.expectRevert(OffRamp.StaleCommitReport.selector); _commit(commitReport, s_latestSequenceNumber); } function test_SourceChainNotEnabled_Revert() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: 0, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + minSeqNr: 1, + maxSeqNr: 2, merkleRoot: "Only a single root" }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.SourceChainNotEnabled.selector, 0)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, 0)); _commit(commitReport, s_latestSequenceNumber); } function test_RootAlreadyCommitted_Revert() public { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 2, merkleRoot: "Only a single root" }); - EVM2EVMMultiOffRamp.CommitReport memory commitReport = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); _commit(commitReport, s_latestSequenceNumber); - commitReport.merkleRoots[0].interval = EVM2EVMMultiOffRamp.Interval(3, 3); + commitReport.merkleRoots[0].minSeqNr = 3; + commitReport.merkleRoots[0].maxSeqNr = 3; vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.RootAlreadyCommitted.selector, roots[0].sourceChainSelector, roots[0].merkleRoot - ) + abi.encodeWithSelector(OffRamp.RootAlreadyCommitted.selector, roots[0].sourceChainSelector, roots[0].merkleRoot) ); _commit(commitReport, ++s_latestSequenceNumber); } - function _constructCommitReport() internal view returns (EVM2EVMMultiOffRamp.CommitReport memory) { - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, s_maxInterval), - merkleRoot: "test #2" - }); + function test_CommitOnRampMismatch_Revert() public { + OffRamp.CommitReport memory commitReport = _constructCommitReport(); - return EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots - }); - } -} + commitReport.merkleRoots[0].onRampAddress = ON_RAMP_ADDRESS_2; -contract EVM2EVMMultiOffRamp_resetUnblessedRoots is EVM2EVMMultiOffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupRealRMN(); - _deployOffRamp(s_destRouter, s_realRMN, s_inboundNonceManager); - _setupMultipleOffRamps(); + vm.expectRevert(abi.encodeWithSelector(OffRamp.CommitOnRampMismatch.selector, ON_RAMP_ADDRESS_2, ON_RAMP_ADDRESS_1)); + _commit(commitReport, s_latestSequenceNumber); } - function test_ResetUnblessedRoots_Success() public { - EVM2EVMMultiOffRamp.UnblessedRoot[] memory rootsToReset = new EVM2EVMMultiOffRamp.UnblessedRoot[](3); - rootsToReset[0] = EVM2EVMMultiOffRamp.UnblessedRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR, merkleRoot: "1"}); - rootsToReset[1] = EVM2EVMMultiOffRamp.UnblessedRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR, merkleRoot: "2"}); - rootsToReset[2] = EVM2EVMMultiOffRamp.UnblessedRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR, merkleRoot: "3"}); - - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](3); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), - merkleRoot: rootsToReset[0].merkleRoot - }); - roots[1] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(3, 4), - merkleRoot: rootsToReset[1].merkleRoot - }); - roots[2] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(5, 5), - merkleRoot: rootsToReset[2].merkleRoot + function _constructCommitReport() internal view returns (OffRamp.CommitReport memory) { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: s_maxInterval, + merkleRoot: "test #2" }); - EVM2EVMMultiOffRamp.CommitReport memory report = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - - _commit(report, ++s_latestSequenceNumber); - - IRMN.TaggedRoot[] memory blessedTaggedRoots = new IRMN.TaggedRoot[](1); - blessedTaggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: rootsToReset[1].merkleRoot}); - - vm.startPrank(BLESS_VOTE_ADDR); - s_realRMN.voteToBless(blessedTaggedRoots); - - vm.expectEmit(false, false, false, true); - emit EVM2EVMMultiOffRamp.RootRemoved(rootsToReset[0].merkleRoot); - - vm.expectEmit(false, false, false, true); - emit EVM2EVMMultiOffRamp.RootRemoved(rootsToReset[2].merkleRoot); - - vm.startPrank(OWNER); - s_offRamp.resetUnblessedRoots(rootsToReset); - - assertEq(0, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR, rootsToReset[0].merkleRoot)); - assertEq(BLOCK_TIME, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR, rootsToReset[1].merkleRoot)); - assertEq(0, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR, rootsToReset[2].merkleRoot)); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - EVM2EVMMultiOffRamp.UnblessedRoot[] memory rootsToReset = new EVM2EVMMultiOffRamp.UnblessedRoot[](0); - s_offRamp.resetUnblessedRoots(rootsToReset); + return OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); } } -contract EVM2EVMMultiOffRamp_verify is EVM2EVMMultiOffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupRealRMN(); - _deployOffRamp(s_destRouter, s_realRMN, s_inboundNonceManager); - _setupMultipleOffRamps(); - } - - function test_NotBlessed_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), - merkleRoot: leaves[0] - }); - EVM2EVMMultiOffRamp.CommitReport memory report = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - _commit(report, ++s_latestSequenceNumber); - bytes32[] memory proofs = new bytes32[](0); - // We have not blessed this root, should return 0. - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); - assertEq(uint256(0), timestamp); - } - - function test_Blessed_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), - merkleRoot: leaves[0] - }); - EVM2EVMMultiOffRamp.CommitReport memory report = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - _commit(report, ++s_latestSequenceNumber); - // Bless that root. - IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); - taggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: leaves[0]}); - vm.startPrank(BLESS_VOTE_ADDR); - s_realRMN.voteToBless(taggedRoots); - bytes32[] memory proofs = new bytes32[](0); - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); - assertEq(BLOCK_TIME, timestamp); - } - - function test_NotBlessedWrongChainSelector_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(1, 2), - merkleRoot: leaves[0] - }); - - EVM2EVMMultiOffRamp.CommitReport memory report = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - _commit(report, ++s_latestSequenceNumber); - - // Bless that root. - IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); - taggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: leaves[0]}); - vm.startPrank(BLESS_VOTE_ADDR); - s_realRMN.voteToBless(taggedRoots); - - bytes32[] memory proofs = new bytes32[](0); - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, leaves, proofs, 0); - assertEq(uint256(0), timestamp); - } +contract OffRamp_afterOC3ConfigSet is OffRampSetup { + function test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() public { + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + new OffRamp.SourceChainConfigArgs[](0) + ); - // Reverts + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_validSigners, + transmitters: s_validTransmitters + }); - function test_TooManyLeaves_Revert() public { - bytes32[] memory leaves = new bytes32[](258); - bytes32[] memory proofs = new bytes32[](0); - vm.expectRevert(MerkleMultiProof.InvalidProof.selector); - s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); + vm.expectRevert(OffRamp.SignatureVerificationDisabled.selector); + s_offRamp.setOCR3Configs(ocrConfigs); } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol similarity index 57% rename from contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol rename to contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index 507e966a70a..a789bc23605 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -2,35 +2,26 @@ pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; - -import {IAny2EVMOffRamp} from "../../interfaces/IAny2EVMOffRamp.sol"; import {ICommitStore} from "../../interfaces/ICommitStore.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {NonceManager} from "../../NonceManager.sol"; -import {RMN} from "../../RMN.sol"; import {Router} from "../../Router.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; -import {EVM2EVMMultiOffRamp} from "../../offRamp/EVM2EVMMultiOffRamp.sol"; -import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; -import {EVM2EVMMultiOffRampHelper} from "../helpers/EVM2EVMMultiOffRampHelper.sol"; -import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; +import {OffRampHelper} from "../helpers/OffRampHelper.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {MockCommitStore} from "../mocks/MockCommitStore.sol"; import {MultiOCR3BaseSetup} from "../ocr/MultiOCR3BaseSetup.t.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {Vm} from "forge-std/Test.sol"; -contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3BaseSetup { +contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 internal constant SOURCE_CHAIN_SELECTOR_1 = SOURCE_CHAIN_SELECTOR; uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; @@ -47,10 +38,9 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; - EVM2EVMMultiOffRampHelper internal s_offRamp; - MessageInterceptorHelper internal s_inboundMessageValidator; + OffRampHelper internal s_offRamp; + MessageInterceptorHelper internal s_inboundMessageInterceptor; NonceManager internal s_inboundNonceManager; - RMN internal s_realRMN; address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); bytes32 internal s_configDigestExec; @@ -60,12 +50,13 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba uint64 internal s_latestSequenceNumber; - function setUp() public virtual override(TokenSetup, PriceRegistrySetup, MultiOCR3BaseSetup) { - TokenSetup.setUp(); - PriceRegistrySetup.setUp(); + IRMNRemote.Signature[] internal s_rmnSignatures; + + function setUp() public virtual override(FeeQuoterSetup, MultiOCR3BaseSetup) { + FeeQuoterSetup.setUp(); MultiOCR3BaseSetup.setUp(); - s_inboundMessageValidator = new MessageInterceptorHelper(); + s_inboundMessageInterceptor = new MessageInterceptorHelper(); s_receiver = new MaybeRevertMessageReceiver(false); s_secondary_receiver = new MaybeRevertMessageReceiver(false); s_reverting_receiver = new MaybeRevertMessageReceiver(true); @@ -73,21 +64,20 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba s_maybeRevertingPool = MaybeRevertingBurnMintTokenPool(s_destPoolByToken[s_destTokens[1]]); s_inboundNonceManager = new NonceManager(new address[](0)); - _deployOffRamp(s_destRouter, s_mockRMN, s_inboundNonceManager); + _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); } - function _deployOffRamp(Router router, IRMN rmnProxy, NonceManager nonceManager) internal { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); + function _deployOffRamp(IRMNRemote rmnRemote, NonceManager nonceManager) internal { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(rmnProxy), + rmnRemote: rmnRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(nonceManager) }), - _generateDynamicMultiOffRampConfig(address(router), address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); @@ -112,7 +102,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba transmitters: s_validTransmitters }); - s_offRamp.setDynamicConfig(_generateDynamicMultiOffRampConfig(address(router), address(s_priceRegistry))); + s_offRamp.setDynamicConfig(_generateDynamicOffRampConfig(address(s_feeQuoter))); s_offRamp.setOCR3Configs(ocrConfigs); address[] memory authorizedCallers = new address[](1); @@ -123,68 +113,31 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba address[] memory priceUpdaters = new address[](1); priceUpdaters[0] = address(s_offRamp); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) ); - } - - // TODO: function can be made common across OffRampSetup and MultiOffRampSetup - function _deploySingleLaneOffRamp( - ICommitStore commitStore, - Router router, - address prevOffRamp, - uint64 sourceChainSelector, - address onRampAddress - ) internal returns (EVM2EVMOffRampHelper) { - EVM2EVMOffRampHelper offRamp = new EVM2EVMOffRampHelper( - EVM2EVMOffRamp.StaticConfig({ - commitStore: address(commitStore), - chainSelector: DEST_CHAIN_SELECTOR, - sourceChainSelector: sourceChainSelector, - onRamp: onRampAddress, - prevOffRamp: prevOffRamp, - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - getInboundRateLimiterConfig() - ); - offRamp.setOCR2Config( - s_validSigners, - s_validTransmitters, - s_F, - abi.encode(_generateDynamicOffRampConfig(address(router), address(s_priceRegistry))), - s_offchainConfigVersion, - abi.encode("") - ); - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: sourceChainSelector, offRamp: address(s_offRamp)}); - offRampUpdates[1] = Router.OffRamp({sourceChainSelector: sourceChainSelector, offRamp: address(prevOffRamp)}); - s_destRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - EVM2EVMOffRamp.RateLimitToken[] memory tokensToAdd = new EVM2EVMOffRamp.RateLimitToken[](s_sourceTokens.length); - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = EVM2EVMOffRamp.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); - } - offRamp.updateRateLimitTokens(new EVM2EVMOffRamp.RateLimitToken[](0), tokensToAdd); - - return offRamp; + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: address(s_offRamp)}); + s_destRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); } function _setupMultipleOffRamps() internal { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true }); - sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, onRamp: ON_RAMP_ADDRESS_2, isEnabled: false }); - sourceChainConfigs[2] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, onRamp: ON_RAMP_ADDRESS_3, isEnabled: true @@ -192,9 +145,9 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba _setupMultipleOffRampsFromConfigs(sourceChainConfigs); } - function _setupMultipleOffRampsFromConfigs(EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs) - internal - { + function _setupMultipleOffRampsFromConfigs( + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs + ) internal { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); @@ -213,47 +166,29 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba s_destRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); } - function _generateDynamicOffRampConfig( - address router, - address priceRegistry - ) internal pure returns (EVM2EVMOffRamp.DynamicConfig memory) { - return EVM2EVMOffRamp.DynamicConfig({ - permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, - router: router, - priceRegistry: priceRegistry, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - maxDataBytes: MAX_DATA_SIZE, - maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, - maxTokenTransferGas: MAX_TOKEN_POOL_TRANSFER_GAS - }); - } + uint32 internal constant MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS = 200_000; + uint32 internal constant MAX_TOKEN_POOL_TRANSFER_GAS = 50_000; - function _generateDynamicMultiOffRampConfig( - address router, - address priceRegistry - ) internal pure returns (EVM2EVMMultiOffRamp.DynamicConfig memory) { - return EVM2EVMMultiOffRamp.DynamicConfig({ + function _generateDynamicOffRampConfig( + address feeQuoter + ) internal pure returns (OffRamp.DynamicConfig memory) { + return OffRamp.DynamicConfig({ permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, - router: router, - priceRegistry: priceRegistry, - messageValidator: address(0), - maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, - maxTokenTransferGas: MAX_TOKEN_POOL_TRANSFER_GAS + feeQuoter: feeQuoter, + messageInterceptor: address(0) }); } - function _convertToGeneralMessage(Internal.Any2EVMRampMessage memory original) - internal - view - returns (Client.Any2EVMMessage memory message) - { + function _convertToGeneralMessage( + Internal.Any2EVMRampMessage memory original + ) internal view returns (Client.Any2EVMMessage memory message) { uint256 numberOfTokens = original.tokenAmounts.length; Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); for (uint256 i = 0; i < numberOfTokens; ++i) { - Internal.RampTokenAmount memory tokenAmount = original.tokenAmounts[i]; + Internal.Any2EVMTokenTransfer memory tokenAmount = original.tokenAmounts[i]; - address destPoolAddress = abi.decode(tokenAmount.destTokenAddress, (address)); + address destPoolAddress = tokenAmount.destTokenAddress; TokenPool pool = TokenPool(destPoolAddress); destTokenAmounts[i].token = address(pool.getToken()); destTokenAmounts[i].amount = tokenAmount.amount; @@ -282,7 +217,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba uint64 sequenceNumber, uint256[] memory amounts ) internal view returns (Internal.Any2EVMRampMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); for (uint256 i = 0; i < tokenAmounts.length; ++i) { tokenAmounts[i].amount = amounts[i]; } @@ -298,15 +233,17 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba ) internal view returns (Internal.Any2EVMRampMessage memory) { bytes memory data = abi.encode(0); - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](tokenAmounts.length); + Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = + new Internal.Any2EVMTokenTransfer[](tokenAmounts.length); // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. for (uint256 i = 0; i < tokenAmounts.length; ++i) { - rampTokenAmounts[i] = Internal.RampTokenAmount({ + any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[tokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[tokenAmounts[i].token], extraData: "", - amount: tokenAmounts[i].amount + amount: tokenAmounts[i].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } @@ -321,11 +258,11 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba sender: abi.encode(OWNER), data: data, receiver: address(s_receiver), - tokenAmounts: rampTokenAmounts, + tokenAmounts: any2EVMTokenTransfer, gasLimit: GAS_LIMIT }); - message.header.messageId = Internal._hash(message, onRamp); + message.header.messageId = _hashMessage(message, onRamp); return message; } @@ -344,7 +281,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba bytes memory onRamp ) internal view returns (Internal.Any2EVMRampMessage[] memory) { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); - Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); tokenAmounts[0].amount = 1e18; tokenAmounts[1].amount = 5e18; messages[0] = _generateAny2EVMMessage(sourceChainSelector, onRamp, 1, tokenAmounts, false); @@ -356,14 +293,14 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba function _generateReportFromMessages( uint64 sourceChainSelector, Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (Internal.ExecutionReportSingleChain memory) { + ) internal pure returns (Internal.ExecutionReport memory) { bytes[][] memory offchainTokenData = new bytes[][](messages.length); for (uint256 i = 0; i < messages.length; ++i) { offchainTokenData[i] = new bytes[](messages[i].tokenAmounts.length); } - return Internal.ExecutionReportSingleChain({ + return Internal.ExecutionReport({ sourceChainSelector: sourceChainSelector, proofs: new bytes32[](0), proofFlagBits: 2 ** 256 - 1, @@ -375,79 +312,71 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba function _generateBatchReportFromMessages( uint64 sourceChainSelector, Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (Internal.ExecutionReportSingleChain[] memory) { - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](1); + ) internal pure returns (Internal.ExecutionReport[] memory) { + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](1); reports[0] = _generateReportFromMessages(sourceChainSelector, messages); return reports; } - function _getGasLimitsFromMessages(Internal.Any2EVMRampMessage[] memory messages) - internal - pure - returns (uint256[] memory) - { - uint256[] memory gasLimits = new uint256[](messages.length); + function _getGasLimitsFromMessages( + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (OffRamp.GasLimitOverride[] memory) { + OffRamp.GasLimitOverride[] memory gasLimits = new OffRamp.GasLimitOverride[](messages.length); for (uint256 i = 0; i < messages.length; ++i) { - gasLimits[i] = messages[i].gasLimit; + gasLimits[i].receiverExecutionGasLimit = messages[i].gasLimit; } return gasLimits; } - function _assertSameConfig( - EVM2EVMMultiOffRamp.DynamicConfig memory a, - EVM2EVMMultiOffRamp.DynamicConfig memory b - ) public pure { + function _assertSameConfig(OffRamp.DynamicConfig memory a, OffRamp.DynamicConfig memory b) public pure { assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); - assertEq(a.router, b.router); - assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); - assertEq(a.maxTokenTransferGas, b.maxTokenTransferGas); - assertEq(a.messageValidator, b.messageValidator); - assertEq(a.priceRegistry, b.priceRegistry); + assertEq(a.messageInterceptor, b.messageInterceptor); + assertEq(a.feeQuoter, b.feeQuoter); } function _assertSourceChainConfigEquality( - EVM2EVMMultiOffRamp.SourceChainConfig memory config1, - EVM2EVMMultiOffRamp.SourceChainConfig memory config2 + OffRamp.SourceChainConfig memory config1, + OffRamp.SourceChainConfig memory config2 ) internal pure { assertEq(config1.isEnabled, config2.isEnabled); assertEq(config1.minSeqNr, config2.minSeqNr); assertEq(config1.onRamp, config2.onRamp); + assertEq(address(config1.router), address(config2.router)); } - function _getDefaultSourceTokenData(Client.EVMTokenAmount[] memory srcTokenAmounts) - internal - view - returns (Internal.RampTokenAmount[] memory) - { - Internal.RampTokenAmount[] memory sourceTokenData = new Internal.RampTokenAmount[](srcTokenAmounts.length); + function _getDefaultSourceTokenData( + Client.EVMTokenAmount[] memory srcTokenAmounts + ) internal view returns (Internal.Any2EVMTokenTransfer[] memory) { + Internal.Any2EVMTokenTransfer[] memory sourceTokenData = new Internal.Any2EVMTokenTransfer[](srcTokenAmounts.length); for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { - sourceTokenData[i] = Internal.RampTokenAmount({ + sourceTokenData[i] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[srcTokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[srcTokenAmounts[i].token], extraData: "", - amount: srcTokenAmounts[i].amount + amount: srcTokenAmounts[i].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } return sourceTokenData; } - function _enableInboundMessageValidator() internal { - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); - dynamicConfig.messageValidator = address(s_inboundMessageValidator); + function _enableInboundMessageInterceptor() internal { + OffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); + dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); s_offRamp.setDynamicConfig(dynamicConfig); } function _redeployOffRampWithNoOCRConfigs() internal { - s_offRamp = new EVM2EVMMultiOffRampHelper( - EVM2EVMMultiOffRamp.StaticConfig({ + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicMultiOffRampConfig(address(s_destRouter), address(s_priceRegistry)), - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0) + _generateDynamicOffRampConfig(address(s_feeQuoter)), + new OffRamp.SourceChainConfigArgs[](0) ); address[] memory authorizedCallers = new address[](1); @@ -459,20 +388,12 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba address[] memory priceUpdaters = new address[](1); priceUpdaters[0] = address(s_offRamp); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) ); } - function _setupRealRMN() internal { - RMN.Voter[] memory voters = new RMN.Voter[](1); - voters[0] = - RMN.Voter({blessVoteAddr: BLESS_VOTE_ADDR, curseVoteAddr: address(9999), blessWeight: 1, curseWeight: 1}); - // Overwrite base mock rmn with real. - s_realRMN = new RMN(RMN.Config({voters: voters, blessWeightThreshold: 1, curseWeightThreshold: 1})); - } - - function _commit(EVM2EVMMultiOffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { + function _commit(OffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber)), s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -482,10 +403,95 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function _execute(Internal.ExecutionReportSingleChain[] memory reports) internal { + function _execute( + Internal.ExecutionReport[] memory reports + ) internal { bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); s_offRamp.execute(reportContext, abi.encode(reports)); } + + function assertExecutionStateChangedEventLogs( + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes memory returnData + ) public { + Vm.Log[] memory logs = vm.getRecordedLogs(); + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = + abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + if (logMessageId == messageId) { + assertEq(logSourceChainSelector, sourceChainSelector); + assertEq(logSequenceNumber, sequenceNumber); + assertEq(logMessageId, messageId); + assertEq(logMessageHash, messageHash); + assertEq(logState, uint8(state)); + assertEq(logReturnData, returnData); + } + } + } + } + + function assertExecutionStateChangedEventLogs( + Vm.Log[] memory logs, + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes memory returnData + ) public pure { + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = + abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + if (logMessageId == messageId) { + assertEq(logSourceChainSelector, sourceChainSelector); + assertEq(logSequenceNumber, sequenceNumber); + assertEq(logMessageId, messageId); + assertEq(logMessageHash, messageHash); + assertEq(logState, uint8(state)); + assertEq(logReturnData, returnData); + } + } + } + } + + function _assertNoEmit( + bytes32 eventSelector + ) internal { + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 i = 0; i < logs.length; i++) { + assertTrue(logs[i].topics[0] != eventSelector); + } + } + + function _hashMessage( + Internal.Any2EVMRampMessage memory message, + bytes memory onRamp + ) internal pure returns (bytes32) { + return Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); + } } diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol deleted file mode 100644 index bc7fac95be6..00000000000 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol +++ /dev/null @@ -1,720 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; -import {EVM2EVMMultiOnRamp} from "../../onRamp/EVM2EVMMultiOnRamp.sol"; -import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {EVM2EVMOnRampHelper} from "../helpers/EVM2EVMOnRampHelper.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; -import "./EVM2EVMMultiOnRampSetup.t.sol"; - -contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { - function test_Constructor_Success() public { - EVM2EVMMultiOnRamp.StaticConfig memory staticConfig = EVM2EVMMultiOnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }); - EVM2EVMMultiOnRamp.DynamicConfig memory dynamicConfig = - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.ConfigSet(staticConfig, dynamicConfig); - - _deployOnRamp( - SOURCE_CHAIN_SELECTOR, address(s_sourceRouter), address(s_outboundNonceManager), address(s_tokenAdminRegistry) - ); - - EVM2EVMMultiOnRamp.StaticConfig memory gotStaticConfig = s_onRamp.getStaticConfig(); - _assertStaticConfigsEqual(staticConfig, gotStaticConfig); - - EVM2EVMMultiOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - _assertDynamicConfigsEqual(dynamicConfig, gotDynamicConfig); - - // Initial values - assertEq("EVM2EVMMultiOnRamp 1.6.0-dev", s_onRamp.typeAndVersion()); - assertEq(OWNER, s_onRamp.owner()); - assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); - } - - function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - new EVM2EVMMultiOnRampHelper( - EVM2EVMMultiOnRamp.StaticConfig({ - chainSelector: 0, - rmnProxy: address(s_mockRMN), - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) - ); - } - - function test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - s_onRamp = new EVM2EVMMultiOnRampHelper( - EVM2EVMMultiOnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(0), - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) - ); - } - - function test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - new EVM2EVMMultiOnRampHelper( - EVM2EVMMultiOnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), - nonceManager: address(0), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) - ); - } - - function test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - new EVM2EVMMultiOnRampHelper( - EVM2EVMMultiOnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(0) - }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) - ); - } -} - -contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { - struct LegacyExtraArgs { - uint256 gasLimit; - bool strict; - } - - function setUp() public virtual override { - super.setUp(); - - address[] memory feeTokens = new address[](1); - feeTokens[0] = s_sourceTokens[1]; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - - // Since we'll mostly be testing for valid calls from the router we'll - // mock all calls to be originating from the router and re-mock in - // tests that require failure. - vm.startPrank(address(s_sourceRouter)); - } - - function test_ForwardFromRouterSuccessCustomExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterSuccessLegacyExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = - abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V1_TAG, LegacyExtraArgs({gasLimit: GAS_LIMIT * 2, strict: true})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - // We expect the message to be emitted with strict = false. - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterSuccessEmptyExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = ""; - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - // We expect the message to be emitted with strict = false. - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouter_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterExtraArgsV2_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: false}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ShouldIncrementSeqNumAndNonce_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - for (uint64 i = 1; i < 4; ++i) { - uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - assertEq(nonceAfter, nonceBefore + 1); - assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); - } - } - - function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - - for (uint64 i = 1; i < 4; ++i) { - uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - assertEq(nonceAfter, nonceBefore); - assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); - } - } - - function test_ShouldStoreLinkFees() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.FeePaid(s_sourceFeeToken, feeAmount); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - 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_priceRegistry.getTokenPrice(s_sourceTokens[1]).value; - uint256 linkTokenPrice = s_priceRegistry.getTokenPrice(s_sourceFeeToken).value; - uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; - uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.FeePaid(s_sourceTokens[1], expectedJuels); - 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 test_Fuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { - // To avoid RouterMustSetOriginalSender - vm.assume(originalSender != address(0)); - vm.assume(uint160(receiver) >= Internal.PRECOMPILE_SPACE); - feeTokenAmount = uint96(bound(feeTokenAmount, 0, MAX_MSG_FEES_JUELS)); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(receiver); - - // Make sure the tokens are in the contract - deal(s_sourceFeeToken, address(s_onRamp), feeTokenAmount); - - Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.FeePaid(s_sourceFeeToken, feeTokenAmount); - vm.expectEmit(false, false, false, true); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, expectedEvent); - - // Assert the message Id is correct - assertEq( - expectedEvent.header.messageId, - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) - ); - } - - function test_forwardFromRouter_WithValidation_Success() public { - _enableOutboundMessageValidator(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1e18; - message.tokenAmounts[0].token = s_sourceTokens[0]; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_outboundMessageValidator.setMessageIdValidationState(keccak256(abi.encode(message)), false); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - // Reverts - - function test_Paused_Revert() public { - // We pause by disabling the whitelist - vm.stopPrank(); - vm.startPrank(OWNER); - address router = address(0); - s_onRamp.setDynamicConfig(_generateDynamicMultiOnRampConfig(router, address(2))); - vm.expectRevert(EVM2EVMMultiOnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_InvalidExtraArgsTag_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = bytes("bad args"); - - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidExtraArgsTag.selector); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_Permissions_Revert() public { - vm.stopPrank(); - vm.startPrank(OWNER); - vm.expectRevert(EVM2EVMMultiOnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_OriginalSender_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.RouterMustSetOriginalSender.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); - } - - function test_MessageValidationError_Revert() public { - _enableOutboundMessageValidator(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1e18; - message.tokenAmounts[0].token = s_sourceTokens[0]; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_outboundMessageValidator.setMessageIdValidationState(keccak256(abi.encode(message)), true); - - vm.expectRevert( - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_CannotSendZeroTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 0; - message.tokenAmounts[0].token = s_sourceTokens[0]; - vm.expectRevert(EVM2EVMMultiOnRamp.CannotSendZeroTokens.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); - } - - function test_UnsupportedToken_Revert() public { - address wrongToken = address(1); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].token = wrongToken; - message.tokenAmounts[0].amount = 1; - - // We need to set the price of this new token to be able to reach - // the proper revert point. This must be called by the owner. - vm.stopPrank(); - vm.startPrank(OWNER); - - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(wrongToken, 1); - s_priceRegistry.updatePrices(priceUpdates); - - // Change back to the router - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.UnsupportedToken.selector, wrongToken)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_forwardFromRouter_UnsupportedToken_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1; - message.tokenAmounts[0].token = address(1); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_MesssageFeeTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); - } - - function test_SourceTokenDataTooLarge_Revert() public { - address sourceETH = s_sourceTokens[1]; - vm.stopPrank(); - vm.startPrank(OWNER); - - MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMN), address(s_sourceRouter) - ); - BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); - deal(address(sourceETH), address(newPool), type(uint256).max); - - // Add TokenPool to OnRamp - s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); - - // Allow chain in TokenPool - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - newPool.applyChainUpdates(chainUpdates); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); - - // No data set, should succeed - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set max data length, should succeed - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES)); - - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set data to max length +1, should revert - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); - - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set token config to allow larger data - vm.startPrank(OWNER); - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, - isEnabled: true - }); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set the token data larger than the configured token data, should revert - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); - - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } -} - -contract EVM2EVMMultiOnRamp_getSupportedTokens is EVM2EVMMultiOnRampSetup { - function test_GetSupportedTokens_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); - s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); - } -} - -contract EVM2EVMMultiOnRamp_getFee is EVM2EVMMultiOnRampSetup { - using USDPriceWith18Decimals for uint224; - - function test_EmptyMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = testTokens[i]; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 expectedFeeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - assertEq(expectedFeeAmount, feeAmount); - } - } - - function test_SingleTokenMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 tokenAmount = 10000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - message.feeToken = testTokens[i]; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 expectedFeeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - assertEq(expectedFeeAmount, feeAmount); - } - } - - // Reverts - - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); - } - - function test_EnforceOutOfOrder_Revert() public { - // Update dynamic config to enforce allowOutOfOrderExecution = true. - vm.stopPrank(); - vm.startPrank(OWNER); - - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - vm.stopPrank(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - // Empty extraArgs to should revert since it enforceOutOfOrder is true. - message.extraArgs = ""; - - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract EVM2EVMMultiOnRamp_setDynamicConfig is EVM2EVMMultiOnRampSetup { - function test_SetDynamicConfig_Success() public { - EVM2EVMMultiOnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); - EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ - router: address(2134), - priceRegistry: address(23423), - messageValidator: makeAddr("messageValidator"), - feeAggregator: FEE_AGGREGATOR - }); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.ConfigSet(staticConfig, newConfig); - - s_onRamp.setDynamicConfig(newConfig); - - EVM2EVMMultiOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - assertEq(newConfig.router, gotDynamicConfig.router); - assertEq(newConfig.priceRegistry, gotDynamicConfig.priceRegistry); - } - - // Reverts - - function test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() public { - EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ - router: address(2134), - priceRegistry: address(0), - feeAggregator: FEE_AGGREGATOR, - messageValidator: makeAddr("messageValidator") - }); - - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_SetConfigInvalidConfig_Revert() public { - EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ - router: address(1), - priceRegistry: address(23423), - messageValidator: address(0), - feeAggregator: FEE_AGGREGATOR - }); - - // Invalid price reg reverts. - newConfig.priceRegistry = address(0); - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() public { - EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ - router: address(2134), - priceRegistry: address(23423), - messageValidator: address(0), - feeAggregator: address(0) - }); - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_SetConfigOnlyOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_onRamp.setDynamicConfig(_generateDynamicMultiOnRampConfig(address(1), address(2))); - vm.startPrank(ADMIN); - vm.expectRevert("Only callable by owner"); - s_onRamp.setDynamicConfig(_generateDynamicMultiOnRampConfig(address(1), address(2))); - } -} - -contract EVM2EVMMultiOnRamp_withdrawFeeTokens is EVM2EVMMultiOnRampSetup { - mapping(address => uint256) internal s_nopFees; - - function setUp() public virtual override { - super.setUp(); - - // Since we'll mostly be testing for valid calls from the router we'll - // mock all calls to be originating from the router and re-mock in - // tests that require failure. - vm.startPrank(address(s_sourceRouter)); - - uint256 feeAmount = 1234567890; - - // Send a bunch of messages, increasing the juels in the contract - for (uint256 i = 0; i < s_sourceFeeTokens.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceFeeTokens[i % s_sourceFeeTokens.length]; - uint256 newFeeTokenBalance = IERC20(message.feeToken).balanceOf(address(s_onRamp)) + feeAmount; - deal(message.feeToken, address(s_onRamp), newFeeTokenBalance); - s_nopFees[message.feeToken] = newFeeTokenBalance; - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - } - - function test_Fuzz_WithdrawFeeTokens_Success(uint256[5] memory amounts) public { - vm.startPrank(OWNER); - address[] memory feeTokens = new address[](amounts.length); - for (uint256 i = 0; i < amounts.length; ++i) { - vm.assume(amounts[i] > 0); - feeTokens[i] = _deploySourceToken("", amounts[i], 18); - IERC20(feeTokens[i]).transfer(address(s_onRamp), amounts[i]); - } - - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - - for (uint256 i = 0; i < feeTokens.length; ++i) { - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, feeTokens[i], amounts[i]); - } - - s_onRamp.withdrawFeeTokens(); - - for (uint256 i = 0; i < feeTokens.length; ++i) { - assertEq(IERC20(feeTokens[i]).balanceOf(FEE_AGGREGATOR), amounts[i]); - assertEq(IERC20(feeTokens[i]).balanceOf(address(s_onRamp)), 0); - } - } - - function test_WithdrawFeeTokens_Success() public { - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, s_sourceFeeToken, s_nopFees[s_sourceFeeToken]); - - s_onRamp.withdrawFeeTokens(); - - assertEq(IERC20(s_sourceFeeToken).balanceOf(FEE_AGGREGATOR), s_nopFees[s_sourceFeeToken]); - assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), 0); - } -} - -contract EVM2EVMMultiOnRamp_getTokenPool is EVM2EVMMultiOnRampSetup { - function test_GetTokenPool_Success() public view { - assertEq( - s_sourcePoolByToken[s_sourceTokens[0]], - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) - ); - assertEq( - s_sourcePoolByToken[s_sourceTokens[1]], - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[1]))) - ); - - address wrongToken = address(123); - address nonExistentPool = address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(wrongToken))); - - assertEq(address(0), nonExistentPool); - } -} diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol deleted file mode 100644 index 197a87b7081..00000000000 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol +++ /dev/null @@ -1,1986 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; -import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import "./EVM2EVMOnRampSetup.t.sol"; - -contract EVM2EVMOnRamp_constructor is EVM2EVMOnRampSetup { - function test_Constructor_Success() public { - EVM2EVMOnRamp.StaticConfig memory staticConfig = EVM2EVMOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], - chainSelector: SOURCE_CHAIN_SELECTOR, - destChainSelector: DEST_CHAIN_SELECTOR, - defaultTxGasLimit: GAS_LIMIT, - maxNopFeesJuels: MAX_NOP_FEES_JUELS, - prevOnRamp: address(0), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }); - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = - generateDynamicOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)); - - vm.expectEmit(); - emit EVM2EVMOnRamp.ConfigSet(staticConfig, dynamicConfig); - - s_onRamp = new EVM2EVMOnRampHelper( - staticConfig, - dynamicConfig, - getOutboundRateLimiterConfig(), - s_feeTokenConfigArgs, - s_tokenTransferFeeConfigArgs, - getNopsAndWeights() - ); - - EVM2EVMOnRamp.StaticConfig memory gotStaticConfig = s_onRamp.getStaticConfig(); - assertEq(staticConfig.linkToken, gotStaticConfig.linkToken); - assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); - assertEq(staticConfig.destChainSelector, gotStaticConfig.destChainSelector); - assertEq(staticConfig.defaultTxGasLimit, gotStaticConfig.defaultTxGasLimit); - assertEq(staticConfig.maxNopFeesJuels, gotStaticConfig.maxNopFeesJuels); - assertEq(staticConfig.prevOnRamp, gotStaticConfig.prevOnRamp); - assertEq(staticConfig.rmnProxy, gotStaticConfig.rmnProxy); - - EVM2EVMOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - assertEq(dynamicConfig.router, gotDynamicConfig.router); - assertEq(dynamicConfig.maxNumberOfTokensPerMsg, gotDynamicConfig.maxNumberOfTokensPerMsg); - assertEq(dynamicConfig.destGasOverhead, gotDynamicConfig.destGasOverhead); - assertEq(dynamicConfig.destGasPerPayloadByte, gotDynamicConfig.destGasPerPayloadByte); - assertEq(dynamicConfig.priceRegistry, gotDynamicConfig.priceRegistry); - assertEq(dynamicConfig.maxDataBytes, gotDynamicConfig.maxDataBytes); - assertEq(dynamicConfig.maxPerMsgGasLimit, gotDynamicConfig.maxPerMsgGasLimit); - - // Initial values - assertEq("EVM2EVMOnRamp 1.5.0-dev", s_onRamp.typeAndVersion()); - assertEq(OWNER, s_onRamp.owner()); - assertEq(1, s_onRamp.getExpectedNextSequenceNumber()); - } -} - -contract EVM2EVMOnRamp_payNops_fuzz is EVM2EVMOnRampSetup { - function test_Fuzz_NopPayNops_Success(uint96 nopFeesJuels) public { - (EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights, uint256 weightsTotal) = s_onRamp.getNops(); - // To avoid NoFeesToPay - vm.assume(nopFeesJuels > weightsTotal); - vm.assume(nopFeesJuels < MAX_NOP_FEES_JUELS); - - // Set Nop fee juels - deal(s_sourceFeeToken, address(s_onRamp), nopFeesJuels); - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), nopFeesJuels, OWNER); - - vm.startPrank(OWNER); - - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - s_onRamp.payNops(); - for (uint256 i = 0; i < nopsAndWeights.length; ++i) { - uint256 expectedPayout = (totalJuels * nopsAndWeights[i].weight) / weightsTotal; - assertEq(IERC20(s_sourceFeeToken).balanceOf(nopsAndWeights[i].nop), expectedPayout); - } - } -} - -contract EVM2EVMNopsFeeSetup is EVM2EVMOnRampSetup { - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - - // Since we'll mostly be testing for valid calls from the router we'll - // mock all calls to be originating from the router and re-mock in - // tests that require failure. - vm.startPrank(address(s_sourceRouter)); - - uint256 feeAmount = 1234567890; - uint256 numberOfMessages = 5; - - // Send a bunch of messages, increasing the juels in the contract - for (uint256 i = 0; i < numberOfMessages; ++i) { - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), feeAmount, OWNER); - } - - assertEq(s_onRamp.getNopFeesJuels(), feeAmount * numberOfMessages); - assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount * numberOfMessages); - } -} - -contract EVM2EVMOnRamp_payNops is EVM2EVMNopsFeeSetup { - function test_OwnerPayNops_Success() public { - vm.startPrank(OWNER); - - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - s_onRamp.payNops(); - (EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights, uint256 weightsTotal) = s_onRamp.getNops(); - for (uint256 i = 0; i < nopsAndWeights.length; ++i) { - uint256 expectedPayout = (nopsAndWeights[i].weight * totalJuels) / weightsTotal; - assertEq(IERC20(s_sourceFeeToken).balanceOf(nopsAndWeights[i].nop), expectedPayout); - } - } - - function test_AdminPayNops_Success() public { - vm.startPrank(ADMIN); - - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - s_onRamp.payNops(); - (EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights, uint256 weightsTotal) = s_onRamp.getNops(); - for (uint256 i = 0; i < nopsAndWeights.length; ++i) { - uint256 expectedPayout = (nopsAndWeights[i].weight * totalJuels) / weightsTotal; - assertEq(IERC20(s_sourceFeeToken).balanceOf(nopsAndWeights[i].nop), expectedPayout); - } - } - - function test_NopPayNops_Success() public { - vm.startPrank(getNopsAndWeights()[0].nop); - - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - s_onRamp.payNops(); - (EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights, uint256 weightsTotal) = s_onRamp.getNops(); - for (uint256 i = 0; i < nopsAndWeights.length; ++i) { - uint256 expectedPayout = (nopsAndWeights[i].weight * totalJuels) / weightsTotal; - assertEq(IERC20(s_sourceFeeToken).balanceOf(nopsAndWeights[i].nop), expectedPayout); - } - } - - function test_PayNopsSuccessAfterSetNops() public { - vm.startPrank(OWNER); - - // set 2 nops, 1 from previous, 1 new - address prevNop = getNopsAndWeights()[0].nop; - address newNop = STRANGER; - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](2); - nopsAndWeights[0] = EVM2EVMOnRamp.NopAndWeight({nop: prevNop, weight: 1}); - nopsAndWeights[1] = EVM2EVMOnRamp.NopAndWeight({nop: newNop, weight: 1}); - s_onRamp.setNops(nopsAndWeights); - - // refill OnRamp nops fees - vm.startPrank(address(s_sourceRouter)); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), feeAmount, OWNER); - - vm.startPrank(newNop); - uint256 prevNopBalance = IERC20(s_sourceFeeToken).balanceOf(prevNop); - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - - s_onRamp.payNops(); - - assertEq(totalJuels / 2 + prevNopBalance, IERC20(s_sourceFeeToken).balanceOf(prevNop)); - assertEq(totalJuels / 2, IERC20(s_sourceFeeToken).balanceOf(newNop)); - } - - // Reverts - - function test_InsufficientBalance_Revert() public { - vm.startPrank(address(s_onRamp)); - IERC20(s_sourceFeeToken).transfer(OWNER, IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp))); - vm.startPrank(OWNER); - vm.expectRevert(EVM2EVMOnRamp.InsufficientBalance.selector); - s_onRamp.payNops(); - } - - function test_WrongPermissions_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdminOrNop.selector); - s_onRamp.payNops(); - } - - function test_NoFeesToPay_Revert() public { - vm.startPrank(OWNER); - s_onRamp.payNops(); - vm.expectRevert(EVM2EVMOnRamp.NoFeesToPay.selector); - s_onRamp.payNops(); - } - - function test_NoNopsToPay_Revert() public { - vm.startPrank(OWNER); - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](0); - s_onRamp.setNops(nopsAndWeights); - vm.expectRevert(EVM2EVMOnRamp.NoNopsToPay.selector); - s_onRamp.payNops(); - } -} - -contract EVM2EVMOnRamp_linkAvailableForPayment is EVM2EVMNopsFeeSetup { - function test_LinkAvailableForPayment_Success() public { - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - uint256 linkBalance = IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)); - - assertEq(int256(linkBalance - totalJuels), s_onRamp.linkAvailableForPayment()); - - vm.startPrank(OWNER); - s_onRamp.payNops(); - - assertEq(int256(linkBalance - totalJuels), s_onRamp.linkAvailableForPayment()); - } - - function test_InsufficientLinkBalance_Success() public { - uint256 totalJuels = s_onRamp.getNopFeesJuels(); - uint256 linkBalance = IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)); - - vm.startPrank(address(s_onRamp)); - - uint256 linkRemaining = 1; - IERC20(s_sourceFeeToken).transfer(OWNER, linkBalance - linkRemaining); - - vm.startPrank(STRANGER); - assertEq(int256(linkRemaining) - int256(totalJuels), s_onRamp.linkAvailableForPayment()); - } -} - -contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { - struct LegacyExtraArgs { - uint256 gasLimit; - bool strict; - } - - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - - address[] memory feeTokens = new address[](1); - feeTokens[0] = s_sourceTokens[1]; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - - // Since we'll mostly be testing for valid calls from the router we'll - // mock all calls to be originating from the router and re-mock in - // tests that require failure. - vm.startPrank(address(s_sourceRouter)); - } - - function test_ForwardFromRouterSuccessCustomExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterSuccessLegacyExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = - abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V1_TAG, LegacyExtraArgs({gasLimit: GAS_LIMIT * 2, strict: true})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - // We expect the message to be emitted with strict = false. - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouter_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterExtraArgsV2_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { - // Update dynamic config to enforce allowOutOfOrderExecution = defaultVal. - vm.stopPrank(); - vm.startPrank(OWNER); - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - s_onRamp.setDynamicConfig( - EVM2EVMOnRamp.DynamicConfig({ - router: dynamicConfig.router, - maxNumberOfTokensPerMsg: dynamicConfig.maxNumberOfTokensPerMsg, - destGasOverhead: dynamicConfig.destGasOverhead, - destGasPerPayloadByte: dynamicConfig.destGasPerPayloadByte, - destDataAvailabilityOverheadGas: dynamicConfig.destDataAvailabilityOverheadGas, - destGasPerDataAvailabilityByte: dynamicConfig.destGasPerDataAvailabilityByte, - destDataAvailabilityMultiplierBps: dynamicConfig.destDataAvailabilityMultiplierBps, - priceRegistry: dynamicConfig.priceRegistry, - maxDataBytes: dynamicConfig.maxDataBytes, - maxPerMsgGasLimit: dynamicConfig.maxPerMsgGasLimit, - defaultTokenFeeUSDCents: dynamicConfig.defaultTokenFeeUSDCents, - defaultTokenDestGasOverhead: dynamicConfig.defaultTokenDestGasOverhead, - defaultTokenDestBytesOverhead: dynamicConfig.defaultTokenDestBytesOverhead, - enforceOutOfOrder: enforce - }) - ); - vm.stopPrank(); - - vm.startPrank(address(s_sourceRouter)); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - if (enforce) { - // If enforcement is on, only true should be allowed. - if (allowOutOfOrderExecution) { - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } else { - vm.expectRevert(EVM2EVMOnRamp.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - } else { - // no enforcement should allow any value. - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, feeAmount, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - } - - function test_ShouldIncrementSeqNumAndNonce_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - for (uint64 i = 1; i < 4; ++i) { - uint64 nonceBefore = s_onRamp.getSenderNonce(OWNER); - uint64 sequenceNumberBefore = s_onRamp.getSequenceNumber(); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, i, i, 0, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - uint64 nonceAfter = s_onRamp.getSenderNonce(OWNER); - uint64 sequenceNumberAfter = s_onRamp.getSequenceNumber(); - assertEq(nonceAfter, nonceBefore + 1); - assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); - } - } - - function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - - for (uint64 i = 1; i < 4; ++i) { - uint64 nonceBefore = s_onRamp.getSenderNonce(OWNER); - uint64 sequenceNumberBefore = s_onRamp.getSequenceNumber(); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, i, i, 0, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - uint64 nonceAfter = s_onRamp.getSenderNonce(OWNER); - uint64 sequenceNumberAfter = s_onRamp.getSequenceNumber(); - assertEq(nonceAfter, nonceBefore); - assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); - } - } - - function test_forwardFromRouter_ShouldStoreLinkFees_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount); - assertEq(s_onRamp.getNopFeesJuels(), 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); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); - - // Calculate conversion done by prices contract - uint256 feeTokenPrice = s_priceRegistry.getTokenPrice(s_sourceTokens[1]).value; - uint256 linkTokenPrice = s_priceRegistry.getTokenPrice(s_sourceFeeToken).value; - uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; - uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; - - assertEq(s_onRamp.getNopFeesJuels(), expectedJuels); - } - - // 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-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 32 - function test_Fuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { - // To avoid RouterMustSetOriginalSender - vm.assume(originalSender != address(0)); - vm.assume(uint160(receiver) >= Internal.PRECOMPILE_SPACE); - vm.assume(feeTokenAmount <= MAX_NOP_FEES_JUELS); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(receiver); - - // Make sure the tokens are in the contract - deal(s_sourceFeeToken, address(s_onRamp), feeTokenAmount); - - Internal.EVM2EVMMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); - - vm.expectEmit(false, false, false, true); - emit EVM2EVMOnRamp.CCIPSendRequested(expectedEvent); - - // Assert the message Id is correct - assertEq( - expectedEvent.messageId, s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) - ); - // Assert the fee token amount is correctly assigned to the nop fee pool - assertEq(feeTokenAmount, s_onRamp.getNopFeesJuels()); - } - - function test_OverValueWithARLOff_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 10; - message.tokenAmounts[0].token = s_sourceTokens[0]; - - IERC20(s_sourceTokens[0]).approve(address(s_onRamp), 10); - - vm.startPrank(OWNER); - // Set a high price to trip the ARL - uint224 tokenPrice = 3 ** 128; - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(s_sourceTokens[0], tokenPrice); - s_priceRegistry.updatePrices(priceUpdates); - vm.startPrank(address(s_sourceRouter)); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueMaxCapacityExceeded.selector, - getOutboundRateLimiterConfig().capacity, - (message.tokenAmounts[0].amount * tokenPrice) / 1e18 - ) - ); - // Expect to fail from ARL - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Configure ARL off for token - EVM2EVMOnRamp.TokenTransferFeeConfig memory tokenTransferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(s_sourceTokens[0]); - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](1); - tokenTransferFeeConfigArgs[0] = EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: s_sourceTokens[0], - minFeeUSDCents: tokenTransferFeeConfig.minFeeUSDCents, - maxFeeUSDCents: tokenTransferFeeConfig.maxFeeUSDCents, - deciBps: tokenTransferFeeConfig.deciBps, - destGasOverhead: tokenTransferFeeConfig.destGasOverhead, - destBytesOverhead: tokenTransferFeeConfig.destBytesOverhead, - aggregateRateLimitEnabled: false - }); - vm.startPrank(OWNER); - s_onRamp.setTokenTransferFeeConfig(tokenTransferFeeConfigArgs, new address[](0)); - - vm.startPrank(address(s_sourceRouter)); - // Expect the call now succeeds - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - // Reverts - - function test_Paused_Revert() public { - // We pause by disabling the whitelist - vm.stopPrank(); - vm.startPrank(OWNER); - address router = address(0); - s_onRamp.setDynamicConfig(generateDynamicOnRampConfig(router, address(2))); - vm.expectRevert(EVM2EVMOnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_InvalidExtraArgsTag_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = bytes("bad args"); - - vm.expectRevert(EVM2EVMOnRamp.InvalidExtraArgsTag.selector); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(EVM2EVMOnRamp.CursedByRMN.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_Permissions_Revert() public { - vm.stopPrank(); - vm.startPrank(OWNER); - vm.expectRevert(EVM2EVMOnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_OriginalSender_Revert() public { - vm.expectRevert(EVM2EVMOnRamp.RouterMustSetOriginalSender.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); - } - - function test_MessageTooLarge_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); - } - - function test_TooManyTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 tooMany = MAX_TOKENS_LENGTH + 1; - message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(EVM2EVMOnRamp.UnsupportedNumberOfTokens.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); - } - - function test_CannotSendZeroTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 0; - message.tokenAmounts[0].token = s_sourceTokens[0]; - vm.expectRevert(EVM2EVMOnRamp.CannotSendZeroTokens.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); - } - - function test_UnsupportedToken_Revert() public { - address wrongToken = address(1); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].token = wrongToken; - message.tokenAmounts[0].amount = 1; - - // We need to set the price of this new token to be able to reach - // the proper revert point. This must be called by the owner. - vm.stopPrank(); - vm.startPrank(OWNER); - - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(wrongToken, 1); - s_priceRegistry.updatePrices(priceUpdates); - - // Change back to the router - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.UnsupportedToken.selector, wrongToken)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_MaxCapacityExceeded_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 2 ** 128; - message.tokenAmounts[0].token = s_sourceTokens[0]; - - IERC20(s_sourceTokens[0]).approve(address(s_onRamp), 2 ** 128); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueMaxCapacityExceeded.selector, - getOutboundRateLimiterConfig().capacity, - (message.tokenAmounts[0].amount * s_sourceTokenPrices[0]) / 1e18 - ) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_PriceNotFoundForToken_Revert() public { - // Set token price to 0 - vm.stopPrank(); - vm.startPrank(OWNER); - s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, 0)); - - vm.startPrank(address(s_sourceRouter)); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].token = CUSTOM_TOKEN; - message.tokenAmounts[0].amount = 1; - - vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, CUSTOM_TOKEN)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.MessageGasLimitTooHigh.selector)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_InvalidAddressEncodePacked_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encodePacked(address(234)); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); - } - - function test_InvalidAddress_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(type(uint208).max); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); - } - - // We disallow sending to addresses 0-9. - function test_ZeroAddressReceiver_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - for (uint160 i = 0; i < 10; ++i) { - message.receiver = abi.encode(address(i)); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); - } - } - - function test_MaxFeeBalanceReached_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectRevert(EVM2EVMOnRamp.MaxFeeBalanceReached.selector); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_NOP_FEES_JUELS + 1, OWNER); - } - - function test_InvalidChainSelector_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint64 wrongChainSelector = DEST_CHAIN_SELECTOR + 1; - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.InvalidChainSelector.selector, wrongChainSelector)); - - s_onRamp.forwardFromRouter(wrongChainSelector, message, 1, OWNER); - } - - function test_SourceTokenDataTooLarge_Revert() public { - address sourceETH = s_sourceTokens[1]; - vm.stopPrank(); - vm.startPrank(OWNER); - - MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMN), address(s_sourceRouter) - ); - BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); - deal(address(sourceETH), address(newPool), type(uint256).max); - - // Add TokenPool to OnRamp - s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); - - // Allow chain in TokenPool - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - newPool.applyChainUpdates(chainUpdates); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); - - // No data set, should succeed - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set max data length, should succeed - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES)); - - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set data to max length +1, should revert - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); - - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.SourceTokenDataTooLarge.selector, sourceETH)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set token config to allow larger data - vm.startPrank(OWNER); - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](1); - tokenTransferFeeConfigArgs[0] = EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: sourceETH, - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, - aggregateRateLimitEnabled: false - }); - s_onRamp.setTokenTransferFeeConfig(tokenTransferFeeConfigArgs, new address[](0)); - - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set the token data larger than the configured token data, should revert - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); - - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.SourceTokenDataTooLarge.selector, sourceETH)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_forwardFromRouter_UnsupportedToken_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1; - message.tokenAmounts[0].token = address(1); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_EnforceOutOfOrder_Revert() public { - // Update dynamic config to enforce allowOutOfOrderExecution = true. - vm.stopPrank(); - vm.startPrank(OWNER); - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - s_onRamp.setDynamicConfig( - EVM2EVMOnRamp.DynamicConfig({ - router: dynamicConfig.router, - maxNumberOfTokensPerMsg: dynamicConfig.maxNumberOfTokensPerMsg, - destGasOverhead: dynamicConfig.destGasOverhead, - destGasPerPayloadByte: dynamicConfig.destGasPerPayloadByte, - destDataAvailabilityOverheadGas: dynamicConfig.destDataAvailabilityOverheadGas, - destGasPerDataAvailabilityByte: dynamicConfig.destGasPerDataAvailabilityByte, - destDataAvailabilityMultiplierBps: dynamicConfig.destDataAvailabilityMultiplierBps, - priceRegistry: dynamicConfig.priceRegistry, - maxDataBytes: dynamicConfig.maxDataBytes, - maxPerMsgGasLimit: dynamicConfig.maxPerMsgGasLimit, - defaultTokenFeeUSDCents: dynamicConfig.defaultTokenFeeUSDCents, - defaultTokenDestGasOverhead: dynamicConfig.defaultTokenDestGasOverhead, - defaultTokenDestBytesOverhead: dynamicConfig.defaultTokenDestBytesOverhead, - enforceOutOfOrder: true - }) - ); - vm.stopPrank(); - - vm.startPrank(address(s_sourceRouter)); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - // Empty extraArgs to should revert since it enforceOutOfOrder is true. - message.extraArgs = ""; - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectRevert(EVM2EVMOnRamp.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } -} - -contract EVM2EVMOnRamp_forwardFromRouter_upgrade is EVM2EVMOnRampSetup { - uint256 internal constant FEE_AMOUNT = 1234567890; - EVM2EVMOnRampHelper internal s_prevOnRamp; - - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - - s_prevOnRamp = s_onRamp; - - s_onRamp = new EVM2EVMOnRampHelper( - EVM2EVMOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], - chainSelector: SOURCE_CHAIN_SELECTOR, - destChainSelector: DEST_CHAIN_SELECTOR, - defaultTxGasLimit: GAS_LIMIT, - maxNopFeesJuels: MAX_NOP_FEES_JUELS, - prevOnRamp: address(s_prevOnRamp), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - generateDynamicOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - getOutboundRateLimiterConfig(), - s_feeTokenConfigArgs, - s_tokenTransferFeeConfigArgs, - getNopsAndWeights() - ); - s_onRamp.setAdmin(ADMIN); - - s_metadataHash = keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, address(s_onRamp)) - ); - - vm.startPrank(address(s_sourceRouter)); - } - - function test_V2_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - } - - function test_V2SenderNoncesReadsPreviousRamp_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 startNonce = s_onRamp.getSenderNonce(OWNER); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - assertEq(startNonce + i, s_onRamp.getSenderNonce(OWNER)); - } - } - - function test_V2NonceStartsAtV1Nonce_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint64 startNonce = s_onRamp.getSenderNonce(OWNER); - - // send 1 message from previous onramp - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 1, s_onRamp.getSenderNonce(OWNER)); - - // new onramp nonce should start from 2, while sequence number start from 1 - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 2, s_onRamp.getSenderNonce(OWNER)); - - // after another send, nonce should be 3, and sequence number be 2 - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 3, s_onRamp.getSenderNonce(OWNER)); - } - - function test_V2NonceNewSenderStartsAtZero_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - // send 1 message from previous onramp from OWNER - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - address newSender = address(1234567); - // new onramp nonce should start from 1 for new sender - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(_messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); - } -} - -contract EVM2EVMOnRamp_getFeeSetup is EVM2EVMOnRampSetup { - uint224 internal s_feeTokenPrice; - uint224 internal s_wrappedTokenPrice; - uint224 internal s_customTokenPrice; - - address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); - - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - - // Add additional pool addresses for test tokens to mark them as supported - s_tokenAdminRegistry.proposeAdministrator(s_sourceRouter.getWrappedNative(), OWNER); - s_tokenAdminRegistry.acceptAdminRole(s_sourceRouter.getWrappedNative()); - s_tokenAdminRegistry.proposeAdministrator(CUSTOM_TOKEN, OWNER); - s_tokenAdminRegistry.acceptAdminRole(CUSTOM_TOKEN); - - LockReleaseTokenPool wrappedNativePool = new LockReleaseTokenPool( - IERC20(s_sourceRouter.getWrappedNative()), new address[](0), address(s_mockRMN), true, address(s_sourceRouter) - ); - - TokenPool.ChainUpdate[] memory wrappedNativeChainUpdate = new TokenPool.ChainUpdate[](1); - wrappedNativeChainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(address(111111)), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - wrappedNativePool.applyChainUpdates(wrappedNativeChainUpdate); - s_tokenAdminRegistry.setPool(s_sourceRouter.getWrappedNative(), address(wrappedNativePool)); - - LockReleaseTokenPool customPool = new LockReleaseTokenPool( - IERC20(CUSTOM_TOKEN), new address[](0), address(s_mockRMN), true, address(s_sourceRouter) - ); - TokenPool.ChainUpdate[] memory customChainUpdate = new TokenPool.ChainUpdate[](1); - customChainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(makeAddr("random")), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - customPool.applyChainUpdates(customChainUpdate); - s_tokenAdminRegistry.setPool(CUSTOM_TOKEN, address(customPool)); - - s_feeTokenPrice = s_sourceTokenPrices[0]; - s_wrappedTokenPrice = s_sourceTokenPrices[2]; - s_customTokenPrice = CUSTOM_TOKEN_PRICE; - - // Ensure the self-serve token is set up on the admin registry - vm.mockCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, s_selfServeTokenDefaultPricing), - abi.encode(makeAddr("self-serve-pool")) - ); - } - - function calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { - return (tokenPrice * tokenAmount) / 1e18; - } - - function applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { - return (tokenAmount * ratio) / 1e5; - } - - function configUSDCentToWei(uint256 usdCent) internal pure returns (uint256) { - return usdCent * 1e16; - } -} - -contract EVM2EVMOnRamp_getDataAvailabilityCost is EVM2EVMOnRamp_getFeeSetup { - function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public view { - uint256 dataAvailabilityCostUSD = s_onRamp.getDataAvailabilityCost(USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - - uint256 dataAvailabilityGas = dynamicConfig.destDataAvailabilityOverheadGas - + dynamicConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; - uint256 expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * dynamicConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } - - function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { - uint256 dataAvailabilityCostUSD = s_onRamp.getDataAvailabilityCost(USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - - uint256 dataAvailabilityLengthBytes = - Internal.MESSAGE_FIXED_BYTES + 100 + (5 * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; - uint256 dataAvailabilityGas = dynamicConfig.destDataAvailabilityOverheadGas - + dynamicConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * dynamicConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } - - function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public view { - uint256 dataAvailabilityCostUSD = - s_onRamp.getDataAvailabilityCost(0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead); - - assertEq(0, dataAvailabilityCostUSD); - } - - function test_Fuzz_CalculateDataAvailabilityCost_Success( - uint32 destDataAvailabilityOverheadGas, - uint16 destGasPerDataAvailabilityByte, - uint16 destDataAvailabilityMultiplierBps, - uint112 dataAvailabilityGasPrice, - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public { - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - dynamicConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; - dynamicConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; - dynamicConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; - s_onRamp.setDynamicConfig(dynamicConfig); - - uint256 dataAvailabilityCostUSD = s_onRamp.getDataAvailabilityCost( - dataAvailabilityGasPrice, messageDataLength, numberOfTokens, tokenTransferBytesOverhead - ); - - uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - uint256 dataAvailabilityGas = - destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } -} - -contract EVM2EVMOnRamp_getSupportedTokens is EVM2EVMOnRampSetup { - function test_GetSupportedTokens_Revert() public { - vm.expectRevert(EVM2EVMOnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); - s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); - } -} - -contract EVM2EVMOnRamp_getTokenTransferCost is EVM2EVMOnRamp_getFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_NoTokenTransferChargesZeroFee_Success() public view { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(0, feeUSDWei); - assertEq(0, destGasOverhead); - assertEq(0, destBytesOverhead); - } - - function test__getTokenTransferCost_selfServeUsesDefaults_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); - - // Get config to assert it isn't set - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - assertFalse(transferFeeConfig.isEnabled); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // Assert that the default values are used - assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); - assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); - assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); - } - - function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_FeeTokenBpsFee_Success() public view { - uint256 tokenAmount = 10000e18; - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); - uint256 bpsUSDWei = applyBpsRatio(usdWei, s_tokenTransferFeeConfigArgs[0].deciBps); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_WETHTokenBpsFee_Success() public view { - uint256 tokenAmount = 100e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceRouter.getWrappedNative(), amount: tokenAmount}); - - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_wrappedTokenPrice, tokenAmount); - uint256 bpsUSDWei = applyBpsRatio(usdWei, s_tokenTransferFeeConfigArgs[1].deciBps); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_CustomTokenBpsFee_Success() public view { - uint256 tokenAmount = 200000e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); - - EVM2EVMOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); - uint256 bpsUSDWei = applyBpsRatio(usdWei, s_tokenTransferFeeConfigArgs[2].deciBps); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroFeeConfigChargesMinFee_Success() public { - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](1); - tokenTransferFeeConfigArgs[0] = EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: s_sourceFeeToken, - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), - aggregateRateLimitEnabled: true - }); - s_onRamp.setTokenTransferFeeConfig(tokenTransferFeeConfigArgs, new address[](0)); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // if token charges 0 bps, it should cost minFee to transfer - assertEq(configUSDCentToWei(tokenTransferFeeConfigArgs[0].minFeeUSDCents), feeUSDWei); - assertEq(0, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { - // It shouldn't be possible to pay materially lower fees by splitting up the transfers. - // Note it is possible to pay higher fees since the minimum fees are added. - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - transfers = bound(transfers, 1, dynamicConfig.maxNumberOfTokensPerMsg); - // Cap amount to avoid overflow - amount = bound(amount, 0, 1e36); - Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); - for (uint256 i = 0; i < transfers; ++i) { - multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); - } - Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); - single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); - - address feeToken = s_sourceRouter.getWrappedNative(); - - (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = - s_onRamp.getTokenTransferCost(feeToken, s_wrappedTokenPrice, single); - (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = - s_onRamp.getTokenTransferCost(feeToken, s_wrappedTokenPrice, multiple); - - // Note that there can be a rounding error once per split. - assertTrue(feeMultipleUSDWei >= (feeSingleUSDWei - dynamicConfig.maxNumberOfTokensPerMsg)); - assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); - assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); - } - - function test_MixedTokenTransferFee_Success() public view { - address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; - uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; - EVM2EVMOnRamp.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ - s_onRamp.getTokenTransferFeeConfig(testTokens[0]), - s_onRamp.getTokenTransferFeeConfig(testTokens[1]), - s_onRamp.getTokenTransferFeeConfig(testTokens[2]) - ]; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](3), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - uint256 expectedTotalGas = 0; - uint256 expectedTotalBytes = 0; - - // Start with small token transfers, total bps fee is lower than min token transfer fee - for (uint256 i = 0; i < testTokens.length; ++i) { - message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); - expectedTotalGas += s_onRamp.getTokenTransferFeeConfig(testTokens[i]).destGasOverhead; - uint32 dstBytesOverhead = s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[i].token).destBytesOverhead; - expectedTotalBytes += dstBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : dstBytesOverhead; - } - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - - uint256 expectedFeeUSDWei = 0; - for (uint256 i = 0; i < testTokens.length; ++i) { - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[i].minFeeUSDCents); - } - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - - // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee - message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - expectedFeeUSDWei = applyBpsRatio( - calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].minFeeUSDCents); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - - // Set 2nd token transfer to a large amount that is higher than maxFeeUSD - message.tokenAmounts[1] = Client.EVMTokenAmount({token: testTokens[1], amount: 1e36}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = - s_onRamp.getTokenTransferCost(message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - expectedFeeUSDWei = applyBpsRatio( - calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].maxFeeUSDCents); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - } - - // reverts - - function test_UnsupportedToken_Revert() public { - address NOT_SUPPORTED_TOKEN = address(123); - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(NOT_SUPPORTED_TOKEN, 200); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.UnsupportedToken.selector, NOT_SUPPORTED_TOKEN)); - - s_onRamp.getTokenTransferCost(message.feeToken, s_feeTokenPrice, message.tokenAmounts); - } -} - -contract EVM2EVMOnRamp_getFee is EVM2EVMOnRamp_getFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_EmptyMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = testTokens[i]; - EVM2EVMOnRamp.FeeTokenConfig memory feeTokenConfig = s_onRamp.getFeeTokenConfig(message.feeToken); - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * feeTokenConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = - (configUSDCentToWei(feeTokenConfig.networkFeeUSDCents) * feeTokenConfig.premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_ZeroDataAvailabilityMultiplier_Success() public { - EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - dynamicConfig.destDataAvailabilityMultiplierBps = 0; - s_onRamp.setDynamicConfig(dynamicConfig); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - EVM2EVMOnRamp.FeeTokenConfig memory feeTokenConfig = s_onRamp.getFeeTokenConfig(message.feeToken); - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * feeTokenConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = - (configUSDCentToWei(feeTokenConfig.networkFeeUSDCents) * feeTokenConfig.premiumMultiplierWeiPerEth); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; - assertEq(totalPriceInFeeToken, feeAmount); - } - - function test_HighGasMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = MAX_GAS_LIMIT; - uint256 customDataSize = MAX_DATA_SIZE; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: new bytes(customDataSize), - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - - EVM2EVMOnRamp.FeeTokenConfig memory feeTokenConfig = s_onRamp.getFeeTokenConfig(message.feeToken); - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; - uint256 gasFeeUSD = (gasUsed * feeTokenConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = - (configUSDCentToWei(feeTokenConfig.networkFeeUSDCents) * feeTokenConfig.premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_SingleTokenMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 tokenAmount = 10000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - message.feeToken = testTokens[i]; - EVM2EVMOnRamp.FeeTokenConfig memory feeTokenConfig = s_onRamp.getFeeTokenConfig(message.feeToken); - uint32 tokenGasOverhead = s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token).destGasOverhead; - uint32 destBytesOverhead = s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[0].token).destBytesOverhead; - uint32 tokenBytesOverhead = - destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + tokenGasOverhead; - uint256 gasFeeUSD = (gasUsed * feeTokenConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = - s_onRamp.getTokenTransferCost(message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * feeTokenConfig.premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_MessageWithDataAndTokenTransfer_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = 1_000_000; - uint256 feeTokenAmount = 10000e18; - uint256 customTokenAmount = 200000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](2), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - EVM2EVMOnRamp.FeeTokenConfig memory feeTokenConfig = s_onRamp.getFeeTokenConfig(message.feeToken); - - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: feeTokenAmount}); - message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: customTokenAmount}); - message.data = "random bits and bytes that should be factored into the cost of the message"; - - uint32 tokenGasOverhead = 0; - uint32 tokenBytesOverhead = 0; - for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { - tokenGasOverhead += s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[j].token).destGasOverhead; - uint32 destBytesOverhead = s_onRamp.getTokenTransferFeeConfig(message.tokenAmounts[j].token).destBytesOverhead; - tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - } - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = - customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; - uint256 gasFeeUSD = (gasUsed * feeTokenConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = - s_onRamp.getTokenTransferCost(message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * feeTokenConfig.premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - // Reverts - - function test_NotAFeeToken_Revert() public { - address notAFeeToken = address(0x111111); - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); - message.feeToken = notAFeeToken; - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.NotAFeeToken.selector, notAFeeToken)); - - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_MessageTooLarge_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); - - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_TooManyTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 tooMany = MAX_TOKENS_LENGTH + 1; - message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(EVM2EVMOnRamp.UnsupportedNumberOfTokens.selector); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.MessageGasLimitTooHigh.selector)); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract EVM2EVMOnRamp_setNops is EVM2EVMOnRampSetup { - // Used because EnumerableMap doesn't guarantee order - mapping(address nop => uint256 weight) internal s_nopsToWeights; - - function test_SetNops_Success() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = getNopsAndWeights(); - nopsAndWeights[1].nop = USER_4; - nopsAndWeights[1].weight = 20; - for (uint256 i = 0; i < nopsAndWeights.length; ++i) { - s_nopsToWeights[nopsAndWeights[i].nop] = nopsAndWeights[i].weight; - } - - s_onRamp.setNops(nopsAndWeights); - - (EVM2EVMOnRamp.NopAndWeight[] memory actual,) = s_onRamp.getNops(); - for (uint256 i = 0; i < actual.length; ++i) { - assertEq(actual[i].weight, s_nopsToWeights[actual[i].nop]); - } - } - - function test_AdminCanSetNops_Success() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = getNopsAndWeights(); - // Should not revert - vm.startPrank(ADMIN); - s_onRamp.setNops(nopsAndWeights); - } - - function test_IncludesPayment_Success() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = getNopsAndWeights(); - nopsAndWeights[1].nop = USER_4; - nopsAndWeights[1].weight = 20; - uint32 totalWeight; - for (uint256 i = 0; i < nopsAndWeights.length; ++i) { - totalWeight += nopsAndWeights[i].weight; - s_nopsToWeights[nopsAndWeights[i].nop] = nopsAndWeights[i].weight; - } - - // Make sure a payout happens regardless of what the weights are set to - uint96 nopFeesJuels = totalWeight * 5; - // Set Nop fee juels - deal(s_sourceFeeToken, address(s_onRamp), nopFeesJuels); - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), nopFeesJuels, OWNER); - vm.startPrank(OWNER); - - // We don't care about the fee calculation logic in this test - // so we don't verify the amounts. We do verify the addresses to - // make sure the existing nops get paid and not the new ones. - EVM2EVMOnRamp.NopAndWeight[] memory existingNopsAndWeights = getNopsAndWeights(); - for (uint256 i = 0; i < existingNopsAndWeights.length; ++i) { - vm.expectEmit(true, false, false, false); - emit EVM2EVMOnRamp.NopPaid(existingNopsAndWeights[i].nop, 0); - } - - s_onRamp.setNops(nopsAndWeights); - - (EVM2EVMOnRamp.NopAndWeight[] memory actual,) = s_onRamp.getNops(); - for (uint256 i = 0; i < actual.length; ++i) { - assertEq(actual[i].weight, s_nopsToWeights[actual[i].nop]); - } - } - - function test_SetNopsRemovesOldNopsCompletely_Success() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](0); - s_onRamp.setNops(nopsAndWeights); - (EVM2EVMOnRamp.NopAndWeight[] memory actual, uint256 totalWeight) = s_onRamp.getNops(); - assertEq(actual.length, 0); - assertEq(totalWeight, 0); - - address prevNop = getNopsAndWeights()[0].nop; - vm.startPrank(prevNop); - - // prev nop should not have permission to call payNops - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdminOrNop.selector); - s_onRamp.payNops(); - } - - // Reverts - - function test_NotEnoughFundsForPayout_Revert() public { - uint96 nopFeesJuels = MAX_NOP_FEES_JUELS; - // Set Nop fee juels but don't transfer LINK. This can happen when users - // pay in non-link tokens. - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), nopFeesJuels, OWNER); - vm.startPrank(OWNER); - - vm.expectRevert(EVM2EVMOnRamp.InsufficientBalance.selector); - - s_onRamp.setNops(getNopsAndWeights()); - } - - function test_NonOwnerOrAdmin_Revert() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = getNopsAndWeights(); - vm.startPrank(STRANGER); - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdmin.selector); - s_onRamp.setNops(nopsAndWeights); - } - - function test_LinkTokenCannotBeNop_Revert() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = getNopsAndWeights(); - nopsAndWeights[0].nop = address(s_sourceTokens[0]); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.InvalidNopAddress.selector, address(s_sourceTokens[0]))); - - s_onRamp.setNops(nopsAndWeights); - } - - function test_ZeroAddressCannotBeNop_Revert() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = getNopsAndWeights(); - nopsAndWeights[0].nop = address(0); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.InvalidNopAddress.selector, address(0))); - - s_onRamp.setNops(nopsAndWeights); - } - - function test_TooManyNops_Revert() public { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](257); - - vm.expectRevert(EVM2EVMOnRamp.TooManyNops.selector); - - s_onRamp.setNops(nopsAndWeights); - } -} - -contract EVM2EVMOnRamp_withdrawNonLinkFees is EVM2EVMOnRampSetup { - IERC20 internal s_token; - - function setUp() public virtual override { - EVM2EVMOnRampSetup.setUp(); - // Send some non-link tokens to the onRamp - s_token = IERC20(s_sourceTokens[1]); - deal(s_sourceTokens[1], address(s_onRamp), 100); - } - - function test_WithdrawNonLinkFees_Success() public { - s_onRamp.withdrawNonLinkFees(address(s_token), address(this)); - - assertEq(0, s_token.balanceOf(address(s_onRamp))); - assertEq(100, s_token.balanceOf(address(this))); - } - - function test_SettlingBalance_Success() public { - // Set Nop fee juels - uint96 nopFeesJuels = 10000000; - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), nopFeesJuels, OWNER); - vm.startPrank(OWNER); - - vm.expectRevert(EVM2EVMOnRamp.LinkBalanceNotSettled.selector); - s_onRamp.withdrawNonLinkFees(address(s_token), address(this)); - - // It doesnt matter how the link tokens get to the onRamp - // In this case we simply deal them to the ramp to show - // anyone can settle the balance - deal(s_sourceTokens[0], address(s_onRamp), nopFeesJuels); - - s_onRamp.withdrawNonLinkFees(address(s_token), address(this)); - } - - function test_Fuzz_FuzzWithdrawalOnlyLeftoverLink_Success(uint96 nopFeeJuels, uint64 extraJuels) public { - nopFeeJuels = uint96(bound(nopFeeJuels, 1, MAX_NOP_FEES_JUELS)); - - // Set Nop fee juels - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), nopFeeJuels, OWNER); - vm.startPrank(OWNER); - - vm.expectRevert(EVM2EVMOnRamp.LinkBalanceNotSettled.selector); - s_onRamp.withdrawNonLinkFees(address(s_token), address(this)); - - address linkToken = s_sourceTokens[0]; - // It doesnt matter how the link tokens get to the onRamp - // In this case we simply deal them to the ramp to show - // anyone can settle the balance - deal(linkToken, address(s_onRamp), nopFeeJuels + uint96(extraJuels)); - - // Now that we've sent nopFeesJuels + extraJuels, we should be able to withdraw extraJuels - address linkRecipient = address(0x123456789); - assertEq(0, IERC20(linkToken).balanceOf(linkRecipient)); - - s_onRamp.withdrawNonLinkFees(linkToken, linkRecipient); - - assertEq(extraJuels, IERC20(linkToken).balanceOf(linkRecipient)); - } - - // Reverts - - function test_LinkBalanceNotSettled_Revert() public { - // Set Nop fee juels - uint96 nopFeesJuels = 10000000; - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), nopFeesJuels, OWNER); - vm.startPrank(OWNER); - - vm.expectRevert(EVM2EVMOnRamp.LinkBalanceNotSettled.selector); - - s_onRamp.withdrawNonLinkFees(address(s_token), address(this)); - } - - function test_NonOwnerOrAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdmin.selector); - s_onRamp.withdrawNonLinkFees(address(s_token), address(this)); - } - - function test_WithdrawToZeroAddress_Revert() public { - vm.expectRevert(EVM2EVMOnRamp.InvalidWithdrawParams.selector); - s_onRamp.withdrawNonLinkFees(address(s_token), address(0)); - } -} - -contract EVM2EVMOnRamp_setFeeTokenConfig is EVM2EVMOnRampSetup { - function test_SetFeeTokenConfig_Success() public { - EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeConfig; - - vm.expectEmit(); - emit EVM2EVMOnRamp.FeeConfigSet(feeConfig); - - s_onRamp.setFeeTokenConfig(feeConfig); - } - - function test_SetFeeTokenConfigByAdmin_Success() public { - EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeConfig; - - vm.startPrank(ADMIN); - - vm.expectEmit(); - emit EVM2EVMOnRamp.FeeConfigSet(feeConfig); - - s_onRamp.setFeeTokenConfig(feeConfig); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeConfig; - vm.startPrank(STRANGER); - - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdmin.selector); - - s_onRamp.setFeeTokenConfig(feeConfig); - } -} - -contract EVM2EVMOnRamp_setTokenTransferFeeConfig is EVM2EVMOnRampSetup { - function test__setTokenTransferFeeConfig_Success() public { - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeArgs = - new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](2); - tokenTransferFeeArgs[0] = EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: address(5), - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: 312, - aggregateRateLimitEnabled: true - }); - tokenTransferFeeArgs[1] = EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: address(11), - minFeeUSDCents: 12, - maxFeeUSDCents: 13, - deciBps: 14, - destGasOverhead: 15, - destBytesOverhead: 394, - aggregateRateLimitEnabled: false - }); - - vm.expectEmit(); - emit EVM2EVMOnRamp.TokenTransferFeeConfigSet(tokenTransferFeeArgs); - - s_onRamp.setTokenTransferFeeConfig(tokenTransferFeeArgs, new address[](0)); - - EVM2EVMOnRamp.TokenTransferFeeConfig memory config0 = - s_onRamp.getTokenTransferFeeConfig(tokenTransferFeeArgs[0].token); - - assertEq(tokenTransferFeeArgs[0].minFeeUSDCents, config0.minFeeUSDCents); - assertEq(tokenTransferFeeArgs[0].maxFeeUSDCents, config0.maxFeeUSDCents); - assertEq(tokenTransferFeeArgs[0].deciBps, config0.deciBps); - assertEq(tokenTransferFeeArgs[0].destGasOverhead, config0.destGasOverhead); - assertEq(tokenTransferFeeArgs[0].destBytesOverhead, config0.destBytesOverhead); - assertEq(tokenTransferFeeArgs[0].aggregateRateLimitEnabled, config0.aggregateRateLimitEnabled); - assertTrue(config0.isEnabled); - - EVM2EVMOnRamp.TokenTransferFeeConfig memory config1 = - s_onRamp.getTokenTransferFeeConfig(tokenTransferFeeArgs[1].token); - - assertEq(tokenTransferFeeArgs[1].minFeeUSDCents, config1.minFeeUSDCents); - assertEq(tokenTransferFeeArgs[1].maxFeeUSDCents, config1.maxFeeUSDCents); - assertEq(tokenTransferFeeArgs[1].deciBps, config1.deciBps); - assertEq(tokenTransferFeeArgs[1].destGasOverhead, config1.destGasOverhead); - assertEq(tokenTransferFeeArgs[1].destBytesOverhead, config1.destBytesOverhead); - assertEq(tokenTransferFeeArgs[1].aggregateRateLimitEnabled, config1.aggregateRateLimitEnabled); - assertTrue(config0.isEnabled); - - // Remove only the first token and validate only the first token is removed - address[] memory tokensToRemove = new address[](1); - tokensToRemove[0] = tokenTransferFeeArgs[0].token; - - vm.expectEmit(); - emit EVM2EVMOnRamp.TokenTransferFeeConfigDeleted(tokensToRemove); - - s_onRamp.setTokenTransferFeeConfig(new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](0), tokensToRemove); - - config0 = s_onRamp.getTokenTransferFeeConfig(tokenTransferFeeArgs[0].token); - - assertEq(0, config0.minFeeUSDCents); - assertEq(0, config0.maxFeeUSDCents); - assertEq(0, config0.deciBps); - assertEq(0, config0.destGasOverhead); - assertEq(0, config0.destBytesOverhead); - assertFalse(config0.aggregateRateLimitEnabled); - assertFalse(config0.isEnabled); - - config1 = s_onRamp.getTokenTransferFeeConfig(tokenTransferFeeArgs[1].token); - - assertEq(tokenTransferFeeArgs[1].minFeeUSDCents, config1.minFeeUSDCents); - assertEq(tokenTransferFeeArgs[1].maxFeeUSDCents, config1.maxFeeUSDCents); - assertEq(tokenTransferFeeArgs[1].deciBps, config1.deciBps); - assertEq(tokenTransferFeeArgs[1].destGasOverhead, config1.destGasOverhead); - assertEq(tokenTransferFeeArgs[1].destBytesOverhead, config1.destBytesOverhead); - assertEq(tokenTransferFeeArgs[1].aggregateRateLimitEnabled, config1.aggregateRateLimitEnabled); - assertTrue(config1.isEnabled); - } - - function test__setTokenTransferFeeConfig_byAdmin_Success() public { - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory transferFeeConfig; - vm.startPrank(ADMIN); - - vm.expectEmit(); - emit EVM2EVMOnRamp.TokenTransferFeeConfigSet(transferFeeConfig); - - s_onRamp.setTokenTransferFeeConfig(transferFeeConfig, new address[](0)); - } - - // Reverts - - function test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() public { - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory transferFeeConfig = - new EVM2EVMOnRamp.TokenTransferFeeConfigArgs[](1); - transferFeeConfig[0].destBytesOverhead = uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) - 1; - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMOnRamp.InvalidDestBytesOverhead.selector, - transferFeeConfig[0].token, - transferFeeConfig[0].destBytesOverhead - ) - ); - s_onRamp.setTokenTransferFeeConfig(transferFeeConfig, new address[](0)); - } - - function test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() public { - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] memory transferFeeConfig; - vm.startPrank(STRANGER); - - vm.expectRevert(EVM2EVMOnRamp.OnlyCallableByOwnerOrAdmin.selector); - - s_onRamp.setTokenTransferFeeConfig(transferFeeConfig, new address[](0)); - } -} - -contract EVM2EVMOnRamp_getTokenPool is EVM2EVMOnRampSetup { - function test_GetTokenPool_Success() public view { - assertEq( - s_sourcePoolByToken[s_sourceTokens[0]], - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) - ); - assertEq( - s_sourcePoolByToken[s_sourceTokens[1]], - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[1]))) - ); - - address wrongToken = address(123); - address nonExistentPool = address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(wrongToken))); - - assertEq(address(0), nonExistentPool); - } -} - -contract EVM2EVMOnRamp_setDynamicConfig is EVM2EVMOnRampSetup { - function test_SetDynamicConfig_Success() public { - EVM2EVMOnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); - EVM2EVMOnRamp.DynamicConfig memory newConfig = EVM2EVMOnRamp.DynamicConfig({ - router: address(2134), - maxNumberOfTokensPerMsg: 14, - destGasOverhead: DEST_GAS_OVERHEAD / 2, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE / 2, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - priceRegistry: address(23423), - maxDataBytes: 400, - maxPerMsgGasLimit: MAX_GAS_LIMIT / 2, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, - enforceOutOfOrder: false - }); - - vm.expectEmit(); - emit EVM2EVMOnRamp.ConfigSet(staticConfig, newConfig); - - s_onRamp.setDynamicConfig(newConfig); - - EVM2EVMOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - assertEq(newConfig.router, gotDynamicConfig.router); - assertEq(newConfig.maxNumberOfTokensPerMsg, gotDynamicConfig.maxNumberOfTokensPerMsg); - assertEq(newConfig.destGasOverhead, gotDynamicConfig.destGasOverhead); - assertEq(newConfig.destGasPerPayloadByte, gotDynamicConfig.destGasPerPayloadByte); - assertEq(newConfig.priceRegistry, gotDynamicConfig.priceRegistry); - assertEq(newConfig.maxDataBytes, gotDynamicConfig.maxDataBytes); - assertEq(newConfig.maxPerMsgGasLimit, gotDynamicConfig.maxPerMsgGasLimit); - } - - // Reverts - - function test_SetConfigInvalidConfig_Revert() public { - EVM2EVMOnRamp.DynamicConfig memory newConfig = EVM2EVMOnRamp.DynamicConfig({ - router: address(1), - maxNumberOfTokensPerMsg: 14, - destGasOverhead: DEST_GAS_OVERHEAD / 2, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE / 2, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - priceRegistry: address(23423), - maxDataBytes: 400, - maxPerMsgGasLimit: MAX_GAS_LIMIT / 2, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, - enforceOutOfOrder: false - }); - - // Invalid price reg reverts. - newConfig.priceRegistry = address(0); - vm.expectRevert(EVM2EVMOnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - - // Succeeds if valid - newConfig.priceRegistry = address(23423); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_SetConfigOnlyOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_onRamp.setDynamicConfig(generateDynamicOnRampConfig(address(1), address(2))); - vm.startPrank(ADMIN); - vm.expectRevert("Only callable by owner"); - s_onRamp.setDynamicConfig(generateDynamicOnRampConfig(address(1), address(2))); - } -} diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol deleted file mode 100644 index 6659b1217fd..00000000000 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol +++ /dev/null @@ -1,261 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPoolV1} from "../../interfaces/IPool.sol"; - -import {PriceRegistry} from "../../PriceRegistry.sol"; -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; -import {EVM2EVMOnRampHelper} from "../helpers/EVM2EVMOnRampHelper.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract EVM2EVMOnRampSetup is TokenSetup, PriceRegistrySetup { - uint256 internal immutable i_tokenAmount0 = 9; - uint256 internal immutable i_tokenAmount1 = 7; - - bytes32 internal s_metadataHash; - - EVM2EVMOnRampHelper internal s_onRamp; - address[] internal s_offRamps; - - address internal s_destTokenPool = makeAddr("destTokenPool"); - address internal s_destToken = makeAddr("destToken"); - - EVM2EVMOnRamp.FeeTokenConfigArgs[] internal s_feeTokenConfigArgs; - EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] internal s_tokenTransferFeeConfigArgs; - - function setUp() public virtual override(TokenSetup, PriceRegistrySetup) { - TokenSetup.setUp(); - PriceRegistrySetup.setUp(); - - s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); - - address WETH = s_sourceRouter.getWrappedNative(); - - s_feeTokenConfigArgs.push( - EVM2EVMOnRamp.FeeTokenConfigArgs({ - token: s_sourceFeeToken, - networkFeeUSDCents: 1_00, // 1 USD - gasMultiplierWeiPerEth: 1e18, // 1x - premiumMultiplierWeiPerEth: 5e17, // 0.5x - enabled: true - }) - ); - s_feeTokenConfigArgs.push( - EVM2EVMOnRamp.FeeTokenConfigArgs({ - token: WETH, - networkFeeUSDCents: 5_00, // 5 USD - gasMultiplierWeiPerEth: 2e18, // 2x - premiumMultiplierWeiPerEth: 2e18, // 2x - enabled: true - }) - ); - - s_tokenTransferFeeConfigArgs.push( - EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: s_sourceFeeToken, - minFeeUSDCents: 1_00, // 1 USD - maxFeeUSDCents: 1000_00, // 1,000 USD - deciBps: 2_5, // 2.5 bps, or 0.025% - destGasOverhead: 40_000, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), - aggregateRateLimitEnabled: true - }) - ); - s_tokenTransferFeeConfigArgs.push( - EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: s_sourceRouter.getWrappedNative(), - minFeeUSDCents: 50, // 0.5 USD - maxFeeUSDCents: 500_00, // 500 USD - deciBps: 5_0, // 5 bps, or 0.05% - destGasOverhead: 10_000, - destBytesOverhead: 100, - aggregateRateLimitEnabled: true - }) - ); - s_tokenTransferFeeConfigArgs.push( - EVM2EVMOnRamp.TokenTransferFeeConfigArgs({ - token: CUSTOM_TOKEN, - minFeeUSDCents: 2_00, // 1 USD - maxFeeUSDCents: 2000_00, // 1,000 USD - deciBps: 10_0, // 10 bps, or 0.1% - destGasOverhead: 1, - destBytesOverhead: 200, - aggregateRateLimitEnabled: true - }) - ); - - s_onRamp = new EVM2EVMOnRampHelper( - EVM2EVMOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], - chainSelector: SOURCE_CHAIN_SELECTOR, - destChainSelector: DEST_CHAIN_SELECTOR, - defaultTxGasLimit: GAS_LIMIT, - maxNopFeesJuels: MAX_NOP_FEES_JUELS, - prevOnRamp: address(0), - rmnProxy: address(s_mockRMN), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - generateDynamicOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - getOutboundRateLimiterConfig(), - s_feeTokenConfigArgs, - s_tokenTransferFeeConfigArgs, - getNopsAndWeights() - ); - s_onRamp.setAdmin(ADMIN); - - s_metadataHash = keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, address(s_onRamp)) - ); - - s_offRamps = new address[](2); - s_offRamps[0] = address(10); - s_offRamps[1] = address(11); - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp)}); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_offRamps[0]}); - offRampUpdates[1] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_offRamps[1]}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - - // Pre approve the first token so the gas estimates of the tests - // only cover actual gas usage from the ramps - IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 2 ** 128); - IERC20(s_sourceTokens[1]).approve(address(s_sourceRouter), 2 ** 128); - } - - function getNopsAndWeights() internal pure returns (EVM2EVMOnRamp.NopAndWeight[] memory) { - EVM2EVMOnRamp.NopAndWeight[] memory nopsAndWeights = new EVM2EVMOnRamp.NopAndWeight[](3); - nopsAndWeights[0] = EVM2EVMOnRamp.NopAndWeight({nop: USER_1, weight: 19284}); - nopsAndWeights[1] = EVM2EVMOnRamp.NopAndWeight({nop: USER_2, weight: 52935}); - nopsAndWeights[2] = EVM2EVMOnRamp.NopAndWeight({nop: USER_3, weight: 8}); - return nopsAndWeights; - } - - function generateDynamicOnRampConfig( - address router, - address priceRegistry - ) internal pure returns (EVM2EVMOnRamp.DynamicConfig memory) { - return EVM2EVMOnRamp.DynamicConfig({ - router: router, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - destGasOverhead: DEST_GAS_OVERHEAD, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - priceRegistry: priceRegistry, - maxDataBytes: MAX_DATA_SIZE, - maxPerMsgGasLimit: MAX_GAS_LIMIT, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, - enforceOutOfOrder: false - }); - } - - function _generateTokenMessage() public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - tokenAmounts[0].amount = i_tokenAmount0; - tokenAmounts[1].amount = i_tokenAmount1; - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _generateSingleTokenMessage( - address token, - uint256 amount - ) public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _messageToEvent( - Client.EVM2AnyMessage memory message, - uint64 seqNum, - uint64 nonce, - uint256 feeTokenAmount, - address originalSender - ) public view returns (Internal.EVM2EVMMessage memory) { - // Slicing is only available for calldata. So we have to build a new bytes array. - bytes memory args = new bytes(message.extraArgs.length - 4); - for (uint256 i = 4; i < message.extraArgs.length; ++i) { - args[i - 4] = message.extraArgs[i]; - } - uint256 numberOfTokens = message.tokenAmounts.length; - Client.EVMExtraArgsV2 memory extraArgs = _extraArgsFromBytes(bytes4(message.extraArgs), args); - Internal.EVM2EVMMessage memory messageEvent = Internal.EVM2EVMMessage({ - sequenceNumber: seqNum, - feeTokenAmount: feeTokenAmount, - sender: originalSender, - nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce, - gasLimit: extraArgs.gasLimit, - strict: false, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - receiver: abi.decode(message.receiver, (address)), - data: message.data, - tokenAmounts: message.tokenAmounts, - sourceTokenData: new bytes[](numberOfTokens), - feeToken: message.feeToken, - messageId: "" - }); - - for (uint256 i = 0; i < numberOfTokens; ++i) { - messageEvent.sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[message.tokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[message.tokenAmounts[i].token]), - extraData: "" - }) - ); - } - - messageEvent.messageId = Internal._hash(messageEvent, s_metadataHash); - return messageEvent; - } - - function _extraArgsFromBytes( - bytes4 sig, - bytes memory extraArgData - ) public pure returns (Client.EVMExtraArgsV2 memory) { - if (sig == Client.EVM_EXTRA_ARGS_V1_TAG) { - Client.EVMExtraArgsV1 memory extraArgsV1 = abi.decode(extraArgData, (Client.EVMExtraArgsV1)); - return Client.EVMExtraArgsV2({gasLimit: extraArgsV1.gasLimit, allowOutOfOrderExecution: false}); - } else if (sig == Client.EVM_EXTRA_ARGS_V2_TAG) { - return abi.decode(extraArgData, (Client.EVMExtraArgsV2)); - } else { - revert("Invalid extraArgs tag"); - } - } -} diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol new file mode 100644 index 00000000000..d7a50a7724e --- /dev/null +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -0,0 +1,1074 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; +import "./OnRampSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract OnRamp_constructor is OnRampSetup { + function test_Constructor_Success() public { + OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }); + OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); + + vm.expectEmit(); + emit OnRamp.ConfigSet(staticConfig, dynamicConfig); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + + _deployOnRamp(SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry)); + + OnRamp.StaticConfig memory gotStaticConfig = s_onRamp.getStaticConfig(); + _assertStaticConfigsEqual(staticConfig, gotStaticConfig); + + OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); + _assertDynamicConfigsEqual(dynamicConfig, gotDynamicConfig); + + // Initial values + assertEq("OnRamp 1.6.0-dev", s_onRamp.typeAndVersion()); + assertEq(OWNER, s_onRamp.owner()); + assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); + assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); + } + + function test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() public { + OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }); + + OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); + + // Creating a DestChainConfig and setting allowlistEnabled : true + OnRamp.DestChainConfigArgs[] memory destChainConfigs = new OnRamp.DestChainConfigArgs[](1); + destChainConfigs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowlistEnabled: true + }); + + vm.expectEmit(); + emit OnRamp.ConfigSet(staticConfig, dynamicConfig); + + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, true); + + OnRampHelper tempOnRamp = new OnRampHelper(staticConfig, dynamicConfig, destChainConfigs); + + // Sending a message and expecting revert as allowlist is enabled with no address in allowlist + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, OWNER)); + tempOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: 0, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } + + function test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp = new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: IRMNRemote(address(0)), + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } + + function test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(0), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } + + function test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(0) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } +} + +contract OnRamp_forwardFromRouter is OnRampSetup { + struct LegacyExtraArgs { + uint256 gasLimit; + bool strict; + } + + function setUp() public virtual override { + super.setUp(); + + address[] memory feeTokens = new address[](1); + feeTokens[0] = s_sourceTokens[1]; + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + + uint64[] memory destinationChainSelectors = new uint64[](1); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + address[] memory addAllowedList = new address[](1); + addAllowedList[0] = OWNER; + OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = 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); + + // Since we'll mostly be testing for valid calls from the router we'll + // mock all calls to be originating from the router and re-mock in + // tests that require failure. + vm.startPrank(address(s_sourceRouter)); + } + + function test_ForwardFromRouterSuccessCustomExtraArgs() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouter_Success_ConfigurableSourceRouter() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + // Change the source router for this lane + IRouter newRouter = IRouter(makeAddr("NEW ROUTER")); + vm.stopPrank(); + vm.prank(OWNER); + s_onRamp.applyDestChainConfigUpdates(_generateDestChainConfigArgs(newRouter)); + + // forward fails from wrong router + vm.prank(address(s_sourceRouter)); + vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + + // forward succeeds from correct router + vm.prank(address(newRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterSuccessLegacyExtraArgs() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = + abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V1_TAG, LegacyExtraArgs({gasLimit: GAS_LIMIT * 2, strict: true})); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + // We expect the message to be emitted with strict = false. + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterSuccessEmptyExtraArgs() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = ""; + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + // We expect the message to be emitted with strict = false. + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouter_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterExtraArgsV2_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: false}) + ); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) + ); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ShouldIncrementSeqNumAndNonce_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + for (uint64 i = 1; i < 4; ++i) { + uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, i, _messageToEvent(message, i, i, 0, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + assertEq(nonceAfter, nonceBefore + 1); + assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); + } + } + + function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) + ); + + for (uint64 i = 1; i < 4; ++i) { + uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, i, _messageToEvent(message, i, i, 0, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + assertEq(nonceAfter, nonceBefore); + assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); + } + } + + function test_ShouldStoreLinkFees() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + + 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 test_Fuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { + // To avoid RouterMustSetOriginalSender + vm.assume(originalSender != address(0)); + vm.assume(uint160(receiver) >= Internal.PRECOMPILE_SPACE); + feeTokenAmount = uint96(bound(feeTokenAmount, 0, MAX_MSG_FEES_JUELS)); + vm.stopPrank(); + + vm.startPrank(OWNER); + uint64[] memory destinationChainSelectors = new uint64[](1); + destinationChainSelectors[0] = uint64(DEST_CHAIN_SELECTOR); + address[] memory addAllowedList = new address[](1); + addAllowedList[0] = originalSender; + OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = 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(); + + vm.startPrank(address(s_sourceRouter)); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.receiver = abi.encode(receiver); + + // Make sure the tokens are in the contract + deal(s_sourceFeeToken, address(s_onRamp), feeTokenAmount); + + 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, + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) + ); + } + + function test_forwardFromRouter_WithInterception_Success() public { + _enableOutboundMessageInterceptor(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1e18; + message.tokenAmounts[0].token = s_sourceTokens[0]; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + s_outboundMessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), false); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + // Reverts + + function test_Paused_Revert() public { + // We pause by disabling the whitelist + vm.stopPrank(); + vm.startPrank(OWNER); + s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); + vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); + } + + function test_InvalidExtraArgsTag_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = bytes("bad args"); + + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_Permissions_Revert() 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 { + vm.expectRevert(OnRamp.RouterMustSetOriginalSender.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); + } + + function test_UnAllowedOriginalSender_Revert() 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 { + _enableOutboundMessageInterceptor(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1e18; + message.tokenAmounts[0].token = s_sourceTokens[0]; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + s_outboundMessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), true); + + vm.expectRevert( + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) + ); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_MultiCannotSendZeroTokens_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 0; + message.tokenAmounts[0].token = s_sourceTokens[0]; + vm.expectRevert(OnRamp.CannotSendZeroTokens.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_UnsupportedToken_Revert() public { + address wrongToken = address(1); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].token = wrongToken; + message.tokenAmounts[0].amount = 1; + + // We need to set the price of this new token to be able to reach + // the proper revert point. This must be called by the owner. + vm.stopPrank(); + vm.startPrank(OWNER); + + Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(wrongToken, 1); + s_feeQuoter.updatePrices(priceUpdates); + + // Change back to the router + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(OnRamp.UnsupportedToken.selector, wrongToken)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_forwardFromRouter_UnsupportedToken_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1; + message.tokenAmounts[0].token = address(1); + + vm.expectRevert(abi.encodeWithSelector(OnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_MesssageFeeTooHigh_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + ); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); + } + + function test_SourceTokenDataTooLarge_Revert() public { + address sourceETH = s_sourceTokens[1]; + vm.stopPrank(); + vm.startPrank(OWNER); + + MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( + BurnMintERC677(sourceETH), new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) + ); + BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); + deal(address(sourceETH), address(newPool), type(uint256).max); + + // Add TokenPool to OnRamp + s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); + + // Allow chain in TokenPool + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_destTokenPool), + remoteTokenAddress: abi.encode(s_destToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + newPool.applyChainUpdates(chainUpdates); + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); + + // No data set, should succeed + vm.startPrank(address(s_sourceRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set max data length, should succeed + vm.startPrank(OWNER); + newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES)); + + vm.startPrank(address(s_sourceRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set data to max length +1, should revert + vm.startPrank(OWNER); + newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); + + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set token config to allow larger data + vm.startPrank(OWNER); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, + isEnabled: true + }); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + vm.startPrank(address(s_sourceRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set the token data larger than the configured token data, should revert + vm.startPrank(OWNER); + newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); + + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } +} + +contract OnRamp_getSupportedTokens is OnRampSetup { + function test_GetSupportedTokens_Revert() public { + vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); + s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); + } +} + +contract OnRamp_getFee is OnRampSetup { + using USDPriceWith18Decimals for uint224; + + function test_EmptyMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = testTokens[i]; + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + assertEq(expectedFeeAmount, feeAmount); + } + } + + function test_SingleTokenMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 tokenAmount = 10000e18; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + message.feeToken = testTokens[i]; + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + assertEq(expectedFeeAmount, feeAmount); + } + } + + function test_GetFeeOfZeroForTokenMessage_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + assertTrue(feeAmount > 0); + + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory tokenMults = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + tokenMults[0] = FeeQuoter.PremiumMultiplierWeiPerEthArgs({token: message.feeToken, premiumMultiplierWeiPerEth: 0}); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(tokenMults); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; + destChainConfigArgs[0].destChainConfig.gasMultiplierWeiPerEth = 0; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + + assertEq(0, feeAmount); + } + + // Reverts + + function test_Unhealthy_Revert() 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 { + // Update dynamic config to enforce allowOutOfOrderExecution = true. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + vm.stopPrank(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // Empty extraArgs to should revert since it enforceOutOfOrder is true. + message.extraArgs = ""; + + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + } + + function test_NotAFeeTokenButPricedToken_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceTokens[1]; + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, message.feeToken)); + + s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + } +} + +contract OnRamp_setDynamicConfig is OnRampSetup { + function test_setDynamicConfig_Success() public { + OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: false, + messageInterceptor: makeAddr("messageInterceptor"), + feeAggregator: FEE_AGGREGATOR, + allowlistAdmin: address(0) + }); + + vm.expectEmit(); + emit OnRamp.ConfigSet(staticConfig, newConfig); + + s_onRamp.setDynamicConfig(newConfig); + + OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); + assertEq(newConfig.feeQuoter, gotDynamicConfig.feeQuoter); + } + + // Reverts + + function test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(0), + reentrancyGuardEntered: false, + feeAggregator: FEE_AGGREGATOR, + messageInterceptor: makeAddr("messageInterceptor"), + allowlistAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } + + function test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: false, + messageInterceptor: address(0), + feeAggregator: FEE_AGGREGATOR, + allowlistAdmin: address(0) + }); + + // Invalid price reg reverts. + newConfig.feeQuoter = address(0); + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } + + function test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: false, + messageInterceptor: address(0), + feeAggregator: address(0), + allowlistAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } + + function test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); + vm.startPrank(ADMIN); + vm.expectRevert("Only callable by owner"); + s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); + } + + function test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: true, + messageInterceptor: makeAddr("messageInterceptor"), + feeAggregator: FEE_AGGREGATOR, + allowlistAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } +} + +contract OnRamp_withdrawFeeTokens is OnRampSetup { + mapping(address => uint256) internal s_nopFees; + + function setUp() public virtual override { + super.setUp(); + + // Since we'll mostly be testing for valid calls from the router we'll + // mock all calls to be originating from the router and re-mock in + // tests that require failure. + vm.startPrank(address(s_sourceRouter)); + + uint256 feeAmount = 1234567890; + + // Send a bunch of messages, increasing the juels in the contract + for (uint256 i = 0; i < s_sourceFeeTokens.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceFeeTokens[i % s_sourceFeeTokens.length]; + uint256 newFeeTokenBalance = IERC20(message.feeToken).balanceOf(address(s_onRamp)) + feeAmount; + deal(message.feeToken, address(s_onRamp), newFeeTokenBalance); + s_nopFees[message.feeToken] = newFeeTokenBalance; + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + } + + function test_Fuzz_WithdrawFeeTokens_Success( + uint256[5] memory amounts + ) public { + vm.startPrank(OWNER); + address[] memory feeTokens = new address[](amounts.length); + for (uint256 i = 0; i < amounts.length; ++i) { + vm.assume(amounts[i] > 0); + feeTokens[i] = _deploySourceToken("", amounts[i], 18); + IERC20(feeTokens[i]).transfer(address(s_onRamp), amounts[i]); + } + + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + + for (uint256 i = 0; i < feeTokens.length; ++i) { + vm.expectEmit(); + emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, feeTokens[i], amounts[i]); + } + + s_onRamp.withdrawFeeTokens(); + + for (uint256 i = 0; i < feeTokens.length; ++i) { + assertEq(IERC20(feeTokens[i]).balanceOf(FEE_AGGREGATOR), amounts[i]); + assertEq(IERC20(feeTokens[i]).balanceOf(address(s_onRamp)), 0); + } + } + + function test_WithdrawFeeTokens_Success() public { + vm.expectEmit(); + emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, s_sourceFeeToken, s_nopFees[s_sourceFeeToken]); + + s_onRamp.withdrawFeeTokens(); + + assertEq(IERC20(s_sourceFeeToken).balanceOf(FEE_AGGREGATOR), s_nopFees[s_sourceFeeToken]); + assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), 0); + } +} + +contract OnRamp_getTokenPool is OnRampSetup { + function test_GetTokenPool_Success() public view { + assertEq( + s_sourcePoolByToken[s_sourceTokens[0]], + address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) + ); + assertEq( + s_sourcePoolByToken[s_sourceTokens[1]], + address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[1]))) + ); + + address wrongToken = address(123); + address nonExistentPool = address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(wrongToken))); + + assertEq(address(0), nonExistentPool); + } +} + +contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { + function test_ApplyDestChainConfigUpdates_Success() external { + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); + configArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + + // supports disabling a lane by setting a router to zero + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, IRouter(address(0)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + assertEq(address(0), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); + + // supports updating and adding lanes simultaneously + configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowlistEnabled: false + }); + configArgs[1] = + OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowlistEnabled: false}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); + assertEq(address(9999), address(s_onRamp.getRouter(9999))); + + // handles empty list + uint256 numLogs = vm.getRecordedLogs().length; + configArgs = new OnRamp.DestChainConfigArgs[](0); + s_onRamp.applyDestChainConfigUpdates(configArgs); + assertEq(numLogs, vm.getRecordedLogs().length); // indicates no changes made + } + + function test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() external { + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); + configArgs[0].destChainSelector = 0; // invalid + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidDestChainConfig.selector, 0)); + s_onRamp.applyDestChainConfigUpdates(configArgs); + } +} + +contract OnRamp_applyAllowlistUpdates is OnRampSetup { + function test_applyAllowlistUpdates_Success() public { + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowlistEnabled: false + }); + configArgs[1] = + OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowlistEnabled: false}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + + (uint64 sequenceNumber, bool allowlistEnabled, address router) = s_onRamp.getDestChainConfig(9999); + assertEq(sequenceNumber, 0); + assertEq(allowlistEnabled, false); + assertEq(router, address(9999)); + + uint64[] memory destinationChainSelectors = new uint64[](2); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + destinationChainSelectors[1] = uint64(99999); + + address[] memory addedAllowlistedSenders = new address[](4); + addedAllowlistedSenders[0] = vm.addr(1); + addedAllowlistedSenders[1] = vm.addr(2); + addedAllowlistedSenders[2] = vm.addr(3); + addedAllowlistedSenders[3] = vm.addr(4); + + vm.expectEmit(); + emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); + + OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ + allowlistEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + + OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); + applyAllowlistConfigArgsItems[0] = allowlistConfigArgs; + + s_onRamp.applyAllowlistUpdates(applyAllowlistConfigArgsItems); + + (bool isActive, address[] memory gotAllowList) = s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR); + assertEq(4, gotAllowList.length); + assertEq(addedAllowlistedSenders, gotAllowList); + assertEq(true, isActive); + + address[] memory removedAllowlistedSenders = new address[](1); + removedAllowlistedSenders[0] = vm.addr(2); + + vm.expectEmit(); + emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); + + allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ + allowlistEnabled: false, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: new address[](0), + removedAllowlistedSenders: removedAllowlistedSenders + }); + + OnRamp.AllowlistConfigArgs[] memory allowlistConfigArgsItems_2 = new OnRamp.AllowlistConfigArgs[](1); + allowlistConfigArgsItems_2[0] = allowlistConfigArgs; + + s_onRamp.applyAllowlistUpdates(allowlistConfigArgsItems_2); + (isActive, gotAllowList) = s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR); + assertEq(3, gotAllowList.length); + assertFalse(isActive); + + addedAllowlistedSenders = new address[](2); + addedAllowlistedSenders[0] = vm.addr(5); + addedAllowlistedSenders[1] = vm.addr(6); + + removedAllowlistedSenders = new address[](2); + removedAllowlistedSenders[0] = vm.addr(1); + removedAllowlistedSenders[1] = vm.addr(3); + + vm.expectEmit(); + emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); + emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); + + allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ + allowlistEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: removedAllowlistedSenders + }); + + OnRamp.AllowlistConfigArgs[] memory allowlistConfigArgsItems_3 = new OnRamp.AllowlistConfigArgs[](1); + allowlistConfigArgsItems_3[0] = allowlistConfigArgs; + + s_onRamp.applyAllowlistUpdates(allowlistConfigArgsItems_3); + (isActive, gotAllowList) = s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR); + + assertEq(3, gotAllowList.length); + assertTrue(isActive); + } + + function test_applyAllowlistUpdates_Revert() public { + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowlistEnabled: false + }); + configArgs[1] = + OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowlistEnabled: false}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + + uint64[] memory destinationChainSelectors = new uint64[](2); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + destinationChainSelectors[1] = uint64(99999); + + address[] memory addedAllowlistedSenders = new address[](4); + addedAllowlistedSenders[0] = vm.addr(1); + addedAllowlistedSenders[1] = vm.addr(2); + addedAllowlistedSenders[2] = vm.addr(3); + addedAllowlistedSenders[3] = vm.addr(4); + + OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ + allowlistEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + + OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); + applyAllowlistConfigArgsItems[0] = allowlistConfigArgs; + + vm.startPrank(STRANGER); + vm.expectRevert(OnRamp.OnlyCallableByOwnerOrAllowlistAdmin.selector); + s_onRamp.applyAllowlistUpdates(applyAllowlistConfigArgsItems); + vm.stopPrank(); + + applyAllowlistConfigArgsItems[0].addedAllowlistedSenders[0] = address(0); + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); + vm.startPrank(OWNER); + s_onRamp.applyAllowlistUpdates(applyAllowlistConfigArgsItems); + vm.stopPrank(); + } + + function test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() public { + address[] memory addedAllowlistedSenders = new address[](1); + addedAllowlistedSenders[0] = vm.addr(1); + + OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ + allowlistEnabled: false, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); + applyAllowlistConfigArgsItems[0] = allowlistConfigArgs; + + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); + s_onRamp.applyAllowlistUpdates(applyAllowlistConfigArgsItems); + } +} diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol similarity index 56% rename from contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol rename to contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index f085185753d..8254dd977f7 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -1,44 +1,38 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IPoolV1} from "../../interfaces/IPool.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {NonceManager} from "../../NonceManager.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; import {Router} from "../../Router.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {EVM2EVMMultiOnRamp} from "../../onRamp/EVM2EVMMultiOnRamp.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; -import {EVM2EVMMultiOnRampHelper} from "../helpers/EVM2EVMMultiOnRampHelper.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {FeeQuoterFeeSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; -import {PriceRegistryFeeSetup} from "../priceRegistry/PriceRegistry.t.sol"; +import {OnRampHelper} from "../helpers/OnRampHelper.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { +contract OnRampSetup is FeeQuoterFeeSetup { uint256 internal immutable i_tokenAmount0 = 9; uint256 internal immutable i_tokenAmount1 = 7; bytes32 internal s_metadataHash; - EVM2EVMMultiOnRampHelper internal s_onRamp; - MessageInterceptorHelper internal s_outboundMessageValidator; + OnRampHelper internal s_onRamp; + MessageInterceptorHelper internal s_outboundMessageInterceptor; address[] internal s_offRamps; NonceManager internal s_outboundNonceManager; - function setUp() public virtual override(TokenSetup, PriceRegistryFeeSetup) { - TokenSetup.setUp(); - PriceRegistryFeeSetup.setUp(); + function setUp() public virtual override { + super.setUp(); - s_outboundMessageValidator = new MessageInterceptorHelper(); + s_outboundMessageInterceptor = new MessageInterceptorHelper(); s_outboundNonceManager = new NonceManager(new address[](0)); (s_onRamp, s_metadataHash) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, address(s_sourceRouter), address(s_outboundNonceManager), address(s_tokenAdminRegistry) + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) ); s_offRamps = new address[](2); @@ -58,7 +52,7 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { } function _generateTokenMessage() public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); + Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); tokenAmounts[0].amount = i_tokenAmount0; tokenAmounts[1].amount = i_tokenAmount1; return Client.EVM2AnyMessage({ @@ -70,13 +64,33 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { }); } + /// @dev a helper function to compose EVM2AnyRampMessage messages + /// @dev it is assumed that LINK is the payment token because feeTokenAmount == feeValueJuels function _messageToEvent( Client.EVM2AnyMessage memory message, uint64 seqNum, uint64 nonce, uint256 feeTokenAmount, address originalSender - ) public view returns (Internal.EVM2AnyRampMessage memory) { + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + return _messageToEvent( + message, + seqNum, + nonce, + feeTokenAmount, // fee paid + feeTokenAmount, // conversion to jules is the same + originalSender + ); + } + + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + uint256 feeValueJuels, + address originalSender + ) internal view returns (Internal.EVM2AnyRampMessage memory) { return _messageToEvent( message, SOURCE_CHAIN_SELECTOR, @@ -84,26 +98,29 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { seqNum, nonce, feeTokenAmount, + feeValueJuels, originalSender, s_metadataHash, s_tokenAdminRegistry ); } - function _generateDynamicMultiOnRampConfig( - address router, - address priceRegistry - ) internal pure returns (EVM2EVMMultiOnRamp.DynamicConfig memory) { - return EVM2EVMMultiOnRamp.DynamicConfig({ - router: router, - priceRegistry: priceRegistry, - messageValidator: address(0), - feeAggregator: FEE_AGGREGATOR + function _generateDynamicOnRampConfig( + address feeQuoter + ) internal pure returns (OnRamp.DynamicConfig memory) { + return OnRamp.DynamicConfig({ + feeQuoter: feeQuoter, + reentrancyGuardEntered: false, + messageInterceptor: address(0), + feeAggregator: FEE_AGGREGATOR, + allowlistAdmin: address(0) }); } // Slicing is only available for calldata. So we have to build a new bytes array. - function _removeFirst4Bytes(bytes memory data) internal pure returns (bytes memory) { + function _removeFirst4Bytes( + bytes memory data + ) internal pure returns (bytes memory) { bytes memory result = new bytes(data.length - 4); for (uint256 i = 4; i < data.length; ++i) { result[i - 4] = data[i]; @@ -111,20 +128,30 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { return result; } + function _generateDestChainConfigArgs( + IRouter router + ) internal pure returns (OnRamp.DestChainConfigArgs[] memory) { + OnRamp.DestChainConfigArgs[] memory destChainConfigs = new OnRamp.DestChainConfigArgs[](1); + destChainConfigs[0] = + OnRamp.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, router: router, allowlistEnabled: false}); + return destChainConfigs; + } + function _deployOnRamp( uint64 sourceChainSelector, - address sourceRouter, + IRouter router, address nonceManager, address tokenAdminRegistry - ) internal returns (EVM2EVMMultiOnRampHelper, bytes32 metadataHash) { - EVM2EVMMultiOnRampHelper onRamp = new EVM2EVMMultiOnRampHelper( - EVM2EVMMultiOnRamp.StaticConfig({ + ) internal returns (OnRampHelper, bytes32 metadataHash) { + OnRampHelper onRamp = new OnRampHelper( + OnRamp.StaticConfig({ chainSelector: sourceChainSelector, - rmnProxy: address(s_mockRMN), + rmnRemote: s_mockRMNRemote, nonceManager: nonceManager, tokenAdminRegistry: tokenAdminRegistry }), - _generateDynamicMultiOnRampConfig(sourceRouter, address(s_priceRegistry)) + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(router) ); address[] memory authorizedCallers = new address[](1); @@ -140,7 +167,7 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { ); } - function _enableOutboundMessageValidator() internal { + function _enableOutboundMessageInterceptor() internal { (, address msgSender,) = vm.readCallers(); bool resetPrank = false; @@ -151,8 +178,8 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { resetPrank = true; } - EVM2EVMMultiOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - dynamicConfig.messageValidator = address(s_outboundMessageValidator); + OnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); + dynamicConfig.messageInterceptor = address(s_outboundMessageInterceptor); s_onRamp.setDynamicConfig(dynamicConfig); if (resetPrank) { @@ -161,20 +188,13 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { } } - function _assertStaticConfigsEqual( - EVM2EVMMultiOnRamp.StaticConfig memory a, - EVM2EVMMultiOnRamp.StaticConfig memory b - ) internal pure { + function _assertStaticConfigsEqual(OnRamp.StaticConfig memory a, OnRamp.StaticConfig memory b) internal pure { assertEq(a.chainSelector, b.chainSelector); - assertEq(a.rmnProxy, b.rmnProxy); + assertEq(address(a.rmnRemote), address(b.rmnRemote)); assertEq(a.tokenAdminRegistry, b.tokenAdminRegistry); } - function _assertDynamicConfigsEqual( - EVM2EVMMultiOnRamp.DynamicConfig memory a, - EVM2EVMMultiOnRamp.DynamicConfig memory b - ) internal pure { - assertEq(a.router, b.router); - assertEq(a.priceRegistry, b.priceRegistry); + function _assertDynamicConfigsEqual(OnRamp.DynamicConfig memory a, OnRamp.DynamicConfig memory b) internal pure { + assertEq(a.feeQuoter, b.feeQuoter); } } diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol index 290c4ae1537..b5967e74d1e 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol @@ -5,7 +5,6 @@ import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {BurnFromMintTokenPool} from "../../pools/BurnFromMintTokenPool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; import {BurnMintSetup} from "./BurnMintSetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -29,7 +28,7 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); - assertEq("BurnFromMintTokenPool 1.5.0-dev", s_pool.typeAndVersion()); + assertEq("BurnFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); } function test_PoolBurn_Success() public { @@ -95,8 +94,8 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { amount: 1, localToken: address(s_burnMintERC677), remoteChainSelector: wrongChainSelector, - sourcePoolAddress: generateSourceTokenData().sourcePoolAddress, - sourcePoolData: generateSourceTokenData().extraData, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, offchainTokenData: "" }) ); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol index a39fd1bb9fa..7bf0ce57d5b 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol @@ -21,15 +21,17 @@ contract BurnMintSetup is RouterSetup { s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 0); } - function _applyChainUpdates(address pool) internal { + function _applyChainUpdates( + address pool + ) internal { TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); chains[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, remotePoolAddress: abi.encode(s_remoteBurnMintPool), remoteTokenAddress: abi.encode(s_remoteToken), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); BurnMintTokenPool(pool).applyChainUpdates(chains); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol index c628c510d43..8a6d047380c 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol @@ -1,15 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IPoolV1} from "../../interfaces/IPool.sol"; - -import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; import {BurnMintSetup} from "./BurnMintSetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -32,7 +27,7 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { assertEq(address(s_burnMintERC677), address(s_pool.getToken())); assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); - assertEq("BurnMintTokenPool 1.5.0-dev", s_pool.typeAndVersion()); + assertEq("BurnMintTokenPool 1.5.0", s_pool.typeAndVersion()); } function test_PoolBurn_Success() public { @@ -107,15 +102,17 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { function test_PoolMint_Success() public { uint256 amount = 1e19; + address receiver = makeAddr("receiver_address"); vm.startPrank(s_burnMintOffRamp); vm.expectEmit(); - emit IERC20.Transfer(address(0), address(s_burnMintOffRamp), amount); + emit IERC20.Transfer(address(0), receiver, amount); + s_pool.releaseOrMint( Pool.ReleaseOrMintInV1({ originalSender: bytes(""), - receiver: OWNER, + receiver: receiver, amount: amount, localToken: address(s_burnMintERC677), remoteChainSelector: DEST_CHAIN_SELECTOR, @@ -125,7 +122,7 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { }) ); - assertEq(s_burnMintERC677.balanceOf(s_burnMintOffRamp), amount); + assertEq(s_burnMintERC677.balanceOf(receiver), amount); } function test_PoolMintNotHealthy_Revert() public { @@ -142,8 +139,8 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { amount: 1e5, localToken: address(s_burnMintERC677), remoteChainSelector: DEST_CHAIN_SELECTOR, - sourcePoolAddress: generateSourceTokenData().sourcePoolAddress, - sourcePoolData: generateSourceTokenData().extraData, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, offchainTokenData: "" }) ); @@ -162,8 +159,8 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { amount: 1, localToken: address(s_burnMintERC677), remoteChainSelector: wrongChainSelector, - sourcePoolAddress: generateSourceTokenData().sourcePoolAddress, - sourcePoolData: generateSourceTokenData().extraData, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, offchainTokenData: "" }) ); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol index 22362ee4a55..92e871708da 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol @@ -5,7 +5,6 @@ import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {BurnWithFromMintTokenPool} from "../../pools/BurnWithFromMintTokenPool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; import {BurnMintSetup} from "./BurnMintSetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -30,7 +29,7 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); - assertEq("BurnWithFromMintTokenPool 1.5.0-dev", s_pool.typeAndVersion()); + assertEq("BurnWithFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); } function test_PoolBurn_Success() public { @@ -96,8 +95,8 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup amount: 1, localToken: address(s_burnMintERC677), remoteChainSelector: wrongChainSelector, - sourcePoolAddress: generateSourceTokenData().sourcePoolAddress, - sourcePoolData: generateSourceTokenData().extraData, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, offchainTokenData: "" }) ); diff --git a/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol new file mode 100644 index 00000000000..73426129efd --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol @@ -0,0 +1,886 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {IPoolV1} from "../../interfaces/IPool.sol"; +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; + +import {TokenPool} from "../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCBridgeMigrator} from "../../pools/USDC/USDCBridgeMigrator.sol"; +import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + 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_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + +contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { + function test_LockOrBurn_onLockReleaseMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // 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); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + } + + function test_MintOrRelease_OnLockReleaseMechanism_Success() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e12; + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + + // Simulate the off-ramp forwarding tokens to the recipient on destination chain + // s_token.transfer(recipient, amount); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount - amount, + "Incorrect remaining liquidity in TokenPool" + ); + assertEq(s_token.balanceOf(recipient), amount, "Tokens not transferred to recipient"); + } + + function test_LockOrBurn_PrimaryMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + uint256 amount = 1; + + vm.startPrank(OWNER); + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + receiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + } + + // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 + function test_MintOrRelease_incomingMessageWithPrimaryMechanism() public { + bytes memory encodedUsdcMessage = + hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; + bytes memory attestation = bytes("attestation bytes"); + + uint32 nonce = 4730; + uint32 sourceDomain = 3; + uint256 amount = 100; + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + function test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() public { + // Test Enabling the LR mechanism and sending an outgoing message + test_LockOrBurn_PrimaryMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = DEST_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + // Send an outgoing message + test_LockOrBurn_PrimaryMechanism_Success(); + } + + function test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() public { + test_MintOrRelease_OnLockReleaseMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = SOURCE_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(SOURCE_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(OWNER, OWNER, SOURCE_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Test incoming on the primary mechanism after disable LR, simulating Circle's new support for CCTP on + // DEST_CHAIN_SELECTOR + test_MintOrRelease_incomingMessageWithPrimaryMechanism(); + } + + function test_LockOrBurn_WhileMigrationPause_Revert() public { + // Create a fake migration proposal + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), DEST_CHAIN_SELECTOR); + + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // 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); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + // Expect the lockOrBurn to fail because a pending CCTP-Migration has paused outgoing messages on CCIP + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_ReleaseOrMint_WhileMigrationPause_Revert() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(SOURCE_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory sourcePoolDataLockRelease = abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + // Expect revert because the lane is paused and no incoming messages should be allowed + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, SOURCE_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourcePoolDataLockRelease, + offchainTokenData: "" + }) + ); + } + + 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); + + 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); + } +} + +contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { + function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); + + // 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); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + // Ensure that the tokens are properly locked + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + amount, + "Internal locked token accounting is incorrect" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CircleMigratorAddressSet(CIRCLE); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "Current proposed chain migration does not match expected for DEST_CHAIN_SELECTOR" + ); + + // Impersonate the set circle address and execute the proposal + vm.startPrank(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationExecuted(DEST_CHAIN_SELECTOR, amount); + + // Ensure the call to the burn function is properly + vm.expectCall(address(s_token), abi.encodeWithSelector(bytes4(keccak256("burn(uint256)")), amount)); + + s_usdcTokenPool.burnLockedUSDC(); + + // Assert that the tokens were actually burned + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens were not burned out of the tokenPool"); + + // Ensure the proposal slot was cleared and there's no tokens locked for the destination chain anymore + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), 0, "Proposal Slot should be empty"); + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "No tokens should be locked for DEST_CHAIN_SELECTOR after CCTP-approved burn" + ); + + assertFalse( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" + ); + + test_LockOrBurn_PrimaryMechanism_Success(); + } + + function test_cancelExistingCCTPMigrationProposal() public { + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "migration proposal should exist, but doesn't" + ); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationCancelled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + 0, + "migration proposal exists, but shouldn't after being cancelled" + ); + + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_burnLockedUSDC_invalidPermissions_Revert() public { + address CIRCLE = makeAddr("CIRCLE"); + + vm.startPrank(OWNER); + + // Set the circle migrator address for later, but don't start pranking as it yet + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.onlyCircle.selector)); + + // Should fail because only Circle can call this function + s_usdcTokenPool.burnLockedUSDC(); + + vm.startPrank(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.ExistingMigrationProposal.selector)); + s_usdcTokenPool.burnLockedUSDC(); + } + + function test_cannotModifyLiquidityWithoutPermissions_Revert() public { + address randomAddr = makeAddr("RANDOM"); + + vm.startPrank(randomAddr); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + + // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } + + function test_cannotCancelANonExistentMigrationProposal() public { + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + + // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_unstickManualTxAfterMigration_destChain_Success() 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, + // which should tell it to use the lock-release mechanism with the tokens provided. + + // We want the released amount to be 1e6, so to simulate the workflow, we sent those tokens to the contract as + // liquidity + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount); + + // By Default, the source chain will be indicated as use-CCTP so we need to change that. We create a message + // that will use the Lock-Release flag in the offchain data to indicate that the tokens should be released + // instead of minted since there's no attestation for us to use. + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + // By this point, the tx should have executed, with the Lock-Release taking over, and being forwaded to the + // recipient + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + // which after a migration will mean all new messages. + + // The message should fail without an error because it failed to decode a non-existent attestation which would + // revert without an error + vm.expectRevert(); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_unstickManualTxAfterMigration_homeChain_Success() public { + address CIRCLE = makeAddr("CIRCLE"); + address recipient = address(1234); + + // 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); + + // Test the edge case where a tx is stuck in the manual tx queue and the source chain (mainnet) needs unsticking + // In this test we want 1e6 worth of tokens to be stuck, so first we provide liquidity to the pool >1e6 + + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + // I picked 3x the amount to be stuck so that we can have enough to release with a buffer + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount * 3); + + // At this point in the process, the router will lock new messages, so we want to simulate excluding tokens + // stuck coming back from the destination, to the home chain. This way they can be released and not minted + // since there's no corresponding attestation to use for minting. + vm.startPrank(OWNER); + + // Exclude the tokens from being burned and check for the event + vm.expectEmit(); + emit USDCBridgeMigrator.TokensExcludedFromBurn(SOURCE_CHAIN_SELECTOR, amount, (amount * 3) - amount); + + s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, amount); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), + (amount * 3), + "Tokens locked minus ones excluded from the burn should be 2e6" + ); + + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "1e6 tokens should be excluded from the burn" + ); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + vm.startPrank(CIRCLE); + + s_usdcTokenPool.burnLockedUSDC(); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), 0, "All tokens should be burned out of the pool" + ); + + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "There should still be 1e6 tokens excluded from the burn" + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 1e6, "All tokens minus the excluded should be in the pool"); + + // Now that the burn is successful, we can release the tokens that were excluded from the burn + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 0, + "All tokens should be released from the exclusion list" + ); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + test_MintOrRelease_incomingMessageWithPrimaryMechanism(); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol index 97d0d4e8947..eea7f2af4c9 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol @@ -5,16 +5,13 @@ import {IPoolV1} from "../../interfaces/IPool.sol"; import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; import {Router} from "../../Router.sol"; -import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.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 {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; import {RouterSetup} from "../router/RouterSetup.t.sol"; contract LockReleaseTokenPoolSetup is RouterSetup { @@ -47,8 +44,8 @@ contract LockReleaseTokenPoolSetup is RouterSetup { remotePoolAddress: abi.encode(s_destPoolAddress), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); @@ -79,8 +76,10 @@ contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { } contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { - function test_Fuzz_LockOrBurnNoAllowList_Success(uint256 amount) public { - amount = bound(amount, 1, getOutboundRateLimiterConfig().capacity); + function test_Fuzz_LockOrBurnNoAllowList_Success( + uint256 amount + ) public { + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); vm.startPrank(s_allowedOnRamp); vm.expectEmit(); @@ -179,8 +178,8 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { remotePoolAddress: abi.encode(s_sourcePoolAddress), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); @@ -222,7 +221,7 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { deal(address(s_token), address(s_lockReleaseTokenPool), amount); vm.startPrank(s_allowedOffRamp); - uint256 capacity = getInboundRateLimiterConfig().capacity; + uint256 capacity = _getInboundRateLimiterConfig().capacity; // Determine if we hit the rate limit or the txs should succeed. if (amount > capacity) { vm.expectRevert( @@ -298,8 +297,8 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { amount: 1e5, localToken: address(s_token), remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: generateSourceTokenData().sourcePoolAddress, - sourcePoolData: generateSourceTokenData().extraData, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, offchainTokenData: "" }) ); @@ -319,7 +318,9 @@ contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { } contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { - function test_Fuzz_ProvideLiquidity_Success(uint256 amount) public { + function test_Fuzz_ProvideLiquidity_Success( + uint256 amount + ) public { uint256 balancePre = s_token.balanceOf(OWNER); s_token.approve(address(s_lockReleaseTokenPool), amount); @@ -333,12 +334,14 @@ contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { function test_Unauthorized_Revert() public { vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(LockReleaseTokenPool.Unauthorized.selector, STRANGER)); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); s_lockReleaseTokenPool.provideLiquidity(1); } - function test_Fuzz_ExceedsAllowance(uint256 amount) public { + function test_Fuzz_ExceedsAllowance( + uint256 amount + ) public { vm.assume(amount > 0); vm.expectRevert("ERC20: insufficient allowance"); s_lockReleaseTokenPool.provideLiquidity(amount); @@ -354,7 +357,9 @@ contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { } contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { - function test_Fuzz_WithdrawalLiquidity_Success(uint256 amount) public { + function test_Fuzz_WithdrawalLiquidity_Success( + uint256 amount + ) public { uint256 balancePre = s_token.balanceOf(OWNER); s_token.approve(address(s_lockReleaseTokenPool), amount); s_lockReleaseTokenPool.provideLiquidity(amount); @@ -368,7 +373,7 @@ contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { function test_Unauthorized_Revert() public { vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(LockReleaseTokenPool.Unauthorized.selector, STRANGER)); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); s_lockReleaseTokenPool.withdrawLiquidity(1); } @@ -387,126 +392,47 @@ contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { } } -contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); - } -} - -contract LockReleaseTokenPool_setChainRateLimiterConfig is LockReleaseTokenPoolSetup { - uint64 internal s_remoteChainSelector; +contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { + LockReleaseTokenPool internal s_oldLockReleaseTokenPool; + uint256 internal s_amount = 100000; function setUp() public virtual override { - LockReleaseTokenPoolSetup.setUp(); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - s_remoteChainSelector = 123124; - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: s_remoteChainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - s_lockReleaseTokenPool.applyChainUpdates(chainUpdates); - } + super.setUp(); - function test_Fuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { - // Cap the lower bound to 4 so 4/2 is still >= 2 - vm.assume(capacity >= 4); - // Cap the lower bound to 2 so 2/2 is still >= 1 - rate = uint128(bound(rate, 2, capacity - 2)); - // Bucket updates only work on increasing time - newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); - vm.warp(newTime); - - uint256 oldOutboundTokens = s_lockReleaseTokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector).tokens; - uint256 oldInboundTokens = s_lockReleaseTokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector).tokens; - - RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); - RateLimiter.Config memory newInboundConfig = - RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); - - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newOutboundConfig); - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newInboundConfig); - vm.expectEmit(); - emit TokenPool.ChainConfigured(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - s_lockReleaseTokenPool.setChainRateLimiterConfig(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); - - RateLimiter.TokenBucket memory bucket = - s_lockReleaseTokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newOutboundConfig.capacity); - assertEq(bucket.rate, newOutboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - - expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); + s_oldLockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - bucket = s_lockReleaseTokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newInboundConfig.capacity); - assertEq(bucket.rate, newInboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); + deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); } - function test_OnlyOwnerOrRateLimitAdmin_Revert() public { - address rateLimiterAdmin = address(28973509103597907); + function test_transferLiquidity_Success() public { + uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); - s_lockReleaseTokenPool.setRateLimitAdmin(rateLimiterAdmin); + s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); - vm.startPrank(rateLimiterAdmin); - - s_lockReleaseTokenPool.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); + vm.expectEmit(); + emit LockReleaseTokenPool.LiquidityTransferred(address(s_oldLockReleaseTokenPool), s_amount); - vm.startPrank(OWNER); + s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount); - s_lockReleaseTokenPool.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); } - // Reverts - - function test_OnlyOwner_Revert() public { - vm.startPrank(STRANGER); + function test_transferLiquidity_transferTooMuch_Revert() public { + uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); - vm.expectRevert(abi.encodeWithSelector(LockReleaseTokenPool.Unauthorized.selector, STRANGER)); - s_lockReleaseTokenPool.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); - } + s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); - function test_NonExistentChain_Revert() public { - uint64 wrongChainSelector = 9084102894; + vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); + s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount + 1); - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); - s_lockReleaseTokenPool.setChainRateLimiterConfig( - wrongChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() - ); + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre); } } -contract LockReleaseTokenPool_setRateLimitAdmin is LockReleaseTokenPoolSetup { - function test_SetRateLimitAdmin_Success() public { - assertEq(address(0), s_lockReleaseTokenPool.getRateLimitAdmin()); - s_lockReleaseTokenPool.setRateLimitAdmin(OWNER); - assertEq(OWNER, s_lockReleaseTokenPool.getRateLimitAdmin()); - } - - // Reverts - - function test_SetRateLimitAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_lockReleaseTokenPool.setRateLimitAdmin(STRANGER); +contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { + function test_SupportsInterface_Success() 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/TokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol index e5eb04b7413..d524c015b70 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol @@ -5,7 +5,6 @@ import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; import {Router} from "../../Router.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/RouterSetup.t.sol"; @@ -55,8 +54,8 @@ contract TokenPool_getRemotePool is TokenPoolSetup { remotePoolAddress: abi.encode(remotePool), remoteTokenAddress: abi.encode(remoteToken), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdates); @@ -78,8 +77,8 @@ contract TokenPool_setRemotePool is TokenPoolSetup { remotePoolAddress: abi.encode(initialPool), remoteTokenAddress: abi.encode(remoteToken), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdates); @@ -110,7 +109,9 @@ contract TokenPool_setRemotePool is TokenPoolSetup { } contract TokenPool_applyChainUpdates is TokenPoolSetup { - function assertState(TokenPool.ChainUpdate[] memory chainUpdates) public view { + function assertState( + TokenPool.ChainUpdate[] memory chainUpdates + ) public view { uint64[] memory chainSelectors = s_tokenPool.getSupportedChains(); for (uint256 i = 0; i < chainUpdates.length; i++) { assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i]); @@ -379,8 +380,8 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { remotePoolAddress: abi.encode(address(2)), remoteTokenAddress: abi.encode(address(3)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdates); } @@ -429,12 +430,12 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { // Reverts - function test_OnlyOwner_Revert() public { + function test_OnlyOwnerOrRateLimitAdmin_Revert() public { vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); s_tokenPool.setChainRateLimiterConfig( - s_remoteChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() + s_remoteChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() ); } @@ -443,11 +444,28 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); s_tokenPool.setChainRateLimiterConfig( - wrongChainSelector, getOutboundRateLimiterConfig(), getInboundRateLimiterConfig() + wrongChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() ); } } +contract LockRelease_setRateLimitAdmin is TokenPoolSetup { + function test_SetRateLimitAdmin_Success() public { + assertEq(address(0), s_tokenPool.getRateLimitAdmin()); + s_tokenPool.setRateLimitAdmin(OWNER); + assertEq(OWNER, s_tokenPool.getRateLimitAdmin()); + } + + // Reverts + + function test_SetRateLimitAdmin_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_tokenPool.setRateLimitAdmin(STRANGER); + } +} + contract TokenPool_onlyOnRamp is TokenPoolSetup { function test_onlyOnRamp_Success() public { uint64 chainSelector = 13377; @@ -459,8 +477,8 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdate); @@ -490,8 +508,8 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdate); @@ -531,8 +549,8 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdate); @@ -555,8 +573,8 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdate); @@ -586,8 +604,8 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdate); @@ -627,8 +645,8 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_tokenPool.applyChainUpdates(chainUpdate); @@ -724,7 +742,7 @@ contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListS assertEq(address(2), setAddresses[2]); assertEq(address(3), setAddresses[3]); - // remove all from allowList + // remove all from allowlist for (uint256 i = 0; i < setAddresses.length; ++i) { vm.expectEmit(); emit TokenPool.AllowListRemove(setAddresses[i]); diff --git a/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol index 200ffb4f6d6..da5caba9d7e 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol @@ -17,12 +17,13 @@ import {USDCTokenPoolHelper} from "../helpers/USDCTokenPoolHelper.sol"; import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; contract USDCTokenPoolSetup is BaseTest { IBurnMintERC20 internal s_token; MockUSDCTokenMessenger internal s_mockUSDC; MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; struct USDCMessage { uint32 version; @@ -56,7 +57,7 @@ contract USDCTokenPoolSetup is BaseTest { BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); s_token = usdcToken; deal(address(s_token), OWNER, type(uint256).max); - setUpRamps(); + _setUpRamps(); s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); @@ -77,16 +78,16 @@ contract USDCTokenPoolSetup is BaseTest { remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), remoteTokenAddress: abi.encode(address(s_token)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); chainUpdates[1] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_usdcTokenPool.applyChainUpdates(chainUpdates); @@ -104,7 +105,7 @@ contract USDCTokenPoolSetup is BaseTest { s_usdcTokenPoolWithAllowList.setDomains(domains); } - function setUpRamps() internal { + function _setUpRamps() internal { s_router = new Router(address(s_token), address(s_mockRMN)); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); @@ -117,7 +118,9 @@ contract USDCTokenPoolSetup is BaseTest { s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); } - function _generateUSDCMessage(USDCMessage memory usdcMessage) internal pure returns (bytes memory) { + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { return abi.encodePacked( usdcMessage.version, usdcMessage.sourceDomain, @@ -150,7 +153,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { address(s_token), amount, address(s_usdcTokenPool), - expectedDomain.allowedCaller, + receiver, expectedDomain.domainIdentifier, s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), expectedDomain.allowedCaller @@ -175,7 +178,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { function test_Fuzz_LockOrBurn_Success(bytes32 destinationReceiver, uint256 amount) public { vm.assume(destinationReceiver != bytes32(0)); - amount = bound(amount, 1, getOutboundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); s_token.transfer(address(s_usdcTokenPool), amount); vm.startPrank(s_routerAllowedOnRamp); @@ -190,7 +193,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { address(s_token), amount, address(s_usdcTokenPool), - expectedDomain.allowedCaller, + destinationReceiver, expectedDomain.domainIdentifier, s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), expectedDomain.allowedCaller @@ -216,7 +219,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { function test_Fuzz_LockOrBurnWithAllowList_Success(bytes32 destinationReceiver, uint256 amount) public { vm.assume(destinationReceiver != bytes32(0)); - amount = bound(amount, 1, getOutboundRateLimiterConfig().capacity); + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); s_token.transfer(address(s_usdcTokenPoolWithAllowList), amount); vm.startPrank(s_routerAllowedOnRamp); @@ -230,7 +233,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { address(s_token), amount, address(s_usdcTokenPoolWithAllowList), - expectedDomain.allowedCaller, + destinationReceiver, expectedDomain.domainIdentifier, s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), expectedDomain.allowedCaller @@ -266,8 +269,8 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); s_usdcTokenPool.applyChainUpdates(chainUpdates); @@ -319,30 +322,23 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { }) ); } - - function test_lockOrBurn_InvalidReceiver_Revert() public { - vm.startPrank(s_routerAllowedOnRamp); - - bytes memory receiver = abi.encodePacked(address(0), address(1)); - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidReceiver.selector, receiver)); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: receiver, - amount: 1, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } } contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { + // From https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/BurnMessage.sol#L57 + function _formatMessage( + uint32 _version, + bytes32 _burnToken, + bytes32 _mintRecipient, + uint256 _amount, + bytes32 _messageSender + ) internal pure returns (bytes memory) { + return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + } + function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { vm.assume(recipient != address(0) && recipient != address(s_token)); - amount = bound(amount, 0, getInboundRateLimiterConfig().capacity); + amount = bound(amount, 0, _getInboundRateLimiterConfig().capacity); USDCMessage memory usdcMessage = USDCMessage({ version: 0, @@ -352,7 +348,13 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { sender: SOURCE_CHAIN_TOKEN_SENDER, recipient: bytes32(uint256(uint160(recipient))), destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: bytes("") + messageBody: _formatMessage( + 0, + bytes32(uint256(uint160(address(s_token)))), + bytes32(uint256(uint160(recipient))), + amount, + bytes32(uint256(uint160(OWNER))) + ) }); bytes memory message = _generateUSDCMessage(usdcMessage); @@ -363,7 +365,8 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { destTokenAddress: abi.encode(address(s_usdcTokenPool)), extraData: abi.encode( USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ) + ), + destGasAmount: USDC_DEST_TOKEN_GAS }); bytes memory offchainTokenData = @@ -408,7 +411,8 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})) + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS }); // The mocked receiver does not release the token to the pool, so we manually do it here @@ -452,7 +456,13 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { sender: SOURCE_CHAIN_TOKEN_SENDER, recipient: bytes32(uint256(uint160(address(s_mockUSDC)))), destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: bytes("") + messageBody: _formatMessage( + 0, + bytes32(uint256(uint160(address(s_token)))), + bytes32(uint256(uint160(OWNER))), + amount, + bytes32(uint256(uint160(OWNER))) + ) }); Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ @@ -460,7 +470,8 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { destTokenAddress: abi.encode(address(s_usdcTokenPool)), extraData: abi.encode( USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ) + ), + destGasAmount: USDC_DEST_TOKEN_GAS }); bytes memory offchainTokenData = abi.encode( @@ -484,7 +495,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { } function test_TokenMaxCapacityExceeded_Revert() public { - uint256 capacity = getInboundRateLimiterConfig().capacity; + uint256 capacity = _getInboundRateLimiterConfig().capacity; uint256 amount = 10 * capacity; address recipient = address(1); vm.startPrank(s_routerAllowedOffRamp); @@ -492,7 +503,8 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})) + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS }); bytes memory offchainTokenData = diff --git a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol deleted file mode 100644 index c3c22ef2909..00000000000 --- a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol +++ /dev/null @@ -1,2542 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; -import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; - -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; - -import {TokenSetup} from "../TokenSetup.t.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {PriceRegistryHelper} from "../helpers/PriceRegistryHelper.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -import {Vm} from "forge-std/Vm.sol"; -import {console} from "forge-std/console.sol"; - -contract PriceRegistrySetup is TokenSetup { - uint112 internal constant USD_PER_GAS = 1e6; // 0.001 gwei - uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei - - address internal constant CUSTOM_TOKEN = address(12345); - uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM - - // Encode L1 gas price and L2 gas price into a packed price. - // L1 gas price is left-shifted to the higher-order bits. - uint224 internal constant PACKED_USD_PER_GAS = - (uint224(USD_PER_DATA_AVAILABILITY_GAS) << Internal.GAS_PRICE_BITS) + USD_PER_GAS; - - PriceRegistryHelper internal s_priceRegistry; - // Cheat to store the price updates in storage since struct arrays aren't supported. - bytes internal s_encodedInitialPriceUpdates; - address internal s_weth; - - address[] internal s_sourceFeeTokens; - uint224[] internal s_sourceTokenPrices; - address[] internal s_destFeeTokens; - uint224[] internal s_destTokenPrices; - - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] internal s_priceRegistryPremiumMultiplierWeiPerEthArgs; - PriceRegistry.TokenTransferFeeConfigArgs[] internal s_priceRegistryTokenTransferFeeConfigArgs; - - mapping(address token => address dataFeedAddress) internal s_dataFeedByToken; - - function setUp() public virtual override { - TokenSetup.setUp(); - - _deployTokenPriceDataFeed(s_sourceFeeToken, 8, 1e8); - - s_weth = s_sourceRouter.getWrappedNative(); - _deployTokenPriceDataFeed(s_weth, 8, 1e11); - - address[] memory sourceFeeTokens = new address[](3); - sourceFeeTokens[0] = s_sourceTokens[0]; - sourceFeeTokens[1] = s_sourceTokens[1]; - sourceFeeTokens[2] = s_sourceRouter.getWrappedNative(); - s_sourceFeeTokens = sourceFeeTokens; - - uint224[] memory sourceTokenPrices = new uint224[](3); - sourceTokenPrices[0] = 5e18; - sourceTokenPrices[1] = 2000e18; - sourceTokenPrices[2] = 2000e18; - s_sourceTokenPrices = sourceTokenPrices; - - address[] memory destFeeTokens = new address[](3); - destFeeTokens[0] = s_destTokens[0]; - destFeeTokens[1] = s_destTokens[1]; - destFeeTokens[2] = s_destRouter.getWrappedNative(); - s_destFeeTokens = destFeeTokens; - - uint224[] memory destTokenPrices = new uint224[](3); - destTokenPrices[0] = 5e18; - destTokenPrices[1] = 2000e18; - destTokenPrices[2] = 2000e18; - s_destTokenPrices = destTokenPrices; - - uint256 sourceTokenCount = sourceFeeTokens.length; - uint256 destTokenCount = destFeeTokens.length; - address[] memory pricedTokens = new address[](sourceTokenCount + destTokenCount); - uint224[] memory tokenPrices = new uint224[](sourceTokenCount + destTokenCount); - for (uint256 i = 0; i < sourceTokenCount; ++i) { - pricedTokens[i] = sourceFeeTokens[i]; - tokenPrices[i] = sourceTokenPrices[i]; - } - for (uint256 i = 0; i < destTokenCount; ++i) { - pricedTokens[i + sourceTokenCount] = destFeeTokens[i]; - tokenPrices[i + sourceTokenCount] = destTokenPrices[i]; - } - - Internal.PriceUpdates memory priceUpdates = getPriceUpdatesStruct(pricedTokens, tokenPrices); - priceUpdates.gasPriceUpdates = - getSingleGasPriceUpdateStruct(DEST_CHAIN_SELECTOR, PACKED_USD_PER_GAS).gasPriceUpdates; - - s_encodedInitialPriceUpdates = abi.encode(priceUpdates); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = OWNER; - address[] memory feeTokens = new address[](2); - feeTokens[0] = s_sourceTokens[0]; - feeTokens[1] = s_weth; - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](0); - - s_priceRegistryPremiumMultiplierWeiPerEthArgs.push( - PriceRegistry.PremiumMultiplierWeiPerEthArgs({ - token: s_sourceFeeToken, - premiumMultiplierWeiPerEth: 5e17 // 0.5x - }) - ); - s_priceRegistryPremiumMultiplierWeiPerEthArgs.push( - PriceRegistry.PremiumMultiplierWeiPerEthArgs({ - token: s_sourceRouter.getWrappedNative(), - premiumMultiplierWeiPerEth: 2e18 // 2x - }) - ); - - s_priceRegistryTokenTransferFeeConfigArgs.push(); - s_priceRegistryTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ - token: s_sourceFeeToken, - tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ - minFeeUSDCents: 1_00, // 1 USD - maxFeeUSDCents: 1000_00, // 1,000 USD - deciBps: 2_5, // 2.5 bps, or 0.025% - destGasOverhead: 40_000, - destBytesOverhead: 32, - isEnabled: true - }) - }) - ); - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ - token: s_sourceRouter.getWrappedNative(), - tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ - minFeeUSDCents: 50, // 0.5 USD - maxFeeUSDCents: 500_00, // 500 USD - deciBps: 5_0, // 5 bps, or 0.05% - destGasOverhead: 10_000, - destBytesOverhead: 100, - isEnabled: true - }) - }) - ); - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ - token: CUSTOM_TOKEN, - tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ - minFeeUSDCents: 2_00, // 1 USD - maxFeeUSDCents: 2000_00, // 1,000 USD - deciBps: 10_0, // 10 bps, or 0.1% - destGasOverhead: 1, - destBytesOverhead: 200, - isEnabled: true - }) - }) - ); - - s_priceRegistry = new PriceRegistryHelper( - PriceRegistry.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: uint32(TWELVE_HOURS) - }), - priceUpdaters, - feeTokens, - tokenPriceFeedUpdates, - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - _generatePriceRegistryDestChainConfigArgs() - ); - s_priceRegistry.updatePrices(priceUpdates); - } - - function _deployTokenPriceDataFeed(address token, uint8 decimals, int256 initialAnswer) internal returns (address) { - MockV3Aggregator dataFeed = new MockV3Aggregator(decimals, initialAnswer); - s_dataFeedByToken[token] = address(dataFeed); - return address(dataFeed); - } - - function getPriceUpdatesStruct( - address[] memory tokens, - uint224[] memory prices - ) internal pure returns (Internal.PriceUpdates memory) { - uint256 length = tokens.length; - - Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](length); - for (uint256 i = 0; i < length; ++i) { - tokenPriceUpdates[i] = Internal.TokenPriceUpdate({sourceToken: tokens[i], usdPerToken: prices[i]}); - } - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: new Internal.GasPriceUpdate[](0)}); - - return priceUpdates; - } - - function getEmptyPriceUpdates() internal pure returns (Internal.PriceUpdates memory priceUpdates) { - return Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - } - - function getSingleTokenPriceFeedUpdateStruct( - address sourceToken, - address dataFeedAddress, - uint8 tokenDecimals - ) internal pure returns (PriceRegistry.TokenPriceFeedUpdate memory) { - return PriceRegistry.TokenPriceFeedUpdate({ - sourceToken: sourceToken, - feedConfig: IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) - }); - } - - function _initialiseSingleTokenPriceFeed() internal returns (address) { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - return s_sourceTokens[0]; - } - - function _generateTokenTransferFeeConfigArgs( - uint256 destChainSelectorLength, - uint256 tokenLength - ) internal pure returns (PriceRegistry.TokenTransferFeeConfigArgs[] memory) { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new PriceRegistry.TokenTransferFeeConfigArgs[](destChainSelectorLength); - for (uint256 i = 0; i < destChainSelectorLength; ++i) { - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = - new PriceRegistry.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); - } - return tokenTransferFeeConfigArgs; - } - - function _generatePriceRegistryDestChainConfigArgs() - internal - pure - returns (PriceRegistry.DestChainConfigArgs[] memory) - { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigs = new PriceRegistry.DestChainConfigArgs[](1); - destChainConfigs[0] = PriceRegistry.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - destChainConfig: PriceRegistry.DestChainConfig({ - isEnabled: true, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - destGasOverhead: DEST_GAS_OVERHEAD, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - maxDataBytes: MAX_DATA_SIZE, - maxPerMsgGasLimit: MAX_GAS_LIMIT, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, - defaultTxGasLimit: GAS_LIMIT, - gasMultiplierWeiPerEth: 5e17, - networkFeeUSDCents: 1_00, - enforceOutOfOrder: false, - chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM - }) - }); - return destChainConfigs; - } - - function _assertTokenPriceFeedConfigEquality( - IPriceRegistry.TokenPriceFeedConfig memory config1, - IPriceRegistry.TokenPriceFeedConfig memory config2 - ) internal pure virtual { - assertEq(config1.dataFeedAddress, config2.dataFeedAddress); - assertEq(config1.tokenDecimals, config2.tokenDecimals); - } - - function _assertTokenPriceFeedConfigUnconfigured(IPriceRegistry.TokenPriceFeedConfig memory config) - internal - pure - virtual - { - _assertTokenPriceFeedConfigEquality( - config, IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) - ); - } - - function _assertTokenTransferFeeConfigEqual( - PriceRegistry.TokenTransferFeeConfig memory a, - PriceRegistry.TokenTransferFeeConfig memory b - ) internal pure { - assertEq(a.minFeeUSDCents, b.minFeeUSDCents); - assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); - assertEq(a.deciBps, b.deciBps); - assertEq(a.destGasOverhead, b.destGasOverhead); - assertEq(a.destBytesOverhead, b.destBytesOverhead); - assertEq(a.isEnabled, b.isEnabled); - } - - function _assertPriceRegistryStaticConfigsEqual( - PriceRegistry.StaticConfig memory a, - PriceRegistry.StaticConfig memory b - ) internal pure { - assertEq(a.linkToken, b.linkToken); - assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); - } - - function _assertPriceRegistryDestChainConfigsEqual( - PriceRegistry.DestChainConfig memory a, - PriceRegistry.DestChainConfig memory b - ) internal pure { - assertEq(a.isEnabled, b.isEnabled); - assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); - assertEq(a.maxDataBytes, b.maxDataBytes); - assertEq(a.maxPerMsgGasLimit, b.maxPerMsgGasLimit); - assertEq(a.destGasOverhead, b.destGasOverhead); - assertEq(a.destGasPerPayloadByte, b.destGasPerPayloadByte); - assertEq(a.destDataAvailabilityOverheadGas, b.destDataAvailabilityOverheadGas); - assertEq(a.destGasPerDataAvailabilityByte, b.destGasPerDataAvailabilityByte); - assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); - assertEq(a.defaultTokenFeeUSDCents, b.defaultTokenFeeUSDCents); - assertEq(a.defaultTokenDestGasOverhead, b.defaultTokenDestGasOverhead); - assertEq(a.defaultTokenDestBytesOverhead, b.defaultTokenDestBytesOverhead); - assertEq(a.defaultTxGasLimit, b.defaultTxGasLimit); - } -} - -contract PriceRegistryFeeSetup is PriceRegistrySetup { - uint224 internal s_feeTokenPrice; - uint224 internal s_wrappedTokenPrice; - uint224 internal s_customTokenPrice; - - address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); - - address internal s_destTokenPool = makeAddr("destTokenPool"); - address internal s_destToken = makeAddr("destToken"); - - function setUp() public virtual override { - super.setUp(); - - s_feeTokenPrice = s_sourceTokenPrices[0]; - s_wrappedTokenPrice = s_sourceTokenPrices[2]; - s_customTokenPrice = CUSTOM_TOKEN_PRICE; - - s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); - } - - function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _generateSingleTokenMessage( - address token, - uint256 amount - ) public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _messageToEvent( - Client.EVM2AnyMessage memory message, - uint64 sourceChainSelector, - uint64 destChainSelector, - uint64 seqNum, - uint64 nonce, - uint256 feeTokenAmount, - address originalSender, - bytes32 metadataHash, - TokenAdminRegistry tokenAdminRegistry - ) internal view returns (Internal.EVM2AnyRampMessage memory) { - Client.EVMExtraArgsV2 memory extraArgs = - s_priceRegistry.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); - - Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ - header: Internal.RampMessageHeader({ - messageId: "", - sourceChainSelector: sourceChainSelector, - destChainSelector: destChainSelector, - sequenceNumber: seqNum, - nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce - }), - sender: originalSender, - data: message.data, - receiver: message.receiver, - extraArgs: Client._argsToBytes(extraArgs), - feeToken: message.feeToken, - feeTokenAmount: feeTokenAmount, - tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) - }); - - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - messageEvent.tokenAmounts[i] = _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry); - } - - messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); - return messageEvent; - } - - function _getSourceTokenData( - Client.EVMTokenAmount memory tokenAmount, - TokenAdminRegistry tokenAdminRegistry - ) internal view returns (Internal.RampTokenAmount memory) { - address destToken = s_destTokenBySourceToken[tokenAmount.token]; - - return Internal.RampTokenAmount({ - sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), - destTokenAddress: abi.encode(destToken), - extraData: "", - amount: tokenAmount.amount - }); - } - - function calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { - return (tokenPrice * tokenAmount) / 1e18; - } - - function applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { - return (tokenAmount * ratio) / 1e5; - } - - function configUSDCentToWei(uint256 usdCent) internal pure returns (uint256) { - return usdCent * 1e16; - } -} - -contract PriceRegistry_constructor is PriceRegistrySetup { - function test_Setup_Success() public virtual { - address[] memory priceUpdaters = new address[](2); - priceUpdaters[0] = STRANGER; - priceUpdaters[1] = OWNER; - address[] memory feeTokens = new address[](2); - feeTokens[0] = s_sourceTokens[0]; - feeTokens[1] = s_sourceTokens[1]; - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](2); - tokenPriceFeedUpdates[0] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - tokenPriceFeedUpdates[1] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[1], s_dataFeedByToken[s_sourceTokens[1]], 6); - - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: uint32(TWELVE_HOURS) - }); - s_priceRegistry = new PriceRegistryHelper( - staticConfig, - priceUpdaters, - feeTokens, - tokenPriceFeedUpdates, - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - destChainConfigArgs - ); - - _assertPriceRegistryStaticConfigsEqual(s_priceRegistry.getStaticConfig(), staticConfig); - assertEq(feeTokens, s_priceRegistry.getFeeTokens()); - assertEq(priceUpdaters, s_priceRegistry.getAllAuthorizedCallers()); - assertEq(s_priceRegistry.typeAndVersion(), "PriceRegistry 1.6.0-dev"); - - _assertTokenPriceFeedConfigEquality( - tokenPriceFeedUpdates[0].feedConfig, s_priceRegistry.getTokenPriceFeedConfig(s_sourceTokens[0]) - ); - - _assertTokenPriceFeedConfigEquality( - tokenPriceFeedUpdates[1].feedConfig, s_priceRegistry.getTokenPriceFeedConfig(s_sourceTokens[1]) - ); - - assertEq( - s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].token) - ); - - assertEq( - s_priceRegistryPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(s_priceRegistryPremiumMultiplierWeiPerEthArgs[1].token) - ); - - PriceRegistry.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = - s_priceRegistryTokenTransferFeeConfigArgs[0]; - for (uint256 i = 0; i < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++i) { - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; - - _assertTokenTransferFeeConfigEqual( - tokenFeeArgs.tokenTransferFeeConfig, - s_priceRegistry.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) - ); - } - - for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { - PriceRegistry.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; - uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - - _assertPriceRegistryDestChainConfigsEqual(expectedConfig, s_priceRegistry.getDestChainConfig(destChainSelector)); - } - } - - function test_InvalidStalenessThreshold_Revert() public { - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: 0 - }); - - vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); - - s_priceRegistry = new PriceRegistryHelper( - staticConfig, - new address[](0), - new address[](0), - new PriceRegistry.TokenPriceFeedUpdate[](0), - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - new PriceRegistry.DestChainConfigArgs[](0) - ); - } - - function test_InvalidLinkTokenEqZeroAddress_Revert() public { - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ - linkToken: address(0), - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: uint32(TWELVE_HOURS) - }); - - vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); - - s_priceRegistry = new PriceRegistryHelper( - staticConfig, - new address[](0), - new address[](0), - new PriceRegistry.TokenPriceFeedUpdate[](0), - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - new PriceRegistry.DestChainConfigArgs[](0) - ); - } - - function test_InvalidMaxFeeJuelsPerMsg_Revert() public { - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: 0, - stalenessThreshold: uint32(TWELVE_HOURS) - }); - - vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); - - s_priceRegistry = new PriceRegistryHelper( - staticConfig, - new address[](0), - new address[](0), - new PriceRegistry.TokenPriceFeedUpdate[](0), - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - new PriceRegistry.DestChainConfigArgs[](0) - ); - } -} - -contract PriceRegistry_getTokenPrices is PriceRegistrySetup { - function test_GetTokenPrices_Success() public view { - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - - address[] memory tokens = new address[](3); - tokens[0] = s_sourceTokens[0]; - tokens[1] = s_sourceTokens[1]; - tokens[2] = s_weth; - - Internal.TimestampedPackedUint224[] memory tokenPrices = s_priceRegistry.getTokenPrices(tokens); - - assertEq(tokenPrices.length, 3); - assertEq(tokenPrices[0].value, priceUpdates.tokenPriceUpdates[0].usdPerToken); - assertEq(tokenPrices[1].value, priceUpdates.tokenPriceUpdates[1].usdPerToken); - assertEq(tokenPrices[2].value, priceUpdates.tokenPriceUpdates[2].usdPerToken); - } -} - -contract PriceRegistry_getTokenPrice is PriceRegistrySetup { - function test_GetTokenPriceFromFeed_Success() public { - uint256 originalTimestampValue = block.timestamp; - - // Below staleness threshold - vm.warp(originalTimestampValue + 1 hours); - - address sourceToken = _initialiseSingleTokenPriceFeed(); - Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_priceRegistry.getTokenPrice(sourceToken); - - // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer.value, uint224(1e18)); - assertEq(tokenPriceAnswer.timestamp, uint32(block.timestamp)); - } -} - -contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { - function test_GetValidatedTokenPrice_Success() public view { - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - address token = priceUpdates.tokenPriceUpdates[0].sourceToken; - - uint224 tokenPrice = s_priceRegistry.getValidatedTokenPrice(token); - - assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); - } - - function test_GetValidatedTokenPriceFromFeed_Success() public { - uint256 originalTimestampValue = block.timestamp; - - // Right below staleness threshold - vm.warp(originalTimestampValue + TWELVE_HOURS); - - address sourceToken = _initialiseSingleTokenPriceFeed(); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(sourceToken); - - // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer, uint224(1e18)); - } - - function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() public { - uint256 originalTimestampValue = block.timestamp; - - // Right above staleness threshold - vm.warp(originalTimestampValue + TWELVE_HOURS + 1); - - address sourceToken = _initialiseSingleTokenPriceFeed(); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(sourceToken); - - // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer, uint224(1e18)); - } - - function test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); - - // Price answer is: uint224.MAX_VALUE * (10 ** (36 - 18 - 18)) - assertEq(tokenPriceAnswer, uint224(type(uint224).max)); - } - - function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 6); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 6); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e6) -> expected 1e30 - assertEq(tokenPriceAnswer, uint224(1e30)); - } - - function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 24); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 24); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e24) -> expected 1e12 - assertEq(tokenPriceAnswer, uint224(1e12)); - } - - function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer, uint224(1e18)); - } - - function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 0); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 0); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e31 (0 decimal token) - unit is (1e18 * 1e18 / 1e0) -> expected 1e36 - assertEq(tokenPriceAnswer, uint224(1e67)); - } - - function test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 20); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 20); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e20) -> expected 1e14 - assertEq(tokenPriceAnswer, uint224(1e14)); - } - - function test_StaleFeeToken_Success() public { - vm.warp(block.timestamp + TWELVE_HOURS + 1); - - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - address token = priceUpdates.tokenPriceUpdates[0].sourceToken; - - uint224 tokenPrice = s_priceRegistry.getValidatedTokenPrice(token); - - assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); - } - - // Reverts - - function test_OverflowFeedPrice_Revert() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - vm.expectRevert(PriceRegistry.DataFeedValueOutOfUint224Range.selector); - s_priceRegistry.getValidatedTokenPrice(tokenAddress); - } - - function test_UnderflowFeedPrice_Revert() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - vm.expectRevert(PriceRegistry.DataFeedValueOutOfUint224Range.selector); - s_priceRegistry.getValidatedTokenPrice(tokenAddress); - } - - function test_TokenNotSupported_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_priceRegistry.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); - } - - function test_TokenNotSupportedFeed_Revert() public { - address sourceToken = _initialiseSingleTokenPriceFeed(); - MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, sourceToken)); - s_priceRegistry.getValidatedTokenPrice(sourceToken); - } -} - -contract PriceRegistry_applyFeeTokensUpdates is PriceRegistrySetup { - function test_ApplyFeeTokensUpdates_Success() public { - address[] memory feeTokens = new address[](1); - feeTokens[0] = s_sourceTokens[1]; - - vm.expectEmit(); - emit PriceRegistry.FeeTokenAdded(feeTokens[0]); - - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - assertEq(s_priceRegistry.getFeeTokens().length, 3); - assertEq(s_priceRegistry.getFeeTokens()[2], feeTokens[0]); - - // add same feeToken is no-op - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - assertEq(s_priceRegistry.getFeeTokens().length, 3); - assertEq(s_priceRegistry.getFeeTokens()[2], feeTokens[0]); - - vm.expectEmit(); - emit PriceRegistry.FeeTokenRemoved(feeTokens[0]); - - s_priceRegistry.applyFeeTokensUpdates(new address[](0), feeTokens); - assertEq(s_priceRegistry.getFeeTokens().length, 2); - - // removing already removed feeToken is no-op - s_priceRegistry.applyFeeTokensUpdates(new address[](0), feeTokens); - assertEq(s_priceRegistry.getFeeTokens().length, 2); - } - - function test_OnlyCallableByOwner_Revert() public { - address[] memory feeTokens = new address[](1); - feeTokens[0] = STRANGER; - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - } -} - -contract PriceRegistry_updatePrices is PriceRegistrySetup { - function test_OnlyTokenPrice_Success() public { - 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: 4e18}); - - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated( - update.tokenPriceUpdates[0].sourceToken, update.tokenPriceUpdates[0].usdPerToken, block.timestamp - ); - - s_priceRegistry.updatePrices(update); - - assertEq(s_priceRegistry.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); - } - - function test_OnlyGasPrice_Success() public { - Internal.PriceUpdates memory update = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), - gasPriceUpdates: new Internal.GasPriceUpdate[](1) - }); - update.gasPriceUpdates[0] = - Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); - - vm.expectEmit(); - emit PriceRegistry.UsdPerUnitGasUpdated( - update.gasPriceUpdates[0].destChainSelector, update.gasPriceUpdates[0].usdPerUnitGas, block.timestamp - ); - - s_priceRegistry.updatePrices(update); - - assertEq( - s_priceRegistry.getDestinationChainGasPrice(DEST_CHAIN_SELECTOR).value, update.gasPriceUpdates[0].usdPerUnitGas - ); - } - - function test_UpdateMultiplePrices_Success() 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}); - tokenPriceUpdates[2] = Internal.TokenPriceUpdate({sourceToken: address(12345), usdPerToken: 1e18}); - - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](3); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2e6}); - gasPriceUpdates[1] = Internal.GasPriceUpdate({destChainSelector: SOURCE_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); - gasPriceUpdates[2] = Internal.GasPriceUpdate({destChainSelector: 12345, usdPerUnitGas: 1e18}); - - Internal.PriceUpdates memory update = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); - - for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated( - update.tokenPriceUpdates[i].sourceToken, update.tokenPriceUpdates[i].usdPerToken, block.timestamp - ); - } - for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { - vm.expectEmit(); - emit PriceRegistry.UsdPerUnitGasUpdated( - update.gasPriceUpdates[i].destChainSelector, update.gasPriceUpdates[i].usdPerUnitGas, block.timestamp - ); - } - - s_priceRegistry.updatePrices(update); - - for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { - assertEq( - s_priceRegistry.getTokenPrice(update.tokenPriceUpdates[i].sourceToken).value, tokenPriceUpdates[i].usdPerToken - ); - } - for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { - assertEq( - s_priceRegistry.getDestinationChainGasPrice(update.gasPriceUpdates[i].destChainSelector).value, - gasPriceUpdates[i].usdPerUnitGas - ); - } - } - - function test_UpdatableByAuthorizedCaller_Success() public { - Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); - - // Revert when caller is not authorized - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_priceRegistry.updatePrices(priceUpdates); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = STRANGER; - vm.startPrank(OWNER); - s_priceRegistry.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) - ); - - // Stranger is now an authorized caller to update prices - vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated( - priceUpdates.tokenPriceUpdates[0].sourceToken, priceUpdates.tokenPriceUpdates[0].usdPerToken, block.timestamp - ); - s_priceRegistry.updatePrices(priceUpdates); - - assertEq(s_priceRegistry.getTokenPrice(s_sourceTokens[0]).value, priceUpdates.tokenPriceUpdates[0].usdPerToken); - - vm.startPrank(OWNER); - s_priceRegistry.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: new address[](0), removedCallers: priceUpdaters}) - ); - - // Revert when authorized caller is removed - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_priceRegistry.updatePrices(priceUpdates); - } - - // Reverts - - function test_OnlyCallableByUpdater_Revert() public { - Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_priceRegistry.updatePrices(priceUpdates); - } -} - -contract PriceRegistry_convertTokenAmount is PriceRegistrySetup { - function test_ConvertTokenAmount_Success() public view { - Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - uint256 amount = 3e16; - uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) - / uint256(initialPriceUpdates.tokenPriceUpdates[0].usdPerToken); - uint256 expected = (amount * conversionRate) / 1e18; - assertEq(s_priceRegistry.convertTokenAmount(s_weth, amount, s_sourceTokens[0]), expected); - } - - function test_Fuzz_ConvertTokenAmount_Success( - uint256 feeTokenAmount, - uint224 usdPerFeeToken, - uint160 usdPerLinkToken, - uint224 usdPerUnitGas - ) public { - vm.assume(usdPerFeeToken > 0); - vm.assume(usdPerLinkToken > 0); - // We bound the max fees to be at most uint96.max link. - feeTokenAmount = bound(feeTokenAmount, 0, (uint256(type(uint96).max) * usdPerLinkToken) / usdPerFeeToken); - - address feeToken = address(1); - address linkToken = address(2); - address[] memory feeTokens = new address[](1); - feeTokens[0] = feeToken; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - - Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](2); - tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: feeToken, usdPerToken: usdPerFeeToken}); - tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: linkToken, usdPerToken: usdPerLinkToken}); - - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: usdPerUnitGas}); - - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); - - s_priceRegistry.updatePrices(priceUpdates); - - uint256 linkFee = s_priceRegistry.convertTokenAmount(feeToken, feeTokenAmount, linkToken); - assertEq(linkFee, (feeTokenAmount * usdPerFeeToken) / usdPerLinkToken); - } - - // Reverts - - function test_LinkTokenNotSupported_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_priceRegistry.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_priceRegistry.convertTokenAmount(s_sourceTokens[0], 3e16, DUMMY_CONTRACT_ADDRESS); - } -} - -contract PriceRegistry_getTokenAndGasPrices is PriceRegistrySetup { - function test_GetFeeTokenAndGasPrices_Success() public view { - (uint224 feeTokenPrice, uint224 gasPrice) = - s_priceRegistry.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); - - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - - assertEq(feeTokenPrice, s_sourceTokenPrices[0]); - assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); - } - - function test_ZeroGasPrice_Success() public { - uint64 zeroGasDestChainSelector = 345678; - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: zeroGasDestChainSelector, usdPerUnitGas: 0}); - - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); - s_priceRegistry.updatePrices(priceUpdates); - - (, uint224 gasPrice) = s_priceRegistry.getTokenAndGasPrices(s_sourceFeeToken, zeroGasDestChainSelector); - - assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); - } - - function test_UnsupportedChain_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.ChainNotSupported.selector, DEST_CHAIN_SELECTOR + 1)); - s_priceRegistry.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); - } - - function test_StaleGasPrice_Revert() public { - uint256 diff = TWELVE_HOURS + 1; - vm.warp(block.timestamp + diff); - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff) - ); - s_priceRegistry.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR); - } -} - -contract PriceRegistry_updateTokenPriceFeeds is PriceRegistrySetup { - function test_ZeroFeeds_Success() public { - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](0); - vm.recordLogs(); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - // Verify no log emissions - assertEq(logEntries.length, 0); - } - - function test_SingleFeedUpdate_Success() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - _assertTokenPriceFeedConfigUnconfigured( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken) - ); - - vm.expectEmit(); - emit PriceRegistry.PriceFeedPerTokenUpdated( - tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig - ); - - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - } - - function test_MultipleFeedUpdate_Success() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](2); - - for (uint256 i = 0; i < 2; ++i) { - tokenPriceFeedUpdates[i] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[i], s_dataFeedByToken[s_sourceTokens[i]], 18); - - _assertTokenPriceFeedConfigUnconfigured( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[i].sourceToken) - ); - - vm.expectEmit(); - emit PriceRegistry.PriceFeedPerTokenUpdated( - tokenPriceFeedUpdates[i].sourceToken, tokenPriceFeedUpdates[i].feedConfig - ); - } - - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[1].sourceToken), tokenPriceFeedUpdates[1].feedConfig - ); - } - - function test_FeedUnset_Success() public { - Internal.TimestampedPackedUint224 memory priceQueryInitial = s_priceRegistry.getTokenPrice(s_sourceTokens[0]); - assertFalse(priceQueryInitial.value == 0); - assertFalse(priceQueryInitial.timestamp == 0); - - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - - tokenPriceFeedUpdates[0].feedConfig.dataFeedAddress = address(0); - vm.expectEmit(); - emit PriceRegistry.PriceFeedPerTokenUpdated( - tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig - ); - - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - - // Price data should remain after a feed has been set->unset - Internal.TimestampedPackedUint224 memory priceQueryPostUnsetFeed = s_priceRegistry.getTokenPrice(s_sourceTokens[0]); - assertEq(priceQueryPostUnsetFeed.value, priceQueryInitial.value); - assertEq(priceQueryPostUnsetFeed.timestamp, priceQueryInitial.timestamp); - } - - function test_FeedNotUpdated() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - } - - // Reverts - - function test_FeedUpdatedByNonOwner_Revert() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - } -} - -contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { - function test_Fuzz_applyDestChainConfigUpdates_Success(PriceRegistry.DestChainConfigArgs memory destChainConfigArgs) - public - { - vm.assume(destChainConfigArgs.destChainSelector != 0); - vm.assume(destChainConfigArgs.destChainConfig.maxPerMsgGasLimit != 0); - destChainConfigArgs.destChainConfig.defaultTxGasLimit = uint32( - bound( - destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit - ) - ); - destChainConfigArgs.destChainConfig.defaultTokenDestBytesOverhead = uint32( - bound( - destChainConfigArgs.destChainConfig.defaultTokenDestBytesOverhead, - Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, - type(uint32).max - ) - ); - destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - - bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; - - PriceRegistry.DestChainConfigArgs[] memory newDestChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); - newDestChainConfigArgs[0] = destChainConfigArgs; - - if (isNewChain) { - vm.expectEmit(); - emit PriceRegistry.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); - } else { - vm.expectEmit(); - emit PriceRegistry.DestChainConfigUpdated( - destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig - ); - } - - s_priceRegistry.applyDestChainConfigUpdates(newDestChainConfigArgs); - - _assertPriceRegistryDestChainConfigsEqual( - destChainConfigArgs.destChainConfig, s_priceRegistry.getDestChainConfig(destChainConfigArgs.destChainSelector) - ); - } - - function test_applyDestChainConfigUpdates_Success() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](2); - destChainConfigArgs[0] = _generatePriceRegistryDestChainConfigArgs()[0]; - destChainConfigArgs[0].destChainConfig.isEnabled = false; - destChainConfigArgs[1] = _generatePriceRegistryDestChainConfigArgs()[0]; - destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; - - vm.expectEmit(); - emit PriceRegistry.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); - vm.expectEmit(); - emit PriceRegistry.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); - - vm.recordLogs(); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - PriceRegistry.DestChainConfig memory gotDestChainConfig0 = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - PriceRegistry.DestChainConfig memory gotDestChainConfig1 = - s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); - - assertEq(vm.getRecordedLogs().length, 2); - _assertPriceRegistryDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); - _assertPriceRegistryDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); - } - - function test_applyDestChainConfigUpdatesZeroIntput_Success() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](0); - - vm.recordLogs(); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.defaultTxGasLimit = 0; - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - // Allow setting to the max value - destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - // Revert when exceeding max value - destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit + 1; - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainSelector = 0; - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidDestBytesOverhead_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.defaultTokenDestBytesOverhead = uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1); - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, DEST_CHAIN_SELECTOR)); - - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidChainFamilySelector_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1)); - - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - } -} - -contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { - function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { - uint256 dataAvailabilityCostUSD = - s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas - + destChainConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; - uint256 expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - - // Test that the cost is destnation chain specific - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; - destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = - destChainConfig.destDataAvailabilityOverheadGas * 2; - destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = - destChainConfig.destGasPerDataAvailabilityByte * 2; - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = - destChainConfig.destDataAvailabilityMultiplierBps * 2; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); - uint256 dataAvailabilityCostUSD2 = - s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas - + destChainConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; - expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD2); - assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); - } - - function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { - uint256 dataAvailabilityCostUSD = - s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 dataAvailabilityLengthBytes = - Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + 100 + (5 * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; - uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas - + destChainConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } - - function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { - uint256 dataAvailabilityCostUSD = - s_priceRegistry.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - assertEq(dataAvailabilityCostUSD, 0); - } - - function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public view { - uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead - ); - - assertEq(0, dataAvailabilityCostUSD); - } - - function test_Fuzz_CalculateDataAvailabilityCost_Success( - uint64 destChainSelector, - uint32 destDataAvailabilityOverheadGas, - uint16 destGasPerDataAvailabilityByte, - uint16 destDataAvailabilityMultiplierBps, - uint112 dataAvailabilityGasPrice, - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public { - vm.assume(destChainSelector != 0); - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(destChainSelector); - destChainConfigArgs[0] = - PriceRegistry.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); - destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; - destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; - destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; - destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; - destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - destChainConfigArgs[0].destChainConfig.defaultTokenDestBytesOverhead = DEFAULT_TOKEN_BYTES_OVERHEAD; - - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( - destChainConfigArgs[0].destChainSelector, - dataAvailabilityGasPrice, - messageDataLength, - numberOfTokens, - tokenTransferBytesOverhead - ); - - uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - uint256 dataAvailabilityGas = - destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } -} - -contract PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates is PriceRegistrySetup { - function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( - PriceRegistry.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg - ) public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; - - vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( - premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth - ); - - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = s_priceRegistryPremiumMultiplierWeiPerEthArgs[0]; - premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); - - vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( - vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(1)) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](2); - premiumMultiplierWeiPerEthArgs[0] = s_priceRegistryPremiumMultiplierWeiPerEthArgs[0]; - premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); - premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); - - vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( - vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( - vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth - ); - - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(1)) - ); - assertEq( - premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(2)) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { - vm.recordLogs(); - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](0)); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - } -} - -contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup { - function test_Fuzz_ApplyTokenTransferFeeConfig_Success( - PriceRegistry.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs - ) public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(2, 2); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; - - for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { - for (uint256 j = 0; j < tokenTransferFeeConfigs.length; ++j) { - tokenTransferFeeConfigs[j].destBytesOverhead = uint32( - bound(tokenTransferFeeConfigs[j].destBytesOverhead, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, type(uint32).max) - ); - address feeToken = s_sourceTokens[j]; - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].token = feeToken; - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; - - vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] - ); - } - } - - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - - for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigs[i], - s_priceRegistry.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token - ) - ); - } - } - - function test_ApplyTokenTransferFeeConfig_Success() public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 2); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: 312, - isEnabled: true - }); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ - minFeeUSDCents: 12, - maxFeeUSDCents: 13, - deciBps: 14, - destGasOverhead: 15, - destBytesOverhead: 394, - isEnabled: true - }); - - vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig - ); - vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig - ); - - PriceRegistry.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = - new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0); - s_priceRegistry.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); - - PriceRegistry.TokenTransferFeeConfig memory config0 = s_priceRegistry.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - PriceRegistry.TokenTransferFeeConfig memory config1 = s_priceRegistry.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token - ); - - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig, config0 - ); - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 - ); - - // Remove only the first token and validate only the first token is removed - tokensToRemove = new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](1); - tokensToRemove[0] = PriceRegistry.TokenTransferFeeConfigRemoveArgs({ - destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, - token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - }); - - vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigDeleted( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - new PriceRegistry.TokenTransferFeeConfigArgs[](0), tokensToRemove - ); - - config0 = s_priceRegistry.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - config1 = s_priceRegistry.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token - ); - - PriceRegistry.TokenTransferFeeConfig memory emptyConfig; - - _assertTokenTransferFeeConfigEqual(emptyConfig, config0); - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 - ); - } - - function test_ApplyTokenTransferFeeZeroInput() public { - vm.recordLogs(); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - new PriceRegistry.TokenTransferFeeConfigArgs[](0), new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - vm.startPrank(STRANGER); - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; - - vm.expectRevert("Only callable by owner"); - - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - } - - function test_InvalidDestBytesOverhead_Revert() public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1), - isEnabled: true - }); - - vm.expectRevert( - abi.encodeWithSelector( - PriceRegistry.InvalidDestBytesOverhead.selector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead - ) - ); - - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - } -} - -contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_NoTokenTransferChargesZeroFee_Success() public view { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(0, feeUSDWei); - assertEq(0, destGasOverhead); - assertEq(0, destBytesOverhead); - } - - function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); - - // Get config to assert it isn't set - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - assertFalse(transferFeeConfig.isEnabled); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // Assert that the default values are used - assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); - assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); - assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); - } - - function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_FeeTokenBpsFee_Success() public view { - uint256 tokenAmount = 10000e18; - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); - uint256 bpsUSDWei = applyBpsRatio( - usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps - ); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_WETHTokenBpsFee_Success() public view { - uint256 tokenAmount = 100e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceRouter.getWrappedNative(), amount: tokenAmount}); - - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_wrappedTokenPrice, tokenAmount); - uint256 bpsUSDWei = applyBpsRatio( - usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps - ); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_CustomTokenBpsFee_Success() public view { - uint256 tokenAmount = 200000e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); - - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); - uint256 bpsUSDWei = applyBpsRatio( - usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[2].tokenTransferFeeConfig.deciBps - ); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroFeeConfigChargesMinFee_Success() public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), - isEnabled: true - }); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // if token charges 0 bps, it should cost minFee to transfer - assertEq( - configUSDCentToWei(tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.minFeeUSDCents), - feeUSDWei - ); - assertEq(0, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { - // It shouldn't be possible to pay materially lower fees by splitting up the transfers. - // Note it is possible to pay higher fees since the minimum fees are added. - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - transfers = bound(transfers, 1, destChainConfig.maxNumberOfTokensPerMsg); - // Cap amount to avoid overflow - amount = bound(amount, 0, 1e36); - Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); - for (uint256 i = 0; i < transfers; ++i) { - multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); - } - Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); - single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); - - address feeToken = s_sourceRouter.getWrappedNative(); - - (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); - (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); - - // Note that there can be a rounding error once per split. - assertGe(feeMultipleUSDWei, (feeSingleUSDWei - destChainConfig.maxNumberOfTokensPerMsg)); - assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); - assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); - } - - function test_MixedTokenTransferFee_Success() public view { - address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; - uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; - PriceRegistry.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) - ]; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](3), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - uint256 expectedTotalGas = 0; - uint256 expectedTotalBytes = 0; - - // Start with small token transfers, total bps fee is lower than min token transfer fee - for (uint256 i = 0; i < testTokens.length; ++i) { - message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); - expectedTotalGas += s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]).destGasOverhead; - expectedTotalBytes += - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]).destBytesOverhead; - } - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); - - uint256 expectedFeeUSDWei = 0; - for (uint256 i = 0; i < testTokens.length; ++i) { - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[i].minFeeUSDCents); - } - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - - // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee - message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); - expectedFeeUSDWei = applyBpsRatio( - calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].minFeeUSDCents); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - - // Set 2nd token transfer to a large amount that is higher than maxFeeUSD - message.tokenAmounts[1] = Client.EVMTokenAmount({token: testTokens[1], amount: 1e36}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); - expectedFeeUSDWei = applyBpsRatio( - calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].maxFeeUSDCents); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - } -} - -contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_EmptyMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = testTokens[i]; - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 feeAmount = s_priceRegistry.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 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_ZeroDataAvailabilityMultiplier_Success() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - destChainConfigArgs[0] = - PriceRegistry.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - - uint256 feeAmount = s_priceRegistry.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 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; - assertEq(totalPriceInFeeToken, feeAmount); - } - - function test_HighGasMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = MAX_GAS_LIMIT; - uint256 customDataSize = MAX_DATA_SIZE; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: new bytes(customDataSize), - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 feeAmount = s_priceRegistry.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 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_SingleTokenMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 tokenAmount = 10000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - message.feeToken = testTokens[i]; - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - uint32 destBytesOverhead = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; - uint32 tokenBytesOverhead = - destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - - uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD - + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts - ); - uint256 messageFeeUSD = (transferFeeUSD * s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken)); - uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, - USD_PER_DATA_AVAILABILITY_GAS, - message.data.length, - message.tokenAmounts.length, - tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_MessageWithDataAndTokenTransfer_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = 1_000_000; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](2), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount - message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount - message.data = "random bits and bytes that should be factored into the cost of the message"; - - uint32 tokenGasOverhead = 0; - uint32 tokenBytesOverhead = 0; - for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { - tokenGasOverhead += - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; - uint32 destBytesOverhead = s_priceRegistry.getTokenTransferFeeConfig( - DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token - ).destBytesOverhead; - 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,,) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts - ); - uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, - USD_PER_DATA_AVAILABILITY_GAS, - message.data.length, - message.tokenAmounts.length, - tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message)); - } - } - - function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { - // Update config to enforce allowOutOfOrderExecution = defaultVal. - vm.stopPrank(); - vm.startPrank(OWNER); - - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = enforce; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) - ); - - // If enforcement is on, only true should be allowed. - if (enforce && !allowOutOfOrderExecution) { - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - } - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - // Reverts - - function test_DestinationChainNotEnabled_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); - } - - function test_EnforceOutOfOrder_Revert() public { - // Update config to enforce allowOutOfOrderExecution = true. - vm.stopPrank(); - vm.startPrank(OWNER); - - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - vm.stopPrank(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - // Empty extraArgs to should revert since it enforceOutOfOrder is true. - message.extraArgs = ""; - - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_MessageTooLarge_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); - - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_TooManyTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 tooMany = MAX_TOKENS_LENGTH + 1; - message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(PriceRegistry.UnsupportedNumberOfTokens.selector); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.MessageGasLimitTooHigh.selector)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_NotAFeeToken_Revert() public { - address notAFeeToken = address(0x111111); - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); - message.feeToken = notAFeeToken; - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, notAFeeToken)); - - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_InvalidEVMAddress_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(type(uint208).max); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { - using USDPriceWith18Decimals for uint224; - - function setUp() public virtual override { - super.setUp(); - } - - function test_WithLinkTokenAmount_Success() public view { - ( - uint256 msgFeeJuels, - /* bool isOutOfOrderExecution */ - , - /* bytes memory convertedExtraArgs */ - ) = s_priceRegistry.processMessageArgs( - DEST_CHAIN_SELECTOR, - // LINK - s_sourceTokens[0], - MAX_MSG_FEES_JUELS, - "" - ); - - assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); - } - - function test_WithConvertedTokenAmount_Success() public view { - address feeToken = s_sourceTokens[1]; - uint256 feeTokenAmount = 10_000 gwei; - uint256 expectedConvertedAmount = s_priceRegistry.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); - - ( - uint256 msgFeeJuels, - /* bool isOutOfOrderExecution */ - , - /* bytes memory convertedExtraArgs */ - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, feeToken, feeTokenAmount, ""); - - assertEq(msgFeeJuels, expectedConvertedAmount); - } - - function test_WithEmptyEVMExtraArgs_Success() public view { - ( - /* uint256 msgFeeJuels */ - , - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, ""); - - assertEq(isOutOfOrderExecution, false); - assertEq( - convertedExtraArgs, Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR)) - ); - } - - function test_WithEVMExtraArgsV1_Success() public view { - bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); - - ( - /* uint256 msgFeeJuels */ - , - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); - - assertEq(isOutOfOrderExecution, false); - assertEq( - convertedExtraArgs, - Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) - ); - } - - function test_WitEVMExtraArgsV2_Success() public view { - bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); - - ( - /* uint256 msgFeeJuels */ - , - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); - - assertEq(isOutOfOrderExecution, true); - assertEq( - convertedExtraArgs, - Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) - ); - } - - // Reverts - - function test_MessageFeeTooHigh_Revert() public { - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) - ); - - s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS + 1, ""); - } - - function test_InvalidExtraArgs_Revert() public { - vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); - - s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "abcde"); - } - - function test_MalformedEVMExtraArgs_Revert() public { - // abi.decode error - vm.expectRevert(); - - s_priceRegistry.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - 0, - abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})) - ); - } -} - -contract PriceRegistry_validatePoolReturnData is PriceRegistryFeeSetup { - function test_WithSingleToken_Success() public view { - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); - sourceTokenAmounts[0].amount = 1e18; - sourceTokenAmounts[0].token = s_sourceTokens[0]; - - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); - - // No revert - successful - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - } - - function test_TokenAmountArraysMismatching_Revert() public { - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); - sourceTokenAmounts[0].amount = 1e18; - sourceTokenAmounts[0].token = s_sourceTokens[0]; - - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); - - // Revert due to index out of bounds access - vm.expectRevert(); - - s_priceRegistry.validatePoolReturnData( - DEST_CHAIN_SELECTOR, new Internal.RampTokenAmount[](1), new Client.EVMTokenAmount[](0) - ); - } - - function test_SourceTokenDataTooLarge_Revert() public { - address sourceETH = s_sourceTokens[1]; - - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); - sourceTokenAmounts[0].amount = 1000; - sourceTokenAmounts[0].token = sourceETH; - - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); - - // No data set, should succeed - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - - // Set max data length, should succeed - rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - - // Set data to max length +1, should revert - rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - - // Set token config to allow larger data - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, - isEnabled: true - }); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) - ); - - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - - // Set the token data larger than the configured token data, should revert - rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - } - - function test_InvalidEVMAddressDestToken_Revert() public { - bytes memory nonEvmAddress = abi.encode(type(uint208).max); - - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); - sourceTokenAmounts[0].amount = 1e18; - sourceTokenAmounts[0].token = s_sourceTokens[0]; - - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); - rampTokenAmounts[0].destTokenAddress = nonEvmAddress; - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); - } -} - -contract PriceRegistry_validateDestFamilyAddress is PriceRegistrySetup { - function test_ValidEVMAddress_Success() public view { - bytes memory encodedAddress = abi.encode(address(10000)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); - } - - function test_ValidNonEVMAddress_Success() public view { - s_priceRegistry.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); - } - - // Reverts - - function test_InvalidEVMAddress_Revert() public { - bytes memory invalidAddress = abi.encode(type(uint208).max); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } - - function test_InvalidEVMAddressEncodePacked_Revert() public { - bytes memory invalidAddress = abi.encodePacked(address(234)); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } - - function test_InvalidEVMAddressPrecompiles_Revert() 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_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } - - s_priceRegistry.validateDestFamilyAddress( - Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) - ); - } -} - -contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { - PriceRegistry.DestChainConfig private s_destChainConfig; - - function setUp() public virtual override { - super.setUp(); - s_destChainConfig = _generatePriceRegistryDestChainConfigArgs()[0].destChainConfig; - } - - function test_EVMExtraArgsV1_Success() 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_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), - abi.encode(expectedOutputArgs) - ); - } - - function test_EVMExtraArgsV2_Success() public view { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - - vm.assertEq( - abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) - ); - } - - function test_EVMExtraArgsDefault_Success() public view { - Client.EVMExtraArgsV2 memory expectedOutputArgs = - Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); - - vm.assertEq( - abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) - ); - } - - // Reverts - - function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - // Invalidate selector - inputExtraArgs[0] = bytes1(uint8(0)); - - vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); - s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); - } - - function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - s_destChainConfig.enforceOutOfOrder = true; - - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); - } - - function test_EVMExtraArgsGasLimitTooHigh_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - - vm.expectRevert(PriceRegistry.MessageGasLimitTooHigh.selector); - s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); - } -} diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol deleted file mode 100644 index d3a07ef11e9..00000000000 --- a/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {AggregateRateLimiterHelper} from "../helpers/AggregateRateLimiterHelper.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; - -import {stdError} from "forge-std/Test.sol"; - -contract AggregateTokenLimiterSetup is PriceRegistrySetup { - AggregateRateLimiterHelper internal s_rateLimiter; - RateLimiter.Config internal s_config; - - address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; - uint224 internal constant TOKEN_PRICE = 4e18; - - function setUp() public virtual override { - PriceRegistrySetup.setUp(); - - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); - s_priceRegistry.updatePrices(priceUpdates); - - s_config = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); - s_rateLimiter = new AggregateRateLimiterHelper(s_config); - s_rateLimiter.setAdmin(ADMIN); - } -} - -contract AggregateTokenLimiter_constructor is AggregateTokenLimiterSetup { - function test_Constructor_Success() public view { - assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); - assertEq(OWNER, s_rateLimiter.owner()); - - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - } -} - -contract AggregateTokenLimiter_getTokenLimitAdmin is AggregateTokenLimiterSetup { - function test_GetTokenLimitAdmin_Success() public view { - assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); - } -} - -contract AggregateTokenLimiter_setAdmin is AggregateTokenLimiterSetup { - function test_Owner_Success() public { - vm.expectEmit(); - emit AggregateRateLimiter.AdminSet(STRANGER); - - s_rateLimiter.setAdmin(STRANGER); - assertEq(STRANGER, s_rateLimiter.getTokenLimitAdmin()); - } - - // Reverts - - function test_OnlyOwnerOrAdmin_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(RateLimiter.OnlyCallableByAdminOrOwner.selector); - - s_rateLimiter.setAdmin(STRANGER); - } -} - -contract AggregateTokenLimiter_getTokenBucket is AggregateTokenLimiterSetup { - function test_GetTokenBucket_Success() public view { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(BLOCK_TIME, bucket.lastUpdated); - } - - function test_Refill_Success() public { - s_config.capacity = s_config.capacity * 2; - s_rateLimiter.setRateLimiterConfig(s_config); - - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 2, bucket.tokens); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - uint256 warpTime = 4; - vm.warp(BLOCK_TIME + warpTime); - - bucket = s_rateLimiter.currentRateLimiterState(); - - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 2 + warpTime * s_config.rate, bucket.tokens); - assertEq(BLOCK_TIME + warpTime, bucket.lastUpdated); - - vm.warp(BLOCK_TIME + warpTime * 100); - - // Bucket overflow - bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.capacity, bucket.tokens); - } - - // Reverts - - function test_TimeUnderflow_Revert() public { - vm.warp(BLOCK_TIME - 1); - - vm.expectRevert(stdError.arithmeticError); - s_rateLimiter.currentRateLimiterState(); - } -} - -contract AggregateTokenLimiter_setRateLimiterConfig is AggregateTokenLimiterSetup { - function test_Owner_Success() public { - setConfig(); - } - - function test_TokenLimitAdmin_Success() public { - vm.startPrank(ADMIN); - setConfig(); - } - - function setConfig() private { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - - if (bucket.isEnabled) { - s_config = RateLimiter.Config({isEnabled: false, rate: 0, capacity: 0}); - } else { - s_config = RateLimiter.Config({isEnabled: true, rate: 100, capacity: 200}); - } - - vm.expectEmit(); - emit RateLimiter.ConfigChanged(s_config); - - s_rateLimiter.setRateLimiterConfig(s_config); - - bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.isEnabled, bucket.isEnabled); - } - - // Reverts - - function test_OnlyOnlyCallableByAdminOrOwner_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(RateLimiter.OnlyCallableByAdminOrOwner.selector); - - s_rateLimiter.setRateLimiterConfig(s_config); - } -} - -contract AggregateTokenLimiter_rateLimitValue is AggregateTokenLimiterSetup { - function test_RateLimitValueSuccess_gas() public { - vm.pauseGasMetering(); - // start from blocktime that does not equal rate limiter init timestamp - vm.warp(BLOCK_TIME + 1); - - // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) - uint256 numberOfTokens = 15; - uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(value); - - vm.resumeGasMetering(); - s_rateLimiter.rateLimitValue(value); - vm.pauseGasMetering(); - - // Get the updated bucket status - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - // Assert the proper value has been taken out of the bucket - assertEq(bucket.capacity - value, bucket.tokens); - - // Since value * 2 > bucket.capacity we cannot take it out twice. - // Expect a revert when we try, with a wait time. - uint256 waitTime = 4; - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) - ); - s_rateLimiter.rateLimitValue(value); - - // Move the block time forward by 10 so the bucket refills by 10 * rate - vm.warp(BLOCK_TIME + 1 + waitTime); - - // The bucket has filled up enough so we can take out more tokens - s_rateLimiter.rateLimitValue(value); - bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(bucket.capacity - value + waitTime * s_config.rate - value, bucket.tokens); - vm.resumeGasMetering(); - } - - // Reverts - - function test_AggregateValueMaxCapacityExceeded_Revert() public { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - - uint256 numberOfTokens = 100; - uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueMaxCapacityExceeded.selector, bucket.capacity, (numberOfTokens * TOKEN_PRICE) / 1e18 - ) - ); - s_rateLimiter.rateLimitValue(value); - } -} - -contract AggregateTokenLimiter_getTokenValue is AggregateTokenLimiterSetup { - function test_GetTokenValue_Success() public view { - uint256 numberOfTokens = 10; - Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); - uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); - assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); - } - - // Reverts - function test_NoTokenPrice_Reverts() public { - address tokenWithNoPrice = makeAddr("Token with no price"); - Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); - - vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); - s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); - } -} diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 2bd31452f00..a7d73cc8b37 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -7,12 +7,13 @@ 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"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; import {stdError} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; -contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { +contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { MultiAggregateRateLimiterHelper internal s_rateLimiter; address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; @@ -29,12 +30,12 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { address[] internal s_authorizedCallers; - function setUp() public virtual override(BaseTest, PriceRegistrySetup) { + function setUp() public virtual override(BaseTest, FeeQuoterSetup) { BaseTest.setUp(); - PriceRegistrySetup.setUp(); + FeeQuoterSetup.setUp(); - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); - s_priceRegistry.updatePrices(priceUpdates); + Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); + s_feeQuoter.updatePrices(priceUpdates); MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](4); @@ -63,7 +64,7 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { s_authorizedCallers[0] = MOCK_OFFRAMP; s_authorizedCallers[1] = MOCK_ONRAMP; - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_priceRegistry), s_authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), s_authorizedCallers); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } @@ -100,11 +101,9 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { }); } - function _generateAny2EVMMessageNoTokens(uint64 sourceChainSelector) - internal - pure - returns (Client.Any2EVMMessage memory) - { + function _generateAny2EVMMessageNoTokens( + uint64 sourceChainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { return _generateAny2EVMMessage(sourceChainSelector, new Client.EVMTokenAmount[](0)); } } @@ -114,14 +113,14 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup address[] memory authorizedCallers = new address[](0); vm.recordLogs(); - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); - // PriceRegistrySet + // FeeQuoterSet Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 1); assertEq(OWNER, s_rateLimiter.owner()); - assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); + assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); } function test_Constructor_Success() public { @@ -130,24 +129,25 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup authorizedCallers[1] = MOCK_ONRAMP; vm.expectEmit(); - emit MultiAggregateRateLimiter.PriceRegistrySet(address(s_priceRegistry)); + emit MultiAggregateRateLimiter.FeeQuoterSet(address(s_feeQuoter)); - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); assertEq(OWNER, s_rateLimiter.owner()); - assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); + assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); + assertEq(s_rateLimiter.typeAndVersion(), "MultiAggregateRateLimiter 1.6.0-dev"); } } -contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiterSetup { +contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetup { function test_Owner_Success() public { address newAddress = address(42); vm.expectEmit(); - emit MultiAggregateRateLimiter.PriceRegistrySet(newAddress); + emit MultiAggregateRateLimiter.FeeQuoterSet(newAddress); - s_rateLimiter.setPriceRegistry(newAddress); - assertEq(newAddress, s_rateLimiter.getPriceRegistry()); + s_rateLimiter.setFeeQuoter(newAddress); + assertEq(newAddress, s_rateLimiter.getFeeQuoter()); } // Reverts @@ -156,12 +156,12 @@ contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiter vm.startPrank(STRANGER); vm.expectRevert(bytes("Only callable by owner")); - s_rateLimiter.setPriceRegistry(STRANGER); + s_rateLimiter.setFeeQuoter(STRANGER); } function test_ZeroAddress_Revert() public { vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - s_rateLimiter.setPriceRegistry(address(0)); + s_rateLimiter.setFeeQuoter(address(0)); } } @@ -482,14 +482,14 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[0] }), - remoteToken: bytes32(bytes20(s_sourceTokens[0])) + remoteToken: abi.encode(s_sourceTokens[0]) }); adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[1] }), - remoteToken: bytes32(bytes20(s_sourceTokens[1])) + remoteToken: abi.encode(s_sourceTokens[1]) }); for (uint256 i = 0; i < adds.length; ++i) { @@ -501,8 +501,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - (address[] memory localTokens, bytes32[] memory remoteTokens) = - s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); assertEq(localTokens.length, adds.length); assertEq(localTokens.length, remoteTokens.length); @@ -520,14 +519,14 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[0] }), - remoteToken: bytes32(bytes20(s_sourceTokens[0])) + remoteToken: abi.encode(s_sourceTokens[0]) }); adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ remoteChainSelector: CHAIN_SELECTOR_2, localToken: s_destTokens[1] }), - remoteToken: bytes32(bytes20(s_sourceTokens[1])) + remoteToken: abi.encode(s_sourceTokens[1]) }); for (uint256 i = 0; i < adds.length; ++i) { @@ -539,7 +538,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - (address[] memory localTokensChain1, bytes32[] memory remoteTokensChain1) = + (address[] memory localTokensChain1, bytes[] memory remoteTokensChain1) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); assertEq(localTokensChain1.length, 1); @@ -547,7 +546,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi assertEq(localTokensChain1[0], adds[0].localTokenArgs.localToken); assertEq(remoteTokensChain1[0], adds[0].remoteToken); - (address[] memory localTokensChain2, bytes32[] memory remoteTokensChain2) = + (address[] memory localTokensChain2, bytes[] memory remoteTokensChain2) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_2); assertEq(localTokensChain2.length, 1); @@ -563,14 +562,14 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[0] }), - remoteToken: bytes32(bytes20(s_sourceTokens[0])) + remoteToken: abi.encode(s_sourceTokens[0]) }); adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[1] }), - remoteToken: bytes32(bytes20(s_sourceTokens[1])) + remoteToken: abi.encode(s_sourceTokens[1]) }); MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = @@ -593,8 +592,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); - (address[] memory localTokens, bytes32[] memory remoteTokens) = - s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); assertEq(1, remoteTokens.length); assertEq(adds[1].remoteToken, remoteTokens[0]); @@ -620,8 +618,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 0); - (address[] memory localTokens, bytes32[] memory remoteTokens) = - s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); assertEq(localTokens.length, 0); assertEq(localTokens.length, remoteTokens.length); @@ -636,7 +633,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[0] }), - remoteToken: bytes32(bytes20(address(0))) + remoteToken: new bytes(0) }); vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); @@ -650,7 +647,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi remoteChainSelector: CHAIN_SELECTOR_1, localToken: address(0) }), - remoteToken: bytes32(bytes20(s_destTokens[0])) + remoteToken: abi.encode(s_destTokens[0]) }); vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); @@ -681,12 +678,12 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_destTokens[i] }), - remoteToken: bytes32(bytes20(s_sourceTokens[i])) + remoteToken: abi.encode(s_sourceTokens[i]) }); Internal.PriceUpdates memory priceUpdates = - getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); - s_priceRegistry.updatePrices(priceUpdates); + _getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); + s_feeQuoter.updatePrices(priceUpdates); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } @@ -771,7 +768,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter localToken: s_destTokens[i] }), // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: bytes32(uint256(uint160(s_sourceTokens[i])) + type(uint160).max + 1) + remoteToken: abi.encode(uint256(uint160(s_sourceTokens[i])) + type(uint160).max + 1) }); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); @@ -820,7 +817,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter localToken: s_destTokens[0] }), // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: bytes32(uint256(uint160(s_sourceTokens[0])) + type(uint160).max + 1) + remoteToken: abi.encode(uint256(uint160(s_sourceTokens[0])) + type(uint160).max + 1) }); s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); @@ -917,12 +914,12 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite remoteChainSelector: CHAIN_SELECTOR_1, localToken: s_sourceTokens[i] }), - remoteToken: bytes32(bytes20(s_destTokenBySourceToken[s_sourceTokens[i]])) + remoteToken: abi.encode(bytes20(s_destTokenBySourceToken[s_sourceTokens[i]])) }); Internal.PriceUpdates memory priceUpdates = - getSingleTokenPriceUpdateStruct(s_sourceTokens[i], TOKEN_PRICE * (i + 1)); - s_priceRegistry.updatePrices(priceUpdates); + _getSingleTokenPriceUpdateStruct(s_sourceTokens[i], TOKEN_PRICE * (i + 1)); + s_feeQuoter.updatePrices(priceUpdates); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } @@ -1005,7 +1002,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite localToken: s_sourceTokens[i] }), // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: bytes32(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[i]])) + type(uint160).max + 1) + remoteToken: abi.encode(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[i]])) + type(uint160).max + 1) }); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); @@ -1054,7 +1051,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite localToken: s_sourceTokens[0] }), // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: bytes32(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[0]])) + type(uint160).max + 1) + remoteToken: abi.encode(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[0]])) + type(uint160).max + 1) }); s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); @@ -1181,11 +1178,9 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessageNoTokens()); } - function _generateEVM2AnyMessage(Client.EVMTokenAmount[] memory tokenAmounts) - public - view - returns (Client.EVM2AnyMessage memory) - { + function _generateEVM2AnyMessage( + Client.EVMTokenAmount[] memory tokenAmounts + ) public view returns (Client.EVM2AnyMessage memory) { return Client.EVM2AnyMessage({ receiver: abi.encode(OWNER), data: "", diff --git a/contracts/src/v0.8/ccip/test/arm/ARMProxy_standalone.t.sol b/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol similarity index 61% rename from contracts/src/v0.8/ccip/test/arm/ARMProxy_standalone.t.sol rename to contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol index 4f3e96fafa2..efcdfd82277 100644 --- a/contracts/src/v0.8/ccip/test/arm/ARMProxy_standalone.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol @@ -1,9 +1,37 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {ARMProxy} from "../../ARMProxy.sol"; +import {IRMN} from "../../interfaces/IRMN.sol"; + +import {ARMProxy} from "../../rmn/ARMProxy.sol"; +import {MockRMN} from "../mocks/MockRMN.sol"; import {Test} from "forge-std/Test.sol"; +contract ARMProxyTest is Test { + MockRMN internal s_mockRMN; + ARMProxy internal s_armProxy; + + function setUp() public virtual { + s_mockRMN = new MockRMN(); + s_armProxy = new ARMProxy(address(s_mockRMN)); + } + + function test_ARMIsCursed_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_ARMCallRevertReasonForwarded() 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(); + } +} + contract ARMProxyStandaloneTest is Test { address internal constant EMPTY_ADDRESS = address(0x1); address internal constant OWNER_ADDRESS = 0xC0ffeeEeC0fFeeeEc0ffeEeEc0ffEEEEC0FfEEee; @@ -40,33 +68,6 @@ contract ARMProxyStandaloneTest is Test { s_armProxy.setARM(address(0x0)); } - /* - function test_Fuzz_ARMCall(bool expectedSuccess, bytes memory call, bytes memory ret) public { - // filter out calls to functions that will be handled on the ARMProxy instead - // of the underlying ARM contract - vm.assume( - call.length < 4 || - (bytes4(call) != s_armProxy.getARM.selector && - bytes4(call) != s_armProxy.setARM.selector && - bytes4(call) != s_armProxy.owner.selector && - bytes4(call) != s_armProxy.acceptOwnership.selector && - bytes4(call) != s_armProxy.transferOwnership.selector && - bytes4(call) != s_armProxy.typeAndVersion.selector) - ); - - if (expectedSuccess) { - vm.mockCall(MOCK_RMN_ADDRESS, 0, call, ret); - } else { - vm.mockCallRevert(MOCK_RMN_ADDRESS, 0, call, ret); - } - (bool actualSuccess, bytes memory result) = address(s_armProxy).call(call); - vm.clearMockedCalls(); - - assertEq(result, ret); - assertEq(expectedSuccess, actualSuccess); - } - */ - function test_ARMCallEmptyContractRevert() public { vm.prank(OWNER_ADDRESS); s_armProxy.setARM(EMPTY_ADDRESS); // No code at address 1, should revert. diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol new file mode 100644 index 00000000000..c5226d32067 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../libraries/Internal.sol"; +import {RMNHome} from "../../rmn/RMNHome.sol"; +import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; + +contract RMNHomeTest is Test { + struct Config { + RMNHome.StaticConfig staticConfig; + RMNHome.DynamicConfig dynamicConfig; + } + + bytes32 internal constant ZERO_DIGEST = bytes32(uint256(0)); + RMNHome public s_rmnHome = new RMNHome(); + + function _getBaseConfig() internal pure returns (Config memory) { + RMNHome.Node[] memory nodes = new RMNHome.Node[](3); + nodes[0] = RMNHome.Node({peerId: keccak256("peerId_0"), offchainPublicKey: keccak256("offchainPublicKey_0")}); + nodes[1] = RMNHome.Node({peerId: keccak256("peerId_1"), offchainPublicKey: keccak256("offchainPublicKey_1")}); + nodes[2] = RMNHome.Node({peerId: keccak256("peerId_2"), offchainPublicKey: keccak256("offchainPublicKey_2")}); + + RMNHome.SourceChain[] memory sourceChains = new RMNHome.SourceChain[](2); + // Observer 0 for source chain 9000 + sourceChains[0] = RMNHome.SourceChain({chainSelector: 9000, minObservers: 1, observerNodesBitmap: 1 << 0}); + // Observers 1 and 2 for source chain 9001 + sourceChains[1] = RMNHome.SourceChain({chainSelector: 9001, minObservers: 2, observerNodesBitmap: 1 << 1 | 1 << 2}); + + return Config({ + staticConfig: RMNHome.StaticConfig({nodes: nodes, offchainConfig: abi.encode("static_config")}), + dynamicConfig: RMNHome.DynamicConfig({sourceChains: sourceChains, offchainConfig: abi.encode("dynamic_config")}) + }); + } + + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 private constant PREFIX = 0x000b << (256 - 16); // 0x000b00..00 + + function _getConfigDigest(bytes memory staticConfig, uint32 version) internal view returns (bytes32) { + return bytes32( + (PREFIX & PREFIX_MASK) + | ( + uint256( + keccak256(bytes.concat(abi.encode(bytes32("EVM"), block.chainid, address(s_rmnHome), version), staticConfig)) + ) & ~PREFIX_MASK + ) + ); + } +} + +contract RMNHome_getConfigDigests is RMNHomeTest { + function test_getConfigDigests_success() public { + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + + Config memory config = _getBaseConfig(); + bytes32 firstDigest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, firstDigest); + + s_rmnHome.promoteCandidateAndRevokeActive(firstDigest, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, ZERO_DIGEST); + + bytes32 secondDigest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, secondDigest); + + assertEq(activeDigest, s_rmnHome.getActiveDigest()); + assertEq(candidateDigest, s_rmnHome.getCandidateDigest()); + } +} + +contract RMNHome_setCandidate is RMNHomeTest { + function test_setCandidate_success() public { + Config memory config = _getBaseConfig(); + RMNHome.VersionedConfig memory versionedConfig = RMNHome.VersionedConfig({ + version: 1, + staticConfig: config.staticConfig, + dynamicConfig: config.dynamicConfig, + configDigest: ZERO_DIGEST + }); + + versionedConfig.configDigest = _getConfigDigest(abi.encode(versionedConfig.staticConfig), versionedConfig.version); + + vm.expectEmit(); + emit RMNHome.ConfigSet( + versionedConfig.configDigest, versionedConfig.version, versionedConfig.staticConfig, versionedConfig.dynamicConfig + ); + + s_rmnHome.setCandidate(versionedConfig.staticConfig, versionedConfig.dynamicConfig, ZERO_DIGEST); + + (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(versionedConfig.configDigest); + assertTrue(ok); + assertEq(storedVersionedConfig.version, versionedConfig.version); + RMNHome.StaticConfig memory storedStaticConfig = storedVersionedConfig.staticConfig; + RMNHome.DynamicConfig memory storedDynamicConfig = storedVersionedConfig.dynamicConfig; + + assertEq(storedStaticConfig.nodes.length, versionedConfig.staticConfig.nodes.length); + for (uint256 i = 0; i < storedStaticConfig.nodes.length; i++) { + RMNHome.Node memory storedNode = storedStaticConfig.nodes[i]; + assertEq(storedNode.peerId, versionedConfig.staticConfig.nodes[i].peerId); + assertEq(storedNode.offchainPublicKey, versionedConfig.staticConfig.nodes[i].offchainPublicKey); + } + + assertEq(storedDynamicConfig.sourceChains.length, versionedConfig.dynamicConfig.sourceChains.length); + 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.minObservers, versionedConfig.dynamicConfig.sourceChains[i].minObservers); + 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 { + Config memory config = _getBaseConfig(); + + bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, digest, ZERO_DIGEST)); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectEmit(); + emit RMNHome.CandidateConfigRevoked(digest); + + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, digest); + } + + function test_setCandidate_OnlyOwner_reverts() public { + Config memory config = _getBaseConfig(); + + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } +} + +contract RMNHome_revokeCandidate is RMNHomeTest { + // Sets two configs + function setUp() public { + Config memory config = _getBaseConfig(); + bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + s_rmnHome.promoteCandidateAndRevokeActive(digest, ZERO_DIGEST); + + config.dynamicConfig.sourceChains[0].minObservers--; + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_revokeCandidate_success() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); + + vm.expectEmit(); + emit RMNHome.CandidateConfigRevoked(priorCandidateDigest); + + s_rmnHome.revokeCandidate(priorCandidateDigest); + + (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(priorCandidateDigest); + assertFalse(ok); + // Ensure no old data is returned, even though it's still in storage + assertEq(storedVersionedConfig.version, 0); + assertEq(storedVersionedConfig.staticConfig.nodes.length, 0); + assertEq(storedVersionedConfig.dynamicConfig.sourceChains.length, 0); + + // Asser the active digest is unaffected but the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, priorActiveDigest); + assertEq(candidateDigest, ZERO_DIGEST); + assertTrue(candidateDigest != priorCandidateDigest); + } + + function test_revokeCandidate_ConfigDigestMismatch_reverts() public { + (, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); + + bytes32 wrongDigest = keccak256("wrong_digest"); + vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorCandidateDigest, wrongDigest)); + s_rmnHome.revokeCandidate(wrongDigest); + } + + function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { + vm.expectRevert(RMNHome.RevokingZeroDigestNotAllowed.selector); + s_rmnHome.revokeCandidate(ZERO_DIGEST); + } + + function test_revokeCandidate_OnlyOwner_reverts() public { + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.revokeCandidate(keccak256("configDigest")); + } +} + +contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTest { + function test_promoteCandidateAndRevokeActive_success() public { + Config memory config = _getBaseConfig(); + bytes32 firstConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectEmit(); + emit RMNHome.ConfigPromoted(firstConfigToPromote); + + s_rmnHome.promoteCandidateAndRevokeActive(firstConfigToPromote, ZERO_DIGEST); + + // Assert the active digest is updated and the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, firstConfigToPromote); + assertEq(candidateDigest, ZERO_DIGEST); + + // Set a new candidate to promote over a non-zero active config. + config.staticConfig.offchainConfig = abi.encode("new_static_config"); + config.dynamicConfig.offchainConfig = abi.encode("new_dynamic_config"); + bytes32 secondConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectEmit(); + emit RMNHome.ActiveConfigRevoked(firstConfigToPromote); + + vm.expectEmit(); + emit RMNHome.ConfigPromoted(secondConfigToPromote); + + s_rmnHome.promoteCandidateAndRevokeActive(secondConfigToPromote, firstConfigToPromote); + + (RMNHome.VersionedConfig memory activeConfig, RMNHome.VersionedConfig memory candidateConfig) = + s_rmnHome.getAllConfigs(); + assertEq(activeConfig.configDigest, secondConfigToPromote); + assertEq(activeConfig.staticConfig.offchainConfig, config.staticConfig.offchainConfig); + assertEq(activeConfig.dynamicConfig.offchainConfig, config.dynamicConfig.offchainConfig); + + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + } + + function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { + vm.expectRevert(RMNHome.NoOpStateTransitionNotAllowed.selector); + s_rmnHome.promoteCandidateAndRevokeActive(ZERO_DIGEST, ZERO_DIGEST); + } + + function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); + bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); + bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); + + vm.expectRevert( + abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongCandidateDigest) + ); + s_rmnHome.promoteCandidateAndRevokeActive(wrongCandidateDigest, wrongActiveDigest); + + vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongActiveDigest)); + + s_rmnHome.promoteCandidateAndRevokeActive(priorCandidateDigest, wrongActiveDigest); + } + + function test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() public { + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.promoteCandidateAndRevokeActive(keccak256("toPromote"), keccak256("ToRevoke")); + } +} + +contract RMNHome__validateStaticAndDynamicConfig is RMNHomeTest { + function test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() public { + Config memory config = _getBaseConfig(); + config.staticConfig.nodes = new RMNHome.Node[](257); + + vm.expectRevert(RMNHome.OutOfBoundsNodesLength.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() public { + Config memory config = _getBaseConfig(); + config.staticConfig.nodes[1].peerId = config.staticConfig.nodes[0].peerId; + + vm.expectRevert(RMNHome.DuplicatePeerId.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() public { + Config memory config = _getBaseConfig(); + config.staticConfig.nodes[1].offchainPublicKey = config.staticConfig.nodes[0].offchainPublicKey; + + vm.expectRevert(RMNHome.DuplicateOffchainPublicKey.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[1].chainSelector = config.dynamicConfig.sourceChains[0].chainSelector; + + vm.expectRevert(RMNHome.DuplicateSourceChain.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].observerNodesBitmap = 1 << config.staticConfig.nodes.length; + + vm.expectRevert(RMNHome.OutOfBoundsObserverNodeIndex.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_MinObserversTooHigh_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].minObservers++; + + vm.expectRevert(RMNHome.MinObserversTooHigh.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } +} + +contract RMNHome_setDynamicConfig is RMNHomeTest { + function setUp() public { + Config memory config = _getBaseConfig(); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_setDynamicConfig_success() public { + (bytes32 priorActiveDigest,) = s_rmnHome.getConfigDigests(); + + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].minObservers--; + + (, bytes32 candidateConfigDigest) = s_rmnHome.getConfigDigests(); + + vm.expectEmit(); + emit RMNHome.DynamicConfigSet(candidateConfigDigest, config.dynamicConfig); + + s_rmnHome.setDynamicConfig(config.dynamicConfig, candidateConfigDigest); + + (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(candidateConfigDigest); + assertTrue(ok); + assertEq( + storedVersionedConfig.dynamicConfig.sourceChains[0].minObservers, + config.dynamicConfig.sourceChains[0].minObservers + ); + + // Asser the digests don't change when updating the dynamic config + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, priorActiveDigest); + assertEq(candidateDigest, candidateConfigDigest); + } + + // Asserts the validation function is being called + function test_setDynamicConfig_MinObserversTooHigh_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].minObservers++; + + vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); + s_rmnHome.setDynamicConfig(config.dynamicConfig, ZERO_DIGEST); + } + + function test_setDynamicConfig_DigestNotFound_reverts() public { + // Zero always reverts + vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); + s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, ZERO_DIGEST); + + // Non-existent digest reverts + bytes32 nonExistentDigest = keccak256("nonExistentDigest"); + vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, nonExistentDigest)); + s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, nonExistentDigest); + } + + function test_setDynamicConfig_OnlyOwner_reverts() public { + Config memory config = _getBaseConfig(); + + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.setDynamicConfig(config.dynamicConfig, keccak256("configDigest")); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol new file mode 100644 index 00000000000..5f46f856691 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {GLOBAL_CURSE_SUBJECT, LEGACY_CURSE_SUBJECT, RMNRemote} from "../../rmn/RMNRemote.sol"; +import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; + +contract RMNRemote_constructor is RMNRemoteSetup { + function test_constructor_success() public view { + assertEq(s_rmnRemote.getLocalChainSelector(), 1); + } + + function test_constructor_zeroChainSelector_reverts() public { + vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); + new RMNRemote(0); + } +} + +contract RMNRemote_setConfig is RMNRemoteSetup { + function test_setConfig_minSignersIs0_success() public { + // Initially there is no config, the version is 0 + uint32 currentConfigVersion = 0; + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.minSigners, 0); + assertEq(version, currentConfigVersion); + + // A new config should increment the version + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + } + + function test_setConfig_addSigner_removeSigner_success() public { + uint32 currentConfigVersion = 0; + uint256 numSigners = s_signers.length; + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + // 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, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.signers.length, s_signers.length); + assertEq(gotConfig.signers[numSigners].onchainPublicKey, newSigner); + assertEq(gotConfig.signers[numSigners].nodeIndex, uint64(numSigners)); + assertEq(version, currentConfigVersion); + + // remove two signers + s_signers.pop(); + s_signers.pop(); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (version, gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.signers.length, s_signers.length); + assertEq(version, currentConfigVersion); + } + + function test_setConfig_invalidSignerOrder_reverts() public { + s_signers.push(RMNRemote.Signer({onchainPublicKey: address(4), nodeIndex: 0})); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectRevert(RMNRemote.InvalidSignerOrder.selector); + s_rmnRemote.setConfig(config); + } + + function test_setConfig_minSignersTooHigh_reverts() public { + RMNRemote.Config memory config = RMNRemote.Config({ + rmnHomeContractConfigDigest: _randomBytes32(), + signers: s_signers, + minSigners: uint64(s_signers.length + 1) + }); + + vm.expectRevert(RMNRemote.MinSignersTooHigh.selector); + s_rmnRemote.setConfig(config); + } + + function test_setConfig_duplicateOnChainPublicKey_reverts() 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, minSigners: 0}); + + vm.expectRevert(RMNRemote.DuplicateOnchainPublicKey.selector); + s_rmnRemote.setConfig(config); + } +} + +contract RMNRemote_verify_withConfigNotSet is RMNRemoteSetup { + function test_verify_reverts() public { + Internal.MerkleRoot[] memory merkleRoots = new Internal.MerkleRoot[](0); + IRMNRemote.Signature[] memory signatures = new IRMNRemote.Signature[](0); + + vm.expectRevert(RMNRemote.ConfigNotSet.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, merkleRoots, signatures, 0); + } +} + +contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { + function setUp() public override { + super.setUp(); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 2}); + s_rmnRemote.setConfig(config); + _generatePayloadAndSigs(2, 2); + } + + function test_verify_success() public view { + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_minSignersIsZero_success() public { + vm.stopPrank(); + vm.prank(OWNER); + s_rmnRemote.setConfig( + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}) + ); + + vm.stopPrank(); + vm.prank(OFF_RAMP_ADDRESS); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, new IRMNRemote.Signature[](0), s_v); + } + + 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); + + vm.expectRevert(RMNRemote.InvalidSignature.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_OutOfOrderSignatures_not_sorted_reverts() 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); + + vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_OutOfOrderSignatures_duplicateSignature_reverts() public { + IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 2]; + s_signatures.pop(); + s_signatures.push(sig); + + vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_UnexpectedSigner_reverts() public { + _setupSigners(2); // create 2 new signers that aren't configured on RMNRemote + _generatePayloadAndSigs(2, 2); + + vm.expectRevert(RMNRemote.UnexpectedSigner.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_ThresholdNotMet_reverts() public { + _generatePayloadAndSigs(2, 1); // 1 sig requested, but 2 required + + vm.expectRevert(RMNRemote.ThresholdNotMet.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } +} + +contract RMNRemote_curse is RMNRemoteSetup { + function test_curse_success() public { + vm.expectEmit(); + emit RMNRemote.Cursed(s_curseSubjects); + + s_rmnRemote.curse(s_curseSubjects); + + assertEq(abi.encode(s_rmnRemote.getCursedSubjects()), abi.encode(s_curseSubjects)); + assertTrue(s_rmnRemote.isCursed(curseSubj1)); + assertTrue(s_rmnRemote.isCursed(curseSubj2)); + // Should not have cursed a random subject + assertFalse(s_rmnRemote.isCursed(bytes16(keccak256("subject 3")))); + } + + function test_curse_AlreadyCursed_duplicateSubject_reverts() public { + s_curseSubjects.push(curseSubj1); + + vm.expectRevert(abi.encodeWithSelector(RMNRemote.AlreadyCursed.selector, curseSubj1)); + s_rmnRemote.curse(s_curseSubjects); + } + + function test_curse_calledByNonOwner_reverts() public { + vm.expectRevert("Only callable by owner"); + vm.stopPrank(); + vm.prank(STRANGER); + s_rmnRemote.curse(s_curseSubjects); + } +} + +contract RMNRemote_uncurse is RMNRemoteSetup { + function setUp() public override { + super.setUp(); + s_rmnRemote.curse(s_curseSubjects); + } + + function test_uncurse_success() public { + vm.expectEmit(); + emit RMNRemote.Uncursed(s_curseSubjects); + + s_rmnRemote.uncurse(s_curseSubjects); + + assertEq(s_rmnRemote.getCursedSubjects().length, 0); + assertFalse(s_rmnRemote.isCursed(curseSubj1)); + assertFalse(s_rmnRemote.isCursed(curseSubj2)); + } + + function test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() public { + s_curseSubjects.push(curseSubj1); + + vm.expectRevert(abi.encodeWithSelector(RMNRemote.NotCursed.selector, curseSubj1)); + s_rmnRemote.uncurse(s_curseSubjects); + } + + function test_uncurse_calledByNonOwner_reverts() public { + vm.expectRevert("Only callable by owner"); + vm.stopPrank(); + vm.prank(STRANGER); + s_rmnRemote.uncurse(s_curseSubjects); + } +} + +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/RMNRemoteSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol new file mode 100644 index 00000000000..131dfec7cb5 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {RMNRemote} from "../../rmn/RMNRemote.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import "forge-std/console.sol"; + +contract RMNRemoteSetup is BaseTest { + RMNRemote public s_rmnRemote; + address public OFF_RAMP_ADDRESS; + + RMNRemote.Signer[] public s_signers; + Vm.Wallet[] public s_signerWallets; + + Internal.MerkleRoot[] s_merkleRoots; + IRMNRemote.Signature[] s_signatures; + uint256 internal s_v; + + bytes16 internal constant curseSubj1 = bytes16(keccak256("subject 1")); + bytes16 internal constant curseSubj2 = bytes16(keccak256("subject 2")); + bytes16[] internal s_curseSubjects; + + function setUp() public virtual override { + super.setUp(); + s_rmnRemote = new RMNRemote(1); + OFF_RAMP_ADDRESS = makeAddr("OFF RAMP"); + s_curseSubjects = [curseSubj1, curseSubj2]; + + _setupSigners(10); + } + + /// @notice sets up a list of signers with strictly increasing onchain public keys + /// @dev signers do not have to be in order when configured, but they do when generating signatures + /// rather than sort signers every time, we do it once here and store the sorted list + function _setupSigners( + uint256 numSigners + ) internal { + // remove any existing config + while (s_signerWallets.length > 0) { + s_signerWallets.pop(); + } + while (s_signers.length > 0) { + s_signers.pop(); + } + + for (uint256 i = 0; i < numSigners; i++) { + s_signerWallets.push(vm.createWallet(_randomNum())); + } + + _sort(s_signerWallets); + + for (uint256 i = 0; i < numSigners; i++) { + s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[i].addr, nodeIndex: uint64(i)})); + } + } + + /// @notice generates n merkleRoots and matching valid signatures and populates them into + /// the shared storage vars + function _generatePayloadAndSigs(uint256 numUpdates, uint256 numSigs) internal { + require(numUpdates > 0, "need at least 1 dest lane update"); + require(numSigs <= s_signerWallets.length, "cannot generate more sigs than signers"); + + // remove any existing merkleRoots and sigs + while (s_merkleRoots.length > 0) { + s_merkleRoots.pop(); + } + while (s_signatures.length > 0) { + s_signatures.pop(); + } + s_v = 0; + + for (uint256 i = 0; i < numUpdates; i++) { + s_merkleRoots.push(_generateRandomDestLaneUpdate()); + } + + for (uint256 i = 0; i < numSigs; i++) { + (uint8 v, IRMNRemote.Signature memory sig) = _signDestLaneUpdate(s_merkleRoots, s_signerWallets[i]); + s_signatures.push(sig); + if (v == 28) { + s_v += 1 << i; + } + } + } + + /// @notice generates a random dest lane update + function _generateRandomDestLaneUpdate() private returns (Internal.MerkleRoot memory) { + uint64 minSeqNum = uint32(_randomNum()); + uint64 maxSeqNum = minSeqNum + 100; + return Internal.MerkleRoot({ + sourceChainSelector: uint64(_randomNum()), + onRampAddress: abi.encode(_randomAddress()), + minSeqNr: minSeqNum, + maxSeqNr: maxSeqNum, + merkleRoot: _randomBytes32() + }); + } + + /// @notice signs the provided payload with the provided wallet + /// @return sigV v, either 27 of 28 + /// @return sig the signature + function _signDestLaneUpdate( + Internal.MerkleRoot[] memory merkleRoots, + Vm.Wallet memory wallet + ) private returns (uint8 sigV, IRMNRemote.Signature memory) { + (, RMNRemote.Config memory config) = s_rmnRemote.getVersionedConfig(); + bytes32 digest = keccak256( + abi.encode( + s_rmnRemote.getReportDigestHeader(), + RMNRemote.Report({ + destChainId: block.chainid, + destChainSelector: s_rmnRemote.getLocalChainSelector(), + rmnRemoteContractAddress: address(s_rmnRemote), + offrampAddress: OFF_RAMP_ADDRESS, + rmnHomeContractConfigDigest: config.rmnHomeContractConfigDigest, + merkleRoots: merkleRoots + }) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(wallet, digest); + return (v, IRMNRemote.Signature({r: r, s: s})); + } + + /// @notice bubble sort on a storage array of wallets + function _sort( + Vm.Wallet[] storage wallets + ) private { + bool swapped; + for (uint256 i = 1; i < wallets.length; i++) { + swapped = false; + for (uint256 j = 0; j < wallets.length - i; j++) { + Vm.Wallet memory next = wallets[j + 1]; + Vm.Wallet memory actual = wallets[j]; + if (next.addr < actual.addr) { + wallets[j] = next; + wallets[j + 1] = actual; + swapped = true; + } + } + if (!swapped) { + return; + } + } + } +} diff --git a/contracts/src/v0.8/ccip/test/router/Router.t.sol b/contracts/src/v0.8/ccip/test/router/Router.t.sol index cfe01e3c417..b5cfd6cfbec 100644 --- a/contracts/src/v0.8/ccip/test/router/Router.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router.t.sol @@ -9,22 +9,22 @@ import {IWrappedNative} from "../../interfaces/IWrappedNative.sol"; import {Router} from "../../Router.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {EVM2EVMOffRampSetup} from "../offRamp/EVM2EVMOffRampSetup.t.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; +import {OffRampSetup} from "../offRamp/OffRampSetup.t.sol"; +import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; import {RouterSetup} from "../router/RouterSetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract Router_constructor is EVM2EVMOnRampSetup { +contract Router_constructor is OnRampSetup { function test_Constructor_Success() public view { assertEq("Router 1.2.0", s_sourceRouter.typeAndVersion()); assertEq(OWNER, s_sourceRouter.owner()); } } -contract Router_recoverTokens is EVM2EVMOnRampSetup { +contract Router_recoverTokens is OnRampSetup { function test_RecoverTokens_Success() public { // Assert we can recover sourceToken IERC20 token = IERC20(s_sourceTokens[0]); @@ -72,7 +72,7 @@ contract Router_recoverTokens is EVM2EVMOnRampSetup { } } -contract Router_ccipSend is EVM2EVMOnRampSetup { +contract Router_ccipSend is OnRampSetup { event Burned(address indexed sender, uint256 amount); function test_CCIPSendLinkFeeOneTokenSuccess_gas() public { @@ -95,16 +95,16 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { vm.expectEmit(); emit Burned(address(s_onRamp), message.tokenAmounts[0].amount); - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); vm.resumeGasMetering(); bytes32 messageId = s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - assertEq(msgEvent.messageId, messageId); + assertEq(msgEvent.header.messageId, messageId); // Assert the user balance is lowered by the tokenAmounts sent and the fee amount uint256 expectedBalance = balanceBefore - (message.tokenAmounts[0].amount); assertEq(expectedBalance, sourceToken1.balanceOf(OWNER)); @@ -118,99 +118,90 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); assertGt(expectedFee, 0); - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); vm.resumeGasMetering(); bytes32 messageId = s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - assertEq(msgEvent.messageId, messageId); + assertEq(msgEvent.header.messageId, messageId); vm.resumeGasMetering(); } - function test_CCIPSendNativeFeeOneTokenSuccess_gas() public { + function test_ccipSend_nativeFeeOneTokenSuccess_gas() public { vm.pauseGasMetering(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); IERC20 sourceToken1 = IERC20(s_sourceTokens[1]); sourceToken1.approve(address(s_sourceRouter), 2 ** 64); + uint256 balanceBefore = sourceToken1.balanceOf(OWNER); + message.tokenAmounts = new Client.EVMTokenAmount[](1); message.tokenAmounts[0].amount = 2 ** 64; message.tokenAmounts[0].token = s_sourceTokens[1]; + // Native fees will be wrapped so we need to calculate the event with + // the wrapped native feeCoin address. + message.feeToken = s_sourceRouter.getWrappedNative(); uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); assertGt(expectedFee, 0); - uint256 balanceBefore = sourceToken1.balanceOf(OWNER); + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + msgEvent.feeValueJuels = expectedFee * s_sourceTokenPrices[1] / s_sourceTokenPrices[0]; + message.feeToken = address(0); // Assert that the tokens are burned vm.expectEmit(); emit Burned(address(s_onRamp), message.tokenAmounts[0].amount); - // Native fees will be wrapped so we need to calculate the event with - // the wrapped native feeCoin address. - message.feeToken = s_sourceRouter.getWrappedNative(); - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - // Set it to address(0) to indicate native - message.feeToken = address(0); - vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); vm.resumeGasMetering(); bytes32 messageId = s_sourceRouter.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - assertEq(msgEvent.messageId, messageId); + assertEq(msgEvent.header.messageId, messageId); // Assert the user balance is lowered by the tokenAmounts sent and the fee amount uint256 expectedBalance = balanceBefore - (message.tokenAmounts[0].amount); assertEq(expectedBalance, sourceToken1.balanceOf(OWNER)); vm.resumeGasMetering(); } - function test_CCIPSendNativeFeeNoTokenSuccess_gas() public { + function test_ccipSend_nativeFeeNoTokenSuccess_gas() public { vm.pauseGasMetering(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertGt(expectedFee, 0); - // Native fees will be wrapped so we need to calculate the event with // the wrapped native feeCoin address. message.feeToken = s_sourceRouter.getWrappedNative(); - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + assertGt(expectedFee, 0); + + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + msgEvent.feeValueJuels = expectedFee * s_sourceTokenPrices[1] / s_sourceTokenPrices[0]; // Set it to address(0) to indicate native message.feeToken = address(0); vm.expectEmit(); - emit EVM2EVMOnRamp.CCIPSendRequested(msgEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); vm.resumeGasMetering(); bytes32 messageId = s_sourceRouter.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - assertEq(msgEvent.messageId, messageId); + assertEq(msgEvent.header.messageId, messageId); // Assert the user balance is lowered by the tokenAmounts sent and the fee amount vm.resumeGasMetering(); } function test_NonLinkFeeToken_Success() public { - EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeTokenConfigArgs = new EVM2EVMOnRamp.FeeTokenConfigArgs[](1); - feeTokenConfigArgs[0] = EVM2EVMOnRamp.FeeTokenConfigArgs({ - token: s_sourceTokens[1], - networkFeeUSDCents: 1, - gasMultiplierWeiPerEth: 108e16, - premiumMultiplierWeiPerEth: 1e18, - enabled: true - }); - s_onRamp.setFeeTokenConfig(feeTokenConfigArgs); - address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = s_sourceTokens[1]; @@ -251,47 +242,6 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); } - // Since sending with zero fees is a legitimate use case for some destination - // chains, e.g. private chains, we want to make sure that we can still send even - // when the configured fee is 0. - function test_ZeroFeeAndGasPrice_Success() public { - // Configure a new fee token that has zero gas and zero fees but is still - // enabled and valid to pay with. - address feeTokenWithZeroFeeAndGas = s_sourceTokens[1]; - - // Set the new token as feeToken - address[] memory feeTokens = new address[](1); - feeTokens[0] = feeTokenWithZeroFeeAndGas; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - - // Update the price of the newly set feeToken - Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(feeTokenWithZeroFeeAndGas, 2_000 ether); - priceUpdates.gasPriceUpdates = getSingleGasPriceUpdateStruct(DEST_CHAIN_SELECTOR, 0).gasPriceUpdates; - s_priceRegistry.updatePrices(priceUpdates); - - // Set the feeToken args on the onRamp - EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeTokenConfigArgs = new EVM2EVMOnRamp.FeeTokenConfigArgs[](1); - feeTokenConfigArgs[0] = EVM2EVMOnRamp.FeeTokenConfigArgs({ - token: s_sourceTokens[1], - networkFeeUSDCents: 0, - gasMultiplierWeiPerEth: 108e16, - premiumMultiplierWeiPerEth: 1e18, - enabled: true - }); - - s_onRamp.setFeeTokenConfig(feeTokenConfigArgs); - - // Send a message with the new feeToken - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = feeTokenWithZeroFeeAndGas; - - // Fee should be 0 and sending should not revert - uint256 fee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertEq(fee, 0); - - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - // Reverts function test_WhenNotHealthy_Revert() public { @@ -310,38 +260,6 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { s_sourceRouter.ccipSend(wrongChain, message); } - function test_Fuzz_UnsupportedFeeToken_Reverts(address wrongFeeToken) public { - // We have three fee tokens set, all others should revert. - vm.assume(address(s_sourceFeeToken) != wrongFeeToken); - vm.assume(address(s_sourceRouter.getWrappedNative()) != wrongFeeToken); - vm.assume(address(0) != wrongFeeToken); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = wrongFeeToken; - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.NotAFeeToken.selector, wrongFeeToken)); - - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_Fuzz_UnsupportedToken_Reverts(address wrongToken) public { - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - vm.assume(address(s_sourceTokens[i]) != wrongToken); - } - - for (uint256 i = 0; i < s_destTokens.length; ++i) { - vm.assume(address(s_destTokens[i]) != wrongToken); - } - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: wrongToken, amount: 1}); - message.tokenAmounts = tokenAmounts; - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMOnRamp.UnsupportedToken.selector, wrongToken)); - - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - function test_FeeTokenAmountTooLow_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 0); @@ -374,8 +292,6 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { // Include insufficient, should also revert vm.stopPrank(); - s_onRamp.getFeeTokenConfig(s_sourceRouter.getWrappedNative()); - hoax(address(1), 1); vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); s_sourceRouter.ccipSend{value: 1}(DEST_CHAIN_SELECTOR, message); @@ -392,28 +308,34 @@ contract Router_applyRampUpdates is RouterSetup { MaybeRevertMessageReceiver internal s_receiver; function setUp() public virtual override(RouterSetup) { - RouterSetup.setUp(); + super.setUp(); s_receiver = new MaybeRevertMessageReceiver(false); } - function assertOffRampRouteSucceeds(Router.OffRamp memory offRamp) internal { + function _assertOffRampRouteSucceeds( + Router.OffRamp memory offRamp + ) internal { vm.startPrank(offRamp.offRamp); - Client.Any2EVMMessage memory message = generateReceiverMessage(offRamp.sourceChainSelector); + Client.Any2EVMMessage memory message = _generateReceiverMessage(offRamp.sourceChainSelector); 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)); } - function assertOffRampRouteReverts(Router.OffRamp memory offRamp) internal { + function _assertOffRampRouteReverts( + Router.OffRamp memory offRamp + ) internal { vm.startPrank(offRamp.offRamp); vm.expectRevert(IRouter.OnlyOffRamp.selector); s_sourceRouter.routeMessage( - generateReceiverMessage(offRamp.sourceChainSelector), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + _generateReceiverMessage(offRamp.sourceChainSelector), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); } - function test_Fuzz_OffRampUpdates(address[20] memory offRampsInput) public { + function test_Fuzz_OffRampUpdates( + address[20] memory offRampsInput + ) public { Router.OffRamp[] memory offRamps = new Router.OffRamp[](20); for (uint256 i = 0; i < offRampsInput.length; ++i) { @@ -483,7 +405,7 @@ contract Router_applyRampUpdates is RouterSetup { for (uint256 i = 0; i < offRampUpdates.length; ++i) { assertEq(offRampUpdates[i].offRamp, gotOffRamps[i].offRamp); assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - assertOffRampRouteSucceeds(offRampUpdates[i]); + _assertOffRampRouteSucceeds(offRampUpdates[i]); } vm.startPrank(OWNER); @@ -520,14 +442,14 @@ contract Router_applyRampUpdates is RouterSetup { assertFalse( s_sourceRouter.isOffRamp(partialOffRampRemoves[i].sourceChainSelector, partialOffRampRemoves[i].offRamp) ); - assertOffRampRouteReverts(partialOffRampRemoves[i]); + _assertOffRampRouteReverts(partialOffRampRemoves[i]); assertTrue(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); - assertOffRampRouteSucceeds(partialOffRampAdds[i]); + _assertOffRampRouteSucceeds(partialOffRampAdds[i]); } for (uint256 i = numberOfPartialUpdates; i < offRampUpdates.length; ++i) { assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - assertOffRampRouteSucceeds(offRampUpdates[i]); + _assertOffRampRouteSucceeds(offRampUpdates[i]); } vm.startPrank(OWNER); @@ -557,11 +479,11 @@ contract Router_applyRampUpdates is RouterSetup { for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { assertFalse(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); - assertOffRampRouteReverts(partialOffRampAdds[i]); + _assertOffRampRouteReverts(partialOffRampAdds[i]); } for (uint256 i = 0; i < offRampUpdates.length; ++i) { assertFalse(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - assertOffRampRouteReverts(offRampUpdates[i]); + _assertOffRampRouteReverts(offRampUpdates[i]); } vm.startPrank(OWNER); @@ -582,17 +504,19 @@ contract Router_applyRampUpdates is RouterSetup { for (uint256 i = 0; i < offRampUpdates.length; ++i) { assertEq(offRampUpdates[i].offRamp, gotOffRamps[i].offRamp); assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - assertOffRampRouteSucceeds(offRampUpdates[i]); + _assertOffRampRouteSucceeds(offRampUpdates[i]); } // Check offramps that were not added back remain unset. for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { assertFalse(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); - assertOffRampRouteReverts(partialOffRampAdds[i]); + _assertOffRampRouteReverts(partialOffRampAdds[i]); } } - function test_Fuzz_OnRampUpdates(Router.OnRamp[] memory onRamps) public { + function test_Fuzz_OnRampUpdates( + Router.OnRamp[] memory onRamps + ) public { // Test adding onRamps for (uint256 i = 0; i < onRamps.length; ++i) { vm.expectEmit(); @@ -664,8 +588,10 @@ contract Router_applyRampUpdates is RouterSetup { } } -contract Router_setWrappedNative is EVM2EVMOnRampSetup { - function test_Fuzz_SetWrappedNative_Success(address wrappedNative) public { +contract Router_setWrappedNative is OnRampSetup { + function test_Fuzz_SetWrappedNative_Success( + address wrappedNative + ) public { s_sourceRouter.setWrappedNative(wrappedNative); assertEq(wrappedNative, s_sourceRouter.getWrappedNative()); } @@ -678,31 +604,33 @@ contract Router_setWrappedNative is EVM2EVMOnRampSetup { } } -contract Router_getSupportedTokens is EVM2EVMOnRampSetup { +contract Router_getSupportedTokens is OnRampSetup { function test_GetSupportedTokens_Revert() public { - vm.expectRevert(EVM2EVMOnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); + vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); } } -contract Router_routeMessage is EVM2EVMOffRampSetup { +contract Router_routeMessage is OffRampSetup { function setUp() public virtual override { - EVM2EVMOffRampSetup.setUp(); + super.setUp(); vm.startPrank(address(s_offRamp)); } - function generateManualGasLimit(uint256 callDataLength) internal view returns (uint256) { + function _generateManualGasLimit( + uint256 callDataLength + ) internal view returns (uint256) { return ((gasleft() - 2 * (16 * callDataLength + GAS_FOR_CALL_EXACT_CHECK)) * 62) / 64; } - function test_ManualExec_Success() public { - Client.Any2EVMMessage memory message = generateReceiverMessage(SOURCE_CHAIN_SELECTOR); + function test_routeMessage_ManualExec_Success() public { + Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); // Manuel execution cannot run out of gas (bool success, bytes memory retData, uint256 gasUsed) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, - generateManualGasLimit(message.data.length), + _generateManualGasLimit(message.data.length), address(s_receiver) ); assertTrue(success); @@ -710,8 +638,8 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { assertGt(gasUsed, 3_000); } - function test_ExecutionEvent_Success() public { - Client.Any2EVMMessage memory message = generateReceiverMessage(SOURCE_CHAIN_SELECTOR); + function test_routeMessage_ExecutionEvent_Success() public { + Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); // Should revert with reason bytes memory realError1 = new bytes(2); realError1[0] = 0xbe; @@ -727,9 +655,9 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { ); (bool success, bytes memory retData, uint256 gasUsed) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, - generateManualGasLimit(message.data.length), + _generateManualGasLimit(message.data.length), address(s_reverting_receiver) ); @@ -753,9 +681,9 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { ); (success, retData, gasUsed) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, - generateManualGasLimit(message.data.length), + _generateManualGasLimit(message.data.length), address(s_reverting_receiver) ); @@ -782,9 +710,9 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { ); (success, retData, gasUsed) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, - generateManualGasLimit(message.data.length), + _generateManualGasLimit(message.data.length), address(s_receiver) ); @@ -793,8 +721,10 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { assertGt(gasUsed, 3_000); } - function test_Fuzz_ExecutionEvent_Success(bytes calldata error) public { - Client.Any2EVMMessage memory message = generateReceiverMessage(SOURCE_CHAIN_SELECTOR); + function testFuzz_routeMessage_ExecutionEvent_Success( + bytes calldata error + ) public { + Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); s_reverting_receiver.setErr(error); bytes memory expectedRetData; @@ -827,9 +757,9 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { } (bool success, bytes memory retData,) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, - generateManualGasLimit(message.data.length), + _generateManualGasLimit(message.data.length), address(s_reverting_receiver) ); @@ -837,15 +767,15 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { assertEq(expectedRetData, retData); } - function test_AutoExec_Success() public { + function test_routeMessage_AutoExec_Success() public { (bool success,,) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); assertTrue(success); (success,,) = s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 1, address(s_receiver) + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 1, address(s_receiver) ); // Can run out of gas, should return false @@ -853,26 +783,26 @@ contract Router_routeMessage is EVM2EVMOffRampSetup { } // Reverts - function test_OnlyOffRamp_Revert() public { + function test_routeMessage_OnlyOffRamp_Revert() public { vm.stopPrank(); vm.startPrank(STRANGER); vm.expectRevert(IRouter.OnlyOffRamp.selector); s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); } - function test_WhenNotHealthy_Revert() public { + function test_routeMessage_WhenNotHealthy_Revert() public { s_mockRMN.setGlobalCursed(true); vm.expectRevert(Router.BadARMSignal.selector); s_destRouter.routeMessage( - generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); } } -contract Router_getFee is EVM2EVMOnRampSetup { +contract Router_getFee is OnRampSetup { function test_GetFeeSupportedChain_Success() public view { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); diff --git a/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol b/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol index de751617612..f4c1114bf2a 100644 --- a/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol @@ -26,7 +26,9 @@ contract RouterSetup is BaseTest { } } - function generateReceiverMessage(uint64 chainSelector) internal pure returns (Client.Any2EVMMessage memory) { + function _generateReceiverMessage( + uint64 chainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); return Client.Any2EVMMessage({ messageId: bytes32("a"), @@ -37,11 +39,12 @@ contract RouterSetup is BaseTest { }); } - function generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { + function _generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { return Internal.SourceTokenData({ sourcePoolAddress: abi.encode(address(12312412312)), destTokenAddress: abi.encode(address(9809808909)), - extraData: "" + extraData: "", + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } } diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol index ada0369045c..a5c2487478f 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol @@ -99,7 +99,9 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { } contract TokenAdminRegistry_getAllConfiguredTokens is TokenAdminRegistrySetup { - function test_Fuzz_getAllConfiguredTokens_Success(uint8 numberOfTokens) public { + function test_Fuzz_getAllConfiguredTokens_Success( + uint8 numberOfTokens + ) public { TokenAdminRegistry cleanTokenAdminRegistry = new TokenAdminRegistry(); for (uint160 i = 0; i < numberOfTokens; ++i) { cleanTokenAdminRegistry.proposeAdministrator(address(i), address(i + 1000)); diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol index 3cd17df05f2..dd2c82fe3dc 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol @@ -12,12 +12,14 @@ contract RegistryModuleOwnerCustom is ITypeAndVersion { event AdministratorRegistered(address indexed token, address indexed administrator); - string public constant override typeAndVersion = "RegistryModuleOwnerCustom 1.5.0-dev"; + string public constant override typeAndVersion = "RegistryModuleOwnerCustom 1.5.0"; // The TokenAdminRegistry contract ITokenAdminRegistry internal immutable i_tokenAdminRegistry; - constructor(address tokenAdminRegistry) { + constructor( + address tokenAdminRegistry + ) { if (tokenAdminRegistry == address(0)) { revert AddressZero(); } @@ -27,14 +29,18 @@ contract RegistryModuleOwnerCustom is ITypeAndVersion { /// @notice Registers the admin of the token using the `getCCIPAdmin` method. /// @param token The token to register the admin for. /// @dev The caller must be the admin returned by the `getCCIPAdmin` method. - function registerAdminViaGetCCIPAdmin(address token) external { + function registerAdminViaGetCCIPAdmin( + address token + ) external { _registerAdmin(token, IGetCCIPAdmin(token).getCCIPAdmin()); } /// @notice Registers the admin of the token using the `owner` method. /// @param token The token to register the admin for. /// @dev The caller must be the admin returned by the `owner` method. - function registerAdminViaOwner(address token) external { + function registerAdminViaOwner( + address token + ) external { _registerAdmin(token, IOwner(token).owner()); } diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol index 32394a396ec..fbe821ebc7d 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol @@ -7,7 +7,7 @@ import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice This contract stores the token pool configuration for all CCIP enabled tokens. It works /// on a self-serve basis, where tokens can be registered without intervention from the CCIP owner. @@ -26,8 +26,6 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea event PoolSet(address indexed token, address indexed previousPool, address indexed newPool); event AdministratorTransferRequested(address indexed token, address indexed currentAdmin, address indexed newAdmin); event AdministratorTransferred(address indexed token, address indexed newAdmin); - event DisableReRegistrationSet(address indexed token, bool disabled); - event RemovedAdministrator(address token); event RegistryModuleAdded(address module); event RegistryModuleRemoved(address indexed module); @@ -39,7 +37,7 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea address tokenPool; // the token pool for this token. Can be address(0) if not deployed or not configured. } - string public constant override typeAndVersion = "TokenAdminRegistry 1.5.0-dev"; + string public constant override typeAndVersion = "TokenAdminRegistry 1.5.0"; // Mapping of token address to token configuration mapping(address token => TokenConfig) internal s_tokenConfig; @@ -52,7 +50,9 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea /// @notice Returns all pools for the given tokens. /// @dev Will return address(0) for tokens that do not have a pool. - function getPools(address[] calldata tokens) external view returns (address[] memory) { + function getPools( + address[] calldata tokens + ) external view returns (address[] memory) { address[] memory pools = new address[](tokens.length); for (uint256 i = 0; i < tokens.length; ++i) { pools[i] = s_tokenConfig[tokens[i]].tokenPool; @@ -61,14 +61,18 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea } /// @inheritdoc ITokenAdminRegistry - function getPool(address token) external view returns (address) { + function getPool( + address token + ) external view returns (address) { return s_tokenConfig[token].tokenPool; } /// @notice Returns the configuration for a token. /// @param token The token to get the configuration for. /// @return config The configuration for the token. - function getTokenConfig(address token) external view returns (TokenConfig memory) { + function getTokenConfig( + address token + ) external view returns (TokenConfig memory) { return s_tokenConfig[token]; } @@ -138,7 +142,9 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea /// @notice Accepts the administrator role for a token. /// @param localToken The token to accept the administrator role for. /// @dev This function can only be called by the pending administrator. - function acceptAdminRole(address localToken) external { + function acceptAdminRole( + address localToken + ) external { TokenConfig storage config = s_tokenConfig[localToken]; if (config.pendingAdministrator != msg.sender) { revert OnlyPendingAdministrator(msg.sender, localToken); @@ -189,13 +195,17 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea /// @notice Checks if an address is a registry module. /// @param module The address to check. /// @return True if the address is a registry module, false otherwise. - function isRegistryModule(address module) public view returns (bool) { + function isRegistryModule( + address module + ) public view returns (bool) { return s_registryModules.contains(module); } /// @notice Adds a new registry module to the list of allowed modules. /// @param module The module to add. - function addRegistryModule(address module) external onlyOwner { + function addRegistryModule( + address module + ) external onlyOwner { if (s_registryModules.add(module)) { emit RegistryModuleAdded(module); } @@ -203,7 +213,9 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea /// @notice Removes a registry module from the list of allowed modules. /// @param module The module to remove. - function removeRegistryModule(address module) external onlyOwner { + function removeRegistryModule( + address module + ) external onlyOwner { if (s_registryModules.remove(module)) { emit RegistryModuleRemoved(module); } @@ -214,7 +226,9 @@ contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCrea // ================================================================ /// @notice Checks if an address is the administrator of the given token. - modifier onlyTokenAdmin(address token) { + modifier onlyTokenAdmin( + address token + ) { if (s_tokenConfig[token].administrator != msg.sender) { revert OnlyAdministrator(msg.sender, token); } diff --git a/contracts/src/v0.8/ccip/v1.4-CCIP-License-grants.md b/contracts/src/v0.8/ccip/v1.4-CCIP-License-grants.md deleted file mode 100644 index f206b8adcc1..00000000000 --- a/contracts/src/v0.8/ccip/v1.4-CCIP-License-grants.md +++ /dev/null @@ -1,5 +0,0 @@ -v1.4-CCIP-License-grants - -Additional Use Grant(s): - -You may make use of the Cross-Chain Interoperability Protocol v1.4 (which is available subject to the license here the “Licensed Work ”) solely for purposes of importing client-side libraries or example clients to facilitate the integration of the Licensed Work into your application. \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md b/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md new file mode 100644 index 00000000000..ef0f55ea924 --- /dev/null +++ b/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md @@ -0,0 +1,8 @@ +v1.5-CCIP-License-grants + +Additional Use Grant(s): + +You may make use of the Cross-Chain Interoperability Protocol v1.5 (which is available subject to the license here, the “Licensed Work ”) solely for purposes of + +1. importing client-side libraries or example clients to facilitate the integration of the Licensed Work into your application. +2. Developing, deploying and operating [the token pool contracts](./pools) solely for purposes of the integration and use of CCIP. \ No newline at end of file diff --git a/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol b/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol index 4d159594b6d..28fa670650b 100644 --- a/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol +++ b/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol @@ -72,11 +72,7 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { */ // Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 numSigners, - uint256 numTransmitters, - uint256 f - ) { + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); if (f == 0) revert InvalidConfig("f must be positive"); if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); diff --git a/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol b/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol index ba671d4468b..b7c3f03fea7 100644 --- a/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol +++ b/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol @@ -70,11 +70,7 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { */ // Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 numSigners, - uint256 numTransmitters, - uint256 f - ) { + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); if (f == 0) revert InvalidConfig("f must be positive"); if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); diff --git a/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol b/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol index 5bee4360054..a4fd2bfa128 100644 --- a/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol +++ b/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol @@ -64,11 +64,7 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { */ // Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 numSigners, - uint256 numTransmitters, - uint256 f - ) { + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); if (f == 0) revert InvalidConfig("f must be positive"); if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); diff --git a/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol b/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol index caa9c301a33..565e7d800dd 100644 --- a/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol +++ b/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol @@ -72,11 +72,7 @@ abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { */ // Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 numSigners, - uint256 numTransmitters, - uint256 f - ) { + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); if (f == 0) revert InvalidConfig("f must be positive"); if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); diff --git a/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol index 2b8a82a2858..2dd707672da 100644 --- a/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol @@ -1,33 +1,32 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; + import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; - -/// @notice CapabilitiesRegistry is used to manage Nodes (including their links to Node -/// Operators), Capabilities, and DONs (Decentralized Oracle Networks) which are -/// sets of nodes that support those Capabilities. -/// @dev The contract currently stores the entire state of Node Operators, Nodes, -/// Capabilities and DONs in the contract and requires a full state migration -/// if an upgrade is ever required. The team acknowledges this and is fine -/// reconfiguring the upgraded contract in the future so as to not add extra -/// complexity to this current version. -contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { +import {INodeInfoProvider} from "./interfaces/INodeInfoProvider.sol"; + +/// @notice CapabilitiesRegistry is used to manage Nodes (including their links to Node Operators), Capabilities, +/// and DONs (Decentralized Oracle Networks) which are sets of nodes that support those Capabilities. +/// @dev The contract currently stores the entire state of Node Operators, Nodes, Capabilities and DONs in the +/// contract and requires a full state migration if an upgrade is ever required. The team acknowledges this and is +/// fine reconfiguring the upgraded contract in the future so as to not add extra complexity to this current version. +contract CapabilitiesRegistry is INodeInfoProvider, OwnerIsCreator, ITypeAndVersion { // Add the library methods using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.UintSet; struct NodeOperator { - /// @notice The address of the admin that can manage a node - /// operator + /// @notice The address of the admin that can manage a node operator address admin; /// @notice Human readable name of a Node Operator managing the node - /// @dev The contract does not validate the length or characters of the - /// node operator name because a trusted admin will supply these names. - /// We reduce gas costs by omitting these checks on-chain. + /// @dev The contract does not validate the length or characters of the node operator name because + /// a trusted admin will supply these names. We reduce gas costs by omitting these checks on-chain. string name; } @@ -36,34 +35,13 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { uint32 nodeOperatorId; /// @notice The signer address for application-layer message verification. bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. - /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is - /// used to identify a node in the the P2P network. - bytes32 p2pId; - /// @notice The list of hashed capability IDs supported by the node - bytes32[] hashedCapabilityIds; - } - - struct NodeInfo { - /// @notice The id of the node operator that manages this node - uint32 nodeOperatorId; - /// @notice The number of times the node's configuration has been updated - uint32 configCount; - /// @notice The ID of the Workflow DON that the node belongs to. A node can - /// only belong to one DON that accepts Workflows. - uint32 workflowDONId; - /// @notice The signer address for application-layer message verification. - bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. - /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is - /// used to identify a node in the the P2P network. + /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed to + /// be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; /// @notice The list of hashed capability IDs supported by the node bytes32[] hashedCapabilityIds; - /// @notice The list of capabilities DON Ids supported by the node. A node - /// can belong to multiple capabilities DONs. This list does not include a - /// Workflow DON id if the node belongs to one. - uint256[] capabilitiesDONIds; } struct Node { @@ -76,35 +54,31 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// only belong to one DON that accepts Workflows. uint32 workflowDONId; /// @notice The signer address for application-layer message verification. - /// @dev This key is guaranteed to be unique in the CapabilitiesRegistry - /// as a signer address can only belong to one node. - /// @dev This should be the ABI encoded version of the node's address. - /// I.e 0x0000address. The Capability Registry does not store it as an address so that - /// non EVM chains with addresses greater than 20 bytes can be supported + /// @dev This key is guaranteed to be unique in the CapabilitiesRegistry as a signer + /// address can only belong to one node. + /// @dev This should be the ABI encoded version of the node's address. I.e 0x0000address. The Capability Registry + /// does not store it as an address so that non EVM chains with addresses greater than 20 bytes can be supported /// in the future. bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. - /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is - /// used to identify a node in the the P2P network. + /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed + /// to be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; /// @notice The node's supported capabilities - /// @dev This is stored as a map so that we can easily update to a set of - /// new capabilities by incrementing the configCount and creating a - /// new set of supported capability IDs + /// @dev This is stored as a map so that we can easily update to a set of new capabilities by + /// incrementing the configCount and creating a new set of supported capability IDs mapping(uint32 configCount => EnumerableSet.Bytes32Set capabilityId) supportedHashedCapabilityIds; - /// @notice The list of capabilities DON Ids supported by the node. A node - /// can belong to multiple capabilities DONs. This list does not include a - /// Workflow DON id if the node belongs to one. + /// @notice The list of capabilities DON Ids supported by the node. A node can belong to multiple + /// capabilities DONs. This list does not include a Workflow DON id if the node belongs to one. EnumerableSet.UintSet capabilitiesDONIds; } - /// @notice CapabilityResponseType indicates whether remote response requires - // aggregation or is an already aggregated report. There are multiple - // possible ways to aggregate. - /// @dev REPORT response type receives signatures together with the response that - /// is used to verify the data. OBSERVATION_IDENTICAL just receives data without - /// signatures and waits for some number of observations before proceeeding to - /// the next step + /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is + /// an already aggregated report. There are multiple possible ways to aggregate. + /// @dev REPORT response type receives signatures together with the response that is used to verify the data. + /// OBSERVATION_IDENTICAL just receives data without signatures and waits for some number of observations before + /// proceeding to the next step enum CapabilityResponseType { // No additional aggregation is needed on the remote response. REPORT, @@ -124,7 +98,8 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { struct Capability { /// @notice The partially qualified ID for the capability. /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} - // Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` portion of the ID. + /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` + /// portion of the ID. /// /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" /// labelledName = "data-streams-reports:chain:ethereum" @@ -135,22 +110,18 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice CapabilityType indicates the type of capability which determines /// where the capability can be used in a Workflow Spec. CapabilityType capabilityType; - /// @notice CapabilityResponseType indicates whether remote response requires - // aggregation or is an already aggregated report. There are multiple - // possible ways to aggregate. + /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is an + /// already aggregated report. There are multiple possible ways to aggregate. CapabilityResponseType responseType; - /// @notice An address to the capability configuration contract. Having this defined - // on a capability enforces consistent configuration across DON instances - // serving the same capability. Configuration contract MUST implement - // CapabilityConfigurationContractInterface. - // + /// @notice An address to the capability configuration contract. Having this defined on a capability enforces + /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement + /// CapabilityConfigurationContractInterface. + /// /// @dev The main use cases are: - // 1) Sharing capability configuration across DON instances - // 2) Inspect and modify on-chain configuration without off-chain - // capability code. - // - // It is not recommended to store configuration which requires knowledge of - // the DON membership. + /// 1) Sharing capability configuration across DON instances + /// 2) Inspect and modify on-chain configuration without off-chain capability code. + /// + /// It is not recommended to store configuration which requires knowledge of the DON membership. address configurationContract; } @@ -159,7 +130,8 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { bytes32 hashedId; /// @notice The partially qualified ID for the capability. /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} - // Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` portion of the ID. + /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` + /// portion of the ID. /// /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" /// labelledName = "data-streams-reports:chain:ethereum" @@ -170,22 +142,18 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice CapabilityType indicates the type of capability which determines /// where the capability can be used in a Workflow Spec. CapabilityType capabilityType; - /// @notice CapabilityResponseType indicates whether remote response requires - // aggregation or is an already aggregated report. There are multiple - // possible ways to aggregate. + /// @notice CapabilityResponseType indicates whether remote response requires aggregation + /// or is an already aggregated report. There are multiple possible ways to aggregate. CapabilityResponseType responseType; - /// @notice An address to the capability configuration contract. Having this defined - // on a capability enforces consistent configuration across DON instances - // serving the same capability. Configuration contract MUST implement - // CapabilityConfigurationContractInterface. - // + /// @notice An address to the capability configuration contract. Having this defined on a capability enforces + /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement + /// CapabilityConfigurationContractInterface. + /// /// @dev The main use cases are: - // 1) Sharing capability configuration across DON instances - // 2) Inspect and modify on-chain configuration without off-chain - // capability code. - // - // It is not recommended to store configuration which requires knowledge of - // the DON membership. + /// 1) Sharing capability configuration across DON instances + /// 2) Inspect and modify on-chain configuration without off-chain capability code. + /// + /// It is not recommended to store configuration which requires knowledge of the DON membership. address configurationContract; /// @notice True if the capability is deprecated bool isDeprecated; @@ -196,14 +164,12 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { struct CapabilityConfiguration { /// @notice The capability Id bytes32 capabilityId; - /// @notice The capability config specific to a DON. This will be decoded - /// offchain + /// @notice The capability config specific to a DON. This will be decoded offchain bytes config; } struct DONCapabilityConfig { - /// @notice The set of p2pIds of nodes that belong to this DON. A node (the same - // p2pId) can belong to multiple DONs. + /// @notice The set of p2pIds of nodes that belong to this DON. A node (the same p2pId) can belong to multiple DONs. EnumerableSet.Bytes32Set nodes; /// @notice The set of capabilityIds bytes32[] capabilityIds; @@ -283,6 +249,11 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param p2pId The provided P2P ID error InvalidNodeP2PId(bytes32 p2pId); + /// @notice This error is thrown when trying to add a node without + /// including the encryption public key bytes. + /// @param encryptionPublicKey The encryption public key bytes + error InvalidNodeEncryptionPublicKey(bytes32 encryptionPublicKey); + /// @notice This error is thrown when trying to add a node without /// capabilities or with capabilities that do not exist. /// @param hashedCapabilityIds The IDs of the capabilities that are being added. @@ -341,17 +312,12 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param hashedCapabilityId The hashed ID of the capability that is deprecated. error CapabilityIsDeprecated(bytes32 hashedCapabilityId); - /// @notice This error is thrown when a node with the provided P2P ID is - /// not found. - /// @param nodeP2PId The node P2P ID used for the lookup. - error NodeDoesNotExist(bytes32 nodeP2PId); - /// @notice This error is thrown when a node operator does not exist /// @param nodeOperatorId The ID of the node operator that does not exist error NodeOperatorDoesNotExist(uint32 nodeOperatorId); /// @notice This error is thrown when trying to remove a node that is still - /// part of a capabitlities DON + /// part of a capabilities DON /// @param donId The Id of the DON the node belongs to /// @param nodeP2PId The P2P Id of the node being removed error NodePartOfCapabilitiesDON(uint32 donId, bytes32 nodeP2PId); @@ -396,7 +362,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param donId The ID of the DON the config was set for /// @param configCount The number of times the DON has been /// configured - event ConfigSet(uint32 donId, uint32 configCount); + event ConfigSet(uint32 indexed donId, uint32 configCount); /// @notice This event is emitted when a new node operator is added /// @param nodeOperatorId The ID of the newly added node operator @@ -423,6 +389,8 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param hashedCapabilityId The hashed ID of the deprecated capability event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); + string public constant override typeAndVersion = "CapabilitiesRegistry 1.0.1"; + /// @notice Mapping of capabilities mapping(bytes32 hashedCapabilityId => Capability capability) private s_capabilities; @@ -456,13 +424,8 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice The next ID to assign a new DON to /// @dev Starting with 1 to avoid confusion with the zero value - /// @dev No getter for this as this is an implementation detail uint32 private s_nextDONId = 1; - function typeAndVersion() external pure override returns (string memory) { - return "CapabilitiesRegistry 1.0.0"; - } - /// @notice Adds a list of node operators /// @param nodeOperators List of node operators to add function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner { @@ -543,6 +506,12 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { return nodeOperators; } + /// @notice Gets the next node DON ID + /// @return uint32 The next node DON ID + function getNextDONId() external view returns (uint32) { + return s_nextDONId; + } + /// @notice Adds nodes. Nodes can be added with deprecated capabilities to /// avoid breaking changes when deprecating capabilities. /// @param nodes The nodes to add @@ -561,6 +530,8 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { if (node.signer == bytes32("") || s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); + if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey); + bytes32[] memory capabilityIds = node.hashedCapabilityIds; if (capabilityIds.length == 0) revert InvalidNodeCapabilities(capabilityIds); @@ -572,6 +543,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(capabilityIds[j]); } + storedNode.encryptionPublicKey = node.encryptionPublicKey; storedNode.nodeOperatorId = node.nodeOperatorId; storedNode.p2pId = node.p2pId; storedNode.signer = node.signer; @@ -627,6 +599,8 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { s_nodeSigners.add(node.signer); } + if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey); + bytes32[] memory supportedHashedCapabilityIds = node.hashedCapabilityIds; if (supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(supportedHashedCapabilityIds); @@ -664,6 +638,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { storedNode.nodeOperatorId = node.nodeOperatorId; storedNode.p2pId = node.p2pId; + storedNode.encryptionPublicKey = node.encryptionPublicKey; emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer); } @@ -678,6 +653,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { nodeOperatorId: s_nodes[p2pId].nodeOperatorId, p2pId: s_nodes[p2pId].p2pId, signer: s_nodes[p2pId].signer, + encryptionPublicKey: s_nodes[p2pId].encryptionPublicKey, hashedCapabilityIds: s_nodes[p2pId].supportedHashedCapabilityIds[s_nodes[p2pId].configCount].values(), configCount: s_nodes[p2pId].configCount, workflowDONId: s_nodes[p2pId].workflowDONId, @@ -698,6 +674,19 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { return nodesInfo; } + /// @notice Gets nodes by their P2P IDs + /// @param p2pIds The P2P IDs of the nodes to query for + /// @return NodeInfo[] The nodes data + function getNodesByP2PIds(bytes32[] calldata p2pIds) external view returns (NodeInfo[] memory) { + NodeInfo[] memory nodesInfo = new NodeInfo[](p2pIds.length); + + for (uint256 i; i < p2pIds.length; ++i) { + nodesInfo[i] = getNode(p2pIds[i]); + if (nodesInfo[i].p2pId == bytes32("")) revert NodeDoesNotExist(p2pIds[i]); + } + return nodesInfo; + } + /// @notice Adds a new capability to the capability registry /// @param capabilities The capabilities being added /// @dev There is no function to update capabilities as this would require @@ -904,8 +893,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice Sets the configuration for a DON /// @param nodes The nodes making up the DON - /// @param capabilityConfigurations The list of configurations for the - /// capabilities supported by the DON + /// @param capabilityConfigurations The list of configurations for the capabilities supported by the DON /// @param donParams The DON's parameters function _setDONConfig( bytes32[] calldata nodes, @@ -1021,8 +1009,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// by implementing both getCapabilityConfiguration and /// beforeCapabilityConfigSet if ( - capability.configurationContract.code.length == 0 || - !IERC165(capability.configurationContract).supportsInterface(type(ICapabilityConfiguration).interfaceId) + !ERC165Checker.supportsInterface(capability.configurationContract, type(ICapabilityConfiguration).interfaceId) ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); } s_capabilities[hashedCapabilityId] = capability; diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index ba1a7c6a8c3..447c979d405 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; import {IReceiver} from "./interfaces/IReceiver.sol"; +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); @@ -99,7 +101,7 @@ contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { return (report.Price, report.Timestamp); } - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return interfaceId == this.onReport.selector; + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol new file mode 100644 index 00000000000..5a28aa5f96a --- /dev/null +++ b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +/// @title Keystone Feeds Permission Handler +/// @notice This contract is designed to manage and validate permissions for accessing specific reports within a decentralized system. +/// @dev The contract uses mappings to keep track of report permissions associated with a unique report ID. +abstract contract KeystoneFeedsPermissionHandler is OwnerIsCreator { + /// @notice Holds the details for permissions of a report + /// @dev Workflow names and report names are stored as bytes to optimize for gas efficiency. + struct Permission { + address forwarder; // ──────╮ The address of the forwarder (20 bytes) + bytes10 workflowName; // │ The name of the workflow in bytes10 + bytes2 reportName; // ──────╯ The name of the report in bytes2 + address workflowOwner; // ──╮ The address of the workflow owner (20 bytes) + bool isAllowed; // ─────────╯ Whether the report is allowed or not (1 byte) + } + + /// @notice Event emitted when report permissions are set + event ReportPermissionSet(bytes32 indexed reportId, Permission permission); + + /// @notice Error to be thrown when an unauthorized access attempt is made + error ReportForwarderUnauthorized(address forwarder, address workflowOwner, bytes10 workflowName, bytes2 reportName); + + /// @dev Mapping from a report ID to a boolean indicating whether the report is allowed or not + mapping(bytes32 reportId => bool isAllowed) internal s_allowedReports; + + /// @notice Sets permissions for multiple reports + /// @param permissions An array of Permission structs for which to set permissions + /// @dev Emits a ReportPermissionSet event for each permission set + function setReportPermissions(Permission[] memory permissions) external onlyOwner { + for (uint256 i; i < permissions.length; ++i) { + _setReportPermission(permissions[i]); + } + } + + /// @dev Internal function to set a single report permission + /// @param permission The Permission struct containing details about the permission to set + /// @dev Emits a ReportPermissionSet event + function _setReportPermission(Permission memory permission) internal { + bytes32 reportId = _createReportId( + permission.forwarder, + permission.workflowOwner, + permission.workflowName, + permission.reportName + ); + s_allowedReports[reportId] = permission.isAllowed; + emit ReportPermissionSet(reportId, permission); + } + + /// @dev Internal view function to validate if a report is allowed for a given set of details + /// @param forwarder The address of the forwarder + /// @param workflowOwner The address of the workflow owner + /// @param workflowName The name of the workflow in bytes10 + /// @param reportName The name of the report in bytes2 + /// @dev Reverts with Unauthorized if the report is not allowed + function _validateReportPermission( + address forwarder, + address workflowOwner, + bytes10 workflowName, + bytes2 reportName + ) internal view { + bytes32 reportId = _createReportId(forwarder, workflowOwner, workflowName, reportName); + if (!s_allowedReports[reportId]) { + revert ReportForwarderUnauthorized(forwarder, workflowOwner, workflowName, reportName); + } + } + + /// @notice Generates a unique report ID based on the provided parameters. + /// @dev The report ID is computed using the Keccak-256 hash function over the encoded parameters. + /// @param forwarder The address of the forwarder associated with the report. + /// @param workflowOwner The address of the owner of the workflow. + /// @param workflowName The name of the workflow, represented as a 10-byte value. + /// @param reportName The name of the report, represented as a 2-byte value. + /// @return reportId The computed unique report ID as a bytes32 value. + function _createReportId( + address forwarder, + address workflowOwner, + bytes10 workflowName, + bytes2 reportName + ) internal pure returns (bytes32 reportId) { + return keccak256(abi.encode(forwarder, workflowOwner, workflowName, reportName)); + } +} diff --git a/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/contracts/src/v0.8/keystone/KeystoneForwarder.sol index f92295cab97..3616667fc78 100644 --- a/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ b/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -1,57 +1,50 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - +import {IReceiver} from "./interfaces/IReceiver.sol"; +import {IRouter} from "./interfaces/IRouter.sol"; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; + import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -import {IReceiver} from "./interfaces/IReceiver.sol"; -import {IRouter} from "./interfaces/IRouter.sol"; +import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; -/// @notice This is an entry point for `write_${chain}` Target capability. It -/// allows nodes to determine if reports have been processed (successfully or -/// not) in a decentralized and product-agnostic way by recording processed -/// reports. +/// @notice This is an entry point for `write_${chain}` Target capability. It allows nodes to +/// determine if reports have been processed (successfully or not) in a decentralized and +/// product-agnostic way by recording processed reports. contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { - /// @notice This error is returned when the report is shorter than - /// REPORT_METADATA_LENGTH, which is the minimum length of a report. + /// @notice This error is returned when the report is shorter than REPORT_METADATA_LENGTH, + /// which is the minimum length of a report. error InvalidReport(); - /// @notice This error is thrown whenever trying to set a config with a fault - /// tolerance of 0. + /// @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 configuration provides more signers - /// than the maximum allowed number. + /// @notice This error is thrown whenever configuration provides more signers than the maximum allowed number. /// @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 configuration is provided with - /// less than the minimum number of signers. + /// @notice This error is thrown whenever a configuration is provided with less than the minimum number of signers. /// @param numSigners The number of signers provided /// @param minSigners The minimum number of signers expected error InsufficientSigners(uint256 numSigners, uint256 minSigners); - /// @notice This error is thrown whenever a duplicate signer address is - /// provided in the configuration. + /// @notice This error is thrown whenever a duplicate signer address is provided in the configuration. /// @param signer The signer address that was duplicated. error DuplicateSigner(address signer); - /// @notice This error is thrown whenever a report has an incorrect number of - /// signatures. + /// @notice This error is thrown whenever a report has an incorrect number of signatures. /// @param expected The number of signatures expected, F + 1 /// @param received The number of signatures received error InvalidSignatureCount(uint256 expected, uint256 received); - /// @notice This error is thrown whenever a report specifies a configuration that - /// does not exist. + /// @notice This error is thrown whenever a report specifies a configuration that does not exist. /// @param configId (uint64(donId) << 32) | configVersion error InvalidConfig(uint64 configId); - /// @notice This error is thrown whenever a signer address is not in the - /// configuration or when trying to set a zero address as a signer. + /// @notice This error is thrown whenever a signer address is not in the configuration or + /// when trying to set a zero address as a signer. /// @param signer The signer address that was not in the configuration error InvalidSigner(address signer); @@ -66,11 +59,18 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { mapping(address signer => uint256 position) _positions; // 1-indexed to detect unset values } - /// @notice Contains the configuration for each DON ID - // @param configId (uint64(donId) << 32) | configVersion - mapping(uint64 configId => OracleSet oracleSet) internal s_configs; - - event ConfigSet(uint32 indexed donId, uint32 indexed configVersion, uint8 f, address[] signers); + struct Transmission { + address transmitter; + // This is true if the receiver is not a contract or does not implement the `IReceiver` interface. + bool invalidReceiver; + // Whether the transmission attempt was successful. If `false`, the transmission can be retried + // with an increased gas limit. + bool success; + // The amount of gas allocated for the `IReceiver.onReport` call. uint80 allows storing gas for known EVM block + // gas limits. Ensures that the minimum gas requested by the user is available during the transmission attempt. + // If the transmission fails (indicated by a `false` success state), it can be retried with an increased gas limit. + uint80 gasLimit; + } /// @notice Emitted when a report is processed /// @param result The result of the attempted delivery. True if successful. @@ -81,6 +81,12 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { bool result ); + /// @notice Contains the configuration for each DON ID + /// configId (uint64(donId) << 32) | configVersion + mapping(uint64 configId => OracleSet oracleSet) internal s_configs; + + event ConfigSet(uint32 indexed donId, uint32 indexed configVersion, uint8 f, address[] signers); + string public constant override typeAndVersion = "Forwarder and Router 1.0.0"; constructor() OwnerIsCreator() { @@ -92,9 +98,15 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { uint256 internal constant FORWARDER_METADATA_LENGTH = 45; uint256 internal constant SIGNATURE_LENGTH = 65; - /// @dev The gas we require to revert in case of a revert in the call to the - /// receiver. This is more than enough and does not attempt to be exact. - uint256 internal constant REQUIRED_GAS_FOR_ROUTING = 40_000; + /// @dev This is the gas required to store `success` after the report is processed. + /// It is a warm storage write because of the packed struct. In practice it will cost less. + uint256 internal constant INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT = 5_000; + /// @dev This is the gas required to store the transmission struct and perform other checks. + uint256 internal constant INTERNAL_GAS_REQUIREMENTS = 25_000 + INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT; + /// @dev This is the minimum gas required to route a report. This includes internal gas requirements + /// as well as the minimum gas that the user contract will receive. 30k * 3 gas is to account for + /// cases where consumers need close to the 30k limit provided in the supportsInterface check. + uint256 internal constant MINIMUM_GAS_LIMIT = INTERNAL_GAS_REQUIREMENTS + 30_000 * 3 + 10_000; // ================================================================ // │ Router │ @@ -121,39 +133,36 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { bytes calldata validatedReport ) public returns (bool) { if (!s_forwarders[msg.sender]) revert UnauthorizedForwarder(); - uint256 gasLeft = gasleft(); - if (gasLeft < REQUIRED_GAS_FOR_ROUTING) revert InsufficientGasForRouting(transmissionId); + + uint256 gasLimit = gasleft() - INTERNAL_GAS_REQUIREMENTS; + if (gasLimit < MINIMUM_GAS_LIMIT) revert InsufficientGasForRouting(transmissionId); Transmission memory transmission = s_transmissions[transmissionId]; if (transmission.success || transmission.invalidReceiver) revert AlreadyAttempted(transmissionId); - uint256 gasLimit = gasLeft - REQUIRED_GAS_FOR_ROUTING; s_transmissions[transmissionId].transmitter = transmitter; s_transmissions[transmissionId].gasLimit = uint80(gasLimit); - if (receiver.code.length == 0) { + // This call can consume up to 90k gas. + if (!ERC165Checker.supportsInterface(receiver, type(IReceiver).interfaceId)) { s_transmissions[transmissionId].invalidReceiver = true; return false; } - try IERC165(receiver).supportsInterface(type(IReceiver).interfaceId) { - bool success; - bytes memory payload = abi.encodeCall(IReceiver.onReport, (metadata, validatedReport)); + bool success; + bytes memory payload = abi.encodeCall(IReceiver.onReport, (metadata, validatedReport)); - assembly { - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasLimit, receiver, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) - } + uint256 remainingGas = gasleft() - INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT; + assembly { + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(remainingGas, receiver, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) + } - if (success) { - s_transmissions[transmissionId].success = true; - } - return success; - } catch { - s_transmissions[transmissionId].invalidReceiver = true; - return false; + if (success) { + s_transmissions[transmissionId].success = true; } + return success; } function getTransmissionId( @@ -161,8 +170,7 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { bytes32 workflowExecutionId, bytes2 reportId ) public pure returns (bytes32) { - // This is slightly cheaper compared to - // keccak256(abi.encode(receiver, workflowExecutionId, reportId)); + // This is slightly cheaper compared to `keccak256(abi.encode(receiver, workflowExecutionId, reportId));` return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); } diff --git a/contracts/src/v0.8/keystone/OCR3Capability.sol b/contracts/src/v0.8/keystone/OCR3Capability.sol index 1ba934b1c40..d054434361c 100644 --- a/contracts/src/v0.8/keystone/OCR3Capability.sol +++ b/contracts/src/v0.8/keystone/OCR3Capability.sol @@ -1,29 +1,168 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {OCR2Base} from "./ocr/OCR2Base.sol"; +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; +import {OCR2Abstract} from "./ocr/OCR2Abstract.sol"; -// OCR2Base provides config management compatible with OCR3 -contract OCR3Capability is OCR2Base { +/// @notice OCR2Base provides config management compatible with OCR3 +contract OCR3Capability is OwnerIsCreator, OCR2Abstract { + error InvalidConfig(string message); error ReportingUnsupported(); - constructor() OCR2Base() {} + string public constant override typeAndVersion = "Keystone 1.0.0"; - function typeAndVersion() external pure override returns (string memory) { - return "Keystone 1.0.0"; + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + // makes it easier for offchain systems to extract config from logs. + uint32 internal s_latestConfigBlockNumber; + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a single SLOAD. If any further fields are + // added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // TODO: could be optimized by squeezing into one slot + uint8 n; + } + ConfigInfo internal s_configInfo; + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @param _signers addresses with which oracles sign the reports + /// @param _transmitters addresses oracles use to transmit the reports + /// @param _f number of faulty oracles the system can tolerate + /// @param _onchainConfig encoded on-chain contract configuration + /// @param _offchainConfigVersion version number for offchainEncoding schema + /// @param _offchainConfig encoded off-chain oracle configuration + /// @dev signer = [ 1 byte type | 2 byte len | n byte value ]... + function setConfig( + bytes[] calldata _signers, + address[] calldata _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < _signers.length; ++i) { + if (_transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); + // add new signers + bytes calldata publicKeys = _signers[i]; + uint256 offset = 0; + uint256 publicKeysLength = uint16(publicKeys.length); + // scan through public keys to validate encoded format + while (offset < publicKeysLength) { + if (offset + 3 > publicKeysLength) revert InvalidConfig("invalid signer pubKey encoding"); + uint256 keyLen = uint256(uint8(publicKeys[offset + 1])) + (uint256(uint8(publicKeys[offset + 2])) << 8); + if (offset + 3 + keyLen > publicKeysLength) revert InvalidConfig("invalid signer pubKey encoding"); + offset += 3 + keyLen; + } + } + s_configInfo.f = _f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _offchainConfigVersion, + _offchainConfig + ); + } + s_configInfo.n = uint8(_signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _offchainConfigVersion, + _offchainConfig + ); + } + + function _configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + bytes[] calldata _signers, + address[] calldata _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x000e << (256 - 16); // 0x000e00..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); } - function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { - // no-op + /// @notice information about current offchain reporting protocol configuration + /// @return configCount ordinal number of current config, out of all configs applied to this contract so far + /// @return blockNumber block at which this config was set + /// @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); } - function _report( - uint256 /* initialGas */, - address /* transmitter */, - uint8 /* signerCount */, - address[MAX_NUM_ORACLES] memory /* signers */, - bytes calldata /* report */ - ) internal virtual override { + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata /* reportContext */, + bytes calldata /* report */, + bytes32[] calldata /* rs */, + bytes32[] calldata /* ss */, + bytes32 /* rawVs */ // signatures + ) external pure override { revert ReportingUnsupported(); } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } } diff --git a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol index 702d55dba9d..6c144474684 100644 --- a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol +++ b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.0; /// @notice Interface for capability configuration contract. It MUST be /// implemented for a contract to be used as a capability configuration. diff --git a/contracts/src/v0.8/ccip/capability/interfaces/ICapabilitiesRegistry.sol b/contracts/src/v0.8/keystone/interfaces/INodeInfoProvider.sol similarity index 50% rename from contracts/src/v0.8/ccip/capability/interfaces/ICapabilitiesRegistry.sol rename to contracts/src/v0.8/keystone/interfaces/INodeInfoProvider.sol index 621c3686cfa..47b4b2065fc 100644 --- a/contracts/src/v0.8/ccip/capability/interfaces/ICapabilitiesRegistry.sol +++ b/contracts/src/v0.8/keystone/interfaces/INodeInfoProvider.sol @@ -1,7 +1,14 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @title INodeInfoProvider +/// @notice Interface for retrieving node information. +interface INodeInfoProvider { + /// @notice This error is thrown when a node with the provided P2P ID is + /// not found. + /// @param nodeP2PId The node P2P ID used for the lookup. + error NodeDoesNotExist(bytes32 nodeP2PId); -interface ICapabilitiesRegistry { struct NodeInfo { /// @notice The id of the node operator that manages this node uint32 nodeOperatorId; @@ -16,6 +23,8 @@ interface ICapabilitiesRegistry { /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is /// used to identify a node in the the P2P network. bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; /// @notice The list of hashed capability IDs supported by the node bytes32[] hashedCapabilityIds; /// @notice The list of capabilities DON Ids supported by the node. A node @@ -24,8 +33,17 @@ interface ICapabilitiesRegistry { uint256[] capabilitiesDONIds; } - /// @notice Gets a node's data - /// @param p2pId The P2P ID of the node to query for - /// @return NodeInfo The node data - function getNode(bytes32 p2pId) external view returns (NodeInfo memory); + /// @notice Retrieves node information by its P2P ID. + /// @param p2pId The P2P ID of the node to query for. + /// @return nodeInfo The node data. + function getNode(bytes32 p2pId) external view returns (NodeInfo memory nodeInfo); + + /// @notice Retrieves all node information. + /// @return NodeInfo[] Array of all nodes in the registry. + function getNodes() external view returns (NodeInfo[] memory); + + /// @notice Retrieves nodes by their P2P IDs. + /// @param p2pIds Array of P2P IDs to query for. + /// @return NodeInfo[] Array of node data corresponding to the provided P2P IDs. + function getNodesByP2PIds(bytes32[] calldata p2pIds) external view returns (NodeInfo[] memory); } diff --git a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol index debe58feea4..9afa1d340a3 100644 --- a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol +++ b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.0; /// @title IReceiver - receives keystone reports interface IReceiver { diff --git a/contracts/src/v0.8/keystone/interfaces/IRouter.sol b/contracts/src/v0.8/keystone/interfaces/IRouter.sol index e40f3318679..3d2e24f550a 100644 --- a/contracts/src/v0.8/keystone/interfaces/IRouter.sol +++ b/contracts/src/v0.8/keystone/interfaces/IRouter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.4; /// @title IRouter - delivers keystone reports to receiver interface IRouter { @@ -19,22 +19,6 @@ interface IRouter { FAILED } - struct Transmission { - address transmitter; - // This is true if the receiver is not a contract or does not implement the - // `IReceiver` interface. - bool invalidReceiver; - // Whether the transmission attempt was successful. If `false`, the - // transmission can be retried with an increased gas limit. - bool success; - // The amount of gas allocated for the `IReceiver.onReport` call. uint80 - // allows storing gas for known EVM block gas limits. - // Ensures that the minimum gas requested by the user is available during - // the transmission attempt. If the transmission fails (indicated by a - // `false` success state), it can be retried with an increased gas limit. - uint80 gasLimit; - } - struct TransmissionInfo { bytes32 transmissionId; TransmissionState state; diff --git a/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol b/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol new file mode 100644 index 00000000000..2eb9b5529de --- /dev/null +++ b/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +library KeystoneFeedDefaultMetadataLib { + /** + * Metadata Layout: + * + * +-------------------------------+--------------------+---------------------+---------------+ + * | 32 bytes (length prefix) | 32 bytes | 10 bytes | 20 bytes | 2 bytes | + * | (Not used in function) | workflow_cid | workflow_name | workflow_owner| report_name | + * +-------------------------------+--------------------+---------------------+---------------+----------------+ + * | | | | | | + * | (Offset 0) | (Offset 32) | (Offset 64) | (Offset 74) | (Offset 94) | + * +-------------------------------+--------------------+---------------------+---------------+----------------+ + * @dev used to slice metadata bytes into workflowName, workflowOwner and report name + */ + function _extractMetadataInfo( + bytes memory metadata + ) internal pure returns (bytes10 workflowName, address workflowOwner, bytes2 reportName) { + // (first 32 bytes contain length of the byte array) + // workflow_cid // offset 32, size 32 + // workflow_name // offset 64, size 10 + // workflow_owner // offset 74, size 20 + // report_name // offset 94, size 2 + assembly { + // no shifting needed for bytes10 type + workflowName := mload(add(metadata, 64)) + // shift right by 12 bytes to get the actual value + workflowOwner := shr(mul(12, 8), mload(add(metadata, 74))) + // no shifting needed for bytes2 type + reportName := mload(add(metadata, 94)) + } + return (workflowName, workflowOwner, reportName); + } +} diff --git a/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol b/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol index 3c1e304748f..af822a69854 100644 --- a/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol +++ b/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol @@ -23,7 +23,7 @@ abstract contract OCR2Abstract is ITypeAndVersion { uint32 previousConfigBlockNumber, bytes32 configDigest, uint64 configCount, - address[] signers, + bytes[] signers, address[] transmitters, uint8 f, bytes onchainConfig, @@ -41,7 +41,7 @@ abstract contract OCR2Abstract is ITypeAndVersion { * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract */ function setConfig( - address[] memory signers, + bytes[] memory signers, address[] memory transmitters, uint8 f, bytes memory onchainConfig, @@ -62,8 +62,8 @@ abstract contract OCR2Abstract is ITypeAndVersion { returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); /** - * @notice optionally emited to indicate the latest configDigest and epoch for - which a report was successfully transmited. Alternatively, the contract may + * @notice optionally emitted to indicate the latest configDigest and epoch for + which a report was successfully transmitted. Alternatively, the contract may use latestConfigDigestAndEpoch with scanLogs set to false. */ event Transmitted(bytes32 configDigest, uint32 epoch); diff --git a/contracts/src/v0.8/keystone/ocr/OCR2Base.sol b/contracts/src/v0.8/keystone/ocr/OCR2Base.sol deleted file mode 100644 index efc7992e90a..00000000000 --- a/contracts/src/v0.8/keystone/ocr/OCR2Base.sol +++ /dev/null @@ -1,352 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/** - * @notice Onchain verification of reports from the offchain reporting protocol - * @dev For details on its operation, see the offchain reporting protocol design - * doc, which refers to this contract as simply the "contract". - */ -abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { - error ReportInvalid(string message); - error InvalidConfig(string message); - - constructor() ConfirmedOwner(msg.sender) {} - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems - // to extract config from logs. - - // Storing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them to a single SLOAD. If any further fields are - // added, make sure that storage of the struct still takes at most 32 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // TODO: could be optimized by squeezing into one slot - uint8 n; - } - ConfigInfo internal s_configInfo; - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - mapping(address signerOrTransmitter => Oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - /* - * Config logic - */ - - // Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 numSigners, - uint256 numTransmitters, - uint256 f - ) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - // solhint-disable-next-line gas-struct-packing - struct SetConfigArgs { - address[] signers; - address[] transmitters; - uint8 f; - bytes onchainConfig; - uint64 offchainConfigVersion; - bytes offchainConfig; - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param _signers addresses with which oracles sign the reports - * @param _transmitters addresses oracles use to transmit the reports - * @param _f number of faulty oracles the system can tolerate - * @param _onchainConfig encoded on-chain contract configuration - * @param _offchainConfigVersion version number for offchainEncoding schema - * @param _offchainConfig encoded off-chain oracle configuration - */ - function setConfig( - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - SetConfigArgs memory args = SetConfigArgs({ - signers: _signers, - transmitters: _transmitters, - f: _f, - onchainConfig: _onchainConfig, - offchainConfigVersion: _offchainConfigVersion, - offchainConfig: _offchainConfig - }); - - _beforeSetConfig(args.f, args.onchainConfig); - - while (s_signers.length != 0) { - // remove any old signer/transmitter addresses - uint256 lastIdx = s_signers.length - 1; - address signer = s_signers[lastIdx]; - address transmitter = s_transmitters[lastIdx]; - delete s_oracles[signer]; - delete s_oracles[transmitter]; - s_signers.pop(); - s_transmitters.pop(); - } - - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < args.signers.length; i++) { - if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); - if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); - // add new signer/transmitter addresses - if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); - s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); - if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); - s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); - s_signers.push(args.signers[i]); - s_transmitters.push(args.transmitters[i]); - } - s_configInfo.f = args.f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - s_configInfo.n = uint8(args.signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - - function _configDigestFromConfigData( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /** - * @return list of addresses permitted to transmit reports to this contract - * @dev The list will match the order used to specify the transmitter during setConfig - */ - function transmitters() external view returns (address[] memory) { - return s_transmitters; - } - - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - /** - * @dev hook called after the report has been fully validated - * for the extending contract to handle additional logic, such as oracle payment - * @param initialGas the amount of gas before validation - * @param transmitter the address of the account that submitted the report - * @param signers the addresses of all signing accounts - * @param report serialized report - */ - function _report( - uint256 initialGas, - address transmitter, - uint8 signerCount, - address[MAX_NUM_ORACLES] memory signers, - bytes calldata report - ) internal virtual; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32 + // word containing length of ss - 0; // placeholder - - function _requireExpectedMsgDataLength( - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss - ) private pure { - // calldata will never be big enough to make this overflow - uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32 + // 32 bytes per entry in _ss - 0; // placeholder - if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); - } - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - uint256 initialGas = gasleft(); // This line must come first - - { - // 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]; - uint32 epochAndRound = uint32(uint256(reportContext[1])); - - emit Transmitted(configDigest, uint32(epochAndRound >> 8)); - - // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest - // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router - // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); - - _requireExpectedMsgDataLength(report, rs, ss); - - uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; - - if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); - if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); - - Oracle memory transmitter = s_oracles[msg.sender]; - if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) - revert ReportInvalid("unauthorized transmitter"); - } - - address[MAX_NUM_ORACLES] memory signed; - uint8 signerCount = 0; - - { - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - Oracle memory o; - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < rs.length; ++i) { - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_oracles[signer]; - if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); - if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); - signed[o.index] = signer; - signerCount += 1; - } - } - - _report(initialGas, msg.sender, signerCount, signed, report); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol index dc0b85bfa3f..4e8725a2ee1 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol @@ -25,6 +25,7 @@ contract CapabilitiesRegistry_AddDONTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: capabilityIds }); @@ -35,6 +36,7 @@ contract CapabilitiesRegistry_AddDONTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: nodeTwoCapabilityIds }); @@ -42,6 +44,7 @@ contract CapabilitiesRegistry_AddDONTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, hashedCapabilityIds: capabilityIds }); @@ -275,6 +278,7 @@ contract CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationCon nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: capabilityIds }); @@ -285,6 +289,7 @@ contract CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationCon nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: nodeTwoCapabilityIds }); @@ -292,6 +297,7 @@ contract CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationCon nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, hashedCapabilityIds: capabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol index c7c92587cf7..aa6cca4aa28 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol @@ -27,6 +27,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -47,6 +48,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: invalidNodeOperatorId, // Invalid NOP p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -67,6 +69,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: bytes32(""), + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -74,6 +77,25 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { s_CapabilitiesRegistry.addNodes(nodes); } + function test_RevertWhen_EncryptionPublicKeyEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: bytes32(""), + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); + s_CapabilitiesRegistry.addNodes(nodes); + } + function test_RevertWhen_SignerAddressNotUnique() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); @@ -85,6 +107,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -97,6 +120,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); @@ -114,6 +138,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -134,6 +159,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: bytes32(""), signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -151,6 +177,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -169,6 +196,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -188,6 +216,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -216,6 +245,7 @@ contract CapabilitiesRegistry_AddNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol index a79485abad1..6d8dd13eb6a 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol @@ -27,6 +27,7 @@ contract CapabilitiesRegistry_GetDONsTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: capabilityIds }); @@ -37,6 +38,7 @@ contract CapabilitiesRegistry_GetDONsTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: nodeTwoCapabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNextDONIdTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNextDONIdTest.t.sol new file mode 100644 index 00000000000..0c6c74c204f --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNextDONIdTest.t.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; + +contract CapabilitiesRegistry_GetNextDONIdTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicHashedCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + nodes[2] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, + p2pId: P2P_ID_THREE, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + hashedCapabilityIds: capabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + changePrank(ADMIN); + } + + function test_CorrectlyFetchesNextDONId() public { + uint32 nextDONId = s_CapabilitiesRegistry.getNextDONId(); + assertEq(nextDONId, 1); // Expecting the first DON ID since no DONs have been added yet + + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_THREE; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, 1); + vm.expectCall( + address(s_capabilityConfigurationContract), + abi.encodeWithSelector( + ICapabilityConfiguration.beforeCapabilityConfigSet.selector, + nodes, + CONFIG_CAPABILITY_CONFIG, + 1, + DON_ID + ), + 1 + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + nextDONId = s_CapabilitiesRegistry.getNextDONId(); + assertEq(nextDONId, 2); // After adding one DON, the next DON ID should be 2 + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol index a5fe5fa1d1a..e01747877e7 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +import {INodeInfoProvider} from "../interfaces/INodeInfoProvider.sol"; contract CapabilitiesRegistry_GetNodesTest is BaseTest { function setUp() public override { @@ -25,6 +26,7 @@ contract CapabilitiesRegistry_GetNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -32,6 +34,7 @@ contract CapabilitiesRegistry_GetNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); @@ -61,6 +64,24 @@ contract CapabilitiesRegistry_GetNodesTest is BaseTest { assertEq(nodes[1].configCount, 1); } + function test_CorrectlyFetchesSpecificNodes() public view { + bytes32[] memory p2pIds = new bytes32[](1); + p2pIds[0] = P2P_ID; + + CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodesByP2PIds(p2pIds); + assertEq(nodes.length, 1); + assertEq(nodes[0].p2pId, P2P_ID); + assertEq(nodes[0].signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + } + + function test_GetNodesByP2PIdsInvalidNode_Revers() public { + bytes32[] memory p2pIds = new bytes32[](1); + p2pIds[0] = keccak256(abi.encodePacked("invalid")); + + vm.expectRevert(abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, p2pIds[0])); + CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodesByP2PIds(p2pIds); + } + function test_DoesNotIncludeRemovedNodes() public { changePrank(ADMIN); bytes32[] memory nodesToRemove = new bytes32[](1); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol index 0311ffd6f8b..c3a8dc16255 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol @@ -25,6 +25,7 @@ contract CapabilitiesRegistry_RemoveDONsTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: capabilityIds }); @@ -35,6 +36,7 @@ contract CapabilitiesRegistry_RemoveDONsTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: nodeTwoCapabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol index 08646600a67..c9f5e61b4f4 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +import {INodeInfoProvider} from "../interfaces/INodeInfoProvider.sol"; contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { function setUp() public override { @@ -24,6 +25,7 @@ contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -31,6 +33,7 @@ contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); @@ -38,6 +41,7 @@ contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, hashedCapabilityIds: hashedCapabilityIds }); @@ -60,7 +64,7 @@ contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = INVALID_P2P_ID; - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); + vm.expectRevert(abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, INVALID_P2P_ID)); s_CapabilitiesRegistry.removeNodes(nodes); } @@ -69,7 +73,7 @@ contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = bytes32(""); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); + vm.expectRevert(abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, bytes32(""))); s_CapabilitiesRegistry.removeNodes(nodes); } @@ -205,6 +209,7 @@ contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol index 00ce88f54f0..52ac0c15c73 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol @@ -5,6 +5,6 @@ import {BaseTest} from "./BaseTest.t.sol"; contract CapabilitiesRegistry_TypeAndVersionTest is BaseTest { function test_TypeAndVersion() public view { - assertEq(s_CapabilitiesRegistry.typeAndVersion(), "CapabilitiesRegistry 1.0.0"); + assertEq(s_CapabilitiesRegistry.typeAndVersion(), "CapabilitiesRegistry 1.0.1"); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol index 825524ebe86..52b496de2d0 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol @@ -25,6 +25,7 @@ contract CapabilitiesRegistry_UpdateDONTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: capabilityIds }); @@ -35,6 +36,7 @@ contract CapabilitiesRegistry_UpdateDONTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: nodeTwoCapabilityIds }); @@ -42,6 +44,7 @@ contract CapabilitiesRegistry_UpdateDONTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, hashedCapabilityIds: capabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol index 9b516767f27..d872bdf68c0 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +import {INodeInfoProvider} from "../interfaces/INodeInfoProvider.sol"; contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { function setUp() public override { @@ -24,6 +25,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -34,6 +36,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); @@ -52,6 +55,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); @@ -70,6 +74,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID, signer: NEW_NODE_SIGNER, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); @@ -88,10 +93,11 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: INVALID_P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); + vm.expectRevert(abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, INVALID_P2P_ID)); s_CapabilitiesRegistry.updateNodes(nodes); } @@ -106,10 +112,11 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: bytes32(""), signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); + vm.expectRevert(abi.encodeWithSelector(INodeInfoProvider.NodeDoesNotExist.selector, bytes32(""))); s_CapabilitiesRegistry.updateNodes(nodes); } @@ -124,6 +131,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: bytes32(""), + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -131,6 +139,25 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { s_CapabilitiesRegistry.updateNodes(nodes); } + function test_RevertWhen_EncryptionPublicKeyEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: bytes32(""), + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); + s_CapabilitiesRegistry.updateNodes(nodes); + } + function test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); @@ -142,6 +169,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); @@ -159,6 +187,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -177,6 +206,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -206,6 +236,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); uint32 workflowDonId = 1; @@ -246,6 +277,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); uint32 capabilitiesDonId = 1; @@ -276,6 +308,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: bytes32(abi.encodePacked(address(6666))), + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -287,6 +320,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, hashedCapabilityIds: hashedCapabilityIds }); s_CapabilitiesRegistry.updateNodes(nodes); @@ -306,6 +340,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NEW_NODE_SIGNER, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -333,6 +368,7 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NEW_NODE_SIGNER, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol index a540a255725..a0501a98fb0 100644 --- a/contracts/src/v0.8/keystone/test/Constants.t.sol +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -10,18 +10,21 @@ contract Constants { string internal constant NODE_OPERATOR_ONE_NAME = "node-operator-one"; bytes32 internal constant NODE_OPERATOR_ONE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(3333))); bytes32 internal constant P2P_ID = hex"e42415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; + bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY = bytes32("test-encryption-public-key"); uint32 internal constant TEST_NODE_OPERATOR_TWO_ID = 2; address internal constant NODE_OPERATOR_TWO_ADMIN = address(4); string internal constant NODE_OPERATOR_TWO_NAME = "node-operator-two"; bytes32 internal constant NODE_OPERATOR_TWO_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(4444))); bytes32 internal constant P2P_ID_TWO = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; + bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY_TWO = bytes32("test-encryption-public-key-2"); uint32 internal constant TEST_NODE_OPERATOR_THREE_ID = 3; address internal constant NODE_OPERATOR_THREE = address(4); string internal constant NODE_OPERATOR_THREE_NAME = "node-operator-three"; bytes32 internal constant NODE_OPERATOR_THREE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(5555))); bytes32 internal constant P2P_ID_THREE = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a06"; + bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY_THREE = bytes32("test-encryption-public-key-3"); uint8 internal constant F_VALUE = 1; uint32 internal constant DON_ID = 1; diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol index c106c2b2b21..0dd480a4282 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol @@ -32,7 +32,7 @@ contract BaseTest is Test { uint256 seed = 0; - for (uint256 i; i < MAX_ORACLES; i++) { + for (uint256 i; i < MAX_ORACLES; ++i) { uint256 mockPK = seed + i + 1; s_signers[i].mockPrivateKey = mockPK; s_signers[i].signerAddress = vm.addr(mockPK); @@ -41,7 +41,7 @@ contract BaseTest is Test { function _getSignerAddresses() internal view returns (address[] memory) { address[] memory signerAddrs = new address[](s_signers.length); - for (uint256 i = 0; i < signerAddrs.length; i++) { + for (uint256 i = 0; i < signerAddrs.length; ++i) { signerAddrs[i] = s_signers[i].signerAddress; } return signerAddrs; @@ -49,7 +49,7 @@ contract BaseTest is Test { function _getSignerAddresses(uint256 limit) internal view returns (address[] memory) { address[] memory signerAddrs = new address[](limit); - for (uint256 i = 0; i < limit; i++) { + for (uint256 i = 0; i < limit; ++i) { signerAddrs[i] = s_signers[i].signerAddress; } return signerAddrs; @@ -61,7 +61,7 @@ contract BaseTest is Test { uint256 requiredSignatures ) internal view returns (bytes[] memory signatures) { signatures = new bytes[](requiredSignatures); - for (uint256 i = 0; i < requiredSignatures; i++) { + for (uint256 i = 0; i < requiredSignatures; ++i) { (uint8 v, bytes32 r, bytes32 s) = vm.sign( s_signers[i].mockPrivateKey, keccak256(abi.encodePacked(keccak256(report), reportContext)) diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol index 5363d87e92b..c6dc7fca538 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.24; import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; import {IRouter} from "../interfaces/IRouter.sol"; +import {MaliciousReportReceiver} from "./mocks/MaliciousReportReceiver.sol"; +import {MaliciousRevertingReceiver} from "./mocks/MaliciousRevertingReceiver.sol"; import {KeystoneForwarder} from "../KeystoneForwarder.sol"; contract KeystoneForwarder_ReportTest is BaseTest { @@ -164,7 +166,7 @@ contract KeystoneForwarder_ReportTest is BaseTest { function test_RevertWhen_AttemptingTransmissionWithInsufficientGas() public { bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); vm.expectRevert(abi.encodeWithSelector(IRouter.InsufficientGasForRouting.selector, transmissionId)); - s_forwarder.report{gas: 50_000}(address(s_receiver), report, reportContext, signatures); + s_forwarder.report{gas: 150_000}(address(s_receiver), report, reportContext, signatures); } function test_Report_SuccessfulDelivery() public { @@ -236,6 +238,38 @@ contract KeystoneForwarder_ReportTest is BaseTest { assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.INVALID_RECEIVER), "state mismatch"); } + function test_Report_FailedDeliveryWhenReportReceiverConsumesAllGasAndInterfaceCheckUsesMax() public { + MaliciousRevertingReceiver maliciousReceiver = new MaliciousRevertingReceiver(); + // This should not revert if gas tracking is effective + // It may revert if it fails to reserve sufficient gas for routing + // This POC requires pretty specific initial gas, so that 1/64 of gas passed to `onReport()` is insufficient to store the success + s_forwarder.report{gas: 200_000}(address(maliciousReceiver), report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( + address(maliciousReceiver), + executionId, + reportId + ); + + assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); + } + + function test_Report_FailedDelieryWhenReportReceiverConsumesAllGas() public { + MaliciousReportReceiver s_maliciousReceiver = new MaliciousReportReceiver(); + s_forwarder.report{gas: 500_000}(address(s_maliciousReceiver), report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( + address(s_maliciousReceiver), + executionId, + reportId + ); + + assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.FAILED), "state mismatch"); + assertGt(transmissionInfo.gasLimit, 410_000, "gas limit mismatch"); + } + function test_Report_ConfigVersion() public { vm.stopPrank(); // configure a new configVersion diff --git a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol index c2a916c87e8..105c89006f0 100644 --- a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol +++ b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -2,9 +2,9 @@ pragma solidity 0.8.24; import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; -import {ERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -contract CapabilityConfigurationContract is ICapabilityConfiguration, ERC165 { +contract CapabilityConfigurationContract is ICapabilityConfiguration, IERC165 { mapping(uint256 => bytes) private s_donConfiguration; function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration) { @@ -17,7 +17,7 @@ contract CapabilityConfigurationContract is ICapabilityConfiguration, ERC165 { s_donConfiguration[donId] = config; } - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return interfaceId == this.getCapabilityConfiguration.selector ^ this.beforeCapabilityConfigSet.selector; + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol index 72c2e23efeb..9325014322c 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol @@ -3,17 +3,17 @@ pragma solidity 0.8.24; import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; import {CapabilitiesRegistry} from "../../CapabilitiesRegistry.sol"; -import {ERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {Constants} from "../Constants.t.sol"; -contract MaliciousConfigurationContract is ICapabilityConfiguration, ERC165, Constants { +contract MaliciousConfigurationContract is ICapabilityConfiguration, IERC165, Constants { bytes32 internal s_capabilityWithConfigurationContractId; constructor(bytes32 capabilityWithConfigContractId) { s_capabilityWithConfigurationContractId = capabilityWithConfigContractId; } - function getCapabilityConfiguration(uint32) external view returns (bytes memory configuration) { + function getCapabilityConfiguration(uint32) external pure returns (bytes memory configuration) { return bytes(""); } @@ -28,6 +28,7 @@ contract MaliciousConfigurationContract is ICapabilityConfiguration, ERC165, Con nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); @@ -35,13 +36,14 @@ contract MaliciousConfigurationContract is ICapabilityConfiguration, ERC165, Con nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, hashedCapabilityIds: hashedCapabilityIds }); CapabilitiesRegistry(msg.sender).updateNodes(nodes); } - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return interfaceId == this.getCapabilityConfiguration.selector ^ this.beforeCapabilityConfigSet.selector; + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol new file mode 100644 index 00000000000..8f039b5f0ce --- /dev/null +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IReceiver} from "../../interfaces/IReceiver.sol"; + +contract MaliciousReportReceiver is IReceiver, IERC165 { + event MessageReceived(bytes metadata, bytes[] mercuryReports); + bytes public latestReport; + + function onReport(bytes calldata metadata, bytes calldata rawReport) external { + // Exhaust all gas that was provided + for (uint256 i = 0; i < 1_000_000_000; ++i) { + bytes[] memory mercuryReports = abi.decode(rawReport, (bytes[])); + latestReport = rawReport; + emit MessageReceived(metadata, mercuryReports); + } + } + + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol new file mode 100644 index 00000000000..f45e95afb2c --- /dev/null +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IReceiver} from "../../interfaces/IReceiver.sol"; + +/// A malicious receiver that uses max allowed for ERC165 checks and consumes all gas in `onReport()` +/// Causes parent Forwarder contract to revert if it doesn't handle gas tracking accurately +contract MaliciousRevertingReceiver is IReceiver, IERC165 { + function onReport(bytes calldata, bytes calldata) external view override { + // consumes about 63/64 of all gas available + uint256 targetGasRemaining = 200; + for (uint256 i = 0; gasleft() > targetGasRemaining; ++i) {} + } + + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + // Consume up to the maximum amount of gas that can be consumed in this check + for (uint256 i = 0; i < 500; ++i) {} + + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol index 3c1f157bc4d..d4005950ade 100644 --- a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol @@ -18,7 +18,7 @@ contract Receiver is IReceiver, IERC165 { emit MessageReceived(metadata, mercuryReports); } - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return interfaceId == this.onReport.selector; + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol index 5dc73619afc..859c6f0e7f3 100644 --- a/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {CrossDomainOwnable} from "./CrossDomainOwnable.sol"; -import {DelegateForwarderInterface} from "./interfaces/DelegateForwarderInterface.sol"; +import {IDelegateForwarder} from "./interfaces/IDelegateForwarder.sol"; /** * @title CrossDomainDelegateForwarder - L1 xDomain account representation (with delegatecall support) @@ -10,4 +10,4 @@ import {DelegateForwarderInterface} from "./interfaces/DelegateForwarderInterfac * @dev Any other L2 contract which uses this contract's address as a privileged position, * can consider that position to be held by the `l1Owner` */ -abstract contract CrossDomainDelegateForwarder is DelegateForwarderInterface, CrossDomainOwnable {} +abstract contract CrossDomainDelegateForwarder is IDelegateForwarder, CrossDomainOwnable {} diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol index 8f218f66b80..c097057f8a7 100644 --- a/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {CrossDomainOwnable} from "./CrossDomainOwnable.sol"; -import {ForwarderInterface} from "./interfaces/ForwarderInterface.sol"; +import {IForwarder} from "./interfaces/IForwarder.sol"; /** * @title CrossDomainForwarder - L1 xDomain account representation @@ -10,4 +10,4 @@ import {ForwarderInterface} from "./interfaces/ForwarderInterface.sol"; * @dev Any other L2 contract which uses this contract's address as a privileged position, * can consider that position to be held by the `l1Owner` */ -abstract contract CrossDomainForwarder is ForwarderInterface, CrossDomainOwnable {} +abstract contract CrossDomainForwarder is IForwarder, CrossDomainOwnable {} diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol index f861da32a7c..c85762b6fca 100644 --- a/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol +++ b/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.0; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {CrossDomainOwnableInterface} from "./interfaces/CrossDomainOwnableInterface.sol"; +import {ICrossDomainOwnable} from "./interfaces/ICrossDomainOwnable.sol"; /** * @title The CrossDomainOwnable contract * @notice A contract with helpers for cross-domain contract ownership. */ -contract CrossDomainOwnable is CrossDomainOwnableInterface, ConfirmedOwner { +contract CrossDomainOwnable is ICrossDomainOwnable, ConfirmedOwner { address internal s_l1Owner; address internal s_l1PendingOwner; diff --git a/contracts/src/v0.8/l2ep/dev/Flags.sol b/contracts/src/v0.8/l2ep/dev/Flags.sol index 0fcd095ac8e..2dc030d7d59 100644 --- a/contracts/src/v0.8/l2ep/dev/Flags.sol +++ b/contracts/src/v0.8/l2ep/dev/Flags.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; +pragma solidity ^0.8.24; import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; /* dev dependencies - to be re/moved after audit */ -import {FlagsInterface} from "./interfaces/FlagsInterface.sol"; +import {IFlags} from "./interfaces/IFlags.sol"; /** * @title The Flags contract @@ -18,7 +18,7 @@ import {FlagsInterface} from "./interfaces/FlagsInterface.sol"; * FlagOn events you should filter for addresses you care about. */ // solhint-disable gas-custom-errors -contract Flags is ITypeAndVersion, FlagsInterface, SimpleReadAccessController { +contract Flags is ITypeAndVersion, IFlags, SimpleReadAccessController { AccessControllerInterface public raisingAccessController; AccessControllerInterface public loweringAccessController; diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol index 158ffcc3042..0db657ee71c 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.24; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import -import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; @@ -17,7 +17,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut * @dev Any other L2 contract which uses this contract's address as a privileged position, * can be considered to be owned by the `l1Owner` */ -contract ArbitrumCrossDomainForwarder is TypeAndVersionInterface, CrossDomainForwarder { +contract ArbitrumCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { /** * @notice creates a new Arbitrum xDomain Forwarder contract * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn @@ -31,7 +31,7 @@ contract ArbitrumCrossDomainForwarder is TypeAndVersionInterface, CrossDomainFor * - ArbitrumCrossDomainForwarder 0.1.0: initial release * - ArbitrumCrossDomainForwarder 1.0.0: Use OZ Address, CrossDomainOwnable * - * @inheritdoc TypeAndVersionInterface + * @inheritdoc ITypeAndVersion */ function typeAndVersion() external pure virtual override returns (string memory) { return "ArbitrumCrossDomainForwarder 1.0.0"; @@ -46,7 +46,7 @@ contract ArbitrumCrossDomainForwarder is TypeAndVersionInterface, CrossDomainFor /** * @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address - * @inheritdoc ForwarderInterface + * @inheritdoc IForwarder */ function forward(address target, bytes memory data) external virtual override onlyL1Owner { Address.functionCall(target, data, "Forwarder call reverted"); diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol index ebf579b8494..60d9cc52666 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.0; // solhint-disable-next-line no-unused-import -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import -import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; -import {DelegateForwarderInterface} from "../interfaces/DelegateForwarderInterface.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; +import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; import {ArbitrumCrossDomainForwarder} from "./ArbitrumCrossDomainForwarder.sol"; @@ -17,7 +17,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut * @dev Any other L2 contract which uses this contract's address as a privileged position, * can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` */ -contract ArbitrumCrossDomainGovernor is DelegateForwarderInterface, ArbitrumCrossDomainForwarder { +contract ArbitrumCrossDomainGovernor is IDelegateForwarder, ArbitrumCrossDomainForwarder { /** * @notice creates a new Arbitrum xDomain Forwarder contract * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn @@ -30,7 +30,7 @@ contract ArbitrumCrossDomainGovernor is DelegateForwarderInterface, ArbitrumCros * * - ArbitrumCrossDomainGovernor 1.0.0: initial release * - * @inheritdoc TypeAndVersionInterface + * @inheritdoc ITypeAndVersion */ function typeAndVersion() external pure virtual override returns (string memory) { return "ArbitrumCrossDomainGovernor 1.0.0"; @@ -38,7 +38,7 @@ contract ArbitrumCrossDomainGovernor is DelegateForwarderInterface, ArbitrumCros /** * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc ForwarderInterface + * @inheritdoc IForwarder */ function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { Address.functionCall(target, data, "Governor call reverted"); @@ -46,7 +46,7 @@ contract ArbitrumCrossDomainGovernor is DelegateForwarderInterface, ArbitrumCros /** * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc DelegateForwarderInterface + * @inheritdoc IDelegateForwarder */ function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol index 63952ab7ba6..678bef3a853 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; +pragma solidity ^0.8.24; import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {FlagsInterface} from "../interfaces/FlagsInterface.sol"; -import {ArbitrumSequencerUptimeFeedInterface} from "../interfaces/ArbitrumSequencerUptimeFeedInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IFlags} from "../interfaces/IFlags.sol"; +import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; /** @@ -18,8 +18,8 @@ import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAcces */ contract ArbitrumSequencerUptimeFeed is AggregatorV2V3Interface, - ArbitrumSequencerUptimeFeedInterface, - TypeAndVersionInterface, + ISequencerUptimeFeed, + ITypeAndVersion, SimpleReadAccessController { /// @dev Round info (for uptime history) @@ -62,7 +62,7 @@ contract ArbitrumSequencerUptimeFeed is /// @dev Flags contract to raise/lower flags on, during status transitions // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - FlagsInterface public immutable FLAGS; + IFlags public immutable FLAGS; /// @dev L1 address address private s_l1Sender; /// @dev s_latestRoundId == 0 means this contract is uninitialized. @@ -76,7 +76,7 @@ contract ArbitrumSequencerUptimeFeed is constructor(address flagsAddress, address l1SenderAddress) { _setL1Sender(l1SenderAddress); - FLAGS = FlagsInterface(flagsAddress); + FLAGS = IFlags(flagsAddress); } /** @@ -120,7 +120,7 @@ contract ArbitrumSequencerUptimeFeed is * * - ArbitrumSequencerUptimeFeed 1.0.0: initial release * - * @inheritdoc TypeAndVersionInterface + * @inheritdoc ITypeAndVersion */ function typeAndVersion() external pure virtual override returns (string memory) { return "ArbitrumSequencerUptimeFeed 1.0.0"; diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol index edcb62cae90..05f9349eb62 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.24; import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; /* ./dev dependencies - to be moved from ./dev after audit */ -import {ArbitrumSequencerUptimeFeedInterface} from "../interfaces/ArbitrumSequencerUptimeFeedInterface.sol"; +import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; import {IArbitrumDelayedInbox} from "../interfaces/IArbitrumDelayedInbox.sol"; import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; @@ -20,7 +20,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut * - Gas configuration is controlled by a configurable external SimpleWriteAccessController * - Funds on the contract are managed by the owner */ -contract ArbitrumValidator is TypeAndVersionInterface, AggregatorValidatorInterface, SimpleWriteAccessController { +contract ArbitrumValidator is ITypeAndVersion, AggregatorValidatorInterface, SimpleWriteAccessController { enum PaymentStrategy { L1, L2 @@ -124,7 +124,7 @@ contract ArbitrumValidator is TypeAndVersionInterface, AggregatorValidatorInterf * - ArbitrumValidator 2.0.0: change how maxSubmissionCost is calculated when sending cross chain messages * - now calls `calculateRetryableSubmissionFee` instead of inlining equation to estimate * the maxSubmissionCost required to send the message to L2 - * @inheritdoc TypeAndVersionInterface + * @inheritdoc ITypeAndVersion */ function typeAndVersion() external pure virtual override returns (string memory) { return "ArbitrumValidator 2.0.0"; @@ -264,7 +264,7 @@ contract ArbitrumValidator is TypeAndVersionInterface, AggregatorValidatorInterf // Excess gas on L2 will be sent to the L2 xDomain alias address of this contract address refundAddr = L2_ALIAS; // Encode the ArbitrumSequencerUptimeFeed call - bytes4 selector = ArbitrumSequencerUptimeFeedInterface.updateStatus.selector; + bytes4 selector = ISequencerUptimeFeed.updateStatus.selector; bool status = currentAnswer == ANSWER_SEQ_OFFLINE; uint64 timestamp = uint64(block.timestamp); // Encode `status` and `timestamp` diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/DelegateForwarderInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/DelegateForwarderInterface.sol deleted file mode 100644 index 498dee586c8..00000000000 --- a/contracts/src/v0.8/l2ep/dev/interfaces/DelegateForwarderInterface.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title DelegateForwarderInterface - forwards a delegatecall to a target, under some conditions -// solhint-disable-next-line interface-starts-with-i -interface DelegateForwarderInterface { - /** - * @notice forward delegatecalls the `target` with `data` - * @param target contract address to be delegatecalled - * @param data to send to target contract - */ - function forwardDelegate(address target, bytes memory data) external; -} diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/ForwarderInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ForwarderInterface.sol deleted file mode 100644 index a6db32b9231..00000000000 --- a/contracts/src/v0.8/l2ep/dev/interfaces/ForwarderInterface.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title ForwarderInterface - forwards a call to a target, under some conditions -// solhint-disable-next-line interface-starts-with-i -interface ForwarderInterface { - /** - * @notice forward calls the `target` with `data` - * @param target contract address to be called - * @param data to send to target contract - */ - function forward(address target, bytes memory data) external; -} diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/CrossDomainOwnableInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol similarity index 65% rename from contracts/src/v0.8/l2ep/dev/interfaces/CrossDomainOwnableInterface.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol index ddcfded9ca2..d5a01386e3c 100644 --- a/contracts/src/v0.8/l2ep/dev/interfaces/CrossDomainOwnableInterface.sol +++ b/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -/// @title CrossDomainOwnableInterface - A contract with helpers for cross-domain contract ownership -// solhint-disable-next-line interface-starts-with-i -interface CrossDomainOwnableInterface { +/// @title A contract with helpers for cross-domain contract ownership +interface ICrossDomainOwnable { event L1OwnershipTransferRequested(address indexed from, address indexed to); event L1OwnershipTransferred(address indexed from, address indexed to); diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol new file mode 100644 index 00000000000..3df532b94c5 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title Forwards a delegatecall to a target, under some conditions +interface IDelegateForwarder { + /// @notice forward delegatecalls the `target` with `data` + /// @param target contract address to be delegatecalled + /// @param data to send to target contract + function forwardDelegate(address target, bytes memory data) external; +} diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/FlagsInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol similarity index 82% rename from contracts/src/v0.8/l2ep/dev/interfaces/FlagsInterface.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol index b6491a9d601..6ae5a3a3f38 100644 --- a/contracts/src/v0.8/l2ep/dev/interfaces/FlagsInterface.sol +++ b/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; +pragma solidity ^0.8.0; -// solhint-disable-next-line interface-starts-with-i -interface FlagsInterface { +interface IFlags { function getFlag(address) external view returns (bool); function getFlags(address[] calldata) external view returns (bool[] memory); diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol new file mode 100644 index 00000000000..374e3810647 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title Forwards a call to a target, under some conditions +interface IForwarder { + /// @notice forward calls the `target` with `data` + /// @param target contract address to be called + /// @param data to send to target contract + function forward(address target, bytes memory data) external; +} diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/ArbitrumSequencerUptimeFeedInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol similarity index 54% rename from contracts/src/v0.8/l2ep/dev/interfaces/ArbitrumSequencerUptimeFeedInterface.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol index 57b507bae8d..879dc06d37e 100644 --- a/contracts/src/v0.8/l2ep/dev/interfaces/ArbitrumSequencerUptimeFeedInterface.sol +++ b/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -// solhint-disable-next-line interface-starts-with-i -interface ArbitrumSequencerUptimeFeedInterface { +interface ISequencerUptimeFeed { function updateStatus(bool status, uint64 timestamp) external; } diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/OptimismSequencerUptimeFeedInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/OptimismSequencerUptimeFeedInterface.sol deleted file mode 100644 index a08a1b26204..00000000000 --- a/contracts/src/v0.8/l2ep/dev/interfaces/OptimismSequencerUptimeFeedInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface OptimismSequencerUptimeFeedInterface { - function updateStatus(bool status, uint64 timestamp) external; -} diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol deleted file mode 100644 index 89327fbc3a1..00000000000 --- a/contracts/src/v0.8/l2ep/dev/interfaces/ScrollSequencerUptimeFeedInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -// solhint-disable-next-line interface-starts-with-i -interface ScrollSequencerUptimeFeedInterface { - function updateStatus(bool status, uint64 timestamp) external; -} diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol index 37d9260b47b..1d037886960 100644 --- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.24; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import -import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; /* ./dev dependencies - to be moved from ./dev after audit */ import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; @@ -18,7 +18,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut * @dev Any other L2 contract which uses this contract's address as a privileged position, * can be considered to be owned by the `l1Owner` */ -contract OptimismCrossDomainForwarder is TypeAndVersionInterface, CrossDomainForwarder { +contract OptimismCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { // OVM_L2CrossDomainMessenger is a precompile usually deployed to 0x4200000000000000000000000000000000000007 // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i iOVM_CrossDomainMessenger private immutable OVM_CROSS_DOMAIN_MESSENGER; @@ -40,7 +40,7 @@ contract OptimismCrossDomainForwarder is TypeAndVersionInterface, CrossDomainFor * - OptimismCrossDomainForwarder 0.1.0: initial release * - OptimismCrossDomainForwarder 1.0.0: Use OZ Address, CrossDomainOwnable * - * @inheritdoc TypeAndVersionInterface + * @inheritdoc ITypeAndVersion */ function typeAndVersion() external pure virtual override returns (string memory) { return "OptimismCrossDomainForwarder 1.0.0"; @@ -48,7 +48,7 @@ contract OptimismCrossDomainForwarder is TypeAndVersionInterface, CrossDomainFor /** * @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address - * @inheritdoc ForwarderInterface + * @inheritdoc IForwarder */ function forward(address target, bytes memory data) external virtual override onlyL1Owner { Address.functionCall(target, data, "Forwarder call reverted"); diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol index ad780946911..6a41bd98f03 100644 --- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.24; -import {DelegateForwarderInterface} from "../interfaces/DelegateForwarderInterface.sol"; +import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; // solhint-disable-next-line no-unused-import -import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; import {OptimismCrossDomainForwarder} from "./OptimismCrossDomainForwarder.sol"; @@ -16,7 +16,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut * @dev Any other L2 contract which uses this contract's address as a privileged position, * can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` */ -contract OptimismCrossDomainGovernor is DelegateForwarderInterface, OptimismCrossDomainForwarder { +contract OptimismCrossDomainGovernor is IDelegateForwarder, OptimismCrossDomainForwarder { /** * @notice creates a new Optimism xDomain Forwarder contract * @param crossDomainMessengerAddr the xDomain bridge messenger (Optimism bridge L2) contract address @@ -39,7 +39,7 @@ contract OptimismCrossDomainGovernor is DelegateForwarderInterface, OptimismCros /** * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc ForwarderInterface + * @inheritdoc IForwarder */ function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { Address.functionCall(target, data, "Governor call reverted"); @@ -47,7 +47,7 @@ contract OptimismCrossDomainGovernor is DelegateForwarderInterface, OptimismCros /** * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc DelegateForwarderInterface + * @inheritdoc IDelegateForwarder */ function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol index 947b1b0bf5d..0e6f9c52f22 100644 --- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol @@ -1,12 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; +pragma solidity ^0.8.19; + +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; -import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {OptimismSequencerUptimeFeedInterface} from "./../interfaces/OptimismSequencerUptimeFeedInterface.sol"; -import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; /** @@ -14,50 +10,8 @@ import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2C * @notice L2 contract that receives status updates from a specific L1 address, * records a new answer if the status changed */ -contract OptimismSequencerUptimeFeed is - AggregatorV2V3Interface, - OptimismSequencerUptimeFeedInterface, - TypeAndVersionInterface, - SimpleReadAccessController -{ - /// @dev Round info (for uptime history) - struct Round { - bool status; - uint64 startedAt; - uint64 updatedAt; - } - - /// @dev Packed state struct to save sloads - struct FeedState { - uint80 latestRoundId; - bool latestStatus; - uint64 startedAt; - uint64 updatedAt; - } - - /// @notice Sender is not the L2 messenger - error InvalidSender(); - /// @notice Replacement for AggregatorV3Interface "No data present" - error NoDataPresent(); - - event L1SenderTransferred(address indexed from, address indexed to); - /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - /// @dev Emitted when a updateStatus is called without the status changing - event RoundUpdated(int256 status, uint64 updatedAt); - - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint8 public constant override decimals = 0; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override description = "L2 Sequencer Uptime Status Feed"; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint256 public constant override version = 1; - - /// @dev L1 address - address private s_l1Sender; - /// @dev s_latestRoundId == 0 means this contract is uninitialized. - FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, startedAt: 0, updatedAt: 0}); - mapping(uint80 => Round) private s_rounds; +contract OptimismSequencerUptimeFeed is BaseSequencerUptimeFeed { + string public constant override typeAndVersion = "OptimismSequencerUptimeFeed 1.1.0-dev"; // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i IL2CrossDomainMessenger private immutable s_l2CrossDomainMessenger; @@ -67,202 +21,19 @@ contract OptimismSequencerUptimeFeed is * @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract * @param initialStatus The initial status of the feed */ - constructor(address l1SenderAddress, address l2CrossDomainMessengerAddr, bool initialStatus) { - _setL1Sender(l1SenderAddress); + constructor( + address l1SenderAddress, + address l2CrossDomainMessengerAddr, + bool initialStatus + ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { s_l2CrossDomainMessenger = IL2CrossDomainMessenger(l2CrossDomainMessengerAddr); - uint64 timestamp = uint64(block.timestamp); - - // Initialise roundId == 1 as the first round - _recordRound(1, initialStatus, timestamp); - } - - /** - * @notice Check if a roundId is valid in this current contract state - * @dev Mainly used for AggregatorV2V3Interface functions - * @param roundId Round ID to check - */ - function _isValidRound(uint256 roundId) private view returns (bool) { - return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; - } - - /** - * @notice versions: - * - * - OptimismSequencerUptimeFeed 1.0.0: initial release - * - * @inheritdoc TypeAndVersionInterface - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "OptimismSequencerUptimeFeed 1.0.0"; - } - - /// @return L1 sender address - function l1Sender() public view virtual returns (address) { - return s_l1Sender; - } - - /** - * @notice Set the allowed L1 sender for this contract to a new L1 sender - * @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. - * @param to new L1 sender that will be allowed to call `updateStatus` on this contract - */ - function transferL1Sender(address to) external virtual onlyOwner { - _setL1Sender(to); - } - - /// @notice internal method that stores the L1 sender - function _setL1Sender(address to) private { - address from = s_l1Sender; - if (from != to) { - s_l1Sender = to; - emit L1SenderTransferred(from, to); - } - } - - /** - * @dev Returns an AggregatorV2V3Interface compatible answer from status flag - * - * @param status The status flag to convert to an aggregator-compatible answer - */ - function _getStatusAnswer(bool status) private pure returns (int256) { - return status ? int256(1) : int256(0); - } - - /** - * @notice Helper function to record a round and set the latest feed state. - * - * @param roundId The round ID to record - * @param status Sequencer status - * @param timestamp The L1 block timestamp of status update - */ - function _recordRound(uint80 roundId, bool status, uint64 timestamp) private { - uint64 updatedAt = uint64(block.timestamp); - Round memory nextRound = Round(status, timestamp, updatedAt); - FeedState memory feedState = FeedState(roundId, status, timestamp, updatedAt); - - s_rounds[roundId] = nextRound; - s_feedState = feedState; - - emit NewRound(roundId, msg.sender, timestamp); - emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); } - /** - * @notice Helper function to update when a round was last updated - * - * @param roundId The round ID to update - * @param status Sequencer status - */ - function _updateRound(uint80 roundId, bool status) private { - uint64 updatedAt = uint64(block.timestamp); - s_rounds[roundId].updatedAt = updatedAt; - s_feedState.updatedAt = updatedAt; - emit RoundUpdated(_getStatusAnswer(status), updatedAt); - } - - /** - * @notice Record a new status and timestamp if it has changed since the last round. - * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. - * - * @param status Sequencer status - * @param timestamp Block timestamp of status update - */ - function updateStatus(bool status, uint64 timestamp) external override { - FeedState memory feedState = s_feedState; + function _validateSender(address l1Sender) internal view override { if ( - msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != s_l1Sender + msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != l1Sender ) { revert InvalidSender(); } - - // Ignore if latest recorded timestamp is newer - if (feedState.startedAt > timestamp) { - emit UpdateIgnored(feedState.latestStatus, feedState.startedAt, status, timestamp); - return; - } - - if (feedState.latestStatus == status) { - _updateRound(feedState.latestRoundId, status); - } else { - feedState.latestRoundId += 1; - _recordRound(feedState.latestRoundId, status, timestamp); - } - } - - /// @inheritdoc AggregatorInterface - function latestAnswer() external view override checkAccess returns (int256) { - FeedState memory feedState = s_feedState; - return _getStatusAnswer(feedState.latestStatus); - } - - /// @inheritdoc AggregatorInterface - function latestTimestamp() external view override checkAccess returns (uint256) { - FeedState memory feedState = s_feedState; - return feedState.startedAt; - } - - /// @inheritdoc AggregatorInterface - function latestRound() external view override checkAccess returns (uint256) { - FeedState memory feedState = s_feedState; - return feedState.latestRoundId; - } - - /// @inheritdoc AggregatorInterface - function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { - if (_isValidRound(roundId)) { - return _getStatusAnswer(s_rounds[uint80(roundId)].status); - } - - revert NoDataPresent(); - } - - /// @inheritdoc AggregatorInterface - function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { - if (_isValidRound(roundId)) { - return s_rounds[uint80(roundId)].startedAt; - } - - revert NoDataPresent(); - } - - /// @inheritdoc AggregatorV3Interface - function getRoundData( - uint80 _roundId - ) - public - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - if (_isValidRound(_roundId)) { - Round memory round = s_rounds[_roundId]; - answer = _getStatusAnswer(round.status); - startedAt = uint256(round.startedAt); - roundId = _roundId; - updatedAt = uint256(round.updatedAt); - answeredInRound = roundId; - } else { - revert NoDataPresent(); - } - return (roundId, answer, startedAt, updatedAt, answeredInRound); - } - - /// @inheritdoc AggregatorV3Interface - function latestRoundData() - external - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - FeedState memory feedState = s_feedState; - - roundId = feedState.latestRoundId; - answer = _getStatusAnswer(feedState.latestStatus); - startedAt = feedState.startedAt; - updatedAt = feedState.updatedAt; - answeredInRound = roundId; - return (roundId, answer, startedAt, updatedAt, answeredInRound); } } diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol index a54a56ee604..cf5222f017e 100644 --- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol @@ -1,82 +1,28 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.19; -import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {OptimismSequencerUptimeFeedInterface} from "./../interfaces/OptimismSequencerUptimeFeedInterface.sol"; +import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; +import {BaseValidator} from "../shared/BaseValidator.sol"; import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; -/** - * @title OptimismValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 - */ -contract OptimismValidator is TypeAndVersionInterface, AggregatorValidatorInterface, SimpleWriteAccessController { - int256 private constant ANSWER_SEQ_OFFLINE = 1; - uint32 private s_gasLimit; - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L1_CROSS_DOMAIN_MESSENGER_ADDRESS; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L2_UPTIME_FEED_ADDR; - - /** - * @notice emitted when gas cost to spend on L2 is updated - * @param gasLimit updated gas cost - */ - event GasLimitUpdated(uint32 gasLimit); - - /** - * @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address - * @param l2UptimeFeedAddr the address of the OptimismSequencerUptimeFeed contract address - * @param gasLimit the gasLimit to use for sending a message from L1 to L2 - */ - constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { - // solhint-disable-next-line gas-custom-errors - require(l1CrossDomainMessengerAddress != address(0), "Invalid xDomain Messenger address"); - // solhint-disable-next-line gas-custom-errors - require(l2UptimeFeedAddr != address(0), "Invalid OptimismSequencerUptimeFeed contract address"); - L1_CROSS_DOMAIN_MESSENGER_ADDRESS = l1CrossDomainMessengerAddress; - L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr; - s_gasLimit = gasLimit; - } - - /** - * @notice versions: - * - * - OptimismValidator 0.1.0: initial release - * - OptimismValidator 1.0.0: change target of L2 sequencer status update - * - now calls `updateStatus` on an L2 OptimismSequencerUptimeFeed contract instead of - * directly calling the Flags contract - * - * @inheritdoc TypeAndVersionInterface - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "OptimismValidator 1.0.0"; - } - - /** - * @notice sets the new gas cost to spend when sending cross chain message - * @param gasLimit the updated gas cost - */ - function setGasLimit(uint32 gasLimit) external onlyOwner { - s_gasLimit = gasLimit; - emit GasLimitUpdated(gasLimit); - } - - /** - * @notice fetches the gas cost of sending a cross chain message - */ - function getGasLimit() external view returns (uint32) { - return s_gasLimit; - } - - /** - * @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. - * @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. - * @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. - */ +/// @title OptimismValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 +contract OptimismValidator is BaseValidator { + string public constant override typeAndVersion = "OptimismValidator 1.1.0-dev"; + + /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address + /// @param l2UptimeFeedAddr the address of the OptimismSequencerUptimeFeed contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor( + address l1CrossDomainMessengerAddress, + address l2UptimeFeedAddr, + uint32 gasLimit + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {} + + /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. + /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. function validate( uint256 /* previousRoundId */, int256 /* previousAnswer */, @@ -84,7 +30,7 @@ contract OptimismValidator is TypeAndVersionInterface, AggregatorValidatorInterf int256 currentAnswer ) external override checkAccess returns (bool) { // Encode the OptimismSequencerUptimeFeed call - bytes4 selector = OptimismSequencerUptimeFeedInterface.updateStatus.selector; + bytes4 selector = ISequencerUptimeFeed.updateStatus.selector; bool status = currentAnswer == ANSWER_SEQ_OFFLINE; uint64 timestamp = uint64(block.timestamp); // Encode `status` and `timestamp` diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol index 4ec51fc6938..c70bc794afb 100644 --- a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; @@ -14,7 +14,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut /// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. /// @dev Any other L2 contract which uses this contract's address as a privileged position, /// can be considered to be owned by the `l1Owner` -contract ScrollCrossDomainForwarder is TypeAndVersionInterface, CrossDomainForwarder { +contract ScrollCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { string public constant override typeAndVersion = "ScrollCrossDomainForwarder 1.0.0"; address internal immutable i_scrollCrossDomainMessenger; @@ -28,7 +28,7 @@ contract ScrollCrossDomainForwarder is TypeAndVersionInterface, CrossDomainForwa } /// @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address - /// @inheritdoc ForwarderInterface + /// @inheritdoc IForwarder function forward(address target, bytes memory data) external override onlyL1Owner { Address.functionCall(target, data, "Forwarder call reverted"); } diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol index f7d13059fe7..dae621e9b08 100644 --- a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {DelegateForwarderInterface} from "../interfaces/DelegateForwarderInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; // solhint-disable-next-line no-unused-import -import {ForwarderInterface} from "../interfaces/ForwarderInterface.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; @@ -16,7 +16,7 @@ import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/ut /// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. /// @dev Any other L2 contract which uses this contract's address as a privileged position, /// can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` -contract ScrollCrossDomainGovernor is DelegateForwarderInterface, TypeAndVersionInterface, CrossDomainForwarder { +contract ScrollCrossDomainGovernor is IDelegateForwarder, ITypeAndVersion, CrossDomainForwarder { string public constant override typeAndVersion = "ScrollCrossDomainGovernor 1.0.0"; address internal immutable i_scrollCrossDomainMessenger; @@ -29,13 +29,13 @@ contract ScrollCrossDomainGovernor is DelegateForwarderInterface, TypeAndVersion i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); } - /// @inheritdoc ForwarderInterface + /// @inheritdoc IForwarder /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { Address.functionCall(target, data, "Governor call reverted"); } - /// @inheritdoc DelegateForwarderInterface + /// @inheritdoc IDelegateForwarder /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol index e60e8703b77..40f2941aa69 100644 --- a/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol @@ -1,66 +1,16 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; -import {ScrollSequencerUptimeFeedInterface} from "../interfaces/ScrollSequencerUptimeFeedInterface.sol"; -import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; - -import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; /// @title ScrollSequencerUptimeFeed - L2 sequencer uptime status aggregator /// @notice L2 contract that receives status updates, and records a new answer if the status changed -contract ScrollSequencerUptimeFeed is - AggregatorV2V3Interface, - ScrollSequencerUptimeFeedInterface, - TypeAndVersionInterface, - SimpleReadAccessController -{ - string public constant override typeAndVersion = "ScrollSequencerUptimeFeed 1.0.0"; - - /// @dev Round info (for uptime history) - struct Round { - bool status; - uint64 startedAt; - uint64 updatedAt; - } - - /// @dev Packed state struct to save sloads - struct FeedState { - uint80 latestRoundId; - bool latestStatus; - uint64 startedAt; - uint64 updatedAt; - } - - /// @notice Sender is not the L2 messenger - error InvalidSender(); - /// @notice Replacement for AggregatorV3Interface "No data present" - error NoDataPresent(); - /// @notice Address must not be the zero address +contract ScrollSequencerUptimeFeed is BaseSequencerUptimeFeed { error ZeroAddress(); - event L1SenderTransferred(address indexed from, address indexed to); - /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - /// @dev Emitted when a updateStatus is called without the status changing - event RoundUpdated(int256 status, uint64 updatedAt); - - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint8 public constant override decimals = 0; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override description = "L2 Sequencer Uptime Status Feed"; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint256 public constant override version = 1; - - /// @dev L1 address - address private s_l1Sender; - /// @dev s_latestRoundId == 0 means this contract is uninitialized. - FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, startedAt: 0, updatedAt: 0}); - mapping(uint80 roundId => Round round) private s_rounds; + string public constant override typeAndVersion = "ScrollSequencerUptimeFeed 1.1.0-dev"; // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i IL2ScrollMessenger private immutable s_l2CrossDomainMessenger; @@ -68,169 +18,23 @@ contract ScrollSequencerUptimeFeed is /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract /// @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract /// @param initialStatus The initial status of the feed - constructor(address l1SenderAddress, address l2CrossDomainMessengerAddr, bool initialStatus) { + constructor( + address l1SenderAddress, + address l2CrossDomainMessengerAddr, + bool initialStatus + ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { if (l2CrossDomainMessengerAddr == address(0)) { revert ZeroAddress(); } - _setL1Sender(l1SenderAddress); s_l2CrossDomainMessenger = IL2ScrollMessenger(l2CrossDomainMessengerAddr); - - // Initialise roundId == 1 as the first round - _recordRound(1, initialStatus, uint64(block.timestamp)); - } - - /// @notice Check if a roundId is valid in this current contract state - /// @dev Mainly used for AggregatorV2V3Interface functions - /// @param roundId Round ID to check - function _isValidRound(uint256 roundId) private view returns (bool) { - return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; - } - - /// @return L1 sender address - function l1Sender() public view virtual returns (address) { - return s_l1Sender; } - /// @notice Set the allowed L1 sender for this contract to a new L1 sender - /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. - /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract - function transferL1Sender(address to) external virtual onlyOwner { - _setL1Sender(to); - } - - /// @notice internal method that stores the L1 sender - function _setL1Sender(address to) private { - address from = s_l1Sender; - if (from != to) { - s_l1Sender = to; - emit L1SenderTransferred(from, to); - } - } - - /// @dev Returns an AggregatorV2V3Interface compatible answer from status flag - /// @param status The status flag to convert to an aggregator-compatible answer - function _getStatusAnswer(bool status) private pure returns (int256) { - return status ? int256(1) : int256(0); - } - - /// @notice Helper function to record a round and set the latest feed state. - /// @param roundId The round ID to record - /// @param status Sequencer status - /// @param timestamp The L1 block timestamp of status update - function _recordRound(uint80 roundId, bool status, uint64 timestamp) private { - s_feedState = FeedState(roundId, status, timestamp, uint64(block.timestamp)); - s_rounds[roundId] = Round(status, timestamp, uint64(block.timestamp)); - - emit NewRound(roundId, msg.sender, timestamp); - emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); - } - - /// @notice Helper function to update when a round was last updated - /// @param roundId The round ID to update - /// @param status Sequencer status - function _updateRound(uint80 roundId, bool status) private { - s_feedState.updatedAt = uint64(block.timestamp); - s_rounds[roundId].updatedAt = uint64(block.timestamp); - emit RoundUpdated(_getStatusAnswer(status), uint64(block.timestamp)); - } - - /// @notice Record a new status and timestamp if it has changed since the last round. - /// @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. - /// - /// @param status Sequencer status - /// @param timestamp Block timestamp of status update - function updateStatus(bool status, uint64 timestamp) external override { - FeedState memory feedState = s_feedState; - + function _validateSender(address l1Sender) internal view override { if ( - msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != s_l1Sender + msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != l1Sender ) { revert InvalidSender(); } - - // Ignore if latest recorded timestamp is newer - if (feedState.startedAt > timestamp) { - emit UpdateIgnored(feedState.latestStatus, feedState.startedAt, status, timestamp); - return; - } - - if (feedState.latestStatus == status) { - _updateRound(feedState.latestRoundId, status); - } else { - feedState.latestRoundId += 1; - _recordRound(feedState.latestRoundId, status, timestamp); - } - } - - /// @inheritdoc AggregatorInterface - function latestAnswer() external view override checkAccess returns (int256) { - return _getStatusAnswer(s_feedState.latestStatus); - } - - /// @inheritdoc AggregatorInterface - function latestTimestamp() external view override checkAccess returns (uint256) { - return s_feedState.startedAt; - } - - /// @inheritdoc AggregatorInterface - function latestRound() external view override checkAccess returns (uint256) { - return s_feedState.latestRoundId; - } - - /// @inheritdoc AggregatorInterface - function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { - if (!_isValidRound(roundId)) { - revert NoDataPresent(); - } - - return _getStatusAnswer(s_rounds[uint80(roundId)].status); - } - - /// @inheritdoc AggregatorInterface - function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { - if (!_isValidRound(roundId)) { - revert NoDataPresent(); - } - - return s_rounds[uint80(roundId)].startedAt; - } - - /// @inheritdoc AggregatorV3Interface - function getRoundData( - uint80 _roundId - ) - public - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - if (!_isValidRound(_roundId)) { - revert NoDataPresent(); - } - - Round memory round = s_rounds[_roundId]; - - return (_roundId, _getStatusAnswer(round.status), uint256(round.startedAt), uint256(round.updatedAt), _roundId); - } - - /// @inheritdoc AggregatorV3Interface - function latestRoundData() - external - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - FeedState memory feedState = s_feedState; - - return ( - feedState.latestRoundId, - _getStatusAnswer(feedState.latestStatus), - feedState.startedAt, - feedState.updatedAt, - feedState.latestRoundId - ); } } diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol index 9df4a12ac6e..b009c80fdfd 100644 --- a/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol @@ -1,71 +1,31 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; -import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {ScrollSequencerUptimeFeedInterface} from "../interfaces/ScrollSequencerUptimeFeedInterface.sol"; +import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; +import {BaseValidator} from "../shared/BaseValidator.sol"; import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; /// @title ScrollValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 -contract ScrollValidator is TypeAndVersionInterface, AggregatorValidatorInterface, SimpleWriteAccessController { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L1_CROSS_DOMAIN_MESSENGER_ADDRESS; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L2_UPTIME_FEED_ADDR; +contract ScrollValidator is BaseValidator { + string public constant override typeAndVersion = "ScrollValidator 1.1.0-dev"; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i address public immutable L1_MSG_QUEUE_ADDR; - string public constant override typeAndVersion = "ScrollValidator 1.0.0"; - int256 private constant ANSWER_SEQ_OFFLINE = 1; - uint32 private s_gasLimit; - - /// @notice emitted when gas cost to spend on L2 is updated - /// @param gasLimit updated gas cost - event GasLimitUpdated(uint32 gasLimit); - - /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address - /// @param l2UptimeFeedAddr the address of the ScrollSequencerUptimeFeed contract address - /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 constructor( address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, address l1MessageQueueAddr, uint32 gasLimit - ) { - // solhint-disable-next-line gas-custom-errors - require(l1CrossDomainMessengerAddress != address(0), "Invalid xDomain Messenger address"); + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) { // solhint-disable-next-line gas-custom-errors require(l1MessageQueueAddr != address(0), "Invalid L1 message queue address"); - // solhint-disable-next-line gas-custom-errors - require(l2UptimeFeedAddr != address(0), "Invalid ScrollSequencerUptimeFeed contract address"); - L1_CROSS_DOMAIN_MESSENGER_ADDRESS = l1CrossDomainMessengerAddress; - L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr; L1_MSG_QUEUE_ADDR = l1MessageQueueAddr; - s_gasLimit = gasLimit; - } - - /// @notice sets the new gas cost to spend when sending cross chain message - /// @param gasLimit the updated gas cost - function setGasLimit(uint32 gasLimit) external onlyOwner { - s_gasLimit = gasLimit; - emit GasLimitUpdated(gasLimit); } - /// @notice fetches the gas cost of sending a cross chain message - function getGasLimit() external view returns (uint32) { - return s_gasLimit; - } - - /// @notice makes this contract payable - /// @dev receives funds: - /// - to use them (if configured) to pay for L2 execution on L1 - /// - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2) - receive() external payable {} - /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. @@ -82,7 +42,7 @@ contract ScrollValidator is TypeAndVersionInterface, AggregatorValidatorInterfac L2_UPTIME_FEED_ADDR, 0, abi.encodeWithSelector( - ScrollSequencerUptimeFeedInterface.updateStatus.selector, + ISequencerUptimeFeed.updateStatus.selector, currentAnswer == ANSWER_SEQ_OFFLINE, uint64(block.timestamp) ), diff --git a/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol new file mode 100644 index 00000000000..15c20504569 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; + +import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; + +/// @title L2 sequencer uptime status aggregator +/// @notice L2 contract that receives status updates from a specific L1 address, +/// records a new answer if the status changed +abstract contract BaseSequencerUptimeFeed is + ITypeAndVersion, + AggregatorV2V3Interface, + ISequencerUptimeFeed, + SimpleReadAccessController +{ + /// @dev Round info for uptime history + struct Round { + uint64 startedAt; // ─╮ The timestamp at which the round started + uint64 updatedAt; // │ The timestamp at which the round was updated + bool status; // ──────╯ The sequencer status for the round + } + + struct FeedState { + uint80 latestRoundId; // ─╮ The ID of the latest round + uint64 startedAt; // │ The date at which the latest round started + uint64 updatedAt; // │ The date at which the latest round was updated + bool latestStatus; // ────╯ The status of the latest round + } + + /// @notice Sender is not the L2 messenger + error InvalidSender(); + /// @notice Replacement for AggregatorV3Interface "No data present" + error NoDataPresent(); + + event L1SenderTransferred(address indexed from, address indexed to); + /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + /// @dev Emitted when a updateStatus is called without the status changing + event RoundUpdated(int256 status, uint64 updatedAt); + + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint8 public constant override decimals = 0; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override description = "L2 Sequencer Uptime Status Feed"; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint256 public constant override version = 1; + + /// @dev L1 address + address private s_l1Sender; + /// @dev s_latestRoundId == 0 means this contract is uninitialized. + FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, startedAt: 0, updatedAt: 0}); + mapping(uint80 roundId => Round round) private s_rounds; + + /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + /// @param initialStatus The initial status of the feed + constructor(address l1SenderAddress, bool initialStatus) { + // We neet to allow l1SenderAddress to be zero because this contract is deployed first + // After deploying the validator contract, this contract will be updated with the correct L1 sender address + _setL1Sender(l1SenderAddress); + + // Initialise roundId == 1 as the first round + _recordRound(1, initialStatus, uint64(block.timestamp)); + } + + /// @notice Check if a roundId is valid in this current contract state + /// @dev Mainly used for AggregatorV2V3Interface functions + /// @param roundId Round ID to check + function _isValidRound(uint256 roundId) private view returns (bool) { + return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; + } + + /// @return L1 sender address + function l1Sender() public view virtual returns (address) { + return s_l1Sender; + } + + /// @notice Set the allowed L1 sender for this contract to a new L1 sender + /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. + /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract + function transferL1Sender(address to) external virtual onlyOwner { + _setL1Sender(to); + } + + /// @notice internal method that stores the L1 sender + function _setL1Sender(address newSender) internal { + address oldSender = s_l1Sender; + if (oldSender != newSender) { + s_l1Sender = newSender; + emit L1SenderTransferred(oldSender, newSender); + } + } + + /// @dev Returns an AggregatorV2V3Interface compatible answer from status flag + /// @param status The status flag to convert to an aggregator-compatible answer + function _getStatusAnswer(bool status) internal pure returns (int256) { + return status ? int256(1) : int256(0); + } + + /// @notice Helper function to record a round and set the latest feed state. + /// @param roundId The round ID to record + /// @param status Sequencer status + /// @param timestamp The L1 block timestamp of status update + function _recordRound(uint80 roundId, bool status, uint64 timestamp) internal { + s_rounds[roundId] = Round({status: status, startedAt: timestamp, updatedAt: uint64(block.timestamp)}); + s_feedState = FeedState({ + latestRoundId: roundId, + latestStatus: status, + startedAt: timestamp, + updatedAt: uint64(block.timestamp) + }); + + emit NewRound(roundId, msg.sender, timestamp); + emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); + } + + /// @notice Helper function to update when a round was last updated + /// @param roundId The round ID to update + /// @param status Sequencer status + function _updateRound(uint80 roundId, bool status) internal { + s_rounds[roundId].updatedAt = uint64(block.timestamp); + s_feedState.updatedAt = uint64(block.timestamp); + emit RoundUpdated(_getStatusAnswer(status), uint64(block.timestamp)); + } + + function _getFeedState() internal view returns (FeedState memory) { + return s_feedState; + } + + /// @inheritdoc AggregatorInterface + function latestAnswer() external view override checkAccess returns (int256) { + return _getStatusAnswer(s_feedState.latestStatus); + } + + /// @inheritdoc AggregatorInterface + function latestTimestamp() external view override checkAccess returns (uint256) { + return s_feedState.startedAt; + } + + /// @inheritdoc AggregatorInterface + function latestRound() external view override checkAccess returns (uint256) { + return s_feedState.latestRoundId; + } + + /// @inheritdoc AggregatorInterface + function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { + if (!_isValidRound(roundId)) { + revert NoDataPresent(); + } + + return _getStatusAnswer(s_rounds[uint80(roundId)].status); + } + + /// @inheritdoc AggregatorInterface + function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { + if (!_isValidRound(roundId)) { + revert NoDataPresent(); + } + + return s_rounds[uint80(roundId)].startedAt; + } + + /** + * @notice Record a new status and timestamp if it has changed since the last round. + * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. + * + * @param status Sequencer status + * @param timestamp Block timestamp of status update + */ + function updateStatus(bool status, uint64 timestamp) external override { + _validateSender(s_l1Sender); + + FeedState memory feedState = _getFeedState(); + // Ignore if latest recorded timestamp is newer + if (feedState.startedAt > timestamp) { + emit UpdateIgnored(feedState.latestStatus, feedState.startedAt, status, timestamp); + return; + } + + if (feedState.latestStatus == status) { + _updateRound(feedState.latestRoundId, status); + } else { + feedState.latestRoundId += 1; + _recordRound(feedState.latestRoundId, status, timestamp); + } + } + + function _validateSender(address l1Sender) internal virtual; + + /// @inheritdoc AggregatorV3Interface + function getRoundData( + uint80 _roundId + ) + public + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + if (!_isValidRound(_roundId)) { + revert NoDataPresent(); + } + + Round storage round = s_rounds[_roundId]; + + return (_roundId, _getStatusAnswer(round.status), uint256(round.startedAt), uint256(round.updatedAt), _roundId); + } + + /// @inheritdoc AggregatorV3Interface + function latestRoundData() + external + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + FeedState storage feedState = s_feedState; + + return ( + feedState.latestRoundId, + _getStatusAnswer(feedState.latestStatus), + feedState.startedAt, + feedState.updatedAt, + feedState.latestRoundId + ); + } +} diff --git a/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol b/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol new file mode 100644 index 00000000000..33df388972f --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; + +abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValidatorInterface, ITypeAndVersion { + /// @notice emitted when gas cost to spend on L2 is updated + /// @param gasLimit updated gas cost + event GasLimitUpdated(uint32 gasLimit); + + error L1CrossDomainMessengerAddressZero(); + error L2UptimeFeedAddrZero(); + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L1_CROSS_DOMAIN_MESSENGER_ADDRESS; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L2_UPTIME_FEED_ADDR; + + int256 internal constant ANSWER_SEQ_OFFLINE = 1; + + uint32 internal s_gasLimit; + + /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address + /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeed contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { + if (l1CrossDomainMessengerAddress == address(0)) { + revert L1CrossDomainMessengerAddressZero(); + } + if (l2UptimeFeedAddr == address(0)) { + revert L2UptimeFeedAddrZero(); + } + + L1_CROSS_DOMAIN_MESSENGER_ADDRESS = l1CrossDomainMessengerAddress; + L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr; + s_gasLimit = gasLimit; + } + + /// @notice fetches the gas cost of sending a cross chain message + function getGasLimit() external view returns (uint32) { + return s_gasLimit; + } + + /// @notice sets the new gas cost to spend when sending cross chain message + /// @param gasLimit the updated gas cost + function setGasLimit(uint32 gasLimit) external onlyOwner { + s_gasLimit = gasLimit; + emit GasLimitUpdated(gasLimit); + } + + /// @notice makes this contract payable + /// @dev receives funds: + /// - to use them (if configured) to pay for L2 execution on L1 + /// - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2) + receive() external payable {} +} diff --git a/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol new file mode 100644 index 00000000000..0074a0277d1 --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; + +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; + +/// @title ZKSyncSequencerUptimeFeed - L2 sequencer uptime status aggregator +/// @notice L2 contract that receives status updates from a specific L1 address, +/// records a new answer if the status changed +contract ZKSyncSequencerUptimeFeed is BaseSequencerUptimeFeed { + string public constant override typeAndVersion = "ZKSyncSequencerUptimeFeed 1.1.0-dev"; + + /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + /// @param initialStatus The initial status of the feed + constructor(address l1SenderAddress, bool initialStatus) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) {} + + function _validateSender(address l1Sender) internal view override { + address aliasedL1Sender = AddressAliasHelper.applyL1ToL2Alias(l1Sender); + + if (msg.sender != aliasedL1Sender) { + revert InvalidSender(); + } + } +} diff --git a/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol new file mode 100644 index 00000000000..10f68ce286d --- /dev/null +++ b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; + +import {BaseValidator} from "../shared/BaseValidator.sol"; + +import {IBridgehub, L2TransactionRequestDirect} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; + +/// @title ZKSyncValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 +contract ZKSyncValidator is BaseValidator { + /// Contract state variables + string public constant override typeAndVersion = "ZKSyncValidator 1.1.0-dev"; + uint32 private constant ZKSYNC_TEST_NET_CHAIN_ID = 300; + uint32 private constant ZKSYNC_MAIN_NET_CHAIN_ID = 324; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + uint32 private immutable CHAIN_ID; + /// @dev how much l2 gas each byte of pubdata costs + uint32 private s_l2GasPerPubdataByteLimit; + + /// @notice emitted when the gas per pubdata byte limit is updated + /// @param l2GasPerPubdataByteLimit updated gas per pubdata byte limit + event GasPerPubdataByteLimitUpdated(uint32 l2GasPerPubdataByteLimit); + + /// @notice ChainID is not a valid value + error InvalidChainID(); + + /// @param l1CrossDomainMessengerAddress address the Bridgehub contract address + /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeedInterface contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor( + address l1CrossDomainMessengerAddress, + address l2UptimeFeedAddr, + uint32 gasLimit, + uint32 chainId, + uint32 l2GasPerPubdataByteLimit + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) { + if (chainId != ZKSYNC_TEST_NET_CHAIN_ID && chainId != ZKSYNC_MAIN_NET_CHAIN_ID) { + revert InvalidChainID(); + } + + s_l2GasPerPubdataByteLimit = l2GasPerPubdataByteLimit; + CHAIN_ID = chainId; + } + + /// @notice sets the l2GasPerPubdataByteLimit for the L2 transaction request + /// @param l2GasPerPubdataByteLimit the updated l2GasPerPubdataByteLimit + function setL2GasPerPubdataByteLimit(uint32 l2GasPerPubdataByteLimit) external onlyOwner { + if (s_l2GasPerPubdataByteLimit != l2GasPerPubdataByteLimit) { + s_l2GasPerPubdataByteLimit = l2GasPerPubdataByteLimit; + emit GasPerPubdataByteLimitUpdated(l2GasPerPubdataByteLimit); + } + } + + /// @notice fetches the l2GasPerPubdataByteLimit for the L2 transaction request + function getL2GasPerPubdataByteLimit() external view returns (uint32) { + return s_l2GasPerPubdataByteLimit; + } + + /// @notice fetches the chain id + function getChainId() external view returns (uint32) { + return CHAIN_ID; + } + + /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + /// @dev A message is sent using the Bridgehub. This method is accessed controlled. + /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + IBridgehub bridgeHub = IBridgehub(L1_CROSS_DOMAIN_MESSENGER_ADDRESS); + + uint256 transactionBaseCostEstimate = bridgeHub.l2TransactionBaseCost( + CHAIN_ID, + tx.gasprice, + s_gasLimit, + s_l2GasPerPubdataByteLimit + ); + + L2TransactionRequestDirect memory l2TransactionRequestDirect = L2TransactionRequestDirect({ + chainId: CHAIN_ID, + mintValue: transactionBaseCostEstimate, + l2Contract: L2_UPTIME_FEED_ADDR, + l2Value: 0, + l2Calldata: abi.encodeWithSelector( + ISequencerUptimeFeed.updateStatus.selector, + currentAnswer == ANSWER_SEQ_OFFLINE, + uint64(block.timestamp) + ), + l2GasLimit: s_gasLimit, + l2GasPerPubdataByteLimit: s_l2GasPerPubdataByteLimit, + factoryDeps: new bytes[](0), + refundRecipient: msg.sender + }); + + // Make the xDomain call + bridgeHub.requestL2TransactionDirect{value: transactionBaseCostEstimate}(l2TransactionRequestDirect); + + return true; + } +} diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol b/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol index c4e2f710300..52019324f59 100644 --- a/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol +++ b/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; +pragma solidity ^0.8.24; import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; diff --git a/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol b/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol index e63847d6557..42147fbd91e 100644 --- a/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol +++ b/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; +pragma solidity ^0.8.24; import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol b/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol index 1700bcbe168..e43f1bf1366 100644 --- a/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol +++ b/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; diff --git a/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol b/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol index 66400b7d305..af0e0b5ca59 100644 --- a/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol +++ b/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; +pragma solidity ^0.8.24; import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol b/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol new file mode 100644 index 00000000000..b46b9d9fdf0 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; +import {IL1SharedBridge} from "@zksync/contracts/l1-contracts/contracts/bridge/interfaces/IL1SharedBridge.sol"; +import {L2Message, L2Log, TxStatus} from "@zksync/contracts/l1-contracts/contracts/common/Messaging.sol"; + +contract MockBridgehub is IBridgehub { + address public pendingAdmin; + address public admin; + address public sharedBridgeAddr; + + mapping(address stateTransitionManager => bool stateTransitionManagerIsRegistered) + public registeredStateTransitionManagers; + mapping(uint256 chainId => address stateTransitionManagerAddress) public stateTransitionManagers; + mapping(address baseToken => bool tokenIsRegistered) public registeredTokens; + mapping(uint256 chainId => address baseToken) public baseTokens; + mapping(uint256 chainId => address hyperChain) public hyperchains; + + /// Generic error for unauthorized actions + error NotAuthorized(string msg); + + /// Fake event that will get emitted when `requestL2TransactionDirect` is called + event SentMessage(address indexed sender, bytes message); + + /// Admin functions + function setPendingAdmin(address _newPendingAdmin) external override { + emit NewPendingAdmin(pendingAdmin, _newPendingAdmin); + pendingAdmin = _newPendingAdmin; + } + + function acceptAdmin() external override { + if (msg.sender != pendingAdmin) { + revert NotAuthorized("Only pending admin can accept"); + } + + emit NewAdmin(admin, pendingAdmin); + admin = pendingAdmin; + pendingAdmin = address(0); + } + + /// Getters + function stateTransitionManagerIsRegistered(address _stateTransitionManager) external view override returns (bool) { + return registeredStateTransitionManagers[_stateTransitionManager]; + } + + function stateTransitionManager(uint256 _chainId) external view override returns (address) { + return stateTransitionManagers[_chainId]; + } + + function tokenIsRegistered(address _baseToken) external view override returns (bool) { + return registeredTokens[_baseToken]; + } + + function baseToken(uint256 _chainId) external view override returns (address) { + return baseTokens[_chainId]; + } + + function sharedBridge() external view override returns (IL1SharedBridge) { + return IL1SharedBridge(sharedBridgeAddr); + } + + function getHyperchain(uint256 _chainId) external view override returns (address) { + return hyperchains[_chainId]; + } + + /// Mailbox forwarder + function proveL2MessageInclusion( + uint256, + uint256, + uint256, + L2Message calldata, + bytes32[] calldata + ) external pure override returns (bool) { + return true; + } + + function proveL2LogInclusion( + uint256, + uint256, + uint256, + L2Log memory, + bytes32[] calldata + ) external pure override returns (bool) { + return true; + } + + function proveL1ToL2TransactionStatus( + uint256, + bytes32, + uint256, + uint256, + uint16, + bytes32[] calldata, + TxStatus + ) external pure override returns (bool) { + return true; + } + + function requestL2TransactionDirect( + L2TransactionRequestDirect calldata txRequest + ) external payable override returns (bytes32) { + emit SentMessage(msg.sender, txRequest.l2Calldata); + return keccak256(abi.encodePacked("L2TransactionDirect")); + } + + function requestL2TransactionTwoBridges( + L2TransactionRequestTwoBridgesOuter calldata + ) external payable override returns (bytes32) { + return keccak256(abi.encodePacked("L2TransactionTwoBridges")); + } + + function l2TransactionBaseCost(uint256, uint256, uint256, uint256) external pure override returns (uint256) { + return 0; + } + + /// Registry + function createNewChain( + uint256 _chainId, + address _stateTransitionManager, + address _baseToken, + uint256, + address, + bytes calldata + ) external override returns (uint256 chainId) { + hyperchains[_chainId] = _stateTransitionManager; + baseTokens[_chainId] = _baseToken; + emit NewChain(_chainId, _stateTransitionManager, address(this)); + return _chainId; + } + + function addStateTransitionManager(address _stateTransitionManager) external override { + registeredStateTransitionManagers[_stateTransitionManager] = true; + } + + function removeStateTransitionManager(address _stateTransitionManager) external override { + registeredStateTransitionManagers[_stateTransitionManager] = false; + } + + function addToken(address _token) external override { + registeredTokens[_token] = true; + } + + function setSharedBridge(address _sharedBridgeAddr) external override { + sharedBridgeAddr = _sharedBridgeAddr; + } +} 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 561e32be1a2..93640f4bcb4 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,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity ^0.8.24; import {Greeter} from "../../../tests/Greeter.sol"; @@ -13,21 +13,6 @@ contract L2EPTest is Test { address internal s_eoaValidator = vm.addr(0x3); address internal s_deployerAddr = vm.addr(0x4); - /// @param expectedGasUsage - the expected gas usage - /// @param startGasUsage - the gas usage before the code of interest is run - /// @param finalGasUsage - the gas usage after the code of interest is run - /// @param deviation - the amount of gas that the actual usage is allowed to deviate by (e.g. (expectedGas - deviation) <= actualGasUsage <= (expectedGas + deviation)) - function assertGasUsageIsCloseTo( - uint256 expectedGasUsage, - uint256 startGasUsage, - uint256 finalGasUsage, - uint256 deviation - ) public { - uint256 gasUsed = (startGasUsage - finalGasUsage) * tx.gasprice; - assertLe(gasUsed, expectedGasUsage + deviation); - assertGe(gasUsed, expectedGasUsage - deviation); - } - /// @param selector - the function selector /// @param greeterAddr - the address of the Greeter contract /// @param message - the new greeting message, which will be passed as an argument to Greeter#setGreeting 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 be3851c5b5d..cff9b953e2e 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {ArbitrumCrossDomainForwarder} from "../../../dev/arbitrum/ArbitrumCrossDomainForwarder.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; 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 c5b8adaf7d2..610f49f16c4 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {ArbitrumCrossDomainGovernor} from "../../../dev/arbitrum/ArbitrumCrossDomainGovernor.sol"; import {Greeter} from "../../../../tests/Greeter.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 3b9df3bf910..e308ead3432 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; @@ -246,199 +246,3 @@ contract ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFuncti assertEq(answer, 0); } } - -contract ArbitrumSequencerUptimeFeed_GasCosts is ArbitrumSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for updates - function test_GasCosts() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Assert initial conditions - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp(); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed; - uint256 gasStart; - uint256 gasFinal; - - // measures gas used for no update - expectedGasUsed = 5507; // NOTE: used to be 28300 in hardhat tests - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - - // measures gas used for update - expectedGasUsed = 68198; // NOTE: used to be 93015 in hardhat tests - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} - -contract ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts is ArbitrumSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for getRoundData(uint80) - function test_GasUsageForGetRoundData() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4658; // NOTE: used to be 31157 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.getRoundData(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRoundData() - function test_GasUsageForLatestRoundData() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 2154; // NOTE: used to be 28523 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestRoundData(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestAnswer() - function test_GasUsageForLatestAnswer() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1722; // NOTE: used to be 28329 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestAnswer(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestTimestamp() - function test_GasUsageForLatestTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1652; // NOTE: used to be 28229 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestTimestamp(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRound() - function test_GasUsageForLatestRound() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1632; // NOTE: used to be 28245 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestRound(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getAnswer() - function test_GasUsageForGetAnswer() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4059; // NOTE: used to be 30799 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.getAnswer(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getTimestamp() - function test_GasUsageForGetTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4024; // NOTE: used to be 30753 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.getTimestamp(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} 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 504635540ce..ab872991749 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.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 d5c482dce98..c0e82ab8d5e 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {OptimismCrossDomainForwarder} from "../../../dev/optimism/OptimismCrossDomainForwarder.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; 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 e1a5aef95a1..8f8fb9d7e7c 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {OptimismCrossDomainGovernor} from "../../../dev/optimism/OptimismCrossDomainGovernor.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.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 60598b9f952..eec9657ac14 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,9 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; @@ -61,7 +62,7 @@ contract OptimismSequencerUptimeFeed_UpdateStatus is OptimismSequencerUptimeFeed vm.startPrank(s_strangerAddr, s_strangerAddr); // Tries to update the status from an unauthorized account - vm.expectRevert(OptimismSequencerUptimeFeed.InvalidSender.selector); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); } @@ -74,7 +75,7 @@ contract OptimismSequencerUptimeFeed_UpdateStatus is OptimismSequencerUptimeFeed s_mockOptimismL2CrossDomainMessenger.setSender(s_strangerAddr); // Tries to update the status from an unauthorized account - vm.expectRevert(OptimismSequencerUptimeFeed.InvalidSender.selector); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); } @@ -257,7 +258,7 @@ contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerU vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Gets data from a round that has not happened yet - vm.expectRevert(OptimismSequencerUptimeFeed.NoDataPresent.selector); + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); s_optimismSequencerUptimeFeed.getRoundData(2); } @@ -267,7 +268,7 @@ contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerU vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Gets data from a round that has not happened yet - vm.expectRevert(OptimismSequencerUptimeFeed.NoDataPresent.selector); + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); s_optimismSequencerUptimeFeed.getAnswer(2); } @@ -277,7 +278,7 @@ contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerU vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Gets data from a round that has not happened yet - vm.expectRevert(OptimismSequencerUptimeFeed.NoDataPresent.selector); + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); s_optimismSequencerUptimeFeed.getTimestamp(2); } } @@ -318,207 +319,3 @@ contract OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFuncti assertEq(answer, 0); } } - -contract OptimismSequencerUptimeFeed_GasCosts is OptimismSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for updates - function test_GasCosts() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Assert initial conditions - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed; - uint256 gasStart; - uint256 gasFinal; - - // measures gas used for no update - expectedGasUsed = 10197; // NOTE: used to be 38594 in hardhat tests - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - - // measures gas used for update - expectedGasUsed = 33348; // NOTE: used to be 60170 in hardhat tests - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} - -contract OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts is OptimismSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for getRoundData(uint80) - function test_GasUsageForGetRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4504; // NOTE: used to be 30952 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.getRoundData(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRoundData() - function test_GasUsageForLatestRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 2154; // NOTE: used to be 28523 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestRoundData(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestAnswer() - function test_GasUsageForLatestAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1722; // NOTE: used to be 28329 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestAnswer(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestTimestamp() - function test_GasUsageForLatestTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1598; // NOTE: used to be 28229 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestTimestamp(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRound() - function test_GasUsageForLatestRound() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1632; // NOTE: used to be 28245 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestRound(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getAnswer() - function test_GasUsageForGetAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3929; // NOTE: used to be 30682 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.getAnswer(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getTimestamp() - function test_GasUsageForGetTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3817; // NOTE: used to be 30570 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.getTimestamp(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} 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 9364396817a..59395bf5d8b 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 @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; + +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; @@ -73,7 +75,7 @@ contract OptimismValidator_Validate is OptimismValidatorTest { emit SentMessage( L2_SEQ_STATUS_RECORDER_ADDRESS, // target address(s_optimismValidator), // sender - abi.encodeWithSelector(OptimismSequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds), // message + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds), // message 0, // nonce INIT_GAS_LIMIT // gas limit ); @@ -97,7 +99,7 @@ contract OptimismValidator_Validate is OptimismValidatorTest { emit SentMessage( L2_SEQ_STATUS_RECORDER_ADDRESS, // target address(s_optimismValidator), // sender - abi.encodeWithSelector(OptimismSequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds), // message + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds), // message 0, // nonce INIT_GAS_LIMIT // gas limit ); 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 f921fa9242e..e34e84f4006 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; import {ScrollCrossDomainForwarder} from "../../../dev/scroll/ScrollCrossDomainForwarder.sol"; 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 9c444604946..8c3d56d1560 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 @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; import {ScrollCrossDomainGovernor} from "../../../dev/scroll/ScrollCrossDomainGovernor.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol index 520fbf6dfdc..0968c69415f 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; @@ -65,7 +66,7 @@ contract ScrollSequencerUptimeFeed_UpdateStatus is ScrollSequencerUptimeFeedTest vm.startPrank(s_strangerAddr, s_strangerAddr); // Tries to update the status from an unauthorized account - vm.expectRevert(ScrollSequencerUptimeFeed.InvalidSender.selector); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); } @@ -78,7 +79,7 @@ contract ScrollSequencerUptimeFeed_UpdateStatus is ScrollSequencerUptimeFeedTest s_mockScrollL2CrossDomainMessenger.setSender(s_strangerAddr); // Tries to update the status from an unauthorized account - vm.expectRevert(ScrollSequencerUptimeFeed.InvalidSender.selector); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); } @@ -261,7 +262,7 @@ contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptim vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Gets data from a round that has not happened yet - vm.expectRevert(ScrollSequencerUptimeFeed.NoDataPresent.selector); + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); s_scrollSequencerUptimeFeed.getRoundData(2); } @@ -271,7 +272,7 @@ contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptim vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Gets data from a round that has not happened yet - vm.expectRevert(ScrollSequencerUptimeFeed.NoDataPresent.selector); + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); s_scrollSequencerUptimeFeed.getAnswer(2); } @@ -281,7 +282,7 @@ contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptim vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Gets data from a round that has not happened yet - vm.expectRevert(ScrollSequencerUptimeFeed.NoDataPresent.selector); + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); s_scrollSequencerUptimeFeed.getTimestamp(2); } } @@ -322,207 +323,3 @@ contract ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunction assertEq(answer, 0); } } - -contract ScrollSequencerUptimeFeed_GasCosts is ScrollSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for updates - function test_GasCosts() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Assert initial conditions - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed; - uint256 gasStart; - uint256 gasFinal; - - // measures gas used for no update - expectedGasUsed = 10197; // NOTE: used to be 38594 in hardhat tests - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - - // measures gas used for update - expectedGasUsed = 31644; // NOTE: used to be 58458 in hardhat tests - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} - -contract ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts is ScrollSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for getRoundData(uint80) - function test_GasUsageForGetRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4504; // NOTE: used to be 30952 in hardhat tesst - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.getRoundData(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRoundData() - function test_GasUsageForLatestRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 2154; // NOTE: used to be 28523 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestRoundData(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestAnswer() - function test_GasUsageForLatestAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1566; // NOTE: used to be 28229 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestAnswer(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestTimestamp() - function test_GasUsageForLatestTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1459; // NOTE: used to be 28129 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestTimestamp(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRound() - function test_GasUsageForLatestRound() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1470; // NOTE: used to be 28145 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestRound(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getAnswer() - function test_GasUsageForGetAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3929; // NOTE: used to be 30682 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.getAnswer(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getTimestamp() - function test_GasUsageForGetTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3817; // NOTE: used to be 30570 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.getTimestamp(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol index f425ca1c6e5..3d5298d5184 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; + +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; @@ -87,7 +89,7 @@ contract ScrollValidator_Validate is ScrollValidatorTest { 0, // value 0, // nonce INIT_GAS_LIMIT, // gas limit - abi.encodeWithSelector(ScrollSequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds) // message + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds) // message ); // Runs the function (which produces the event to test) @@ -112,7 +114,7 @@ contract ScrollValidator_Validate is ScrollValidatorTest { 0, // value 0, // nonce INIT_GAS_LIMIT, // gas limit - abi.encodeWithSelector(ScrollSequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) // message + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) // message ); // Runs the function (which produces the event to test) diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol new file mode 100644 index 00000000000..6d90b3973e9 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {ZKSyncSequencerUptimeFeed} from "../../../dev/zksync/ZKSyncSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ZKSyncSequencerUptimeFeedTest is L2EPTest { + /// Helper Variables + address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); + + /// L2EP contracts + ZKSyncSequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); + + /// Setup + function setUp() public { + // Deploys contracts + s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed(s_l1OwnerAddr, false); + } +} + +contract ZKSyncSequencerUptimeFeed_Constructor is ZKSyncSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Checks L1 sender + address actualL1Addr = s_zksyncSequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); + + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} + +contract ZKSyncSequencerUptimeFeed_UpdateStatus is ZKSyncSequencerUptimeFeedTest { + /// @notice it should revert if called by an unauthorized account + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + } +} + +contract ZKSyncSequencerUptimeFeed_AggregatorV3Interface is ZKSyncSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getTimestamp(2); + } +} + +contract ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ZKSyncSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); + + // Whitelist consumer + s_zksyncSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol new file mode 100644 index 00000000000..0bea147c8cd --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {MockBridgehub} from "../../mocks/zksync/MockZKSyncL1Bridge.sol"; +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; +import {ZKSyncValidator} from "../../../dev/zksync/ZKSyncValidator.sol"; +import {BaseValidator} from "../../../dev/shared/BaseValidator.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ZKSyncValidatorTest is L2EPTest { + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = address(0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b); + address internal constant DUMMY_L1_XDOMAIN_MSNGR_ADDR = address(0xa04Fc18f012B1a5A8231c7Ee4b916Dd6dbd271b6); + address internal constant DUMMY_L2_UPTIME_FEED_ADDR = address(0xFe31891940A2e5f04B76eD8bD1038E44127d1512); + uint32 internal constant INIT_GAS_PER_PUBDATA_BYTE_LIMIT = 800; + uint32 internal constant INIT_GAS_LIMIT = 1900000; + uint32 internal constant MAIN_NET_CHAIN_ID = 300; + uint32 internal constant BAD_CHAIN_ID = 0; + + ISequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; + MockBridgehub internal s_mockZKSyncL1Bridge; + ZKSyncValidator internal s_zksyncValidator; + + /// Fake event that will get emitted when `requestL2TransactionDirect` is called + /// Definition is taken from MockZKSyncL1Bridge + event SentMessage(address indexed sender, bytes message); + + /// Setup + function setUp() public { + s_mockZKSyncL1Bridge = new MockBridgehub(); + + s_zksyncValidator = new ZKSyncValidator( + address(s_mockZKSyncL1Bridge), + DUMMY_L2_UPTIME_FEED_ADDR, + INIT_GAS_LIMIT, + MAIN_NET_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } +} + +contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { + /// @notice it correctly validates that the chain id is valid + function test_ConstructingRevertedWithInvalidChainId() public { + vm.expectRevert(ZKSyncValidator.InvalidChainID.selector); + new ZKSyncValidator( + DUMMY_L1_XDOMAIN_MSNGR_ADDR, + DUMMY_L2_UPTIME_FEED_ADDR, + INIT_GAS_LIMIT, + BAD_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } + + /// @notice it correctly validates that the L1 bridge address is not zero + function test_ConstructingRevertedWithZeroL1BridgeAddress() public { + vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); + new ZKSyncValidator( + address(0), + DUMMY_L2_UPTIME_FEED_ADDR, + INIT_GAS_LIMIT, + MAIN_NET_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } + + /// @notice it correctly validates that the L2 Uptime feed address is not zero + function test_ConstructingRevertedWithZeroL2UpdateFeedAddress() public { + vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); + new ZKSyncValidator( + DUMMY_L1_XDOMAIN_MSNGR_ADDR, + address(0), + INIT_GAS_LIMIT, + MAIN_NET_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } +} + +contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidatorTest { + /// @notice it correctly updates the gas limit per pubdata byte + function test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() public { + assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), INIT_GAS_PER_PUBDATA_BYTE_LIMIT); + + uint32 newGasPerPubDataByteLimit = 2000000; + s_zksyncValidator.setL2GasPerPubdataByteLimit(newGasPerPubDataByteLimit); + assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), newGasPerPubDataByteLimit); + } +} + +contract ZKSyncValidator_GetChainId is ZKSyncValidatorTest { + /// @notice it correctly gets the chain id + function test_CorrectlyGetsTheChainId() public { + assertEq(s_zksyncValidator.getChainId(), MAIN_NET_CHAIN_ID); + } +} + +contract ZKSyncValidator_Validate is ZKSyncValidatorTest { + /// @notice it reverts if called by account with no access + function test_RevertsIfCalledByAnAccountWithNoAccess() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("No access"); + s_zksyncValidator.validate(0, 0, 1, 1); + } + + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + // Gives access to the s_eoaValidator + s_zksyncValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 5000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + bytes memory message = abi.encodeWithSelector( + ISequencerUptimeFeed.updateStatus.selector, + false, + futureTimestampInSeconds + ); + + vm.expectEmit(false, false, false, true); + emit SentMessage(address(s_zksyncValidator), message); + + // Runs the function (which produces the event to test) + s_zksyncValidator.validate(0, 0, 0, 0); + } + + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { + // Gives access to the s_eoaValidator + s_zksyncValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 10000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + vm.expectEmit(false, false, false, true); + emit SentMessage( + address(s_zksyncValidator), + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) + ); + + // Runs the function (which produces the event to test) + s_zksyncValidator.validate(0, 0, 1, 1); + } +} diff --git a/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol b/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol index b856f734e7b..655f1b11182 100644 --- a/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol +++ b/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol @@ -90,11 +90,7 @@ abstract contract OCR3Base is OwnerIsCreator, OCR3Abstract { } // Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 numSigners, - uint256 numTransmitters, - uint256 f - ) { + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); if (f == 0) revert InvalidConfig("f must be positive"); if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); @@ -236,7 +232,7 @@ abstract contract OCR3Base is OwnerIsCreator, OCR3Abstract { // Scoping this reduces stack pressure and gas usage { uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report + report.length + // one byte per entry in report rs.length * 32 + // 32 bytes per entry in _rs ss.length * diff --git a/contracts/src/v0.8/llo-feeds/dev/ChannelConfigStore.sol b/contracts/src/v0.8/llo-feeds/dev/ChannelConfigStore.sol deleted file mode 100644 index 6c6a5ec9b3e..00000000000 --- a/contracts/src/v0.8/llo-feeds/dev/ChannelConfigStore.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IChannelConfigStore} from "./interfaces/IChannelConfigStore.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; - -contract ChannelConfigStore is ConfirmedOwner, IChannelConfigStore, TypeAndVersionInterface { - mapping(uint32 => ChannelDefinition) private s_channelDefinitions; - - // mapping(bytes32 => ChannelConfiguration) private s_channelProductionConfigurations; - // mapping(bytes32 => ChannelConfiguration) private s_channelStagingConfigurations; - - event NewChannelDefinition(uint32 channelId, ChannelDefinition channelDefinition); - event ChannelDefinitionRemoved(uint32 channelId); - // event NewProductionConfig(ChannelConfiguration channelConfig); - // event NewStagingConfig(ChannelConfiguration channelConfig); - event PromoteStagingConfig(uint32 channelId); - - error OnlyCallableByEOA(); - error StagingConfigAlreadyPromoted(); - error EmptyStreamIDs(); - error ZeroReportFormat(); - error ZeroChainSelector(); - error ChannelDefinitionNotFound(); - - constructor() ConfirmedOwner(msg.sender) {} - - // function setStagingConfig(bytes32 configDigest, ChannelConfiguration calldata channelConfig) external onlyOwner { - // s_channelStagingConfigurations[channelId] = channelConfig; - - // emit NewStagingConfig(channelConfig); - // } - - //// this will trigger the following: - //// - offchain ShouldRetireCache will start returning true for the old (production) - //// protocol instance - //// - once the old production instance retires it will generate a handover - //// retirement report - //// - the staging instance will become the new production instance once - //// any honest oracle that is on both instances forward the retirement - //// report from the old instance to the new instace via the - //// PredecessorRetirementReportCache - //// - //// Note: the promotion flow only works if the previous production instance - //// is working correctly & generating reports. If that's not the case, the - //// owner is expected to "setProductionConfig" directly instead. This will - //// cause "gaps" to be created, but that seems unavoidable in such a scenario. - // function promoteStagingConfig(bytes32 configDigest) external onlyOwner { - // ChannelConfiguration memory stagingConfig = s_channelStagingConfigurations[channelId]; - - // if(stagingConfig.channelConfigId.length == 0) { - // revert StagingConfigAlreadyPromoted(); - // } - - // s_channelProductionConfigurations[channelId] = s_channelStagingConfigurations[channelId]; - - // emit PromoteStagingConfig(channelId); - // } - - function addChannel(uint32 channelId, ChannelDefinition calldata channelDefinition) external onlyOwner { - if (channelDefinition.streamIDs.length == 0) { - revert EmptyStreamIDs(); - } - - if (channelDefinition.chainSelector == 0) { - revert ZeroChainSelector(); - } - - if (channelDefinition.reportFormat == 0) { - revert ZeroReportFormat(); - } - - s_channelDefinitions[channelId] = channelDefinition; - - emit NewChannelDefinition(channelId, channelDefinition); - } - - function removeChannel(uint32 channelId) external onlyOwner { - if (s_channelDefinitions[channelId].streamIDs.length == 0) { - revert ChannelDefinitionNotFound(); - } - - delete s_channelDefinitions[channelId]; - - emit ChannelDefinitionRemoved(channelId); - } - - function getChannelDefinitions(uint32 channelId) external view returns (ChannelDefinition memory) { - // solhint-disable-next-line avoid-tx-origin - if (msg.sender != tx.origin) { - revert OnlyCallableByEOA(); - } - - return s_channelDefinitions[channelId]; - } - - function typeAndVersion() external pure override returns (string memory) { - return "ChannelConfigStore 0.0.0"; - } - - function supportsInterface(bytes4 interfaceId) external pure returns (bool) { - return interfaceId == type(IChannelConfigStore).interfaceId; - } -} diff --git a/contracts/src/v0.8/llo-feeds/dev/ChannelVerifier.sol b/contracts/src/v0.8/llo-feeds/dev/ChannelVerifier.sol deleted file mode 100644 index 424022dc441..00000000000 --- a/contracts/src/v0.8/llo-feeds/dev/ChannelVerifier.sol +++ /dev/null @@ -1,536 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../libraries/Common.sol"; -import {IChannelVerifier} from "./interfaces/IChannelVerifier.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 ChannelVerifier is IChannelVerifier, ConfirmedOwner, TypeAndVersionInterface { - // 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 feed data - Signer - } - - struct Signer { - // Index of oracle in a configuration - uint8 index; - // The oracle's role - Role role; - } - - struct Config { - // Fault tolerance - uint8 f; - // Marks whether or not a configuration is active - bool isActive; - // Map of signer addresses to oracles - mapping(address => Signer) oracles; - } - - struct VerifierState { - // The number of times a new configuration - /// has been set - uint32 configCount; - // The block number of the block the last time - /// the configuration was updated. - uint32 latestConfigBlockNumber; - // The latest epoch a report was verified for - uint32 latestEpoch; - /// The latest config digest set - bytes32 latestConfigDigest; - /// List of deactivated feeds - mapping(bytes32 => bool) deactivatedFeeds; - /// The historical record of all previously set configs by feedId - mapping(bytes32 => Config) s_verificationDataConfigs; - } - - /// @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 configuration is set. It triggers a new run of the offchain reporting protocol. - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - bytes32[] offchainTransmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /// @notice This event is emitted whenever a configuration is deactivated - event ConfigDeactivated(bytes32 configDigest); - - /// @notice This event is emitted whenever a configuration is activated - event ConfigActivated(bytes32 configDigest); - - /// @notice This event is emitted whenever a feed is activated - event FeedActivated(bytes32 indexed feedId); - - /// @notice This event is emitted whenever a feed is deactivated - event FeedDeactivated(bytes32 indexed feedId); - - /// @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 feed ID passed in - /// a signed report is empty - error FeedIdEmpty(); - - /// @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 the admin tries to deactivate - /// the latest config digest - /// @param configDigest The latest config digest - error CannotDeactivateLatestConfig(bytes32 configDigest); - - /// @notice This error is thrown whenever the feed ID passed in is deactivated - /// @param feedId The feed ID - error InactiveFeed(bytes32 feedId); - - /// @notice This error is thrown whenever the feed ID passed in is not found - /// @param feedId The feed ID - error InvalidFeed(bytes32 feedId); - - /// @notice The address of the verifier proxy - address private immutable i_verifierProxyAddr; - - /// @notice Verifier states keyed on Feed ID - VerifierState internal s_feedVerifierState; - - /// @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 TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "ChannelVerifier 0.0.0"; - } - - /// @inheritdoc IChannelVerifier - 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)); - - // The feed ID is the first 32 bytes of the report data. - bytes32 feedId = bytes32(reportData); - - // If the feed has been deactivated, do not verify the report - if (s_feedVerifierState.deactivatedFeeds[feedId]) { - revert InactiveFeed(feedId); - } - - // 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]; - Config storage s_config = s_feedVerifierState.s_verificationDataConfigs[configDigest]; - - _validateReport(configDigest, rs, ss, s_config); - _updateEpoch(reportContext, s_feedVerifierState); - - bytes32 hashedReport = keccak256(reportData); - - _verifySignatures(hashedReport, reportContext, rs, ss, rawVs, s_config); - emit ReportVerified(feedId, 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 feed ID keyed on the config digest - function _validateReport( - bytes32 configDigest, - bytes32[] memory rs, - bytes32[] memory ss, - Config 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 Conditionally update the epoch for a feed - * @param reportContext Report context containing the epoch and round - * @param feedVerifierState Feed verifier state to conditionally update - */ - function _updateEpoch(bytes32[3] memory reportContext, VerifierState storage feedVerifierState) private { - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - if (epoch > feedVerifierState.latestEpoch) { - feedVerifierState.latestEpoch = epoch; - } - } - - /// @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 s_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, - Config storage s_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 = s_config.oracles[signerAddress]; - if (o.role != Role.Signer) revert BadVerification(); - unchecked { - signedCount += 1 << (8 * o.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert BadVerification(); - } - - /// @inheritdoc IChannelVerifier - function setConfig( - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig( - block.chainid, - address(this), - 0, // 0 defaults to feedConfig.configCount + 1 - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig, - recipientAddressesAndWeights - ); - } - - /// @inheritdoc IChannelVerifier - function setConfigFromSource( - uint256 sourceChainId, - address sourceAddress, - uint32 newConfigCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig( - sourceChainId, - sourceAddress, - newConfigCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig, - recipientAddressesAndWeights - ); - } - - /// @notice Sets config based on the given arguments - /// @param sourceChainId Chain ID of source config - /// @param sourceAddress Address of source config Verifier - /// @param newConfigCount Optional param to force the new config count - /// @param signers addresses with which oracles sign the reports - /// @param offchainTransmitters CSA key for the ith Oracle - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - /// @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - function _setConfig( - uint256 sourceChainId, - address sourceAddress, - uint32 newConfigCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) internal { - // Increment the number of times a config has been set first - if (newConfigCount > 0) s_feedVerifierState.configCount = newConfigCount; - else s_feedVerifierState.configCount++; - - bytes32 configDigest = _configDigestFromConfigData( - sourceChainId, - sourceAddress, - s_feedVerifierState.configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - s_feedVerifierState.s_verificationDataConfigs[configDigest].f = f; - s_feedVerifierState.s_verificationDataConfigs[configDigest].isActive = true; - 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 = s_feedVerifierState.s_verificationDataConfigs[configDigest].oracles[signerAddr].role != - Role.Unset; - if (isSignerAlreadySet) revert NonUniqueSignatures(); - s_feedVerifierState.s_verificationDataConfigs[configDigest].oracles[signerAddr] = Signer({ - role: Role.Signer, - index: i - }); - } - - recipientAddressesAndWeights; // silence unused var warning - // IVerifierProxy(i_verifierProxyAddr).setVerifier( - // feedVerifierState.latestConfigDigest, - // configDigest, - // recipientAddressesAndWeights - // ); - - emit ConfigSet( - s_feedVerifierState.latestConfigBlockNumber, - configDigest, - s_feedVerifierState.configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - s_feedVerifierState.latestEpoch = 0; - s_feedVerifierState.latestConfigBlockNumber = uint32(block.number); - s_feedVerifierState.latestConfigDigest = configDigest; - } - - /// @notice Generates the config digest from config data - /// @param sourceChainId Chain ID of source config - /// @param sourceAddress Address of source config Verifier - /// @param configCount ordinal number of this config setting among all config settings over the life of this contract - /// @param signers ith element is address ith oracle uses to sign a report - /// @param offchainTransmitters ith element is address ith oracle used to transmit reports (in this case used for flexible additional field, such as CSA pub keys) - /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - /// @dev This function is a modified version of the method from OCR2Abstract - function _configDigestFromConfigData( - uint256 sourceChainId, - address sourceAddress, - 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( - sourceChainId, - sourceAddress, - configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - // 0x0009 corresponds to ConfigDigestPrefixLLO in libocr - uint256 prefix = 0x0009 << (256 - 16); // 0x000900..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /// @inheritdoc IChannelVerifier - function activateConfig(bytes32 configDigest) external onlyOwner { - if (configDigest == bytes32("")) revert DigestEmpty(); - if (s_feedVerifierState.s_verificationDataConfigs[configDigest].f == 0) revert DigestNotSet(configDigest); - s_feedVerifierState.s_verificationDataConfigs[configDigest].isActive = true; - emit ConfigActivated(configDigest); - } - - /// @inheritdoc IChannelVerifier - function deactivateConfig(bytes32 configDigest) external onlyOwner { - if (configDigest == bytes32("")) revert DigestEmpty(); - if (s_feedVerifierState.s_verificationDataConfigs[configDigest].f == 0) revert DigestNotSet(configDigest); - if (configDigest == s_feedVerifierState.latestConfigDigest) { - revert CannotDeactivateLatestConfig(configDigest); - } - s_feedVerifierState.s_verificationDataConfigs[configDigest].isActive = false; - emit ConfigDeactivated(configDigest); - } - - /// @inheritdoc IChannelVerifier - function activateFeed(bytes32 feedId) external onlyOwner { - if (s_feedVerifierState.deactivatedFeeds[feedId]) return; - - s_feedVerifierState.deactivatedFeeds[feedId] = false; - emit FeedActivated(feedId); - } - - /// @inheritdoc IChannelVerifier - function deactivateFeed(bytes32 feedId) external onlyOwner { - if (s_feedVerifierState.deactivatedFeeds[feedId] == false) return; - - s_feedVerifierState.deactivatedFeeds[feedId] = true; - emit FeedDeactivated(feedId); - } - - /// @inheritdoc IChannelVerifier - function latestConfigDigestAndEpoch() - external - view - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (false, s_feedVerifierState.latestConfigDigest, s_feedVerifierState.latestEpoch); - } - - /// @inheritdoc IChannelVerifier - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return ( - s_feedVerifierState.configCount, - s_feedVerifierState.latestConfigBlockNumber, - s_feedVerifierState.latestConfigDigest - ); - } -} diff --git a/contracts/src/v0.8/llo-feeds/dev/interfaces/IChannelConfigStore.sol b/contracts/src/v0.8/llo-feeds/dev/interfaces/IChannelConfigStore.sol deleted file mode 100644 index 45e3ee313d8..00000000000 --- a/contracts/src/v0.8/llo-feeds/dev/interfaces/IChannelConfigStore.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -interface IChannelConfigStore is IERC165 { - // function setStagingConfig(bytes32 configDigest, ChannelConfiguration calldata channelConfig) external; - - // function promoteStagingConfig(bytes32 configDigest) external; - - function addChannel(uint32 channelId, ChannelDefinition calldata channelDefinition) external; - - function removeChannel(uint32 channelId) external; - - function getChannelDefinitions(uint32 channelId) external view returns (ChannelDefinition memory); - - // struct ChannelConfiguration { - // bytes32 configDigest; - // } - - struct ChannelDefinition { - // e.g. evm, solana, CosmWasm, kalechain, etc... - uint32 reportFormat; - // Specifies the chain on which this channel can be verified. Currently uses - // CCIP chain selectors, but lots of other schemes are possible as well. - uint64 chainSelector; - // We assume that StreamIDs is always non-empty and that the 0-th stream - // contains the verification price in LINK and the 1-st stream contains the - // verification price in the native coin. - uint32[] streamIDs; - } -} diff --git a/contracts/src/v0.8/llo-feeds/dev/interfaces/IChannelVerifier.sol b/contracts/src/v0.8/llo-feeds/dev/interfaces/IChannelVerifier.sol deleted file mode 100644 index 6bab5912a70..00000000000 --- a/contracts/src/v0.8/llo-feeds/dev/interfaces/IChannelVerifier.sol +++ /dev/null @@ -1,111 +0,0 @@ -// 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 IChannelVerifier 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 offchain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param offchainTransmitters CSA key for the ith Oracle - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - */ - function setConfig( - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external; - - /** - * @notice identical to `setConfig` except with args for sourceChainId and sourceAddress - * @param sourceChainId Chain ID of source config - * @param sourceAddress Address of source config Verifier - * @param newConfigCount Param to force the new config count - * @param signers addresses with which oracles sign the reports - * @param offchainTransmitters CSA key for the ith Oracle - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - */ - function setConfigFromSource( - uint256 sourceChainId, - address sourceAddress, - uint32 newConfigCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) 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 Activates the given feed - * @param feedId Feed ID to activated - * @dev This function can be called by the contract admin to activate a feed - */ - function activateFeed(bytes32 feedId) external; - - /** - * @notice Deactivates the given feed - * @param feedId Feed ID to deactivated - * @dev This function can be called by the contract admin to deactivate a feed - */ - function deactivateFeed(bytes32 feedId) external; - - /** - * @notice returns the latest config digest and epoch - * @return scanLogs indicates whether to rely on the configDigest and epoch - * returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config - */ - function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); -} diff --git a/contracts/src/v0.8/llo-feeds/dev/test/mocks/ExposedChannelVerifier.sol b/contracts/src/v0.8/llo-feeds/dev/test/mocks/ExposedChannelVerifier.sol deleted file mode 100644 index 650b3b4a81e..00000000000 --- a/contracts/src/v0.8/llo-feeds/dev/test/mocks/ExposedChannelVerifier.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -// ExposedChannelVerifier exposes certain internal Verifier -// methods/structures so that golang code can access them, and we get -// reliable type checking on their usage -contract ExposedChannelVerifier { - constructor() {} - - function _configDigestFromConfigData( - 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( - chainId, - contractAddress, - configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - // 0x0009 corresponds to ConfigDigestPrefixLLO in libocr - uint256 prefix = 0x0009 << (256 - 16); // 0x000900..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - function exposedConfigDigestFromConfigData( - 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( - _chainId, - _contractAddress, - _configCount, - _signers, - _offchainTransmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ); - } -} diff --git a/contracts/src/v0.8/llo-feeds/dev/test/mocks/ExposedVerifier.sol b/contracts/src/v0.8/llo-feeds/dev/test/mocks/ExposedVerifier.sol deleted file mode 100644 index 1c004bf3846..00000000000 --- a/contracts/src/v0.8/llo-feeds/dev/test/mocks/ExposedVerifier.sol +++ /dev/null @@ -1,69 +0,0 @@ -// 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/libraries/test/ByteUtilTest.t.sol b/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol index 8b5343866f6..8f11dab0936 100644 --- a/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol @@ -15,7 +15,7 @@ contract ByteUtilTest is Test { bytes4 internal constant MALFORMED_ERROR_SELECTOR = bytes4(keccak256("MalformedData()")); - function test_readUint256Max() public { + function test_readUint256Max() public pure { //read the first 32 bytes uint256 result = B_512._readUint256(0); @@ -23,7 +23,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint256).max); } - function test_readUint192Max() public { + function test_readUint192Max() public pure { //read the first 24 bytes uint256 result = B_512._readUint192(0); @@ -31,7 +31,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint192).max); } - function test_readUint32Max() public { + function test_readUint32Max() public pure { //read the first 4 bytes uint256 result = B_512._readUint32(0); @@ -39,7 +39,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint32).max); } - function test_readUint256Min() public { + function test_readUint256Min() public pure { //read the second 32 bytes uint256 result = B_512._readUint256(32); @@ -47,7 +47,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint256).min); } - function test_readUint192Min() public { + function test_readUint192Min() public pure { //read the second 24 bytes uint256 result = B_512._readUint192(32); @@ -55,7 +55,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint192).min); } - function test_readUint32Min() public { + function test_readUint32Min() public pure { //read the second 4 bytes uint256 result = B_512._readUint32(32); @@ -63,7 +63,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint32).min); } - function test_readUint256MultiWord() public { + function test_readUint256MultiWord() public pure { //read the first 32 bytes uint256 result = B_512._readUint256(31); @@ -71,7 +71,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint256).max << 248); } - function test_readUint192MultiWord() public { + function test_readUint192MultiWord() public pure { //read the first 24 bytes uint256 result = B_512._readUint192(31); @@ -79,7 +79,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint192).max << 184); } - function test_readUint32MultiWord() public { + function test_readUint32MultiWord() public pure { //read the first 4 bytes uint256 result = B_512._readUint32(31); @@ -135,7 +135,7 @@ contract ByteUtilTest is Test { B_EMPTY._readUint32(0); } - function test_readAddress() public { + function test_readAddress() public pure { //read the first 20 bytes address result = B_512._readAddress(0); @@ -143,7 +143,7 @@ contract ByteUtilTest is Test { assertEq(result, address(type(uint160).max)); } - function test_readZeroAddress() public { + function test_readZeroAddress() public pure { //read the first 32 bytes after the first word address result = B_512._readAddress(32); @@ -151,7 +151,7 @@ contract ByteUtilTest is Test { assertEq(result, address(type(uint160).min)); } - function test_readAddressMultiWord() public { + function test_readAddressMultiWord() public pure { //read the first 20 bytes after byte 13 address result = B_512._readAddress(13); 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 38d93de5cb7..08ac1d45f58 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 @@ -11,6 +11,7 @@ import {Math} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/ma import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; import {IDestinationRewardManager} from "./interfaces/IDestinationRewardManager.sol"; import {IDestinationFeeManager} from "./interfaces/IDestinationFeeManager.sol"; +import {IDestinationVerifierFeeManager} from "./interfaces/IDestinationVerifierFeeManager.sol"; /** * @title FeeManager @@ -18,12 +19,20 @@ import {IDestinationFeeManager} from "./interfaces/IDestinationFeeManager.sol"; * @author Austin Born * @notice This contract is used for the handling of fees required for users verifying reports. */ -contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAndVersionInterface { +contract DestinationFeeManager is + IDestinationFeeManager, + IDestinationVerifierFeeManager, + ConfirmedOwner, + TypeAndVersionInterface +{ 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; @@ -150,11 +159,6 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); } - modifier onlyOwnerOrVerifier() { - if (msg.sender != s_verifierAddressList[msg.sender] && msg.sender != owner()) revert Unauthorized(); - _; - } - modifier onlyVerifier() { if (msg.sender != s_verifierAddressList[msg.sender]) revert Unauthorized(); _; @@ -162,26 +166,17 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn /// @inheritdoc TypeAndVersionInterface function typeAndVersion() external pure override returns (string memory) { - return "DestinationFeeManager 1.0.0"; + return "DestinationFeeManager 0.4.0"; } /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - //for each function in IDestinationFeeManager we need to check if it matches the selector return - interfaceId == this.getFeeAndReward.selector || - interfaceId == this.setNativeSurcharge.selector || - interfaceId == this.updateSubscriberDiscount.selector || - interfaceId == this.withdraw.selector || - interfaceId == this.linkAvailableForPayment.selector || - interfaceId == this.payLinkDeficit.selector || - interfaceId == this.addVerifier.selector || - interfaceId == this.removeVerifier.selector || - interfaceId == this.processFee.selector || - interfaceId == this.processFeeBulk.selector || - interfaceId == this.setFeeRecipients.selector; + interfaceId == type(IDestinationFeeManager).interfaceId || + interfaceId == type(IDestinationVerifierFeeManager).interfaceId; } + /// @inheritdoc IDestinationVerifierFeeManager function processFee( bytes32 recipient, bytes calldata payload, @@ -209,7 +204,7 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn } } - /// @inheritdoc IDestinationFeeManager + /// @inheritdoc IDestinationVerifierFeeManager function processFeeBulk( bytes32[] memory poolIds, bytes[] calldata payloads, @@ -304,9 +299,14 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn revert ExpiredReport(); } - //get the discount being applied + //check if feed discount has been 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); @@ -326,11 +326,11 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn return (fee, reward, discount); } - /// @inheritdoc IDestinationFeeManager + /// @inheritdoc IDestinationVerifierFeeManager function setFeeRecipients( bytes32 configDigest, Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external onlyOwnerOrVerifier { + ) external onlyVerifier { i_rewardManager.setRewardRecipients(configDigest, rewardRecipientAndWeights); } @@ -360,6 +360,17 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn 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 IDestinationFeeManager function withdraw(address assetAddress, address recipient, uint192 quantity) external onlyOwner { //address 0 is used to withdraw native in the context of withdrawing @@ -550,8 +561,13 @@ contract DestinationFeeManager is IDestinationFeeManager, ConfirmedOwner, TypeAn /// @inheritdoc IDestinationFeeManager function setRewardManager(address rewardManagerAddress) external onlyOwner { if (rewardManagerAddress == address(0)) revert InvalidAddress(); + + if (!IERC165(rewardManagerAddress).supportsInterface(type(IDestinationRewardManager).interfaceId)) { + revert InvalidAddress(); + } + IERC20(i_linkAddress).approve(address(i_rewardManager), 0); i_rewardManager = IDestinationRewardManager(rewardManagerAddress); - IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); + IERC20(i_linkAddress).approve(address(rewardManagerAddress), type(uint256).max); } } 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 ae40a2385c7..4b4c1f50efd 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 @@ -75,29 +75,21 @@ contract DestinationRewardManager is IDestinationRewardManager, ConfirmedOwner, // @inheritdoc TypeAndVersionInterface function typeAndVersion() external pure override returns (string memory) { - return "RewardManager 1.0.0"; + return "DestinationRewardManager 0.4.0"; } // @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return - interfaceId == this.claimRewards.selector || - interfaceId == this.setRewardRecipients.selector || - interfaceId == this.updateRewardRecipients.selector || - interfaceId == this.payRecipients.selector || - interfaceId == this.addFeeManager.selector || - interfaceId == this.removeFeeManager.selector || - interfaceId == this.getAvailableRewardPoolIds.selector || - interfaceId == this.onFeePaid.selector; + return interfaceId == type(IDestinationRewardManager).interfaceId; } modifier onlyOwnerOrFeeManager() { - if (msg.sender != owner() && msg.sender != s_feeManagerAddressList[msg.sender]) revert Unauthorized(); + if (msg.sender != s_feeManagerAddressList[msg.sender] && msg.sender != owner()) revert Unauthorized(); _; } modifier onlyOwnerOrRecipientInPool(bytes32 poolId) { - if (msg.sender != owner() && s_rewardRecipientWeights[poolId][msg.sender] == 0) revert Unauthorized(); + if (s_rewardRecipientWeights[poolId][msg.sender] == 0 && msg.sender != owner()) revert Unauthorized(); _; } 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 52b2bd7c9a7..8ab0f6acc23 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 @@ -8,7 +8,8 @@ import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/inter import {Common} from "../libraries/Common.sol"; import {IAccessController} from "../../shared/interfaces/IAccessController.sol"; import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; -import {IDestinationFeeManager} from "./interfaces/IDestinationFeeManager.sol"; +import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; +import {IDestinationVerifierFeeManager} from "./interfaces/IDestinationVerifierFeeManager.sol"; // OCR2 standard uint256 constant MAX_NUM_ORACLES = 31; @@ -18,7 +19,12 @@ uint256 constant MAX_NUM_ORACLES = 31; * @author Michael Fletcher * @notice This contract will be used to verify reports based on the oracle signatures. This is not the source verifier which required individual fee configurations, instead, this checks that a report has been signed by one of the configured oracles. */ -contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVersionInterface, IERC165 { +contract DestinationVerifier is + IDestinationVerifier, + IDestinationVerifierProxyVerifier, + ConfirmedOwner, + TypeAndVersionInterface +{ /// @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; @@ -84,9 +90,6 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer /// @notice This error is thrown whenever a config does not exist error DonConfigDoesNotExist(); - /// @notice this error is thrown when the verifierProxy is incorrect when initialising - error VerifierProxyInvalid(); - /// @notice This error is thrown when the activation time is either in the future or less than the current configs error BadActivationTime(); @@ -105,7 +108,8 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer bytes24 indexed donConfigId, address[] signers, uint8 f, - Common.AddressAndWeight[] recipientAddressesAndWeights + Common.AddressAndWeight[] recipientAddressesAndWeights, + uint16 donConfigIndex ); /// @notice This event is emitted when a new fee manager is set @@ -137,18 +141,25 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer i_verifierProxy = IDestinationVerifierProxy(verifierProxy); } - /// @inheritdoc IDestinationVerifier + /// @inheritdoc IDestinationVerifierProxyVerifier function verify( bytes calldata signedReport, bytes calldata parameterPayload, address sender - ) external payable override checkValidProxy checkAccess(sender) returns (bytes memory) { + ) external payable override onlyProxy checkAccess(sender) returns (bytes memory) { (bytes memory verifierResponse, bytes32 donConfigId) = _verify(signedReport, sender); address fm = s_feeManager; if (fm != address(0)) { //process the fee and catch the error - try IDestinationFeeManager(fm).processFee{value: msg.value}(donConfigId, signedReport, parameterPayload, sender) { + try + IDestinationVerifierFeeManager(fm).processFee{value: msg.value}( + donConfigId, + signedReport, + parameterPayload, + sender + ) + { //do nothing } catch { // we purposefully obfuscate the error here to prevent information leaking leading to free verifications @@ -159,12 +170,12 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer return verifierResponse; } - /// @inheritdoc IDestinationVerifier + /// @inheritdoc IDestinationVerifierProxyVerifier function verifyBulk( bytes[] calldata signedReports, bytes calldata parameterPayload, address sender - ) external payable override checkValidProxy checkAccess(sender) returns (bytes[] memory) { + ) external payable override onlyProxy checkAccess(sender) returns (bytes[] memory) { bytes[] memory verifierResponses = new bytes[](signedReports.length); bytes32[] memory donConfigs = new bytes32[](signedReports.length); @@ -178,7 +189,12 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer if (fm != address(0)) { //process the fee and catch the error try - IDestinationFeeManager(fm).processFeeBulk{value: msg.value}(donConfigs, signedReports, parameterPayload, sender) + IDestinationVerifierFeeManager(fm).processFeeBulk{value: msg.value}( + donConfigs, + signedReports, + parameterPayload, + sender + ) { //do nothing } catch { @@ -276,7 +292,7 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer uint8 f, Common.AddressAndWeight[] memory recipientAddressesAndWeights, uint32 activationTime - ) internal checkConfigValid(signers.length, f) onlyOwner { + ) internal { // Duplicate addresses would break protocol rules if (Common._hasDuplicateAddresses(signers)) { revert NonUniqueSignatures(); @@ -304,7 +320,7 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer // Check the activation time is greater than the latest config uint256 donConfigLength = s_donConfigs.length; - if (donConfigLength > 0 && s_donConfigs[donConfigLength - 1].activationTime > activationTime) { + if (donConfigLength > 0 && s_donConfigs[donConfigLength - 1].activationTime >= activationTime) { revert BadActivationTime(); } @@ -315,22 +331,22 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer // We may want to register these later or skip this step in the unlikely scenario they've previously been registered in the RewardsManager if (recipientAddressesAndWeights.length != 0) { - IDestinationFeeManager(s_feeManager).setFeeRecipients(donConfigId, recipientAddressesAndWeights); + if (s_feeManager == address(0)) { + revert FeeManagerInvalid(); + } + IDestinationVerifierFeeManager(s_feeManager).setFeeRecipients(donConfigId, recipientAddressesAndWeights); } // push the DonConfig s_donConfigs.push(DonConfig(donConfigId, f, true, activationTime)); - emit ConfigSet(donConfigId, signers, f, recipientAddressesAndWeights); + emit ConfigSet(donConfigId, signers, f, recipientAddressesAndWeights, uint16(donConfigLength)); } /// @inheritdoc IDestinationVerifier function setFeeManager(address feeManager) external override onlyOwner { - if ( - !IERC165(feeManager).supportsInterface(IDestinationFeeManager.processFee.selector) || - !IERC165(feeManager).supportsInterface(IDestinationFeeManager.processFeeBulk.selector) || - !IERC165(feeManager).supportsInterface(IDestinationFeeManager.setFeeRecipients.selector) - ) revert FeeManagerInvalid(); + if (!IERC165(feeManager).supportsInterface(type(IDestinationVerifierFeeManager).interfaceId)) + revert FeeManagerInvalid(); address oldFeeManager = s_feeManager; s_feeManager = feeManager; @@ -400,7 +416,7 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer _; } - modifier checkValidProxy() { + modifier onlyProxy() { if (address(i_verifierProxy) != msg.sender) { revert AccessForbidden(); } @@ -416,19 +432,12 @@ contract DestinationVerifier is IDestinationVerifier, ConfirmedOwner, TypeAndVer /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { return - interfaceId == this.verify.selector || - interfaceId == this.verifyBulk.selector || - interfaceId == this.s_accessController.selector || - interfaceId == this.s_feeManager.selector || - interfaceId == this.setConfig.selector || - interfaceId == this.setConfigWithActivationTime.selector || - interfaceId == this.setFeeManager.selector || - interfaceId == this.setAccessController.selector || - interfaceId == this.setConfigActive.selector; + interfaceId == type(IDestinationVerifier).interfaceId || + interfaceId == type(IDestinationVerifierProxyVerifier).interfaceId; } /// @inheritdoc TypeAndVersionInterface function typeAndVersion() external pure override returns (string memory) { - return "DestinationVerifier 1.0.0"; + 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 1a5c62b4292..6790883ba31 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 @@ -5,16 +5,16 @@ import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; -import {IDestinationVerifier} from "./interfaces/IDestinationVerifier.sol"; +import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; /** * @title DestinationVerifierProxy * @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, IERC165 { +contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { /// @notice The active verifier for this proxy - IDestinationVerifier private s_verifier; + IDestinationVerifierProxyVerifier private s_verifier; /// @notice This error is thrown whenever a zero address is passed error ZeroAddress(); @@ -26,7 +26,7 @@ contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, /// @inheritdoc TypeAndVersionInterface function typeAndVersion() external pure override returns (string memory) { - return "DestinationVerifierProxy 1.0.0"; + return "DestinationVerifierProxy 0.4.0"; } /// @inheritdoc IDestinationVerifierProxy @@ -45,14 +45,10 @@ contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, /// @inheritdoc IDestinationVerifierProxy function setVerifier(address verifierAddress) external onlyOwner { //check it supports the functions we need - if ( - !IERC165(verifierAddress).supportsInterface(IDestinationVerifier.s_accessController.selector) || - !IERC165(verifierAddress).supportsInterface(IDestinationVerifier.s_feeManager.selector) || - !IERC165(verifierAddress).supportsInterface(IDestinationVerifier.verify.selector) || - !IERC165(verifierAddress).supportsInterface(IDestinationVerifier.verifyBulk.selector) - ) revert VerifierInvalid(verifierAddress); + if (!IERC165(verifierAddress).supportsInterface(type(IDestinationVerifierProxyVerifier).interfaceId)) + revert VerifierInvalid(verifierAddress); - s_verifier = IDestinationVerifier(verifierAddress); + s_verifier = IDestinationVerifierProxyVerifier(verifierAddress); } /// @inheritdoc IDestinationVerifierProxy @@ -69,11 +65,6 @@ contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return - interfaceId == this.setVerifier.selector || - interfaceId == this.verify.selector || - interfaceId == this.verifyBulk.selector || - interfaceId == this.s_feeManager.selector || - interfaceId == this.s_accessController.selector; + return interfaceId == type(IDestinationVerifierProxy).interfaceId; } } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol index f92e7cd146b..00420a4edb7 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol @@ -33,6 +33,14 @@ interface IDestinationFeeManager is IERC165 { */ function updateSubscriberDiscount(address subscriber, bytes32 feedId, address token, uint64 discount) 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 Withdraws any native or LINK rewards to the owner address * @param assetAddress address of the asset to withdraw @@ -71,44 +79,6 @@ interface IDestinationFeeManager is IERC165 { */ function setRewardManager(address rewardManager) external; - /** - * @notice Handles fees for a report from the subscriber and manages rewards - * @param poolId pool id of the pool to pay into - * @param payload report to process the fee for - * @param parameterPayload fee payload - * @param subscriber address of the fee will be applied - */ - function processFee( - bytes32 poolId, - 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 poolIds pool ids of the pool to pay into - * @param payloads reports to process - * @param parameterPayload fee payload - * @param subscriber address of the user to process fee for - */ - function processFeeBulk( - bytes32[] memory poolIds, - 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; - /** * @notice The structure to hold a fee and reward to verify a report * @param digest the digest linked to the fee and reward diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol index 69516f6e924..041a8c8f72c 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol @@ -2,36 +2,9 @@ pragma solidity 0.8.19; import {Common} from "../../libraries/Common.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -interface IDestinationVerifier { - /** - * @notice Verifies that the data encoded has been signed correctly using the signatures included within the payload. - * @param signedReport The encoded data to be verified. - * @param parameterPayload The encoded parameters to be used in the verification and billing process. - * @param sender The address that requested to verify the contract.Used for logging and applying the fee. - * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. - * @return verifierResponse The encoded verified response. - */ - function verify( - bytes calldata signedReport, - bytes calldata parameterPayload, - address sender - ) external payable returns (bytes memory verifierResponse); - - /** - * @notice Bulk verifies that the data encoded has been signed correctly using the signatures included within the payload. - * @param signedReports The encoded data to be verified. - * @param parameterPayload The encoded parameters to be used in the verification and billing process. - * @param sender The address that requested to verify the contract. Used for logging and applying the fee. - * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. - * @return verifiedReports The encoded verified responses. - */ - function verifyBulk( - bytes[] calldata signedReports, - bytes calldata parameterPayload, - address sender - ) external payable returns (bytes[] memory verifiedReports); - +interface IDestinationVerifier is IERC165 { /** * @notice sets off-chain reporting protocol configuration incl. participating oracles * @param signers addresses with which oracles sign the reports @@ -81,18 +54,4 @@ interface IDestinationVerifier { * @notice Removes the latest config */ function removeLatestConfig() external; - - /* - * @notice Returns the reward manager - * @return IDestinationRewardManager - */ - // solhint-disable-next-line func-name-mixedcase - function s_feeManager() external view returns (address); - - /** - * @notice Returns the access controller - * @return IDestinationFeeManager - */ - // solhint-disable-next-line func-name-mixedcase - function s_accessController() external view returns (address); } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol new file mode 100644 index 00000000000..291f3706b3e --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol @@ -0,0 +1,45 @@ +// 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 IDestinationVerifierFeeManager is IERC165 { + /** + * @notice Handles fees for a report from the subscriber and manages rewards + * @param poolId pool id of the pool to pay into + * @param payload report to process the fee for + * @param parameterPayload fee payload + * @param subscriber address of the fee will be applied + */ + function processFee( + bytes32 poolId, + 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 poolIds pool ids of the pool to pay into + * @param payloads reports to process + * @param parameterPayload fee payload + * @param subscriber address of the user to process fee for + */ + function processFeeBulk( + bytes32[] memory poolIds, + 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.4.0/interfaces/IDestinationVerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol index a88349b3014..e0dcb30d541 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -interface IDestinationVerifierProxy { +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IDestinationVerifierProxy is IERC165 { /** * @notice Verifies that the data encoded has been signed * correctly by routing to the verifier, and bills the user if applicable. diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol new file mode 100644 index 00000000000..a957f8f928d --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IDestinationVerifierProxyVerifier is IERC165 { + /** + * @notice Verifies that the data encoded has been signed correctly using the signatures included within the payload. + * @param signedReport The encoded data to be verified. + * @param parameterPayload The encoded parameters to be used in the verification and billing process. + * @param sender The address that requested to verify the contract.Used for logging and applying the fee. + * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. + * @return verifierResponse The encoded verified response. + */ + function verify( + bytes calldata signedReport, + bytes calldata parameterPayload, + address sender + ) external payable returns (bytes memory verifierResponse); + + /** + * @notice Bulk verifies that the data encoded has been signed correctly using the signatures included within the payload. + * @param signedReports The encoded data to be verified. + * @param parameterPayload The encoded parameters to be used in the verification and billing process. + * @param sender The address that requested to verify the contract. Used for logging and applying the fee. + * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. + * @return verifiedReports The encoded verified responses. + */ + function verifyBulk( + bytes[] calldata signedReports, + bytes calldata parameterPayload, + address sender + ) external payable returns (bytes[] memory verifiedReports); + + /* + * @notice Returns the reward manager + * @return IDestinationRewardManager + */ + // solhint-disable-next-line func-name-mixedcase + function s_feeManager() external view returns (address); + + /** + * @notice Returns the access controller + * @return IDestinationFeeManager + */ + // solhint-disable-next-line func-name-mixedcase + function s_accessController() external view returns (address); +} diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol index 8b70e5b2b33..38b1bad2171 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol @@ -108,7 +108,7 @@ contract BaseDestinationFeeManagerTest is Test { ); //link the feeManager to the proxy - feeManagerProxy.setDestinationFeeManager(feeManager); + feeManagerProxy.setDestinationFeeManager(address(feeManager)); //link the feeManager to the reward manager rewardManager.addFeeManager(address(feeManager)); @@ -147,6 +147,18 @@ contract BaseDestinationFeeManagerTest is Test { 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; diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol index 30be694df2c..ddd3ac5a8ea 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol @@ -603,4 +603,118 @@ contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { //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.4.0/test/mocks/DestinationFeeManagerProxy.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol index 46ec7fff3b5..7dde878321e 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {IDestinationFeeManager} from "../../interfaces/IDestinationFeeManager.sol"; +import {IDestinationVerifierFeeManager} from "../../interfaces/IDestinationVerifierFeeManager.sol"; contract DestinationFeeManagerProxy { - IDestinationFeeManager internal s_feeManager; + IDestinationVerifierFeeManager internal s_feeManager; function processFee(bytes32 poolId, bytes calldata payload, bytes calldata parameterPayload) public payable { s_feeManager.processFee{value: msg.value}(poolId, payload, parameterPayload, msg.sender); @@ -18,7 +18,7 @@ contract DestinationFeeManagerProxy { s_feeManager.processFeeBulk{value: msg.value}(poolIds, payloads, parameterPayload, msg.sender); } - function setDestinationFeeManager(IDestinationFeeManager feeManager) public { - s_feeManager = feeManager; + function setDestinationFeeManager(address feeManager) public { + s_feeManager = IDestinationVerifierFeeManager(feeManager); } } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol index c93c9dc6d9a..2851057d0e8 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol @@ -33,6 +33,6 @@ contract DestinationVerifierProxyInitializeVerifierTest is BaseTest { function test_correctlySetsVersion() public view { string memory version = s_verifierProxy.typeAndVersion(); - assertEq(version, "DestinationVerifierProxy 1.0.0"); + assertEq(version, "DestinationVerifierProxy 0.4.0"); } } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol index f6e5fd1f213..4f96e4969a3 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol @@ -64,6 +64,7 @@ contract DestinationVerifierSetConfigTest is BaseTest { bytes24 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); address temp = signerAddrs[0]; signerAddrs[0] = signerAddrs[1]; @@ -80,9 +81,13 @@ contract DestinationVerifierSetConfigTest is BaseTest { s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + // testing adding same set of Signers but different FAULT_TOLERENCE does not result in DonConfigAlreadyExists revert s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + // testing adding a different set of Signers with same FAULT_TOLERENCE does not result in DonConfigAlreadyExists revert address[] memory signerAddrsMinusOne = new address[](signerAddrs.length - 1); for (uint256 i = 0; i < signerAddrs.length - 1; i++) { @@ -96,6 +101,7 @@ contract DestinationVerifierSetConfigTest is BaseTest { address[] memory signerAddrs = _getSignerAddresses(signers); s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); bytes24 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); @@ -156,4 +162,15 @@ contract DestinationVerifierSetConfigTest is BaseTest { oldActivationTime ); } + + function test_setConfigWithActivationTimeTheSameAsLatestConfigShouldFail() public { + // setting a config older than the latest current config should fail + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + // sets a config with timestamp = block.timestamp + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + // setting a config with ealier timestamp retuls in failure + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol index dd157d2a475..476acbf806d 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {IDestinationVerifier} from "../../../v0.4.0/interfaces/IDestinationVerifier.sol"; +import {IDestinationVerifierProxyVerifier} from "../../../v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol"; contract DestinationVerifierConstructorTest is BaseTest { bytes32[3] internal s_reportContext; @@ -16,7 +18,7 @@ contract DestinationVerifierConstructorTest is BaseTest { DestinationVerifier v = new DestinationVerifier(address(s_verifierProxy)); assertEq(v.owner(), ADMIN); string memory typeAndVersion = s_verifier.typeAndVersion(); - assertEq(typeAndVersion, "DestinationVerifier 1.0.0"); + assertEq(typeAndVersion, "DestinationVerifier 0.4.0"); } function test_falseIfIsNotCorrectInterface() public view { @@ -25,7 +27,8 @@ contract DestinationVerifierConstructorTest is BaseTest { } function test_trueIfIsCorrectInterface() public view { - bool isInterface = s_verifier.supportsInterface(DestinationVerifier.verify.selector); + bool isInterface = s_verifier.supportsInterface(type(IDestinationVerifier).interfaceId) && + s_verifier.supportsInterface(type(IDestinationVerifierProxyVerifier).interfaceId); assertEq(isInterface, true); } } diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol index 658bf4f127c..e72cfd09b65 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol @@ -313,6 +313,7 @@ contract VerifierVerifyTest is BaseTest { address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); // Config1 s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); signersSubset2[0] = signers[7]; @@ -326,6 +327,7 @@ contract VerifierVerifyTest is BaseTest { address[] memory signersAddrSubset2 = _getSignerAddresses(signersSubset2); // Config2 s_verifier.setConfig(signersAddrSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); BaseTest.Signer[] memory signersSubset3 = new BaseTest.Signer[](7); signersSubset3[0] = signers[30]; @@ -339,6 +341,7 @@ contract VerifierVerifyTest is BaseTest { address[] memory signersAddrSubset3 = _getSignerAddresses(signersSubset3); // Config3 s_verifier.setConfig(signersAddrSubset3, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); V3Report memory report = V3Report({ feedId: FEED_ID_V3, 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 new file mode 100644 index 00000000000..f5e5040bb8f --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {IChannelConfigStore} from "./interfaces/IChannelConfigStore.sol"; +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; + +contract ChannelConfigStore is ConfirmedOwner, IChannelConfigStore, TypeAndVersionInterface { + event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); + + constructor() ConfirmedOwner(msg.sender) {} + + /// @notice The version of a channel definition keyed by DON ID + // Increments by 1 on every update + mapping(uint256 => uint256) internal s_channelDefinitionVersions; + + function setChannelDefinitions(uint32 donId, string calldata url, bytes32 sha) external onlyOwner { + uint32 newVersion = uint32(++s_channelDefinitionVersions[uint256(donId)]); + emit NewChannelDefinition(donId, newVersion, url, sha); + } + + function typeAndVersion() external pure override returns (string memory) { + return "ChannelConfigStore 0.0.1"; + } + + function supportsInterface(bytes4 interfaceId) external pure returns (bool) { + return interfaceId == type(IChannelConfigStore).interfaceId; + } +} 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 new file mode 100644 index 00000000000..96be15fd6be --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IConfigurator} from "./interfaces/IConfigurator.sol"; + +// OCR2 standard +uint256 constant MAX_NUM_ORACLES = 31; + +// Subsequent versions of the onchain config must be backwards compatible and only append fields +uint256 constant MIN_SUPPORTED_ONCHAIN_CONFIG_VERSION = 1; + +/** + * @title Configurator + * @author samsondav + * @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 { + /// @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 the onchainConfig length is invalid + /// (must be at least 64 bytes) + /// @param onchainConfigLength The (wrong) length of the onchainConfig + error InvalidOnchainLength(uint256 onchainConfigLength); + + /// @notice This error is thrown if the onchainConfig version is too old. + /// @param version The version of the onchainConfig + error UnsupportedOnchainConfigVersion(uint256 version); + + /// @notice This event is emitted when a production config is set with a non-zero predecessor config digest in the on-chain config. + /// @param predecessorConfigDigest The predecessor config digest + error NonZeroPredecessorConfigDigest(bytes32 predecessorConfigDigest); + + /// @notice This event is emitted when a staging config is set with a predecessor config digest that does not match the current production config digest. + /// @param predecessorConfigDigest The predecessor config digest + error InvalidPredecessorConfigDigest(bytes32 predecessorConfigDigest); + + /// @notice This event is emitted during promoteStagingConfig if the isGreenProduction flag does not match the contract state + /// @param configId The configId + /// @param isGreenProductionContractState The current (correct) isGreenProduction state according to the contract + error IsGreenProductionMustMatchContractState(bytes32 configId, bool isGreenProductionContractState); + + /// @notice This event is emitted during promoteStagingConfig if the configId has never been set + /// @param configId The configId that has never been set + error ConfigUnset(bytes32 configId); + + /// @notice This event is emitted during promoteStagingConfig if the configId has never been set as a staging config + /// @param configId The configId that has never been set as a staging config + /// @param isGreenProduction The isGreenProduction flag + error ConfigUnsetStaging(bytes32 configId, bool isGreenProduction); + + /// @notice This event is emitted during promoteStagingConfig if the configId has never been set as a production config + /// @param configId The configId that has never been set as a production config + /// @param isGreenProduction The isGreenProduction flag + error ConfigUnsetProduction(bytes32 configId, bool isGreenProduction); + + struct ConfigurationState { + // The number of times a configuration (either staging or production) has + // been set for this configId + uint64 configCount; + // The block number of the block the last time + // the configuration was updated. + uint32 latestConfigBlockNumber; + // isGreenProduction is a bit flip that indicates whether blue is production + // exactly one of blue/green must be production at all times. + // 0 -> blue is production + // 1 -> green is production + // + // So, to clarify, if isGreenProduction is false (initial state) then: + // [0](blue) is production and [1](green) is staging/retired + // + // and if isGreenProduction is true then: + // [0](blue) is staging/retired and [1](green) is production + // State is swapped every time a staging config is promoted to production. + bool isGreenProduction; + // The digest of the current configurations (0 is always blue, 1 is always green) + bytes32[2] configDigest; + } + + constructor() ConfirmedOwner(msg.sender) {} + + /// @notice Configuration states keyed on config ID + /// @dev The first element is the blue configuration state + /// and the second element is the green configuration state + mapping(bytes32 => ConfigurationState) internal s_configurationStates; + + /// @inheritdoc IConfigurator + function setProductionConfig( + bytes32 configId, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override checkConfigValid(signers.length, f) onlyOwner { + if (onchainConfig.length < 64) revert InvalidOnchainLength(onchainConfig.length); + + // Ensure that predecessorConfigDigest is unset and version is correct + uint256 version; + bytes32 predecessorConfigDigest; + assembly { + version := mload(add(onchainConfig, 32)) + predecessorConfigDigest := mload(add(onchainConfig, 64)) + } + if (version < MIN_SUPPORTED_ONCHAIN_CONFIG_VERSION) revert UnsupportedOnchainConfigVersion(version); + if (predecessorConfigDigest != 0) revert NonZeroPredecessorConfigDigest(predecessorConfigDigest); + + _setConfig( + configId, + block.chainid, + address(this), + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + true + ); + } + + /// @inheritdoc IConfigurator + function setStagingConfig( + bytes32 configId, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override checkConfigValid(signers.length, f) onlyOwner { + if (onchainConfig.length < 64) revert InvalidOnchainLength(onchainConfig.length); + + // Ensure that predecessorConfigDigest is set and corresponds to an + // existing production instance + uint256 version; + bytes32 predecessorConfigDigest; + assembly { + version := mload(add(onchainConfig, 32)) + predecessorConfigDigest := mload(add(onchainConfig, 64)) + } + if (version < MIN_SUPPORTED_ONCHAIN_CONFIG_VERSION) revert UnsupportedOnchainConfigVersion(version); + + ConfigurationState memory configurationState = s_configurationStates[configId]; + if ( + predecessorConfigDigest != + s_configurationStates[configId].configDigest[configurationState.isGreenProduction ? 1 : 0] + ) revert InvalidPredecessorConfigDigest(predecessorConfigDigest); + + _setConfig( + configId, + block.chainid, + address(this), + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + false + ); + } + + /// @inheritdoc IConfigurator + // This will trigger the following: + // - Offchain ShouldRetireCache will start returning true for the old (production) + // protocol instance + // - Once the old production instance retires it will generate a handover + // retirement report + // - The staging instance will become the new production instance once + // any honest oracle that is on both instances forward the retirement + // report from the old instance to the new instance via the + // PredecessorRetirementReportCache + // + // Note: the promotion flow only works if the previous production instance + // is working correctly & generating reports. If that's not the case, the + // owner is expected to "setProductionConfig" directly instead. This will + // cause "gaps" to be created, but that seems unavoidable in such a scenario. + function promoteStagingConfig(bytes32 configId, bool isGreenProduction) external onlyOwner { + ConfigurationState storage configurationState = s_configurationStates[configId]; + if (isGreenProduction != configurationState.isGreenProduction) + revert IsGreenProductionMustMatchContractState(configId, !isGreenProduction); + if (configurationState.configCount == 0) revert ConfigUnset(configId); + if (configurationState.configDigest[isGreenProduction ? 0 : 1] == bytes32(0)) + revert ConfigUnsetStaging(configId, isGreenProduction); + bytes32 retiredConfigDigest = configurationState.configDigest[isGreenProduction ? 1 : 0]; + if (retiredConfigDigest == bytes32(0)) revert ConfigUnsetProduction(configId, isGreenProduction); + + configurationState.isGreenProduction = !isGreenProduction; // flip blue<->green + emit PromoteStagingConfig(configId, retiredConfigDigest, !isGreenProduction); + } + + /// @notice Sets config based on the given arguments + /// @param configId config ID to set config for + /// @param sourceChainId Chain ID of source config + /// @param sourceAddress Address of source config Verifier + /// @param signers addresses with which oracles sign the reports + /// @param offchainTransmitters CSA key for the ith Oracle + /// @param f number of faulty oracles the system can tolerate + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version number for offchainEncoding schema + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + function _setConfig( + bytes32 configId, + uint256 sourceChainId, + address sourceAddress, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + bool isProduction + ) internal { + ConfigurationState storage configurationState = s_configurationStates[configId]; + + uint64 newConfigCount = ++configurationState.configCount; + + bytes32 configDigest = _configDigestFromConfigData( + configId, + sourceChainId, + sourceAddress, + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + if (isProduction) { + emit ProductionConfigSet( + configId, + configurationState.latestConfigBlockNumber, + configDigest, + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + configurationState.isGreenProduction + ); + s_configurationStates[configId].configDigest[configurationState.isGreenProduction ? 1 : 0] = configDigest; + } else { + emit StagingConfigSet( + configId, + configurationState.latestConfigBlockNumber, + configDigest, + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + configurationState.isGreenProduction + ); + s_configurationStates[configId].configDigest[configurationState.isGreenProduction ? 0 : 1] = configDigest; + } + + configurationState.latestConfigBlockNumber = uint32(block.number); + } + + /// @notice Generates the config digest from config data + /// @param configId config ID to set config for + /// @param sourceChainId Chain ID of configurator contract + /// @param sourceAddress Address of configurator contract + /// @param configCount ordinal number of this config setting among all config settings over the life of this contract + /// @param signers ith element is address ith oracle uses to sign a report + /// @param offchainTransmitters ith element is address ith oracle used to transmit reports (in this case used for flexible additional field, such as CSA pub keys) + /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + /// @dev This function is a modified version of the method from OCR2Abstract + 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); // 0xFFFF00..00 + // 0x0009 corresponds to ConfigDigestPrefixLLO in libocr + uint256 prefix = 0x0009 << (256 - 16); // 0x000900..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool isVerifier) { + return interfaceId == type(IConfigurator).interfaceId; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "Configurator 0.5.0"; + } + + 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); + _; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol new file mode 100644 index 00000000000..8628e3c1d51 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IChannelConfigStore is IERC165 { + function setChannelDefinitions(uint32 donId, string calldata url, bytes32 sha) external; +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IConfigurator.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IConfigurator.sol new file mode 100644 index 00000000000..5f9b14b29c5 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IConfigurator.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +interface IConfigurator { + /// @notice This event is emitted whenever a new production configuration is set for a feed. It triggers a new run of the offchain reporting protocol. + event ProductionConfigSet( + bytes32 indexed configId, + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + bytes[] signers, + bytes32[] offchainTransmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig, + bool isGreenProduction + ); + + /// @notice This event is emitted whenever a new staging configuration is set for a feed. It triggers a new run of the offchain reporting protocol. + event StagingConfigSet( + bytes32 indexed configId, + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + bytes[] signers, + bytes32[] offchainTransmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig, + bool isGreenProduction + ); + + event PromoteStagingConfig(bytes32 indexed configId, bytes32 indexed retiredConfigDigest, bool isGreenProduction); + + /// @notice Promotes the staging configuration to production + // currentState must match the current state for the given configId (prevents + // accidentally double-flipping if same transaction is sent twice) + function promoteStagingConfig(bytes32 configId, bool currentState) external; + + function setProductionConfig( + bytes32 configId, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + + function setStagingConfig( + bytes32 configId, + bytes[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol new file mode 100644 index 00000000000..afea37f48a3 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {IChannelConfigStore} from "../interfaces/IChannelConfigStore.sol"; +import {Test} from "forge-std/Test.sol"; +import {ChannelConfigStore} from "../ChannelConfigStore.sol"; +import {ExposedChannelConfigStore} from "./mocks/ExposedChannelConfigStore.sol"; + +/** + * @title ChannelConfigStoreTest + * @author samsondav + * @notice Base class for ChannelConfigStore tests + */ +contract ChannelConfigStoreTest is Test { + ExposedChannelConfigStore public channelConfigStore; + event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); + + function setUp() public virtual { + channelConfigStore = new ExposedChannelConfigStore(); + } + + function testTypeAndVersion() public view { + assertEq(channelConfigStore.typeAndVersion(), "ChannelConfigStore 0.0.1"); + } + + function testSupportsInterface() public view { + assertTrue(channelConfigStore.supportsInterface(type(IChannelConfigStore).interfaceId)); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + + vm.startPrank(address(2)); + channelConfigStore.setChannelDefinitions(42, "url", keccak256("sha")); + } + + function testSetChannelDefinitions() public { + vm.expectEmit(); + emit NewChannelDefinition(42, 1, "url", keccak256("sha")); + channelConfigStore.setChannelDefinitions(42, "url", keccak256("sha")); + + vm.expectEmit(); + emit NewChannelDefinition(42, 2, "url2", keccak256("sha2")); + channelConfigStore.setChannelDefinitions(42, "url2", keccak256("sha2")); + + assertEq(channelConfigStore.exposedReadChannelDefinitionStates(42), uint32(2)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/BaseConfiguratorTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/BaseConfiguratorTest.t.sol new file mode 100644 index 00000000000..fb44c1f1981 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/BaseConfiguratorTest.t.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {IConfigurator} from "../../interfaces/IConfigurator.sol"; +import {Test} from "forge-std/Test.sol"; +import {Configurator} from "../../Configurator.sol"; +import {ExposedConfigurator} from "../mocks/ExposedConfigurator.sol"; +import {ExposedChannelConfigStore} from "../mocks/ExposedChannelConfigStore.sol"; + +/** + * @title ConfiguratorTest + * @author samsondav + * @notice Base class for Configurator tests + */ +contract BaseTest is Test { + uint256 internal constant MAX_ORACLES = 31; + address internal constant USER = address(2); + bytes32 internal constant CONFIG_ID_1 = (keccak256("CONFIG_ID_1")); + uint8 internal constant FAULT_TOLERANCE = 10; + uint64 internal constant OFFCHAIN_CONFIG_VERSION = 1; + + bytes32[] internal s_offchaintransmitters; + bool private s_baseTestInitialized; + + Configurator internal s_configurator; + ExposedConfigurator internal s_exposedConfigurator; + + event ProductionConfigSet( + bytes32 indexed configId, + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + bytes[] signers, + bytes32[] offchainTransmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig, + bool isGreenProduction + ); + event StagingConfigSet( + bytes32 indexed configId, + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + bytes[] signers, + bytes32[] offchainTransmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig, + bool isGreenProduction + ); + event PromoteStagingConfig(bytes32 indexed configId, bytes32 indexed retiredConfigDigest, bool isGreenProduction); + + bytes[MAX_ORACLES] internal s_signers; + + function setUp() public virtual { + // BaseTest.setUp may be called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + s_configurator = new Configurator(); + s_exposedConfigurator = new ExposedConfigurator(); + + for (uint256 i; i < MAX_ORACLES; i++) { + bytes memory mockSigner = abi.encodePacked(i + 1); + s_signers[i] = mockSigner; + } + + for (uint256 i; i < MAX_ORACLES; i++) { + s_offchaintransmitters.push(bytes32(i + 1)); + } + } + + function _getSigners(uint256 numSigners) internal view returns (bytes[] memory) { + bytes[] memory signers = new bytes[](numSigners); + for (uint256 i; i < numSigners; i++) { + signers[i] = s_signers[i]; + } + return signers; + } + + function _getOffchainTransmitters(uint256 numTransmitters) internal pure returns (bytes32[] memory) { + bytes32[] memory transmitters = new bytes32[](numTransmitters); + for (uint256 i; i < numTransmitters; i++) { + transmitters[i] = bytes32(101 + i); + } + return transmitters; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorPromoteStagingConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorPromoteStagingConfigTest.t.sol new file mode 100644 index 00000000000..604c9d266eb --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorPromoteStagingConfigTest.t.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseConfiguratorTest.t.sol"; +import {Configurator} from "../../Configurator.sol"; + +contract ConfiguratorPromoteStagingConfigTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.startPrank(USER); + + vm.expectRevert("Only callable by owner"); + + s_configurator.promoteStagingConfig(CONFIG_ID_1, false); + } + + function test_revertsIfIsGreenProductionDoesNotMatchContractState() public { + vm.expectRevert( + abi.encodeWithSelector(Configurator.IsGreenProductionMustMatchContractState.selector, CONFIG_ID_1, false) + ); + s_configurator.promoteStagingConfig(CONFIG_ID_1, true); + } + + function test_revertsIfNoConfigHasEverBeenSetWithThisConfigId() public { + vm.expectRevert(abi.encodeWithSelector(Configurator.ConfigUnset.selector, keccak256("nonExistentConfigId"))); + s_configurator.promoteStagingConfig(keccak256("nonExistentConfigId"), false); + } + + function test_revertsIfStagingConfigDigestIsZero() public { + // isGreenProduction = false + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState(1, uint32(block.number), false, [bytes32(0), bytes32(0)]) + ); + + vm.expectRevert(abi.encodeWithSelector(Configurator.ConfigUnsetStaging.selector, CONFIG_ID_1, false)); + s_exposedConfigurator.promoteStagingConfig(CONFIG_ID_1, false); + + // isGreenProduction = true + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState(1, uint32(block.number), true, [bytes32(0), bytes32(0)]) + ); + + vm.expectRevert(abi.encodeWithSelector(Configurator.ConfigUnsetStaging.selector, CONFIG_ID_1, true)); + s_exposedConfigurator.promoteStagingConfig(CONFIG_ID_1, true); + } + + function test_revertsIfProductionConfigDigestIsZero() public { + // isGreenProduction = false + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState(1, uint32(block.number), false, [bytes32(0), keccak256("stagingConfigDigest")]) + ); + + vm.expectRevert(abi.encodeWithSelector(Configurator.ConfigUnsetProduction.selector, CONFIG_ID_1, false)); + s_exposedConfigurator.promoteStagingConfig(CONFIG_ID_1, false); + + // isGreenProduction = true + + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState(1, uint32(block.number), true, [keccak256("stagingConfigDigest"), bytes32(0)]) + ); + + vm.expectRevert(abi.encodeWithSelector(Configurator.ConfigUnsetProduction.selector, CONFIG_ID_1, true)); + s_exposedConfigurator.promoteStagingConfig(CONFIG_ID_1, true); + } + + function test_promotesStagingConfig() public { + // isGreenProduction = false + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState( + 1, + uint32(block.number), + false, + [keccak256("productionConfigDigest"), keccak256("stagingConfigDigest")] + ) + ); + + vm.expectEmit(); + emit PromoteStagingConfig(CONFIG_ID_1, keccak256("productionConfigDigest"), true); + + s_exposedConfigurator.promoteStagingConfig(CONFIG_ID_1, false); + assertEq(s_exposedConfigurator.exposedReadConfigurationStates(CONFIG_ID_1).isGreenProduction, true); + + // isGreenProduction = true + + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState( + 1, + uint32(block.number), + true, + [keccak256("stagingConfigDigest"), keccak256("productionConfigDigest")] + ) + ); + + vm.expectEmit(); + emit PromoteStagingConfig(CONFIG_ID_1, keccak256("productionConfigDigest"), false); + + s_exposedConfigurator.promoteStagingConfig(CONFIG_ID_1, true); + assertEq(s_exposedConfigurator.exposedReadConfigurationStates(CONFIG_ID_1).isGreenProduction, false); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetProductionConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetProductionConfigTest.t.sol new file mode 100644 index 00000000000..c4c177ef4c6 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetProductionConfigTest.t.sol @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseConfiguratorTest.t.sol"; +import {Configurator} from "../../Configurator.sol"; + +contract ConfiguratorSetProductionConfigTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + bytes[] memory signers = _getSigners(MAX_ORACLES); + + vm.startPrank(USER); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfSetWithTooManySigners() public { + bytes[] memory signers = new bytes[](MAX_ORACLES + 1); + vm.expectRevert(abi.encodeWithSelector(Configurator.ExcessSigners.selector, signers.length, MAX_ORACLES)); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfFaultToleranceIsZero() public { + vm.expectRevert(abi.encodeWithSelector(Configurator.FaultToleranceMustBePositive.selector)); + bytes[] memory signers = _getSigners(MAX_ORACLES); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + 0, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfNotEnoughSigners() public { + bytes[] memory signers = _getSigners(2); + + vm.expectRevert( + abi.encodeWithSelector(Configurator.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) + ); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfOnchainConfigIsInvalid() public { + bytes[] memory signers = _getSigners(4); + bytes32[] memory offchainTransmitters = _getOffchainTransmitters(4); + bytes memory onchainConfig = bytes(""); + uint8 f = 1; + bytes memory offchainConfig = abi.encodePacked(keccak256("offchainConfig")); + + vm.expectRevert(abi.encodeWithSelector(Configurator.InvalidOnchainLength.selector, onchainConfig.length)); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + onchainConfig = abi.encode(uint256(0), bytes32(0)); + + vm.expectRevert(abi.encodeWithSelector(Configurator.UnsupportedOnchainConfigVersion.selector, uint256(0))); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + onchainConfig = abi.encode( + uint256(1), + keccak256("any non-zero predecessor config digest is invalid for production") + ); + + vm.expectRevert( + abi.encodeWithSelector( + Configurator.NonZeroPredecessorConfigDigest.selector, + keccak256("any non-zero predecessor config digest is invalid for production") + ) + ); + s_configurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + } + + function test_supportsHigherVersionsIgnoringExcessOnchainConfig() public { + bytes[] memory signers = _getSigners(4); + bytes32[] memory offchainTransmitters = _getOffchainTransmitters(4); + uint8 f = 1; + bytes memory onchainConfig = abi.encodePacked(uint256(2), bytes32(0), keccak256("some rubbish")); + bytes memory offchainConfig = abi.encodePacked(keccak256("offchainConfig")); + + // initial block number + vm.roll(5); + + bytes32 cd1 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + // when isGreenProduction=false + + vm.expectEmit(); + emit ProductionConfigSet( + CONFIG_ID_1, + 0, + cd1, + 1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + false + ); + + s_exposedConfigurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + } + + function test_correctlyUpdatesTheConfig() public { + bytes[] memory signers = _getSigners(4); + bytes32[] memory offchainTransmitters = _getOffchainTransmitters(4); + uint8 f = 1; + bytes memory onchainConfig = abi.encodePacked(uint256(1), bytes32(0)); + bytes memory offchainConfig = abi.encodePacked(keccak256("offchainConfig")); + + // initial block number + vm.roll(5); + + bytes32 cd1 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + // when isGreenProduction=false + + vm.expectEmit(); + emit ProductionConfigSet( + CONFIG_ID_1, + 0, + cd1, + 1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + false + ); + + s_exposedConfigurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + Configurator.ConfigurationState memory configurationState = s_exposedConfigurator.exposedReadConfigurationStates( + CONFIG_ID_1 + ); + assertEq(configurationState.configDigest[0], cd1); + assertEq(configurationState.configDigest[1], 0); // no staging config yet + assertEq(configurationState.configCount, 1); + assertEq(configurationState.isGreenProduction, false); + assertEq(configurationState.latestConfigBlockNumber, block.number); + + // go to new block + vm.roll(10); + + // set it again, configCount=2 + + bytes32 cd2 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 2, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + vm.expectEmit(); + emit ProductionConfigSet( + CONFIG_ID_1, + 5, + cd2, + 2, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + false + ); + + s_exposedConfigurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + configurationState = s_exposedConfigurator.exposedReadConfigurationStates(CONFIG_ID_1); + assertEq(configurationState.configDigest[0], cd2); + assertEq(configurationState.configDigest[1], 0); // no staging config yet + assertEq(configurationState.configCount, 2); + assertEq(configurationState.isGreenProduction, false); + assertEq(configurationState.latestConfigBlockNumber, block.number); + + // when isGreenProduction=true + s_exposedConfigurator.exposedSetIsGreenProduction(CONFIG_ID_1, true); + + // go to new block + vm.roll(15); + + // set it again, configCount=3 + bytes32 cd3 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 3, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + vm.expectEmit(); + emit ProductionConfigSet( + CONFIG_ID_1, + 10, + cd3, + 3, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + true + ); + + s_exposedConfigurator.setProductionConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + configurationState = s_exposedConfigurator.exposedReadConfigurationStates(CONFIG_ID_1); + assertEq(configurationState.configDigest[0], cd2); // the previous config left unchanged + assertEq(configurationState.configDigest[1], cd3); // new config is on green now because green is production due to isGreenProduction=true + assertEq(configurationState.configCount, 3); + assertEq(configurationState.isGreenProduction, true); + assertEq(configurationState.latestConfigBlockNumber, block.number); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol new file mode 100644 index 00000000000..4487ece16e1 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseConfiguratorTest.t.sol"; +import {Configurator} from "../../Configurator.sol"; + +contract ConfiguratorSetStagingConfigTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + bytes[] memory signers = _getSigners(MAX_ORACLES); + + vm.startPrank(USER); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfSetWithTooManySigners() public { + bytes[] memory signers = new bytes[](MAX_ORACLES + 1); + vm.expectRevert(abi.encodeWithSelector(Configurator.ExcessSigners.selector, signers.length, MAX_ORACLES)); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfFaultToleranceIsZero() public { + vm.expectRevert(abi.encodeWithSelector(Configurator.FaultToleranceMustBePositive.selector)); + bytes[] memory signers = _getSigners(MAX_ORACLES); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + 0, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfNotEnoughSigners() public { + bytes[] memory signers = _getSigners(2); + + vm.expectRevert( + abi.encodeWithSelector(Configurator.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) + ); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + OFFCHAIN_CONFIG_VERSION, + bytes("") + ); + } + + function test_revertsIfOnchainConfigIsInvalid() public { + bytes[] memory signers = _getSigners(4); + bytes32[] memory offchainTransmitters = _getOffchainTransmitters(4); + bytes memory onchainConfig = bytes(""); + uint8 f = 1; + bytes memory offchainConfig = abi.encodePacked(keccak256("offchainConfig")); + + vm.expectRevert(abi.encodeWithSelector(Configurator.InvalidOnchainLength.selector, onchainConfig.length)); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + onchainConfig = abi.encode(uint256(0), keccak256("previousConfigDigest")); + + vm.expectRevert(abi.encodeWithSelector(Configurator.UnsupportedOnchainConfigVersion.selector, uint256(0))); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + onchainConfig = abi.encode(uint256(1), keccak256("previousConfigDigest")); + + vm.expectRevert( + abi.encodeWithSelector(Configurator.InvalidPredecessorConfigDigest.selector, keccak256("previousConfigDigest")) + ); + s_configurator.setStagingConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + } + + function test_correctlyUpdatesTheConfig() public { + bytes[] memory signers = _getSigners(4); + bytes32[] memory offchainTransmitters = _getOffchainTransmitters(4); + uint8 f = 1; + + // initial block number + vm.roll(2); + + bytes32 productionConfigDigest = keccak256("productionConfigDigest"); + s_exposedConfigurator.exposedSetConfigurationState( + CONFIG_ID_1, + Configurator.ConfigurationState(1, uint32(block.number), false, [productionConfigDigest, bytes32(0)]) + ); + bytes memory onchainConfig = abi.encodePacked(uint256(1), productionConfigDigest); + bytes memory offchainConfig = abi.encodePacked(keccak256("offchainConfig")); + + vm.roll(5); + + bytes32 cd1 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 2, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + // when isGreenProduction=false + + vm.expectEmit(); + emit StagingConfigSet( + CONFIG_ID_1, + 2, + cd1, + 2, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + false + ); + + s_exposedConfigurator.setStagingConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + Configurator.ConfigurationState memory configurationState = s_exposedConfigurator.exposedReadConfigurationStates( + CONFIG_ID_1 + ); + assertEq(configurationState.configDigest[0], productionConfigDigest); + assertEq(configurationState.configDigest[1], cd1); + assertEq(configurationState.configCount, 2); + assertEq(configurationState.isGreenProduction, false); + assertEq(configurationState.latestConfigBlockNumber, block.number); + + // go to new block + vm.roll(10); + + // set it again, configCount=2 + + bytes32 cd2 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 3, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + vm.expectEmit(); + emit StagingConfigSet( + CONFIG_ID_1, + 5, + cd2, + 3, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + false + ); + + s_exposedConfigurator.setStagingConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + configurationState = s_exposedConfigurator.exposedReadConfigurationStates(CONFIG_ID_1); + assertEq(configurationState.configDigest[0], productionConfigDigest); + assertEq(configurationState.configDigest[1], cd2); + assertEq(configurationState.configCount, 3); + assertEq(configurationState.isGreenProduction, false); + assertEq(configurationState.latestConfigBlockNumber, block.number); + + // when isGreenProduction=true + s_exposedConfigurator.exposedSetIsGreenProduction(CONFIG_ID_1, true); + onchainConfig = abi.encodePacked(uint256(1), cd2); // predecessorConfigDigest the production digest is now the green digest + + // go to new block + vm.roll(15); + + // set it again, configCount=3 + bytes32 cd3 = s_exposedConfigurator.exposedConfigDigestFromConfigData( + CONFIG_ID_1, + block.chainid, + address(s_exposedConfigurator), + 4, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + vm.expectEmit(); + emit StagingConfigSet( + CONFIG_ID_1, + 10, + cd3, + 4, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig, + true + ); + + s_exposedConfigurator.setStagingConfig( + CONFIG_ID_1, + signers, + offchainTransmitters, + f, + onchainConfig, + OFFCHAIN_CONFIG_VERSION, + offchainConfig + ); + + configurationState = s_exposedConfigurator.exposedReadConfigurationStates(CONFIG_ID_1); + assertEq(configurationState.configDigest[0], cd3); // new config is on blue now because blue is staging due to isGreenProduction=true + assertEq(configurationState.configDigest[1], cd2); // the previous config left unchanged + assertEq(configurationState.configCount, 4); + assertEq(configurationState.isGreenProduction, true); + assertEq(configurationState.latestConfigBlockNumber, block.number); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorTest.t.sol new file mode 100644 index 00000000000..272cbb2e0d6 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorTest.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseConfiguratorTest.t.sol"; +import {Configurator} from "../../Configurator.sol"; +import {IConfigurator} from "../../interfaces/IConfigurator.sol"; + +contract ConfiguratorTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function testTypeAndVersion() public view { + assertEq(s_configurator.typeAndVersion(), "Configurator 0.5.0"); + } + + function testSupportsInterface() public view { + assertTrue(s_configurator.supportsInterface(type(IConfigurator).interfaceId)); + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol new file mode 100644 index 00000000000..1ffd51210f1 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ChannelConfigStore} from "../../ChannelConfigStore.sol"; + +// Exposed ChannelConfigStore exposes certain internal ChannelConfigStore +// methods/structures so that golang code can access them, and we get +// reliable type checking on their usage +contract ExposedChannelConfigStore is ChannelConfigStore { + constructor() {} + + function exposedReadChannelDefinitionStates(uint256 donId) public view returns (uint256) { + return s_channelDefinitionVersions[donId]; + } +} diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol new file mode 100644 index 00000000000..29a2bde54c7 --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Configurator} from "../../Configurator.sol"; + +// Exposed ChannelConfigStore exposes certain internal ChannelConfigStore +// methods/structures so that golang code can access them, and we get +// reliable type checking on their usage +contract ExposedConfigurator is Configurator { + constructor() {} + + function exposedReadConfigurationStates(bytes32 configId) public view returns (ConfigurationState memory) { + return s_configurationStates[configId]; + } + + function exposedSetIsGreenProduction(bytes32 configId, bool isGreenProduction) public { + s_configurationStates[configId].isGreenProduction = isGreenProduction; + } + + function exposedSetConfigurationState(bytes32 configId, ConfigurationState memory state) public { + s_configurationStates[configId] = state; + } + + function exposedConfigDigestFromConfigData( + bytes32 _configId, + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + bytes[] memory _signers, + bytes32[] memory _offchainTransmitters, + uint8 _f, + bytes calldata _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) public pure returns (bytes32) { + return + _configDigestFromConfigData( + _configId, + _chainId, + _contractAddress, + _configCount, + _signers, + _offchainTransmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol index 842eec90542..bd731c7718e 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol @@ -7,7 +7,7 @@ contract MaliciousConsumer is Chainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; uint256 private s_expiration; - constructor(address _link, address _oracle) public payable { + constructor(address _link, address _oracle) payable { setLinkToken(_link); setOracle(_oracle); } diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol index 6e5881524f5..93af16f64fd 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol @@ -8,7 +8,7 @@ contract MaliciousMultiWordConsumer is ChainlinkClient { uint256 private constant ORACLE_PAYMENT = 1 ether; uint256 private s_expiration; - constructor(address _link, address _oracle) public payable { + constructor(address _link, address _oracle) payable { _setChainlinkToken(_link); _setChainlinkOracle(_oracle); } diff --git a/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol b/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol new file mode 100644 index 00000000000..b78096773ab --- /dev/null +++ b/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +/// @dev this is a fully copy of OZ's EnumerableSet library with the addition of a Bytes16Set + +pragma solidity ^0.8.0; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes32 value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // Bytes16Set + + struct Bytes16Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes16Set storage set, bytes16 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes16Set storage set, bytes16 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes16Set storage set, bytes16 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes16Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes16Set storage set, uint256 index) internal view returns (bytes16) { + return bytes16(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes16Set storage set) internal view returns (bytes16[] memory) { + bytes32[] memory store = _values(set._inner); + bytes16[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/contracts/src/v0.8/shared/ocr2/OCR2Base.sol b/contracts/src/v0.8/shared/ocr2/OCR2Base.sol index 7a90f2abf93..07837826181 100644 --- a/contracts/src/v0.8/shared/ocr2/OCR2Base.sol +++ b/contracts/src/v0.8/shared/ocr2/OCR2Base.sol @@ -67,11 +67,7 @@ abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract { address[] internal s_transmitters; /// @dev Reverts transaction if config args are invalid - modifier checkConfigValid( - uint256 _numSigners, - uint256 _numTransmitters, - uint256 _f - ) { + modifier checkConfigValid(uint256 _numSigners, uint256 _numTransmitters, uint256 _f) { require(_numSigners <= MAX_NUM_ORACLES, "too many signers"); require(_f > 0, "f must be positive"); require(_numSigners == _numTransmitters, "oracle addresses out of registration"); @@ -250,7 +246,7 @@ abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract { ) private pure { // calldata will never be big enough to make this overflow uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report + report.length + // one byte per entry in report rs.length * 32 + // 32 bytes per entry in _rs ss.length * diff --git a/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol b/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol index 444112d2d8d..3623cb8b129 100644 --- a/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol +++ b/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol @@ -220,7 +220,7 @@ contract CallWithExactGas__callWithExactGasSafeReturnData is CallWithExactGasSet assertGt(gasUsed, 500); } - function testFuzz_CallWithExactGasSafeReturnData_ConsumeAllGas_Success(uint8 gasLimitMultiplier) external { + function test_Fuzz_CallWithExactGasSafeReturnData_ConsumeAllGas_Success(uint8 gasLimitMultiplier) external { vm.assume(gasLimitMultiplier > 0); // Assume not zero to avoid zero gas being passed to s_gasConsumer uint16 maxRetBytes = 0; @@ -244,7 +244,7 @@ contract CallWithExactGas__callWithExactGasSafeReturnData is CallWithExactGasSet assertTrue(success, "Error: External Call Failed"); - //Assert equal within a margin of error of 1/64 of the gas limit to account for excess gas used by execution library + // Assert equal within a margin of error of 1/64 of the gas limit to account for excess gas used by execution library assertApproxEqAbs( gasUsed - CALL_WITH_EXACT_GAS_SAFE_RETURN_DATA_GAS_OVERHEAD, gasLimit, diff --git a/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol b/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol index 709d00cc382..bf4bd4b25d5 100644 --- a/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol +++ b/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol @@ -8,31 +8,45 @@ struct TestStruct { uint8 OracleId; uint8[32] OracleIds; address Account; + address AccountStr; address[] Accounts; int192 BigField; - MidLevelTestStruct NestedStruct; + MidLevelDynamicTestStruct NestedDynamicStruct; + MidLevelStaticTestStruct NestedStaticStruct; } -struct MidLevelTestStruct { +struct MidLevelDynamicTestStruct { bytes2 FixedBytes; - InnerTestStruct Inner; + InnerDynamicTestStruct Inner; } -struct InnerTestStruct { +struct InnerDynamicTestStruct { int64 IntVal; string S; } +struct MidLevelStaticTestStruct { + bytes2 FixedBytes; + InnerStaticTestStruct Inner; +} + +struct InnerStaticTestStruct { + int64 IntVal; + address A; +} + contract ChainReaderTester { event Triggered( int32 indexed field, - string differentField, uint8 oracleId, + MidLevelDynamicTestStruct nestedDynamicStruct, + MidLevelStaticTestStruct nestedStaticStruct, uint8[32] oracleIds, address Account, + address AccountStr, address[] Accounts, - int192 bigField, - MidLevelTestStruct nestedStruct + string differentField, + int192 bigField ); event TriggeredEventWithDynamicTopic(string indexed fieldHash, string field); @@ -43,6 +57,9 @@ contract ChainReaderTester { // first topic is event hash, second and third topics get hashed before getting stored event TriggeredWithFourTopicsWithHashed(string indexed field1, uint8[32] indexed field2, bytes32 indexed field3); + // emits dynamic bytes which encode data in the same way every time. + event StaticBytes(bytes message); + TestStruct[] private s_seen; uint64[] private s_arr; uint64 private s_value; @@ -59,11 +76,26 @@ contract ChainReaderTester { uint8 oracleId, uint8[32] calldata oracleIds, address account, + address accountStr, address[] calldata accounts, int192 bigField, - MidLevelTestStruct calldata nestedStruct + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct ) public { - s_seen.push(TestStruct(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct)); + s_seen.push( + TestStruct( + field, + differentField, + oracleId, + oracleIds, + account, + accountStr, + accounts, + bigField, + nestedDynamicStruct, + nestedStaticStruct + ) + ); } function setAlterablePrimitiveValue(uint64 value) public { @@ -76,11 +108,25 @@ contract ChainReaderTester { uint8 oracleId, uint8[32] calldata oracleIds, address account, + address accountStr, address[] calldata accounts, int192 bigField, - MidLevelTestStruct calldata nestedStruct + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct ) public pure returns (TestStruct memory) { - return TestStruct(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct); + return + TestStruct( + field, + differentField, + oracleId, + oracleIds, + account, + accountStr, + accounts, + bigField, + nestedDynamicStruct, + nestedStaticStruct + ); } function getElementAtIndex(uint256 i) public view returns (TestStruct memory) { @@ -109,15 +155,28 @@ contract ChainReaderTester { function triggerEvent( int32 field, - string calldata differentField, uint8 oracleId, + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct, uint8[32] calldata oracleIds, address account, + address accountStr, address[] calldata accounts, - int192 bigField, - MidLevelTestStruct calldata nestedStruct + string calldata differentField, + int192 bigField ) public { - emit Triggered(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct); + emit Triggered( + field, + oracleId, + nestedDynamicStruct, + nestedStaticStruct, + oracleIds, + account, + accountStr, + accounts, + differentField, + bigField + ); } function triggerEventWithDynamicTopic(string calldata field) public { @@ -133,4 +192,19 @@ contract ChainReaderTester { function triggerWithFourTopicsWithHashed(string memory field1, uint8[32] memory field2, bytes32 field3) public { emit TriggeredWithFourTopicsWithHashed(field1, field2, field3); } + + // emulate CCTP message event. + function triggerStaticBytes( + uint32 val1, + uint32 val2, + uint32 val3, + uint64 val4, + bytes32 val5, + bytes32 val6, + bytes32 val7, + bytes memory raw + ) public { + bytes memory _message = abi.encodePacked(val1, val2, val3, val4, val5, val6, val7, raw); + emit StaticBytes(_message); + } } diff --git a/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol b/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol index 3c7bd2d596e..daf847985e3 100644 --- a/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol +++ b/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol @@ -6,11 +6,10 @@ contract GasConsumer { // While loop that operates indefinitely, written in yul to ensure better granularity over exactly how much gas is spent for { // Loop will run forever since 0 < 1 - } lt(0, 1) { - - } { - // If 60 gas is remaining, then exit the loop by returning. 60 was determined by manual binary search to be the minimal amount of gas needed but less than the cost of another loop - if lt(gas(), 60) { + } lt(0, 1) {} { + // If 100 gas is remaining, then exit the loop by returning. 100 was determined by manual binary search to be + // the minimal amount of gas needed but less than the cost of another loop + if lt(gas(), 100) { return(0x0, 0x0) // Return with no return data } } diff --git a/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol b/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol index de9067a569a..2815f992563 100644 --- a/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol +++ b/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol @@ -338,7 +338,7 @@ contract BurnMintERC677_increaseApproval is BurnMintERC677Setup { } contract BurnMintERC677_supportsInterface is BurnMintERC677Setup { - function testConstructorSuccess() public { + function testConstructorSuccess() public view { assertTrue(s_burnMintERC677.supportsInterface(type(IERC20).interfaceId)); assertTrue(s_burnMintERC677.supportsInterface(type(IERC677).interfaceId)); assertTrue(s_burnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); diff --git a/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol b/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol index 7987fefec48..614b3bea15b 100644 --- a/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol +++ b/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol @@ -41,7 +41,7 @@ contract OpStackBurnMintERC677_constructor is OpStackBurnMintERC677Setup { } contract OpStackBurnMintERC677_supportsInterface is OpStackBurnMintERC677Setup { - function testConstructorSuccess() public { + function testConstructorSuccess() public view { assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IOptimismMintableERC20Minimal).interfaceId)); assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IERC677).interfaceId)); assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); diff --git a/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol b/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol index ae7eba479ff..bf88df64ad5 100644 --- a/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol +++ b/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol @@ -50,7 +50,7 @@ contract SortedSetValidationUtilBaseTest is BaseTest { contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValidationUtilBaseTest { // Successes. - function test__checkIsValidUniqueSubset_ValidSubset_Success() public { + function test__checkIsValidUniqueSubset_ValidSubset_Success() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); _convertArrayToSortedSet(superset, OFFSET); _convertArrayToSubset(subset, superset); @@ -123,7 +123,7 @@ contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValida SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); } - function test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() public { + function test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(5, 5); _convertArrayToSortedSet(subset, OFFSET); _convertArrayToSortedSet(superset, OFFSET); @@ -131,7 +131,7 @@ contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValida SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); } - function test__checkIsValidUniqueSubset_SingleElementSubset() public { + function test__checkIsValidUniqueSubset_SingleElementSubset() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 5); _convertArrayToSortedSet(superset, OFFSET); _convertArrayToSubset(subset, superset); @@ -139,7 +139,7 @@ contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValida SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); } - function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() public { + function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 1); _convertArrayToSortedSet(subset, OFFSET); _convertArrayToSortedSet(superset, OFFSET); diff --git a/contracts/src/v0.8/tests/MockGasBoundCaller.sol b/contracts/src/v0.8/tests/MockGasBoundCaller.sol new file mode 100644 index 00000000000..3184f9dba38 --- /dev/null +++ b/contracts/src/v0.8/tests/MockGasBoundCaller.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +contract MockGasBoundCaller { + error TransactionFailed(address target); + + function gasBoundCall(address target, uint256 gasAmount, bytes memory data) external payable { + bool success; + assembly { + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + + // gas bound caller will propagate the revert + if (!success) { + revert TransactionFailed(target); + } + + uint256 pubdataGas = 500000; + bytes memory returnData = abi.encode(address(0), pubdataGas); + + uint256 paddedReturndataLen = returnData.length + 96; + if (paddedReturndataLen % 32 != 0) { + paddedReturndataLen += 32 - (paddedReturndataLen % 32); + } + + assembly { + mstore(sub(returnData, 0x40), 0x40) + mstore(sub(returnData, 0x20), pubdataGas) + return(sub(returnData, 0x40), paddedReturndataLen) + } + } +} diff --git a/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol b/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol index 29790b0e150..6bb0dae6455 100644 --- a/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol +++ b/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol @@ -1,7 +1,12 @@ +// SPDX-License-Identifier: MIT pragma solidity 0.8.6; contract MockOVMGasPriceOracle { - function getL1Fee(bytes memory _data) public view returns (uint256) { + function getL1Fee(bytes memory) public pure returns (uint256) { + return 2000000; + } + + function getL1FeeUpperBound(uint256) public pure returns (uint256) { return 2000000; } } diff --git a/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol b/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol new file mode 100644 index 00000000000..265d4b678a5 --- /dev/null +++ b/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +contract MockZKSyncSystemContext { + function gasPrice() external pure returns (uint256) { + return 250000000; // 0.25 gwei + } + + function gasPerPubdataByte() external pure returns (uint256) { + return 500; + } + + function getCurrentPubdataSpent() external pure returns (uint256 currentPubdataSpent) { + return 1000; + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol b/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol index 5815bd69cf8..9ca1b82d9e5 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol @@ -194,7 +194,7 @@ abstract contract StdChains { stdChainsInitialized = true; - // If adding an RPC here, make sure to test the default RPC URL in `testRpcs` + // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); setChainWithDefaultRpcUrl( "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP") @@ -235,8 +235,21 @@ abstract contract StdChains { setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); + setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); + setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); + setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); + setChainWithDefaultRpcUrl( + "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/") + ); setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); + setChainWithDefaultRpcUrl( + "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com") + ); + setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); + setChainWithDefaultRpcUrl( + "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc") + ); } // set chain info, with priority to chainAlias' rpc url in foundry.toml diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol b/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol index f2933139cc8..95850d118e5 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol @@ -228,7 +228,7 @@ abstract contract StdCheatsSafe { // Checks that `addr` is not blacklisted by token contracts that have a blacklist. // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for - // backwards compatibility, since this name was used in the original PR which has already has + // backwards compatibility, since this name was used in the original PR which already has // a release. This function can be removed in a future release once we want a breaking change. function assumeNoBlacklisted(address token, address addr) internal view virtual { assumeNotBlacklisted(token, addr); @@ -322,8 +322,8 @@ abstract contract StdCheatsSafe { // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific // address), but the same rationale for excluding them applies so we include those too. - // These should be present on all EVM-compatible chains. - vm.assume(addr < address(0x1) || addr > address(0x9)); + // These are reserved by Ethereum and may be on all EVM-compatible chains. + vm.assume(addr < address(0x1) || addr > address(0xff)); // forgefmt: disable-start if (chainId == 10 || chainId == 420) { diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol b/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol index 7620cbf3d86..056db98fcf1 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol @@ -29,6 +29,7 @@ abstract contract StdInvariant { FuzzArtifactSelector[] private _targetedArtifactSelectors; + FuzzSelector[] private _excludedSelectors; FuzzSelector[] private _targetedSelectors; FuzzInterface[] private _targetedInterfaces; @@ -40,6 +41,10 @@ abstract contract StdInvariant { _excludedContracts.push(newExcludedContract_); } + function excludeSelector(FuzzSelector memory newExcludedSelector_) internal { + _excludedSelectors.push(newExcludedSelector_); + } + function excludeSender(address newExcludedSender_) internal { _excludedSenders.push(newExcludedSender_); } @@ -83,6 +88,10 @@ abstract contract StdInvariant { excludedContracts_ = _excludedContracts; } + function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) { + excludedSelectors_ = _excludedSelectors; + } + function excludeSenders() public view returns (address[] memory excludedSenders_) { excludedSenders_ = _excludedSenders; } diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol b/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol index 6dbde835423..2a033c03a7d 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol @@ -25,6 +25,10 @@ import {VmSafe} from "./Vm.sol"; library stdJson { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + function keyExists(string memory json, string memory key) internal view returns (bool) { + return vm.keyExistsJson(json, key); + } + function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJson(json, key); } @@ -85,6 +89,106 @@ library stdJson { return vm.parseJsonBytesArray(json, key); } + function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { + return keyExists(json, key) ? readUint(json, key) : defaultValue; + } + + function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) + internal + view + returns (uint256[] memory) + { + return keyExists(json, key) ? readUintArray(json, key) : defaultValue; + } + + function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { + return keyExists(json, key) ? readInt(json, key) : defaultValue; + } + + function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) + internal + view + returns (int256[] memory) + { + return keyExists(json, key) ? readIntArray(json, key) : defaultValue; + } + + function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) + internal + view + returns (bytes32) + { + return keyExists(json, key) ? readBytes32(json, key) : defaultValue; + } + + function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) + internal + view + returns (bytes32[] memory) + { + return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; + } + + function readStringOr(string memory json, string memory key, string memory defaultValue) + internal + view + returns (string memory) + { + return keyExists(json, key) ? readString(json, key) : defaultValue; + } + + function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) + internal + view + returns (string[] memory) + { + return keyExists(json, key) ? readStringArray(json, key) : defaultValue; + } + + function readAddressOr(string memory json, string memory key, address defaultValue) + internal + view + returns (address) + { + return keyExists(json, key) ? readAddress(json, key) : defaultValue; + } + + function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) + internal + view + returns (address[] memory) + { + return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; + } + + function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { + return keyExists(json, key) ? readBool(json, key) : defaultValue; + } + + function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) + internal + view + returns (bool[] memory) + { + return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; + } + + function readBytesOr(string memory json, string memory key, bytes memory defaultValue) + internal + view + returns (bytes memory) + { + return keyExists(json, key) ? readBytes(json, key) : defaultValue; + } + + function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) + internal + view + returns (bytes[] memory) + { + return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; + } + function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol b/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol index ffd668c555e..bf3223dee5d 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol @@ -123,7 +123,7 @@ library stdStorageSafe { if (reads.length == 0) { revert("stdStorage find(StdStorage): No storage use detected for target."); } else { - for (uint256 i = 0; i < reads.length; i++) { + for (uint256 i = reads.length; --i >= 0;) { bytes32 prev = vm.load(who, reads[i]); if (prev == bytes32(0)) { emit WARNING_UninitedSlot(who, uint256(reads[i])); diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol b/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol index ef88db6d2f0..7ad3be2f970 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol @@ -25,6 +25,10 @@ import {VmSafe} from "./Vm.sol"; library stdToml { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + function keyExists(string memory toml, string memory key) internal view returns (bool) { + return vm.keyExistsToml(toml, key); + } + function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { return vm.parseToml(toml, key); } @@ -85,6 +89,106 @@ library stdToml { return vm.parseTomlBytesArray(toml, key); } + function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) { + return keyExists(toml, key) ? readUint(toml, key) : defaultValue; + } + + function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue) + internal + view + returns (uint256[] memory) + { + return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue; + } + + function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) { + return keyExists(toml, key) ? readInt(toml, key) : defaultValue; + } + + function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue) + internal + view + returns (int256[] memory) + { + return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue; + } + + function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue) + internal + view + returns (bytes32) + { + return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue; + } + + function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue) + internal + view + returns (bytes32[] memory) + { + return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue; + } + + function readStringOr(string memory toml, string memory key, string memory defaultValue) + internal + view + returns (string memory) + { + return keyExists(toml, key) ? readString(toml, key) : defaultValue; + } + + function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue) + internal + view + returns (string[] memory) + { + return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue; + } + + function readAddressOr(string memory toml, string memory key, address defaultValue) + internal + view + returns (address) + { + return keyExists(toml, key) ? readAddress(toml, key) : defaultValue; + } + + function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue) + internal + view + returns (address[] memory) + { + return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue; + } + + function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) { + return keyExists(toml, key) ? readBool(toml, key) : defaultValue; + } + + function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue) + internal + view + returns (bool[] memory) + { + return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue; + } + + function readBytesOr(string memory toml, string memory key, bytes memory defaultValue) + internal + view + returns (bytes memory) + { + return keyExists(toml, key) ? readBytes(toml, key) : defaultValue; + } + + function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue) + internal + view + returns (bytes[] memory) + { + return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue; + } + function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } diff --git a/contracts/src/v0.8/vendor/forge-std/src/Vm.sol b/contracts/src/v0.8/vendor/forge-std/src/Vm.sol index 6b1f2913cfb..591508c097a 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/Vm.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/Vm.sol @@ -235,7 +235,7 @@ interface VmSafe { uint64 gasLimit; // The total gas used. uint64 gasTotalUsed; - // The amount of gas used for memory expansion. + // DEPRECATED: The amount of gas used for memory expansion. Ref: uint64 gasMemoryUsed; // The amount of gas refunded. int64 gasRefunded; @@ -243,6 +243,97 @@ interface VmSafe { uint64 gasRemaining; } + // ======== Crypto ======== + + /// Derives a private key from the name, labels the account with that name, and returns the wallet. + function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); + + /// Generates a wallet from the private key and returns the wallet. + function createWallet(uint256 privateKey) external returns (Wallet memory wallet); + + /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. + function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) + /// at the derivation path `m/44'/60'/0'/0/{index}`. + function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) + /// at `{derivationPath}{index}`. + function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) + external + pure + returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language + /// at the derivation path `m/44'/60'/0'/0/{index}`. + function deriveKey(string calldata mnemonic, uint32 index, string calldata language) + external + pure + returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language + /// at `{derivationPath}{index}`. + function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) + external + pure + returns (uint256 privateKey); + + /// Derives secp256r1 public key from the provided `privateKey`. + function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); + + /// Adds a private key to the local forge wallet and returns the address. + function rememberKey(uint256 privateKey) external returns (address keyAddr); + + /// Signs data with a `Wallet`. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with `privateKey` using the secp256k1 curve. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + /// If `--sender` is provided, the signer with provided address is used, otherwise, + /// if exactly one signer is provided to the script, that signer is used. + /// Raises error if signer passed through `--sender` does not match any unlocked signers or + /// if `--sender` is not provided and not exactly one signer is passed to the script. + function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + /// Raises error if none of the signers passed into the script have provided address. + function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with `privateKey` using the secp256r1 curve. + function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); + + /// Signs data with a `Wallet`. + function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with `privateKey` using the secp256k1 curve. + function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// If `--sender` is provided, the signer with provided address is used, otherwise, + /// if exactly one signer is provided to the script, that signer is used. + /// Raises error if signer passed through `--sender` does not match any unlocked signers or + /// if `--sender` is not provided and not exactly one signer is passed to the script. + function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Raises error if none of the signers passed into the script have provided address. + function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + // ======== Environment ======== /// Gets the environment variable `name` and parses it as `address`. @@ -447,6 +538,9 @@ interface VmSafe { /// Gets the nonce of an account. function getNonce(address account) external view returns (uint64 nonce); + /// Get the nonce of a `Wallet`. + function getNonce(Wallet calldata wallet) external returns (uint64 nonce); + /// Gets all the recorded logs. function getRecordedLogs() external returns (Log[] memory logs); @@ -465,28 +559,19 @@ interface VmSafe { /// Record all the transaction logs. function recordLogs() external; + /// Reset gas metering (i.e. gas usage is set to gas limit). + function resetGasMetering() external; + /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. function resumeGasMetering() external; /// Performs an Ethereum JSON-RPC request to the current fork URL. function rpc(string calldata method, string calldata params) external returns (bytes memory data); - /// Signs `digest` with `privateKey` using the secp256r1 curve. - function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); - - /// Signs `digest` with `privateKey` using the secp256k1 curve. - function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); - - /// Signs `digest` with signer provided to script using the secp256k1 curve. - /// If `--sender` is provided, the signer with provided address is used, otherwise, - /// if exactly one signer is provided to the script, that signer is used. - /// Raises error if signer passed through `--sender` does not match any unlocked signers or - /// if `--sender` is not provided and not exactly one signer is passed to the script. - function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); - - /// Signs `digest` with signer provided to script using the secp256k1 curve. - /// Raises error if none of the signers passed into the script have provided address. - function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + /// Performs an Ethereum JSON-RPC request to the given endpoint. + function rpc(string calldata urlOrAlias, string calldata method, string calldata params) + external + returns (bytes memory data); /// Starts recording all map SSTOREs for later retrieval. function startMappingRecording() external; @@ -520,6 +605,17 @@ interface VmSafe { /// `path` is relative to the project root. function createDir(string calldata path, bool recursive) external; + /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + function deployCode(string calldata artifactPath) external returns (address deployedAddress); + + /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + /// Additionally accepts abi-encoded constructor arguments. + function deployCode(string calldata artifactPath, bytes calldata constructorArgs) + external + returns (address deployedAddress); + /// Returns true if the given path points to an existing entity, else returns false. function exists(string calldata path) external returns (bool result); @@ -529,6 +625,12 @@ interface VmSafe { /// Given a path, query the file system to get information about a file, directory, etc. function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); + /// Gets the artifact path from code (aka. creation code). + function getArtifactPathByCode(bytes calldata code) external view returns (string memory path); + + /// Gets the artifact path from deployed code (aka. runtime code). + function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path); + /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the /// artifact in the form of :: where and parts are optional. function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); @@ -555,6 +657,9 @@ interface VmSafe { /// Prompts the user for a hidden string value in the terminal. function promptSecret(string calldata promptText) external returns (string memory input); + /// Prompts the user for hidden uint256 in the terminal (usually pk). + function promptSecretUint(string calldata promptText) external returns (uint256); + /// Prompts the user for uint256 in the terminal. function promptUint(string calldata promptText) external returns (uint256); @@ -624,10 +729,6 @@ interface VmSafe { // ======== JSON ======== - /// Checks if `key` exists in a JSON object - /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. - function keyExists(string calldata json, string calldata key) external view returns (bool); - /// Checks if `key` exists in a JSON object. function keyExistsJson(string calldata json, string calldata key) external view returns (bool); @@ -676,6 +777,24 @@ interface VmSafe { /// Parses a string of JSON data at `key` and coerces it to `string[]`. function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); + /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`. + function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. + function parseJsonType(string calldata json, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. + function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + /// Parses a string of JSON data at `key` and coerces it to `uint256`. function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); @@ -742,6 +861,20 @@ interface VmSafe { /// Returns the stringified version of the specific JSON file up to that moment. function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); + /// See `serializeJson`. + function serializeJsonType(string calldata typeDescription, bytes calldata value) + external + pure + returns (string memory json); + + /// See `serializeJson`. + function serializeJsonType( + string calldata objectKey, + string calldata valueKey, + string calldata typeDescription, + bytes calldata value + ) external returns (string memory json); + /// See `serializeJson`. function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) external @@ -774,8 +907,15 @@ interface VmSafe { /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. function writeJson(string calldata json, string calldata path, string calldata valueKey) external; + /// Checks if `key` exists in a JSON object + /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. + function keyExists(string calldata json, string calldata key) external view returns (bool); + // ======== Scripting ======== + /// Takes a signed transaction and broadcasts it to the network. + function broadcastRawTransaction(bytes calldata data) external; + /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. /// Broadcasting address is determined by checking the following in order: /// 1. If `--sender` argument was provided, that address is used. @@ -1303,12 +1443,23 @@ interface VmSafe { /// If the condition is false, discard this run's fuzz inputs and generate new ones. function assume(bool condition) external pure; + /// Discard this run's fuzz inputs and generate new ones if next call reverted. + function assumeNoRevert() external pure; + /// Writes a breakpoint to jump to in the debugger. function breakpoint(string calldata char) external; /// Writes a conditional breakpoint to jump to in the debugger. function breakpoint(string calldata char, bool value) external; + /// Returns the Foundry version. + /// Format: ++ + /// Sample output: 0.2.0+faa94c384+202407110019 + /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs. + /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000) + /// to compare timestamps while ignoring minor time differences. + function getFoundryVersion() external view returns (string memory version); + /// Returns the RPC url for the given alias. function rpcUrl(string calldata rpcAlias) external view returns (string memory json); @@ -1371,6 +1522,24 @@ interface VmSafe { /// Parses a string of TOML data at `key` and coerces it to `string[]`. function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); + /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`. + function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`. + function parseTomlType(string calldata toml, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`. + function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + /// Parses a string of TOML data at `key` and coerces it to `uint256`. function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); @@ -1404,57 +1573,51 @@ interface VmSafe { /// Compute the address a contract will be deployed at for a given deployer address and nonce. function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); - /// Derives a private key from the name, labels the account with that name, and returns the wallet. - function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); + /// Utility cheatcode to copy storage of `from` contract to another `to` contract. + function copyStorage(address from, address to) external; - /// Generates a wallet from the private key and returns the wallet. - function createWallet(uint256 privateKey) external returns (Wallet memory wallet); + /// Returns ENS namehash for provided string. + function ensNamehash(string calldata name) external pure returns (bytes32); - /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. - function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); + /// Gets the label for the specified address. + function getLabel(address account) external view returns (string memory currentLabel); - /// Derive a private key from a provided mnenomic string (or mnenomic file path) - /// at the derivation path `m/44'/60'/0'/0/{index}`. - function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); + /// Labels an address in call traces. + function label(address account, string calldata newLabel) external; - /// Derive a private key from a provided mnenomic string (or mnenomic file path) - /// at `{derivationPath}{index}`. - function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) - external - pure - returns (uint256 privateKey); + /// Pauses collection of call traces. Useful in cases when you want to skip tracing of + /// complex calls which are not useful for debugging. + function pauseTracing() external view; - /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language - /// at the derivation path `m/44'/60'/0'/0/{index}`. - function deriveKey(string calldata mnemonic, uint32 index, string calldata language) - external - pure - returns (uint256 privateKey); + /// Returns a random `address`. + function randomAddress() external returns (address); - /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language - /// at `{derivationPath}{index}`. - function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) - external - pure - returns (uint256 privateKey); + /// Returns an random `bool`. + function randomBool() external view returns (bool); - /// Returns ENS namehash for provided string. - function ensNamehash(string calldata name) external pure returns (bytes32); + /// Returns an random byte array value of the given length. + function randomBytes(uint256 len) external view returns (bytes memory); - /// Gets the label for the specified address. - function getLabel(address account) external view returns (string memory currentLabel); + /// Returns an random `int256` value. + function randomInt() external view returns (int256); - /// Get a `Wallet`'s nonce. - function getNonce(Wallet calldata wallet) external returns (uint64 nonce); + /// Returns an random `int256` value of given bits. + function randomInt(uint256 bits) external view returns (int256); - /// Labels an address in call traces. - function label(address account, string calldata newLabel) external; + /// Returns a random uint256 value. + function randomUint() external returns (uint256); - /// Adds a private key to the local forge wallet and returns the address. - function rememberKey(uint256 privateKey) external returns (address keyAddr); + /// Returns random uint256 value between the provided range (=min..=max). + function randomUint(uint256 min, uint256 max) external returns (uint256); - /// Signs data with a `Wallet`. - function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + /// Returns an random `uint256` value of given bits. + function randomUint(uint256 bits) external view returns (uint256); + + /// Unpauses collection of call traces. + function resumeTracing() external view; + + /// Utility cheatcode to set arbitrary storage for given target address. + function setArbitraryStorage(address target) external; /// Encodes a `bytes` value to a base64url string. function toBase64URL(bytes calldata data) external pure returns (string memory); @@ -1584,6 +1747,14 @@ interface Vm is VmSafe { /// Calldata match takes precedence over `msg.value` in case of ambiguity. function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls + /// `target` with the same calldata. This functionality is similar to a delegate call made to + /// `target` contract from `callee`. + /// Can be used to substitute a call to a function with another implementation that captures + /// the primary logic of the original function but is easier to reason about. + /// If calldata is not a strict match then partial match by selector is attempted. + function mockFunction(address callee, address target, bytes calldata data) external; + /// Sets the *next* call's `msg.sender` to be the input address. function prank(address msgSender) external; @@ -1645,6 +1816,10 @@ interface Vm is VmSafe { /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. function selectFork(uint256 forkId) external; + /// Set blockhash for the current block. + /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. + function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; + /// Sets the nonce of an account. Must be higher than the current nonce of the account. function setNonce(address account, uint64 newNonce) external; @@ -1708,6 +1883,30 @@ interface Vm is VmSafe { /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; + /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). + /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). + function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) + external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmitAnonymous( + bool checkTopic0, + bool checkTopic1, + bool checkTopic2, + bool checkTopic3, + bool checkData, + address emitter + ) external; + + /// Prepare an expected anonymous log with all topic and data checks enabled. + /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data. + function expectEmitAnonymous() external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmitAnonymous(address emitter) external; + /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). /// Call this function, then emit an event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). @@ -1725,15 +1924,30 @@ interface Vm is VmSafe { /// Same as the previous method, but also checks supplied address against emitting contract. function expectEmit(address emitter) external; + /// Expects an error on next call that starts with the revert data. + function expectPartialRevert(bytes4 revertData) external; + + /// Expects an error on next call to reverter address, that starts with the revert data. + function expectPartialRevert(bytes4 revertData, address reverter) external; + /// Expects an error on next call with any revert data. function expectRevert() external; - /// Expects an error on next call that starts with the revert data. + /// Expects an error on next call that exactly matches the revert data. function expectRevert(bytes4 revertData) external; /// Expects an error on next call that exactly matches the revert data. function expectRevert(bytes calldata revertData) external; + /// Expects an error with any revert data on next call to reverter address. + function expectRevert(address reverter) external; + + /// Expects an error from reverter address on next call, with any revert data. + function expectRevert(bytes4 revertData, address reverter) external; + + /// Expects an error from reverter address on next call, that exactly matches the revert data. + function expectRevert(bytes calldata revertData, address reverter) external; + /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. function expectSafeMemory(uint64 min, uint64 max) external; @@ -1743,9 +1957,12 @@ interface Vm is VmSafe { /// to the set. function expectSafeMemoryCall(uint64 min, uint64 max) external; - /// Marks a test as skipped. Must be called at the top of the test. + /// Marks a test as skipped. Must be called at the top level of a test. function skip(bool skipTest) external; + /// Marks a test as skipped with a reason. Must be called at the top level of a test. + function skip(bool skipTest, string calldata reason) external; + /// Stops all safe memory expectation in the current subcontext. function stopExpectSafeMemory() external; } diff --git a/contracts/src/v0.8/vendor/forge-std/src/console.sol b/contracts/src/v0.8/vendor/forge-std/src/console.sol index ad57e53687d..4fdb6679edf 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/console.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/console.sol @@ -2,1532 +2,1559 @@ pragma solidity >=0.4.22 <0.9.0; library console { - address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); + address constant CONSOLE_ADDRESS = + 0x000000000000000000636F6e736F6c652e6c6f67; - function _sendLogPayload(bytes memory payload) private view { - uint256 payloadLength = payload.length; + function _sendLogPayloadImplementation(bytes memory payload) internal view { address consoleAddress = CONSOLE_ADDRESS; /// @solidity memory-safe-assembly assembly { - let payloadStart := add(payload, 32) - let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) + pop( + staticcall( + gas(), + consoleAddress, + add(payload, 32), + mload(payload), + 0, + 0 + ) + ) } } - function log() internal view { + function _castToPure( + function(bytes memory) internal view fnIn + ) internal pure returns (function(bytes memory) pure fnOut) { + assembly { + fnOut := fnIn + } + } + + function _sendLogPayload(bytes memory payload) internal pure { + _castToPure(_sendLogPayloadImplementation)(payload); + } + + function log() internal pure { _sendLogPayload(abi.encodeWithSignature("log()")); } - function logInt(int p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); + function logInt(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } - function logUint(uint p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); + function logUint(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } - function logString(string memory p0) internal view { + function logString(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } - function logBool(bool p0) internal view { + function logBool(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } - function logAddress(address p0) internal view { + function logAddress(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } - function logBytes(bytes memory p0) internal view { + function logBytes(bytes memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } - function logBytes1(bytes1 p0) internal view { + function logBytes1(bytes1 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } - function logBytes2(bytes2 p0) internal view { + function logBytes2(bytes2 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } - function logBytes3(bytes3 p0) internal view { + function logBytes3(bytes3 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } - function logBytes4(bytes4 p0) internal view { + function logBytes4(bytes4 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } - function logBytes5(bytes5 p0) internal view { + function logBytes5(bytes5 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } - function logBytes6(bytes6 p0) internal view { + function logBytes6(bytes6 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } - function logBytes7(bytes7 p0) internal view { + function logBytes7(bytes7 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } - function logBytes8(bytes8 p0) internal view { + function logBytes8(bytes8 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } - function logBytes9(bytes9 p0) internal view { + function logBytes9(bytes9 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } - function logBytes10(bytes10 p0) internal view { + function logBytes10(bytes10 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } - function logBytes11(bytes11 p0) internal view { + function logBytes11(bytes11 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } - function logBytes12(bytes12 p0) internal view { + function logBytes12(bytes12 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } - function logBytes13(bytes13 p0) internal view { + function logBytes13(bytes13 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } - function logBytes14(bytes14 p0) internal view { + function logBytes14(bytes14 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } - function logBytes15(bytes15 p0) internal view { + function logBytes15(bytes15 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } - function logBytes16(bytes16 p0) internal view { + function logBytes16(bytes16 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } - function logBytes17(bytes17 p0) internal view { + function logBytes17(bytes17 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } - function logBytes18(bytes18 p0) internal view { + function logBytes18(bytes18 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } - function logBytes19(bytes19 p0) internal view { + function logBytes19(bytes19 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } - function logBytes20(bytes20 p0) internal view { + function logBytes20(bytes20 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } - function logBytes21(bytes21 p0) internal view { + function logBytes21(bytes21 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } - function logBytes22(bytes22 p0) internal view { + function logBytes22(bytes22 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } - function logBytes23(bytes23 p0) internal view { + function logBytes23(bytes23 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } - function logBytes24(bytes24 p0) internal view { + function logBytes24(bytes24 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } - function logBytes25(bytes25 p0) internal view { + function logBytes25(bytes25 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } - function logBytes26(bytes26 p0) internal view { + function logBytes26(bytes26 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } - function logBytes27(bytes27 p0) internal view { + function logBytes27(bytes27 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } - function logBytes28(bytes28 p0) internal view { + function logBytes28(bytes28 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } - function logBytes29(bytes29 p0) internal view { + function logBytes29(bytes29 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } - function logBytes30(bytes30 p0) internal view { + function logBytes30(bytes30 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } - function logBytes31(bytes31 p0) internal view { + function logBytes31(bytes31 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } - function logBytes32(bytes32 p0) internal view { + function logBytes32(bytes32 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } - function log(uint p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); + function log(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } - function log(string memory p0) internal view { + function log(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); + } + + function log(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } - function log(bool p0) internal view { + function log(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } - function log(address p0) internal view { + function log(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } - function log(uint p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); + function log(uint256 p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); } - function log(uint p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); + function log(uint256 p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); } - function log(uint p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); + function log(uint256 p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); } - function log(uint p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); + function log(uint256 p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); } - function log(string memory p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); + function log(string memory p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } - function log(string memory p0, string memory p1) internal view { + function log(string memory p0, int256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); + } + + function log(string memory p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } - function log(string memory p0, bool p1) internal view { + function log(string memory p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } - function log(string memory p0, address p1) internal view { + function log(string memory p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } - function log(bool p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); + function log(bool p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); } - function log(bool p0, string memory p1) internal view { + function log(bool p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } - function log(bool p0, bool p1) internal view { + function log(bool p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } - function log(bool p0, address p1) internal view { + function log(bool p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } - function log(address p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); + function log(address p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); } - function log(address p0, string memory p1) internal view { + function log(address p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } - function log(address p0, bool p1) internal view { + function log(address p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } - function log(address p0, address p1) internal view { + function log(address p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } - function log(uint p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); } - function log(uint p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); } - function log(uint p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); } - function log(uint p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); + function log(uint256 p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); } - function log(uint p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); + function log(uint256 p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); } - function log(uint p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); + function log(uint256 p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); } - function log(uint p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); + function log(uint256 p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); } - function log(uint p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); + function log(uint256 p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); } - function log(uint p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); + function log(uint256 p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); } - function log(uint p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); + function log(uint256 p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); } - function log(uint p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); + function log(uint256 p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); } - function log(uint p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); + function log(uint256 p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); } - function log(uint p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); + function log(uint256 p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); } - function log(uint p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); + function log(uint256 p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); } - function log(uint p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); + function log(uint256 p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); } - function log(uint p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); + function log(uint256 p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); } - function log(string memory p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); + function log(string memory p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); } - function log(string memory p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); + function log(string memory p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); } - function log(string memory p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); + function log(string memory p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); } - function log(string memory p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); + function log(string memory p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); } - function log(string memory p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); + function log(string memory p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); } - function log(string memory p0, string memory p1, string memory p2) internal view { + function log(string memory p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } - function log(string memory p0, string memory p1, bool p2) internal view { + function log(string memory p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } - function log(string memory p0, string memory p1, address p2) internal view { + function log(string memory p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } - function log(string memory p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); + function log(string memory p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); } - function log(string memory p0, bool p1, string memory p2) internal view { + function log(string memory p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } - function log(string memory p0, bool p1, bool p2) internal view { + function log(string memory p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } - function log(string memory p0, bool p1, address p2) internal view { + function log(string memory p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } - function log(string memory p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); + function log(string memory p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); } - function log(string memory p0, address p1, string memory p2) internal view { + function log(string memory p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } - function log(string memory p0, address p1, bool p2) internal view { + function log(string memory p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } - function log(string memory p0, address p1, address p2) internal view { + function log(string memory p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } - function log(bool p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); + function log(bool p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); } - function log(bool p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); + function log(bool p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); } - function log(bool p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); + function log(bool p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); } - function log(bool p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); + function log(bool p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); } - function log(bool p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); + function log(bool p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); } - function log(bool p0, string memory p1, string memory p2) internal view { + function log(bool p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } - function log(bool p0, string memory p1, bool p2) internal view { + function log(bool p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } - function log(bool p0, string memory p1, address p2) internal view { + function log(bool p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } - function log(bool p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); + function log(bool p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); } - function log(bool p0, bool p1, string memory p2) internal view { + function log(bool p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } - function log(bool p0, bool p1, bool p2) internal view { + function log(bool p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } - function log(bool p0, bool p1, address p2) internal view { + function log(bool p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } - function log(bool p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); + function log(bool p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); } - function log(bool p0, address p1, string memory p2) internal view { + function log(bool p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } - function log(bool p0, address p1, bool p2) internal view { + function log(bool p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } - function log(bool p0, address p1, address p2) internal view { + function log(bool p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } - function log(address p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); + function log(address p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); } - function log(address p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); + function log(address p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); } - function log(address p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); + function log(address p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); } - function log(address p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); + function log(address p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); } - function log(address p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); + function log(address p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); } - function log(address p0, string memory p1, string memory p2) internal view { + function log(address p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } - function log(address p0, string memory p1, bool p2) internal view { + function log(address p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } - function log(address p0, string memory p1, address p2) internal view { + function log(address p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } - function log(address p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); + function log(address p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); } - function log(address p0, bool p1, string memory p2) internal view { + function log(address p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } - function log(address p0, bool p1, bool p2) internal view { + function log(address p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } - function log(address p0, bool p1, address p2) internal view { + function log(address p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } - function log(address p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); + function log(address p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); } - function log(address p0, address p1, string memory p2) internal view { + function log(address p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } - function log(address p0, address p1, bool p2) internal view { + function log(address p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } - function log(address p0, address p1, address p2) internal view { + function log(address p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } - function log(uint p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); } - function log(uint p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); + function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); } - function log(uint p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); + function log(uint256 p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); } - function log(uint p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); + function log(uint256 p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); } - function log(uint p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); } - function log(uint p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); } - function log(uint p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); } - function log(uint p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); } - function log(uint p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); } - function log(uint p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); } - function log(uint p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); } - function log(uint p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); } - function log(uint p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); } - function log(uint p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); } - function log(uint p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); } - function log(uint p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); } - function log(uint p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); } - function log(uint p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); } - function log(uint p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); } - function log(uint p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); + function log(uint256 p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); } - function log(string memory p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); + function log(string memory p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { + function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { + function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, string memory p2, address p3) internal view { + function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { + function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, bool p3) internal view { + function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, bool p2, address p3) internal view { + function log(string memory p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, address p2, string memory p3) internal view { + function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, address p2, bool p3) internal view { + function log(string memory p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } - function log(string memory p0, string memory p1, address p2, address p3) internal view { + function log(string memory p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { + function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, bool p3) internal view { + function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, string memory p2, address p3) internal view { + function log(string memory p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, string memory p3) internal view { + function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, bool p3) internal view { + function log(string memory p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, bool p2, address p3) internal view { + function log(string memory p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, string memory p3) internal view { + function log(string memory p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, bool p3) internal view { + function log(string memory p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } - function log(string memory p0, bool p1, address p2, address p3) internal view { + function log(string memory p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); + function log(string memory p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, string memory p2, string memory p3) internal view { + function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, string memory p2, bool p3) internal view { + function log(string memory p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, string memory p2, address p3) internal view { + function log(string memory p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, bool p2, string memory p3) internal view { + function log(string memory p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, bool p2, bool p3) internal view { + function log(string memory p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, bool p2, address p3) internal view { + function log(string memory p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); + function log(string memory p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, address p2, string memory p3) internal view { + function log(string memory p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, address p2, bool p3) internal view { + function log(string memory p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } - function log(string memory p0, address p1, address p2, address p3) internal view { + function log(string memory p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); + function log(bool p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { + function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, bool p3) internal view { + function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, string memory p2, address p3) internal view { + function log(bool p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, string memory p3) internal view { + function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, bool p3) internal view { + function log(bool p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, bool p2, address p3) internal view { + function log(bool p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); + function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, string memory p3) internal view { + function log(bool p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, bool p3) internal view { + function log(bool p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, string memory p1, address p2, address p3) internal view { + function log(bool p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); + function log(bool p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, string memory p3) internal view { + function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, bool p3) internal view { + function log(bool p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, string memory p2, address p3) internal view { + function log(bool p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, string memory p3) internal view { + function log(bool p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, bool p3) internal view { + function log(bool p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, bool p2, address p3) internal view { + function log(bool p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); + function log(bool p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, string memory p3) internal view { + function log(bool p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, bool p3) internal view { + function log(bool p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, bool p1, address p2, address p3) internal view { + function log(bool p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } - function log(bool p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); } - function log(bool p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); } - function log(bool p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); + function log(bool p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); } - function log(bool p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); } - function log(bool p0, address p1, string memory p2, string memory p3) internal view { + function log(bool p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } - function log(bool p0, address p1, string memory p2, bool p3) internal view { + function log(bool p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, string memory p2, address p3) internal view { + function log(bool p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, string memory p3) internal view { + function log(bool p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, bool p3) internal view { + function log(bool p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, bool p2, address p3) internal view { + function log(bool p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } - function log(bool p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); + function log(bool p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); } - function log(bool p0, address p1, address p2, string memory p3) internal view { + function log(bool p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } - function log(bool p0, address p1, address p2, bool p3) internal view { + function log(bool p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } - function log(bool p0, address p1, address p2, address p3) internal view { + function log(bool p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } - function log(address p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); } - function log(address p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); } - function log(address p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); } - function log(address p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); } - function log(address p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); } - function log(address p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); } - function log(address p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); } - function log(address p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); } - function log(address p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); } - function log(address p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); } - function log(address p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); } - function log(address p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); } - function log(address p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); } - function log(address p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); } - function log(address p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); + function log(address p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); + function log(address p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, string memory p2, string memory p3) internal view { + function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, string memory p2, bool p3) internal view { + function log(address p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, string memory p2, address p3) internal view { + function log(address p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, bool p2, string memory p3) internal view { + function log(address p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, bool p2, bool p3) internal view { + function log(address p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, bool p2, address p3) internal view { + function log(address p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); + function log(address p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, address p2, string memory p3) internal view { + function log(address p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, address p2, bool p3) internal view { + function log(address p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } - function log(address p0, string memory p1, address p2, address p3) internal view { + function log(address p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } - function log(address p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); } - function log(address p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); } - function log(address p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); + function log(address p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); } - function log(address p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); } - function log(address p0, bool p1, string memory p2, string memory p3) internal view { + function log(address p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } - function log(address p0, bool p1, string memory p2, bool p3) internal view { + function log(address p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, string memory p2, address p3) internal view { + function log(address p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, string memory p3) internal view { + function log(address p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, bool p3) internal view { + function log(address p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, bool p2, address p3) internal view { + function log(address p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } - function log(address p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); + function log(address p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); } - function log(address p0, bool p1, address p2, string memory p3) internal view { + function log(address p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } - function log(address p0, bool p1, address p2, bool p3) internal view { + function log(address p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } - function log(address p0, bool p1, address p2, address p3) internal view { + function log(address p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } - function log(address p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); + function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); } - function log(address p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); + function log(address p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); } - function log(address p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); + function log(address p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); } - function log(address p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); + function log(address p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); } - function log(address p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); + function log(address p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); } - function log(address p0, address p1, string memory p2, string memory p3) internal view { + function log(address p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } - function log(address p0, address p1, string memory p2, bool p3) internal view { + function log(address p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } - function log(address p0, address p1, string memory p2, address p3) internal view { + function log(address p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } - function log(address p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); + function log(address p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); } - function log(address p0, address p1, bool p2, string memory p3) internal view { + function log(address p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } - function log(address p0, address p1, bool p2, bool p3) internal view { + function log(address p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } - function log(address p0, address p1, bool p2, address p3) internal view { + function log(address p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } - function log(address p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); + function log(address p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); } - function log(address p0, address p1, address p2, string memory p3) internal view { + function log(address p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } - function log(address p0, address p1, address p2, bool p3) internal view { + function log(address p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } - function log(address p0, address p1, address p2, address p3) internal view { + function log(address p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } - -} \ No newline at end of file +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/console2.sol b/contracts/src/v0.8/vendor/forge-std/src/console2.sol index c1e2cd7546c..03531d91d30 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/console2.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/console2.sol @@ -1,1558 +1,4 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; -/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should -/// use `int256` and `uint256`. This modified version fixes that. This version is recommended -/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in -/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`. -/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178 -library console2 { - address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); - - function _castLogPayloadViewToPure( - function(bytes memory) internal view fnIn - ) internal pure returns (function(bytes memory) internal pure fnOut) { - assembly { - fnOut := fnIn - } - } - - function _sendLogPayload(bytes memory payload) internal pure { - _castLogPayloadViewToPure(_sendLogPayloadView)(payload); - } - - function _sendLogPayloadView(bytes memory payload) private view { - uint256 payloadLength = payload.length; - address consoleAddress = CONSOLE_ADDRESS; - /// @solidity memory-safe-assembly - assembly { - let payloadStart := add(payload, 32) - let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) - } - } - - function log() internal pure { - _sendLogPayload(abi.encodeWithSignature("log()")); - } - - function logInt(int256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); - } - - function logUint(uint256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); - } - - function logString(string memory p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function logBool(bool p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function logAddress(address p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function logBytes(bytes memory p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); - } - - function logBytes1(bytes1 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); - } - - function logBytes2(bytes2 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); - } - - function logBytes3(bytes3 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); - } - - function logBytes4(bytes4 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); - } - - function logBytes5(bytes5 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); - } - - function logBytes6(bytes6 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); - } - - function logBytes7(bytes7 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); - } - - function logBytes8(bytes8 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); - } - - function logBytes9(bytes9 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); - } - - function logBytes10(bytes10 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); - } - - function logBytes11(bytes11 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); - } - - function logBytes12(bytes12 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); - } - - function logBytes13(bytes13 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); - } - - function logBytes14(bytes14 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); - } - - function logBytes15(bytes15 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); - } - - function logBytes16(bytes16 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); - } - - function logBytes17(bytes17 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); - } - - function logBytes18(bytes18 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); - } - - function logBytes19(bytes19 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); - } - - function logBytes20(bytes20 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); - } - - function logBytes21(bytes21 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); - } - - function logBytes22(bytes22 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); - } - - function logBytes23(bytes23 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); - } - - function logBytes24(bytes24 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); - } - - function logBytes25(bytes25 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); - } - - function logBytes26(bytes26 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); - } - - function logBytes27(bytes27 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); - } - - function logBytes28(bytes28 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); - } - - function logBytes29(bytes29 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); - } - - function logBytes30(bytes30 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); - } - - function logBytes31(bytes31 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); - } - - function logBytes32(bytes32 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); - } - - function log(uint256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); - } - - function log(int256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); - } - - function log(string memory p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function log(bool p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function log(address p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function log(uint256 p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); - } - - function log(uint256 p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); - } - - function log(uint256 p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); - } - - function log(uint256 p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); - } - - function log(string memory p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); - } - - function log(string memory p0, int256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); - } - - function log(string memory p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); - } - - function log(string memory p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); - } - - function log(string memory p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); - } - - function log(bool p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); - } - - function log(bool p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); - } - - function log(bool p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); - } - - function log(bool p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); - } - - function log(address p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); - } - - function log(address p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); - } - - function log(address p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); - } - - function log(address p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); - } - - function log(uint256 p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); - } - - function log(string memory p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); - } - - function log(string memory p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); - } - - function log(string memory p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); - } - - function log(string memory p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); - } - - function log(bool p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); - } - - function log(bool p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); - } - - function log(bool p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); - } - - function log(bool p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); - } - - function log(bool p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); - } - - function log(bool p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); - } - - function log(bool p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); - } - - function log(bool p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); - } - - function log(address p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); - } - - function log(address p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); - } - - function log(address p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); - } - - function log(address p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); - } - - function log(address p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); - } - - function log(address p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); - } - - function log(address p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); - } - - function log(address p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); - } - - function log(address p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); - } - - function log(address p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); - } - - function log(address p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); - } - - function log(address p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); - } - -} \ No newline at end of file +import {console as console2} from "./console.sol"; diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol index bfe3a1155e1..391eeb4de74 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol @@ -119,7 +119,7 @@ interface IERC4626 is IERC20 { function mint(uint256 shares, address receiver) external returns (uint256 assets); /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the - /// Vault, through a withdraw call. + /// Vault, through a withdrawal call. /// @dev /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. /// - MUST NOT revert. @@ -145,7 +145,7 @@ interface IERC4626 is IERC20 { /// @dev /// - MUST emit the Withdraw event. /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the - /// withdraw execution, and are accounted for during withdraw. + /// withdraw execution, and are accounted for during withdrawal. /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner /// not having enough shares, etc). /// diff --git a/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol b/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol index f21151bb9b1..7a4909e58ce 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; -import {IERC721Metadata} from "../interfaces/IERC721.sol"; +import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol"; /// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol @@ -229,7 +229,3 @@ contract MockERC721 is IERC721Metadata { return codeLength > 0; } } - -interface IERC721TokenReceiver { - function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4); -} diff --git a/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol b/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol index 5714d0902d8..87c475a5b05 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol @@ -11,6 +11,7 @@ library safeconsole { function _sendLogPayload(uint256 offset, uint256 size) private pure { function(uint256, uint256) internal view fnIn = _sendLogPayloadView; function(uint256, uint256) internal pure pureSendLogPayload; + /// @solidity memory-safe-assembly assembly { pureSendLogPayload := fnIn } @@ -18,6 +19,7 @@ library safeconsole { } function _sendLogPayloadView(uint256 offset, uint256 size) private view { + /// @solidity memory-safe-assembly assembly { pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) } @@ -26,6 +28,7 @@ library safeconsole { function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { function(uint256, uint256, uint256) internal view fnIn = _memcopyView; function(uint256, uint256, uint256) internal pure pureMemcopy; + /// @solidity memory-safe-assembly assembly { pureMemcopy := fnIn } @@ -33,6 +36,7 @@ library safeconsole { } function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { + /// @solidity memory-safe-assembly assembly { pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) } @@ -44,16 +48,18 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(sub(offset, 0x60)) m1 := mload(sub(offset, 0x40)) m2 := mload(sub(offset, 0x20)) - // Selector of `logBytes(bytes)`. - mstore(sub(offset, 0x60), 0xe17bf956) + // Selector of `log(bytes)`. + mstore(sub(offset, 0x60), 0x0be77f56) mstore(sub(offset, 0x40), 0x20) mstore(sub(offset, 0x20), length) } _sendLogPayload(offset - 0x44, length + 0x44); + /// @solidity memory-safe-assembly assembly { mstore(sub(offset, 0x60), m0) mstore(sub(offset, 0x40), m1) @@ -65,20 +71,23 @@ library safeconsole { bytes32 m1; bytes32 m2; uint256 endOffset = offset + length; + /// @solidity memory-safe-assembly assembly { m0 := mload(add(endOffset, 0x00)) m1 := mload(add(endOffset, 0x20)) m2 := mload(add(endOffset, 0x40)) } _memcopy(offset, offset + 0x60, length); + /// @solidity memory-safe-assembly assembly { - // Selector of `logBytes(bytes)`. - mstore(add(offset, 0x00), 0xe17bf956) + // Selector of `log(bytes)`. + mstore(add(offset, 0x00), 0x0be77f56) mstore(add(offset, 0x20), 0x20) mstore(add(offset, 0x40), length) } _sendLogPayload(offset + 0x1c, length + 0x44); _memcopy(offset + 0x60, offset, length); + /// @solidity memory-safe-assembly assembly { mstore(add(endOffset, 0x00), m0) mstore(add(endOffset, 0x20), m1) @@ -90,6 +99,7 @@ library safeconsole { function log(address p0) internal pure { bytes32 m0; bytes32 m1; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -98,6 +108,7 @@ library safeconsole { mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -107,6 +118,7 @@ library safeconsole { function log(bool p0) internal pure { bytes32 m0; bytes32 m1; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -115,6 +127,7 @@ library safeconsole { mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -124,6 +137,7 @@ library safeconsole { function log(uint256 p0) internal pure { bytes32 m0; bytes32 m1; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -132,6 +146,7 @@ library safeconsole { mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -143,6 +158,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -161,6 +177,7 @@ library safeconsole { writeString(0x40, p0) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -173,6 +190,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -183,6 +201,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -194,6 +213,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -204,6 +224,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -215,6 +236,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -225,6 +247,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -238,6 +261,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -258,6 +282,7 @@ library safeconsole { writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -271,6 +296,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -281,6 +307,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -292,6 +319,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -302,6 +330,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -313,6 +342,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -323,6 +353,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -336,6 +367,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -356,6 +388,7 @@ library safeconsole { writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -369,6 +402,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -379,6 +413,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -390,6 +425,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -400,6 +436,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -411,6 +448,7 @@ library safeconsole { bytes32 m0; bytes32 m1; bytes32 m2; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -421,6 +459,7 @@ library safeconsole { mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -434,6 +473,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -454,6 +494,7 @@ library safeconsole { writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -469,6 +510,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -489,6 +531,7 @@ library safeconsole { writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -504,6 +547,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -524,6 +568,7 @@ library safeconsole { writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -539,6 +584,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -559,6 +605,7 @@ library safeconsole { writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -576,6 +623,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -599,6 +647,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -615,6 +664,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -627,6 +677,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -640,6 +691,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -652,6 +704,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -665,6 +718,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -677,6 +731,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -692,6 +747,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -714,6 +770,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -729,6 +786,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -741,6 +799,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -754,6 +813,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -766,6 +826,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -779,6 +840,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -791,6 +853,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -806,6 +869,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -828,6 +892,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -843,6 +908,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -855,6 +921,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -868,6 +935,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -880,6 +948,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -893,6 +962,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -905,6 +975,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -920,6 +991,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -942,6 +1014,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -959,6 +1032,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -981,6 +1055,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -998,6 +1073,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1020,6 +1096,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1037,6 +1114,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1059,6 +1137,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1078,6 +1157,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1103,6 +1183,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1120,6 +1201,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1132,6 +1214,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1145,6 +1228,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1157,6 +1241,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1170,6 +1255,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1182,6 +1268,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1197,6 +1284,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1219,6 +1307,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1234,6 +1323,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1246,6 +1336,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1259,6 +1350,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1271,6 +1363,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1284,6 +1377,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1296,6 +1390,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1311,6 +1406,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1333,6 +1429,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1348,6 +1445,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1360,6 +1458,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1373,6 +1472,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1385,6 +1485,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1398,6 +1499,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1410,6 +1512,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1425,6 +1528,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1447,6 +1551,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1464,6 +1569,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1486,6 +1592,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1503,6 +1610,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1525,6 +1633,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1542,6 +1651,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1564,6 +1674,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1583,6 +1694,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1608,6 +1720,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1625,6 +1738,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1637,6 +1751,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1650,6 +1765,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1662,6 +1778,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1675,6 +1792,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1687,6 +1805,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1702,6 +1821,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1724,6 +1844,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1739,6 +1860,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1751,6 +1873,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1764,6 +1887,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1776,6 +1900,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1789,6 +1914,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1801,6 +1927,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1816,6 +1943,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1838,6 +1966,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1853,6 +1982,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1865,6 +1995,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1878,6 +2009,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1890,6 +2022,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1903,6 +2036,7 @@ library safeconsole { bytes32 m1; bytes32 m2; bytes32 m3; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -1915,6 +2049,7 @@ library safeconsole { mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1930,6 +2065,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1952,6 +2088,7 @@ library safeconsole { writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -1969,6 +2106,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -1991,6 +2129,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2008,6 +2147,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2030,6 +2170,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2047,6 +2188,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2069,6 +2211,7 @@ library safeconsole { writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2088,6 +2231,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2113,6 +2257,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2132,6 +2277,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2154,6 +2300,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2171,6 +2318,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2193,6 +2341,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2210,6 +2359,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2232,6 +2382,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2251,6 +2402,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2276,6 +2428,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2295,6 +2448,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2317,6 +2471,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2334,6 +2489,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2356,6 +2512,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2373,6 +2530,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2395,6 +2553,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2414,6 +2573,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2439,6 +2599,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2458,6 +2619,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2480,6 +2642,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2497,6 +2660,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2519,6 +2683,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2536,6 +2701,7 @@ library safeconsole { bytes32 m3; bytes32 m4; bytes32 m5; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2558,6 +2724,7 @@ library safeconsole { writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2577,6 +2744,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2602,6 +2770,7 @@ library safeconsole { writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2623,6 +2792,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2648,6 +2818,7 @@ library safeconsole { writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2669,6 +2840,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2694,6 +2866,7 @@ library safeconsole { writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2715,6 +2888,7 @@ library safeconsole { bytes32 m5; bytes32 m6; bytes32 m7; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2740,6 +2914,7 @@ library safeconsole { writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2763,6 +2938,7 @@ library safeconsole { bytes32 m7; bytes32 m8; bytes32 m9; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2791,6 +2967,7 @@ library safeconsole { writeString(0x100, p2) } _sendLogPayload(0x1c, 0x124); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2811,6 +2988,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -2825,6 +3003,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2840,6 +3019,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -2854,6 +3034,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2869,6 +3050,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -2883,6 +3065,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2900,6 +3083,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -2924,6 +3108,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2941,6 +3126,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -2955,6 +3141,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2970,6 +3157,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -2984,6 +3172,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -2999,6 +3188,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3013,6 +3203,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3030,6 +3221,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3054,6 +3246,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3071,6 +3264,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3085,6 +3279,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3100,6 +3295,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3114,6 +3310,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3129,6 +3326,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3143,6 +3341,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3160,6 +3359,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3184,6 +3384,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3203,6 +3404,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3227,6 +3429,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3246,6 +3449,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3270,6 +3474,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3289,6 +3494,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3313,6 +3519,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3334,6 +3541,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3361,6 +3569,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3380,6 +3589,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3394,6 +3604,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3409,6 +3620,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3423,6 +3635,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3438,6 +3651,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3452,6 +3666,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3469,6 +3684,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3493,6 +3709,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3510,6 +3727,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3524,6 +3742,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3539,6 +3758,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3553,6 +3773,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3568,6 +3789,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3582,6 +3804,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3599,6 +3822,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3623,6 +3847,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3640,6 +3865,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3654,6 +3880,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3669,6 +3896,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3683,6 +3911,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3698,6 +3927,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3712,6 +3942,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3729,6 +3960,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3753,6 +3985,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3772,6 +4005,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3796,6 +4030,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3815,6 +4050,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3839,6 +4075,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3858,6 +4095,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3882,6 +4120,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3903,6 +4142,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -3930,6 +4170,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3949,6 +4190,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3963,6 +4205,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -3978,6 +4221,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -3992,6 +4236,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4007,6 +4252,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4021,6 +4267,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4038,6 +4285,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4062,6 +4310,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4079,6 +4328,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4093,6 +4343,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4108,6 +4359,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4122,6 +4374,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4137,6 +4390,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4151,6 +4405,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4168,6 +4423,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4192,6 +4448,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4209,6 +4466,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4223,6 +4481,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4238,6 +4497,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4252,6 +4512,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4267,6 +4528,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -4281,6 +4543,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4298,6 +4561,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4322,6 +4586,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4341,6 +4606,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4365,6 +4631,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4384,6 +4651,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4408,6 +4676,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4427,6 +4696,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4451,6 +4721,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4472,6 +4743,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4499,6 +4771,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4520,6 +4793,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4544,6 +4818,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4563,6 +4838,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4587,6 +4863,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4606,6 +4883,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4630,6 +4908,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4651,6 +4930,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4678,6 +4958,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4699,6 +4980,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4723,6 +5005,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4742,6 +5025,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4766,6 +5050,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4785,6 +5070,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4809,6 +5095,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4830,6 +5117,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4857,6 +5145,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4878,6 +5167,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4902,6 +5192,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4921,6 +5212,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4945,6 +5237,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -4964,6 +5257,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -4988,6 +5282,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5009,6 +5304,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5036,6 +5332,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5059,6 +5356,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5086,6 +5384,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5109,6 +5408,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5136,6 +5436,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5159,6 +5460,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5186,6 +5488,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5211,6 +5514,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5241,6 +5545,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5262,6 +5567,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5276,6 +5582,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5291,6 +5598,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5305,6 +5613,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5320,6 +5629,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5334,6 +5644,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5351,6 +5662,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5375,6 +5687,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5392,6 +5705,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5406,6 +5720,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5421,6 +5736,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5435,6 +5751,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5450,6 +5767,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5464,6 +5782,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5481,6 +5800,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5505,6 +5825,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5522,6 +5843,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5536,6 +5858,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5551,6 +5874,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5565,6 +5889,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5580,6 +5905,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5594,6 +5920,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5611,6 +5938,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5635,6 +5963,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5654,6 +5983,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5678,6 +6008,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5697,6 +6028,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5721,6 +6053,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5740,6 +6073,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5764,6 +6098,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5785,6 +6120,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5812,6 +6148,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5831,6 +6168,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5845,6 +6183,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5860,6 +6199,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5874,6 +6214,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5889,6 +6230,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5903,6 +6245,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5920,6 +6263,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -5944,6 +6288,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5961,6 +6306,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -5975,6 +6321,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -5990,6 +6337,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6004,6 +6352,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6019,6 +6368,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6033,6 +6383,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6050,6 +6401,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6074,6 +6426,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6091,6 +6444,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6105,6 +6459,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6120,6 +6475,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6134,6 +6490,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6149,6 +6506,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6163,6 +6521,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6180,6 +6539,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6204,6 +6564,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6223,6 +6584,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6247,6 +6609,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6266,6 +6629,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6290,6 +6654,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6309,6 +6674,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6333,6 +6699,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6354,6 +6721,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6381,6 +6749,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6400,6 +6769,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6414,6 +6784,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6429,6 +6800,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6443,6 +6815,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6458,6 +6831,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6472,6 +6846,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6489,6 +6864,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6513,6 +6889,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6530,6 +6907,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6544,6 +6922,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6559,6 +6938,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6573,6 +6953,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6588,6 +6969,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6602,6 +6984,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6619,6 +7002,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6643,6 +7027,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6660,6 +7045,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6674,6 +7060,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6689,6 +7076,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6703,6 +7091,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6718,6 +7107,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -6732,6 +7122,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6749,6 +7140,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6773,6 +7165,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6792,6 +7185,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6816,6 +7210,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6835,6 +7230,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6859,6 +7255,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6878,6 +7275,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6902,6 +7300,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6923,6 +7322,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6950,6 +7350,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -6971,6 +7372,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -6995,6 +7397,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7014,6 +7417,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7038,6 +7442,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7057,6 +7462,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7081,6 +7487,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7102,6 +7509,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7129,6 +7537,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7150,6 +7559,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7174,6 +7584,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7193,6 +7604,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7217,6 +7629,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7236,6 +7649,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7260,6 +7674,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7281,6 +7696,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7308,6 +7724,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7329,6 +7746,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7353,6 +7771,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7372,6 +7791,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7396,6 +7816,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7415,6 +7836,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7439,6 +7861,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7460,6 +7883,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7487,6 +7911,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7510,6 +7935,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7537,6 +7963,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7560,6 +7987,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7587,6 +8015,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7610,6 +8039,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7637,6 +8067,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7662,6 +8093,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7692,6 +8124,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7713,6 +8146,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7727,6 +8161,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7742,6 +8177,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7756,6 +8192,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7771,6 +8208,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7785,6 +8223,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7802,6 +8241,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7826,6 +8266,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7843,6 +8284,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7857,6 +8299,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7872,6 +8315,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7886,6 +8330,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7901,6 +8346,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7915,6 +8361,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7932,6 +8379,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -7956,6 +8404,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -7973,6 +8422,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -7987,6 +8437,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8002,6 +8453,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8016,6 +8468,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8031,6 +8484,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8045,6 +8499,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8062,6 +8517,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8086,6 +8542,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8105,6 +8562,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8129,6 +8587,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8148,6 +8607,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8172,6 +8632,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8191,6 +8652,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8215,6 +8677,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8236,6 +8699,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8263,6 +8727,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8282,6 +8747,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8296,6 +8762,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8311,6 +8778,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8325,6 +8793,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8340,6 +8809,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8354,6 +8824,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8371,6 +8842,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8395,6 +8867,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8412,6 +8885,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8426,6 +8900,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8441,6 +8916,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8455,6 +8931,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8470,6 +8947,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8484,6 +8962,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8501,6 +8980,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8525,6 +9005,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8542,6 +9023,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8556,6 +9038,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8571,6 +9054,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8585,6 +9069,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8600,6 +9085,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8614,6 +9100,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8631,6 +9118,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8655,6 +9143,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8674,6 +9163,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8698,6 +9188,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8717,6 +9208,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8741,6 +9233,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8760,6 +9253,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8784,6 +9278,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8805,6 +9300,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8832,6 +9328,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8851,6 +9348,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8865,6 +9363,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8880,6 +9379,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8894,6 +9394,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8909,6 +9410,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8923,6 +9425,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8940,6 +9443,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -8964,6 +9468,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -8981,6 +9486,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -8995,6 +9501,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9010,6 +9517,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -9024,6 +9532,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9039,6 +9548,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -9053,6 +9563,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9070,6 +9581,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9094,6 +9606,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9111,6 +9624,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -9125,6 +9639,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9140,6 +9655,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -9154,6 +9670,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9169,6 +9686,7 @@ library safeconsole { bytes32 m2; bytes32 m3; bytes32 m4; + /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) @@ -9183,6 +9701,7 @@ library safeconsole { mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9200,6 +9719,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9224,6 +9744,7 @@ library safeconsole { writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9243,6 +9764,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9267,6 +9789,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9286,6 +9809,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9310,6 +9834,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9329,6 +9854,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9353,6 +9879,7 @@ library safeconsole { writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9374,6 +9901,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9401,6 +9929,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9422,6 +9951,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9446,6 +9976,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9465,6 +9996,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9489,6 +10021,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9508,6 +10041,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9532,6 +10066,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9553,6 +10088,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9580,6 +10116,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9601,6 +10138,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9625,6 +10163,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9644,6 +10183,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9668,6 +10208,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9687,6 +10228,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9711,6 +10253,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9732,6 +10275,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9759,6 +10303,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9780,6 +10325,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9804,6 +10350,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9823,6 +10370,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9847,6 +10395,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9866,6 +10415,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9890,6 +10440,7 @@ library safeconsole { writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9911,6 +10462,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9938,6 +10490,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -9961,6 +10514,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -9988,6 +10542,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10011,6 +10566,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10038,6 +10594,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10061,6 +10618,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10088,6 +10646,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10113,6 +10672,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10143,6 +10703,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10166,6 +10727,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10190,6 +10752,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10209,6 +10772,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10233,6 +10797,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10252,6 +10817,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10276,6 +10842,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10297,6 +10864,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10324,6 +10892,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10345,6 +10914,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10369,6 +10939,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10388,6 +10959,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10412,6 +10984,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10431,6 +11004,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10455,6 +11029,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10476,6 +11051,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10503,6 +11079,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10524,6 +11101,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10548,6 +11126,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10567,6 +11146,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10591,6 +11171,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10610,6 +11191,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10634,6 +11216,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10655,6 +11238,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10682,6 +11266,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10705,6 +11290,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10732,6 +11318,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10755,6 +11342,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10782,6 +11370,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10805,6 +11394,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10832,6 +11422,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10857,6 +11448,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10887,6 +11479,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10910,6 +11503,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10934,6 +11528,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10953,6 +11548,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -10977,6 +11573,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -10996,6 +11593,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11020,6 +11618,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11041,6 +11640,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11068,6 +11668,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11089,6 +11690,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11113,6 +11715,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11132,6 +11735,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11156,6 +11760,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11175,6 +11780,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11199,6 +11805,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11220,6 +11827,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11247,6 +11855,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11268,6 +11877,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11292,6 +11902,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11311,6 +11922,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11335,6 +11947,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11354,6 +11967,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11378,6 +11992,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11399,6 +12014,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11426,6 +12042,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11449,6 +12066,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11476,6 +12094,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11499,6 +12118,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11526,6 +12146,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11549,6 +12170,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11576,6 +12198,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11601,6 +12224,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11631,6 +12255,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11654,6 +12279,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11678,6 +12304,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11697,6 +12324,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11721,6 +12349,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11740,6 +12369,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11764,6 +12394,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11785,6 +12416,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11812,6 +12444,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11833,6 +12466,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11857,6 +12491,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11876,6 +12511,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11900,6 +12536,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11919,6 +12556,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11943,6 +12581,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -11964,6 +12603,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -11991,6 +12631,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12012,6 +12653,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12036,6 +12678,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12055,6 +12698,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12079,6 +12723,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12098,6 +12743,7 @@ library safeconsole { bytes32 m4; bytes32 m5; bytes32 m6; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12122,6 +12768,7 @@ library safeconsole { writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12143,6 +12790,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12170,6 +12818,7 @@ library safeconsole { writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12193,6 +12842,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12220,6 +12870,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12243,6 +12894,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12270,6 +12922,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12293,6 +12946,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12320,6 +12974,7 @@ library safeconsole { writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12345,6 +13000,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12375,6 +13031,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12400,6 +13057,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12427,6 +13085,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12450,6 +13109,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12477,6 +13137,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12500,6 +13161,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12527,6 +13189,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12552,6 +13215,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12582,6 +13246,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12607,6 +13272,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12634,6 +13300,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12657,6 +13324,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12684,6 +13352,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12707,6 +13376,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12734,6 +13404,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12759,6 +13430,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12789,6 +13461,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12814,6 +13487,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12841,6 +13515,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12864,6 +13539,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12891,6 +13567,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12914,6 +13591,7 @@ library safeconsole { bytes32 m6; bytes32 m7; bytes32 m8; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12941,6 +13619,7 @@ library safeconsole { writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -12966,6 +13645,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -12996,6 +13676,7 @@ library safeconsole { writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -13023,6 +13704,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -13053,6 +13735,7 @@ library safeconsole { writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -13080,6 +13763,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -13110,6 +13794,7 @@ library safeconsole { writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -13137,6 +13822,7 @@ library safeconsole { bytes32 m8; bytes32 m9; bytes32 m10; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -13167,6 +13853,7 @@ library safeconsole { writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) @@ -13196,6 +13883,7 @@ library safeconsole { bytes32 m10; bytes32 m11; bytes32 m12; + /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 @@ -13229,6 +13917,7 @@ library safeconsole { writeString(0x160, p3) } _sendLogPayload(0x1c, 0x184); + /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol new file mode 100644 index 00000000000..2e9c4a2da75 --- /dev/null +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol @@ -0,0 +1,773 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface.sol"; +import {VRFOld} from "./VRFOld.sol"; +import {VRFTypes} from "../../VRFTypes.sol"; +import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {SubscriptionAPI} from "../SubscriptionAPI.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; +import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; +// solhint-disable-next-line no-unused-import +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract VRFCoordinatorTestV2_5 is VRFOld, SubscriptionAPI, IVRFCoordinatorV2Plus { + /// @dev should always be available + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + BlockhashStoreInterface public immutable BLOCKHASH_STORE; + + // Set this maximum to 200 to give us a 56 block window to fulfill + // the request before requiring the block hash feeder. + uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; + uint32 public constant MAX_NUM_WORDS = 500; + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + // upper bound limit for premium percentages to make sure fee calculations don't overflow + uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; + error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); + error GasLimitTooBig(uint32 have, uint32 want); + error NumWordsTooBig(uint32 have, uint32 want); + error MsgDataTooBig(uint256 have, uint32 max); + error ProvingKeyAlreadyRegistered(bytes32 keyHash); + error NoSuchProvingKey(bytes32 keyHash); + error InvalidLinkWeiPrice(int256 linkWei); + error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); + error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); + error NoCorrespondingRequest(); + error IncorrectCommitment(); + error BlockhashNotInStore(uint256 blockNum); + error PaymentTooLarge(); + error InvalidExtraArgsTag(); + error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); + + struct ProvingKey { + bool exists; // proving key exists + uint64 maxGas; // gas lane max gas price for fulfilling requests + } + + mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; + bytes32[] public s_provingKeyHashes; + mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); + event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + int256 public s_fallbackWeiPerUnitLink; + + event ConfigSet( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ); + + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + + constructor(address blockhashStore) SubscriptionAPI() { + BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); + } + + /** + * @notice Registers a proving key to. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + if (s_provingKeys[kh].exists) { + revert ProvingKeyAlreadyRegistered(kh); + } + s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); + s_provingKeyHashes.push(kh); + emit ProvingKeyRegistered(kh, maxGas); + } + + /** + * @notice Deregisters a proving key. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + ProvingKey memory key = s_provingKeys[kh]; + if (!key.exists) { + revert NoSuchProvingKey(kh); + } + delete s_provingKeys[kh]; + uint256 s_provingKeyHashesLength = s_provingKeyHashes.length; + for (uint256 i = 0; i < s_provingKeyHashesLength; ++i) { + if (s_provingKeyHashes[i] == kh) { + // Copy last element and overwrite kh to be deleted with it + s_provingKeyHashes[i] = s_provingKeyHashes[s_provingKeyHashesLength - 1]; + s_provingKeyHashes.pop(); + break; + } + } + emit ProvingKeyDeregistered(kh, key.maxGas); + } + + /** + * @notice Returns the proving key hash key associated with this public key + * @param publicKey the key to return the hash of + */ + function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed + * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment + * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native + * @param nativePremiumPercentage native premium percentage + * @param linkPremiumPercentage link premium percentage + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ) external onlyOwner { + if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { + revert InvalidRequestConfirmations( + minimumRequestConfirmations, + minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + if (fallbackWeiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); + } + if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { + revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); + } + if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + s_config = Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage: nativePremiumPercentage, + linkPremiumPercentage: linkPremiumPercentage + }); + s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; + emit ConfigSet( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage, + linkPremiumPercentage + ); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + /** + * @notice Request a set of random words. + * @param req - a struct containing following fiels for randomness request: + * keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * requestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * extraArgs - Encoded extra arguments that has a boolean flag for whether payment + * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata req + ) external override nonReentrant returns (uint256 requestId) { + // Input validation using the subscription storage. + uint256 subId = req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // Its important to ensure that the consumer is in fact who they say they + // are, otherwise they could use someone else's subscription balance. + mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; + ConsumerConfig memory consumerConfig = consumerConfigs[subId]; + if (!consumerConfig.active) { + revert InvalidConsumer(subId, msg.sender); + } + // Input validation using the config storage word. + if ( + req.requestConfirmations < s_config.minimumRequestConfirmations || + req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS + ) { + revert InvalidRequestConfirmations( + req.requestConfirmations, + s_config.minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + // No lower bound on the requested gas limit. A user could request 0 + // and they would simply be billed for the proof verification and wouldn't be + // able to do anything with the random value. + if (req.callbackGasLimit > s_config.maxGasLimit) { + revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); + } + if (req.numWords > MAX_NUM_WORDS) { + revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); + } + + // Note we do not check whether the keyHash is valid to save gas. + // The consequence for users is that they can send requests + // for invalid keyHashes which will simply not be fulfilled. + ++consumerConfig.nonce; + ++consumerConfig.pendingReqCount; + uint256 preSeed; + (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); + s_requestCommitments[requestId] = keccak256( + abi.encode( + requestId, + ChainSpecificUtil._getBlockNumber(), + subId, + req.callbackGasLimit, + req.numWords, + msg.sender, + extraArgsBytes + ) + ); + emit RandomWordsRequested( + req.keyHash, + requestId, + preSeed, + subId, + req.requestConfirmations, + req.callbackGasLimit, + req.numWords, + extraArgsBytes, + msg.sender + ); + consumerConfigs[subId] = consumerConfig; + + return requestId; + } + + function _computeRequestId( + bytes32 keyHash, + address sender, + uint256 subId, + uint64 nonce + ) internal pure returns (uint256, uint256) { + uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); + return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + struct Output { + ProvingKey provingKey; + uint256 requestId; + uint256 randomness; + } + + function _getRandomnessFromProof( + Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc + ) internal view returns (Output memory) { + bytes32 keyHash = hashOfKey(proof.pk); + ProvingKey memory key = s_provingKeys[keyHash]; + // Only registered proving keys are permitted. + if (!key.exists) { + revert NoSuchProvingKey(keyHash); + } + uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); + bytes32 commitment = s_requestCommitments[requestId]; + if (commitment == 0) { + revert NoCorrespondingRequest(); + } + if ( + commitment != + keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) + ) { + revert IncorrectCommitment(); + } + + bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + revert BlockhashNotInStore(rc.blockNum); + } + } + + // The seed actually used by the VRF machinery, mixing in the blockhash + uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); + uint256 randomness = VRFOld._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure + return Output(key, requestId, randomness); + } + + function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { + if (tx.gasprice > gasLaneMaxGas) { + if (onlyPremium) { + // if only the premium amount needs to be billed, then the premium is capped by the gas lane max + return uint256(gasLaneMaxGas); + } else { + // Ensure gas price does not exceed the gas lane max gas price + revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); + } + } + return tx.gasprice; + } + + function _deliverRandomness( + uint256 requestId, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256[] memory randomWords + ) internal returns (bool success) { + VRFConsumerBaseV2Plus v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that _callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + return success; + } + + /* + * @notice Fulfill a randomness request. + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + * @param onlyPremium only charge premium + * @return payment amount billed to the subscription + * @dev simulated offchain to determine if sufficient balance is present to fulfill the request + */ + function fulfillRandomWords( + Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + bool onlyPremium + ) external nonReentrant returns (uint96 payment) { + uint256 startGas = gasleft(); + // fulfillRandomWords msg.data has 772 bytes and with an additional + // buffer of 32 bytes, we get 804 bytes. + /* Data size split: + * fulfillRandomWords function signature - 4 bytes + * proof - 416 bytes + * pk - 64 bytes + * gamma - 64 bytes + * c - 32 bytes + * s - 32 bytes + * seed - 32 bytes + * uWitness - 32 bytes + * cGammaWitness - 64 bytes + * sHashWitness - 64 bytes + * zInv - 32 bytes + * requestCommitment - 320 bytes + * blockNum - 32 bytes + * subId - 32 bytes + * callbackGasLimit - 32 bytes + * numWords - 32 bytes + * sender - 32 bytes + * extraArgs - 128 bytes + * onlyPremium - 32 bytes + */ + if (msg.data.length > 804) { + revert MsgDataTooBig(msg.data.length, 804); + } + Output memory output = _getRandomnessFromProof(proof, rc); + uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); + + uint256[] memory randomWords; + uint256 randomness = output.randomness; + // stack too deep error + { + uint256 numWords = rc.numWords; + randomWords = new uint256[](numWords); + for (uint256 i = 0; i < numWords; ++i) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } + } + + delete s_requestCommitments[output.requestId]; + bool success = _deliverRandomness(output.requestId, rc, randomWords); + + // Increment the req count for the subscription. + ++s_subscriptions[rc.subId].reqCount; + // Decrement the pending req count for the consumer. + --s_consumers[rc.sender][rc.subId].pendingReqCount; + + bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; + + // stack too deep error + { + // We want to charge users exactly for how much gas they use in their callback with + // an additional premium. If onlyPremium is true, only premium is charged without + // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional + // operations where we decrement the subscription balance and increment the + // withdrawable balance. + bool isFeedStale; + (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); + if (isFeedStale) { + emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); + } + } + + _chargePayment(payment, nativePayment, rc.subId); + + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); + + return payment; + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + function _calculatePaymentAmount( + uint256 startGas, + uint256 weiPerUnitGas, + bool nativePayment, + bool onlyPremium + ) internal view returns (uint96, bool) { + if (nativePayment) { + return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); + } + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); + } + + function _calculatePaymentAmountNative( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96) { + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // calculate the payment without the premium + uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); + // calculate flat fee in native + uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); + if (onlyPremium) { + return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } else { + return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } + } + + // Get the amount of gas used for fulfillment + function _calculatePaymentAmountLink( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96, bool) { + (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * + (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / + uint256(weiPerUnitLink); + // calculate the flat fee in wei + uint256 flatFeeWei = 1e12 * + uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); + uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); + uint256 payment; + if (onlyPremium) { + payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } else { + payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } + if (payment > 1e27) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return (uint96(payment), isFeedStale); + } + + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + uint256 timestamp; + (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; + if (isFeedStale) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return (weiPerUnitLink, isFeedStale); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function pendingRequestExists(uint256 subId) public view override returns (bool) { + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + uint256 consumersLength = consumers.length; + if (consumersLength == 0) { + return false; + } + for (uint256 i = 0; i < consumersLength; ++i) { + if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { + return true; + } + } + return false; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + if (!s_consumers[consumer][subId].active) { + revert InvalidConsumer(subId, consumer); + } + // Note bounded by MAX_CONSUMERS + address[] memory consumers = s_subscriptionConfigs[subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == consumer) { + address last = consumers[lastConsumerIndex]; + // Storage write to preserve last element + s_subscriptionConfigs[subId].consumers[i] = last; + // Storage remove last element + s_subscriptionConfigs[subId].consumers.pop(); + break; + } + } + s_consumers[consumer][subId].active = false; + emit SubscriptionConsumerRemoved(subId, consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + _cancelSubscriptionHelper(subId, to); + } + + /*************************************************************************** + * Section: Migration + ***************************************************************************/ + + address[] internal s_migrationTargets; + + /// @dev Emitted when new coordinator is registered as migratable target + event CoordinatorRegistered(address coordinatorAddress); + + /// @dev Emitted when new coordinator is deregistered + event CoordinatorDeregistered(address coordinatorAddress); + + /// @notice emitted when migration to new coordinator completes successfully + /// @param newCoordinator coordinator address after migration + /// @param subId subscription ID + event MigrationCompleted(address newCoordinator, uint256 subId); + + /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target + error CoordinatorNotRegistered(address coordinatorAddress); + + /// @notice emitted when migrate() is called and given coordinator is registered as migratable target + error CoordinatorAlreadyRegistered(address coordinatorAddress); + + /// @dev encapsulates data to be migrated from current coordinator + // solhint-disable-next-line gas-struct-packing + struct V1MigrationData { + uint8 fromVersion; + uint256 subId; + address subOwner; + address[] consumers; + uint96 linkBalance; + uint96 nativeBalance; + } + + function _isTargetRegistered(address target) internal view returns (bool) { + uint256 migrationTargetsLength = s_migrationTargets.length; + for (uint256 i = 0; i < migrationTargetsLength; ++i) { + if (s_migrationTargets[i] == target) { + return true; + } + } + return false; + } + + function registerMigratableCoordinator(address target) external onlyOwner { + if (_isTargetRegistered(target)) { + revert CoordinatorAlreadyRegistered(target); + } + s_migrationTargets.push(target); + emit CoordinatorRegistered(target); + } + + function deregisterMigratableCoordinator(address target) external onlyOwner { + uint256 nTargets = s_migrationTargets.length; + for (uint256 i = 0; i < nTargets; ++i) { + if (s_migrationTargets[i] == target) { + s_migrationTargets[i] = s_migrationTargets[nTargets - 1]; + s_migrationTargets.pop(); + emit CoordinatorDeregistered(target); + return; + } + } + revert CoordinatorNotRegistered(target); + } + + function migrate(uint256 subId, address newCoordinator) external nonReentrant { + if (!_isTargetRegistered(newCoordinator)) { + revert CoordinatorNotRegistered(newCoordinator); + } + (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); + // solhint-disable-next-line gas-custom-errors + require(subOwner == msg.sender, "Not subscription owner"); + // solhint-disable-next-line gas-custom-errors + require(!pendingRequestExists(subId), "Pending request exists"); + + V1MigrationData memory migrationData = V1MigrationData({ + fromVersion: 1, + subId: subId, + subOwner: subOwner, + consumers: consumers, + linkBalance: balance, + nativeBalance: nativeBalance + }); + bytes memory encodedData = abi.encode(migrationData); + _deleteSubscription(subId); + IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); + + // Only transfer LINK if the token is active and there is a balance. + if (address(LINK) != address(0) && balance != 0) { + // solhint-disable-next-line gas-custom-errors + require(LINK.transfer(address(newCoordinator), balance), "insufficient funds"); + } + + // despite the fact that we follow best practices this is still probably safest + // to prevent any re-entrancy possibilities. + s_config.reentrancyLock = true; + for (uint256 i = 0; i < consumers.length; ++i) { + IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); + } + s_config.reentrancyLock = false; + + emit MigrationCompleted(newCoordinator, subId); + } +} diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol new file mode 100644 index 00000000000..137235fd0a3 --- /dev/null +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol @@ -0,0 +1,588 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** **************************************************************************** + * @notice Verification of verifiable-random-function (VRF) proofs, following + * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 + * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. + + * @dev Bibliographic references: + + * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft + * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 + + * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology + * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf + * **************************************************************************** + * @dev USAGE + + * @dev The main entry point is _randomValueFromVRFProof. See its docstring. + * **************************************************************************** + * @dev PURPOSE + + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is computationally indistinguishable to her from a uniform + * @dev random sample from the output space. + + * @dev The purpose of this contract is to perform that verification. + * **************************************************************************** + * @dev DESIGN NOTES + + * @dev The VRF algorithm verified here satisfies the full uniqueness, full + * @dev collision resistance, and full pseudo-randomness security properties. + * @dev See "SECURITY PROPERTIES" below, and + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 + + * @dev An elliptic curve point is generally represented in the solidity code + * @dev as a uint256[2], corresponding to its affine coordinates in + * @dev GF(FIELD_SIZE). + + * @dev For the sake of efficiency, this implementation deviates from the spec + * @dev in some minor ways: + + * @dev - Keccak hash rather than the SHA256 hash recommended in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 + * @dev Keccak costs much less gas on the EVM, and provides similar security. + + * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 + * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER + + * @dev - _hashToCurve recursively hashes until it finds a curve x-ordinate. On + * @dev the EVM, this is slightly more efficient than the recommendation in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 + * @dev step 5, to concatenate with a nonce then hash, and rehash with the + * @dev nonce updated until a valid x-ordinate is found. + + * @dev - _hashToCurve does not include a cipher version string or the byte 0x1 + * @dev in the hash message, as recommended in step 5.B of the draft + * @dev standard. They are unnecessary here because no variation in the + * @dev cipher suite is allowed. + + * @dev - Similarly, the hash input in _scalarFromCurvePoints does not include a + * @dev commitment to the cipher suite, either, which differs from step 2 of + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 + * @dev . Also, the hash input is the concatenation of the uncompressed + * @dev points, not the compressed points as recommended in step 3. + + * @dev - In the calculation of the challenge value "c", the "u" value (i.e. + * @dev the value computed by Reggie as the nonce times the secp256k1 + * @dev generator point, see steps 5 and 7 of + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 + * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the + * @dev keccak hash of the original u. This is because we only verify the + * @dev calculation of u up to its address, by abusing ECRECOVER. + * **************************************************************************** + * @dev SECURITY PROPERTIES + + * @dev Here are the security properties for this VRF: + + * @dev Full uniqueness: For any seed and valid VRF public key, there is + * @dev exactly one VRF output which can be proved to come from that seed, in + * @dev the sense that the proof will pass _verifyVRFProof. + + * @dev Full collision resistance: It's cryptographically infeasible to find + * @dev two seeds with same VRF output from a fixed, valid VRF key + + * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are + * @dev derived from a given seed, the outputs are computationally + * @dev indistinguishable from randomness. + + * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs + * @dev for these properties. + + * @dev For secp256k1, the key validation described in section + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 + * @dev is unnecessary, because secp256k1 has cofactor 1, and the + * @dev representation of the public key used here (affine x- and y-ordinates + * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to + * @dev the point at infinity. + * **************************************************************************** + * @dev OTHER SECURITY CONSIDERATIONS + * + * @dev The seed input to the VRF could in principle force an arbitrary amount + * @dev of work in _hashToCurve, by requiring extra rounds of hashing and + * @dev checking whether that's yielded the x ordinate of a secp256k1 point. + * @dev However, under the Random Oracle Model the probability of choosing a + * @dev point which forces n extra rounds in _hashToCurve is 2⁻ⁿ. The base cost + * @dev for calling _hashToCurve is about 25,000 gas, and each round of checking + * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for + * @dev which _hashToCurve would cost more than 2,017,000 gas, one would have to + * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any + * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) + + * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, + * @dev this means it is infeasible for an adversary to prevent correct + * @dev operation of this contract by choosing an adverse seed. + + * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for + * @dev _hashToCurve.) + + * @dev It may be possible to make a secure constant-time _hashToCurve function. + * @dev See notes in _hashToCurve docstring. +*/ +contract VRFOld { + // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. + // Number of points in Secp256k1 + uint256 private constant GROUP_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; + // Prime characteristic of the galois field over which Secp256k1 is defined + uint256 private constant FIELD_SIZE = + // solium-disable-next-line indentation + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; + uint256 private constant WORD_LENGTH_BYTES = 0x20; + + // (base^exponent) % FIELD_SIZE + // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 + function _bigModExp(uint256 base, uint256 exponent) internal view returns (uint256 exponentiation) { + uint256 callResult; + uint256[6] memory bigModExpContractInputs; + bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base + bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent + bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus + bigModExpContractInputs[3] = base; + bigModExpContractInputs[4] = exponent; + bigModExpContractInputs[5] = FIELD_SIZE; + uint256[1] memory output; + assembly { + callResult := staticcall( + not(0), // Gas cost: no limit + 0x05, // Bigmodexp contract address + bigModExpContractInputs, + 0xc0, // Length of input segment: 6*0x20-bytes + output, + 0x20 // Length of output segment + ) + } + if (callResult == 0) { + // solhint-disable-next-line gas-custom-errors + revert("bigModExp failure!"); + } + return output[0]; + } + + // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See + // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus + uint256 private constant SQRT_POWER = (FIELD_SIZE + 1) >> 2; + + // Computes a s.t. a^2 = x in the field. Assumes a exists + function _squareRoot(uint256 x) internal view returns (uint256) { + return _bigModExp(x, SQRT_POWER); + } + + // The value of y^2 given that (x,y) is on secp256k1. + function _ySquared(uint256 x) internal pure returns (uint256) { + // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf + uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); + return addmod(xCubed, 7, FIELD_SIZE); + } + + // True iff p is on secp256k1 + function _isOnCurve(uint256[2] memory p) internal pure returns (bool) { + // Section 2.3.6. in https://www.secg.org/sec1-v2.pdf + // requires each ordinate to be in [0, ..., FIELD_SIZE-1] + // solhint-disable-next-line gas-custom-errors + require(p[0] < FIELD_SIZE, "invalid x-ordinate"); + // solhint-disable-next-line gas-custom-errors + require(p[1] < FIELD_SIZE, "invalid y-ordinate"); + return _ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); + } + + // Hash x uniformly into {0, ..., FIELD_SIZE-1}. + function _fieldHash(bytes memory b) internal pure returns (uint256 x_) { + x_ = uint256(keccak256(b)); + // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of + // http://www.secg.org/sec1-v2.pdf , which is part of the definition of + // string_to_point in the IETF draft + while (x_ >= FIELD_SIZE) { + x_ = uint256(keccak256(abi.encodePacked(x_))); + } + return x_; + } + + // Hash b to a random point which hopefully lies on secp256k1. The y ordinate + // is always even, due to + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 + // step 5.C, which references arbitrary_string_to_point, defined in + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as + // returning the point with given x ordinate, and even y ordinate. + function _newCandidateSecp256k1Point(bytes memory b) internal view returns (uint256[2] memory p) { + unchecked { + p[0] = _fieldHash(b); + p[1] = _squareRoot(_ySquared(p[0])); + if (p[1] % 2 == 1) { + // Note that 0 <= p[1] < FIELD_SIZE + // so this cannot wrap, we use unchecked to save gas. + p[1] = FIELD_SIZE - p[1]; + } + } + return p; + } + + // Domain-separation tag for initial hash in _hashToCurve. Corresponds to + // vrf.go/hashToCurveHashPrefix + uint256 internal constant HASH_TO_CURVE_HASH_PREFIX = 1; + + // Cryptographic hash function onto the curve. + // + // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see + // DESIGN NOTES above for slight differences.) + // + // TODO(alx): Implement a bounded-computation hash-to-curve, as described in + // "Construction of Rational Points on Elliptic Curves over Finite Fields" + // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf + // and suggested by + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 + // (Though we can't used exactly that because secp256k1's j-invariant is 0.) + // + // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" + // https://www.pivotaltracker.com/story/show/171120900 + function _hashToCurve(uint256[2] memory pk, uint256 input) internal view returns (uint256[2] memory rv) { + rv = _newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, pk, input)); + while (!_isOnCurve(rv)) { + rv = _newCandidateSecp256k1Point(abi.encodePacked(rv[0])); + } + return rv; + } + + /** ********************************************************************* + * @notice Check that product==scalar*multiplicand + * + * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. + * + * @param multiplicand: secp256k1 point + * @param scalar: non-zero GF(GROUP_ORDER) scalar + * @param product: secp256k1 expected to be multiplier * multiplicand + * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability + */ + function _ecmulVerify( + uint256[2] memory multiplicand, + uint256 scalar, + uint256[2] memory product + ) internal pure returns (bool verifies) { + // solhint-disable-next-line gas-custom-errors + require(scalar != 0, "zero scalar"); // Rules out an ecrecover failure case + uint256 x = multiplicand[0]; // x ordinate of multiplicand + uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate + // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 + // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is + // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. + // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 + bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); + address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); + // Explicit conversion to address takes bottom 160 bits + address expected = address(uint160(uint256(keccak256(abi.encodePacked(product))))); + return (actual == expected); + } + + // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) + function _projectiveSub( + uint256 x1, + uint256 z1, + uint256 x2, + uint256 z2 + ) internal pure returns (uint256 x3, uint256 z3) { + unchecked { + uint256 num1 = mulmod(z2, x1, FIELD_SIZE); + // Note this cannot wrap since x2 is a point in [0, FIELD_SIZE-1] + // we use unchecked to save gas. + uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); + (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); + } + return (x3, z3); + } + + // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) + function _projectiveMul( + uint256 x1, + uint256 z1, + uint256 x2, + uint256 z2 + ) internal pure returns (uint256 x3, uint256 z3) { + (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); + return (x3, z3); + } + + /** ************************************************************************** + @notice Computes elliptic-curve sum, in projective co-ordinates + + @dev Using projective coordinates avoids costly divisions + + @dev To use this with p and q in affine coordinates, call + @dev _projectiveECAdd(px, py, qx, qy). This will return + @dev the addition of (px, py, 1) and (qx, qy, 1), in the + @dev secp256k1 group. + + @dev This can be used to calculate the z which is the inverse to zInv + @dev in isValidVRFOutput. But consider using a faster + @dev re-implementation such as ProjectiveECAdd in the golang vrf package. + + @dev This function assumes [px,py,1],[qx,qy,1] are valid projective + coordinates of secp256k1 points. That is safe in this contract, + because this method is only used by _linearCombination, which checks + points are on the curve via ecrecover. + ************************************************************************** + @param px The first affine coordinate of the first summand + @param py The second affine coordinate of the first summand + @param qx The first affine coordinate of the second summand + @param qy The second affine coordinate of the second summand + + (px,py) and (qx,qy) must be distinct, valid secp256k1 points. + ************************************************************************** + Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points + on secp256k1, in P²(𝔽ₙ) + @return sx + @return sy + @return sz + */ + function _projectiveECAdd( + uint256 px, + uint256 py, + uint256 qx, + uint256 qy + ) internal pure returns (uint256 sx, uint256 sy, uint256 sz) { + unchecked { + // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, + // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone + // We take the equations there for (sx,sy), and homogenize them to + // projective coordinates. That way, no inverses are required, here, and we + // only need the one inverse in _affineECAdd. + + // We only need the "point addition" equations from Hankerson et al. Can + // skip the "point doubling" equations because p1 == p2 is cryptographically + // impossible, and required not to be the case in _linearCombination. + + // Add extra "projective coordinate" to the two points + (uint256 z1, uint256 z2) = (1, 1); + + // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. + // Cannot wrap since px and py are in [0, FIELD_SIZE-1] + uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); + uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); + + uint256 dx; // Accumulates denominator from sx calculation + // sx=((qy-py)/(qx-px))^2-px-qx + (sx, dx) = _projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 + (sx, dx) = _projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px + (sx, dx) = _projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx + + uint256 dy; // Accumulates denominator from sy calculation + // sy=((qy-py)/(qx-px))(px-sx)-py + (sy, dy) = _projectiveSub(px, z1, sx, dx); // px-sx + (sy, dy) = _projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) + (sy, dy) = _projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py + + if (dx != dy) { + // Cross-multiply to put everything over a common denominator + sx = mulmod(sx, dy, FIELD_SIZE); + sy = mulmod(sy, dx, FIELD_SIZE); + sz = mulmod(dx, dy, FIELD_SIZE); + } else { + // Already over a common denominator, use that for z ordinate + sz = dx; + } + } + return (sx, sy, sz); + } + + // p1+p2, as affine points on secp256k1. + // + // invZ must be the inverse of the z returned by _projectiveECAdd(p1, p2). + // It is computed off-chain to save gas. + // + // p1 and p2 must be distinct, because _projectiveECAdd doesn't handle + // point doubling. + function _affineECAdd( + uint256[2] memory p1, + uint256[2] memory p2, + uint256 invZ + ) internal pure returns (uint256[2] memory) { + uint256 x; + uint256 y; + uint256 z; + (x, y, z) = _projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); + // solhint-disable-next-line gas-custom-errors + require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); + // Clear the z ordinate of the projective representation by dividing through + // by it, to obtain the affine representation + return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; + } + + // True iff address(c*p+s*g) == lcWitness, where g is generator. (With + // cryptographically high probability.) + function _verifyLinearCombinationWithGenerator( + uint256 c, + uint256[2] memory p, + uint256 s, + address lcWitness + ) internal pure returns (bool) { + // Rule out ecrecover failure modes which return address 0. + unchecked { + // solhint-disable-next-line gas-custom-errors + require(lcWitness != address(0), "bad witness"); + uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p + // Note this cannot wrap (X - Y % X), but we use unchecked to save + // gas. + bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] + bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] + // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 + // The point corresponding to the address returned by + // ecrecover(-s*p[0],v,p[0],c*p[0]) is + // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. + // See https://crypto.stackexchange.com/a/18106 + // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v + address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); + return computed == lcWitness; + } + } + + // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also + // requires cp1Witness != sp2Witness (which is fine for this application, + // since it is cryptographically impossible for them to be equal. In the + // (cryptographically impossible) case that a prover accidentally derives + // a proof with equal c*p1 and s*p2, they should retry with a different + // proof nonce.) Assumes that all points are on secp256k1 + // (which is checked in _verifyVRFProof below.) + function _linearCombination( + uint256 c, + uint256[2] memory p1, + uint256[2] memory cp1Witness, + uint256 s, + uint256[2] memory p2, + uint256[2] memory sp2Witness, + uint256 zInv + ) internal pure returns (uint256[2] memory) { + unchecked { + // Note we are relying on the wrap around here + // solhint-disable-next-line gas-custom-errors + require((cp1Witness[0] % FIELD_SIZE) != (sp2Witness[0] % FIELD_SIZE), "points in sum must be distinct"); + // solhint-disable-next-line gas-custom-errors + require(_ecmulVerify(p1, c, cp1Witness), "First mul check failed"); + // solhint-disable-next-line gas-custom-errors + require(_ecmulVerify(p2, s, sp2Witness), "Second mul check failed"); + return _affineECAdd(cp1Witness, sp2Witness, zInv); + } + } + + // Domain-separation tag for the hash taken in _scalarFromCurvePoints. + // Corresponds to scalarFromCurveHashPrefix in vrf.go + uint256 internal constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; + + // Pseudo-random number from inputs. Matches vrf.go/_scalarFromCurvePoints, and + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 + // The draft calls (in step 7, via the definition of string_to_int, in + // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the + // first hash without checking that it corresponds to a number less than the + // group order, which will lead to a slight bias in the sample. + // + // TODO(alx): We could save a bit of gas by following the standard here and + // using the compressed representation of the points, if we collated the y + // parities into a single bytes32. + // https://www.pivotaltracker.com/story/show/171120588 + function _scalarFromCurvePoints( + uint256[2] memory hash, + uint256[2] memory pk, + uint256[2] memory gamma, + address uWitness, + uint256[2] memory v + ) internal pure returns (uint256 s) { + return uint256(keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, hash, pk, gamma, v, uWitness))); + } + + // True if (gamma, c, s) is a correctly constructed randomness proof from pk + // and seed. zInv must be the inverse of the third ordinate from + // _projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to + // section 5.3 of the IETF draft. + // + // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass + // the x ordinate, and the parity of the y ordinate in the top bit of uWitness + // (which I could make a uint256 without using any extra space.) Would save + // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 + function _verifyVRFProof( + uint256[2] memory pk, + uint256[2] memory gamma, + uint256 c, + uint256 s, + uint256 seed, + address uWitness, + uint256[2] memory cGammaWitness, + uint256[2] memory sHashWitness, + uint256 zInv + ) internal view { + unchecked { + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(pk), "public key is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(gamma), "gamma is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(sHashWitness), "sHashWitness is not on curve"); + // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here + // we use the address of u instead of u itself. Also, here we add the + // terms instead of taking the difference, and in the proof construction in + // vrf.GenerateProof, we correspondingly take the difference instead of + // taking the sum as they do in step 7 of section 5.1.) + // solhint-disable-next-line gas-custom-errors + require(_verifyLinearCombinationWithGenerator(c, pk, s, uWitness), "addr(c*pk+s*g)!=_uWitness"); + // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) + uint256[2] memory hash = _hashToCurve(pk, seed); + // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms + uint256[2] memory v = _linearCombination(c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); + // Steps 7. and 8. of IETF draft section 5.3 + uint256 derivedC = _scalarFromCurvePoints(hash, pk, gamma, uWitness, v); + // solhint-disable-next-line gas-custom-errors + require(c == derivedC, "invalid proof"); + } + } + + // Domain-separation tag for the hash used as the final VRF output. + // Corresponds to vrfRandomOutputHashPrefix in vrf.go + uint256 internal constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; + + struct Proof { + uint256[2] pk; + uint256[2] gamma; + uint256 c; + uint256 s; + uint256 seed; + address uWitness; + uint256[2] cGammaWitness; + uint256[2] sHashWitness; + uint256 zInv; + } + + /* *************************************************************************** + * @notice Returns proof's output, if proof is valid. Otherwise reverts + + * @param proof vrf proof components + * @param seed seed used to generate the vrf output + * + * Throws if proof is invalid, otherwise: + * @return output i.e., the random output implied by the proof + * *************************************************************************** + */ + function _randomValueFromVRFProof(Proof memory proof, uint256 seed) internal view returns (uint256 output) { + _verifyVRFProof( + proof.pk, + proof.gamma, + proof.c, + proof.s, + seed, + proof.uWitness, + proof.cGammaWitness, + proof.sHashWitness, + proof.zInv + ); + output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, proof.gamma))); + return output; + } +} diff --git a/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol b/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol index c2938cb35b0..4197073aa50 100644 --- a/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol +++ b/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol @@ -48,17 +48,26 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { // Store the previous block's blockhash. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); VRFTypes.Proof[] memory proofs = new VRFTypes.Proof[](2); VRFTypes.RequestCommitmentV2Plus[] memory rcs = new VRFTypes.RequestCommitmentV2Plus[](2); - // Proof generated via the generate-proof-v2-plus script command. Example usage: - // _printGenerateProofV2PlusCommand(address(s_consumer), 1, requestBlock, true); + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment the print command below and run the test to print the output. + // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 3rd step: copy the output from the 1st step and update the command below, then run the command + // and copy the command output in the proof section below /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 33855227690351884611579800220581891477580182035146587491531555927634180294480 \ - -block-hash 0x0a \ + -pre-seed 4430852740828987645228960511496023658059009607317025880962658187812299131155 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0xdc90e8ce61c1af8a638b95264037c8e67ee5765c \ -native-payment true @@ -70,22 +79,22 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 80420391742429647505172101941811820476888293644816377569181566466584288434705, - 24046736031266889997051641830469514057863365715722268340801477580836256044582 + 26762213923453052192184693334574145607290366984305044804336172347176490943606, + 70503534560525619072578237689732581746976650376431765635714023643649039207077 ], - c: 74775128390693502914275156263410881155583102046081919417827483535122161050585, - s: 69563235412360165148368009853509434870917653835330501139204071967997764190111, - seed: 33855227690351884611579800220581891477580182035146587491531555927634180294480, - uWitness: 0xfB0663eaf48785540dE0FD0F837FD9c09BF4B80A, + c: 10992233996918874905152274435276937088064589467016709044984819613170049539489, + s: 79662863379962724455809192044326025082567113176696761949197261107120333769102, + seed: 4430852740828987645228960511496023658059009607317025880962658187812299131155, + uWitness: 0x421A52Fb797d76Fb610aA1a0c020346fC1Ee2DeB, cGammaWitness: [ - 53711159452748734758194447734939737695995909567499536035707522847057731697403, - 113650002631484103366420937668971311744887820666944514581352028601506700116835 + 50748523246052507241857300891945475679319243536065937584940024494820365165901, + 85746856994474260612851047426766648416105284284185975301552792881940939754570 ], sHashWitness: [ - 89656531714223714144489731263049239277719465105516547297952288438117443488525, - 90859682705760125677895017864538514058733199985667976488434404721197234427011 + 78637275871978664522379716948105702461748200460627087255706483027519919611423, + 82219236913923465822780520561305604064850823877720616893986252854976640396959 ], - zInv: 97275608653505690744303242942631893944856831559408852202478373762878300587548 + zInv: 60547558497534848069125896511700272238016171243048151035528198622956754542730 }); rcs[0] = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -116,14 +125,23 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { // Store the previous block's blockhash. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); + assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment the print command below and run the test to print the output. // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 3rd step: copy the output from the 1st step and update the command below, then run the command + // and copy the command output in the proof section below /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 76568185840201037774581758921393822690942290841865097674309745036496166431060 \ - -block-hash 0x14 \ + -pre-seed 14541556911652758131165474365357244907354309169650401973525070879190071151266 \ + -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ -block-num 20 \ -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ -native-payment false @@ -134,22 +152,22 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 21323932463597506192387578758854201988004673105893105492473194972397109828006, - 96834737826889397196571646974355352644437196500310392203712129010026003355112 + 97658842840420719674383370910135023062422561858595941631054490821636116883585, + 44255438468488339528368406358785988551798314198954634050943346751039644360856 ], - c: 8775807990949224376582975115621037245862755412370175152581490650310350359728, - s: 6805708577951013810918872616271445638109899206333819877111740872779453350091, - seed: 76568185840201037774581758921393822690942290841865097674309745036496166431060, - uWitness: 0xE82fF24Fecfbe73d682f38308bE3E039Dfabdf5c, + c: 5233652943248967403606766735502925802264855214922758107203237169366748118852, + s: 87931642435666855739510477620068257005869145374865238974094299759068218698655, + seed: 14541556911652758131165474365357244907354309169650401973525070879190071151266, + uWitness: 0x0A87a9CB71983cE0F2C4bA41D0c1A6Fb1785c46A, cGammaWitness: [ - 92810770919624535241476539842820168209710445519252592382122118536598338376923, - 17271305664006119131434661141858450289379246199095231636439133258170648418554 + 54062743217909816783918413821204010151082432359411822104552882037459289383418, + 67491004534731980264926765871774299056809003077448271411776926359153820235981 ], sHashWitness: [ - 29540023305939374439696120003978246982707698669656874393367212257432197207536, - 93902323936532381028323379401739289810874348405259732508442252936582467730050 + 7745933951617569731026754652291310837540252155195826133994719499558406927394, + 58405861596456412358325504621101233475720292237067230796670629212111423924259 ], - zInv: 88845170436601946907659333156418518556235340365885668267853966404617557948692 + zInv: 44253513765558903217330502897662324213800000485156126961643960636269885275795 }); rcs[1] = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -168,9 +186,9 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { // The payments are NOT pre-calculated and simply copied from the actual event. // We can assert and ignore the payment field but the code will be considerably longer. vm.expectEmit(true, true, false, true, address(s_coordinator)); - emit RandomWordsFulfilled(output.requestId, output.randomness, s_subId, 500000000000143283, true, true, false); + emit RandomWordsFulfilled(output.requestId, output.randomness, s_subId, 500000000000143261, true, true, false); vm.expectEmit(true, true, false, true, address(s_coordinator)); - emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000306143, false, true, false); + emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000312358, false, true, false); // Fulfill the requests. s_batchCoordinator.fulfillRandomWords(proofs, rcs); diff --git a/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol index 75a8d969273..dd3f54b580a 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol @@ -513,26 +513,33 @@ contract VRFV2Plus is BaseTest { assertEq(fulfilled, false); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - // Uncomment these console logs to see info about the request: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // Move on to the next block. // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"0000000000000000000000000000000000000000000000000000000000000014", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 58424872742560034068603954318478134981993109073728628043159461959392650534066 \ - -block-hash 0x0000000000000000000000000000000000000000000000000000000000000014 \ + -pre-seed 77134414723242246520332717536018735794426514244521954002798799849127623496871 \ + -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ -block-num 20 \ - -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 + -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ + -native-payment false */ proof = VRF.Proof({ pk: [ @@ -540,22 +547,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 38041205470219573731614166317842050442610096576830191475863676359766283013831, - 31897503406364148988967447112698248795931483458172800286988696482435433838056 + 103927982338770370318312316555080928288985522873495041111817988974598585393796, + 56789421278806198480964888112155620425048056183534931202752833185923411715624 ], - c: 114706080610174375269579192101772790158458728655229562781479812703475130740224, - s: 91869928024010088265014058436030407245056128545665425448353233998362687232253, - seed: 58424872742560034068603954318478134981993109073728628043159461959392650534066, - uWitness: 0x1514536B09a51E671d070312bcD3653386d5a82b, + c: 23645475075665525321781505993434124657388421977074956645288621921391376468128, + s: 106817081950846808215350231311242951539230271757396902089035477907017240898689, + seed: 77134414723242246520332717536018735794426514244521954002798799849127623496871, + uWitness: 0xD6899602060d574DE03FE1cf76fDf66afE12d549, cGammaWitness: [ - 90605489216274499662544489893800286859751132311034850249229378789467669572783, - 76568417372883461229305641415175605031997103681542349721251313705711146936024 + 9892458071712426452033749279561067220589549155902380165087951541202159693388, + 61235995320721681444549354910430438435754757626312862714628885100042911955139 ], sHashWitness: [ - 43417948503950579681520475434461454031791886587406480417092620950034789197994, - 100772571879140362396088596211082924128900752544164141322636815729889228000249 + 101478618362722903511580105256015180591690884037598276249676652094434483808775, + 82512235485399822034680598942438982472006937353405384896956013889074719896188 ], - zInv: 82374292458278672300647114418593830323283909625362447038989596015264004164958 + zInv: 82281039329215616805111360985152709712368762415186906218863971780664103705723 }); rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -602,24 +609,30 @@ contract VRFV2Plus is BaseTest { assertEq(fulfilled, false); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - // Uncomment these console logs to see info about the request: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // Move on to the next block. // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"000000000000000000000000000000000000000000000000000000000000000a", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 83266692323404068105564931899467966321583332182309426611016082057597749986430 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 88177119495082281213609405072572269421661478022189589823108119237563684383163 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ -native-payment true @@ -630,22 +643,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 47144451677122876068574640250190132179872561942855874114516471019540736524783, - 63001220656590641645486673489302242739512599229187442248048295264418080499391 + 102142782721757938350759722545721736888276217484353597703162772276193136052353, + 87167280284008869627768921028415708350806510214000539818296353518495698939660 ], - c: 42928477813589729783511577059394077774341588261592343937605454161333818133643, - s: 14447529458406454898597883219032514356523135029224613793880920230249515634875, - seed: 83266692323404068105564931899467966321583332182309426611016082057597749986430, - uWitness: 0x5Ed3bb2AA8EAFe168a23079644d5dfBf892B1038, + c: 78738462581063211677832865654743924688552792392007862664964608134754001810280, + s: 97066881804257970453329086439696419448135613089654606517271688187030953014593, + seed: 88177119495082281213609405072572269421661478022189589823108119237563684383163, + uWitness: 0xa335ea8dF652d5331a276B60b16c9733435D4f73, cGammaWitness: [ - 40742088032247467257043132769297935807697466810312051815364187117543257089153, - 110399474382135664619186049639190334359061769014381608543009407662815758204131 + 114435126227922602743444254494036972095649501991695809092954325430947992864624, + 63032211040463927862594425238691911311087931119674607521158894139074063158678 ], sHashWitness: [ - 26556776392895292893984393164594214244553035014769995354896600239759043777485, - 67126706735912782218279556535631175449291035782208850310724682668198932501077 + 105043781471073183057173130563345930784924139079040814418442661347864735908726, + 68696469914696211053833437482938344908217760552761185546164836556562945431554 ], - zInv: 88742453392918610091640193378775723954629905126315835248392650970979000380325 + zInv: 73325637847357165955904789471972164751975373195750497508525598331798833112175 }); rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -750,26 +763,26 @@ contract VRFV2Plus is BaseTest { (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); assertEq(fulfilled, true); - // The cost of fulfillRandomWords is approximately 86_700 gas. + // The cost of fulfillRandomWords is approximately 89_100 gas. // gasAfterPaymentCalculation is 50_000. // // The cost of the VRF fulfillment charged to the user is: // paymentNoFee = (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft() + l1CostWei) / link_native_ratio) // network gas price is capped at gas lane max gas (5000 gwei) - // paymentNoFee = (5e12 * (50_000 + 86_700 + 0)) / .5 - // paymentNoFee = 1.367e+18 + // paymentNoFee = (5e12 * (50_000 + 89_100 + 0)) / .5 + // paymentNoFee = 1.391e+18 // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM - fulfillmentFlatFeeLinkDiscountPPM) // flatFeeWei = 1e12 * (500_000 - 100_000) // flatFeeJuels = 1e18 * flatFeeWei / link_native_ratio // flatFeeJuels = 4e17 / 0.5 = 8e17 // billed_fee = paymentNoFee * (10 / 100) + 8e17 - // billed_fee = 1.367e+18 * 0.1 + 8e17 - // billed_fee = 9.367e+17 + // billed_fee = 1.391e+18 * 0.1 + 8e17 + // billed_fee = 9.391e+17 // note: delta is doubled from the native test to account for more variance due to the link/native ratio (uint96 linkBalanceAfter, , , , ) = s_testCoordinator.getSubscription(subId); // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 9.367 * 1e17, 1e15); - assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 9.367 * 1e17, 1e15); + assertApproxEqAbs(payment, 9.391 * 1e17, 1e15); + assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 9.391 * 1e17, 1e15); assertFalse(s_testCoordinator.pendingRequestExists(subId)); } @@ -834,24 +847,30 @@ contract VRFV2Plus is BaseTest { ); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - // 3. Fulfill the request above - //console.log("requestId: ", requestId); - //console.log("preSeed: ", preSeed); - //console.log("sender: ", address(consumer)); - // Move on to the next block. // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"000000000000000000000000000000000000000000000000000000000000000a", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // 3. Fulfill the request above + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 94043941380654896554739370173616551044559721638888689173752661912204412136884 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ -native-payment true @@ -862,22 +881,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 18593555375562408458806406536059989757338587469093035962641476877033456068708, - 55675218112764789548330682504442195066741636758414578491295297591596761905475 + 65913937398148449626792563067325648649534055460473988721938103219381973178278, + 63156327344180203180831822252171874192175272818200597638000091892096122362120 ], - c: 56595337384472359782910435918403237878894172750128610188222417200315739516270, - s: 60666722370046279064490737533582002977678558769715798604164042022636022215663, - seed: 94043941380654896554739370173616551044559721638888689173752661912204412136884, - uWitness: 0xEdbE15fd105cfEFb9CCcbBD84403d1F62719E50d, + c: 96524997218413735279221574381819903278651909890109201564980667824986706861580, + s: 32941032142956097592442894642111025677491308239274769364799856748447418202313, + seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, + uWitness: 0xda613621Dc2347d9A6670a1cBA812d52A7ec3A3A, cGammaWitness: [ - 11752391553651713021860307604522059957920042356542944931263270793211985356642, - 14713353048309058367510422609936133400473710094544154206129568172815229277104 + 6776842114900054689355891239487365968068230823400902903493665825747641410781, + 753482930067864853610521010650481816782338376846697006021590704037205560592 ], sHashWitness: [ - 109716108880570827107616596438987062129934448629902940427517663799192095060206, - 79378277044196229730810703755304140279837983575681427317104232794580059801930 + 76619528582417858778905184311764104068650968652636772643050945629834129417915, + 27947566794040118487986033070014357750801611688958204148187927873566412002355 ], - zInv: 18898957977631212231148068121702167284572066246731769473720131179584458697812 + zInv: 77351076831418813780936064446565588198113457019145030499544500588309236458362 }); VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -988,20 +1007,26 @@ contract VRFV2Plus is BaseTest { // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"000000000000000000000000000000000000000000000000000000000000000a", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); // 3. Fulfill the 1st request above - console.log("requestId: ", requestId1); - console.log("preSeed: ", preSeed1); - console.log("sender: ", address(consumer1)); - - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 94043941380654896554739370173616551044559721638888689173752661912204412136884 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ -native-payment true @@ -1012,22 +1037,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 18593555375562408458806406536059989757338587469093035962641476877033456068708, - 55675218112764789548330682504442195066741636758414578491295297591596761905475 + 65913937398148449626792563067325648649534055460473988721938103219381973178278, + 63156327344180203180831822252171874192175272818200597638000091892096122362120 ], - c: 56595337384472359782910435918403237878894172750128610188222417200315739516270, - s: 60666722370046279064490737533582002977678558769715798604164042022636022215663, - seed: 94043941380654896554739370173616551044559721638888689173752661912204412136884, - uWitness: 0xEdbE15fd105cfEFb9CCcbBD84403d1F62719E50d, + c: 103296526941774692908067234360350834482645116475454593803823148315342533216203, + s: 50291245814080656739779812653411869801334231723444391096753849942661931376590, + seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, + uWitness: 0x38500711AdcB471ac1A566c4b915759eb9cBCE2F, cGammaWitness: [ - 11752391553651713021860307604522059957920042356542944931263270793211985356642, - 14713353048309058367510422609936133400473710094544154206129568172815229277104 + 56476970720509547210740928951846471668018949971632948991136782499758110143588, + 44326075300781389077656415325167171692706436527877070415603658305817367373598 ], sHashWitness: [ - 109716108880570827107616596438987062129934448629902940427517663799192095060206, - 79378277044196229730810703755304140279837983575681427317104232794580059801930 + 109524696164787283409393383708118913934136014139634321235031691839206768278439, + 52690039857779635909051684567562068782378693408005554345469129234366171822741 ], - zInv: 18898957977631212231148068121702167284572066246731769473720131179584458697812 + zInv: 108537983043800425266290112227943788107669768716438017124275578856644517258573 }); VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -1040,18 +1065,24 @@ contract VRFV2Plus is BaseTest { s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - //4. Fulfill the 2nd request - console.log("requestId: ", requestId2); - console.log("preSeed: ", preSeed2); - console.log("sender: ", address(consumer2)); - - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // 4. Fulfill the 2nd request + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 60086281972849674111646805013521068579710860774417505336898013292594859262126 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 53330100288105770463016865504321558518073051667771993294213115153676065708950 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0xf5a165378E120f93784395aDF1E08a437e902865 \ -native-payment true @@ -1062,22 +1093,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 8781676794493524976318989249067879326013864868749595045909181134740761572122, - 70144896394968351242907510966944756907625107566821127114847472296460405612124 + 7260273098301741284457725182313945178888499328441106869722941415453613782770, + 91648498042618923465107471165504200585847250228048015102713552756245653299952 ], - c: 67847193668837615807355025316836592349514589069599294392546721746916067719949, - s: 114946531382736685625345450298146929067341928840493664822961336014597880904075, - seed: 60086281972849674111646805013521068579710860774417505336898013292594859262126, - uWitness: 0xe1de4fD69277D0C5516cAE4d760b1d08BC340A28, + c: 64987886290696558870328339791409334400119338012796549091587853494368167422332, + s: 69469162696695326295567645789624554797683340898724555794078876350372084267572, + seed: 53330100288105770463016865504321558518073051667771993294213115153676065708950, + uWitness: 0xa6ce21aD47eC5E90Ac7a2c6152D9710234Afe8ab, cGammaWitness: [ - 90301582727701442026215692513959255065128476395727596945643431833363167168678, - 61501369717028493801369453424028509804064958915788808540582630993703331669978 + 57318358662553647785891634403735348577492991113152343207139729697842283565417, + 57942043484796308689103390068712967247519265087617809262260051163954389512396 ], sHashWitness: [ - 98738650825542176387169085844714248077697103572877410412808249468787326424906, - 85647963391545223707301702874240345890884970941786094239896961457539737216630 + 113345999157319332195230171660555736547709417795439282230372737104445523493539, + 113358219039155973560933190466797830695088313506343976960055230355894888727567 ], - zInv: 29080001901010358083725892808339807464533563010468652346220922643802059192842 + zInv: 68349552569605209428774574139615352877146713490794995768725549089572297658255 }); rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, diff --git a/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts b/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts index 62733bcad43..6b220f2f7cb 100644 --- a/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistry2_2.test.ts @@ -23,7 +23,7 @@ import { MockArbGasInfo__factory as MockArbGasInfoFactory } from '../../../typec 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 { OptimismModule__factory as OptimismModuleFactory } from '../../../typechain/factories/OptimismModule__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' @@ -35,7 +35,7 @@ import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' import { UpkeepMock } from '../../../typechain/UpkeepMock' import { ChainModuleBase } from '../../../typechain/ChainModuleBase' import { ArbitrumModule } from '../../../typechain/ArbitrumModule' -import { OptimismModule } from '../../../typechain/OptimismModule' +import { OptimismModuleV2 } from '../../../typechain/OptimismModuleV2' import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' import { IChainModule, UpkeepAutoFunder } from '../../../typechain' import { @@ -148,7 +148,7 @@ let upkeepMockFactory: UpkeepMockFactory let upkeepAutoFunderFactory: UpkeepAutoFunderFactory let chainModuleBaseFactory: ChainModuleBaseFactory let arbitrumModuleFactory: ArbitrumModuleFactory -let optimismModuleFactory: OptimismModuleFactory +let optimismModuleV2Factory: OptimismModuleV2Factory let streamsLookupUpkeepFactory: StreamsLookupUpkeepFactory let personas: Personas @@ -169,7 +169,7 @@ let ltUpkeep: MockContract let transcoder: UpkeepTranscoder let chainModuleBase: ChainModuleBase let arbitrumModule: ArbitrumModule -let optimismModule: OptimismModule +let optimismModule: OptimismModuleV2 let streamsLookupUpkeep: StreamsLookupUpkeep let automationUtils: AutomationCompatibleUtils @@ -430,7 +430,8 @@ describe('AutomationRegistry2_2', () => { await ethers.getContractFactory('UpkeepAutoFunder') chainModuleBaseFactory = await ethers.getContractFactory('ChainModuleBase') arbitrumModuleFactory = await ethers.getContractFactory('ArbitrumModule') - optimismModuleFactory = await ethers.getContractFactory('OptimismModule') + optimismModuleV2Factory = + await ethers.getContractFactory('OptimismModuleV2') streamsLookupUpkeepFactory = await ethers.getContractFactory( 'StreamsLookupUpkeep', ) @@ -844,7 +845,7 @@ describe('AutomationRegistry2_2', () => { .deploy() chainModuleBase = await chainModuleBaseFactory.connect(owner).deploy() arbitrumModule = await arbitrumModuleFactory.connect(owner).deploy() - optimismModule = await optimismModuleFactory.connect(owner).deploy() + optimismModule = await optimismModuleV2Factory.connect(owner).deploy() streamsLookupUpkeep = await streamsLookupUpkeepFactory .connect(owner) .deploy( diff --git a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts index 3f28a4410b1..f3c2d9bb984 100644 --- a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts @@ -23,7 +23,7 @@ import { MockArbGasInfo__factory as MockArbGasInfoFactory } from '../../../typec 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 { OptimismModule__factory as OptimismModuleFactory } from '../../../typechain/factories/OptimismModule__factory' +import { OptimismModuleV2__factory as OptimismModuleV2Factory } from '../../../typechain/factories/OptimismModuleV2__factory' import { ILogAutomation__factory as ILogAutomationactory } from '../../../typechain/factories/ILogAutomation__factory' import { MockArbSys__factory as MockArbSysFactory } from '../../../typechain/factories/MockArbSys__factory' import { AutomationCompatibleUtils } from '../../../typechain/AutomationCompatibleUtils' @@ -34,7 +34,7 @@ import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' import { UpkeepMock } from '../../../typechain/UpkeepMock' import { ChainModuleBase } from '../../../typechain/ChainModuleBase' import { ArbitrumModule } from '../../../typechain/ArbitrumModule' -import { OptimismModule } from '../../../typechain/OptimismModule' +import { OptimismModuleV2 } from '../../../typechain/OptimismModuleV2' import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' import { IChainModule, UpkeepAutoFunder } from '../../../typechain' import { @@ -152,7 +152,7 @@ let upkeepMockFactory: UpkeepMockFactory let upkeepAutoFunderFactory: UpkeepAutoFunderFactory let chainModuleBaseFactory: ChainModuleBaseFactory let arbitrumModuleFactory: ArbitrumModuleFactory -let optimismModuleFactory: OptimismModuleFactory +let optimismModuleFactory: OptimismModuleV2Factory let streamsLookupUpkeepFactory: StreamsLookupUpkeepFactory let personas: Personas @@ -174,7 +174,7 @@ let ltUpkeep: MockContract let transcoder: UpkeepTranscoder let chainModuleBase: ChainModuleBase let arbitrumModule: ArbitrumModule -let optimismModule: OptimismModule +let optimismModule: OptimismModuleV2 let streamsLookupUpkeep: StreamsLookupUpkeep let automationUtils: AutomationCompatibleUtils let automationUtils2_3: AutomationUtils2_3 @@ -442,7 +442,7 @@ describe('AutomationRegistry2_3', () => { await ethers.getContractFactory('UpkeepAutoFunder') chainModuleBaseFactory = await ethers.getContractFactory('ChainModuleBase') arbitrumModuleFactory = await ethers.getContractFactory('ArbitrumModule') - optimismModuleFactory = await ethers.getContractFactory('OptimismModule') + optimismModuleFactory = await ethers.getContractFactory('OptimismModuleV2') streamsLookupUpkeepFactory = await ethers.getContractFactory( 'StreamsLookupUpkeep', ) diff --git a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts index 0c1e34a1167..11da7273ab9 100644 --- a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts +++ b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_2.test.ts @@ -93,7 +93,8 @@ describe('IAutomationRegistryMaster2_2', () => { ) }) - it('satisfies the OCR2Abstract interface', async () => { + // 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, diff --git a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts index 8bc4f695672..44fa277b5e1 100644 --- a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts +++ b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts @@ -87,7 +87,8 @@ describe('IAutomationRegistryMaster2_3', () => { ) }) - it('satisfies the OCR2Abstract interface', async () => { + // 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, diff --git a/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts b/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts new file mode 100644 index 00000000000..95210cf6444 --- /dev/null +++ b/contracts/test/v0.8/automation/ZKSyncAutomationRegistry2_3.test.ts @@ -0,0 +1,4403 @@ +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 { MockZKSyncSystemContext__factory as MockZKSyncSystemContextFactory } from '../../../typechain/factories/MockZKSyncSystemContext__factory' +import { ChainModuleBase__factory as ChainModuleBaseFactory } from '../../../typechain/factories/ChainModuleBase__factory' +import { MockGasBoundCaller__factory as MockGasBoundCallerFactory } from '../../../typechain/factories/MockGasBoundCaller__factory' +import { ILogAutomation__factory as ILogAutomationactory } from '../../../typechain/factories/ILogAutomation__factory' +import { AutomationCompatibleUtils } from '../../../typechain/AutomationCompatibleUtils' +import { StreamsLookupUpkeep } from '../../../typechain/StreamsLookupUpkeep' +import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' +import { MockGasBoundCaller } from '../../../typechain/MockGasBoundCaller' +import { UpkeepMock } from '../../../typechain/UpkeepMock' +import { ChainModuleBase } from '../../../typechain/ChainModuleBase' +import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' +import { MockZKSyncSystemContext } from '../../../typechain/MockZKSyncSystemContext' +import { IChainModule, UpkeepAutoFunder } from '../../../typechain' +import { + CancelledUpkeepReportEvent, + IAutomationRegistryMaster2_3 as IAutomationRegistry, + ReorgedUpkeepReportEvent, + StaleUpkeepReportEvent, + UpkeepPerformedEvent, +} from '../../../typechain/IAutomationRegistryMaster2_3' +import { + deployMockContract, + MockContract, +} from '@ethereum-waffle/mock-contract' +import { deployZKSyncRegistry23 } from './helpers' +import { AutomationUtils2_3 } from '../../../typechain/AutomationUtils2_3' + +const describeMaybe = process.env.SKIP_SLOW ? describe.skip : describe +const itMaybe = process.env.SKIP_SLOW ? it.skip : it + +// copied from AutomationRegistryInterface2_3.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_3.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] +type OnChainConfig = Parameters[3] + +// ----------------------------------------------------------------------------------------------- + +// 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(50_000) +// 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(50_000) + +// 1 Link = 0.005 Eth +const linkUSD = BigNumber.from('2000000000') // 1 LINK = $20 +const nativeUSD = BigNumber.from('400000000000') // 1 ETH = $4000 +const gasWei = BigNumber.from(1000000000) // 1 gwei +// ----------------------------------------------------------------------------------------------- +// test-wide configs for upkeeps +const performGas = BigNumber.from('1000000') +const paymentPremiumBase = BigNumber.from('1000000000') +const paymentPremiumPPB = BigNumber.from('250000000') +const flatFeeMilliCents = BigNumber.from(0) + +const randomBytes = '0x1234abcd' +const emptyBytes = '0x' +const emptyBytes32 = + '0x0000000000000000000000000000000000000000000000000000000000000000' + +const pubdataGas = BigNumber.from(500000) +const transmitGasOverhead = 1_040_000 +const checkGasOverhead = 600_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 = linkUSD.div(BigNumber.from('2')) +const fallbackNativePrice = nativeUSD.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 wrappedNativeTokenAddress = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' +const epochAndRound5_1 = + '0x0000000000000000000000000000000000000000000000000000000000000501' + +let logTriggerConfig: string + +// ----------------------------------------------------------------------------------------------- + +// Smart contract factories +let linkTokenFactory: ContractFactory +let mockV3AggregatorFactory: MockV3AggregatorFactory +let mockGasBoundCallerFactory: MockGasBoundCallerFactory +let upkeepMockFactory: UpkeepMockFactory +let upkeepAutoFunderFactory: UpkeepAutoFunderFactory +let moduleBaseFactory: ChainModuleBaseFactory +let mockZKSyncSystemContextFactory: MockZKSyncSystemContextFactory +let streamsLookupUpkeepFactory: StreamsLookupUpkeepFactory +let personas: Personas + +// contracts +let linkToken: Contract +let linkUSDFeed: MockV3Aggregator +let nativeUSDFeed: MockV3Aggregator +let gasPriceFeed: MockV3Aggregator +let registry: IAutomationRegistry // default registry, used for most tests +let mgRegistry: IAutomationRegistry // "migrate registry" used in migration tests +let mock: UpkeepMock +let autoFunderUpkeep: UpkeepAutoFunder +let ltUpkeep: MockContract +let transcoder: UpkeepTranscoder +let moduleBase: ChainModuleBase +let mockGasBoundCaller: MockGasBoundCaller +let mockZKSyncSystemContext: MockZKSyncSystemContext +let streamsLookupUpkeep: StreamsLookupUpkeep +let automationUtils: AutomationCompatibleUtils +let automationUtils2_3: AutomationUtils2_3 + +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' + + automationUtils2_3.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, + linkUSD, + 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('ZKSyncAutomationRegistry2_3', () => { + 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 financeAdmin: 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: OnChainConfig + let baseConfig: Parameters + let upkeepManager: string + + before(async () => { + personas = (await getUsers()).personas + + const compatibleUtilsFactory = await ethers.getContractFactory( + 'AutomationCompatibleUtils', + ) + automationUtils = await compatibleUtilsFactory.deploy() + + const utilsFactory = await ethers.getContractFactory('AutomationUtils2_3') + automationUtils2_3 = await utilsFactory.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 + mockZKSyncSystemContextFactory = await ethers.getContractFactory( + 'MockZKSyncSystemContext', + ) + mockGasBoundCallerFactory = + await ethers.getContractFactory('MockGasBoundCaller') + upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') + upkeepAutoFunderFactory = + await ethers.getContractFactory('UpkeepAutoFunder') + moduleBaseFactory = await ethers.getContractFactory('ChainModuleBase') + 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() + financeAdmin = personas.Nick + // 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, // in millicents + ) => { + const gasSpent = gasOverhead.add(BigNumber.from(upkeepGasSpent)) + const gasPayment = gasWei + .mul(gasMultiplier) + .mul(gasSpent) + .mul(nativeUSD) + .div(linkUSD) + + const premium = gasWei + .mul(gasMultiplier) + .mul(upkeepGasSpent) + .mul(premiumPPB) + .mul(nativeUSD) + .div(paymentPremiumBase) + .add(flatFee.mul(BigNumber.from(10).pow(21))) + .div(linkUSD) + + return { + total: gasPayment.add(premium), + gasPayment, + premium, + } + } + + const verifyMaxPayment = async ( + registry: IAutomationRegistry, + chainModule: IChainModule, + ) => { + 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(chainModuleOverheads.chainModuleFixedOverhead) + + const totalLogOverhead = registryLogOverhead + .add(registryPerSignerGasOverhead.mul(fPlusOne)) + .add(chainModuleOverheads.chainModuleFixedOverhead) + + const financeAdminAddress = await financeAdmin.getAddress() + + for (const test of tests) { + await registry.connect(owner).setConfigTypeSafe( + signerAddresses, + keeperAddresses, + f, + { + checkGasLimit, + stalenessSeconds, + gasCeilingMultiplier: test.multiplier, + maxCheckDataSize, + maxPerformDataSize, + maxRevertDataSize, + maxPerformGas, + fallbackGasPrice, + fallbackLinkPrice, + fallbackNativePrice, + transcoder: transcoder.address, + registrars: [], + upkeepPrivilegeManager: upkeepManager, + chainModule: chainModule.address, + reorgProtectionEnabled: true, + financeAdmin: financeAdminAddress, + }, + offchainVersion, + offchainBytes, + [linkToken.address], + [ + { + gasFeePPB: test.premium, + flatFeeMilliCents: test.flatFee, + priceFeed: linkUSDFeed.address, + fallbackPrice: fallbackLinkPrice, + minSpend: minUpkeepSpend, + decimals: 18, + }, + ], + ) + + const conditionalPrice = await registry.getMaxPaymentForGas( + upkeepId, + Trigger.CONDITION, + test.gas, + linkToken.address, + ) + expect(conditionalPrice).to.equal( + linkForGas( + BigNumber.from(test.gas), + totalConditionalOverhead, + BigNumber.from(test.multiplier), + BigNumber.from(test.premium), + BigNumber.from(test.flatFee), + ).total, + ) + + const logPrice = await registry.getMaxPaymentForGas( + upkeepId, + Trigger.LOG, + test.gas, + linkToken.address, + ) + expect(logPrice).to.equal( + linkForGas( + BigNumber.from(test.gas), + totalLogOverhead, + BigNumber.from(test.multiplier), + BigNumber.from(test.premium), + BigNumber.from(test.flatFee), + ).total, + ) + } + } + + const verifyConsistentAccounting = async ( + maxAllowedSpareChange: BigNumber, + ) => { + const expectedLinkBalance = await registry.getReserveAmount( + linkToken.address, + ) + 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 linkAvailableForPayment = await registry.linkAvailableForPayment() + assert.isTrue(expectedLinkBalance.eq(linkTokenBalance)) + assert.isTrue( + upkeepIdBalance + .add(totalKeeperBalance) + .add(linkAvailableForPayment) + .lte(expectedLinkBalance), + ) + assert.isTrue( + expectedLinkBalance + .sub(upkeepIdBalance) + .sub(totalKeeperBalance) + .sub(linkAvailableForPayment) + .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) + linkUSDFeed = await mockV3AggregatorFactory + .connect(owner) + .deploy(8, linkUSD) + nativeUSDFeed = await mockV3AggregatorFactory + .connect(owner) + .deploy(8, nativeUSD) + const upkeepTranscoderFactory = await ethers.getContractFactory( + 'UpkeepTranscoder5_0', + ) + transcoder = await upkeepTranscoderFactory.connect(owner).deploy() + mockZKSyncSystemContext = await mockZKSyncSystemContextFactory + .connect(owner) + .deploy() + mockGasBoundCaller = await mockGasBoundCallerFactory.connect(owner).deploy() + moduleBase = await moduleBaseFactory.connect(owner).deploy() + streamsLookupUpkeep = await streamsLookupUpkeepFactory + .connect(owner) + .deploy( + BigNumber.from('10000'), + BigNumber.from('100'), + false /* useArbBlock */, + true /* staging */, + false /* verify mercury response */, + ) + + const zksyncSystemContextCode = await ethers.provider.send('eth_getCode', [ + mockZKSyncSystemContext.address, + ]) + await ethers.provider.send('hardhat_setCode', [ + '0x000000000000000000000000000000000000800B', + zksyncSystemContextCode, + ]) + + const gasBoundCallerCode = await ethers.provider.send('eth_getCode', [ + mockGasBoundCaller.address, + ]) + await ethers.provider.send('hardhat_setCode', [ + '0xc706EC7dfA5D4Dc87f29f859094165E8290530f5', + gasBoundCallerCode, + ]) + + const financeAdminAddress = await financeAdmin.getAddress() + + config = { + checkGasLimit, + stalenessSeconds, + gasCeilingMultiplier, + maxCheckDataSize, + maxPerformDataSize, + maxRevertDataSize, + maxPerformGas, + fallbackGasPrice, + fallbackLinkPrice, + fallbackNativePrice, + transcoder: transcoder.address, + registrars: [], + upkeepPrivilegeManager: upkeepManager, + chainModule: moduleBase.address, + reorgProtectionEnabled: true, + financeAdmin: financeAdminAddress, + } + + baseConfig = [ + signerAddresses, + keeperAddresses, + f, + config, + offchainVersion, + offchainBytes, + [linkToken.address], + [ + { + gasFeePPB: paymentPremiumPPB, + flatFeeMilliCents, + priceFeed: linkUSDFeed.address, + fallbackPrice: fallbackLinkPrice, + minSpend: minUpkeepSpend, + decimals: 18, + }, + ], + ] + + const registryParams: Parameters = [ + owner, + linkToken.address, + linkUSDFeed.address, + nativeUSDFeed.address, + gasPriceFeed.address, + zeroAddress, + 0, // onchain payout mode + wrappedNativeTokenAddress, + ] + + registry = await deployZKSyncRegistry23(...registryParams) + mgRegistry = await deployZKSyncRegistry23(...registryParams) + + 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) + for (const reg of [registry, 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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + randomBytes, + '0x', + '0x', + ) + upkeepId = await getUpkeepID(tx) + + autoFunderUpkeep = await upkeepAutoFunderFactory + .connect(owner) + .deploy(linkToken.address, registry.address) + tx = await registry + .connect(owner) + .registerUpkeep( + autoFunderUpkeep.address, + performGas, + autoFunderUpkeep.address, + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '0x', + ) + afUpkeepId = await getUpkeepID(tx) + + ltUpkeep = await deployMockContract(owner, ILogAutomationactory.abi) + tx = await registry + .connect(owner) + .registerUpkeep( + ltUpkeep.address, + performGas, + await admin.getAddress(), + Trigger.LOG, + linkToken.address, + '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( + streamsLookupUpkeep.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.LOG, + linkToken.address, + '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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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, + linkUSD: 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, + baseConfig[6], + baseConfig[7], + ) + + 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, + baseConfig[6], + baseConfig[7], + ) + 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, + baseConfig[6], + baseConfig[7], + ) + 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 mock.setCanPerform(true) + await evmRevert( + getTransmitTx(registry, keeper1, [upkeepId], { + gasLimit: BigNumber.from(150000), + }), + ) + }) + + 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 == gasWei + const gasPrice = gasWei + 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 // 14657 gasUsed + const gasOverhead = upkeepPerformedLog.args.gasOverhead // 137230 gasOverhead + const totalPayment = upkeepPerformedLog.args.totalPayment + + assert.equal( + linkForGas( + gasUsed, + gasOverhead, + BigNumber.from('1'), // Not the config multiplier, but the actual gas used + paymentPremiumPPB, + flatFeeMilliCents, + // pubdataGas.mul(gasPrice), + ).total.toString(), + totalPayment.toString(), + ) + + assert.equal( + linkForGas( + gasUsed, + gasOverhead, + BigNumber.from('1'), // Not the config multiplier, but the actual gas used + paymentPremiumPPB, + flatFeeMilliCents, + // pubdataGas.mul(gasPrice), + ).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, + flatFeeMilliCents, + // pubdataGas.mul(gasPrice), + ).total.toString(), + totalPayment.toString(), + ) + }) + + itMaybe('can self fund', async () => { + const maxPayment = await registry.getMaxPaymentForGas( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + + // 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, + baseConfig[6], + baseConfig[7], + ) + const tx = await registry.connect(owner).registerUpkeep( + mock.address, + maxPerformGas, // max allowed gas + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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, + baseConfig[6], + baseConfig[7], + ) + 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) + } + }, + ) + + // describe.only('Gas benchmarking conditional upkeeps [ @skip-coverage ]', function () { + // const fs = [1] + // 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() + // + // await registry + // .connect(admin) + // .setUpkeepGasLimit(upkeepId, performGas.mul(3)) + // + // // 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 moduleBase.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, + // baseConfig[6], + // baseConfig[7], + // ) + // 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) + // .add(500000) // the amount of pubdataGas used returned by mock gas bound caller + // const estimatedGasOverhead = registryConditionalOverhead + // .add( + // registryPerSignerGasOverhead.mul( + // BigNumber.from(newF + 1), + // ), + // ) + // .add(chainModuleOverheads.chainModuleFixedOverhead) + // .add(65_400) + // + // 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(), // 179800 + // ' charged overhead: ', + // chargedGasOverhead.toString(), // 180560 + // ' actual overhead: ', + // actualGasOverhead.toString(), // 632949 + // ' calculation margin over gasUsed: ', + // chargedGasOverhead.sub(actualGasOverhead).toString(), // 18456 + // ' estimation margin over gasUsed: ', + // estimatedGasOverhead.sub(actualGasOverhead).toString(), // -27744 + // ' upkeepGasUsed: ', + // upkeepGasUsed, // 988620 + // ' receipt.gasUsed: ', + // receipt.gasUsed, // 1121569 + // ) + // + // // 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 // 180560 + // .sub(actualGasOverhead) // 132940 + // .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.only('Gas benchmarking log upkeeps [ @skip-coverage ]', function () { + // const fs = [1] + // 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, + // baseConfig[6], + // baseConfig[7], + // ) + // 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 moduleBase.getGasOverhead() + // + // const upkeepGasUsed = upkeepPerformedLog.args.gasUsed + // const chargedGasOverhead = upkeepPerformedLog.args.gasOverhead + // const actualGasOverhead = receipt.gasUsed + // .sub(upkeepGasUsed) + // .add(500000) // the amount of pubdataGas used returned by mock gas bound caller + // const estimatedGasOverhead = registryLogOverhead + // .add(registryPerSignerGasOverhead.mul(BigNumber.from(newF + 1))) + // .add(chainModuleOverheads.chainModuleFixedOverhead) + // .add(65_400) + // + // 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(), + // ' upkeepGasUsed: ', + // upkeepGasUsed, + // ' receipt.gasUsed: ', + // receipt.gasUsed, + // ) + // + // 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(), + // ) + // }, + // ) + // }) + // }) + }) + }) + + describeMaybe( + '#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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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), + }) + }) + }, + ) + + 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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '0x', + ) + + 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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '0x', + ) + 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()) + }) + }) + + 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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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( + mock.address, + performGas, + await admin.getAddress(), + Trigger.CONDITION, + linkToken.address, + '0x', + '0x', + '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]) + }) + + 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(registration.balance.toNumber(), 0) + }) + }) + }) + + 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) // 1,000,000 + + // increase upkeep gas limit because the mock gas bound caller will always return 500,000 as the L1 gas used + // that brings the total gas used to about 1M + 0.5M = 1.5M + await registry + .connect(admin) + .setUpkeepGasLimit(upkeepId, BigNumber.from(2000000)) + + const simulatePerformResult = await registry + .connect(zeroAddress) + .callStatic.simulatePerformUpkeep(upkeepId, '0x') + + // Full execute gas should be used, with some performGasBuffer(1000) + assert.isTrue( + simulatePerformResult.gasUsed.gt( + performGas.add(pubdataGas).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.linkUSD.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.linkUSD.eq(linkUSD)) + }) + + 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('#getMaxPaymentForGas', () => { + itMaybe('calculates the max fee appropriately in ZKSync', async () => { + await verifyMaxPayment(registry, moduleBase) + }) + + it('uses the fallback gas price if the feed has issues in ZKSync', async () => { + const chainModuleOverheads = await moduleBase.getGasOverhead() + const expectedFallbackMaxPayment = linkForGas( + performGas, + registryConditionalOverhead + .add(registryPerSignerGasOverhead.mul(f + 1)) + .add(chainModuleOverheads.chainModuleFixedOverhead), + gasCeilingMultiplier.mul('2'), // fallbackGasPrice is 2x gas price + paymentPremiumPPB, + flatFeeMilliCents, + ).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( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + ).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( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + ).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( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + ).toString(), + ) + }) + + it('uses the fallback link price if the feed has issues in ZKSync', async () => { + const chainModuleOverheads = await moduleBase.getGasOverhead() + const expectedFallbackMaxPayment = linkForGas( + performGas, + registryConditionalOverhead + .add(registryPerSignerGasOverhead.mul(f + 1)) + .add(chainModuleOverheads.chainModuleFixedOverhead), + gasCeilingMultiplier.mul('2'), // fallbackLinkPrice is 1/2 link price, so multiply by 2 + paymentPremiumPPB, + flatFeeMilliCents, + ).total + + // Stale feed + let roundId = 99 + const answer = 100 + let updatedAt = 946684800 // New Years 2000 🥳 + let startedAt = 946684799 + await linkUSDFeed + .connect(owner) + .updateRoundData(roundId, answer, updatedAt, startedAt) + + assert.equal( + expectedFallbackMaxPayment.toString(), + ( + await registry.getMaxPaymentForGas( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + ).toString(), + ) + + // Negative feed price + roundId = 100 + updatedAt = now() + startedAt = 946684799 + await linkUSDFeed + .connect(owner) + .updateRoundData(roundId, -100, updatedAt, startedAt) + + assert.equal( + expectedFallbackMaxPayment.toString(), + ( + await registry.getMaxPaymentForGas( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + ).toString(), + ) + + // Zero feed price + roundId = 101 + updatedAt = now() + startedAt = 946684799 + await linkUSDFeed + .connect(owner) + .updateRoundData(roundId, 0, updatedAt, startedAt) + + assert.equal( + expectedFallbackMaxPayment.toString(), + ( + await registry.getMaxPaymentForGas( + upkeepId, + Trigger.CONDITION, + performGas, + linkToken.address, + ) + ).toString(), + ) + }) + }) + + describe('#typeAndVersion', () => { + it('uses the correct type and version', async () => { + const typeAndVersion = await registry.typeAndVersion() + assert.equal(typeAndVersion, 'AutomationRegistry 2.3.0') + }) + }) + + describeMaybe('#setConfig - onchain', async () => { + const maxGas = BigNumber.from(6) + const staleness = BigNumber.from(4) + const ceiling = BigNumber.from(5) + 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 fbNativeEth = BigNumber.from(100) + const newTranscoder = randomAddress() + const newRegistrars = [randomAddress(), randomAddress()] + const upkeepManager = randomAddress() + const financeAdminAddress = randomAddress() + + const newConfig: OnChainConfig = { + checkGasLimit: maxGas, + stalenessSeconds: staleness, + gasCeilingMultiplier: ceiling, + maxCheckDataSize: newMaxCheckDataSize, + maxPerformDataSize: newMaxPerformDataSize, + maxRevertDataSize: newMaxRevertDataSize, + maxPerformGas: newMaxPerformGas, + fallbackGasPrice: fbGasEth, + fallbackLinkPrice: fbLinkEth, + fallbackNativePrice: fbNativeEth, + transcoder: newTranscoder, + registrars: newRegistrars, + upkeepPrivilegeManager: upkeepManager, + chainModule: moduleBase.address, + reorgProtectionEnabled: true, + financeAdmin: financeAdminAddress, + } + + it('reverts when called by anyone but the proposed owner', async () => { + await evmRevert( + registry + .connect(payee1) + .setConfigTypeSafe( + signerAddresses, + keeperAddresses, + f, + newConfig, + offchainVersion, + offchainBytes, + baseConfig[6], + baseConfig[7], + ), + '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, + baseConfig[6], + baseConfig[7], + ), + registry, + 'InvalidSigner', + ) + + await evmRevertCustomError( + registry + .connect(owner) + .setConfigTypeSafe( + [ + randomAddress(), + randomAddress(), + randomAddress(), + randomAddress(), + ], + [randomAddress(), randomAddress(), randomAddress(), zeroAddress], + f, + newConfig, + offchainVersion, + offchainBytes, + baseConfig[6], + baseConfig[7], + ), + registry, + 'InvalidTransmitter', + ) + }) + + it('updates the onchainConfig and configDigest', async () => { + const old = await registry.getState() + const oldConfig = await registry.getConfig() + const oldState = old.state + 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.stalenessSeconds, staleness.toNumber()) + assert.equal(updatedConfig.gasCeilingMultiplier, ceiling.toNumber()) + 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, + baseConfig[6], + baseConfig[7], + ), + '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, + baseConfig[6], + baseConfig[7], + ), + registry, + 'TooManyOracles', + ) + }) + + it('reverts if f=0', async () => { + await evmRevertCustomError( + registry + .connect(owner) + .setConfigTypeSafe( + newKeepers, + newKeepers, + 0, + config, + offchainVersion, + offchainBytes, + baseConfig[6], + baseConfig[7], + ), + registry, + 'IncorrectNumberOfFaultyOracles', + ) + }) + + it('reverts if signers != transmitters length', async () => { + const signers = [randomAddress()] + await evmRevertCustomError( + registry + .connect(owner) + .setConfigTypeSafe( + signers, + newKeepers, + f, + config, + offchainVersion, + offchainBytes, + baseConfig[6], + baseConfig[7], + ), + registry, + 'IncorrectNumberOfSigners', + ) + }) + + it('reverts if signers <= 3f', async () => { + newKeepers.pop() + await evmRevertCustomError( + registry + .connect(owner) + .setConfigTypeSafe( + newKeepers, + newKeepers, + f, + config, + offchainVersion, + offchainBytes, + baseConfig[6], + baseConfig[7], + ), + 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, + baseConfig[6], + baseConfig[7], + ), + 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, + baseConfig[6], + baseConfig[7], + ), + 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('#cancelUpkeep', () => { + describe('when called by the admin', async () => { + 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 adds to reserve', async () => { + const newMinUpkeepSpend = toWei('10') + const financeAdminAddress = await financeAdmin.getAddress() + + await registry.connect(owner).setConfigTypeSafe( + signerAddresses, + keeperAddresses, + f, + { + checkGasLimit, + stalenessSeconds, + gasCeilingMultiplier, + maxCheckDataSize, + maxPerformDataSize, + maxRevertDataSize, + maxPerformGas, + fallbackGasPrice, + fallbackLinkPrice, + fallbackNativePrice, + transcoder: transcoder.address, + registrars: [], + upkeepPrivilegeManager: upkeepManager, + chainModule: moduleBase.address, + reorgProtectionEnabled: true, + financeAdmin: financeAdminAddress, + }, + offchainVersion, + offchainBytes, + [linkToken.address], + [ + { + gasFeePPB: paymentPremiumPPB, + flatFeeMilliCents, + priceFeed: linkUSDFeed.address, + fallbackPrice: fallbackLinkPrice, + minSpend: newMinUpkeepSpend, + decimals: 18, + }, + ], + ) + + const payee1Before = await linkToken.balanceOf( + await payee1.getAddress(), + ) + const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance + const ownerBefore = await registry.linkAvailableForPayment() + + const amountSpent = toWei('100').sub(upkeepBefore) + const cancellationFee = newMinUpkeepSpend.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.linkAvailableForPayment() + + // 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 newMinUpkeepSpend = toWei('1000') + const financeAdminAddress = await financeAdmin.getAddress() + + await registry.connect(owner).setConfigTypeSafe( + signerAddresses, + keeperAddresses, + f, + { + checkGasLimit, + stalenessSeconds, + gasCeilingMultiplier, + maxCheckDataSize, + maxPerformDataSize, + maxRevertDataSize, + maxPerformGas, + fallbackGasPrice, + fallbackLinkPrice, + fallbackNativePrice, + transcoder: transcoder.address, + registrars: [], + upkeepPrivilegeManager: upkeepManager, + chainModule: moduleBase.address, + reorgProtectionEnabled: true, + financeAdmin: financeAdminAddress, + }, + offchainVersion, + offchainBytes, + [linkToken.address], + [ + { + gasFeePPB: paymentPremiumPPB, + flatFeeMilliCents, + priceFeed: linkUSDFeed.address, + fallbackPrice: fallbackLinkPrice, + minSpend: newMinUpkeepSpend, + decimals: 18, + }, + ], + ) + const payee1Before = await linkToken.balanceOf( + await payee1.getAddress(), + ) + const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance + const ownerBefore = await registry.linkAvailableForPayment() + + await registry.connect(admin).cancelUpkeep(upkeepId) + const payee1After = await linkToken.balanceOf( + await payee1.getAddress(), + ) + const ownerAfter = await registry.linkAvailableForPayment() + const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance + + // all upkeep balance is deducted for cancellation fee + assert.equal(upkeepAfter.toNumber(), 0) + // 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 minUpkeepSpendDollars is spent', async () => { + // Very low min spend, already spent in one perform upkeep + const newMinUpkeepSpend = BigNumber.from(420) + const financeAdminAddress = await financeAdmin.getAddress() + + await registry.connect(owner).setConfigTypeSafe( + signerAddresses, + keeperAddresses, + f, + { + checkGasLimit, + stalenessSeconds, + gasCeilingMultiplier, + maxCheckDataSize, + maxPerformDataSize, + maxRevertDataSize, + maxPerformGas, + fallbackGasPrice, + fallbackLinkPrice, + fallbackNativePrice, + transcoder: transcoder.address, + registrars: [], + upkeepPrivilegeManager: upkeepManager, + chainModule: moduleBase.address, + reorgProtectionEnabled: true, + financeAdmin: financeAdminAddress, + }, + offchainVersion, + offchainBytes, + [linkToken.address], + [ + { + gasFeePPB: paymentPremiumPPB, + flatFeeMilliCents, + priceFeed: linkUSDFeed.address, + fallbackPrice: fallbackLinkPrice, + minSpend: newMinUpkeepSpend, + decimals: 18, + }, + ], + ) + const payee1Before = await linkToken.balanceOf( + await payee1.getAddress(), + ) + const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance + const ownerBefore = await registry.linkAvailableForPayment() + + await registry.connect(admin).cancelUpkeep(upkeepId) + const payee1After = await linkToken.balanceOf( + await payee1.getAddress(), + ) + const ownerAfter = await registry.linkAvailableForPayment() + 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.linkAvailableForPayment() + + // 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.linkAvailableForPayment() + + // 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('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( + it('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, + baseConfig[6], + baseConfig[7], + ) + 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, + baseConfig[6], + baseConfig[7], + ) + 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/helpers.ts b/contracts/test/v0.8/automation/helpers.ts index b2cdfb4efd9..99f2cef9b87 100644 --- a/contracts/test/v0.8/automation/helpers.ts +++ b/contracts/test/v0.8/automation/helpers.ts @@ -9,6 +9,7 @@ import { IAutomationRegistryMaster__factory as IAutomationRegistryMasterFactory import { assert } from 'chai' import { FunctionFragment } from '@ethersproject/abi' import { AutomationRegistryLogicC2_3__factory as AutomationRegistryLogicC2_3Factory } from '../../../typechain/factories/AutomationRegistryLogicC2_3__factory' +import { ZKSyncAutomationRegistryLogicC2_3__factory as ZKSyncAutomationRegistryLogicC2_3Factory } from '../../../typechain/factories/ZKSyncAutomationRegistryLogicC2_3__factory' import { IAutomationRegistryMaster2_3 as IAutomationRegistry2_3 } from '../../../typechain/IAutomationRegistryMaster2_3' import { IAutomationRegistryMaster2_3__factory as IAutomationRegistryMaster2_3Factory } from '../../../typechain/factories/IAutomationRegistryMaster2_3__factory' @@ -212,3 +213,51 @@ export const deployRegistry23 = async ( const master = await registryFactory.connect(from).deploy(logicA.address) return IAutomationRegistryMaster2_3Factory.connect(master.address, from) } + +export const deployZKSyncRegistry23 = async ( + from: Signer, + link: Parameters[0], + linkUSD: Parameters[1], + nativeUSD: Parameters[2], + fastgas: Parameters[3], + allowedReadOnlyAddress: Parameters< + AutomationRegistryLogicC2_3Factory['deploy'] + >[5], + payoutMode: Parameters[6], + wrappedNativeTokenAddress: Parameters< + ZKSyncAutomationRegistryLogicC2_3Factory['deploy'] + >[7], +): Promise => { + const logicCFactory = await ethers.getContractFactory( + 'ZKSyncAutomationRegistryLogicC2_3', + ) + const logicBFactory = await ethers.getContractFactory( + 'ZKSyncAutomationRegistryLogicB2_3', + ) + const logicAFactory = await ethers.getContractFactory( + 'ZKSyncAutomationRegistryLogicA2_3', + ) + const registryFactory = await ethers.getContractFactory( + 'ZKSyncAutomationRegistry2_3', + ) + const forwarderLogicFactory = await ethers.getContractFactory( + 'AutomationForwarderLogic', + ) + const forwarderLogic = await forwarderLogicFactory.connect(from).deploy() + const logicC = await logicCFactory + .connect(from) + .deploy( + link, + linkUSD, + nativeUSD, + fastgas, + forwarderLogic.address, + allowedReadOnlyAddress, + payoutMode, + wrappedNativeTokenAddress, + ) + const logicB = await logicBFactory.connect(from).deploy(logicC.address) + const logicA = await logicAFactory.connect(from).deploy(logicB.address) + const master = await registryFactory.connect(from).deploy(logicA.address) + return IAutomationRegistryMaster2_3Factory.connect(master.address, from) +} diff --git a/core/capabilities/aggregator_factory.go b/core/capabilities/aggregator_factory.go index 18336e3f802..1abf58b6c12 100644 --- a/core/capabilities/aggregator_factory.go +++ b/core/capabilities/aggregator_factory.go @@ -3,6 +3,7 @@ package capabilities import ( "fmt" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/aggregators" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/datafeeds" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -14,7 +15,9 @@ func NewAggregator(name string, config values.Map, lggr logger.Logger) (types.Ag switch name { case "data_feeds": mc := streams.NewCodec(lggr) - return datafeeds.NewDataFeedsAggregator(config, mc, lggr) + return datafeeds.NewDataFeedsAggregator(config, mc) + case "identical": + return aggregators.NewIdenticalAggregator(config) default: return nil, fmt.Errorf("aggregator %s not supported", name) } diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index 66c47f4741f..ff5d62205d0 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -3,6 +3,7 @@ package ccipreader import ( "context" "math/big" + "sort" "testing" "time" @@ -16,8 +17,9 @@ import ( "go.uber.org/zap/zapcore" "golang.org/x/exp/maps" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" @@ -30,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" @@ -63,13 +66,21 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { }, } - s := testSetup(ctx, t, chainD, chainD, nil, cfg) + onRampAddress := utils.RandomAddress() + s := testSetup(ctx, t, chainD, chainD, nil, cfg, map[cciptypes.ChainSelector][]types.BoundContract{ + chainS1: { + { + Address: onRampAddress.Hex(), + Name: consts.ContractNameOnRamp, + }, + }, + }) tokenA := common.HexToAddress("123") const numReports = 5 - for i := uint8(0); i < numReports; i++ { - _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.EVM2EVMMultiOffRampCommitReport{ + for i := 0; i < numReports; i++ { + _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.OffRampCommitReport{ PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ { @@ -84,21 +95,35 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { }, }, }, - MerkleRoots: []ccip_reader_tester.EVM2EVMMultiOffRampMerkleRoot{ + MerkleRoots: []ccip_reader_tester.InternalMerkleRoot{ { SourceChainSelector: uint64(chainS1), - Interval: ccip_reader_tester.EVM2EVMMultiOffRampInterval{ - Min: 10, - Max: 20, - }, - MerkleRoot: [32]byte{i + 1}, + MinSeqNr: 10, + MaxSeqNr: 20, + MerkleRoot: [32]byte{uint8(i) + 1}, //nolint:gosec // this won't overflow + OnRampAddress: common.LeftPadBytes(onRampAddress.Bytes(), 32), + }, + }, + RmnSignatures: []ccip_reader_tester.IRMNRemoteSignature{ + { + R: [32]byte{1}, + S: [32]byte{2}, + }, + { + R: [32]byte{3}, + S: [32]byte{4}, }, }, + RmnRawVs: big.NewInt(100), }) assert.NoError(t, err) s.sb.Commit() } + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + var reports []plugintypes.CommitPluginReportWithMeta var err error require.Eventually(t, func() bool { @@ -110,10 +135,12 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { ) require.NoError(t, err) return len(reports) == numReports-1 - }, testutils.WaitTimeout(t), 50*time.Millisecond) + }, tests.WaitTimeout(t), 50*time.Millisecond) + assert.Len(t, reports, numReports-1) assert.Len(t, reports[0].Report.MerkleRoots, 1) assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) + assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", @@ -145,15 +172,17 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { }, } - s := testSetup(ctx, t, chainD, chainD, nil, cfg) + s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil) _, err := s.contract.EmitExecutionStateChanged( s.auth, uint64(chainS1), 14, cciptypes.Bytes32{1, 0, 0, 1}, + cciptypes.Bytes32{1, 0, 0, 1, 1, 0, 0, 1}, 1, []byte{1, 2, 3, 4}, + big.NewInt(250_000), ) assert.NoError(t, err) s.sb.Commit() @@ -163,8 +192,10 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { uint64(chainS1), 15, cciptypes.Bytes32{1, 0, 0, 2}, + cciptypes.Bytes32{1, 0, 0, 2, 1, 0, 0, 2}, 1, []byte{1, 2, 3, 4, 5}, + big.NewInt(350_000), ) assert.NoError(t, err) s.sb.Commit() @@ -199,12 +230,12 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { Contracts: map[string]evmtypes.ChainContractReader{ consts.ContractNameOnRamp: { ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCCIPSendRequested}, + GenericEventNames: []string{consts.EventNameCCIPMessageSent}, }, ContractABI: ccip_reader_tester.CCIPReaderTesterABI, Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCCIPSendRequested: { - ChainSpecificName: consts.EventNameCCIPSendRequested, + consts.EventNameCCIPMessageSent: { + ChainSpecificName: "CCIPMessageSent", ReadType: evmtypes.Event, }, }, @@ -212,9 +243,9 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { }, } - s := testSetup(ctx, t, chainS1, chainD, nil, cfg) + s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil) - _, err := s.contract.EmitCCIPSendRequested(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ MessageId: [32]byte{1, 0, 0, 0, 0}, SourceChainSelector: uint64(chainS1), @@ -227,11 +258,12 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { ExtraArgs: make([]byte, 0), FeeToken: utils.RandomAddress(), FeeTokenAmount: big.NewInt(0), - TokenAmounts: make([]ccip_reader_tester.InternalRampTokenAmount, 0), + FeeValueJuels: big.NewInt(0), + TokenAmounts: make([]ccip_reader_tester.InternalEVM2AnyTokenTransfer, 0), }) assert.NoError(t, err) - _, err = s.contract.EmitCCIPSendRequested(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ MessageId: [32]byte{1, 0, 0, 0, 1}, SourceChainSelector: uint64(chainS1), @@ -244,12 +276,17 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { ExtraArgs: make([]byte, 0), FeeToken: utils.RandomAddress(), FeeTokenAmount: big.NewInt(0), - TokenAmounts: make([]ccip_reader_tester.InternalRampTokenAmount, 0), + FeeValueJuels: big.NewInt(0), + TokenAmounts: make([]ccip_reader_tester.InternalEVM2AnyTokenTransfer, 0), }) assert.NoError(t, err) s.sb.Commit() + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + var msgs []cciptypes.Message require.Eventually(t, func() bool { msgs, err = s.reader.MsgsBetweenSeqNums( @@ -259,9 +296,13 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { ) require.NoError(t, err) return len(msgs) == 2 - }, 10*time.Second, 100*time.Millisecond) + }, tests.WaitTimeout(t), 100*time.Millisecond) require.Len(t, msgs, 2) + // sort to ensure ascending order of sequence numbers. + sort.Slice(msgs, func(i, j int) bool { + return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber + }) require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) for _, msg := range msgs { @@ -293,7 +334,7 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { }, } - s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg) + s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg, nil) seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) assert.NoError(t, err) @@ -303,7 +344,109 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) } -func testSetup(ctx context.Context, t *testing.T, readerChain, destChain cciptypes.ChainSelector, onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, cfg evmtypes.ChainReaderConfig) *testSetupData { +func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetExpectedNextSequenceNumber: { + ChainSpecificName: "getExpectedNextSequenceNumber", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil) + + _, err := s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 10) + require.NoError(t, err) + s.sb.Commit() + + seqNum, err := s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) + require.NoError(t, err) + require.Equal(t, cciptypes.SeqNum(10)+1, seqNum) + + _, err = s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 25) + require.NoError(t, err) + s.sb.Commit() + + seqNum, err = s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) + require.NoError(t, err) + require.Equal(t, cciptypes.SeqNum(25)+1, seqNum) +} + +func TestCCIPReader_Nonces(t *testing.T) { + ctx := testutils.Context(t) + var nonces = map[cciptypes.ChainSelector]map[common.Address]uint64{ + chainS1: { + utils.RandomAddress(): 10, + utils.RandomAddress(): 20, + }, + chainS2: { + utils.RandomAddress(): 30, + utils.RandomAddress(): 40, + }, + chainS3: { + utils.RandomAddress(): 50, + utils.RandomAddress(): 60, + }, + } + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameNonceManager: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetInboundNonce: { + ChainSpecificName: "getInboundNonce", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil) + + // Add some nonces. + for chain, addrs := range nonces { + for addr, nonce := range addrs { + _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, addr.Bytes()) + assert.NoError(t, err) + } + } + s.sb.Commit() + + for sourceChain, addrs := range nonces { + var addrQuery []string + for addr := range addrs { + addrQuery = append(addrQuery, addr.String()) + } + addrQuery = append(addrQuery, utils.RandomAddress().String()) + + results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) + assert.NoError(t, err) + assert.Len(t, results, len(addrQuery)) + for addr, nonce := range addrs { + assert.Equal(t, nonce, results[addr.String()]) + } + } +} + +func testSetup( + ctx context.Context, + t *testing.T, + readerChain, + destChain cciptypes.ChainSelector, + onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, + cfg evmtypes.ChainReaderConfig, + otherBindings map[cciptypes.ChainSelector][]types.BoundContract, +) *testSetupData { const chainID = 1337 // Generate a new key pair for the simulated account @@ -350,9 +493,10 @@ func testSetup(ctx context.Context, t *testing.T, readerChain, destChain cciptyp assert.NoError(t, lp.Start(ctx)) for sourceChain, seqNum := range onChainSeqNums { - _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.EVM2EVMMultiOffRampSourceChainConfig{ + _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ IsEnabled: true, MinSeqNr: uint64(seqNum), + OnRamp: utils.RandomAddress().Bytes(), }) assert.NoError(t, err1) simulatedBackend.Commit() @@ -375,13 +519,25 @@ func testSetup(ctx context.Context, t *testing.T, readerChain, destChain cciptyp }, }) require.NoError(t, err) + var otherCrs = make(map[cciptypes.ChainSelector]contractreader.Extended) + for chain, bindings := range otherBindings { + m := readermocks.NewMockContractReaderFacade(t) + m.EXPECT().Bind(ctx, bindings).Return(nil) + ecr := contractreader.NewExtendedContractReader(m) + err = ecr.Bind(ctx, bindings) + require.NoError(t, err) + otherCrs[chain] = ecr + } err = cr.Start(ctx) require.NoError(t, err) contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{readerChain: extendedCr} + for chain, cr := range otherCrs { + contractReaders[chain] = cr + } contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(lggr, contractReaders, contractWriters, destChain) + reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, destChain, nil) t.Cleanup(func() { require.NoError(t, cr.Close()) diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile b/core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile deleted file mode 100644 index e9c88564e69..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile +++ /dev/null @@ -1,12 +0,0 @@ - -# IMPORTANT: If you encounter any issues try using solc 0.8.18 and abigen 1.14.5 - -.PHONY: build -build: - rm -rf build/ - solc --evm-version paris --abi --bin mycontract.sol -o build - abigen --abi build/mycontract_sol_SimpleContract.abi --bin build/mycontract_sol_SimpleContract.bin --pkg=chainreader --out=mycontract.go - -.PHONY: test -test: build - go test -v --tags "playground" ./... diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go b/core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go deleted file mode 100644 index 52a3de0dae9..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go +++ /dev/null @@ -1,273 +0,0 @@ -//go:build playground -// +build playground - -package chainreader - -import ( - "context" - _ "embed" - "math/big" - "strconv" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "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/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/codec" - types2 "github.com/smartcontractkit/chainlink-common/pkg/types" - query2 "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "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" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - logger2 "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -const chainID = 1337 - -type testSetupData struct { - contractAddr common.Address - contract *Chainreader - sb *backends.SimulatedBackend - auth *bind.TransactOpts -} - -func TestChainReader(t *testing.T) { - ctx := testutils.Context(t) - lggr := logger2.NullLogger - d := testSetup(t, ctx) - - db := pgtest.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 0, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, d.sb, big.NewInt(chainID)) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(chainID), db, lggr), - cl, - lggr, - headTracker, - lpOpts, - ) - assert.NoError(t, lp.Start(ctx)) - - const ( - ContractNameAlias = "myCoolContract" - - FnAliasGetCount = "myCoolFunction" - FnGetCount = "getEventCount" - - FnAliasGetNumbers = "GetNumbers" - FnGetNumbers = "getNumbers" - - FnAliasGetPerson = "GetPerson" - FnGetPerson = "getPerson" - - EventNameAlias = "myCoolEvent" - EventName = "SimpleEvent" - ) - - // Initialize chainReader - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - ContractNameAlias: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{EventNameAlias}, - }, - ContractABI: ChainreaderMetaData.ABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - EventNameAlias: { - ChainSpecificName: EventName, - ReadType: evmtypes.Event, - ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": 0}, - }, - FnAliasGetCount: { - ChainSpecificName: FnGetCount, - }, - FnAliasGetNumbers: { - ChainSpecificName: FnGetNumbers, - OutputModifications: codec.ModifiersConfig{}, - }, - FnAliasGetPerson: { - ChainSpecificName: FnGetPerson, - OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{ - Fields: map[string]string{"Name": "NameField"}, // solidity name -> go struct name - }, - }, - }, - }, - }, - }, - } - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, cl, cfg) - assert.NoError(t, err) - err = cr.Bind(ctx, []types2.BoundContract{ - { - Address: d.contractAddr.String(), - Name: ContractNameAlias, - Pending: false, - }, - }) - assert.NoError(t, err) - - err = cr.Start(ctx) - assert.NoError(t, err) - for { - if err := cr.Ready(); err == nil { - break - } - } - - emitEvents(t, d, ctx) // Calls the contract to emit events - - // (hack) Sometimes LP logs are missing, commit several times and wait few seconds to make it work. - for i := 0; i < 100; i++ { - d.sb.Commit() - } - time.Sleep(5 * time.Second) - - t.Run("simple contract read", func(t *testing.T) { - var cnt big.Int - err = cr.GetLatestValue(ctx, ContractNameAlias, FnAliasGetCount, map[string]interface{}{}, &cnt) - assert.NoError(t, err) - assert.Equal(t, int64(10), cnt.Int64()) - }) - - t.Run("read array", func(t *testing.T) { - var nums []big.Int - err = cr.GetLatestValue(ctx, ContractNameAlias, FnAliasGetNumbers, map[string]interface{}{}, &nums) - assert.NoError(t, err) - assert.Len(t, nums, 10) - for i := 1; i <= 10; i++ { - assert.Equal(t, int64(i), nums[i-1].Int64()) - } - }) - - t.Run("read struct", func(t *testing.T) { - person := struct { - NameField string - Age *big.Int // WARN: specifying a wrong data type e.g. int instead of *big.Int fails silently with a default value of 0 - }{} - err = cr.GetLatestValue(ctx, ContractNameAlias, FnAliasGetPerson, map[string]interface{}{}, &person) - assert.Equal(t, "Dim", person.NameField) - assert.Equal(t, int64(18), person.Age.Int64()) - }) - - t.Run("read events", func(t *testing.T) { - var myDataType *big.Int - seq, err := cr.QueryKey( - ctx, - ContractNameAlias, - query2.KeyFilter{ - Key: EventNameAlias, - Expressions: []query2.Expression{}, - }, - query2.LimitAndSort{}, - myDataType, - ) - assert.NoError(t, err) - assert.Equal(t, 10, len(seq), "expected 10 events from chain reader") - for _, v := range seq { - // TODO: for some reason log poller does not populate event data - blockNum, err := strconv.ParseUint(v.Identifier, 10, 64) - assert.NoError(t, err) - assert.Positive(t, blockNum) - t.Logf("(chain reader) got event: (data=%v) (hash=%x)", v.Data, v.Hash) - } - }) -} - -func testSetup(t *testing.T, ctx context.Context) *testSetupData { - // Generate a new key pair for the simulated account - privateKey, err := crypto.GenerateKey() - assert.NoError(t, err) - // Set up the genesis account with balance - blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) - assert.True(t, ok) - alloc := map[common.Address]core.GenesisAccount{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} - simulatedBackend := backends.NewSimulatedBackend(alloc, 0) - // Create a transactor - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) - assert.NoError(t, err) - auth.GasLimit = uint64(0) - - // Deploy the contract - address, tx, _, err := DeployChainreader(auth, simulatedBackend) - assert.NoError(t, err) - simulatedBackend.Commit() - t.Logf("contract deployed: addr=%s tx=%s", address.Hex(), tx.Hash()) - - // Setup contract client - contract, err := NewChainreader(address, simulatedBackend) - assert.NoError(t, err) - - return &testSetupData{ - contractAddr: address, - contract: contract, - sb: simulatedBackend, - auth: auth, - } -} - -func emitEvents(t *testing.T, d *testSetupData, ctx context.Context) { - var wg sync.WaitGroup - wg.Add(2) - - // Start emitting events - go func() { - defer wg.Done() - for i := 0; i < 10; i++ { - _, err := d.contract.EmitEvent(d.auth) - assert.NoError(t, err) - d.sb.Commit() - } - }() - - // Listen events using go-ethereum lib - go func() { - query := ethereum.FilterQuery{ - FromBlock: big.NewInt(0), - Addresses: []common.Address{d.contractAddr}, - } - logs := make(chan types.Log) - sub, err := d.sb.SubscribeFilterLogs(ctx, query, logs) - assert.NoError(t, err) - - numLogs := 0 - defer wg.Done() - for { - // Wait for the events - select { - case err := <-sub.Err(): - assert.NoError(t, err, "got an unexpected error") - case vLog := <-logs: - assert.Equal(t, d.contractAddr, vLog.Address, "got an unexpected address") - t.Logf("(geth) got new log (cnt=%d) (data=%x) (topics=%s)", numLogs, vLog.Data, vLog.Topics) - numLogs++ - if numLogs == 10 { - return - } - } - } - }() - - wg.Wait() // wait for all the events to be consumed -} diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go b/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go deleted file mode 100644 index c7d480eed46..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go +++ /dev/null @@ -1,519 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package chainreader - -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" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// SimpleContractPerson is an auto generated low-level Go binding around an user-defined struct. -type SimpleContractPerson struct { - Name string - Age *big.Int -} - -// ChainreaderMetaData contains all meta data concerning the Chainreader contract. -var ChainreaderMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SimpleEvent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"emitEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEventCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumbers\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerson\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"age\",\"type\":\"uint256\"}],\"internalType\":\"structSimpleContract.Person\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"numbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506105a1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806371be2e4a146100675780637b0cb8391461008557806389f915f61461008f5780638ec4dc95146100ad578063d39fa233146100cb578063d9e48f5c146100fb575b600080fd5b61006f610119565b60405161007c91906102ac565b60405180910390f35b61008d61011f565b005b61009761019c565b6040516100a49190610385565b60405180910390f35b6100b56101f4565b6040516100c29190610474565b60405180910390f35b6100e560048036038101906100e091906104c7565b61024c565b6040516100f291906102ac565b60405180910390f35b610103610270565b60405161011091906102ac565b60405180910390f35b60005481565b60008081548092919061013190610523565b9190505550600160005490806001815401808255809150506001900390600052602060002001600090919091909150557f12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb60005460405161019291906102ac565b60405180910390a1565b606060018054806020026020016040519081016040528092919081815260200182805480156101ea57602002820191906000526020600020905b8154815260200190600101908083116101d6575b5050505050905090565b6101fc610279565b60405180604001604052806040518060400160405280600381526020017f44696d000000000000000000000000000000000000000000000000000000000081525081526020016012815250905090565b6001818154811061025c57600080fd5b906000526020600020016000915090505481565b60008054905090565b604051806040016040528060608152602001600081525090565b6000819050919050565b6102a681610293565b82525050565b60006020820190506102c1600083018461029d565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6102fc81610293565b82525050565b600061030e83836102f3565b60208301905092915050565b6000602082019050919050565b6000610332826102c7565b61033c81856102d2565b9350610347836102e3565b8060005b8381101561037857815161035f8882610302565b975061036a8361031a565b92505060018101905061034b565b5085935050505092915050565b6000602082019050818103600083015261039f8184610327565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156103e15780820151818401526020810190506103c6565b60008484015250505050565b6000601f19601f8301169050919050565b6000610409826103a7565b61041381856103b2565b93506104238185602086016103c3565b61042c816103ed565b840191505092915050565b6000604083016000830151848203600086015261045482826103fe565b915050602083015161046960208601826102f3565b508091505092915050565b6000602082019050818103600083015261048e8184610437565b905092915050565b600080fd5b6104a481610293565b81146104af57600080fd5b50565b6000813590506104c18161049b565b92915050565b6000602082840312156104dd576104dc610496565b5b60006104eb848285016104b2565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061052e82610293565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036105605761055f6104f4565b5b60018201905091905056fea2646970667358221220f7986dc9efbc0d9ef58e2925ffddc62ea13a6bab8b3a2c03ad2d85d50653129664736f6c63430008120033", -} - -// ChainreaderABI is the input ABI used to generate the binding from. -// Deprecated: Use ChainreaderMetaData.ABI instead. -var ChainreaderABI = ChainreaderMetaData.ABI - -// ChainreaderBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use ChainreaderMetaData.Bin instead. -var ChainreaderBin = ChainreaderMetaData.Bin - -// DeployChainreader deploys a new Ethereum contract, binding an instance of Chainreader to it. -func DeployChainreader(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Chainreader, error) { - parsed, err := ChainreaderMetaData.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(ChainreaderBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Chainreader{ChainreaderCaller: ChainreaderCaller{contract: contract}, ChainreaderTransactor: ChainreaderTransactor{contract: contract}, ChainreaderFilterer: ChainreaderFilterer{contract: contract}}, nil -} - -// Chainreader is an auto generated Go binding around an Ethereum contract. -type Chainreader struct { - ChainreaderCaller // Read-only binding to the contract - ChainreaderTransactor // Write-only binding to the contract - ChainreaderFilterer // Log filterer for contract events -} - -// ChainreaderCaller is an auto generated read-only Go binding around an Ethereum contract. -type ChainreaderCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ChainreaderTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ChainreaderTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ChainreaderFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ChainreaderFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ChainreaderSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ChainreaderSession struct { - Contract *Chainreader // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ChainreaderCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ChainreaderCallerSession struct { - Contract *ChainreaderCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ChainreaderTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ChainreaderTransactorSession struct { - Contract *ChainreaderTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ChainreaderRaw is an auto generated low-level Go binding around an Ethereum contract. -type ChainreaderRaw struct { - Contract *Chainreader // Generic contract binding to access the raw methods on -} - -// ChainreaderCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ChainreaderCallerRaw struct { - Contract *ChainreaderCaller // Generic read-only contract binding to access the raw methods on -} - -// ChainreaderTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ChainreaderTransactorRaw struct { - Contract *ChainreaderTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewChainreader creates a new instance of Chainreader, bound to a specific deployed contract. -func NewChainreader(address common.Address, backend bind.ContractBackend) (*Chainreader, error) { - contract, err := bindChainreader(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Chainreader{ChainreaderCaller: ChainreaderCaller{contract: contract}, ChainreaderTransactor: ChainreaderTransactor{contract: contract}, ChainreaderFilterer: ChainreaderFilterer{contract: contract}}, nil -} - -// NewChainreaderCaller creates a new read-only instance of Chainreader, bound to a specific deployed contract. -func NewChainreaderCaller(address common.Address, caller bind.ContractCaller) (*ChainreaderCaller, error) { - contract, err := bindChainreader(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ChainreaderCaller{contract: contract}, nil -} - -// NewChainreaderTransactor creates a new write-only instance of Chainreader, bound to a specific deployed contract. -func NewChainreaderTransactor(address common.Address, transactor bind.ContractTransactor) (*ChainreaderTransactor, error) { - contract, err := bindChainreader(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ChainreaderTransactor{contract: contract}, nil -} - -// NewChainreaderFilterer creates a new log filterer instance of Chainreader, bound to a specific deployed contract. -func NewChainreaderFilterer(address common.Address, filterer bind.ContractFilterer) (*ChainreaderFilterer, error) { - contract, err := bindChainreader(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ChainreaderFilterer{contract: contract}, nil -} - -// bindChainreader binds a generic wrapper to an already deployed contract. -func bindChainreader(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ChainreaderMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Chainreader *ChainreaderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Chainreader.Contract.ChainreaderCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Chainreader *ChainreaderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Chainreader.Contract.ChainreaderTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Chainreader *ChainreaderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Chainreader.Contract.ChainreaderTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Chainreader *ChainreaderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Chainreader.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Chainreader *ChainreaderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Chainreader.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Chainreader *ChainreaderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Chainreader.Contract.contract.Transact(opts, method, params...) -} - -// EventCount is a free data retrieval call binding the contract method 0x71be2e4a. -// -// Solidity: function eventCount() view returns(uint256) -func (_Chainreader *ChainreaderCaller) EventCount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "eventCount") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// EventCount is a free data retrieval call binding the contract method 0x71be2e4a. -// -// Solidity: function eventCount() view returns(uint256) -func (_Chainreader *ChainreaderSession) EventCount() (*big.Int, error) { - return _Chainreader.Contract.EventCount(&_Chainreader.CallOpts) -} - -// EventCount is a free data retrieval call binding the contract method 0x71be2e4a. -// -// Solidity: function eventCount() view returns(uint256) -func (_Chainreader *ChainreaderCallerSession) EventCount() (*big.Int, error) { - return _Chainreader.Contract.EventCount(&_Chainreader.CallOpts) -} - -// GetEventCount is a free data retrieval call binding the contract method 0xd9e48f5c. -// -// Solidity: function getEventCount() view returns(uint256) -func (_Chainreader *ChainreaderCaller) GetEventCount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "getEventCount") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetEventCount is a free data retrieval call binding the contract method 0xd9e48f5c. -// -// Solidity: function getEventCount() view returns(uint256) -func (_Chainreader *ChainreaderSession) GetEventCount() (*big.Int, error) { - return _Chainreader.Contract.GetEventCount(&_Chainreader.CallOpts) -} - -// GetEventCount is a free data retrieval call binding the contract method 0xd9e48f5c. -// -// Solidity: function getEventCount() view returns(uint256) -func (_Chainreader *ChainreaderCallerSession) GetEventCount() (*big.Int, error) { - return _Chainreader.Contract.GetEventCount(&_Chainreader.CallOpts) -} - -// GetNumbers is a free data retrieval call binding the contract method 0x89f915f6. -// -// Solidity: function getNumbers() view returns(uint256[]) -func (_Chainreader *ChainreaderCaller) GetNumbers(opts *bind.CallOpts) ([]*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "getNumbers") - - if err != nil { - return *new([]*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) - - return out0, err - -} - -// GetNumbers is a free data retrieval call binding the contract method 0x89f915f6. -// -// Solidity: function getNumbers() view returns(uint256[]) -func (_Chainreader *ChainreaderSession) GetNumbers() ([]*big.Int, error) { - return _Chainreader.Contract.GetNumbers(&_Chainreader.CallOpts) -} - -// GetNumbers is a free data retrieval call binding the contract method 0x89f915f6. -// -// Solidity: function getNumbers() view returns(uint256[]) -func (_Chainreader *ChainreaderCallerSession) GetNumbers() ([]*big.Int, error) { - return _Chainreader.Contract.GetNumbers(&_Chainreader.CallOpts) -} - -// GetPerson is a free data retrieval call binding the contract method 0x8ec4dc95. -// -// Solidity: function getPerson() pure returns((string,uint256)) -func (_Chainreader *ChainreaderCaller) GetPerson(opts *bind.CallOpts) (SimpleContractPerson, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "getPerson") - - if err != nil { - return *new(SimpleContractPerson), err - } - - out0 := *abi.ConvertType(out[0], new(SimpleContractPerson)).(*SimpleContractPerson) - - return out0, err - -} - -// GetPerson is a free data retrieval call binding the contract method 0x8ec4dc95. -// -// Solidity: function getPerson() pure returns((string,uint256)) -func (_Chainreader *ChainreaderSession) GetPerson() (SimpleContractPerson, error) { - return _Chainreader.Contract.GetPerson(&_Chainreader.CallOpts) -} - -// GetPerson is a free data retrieval call binding the contract method 0x8ec4dc95. -// -// Solidity: function getPerson() pure returns((string,uint256)) -func (_Chainreader *ChainreaderCallerSession) GetPerson() (SimpleContractPerson, error) { - return _Chainreader.Contract.GetPerson(&_Chainreader.CallOpts) -} - -// Numbers is a free data retrieval call binding the contract method 0xd39fa233. -// -// Solidity: function numbers(uint256 ) view returns(uint256) -func (_Chainreader *ChainreaderCaller) Numbers(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "numbers", arg0) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Numbers is a free data retrieval call binding the contract method 0xd39fa233. -// -// Solidity: function numbers(uint256 ) view returns(uint256) -func (_Chainreader *ChainreaderSession) Numbers(arg0 *big.Int) (*big.Int, error) { - return _Chainreader.Contract.Numbers(&_Chainreader.CallOpts, arg0) -} - -// Numbers is a free data retrieval call binding the contract method 0xd39fa233. -// -// Solidity: function numbers(uint256 ) view returns(uint256) -func (_Chainreader *ChainreaderCallerSession) Numbers(arg0 *big.Int) (*big.Int, error) { - return _Chainreader.Contract.Numbers(&_Chainreader.CallOpts, arg0) -} - -// EmitEvent is a paid mutator transaction binding the contract method 0x7b0cb839. -// -// Solidity: function emitEvent() returns() -func (_Chainreader *ChainreaderTransactor) EmitEvent(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Chainreader.contract.Transact(opts, "emitEvent") -} - -// EmitEvent is a paid mutator transaction binding the contract method 0x7b0cb839. -// -// Solidity: function emitEvent() returns() -func (_Chainreader *ChainreaderSession) EmitEvent() (*types.Transaction, error) { - return _Chainreader.Contract.EmitEvent(&_Chainreader.TransactOpts) -} - -// EmitEvent is a paid mutator transaction binding the contract method 0x7b0cb839. -// -// Solidity: function emitEvent() returns() -func (_Chainreader *ChainreaderTransactorSession) EmitEvent() (*types.Transaction, error) { - return _Chainreader.Contract.EmitEvent(&_Chainreader.TransactOpts) -} - -// ChainreaderSimpleEventIterator is returned from FilterSimpleEvent and is used to iterate over the raw logs and unpacked data for SimpleEvent events raised by the Chainreader contract. -type ChainreaderSimpleEventIterator struct { - Event *ChainreaderSimpleEvent // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ChainreaderSimpleEventIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChainreaderSimpleEvent) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ChainreaderSimpleEvent) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ChainreaderSimpleEventIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ChainreaderSimpleEventIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ChainreaderSimpleEvent represents a SimpleEvent event raised by the Chainreader contract. -type ChainreaderSimpleEvent struct { - Value *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSimpleEvent is a free log retrieval operation binding the contract event 0x12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb. -// -// Solidity: event SimpleEvent(uint256 value) -func (_Chainreader *ChainreaderFilterer) FilterSimpleEvent(opts *bind.FilterOpts) (*ChainreaderSimpleEventIterator, error) { - - logs, sub, err := _Chainreader.contract.FilterLogs(opts, "SimpleEvent") - if err != nil { - return nil, err - } - return &ChainreaderSimpleEventIterator{contract: _Chainreader.contract, event: "SimpleEvent", logs: logs, sub: sub}, nil -} - -// WatchSimpleEvent is a free log subscription operation binding the contract event 0x12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb. -// -// Solidity: event SimpleEvent(uint256 value) -func (_Chainreader *ChainreaderFilterer) WatchSimpleEvent(opts *bind.WatchOpts, sink chan<- *ChainreaderSimpleEvent) (event.Subscription, error) { - - logs, sub, err := _Chainreader.contract.WatchLogs(opts, "SimpleEvent") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ChainreaderSimpleEvent) - if err := _Chainreader.contract.UnpackLog(event, "SimpleEvent", 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 -} - -// ParseSimpleEvent is a log parse operation binding the contract event 0x12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb. -// -// Solidity: event SimpleEvent(uint256 value) -func (_Chainreader *ChainreaderFilterer) ParseSimpleEvent(log types.Log) (*ChainreaderSimpleEvent, error) { - event := new(ChainreaderSimpleEvent) - if err := _Chainreader.contract.UnpackLog(event, "SimpleEvent", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol b/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol deleted file mode 100644 index 0fae1f4baac..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.18; - -contract SimpleContract { - event SimpleEvent(uint256 value); - uint256 public eventCount; - uint[] public numbers; - - struct Person { - string name; - uint age; - } - - function emitEvent() public { - eventCount++; - numbers.push(eventCount); - emit SimpleEvent(eventCount); - } - - function getEventCount() public view returns (uint256) { - return eventCount; - } - - function getNumbers() public view returns (uint256[] memory) { - return numbers; - } - - function getPerson() public pure returns (Person memory) { - return Person("Dim", 18); - } -} diff --git a/core/capabilities/ccip/ccip_integration_tests/helpers.go b/core/capabilities/ccip/ccip_integration_tests/helpers.go deleted file mode 100644 index 7606c8bbebc..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/helpers.go +++ /dev/null @@ -1,938 +0,0 @@ -package ccip_integration_tests - -import ( - "bytes" - "encoding/hex" - "math/big" - "sort" - "testing" - "time" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "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/core" - - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/arm_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_arm_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ocr3_config_encoder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" - "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" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/stretchr/testify/require" -) - -var ( - homeChainID = chainsel.GETH_TESTNET.EvmChainID - ccipSendRequestedTopic = evm_2_evm_multi_onramp.EVM2EVMMultiOnRampCCIPSendRequested{}.Topic() - commitReportAcceptedTopic = evm_2_evm_multi_offramp.EVM2EVMMultiOffRampCommitReportAccepted{}.Topic() - executionStateChangedTopic = evm_2_evm_multi_offramp.EVM2EVMMultiOffRampExecutionStateChanged{}.Topic() -) - -const ( - CapabilityLabelledName = "ccip" - CapabilityVersion = "v1.0.0" - NodeOperatorID = 1 - - // These constants drive what is set in the plugin offchain configs. - FirstBlockAge = 8 * time.Hour - RemoteGasPriceBatchWriteFrequency = 30 * time.Minute - BatchGasLimit = 6_500_000 - RelativeBoostPerWaitHour = 1.5 - InflightCacheExpiry = 10 * time.Minute - RootSnoozeTime = 30 * time.Minute - BatchingStrategyID = 0 - DeltaProgress = 30 * time.Second - DeltaResend = 10 * time.Second - DeltaInitial = 20 * time.Second - DeltaRound = 2 * time.Second - DeltaGrace = 2 * time.Second - DeltaCertifiedCommitRequest = 10 * time.Second - DeltaStage = 10 * time.Second - Rmax = 3 - MaxDurationQuery = 50 * time.Millisecond - MaxDurationObservation = 5 * time.Second - MaxDurationShouldAcceptAttestedReport = 10 * time.Second - MaxDurationShouldTransmitAcceptedReport = 10 * time.Second -) - -func e18Mult(amount uint64) *big.Int { - return new(big.Int).Mul(uBigInt(amount), uBigInt(1e18)) -} - -func uBigInt(i uint64) *big.Int { - return new(big.Int).SetUint64(i) -} - -type homeChain struct { - backend *backends.SimulatedBackend - owner *bind.TransactOpts - chainID uint64 - capabilityRegistry *kcr.CapabilitiesRegistry - ccipConfig *ccip_config.CCIPConfig -} - -type onchainUniverse struct { - backend *backends.SimulatedBackend - owner *bind.TransactOpts - chainID uint64 - linkToken *link_token.LinkToken - weth *weth9.WETH9 - router *router.Router - rmnProxy *arm_proxy_contract.ARMProxyContract - rmn *mock_arm_contract.MockARMContract - onramp *evm_2_evm_multi_onramp.EVM2EVMMultiOnRamp - offramp *evm_2_evm_multi_offramp.EVM2EVMMultiOffRamp - priceRegistry *price_registry.PriceRegistry - tokenAdminRegistry *token_admin_registry.TokenAdminRegistry - nonceManager *nonce_manager.NonceManager - receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver -} - -type requestData struct { - destChainSelector uint64 - receiverAddress common.Address - data []byte -} - -func (u *onchainUniverse) SendCCIPRequests(t *testing.T, requestDatas []requestData) { - for _, reqData := range requestDatas { - msg := router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(reqData.receiverAddress.Bytes(), 32), - Data: reqData.data, - TokenAmounts: nil, // TODO: no tokens for now - FeeToken: u.weth.Address(), - ExtraArgs: nil, // TODO: no extra args for now, falls back to default - } - fee, err := u.router.GetFee(&bind.CallOpts{Context: testutils.Context(t)}, reqData.destChainSelector, msg) - require.NoError(t, err) - _, err = u.weth.Deposit(&bind.TransactOpts{ - From: u.owner.From, - Signer: u.owner.Signer, - Value: fee, - }) - require.NoError(t, err) - u.backend.Commit() - _, err = u.weth.Approve(u.owner, u.router.Address(), fee) - require.NoError(t, err) - u.backend.Commit() - - t.Logf("Sending CCIP request from chain %d (selector %d) to chain selector %d", - u.chainID, getSelector(u.chainID), reqData.destChainSelector) - _, err = u.router.CcipSend(u.owner, reqData.destChainSelector, msg) - require.NoError(t, err) - u.backend.Commit() - } -} - -type chainBase struct { - backend *backends.SimulatedBackend - owner *bind.TransactOpts -} - -// createUniverses does the following: -// 1. Creates 1 home chain and `numChains`-1 non-home chains -// 2. Sets up home chain with the capability registry and the CCIP config contract -// 2. Deploys the CCIP contracts to all chains. -// 3. Sets up the initial configurations for the contracts on all chains. -// 4. Wires the chains together. -// -// Conceptually one universe is ONE chain with all the contracts deployed on it and all the dependencies initialized. -func createUniverses( - t *testing.T, - numChains int, -) (homeChainUni homeChain, universes map[uint64]onchainUniverse) { - chains := createChains(t, numChains) - - homeChainBase, ok := chains[homeChainID] - require.True(t, ok, "home chain backend not available") - // Set up home chain first - homeChainUniverse := setupHomeChain(t, homeChainBase.owner, homeChainBase.backend) - - // deploy the ccip contracts on all chains - universes = make(map[uint64]onchainUniverse) - for chainID, base := range chains { - owner := base.owner - backend := base.backend - // deploy the CCIP contracts - linkToken := deployLinkToken(t, owner, backend, chainID) - rmn := deployMockARMContract(t, owner, backend, chainID) - rmnProxy := deployARMProxyContract(t, owner, backend, rmn.Address(), chainID) - weth := deployWETHContract(t, owner, backend, chainID) - rout := deployRouter(t, owner, backend, weth.Address(), rmnProxy.Address(), chainID) - priceRegistry := deployPriceRegistry(t, owner, backend, linkToken.Address(), weth.Address(), big.NewInt(1e18), chainID) - tokenAdminRegistry := deployTokenAdminRegistry(t, owner, backend, chainID) - nonceManager := deployNonceManager(t, owner, backend, chainID) - - // ====================================================================== - // OnRamp - // ====================================================================== - onRampAddr, _, _, err := evm_2_evm_multi_onramp.DeployEVM2EVMMultiOnRamp( - owner, - backend, - evm_2_evm_multi_onramp.EVM2EVMMultiOnRampStaticConfig{ - ChainSelector: getSelector(chainID), - RmnProxy: rmnProxy.Address(), - NonceManager: nonceManager.Address(), - TokenAdminRegistry: tokenAdminRegistry.Address(), - }, - evm_2_evm_multi_onramp.EVM2EVMMultiOnRampDynamicConfig{ - Router: rout.Address(), - PriceRegistry: priceRegistry.Address(), - // `withdrawFeeTokens` onRamp function is not part of the message flow - // so we can set this to any address - FeeAggregator: testutils.NewAddress(), - }, - ) - require.NoErrorf(t, err, "failed to deploy onramp on chain id %d", chainID) - backend.Commit() - onramp, err := evm_2_evm_multi_onramp.NewEVM2EVMMultiOnRamp(onRampAddr, backend) - require.NoError(t, err) - - // ====================================================================== - // OffRamp - // ====================================================================== - offrampAddr, _, _, err := evm_2_evm_multi_offramp.DeployEVM2EVMMultiOffRamp( - owner, - backend, - evm_2_evm_multi_offramp.EVM2EVMMultiOffRampStaticConfig{ - ChainSelector: getSelector(chainID), - RmnProxy: rmnProxy.Address(), - TokenAdminRegistry: tokenAdminRegistry.Address(), - NonceManager: nonceManager.Address(), - }, - evm_2_evm_multi_offramp.EVM2EVMMultiOffRampDynamicConfig{ - Router: rout.Address(), - PriceRegistry: priceRegistry.Address(), - }, - // Source chain configs will be set up later once we have all chains - []evm_2_evm_multi_offramp.EVM2EVMMultiOffRampSourceChainConfigArgs{}, - ) - require.NoErrorf(t, err, "failed to deploy offramp on chain id %d", chainID) - backend.Commit() - offramp, err := evm_2_evm_multi_offramp.NewEVM2EVMMultiOffRamp(offrampAddr, backend) - require.NoError(t, err) - - receiverAddress, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( - owner, - backend, - false, - ) - require.NoError(t, err, "failed to deploy MaybeRevertMessageReceiver on chain id %d", chainID) - backend.Commit() - receiver, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(receiverAddress, backend) - require.NoError(t, err) - - universe := onchainUniverse{ - backend: backend, - owner: owner, - chainID: chainID, - linkToken: linkToken, - weth: weth, - router: rout, - rmnProxy: rmnProxy, - rmn: rmn, - onramp: onramp, - offramp: offramp, - priceRegistry: priceRegistry, - tokenAdminRegistry: tokenAdminRegistry, - nonceManager: nonceManager, - receiver: receiver, - } - // Set up the initial configurations for the contracts - setupUniverseBasics(t, universe) - - universes[chainID] = universe - } - - // Once we have all chains created and contracts deployed, we can set up the initial configurations and wire chains together - connectUniverses(t, universes) - - // print out all contract addresses for debugging purposes - for chainID, uni := range universes { - t.Logf("Chain ID: %d\n Chain Selector: %d\n LinkToken: %s\n WETH: %s\n Router: %s\n RMNProxy: %s\n RMN: %s\n OnRamp: %s\n OffRamp: %s\n PriceRegistry: %s\n TokenAdminRegistry: %s\n NonceManager: %s\n", - chainID, - getSelector(chainID), - uni.linkToken.Address().Hex(), - uni.weth.Address().Hex(), - uni.router.Address().Hex(), - uni.rmnProxy.Address().Hex(), - uni.rmn.Address().Hex(), - uni.onramp.Address().Hex(), - uni.offramp.Address().Hex(), - uni.priceRegistry.Address().Hex(), - uni.tokenAdminRegistry.Address().Hex(), - uni.nonceManager.Address().Hex(), - ) - } - - // print out topic hashes of relevant events for debugging purposes - t.Logf("Topic hash of CommitReportAccepted: %s", commitReportAcceptedTopic.Hex()) - t.Logf("Topic hash of ExecutionStateChanged: %s", executionStateChangedTopic.Hex()) - t.Logf("Topic hash of CCIPSendRequested: %s", ccipSendRequestedTopic.Hex()) - - return homeChainUniverse, universes -} - -// Creates 1 home chain and `numChains`-1 non-home chains -func createChains(t *testing.T, numChains int) map[uint64]chainBase { - chains := make(map[uint64]chainBase) - - homeChainOwner := testutils.MustNewSimTransactor(t) - homeChainBackend := backends.NewSimulatedBackend(core.GenesisAlloc{ - homeChainOwner.From: core.GenesisAccount{ - Balance: assets.Ether(10_000).ToInt(), - }, - }, 30e6) - tweakChainTimestamp(t, homeChainBackend, FirstBlockAge) - - chains[homeChainID] = chainBase{ - owner: homeChainOwner, - backend: homeChainBackend, - } - - for chainID := chainsel.TEST_90000001.EvmChainID; len(chains) < numChains && chainID < chainsel.TEST_90000020.EvmChainID; chainID++ { - owner := testutils.MustNewSimTransactor(t) - backend := backends.NewSimulatedBackend(core.GenesisAlloc{ - owner.From: core.GenesisAccount{ - Balance: assets.Ether(10_000).ToInt(), - }, - }, 30e6) - - tweakChainTimestamp(t, backend, FirstBlockAge) - - chains[chainID] = chainBase{ - owner: owner, - backend: backend, - } - } - - return chains -} - -// CCIP relies on block timestamps, but SimulatedBackend uses by default clock starting from 1970-01-01 -// This trick is used to move the clock closer to the current time. We set first block to be X hours ago. -// Tests create plenty of transactions so this number can't be too low, every new block mined will tick the clock, -// if you mine more than "X hours" transactions, SimulatedBackend will panic because generated timestamps will be in the future. -func tweakChainTimestamp(t *testing.T, backend *backends.SimulatedBackend, tweak time.Duration) { - blockTime := time.Unix(int64(backend.Blockchain().CurrentHeader().Time), 0) - sinceBlockTime := time.Since(blockTime) - diff := sinceBlockTime - tweak - err := backend.AdjustTime(diff) - require.NoError(t, err, "unable to adjust time on simulated chain") - backend.Commit() - backend.Commit() -} - -func setupHomeChain(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend) homeChain { - // deploy the capability registry on the home chain - crAddress, _, _, err := kcr.DeployCapabilitiesRegistry(owner, backend) - require.NoError(t, err, "failed to deploy capability registry on home chain") - backend.Commit() - - capabilityRegistry, err := kcr.NewCapabilitiesRegistry(crAddress, backend) - require.NoError(t, err) - - ccAddress, _, _, err := ccip_config.DeployCCIPConfig(owner, backend, crAddress) - require.NoError(t, err) - backend.Commit() - - capabilityConfig, err := ccip_config.NewCCIPConfig(ccAddress, backend) - require.NoError(t, err) - - _, err = capabilityRegistry.AddCapabilities(owner, []kcr.CapabilitiesRegistryCapability{ - { - LabelledName: CapabilityLabelledName, - Version: CapabilityVersion, - CapabilityType: 2, // consensus. not used (?) - ResponseType: 0, // report. not used (?) - ConfigurationContract: ccAddress, - }, - }) - require.NoError(t, err, "failed to add capabilities to the capability registry") - backend.Commit() - - // Add NodeOperator, for simplicity we'll add one NodeOperator only - // First NodeOperator will have NodeOperatorId = 1 - _, err = capabilityRegistry.AddNodeOperators(owner, []kcr.CapabilitiesRegistryNodeOperator{ - { - Admin: owner.From, - Name: "NodeOperator", - }, - }) - require.NoError(t, err, "failed to add node operator to the capability registry") - backend.Commit() - - return homeChain{ - backend: backend, - owner: owner, - chainID: homeChainID, - capabilityRegistry: capabilityRegistry, - ccipConfig: capabilityConfig, - } -} - -func sortP2PIDS(p2pIDs [][32]byte) { - sort.Slice(p2pIDs, func(i, j int) bool { - return bytes.Compare(p2pIDs[i][:], p2pIDs[j][:]) < 0 - }) -} - -func (h *homeChain) AddNodes( - t *testing.T, - p2pIDs [][32]byte, - capabilityIDs [][32]byte, -) { - // Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail - sortP2PIDS(p2pIDs) - var nodeParams []kcr.CapabilitiesRegistryNodeParams - for _, p2pID := range p2pIDs { - nodeParam := kcr.CapabilitiesRegistryNodeParams{ - NodeOperatorId: NodeOperatorID, - Signer: p2pID, // Not used in tests - P2pId: p2pID, - HashedCapabilityIds: capabilityIDs, - } - nodeParams = append(nodeParams, nodeParam) - } - _, err := h.capabilityRegistry.AddNodes(h.owner, nodeParams) - require.NoError(t, err, "failed to add node operator oracles") - h.backend.Commit() -} - -func AddChainConfig( - t *testing.T, - h homeChain, - chainSelector uint64, - p2pIDs [][32]byte, - f uint8, -) ccip_config.CCIPConfigTypesChainConfigInfo { - // Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail - sortP2PIDS(p2pIDs) - // First Add ChainConfig that includes all p2pIDs as readers - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - FinalityDepth: 10, - OptimisticConfirmations: 1, - }) - require.NoError(t, err) - chainConfig := integrationhelpers.SetupConfigInfo(chainSelector, p2pIDs, f, encodedExtraChainConfig) - inputConfig := []ccip_config.CCIPConfigTypesChainConfigInfo{ - chainConfig, - } - _, err = h.ccipConfig.ApplyChainConfigUpdates(h.owner, nil, inputConfig) - require.NoError(t, err) - h.backend.Commit() - return chainConfig -} - -func (h *homeChain) AddDON( - t *testing.T, - ccipCapabilityID [32]byte, - chainSelector uint64, - uni onchainUniverse, - f uint8, - bootstrapP2PID [32]byte, - p2pIDs [][32]byte, - oracles []confighelper2.OracleIdentityExtra, -) { - // Get OCR3 Config from helper - var schedule []int - for range oracles { - schedule = append(schedule, 1) - } - - tabi, err := ocr3_config_encoder.IOCR3ConfigEncoderMetaData.GetAbi() - require.NoError(t, err) - - // Add DON on capability registry contract - var ocr3Configs []ocr3_config_encoder.CCIPConfigTypesOCR3Config - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - var encodedOffchainConfig []byte - var err2 error - if pluginType == cctypes.PluginTypeCCIPCommit { - encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: *commonconfig.MustNewDuration(RemoteGasPriceBatchWriteFrequency), - // TODO: implement token price writes - // TokenPriceBatchWriteFrequency: *commonconfig.MustNewDuration(tokenPriceBatchWriteFrequency), - }) - require.NoError(t, err2) - } else { - encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: BatchGasLimit, - RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, - MessageVisibilityInterval: *commonconfig.MustNewDuration(FirstBlockAge), - InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry), - RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime), - BatchingStrategyID: BatchingStrategyID, - }) - require.NoError(t, err2) - } - signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsForTests( - DeltaProgress, - DeltaResend, - DeltaInitial, - DeltaRound, - DeltaGrace, - DeltaCertifiedCommitRequest, - DeltaStage, - Rmax, - schedule, - oracles, - encodedOffchainConfig, - MaxDurationQuery, - MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport, - int(f), - []byte{}, // empty OnChainConfig - ) - require.NoError(t, err2, "failed to create contract config") - - signersBytes := make([][]byte, len(signers)) - for i, signer := range signers { - signersBytes[i] = signer - } - - transmittersBytes := make([][]byte, len(transmitters)) - for i, transmitter := range transmitters { - // anotherErr because linting doesn't want to shadow err - parsed, anotherErr := common.ParseHexOrString(string(transmitter)) - require.NoError(t, anotherErr) - transmittersBytes[i] = parsed - } - - ocr3Configs = append(ocr3Configs, ocr3_config_encoder.CCIPConfigTypesOCR3Config{ - PluginType: uint8(pluginType), - ChainSelector: chainSelector, - F: configF, - OffchainConfigVersion: offchainConfigVersion, - OfframpAddress: uni.offramp.Address().Bytes(), - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2pIds: p2pIDs, - Signers: signersBytes, - Transmitters: transmittersBytes, - OffchainConfig: offchainConfig, - }) - } - - encodedCall, err := tabi.Pack("exposeOCR3Config", ocr3Configs) - require.NoError(t, err) - - // Trim first four bytes to remove function selector. - encodedConfigs := encodedCall[4:] - - // commit so that we have an empty block to filter events from - h.backend.Commit() - - _, err = h.capabilityRegistry.AddDON(h.owner, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: ccipCapabilityID, - Config: encodedConfigs, - }, - }, false, false, f) - require.NoError(t, err) - h.backend.Commit() - - endBlock := h.backend.Blockchain().CurrentBlock().Number.Uint64() - iter, err := h.capabilityRegistry.FilterConfigSet(&bind.FilterOpts{ - Start: h.backend.Blockchain().CurrentBlock().Number.Uint64() - 1, - End: &endBlock, - }) - require.NoError(t, err, "failed to filter config set events") - var donID uint32 - for iter.Next() { - donID = iter.Event.DonId - break - } - require.NotZero(t, donID, "failed to get donID from config set event") - - var signerAddresses []common.Address - for _, oracle := range oracles { - signerAddresses = append(signerAddresses, common.BytesToAddress(oracle.OnchainPublicKey)) - } - - var transmitterAddresses []common.Address - for _, oracle := range oracles { - transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(oracle.TransmitAccount))) - } - - // get the config digest from the ccip config contract and set config on the offramp. - var offrampOCR3Configs []evm_2_evm_multi_offramp.MultiOCR3BaseOCRConfigArgs - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err1 := h.ccipConfig.GetOCRConfig(&bind.CallOpts{ - Context: testutils.Context(t), - }, donID, uint8(pluginType)) - require.NoError(t, err1, "failed to get OCR3 config from ccip config contract") - require.Len(t, ocrConfig, 1, "expected exactly one OCR3 config") - offrampOCR3Configs = append(offrampOCR3Configs, evm_2_evm_multi_offramp.MultiOCR3BaseOCRConfigArgs{ - ConfigDigest: ocrConfig[0].ConfigDigest, - OcrPluginType: uint8(pluginType), - F: f, - IsSignatureVerificationEnabled: pluginType == cctypes.PluginTypeCCIPCommit, - Signers: signerAddresses, - Transmitters: transmitterAddresses, - }) - } - - uni.backend.Commit() - - _, err = uni.offramp.SetOCR3Configs(uni.owner, offrampOCR3Configs) - require.NoError(t, err, "failed to set ocr3 configs on offramp") - uni.backend.Commit() - - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err := uni.offramp.LatestConfigDetails(&bind.CallOpts{ - Context: testutils.Context(t), - }, uint8(pluginType)) - require.NoError(t, err, "failed to get latest commit OCR3 config") - require.Equalf(t, offrampOCR3Configs[pluginType].ConfigDigest, ocrConfig.ConfigInfo.ConfigDigest, "%s OCR3 config digest mismatch", pluginType.String()) - require.Equalf(t, offrampOCR3Configs[pluginType].F, ocrConfig.ConfigInfo.F, "%s OCR3 config F mismatch", pluginType.String()) - require.Equalf(t, offrampOCR3Configs[pluginType].IsSignatureVerificationEnabled, ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, "%s OCR3 config signature verification mismatch", pluginType.String()) - if pluginType == cctypes.PluginTypeCCIPCommit { - // only commit will set signers, exec doesn't need them. - require.Equalf(t, offrampOCR3Configs[pluginType].Signers, ocrConfig.Signers, "%s OCR3 config signers mismatch", pluginType.String()) - } - require.Equalf(t, offrampOCR3Configs[pluginType].Transmitters, ocrConfig.Transmitters, "%s OCR3 config transmitters mismatch", pluginType.String()) - } - - t.Logf("set ocr3 config on the offramp, signers: %+v, transmitters: %+v", signerAddresses, transmitterAddresses) -} - -func connectUniverses( - t *testing.T, - universes map[uint64]onchainUniverse, -) { - for _, uni := range universes { - wireRouter(t, uni, universes) - wirePriceRegistry(t, uni, universes) - wireOffRamp(t, uni, universes) - initRemoteChainsGasPrices(t, uni, universes) - } -} - -// setupUniverseBasics sets up the initial configurations for the CCIP contracts on a single chain. -// 1. Mint 1000 LINK to the owner -// 2. Set the price registry with local token prices -// 3. Authorize the onRamp and offRamp on the nonce manager -func setupUniverseBasics(t *testing.T, uni onchainUniverse) { - // ============================================================================= - // Universe specific updates/configs - // These updates are specific to each universe and are set up here - // These updates don't depend on other chains - // ============================================================================= - owner := uni.owner - // ============================================================================= - // Mint 1000 LINK to owner - // ============================================================================= - _, err := uni.linkToken.GrantMintRole(owner, owner.From) - require.NoError(t, err) - _, err = uni.linkToken.Mint(owner, owner.From, e18Mult(1000)) - require.NoError(t, err) - uni.backend.Commit() - - // ============================================================================= - // Price updates for tokens - // These are the prices of the fee tokens of local chain in USD - // ============================================================================= - tokenPriceUpdates := []price_registry.InternalTokenPriceUpdate{ - { - SourceToken: uni.linkToken.Address(), - UsdPerToken: e18Mult(20), - }, - { - SourceToken: uni.weth.Address(), - UsdPerToken: e18Mult(4000), - }, - } - _, err = uni.priceRegistry.UpdatePrices(owner, price_registry.InternalPriceUpdates{ - TokenPriceUpdates: tokenPriceUpdates, - }) - require.NoErrorf(t, err, "failed to update prices in price registry on chain id %d", uni.chainID) - uni.backend.Commit() - - _, err = uni.priceRegistry.ApplyAuthorizedCallerUpdates(owner, price_registry.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{ - uni.offramp.Address(), - }, - }) - require.NoError(t, err, "failed to authorize offramp on price registry") - uni.backend.Commit() - - // ============================================================================= - // Authorize OnRamp & OffRamp on NonceManager - // Otherwise the onramp will not be able to call the nonceManager to get next Nonce - // ============================================================================= - authorizedCallersAuthorizedCallerArgs := nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{ - uni.onramp.Address(), - uni.offramp.Address(), - }, - } - _, err = uni.nonceManager.ApplyAuthorizedCallerUpdates(owner, authorizedCallersAuthorizedCallerArgs) - require.NoError(t, err) - uni.backend.Commit() -} - -// As we can't change router contract. The contract was expecting onRamp and offRamp per lane and not per chain -// In the new architecture we have only one onRamp and one offRamp per chain. -// hence we add the mapping for all remote chains to the onRamp/offRamp contract of the local chain -func wireRouter(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var ( - routerOnrampUpdates []router.RouterOnRamp - routerOfframpUpdates []router.RouterOffRamp - ) - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - routerOnrampUpdates = append(routerOnrampUpdates, router.RouterOnRamp{ - DestChainSelector: getSelector(remoteChainID), - OnRamp: uni.onramp.Address(), - }) - routerOfframpUpdates = append(routerOfframpUpdates, router.RouterOffRamp{ - SourceChainSelector: getSelector(remoteChainID), - OffRamp: uni.offramp.Address(), - }) - } - _, err := uni.router.ApplyRampUpdates(owner, routerOnrampUpdates, []router.RouterOffRamp{}, routerOfframpUpdates) - require.NoErrorf(t, err, "failed to apply ramp updates on router on chain id %d", uni.chainID) - uni.backend.Commit() -} - -// Setting OnRampDestChainConfigs -func wirePriceRegistry(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var priceRegistryDestChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - priceRegistryDestChainConfigArgs = append(priceRegistryDestChainConfigArgs, price_registry.PriceRegistryDestChainConfigArgs{ - DestChainSelector: getSelector(remoteChainID), - DestChainConfig: defaultPriceRegistryDestChainConfig(t), - }) - } - _, err := uni.priceRegistry.ApplyDestChainConfigUpdates(owner, priceRegistryDestChainConfigArgs) - require.NoErrorf(t, err, "failed to apply dest chain config updates on price registry on chain id %d", uni.chainID) - uni.backend.Commit() -} - -// Setting OffRampSourceChainConfigs -func wireOffRamp(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var offrampSourceChainConfigArgs []evm_2_evm_multi_offramp.EVM2EVMMultiOffRampSourceChainConfigArgs - for remoteChainID, remoteUniverse := range universes { - if remoteChainID == uni.chainID { - continue - } - offrampSourceChainConfigArgs = append(offrampSourceChainConfigArgs, evm_2_evm_multi_offramp.EVM2EVMMultiOffRampSourceChainConfigArgs{ - SourceChainSelector: getSelector(remoteChainID), // for each destination chain, add a source chain config - IsEnabled: true, - OnRamp: remoteUniverse.onramp.Address().Bytes(), - }) - } - _, err := uni.offramp.ApplySourceChainConfigUpdates(owner, offrampSourceChainConfigArgs) - require.NoErrorf(t, err, "failed to apply source chain config updates on offramp on chain id %d", uni.chainID) - uni.backend.Commit() - for remoteChainID, remoteUniverse := range universes { - if remoteChainID == uni.chainID { - continue - } - sourceCfg, err2 := uni.offramp.GetSourceChainConfig(&bind.CallOpts{}, getSelector(remoteChainID)) - require.NoError(t, err2) - require.True(t, sourceCfg.IsEnabled, "source chain config should be enabled") - require.Equal(t, remoteUniverse.onramp.Address(), common.BytesToAddress(sourceCfg.OnRamp), "source chain config onRamp address mismatch") - } -} - -func getSelector(chainID uint64) uint64 { - selector, err := chainsel.SelectorFromChainId(chainID) - if err != nil { - panic(err) - } - return selector -} - -// initRemoteChainsGasPrices sets the gas prices for all chains except the local chain in the local price registry -func initRemoteChainsGasPrices(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - var gasPriceUpdates []price_registry.InternalGasPriceUpdate - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - gasPriceUpdates = append(gasPriceUpdates, - price_registry.InternalGasPriceUpdate{ - DestChainSelector: getSelector(remoteChainID), - UsdPerUnitGas: big.NewInt(2e12), - }, - ) - } - _, err := uni.priceRegistry.UpdatePrices(uni.owner, price_registry.InternalPriceUpdates{ - GasPriceUpdates: gasPriceUpdates, - }) - require.NoError(t, err) -} - -func defaultPriceRegistryDestChainConfig(t *testing.T) price_registry.PriceRegistryDestChainConfig { - // 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, err := hex.DecodeString("2812d52c") - require.NoError(t, err) - return price_registry.PriceRegistryDestChainConfig{ - IsEnabled: true, - MaxNumberOfTokensPerMsg: 10, - MaxDataBytes: 256, - MaxPerMsgGasLimit: 3_000_000, - DestGasOverhead: 50_000, - DefaultTokenFeeUSDCents: 1, - DestGasPerPayloadByte: 10, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 100, - DestDataAvailabilityMultiplierBps: 1, - DefaultTokenDestGasOverhead: 125_000, - DefaultTokenDestBytesOverhead: 32, - DefaultTxGasLimit: 200_000, - GasMultiplierWeiPerEth: 1, - NetworkFeeUSDCents: 1, - ChainFamilySelector: [4]byte(evmFamilySelector), - } -} - -func deployLinkToken(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *link_token.LinkToken { - linkAddr, _, _, err := link_token.DeployLinkToken(owner, backend) - require.NoErrorf(t, err, "failed to deploy link token on chain id %d", chainID) - backend.Commit() - linkToken, err := link_token.NewLinkToken(linkAddr, backend) - require.NoError(t, err) - return linkToken -} - -func deployMockARMContract(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *mock_arm_contract.MockARMContract { - rmnAddr, _, _, err := mock_arm_contract.DeployMockARMContract(owner, backend) - require.NoErrorf(t, err, "failed to deploy mock arm on chain id %d", chainID) - backend.Commit() - rmn, err := mock_arm_contract.NewMockARMContract(rmnAddr, backend) - require.NoError(t, err) - return rmn -} - -func deployARMProxyContract(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, rmnAddr common.Address, chainID uint64) *arm_proxy_contract.ARMProxyContract { - rmnProxyAddr, _, _, err := arm_proxy_contract.DeployARMProxyContract(owner, backend, rmnAddr) - require.NoErrorf(t, err, "failed to deploy arm proxy on chain id %d", chainID) - backend.Commit() - rmnProxy, err := arm_proxy_contract.NewARMProxyContract(rmnProxyAddr, backend) - require.NoError(t, err) - return rmnProxy -} - -func deployWETHContract(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *weth9.WETH9 { - wethAddr, _, _, err := weth9.DeployWETH9(owner, backend) - require.NoErrorf(t, err, "failed to deploy weth contract on chain id %d", chainID) - backend.Commit() - weth, err := weth9.NewWETH9(wethAddr, backend) - require.NoError(t, err) - return weth -} - -func deployRouter(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, wethAddr, rmnProxyAddr common.Address, chainID uint64) *router.Router { - routerAddr, _, _, err := router.DeployRouter(owner, backend, wethAddr, rmnProxyAddr) - require.NoErrorf(t, err, "failed to deploy router on chain id %d", chainID) - backend.Commit() - rout, err := router.NewRouter(routerAddr, backend) - require.NoError(t, err) - return rout -} - -func deployPriceRegistry( - t *testing.T, - owner *bind.TransactOpts, - backend *backends.SimulatedBackend, - linkAddr, - wethAddr common.Address, - maxFeeJuelsPerMsg *big.Int, - chainID uint64, -) *price_registry.PriceRegistry { - priceRegistryAddr, _, _, err := price_registry.DeployPriceRegistry( - owner, - backend, - price_registry.PriceRegistryStaticConfig{ - MaxFeeJuelsPerMsg: maxFeeJuelsPerMsg, - LinkToken: linkAddr, - StalenessThreshold: 24 * 60 * 60, // 24 hours - }, - []common.Address{ - owner.From, // owner can update prices in this test - }, // price updaters, will be set to offramp later - []common.Address{linkAddr, wethAddr}, // fee tokens - // empty for now, need to fill in when testing token transfers - []price_registry.PriceRegistryTokenPriceFeedUpdate{}, - // empty for now, need to fill in when testing token transfers - []price_registry.PriceRegistryTokenTransferFeeConfigArgs{}, - []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs{ - { - PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH - Token: linkAddr, - }, - { - PremiumMultiplierWeiPerEth: 1e18, - Token: wethAddr, - }, - }, - // Destination chain configs will be set up later once we have all chains - []price_registry.PriceRegistryDestChainConfigArgs{}, - ) - require.NoErrorf(t, err, "failed to deploy price registry on chain id %d", chainID) - backend.Commit() - priceRegistry, err := price_registry.NewPriceRegistry(priceRegistryAddr, backend) - require.NoError(t, err) - return priceRegistry -} - -func deployTokenAdminRegistry(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *token_admin_registry.TokenAdminRegistry { - tarAddr, _, _, err := token_admin_registry.DeployTokenAdminRegistry(owner, backend) - require.NoErrorf(t, err, "failed to deploy token admin registry on chain id %d", chainID) - backend.Commit() - tokenAdminRegistry, err := token_admin_registry.NewTokenAdminRegistry(tarAddr, backend) - require.NoError(t, err) - return tokenAdminRegistry -} - -func deployNonceManager(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *nonce_manager.NonceManager { - nonceManagerAddr, _, _, err := nonce_manager.DeployNonceManager(owner, backend, []common.Address{owner.From}) - require.NoErrorf(t, err, "failed to deploy nonce_manager on chain id %d", chainID) - backend.Commit() - nonceManager, err := nonce_manager.NewNonceManager(nonceManagerAddr, backend) - require.NoError(t, err) - return nonceManager -} diff --git a/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go b/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go index c78fd37b809..8c8e4f05c38 100644 --- a/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go @@ -1,29 +1,28 @@ package ccip_integration_tests import ( + "math/big" "testing" "time" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" - mapset "github.com/deckarep/golang-set/v2" - "github.com/onsi/gomega" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" libocrtypes "github.com/smartcontractkit/libocr/ragep2p/types" "github.com/smartcontractkit/chainlink-ccip/chainconfig" ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/stretchr/testify/require" - capcfg "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) -func TestHomeChainReader(t *testing.T) { +func TestHomeChainReader_ChainConfigs(t *testing.T) { ctx := testutils.Context(t) lggr := logger.TestLogger(t) uni := integrationhelpers.NewTestUniverse(ctx, t, lggr) @@ -35,36 +34,34 @@ func TestHomeChainReader(t *testing.T) { } p2pIDs := integrationhelpers.P2pIDsFromInts(arr) uni.AddCapability(p2pIDs) + //==============================Apply configs to Capability Contract================================= encodedChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ GasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1000), DAGasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1_000_000), - FinalityDepth: -1, OptimisticConfirmations: 1, }) require.NoError(t, err) - chainAConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainA, p2pIDs, integrationhelpers.FChainA, encodedChainConfig) - chainBConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainB, p2pIDs[1:], integrationhelpers.FChainB, encodedChainConfig) - chainCConf := integrationhelpers.SetupConfigInfo(integrationhelpers.ChainC, p2pIDs[2:], integrationhelpers.FChainC, encodedChainConfig) - inputConfig := []capcfg.CCIPConfigTypesChainConfigInfo{ - chainAConf, - chainBConf, - chainCConf, + inputConfig := []ccip_home.CCIPHomeChainConfigArgs{ + integrationhelpers.SetupConfigInfo(integrationhelpers.ChainA, p2pIDs, integrationhelpers.FChainA, encodedChainConfig), + integrationhelpers.SetupConfigInfo(integrationhelpers.ChainB, p2pIDs[1:], integrationhelpers.FChainB, encodedChainConfig), + integrationhelpers.SetupConfigInfo(integrationhelpers.ChainC, p2pIDs[2:], integrationhelpers.FChainC, encodedChainConfig), } - _, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig) + _, err = uni.CCIPHome.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig) require.NoError(t, err) uni.Backend.Commit() - //================================Setup HomeChainReader=============================== - - pollDuration := time.Second - homeChain := uni.HomeChainReader + chainConfigInfos, err := uni.CCIPHome.GetAllChainConfigs(nil, big.NewInt(0), big.NewInt(100)) + require.NoError(t, err) + require.Len(t, chainConfigInfos, len(inputConfig)) - gomega.NewWithT(t).Eventually(func() bool { - configs, _ := homeChain.GetAllChainConfigs() - return configs != nil - }, testutils.WaitTimeout(t), pollDuration*5).Should(gomega.BeTrue()) + // Wait for the home chain reader to read the expected amount of chain configs. + require.Eventually(t, func() bool { + configs, _ := uni.HomeChainReader.GetAllChainConfigs() + return len(configs) == len(inputConfig) + }, testutils.WaitTimeout(t), 1*time.Second) t.Logf("homchain reader is ready") + //================================Test HomeChain Reader=============================== expectedChainConfigs := map[cciptypes.ChainSelector]ccipreader.ChainConfig{} for _, c := range inputConfig { @@ -74,16 +71,26 @@ func TestHomeChainReader(t *testing.T) { Config: mustDecodeChainConfig(t, c.ChainConfig.Config), } } - configs, err := homeChain.GetAllChainConfigs() + + configs, err := uni.HomeChainReader.GetAllChainConfigs() require.NoError(t, err) + require.Equal(t, expectedChainConfigs, configs) - //=================================Remove ChainC from OnChainConfig========================================= - _, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, []uint64{integrationhelpers.ChainC}, nil) + + // Remove chain C from the chain configs and expect the home chain reader to + // update its state accordingly. + _, err = uni.CCIPHome.ApplyChainConfigUpdates(uni.Transactor, []uint64{integrationhelpers.ChainC}, nil) require.NoError(t, err) uni.Backend.Commit() - time.Sleep(pollDuration * 5) // Wait for the chain reader to update - configs, err = homeChain.GetAllChainConfigs() + + // Wait for the home chain reader to read the expected amount of chain configs. + require.Eventually(t, func() bool { + chainConfigs, _ := uni.HomeChainReader.GetAllChainConfigs() + return len(chainConfigs) == len(inputConfig)-1 + }, testutils.WaitTimeout(t), 1*time.Second) + configs, err = uni.HomeChainReader.GetAllChainConfigs() require.NoError(t, err) + delete(expectedChainConfigs, cciptypes.ChainSelector(integrationhelpers.ChainC)) require.Equal(t, expectedChainConfigs, configs) } 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 7520b126336..fc31471c149 100644 --- a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go +++ b/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go @@ -2,6 +2,8 @@ package integrationhelpers import ( "context" + "crypto/ed25519" + "encoding/hex" "encoding/json" "fmt" "math/big" @@ -9,38 +11,40 @@ import ( "testing" "time" - configsevm "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + mapset "github.com/deckarep/golang-set/v2" "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/core" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-ccip/pkg/consts" ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ocr3_config_encoder" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/stretchr/testify/require" - + configsevm "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "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/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) const chainID = 1337 +var CapabilityID = fmt.Sprintf("%s@%s", CcipCapabilityLabelledName, CcipCapabilityVersion) + func NewReader( t *testing.T, logPoller logpoller.LogPoller, @@ -82,18 +86,17 @@ const ( CcipCapabilityVersion = "v1.0" ) -var CapabilityID = fmt.Sprintf("%s@%s", CcipCapabilityLabelledName, CcipCapabilityVersion) - type TestUniverse struct { - Transactor *bind.TransactOpts - Backend *backends.SimulatedBackend - CapReg *kcr.CapabilitiesRegistry - CcipCfg *ccip_config.CCIPConfig - TestingT *testing.T - LogPoller logpoller.LogPoller - HeadTracker logpoller.HeadTracker - SimClient client.Client - HomeChainReader ccipreader.HomeChain + Transactor *bind.TransactOpts + Backend *backends.SimulatedBackend + CapReg *kcr.CapabilitiesRegistry + CCIPHome *ccip_home.CCIPHome + TestingT *testing.T + LogPoller logpoller.LogPoller + HeadTracker logpoller.HeadTracker + SimClient client.Client + HomeChainReader ccipreader.HomeChain + HomeContractReader types.ContractReader } func NewTestUniverse(ctx context.Context, t *testing.T, lggr logger.Logger) TestUniverse { @@ -109,11 +112,11 @@ func NewTestUniverse(ctx context.Context, t *testing.T, lggr logger.Logger) Test capReg, err := kcr.NewCapabilitiesRegistry(crAddress, backend) require.NoError(t, err) - ccAddress, _, _, err := ccip_config.DeployCCIPConfig(transactor, backend, crAddress) + ccAddress, _, _, err := ccip_home.DeployCCIPHome(transactor, backend, crAddress) require.NoError(t, err) backend.Commit() - cc, err := ccip_config.NewCCIPConfig(ccAddress, backend) + cc, err := ccip_home.NewCCIPHome(ccAddress, backend) require.NoError(t, err) db := pgtest.NewSqlxDB(t) @@ -133,17 +136,19 @@ func NewTestUniverse(ctx context.Context, t *testing.T, lggr logger.Logger) Test require.NoError(t, lp.Start(ctx)) t.Cleanup(func() { require.NoError(t, lp.Close()) }) - hcr := NewHomeChainReader(t, lp, headTracker, cl, ccAddress) + cr := NewReader(t, lp, headTracker, cl, ccAddress, configsevm.HomeChainReaderConfigRaw) + hcr := NewHomeChainReader(t, cr, ccAddress) return TestUniverse{ - Transactor: transactor, - Backend: backend, - CapReg: capReg, - CcipCfg: cc, - TestingT: t, - SimClient: cl, - LogPoller: lp, - HeadTracker: headTracker, - HomeChainReader: hcr, + Transactor: transactor, + Backend: backend, + CapReg: capReg, + CCIPHome: cc, + TestingT: t, + SimClient: cl, + LogPoller: lp, + HeadTracker: headTracker, + HomeChainReader: hcr, + HomeContractReader: cr, } } @@ -180,7 +185,7 @@ func (t *TestUniverse) AddCapability(p2pIDs [][32]byte) { Version: CcipCapabilityVersion, CapabilityType: 0, ResponseType: 0, - ConfigurationContract: t.CcipCfg.Address(), + ConfigurationContract: t.CCIPHome.Address(), }, }) require.NoError(t.TestingT, err, "failed to add capability to registry") @@ -216,6 +221,7 @@ func (t *TestUniverse) AddCapability(p2pIDs [][32]byte) { NodeOperatorId: nodeOperatorID, Signer: testutils.Random32Byte(), P2pId: p2pIDs[i], + EncryptionPublicKey: testutils.Random32Byte(), HashedCapabilityIds: [][32]byte{ccipCapabilityID}, }, }) @@ -231,10 +237,11 @@ func (t *TestUniverse) AddCapability(p2pIDs [][32]byte) { } } -func NewHomeChainReader(t *testing.T, logPoller logpoller.LogPoller, headTracker logpoller.HeadTracker, client client.Client, ccAddress common.Address) ccipreader.HomeChain { - cr := NewReader(t, logPoller, headTracker, client, ccAddress, configsevm.HomeChainReaderConfigRaw()) - - hcr := ccipreader.NewHomeChainReader(cr, logger.TestLogger(t), 500*time.Millisecond) +func NewHomeChainReader(t *testing.T, cr types.ContractReader, ccAddress common.Address) ccipreader.HomeChain { + hcr := ccipreader.NewHomeChainReader(cr, logger.TestLogger(t), 50*time.Millisecond, types.BoundContract{ + Address: ccAddress.String(), + Name: consts.ContractNameCCIPConfig, + }) require.NoError(t, hcr.Start(testutils.Context(t))) t.Cleanup(func() { require.NoError(t, hcr.Close()) }) @@ -245,60 +252,186 @@ func (t *TestUniverse) AddDONToRegistry( ccipCapabilityID [32]byte, chainSelector uint64, f uint8, - bootstrapP2PID [32]byte, p2pIDs [][32]byte, ) { - tabi, err := ocr3_config_encoder.IOCR3ConfigEncoderMetaData.GetAbi() + tabi, err := ccip_home.CCIPHomeMetaData.GetAbi() require.NoError(t.TestingT, err) - var ( - signers [][]byte - transmitters [][]byte - ) - for range p2pIDs { - signers = append(signers, testutils.NewAddress().Bytes()) - transmitters = append(transmitters, testutils.NewAddress().Bytes()) + var nodes []ccip_home.CCIPHomeOCR3Node + + for i := range p2pIDs { + nodes = append(nodes, ccip_home.CCIPHomeOCR3Node{ + P2pId: p2pIDs[i], + SignerKey: testutils.NewAddress().Bytes(), + TransmitterKey: testutils.NewAddress().Bytes(), + }) + } + + // find the max don id, the next DON id will be max + 1. + iter, err := t.CapReg.FilterConfigSet(nil, nil) + require.NoError(t.TestingT, err) + var maxDonID uint32 + for iter.Next() { + if iter.Event.DonId > maxDonID { + maxDonID = iter.Event.DonId + } } - var ocr3Configs []ocr3_config_encoder.CCIPConfigTypesOCR3Config + donID := maxDonID + 1 + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocr3Configs = append(ocr3Configs, ocr3_config_encoder.CCIPConfigTypesOCR3Config{ + ocr3Config := ccip_home.CCIPHomeOCR3Config{ PluginType: uint8(pluginType), ChainSelector: chainSelector, - F: f, + FRoleDON: f, OffchainConfigVersion: 30, OfframpAddress: testutils.NewAddress().Bytes(), - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2pIds: p2pIDs, - Signers: signers, - Transmitters: transmitters, + RmnHomeAddress: testutils.NewAddress().Bytes(), + Nodes: nodes, OffchainConfig: []byte("offchain config"), - }) - } + } + encodedSetCandidateCall, err := tabi.Pack( + "setCandidate", + donID, + ocr3Config.PluginType, + ocr3Config, + [32]byte{}, + ) + require.NoError(t.TestingT, err) + // Create DON should be called only once, any subsequent calls should be updating DON + if pluginType == cctypes.PluginTypeCCIPCommit { + _, err = t.CapReg.AddDON( + t.Transactor, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: ccipCapabilityID, + Config: encodedSetCandidateCall, + }, + }, + false, + false, + f, + ) + } else { + _, err = t.CapReg.UpdateDON( + t.Transactor, donID, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: ccipCapabilityID, + Config: encodedSetCandidateCall, + }, + }, + false, + f, + ) + } - encodedCall, err := tabi.Pack("exposeOCR3Config", ocr3Configs) - require.NoError(t.TestingT, err) + require.NoError(t.TestingT, err) + t.Backend.Commit() - // Trim first four bytes to remove function selector. - encodedConfigs := encodedCall[4:] + configs, err := t.CCIPHome.GetAllConfigs(nil, donID, uint8(pluginType)) + require.NoError(t.TestingT, err) + require.Equal(t.TestingT, ocr3Config, configs.CandidateConfig.Config) - _, err = t.CapReg.AddDON(t.Transactor, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: ccipCapabilityID, - Config: encodedConfigs, - }, - }, false, false, f) - require.NoError(t.TestingT, err) - t.Backend.Commit() + // get the config digest of the candidate + candidateDigest, err := t.CCIPHome.GetCandidateDigest(nil, donID, ocr3Config.PluginType) + require.NoError(t.TestingT, err) + encodedPromotionCall, err := tabi.Pack( + "promoteCandidateAndRevokeActive", + donID, + ocr3Config.PluginType, + candidateDigest, + [32]byte{}, + ) + require.NoError(t.TestingT, err) + + _, err = t.CapReg.UpdateDON( + t.Transactor, donID, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: ccipCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + f, + ) + + require.NoError(t.TestingT, err) + t.Backend.Commit() + + configs, err = t.CCIPHome.GetAllConfigs(nil, donID, uint8(pluginType)) + require.NoError(t.TestingT, err) + require.Equal(t.TestingT, ocr3Config, configs.ActiveConfig.Config) + } } -func SetupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_config.CCIPConfigTypesChainConfigInfo { - return ccip_config.CCIPConfigTypesChainConfigInfo{ +func SetupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_home.CCIPHomeChainConfigArgs { + return ccip_home.CCIPHomeChainConfigArgs{ ChainSelector: chainSelector, - ChainConfig: ccip_config.CCIPConfigTypesChainConfig{ + ChainConfig: ccip_home.CCIPHomeChainConfig{ Readers: readers, FChain: fChain, Config: cfg, }, } } + +func GenerateRMNHomeConfigs( + peerID string, + offchainPK string, + offchainCfg string, + chainSelector uint64, + minObservers uint64, + observerBitmap *big.Int) (rmn_home.RMNHomeStaticConfig, rmn_home.RMNHomeDynamicConfig, error) { + peerIDByte, _ := hex.DecodeString(peerID) + var peerIDBytes [32]byte + copy(peerIDBytes[:], peerIDByte) + + offchainPublicKey, err := hex.DecodeString(offchainPK) + + if err != nil { + return rmn_home.RMNHomeStaticConfig{}, rmn_home.RMNHomeDynamicConfig{}, fmt.Errorf("error decoding offchain public key: %w", err) + } + + var offchainPublicKeyBytes [32]byte + copy(offchainPublicKeyBytes[:], offchainPublicKey) + + staticConfig := rmn_home.RMNHomeStaticConfig{ + Nodes: []rmn_home.RMNHomeNode{ + { + PeerId: peerIDBytes, + OffchainPublicKey: offchainPublicKeyBytes, + }, + }, + OffchainConfig: []byte(offchainCfg), + } + + dynamicConfig := rmn_home.RMNHomeDynamicConfig{ + SourceChains: []rmn_home.RMNHomeSourceChain{ + { + ChainSelector: chainSelector, + MinObservers: minObservers, + ObserverNodesBitmap: observerBitmap, + }, + }, + OffchainConfig: []byte(offchainCfg), + } + return staticConfig, dynamicConfig, nil +} + +func GenerateExpectedRMNHomeNodesInfo(staticConfig rmn_home.RMNHomeStaticConfig, chainID int) []ccipreader.HomeNodeInfo { + expectedCandidateNodesInfo := make([]ccipreader.HomeNodeInfo, 0) + + supportedCandidateSourceChains := mapset.NewSet(ccipocr3.ChainSelector(chainID)) + + var counter uint32 + for _, n := range staticConfig.Nodes { + pk := ed25519.PublicKey(n.OffchainPublicKey[:]) + expectedCandidateNodesInfo = append(expectedCandidateNodesInfo, ccipreader.HomeNodeInfo{ + ID: ccipreader.NodeID(counter), + PeerID: n.PeerId, + SupportedSourceChains: supportedCandidateSourceChains, + OffchainPublicKey: &pk, + }) + counter++ + } + return expectedCandidateNodesInfo +} diff --git a/core/capabilities/ccip/ccip_integration_tests/ocr3_node_test.go b/core/capabilities/ccip/ccip_integration_tests/ocr3_node_test.go deleted file mode 100644 index 8cafb901724..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/ocr3_node_test.go +++ /dev/null @@ -1,281 +0,0 @@ -package ccip_integration_tests - -import ( - "fmt" - "math/big" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/hashicorp/consul/sdk/freeport" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" - "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/p2pkey" - - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/stretchr/testify/require" -) - -const STATE_SUCCESS = uint8(2) - -/* -* If you want to debug, set log level to info and use the following commands for easier logs filtering. -* -* // Run the test and redirect logs to logs.txt -* go test -v -run "^TestIntegration_OCR3Nodes" ./core/capabilities/ccip/ccip_integration_tests 2>&1 > logs.txt -* -* // Reads logs.txt as a stream and apply filters using grep -* tail -fn0 logs.txt | grep "CCIPExecPlugin" - */ -func TestIntegration_OCR3Nodes(t *testing.T) { - const ( - numChains = 3 // number of chains that this test will run on - numNodes = 4 // number of OCR3 nodes, test assumes that every node supports every chain - - simulatedBackendBlockTime = 900 * time.Millisecond // Simulated backend blocks committing interval - oraclesBootWaitTime = 30 * time.Second // Time to wait for oracles to come up (HACK) - fChain = 1 // fChain value for all the chains - oracleLogLevel = zapcore.InfoLevel // Log level for the oracle / plugins. - ) - - t.Logf("creating %d universes", numChains) - homeChainUni, universes := createUniverses(t, numChains) - - var ( - oracles = make(map[uint64][]confighelper2.OracleIdentityExtra) - apps []chainlink.Application - nodes []*ocr3Node - p2pIDs [][32]byte - - // The bootstrap node will be: nodes[0] - bootstrapPort int - bootstrapP2PID p2pkey.PeerID - ) - - ports := freeport.GetN(t, numNodes) - ctx := testutils.Context(t) - callCtx := &bind.CallOpts{Context: ctx} - - for i := 0; i < numNodes; i++ { - t.Logf("Setting up ocr3 node:%d at port:%d", i, ports[i]) - node := setupNodeOCR3(t, ports[i], universes, homeChainUni, oracleLogLevel) - - for chainID, transmitter := range node.transmitters { - identity := confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: node.keybundle.PublicKey(), // Different for each chain - TransmitAccount: ocrtypes.Account(transmitter.Hex()), - OffchainPublicKey: node.keybundle.OffchainPublicKey(), // Same for each family - PeerID: node.peerID, - }, - ConfigEncryptionPublicKey: node.keybundle.ConfigEncryptionPublicKey(), // Different for each chain - } - oracles[chainID] = append(oracles[chainID], identity) - } - - apps = append(apps, node.app) - nodes = append(nodes, node) - - peerID, err := p2pkey.MakePeerID(node.peerID) - require.NoError(t, err) - p2pIDs = append(p2pIDs, peerID) - } - - bootstrapPort = ports[0] - bootstrapP2PID = p2pIDs[0] - bootstrapAddr := fmt.Sprintf("127.0.0.1:%d", bootstrapPort) - t.Logf("[bootstrap node] peerID:%s p2pID:%d address:%s", nodes[0].peerID, bootstrapP2PID, bootstrapAddr) - - // Start committing periodically in the background for all the chains - tick := time.NewTicker(simulatedBackendBlockTime) - defer tick.Stop() - commitBlocksBackground(t, universes, tick) - - ccipCapabilityID, err := homeChainUni.capabilityRegistry.GetHashedCapabilityId( - callCtx, CapabilityLabelledName, CapabilityVersion) - require.NoError(t, err, "failed to get hashed capability id for ccip") - require.NotEqual(t, [32]byte{}, ccipCapabilityID, "ccip capability id is empty") - - // Need to Add nodes and assign capabilities to them before creating DONS - homeChainUni.AddNodes(t, p2pIDs, [][32]byte{ccipCapabilityID}) - - for _, uni := range universes { - t.Logf("Adding chainconfig for chain %d", uni.chainID) - AddChainConfig(t, homeChainUni, getSelector(uni.chainID), p2pIDs, fChain) - } - - cfgs, err := homeChainUni.ccipConfig.GetAllChainConfigs(callCtx) - require.NoError(t, err) - require.Len(t, cfgs, numChains) - - // Create a DON for each chain - for _, uni := range universes { - // Add nodes and give them the capability - t.Log("Adding DON for universe: ", uni.chainID) - chainSelector := getSelector(uni.chainID) - homeChainUni.AddDON( - t, - ccipCapabilityID, - chainSelector, - uni, - fChain, - bootstrapP2PID, - p2pIDs, - oracles[uni.chainID], - ) - } - - t.Log("Creating ocr3 jobs, starting oracles") - for i := 0; i < len(nodes); i++ { - err1 := nodes[i].app.Start(ctx) - require.NoError(t, err1) - tApp := apps[i] - t.Cleanup(func() { require.NoError(t, tApp.Stop()) }) - - jb := mustGetJobSpec(t, bootstrapP2PID, bootstrapPort, nodes[i].peerID, nodes[i].keybundle.ID()) - require.NoErrorf(t, tApp.AddJobV2(ctx, &jb), "Wasn't able to create ccip job for node %d", i) - } - - t.Logf("Sending ccip requests from each chain to all other chains") - for _, uni := range universes { - requests := genRequestData(uni.chainID, universes) - uni.SendCCIPRequests(t, requests) - } - - // Wait for the oracles to come up. - // TODO: We need some data driven way to do this e.g. wait until LP filters to be registered. - time.Sleep(oraclesBootWaitTime) - - // Replay the log poller on all the chains so that the logs are in the db. - // otherwise the plugins won't pick them up. - for _, node := range nodes { - for chainID := range universes { - t.Logf("Replaying logs for chain %d from block %d", chainID, 1) - require.NoError(t, node.app.ReplayFromBlock(big.NewInt(int64(chainID)), 1, false), "failed to replay logs") - } - } - - // with only one request sent from each chain to each other chain, - // and with sequence numbers on incrementing by 1 on a per-dest chain - // basis, we expect the min sequence number to be 1 on all chains. - expectedSeqNrRange := ccipocr3.NewSeqNumRange(1, 1) - var wg sync.WaitGroup - for _, uni := range universes { - for remoteSelector := range universes { - if remoteSelector == uni.chainID { - continue - } - wg.Add(1) - go func(uni onchainUniverse, remoteSelector uint64) { - defer wg.Done() - waitForCommitWithInterval(t, uni, getSelector(remoteSelector), expectedSeqNrRange) - }(uni, remoteSelector) - } - } - - start := time.Now() - wg.Wait() - t.Logf("All chains received the expected commit report in %s", time.Since(start)) - - // with only one request sent from each chain to each other chain, - // all ExecutionStateChanged events should have the sequence number 1. - expectedSeqNr := uint64(1) - for _, uni := range universes { - for remoteSelector := range universes { - if remoteSelector == uni.chainID { - continue - } - wg.Add(1) - go func(uni onchainUniverse, remoteSelector uint64) { - defer wg.Done() - waitForExecWithSeqNr(t, uni, getSelector(remoteSelector), expectedSeqNr) - }(uni, remoteSelector) - } - } - - start = time.Now() - wg.Wait() - t.Logf("All chains received the expected ExecutionStateChanged event in %s", time.Since(start)) -} - -func genRequestData(chainID uint64, universes map[uint64]onchainUniverse) []requestData { - var res []requestData - for destChainID, destUni := range universes { - if destChainID == chainID { - continue - } - res = append(res, requestData{ - destChainSelector: getSelector(destChainID), - receiverAddress: destUni.receiver.Address(), - data: []byte(fmt.Sprintf("msg from chain %d to chain %d", chainID, destChainID)), - }) - } - return res -} - -func waitForCommitWithInterval( - t *testing.T, - uni onchainUniverse, - expectedSourceChainSelector uint64, - expectedSeqNumRange ccipocr3.SeqNumRange, -) { - sink := make(chan *evm_2_evm_multi_offramp.EVM2EVMMultiOffRampCommitReportAccepted) - subscription, err := uni.offramp.WatchCommitReportAccepted(&bind.WatchOpts{ - Context: testutils.Context(t), - }, sink) - require.NoError(t, err) - - for { - select { - case <-time.After(10 * time.Second): - t.Logf("Waiting for commit report on chain id %d (selector %d) from source selector %d expected seq nr range %s", - uni.chainID, getSelector(uni.chainID), expectedSourceChainSelector, expectedSeqNumRange.String()) - case subErr := <-subscription.Err(): - t.Fatalf("Subscription error: %+v", subErr) - case report := <-sink: - if len(report.Report.MerkleRoots) > 0 { - // Check the interval of sequence numbers and make sure it matches - // the expected range. - for _, mr := range report.Report.MerkleRoots { - if mr.SourceChainSelector == expectedSourceChainSelector && - uint64(expectedSeqNumRange.Start()) == mr.Interval.Min && - uint64(expectedSeqNumRange.End()) == mr.Interval.Max { - t.Logf("Received commit report on chain id %d (selector %d) from source selector %d expected seq nr range %s", - uni.chainID, getSelector(uni.chainID), expectedSourceChainSelector, expectedSeqNumRange.String()) - return - } - } - } - } - } -} - -func waitForExecWithSeqNr(t *testing.T, uni onchainUniverse, expectedSourceChainSelector, expectedSeqNr uint64) { - for { - scc, err := uni.offramp.GetSourceChainConfig(nil, expectedSourceChainSelector) - require.NoError(t, err) - t.Logf("Waiting for ExecutionStateChanged on chain %d (selector %d) from chain %d with expected sequence number %d, current onchain minSeqNr: %d", - uni.chainID, getSelector(uni.chainID), expectedSourceChainSelector, expectedSeqNr, scc.MinSeqNr) - iter, err := uni.offramp.FilterExecutionStateChanged(nil, []uint64{expectedSourceChainSelector}, []uint64{expectedSeqNr}, nil) - require.NoError(t, err) - var count int - for iter.Next() { - if iter.Event.SequenceNumber == expectedSeqNr && iter.Event.SourceChainSelector == expectedSourceChainSelector { - count++ - } - } - if count == 1 { - t.Logf("Received ExecutionStateChanged on chain %d (selector %d) from chain %d with expected sequence number %d", - uni.chainID, getSelector(uni.chainID), expectedSourceChainSelector, expectedSeqNr) - return - } - time.Sleep(5 * time.Second) - } -} diff --git a/core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go b/core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go deleted file mode 100644 index 8a65ff5167d..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package ccip_integration_tests - -import ( - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - gethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/stretchr/testify/require" - - "golang.org/x/exp/maps" - - pp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ping_pong_demo" -) - -/* -* Test is setting up 3 chains (let's call them A, B, C), each chain deploys and starts 2 ping pong contracts for the other 2. -* A ---deploy+start---> (pingPongB, pingPongC) -* B ---deploy+start---> (pingPongA, pingPongC) -* C ---deploy+start---> (pingPongA, pingPongB) -* and then checks that each ping pong contract emitted `CCIPSendRequested` event from the expected source to destination. -* Test fails if any wiring between contracts is not correct. - */ -func TestPingPong(t *testing.T) { - _, universes := createUniverses(t, 3) - pingPongs := initializePingPongContracts(t, universes) - for chainID, universe := range universes { - for otherChain, pingPong := range pingPongs[chainID] { - t.Log("PingPong From: ", chainID, " To: ", otherChain) - _, err := pingPong.StartPingPong(universe.owner) - require.NoError(t, err) - universe.backend.Commit() - - logIter, err := universe.onramp.FilterCCIPSendRequested(&bind.FilterOpts{Start: 0}, nil) - require.NoError(t, err) - // Iterate until latest event - for logIter.Next() { - } - log := logIter.Event - require.Equal(t, getSelector(otherChain), log.DestChainSelector) - require.Equal(t, pingPong.Address(), log.Message.Sender) - chainPingPongAddr := pingPongs[otherChain][chainID].Address().Bytes() - // With chain agnostic addresses we need to pad the address to the correct length if the receiver is zero prefixed - paddedAddr := gethcommon.LeftPadBytes(chainPingPongAddr, len(log.Message.Receiver)) - require.Equal(t, paddedAddr, log.Message.Receiver) - } - } -} - -// InitializeContracts initializes ping pong contracts on all chains and -// connects them all to each other. -func initializePingPongContracts( - t *testing.T, - chainUniverses map[uint64]onchainUniverse, -) map[uint64]map[uint64]*pp.PingPongDemo { - pingPongs := make(map[uint64]map[uint64]*pp.PingPongDemo) - chainIDs := maps.Keys(chainUniverses) - // For each chain initialize N ping pong contracts, where N is the (number of chains - 1) - for chainID, universe := range chainUniverses { - pingPongs[chainID] = make(map[uint64]*pp.PingPongDemo) - for _, chainToConnect := range chainIDs { - if chainToConnect == chainID { - continue // don't connect chain to itself - } - backend := universe.backend - owner := universe.owner - pingPongAddr, _, _, err := pp.DeployPingPongDemo(owner, backend, universe.router.Address(), universe.linkToken.Address()) - require.NoError(t, err) - backend.Commit() - pingPong, err := pp.NewPingPongDemo(pingPongAddr, backend) - require.NoError(t, err) - backend.Commit() - // Fund the ping pong contract with LINK - _, err = universe.linkToken.Transfer(owner, pingPong.Address(), e18Mult(10)) - backend.Commit() - require.NoError(t, err) - pingPongs[chainID][chainToConnect] = pingPong - } - } - - // Set up each ping pong contract to its counterpart on the other chain - for chainID, universe := range chainUniverses { - for chainToConnect, pingPong := range pingPongs[chainID] { - _, err := pingPong.SetCounterpart( - universe.owner, - getSelector(chainUniverses[chainToConnect].chainID), - // This is the address of the ping pong contract on the other chain - pingPongs[chainToConnect][chainID].Address(), - ) - require.NoError(t, err) - universe.backend.Commit() - } - } - return pingPongs -} diff --git a/core/capabilities/ccip/ccip_integration_tests/rmn/rmn_home_test.go b/core/capabilities/ccip/ccip_integration_tests/rmn/rmn_home_test.go new file mode 100644 index 00000000000..12a207ea5b9 --- /dev/null +++ b/core/capabilities/ccip/ccip_integration_tests/rmn/rmn_home_test.go @@ -0,0 +1,174 @@ +package rmn + +import ( + "bytes" + "math/big" + "slices" + "testing" + "time" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + + readerpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" +) + +func TestRMNHomeReader_GetRMNNodesInfo(t *testing.T) { + ctx := testutils.Context(t) + lggr := logger.TestLogger(t) + uni := integrationhelpers.NewTestUniverse(ctx, t, lggr) + zeroBytes := [32]byte{0} + + const ( + chainID1 = 1 + minObservers1 = 1 + observerBitmap1 = 1 + + chainID2 = 2 + minObservers2 = 0 + observerBitmap2 = 1 + ) + + //================================Deploy and configure RMNHome=============================== + rmnHomeAddress, _, rmnHome, err := rmn_home.DeployRMNHome(uni.Transactor, uni.Backend) + require.NoError(t, err) + uni.Backend.Commit() + + staticConfig, dynamicConfig, err := integrationhelpers.GenerateRMNHomeConfigs( + "PeerID1", + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "This is a sample offchain configuration in the static config", + chainID1, + minObservers1, + big.NewInt(observerBitmap1), + ) + require.NoError(t, err) + + _, err = rmnHome.SetCandidate(uni.Transactor, staticConfig, dynamicConfig, zeroBytes) + require.NoError(t, err) + uni.Backend.Commit() + + configDigest, err := rmnHome.GetCandidateDigest(&bind.CallOpts{}) + require.NoError(t, err) + + _, err = rmnHome.PromoteCandidateAndRevokeActive(uni.Transactor, configDigest, zeroBytes) + require.NoError(t, err) + uni.Backend.Commit() + + rmnHomeBoundContract := types.BoundContract{ + Address: rmnHomeAddress.String(), + Name: consts.ContractNameRMNHome, + } + + err = uni.HomeContractReader.Bind(testutils.Context(t), []types.BoundContract{rmnHomeBoundContract}) + require.NoError(t, err) + + rmnHomeReader := readerpkg.NewRMNHomePoller(uni.HomeContractReader, rmnHomeBoundContract, lggr, 100*time.Millisecond) + + err = rmnHomeReader.Start(testutils.Context(t)) + require.NoError(t, err) + + t.Cleanup(func() { + err1 := rmnHomeReader.Close() + require.NoError(t, err1) + }) + + //================================Test RMNHome Reader=============================== + expectedNodesInfo := integrationhelpers.GenerateExpectedRMNHomeNodesInfo(staticConfig, chainID1) + + require.Eventually( + t, + assertRMNHomeNodesInfo(t, rmnHomeReader, configDigest, expectedNodesInfo, nil), + 5*time.Second, + 100*time.Millisecond, + ) + + // Add a new candidate config + staticConfig2, dynamicConfig2, err := integrationhelpers.GenerateRMNHomeConfigs( + "PeerID2", + "1123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "This is a sample offchain configuration in the static config 2", + chainID2, + minObservers2, + big.NewInt(observerBitmap2), + ) + require.NoError(t, err) + + _, err = rmnHome.SetCandidate(uni.Transactor, staticConfig2, dynamicConfig2, zeroBytes) + require.NoError(t, err) + uni.Backend.Commit() + + candidateConfigDigest, err := rmnHome.GetCandidateDigest(&bind.CallOpts{}) + require.NoError(t, err) + + expectedCandidateNodesInfo := integrationhelpers.GenerateExpectedRMNHomeNodesInfo(staticConfig2, chainID2) + + require.Eventually( + t, + assertRMNHomeNodesInfo(t, rmnHomeReader, candidateConfigDigest, expectedCandidateNodesInfo, nil), + 5*time.Second, + 100*time.Millisecond, + ) + + // Promote the candidate config + _, err = rmnHome.PromoteCandidateAndRevokeActive(uni.Transactor, candidateConfigDigest, configDigest) + require.NoError(t, err) + uni.Backend.Commit() + + require.Eventually( + t, + assertRMNHomeNodesInfo(t, rmnHomeReader, candidateConfigDigest, expectedCandidateNodesInfo, &configDigest), + 5*time.Second, + 100*time.Millisecond, + ) +} + +func assertRMNHomeNodesInfo( + t *testing.T, + rmnHomeReader readerpkg.RMNHome, + configDigest [32]byte, + expectedNodesInfo []readerpkg.HomeNodeInfo, + prevConfigDigest *[32]byte, +) func() bool { + return func() bool { + nodesInfo, err := rmnHomeReader.GetRMNNodesInfo(configDigest) + if err != nil { + t.Logf("Error getting RMN nodes info: %v", err) + return false + } + + equal := slices.EqualFunc(expectedNodesInfo, nodesInfo, func(a, b readerpkg.HomeNodeInfo) bool { + return a.ID == b.ID && + a.PeerID == b.PeerID && + bytes.Equal(*a.OffchainPublicKey, *b.OffchainPublicKey) && + a.SupportedSourceChains.Equal(b.SupportedSourceChains) + }) + + if !equal { + t.Logf("Expected nodes info doesn't match actual nodes info") + t.Logf("Expected: %+v", expectedNodesInfo) + t.Logf("Actual: %+v", nodesInfo) + return false + } + + if prevConfigDigest != nil { + isPrevConfigStillSet := rmnHomeReader.IsRMNHomeConfigDigestSet(*prevConfigDigest) + if isPrevConfigStillSet { + t.Logf("Previous config is still set") + return false + } + } + + return true + } +} diff --git a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go new file mode 100644 index 00000000000..10e33cd8f39 --- /dev/null +++ b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go @@ -0,0 +1,300 @@ +package usdcreader + +import ( + "context" + "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/core" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + sel "github.com/smartcontractkit/chain-selectors" + + "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" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_reader_tester" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +func Test_USDCReader_MessageHashes(t *testing.T) { + finalityDepth := 5 + + ctx := testutils.Context(t) + ethereumChain := cciptypes.ChainSelector(sel.ETHEREUM_MAINNET_OPTIMISM_1.Selector) + ethereumDomainCCTP := reader.CCTPDestDomains[uint64(ethereumChain)] + avalancheChain := cciptypes.ChainSelector(sel.AVALANCHE_MAINNET.Selector) + avalancheDomainCCTP := reader.CCTPDestDomains[uint64(avalancheChain)] + polygonChain := cciptypes.ChainSelector(sel.POLYGON_MAINNET.Selector) + polygonDomainCCTP := reader.CCTPDestDomains[uint64(polygonChain)] + + ts := testSetup(ctx, t, ethereumChain, evmconfig.USDCReaderConfig, finalityDepth) + + usdcReader, err := reader.NewUSDCMessageReader( + ctx, + logger.TestLogger(t), + map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig{ + ethereumChain: { + SourceMessageTransmitterAddr: ts.contractAddr.String(), + }, + }, + map[cciptypes.ChainSelector]contractreader.ContractReaderFacade{ + ethereumChain: ts.reader, + }) + require.NoError(t, err) + + emitMessageSent(t, ts, ethereumDomainCCTP, avalancheDomainCCTP, 11) + emitMessageSent(t, ts, ethereumDomainCCTP, avalancheDomainCCTP, 21) + emitMessageSent(t, ts, ethereumDomainCCTP, avalancheDomainCCTP, 31) + emitMessageSent(t, ts, ethereumDomainCCTP, avalancheDomainCCTP, 41) + emitMessageSent(t, ts, ethereumDomainCCTP, polygonDomainCCTP, 31) + emitMessageSent(t, ts, ethereumDomainCCTP, polygonDomainCCTP, 41) + // Finalize events + for i := 0; i < finalityDepth; i++ { + ts.sb.Commit() + } + emitMessageSent(t, ts, ethereumDomainCCTP, avalancheDomainCCTP, 51) + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, ts.lp.Replay(ctx, 1)) + + tt := []struct { + name string + tokens map[reader.MessageTokenID]cciptypes.RampTokenAmount + sourceChain cciptypes.ChainSelector + destChain cciptypes.ChainSelector + expectedMsgIDs []reader.MessageTokenID + }{ + { + name: "empty messages should return empty response", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{}, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{}, + }, + { + name: "single token message", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 1): { + ExtraData: reader.NewSourceTokenDataPayload(11, ethereumDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{reader.NewMessageTokenID(1, 1)}, + }, + { + name: "single token message but different chain", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 2): { + ExtraData: reader.NewSourceTokenDataPayload(31, ethereumDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: polygonChain, + expectedMsgIDs: []reader.MessageTokenID{reader.NewMessageTokenID(1, 2)}, + }, + { + name: "message without matching nonce", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 1): { + ExtraData: reader.NewSourceTokenDataPayload(1234, ethereumDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{}, + }, + { + name: "message without matching source domain", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 1): { + ExtraData: reader.NewSourceTokenDataPayload(11, avalancheDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{}, + }, + { + name: "message with multiple tokens", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 1): { + ExtraData: reader.NewSourceTokenDataPayload(11, ethereumDomainCCTP).ToBytes(), + }, + reader.NewMessageTokenID(1, 2): { + ExtraData: reader.NewSourceTokenDataPayload(21, ethereumDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{ + reader.NewMessageTokenID(1, 1), + reader.NewMessageTokenID(1, 2), + }, + }, + { + name: "message with multiple tokens, one without matching nonce", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 1): { + ExtraData: reader.NewSourceTokenDataPayload(11, ethereumDomainCCTP).ToBytes(), + }, + reader.NewMessageTokenID(1, 2): { + ExtraData: reader.NewSourceTokenDataPayload(12, ethereumDomainCCTP).ToBytes(), + }, + reader.NewMessageTokenID(1, 3): { + ExtraData: reader.NewSourceTokenDataPayload(31, ethereumDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{ + reader.NewMessageTokenID(1, 1), + reader.NewMessageTokenID(1, 3), + }, + }, + { + name: "not finalized events are not returned", + tokens: map[reader.MessageTokenID]cciptypes.RampTokenAmount{ + reader.NewMessageTokenID(1, 5): { + ExtraData: reader.NewSourceTokenDataPayload(51, ethereumDomainCCTP).ToBytes(), + }, + }, + sourceChain: ethereumChain, + destChain: avalancheChain, + expectedMsgIDs: []reader.MessageTokenID{}, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + hashes, err1 := usdcReader.MessageHashes(ctx, tc.sourceChain, tc.destChain, tc.tokens) + require.NoError(t, err1) + + require.Equal(t, len(tc.expectedMsgIDs), len(hashes)) + + for _, msgID := range tc.expectedMsgIDs { + _, ok := hashes[msgID] + require.True(t, ok) + } + }) + } +} + +func emitMessageSent(t *testing.T, testEnv *testSetupData, source, dest uint32, nonce uint64) { + payload := utils.RandomBytes32() + _, err := testEnv.contract.EmitMessageSent( + testEnv.auth, + reader.CCTPMessageVersion, + source, + dest, + utils.RandomBytes32(), + utils.RandomBytes32(), + [32]byte{}, + nonce, + payload[:], + ) + require.NoError(t, err) + testEnv.sb.Commit() +} + +func testSetup(ctx context.Context, t *testing.T, readerChain cciptypes.ChainSelector, cfg evmtypes.ChainReaderConfig, depth int) *testSetupData { + const chainID = 1337 + + // Generate a new key pair for the simulated account + privateKey, err := crypto.GenerateKey() + assert.NoError(t, err) + // Set up the genesis account with balance + blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) + assert.True(t, ok) + alloc := map[common.Address]core.GenesisAccount{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} + simulatedBackend := backends.NewSimulatedBackend(alloc, 0) + // Create a transactor + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) + assert.NoError(t, err) + auth.GasLimit = uint64(0) + + address, _, _, err := usdc_reader_tester.DeployUSDCReaderTester( + auth, + simulatedBackend, + ) + require.NoError(t, err) + simulatedBackend.Commit() + + contract, err := usdc_reader_tester.NewUSDCReaderTester(address, simulatedBackend) + require.NoError(t, err) + + lggr := logger.TestLogger(t) + lggr.SetLogLevel(zapcore.ErrorLevel) + db := pgtest.NewSqlxDB(t) + lpOpts := logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: int64(depth), + BackfillBatchSize: 10, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 100000, + } + cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) + headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), + cl, + lggr, + headTracker, + lpOpts, + ) + require.NoError(t, lp.Start(ctx)) + + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) + require.NoError(t, err) + + err = cr.Start(ctx) + require.NoError(t, err) + + t.Cleanup(func() { + require.NoError(t, cr.Close()) + require.NoError(t, lp.Close()) + require.NoError(t, db.Close()) + }) + + return &testSetupData{ + contractAddr: address, + contract: contract, + sb: simulatedBackend, + auth: auth, + cl: cl, + reader: cr, + lp: lp, + } +} + +type testSetupData struct { + contractAddr common.Address + contract *usdc_reader_tester.USDCReaderTester + sb *backends.SimulatedBackend + auth *bind.TransactOpts + cl client.Client + reader types.ContractReader + lp logpoller.LogPoller +} diff --git a/core/capabilities/ccip/ccipevm/commitcodec.go b/core/capabilities/ccip/ccipevm/commitcodec.go index 928cecd0a41..2f74f2d7096 100644 --- a/core/capabilities/ccip/ccipevm/commitcodec.go +++ b/core/capabilities/ccip/ccipevm/commitcodec.go @@ -4,47 +4,53 @@ import ( "context" "fmt" "math/big" - "strings" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_encoding_utils" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ) +var ( + ccipEncodingUtilsABI = abihelpers.MustParseABI(ccip_encoding_utils.EncodingUtilsABI) +) + // CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. // Compatible with: -// - "EVM2EVMMultiOffRamp 1.6.0-dev" -type CommitPluginCodecV1 struct { - commitReportAcceptedEventInputs abi.Arguments -} +// - "OffRamp 1.6.0-dev" +type CommitPluginCodecV1 struct{} func NewCommitPluginCodecV1() *CommitPluginCodecV1 { - abiParsed, err := abi.JSON(strings.NewReader(evm_2_evm_multi_offramp.EVM2EVMMultiOffRampABI)) - if err != nil { - panic(fmt.Errorf("parse multi offramp abi: %s", err)) - } - eventInputs := abihelpers.MustGetEventInputs("CommitReportAccepted", abiParsed) - return &CommitPluginCodecV1{commitReportAcceptedEventInputs: eventInputs} + return &CommitPluginCodecV1{} } func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { - merkleRoots := make([]evm_2_evm_multi_offramp.EVM2EVMMultiOffRampMerkleRoot, 0, len(report.MerkleRoots)) + merkleRoots := make([]ccip_encoding_utils.InternalMerkleRoot, 0, len(report.MerkleRoots)) for _, root := range report.MerkleRoots { - merkleRoots = append(merkleRoots, evm_2_evm_multi_offramp.EVM2EVMMultiOffRampMerkleRoot{ + merkleRoots = append(merkleRoots, ccip_encoding_utils.InternalMerkleRoot{ SourceChainSelector: uint64(root.ChainSel), - Interval: evm_2_evm_multi_offramp.EVM2EVMMultiOffRampInterval{ - Min: uint64(root.SeqNumsRange.Start()), - Max: uint64(root.SeqNumsRange.End()), - }, - MerkleRoot: root.MerkleRoot, + // TODO: abi-encoded address for EVM source, figure out what to do for non-EVM. + OnRampAddress: common.LeftPadBytes(root.OnRampAddress, 32), + MinSeqNr: uint64(root.SeqNumsRange.Start()), + MaxSeqNr: uint64(root.SeqNumsRange.End()), + MerkleRoot: root.MerkleRoot, + }) + } + + rmnSignatures := make([]ccip_encoding_utils.IRMNRemoteSignature, 0, len(report.RMNSignatures)) + for _, sig := range report.RMNSignatures { + rmnSignatures = append(rmnSignatures, ccip_encoding_utils.IRMNRemoteSignature{ + R: sig.R, + S: sig.S, }) } - tokenPriceUpdates := make([]evm_2_evm_multi_offramp.InternalTokenPriceUpdate, 0, len(report.PriceUpdates.TokenPriceUpdates)) + tokenPriceUpdates := make([]ccip_encoding_utils.InternalTokenPriceUpdate, 0, len(report.PriceUpdates.TokenPriceUpdates)) for _, update := range report.PriceUpdates.TokenPriceUpdates { if !common.IsHexAddress(string(update.TokenID)) { return nil, fmt.Errorf("invalid token address: %s", update.TokenID) @@ -52,58 +58,68 @@ func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.Commi if update.Price.IsEmpty() { return nil, fmt.Errorf("empty price for token: %s", update.TokenID) } - tokenPriceUpdates = append(tokenPriceUpdates, evm_2_evm_multi_offramp.InternalTokenPriceUpdate{ + tokenPriceUpdates = append(tokenPriceUpdates, ccip_encoding_utils.InternalTokenPriceUpdate{ SourceToken: common.HexToAddress(string(update.TokenID)), UsdPerToken: update.Price.Int, }) } - gasPriceUpdates := make([]evm_2_evm_multi_offramp.InternalGasPriceUpdate, 0, len(report.PriceUpdates.GasPriceUpdates)) + gasPriceUpdates := make([]ccip_encoding_utils.InternalGasPriceUpdate, 0, len(report.PriceUpdates.GasPriceUpdates)) for _, update := range report.PriceUpdates.GasPriceUpdates { if update.GasPrice.IsEmpty() { return nil, fmt.Errorf("empty gas price for chain: %d", update.ChainSel) } - gasPriceUpdates = append(gasPriceUpdates, evm_2_evm_multi_offramp.InternalGasPriceUpdate{ + gasPriceUpdates = append(gasPriceUpdates, ccip_encoding_utils.InternalGasPriceUpdate{ DestChainSelector: uint64(update.ChainSel), UsdPerUnitGas: update.GasPrice.Int, }) } - evmReport := evm_2_evm_multi_offramp.EVM2EVMMultiOffRampCommitReport{ - PriceUpdates: evm_2_evm_multi_offramp.InternalPriceUpdates{ - TokenPriceUpdates: tokenPriceUpdates, - GasPriceUpdates: gasPriceUpdates, - }, - MerkleRoots: merkleRoots, + priceUpdates := ccip_encoding_utils.InternalPriceUpdates{ + TokenPriceUpdates: tokenPriceUpdates, + GasPriceUpdates: gasPriceUpdates, + } + + commitReport := &ccip_encoding_utils.OffRampCommitReport{ + PriceUpdates: priceUpdates, + MerkleRoots: merkleRoots, + RmnSignatures: rmnSignatures, + RmnRawVs: report.RMNRawVs.Int, + } + + packed, err := ccipEncodingUtilsABI.Pack("exposeCommitReport", commitReport) + if err != nil { + return nil, fmt.Errorf("failed to pack commit report: %w", err) } - return c.commitReportAcceptedEventInputs.PackValues([]interface{}{evmReport}) + return packed[4:], nil } func (c *CommitPluginCodecV1) Decode(ctx context.Context, bytes []byte) (cciptypes.CommitPluginReport, error) { - unpacked, err := c.commitReportAcceptedEventInputs.Unpack(bytes) + method, ok := ccipEncodingUtilsABI.Methods["exposeCommitReport"] + if !ok { + return cciptypes.CommitPluginReport{}, fmt.Errorf("missing method exposeCommitReport") + } + + unpacked, err := method.Inputs.Unpack(bytes) if err != nil { - return cciptypes.CommitPluginReport{}, err + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to unpack commit report: %w", err) } if len(unpacked) != 1 { return cciptypes.CommitPluginReport{}, fmt.Errorf("expected 1 argument, got %d", len(unpacked)) } - commitReportRaw := abi.ConvertType(unpacked[0], new(evm_2_evm_multi_offramp.EVM2EVMMultiOffRampCommitReport)) - commitReport, is := commitReportRaw.(*evm_2_evm_multi_offramp.EVM2EVMMultiOffRampCommitReport) - if !is { - return cciptypes.CommitPluginReport{}, - fmt.Errorf("expected EVM2EVMMultiOffRampCommitReport, got %T", unpacked[0]) - } + commitReport := *abi.ConvertType(unpacked[0], new(ccip_encoding_utils.OffRampCommitReport)).(*ccip_encoding_utils.OffRampCommitReport) merkleRoots := make([]cciptypes.MerkleRootChain, 0, len(commitReport.MerkleRoots)) for _, root := range commitReport.MerkleRoots { merkleRoots = append(merkleRoots, cciptypes.MerkleRootChain{ - ChainSel: cciptypes.ChainSelector(root.SourceChainSelector), + ChainSel: cciptypes.ChainSelector(root.SourceChainSelector), + OnRampAddress: root.OnRampAddress, SeqNumsRange: cciptypes.NewSeqNumRange( - cciptypes.SeqNum(root.Interval.Min), - cciptypes.SeqNum(root.Interval.Max), + cciptypes.SeqNum(root.MinSeqNr), + cciptypes.SeqNum(root.MaxSeqNr), ), MerkleRoot: root.MerkleRoot, }) @@ -125,12 +141,22 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, bytes []byte) (cciptyp }) } + rmnSignatures := make([]cciptypes.RMNECDSASignature, 0, len(commitReport.RmnSignatures)) + for _, sig := range commitReport.RmnSignatures { + rmnSignatures = append(rmnSignatures, cciptypes.RMNECDSASignature{ + R: sig.R, + S: sig.S, + }) + } + return cciptypes.CommitPluginReport{ MerkleRoots: merkleRoots, PriceUpdates: cciptypes.PriceUpdates{ TokenPriceUpdates: tokenPriceUpdates, GasPriceUpdates: gasPriceUpdates, }, + RMNSignatures: rmnSignatures, + RMNRawVs: cciptypes.NewBigInt(commitReport.RmnRawVs), }, nil } diff --git a/core/capabilities/ccip/ccipevm/commitcodec_test.go b/core/capabilities/ccip/ccipevm/commitcodec_test.go index 737f7be1d6e..c5322dd6383 100644 --- a/core/capabilities/ccip/ccipevm/commitcodec_test.go +++ b/core/capabilities/ccip/ccipevm/commitcodec_test.go @@ -5,11 +5,13 @@ import ( "math/rand" "testing" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -18,7 +20,8 @@ var randomCommitReport = func() cciptypes.CommitPluginReport { return cciptypes.CommitPluginReport{ MerkleRoots: []cciptypes.MerkleRootChain{ { - ChainSel: cciptypes.ChainSelector(rand.Uint64()), + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), SeqNumsRange: cciptypes.NewSeqNumRange( cciptypes.SeqNum(rand.Uint64()), cciptypes.SeqNum(rand.Uint64()), @@ -26,7 +29,8 @@ var randomCommitReport = func() cciptypes.CommitPluginReport { MerkleRoot: utils.RandomBytes32(), }, { - ChainSel: cciptypes.ChainSelector(rand.Uint64()), + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), SeqNumsRange: cciptypes.NewSeqNumRange( cciptypes.SeqNum(rand.Uint64()), cciptypes.SeqNum(rand.Uint64()), @@ -47,6 +51,11 @@ var randomCommitReport = func() cciptypes.CommitPluginReport { {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, }, }, + RMNSignatures: []cciptypes.RMNECDSASignature{ + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + }, + RMNRawVs: cciptypes.NewBigInt(utils.RandUint256()), } } diff --git a/core/capabilities/ccip/ccipevm/executecodec.go b/core/capabilities/ccip/ccipevm/executecodec.go index a64c775112c..3fa700685d9 100644 --- a/core/capabilities/ccip/ccipevm/executecodec.go +++ b/core/capabilities/ccip/ccipevm/executecodec.go @@ -8,21 +8,21 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ) // ExecutePluginCodecV1 is a codec for encoding and decoding execute plugin reports. // Compatible with: -// - "EVM2EVMMultiOffRamp 1.6.0-dev" +// - "OffRamp 1.6.0-dev" type ExecutePluginCodecV1 struct { executeReportMethodInputs abi.Arguments } func NewExecutePluginCodecV1() *ExecutePluginCodecV1 { - abiParsed, err := abi.JSON(strings.NewReader(evm_2_evm_multi_offramp.EVM2EVMMultiOffRampABI)) + abiParsed, err := abi.JSON(strings.NewReader(offramp.OffRampABI)) if err != nil { panic(fmt.Errorf("parse multi offramp abi: %s", err)) } @@ -37,7 +37,7 @@ func NewExecutePluginCodecV1() *ExecutePluginCodecV1 { } func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.ExecutePluginReport) ([]byte, error) { - evmReport := make([]evm_2_evm_multi_offramp.InternalExecutionReportSingleChain, 0, len(report.ChainReports)) + evmReport := make([]offramp.InternalExecutionReport, 0, len(report.ChainReports)) for _, chainReport := range report.ChainReports { if chainReport.ProofFlagBits.IsEmpty() { @@ -49,21 +49,27 @@ func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.Exec evmProofs = append(evmProofs, proof) } - evmMessages := make([]evm_2_evm_multi_offramp.InternalAny2EVMRampMessage, 0, len(chainReport.Messages)) + evmMessages := make([]offramp.InternalAny2EVMRampMessage, 0, len(chainReport.Messages)) for _, message := range chainReport.Messages { receiver := common.BytesToAddress(message.Receiver) - tokenAmounts := make([]evm_2_evm_multi_offramp.InternalRampTokenAmount, 0, len(message.TokenAmounts)) + tokenAmounts := make([]offramp.InternalAny2EVMTokenTransfer, 0, len(message.TokenAmounts)) for _, tokenAmount := range message.TokenAmounts { if tokenAmount.Amount.IsEmpty() { return nil, fmt.Errorf("empty amount for token: %s", tokenAmount.DestTokenAddress) } - tokenAmounts = append(tokenAmounts, evm_2_evm_multi_offramp.InternalRampTokenAmount{ + destGasAmount, err := abiDecodeUint32(tokenAmount.DestExecData) + if err != nil { + return nil, fmt.Errorf("decode dest gas amount: %w", err) + } + + tokenAmounts = append(tokenAmounts, offramp.InternalAny2EVMTokenTransfer{ SourcePoolAddress: tokenAmount.SourcePoolAddress, - DestTokenAddress: tokenAmount.DestTokenAddress, + DestTokenAddress: common.BytesToAddress(tokenAmount.DestTokenAddress), ExtraData: tokenAmount.ExtraData, Amount: tokenAmount.Amount.Int, + DestGasAmount: destGasAmount, }) } @@ -72,8 +78,8 @@ func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.Exec return nil, fmt.Errorf("decode extra args to get gas limit: %w", err) } - evmMessages = append(evmMessages, evm_2_evm_multi_offramp.InternalAny2EVMRampMessage{ - Header: evm_2_evm_multi_offramp.InternalRampMessageHeader{ + evmMessages = append(evmMessages, offramp.InternalAny2EVMRampMessage{ + Header: offramp.InternalRampMessageHeader{ MessageId: message.Header.MessageID, SourceChainSelector: uint64(message.Header.SourceChainSelector), DestChainSelector: uint64(message.Header.DestChainSelector), @@ -88,7 +94,7 @@ func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.Exec }) } - evmChainReport := evm_2_evm_multi_offramp.InternalExecutionReportSingleChain{ + evmChainReport := offramp.InternalExecutionReport{ SourceChainSelector: uint64(chainReport.SourceChainSelector), Messages: evmMessages, OffchainTokenData: chainReport.OffchainTokenData, @@ -110,8 +116,8 @@ func (e *ExecutePluginCodecV1) Decode(ctx context.Context, encodedReport []byte) return cciptypes.ExecutePluginReport{}, fmt.Errorf("unpacked report is empty") } - evmReportRaw := abi.ConvertType(unpacked[0], new([]evm_2_evm_multi_offramp.InternalExecutionReportSingleChain)) - evmReportPtr, is := evmReportRaw.(*[]evm_2_evm_multi_offramp.InternalExecutionReportSingleChain) + evmReportRaw := abi.ConvertType(unpacked[0], new([]offramp.InternalExecutionReport)) + evmReportPtr, is := evmReportRaw.(*[]offramp.InternalExecutionReport) if !is { return cciptypes.ExecutePluginReport{}, fmt.Errorf("got an unexpected report type %T", unpacked[0]) } @@ -134,11 +140,17 @@ func (e *ExecutePluginCodecV1) Decode(ctx context.Context, encodedReport []byte) for _, evmMessage := range evmChainReport.Messages { tokenAmounts := make([]cciptypes.RampTokenAmount, 0, len(evmMessage.TokenAmounts)) for _, tokenAmount := range evmMessage.TokenAmounts { + destData, err := abiEncodeUint32(tokenAmount.DestGasAmount) + if err != nil { + return cciptypes.ExecutePluginReport{}, fmt.Errorf("abi encode dest gas amount: %w", err) + } tokenAmounts = append(tokenAmounts, cciptypes.RampTokenAmount{ SourcePoolAddress: tokenAmount.SourcePoolAddress, - DestTokenAddress: tokenAmount.DestTokenAddress, - ExtraData: tokenAmount.ExtraData, - Amount: cciptypes.NewBigInt(tokenAmount.Amount), + // TODO: should this be abi-encoded? + DestTokenAddress: tokenAmount.DestTokenAddress.Bytes(), + ExtraData: tokenAmount.ExtraData, + Amount: cciptypes.NewBigInt(tokenAmount.Amount), + DestExecData: destData, }) } diff --git a/core/capabilities/ccip/ccipevm/executecodec_test.go b/core/capabilities/ccip/ccipevm/executecodec_test.go index 4f207fdb0e2..40a04512ed1 100644 --- a/core/capabilities/ccip/ccipevm/executecodec_test.go +++ b/core/capabilities/ccip/ccipevm/executecodec_test.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/core" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -34,11 +34,15 @@ var randomExecuteReport = func(t *testing.T, d *testSetupData) cciptypes.Execute tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) for z := 0; z < numTokensPerMsg; z++ { + encodedDestExecData, err2 := abiEncodeUint32(rand.Uint32()) + require.NoError(t, err2) + tokenAmounts[z] = cciptypes.RampTokenAmount{ SourcePoolAddress: utils.RandomAddress().Bytes(), DestTokenAddress: utils.RandomAddress().Bytes(), ExtraData: data, Amount: cciptypes.NewBigInt(utils.RandUint256()), + DestExecData: encodedDestExecData, } } diff --git a/core/capabilities/ccip/ccipevm/gas_helpers.go b/core/capabilities/ccip/ccipevm/gas_helpers.go new file mode 100644 index 00000000000..f6b8348f29a --- /dev/null +++ b/core/capabilities/ccip/ccipevm/gas_helpers.go @@ -0,0 +1,89 @@ +package ccipevm + +import ( + "math" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +const ( + EvmAddressLengthBytes = 20 + EvmWordBytes = 32 + CalldataGasPerByte = 16 + TokenAdminRegistryWarmupCost = 2_500 + TokenAdminRegistryPoolLookupGas = 100 + // WARM_ACCESS_COST TokenAdminRegistry + 700 + // CALL cost for TokenAdminRegistry + 2_100 // COLD_SLOAD_COST loading the pool address + SupportsInterfaceCheck = 2600 + // because the receiver will be untouched initially + 30_000*3 // supportsInterface of ERC165Checker library performs 3 static-calls of 30k gas each + PerTokenOverheadGas = TokenAdminRegistryPoolLookupGas + + SupportsInterfaceCheck + + 200_000 + // releaseOrMint using callWithExactGas + 50_000 // transfer using callWithExactGas + RateLimiterOverheadGas = 2_100 + // COLD_SLOAD_COST for accessing token bucket + 5_000 // SSTORE_RESET_GAS for updating & decreasing token bucket + ConstantMessagePartBytes = 10 * 32 // A message consists of 10 abi encoded fields 32B each (after encoding) + ExecutionStateProcessingOverheadGas = 2_100 + // COLD_SLOAD_COST for first reading the state + 20_000 + // SSTORE_SET_GAS for writing from 0 (untouched) to non-zero (in-progress) + 100 //# SLOAD_GAS = WARM_STORAGE_READ_COST for rewriting from non-zero (in-progress) to non-zero (success/failure) +) + +func NewGasEstimateProvider() EstimateProvider { + return EstimateProvider{} +} + +type EstimateProvider struct { +} + +// CalculateMerkleTreeGas estimates the merkle tree gas based on number of requests +func (gp EstimateProvider) CalculateMerkleTreeGas(numRequests int) uint64 { + if numRequests == 0 { + return 0 + } + merkleProofBytes := (math.Ceil(math.Log2(float64(numRequests))))*32 + (1+2)*32 // only ever one outer root hash + return uint64(merkleProofBytes * CalldataGasPerByte) +} + +// return the size of bytes for msg tokens +func bytesForMsgTokens(numTokens int) int { + // token address (address) + token amount (uint256) + return (EvmAddressLengthBytes + EvmWordBytes) * numTokens +} + +// CalculateMessageMaxGas computes the maximum gas overhead for a message. +func (gp EstimateProvider) CalculateMessageMaxGas(msg cciptypes.Message) uint64 { + numTokens := len(msg.TokenAmounts) + var data []byte = msg.Data + dataLength := len(data) + + // TODO: update interface to return error? + // Although this decoding should never fail. + messageGasLimit, err := decodeExtraArgsV1V2(msg.ExtraArgs) + if err != nil { + panic(err) + } + + messageBytes := ConstantMessagePartBytes + + bytesForMsgTokens(numTokens) + + dataLength + + messageCallDataGas := uint64(messageBytes * CalldataGasPerByte) + + // 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 + // if there are tokens, and it's only loaded once. + rateLimiterOverhead := uint64(0) + adminRegistryOverhead := uint64(0) + if numTokens >= 1 { + rateLimiterOverhead = RateLimiterOverheadGas + adminRegistryOverhead = TokenAdminRegistryWarmupCost + } + + return messageGasLimit.Uint64() + + messageCallDataGas + + ExecutionStateProcessingOverheadGas + + SupportsInterfaceCheck + + adminRegistryOverhead + + rateLimiterOverhead + + PerTokenOverheadGas*uint64(numTokens) +} diff --git a/core/capabilities/ccip/ccipevm/gas_helpers_test.go b/core/capabilities/ccip/ccipevm/gas_helpers_test.go new file mode 100644 index 00000000000..23afd084d80 --- /dev/null +++ b/core/capabilities/ccip/ccipevm/gas_helpers_test.go @@ -0,0 +1,157 @@ +package ccipevm + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +func Test_calculateMessageMaxGas(t *testing.T) { + type args struct { + dataLen int + numTokens int + extraArgs []byte + } + tests := []struct { + name string + args args + want uint64 + }{ + { + name: "base", + args: args{dataLen: 5, numTokens: 2, extraArgs: makeExtraArgsV1(200_000)}, + want: 1_022_264, + }, + { + name: "large", + args: args{dataLen: 1000, numTokens: 1000, extraArgs: makeExtraArgsV1(200_000)}, + want: 346_677_520, + }, + { + name: "overheadGas test 1", + args: args{dataLen: 0, numTokens: 0, extraArgs: makeExtraArgsV1(200_000)}, + want: 319_920, + }, + { + name: "overheadGas test 2", + args: args{dataLen: len([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}), numTokens: 1, extraArgs: makeExtraArgsV1(200_000)}, + want: 675_948, + }, + { + name: "allowOOO set to true makes no difference to final gas estimate", + args: args{dataLen: 5, numTokens: 2, extraArgs: makeExtraArgsV2(200_000, true)}, + want: 1_022_264, + }, + { + name: "allowOOO set to false makes no difference to final gas estimate", + args: args{dataLen: 5, numTokens: 2, extraArgs: makeExtraArgsV2(200_000, false)}, + want: 1_022_264, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + msg := ccipocr3.Message{ + Data: make([]byte, tt.args.dataLen), + TokenAmounts: make([]ccipocr3.RampTokenAmount, tt.args.numTokens), + ExtraArgs: tt.args.extraArgs, + } + ep := EstimateProvider{} + got := ep.CalculateMessageMaxGas(msg) + t.Log(got) + assert.Equalf(t, tt.want, got, "calculateMessageMaxGas(%v, %v)", tt.args.dataLen, tt.args.numTokens) + }) + } +} + +// TestCalculateMaxGas is taken from the ccip repo where the CalculateMerkleTreeGas and CalculateMessageMaxGas values +// are combined to one function. +func TestCalculateMaxGas(t *testing.T) { + tests := []struct { + name string + numRequests int + dataLength int + numberOfTokens int + extraArgs []byte + want uint64 + }{ + { + name: "maxGasOverheadGas 1", + numRequests: 6, + dataLength: 0, + numberOfTokens: 0, + extraArgs: makeExtraArgsV1(200_000), + want: 322_992, + }, + { + name: "maxGasOverheadGas 2", + numRequests: 3, + dataLength: len([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}), + numberOfTokens: 1, + extraArgs: makeExtraArgsV1(200_000), + want: 678_508, + }, + { + name: "v2 extra args", + numRequests: 3, + dataLength: len([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}), + numberOfTokens: 1, + extraArgs: makeExtraArgsV2(200_000, true), + want: 678_508, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + msg := ccipocr3.Message{ + Data: make([]byte, tt.dataLength), + TokenAmounts: make([]ccipocr3.RampTokenAmount, tt.numberOfTokens), + ExtraArgs: tt.extraArgs, + } + ep := EstimateProvider{} + + gotTree := ep.CalculateMerkleTreeGas(tt.numRequests) + gotMsg := ep.CalculateMessageMaxGas(msg) + t.Log("want", tt.want, "got", gotTree+gotMsg) + assert.Equal(t, tt.want, gotTree+gotMsg) + }) + } +} + +func makeExtraArgsV1(gasLimit uint64) []byte { + // extra args is the tag followed by the gas limit abi-encoded. + var extraArgs []byte + extraArgs = append(extraArgs, evmExtraArgsV1Tag...) + gasLimitBytes := new(big.Int).SetUint64(gasLimit).Bytes() + // pad from the left to 32 bytes + gasLimitBytes = common.LeftPadBytes(gasLimitBytes, 32) + extraArgs = append(extraArgs, gasLimitBytes...) + return extraArgs +} + +func makeExtraArgsV2(gasLimit uint64, allowOOO bool) []byte { + // extra args is the tag followed by the gas limit and allowOOO abi-encoded. + var extraArgs []byte + extraArgs = append(extraArgs, evmExtraArgsV2Tag...) + gasLimitBytes := new(big.Int).SetUint64(gasLimit).Bytes() + // pad from the left to 32 bytes + gasLimitBytes = common.LeftPadBytes(gasLimitBytes, 32) + + // abi-encode allowOOO + var allowOOOBytes []byte + if allowOOO { + allowOOOBytes = append(allowOOOBytes, 1) + } else { + allowOOOBytes = append(allowOOOBytes, 0) + } + // pad from the left to 32 bytes + allowOOOBytes = common.LeftPadBytes(allowOOOBytes, 32) + + extraArgs = append(extraArgs, gasLimitBytes...) + extraArgs = append(extraArgs, allowOOOBytes...) + return extraArgs +} diff --git a/core/capabilities/ccip/ccipevm/helpers.go b/core/capabilities/ccip/ccipevm/helpers.go index ee83230a4ce..4cfd64b7c65 100644 --- a/core/capabilities/ccip/ccipevm/helpers.go +++ b/core/capabilities/ccip/ccipevm/helpers.go @@ -4,6 +4,8 @@ import ( "bytes" "fmt" "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" ) func decodeExtraArgsV1V2(extraArgs []byte) (gasLimit *big.Int, err error) { @@ -31,3 +33,13 @@ func decodeExtraArgsV1V2(extraArgs []byte) (gasLimit *big.Int, err error) { } return ifaces[0].(*big.Int), nil } + +// abiEncodeMethodInputs encodes the inputs for a method call. +// example abi: `[{ "name" : "method", "type": "function", "inputs": [{"name": "a", "type": "uint256"}]}]` +func abiEncodeMethodInputs(abiDef abi.ABI, inputs ...interface{}) ([]byte, error) { + packed, err := abiDef.Pack("method", inputs...) + if err != nil { + return nil, err + } + return packed[4:], nil // remove the method selector +} diff --git a/core/capabilities/ccip/ccipevm/helpers_test.go b/core/capabilities/ccip/ccipevm/helpers_test.go index 95a5d4439bb..e0de0572226 100644 --- a/core/capabilities/ccip/ccipevm/helpers_test.go +++ b/core/capabilities/ccip/ccipevm/helpers_test.go @@ -5,9 +5,9 @@ import ( "math/rand" "testing" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" - "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" ) func Test_decodeExtraArgs(t *testing.T) { diff --git a/core/capabilities/ccip/ccipevm/msghasher.go b/core/capabilities/ccip/ccipevm/msghasher.go index 0df0a8254ac..4d86e8a930b 100644 --- a/core/capabilities/ccip/ccipevm/msghasher.go +++ b/core/capabilities/ccip/ccipevm/msghasher.go @@ -4,8 +4,9 @@ import ( "context" "fmt" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -32,7 +33,7 @@ var ( // MessageHasherV1 implements the MessageHasher interface. // Compatible with: -// - "EVM2EVMMultiOnRamp 1.6.0-dev" +// - "OnRamp 1.6.0-dev" type MessageHasherV1 struct{} func NewMessageHasherV1() *MessageHasherV1 { @@ -43,35 +44,59 @@ func NewMessageHasherV1() *MessageHasherV1 { // It constructs all of the inputs to the final keccak256 hash in Internal._hash(Any2EVMRampMessage). // The main structure of the hash is as follows: /* - keccak256( - leafDomainSeparator, - keccak256(any_2_evm_message_hash, header.sourceChainSelector, header.destinationChainSelector, onRamp), - keccak256(fixedSizeMessageFields), - keccak256(messageData), - keccak256(encodedRampTokenAmounts), - ) + // Fixed-size message fields are included in nested hash to reduce stack pressure. + // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. + return keccak256( + abi.encode( + MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, + metadataHash, + keccak256( + abi.encode( + original.header.messageId, + original.receiver, + original.header.sequenceNumber, + original.gasLimit, + original.header.nonce + ) + ), + keccak256(original.sender), + keccak256(original.data), + keccak256(abi.encode(original.tokenAmounts)) + ) + ); */ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (cciptypes.Bytes32, error) { - var rampTokenAmounts []message_hasher.InternalRampTokenAmount + var rampTokenAmounts []message_hasher.InternalAny2EVMTokenTransfer for _, rta := range msg.TokenAmounts { - rampTokenAmounts = append(rampTokenAmounts, message_hasher.InternalRampTokenAmount{ + destGasAmount, err := abiDecodeUint32(rta.DestExecData) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest gas amount: %w", err) + } + + rampTokenAmounts = append(rampTokenAmounts, message_hasher.InternalAny2EVMTokenTransfer{ SourcePoolAddress: rta.SourcePoolAddress, - DestTokenAddress: rta.DestTokenAddress, + DestTokenAddress: common.BytesToAddress(rta.DestTokenAddress), ExtraData: rta.ExtraData, Amount: rta.Amount.Int, + DestGasAmount: destGasAmount, }) } - encodedRampTokenAmounts, err := abiEncode("encodeTokenAmountsHashPreimage", rampTokenAmounts) + + encodedRampTokenAmounts, err := h.abiEncode("encodeAny2EVMTokenAmountsHashPreimage", rampTokenAmounts) if err != nil { return [32]byte{}, fmt.Errorf("abi encode token amounts: %w", err) } - metaDataHashInput, err := abiEncode( + fmt.Printf("encodedRampTokenAmounts: %x\n", encodedRampTokenAmounts) + + metaDataHashInput, err := h.abiEncode( "encodeMetadataHashPreimage", ANY_2_EVM_MESSAGE_HASH, uint64(msg.Header.SourceChainSelector), uint64(msg.Header.DestChainSelector), - []byte(msg.Header.OnRamp), + // TODO: this is evm-specific padding, fix. + // no-op if the onramp is already 32 bytes. + utils.Keccak256Fixed(common.LeftPadBytes(msg.Header.OnRamp, 32)), ) if err != nil { return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err) @@ -86,10 +111,9 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (ccipty return [32]byte{}, fmt.Errorf("decode extra args: %w", err) } - fixedSizeFieldsEncoded, err := abiEncode( + fixedSizeFieldsEncoded, err := h.abiEncode( "encodeFixedSizeFieldsHashPreimage", msg.Header.MessageID, - []byte(msg.Sender), common.BytesToAddress(msg.Receiver), uint64(msg.Header.SequenceNumber), gasLimit, @@ -99,11 +123,12 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (ccipty return [32]byte{}, fmt.Errorf("abi encode fixed size values: %w", err) } - packedValues, err := abiEncode( + packedValues, err := h.abiEncode( "encodeFinalHashPreimage", leafDomainSeparator, - utils.Keccak256Fixed(metaDataHashInput), + utils.Keccak256Fixed(metaDataHashInput), // metaDataHash utils.Keccak256Fixed(fixedSizeFieldsEncoded), + utils.Keccak256Fixed(msg.Sender), utils.Keccak256Fixed(msg.Data), utils.Keccak256Fixed(encodedRampTokenAmounts), ) @@ -111,10 +136,12 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (ccipty return [32]byte{}, fmt.Errorf("abi encode packed values: %w", err) } + fmt.Printf("packedValues: %x\n", packedValues) + return utils.Keccak256Fixed(packedValues), nil } -func abiEncode(method string, values ...interface{}) ([]byte, error) { +func (h *MessageHasherV1) abiEncode(method string, values ...interface{}) ([]byte, error) { res, err := messageHasherABI.Pack(method, values...) if err != nil { return nil, err @@ -123,5 +150,19 @@ func abiEncode(method string, values ...interface{}) ([]byte, error) { return res[4:], nil } +func abiDecodeUint32(data []byte) (uint32, error) { + raw, err := utils.ABIDecode(`[{ "type": "uint32" }]`, data) + if err != nil { + return 0, fmt.Errorf("abi decode uint32: %w", err) + } + + val := *abi.ConvertType(raw[0], new(uint32)).(*uint32) + return val, nil +} + +func abiEncodeUint32(data uint32) ([]byte, error) { + return utils.ABIEncode(`[{ "type": "uint32" }]`, data) +} + // Interface compliance check var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/capabilities/ccip/ccipevm/msghasher_test.go b/core/capabilities/ccip/ccipevm/msghasher_test.go index 911a10b26a5..7f780b30db8 100644 --- a/core/capabilities/ccip/ccipevm/msghasher_test.go +++ b/core/capabilities/ccip/ccipevm/msghasher_test.go @@ -15,7 +15,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/stretchr/testify/require" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" @@ -43,13 +43,17 @@ func TestMessageHasher_EVM2EVM(t *testing.T) { func testHasherEVM2EVM(ctx context.Context, t *testing.T, d *testSetupData, evmExtraArgs evmExtraArgs) { ccipMsg := createEVM2EVMMessage(t, d.contract, evmExtraArgs) - var tokenAmounts []message_hasher.InternalRampTokenAmount + var tokenAmounts []message_hasher.InternalAny2EVMTokenTransfer for _, rta := range ccipMsg.TokenAmounts { - tokenAmounts = append(tokenAmounts, message_hasher.InternalRampTokenAmount{ + destGasAmount, err := abiDecodeUint32(rta.DestExecData) + require.NoError(t, err) + + tokenAmounts = append(tokenAmounts, message_hasher.InternalAny2EVMTokenTransfer{ SourcePoolAddress: rta.SourcePoolAddress, - DestTokenAddress: rta.DestTokenAddress, + DestTokenAddress: common.BytesToAddress(rta.DestTokenAddress), ExtraData: rta.ExtraData[:], Amount: rta.Amount.Int, + DestGasAmount: destGasAmount, }) } evmMsg := message_hasher.InternalAny2EVMRampMessage{ @@ -124,11 +128,14 @@ func createEVM2EVMMessage(t *testing.T, messageHasher *message_hasher.MessageHas var tokenAmounts []cciptypes.RampTokenAmount for i := 0; i < len(sourceTokenDatas); i++ { extraData := utils.RandomBytes32() + encodedDestExecData, err := utils.ABIEncode(`[{ "type": "uint32" }]`, rand.Uint32()) + require.NoError(t, err) tokenAmounts = append(tokenAmounts, cciptypes.RampTokenAmount{ SourcePoolAddress: abiEncodedAddress(t), DestTokenAddress: abiEncodedAddress(t), ExtraData: extraData[:], Amount: cciptypes.NewBigInt(big.NewInt(0).SetUint64(rand.Uint64())), + DestExecData: encodedDestExecData, }) } diff --git a/core/capabilities/ccip/ccipevm/rmncrypto.go b/core/capabilities/ccip/ccipevm/rmncrypto.go new file mode 100644 index 00000000000..ce21a6a8edd --- /dev/null +++ b/core/capabilities/ccip/ccipevm/rmncrypto.go @@ -0,0 +1,182 @@ +package ccipevm + +import ( + "bytes" + "context" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// encodingUtilsAbi is the ABI for the EncodingUtils contract. +// Should be imported when gethwrappers are moved from ccip repo to core. +// nolint:lll +const encodingUtilsAbiRaw = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DoNotDeploy","type":"error"},{"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":"struct Internal.MerkleRoot[]","name":"destLaneUpdates","type":"tuple[]"}],"internalType":"struct RMNRemote.Report","name":"rmnReport","type":"tuple"}],"name":"_rmnReport","outputs":[],"stateMutability":"nonpayable","type":"function"}]` +const addressEncodeAbiRaw = `[{"name":"method","type":"function","inputs":[{"name": "", "type": "address"}]}]` + +var ( + encodingUtilsABI abi.ABI + addressEncodeABI abi.ABI +) + +func init() { + var err error + + encodingUtilsABI, err = abi.JSON(strings.NewReader(encodingUtilsAbiRaw)) + if err != nil { + panic(fmt.Errorf("failed to parse encoding utils ABI: %v", err)) + } + + addressEncodeABI, err = abi.JSON(strings.NewReader(addressEncodeAbiRaw)) + if err != nil { + panic(fmt.Errorf("failed to parse address encode ABI: %v", err)) + } +} + +const ( + // v is the recovery ID for ECDSA signatures. This implementation assumes that v is always 27. + v = 27 +) + +// EVMRMNCrypto is the RMNCrypto implementation for EVM chains. +type EVMRMNCrypto struct{} + +// Interface compliance check +var _ cciptypes.RMNCrypto = (*EVMRMNCrypto)(nil) + +func NewEVMRMNCrypto() *EVMRMNCrypto { + return &EVMRMNCrypto{} +} + +// Should be replaced by gethwrapper types when they're available +type evmRMNRemoteReport struct { + DestChainID *big.Int `abi:"destChainId"` + DestChainSelector uint64 + RmnRemoteContractAddress common.Address + OfframpAddress common.Address + RmnHomeContractConfigDigest [32]byte + DestLaneUpdates []evmInternalMerkleRoot +} + +type evmInternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + +func (r *EVMRMNCrypto) VerifyReportSignatures( + _ context.Context, + sigs []cciptypes.RMNECDSASignature, + report cciptypes.RMNReport, + signerAddresses []cciptypes.Bytes, +) error { + if sigs == nil { + return fmt.Errorf("no signatures provided") + } + if report.LaneUpdates == nil { + return fmt.Errorf("no lane updates provided") + } + + evmLaneUpdates := make([]evmInternalMerkleRoot, len(report.LaneUpdates)) + for i, lu := range report.LaneUpdates { + onRampAddress := common.BytesToAddress(lu.OnRampAddress) + onRampAddrAbi, err := abiEncodeMethodInputs(addressEncodeABI, onRampAddress) + if err != nil { + return fmt.Errorf("ΑΒΙ encode onRampAddress: %w", err) + } + evmLaneUpdates[i] = evmInternalMerkleRoot{ + SourceChainSelector: uint64(lu.SourceChainSelector), + OnRampAddress: onRampAddrAbi, + MinSeqNr: uint64(lu.MinSeqNr), + MaxSeqNr: uint64(lu.MaxSeqNr), + MerkleRoot: lu.MerkleRoot, + } + } + + evmReport := evmRMNRemoteReport{ + DestChainID: report.DestChainID.Int, + DestChainSelector: uint64(report.DestChainSelector), + RmnRemoteContractAddress: common.HexToAddress(report.RmnRemoteContractAddress.String()), + OfframpAddress: common.HexToAddress(report.OfframpAddress.String()), + RmnHomeContractConfigDigest: report.RmnHomeContractConfigDigest, + DestLaneUpdates: evmLaneUpdates, + } + + abiEnc, err := encodingUtilsABI.Methods["_rmnReport"].Inputs.Pack(report.ReportVersionDigest, evmReport) + if err != nil { + return fmt.Errorf("failed to ABI encode args: %w", err) + } + + signedHash := crypto.Keccak256Hash(abiEnc) + + // keep track of the previous signer for validating signers ordering + prevSignerAddr := common.Address{} + + for _, sig := range sigs { + recoveredAddress, err := recoverAddressFromSig( + v, + sig.R, + sig.S, + signedHash[:], + ) + if err != nil { + return fmt.Errorf("failed to recover public key from signature: %w", err) + } + + // make sure that signers are ordered correctly (ASC addresses). + if bytes.Compare(prevSignerAddr.Bytes(), recoveredAddress.Bytes()) == 1 { + return fmt.Errorf("signers are not ordered correctly") + } + prevSignerAddr = recoveredAddress + + // Check if the public key is in the list of the provided RMN nodes + found := false + for _, signerAddr := range signerAddresses { + signerAddrEvm := common.BytesToAddress(signerAddr) + if signerAddrEvm == recoveredAddress { + found = true + break + } + } + if !found { + return fmt.Errorf("the recovered public key does not match any signer address, verification failed") + } + } + + return nil +} + +// recoverAddressFromSig Recovers a public address from an ECDSA signature using r, s, v, and the hash of the message. +func recoverAddressFromSig(v int, r, s [32]byte, hash []byte) (common.Address, error) { + // Ensure v is either 27 or 28 (as used in Ethereum) + if v != 27 && v != 28 { + return common.Address{}, errors.New("v must be 27 or 28") + } + + // Construct the signature by concatenating r, s, and the recovery ID (v - 27 to convert to 0/1) + sig := append(r[:], s[:]...) + sig = append(sig, byte(v-27)) + + // Recover the public key bytes from the signature and message hash + pubKeyBytes, err := crypto.Ecrecover(hash, sig) + if err != nil { + return common.Address{}, fmt.Errorf("failed to recover public key: %v", err) + } + + // Convert the recovered public key to an ECDSA public key + pubKey, err := crypto.UnmarshalPubkey(pubKeyBytes) + if err != nil { + return common.Address{}, fmt.Errorf("failed to unmarshal public key: %v", err) + } // or SigToPub + + return crypto.PubkeyToAddress(*pubKey), nil +} diff --git a/core/capabilities/ccip/ccipevm/rmncrypto_test.go b/core/capabilities/ccip/ccipevm/rmncrypto_test.go new file mode 100644 index 00000000000..7e33a88bc52 --- /dev/null +++ b/core/capabilities/ccip/ccipevm/rmncrypto_test.go @@ -0,0 +1,69 @@ +package ccipevm + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_VerifyRmnReportSignatures(t *testing.T) { + // NOTE: The following test data (public keys, signatures, ...) are shared from the RMN team. + + onchainRmnRemoteAddr := common.HexToAddress("0x7821bcd6944457d17c631157efeb0c621baa76eb") + + rmnHomeContractConfigDigestHex := "0x785936570d1c7422ef30b7da5555ad2f175fa2dd97a2429a2e71d1e07c94e060" + rmnHomeContractConfigDigest := common.FromHex(rmnHomeContractConfigDigestHex) + require.Len(t, rmnHomeContractConfigDigest, 32) + var rmnHomeContractConfigDigest32 [32]byte + copy(rmnHomeContractConfigDigest32[:], rmnHomeContractConfigDigest) + + rootHex := "0x48e688aefc20a04fdec6b8ff19df358fd532455659dcf529797cda358e9e5205" + root := common.FromHex(rootHex) + require.Len(t, root, 32) + var root32 [32]byte + copy(root32[:], root) + + onRampAddr := common.HexToAddress("0x6662cb20464f4be557262693bea0409f068397ed") + + destChainEvmID := int64(4083663998511321420) + + reportData := cciptypes.RMNReport{ + ReportVersionDigest: cciptypes.Bytes32(crypto.Keccak256Hash([]byte("RMN_V1_6_ANY2EVM_REPORT"))), + DestChainID: cciptypes.NewBigIntFromInt64(destChainEvmID), + DestChainSelector: 5266174733271469989, + RmnRemoteContractAddress: common.HexToAddress("0x3d015cec4411357eff4ea5f009a581cc519f75d3").Bytes(), + OfframpAddress: common.HexToAddress("0xc5cdb7711a478058023373b8ae9e7421925140f8").Bytes(), + RmnHomeContractConfigDigest: rmnHomeContractConfigDigest32, + LaneUpdates: []cciptypes.RMNLaneUpdate{ + { + SourceChainSelector: 8258882951688608272, + OnRampAddress: onRampAddr.Bytes(), + MinSeqNr: 9018980618932210108, + MaxSeqNr: 8239368306600774074, + MerkleRoot: root32, + }, + }, + } + + ctx := tests.Context(t) + + rmnCrypto := NewEVMRMNCrypto() + + r, _ := cciptypes.NewBytes32FromString("0x89546b4652d0377062a398e413344e4da6034ae877c437d0efe0e5246b70a9a1") + s, _ := cciptypes.NewBytes32FromString("0x95eef2d24d856ccac3886db8f4aebea60684ed73942392692908fed79a679b4e") + + err := rmnCrypto.VerifyReportSignatures( + ctx, + []cciptypes.RMNECDSASignature{{R: r, S: s}}, + reportData, + []cciptypes.Bytes{onchainRmnRemoteAddr.Bytes()}, + ) + assert.NoError(t, err) +} diff --git a/core/capabilities/ccip/ccipevm/tokendata.go b/core/capabilities/ccip/ccipevm/tokendata.go new file mode 100644 index 00000000000..9239b668f2c --- /dev/null +++ b/core/capabilities/ccip/ccipevm/tokendata.go @@ -0,0 +1,38 @@ +package ccipevm + +import ( + "context" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" +) + +type usdcAttestationPayload struct { + Message []byte + Attestation []byte +} + +func (m usdcAttestationPayload) AbiString() string { + return ` + [{ + "components": [ + {"name": "message", "type": "bytes"}, + {"name": "attestation", "type": "bytes"} + ], + "type": "tuple" + }]` +} + +type EVMTokenDataEncoder struct{} + +func NewEVMTokenDataEncoder() EVMTokenDataEncoder { + return EVMTokenDataEncoder{} +} + +func (e EVMTokenDataEncoder) EncodeUSDC(_ context.Context, message cciptypes.Bytes, attestation cciptypes.Bytes) (cciptypes.Bytes, error) { + return abihelpers.EncodeAbiStruct(usdcAttestationPayload{ + Message: message, + Attestation: attestation, + }) +} diff --git a/core/capabilities/ccip/ccipevm/tokendata_test.go b/core/capabilities/ccip/ccipevm/tokendata_test.go new file mode 100644 index 00000000000..00744803e0d --- /dev/null +++ b/core/capabilities/ccip/ccipevm/tokendata_test.go @@ -0,0 +1,73 @@ +package ccipevm + +import ( + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" +) + +func Test_EVMTokenDataEncoder(t *testing.T) { + var empty usdcAttestationPayload + encoder := NewEVMTokenDataEncoder() + + //https://testnet.snowtrace.io/tx/0xeeb0ad6b26bacd1570a9361724a36e338f4aacf1170dec64399220b7483b7eed/eventlog?chainid=43113 + //https://iris-api-sandbox.circle.com/v1/attestations/0x69fb1b419d648cf6c9512acad303746dc85af3b864af81985c76764aba60bf6b + realMessage, err := cciptypes.NewBytesFromString("0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f8000000000000000100000006000000000004ac0d000000000000000000000000eb08f243e5d3fcff26a9e38ae5520a669f4019d00000000000000000000000009f3b8679c73c2fef8b59b4f3444d4e156fb70aa5000000000000000000000000c08835adf4884e51ff076066706e407506826d9d000000000000000000000000000000005425890298aed601595a70ab815c96711a31bc650000000000000000000000004f32ae7f112c26b109357785e5c66dc5d747fbce00000000000000000000000000000000000000000000000000000000000000640000000000000000000000007a4d8f8c18762d362e64b411d7490fba112811cd0000000000000000") + require.NoError(t, err) + realAttestation, err := cciptypes.NewBytesFromString("0xee466fbd340596aa56e3e40d249869573e4008d84d795b4f2c3cba8649083d08653d38190d0df7e0ee12ae685df2f806d100a03b3716ab1ff2013c7201f1c2d01c9af959b55a4b52dbd0319eed69ce9ace25259830e0b1bff79faf0c9c5d1b5e6d6304e824d657db38f802bcff3e97d0bd30f2ffc62b62381f52c1668ceaa5a73a1b") + require.NoError(t, err) + + tt := []struct { + name string + message []byte + attestation []byte + }{ + { + name: "empty both fields", + message: nil, + attestation: []byte{}, + }, + { + name: "empty attestation", + message: []byte("message"), + attestation: nil, + }, + { + name: "both attestation and message are set", + message: realMessage, + attestation: realAttestation, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + got, err := encoder.EncodeUSDC(tests.Context(t), tc.message, tc.attestation) + require.NoError(t, err) + + decoded, err := abihelpers.ABIDecode(empty.AbiString(), got) + require.NoError(t, err) + + converted := abi.ConvertType(decoded[0], &empty) + casted, ok := converted.(*usdcAttestationPayload) + require.True(t, ok) + + if tc.message == nil { + require.Empty(t, casted.Message) + } else { + require.Equal(t, tc.message, casted.Message) + } + + if tc.attestation == nil { + require.Empty(t, casted.Attestation) + } else { + require.Equal(t, tc.attestation, casted.Attestation) + } + }) + } +} diff --git a/core/capabilities/ccip/configs/evm/chain_writer.go b/core/capabilities/ccip/configs/evm/chain_writer.go index 6d3b73c6f5c..f88bfce937b 100644 --- a/core/capabilities/ccip/configs/evm/chain_writer.go +++ b/core/capabilities/ccip/configs/evm/chain_writer.go @@ -1,51 +1,50 @@ package evm import ( - "encoding/json" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) var ( - offrampABI = evmtypes.MustGetABI(evm_2_evm_multi_offramp.EVM2EVMMultiOffRampABI) + offrampABI = evmtypes.MustGetABI(offramp.OffRampABI) ) -func MustChainWriterConfig( - fromAddress common.Address, - maxGasPrice *assets.Wei, - commitGasLimit, - execBatchGasLimit uint64, -) []byte { - rawConfig := ChainWriterConfigRaw(fromAddress, maxGasPrice, commitGasLimit, execBatchGasLimit) - encoded, err := json.Marshal(rawConfig) - if err != nil { - panic(fmt.Errorf("failed to marshal ChainWriterConfig: %w", err)) - } - - return encoded -} - // ChainWriterConfigRaw returns a ChainWriterConfig that can be used to transmit commit and execute reports. func ChainWriterConfigRaw( fromAddress common.Address, maxGasPrice *assets.Wei, commitGasLimit, execBatchGasLimit uint64, -) evmrelaytypes.ChainWriterConfig { +) (evmrelaytypes.ChainWriterConfig, error) { + if fromAddress == common.HexToAddress("0x0") { + return evmrelaytypes.ChainWriterConfig{}, fmt.Errorf("fromAddress cannot be zero") + } + if maxGasPrice == nil { + return evmrelaytypes.ChainWriterConfig{}, fmt.Errorf("maxGasPrice cannot be nil") + } + if maxGasPrice.Cmp(assets.NewWeiI(0)) <= 0 { + return evmrelaytypes.ChainWriterConfig{}, fmt.Errorf("maxGasPrice must be greater than zero") + } + if commitGasLimit == 0 { + return evmrelaytypes.ChainWriterConfig{}, fmt.Errorf("commitGasLimit must be greater than zero") + } + if execBatchGasLimit == 0 { + return evmrelaytypes.ChainWriterConfig{}, fmt.Errorf("execBatchGasLimit must be greater than zero") + } + return evmrelaytypes.ChainWriterConfig{ Contracts: map[string]*evmrelaytypes.ContractConfig{ consts.ContractNameOffRamp: { - ContractABI: evm_2_evm_multi_offramp.EVM2EVMMultiOffRampABI, + ContractABI: offramp.OffRampABI, Configs: map[string]*evmrelaytypes.ChainWriterDefinition{ consts.MethodCommit: { ChainSpecificName: mustGetMethodName("commit", offrampABI), @@ -60,9 +59,8 @@ func ChainWriterConfigRaw( }, }, }, - SendStrategy: txmgr.NewSendEveryStrategy(), - MaxGasPrice: maxGasPrice, - } + MaxGasPrice: maxGasPrice, + }, nil } // mustGetMethodName panics if the method name is not found in the provided ABI. diff --git a/core/capabilities/ccip/configs/evm/chain_writer_test.go b/core/capabilities/ccip/configs/evm/chain_writer_test.go new file mode 100644 index 00000000000..e24863866cc --- /dev/null +++ b/core/capabilities/ccip/configs/evm/chain_writer_test.go @@ -0,0 +1,103 @@ +package evm_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" +) + +func TestChainWriterConfigRaw(t *testing.T) { + tests := []struct { + name string + fromAddress common.Address + maxGasPrice *assets.Wei + commitGasLimit uint64 + execBatchGasLimit uint64 + expectedError string + }{ + { + name: "valid input", + fromAddress: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"), + maxGasPrice: assets.NewWeiI(1000000000), + commitGasLimit: 21000, + execBatchGasLimit: 42000, + expectedError: "", + }, + { + name: "zero fromAddress", + fromAddress: common.HexToAddress("0x0"), + maxGasPrice: assets.NewWeiI(1000000000), + commitGasLimit: 21000, + execBatchGasLimit: 42000, + expectedError: "fromAddress cannot be zero", + }, + { + name: "nil maxGasPrice", + fromAddress: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"), + maxGasPrice: nil, + commitGasLimit: 21000, + execBatchGasLimit: 42000, + expectedError: "maxGasPrice cannot be nil", + }, + { + name: "zero maxGasPrice", + fromAddress: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"), + maxGasPrice: assets.NewWeiI(0), + commitGasLimit: 21000, + execBatchGasLimit: 42000, + expectedError: "maxGasPrice must be greater than zero", + }, + { + name: "negative maxGasPrice", + fromAddress: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"), + maxGasPrice: assets.NewWeiI(-1), + commitGasLimit: 21000, + execBatchGasLimit: 42000, + expectedError: "maxGasPrice must be greater than zero", + }, + { + name: "zero commitGasLimit", + fromAddress: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"), + maxGasPrice: assets.NewWeiI(1000000000), + commitGasLimit: 0, + execBatchGasLimit: 42000, + expectedError: "commitGasLimit must be greater than zero", + }, + { + name: "zero execBatchGasLimit", + fromAddress: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"), + maxGasPrice: assets.NewWeiI(1000000000), + commitGasLimit: 21000, + execBatchGasLimit: 0, + expectedError: "execBatchGasLimit must be greater than zero", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config, err := evm.ChainWriterConfigRaw(tt.fromAddress, tt.maxGasPrice, tt.commitGasLimit, tt.execBatchGasLimit) + if tt.expectedError != "" { + assert.EqualError(t, err, tt.expectedError) + } else { + assert.NoError(t, err) + assert.Equal(t, + tt.fromAddress, + config.Contracts[consts.ContractNameOffRamp].Configs[consts.MethodCommit].FromAddress) + assert.Equal(t, + tt.commitGasLimit, + config.Contracts[consts.ContractNameOffRamp].Configs[consts.MethodCommit].GasLimit) + assert.Equal(t, + tt.execBatchGasLimit, + config.Contracts[consts.ContractNameOffRamp].Configs[consts.MethodExecute].GasLimit) + assert.Equal(t, + tt.maxGasPrice, + config.MaxGasPrice) + } + }) + } +} diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go index 085729690d5..c7f25ab97e0 100644 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ b/core/capabilities/ccip/configs/evm/contract_reader.go @@ -6,208 +6,338 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" + "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/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/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" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) var ( - onrampABI = evmtypes.MustGetABI(evm_2_evm_multi_onramp.EVM2EVMMultiOnRampABI) - capabilitiesRegsitryABI = evmtypes.MustGetABI(kcr.CapabilitiesRegistryABI) - ccipConfigABI = evmtypes.MustGetABI(ccip_config.CCIPConfigABI) - priceRegistryABI = evmtypes.MustGetABI(price_registry.PriceRegistryABI) + onrampABI = evmtypes.MustGetABI(onramp.OnRampABI) + capabilitiesRegistryABI = evmtypes.MustGetABI(kcr.CapabilitiesRegistryABI) + ccipHomeABI = evmtypes.MustGetABI(ccip_home.CCIPHomeABI) + feeQuoterABI = evmtypes.MustGetABI(fee_quoter.FeeQuoterABI) + nonceManagerABI = evmtypes.MustGetABI(nonce_manager.NonceManagerABI) + priceFeedABI = evmtypes.MustGetABI(aggregator_v3_interface.AggregatorV3InterfaceABI) + rmnRemoteABI = evmtypes.MustGetABI(rmn_remote.RMNRemoteABI) + rmnHomeABI = evmtypes.MustGetABI(rmn_home.RMNHomeABI) + routerABI = evmtypes.MustGetABI(router.RouterABI) ) -// MustSourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. -// The configuration is marshaled into JSON so that it can be passed to the relayer NewContractReader() method. -func MustSourceReaderConfig() []byte { - rawConfig := SourceReaderConfig() - encoded, err := json.Marshal(rawConfig) - if err != nil { - panic(fmt.Errorf("failed to marshal ChainReaderConfig into JSON: %w", err)) - } - - return encoded -} - -// MustDestReaderConfig returns a ChainReaderConfig that can be used to read from the offramp. -// The configuration is marshaled into JSON so that it can be passed to the relayer NewContractReader() method. -func MustDestReaderConfig() []byte { - rawConfig := DestReaderConfig() - encoded, err := json.Marshal(rawConfig) - if err != nil { - panic(fmt.Errorf("failed to marshal ChainReaderConfig into JSON: %w", err)) +func MergeReaderConfigs(configs ...evmrelaytypes.ChainReaderConfig) evmrelaytypes.ChainReaderConfig { + allContracts := make(map[string]evmrelaytypes.ChainContractReader) + for _, c := range configs { + for contractName, contractReader := range c.Contracts { + allContracts[contractName] = contractReader + } } - return encoded + return evmrelaytypes.ChainReaderConfig{Contracts: allContracts} } // DestReaderConfig returns a ChainReaderConfig that can be used to read from the offramp. -func DestReaderConfig() evmrelaytypes.ChainReaderConfig { - return evmrelaytypes.ChainReaderConfig{ - Contracts: map[string]evmrelaytypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractABI: evm_2_evm_multi_offramp.EVM2EVMMultiOffRampABI, - ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ - GenericEventNames: []string{ - mustGetEventName(consts.EventNameExecutionStateChanged, offrampABI), - mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), - }, +var DestReaderConfig = evmrelaytypes.ChainReaderConfig{ + Contracts: map[string]evmrelaytypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractABI: offramp.OffRampABI, + ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ + GenericEventNames: []string{ + mustGetEventName(consts.EventNameExecutionStateChanged, offrampABI), + mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), }, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetExecutionState: { - ChainSpecificName: mustGetMethodName("getExecutionState", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetMerkleRoot: { - ChainSpecificName: mustGetMethodName("getMerkleRoot", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameIsBlessed: { - ChainSpecificName: mustGetMethodName("isBlessed", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetLatestPriceSequenceNumber: { - ChainSpecificName: mustGetMethodName("getLatestPriceSequenceNumber", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOfframpGetStaticConfig: { - ChainSpecificName: mustGetMethodName("getStaticConfig", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOfframpGetDynamicConfig: { - ChainSpecificName: mustGetMethodName("getDynamicConfig", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetSourceChainConfig: { - ChainSpecificName: mustGetMethodName("getSourceChainConfig", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.EventNameCommitReportAccepted: { - ChainSpecificName: mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), - ReadType: evmrelaytypes.Event, - }, - consts.EventNameExecutionStateChanged: { - ChainSpecificName: mustGetEventName(consts.EventNameExecutionStateChanged, offrampABI), - ReadType: evmrelaytypes.Event, - }, + }, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetExecutionState: { + ChainSpecificName: mustGetMethodName("getExecutionState", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetMerkleRoot: { + ChainSpecificName: mustGetMethodName("getMerkleRoot", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetLatestPriceSequenceNumber: { + ChainSpecificName: mustGetMethodName("getLatestPriceSequenceNumber", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameOffRampGetStaticConfig: { + ChainSpecificName: mustGetMethodName("getStaticConfig", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameOffRampGetDynamicConfig: { + ChainSpecificName: mustGetMethodName("getDynamicConfig", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetSourceChainConfig: { + ChainSpecificName: mustGetMethodName("getSourceChainConfig", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameOffRampGetAllSourceChainConfigs: { + ChainSpecificName: mustGetMethodName("getAllSourceChainConfigs", offrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.EventNameCommitReportAccepted: { + ChainSpecificName: mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), + ReadType: evmrelaytypes.Event, + }, + consts.EventNameExecutionStateChanged: { + ChainSpecificName: mustGetEventName(consts.EventNameExecutionStateChanged, offrampABI), + ReadType: evmrelaytypes.Event, }, }, }, - } + consts.ContractNameNonceManager: { + ContractABI: nonce_manager.NonceManagerABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetInboundNonce: { + ChainSpecificName: mustGetMethodName("getInboundNonce", nonceManagerABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetOutboundNonce: { + ChainSpecificName: mustGetMethodName("getOutboundNonce", nonceManagerABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, + consts.ContractNameFeeQuoter: { + ContractABI: fee_quoter.FeeQuoterABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameFeeQuoterGetStaticConfig: { + ChainSpecificName: mustGetMethodName("getStaticConfig", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameFeeQuoterGetTokenPrices: { + ChainSpecificName: mustGetMethodName("getTokenPrices", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameFeeQuoterGetTokenPrice: { + ChainSpecificName: mustGetMethodName("getTokenPrice", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetFeePriceUpdate: { + ChainSpecificName: mustGetMethodName("getDestinationChainGasPrice", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetDestChainConfig: { + ChainSpecificName: mustGetMethodName("getDestChainConfig", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetPremiumMultiplierWeiPerEth: { + ChainSpecificName: mustGetMethodName("getPremiumMultiplierWeiPerEth", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetTokenTransferFeeConfig: { + ChainSpecificName: mustGetMethodName("getTokenTransferFeeConfig", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameProcessMessageArgs: { + ChainSpecificName: mustGetMethodName("processMessageArgs", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetValidatedTokenPrice: { + ChainSpecificName: mustGetMethodName("getValidatedTokenPrice", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetFeeTokens: { + ChainSpecificName: mustGetMethodName("getFeeTokens", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, + consts.ContractNameRMNRemote: { + ContractABI: rmn_remote.RMNRemoteABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetVersionedConfig: { + ChainSpecificName: mustGetMethodName("getVersionedConfig", rmnRemoteABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetReportDigestHeader: { + ChainSpecificName: mustGetMethodName("getReportDigestHeader", rmnRemoteABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, + consts.ContractNameRouter: { + ContractABI: router.RouterABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameRouterGetWrappedNative: { + ChainSpecificName: mustGetMethodName("getWrappedNative", routerABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, + }, } // SourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. -func SourceReaderConfig() evmrelaytypes.ChainReaderConfig { - return evmrelaytypes.ChainReaderConfig{ - Contracts: map[string]evmrelaytypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractABI: evm_2_evm_multi_onramp.EVM2EVMMultiOnRampABI, - ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ - GenericEventNames: []string{ - mustGetEventName(consts.EventNameCCIPSendRequested, onrampABI), - }, +var SourceReaderConfig = evmrelaytypes.ChainReaderConfig{ + Contracts: map[string]evmrelaytypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractABI: onramp.OnRampABI, + ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ + GenericEventNames: []string{ + consts.EventNameCCIPMessageSent, }, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - // all "{external|public} view" functions in the onramp except for getFee and getPoolBySourceToken are here. - // getFee is not expected to get called offchain and is only called by end-user contracts. - consts.MethodNameGetExpectedNextSequenceNumber: { - ChainSpecificName: mustGetMethodName("getExpectedNextSequenceNumber", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOnrampGetStaticConfig: { - ChainSpecificName: mustGetMethodName("getStaticConfig", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOnrampGetDynamicConfig: { - ChainSpecificName: mustGetMethodName("getDynamicConfig", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.EventNameCCIPSendRequested: { - ChainSpecificName: mustGetEventName(consts.EventNameCCIPSendRequested, onrampABI), - ReadType: evmrelaytypes.Event, - EventDefinitions: &evmrelaytypes.EventDefinitions{ - GenericDataWordNames: map[string]uint8{ - consts.EventAttributeSequenceNumber: 5, - }, - }, - }, + }, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + // all "{external|public} view" functions in the onramp except for getFee and getPoolBySourceToken are here. + // getFee is not expected to get called offchain and is only called by end-user contracts. + consts.MethodNameGetExpectedNextSequenceNumber: { + ChainSpecificName: mustGetMethodName("getExpectedNextSequenceNumber", onrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.EventNameCCIPMessageSent: { + ChainSpecificName: mustGetEventName("CCIPMessageSent", onrampABI), + ReadType: evmrelaytypes.Event, + }, + consts.MethodNameOnRampGetStaticConfig: { + ChainSpecificName: mustGetMethodName("getStaticConfig", onrampABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameOnRampGetDynamicConfig: { + ChainSpecificName: mustGetMethodName("getDynamicConfig", onrampABI), + ReadType: evmrelaytypes.Method, + }, + // TODO: swap with const. + consts.MethodNameOnRampGetDestChainConfig: { + ChainSpecificName: mustGetMethodName("getDestChainConfig", onrampABI), + ReadType: evmrelaytypes.Method, }, }, - consts.ContractNamePriceRegistry: { - ContractABI: price_registry.PriceRegistryABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - // TODO: update with the consts from https://github.com/smartcontractkit/chainlink-ccip/pull/39 - // in a followup. - "GetStaticConfig": { - ChainSpecificName: mustGetMethodName("getStaticConfig", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetDestChainConfig": { - ChainSpecificName: mustGetMethodName("getDestChainConfig", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetPremiumMultiplierWeiPerEth": { - ChainSpecificName: mustGetMethodName("getPremiumMultiplierWeiPerEth", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetTokenTransferFeeConfig": { - ChainSpecificName: mustGetMethodName("getTokenTransferFeeConfig", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "ProcessMessageArgs": { - ChainSpecificName: mustGetMethodName("processMessageArgs", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "ValidatePoolReturnData": { - ChainSpecificName: mustGetMethodName("validatePoolReturnData", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetValidatedTokenPrice": { - ChainSpecificName: mustGetMethodName("getValidatedTokenPrice", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetFeeTokens": { - ChainSpecificName: mustGetMethodName("getFeeTokens", priceRegistryABI), - ReadType: evmrelaytypes.Method, + }, + consts.ContractNameRouter: { + ContractABI: router.RouterABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameRouterGetWrappedNative: { + ChainSpecificName: mustGetMethodName("getWrappedNative", routerABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, + consts.ContractNameFeeQuoter: { + ContractABI: fee_quoter.FeeQuoterABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameFeeQuoterGetTokenPrices: { + ChainSpecificName: mustGetMethodName("getTokenPrices", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameFeeQuoterGetTokenPrice: { + ChainSpecificName: mustGetMethodName("getTokenPrice", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetFeePriceUpdate: { + ChainSpecificName: mustGetMethodName("getDestinationChainGasPrice", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetDestChainConfig: { + ChainSpecificName: mustGetMethodName("getDestChainConfig", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + consts.MethodNameGetFeeTokens: { + ChainSpecificName: mustGetMethodName("getFeeTokens", feeQuoterABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, + }, +} + +// FeedReaderConfig provides a ChainReaderConfig that can be used to read from a price feed +// that is deployed on-chain. +var FeedReaderConfig = evmrelaytypes.ChainReaderConfig{ + Contracts: map[string]evmrelaytypes.ChainContractReader{ + consts.ContractNamePriceAggregator: { + ContractABI: aggregator_v3_interface.AggregatorV3InterfaceABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetLatestRoundData: { + ChainSpecificName: mustGetMethodName(consts.MethodNameGetLatestRoundData, priceFeedABI), + }, + consts.MethodNameGetDecimals: { + ChainSpecificName: mustGetMethodName(consts.MethodNameGetDecimals, priceFeedABI), + }, + }, + }, + }, +} + +var USDCReaderConfig = evmrelaytypes.ChainReaderConfig{ + Contracts: map[string]evmrelaytypes.ChainContractReader{ + consts.ContractNameCCTPMessageTransmitter: { + ContractABI: MessageTransmitterABI, + ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCCTPMessageSent}, + }, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.EventNameCCTPMessageSent: { + ChainSpecificName: consts.EventNameCCTPMessageSent, + ReadType: evmrelaytypes.Event, + EventDefinitions: &evmrelaytypes.EventDefinitions{ + GenericDataWordDetails: map[string]evmrelaytypes.DataWordDetail{ + consts.CCTPMessageSentValue: { + Name: consts.CCTPMessageSentValue, + // Filtering by the 3rd word (indexing starts from 0) so it's ptr(2) + Index: ptr(2), + Type: "bytes32", + }, + }, }, }, }, }, - } + }, } // HomeChainReaderConfigRaw returns a ChainReaderConfig that can be used to read from the home chain. -func HomeChainReaderConfigRaw() evmrelaytypes.ChainReaderConfig { - return evmrelaytypes.ChainReaderConfig{ - Contracts: map[string]evmrelaytypes.ChainContractReader{ - consts.ContractNameCapabilitiesRegistry: { - ContractABI: kcr.CapabilitiesRegistryABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetCapability: { - ChainSpecificName: mustGetMethodName("getCapability", capabilitiesRegsitryABI), - }, +var HomeChainReaderConfigRaw = evmrelaytypes.ChainReaderConfig{ + Contracts: map[string]evmrelaytypes.ChainContractReader{ + consts.ContractNameCapabilitiesRegistry: { + ContractABI: kcr.CapabilitiesRegistryABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetCapability: { + ChainSpecificName: mustGetMethodName("getCapability", capabilitiesRegistryABI), }, }, - consts.ContractNameCCIPConfig: { - ContractABI: ccip_config.CCIPConfigABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetAllChainConfigs: { - ChainSpecificName: mustGetMethodName("getAllChainConfigs", ccipConfigABI), - }, - consts.MethodNameGetOCRConfig: { - ChainSpecificName: mustGetMethodName("getOCRConfig", ccipConfigABI), - }, + }, + consts.ContractNameCCIPConfig: { + ContractABI: ccip_home.CCIPHomeABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetAllChainConfigs: { + ChainSpecificName: mustGetMethodName("getAllChainConfigs", ccipHomeABI), + }, + consts.MethodNameGetOCRConfig: { + ChainSpecificName: mustGetMethodName("getAllConfigs", ccipHomeABI), + }, + }, + }, + consts.ContractNameRMNHome: { + ContractABI: rmn_home.RMNHomeABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetAllConfigs: { + ChainSpecificName: mustGetMethodName("getAllConfigs", rmnHomeABI), }, }, }, + }, +} + +var HomeChainReaderConfig = mustMarshal(HomeChainReaderConfigRaw) + +func mustMarshal(v interface{}) []byte { + b, err := json.Marshal(v) + if err != nil { + panic(err) } + return b } func mustGetEventName(event string, tabi abi.ABI) string { @@ -217,3 +347,7 @@ func mustGetEventName(event string, tabi abi.ABI) string { } return e.Name } + +func ptr[T any](v T) *T { + return &v +} diff --git a/core/capabilities/ccip/configs/evm/init_test.go b/core/capabilities/ccip/configs/evm/init_test.go new file mode 100644 index 00000000000..010592b6dc9 --- /dev/null +++ b/core/capabilities/ccip/configs/evm/init_test.go @@ -0,0 +1,12 @@ +package evm + +import ( + "testing" +) + +func TestConfig(t *testing.T) { + // Config is created during initialization, the following functions may panic: + // MustGetABI + // mustGetMethodName + // mustGetEventName +} diff --git a/core/capabilities/ccip/configs/evm/usdc.go b/core/capabilities/ccip/configs/evm/usdc.go new file mode 100644 index 00000000000..47efcdc25f5 --- /dev/null +++ b/core/capabilities/ccip/configs/evm/usdc.go @@ -0,0 +1,26 @@ +package evm + +import ( + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +var ( + // We need only ABI part of the contract that describes the event structure + // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L41 + MessageTransmitterABI = `[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "MessageSent", + "type": "event" + } + ]` + _ = evmtypes.MustGetABI(MessageTransmitterABI) +) diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 187ae0c5811..e3397969fab 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -3,27 +3,37 @@ package ccip import ( "context" "fmt" + "math/big" + "strconv" "time" + "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" configsevm "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/launcher" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/oraclecreator" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + chainsel "github.com/smartcontractkit/chain-selectors" + + 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" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -34,7 +44,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -48,13 +57,13 @@ type Delegate struct { lggr logger.Logger registrarConfig plugins.RegistrarConfig pipelineRunner pipeline.Runner - chains legacyevm.LegacyChainContainer relayers RelayGetter keystore keystore.Master ds sqlutil.DataSource peerWrapper *ocrcommon.SingletonPeerWrapper monitoringEndpointGen telemetry.MonitoringEndpointGenerator capabilityConfig config.Capabilities + evmConfigs toml.EVMConfigs isNewlyCreatedJob bool } @@ -63,25 +72,25 @@ func NewDelegate( lggr logger.Logger, registrarConfig plugins.RegistrarConfig, pipelineRunner pipeline.Runner, - chains legacyevm.LegacyChainContainer, relayers RelayGetter, keystore keystore.Master, ds sqlutil.DataSource, peerWrapper *ocrcommon.SingletonPeerWrapper, monitoringEndpointGen telemetry.MonitoringEndpointGenerator, capabilityConfig config.Capabilities, + evmConfigs toml.EVMConfigs, ) *Delegate { return &Delegate{ lggr: lggr, registrarConfig: registrarConfig, pipelineRunner: pipelineRunner, - chains: chains, relayers: relayers, ds: ds, keystore: keystore, peerWrapper: peerWrapper, monitoringEndpointGen: monitoringEndpointGen, capabilityConfig: capabilityConfig, + evmConfigs: evmConfigs, } } @@ -109,7 +118,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services cfg := d.capabilityConfig rid := cfg.ExternalRegistry().RelayID() - relayer, err := d.relayers.Get(rid) + homeChainRelayer, err := d.relayers.Get(rid) if err != nil { return nil, fmt.Errorf("could not fetch relayer %s configured for capabilities registry: %w", rid, err) } @@ -118,12 +127,12 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services func() (p2ptypes.PeerID, error) { return p2ptypes.PeerID(p2pID.PeerID()), nil }, - relayer, + homeChainRelayer, cfg.ExternalRegistry().Address(), registrysyncer.NewORM(d.ds, d.lggr), ) if err != nil { - return nil, fmt.Errorf("could not configure syncer: %w", err) + return nil, fmt.Errorf("could not create registry syncer: %w", err) } ocrKeys, err := d.getOCRKeys(spec.CCIPSpec.OCRKeyBundleIDs) @@ -131,7 +140,11 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services return nil, err } - transmitterKeys, err := d.getTransmitterKeys(ctx, d.chains) + allRelayers, err := d.relayers.GetIDToRelayerMap() + if err != nil { + return nil, fmt.Errorf("could not fetch all relayers: %w", err) + } + transmitterKeys, err := d.getTransmitterKeys(ctx, maps.Keys(allRelayers)) if err != nil { return nil, err } @@ -145,9 +158,9 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services // since all queries are scoped by config digest. ocrDB := ocr2.NewDB(d.ds, spec.ID, 0, d.lggr) - homeChainContractReader, err := d.getHomeChainContractReader( + homeChainContractReader, ccipConfigBinding, err := d.getHomeChainContractReader( ctx, - d.chains, + homeChainRelayer, spec.CCIPSpec.CapabilityLabelledName, spec.CCIPSpec.CapabilityVersion) if err != nil { @@ -158,23 +171,51 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services homeChainContractReader, d.lggr.Named("HomeChainReader"), 100*time.Millisecond, + ccipConfigBinding, ) - oracleCreator := oraclecreator.New( - ocrKeys, - transmitterKeys, - d.chains, - d.peerWrapper, - spec.ExternalJobID, - spec.ID, - d.isNewlyCreatedJob, - spec.CCIPSpec.PluginConfig, - ocrDB, - d.lggr, - d.monitoringEndpointGen, - bootstrapperLocators, - hcr, - ) + // get the chain selector for the home chain + homeChainChainID, err := strconv.ParseUint(d.capabilityConfig.ExternalRegistry().RelayID().ChainID, 10, 64) + if err != nil { + return nil, fmt.Errorf("failed to parse chain ID %s: %w", d.capabilityConfig.ExternalRegistry().RelayID().ChainID, err) + } + homeChainChainSelector, err := chainsel.SelectorFromChainId(homeChainChainID) + if err != nil { + return nil, fmt.Errorf("failed to get chain selector from chain ID %d", homeChainChainID) + } + + // if bootstrappers are provided we assume that the node is a plugin oracle. + // the reason for this is that bootstrap oracles do not need to be aware + // of other bootstrap oracles. however, plugin oracles, at least initially, + // must be aware of available bootstrappers. + var oracleCreator cctypes.OracleCreator + if len(spec.CCIPSpec.P2PV2Bootstrappers) > 0 { + oracleCreator = oraclecreator.NewPluginOracleCreator( + ocrKeys, + transmitterKeys, + allRelayers, + d.peerWrapper, + spec.ExternalJobID, + spec.ID, + d.isNewlyCreatedJob, + spec.CCIPSpec.PluginConfig, + ocrDB, + d.lggr, + d.monitoringEndpointGen, + bootstrapperLocators, + hcr, + cciptypes.ChainSelector(homeChainChainSelector), + d.evmConfigs, + ) + } else { + oracleCreator = oraclecreator.NewBootstrapOracleCreator( + d.peerWrapper, + bootstrapperLocators, + ocrDB, + d.monitoringEndpointGen, + d.lggr, + ) + } capabilityID := fmt.Sprintf("%s@%s", spec.CCIPSpec.CapabilityLabelledName, spec.CCIPSpec.CapabilityVersion) capLauncher := launcher.New( @@ -182,14 +223,15 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services ragep2ptypes.PeerID(p2pID.PeerID()), d.lggr, hcr, - oracleCreator, 12*time.Second, + oracleCreator, ) // register the capability launcher with the registry syncer registrySyncer.AddLauncher(capLauncher) return []job.ServiceCtx{ + homeChainContractReader, registrySyncer, hcr, capLauncher, @@ -227,13 +269,17 @@ func (d *Delegate) getOCRKeys(ocrKeyBundleIDs job.JSONConfig) (map[string]ocr2ke return ocrKeys, nil } -func (d *Delegate) getTransmitterKeys(ctx context.Context, chains legacyevm.LegacyChainContainer) (map[types.RelayID][]string, error) { +func (d *Delegate) getTransmitterKeys(ctx context.Context, relayIDs []types.RelayID) (map[types.RelayID][]string, error) { transmitterKeys := make(map[types.RelayID][]string) - for _, chain := range chains.Slice() { - relayID := types.NewRelayID(relay.NetworkEVM, chain.ID().String()) - ethKeys, err2 := d.keystore.Eth().EnabledAddressesForChain(ctx, chain.ID()) - if err2 != nil { - return nil, fmt.Errorf("error getting enabled addresses for chain: %s %w", chain.ID().String(), err2) + for _, relayID := range relayIDs { + chainID, ok := new(big.Int).SetString(relayID.ChainID, 10) + if !ok { + return nil, fmt.Errorf("error parsing chain ID, expected big int: %s", relayID.ChainID) + } + + ethKeys, err := d.keystore.Eth().EnabledAddressesForChain(ctx, chainID) + if err != nil { + return nil, fmt.Errorf("error getting enabled addresses for chain: %s %w", chainID.String(), err) } transmitterKeys[relayID] = func() (r []string) { @@ -248,76 +294,67 @@ func (d *Delegate) getTransmitterKeys(ctx context.Context, chains legacyevm.Lega func (d *Delegate) getHomeChainContractReader( ctx context.Context, - chains legacyevm.LegacyChainContainer, + homeChainRelayer loop.Relayer, capabilityLabelledName, capabilityVersion string, -) (types.ContractReader, error) { - // home chain is where the capability registry is deployed, - // which should be set correctly in toml config. - homeChainRelayID := d.capabilityConfig.ExternalRegistry().RelayID() - homeChain, err := chains.Get(homeChainRelayID.ChainID) - if err != nil { - return nil, fmt.Errorf("home chain relayer not found, chain id: %s, err: %w", homeChainRelayID.String(), err) - } - - reader, err := evm.NewChainReaderService( - context.Background(), - d.lggr, - homeChain.LogPoller(), - homeChain.HeadTracker(), - homeChain.Client(), - configsevm.HomeChainReaderConfigRaw(), - ) +) (types.ContractReader, types.BoundContract, error) { + reader, err := homeChainRelayer.NewContractReader(ctx, configsevm.HomeChainReaderConfig) if err != nil { - return nil, fmt.Errorf("failed to create home chain contract reader: %w", err) + return nil, types.BoundContract{}, fmt.Errorf("failed to create home chain contract reader: %w", err) } - reader, err = bindReader(ctx, reader, d.capabilityConfig.ExternalRegistry().Address(), capabilityLabelledName, capabilityVersion) + reader, ccipConfigBinding, err := bindReader(ctx, reader, d.capabilityConfig.ExternalRegistry().Address(), capabilityLabelledName, capabilityVersion) if err != nil { - return nil, fmt.Errorf("failed to bind home chain contract reader: %w", err) + return nil, types.BoundContract{}, fmt.Errorf("failed to bind home chain contract reader: %w", err) } - return reader, nil + return reader, ccipConfigBinding, nil } func bindReader(ctx context.Context, reader types.ContractReader, capRegAddress, capabilityLabelledName, - capabilityVersion string) (types.ContractReader, error) { - err := reader.Bind(ctx, []types.BoundContract{ - { - Address: capRegAddress, - Name: consts.ContractNameCapabilitiesRegistry, - }, - }) + capabilityVersion string, +) (boundReader types.ContractReader, ccipConfigBinding types.BoundContract, err error) { + boundContract := types.BoundContract{ + Address: capRegAddress, + Name: consts.ContractNameCapabilitiesRegistry, + } + + err = reader.Bind(ctx, []types.BoundContract{boundContract}) if err != nil { - return nil, fmt.Errorf("failed to bind home chain contract reader: %w", err) + return nil, types.BoundContract{}, fmt.Errorf("failed to bind home chain contract reader: %w", err) } hid, err := common.HashedCapabilityID(capabilityLabelledName, capabilityVersion) if err != nil { - return nil, fmt.Errorf("failed to hash capability id: %w", err) + return nil, types.BoundContract{}, fmt.Errorf("failed to hash capability id: %w", err) } var ccipCapabilityInfo kcr.CapabilitiesRegistryCapabilityInfo - err = reader.GetLatestValue(ctx, consts.ContractNameCapabilitiesRegistry, consts.MethodNameGetCapability, primitives.Unconfirmed, map[string]any{ - "hashedId": hid, - }, &ccipCapabilityInfo) + err = reader.GetLatestValue( + ctx, + boundContract.ReadIdentifier(consts.MethodNameGetCapability), + primitives.Unconfirmed, + map[string]any{ + "hashedId": hid, + }, + &ccipCapabilityInfo, + ) if err != nil { - return nil, fmt.Errorf("failed to get CCIP capability info from chain reader: %w", err) + return nil, types.BoundContract{}, fmt.Errorf("failed to get CCIP capability info from chain reader: %w", err) } // bind the ccip capability configuration contract - err = reader.Bind(ctx, []types.BoundContract{ - { - Address: ccipCapabilityInfo.ConfigurationContract.String(), - Name: consts.ContractNameCCIPConfig, - }, - }) + ccipConfigBinding = types.BoundContract{ + Address: ccipCapabilityInfo.ConfigurationContract.String(), + Name: consts.ContractNameCCIPConfig, + } + err = reader.Bind(ctx, []types.BoundContract{ccipConfigBinding}) if err != nil { - return nil, fmt.Errorf("failed to bind CCIP capability configuration contract: %w", err) + return nil, types.BoundContract{}, fmt.Errorf("failed to bind CCIP capability configuration contract: %w", err) } - return reader, nil + return reader, ccipConfigBinding, nil } diff --git a/core/capabilities/ccip/launcher/bluegreen.go b/core/capabilities/ccip/launcher/bluegreen.go deleted file mode 100644 index 62458466291..00000000000 --- a/core/capabilities/ccip/launcher/bluegreen.go +++ /dev/null @@ -1,178 +0,0 @@ -package launcher - -import ( - "fmt" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "go.uber.org/multierr" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" -) - -// blueGreenDeployment represents a blue-green deployment of OCR instances. -type blueGreenDeployment struct { - // blue is the blue OCR instance. - // blue must always be present. - blue cctypes.CCIPOracle - - // bootstrapBlue is the bootstrap node of the blue OCR instance. - // Only a subset of the DON will be running bootstrap instances, - // so this may be nil. - bootstrapBlue cctypes.CCIPOracle - - // green is the green OCR instance. - // green may or may not be present. - // green must never be present if blue is not present. - // TODO: should we enforce this invariant somehow? - green cctypes.CCIPOracle - - // bootstrapGreen is the bootstrap node of the green OCR instance. - // Only a subset of the DON will be running bootstrap instances, - // so this may be nil, even when green is not nil. - bootstrapGreen cctypes.CCIPOracle -} - -// ccipDeployment represents blue-green deployments of both commit and exec -// OCR instances. -type ccipDeployment struct { - commit blueGreenDeployment - exec blueGreenDeployment -} - -// Close shuts down all OCR instances in the deployment. -func (c *ccipDeployment) Close() error { - var err error - - // shutdown blue commit instances. - err = multierr.Append(err, c.commit.blue.Close()) - if c.commit.bootstrapBlue != nil { - err = multierr.Append(err, c.commit.bootstrapBlue.Close()) - } - - // shutdown green commit instances. - if c.commit.green != nil { - err = multierr.Append(err, c.commit.green.Close()) - } - if c.commit.bootstrapGreen != nil { - err = multierr.Append(err, c.commit.bootstrapGreen.Close()) - } - - // shutdown blue exec instances. - err = multierr.Append(err, c.exec.blue.Close()) - if c.exec.bootstrapBlue != nil { - err = multierr.Append(err, c.exec.bootstrapBlue.Close()) - } - - // shutdown green exec instances. - if c.exec.green != nil { - err = multierr.Append(err, c.exec.green.Close()) - } - if c.exec.bootstrapGreen != nil { - err = multierr.Append(err, c.exec.bootstrapGreen.Close()) - } - - return err -} - -// StartBlue starts the blue OCR instances. -func (c *ccipDeployment) StartBlue() error { - var err error - - err = multierr.Append(err, c.commit.blue.Start()) - if c.commit.bootstrapBlue != nil { - err = multierr.Append(err, c.commit.bootstrapBlue.Start()) - } - err = multierr.Append(err, c.exec.blue.Start()) - if c.exec.bootstrapBlue != nil { - err = multierr.Append(err, c.exec.bootstrapBlue.Start()) - } - - return err -} - -// CloseBlue shuts down the blue OCR instances. -func (c *ccipDeployment) CloseBlue() error { - var err error - - err = multierr.Append(err, c.commit.blue.Close()) - if c.commit.bootstrapBlue != nil { - err = multierr.Append(err, c.commit.bootstrapBlue.Close()) - } - err = multierr.Append(err, c.exec.blue.Close()) - if c.exec.bootstrapBlue != nil { - err = multierr.Append(err, c.exec.bootstrapBlue.Close()) - } - - return err -} - -// HandleBlueGreen handles the blue-green deployment transition. -// prevDeployment is the previous deployment state. -// there are two possible cases: -// -// 1. both blue and green are present in prevDeployment, but only blue is present in c. -// this is a promotion of green to blue, so we need to shut down the blue deployment -// and make green the new blue. In this case green is already running, so there's no -// need to start it. However, we need to shut down the blue deployment. -// -// 2. only blue is present in prevDeployment, both blue and green are present in c. -// In this case, blue is already running, so there's no need to start it. We need to -// start green. -func (c *ccipDeployment) HandleBlueGreen(prevDeployment *ccipDeployment) error { - if prevDeployment == nil { - return fmt.Errorf("previous deployment is nil") - } - - var err error - if prevDeployment.commit.green != nil && c.commit.green == nil { - err = multierr.Append(err, prevDeployment.commit.blue.Close()) - if prevDeployment.commit.bootstrapBlue != nil { - err = multierr.Append(err, prevDeployment.commit.bootstrapBlue.Close()) - } - } else if prevDeployment.commit.green == nil && c.commit.green != nil { - err = multierr.Append(err, c.commit.green.Start()) - if c.commit.bootstrapGreen != nil { - err = multierr.Append(err, c.commit.bootstrapGreen.Start()) - } - } else { - return fmt.Errorf("invalid blue-green deployment transition") - } - - if prevDeployment.exec.green != nil && c.exec.green == nil { - err = multierr.Append(err, prevDeployment.exec.blue.Close()) - if prevDeployment.exec.bootstrapBlue != nil { - err = multierr.Append(err, prevDeployment.exec.bootstrapBlue.Close()) - } - } else if prevDeployment.exec.green == nil && c.exec.green != nil { - err = multierr.Append(err, c.exec.green.Start()) - if c.exec.bootstrapGreen != nil { - err = multierr.Append(err, c.exec.bootstrapGreen.Start()) - } - } else { - return fmt.Errorf("invalid blue-green deployment transition") - } - - return err -} - -// HasGreenInstance returns true if the deployment has a green instance for the -// given plugin type. -func (c *ccipDeployment) HasGreenInstance(pluginType cctypes.PluginType) bool { - switch pluginType { - case cctypes.PluginTypeCCIPCommit: - return c.commit.green != nil - case cctypes.PluginTypeCCIPExec: - return c.exec.green != nil - default: - return false - } -} - -func isNewGreenInstance(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { - return len(ocrConfigs) == 2 && !prevDeployment.HasGreenInstance(pluginType) -} - -func isPromotion(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { - return len(ocrConfigs) == 1 && prevDeployment.HasGreenInstance(pluginType) -} diff --git a/core/capabilities/ccip/launcher/bluegreen_test.go b/core/capabilities/ccip/launcher/bluegreen_test.go deleted file mode 100644 index 9fd71a0cb44..00000000000 --- a/core/capabilities/ccip/launcher/bluegreen_test.go +++ /dev/null @@ -1,1043 +0,0 @@ -package launcher - -import ( - "errors" - "testing" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - mocktypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" - - "github.com/stretchr/testify/require" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" -) - -func Test_ccipDeployment_Close(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - commitGreenBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - execGreenBootstrap *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors, blue only", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "no errors, blue and green", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitGreen.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execGreen.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitGreen.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "bootstrap blue also closed", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "bootstrap green also closed", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(nil).Once() - args.commitGreen.On("Close").Return(nil).Once() - args.commitGreenBootstrap.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(nil).Once() - args.execGreen.On("Close").Return(nil).Once() - args.execGreenBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.commitGreen.AssertExpectations(t) - args.commitGreenBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - args.execGreenBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.args.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.args.execBlue, - }, - } - if tt.args.commitGreen != nil { - c.commit.green = tt.args.commitGreen - } - if tt.args.commitBlueBootstrap != nil { - c.commit.bootstrapBlue = tt.args.commitBlueBootstrap - } - if tt.args.commitGreenBootstrap != nil { - c.commit.bootstrapGreen = tt.args.commitGreenBootstrap - } - - if tt.args.execGreen != nil { - c.exec.green = tt.args.execGreen - } - if tt.args.execBlueBootstrap != nil { - c.exec.bootstrapBlue = tt.args.execBlueBootstrap - } - if tt.args.execGreenBootstrap != nil { - c.exec.bootstrapGreen = tt.args.execGreenBootstrap - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.Close() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_StartBlue(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors, no bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "no errors, with bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.commitBlueBootstrap.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - args.execBlueBootstrap.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(errors.New("failed")).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on commit blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.commitBlueBootstrap.On("Start").Return(errors.New("failed")).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - args.execBlueBootstrap.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.args.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.args.execBlue, - }, - } - if tt.args.commitBlueBootstrap != nil { - c.commit.bootstrapBlue = tt.args.commitBlueBootstrap - } - if tt.args.execBlueBootstrap != nil { - c.exec.bootstrapBlue = tt.args.execBlueBootstrap - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.StartBlue() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_CloseBlue(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors, no bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "no errors, with bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on commit blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.args.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.args.execBlue, - }, - } - if tt.args.commitBlueBootstrap != nil { - c.commit.bootstrapBlue = tt.args.commitBlueBootstrap - } - if tt.args.execBlueBootstrap != nil { - c.exec.bootstrapBlue = tt.args.execBlueBootstrap - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.CloseBlue() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { - require.Error(t, (&ccipDeployment{}).HandleBlueGreen(nil)) -} - -func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - commitGreenBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - execGreenBootstrap *mocktypes.CCIPOracle - } - tests := []struct { - name string - argsPrevDeployment args - argsFutureDeployment args - expect func(t *testing.T, args args, argsPrevDeployment args) - asserts func(t *testing.T, args args, argsPrevDeployment args) - wantErr bool - }{ - { - name: "promotion blue to green, no bootstrap", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() - argsPrevDeployment.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.AssertExpectations(t) - argsPrevDeployment.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "promotion blue to green, with bootstrap", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() - argsPrevDeployment.commitBlueBootstrap.On("Close").Return(nil).Once() - argsPrevDeployment.execBlue.On("Close").Return(nil).Once() - argsPrevDeployment.execBlueBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.AssertExpectations(t) - argsPrevDeployment.commitBlueBootstrap.AssertExpectations(t) - argsPrevDeployment.execBlue.AssertExpectations(t) - argsPrevDeployment.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "new green deployment, no bootstrap", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "new green deployment, with bootstrap", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.commitGreenBootstrap.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(nil).Once() - args.execGreenBootstrap.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.commitGreenBootstrap.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - args.execGreenBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit green start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(errors.New("failed")).Once() - args.execGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec green start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on commit green bootstrap start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.commitGreenBootstrap.On("Start").Return(errors.New("failed")).Once() - args.execGreen.On("Start").Return(nil).Once() - args.execGreenBootstrap.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.commitGreenBootstrap.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - args.execGreenBootstrap.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "invalid blue-green deployment transition commit: both prev and future deployment have green", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) {}, - asserts: func(t *testing.T, args args, argsPrevDeployment args) {}, - wantErr: true, - }, - { - name: "invalid blue-green deployment transition exec: both prev and future deployment have green", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - futDeployment := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.argsFutureDeployment.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.argsFutureDeployment.execBlue, - }, - } - if tt.argsFutureDeployment.commitGreen != nil { - futDeployment.commit.green = tt.argsFutureDeployment.commitGreen - } - if tt.argsFutureDeployment.commitBlueBootstrap != nil { - futDeployment.commit.bootstrapBlue = tt.argsFutureDeployment.commitBlueBootstrap - } - if tt.argsFutureDeployment.commitGreenBootstrap != nil { - futDeployment.commit.bootstrapGreen = tt.argsFutureDeployment.commitGreenBootstrap - } - if tt.argsFutureDeployment.execGreen != nil { - futDeployment.exec.green = tt.argsFutureDeployment.execGreen - } - if tt.argsFutureDeployment.execBlueBootstrap != nil { - futDeployment.exec.bootstrapBlue = tt.argsFutureDeployment.execBlueBootstrap - } - if tt.argsFutureDeployment.execGreenBootstrap != nil { - futDeployment.exec.bootstrapGreen = tt.argsFutureDeployment.execGreenBootstrap - } - - prevDeployment := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.argsPrevDeployment.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.argsPrevDeployment.execBlue, - }, - } - if tt.argsPrevDeployment.commitGreen != nil { - prevDeployment.commit.green = tt.argsPrevDeployment.commitGreen - } - if tt.argsPrevDeployment.commitBlueBootstrap != nil { - prevDeployment.commit.bootstrapBlue = tt.argsPrevDeployment.commitBlueBootstrap - } - if tt.argsPrevDeployment.commitGreenBootstrap != nil { - prevDeployment.commit.bootstrapGreen = tt.argsPrevDeployment.commitGreenBootstrap - } - if tt.argsPrevDeployment.execGreen != nil { - prevDeployment.exec.green = tt.argsPrevDeployment.execGreen - } - if tt.argsPrevDeployment.execBlueBootstrap != nil { - prevDeployment.exec.bootstrapBlue = tt.argsPrevDeployment.execBlueBootstrap - } - if tt.argsPrevDeployment.execGreenBootstrap != nil { - prevDeployment.exec.bootstrapGreen = tt.argsPrevDeployment.execGreenBootstrap - } - - tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) - defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) - err := futDeployment.HandleBlueGreen(prevDeployment) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_isNewGreenInstance(t *testing.T) { - type args struct { - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - prevDeployment ccipDeployment - } - tests := []struct { - name string - args args - want bool - }{ - { - "prev deployment only blue", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - }, - true, - }, - { - "green -> blue promotion", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := isNewGreenInstance(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment) - require.Equal(t, tt.want, got) - }) - } -} - -func Test_isPromotion(t *testing.T) { - type args struct { - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - prevDeployment ccipDeployment - } - tests := []struct { - name string - args args - want bool - }{ - { - "prev deployment only blue", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - }, - false, - }, - { - "green -> blue promotion", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - }, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := isPromotion(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment); got != tt.want { - t.Errorf("isPromotion() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_ccipDeployment_HasGreenInstance(t *testing.T) { - type fields struct { - commit blueGreenDeployment - exec blueGreenDeployment - } - type args struct { - pluginType cctypes.PluginType - } - tests := []struct { - name string - fields fields - args args - want bool - }{ - { - "commit green present", - fields{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - }, - true, - }, - { - "commit green not present", - fields{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - }, - false, - }, - { - "exec green present", - fields{ - exec: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPExec, - }, - true, - }, - { - "exec green not present", - fields{ - exec: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPExec, - }, - false, - }, - { - "invalid plugin type", - fields{}, - args{ - pluginType: cctypes.PluginType(100), - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{} - if tt.fields.commit.blue != nil { - c.commit.blue = tt.fields.commit.blue - } - if tt.fields.commit.green != nil { - c.commit.green = tt.fields.commit.green - } - if tt.fields.exec.blue != nil { - c.exec.blue = tt.fields.exec.blue - } - if tt.fields.exec.green != nil { - c.exec.green = tt.fields.exec.green - } - got := c.HasGreenInstance(tt.args.pluginType) - require.Equal(t, tt.want, got) - }) - } -} diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go new file mode 100644 index 00000000000..bed6296549e --- /dev/null +++ b/core/capabilities/ccip/launcher/deployment.go @@ -0,0 +1,131 @@ +package launcher + +import ( + "fmt" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + + "go.uber.org/multierr" + + ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" +) + +// activeCandidateDeployment represents a active-candidate deployment of OCR instances. +type activeCandidateDeployment struct { + // active is the active OCR instance. + // active must always be present. + active cctypes.CCIPOracle + + // candidate is the candidate OCR instance. + // candidate may or may not be present. + // candidate must never be present if active is not present. + candidate cctypes.CCIPOracle +} + +// ccipDeployment represents active-candidate deployments of both commit and exec +// OCR instances. +type ccipDeployment struct { + commit activeCandidateDeployment + exec activeCandidateDeployment +} + +// Close shuts down all OCR instances in the deployment. +func (c *ccipDeployment) Close() error { + var err error + + // shutdown active commit instance. + err = multierr.Append(err, c.commit.active.Close()) + + // shutdown candidate commit instance. + if c.commit.candidate != nil { + err = multierr.Append(err, c.commit.candidate.Close()) + } + + // shutdown active exec instance. + err = multierr.Append(err, c.exec.active.Close()) + + // shutdown candidate exec instance. + if c.exec.candidate != nil { + err = multierr.Append(err, c.exec.candidate.Close()) + } + + return err +} + +// StartActive starts the active OCR instances. +func (c *ccipDeployment) StartActive() error { + var err error + + err = multierr.Append(err, c.commit.active.Start()) + err = multierr.Append(err, c.exec.active.Start()) + + return err +} + +// CloseActive shuts down the active OCR instances. +func (c *ccipDeployment) CloseActive() error { + var err error + + err = multierr.Append(err, c.commit.active.Close()) + err = multierr.Append(err, c.exec.active.Close()) + + return err +} + +// TransitionDeployment handles the active-candidate deployment transition. +// prevDeployment is the previous deployment state. +// there are two possible cases: +// +// 1. both active and candidate are present in prevDeployment, but only active is present in c. +// this is a promotion of candidate to active, so we need to shut down the active deployment +// and make candidate the new active. In this case candidate is already running, so there's no +// need to start it. However, we need to shut down the active deployment. +// +// 2. only active is present in prevDeployment, both active and candidate are present in c. +// In this case, active is already running, so there's no need to start it. We need to +// start candidate. +func (c *ccipDeployment) TransitionDeployment(prevDeployment *ccipDeployment) error { + if prevDeployment == nil { + return fmt.Errorf("previous deployment is nil") + } + + var err error + if prevDeployment.commit.candidate != nil && c.commit.candidate == nil { + err = multierr.Append(err, prevDeployment.commit.active.Close()) + } else if prevDeployment.commit.candidate == nil && c.commit.candidate != nil { + err = multierr.Append(err, c.commit.candidate.Start()) + } else { + return fmt.Errorf("invalid active-candidate deployment transition") + } + + if prevDeployment.exec.candidate != nil && c.exec.candidate == nil { + err = multierr.Append(err, prevDeployment.exec.active.Close()) + } else if prevDeployment.exec.candidate == nil && c.exec.candidate != nil { + err = multierr.Append(err, c.exec.candidate.Start()) + } else { + return fmt.Errorf("invalid active-candidate deployment transition") + } + + return err +} + +// HasCandidateInstance returns true if the deployment has a candidate instance for the +// given plugin type. +func (c *ccipDeployment) HasCandidateInstance(pluginType cctypes.PluginType) bool { + switch pluginType { + case cctypes.PluginTypeCCIPCommit: + return c.commit.candidate != nil + case cctypes.PluginTypeCCIPExec: + return c.exec.candidate != nil + default: + return false + } +} + +func isNewCandidateInstance(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { + return len(ocrConfigs) == 2 && !prevDeployment.HasCandidateInstance(pluginType) +} + +func isPromotion(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { + return len(ocrConfigs) == 1 && prevDeployment.HasCandidateInstance(pluginType) +} diff --git a/core/capabilities/ccip/launcher/deployment_test.go b/core/capabilities/ccip/launcher/deployment_test.go new file mode 100644 index 00000000000..a7fa8888314 --- /dev/null +++ b/core/capabilities/ccip/launcher/deployment_test.go @@ -0,0 +1,681 @@ +package launcher + +import ( + "errors" + "testing" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + mocktypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" + + "github.com/stretchr/testify/require" + + ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" +) + +func Test_ccipDeployment_Close(t *testing.T) { + type args struct { + commitBlue *mocktypes.CCIPOracle + commitGreen *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle + execGreen *mocktypes.CCIPOracle + } + tests := []struct { + name string + args args + expect func(t *testing.T, args args) + asserts func(t *testing.T, args args) + wantErr bool + }{ + { + name: "no errors, active only", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Close").Return(nil).Once() + args.execBlue.On("Close").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: false, + }, + { + name: "no errors, active and candidate", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Close").Return(nil).Once() + args.commitGreen.On("Close").Return(nil).Once() + args.execBlue.On("Close").Return(nil).Once() + args.execGreen.On("Close").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.commitGreen.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + args.execGreen.AssertExpectations(t) + }, + wantErr: false, + }, + { + name: "error on commit active", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Close").Return(errors.New("failed")).Once() + args.execBlue.On("Close").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &ccipDeployment{ + commit: activeCandidateDeployment{ + active: tt.args.commitBlue, + }, + exec: activeCandidateDeployment{ + active: tt.args.execBlue, + }, + } + if tt.args.commitGreen != nil { + c.commit.candidate = tt.args.commitGreen + } + + if tt.args.execGreen != nil { + c.exec.candidate = tt.args.execGreen + } + + tt.expect(t, tt.args) + defer tt.asserts(t, tt.args) + err := c.Close() + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_ccipDeployment_StartBlue(t *testing.T) { + type args struct { + commitBlue *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle + } + tests := []struct { + name string + args args + expect func(t *testing.T, args args) + asserts func(t *testing.T, args args) + wantErr bool + }{ + { + name: "no errors", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Start").Return(nil).Once() + args.execBlue.On("Start").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: false, + }, + { + name: "error on commit active", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Start").Return(errors.New("failed")).Once() + args.execBlue.On("Start").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: true, + }, + { + name: "error on exec active", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Start").Return(nil).Once() + args.execBlue.On("Start").Return(errors.New("failed")).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &ccipDeployment{ + commit: activeCandidateDeployment{ + active: tt.args.commitBlue, + }, + exec: activeCandidateDeployment{ + active: tt.args.execBlue, + }, + } + + tt.expect(t, tt.args) + defer tt.asserts(t, tt.args) + err := c.StartActive() + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_ccipDeployment_CloseBlue(t *testing.T) { + type args struct { + commitBlue *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle + } + tests := []struct { + name string + args args + expect func(t *testing.T, args args) + asserts func(t *testing.T, args args) + wantErr bool + }{ + { + name: "no errors", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Close").Return(nil).Once() + args.execBlue.On("Close").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: false, + }, + { + name: "error on commit active", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Close").Return(errors.New("failed")).Once() + args.execBlue.On("Close").Return(nil).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: true, + }, + { + name: "error on exec active", + args: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args) { + args.commitBlue.On("Close").Return(nil).Once() + args.execBlue.On("Close").Return(errors.New("failed")).Once() + }, + asserts: func(t *testing.T, args args) { + args.commitBlue.AssertExpectations(t) + args.execBlue.AssertExpectations(t) + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &ccipDeployment{ + commit: activeCandidateDeployment{ + active: tt.args.commitBlue, + }, + exec: activeCandidateDeployment{ + active: tt.args.execBlue, + }, + } + + tt.expect(t, tt.args) + defer tt.asserts(t, tt.args) + err := c.CloseActive() + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { + require.Error(t, (&ccipDeployment{}).TransitionDeployment(nil)) +} + +func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { + type args struct { + commitBlue *mocktypes.CCIPOracle + commitGreen *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle + execGreen *mocktypes.CCIPOracle + } + tests := []struct { + name string + argsPrevDeployment args + argsFutureDeployment args + expect func(t *testing.T, args args, argsPrevDeployment args) + asserts func(t *testing.T, args args, argsPrevDeployment args) + wantErr bool + }{ + { + name: "promotion active to candidate", + argsPrevDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + argsFutureDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, + }, + expect: func(t *testing.T, args args, argsPrevDeployment args) { + argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() + argsPrevDeployment.execBlue.On("Close").Return(nil).Once() + }, + asserts: func(t *testing.T, args args, argsPrevDeployment args) { + argsPrevDeployment.commitBlue.AssertExpectations(t) + argsPrevDeployment.execBlue.AssertExpectations(t) + }, + wantErr: false, + }, + { + name: "new candidate deployment", + argsPrevDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, + }, + argsFutureDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.On("Start").Return(nil).Once() + args.execGreen.On("Start").Return(nil).Once() + }, + asserts: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.AssertExpectations(t) + args.execGreen.AssertExpectations(t) + }, + wantErr: false, + }, + { + name: "error on commit candidate start", + argsPrevDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, + }, + argsFutureDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.On("Start").Return(errors.New("failed")).Once() + args.execGreen.On("Start").Return(nil).Once() + }, + asserts: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.AssertExpectations(t) + args.execGreen.AssertExpectations(t) + }, + wantErr: true, + }, + { + name: "error on exec candidate start", + argsPrevDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, + }, + argsFutureDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.On("Start").Return(nil).Once() + args.execGreen.On("Start").Return(errors.New("failed")).Once() + }, + asserts: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.AssertExpectations(t) + args.execGreen.AssertExpectations(t) + }, + wantErr: true, + }, + { + name: "invalid active-candidate deployment transition commit: both prev and future deployment have candidate", + argsPrevDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + argsFutureDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args, argsPrevDeployment args) {}, + asserts: func(t *testing.T, args args, argsPrevDeployment args) {}, + wantErr: true, + }, + { + name: "invalid active-candidate deployment transition exec: both prev and future exec deployment have candidate", + argsPrevDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + argsFutureDeployment: args{ + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: mocktypes.NewCCIPOracle(t), + }, + expect: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.On("Start").Return(nil).Once() + }, + asserts: func(t *testing.T, args args, argsPrevDeployment args) { + args.commitGreen.AssertExpectations(t) + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + futDeployment := &ccipDeployment{ + commit: activeCandidateDeployment{ + active: tt.argsFutureDeployment.commitBlue, + }, + exec: activeCandidateDeployment{ + active: tt.argsFutureDeployment.execBlue, + }, + } + if tt.argsFutureDeployment.commitGreen != nil { + futDeployment.commit.candidate = tt.argsFutureDeployment.commitGreen + } + if tt.argsFutureDeployment.execGreen != nil { + futDeployment.exec.candidate = tt.argsFutureDeployment.execGreen + } + + prevDeployment := &ccipDeployment{ + commit: activeCandidateDeployment{ + active: tt.argsPrevDeployment.commitBlue, + }, + exec: activeCandidateDeployment{ + active: tt.argsPrevDeployment.execBlue, + }, + } + if tt.argsPrevDeployment.commitGreen != nil { + prevDeployment.commit.candidate = tt.argsPrevDeployment.commitGreen + } + if tt.argsPrevDeployment.execGreen != nil { + prevDeployment.exec.candidate = tt.argsPrevDeployment.execGreen + } + + tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) + defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) + err := futDeployment.TransitionDeployment(prevDeployment) + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_isNewGreenInstance(t *testing.T) { + type args struct { + pluginType cctypes.PluginType + ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta + prevDeployment ccipDeployment + } + tests := []struct { + name string + args args + want bool + }{ + { + "prev deployment only active", + args{ + pluginType: cctypes.PluginTypeCCIPCommit, + ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ + {}, {}, + }, + prevDeployment: ccipDeployment{ + commit: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + }, + }, + }, + true, + }, + { + "candidate -> active promotion", + args{ + pluginType: cctypes.PluginTypeCCIPCommit, + ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ + {}, + }, + prevDeployment: ccipDeployment{ + commit: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + candidate: mocktypes.NewCCIPOracle(t), + }, + }, + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := isNewCandidateInstance(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment) + require.Equal(t, tt.want, got) + }) + } +} + +func Test_isPromotion(t *testing.T) { + type args struct { + pluginType cctypes.PluginType + ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta + prevDeployment ccipDeployment + } + tests := []struct { + name string + args args + want bool + }{ + { + "prev deployment only active", + args{ + pluginType: cctypes.PluginTypeCCIPCommit, + ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ + {}, {}, + }, + prevDeployment: ccipDeployment{ + commit: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + }, + }, + }, + false, + }, + { + "candidate -> active promotion", + args{ + pluginType: cctypes.PluginTypeCCIPCommit, + ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ + {}, + }, + prevDeployment: ccipDeployment{ + commit: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + candidate: mocktypes.NewCCIPOracle(t), + }, + }, + }, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isPromotion(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment); got != tt.want { + t.Errorf("isPromotion() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_ccipDeployment_HasGreenInstance(t *testing.T) { + type fields struct { + commit activeCandidateDeployment + exec activeCandidateDeployment + } + type args struct { + pluginType cctypes.PluginType + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + "commit candidate present", + fields{ + commit: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + candidate: mocktypes.NewCCIPOracle(t), + }, + }, + args{ + pluginType: cctypes.PluginTypeCCIPCommit, + }, + true, + }, + { + "commit candidate not present", + fields{ + commit: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + }, + }, + args{ + pluginType: cctypes.PluginTypeCCIPCommit, + }, + false, + }, + { + "exec candidate present", + fields{ + exec: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + candidate: mocktypes.NewCCIPOracle(t), + }, + }, + args{ + pluginType: cctypes.PluginTypeCCIPExec, + }, + true, + }, + { + "exec candidate not present", + fields{ + exec: activeCandidateDeployment{ + active: mocktypes.NewCCIPOracle(t), + }, + }, + args{ + pluginType: cctypes.PluginTypeCCIPExec, + }, + false, + }, + { + "invalid plugin type", + fields{}, + args{ + pluginType: cctypes.PluginType(100), + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &ccipDeployment{} + if tt.fields.commit.active != nil { + c.commit.active = tt.fields.commit.active + } + if tt.fields.commit.candidate != nil { + c.commit.candidate = tt.fields.commit.candidate + } + if tt.fields.exec.active != nil { + c.exec.active = tt.fields.exec.active + } + if tt.fields.exec.candidate != nil { + c.exec.candidate = tt.fields.exec.candidate + } + got := c.HasCandidateInstance(tt.args.pluginType) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/core/capabilities/ccip/launcher/diff.go b/core/capabilities/ccip/launcher/diff.go index e631ea9fc78..de429deedc1 100644 --- a/core/capabilities/ccip/launcher/diff.go +++ b/core/capabilities/ccip/launcher/diff.go @@ -126,16 +126,3 @@ func isMemberOfDON(don registrysyncer.DON, p2pID ragep2ptypes.PeerID) bool { } return false } - -// isMemberOfBootstrapSubcommittee returns true if and only if the given p2pID is a member of the given bootstrap subcommittee. -func isMemberOfBootstrapSubcommittee( - bootstrapP2PIDs [][32]byte, - p2pID ragep2ptypes.PeerID, -) bool { - for _, bootstrapID := range bootstrapP2PIDs { - if bootstrapID == p2pID { - return true - } - } - return false -} diff --git a/core/capabilities/ccip/launcher/diff_test.go b/core/capabilities/ccip/launcher/diff_test.go index f3dd327fe91..a098bf816ab 100644 --- a/core/capabilities/ccip/launcher/diff_test.go +++ b/core/capabilities/ccip/launcher/diff_test.go @@ -38,7 +38,7 @@ func Test_diff(t *testing.T) { IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ 1: defaultRegistryDon, }, - IDsToNodes: map[types.PeerID]kcr.CapabilitiesRegistryNodeInfo{}, + IDsToNodes: map[types.PeerID]kcr.INodeInfoProviderNodeInfo{}, }, newState: registrysyncer.LocalRegistry{ IDsToCapabilities: map[string]registrysyncer.Capability{ @@ -47,7 +47,7 @@ func Test_diff(t *testing.T) { IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ 1: defaultRegistryDon, }, - IDsToNodes: map[types.PeerID]kcr.CapabilitiesRegistryNodeInfo{}, + IDsToNodes: map[types.PeerID]kcr.INodeInfoProviderNodeInfo{}, }, }, want: diffResult{ @@ -341,12 +341,3 @@ func Test_isMemberOfDON(t *testing.T) { require.True(t, isMemberOfDON(don, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()))) require.False(t, isMemberOfDON(don, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(5)).PeerID()))) } - -func Test_isMemberOfBootstrapSubcommittee(t *testing.T) { - var bootstrapKeys [][32]byte - for i := range [4]struct{}{} { - bootstrapKeys = append(bootstrapKeys, p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(i+1))).PeerID()) - } - require.True(t, isMemberOfBootstrapSubcommittee(bootstrapKeys, p2pID1)) - require.False(t, isMemberOfBootstrapSubcommittee(bootstrapKeys, getP2PID(5))) -} diff --git a/core/capabilities/ccip/launcher/integration_test.go b/core/capabilities/ccip/launcher/integration_test.go index 7973316b31d..f0a4bd46bb3 100644 --- a/core/capabilities/ccip/launcher/integration_test.go +++ b/core/capabilities/ccip/launcher/integration_test.go @@ -4,15 +4,16 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" it "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" - "github.com/onsi/gomega" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" @@ -42,17 +43,16 @@ func TestIntegration_Launcher(t *testing.T) { ) require.NoError(t, err) - hcr := uni.HomeChainReader - + oracleCreator := &oracleCreatorPrints{ + t: t, + } launcher := New( it.CapabilityID, p2pIDs[0], logger.TestLogger(t), - hcr, - &oracleCreatorPrints{ - t: t, - }, + uni.HomeChainReader, 1*time.Second, + oracleCreator, ) regSyncer.AddLauncher(launcher) @@ -61,15 +61,22 @@ func TestIntegration_Launcher(t *testing.T) { t.Cleanup(func() { require.NoError(t, regSyncer.Close()) }) t.Cleanup(func() { require.NoError(t, launcher.Close()) }) - chainAConf := it.SetupConfigInfo(it.ChainA, p2pIDs, it.FChainA, []byte("ChainA")) - chainBConf := it.SetupConfigInfo(it.ChainB, p2pIDs[1:], it.FChainB, []byte("ChainB")) - chainCConf := it.SetupConfigInfo(it.ChainC, p2pIDs[2:], it.FChainC, []byte("ChainC")) - inputConfig := []ccip_config.CCIPConfigTypesChainConfigInfo{ + encodedChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1000), + DAGasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1_000_000), + OptimisticConfirmations: 1, + }) + require.NoError(t, err) + + chainAConf := it.SetupConfigInfo(it.ChainA, p2pIDs, it.FChainA, encodedChainConfig) + chainBConf := it.SetupConfigInfo(it.ChainB, p2pIDs[1:], it.FChainB, encodedChainConfig) + chainCConf := it.SetupConfigInfo(it.ChainC, p2pIDs[2:], it.FChainC, encodedChainConfig) + inputConfig := []ccip_home.CCIPHomeChainConfigArgs{ chainAConf, chainBConf, chainCConf, } - _, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig) + _, err = uni.CCIPHome.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig) require.NoError(t, err) uni.Backend.Commit() @@ -80,12 +87,11 @@ func TestIntegration_Launcher(t *testing.T) { ccipCapabilityID, it.ChainA, it.FChainA, - p2pIDs[1], p2pIDs) - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { return len(launcher.runningDONIDs()) == 1 - }, testutils.WaitTimeout(t), testutils.TestInterval).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), testutils.TestInterval) } type oraclePrints struct { @@ -109,14 +115,14 @@ type oracleCreatorPrints struct { t *testing.T } -func (o *oracleCreatorPrints) CreatePluginOracle(pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { +func (o *oracleCreatorPrints) Create(_ uint32, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { + pluginType := cctypes.PluginType(config.Config.PluginType) o.t.Logf("Creating plugin oracle (pluginType: %s) with config %+v\n", pluginType, config) return &oraclePrints{pluginType: pluginType, config: config, t: o.t}, nil } -func (o *oracleCreatorPrints) CreateBootstrapOracle(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - o.t.Logf("Creating bootstrap oracle with config %+v\n", config) - return &oraclePrints{pluginType: cctypes.PluginTypeCCIPCommit, config: config, isBootstrap: true, t: o.t}, nil +func (o *oracleCreatorPrints) Type() cctypes.OracleType { + return cctypes.OracleTypePlugin } var _ cctypes.OracleCreator = &oracleCreatorPrints{} diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 2dc1a1954f5..bc351291dc0 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -33,8 +33,8 @@ func New( p2pID ragep2ptypes.PeerID, lggr logger.Logger, homeChainReader ccipreader.HomeChain, - oracleCreator cctypes.OracleCreator, tickInterval time.Duration, + oracleCreator cctypes.OracleCreator, ) *launcher { return &launcher{ p2pID: p2pID, @@ -43,12 +43,12 @@ func New( homeChainReader: homeChainReader, regState: registrysyncer.LocalRegistry{ IDsToDONs: make(map[registrysyncer.DonID]registrysyncer.DON), - IDsToNodes: make(map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo), + IDsToNodes: make(map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo), IDsToCapabilities: make(map[string]registrysyncer.Capability), }, - oracleCreator: oracleCreator, dons: make(map[registrysyncer.DonID]*ccipDeployment), tickInterval: tickInterval, + oracleCreator: oracleCreator, } } @@ -194,16 +194,16 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]registrysyncer l.lggr, l.p2pID, l.homeChainReader, - l.oracleCreator, *prevDeployment, don, + l.oracleCreator, ) if err != nil { return err } - if err := futDeployment.HandleBlueGreen(prevDeployment); err != nil { - // TODO: how to handle a failed blue-green deployment? - return fmt.Errorf("failed to handle blue-green deployment for CCIP DON %d: %w", donID, err) + if err := futDeployment.TransitionDeployment(prevDeployment); err != nil { + // TODO: how to handle a failed active-candidate deployment? + return fmt.Errorf("failed to handle active-candidate deployment for CCIP DON %d: %w", donID, err) } // update state. @@ -225,8 +225,8 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO l.lggr, l.p2pID, l.homeChainReader, - l.oracleCreator, don, + l.oracleCreator, ) if err != nil { return err @@ -236,9 +236,9 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]registrysyncer.DO continue } - if err := dep.StartBlue(); err != nil { - if shutdownErr := dep.CloseBlue(); shutdownErr != nil { - l.lggr.Errorw("Failed to shutdown blue instance after failed start", "donId", donID, "err", shutdownErr) + if err := dep.StartActive(); err != nil { + if shutdownErr := dep.CloseActive(); shutdownErr != nil { + l.lggr.Errorw("Failed to shutdown active instance after failed start", "donId", donID, "err", shutdownErr) } return fmt.Errorf("failed to start oracles for CCIP DON %d: %w", donID, err) } @@ -278,15 +278,15 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce // updateDON is a pure function that handles the case where a DON in the capability registry // has received a new configuration. -// It returns a new ccipDeployment that can then be used to perform the blue-green deployment, +// It returns a new ccipDeployment that can then be used to perform the active-candidate deployment, // based on the previous deployment. func updateDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, homeChainReader ccipreader.HomeChain, - oracleCreator cctypes.OracleCreator, prevDeployment ccipDeployment, don registrysyncer.DON, + oracleCreator cctypes.OracleCreator, ) (futDeployment *ccipDeployment, err error) { if !isMemberOfDON(don, p2pID) { lggr.Infow("Not a member of this DON, skipping", "donId", don.ID, "p2pId", p2pID.String()) @@ -306,14 +306,14 @@ func updateDON( don.ID, err) } - commitBgd, err := createFutureBlueGreenDeployment(prevDeployment, commitOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPCommit) + commitBgd, err := createFutureActiveCandidateDeployment(don.ID, prevDeployment, commitOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPCommit) if err != nil { - return nil, fmt.Errorf("failed to create future blue-green deployment for CCIP commit plugin: %w, don id: %d", err, don.ID) + return nil, fmt.Errorf("failed to create future active-candidate deployment for CCIP commit plugin: %w, don id: %d", err, don.ID) } - execBgd, err := createFutureBlueGreenDeployment(prevDeployment, execOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPExec) + execBgd, err := createFutureActiveCandidateDeployment(don.ID, prevDeployment, execOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPExec) if err != nil { - return nil, fmt.Errorf("failed to create future blue-green deployment for CCIP exec plugin: %w, don id: %d", err, don.ID) + return nil, fmt.Errorf("failed to create future active-candidate deployment for CCIP exec plugin: %w, don id: %d", err, don.ID) } return &ccipDeployment{ @@ -323,49 +323,45 @@ func updateDON( } // valid cases: -// a) len(ocrConfigs) == 2 && !prevDeployment.HasGreenInstance(pluginType): this is a new green instance. -// b) len(ocrConfigs) == 1 && prevDeployment.HasGreenInstance(): this is a promotion of green->blue. +// a) len(ocrConfigs) == 2 && !prevDeployment.HasCandidateInstance(pluginType): this is a new candidate instance. +// b) len(ocrConfigs) == 1 && prevDeployment.HasCandidateInstance(): this is a promotion of candidate->active. // All other cases are invalid. This is enforced in the ccip config contract. -func createFutureBlueGreenDeployment( +func createFutureActiveCandidateDeployment( + donID uint32, prevDeployment ccipDeployment, ocrConfigs []ccipreader.OCR3ConfigWithMeta, oracleCreator cctypes.OracleCreator, pluginType cctypes.PluginType, -) (blueGreenDeployment, error) { - var deployment blueGreenDeployment - if isNewGreenInstance(pluginType, ocrConfigs, prevDeployment) { - // this is a new green instance. - greenOracle, err := oracleCreator.CreatePluginOracle(pluginType, cctypes.OCR3ConfigWithMeta(ocrConfigs[1])) +) (activeCandidateDeployment, error) { + var deployment activeCandidateDeployment + if isNewCandidateInstance(pluginType, ocrConfigs, prevDeployment) { + // this is a new candidate instance. + greenOracle, err := oracleCreator.Create(donID, cctypes.OCR3ConfigWithMeta(ocrConfigs[1])) if err != nil { - return blueGreenDeployment{}, fmt.Errorf("failed to create CCIP commit oracle: %w", err) + return activeCandidateDeployment{}, fmt.Errorf("failed to create CCIP commit oracle: %w", err) } - deployment.blue = prevDeployment.commit.blue - deployment.green = greenOracle + deployment.active = prevDeployment.commit.active + deployment.candidate = greenOracle } else if isPromotion(pluginType, ocrConfigs, prevDeployment) { - // this is a promotion of green->blue. - deployment.blue = prevDeployment.commit.green + // this is a promotion of candidate->active. + deployment.active = prevDeployment.commit.candidate } else { - return blueGreenDeployment{}, fmt.Errorf("invariant violation: expected 1 or 2 OCR configs for CCIP plugin (type: %d), got %d", pluginType, len(ocrConfigs)) + return activeCandidateDeployment{}, fmt.Errorf("invariant violation: expected 1 or 2 OCR configs for CCIP plugin (type: %d), got %d", pluginType, len(ocrConfigs)) } return deployment, nil } // createDON is a pure function that handles the case where a new DON is added to the capability registry. -// It returns a new ccipDeployment that can then be used to start the blue instance. +// It returns a new ccipDeployment that can then be used to start the active instance. func createDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, homeChainReader ccipreader.HomeChain, - oracleCreator cctypes.OracleCreator, don registrysyncer.DON, + oracleCreator cctypes.OracleCreator, ) (*ccipDeployment, error) { - if !isMemberOfDON(don, p2pID) { - lggr.Infow("Not a member of this DON, skipping", "donId", don.ID, "p2pId", p2pID.String()) - return nil, nil - } - // this should be a retryable error. commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.ID, uint8(cctypes.PluginTypeCCIPCommit)) if err != nil { @@ -388,45 +384,29 @@ func createDON( return nil, fmt.Errorf("expected exactly one OCR config for CCIP exec plugin (don id: %d), got %d", don.ID, len(execOCRConfigs)) } - commitOracle, commitBootstrap, err := createOracle(p2pID, oracleCreator, cctypes.PluginTypeCCIPCommit, commitOCRConfigs) + if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { + lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.ID, "p2pId", p2pID.String()) + return nil, nil + } + + // at this point we know we are either a member of the DON or a bootstrap node. + // the injected oracleCreator will create the appropriate oracle. + commitOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(commitOCRConfigs[0])) if err != nil { return nil, fmt.Errorf("failed to create CCIP commit oracle: %w", err) } - execOracle, execBootstrap, err := createOracle(p2pID, oracleCreator, cctypes.PluginTypeCCIPExec, execOCRConfigs) + execOracle, err := oracleCreator.Create(don.ID, cctypes.OCR3ConfigWithMeta(execOCRConfigs[0])) if err != nil { return nil, fmt.Errorf("failed to create CCIP exec oracle: %w", err) } return &ccipDeployment{ - commit: blueGreenDeployment{ - blue: commitOracle, - bootstrapBlue: commitBootstrap, + commit: activeCandidateDeployment{ + active: commitOracle, }, - exec: blueGreenDeployment{ - blue: execOracle, - bootstrapBlue: execBootstrap, + exec: activeCandidateDeployment{ + active: execOracle, }, }, nil } - -func createOracle( - p2pID ragep2ptypes.PeerID, - oracleCreator cctypes.OracleCreator, - pluginType cctypes.PluginType, - ocrConfigs []ccipreader.OCR3ConfigWithMeta, -) (pluginOracle, bootstrapOracle cctypes.CCIPOracle, err error) { - pluginOracle, err = oracleCreator.CreatePluginOracle(pluginType, cctypes.OCR3ConfigWithMeta(ocrConfigs[0])) - if err != nil { - return nil, nil, fmt.Errorf("failed to create CCIP plugin oracle (plugintype: %d): %w", pluginType, err) - } - - if isMemberOfBootstrapSubcommittee(ocrConfigs[0].Config.BootstrapP2PIds, p2pID) { - bootstrapOracle, err = oracleCreator.CreateBootstrapOracle(cctypes.OCR3ConfigWithMeta(ocrConfigs[0])) - if err != nil { - return nil, nil, fmt.Errorf("failed to create CCIP bootstrap oracle (plugintype: %d): %w", pluginType, err) - } - } - - return pluginOracle, bootstrapOracle, nil -} diff --git a/core/capabilities/ccip/launcher/launcher_test.go b/core/capabilities/ccip/launcher/launcher_test.go index 242dd0be248..48bdeda4cde 100644 --- a/core/capabilities/ccip/launcher/launcher_test.go +++ b/core/capabilities/ccip/launcher/launcher_test.go @@ -1,7 +1,6 @@ package launcher import ( - "errors" "math/big" "reflect" "testing" @@ -15,170 +14,94 @@ import ( ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" ) -func Test_createOracle(t *testing.T) { - var p2pKeys []ragep2ptypes.PeerID - for i := 0; i < 3; i++ { - p2pKeys = append(p2pKeys, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(i+1))).PeerID())) - } - myP2PKey := p2pKeys[0] +func Test_createDON(t *testing.T) { type args struct { - p2pID ragep2ptypes.PeerID - oracleCreator *mocks.OracleCreator - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta + lggr logger.Logger + p2pID ragep2ptypes.PeerID + homeChainReader *mocks.HomeChainReader + oracleCreator *mocks.OracleCreator + don registrysyncer.DON } tests := []struct { name string args args - expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) + expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) wantErr bool }{ { - "success, no bootstrap", + "not a member of the DON and not a bootstrap node", args{ - myP2PKey, + logger.TestLogger(t), + p2pID1, + mocks.NewHomeChainReader(t), mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { - Config: ccipreaderpkg.OCR3Config{}, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, + registrysyncer.DON{ + DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), + CapabilityConfigurations: defaultCapCfgs, }, }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - }, - false, - }, - { - "success, with bootstrap", - args{ - myP2PKey, - mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { + func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ Config: ccipreaderpkg.OCR3Config{ - BootstrapP2PIds: [][32]byte{myP2PKey}, + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), }, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - oracleCreator. - On("CreateBootstrapOracle", cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - }, - false, - }, - { - "error creating plugin oracle", - args{ - myP2PKey, - mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { - Config: ccipreaderpkg.OCR3Config{}, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(nil, errors.New("error creating oracle")) - }, - true, - }, - { - "error creating bootstrap oracle", - args{ - myP2PKey, - mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { + }}, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ Config: ccipreaderpkg.OCR3Config{ - BootstrapP2PIds: [][32]byte{myP2PKey}, + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), }, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, - }, + }}, nil) + oracleCreator.EXPECT().Type().Return(cctypes.OracleTypePlugin).Once() }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - oracleCreator. - On("CreateBootstrapOracle", cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(nil, errors.New("error creating oracle")) - }, - true, + false, }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.expect(t, tt.args, tt.args.oracleCreator) - _, _, err := createOracle(tt.args.p2pID, tt.args.oracleCreator, tt.args.pluginType, tt.args.ocrConfigs) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_createDON(t *testing.T) { - type args struct { - lggr logger.Logger - p2pID ragep2ptypes.PeerID - homeChainReader *mocks.HomeChainReader - oracleCreator *mocks.OracleCreator - don registrysyncer.DON - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) - wantErr bool - }{ { - "not a member of the DON", + "not a member of the DON but a running a bootstrap oracle creator", args{ logger.TestLogger(t), - p2pID1, + ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), mocks.NewHomeChainReader(t), mocks.NewOracleCreator(t), registrysyncer.DON{ - DON: getDON(2, []ragep2ptypes.PeerID{p2pID2}, 0), + DON: getDON(2, []ragep2ptypes.PeerID{p2pID3, p2pID4}, 0), CapabilityConfigurations: defaultCapCfgs, }, }, func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + }}, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + }}, nil) + oracleCreator.EXPECT().Type().Return(cctypes.OracleTypeBootstrap).Once() + oracleCreator.EXPECT().Create(mock.Anything, mock.Anything).Return(mocks.NewCCIPOracle(t), nil).Twice() }, false, }, { - "success, no bootstrap", + "success", args{ logger.TestLogger(t), p2pID1, @@ -189,15 +112,28 @@ func Test_createDON(t *testing.T) { func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + Nodes: getOCR3Nodes(3, 4), + }, + }}, nil) homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, mock.Anything). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + Nodes: getOCR3Nodes(3, 4), + }, + }}, nil) + + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). Return(mocks.NewCCIPOracle(t), nil) - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPExec, mock.Anything). + oracleCreator.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). Return(mocks.NewCCIPOracle(t), nil) }, false, @@ -208,7 +144,8 @@ func Test_createDON(t *testing.T) { if tt.expect != nil { tt.expect(t, tt.args, tt.args.oracleCreator, tt.args.homeChainReader) } - _, err := createDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.oracleCreator, tt.args.don) + + _, err := createDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.don, tt.args.oracleCreator) if tt.wantErr { require.Error(t, err) } else { @@ -220,6 +157,7 @@ func Test_createDON(t *testing.T) { func Test_createFutureBlueGreenDeployment(t *testing.T) { type args struct { + donID uint32 prevDeployment ccipDeployment ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta oracleCreator *mocks.OracleCreator @@ -228,20 +166,20 @@ func Test_createFutureBlueGreenDeployment(t *testing.T) { tests := []struct { name string args args - want blueGreenDeployment + want activeCandidateDeployment wantErr bool }{ // TODO: Add test cases. } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := createFutureBlueGreenDeployment(tt.args.prevDeployment, tt.args.ocrConfigs, tt.args.oracleCreator, tt.args.pluginType) + got, err := createFutureActiveCandidateDeployment(tt.args.donID, tt.args.prevDeployment, tt.args.ocrConfigs, tt.args.oracleCreator, tt.args.pluginType) if (err != nil) != tt.wantErr { - t.Errorf("createFutureBlueGreenDeployment() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("createFutureActiveCandidateDeployment() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("createFutureBlueGreenDeployment() = %v, want %v", got, tt.want) + t.Errorf("createFutureActiveCandidateDeployment() = %v, want %v", got, tt.want) } }) } @@ -266,7 +204,7 @@ func Test_updateDON(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotFutDeployment, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.oracleCreator, tt.args.prevDeployment, tt.args.don) + gotFutDeployment, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.prevDeployment, tt.args.don, tt.args.oracleCreator) if (err != nil) != tt.wantErr { t.Errorf("updateDON() error = %v, wantErr %v", err, tt.wantErr) return @@ -302,15 +240,15 @@ func Test_launcher_processDiff(t *testing.T) { fields{ dons: map[registrysyncer.DonID]*ccipDeployment{ 1: { - commit: blueGreenDeployment{ - blue: newMock(t, + commit: activeCandidateDeployment{ + active: newMock(t, func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, func(m *mocks.CCIPOracle) { m.On("Close").Return(nil) }), }, - exec: blueGreenDeployment{ - blue: newMock(t, + exec: activeCandidateDeployment{ + active: newMock(t, func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, func(m *mocks.CCIPOracle) { m.On("Close").Return(nil) @@ -346,9 +284,17 @@ func Test_launcher_processDiff(t *testing.T) { return mocks.NewHomeChainReader(t) }, func(m *mocks.HomeChainReader) { m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + }, + }}, nil) m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + }, + }}, nil) }), oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { return mocks.NewOracleCreator(t) @@ -357,9 +303,13 @@ func Test_launcher_processDiff(t *testing.T) { commitOracle.On("Start").Return(nil) execOracle := mocks.NewCCIPOracle(t) execOracle.On("Start").Return(nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, mock.Anything). + m.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). Return(commitOracle, nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPExec, mock.Anything). + m.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). Return(execOracle, nil) }), dons: map[registrysyncer.DonID]*ccipDeployment{}, @@ -381,7 +331,7 @@ func Test_launcher_processDiff(t *testing.T) { false, }, { - "don updated new green instance success", + "don updated new candidate instance success", fields{ lggr: logger.TestLogger(t), p2pID: p2pID1, @@ -389,9 +339,25 @@ func Test_launcher_processDiff(t *testing.T) { return mocks.NewHomeChainReader(t) }, func(m *mocks.HomeChainReader) { m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}, {}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + }, + }, { + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + }, + }}, nil) m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}, {}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + }, + }, { + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + }, + }}, nil) }), oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { return mocks.NewOracleCreator(t) @@ -400,20 +366,24 @@ func Test_launcher_processDiff(t *testing.T) { commitOracle.On("Start").Return(nil) execOracle := mocks.NewCCIPOracle(t) execOracle.On("Start").Return(nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, mock.Anything). + m.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). Return(commitOracle, nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPExec, mock.Anything). + m.EXPECT().Create(mock.Anything, mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). Return(execOracle, nil) }), dons: map[registrysyncer.DonID]*ccipDeployment{ 1: { - commit: blueGreenDeployment{ - blue: newMock(t, func(t *testing.T) *mocks.CCIPOracle { + commit: activeCandidateDeployment{ + active: newMock(t, func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, func(m *mocks.CCIPOracle) {}), }, - exec: blueGreenDeployment{ - blue: newMock(t, func(t *testing.T) *mocks.CCIPOracle { + exec: activeCandidateDeployment{ + active: newMock(t, func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, func(m *mocks.CCIPOracle) {}), }, @@ -465,6 +435,13 @@ func Test_launcher_processDiff(t *testing.T) { } } +func getOCR3Nodes(p2pIDs ...int64) []ccipreaderpkg.OCR3Node { + nodes := make([]ccipreaderpkg.OCR3Node, len(p2pIDs)) + for i, p2pID := range p2pIDs { + nodes[i] = ccipreaderpkg.OCR3Node{P2pID: p2pkey.MustNewV2XXXTestingOnly(big.NewInt(p2pID)).PeerID()} + } + return nodes +} func newMock[T any](t *testing.T, newer func(t *testing.T) T, expect func(m T)) T { o := newer(t) expect(o) diff --git a/core/capabilities/ccip/launcher/test_helpers.go b/core/capabilities/ccip/launcher/test_helpers.go index a2ebf3fdba9..f4ded9c2cf2 100644 --- a/core/capabilities/ccip/launcher/test_helpers.go +++ b/core/capabilities/ccip/launcher/test_helpers.go @@ -23,8 +23,10 @@ var ( newCapability = getCapability(ccipCapName, ccipCapNewVersion) p2pID1 = getP2PID(1) p2pID2 = getP2PID(2) + p2pID3 = getP2PID(3) + p2pID4 = getP2PID(4) defaultCapCfgs = map[string]registrysyncer.CapabilityConfiguration{ - defaultCapability.ID: registrysyncer.CapabilityConfiguration{}, + defaultCapability.ID: {}, } defaultRegistryDon = registrysyncer.DON{ DON: getDON(1, []ragep2ptypes.PeerID{p2pID1}, 0), diff --git a/core/capabilities/ccip/ocrimpls/config_digester.go b/core/capabilities/ccip/ocrimpls/config_digester.go index ef0c5e7ca32..5bbaf590717 100644 --- a/core/capabilities/ccip/ocrimpls/config_digester.go +++ b/core/capabilities/ccip/ocrimpls/config_digester.go @@ -1,6 +1,10 @@ package ocrimpls -import "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +import ( + "context" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) type configDigester struct { d types.ConfigDigest @@ -11,12 +15,12 @@ func NewConfigDigester(d types.ConfigDigest) *configDigester { } // ConfigDigest implements types.OffchainConfigDigester. -func (c *configDigester) ConfigDigest(types.ContractConfig) (types.ConfigDigest, error) { +func (c *configDigester) ConfigDigest(context.Context, types.ContractConfig) (types.ConfigDigest, error) { return c.d, nil } // ConfigDigestPrefix implements types.OffchainConfigDigester. -func (c *configDigester) ConfigDigestPrefix() (types.ConfigDigestPrefix, error) { +func (c *configDigester) ConfigDigestPrefix(ctx context.Context) (types.ConfigDigestPrefix, error) { return types.ConfigDigestPrefixCCIPMultiRole, nil } diff --git a/core/capabilities/ccip/ocrimpls/config_tracker.go b/core/capabilities/ccip/ocrimpls/config_tracker.go index 3a6a27fa40c..c70aa50030a 100644 --- a/core/capabilities/ccip/ocrimpls/config_tracker.go +++ b/core/capabilities/ccip/ocrimpls/config_tracker.go @@ -39,12 +39,19 @@ func (c *configTracker) Notify() <-chan struct{} { } func (c *configTracker) contractConfig() types.ContractConfig { + var signers [][]byte + var transmitters [][]byte + for _, node := range c.cfg.Config.Nodes { + signers = append(signers, node.SignerKey) + transmitters = append(transmitters, node.TransmitterKey) + } + return types.ContractConfig{ ConfigDigest: c.cfg.ConfigDigest, - ConfigCount: c.cfg.ConfigCount, - Signers: toOnchainPublicKeys(c.cfg.Config.Signers), - Transmitters: toOCRAccounts(c.cfg.Config.Transmitters), - F: c.cfg.Config.F, + ConfigCount: uint64(c.cfg.Version), + Signers: toOnchainPublicKeys(signers), + Transmitters: toOCRAccounts(transmitters), + F: c.cfg.Config.FRoleDON, OnchainConfig: []byte{}, OffchainConfigVersion: c.cfg.Config.OffchainConfigVersion, OffchainConfig: c.cfg.Config.OffchainConfig, diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index fd8e206d0e3..d3ca35bbe83 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -113,7 +113,7 @@ func NewExecContractTransmitter[RI any]( } // FromAccount implements ocr3types.ContractTransmitter. -func (c *commitTransmitter[RI]) FromAccount() (ocrtypes.Account, error) { +func (c *commitTransmitter[RI]) FromAccount(context.Context) (ocrtypes.Account, error) { return c.fromAccount, nil } diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 871afbb6697..0f84d80a1f8 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -7,8 +7,12 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" @@ -16,7 +20,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/jmoiron/sqlx" - "github.com/onsi/gomega" "github.com/stretchr/testify/require" "github.com/smartcontractkit/libocr/commontypes" @@ -24,7 +27,6 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -90,7 +92,6 @@ func Test_ContractTransmitter_TransmitWithoutSignatures(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tc := tc - t.Parallel() testTransmitter(t, tc.pluginType, tc.withSigs, tc.expectedSigsEnabled, tc.report) }) } @@ -103,6 +104,7 @@ func testTransmitter( expectedSigsEnabled bool, report []byte, ) { + ctx := tests.Context(t) uni := newTestUniverse[[]byte](t, nil) c, err := uni.wrapper.LatestConfigDetails(nil, pluginType) @@ -125,7 +127,7 @@ func testTransmitter( seqNr := uint64(1) attributedSigs := uni.SignReport(t, configDigest, rwi, seqNr) - account, err := uni.transmitterWithSigs.FromAccount() + account, err := uni.transmitterWithSigs.FromAccount(ctx) require.NoError(t, err, "failed to get from account") require.Equal(t, ocrtypes.Account(uni.transmitters[0].Hex()), account, "from account mismatch") if withSigs { @@ -137,7 +139,7 @@ func testTransmitter( uni.backend.Commit() var txStatus uint64 - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { uni.backend.Commit() rows, err := uni.db.QueryContext(testutils.Context(t), `SELECT hash FROM evm.tx_attempts LIMIT 1`) require.NoError(t, err, "failed to query txes") @@ -155,10 +157,10 @@ func testTransmitter( t.Log("tx found:", hexutil.Encode(txHash), "status:", receipt.Status) txStatus = receipt.Status return true - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 1*time.Second) // wait for receipt to be written to the db - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { rows, err := uni.db.QueryContext(testutils.Context(t), `SELECT count(*) as cnt FROM evm.receipts LIMIT 1`) require.NoError(t, err, "failed to query receipts") defer rows.Close() @@ -167,7 +169,7 @@ func testTransmitter( require.NoError(t, rows.Scan(&count), "failed to scan") } return count == 1 - }, testutils.WaitTimeout(t), 2*time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 2*time.Second) require.Equal(t, uint64(1), txStatus, "tx status should be success") @@ -402,8 +404,7 @@ func chainWriterConfigRaw(fromAddress common.Address, maxGasPrice *assets.Wei) e }, }, }, - SendStrategy: txmgrcommon.NewSendEveryStrategy(), - MaxGasPrice: maxGasPrice, + MaxGasPrice: maxGasPrice, } } @@ -414,7 +415,7 @@ func makeTestEvmTxm( keyStore keystore.Eth) (txmgr.TxManager, gas.EvmFeeEstimator) { config, dbConfig, evmConfig := MakeTestConfigs(t) - estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) require.NoError(t, err, "failed to create gas estimator") lggr := logger.TestLogger(t) @@ -542,6 +543,10 @@ func (t *TestHeadTrackerConfig) SamplingInterval() time.Duration { return 1 * time.Second } +func (t *TestHeadTrackerConfig) PersistenceEnabled() bool { + return true +} + var _ evmconfig.HeadTracker = (*TestHeadTrackerConfig)(nil) type TestEvmConfig struct { @@ -587,10 +592,32 @@ type TestGasEstimatorConfig struct { bumpThreshold uint64 } +func (g *TestGasEstimatorConfig) DAOracle() evmconfig.DAOracle { + return &TestDAOracleConfig{} +} + +type TestDAOracleConfig struct { + evmconfig.DAOracle +} + +func (d *TestDAOracleConfig) OracleType() toml.DAOracleType { return toml.DAOracleOPStack } +func (d *TestDAOracleConfig) OracleAddress() *types.EIP55Address { + a, err := types.NewEIP55Address("0x420000000000000000000000000000000000000F") + if err != nil { + panic(err) + } + return &a +} +func (d *TestDAOracleConfig) CustomGasPriceCalldata() string { return "" } + func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory { return &TestBlockHistoryConfig{} } +func (g *TestGasEstimatorConfig) FeeHistory() evmconfig.FeeHistory { + return &TestFeeHistoryConfig{} +} + func (g *TestGasEstimatorConfig) EIP1559DynamicFees() bool { return false } func (g *TestGasEstimatorConfig) LimitDefault() uint64 { return 1e6 } func (g *TestGasEstimatorConfig) BumpPercent() uint16 { return 2 } @@ -613,6 +640,7 @@ func (g *TestGasEstimatorConfig) LimitJobType() evmconfig.LimitJobType { func (g *TestGasEstimatorConfig) PriceMaxKey(addr common.Address) *assets.Wei { return assets.GWei(1) } +func (g *TestGasEstimatorConfig) EstimateLimit() bool { return false } func (e *TestEvmConfig) GasEstimator() evmconfig.GasEstimator { return &TestGasEstimatorConfig{bumpThreshold: e.BumpThreshold} @@ -638,6 +666,10 @@ func (b *TestBlockHistoryConfig) BlockHistorySize() uint16 { return 42 func (b *TestBlockHistoryConfig) EIP1559FeeCapBufferBlocks() uint16 { return 42 } func (b *TestBlockHistoryConfig) TransactionPercentile() uint16 { return 42 } +type TestFeeHistoryConfig struct { + evmconfig.FeeHistory +} + type transactionsConfig struct { evmconfig.Transactions e *TestEvmConfig diff --git a/core/capabilities/ccip/oraclecreator/bootstrap.go b/core/capabilities/ccip/oraclecreator/bootstrap.go new file mode 100644 index 00000000000..22de4ae9486 --- /dev/null +++ b/core/capabilities/ccip/oraclecreator/bootstrap.go @@ -0,0 +1,97 @@ +package oraclecreator + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common/hexutil" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/libocr/commontypes" + libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" + "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" +) + +var _ cctypes.OracleCreator = &bootstrapOracleCreator{} + +type bootstrapOracleCreator struct { + peerWrapper *ocrcommon.SingletonPeerWrapper + bootstrapperLocators []commontypes.BootstrapperLocator + db ocr3types.Database + monitoringEndpointGen telemetry.MonitoringEndpointGenerator + lggr logger.Logger +} + +func NewBootstrapOracleCreator( + peerWrapper *ocrcommon.SingletonPeerWrapper, + bootstrapperLocators []commontypes.BootstrapperLocator, + db ocr3types.Database, + monitoringEndpointGen telemetry.MonitoringEndpointGenerator, + lggr logger.Logger, +) cctypes.OracleCreator { + return &bootstrapOracleCreator{ + peerWrapper: peerWrapper, + bootstrapperLocators: bootstrapperLocators, + db: db, + monitoringEndpointGen: monitoringEndpointGen, + lggr: lggr, + } +} + +// Type implements types.OracleCreator. +func (i *bootstrapOracleCreator) Type() cctypes.OracleType { + return cctypes.OracleTypeBootstrap +} + +// Create implements types.OracleCreator. +func (i *bootstrapOracleCreator) Create(_ uint32, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { + // Assuming that the chain selector is referring to an evm chain for now. + // TODO: add an api that returns chain family. + // NOTE: this doesn't really matter for the bootstrap node, it doesn't do anything on-chain. + // Its for the monitoring endpoint generation below. + chainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) + if err != nil { + return nil, fmt.Errorf("failed to get chain ID from selector: %w", err) + } + + destChainFamily := chaintype.EVM + destRelayID := types.NewRelayID(string(destChainFamily), fmt.Sprintf("%d", chainID)) + + bootstrapperArgs := libocr3.BootstrapperArgs{ + BootstrapperFactory: i.peerWrapper.Peer2, + V2Bootstrappers: i.bootstrapperLocators, + ContractConfigTracker: ocrimpls.NewConfigTracker(config), + Database: i.db, + LocalConfig: defaultLocalConfig(), + Logger: ocrcommon.NewOCRWrapper( + i.lggr. + Named("CCIPBootstrap"). + Named(destRelayID.String()). + Named(config.Config.ChainSelector.String()). + Named(hexutil.Encode(config.Config.OfframpAddress)), + false, /* traceLogging */ + func(ctx context.Context, msg string) {}), + MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( + string(destChainFamily), + destRelayID.ChainID, + hexutil.Encode(config.Config.OfframpAddress), + synchronization.OCR3CCIPBootstrap, + ), + OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), + } + bootstrapper, err := libocr3.NewBootstrapper(bootstrapperArgs) + if err != nil { + return nil, err + } + return bootstrapper, nil +} diff --git a/core/capabilities/ccip/oraclecreator/inprocess.go b/core/capabilities/ccip/oraclecreator/inprocess.go deleted file mode 100644 index 6616d356756..00000000000 --- a/core/capabilities/ccip/oraclecreator/inprocess.go +++ /dev/null @@ -1,371 +0,0 @@ -package oraclecreator - -import ( - "context" - "fmt" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/google/uuid" - "github.com/prometheus/client_golang/prometheus" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - - "github.com/smartcontractkit/libocr/commontypes" - libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" - execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - "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/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" -) - -var _ cctypes.OracleCreator = &inprocessOracleCreator{} - -const ( - defaultCommitGasLimit = 500_000 -) - -// inprocessOracleCreator creates oracles that reference plugins running -// in the same process as the chainlink node, i.e not LOOPPs. -type inprocessOracleCreator struct { - ocrKeyBundles map[string]ocr2key.KeyBundle - transmitters map[types.RelayID][]string - chains legacyevm.LegacyChainContainer - peerWrapper *ocrcommon.SingletonPeerWrapper - externalJobID uuid.UUID - jobID int32 - isNewlyCreatedJob bool - pluginConfig job.JSONConfig - db ocr3types.Database - lggr logger.Logger - monitoringEndpointGen telemetry.MonitoringEndpointGenerator - bootstrapperLocators []commontypes.BootstrapperLocator - homeChainReader ccipreaderpkg.HomeChain -} - -func New( - ocrKeyBundles map[string]ocr2key.KeyBundle, - transmitters map[types.RelayID][]string, - chains legacyevm.LegacyChainContainer, - peerWrapper *ocrcommon.SingletonPeerWrapper, - externalJobID uuid.UUID, - jobID int32, - isNewlyCreatedJob bool, - pluginConfig job.JSONConfig, - db ocr3types.Database, - lggr logger.Logger, - monitoringEndpointGen telemetry.MonitoringEndpointGenerator, - bootstrapperLocators []commontypes.BootstrapperLocator, - homeChainReader ccipreaderpkg.HomeChain, -) cctypes.OracleCreator { - return &inprocessOracleCreator{ - ocrKeyBundles: ocrKeyBundles, - transmitters: transmitters, - chains: chains, - peerWrapper: peerWrapper, - externalJobID: externalJobID, - jobID: jobID, - isNewlyCreatedJob: isNewlyCreatedJob, - pluginConfig: pluginConfig, - db: db, - lggr: lggr, - monitoringEndpointGen: monitoringEndpointGen, - bootstrapperLocators: bootstrapperLocators, - homeChainReader: homeChainReader, - } -} - -// CreateBootstrapOracle implements types.OracleCreator. -func (i *inprocessOracleCreator) CreateBootstrapOracle(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - // Assuming that the chain selector is referring to an evm chain for now. - // TODO: add an api that returns chain family. - chainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, fmt.Errorf("failed to get chain ID from selector: %w", err) - } - - destChainFamily := chaintype.EVM - destRelayID := types.NewRelayID(string(destChainFamily), fmt.Sprintf("%d", chainID)) - - bootstrapperArgs := libocr3.BootstrapperArgs{ - BootstrapperFactory: i.peerWrapper.Peer2, - V2Bootstrappers: i.bootstrapperLocators, - ContractConfigTracker: ocrimpls.NewConfigTracker(config), - Database: i.db, - LocalConfig: defaultLocalConfig(), - Logger: ocrcommon.NewOCRWrapper( - i.lggr. - Named("CCIPBootstrap"). - Named(destRelayID.String()). - Named(config.Config.ChainSelector.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - false, /* traceLogging */ - func(ctx context.Context, msg string) {}), - MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( - string(destChainFamily), - destRelayID.ChainID, - hexutil.Encode(config.Config.OfframpAddress), - synchronization.OCR3CCIPBootstrap, - ), - OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), - } - bootstrapper, err := libocr3.NewBootstrapper(bootstrapperArgs) - if err != nil { - return nil, err - } - return bootstrapper, nil -} - -// CreatePluginOracle implements types.OracleCreator. -func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - // Assuming that the chain selector is referring to an evm chain for now. - // TODO: add an api that returns chain family. - destChainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, fmt.Errorf("failed to get chain ID from selector %d: %w", config.Config.ChainSelector, err) - } - destChainFamily := relay.NetworkEVM - destRelayID := types.NewRelayID(destChainFamily, fmt.Sprintf("%d", destChainID)) - - configTracker := ocrimpls.NewConfigTracker(config) - publicConfig, err := configTracker.PublicConfig() - if err != nil { - return nil, fmt.Errorf("failed to get public config from OCR config: %w", err) - } - var execBatchGasLimit uint64 - if pluginType == cctypes.PluginTypeCCIPExec { - execOffchainConfig, err2 := pluginconfig.DecodeExecuteOffchainConfig(publicConfig.ReportingPluginConfig) - if err2 != nil { - return nil, fmt.Errorf("failed to decode execute offchain config: %w, raw: %s", - err2, string(publicConfig.ReportingPluginConfig)) - } - if execOffchainConfig.BatchGasLimit == 0 && destChainFamily == relay.NetworkEVM { - return nil, fmt.Errorf("BatchGasLimit not set in execute offchain config, must be > 0") - } - execBatchGasLimit = execOffchainConfig.BatchGasLimit - } - - // this is so that we can use the msg hasher and report encoder from that dest chain relayer's provider. - contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) - chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) - for _, chain := range i.chains.Slice() { - var chainReaderConfig evmrelaytypes.ChainReaderConfig - if chain.ID().Uint64() == destChainID { - chainReaderConfig = evmconfig.DestReaderConfig() - } else { - chainReaderConfig = evmconfig.SourceReaderConfig() - } - cr, err2 := evm.NewChainReaderService( - context.Background(), - i.lggr. - Named("EVMChainReaderService"). - Named(chain.ID().String()). - Named(pluginType.String()), - chain.LogPoller(), - chain.HeadTracker(), - chain.Client(), - chainReaderConfig, - ) - if err2 != nil { - return nil, fmt.Errorf("failed to create contract reader for chain %s: %w", chain.ID(), err2) - } - - if chain.ID().Uint64() == destChainID { - // bind the chain reader to the dest chain's offramp. - offrampAddressHex := common.BytesToAddress(config.Config.OfframpAddress).Hex() - err3 := cr.Bind(context.Background(), []types.BoundContract{ - { - Address: offrampAddressHex, - Name: consts.ContractNameOffRamp, - }, - }) - if err3 != nil { - return nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chain.ID(), offrampAddressHex, err3) - } - } - - // TODO: figure out shutdown. - // maybe from the plugin directly? - err2 = cr.Start(context.Background()) - if err2 != nil { - return nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chain.ID(), err2) - } - - // Even though we only write to the dest chain, we need to create chain writers for all chains - // we know about in order to post gas prices on the dest. - var fromAddress common.Address - transmitter, ok := i.transmitters[types.NewRelayID(relay.NetworkEVM, chain.ID().String())] - if ok { - fromAddress = common.HexToAddress(transmitter[0]) - } - cw, err2 := evm.NewChainWriterService( - i.lggr.Named("EVMChainWriterService"). - Named(chain.ID().String()). - Named(pluginType.String()), - chain.Client(), - chain.TxManager(), - chain.GasEstimator(), - evmconfig.ChainWriterConfigRaw( - fromAddress, - chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddress), - defaultCommitGasLimit, - execBatchGasLimit, - ), - ) - if err2 != nil { - return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chain.ID(), err2) - } - - // TODO: figure out shutdown. - // maybe from the plugin directly? - err2 = cw.Start(context.Background()) - if err2 != nil { - return nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chain.ID(), err2) - } - - chainSelector, ok := chainsel.EvmChainIdToChainSelector()[chain.ID().Uint64()] - if !ok { - return nil, fmt.Errorf("failed to get chain selector from chain ID %s", chain.ID()) - } - - contractReaders[cciptypes.ChainSelector(chainSelector)] = cr - chainWriters[cciptypes.ChainSelector(chainSelector)] = cw - } - - // build the onchain keyring. it will be the signing key for the destination chain family. - keybundle, ok := i.ocrKeyBundles[destChainFamily] - if !ok { - return nil, fmt.Errorf("no OCR key bundle found for chain family %s, forgot to create one?", destChainFamily) - } - onchainKeyring := ocrimpls.NewOnchainKeyring[[]byte](keybundle, i.lggr) - - // build the contract transmitter - // assume that we are using the first account in the keybundle as the from account - // and that we are able to transmit to the dest chain. - // TODO: revisit this in the future, since not all oracles will be able to transmit to the dest chain. - destChainWriter, ok := chainWriters[config.Config.ChainSelector] - if !ok { - return nil, fmt.Errorf("no chain writer found for dest chain selector %d, can't create contract transmitter", - config.Config.ChainSelector) - } - destFromAccounts, ok := i.transmitters[destRelayID] - if !ok { - return nil, fmt.Errorf("no transmitter found for dest relay ID %s, can't create contract transmitter", destRelayID) - } - - // TODO: Extract the correct transmitter address from the destsFromAccount - var factory ocr3types.ReportingPluginFactory[[]byte] - var transmitter ocr3types.ContractTransmitter[[]byte] - if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { - factory = commitocr3.NewPluginFactory( - i.lggr. - Named("CCIPCommitPlugin"). - Named(destRelayID.String()). - Named(fmt.Sprintf("%d", config.Config.ChainSelector)). - Named(hexutil.Encode(config.Config.OfframpAddress)), - ccipreaderpkg.OCR3ConfigWithMeta(config), - ccipevm.NewCommitPluginCodecV1(), - ccipevm.NewMessageHasherV1(), - i.homeChainReader, - contractReaders, - chainWriters, - ) - transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, - ocrtypes.Account(destFromAccounts[0]), - hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? - ) - } else if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) { - factory = execocr3.NewPluginFactory( - i.lggr. - Named("CCIPExecPlugin"). - Named(destRelayID.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - ccipreaderpkg.OCR3ConfigWithMeta(config), - ccipevm.NewExecutePluginCodecV1(), - ccipevm.NewMessageHasherV1(), - i.homeChainReader, - contractReaders, - chainWriters, - ) - transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, - ocrtypes.Account(destFromAccounts[0]), - hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? - ) - } else { - return nil, fmt.Errorf("unsupported plugin type %d", config.Config.PluginType) - } - - oracleArgs := libocr3.OCR3OracleArgs[[]byte]{ - BinaryNetworkEndpointFactory: i.peerWrapper.Peer2, - Database: i.db, - V2Bootstrappers: i.bootstrapperLocators, - ContractConfigTracker: configTracker, - ContractTransmitter: transmitter, - LocalConfig: defaultLocalConfig(), - Logger: ocrcommon.NewOCRWrapper( - i.lggr. - Named(fmt.Sprintf("CCIP%sOCR3", pluginType.String())). - Named(destRelayID.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - false, - func(ctx context.Context, msg string) {}), - MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"name": fmt.Sprintf("commit-%d", config.Config.ChainSelector)}, prometheus.DefaultRegisterer), - MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( - destChainFamily, - destRelayID.ChainID, - string(config.Config.OfframpAddress), - synchronization.OCR3CCIPCommit, - ), - OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), - OffchainKeyring: keybundle, - OnchainKeyring: onchainKeyring, - ReportingPluginFactory: factory, - } - oracle, err := libocr3.NewOracle(oracleArgs) - if err != nil { - return nil, err - } - return oracle, nil -} - -func defaultLocalConfig() ocrtypes.LocalConfig { - return ocrtypes.LocalConfig{ - BlockchainTimeout: 10 * time.Second, - // Config tracking is handled by the launcher, since we're doing blue-green - // deployments we're not going to be using OCR's built-in config switching, - // which always shuts down the previous instance. - ContractConfigConfirmations: 1, - SkipContractConfigConfirmations: true, - ContractConfigTrackerPollInterval: 10 * time.Second, - ContractTransmitterTransmitTimeout: 10 * time.Second, - DatabaseTimeout: 10 * time.Second, - MinOCR2MaxDurationQuery: 1 * time.Second, - DevelopmentMode: "false", - } -} diff --git a/core/capabilities/ccip/oraclecreator/inprocess_test.go b/core/capabilities/ccip/oraclecreator/inprocess_test.go deleted file mode 100644 index 639f01e62e3..00000000000 --- a/core/capabilities/ccip/oraclecreator/inprocess_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package oraclecreator_test - -import ( - "fmt" - "testing" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/oraclecreator" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/google/uuid" - "github.com/hashicorp/consul/sdk/freeport" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gopkg.in/guregu/null.v4" - - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/libocr/offchainreporting2/types" - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/libocr/commontypes" - - "github.com/smartcontractkit/chainlink/v2/core/bridges" - "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" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "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/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" - ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -func TestOracleCreator_CreateBootstrap(t *testing.T) { - db := pgtest.NewSqlxDB(t) - - keyStore := keystore.New(db, utils.DefaultScryptParams, logger.NullLogger) - require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password), "unable to unlock keystore") - p2pKey, err := keyStore.P2P().Create(testutils.Context(t)) - require.NoError(t, err) - peerID := p2pKey.PeerID() - listenPort := freeport.GetOne(t) - generalConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.P2P.PeerID = ptr(peerID) - c.P2P.TraceLogging = ptr(false) - c.P2P.V2.Enabled = ptr(true) - c.P2P.V2.ListenAddresses = ptr([]string{fmt.Sprintf("127.0.0.1:%d", listenPort)}) - - c.OCR2.Enabled = ptr(true) - }) - peerWrapper := ocrcommon.NewSingletonPeerWrapper(keyStore, generalConfig.P2P(), generalConfig.OCR(), db, logger.NullLogger) - require.NoError(t, peerWrapper.Start(testutils.Context(t))) - t.Cleanup(func() { assert.NoError(t, peerWrapper.Close()) }) - - // NOTE: this is a bit of a hack to get the OCR2 job created in order to use the ocr db - // the ocr2_contract_configs table has a foreign key constraint on ocr2_oracle_spec_id - // which is passed into ocr2.NewDB. - pipelineORM := pipeline.NewORM(db, - logger.NullLogger, generalConfig.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(db) - - jobORM := job.NewORM(db, pipelineORM, bridgesORM, keyStore, logger.TestLogger(t)) - t.Cleanup(func() { assert.NoError(t, jobORM.Close()) }) - - jb, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), generalConfig.OCR2(), generalConfig.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) - require.NoError(t, err) - const juelsPerFeeCoinSource = ` - ds [type=http method=GET url="https://chain.link/ETH-USD"]; - ds_parse [type=jsonparse path="data.price" separator="."]; - ds_multiply [type=multiply times=100]; - ds -> ds_parse -> ds_multiply;` - - _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) - jb.Name = null.StringFrom("Job 1") - jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) - jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - - err = jobORM.CreateJob(testutils.Context(t), &jb) - require.NoError(t, err) - - cltest.AssertCount(t, db, "ocr2_oracle_specs", 1) - cltest.AssertCount(t, db, "jobs", 1) - - var oracleSpecID int32 - err = db.Get(&oracleSpecID, "SELECT id FROM ocr2_oracle_specs LIMIT 1") - require.NoError(t, err) - - ocrdb := ocr2.NewDB(db, oracleSpecID, 0, logger.NullLogger) - - oc := oraclecreator.New( - nil, - nil, - nil, - peerWrapper, - uuid.Max, - 0, - false, - nil, - ocrdb, - logger.TestLogger(t), - &mockEndpointGen{}, - []commontypes.BootstrapperLocator{}, - nil, - ) - - chainSelector := chainsel.GETH_TESTNET.Selector - oracles, offchainConfig := ocrOffchainConfig(t, keyStore) - bootstrapP2PID, err := p2pkey.MakePeerID(oracles[0].PeerID) - require.NoError(t, err) - transmitters := func() [][]byte { - var transmitters [][]byte - for _, o := range oracles { - transmitters = append(transmitters, hexutil.MustDecode(string(o.TransmitAccount))) - } - return transmitters - }() - configDigest := ccipConfigDigest() - bootstrap, err := oc.CreateBootstrapOracle(cctypes.OCR3ConfigWithMeta{ - ConfigDigest: configDigest, - ConfigCount: 1, - Config: reader.OCR3Config{ - ChainSelector: ccipocr3.ChainSelector(chainSelector), - OfframpAddress: testutils.NewAddress().Bytes(), - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - F: 1, - OffchainConfigVersion: 30, - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2PIds: func() [][32]byte { - var ids [][32]byte - for _, o := range oracles { - id, err2 := p2pkey.MakePeerID(o.PeerID) - require.NoError(t, err2) - ids = append(ids, id) - } - return ids - }(), - Signers: func() [][]byte { - var signers [][]byte - for _, o := range oracles { - signers = append(signers, o.OnchainPublicKey) - } - return signers - }(), - Transmitters: transmitters, - OffchainConfig: offchainConfig, - }, - }) - require.NoError(t, err) - require.NoError(t, bootstrap.Start()) - t.Cleanup(func() { assert.NoError(t, bootstrap.Close()) }) - - tests.AssertEventually(t, func() bool { - c, err := ocrdb.ReadConfig(testutils.Context(t)) - require.NoError(t, err) - return c.ConfigDigest == configDigest - }) -} - -func ccipConfigDigest() [32]byte { - rand32Bytes := testutils.Random32Byte() - // overwrite first four bytes to be 0x000a, to match the prefix in libocr. - rand32Bytes[0] = 0x00 - rand32Bytes[1] = 0x0a - return rand32Bytes -} - -type mockEndpointGen struct{} - -func (m *mockEndpointGen) GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) commontypes.MonitoringEndpoint { - return &telemetry.NoopAgent{} -} - -func ptr[T any](b T) *T { - return &b -} - -func ocrOffchainConfig(t *testing.T, ks keystore.Master) (oracles []confighelper2.OracleIdentityExtra, offchainConfig []byte) { - for i := 0; i < 4; i++ { - kb, err := ks.OCR2().Create(testutils.Context(t), chaintype.EVM) - require.NoError(t, err) - p2pKey, err := ks.P2P().Create(testutils.Context(t)) - require.NoError(t, err) - ethKey, err := ks.Eth().Create(testutils.Context(t)) - require.NoError(t, err) - oracles = append(oracles, confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OffchainPublicKey: kb.OffchainPublicKey(), - OnchainPublicKey: types.OnchainPublicKey(kb.OnChainPublicKey()), - PeerID: p2pKey.ID(), - TransmitAccount: types.Account(ethKey.Address.Hex()), - }, - ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), - }) - } - var schedule []int - for range oracles { - schedule = append(schedule, 1) - } - offchainConfig, onchainConfig := []byte{}, []byte{} - f := uint8(1) - - _, _, _, _, _, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( - 30*time.Second, // deltaProgress - 10*time.Second, // deltaResend - 20*time.Second, // deltaInitial - 2*time.Second, // deltaRound - 20*time.Second, // deltaGrace - 10*time.Second, // deltaCertifiedCommitRequest - 10*time.Second, // deltaStage - 3, // rmax - schedule, - oracles, - offchainConfig, - 50*time.Millisecond, // maxDurationQuery - 5*time.Second, // maxDurationObservation - 10*time.Second, // maxDurationShouldAcceptAttestedReport - 10*time.Second, // maxDurationShouldTransmitAcceptedReport - int(f), - onchainConfig) - require.NoError(t, err, "failed to create contract config") - - return oracles, offchainConfig -} diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go new file mode 100644 index 00000000000..117e1fe1bcd --- /dev/null +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -0,0 +1,580 @@ +package oraclecreator + +import ( + "context" + "encoding/json" + "fmt" + "io" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/google/uuid" + "github.com/prometheus/client_golang/prometheus" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + + "github.com/smartcontractkit/libocr/commontypes" + libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + + commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" + "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" + execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + ccipreaderpkg "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" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" + "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" +) + +var _ cctypes.OracleCreator = &pluginOracleCreator{} + +const ( + defaultCommitGasLimit = 500_000 + defaultExecGasLimit = 6_500_000 +) + +// pluginOracleCreator creates oracles that reference plugins running +// in the same process as the chainlink node, i.e not LOOPPs. +type pluginOracleCreator struct { + ocrKeyBundles map[string]ocr2key.KeyBundle + transmitters map[types.RelayID][]string + peerWrapper *ocrcommon.SingletonPeerWrapper + externalJobID uuid.UUID + jobID int32 + isNewlyCreatedJob bool + pluginConfig job.JSONConfig + db ocr3types.Database + lggr logger.Logger + monitoringEndpointGen telemetry.MonitoringEndpointGenerator + bootstrapperLocators []commontypes.BootstrapperLocator + homeChainReader ccipreaderpkg.HomeChain + homeChainSelector cciptypes.ChainSelector + relayers map[types.RelayID]loop.Relayer + evmConfigs toml.EVMConfigs +} + +func NewPluginOracleCreator( + ocrKeyBundles map[string]ocr2key.KeyBundle, + transmitters map[types.RelayID][]string, + relayers map[types.RelayID]loop.Relayer, + peerWrapper *ocrcommon.SingletonPeerWrapper, + externalJobID uuid.UUID, + jobID int32, + isNewlyCreatedJob bool, + pluginConfig job.JSONConfig, + db ocr3types.Database, + lggr logger.Logger, + monitoringEndpointGen telemetry.MonitoringEndpointGenerator, + bootstrapperLocators []commontypes.BootstrapperLocator, + homeChainReader ccipreaderpkg.HomeChain, + homeChainSelector cciptypes.ChainSelector, + evmConfigs toml.EVMConfigs, +) cctypes.OracleCreator { + return &pluginOracleCreator{ + ocrKeyBundles: ocrKeyBundles, + transmitters: transmitters, + relayers: relayers, + peerWrapper: peerWrapper, + externalJobID: externalJobID, + jobID: jobID, + isNewlyCreatedJob: isNewlyCreatedJob, + pluginConfig: pluginConfig, + db: db, + lggr: lggr, + monitoringEndpointGen: monitoringEndpointGen, + bootstrapperLocators: bootstrapperLocators, + homeChainReader: homeChainReader, + homeChainSelector: homeChainSelector, + evmConfigs: evmConfigs, + } +} + +// Type implements types.OracleCreator. +func (i *pluginOracleCreator) Type() cctypes.OracleType { + return cctypes.OracleTypePlugin +} + +// Create implements types.OracleCreator. +func (i *pluginOracleCreator) Create(donID uint32, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { + pluginType := cctypes.PluginType(config.Config.PluginType) + + // Assuming that the chain selector is referring to an evm chain for now. + // TODO: add an api that returns chain family. + destChainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) + if err != nil { + return nil, fmt.Errorf("failed to get chain ID from selector %d: %w", config.Config.ChainSelector, err) + } + destChainFamily := relay.NetworkEVM + destRelayID := types.NewRelayID(destChainFamily, fmt.Sprintf("%d", destChainID)) + + configTracker := ocrimpls.NewConfigTracker(config) + publicConfig, err := configTracker.PublicConfig() + if err != nil { + return nil, fmt.Errorf("failed to get public config from OCR config: %w", err) + } + + contractReaders, chainWriters, err := i.createReadersAndWriters( + destChainID, + pluginType, + config, + publicConfig, + ) + if err != nil { + return nil, fmt.Errorf("failed to create readers and writers: %w", err) + } + + // build the onchain keyring. it will be the signing key for the destination chain family. + keybundle, ok := i.ocrKeyBundles[destChainFamily] + if !ok { + return nil, fmt.Errorf("no OCR key bundle found for chain family %s, forgot to create one?", destChainFamily) + } + onchainKeyring := ocrimpls.NewOnchainKeyring[[]byte](keybundle, i.lggr) + + // build the contract transmitter + // assume that we are using the first account in the keybundle as the from account + // and that we are able to transmit to the dest chain. + // TODO: revisit this in the future, since not all oracles will be able to transmit to the dest chain. + destChainWriter, ok := chainWriters[config.Config.ChainSelector] + if !ok { + return nil, fmt.Errorf("no chain writer found for dest chain selector %d, can't create contract transmitter", + config.Config.ChainSelector) + } + destFromAccounts, ok := i.transmitters[destRelayID] + if !ok { + return nil, fmt.Errorf("no transmitter found for dest relay ID %s, can't create contract transmitter", destRelayID) + } + + // TODO: Extract the correct transmitter address from the destsFromAccount + factory, transmitter, err := i.createFactoryAndTransmitter(donID, config, destRelayID, contractReaders, chainWriters, destChainWriter, destFromAccounts) + if err != nil { + return nil, fmt.Errorf("failed to create factory and transmitter: %w", err) + } + + oracleArgs := libocr3.OCR3OracleArgs[[]byte]{ + BinaryNetworkEndpointFactory: i.peerWrapper.Peer2, + Database: i.db, + // NOTE: when specifying V2Bootstrappers here we actually do NOT need to run a full bootstrap node! + // Thus it is vital that the bootstrapper locators are correctly set in the job spec. + V2Bootstrappers: i.bootstrapperLocators, + ContractConfigTracker: configTracker, + ContractTransmitter: transmitter, + LocalConfig: defaultLocalConfig(), + Logger: ocrcommon.NewOCRWrapper( + i.lggr. + Named(fmt.Sprintf("CCIP%sOCR3", pluginType.String())). + Named(destRelayID.String()). + Named(hexutil.Encode(config.Config.OfframpAddress)), + false, + func(ctx context.Context, msg string) {}), + MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"name": fmt.Sprintf("commit-%d", config.Config.ChainSelector)}, prometheus.DefaultRegisterer), + MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( + destChainFamily, + destRelayID.ChainID, + string(config.Config.OfframpAddress), + synchronization.OCR3CCIPCommit, + ), + OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), + OffchainKeyring: keybundle, + OnchainKeyring: onchainKeyring, + ReportingPluginFactory: factory, + } + oracle, err := libocr3.NewOracle(oracleArgs) + if err != nil { + return nil, err + } + + closers := make([]io.Closer, 0, len(contractReaders)+len(chainWriters)) + for _, cr := range contractReaders { + closers = append(closers, cr) + } + for _, cw := range chainWriters { + closers = append(closers, cw) + } + return newWrappedOracle(oracle, closers), nil +} + +func (i *pluginOracleCreator) createFactoryAndTransmitter( + donID uint32, + config cctypes.OCR3ConfigWithMeta, + destRelayID types.RelayID, + contractReaders map[cciptypes.ChainSelector]types.ContractReader, + chainWriters map[cciptypes.ChainSelector]types.ChainWriter, + destChainWriter types.ChainWriter, + destFromAccounts []string, +) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { + var factory ocr3types.ReportingPluginFactory[[]byte] + var transmitter ocr3types.ContractTransmitter[[]byte] + if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { + if !i.peerWrapper.IsStarted() { + return nil, nil, fmt.Errorf("peer wrapper is not started") + } + + rmnPeerClient := rmn.NewPeerClient(i.lggr, i.peerWrapper.PeerGroupFactory, i.bootstrapperLocators) + + rmnCrypto := ccipevm.NewEVMRMNCrypto() + + factory = commitocr3.NewPluginFactory( + i.lggr. + Named("CCIPCommitPlugin"). + Named(destRelayID.String()). + Named(fmt.Sprintf("%d", config.Config.ChainSelector)). + Named(hexutil.Encode(config.Config.OfframpAddress)), + donID, + ccipreaderpkg.OCR3ConfigWithMeta(config), + ccipevm.NewCommitPluginCodecV1(), + ccipevm.NewMessageHasherV1(), + i.homeChainReader, + i.homeChainSelector, + contractReaders, + chainWriters, + rmnPeerClient, + rmnCrypto, + ) + transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, + ocrtypes.Account(destFromAccounts[0]), + hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? + ) + } else if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) { + factory = execocr3.NewPluginFactory( + i.lggr. + Named("CCIPExecPlugin"). + Named(destRelayID.String()). + Named(hexutil.Encode(config.Config.OfframpAddress)), + donID, + ccipreaderpkg.OCR3ConfigWithMeta(config), + ccipevm.NewExecutePluginCodecV1(), + ccipevm.NewMessageHasherV1(), + i.homeChainReader, + ccipevm.NewEVMTokenDataEncoder(), + ccipevm.NewGasEstimateProvider(), + contractReaders, + chainWriters, + ) + transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, + ocrtypes.Account(destFromAccounts[0]), + hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? + ) + } else { + return nil, nil, fmt.Errorf("unsupported plugin type %d", config.Config.PluginType) + } + return factory, transmitter, nil +} + +func (i *pluginOracleCreator) createReadersAndWriters( + destChainID uint64, + pluginType cctypes.PluginType, + config cctypes.OCR3ConfigWithMeta, + publicCfg ocr3confighelper.PublicConfig, +) ( + map[cciptypes.ChainSelector]types.ContractReader, + map[cciptypes.ChainSelector]types.ChainWriter, + error, +) { + ofc, err := decodeAndValidateOffchainConfig(pluginType, publicCfg) + if err != nil { + return nil, nil, err + } + + var execBatchGasLimit uint64 + if !ofc.execEmpty() { + execBatchGasLimit = ofc.exec().BatchGasLimit + } else { + // Set the default here so chain writer config validation doesn't fail. + // For commit, this won't be used, so its harmless. + execBatchGasLimit = defaultExecGasLimit + } + + homeChainID, err := i.getChainID(i.homeChainSelector) + if err != nil { + return nil, nil, err + } + + contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) + chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + for relayID, relayer := range i.relayers { + chainID, ok := new(big.Int).SetString(relayID.ChainID, 10) + if !ok { + return nil, nil, fmt.Errorf("error parsing chain ID, expected big int: %s", relayID.ChainID) + } + + chainSelector, err1 := i.getChainSelector(chainID.Uint64()) + if err1 != nil { + return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s: %w", chainID.String(), err1) + } + + chainReaderConfig, err1 := getChainReaderConfig(chainID.Uint64(), destChainID, homeChainID, ofc, chainSelector) + if err1 != nil { + return nil, nil, fmt.Errorf("failed to get chain reader config: %w", err1) + } + + // TODO: context. + cr, err1 := relayer.NewContractReader(context.Background(), chainReaderConfig) + if err1 != nil { + return nil, nil, err1 + } + + if chainID.Uint64() == destChainID { + offrampAddressHex := common.BytesToAddress(config.Config.OfframpAddress).Hex() + err2 := cr.Bind(context.Background(), []types.BoundContract{ + { + Address: offrampAddressHex, + Name: consts.ContractNameOffRamp, + }, + }) + if err2 != nil { + return nil, nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chainID.String(), offrampAddressHex, err) + } + } + + if err2 := cr.Start(context.Background()); err2 != nil { + return nil, nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chainID.String(), err2) + } + + cw, err1 := createChainWriter( + chainID, + i.evmConfigs, + relayer, + i.transmitters, + execBatchGasLimit) + if err1 != nil { + return nil, nil, err1 + } + + if err4 := cw.Start(context.Background()); err4 != nil { + return nil, nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chainID.String(), err4) + } + + contractReaders[chainSelector] = cr + chainWriters[chainSelector] = cw + } + return contractReaders, chainWriters, nil +} + +func decodeAndValidateOffchainConfig( + pluginType cctypes.PluginType, + publicConfig ocr3confighelper.PublicConfig, +) (offChainConfig, error) { + var ofc offChainConfig + if pluginType == cctypes.PluginTypeCCIPExec { + execOffchainCfg, err1 := pluginconfig.DecodeExecuteOffchainConfig(publicConfig.ReportingPluginConfig) + if err1 != nil { + return offChainConfig{}, fmt.Errorf("failed to decode execute offchain config: %w, raw: %s", err1, string(publicConfig.ReportingPluginConfig)) + } + if err2 := execOffchainCfg.Validate(); err2 != nil { + return offChainConfig{}, fmt.Errorf("failed to validate execute offchain config: %w", err2) + } + ofc.execOffchainConfig = &execOffchainCfg + } else if pluginType == cctypes.PluginTypeCCIPCommit { + commitOffchainCfg, err1 := pluginconfig.DecodeCommitOffchainConfig(publicConfig.ReportingPluginConfig) + if err1 != nil { + return offChainConfig{}, fmt.Errorf("failed to decode commit offchain config: %w, raw: %s", err1, string(publicConfig.ReportingPluginConfig)) + } + if err2 := commitOffchainCfg.ApplyDefaultsAndValidate(); err2 != nil { + return offChainConfig{}, fmt.Errorf("failed to validate commit offchain config: %w", err2) + } + ofc.commitOffchainConfig = &commitOffchainCfg + } + if !ofc.isValid() { + return offChainConfig{}, fmt.Errorf("invalid offchain config: both commit and exec configs are either set or unset") + } + return ofc, nil +} + +func (i *pluginOracleCreator) getChainSelector(chainID uint64) (cciptypes.ChainSelector, error) { + chainSelector, ok := chainsel.EvmChainIdToChainSelector()[chainID] + if !ok { + return 0, fmt.Errorf("failed to get chain selector from chain ID %d", chainID) + } + return cciptypes.ChainSelector(chainSelector), nil +} + +func (i *pluginOracleCreator) getChainID(chainSelector cciptypes.ChainSelector) (uint64, error) { + chainID, err := chainsel.ChainIdFromSelector(uint64(chainSelector)) + if err != nil { + return 0, fmt.Errorf("failed to get chain ID from chain selector %d: %w", chainSelector, err) + } + return chainID, nil +} + +func getChainReaderConfig( + chainID uint64, + destChainID uint64, + homeChainID uint64, + ofc offChainConfig, + chainSelector cciptypes.ChainSelector, +) ([]byte, error) { + var chainReaderConfig evmrelaytypes.ChainReaderConfig + if chainID == destChainID { + chainReaderConfig = evmconfig.DestReaderConfig + } else { + chainReaderConfig = evmconfig.SourceReaderConfig + } + + if !ofc.commitEmpty() && ofc.commit().PriceFeedChainSelector == chainSelector { + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.FeedReaderConfig) + } + + if isUSDCEnabled(chainID, destChainID, ofc) { + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.USDCReaderConfig) + } + + if chainID == homeChainID { + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.HomeChainReaderConfigRaw) + } + + marshaledConfig, err := json.Marshal(chainReaderConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) + } + + return marshaledConfig, nil +} + +func isUSDCEnabled(chainID uint64, destChainID uint64, ofc offChainConfig) bool { + if chainID == destChainID { + return false + } + + if ofc.execEmpty() { + return false + } + + return ofc.exec().IsUSDCEnabled() +} + +func createChainWriter( + chainID *big.Int, + evmConfigs toml.EVMConfigs, + relayer loop.Relayer, + transmitters map[types.RelayID][]string, + execBatchGasLimit uint64, +) (types.ChainWriter, error) { + var fromAddress common.Address + transmitter, ok := transmitters[types.NewRelayID(relay.NetworkEVM, chainID.String())] + if ok { + // TODO: remove EVM-specific stuff + fromAddress = common.HexToAddress(transmitter[0]) + } + + maxGasPrice := getKeySpecificMaxGasPrice(evmConfigs, chainID, fromAddress) + if maxGasPrice == nil { + return nil, fmt.Errorf("failed to find max gas price for chain %s", chainID.String()) + } + + chainWriterRawConfig, err := evmconfig.ChainWriterConfigRaw( + fromAddress, + maxGasPrice, + defaultCommitGasLimit, + execBatchGasLimit, + ) + if err != nil { + return nil, fmt.Errorf("failed to create chain writer config: %w", err) + } + + chainWriterConfig, err := json.Marshal(chainWriterRawConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal chain writer config: %w", err) + } + + // TODO: context. + cw, err := relayer.NewChainWriter(context.Background(), chainWriterConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chainID.String(), err) + } + + return cw, nil +} + +func getKeySpecificMaxGasPrice(evmConfigs toml.EVMConfigs, chainID *big.Int, fromAddress common.Address) *assets.Wei { + var maxGasPrice *assets.Wei + + // If a chain is enabled it should have some configuration in the TOML config + // of the chainlink node. + for _, config := range evmConfigs { + if config.ChainID.ToInt().Cmp(chainID) != 0 { + continue + } + + // find the key-specific max gas price for the given fromAddress. + for _, keySpecific := range config.KeySpecific { + if keySpecific.Key.Address() == fromAddress { + maxGasPrice = keySpecific.GasEstimator.PriceMax + } + } + + // if we didn't find a key-specific max gas price, use the one specified + // in the gas estimator config, which should have a default value. + if maxGasPrice == nil { + maxGasPrice = config.GasEstimator.PriceMax + } + } + + return maxGasPrice +} + +type offChainConfig struct { + commitOffchainConfig *pluginconfig.CommitOffchainConfig + execOffchainConfig *pluginconfig.ExecuteOffchainConfig +} + +func (ofc offChainConfig) commitEmpty() bool { + return ofc.commitOffchainConfig == nil +} + +func (ofc offChainConfig) execEmpty() bool { + return ofc.execOffchainConfig == nil +} + +func (ofc offChainConfig) commit() *pluginconfig.CommitOffchainConfig { + return ofc.commitOffchainConfig +} + +func (ofc offChainConfig) exec() *pluginconfig.ExecuteOffchainConfig { + return ofc.execOffchainConfig +} + +// Exactly one of both plugins should be empty at any given time. +func (ofc offChainConfig) isValid() bool { + return (ofc.commitEmpty() && !ofc.execEmpty()) || (!ofc.commitEmpty() && ofc.execEmpty()) +} + +func defaultLocalConfig() ocrtypes.LocalConfig { + return ocrtypes.LocalConfig{ + DefaultMaxDurationInitialization: 30 * time.Second, + BlockchainTimeout: 10 * time.Second, + ContractConfigLoadTimeout: 10 * time.Second, + // Config tracking is handled by the launcher, since we're doing blue-green + // deployments we're not going to be using OCR's built-in config switching, + // which always shuts down the previous instance. + ContractConfigConfirmations: 1, + SkipContractConfigConfirmations: true, + ContractConfigTrackerPollInterval: 10 * time.Second, + ContractTransmitterTransmitTimeout: 10 * time.Second, + DatabaseTimeout: 10 * time.Second, + MinOCR2MaxDurationQuery: 1 * time.Second, + DevelopmentMode: "false", + } +} diff --git a/core/capabilities/ccip/oraclecreator/wrapped_oracle.go b/core/capabilities/ccip/oraclecreator/wrapped_oracle.go new file mode 100644 index 00000000000..0ecde57dac3 --- /dev/null +++ b/core/capabilities/ccip/oraclecreator/wrapped_oracle.go @@ -0,0 +1,42 @@ +package oraclecreator + +import ( + "errors" + "fmt" + "io" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" +) + +// wrappedOracle is a wrapper for cctypes.CCIPOracle that allows custom actions on Oracle shutdown. +type wrappedOracle struct { + baseOracle cctypes.CCIPOracle + + // closableResources will be closed after calling baseOracle.Close() + closableResources []io.Closer +} + +func newWrappedOracle(baseOracle cctypes.CCIPOracle, closableResources []io.Closer) cctypes.CCIPOracle { + return &wrappedOracle{ + baseOracle: baseOracle, + closableResources: closableResources, + } +} + +func (o *wrappedOracle) Start() error { + return o.baseOracle.Start() +} + +func (o *wrappedOracle) Close() error { + errs := make([]error, 0) + + if err := o.baseOracle.Close(); err != nil { + errs = append(errs, fmt.Errorf("close base oracle: %w", err)) + } + + errs = append(errs, services.CloseAll(o.closableResources...)) + + return errors.Join(errs...) +} diff --git a/core/capabilities/ccip/oraclecreator/wrapped_oracle_test.go b/core/capabilities/ccip/oraclecreator/wrapped_oracle_test.go new file mode 100644 index 00000000000..062ed8d56c8 --- /dev/null +++ b/core/capabilities/ccip/oraclecreator/wrapped_oracle_test.go @@ -0,0 +1,81 @@ +package oraclecreator + +import ( + "errors" + "io" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_wrappedOracle_Close(t *testing.T) { + tests := []struct { + name string + oracleErr error + closerErrors []error + expectedErr error + }{ + { + name: "no errors", + expectedErr: nil, + }, + { + name: "oracle error", + oracleErr: err1, + expectedErr: errors.New("close base oracle: err1"), + }, + { + name: "oracle and closers errors", + oracleErr: err1, + closerErrors: []error{nil, nil, err3}, + expectedErr: errors.New("close base oracle: err1\nerr3"), + }, + { + name: "closers only errors", + oracleErr: nil, + closerErrors: []error{nil, err2, nil}, + expectedErr: err2, + }, + { + name: "no errors with closers", + closerErrors: []error{nil, nil, nil, nil}, + expectedErr: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + closers := make([]io.Closer, 0, len(tt.closerErrors)) + for _, err := range tt.closerErrors { + closers = append(closers, mockCloser{err: err}) + } + + o := newWrappedOracle(mockOracle{err: tt.oracleErr}, closers) + + err := o.Close() + if err == nil && tt.expectedErr == nil { + assert.NoError(t, err) + return + } + + assert.Error(t, err) + assert.Equal(t, tt.expectedErr.Error(), err.Error()) + }) + } +} + +type mockCloser struct{ err error } + +func (m mockCloser) Close() error { return m.err } + +type mockOracle struct{ err error } + +func (m mockOracle) Close() error { return m.err } + +func (m mockOracle) Start() error { return m.err } + +var ( + err1 = errors.New("err1") + err2 = errors.New("err2") + err3 = errors.New("err3") +) diff --git a/core/capabilities/ccip/types/mocks/home_chain_reader.go b/core/capabilities/ccip/types/mocks/home_chain_reader.go index a5a581a1d2d..4624332c055 100644 --- a/core/capabilities/ccip/types/mocks/home_chain_reader.go +++ b/core/capabilities/ccip/types/mocks/home_chain_reader.go @@ -8,7 +8,7 @@ import ( ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/libocr/ragep2p/types" ) diff --git a/core/capabilities/ccip/types/mocks/oracle_creator.go b/core/capabilities/ccip/types/mocks/oracle_creator.go index d83ad042bfe..362a89a94d9 100644 --- a/core/capabilities/ccip/types/mocks/oracle_creator.go +++ b/core/capabilities/ccip/types/mocks/oracle_creator.go @@ -20,29 +20,29 @@ func (_m *OracleCreator) EXPECT() *OracleCreator_Expecter { return &OracleCreator_Expecter{mock: &_m.Mock} } -// CreateBootstrapOracle provides a mock function with given fields: config -func (_m *OracleCreator) CreateBootstrapOracle(config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { - ret := _m.Called(config) +// Create provides a mock function with given fields: donID, config +func (_m *OracleCreator) Create(donID uint32, config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { + ret := _m.Called(donID, config) if len(ret) == 0 { - panic("no return value specified for CreateBootstrapOracle") + panic("no return value specified for Create") } var r0 types.CCIPOracle var r1 error - if rf, ok := ret.Get(0).(func(types.OCR3ConfigWithMeta) (types.CCIPOracle, error)); ok { - return rf(config) + if rf, ok := ret.Get(0).(func(uint32, types.OCR3ConfigWithMeta) (types.CCIPOracle, error)); ok { + return rf(donID, config) } - if rf, ok := ret.Get(0).(func(types.OCR3ConfigWithMeta) types.CCIPOracle); ok { - r0 = rf(config) + if rf, ok := ret.Get(0).(func(uint32, types.OCR3ConfigWithMeta) types.CCIPOracle); ok { + r0 = rf(donID, config) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(types.CCIPOracle) } } - if rf, ok := ret.Get(1).(func(types.OCR3ConfigWithMeta) error); ok { - r1 = rf(config) + if rf, ok := ret.Get(1).(func(uint32, types.OCR3ConfigWithMeta) error); ok { + r1 = rf(donID, config) } else { r1 = ret.Error(1) } @@ -50,89 +50,76 @@ func (_m *OracleCreator) CreateBootstrapOracle(config types.OCR3ConfigWithMeta) return r0, r1 } -// OracleCreator_CreateBootstrapOracle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateBootstrapOracle' -type OracleCreator_CreateBootstrapOracle_Call struct { +// OracleCreator_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type OracleCreator_Create_Call struct { *mock.Call } -// CreateBootstrapOracle is a helper method to define mock.On call +// Create is a helper method to define mock.On call +// - donID uint32 // - config types.OCR3ConfigWithMeta -func (_e *OracleCreator_Expecter) CreateBootstrapOracle(config interface{}) *OracleCreator_CreateBootstrapOracle_Call { - return &OracleCreator_CreateBootstrapOracle_Call{Call: _e.mock.On("CreateBootstrapOracle", config)} +func (_e *OracleCreator_Expecter) Create(donID interface{}, config interface{}) *OracleCreator_Create_Call { + return &OracleCreator_Create_Call{Call: _e.mock.On("Create", donID, config)} } -func (_c *OracleCreator_CreateBootstrapOracle_Call) Run(run func(config types.OCR3ConfigWithMeta)) *OracleCreator_CreateBootstrapOracle_Call { +func (_c *OracleCreator_Create_Call) Run(run func(donID uint32, config types.OCR3ConfigWithMeta)) *OracleCreator_Create_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.OCR3ConfigWithMeta)) + run(args[0].(uint32), args[1].(types.OCR3ConfigWithMeta)) }) return _c } -func (_c *OracleCreator_CreateBootstrapOracle_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_CreateBootstrapOracle_Call { +func (_c *OracleCreator_Create_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_Create_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *OracleCreator_CreateBootstrapOracle_Call) RunAndReturn(run func(types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_CreateBootstrapOracle_Call { +func (_c *OracleCreator_Create_Call) RunAndReturn(run func(uint32, types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_Create_Call { _c.Call.Return(run) return _c } -// CreatePluginOracle provides a mock function with given fields: pluginType, config -func (_m *OracleCreator) CreatePluginOracle(pluginType types.PluginType, config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { - ret := _m.Called(pluginType, config) +// Type provides a mock function with given fields: +func (_m *OracleCreator) Type() types.OracleType { + ret := _m.Called() if len(ret) == 0 { - panic("no return value specified for CreatePluginOracle") + panic("no return value specified for Type") } - var r0 types.CCIPOracle - var r1 error - if rf, ok := ret.Get(0).(func(types.PluginType, types.OCR3ConfigWithMeta) (types.CCIPOracle, error)); ok { - return rf(pluginType, config) - } - if rf, ok := ret.Get(0).(func(types.PluginType, types.OCR3ConfigWithMeta) types.CCIPOracle); ok { - r0 = rf(pluginType, config) + var r0 types.OracleType + if rf, ok := ret.Get(0).(func() types.OracleType); ok { + r0 = rf() } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.CCIPOracle) - } + r0 = ret.Get(0).(types.OracleType) } - if rf, ok := ret.Get(1).(func(types.PluginType, types.OCR3ConfigWithMeta) error); ok { - r1 = rf(pluginType, config) - } else { - r1 = ret.Error(1) - } - - return r0, r1 + return r0 } -// OracleCreator_CreatePluginOracle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePluginOracle' -type OracleCreator_CreatePluginOracle_Call struct { +// OracleCreator_Type_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Type' +type OracleCreator_Type_Call struct { *mock.Call } -// CreatePluginOracle is a helper method to define mock.On call -// - pluginType types.PluginType -// - config types.OCR3ConfigWithMeta -func (_e *OracleCreator_Expecter) CreatePluginOracle(pluginType interface{}, config interface{}) *OracleCreator_CreatePluginOracle_Call { - return &OracleCreator_CreatePluginOracle_Call{Call: _e.mock.On("CreatePluginOracle", pluginType, config)} +// Type is a helper method to define mock.On call +func (_e *OracleCreator_Expecter) Type() *OracleCreator_Type_Call { + return &OracleCreator_Type_Call{Call: _e.mock.On("Type")} } -func (_c *OracleCreator_CreatePluginOracle_Call) Run(run func(pluginType types.PluginType, config types.OCR3ConfigWithMeta)) *OracleCreator_CreatePluginOracle_Call { +func (_c *OracleCreator_Type_Call) Run(run func()) *OracleCreator_Type_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.PluginType), args[1].(types.OCR3ConfigWithMeta)) + run() }) return _c } -func (_c *OracleCreator_CreatePluginOracle_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_CreatePluginOracle_Call { - _c.Call.Return(_a0, _a1) +func (_c *OracleCreator_Type_Call) Return(_a0 types.OracleType) *OracleCreator_Type_Call { + _c.Call.Return(_a0) return _c } -func (_c *OracleCreator_CreatePluginOracle_Call) RunAndReturn(run func(types.PluginType, types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_CreatePluginOracle_Call { +func (_c *OracleCreator_Type_Call) RunAndReturn(run func() types.OracleType) *OracleCreator_Type_Call { _c.Call.Return(run) return _c } diff --git a/core/capabilities/ccip/types/types.go b/core/capabilities/ccip/types/types.go index 952b8fe4465..04da1157b33 100644 --- a/core/capabilities/ccip/types/types.go +++ b/core/capabilities/ccip/types/types.go @@ -27,6 +27,13 @@ func (pt PluginType) String() string { } } +type OracleType uint8 + +const ( + OracleTypePlugin OracleType = 0 + OracleTypeBootstrap OracleType = 1 +) + // CCIPOracle represents either a CCIP commit or exec oracle or a bootstrap node. type CCIPOracle interface { Close() error @@ -36,11 +43,12 @@ type CCIPOracle interface { // OracleCreator is an interface for creating CCIP oracles. // Whether the oracle uses a LOOPP or not is an implementation detail. type OracleCreator interface { - // CreatePlugin creates a new oracle that will run either the commit or exec ccip plugin. + // Create creates a new oracle that will run either the commit or exec ccip plugin, + // if its a plugin oracle, or a bootstrap oracle if its a bootstrap oracle. // The oracle must be returned unstarted. - CreatePluginOracle(pluginType PluginType, config OCR3ConfigWithMeta) (CCIPOracle, error) + Create(donID uint32, config OCR3ConfigWithMeta) (CCIPOracle, error) - // CreateBootstrapOracle creates a new bootstrap node with the given OCR config. - // The oracle must be returned unstarted. - CreateBootstrapOracle(config OCR3ConfigWithMeta) (CCIPOracle, error) + // Type returns the type of oracle that this creator creates. + // The only valid values are OracleTypePlugin and OracleTypeBootstrap. + Type() OracleType } diff --git a/core/capabilities/ccip/validate/validate.go b/core/capabilities/ccip/validate/validate.go index 04f4f4a4959..02e1cb5c8ee 100644 --- a/core/capabilities/ccip/validate/validate.go +++ b/core/capabilities/ccip/validate/validate.go @@ -40,9 +40,6 @@ func ValidatedCCIPSpec(tomlString string) (jb job.Job, err error) { if jb.CCIPSpec.P2PKeyID == "" { return job.Job{}, fmt.Errorf("p2pKeyID must be set") } - if len(jb.CCIPSpec.P2PV2Bootstrappers) == 0 { - return job.Job{}, fmt.Errorf("p2pV2Bootstrappers must be set") - } // ensure that the P2PV2Bootstrappers is in the right format. for _, bootstrapperLocator := range jb.CCIPSpec.P2PV2Bootstrappers { diff --git a/core/capabilities/compute/cache.go b/core/capabilities/compute/cache.go new file mode 100644 index 00000000000..7b7cd78aaab --- /dev/null +++ b/core/capabilities/compute/cache.go @@ -0,0 +1,132 @@ +package compute + +import ( + "sync" + "time" + + "github.com/jonboulle/clockwork" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" +) + +var ( + moduleCacheHit = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "compute_module_cache_hit", + Help: "hit vs non-hits of the module cache for custom compute", + }, []string{"hit"}) + moduleCacheEviction = promauto.NewCounter(prometheus.CounterOpts{ + Name: "compute_module_cache_eviction", + Help: "evictions from the module cache", + }) + moduleCacheAddition = promauto.NewCounter(prometheus.CounterOpts{ + Name: "compute_module_cache_addition", + Help: "additions to the module cache", + }) +) + +type moduleCache struct { + m map[string]*module + mu sync.RWMutex + + wg sync.WaitGroup + stopChan services.StopChan + + tickInterval time.Duration + timeout time.Duration + evictAfterSize int + + clock clockwork.Clock + onReaper chan struct{} +} + +func newModuleCache(clock clockwork.Clock, tick, timeout time.Duration, evictAfterSize int) *moduleCache { + return &moduleCache{ + m: map[string]*module{}, + tickInterval: tick, + timeout: timeout, + evictAfterSize: evictAfterSize, + clock: clock, + stopChan: make(chan struct{}), + } +} + +func (mc *moduleCache) start() { + mc.wg.Add(1) + go func() { + defer mc.wg.Done() + mc.reapLoop() + }() +} + +func (mc *moduleCache) close() { + close(mc.stopChan) + mc.wg.Wait() +} + +func (mc *moduleCache) reapLoop() { + ticker := mc.clock.NewTicker(mc.tickInterval) + for { + select { + case <-ticker.Chan(): + mc.evictOlderThan(mc.timeout) + if mc.onReaper != nil { + mc.onReaper <- struct{}{} + } + case <-mc.stopChan: + return + } + } +} + +func (mc *moduleCache) add(id string, mod *module) { + mc.mu.Lock() + defer mc.mu.Unlock() + mod.lastFetchedAt = time.Now() + mc.m[id] = mod + moduleCacheAddition.Inc() +} + +func (mc *moduleCache) get(id string) (*module, bool) { + mc.mu.Lock() + defer mc.mu.Unlock() + gotModule, ok := mc.m[id] + if !ok { + moduleCacheHit.WithLabelValues("false").Inc() + return nil, false + } + + moduleCacheHit.WithLabelValues("true").Inc() + gotModule.lastFetchedAt = mc.clock.Now() + return gotModule, true +} + +func (mc *moduleCache) evictOlderThan(duration time.Duration) { + mc.mu.Lock() + defer mc.mu.Unlock() + + evicted := 0 + + if len(mc.m) > mc.evictAfterSize { + for id, m := range mc.m { + if mc.clock.Now().Sub(m.lastFetchedAt) > duration { + delete(mc.m, id) + m.module.Close() + evicted++ + } + + if len(mc.m) <= mc.evictAfterSize { + break + } + } + } + + moduleCacheEviction.Add(float64(evicted)) +} + +type module struct { + module *host.Module + lastFetchedAt time.Time +} diff --git a/core/capabilities/compute/cache_test.go b/core/capabilities/compute/cache_test.go new file mode 100644 index 00000000000..358eb37f4e3 --- /dev/null +++ b/core/capabilities/compute/cache_test.go @@ -0,0 +1,94 @@ +package compute + +import ( + "testing" + "time" + + "github.com/google/uuid" + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +const ( + binaryLocation = "test/simple/cmd/testmodule.wasm" + binaryCmd = "core/capabilities/compute/test/simple/cmd" +) + +func TestCache(t *testing.T) { + clock := clockwork.NewFakeClock() + tick := 1 * time.Second + timeout := 1 * time.Second + + cache := newModuleCache(clock, tick, timeout, 0) + cache.onReaper = make(chan struct{}, 1) + cache.start() + defer cache.close() + + binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, false, t) + hmod, err := host.NewModule(&host.ModuleConfig{ + Logger: logger.TestLogger(t), + IsUncompressed: true, + }, binary) + require.NoError(t, err) + + id := uuid.New().String() + mod := &module{ + module: hmod, + } + cache.add(id, mod) + + got, ok := cache.get(id) + assert.True(t, ok) + + assert.Equal(t, got, mod) + + clock.Advance(15 * time.Second) + <-cache.onReaper + _, ok = cache.get(id) + assert.False(t, ok) +} + +func TestCache_EvictAfterSize(t *testing.T) { + ctx := tests.Context(t) + clock := clockwork.NewFakeClock() + tick := 1 * time.Second + timeout := 1 * time.Second + + cache := newModuleCache(clock, tick, timeout, 1) + cache.onReaper = make(chan struct{}, 1) + cache.start() + defer cache.close() + + binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, false, t) + hmod, err := host.NewModule(&host.ModuleConfig{ + Logger: logger.TestLogger(t), + IsUncompressed: true, + }, binary) + require.NoError(t, err) + + id := uuid.New().String() + mod := &module{ + module: hmod, + } + cache.add(id, mod) + + got, ok := cache.get(id) + assert.True(t, ok) + + assert.Equal(t, got, mod) + + clock.Advance(15 * time.Second) + select { + case <-ctx.Done(): + return + case <-cache.onReaper: + } + _, ok = cache.get(id) + assert.True(t, ok) +} diff --git a/core/capabilities/compute/compute.go b/core/capabilities/compute/compute.go new file mode 100644 index 00000000000..4de17e290ca --- /dev/null +++ b/core/capabilities/compute/compute.go @@ -0,0 +1,256 @@ +package compute + +import ( + "context" + "crypto/sha256" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/google/uuid" + "github.com/jonboulle/clockwork" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + wasmpb "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/pb" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" +) + +const ( + CapabilityIDCompute = "custom_compute@1.0.0" + + binaryKey = "binary" + configKey = "config" + maxMemoryMBsKey = "maxMemoryMBs" + timeoutKey = "timeout" + tickIntervalKey = "tickInterval" +) + +var ( + computeWASMInit = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "compute_wasm_module_init", + Help: "how long it takes to initialize a WASM module", + Buckets: []float64{ + float64(50 * time.Millisecond), + float64(100 * time.Millisecond), + float64(200 * time.Millisecond), + float64(500 * time.Millisecond), + float64(1 * time.Second), + float64(2 * time.Second), + float64(4 * time.Second), + float64(8 * time.Second), + }, + }, []string{"workflowID", "stepRef"}) + computeWASMExec = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "compute_wasm_module_exec", + Help: "how long it takes to execute a request from a WASM module", + Buckets: []float64{ + float64(50 * time.Millisecond), + float64(100 * time.Millisecond), + float64(200 * time.Millisecond), + float64(500 * time.Millisecond), + float64(1 * time.Second), + float64(2 * time.Second), + float64(4 * time.Second), + float64(8 * time.Second), + }, + }, []string{"workflowID", "stepRef"}) +) + +var _ capabilities.ActionCapability = (*Compute)(nil) + +type Compute struct { + log logger.Logger + registry coretypes.CapabilitiesRegistry + modules *moduleCache + + transformer ConfigTransformer + outgoingConnectorHandler *webapi.OutgoingConnectorHandler + idGenerator func() string +} + +func (c *Compute) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { + return nil +} + +func (c *Compute) UnregisterFromWorkflow(ctx context.Context, request capabilities.UnregisterFromWorkflowRequest) error { + return nil +} + +func generateID(binary []byte) string { + id := sha256.Sum256(binary) + return fmt.Sprintf("%x", id) +} + +func copyRequest(req capabilities.CapabilityRequest) capabilities.CapabilityRequest { + return capabilities.CapabilityRequest{ + Metadata: req.Metadata, + Inputs: req.Inputs.CopyMap(), + Config: req.Config.CopyMap(), + } +} + +func (c *Compute) Execute(ctx context.Context, request capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + copied := copyRequest(request) + + cfg, err := c.transformer.Transform(copied.Config, WithLogger(c.log)) + if err != nil { + return capabilities.CapabilityResponse{}, fmt.Errorf("invalid request: could not transform config: %w", err) + } + + id := generateID(cfg.Binary) + + m, ok := c.modules.get(id) + if !ok { + mod, err := c.initModule(id, cfg.ModuleConfig, cfg.Binary, request.Metadata.WorkflowID, request.Metadata.WorkflowExecutionID, request.Metadata.ReferenceID) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + m = mod + } + + return c.executeWithModule(m.module, cfg.Config, request) +} + +func (c *Compute) initModule(id string, cfg *host.ModuleConfig, binary []byte, workflowID, workflowExecutionID, referenceID string) (*module, error) { + initStart := time.Now() + + cfg.Fetch = c.createFetcher(workflowID, workflowExecutionID) + mod, err := host.NewModule(cfg, binary) + if err != nil { + return nil, fmt.Errorf("failed to instantiate WASM module: %w", err) + } + + mod.Start() + + initDuration := time.Since(initStart) + computeWASMInit.WithLabelValues(workflowID, referenceID).Observe(float64(initDuration)) + + m := &module{module: mod} + c.modules.add(id, m) + return m, nil +} + +func (c *Compute) executeWithModule(module *host.Module, config []byte, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + executeStart := time.Now() + capReq := capabilitiespb.CapabilityRequestToProto(req) + + wasmReq := &wasmpb.Request{ + Id: uuid.New().String(), + Config: config, + Message: &wasmpb.Request_ComputeRequest{ + ComputeRequest: &wasmpb.ComputeRequest{ + Request: capReq, + }, + }, + } + resp, err := module.Run(wasmReq) + if err != nil { + return capabilities.CapabilityResponse{}, fmt.Errorf("error running module: %w", err) + } + + cresppb := resp.GetComputeResponse().GetResponse() + if cresppb == nil { + return capabilities.CapabilityResponse{}, errors.New("got nil compute response") + } + + cresp, err := capabilitiespb.CapabilityResponseFromProto(cresppb) + if err != nil { + return capabilities.CapabilityResponse{}, fmt.Errorf("could not convert response proto into response: %w", err) + } + + computeWASMExec.WithLabelValues( + req.Metadata.WorkflowID, + req.Metadata.ReferenceID, + ).Observe(float64(time.Since(executeStart))) + + return cresp, nil +} + +func (c *Compute) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return capabilities.NewCapabilityInfo( + CapabilityIDCompute, + capabilities.CapabilityTypeAction, + "WASM custom compute capability", + ) +} + +func (c *Compute) Start(ctx context.Context) error { + c.modules.start() + return c.registry.Add(ctx, c) +} + +func (c *Compute) Close() error { + c.modules.close() + return nil +} + +func (c *Compute) createFetcher(workflowID, workflowExecutionID string) func(req *wasmpb.FetchRequest) (*wasmpb.FetchResponse, error) { + return func(req *wasmpb.FetchRequest) (*wasmpb.FetchResponse, error) { + if err := validation.ValidateWorkflowOrExecutionID(workflowID); err != nil { + return nil, fmt.Errorf("workflow ID %q is invalid: %w", workflowID, err) + } + if err := validation.ValidateWorkflowOrExecutionID(workflowExecutionID); err != nil { + return nil, fmt.Errorf("workflow execution ID %q is invalid: %w", workflowExecutionID, err) + } + + messageID := strings.Join([]string{ + workflowID, + workflowExecutionID, + ghcapabilities.MethodComputeAction, + c.idGenerator(), + }, "/") + + fields := req.Headers.GetFields() + headersReq := make(map[string]string, len(fields)) + for k, v := range fields { + headersReq[k] = v.String() + } + + payloadBytes, err := json.Marshal(ghcapabilities.Request{ + URL: req.Url, + Method: req.Method, + Headers: headersReq, + Body: req.Body, + TimeoutMs: req.TimeoutMs, + }) + if err != nil { + return nil, fmt.Errorf("failed to marshal fetch request: %w", err) + } + + resp, err := c.outgoingConnectorHandler.HandleSingleNodeRequest(context.Background(), messageID, payloadBytes) + if err != nil { + return nil, err + } + + c.log.Debugw("received gateway response", "resp", resp) + var response wasmpb.FetchResponse + err = json.Unmarshal(resp.Body.Payload, &response) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal fetch response: %w", err) + } + return &response, nil + } +} + +func NewAction(config webapi.ServiceConfig, log logger.Logger, registry coretypes.CapabilitiesRegistry, handler *webapi.OutgoingConnectorHandler, idGenerator func() string) *Compute { + compute := &Compute{ + log: logger.Named(log, "CustomCompute"), + registry: registry, + modules: newModuleCache(clockwork.NewRealClock(), 1*time.Minute, 10*time.Minute, 3), + transformer: NewTransformer(), + outgoingConnectorHandler: handler, + idGenerator: idGenerator, + } + return compute +} diff --git a/core/capabilities/compute/compute_test.go b/core/capabilities/compute/compute_test.go new file mode 100644 index 00000000000..35021969ebe --- /dev/null +++ b/core/capabilities/compute/compute_test.go @@ -0,0 +1,257 @@ +package compute + +import ( + "context" + "encoding/json" + "strings" + "testing" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + + cappkg "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/values" + corecapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" +) + +const ( + fetchBinaryLocation = "test/fetch/cmd/testmodule.wasm" + fetchBinaryCmd = "core/capabilities/compute/test/fetch/cmd" + validRequestUUID = "d2fe6db9-beb4-47c9-b2d6-d3065ace111e" +) + +var defaultConfig = webapi.ServiceConfig{ + RateLimiter: common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + }, +} + +type testHarness struct { + registry *corecapabilities.Registry + connector *gcmocks.GatewayConnector + log logger.Logger + config webapi.ServiceConfig + connectorHandler *webapi.OutgoingConnectorHandler + compute *Compute +} + +func setup(t *testing.T, config webapi.ServiceConfig) testHarness { + log := logger.TestLogger(t) + registry := capabilities.NewRegistry(log) + connector := gcmocks.NewGatewayConnector(t) + idGeneratorFn := func() string { return validRequestUUID } + connectorHandler, err := webapi.NewOutgoingConnectorHandler(connector, config, ghcapabilities.MethodComputeAction, log) + require.NoError(t, err) + + compute := NewAction(config, log, registry, connectorHandler, idGeneratorFn) + compute.modules.clock = clockwork.NewFakeClock() + + return testHarness{ + registry: registry, + connector: connector, + log: log, + config: config, + connectorHandler: connectorHandler, + compute: compute, + } +} + +func TestComputeStartAddsToRegistry(t *testing.T) { + th := setup(t, defaultConfig) + + require.NoError(t, th.compute.Start(tests.Context(t))) + + cp, err := th.registry.Get(tests.Context(t), CapabilityIDCompute) + require.NoError(t, err) + assert.Equal(t, th.compute, cp) +} + +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) + + config, err := values.WrapMap(map[string]any{ + "binary": binary, + }) + require.NoError(t, err) + req := cappkg.CapabilityRequest{ + Inputs: values.EmptyMap(), + Config: config, + Metadata: cappkg.RequestMetadata{ + ReferenceID: "compute", + }, + } + _, err = th.compute.Execute(tests.Context(t), req) + assert.ErrorContains(t, err, "invalid request: could not find \"config\" in map") +} + +func TestComputeExecuteMissingBinary(t *testing.T) { + th := setup(t, defaultConfig) + + require.NoError(t, th.compute.Start(tests.Context(t))) + + config, err := values.WrapMap(map[string]any{ + "config": []byte(""), + }) + require.NoError(t, err) + req := cappkg.CapabilityRequest{ + Inputs: values.EmptyMap(), + Config: config, + Metadata: cappkg.RequestMetadata{ + ReferenceID: "compute", + }, + } + _, err = th.compute.Execute(tests.Context(t), req) + assert.ErrorContains(t, err, "invalid request: could not find \"binary\" in map") +} + +func TestComputeExecute(t *testing.T) { + th := setup(t, defaultConfig) + + require.NoError(t, th.compute.Start(tests.Context(t))) + + binary := wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) + + config, err := values.WrapMap(map[string]any{ + "config": []byte(""), + "binary": binary, + }) + require.NoError(t, err) + inputs, err := values.WrapMap(map[string]any{ + "arg0": map[string]any{ + "cool_output": "foo", + }, + }) + require.NoError(t, err) + req := cappkg.CapabilityRequest{ + Inputs: inputs, + Config: config, + Metadata: cappkg.RequestMetadata{ + WorkflowID: "workflowID", + ReferenceID: "compute", + }, + } + resp, err := th.compute.Execute(tests.Context(t), req) + assert.NoError(t, err) + assert.True(t, resp.Value.Underlying["Value"].(*values.Bool).Underlying) + + inputs, err = values.WrapMap(map[string]any{ + "arg0": map[string]any{ + "cool_output": "baz", + }, + }) + require.NoError(t, err) + config, err = values.WrapMap(map[string]any{ + "config": []byte(""), + "binary": binary, + }) + require.NoError(t, err) + req = cappkg.CapabilityRequest{ + Inputs: inputs, + Config: config, + Metadata: cappkg.RequestMetadata{ + ReferenceID: "compute", + }, + } + resp, err = th.compute.Execute(tests.Context(t), req) + assert.NoError(t, err) + assert.False(t, resp.Value.Underlying["Value"].(*values.Bool).Underlying) +} + +func TestComputeFetch(t *testing.T) { + workflowID := "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0" + workflowExecutionID := "95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0abbadeed" + th := setup(t, defaultConfig) + + th.connector.EXPECT().DonID().Return("don-id") + th.connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) + + msgID := strings.Join([]string{ + workflowID, + workflowExecutionID, + ghcapabilities.MethodComputeAction, + validRequestUUID, + }, "/") + + gatewayResp := gatewayResponse(t, msgID) + th.connector.On("SignAndSendToGateway", mock.Anything, "gateway1", mock.Anything).Return(nil).Run(func(args mock.Arguments) { + th.connectorHandler.HandleGatewayMessage(context.Background(), "gateway1", gatewayResp) + }).Once() + + require.NoError(t, th.compute.Start(tests.Context(t))) + + binary := wasmtest.CreateTestBinary(fetchBinaryCmd, fetchBinaryLocation, true, t) + + config, err := values.WrapMap(map[string]any{ + "config": []byte(""), + "binary": binary, + }) + require.NoError(t, err) + + req := cappkg.CapabilityRequest{ + Config: config, + Metadata: cappkg.RequestMetadata{ + WorkflowID: workflowID, + WorkflowExecutionID: workflowExecutionID, + ReferenceID: "compute", + }, + } + + headers, err := values.NewMap(map[string]any{}) + require.NoError(t, err) + expected := cappkg.CapabilityResponse{ + Value: &values.Map{ + Underlying: map[string]values.Value{ + "Value": &values.Map{ + Underlying: map[string]values.Value{ + "Body": values.NewBytes([]byte("response body")), + "Headers": headers, + "StatusCode": values.NewInt64(200), + "ErrorMessage": values.NewString(""), + "ExecutionError": values.NewBool(false), + }, + }, + }, + }, + } + + actual, err := th.compute.Execute(tests.Context(t), req) + require.NoError(t, err) + assert.EqualValues(t, expected, actual) +} + +func gatewayResponse(t *testing.T, msgID 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, + }) + require.NoError(t, err) + return &api.Message{ + Body: api.MessageBody{ + MessageId: msgID, + Method: ghcapabilities.MethodComputeAction, + Payload: responsePayload, + }, + } +} diff --git a/core/capabilities/compute/test/fetch/cmd/main.go b/core/capabilities/compute/test/fetch/cmd/main.go new file mode 100644 index 00000000000..bc45b426005 --- /dev/null +++ b/core/capabilities/compute/test/fetch/cmd/main.go @@ -0,0 +1,43 @@ +//go:build wasip1 + +package main + +import ( + "net/http" + + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/testdata/fixtures/capabilities/basictrigger" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) + + triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} + trigger := triggerCfg.New(workflow) + + sdk.Compute1[basictrigger.TriggerOutputs, sdk.FetchResponse]( + workflow, + "compute", + sdk.Compute1Inputs[basictrigger.TriggerOutputs]{Arg0: trigger}, + func(rsdk sdk.Runtime, outputs basictrigger.TriggerOutputs) (sdk.FetchResponse, error) { + return rsdk.Fetch(sdk.FetchRequest{ + Method: http.MethodGet, + URL: "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=BTC", + }) + }) + + return workflow +} + +func main() { + runner := wasm.NewRunner() + workflow := BuildWorkflow(runner.Config()) + runner.Run(workflow) +} diff --git a/core/capabilities/compute/test/simple/cmd/main.go b/core/capabilities/compute/test/simple/cmd/main.go new file mode 100644 index 00000000000..4ddacebe30b --- /dev/null +++ b/core/capabilities/compute/test/simple/cmd/main.go @@ -0,0 +1,38 @@ +//go:build wasip1 + +package main + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/testdata/fixtures/capabilities/basictrigger" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) + + triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} + trigger := triggerCfg.New(workflow) + + sdk.Compute1[basictrigger.TriggerOutputs, bool]( + workflow, + "compute", + sdk.Compute1Inputs[basictrigger.TriggerOutputs]{Arg0: trigger}, + func(sdk sdk.Runtime, outputs basictrigger.TriggerOutputs) (bool, error) { + return outputs.CoolOutput == "foo", nil + }) + + return workflow +} + +func main() { + runner := wasm.NewRunner() + workflow := BuildWorkflow(runner.Config()) + runner.Run(workflow) +} diff --git a/core/capabilities/compute/transformer.go b/core/capabilities/compute/transformer.go new file mode 100644 index 00000000000..7eca7b7c72f --- /dev/null +++ b/core/capabilities/compute/transformer.go @@ -0,0 +1,149 @@ +package compute + +import ( + "errors" + "fmt" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" +) + +type Transformer[T any, U any] interface { + Transform(T, ...func(*U)) (*U, error) +} + +type ConfigTransformer = Transformer[*values.Map, ParsedConfig] + +type ParsedConfig struct { + Binary []byte + Config []byte + ModuleConfig *host.ModuleConfig +} + +type transformer struct{} + +func (t *transformer) Transform(in *values.Map, opts ...func(*ParsedConfig)) (*ParsedConfig, error) { + binary, err := popValue[[]byte](in, binaryKey) + if err != nil { + return nil, NewInvalidRequestError(err) + } + + config, err := popValue[[]byte](in, configKey) + if err != nil { + return nil, NewInvalidRequestError(err) + } + + maxMemoryMBs, err := popOptionalValue[int64](in, maxMemoryMBsKey) + if err != nil { + return nil, NewInvalidRequestError(err) + } + + mc := &host.ModuleConfig{ + MaxMemoryMBs: maxMemoryMBs, + } + + timeout, err := popOptionalValue[string](in, timeoutKey) + if err != nil { + return nil, NewInvalidRequestError(err) + } + + var td time.Duration + if timeout != "" { + td, err = time.ParseDuration(timeout) + if err != nil { + return nil, NewInvalidRequestError(err) + } + mc.Timeout = &td + } + + tickInterval, err := popOptionalValue[string](in, tickIntervalKey) + if err != nil { + return nil, NewInvalidRequestError(err) + } + + var ti time.Duration + if tickInterval != "" { + ti, err = time.ParseDuration(tickInterval) + if err != nil { + return nil, NewInvalidRequestError(err) + } + mc.TickInterval = ti + } + + pc := &ParsedConfig{ + Binary: binary, + Config: config, + ModuleConfig: mc, + } + + for _, opt := range opts { + opt(pc) + } + + return pc, nil +} + +func NewTransformer() *transformer { + return &transformer{} +} + +func WithLogger(l logger.Logger) func(*ParsedConfig) { + return func(pc *ParsedConfig) { + pc.ModuleConfig.Logger = l + } +} + +func popOptionalValue[T any](m *values.Map, key string) (T, error) { + v, err := popValue[T](m, key) + if err != nil { + var nfe *NotFoundError + if errors.As(err, &nfe) { + return v, nil + } + return v, err + } + return v, nil +} + +func popValue[T any](m *values.Map, key string) (T, error) { + var empty T + + wrapped, ok := m.Underlying[key] + if !ok { + return empty, NewNotFoundError(key) + } + + delete(m.Underlying, key) + err := wrapped.UnwrapTo(&empty) + if err != nil { + return empty, fmt.Errorf("could not unwrap value: %w", err) + } + + return empty, nil +} + +type NotFoundError struct { + Key string +} + +func (e *NotFoundError) Error() string { + return fmt.Sprintf("could not find %q in map", e.Key) +} + +func NewNotFoundError(key string) *NotFoundError { + return &NotFoundError{Key: key} +} + +type InvalidRequestError struct { + Err error +} + +func (e *InvalidRequestError) Error() string { + return fmt.Sprintf("invalid request: %v", e.Err) +} + +func NewInvalidRequestError(err error) *InvalidRequestError { + return &InvalidRequestError{Err: err} +} diff --git a/core/capabilities/compute/transformer_test.go b/core/capabilities/compute/transformer_test.go new file mode 100644 index 00000000000..3da152de28b --- /dev/null +++ b/core/capabilities/compute/transformer_test.go @@ -0,0 +1,167 @@ +package compute + +import ( + "testing" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/stretchr/testify/assert" +) + +func Test_NotFoundError(t *testing.T) { + nfe := NewNotFoundError("test") + assert.Equal(t, "could not find \"test\" in map", nfe.Error()) +} + +func Test_popValue(t *testing.T) { + m, err := values.NewMap( + map[string]any{ + "test": "value", + "mismatch": 42, + }, + ) + assert.NoError(t, err) + + t.Run("success", func(t *testing.T) { + var gotValue string + gotValue, err = popValue[string](m, "test") + assert.NoError(t, err) + assert.Equal(t, "value", gotValue) + }) + + t.Run("not found", func(t *testing.T) { + _, err = popValue[string](m, "foo") + var nfe *NotFoundError + assert.ErrorAs(t, err, &nfe) + }) + + t.Run("type mismatch", func(t *testing.T) { + _, err = popValue[string](m, "mismatch") + assert.Error(t, err) + assert.ErrorContains(t, err, "could not unwrap value") + }) + + assert.Len(t, m.Underlying, 0) +} + +func Test_popOptionalValue(t *testing.T) { + m, err := values.NewMap( + map[string]any{ + "test": "value", + "buzz": "fizz", + }, + ) + assert.NoError(t, err) + t.Run("found value", func(t *testing.T) { + var gotValue string + gotValue, err = popOptionalValue[string](m, "test") + assert.NoError(t, err) + assert.Equal(t, "value", gotValue) + }) + + t.Run("not found returns nil error", func(t *testing.T) { + var gotValue string + gotValue, err = popOptionalValue[string](m, "foo") + assert.NoError(t, err) + assert.Zero(t, gotValue) + }) + + t.Run("some other error fails", func(t *testing.T) { + var gotValue int + gotValue, err = popOptionalValue[int](m, "buzz") + assert.Error(t, err) + assert.Zero(t, gotValue) + }) + + assert.Len(t, m.Underlying, 0) +} + +func Test_transformer(t *testing.T) { + t.Run("success", func(t *testing.T) { + lgger := logger.TestLogger(t) + giveMap, err := values.NewMap(map[string]any{ + "maxMemoryMBs": 1024, + "timeout": "4s", + "tickInterval": "8s", + "binary": []byte{0x01, 0x02, 0x03}, + "config": []byte{0x04, 0x05, 0x06}, + }) + assert.NoError(t, err) + + wantTO := 4 * time.Second + wantConfig := &ParsedConfig{ + Binary: []byte{0x01, 0x02, 0x03}, + Config: []byte{0x04, 0x05, 0x06}, + ModuleConfig: &host.ModuleConfig{ + MaxMemoryMBs: 1024, + Timeout: &wantTO, + TickInterval: 8 * time.Second, + Logger: lgger, + }, + } + + tf := NewTransformer() + gotConfig, err := tf.Transform(giveMap, WithLogger(lgger)) + + assert.NoError(t, err) + assert.Equal(t, wantConfig, gotConfig) + }) + + t.Run("success missing optional fields", func(t *testing.T) { + lgger := logger.TestLogger(t) + giveMap, err := values.NewMap(map[string]any{ + "binary": []byte{0x01, 0x02, 0x03}, + "config": []byte{0x04, 0x05, 0x06}, + }) + assert.NoError(t, err) + + wantConfig := &ParsedConfig{ + Binary: []byte{0x01, 0x02, 0x03}, + Config: []byte{0x04, 0x05, 0x06}, + ModuleConfig: &host.ModuleConfig{ + Logger: lgger, + }, + } + + tf := NewTransformer() + gotConfig, err := tf.Transform(giveMap, WithLogger(lgger)) + + assert.NoError(t, err) + assert.Equal(t, wantConfig, gotConfig) + }) + + t.Run("fails parsing timeout", func(t *testing.T) { + lgger := logger.TestLogger(t) + giveMap, err := values.NewMap(map[string]any{ + "timeout": "not a duration", + "binary": []byte{0x01, 0x02, 0x03}, + "config": []byte{0x04, 0x05, 0x06}, + }) + assert.NoError(t, err) + + tf := NewTransformer() + _, err = tf.Transform(giveMap, WithLogger(lgger)) + + assert.Error(t, err) + assert.ErrorContains(t, err, "invalid request") + }) + + t.Run("fails parsing tick interval", func(t *testing.T) { + lgger := logger.TestLogger(t) + giveMap, err := values.NewMap(map[string]any{ + "tickInterval": "not a duration", + "binary": []byte{0x01, 0x02, 0x03}, + "config": []byte{0x04, 0x05, 0x06}, + }) + assert.NoError(t, err) + + tf := NewTransformer() + _, err = tf.Transform(giveMap, WithLogger(lgger)) + + assert.Error(t, err) + assert.ErrorContains(t, err, "invalid request") + }) +} diff --git a/core/capabilities/encoder_factory.go b/core/capabilities/encoder_factory.go new file mode 100644 index 00000000000..6e6932fbb75 --- /dev/null +++ b/core/capabilities/encoder_factory.go @@ -0,0 +1,26 @@ +package capabilities + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/ocr3cap" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/values" + + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" +) + +func NewEncoder(name string, config *values.Map, lggr logger.Logger) (types.Encoder, error) { + switch ocr3cap.Encoder(name) { + case ocr3cap.EncoderEVM: + return evm.NewEVMEncoder(config) + case ocr3cap.EncoderValueMap: + return ocr3.ValueMapEncoder{}, nil + // TODO: add a "no-op" encoder for users who only want to use dynamic ones? + // https://smartcontract-it.atlassian.net/browse/CAPPL-88 + default: + return nil, fmt.Errorf("encoder %s not supported", name) + } +} diff --git a/core/capabilities/encoder_factory_test.go b/core/capabilities/encoder_factory_test.go new file mode 100644 index 00000000000..a7f9a7bee8d --- /dev/null +++ b/core/capabilities/encoder_factory_test.go @@ -0,0 +1,33 @@ +package capabilities + +import ( + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/ocr3cap" + "github.com/smartcontractkit/chainlink-common/pkg/values" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/stretchr/testify/require" +) + +func Test_NewEncoder(t *testing.T) { + t.Parallel() + t.Run("All ocr3 encoder types return a factory", func(t *testing.T) { + evmEncoding, err := values.NewMap(map[string]any{"abi": "bytes[] Full_reports"}) + require.NoError(t, err) + + config := map[ocr3cap.Encoder]*values.Map{ocr3cap.EncoderEVM: evmEncoding} + + for _, tt := range ocr3cap.Encoders() { + encoder, err2 := NewEncoder(string(tt), config[tt], logger.NullLogger) + require.NoError(t, err2) + require.NotNil(t, encoder) + } + }) + + t.Run("Invalid encoder returns an error", func(t *testing.T) { + _, err2 := NewEncoder("NotReal", values.EmptyMap(), logger.NullLogger) + require.Error(t, err2) + }) +} diff --git a/core/capabilities/gateway_connector/service_wrapper.go b/core/capabilities/gateway_connector/service_wrapper.go new file mode 100644 index 00000000000..824c92b4f89 --- /dev/null +++ b/core/capabilities/gateway_connector/service_wrapper.go @@ -0,0 +1,114 @@ +package gatewayconnector + +import ( + "context" + "crypto/ecdsa" + "errors" + "math/big" + "slices" + + "github.com/ethereum/go-ethereum/common" + "github.com/jonboulle/clockwork" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/config" + "github.com/smartcontractkit/chainlink/v2/core/logger" + gwcommon "github.com/smartcontractkit/chainlink/v2/core/services/gateway/common" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" +) + +type ServiceWrapper struct { + services.StateMachine + + config config.GatewayConnector + keystore keystore.Eth + connector connector.GatewayConnector + signerKey *ecdsa.PrivateKey + lggr logger.Logger + clock clockwork.Clock +} + +func translateConfigs(f config.GatewayConnector) connector.ConnectorConfig { + r := connector.ConnectorConfig{} + r.NodeAddress = f.NodeAddress() + r.DonId = f.DonID() + + if len(f.Gateways()) != 0 { + r.Gateways = make([]connector.ConnectorGatewayConfig, len(f.Gateways())) + for index, element := range f.Gateways() { + r.Gateways[index] = connector.ConnectorGatewayConfig{Id: element.ID(), URL: element.URL()} + } + } + + r.WsClientConfig = network.WebSocketClientConfig{HandshakeTimeoutMillis: f.WSHandshakeTimeoutMillis()} + r.AuthMinChallengeLen = f.AuthMinChallengeLen() + r.AuthTimestampToleranceSec = f.AuthTimestampToleranceSec() + return r +} + +// NOTE: this wrapper is needed to make sure that our services are started after Keystore. +func NewGatewayConnectorServiceWrapper(config config.GatewayConnector, keystore keystore.Eth, clock clockwork.Clock, lggr logger.Logger) *ServiceWrapper { + return &ServiceWrapper{ + config: config, + keystore: keystore, + clock: clock, + lggr: lggr, + } +} + +func (e *ServiceWrapper) Start(ctx context.Context) error { + return e.StartOnce("GatewayConnectorServiceWrapper", func() error { + conf := e.config + nodeAddress := conf.NodeAddress() + chainID, _ := new(big.Int).SetString(conf.ChainIDForNodeKey(), 0) + enabledKeys, err := e.keystore.EnabledKeysForChain(ctx, chainID) + if err != nil { + return err + } + if len(enabledKeys) == 0 { + return errors.New("no available keys found") + } + configuredNodeAddress := common.HexToAddress(nodeAddress) + idx := slices.IndexFunc(enabledKeys, func(key ethkey.KeyV2) bool { return key.Address == configuredNodeAddress }) + + if idx == -1 { + return errors.New("key for configured node address not found") + } + e.signerKey = enabledKeys[idx].ToEcdsaPrivKey() + if enabledKeys[idx].ID() != nodeAddress { + return errors.New("node address mismatch") + } + + translated := translateConfigs(conf) + e.connector, err = connector.NewGatewayConnector(&translated, e, e.clock, e.lggr) + if err != nil { + return err + } + return e.connector.Start(ctx) + }) +} + +func (e *ServiceWrapper) Sign(data ...[]byte) ([]byte, error) { + return gwcommon.SignData(e.signerKey, data...) +} + +func (e *ServiceWrapper) Close() error { + return e.StopOnce("GatewayConnectorServiceWrapper", func() (err error) { + return e.connector.Close() + }) +} + +func (e *ServiceWrapper) HealthReport() map[string]error { + return map[string]error{e.Name(): e.Healthy()} +} + +func (e *ServiceWrapper) Name() string { + return "GatewayConnectorServiceWrapper" +} + +func (e *ServiceWrapper) GetGatewayConnector() connector.GatewayConnector { + return e.connector +} diff --git a/core/capabilities/gateway_connector/service_wrapper_test.go b/core/capabilities/gateway_connector/service_wrapper_test.go new file mode 100644 index 00000000000..c88622fcd27 --- /dev/null +++ b/core/capabilities/gateway_connector/service_wrapper_test.go @@ -0,0 +1,81 @@ +package gatewayconnector_test + +import ( + "crypto/ecdsa" + "testing" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + gatewayconnector "github.com/smartcontractkit/chainlink/v2/core/capabilities/gateway_connector" + "github.com/smartcontractkit/chainlink/v2/core/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" +) + +func generateWrapper(t *testing.T, privateKey *ecdsa.PrivateKey, keystoreKey *ecdsa.PrivateKey) (*gatewayconnector.ServiceWrapper, error) { + logger := logger.TestLogger(t) + privateKeyV2 := ethkey.FromPrivateKey(privateKey) + addr := privateKeyV2.Address + keystoreKeyV2 := ethkey.FromPrivateKey(keystoreKey) + + config, err := chainlink.GeneralConfigOpts{ + Config: chainlink.Config{ + Core: toml.Core{ + Capabilities: toml.Capabilities{ + GatewayConnector: toml.GatewayConnector{ + ChainIDForNodeKey: ptr("1"), + NodeAddress: ptr(addr.Hex()), + DonID: ptr("5"), + WSHandshakeTimeoutMillis: ptr[uint32](100), + AuthMinChallengeLen: ptr[int](0), + AuthTimestampToleranceSec: ptr[uint32](10), + Gateways: []toml.ConnectorGateway{{ID: ptr("example_gateway"), URL: ptr("wss://localhost:8081/node")}}, + }, + }, + }, + }, + }.New() + ethKeystore := ksmocks.NewEth(t) + ethKeystore.On("EnabledKeysForChain", mock.Anything, mock.Anything).Return([]ethkey.KeyV2{keystoreKeyV2}, nil) + gc := config.Capabilities().GatewayConnector() + wrapper := gatewayconnector.NewGatewayConnectorServiceWrapper(gc, ethKeystore, clockwork.NewFakeClock(), logger) + require.NoError(t, err) + return wrapper, err +} + +func TestGatewayConnectorServiceWrapper_CleanStartClose(t *testing.T) { + t.Parallel() + + key, _ := testutils.NewPrivateKeyAndAddress(t) + wrapper, err := generateWrapper(t, key, key) + require.NoError(t, err) + + ctx := testutils.Context(t) + err = wrapper.Start(ctx) + require.NoError(t, err) + + t.Cleanup(func() { + assert.NoError(t, wrapper.Close()) + }) +} + +func TestGatewayConnectorServiceWrapper_NonexistentKey(t *testing.T) { + t.Parallel() + + key, _ := testutils.NewPrivateKeyAndAddress(t) + keystoreKey, _ := testutils.NewPrivateKeyAndAddress(t) + wrapper, err := generateWrapper(t, key, keystoreKey) + require.NoError(t, err) + + ctx := testutils.Context(t) + err = wrapper.Start(ctx) + require.Error(t, err) +} + +func ptr[T any](t T) *T { return &t } diff --git a/core/capabilities/integration_tests/framework/capabilities_registry.go b/core/capabilities/integration_tests/framework/capabilities_registry.go new file mode 100644 index 00000000000..604c1d082d8 --- /dev/null +++ b/core/capabilities/integration_tests/framework/capabilities_registry.go @@ -0,0 +1,129 @@ +package framework + +import ( + "context" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "google.golang.org/protobuf/proto" + + "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" + + "testing" + + "github.com/stretchr/testify/require" +) + +type CapabilitiesRegistry struct { + t *testing.T + backend *EthBlockchain + contract *kcr.CapabilitiesRegistry + addr common.Address + nodeOperatorID uint32 + nextDonID int +} + +func NewCapabilitiesRegistry(ctx context.Context, t *testing.T, backend *EthBlockchain) *CapabilitiesRegistry { + addr, _, contract, err := kcr.DeployCapabilitiesRegistry(backend.transactionOpts, backend) + require.NoError(t, err) + backend.Commit() + + _, err = contract.AddNodeOperators(backend.transactionOpts, []kcr.CapabilitiesRegistryNodeOperator{ + { + Admin: backend.transactionOpts.From, + Name: "TEST_NODE_OPERATOR", + }, + }) + require.NoError(t, err) + blockHash := backend.Commit() + + logs, err := backend.FilterLogs(ctx, ethereum.FilterQuery{ + BlockHash: &blockHash, + FromBlock: nil, + ToBlock: nil, + Addresses: nil, + Topics: nil, + }) + + require.NoError(t, err) + + recLog, err := contract.ParseNodeOperatorAdded(logs[0]) + require.NoError(t, err) + + nopID := recLog.NodeOperatorId + + return &CapabilitiesRegistry{t: t, addr: addr, contract: contract, backend: backend, nodeOperatorID: nopID} +} + +func (r *CapabilitiesRegistry) getAddress() common.Address { + return r.addr +} + +type capability struct { + donCapabilityConfig *pb.CapabilityConfig + registryConfig kcr.CapabilitiesRegistryCapability +} + +// SetupDON sets up a new DON with the given capabilities and returns the DON ID +func (r *CapabilitiesRegistry) setupDON(donInfo DonConfiguration, capabilities []capability) int { + var hashedCapabilityIDs [][32]byte + + for _, c := range capabilities { + id, err := r.contract.GetHashedCapabilityId(&bind.CallOpts{}, c.registryConfig.LabelledName, c.registryConfig.Version) + require.NoError(r.t, err) + hashedCapabilityIDs = append(hashedCapabilityIDs, id) + } + + var registryCapabilities []kcr.CapabilitiesRegistryCapability + for _, c := range capabilities { + registryCapabilities = append(registryCapabilities, c.registryConfig) + } + + _, err := r.contract.AddCapabilities(r.backend.transactionOpts, registryCapabilities) + require.NoError(r.t, err) + + r.backend.Commit() + + nodes := []kcr.CapabilitiesRegistryNodeParams{} + for _, peerID := range donInfo.peerIDs { + n, innerErr := peerToNode(r.nodeOperatorID, peerID) + require.NoError(r.t, innerErr) + + n.HashedCapabilityIds = hashedCapabilityIDs + nodes = append(nodes, n) + } + + _, err = r.contract.AddNodes(r.backend.transactionOpts, nodes) + require.NoError(r.t, err) + r.backend.Commit() + + ps, err := peers(donInfo.peerIDs) + require.NoError(r.t, err) + + var capabilityConfigurations []kcr.CapabilitiesRegistryCapabilityConfiguration + for i, c := range capabilities { + configBinary, err2 := proto.Marshal(c.donCapabilityConfig) + require.NoError(r.t, err2) + + capabilityConfigurations = append(capabilityConfigurations, kcr.CapabilitiesRegistryCapabilityConfiguration{ + CapabilityId: hashedCapabilityIDs[i], + Config: configBinary, + }) + } + + _, err = r.contract.AddDON(r.backend.transactionOpts, ps, capabilityConfigurations, true, donInfo.AcceptsWorkflows, donInfo.F) + require.NoError(r.t, err) + r.backend.Commit() + + r.nextDonID++ + return r.nextDonID +} + +func newCapabilityConfig() *pb.CapabilityConfig { + return &pb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } +} diff --git a/core/capabilities/integration_tests/framework/don.go b/core/capabilities/integration_tests/framework/don.go new file mode 100644 index 00000000000..1cb38c1bf71 --- /dev/null +++ b/core/capabilities/integration_tests/framework/don.go @@ -0,0 +1,399 @@ +package framework + +import ( + "context" + "fmt" + "strconv" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/durationpb" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + + "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" + 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" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" +) + +type DonContext struct { + EthBlockchain *EthBlockchain + p2pNetwork *MockRageP2PNetwork + capabilityRegistry *CapabilitiesRegistry +} + +func CreateDonContext(ctx context.Context, t *testing.T) DonContext { + ethBlockchain := NewEthBlockchain(t, 1000, 1*time.Second) + rageP2PNetwork := NewMockRageP2PNetwork(t, 1000) + capabilitiesRegistry := NewCapabilitiesRegistry(ctx, t, ethBlockchain) + + servicetest.Run(t, rageP2PNetwork) + servicetest.Run(t, ethBlockchain) + return DonContext{EthBlockchain: ethBlockchain, p2pNetwork: rageP2PNetwork, capabilityRegistry: capabilitiesRegistry} +} + +type capabilityNode struct { + *cltest.TestApplication + registry *capabilities.Registry + key ethkey.KeyV2 + KeyBundle ocr2key.KeyBundle + peerID peer + start func() +} + +type DON struct { + t *testing.T + config DonConfiguration + lggr logger.Logger + nodes []*capabilityNode + standardCapabilityJobs []*job.Job + externalCapabilities []capability + capabilitiesRegistry *CapabilitiesRegistry + + nodeConfigModifiers []func(c *chainlink.Config, node *capabilityNode) + + addOCR3NonStandardCapability bool + + triggerFactories []TriggerFactory + targetFactories []TargetFactory +} + +func NewDON(ctx context.Context, t *testing.T, lggr logger.Logger, donConfig DonConfiguration, + dependentDONs []commoncap.DON, donContext DonContext, supportsOCR bool) *DON { + don := &DON{t: t, lggr: lggr.Named(donConfig.name), config: donConfig, capabilitiesRegistry: donContext.capabilityRegistry} + + var newOracleFactoryFn standardcapabilities.NewOracleFactoryFn + var libOcr *MockLibOCR + if supportsOCR { + libOcr = NewMockLibOCR(t, lggr, donConfig.F, 1*time.Second) + servicetest.Run(t, libOcr) + } + + for i, member := range donConfig.Members { + dispatcher := donContext.p2pNetwork.NewDispatcherForNode(member) + capabilityRegistry := capabilities.NewRegistry(lggr) + + nodeInfo := commoncap.Node{ + PeerID: &member, + WorkflowDON: donConfig.DON, + CapabilityDONs: dependentDONs, + } + + cn := &capabilityNode{ + registry: capabilityRegistry, + key: donConfig.keys[i], + KeyBundle: donConfig.KeyBundles[i], + peerID: donConfig.peerIDs[i], + } + don.nodes = append(don.nodes, cn) + + if supportsOCR { + factory := newMockLibOcrOracleFactory(libOcr, donConfig.KeyBundles[i], len(donConfig.Members), int(donConfig.F)) + newOracleFactoryFn = factory.NewOracleFactory + } + + cn.start = func() { + node := startNewNode(ctx, t, lggr.Named(donConfig.name+"-"+strconv.Itoa(i)), nodeInfo, donContext.EthBlockchain, + donContext.capabilityRegistry.getAddress(), dispatcher, + peerWrapper{peer: p2pPeer{member}}, capabilityRegistry, newOracleFactoryFn, + donConfig.keys[i], func(c *chainlink.Config) { + for _, modifier := range don.nodeConfigModifiers { + modifier(c, cn) + } + }) + + require.NoError(t, node.Start(testutils.Context(t))) + cn.TestApplication = node + } + } + + return don +} + +// Initialise must be called after all capabilities have been added to the DONs and before Start is called +func (d *DON) Initialise() { + if len(d.externalCapabilities) > 0 { + id := d.capabilitiesRegistry.setupDON(d.config, d.externalCapabilities) + + //nolint:gosec // disable G115 + d.config.DON.ID = uint32(id) + } +} + +func (d *DON) GetID() uint32 { + if d.config.DON.ID == 0 { + panic("DON ID not set, call Initialise() first") + } + + return d.config.ID +} + +func (d *DON) GetConfigVersion() uint32 { + return d.config.ConfigVersion +} + +func (d *DON) GetF() uint8 { + return d.config.F +} + +func (d *DON) GetPeerIDs() []peer { + return d.config.peerIDs +} + +func (d *DON) Start(ctx context.Context, t *testing.T) { + for _, triggerFactory := range d.triggerFactories { + for _, node := range d.nodes { + trigger := triggerFactory.CreateNewTrigger(t) + err := node.registry.Add(ctx, trigger) + require.NoError(t, err) + } + } + + for _, targetFactory := range d.targetFactories { + for _, node := range d.nodes { + target := targetFactory.CreateNewTarget(t) + err := node.registry.Add(ctx, target) + require.NoError(t, err) + } + } + + for _, node := range d.nodes { + node.start() + } + + if d.addOCR3NonStandardCapability { + libocr := NewMockLibOCR(t, d.lggr, d.config.F, 1*time.Second) + servicetest.Run(t, libocr) + + for _, node := range d.nodes { + addOCR3Capability(ctx, t, d.lggr, node.registry, libocr, d.config.F, node.KeyBundle) + } + } + + for _, capabilityJob := range d.standardCapabilityJobs { + err := d.AddJob(ctx, capabilityJob) + require.NoError(t, err) + } +} + +const StandardCapabilityTemplateJobSpec = ` +type = "standardcapabilities" +schemaVersion = 1 +name = "%s" +command="%s" +config="%s" +` + +func (d *DON) AddStandardCapability(name string, command string, config string) { + spec := fmt.Sprintf(StandardCapabilityTemplateJobSpec, name, command, config) + capabilitiesSpecJob, err := standardcapabilities.ValidatedStandardCapabilitiesSpec(spec) + require.NoError(d.t, err) + + d.standardCapabilityJobs = append(d.standardCapabilityJobs, &capabilitiesSpecJob) +} + +// TODO - add configuration for remote support - do this for each capability as an option +func (d *DON) AddTargetCapability(targetFactory TargetFactory) { + d.targetFactories = append(d.targetFactories, targetFactory) +} + +func (d *DON) AddExternalTriggerCapability(triggerFactory TriggerFactory) { + d.triggerFactories = append(d.triggerFactories, triggerFactory) + + // Arguably this should be a parameter to AddExternalTriggerCapability, but for now we're just using the default + // See TODO about local/remote exposure + defaultTriggerCapabilityConfig := newCapabilityConfig() + defaultTriggerCapabilityConfig.RemoteConfig = &pb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &pb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(1000 * time.Millisecond), + RegistrationExpiry: durationpb.New(60000 * time.Millisecond), + // F + 1 + MinResponsesToAggregate: uint32(d.config.F) + 1, + }, + } + + triggerCapability := capability{ + donCapabilityConfig: defaultTriggerCapabilityConfig, + registryConfig: kcr.CapabilitiesRegistryCapability{ + LabelledName: triggerFactory.GetTriggerName(), + Version: triggerFactory.GetTriggerVersion(), + CapabilityType: uint8(registrysyncer.ContractCapabilityTypeTrigger), + }, + } + + d.externalCapabilities = append(d.externalCapabilities, triggerCapability) +} + +func (d *DON) AddJob(ctx context.Context, j *job.Job) error { + for _, node := range d.nodes { + err := node.AddJobV2(ctx, j) + if err != nil { + return fmt.Errorf("failed to add job: %w", err) + } + } + + return nil +} + +type TriggerFactory interface { + CreateNewTrigger(t *testing.T) commoncap.TriggerCapability + GetTriggerID() string + GetTriggerName() string + GetTriggerVersion() string +} + +type TargetFactory interface { + CreateNewTarget(t *testing.T) commoncap.TargetCapability + GetTargetID() string + GetTargetName() string + GetTargetVersion() string +} + +func startNewNode(ctx context.Context, + t *testing.T, lggr logger.Logger, nodeInfo commoncap.Node, + ethBlockchain *EthBlockchain, capRegistryAddr common.Address, + dispatcher remotetypes.Dispatcher, + peerWrapper p2ptypes.PeerWrapper, + localCapabilities *capabilities.Registry, + newOracleFactoryFn standardcapabilities.NewOracleFactoryFn, + keyV2 ethkey.KeyV2, + setupCfg func(c *chainlink.Config), +) *cltest.TestApplication { + config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Capabilities.ExternalRegistry.ChainID = ptr(fmt.Sprintf("%d", testutils.SimulatedChainID)) + c.Capabilities.ExternalRegistry.Address = ptr(capRegistryAddr.String()) + c.Capabilities.Peering.V2.Enabled = ptr(true) + c.Feature.FeedsManager = ptr(false) + + if setupCfg != nil { + setupCfg(c) + } + }) + + n, err := ethBlockchain.NonceAt(ctx, ethBlockchain.transactionOpts.From, nil) + require.NoError(t, err) + + tx := cltest.NewLegacyTransaction( + n, keyV2.Address, + assets.Ether(1).ToInt(), + 21000, + assets.GWei(1).ToInt(), + nil) + signedTx, err := ethBlockchain.transactionOpts.Signer(ethBlockchain.transactionOpts.From, tx) + require.NoError(t, err) + err = ethBlockchain.SendTransaction(ctx, signedTx) + require.NoError(t, err) + ethBlockchain.Commit() + + return cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, ethBlockchain.SimulatedBackend, nodeInfo, + dispatcher, peerWrapper, newOracleFactoryFn, localCapabilities, keyV2, lggr) +} + +// Functions below this point are for adding non-standard capabilities to a DON, deliberately verbose. Eventually these +// should be replaced with standard capabilities. + +func (d *DON) AddOCR3NonStandardCapability() { + d.addOCR3NonStandardCapability = true + + ocr := kcr.CapabilitiesRegistryCapability{ + LabelledName: "offchain_reporting", + Version: "1.0.0", + CapabilityType: uint8(registrysyncer.ContractCapabilityTypeConsensus), + } + + d.externalCapabilities = append(d.externalCapabilities, capability{ + donCapabilityConfig: newCapabilityConfig(), + registryConfig: ocr, + }) +} + +func (d *DON) AddEthereumWriteTargetNonStandardCapability(forwarderAddr common.Address) error { + d.nodeConfigModifiers = append(d.nodeConfigModifiers, func(c *chainlink.Config, node *capabilityNode) { + eip55Address := types.EIP55AddressFromAddress(forwarderAddr) + c.EVM[0].Chain.Workflow.ForwarderAddress = &eip55Address + c.EVM[0].Chain.Workflow.FromAddress = &node.key.EIP55Address + }) + + writeChain := kcr.CapabilitiesRegistryCapability{ + LabelledName: "write_geth-testnet", + Version: "1.0.0", + CapabilityType: uint8(registrysyncer.ContractCapabilityTypeTarget), + } + + targetCapabilityConfig := newCapabilityConfig() + + configWithLimit, err := values.WrapMap(map[string]any{"gasLimit": 500000}) + if err != nil { + return fmt.Errorf("failed to wrap map: %w", err) + } + + targetCapabilityConfig.DefaultConfig = values.Proto(configWithLimit).GetMapValue() + + targetCapabilityConfig.RemoteConfig = &pb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &pb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, + }, + } + + d.externalCapabilities = append(d.externalCapabilities, capability{ + donCapabilityConfig: targetCapabilityConfig, + registryConfig: writeChain, + }) + + return nil +} + +func addOCR3Capability(ctx context.Context, t *testing.T, lggr logger.Logger, capabilityRegistry *capabilities.Registry, + libocr *MockLibOCR, donF uint8, ocr2KeyBundle ocr2key.KeyBundle) { + requestTimeout := 10 * time.Minute + cfg := ocr3.Config{ + Logger: lggr, + EncoderFactory: capabilities.NewEncoder, + AggregatorFactory: capabilities.NewAggregator, + RequestTimeout: &requestTimeout, + } + + ocr3Capability := ocr3.NewOCR3(cfg) + servicetest.Run(t, ocr3Capability) + + pluginCfg := coretypes.ReportingPluginServiceConfig{} + pluginFactory, err := ocr3Capability.NewReportingPluginFactory(ctx, pluginCfg, nil, + nil, nil, nil, capabilityRegistry, nil, nil) + require.NoError(t, err) + + repConfig := ocr3types.ReportingPluginConfig{ + F: int(donF), + } + plugin, _, err := pluginFactory.NewReportingPlugin(ctx, repConfig) + require.NoError(t, err) + + transmitter := ocr3.NewContractTransmitter(lggr, capabilityRegistry, "") + + libocr.AddNode(plugin, transmitter, ocr2KeyBundle) +} + +func Context(tb testing.TB) context.Context { + return testutils.Context(tb) +} diff --git a/core/capabilities/integration_tests/framework/don_configuration.go b/core/capabilities/integration_tests/framework/don_configuration.go new file mode 100644 index 00000000000..2fd1afd6554 --- /dev/null +++ b/core/capabilities/integration_tests/framework/don_configuration.go @@ -0,0 +1,67 @@ +package framework + +import ( + "fmt" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +type DonConfiguration struct { + commoncap.DON + name string + keys []ethkey.KeyV2 + KeyBundles []ocr2key.KeyBundle + peerIDs []peer +} + +// NewDonConfigurationParams exists purely to make it obvious in the test code what DON configuration is being used +type NewDonConfigurationParams struct { + Name string + NumNodes int + F uint8 + AcceptsWorkflows bool +} + +func NewDonConfiguration(don NewDonConfigurationParams) (DonConfiguration, error) { + if !(don.NumNodes >= int(3*don.F+1)) { + return DonConfiguration{}, fmt.Errorf("invalid configuration, number of nodes must be at least 3*F+1") + } + + keyBundles, peerIDs, err := getKeyBundlesAndPeerIDs(don.NumNodes) + if err != nil { + return DonConfiguration{}, fmt.Errorf("failed to get key bundles and peer IDs: %w", err) + } + + donPeers := make([]p2ptypes.PeerID, len(peerIDs)) + var donKeys []ethkey.KeyV2 + for i := 0; i < len(peerIDs); i++ { + peerID := p2ptypes.PeerID{} + err = peerID.UnmarshalText([]byte(peerIDs[i].PeerID)) + if err != nil { + return DonConfiguration{}, fmt.Errorf("failed to unmarshal peer ID: %w", err) + } + donPeers[i] = peerID + newKey, err := ethkey.NewV2() + if err != nil { + return DonConfiguration{}, fmt.Errorf("failed to create key: %w", err) + } + donKeys = append(donKeys, newKey) + } + + donConfiguration := DonConfiguration{ + DON: commoncap.DON{ + Members: donPeers, + F: don.F, + ConfigVersion: 1, + AcceptsWorkflows: don.AcceptsWorkflows, + }, + name: don.Name, + peerIDs: peerIDs, + keys: donKeys, + KeyBundles: keyBundles, + } + return donConfiguration, nil +} diff --git a/core/capabilities/integration_tests/framework/ethereum.go b/core/capabilities/integration_tests/framework/ethereum.go new file mode 100644 index 00000000000..47558dacfcb --- /dev/null +++ b/core/capabilities/integration_tests/framework/ethereum.go @@ -0,0 +1,79 @@ +package framework + +import ( + "context" + "os" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + gethlog "github.com/ethereum/go-ethereum/log" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +type EthBlockchain struct { + services.StateMachine + *backends.SimulatedBackend + transactionOpts *bind.TransactOpts + + blockTimeProcessingTime time.Duration + + stopCh services.StopChan + wg sync.WaitGroup +} + +func NewEthBlockchain(t *testing.T, initialEth int, blockTimeProcessingTime time.Duration) *EthBlockchain { + transactOpts := testutils.MustNewSimTransactor(t) // config contract deployer and owner + genesisData := core.GenesisAlloc{transactOpts.From: {Balance: assets.Ether(initialEth).ToInt()}} + //nolint:gosec // disable G115 + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + gethlog.SetDefault(gethlog.NewLogger(gethlog.NewTerminalHandlerWithLevel(os.Stderr, gethlog.LevelWarn, true))) + backend.Commit() + + return &EthBlockchain{SimulatedBackend: backend, stopCh: make(services.StopChan), + blockTimeProcessingTime: blockTimeProcessingTime, transactionOpts: transactOpts} +} + +func (b *EthBlockchain) Start(ctx context.Context) error { + return b.StartOnce("EthBlockchain", func() error { + b.wg.Add(1) + go func() { + defer b.wg.Done() + ticker := time.NewTicker(b.blockTimeProcessingTime) + defer ticker.Stop() + + for { + select { + case <-b.stopCh: + return + case <-ctx.Done(): + return + case <-ticker.C: + b.SimulatedBackend.Commit() + } + } + }() + + return nil + }) +} + +func (b *EthBlockchain) Close() error { + return b.StopOnce("EthBlockchain", func() error { + close(b.stopCh) + b.wg.Wait() + return nil + }) +} + +func (b *EthBlockchain) TransactionOpts() *bind.TransactOpts { + return b.transactionOpts +} diff --git a/core/capabilities/integration_tests/mock_dispatcher.go b/core/capabilities/integration_tests/framework/mock_dispatcher.go similarity index 77% rename from core/capabilities/integration_tests/mock_dispatcher.go rename to core/capabilities/integration_tests/framework/mock_dispatcher.go index 1230e59427d..f208933f1f1 100644 --- a/core/capabilities/integration_tests/mock_dispatcher.go +++ b/core/capabilities/integration_tests/framework/mock_dispatcher.go @@ -1,4 +1,4 @@ -package integration_tests +package framework import ( "context" @@ -16,9 +16,9 @@ import ( "google.golang.org/protobuf/proto" ) -// testAsyncMessageBroker backs the dispatchers created for each node in the test and effectively +// MockRageP2PNetwork backs the dispatchers created for each node in the test and effectively // acts as the rageP2P network layer. -type testAsyncMessageBroker struct { +type MockRageP2PNetwork struct { services.StateMachine t *testing.T @@ -31,8 +31,8 @@ type testAsyncMessageBroker struct { mux sync.Mutex } -func newTestAsyncMessageBroker(t *testing.T, chanBufferSize int) *testAsyncMessageBroker { - return &testAsyncMessageBroker{ +func NewMockRageP2PNetwork(t *testing.T, chanBufferSize int) *MockRageP2PNetwork { + return &MockRageP2PNetwork{ t: t, stopCh: make(services.StopChan), chanBufferSize: chanBufferSize, @@ -40,14 +40,14 @@ func newTestAsyncMessageBroker(t *testing.T, chanBufferSize int) *testAsyncMessa } } -func (a *testAsyncMessageBroker) Start(ctx context.Context) error { - return a.StartOnce("testAsyncMessageBroker", func() error { +func (a *MockRageP2PNetwork) Start(ctx context.Context) error { + return a.StartOnce("MockRageP2PNetwork", func() error { return nil }) } -func (a *testAsyncMessageBroker) Close() error { - return a.StopOnce("testAsyncMessageBroker", func() error { +func (a *MockRageP2PNetwork) Close() error { + return a.StopOnce("MockRageP2PNetwork", func() error { close(a.stopCh) a.wg.Wait() return nil @@ -55,7 +55,7 @@ func (a *testAsyncMessageBroker) Close() error { } // NewDispatcherForNode creates a new dispatcher for a node with the given peer ID. -func (a *testAsyncMessageBroker) NewDispatcherForNode(nodePeerID p2ptypes.PeerID) remotetypes.Dispatcher { +func (a *MockRageP2PNetwork) NewDispatcherForNode(nodePeerID p2ptypes.PeerID) remotetypes.Dispatcher { return &brokerDispatcher{ callerPeerID: nodePeerID, broker: a, @@ -63,15 +63,15 @@ func (a *testAsyncMessageBroker) NewDispatcherForNode(nodePeerID p2ptypes.PeerID } } -func (a *testAsyncMessageBroker) HealthReport() map[string]error { +func (a *MockRageP2PNetwork) HealthReport() map[string]error { return nil } -func (a *testAsyncMessageBroker) Name() string { - return "testAsyncMessageBroker" +func (a *MockRageP2PNetwork) Name() string { + return "MockRageP2PNetwork" } -func (a *testAsyncMessageBroker) registerReceiverNode(nodePeerID p2ptypes.PeerID, capabilityId string, capabilityDonID uint32, receiver remotetypes.Receiver) { +func (a *MockRageP2PNetwork) registerReceiverNode(nodePeerID p2ptypes.PeerID, capabilityID string, capabilityDonID uint32, receiver remotetypes.Receiver) { a.mux.Lock() defer a.mux.Unlock() @@ -83,14 +83,14 @@ func (a *testAsyncMessageBroker) registerReceiverNode(nodePeerID p2ptypes.PeerID node.registerReceiverCh <- ®isterReceiverRequest{ receiverKey: receiverKey{ - capabilityId: capabilityId, + capabilityId: capabilityID, donId: capabilityDonID, }, receiver: receiver, } } -func (a *testAsyncMessageBroker) Send(msg *remotetypes.MessageBody) { +func (a *MockRageP2PNetwork) Send(msg *remotetypes.MessageBody) { peerID := toPeerID(msg.Receiver) node, ok := a.peerIDToBrokerNode[peerID] if !ok { @@ -115,7 +115,7 @@ type registerReceiverRequest struct { receiver remotetypes.Receiver } -func (a *testAsyncMessageBroker) newNode() *brokerNode { +func (a *MockRageP2PNetwork) newNode() *brokerNode { n := &brokerNode{ receiveCh: make(chan *remotetypes.MessageBody, a.chanBufferSize), registerReceiverCh: make(chan *registerReceiverRequest, a.chanBufferSize), @@ -190,7 +190,7 @@ func (t *brokerDispatcher) SetReceiver(capabilityId string, donId uint32, receiv } t.receivers[k] = receiver - t.broker.(*testAsyncMessageBroker).registerReceiverNode(t.callerPeerID, capabilityId, donId, receiver) + t.broker.(*MockRageP2PNetwork).registerReceiverNode(t.callerPeerID, capabilityId, donId, receiver) return nil } func (t *brokerDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} diff --git a/core/capabilities/integration_tests/mock_libocr.go b/core/capabilities/integration_tests/framework/mock_libocr.go similarity index 52% rename from core/capabilities/integration_tests/mock_libocr.go rename to core/capabilities/integration_tests/framework/mock_libocr.go index 14ccdce6000..39705031f55 100644 --- a/core/capabilities/integration_tests/mock_libocr.go +++ b/core/capabilities/integration_tests/framework/mock_libocr.go @@ -1,4 +1,4 @@ -package integration_tests +package framework import ( "bytes" @@ -9,28 +9,86 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" + "github.com/google/uuid" "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" + coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/generic" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + + "github.com/smartcontractkit/chainlink/v2/core/logger" ) +type oracleFactoryFactory struct { + mockLibOCr *MockLibOCR + key ocr2key.KeyBundle + N int + F int +} + +func newMockLibOcrOracleFactory(mockLibOCr *MockLibOCR, key ocr2key.KeyBundle, N int, F int) *oracleFactoryFactory { + return &oracleFactoryFactory{ + mockLibOCr: mockLibOCr, + key: key, + N: N, + F: F, + } +} + +func (o *oracleFactoryFactory) NewOracleFactory(params generic.OracleFactoryParams) (coretypes.OracleFactory, error) { + return &mockOracleFactory{o}, nil +} + +type mockOracle struct { + *mockOracleFactory + args coretypes.OracleArgs + libocrNodeID string +} + +func (m *mockOracle) Start(ctx context.Context) error { + plugin, _, err := m.args.ReportingPluginFactoryService.NewReportingPlugin(ctx, ocr3types.ReportingPluginConfig{ + F: m.F, + N: m.N, + }) + if err != nil { + return fmt.Errorf("failed to create reporting plugin: %w", err) + } + + m.libocrNodeID = m.mockLibOCr.AddNode(plugin, m.args.ContractTransmitter, m.key) + return nil +} + +func (m *mockOracle) Close(ctx context.Context) error { + m.mockLibOCr.RemoveNode(m.libocrNodeID) + return nil +} + +type mockOracleFactory struct { + *oracleFactoryFactory +} + +func (m *mockOracleFactory) NewOracle(ctx context.Context, args coretypes.OracleArgs) (coretypes.Oracle, error) { + return &mockOracle{mockOracleFactory: m, args: args}, nil +} + type libocrNode struct { + id string ocr3types.ReportingPlugin[[]byte] - *ocr3.ContractTransmitter + ocr3types.ContractTransmitter[[]byte] key ocr2key.KeyBundle } -// mockLibOCR is a mock libocr implementation for testing purposes that simulates libocr protocol rounds without having +// MockLibOCR is a mock libocr implementation for testing purposes that simulates libocr protocol rounds without having // to setup the libocr network -type mockLibOCR struct { +type MockLibOCR struct { services.StateMachine - t *testing.T + t *testing.T + lggr logger.Logger nodes []*libocrNode f uint8 @@ -39,15 +97,17 @@ type mockLibOCR struct { seqNr uint64 outcomeCtx ocr3types.OutcomeContext + mux sync.Mutex stopCh services.StopChan wg sync.WaitGroup } -func newMockLibOCR(t *testing.T, f uint8, protocolRoundInterval time.Duration) *mockLibOCR { - return &mockLibOCR{ - t: t, - f: f, outcomeCtx: ocr3types.OutcomeContext{ - SeqNr: 0, +func NewMockLibOCR(t *testing.T, lggr logger.Logger, f uint8, protocolRoundInterval time.Duration) *MockLibOCR { + return &MockLibOCR{ + t: t, + lggr: lggr, + f: f, outcomeCtx: ocr3types.OutcomeContext{ + SeqNr: 1, PreviousOutcome: nil, Epoch: 0, Round: 0, @@ -57,8 +117,8 @@ func newMockLibOCR(t *testing.T, f uint8, protocolRoundInterval time.Duration) * } } -func (m *mockLibOCR) Start(ctx context.Context) error { - return m.StartOnce("mockLibOCR", func() error { +func (m *MockLibOCR) Start(ctx context.Context) error { + return m.StartOnce("MockLibOCR", func() error { m.wg.Add(1) go func() { defer m.wg.Done() @@ -75,7 +135,7 @@ func (m *mockLibOCR) Start(ctx context.Context) error { case <-ticker.C: err := m.simulateProtocolRound(ctx) if err != nil { - require.FailNow(m.t, err.Error()) + m.lggr.Errorf("simulating protocol round: %v", err) } } } @@ -84,19 +144,43 @@ func (m *mockLibOCR) Start(ctx context.Context) error { }) } -func (m *mockLibOCR) Close() error { - return m.StopOnce("mockLibOCR", func() error { +func (m *MockLibOCR) Close() error { + return m.StopOnce("MockLibOCR", func() error { close(m.stopCh) m.wg.Wait() return nil }) } -func (m *mockLibOCR) AddNode(plugin ocr3types.ReportingPlugin[[]byte], transmitter *ocr3.ContractTransmitter, key ocr2key.KeyBundle) { - m.nodes = append(m.nodes, &libocrNode{plugin, transmitter, key}) +func (m *MockLibOCR) AddNode(plugin ocr3types.ReportingPlugin[[]byte], transmitter ocr3types.ContractTransmitter[[]byte], key ocr2key.KeyBundle) string { + m.mux.Lock() + defer m.mux.Unlock() + node := &libocrNode{uuid.New().String(), plugin, transmitter, key} + m.nodes = append(m.nodes, node) + return node.id +} + +func (m *MockLibOCR) RemoveNode(id string) { + m.mux.Lock() + defer m.mux.Unlock() + + var updatedNodes []*libocrNode + for _, node := range m.nodes { + if node.id != id { + updatedNodes = append(updatedNodes, node) + } + } + + m.nodes = updatedNodes } -func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { +func (m *MockLibOCR) simulateProtocolRound(ctx context.Context) error { + m.mux.Lock() + defer m.mux.Unlock() + if len(m.nodes) == 0 { + return nil + } + // randomly select a leader leader := m.nodes[rand.Intn(len(m.nodes))] @@ -110,7 +194,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { for oracleID, node := range m.nodes { obs, err2 := node.Observation(ctx, m.outcomeCtx, query) if err2 != nil { - return fmt.Errorf("failed to get observation: %w", err) + return fmt.Errorf("failed to get observation: %w", err2) } observations = append(observations, types.AttributedObservation{ @@ -121,9 +205,9 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { var outcomes []ocr3types.Outcome for _, node := range m.nodes { - outcome, err2 := node.Outcome(m.outcomeCtx, query, observations) + outcome, err2 := node.Outcome(ctx, m.outcomeCtx, query, observations) if err2 != nil { - return fmt.Errorf("failed to get outcome: %w", err) + return fmt.Errorf("failed to get outcome: %w", err2) } if len(outcome) == 0 { @@ -140,7 +224,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { } } - reports, err := leader.Reports(0, outcomes[0]) + reports, err := leader.Reports(ctx, 0, outcomes[0]) if err != nil { return fmt.Errorf("failed to get reports: %w", err) } @@ -148,7 +232,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { // create signatures var signatures []types.AttributedOnchainSignature for i, node := range m.nodes { - sig, err := node.key.Sign(types.ReportContext{}, report.Report) + sig, err := node.key.Sign(types.ReportContext{}, report.ReportWithInfo.Report) if err != nil { return fmt.Errorf("failed to sign report: %w", err) } @@ -160,7 +244,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { } for _, node := range m.nodes { - accept, err := node.ShouldAcceptAttestedReport(ctx, m.seqNr, report) + accept, err := node.ShouldAcceptAttestedReport(ctx, m.seqNr, report.ReportWithInfo) if err != nil { return fmt.Errorf("failed to check if report should be accepted: %w", err) } @@ -168,7 +252,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { continue } - transmit, err := node.ShouldTransmitAcceptedReport(ctx, m.seqNr, report) + transmit, err := node.ShouldTransmitAcceptedReport(ctx, m.seqNr, report.ReportWithInfo) if err != nil { return fmt.Errorf("failed to check if report should be transmitted: %w", err) } @@ -177,7 +261,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { continue } - // For each node select a random set of f+1 signatures to mimic libocr behaviour + // For each node select a random set of F+1 signatures to mimic libocr behaviour s := rand.NewSource(time.Now().UnixNano()) r := rand.New(s) indices := r.Perm(len(signatures)) @@ -186,7 +270,7 @@ func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { selectedSignatures[i] = signatures[indices[i]] } - err = node.Transmit(ctx, types.ConfigDigest{}, 0, report, selectedSignatures) + err = node.Transmit(ctx, types.ConfigDigest{}, 0, report.ReportWithInfo, selectedSignatures) if err != nil { return fmt.Errorf("failed to transmit report: %w", err) } diff --git a/core/capabilities/integration_tests/framework/mock_target.go b/core/capabilities/integration_tests/framework/mock_target.go new file mode 100644 index 00000000000..e9c03deaca2 --- /dev/null +++ b/core/capabilities/integration_tests/framework/mock_target.go @@ -0,0 +1,93 @@ +package framework + +import ( + "context" + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" +) + +var ( + _ capabilities.ActionCapability = &mockTarget{} +) + +type TargetSink struct { + services.StateMachine + targetID string + targetName string + version string + + targets []mockTarget + Sink chan capabilities.CapabilityRequest +} + +func NewTargetSink(targetName string, version string) *TargetSink { + return &TargetSink{ + targetID: targetName + "@" + version, + targetName: targetName, + version: version, + Sink: make(chan capabilities.CapabilityRequest, 1000), + } +} + +func (ts *TargetSink) GetTargetVersion() string { + return ts.version +} + +func (ts *TargetSink) GetTargetName() string { + return ts.targetName +} + +func (ts *TargetSink) GetTargetID() string { + return ts.targetID +} + +func (ts *TargetSink) Start(ctx context.Context) error { + return ts.StartOnce("TargetSinkService", func() error { + return nil + }) +} + +func (ts *TargetSink) Close() error { + return ts.StopOnce("TargetSinkService", func() error { + return nil + }) +} + +func (ts *TargetSink) CreateNewTarget(t *testing.T) capabilities.TargetCapability { + target := mockTarget{ + t: t, + targetID: ts.targetID, + ch: ts.Sink, + } + ts.targets = append(ts.targets, target) + return &target +} + +type mockTarget struct { + t *testing.T + targetID string + ch chan capabilities.CapabilityRequest +} + +func (mt *mockTarget) Execute(ctx context.Context, rawRequest capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + mt.ch <- rawRequest + return capabilities.CapabilityResponse{}, nil +} + +func (mt *mockTarget) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return capabilities.MustNewCapabilityInfo( + mt.targetID, + capabilities.CapabilityTypeTarget, + "mock target for target ID "+mt.targetID, + ), nil +} + +func (mt *mockTarget) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { + return nil +} + +func (mt *mockTarget) UnregisterFromWorkflow(ctx context.Context, request capabilities.UnregisterFromWorkflowRequest) error { + return nil +} diff --git a/core/capabilities/integration_tests/framework/mock_trigger.go b/core/capabilities/integration_tests/framework/mock_trigger.go new file mode 100644 index 00000000000..afc874af6c3 --- /dev/null +++ b/core/capabilities/integration_tests/framework/mock_trigger.go @@ -0,0 +1,155 @@ +package framework + +import ( + "context" + "sync" + "testing" + + "github.com/google/uuid" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/values" +) + +// TriggerSink is a TriggerFactory implementation that sends output to all triggers created by it. +type TriggerSink struct { + services.StateMachine + triggerID string + triggerName string + version string + + triggers []mockTrigger + + stopCh services.StopChan + wg sync.WaitGroup +} + +func NewTriggerSink(t *testing.T, triggerName string, version string) *TriggerSink { + triggersFactory := &TriggerSink{ + triggerID: triggerName + "@" + version, + triggerName: triggerName, + version: version, + stopCh: make(services.StopChan), + } + servicetest.Run(t, triggersFactory) + return triggersFactory +} + +func (r *TriggerSink) GetTriggerVersion() string { + return r.version +} + +func (r *TriggerSink) GetTriggerName() string { + return r.triggerName +} + +func (r *TriggerSink) GetTriggerID() string { + return r.triggerID +} + +func (r *TriggerSink) Start(ctx context.Context) error { + return r.StartOnce("TriggerSink", func() error { + return nil + }) +} + +func (r *TriggerSink) Close() error { + return r.StopOnce("TriggerSink", func() error { + close(r.stopCh) + r.wg.Wait() + return nil + }) +} + +func (r *TriggerSink) SendOutput(outputs *values.Map) { + triggerEvent := capabilities.TriggerEvent{ + TriggerType: r.triggerID, + ID: uuid.New().String(), + Outputs: outputs, + } + + resp := capabilities.TriggerResponse{ + Event: triggerEvent, + } + + for _, trigger := range r.triggers { + trigger.sendResponse(resp) + } +} + +func (r *TriggerSink) CreateNewTrigger(t *testing.T) capabilities.TriggerCapability { + trigger := newMockTrigger(t, r.triggerID, &r.wg, r.stopCh) + r.triggers = append(r.triggers, trigger) + return &trigger +} + +type mockTrigger struct { + t *testing.T + triggerID string + cancel context.CancelFunc + toSend chan capabilities.TriggerResponse + + wg *sync.WaitGroup + stopCh services.StopChan +} + +func newMockTrigger(t *testing.T, triggerID string, wg *sync.WaitGroup, stopCh services.StopChan) mockTrigger { + return mockTrigger{ + t: t, + triggerID: triggerID, + toSend: make(chan capabilities.TriggerResponse, 1000), + wg: wg, + stopCh: stopCh, + } +} + +func (s *mockTrigger) sendResponse(resp capabilities.TriggerResponse) { + s.toSend <- resp +} + +func (s *mockTrigger) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return capabilities.MustNewCapabilityInfo( + s.triggerID, + capabilities.CapabilityTypeTrigger, + "mock trigger for trigger id "+s.triggerID, + ), nil +} + +func (s *mockTrigger) RegisterTrigger(ctx context.Context, request capabilities.TriggerRegistrationRequest) (<-chan capabilities.TriggerResponse, error) { + if s.cancel != nil { + s.t.Fatal("trigger already registered") + } + + responseCh := make(chan capabilities.TriggerResponse) + + ctxWithCancel, cancel := context.WithCancel(context.Background()) + s.cancel = cancel + s.wg.Add(1) + go func() { + defer s.wg.Done() + for { + select { + case <-s.stopCh: + return + case <-ctxWithCancel.Done(): + return + case resp := <-s.toSend: + responseCh <- resp + } + } + }() + + return responseCh, nil +} + +func (s *mockTrigger) UnregisterTrigger(ctx context.Context, request capabilities.TriggerRegistrationRequest) error { + if s.cancel == nil { + s.t.Fatal("trigger not registered") + } + + s.cancel() + s.cancel = nil + return nil +} diff --git a/core/capabilities/integration_tests/framework/peer.go b/core/capabilities/integration_tests/framework/peer.go new file mode 100644 index 00000000000..1ea24fba3ca --- /dev/null +++ b/core/capabilities/integration_tests/framework/peer.go @@ -0,0 +1,182 @@ +package framework + +import ( + "context" + "crypto/rand" + "encoding/hex" + "fmt" + "strings" + + "github.com/mr-tron/base58" + + ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "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" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +type peer struct { + PeerID string + Signer string +} + +func peerIDToBytes(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 := peerIDToBytes(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 := peerIDToBytes(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) + } + + var sigb [32]byte + copy(sigb[:], signerB) + + return kcr.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + P2pId: peerIDB, + Signer: sigb, + EncryptionPublicKey: testutils.Random32Byte(), + }, nil +} + +func getKeyBundlesAndPeerIDs(numNodes int) ([]ocr2key.KeyBundle, []peer, error) { + var keyBundles []ocr2key.KeyBundle + var donPeerIDs []peer + for i := 0; i < numNodes; i++ { + peerID := NewPeerID() + + keyBundle, err := ocr2key.New(chaintype.EVM) + if err != nil { + return nil, nil, fmt.Errorf("failed to create key bundle: %w", err) + } + + keyBundles = append(keyBundles, keyBundle) + + pk := keyBundle.PublicKey() + + p := peer{ + PeerID: peerID, + Signer: fmt.Sprintf("0x%x", pk), + } + + donPeerIDs = append(donPeerIDs, p) + } + return keyBundles, donPeerIDs, nil +} + +type peerWrapper struct { + peer p2pPeer +} + +func (t peerWrapper) Start(ctx context.Context) error { + return nil +} + +func (t peerWrapper) Close() error { + return nil +} + +func (t peerWrapper) Ready() error { + return nil +} + +func (t peerWrapper) HealthReport() map[string]error { + return nil +} + +func (t peerWrapper) Name() string { + return "peerWrapper" +} + +func (t peerWrapper) GetPeer() p2ptypes.Peer { + return t.peer +} + +type p2pPeer struct { + id p2ptypes.PeerID +} + +func (t p2pPeer) Start(ctx context.Context) error { + return nil +} + +func (t p2pPeer) Close() error { + return nil +} + +func (t p2pPeer) Ready() error { + return nil +} + +func (t p2pPeer) HealthReport() map[string]error { + return nil +} + +func (t p2pPeer) Name() string { + return "p2pPeer" +} + +func (t p2pPeer) ID() p2ptypes.PeerID { + return t.id +} + +func (t p2pPeer) UpdateConnections(peers map[p2ptypes.PeerID]p2ptypes.StreamConfig) error { + return nil +} + +func (t p2pPeer) Send(peerID p2ptypes.PeerID, msg []byte) error { + return nil +} + +func (t p2pPeer) Receive() <-chan p2ptypes.Message { + return nil +} + +func NewPeerID() string { + var privKey [32]byte + _, err := rand.Read(privKey[:]) + if err != nil { + panic(err) + } + + peerID := append(libp2pMagic(), privKey[:]...) + + return base58.Encode(peerID[:]) +} + +func libp2pMagic() []byte { + return []byte{0x00, 0x24, 0x08, 0x01, 0x12, 0x20} +} + +func ptr[T any](t T) *T { return &t } diff --git a/core/capabilities/integration_tests/keystone/contracts_setup.go b/core/capabilities/integration_tests/keystone/contracts_setup.go new file mode 100644 index 00000000000..396c74c7458 --- /dev/null +++ b/core/capabilities/integration_tests/keystone/contracts_setup.go @@ -0,0 +1,49 @@ +package keystone + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "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" +) + +func SetupForwarderContract(t *testing.T, reportCreator *framework.DON, + backend *framework.EthBlockchain) (common.Address, *forwarder.KeystoneForwarder) { + addr, _, fwd, err := forwarder.DeployKeystoneForwarder(backend.TransactionOpts(), backend) + require.NoError(t, err) + backend.Commit() + + var signers []common.Address + for _, p := range reportCreator.GetPeerIDs() { + signers = append(signers, common.HexToAddress(p.Signer)) + } + + _, err = fwd.SetConfig(backend.TransactionOpts(), reportCreator.GetID(), reportCreator.GetConfigVersion(), reportCreator.GetF(), signers) + require.NoError(t, err) + backend.Commit() + + return addr, fwd +} + +func SetupConsumerContract(t *testing.T, backend *framework.EthBlockchain, + forwarderAddress common.Address, workflowOwner string, workflowName string) (common.Address, *feeds_consumer.KeystoneFeedsConsumer) { + addr, _, consumer, err := feeds_consumer.DeployKeystoneFeedsConsumer(backend.TransactionOpts(), backend) + require.NoError(t, err) + backend.Commit() + + var nameBytes [10]byte + copy(nameBytes[:], workflowName) + + ownerAddr := common.HexToAddress(workflowOwner) + + _, err = consumer.SetConfig(backend.TransactionOpts(), []common.Address{forwarderAddress}, []common.Address{ownerAddr}, [][10]byte{nameBytes}) + require.NoError(t, err) + + backend.Commit() + + return addr, consumer +} diff --git a/core/capabilities/integration_tests/keystone/keystone_test.go b/core/capabilities/integration_tests/keystone/keystone_test.go new file mode 100644 index 00000000000..033bb8a2c76 --- /dev/null +++ b/core/capabilities/integration_tests/keystone/keystone_test.go @@ -0,0 +1,127 @@ +package keystone + +import ( + "context" + "crypto/rand" + "encoding/hex" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "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" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" +) + +func Test_AllAtOnceTransmissionSchedule(t *testing.T) { + testTransmissionSchedule(t, "2s", "allAtOnce") +} + +func Test_OneAtATimeTransmissionSchedule(t *testing.T) { + testTransmissionSchedule(t, "2s", "oneAtATime") +} + +func testTransmissionSchedule(t *testing.T, deltaStage string, schedule string) { + ctx := testutils.Context(t) + lggr := logger.TestLogger(t) + lggr.SetLogLevel(zapcore.InfoLevel) + + workflowDonConfiguration, err := framework.NewDonConfiguration(framework.NewDonConfigurationParams{Name: "Workflow", NumNodes: 7, F: 2, AcceptsWorkflows: true}) + require.NoError(t, err) + triggerDonConfiguration, err := framework.NewDonConfiguration(framework.NewDonConfigurationParams{Name: "Trigger", NumNodes: 7, F: 2}) + require.NoError(t, err) + targetDonConfiguration, err := framework.NewDonConfiguration(framework.NewDonConfigurationParams{Name: "Target", NumNodes: 4, F: 1}) + require.NoError(t, err) + + triggerSink := framework.NewTriggerSink(t, "streams-trigger", "1.0.0") + workflowDon, consumer := setupKeystoneDons(ctx, t, lggr, workflowDonConfiguration, triggerDonConfiguration, + targetDonConfiguration, triggerSink) + + feedCount := 3 + var feedIDs []string + for i := 0; i < feedCount; i++ { + feedIDs = append(feedIDs, newFeedID(t)) + } + + job := createKeystoneWorkflowJob(t, workflowName, workflowOwnerID, feedIDs, consumer.Address(), deltaStage, schedule) + err = workflowDon.AddJob(ctx, &job) + require.NoError(t, err) + + reports := []*datastreams.FeedReport{ + createFeedReport(t, big.NewInt(1), 5, feedIDs[0], triggerDonConfiguration.KeyBundles), + createFeedReport(t, big.NewInt(3), 7, feedIDs[1], triggerDonConfiguration.KeyBundles), + createFeedReport(t, big.NewInt(2), 6, feedIDs[2], triggerDonConfiguration.KeyBundles), + } + + wrappedReports, err := wrapReports(reports, 12, datastreams.Metadata{}) + require.NoError(t, err) + + triggerSink.SendOutput(wrappedReports) + + waitForConsumerReports(ctx, t, consumer, reports) +} + +func wrapReports(reportList []*datastreams.FeedReport, + timestamp int64, meta datastreams.Metadata) (*values.Map, error) { + var rl []datastreams.FeedReport + for _, r := range reportList { + rl = append(rl, *r) + } + + return values.WrapMap(datastreams.StreamsTriggerEvent{ + Payload: rl, + Metadata: meta, + Timestamp: timestamp, + }) +} + +func newFeedID(t *testing.T) string { + buf := [32]byte{} + _, err := rand.Read(buf[:]) + require.NoError(t, err) + return "0x" + hex.EncodeToString(buf[:]) +} + +func waitForConsumerReports(ctx context.Context, t *testing.T, consumer *feeds_consumer.KeystoneFeedsConsumer, triggerFeedReports []*datastreams.FeedReport) { + feedsReceived := make(chan *feeds_consumer.KeystoneFeedsConsumerFeedReceived, 1000) + feedsSub, err := consumer.WatchFeedReceived(&bind.WatchOpts{}, feedsReceived, nil) + require.NoError(t, err) + + feedToReport := map[string]*datastreams.FeedReport{} + for _, report := range triggerFeedReports { + feedToReport[report.FeedID] = report + } + + ctxWithTimeout, cancel := context.WithTimeout(ctx, 1*time.Minute) + defer cancel() + feedCount := 0 + for { + select { + case <-ctxWithTimeout.Done(): + t.Fatalf("timed out waiting for feed reports, expected %d, received %d", len(triggerFeedReports), feedCount) + case err := <-feedsSub.Err(): + require.NoError(t, err) + case feed := <-feedsReceived: + feedID := "0x" + hex.EncodeToString(feed.FeedId[:]) + report := feedToReport[feedID] + decodedReport, err := reporttypes.Decode(report.FullReport) + require.NoError(t, err) + assert.Equal(t, decodedReport.BenchmarkPrice, feed.Price) + assert.Equal(t, decodedReport.ObservationsTimestamp, feed.Timestamp) + + feedCount++ + if feedCount == len(triggerFeedReports) { + return + } + } + } +} diff --git a/core/capabilities/integration_tests/keystone/setup.go b/core/capabilities/integration_tests/keystone/setup.go new file mode 100644 index 00000000000..f90b582d0ee --- /dev/null +++ b/core/capabilities/integration_tests/keystone/setup.go @@ -0,0 +1,138 @@ +package keystone + +import ( + "context" + "encoding/hex" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" + 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" + + ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" +) + +var ( + workflowName = "abcdef0123" + workflowOwnerID = "0100000000000000000000000000000000000001" +) + +func setupKeystoneDons(ctx context.Context, t *testing.T, lggr logger.SugaredLogger, + workflowDonInfo framework.DonConfiguration, + triggerDonInfo framework.DonConfiguration, + targetDonInfo framework.DonConfiguration, + trigger framework.TriggerFactory) (workflowDon *framework.DON, consumer *feeds_consumer.KeystoneFeedsConsumer) { + donContext := framework.CreateDonContext(ctx, t) + + workflowDon = createKeystoneWorkflowDon(ctx, t, lggr, workflowDonInfo, triggerDonInfo, targetDonInfo, donContext) + + forwarderAddr, _ := SetupForwarderContract(t, workflowDon, donContext.EthBlockchain) + _, consumer = SetupConsumerContract(t, donContext.EthBlockchain, forwarderAddr, workflowOwnerID, workflowName) + + writeTargetDon := createKeystoneWriteTargetDon(ctx, t, lggr, targetDonInfo, donContext, forwarderAddr) + + triggerDon := createKeystoneTriggerDon(ctx, t, lggr, triggerDonInfo, donContext, trigger) + + workflowDon.Start(ctx, t) + triggerDon.Start(ctx, t) + writeTargetDon.Start(ctx, t) + + return workflowDon, consumer +} + +func createKeystoneTriggerDon(ctx context.Context, t *testing.T, lggr logger.SugaredLogger, triggerDonInfo framework.DonConfiguration, + donContext framework.DonContext, trigger framework.TriggerFactory) *framework.DON { + triggerDon := framework.NewDON(ctx, t, lggr, triggerDonInfo, + []commoncap.DON{}, donContext, false) + + triggerDon.AddExternalTriggerCapability(trigger) + triggerDon.Initialise() + return triggerDon +} + +func createKeystoneWriteTargetDon(ctx context.Context, t *testing.T, lggr logger.SugaredLogger, targetDonInfo framework.DonConfiguration, donContext framework.DonContext, forwarderAddr common.Address) *framework.DON { + writeTargetDon := framework.NewDON(ctx, t, lggr, targetDonInfo, + []commoncap.DON{}, donContext, false) + err := writeTargetDon.AddEthereumWriteTargetNonStandardCapability(forwarderAddr) + require.NoError(t, err) + writeTargetDon.Initialise() + return writeTargetDon +} + +func createKeystoneWorkflowDon(ctx context.Context, t *testing.T, lggr logger.SugaredLogger, workflowDonInfo framework.DonConfiguration, + triggerDonInfo framework.DonConfiguration, targetDonInfo framework.DonConfiguration, donContext framework.DonContext) *framework.DON { + workflowDon := framework.NewDON(ctx, t, lggr, workflowDonInfo, + []commoncap.DON{triggerDonInfo.DON, targetDonInfo.DON}, + donContext, true) + + workflowDon.AddOCR3NonStandardCapability() + workflowDon.Initialise() + return workflowDon +} + +func createFeedReport(t *testing.T, price *big.Int, observationTimestamp int64, + feedIDString string, + keyBundles []ocr2key.KeyBundle) *datastreams.FeedReport { + reportCtx := ocrTypes.ReportContext{} + rawCtx := RawReportContext(reportCtx) + + bytes, err := hex.DecodeString(feedIDString[2:]) + require.NoError(t, err) + var feedIDBytes [32]byte + copy(feedIDBytes[:], bytes) + + report := &datastreams.FeedReport{ + FeedID: feedIDString, + FullReport: newReport(t, feedIDBytes, price, observationTimestamp), + BenchmarkPrice: price.Bytes(), + ObservationTimestamp: observationTimestamp, + Signatures: [][]byte{}, + ReportContext: rawCtx, + } + + for _, key := range keyBundles { + sig, err := key.Sign(reportCtx, report.FullReport) + require.NoError(t, err) + report.Signatures = append(report.Signatures, sig) + } + + return report +} + +func RawReportContext(reportCtx ocrTypes.ReportContext) []byte { + rc := evmutil.RawReportContext(reportCtx) + flat := []byte{} + for _, r := range rc { + flat = append(flat, r[:]...) + } + return flat +} + +func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) []byte { + ctx := tests.Context(t) + v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) + raw, err := v3Codec.BuildReport(ctx, v3.ReportFields{ + BenchmarkPrice: price, + //nolint:gosec // disable G115 + Timestamp: uint32(timestamp), + Bid: big.NewInt(0), + Ask: big.NewInt(0), + LinkFee: big.NewInt(0), + NativeFee: big.NewInt(0), + }) + require.NoError(t, err) + return raw +} diff --git a/core/capabilities/integration_tests/workflow.go b/core/capabilities/integration_tests/keystone/workflow.go similarity index 79% rename from core/capabilities/integration_tests/workflow.go rename to core/capabilities/integration_tests/keystone/workflow.go index d116a1ec639..1686fd2d6dd 100644 --- a/core/capabilities/integration_tests/workflow.go +++ b/core/capabilities/integration_tests/keystone/workflow.go @@ -1,14 +1,12 @@ -package integration_tests +package keystone import ( "fmt" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" ) @@ -49,13 +47,13 @@ targets: schedule: %s ` -func addWorkflowJob(t *testing.T, app *cltest.TestApplication, +func createKeystoneWorkflowJob(t *testing.T, workflowName string, workflowOwner string, feedIDs []string, consumerAddr common.Address, deltaStage string, - schedule string) { + schedule string) job.Job { triggerFeedIDs := "" for _, feedID := range feedIDs { triggerFeedIDs += fmt.Sprintf(" - \"%s\"\n", feedID) @@ -68,8 +66,5 @@ func addWorkflowJob(t *testing.T, app *cltest.TestApplication, workflowJobSpec := testspecs.GenerateWorkflowJobSpec(t, fmt.Sprintf(hardcodedWorkflow, workflowName, workflowOwner, triggerFeedIDs, aggregationFeeds, consumerAddr.String(), deltaStage, schedule)) - job := workflowJobSpec.Job() - - err := app.AddJobV2(testutils.Context(t), &job) - require.NoError(t, err) + return workflowJobSpec.Job() } diff --git a/core/capabilities/integration_tests/keystone_contracts_setup.go b/core/capabilities/integration_tests/keystone_contracts_setup.go deleted file mode 100644 index b138b8f8127..00000000000 --- a/core/capabilities/integration_tests/keystone_contracts_setup.go +++ /dev/null @@ -1,362 +0,0 @@ -package integration_tests - -import ( - "context" - "encoding/hex" - "fmt" - "log" - "os" - "strings" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/eth/ethconfig" - gethlog "github.com/ethereum/go-ethereum/log" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - - ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" - "github.com/smartcontractkit/chainlink-common/pkg/values" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" -) - -const ( - CapabilityTypeTrigger = 0 - CapabilityTypeAction = 1 - CapabilityTypeConsensus = 2 - CapabilityTypeTarget = 3 -) - -type peer struct { - PeerID string - Signer string -} - -func peerIDToBytes(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 := peerIDToBytes(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 := peerIDToBytes(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) - } - - var sigb [32]byte - copy(sigb[:], signerB) - - return kcr.CapabilitiesRegistryNodeParams{ - NodeOperatorId: nopID, - P2pId: peerIDB, - Signer: sigb, - }, nil -} - -func setupCapabilitiesRegistryContract(ctx context.Context, t *testing.T, workflowDon donInfo, triggerDon donInfo, - targetDon donInfo, - transactOpts *bind.TransactOpts, backend *ethBackend) common.Address { - addr, _, reg, err := kcr.DeployCapabilitiesRegistry(transactOpts, backend) - require.NoError(t, err) - - backend.Commit() - - streamsTrigger := kcr.CapabilitiesRegistryCapability{ - LabelledName: "streams-trigger", - Version: "1.0.0", - CapabilityType: CapabilityTypeTrigger, - } - sid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) - require.NoError(t, err) - - writeChain := kcr.CapabilitiesRegistryCapability{ - LabelledName: "write_geth-testnet", - Version: "1.0.0", - - CapabilityType: CapabilityTypeTarget, - } - wid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) - if err != nil { - log.Printf("failed to call GetHashedCapabilityId: %s", err) - } - - ocr := kcr.CapabilitiesRegistryCapability{ - LabelledName: "offchain_reporting", - Version: "1.0.0", - CapabilityType: CapabilityTypeConsensus, - } - ocrid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, ocr.LabelledName, ocr.Version) - require.NoError(t, err) - - _, err = reg.AddCapabilities(transactOpts, []kcr.CapabilitiesRegistryCapability{ - streamsTrigger, - writeChain, - ocr, - }) - require.NoError(t, err) - backend.Commit() - - _, err = reg.AddNodeOperators(transactOpts, []kcr.CapabilitiesRegistryNodeOperator{ - { - Admin: transactOpts.From, - Name: "TEST_NODE_OPERATOR", - }, - }) - require.NoError(t, err) - blockHash := backend.Commit() - - logs, err := backend.FilterLogs(ctx, ethereum.FilterQuery{ - BlockHash: &blockHash, - FromBlock: nil, - ToBlock: nil, - Addresses: nil, - Topics: nil, - }) - - require.NoError(t, err) - - recLog, err := reg.ParseNodeOperatorAdded(logs[0]) - require.NoError(t, err) - - nopID := recLog.NodeOperatorId - nodes := []kcr.CapabilitiesRegistryNodeParams{} - for _, wfPeer := range workflowDon.peerIDs { - n, innerErr := peerToNode(nopID, wfPeer) - require.NoError(t, innerErr) - - n.HashedCapabilityIds = [][32]byte{ocrid} - nodes = append(nodes, n) - } - - for _, triggerPeer := range triggerDon.peerIDs { - n, innerErr := peerToNode(nopID, triggerPeer) - require.NoError(t, innerErr) - - n.HashedCapabilityIds = [][32]byte{sid} - nodes = append(nodes, n) - } - - for _, targetPeer := range targetDon.peerIDs { - n, innerErr := peerToNode(nopID, targetPeer) - require.NoError(t, innerErr) - - n.HashedCapabilityIds = [][32]byte{wid} - nodes = append(nodes, n) - } - - _, err = reg.AddNodes(transactOpts, nodes) - require.NoError(t, err) - - // workflow DON - ps, err := peers(workflowDon.peerIDs) - require.NoError(t, err) - - cc := newCapabilityConfig() - ccb, err := proto.Marshal(cc) - require.NoError(t, err) - - cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: ocrid, - Config: ccb, - }, - } - - _, err = reg.AddDON(transactOpts, ps, cfgs, false, true, workflowDon.F) - require.NoError(t, err) - - // trigger DON - ps, err = peers(triggerDon.peerIDs) - require.NoError(t, err) - - triggerCapabilityConfig := newCapabilityConfig() - triggerCapabilityConfig.RemoteConfig = &pb.CapabilityConfig_RemoteTriggerConfig{ - RemoteTriggerConfig: &pb.RemoteTriggerConfig{ - RegistrationRefresh: durationpb.New(1000 * time.Millisecond), - RegistrationExpiry: durationpb.New(60000 * time.Millisecond), - // F + 1 - MinResponsesToAggregate: uint32(triggerDon.F) + 1, - }, - } - - configb, err := proto.Marshal(triggerCapabilityConfig) - require.NoError(t, err) - - cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: sid, - Config: configb, - }, - } - - _, err = reg.AddDON(transactOpts, ps, cfgs, true, false, triggerDon.F) - require.NoError(t, err) - - // target DON - ps, err = peers(targetDon.peerIDs) - require.NoError(t, err) - - targetCapabilityConfig := newCapabilityConfig() - targetCapabilityConfig.RemoteConfig = &pb.CapabilityConfig_RemoteTargetConfig{ - RemoteTargetConfig: &pb.RemoteTargetConfig{ - RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, - }, - } - - remoteTargetConfigBytes, err := proto.Marshal(targetCapabilityConfig) - require.NoError(t, err) - - cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: wid, - Config: remoteTargetConfigBytes, - }, - } - - _, err = reg.AddDON(transactOpts, ps, cfgs, true, false, targetDon.F) - require.NoError(t, err) - - backend.Commit() - - return addr -} - -func newCapabilityConfig() *pb.CapabilityConfig { - return &pb.CapabilityConfig{ - DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), - } -} - -func setupForwarderContract(t *testing.T, workflowDon donInfo, - transactOpts *bind.TransactOpts, backend *ethBackend) (common.Address, *forwarder.KeystoneForwarder) { - addr, _, fwd, err := forwarder.DeployKeystoneForwarder(transactOpts, backend) - require.NoError(t, err) - backend.Commit() - - var signers []common.Address - for _, p := range workflowDon.peerIDs { - signers = append(signers, common.HexToAddress(p.Signer)) - } - - _, err = fwd.SetConfig(transactOpts, workflowDon.ID, workflowDon.ConfigVersion, workflowDon.F, signers) - require.NoError(t, err) - backend.Commit() - - return addr, fwd -} - -func setupConsumerContract(t *testing.T, transactOpts *bind.TransactOpts, backend *ethBackend, - forwarderAddress common.Address, workflowOwner string, workflowName string) (common.Address, *feeds_consumer.KeystoneFeedsConsumer) { - addr, _, consumer, err := feeds_consumer.DeployKeystoneFeedsConsumer(transactOpts, backend) - require.NoError(t, err) - backend.Commit() - - var nameBytes [10]byte - copy(nameBytes[:], workflowName) - - ownerAddr := common.HexToAddress(workflowOwner) - - _, err = consumer.SetConfig(transactOpts, []common.Address{forwarderAddress}, []common.Address{ownerAddr}, [][10]byte{nameBytes}) - require.NoError(t, err) - - backend.Commit() - - return addr, consumer -} - -type ethBackend struct { - services.StateMachine - *backends.SimulatedBackend - - blockTimeProcessingTime time.Duration - - stopCh services.StopChan - wg sync.WaitGroup -} - -func setupBlockchain(t *testing.T, initialEth int, blockTimeProcessingTime time.Duration) (*ethBackend, *bind.TransactOpts) { - transactOpts := testutils.MustNewSimTransactor(t) // config contract deployer and owner - genesisData := core.GenesisAlloc{transactOpts.From: {Balance: assets.Ether(initialEth).ToInt()}} - backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) - gethlog.SetDefault(gethlog.NewLogger(gethlog.NewTerminalHandlerWithLevel(os.Stderr, gethlog.LevelWarn, true))) - backend.Commit() - - return ðBackend{SimulatedBackend: backend, stopCh: make(services.StopChan), - blockTimeProcessingTime: blockTimeProcessingTime}, transactOpts -} - -func (b *ethBackend) Start(ctx context.Context) error { - return b.StartOnce("ethBackend", func() error { - b.wg.Add(1) - go func() { - defer b.wg.Done() - ticker := time.NewTicker(b.blockTimeProcessingTime) - defer ticker.Stop() - - for { - select { - case <-b.stopCh: - return - case <-ctx.Done(): - return - case <-ticker.C: - b.SimulatedBackend.Commit() - } - } - }() - - return nil - }) -} - -func (b *ethBackend) Close() error { - return b.StopOnce("ethBackend", func() error { - close(b.stopCh) - b.wg.Wait() - return nil - }) -} diff --git a/core/capabilities/integration_tests/mock_trigger.go b/core/capabilities/integration_tests/mock_trigger.go deleted file mode 100644 index 0ed1fe5c8dd..00000000000 --- a/core/capabilities/integration_tests/mock_trigger.go +++ /dev/null @@ -1,149 +0,0 @@ -package integration_tests - -import ( - "context" - "fmt" - "strconv" - "sync" - "testing" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/values" -) - -const triggerID = "streams-trigger@1.0.0" - -type reportsSink struct { - services.StateMachine - triggers []streamsTrigger - - stopCh services.StopChan - wg sync.WaitGroup -} - -func newReportsSink() *reportsSink { - return &reportsSink{ - stopCh: make(services.StopChan), - } -} - -func (r *reportsSink) Start(ctx context.Context) error { - return r.StartOnce("reportsSink", func() error { - return nil - }) -} - -func (r *reportsSink) Close() error { - return r.StopOnce("reportsSink", func() error { - close(r.stopCh) - r.wg.Wait() - return nil - }) -} - -func (r *reportsSink) sendReports(reportList []*datastreams.FeedReport) { - for _, trigger := range r.triggers { - resp, err := wrapReports(reportList, "1", 12, datastreams.SignersMetadata{}) - if err != nil { - panic(err) - } - trigger.sendResponse(resp) - } -} - -func (r *reportsSink) getNewTrigger(t *testing.T) *streamsTrigger { - trigger := streamsTrigger{t: t, toSend: make(chan capabilities.CapabilityResponse, 1000), - wg: &r.wg, stopCh: r.stopCh} - r.triggers = append(r.triggers, trigger) - return &trigger -} - -type streamsTrigger struct { - t *testing.T - cancel context.CancelFunc - toSend chan capabilities.CapabilityResponse - - wg *sync.WaitGroup - stopCh services.StopChan -} - -func (s *streamsTrigger) sendResponse(resp capabilities.CapabilityResponse) { - s.toSend <- resp -} - -func (s *streamsTrigger) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { - return capabilities.MustNewCapabilityInfo( - triggerID, - capabilities.CapabilityTypeTrigger, - "issues a trigger when a report is received.", - ), nil -} - -func (s *streamsTrigger) RegisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - if s.cancel != nil { - s.t.Fatal("trigger already registered") - } - - responseCh := make(chan capabilities.CapabilityResponse) - - ctxWithCancel, cancel := context.WithCancel(context.Background()) - s.cancel = cancel - s.wg.Add(1) - go func() { - defer s.wg.Done() - for { - select { - case <-s.stopCh: - return - case <-ctxWithCancel.Done(): - return - case resp := <-s.toSend: - responseCh <- resp - } - } - }() - - return responseCh, nil -} - -func (s *streamsTrigger) UnregisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) error { - if s.cancel == nil { - s.t.Fatal("trigger not registered") - } - - s.cancel() - s.cancel = nil - return nil -} - -func wrapReports(reportList []*datastreams.FeedReport, eventID string, timestamp int64, meta datastreams.SignersMetadata) (capabilities.CapabilityResponse, error) { - val, err := values.Wrap(reportList) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - metaVal, err := values.Wrap(meta) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - triggerEvent := capabilities.TriggerEvent{ - TriggerType: triggerID, - ID: eventID, - Timestamp: strconv.FormatInt(timestamp, 10), - Metadata: metaVal, - Payload: val, - } - - triggerEventMapValue, err := values.WrapMap(triggerEvent) - if err != nil { - return capabilities.CapabilityResponse{}, fmt.Errorf("failed to wrap trigger event: %w", err) - } - - // Create a new CapabilityResponse with the MercuryTriggerEvent - return capabilities.CapabilityResponse{ - Value: triggerEventMapValue, - }, nil -} diff --git a/core/capabilities/integration_tests/setup.go b/core/capabilities/integration_tests/setup.go deleted file mode 100644 index 69b8c3eaa0a..00000000000 --- a/core/capabilities/integration_tests/setup.go +++ /dev/null @@ -1,439 +0,0 @@ -package integration_tests - -import ( - "context" - "crypto/rand" - "encoding/hex" - "fmt" - "math/big" - "strconv" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/mr-tron/base58" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" - - commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" - v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" - "github.com/smartcontractkit/chainlink/v2/core/capabilities" - 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" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" -) - -const ( - // As a default set the logging to info otherwise 10s/100s of MB of logs are created on each test run - TestLogLevel = zapcore.InfoLevel -) - -var ( - workflowName = "abcdef0123" - workflowOwnerID = "0100000000000000000000000000000000000001" -) - -type donInfo struct { - commoncap.DON - keys []ethkey.KeyV2 - keyBundles []ocr2key.KeyBundle - peerIDs []peer -} - -func setupStreamDonsWithTransmissionSchedule(ctx context.Context, t *testing.T, workflowDonInfo donInfo, triggerDonInfo donInfo, targetDonInfo donInfo, - feedCount int, deltaStage string, schedule string) (*feeds_consumer.KeystoneFeedsConsumer, []string, *reportsSink) { - lggr := logger.TestLogger(t) - lggr.SetLogLevel(TestLogLevel) - - ethBlockchain, transactor := setupBlockchain(t, 1000, 1*time.Second) - capabilitiesRegistryAddr := setupCapabilitiesRegistryContract(ctx, t, workflowDonInfo, triggerDonInfo, targetDonInfo, transactor, ethBlockchain) - forwarderAddr, _ := setupForwarderContract(t, workflowDonInfo, transactor, ethBlockchain) - consumerAddr, consumer := setupConsumerContract(t, transactor, ethBlockchain, forwarderAddr, workflowOwnerID, workflowName) - - var feedIDs []string - for i := 0; i < feedCount; i++ { - feedIDs = append(feedIDs, newFeedID(t)) - } - - sink := newReportsSink() - - libocr := newMockLibOCR(t, workflowDonInfo.F, 1*time.Second) - workflowDonNodes, _, _ := createDons(ctx, t, lggr, sink, - workflowDonInfo, triggerDonInfo, targetDonInfo, - ethBlockchain, capabilitiesRegistryAddr, forwarderAddr, - workflowDonInfo.keyBundles, transactor, libocr) - for _, node := range workflowDonNodes { - addWorkflowJob(t, node, workflowName, workflowOwnerID, feedIDs, consumerAddr, deltaStage, schedule) - } - - servicetest.Run(t, ethBlockchain) - servicetest.Run(t, libocr) - servicetest.Run(t, sink) - return consumer, feedIDs, sink -} - -func createDons(ctx context.Context, t *testing.T, lggr logger.Logger, reportsSink *reportsSink, - workflowDon donInfo, - triggerDon donInfo, - targetDon donInfo, - simulatedEthBlockchain *ethBackend, - capRegistryAddr common.Address, - forwarderAddr common.Address, - workflowNodeKeyBundles []ocr2key.KeyBundle, - transactor *bind.TransactOpts, - libocr *mockLibOCR, -) ([]*cltest.TestApplication, []*cltest.TestApplication, []*cltest.TestApplication) { - broker := newTestAsyncMessageBroker(t, 1000) - - var triggerNodes []*cltest.TestApplication - for i, triggerPeer := range triggerDon.Members { - triggerPeerDispatcher := broker.NewDispatcherForNode(triggerPeer) - nodeInfo := commoncap.Node{ - PeerID: &triggerPeer, - } - - capabilityRegistry := capabilities.NewRegistry(lggr) - trigger := reportsSink.getNewTrigger(t) - err := capabilityRegistry.Add(ctx, trigger) - require.NoError(t, err) - - triggerNode := startNewNode(ctx, t, lggr.Named("Trigger-"+strconv.Itoa(i)), nodeInfo, simulatedEthBlockchain, capRegistryAddr, triggerPeerDispatcher, - testPeerWrapper{peer: testPeer{triggerPeer}}, capabilityRegistry, nil, transactor, - triggerDon.keys[i]) - - require.NoError(t, triggerNode.Start(testutils.Context(t))) - triggerNodes = append(triggerNodes, triggerNode) - } - - var targetNodes []*cltest.TestApplication - for i, targetPeer := range targetDon.Members { - targetPeerDispatcher := broker.NewDispatcherForNode(targetPeer) - nodeInfo := commoncap.Node{ - PeerID: &targetPeer, - } - - capabilityRegistry := capabilities.NewRegistry(lggr) - - targetNode := startNewNode(ctx, t, lggr.Named("Target-"+strconv.Itoa(i)), nodeInfo, simulatedEthBlockchain, capRegistryAddr, targetPeerDispatcher, - testPeerWrapper{peer: testPeer{targetPeer}}, capabilityRegistry, &forwarderAddr, transactor, - targetDon.keys[i]) - - require.NoError(t, targetNode.Start(testutils.Context(t))) - targetNodes = append(triggerNodes, targetNode) - } - - var workflowNodes []*cltest.TestApplication - for i, workflowPeer := range workflowDon.Members { - workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeer) - capabilityRegistry := capabilities.NewRegistry(lggr) - - requestTimeout := 10 * time.Minute - cfg := ocr3.Config{ - Logger: lggr, - EncoderFactory: evm.NewEVMEncoder, - AggregatorFactory: capabilities.NewAggregator, - RequestTimeout: &requestTimeout, - } - - ocr3Capability := ocr3.NewOCR3(cfg) - servicetest.Run(t, ocr3Capability) - - pluginCfg := coretypes.ReportingPluginServiceConfig{} - pluginFactory, err := ocr3Capability.NewReportingPluginFactory(ctx, pluginCfg, nil, - nil, nil, nil, capabilityRegistry, nil, nil) - require.NoError(t, err) - - repConfig := ocr3types.ReportingPluginConfig{ - F: int(workflowDon.F), - } - plugin, _, err := pluginFactory.NewReportingPlugin(repConfig) - require.NoError(t, err) - - transmitter := ocr3.NewContractTransmitter(lggr, capabilityRegistry, "") - - libocr.AddNode(plugin, transmitter, workflowNodeKeyBundles[i]) - - nodeInfo := commoncap.Node{ - PeerID: &workflowPeer, - WorkflowDON: workflowDon.DON, - CapabilityDONs: []commoncap.DON{triggerDon.DON, targetDon.DON}, - } - - workflowNode := startNewNode(ctx, t, lggr.Named("Workflow-"+strconv.Itoa(i)), nodeInfo, simulatedEthBlockchain, capRegistryAddr, workflowPeerDispatcher, - testPeerWrapper{peer: testPeer{workflowPeer}}, capabilityRegistry, nil, transactor, - workflowDon.keys[i]) - - require.NoError(t, workflowNode.Start(testutils.Context(t))) - workflowNodes = append(workflowNodes, workflowNode) - } - - servicetest.Run(t, broker) - - return workflowNodes, triggerNodes, targetNodes -} - -func startNewNode(ctx context.Context, - t *testing.T, lggr logger.Logger, nodeInfo commoncap.Node, - backend *ethBackend, capRegistryAddr common.Address, - dispatcher remotetypes.Dispatcher, - peerWrapper p2ptypes.PeerWrapper, - localCapabilities *capabilities.Registry, - forwarderAddress *common.Address, - transactor *bind.TransactOpts, - keyV2 ethkey.KeyV2, -) *cltest.TestApplication { - config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Capabilities.ExternalRegistry.ChainID = ptr(fmt.Sprintf("%d", testutils.SimulatedChainID)) - c.Capabilities.ExternalRegistry.Address = ptr(capRegistryAddr.String()) - c.Capabilities.Peering.V2.Enabled = ptr(true) - - if forwarderAddress != nil { - eip55Address := types.EIP55AddressFromAddress(*forwarderAddress) - c.EVM[0].Chain.Workflow.ForwarderAddress = &eip55Address - c.EVM[0].Chain.Workflow.FromAddress = &keyV2.EIP55Address - } - - c.Feature.FeedsManager = ptr(false) - }) - - n, err := backend.NonceAt(ctx, transactor.From, nil) - require.NoError(t, err) - - tx := cltest.NewLegacyTransaction( - n, keyV2.Address, - assets.Ether(1).ToInt(), - 21000, - assets.GWei(1).ToInt(), - nil) - signedTx, err := transactor.Signer(transactor.From, tx) - require.NoError(t, err) - err = backend.SendTransaction(ctx, signedTx) - require.NoError(t, err) - backend.Commit() - - return cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, backend.SimulatedBackend, nodeInfo, - dispatcher, peerWrapper, localCapabilities, keyV2, lggr) -} - -type don struct { - id uint32 - numNodes int - f uint8 -} - -func createDonInfo(t *testing.T, don don) donInfo { - keyBundles, peerIDs := getKeyBundlesAndPeerIDs(t, don.numNodes) - - donPeers := make([]p2ptypes.PeerID, len(peerIDs)) - var donKeys []ethkey.KeyV2 - for i := 0; i < len(peerIDs); i++ { - peerID := p2ptypes.PeerID{} - require.NoError(t, peerID.UnmarshalText([]byte(peerIDs[i].PeerID))) - donPeers[i] = peerID - newKey, err := ethkey.NewV2() - require.NoError(t, err) - donKeys = append(donKeys, newKey) - } - - triggerDonInfo := donInfo{ - DON: commoncap.DON{ - ID: don.id, - Members: donPeers, - F: don.f, - ConfigVersion: 1, - }, - peerIDs: peerIDs, - keys: donKeys, - keyBundles: keyBundles, - } - return triggerDonInfo -} - -func createFeedReport(t *testing.T, price *big.Int, observationTimestamp int64, - feedIDString string, - keyBundles []ocr2key.KeyBundle) *datastreams.FeedReport { - reportCtx := ocrTypes.ReportContext{} - rawCtx := RawReportContext(reportCtx) - - bytes, err := hex.DecodeString(feedIDString[2:]) - require.NoError(t, err) - var feedIDBytes [32]byte - copy(feedIDBytes[:], bytes) - - report := &datastreams.FeedReport{ - FeedID: feedIDString, - FullReport: newReport(t, feedIDBytes, price, observationTimestamp), - BenchmarkPrice: price.Bytes(), - ObservationTimestamp: observationTimestamp, - Signatures: [][]byte{}, - ReportContext: rawCtx, - } - - for _, key := range keyBundles { - sig, err := key.Sign(reportCtx, report.FullReport) - require.NoError(t, err) - report.Signatures = append(report.Signatures, sig) - } - - return report -} - -func getKeyBundlesAndPeerIDs(t *testing.T, numNodes int) ([]ocr2key.KeyBundle, []peer) { - var keyBundles []ocr2key.KeyBundle - var donPeerIDs []peer - for i := 0; i < numNodes; i++ { - peerID := NewPeerID() - - keyBundle, err := ocr2key.New(chaintype.EVM) - require.NoError(t, err) - keyBundles = append(keyBundles, keyBundle) - - pk := keyBundle.PublicKey() - - p := peer{ - PeerID: peerID, - Signer: fmt.Sprintf("0x%x", pk), - } - - donPeerIDs = append(donPeerIDs, p) - } - return keyBundles, donPeerIDs -} - -func newFeedID(t *testing.T) string { - buf := [32]byte{} - _, err := rand.Read(buf[:]) - require.NoError(t, err) - return "0x" + hex.EncodeToString(buf[:]) -} - -func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) []byte { - v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) - raw, err := v3Codec.BuildReport(v3.ReportFields{ - BenchmarkPrice: price, - Timestamp: uint32(timestamp), - Bid: big.NewInt(0), - Ask: big.NewInt(0), - LinkFee: big.NewInt(0), - NativeFee: big.NewInt(0), - }) - require.NoError(t, err) - return raw -} - -type testPeerWrapper struct { - peer testPeer -} - -func (t testPeerWrapper) Start(ctx context.Context) error { - return nil -} - -func (t testPeerWrapper) Close() error { - return nil -} - -func (t testPeerWrapper) Ready() error { - return nil -} - -func (t testPeerWrapper) HealthReport() map[string]error { - return nil -} - -func (t testPeerWrapper) Name() string { - return "testPeerWrapper" -} - -func (t testPeerWrapper) GetPeer() p2ptypes.Peer { - return t.peer -} - -type testPeer struct { - id p2ptypes.PeerID -} - -func (t testPeer) Start(ctx context.Context) error { - return nil -} - -func (t testPeer) Close() error { - return nil -} - -func (t testPeer) Ready() error { - return nil -} - -func (t testPeer) HealthReport() map[string]error { - return nil -} - -func (t testPeer) Name() string { - return "testPeer" -} - -func (t testPeer) ID() p2ptypes.PeerID { - return t.id -} - -func (t testPeer) UpdateConnections(peers map[p2ptypes.PeerID]p2ptypes.StreamConfig) error { - return nil -} - -func (t testPeer) Send(peerID p2ptypes.PeerID, msg []byte) error { - return nil -} - -func (t testPeer) Receive() <-chan p2ptypes.Message { - return nil -} - -func NewPeerID() string { - var privKey [32]byte - _, err := rand.Read(privKey[:]) - if err != nil { - panic(err) - } - - peerID := append(libp2pMagic(), privKey[:]...) - - return base58.Encode(peerID[:]) -} - -func libp2pMagic() []byte { - return []byte{0x00, 0x24, 0x08, 0x01, 0x12, 0x20} -} - -func ptr[T any](t T) *T { return &t } - -func RawReportContext(reportCtx ocrTypes.ReportContext) []byte { - rc := evmutil.RawReportContext(reportCtx) - flat := []byte{} - for _, r := range rc { - flat = append(flat, r[:]...) - } - return flat -} diff --git a/core/capabilities/integration_tests/streams_test.go b/core/capabilities/integration_tests/streams_test.go deleted file mode 100644 index 8c8f51914c2..00000000000 --- a/core/capabilities/integration_tests/streams_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package integration_tests - -import ( - "context" - "encoding/hex" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" -) - -func Test_AllAtOnceTransmissionSchedule(t *testing.T) { - ctx := testutils.Context(t) - - // The don IDs set in the below calls are inferred from the order in which the dons are added to the capabilities registry - // in the setupCapabilitiesRegistryContract function, should this order change the don IDs will need updating. - workflowDonInfo := createDonInfo(t, don{id: 1, numNodes: 7, f: 2}) - triggerDonInfo := createDonInfo(t, don{id: 2, numNodes: 7, f: 2}) - targetDonInfo := createDonInfo(t, don{id: 3, numNodes: 4, f: 1}) - - consumer, feedIDs, triggerSink := setupStreamDonsWithTransmissionSchedule(ctx, t, workflowDonInfo, triggerDonInfo, targetDonInfo, 3, - "2s", "allAtOnce") - - reports := []*datastreams.FeedReport{ - createFeedReport(t, big.NewInt(1), 5, feedIDs[0], triggerDonInfo.keyBundles), - createFeedReport(t, big.NewInt(3), 7, feedIDs[1], triggerDonInfo.keyBundles), - createFeedReport(t, big.NewInt(2), 6, feedIDs[2], triggerDonInfo.keyBundles), - } - - triggerSink.sendReports(reports) - - waitForConsumerReports(ctx, t, consumer, reports) -} - -func Test_OneAtATimeTransmissionSchedule(t *testing.T) { - ctx := testutils.Context(t) - - // The don IDs set in the below calls are inferred from the order in which the dons are added to the capabilities registry - // in the setupCapabilitiesRegistryContract function, should this order change the don IDs will need updating. - workflowDonInfo := createDonInfo(t, don{id: 1, numNodes: 7, f: 2}) - triggerDonInfo := createDonInfo(t, don{id: 2, numNodes: 7, f: 2}) - targetDonInfo := createDonInfo(t, don{id: 3, numNodes: 4, f: 1}) - - consumer, feedIDs, triggerSink := setupStreamDonsWithTransmissionSchedule(ctx, t, workflowDonInfo, triggerDonInfo, targetDonInfo, 3, - "2s", "oneAtATime") - - reports := []*datastreams.FeedReport{ - createFeedReport(t, big.NewInt(1), 5, feedIDs[0], triggerDonInfo.keyBundles), - createFeedReport(t, big.NewInt(3), 7, feedIDs[1], triggerDonInfo.keyBundles), - createFeedReport(t, big.NewInt(2), 6, feedIDs[2], triggerDonInfo.keyBundles), - } - - triggerSink.sendReports(reports) - - waitForConsumerReports(ctx, t, consumer, reports) -} - -func waitForConsumerReports(ctx context.Context, t *testing.T, consumer *feeds_consumer.KeystoneFeedsConsumer, triggerFeedReports []*datastreams.FeedReport) { - feedsReceived := make(chan *feeds_consumer.KeystoneFeedsConsumerFeedReceived, 1000) - feedsSub, err := consumer.WatchFeedReceived(&bind.WatchOpts{}, feedsReceived, nil) - require.NoError(t, err) - - feedToReport := map[string]*datastreams.FeedReport{} - for _, report := range triggerFeedReports { - feedToReport[report.FeedID] = report - } - - ctxWithTimeout, cancel := context.WithTimeout(ctx, 5*time.Minute) - defer cancel() - feedCount := 0 - for { - select { - case <-ctxWithTimeout.Done(): - t.Fatalf("timed out waiting for feed reports, expected %d, received %d", len(triggerFeedReports), feedCount) - case err := <-feedsSub.Err(): - require.NoError(t, err) - case feed := <-feedsReceived: - feedID := "0x" + hex.EncodeToString(feed.FeedId[:]) - report := feedToReport[feedID] - decodedReport, err := reporttypes.Decode(report.FullReport) - require.NoError(t, err) - assert.Equal(t, decodedReport.BenchmarkPrice, feed.Price) - assert.Equal(t, decodedReport.ObservationsTimestamp, feed.Timestamp) - - feedCount++ - if feedCount == len(triggerFeedReports) { - return - } - } - } -} diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index fbf4d918a56..1d309816c1c 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -4,20 +4,20 @@ import ( "context" "errors" "fmt" + "slices" "strings" "time" "google.golang.org/protobuf/proto" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/libocr/ragep2p" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" + "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/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -130,6 +130,12 @@ func (w *launcher) Name() string { func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegistry) error { w.registry.SetLocalRegistry(state) + allDONIDs := []registrysyncer.DonID{} + for id := range state.IDsToDONs { + allDONIDs = append(allDONIDs, id) + } + slices.Sort(allDONIDs) // ensure deterministic order + // Let's start by updating the list of Peers // We do this by creating a new entry for each node belonging // to a public DON. @@ -137,7 +143,8 @@ func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegist allPeers := make(map[ragetypes.PeerID]p2ptypes.StreamConfig) publicDONs := []registrysyncer.DON{} - for _, d := range state.IDsToDONs { + for _, id := range allDONIDs { + d := state.IDsToDONs[id] if !d.DON.IsPublic { continue } @@ -167,7 +174,8 @@ func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegist myWorkflowDONs := []registrysyncer.DON{} remoteWorkflowDONs := []registrysyncer.DON{} myDONs := map[uint32]bool{} - for _, d := range state.IDsToDONs { + for _, id := range allDONIDs { + d := state.IDsToDONs[id] for _, peerID := range d.Members { if peerID == myID { myDONs[d.ID] = true @@ -244,24 +252,25 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON registrysync switch capability.CapabilityType { case capabilities.CapabilityTypeTrigger: newTriggerFn := func(info capabilities.CapabilityInfo) (capabilityService, error) { - if !strings.HasPrefix(info.ID, "streams-trigger") { - return nil, errors.New("not supported: trigger capability does not have id = streams-trigger") + var aggregator remotetypes.Aggregator + if strings.HasPrefix(info.ID, "streams-trigger") { + codec := streams.NewCodec(w.lggr) + + signers, err := signersFor(remoteDON, state) + if err != nil { + return nil, err + } + + aggregator = triggers.NewMercuryRemoteAggregator( + codec, + signers, + int(remoteDON.F+1), + w.lggr, + ) + } else { + aggregator = remote.NewDefaultModeAggregator(uint32(remoteDON.F) + 1) } - codec := streams.NewCodec(w.lggr) - - signers, err := signersFor(remoteDON, state) - if err != nil { - return nil, err - } - - aggregator := triggers.NewMercuryRemoteAggregator( - codec, - signers, - int(remoteDON.F+1), - w.lggr, - ) - // TODO: We need to implement a custom, Mercury-specific // aggregator here, because there is no guarantee that // all trigger events in the workflow will have the same @@ -385,7 +394,7 @@ func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.Pee switch capability.CapabilityType { case capabilities.CapabilityTypeTrigger: - newTriggerPublisher := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error) { + newTriggerPublisher := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (remotetypes.ReceiverService, error) { publisher := remote.NewTriggerPublisher( capabilityConfig.RemoteTriggerConfig, capability.(capabilities.TriggerCapability), @@ -407,7 +416,7 @@ func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.Pee case capabilities.CapabilityTypeConsensus: w.lggr.Warn("no remote client configured for capability type consensus, skipping configuration") case capabilities.CapabilityTypeTarget: - newTargetServer := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error) { + newTargetServer := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (remotetypes.ReceiverService, error) { return target.NewServer( capabilityConfig.RemoteTargetConfig, myPeerID, @@ -432,12 +441,7 @@ func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.Pee return nil } -type receiverService interface { - services.Service - remotetypes.Receiver -} - -func (w *launcher) addReceiver(ctx context.Context, capability registrysyncer.Capability, don registrysyncer.DON, newReceiverFn func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error)) error { +func (w *launcher) addReceiver(ctx context.Context, capability registrysyncer.Capability, don registrysyncer.DON, newReceiverFn func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (remotetypes.ReceiverService, error)) error { capID := capability.ID info, err := capabilities.NewRemoteCapabilityInfo( capID, diff --git a/core/capabilities/launcher_test.go b/core/capabilities/launcher_test.go index 8bca3be0db1..11482b0dd30 100644 --- a/core/capabilities/launcher_test.go +++ b/core/capabilities/launcher_test.go @@ -15,12 +15,16 @@ import ( ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "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" remoteMocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "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" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" @@ -30,11 +34,11 @@ type mockTrigger struct { capabilities.CapabilityInfo } -func (m *mockTrigger) RegisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { +func (m *mockTrigger) RegisterTrigger(ctx context.Context, request capabilities.TriggerRegistrationRequest) (<-chan capabilities.TriggerResponse, error) { return nil, nil } -func (m *mockTrigger) UnregisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) error { +func (m *mockTrigger) UnregisterTrigger(ctx context.Context, request capabilities.TriggerRegistrationRequest) error { return nil } @@ -46,8 +50,8 @@ type mockCapability struct { capabilities.CapabilityInfo } -func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - return nil, nil +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + return capabilities.CapabilityResponse{}, nil } func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { @@ -141,29 +145,33 @@ func TestLauncher_WiresUpExternalCapabilities(t *testing.T) { CapabilityType: capabilities.CapabilityTypeTarget, }, }, - IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + IDsToNodes: map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ nodes[0]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, nodes[1]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, nodes[2]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, nodes[3]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[3], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, }, @@ -184,6 +192,242 @@ func TestLauncher_WiresUpExternalCapabilities(t *testing.T) { defer launcher.Close() } +func newTriggerEventMsg(t *testing.T, + senderPeerID types.PeerID, + workflowID string, + triggerEvent map[string]any, + triggerEventID string) (*remotetypes.MessageBody, *values.Map) { + triggerEventValue, err := values.NewMap(triggerEvent) + require.NoError(t, err) + capResponse := capabilities.TriggerResponse{ + Event: capabilities.TriggerEvent{ + Outputs: triggerEventValue, + ID: triggerEventID, + }, + Err: nil, + } + marshaled, err := pb.MarshalTriggerResponse(capResponse) + require.NoError(t, err) + return &remotetypes.MessageBody{ + Sender: senderPeerID[:], + Method: remotetypes.MethodTriggerEvent, + Metadata: &remotetypes.MessageBody_TriggerEventMetadata{ + TriggerEventMetadata: &remotetypes.TriggerEventMetadata{ + WorkflowIds: []string{workflowID}, + }, + }, + Payload: marshaled, + }, triggerEventValue +} + +func TestLauncher_RemoteTriggerModeAggregatorShim(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + registry := NewRegistry(lggr) + dispatcher := remoteMocks.NewDispatcher(t) + + var pid ragetypes.PeerID + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) + require.NoError(t, err) + peer := mocks.NewPeer(t) + peer.On("UpdateConnections", mock.Anything).Return(nil) + peer.On("ID").Return(pid) + wrapper := mocks.NewPeerWrapper(t) + wrapper.On("GetPeer").Return(peer) + + workflowDonNodes := []ragetypes.PeerID{ + pid, + randomWord(), + randomWord(), + randomWord(), + } + + capabilityDonNodes := []ragetypes.PeerID{ + randomWord(), + randomWord(), + randomWord(), + randomWord(), + } + + fullTriggerCapID := "log-event-trigger-evm-43113@1.0.0" + fullTargetID := "write-chain_evm_1@1.0.0" + triggerCapID := randomWord() + targetCapID := randomWord() + dID := uint32(1) + capDonID := uint32(2) + // The below state describes a Workflow DON (AcceptsWorkflows = true), + // which exposes the log-event-trigger and write_chain capabilities. + // We expect receivers to be wired up and both capabilities to be added to the registry. + rtc := &capabilities.RemoteTriggerConfig{} + rtc.ApplyDefaults() + + cfg, err := proto.Marshal(&capabilitiespb.CapabilityConfig{ + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(1 * time.Second), + MinResponsesToAggregate: 3, + }, + }, + }) + require.NoError(t, err) + + state := ®istrysyncer.LocalRegistry{ + IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ + registrysyncer.DonID(dID): { + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + Members: workflowDonNodes, + }, + }, + registrysyncer.DonID(capDonID): { + DON: capabilities.DON{ + ID: capDonID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: false, + Members: capabilityDonNodes, + }, + CapabilityConfigurations: map[string]registrysyncer.CapabilityConfiguration{ + fullTriggerCapID: { + Config: cfg, + }, + fullTargetID: { + Config: cfg, + }, + }, + }, + }, + IDsToCapabilities: map[string]registrysyncer.Capability{ + fullTriggerCapID: { + ID: fullTriggerCapID, + CapabilityType: capabilities.CapabilityTypeTrigger, + }, + fullTargetID: { + ID: fullTargetID, + CapabilityType: capabilities.CapabilityTypeTarget, + }, + }, + IDsToNodes: map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ + capabilityDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[0], + EncryptionPublicKey: randomWord(), + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[1], + EncryptionPublicKey: randomWord(), + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[2], + EncryptionPublicKey: randomWord(), + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[3], + EncryptionPublicKey: randomWord(), + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + workflowDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + EncryptionPublicKey: randomWord(), + }, + workflowDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + EncryptionPublicKey: randomWord(), + }, + workflowDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + EncryptionPublicKey: randomWord(), + }, + workflowDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + EncryptionPublicKey: randomWord(), + }, + }, + } + + launcher := NewLauncher( + lggr, + wrapper, + dispatcher, + registry, + ) + + dispatcher.On("SetReceiver", fullTriggerCapID, capDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) + dispatcher.On("SetReceiver", fullTargetID, capDonID, mock.AnythingOfType("*target.client")).Return(nil) + awaitRegistrationMessageCh := make(chan struct{}) + dispatcher.On("Send", mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { + select { + case awaitRegistrationMessageCh <- struct{}{}: + default: + } + }) + + err = launcher.Launch(ctx, state) + require.NoError(t, err) + defer launcher.Close() + + baseCapability, err := registry.Get(ctx, fullTriggerCapID) + require.NoError(t, err) + + remoteTriggerSubscriber, ok := baseCapability.(remote.TriggerSubscriber) + require.True(t, ok, "remote trigger capability") + + // Register trigger + workflowID1 := "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0" + workflowExecutionID1 := "95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0abbadeed" + req := capabilities.TriggerRegistrationRequest{ + TriggerID: "logeventtrigger_log1", + Metadata: capabilities.RequestMetadata{ + ReferenceID: "logeventtrigger", + WorkflowID: workflowID1, + WorkflowExecutionID: workflowExecutionID1, + }, + } + triggerEventCallbackCh, err := remoteTriggerSubscriber.RegisterTrigger(ctx, req) + require.NoError(t, err) + <-awaitRegistrationMessageCh + + // Receive trigger event + triggerEvent1 := map[string]any{"event": "triggerEvent1"} + triggerEvent2 := map[string]any{"event": "triggerEvent2"} + triggerEventMsg1, triggerEventValue := newTriggerEventMsg(t, capabilityDonNodes[0], workflowID1, triggerEvent1, "TriggerEventID1") + triggerEventMsg2, _ := newTriggerEventMsg(t, capabilityDonNodes[1], workflowID1, triggerEvent1, "TriggerEventID1") + // One Faulty Node (F = 1) sending bad event data for the same TriggerEventID1 + triggerEventMsg3, _ := newTriggerEventMsg(t, capabilityDonNodes[2], workflowID1, triggerEvent2, "TriggerEventID1") + remoteTriggerSubscriber.Receive(ctx, triggerEventMsg1) + remoteTriggerSubscriber.Receive(ctx, triggerEventMsg2) + remoteTriggerSubscriber.Receive(ctx, triggerEventMsg3) + + // After MinResponsesToAggregate, we should get a response + response := <-triggerEventCallbackCh + + // Checks if response is same as minIdenticalResponses = F + 1, F = 1 + require.Equal(t, response.Event.Outputs, triggerEventValue) +} + func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { ctx := tests.Context(t) lggr := logger.TestLogger(t) @@ -243,29 +487,33 @@ func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { CapabilityType: capabilities.CapabilityTypeTarget, }, }, - IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + IDsToNodes: map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ nodes[0]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, nodes[1]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, nodes[2]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, nodes[3]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[3], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, }, @@ -380,50 +628,58 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDON(t *testing.T) { CapabilityType: capabilities.CapabilityTypeTarget, }, }, - IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + IDsToNodes: map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ capabilityDonNodes[0]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, capabilityDonNodes[1]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, capabilityDonNodes[2]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, capabilityDonNodes[3]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[3], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, workflowDonNodes[0]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[0], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[1]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[1], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[2]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[2], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[3]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[3], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + EncryptionPublicKey: randomWord(), }, }, } @@ -537,50 +793,58 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie CapabilityType: capabilities.CapabilityTypeTarget, }, }, - IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + IDsToNodes: map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ capabilityDonNodes[0]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, capabilityDonNodes[1]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, capabilityDonNodes[2]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, capabilityDonNodes[3]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[3], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, }, workflowDonNodes[0]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[0], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[1]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[1], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[2]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[2], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[3]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[3], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + EncryptionPublicKey: randomWord(), }, }, } @@ -677,50 +941,58 @@ func TestLauncher_SucceedsEvenIfDispatcherAlreadyHasReceiver(t *testing.T) { CapabilityType: capabilities.CapabilityTypeTrigger, }, }, - IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + IDsToNodes: map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ capabilityDonNodes[0]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID}, }, capabilityDonNodes[1]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID}, }, capabilityDonNodes[2]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID}, }, capabilityDonNodes[3]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: capabilityDonNodes[3], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{triggerCapID}, }, workflowDonNodes[0]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[0], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[1]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[1], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[2]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[2], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[3]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[3], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + EncryptionPublicKey: randomWord(), }, }, } diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 4da51a27b6b..47285505805 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" ) @@ -199,3 +200,30 @@ func NewRegistry(lggr logger.Logger) *Registry { lggr: lggr.Named("CapabilitiesRegistry"), } } + +// TestMetadataRegistry is a test implementation of the metadataRegistry +// interface. It is used when ExternalCapabilitiesRegistry is not available. +type TestMetadataRegistry struct{} + +func (t *TestMetadataRegistry) LocalNode(ctx context.Context) (capabilities.Node, error) { + peerID := p2ptypes.PeerID{} + workflowDON := capabilities.DON{ + ID: 1, + ConfigVersion: 1, + Members: []p2ptypes.PeerID{ + peerID, + }, + F: 0, + IsPublic: false, + AcceptsWorkflows: true, + } + return capabilities.Node{ + PeerID: &peerID, + WorkflowDON: workflowDON, + CapabilityDONs: []capabilities.DON{}, + }, nil +} + +func (t *TestMetadataRegistry) ConfigForCapability(ctx context.Context, capabilityID string, donID uint32) (registrysyncer.CapabilityConfiguration, error) { + return registrysyncer.CapabilityConfiguration{}, nil +} diff --git a/core/capabilities/registry_test.go b/core/capabilities/registry_test.go index 77e5d9edcd6..89f366da04a 100644 --- a/core/capabilities/registry_test.go +++ b/core/capabilities/registry_test.go @@ -21,8 +21,8 @@ type mockCapability struct { capabilities.CapabilityInfo } -func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - return nil, nil +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + return capabilities.CapabilityResponse{}, nil } func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { diff --git a/core/capabilities/remote/dispatcher.go b/core/capabilities/remote/dispatcher.go index dab4f6c98bf..f27d691bb66 100644 --- a/core/capabilities/remote/dispatcher.go +++ b/core/capabilities/remote/dispatcher.go @@ -2,11 +2,11 @@ package remote import ( "context" - "errors" "fmt" - sync "sync" + "sync" "time" + "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "google.golang.org/protobuf/proto" @@ -15,8 +15,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" - remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -26,11 +27,13 @@ var ( // dispatcher en/decodes messages and routes traffic between peers and capabilities type dispatcher struct { + cfg config.Dispatcher peerWrapper p2ptypes.PeerWrapper peer p2ptypes.Peer peerID p2ptypes.PeerID signer p2ptypes.Signer registry core.CapabilitiesRegistry + rateLimiter *common.RateLimiter receivers map[key]*receiver mu sync.RWMutex stopCh services.StopChan @@ -45,17 +48,26 @@ type key struct { var _ services.Service = &dispatcher{} -const supportedVersion = 1 - -func NewDispatcher(peerWrapper p2ptypes.PeerWrapper, signer p2ptypes.Signer, registry core.CapabilitiesRegistry, lggr logger.Logger) *dispatcher { +func NewDispatcher(cfg config.Dispatcher, peerWrapper p2ptypes.PeerWrapper, signer p2ptypes.Signer, registry core.CapabilitiesRegistry, lggr logger.Logger) (*dispatcher, error) { + rl, err := common.NewRateLimiter(common.RateLimiterConfig{ + GlobalRPS: cfg.RateLimit().GlobalRPS(), + GlobalBurst: cfg.RateLimit().GlobalBurst(), + PerSenderRPS: cfg.RateLimit().PerSenderRPS(), + PerSenderBurst: cfg.RateLimit().PerSenderBurst(), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to create rate limiter") + } return &dispatcher{ + cfg: cfg, peerWrapper: peerWrapper, signer: signer, registry: registry, + rateLimiter: rl, receivers: make(map[key]*receiver), stopCh: make(services.StopChan), lggr: lggr.Named("Dispatcher"), - } + }, nil } func (d *dispatcher) Start(ctx context.Context) error { @@ -86,14 +98,12 @@ var capReceiveChannelUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ Help: "The usage of the receive channel for each capability, 0 indicates empty, 1 indicates full.", }, []string{"capabilityId", "donId"}) -const receiverBufferSize = 10000 - type receiver struct { cancel context.CancelFunc - ch chan *remotetypes.MessageBody + ch chan *types.MessageBody } -func (d *dispatcher) SetReceiver(capabilityId string, donId uint32, rec remotetypes.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} @@ -102,7 +112,7 @@ func (d *dispatcher) SetReceiver(capabilityId string, donId uint32, rec remotety return fmt.Errorf("%w: receiver already exists for capability %s and don %d", ErrReceiverExists, capabilityId, donId) } - receiverCh := make(chan *remotetypes.MessageBody, receiverBufferSize) + receiverCh := make(chan *types.MessageBody, d.cfg.ReceiverBufferSize()) ctx, cancelCtx := d.stopCh.NewCtx() d.wg.Add(1) @@ -140,8 +150,8 @@ func (d *dispatcher) RemoveReceiver(capabilityId string, donId uint32) { } } -func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBody) error { - msgBody.Version = supportedVersion +func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { + msgBody.Version = uint32(d.cfg.SupportedVersion()) msgBody.Sender = d.peerID[:] msgBody.Receiver = peerID[:] msgBody.Timestamp = time.Now().UnixMilli() @@ -153,7 +163,7 @@ func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBo if err != nil { return err } - msg := &remotetypes.Message{Signature: signature, Body: rawBody} + msg := &types.Message{Signature: signature, Body: rawBody} rawMsg, err := proto.Marshal(msg) if err != nil { return err @@ -169,6 +179,10 @@ func (d *dispatcher) receive() { d.lggr.Info("stopped - exiting receive") return case msg := <-recvCh: + if !d.rateLimiter.Allow(msg.Sender.String()) { + d.lggr.Debugw("rate limit exceeded, dropping message", "sender", msg.Sender) + continue + } body, err := ValidateMessage(msg, d.peerID) if err != nil { d.lggr.Debugw("received invalid message", "error", err) @@ -185,7 +199,7 @@ func (d *dispatcher) receive() { continue } - receiverQueueUsage := float64(len(receiver.ch)) / receiverBufferSize + receiverQueueUsage := float64(len(receiver.ch)) / float64(d.cfg.ReceiverBufferSize()) capReceiveChannelUsage.WithLabelValues(k.capId, fmt.Sprint(k.donId)).Set(receiverQueueUsage) select { case receiver.ch <- body: @@ -196,7 +210,7 @@ func (d *dispatcher) receive() { } } -func (d *dispatcher) tryRespondWithError(peerID p2ptypes.PeerID, body *remotetypes.MessageBody, errType types.Error) { +func (d *dispatcher) tryRespondWithError(peerID p2ptypes.PeerID, body *types.MessageBody, errType types.Error) { if body == nil { return } diff --git a/core/capabilities/remote/dispatcher_test.go b/core/capabilities/remote/dispatcher_test.go index 7ea4c2e2626..50edc5f3530 100644 --- a/core/capabilities/remote/dispatcher_test.go +++ b/core/capabilities/remote/dispatcher_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -32,6 +33,47 @@ func (r *testReceiver) Receive(_ context.Context, msg *remotetypes.MessageBody) r.ch <- msg } +type testRateLimitConfig struct { + globalRPS float64 + globalBurst int + rps float64 + burst int +} + +func (c testRateLimitConfig) GlobalRPS() float64 { + return c.globalRPS +} + +func (c testRateLimitConfig) GlobalBurst() int { + return c.globalBurst +} + +func (c testRateLimitConfig) PerSenderRPS() float64 { + return c.rps +} + +func (c testRateLimitConfig) PerSenderBurst() int { + return c.burst +} + +type testConfig struct { + supportedVersion int + receiverBufferSize int + rateLimit testRateLimitConfig +} + +func (c testConfig) SupportedVersion() int { + return c.supportedVersion +} + +func (c testConfig) ReceiverBufferSize() int { + return c.receiverBufferSize +} + +func (c testConfig) RateLimit() config.DispatcherRateLimit { + return c.rateLimit +} + func TestDispatcher_CleanStartClose(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) @@ -44,7 +86,17 @@ func TestDispatcher_CleanStartClose(t *testing.T) { signer := mocks.NewSigner(t) registry := commonMocks.NewCapabilitiesRegistry(t) - dispatcher := remote.NewDispatcher(wrapper, signer, registry, lggr) + dispatcher, err := remote.NewDispatcher(testConfig{ + supportedVersion: 1, + receiverBufferSize: 10000, + rateLimit: testRateLimitConfig{ + globalRPS: 800.0, + globalBurst: 100, + rps: 10.0, + burst: 50, + }, + }, wrapper, signer, registry, lggr) + require.NoError(t, err) require.NoError(t, dispatcher.Start(ctx)) require.NoError(t, dispatcher.Close()) } @@ -65,11 +117,21 @@ func TestDispatcher_Receive(t *testing.T) { signer.On("Sign", mock.Anything).Return(nil, errors.New("not implemented")) registry := commonMocks.NewCapabilitiesRegistry(t) - dispatcher := remote.NewDispatcher(wrapper, signer, registry, lggr) + dispatcher, err := remote.NewDispatcher(testConfig{ + supportedVersion: 1, + receiverBufferSize: 10000, + rateLimit: testRateLimitConfig{ + globalRPS: 800.0, + globalBurst: 100, + rps: 10.0, + burst: 50, + }, + }, wrapper, signer, registry, lggr) + require.NoError(t, err) 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 @@ -113,7 +175,17 @@ func TestDispatcher_RespondWithError(t *testing.T) { signer.On("Sign", mock.Anything).Return([]byte{}, nil) registry := commonMocks.NewCapabilitiesRegistry(t) - dispatcher := remote.NewDispatcher(wrapper, signer, registry, lggr) + dispatcher, err := remote.NewDispatcher(testConfig{ + supportedVersion: 1, + receiverBufferSize: 10000, + rateLimit: testRateLimitConfig{ + globalRPS: 800.0, + globalBurst: 100, + rps: 10.0, + burst: 50, + }, + }, wrapper, signer, registry, lggr) + require.NoError(t, err) require.NoError(t, dispatcher.Start(ctx)) // unknown capability diff --git a/core/capabilities/remote/target/client.go b/core/capabilities/remote/target/client.go index 4273169d23e..64dcbd14f01 100644 --- a/core/capabilities/remote/target/client.go +++ b/core/capabilities/remote/target/client.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target/request" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -122,7 +123,17 @@ func (c *client) UnregisterFromWorkflow(ctx context.Context, request commoncap.U return nil } -func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { +func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest) (commoncap.CapabilityResponse, error) { + req, err := c.executeRequest(ctx, capReq) + if err != nil { + return commoncap.CapabilityResponse{}, fmt.Errorf("failed to execute request: %w", err) + } + + resp := <-req.ResponseChan() + return resp.CapabilityResponse, resp.Err +} + +func (c *client) executeRequest(ctx context.Context, capReq commoncap.CapabilityRequest) (*request.ClientRequest, error) { c.mutex.Lock() defer c.mutex.Unlock() @@ -144,8 +155,7 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest } c.messageIDToCallerRequest[messageID] = req - - return req.ResponseChan(), nil + return req, nil } func (c *client) Receive(ctx context.Context, msg *types.MessageBody) { @@ -172,8 +182,12 @@ func (c *client) Receive(ctx context.Context, msg *types.MessageBody) { } func GetMessageIDForRequest(req commoncap.CapabilityRequest) (string, error) { - if !remote.IsValidWorkflowOrExecutionID(req.Metadata.WorkflowID) || !remote.IsValidWorkflowOrExecutionID(req.Metadata.WorkflowExecutionID) { - return "", errors.New("workflow ID and workflow execution ID in request metadata are invalid") + if err := validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowID); err != nil { + return "", fmt.Errorf("workflow ID is invalid: %w", err) + } + + if err := validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowExecutionID); err != nil { + return "", fmt.Errorf("workflow execution ID is invalid: %w", err) } return req.Metadata.WorkflowID + req.Metadata.WorkflowExecutionID, nil diff --git a/core/capabilities/remote/target/client_test.go b/core/capabilities/remote/target/client_test.go index 2198636a7a2..697cb6e383a 100644 --- a/core/capabilities/remote/target/client_test.go +++ b/core/capabilities/remote/target/client_test.go @@ -35,9 +35,8 @@ func Test_Client_DonTopologies(t *testing.T) { }) require.NoError(t, err) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) - response := <-responseCh mp, err := response.Value.Unwrap() require.NoError(t, err) assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) @@ -66,9 +65,8 @@ func Test_Client_DonTopologies(t *testing.T) { func Test_Client_TransmissionSchedules(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) - response := <-responseCh mp, err := response.Value.Unwrap() require.NoError(t, err) assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) @@ -104,10 +102,8 @@ func Test_Client_TransmissionSchedules(t *testing.T) { func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { - require.NoError(t, responseError) - response := <-responseCh - assert.NotNil(t, response.Err) + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { + assert.NotNil(t, responseError) } capability := &TestCapability{} @@ -126,7 +122,7 @@ func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflowNodeResponseTimeout time.Duration, numCapabilityPeers int, capabilityDonF uint8, underlying commoncap.TargetCapability, transmissionSchedule *values.Map, - responseTest func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error)) { + responseTest func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error)) { lggr := logger.TestLogger(t) capabilityPeers := make([]p2ptypes.PeerID, numCapabilityPeers) @@ -261,8 +257,7 @@ func (t *clientTestServer) Receive(_ context.Context, msg *remotetypes.MessageBo panic(err) } - respCh, responseErr := t.targetCapability.Execute(context.Background(), capabilityRequest) - resp := <-respCh + resp, responseErr := t.targetCapability.Execute(context.Background(), capabilityRequest) for receiver := range t.messageIDToSenders[messageID] { var responseMsg = &remotetypes.MessageBody{ diff --git a/core/capabilities/remote/target/endtoend_test.go b/core/capabilities/remote/target/endtoend_test.go index 31bdc83e266..3b077bbafe0 100644 --- a/core/capabilities/remote/target/endtoend_test.go +++ b/core/capabilities/remote/target/endtoend_test.go @@ -29,10 +29,8 @@ import ( func Test_RemoteTargetCapability_InsufficientCapabilityResponses(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { - require.NoError(t, responseError) - response := <-responseCh - assert.NotNil(t, response.Err) + responseTest := func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { + assert.NotNil(t, responseError) } capability := &TestCapability{} @@ -49,10 +47,8 @@ func Test_RemoteTargetCapability_InsufficientCapabilityResponses(t *testing.T) { func Test_RemoteTargetCapability_InsufficientWorkflowRequests(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { - require.NoError(t, responseError) - response := <-responseCh - assert.NotNil(t, response.Err) + responseTest := func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { + assert.NotNil(t, responseError) } timeOut := 10 * time.Minute @@ -71,9 +67,8 @@ func Test_RemoteTargetCapability_InsufficientWorkflowRequests(t *testing.T) { func Test_RemoteTargetCapability_TransmissionSchedules(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) - response := <-responseCh mp, err := response.Value.Unwrap() require.NoError(t, err) assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) @@ -103,9 +98,8 @@ func Test_RemoteTargetCapability_TransmissionSchedules(t *testing.T) { func Test_RemoteTargetCapability_DonTopologies(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) - response := <-responseCh mp, err := response.Value.Unwrap() require.NoError(t, err) assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) @@ -138,10 +132,8 @@ func Test_RemoteTargetCapability_DonTopologies(t *testing.T) { func Test_RemoteTargetCapability_CapabilityError(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { - require.NoError(t, responseError) - response := <-responseCh - assert.Equal(t, "failed to execute capability: an error", response.Err.Error()) + responseTest := func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { + assert.Equal(t, "failed to execute capability: an error", responseError.Error()) } capability := &TestErrorCapability{} @@ -158,10 +150,8 @@ func Test_RemoteTargetCapability_CapabilityError(t *testing.T) { func Test_RemoteTargetCapability_RandomCapabilityError(t *testing.T) { ctx := testutils.Context(t) - responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { - require.NoError(t, responseError) - response := <-responseCh - assert.Equal(t, "request expired", response.Err.Error()) + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { + assert.Equal(t, "request expired", responseError.Error()) } capability := &TestRandomErrorCapability{} @@ -177,7 +167,7 @@ func Test_RemoteTargetCapability_RandomCapabilityError(t *testing.T) { func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.TargetCapability, numWorkflowPeers int, workflowDonF uint8, workflowNodeTimeout time.Duration, numCapabilityPeers int, capabilityDonF uint8, capabilityNodeResponseTimeout time.Duration, transmissionSchedule *values.Map, - responseTest func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error)) { + responseTest func(t *testing.T, response commoncap.CapabilityResponse, responseError error)) { lggr := logger.TestLogger(t) capabilityPeers := make([]p2ptypes.PeerID, numCapabilityPeers) @@ -258,7 +248,7 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta for _, caller := range workflowNodes { go func(caller commoncap.TargetCapability) { defer wg.Done() - responseCh, err := caller.Execute(ctx, + response, err := caller.Execute(ctx, commoncap.CapabilityRequest{ Metadata: commoncap.RequestMetadata{ WorkflowID: workflowID1, @@ -268,7 +258,7 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta Inputs: executeInputs, }) - responseTest(t, responseCh, err) + responseTest(t, response, err) }(caller) } @@ -276,67 +266,47 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta } type testAsyncMessageBroker struct { - services.StateMachine - t *testing.T + services.Service + eng *services.Engine + t *testing.T nodes map[p2ptypes.PeerID]remotetypes.Receiver sendCh chan *remotetypes.MessageBody - - stopCh services.StopChan - wg sync.WaitGroup -} - -func (a *testAsyncMessageBroker) HealthReport() map[string]error { - return nil -} - -func (a *testAsyncMessageBroker) Name() string { - return "testAsyncMessageBroker" } func newTestAsyncMessageBroker(t *testing.T, sendChBufferSize int) *testAsyncMessageBroker { - return &testAsyncMessageBroker{ + b := &testAsyncMessageBroker{ t: t, nodes: make(map[p2ptypes.PeerID]remotetypes.Receiver), - stopCh: make(services.StopChan), sendCh: make(chan *remotetypes.MessageBody, sendChBufferSize), } -} - -func (a *testAsyncMessageBroker) Start(ctx context.Context) error { - return a.StartOnce("testAsyncMessageBroker", func() error { - a.wg.Add(1) - go func() { - defer a.wg.Done() - - for { - select { - case <-a.stopCh: - return - case msg := <-a.sendCh: - receiverId := toPeerID(msg.Receiver) - - receiver, ok := a.nodes[receiverId] - if !ok { - panic("server not found for peer id") - } - - receiver.Receive(tests.Context(a.t), msg) + b.Service, b.eng = services.Config{ + Name: "testAsyncMessageBroker", + Start: b.start, + }.NewServiceEngine(logger.TestLogger(t)) + return b +} + +func (a *testAsyncMessageBroker) start(ctx context.Context) error { + a.eng.Go(func(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + case msg := <-a.sendCh: + receiverId := toPeerID(msg.Receiver) + + receiver, ok := a.nodes[receiverId] + if !ok { + panic("server not found for peer id") } - } - }() - return nil - }) -} - -func (a *testAsyncMessageBroker) Close() error { - return a.StopOnce("testAsyncMessageBroker", func() error { - close(a.stopCh) - a.wg.Wait() - return nil + receiver.Receive(tests.Context(a.t), msg) + } + } }) + return nil } func (a *testAsyncMessageBroker) NewDispatcherForNode(nodePeerID p2ptypes.PeerID) remotetypes.Dispatcher { @@ -424,36 +394,31 @@ type TestCapability struct { abstractTestCapability } -func (t TestCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - ch := make(chan commoncap.CapabilityResponse, 1) - +func (t TestCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (commoncap.CapabilityResponse, error) { value := request.Inputs.Underlying["executeValue1"] - response, err := values.NewMap(map[string]any{"response": value}) if err != nil { - return nil, err + return commoncap.CapabilityResponse{}, err } - ch <- commoncap.CapabilityResponse{ + return commoncap.CapabilityResponse{ Value: response, - } - - return ch, nil + }, nil } type TestErrorCapability struct { abstractTestCapability } -func (t TestErrorCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - return nil, errors.New("an error") +func (t TestErrorCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (commoncap.CapabilityResponse, error) { + return commoncap.CapabilityResponse{}, errors.New("an error") } type TestRandomErrorCapability struct { abstractTestCapability } -func (t TestRandomErrorCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - return nil, errors.New(uuid.New().String()) +func (t TestRandomErrorCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (commoncap.CapabilityResponse, error) { + return commoncap.CapabilityResponse{}, errors.New(uuid.New().String()) } func NewP2PPeerID(t *testing.T) p2ptypes.PeerID { diff --git a/core/capabilities/remote/target/request/client_request.go b/core/capabilities/remote/target/request/client_request.go index 0370fd229cf..1a0d707146b 100644 --- a/core/capabilities/remote/target/request/client_request.go +++ b/core/capabilities/remote/target/request/client_request.go @@ -22,9 +22,14 @@ import ( p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) +type asyncCapabilityResponse struct { + capabilities.CapabilityResponse + Err error +} + type ClientRequest struct { cancelFn context.CancelFunc - responseCh chan commoncap.CapabilityResponse + responseCh chan asyncCapabilityResponse createdAt time.Time responseIDCount map[[32]byte]int errorCount map[string]int @@ -101,13 +106,13 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap responseIDCount: make(map[[32]byte]int), errorCount: make(map[string]int), responseReceived: responseReceived, - responseCh: make(chan commoncap.CapabilityResponse, 1), + responseCh: make(chan asyncCapabilityResponse, 1), wg: wg, lggr: lggr, }, nil } -func (c *ClientRequest) ResponseChan() <-chan commoncap.CapabilityResponse { +func (c *ClientRequest) ResponseChan() <-chan asyncCapabilityResponse { return c.responseCh } @@ -121,11 +126,10 @@ func (c *ClientRequest) Cancel(err error) { c.mux.Lock() defer c.mux.Unlock() if !c.respSent { - c.sendResponse(commoncap.CapabilityResponse{Err: err}) + c.sendResponse(asyncCapabilityResponse{Err: err}) } } -// TODO OnMessage assumes that only one response is received from each peer, if streaming responses need to be supported this will need to be updated func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) error { c.mux.Lock() defer c.mux.Unlock() @@ -140,7 +144,10 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err c.lggr.Debugw("OnMessage called for client request", "messageID", msg.MessageId) - sender := remote.ToPeerID(msg.Sender) + sender, err := remote.ToPeerID(msg.Sender) + if err != nil { + return fmt.Errorf("failed to convert message sender to PeerID: %w", err) + } received, expected := c.responseReceived[sender] if !expected { @@ -164,22 +171,22 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err if c.responseIDCount[responseID] == c.requiredIdenticalResponses { capabilityResponse, err := pb.UnmarshalCapabilityResponse(msg.Payload) if err != nil { - c.sendResponse(commoncap.CapabilityResponse{Err: fmt.Errorf("failed to unmarshal capability response: %w", err)}) + c.sendResponse(asyncCapabilityResponse{Err: fmt.Errorf("failed to unmarshal capability response: %w", err)}) } else { - c.sendResponse(commoncap.CapabilityResponse{Value: capabilityResponse.Value}) + c.sendResponse(asyncCapabilityResponse{CapabilityResponse: commoncap.CapabilityResponse{Value: capabilityResponse.Value}}) } } } else { c.lggr.Warnw("received error response", "error", remote.SanitizeLogString(msg.ErrorMsg)) c.errorCount[msg.ErrorMsg]++ if c.errorCount[msg.ErrorMsg] == c.requiredIdenticalResponses { - c.sendResponse(commoncap.CapabilityResponse{Err: errors.New(msg.ErrorMsg)}) + c.sendResponse(asyncCapabilityResponse{Err: errors.New(msg.ErrorMsg)}) } } return nil } -func (c *ClientRequest) sendResponse(response commoncap.CapabilityResponse) { +func (c *ClientRequest) sendResponse(response asyncCapabilityResponse) { c.responseCh <- response close(c.responseCh) c.respSent = true diff --git a/core/capabilities/remote/target/request/client_request_test.go b/core/capabilities/remote/target/request/client_request_test.go index 7edb2f5e534..095c73e8ad9 100644 --- a/core/capabilities/remote/target/request/client_request_test.go +++ b/core/capabilities/remote/target/request/client_request_test.go @@ -84,7 +84,6 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { require.NoError(t, err) capabilityResponse := commoncap.CapabilityResponse{ Value: m, - Err: nil, } rawResponse, err := pb.MarshalCapabilityResponse(capabilityResponse) @@ -117,7 +116,6 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { require.NoError(t, err) capabilityResponse2 := commoncap.CapabilityResponse{ Value: nm, - Err: nil, } rawResponse2, err := pb.MarshalCapabilityResponse(capabilityResponse2) diff --git a/core/capabilities/remote/target/request/server_request.go b/core/capabilities/remote/target/request/server_request.go index 16e90a034bc..d23ba93a44d 100644 --- a/core/capabilities/remote/target/request/server_request.go +++ b/core/capabilities/remote/target/request/server_request.go @@ -74,7 +74,11 @@ func (e *ServerRequest) OnMessage(ctx context.Context, msg *types.MessageBody) e return fmt.Errorf("sender missing from message") } - requester := remote.ToPeerID(msg.Sender) + requester, err := remote.ToPeerID(msg.Sender) + if err != nil { + return fmt.Errorf("failed to convert message sender to PeerID: %w", err) + } + if err := e.addRequester(requester); err != nil { return fmt.Errorf("failed to add requester to request: %w", err) } @@ -121,20 +125,19 @@ func (e *ServerRequest) executeRequest(ctx context.Context, payload []byte) erro } e.lggr.Debugw("executing capability", "metadata", capabilityRequest.Metadata) - capResponseCh, err := e.capability.Execute(ctxWithTimeout, capabilityRequest) + capResponse, err := e.capability.Execute(ctxWithTimeout, capabilityRequest) if err != nil { + e.lggr.Debugw("received execution error", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID, "error", err) return fmt.Errorf("failed to execute capability: %w", err) } - // NOTE working on the assumption that the capability will only ever return one response from its channel - capResponse := <-capResponseCh responsePayload, err := pb.MarshalCapabilityResponse(capResponse) if err != nil { return fmt.Errorf("failed to marshal capability response: %w", err) } - e.lggr.Debugw("received execution results", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID, "error", capResponse.Err) + e.lggr.Debugw("received execution results", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID) e.setResult(responsePayload) return nil } diff --git a/core/capabilities/remote/target/request/server_request_test.go b/core/capabilities/remote/target/request/server_request_test.go index a35725d6b19..619142d0a6f 100644 --- a/core/capabilities/remote/target/request/server_request_test.go +++ b/core/capabilities/remote/target/request/server_request_test.go @@ -240,28 +240,25 @@ type TestCapability struct { abstractTestCapability } -func (t TestCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - ch := make(chan commoncap.CapabilityResponse, 1) - +func (t TestCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (commoncap.CapabilityResponse, error) { value := request.Inputs.Underlying["executeValue1"] response, err := values.NewMap(map[string]any{"response": value}) if err != nil { - return nil, err - } - ch <- commoncap.CapabilityResponse{ - Value: response, + return commoncap.CapabilityResponse{}, err } - return ch, nil + return commoncap.CapabilityResponse{ + Value: response, + }, nil } type TestErrorCapability struct { abstractTestCapability } -func (t TestErrorCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - return nil, errors.New("an error") +func (t TestErrorCapability) Execute(ctx context.Context, request commoncap.CapabilityRequest) (commoncap.CapabilityResponse, error) { + return commoncap.CapabilityResponse{}, errors.New("an error") } func NewP2PPeerID(t *testing.T) p2ptypes.PeerID { diff --git a/core/capabilities/remote/target/server.go b/core/capabilities/remote/target/server.go index 56cad3739b6..5324475b192 100644 --- a/core/capabilities/remote/target/server.go +++ b/core/capabilities/remote/target/server.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target/request" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -210,7 +211,7 @@ func (r *server) getMessageHash(msg *types.MessageBody) ([32]byte, error) { func GetMessageID(msg *types.MessageBody) (string, error) { idStr := string(msg.MessageId) - if !remote.IsValidID(idStr) { + if !validation.IsValidID(idStr) { return "", fmt.Errorf("invalid message id") } return idStr, nil diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 23b778f6018..e5a46c87914 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -2,14 +2,16 @@ package remote import ( "context" - sync "sync" + "crypto/sha256" + "encoding/binary" + "sync" "time" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" 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/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -21,19 +23,22 @@ import ( // // TriggerPublisher communicates with corresponding TriggerSubscribers on remote nodes. type triggerPublisher struct { - config *capabilities.RemoteTriggerConfig - underlying commoncap.TriggerCapability - capInfo commoncap.CapabilityInfo - capDonInfo commoncap.DON - workflowDONs map[uint32]commoncap.DON - membersCache map[uint32]map[p2ptypes.PeerID]bool - dispatcher types.Dispatcher - messageCache *messageCache[registrationKey, p2ptypes.PeerID] - registrations map[registrationKey]*pubRegState - mu sync.RWMutex // protects messageCache and registrations - stopCh services.StopChan - wg sync.WaitGroup - lggr logger.Logger + config *commoncap.RemoteTriggerConfig + underlying commoncap.TriggerCapability + capInfo commoncap.CapabilityInfo + capDonInfo commoncap.DON + workflowDONs map[uint32]commoncap.DON + membersCache map[uint32]map[p2ptypes.PeerID]bool + dispatcher types.Dispatcher + messageCache *messageCache[registrationKey, p2ptypes.PeerID] + registrations map[registrationKey]*pubRegState + mu sync.RWMutex // protects messageCache and registrations + batchingQueue map[[32]byte]*batchedResponse + batchingEnabled bool + bqMu sync.Mutex // protects batchingQueue + stopCh services.StopChan + wg sync.WaitGroup + lggr logger.Logger } type registrationKey struct { @@ -42,17 +47,25 @@ type registrationKey struct { } type pubRegState struct { - callback <-chan commoncap.CapabilityResponse - request commoncap.CapabilityRequest + callback <-chan commoncap.TriggerResponse + request commoncap.TriggerRegistrationRequest } -var _ types.Receiver = &triggerPublisher{} -var _ services.Service = &triggerPublisher{} +type batchedResponse struct { + rawResponse []byte + callerDonID uint32 + triggerEventID string + workflowIDs []string +} + +var _ types.ReceiverService = &triggerPublisher{} + +const minAllowedBatchCollectionPeriod = 10 * time.Millisecond -func NewTriggerPublisher(config *capabilities.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[uint32]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { +func NewTriggerPublisher(config *commoncap.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[uint32]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { if config == nil { lggr.Info("no config provided, using default values") - config = &capabilities.RemoteTriggerConfig{} + config = &commoncap.RemoteTriggerConfig{} } config.ApplyDefaults() membersCache := make(map[uint32]map[p2ptypes.PeerID]bool) @@ -64,33 +77,44 @@ func NewTriggerPublisher(config *capabilities.RemoteTriggerConfig, underlying co membersCache[id] = cache } return &triggerPublisher{ - config: config, - underlying: underlying, - capInfo: capInfo, - capDonInfo: capDonInfo, - workflowDONs: workflowDONs, - membersCache: membersCache, - dispatcher: dispatcher, - messageCache: NewMessageCache[registrationKey, p2ptypes.PeerID](), - registrations: make(map[registrationKey]*pubRegState), - stopCh: make(services.StopChan), - lggr: lggr.Named("TriggerPublisher"), + config: config, + underlying: underlying, + capInfo: capInfo, + capDonInfo: capDonInfo, + workflowDONs: workflowDONs, + membersCache: membersCache, + dispatcher: dispatcher, + messageCache: NewMessageCache[registrationKey, p2ptypes.PeerID](), + registrations: make(map[registrationKey]*pubRegState), + batchingQueue: make(map[[32]byte]*batchedResponse), + batchingEnabled: config.MaxBatchSize > 1 && config.BatchCollectionPeriod >= minAllowedBatchCollectionPeriod, + stopCh: make(services.StopChan), + lggr: lggr.Named("TriggerPublisher"), } } func (p *triggerPublisher) Start(ctx context.Context) error { p.wg.Add(1) go p.registrationCleanupLoop() + if p.batchingEnabled { + p.wg.Add(1) + go p.batchingLoop() + } p.lggr.Info("TriggerPublisher started") return nil } func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { - sender := ToPeerID(msg.Sender) + sender, err := ToPeerID(msg.Sender) + if err != nil { + p.lggr.Errorw("failed to convert message sender to PeerID", "err", err) + return + } + if msg.Method == types.MethodRegisterTrigger { - req, err := pb.UnmarshalCapabilityRequest(msg.Payload) + req, err := pb.UnmarshalTriggerRegistrationRequest(msg.Payload) if err != nil { - p.lggr.Errorw("failed to unmarshal capability request", "capabilityId", p.capInfo.ID, "err", err) + p.lggr.Errorw("failed to unmarshal trigger registration request", "capabilityId", p.capInfo.ID, "err", err) return } callerDon, ok := p.workflowDONs[msg.CallerDonId] @@ -102,8 +126,8 @@ func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { p.lggr.Errorw("sender not a member of its workflow DON", "capabilityId", p.capInfo.ID, "callerDonId", msg.CallerDonId, "sender", sender) return } - if !IsValidWorkflowOrExecutionID(req.Metadata.WorkflowID) { - p.lggr.Errorw("received trigger request with invalid workflow ID", "capabilityId", p.capInfo.ID, "workflowId", SanitizeLogString(req.Metadata.WorkflowID)) + if err = validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowID); err != nil { + p.lggr.Errorw("received trigger request with invalid workflow ID", "capabilityId", p.capInfo.ID, "workflowId", SanitizeLogString(req.Metadata.WorkflowID), "err", err) return } p.lggr.Debugw("received trigger registration", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "sender", sender) @@ -129,7 +153,7 @@ func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { p.lggr.Errorw("failed to aggregate trigger registrations", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "err", err) return } - unmarshaled, err := pb.UnmarshalCapabilityRequest(aggregated) + unmarshaled, err := pb.UnmarshalTriggerRegistrationRequest(aggregated) if err != nil { p.lggr.Errorw("failed to unmarshal request", "capabilityId", p.capInfo.ID, "err", err) return @@ -183,7 +207,7 @@ func (p *triggerPublisher) registrationCleanupLoop() { } } -func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.CapabilityResponse, key registrationKey) { +func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerResponse, key registrationKey) { defer p.wg.Done() for { select { @@ -194,38 +218,100 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.Capabili p.lggr.Infow("triggerEventLoop channel closed", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId) return } - triggerEvent := capabilities.TriggerEvent{} - err := response.Value.UnwrapTo(&triggerEvent) - if err != nil { - p.lggr.Errorw("can't unwrap trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId, "err", err) - break - } + triggerEvent := response.Event p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId, "triggerEventID", triggerEvent.ID) - marshaled, err := pb.MarshalCapabilityResponse(response) + marshaledResponse, err := pb.MarshalTriggerResponse(response) if err != nil { p.lggr.Debugw("can't marshal trigger event", "err", err) break } - msg := &types.MessageBody{ - CapabilityId: p.capInfo.ID, - CapabilityDonId: p.capDonInfo.ID, - CallerDonId: key.callerDonId, - Method: types.MethodTriggerEvent, - Payload: marshaled, - Metadata: &types.MessageBody_TriggerEventMetadata{ - TriggerEventMetadata: &types.TriggerEventMetadata{ - // NOTE: optionally introduce batching across workflows as an optimization - WorkflowIds: []string{key.workflowId}, - TriggerEventId: triggerEvent.ID, - }, + + if p.batchingEnabled { + p.enqueueForBatching(marshaledResponse, key, triggerEvent.ID) + } else { + // a single-element "batch" + p.sendBatch(&batchedResponse{ + rawResponse: marshaledResponse, + callerDonID: key.callerDonId, + triggerEventID: triggerEvent.ID, + workflowIDs: []string{key.workflowId}, + }) + } + } + } +} + +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) + combined = append(combined, []byte(triggerEventID)...) + combined = append(combined, rawResponse...) + sha := sha256.Sum256(combined) + p.bqMu.Lock() + elem, exists := p.batchingQueue[sha] + if !exists { + elem = &batchedResponse{ + rawResponse: rawResponse, + callerDonID: key.callerDonId, + triggerEventID: triggerEventID, + workflowIDs: []string{key.workflowId}, + } + p.batchingQueue[sha] = elem + } else { + elem.workflowIDs = append(elem.workflowIDs, key.workflowId) + } + p.bqMu.Unlock() +} + +func (p *triggerPublisher) sendBatch(resp *batchedResponse) { + for len(resp.workflowIDs) > 0 { + idBatch := resp.workflowIDs + if p.batchingEnabled && int64(len(idBatch)) > int64(p.config.MaxBatchSize) { + idBatch = idBatch[:p.config.MaxBatchSize] + resp.workflowIDs = resp.workflowIDs[p.config.MaxBatchSize:] + } else { + resp.workflowIDs = nil + } + msg := &types.MessageBody{ + CapabilityId: p.capInfo.ID, + CapabilityDonId: p.capDonInfo.ID, + CallerDonId: resp.callerDonID, + Method: types.MethodTriggerEvent, + Payload: resp.rawResponse, + Metadata: &types.MessageBody_TriggerEventMetadata{ + TriggerEventMetadata: &types.TriggerEventMetadata{ + WorkflowIds: idBatch, + TriggerEventId: resp.triggerEventID, }, + }, + } + // NOTE: send to all nodes by default, introduce different strategies later (KS-76) + for _, peerID := range p.workflowDONs[resp.callerDonID].Members { + err := p.dispatcher.Send(peerID, msg) + if err != nil { + p.lggr.Errorw("failed to send trigger event", "capabilityId", p.capInfo.ID, "peerID", peerID, "err", err) } - // NOTE: send to all nodes by default, introduce different strategies later (KS-76) - for _, peerID := range p.workflowDONs[key.callerDonId].Members { - err = p.dispatcher.Send(peerID, msg) - if err != nil { - p.lggr.Errorw("failed to send trigger event", "capabilityId", p.capInfo.ID, "peerID", peerID, "err", err) - } + } + } +} + +func (p *triggerPublisher) batchingLoop() { + defer p.wg.Done() + ticker := time.NewTicker(p.config.BatchCollectionPeriod) + defer ticker.Stop() + for { + select { + case <-p.stopCh: + return + case <-ticker.C: + p.bqMu.Lock() + queue := p.batchingQueue + p.batchingQueue = make(map[[32]byte]*batchedResponse) + p.bqMu.Unlock() + + for _, elem := range queue { + p.sendBatch(elem) } } } diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index 32de37a95aa..8d078dc1aad 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -5,99 +5,176 @@ import ( "testing" "time" + "github.com/stretchr/testify/mock" "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/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" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) +const capID = "cap_id@1" + func TestTriggerPublisher_Register(t *testing.T) { + ctx := testutils.Context(t) + capabilityDONID, workflowDONID := uint32(1), uint32(2) + + underlyingTriggerCap, publisher, _, peers := newServices(t, capabilityDONID, workflowDONID, 1) + + // invalid sender case - node 0 is not a member of the workflow DON, registration shoudn't happen + regEvent := newRegisterTriggerMessage(t, workflowDONID, peers[0]) + publisher.Receive(ctx, regEvent) + require.Empty(t, underlyingTriggerCap.registrationsCh) + + // valid registration + regEvent = newRegisterTriggerMessage(t, workflowDONID, peers[1]) + publisher.Receive(ctx, regEvent) + require.NotEmpty(t, underlyingTriggerCap.registrationsCh) + forwarded := <-underlyingTriggerCap.registrationsCh + require.Equal(t, workflowID1, forwarded.Metadata.WorkflowID) + + require.NoError(t, publisher.Close()) +} + +func TestTriggerPublisher_ReceiveTriggerEvents_NoBatching(t *testing.T) { + ctx := testutils.Context(t) + capabilityDONID, workflowDONID := uint32(1), uint32(2) + + underlyingTriggerCap, publisher, dispatcher, peers := newServices(t, capabilityDONID, workflowDONID, 1) + regEvent := newRegisterTriggerMessage(t, workflowDONID, peers[1]) + publisher.Receive(ctx, regEvent) + require.NotEmpty(t, underlyingTriggerCap.registrationsCh) + + // send a trigger event and expect that it gets delivered right away + underlyingTriggerCap.eventCh <- commoncap.TriggerResponse{} + awaitOutgoingMessageCh := make(chan struct{}) + dispatcher.On("Send", peers[1], mock.Anything).Run(func(args mock.Arguments) { + awaitOutgoingMessageCh <- struct{}{} + }).Return(nil) + <-awaitOutgoingMessageCh + + require.NoError(t, publisher.Close()) +} + +func TestTriggerPublisher_ReceiveTriggerEvents_BatchingEnabled(t *testing.T) { + ctx := testutils.Context(t) + capabilityDONID, workflowDONID := uint32(1), uint32(2) + + underlyingTriggerCap, publisher, dispatcher, peers := newServices(t, capabilityDONID, workflowDONID, 2) + regEvent := newRegisterTriggerMessage(t, workflowDONID, peers[1]) + publisher.Receive(ctx, regEvent) + require.NotEmpty(t, underlyingTriggerCap.registrationsCh) + + // send two trigger events and expect them to be delivered in a batch + underlyingTriggerCap.eventCh <- commoncap.TriggerResponse{} + underlyingTriggerCap.eventCh <- commoncap.TriggerResponse{} + awaitOutgoingMessageCh := make(chan struct{}) + dispatcher.On("Send", peers[1], mock.Anything).Run(func(args mock.Arguments) { + msg := args.Get(1).(*remotetypes.MessageBody) + require.Equal(t, capID, msg.CapabilityId) + require.Equal(t, remotetypes.MethodTriggerEvent, msg.Method) + require.NotEmpty(t, msg.Payload) + metadata := msg.Metadata.(*remotetypes.MessageBody_TriggerEventMetadata) + require.Len(t, metadata.TriggerEventMetadata.WorkflowIds, 2) + awaitOutgoingMessageCh <- struct{}{} + }).Return(nil).Once() + <-awaitOutgoingMessageCh + + // if there are fewer pending event than the batch size, + // the events should still be sent after the batch collection period + underlyingTriggerCap.eventCh <- commoncap.TriggerResponse{} + dispatcher.On("Send", peers[1], mock.Anything).Run(func(args mock.Arguments) { + msg := args.Get(1).(*remotetypes.MessageBody) + metadata := msg.Metadata.(*remotetypes.MessageBody_TriggerEventMetadata) + require.Len(t, metadata.TriggerEventMetadata.WorkflowIds, 1) + awaitOutgoingMessageCh <- struct{}{} + }).Return(nil).Once() + <-awaitOutgoingMessageCh + + require.NoError(t, publisher.Close()) +} + +func newServices(t *testing.T, capabilityDONID uint32, workflowDONID uint32, maxBatchSize uint32) (*testTrigger, remotetypes.ReceiverService, *mocks.Dispatcher, []p2ptypes.PeerID) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) capInfo := commoncap.CapabilityInfo{ - ID: "cap_id@1", + ID: capID, CapabilityType: commoncap.CapabilityTypeTrigger, Description: "Remote Trigger", } - p1 := p2ptypes.PeerID{} - require.NoError(t, p1.UnmarshalText([]byte(peerID1))) - p2 := p2ptypes.PeerID{} - require.NoError(t, p2.UnmarshalText([]byte(peerID2))) + peers := make([]p2ptypes.PeerID, 2) + require.NoError(t, peers[0].UnmarshalText([]byte(peerID1))) + require.NoError(t, peers[1].UnmarshalText([]byte(peerID2))) capDonInfo := commoncap.DON{ - ID: 1, - Members: []p2ptypes.PeerID{p1}, + ID: capabilityDONID, + Members: []p2ptypes.PeerID{peers[0]}, // peer 0 is in the capability DON F: 0, } workflowDonInfo := commoncap.DON{ - ID: 2, - Members: []p2ptypes.PeerID{p2}, + ID: workflowDONID, + Members: []p2ptypes.PeerID{peers[1]}, // peer 1 is in the workflow DON F: 0, } - dispatcher := remoteMocks.NewDispatcher(t) + dispatcher := mocks.NewDispatcher(t) config := &commoncap.RemoteTriggerConfig{ RegistrationRefresh: 100 * time.Millisecond, RegistrationExpiry: 100 * time.Second, MinResponsesToAggregate: 1, MessageExpiry: 100 * time.Second, + MaxBatchSize: maxBatchSize, + BatchCollectionPeriod: time.Second, } workflowDONs := map[uint32]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } underlying := &testTrigger{ info: capInfo, - registrationsCh: make(chan commoncap.CapabilityRequest, 2), + registrationsCh: make(chan commoncap.TriggerRegistrationRequest, 2), + eventCh: make(chan commoncap.TriggerResponse, 2), } publisher := remote.NewTriggerPublisher(config, underlying, capInfo, capDonInfo, workflowDONs, dispatcher, lggr) require.NoError(t, publisher.Start(ctx)) + return underlying, publisher, dispatcher, peers +} +func newRegisterTriggerMessage(t *testing.T, callerDonID uint32, sender p2ptypes.PeerID) *remotetypes.MessageBody { // trigger registration event - capRequest := commoncap.CapabilityRequest{ + triggerRequest := commoncap.TriggerRegistrationRequest{ Metadata: commoncap.RequestMetadata{ WorkflowID: workflowID1, }, } - marshaled, err := pb.MarshalCapabilityRequest(capRequest) + marshaled, err := pb.MarshalTriggerRegistrationRequest(triggerRequest) require.NoError(t, err) - regEvent := &remotetypes.MessageBody{ - Sender: p1[:], + return &remotetypes.MessageBody{ + Sender: sender[:], Method: remotetypes.MethodRegisterTrigger, - CallerDonId: workflowDonInfo.ID, + CallerDonId: callerDonID, Payload: marshaled, } - publisher.Receive(ctx, regEvent) - // node p1 is not a member of the workflow DON so registration shoudn't happen - require.Empty(t, underlying.registrationsCh) - - regEvent.Sender = p2[:] - publisher.Receive(ctx, regEvent) - require.NotEmpty(t, underlying.registrationsCh) - forwarded := <-underlying.registrationsCh - require.Equal(t, capRequest.Metadata.WorkflowID, forwarded.Metadata.WorkflowID) - - require.NoError(t, publisher.Close()) } type testTrigger struct { info commoncap.CapabilityInfo - registrationsCh chan commoncap.CapabilityRequest + registrationsCh chan commoncap.TriggerRegistrationRequest + eventCh chan commoncap.TriggerResponse } -func (t *testTrigger) Info(_ context.Context) (commoncap.CapabilityInfo, error) { - return t.info, nil +func (tr *testTrigger) Info(_ context.Context) (commoncap.CapabilityInfo, error) { + return tr.info, nil } -func (t *testTrigger) RegisterTrigger(_ context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - t.registrationsCh <- request - return nil, nil +func (tr *testTrigger) RegisterTrigger(_ context.Context, request commoncap.TriggerRegistrationRequest) (<-chan commoncap.TriggerResponse, error) { + tr.registrationsCh <- request + return tr.eventCh, nil } -func (t *testTrigger) UnregisterTrigger(_ context.Context, request commoncap.CapabilityRequest) error { +func (tr *testTrigger) UnregisterTrigger(_ context.Context, request commoncap.TriggerRegistrationRequest) error { return nil } diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index c932dc68e37..9f40c6c1f51 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -43,10 +43,15 @@ type triggerEventKey struct { } type subRegState struct { - callback chan commoncap.CapabilityResponse + callback chan commoncap.TriggerResponse rawRequest []byte } +type TriggerSubscriber interface { + commoncap.TriggerCapability + Receive(ctx context.Context, msg *types.MessageBody) +} + var _ commoncap.TriggerCapability = &triggerSubscriber{} var _ types.Receiver = &triggerSubscriber{} var _ services.Service = &triggerSubscriber{} @@ -98,8 +103,8 @@ func (s *triggerSubscriber) Info(ctx context.Context) (commoncap.CapabilityInfo, return s.capInfo, nil } -func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { - rawRequest, err := pb.MarshalCapabilityRequest(request) +func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, request commoncap.TriggerRegistrationRequest) (<-chan commoncap.TriggerResponse, error) { + rawRequest, err := pb.MarshalTriggerRegistrationRequest(request) if err != nil { return nil, err } @@ -113,7 +118,7 @@ func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, request commonc regState, ok := s.registeredWorkflows[request.Metadata.WorkflowID] if !ok { regState = &subRegState{ - callback: make(chan commoncap.CapabilityResponse, defaultSendChannelBufferSize), + callback: make(chan commoncap.TriggerResponse, defaultSendChannelBufferSize), rawRequest: rawRequest, } s.registeredWorkflows[request.Metadata.WorkflowID] = regState @@ -160,7 +165,7 @@ func (s *triggerSubscriber) registrationLoop() { } } -func (s *triggerSubscriber) UnregisterTrigger(ctx context.Context, request commoncap.CapabilityRequest) error { +func (s *triggerSubscriber) UnregisterTrigger(ctx context.Context, request commoncap.TriggerRegistrationRequest) error { s.mu.Lock() defer s.mu.Unlock() @@ -175,7 +180,12 @@ func (s *triggerSubscriber) UnregisterTrigger(ctx context.Context, request commo } func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { - sender := ToPeerID(msg.Sender) + sender, err := ToPeerID(msg.Sender) + if err != nil { + s.lggr.Errorw("failed to convert message sender to PeerID", "err", err) + return + } + if _, found := s.capDonMembers[sender]; !found { s.lggr.Errorw("received message from unexpected node", "capabilityId", s.capInfo.ID, "sender", sender) return diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index c834a271d56..b8cc3ddc7bd 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -71,7 +71,7 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { subscriber := remote.NewTriggerSubscriber(config, capInfo, capDonInfo, workflowDonInfo, dispatcher, nil, lggr) require.NoError(t, subscriber.Start(ctx)) - req := commoncap.CapabilityRequest{ + req := commoncap.TriggerRegistrationRequest{ Metadata: commoncap.RequestMetadata{ WorkflowID: workflowID1, }, @@ -83,11 +83,13 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { // receive trigger event triggerEventValue, err := values.NewMap(triggerEvent1) require.NoError(t, err) - capResponse := commoncap.CapabilityResponse{ - Value: triggerEventValue, - Err: nil, + capResponse := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: triggerEventValue, + }, + Err: nil, } - marshaled, err := pb.MarshalCapabilityResponse(capResponse) + marshaled, err := pb.MarshalTriggerResponse(capResponse) require.NoError(t, err) triggerEvent := &remotetypes.MessageBody{ Sender: p1[:], @@ -101,7 +103,7 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { } subscriber.Receive(ctx, triggerEvent) response := <-triggerEventCallbackCh - require.Equal(t, response.Value, triggerEventValue) + require.Equal(t, response.Event.Outputs, triggerEventValue) require.NoError(t, subscriber.UnregisterTrigger(ctx, req)) require.NoError(t, subscriber.UnregisterTrigger(ctx, req)) diff --git a/core/capabilities/remote/types/messages.pb.go b/core/capabilities/remote/types/messages.pb.go index f5b77b5c15a..0675bcc0f2a 100644 --- a/core/capabilities/remote/types/messages.pb.go +++ b/core/capabilities/remote/types/messages.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.35.1 // protoc v4.25.1 // source: core/capabilities/remote/types/messages.proto @@ -89,11 +89,9 @@ type Message struct { func (x *Message) Reset() { *x = Message{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Message) String() string { @@ -104,7 +102,7 @@ func (*Message) ProtoMessage() {} func (x *Message) ProtoReflect() protoreflect.Message { mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -160,11 +158,9 @@ type MessageBody struct { func (x *MessageBody) Reset() { *x = MessageBody{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *MessageBody) String() string { @@ -175,7 +171,7 @@ func (*MessageBody) ProtoMessage() {} func (x *MessageBody) ProtoReflect() protoreflect.Message { mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -321,11 +317,9 @@ type TriggerRegistrationMetadata struct { func (x *TriggerRegistrationMetadata) Reset() { *x = TriggerRegistrationMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TriggerRegistrationMetadata) String() string { @@ -336,7 +330,7 @@ func (*TriggerRegistrationMetadata) ProtoMessage() {} func (x *TriggerRegistrationMetadata) ProtoReflect() protoreflect.Message { mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -369,11 +363,9 @@ type TriggerEventMetadata struct { func (x *TriggerEventMetadata) Reset() { *x = TriggerEventMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TriggerEventMetadata) String() string { @@ -384,7 +376,7 @@ func (*TriggerEventMetadata) ProtoMessage() {} func (x *TriggerEventMetadata) ProtoReflect() protoreflect.Message { mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -522,56 +514,6 @@ func file_core_capabilities_remote_types_messages_proto_init() { if File_core_capabilities_remote_types_messages_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_core_capabilities_remote_types_messages_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_capabilities_remote_types_messages_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*MessageBody); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_capabilities_remote_types_messages_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*TriggerRegistrationMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_capabilities_remote_types_messages_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*TriggerEventMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } file_core_capabilities_remote_types_messages_proto_msgTypes[1].OneofWrappers = []any{ (*MessageBody_TriggerRegistrationMetadata)(nil), (*MessageBody_TriggerEventMetadata)(nil), diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index 3629fc06fe9..54ec16f09f1 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -30,8 +30,13 @@ type Receiver interface { Receive(ctx context.Context, msg *MessageBody) } +type ReceiverService interface { + services.Service + Receiver +} + type Aggregator interface { - Aggregate(eventID string, responses [][]byte) (commoncap.CapabilityResponse, error) + Aggregate(eventID string, responses [][]byte) (commoncap.TriggerResponse, error) } // NOTE: this type will become part of the Registry (KS-108) diff --git a/core/capabilities/remote/utils.go b/core/capabilities/remote/utils.go index 7e303eefc8f..ea6a3efb186 100644 --- a/core/capabilities/remote/utils.go +++ b/core/capabilities/remote/utils.go @@ -19,8 +19,6 @@ import ( const ( maxLoggedStringLen = 256 - validWorkflowIDLen = 64 - maxIDLen = 128 ) func ValidateMessage(msg p2ptypes.Message, expectedReceiver p2ptypes.PeerID) (*remotetypes.MessageBody, error) { @@ -50,10 +48,14 @@ func ValidateMessage(msg p2ptypes.Message, expectedReceiver p2ptypes.PeerID) (*r return &body, nil } -func ToPeerID(peerID []byte) p2ptypes.PeerID { +func ToPeerID(peerID []byte) (p2ptypes.PeerID, error) { + if len(peerID) != p2ptypes.PeerIDLength { + return p2ptypes.PeerID{}, fmt.Errorf("invalid peer ID length: %d", len(peerID)) + } + var id p2ptypes.PeerID copy(id[:], peerID) - return id + return id, nil } // Default MODE Aggregator needs a configurable number of identical responses for aggregation to succeed @@ -69,15 +71,15 @@ func NewDefaultModeAggregator(minIdenticalResponses uint32) *defaultModeAggregat } } -func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.CapabilityResponse, error) { +func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.TriggerResponse, error) { found, err := AggregateModeRaw(responses, a.minIdenticalResponses) if err != nil { - return commoncap.CapabilityResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) + return commoncap.TriggerResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) } - unmarshaled, err := pb.UnmarshalCapabilityResponse(found) + unmarshaled, err := pb.UnmarshalTriggerResponse(found) if err != nil { - return commoncap.CapabilityResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) + return commoncap.TriggerResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) } return unmarshaled, nil } @@ -115,25 +117,3 @@ func SanitizeLogString(s string) string { } return s + tooLongSuffix } - -// Workflow IDs and Execution IDs are 32-byte hex-encoded strings -func IsValidWorkflowOrExecutionID(id string) bool { - if len(id) != validWorkflowIDLen { - return false - } - _, err := hex.DecodeString(id) - return err == nil -} - -// Trigger event IDs and message IDs can only contain printable characters and must be non-empty -func IsValidID(id string) bool { - if len(id) == 0 || len(id) > maxIDLen { - return false - } - for i := 0; i < len(id); i++ { - if !unicode.IsPrint(rune(id[i])) { - return false - } - } - return true -} diff --git a/core/capabilities/remote/utils_test.go b/core/capabilities/remote/utils_test.go index 177ab5a7d14..6707e6ffb25 100644 --- a/core/capabilities/remote/utils_test.go +++ b/core/capabilities/remote/utils_test.go @@ -84,27 +84,32 @@ func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderId p2pt } func TestToPeerID(t *testing.T) { - id := remote.ToPeerID([]byte("12345678901234567890123456789012")) + id, err := remote.ToPeerID([]byte("12345678901234567890123456789012")) + require.NoError(t, err) require.Equal(t, "12D3KooWD8QYTQVYjB6oog4Ej8PcPpqTrPRnxLQap8yY8KUQRVvq", id.String()) } func TestDefaultModeAggregator_Aggregate(t *testing.T) { val, err := values.NewMap(triggerEvent1) require.NoError(t, err) - capResponse1 := commoncap.CapabilityResponse{ - Value: val, - Err: nil, + capResponse1 := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: val, + }, + Err: nil, } - marshaled1, err := pb.MarshalCapabilityResponse(capResponse1) + marshaled1, err := pb.MarshalTriggerResponse(capResponse1) require.NoError(t, err) val2, err := values.NewMap(triggerEvent2) require.NoError(t, err) - capResponse2 := commoncap.CapabilityResponse{ - Value: val2, - Err: nil, + capResponse2 := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: val2, + }, + Err: nil, } - marshaled2, err := pb.MarshalCapabilityResponse(capResponse2) + marshaled2, err := pb.MarshalTriggerResponse(capResponse2) require.NoError(t, err) agg := remote.NewDefaultModeAggregator(2) @@ -129,15 +134,3 @@ func TestSanitizeLogString(t *testing.T) { } require.Equal(t, longString[:256]+" [TRUNCATED]", remote.SanitizeLogString(longString)) } - -func TestIsValidWorkflowID(t *testing.T) { - require.False(t, remote.IsValidWorkflowOrExecutionID("too_short")) - require.False(t, remote.IsValidWorkflowOrExecutionID("nothex--95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0")) - require.True(t, remote.IsValidWorkflowOrExecutionID("15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0")) -} - -func TestIsValidTriggerEventID(t *testing.T) { - require.False(t, remote.IsValidID("")) - require.False(t, remote.IsValidID("\n\n")) - require.True(t, remote.IsValidID("id_id_2")) -} diff --git a/core/capabilities/streams/codec.go b/core/capabilities/streams/codec.go index 26011cb7f35..d6918f0c739 100644 --- a/core/capabilities/streams/codec.go +++ b/core/capabilities/streams/codec.go @@ -20,7 +20,7 @@ type codec struct { var _ datastreams.ReportCodec = &codec{} func (c *codec) Unwrap(wrapped values.Value) ([]datastreams.FeedReport, error) { - dest, err := datastreams.UnwrapFeedReportList(wrapped) + dest, err := datastreams.UnwrapStreamsTriggerEventToFeedReportList(wrapped) if err != nil { return nil, fmt.Errorf("failed to unwrap: %v", err) } @@ -45,7 +45,9 @@ func (c *codec) Unwrap(wrapped values.Value) ([]datastreams.FeedReport, error) { } func (c *codec) Wrap(reports []datastreams.FeedReport) (values.Value, error) { - return values.Wrap(reports) + return values.Wrap(&datastreams.StreamsTriggerEvent{ + Payload: reports, + }) } func (c *codec) Validate(report datastreams.FeedReport, allowedSigners [][]byte, minRequiredSignatures int) error { diff --git a/core/capabilities/streams/codec_test.go b/core/capabilities/streams/codec_test.go index 02ec474fec9..13f4f299f8c 100644 --- a/core/capabilities/streams/codec_test.go +++ b/core/capabilities/streams/codec_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -109,8 +110,9 @@ func newFeedID(t *testing.T) ([32]byte, string) { } func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) []byte { + ctx := tests.Context(t) v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) - raw, err := v3Codec.BuildReport(v3.ReportFields{ + raw, err := v3Codec.BuildReport(ctx, v3.ReportFields{ BenchmarkPrice: price, Timestamp: uint32(timestamp), ValidFromTimestamp: uint32(timestamp), diff --git a/core/capabilities/streams/consensus_agg_test.go b/core/capabilities/streams/consensus_agg_test.go index 506ad26f86f..834889f2c31 100644 --- a/core/capabilities/streams/consensus_agg_test.go +++ b/core/capabilities/streams/consensus_agg_test.go @@ -9,7 +9,6 @@ import ( "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/datafeeds" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" "github.com/smartcontractkit/chainlink-common/pkg/values" @@ -37,11 +36,11 @@ func TestStreamsConsensusAggregator(t *testing.T) { config := newAggConfig(t, feeds) lggr := logger.TestLogger(t) codec := streams.NewCodec(lggr) - agg, err := datafeeds.NewDataFeedsAggregator(*config, codec, lggr) + agg, err := datafeeds.NewDataFeedsAggregator(*config, codec) require.NoError(t, err) // init round - empty previous Outcome, empty observations - outcome, err := agg.Aggregate(nil, map[commontypes.OracleID][]values.Value{}, Fw) + outcome, err := agg.Aggregate(lggr, nil, map[commontypes.OracleID][]values.Value{}, Fw) require.NoError(t, err) require.False(t, outcome.ShouldReport) @@ -57,7 +56,7 @@ func TestStreamsConsensusAggregator(t *testing.T) { for c := 0; c < T; c++ { obs := newObservations(t, Nw, feeds, Ft+1, allowedSigners) processingStart := time.Now().UnixMilli() - outcome, err = agg.Aggregate(outcome, obs, Fw) + outcome, err = agg.Aggregate(lggr, outcome, obs, Fw) processingTime += time.Now().UnixMilli() - processingStart require.NoError(t, err) } @@ -98,26 +97,18 @@ func newObservations(t *testing.T, nNodes int, feeds []feed, minRequiredSignatur reportList = append(reportList, signedStreamsReport) } - payloadVal, err := values.Wrap(reportList) - require.NoError(t, err) - - meta := datastreams.SignersMetadata{ + meta := datastreams.Metadata{ Signers: allowedSigners, MinRequiredSignatures: minRequiredSignatures, } - metaVal, err := values.Wrap(meta) - require.NoError(t, err) - - triggerEvent := capabilities.TriggerEvent{ - TriggerType: triggerID, - ID: "unused", - Timestamp: "1234", - Metadata: metaVal, - Payload: payloadVal, + p := datastreams.StreamsTriggerEvent{ + Payload: reportList, + Metadata: meta, } - wrappedEvent, err := values.Wrap(triggerEvent) + outputs, err := values.WrapMap(p) require.NoError(t, err) - observations[commontypes.OracleID(i)] = []values.Value{wrappedEvent} + + observations[commontypes.OracleID(i)] = []values.Value{outputs} } return observations } diff --git a/core/capabilities/streams/trigger_test.go b/core/capabilities/streams/trigger_test.go index 853f07f2aae..3db6f2445ea 100644 --- a/core/capabilities/streams/trigger_test.go +++ b/core/capabilities/streams/trigger_test.go @@ -93,7 +93,7 @@ func TestStreamsTrigger(t *testing.T) { subscriber := remote.NewTriggerSubscriber(config, capInfo, capDonInfo, capabilities.DON{}, nil, agg, lggr) // register trigger - req := capabilities.CapabilityRequest{ + req := capabilities.TriggerRegistrationRequest{ Metadata: capabilities.RequestMetadata{ WorkflowID: workflowID, }, @@ -131,7 +131,7 @@ func TestStreamsTrigger(t *testing.T) { } response := <-triggerEventCallbackCh - validateLatestReports(t, response.Value, P, basePrice+R-1, baseTimestamp+R-1) + validateLatestReports(t, response.Event.Outputs, P, basePrice+R-1, baseTimestamp+R-1) } totalTime := time.Now().UnixMilli() - startTs lggr.Infow("elapsed", "totalMs", totalTime, "processingMs", processingTime) @@ -180,24 +180,20 @@ func newFeedsWithSignedReports(t *testing.T, nodes []node, N, P, R int) []feed { } func newTriggerEvent(t *testing.T, reportList []datastreams.FeedReport, triggerEventID string, sender ragetypes.PeerID) *remotetypes.MessageBody { - val, err := values.Wrap(reportList) + outputs, err := values.WrapMap(&datastreams.StreamsTriggerEvent{ + Timestamp: 10, + Payload: reportList, + }) require.NoError(t, err) triggerEvent := capabilities.TriggerEvent{ TriggerType: triggerID, ID: triggerEventID, - Timestamp: strconv.FormatInt(1000, 10), - Metadata: nil, - Payload: val, + Outputs: outputs, } - eventVal, err := values.WrapMap(triggerEvent) - require.NoError(t, err) + marshaled, err := pb.MarshalTriggerResponse(capabilities.TriggerResponse{Event: triggerEvent}) - marshaled, err := pb.MarshalCapabilityResponse( - capabilities.CapabilityResponse{ - Value: eventVal, - }) require.NoError(t, err) msg := &remotetypes.MessageBody{ Sender: sender[:], @@ -214,13 +210,11 @@ func newTriggerEvent(t *testing.T, reportList []datastreams.FeedReport, triggerE } func validateLatestReports(t *testing.T, wrapped values.Value, expectedFeedsLen int, expectedPrice int, expectedTimestamp int) { - triggerEvent := capabilities.TriggerEvent{} + triggerEvent := datastreams.StreamsTriggerEvent{} require.NoError(t, wrapped.UnwrapTo(&triggerEvent)) - reports := []datastreams.FeedReport{} - require.NoError(t, triggerEvent.Payload.UnwrapTo(&reports)) - require.Equal(t, expectedFeedsLen, len(reports)) + require.Equal(t, expectedFeedsLen, len(triggerEvent.Payload)) priceBig := big.NewInt(int64(expectedPrice)) - for _, report := range reports { + for _, report := range triggerEvent.Payload { require.Equal(t, priceBig.Bytes(), report.BenchmarkPrice) require.Equal(t, int64(expectedTimestamp), report.ObservationTimestamp) } diff --git a/core/capabilities/targets/mocks/chain_reader.go b/core/capabilities/targets/mocks/chain_reader.go deleted file mode 100644 index 9c1c85ff60c..00000000000 --- a/core/capabilities/targets/mocks/chain_reader.go +++ /dev/null @@ -1,487 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mocks - -import ( - context "context" - - query "github.com/smartcontractkit/chainlink-common/pkg/types/query" - primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// ChainReader is an autogenerated mock type for the ChainReader type -type ChainReader struct { - mock.Mock -} - -type ChainReader_Expecter struct { - mock *mock.Mock -} - -func (_m *ChainReader) EXPECT() *ChainReader_Expecter { - return &ChainReader_Expecter{mock: &_m.Mock} -} - -// BatchGetLatestValues provides a mock function with given fields: ctx, request -func (_m *ChainReader) BatchGetLatestValues(ctx context.Context, request types.BatchGetLatestValuesRequest) (types.BatchGetLatestValuesResult, error) { - ret := _m.Called(ctx, request) - - if len(ret) == 0 { - panic("no return value specified for BatchGetLatestValues") - } - - var r0 types.BatchGetLatestValuesResult - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.BatchGetLatestValuesRequest) (types.BatchGetLatestValuesResult, error)); ok { - return rf(ctx, request) - } - if rf, ok := ret.Get(0).(func(context.Context, types.BatchGetLatestValuesRequest) types.BatchGetLatestValuesResult); ok { - r0 = rf(ctx, request) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.BatchGetLatestValuesResult) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, types.BatchGetLatestValuesRequest) error); ok { - r1 = rf(ctx, request) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChainReader_BatchGetLatestValues_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchGetLatestValues' -type ChainReader_BatchGetLatestValues_Call struct { - *mock.Call -} - -// BatchGetLatestValues is a helper method to define mock.On call -// - ctx context.Context -// - request types.BatchGetLatestValuesRequest -func (_e *ChainReader_Expecter) BatchGetLatestValues(ctx interface{}, request interface{}) *ChainReader_BatchGetLatestValues_Call { - return &ChainReader_BatchGetLatestValues_Call{Call: _e.mock.On("BatchGetLatestValues", ctx, request)} -} - -func (_c *ChainReader_BatchGetLatestValues_Call) Run(run func(ctx context.Context, request types.BatchGetLatestValuesRequest)) *ChainReader_BatchGetLatestValues_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(types.BatchGetLatestValuesRequest)) - }) - return _c -} - -func (_c *ChainReader_BatchGetLatestValues_Call) Return(_a0 types.BatchGetLatestValuesResult, _a1 error) *ChainReader_BatchGetLatestValues_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ChainReader_BatchGetLatestValues_Call) RunAndReturn(run func(context.Context, types.BatchGetLatestValuesRequest) (types.BatchGetLatestValuesResult, error)) *ChainReader_BatchGetLatestValues_Call { - _c.Call.Return(run) - return _c -} - -// Bind provides a mock function with given fields: ctx, bindings -func (_m *ChainReader) Bind(ctx context.Context, bindings []types.BoundContract) error { - ret := _m.Called(ctx, bindings) - - if len(ret) == 0 { - panic("no return value specified for Bind") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []types.BoundContract) error); ok { - r0 = rf(ctx, bindings) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainReader_Bind_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Bind' -type ChainReader_Bind_Call struct { - *mock.Call -} - -// Bind is a helper method to define mock.On call -// - ctx context.Context -// - bindings []types.BoundContract -func (_e *ChainReader_Expecter) Bind(ctx interface{}, bindings interface{}) *ChainReader_Bind_Call { - return &ChainReader_Bind_Call{Call: _e.mock.On("Bind", ctx, bindings)} -} - -func (_c *ChainReader_Bind_Call) Run(run func(ctx context.Context, bindings []types.BoundContract)) *ChainReader_Bind_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]types.BoundContract)) - }) - return _c -} - -func (_c *ChainReader_Bind_Call) Return(_a0 error) *ChainReader_Bind_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_Bind_Call) RunAndReturn(run func(context.Context, []types.BoundContract) error) *ChainReader_Bind_Call { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *ChainReader) 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 -} - -// ChainReader_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type ChainReader_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *ChainReader_Expecter) Close() *ChainReader_Close_Call { - return &ChainReader_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *ChainReader_Close_Call) Run(run func()) *ChainReader_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainReader_Close_Call) Return(_a0 error) *ChainReader_Close_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_Close_Call) RunAndReturn(run func() error) *ChainReader_Close_Call { - _c.Call.Return(run) - return _c -} - -// GetLatestValue provides a mock function with given fields: ctx, contractName, method, confidenceLevel, params, returnVal -func (_m *ChainReader) GetLatestValue(ctx context.Context, contractName string, method string, confidenceLevel primitives.ConfidenceLevel, params interface{}, returnVal interface{}) error { - ret := _m.Called(ctx, contractName, method, confidenceLevel, params, returnVal) - - if len(ret) == 0 { - panic("no return value specified for GetLatestValue") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, primitives.ConfidenceLevel, interface{}, interface{}) error); ok { - r0 = rf(ctx, contractName, method, confidenceLevel, params, returnVal) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainReader_GetLatestValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestValue' -type ChainReader_GetLatestValue_Call struct { - *mock.Call -} - -// GetLatestValue is a helper method to define mock.On call -// - ctx context.Context -// - contractName string -// - method string -// - confidenceLevel primitives.ConfidenceLevel -// - params interface{} -// - returnVal interface{} -func (_e *ChainReader_Expecter) GetLatestValue(ctx interface{}, contractName interface{}, method interface{}, confidenceLevel interface{}, params interface{}, returnVal interface{}) *ChainReader_GetLatestValue_Call { - return &ChainReader_GetLatestValue_Call{Call: _e.mock.On("GetLatestValue", ctx, contractName, method, confidenceLevel, params, returnVal)} -} - -func (_c *ChainReader_GetLatestValue_Call) Run(run func(ctx context.Context, contractName string, method string, confidenceLevel primitives.ConfidenceLevel, params interface{}, returnVal interface{})) *ChainReader_GetLatestValue_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(primitives.ConfidenceLevel), args[4].(interface{}), args[5].(interface{})) - }) - return _c -} - -func (_c *ChainReader_GetLatestValue_Call) Return(_a0 error) *ChainReader_GetLatestValue_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_GetLatestValue_Call) RunAndReturn(run func(context.Context, string, string, primitives.ConfidenceLevel, interface{}, interface{}) error) *ChainReader_GetLatestValue_Call { - _c.Call.Return(run) - return _c -} - -// HealthReport provides a mock function with given fields: -func (_m *ChainReader) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// ChainReader_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type ChainReader_HealthReport_Call struct { - *mock.Call -} - -// HealthReport is a helper method to define mock.On call -func (_e *ChainReader_Expecter) HealthReport() *ChainReader_HealthReport_Call { - return &ChainReader_HealthReport_Call{Call: _e.mock.On("HealthReport")} -} - -func (_c *ChainReader_HealthReport_Call) Run(run func()) *ChainReader_HealthReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainReader_HealthReport_Call) Return(_a0 map[string]error) *ChainReader_HealthReport_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_HealthReport_Call) RunAndReturn(run func() map[string]error) *ChainReader_HealthReport_Call { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *ChainReader) 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 -} - -// ChainReader_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type ChainReader_Name_Call struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *ChainReader_Expecter) Name() *ChainReader_Name_Call { - return &ChainReader_Name_Call{Call: _e.mock.On("Name")} -} - -func (_c *ChainReader_Name_Call) Run(run func()) *ChainReader_Name_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainReader_Name_Call) Return(_a0 string) *ChainReader_Name_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_Name_Call) RunAndReturn(run func() string) *ChainReader_Name_Call { - _c.Call.Return(run) - return _c -} - -// QueryKey provides a mock function with given fields: ctx, contractName, filter, limitAndSort, sequenceDataType -func (_m *ChainReader) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType interface{}) ([]types.Sequence, error) { - ret := _m.Called(ctx, contractName, filter, limitAndSort, sequenceDataType) - - if len(ret) == 0 { - panic("no return value specified for QueryKey") - } - - var r0 []types.Sequence - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, query.KeyFilter, query.LimitAndSort, interface{}) ([]types.Sequence, error)); ok { - return rf(ctx, contractName, filter, limitAndSort, sequenceDataType) - } - if rf, ok := ret.Get(0).(func(context.Context, string, query.KeyFilter, query.LimitAndSort, interface{}) []types.Sequence); ok { - r0 = rf(ctx, contractName, filter, limitAndSort, sequenceDataType) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]types.Sequence) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, query.KeyFilter, query.LimitAndSort, interface{}) error); ok { - r1 = rf(ctx, contractName, filter, limitAndSort, sequenceDataType) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChainReader_QueryKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryKey' -type ChainReader_QueryKey_Call struct { - *mock.Call -} - -// QueryKey is a helper method to define mock.On call -// - ctx context.Context -// - contractName string -// - filter query.KeyFilter -// - limitAndSort query.LimitAndSort -// - sequenceDataType interface{} -func (_e *ChainReader_Expecter) QueryKey(ctx interface{}, contractName interface{}, filter interface{}, limitAndSort interface{}, sequenceDataType interface{}) *ChainReader_QueryKey_Call { - return &ChainReader_QueryKey_Call{Call: _e.mock.On("QueryKey", ctx, contractName, filter, limitAndSort, sequenceDataType)} -} - -func (_c *ChainReader_QueryKey_Call) Run(run func(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType interface{})) *ChainReader_QueryKey_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(query.KeyFilter), args[3].(query.LimitAndSort), args[4].(interface{})) - }) - return _c -} - -func (_c *ChainReader_QueryKey_Call) Return(_a0 []types.Sequence, _a1 error) *ChainReader_QueryKey_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ChainReader_QueryKey_Call) RunAndReturn(run func(context.Context, string, query.KeyFilter, query.LimitAndSort, interface{}) ([]types.Sequence, error)) *ChainReader_QueryKey_Call { - _c.Call.Return(run) - return _c -} - -// Ready provides a mock function with given fields: -func (_m *ChainReader) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainReader_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type ChainReader_Ready_Call struct { - *mock.Call -} - -// Ready is a helper method to define mock.On call -func (_e *ChainReader_Expecter) Ready() *ChainReader_Ready_Call { - return &ChainReader_Ready_Call{Call: _e.mock.On("Ready")} -} - -func (_c *ChainReader_Ready_Call) Run(run func()) *ChainReader_Ready_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainReader_Ready_Call) Return(_a0 error) *ChainReader_Ready_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_Ready_Call) RunAndReturn(run func() error) *ChainReader_Ready_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *ChainReader) 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 -} - -// ChainReader_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type ChainReader_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *ChainReader_Expecter) Start(_a0 interface{}) *ChainReader_Start_Call { - return &ChainReader_Start_Call{Call: _e.mock.On("Start", _a0)} -} - -func (_c *ChainReader_Start_Call) Run(run func(_a0 context.Context)) *ChainReader_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ChainReader_Start_Call) Return(_a0 error) *ChainReader_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainReader_Start_Call) RunAndReturn(run func(context.Context) error) *ChainReader_Start_Call { - _c.Call.Return(run) - return _c -} - -// NewChainReader creates a new instance of ChainReader. 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 NewChainReader(t interface { - mock.TestingT - Cleanup(func()) -}) *ChainReader { - mock := &ChainReader{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/targets/mocks/contract_value_getter.go b/core/capabilities/targets/mocks/contract_value_getter.go new file mode 100644 index 00000000000..2621de45876 --- /dev/null +++ b/core/capabilities/targets/mocks/contract_value_getter.go @@ -0,0 +1,136 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// ContractValueGetter is an autogenerated mock type for the ContractValueGetter type +type ContractValueGetter struct { + mock.Mock +} + +type ContractValueGetter_Expecter struct { + mock *mock.Mock +} + +func (_m *ContractValueGetter) EXPECT() *ContractValueGetter_Expecter { + return &ContractValueGetter_Expecter{mock: &_m.Mock} +} + +// Bind provides a mock function with given fields: _a0, _a1 +func (_m *ContractValueGetter) Bind(_a0 context.Context, _a1 []types.BoundContract) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Bind") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []types.BoundContract) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractValueGetter_Bind_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Bind' +type ContractValueGetter_Bind_Call struct { + *mock.Call +} + +// Bind is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 []types.BoundContract +func (_e *ContractValueGetter_Expecter) Bind(_a0 interface{}, _a1 interface{}) *ContractValueGetter_Bind_Call { + return &ContractValueGetter_Bind_Call{Call: _e.mock.On("Bind", _a0, _a1)} +} + +func (_c *ContractValueGetter_Bind_Call) Run(run func(_a0 context.Context, _a1 []types.BoundContract)) *ContractValueGetter_Bind_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]types.BoundContract)) + }) + return _c +} + +func (_c *ContractValueGetter_Bind_Call) Return(_a0 error) *ContractValueGetter_Bind_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractValueGetter_Bind_Call) RunAndReturn(run func(context.Context, []types.BoundContract) error) *ContractValueGetter_Bind_Call { + _c.Call.Return(run) + return _c +} + +// 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 interface{}, _a4 interface{}) error { + ret := _m.Called(_a0, _a1, _a2, _a3, _a4) + + if len(ret) == 0 { + panic("no return value specified for GetLatestValue") + } + + var r0 error + 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) + } + + return r0 +} + +// ContractValueGetter_GetLatestValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestValue' +type ContractValueGetter_GetLatestValue_Call struct { + *mock.Call +} + +// GetLatestValue is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +// - _a2 primitives.ConfidenceLevel +// - _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 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].(interface{}), args[4].(interface{})) + }) + return _c +} + +func (_c *ContractValueGetter_GetLatestValue_Call) Return(_a0 error) *ContractValueGetter_GetLatestValue_Call { + _c.Call.Return(_a0) + return _c +} + +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 +} + +// NewContractValueGetter creates a new instance of ContractValueGetter. 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 NewContractValueGetter(t interface { + mock.TestingT + Cleanup(func()) +}) *ContractValueGetter { + mock := &ContractValueGetter{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 282a4741a6a..0e0b2071829 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -13,18 +13,19 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) var ( - _ capabilities.ActionCapability = &WriteTarget{} + _ capabilities.TargetCapability = &WriteTarget{} ) type WriteTarget struct { - cr commontypes.ContractReader + cr ContractValueGetter cw commontypes.ChainWriter + binding commontypes.BoundContract forwarderAddress string // The minimum amount of gas that the receiver contract must get to process the forwarder report receiverGasMinimum uint64 @@ -47,24 +48,38 @@ type TransmissionInfo struct { // The gas cost of the forwarder contract logic, including state updates and event emission. // This is a rough estimate and should be updated if the forwarder contract logic changes. // TODO: Make this part of the on-chain capability configuration -const FORWARDER_CONTRACT_LOGIC_GAS_COST = 100_000 +const ForwarderContractLogicGasCost = 100_000 -func NewWriteTarget(lggr logger.Logger, id string, cr commontypes.ContractReader, cw commontypes.ChainWriter, forwarderAddress string, txGasLimit uint64) *WriteTarget { +type ContractValueGetter interface { + Bind(context.Context, []commontypes.BoundContract) error + GetLatestValue(context.Context, string, primitives.ConfidenceLevel, any, any) error +} + +func NewWriteTarget( + lggr logger.Logger, + id string, + cr ContractValueGetter, + cw commontypes.ChainWriter, + forwarderAddress string, + txGasLimit uint64, +) *WriteTarget { info := capabilities.MustNewCapabilityInfo( id, capabilities.CapabilityTypeTarget, "Write target.", ) - logger := lggr.Named("WriteTarget") - return &WriteTarget{ cr, cw, + commontypes.BoundContract{ + Address: forwarderAddress, + Name: "forwarder", + }, forwarderAddress, - txGasLimit - FORWARDER_CONTRACT_LOGIC_GAS_COST, + txGasLimit - ForwarderContractLogicGasCost, info, - logger, + logger.Named(lggr, "WriteTarget"), false, } } @@ -109,6 +124,8 @@ func decodeReportMetadata(data []byte) (metadata ReportV1Metadata, err error) { type Config struct { // Address of the contract that will get the forwarded report Address string + // Optional gas limit that overrides the default limit sent to the chain writer + GasLimit *uint64 } type Inputs struct { @@ -160,37 +177,38 @@ func evaluate(rawRequest capabilities.CapabilityRequest) (r Request, err error) return r, fmt.Errorf("unsupported report version: %d", reportMetadata.Version) } - if hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]) != rawRequest.Metadata.WorkflowExecutionID || - hex.EncodeToString(reportMetadata.WorkflowOwner[:]) != rawRequest.Metadata.WorkflowOwner || - hex.EncodeToString(reportMetadata.WorkflowName[:]) != rawRequest.Metadata.WorkflowName || - hex.EncodeToString(reportMetadata.WorkflowCID[:]) != rawRequest.Metadata.WorkflowID { - return r, fmt.Errorf("report metadata does not match request metadata. reportMetadata: %+v, requestMetadata: %+v", reportMetadata, rawRequest.Metadata) + if hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]) != rawRequest.Metadata.WorkflowExecutionID { + return r, fmt.Errorf("WorkflowExecutionID in the report does not match WorkflowExecutionID in the request metadata. Report WorkflowExecutionID: %+v, request WorkflowExecutionID: %+v", reportMetadata.WorkflowExecutionID, rawRequest.Metadata.WorkflowExecutionID) } - return r, nil -} + if hex.EncodeToString(reportMetadata.WorkflowOwner[:]) != rawRequest.Metadata.WorkflowOwner { + return r, fmt.Errorf("WorkflowOwner in the report does not match WorkflowOwner in the request metadata. Report WorkflowOwner: %+v, request WorkflowOwner: %+v", reportMetadata.WorkflowOwner, rawRequest.Metadata.WorkflowOwner) + } + + if hex.EncodeToString(reportMetadata.WorkflowName[:]) != rawRequest.Metadata.WorkflowName { + return r, fmt.Errorf("WorkflowName in the report does not match WorkflowName in the request metadata. Report WorkflowName: %+v, request WorkflowName: %+v", reportMetadata.WorkflowName, rawRequest.Metadata.WorkflowName) + } + + if hex.EncodeToString(reportMetadata.WorkflowCID[:]) != rawRequest.Metadata.WorkflowID { + return r, fmt.Errorf("WorkflowID in the report does not match WorkflowID in the request metadata. Report WorkflowID: %+v, request WorkflowID: %+v", reportMetadata.WorkflowCID, rawRequest.Metadata.WorkflowID) + } + + if !bytes.Equal(reportMetadata.ReportID[:], r.Inputs.SignedReport.ID) { + return r, fmt.Errorf("ReportID in the report does not match ReportID in the inputs. reportMetadata.ReportID: %x, Inputs.SignedReport.ID: %x", reportMetadata.ReportID, r.Inputs.SignedReport.ID) + } -func success() <-chan capabilities.CapabilityResponse { - callback := make(chan capabilities.CapabilityResponse) - go func() { - callback <- capabilities.CapabilityResponse{} - close(callback) - }() - return callback + return r, nil } -func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { +func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { // Bind to the contract address on the write path. // Bind() requires a connection to the node's RPCs and // cannot be run during initialization. if !cap.bound { cap.lggr.Debugw("Binding to forwarder address") - err := cap.cr.Bind(ctx, []commontypes.BoundContract{{ - Address: cap.forwarderAddress, - Name: "forwarder", - }}) + err := cap.cr.Bind(ctx, []commontypes.BoundContract{cap.binding}) if err != nil { - return nil, err + return capabilities.CapabilityResponse{}, err } cap.bound = true } @@ -199,12 +217,12 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap request, err := evaluate(rawRequest) if err != nil { - return nil, err + return capabilities.CapabilityResponse{}, err } rawExecutionID, err := hex.DecodeString(request.Metadata.WorkflowExecutionID) if err != nil { - return nil, err + return capabilities.CapabilityResponse{}, err } // Check whether value was already transmitted on chain @@ -218,33 +236,37 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap ReportId: request.Inputs.SignedReport.ID, } var transmissionInfo TransmissionInfo - if err = cap.cr.GetLatestValue(ctx, "forwarder", "getTransmissionInfo", primitives.Unconfirmed, queryInputs, &transmissionInfo); err != nil { - return nil, fmt.Errorf("failed to getTransmissionInfo latest value: %w", err) + if err = cap.cr.GetLatestValue(ctx, cap.binding.ReadIdentifier("getTransmissionInfo"), primitives.Unconfirmed, queryInputs, &transmissionInfo); err != nil { + return capabilities.CapabilityResponse{}, fmt.Errorf("failed to getTransmissionInfo latest value: %w", err) } switch { case transmissionInfo.State == 0: // NOT_ATTEMPTED - cap.lggr.Infow("non-empty report - tranasmission not attempted - attempting to push to txmgr", "request", request, "reportLen", len(request.Inputs.SignedReport.Report), "reportContextLen", len(request.Inputs.SignedReport.Context), "nSignatures", len(request.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID) + cap.lggr.Infow("non-empty report - transmission not attempted - attempting to push to txmgr", "request", request, "reportLen", len(request.Inputs.SignedReport.Report), "reportContextLen", len(request.Inputs.SignedReport.Context), "nSignatures", len(request.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID) case transmissionInfo.State == 1: // SUCCEEDED - cap.lggr.Infow("returning without a tranmission attempt - report already onchain ", "executionID", request.Metadata.WorkflowExecutionID) - return success(), nil + cap.lggr.Infow("returning without a transmission attempt - report already onchain ", "executionID", request.Metadata.WorkflowExecutionID) + return capabilities.CapabilityResponse{}, nil case transmissionInfo.State == 2: // INVALID_RECEIVER - cap.lggr.Infow("returning without a tranmission attempt - transmission already attempted, receiver was marked as invalid", "executionID", request.Metadata.WorkflowExecutionID) - return success(), nil + cap.lggr.Infow("returning without a transmission attempt - transmission already attempted, receiver was marked as invalid", "executionID", request.Metadata.WorkflowExecutionID) + return capabilities.CapabilityResponse{}, nil case transmissionInfo.State == 3: // FAILED - if transmissionInfo.GasLimit.Uint64() > cap.receiverGasMinimum { - cap.lggr.Infow("returning without a tranmission attempt - transmission already attempted and failed, sufficient gas was provided", "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", cap.receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) - return success(), nil + receiverGasMinimum := cap.receiverGasMinimum + if request.Config.GasLimit != nil { + receiverGasMinimum = *request.Config.GasLimit - ForwarderContractLogicGasCost + } + if transmissionInfo.GasLimit.Uint64() > receiverGasMinimum { + cap.lggr.Infow("returning without a transmission attempt - transmission already attempted and failed, sufficient gas was provided", "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) + return capabilities.CapabilityResponse{}, nil } else { - cap.lggr.Infow("non-empty report - retrying a failed transmission - attempting to push to txmgr", "request", request, "reportLen", len(request.Inputs.SignedReport.Report), "reportContextLen", len(request.Inputs.SignedReport.Context), "nSignatures", len(request.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", cap.receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) + cap.lggr.Infow("non-empty report - retrying a failed transmission - attempting to push to txmgr", "request", request, "reportLen", len(request.Inputs.SignedReport.Report), "reportContextLen", len(request.Inputs.SignedReport.Context), "nSignatures", len(request.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) } default: - return nil, fmt.Errorf("unexpected transmission state: %v", transmissionInfo.State) + return capabilities.CapabilityResponse{}, fmt.Errorf("unexpected transmission state: %v", transmissionInfo.State) } txID, err := uuid.NewUUID() // NOTE: CW expects us to generate an ID, rather than return one if err != nil { - return nil, err + return capabilities.CapabilityResponse{}, err } // Note: The codec that ChainWriter uses to encode the parameters for the contract ABI cannot handle @@ -271,12 +293,23 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap cap.lggr.Debugw("Transaction raw report", "report", hex.EncodeToString(req.RawReport)) meta := commontypes.TxMeta{WorkflowExecutionID: &request.Metadata.WorkflowExecutionID} + if request.Config.GasLimit != nil { + meta.GasLimit = new(big.Int).SetUint64(*request.Config.GasLimit) + } + value := big.NewInt(0) if err := cap.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), cap.forwarderAddress, &meta, value); err != nil { - return nil, err + if !commontypes.ErrSettingTransactionGasLimitNotSupported.Is(err) { + return capabilities.CapabilityResponse{}, fmt.Errorf("failed to submit transaction: %w", err) + } + meta.GasLimit = nil + if err := cap.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), cap.forwarderAddress, &meta, value); err != nil { + return capabilities.CapabilityResponse{}, fmt.Errorf("failed to submit transaction: %w", err) + } } + cap.lggr.Debugw("Transaction submitted", "request", request, "transaction", txID) - return success(), nil + return capabilities.CapabilityResponse{}, nil } func (cap *WriteTarget) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index 522fee32513..499f4f9b29b 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -14,7 +14,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -26,7 +28,7 @@ func TestWriteTarget(t *testing.T) { ctx := context.Background() cw := mocks.NewChainWriter(t) - cr := mocks.NewChainReader(t) + cr := mocks.NewContractValueGetter(t) forwarderA := testutils.NewAddress() forwarderAddr := forwarderA.Hex() @@ -39,6 +41,7 @@ func TestWriteTarget(t *testing.T) { }) require.NoError(t, err) + reportID := [2]byte{0x00, 0x01} reportMetadata := targets.ReportV1Metadata{ Version: 1, WorkflowExecutionID: [32]byte{}, @@ -48,7 +51,7 @@ func TestWriteTarget(t *testing.T) { WorkflowCID: [32]byte{}, WorkflowName: [10]byte{}, WorkflowOwner: [20]byte{}, - ReportID: [2]byte{}, + ReportID: reportID, } reportMetadataBytes, err := reportMetadata.Encode() @@ -58,6 +61,8 @@ func TestWriteTarget(t *testing.T) { "signed_report": map[string]any{ "report": reportMetadataBytes, "signatures": [][]byte{}, + "context": []byte{4, 5}, + "id": reportID[:], }, }) require.NoError(t, err) @@ -69,15 +74,15 @@ func TestWriteTarget(t *testing.T) { WorkflowExecutionID: hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]), } - cr.On("Bind", mock.Anything, []types.BoundContract{ - { - Address: forwarderAddr, - Name: "forwarder", - }, - }).Return(nil) + binding := types.BoundContract{ + Address: forwarderAddr, + Name: "forwarder", + } - cr.On("GetLatestValue", mock.Anything, "forwarder", "getTransmissionInfo", mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(5).(*targets.TransmissionInfo) + cr.On("Bind", mock.Anything, []types.BoundContract{binding}).Return(nil) + + cr.EXPECT().GetLatestValue(mock.Anything, binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(_ context.Context, _ string, _ primitives.ConfidenceLevel, _, retVal any) { + transmissionInfo := retVal.(*targets.TransmissionInfo) *transmissionInfo = targets.TransmissionInfo{ GasLimit: big.NewInt(0), InvalidReceiver: false, @@ -86,7 +91,7 @@ func TestWriteTarget(t *testing.T) { TransmissionId: [32]byte{}, Transmitter: common.HexToAddress("0x0"), } - }).Once() + }) cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once() @@ -97,31 +102,80 @@ func TestWriteTarget(t *testing.T) { Inputs: validInputs, } - ch, err2 := writeTarget.Execute(ctx, req) + response, err2 := writeTarget.Execute(ctx, req) require.NoError(t, err2) - response := <-ch require.NotNil(t, response) }) - t.Run("fails when ChainReader's GetLatestValue returns error", func(t *testing.T) { + t.Run("fails when ChainWriter's SubmitTransaction returns error", func(t *testing.T) { req := capabilities.CapabilityRequest{ Metadata: validMetadata, Config: config, Inputs: validInputs, } - cr.On("GetLatestValue", mock.Anything, "forwarder", "getTransmissionInfo", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("reader error")) + cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, mock.Anything, mock.Anything).Return(errors.New("writer error")) _, err = writeTarget.Execute(ctx, req) require.Error(t, err) }) - t.Run("fails when ChainWriter's SubmitTransaction returns error", func(t *testing.T) { + t.Run("passes gas limit set on config to the chain writer", func(t *testing.T) { + configGasLimit, err2 := values.NewMap(map[string]any{ + "Address": forwarderAddr, + "GasLimit": 500000, + }) + require.NoError(t, err2) + req := capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: configGasLimit, + Inputs: validInputs, + } + + meta := types.TxMeta{WorkflowExecutionID: &req.Metadata.WorkflowExecutionID, GasLimit: big.NewInt(500000)} + cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, &meta, mock.Anything).Return(types.ErrSettingTransactionGasLimitNotSupported) + + _, err2 = writeTarget.Execute(ctx, req) + require.Error(t, err2) + }) + + t.Run("retries without gas limit when ChainWriter's SubmitTransaction returns error due to gas limit not supported", func(t *testing.T) { + configGasLimit, err2 := values.NewMap(map[string]any{ + "Address": forwarderAddr, + "GasLimit": 500000, + }) + require.NoError(t, err2) + req := capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: configGasLimit, + Inputs: validInputs, + } + + meta := types.TxMeta{WorkflowExecutionID: &req.Metadata.WorkflowExecutionID, GasLimit: big.NewInt(500000)} + cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, &meta, mock.Anything).Return(types.ErrSettingTransactionGasLimitNotSupported) + meta = types.TxMeta{WorkflowExecutionID: &req.Metadata.WorkflowExecutionID} + cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, &meta, mock.Anything).Return(nil) + + configGasLimit, err = values.NewMap(map[string]any{ + "Address": forwarderAddr, + }) + require.NoError(t, err) + req = capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: configGasLimit, + Inputs: validInputs, + } + + _, err2 = writeTarget.Execute(ctx, req) + require.Error(t, err2) + }) + + t.Run("fails when ChainReader's GetLatestValue returns error", func(t *testing.T) { req := capabilities.CapabilityRequest{ Metadata: validMetadata, Config: config, Inputs: validInputs, } - cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, mock.Anything, mock.Anything).Return(errors.New("writer error")) + cr.EXPECT().GetLatestValue(mock.Anything, binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(errors.New("reader error")) _, err = writeTarget.Execute(ctx, req) require.Error(t, err) diff --git a/core/capabilities/transmission/local_target_capability.go b/core/capabilities/transmission/local_target_capability.go index 1240d3a0e7f..637aea4523f 100644 --- a/core/capabilities/transmission/local_target_capability.go +++ b/core/capabilities/transmission/local_target_capability.go @@ -27,7 +27,7 @@ func NewLocalTargetCapability(lggr logger.Logger, capabilityID string, localDON } } -func (l *LocalTargetCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { +func (l *LocalTargetCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { if l.localNode.PeerID == nil || l.localNode.WorkflowDON.ID == 0 { l.lggr.Debugf("empty DON info, executing immediately") return l.TargetCapability.Execute(ctx, req) @@ -40,17 +40,17 @@ func (l *LocalTargetCapability) Execute(ctx context.Context, req capabilities.Ca peerIDToTransmissionDelay, err := GetPeerIDToTransmissionDelay(l.localNode.WorkflowDON.Members, req) if err != nil { - return nil, fmt.Errorf("capability id: %s failed to get peer ID to transmission delay map: %w", l.capabilityID, err) + return capabilities.CapabilityResponse{}, fmt.Errorf("capability id: %s failed to get peer ID to transmission delay map: %w", l.capabilityID, err) } delay, existsForPeerID := peerIDToTransmissionDelay[*l.localNode.PeerID] if !existsForPeerID { - return nil, nil + return capabilities.CapabilityResponse{}, nil } select { case <-ctx.Done(): - return nil, ctx.Err() + return capabilities.CapabilityResponse{}, ctx.Err() case <-time.After(delay): return l.TargetCapability.Execute(ctx, req) } diff --git a/core/capabilities/transmission/local_target_capability_test.go b/core/capabilities/transmission/local_target_capability_test.go index 93bf708ccef..67f22753bda 100644 --- a/core/capabilities/transmission/local_target_capability_test.go +++ b/core/capabilities/transmission/local_target_capability_test.go @@ -54,8 +54,8 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { name: "position 0; oneAtATime", position: 0, schedule: "oneAtATime", - low: 300 * time.Millisecond, - high: 400 * time.Millisecond, + low: 200 * time.Millisecond, + high: 300 * time.Millisecond, }, { name: "position 1; oneAtATime", @@ -68,15 +68,15 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { name: "position 2; oneAtATime", position: 2, schedule: "oneAtATime", - low: 0 * time.Millisecond, - high: 100 * time.Millisecond, + low: 300 * time.Millisecond, + high: 400 * time.Millisecond, }, { name: "position 3; oneAtATime", position: 3, schedule: "oneAtATime", - low: 100 * time.Millisecond, - high: 300 * time.Millisecond, + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, }, { name: "position 0; allAtOnce", @@ -121,8 +121,8 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { req := capabilities.CapabilityRequest{ Config: m, Metadata: capabilities.RequestMetadata{ - WorkflowID: "mock-workflow-id", - WorkflowExecutionID: "mock-execution-id-1", + WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0", + WorkflowExecutionID: "32c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce1", }, } @@ -162,7 +162,7 @@ func randKey() [32]byte { type mockCapability struct { capabilities.CapabilityInfo - capabilities.CallbackExecutable + capabilities.Executable response chan capabilities.CapabilityResponse transform func(capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) } @@ -175,18 +175,14 @@ func newMockCapability(info capabilities.CapabilityInfo, transform func(capabili } } -func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { cr, err := m.transform(req) if err != nil { - return nil, err + return capabilities.CapabilityResponse{}, err } - ch := make(chan capabilities.CapabilityResponse, 10) - m.response <- cr - ch <- cr - close(ch) - return ch, nil + return cr, nil } func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { diff --git a/core/capabilities/transmission/transmission.go b/core/capabilities/transmission/transmission.go index b41be5bcaa5..88ce0fa3edd 100644 --- a/core/capabilities/transmission/transmission.go +++ b/core/capabilities/transmission/transmission.go @@ -4,10 +4,10 @@ import ( "fmt" "time" - "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/permutation" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -56,8 +56,12 @@ func GetPeerIDToTransmissionDelay(donPeerIDs []types.PeerID, req capabilities.Ca return nil, fmt.Errorf("failed to extract transmission config from request: %w", err) } - if req.Metadata.WorkflowID == "" || req.Metadata.WorkflowExecutionID == "" { - return nil, errors.New("workflow ID and workflow execution ID must be set in request metadata") + if err = validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowID); err != nil { + return nil, fmt.Errorf("workflow ID is invalid: %w", err) + } + + if err = validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowExecutionID); err != nil { + return nil, fmt.Errorf("workflow execution ID is invalid: %w", err) } transmissionID := req.Metadata.WorkflowID + req.Metadata.WorkflowExecutionID diff --git a/core/capabilities/transmission/transmission_test.go b/core/capabilities/transmission/transmission_test.go index fba233eadb0..aaa367e78cf 100644 --- a/core/capabilities/transmission/transmission_test.go +++ b/core/capabilities/transmission/transmission_test.go @@ -36,20 +36,21 @@ func Test_GetPeerIDToTransmissionDelay(t *testing.T) { "one", "oneAtATime", "100ms", - "mock-execution-id", + "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0", map[string]time.Duration{ "one": 300 * time.Millisecond, - "two": 100 * time.Millisecond, - "three": 0 * time.Millisecond, + "two": 0 * time.Millisecond, + "three": 100 * time.Millisecond, "four": 200 * time.Millisecond, }, }, + { "TestAllAtOnce", "one", "allAtOnce", "100ms", - "mock-execution-id", + "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0", map[string]time.Duration{ "one": 0 * time.Millisecond, "two": 0 * time.Millisecond, @@ -57,17 +58,18 @@ func Test_GetPeerIDToTransmissionDelay(t *testing.T) { "four": 0 * time.Millisecond, }, }, + { "TestOneAtATimeWithDifferentExecutionID", "one", "oneAtATime", "100ms", - "mock-execution-id2", + "16c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce1", map[string]time.Duration{ - "one": 0 * time.Millisecond, - "two": 200 * time.Millisecond, - "three": 100 * time.Millisecond, - "four": 300 * time.Millisecond, + "one": 300 * time.Millisecond, + "two": 100 * time.Millisecond, + "three": 200 * time.Millisecond, + "four": 0 * time.Millisecond, }, }, } @@ -83,7 +85,7 @@ func Test_GetPeerIDToTransmissionDelay(t *testing.T) { capabilityRequest := capabilities.CapabilityRequest{ Config: transmissionCfg, Metadata: capabilities.RequestMetadata{ - WorkflowID: "mock-workflow-id", + WorkflowID: "17c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0", WorkflowExecutionID: tc.workflowExecutionID, }, } diff --git a/core/capabilities/triggers/logevent/logeventcap/event_trigger-schema.json b/core/capabilities/triggers/logevent/logeventcap/event_trigger-schema.json new file mode 100644 index 00000000000..a60d8823582 --- /dev/null +++ b/core/capabilities/triggers/logevent/logeventcap/event_trigger-schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent/logeventcap/log-event-trigger", + "$defs": { + "head": { + "type": "object", + "properties": { + "Height": { + "type": "string", + "minLength": 1 + }, + "Hash": { + "type": "string", + "minLength": 1 + }, + "Timestamp": { + "type": "integer", + "minimum": 0 + } + } + }, + "config": { + "type": "object", + "properties": { + "contractName": { + "type": "string", + "minLength": 1 + }, + "contractAddress": { + "type": "string", + "minLength": 1 + }, + "contractEventName": { + "type": "string", + "minLength": 1 + }, + "contractReaderConfig": { + "type": "object", + "properties": { + "contracts": { + "type": "object" + } + }, + "required": ["contracts"] + } + }, + "required": ["contractName", "contractAddress", "contractEventName", "contractReaderConfig"] + }, + "output": { + "type": "object", + "properties": { + "Cursor": { + "type": "string", + "minLength": 1 + }, + "Head": { + "$ref": "#/$defs/head" + }, + "Data": { + "type": "object" + } + }, + "required": ["Cursor", "Head", "Data"] + } + }, + "type": "object", + "properties": { + "Config": { + "$ref": "#/$defs/config" + }, + "Outputs": { + "$ref": "#/$defs/output" + } + } + } \ No newline at end of file diff --git a/core/capabilities/triggers/logevent/logeventcap/event_trigger_generated.go b/core/capabilities/triggers/logevent/logeventcap/event_trigger_generated.go new file mode 100644 index 00000000000..23376958309 --- /dev/null +++ b/core/capabilities/triggers/logevent/logeventcap/event_trigger_generated.go @@ -0,0 +1,160 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package logeventcap + +import ( + "encoding/json" + "fmt" +) + +type Config struct { + // ContractAddress corresponds to the JSON schema field "contractAddress". + ContractAddress string `json:"contractAddress" yaml:"contractAddress" mapstructure:"contractAddress"` + + // ContractEventName corresponds to the JSON schema field "contractEventName". + ContractEventName string `json:"contractEventName" yaml:"contractEventName" mapstructure:"contractEventName"` + + // ContractName corresponds to the JSON schema field "contractName". + ContractName string `json:"contractName" yaml:"contractName" mapstructure:"contractName"` + + // ContractReaderConfig corresponds to the JSON schema field + // "contractReaderConfig". + ContractReaderConfig ConfigContractReaderConfig `json:"contractReaderConfig" yaml:"contractReaderConfig" mapstructure:"contractReaderConfig"` +} + +type ConfigContractReaderConfig struct { + // Contracts corresponds to the JSON schema field "contracts". + Contracts ConfigContractReaderConfigContracts `json:"contracts" yaml:"contracts" mapstructure:"contracts"` +} + +type ConfigContractReaderConfigContracts map[string]interface{} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ConfigContractReaderConfig) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["contracts"]; raw != nil && !ok { + return fmt.Errorf("field contracts in ConfigContractReaderConfig: required") + } + type Plain ConfigContractReaderConfig + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = ConfigContractReaderConfig(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Config) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["contractAddress"]; raw != nil && !ok { + return fmt.Errorf("field contractAddress in Config: required") + } + if _, ok := raw["contractEventName"]; raw != nil && !ok { + return fmt.Errorf("field contractEventName in Config: required") + } + if _, ok := raw["contractName"]; raw != nil && !ok { + return fmt.Errorf("field contractName in Config: required") + } + if _, ok := raw["contractReaderConfig"]; raw != nil && !ok { + return fmt.Errorf("field contractReaderConfig in Config: required") + } + type Plain Config + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if len(plain.ContractAddress) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "contractAddress", 1) + } + if len(plain.ContractEventName) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "contractEventName", 1) + } + if len(plain.ContractName) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "contractName", 1) + } + *j = Config(plain) + return nil +} + +type Head struct { + // Hash corresponds to the JSON schema field "Hash". + Hash *string `json:"Hash,omitempty" yaml:"Hash,omitempty" mapstructure:"Hash,omitempty"` + + // Height corresponds to the JSON schema field "Height". + Height *string `json:"Height,omitempty" yaml:"Height,omitempty" mapstructure:"Height,omitempty"` + + // Timestamp corresponds to the JSON schema field "Timestamp". + Timestamp *uint64 `json:"Timestamp,omitempty" yaml:"Timestamp,omitempty" mapstructure:"Timestamp,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Head) UnmarshalJSON(b []byte) error { + type Plain Head + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.Hash != nil && len(*plain.Hash) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "Hash", 1) + } + if plain.Height != nil && len(*plain.Height) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "Height", 1) + } + *j = Head(plain) + return nil +} + +type Output struct { + // Cursor corresponds to the JSON schema field "Cursor". + Cursor string `json:"Cursor" yaml:"Cursor" mapstructure:"Cursor"` + + // Data corresponds to the JSON schema field "Data". + Data OutputData `json:"Data" yaml:"Data" mapstructure:"Data"` + + // Head corresponds to the JSON schema field "Head". + Head Head `json:"Head" yaml:"Head" mapstructure:"Head"` +} + +type OutputData map[string]interface{} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Output) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["Cursor"]; raw != nil && !ok { + return fmt.Errorf("field Cursor in Output: required") + } + if _, ok := raw["Data"]; raw != nil && !ok { + return fmt.Errorf("field Data in Output: required") + } + if _, ok := raw["Head"]; raw != nil && !ok { + return fmt.Errorf("field Head in Output: required") + } + type Plain Output + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if len(plain.Cursor) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "Cursor", 1) + } + *j = Output(plain) + return nil +} + +type Trigger struct { + // Config corresponds to the JSON schema field "Config". + Config *Config `json:"Config,omitempty" yaml:"Config,omitempty" mapstructure:"Config,omitempty"` + + // Outputs corresponds to the JSON schema field "Outputs". + Outputs *Output `json:"Outputs,omitempty" yaml:"Outputs,omitempty" mapstructure:"Outputs,omitempty"` +} diff --git a/core/capabilities/triggers/logevent/logeventcap/gen.go b/core/capabilities/triggers/logevent/logeventcap/gen.go new file mode 100644 index 00000000000..09655a9a113 --- /dev/null +++ b/core/capabilities/triggers/logevent/logeventcap/gen.go @@ -0,0 +1,5 @@ +package logeventcap + +import _ "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd" // Required so that the tool is available to be run in go generate below. + +//go:generate go run github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/generate-types --dir $GOFILE diff --git a/core/capabilities/triggers/logevent/logeventcap/logeventcaptest/trigger_mock_generated.go b/core/capabilities/triggers/logevent/logeventcap/logeventcaptest/trigger_mock_generated.go new file mode 100644 index 00000000000..f91dbc6e2b3 --- /dev/null +++ b/core/capabilities/triggers/logevent/logeventcap/logeventcaptest/trigger_mock_generated.go @@ -0,0 +1,17 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package logeventcaptest + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk/testutils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent/logeventcap" +) + +// Trigger registers a new capability mock with the runner +func Trigger(runner *testutils.Runner, id string, fn func() (logeventcap.Output, error)) *testutils.TriggerMock[logeventcap.Output] { + mock := testutils.MockTrigger[logeventcap.Output](id, fn) + runner.MockCapability(id, nil, mock) + return mock +} diff --git a/core/capabilities/triggers/logevent/logeventcap/trigger_builders_generated.go b/core/capabilities/triggers/logevent/logeventcap/trigger_builders_generated.go new file mode 100644 index 00000000000..8788f005d63 --- /dev/null +++ b/core/capabilities/triggers/logevent/logeventcap/trigger_builders_generated.go @@ -0,0 +1,156 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package logeventcap + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func (cfg Config) New(w *sdk.WorkflowSpecFactory, id string) OutputCap { + ref := "trigger" + def := sdk.StepDefinition{ + ID: id, Ref: ref, + Inputs: sdk.StepInputs{}, + Config: map[string]any{ + "contractAddress": cfg.ContractAddress, + "contractEventName": cfg.ContractEventName, + "contractName": cfg.ContractName, + "contractReaderConfig": cfg.ContractReaderConfig, + }, + CapabilityType: capabilities.CapabilityTypeTrigger, + } + + step := sdk.Step[Output]{Definition: def} + return OutputCapFromStep(w, step) +} + +type HeadCap interface { + sdk.CapDefinition[Head] + Hash() sdk.CapDefinition[string] + Height() sdk.CapDefinition[string] + Timestamp() sdk.CapDefinition[uint64] + private() +} + +// HeadCapFromStep should only be called from generated code to assure type safety +func HeadCapFromStep(w *sdk.WorkflowSpecFactory, step sdk.Step[Head]) HeadCap { + raw := step.AddTo(w) + return &head{CapDefinition: raw} +} + +type head struct { + sdk.CapDefinition[Head] +} + +func (*head) private() {} +func (c *head) Hash() sdk.CapDefinition[string] { + return sdk.AccessField[Head, string](c.CapDefinition, "Hash") +} +func (c *head) Height() sdk.CapDefinition[string] { + return sdk.AccessField[Head, string](c.CapDefinition, "Height") +} +func (c *head) Timestamp() sdk.CapDefinition[uint64] { + return sdk.AccessField[Head, uint64](c.CapDefinition, "Timestamp") +} + +func NewHeadFromFields( + hash sdk.CapDefinition[string], + height sdk.CapDefinition[string], + timestamp sdk.CapDefinition[uint64]) HeadCap { + return &simpleHead{ + CapDefinition: sdk.ComponentCapDefinition[Head]{ + "Hash": hash.Ref(), + "Height": height.Ref(), + "Timestamp": timestamp.Ref(), + }, + hash: hash, + height: height, + timestamp: timestamp, + } +} + +type simpleHead struct { + sdk.CapDefinition[Head] + hash sdk.CapDefinition[string] + height sdk.CapDefinition[string] + timestamp sdk.CapDefinition[uint64] +} + +func (c *simpleHead) Hash() sdk.CapDefinition[string] { + return c.hash +} +func (c *simpleHead) Height() sdk.CapDefinition[string] { + return c.height +} +func (c *simpleHead) Timestamp() sdk.CapDefinition[uint64] { + return c.timestamp +} + +func (c *simpleHead) private() {} + +type OutputCap interface { + sdk.CapDefinition[Output] + Cursor() sdk.CapDefinition[string] + Data() OutputDataCap + Head() HeadCap + private() +} + +// OutputCapFromStep should only be called from generated code to assure type safety +func OutputCapFromStep(w *sdk.WorkflowSpecFactory, step sdk.Step[Output]) OutputCap { + raw := step.AddTo(w) + return &output{CapDefinition: raw} +} + +type output struct { + sdk.CapDefinition[Output] +} + +func (*output) private() {} +func (c *output) Cursor() sdk.CapDefinition[string] { + return sdk.AccessField[Output, string](c.CapDefinition, "Cursor") +} +func (c *output) Data() OutputDataCap { + return OutputDataCap(sdk.AccessField[Output, OutputData](c.CapDefinition, "Data")) +} +func (c *output) Head() HeadCap { + return &head{CapDefinition: sdk.AccessField[Output, Head](c.CapDefinition, "Head")} +} + +func NewOutputFromFields( + cursor sdk.CapDefinition[string], + data OutputDataCap, + head HeadCap) OutputCap { + return &simpleOutput{ + CapDefinition: sdk.ComponentCapDefinition[Output]{ + "Cursor": cursor.Ref(), + "Data": data.Ref(), + "Head": head.Ref(), + }, + cursor: cursor, + data: data, + head: head, + } +} + +type simpleOutput struct { + sdk.CapDefinition[Output] + cursor sdk.CapDefinition[string] + data OutputDataCap + head HeadCap +} + +func (c *simpleOutput) Cursor() sdk.CapDefinition[string] { + return c.cursor +} +func (c *simpleOutput) Data() OutputDataCap { + return c.data +} +func (c *simpleOutput) Head() HeadCap { + return c.head +} + +func (c *simpleOutput) private() {} + +type OutputDataCap sdk.CapDefinition[OutputData] diff --git a/core/capabilities/triggers/logevent/service.go b/core/capabilities/triggers/logevent/service.go new file mode 100644 index 00000000000..8a59865e3f5 --- /dev/null +++ b/core/capabilities/triggers/logevent/service.go @@ -0,0 +1,161 @@ +package logevent + +import ( + "context" + "errors" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent/logeventcap" +) + +const ID = "log-event-trigger-%s-%s@1.0.0" + +const defaultSendChannelBufferSize = 1000 + +// Log Event Trigger Capability Input +type Input struct { +} + +// Log Event Trigger Capabilities Manager +// Manages different log event triggers using an underlying triggerStore +type TriggerService struct { + services.StateMachine + capabilities.CapabilityInfo + capabilities.Validator[logeventcap.Config, Input, capabilities.TriggerResponse] + lggr logger.Logger + triggers CapabilitiesStore[logEventTrigger, capabilities.TriggerResponse] + relayer core.Relayer + logEventConfig Config + stopCh services.StopChan +} + +// Common capability level config across all workflows +type Config struct { + ChainID string `json:"chainId"` + Network string `json:"network"` + LookbackBlocks uint64 `json:"lookbakBlocks"` + PollPeriod uint32 `json:"pollPeriod"` + QueryCount uint64 `json:"queryCount"` +} + +func (config Config) Version(capabilityVersion string) string { + return fmt.Sprintf(capabilityVersion, config.Network, config.ChainID) +} + +var _ capabilities.TriggerCapability = (*TriggerService)(nil) +var _ services.Service = &TriggerService{} + +// Creates a new Cron Trigger Service. +// Scheduling will commence on calling .Start() +func NewTriggerService(ctx context.Context, + lggr logger.Logger, + relayer core.Relayer, + logEventConfig Config) (*TriggerService, error) { + l := logger.Named(lggr, "LogEventTriggerCapabilityService") + + logEventStore := NewCapabilitiesStore[logEventTrigger, capabilities.TriggerResponse]() + + s := &TriggerService{ + lggr: l, + triggers: logEventStore, + relayer: relayer, + logEventConfig: logEventConfig, + stopCh: make(services.StopChan), + } + var err error + s.CapabilityInfo, err = s.Info(ctx) + if err != nil { + return s, err + } + s.Validator = capabilities.NewValidator[logeventcap.Config, Input, capabilities.TriggerResponse](capabilities.ValidatorArgs{Info: s.CapabilityInfo}) + return s, nil +} + +func (s *TriggerService) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return capabilities.NewCapabilityInfo( + s.logEventConfig.Version(ID), + capabilities.CapabilityTypeTrigger, + "A trigger that listens for specific contract log events and starts a workflow run.", + ) +} + +// Register a new trigger +// Can register triggers before the service is actively scheduling +func (s *TriggerService) RegisterTrigger(ctx context.Context, + req capabilities.TriggerRegistrationRequest) (<-chan capabilities.TriggerResponse, error) { + if req.Config == nil { + return nil, errors.New("config is required to register a log event trigger") + } + reqConfig, err := s.ValidateConfig(req.Config) + if err != nil { + return nil, err + } + // Add log event trigger with Contract details to CapabilitiesStore + var respCh chan capabilities.TriggerResponse + ok := s.IfNotStopped(func() { + respCh, err = s.triggers.InsertIfNotExists(req.TriggerID, func() (*logEventTrigger, chan capabilities.TriggerResponse, error) { + l, ch, tErr := newLogEventTrigger(ctx, s.lggr, req.Metadata.WorkflowID, reqConfig, s.logEventConfig, s.relayer) + if tErr != nil { + return l, ch, tErr + } + tErr = l.Start(ctx) + return l, ch, tErr + }) + }) + if !ok { + return nil, fmt.Errorf("cannot create new trigger since LogEventTriggerCapabilityService has been stopped") + } + if err != nil { + return nil, fmt.Errorf("create new trigger failed %w", err) + } + s.lggr.Infow("RegisterTrigger", "triggerId", req.TriggerID, "WorkflowID", req.Metadata.WorkflowID) + return respCh, nil +} + +func (s *TriggerService) UnregisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) error { + trigger, ok := s.triggers.Read(req.TriggerID) + if !ok { + return fmt.Errorf("triggerId %s not found", req.TriggerID) + } + // Close callback channel and stop log event trigger listener + err := trigger.Close() + if err != nil { + return fmt.Errorf("error closing trigger %s (chainID %s): %w", req.TriggerID, s.logEventConfig.ChainID, err) + } + // Remove from triggers context + s.triggers.Delete(req.TriggerID) + s.lggr.Infow("UnregisterTrigger", "triggerId", req.TriggerID, "WorkflowID", req.Metadata.WorkflowID) + return nil +} + +// Start the service. +func (s *TriggerService) Start(ctx context.Context) error { + return s.StartOnce("LogEventTriggerCapabilityService", func() error { + s.lggr.Info("Starting LogEventTriggerCapabilityService") + return nil + }) +} + +// Close stops the Service. +// After this call the Service cannot be started again, +// The service will need to be re-built to start scheduling again. +func (s *TriggerService) Close() error { + return s.StopOnce("LogEventTriggerCapabilityService", func() error { + s.lggr.Infow("Stopping LogEventTriggerCapabilityService") + triggers := s.triggers.ReadAll() + return services.MultiCloser(triggers).Close() + }) +} + +func (s *TriggerService) HealthReport() map[string]error { + return map[string]error{s.Name(): s.Healthy()} +} + +func (s *TriggerService) Name() string { + return s.lggr.Name() +} diff --git a/core/capabilities/triggers/logevent/store.go b/core/capabilities/triggers/logevent/store.go new file mode 100644 index 00000000000..ac9d3741cd1 --- /dev/null +++ b/core/capabilities/triggers/logevent/store.go @@ -0,0 +1,82 @@ +package logevent + +import ( + "fmt" + "sync" +) + +type RegisterCapabilityFn[T any, Resp any] func() (*T, chan Resp, error) + +// Interface of the capabilities store +type CapabilitiesStore[T any, Resp any] interface { + Read(capabilityID string) (value *T, ok bool) + ReadAll() (values []*T) + Write(capabilityID string, value *T) + InsertIfNotExists(capabilityID string, fn RegisterCapabilityFn[T, Resp]) (chan Resp, error) + Delete(capabilityID string) +} + +// Implementation for the CapabilitiesStore interface +type capabilitiesStore[T any, Resp any] struct { + mu sync.RWMutex + capabilities map[string]*T +} + +var _ CapabilitiesStore[string, string] = (CapabilitiesStore[string, string])(nil) + +// Constructor for capabilitiesStore struct implementing CapabilitiesStore interface +func NewCapabilitiesStore[T any, Resp any]() CapabilitiesStore[T, Resp] { + return &capabilitiesStore[T, Resp]{ + capabilities: map[string]*T{}, + } +} + +func (cs *capabilitiesStore[T, Resp]) Read(capabilityID string) (value *T, ok bool) { + cs.mu.RLock() + defer cs.mu.RUnlock() + trigger, ok := cs.capabilities[capabilityID] + return trigger, ok +} + +func (cs *capabilitiesStore[T, Resp]) ReadAll() (values []*T) { + cs.mu.RLock() + defer cs.mu.RUnlock() + vals := make([]*T, 0) + for _, v := range cs.capabilities { + vals = append(vals, v) + } + return vals +} + +func (cs *capabilitiesStore[T, Resp]) Write(capabilityID string, value *T) { + cs.mu.Lock() + defer cs.mu.Unlock() + cs.capabilities[capabilityID] = value +} + +func (cs *capabilitiesStore[T, Resp]) InsertIfNotExists(capabilityID string, fn RegisterCapabilityFn[T, Resp]) (chan Resp, error) { + cs.mu.RLock() + _, ok := cs.capabilities[capabilityID] + cs.mu.RUnlock() + if ok { + return nil, fmt.Errorf("capabilityID %v already exists", capabilityID) + } + cs.mu.Lock() + defer cs.mu.Unlock() + _, ok = cs.capabilities[capabilityID] + if ok { + return nil, fmt.Errorf("capabilityID %v already exists", capabilityID) + } + value, respCh, err := fn() + if err != nil { + return nil, fmt.Errorf("error registering capability: %v", err) + } + cs.capabilities[capabilityID] = value + return respCh, nil +} + +func (cs *capabilitiesStore[T, Resp]) Delete(capabilityID string) { + cs.mu.Lock() + defer cs.mu.Unlock() + delete(cs.capabilities, capabilityID) +} diff --git a/core/capabilities/triggers/logevent/trigger.go b/core/capabilities/triggers/logevent/trigger.go new file mode 100644 index 00000000000..1ce8ee5fd78 --- /dev/null +++ b/core/capabilities/triggers/logevent/trigger.go @@ -0,0 +1,207 @@ +package logevent + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink-common/pkg/values" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent/logeventcap" +) + +// LogEventTrigger struct to listen for Contract events using ContractReader gRPC client +// in a loop with a periodic delay of pollPeriod milliseconds, which is specified in +// the job spec +type logEventTrigger struct { + ch chan<- capabilities.TriggerResponse + lggr logger.Logger + + // Contract address and Event Signature to monitor for + reqConfig *logeventcap.Config + contractReader types.ContractReader + relayer core.Relayer + startBlockNum uint64 + + // Log Event Trigger config with pollPeriod and lookbackBlocks + logEventConfig Config + ticker *time.Ticker + stopChan services.StopChan + done chan bool +} + +// Construct for logEventTrigger struct +func newLogEventTrigger(ctx context.Context, + lggr logger.Logger, + workflowID string, + reqConfig *logeventcap.Config, + logEventConfig Config, + relayer core.Relayer) (*logEventTrigger, chan capabilities.TriggerResponse, error) { + jsonBytes, err := json.Marshal(reqConfig.ContractReaderConfig) + if err != nil { + return nil, nil, err + } + + // Create a New Contract Reader client, which brings a corresponding ContractReader gRPC service + // in Chainlink Core service + contractReader, err := relayer.NewContractReader(ctx, jsonBytes) + if err != nil { + return nil, nil, + fmt.Errorf("error fetching contractReader for chainID %s from relayerSet: %w", logEventConfig.ChainID, err) + } + + // Bind Contract in ContractReader + boundContracts := []types.BoundContract{{Name: reqConfig.ContractName, Address: reqConfig.ContractAddress}} + err = contractReader.Bind(ctx, boundContracts) + if err != nil { + return nil, nil, err + } + + // Get current block HEAD/tip of the blockchain to start polling from + latestHead, err := relayer.LatestHead(ctx) + if err != nil { + return nil, nil, fmt.Errorf("error getting latestHead from relayer client: %w", err) + } + height, err := strconv.ParseUint(latestHead.Height, 10, 64) + if err != nil { + return nil, nil, fmt.Errorf("invalid height in latestHead from relayer client: %w", err) + } + startBlockNum := uint64(0) + if height > logEventConfig.LookbackBlocks { + startBlockNum = height - logEventConfig.LookbackBlocks + } + + // Setup callback channel, logger and ticker to poll ContractReader + callbackCh := make(chan capabilities.TriggerResponse, defaultSendChannelBufferSize) + ticker := time.NewTicker(time.Duration(logEventConfig.PollPeriod) * time.Millisecond) + + if logEventConfig.QueryCount == 0 { + logEventConfig.QueryCount = 20 + } + + // Initialise a Log Event Trigger + l := &logEventTrigger{ + ch: callbackCh, + lggr: logger.Named(lggr, fmt.Sprintf("LogEventTrigger.%s", workflowID)), + + reqConfig: reqConfig, + contractReader: contractReader, + relayer: relayer, + startBlockNum: startBlockNum, + + logEventConfig: logEventConfig, + ticker: ticker, + stopChan: make(services.StopChan), + done: make(chan bool), + } + return l, callbackCh, nil +} + +func (l *logEventTrigger) Start(ctx context.Context) error { + go l.listen() + return nil +} + +// Start to contract events and trigger workflow runs +func (l *logEventTrigger) listen() { + ctx, cancel := l.stopChan.NewCtx() + defer cancel() + defer close(l.done) + + // Listen for events from lookbackPeriod + var logs []types.Sequence + var err error + var logData values.Value + cursor := "" + limitAndSort := query.LimitAndSort{ + SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, + Limit: query.Limit{Count: l.logEventConfig.QueryCount}, + } + for { + select { + case <-ctx.Done(): + l.lggr.Infow("Closing trigger server for (waiting for waitGroup)", "ChainID", l.logEventConfig.ChainID, + "ContractName", l.reqConfig.ContractName, + "ContractAddress", l.reqConfig.ContractAddress, + "ContractEventName", l.reqConfig.ContractEventName) + return + case t := <-l.ticker.C: + l.lggr.Infow("Polling event logs from ContractReader using QueryKey at", "time", t, + "startBlockNum", l.startBlockNum, + "cursor", cursor) + if cursor != "" { + limitAndSort.Limit = query.CursorLimit(cursor, query.CursorFollowing, l.logEventConfig.QueryCount) + } + logs, err = l.contractReader.QueryKey( + ctx, + types.BoundContract{Name: l.reqConfig.ContractName, Address: l.reqConfig.ContractAddress}, + query.KeyFilter{ + Key: l.reqConfig.ContractEventName, + Expressions: []query.Expression{ + query.Confidence(primitives.Finalized), + query.Block(fmt.Sprintf("%d", l.startBlockNum), primitives.Gte), + }, + }, + limitAndSort, + &logData, + ) + if err != nil { + l.lggr.Errorw("QueryKey failure", "err", err) + continue + } + // ChainReader QueryKey API provides logs including the cursor value and not + // after the cursor value. If the response only consists of the log corresponding + // to the cursor and no log after it, then we understand that there are no new + // logs + if len(logs) == 1 && logs[0].Cursor == cursor { + l.lggr.Infow("No new logs since", "cursor", cursor) + continue + } + for _, log := range logs { + if log.Cursor == cursor { + continue + } + triggerResp := createTriggerResponse(log, l.logEventConfig.Version(ID)) + l.ch <- triggerResp + cursor = log.Cursor + } + } + } +} + +// Create log event trigger capability response +func createTriggerResponse(log types.Sequence, version string) capabilities.TriggerResponse { + wrappedPayload, err := values.WrapMap(log) + if err != nil { + return capabilities.TriggerResponse{ + Err: fmt.Errorf("error wrapping trigger event: %s", err), + } + } + return capabilities.TriggerResponse{ + Event: capabilities.TriggerEvent{ + TriggerType: version, + ID: log.Cursor, + Outputs: wrappedPayload, + }, + } +} + +// Close contract event listener for the current contract +// This function is called when UnregisterTrigger is called individually +// for a specific ContractAddress and EventName +// When the whole capability service is stopped, stopChan of the service +// is closed, which would stop all triggers +func (l *logEventTrigger) Close() error { + close(l.stopChan) + <-l.done + return nil +} diff --git a/core/capabilities/validation/validation.go b/core/capabilities/validation/validation.go new file mode 100644 index 00000000000..67ee3a504cf --- /dev/null +++ b/core/capabilities/validation/validation.go @@ -0,0 +1,38 @@ +package validation + +import ( + "encoding/hex" + "errors" + "unicode" +) + +const ( + validWorkflowIDLen = 64 + maxIDLen = 128 +) + +// Workflow IDs and Execution IDs are 32-byte hex-encoded strings +func ValidateWorkflowOrExecutionID(id string) error { + if len(id) != validWorkflowIDLen { + return errors.New("must be 32 bytes long") + } + _, err := hex.DecodeString(id) + if err != nil { + return errors.New("must be a hex-encoded string") + } + + return nil +} + +// Trigger event IDs and message IDs can only contain printable characters and must be non-empty +func IsValidID(id string) bool { + if len(id) == 0 || len(id) > maxIDLen { + return false + } + for i := 0; i < len(id); i++ { + if !unicode.IsPrint(rune(id[i])) { + return false + } + } + return true +} diff --git a/core/capabilities/validation/validation_test.go b/core/capabilities/validation/validation_test.go new file mode 100644 index 00000000000..205898652fd --- /dev/null +++ b/core/capabilities/validation/validation_test.go @@ -0,0 +1,19 @@ +package validation + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestIsValidWorkflowID(t *testing.T) { + require.NotNil(t, ValidateWorkflowOrExecutionID("too_short")) + require.NotNil(t, ValidateWorkflowOrExecutionID("nothex--95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0")) + require.NoError(t, ValidateWorkflowOrExecutionID("15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0")) +} + +func TestIsValidTriggerEventID(t *testing.T) { + require.False(t, IsValidID("")) + require.False(t, IsValidID("\n\n")) + require.True(t, IsValidID("id_id_2")) +} diff --git a/core/capabilities/webapi/outgoing_connector_handler.go b/core/capabilities/webapi/outgoing_connector_handler.go new file mode 100644 index 00000000000..b00b82b2bd0 --- /dev/null +++ b/core/capabilities/webapi/outgoing_connector_handler.go @@ -0,0 +1,142 @@ +package webapi + +import ( + "context" + "encoding/json" + "fmt" + "sort" + "sync" + + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" +) + +var _ connector.GatewayConnectorHandler = &OutgoingConnectorHandler{} + +type OutgoingConnectorHandler struct { + gc connector.GatewayConnector + method string + lggr logger.Logger + responseChs map[string]chan *api.Message + responseChsMu sync.Mutex + rateLimiter *common.RateLimiter +} + +func NewOutgoingConnectorHandler(gc connector.GatewayConnector, config ServiceConfig, method string, lgger logger.Logger) (*OutgoingConnectorHandler, error) { + rateLimiter, err := common.NewRateLimiter(config.RateLimiter) + if err != nil { + return nil, err + } + + if !validMethod(method) { + return nil, fmt.Errorf("invalid outgoing connector handler method: %s", method) + } + + responseChs := make(map[string]chan *api.Message) + return &OutgoingConnectorHandler{ + gc: gc, + method: method, + responseChs: responseChs, + responseChsMu: sync.Mutex{}, + rateLimiter: rateLimiter, + lggr: lgger, + }, nil +} + +// HandleSingleNodeRequest sends a request to first available gateway node and blocks until response is received +// TODO: handle retries and timeouts +func (c *OutgoingConnectorHandler) HandleSingleNodeRequest(ctx context.Context, messageID string, payload []byte) (*api.Message, error) { + ch := make(chan *api.Message, 1) + c.responseChsMu.Lock() + c.responseChs[messageID] = ch + c.responseChsMu.Unlock() + l := logger.With(c.lggr, "messageID", messageID) + l.Debugw("sending request to gateway") + + body := &api.MessageBody{ + MessageId: messageID, + DonId: c.gc.DonID(), + Method: c.method, + Payload: payload, + } + + // simply, send request to first available gateway node from sorted list + // this allows for deterministic selection of gateway node receiver for easier debugging + gatewayIDs := c.gc.GatewayIDs() + if len(gatewayIDs) == 0 { + return nil, errors.New("no gateway nodes available") + } + sort.Strings(gatewayIDs) + + err := c.gc.SignAndSendToGateway(ctx, gatewayIDs[0], body) + if err != nil { + return nil, errors.Wrap(err, "failed to send request to gateway") + } + + select { + case resp := <-ch: + l.Debugw("received response from gateway") + return resp, nil + case <-ctx.Done(): + return nil, ctx.Err() + } +} + +func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gatewayID string, msg *api.Message) { + body := &msg.Body + l := logger.With(c.lggr, "gatewayID", gatewayID, "method", body.Method, "messageID", msg.Body.MessageId) + if !c.rateLimiter.Allow(body.Sender) { + // error is logged here instead of warning because if a message from gateway is rate-limited, + // the workflow will eventually fail with timeout as there are no retries in place yet + c.lggr.Errorw("request rate-limited") + return + } + l.Debugw("handling gateway request") + switch body.Method { + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: + body := &msg.Body + var payload capabilities.Response + err := json.Unmarshal(body.Payload, &payload) + if err != nil { + l.Errorw("failed to unmarshal payload", "err", err) + return + } + c.responseChsMu.Lock() + defer c.responseChsMu.Unlock() + ch, ok := c.responseChs[body.MessageId] + if !ok { + l.Errorw("no response channel found") + return + } + select { + case ch <- msg: + delete(c.responseChs, body.MessageId) + case <-ctx.Done(): + return + } + default: + l.Errorw("unsupported method") + } +} + +func (c *OutgoingConnectorHandler) Start(ctx context.Context) error { + return c.gc.AddHandler([]string{c.method}, c) +} + +func (c *OutgoingConnectorHandler) Close() error { + return nil +} + +func validMethod(method string) bool { + switch method { + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: + return true + default: + return false + } +} diff --git a/core/capabilities/webapi/target/target.go b/core/capabilities/webapi/target/target.go new file mode 100644 index 00000000000..4576f95a54e --- /dev/null +++ b/core/capabilities/webapi/target/target.go @@ -0,0 +1,179 @@ +package target + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" +) + +const ID = "web-api-target@1.0.0" + +var _ capabilities.TargetCapability = &Capability{} + +var capabilityInfo = capabilities.MustNewCapabilityInfo( + ID, + capabilities.CapabilityTypeTarget, + "A target that sends HTTP requests to external clients via the Chainlink Gateway.", +) + +const ( + DefaultDeliveryMode = webapi.SingleNode + DefaultHTTPMethod = "GET" + DefaultTimeoutMs = 30000 + MaxTimeoutMs = 600000 +) + +// Capability is a target capability that sends HTTP requests to external clients via the Chainlink Gateway. +type Capability struct { + capabilityInfo capabilities.CapabilityInfo + connectorHandler *webapi.OutgoingConnectorHandler + lggr logger.Logger + registry core.CapabilitiesRegistry + config webapi.ServiceConfig +} + +func NewCapability(config webapi.ServiceConfig, registry core.CapabilitiesRegistry, connectorHandler *webapi.OutgoingConnectorHandler, lggr logger.Logger) (*Capability, error) { + return &Capability{ + capabilityInfo: capabilityInfo, + config: config, + registry: registry, + connectorHandler: connectorHandler, + lggr: lggr, + }, nil +} + +func (c *Capability) Start(ctx context.Context) error { + return c.registry.Add(ctx, c) +} + +func (c *Capability) Close() error { + return nil +} + +func (c *Capability) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return capabilityInfo, nil +} + +func getMessageID(req capabilities.CapabilityRequest) (string, error) { + if err := validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowID); err != nil { + return "", fmt.Errorf("workflow ID is invalid: %w", err) + } + if err := validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowExecutionID); err != nil { + return "", fmt.Errorf("workflow execution ID is invalid: %w", err) + } + messageID := []string{ + req.Metadata.WorkflowExecutionID, + ghcapabilities.MethodWebAPITarget, + } + return strings.Join(messageID, "/"), nil +} + +// defaultIfNil is a helper function to handle nil pointers and provide default values +func defaultIfNil[T any](value *T, defaultValue T) T { + if value != nil { + return *value + } + return defaultValue +} + +func getPayload(input webapicap.TargetPayload, cfg webapicap.TargetConfig) (ghcapabilities.Request, error) { + method := defaultIfNil(input.Method, DefaultHTTPMethod) + body := defaultIfNil(input.Body, "") + timeoutMs := defaultIfNil(cfg.TimeoutMs, DefaultTimeoutMs) + if timeoutMs > MaxTimeoutMs { + return ghcapabilities.Request{}, fmt.Errorf("timeoutMs must be between 0 and %d", MaxTimeoutMs) + } + + return ghcapabilities.Request{ + URL: input.Url, + Method: method, + Headers: input.Headers, + Body: []byte(body), + TimeoutMs: timeoutMs, + }, nil +} + +func (c *Capability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + c.lggr.Debugw("executing http target", "capabilityRequest", req) + + var input webapicap.TargetPayload + err := req.Inputs.UnwrapTo(&input) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + var workflowCfg webapicap.TargetConfig + err = req.Config.UnwrapTo(&workflowCfg) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + messageID, err := getMessageID(req) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + payload, err := getPayload(input, workflowCfg) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + payloadBytes, err := json.Marshal(payload) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + // Default to SingleNode delivery mode + deliveryMode := defaultIfNil(workflowCfg.DeliveryMode, webapi.SingleNode) + + switch deliveryMode { + case webapi.SingleNode: + // blocking call to handle single node request. waits for response from gateway + resp, err := c.connectorHandler.HandleSingleNodeRequest(ctx, messageID, payloadBytes) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + c.lggr.Debugw("received gateway response", "resp", resp) + var payload ghcapabilities.Response + err = json.Unmarshal(resp.Body.Payload, &payload) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + // TODO: check target response format and fields CM-473 + values, err := values.NewMap(map[string]any{ + "statusCode": payload.StatusCode, + "headers": payload.Headers, + "body": payload.Body, + }) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + return capabilities.CapabilityResponse{ + Value: values, + }, nil + default: + return capabilities.CapabilityResponse{}, fmt.Errorf("unsupported delivery mode: %v", workflowCfg.DeliveryMode) + } +} + +func (c *Capability) RegisterToWorkflow(ctx context.Context, req capabilities.RegisterToWorkflowRequest) error { + // Workflow engine guarantees registration requests are valid + // TODO: handle retry configuration CM-472 + return nil +} + +func (c *Capability) UnregisterFromWorkflow(ctx context.Context, req capabilities.UnregisterFromWorkflowRequest) error { + // Workflow engine guarantees deregistration requests are valid + return nil +} diff --git a/core/capabilities/webapi/target/target_test.go b/core/capabilities/webapi/target/target_test.go new file mode 100644 index 00000000000..f51cdcd0d70 --- /dev/null +++ b/core/capabilities/webapi/target/target_test.go @@ -0,0 +1,381 @@ +package target + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + registrymock "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" +) + +const ( + workflowID1 = "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0" + workflowID2 = "44f129ea13948d1c4eaa2bbc0e72319266364cba12b789174732b2f72b57088d" + workflowExecutionID1 = "95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0abbadeed" + owner1 = "0x00000000000000000000000000000000000000aa" +) + +var defaultConfig = webapi.ServiceConfig{ + RateLimiter: common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + }, +} + +type testHarness struct { + registry *registrymock.CapabilitiesRegistry + connector *gcmocks.GatewayConnector + lggr logger.Logger + config webapi.ServiceConfig + connectorHandler *webapi.OutgoingConnectorHandler + capability *Capability +} + +func setup(t *testing.T, config webapi.ServiceConfig) testHarness { + registry := registrymock.NewCapabilitiesRegistry(t) + connector := gcmocks.NewGatewayConnector(t) + lggr := logger.Test(t) + connectorHandler, err := webapi.NewOutgoingConnectorHandler(connector, config, ghcapabilities.MethodWebAPITarget, lggr) + require.NoError(t, err) + + capability, err := NewCapability(config, registry, connectorHandler, lggr) + require.NoError(t, err) + + return testHarness{ + registry: registry, + connector: connector, + lggr: lggr, + config: config, + connectorHandler: connectorHandler, + capability: capability, + } +} + +func emptyWfConfig(t *testing.T) *values.Map { + wfConfig, err := values.NewMap(map[string]interface{}{}) + require.NoError(t, err) + return wfConfig +} + +func inputsAndConfig(t *testing.T) (*values.Map, *values.Map) { + data := map[string]string{ + "key": "value", + } + jsonData, err := json.Marshal(data) + require.NoError(t, err) + encoded := base64.StdEncoding.EncodeToString(jsonData) + targetInput := map[string]any{ + "url": "http://example.com", + "method": "POST", + "headers": map[string]string{"Content-Type": "application/json"}, + "body": encoded, + } + inputs, err := values.NewMap(targetInput) + require.NoError(t, err) + wfConfig, err := values.NewMap(map[string]interface{}{ + "timeoutMs": 1000, + "schedule": webapi.SingleNode, + }) + require.NoError(t, err) + return inputs, wfConfig +} + +func capabilityRequest(t *testing.T) capabilities.CapabilityRequest { + inputs, wfConfig := inputsAndConfig(t) + + return capabilities.CapabilityRequest{ + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowExecutionID: workflowExecutionID1, + }, + Inputs: inputs, + Config: wfConfig, + } +} + +func gatewayResponse(t *testing.T, msgID 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, + }) + require.NoError(t, err) + return &api.Message{ + Body: api.MessageBody{ + MessageId: msgID, + Method: ghcapabilities.MethodWebAPITarget, + Payload: responsePayload, + }, + } +} + +func TestRegisterUnregister(t *testing.T) { + th := setup(t, defaultConfig) + ctx := testutils.Context(t) + + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + t.Run("happy case", func(t *testing.T) { + err = th.capability.UnregisterFromWorkflow(ctx, capabilities.UnregisterFromWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + }) + require.NoError(t, err) + }) + + t.Run("unregister non-existent workflow no error", func(t *testing.T) { + err = th.capability.UnregisterFromWorkflow(ctx, capabilities.UnregisterFromWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID2, + WorkflowOwner: owner1, + }, + }) + require.NoError(t, err) + }) + + t.Run("reregister idempotent", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + }) +} + +func TestCapability_Execute(t *testing.T) { + th := setup(t, defaultConfig) + ctx := testutils.Context(t) + th.connector.EXPECT().DonID().Return("donID") + th.connector.EXPECT().GatewayIDs().Return([]string{"gateway2", "gateway1"}) + + t.Run("happy case", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + req := capabilityRequest(t) + msgID, err := getMessageID(req) + require.NoError(t, err) + + gatewayResp := gatewayResponse(t, msgID) + + th.connector.On("SignAndSendToGateway", mock.Anything, "gateway1", mock.Anything).Return(nil).Run(func(args mock.Arguments) { + th.connectorHandler.HandleGatewayMessage(ctx, "gateway1", gatewayResp) + }).Once() + + resp, err := th.capability.Execute(ctx, req) + require.NoError(t, err) + verifyResp(t, resp) + }) + + t.Run("context cancelled while waiting for gateway response", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + req := capabilityRequest(t) + _, err = getMessageID(req) + require.NoError(t, err) + + newCtx, cancel := context.WithCancel(ctx) + th.connector.On("SignAndSendToGateway", mock.Anything, "gateway1", mock.Anything).Return(nil).Run(func(args mock.Arguments) { + cancel() + }).Once() + + _, err = th.capability.Execute(newCtx, req) + require.Error(t, err) + require.Contains(t, err.Error(), "context canceled") + }) + + t.Run("invalid workflow ID during execute", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + inputs, wfConfig := inputsAndConfig(t) + req := capabilities.CapabilityRequest{ + Metadata: capabilities.RequestMetadata{ + WorkflowID: "invalid", + WorkflowExecutionID: workflowExecutionID1, + }, + Inputs: inputs, + Config: wfConfig, + } + + _, err = th.capability.Execute(ctx, req) + require.Error(t, err) + require.ErrorContains(t, err, "workflow ID is invalid") + }) + + t.Run("invalid workflow execution ID during execute", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + inputs, wfConfig := inputsAndConfig(t) + req := capabilities.CapabilityRequest{ + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowExecutionID: "invalid", + }, + Inputs: inputs, + Config: wfConfig, + } + + _, err = th.capability.Execute(ctx, req) + require.Error(t, err) + require.ErrorContains(t, err, "workflow execution ID is invalid") + }) + + t.Run("unsupported delivery mode", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + targetInput := map[string]any{ + "url": "http://example.com", + "method": "POST", + "headers": map[string]string{"Content-Type": "application/json"}, + } + inputs, err := values.NewMap(targetInput) + + require.NoError(t, err) + wfConfig, err := values.NewMap(map[string]interface{}{ + "timeoutMs": 1000, + "deliveryMode": "invalid", + }) + require.NoError(t, err) + + req := capabilities.CapabilityRequest{ + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowExecutionID: workflowExecutionID1, + }, + Inputs: inputs, + Config: wfConfig, + } + + _, err = th.capability.Execute(ctx, req) + require.Error(t, err) + require.Contains(t, err.Error(), "unsupported delivery mode") + }) + + t.Run("gateway connector error", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + req := capabilityRequest(t) + require.NoError(t, err) + + th.connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Return(errors.New("gateway error")).Once() + _, err = th.capability.Execute(ctx, req) + require.Error(t, err) + require.Contains(t, err.Error(), "gateway error") + }) + + t.Run("empty workflow config", func(t *testing.T) { + regReq := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + } + err := th.capability.RegisterToWorkflow(ctx, regReq) + require.NoError(t, err) + + inputs, _ := inputsAndConfig(t) + req := capabilities.CapabilityRequest{ + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowExecutionID: workflowExecutionID1, + }, + Inputs: inputs, + Config: emptyWfConfig(t), + } + + msgID, err := getMessageID(req) + require.NoError(t, err) + gatewayResp := gatewayResponse(t, msgID) + th.connector.On("SignAndSendToGateway", mock.Anything, "gateway1", mock.Anything).Return(nil).Run(func(args mock.Arguments) { + th.connectorHandler.HandleGatewayMessage(ctx, "gateway1", gatewayResp) + }).Once() + + resp, err := th.capability.Execute(ctx, req) + require.NoError(t, err) + verifyResp(t, resp) + }) +} + +func verifyResp(t *testing.T, resp capabilities.CapabilityResponse) { + var values map[string]any + err := resp.Value.UnwrapTo(&values) + require.NoError(t, err) + statusCode, ok := values["statusCode"].(int64) + require.True(t, ok) + require.Equal(t, int64(200), statusCode) + respBody, ok := values["body"].([]byte) + require.True(t, ok) + require.Equal(t, "response body", string(respBody)) +} diff --git a/core/capabilities/webapi/trigger/trigger.go b/core/capabilities/webapi/trigger/trigger.go new file mode 100644 index 00000000000..a08d2f577ff --- /dev/null +++ b/core/capabilities/webapi/trigger/trigger.go @@ -0,0 +1,287 @@ +package trigger + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "sync" + + ethCommon "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink-common/pkg/values" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" +) + +const defaultSendChannelBufferSize = 1000 + +const TriggerType = "web-api-trigger@1.0.0" + +var webapiTriggerInfo = capabilities.MustNewCapabilityInfo( + TriggerType, + capabilities.CapabilityTypeTrigger, + "A trigger to start workflow execution from a web api call", +) + +type webapiTrigger struct { + allowedSenders map[string]bool + allowedTopics map[string]bool + ch chan<- capabilities.TriggerResponse + config webapicap.TriggerConfig + rateLimiter *common.RateLimiter +} + +type triggerConnectorHandler struct { + services.StateMachine + + capabilities.CapabilityInfo + capabilities.Validator[webapicap.TriggerConfig, struct{}, webapicap.TriggerRequestPayload] + connector connector.GatewayConnector + lggr logger.Logger + mu sync.Mutex + registeredWorkflows map[string]webapiTrigger + registry core.CapabilitiesRegistry +} + +var _ capabilities.TriggerCapability = (*triggerConnectorHandler)(nil) +var _ services.Service = &triggerConnectorHandler{} + +func NewTrigger(config string, registry core.CapabilitiesRegistry, connector connector.GatewayConnector, lggr logger.Logger) (*triggerConnectorHandler, error) { + if connector == nil { + return nil, errors.New("missing connector") + } + handler := &triggerConnectorHandler{ + CapabilityInfo: webapiTriggerInfo, + Validator: capabilities.NewValidator[webapicap.TriggerConfig, struct{}, webapicap.TriggerRequestPayload](capabilities.ValidatorArgs{Info: webapiTriggerInfo}), + connector: connector, + registeredWorkflows: map[string]webapiTrigger{}, + registry: registry, + lggr: lggr.Named("WorkflowConnectorHandler"), + } + + return handler, nil +} + +// processTrigger iterates over each topic, checking against senders and rateLimits, then starting event processing and responding +func (h *triggerConnectorHandler) processTrigger(ctx context.Context, gatewayID string, body *api.MessageBody, sender ethCommon.Address, payload webapicap.TriggerRequestPayload) error { + // Pass on the payload with the expectation that it's in an acceptable format for the executor + wrappedPayload, err := values.WrapMap(payload) + if err != nil { + return fmt.Errorf("error wrapping payload %s", err) + } + topics := payload.Topics + + // empty topics is error for V1 + if len(topics) == 0 { + return fmt.Errorf("empty Workflow Topics") + } + + // workflows that have matched topics + matchedWorkflows := 0 + // workflows that have matched topic and passed all checks + fullyMatchedWorkflows := 0 + for _, trigger := range h.registeredWorkflows { + for _, topic := range topics { + if trigger.allowedTopics[topic] { + matchedWorkflows++ + if !trigger.allowedSenders[sender.String()] { + err = fmt.Errorf("unauthorized Sender %s, messageID %s", sender.String(), body.MessageId) + h.lggr.Debugw(err.Error()) + continue + } + if !trigger.rateLimiter.Allow(body.Sender) { + err = fmt.Errorf("request rate-limited for sender %s, messageID %s", sender.String(), body.MessageId) + continue + } + fullyMatchedWorkflows++ + TriggerEventID := body.Sender + payload.TriggerEventId + tr := capabilities.TriggerResponse{ + Event: capabilities.TriggerEvent{ + TriggerType: TriggerType, + ID: TriggerEventID, + Outputs: wrappedPayload, + }, + } + select { + case <-ctx.Done(): + return nil + case trigger.ch <- tr: + // Sending n topics that match a workflow with n allowedTopics, can only be triggered once. + break + } + } + } + } + if matchedWorkflows == 0 { + return fmt.Errorf("no Matching Workflow Topics") + } + + if fullyMatchedWorkflows > 0 { + return nil + } + return err +} + +func (h *triggerConnectorHandler) HandleGatewayMessage(ctx context.Context, gatewayID string, msg *api.Message) { + // TODO: Validate Signature + body := &msg.Body + sender := ethCommon.HexToAddress(body.Sender) + var payload webapicap.TriggerRequestPayload + err := json.Unmarshal(body.Payload, &payload) + if err != nil { + h.lggr.Errorw("error decoding payload", "err", err) + err = h.sendResponse(ctx, gatewayID, body, ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: fmt.Errorf("error %s decoding payload", err.Error()).Error()}) + if err != nil { + h.lggr.Errorw("error sending response", "err", err) + } + return + } + + switch body.Method { + case ghcapabilities.MethodWebAPITrigger: + resp := h.processTrigger(ctx, gatewayID, body, sender, payload) + var response ghcapabilities.TriggerResponsePayload + if resp == nil { + response = ghcapabilities.TriggerResponsePayload{Status: "ACCEPTED"} + } else { + response = ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: resp.Error()} + h.lggr.Errorw("Error processing trigger", "gatewayID", gatewayID, "body", body, "response", resp) + } + err = h.sendResponse(ctx, gatewayID, body, response) + if err != nil { + h.lggr.Errorw("Error sending response", "body", body, "response", response, "err", err) + } + return + + default: + h.lggr.Errorw("unsupported method", "id", gatewayID, "method", body.Method) + err = h.sendResponse(ctx, gatewayID, body, ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: fmt.Errorf("unsupported method %s", body.Method).Error()}) + if err != nil { + h.lggr.Errorw("error sending response", "err", err) + } + } +} + +func (h *triggerConnectorHandler) RegisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) (<-chan capabilities.TriggerResponse, error) { + cfg := req.Config + if cfg == nil { + return nil, errors.New("config is required to register a web api trigger") + } + + reqConfig, err := h.ValidateConfig(cfg) + if err != nil { + return nil, err + } + + if len(reqConfig.AllowedSenders) == 0 { + return nil, errors.New("allowedSenders must have at least 1 entry") + } + + h.mu.Lock() + defer h.mu.Unlock() + _, errBool := h.registeredWorkflows[req.TriggerID] + if errBool { + return nil, fmt.Errorf("triggerId %s already registered", req.TriggerID) + } + + rateLimiterConfig := reqConfig.RateLimiter + commonRateLimiter := common.RateLimiterConfig{ + GlobalRPS: rateLimiterConfig.GlobalRPS, + GlobalBurst: int(rateLimiterConfig.GlobalBurst), + PerSenderRPS: rateLimiterConfig.PerSenderRPS, + PerSenderBurst: int(rateLimiterConfig.PerSenderBurst), + } + + rateLimiter, err := common.NewRateLimiter(commonRateLimiter) + if err != nil { + return nil, err + } + + allowedSendersMap := map[string]bool{} + for _, k := range reqConfig.AllowedSenders { + allowedSendersMap[k] = true + } + + allowedTopicsMap := map[string]bool{} + for _, k := range reqConfig.AllowedTopics { + allowedTopicsMap[k] = true + } + + ch := make(chan capabilities.TriggerResponse, defaultSendChannelBufferSize) + + h.registeredWorkflows[req.TriggerID] = webapiTrigger{ + allowedTopics: allowedTopicsMap, + allowedSenders: allowedSendersMap, + ch: ch, + config: *reqConfig, + rateLimiter: rateLimiter, + } + + return ch, nil +} + +func (h *triggerConnectorHandler) UnregisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) error { + h.mu.Lock() + defer h.mu.Unlock() + workflow, ok := h.registeredWorkflows[req.TriggerID] + if !ok { + return fmt.Errorf("triggerId %s not registered", req.TriggerID) + } + + close(workflow.ch) + delete(h.registeredWorkflows, req.TriggerID) + return nil +} + +func (h *triggerConnectorHandler) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return h.CapabilityInfo, nil +} + +func (h *triggerConnectorHandler) Start(ctx context.Context) error { + if err := h.registry.Add(ctx, h); err != nil { + return err + } + return h.StartOnce("GatewayConnectorServiceWrapper", func() error { + return h.connector.AddHandler([]string{"web_api_trigger"}, h) + }) +} +func (h *triggerConnectorHandler) Close() error { + return h.StopOnce("GatewayConnectorServiceWrapper", func() error { + return nil + }) +} + +func (h *triggerConnectorHandler) HealthReport() map[string]error { + return map[string]error{h.Name(): h.Healthy()} +} + +func (h *triggerConnectorHandler) Name() string { + return "WebAPITrigger" +} + +func (h *triggerConnectorHandler) sendResponse(ctx context.Context, gatewayID string, requestBody *api.MessageBody, payload any) error { + payloadJSON, err := json.Marshal(payload) + if err != nil { + h.lggr.Errorw("error marshalling payload", "err", err) + payloadJSON, _ = json.Marshal(ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: fmt.Errorf("error %s marshalling payload", err.Error()).Error()}) + } + + body := &api.MessageBody{ + MessageId: requestBody.MessageId, + DonId: requestBody.DonId, + Method: requestBody.Method, + Receiver: requestBody.Sender, + Payload: payloadJSON, + } + + return h.connector.SignAndSendToGateway(ctx, gatewayID, body) +} diff --git a/core/capabilities/webapi/trigger/trigger_test.go b/core/capabilities/webapi/trigger/trigger_test.go new file mode 100644 index 00000000000..0c73e31fe62 --- /dev/null +++ b/core/capabilities/webapi/trigger/trigger_test.go @@ -0,0 +1,386 @@ +package trigger + +import ( + "context" + "encoding/json" + "errors" + "testing" + "time" + + "github.com/ethereum/go-ethereum/crypto" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + registrymock "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" + "github.com/smartcontractkit/chainlink-common/pkg/values" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" +) + +const ( + privateKey1 = "65456ffb8af4a2b93959256a8e04f6f2fe0943579fb3c9c3350593aabb89023f" + privateKey2 = "65456ffb8af4a2b93959256a8e04f6f2fe0943579fb3c9c3350593aabb89023e" + triggerID1 = "5" + triggerID2 = "6" + workflowID1 = "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0" + workflowExecutionID1 = "95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0abbadeed" + owner1 = "0x00000000000000000000000000000000000000aa" + address1 = "0x853d51d5d9935964267a5050aC53aa63ECA39bc5" + address2 = "0x853d51d5d9935964267a5050aC53aa63ECA39bc6" +) + +type testHarness struct { + registry *registrymock.CapabilitiesRegistry + connector *gcmocks.GatewayConnector + lggr logger.Logger + config string + trigger *triggerConnectorHandler +} + +func workflowTriggerConfig(_ testHarness, addresses []string, topics []string) (*values.Map, error) { + var rateLimitConfig, err = values.NewMap(map[string]any{ + "GlobalRPS": 100.0, + "GlobalBurst": 101, + "PerSenderRPS": 102.0, + "PerSenderBurst": 103, + }) + if err != nil { + return nil, err + } + + triggerRegistrationConfig, err := values.NewMap(map[string]interface{}{ + "RateLimiter": rateLimitConfig, + "AllowedSenders": addresses, + "AllowedTopics": topics, + "RequiredParams": []string{"bid", "ask"}, + }) + return triggerRegistrationConfig, err +} + +func setup(t *testing.T) testHarness { + registry := registrymock.NewCapabilitiesRegistry(t) + connector := gcmocks.NewGatewayConnector(t) + lggr := corelogger.TestLogger(t) + config := "" + + trigger, err := NewTrigger(config, registry, connector, lggr) + require.NoError(t, err) + + return testHarness{ + registry: registry, + connector: connector, + lggr: lggr, + config: config, + trigger: trigger, + } +} + +func gatewayRequest(t *testing.T, privateKey string, topics string, methodName string) *api.Message { + messageID := "12345" + if methodName == "" { + methodName = ghcapabilities.MethodWebAPITrigger + } + donID := "workflow_don_1" + + key, err := crypto.HexToECDSA(privateKey) + require.NoError(t, err) + + payload := `{ + "trigger_id": "` + TriggerType + `", + "trigger_event_id": "action_1234567890", + "timestamp": 1234567890, + "topics": ` + topics + `, + "params": { + "bid": "101", + "ask": "102" + } + } +` + payloadJSON := []byte(payload) + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: messageID, + Method: methodName, + DonId: donID, + Payload: json.RawMessage(payloadJSON), + }, + } + err = msg.Sign(key) + require.NoError(t, err) + return msg +} + +func getResponseFromArg(arg interface{}) (ghcapabilities.TriggerResponsePayload, error) { + var response ghcapabilities.TriggerResponsePayload + msgBody := arg.(*api.MessageBody) + err := json.Unmarshal(msgBody.Payload, &response) + return response, err +} + +func requireNoChanMsg[T any](t *testing.T, ch <-chan T) { + timedOut := false + select { + case <-ch: + case <-time.After(100 * time.Millisecond): + timedOut = true + } + require.True(t, timedOut) +} + +func requireChanMsg[T capabilities.TriggerResponse](t *testing.T, ch <-chan capabilities.TriggerResponse) (capabilities.TriggerResponse, error) { + timedOut := false + select { + case resp := <-ch: + return resp, nil + case <-time.After(100 * time.Millisecond): + timedOut = true + } + require.False(t, timedOut) + return capabilities.TriggerResponse{}, errors.New("channel timeout") +} + +func TestTriggerExecute(t *testing.T) { + th := setup(t) + ctx := testutils.Context(t) + ctx, cancelContext := context.WithDeadline(ctx, time.Now().Add(10*time.Second)) + Config, _ := workflowTriggerConfig(th, []string{address1}, []string{"daily_price_update", "ad_hoc_price_update"}) + triggerReq := capabilities.TriggerRegistrationRequest{ + TriggerID: triggerID1, + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + Config: Config, + } + channel, err := th.trigger.RegisterTrigger(ctx, triggerReq) + require.NoError(t, err) + + Config2, err := workflowTriggerConfig(th, []string{address1}, []string{"daily_price_update2", "ad_hoc_price_update"}) + require.NoError(t, err) + + triggerReq2 := capabilities.TriggerRegistrationRequest{ + TriggerID: triggerID2, + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + Config: Config2, + } + channel2, err := th.trigger.RegisterTrigger(ctx, triggerReq2) + require.NoError(t, err) + + t.Run("happy case single topic to single workflow", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey1, `["daily_price_update"]`, "") + + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ACCEPTED"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + + received, chanErr := requireChanMsg(t, channel) + require.Equal(t, received.Event.TriggerType, TriggerType) + require.NoError(t, chanErr) + + requireNoChanMsg(t, channel2) + data := received.Event.Outputs + var payload webapicap.TriggerRequestPayload + unwrapErr := data.UnwrapTo(&payload) + require.NoError(t, unwrapErr) + require.Equal(t, payload.Topics, []string{"daily_price_update"}) + }) + + t.Run("happy case single different topic 2 workflows.", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey1, `["ad_hoc_price_update"]`, "") + + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ACCEPTED"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + + sent := <-channel + require.Equal(t, sent.Event.TriggerType, TriggerType) + data := sent.Event.Outputs + var payload webapicap.TriggerRequestPayload + unwrapErr := data.UnwrapTo(&payload) + require.NoError(t, unwrapErr) + require.Equal(t, payload.Topics, []string{"ad_hoc_price_update"}) + + sent2 := <-channel2 + require.Equal(t, sent2.Event.TriggerType, TriggerType) + data2 := sent2.Event.Outputs + var payload2 webapicap.TriggerRequestPayload + err2 := data2.UnwrapTo(&payload2) + require.NoError(t, err2) + require.Equal(t, payload2.Topics, []string{"ad_hoc_price_update"}) + }) + + t.Run("sad case empty topic 2 workflows", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey1, `[]`, "") + + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: "empty Workflow Topics"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + + requireNoChanMsg(t, channel) + requireNoChanMsg(t, channel2) + }) + + t.Run("sad case topic with no workflows", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey1, `["foo"]`, "") + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: "no Matching Workflow Topics"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + requireNoChanMsg(t, channel) + requireNoChanMsg(t, channel2) + }) + + t.Run("sad case Not Allowed Sender", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey2, `["ad_hoc_price_update"]`, "") + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: "unauthorized Sender 0x2dAC9f74Ee66e2D55ea1B8BE284caFedE048dB3A, messageID 12345"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + requireNoChanMsg(t, channel) + requireNoChanMsg(t, channel2) + }) + + t.Run("sad case Invalid Method", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey2, `["ad_hoc_price_update"]`, "boo") + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ERROR", ErrorMessage: "unsupported method boo"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + requireNoChanMsg(t, channel) + requireNoChanMsg(t, channel2) + }) + + err = th.trigger.UnregisterTrigger(ctx, triggerReq) + require.NoError(t, err) + err = th.trigger.UnregisterTrigger(ctx, triggerReq2) + require.NoError(t, err) + cancelContext() +} + +func TestRegisterNoAllowedSenders(t *testing.T) { + th := setup(t) + ctx := testutils.Context(t) + Config, _ := workflowTriggerConfig(th, []string{}, []string{"daily_price_update"}) + + triggerReq := capabilities.TriggerRegistrationRequest{ + TriggerID: triggerID1, + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + Config: Config, + } + _, err := th.trigger.RegisterTrigger(ctx, triggerReq) + require.Error(t, err) + + gatewayRequest(t, privateKey1, `["daily_price_update"]`, "") +} + +func TestTriggerExecute2WorkflowsSameTopicDifferentAllowLists(t *testing.T) { + th := setup(t) + ctx := testutils.Context(t) + ctx, cancelContext := context.WithDeadline(ctx, time.Now().Add(10*time.Second)) + Config, _ := workflowTriggerConfig(th, []string{address2}, []string{"daily_price_update"}) + triggerReq := capabilities.TriggerRegistrationRequest{ + TriggerID: triggerID1, + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + Config: Config, + } + channel, err := th.trigger.RegisterTrigger(ctx, triggerReq) + require.NoError(t, err) + + Config2, err := workflowTriggerConfig(th, []string{address1}, []string{"daily_price_update"}) + require.NoError(t, err) + + triggerReq2 := capabilities.TriggerRegistrationRequest{ + TriggerID: triggerID2, + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + Config: Config2, + } + channel2, err := th.trigger.RegisterTrigger(ctx, triggerReq2) + require.NoError(t, err) + + t.Run("happy case single topic to single workflow", func(t *testing.T) { + gatewayRequest := gatewayRequest(t, privateKey1, `["daily_price_update"]`, "") + + th.connector.On("SignAndSendToGateway", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + resp, _ := getResponseFromArg(args.Get(2)) + require.Equal(t, ghcapabilities.TriggerResponsePayload{Status: "ACCEPTED"}, resp) + }).Return(nil).Once() + + th.trigger.HandleGatewayMessage(ctx, "gateway1", gatewayRequest) + + requireNoChanMsg(t, channel) + received, chanErr := requireChanMsg(t, channel2) + require.Equal(t, received.Event.TriggerType, TriggerType) + require.NoError(t, chanErr) + data := received.Event.Outputs + var payload webapicap.TriggerRequestPayload + unwrapErr := data.UnwrapTo(&payload) + require.NoError(t, unwrapErr) + require.Equal(t, payload.Topics, []string{"daily_price_update"}) + }) + err = th.trigger.UnregisterTrigger(ctx, triggerReq) + require.NoError(t, err) + err = th.trigger.UnregisterTrigger(ctx, triggerReq2) + require.NoError(t, err) + cancelContext() +} + +func TestRegisterUnregister(t *testing.T) { + th := setup(t) + ctx := testutils.Context(t) + Config, err := workflowTriggerConfig(th, []string{address1}, []string{"daily_price_update"}) + require.NoError(t, err) + + triggerReq := capabilities.TriggerRegistrationRequest{ + TriggerID: triggerID1, + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: owner1, + }, + Config: Config, + } + + channel, err := th.trigger.RegisterTrigger(ctx, triggerReq) + require.NoError(t, err) + require.NotEmpty(t, th.trigger.registeredWorkflows[triggerID1]) + + err = th.trigger.UnregisterTrigger(ctx, triggerReq) + require.NoError(t, err) + _, open := <-channel + require.Equal(t, open, false) +} diff --git a/core/capabilities/webapi/types.go b/core/capabilities/webapi/types.go new file mode 100644 index 00000000000..62d6143bea5 --- /dev/null +++ b/core/capabilities/webapi/types.go @@ -0,0 +1,17 @@ +package webapi + +import "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" + +const ( + SingleNode string = "SingleNode" + // TODO: AllAtOnce is not yet implemented + AllAtOnce string = "AllAtOnce" +) + +// ServiceConfig is the configuration for the Target capability and handler +// TODO: handle retry configurations here CM-472 +// Note that workflow executions have their own internal timeouts and retries set by the user +// that are separate from this configuration +type ServiceConfig struct { + RateLimiter common.RateLimiterConfig `toml:"rateLimiter" json:"rateLimiter" yaml:"rateLimiter" mapstructure:"rateLimiter"` +} diff --git a/core/capabilities/webapi/webapicap/event_trigger-schema.json b/core/capabilities/webapi/webapicap/event_trigger-schema.json new file mode 100644 index 00000000000..f7b5997399e --- /dev/null +++ b/core/capabilities/webapi/webapicap/event_trigger-schema.json @@ -0,0 +1,95 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap/web-api-trigger@1.0.0", + "$defs": { + "TriggerConfig": { + "description": "See https://gateway-us-1.chain.link/web-api-trigger", + "type": "object", + "properties": { + "allowedSenders": { + "type": "array", + "items": { + "type": "string" + } + }, + "allowedTopics": { + "type": "array", + "items": { + "type": "string" + } + }, + "rateLimiter": { + "$ref": "#/$defs/RateLimiterConfig" + }, + "requiredParams": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["allowedSenders", "allowedTopics", "rateLimiter", "requiredParams"], + "additionalProperties": false + }, + "RateLimiterConfig": { + "type": "object", + "properties": { + "globalRPS": { + "type": "number" + }, + "globalBurst": { + "type": "integer" + }, + "perSenderRPS": { + "type": "number" + }, + "perSenderBurst": { + "type": "integer" + } + }, + "required": ["globalRPS", "globalBurst", "perSenderRPS", "perSenderBurst"], + "additionalProperties": false + }, + "TriggerRequestPayload": { + "type": "object", + "properties": { + "trigger_id": { + "type": "string", + "description": "ID of the trigger corresponding to the capability ID." + }, + "trigger_event_id": { + "type": "string", + "description": "Uniquely identifies generated event (scoped to trigger_id and sender)." + }, + "timestamp": { + "type": "integer", + "format": "int64", + "description": "Timestamp of the event (unix time), needs to be within certain freshness to be processed." + }, + "topics": { + "type": "array", + "items": { + "type": "string", + "description" : "An array of a single topic (string) to be started by this event." + } + }, + "params": { + "type": "object", + "additionalProperties": true, + "description": "Key-value pairs for the workflow engine, untranslated." + } + }, + "required": ["trigger_id", "trigger_event_id", "timestamp", "topics", "params"], + "additionalProperties": false + } + }, + "type": "object", + "properties": { + "Config": { + "$ref": "#/$defs/TriggerConfig" + }, + "Outputs": { + "$ref": "#/$defs/TriggerRequestPayload" + } + } + } \ No newline at end of file diff --git a/core/capabilities/webapi/webapicap/event_trigger_generated.go b/core/capabilities/webapi/webapicap/event_trigger_generated.go new file mode 100644 index 00000000000..b67a7875ac4 --- /dev/null +++ b/core/capabilities/webapi/webapicap/event_trigger_generated.go @@ -0,0 +1,150 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package webapicap + +import ( + "encoding/json" + "fmt" +) + +type RateLimiterConfig struct { + // GlobalBurst corresponds to the JSON schema field "globalBurst". + GlobalBurst int64 `json:"globalBurst" yaml:"globalBurst" mapstructure:"globalBurst"` + + // GlobalRPS corresponds to the JSON schema field "globalRPS". + GlobalRPS float64 `json:"globalRPS" yaml:"globalRPS" mapstructure:"globalRPS"` + + // PerSenderBurst corresponds to the JSON schema field "perSenderBurst". + PerSenderBurst int64 `json:"perSenderBurst" yaml:"perSenderBurst" mapstructure:"perSenderBurst"` + + // PerSenderRPS corresponds to the JSON schema field "perSenderRPS". + PerSenderRPS float64 `json:"perSenderRPS" yaml:"perSenderRPS" mapstructure:"perSenderRPS"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *RateLimiterConfig) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["globalBurst"]; raw != nil && !ok { + return fmt.Errorf("field globalBurst in RateLimiterConfig: required") + } + if _, ok := raw["globalRPS"]; raw != nil && !ok { + return fmt.Errorf("field globalRPS in RateLimiterConfig: required") + } + if _, ok := raw["perSenderBurst"]; raw != nil && !ok { + return fmt.Errorf("field perSenderBurst in RateLimiterConfig: required") + } + if _, ok := raw["perSenderRPS"]; raw != nil && !ok { + return fmt.Errorf("field perSenderRPS in RateLimiterConfig: required") + } + type Plain RateLimiterConfig + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = RateLimiterConfig(plain) + return nil +} + +type Trigger struct { + // Config corresponds to the JSON schema field "Config". + Config *TriggerConfig `json:"Config,omitempty" yaml:"Config,omitempty" mapstructure:"Config,omitempty"` + + // Outputs corresponds to the JSON schema field "Outputs". + Outputs *TriggerRequestPayload `json:"Outputs,omitempty" yaml:"Outputs,omitempty" mapstructure:"Outputs,omitempty"` +} + +// See https://gateway-us-1.chain.link/web-api-trigger +type TriggerConfig struct { + // AllowedSenders corresponds to the JSON schema field "allowedSenders". + AllowedSenders []string `json:"allowedSenders" yaml:"allowedSenders" mapstructure:"allowedSenders"` + + // AllowedTopics corresponds to the JSON schema field "allowedTopics". + AllowedTopics []string `json:"allowedTopics" yaml:"allowedTopics" mapstructure:"allowedTopics"` + + // RateLimiter corresponds to the JSON schema field "rateLimiter". + RateLimiter RateLimiterConfig `json:"rateLimiter" yaml:"rateLimiter" mapstructure:"rateLimiter"` + + // RequiredParams corresponds to the JSON schema field "requiredParams". + RequiredParams []string `json:"requiredParams" yaml:"requiredParams" mapstructure:"requiredParams"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TriggerConfig) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["allowedSenders"]; raw != nil && !ok { + return fmt.Errorf("field allowedSenders in TriggerConfig: required") + } + if _, ok := raw["allowedTopics"]; raw != nil && !ok { + return fmt.Errorf("field allowedTopics in TriggerConfig: required") + } + if _, ok := raw["rateLimiter"]; raw != nil && !ok { + return fmt.Errorf("field rateLimiter in TriggerConfig: required") + } + if _, ok := raw["requiredParams"]; raw != nil && !ok { + return fmt.Errorf("field requiredParams in TriggerConfig: required") + } + type Plain TriggerConfig + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = TriggerConfig(plain) + return nil +} + +type TriggerRequestPayload struct { + // Key-value pairs for the workflow engine, untranslated. + Params TriggerRequestPayloadParams `json:"params" yaml:"params" mapstructure:"params"` + + // Timestamp of the event (unix time), needs to be within certain freshness to be + // processed. + Timestamp int64 `json:"timestamp" yaml:"timestamp" mapstructure:"timestamp"` + + // Topics corresponds to the JSON schema field "topics". + Topics []string `json:"topics" yaml:"topics" mapstructure:"topics"` + + // Uniquely identifies generated event (scoped to trigger_id and sender). + TriggerEventId string `json:"trigger_event_id" yaml:"trigger_event_id" mapstructure:"trigger_event_id"` + + // ID of the trigger corresponding to the capability ID. + TriggerId string `json:"trigger_id" yaml:"trigger_id" mapstructure:"trigger_id"` +} + +// Key-value pairs for the workflow engine, untranslated. +type TriggerRequestPayloadParams map[string]interface{} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TriggerRequestPayload) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["params"]; raw != nil && !ok { + return fmt.Errorf("field params in TriggerRequestPayload: required") + } + if _, ok := raw["timestamp"]; raw != nil && !ok { + return fmt.Errorf("field timestamp in TriggerRequestPayload: required") + } + if _, ok := raw["topics"]; raw != nil && !ok { + return fmt.Errorf("field topics in TriggerRequestPayload: required") + } + if _, ok := raw["trigger_event_id"]; raw != nil && !ok { + return fmt.Errorf("field trigger_event_id in TriggerRequestPayload: required") + } + if _, ok := raw["trigger_id"]; raw != nil && !ok { + return fmt.Errorf("field trigger_id in TriggerRequestPayload: required") + } + type Plain TriggerRequestPayload + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = TriggerRequestPayload(plain) + return nil +} diff --git a/core/capabilities/webapi/webapicap/gen.go b/core/capabilities/webapi/webapicap/gen.go new file mode 100644 index 00000000000..ac1b7d5272c --- /dev/null +++ b/core/capabilities/webapi/webapicap/gen.go @@ -0,0 +1,5 @@ +package webapicap + +import _ "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd" // Required so that the tool is available to be run in go generate below. + +//go:generate go run github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/generate-types --dir $GOFILE diff --git a/core/capabilities/webapi/webapicap/target_builders_generated.go b/core/capabilities/webapi/webapicap/target_builders_generated.go new file mode 100644 index 00000000000..e406018ac3a --- /dev/null +++ b/core/capabilities/webapi/webapicap/target_builders_generated.go @@ -0,0 +1,43 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package webapicap + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func (cfg TargetConfig) New(w *sdk.WorkflowSpecFactory, input TargetInput) { + + def := sdk.StepDefinition{ + ID: "web-api-target@1.0.0", + Inputs: input.ToSteps(), + Config: map[string]any{ + "deliveryMode": cfg.DeliveryMode, + "retryCount": cfg.RetryCount, + "timeoutMs": cfg.TimeoutMs, + }, + CapabilityType: capabilities.CapabilityTypeTarget, + } + + step := sdk.Step[struct{}]{Definition: def} + step.AddTo(w) +} + +type TargetInput struct { + Body sdk.CapDefinition[string] + Headers sdk.CapDefinition[TargetPayloadHeaders] + Method sdk.CapDefinition[string] + Url sdk.CapDefinition[string] +} + +func (input TargetInput) ToSteps() sdk.StepInputs { + return sdk.StepInputs{ + Mapping: map[string]any{ + "body": input.Body.Ref(), + "headers": input.Headers.Ref(), + "method": input.Method.Ref(), + "url": input.Url.Ref(), + }, + } +} diff --git a/core/capabilities/webapi/webapicap/trigger_builders_generated.go b/core/capabilities/webapi/webapicap/trigger_builders_generated.go new file mode 100644 index 00000000000..296146d4666 --- /dev/null +++ b/core/capabilities/webapi/webapicap/trigger_builders_generated.go @@ -0,0 +1,189 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package webapicap + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func (cfg TriggerConfig) New(w *sdk.WorkflowSpecFactory) TriggerRequestPayloadCap { + ref := "trigger" + def := sdk.StepDefinition{ + ID: "web-api-trigger@1.0.0", Ref: ref, + Inputs: sdk.StepInputs{}, + Config: map[string]any{ + "allowedSenders": cfg.AllowedSenders, + "allowedTopics": cfg.AllowedTopics, + "rateLimiter": cfg.RateLimiter, + "requiredParams": cfg.RequiredParams, + }, + CapabilityType: capabilities.CapabilityTypeTrigger, + } + + step := sdk.Step[TriggerRequestPayload]{Definition: def} + return TriggerRequestPayloadCapFromStep(w, step) +} + +type RateLimiterConfigCap interface { + sdk.CapDefinition[RateLimiterConfig] + GlobalBurst() sdk.CapDefinition[int64] + GlobalRPS() sdk.CapDefinition[float64] + PerSenderBurst() sdk.CapDefinition[int64] + PerSenderRPS() sdk.CapDefinition[float64] + private() +} + +// RateLimiterConfigCapFromStep should only be called from generated code to assure type safety +func RateLimiterConfigCapFromStep(w *sdk.WorkflowSpecFactory, step sdk.Step[RateLimiterConfig]) RateLimiterConfigCap { + raw := step.AddTo(w) + return &rateLimiterConfig{CapDefinition: raw} +} + +type rateLimiterConfig struct { + sdk.CapDefinition[RateLimiterConfig] +} + +func (*rateLimiterConfig) private() {} +func (c *rateLimiterConfig) GlobalBurst() sdk.CapDefinition[int64] { + return sdk.AccessField[RateLimiterConfig, int64](c.CapDefinition, "globalBurst") +} +func (c *rateLimiterConfig) GlobalRPS() sdk.CapDefinition[float64] { + return sdk.AccessField[RateLimiterConfig, float64](c.CapDefinition, "globalRPS") +} +func (c *rateLimiterConfig) PerSenderBurst() sdk.CapDefinition[int64] { + return sdk.AccessField[RateLimiterConfig, int64](c.CapDefinition, "perSenderBurst") +} +func (c *rateLimiterConfig) PerSenderRPS() sdk.CapDefinition[float64] { + return sdk.AccessField[RateLimiterConfig, float64](c.CapDefinition, "perSenderRPS") +} + +func NewRateLimiterConfigFromFields( + globalBurst sdk.CapDefinition[int64], + globalRPS sdk.CapDefinition[float64], + perSenderBurst sdk.CapDefinition[int64], + perSenderRPS sdk.CapDefinition[float64]) RateLimiterConfigCap { + return &simpleRateLimiterConfig{ + CapDefinition: sdk.ComponentCapDefinition[RateLimiterConfig]{ + "globalBurst": globalBurst.Ref(), + "globalRPS": globalRPS.Ref(), + "perSenderBurst": perSenderBurst.Ref(), + "perSenderRPS": perSenderRPS.Ref(), + }, + globalBurst: globalBurst, + globalRPS: globalRPS, + perSenderBurst: perSenderBurst, + perSenderRPS: perSenderRPS, + } +} + +type simpleRateLimiterConfig struct { + sdk.CapDefinition[RateLimiterConfig] + globalBurst sdk.CapDefinition[int64] + globalRPS sdk.CapDefinition[float64] + perSenderBurst sdk.CapDefinition[int64] + perSenderRPS sdk.CapDefinition[float64] +} + +func (c *simpleRateLimiterConfig) GlobalBurst() sdk.CapDefinition[int64] { + return c.globalBurst +} +func (c *simpleRateLimiterConfig) GlobalRPS() sdk.CapDefinition[float64] { + return c.globalRPS +} +func (c *simpleRateLimiterConfig) PerSenderBurst() sdk.CapDefinition[int64] { + return c.perSenderBurst +} +func (c *simpleRateLimiterConfig) PerSenderRPS() sdk.CapDefinition[float64] { + return c.perSenderRPS +} + +func (c *simpleRateLimiterConfig) private() {} + +type TriggerRequestPayloadCap interface { + sdk.CapDefinition[TriggerRequestPayload] + Params() TriggerRequestPayloadParamsCap + Timestamp() sdk.CapDefinition[int64] + Topics() sdk.CapDefinition[[]string] + TriggerEventId() sdk.CapDefinition[string] + TriggerId() sdk.CapDefinition[string] + private() +} + +// TriggerRequestPayloadCapFromStep should only be called from generated code to assure type safety +func TriggerRequestPayloadCapFromStep(w *sdk.WorkflowSpecFactory, step sdk.Step[TriggerRequestPayload]) TriggerRequestPayloadCap { + raw := step.AddTo(w) + return &triggerRequestPayload{CapDefinition: raw} +} + +type triggerRequestPayload struct { + sdk.CapDefinition[TriggerRequestPayload] +} + +func (*triggerRequestPayload) private() {} +func (c *triggerRequestPayload) Params() TriggerRequestPayloadParamsCap { + return TriggerRequestPayloadParamsCap(sdk.AccessField[TriggerRequestPayload, TriggerRequestPayloadParams](c.CapDefinition, "params")) +} +func (c *triggerRequestPayload) Timestamp() sdk.CapDefinition[int64] { + return sdk.AccessField[TriggerRequestPayload, int64](c.CapDefinition, "timestamp") +} +func (c *triggerRequestPayload) Topics() sdk.CapDefinition[[]string] { + return sdk.AccessField[TriggerRequestPayload, []string](c.CapDefinition, "topics") +} +func (c *triggerRequestPayload) TriggerEventId() sdk.CapDefinition[string] { + return sdk.AccessField[TriggerRequestPayload, string](c.CapDefinition, "trigger_event_id") +} +func (c *triggerRequestPayload) TriggerId() sdk.CapDefinition[string] { + return sdk.AccessField[TriggerRequestPayload, string](c.CapDefinition, "trigger_id") +} + +func NewTriggerRequestPayloadFromFields( + params TriggerRequestPayloadParamsCap, + timestamp sdk.CapDefinition[int64], + topics sdk.CapDefinition[[]string], + triggerEventId sdk.CapDefinition[string], + triggerId sdk.CapDefinition[string]) TriggerRequestPayloadCap { + return &simpleTriggerRequestPayload{ + CapDefinition: sdk.ComponentCapDefinition[TriggerRequestPayload]{ + "params": params.Ref(), + "timestamp": timestamp.Ref(), + "topics": topics.Ref(), + "trigger_event_id": triggerEventId.Ref(), + "trigger_id": triggerId.Ref(), + }, + params: params, + timestamp: timestamp, + topics: topics, + triggerEventId: triggerEventId, + triggerId: triggerId, + } +} + +type simpleTriggerRequestPayload struct { + sdk.CapDefinition[TriggerRequestPayload] + params TriggerRequestPayloadParamsCap + timestamp sdk.CapDefinition[int64] + topics sdk.CapDefinition[[]string] + triggerEventId sdk.CapDefinition[string] + triggerId sdk.CapDefinition[string] +} + +func (c *simpleTriggerRequestPayload) Params() TriggerRequestPayloadParamsCap { + return c.params +} +func (c *simpleTriggerRequestPayload) Timestamp() sdk.CapDefinition[int64] { + return c.timestamp +} +func (c *simpleTriggerRequestPayload) Topics() sdk.CapDefinition[[]string] { + return c.topics +} +func (c *simpleTriggerRequestPayload) TriggerEventId() sdk.CapDefinition[string] { + return c.triggerEventId +} +func (c *simpleTriggerRequestPayload) TriggerId() sdk.CapDefinition[string] { + return c.triggerId +} + +func (c *simpleTriggerRequestPayload) private() {} + +type TriggerRequestPayloadParamsCap sdk.CapDefinition[TriggerRequestPayloadParams] diff --git a/core/capabilities/webapi/webapicap/webapi_target-schema.json b/core/capabilities/webapi/webapicap/webapi_target-schema.json new file mode 100644 index 00000000000..22d6a6171af --- /dev/null +++ b/core/capabilities/webapi/webapicap/webapi_target-schema.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap/web-api-target@1.0.0", + "description": "A target that sends HTTP requests to a URL", + "$defs": { + "TargetPayload": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "The URL to send the request to" + }, + "method": { + "type": "string", + "description": "The HTTP method to use for the request" + }, + "headers": { + "type": "object", + "description": "The headers to include in the request", + "additionalProperties" : { + "type": "string" + } + }, + "body": { + "type": "string", + "description": "The body of the request" + } + }, + "required": ["url"], + "additionalProperties": false + }, + "TargetConfig": { + "type": "object", + "properties": { + "timeoutMs": { + "type": "integer", + "description": "The timeout in milliseconds for the request. If set to 0, the default value is 30 seconds", + "minimum": 0, + "maximum": 600000 + }, + "retryCount": { + "type": "integer", + "description": "The number of times to retry the request. Defaults to 0 retries", + "minimum": 0, + "maximum": 10 + }, + "deliveryMode": { + "type": "string", + "description": "The delivery mode for the request. Defaults to SingleNode" + } + }, + "required": [], + "additionalProperties": false + } + }, + "type": "object", + "properties": { + "config": { + "$ref": "#/$defs/TargetConfig" + }, + "inputs": { + "$ref": "#/$defs/TargetPayload" + } + }, + "required": ["config","inputs"] + } \ No newline at end of file diff --git a/core/capabilities/webapi/webapicap/webapi_target_generated.go b/core/capabilities/webapi/webapicap/webapi_target_generated.go new file mode 100644 index 00000000000..470b6307514 --- /dev/null +++ b/core/capabilities/webapi/webapicap/webapi_target_generated.go @@ -0,0 +1,102 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package webapicap + +import ( + "encoding/json" + "fmt" +) + +// A target that sends HTTP requests to a URL +type Target struct { + // Config corresponds to the JSON schema field "config". + Config TargetConfig `json:"config" yaml:"config" mapstructure:"config"` + + // Inputs corresponds to the JSON schema field "inputs". + Inputs TargetPayload `json:"inputs" yaml:"inputs" mapstructure:"inputs"` +} + +type TargetConfig struct { + // The delivery mode for the request. Defaults to SingleNode + DeliveryMode *string `json:"deliveryMode,omitempty" yaml:"deliveryMode,omitempty" mapstructure:"deliveryMode,omitempty"` + + // The number of times to retry the request. Defaults to 0 retries + RetryCount *uint8 `json:"retryCount,omitempty" yaml:"retryCount,omitempty" mapstructure:"retryCount,omitempty"` + + // The timeout in milliseconds for the request. If set to 0, the default value is + // 30 seconds + TimeoutMs *uint32 `json:"timeoutMs,omitempty" yaml:"timeoutMs,omitempty" mapstructure:"timeoutMs,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TargetConfig) UnmarshalJSON(b []byte) error { + type Plain TargetConfig + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.RetryCount != nil && 10 < *plain.RetryCount { + return fmt.Errorf("field %s: must be <= %v", "retryCount", 10) + } + if plain.TimeoutMs != nil && 600000 < *plain.TimeoutMs { + return fmt.Errorf("field %s: must be <= %v", "timeoutMs", 600000) + } + *j = TargetConfig(plain) + return nil +} + +type TargetPayload struct { + // The body of the request + Body *string `json:"body,omitempty" yaml:"body,omitempty" mapstructure:"body,omitempty"` + + // The headers to include in the request + Headers TargetPayloadHeaders `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // The HTTP method to use for the request + Method *string `json:"method,omitempty" yaml:"method,omitempty" mapstructure:"method,omitempty"` + + // The URL to send the request to + Url string `json:"url" yaml:"url" mapstructure:"url"` +} + +// The headers to include in the request +type TargetPayloadHeaders map[string]string + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TargetPayload) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["url"]; raw != nil && !ok { + return fmt.Errorf("field url in TargetPayload: required") + } + type Plain TargetPayload + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = TargetPayload(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Target) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["config"]; raw != nil && !ok { + return fmt.Errorf("field config in Target: required") + } + if _, ok := raw["inputs"]; raw != nil && !ok { + return fmt.Errorf("field inputs in Target: required") + } + type Plain Target + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Target(plain) + return nil +} diff --git a/core/capabilities/webapi/webapicap/webapicaptest/target_mock_generated.go b/core/capabilities/webapi/webapicap/webapicaptest/target_mock_generated.go new file mode 100644 index 00000000000..99e9d1ed1c5 --- /dev/null +++ b/core/capabilities/webapi/webapicap/webapicaptest/target_mock_generated.go @@ -0,0 +1,17 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package webapicaptest + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk/testutils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap" +) + +// Target registers a new capability mock with the runner +func Target(runner *testutils.Runner, fn func(input webapicap.TargetPayload) error) *testutils.TargetMock[webapicap.TargetPayload] { + mock := testutils.MockTarget[webapicap.TargetPayload]("web-api-target@1.0.0", fn) + runner.MockCapability("web-api-target@1.0.0", nil, mock) + return mock +} diff --git a/core/capabilities/webapi/webapicap/webapicaptest/trigger_mock_generated.go b/core/capabilities/webapi/webapicap/webapicaptest/trigger_mock_generated.go new file mode 100644 index 00000000000..025c22eb61f --- /dev/null +++ b/core/capabilities/webapi/webapicap/webapicaptest/trigger_mock_generated.go @@ -0,0 +1,17 @@ +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +// Code generated by github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli, DO NOT EDIT. + +package webapicaptest + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk/testutils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap" +) + +// Trigger registers a new capability mock with the runner +func Trigger(runner *testutils.Runner, fn func() (webapicap.TriggerRequestPayload, error)) *testutils.TriggerMock[webapicap.TriggerRequestPayload] { + mock := testutils.MockTrigger[webapicap.TriggerRequestPayload]("web-api-trigger@1.0.0", fn) + runner.MockCapability("web-api-trigger@1.0.0", nil, mock) + return mock +} diff --git a/core/chainlink.goreleaser.Dockerfile b/core/chainlink.goreleaser.Dockerfile index c35fe015cbd..eb359376006 100644 --- a/core/chainlink.goreleaser.Dockerfile +++ b/core/chainlink.goreleaser.Dockerfile @@ -1,12 +1,12 @@ # This will replace chainlink.Dockerfile once all builds are migrated to goreleaser # Final image: ubuntu with chainlink binary -FROM ubuntu:20.04 +FROM ubuntu:24.04 ARG CHAINLINK_USER=root ARG TARGETARCH ENV DEBIAN_FRONTEND noninteractive -RUN apt-get update && apt-get install -y ca-certificates gnupg lsb-release curl patchelf +RUN apt-get update && apt-get install -y ca-certificates gnupg lsb-release curl # Install Postgres for CLI tools, needed specifically for DB backups RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ @@ -18,11 +18,12 @@ RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ COPY ./chainlink /usr/local/bin/ # Copy native libs if cgo is enabled -COPY ./tmp/linux_${TARGETARCH}/libs /usr/local/bin/libs +COPY ./tmp/libs /usr/local/bin/libs # Copy plugins if exist and enable them # https://stackoverflow.com/questions/70096208/dockerfile-copy-folder-if-it-exists-conditional-copy/70096420#70096420 -COPY ./tmp/linux_${TARGETARCH}/plugin[s] /usr/local/bin/ +COPY ./tm[p]/plugin[s]/ /usr/local/bin/ + # Allow individual plugins to be enabled by supplying their path ARG CL_MEDIAN_CMD ARG CL_MERCURY_CMD @@ -32,11 +33,11 @@ ENV CL_MEDIAN_CMD=${CL_MEDIAN_CMD} \ CL_MERCURY_CMD=${CL_MERCURY_CMD} \ CL_SOLANA_CMD=${CL_SOLANA_CMD} \ CL_STARKNET_CMD=${CL_STARKNET_CMD} -# Temp fix to patch correctly link the libwasmvm.so -COPY ./tools/bin/ldd_fix /usr/local/bin/ldd_fix -RUN chmod +x /usr/local/bin/ldd_fix -RUN /usr/local/bin/ldd_fix -RUN apt-get remove -y patchelf + +# CCIP specific +COPY ./cci[p]/confi[g] /chainlink/ccip-config +ARG CL_CHAIN_DEFAULTS +ENV CL_CHAIN_DEFAULTS=${CL_CHAIN_DEFAULTS} RUN if [ ${CHAINLINK_USER} != root ]; then \ useradd --uid 14933 --create-home ${CHAINLINK_USER}; \ diff --git a/core/chains/chain_kv_test.go b/core/chains/chain_kv_test.go index 205ee693d6f..7c9336285e8 100644 --- a/core/chains/chain_kv_test.go +++ b/core/chains/chain_kv_test.go @@ -89,6 +89,11 @@ func (s *testChainService) HealthReport() map[string]error { return map[string]error{} } +// Implement [types.LatestHead] interface +func (s *testChainService) LatestHead(_ context.Context) (head types.Head, err error) { + return +} + // Implement [types.ChainService] interface func (s *testChainService) GetChainStatus(ctx context.Context) (stat types.ChainStatus, err error) { return diff --git a/core/chains/config.go b/core/chains/config.go index 3556c33a785..73e1e87f146 100644 --- a/core/chains/config.go +++ b/core/chains/config.go @@ -6,8 +6,9 @@ import ( var ( // ErrChainIDEmpty is returned when chain is required but was empty. - ErrChainIDEmpty = errors.New("chain id empty") - ErrNotFound = errors.New("not found") + ErrChainIDEmpty = errors.New("chain id empty") + ErrNotFound = errors.New("not found") + ErrMultipleChainFound = errors.New("multiple chains found with the same chain ID") ) // ChainOpts holds options for configuring a Chain diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index c27d294ebfd..0fc14861ed0 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -3,6 +3,7 @@ package client import ( "context" "math/big" + "sync" "time" "github.com/ethereum/go-ethereum" @@ -12,9 +13,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/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" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -30,8 +29,6 @@ type Client interface { Close() // ChainID locally stored for quick access ConfiguredChainID() *big.Int - // ChainID RPC call - ChainID() (*big.Int, error) // NodeStates returns a map of node Name->node state // It might be nil or empty, e.g. for mock clients etc @@ -56,7 +53,7 @@ type Client interface { // correct hash from the RPC response. HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) HeadByHash(ctx context.Context, n common.Hash) (*evmtypes.Head, error) - SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) + SubscribeToHeads(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) // LatestFinalizedBlock - returns the latest finalized block as it's returned from an RPC. // CAUTION: Using this method might cause local finality violations. It's highly recommended // to use HeadTracker to get latest finalized block. @@ -73,7 +70,7 @@ type Client interface { CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) - SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) + NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, error) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) @@ -84,6 +81,7 @@ type Client interface { SuggestGasPrice(ctx context.Context) (*big.Int, error) SuggestGasTipCap(ctx context.Context) (*big.Int, error) LatestBlockHeight(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) HeaderByNumber(ctx context.Context, n *big.Int) (*types.Header, error) HeaderByHash(ctx context.Context, h common.Hash) (*types.Header, error) @@ -102,21 +100,11 @@ func ContextWithDefaultTimeout() (ctx context.Context, cancel context.CancelFunc } type chainClient struct { - multiNode commonclient.MultiNode[ + multiNode *commonclient.MultiNode[ *big.Int, - evmtypes.Nonce, - common.Address, - common.Hash, - *types.Transaction, - common.Hash, - types.Log, - ethereum.FilterQuery, - *evmtypes.Receipt, - *assets.Wei, - *evmtypes.Head, - RPCClient, - rpc.BatchElem, + *RPCClient, ] + txSender *commonclient.TransactionSender[*types.Transaction, *big.Int, *RPCClient] logger logger.SugaredLogger chainType chaintype.ChainType clientErrors evmconfig.ClientErrors @@ -126,38 +114,53 @@ func NewChainClient( lggr logger.Logger, selectionMode string, leaseDuration time.Duration, - noNewHeadsThreshold time.Duration, - nodes []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient], - sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient], + nodes []commonclient.Node[*big.Int, *RPCClient], + sendonlys []commonclient.SendOnlyNode[*big.Int, *RPCClient], chainID *big.Int, - chainType chaintype.ChainType, clientErrors evmconfig.ClientErrors, deathDeclarationDelay time.Duration, + chainType chaintype.ChainType, ) Client { - multiNode := commonclient.NewMultiNode( + chainFamily := "EVM" + multiNode := commonclient.NewMultiNode[*big.Int, *RPCClient]( lggr, selectionMode, leaseDuration, - noNewHeadsThreshold, nodes, sendonlys, chainID, - "EVM", - func(tx *types.Transaction, err error) commonclient.SendTxReturnCode { - return ClassifySendError(err, clientErrors, logger.Sugared(logger.Nop()), tx, common.Address{}, chainType.IsL2()) - }, - 0, // use the default value provided by the implementation + chainFamily, deathDeclarationDelay, ) + + classifySendError := func(tx *types.Transaction, err error) commonclient.SendTxReturnCode { + return ClassifySendError(err, clientErrors, logger.Sugared(logger.Nop()), tx, common.Address{}, chainType.IsL2()) + } + + txSender := commonclient.NewTransactionSender[*types.Transaction, *big.Int, *RPCClient]( + lggr, + chainID, + chainFamily, + multiNode, + classifySendError, + 0, // use the default value provided by the implementation + ) + return &chainClient{ multiNode: multiNode, + txSender: txSender, logger: logger.Sugared(lggr), + chainType: chainType, clientErrors: clientErrors, } } func (c *chainClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { - return c.multiNode.BalanceAt(ctx, account, blockNumber) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.BalanceAt(ctx, account, blockNumber) } // BatchCallContext - sends all given requests as a single batch. @@ -168,95 +171,170 @@ func (c *chainClient) BalanceAt(ctx context.Context, account common.Address, blo // might not be properly handled and returned results might have weaker finality guarantees. It's highly recommended // to use HeadTracker to identify latest finalized block. func (c *chainClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - return c.multiNode.BatchCallContext(ctx, b) + r, err := c.multiNode.SelectRPC() + if err != nil { + return err + } + return r.BatchCallContext(ctx, b) } // Similar to BatchCallContext, ensure the provided BatchElem slice is passed through func (c *chainClient) BatchCallContextAll(ctx context.Context, b []rpc.BatchElem) error { - return c.multiNode.BatchCallContextAll(ctx, b) + if c.chainType == chaintype.ChainHedera { + activeRPC, err := c.multiNode.SelectRPC() + if err != nil { + return err + } + + return activeRPC.BatchCallContext(ctx, b) + } + + var wg sync.WaitGroup + defer wg.Wait() + + // Select main RPC to use for return value + main, selectionErr := c.multiNode.SelectRPC() + + doFunc := func(ctx context.Context, rpc *RPCClient, isSendOnly bool) { + if rpc == main { + return + } + // Parallel call made to all other nodes with ignored return value + wg.Add(1) + go func(rpc *RPCClient) { + defer wg.Done() + err := rpc.BatchCallContext(ctx, b) + if err != nil { + c.logger.Debugw("Secondary node BatchCallContext failed", "err", err) + } else { + c.logger.Debug("Secondary node BatchCallContext success") + } + }(rpc) + } + + if err := c.multiNode.DoAll(ctx, doFunc); err != nil { + return err + } + + if selectionErr != nil { + return selectionErr + } + + return main.BatchCallContext(ctx, b) } // TODO-1663: return custom Block type instead of geth's once client.go is deprecated. func (c *chainClient) BlockByHash(ctx context.Context, hash common.Hash) (b *types.Block, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return b, err } - return rpc.BlockByHashGeth(ctx, hash) + return r.BlockByHashGeth(ctx, hash) } // TODO-1663: return custom Block type instead of geth's once client.go is deprecated. func (c *chainClient) BlockByNumber(ctx context.Context, number *big.Int) (b *types.Block, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return b, err } - return rpc.BlockByNumberGeth(ctx, number) + return r.BlockByNumberGeth(ctx, number) } func (c *chainClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - return c.multiNode.CallContext(ctx, result, method, args...) + r, err := c.multiNode.SelectRPC() + if err != nil { + return err + } + return r.CallContext(ctx, result, method, args...) } func (c *chainClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - return c.multiNode.CallContract(ctx, msg, blockNumber) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.CallContract(ctx, msg, blockNumber) } func (c *chainClient) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { - return c.multiNode.PendingCallContract(ctx, msg) -} - -// TODO-1663: change this to actual ChainID() call once client.go is deprecated. -func (c *chainClient) ChainID() (*big.Int, error) { - //return c.multiNode.ChainID(ctx), nil - return c.multiNode.ConfiguredChainID(), nil + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.PendingCallContract(ctx, msg) } func (c *chainClient) Close() { - c.multiNode.Close() + _ = c.txSender.Close() + _ = c.multiNode.Close() } func (c *chainClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { - return c.multiNode.CodeAt(ctx, account, blockNumber) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.CodeAt(ctx, account, blockNumber) } func (c *chainClient) ConfiguredChainID() *big.Int { - return c.multiNode.ConfiguredChainID() + return c.multiNode.ChainID() } func (c *chainClient) Dial(ctx context.Context) error { - return c.multiNode.Dial(ctx) + err := c.multiNode.Start(ctx) + if err != nil { + return err + } + return c.txSender.Start(ctx) } func (c *chainClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { - return c.multiNode.EstimateGas(ctx, call) + r, err := c.multiNode.SelectRPC() + if err != nil { + return 0, err + } + return r.EstimateGas(ctx, call) } func (c *chainClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { - return c.multiNode.FilterEvents(ctx, q) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.FilterEvents(ctx, q) } func (c *chainClient) HeaderByHash(ctx context.Context, h common.Hash) (head *types.Header, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return head, err } - return rpc.HeaderByHash(ctx, h) + return r.HeaderByHash(ctx, h) } func (c *chainClient) HeaderByNumber(ctx context.Context, n *big.Int) (head *types.Header, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return head, err } - return rpc.HeaderByNumber(ctx, n) + return r.HeaderByNumber(ctx, n) } func (c *chainClient) HeadByHash(ctx context.Context, h common.Hash) (*evmtypes.Head, error) { - return c.multiNode.BlockByHash(ctx, h) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.BlockByHash(ctx, h) } func (c *chainClient) HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) { - return c.multiNode.BlockByNumber(ctx, n) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.BlockByNumber(ctx, n) } func (c *chainClient) IsL2() bool { @@ -264,11 +342,19 @@ func (c *chainClient) IsL2() bool { } func (c *chainClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*commonassets.Link, error) { - return c.multiNode.LINKBalance(ctx, address, linkAddress) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.LINKBalance(ctx, address, linkAddress) } func (c *chainClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) { - return c.multiNode.LatestBlockHeight(ctx) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.LatestBlockHeight(ctx) } func (c *chainClient) NodeStates() map[string]string { @@ -276,21 +362,33 @@ func (c *chainClient) NodeStates() map[string]string { } func (c *chainClient) PendingCodeAt(ctx context.Context, account common.Address) (b []byte, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return b, err } - return rpc.PendingCodeAt(ctx, account) + return r.PendingCodeAt(ctx, account) } // TODO-1663: change this to evmtypes.Nonce(int64) once client.go is deprecated. func (c *chainClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - n, err := c.multiNode.PendingSequenceAt(ctx, account) + r, err := c.multiNode.SelectRPC() + if err != nil { + return 0, err + } + n, err := r.PendingSequenceAt(ctx, account) return uint64(n), err } func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - return c.multiNode.SendTransaction(ctx, tx) + if c.chainType == chaintype.ChainHedera { + activeRPC, err := c.multiNode.SelectRPC() + if err != nil { + return err + } + return activeRPC.SendTransaction(ctx, tx) + } + _, err := c.txSender.SendTransaction(ctx, tx) + return err } func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { @@ -299,58 +397,92 @@ func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.T return returnCode, err } -func (c *chainClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) { - return c.multiNode.SequenceAt(ctx, account, blockNumber) +func (c *chainClient) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + r, err := c.multiNode.SelectRPC() + if err != nil { + return 0, err + } + return r.NonceAt(ctx, account, blockNumber) } func (c *chainClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (s ethereum.Subscription, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return s, err } - return rpc.SubscribeFilterLogs(ctx, q, ch) + return r.SubscribeFilterLogs(ctx, q, ch) } -func (c *chainClient) SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) { - return c.multiNode.SubscribeNewHead(ctx, ch) +func (c *chainClient) SubscribeToHeads(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, nil, err + } + + ch, sub, err := r.SubscribeToHeads(ctx) + if err != nil { + return nil, nil, err + } + + return ch, sub, nil } func (c *chainClient) SuggestGasPrice(ctx context.Context) (p *big.Int, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return p, err } - return rpc.SuggestGasPrice(ctx) + return r.SuggestGasPrice(ctx) } func (c *chainClient) SuggestGasTipCap(ctx context.Context) (t *big.Int, err error) { - rpc, err := c.multiNode.SelectNodeRPC() + r, err := c.multiNode.SelectRPC() if err != nil { return t, err } - return rpc.SuggestGasTipCap(ctx) + return r.SuggestGasTipCap(ctx) } func (c *chainClient) TokenBalance(ctx context.Context, address common.Address, contractAddress common.Address) (*big.Int, error) { - return c.multiNode.TokenBalance(ctx, address, contractAddress) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.TokenBalance(ctx, address, contractAddress) } func (c *chainClient) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, error) { - return c.multiNode.TransactionByHash(ctx, txHash) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.TransactionByHash(ctx, txHash) } // TODO-1663: return custom Receipt type instead of geth's once client.go is deprecated. -func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (r *types.Receipt, err error) { - rpc, err := c.multiNode.SelectNodeRPC() +func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { + r, err := c.multiNode.SelectRPC() if err != nil { - return r, err + return receipt, err } //return rpc.TransactionReceipt(ctx, txHash) - return rpc.TransactionReceiptGeth(ctx, txHash) + return r.TransactionReceiptGeth(ctx, txHash) } func (c *chainClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, error) { - return c.multiNode.LatestFinalizedBlock(ctx) + r, err := c.multiNode.SelectRPC() + if err != nil { + return nil, err + } + return r.LatestFinalizedBlock(ctx) +} + +func (c *chainClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + r, err := c.multiNode.SelectRPC() + if err != nil { + return feeHistory, err + } + return r.FeeHistory(ctx, blockCount, rewardPercentiles) } func (c *chainClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError { diff --git a/core/chains/evm/client/chain_client_test.go b/core/chains/evm/client/chain_client_test.go index 47041e40e91..77e11db7a90 100644 --- a/core/chains/evm/client/chain_client_test.go +++ b/core/chains/evm/client/chain_client_test.go @@ -21,16 +21,13 @@ import ( "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" 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/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -451,6 +448,20 @@ func TestEthClient_SendTransaction_WithSecondaryURLs(t *testing.T) { require.Eventually(t, func() bool { return service.sentCount.Load() == int32(2) }, tests.WaitTimeout(t), 500*time.Millisecond) } +type sendTxService struct { + chainID *big.Int + sentCount atomic.Int32 +} + +func (x *sendTxService) ChainID(ctx context.Context) (*hexutil.Big, error) { + return (*hexutil.Big)(x.chainID), nil +} + +func (x *sendTxService) SendRawTransaction(ctx context.Context, signRawTx hexutil.Bytes) error { + x.sentCount.Add(1) + return nil +} + func TestEthClient_SendTransactionReturnCode(t *testing.T) { t.Parallel() @@ -691,20 +702,6 @@ func TestEthClient_SendTransactionReturnCode(t *testing.T) { }) } -type sendTxService struct { - chainID *big.Int - sentCount atomic.Int32 -} - -func (x *sendTxService) ChainId(ctx context.Context) (*hexutil.Big, error) { - return (*hexutil.Big)(x.chainID), nil -} - -func (x *sendTxService) SendRawTransaction(ctx context.Context, signRawTx hexutil.Bytes) error { - x.sentCount.Add(1) - return nil -} - func TestEthClient_SubscribeNewHead(t *testing.T) { t.Parallel() @@ -729,8 +726,7 @@ func TestEthClient_SubscribeNewHead(t *testing.T) { err := ethClient.Dial(tests.Context(t)) require.NoError(t, err) - headCh := make(chan *evmtypes.Head) - sub, err := ethClient.SubscribeNewHead(ctx, headCh) + headCh, sub, err := ethClient.SubscribeToHeads(ctx) require.NoError(t, err) select { @@ -745,55 +741,49 @@ func TestEthClient_SubscribeNewHead(t *testing.T) { sub.Unsubscribe() } -func newMockRpc(t *testing.T) *mocks.RPCClient { - mockRpc := mocks.NewRPCClient(t) - mockRpc.On("Dial", mock.Anything).Return(nil).Once() - mockRpc.On("Close").Return(nil).Once() - mockRpc.On("ChainID", mock.Anything).Return(testutils.FixtureChainID, nil).Once() - // node does not always manage to fully setup aliveLoop, so we have to make calls optional to avoid flakes - mockRpc.On("SubscribeToHeads", mock.Anything).Return(nil, client.NewMockSubscription(), nil).Maybe() - mockRpc.On("SetAliveLoopSub", mock.Anything).Return().Maybe() - return mockRpc -} - -func TestChainClient_BatchCallContext(t *testing.T) { +func TestEthClient_BatchCallContext(t *testing.T) { t.Parallel() t.Run("batch requests return errors", func(t *testing.T) { - ctx := tests.Context(t) rpcError := errors.New("something went wrong") - blockNumResp := "" - blockNum := hexutil.EncodeBig(big.NewInt(42)) b := []rpc.BatchElem{ { - Method: "eth_getBlockByNumber", - Args: []interface{}{blockNum, true}, - Result: &types.Block{}, + Method: "eth_call", + Args: []interface{}{0}, + Result: "", }, { - Method: "eth_blockNumber", - Result: &blockNumResp, + Method: "eth_call", + Args: []interface{}{1}, + Result: "", }, } - mockRpc := newMockRpc(t) - mockRpc.On("GetInterceptedChainInfo").Return(commonclient.ChainInfo{}, commonclient.ChainInfo{}).Maybe() - mockRpc.On("BatchCallContext", mock.Anything, b).Run(func(args mock.Arguments) { - reqs := args.Get(1).([]rpc.BatchElem) - for i := 0; i < len(reqs); i++ { - elem := &reqs[i] - elem.Error = rpcError + wsURL := testutils.NewWSServer(t, testutils.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + switch method { + case "eth_subscribe": + resp.Result = `"0x00"` + resp.Notify = headResult + return + case "eth_unsubscribe": + resp.Result = "true" + return } - }).Return(nil).Once() + require.Equal(t, "eth_call", method) + resp.Error.Code = -1 + resp.Error.Message = rpcError.Error() + resp.Result = "" + return + }).WSURL().String() - client := client.NewChainClientWithMockedRpc(t, commonclient.NodeSelectionModeRoundRobin, time.Second*0, time.Second*0, testutils.FixtureChainID, mockRpc) - err := client.Dial(ctx) + ethClient := mustNewChainClient(t, wsURL) + err := ethClient.Dial(tests.Context(t)) require.NoError(t, err) - err = client.BatchCallContext(ctx, b) + err = ethClient.BatchCallContext(context.Background(), b) require.NoError(t, err) for _, elem := range b { - require.ErrorIs(t, rpcError, elem.Error) + require.Equal(t, elem.Error.Error(), rpcError.Error()) } }) } @@ -826,11 +816,8 @@ func TestEthClient_ErroringClient(t *testing.T) { _, err = erroringClient.CallContract(ctx, ethereum.CallMsg{}, nil) require.Equal(t, err, commonclient.ErroringNodeError) - // TODO-1663: test actual ChainID() call once client.go is deprecated. - id, err := erroringClient.ChainID() - require.Equal(t, id, testutils.FixtureChainID) - //require.Equal(t, err, commonclient.ErroringNodeError) - require.Equal(t, err, nil) + id := erroringClient.ConfiguredChainID() + require.Equal(t, id, big.NewInt(0)) _, err = erroringClient.CodeAt(ctx, common.Address{}, nil) require.Equal(t, err, commonclient.ErroringNodeError) @@ -871,20 +858,22 @@ func TestEthClient_ErroringClient(t *testing.T) { _, err = erroringClient.PendingNonceAt(ctx, common.Address{}) require.Equal(t, err, commonclient.ErroringNodeError) + txSenderNotStarted := errors.New("TransactionSender not started") err = erroringClient.SendTransaction(ctx, nil) - require.Equal(t, err, commonclient.ErroringNodeError) + require.Equal(t, err, txSenderNotStarted) - code, err := erroringClient.SendTransactionReturnCode(ctx, nil, common.Address{}) + 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, commonclient.ErroringNodeError) + require.Equal(t, err, txSenderNotStarted) - _, err = erroringClient.SequenceAt(ctx, common.Address{}, nil) + _, err = erroringClient.NonceAt(ctx, common.Address{}, nil) require.Equal(t, err, commonclient.ErroringNodeError) _, err = erroringClient.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, nil) require.Equal(t, err, commonclient.ErroringNodeError) - _, err = erroringClient.SubscribeNewHead(ctx, nil) + _, _, err = erroringClient.SubscribeToHeads(ctx) require.Equal(t, err, commonclient.ErroringNodeError) _, err = erroringClient.SuggestGasPrice(ctx) diff --git a/core/chains/evm/client/config_builder.go b/core/chains/evm/client/config_builder.go index fa702bac111..66bdfc2614f 100644 --- a/core/chains/evm/client/config_builder.go +++ b/core/chains/evm/client/config_builder.go @@ -43,7 +43,7 @@ func NewClientConfigs( deathDeclarationDelay time.Duration, noNewFinalizedHeadsThreshold time.Duration, finalizedBlockPollInterval time.Duration, - + newHeadsPollInterval time.Duration, ) (commonclient.ChainConfig, evmconfig.NodePool, []*toml.Node, error) { nodes, err := parseNodeConfigs(nodeCfgs) if err != nil { @@ -59,12 +59,13 @@ func NewClientConfigs( EnforceRepeatableRead: enforceRepeatableRead, DeathDeclarationDelay: commonconfig.MustNewDuration(deathDeclarationDelay), FinalizedBlockPollInterval: commonconfig.MustNewDuration(finalizedBlockPollInterval), + NewHeadsPollInterval: commonconfig.MustNewDuration(newHeadsPollInterval), } nodePoolCfg := &evmconfig.NodePoolConfig{C: nodePool} chainConfig := &evmconfig.EVMConfig{ C: &toml.EVMConfig{ Chain: toml.Chain{ - ChainType: chaintype.NewChainTypeConfig(chainType), + ChainType: chaintype.NewConfig(chainType), FinalityDepth: finalityDepth, FinalityTagEnabled: finalityTagEnabled, NoNewHeadsThreshold: commonconfig.MustNewDuration(noNewHeadsThreshold), @@ -79,15 +80,21 @@ func NewClientConfigs( func parseNodeConfigs(nodeCfgs []NodeConfig) ([]*toml.Node, error) { nodes := make([]*toml.Node, len(nodeCfgs)) for i, nodeCfg := range nodeCfgs { - if nodeCfg.WSURL == nil || nodeCfg.HTTPURL == nil { - return nil, fmt.Errorf("node config [%d]: missing WS or HTTP URL", i) + var wsURL, httpURL *commonconfig.URL + // wsUrl requirement will be checked in EVMConfig validation + if nodeCfg.WSURL != nil { + wsURL = commonconfig.MustParseURL(*nodeCfg.WSURL) + } + + if nodeCfg.HTTPURL == nil { + return nil, fmt.Errorf("node config [%d]: missing HTTP URL", i) } - wsUrl := commonconfig.MustParseURL(*nodeCfg.WSURL) - httpUrl := commonconfig.MustParseURL(*nodeCfg.HTTPURL) + + httpURL = commonconfig.MustParseURL(*nodeCfg.HTTPURL) node := &toml.Node{ Name: nodeCfg.Name, - WSURL: wsUrl, - HTTPURL: httpUrl, + WSURL: wsURL, + HTTPURL: httpURL, SendOnly: nodeCfg.SendOnly, Order: nodeCfg.Order, } diff --git a/core/chains/evm/client/config_builder_test.go b/core/chains/evm/client/config_builder_test.go index 403c6c2d619..856242edada 100644 --- a/core/chains/evm/client/config_builder_test.go +++ b/core/chains/evm/client/config_builder_test.go @@ -37,9 +37,11 @@ func TestClientConfigBuilder(t *testing.T) { finalityDepth := ptr(uint32(10)) finalityTagEnabled := ptr(true) noNewHeadsThreshold := time.Second + newHeadsPollInterval := 0 * time.Second chainCfg, nodePool, nodes, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, - finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead, deathDeclarationDelay, noNewFinalizedBlocksThreshold, pollInterval) + finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead, deathDeclarationDelay, noNewFinalizedBlocksThreshold, + pollInterval, newHeadsPollInterval) require.NoError(t, err) // Validate node pool configs @@ -52,6 +54,7 @@ func TestClientConfigBuilder(t *testing.T) { require.Equal(t, *enforceRepeatableRead, nodePool.EnforceRepeatableRead()) require.Equal(t, deathDeclarationDelay, nodePool.DeathDeclarationDelay()) require.Equal(t, pollInterval, nodePool.FinalizedBlockPollInterval()) + require.Equal(t, newHeadsPollInterval, nodePool.NewHeadsPollInterval()) // Validate node configs require.Equal(t, *nodeConfigs[0].Name, *nodes[0].Name) @@ -66,7 +69,7 @@ func TestClientConfigBuilder(t *testing.T) { require.Equal(t, noNewFinalizedBlocksThreshold, chainCfg.NoNewFinalizedHeadsThreshold()) // let combiler tell us, when we do not have sufficient data to create evm client - _ = client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), big.NewInt(10), nodes, chaintype.ChainType(chainTypeStr)) + _, _ = client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), big.NewInt(10), nodes, chaintype.ChainType(chainTypeStr)) } func TestNodeConfigs(t *testing.T) { @@ -90,7 +93,7 @@ func TestNodeConfigs(t *testing.T) { require.Len(t, tomlNodes, len(nodeConfigs)) }) - t.Run("parsing missing ws url fails", func(t *testing.T) { + t.Run("ws can be optional", func(t *testing.T) { nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), @@ -98,7 +101,7 @@ func TestNodeConfigs(t *testing.T) { }, } _, err := client.ParseTestNodeConfigs(nodeConfigs) - require.Error(t, err) + require.Nil(t, err) }) t.Run("parsing missing http url fails", func(t *testing.T) { diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index 5980b0dd963..d47d97660b1 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -62,6 +63,7 @@ const ( Fatal ServiceUnavailable TerminallyStuck + TooManyResults ) type ClientErrors map[int]*regexp.Regexp @@ -253,7 +255,7 @@ var zkSync = ClientErrors{ } var zkEvm = ClientErrors{ - TerminallyStuck: regexp.MustCompile(`(?:: |^)not enough .* counters to continue the execution$`), + TerminallyStuck: regexp.MustCompile(`(?:: |^)(?:not enough .* counters to continue the execution|out of counters at node level (?:.*))$`), } var aStar = ClientErrors{ @@ -263,6 +265,17 @@ 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`), +} + +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`) +var hedera = ClientErrors{ + NonceTooLow: regexp.MustCompile(`Nonce too low`), + NonceTooHigh: regexp.MustCompile(`Nonce too high`), + TerminallyUnderpriced: regexp.MustCompile(`(Gas price '(\d+)' is below configured minimum gas price '(\d+)')|(Gas price too low)`), + InsufficientEth: regexp.MustCompile(`Insufficient funds for transfer| failed precheck with status INSUFFICIENT_PAYER_BALANCE`), + ServiceUnavailable: regexp.MustCompile(`Transaction execution returns a null value for transaction`), + Fatal: hederaFatal, } var gnosis = ClientErrors{ @@ -276,7 +289,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, gnosis, internal} +var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, hedera, gnosis, internal} // ClientErrorRegexes returns a map of compiled regexes for each error type func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors { @@ -298,6 +311,7 @@ func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors { TransactionAlreadyMined: regexp.MustCompile(errsRegex.TransactionAlreadyMined()), Fatal: regexp.MustCompile(errsRegex.Fatal()), ServiceUnavailable: regexp.MustCompile(errsRegex.ServiceUnavailable()), + TooManyResults: regexp.MustCompile(errsRegex.TooManyResults()), } } @@ -377,7 +391,11 @@ func (s *SendError) IsL2Full(configErrors *ClientErrors) bool { // IsServiceUnavailable indicates if the error was caused by a service being unavailable func (s *SendError) IsServiceUnavailable(configErrors *ClientErrors) bool { - return s.is(ServiceUnavailable, configErrors) + if s == nil || s.err == nil { + return false + } + + return s.is(ServiceUnavailable, configErrors) || pkgerrors.Is(s.err, commonclient.ErroringNodeError) } // IsTerminallyStuck indicates if a transaction was stuck without any chance of inclusion @@ -457,6 +475,11 @@ func isFatalSendError(err error) bool { return false } +var ( + _ rpc.Error = JsonError{} + _ rpc.DataError = JsonError{} +) + // go-ethereum@v1.10.0/rpc/json.go type JsonError struct { Code int `json:"code"` @@ -471,7 +494,17 @@ func (err JsonError) Error() string { return err.Message } -func (err *JsonError) String() string { +// To satisfy rpc.Error interface +func (err JsonError) ErrorCode() int { + return err.Code +} + +// To satisfy rpc.DataError +func (err JsonError) ErrorData() interface{} { + return err.Data +} + +func (err JsonError) String() string { return fmt.Sprintf("json-rpc error { Code = %d, Message = '%s', Data = '%v' }", err.Code, err.Message, err.Data) } @@ -610,3 +643,88 @@ func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger. lggr.Criticalw("Unknown error encountered when sending transaction", "err", err, "etx", tx) return commonclient.Unknown } + +var infura = ClientErrors{ + TooManyResults: regexp.MustCompile(`(: |^)query returned more than [0-9]+ results. Try with this block range \[0x[0-9A-F]+, 0x[0-9A-F]+\].$`), +} + +var alchemy = ClientErrors{ + TooManyResults: regexp.MustCompile(`(: |^)Log response size exceeded. You can make eth_getLogs requests with up to a [0-9A-Z]+ block range and no limit on the response size, or you can request any block range with a cap of [0-9A-Z]+ logs in the response. Based on your parameters and the response size limit, this block range should work: \[0x[0-9a-f]+, 0x[0-9a-f]+\]$`), +} + +var quicknode = ClientErrors{ + TooManyResults: regexp.MustCompile(`(: |^)eth_getLogs is limited to a [0-9,]+ range$`), +} + +var simplyvc = ClientErrors{ + TooManyResults: regexp.MustCompile(`too wide blocks range, the limit is [0-9,]+$`), +} + +var drpc = ClientErrors{ + TooManyResults: regexp.MustCompile(`(: |^)requested too many blocks from [0-9]+ to [0-9]+, maximum is set to [0-9,]+$`), +} + +// Linkpool, Blockdaemon, and Chainstack all return "request timed out" if the log results are too large for them to process +var defaultClient = ClientErrors{ + TooManyResults: regexp.MustCompile(`request timed out`), +} + +// JSON-RPC error codes which can indicate a refusal of the server to process an eth_getLogs request because the result set is too large +const ( + jsonRpcServerError = -32000 // Server error. SimplyVC uses this error code when too many results are returned + + // Server timeout. When the rpc server has its own limit on how long it can take to compile the results + // Examples: Linkpool, Chainstack, Block Daemon + jsonRpcTimedOut = -32002 + + // See: https://github.com/ethereum/go-ethereum/blob/master/rpc/errors.go#L63 + // Can occur if the rpc server is configured with a maximum byte limit on the response size of batch requests + jsonRpcResponseTooLarge = -32003 + + // Not implemented in geth by default, but is defined in EIP 1474 and implemented by infura and some other 3rd party rpc servers + // See: https://community.infura.io/t/getlogs-error-query-returned-more-than-1000-results/358/5 + jsonRpcLimitExceeded = -32005 // See also: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md + + jsonRpcInvalidParams = -32602 // Invalid method params. Returned by alchemy if the block range is too large or there are too many results to return + + jsonRpcQuicknodeTooManyResults = -32614 // Undocumented error code used by Quicknode for too many results error +) + +func IsTooManyResults(err error, clientErrors config.ClientErrors) bool { + var rpcErr rpc.Error + + if !pkgerrors.As(err, &rpcErr) { + return false + } + configErrors := ClientErrorRegexes(clientErrors) + if configErrors.ErrIs(rpcErr, TooManyResults) { + return true + } + + switch rpcErr.ErrorCode() { + case jsonRpcResponseTooLarge: + return true + case jsonRpcLimitExceeded: + if infura.ErrIs(rpcErr, TooManyResults) { + return true + } + case jsonRpcInvalidParams: + if alchemy.ErrIs(rpcErr, TooManyResults) { + return true + } + case jsonRpcQuicknodeTooManyResults: + if quicknode.ErrIs(rpcErr, TooManyResults) { + return true + } + case jsonRpcTimedOut: + if defaultClient.ErrIs(rpcErr, TooManyResults) { + return true + } + case jsonRpcServerError: + if simplyvc.ErrIs(rpcErr, TooManyResults) || + drpc.ErrIs(rpcErr, TooManyResults) { + return true + } + } + return false +} diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index 095e291f5e9..226f4cef7c9 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -1,12 +1,15 @@ package client_test import ( + "encoding/json" "errors" + "fmt" "testing" pkgerrors "github.com/pkg/errors" "github.com/stretchr/testify/assert" + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) @@ -44,6 +47,8 @@ func Test_Eth_Errors(t *testing.T) { {"call failed: OldNonce, Current nonce: 22, nonce of rejected tx: 17", true, "Nethermind"}, {"nonce too low. allowed nonce range: 427 - 447, actual: 426", true, "zkSync"}, {"client error nonce too low", true, "tomlConfig"}, + {"[Request ID: 2e952947-ffad-408b-aed9-35f3ed152001] Nonce too low. Provided nonce: 15, current nonce: 15", true, "hedera"}, + {"failed to forward tx to sequencer, please try again. Error message: 'nonce too low'", true, "Mantle"}, } for _, test := range tests { @@ -65,6 +70,7 @@ func Test_Eth_Errors(t *testing.T) { {"nonce too high", true, "Erigon"}, {"nonce too high. allowed nonce range: 427 - 477, actual: 527", true, "zkSync"}, {"client error nonce too high", true, "tomlConfig"}, + {"[Request ID: 3ec591b4-9396-49f4-a03f-06c415a7cc6a] Nonce too high. Provided nonce: 16, current nonce: 15", true, "hedera"}, } for _, test := range tests { @@ -168,6 +174,7 @@ func Test_Eth_Errors(t *testing.T) { {"virtual machine entered unexpected state. please contact developers and provide transaction details that caused this error. Error description: The operator included transaction with an unacceptable gas price", true, "zkSync"}, {"client error terminally underpriced", true, "tomlConfig"}, {"gas price less than block base fee", true, "aStar"}, + {"[Request ID: e4d09e44-19a4-4eb7-babe-270db4c2ebc9] Gas price '830000000000' is below configured minimum gas price '950000000000'", true, "hedera"}, } for _, test := range tests { @@ -217,6 +224,8 @@ func Test_Eth_Errors(t *testing.T) { {"client error insufficient eth", true, "tomlConfig"}, {"transaction would cause overdraft", true, "Geth"}, {"failed to forward tx to sequencer, please try again. Error message: 'insufficient funds for gas * price + value'", true, "Mantle"}, + {"[Request ID: 9dd78806-58c8-4e6d-89a8-a60962abe705] Error invoking RPC: transaction 0.0.3041916@1717691931.680570179 failed precheck with status INSUFFICIENT_PAYER_BALANCE", true, "hedera"}, + {"[Request ID: 6198d2a3-590f-4724-aae5-69fecead0c49] Insufficient funds for transfer", true, "hedera"}, } for _, test := range tests { err = evmclient.NewSendErrorS(test.message) @@ -233,6 +242,7 @@ func Test_Eth_Errors(t *testing.T) { {"i/o timeout", true, "Arbitrum"}, {"network is unreachable", true, "Arbitrum"}, {"client error service unavailable", true, "tomlConfig"}, + {"[Request ID: 825608a8-fd8a-4b5b-aea7-92999509306d] Error invoking RPC: [Request ID: 825608a8-fd8a-4b5b-aea7-92999509306d] Transaction execution returns a null value for transaction", true, "hedera"}, } for _, test := range tests { err = evmclient.NewSendErrorS(test.message) @@ -240,6 +250,12 @@ func Test_Eth_Errors(t *testing.T) { err = newSendErrorWrapped(test.message) assert.Equal(t, err.IsServiceUnavailable(clientErrors), test.expect) } + { + err = evmclient.NewSendError(commonclient.ErroringNodeError) + assert.True(t, err.IsServiceUnavailable(clientErrors)) + err = evmclient.NewSendError(fmt.Errorf("failed to send transaction: %w", commonclient.ErroringNodeError)) + assert.True(t, err.IsServiceUnavailable(clientErrors)) + } }) t.Run("IsTxFeeExceedsCap", func(t *testing.T) { @@ -318,6 +334,8 @@ func Test_Eth_Errors(t *testing.T) { {"failed to add tx to the pool: not enough step counters to continue the execution", true, "Xlayer"}, {"failed to add tx to the pool: not enough keccak counters to continue the execution", true, "zkEVM"}, {"failed to add tx to the pool: not enough keccak counters to continue the execution", true, "Xlayer"}, + {"RPC error response: failed to add tx to the pool: out of counters at node level (Steps)", true, "zkEVM"}, + {"RPC error response: failed to add tx to the pool: out of counters at node level (GasUsed, KeccakHashes, PoseidonHashes, PoseidonPaddings, MemAligns, Arithmetics, Binaries, Steps, Sha256Hashes)", true, "Xlayer"}, } for _, test := range tests { @@ -405,6 +423,7 @@ func Test_Eth_Errors_Fatal(t *testing.T) { {"failed to forward tx to sequencer, please try again. Error message: 'invalid sender'", true, "Mantle"}, {"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"}, } @@ -439,3 +458,86 @@ func Test_Config_Errors(t *testing.T) { assert.False(t, clientErrors.ErrIs(errors.New("some old bollocks"), evmclient.NonceTooLow)) }) } + +func Test_IsTooManyResultsError(t *testing.T) { + customErrors := evmclient.NewTestClientErrors() + + tests := []errorCase{ + {`{ + "code":-32602, + "message":"Log response size exceeded. You can make eth_getLogs requests with up to a 2K block range and no limit on the response size, or you can request any block range with a cap of 10K logs in the response. Based on your parameters and the response size limit, this block range should work: [0x0, 0x133e71]"}`, + true, + "alchemy", + }, {`{ + "code":-32005, + "data":{"from":"0xCB3D","limit":10000,"to":"0x7B737"}, + "message":"query returned more than 10000 results. Try with this block range [0xCB3D, 0x7B737]."}`, + true, + "infura", + }, {`{ + "code":-32002, + "message":"request timed out"}`, + true, + "LinkPool-Blockdaemon-Chainstack", + }, {`{ + "code":-32614, + "message":"eth_getLogs is limited to a 10,000 range"}`, + true, + "Quicknode", + }, {`{ + "code":-32000, + "message":"too wide blocks range, the limit is 100"}`, + true, + "SimplyVC", + }, {`{ + "message":"requested too many blocks from 0 to 16777216, maximum is set to 2048", + "code":-32000}`, + true, + "Drpc", + }, {` + + + + 503 Backend fetch failed + + +

Error 503 Backend fetch failed

+

Backend fetch failed

+

Guru Meditation:

+

XID: 343710611

+
+

Varnish cache server

+ +`, + false, + "Nirvana Labs"}, // This isn't an error response we can handle, but including for completeness. }, + + {`{ + "code":-32000", + "message":"unrelated server error"}`, + false, + "any", + }, {`{ + "code":-32500, + "message":"unrelated error code"}`, + false, + "any2", + }, {fmt.Sprintf(`{ + "code" : -43106, + "message" : "%s"}`, customErrors.TooManyResults()), + true, + "custom chain with error specified in toml config", + }, + } + + for _, test := range tests { + t.Run(test.network, func(t *testing.T) { + jsonRpcErr := evmclient.JsonError{} + err := json.Unmarshal([]byte(test.message), &jsonRpcErr) + if err == nil { + err = jsonRpcErr + } + assert.Equal(t, test.expect, evmclient.IsTooManyResults(err, &customErrors)) + }) + } +} diff --git a/core/chains/evm/client/evm_client.go b/core/chains/evm/client/evm_client.go index 1fd533d6aab..18206265fd7 100644 --- a/core/chains/evm/client/evm_client.go +++ b/core/chains/evm/client/evm_client.go @@ -11,33 +11,32 @@ import ( 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" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) -func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, clientErrors evmconfig.ClientErrors, lggr logger.Logger, chainID *big.Int, nodes []*toml.Node, chainType chaintype.ChainType) Client { - var empty url.URL - var primaries []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient] - var sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient] +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] largePayloadRPCTimeout, defaultRPCTimeout := getRPCTimeouts(chainType) + for i, node := range nodes { if node.SendOnly != nil && *node.SendOnly { - rpc := NewRPCClient(lggr, empty, (*url.URL)(node.HTTPURL), *node.Name, int32(i), chainID, - commonclient.Secondary, cfg.FinalizedBlockPollInterval(), largePayloadRPCTimeout, defaultRPCTimeout, chainType) + 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), *node.Name, chainID, rpc) sendonlys = append(sendonlys, sendonly) } else { - rpc := NewRPCClient(lggr, (url.URL)(*node.WSURL), (*url.URL)(node.HTTPURL), *node.Name, int32(i), - chainID, commonclient.Primary, cfg.FinalizedBlockPollInterval(), largePayloadRPCTimeout, defaultRPCTimeout, chainType) + rpc := NewRPCClient(cfg, lggr, node.WSURL.URL(), node.HTTPURL.URL(), *node.Name, i, + chainID, commonclient.Primary, largePayloadRPCTimeout, defaultRPCTimeout, chainType) primaryNode := commonclient.NewNode(cfg, chainCfg, - lggr, (url.URL)(*node.WSURL), (*url.URL)(node.HTTPURL), *node.Name, int32(i), chainID, *node.Order, + lggr, node.WSURL.URL(), node.HTTPURL.URL(), *node.Name, i, chainID, *node.Order, rpc, "EVM") primaries = append(primaries, primaryNode) } } - return NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), chainCfg.NodeNoNewHeadsThreshold(), - primaries, sendonlys, chainID, chainType, clientErrors, cfg.DeathDeclarationDelay()) + return NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), + primaries, sendonlys, chainID, clientErrors, cfg.DeathDeclarationDelay(), chainType), nil } func getRPCTimeouts(chainType chaintype.ChainType) (largePayload, defaultTimeout time.Duration) { diff --git a/core/chains/evm/client/evm_client_test.go b/core/chains/evm/client/evm_client_test.go index bdfcf426744..9deca8edeee 100644 --- a/core/chains/evm/client/evm_client_test.go +++ b/core/chains/evm/client/evm_client_test.go @@ -29,6 +29,7 @@ func TestNewEvmClient(t *testing.T) { deathDeclarationDelay := time.Second * 3 noNewFinalizedBlocksThreshold := time.Second * 5 finalizedBlockPollInterval := time.Second * 4 + newHeadsPollInterval := time.Second * 4 nodeConfigs := []client.NodeConfig{ { Name: ptr("foo"), @@ -40,9 +41,11 @@ func TestNewEvmClient(t *testing.T) { finalityTagEnabled := ptr(true) chainCfg, nodePool, nodes, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, - finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead, deathDeclarationDelay, noNewFinalizedBlocksThreshold, finalizedBlockPollInterval) + finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead, deathDeclarationDelay, noNewFinalizedBlocksThreshold, + finalizedBlockPollInterval, newHeadsPollInterval) require.NoError(t, err) - client := client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), testutils.FixtureChainID, nodes, chaintype.ChainType(chainTypeStr)) + client, err := client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), testutils.FixtureChainID, nodes, chaintype.ChainType(chainTypeStr)) require.NotNil(t, client) + require.NoError(t, err) } diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index e996ccc5e4f..f9751be765c 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -14,7 +14,6 @@ import ( commonclient "github.com/smartcontractkit/chainlink/v2/common/client" clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" "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" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -34,6 +33,7 @@ type TestClientErrors struct { transactionAlreadyMined string fatal string serviceUnavailable string + tooManyResults string } func NewTestClientErrors() TestClientErrors { @@ -52,6 +52,7 @@ func NewTestClientErrors() TestClientErrors { transactionAlreadyMined: "client error transaction already mined", fatal: "client error fatal", serviceUnavailable: "client error service unavailable", + tooManyResults: "client error too many results", } } @@ -77,6 +78,7 @@ func (c *TestClientErrors) L2Full() string { return c.l2Full } func (c *TestClientErrors) TransactionAlreadyMined() string { return c.transactionAlreadyMined } func (c *TestClientErrors) Fatal() string { return c.fatal } func (c *TestClientErrors) ServiceUnavailable() string { return c.serviceUnavailable } +func (c *TestClientErrors) TooManyResults() string { return c.serviceUnavailable } type TestNodePoolConfig struct { NodePollFailureThreshold uint32 @@ -89,6 +91,7 @@ type TestNodePoolConfig struct { NodeErrors config.ClientErrors EnforceRepeatableReadVal bool NodeDeathDeclarationDelay time.Duration + NodeNewHeadsPollInterval time.Duration } func (tc TestNodePoolConfig) PollFailureThreshold() uint32 { return tc.NodePollFailureThreshold } @@ -107,6 +110,10 @@ func (tc TestNodePoolConfig) FinalizedBlockPollInterval() time.Duration { return tc.NodeFinalizedBlockPollInterval } +func (tc TestNodePoolConfig) NewHeadsPollInterval() time.Duration { + return tc.NodeNewHeadsPollInterval +} + func (tc TestNodePoolConfig) Errors() config.ClientErrors { return tc.NodeErrors } @@ -127,7 +134,7 @@ func NewChainClientWithTestNode( rpcUrl string, rpcHTTPURL *url.URL, sendonlyRPCURLs []url.URL, - id int32, + id int, chainID *big.Int, ) (Client, error) { parsed, err := url.ParseRequestURI(rpcUrl) @@ -140,27 +147,28 @@ func NewChainClientWithTestNode( } lggr := logger.Test(t) - rpc := NewRPCClient(lggr, *parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + nodePoolCfg := TestNodePoolConfig{ + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + rpc := NewRPCClient(nodePoolCfg, lggr, parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, commonclient.Primary, commonclient.QueryTimeout, commonclient.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, *evmtypes.Head, RPCClient]{n} + 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} - var sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient] + var sendonlys []commonclient.SendOnlyNode[*big.Int, *RPCClient] 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()) } - var empty url.URL - rpc := NewRPCClient(lggr, empty, &sendonlyRPCURLs[i], fmt.Sprintf("eth-sendonly-rpc-%d", i), id, chainID, commonclient.Secondary, 0, 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, commonclient.Secondary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + s := commonclient.NewSendOnlyNode[*big.Int, *RPCClient]( lggr, u, fmt.Sprintf("eth-sendonly-%d", i), chainID, rpc) sendonlys = append(sendonlys, s) } - var chainType chaintype.ChainType clientErrors := NewTestClientErrors() - c := NewChainClient(lggr, nodeCfg.SelectionMode(), leaseDuration, noNewHeadsThreshold, primaries, sendonlys, chainID, chainType, &clientErrors, 0) + c := NewChainClient(lggr, nodeCfg.SelectionMode(), leaseDuration, primaries, sendonlys, chainID, &clientErrors, 0, "") t.Cleanup(c.Close) return c, nil } @@ -174,8 +182,7 @@ func NewChainClientWithEmptyNode( ) Client { lggr := logger.Test(t) - var chainType chaintype.ChainType - c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, nil, nil, chainID, chainType, nil, 0) + c := NewChainClient(lggr, selectionMode, leaseDuration, nil, nil, chainID, nil, 0, "") t.Cleanup(c.Close) return c } @@ -186,22 +193,20 @@ func NewChainClientWithMockedRpc( leaseDuration time.Duration, noNewHeadsThreshold time.Duration, chainID *big.Int, - rpc RPCClient, + rpc *RPCClient, ) Client { lggr := logger.Test(t) - var chainType chaintype.ChainType - cfg := TestNodePoolConfig{ NodeSelectionMode: commonclient.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, *evmtypes.Head, RPCClient]{n} + 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} clientErrors := NewTestClientErrors() - c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, primaries, nil, chainID, chainType, &clientErrors, 0) + c := NewChainClient(lggr, selectionMode, leaseDuration, primaries, nil, chainID, &clientErrors, 0, "") t.Cleanup(c.Close) return c } diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go index 7b5220033bc..59621a6257d 100644 --- a/core/chains/evm/client/mocks/client.go +++ b/core/chains/evm/client/mocks/client.go @@ -430,63 +430,6 @@ func (_c *Client_CallContract_Call) RunAndReturn(run func(context.Context, ether return _c } -// ChainID provides a mock function with given fields: -func (_m *Client) ChainID() (*big.Int, error) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ChainID") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func() (*big.Int, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Client_ChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainID' -type Client_ChainID_Call struct { - *mock.Call -} - -// ChainID is a helper method to define mock.On call -func (_e *Client_Expecter) ChainID() *Client_ChainID_Call { - return &Client_ChainID_Call{Call: _e.mock.On("ChainID")} -} - -func (_c *Client_ChainID_Call) Run(run func()) *Client_ChainID_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Client_ChainID_Call) Return(_a0 *big.Int, _a1 error) *Client_ChainID_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Client_ChainID_Call) RunAndReturn(run func() (*big.Int, error)) *Client_ChainID_Call { - _c.Call.Return(run) - return _c -} - // CheckTxValidity provides a mock function with given fields: ctx, from, to, data func (_m *Client) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *client.SendError { ret := _m.Called(ctx, from, to, data) @@ -780,6 +723,66 @@ func (_c *Client_EstimateGas_Call) RunAndReturn(run func(context.Context, ethere return _c } +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *Client) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type Client_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *Client_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *Client_FeeHistory_Call { + return &Client_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *Client_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *Client_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *Client_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *Client_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *Client_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *Client_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // FilterLogs provides a mock function with given fields: ctx, q func (_m *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { ret := _m.Called(ctx, q) @@ -1343,6 +1346,64 @@ func (_c *Client_NodeStates_Call) RunAndReturn(run func() map[string]string) *Cl return _c } +// NonceAt provides a mock function with given fields: ctx, account, blockNumber +func (_m *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + ret := _m.Called(ctx, account, blockNumber) + + 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(ctx, account, blockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) uint64); ok { + r0 = rf(ctx, account, blockNumber) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { + r1 = rf(ctx, account, blockNumber) + } 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 +// - ctx context.Context +// - account common.Address +// - blockNumber *big.Int +func (_e *Client_Expecter) NonceAt(ctx interface{}, account interface{}, blockNumber interface{}) *Client_NonceAt_Call { + return &Client_NonceAt_Call{Call: _e.mock.On("NonceAt", ctx, account, blockNumber)} +} + +func (_c *Client_NonceAt_Call) Run(run func(ctx context.Context, account common.Address, blockNumber *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 +} + // PendingCallContract provides a mock function with given fields: ctx, msg func (_m *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { ret := _m.Called(ctx, msg) @@ -1623,64 +1684,6 @@ func (_c *Client_SendTransactionReturnCode_Call) RunAndReturn(run func(context.C return _c } -// SequenceAt provides a mock function with given fields: ctx, account, blockNumber -func (_m *Client) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) { - ret := _m.Called(ctx, account, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for SequenceAt") - } - - var r0 evmtypes.Nonce - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) (evmtypes.Nonce, error)); ok { - return rf(ctx, account, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) evmtypes.Nonce); ok { - r0 = rf(ctx, account, blockNumber) - } else { - r0 = ret.Get(0).(evmtypes.Nonce) - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, account, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Client_SequenceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SequenceAt' -type Client_SequenceAt_Call struct { - *mock.Call -} - -// SequenceAt is a helper method to define mock.On call -// - ctx context.Context -// - account common.Address -// - blockNumber *big.Int -func (_e *Client_Expecter) SequenceAt(ctx interface{}, account interface{}, blockNumber interface{}) *Client_SequenceAt_Call { - return &Client_SequenceAt_Call{Call: _e.mock.On("SequenceAt", ctx, account, blockNumber)} -} - -func (_c *Client_SequenceAt_Call) Run(run func(ctx context.Context, account common.Address, blockNumber *big.Int)) *Client_SequenceAt_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_SequenceAt_Call) Return(_a0 evmtypes.Nonce, _a1 error) *Client_SequenceAt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Client_SequenceAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) (evmtypes.Nonce, error)) *Client_SequenceAt_Call { - _c.Call.Return(run) - return _c -} - // SubscribeFilterLogs provides a mock function with given fields: ctx, q, ch func (_m *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { ret := _m.Called(ctx, q, ch) @@ -1741,61 +1744,69 @@ func (_c *Client_SubscribeFilterLogs_Call) RunAndReturn(run func(context.Context return _c } -// SubscribeNewHead provides a mock function with given fields: ctx, ch -func (_m *Client) SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) { - ret := _m.Called(ctx, ch) +// SubscribeToHeads provides a mock function with given fields: ctx +func (_m *Client) SubscribeToHeads(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { + ret := _m.Called(ctx) if len(ret) == 0 { - panic("no return value specified for SubscribeNewHead") + panic("no return value specified for SubscribeToHeads") } - var r0 ethereum.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- *evmtypes.Head) (ethereum.Subscription, error)); ok { - return rf(ctx, ch) + var r0 <-chan *evmtypes.Head + var r1 ethereum.Subscription + var r2 error + if rf, ok := ret.Get(0).(func(context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func(context.Context, chan<- *evmtypes.Head) ethereum.Subscription); ok { - r0 = rf(ctx, ch) + if rf, ok := ret.Get(0).(func(context.Context) <-chan *evmtypes.Head); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(ethereum.Subscription) + r0 = ret.Get(0).(<-chan *evmtypes.Head) } } - if rf, ok := ret.Get(1).(func(context.Context, chan<- *evmtypes.Head) error); ok { - r1 = rf(ctx, ch) + if rf, ok := ret.Get(1).(func(context.Context) ethereum.Subscription); ok { + r1 = rf(ctx) } else { - r1 = ret.Error(1) + if ret.Get(1) != nil { + r1 = ret.Get(1).(ethereum.Subscription) + } } - return r0, r1 + if rf, ok := ret.Get(2).(func(context.Context) error); ok { + r2 = rf(ctx) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 } -// Client_SubscribeNewHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeNewHead' -type Client_SubscribeNewHead_Call struct { +// Client_SubscribeToHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToHeads' +type Client_SubscribeToHeads_Call struct { *mock.Call } -// SubscribeNewHead is a helper method to define mock.On call +// SubscribeToHeads is a helper method to define mock.On call // - ctx context.Context -// - ch chan<- *evmtypes.Head -func (_e *Client_Expecter) SubscribeNewHead(ctx interface{}, ch interface{}) *Client_SubscribeNewHead_Call { - return &Client_SubscribeNewHead_Call{Call: _e.mock.On("SubscribeNewHead", ctx, ch)} +func (_e *Client_Expecter) SubscribeToHeads(ctx interface{}) *Client_SubscribeToHeads_Call { + return &Client_SubscribeToHeads_Call{Call: _e.mock.On("SubscribeToHeads", ctx)} } -func (_c *Client_SubscribeNewHead_Call) Run(run func(ctx context.Context, ch chan<- *evmtypes.Head)) *Client_SubscribeNewHead_Call { +func (_c *Client_SubscribeToHeads_Call) Run(run func(ctx context.Context)) *Client_SubscribeToHeads_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(chan<- *evmtypes.Head)) + run(args[0].(context.Context)) }) return _c } -func (_c *Client_SubscribeNewHead_Call) Return(_a0 ethereum.Subscription, _a1 error) *Client_SubscribeNewHead_Call { - _c.Call.Return(_a0, _a1) +func (_c *Client_SubscribeToHeads_Call) Return(_a0 <-chan *evmtypes.Head, _a1 ethereum.Subscription, _a2 error) *Client_SubscribeToHeads_Call { + _c.Call.Return(_a0, _a1, _a2) return _c } -func (_c *Client_SubscribeNewHead_Call) RunAndReturn(run func(context.Context, chan<- *evmtypes.Head) (ethereum.Subscription, error)) *Client_SubscribeNewHead_Call { +func (_c *Client_SubscribeToHeads_Call) RunAndReturn(run func(context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error)) *Client_SubscribeToHeads_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/client/mocks/rpc_client.go b/core/chains/evm/client/mocks/rpc_client.go deleted file mode 100644 index 06f79efd551..00000000000 --- a/core/chains/evm/client/mocks/rpc_client.go +++ /dev/null @@ -1,2472 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mocks - -import ( - big "math/big" - - assets "github.com/smartcontractkit/chainlink-common/pkg/assets" - - common "github.com/ethereum/go-ethereum/common" - - commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - - commontypes "github.com/smartcontractkit/chainlink/v2/common/types" - - context "context" - - coretypes "github.com/ethereum/go-ethereum/core/types" - - ethereum "github.com/ethereum/go-ethereum" - - evmassets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - - mock "github.com/stretchr/testify/mock" - - rpc "github.com/ethereum/go-ethereum/rpc" - - types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" -) - -// RPCClient is an autogenerated mock type for the RPCClient type -type RPCClient struct { - mock.Mock -} - -type RPCClient_Expecter struct { - mock *mock.Mock -} - -func (_m *RPCClient) EXPECT() *RPCClient_Expecter { - return &RPCClient_Expecter{mock: &_m.Mock} -} - -// BalanceAt provides a mock function with given fields: ctx, accountAddress, blockNumber -func (_m *RPCClient) BalanceAt(ctx context.Context, accountAddress common.Address, blockNumber *big.Int) (*big.Int, error) { - ret := _m.Called(ctx, accountAddress, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for BalanceAt") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) (*big.Int, error)); ok { - return rf(ctx, accountAddress, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) *big.Int); ok { - r0 = rf(ctx, accountAddress, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, accountAddress, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_BalanceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BalanceAt' -type RPCClient_BalanceAt_Call struct { - *mock.Call -} - -// BalanceAt is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress common.Address -// - blockNumber *big.Int -func (_e *RPCClient_Expecter) BalanceAt(ctx interface{}, accountAddress interface{}, blockNumber interface{}) *RPCClient_BalanceAt_Call { - return &RPCClient_BalanceAt_Call{Call: _e.mock.On("BalanceAt", ctx, accountAddress, blockNumber)} -} - -func (_c *RPCClient_BalanceAt_Call) Run(run func(ctx context.Context, accountAddress common.Address, blockNumber *big.Int)) *RPCClient_BalanceAt_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 *RPCClient_BalanceAt_Call) Return(_a0 *big.Int, _a1 error) *RPCClient_BalanceAt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_BalanceAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) (*big.Int, error)) *RPCClient_BalanceAt_Call { - _c.Call.Return(run) - return _c -} - -// BatchCallContext provides a mock function with given fields: ctx, b -func (_m *RPCClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - ret := _m.Called(ctx, b) - - if len(ret) == 0 { - panic("no return value specified for BatchCallContext") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []rpc.BatchElem) error); ok { - r0 = rf(ctx, b) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RPCClient_BatchCallContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchCallContext' -type RPCClient_BatchCallContext_Call struct { - *mock.Call -} - -// BatchCallContext is a helper method to define mock.On call -// - ctx context.Context -// - b []rpc.BatchElem -func (_e *RPCClient_Expecter) BatchCallContext(ctx interface{}, b interface{}) *RPCClient_BatchCallContext_Call { - return &RPCClient_BatchCallContext_Call{Call: _e.mock.On("BatchCallContext", ctx, b)} -} - -func (_c *RPCClient_BatchCallContext_Call) Run(run func(ctx context.Context, b []rpc.BatchElem)) *RPCClient_BatchCallContext_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]rpc.BatchElem)) - }) - return _c -} - -func (_c *RPCClient_BatchCallContext_Call) Return(_a0 error) *RPCClient_BatchCallContext_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_BatchCallContext_Call) RunAndReturn(run func(context.Context, []rpc.BatchElem) error) *RPCClient_BatchCallContext_Call { - _c.Call.Return(run) - return _c -} - -// BlockByHash provides a mock function with given fields: ctx, hash -func (_m *RPCClient) BlockByHash(ctx context.Context, hash common.Hash) (*types.Head, error) { - ret := _m.Called(ctx, hash) - - if len(ret) == 0 { - panic("no return value specified for BlockByHash") - } - - var r0 *types.Head - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Head, error)); ok { - return rf(ctx, hash) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Head); ok { - r0 = rf(ctx, hash) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Head) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, hash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_BlockByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByHash' -type RPCClient_BlockByHash_Call struct { - *mock.Call -} - -// BlockByHash is a helper method to define mock.On call -// - ctx context.Context -// - hash common.Hash -func (_e *RPCClient_Expecter) BlockByHash(ctx interface{}, hash interface{}) *RPCClient_BlockByHash_Call { - return &RPCClient_BlockByHash_Call{Call: _e.mock.On("BlockByHash", ctx, hash)} -} - -func (_c *RPCClient_BlockByHash_Call) Run(run func(ctx context.Context, hash common.Hash)) *RPCClient_BlockByHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *RPCClient_BlockByHash_Call) Return(_a0 *types.Head, _a1 error) *RPCClient_BlockByHash_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_BlockByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.Head, error)) *RPCClient_BlockByHash_Call { - _c.Call.Return(run) - return _c -} - -// BlockByHashGeth provides a mock function with given fields: ctx, hash -func (_m *RPCClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (*coretypes.Block, error) { - ret := _m.Called(ctx, hash) - - if len(ret) == 0 { - panic("no return value specified for BlockByHashGeth") - } - - var r0 *coretypes.Block - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*coretypes.Block, error)); ok { - return rf(ctx, hash) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *coretypes.Block); ok { - r0 = rf(ctx, hash) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coretypes.Block) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, hash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_BlockByHashGeth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByHashGeth' -type RPCClient_BlockByHashGeth_Call struct { - *mock.Call -} - -// BlockByHashGeth is a helper method to define mock.On call -// - ctx context.Context -// - hash common.Hash -func (_e *RPCClient_Expecter) BlockByHashGeth(ctx interface{}, hash interface{}) *RPCClient_BlockByHashGeth_Call { - return &RPCClient_BlockByHashGeth_Call{Call: _e.mock.On("BlockByHashGeth", ctx, hash)} -} - -func (_c *RPCClient_BlockByHashGeth_Call) Run(run func(ctx context.Context, hash common.Hash)) *RPCClient_BlockByHashGeth_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *RPCClient_BlockByHashGeth_Call) Return(b *coretypes.Block, err error) *RPCClient_BlockByHashGeth_Call { - _c.Call.Return(b, err) - return _c -} - -func (_c *RPCClient_BlockByHashGeth_Call) RunAndReturn(run func(context.Context, common.Hash) (*coretypes.Block, error)) *RPCClient_BlockByHashGeth_Call { - _c.Call.Return(run) - return _c -} - -// BlockByNumber provides a mock function with given fields: ctx, number -func (_m *RPCClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Head, error) { - ret := _m.Called(ctx, number) - - if len(ret) == 0 { - panic("no return value specified for BlockByNumber") - } - - var r0 *types.Head - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Head, error)); ok { - return rf(ctx, number) - } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Head); ok { - r0 = rf(ctx, number) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Head) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, number) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_BlockByNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByNumber' -type RPCClient_BlockByNumber_Call struct { - *mock.Call -} - -// BlockByNumber is a helper method to define mock.On call -// - ctx context.Context -// - number *big.Int -func (_e *RPCClient_Expecter) BlockByNumber(ctx interface{}, number interface{}) *RPCClient_BlockByNumber_Call { - return &RPCClient_BlockByNumber_Call{Call: _e.mock.On("BlockByNumber", ctx, number)} -} - -func (_c *RPCClient_BlockByNumber_Call) Run(run func(ctx context.Context, number *big.Int)) *RPCClient_BlockByNumber_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*big.Int)) - }) - return _c -} - -func (_c *RPCClient_BlockByNumber_Call) Return(_a0 *types.Head, _a1 error) *RPCClient_BlockByNumber_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_BlockByNumber_Call) RunAndReturn(run func(context.Context, *big.Int) (*types.Head, error)) *RPCClient_BlockByNumber_Call { - _c.Call.Return(run) - return _c -} - -// BlockByNumberGeth provides a mock function with given fields: ctx, number -func (_m *RPCClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (*coretypes.Block, error) { - ret := _m.Called(ctx, number) - - if len(ret) == 0 { - panic("no return value specified for BlockByNumberGeth") - } - - var r0 *coretypes.Block - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*coretypes.Block, error)); ok { - return rf(ctx, number) - } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *coretypes.Block); ok { - r0 = rf(ctx, number) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coretypes.Block) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, number) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_BlockByNumberGeth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByNumberGeth' -type RPCClient_BlockByNumberGeth_Call struct { - *mock.Call -} - -// BlockByNumberGeth is a helper method to define mock.On call -// - ctx context.Context -// - number *big.Int -func (_e *RPCClient_Expecter) BlockByNumberGeth(ctx interface{}, number interface{}) *RPCClient_BlockByNumberGeth_Call { - return &RPCClient_BlockByNumberGeth_Call{Call: _e.mock.On("BlockByNumberGeth", ctx, number)} -} - -func (_c *RPCClient_BlockByNumberGeth_Call) Run(run func(ctx context.Context, number *big.Int)) *RPCClient_BlockByNumberGeth_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*big.Int)) - }) - return _c -} - -func (_c *RPCClient_BlockByNumberGeth_Call) Return(b *coretypes.Block, err error) *RPCClient_BlockByNumberGeth_Call { - _c.Call.Return(b, err) - return _c -} - -func (_c *RPCClient_BlockByNumberGeth_Call) RunAndReturn(run func(context.Context, *big.Int) (*coretypes.Block, error)) *RPCClient_BlockByNumberGeth_Call { - _c.Call.Return(run) - return _c -} - -// CallContext provides a mock function with given fields: ctx, result, method, args -func (_m *RPCClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - var _ca []interface{} - _ca = append(_ca, ctx, result, method) - _ca = append(_ca, args...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for CallContext") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, string, ...interface{}) error); ok { - r0 = rf(ctx, result, method, args...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RPCClient_CallContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CallContext' -type RPCClient_CallContext_Call struct { - *mock.Call -} - -// CallContext is a helper method to define mock.On call -// - ctx context.Context -// - result interface{} -// - method string -// - args ...interface{} -func (_e *RPCClient_Expecter) CallContext(ctx interface{}, result interface{}, method interface{}, args ...interface{}) *RPCClient_CallContext_Call { - return &RPCClient_CallContext_Call{Call: _e.mock.On("CallContext", - append([]interface{}{ctx, result, method}, args...)...)} -} - -func (_c *RPCClient_CallContext_Call) Run(run func(ctx context.Context, result interface{}, method string, args ...interface{})) *RPCClient_CallContext_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]interface{}, len(args)-3) - for i, a := range args[3:] { - if a != nil { - variadicArgs[i] = a.(interface{}) - } - } - run(args[0].(context.Context), args[1].(interface{}), args[2].(string), variadicArgs...) - }) - return _c -} - -func (_c *RPCClient_CallContext_Call) Return(_a0 error) *RPCClient_CallContext_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_CallContext_Call) RunAndReturn(run func(context.Context, interface{}, string, ...interface{}) error) *RPCClient_CallContext_Call { - _c.Call.Return(run) - return _c -} - -// CallContract provides a mock function with given fields: ctx, msg, blockNumber -func (_m *RPCClient) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) ([]byte, error) { - ret := _m.Called(ctx, msg, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for CallContract") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, *big.Int) ([]byte, error)); ok { - return rf(ctx, msg, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, interface{}, *big.Int) []byte); ok { - r0 = rf(ctx, msg, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, interface{}, *big.Int) error); ok { - r1 = rf(ctx, msg, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_CallContract_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CallContract' -type RPCClient_CallContract_Call struct { - *mock.Call -} - -// CallContract is a helper method to define mock.On call -// - ctx context.Context -// - msg interface{} -// - blockNumber *big.Int -func (_e *RPCClient_Expecter) CallContract(ctx interface{}, msg interface{}, blockNumber interface{}) *RPCClient_CallContract_Call { - return &RPCClient_CallContract_Call{Call: _e.mock.On("CallContract", ctx, msg, blockNumber)} -} - -func (_c *RPCClient_CallContract_Call) Run(run func(ctx context.Context, msg interface{}, blockNumber *big.Int)) *RPCClient_CallContract_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(*big.Int)) - }) - return _c -} - -func (_c *RPCClient_CallContract_Call) Return(rpcErr []byte, extractErr error) *RPCClient_CallContract_Call { - _c.Call.Return(rpcErr, extractErr) - return _c -} - -func (_c *RPCClient_CallContract_Call) RunAndReturn(run func(context.Context, interface{}, *big.Int) ([]byte, error)) *RPCClient_CallContract_Call { - _c.Call.Return(run) - return _c -} - -// ChainID provides a mock function with given fields: ctx -func (_m *RPCClient) ChainID(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for ChainID") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_ChainID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainID' -type RPCClient_ChainID_Call struct { - *mock.Call -} - -// ChainID is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) ChainID(ctx interface{}) *RPCClient_ChainID_Call { - return &RPCClient_ChainID_Call{Call: _e.mock.On("ChainID", ctx)} -} - -func (_c *RPCClient_ChainID_Call) Run(run func(ctx context.Context)) *RPCClient_ChainID_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_ChainID_Call) Return(_a0 *big.Int, _a1 error) *RPCClient_ChainID_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_ChainID_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *RPCClient_ChainID_Call { - _c.Call.Return(run) - return _c -} - -// ClientVersion provides a mock function with given fields: _a0 -func (_m *RPCClient) ClientVersion(_a0 context.Context) (string, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for ClientVersion") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) string); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_ClientVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientVersion' -type RPCClient_ClientVersion_Call struct { - *mock.Call -} - -// ClientVersion is a helper method to define mock.On call -// - _a0 context.Context -func (_e *RPCClient_Expecter) ClientVersion(_a0 interface{}) *RPCClient_ClientVersion_Call { - return &RPCClient_ClientVersion_Call{Call: _e.mock.On("ClientVersion", _a0)} -} - -func (_c *RPCClient_ClientVersion_Call) Run(run func(_a0 context.Context)) *RPCClient_ClientVersion_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_ClientVersion_Call) Return(_a0 string, _a1 error) *RPCClient_ClientVersion_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_ClientVersion_Call) RunAndReturn(run func(context.Context) (string, error)) *RPCClient_ClientVersion_Call { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *RPCClient) Close() { - _m.Called() -} - -// RPCClient_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type RPCClient_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *RPCClient_Expecter) Close() *RPCClient_Close_Call { - return &RPCClient_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *RPCClient_Close_Call) Run(run func()) *RPCClient_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *RPCClient_Close_Call) Return() *RPCClient_Close_Call { - _c.Call.Return() - return _c -} - -func (_c *RPCClient_Close_Call) RunAndReturn(run func()) *RPCClient_Close_Call { - _c.Call.Return(run) - return _c -} - -// CodeAt provides a mock function with given fields: ctx, account, blockNumber -func (_m *RPCClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { - ret := _m.Called(ctx, account, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for CodeAt") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]byte, error)); ok { - return rf(ctx, account, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) []byte); ok { - r0 = rf(ctx, account, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, account, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_CodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CodeAt' -type RPCClient_CodeAt_Call struct { - *mock.Call -} - -// CodeAt is a helper method to define mock.On call -// - ctx context.Context -// - account common.Address -// - blockNumber *big.Int -func (_e *RPCClient_Expecter) CodeAt(ctx interface{}, account interface{}, blockNumber interface{}) *RPCClient_CodeAt_Call { - return &RPCClient_CodeAt_Call{Call: _e.mock.On("CodeAt", ctx, account, blockNumber)} -} - -func (_c *RPCClient_CodeAt_Call) Run(run func(ctx context.Context, account common.Address, blockNumber *big.Int)) *RPCClient_CodeAt_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 *RPCClient_CodeAt_Call) Return(_a0 []byte, _a1 error) *RPCClient_CodeAt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_CodeAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) ([]byte, error)) *RPCClient_CodeAt_Call { - _c.Call.Return(run) - return _c -} - -// Dial provides a mock function with given fields: ctx -func (_m *RPCClient) 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 -} - -// RPCClient_Dial_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Dial' -type RPCClient_Dial_Call struct { - *mock.Call -} - -// Dial is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) Dial(ctx interface{}) *RPCClient_Dial_Call { - return &RPCClient_Dial_Call{Call: _e.mock.On("Dial", ctx)} -} - -func (_c *RPCClient_Dial_Call) Run(run func(ctx context.Context)) *RPCClient_Dial_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_Dial_Call) Return(_a0 error) *RPCClient_Dial_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_Dial_Call) RunAndReturn(run func(context.Context) error) *RPCClient_Dial_Call { - _c.Call.Return(run) - return _c -} - -// DialHTTP provides a mock function with given fields: -func (_m *RPCClient) DialHTTP() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for DialHTTP") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RPCClient_DialHTTP_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DialHTTP' -type RPCClient_DialHTTP_Call struct { - *mock.Call -} - -// DialHTTP is a helper method to define mock.On call -func (_e *RPCClient_Expecter) DialHTTP() *RPCClient_DialHTTP_Call { - return &RPCClient_DialHTTP_Call{Call: _e.mock.On("DialHTTP")} -} - -func (_c *RPCClient_DialHTTP_Call) Run(run func()) *RPCClient_DialHTTP_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *RPCClient_DialHTTP_Call) Return(_a0 error) *RPCClient_DialHTTP_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_DialHTTP_Call) RunAndReturn(run func() error) *RPCClient_DialHTTP_Call { - _c.Call.Return(run) - return _c -} - -// DisconnectAll provides a mock function with given fields: -func (_m *RPCClient) DisconnectAll() { - _m.Called() -} - -// RPCClient_DisconnectAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisconnectAll' -type RPCClient_DisconnectAll_Call struct { - *mock.Call -} - -// DisconnectAll is a helper method to define mock.On call -func (_e *RPCClient_Expecter) DisconnectAll() *RPCClient_DisconnectAll_Call { - return &RPCClient_DisconnectAll_Call{Call: _e.mock.On("DisconnectAll")} -} - -func (_c *RPCClient_DisconnectAll_Call) Run(run func()) *RPCClient_DisconnectAll_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *RPCClient_DisconnectAll_Call) Return() *RPCClient_DisconnectAll_Call { - _c.Call.Return() - return _c -} - -func (_c *RPCClient_DisconnectAll_Call) RunAndReturn(run func()) *RPCClient_DisconnectAll_Call { - _c.Call.Return(run) - return _c -} - -// EstimateGas provides a mock function with given fields: ctx, call -func (_m *RPCClient) EstimateGas(ctx context.Context, call interface{}) (uint64, error) { - ret := _m.Called(ctx, call) - - if len(ret) == 0 { - panic("no return value specified for EstimateGas") - } - - var r0 uint64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}) (uint64, error)); ok { - return rf(ctx, call) - } - if rf, ok := ret.Get(0).(func(context.Context, interface{}) uint64); ok { - r0 = rf(ctx, call) - } else { - r0 = ret.Get(0).(uint64) - } - - if rf, ok := ret.Get(1).(func(context.Context, interface{}) error); ok { - r1 = rf(ctx, call) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_EstimateGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGas' -type RPCClient_EstimateGas_Call struct { - *mock.Call -} - -// EstimateGas is a helper method to define mock.On call -// - ctx context.Context -// - call interface{} -func (_e *RPCClient_Expecter) EstimateGas(ctx interface{}, call interface{}) *RPCClient_EstimateGas_Call { - return &RPCClient_EstimateGas_Call{Call: _e.mock.On("EstimateGas", ctx, call)} -} - -func (_c *RPCClient_EstimateGas_Call) Run(run func(ctx context.Context, call interface{})) *RPCClient_EstimateGas_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{})) - }) - return _c -} - -func (_c *RPCClient_EstimateGas_Call) Return(gas uint64, err error) *RPCClient_EstimateGas_Call { - _c.Call.Return(gas, err) - return _c -} - -func (_c *RPCClient_EstimateGas_Call) RunAndReturn(run func(context.Context, interface{}) (uint64, error)) *RPCClient_EstimateGas_Call { - _c.Call.Return(run) - return _c -} - -// FilterEvents provides a mock function with given fields: ctx, query -func (_m *RPCClient) FilterEvents(ctx context.Context, query ethereum.FilterQuery) ([]coretypes.Log, error) { - ret := _m.Called(ctx, query) - - if len(ret) == 0 { - panic("no return value specified for FilterEvents") - } - - var r0 []coretypes.Log - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery) ([]coretypes.Log, error)); ok { - return rf(ctx, query) - } - if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery) []coretypes.Log); ok { - r0 = rf(ctx, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]coretypes.Log) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ethereum.FilterQuery) error); ok { - r1 = rf(ctx, query) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_FilterEvents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterEvents' -type RPCClient_FilterEvents_Call struct { - *mock.Call -} - -// FilterEvents is a helper method to define mock.On call -// - ctx context.Context -// - query ethereum.FilterQuery -func (_e *RPCClient_Expecter) FilterEvents(ctx interface{}, query interface{}) *RPCClient_FilterEvents_Call { - return &RPCClient_FilterEvents_Call{Call: _e.mock.On("FilterEvents", ctx, query)} -} - -func (_c *RPCClient_FilterEvents_Call) Run(run func(ctx context.Context, query ethereum.FilterQuery)) *RPCClient_FilterEvents_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ethereum.FilterQuery)) - }) - return _c -} - -func (_c *RPCClient_FilterEvents_Call) Return(_a0 []coretypes.Log, _a1 error) *RPCClient_FilterEvents_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_FilterEvents_Call) RunAndReturn(run func(context.Context, ethereum.FilterQuery) ([]coretypes.Log, error)) *RPCClient_FilterEvents_Call { - _c.Call.Return(run) - return _c -} - -// GetInterceptedChainInfo provides a mock function with given fields: -func (_m *RPCClient) GetInterceptedChainInfo() (commonclient.ChainInfo, commonclient.ChainInfo) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetInterceptedChainInfo") - } - - var r0 commonclient.ChainInfo - var r1 commonclient.ChainInfo - if rf, ok := ret.Get(0).(func() (commonclient.ChainInfo, commonclient.ChainInfo)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() commonclient.ChainInfo); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(commonclient.ChainInfo) - } - - if rf, ok := ret.Get(1).(func() commonclient.ChainInfo); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(commonclient.ChainInfo) - } - - return r0, r1 -} - -// RPCClient_GetInterceptedChainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetInterceptedChainInfo' -type RPCClient_GetInterceptedChainInfo_Call struct { - *mock.Call -} - -// GetInterceptedChainInfo is a helper method to define mock.On call -func (_e *RPCClient_Expecter) GetInterceptedChainInfo() *RPCClient_GetInterceptedChainInfo_Call { - return &RPCClient_GetInterceptedChainInfo_Call{Call: _e.mock.On("GetInterceptedChainInfo")} -} - -func (_c *RPCClient_GetInterceptedChainInfo_Call) Run(run func()) *RPCClient_GetInterceptedChainInfo_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *RPCClient_GetInterceptedChainInfo_Call) Return(latest commonclient.ChainInfo, highestUserObservations commonclient.ChainInfo) *RPCClient_GetInterceptedChainInfo_Call { - _c.Call.Return(latest, highestUserObservations) - return _c -} - -func (_c *RPCClient_GetInterceptedChainInfo_Call) RunAndReturn(run func() (commonclient.ChainInfo, commonclient.ChainInfo)) *RPCClient_GetInterceptedChainInfo_Call { - _c.Call.Return(run) - return _c -} - -// HeaderByHash provides a mock function with given fields: ctx, h -func (_m *RPCClient) HeaderByHash(ctx context.Context, h common.Hash) (*coretypes.Header, error) { - ret := _m.Called(ctx, h) - - if len(ret) == 0 { - panic("no return value specified for HeaderByHash") - } - - var r0 *coretypes.Header - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*coretypes.Header, error)); ok { - return rf(ctx, h) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *coretypes.Header); ok { - r0 = rf(ctx, h) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coretypes.Header) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, h) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_HeaderByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HeaderByHash' -type RPCClient_HeaderByHash_Call struct { - *mock.Call -} - -// HeaderByHash is a helper method to define mock.On call -// - ctx context.Context -// - h common.Hash -func (_e *RPCClient_Expecter) HeaderByHash(ctx interface{}, h interface{}) *RPCClient_HeaderByHash_Call { - return &RPCClient_HeaderByHash_Call{Call: _e.mock.On("HeaderByHash", ctx, h)} -} - -func (_c *RPCClient_HeaderByHash_Call) Run(run func(ctx context.Context, h common.Hash)) *RPCClient_HeaderByHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *RPCClient_HeaderByHash_Call) Return(head *coretypes.Header, err error) *RPCClient_HeaderByHash_Call { - _c.Call.Return(head, err) - return _c -} - -func (_c *RPCClient_HeaderByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*coretypes.Header, error)) *RPCClient_HeaderByHash_Call { - _c.Call.Return(run) - return _c -} - -// HeaderByNumber provides a mock function with given fields: ctx, n -func (_m *RPCClient) HeaderByNumber(ctx context.Context, n *big.Int) (*coretypes.Header, error) { - ret := _m.Called(ctx, n) - - if len(ret) == 0 { - panic("no return value specified for HeaderByNumber") - } - - var r0 *coretypes.Header - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*coretypes.Header, error)); ok { - return rf(ctx, n) - } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *coretypes.Header); ok { - r0 = rf(ctx, n) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coretypes.Header) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, n) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_HeaderByNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HeaderByNumber' -type RPCClient_HeaderByNumber_Call struct { - *mock.Call -} - -// HeaderByNumber is a helper method to define mock.On call -// - ctx context.Context -// - n *big.Int -func (_e *RPCClient_Expecter) HeaderByNumber(ctx interface{}, n interface{}) *RPCClient_HeaderByNumber_Call { - return &RPCClient_HeaderByNumber_Call{Call: _e.mock.On("HeaderByNumber", ctx, n)} -} - -func (_c *RPCClient_HeaderByNumber_Call) Run(run func(ctx context.Context, n *big.Int)) *RPCClient_HeaderByNumber_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*big.Int)) - }) - return _c -} - -func (_c *RPCClient_HeaderByNumber_Call) Return(head *coretypes.Header, err error) *RPCClient_HeaderByNumber_Call { - _c.Call.Return(head, err) - return _c -} - -func (_c *RPCClient_HeaderByNumber_Call) RunAndReturn(run func(context.Context, *big.Int) (*coretypes.Header, error)) *RPCClient_HeaderByNumber_Call { - _c.Call.Return(run) - return _c -} - -// IsSyncing provides a mock function with given fields: ctx -func (_m *RPCClient) 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 -} - -// RPCClient_IsSyncing_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSyncing' -type RPCClient_IsSyncing_Call struct { - *mock.Call -} - -// IsSyncing is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) IsSyncing(ctx interface{}) *RPCClient_IsSyncing_Call { - return &RPCClient_IsSyncing_Call{Call: _e.mock.On("IsSyncing", ctx)} -} - -func (_c *RPCClient_IsSyncing_Call) Run(run func(ctx context.Context)) *RPCClient_IsSyncing_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_IsSyncing_Call) Return(_a0 bool, _a1 error) *RPCClient_IsSyncing_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_IsSyncing_Call) RunAndReturn(run func(context.Context) (bool, error)) *RPCClient_IsSyncing_Call { - _c.Call.Return(run) - return _c -} - -// LINKBalance provides a mock function with given fields: ctx, accountAddress, linkAddress -func (_m *RPCClient) LINKBalance(ctx context.Context, accountAddress common.Address, linkAddress common.Address) (*assets.Link, error) { - ret := _m.Called(ctx, accountAddress, linkAddress) - - if len(ret) == 0 { - panic("no return value specified for LINKBalance") - } - - var r0 *assets.Link - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Address) (*assets.Link, error)); ok { - return rf(ctx, accountAddress, linkAddress) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Address) *assets.Link); ok { - r0 = rf(ctx, accountAddress, linkAddress) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*assets.Link) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Address) error); ok { - r1 = rf(ctx, accountAddress, linkAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_LINKBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LINKBalance' -type RPCClient_LINKBalance_Call struct { - *mock.Call -} - -// LINKBalance is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress common.Address -// - linkAddress common.Address -func (_e *RPCClient_Expecter) LINKBalance(ctx interface{}, accountAddress interface{}, linkAddress interface{}) *RPCClient_LINKBalance_Call { - return &RPCClient_LINKBalance_Call{Call: _e.mock.On("LINKBalance", ctx, accountAddress, linkAddress)} -} - -func (_c *RPCClient_LINKBalance_Call) Run(run func(ctx context.Context, accountAddress common.Address, linkAddress common.Address)) *RPCClient_LINKBalance_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address), args[2].(common.Address)) - }) - return _c -} - -func (_c *RPCClient_LINKBalance_Call) Return(_a0 *assets.Link, _a1 error) *RPCClient_LINKBalance_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_LINKBalance_Call) RunAndReturn(run func(context.Context, common.Address, common.Address) (*assets.Link, error)) *RPCClient_LINKBalance_Call { - _c.Call.Return(run) - return _c -} - -// LatestBlockHeight provides a mock function with given fields: _a0 -func (_m *RPCClient) LatestBlockHeight(_a0 context.Context) (*big.Int, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for LatestBlockHeight") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_LatestBlockHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestBlockHeight' -type RPCClient_LatestBlockHeight_Call struct { - *mock.Call -} - -// LatestBlockHeight is a helper method to define mock.On call -// - _a0 context.Context -func (_e *RPCClient_Expecter) LatestBlockHeight(_a0 interface{}) *RPCClient_LatestBlockHeight_Call { - return &RPCClient_LatestBlockHeight_Call{Call: _e.mock.On("LatestBlockHeight", _a0)} -} - -func (_c *RPCClient_LatestBlockHeight_Call) Run(run func(_a0 context.Context)) *RPCClient_LatestBlockHeight_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_LatestBlockHeight_Call) Return(_a0 *big.Int, _a1 error) *RPCClient_LatestBlockHeight_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_LatestBlockHeight_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *RPCClient_LatestBlockHeight_Call { - _c.Call.Return(run) - return _c -} - -// LatestFinalizedBlock provides a mock function with given fields: ctx -func (_m *RPCClient) LatestFinalizedBlock(ctx context.Context) (*types.Head, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for LatestFinalizedBlock") - } - - var r0 *types.Head - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*types.Head, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *types.Head); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Head) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_LatestFinalizedBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestFinalizedBlock' -type RPCClient_LatestFinalizedBlock_Call struct { - *mock.Call -} - -// LatestFinalizedBlock is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) LatestFinalizedBlock(ctx interface{}) *RPCClient_LatestFinalizedBlock_Call { - return &RPCClient_LatestFinalizedBlock_Call{Call: _e.mock.On("LatestFinalizedBlock", ctx)} -} - -func (_c *RPCClient_LatestFinalizedBlock_Call) Run(run func(ctx context.Context)) *RPCClient_LatestFinalizedBlock_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_LatestFinalizedBlock_Call) Return(_a0 *types.Head, _a1 error) *RPCClient_LatestFinalizedBlock_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_LatestFinalizedBlock_Call) RunAndReturn(run func(context.Context) (*types.Head, error)) *RPCClient_LatestFinalizedBlock_Call { - _c.Call.Return(run) - return _c -} - -// PendingCallContract provides a mock function with given fields: ctx, msg -func (_m *RPCClient) PendingCallContract(ctx context.Context, msg interface{}) ([]byte, error) { - ret := _m.Called(ctx, msg) - - if len(ret) == 0 { - panic("no return value specified for PendingCallContract") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}) ([]byte, error)); ok { - return rf(ctx, msg) - } - if rf, ok := ret.Get(0).(func(context.Context, interface{}) []byte); ok { - r0 = rf(ctx, msg) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, interface{}) error); ok { - r1 = rf(ctx, msg) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_PendingCallContract_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingCallContract' -type RPCClient_PendingCallContract_Call struct { - *mock.Call -} - -// PendingCallContract is a helper method to define mock.On call -// - ctx context.Context -// - msg interface{} -func (_e *RPCClient_Expecter) PendingCallContract(ctx interface{}, msg interface{}) *RPCClient_PendingCallContract_Call { - return &RPCClient_PendingCallContract_Call{Call: _e.mock.On("PendingCallContract", ctx, msg)} -} - -func (_c *RPCClient_PendingCallContract_Call) Run(run func(ctx context.Context, msg interface{})) *RPCClient_PendingCallContract_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{})) - }) - return _c -} - -func (_c *RPCClient_PendingCallContract_Call) Return(rpcErr []byte, extractErr error) *RPCClient_PendingCallContract_Call { - _c.Call.Return(rpcErr, extractErr) - return _c -} - -func (_c *RPCClient_PendingCallContract_Call) RunAndReturn(run func(context.Context, interface{}) ([]byte, error)) *RPCClient_PendingCallContract_Call { - _c.Call.Return(run) - return _c -} - -// PendingCodeAt provides a mock function with given fields: ctx, account -func (_m *RPCClient) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { - ret := _m.Called(ctx, account) - - if len(ret) == 0 { - panic("no return value specified for PendingCodeAt") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address) ([]byte, error)); ok { - return rf(ctx, account) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address) []byte); ok { - r0 = rf(ctx, account) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { - r1 = rf(ctx, account) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_PendingCodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingCodeAt' -type RPCClient_PendingCodeAt_Call struct { - *mock.Call -} - -// PendingCodeAt is a helper method to define mock.On call -// - ctx context.Context -// - account common.Address -func (_e *RPCClient_Expecter) PendingCodeAt(ctx interface{}, account interface{}) *RPCClient_PendingCodeAt_Call { - return &RPCClient_PendingCodeAt_Call{Call: _e.mock.On("PendingCodeAt", ctx, account)} -} - -func (_c *RPCClient_PendingCodeAt_Call) Run(run func(ctx context.Context, account common.Address)) *RPCClient_PendingCodeAt_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address)) - }) - return _c -} - -func (_c *RPCClient_PendingCodeAt_Call) Return(b []byte, err error) *RPCClient_PendingCodeAt_Call { - _c.Call.Return(b, err) - return _c -} - -func (_c *RPCClient_PendingCodeAt_Call) RunAndReturn(run func(context.Context, common.Address) ([]byte, error)) *RPCClient_PendingCodeAt_Call { - _c.Call.Return(run) - return _c -} - -// PendingSequenceAt provides a mock function with given fields: ctx, addr -func (_m *RPCClient) PendingSequenceAt(ctx context.Context, addr common.Address) (types.Nonce, error) { - ret := _m.Called(ctx, addr) - - if len(ret) == 0 { - panic("no return value specified for PendingSequenceAt") - } - - var r0 types.Nonce - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address) (types.Nonce, error)); ok { - return rf(ctx, addr) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address) types.Nonce); ok { - r0 = rf(ctx, addr) - } else { - r0 = ret.Get(0).(types.Nonce) - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { - r1 = rf(ctx, addr) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_PendingSequenceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingSequenceAt' -type RPCClient_PendingSequenceAt_Call struct { - *mock.Call -} - -// PendingSequenceAt is a helper method to define mock.On call -// - ctx context.Context -// - addr common.Address -func (_e *RPCClient_Expecter) PendingSequenceAt(ctx interface{}, addr interface{}) *RPCClient_PendingSequenceAt_Call { - return &RPCClient_PendingSequenceAt_Call{Call: _e.mock.On("PendingSequenceAt", ctx, addr)} -} - -func (_c *RPCClient_PendingSequenceAt_Call) Run(run func(ctx context.Context, addr common.Address)) *RPCClient_PendingSequenceAt_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address)) - }) - return _c -} - -func (_c *RPCClient_PendingSequenceAt_Call) Return(_a0 types.Nonce, _a1 error) *RPCClient_PendingSequenceAt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_PendingSequenceAt_Call) RunAndReturn(run func(context.Context, common.Address) (types.Nonce, error)) *RPCClient_PendingSequenceAt_Call { - _c.Call.Return(run) - return _c -} - -// SendEmptyTransaction provides a mock function with given fields: ctx, newTxAttempt, seq, gasLimit, fee, fromAddress -func (_m *RPCClient) SendEmptyTransaction(ctx context.Context, newTxAttempt func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error), seq types.Nonce, gasLimit uint32, fee *evmassets.Wei, fromAddress common.Address) (string, error) { - ret := _m.Called(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - - if len(ret) == 0 { - panic("no return value specified for SendEmptyTransaction") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error), types.Nonce, uint32, *evmassets.Wei, common.Address) (string, error)); ok { - return rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - } - if rf, ok := ret.Get(0).(func(context.Context, func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error), types.Nonce, uint32, *evmassets.Wei, common.Address) string); ok { - r0 = rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error), types.Nonce, uint32, *evmassets.Wei, common.Address) error); ok { - r1 = rf(ctx, newTxAttempt, seq, gasLimit, fee, fromAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_SendEmptyTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendEmptyTransaction' -type RPCClient_SendEmptyTransaction_Call struct { - *mock.Call -} - -// SendEmptyTransaction is a helper method to define mock.On call -// - ctx context.Context -// - newTxAttempt func(types.Nonce , uint32 , *evmassets.Wei , common.Address)(interface{} , error) -// - seq types.Nonce -// - gasLimit uint32 -// - fee *evmassets.Wei -// - fromAddress common.Address -func (_e *RPCClient_Expecter) SendEmptyTransaction(ctx interface{}, newTxAttempt interface{}, seq interface{}, gasLimit interface{}, fee interface{}, fromAddress interface{}) *RPCClient_SendEmptyTransaction_Call { - return &RPCClient_SendEmptyTransaction_Call{Call: _e.mock.On("SendEmptyTransaction", ctx, newTxAttempt, seq, gasLimit, fee, fromAddress)} -} - -func (_c *RPCClient_SendEmptyTransaction_Call) Run(run func(ctx context.Context, newTxAttempt func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error), seq types.Nonce, gasLimit uint32, fee *evmassets.Wei, fromAddress common.Address)) *RPCClient_SendEmptyTransaction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error)), args[2].(types.Nonce), args[3].(uint32), args[4].(*evmassets.Wei), args[5].(common.Address)) - }) - return _c -} - -func (_c *RPCClient_SendEmptyTransaction_Call) Return(txhash string, err error) *RPCClient_SendEmptyTransaction_Call { - _c.Call.Return(txhash, err) - return _c -} - -func (_c *RPCClient_SendEmptyTransaction_Call) RunAndReturn(run func(context.Context, func(types.Nonce, uint32, *evmassets.Wei, common.Address) (interface{}, error), types.Nonce, uint32, *evmassets.Wei, common.Address) (string, error)) *RPCClient_SendEmptyTransaction_Call { - _c.Call.Return(run) - return _c -} - -// SendTransaction provides a mock function with given fields: ctx, tx -func (_m *RPCClient) SendTransaction(ctx context.Context, tx *coretypes.Transaction) error { - ret := _m.Called(ctx, tx) - - if len(ret) == 0 { - panic("no return value specified for SendTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *coretypes.Transaction) error); ok { - r0 = rf(ctx, tx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RPCClient_SendTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendTransaction' -type RPCClient_SendTransaction_Call struct { - *mock.Call -} - -// SendTransaction is a helper method to define mock.On call -// - ctx context.Context -// - tx *coretypes.Transaction -func (_e *RPCClient_Expecter) SendTransaction(ctx interface{}, tx interface{}) *RPCClient_SendTransaction_Call { - return &RPCClient_SendTransaction_Call{Call: _e.mock.On("SendTransaction", ctx, tx)} -} - -func (_c *RPCClient_SendTransaction_Call) Run(run func(ctx context.Context, tx *coretypes.Transaction)) *RPCClient_SendTransaction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*coretypes.Transaction)) - }) - return _c -} - -func (_c *RPCClient_SendTransaction_Call) Return(_a0 error) *RPCClient_SendTransaction_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_SendTransaction_Call) RunAndReturn(run func(context.Context, *coretypes.Transaction) error) *RPCClient_SendTransaction_Call { - _c.Call.Return(run) - return _c -} - -// SequenceAt provides a mock function with given fields: ctx, accountAddress, blockNumber -func (_m *RPCClient) SequenceAt(ctx context.Context, accountAddress common.Address, blockNumber *big.Int) (types.Nonce, error) { - ret := _m.Called(ctx, accountAddress, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for SequenceAt") - } - - var r0 types.Nonce - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) (types.Nonce, error)); ok { - return rf(ctx, accountAddress, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) types.Nonce); ok { - r0 = rf(ctx, accountAddress, blockNumber) - } else { - r0 = ret.Get(0).(types.Nonce) - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, accountAddress, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_SequenceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SequenceAt' -type RPCClient_SequenceAt_Call struct { - *mock.Call -} - -// SequenceAt is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress common.Address -// - blockNumber *big.Int -func (_e *RPCClient_Expecter) SequenceAt(ctx interface{}, accountAddress interface{}, blockNumber interface{}) *RPCClient_SequenceAt_Call { - return &RPCClient_SequenceAt_Call{Call: _e.mock.On("SequenceAt", ctx, accountAddress, blockNumber)} -} - -func (_c *RPCClient_SequenceAt_Call) Run(run func(ctx context.Context, accountAddress common.Address, blockNumber *big.Int)) *RPCClient_SequenceAt_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 *RPCClient_SequenceAt_Call) Return(_a0 types.Nonce, _a1 error) *RPCClient_SequenceAt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_SequenceAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) (types.Nonce, error)) *RPCClient_SequenceAt_Call { - _c.Call.Return(run) - return _c -} - -// SetAliveLoopSub provides a mock function with given fields: _a0 -func (_m *RPCClient) SetAliveLoopSub(_a0 commontypes.Subscription) { - _m.Called(_a0) -} - -// RPCClient_SetAliveLoopSub_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAliveLoopSub' -type RPCClient_SetAliveLoopSub_Call struct { - *mock.Call -} - -// SetAliveLoopSub is a helper method to define mock.On call -// - _a0 commontypes.Subscription -func (_e *RPCClient_Expecter) SetAliveLoopSub(_a0 interface{}) *RPCClient_SetAliveLoopSub_Call { - return &RPCClient_SetAliveLoopSub_Call{Call: _e.mock.On("SetAliveLoopSub", _a0)} -} - -func (_c *RPCClient_SetAliveLoopSub_Call) Run(run func(_a0 commontypes.Subscription)) *RPCClient_SetAliveLoopSub_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(commontypes.Subscription)) - }) - return _c -} - -func (_c *RPCClient_SetAliveLoopSub_Call) Return() *RPCClient_SetAliveLoopSub_Call { - _c.Call.Return() - return _c -} - -func (_c *RPCClient_SetAliveLoopSub_Call) RunAndReturn(run func(commontypes.Subscription)) *RPCClient_SetAliveLoopSub_Call { - _c.Call.Return(run) - return _c -} - -// SimulateTransaction provides a mock function with given fields: ctx, tx -func (_m *RPCClient) SimulateTransaction(ctx context.Context, tx *coretypes.Transaction) error { - ret := _m.Called(ctx, tx) - - if len(ret) == 0 { - panic("no return value specified for SimulateTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *coretypes.Transaction) error); ok { - r0 = rf(ctx, tx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RPCClient_SimulateTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SimulateTransaction' -type RPCClient_SimulateTransaction_Call struct { - *mock.Call -} - -// SimulateTransaction is a helper method to define mock.On call -// - ctx context.Context -// - tx *coretypes.Transaction -func (_e *RPCClient_Expecter) SimulateTransaction(ctx interface{}, tx interface{}) *RPCClient_SimulateTransaction_Call { - return &RPCClient_SimulateTransaction_Call{Call: _e.mock.On("SimulateTransaction", ctx, tx)} -} - -func (_c *RPCClient_SimulateTransaction_Call) Run(run func(ctx context.Context, tx *coretypes.Transaction)) *RPCClient_SimulateTransaction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*coretypes.Transaction)) - }) - return _c -} - -func (_c *RPCClient_SimulateTransaction_Call) Return(_a0 error) *RPCClient_SimulateTransaction_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_SimulateTransaction_Call) RunAndReturn(run func(context.Context, *coretypes.Transaction) error) *RPCClient_SimulateTransaction_Call { - _c.Call.Return(run) - return _c -} - -// SubscribeFilterLogs provides a mock function with given fields: ctx, q, ch -func (_m *RPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- coretypes.Log) (ethereum.Subscription, error) { - ret := _m.Called(ctx, q, ch) - - if len(ret) == 0 { - panic("no return value specified for SubscribeFilterLogs") - } - - var r0 ethereum.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) (ethereum.Subscription, error)); ok { - return rf(ctx, q, ch) - } - if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) ethereum.Subscription); ok { - r0 = rf(ctx, q, ch) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(ethereum.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) error); ok { - r1 = rf(ctx, q, ch) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_SubscribeFilterLogs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeFilterLogs' -type RPCClient_SubscribeFilterLogs_Call struct { - *mock.Call -} - -// SubscribeFilterLogs is a helper method to define mock.On call -// - ctx context.Context -// - q ethereum.FilterQuery -// - ch chan<- coretypes.Log -func (_e *RPCClient_Expecter) SubscribeFilterLogs(ctx interface{}, q interface{}, ch interface{}) *RPCClient_SubscribeFilterLogs_Call { - return &RPCClient_SubscribeFilterLogs_Call{Call: _e.mock.On("SubscribeFilterLogs", ctx, q, ch)} -} - -func (_c *RPCClient_SubscribeFilterLogs_Call) Run(run func(ctx context.Context, q ethereum.FilterQuery, ch chan<- coretypes.Log)) *RPCClient_SubscribeFilterLogs_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ethereum.FilterQuery), args[2].(chan<- coretypes.Log)) - }) - return _c -} - -func (_c *RPCClient_SubscribeFilterLogs_Call) Return(s ethereum.Subscription, err error) *RPCClient_SubscribeFilterLogs_Call { - _c.Call.Return(s, err) - return _c -} - -func (_c *RPCClient_SubscribeFilterLogs_Call) RunAndReturn(run func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) (ethereum.Subscription, error)) *RPCClient_SubscribeFilterLogs_Call { - _c.Call.Return(run) - return _c -} - -// SubscribeNewHead provides a mock function with given fields: ctx, channel -func (_m *RPCClient) SubscribeNewHead(ctx context.Context, channel chan<- *types.Head) (commontypes.Subscription, error) { - ret := _m.Called(ctx, channel) - - if len(ret) == 0 { - panic("no return value specified for SubscribeNewHead") - } - - var r0 commontypes.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Head) (commontypes.Subscription, error)); ok { - return rf(ctx, channel) - } - if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Head) commontypes.Subscription); ok { - r0 = rf(ctx, channel) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(commontypes.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, chan<- *types.Head) error); ok { - r1 = rf(ctx, channel) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_SubscribeNewHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeNewHead' -type RPCClient_SubscribeNewHead_Call struct { - *mock.Call -} - -// SubscribeNewHead is a helper method to define mock.On call -// - ctx context.Context -// - channel chan<- *types.Head -func (_e *RPCClient_Expecter) SubscribeNewHead(ctx interface{}, channel interface{}) *RPCClient_SubscribeNewHead_Call { - return &RPCClient_SubscribeNewHead_Call{Call: _e.mock.On("SubscribeNewHead", ctx, channel)} -} - -func (_c *RPCClient_SubscribeNewHead_Call) Run(run func(ctx context.Context, channel chan<- *types.Head)) *RPCClient_SubscribeNewHead_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(chan<- *types.Head)) - }) - return _c -} - -func (_c *RPCClient_SubscribeNewHead_Call) Return(s commontypes.Subscription, err error) *RPCClient_SubscribeNewHead_Call { - _c.Call.Return(s, err) - return _c -} - -func (_c *RPCClient_SubscribeNewHead_Call) RunAndReturn(run func(context.Context, chan<- *types.Head) (commontypes.Subscription, error)) *RPCClient_SubscribeNewHead_Call { - _c.Call.Return(run) - return _c -} - -// SubscribeToFinalizedHeads provides a mock function with given fields: _a0 -func (_m *RPCClient) SubscribeToFinalizedHeads(_a0 context.Context) (<-chan *types.Head, commontypes.Subscription, error) { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for SubscribeToFinalizedHeads") - } - - var r0 <-chan *types.Head - var r1 commontypes.Subscription - var r2 error - if rf, ok := ret.Get(0).(func(context.Context) (<-chan *types.Head, commontypes.Subscription, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(context.Context) <-chan *types.Head); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan *types.Head) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) commontypes.Subscription); ok { - r1 = rf(_a0) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(commontypes.Subscription) - } - } - - if rf, ok := ret.Get(2).(func(context.Context) error); ok { - r2 = rf(_a0) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// RPCClient_SubscribeToFinalizedHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToFinalizedHeads' -type RPCClient_SubscribeToFinalizedHeads_Call struct { - *mock.Call -} - -// SubscribeToFinalizedHeads is a helper method to define mock.On call -// - _a0 context.Context -func (_e *RPCClient_Expecter) SubscribeToFinalizedHeads(_a0 interface{}) *RPCClient_SubscribeToFinalizedHeads_Call { - return &RPCClient_SubscribeToFinalizedHeads_Call{Call: _e.mock.On("SubscribeToFinalizedHeads", _a0)} -} - -func (_c *RPCClient_SubscribeToFinalizedHeads_Call) Run(run func(_a0 context.Context)) *RPCClient_SubscribeToFinalizedHeads_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_SubscribeToFinalizedHeads_Call) Return(_a0 <-chan *types.Head, _a1 commontypes.Subscription, _a2 error) *RPCClient_SubscribeToFinalizedHeads_Call { - _c.Call.Return(_a0, _a1, _a2) - return _c -} - -func (_c *RPCClient_SubscribeToFinalizedHeads_Call) RunAndReturn(run func(context.Context) (<-chan *types.Head, commontypes.Subscription, error)) *RPCClient_SubscribeToFinalizedHeads_Call { - _c.Call.Return(run) - return _c -} - -// SubscribeToHeads provides a mock function with given fields: ctx -func (_m *RPCClient) SubscribeToHeads(ctx context.Context) (<-chan *types.Head, commontypes.Subscription, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for SubscribeToHeads") - } - - var r0 <-chan *types.Head - var r1 commontypes.Subscription - var r2 error - if rf, ok := ret.Get(0).(func(context.Context) (<-chan *types.Head, commontypes.Subscription, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) <-chan *types.Head); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan *types.Head) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) commontypes.Subscription); ok { - r1 = rf(ctx) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(commontypes.Subscription) - } - } - - if rf, ok := ret.Get(2).(func(context.Context) error); ok { - r2 = rf(ctx) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// RPCClient_SubscribeToHeads_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToHeads' -type RPCClient_SubscribeToHeads_Call struct { - *mock.Call -} - -// SubscribeToHeads is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) SubscribeToHeads(ctx interface{}) *RPCClient_SubscribeToHeads_Call { - return &RPCClient_SubscribeToHeads_Call{Call: _e.mock.On("SubscribeToHeads", ctx)} -} - -func (_c *RPCClient_SubscribeToHeads_Call) Run(run func(ctx context.Context)) *RPCClient_SubscribeToHeads_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_SubscribeToHeads_Call) Return(ch <-chan *types.Head, sub commontypes.Subscription, err error) *RPCClient_SubscribeToHeads_Call { - _c.Call.Return(ch, sub, err) - return _c -} - -func (_c *RPCClient_SubscribeToHeads_Call) RunAndReturn(run func(context.Context) (<-chan *types.Head, commontypes.Subscription, error)) *RPCClient_SubscribeToHeads_Call { - _c.Call.Return(run) - return _c -} - -// SubscribersCount provides a mock function with given fields: -func (_m *RPCClient) SubscribersCount() int32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for SubscribersCount") - } - - var r0 int32 - if rf, ok := ret.Get(0).(func() int32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(int32) - } - - return r0 -} - -// RPCClient_SubscribersCount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribersCount' -type RPCClient_SubscribersCount_Call struct { - *mock.Call -} - -// SubscribersCount is a helper method to define mock.On call -func (_e *RPCClient_Expecter) SubscribersCount() *RPCClient_SubscribersCount_Call { - return &RPCClient_SubscribersCount_Call{Call: _e.mock.On("SubscribersCount")} -} - -func (_c *RPCClient_SubscribersCount_Call) Run(run func()) *RPCClient_SubscribersCount_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *RPCClient_SubscribersCount_Call) Return(_a0 int32) *RPCClient_SubscribersCount_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RPCClient_SubscribersCount_Call) RunAndReturn(run func() int32) *RPCClient_SubscribersCount_Call { - _c.Call.Return(run) - return _c -} - -// SuggestGasPrice provides a mock function with given fields: ctx -func (_m *RPCClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for SuggestGasPrice") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_SuggestGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasPrice' -type RPCClient_SuggestGasPrice_Call struct { - *mock.Call -} - -// SuggestGasPrice is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) SuggestGasPrice(ctx interface{}) *RPCClient_SuggestGasPrice_Call { - return &RPCClient_SuggestGasPrice_Call{Call: _e.mock.On("SuggestGasPrice", ctx)} -} - -func (_c *RPCClient_SuggestGasPrice_Call) Run(run func(ctx context.Context)) *RPCClient_SuggestGasPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_SuggestGasPrice_Call) Return(p *big.Int, err error) *RPCClient_SuggestGasPrice_Call { - _c.Call.Return(p, err) - return _c -} - -func (_c *RPCClient_SuggestGasPrice_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *RPCClient_SuggestGasPrice_Call { - _c.Call.Return(run) - return _c -} - -// SuggestGasTipCap provides a mock function with given fields: ctx -func (_m *RPCClient) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for SuggestGasTipCap") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_SuggestGasTipCap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasTipCap' -type RPCClient_SuggestGasTipCap_Call struct { - *mock.Call -} - -// SuggestGasTipCap is a helper method to define mock.On call -// - ctx context.Context -func (_e *RPCClient_Expecter) SuggestGasTipCap(ctx interface{}) *RPCClient_SuggestGasTipCap_Call { - return &RPCClient_SuggestGasTipCap_Call{Call: _e.mock.On("SuggestGasTipCap", ctx)} -} - -func (_c *RPCClient_SuggestGasTipCap_Call) Run(run func(ctx context.Context)) *RPCClient_SuggestGasTipCap_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *RPCClient_SuggestGasTipCap_Call) Return(t *big.Int, err error) *RPCClient_SuggestGasTipCap_Call { - _c.Call.Return(t, err) - return _c -} - -func (_c *RPCClient_SuggestGasTipCap_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *RPCClient_SuggestGasTipCap_Call { - _c.Call.Return(run) - return _c -} - -// TokenBalance provides a mock function with given fields: ctx, accountAddress, tokenAddress -func (_m *RPCClient) TokenBalance(ctx context.Context, accountAddress common.Address, tokenAddress common.Address) (*big.Int, error) { - ret := _m.Called(ctx, accountAddress, tokenAddress) - - if len(ret) == 0 { - panic("no return value specified for TokenBalance") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Address) (*big.Int, error)); ok { - return rf(ctx, accountAddress, tokenAddress) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Address) *big.Int); ok { - r0 = rf(ctx, accountAddress, tokenAddress) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Address) error); ok { - r1 = rf(ctx, accountAddress, tokenAddress) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_TokenBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TokenBalance' -type RPCClient_TokenBalance_Call struct { - *mock.Call -} - -// TokenBalance is a helper method to define mock.On call -// - ctx context.Context -// - accountAddress common.Address -// - tokenAddress common.Address -func (_e *RPCClient_Expecter) TokenBalance(ctx interface{}, accountAddress interface{}, tokenAddress interface{}) *RPCClient_TokenBalance_Call { - return &RPCClient_TokenBalance_Call{Call: _e.mock.On("TokenBalance", ctx, accountAddress, tokenAddress)} -} - -func (_c *RPCClient_TokenBalance_Call) Run(run func(ctx context.Context, accountAddress common.Address, tokenAddress common.Address)) *RPCClient_TokenBalance_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address), args[2].(common.Address)) - }) - return _c -} - -func (_c *RPCClient_TokenBalance_Call) Return(_a0 *big.Int, _a1 error) *RPCClient_TokenBalance_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_TokenBalance_Call) RunAndReturn(run func(context.Context, common.Address, common.Address) (*big.Int, error)) *RPCClient_TokenBalance_Call { - _c.Call.Return(run) - return _c -} - -// TransactionByHash provides a mock function with given fields: ctx, txHash -func (_m *RPCClient) TransactionByHash(ctx context.Context, txHash common.Hash) (*coretypes.Transaction, error) { - ret := _m.Called(ctx, txHash) - - if len(ret) == 0 { - panic("no return value specified for TransactionByHash") - } - - var r0 *coretypes.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*coretypes.Transaction, error)); ok { - return rf(ctx, txHash) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *coretypes.Transaction); ok { - r0 = rf(ctx, txHash) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coretypes.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, txHash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_TransactionByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionByHash' -type RPCClient_TransactionByHash_Call struct { - *mock.Call -} - -// TransactionByHash is a helper method to define mock.On call -// - ctx context.Context -// - txHash common.Hash -func (_e *RPCClient_Expecter) TransactionByHash(ctx interface{}, txHash interface{}) *RPCClient_TransactionByHash_Call { - return &RPCClient_TransactionByHash_Call{Call: _e.mock.On("TransactionByHash", ctx, txHash)} -} - -func (_c *RPCClient_TransactionByHash_Call) Run(run func(ctx context.Context, txHash common.Hash)) *RPCClient_TransactionByHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *RPCClient_TransactionByHash_Call) Return(_a0 *coretypes.Transaction, _a1 error) *RPCClient_TransactionByHash_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_TransactionByHash_Call) RunAndReturn(run func(context.Context, common.Hash) (*coretypes.Transaction, error)) *RPCClient_TransactionByHash_Call { - _c.Call.Return(run) - return _c -} - -// TransactionReceipt provides a mock function with given fields: ctx, txHash -func (_m *RPCClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - ret := _m.Called(ctx, txHash) - - if len(ret) == 0 { - panic("no return value specified for TransactionReceipt") - } - - var r0 *types.Receipt - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Receipt, error)); ok { - return rf(ctx, txHash) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Receipt); ok { - r0 = rf(ctx, txHash) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Receipt) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, txHash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_TransactionReceipt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionReceipt' -type RPCClient_TransactionReceipt_Call struct { - *mock.Call -} - -// TransactionReceipt is a helper method to define mock.On call -// - ctx context.Context -// - txHash common.Hash -func (_e *RPCClient_Expecter) TransactionReceipt(ctx interface{}, txHash interface{}) *RPCClient_TransactionReceipt_Call { - return &RPCClient_TransactionReceipt_Call{Call: _e.mock.On("TransactionReceipt", ctx, txHash)} -} - -func (_c *RPCClient_TransactionReceipt_Call) Run(run func(ctx context.Context, txHash common.Hash)) *RPCClient_TransactionReceipt_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *RPCClient_TransactionReceipt_Call) Return(_a0 *types.Receipt, _a1 error) *RPCClient_TransactionReceipt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *RPCClient_TransactionReceipt_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.Receipt, error)) *RPCClient_TransactionReceipt_Call { - _c.Call.Return(run) - return _c -} - -// TransactionReceiptGeth provides a mock function with given fields: ctx, txHash -func (_m *RPCClient) TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (*coretypes.Receipt, error) { - ret := _m.Called(ctx, txHash) - - if len(ret) == 0 { - panic("no return value specified for TransactionReceiptGeth") - } - - var r0 *coretypes.Receipt - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*coretypes.Receipt, error)); ok { - return rf(ctx, txHash) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *coretypes.Receipt); ok { - r0 = rf(ctx, txHash) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*coretypes.Receipt) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { - r1 = rf(ctx, txHash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RPCClient_TransactionReceiptGeth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionReceiptGeth' -type RPCClient_TransactionReceiptGeth_Call struct { - *mock.Call -} - -// TransactionReceiptGeth is a helper method to define mock.On call -// - ctx context.Context -// - txHash common.Hash -func (_e *RPCClient_Expecter) TransactionReceiptGeth(ctx interface{}, txHash interface{}) *RPCClient_TransactionReceiptGeth_Call { - return &RPCClient_TransactionReceiptGeth_Call{Call: _e.mock.On("TransactionReceiptGeth", ctx, txHash)} -} - -func (_c *RPCClient_TransactionReceiptGeth_Call) Run(run func(ctx context.Context, txHash common.Hash)) *RPCClient_TransactionReceiptGeth_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *RPCClient_TransactionReceiptGeth_Call) Return(r *coretypes.Receipt, err error) *RPCClient_TransactionReceiptGeth_Call { - _c.Call.Return(r, err) - return _c -} - -func (_c *RPCClient_TransactionReceiptGeth_Call) RunAndReturn(run func(context.Context, common.Hash) (*coretypes.Receipt, error)) *RPCClient_TransactionReceiptGeth_Call { - _c.Call.Return(run) - return _c -} - -// UnsubscribeAllExceptAliveLoop provides a mock function with given fields: -func (_m *RPCClient) UnsubscribeAllExceptAliveLoop() { - _m.Called() -} - -// RPCClient_UnsubscribeAllExceptAliveLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscribeAllExceptAliveLoop' -type RPCClient_UnsubscribeAllExceptAliveLoop_Call struct { - *mock.Call -} - -// UnsubscribeAllExceptAliveLoop is a helper method to define mock.On call -func (_e *RPCClient_Expecter) UnsubscribeAllExceptAliveLoop() *RPCClient_UnsubscribeAllExceptAliveLoop_Call { - return &RPCClient_UnsubscribeAllExceptAliveLoop_Call{Call: _e.mock.On("UnsubscribeAllExceptAliveLoop")} -} - -func (_c *RPCClient_UnsubscribeAllExceptAliveLoop_Call) Run(run func()) *RPCClient_UnsubscribeAllExceptAliveLoop_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *RPCClient_UnsubscribeAllExceptAliveLoop_Call) Return() *RPCClient_UnsubscribeAllExceptAliveLoop_Call { - _c.Call.Return() - return _c -} - -func (_c *RPCClient_UnsubscribeAllExceptAliveLoop_Call) RunAndReturn(run func()) *RPCClient_UnsubscribeAllExceptAliveLoop_Call { - _c.Call.Return(run) - return _c -} - -// NewRPCClient creates a new instance of RPCClient. 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 NewRPCClient(t interface { - mock.TestingT - Cleanup(func()) -}) *RPCClient { - mock := &RPCClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go index 3129bcff9b0..13fbf66c6cc 100644 --- a/core/chains/evm/client/null_client.go +++ b/core/chains/evm/client/null_client.go @@ -90,9 +90,9 @@ func (nc *NullClient) SubscribeFilterLogs(ctx context.Context, q ethereum.Filter return newNullSubscription(nc.lggr), nil } -func (nc *NullClient) SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) { - nc.lggr.Debug("SubscribeNewHead") - return newNullSubscription(nc.lggr), nil +func (nc *NullClient) SubscribeToHeads(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { + nc.lggr.Debug("SubscribeToHeads") + return nil, newNullSubscription(nc.lggr), nil } // @@ -142,8 +142,8 @@ func (nc *NullClient) PendingNonceAt(ctx context.Context, account common.Address return 0, nil } -func (nc *NullClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) { - nc.lggr.Debug("SequenceAt") +func (nc *NullClient) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + nc.lggr.Debug("NonceAt") return 0, nil } @@ -235,3 +235,7 @@ func (nc *NullClient) LatestFinalizedBlock(_ context.Context) (*evmtypes.Head, e func (nc *NullClient) CheckTxValidity(_ context.Context, _ common.Address, _ common.Address, _ []byte) *SendError { return nil } + +func (nc *NullClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + return nil, nil +} diff --git a/core/chains/evm/client/null_client_test.go b/core/chains/evm/client/null_client_test.go index bc6c166030f..5e07c71c4ee 100644 --- a/core/chains/evm/client/null_client_test.go +++ b/core/chains/evm/client/null_client_test.go @@ -15,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) func TestNullClient(t *testing.T) { @@ -62,10 +61,9 @@ func TestNullClient(t *testing.T) { require.Nil(t, h) require.Equal(t, 1, logs.FilterMessage("HeadByNumber").Len()) - chHeads := make(chan *evmtypes.Head) - sub, err := nc.SubscribeNewHead(ctx, chHeads) + _, sub, err := nc.SubscribeToHeads(ctx) require.NoError(t, err) - require.Equal(t, 1, logs.FilterMessage("SubscribeNewHead").Len()) + require.Equal(t, 1, logs.FilterMessage("SubscribeToHeads").Len()) require.Nil(t, sub.Err()) require.Equal(t, 1, logs.FilterMessage("Err").Len()) sub.Unsubscribe() @@ -101,10 +99,10 @@ func TestNullClient(t *testing.T) { require.Zero(t, n) require.Equal(t, 1, logs.FilterMessage("PendingNonceAt").Len()) - s, err := nc.SequenceAt(ctx, common.Address{}, nil) + s, err := nc.NonceAt(ctx, common.Address{}, nil) require.NoError(t, err) require.Zero(t, s) - require.Equal(t, 1, logs.FilterMessage("SequenceAt").Len()) + require.Equal(t, 1, logs.FilterMessage("NonceAt").Len()) r, err := nc.TransactionReceipt(ctx, common.Hash{}) require.NoError(t, err) diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 07aa86fc450..d2247b0343e 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -29,6 +29,7 @@ import ( 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" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -77,34 +78,6 @@ var ( }, []string{"evmChainID", "nodeName", "rpcHost", "isSendOnly", "success", "rpcCallName"}) ) -// RPCClient includes all the necessary generalized RPC methods along with any additional chain-specific methods. -type RPCClient interface { - commonclient.RPC[ - *big.Int, - evmtypes.Nonce, - common.Address, - common.Hash, - *types.Transaction, - common.Hash, - types.Log, - ethereum.FilterQuery, - *evmtypes.Receipt, - *assets.Wei, - *evmtypes.Head, - rpc.BatchElem, - ] - BlockByHashGeth(ctx context.Context, hash common.Hash) (b *types.Block, err error) - BlockByNumberGeth(ctx context.Context, number *big.Int) (b *types.Block, err error) - HeaderByHash(ctx context.Context, h common.Hash) (head *types.Header, err error) - HeaderByNumber(ctx context.Context, n *big.Int) (head *types.Header, err error) - PendingCodeAt(ctx context.Context, account common.Address) (b []byte, err error) - SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (s ethereum.Subscription, err error) - SuggestGasPrice(ctx context.Context) (p *big.Int, err error) - SuggestGasTipCap(ctx context.Context) (t *big.Int, err error) - TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (r *types.Receipt, err error) - GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) -} - const rpcSubscriptionMethodNewHeads = "newHeads" type rawclient struct { @@ -113,65 +86,72 @@ type rawclient struct { uri url.URL } -type rpcClient struct { +type RPCClient struct { + cfg config.NodePool rpcLog logger.SugaredLogger name string - id int32 + id int chainID *big.Int tier commonclient.NodeTier - largePayloadRpcTimeout time.Duration - rpcTimeout time.Duration + largePayloadRPCTimeout time.Duration finalizedBlockPollInterval time.Duration + newHeadsPollInterval time.Duration + rpcTimeout time.Duration chainType chaintype.ChainType - ws rawclient + ws *rawclient http *rawclient - stateMu sync.RWMutex // protects state* fields + stateMu sync.RWMutex // protects state* fields + subsSliceMu sync.RWMutex // protects subscription slice // Need to track subscriptions because closing the RPC does not (always?) // close the underlying subscription - subs []ethereum.Subscription - - // Need to track the aliveLoop subscription, so we do not cancel it when checking lease on the MultiNode - aliveLoopSub ethereum.Subscription + subs map[ethereum.Subscription]struct{} // chStopInFlight can be closed to immediately cancel all in-flight requests on - // this rpcClient. Closing and replacing should be serialized through - // stateMu since it can happen on state transitions as well as rpcClient Close. + // this RPCClient. Closing and replacing should be serialized through + // stateMu since it can happen on state transitions as well as RPCClient Close. chStopInFlight chan struct{} - // intercepted values seen by callers of the rpcClient excluding health check calls. Need to ensure MultiNode provides repeatable read guarantee + 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 // most recent chain info observed during current lifecycle (reseted on DisconnectAll) latestChainInfo commonclient.ChainInfo } -// NewRPCCLient returns a new *rpcClient as commonclient.RPC +var _ commonclient.RPCClient[*big.Int, *evmtypes.Head] = (*RPCClient)(nil) +var _ commonclient.SendTxRPCClient[*types.Transaction] = (*RPCClient)(nil) + func NewRPCClient( + cfg config.NodePool, lggr logger.Logger, - wsuri url.URL, + wsuri *url.URL, httpuri *url.URL, name string, - id int32, + id int, chainID *big.Int, tier commonclient.NodeTier, - finalizedBlockPollInterval time.Duration, - largePayloadRpcTimeout time.Duration, + largePayloadRPCTimeout time.Duration, rpcTimeout time.Duration, chainType chaintype.ChainType, -) RPCClient { - r := &rpcClient{ - largePayloadRpcTimeout: largePayloadRpcTimeout, +) *RPCClient { + r := &RPCClient{ + largePayloadRPCTimeout: largePayloadRPCTimeout, rpcTimeout: rpcTimeout, chainType: chainType, } + r.cfg = cfg r.name = name r.id = id r.chainID = chainID r.tier = tier - r.ws.uri = wsuri - r.finalizedBlockPollInterval = finalizedBlockPollInterval + r.finalizedBlockPollInterval = cfg.FinalizedBlockPollInterval() + r.newHeadsPollInterval = cfg.NewHeadsPollInterval() + if wsuri != nil { + r.ws = &rawclient{uri: *wsuri} + } if httpuri != nil { r.http = &rawclient{uri: *httpuri} } @@ -184,48 +164,78 @@ func NewRPCClient( "evmChainID", chainID, ) r.rpcLog = logger.Sugared(lggr).Named("RPC") + r.subs = map[ethereum.Subscription]struct{}{} return r } +func (r *RPCClient) Ping(ctx context.Context) error { + version, err := r.ClientVersion(ctx) + if err != nil { + return fmt.Errorf("ping failed: %w", err) + } + r.rpcLog.Debugf("ping client version: %s", version) + return err +} + +func (r *RPCClient) UnsubscribeAllExcept(subs ...commontypes.Subscription) { + r.subsSliceMu.Lock() + defer r.subsSliceMu.Unlock() + + keepSubs := map[commontypes.Subscription]struct{}{} + for _, sub := range subs { + keepSubs[sub] = struct{}{} + } + + for sub := range r.subs { + if _, keep := keepSubs[sub]; !keep { + sub.Unsubscribe() + delete(r.subs, sub) + } + } +} + // Not thread-safe, pure dial. -func (r *rpcClient) Dial(callerCtx context.Context) error { +func (r *RPCClient) Dial(callerCtx context.Context) error { ctx, cancel := r.makeQueryCtx(callerCtx, r.rpcTimeout) defer cancel() - promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc() - lggr := r.rpcLog.With("wsuri", r.ws.uri.Redacted()) - if r.http != nil { - lggr = lggr.With("httpuri", r.http.uri.Redacted()) + if r.ws == nil && r.http == nil { + return errors.New("cannot dial rpc client when both ws and http info are missing") } - lggr.Debugw("RPC dial: evmclient.Client#dial") - wsrpc, err := rpc.DialWebsocket(ctx, r.ws.uri.String(), "") - if err != nil { - promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() - return r.wrapRPCClientError(pkgerrors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted())) - } + promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc() + lggr := r.rpcLog + if r.ws != nil { + lggr = lggr.With("wsuri", r.ws.uri.Redacted()) + wsrpc, err := rpc.DialWebsocket(ctx, r.ws.uri.String(), "") + if err != nil { + promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() + return r.wrapRPCClientError(pkgerrors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted())) + } - r.ws.rpc = wsrpc - r.ws.geth = ethclient.NewClient(wsrpc) + r.ws.rpc = wsrpc + r.ws.geth = ethclient.NewClient(wsrpc) + } if r.http != nil { + lggr = lggr.With("httpuri", r.http.uri.Redacted()) if err := r.DialHTTP(); err != nil { return err } } + lggr.Debugw("RPC dial: evmclient.Client#dial") promEVMPoolRPCNodeDialsSuccess.WithLabelValues(r.chainID.String(), r.name).Inc() - return nil } // Not thread-safe, pure dial. // DialHTTP doesn't actually make any external HTTP calls // It can only return error if the URL is malformed. -func (r *rpcClient) DialHTTP() error { +func (r *RPCClient) DialHTTP() error { promEVMPoolRPCNodeDials.WithLabelValues(r.chainID.String(), r.name).Inc() - lggr := r.rpcLog.With("httpuri", r.ws.uri.Redacted()) + lggr := r.rpcLog.With("httpuri", r.http.uri.Redacted()) lggr.Debugw("RPC dial: evmclient.Client#dial") var httprpc *rpc.Client @@ -243,35 +253,39 @@ func (r *rpcClient) DialHTTP() error { return nil } -func (r *rpcClient) Close() { +func (r *RPCClient) Close() { defer func() { - if r.ws.rpc != nil { + if r.ws != nil && r.ws.rpc != nil { r.ws.rpc.Close() } }() - - r.stateMu.Lock() - defer r.stateMu.Unlock() r.cancelInflightRequests() + r.UnsubscribeAllExcept() + r.chainInfoLock.Lock() + r.latestChainInfo = commonclient.ChainInfo{} + r.chainInfoLock.Unlock() } // cancelInflightRequests closes and replaces the chStopInFlight -// WARNING: NOT THREAD-SAFE -// This must be called from within the r.stateMu lock -func (r *rpcClient) cancelInflightRequests() { +func (r *RPCClient) cancelInflightRequests() { + r.stateMu.Lock() + defer r.stateMu.Unlock() close(r.chStopInFlight) r.chStopInFlight = make(chan struct{}) } -func (r *rpcClient) String() string { - s := fmt.Sprintf("(%s)%s:%s", r.tier.String(), r.name, r.ws.uri.Redacted()) +func (r *RPCClient) String() string { + s := fmt.Sprintf("(%s)%s", r.tier.String(), r.name) + if r.ws != nil { + s = s + fmt.Sprintf(":%s", r.ws.uri.Redacted()) + } if r.http != nil { s = s + fmt.Sprintf(":%s", r.http.uri.Redacted()) } return s } -func (r *rpcClient) logResult( +func (r *RPCClient) logResult( lggr logger.Logger, err error, callDuration time.Duration, @@ -294,7 +308,7 @@ func (r *rpcClient) logResult( promEVMPoolRPCCallTiming. WithLabelValues( r.chainID.String(), // chain id - r.name, // rpcClient name + r.name, // RPCClient name rpcDomain, // rpc domain "false", // is send only strconv.FormatBool(err == nil), // is successful @@ -303,18 +317,18 @@ func (r *rpcClient) logResult( Observe(float64(callDuration)) } -func (r *rpcClient) getRPCDomain() string { +func (r *RPCClient) getRPCDomain() string { if r.http != nil { return r.http.uri.Host } return r.ws.uri.Host } -// registerSub adds the sub to the rpcClient list -func (r *rpcClient) registerSub(sub ethereum.Subscription, stopInFLightCh chan struct{}) error { - r.stateMu.Lock() - defer r.stateMu.Unlock() - // ensure that the `sub` belongs to current life cycle of the `rpcClient` and it should not be killed due to +// registerSub adds the sub to the RPCClient list +func (r *RPCClient) registerSub(sub ethereum.Subscription, stopInFLightCh chan struct{}) error { + r.subsSliceMu.Lock() + defer r.subsSliceMu.Unlock() + // ensure that the `sub` belongs to current life cycle of the `RPCClient` and it should not be killed due to // previous `DisconnectAll` call. select { case <-stopInFLightCh: @@ -323,63 +337,15 @@ func (r *rpcClient) registerSub(sub ethereum.Subscription, stopInFLightCh chan s default: } // TODO: BCI-3358 - delete sub when caller unsubscribes. - r.subs = append(r.subs, sub) + r.subs[sub] = struct{}{} return nil } -// DisconnectAll disconnects all clients connected to the rpcClient -func (r *rpcClient) DisconnectAll() { - r.stateMu.Lock() - defer r.stateMu.Unlock() - if r.ws.rpc != nil { - r.ws.rpc.Close() - } - r.cancelInflightRequests() - r.unsubscribeAll() - r.latestChainInfo = commonclient.ChainInfo{} -} - -// unsubscribeAll unsubscribes all subscriptions -// WARNING: NOT THREAD-SAFE -// This must be called from within the r.stateMu lock -func (r *rpcClient) unsubscribeAll() { - for _, sub := range r.subs { - sub.Unsubscribe() - } - r.subs = nil -} -func (r *rpcClient) SetAliveLoopSub(sub commontypes.Subscription) { - r.stateMu.Lock() - defer r.stateMu.Unlock() - - r.aliveLoopSub = sub -} - -// SubscribersCount returns the number of client subscribed to the node -func (r *rpcClient) SubscribersCount() int32 { - r.stateMu.RLock() - defer r.stateMu.RUnlock() - return int32(len(r.subs)) -} - -// UnsubscribeAllExceptAliveLoop disconnects all subscriptions to the node except the alive loop subscription -// while holding the n.stateMu lock -func (r *rpcClient) UnsubscribeAllExceptAliveLoop() { - r.stateMu.Lock() - defer r.stateMu.Unlock() - - for _, s := range r.subs { - if s != r.aliveLoopSub { - s.Unsubscribe() - } - } -} - // RPC wrappers // CallContext implementation -func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRpcTimeout) +func (r *RPCClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRPCTimeout) defer cancel() lggr := r.newRqLggr().With( "method", method, @@ -401,7 +367,7 @@ func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method return err } -func (r *rpcClient) BatchCallContext(rootCtx context.Context, b []rpc.BatchElem) error { +func (r *RPCClient) BatchCallContext(rootCtx context.Context, b []rpc.BatchElem) error { // Astar's finality tags provide weaker finality guarantees than we require. // Fetch latest finalized block using Astar's custom requests and populate it after batch request completes var astarRawLatestFinalizedBlock json.RawMessage @@ -422,7 +388,7 @@ func (r *rpcClient) BatchCallContext(rootCtx context.Context, b []rpc.BatchElem) } } - ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(rootCtx, r.largePayloadRpcTimeout) + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(rootCtx, r.largePayloadRPCTimeout) defer cancel() lggr := r.newRqLggr().With("nBatchElems", len(b), "batchElems", b) @@ -479,45 +445,34 @@ func isRequestingFinalizedBlock(el rpc.BatchElem) bool { } } -// TODO: Full transition from SubscribeNewHead to SubscribeToHeads is done in BCI-2875 -func (r *rpcClient) SubscribeNewHead(ctx context.Context, channel chan<- *evmtypes.Head) (_ commontypes.Subscription, err error) { +func (r *RPCClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.Head, sub commontypes.Subscription, err error) { ctx, cancel, chStopInFlight, ws, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) defer cancel() - args := []interface{}{"newHeads"} - lggr := r.newRqLggr().With("args", args) - - lggr.Debug("RPC call: evmclient.Client#EthSubscribe") + args := []interface{}{rpcSubscriptionMethodNewHeads} start := time.Now() - defer func() { - duration := time.Since(start) - r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe") - err = r.wrapWS(err) - }() - subForwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head { - head.EVMChainID = ubig.New(r.chainID) - r.onNewHead(ctx, chStopInFlight, head) - return head - }, r.wrapRPCClientError) - err = subForwarder.start(ws.rpc.EthSubscribe(ctx, subForwarder.srcCh, args...)) - if err != nil { - return - } + lggr := r.newRqLggr().With("args", args) - err = r.registerSub(subForwarder, chStopInFlight) - if err != nil { - return - } + // if new head based on http polling is enabled, we will replace it for WS newHead subscription + if r.newHeadsPollInterval > 0 { + interval := r.newHeadsPollInterval + timeout := interval + poller, channel := commonclient.NewPoller[*evmtypes.Head](interval, r.latestBlock, timeout, r.rpcLog) + if err = poller.Start(ctx); err != nil { + return nil, nil, err + } - return subForwarder, nil -} + err = r.registerSub(&poller, chStopInFlight) + if err != nil { + return nil, nil, err + } -func (r *rpcClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.Head, sub commontypes.Subscription, err error) { - ctx, cancel, chStopInFlight, ws, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) - defer cancel() + lggr.Debugf("Polling new heads over http") + return channel, &poller, nil + } - args := []interface{}{rpcSubscriptionMethodNewHeads} - start := time.Now() - lggr := r.newRqLggr().With("args", args) + if ws == nil { + return nil, nil, errors.New("SubscribeNewHead is not allowed without ws url") + } lggr.Debug("RPC call: evmclient.Client#EthSubscribe") defer func() { @@ -546,22 +501,31 @@ func (r *rpcClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H return channel, forwarder, err } -func (r *rpcClient) SubscribeToFinalizedHeads(_ context.Context) (<-chan *evmtypes.Head, commontypes.Subscription, error) { - interval := r.finalizedBlockPollInterval +func (r *RPCClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan *evmtypes.Head, commontypes.Subscription, error) { + ctx, cancel, chStopInFlight, _, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) + defer cancel() + + interval := r.cfg.FinalizedBlockPollInterval() if interval == 0 { return nil, nil, errors.New("FinalizedBlockPollInterval is 0") } timeout := interval poller, channel := commonclient.NewPoller[*evmtypes.Head](interval, r.LatestFinalizedBlock, timeout, r.rpcLog) - if err := poller.Start(); err != nil { + if err := poller.Start(ctx); err != nil { + return nil, nil, err + } + + err := r.registerSub(&poller, chStopInFlight) + if err != nil { return nil, nil, err } + return channel, &poller, nil } // GethClient wrappers -func (r *rpcClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (receipt *evmtypes.Receipt, err error) { +func (r *RPCClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (receipt *evmtypes.Receipt, err error) { err = r.CallContext(ctx, &receipt, "eth_getTransactionReceipt", txHash, false) if err != nil { return nil, err @@ -573,7 +537,7 @@ func (r *rpcClient) TransactionReceipt(ctx context.Context, txHash common.Hash) return } -func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { +func (r *RPCClient) TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("txHash", txHash) @@ -596,7 +560,7 @@ func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Ha return } -func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, err error) { +func (r *RPCClient) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("txHash", txHash) @@ -620,7 +584,7 @@ func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) ( return } -func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header *types.Header, err error) { +func (r *RPCClient) HeaderByNumber(ctx context.Context, number *big.Int) (header *types.Header, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("number", number) @@ -641,7 +605,7 @@ func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header return } -func (r *rpcClient) HeaderByHash(ctx context.Context, hash common.Hash) (header *types.Header, err error) { +func (r *RPCClient) HeaderByHash(ctx context.Context, hash common.Hash) (header *types.Header, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("hash", hash) @@ -664,7 +628,7 @@ func (r *rpcClient) HeaderByHash(ctx context.Context, hash common.Hash) (header return } -func (r *rpcClient) LatestFinalizedBlock(ctx context.Context) (head *evmtypes.Head, err error) { +func (r *RPCClient) LatestFinalizedBlock(ctx context.Context) (head *evmtypes.Head, err error) { // capture chStopInFlight to ensure we are not updating chainInfo with observations related to previous life cycle ctx, cancel, chStopInFlight, _, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) defer cancel() @@ -690,7 +654,11 @@ func (r *rpcClient) LatestFinalizedBlock(ctx context.Context) (head *evmtypes.He return } -func (r *rpcClient) astarLatestFinalizedBlock(ctx context.Context, result interface{}) (err error) { +func (r *RPCClient) latestBlock(ctx context.Context) (head *evmtypes.Head, err error) { + return r.BlockByNumber(ctx, nil) +} + +func (r *RPCClient) astarLatestFinalizedBlock(ctx context.Context, result interface{}) (err error) { var hashResult string err = r.CallContext(ctx, &hashResult, "chain_getFinalizedHead") if err != nil { @@ -717,7 +685,7 @@ func (r *rpcClient) astarLatestFinalizedBlock(ctx context.Context, result interf return nil } -func (r *rpcClient) BlockByNumber(ctx context.Context, number *big.Int) (head *evmtypes.Head, err error) { +func (r *RPCClient) BlockByNumber(ctx context.Context, number *big.Int) (head *evmtypes.Head, err error) { ctx, cancel, chStopInFlight, _, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) defer cancel() hexNumber := ToBlockNumArg(number) @@ -740,7 +708,7 @@ func (r *rpcClient) BlockByNumber(ctx context.Context, number *big.Int) (head *e return } -func (r *rpcClient) ethGetBlockByNumber(ctx context.Context, number string, result interface{}) (err error) { +func (r *RPCClient) ethGetBlockByNumber(ctx context.Context, number string, result interface{}) (err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() const method = "eth_getBlockByNumber" @@ -763,7 +731,7 @@ func (r *rpcClient) ethGetBlockByNumber(ctx context.Context, number string, resu return err } -func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *evmtypes.Head, err error) { +func (r *RPCClient) BlockByHash(ctx context.Context, hash common.Hash) (head *evmtypes.Head, err error) { err = r.CallContext(ctx, &head, "eth_getBlockByHash", hash.Hex(), false) if err != nil { return nil, err @@ -776,7 +744,7 @@ func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *ev return } -func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (block *types.Block, err error) { +func (r *RPCClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (block *types.Block, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("hash", hash) @@ -799,7 +767,7 @@ func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (bloc return } -func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (block *types.Block, err error) { +func (r *RPCClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (block *types.Block, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("number", number) @@ -822,8 +790,8 @@ func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (blo return } -func (r *rpcClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRpcTimeout) +func (r *RPCClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRPCTimeout) defer cancel() lggr := r.newRqLggr().With("tx", tx) @@ -842,12 +810,12 @@ func (r *rpcClient) SendTransaction(ctx context.Context, tx *types.Transaction) return err } -func (r *rpcClient) SimulateTransaction(ctx context.Context, tx *types.Transaction) error { +func (r *RPCClient) SimulateTransaction(ctx context.Context, tx *types.Transaction) error { // Not Implemented return pkgerrors.New("SimulateTransaction not implemented") } -func (r *rpcClient) SendEmptyTransaction( +func (r *RPCClient) SendEmptyTransaction( ctx context.Context, newTxAttempt func(nonce evmtypes.Nonce, feeLimit uint32, fee *assets.Wei, fromAddress common.Address) (attempt any, err error), nonce evmtypes.Nonce, @@ -860,7 +828,7 @@ func (r *rpcClient) SendEmptyTransaction( } // PendingSequenceAt returns one higher than the highest nonce from both mempool and mined transactions -func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Address) (nonce evmtypes.Nonce, err error) { +func (r *RPCClient) PendingSequenceAt(ctx context.Context, account common.Address) (nonce evmtypes.Nonce, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("account", account) @@ -886,24 +854,21 @@ func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Addres return } -// SequenceAt is a bit of a misnomer. You might expect it to return the highest +// NonceAt is a bit of a misnomer. You might expect it to return the highest // mined nonce at the given block number, but it actually returns the total // transaction count which is the highest mined nonce + 1 -func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (nonce evmtypes.Nonce, err error) { +func (r *RPCClient) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (nonce uint64, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) lggr.Debug("RPC call: evmclient.Client#NonceAt") start := time.Now() - var n uint64 if http != nil { - n, err = http.geth.NonceAt(ctx, account, blockNumber) - nonce = evmtypes.Nonce(int64(n)) + nonce, err = http.geth.NonceAt(ctx, account, blockNumber) err = r.wrapHTTP(err) } else { - n, err = ws.geth.NonceAt(ctx, account, blockNumber) - nonce = evmtypes.Nonce(int64(n)) + nonce, err = ws.geth.NonceAt(ctx, account, blockNumber) err = r.wrapWS(err) } duration := time.Since(start) @@ -915,7 +880,7 @@ func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, bloc return } -func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) (code []byte, err error) { +func (r *RPCClient) PendingCodeAt(ctx context.Context, account common.Address) (code []byte, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("account", account) @@ -938,7 +903,7 @@ func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) ( return } -func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) (code []byte, err error) { +func (r *RPCClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) (code []byte, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) @@ -961,8 +926,8 @@ func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNum return } -func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, err error) { - ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRpcTimeout) +func (r *RPCClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, err error) { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRPCTimeout) defer cancel() call := c.(ethereum.CallMsg) lggr := r.newRqLggr().With("call", call) @@ -985,7 +950,7 @@ func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, return } -func (r *rpcClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err error) { +func (r *RPCClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr() @@ -1008,8 +973,8 @@ func (r *rpcClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err er return } -func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) (val []byte, err error) { - ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRpcTimeout) +func (r *RPCClient) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) (val []byte, err error) { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRPCTimeout) defer cancel() lggr := r.newRqLggr().With("callMsg", msg, "blockNumber", blockNumber) message := msg.(ethereum.CallMsg) @@ -1036,8 +1001,8 @@ func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumb return } -func (r *rpcClient) PendingCallContract(ctx context.Context, msg interface{}) (val []byte, err error) { - ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRpcTimeout) +func (r *RPCClient) PendingCallContract(ctx context.Context, msg interface{}) (val []byte, err error) { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRPCTimeout) defer cancel() lggr := r.newRqLggr().With("callMsg", msg) message := msg.(ethereum.CallMsg) @@ -1064,13 +1029,13 @@ func (r *rpcClient) PendingCallContract(ctx context.Context, msg interface{}) (v return } -func (r *rpcClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) { +func (r *RPCClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) { var height big.Int h, err := r.BlockNumber(ctx) return height.SetUint64(h), err } -func (r *rpcClient) BlockNumber(ctx context.Context) (height uint64, err error) { +func (r *RPCClient) BlockNumber(ctx context.Context) (height uint64, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr() @@ -1093,7 +1058,7 @@ func (r *rpcClient) BlockNumber(ctx context.Context) (height uint64, err error) return } -func (r *rpcClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (balance *big.Int, err error) { +func (r *RPCClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (balance *big.Int, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("account", account.Hex(), "blockNumber", blockNumber) @@ -1116,6 +1081,29 @@ func (r *rpcClient) BalanceAt(ctx context.Context, account common.Address, block return } +func (r *RPCClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) + defer cancel() + lggr := r.newRqLggr().With("blockCount", blockCount, "rewardPercentiles", rewardPercentiles) + + lggr.Debug("RPC call: evmclient.Client#FeeHistory") + start := time.Now() + if http != nil { + feeHistory, err = http.geth.FeeHistory(ctx, blockCount, nil, rewardPercentiles) + err = r.wrapHTTP(err) + } else { + feeHistory, err = ws.geth.FeeHistory(ctx, blockCount, nil, rewardPercentiles) + err = r.wrapWS(err) + } + duration := time.Since(start) + + r.logResult(lggr, err, duration, r.getRPCDomain(), "FeeHistory", + "feeHistory", feeHistory, + ) + + return +} + // CallArgs represents the data used to call the balance method of a contract. // "To" is the address of the ERC contract. "Data" is the message sent // to the contract. "From" is the sender address. @@ -1126,7 +1114,7 @@ type CallArgs struct { } // TokenBalance returns the balance of the given address for the token contract address. -func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, contractAddress common.Address) (*big.Int, error) { +func (r *RPCClient) TokenBalance(ctx context.Context, address common.Address, contractAddress common.Address) (*big.Int, error) { result := "" numLinkBigInt := new(big.Int) functionSelector := evmtypes.HexToFunctionSelector(BALANCE_OF_ADDRESS_FUNCTION_SELECTOR) // balanceOf(address) @@ -1146,7 +1134,7 @@ func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, co } // LINKBalance returns the balance of LINK at the given address -func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*commonassets.Link, error) { +func (r *RPCClient) LINKBalance(ctx context.Context, address common.Address, linkAddress common.Address) (*commonassets.Link, error) { balance, err := r.TokenBalance(ctx, address, linkAddress) if err != nil { return commonassets.NewLinkFromJuels(0), err @@ -1154,11 +1142,11 @@ func (r *rpcClient) LINKBalance(ctx context.Context, address common.Address, lin return (*commonassets.Link)(balance), nil } -func (r *rpcClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { +func (r *RPCClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { return r.FilterLogs(ctx, q) } -func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l []types.Log, err error) { +func (r *RPCClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l []types.Log, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr().With("q", q) @@ -1181,14 +1169,17 @@ func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l [ return } -func (r *rpcClient) ClientVersion(ctx context.Context) (version string, err error) { +func (r *RPCClient) ClientVersion(ctx context.Context) (version string, err error) { err = r.CallContext(ctx, &version, "web3_clientVersion") return } -func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (_ ethereum.Subscription, err error) { +func (r *RPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (_ ethereum.Subscription, err error) { ctx, cancel, chStopInFlight, ws, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) defer cancel() + if ws == nil { + return nil, errors.New("SubscribeFilterLogs is not allowed without ws url") + } lggr := r.newRqLggr().With("q", q) lggr.Debug("RPC call: evmclient.Client#SubscribeFilterLogs") @@ -1212,7 +1203,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu return sub, nil } -func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err error) { +func (r *RPCClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr() @@ -1237,7 +1228,7 @@ func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err // Returns the ChainID according to the geth client. This is useful for functions like verify() // the common node. -func (r *rpcClient) ChainID(ctx context.Context) (chainID *big.Int, err error) { +func (r *RPCClient) ChainID(ctx context.Context) (chainID *big.Int, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() @@ -1253,16 +1244,16 @@ func (r *rpcClient) ChainID(ctx context.Context) (chainID *big.Int, err error) { } // newRqLggr generates a new logger with a unique request ID -func (r *rpcClient) newRqLggr() logger.SugaredLogger { +func (r *RPCClient) newRqLggr() logger.SugaredLogger { return r.rpcLog.With("requestID", uuid.New()) } -func (r *rpcClient) wrapRPCClientError(err error) error { +func (r *RPCClient) wrapRPCClientError(err error) error { // simple add msg to the error without adding new stack trace return pkgerrors.WithMessage(err, r.rpcClientErrorPrefix()) } -func (r *rpcClient) rpcClientErrorPrefix() string { +func (r *RPCClient) rpcClientErrorPrefix() string { return fmt.Sprintf("RPCClient returned error (%s)", r.name) } @@ -1276,12 +1267,12 @@ func wrapCallError(err error, tp string) error { return pkgerrors.Wrapf(err, "%s call failed", tp) } -func (r *rpcClient) wrapWS(err error) error { +func (r *RPCClient) wrapWS(err error) error { err = wrapCallError(err, fmt.Sprintf("%s websocket (%s)", r.tier.String(), r.ws.uri.Redacted())) return r.wrapRPCClientError(err) } -func (r *rpcClient) wrapHTTP(err error) error { +func (r *RPCClient) wrapHTTP(err error) error { err = wrapCallError(err, fmt.Sprintf("%s http (%s)", r.tier.String(), r.http.uri.Redacted())) err = r.wrapRPCClientError(err) if err != nil { @@ -1293,18 +1284,21 @@ func (r *rpcClient) wrapHTTP(err error) error { } // makeLiveQueryCtxAndSafeGetClients wraps makeQueryCtx -func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context, timeout time.Duration) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient) { +func (r *RPCClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context, timeout time.Duration) (ctx context.Context, cancel context.CancelFunc, ws *rawclient, http *rawclient) { ctx, cancel, _, ws, http = r.acquireQueryCtx(parentCtx, timeout) return } -func (r *rpcClient) acquireQueryCtx(parentCtx context.Context, timeout time.Duration) (ctx context.Context, cancel context.CancelFunc, - chStopInFlight chan struct{}, ws rawclient, http *rawclient) { +func (r *RPCClient) acquireQueryCtx(parentCtx context.Context, timeout time.Duration) (ctx context.Context, cancel context.CancelFunc, + chStopInFlight chan struct{}, ws *rawclient, http *rawclient) { // Need to wrap in mutex because state transition can cancel and replace the // context r.stateMu.RLock() chStopInFlight = r.chStopInFlight - ws = r.ws + if r.ws != nil { + cp := *r.ws + ws = &cp + } if r.http != nil { cp := *r.http http = &cp @@ -1329,11 +1323,11 @@ func makeQueryCtx(ctx context.Context, ch services.StopChan, timeout time.Durati return ctx, cancel } -func (r *rpcClient) makeQueryCtx(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) { +func (r *RPCClient) makeQueryCtx(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) { return makeQueryCtx(ctx, r.getChStopInflight(), timeout) } -func (r *rpcClient) IsSyncing(ctx context.Context) (bool, error) { +func (r *RPCClient) IsSyncing(ctx context.Context) (bool, error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() lggr := r.newRqLggr() @@ -1360,33 +1354,29 @@ func (r *rpcClient) IsSyncing(ctx context.Context) (bool, error) { // getChStopInflight provides a convenience helper that mutex wraps a // read to the chStopInFlight -func (r *rpcClient) getChStopInflight() chan struct{} { +func (r *RPCClient) getChStopInflight() chan struct{} { r.stateMu.RLock() defer r.stateMu.RUnlock() return r.chStopInFlight } -func (r *rpcClient) Name() string { +func (r *RPCClient) Name() string { return r.name } -func Name(r *rpcClient) string { - return r.name -} - -func (r *rpcClient) onNewHead(ctx context.Context, requestCh <-chan struct{}, head *evmtypes.Head) { +func (r *RPCClient) onNewHead(ctx context.Context, requestCh <-chan struct{}, head *evmtypes.Head) { if head == nil { return } - r.stateMu.Lock() - defer r.stateMu.Unlock() + r.chainInfoLock.Lock() + defer r.chainInfoLock.Unlock() if !commonclient.CtxIsHeathCheckRequest(ctx) { r.highestUserObservations.BlockNumber = max(r.highestUserObservations.BlockNumber, head.Number) r.highestUserObservations.TotalDifficulty = commonclient.MaxTotalDifficulty(r.highestUserObservations.TotalDifficulty, head.TotalDifficulty) } select { - case <-requestCh: // no need to update latestChainInfo, as rpcClient already started new life cycle + case <-requestCh: // no need to update latestChainInfo, as RPCClient already started new life cycle return default: r.latestChainInfo.BlockNumber = head.Number @@ -1394,26 +1384,26 @@ func (r *rpcClient) onNewHead(ctx context.Context, requestCh <-chan struct{}, he } } -func (r *rpcClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan struct{}, head *evmtypes.Head) { +func (r *RPCClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan struct{}, head *evmtypes.Head) { if head == nil { return } - r.stateMu.Lock() - defer r.stateMu.Unlock() + r.chainInfoLock.Lock() + defer r.chainInfoLock.Unlock() if !commonclient.CtxIsHeathCheckRequest(ctx) { r.highestUserObservations.FinalizedBlockNumber = max(r.highestUserObservations.FinalizedBlockNumber, head.Number) } select { - case <-requestCh: // no need to update latestChainInfo, as rpcClient already started new life cycle + case <-requestCh: // no need to update latestChainInfo, as RPCClient already started new life cycle return default: r.latestChainInfo.FinalizedBlockNumber = head.Number } } -func (r *rpcClient) GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) { - r.stateMu.RLock() - defer r.stateMu.RUnlock() +func (r *RPCClient) GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) { + r.chainInfoLock.Lock() + defer r.chainInfoLock.Unlock() return r.latestChainInfo, r.highestUserObservations } diff --git a/core/chains/evm/client/rpc_client_test.go b/core/chains/evm/client/rpc_client_test.go index 12821880996..edbb10cc36f 100644 --- a/core/chains/evm/client/rpc_client_test.go +++ b/core/chains/evm/client/rpc_client_test.go @@ -7,6 +7,7 @@ import ( "fmt" "math/big" "net/url" + "sync" "testing" "time" @@ -18,11 +19,10 @@ import ( "github.com/tidwall/gjson" "go.uber.org/zap" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "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/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" @@ -37,7 +37,7 @@ func makeNewHeadWSMessage(head *evmtypes.Head) string { return fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x00","result":%s}}`, string(asJSON)) } -func TestRPCClient_SubscribeNewHead(t *testing.T) { +func TestRPCClient_SubscribeToHeads(t *testing.T) { t.Parallel() ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) defer cancel() @@ -45,22 +45,76 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { chainId := big.NewInt(123456) lggr := logger.Test(t) + nodePoolCfgHeadPolling := client.TestNodePoolConfig{ + NodeNewHeadsPollInterval: 1 * time.Second, + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + + nodePoolCfgNoPolling := client.TestNodePoolConfig{ + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + + var rpcHeads []*evmtypes.Head + previousHead := &evmtypes.Head{Number: 0} + SetNextRPCHead := func(head *evmtypes.Head) { + rpcHeads = append(rpcHeads, head) + } + serverCallBack := func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { if method == "eth_unsubscribe" { resp.Result = "true" return + } else if method == "eth_subscribe" { + assert.Equal(t, "eth_subscribe", method) + if assert.True(t, params.IsArray()) && assert.Equal(t, "newHeads", params.Array()[0].String()) { + resp.Result = `"0x00"` + } + return } - assert.Equal(t, "eth_subscribe", method) - if assert.True(t, params.IsArray()) && assert.Equal(t, "newHeads", params.Array()[0].String()) { - resp.Result = `"0x00"` + assert.Equal(t, "eth_getBlockByNumber", method) + if assert.True(t, params.IsArray()) && assert.Equal(t, "latest", params.Array()[0].String()) { + if len(rpcHeads) == 0 { + SetNextRPCHead(previousHead) + } + head := rpcHeads[0] + previousHead = head + rpcHeads = rpcHeads[1:] + jsonHead, err := json.Marshal(head) + if err != nil { + panic(fmt.Errorf("failed to marshal head: %w", err)) + } + resp.Result = string(jsonHead) } return } + + checkClosedRPCClientShouldRemoveExistingSub := func(t tests.TestingT, ctx context.Context, sub commontypes.Subscription, rpcClient *client.RPCClient) { + errCh := sub.Err() + + rpcClient.UnsubscribeAllExcept() + + // ensure sub is closed + select { + case <-errCh: // ok + default: + assert.Fail(t, "channel should be closed") + } + + require.NoError(t, rpcClient.Dial(ctx)) + } + + 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.TestObserved(t, zap.DebugLevel) + rpcClient := client.NewRPCClient(nodePoolCfgHeadPolling, observedLggr, nil, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + require.Equal(t, errors.New("cannot dial rpc client when both ws and http info are missing"), rpcClient.Dial(ctx)) + }) + t.Run("Updates chain info on new blocks", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) // set to default values @@ -72,14 +126,14 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) assert.Nil(t, highestUserObservations.TotalDifficulty) - ch := make(chan *evmtypes.Head) - sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + SetNextRPCHead(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)}) + SetNextRPCHead(&evmtypes.Head{Number: 128, TotalDifficulty: big.NewInt(500)}) + + ch, sub, err := rpc.SubscribeToHeads(tests.Context(t)) require.NoError(t, err) defer sub.Unsubscribe() - go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) // received 256 head <-ch - go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 128, TotalDifficulty: big.NewInt(500)})) // received 128 head <-ch @@ -96,8 +150,8 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { assertHighestUserObservations(highestUserObservations) - // DisconnectAll resets latest - rpc.DisconnectAll() + // Close resets latest + rpc.Close() latest, highestUserObservations = rpc.GetInterceptedChainInfo() assert.Equal(t, int64(0), latest.BlockNumber) @@ -110,14 +164,15 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) - ch := make(chan *evmtypes.Head) - sub, err := rpc.SubscribeNewHead(commonclient.CtxAddHealthCheckFlag(tests.Context(t)), ch) + + SetNextRPCHead(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)}) + + ch, sub, err := rpc.SubscribeToHeads(commonclient.CtxAddHealthCheckFlag(tests.Context(t))) require.NoError(t, err) defer sub.Unsubscribe() - go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) // received 256 head <-ch @@ -126,46 +181,156 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { assert.Equal(t, int64(0), latest.FinalizedBlockNumber) assert.Equal(t, big.NewInt(1000), latest.TotalDifficulty) - assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(256), highestUserObservations.BlockNumber) assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) - assert.Equal(t, (*big.Int)(nil), highestUserObservations.TotalDifficulty) + assert.Equal(t, big.NewInt(1000), highestUserObservations.TotalDifficulty) + }) + t.Run("SubscribeToHeads with http polling enabled will update new heads", func(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, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + latest, highestUserObservations := rpc.GetInterceptedChainInfo() + // latest chain info hasn't been initialized + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + + SetNextRPCHead(&evmtypes.Head{Number: 127, TotalDifficulty: big.NewInt(1000)}) + + headCh, sub, err := rpc.SubscribeToHeads(commonclient.CtxAddHealthCheckFlag(tests.Context(t))) + require.NoError(t, err) + defer sub.Unsubscribe() + + head := <-headCh + assert.Equal(t, int64(127), head.BlockNumber()) + // the http polling subscription should update the head block + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + assert.Equal(t, int64(127), latest.BlockNumber) + }) + t.Run("Concurrent Unsubscribe and onNewHead calls do not lead to a deadlock", func(t *testing.T) { + const numberOfAttempts = 1000 // need a large number to increase the odds of reproducing the issue + 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, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + var wg sync.WaitGroup + for i := 0; i < numberOfAttempts; i++ { + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + wg.Add(2) + go func() { + server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) + wg.Done() + }() + go func() { + rpc.UnsubscribeAllExcept(sub) + sub.Unsubscribe() + wg.Done() + }() + wg.Wait() + } }) t.Run("Block's chain ID matched configured", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgHeadPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) - ch := make(chan *evmtypes.Head) - sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + ch, sub, err := rpc.SubscribeToHeads(tests.Context(t)) require.NoError(t, err) defer sub.Unsubscribe() go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256})) head := <-ch require.Equal(t, chainId, head.ChainID()) }) - t.Run("Failed SubscribeNewHead returns and logs proper error", func(t *testing.T) { + t.Run("Failed SubscribeToHeads returns and logs proper error", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, func(reqMethod string, reqParams gjson.Result) (resp testutils.JSONRPCResponse) { return resp }) wsURL := server.WSURL() observedLggr, observed := logger.TestObserved(t, zap.DebugLevel) - rpc := client.NewRPCClient(observedLggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgNoPolling, observedLggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") require.NoError(t, rpc.Dial(ctx)) server.Close() - _, err := rpc.SubscribeNewHead(ctx, make(chan *evmtypes.Head)) + _, _, err := rpc.SubscribeToHeads(ctx) require.ErrorContains(t, err, "RPCClient returned error (rpc)") tests.AssertLogEventually(t, observed, "evmclient.Client#EthSubscribe RPC call failure") }) + 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(nodePoolCfgNoPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeToHeads subscription with HTTP polling", func(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, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + 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(nodePoolCfgNoPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeToHeads subscription with HTTP polling", func(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, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeToFinalizedHeads subscription", func(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, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToFinalizedHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) t.Run("Subscription error is properly wrapper", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() - rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfgNoPolling, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) - sub, err := rpc.SubscribeNewHead(ctx, make(chan *evmtypes.Head)) + SetNextRPCHead(nil) + _, sub, err := rpc.SubscribeToHeads(ctx) require.NoError(t, err) go server.MustWriteBinaryMessageSync(t, "invalid msg") + select { case err = <-sub.Err(): require.ErrorContains(t, err, "RPCClient returned error (rpc): invalid character") @@ -178,17 +343,31 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { func TestRPCClient_SubscribeFilterLogs(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("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.TestObserved(t, zap.DebugLevel) + rpcClient := client.NewRPCClient(nodePoolCfg, observedLggr, nil, &url.URL{}, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + require.Nil(t, rpcClient.Dial(ctx)) + + _, err := rpcClient.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) + require.Equal(t, errors.New("SubscribeFilterLogs is not allowed without ws url"), err) + }) t.Run("Failed SubscribeFilterLogs logs and returns proper error", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, func(reqMethod string, reqParams gjson.Result) (resp testutils.JSONRPCResponse) { return resp }) wsURL := server.WSURL() observedLggr, observed := logger.TestObserved(t, zap.DebugLevel) - rpc := client.NewRPCClient(observedLggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, observedLggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") require.NoError(t, rpc.Dial(ctx)) server.Close() _, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) @@ -205,7 +384,7 @@ func TestRPCClient_SubscribeFilterLogs(t *testing.T) { return resp }) wsURL := server.WSURL() - rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, lggr, wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") defer rpc.Close() require.NoError(t, rpc.Dial(ctx)) sub, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) @@ -227,6 +406,11 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) defer cancel() + nodePoolCfg := client.TestNodePoolConfig{ + NodeNewHeadsPollInterval: 1 * time.Second, + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + chainId := big.NewInt(123456) lggr := logger.Test(t) @@ -254,7 +438,7 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { } server := createRPCServer() - rpc := client.NewRPCClient(lggr, *server.URL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, lggr, server.URL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.QueryTimeout, "") require.NoError(t, rpc.Dial(ctx)) defer rpc.Close() server.Head = &evmtypes.Head{Number: 128} @@ -293,8 +477,8 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { assert.Equal(t, int64(0), latest.BlockNumber) assert.Equal(t, int64(256), latest.FinalizedBlockNumber) - // DisconnectAll resets latest ChainInfo - rpc.DisconnectAll() + // Close resets latest ChainInfo + rpc.Close() latest, highestUserObservations = rpc.GetInterceptedChainInfo() assert.Equal(t, int64(0), highestUserObservations.BlockNumber) assert.Equal(t, int64(128), highestUserObservations.FinalizedBlockNumber) @@ -306,40 +490,45 @@ func TestRPCClient_LatestFinalizedBlock(t *testing.T) { func TestRpcClientLargePayloadTimeout(t *testing.T) { t.Parallel() + nodePoolCfg := client.TestNodePoolConfig{ + NodeNewHeadsPollInterval: 1 * time.Second, + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + testCases := []struct { Name string - Fn func(ctx context.Context, rpc client.RPCClient) error + Fn func(ctx context.Context, rpc *client.RPCClient) error }{ { Name: "SendTransaction", - Fn: func(ctx context.Context, rpc client.RPCClient) error { + Fn: func(ctx context.Context, rpc *client.RPCClient) error { return rpc.SendTransaction(ctx, types.NewTx(&types.LegacyTx{})) }, }, { Name: "EstimateGas", - Fn: func(ctx context.Context, rpc client.RPCClient) error { + Fn: func(ctx context.Context, rpc *client.RPCClient) error { _, err := rpc.EstimateGas(ctx, ethereum.CallMsg{}) return err }, }, { Name: "CallContract", - Fn: func(ctx context.Context, rpc client.RPCClient) error { + Fn: func(ctx context.Context, rpc *client.RPCClient) error { _, err := rpc.CallContract(ctx, ethereum.CallMsg{}, nil) return err }, }, { Name: "CallContext", - Fn: func(ctx context.Context, rpc client.RPCClient) error { + Fn: func(ctx context.Context, rpc *client.RPCClient) error { err := rpc.CallContext(ctx, nil, "rpc_call", nil) return err }, }, { Name: "BatchCallContext", - Fn: func(ctx context.Context, rpc client.RPCClient) error { + Fn: func(ctx context.Context, rpc *client.RPCClient) error { err := rpc.BatchCallContext(ctx, nil) return err }, @@ -364,7 +553,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(logger.Test(t), *rpcURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, largePayloadRPCTimeout, rpcTimeout, "") + rpc := client.NewRPCClient(nodePoolCfg, logger.Test(t), rpcURL, nil, "rpc", 1, chainId, commonclient.Primary, largePayloadRPCTimeout, rpcTimeout, "") require.NoError(t, rpc.Dial(ctx)) defer rpc.Close() err := testCase.Fn(ctx, rpc) @@ -376,6 +565,11 @@ func TestRpcClientLargePayloadTimeout(t *testing.T) { func TestAstarCustomFinality(t *testing.T) { t.Parallel() + nodePoolCfg := client.TestNodePoolConfig{ + NodeNewHeadsPollInterval: 1 * time.Second, + NodeFinalizedBlockPollInterval: 1 * time.Second, + } + chainId := big.NewInt(123456) // create new server that returns 4 block for Astar custom finality and 8 block for finality tag. wsURL := testutils.NewWSServer(t, chainId, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { @@ -404,7 +598,7 @@ func TestAstarCustomFinality(t *testing.T) { const expectedFinalizedBlockNumber = int64(4) const expectedFinalizedBlockHash = "0x7441e97acf83f555e0deefef86db636bc8a37eb84747603412884e4df4d22804" - rpcClient := client.NewRPCClient(logger.Test(t), *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, chaintype.ChainAstar) + rpcClient := client.NewRPCClient(nodePoolCfg, logger.Test(t), wsURL, nil, "rpc", 1, chainId, commonclient.Primary, commonclient.QueryTimeout, commonclient.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 7dfd39f444c..a831f38d10d 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -156,6 +156,10 @@ func (c *SimulatedBackendClient) LINKBalance(ctx context.Context, address common panic("not implemented") } +func (c *SimulatedBackendClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + panic("not implemented") +} + // TransactionReceipt returns the transaction receipt for the given transaction hash. func (c *SimulatedBackendClient) TransactionReceipt(ctx context.Context, receipt common.Hash) (*types.Receipt, error) { return c.b.TransactionReceipt(ctx, receipt) @@ -267,9 +271,8 @@ func (c *SimulatedBackendClient) PendingNonceAt(ctx context.Context, account com } // NonceAt gets nonce as of a specified block. -func (c *SimulatedBackendClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (evmtypes.Nonce, error) { - nonce, err := c.b.NonceAt(ctx, account, blockNumber) - return evmtypes.Nonce(nonce), err +func (c *SimulatedBackendClient) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { + return c.b.NonceAt(ctx, account, blockNumber) } // BalanceAt gets balance as of a specified block. @@ -293,20 +296,20 @@ func (h *headSubscription) Unsubscribe() { // Err returns err channel func (h *headSubscription) Err() <-chan error { return h.subscription.Err() } -// SubscribeNewHead registers a subscription for push notifications of new blocks. +// SubscribeToHeads registers a subscription for push notifications of new blocks. // Note the sim's API only accepts types.Head so we have this goroutine // to convert those into evmtypes.Head. -func (c *SimulatedBackendClient) SubscribeNewHead( +func (c *SimulatedBackendClient) SubscribeToHeads( ctx context.Context, - channel chan<- *evmtypes.Head, -) (ethereum.Subscription, error) { +) (<-chan *evmtypes.Head, ethereum.Subscription, error) { subscription := &headSubscription{unSub: make(chan chan struct{})} ch := make(chan *types.Header) + channel := make(chan *evmtypes.Head) var err error subscription.subscription, err = c.b.SubscribeNewHead(ctx, ch) if err != nil { - return nil, fmt.Errorf("%w: could not subscribe to new heads on "+ + return nil, nil, fmt.Errorf("%w: could not subscribe to new heads on "+ "simulated backend", err) } go func() { @@ -316,7 +319,15 @@ func (c *SimulatedBackendClient) SubscribeNewHead( case h := <-ch: var head *evmtypes.Head if h != nil { - head = &evmtypes.Head{Difficulty: h.Difficulty, Timestamp: time.Unix(int64(h.Time), 0), Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, Parent: lastHead, EVMChainID: ubig.New(c.chainId)} + head = &evmtypes.Head{ + Difficulty: h.Difficulty, + Timestamp: time.Unix(int64(h.Time), 0), //nolint:gosec + Number: h.Number.Int64(), + Hash: h.Hash(), + ParentHash: h.ParentHash, + EVMChainID: ubig.New(c.chainId), + } + head.Parent.Store(lastHead) lastHead = head } select { @@ -334,7 +345,7 @@ func (c *SimulatedBackendClient) SubscribeNewHead( } } }() - return subscription, err + return channel, subscription, err } // HeaderByNumber returns the geth header type. @@ -415,7 +426,7 @@ func (c *SimulatedBackendClient) CallContract(ctx context.Context, msg ethereum. res, err := c.b.CallContract(ctx, msg, blockNumber) if err != nil { dataErr := revertError{} - if errors.Is(err, &dataErr) { + if errors.As(err, &dataErr) { return nil, &JsonError{Data: dataErr.ErrorData(), Message: dataErr.Error(), Code: 3} } // Generic revert, no data @@ -434,7 +445,7 @@ func (c *SimulatedBackendClient) PendingCallContract(ctx context.Context, msg et res, err := c.b.PendingCallContract(ctx, msg) if err != nil { dataErr := revertError{} - if errors.Is(err, &dataErr) { + if errors.As(err, &dataErr) { return nil, &JsonError{Data: dataErr.ErrorData(), Message: dataErr.Error(), Code: 3} } // Generic revert, no data diff --git a/core/chains/evm/config/chain_scoped.go b/core/chains/evm/config/chain_scoped.go index b9b19cdc2c0..de89272b5e2 100644 --- a/core/chains/evm/config/chain_scoped.go +++ b/core/chains/evm/config/chain_scoped.go @@ -176,6 +176,10 @@ func (e *EVMConfig) OperatorFactoryAddress() string { return e.C.OperatorFactoryAddress.String() } +func (e *EVMConfig) LogBroadcasterEnabled() bool { + return e.C.LogBroadcasterEnabled == nil || *e.C.LogBroadcasterEnabled +} + func (e *EVMConfig) LogPrunePageSize() uint32 { return *e.C.LogPrunePageSize } diff --git a/core/chains/evm/config/chain_scoped_client_errors.go b/core/chains/evm/config/chain_scoped_client_errors.go index 53bb04846d2..f9d2096e903 100644 --- a/core/chains/evm/config/chain_scoped_client_errors.go +++ b/core/chains/evm/config/chain_scoped_client_errors.go @@ -48,3 +48,4 @@ func (c *clientErrorsConfig) Fatal() string { return derefOrDefault(c.c.Fatal) } func (c *clientErrorsConfig) ServiceUnavailable() string { return derefOrDefault(c.c.ServiceUnavailable) } +func (c *clientErrorsConfig) TooManyResults() string { return derefOrDefault(c.c.TooManyResults) } diff --git a/core/chains/evm/config/chain_scoped_gas_estimator.go b/core/chains/evm/config/chain_scoped_gas_estimator.go index 689d5e38b81..3f557516e98 100644 --- a/core/chains/evm/config/chain_scoped_gas_estimator.go +++ b/core/chains/evm/config/chain_scoped_gas_estimator.go @@ -1,10 +1,13 @@ package config import ( + "time" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) type gasEstimatorConfig struct { @@ -36,6 +39,14 @@ func (g *gasEstimatorConfig) BlockHistory() BlockHistory { return &blockHistoryConfig{c: g.c.BlockHistory, blockDelay: g.blockDelay, bumpThreshold: g.c.BumpThreshold} } +func (g *gasEstimatorConfig) FeeHistory() FeeHistory { + return &feeHistoryConfig{c: g.c.FeeHistory} +} + +func (g *gasEstimatorConfig) DAOracle() DAOracle { + return &daOracleConfig{c: g.c.DAOracle} +} + func (g *gasEstimatorConfig) EIP1559DynamicFees() bool { return *g.c.EIP1559DynamicFees } @@ -108,6 +119,31 @@ func (g *gasEstimatorConfig) LimitJobType() LimitJobType { return &limitJobTypeConfig{c: g.c.LimitJobType} } +func (g *gasEstimatorConfig) EstimateLimit() bool { + return *g.c.EstimateLimit +} + +type daOracleConfig struct { + c toml.DAOracle +} + +func (d *daOracleConfig) OracleType() toml.DAOracleType { + return d.c.OracleType +} + +// OracleAddress returns the address of the oracle contract and is only supported on the OP stack for now. +func (d *daOracleConfig) OracleAddress() *types.EIP55Address { + return d.c.OracleAddress +} + +// CustomGasPriceCalldata returns the calldata for a custom gas price API. +func (d *daOracleConfig) CustomGasPriceCalldata() string { + if d.c.OracleType == toml.DAOracleCustomCalldata { + return d.c.CustomGasPriceCalldata + } + return "" +} + type limitJobTypeConfig struct { c toml.GasLimitJobType } @@ -172,3 +208,11 @@ func (b *blockHistoryConfig) TransactionPercentile() uint16 { func (b *blockHistoryConfig) BlockDelay() uint16 { return *b.blockDelay } + +type feeHistoryConfig struct { + c toml.FeeHistoryEstimator +} + +func (u *feeHistoryConfig) CacheTimeout() time.Duration { + return u.c.CacheTimeout.Duration() +} diff --git a/core/chains/evm/config/chain_scoped_head_tracker.go b/core/chains/evm/config/chain_scoped_head_tracker.go index 8bc1ff188a7..75a630238ec 100644 --- a/core/chains/evm/config/chain_scoped_head_tracker.go +++ b/core/chains/evm/config/chain_scoped_head_tracker.go @@ -29,3 +29,7 @@ func (h *headTrackerConfig) FinalityTagBypass() bool { func (h *headTrackerConfig) MaxAllowedFinalityDepth() uint32 { return *h.c.MaxAllowedFinalityDepth } + +func (h *headTrackerConfig) PersistenceEnabled() bool { + return *h.c.PersistenceEnabled +} diff --git a/core/chains/evm/config/chain_scoped_node_pool.go b/core/chains/evm/config/chain_scoped_node_pool.go index a4974366486..4b1d02d148e 100644 --- a/core/chains/evm/config/chain_scoped_node_pool.go +++ b/core/chains/evm/config/chain_scoped_node_pool.go @@ -38,6 +38,10 @@ func (n *NodePoolConfig) FinalizedBlockPollInterval() time.Duration { return n.C.FinalizedBlockPollInterval.Duration() } +func (n *NodePoolConfig) NewHeadsPollInterval() time.Duration { + return n.C.NewHeadsPollInterval.Duration() +} + func (n *NodePoolConfig) Errors() ClientErrors { return &clientErrorsConfig{c: n.C.Errors} } func (n *NodePoolConfig) EnforceRepeatableRead() bool { diff --git a/core/chains/evm/config/chain_scoped_workflow.go b/core/chains/evm/config/chain_scoped_workflow.go index 36dcb3ea41c..816270886a4 100644 --- a/core/chains/evm/config/chain_scoped_workflow.go +++ b/core/chains/evm/config/chain_scoped_workflow.go @@ -16,3 +16,7 @@ func (b *workflowConfig) FromAddress() *types.EIP55Address { func (b *workflowConfig) ForwarderAddress() *types.EIP55Address { return b.c.ForwarderAddress } + +func (b *workflowConfig) GasLimitDefault() *uint64 { + return b.c.GasLimitDefault +} diff --git a/core/chains/evm/config/chaintype/chaintype.go b/core/chains/evm/config/chaintype/chaintype.go index 07ea6206241..b2eff02834b 100644 --- a/core/chains/evm/config/chaintype/chaintype.go +++ b/core/chains/evm/config/chaintype/chaintype.go @@ -14,6 +14,7 @@ const ( ChainGnosis ChainType = "gnosis" ChainHedera ChainType = "hedera" ChainKroma ChainType = "kroma" + ChainMantle ChainType = "mantle" ChainMetis ChainType = "metis" ChainOptimismBedrock ChainType = "optimismBedrock" ChainScroll ChainType = "scroll" @@ -21,6 +22,7 @@ const ( ChainXLayer ChainType = "xlayer" ChainZkEvm ChainType = "zkevm" ChainZkSync ChainType = "zksync" + ChainZircuit ChainType = "zircuit" ) // IsL2 returns true if this chain is a Layer 2 chain. Notably: @@ -37,13 +39,13 @@ func (c ChainType) IsL2() bool { func (c ChainType) IsValid() bool { switch c { - case "", ChainArbitrum, ChainAstar, ChainCelo, ChainGnosis, ChainHedera, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXLayer, ChainZkEvm, ChainZkSync: + case "", ChainArbitrum, ChainAstar, ChainCelo, ChainGnosis, ChainHedera, ChainKroma, ChainMantle, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXLayer, ChainZkEvm, ChainZkSync, ChainZircuit: return true } return false } -func ChainTypeFromSlug(slug string) ChainType { +func FromSlug(slug string) ChainType { switch slug { case "arbitrum": return ChainArbitrum @@ -57,6 +59,8 @@ func ChainTypeFromSlug(slug string) ChainType { return ChainHedera case "kroma": return ChainKroma + case "mantle": + return ChainMantle case "metis": return ChainMetis case "optimismBedrock": @@ -71,64 +75,67 @@ func ChainTypeFromSlug(slug string) ChainType { return ChainZkEvm case "zksync": return ChainZkSync + case "zircuit": + return ChainZircuit default: return ChainType(slug) } } -type ChainTypeConfig struct { +type Config struct { value ChainType slug string } -func NewChainTypeConfig(slug string) *ChainTypeConfig { - return &ChainTypeConfig{ - value: ChainTypeFromSlug(slug), +func NewConfig(slug string) *Config { + return &Config{ + value: FromSlug(slug), slug: slug, } } -func (c *ChainTypeConfig) MarshalText() ([]byte, error) { +func (c *Config) MarshalText() ([]byte, error) { if c == nil { return nil, nil } return []byte(c.slug), nil } -func (c *ChainTypeConfig) UnmarshalText(b []byte) error { +func (c *Config) UnmarshalText(b []byte) error { c.slug = string(b) - c.value = ChainTypeFromSlug(c.slug) + c.value = FromSlug(c.slug) return nil } -func (c *ChainTypeConfig) Slug() string { +func (c *Config) Slug() string { if c == nil { return "" } return c.slug } -func (c *ChainTypeConfig) ChainType() ChainType { +func (c *Config) ChainType() ChainType { if c == nil { return "" } return c.value } -func (c *ChainTypeConfig) String() string { +func (c *Config) String() string { if c == nil { return "" } return string(c.value) } -var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Join([]string{ +var ErrInvalid = fmt.Errorf("must be one of %s or omitted", strings.Join([]string{ string(ChainArbitrum), string(ChainAstar), string(ChainCelo), string(ChainGnosis), string(ChainHedera), string(ChainKroma), + string(ChainMantle), string(ChainMetis), string(ChainOptimismBedrock), string(ChainScroll), @@ -136,4 +143,5 @@ var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Joi string(ChainXLayer), string(ChainZkEvm), string(ChainZkSync), + string(ChainZircuit), }, ", ")) diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index 3ccdfeea8b8..6d4bcf159b5 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -11,6 +11,7 @@ import ( "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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -43,6 +44,7 @@ type EVM interface { MinIncomingConfirmations() uint32 NonceAutoSync() bool OperatorFactoryAddress() string + LogBroadcasterEnabled() bool RPCDefaultBatchSize() uint32 NodeNoNewHeadsThreshold() time.Duration FinalizedBlockOffset() uint32 @@ -75,6 +77,7 @@ type HeadTracker interface { SamplingInterval() time.Duration FinalityTagBypass() bool MaxAllowedFinalityDepth() uint32 + PersistenceEnabled() bool } type BalanceMonitor interface { @@ -96,6 +99,7 @@ type ClientErrors interface { TransactionAlreadyMined() string Fatal() string ServiceUnavailable() string + TooManyResults() string } type Transactions interface { @@ -117,6 +121,7 @@ type AutoPurgeConfig interface { type GasEstimator interface { BlockHistory() BlockHistory + FeeHistory() FeeHistory LimitJobType() LimitJobType EIP1559DynamicFees() bool @@ -136,6 +141,8 @@ type GasEstimator interface { PriceMin() *assets.Wei Mode() string PriceMaxKey(gethcommon.Address) *assets.Wei + EstimateLimit() bool + DAOracle() DAOracle } type LimitJobType interface { @@ -157,9 +164,20 @@ type BlockHistory interface { TransactionPercentile() uint16 } +type DAOracle interface { + OracleType() toml.DAOracleType + OracleAddress() *types.EIP55Address + CustomGasPriceCalldata() string +} + +type FeeHistory interface { + CacheTimeout() time.Duration +} + type Workflow interface { FromAddress() *types.EIP55Address ForwarderAddress() *types.EIP55Address + GasLimitDefault() *uint64 } type NodePool interface { @@ -173,6 +191,7 @@ type NodePool interface { Errors() ClientErrors EnforceRepeatableRead() bool DeathDeclarationDelay() time.Duration + NewHeadsPollInterval() time.Duration } // TODO BCF-2509 does the chainscopedconfig really need the entire app config? diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index ba362bda981..53155d7e7d2 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -205,6 +205,25 @@ func TestChainScopedConfig(t *testing.T) { assert.Equal(t, val.String(), cfg3.EVM().OperatorFactoryAddress()) }) }) + + t.Run("LogBroadcasterEnabled", func(t *testing.T) { + t.Run("turn on LogBroadcasterEnabled by default", func(t *testing.T) { + assert.Equal(t, true, cfg.EVM().LogBroadcasterEnabled()) + }) + + t.Run("verify LogBroadcasterEnabled is set correctly", func(t *testing.T) { + val := false + cfg3 := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { + c.LogBroadcasterEnabled = ptr(val) + }) + + assert.Equal(t, false, cfg3.EVM().LogBroadcasterEnabled()) + }) + + t.Run("use Noop logBroadcaster when LogBroadcaster is disabled", func(t *testing.T) { + + }) + }) } func TestChainScopedConfig_BlockHistory(t *testing.T) { @@ -220,6 +239,13 @@ func TestChainScopedConfig_BlockHistory(t *testing.T) { assert.Equal(t, uint16(1), bh.BlockDelay()) assert.Equal(t, uint16(4), bh.EIP1559FeeCapBufferBlocks()) } +func TestChainScopedConfig_FeeHistory(t *testing.T) { + t.Parallel() + cfg := testutils.NewTestChainScopedConfig(t, nil) + + u := cfg.EVM().GasEstimator().FeeHistory() + assert.Equal(t, 10*time.Second, u.CacheTimeout()) +} func TestChainScopedConfig_GasEstimator(t *testing.T) { t.Parallel() @@ -243,6 +269,7 @@ func TestChainScopedConfig_GasEstimator(t *testing.T) { assert.Equal(t, assets.GWei(100), ge.FeeCapDefault()) assert.Equal(t, assets.NewWeiI(1), ge.TipCapDefault()) assert.Equal(t, assets.NewWeiI(1), ge.TipCapMin()) + assert.Equal(t, false, ge.EstimateLimit()) } func TestChainScopedConfig_BSCDefaults(t *testing.T) { @@ -316,6 +343,7 @@ func TestChainScopedConfig_HeadTracker(t *testing.T) { assert.Equal(t, time.Second, ht.SamplingInterval()) assert.Equal(t, true, ht.FinalityTagBypass()) assert.Equal(t, uint32(10000), ht.MaxAllowedFinalityDepth()) + assert.Equal(t, true, ht.PersistenceEnabled()) } func TestNodePoolConfig(t *testing.T) { @@ -353,6 +381,7 @@ func TestClientErrorsConfig(t *testing.T) { TransactionAlreadyMined: ptr("client error transaction already mined"), Fatal: ptr("client error fatal"), ServiceUnavailable: ptr("client error service unavailable"), + TooManyResults: ptr("client error too many results"), }, } }) @@ -372,6 +401,7 @@ func TestClientErrorsConfig(t *testing.T) { assert.Equal(t, "client error transaction already mined", errors.TransactionAlreadyMined()) assert.Equal(t, "client error fatal", errors.Fatal()) assert.Equal(t, "client error service unavailable", errors.ServiceUnavailable()) + assert.Equal(t, "client error too many results", errors.TooManyResults()) }) } diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go index b8e813e8068..44013768156 100644 --- a/core/chains/evm/config/mocks/gas_estimator.go +++ b/core/chains/evm/config/mocks/gas_estimator.go @@ -253,6 +253,53 @@ func (_c *GasEstimator_BumpTxDepth_Call) RunAndReturn(run func() uint32) *GasEst return _c } +// DAOracle provides a mock function with given fields: +func (_m *GasEstimator) DAOracle() config.DAOracle { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for DAOracle") + } + + var r0 config.DAOracle + if rf, ok := ret.Get(0).(func() config.DAOracle); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(config.DAOracle) + } + } + + return r0 +} + +// GasEstimator_DAOracle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DAOracle' +type GasEstimator_DAOracle_Call struct { + *mock.Call +} + +// DAOracle is a helper method to define mock.On call +func (_e *GasEstimator_Expecter) DAOracle() *GasEstimator_DAOracle_Call { + return &GasEstimator_DAOracle_Call{Call: _e.mock.On("DAOracle")} +} + +func (_c *GasEstimator_DAOracle_Call) Run(run func()) *GasEstimator_DAOracle_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GasEstimator_DAOracle_Call) Return(_a0 config.DAOracle) *GasEstimator_DAOracle_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GasEstimator_DAOracle_Call) RunAndReturn(run func() config.DAOracle) *GasEstimator_DAOracle_Call { + _c.Call.Return(run) + return _c +} + // EIP1559DynamicFees provides a mock function with given fields: func (_m *GasEstimator) EIP1559DynamicFees() bool { ret := _m.Called() @@ -298,6 +345,51 @@ func (_c *GasEstimator_EIP1559DynamicFees_Call) RunAndReturn(run func() bool) *G return _c } +// EstimateLimit provides a mock function with given fields: +func (_m *GasEstimator) EstimateLimit() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for EstimateLimit") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// GasEstimator_EstimateLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateLimit' +type GasEstimator_EstimateLimit_Call struct { + *mock.Call +} + +// EstimateLimit is a helper method to define mock.On call +func (_e *GasEstimator_Expecter) EstimateLimit() *GasEstimator_EstimateLimit_Call { + return &GasEstimator_EstimateLimit_Call{Call: _e.mock.On("EstimateLimit")} +} + +func (_c *GasEstimator_EstimateLimit_Call) Run(run func()) *GasEstimator_EstimateLimit_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GasEstimator_EstimateLimit_Call) Return(_a0 bool) *GasEstimator_EstimateLimit_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GasEstimator_EstimateLimit_Call) RunAndReturn(run func() bool) *GasEstimator_EstimateLimit_Call { + _c.Call.Return(run) + return _c +} + // FeeCapDefault provides a mock function with given fields: func (_m *GasEstimator) FeeCapDefault() *assets.Wei { ret := _m.Called() @@ -345,6 +437,53 @@ func (_c *GasEstimator_FeeCapDefault_Call) RunAndReturn(run func() *assets.Wei) return _c } +// FeeHistory provides a mock function with given fields: +func (_m *GasEstimator) FeeHistory() config.FeeHistory { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 config.FeeHistory + if rf, ok := ret.Get(0).(func() config.FeeHistory); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(config.FeeHistory) + } + } + + return r0 +} + +// GasEstimator_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type GasEstimator_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +func (_e *GasEstimator_Expecter) FeeHistory() *GasEstimator_FeeHistory_Call { + return &GasEstimator_FeeHistory_Call{Call: _e.mock.On("FeeHistory")} +} + +func (_c *GasEstimator_FeeHistory_Call) Run(run func()) *GasEstimator_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GasEstimator_FeeHistory_Call) Return(_a0 config.FeeHistory) *GasEstimator_FeeHistory_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GasEstimator_FeeHistory_Call) RunAndReturn(run func() config.FeeHistory) *GasEstimator_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // LimitDefault provides a mock function with given fields: func (_m *GasEstimator) LimitDefault() uint64 { ret := _m.Called() diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index ac7841ac497..faf115e07ad 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -23,7 +23,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) -var ErrNotFound = errors.New("not found") +var ( + ErrNotFound = errors.New("not found") +) type HasEVMConfigs interface { EVMConfigs() EVMConfigs @@ -311,20 +313,32 @@ func (c *EVMConfig) ValidateConfig() (err error) { err = multierr.Append(err, commonconfig.ErrMissing{Name: "Nodes", Msg: "must have at least one node"}) } else { var hasPrimary bool - for _, n := range c.Nodes { + var logBroadcasterEnabled bool + if c.LogBroadcasterEnabled != nil { + logBroadcasterEnabled = *c.LogBroadcasterEnabled + } + + for i, n := range c.Nodes { if n.SendOnly != nil && *n.SendOnly { continue } + hasPrimary = true - break + + // if the node is a primary node, then the WS URL is required when LogBroadcaster is enabled + if logBroadcasterEnabled && (n.WSURL == nil || n.WSURL.IsZero()) { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "Nodes", Msg: fmt.Sprintf("%vth node (primary) must have a valid WSURL when LogBroadcaster is enabled", i)}) + } } + if !hasPrimary { err = multierr.Append(err, commonconfig.ErrMissing{Name: "Nodes", - Msg: "must have at least one primary node with WSURL"}) + Msg: "must have at least one primary node"}) } } err = multierr.Append(err, c.Chain.ValidateConfig()) + err = multierr.Append(err, c.NodePool.ValidateConfig(c.Chain.FinalityTagEnabled)) return } @@ -341,7 +355,7 @@ type Chain struct { AutoCreateKey *bool BlockBackfillDepth *uint32 BlockBackfillSkip *bool - ChainType *chaintype.ChainTypeConfig + ChainType *chaintype.Config FinalityDepth *uint32 FinalityTagEnabled *bool FlagsContractAddress *types.EIP55Address @@ -356,6 +370,7 @@ type Chain struct { NonceAutoSync *bool NoNewHeadsThreshold *commonconfig.Duration OperatorFactoryAddress *types.EIP55Address + LogBroadcasterEnabled *bool RPCDefaultBatchSize *uint32 RPCBlockQueryDelay *uint16 FinalizedBlockOffset *uint32 @@ -375,7 +390,7 @@ type Chain struct { func (c *Chain) ValidateConfig() (err error) { if !c.ChainType.ChainType().IsValid() { err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: c.ChainType.ChainType(), - Msg: chaintype.ErrInvalidChainType.Error()}) + Msg: chaintype.ErrInvalid.Error()}) } if c.GasEstimator.BumpTxDepth != nil && *c.GasEstimator.BumpTxDepth > *c.Transactions.MaxInFlight { @@ -521,6 +536,7 @@ func (a *Automation) setFrom(f *Automation) { type Workflow struct { FromAddress *types.EIP55Address `toml:",omitempty"` ForwarderAddress *types.EIP55Address `toml:",omitempty"` + GasLimitDefault *uint64 } func (m *Workflow) setFrom(f *Workflow) { @@ -530,6 +546,10 @@ func (m *Workflow) setFrom(f *Workflow) { if v := f.ForwarderAddress; v != nil { m.ForwarderAddress = v } + + if v := f.GasLimitDefault; v != nil { + m.GasLimitDefault = v + } } type BalanceMonitor struct { @@ -554,6 +574,7 @@ type GasEstimator struct { LimitMultiplier *decimal.Decimal LimitTransfer *uint64 LimitJobType GasLimitJobType `toml:",omitempty"` + EstimateLimit *bool BumpMin *assets.Wei BumpPercent *uint16 @@ -567,6 +588,8 @@ type GasEstimator struct { TipCapMin *assets.Wei BlockHistory BlockHistoryEstimator `toml:",omitempty"` + FeeHistory FeeHistoryEstimator `toml:",omitempty"` + DAOracle DAOracle `toml:",omitempty"` } func (e *GasEstimator) ValidateConfig() (err error) { @@ -641,6 +664,9 @@ func (e *GasEstimator) setFrom(f *GasEstimator) { if v := f.LimitTransfer; v != nil { e.LimitTransfer = v } + if v := f.EstimateLimit; v != nil { + e.EstimateLimit = v + } if v := f.PriceDefault; v != nil { e.PriceDefault = v } @@ -658,6 +684,8 @@ func (e *GasEstimator) setFrom(f *GasEstimator) { } e.LimitJobType.setFrom(&f.LimitJobType) e.BlockHistory.setFrom(&f.BlockHistory) + e.FeeHistory.setFrom(&f.FeeHistory) + e.DAOracle.setFrom(&f.DAOracle) } type GasLimitJobType struct { @@ -720,6 +748,47 @@ func (e *BlockHistoryEstimator) setFrom(f *BlockHistoryEstimator) { } } +type FeeHistoryEstimator struct { + CacheTimeout *commonconfig.Duration +} + +func (u *FeeHistoryEstimator) setFrom(f *FeeHistoryEstimator) { + if v := f.CacheTimeout; v != nil { + u.CacheTimeout = v + } +} + +type DAOracle struct { + OracleType DAOracleType + OracleAddress *types.EIP55Address + CustomGasPriceCalldata string +} + +type DAOracleType string + +const ( + DAOracleOPStack = DAOracleType("opstack") + DAOracleArbitrum = DAOracleType("arbitrum") + DAOracleZKSync = DAOracleType("zksync") + DAOracleCustomCalldata = DAOracleType("custom_calldata") +) + +func (o DAOracleType) IsValid() bool { + switch o { + case "", DAOracleOPStack, DAOracleArbitrum, DAOracleZKSync, DAOracleCustomCalldata: + return true + } + return false +} + +func (d *DAOracle) setFrom(f *DAOracle) { + d.OracleType = f.OracleType + if v := f.OracleAddress; v != nil { + d.OracleAddress = v + } + d.CustomGasPriceCalldata = f.CustomGasPriceCalldata +} + type KeySpecificConfig []KeySpecific func (ks KeySpecificConfig) ValidateConfig() (err error) { @@ -756,6 +825,7 @@ type HeadTracker struct { SamplingInterval *commonconfig.Duration MaxAllowedFinalityDepth *uint32 FinalityTagBypass *bool + PersistenceEnabled *bool } func (t *HeadTracker) setFrom(f *HeadTracker) { @@ -774,6 +844,9 @@ func (t *HeadTracker) setFrom(f *HeadTracker) { if v := f.FinalityTagBypass; v != nil { t.FinalityTagBypass = v } + if v := f.PersistenceEnabled; v != nil { + t.PersistenceEnabled = v + } } func (t *HeadTracker) ValidateConfig() (err error) { @@ -800,6 +873,7 @@ type ClientErrors struct { TransactionAlreadyMined *string `toml:",omitempty"` Fatal *string `toml:",omitempty"` ServiceUnavailable *string `toml:",omitempty"` + TooManyResults *string `toml:",omitempty"` } func (r *ClientErrors) setFrom(f *ClientErrors) bool { @@ -845,6 +919,9 @@ func (r *ClientErrors) setFrom(f *ClientErrors) bool { if v := f.ServiceUnavailable; v != nil { r.ServiceUnavailable = v } + if v := f.TooManyResults; v != nil { + r.TooManyResults = v + } return true } @@ -859,6 +936,7 @@ type NodePool struct { Errors ClientErrors `toml:",omitempty"` EnforceRepeatableRead *bool DeathDeclarationDelay *commonconfig.Duration + NewHeadsPollInterval *commonconfig.Duration } func (p *NodePool) setFrom(f *NodePool) { @@ -891,9 +969,28 @@ func (p *NodePool) setFrom(f *NodePool) { if v := f.DeathDeclarationDelay; v != nil { p.DeathDeclarationDelay = v } + + if v := f.NewHeadsPollInterval; v != nil { + p.NewHeadsPollInterval = v + } + p.Errors.setFrom(&f.Errors) } +func (p *NodePool) ValidateConfig(finalityTagEnabled *bool) (err error) { + if finalityTagEnabled != nil && *finalityTagEnabled { + if p.FinalizedBlockPollInterval == nil { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "FinalizedBlockPollInterval", Msg: "required when FinalityTagEnabled is true"}) + return + } + if p.FinalizedBlockPollInterval.Duration() <= 0 { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "FinalizedBlockPollInterval", Value: p.FinalizedBlockPollInterval, + Msg: "must be greater than 0"}) + } + } + return +} + type OCR struct { ContractConfirmations *uint16 ContractTransmitterTransmitTimeout *commonconfig.Duration @@ -939,19 +1036,8 @@ func (n *Node) ValidateConfig() (err error) { err = multierr.Append(err, commonconfig.ErrEmpty{Name: "Name", Msg: "required for all nodes"}) } - var sendOnly bool - if n.SendOnly != nil { - sendOnly = *n.SendOnly - } - if n.WSURL == nil { - if !sendOnly { - err = multierr.Append(err, commonconfig.ErrMissing{Name: "WSURL", Msg: "required for primary nodes"}) - } - } else if n.WSURL.IsZero() { - if !sendOnly { - err = multierr.Append(err, commonconfig.ErrEmpty{Name: "WSURL", Msg: "required for primary nodes"}) - } - } else { + // relax the check here as WSURL can potentially be empty if LogBroadcaster is disabled (checked in EVMConfig Validation) + if n.WSURL != nil && !n.WSURL.IsZero() { switch n.WSURL.Scheme { case "ws", "wss": default: diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index c3f087da8c5..0885d94e6df 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -3,7 +3,10 @@ package toml import ( "bytes" "embed" + "fmt" + "io" "log" + "os" "path/filepath" "slices" "strings" @@ -12,37 +15,43 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/config/env" ) var ( + //go:embed defaults/*.toml defaultsFS embed.FS fallback Chain defaults = map[string]Chain{} defaultNames = map[string]string{} + customDefaults = map[string]Chain{} + // DefaultIDs is the set of chain ids which have defaults. DefaultIDs []*big.Big ) func init() { + // read the defaults first + fes, err := defaultsFS.ReadDir("defaults") if err != nil { log.Fatalf("failed to read defaults/: %v", err) } for _, fe := range fes { path := filepath.Join("defaults", fe.Name()) - b, err := defaultsFS.ReadFile(path) - if err != nil { - log.Fatalf("failed to read %q: %v", path, err) + 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 err := cconfig.DecodeTOML(bytes.NewReader(b), &config); err != nil { - log.Fatalf("failed to decode %q: %v", path, err) + 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 { @@ -65,6 +74,63 @@ func init() { slices.SortFunc(DefaultIDs, func(a, b *big.Big) int { return a.Cmp(b) }) + + // read the custom defaults overrides + dir := env.CustomDefaults.Get() + if dir == "" { + // short-circuit; no default overrides provided + return + } + + // use evm overrides specifically + evmDir := fmt.Sprintf("%s/evm", dir) + + // Read directory contents for evm only + entries, err := os.ReadDir(evmDir) + if err != nil { + log.Fatalf("error reading evm custom defaults override directory: %v", err) + return + } + + 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 file contents + b, err := io.ReadAll(file) + file.Close() + if err != nil { + log.Fatalf("error reading file (name: %v) contents in custom defaults override directory: %v", entry.Name(), err) + } + + var config = struct { + ChainID *big.Big + Chain + }{} + + if err := cconfig.DecodeTOML(bytes.NewReader(b), &config); err != nil { + log.Fatalf("failed to decode %q in custom defaults override directory: %v", path, err) + } + + if config.ChainID == nil { + log.Fatalf("missing ChainID in: %s in custom defaults override directory. exiting", path) + } + + id := config.ChainID.String() + + if _, ok := customDefaults[id]; ok { + log.Fatalf("%q contains duplicate ChainID: %s", path, id) + } + customDefaults[id] = config.Chain + } } // DefaultsNamed returns the default Chain values, optionally for the given chainID, as well as a name if the chainID is known. @@ -78,6 +144,9 @@ func DefaultsNamed(chainID *big.Big) (c Chain, name string) { c.SetFrom(&d) name = defaultNames[s] } + if overrides, ok := customDefaults[s]; ok { + c.SetFrom(&overrides) + } return } @@ -155,6 +224,9 @@ func (c *Chain) SetFrom(f *Chain) { if v := f.OperatorFactoryAddress; v != nil { c.OperatorFactoryAddress = v } + if v := f.LogBroadcasterEnabled; v != nil { + c.LogBroadcasterEnabled = v + } if v := f.RPCDefaultBatchSize; v != nil { c.RPCDefaultBatchSize = v } diff --git a/core/chains/evm/config/toml/defaults/Arbitrum_Goerli.toml b/core/chains/evm/config/toml/defaults/Arbitrum_Goerli.toml index 42de6beb9ba..3d4b71347c4 100644 --- a/core/chains/evm/config/toml/defaults/Arbitrum_Goerli.toml +++ b/core/chains/evm/config/toml/defaults/Arbitrum_Goerli.toml @@ -19,6 +19,9 @@ BumpThreshold = 5 # Force an error if someone set GAS_UPDATER_ENABLED=true by accident; we never want to run the block history estimator on arbitrum BlockHistorySize = 0 +[GasEstimator.DAOracle] +OracleType = 'arbitrum' + [NodePool] SyncThreshold = 10 diff --git a/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml b/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml index b297db1bc0f..b81d53731fb 100644 --- a/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml @@ -1,6 +1,7 @@ # Arbitrum is an L2 chain. Pending proper L2 support, for now we rely on their sequencer ChainID = '42161' ChainType = 'arbitrum' +FinalityTagEnabled = true LinkContractAddress = "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4" LogPollInterval = '1s' # Arbitrum only emits blocks when a new tx is received, so this method of liveness detection is not useful @@ -21,6 +22,9 @@ BumpThreshold = 5 # Force an error if someone set GAS_UPDATER_ENABLED=true by accident; we never want to run the block history estimator on arbitrum BlockHistorySize = 0 +[GasEstimator.DAOracle] +OracleType = 'arbitrum' + [NodePool] SyncThreshold = 10 diff --git a/core/chains/evm/config/toml/defaults/Arbitrum_Rinkeby.toml b/core/chains/evm/config/toml/defaults/Arbitrum_Rinkeby.toml index f9296adcb76..68e28e7c5bc 100644 --- a/core/chains/evm/config/toml/defaults/Arbitrum_Rinkeby.toml +++ b/core/chains/evm/config/toml/defaults/Arbitrum_Rinkeby.toml @@ -19,5 +19,8 @@ BumpThreshold = 5 # Force an error if someone set GAS_UPDATER_ENABLED=true by accident; we never want to run the block history estimator on arbitrum BlockHistorySize = 0 +[GasEstimator.DAOracle] +OracleType = 'arbitrum' + [NodePool] SyncThreshold = 10 diff --git a/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml b/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml index e6d660a2729..ab5351b9a74 100644 --- a/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml @@ -1,5 +1,6 @@ ChainID = '421614' ChainType = 'arbitrum' +FinalityTagEnabled = true NoNewHeadsThreshold = '0' OCR.ContractConfirmations = 1 LogPollInterval = '1s' @@ -18,6 +19,9 @@ BumpThreshold = 5 # Force an error if someone set GAS_UPDATER_ENABLED=true by accident; we never want to run the block history estimator on arbitrum BlockHistorySize = 0 +[GasEstimator.DAOracle] +OracleType = 'arbitrum' + [NodePool] SyncThreshold = 10 diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml index 882a91f1acc..6e95be2c7f7 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml @@ -1,5 +1,6 @@ ChainID = '43113' FinalityDepth = 10 +FinalityTagEnabled = true LinkContractAddress = '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846' LogPollInterval = '3s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml index 78d3bbba77a..930f9a910f6 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml @@ -1,5 +1,6 @@ ChainID = '43114' FinalityDepth = 10 +FinalityTagEnabled = true LinkContractAddress = '0x5947BB275c521040051D82396192181b413227A3' LogPollInterval = '3s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml b/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml index 1b248a8c451..b3cf458ad87 100644 --- a/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml @@ -2,6 +2,7 @@ # Clique offers finality within (N/2)+1 blocks where N is number of signers # There are 21 BSC validators so theoretically finality should occur after 21/2+1 = 11 blocks ChainID = '56' +FinalityTagEnabled = true LinkContractAddress = '0x404460C6A5EdE2D891e8297795264fDe62ADBB75' LogPollInterval = '3s' NoNewHeadsThreshold = '30s' @@ -10,6 +11,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 diff --git a/core/chains/evm/config/toml/defaults/BSC_Testnet.toml b/core/chains/evm/config/toml/defaults/BSC_Testnet.toml index 252f90accdd..7b8fc481d7b 100644 --- a/core/chains/evm/config/toml/defaults/BSC_Testnet.toml +++ b/core/chains/evm/config/toml/defaults/BSC_Testnet.toml @@ -2,6 +2,7 @@ # Clique offers finality within (N/2)+1 blocks where N is number of signers # There are 21 BSC validators so theoretically finality should occur after 21/2+1 = 11 blocks ChainID = '97' +FinalityTagEnabled = true LinkContractAddress = '0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06' LogPollInterval = '3s' NoNewHeadsThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Base_Goerli.toml b/core/chains/evm/config/toml/defaults/Base_Goerli.toml index 5ecfd036f46..2dd4f4033c6 100644 --- a/core/chains/evm/config/toml/defaults/Base_Goerli.toml +++ b/core/chains/evm/config/toml/defaults/Base_Goerli.toml @@ -13,6 +13,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 60 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Base_Mainnet.toml b/core/chains/evm/config/toml/defaults/Base_Mainnet.toml index f0896fba414..b683aff9840 100644 --- a/core/chains/evm/config/toml/defaults/Base_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Base_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '8453' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 @@ -14,6 +15,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 24 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Base_Sepolia.toml b/core/chains/evm/config/toml/defaults/Base_Sepolia.toml index 1fc0b51f1f3..3e6aee20e29 100644 --- a/core/chains/evm/config/toml/defaults/Base_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Base_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '84532' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 @@ -14,6 +15,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 60 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml b/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml index 20bb0d8e72a..984150c694d 100644 --- a/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml @@ -1,4 +1,5 @@ ChainID = '1' +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' MinContractPayment = '0.1 link' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' diff --git a/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml b/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml index 1c46d4ca7cf..403ecd7c4b1 100644 --- a/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml @@ -1,4 +1,5 @@ ChainID = '11155111' +FinalityTagEnabled = true LinkContractAddress = '0x779877A7B0D9E8603169DdbD7836e478b4624789' MinContractPayment = '0.1 link' diff --git a/core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml b/core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml new file mode 100644 index 00000000000..7f15a8cf13d --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml @@ -0,0 +1,33 @@ +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 +# Dynamic gas estimation is a must Hedera, since Hedera consumes 80% of gaslimit by default, we will end up overpaying for gas +EstimateLimit = true + +[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 \ No newline at end of file diff --git a/core/chains/evm/config/toml/defaults/Hedera_Testnet.toml b/core/chains/evm/config/toml/defaults/Hedera_Testnet.toml new file mode 100644 index 00000000000..e15b4e98d69 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Hedera_Testnet.toml @@ -0,0 +1,33 @@ +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 +# Dynamic gas estimation is a must Hedera, since Hedera consumes 80% of gaslimit by default, we will end up overpaying for gas +EstimateLimit = true + +[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 \ No newline at end of file diff --git a/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml b/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml index 55154bf766c..327c8b0975c 100644 --- a/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '255' ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture FinalityDepth = 400 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 @@ -13,6 +14,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 24 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x4200000000000000000000000000000000000005' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml b/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml index 643b0556b32..da0dc36541c 100644 --- a/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '2358' ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture FinalityDepth = 400 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 @@ -13,6 +14,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 24 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x4200000000000000000000000000000000000005' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/L3X_Mainnet.toml b/core/chains/evm/config/toml/defaults/L3X_Mainnet.toml index 1fbda42fd2a..9dd33c9e15d 100644 --- a/core/chains/evm/config/toml/defaults/L3X_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/L3X_Mainnet.toml @@ -16,3 +16,6 @@ PriceMin = '0' PriceDefault = '0.1 gwei' FeeCapDefault = '1000 gwei' BumpThreshold = 5 + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' diff --git a/core/chains/evm/config/toml/defaults/L3X_Sepolia.toml b/core/chains/evm/config/toml/defaults/L3X_Sepolia.toml index ee515bb72ba..c0f6a60e943 100644 --- a/core/chains/evm/config/toml/defaults/L3X_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/L3X_Sepolia.toml @@ -16,3 +16,6 @@ PriceMin = '0' PriceDefault = '0.1 gwei' FeeCapDefault = '1000 gwei' BumpThreshold = 5 + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' diff --git a/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml b/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml index cfc79f978f5..f057400d014 100644 --- a/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml @@ -3,6 +3,7 @@ ChainID = '1088' ChainType = 'metis' # Sequencer offers absolute finality FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 NoNewHeadsThreshold = '0' OCR.ContractConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml b/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml index 4e6307302f5..286b888e1a8 100644 --- a/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '59902' ChainType = 'metis' FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 NoNewHeadsThreshold = '0' OCR.ContractConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Optimism_Goerli.toml b/core/chains/evm/config/toml/defaults/Optimism_Goerli.toml index 458b3b08123..76c976a9114 100644 --- a/core/chains/evm/config/toml/defaults/Optimism_Goerli.toml +++ b/core/chains/evm/config/toml/defaults/Optimism_Goerli.toml @@ -14,6 +14,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 60 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml b/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml index 3510aef7047..cd09ad4a60f 100644 --- a/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '10' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LinkContractAddress = '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6' LogPollInterval = '2s' NoNewHeadsThreshold = '40s' @@ -15,6 +16,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 24 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml b/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml index 8da575a5936..ff367df0feb 100644 --- a/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '11155420' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 @@ -14,6 +15,10 @@ BumpMin = '100 wei' [GasEstimator.BlockHistory] BlockHistorySize = 60 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + [Transactions] ResendAfterThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml b/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml index 2a520563302..bf605cab3c6 100644 --- a/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml @@ -2,6 +2,7 @@ ChainID = '137' # It is quite common to see re-orgs on polygon go several hundred blocks deep. See: https://polygonscan.com/blocks_forked FinalityDepth = 500 +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogPollInterval = '1s' MinIncomingConfirmations = 5 diff --git a/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml b/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml index cd91465dae6..46ce80e29fc 100644 --- a/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml +++ b/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml @@ -13,12 +13,14 @@ 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 diff --git a/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml b/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml index 79e0cb0fce5..2fef7874d17 100644 --- a/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml @@ -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/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml b/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml index 4a887b504df..5a5e0459512 100644 --- a/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Scroll_Mainnet.toml @@ -15,6 +15,10 @@ BumpMin = '1 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x5300000000000000000000000000000000000002' + [HeadTracker] HistoryDepth = 50 diff --git a/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml b/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml index b2e1cfbd733..a9c6a979e64 100644 --- a/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Scroll_Sepolia.toml @@ -15,6 +15,10 @@ BumpMin = '1 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x5300000000000000000000000000000000000002' + [HeadTracker] HistoryDepth = 50 diff --git a/core/chains/evm/config/toml/defaults/Soneium_Sepolia.toml b/core/chains/evm/config/toml/defaults/Soneium_Sepolia.toml new file mode 100755 index 00000000000..7ab92f04e5b --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Soneium_Sepolia.toml @@ -0,0 +1,36 @@ +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 + +[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/WeMix_Mainnet.toml b/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml index 7fcbd18890b..4a55450e47e 100644 --- a/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '1111' ChainType = 'wemix' FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 # WeMix emits a block every 1 second, regardless of transactions LogPollInterval = '3s' diff --git a/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml b/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml index 83c483d0348..d4f829bcfd1 100644 --- a/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml +++ b/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml @@ -1,6 +1,7 @@ ChainID = '1112' ChainType = 'wemix' FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 # WeMix emits a block every 1 second, regardless of transactions LogPollInterval = '3s' diff --git a/core/chains/evm/config/toml/defaults/Zircuit_Mainnet.toml b/core/chains/evm/config/toml/defaults/Zircuit_Mainnet.toml new file mode 100644 index 00000000000..b2c1411726d --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Zircuit_Mainnet.toml @@ -0,0 +1,40 @@ +ChainID = '48900' +ChainType = 'zircuit' +FinalityTagEnabled = true +FinalityDepth = 1000 +LinkContractAddress = '0x5D6d033B4FbD2190D99D930719fAbAcB64d2439a' +LogPollInterval = "2s" +NoNewHeadsThreshold = "40s" +NoNewFinalizedHeadsThreshold = "15m" + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 24 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 2000 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 + +[Transactions.AutoPurge] +Enabled = true +Threshold = 90 # 90 blocks at 2s block time ~3 minutes +MinAttempts = 3 \ No newline at end of file diff --git a/core/chains/evm/config/toml/defaults/Zircuit_Sepolia.toml b/core/chains/evm/config/toml/defaults/Zircuit_Sepolia.toml new file mode 100644 index 00000000000..3a82bb9623d --- /dev/null +++ b/core/chains/evm/config/toml/defaults/Zircuit_Sepolia.toml @@ -0,0 +1,40 @@ +ChainID = '48899' +ChainType = 'zircuit' +FinalityTagEnabled = true +FinalityDepth = 1000 +LinkContractAddress = '0xDEE94506570cA186BC1e3516fCf4fd719C312cCD' +LogPollInterval = "2s" +NoNewHeadsThreshold = "40s" +NoNewFinalizedHeadsThreshold = "15m" + +[GasEstimator] +EIP1559DynamicFees = true +PriceMin = '1 wei' +BumpMin = '100 wei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 60 + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' + +[Transactions] +ResendAfterThreshold = '30s' + +[HeadTracker] +HistoryDepth = 2000 + +[NodePool] +SyncThreshold = 10 + +[OCR] +ContractConfirmations = 1 + +[OCR2.Automation] +GasLimit = 6500000 + +[Transactions.AutoPurge] +Enabled = true +Threshold = 90 # 90 blocks at 2s block time ~3 minutes +MinAttempts = 3 \ No newline at end of file diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index a47e56bc918..1e18f4a4ebf 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -16,6 +16,7 @@ RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0' +LogBroadcasterEnabled = true [Transactions] ForwardersEnabled = false @@ -47,6 +48,7 @@ EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1' TipCapMin = '1' +EstimateLimit = false [GasEstimator.BlockHistory] BatchSize = 25 @@ -55,12 +57,16 @@ 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 @@ -72,6 +78,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -83,3 +90,6 @@ ObservationGracePeriod = '1s' [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400_000 diff --git a/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml b/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml index 05d85cfe248..035eec62d49 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Goerli.toml @@ -10,5 +10,8 @@ LimitDefault = 100_000_000 PriceMax = 18446744073709551615 PriceMin = 0 +[GasEstimator.DAOracle] +OracleType = 'zksync' + [HeadTracker] HistoryDepth = 50 diff --git a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml index 02ce2b0f18c..d4602a85479 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml @@ -10,5 +10,8 @@ LimitDefault = 100_000_000 PriceMax = 18446744073709551615 PriceMin = 0 +[GasEstimator.DAOracle] +OracleType = 'zksync' + [HeadTracker] HistoryDepth = 50 diff --git a/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml b/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml index b4e957a6c99..4ea175bfdb8 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml @@ -10,5 +10,8 @@ LimitDefault = 100_000_000 PriceMax = 18446744073709551615 PriceMin = 0 +[GasEstimator.DAOracle] +OracleType = 'zksync' + [HeadTracker] HistoryDepth = 50 diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go index 6436988ba82..0e9f8781c35 100644 --- a/core/chains/evm/forwarders/forwarder_manager.go +++ b/core/chains/evm/forwarders/forwarder_manager.go @@ -33,7 +33,9 @@ type Config interface { } type FwdMgr struct { - services.StateMachine + services.Service + eng *services.Engine + ORM ORM evmClient evmclient.Client cfg Config @@ -48,61 +50,51 @@ type FwdMgr struct { authRcvr authorized_receiver.AuthorizedReceiverInterface offchainAgg offchain_aggregator_wrapper.OffchainAggregatorInterface - stopCh services.StopChan - cacheMu sync.RWMutex - wg sync.WaitGroup } -func NewFwdMgr(ds sqlutil.DataSource, client evmclient.Client, logpoller evmlogpoller.LogPoller, l logger.Logger, cfg Config) *FwdMgr { - lggr := logger.Sugared(logger.Named(l, "EVMForwarderManager")) - fwdMgr := FwdMgr{ - logger: lggr, +func NewFwdMgr(ds sqlutil.DataSource, client evmclient.Client, logpoller evmlogpoller.LogPoller, lggr logger.Logger, cfg Config) *FwdMgr { + fm := FwdMgr{ cfg: cfg, evmClient: client, ORM: NewORM(ds), logpoller: logpoller, sendersCache: make(map[common.Address][]common.Address), } - fwdMgr.stopCh = make(chan struct{}) - return &fwdMgr -} - -func (f *FwdMgr) Name() string { - return f.logger.Name() + fm.Service, fm.eng = services.Config{ + Name: "ForwarderManager", + Start: fm.start, + }.NewServiceEngine(lggr) + fm.logger = logger.Sugared(fm.eng) + return &fm } -// Start starts Forwarder Manager. -func (f *FwdMgr) Start(ctx context.Context) error { - return f.StartOnce("EVMForwarderManager", func() error { - f.logger.Debug("Initializing EVM forwarder manager") - chainId := f.evmClient.ConfiguredChainID() +func (f *FwdMgr) start(ctx context.Context) error { + chainId := f.evmClient.ConfiguredChainID() - fwdrs, err := f.ORM.FindForwardersByChain(ctx, big.Big(*chainId)) - if err != nil { - return pkgerrors.Wrapf(err, "Failed to retrieve forwarders for chain %d", chainId) - } - if len(fwdrs) != 0 { - f.initForwardersCache(ctx, fwdrs) - if err = f.subscribeForwardersLogs(ctx, fwdrs); err != nil { - return err - } + fwdrs, err := f.ORM.FindForwardersByChain(ctx, big.Big(*chainId)) + if err != nil { + return pkgerrors.Wrapf(err, "Failed to retrieve forwarders for chain %d", chainId) + } + if len(fwdrs) != 0 { + f.initForwardersCache(ctx, fwdrs) + if err = f.subscribeForwardersLogs(ctx, fwdrs); err != nil { + return err } + } - f.authRcvr, err = authorized_receiver.NewAuthorizedReceiver(common.Address{}, f.evmClient) - if err != nil { - return pkgerrors.Wrap(err, "Failed to init AuthorizedReceiver") - } + f.authRcvr, err = authorized_receiver.NewAuthorizedReceiver(common.Address{}, f.evmClient) + if err != nil { + return pkgerrors.Wrap(err, "Failed to init AuthorizedReceiver") + } - f.offchainAgg, err = offchain_aggregator_wrapper.NewOffchainAggregator(common.Address{}, f.evmClient) - if err != nil { - return pkgerrors.Wrap(err, "Failed to init OffchainAggregator") - } + f.offchainAgg, err = offchain_aggregator_wrapper.NewOffchainAggregator(common.Address{}, f.evmClient) + if err != nil { + return pkgerrors.Wrap(err, "Failed to init OffchainAggregator") + } - f.wg.Add(1) - go f.runLoop() - return nil - }) + f.eng.Go(f.runLoop) + return nil } func FilterName(addr common.Address) string { @@ -176,7 +168,7 @@ func (f *FwdMgr) ConvertPayload(dest common.Address, origPayload []byte) ([]byte if err != nil { f.logger.AssumptionViolationw("Forwarder encoding failed, this should never happen", "err", err, "to", dest, "payload", origPayload) - f.SvcErrBuffer.Append(err) + f.eng.EmitHealthErr(err) } } return databytes, nil @@ -269,11 +261,7 @@ func (f *FwdMgr) getCachedSenders(addr common.Address) ([]common.Address, bool) return addrs, ok } -func (f *FwdMgr) runLoop() { - defer f.wg.Done() - ctx, cancel := f.stopCh.NewCtx() - defer cancel() - +func (f *FwdMgr) runLoop(ctx context.Context) { ticker := services.NewTicker(time.Minute) defer ticker.Stop() @@ -353,16 +341,3 @@ func (f *FwdMgr) collectAddresses() (addrs []common.Address) { } return } - -// Stop cancels all outgoings calls and stops internal ticker loop. -func (f *FwdMgr) Close() error { - return f.StopOnce("EVMForwarderManager", func() (err error) { - close(f.stopCh) - f.wg.Wait() - return nil - }) -} - -func (f *FwdMgr) HealthReport() map[string]error { - return map[string]error{f.Name(): f.Healthy()} -} diff --git a/core/chains/evm/gas/arbitrum_estimator_test.go b/core/chains/evm/gas/arbitrum_estimator_test.go index cbc6d5d37f4..b1e7efc887e 100644 --- a/core/chains/evm/gas/arbitrum_estimator_test.go +++ b/core/chains/evm/gas/arbitrum_estimator_test.go @@ -195,8 +195,8 @@ func TestArbitrumEstimator(t *testing.T) { o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) fee := gas.DynamicFee{ - FeeCap: assets.NewWeiI(42), - TipCap: assets.NewWeiI(5), + GasFeeCap: assets.NewWeiI(42), + GasTipCap: assets.NewWeiI(5), } _, err = o.BumpDynamicFee(tests.Context(t), fee, maxGasPrice, nil) assert.EqualError(t, err, "dynamic fees are not implemented for this estimator") diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 4075b46f901..12e2d915ee2 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -23,6 +24,7 @@ import ( commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -76,10 +78,6 @@ const BumpingHaltedLabel = "Tx gas bumping halted since price exceeds current bl var _ EvmEstimator = &BlockHistoryEstimator{} -type chainConfig interface { - ChainType() chaintype.ChainType -} - type estimatorGasEstimatorConfig interface { EIP1559DynamicFees() bool BumpThreshold() uint64 @@ -95,9 +93,9 @@ type BlockHistoryEstimator struct { services.StateMachine ethClient feeEstimatorClient chainID *big.Int - config chainConfig + chaintype chaintype.ChainType eConfig estimatorGasEstimatorConfig - bhConfig BlockHistoryConfig + bhConfig evmconfig.BlockHistory // NOTE: it is assumed that blocks will be kept sorted by // block number ascending blocks []evmtypes.Block @@ -125,11 +123,11 @@ type BlockHistoryEstimator struct { // NewBlockHistoryEstimator returns a new BlockHistoryEstimator that listens // for new heads and updates the base gas price dynamically based on the // configured percentile of gas prices in that block -func NewBlockHistoryEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg chainConfig, eCfg estimatorGasEstimatorConfig, bhCfg BlockHistoryConfig, chainID *big.Int, l1Oracle rollups.L1Oracle) EvmEstimator { +func NewBlockHistoryEstimator(lggr logger.Logger, ethClient feeEstimatorClient, chaintype chaintype.ChainType, eCfg estimatorGasEstimatorConfig, bhCfg evmconfig.BlockHistory, chainID *big.Int, l1Oracle rollups.L1Oracle) EvmEstimator { return &BlockHistoryEstimator{ ethClient: ethClient, chainID: chainID, - config: cfg, + chaintype: chaintype, eConfig: eCfg, bhConfig: bhCfg, blocks: make([]evmtypes.Block, 0), @@ -276,6 +274,8 @@ func (b *BlockHistoryEstimator) setMaxPercentileGasPrice(gasPrice *assets.Wei) { } func (b *BlockHistoryEstimator) getBlockHistoryNumbers() (numsInHistory []int64) { + b.blocksMu.RLock() + defer b.blocksMu.RUnlock() for _, b := range b.blocks { numsInHistory = append(numsInHistory, b.Number) } @@ -338,9 +338,9 @@ func (b *BlockHistoryEstimator) haltBumping(attempts []EvmPriorAttempt) error { } // Return error to prevent bumping if gas price is nil or if EIP1559 is enabled and tip cap is nil if maxGasPrice == nil || (b.eConfig.EIP1559DynamicFees() && maxTipCap == nil) { - errorMsg := fmt.Sprintf("%d percentile price is not set. This is likely because there aren't any valid transactions to estimate from. Preventing bumping until valid price is available to compare", percentile) - b.logger.Debugf(errorMsg) - return errors.New(errorMsg) + err := fmt.Errorf("%d percentile price is not set. This is likely because there aren't any valid transactions to estimate from. Preventing bumping until valid price is available to compare", percentile) + b.logger.Debugw("Bumping halted", "err", err) + return err } // Get the latest CheckInclusionBlocks from block history for fee cap check below blockHistory := b.getBlocks() @@ -374,15 +374,15 @@ func (b *BlockHistoryEstimator) haltBumping(attempts []EvmPriorAttempt) error { // feecap must >= tipcap+basefee for the block, otherwise there // is no way this could have been included, and we must bail // out of the check - attemptFeeCap := attempt.DynamicFee.FeeCap - attemptTipCap := attempt.DynamicFee.TipCap + attemptFeeCap := attempt.DynamicFee.GasFeeCap + attemptTipCap := attempt.DynamicFee.GasTipCap if attemptFeeCap.Cmp(attemptTipCap.Add(b.BaseFeePerGas)) < 0 { sufficientFeeCap = false break } } - if sufficientFeeCap && attempt.DynamicFee.TipCap.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.TipCap, percentile, maxTipCap, commonfee.ErrConnectivity) + 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 nil @@ -408,7 +408,8 @@ func (b *BlockHistoryEstimator) GetDynamicFee(_ context.Context, maxGasPriceWei "Using Evm.GasEstimator.TipCapDefault as fallback.", "blocks", b.getBlockHistoryNumbers()) tipCap = b.eConfig.TipCapDefault() } - maxGasPrice := getMaxGasPrice(maxGasPriceWei, b.eConfig.PriceMax()) + maxGasPrice := assets.WeiMin(maxGasPriceWei, b.eConfig.PriceMax()) + tipCap = assets.WeiMin(tipCap, maxGasPrice) if b.eConfig.BumpThreshold() == 0 { // just use the max gas price if gas bumping is disabled feeCap = maxGasPrice @@ -432,8 +433,8 @@ func (b *BlockHistoryEstimator) GetDynamicFee(_ context.Context, maxGasPriceWei if err != nil { return fee, err } - fee.FeeCap = feeCap - fee.TipCap = tipCap + fee.GasFeeCap = feeCap + fee.GasTipCap = tipCap return } @@ -653,12 +654,13 @@ func (b *BlockHistoryEstimator) FetchBlocks(ctx context.Context, head *evmtypes. } blocks := make(map[int64]evmtypes.Block) + earliestInChain := head.EarliestInChain() for _, block := range b.getBlocks() { // Make a best-effort to be re-org resistant using the head // chain, refetch blocks that got re-org'd out. // NOTE: Any blocks in the history that are older than the oldest block // in the provided chain will be assumed final. - if block.Number < head.EarliestInChain().BlockNumber() { + if block.Number < earliestInChain.BlockNumber() { blocks[block.Number] = block } else if head.IsInChain(block.Hash) { blocks[block.Number] = block @@ -824,7 +826,7 @@ func (b *BlockHistoryEstimator) getPricesFromBlocks(blocks []evmtypes.Block, eip b.logger.Warnw(fmt.Sprintf("Block %v is not usable, %s", block.Number, err.Error()), "block", block, "err", err) } for _, tx := range block.Transactions { - if b.IsUsable(tx, block, b.config.ChainType(), b.eConfig.PriceMin(), b.logger) { + if b.IsUsable(tx, block, b.chaintype, b.eConfig.PriceMin(), b.logger) { gp := b.EffectiveGasPrice(block, tx) if gp == nil { b.logger.Warnw("Unable to get gas price for tx", "tx", tx, "block", block) @@ -973,3 +975,29 @@ func (b *BlockHistoryEstimator) EffectiveTipCap(block evmtypes.Block, tx evmtype return nil } } + +// Int64ToHex formats an int64 as a hex string with 0x prefix. +func Int64ToHex(n int64) string { + return fmt.Sprintf("0x%x", n) +} + +// HexToInt64 performs the inverse of Int64ToHex +// Returns 0 on invalid input +func HexToInt64(input interface{}) int64 { + switch v := input.(type) { + case string: + big, err := hexutil.DecodeBig(v) + if err != nil { + return 0 + } + return big.Int64() + case []byte: + big, err := hexutil.DecodeBig(string(v)) + if err != nil { + return 0 + } + return big.Int64() + default: + return 0 + } +} diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index c2f4a2219cb..de698fc9a08 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -25,6 +25,7 @@ import ( "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" + 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/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" @@ -35,6 +36,8 @@ import ( ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) +const defaultChainType chaintype.ChainType = "" + func NewEvmHash() common.Hash { return utils.NewHash() } @@ -45,19 +48,18 @@ func newBlockHistoryConfig() *gas.MockBlockHistoryConfig { return c } -func newBlockHistoryEstimatorWithChainID(t *testing.T, c evmclient.Client, cfg gas.Config, gCfg gas.GasEstimatorConfig, bhCfg gas.BlockHistoryConfig, cid *big.Int, l1Oracle rollups.L1Oracle) gas.EvmEstimator { - return gas.NewBlockHistoryEstimator(logger.Test(t), c, cfg, gCfg, bhCfg, cid, l1Oracle) +func newBlockHistoryEstimatorWithChainID(t *testing.T, c evmclient.Client, chaintype chaintype.ChainType, gCfg gas.GasEstimatorConfig, bhCfg evmconfig.BlockHistory, cid *big.Int, l1Oracle rollups.L1Oracle) gas.EvmEstimator { + return gas.NewBlockHistoryEstimator(logger.Test(t), c, chaintype, gCfg, bhCfg, cid, l1Oracle) } -func newBlockHistoryEstimator(t *testing.T, c evmclient.Client, cfg gas.Config, gCfg gas.GasEstimatorConfig, bhCfg gas.BlockHistoryConfig, l1Oracle rollups.L1Oracle) *gas.BlockHistoryEstimator { - iface := newBlockHistoryEstimatorWithChainID(t, c, cfg, gCfg, bhCfg, testutils.FixtureChainID, l1Oracle) +func newBlockHistoryEstimator(t *testing.T, c evmclient.Client, chaintype chaintype.ChainType, gCfg gas.GasEstimatorConfig, bhCfg evmconfig.BlockHistory, l1Oracle rollups.L1Oracle) *gas.BlockHistoryEstimator { + iface := newBlockHistoryEstimatorWithChainID(t, c, chaintype, gCfg, bhCfg, testutils.FixtureChainID, l1Oracle) return gas.BlockHistoryEstimatorFromInterface(iface) } func TestBlockHistoryEstimator_Start(t *testing.T) { t.Parallel() - cfg := gas.NewMockConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true @@ -82,7 +84,7 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -123,11 +125,10 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { bhCfg2.BlockHistorySizeF = historySize bhCfg2.TransactionPercentileF = percentile - cfg2 := gas.NewMockConfig() ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg2, geCfg2, bhCfg2, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg2, bhCfg2, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -161,7 +162,7 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -180,7 +181,7 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, pkgerrors.New("something exploded")) @@ -202,7 +203,7 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -226,7 +227,7 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -243,7 +244,7 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -267,13 +268,12 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { } func TestBlockHistoryEstimator_OnNewLongestChain(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, nil, defaultChainType, geCfg, bhCfg, l1Oracle) assert.Nil(t, gas.GetLatestBaseFee(bhe)) @@ -297,8 +297,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() - bhCfg := newBlockHistoryConfig() var blockDelay uint16 = 3 var historySize uint16 @@ -308,7 +306,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) head := testutils.Head(42) err := bhe.FetchBlocks(tests.Context(t), head) @@ -320,7 +318,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 = 3 var historySize uint16 = 1 @@ -330,7 +327,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) for i := -1; i < 3; i++ { head := testutils.Head(i) @@ -344,7 +341,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 = 3 var historySize uint16 = 3 @@ -355,7 +351,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) ethClient.On("BatchCallContext", mock.Anything, mock.Anything).Return(pkgerrors.New("something exploded")) @@ -368,7 +364,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 var historySize uint16 = 3 @@ -381,7 +376,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b41 := evmtypes.Block{ Number: 41, @@ -464,7 +459,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 var historySize uint16 = 3 @@ -476,7 +470,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -515,7 +509,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { head2 := evmtypes.NewHead(big.NewInt(2), b2.Hash, b1.Hash, uint64(time.Now().Unix()), ubig.New(testutils.FixtureChainID)) head3 := evmtypes.NewHead(big.NewInt(3), b3.Hash, b2.Hash, uint64(time.Now().Unix()), ubig.New(testutils.FixtureChainID)) - head3.Parent = &head2 + head3.Parent.Store(&head2) err := bhe.FetchBlocks(tests.Context(t), &head3) require.NoError(t, err) @@ -529,7 +523,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 var historySize uint16 = 3 @@ -541,7 +534,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -570,7 +563,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { // RE-ORG, head2 and head3 have different hash than saved b2 and b3 head2 := evmtypes.NewHead(big.NewInt(2), utils.NewHash(), b1.Hash, uint64(time.Now().Unix()), ubig.New(testutils.FixtureChainID)) head3 := evmtypes.NewHead(big.NewInt(3), utils.NewHash(), head2.Hash, uint64(time.Now().Unix()), ubig.New(testutils.FixtureChainID)) - head3.Parent = &head2 + head3.Parent.Store(&head2) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && @@ -602,7 +595,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() var blockDelay uint16 var historySize uint16 = 3 var batchSize uint32 = 2 @@ -614,7 +606,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -643,7 +635,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { // head2 and head3 have identical hash to saved blocks head2 := evmtypes.NewHead(big.NewInt(2), b2.Hash, b1.Hash, uint64(time.Now().Unix()), ubig.New(testutils.FixtureChainID)) head3 := evmtypes.NewHead(big.NewInt(3), b3.Hash, head2.Hash, uint64(time.Now().Unix()), ubig.New(testutils.FixtureChainID)) - head3.Parent = &head2 + head3.Parent.Store(&head2) err := bhe.FetchBlocks(tests.Context(t), &head3) require.NoError(t, err) @@ -661,7 +653,6 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() var blockDelay uint16 var historySize uint16 = 1 var batchSize uint32 = 2 @@ -675,7 +666,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b42 := evmtypes.Block{ Number: 42, @@ -715,7 +706,6 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_NoEIP1559(t *testing.T) ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BlockDelayF = uint16(0) bhCfg.TransactionPercentileF = uint16(35) @@ -730,7 +720,7 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_NoEIP1559(t *testing.T) geCfg.PriceMaxF = assets.NewWeiI(1000) geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -788,7 +778,6 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BlockDelayF = uint16(0) bhCfg.TransactionPercentileF = uint16(50) @@ -804,7 +793,7 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ BaseFeePerGas: assets.NewWeiI(1), @@ -855,7 +844,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -863,7 +851,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{} gas.SetRollingBlockHistory(bhe, blocks) @@ -882,7 +870,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -892,7 +879,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = minGasPrice - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -919,7 +906,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -929,7 +915,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = minGasPrice - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -956,7 +942,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(100) @@ -966,7 +951,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = minGasPrice - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() b2Hash := utils.NewHash() @@ -1005,8 +990,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() - bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(50) @@ -1015,7 +998,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1040,8 +1023,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := evmmocks.NewClient(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() - bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(50) @@ -1050,7 +1031,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(11) // Has to be set as Gnosis will only ignore transactions below this price - ibhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + ibhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) bhe := gas.BlockHistoryEstimatorFromInterface(ibhe) b1Hash := utils.NewHash() @@ -1070,12 +1051,16 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { require.Equal(t, assets.NewWeiI(11), gas.GetGasPrice(bhe)) // Set chainType to Gnosis - GasEstimator should now ignore zero priced transactions - cfg.ChainTypeF = string(chaintype.ChainGnosis) + ibhe = newBlockHistoryEstimator(t, ethClient, chaintype.ChainGnosis, geCfg, bhCfg, l1Oracle) + bhe = gas.BlockHistoryEstimatorFromInterface(ibhe) + gas.SetRollingBlockHistory(bhe, blocks) bhe.Recalculate(testutils.Head(0)) require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe)) // And for X Layer - cfg.ChainTypeF = string(chaintype.ChainXLayer) + ibhe = newBlockHistoryEstimator(t, ethClient, chaintype.ChainXLayer, geCfg, bhCfg, l1Oracle) + bhe = gas.BlockHistoryEstimatorFromInterface(ibhe) + gas.SetRollingBlockHistory(bhe, blocks) bhe.Recalculate(testutils.Head(0)) require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe)) }) @@ -1086,7 +1071,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() reasonablyHugeGasPrice := assets.NewWeiI(1000).Mul(big.NewInt(math.MaxInt64)) @@ -1098,7 +1082,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = reasonablyHugeGasPrice geCfg.PriceMinF = assets.NewWeiI(10) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) unreasonablyHugeGasPrice := assets.NewWeiI(1000000).Mul(big.NewInt(math.MaxInt64)) @@ -1135,7 +1119,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(50) @@ -1145,7 +1128,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(100) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1183,7 +1166,6 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -1191,7 +1173,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{} gas.SetRollingBlockHistory(bhe, blocks) @@ -1222,7 +1204,6 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -1233,7 +1214,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -1262,7 +1243,6 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -1273,7 +1253,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(10) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -1302,7 +1282,6 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(95) @@ -1313,7 +1292,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(10) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() b2Hash := utils.NewHash() @@ -1352,7 +1331,6 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -1363,7 +1341,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(1) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1390,7 +1368,6 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -1401,7 +1378,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1428,12 +1405,11 @@ func TestBlockHistoryEstimator_IsUsable(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) block := evmtypes.Block{ Number: 0, Hash: utils.NewHash(), @@ -1442,78 +1418,67 @@ func TestBlockHistoryEstimator_IsUsable(t *testing.T) { } t.Run("returns false if transaction has 0 gas limit", func(t *testing.T) { tx := evmtypes.Transaction{Type: 0x0, GasPrice: assets.NewWeiI(10), GasLimit: 0, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction gas limit is nil and tx type is 0x0", func(t *testing.T) { tx := evmtypes.Transaction{Type: 0x0, GasPrice: nil, GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction is of type 0x7e only on Optimism", func(t *testing.T) { - cfg.ChainTypeF = "optimismBedrock" tx := evmtypes.Transaction{Type: 0x7e, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainOptimismBedrock, geCfg.PriceMin(), logger.Test(t))) - cfg.ChainTypeF = "" - assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction is of type 0x7c or 0x7b only on Celo", func(t *testing.T) { - cfg.ChainTypeF = "celo" tx := evmtypes.Transaction{Type: 0x7c, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainCelo, geCfg.PriceMin(), logger.Test(t))) tx2 := evmtypes.Transaction{Type: 0x7b, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx2, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx2, block, chaintype.ChainCelo, geCfg.PriceMin(), logger.Test(t))) - cfg.ChainTypeF = "" - assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) - assert.Equal(t, true, bhe.IsUsable(tx2, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx2, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction is of type 0x16 only on WeMix", func(t *testing.T) { - cfg.ChainTypeF = "wemix" tx := evmtypes.Transaction{Type: 0x16, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainWeMix, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction has base fee higher than the gas price only on Celo", func(t *testing.T) { - cfg.ChainTypeF = "celo" tx := evmtypes.Transaction{Type: 0x0, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainCelo, geCfg.PriceMin(), logger.Test(t))) tx2 := evmtypes.Transaction{Type: 0x2, MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasPrice: assets.NewWeiI(50), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainCelo, geCfg.PriceMin(), logger.Test(t))) - cfg.ChainTypeF = "" - assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) - assert.Equal(t, true, bhe.IsUsable(tx2, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx2, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction is of type 0x71 or 0xff only on zkSync", func(t *testing.T) { - cfg.ChainTypeF = string(chaintype.ChainZkSync) tx := evmtypes.Transaction{Type: 0x71, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainZkSync, geCfg.PriceMin(), logger.Test(t))) tx.Type = 0x02 - assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx, block, chaintype.ChainZkSync, geCfg.PriceMin(), logger.Test(t))) tx.Type = 0xff - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainZkSync, geCfg.PriceMin(), logger.Test(t))) - cfg.ChainTypeF = "" - assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) t.Run("returns false if transaction is of type 0x7e only on Scroll", func(t *testing.T) { - cfg.ChainTypeF = string(chaintype.ChainScroll) tx := evmtypes.Transaction{Type: 0x7e, GasPrice: assets.NewWeiI(10), GasLimit: 42, Hash: utils.NewHash()} - assert.Equal(t, false, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, false, bhe.IsUsable(tx, block, chaintype.ChainScroll, geCfg.PriceMin(), logger.Test(t))) - cfg.ChainTypeF = "" - assert.Equal(t, true, bhe.IsUsable(tx, block, cfg.ChainType(), geCfg.PriceMin(), logger.Test(t))) + assert.Equal(t, true, bhe.IsUsable(tx, block, defaultChainType, geCfg.PriceMin(), logger.Test(t))) }) } @@ -1521,13 +1486,12 @@ func TestBlockHistoryEstimator_EffectiveTipCap(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) block := evmtypes.Block{ Number: 0, @@ -1583,13 +1547,12 @@ func TestBlockHistoryEstimator_EffectiveGasPrice(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) block := evmtypes.Block{ Number: 0, @@ -1923,7 +1886,6 @@ func TestBlockHistoryEstimator_GetLegacyGas(t *testing.T) { t.Parallel() l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.TransactionPercentileF = uint16(35) @@ -1936,7 +1898,7 @@ func TestBlockHistoryEstimator_GetLegacyGas(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, nil, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -1973,14 +1935,12 @@ func TestBlockHistoryEstimator_GetLegacyGas(t *testing.T) { bhCfg.TransactionPercentileF = uint16(35) - cfg = gas.NewMockConfig() - geCfg.PriceMaxF = assets.NewWeiI(700) geCfg.PriceMinF = assets.NewWeiI(0) geCfg.EIP1559DynamicFeesF = false - bhe = newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe = newBlockHistoryEstimator(t, nil, defaultChainType, geCfg, bhCfg, l1Oracle) gas.SetRollingBlockHistory(bhe, blocks) bhe.Recalculate(testutils.Head(1)) gas.SimulateStart(t, bhe) @@ -2003,7 +1963,6 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { var specialTxTypeCode evmtypes.TxType = 0x7e t.Run("fallbacks to EvmGasPriceDefault if there aren't any valid transactions to estimate from.", func(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BatchSizeF = batchSize @@ -2019,7 +1978,7 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: nil} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -2055,7 +2014,6 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { }) t.Run("fallbacks to EvmGasTipCapDefault if there aren't any valid transactions to estimate from.", func(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BatchSizeF = batchSize bhCfg.TransactionPercentileF = uint16(35) @@ -2072,7 +2030,7 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(40)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -2103,14 +2061,13 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), assets.NewWeiI(200)) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(114), TipCap: geCfg.TipCapDefault()}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(114), GasTipCap: geCfg.TipCapDefault()}, fee) }) } func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { t.Parallel() - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() maxGasPrice := assets.NewWeiI(1000000) bhCfg.EIP1559FeeCapBufferBlocksF = uint16(4) @@ -2123,7 +2080,7 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, nil, defaultChainType, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -2157,7 +2114,7 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), maxGasPrice) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: maxGasPrice, TipCap: assets.NewWeiI(6000)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: maxGasPrice, GasTipCap: assets.NewWeiI(6000)}, fee) }) h := testutils.Head(1) @@ -2170,7 +2127,7 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), maxGasPrice) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(186203), TipCap: assets.NewWeiI(6000)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(186203), GasTipCap: assets.NewWeiI(6000)}, fee) }) t.Run("if gas bumping is disabled", func(t *testing.T) { @@ -2179,7 +2136,7 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), maxGasPrice) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: maxGasPrice, TipCap: assets.NewWeiI(6000)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: maxGasPrice, GasTipCap: assets.NewWeiI(6000)}, fee) }) t.Run("if gas bumping is enabled and local max gas price set", func(t *testing.T) { @@ -2188,7 +2145,7 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), assets.NewWeiI(180000)) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(180000), TipCap: assets.NewWeiI(6000)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(180000), GasTipCap: assets.NewWeiI(6000)}, fee) }) t.Run("if bump threshold is 0 and local max gas price set", func(t *testing.T) { @@ -2197,7 +2154,7 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), assets.NewWeiI(100)) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(6000)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(100)}, fee) }) h = testutils.Head(1) @@ -2210,12 +2167,11 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { fee, err := bhe.GetDynamicFee(tests.Context(t), assets.NewWeiI(1200000)) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(1000000), TipCap: assets.NewWeiI(6000)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(1000000), GasTipCap: assets.NewWeiI(6000)}, fee) }) } func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.CheckInclusionBlocksF = uint16(4) bhCfg.CheckInclusionPercentileF = uint16(90) @@ -2229,7 +2185,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { ctx := tests.Context(t) bhe := gas.BlockHistoryEstimatorFromInterface( - gas.NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), + gas.NewBlockHistoryEstimator(lggr, ethClient, defaultChainType, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), ) attempts := []gas.EvmPriorAttempt{ @@ -2372,7 +2328,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b0}) attempts = []gas.EvmPriorAttempt{ - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(1), TipCap: assets.NewWeiI(3)}, BroadcastBeforeBlockNum: ptr(int64(0))}, + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(1), GasTipCap: assets.NewWeiI(3)}, BroadcastBeforeBlockNum: ptr(int64(0))}, {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(10), BroadcastBeforeBlockNum: ptr(int64(0))}, } @@ -2396,7 +2352,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { }) attempts = []gas.EvmPriorAttempt{ - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(11), TipCap: assets.NewWeiI(10)}, BroadcastBeforeBlockNum: ptr(int64(0))}, + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(11), GasTipCap: assets.NewWeiI(10)}, BroadcastBeforeBlockNum: ptr(int64(0))}, {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(3), BroadcastBeforeBlockNum: ptr(int64(0))}, } @@ -2447,9 +2403,9 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { gas.SetRollingBlockHistory(bhe, blocks) attempts = []gas.EvmPriorAttempt{ - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(3)}, BroadcastBeforeBlockNum: ptr(int64(0))}, - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(5)}, BroadcastBeforeBlockNum: ptr(int64(1))}, - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(7)}, BroadcastBeforeBlockNum: ptr(int64(1))}, + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(30), GasTipCap: assets.NewWeiI(3)}, BroadcastBeforeBlockNum: ptr(int64(0))}, + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(30), GasTipCap: assets.NewWeiI(5)}, BroadcastBeforeBlockNum: ptr(int64(1))}, + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(30), GasTipCap: assets.NewWeiI(7)}, BroadcastBeforeBlockNum: ptr(int64(1))}, } t.Run("passes check if 90th percentile price higher than highest transaction tip cap", func(t *testing.T) { @@ -2487,7 +2443,7 @@ func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { bhe.Recalculate(testutils.Head(3)) attempts = []gas.EvmPriorAttempt{ - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(4), TipCap: assets.NewWeiI(7)}, BroadcastBeforeBlockNum: ptr(int64(1))}, + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(4), GasTipCap: assets.NewWeiI(7)}, BroadcastBeforeBlockNum: ptr(int64(1))}, } err := bhe.HaltBumping(attempts) @@ -2502,7 +2458,6 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { bhCfg := newBlockHistoryConfig() t.Run("BumpLegacyGas halts bumping", func(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg.BlockDelayF = 0 bhCfg.CheckInclusionBlocksF = 1 bhCfg.CheckInclusionPercentileF = 10 @@ -2517,7 +2472,7 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { ctx := tests.Context(t) bhe := gas.BlockHistoryEstimatorFromInterface( - gas.NewBlockHistoryEstimator(logger.Test(t), ethClient, cfg, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), + gas.NewBlockHistoryEstimator(logger.Test(t), ethClient, defaultChainType, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), ) b0 := evmtypes.Block{ @@ -2546,7 +2501,6 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { }) t.Run("BumpLegacyGas calls BumpLegacyGasPriceOnly with proper current gas price", func(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.CheckInclusionBlocksF = 0 geCfg := &gas.MockGasEstimatorConfig{} @@ -2559,7 +2513,7 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { ctx := tests.Context(t) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil).Once() - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) err := bhe.Start(ctx) require.NoError(t, err) @@ -2632,7 +2586,6 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { }) t.Run("BumpDynamicFee checks connectivity", func(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.CheckInclusionBlocksF = 1 bhCfg.CheckInclusionPercentileF = 10 @@ -2647,7 +2600,7 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ctx := tests.Context(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ BaseFeePerGas: assets.NewWeiI(1), @@ -2665,9 +2618,9 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { err := bhe.Start(ctx) require.NoError(t, err) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(25)} attempts := []gas.EvmPriorAttempt{ - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{TipCap: originalFee.TipCap, FeeCap: originalFee.FeeCap}, BroadcastBeforeBlockNum: ptr(int64(0))}} + {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{GasTipCap: originalFee.GasTipCap, GasFeeCap: originalFee.GasFeeCap}, BroadcastBeforeBlockNum: ptr(int64(0))}} _, err = bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, attempts) require.Error(t, err) @@ -2676,7 +2629,6 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { }) t.Run("BumpDynamicFee bumps the fee", func(t *testing.T) { - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} @@ -2689,50 +2641,50 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ctx := tests.Context(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil).Once() err := bhe.Start(ctx) require.NoError(t, err) t.Run("when current tip cap is nil", func(t *testing.T) { - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(25)} fee, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(250), TipCap: assets.NewWeiI(202)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(250), GasTipCap: assets.NewWeiI(202)}, fee) }) t.Run("ignores current tip cap that is smaller than original fee with bump applied", func(t *testing.T) { gas.SetTipCap(bhe, assets.NewWeiI(201)) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(25)} fee, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(250), TipCap: assets.NewWeiI(202)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(250), GasTipCap: assets.NewWeiI(202)}, fee) }) t.Run("uses current tip cap that is larger than original fee with bump applied", func(t *testing.T) { gas.SetTipCap(bhe, assets.NewWeiI(203)) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(25)} fee, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(250), TipCap: assets.NewWeiI(203)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(250), GasTipCap: assets.NewWeiI(203)}, fee) }) t.Run("ignores absurdly large current tip cap", func(t *testing.T) { gas.SetTipCap(bhe, assets.NewWeiI(1000000000000000)) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(25)} fee, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.NoError(t, err) - assert.Equal(t, gas.DynamicFee{FeeCap: assets.NewWeiI(250), TipCap: assets.NewWeiI(202)}, fee) + assert.Equal(t, gas.DynamicFee{GasFeeCap: assets.NewWeiI(250), GasTipCap: assets.NewWeiI(202)}, fee) }) t.Run("bumped tip cap price > max gas price", func(t *testing.T) { gas.SetTipCap(bhe, assets.NewWeiI(203)) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(990000)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(990000)} fee, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.Error(t, err) @@ -2743,7 +2695,7 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { t.Run("bumped fee cap price > max gas price", func(t *testing.T) { gas.SetTipCap(bhe, assets.NewWeiI(203)) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(990000), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(990000), GasTipCap: assets.NewWeiI(25)} fee, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.Error(t, err) @@ -2760,7 +2712,6 @@ func TestBlockHistoryEstimator_CheckInclusionPercentile_Calculation(t *testing.T ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BlockDelayF = 0 bhCfg.TransactionPercentileF = 35 @@ -2776,7 +2727,7 @@ func TestBlockHistoryEstimator_CheckInclusionPercentile_Calculation(t *testing.T geCfg.PriceMaxF = assets.NewWeiI(1000) geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -2818,7 +2769,6 @@ func TestBlockHistoryEstimator_CheckInclusionPercentile_Calculation(t *testing.T ethClient := testutils.NewEthClientMockWithDefaultChain(t) l1Oracle := rollupMocks.NewL1Oracle(t) - cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BlockDelayF = 0 bhCfg.TransactionPercentileF = 35 @@ -2835,7 +2785,7 @@ func TestBlockHistoryEstimator_CheckInclusionPercentile_Calculation(t *testing.T geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, defaultChainType, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ BaseFeePerGas: assets.NewWeiI(1), diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go index 4be7d1972f8..d1add00758b 100644 --- a/core/chains/evm/gas/chain_specific.go +++ b/core/chains/evm/gas/chain_specific.go @@ -19,7 +19,7 @@ func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainTy return false } } - if chainType == chaintype.ChainOptimismBedrock || chainType == chaintype.ChainKroma || chainType == chaintype.ChainScroll { + if chainType == chaintype.ChainOptimismBedrock || chainType == chaintype.ChainKroma || chainType == chaintype.ChainScroll || chainType == chaintype.ChainZircuit { // This is a special deposit transaction type introduced in Bedrock upgrade. // This is a system transaction that it will occur at least one time per block. // We should discard this type before even processing it to avoid flooding the diff --git a/core/chains/evm/gas/docs/FEE_HISTORY_ESTIMATOR.md b/core/chains/evm/gas/docs/FEE_HISTORY_ESTIMATOR.md new file mode 100644 index 00000000000..7f541344a32 --- /dev/null +++ b/core/chains/evm/gas/docs/FEE_HISTORY_ESTIMATOR.md @@ -0,0 +1,56 @@ +# Fee History Estimator + +## Overview +`Fee History` estimator is an EVM-based gas estimator that utilizes RPC calls to make gas price estimations. The estimator heavily relies on two RPC calls: `eth_gasPrice` and `eth_feeHistory`. It is built as a service and caches the calculated results in order to minimize overhead. While bumping, it prioritizes using the latest result from most recent blocks if it exceeds the bumped gas price. `Fee History` estimator supports both Legacy and Dynamic(EIP-1559) transactions. It can also handle chains that don't have a mempool and process transactions on an FCFS basis. + +## Configs +- `BumpPercent`: is the percentage by which to bump gas on a transaction. This is used when the estimator's bumping API gets called. +- `CacheTimeout`: is the time to wait to refresh the cached values. A small jitter is applied so the timeout won't be exactly the same each time. +- `EIP1559`: enables EIP-1559 mode and deactivates Legacy estimations. This means the estimator will refresh prices and make estimations only for Dynamic transactions. + +The rest of the configs are only applicable when `EIP1559` is enabled + +- `BlockHistorySize`: controls the number of past blocks to include during gas calculations. If set to 0, the estimator will skip any priority fee calculation and calculate the underlying base fee. This config should be set to 0 for chains that don't have a mempool. +- `RewardPercentile`: specifies which fee percentile to pick from for each processed past block. + +### Validations +During startup, the estimator will perform two config checks: +- `BumpPercent` is equal to or higher than *MinimumBumpPercentage*. *MinimumBumpPercentage* is fixed at 10% and it's the minimum percentage allowed by Geth when bumping a transaction, to prevent spam attacks. Replacing a transaction with a price less than 10% from the previous one will result in an error on the RPC side. Even for chains that don't enforce that rule, a 10% bump seems reasonable. +- `RewardPercentile` is equal or lower than *ConnectivityPercentile*, when `EIP1559` is enabled. *ConnectivityPercentile* is fixed at the 85th percentile and it's the maximum percentile we're willing to bump a transaction's price. This is used as a sanity check method in order to avoid excessive gas bumping when an RPC is not responding. + +## As a Service +`Fee History` estimator is built as a service. This means it will periodically poll the RPC for new prices, perform off-chain calculations, and cache the result for future use. For simplicity, only one type of gas estimation can be enabled at a time, Legacy or Dynamic. The poll interval is controlled by `CacheTimeout`. This value should be close to the block time. For slower chains, like Ethereum, you can set it to 12s, the same as the block time. For faster chains, you can skip a block or two, as prices will be refreshed more frequently. Ideally, 1s should be the absolute minimum. + + +## Legacy Gas Price Estimations +### Fetching +Periodically, `Fee History` estimator will call `eth_gasPrice` RPC method to fetch the gas price reported by the RPC. The parameters of this call can not be controlled by the user, meaning the result can sometimes be stale, especially during sudden gas spikes. It is advisable to use EIP-1559 if the chain supports it. + +### Bumping +During bumping, `Fee History` will refresh the cached value by making a call to the RPC. The bumped value of the original price will be compared with the market price and the highest value will be returned. + +## Dynamic Price Estimations +### Fetching +`Fee History` estimator periodically calls `eth_feeHistory` method to get the most up-to-date information from the RPC (more information about the call can be found [here](https://ethereum.github.io/execution-apis/api-documentation/)). It fetches three things: +- Base Fee of the next block +- The Yth priority fee percentiles of the past X blocks, where Y is controlled by `RewardPercentile` and X by `BlockHistorySize`. +- The 85th priority fee percentiles of the past X blocks. + +The above values are used to construct and cache the following: +- **MaxPriorityFeePerGas**: the average of Yth priority fee percentiles, excluding zero values. +- **MaxFeePerGas**: `baseFee * BaseFeeBufferPercentage + MaxPriorityFeePerGas`. *BaseFeeBufferPercentage* is used as a safety to catch any fluctuations in the Base Fee during the next blocks. +- **PriorityFeeThreshold**: the max out of every 85th priority fee percentile. This value is used to stop the estimator from bumping a price above that threshold and represents the maximum allowed value. + +*Note*: for chains that don't have a mempool (activated with `BlockHistorySize=0`) **MaxPriorityFeePerGas** and **PriorityFeeThreshold** are set to 0 since there is no concept of gas bumping. + +### Bumping +For bumping, `Fee History` estimator bumps both maxPriorityFeePerGas and maxFeePerGas of the original transaction attempt. This is required by Geth, along with the 10% minimum bumping threshold. The bumped price is compared to the cached market prices stored in the estimator and the highest of the two is picked. Finally, the resulting maxPriorityFeePerGas gets compared to the cached PriorityFeeThreshold value. If the bumped value is higher, this indicates a potential connection issue with the RPC, and bumping is skipped, returning an error. + +*Note*: for chains that don't have a mempool (activated with `BlockHistorySize=0`) bumping works differently. Instead, we force-fetch the most up-to-date Base Fee value and embed it in the MaxFeePerGas. MaxPriorityFeePerGas remains 0. + +### Metrics +The following prometheus metrics are exposed: +- **gas_price_updater**: latest Gas Price stored +- **base_fee_updater**: Base Fee of the next block +- **max_priority_fee_per_gas_updater**: latest MaxPriorityFeePerGas stored +- **max_fee_per_gas_updater**: latest MaxFeePerGas stored \ No newline at end of file diff --git a/core/chains/evm/gas/fee_history_estimator.go b/core/chains/evm/gas/fee_history_estimator.go new file mode 100644 index 00000000000..6d5f45fa294 --- /dev/null +++ b/core/chains/evm/gas/fee_history_estimator.go @@ -0,0 +1,441 @@ +package gas + +import ( + "context" + "fmt" + "math/big" + "strconv" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "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" + 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/core/chains/evm/assets" + evmclient "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" +) + +// metrics are thread safe +var ( + promFeeHistoryEstimatorGasPrice = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "gas_price_updater", + Help: "Sets latest gas price (in Wei)", + }, + []string{"evmChainID"}, + ) + promFeeHistoryEstimatorBaseFee = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "base_fee_updater", + Help: "Sets latest BaseFee (in Wei)", + }, + []string{"evmChainID"}, + ) + promFeeHistoryEstimatorMaxPriorityFeePerGas = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "max_priority_fee_per_gas_updater", + Help: "Sets latest MaxPriorityFeePerGas (in Wei)", + }, + []string{"evmChainID"}, + ) + promFeeHistoryEstimatorMaxFeePerGas = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "max_fee_per_gas_updater", + Help: "Sets latest MaxFeePerGas (in Wei)", + }, + []string{"evmChainID"}, + ) +) + +const ( + MinimumBumpPercentage = 10 // based on geth's spec + ConnectivityPercentile = 85 + BaseFeeBufferPercentage = 40 +) + +type FeeHistoryEstimatorConfig struct { + BumpPercent uint16 + CacheTimeout time.Duration + + EIP1559 bool + BlockHistorySize uint64 + RewardPercentile float64 +} + +type feeHistoryEstimatorClient interface { + SuggestGasPrice(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) +} + +type FeeHistoryEstimator struct { + services.StateMachine + + client feeHistoryEstimatorClient + logger logger.Logger + config FeeHistoryEstimatorConfig + chainID *big.Int + + gasPriceMu sync.RWMutex + gasPrice *assets.Wei + + dynamicPriceMu sync.RWMutex + dynamicPrice DynamicFee + + priorityFeeThresholdMu sync.RWMutex + priorityFeeThreshold *assets.Wei + + l1Oracle rollups.L1Oracle + + wg *sync.WaitGroup + stopCh services.StopChan + refreshCh chan struct{} +} + +func NewFeeHistoryEstimator(lggr logger.Logger, client feeHistoryEstimatorClient, cfg FeeHistoryEstimatorConfig, chainID *big.Int, l1Oracle rollups.L1Oracle) *FeeHistoryEstimator { + return &FeeHistoryEstimator{ + client: client, + logger: logger.Named(lggr, "FeeHistoryEstimator"), + config: cfg, + chainID: chainID, + l1Oracle: l1Oracle, + wg: new(sync.WaitGroup), + stopCh: make(chan struct{}), + refreshCh: make(chan struct{}), + } +} + +func (f *FeeHistoryEstimator) Start(context.Context) error { + return f.StartOnce("FeeHistoryEstimator", func() error { + if f.config.BumpPercent < MinimumBumpPercentage { + return fmt.Errorf("BumpPercent: %s is less than minimum allowed percentage: %s", + strconv.FormatUint(uint64(f.config.BumpPercent), 10), strconv.Itoa(MinimumBumpPercentage)) + } + if f.config.EIP1559 && f.config.RewardPercentile > ConnectivityPercentile { + return fmt.Errorf("RewardPercentile: %s is greater than maximum allowed percentile: %s", + strconv.FormatUint(uint64(f.config.RewardPercentile), 10), strconv.Itoa(ConnectivityPercentile)) + } + f.wg.Add(1) + go f.run() + + return nil + }) +} + +func (f *FeeHistoryEstimator) Close() error { + return f.StopOnce("FeeHistoryEstimator", func() error { + close(f.stopCh) + f.wg.Wait() + return nil + }) +} + +func (f *FeeHistoryEstimator) run() { + defer f.wg.Done() + + t := services.TickerConfig{ + JitterPct: services.DefaultJitter, + }.NewTicker(f.config.CacheTimeout) + + for { + select { + case <-f.stopCh: + return + case <-f.refreshCh: + t.Reset() + case <-t.C: + if f.config.EIP1559 { + if err := f.RefreshDynamicPrice(); err != nil { + f.logger.Error(err) + } + } else { + if _, err := f.RefreshGasPrice(); err != nil { + f.logger.Error(err) + } + } + } + } +} + +// 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) { + chainSpecificGasLimit = gasLimit + if gasPrice, err = f.getGasPrice(); err != nil { + return + } + + if gasPrice.Cmp(maxPrice) > 0 { + f.logger.Warnf("estimated gas price: %s is greater than the maximum gas price configured: %s, returning the maximum price instead.", gasPrice, maxPrice) + return maxPrice, chainSpecificGasLimit, nil + } + return +} + +// 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.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + gasPrice, err := f.client.SuggestGasPrice(ctx) + if err != nil { + return nil, err + } + + promFeeHistoryEstimatorGasPrice.WithLabelValues(f.chainID.String()).Set(float64(gasPrice.Int64())) + + gasPriceWei := assets.NewWei(gasPrice) + + f.logger.Debugf("fetched new gas price: %v", gasPriceWei) + + f.gasPriceMu.Lock() + defer f.gasPriceMu.Unlock() + f.gasPrice = gasPriceWei + return f.gasPrice, nil +} + +func (f *FeeHistoryEstimator) getGasPrice() (*assets.Wei, error) { + f.gasPriceMu.RLock() + defer f.gasPriceMu.RUnlock() + if f.gasPrice == nil { + return f.gasPrice, fmt.Errorf("gas price not set") + } + return f.gasPrice, nil +} + +// GetDynamicFee will fetch the cached dynamic prices. +func (f *FeeHistoryEstimator) GetDynamicFee(ctx context.Context, maxPrice *assets.Wei) (fee DynamicFee, err error) { + if fee, err = f.getDynamicPrice(); err != nil { + return + } + + if fee.GasFeeCap.Cmp(maxPrice) > 0 { + f.logger.Warnf("estimated maxFeePerGas: %v is greater than the maximum price configured: %v, returning the maximum price instead.", + fee.GasFeeCap, maxPrice) + fee.GasFeeCap = maxPrice + if fee.GasTipCap.Cmp(maxPrice) > 0 { + f.logger.Warnf("estimated maxPriorityFeePerGas: %v is greater than the maximum price configured: %v, returning the maximum price instead.", + fee.GasTipCap, maxPrice) + fee.GasTipCap = maxPrice + } + } + + return +} + +// RefreshDynamicPrice uses eth_feeHistory to fetch the baseFee of the next block and the Nth maxPriorityFeePerGas percentiles +// of the past X blocks. It also fetches the highest 85th maxPriorityFeePerGas percentile of the past X blocks, which represents +// 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.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + // RewardPercentile will be used for maxPriorityFeePerGas estimations and connectivityPercentile to set the highest threshold for bumping. + feeHistory, err := f.client.FeeHistory(ctx, max(f.config.BlockHistorySize, 1), []float64{f.config.RewardPercentile, ConnectivityPercentile}) + if err != nil { + return err + } + + // eth_feeHistory doesn't return the latest baseFee of the range but rather the latest + 1, because it can be derived from the existing + // values. Source: https://github.com/ethereum/go-ethereum/blob/b0f66e34ca2a4ea7ae23475224451c8c9a569826/eth/gasprice/feehistory.go#L235 + // nextBlock is the latest returned + 1 to be aligned with the base fee value. + nextBaseFee := assets.NewWei(feeHistory.BaseFee[len(feeHistory.BaseFee)-1]) + nextBlock := big.NewInt(0).Add(feeHistory.OldestBlock, big.NewInt(int64(f.config.BlockHistorySize))) + + // If BlockHistorySize is 0 it means priority fees will be ignored from the calculations, so we set them to 0. + // If it's not we exclude 0 priced priority fees from the RPC response, even though some networks allow them. For empty blocks, eth_feeHistory + // returns priority fees with 0 values so it's safer to discard them in order to pick values from a more representative sample. + maxPriorityFeePerGas := assets.NewWeiI(0) + priorityFeeThresholdWei := assets.NewWeiI(0) + if f.config.BlockHistorySize > 0 { + var nonZeroRewardsLen int64 + priorityFee := big.NewInt(0) + priorityFeeThreshold := big.NewInt(0) + for _, reward := range feeHistory.Reward { + // reward needs to have values for two percentiles. Some chains may return an empty slice instead of 0x0 values, so we use + // continue instead of throwing an error. + if len(reward) < 2 { + continue + } + // We'll calculate the average of non-zero priority fees + if reward[0].Cmp(big.NewInt(0)) > 0 { + priorityFee = priorityFee.Add(priorityFee, reward[0]) + nonZeroRewardsLen++ + } + // We take the max value for the bumping threshold + if reward[1].Cmp(big.NewInt(0)) > 0 { + priorityFeeThreshold = bigmath.Max(priorityFeeThreshold, reward[1]) + } + } + + if nonZeroRewardsLen == 0 || priorityFeeThreshold.Cmp(big.NewInt(0)) == 0 { + return nil + } + priorityFeeThresholdWei = assets.NewWei(priorityFeeThreshold) + maxPriorityFeePerGas = assets.NewWei(priorityFee.Div(priorityFee, big.NewInt(nonZeroRewardsLen))) + } + // BaseFeeBufferPercentage is used as a safety to catch any fluctuations in the Base Fee during the next blocks. + maxFeePerGas := nextBaseFee.AddPercentage(BaseFeeBufferPercentage).Add(maxPriorityFeePerGas) + + promFeeHistoryEstimatorBaseFee.WithLabelValues(f.chainID.String()).Set(float64(nextBaseFee.Int64())) + promFeeHistoryEstimatorMaxPriorityFeePerGas.WithLabelValues(f.chainID.String()).Set(float64(maxPriorityFeePerGas.Int64())) + promFeeHistoryEstimatorMaxFeePerGas.WithLabelValues(f.chainID.String()).Set(float64(maxFeePerGas.Int64())) + + f.logger.Debugf("Fetched new dynamic prices, nextBlock#: %v - oldestBlock#: %v - nextBaseFee: %v - maxFeePerGas: %v - maxPriorityFeePerGas: %v - maxPriorityFeeThreshold: %v", + nextBlock, feeHistory.OldestBlock, nextBaseFee, maxFeePerGas, maxPriorityFeePerGas, priorityFeeThresholdWei) + + f.priorityFeeThresholdMu.Lock() + f.priorityFeeThreshold = priorityFeeThresholdWei + f.priorityFeeThresholdMu.Unlock() + + f.dynamicPriceMu.Lock() + defer f.dynamicPriceMu.Unlock() + f.dynamicPrice.GasFeeCap = maxFeePerGas + f.dynamicPrice.GasTipCap = maxPriorityFeePerGas + return nil +} + +func (f *FeeHistoryEstimator) getDynamicPrice() (fee DynamicFee, err error) { + f.dynamicPriceMu.RLock() + defer f.dynamicPriceMu.RUnlock() + if f.dynamicPrice.GasFeeCap == nil || f.dynamicPrice.GasTipCap == nil { + return fee, fmt.Errorf("dynamic price not set") + } + return f.dynamicPrice, nil +} + +// BumpLegacyGas provides a bumped gas price value by bumping the previous one by BumpPercent. +// If the original value is higher than the max price it returns an error as there is no room for bumping. +// It aggregates the market, bumped, and max gas price to provide a correct value. +func (f *FeeHistoryEstimator) BumpLegacyGas(ctx context.Context, originalGasPrice *assets.Wei, gasLimit uint64, maxPrice *assets.Wei, _ []EvmPriorAttempt) (*assets.Wei, uint64, error) { + // 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) + } + + currentGasPrice, err := f.RefreshGasPrice() + if err != nil { + return nil, 0, err + } + f.IfStarted(func() { f.refreshCh <- struct{}{} }) + + bumpedGasPrice := originalGasPrice.AddPercentage(f.config.BumpPercent) + bumpedGasPrice, err = LimitBumpedFee(originalGasPrice, currentGasPrice, bumpedGasPrice, maxPrice) + if err != nil { + return nil, 0, fmt.Errorf("failed to limit gas price: %w", err) + } + + f.logger.Debugw("bumped gas price", "originalGasPrice", originalGasPrice, "marketGasPrice", currentGasPrice, "bumpedGasPrice", bumpedGasPrice) + + return bumpedGasPrice, gasLimit, nil +} + +// BumpDynamicFee provides a bumped dynamic fee by bumping the previous one by BumpPercent. +// If the original values are higher than the max price it returns an error as there is no room for bumping. If maxPriorityFeePerGas is bumped +// above the priority fee threshold then there is a good chance there is a connectivity issue and we shouldn't bump. +// Both maxFeePerGas as well as maxPriorityFeePerGas need to be bumped otherwise the RPC won't accept the transaction and throw an error. +// See: https://github.com/ethereum/go-ethereum/issues/24284 +// It aggregates the market, bumped, and max price to provide a correct value, for both maxFeePerGas as well as maxPriorityFerPergas. +func (f *FeeHistoryEstimator) BumpDynamicFee(ctx context.Context, originalFee DynamicFee, maxPrice *assets.Wei, _ []EvmPriorAttempt) (bumped DynamicFee, err error) { + // For chains that don't have a mempool there is no concept of gas bumping so we force-call RefreshDynamicPrice to update the underlying base fee value + if f.config.BlockHistorySize == 0 { + if !f.IfStarted(func() { + if refreshErr := f.RefreshDynamicPrice(); refreshErr != nil { + err = refreshErr + return + } + f.refreshCh <- struct{}{} + bumped, err = f.GetDynamicFee(ctx, maxPrice) + }) { + return bumped, fmt.Errorf("estimator not started") + } + return bumped, err + } + + // Sanitize original fee input + // According to geth's spec we need to bump both maxFeePerGas and maxPriorityFeePerGas for the new attempt to be accepted by the RPC + if originalFee.GasFeeCap == nil || + originalFee.GasTipCap == nil || + ((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) + } + + currentDynamicPrice, err := f.getDynamicPrice() + if err != nil { + return + } + + bumpedMaxPriorityFeePerGas := originalFee.GasTipCap.AddPercentage(f.config.BumpPercent) + bumpedMaxFeePerGas := originalFee.GasFeeCap.AddPercentage(f.config.BumpPercent) + + bumpedMaxPriorityFeePerGas, err = LimitBumpedFee(originalFee.GasTipCap, currentDynamicPrice.GasTipCap, bumpedMaxPriorityFeePerGas, maxPrice) + if err != nil { + return bumped, fmt.Errorf("failed to limit maxPriorityFeePerGas: %w", err) + } + + priorityFeeThreshold, e := f.getPriorityFeeThreshold() + if e != nil { + return bumped, e + } + + 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) + } + + bumpedMaxFeePerGas, err = LimitBumpedFee(originalFee.GasFeeCap, currentDynamicPrice.GasFeeCap, bumpedMaxFeePerGas, maxPrice) + if err != nil { + return bumped, fmt.Errorf("failed to limit maxFeePerGas: %w", err) + } + + bumpedFee := DynamicFee{GasFeeCap: bumpedMaxFeePerGas, GasTipCap: bumpedMaxPriorityFeePerGas} + f.logger.Debugw("bumped dynamic fee", "originalFee", originalFee, "marketFee", currentDynamicPrice, "bumpedFee", bumpedFee) + + return bumpedFee, nil +} + +// LimitBumpedFee selects the maximum value between the bumped attempt and the current fee, if there is one. If the result is higher than the max price it gets capped. +// Geth's implementation has a hard 10% minimum limit for the bumped values, otherwise it rejects the transaction with an error. +// See: https://github.com/ethereum/go-ethereum/blob/bff330335b94af3643ac2fb809793f77de3069d4/core/tx_list.go#L298 +// +// Note: for chains that support EIP-1559 but we still choose to send Legacy transactions to them, the limit is still enforcable due to the fact that Legacy transactions +// are treated the same way as Dynamic transactions under the hood. For chains that don't support EIP-1559 at all, the limit isn't enforcable but a 10% minimum bump percentage +// makes sense anyway. +func LimitBumpedFee(originalFee *assets.Wei, currentFee *assets.Wei, bumpedFee *assets.Wei, maxPrice *assets.Wei) (*assets.Wei, error) { + if currentFee != nil { + bumpedFee = assets.WeiMax(currentFee, bumpedFee) + } + bumpedFee = assets.WeiMin(bumpedFee, maxPrice) + + // The first check is added for the following edge case: + // If originalFee is below 10 wei, then adding the minimum bump percentage won't have any effect on the final value because of rounding down. + // Similarly for bumpedFee, it can have the exact same value as the originalFee, even if we bumped, given an originalFee of less than 10 wei + // and a small enough BumpPercent. + 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) + } + return bumpedFee, nil +} + +func (f *FeeHistoryEstimator) getPriorityFeeThreshold() (*assets.Wei, error) { + f.priorityFeeThresholdMu.RLock() + defer f.priorityFeeThresholdMu.RUnlock() + if f.priorityFeeThreshold == nil { + return f.priorityFeeThreshold, fmt.Errorf("priorityFeeThreshold not set") + } + return f.priorityFeeThreshold, nil +} + +func (f *FeeHistoryEstimator) Name() string { return f.logger.Name() } +func (f *FeeHistoryEstimator) L1Oracle() rollups.L1Oracle { return f.l1Oracle } +func (f *FeeHistoryEstimator) HealthReport() map[string]error { return map[string]error{f.Name(): nil} } +func (f *FeeHistoryEstimator) OnNewLongestChain(context.Context, *evmtypes.Head) {} diff --git a/core/chains/evm/gas/fee_history_estimator_test.go b/core/chains/evm/gas/fee_history_estimator_test.go new file mode 100644 index 00000000000..a96046f1f26 --- /dev/null +++ b/core/chains/evm/gas/fee_history_estimator_test.go @@ -0,0 +1,515 @@ +package gas_test + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + + "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/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" +) + +func TestFeeHistoryEstimatorLifecycle(t *testing.T) { + t.Parallel() + var gasLimit uint64 = 21000 + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("fails if you fetch gas price before the estimator starts", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{ + BumpPercent: 20, + RewardPercentile: 60, + EIP1559: false, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + _, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.ErrorContains(t, err, "gas price not set") + }) + + t.Run("fails to start if BumpPercent is lower than the minimum cap", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 9} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + assert.ErrorContains(t, u.Start(tests.Context(t)), "BumpPercent") + }) + + t.Run("fails to start if RewardPercentile is higher than ConnectivityPercentile in EIP-1559", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{ + BumpPercent: 20, + RewardPercentile: 99, + EIP1559: true, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + assert.ErrorContains(t, u.Start(tests.Context(t)), "RewardPercentile") + }) + + t.Run("starts if configs are correct", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil).Maybe() + + cfg := gas.FeeHistoryEstimatorConfig{ + BumpPercent: 20, + RewardPercentile: 10, + CacheTimeout: 10 * time.Second, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + err := u.Start(tests.Context(t)) + assert.NoError(t, err) + err = u.Close() + assert.NoError(t, err) + }) +} + +func TestFeeHistoryEstimatorGetLegacyGas(t *testing.T) { + t.Parallel() + + var gasLimit uint64 = 21000 + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("fetches a new gas price when first called", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + _, err := u.RefreshGasPrice() + assert.NoError(t, err) + gasPrice, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(10), gasPrice) + }) + + t.Run("will return max price if estimation exceeds it", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{} + + maxPrice := assets.NewWeiI(1) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + _, err := u.RefreshGasPrice() + assert.NoError(t, err) + gas1, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.NoError(t, err) + assert.Equal(t, maxPrice, gas1) + }) + + t.Run("fails if gas price has not been set yet", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{} + + maxPrice := assets.NewWeiI(1) + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + _, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.Error(t, err) + assert.ErrorContains(t, err, "gas price not set") + }) +} + +func TestFeeHistoryEstimatorBumpLegacyGas(t *testing.T) { + t.Parallel() + + var gasLimit uint64 = 21000 + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("bumps a previous attempt by BumpPercent", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalGasPrice := assets.NewWeiI(10) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 50, CacheTimeout: 5 * time.Second} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + servicetest.RunHealthy(t, u) + gasPrice, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(15), gasPrice) + }) + + t.Run("fails if the original attempt is nil, or equal or higher than the max price", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + + cfg := gas.FeeHistoryEstimatorConfig{} + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + + var originalPrice *assets.Wei + _, _, err := u.BumpLegacyGas(tests.Context(t), originalPrice, gasLimit, maxPrice, nil) + assert.Error(t, err) + + originalPrice = assets.NewWeiI(100) + _, _, err = u.BumpLegacyGas(tests.Context(t), originalPrice, gasLimit, maxPrice, nil) + assert.Error(t, err) + }) + + t.Run("returns market gas price if bumped original fee is lower", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(80), nil).Once() + originalGasPrice := assets.NewWeiI(10) + + cfg := gas.FeeHistoryEstimatorConfig{} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + gas, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(80), gas) + }) + + t.Run("returns max gas price if bumped original fee is higher", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(1), nil).Once() + originalGasPrice := assets.NewWeiI(10) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 50} + + maxPrice := assets.NewWeiI(14) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + gas, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, maxPrice, gas) + }) + + t.Run("returns max gas price if the aggregation of max and original bumped fee is higher", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(1), nil).Once() + originalGasPrice := assets.NewWeiI(10) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 50} + + maxPrice := assets.NewWeiI(14) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + gas, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, maxPrice, gas) + }) + + t.Run("fails if the bumped gas price is lower than the minimum bump percentage", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(100), nil).Once() + originalGasPrice := assets.NewWeiI(100) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 20} + + // Price will be capped by the max price + maxPrice := assets.NewWeiI(101) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + _, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.Error(t, err) + }) +} + +func TestFeeHistoryEstimatorGetDynamicFee(t *testing.T) { + t.Parallel() + + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("fetches a new dynamic fee when first called", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + baseFee := big.NewInt(5) + maxPriorityFeePerGas1 := big.NewInt(33) + maxPriorityFeePerGas2 := big.NewInt(20) + + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas1, big.NewInt(5)}, {maxPriorityFeePerGas2, big.NewInt(5)}, {}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee, baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + blockHistoryLength := 2 + cfg := gas.FeeHistoryEstimatorConfig{BlockHistorySize: uint64(blockHistoryLength)} + avrgPriorityFee := big.NewInt(0) + avrgPriorityFee.Add(maxPriorityFeePerGas1, maxPriorityFeePerGas2).Div(avrgPriorityFee, big.NewInt(int64(blockHistoryLength))) + maxFee := (*assets.Wei)(baseFee).AddPercentage(gas.BaseFeeBufferPercentage).Add((*assets.Wei)(avrgPriorityFee)) + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + dynamicFee, err := u.GetDynamicFee(tests.Context(t), maxPrice) + assert.NoError(t, err) + assert.Equal(t, maxFee, dynamicFee.GasFeeCap) + assert.Equal(t, (*assets.Wei)(avrgPriorityFee), dynamicFee.GasTipCap) + }) + + t.Run("fails if dynamic prices have not been set yet", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{} + + maxPrice := assets.NewWeiI(1) + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + _, err := u.GetDynamicFee(tests.Context(t), maxPrice) + assert.Error(t, err) + assert.ErrorContains(t, err, "dynamic price not set") + }) + + t.Run("will return max price if tip cap or fee cap exceed it", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + baseFee := big.NewInt(1) + maxPriorityFeePerGas := big.NewInt(3) + maxPrice := assets.NewWeiI(2) + + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(5)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{BlockHistorySize: 1} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + dynamicFee, err := u.GetDynamicFee(tests.Context(t), maxPrice) + assert.NoError(t, err) + assert.Equal(t, maxPrice, dynamicFee.GasFeeCap) + assert.Equal(t, maxPrice, dynamicFee.GasTipCap) + }) +} + +func TestFeeHistoryEstimatorBumpDynamicFee(t *testing.T) { + t.Parallel() + + globalMaxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("bumps a previous attempt by BumpPercent", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(10), + } + + // These values will be ignored because they are lower prices than the originalFee + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{big.NewInt(5), big.NewInt(50)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{big.NewInt(5)}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 2, + BumpPercent: 50, + } + + expectedFeeCap := originalFee.GasFeeCap.AddPercentage(cfg.BumpPercent) + expectedTipCap := originalFee.GasTipCap.AddPercentage(cfg.BumpPercent) + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + dynamicFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, expectedFeeCap, dynamicFee.GasFeeCap) + assert.Equal(t, expectedTipCap, dynamicFee.GasTipCap) + }) + + t.Run("fails if the original attempt is invalid", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + maxPrice := assets.NewWeiI(20) + cfg := gas.FeeHistoryEstimatorConfig{BlockHistorySize: 1} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + // nil original fee + var originalFee gas.DynamicFee + _, err := u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + + // tip cap is higher than fee cap + originalFee = gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(10), + GasTipCap: assets.NewWeiI(11), + } + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + + // fee cap is equal or higher to max price + originalFee = gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(10), + } + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + }) + + t.Run("returns market prices if bumped original fee is lower", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(10), + } + + // Market fees + baseFee := big.NewInt(5) + maxPriorityFeePerGas := big.NewInt(33) + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(100)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + maxFee := (*assets.Wei)(baseFee).AddPercentage(gas.BaseFeeBufferPercentage).Add((*assets.Wei)(maxPriorityFeePerGas)) + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, (*assets.Wei)(maxPriorityFeePerGas), bumpedFee.GasTipCap) + assert.Equal(t, maxFee, bumpedFee.GasFeeCap) + }) + + t.Run("fails if connectivity percentile value is reached", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(10), + } + + // Market fees + baseFee := big.NewInt(5) + maxPriorityFeePerGas := big.NewInt(33) + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(30)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.Error(t, err) + assert.True(t, fee.IsBumpErr(err)) + }) + + t.Run("returns max price if the aggregation of max and original bumped fee is higher", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(18), + } + + maxPrice := assets.NewWeiI(25) + // Market fees + baseFee := big.NewInt(1) + maxPriorityFeePerGas := big.NewInt(1) + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(30)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, maxPrice, bumpedFee.GasTipCap) + assert.Equal(t, maxPrice, bumpedFee.GasFeeCap) + }) + + t.Run("fails if the bumped gas price is lower than the minimum bump percentage", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(18), + } + + maxPrice := assets.NewWeiI(21) + // Market fees + baseFee := big.NewInt(1) + maxPriorityFeePerGas := big.NewInt(1) + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(30)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + }) + + t.Run("ignores maxPriorityFeePerGas if there is no mempool and forces refetch", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + GasFeeCap: assets.NewWeiI(40), + GasTipCap: assets.NewWeiI(0), + } + + // Market fees + baseFee := big.NewInt(10) + maxPriorityFeePerGas := big.NewInt(0) + feeHistoryResult := ðereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(0)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil) + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 0, + BumpPercent: 20, + CacheTimeout: 10 * time.Second, + EIP1559: true, + } + + maxFeePerGas := assets.NewWei(baseFee).AddPercentage(gas.BaseFeeBufferPercentage) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + servicetest.RunHealthy(t, u) + bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(0), (*assets.Wei)(maxPriorityFeePerGas)) + assert.Equal(t, maxFeePerGas, bumpedFee.GasFeeCap) + }) +} diff --git a/core/chains/evm/gas/fixed_price_estimator.go b/core/chains/evm/gas/fixed_price_estimator.go index 7ac086bf067..43398ef4b19 100644 --- a/core/chains/evm/gas/fixed_price_estimator.go +++ b/core/chains/evm/gas/fixed_price_estimator.go @@ -107,8 +107,8 @@ func (f *fixedPriceEstimator) GetDynamicFee(_ context.Context, maxGasPriceWei *a } return DynamicFee{ - FeeCap: feeCap, - TipCap: gasTipCap, + GasFeeCap: feeCap, + GasTipCap: gasTipCap, }, nil } diff --git a/core/chains/evm/gas/fixed_price_estimator_test.go b/core/chains/evm/gas/fixed_price_estimator_test.go index 80641ae3cc5..16bb4b6f5c0 100644 --- a/core/chains/evm/gas/fixed_price_estimator_test.go +++ b/core/chains/evm/gas/fixed_price_estimator_test.go @@ -103,8 +103,8 @@ func Test_FixedPriceEstimator(t *testing.T) { fee, err := f.GetDynamicFee(tests.Context(t), maxGasPrice) require.NoError(t, err) - assert.Equal(t, assets.NewWeiI(52), fee.TipCap) - assert.Equal(t, assets.NewWeiI(100), fee.FeeCap) + assert.Equal(t, assets.NewWeiI(52), fee.GasTipCap) + assert.Equal(t, assets.NewWeiI(100), fee.GasFeeCap) // Gas bumping disabled config.BumpThresholdF = uint64(0) @@ -112,15 +112,15 @@ func Test_FixedPriceEstimator(t *testing.T) { fee, err = f.GetDynamicFee(tests.Context(t), maxGasPrice) require.NoError(t, err) - assert.Equal(t, assets.NewWeiI(52), fee.TipCap) - assert.Equal(t, maxGasPrice, fee.FeeCap) + assert.Equal(t, assets.NewWeiI(52), fee.GasTipCap) + assert.Equal(t, maxGasPrice, fee.GasFeeCap) // override max gas price fee, err = f.GetDynamicFee(tests.Context(t), assets.NewWeiI(10)) require.NoError(t, err) - assert.Equal(t, assets.NewWeiI(52), fee.TipCap) - assert.Equal(t, assets.NewWeiI(10), fee.FeeCap) + assert.Equal(t, assets.NewWeiI(52), fee.GasTipCap) + assert.Equal(t, assets.NewWeiI(10), fee.GasFeeCap) }) t.Run("BumpDynamicFee calls BumpDynamicFeeOnly", func(t *testing.T) { @@ -134,7 +134,7 @@ func Test_FixedPriceEstimator(t *testing.T) { lggr := logger.TestSugared(t) f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, lggr, l1Oracle) - originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} + originalFee := gas.DynamicFee{GasFeeCap: assets.NewWeiI(100), GasTipCap: assets.NewWeiI(25)} fee, err := f.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, nil) require.NoError(t, err) diff --git a/core/chains/evm/gas/gas_test.go b/core/chains/evm/gas/gas_test.go index 8f3d56b54e7..1f9cd100d0e 100644 --- a/core/chains/evm/gas/gas_test.go +++ b/core/chains/evm/gas/gas_test.go @@ -146,7 +146,7 @@ func Test_BumpDynamicFeeOnly(t *testing.T) { for _, test := range []struct { name string - currentTipCap *assets.Wei + currentGasTipCap *assets.Wei currentBaseFee *assets.Wei originalFee gas.DynamicFee tipCapDefault *assets.Wei @@ -160,128 +160,128 @@ func Test_BumpDynamicFeeOnly(t *testing.T) { }{ { name: "defaults", - currentTipCap: nil, + currentGasTipCap: nil, currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(4000)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(4000)}, tipCapDefault: assets.GWei(20), bumpPercent: 20, bumpMin: toWei("5e9"), // 0.5 GWei priceMax: assets.GWei(5000), - expectedFee: gas.DynamicFee{TipCap: assets.GWei(36), FeeCap: assets.GWei(4800)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(36), GasFeeCap: assets.GWei(4800)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, }, { name: "original + percentage wins", - currentTipCap: nil, + currentGasTipCap: nil, currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(100)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(100)}, tipCapDefault: assets.GWei(20), bumpPercent: 30, bumpMin: toWei("5e9"), // 0.5 GWei priceMax: toWei("5e11"), // 500GWei - expectedFee: gas.DynamicFee{TipCap: assets.GWei(39), FeeCap: assets.GWei(130)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(39), GasFeeCap: assets.GWei(130)}, originalLimit: 100000, limitMultiplierPercent: 1.1, expectedLimit: 110000, }, { name: "original + fixed wins", - currentTipCap: nil, + currentGasTipCap: nil, currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(400)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(400)}, tipCapDefault: assets.GWei(20), bumpPercent: 20, bumpMin: toWei("8e9"), // 0.8 GWei priceMax: toWei("5e11"), // 500GWei - expectedFee: gas.DynamicFee{TipCap: assets.GWei(38), FeeCap: assets.GWei(480)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(38), GasFeeCap: assets.GWei(480)}, originalLimit: 100000, limitMultiplierPercent: 0.8, expectedLimit: 80000, }, { name: "default + percentage wins", - currentTipCap: nil, + currentGasTipCap: nil, currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(400)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(400)}, tipCapDefault: assets.GWei(40), bumpPercent: 20, bumpMin: toWei("5e9"), // 0.5 GWei priceMax: toWei("5e11"), // 500GWei - expectedFee: gas.DynamicFee{TipCap: assets.GWei(48), FeeCap: assets.GWei(480)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(48), GasFeeCap: assets.GWei(480)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, }, { name: "default + fixed wins", - currentTipCap: assets.GWei(48), + currentGasTipCap: assets.GWei(48), currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(400)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(400)}, tipCapDefault: assets.GWei(40), bumpPercent: 20, bumpMin: toWei("9e9"), // 0.9 GWei priceMax: toWei("5e11"), // 500GWei - expectedFee: gas.DynamicFee{TipCap: assets.GWei(49), FeeCap: assets.GWei(480)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(49), GasFeeCap: assets.GWei(480)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, }, { name: "higher current tip cap wins", - currentTipCap: assets.GWei(50), + currentGasTipCap: assets.GWei(50), currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(400)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(400)}, tipCapDefault: assets.GWei(40), bumpPercent: 20, bumpMin: toWei("9e9"), // 0.9 GWei priceMax: toWei("5e11"), // 500GWei - expectedFee: gas.DynamicFee{TipCap: assets.GWei(50), FeeCap: assets.GWei(480)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(50), GasFeeCap: assets.GWei(480)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, }, { name: "if bumped tip cap would exceed bumped fee cap, adds fixed value to expectedFee", - currentTipCap: nil, + currentGasTipCap: nil, currentBaseFee: nil, - originalFee: gas.DynamicFee{TipCap: assets.GWei(10), FeeCap: assets.GWei(20)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(10), GasFeeCap: assets.GWei(20)}, tipCapDefault: assets.GWei(5), bumpPercent: 5, bumpMin: assets.GWei(50), priceMax: toWei("5e11"), // 500GWei - expectedFee: gas.DynamicFee{TipCap: assets.GWei(60), FeeCap: assets.GWei(70)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(60), GasFeeCap: assets.GWei(70)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, }, { name: "ignores current base fee and uses previous fee cap if calculated fee cap would be lower", - currentTipCap: assets.GWei(20), + currentGasTipCap: assets.GWei(20), currentBaseFee: assets.GWei(100), - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(400)}, + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(400)}, tipCapDefault: assets.GWei(20), bumpPercent: 20, bumpMin: toWei("5e9"), // 0.5 GWei priceMax: assets.GWei(5000), - expectedFee: gas.DynamicFee{TipCap: assets.GWei(36), FeeCap: assets.GWei(480)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(36), GasFeeCap: assets.GWei(480)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, }, { - name: "uses current base fee to calculate fee cap if that would be higher than the existing one", - currentTipCap: assets.GWei(20), - currentBaseFee: assets.GWei(1000), - originalFee: gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(400)}, - tipCapDefault: assets.GWei(20), - bumpPercent: 20, - bumpMin: toWei("5e9"), // 0.5 GWei - priceMax: assets.GWei(5000), + name: "uses current base fee to calculate fee cap if that would be higher than the existing one", + currentGasTipCap: assets.GWei(20), + currentBaseFee: assets.GWei(1000), + originalFee: gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(400)}, + tipCapDefault: assets.GWei(20), + bumpPercent: 20, + bumpMin: toWei("5e9"), // 0.5 GWei + priceMax: assets.GWei(5000), // base fee * 4 blocks * 1.125 % plus new tip cap to give max // 1000 * (1.125 ^ 4) + 36 ~= 1637 - expectedFee: gas.DynamicFee{TipCap: assets.GWei(36), FeeCap: assets.NewWeiI(1637806640625)}, + expectedFee: gas.DynamicFee{GasTipCap: assets.GWei(36), GasFeeCap: assets.NewWeiI(1637806640625)}, originalLimit: 100000, limitMultiplierPercent: 1.0, expectedLimit: 100000, @@ -296,13 +296,13 @@ func Test_BumpDynamicFeeOnly(t *testing.T) { cfg.LimitMultiplierF = test.limitMultiplierPercent bufferBlocks := uint16(4) - actual, err := gas.BumpDynamicFeeOnly(cfg, bufferBlocks, logger.TestSugared(t), test.currentTipCap, test.currentBaseFee, test.originalFee, test.priceMax) + actual, err := gas.BumpDynamicFeeOnly(cfg, bufferBlocks, logger.TestSugared(t), test.currentGasTipCap, test.currentBaseFee, test.originalFee, test.priceMax) require.NoError(t, err) - if actual.TipCap.Cmp(test.expectedFee.TipCap) != 0 { - t.Fatalf("TipCap not equal, expected %s but got %s", test.expectedFee.TipCap.String(), actual.TipCap.String()) + if actual.GasTipCap.Cmp(test.expectedFee.GasTipCap) != 0 { + t.Fatalf("TipCap not equal, expected %s but got %s", test.expectedFee.GasTipCap.String(), actual.GasTipCap.String()) } - if actual.FeeCap.Cmp(test.expectedFee.FeeCap) != 0 { - t.Fatalf("FeeCap not equal, expected %s but got %s", test.expectedFee.FeeCap.String(), actual.FeeCap.String()) + if actual.GasFeeCap.Cmp(test.expectedFee.GasFeeCap) != 0 { + t.Fatalf("FeeCap not equal, expected %s but got %s", test.expectedFee.GasFeeCap.String(), actual.GasFeeCap.String()) } }) } @@ -320,14 +320,14 @@ func Test_BumpDynamicFeeOnly_HitsMaxError(t *testing.T) { cfg.PriceMaxF = priceMax t.Run("tip cap hits max", func(t *testing.T) { - originalFee := gas.DynamicFee{TipCap: assets.GWei(30), FeeCap: assets.GWei(100)} + originalFee := gas.DynamicFee{GasTipCap: assets.GWei(30), GasFeeCap: assets.GWei(100)} _, err := gas.BumpDynamicFeeOnly(cfg, 0, logger.TestSugared(t), nil, nil, originalFee, priceMax) require.Error(t, err) require.Contains(t, err.Error(), "bumped tip cap of 45 gwei would exceed configured max gas price of 40 gwei (original fee: tip cap 30 gwei, fee cap 100 gwei)") }) t.Run("fee cap hits max", func(t *testing.T) { - originalFee := gas.DynamicFee{TipCap: assets.GWei(10), FeeCap: assets.GWei(100)} + originalFee := gas.DynamicFee{GasTipCap: assets.GWei(10), GasFeeCap: assets.GWei(100)} _, err := gas.BumpDynamicFeeOnly(cfg, 0, logger.TestSugared(t), nil, nil, originalFee, priceMax) require.Error(t, err) require.Contains(t, err.Error(), "bumped fee cap of 150 gwei would exceed configured max gas price of 40 gwei (original fee: tip cap 10 gwei, fee cap 100 gwei)") diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go index 2c12ed426a6..698a1b7c65c 100644 --- a/core/chains/evm/gas/helpers_test.go +++ b/core/chains/evm/gas/helpers_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -122,27 +121,6 @@ func (m *MockBlockHistoryConfig) TransactionPercentile() uint16 { return m.TransactionPercentileF } -type MockConfig struct { - ChainTypeF string - FinalityTagEnabledF bool -} - -func NewMockConfig() *MockConfig { - return &MockConfig{} -} - -func (m *MockConfig) ChainType() chaintype.ChainType { - return chaintype.ChainType(m.ChainTypeF) -} - -func (m *MockConfig) FinalityDepth() uint32 { - panic("not implemented") // TODO: Implement -} - -func (m *MockConfig) FinalityTagEnabled() bool { - return m.FinalityTagEnabledF -} - type MockGasEstimatorConfig struct { EIP1559DynamicFeesF bool BumpPercentF uint16 @@ -157,6 +135,7 @@ type MockGasEstimatorConfig struct { FeeCapDefaultF *assets.Wei LimitMaxF uint64 ModeF string + EstimateLimitF bool } func NewMockGasConfig() *MockGasEstimatorConfig { @@ -214,3 +193,7 @@ func (m *MockGasEstimatorConfig) LimitMax() uint64 { func (m *MockGasEstimatorConfig) Mode() string { return m.ModeF } + +func (m *MockGasEstimatorConfig) EstimateLimit() bool { + return m.EstimateLimitF +} diff --git a/core/chains/evm/gas/mocks/config.go b/core/chains/evm/gas/mocks/config.go deleted file mode 100644 index 95c3eda171d..00000000000 --- a/core/chains/evm/gas/mocks/config.go +++ /dev/null @@ -1,171 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mocks - -import ( - chaintype "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" - - mock "github.com/stretchr/testify/mock" -) - -// Config is an autogenerated mock type for the Config type -type Config struct { - mock.Mock -} - -type Config_Expecter struct { - mock *mock.Mock -} - -func (_m *Config) EXPECT() *Config_Expecter { - return &Config_Expecter{mock: &_m.Mock} -} - -// ChainType provides a mock function with given fields: -func (_m *Config) ChainType() chaintype.ChainType { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ChainType") - } - - var r0 chaintype.ChainType - if rf, ok := ret.Get(0).(func() chaintype.ChainType); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(chaintype.ChainType) - } - - return r0 -} - -// Config_ChainType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainType' -type Config_ChainType_Call struct { - *mock.Call -} - -// ChainType is a helper method to define mock.On call -func (_e *Config_Expecter) ChainType() *Config_ChainType_Call { - return &Config_ChainType_Call{Call: _e.mock.On("ChainType")} -} - -func (_c *Config_ChainType_Call) Run(run func()) *Config_ChainType_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_ChainType_Call) Return(_a0 chaintype.ChainType) *Config_ChainType_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_ChainType_Call) RunAndReturn(run func() chaintype.ChainType) *Config_ChainType_Call { - _c.Call.Return(run) - return _c -} - -// FinalityDepth provides a mock function with given fields: -func (_m *Config) FinalityDepth() uint32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for FinalityDepth") - } - - var r0 uint32 - if rf, ok := ret.Get(0).(func() uint32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(uint32) - } - - return r0 -} - -// Config_FinalityDepth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FinalityDepth' -type Config_FinalityDepth_Call struct { - *mock.Call -} - -// FinalityDepth is a helper method to define mock.On call -func (_e *Config_Expecter) FinalityDepth() *Config_FinalityDepth_Call { - return &Config_FinalityDepth_Call{Call: _e.mock.On("FinalityDepth")} -} - -func (_c *Config_FinalityDepth_Call) Run(run func()) *Config_FinalityDepth_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_FinalityDepth_Call) Return(_a0 uint32) *Config_FinalityDepth_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_FinalityDepth_Call) RunAndReturn(run func() uint32) *Config_FinalityDepth_Call { - _c.Call.Return(run) - return _c -} - -// FinalityTagEnabled provides a mock function with given fields: -func (_m *Config) FinalityTagEnabled() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for FinalityTagEnabled") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Config_FinalityTagEnabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FinalityTagEnabled' -type Config_FinalityTagEnabled_Call struct { - *mock.Call -} - -// FinalityTagEnabled is a helper method to define mock.On call -func (_e *Config_Expecter) FinalityTagEnabled() *Config_FinalityTagEnabled_Call { - return &Config_FinalityTagEnabled_Call{Call: _e.mock.On("FinalityTagEnabled")} -} - -func (_c *Config_FinalityTagEnabled_Call) Run(run func()) *Config_FinalityTagEnabled_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_FinalityTagEnabled_Call) Return(_a0 bool) *Config_FinalityTagEnabled_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_FinalityTagEnabled_Call) RunAndReturn(run func() bool) *Config_FinalityTagEnabled_Call { - _c.Call.Return(run) - return _c -} - -// NewConfig creates a new instance of Config. 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 NewConfig(t interface { - mock.TestingT - Cleanup(func()) -}) *Config { - mock := &Config{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/gas/mocks/evm_fee_estimator.go b/core/chains/evm/gas/mocks/evm_fee_estimator.go index a9adc261ce3..a7deca2c639 100644 --- a/core/chains/evm/gas/mocks/evm_fee_estimator.go +++ b/core/chains/evm/gas/mocks/evm_fee_estimator.go @@ -7,6 +7,8 @@ import ( assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + common "github.com/ethereum/go-ethereum/common" + context "context" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -145,14 +147,14 @@ func (_c *EvmFeeEstimator_Close_Call) RunAndReturn(run func() error) *EvmFeeEsti return _c } -// GetFee provides a mock function with given fields: ctx, calldata, feeLimit, maxFeePrice, opts -func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...types.Opt) (gas.EvmFee, uint64, error) { +// 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) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] } var _ca []interface{} - _ca = append(_ca, ctx, calldata, feeLimit, maxFeePrice) + _ca = append(_ca, ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -163,23 +165,23 @@ 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, ...types.Opt) (gas.EvmFee, uint64, error)); ok { - return rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.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, ...types.Opt) gas.EvmFee); ok { - r0 = rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.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, ...types.Opt) uint64); ok { - r1 = rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.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, ...types.Opt) error); ok { - r2 = rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) error); ok { + r2 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r2 = ret.Error(2) } @@ -197,43 +199,45 @@ type EvmFeeEstimator_GetFee_Call struct { // - calldata []byte // - feeLimit uint64 // - maxFeePrice *assets.Wei +// - fromAddress *common.Address +// - toAddress *common.Address // - opts ...types.Opt -func (_e *EvmFeeEstimator_Expecter) GetFee(ctx interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, opts ...interface{}) *EvmFeeEstimator_GetFee_Call { +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}, opts...)...)} + 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, 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 ...types.Opt)) *EvmFeeEstimator_GetFee_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-4) - for i, a := range args[4:] { + variadicArgs := make([]types.Opt, len(args)-6) + for i, a := range args[6:] { if a != nil { variadicArgs[i] = a.(types.Opt) } } - run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), variadicArgs...) + run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), args[4].(*common.Address), args[5].(*common.Address), variadicArgs...) }) return _c } -func (_c *EvmFeeEstimator_GetFee_Call) Return(fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) *EvmFeeEstimator_GetFee_Call { - _c.Call.Return(fee, chainSpecificFeeLimit, err) +func (_c *EvmFeeEstimator_GetFee_Call) Return(fee gas.EvmFee, estimatedFeeLimit uint64, err error) *EvmFeeEstimator_GetFee_Call { + _c.Call.Return(fee, estimatedFeeLimit, err) return _c } -func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, ...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, ...types.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, opts -func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...types.Opt) (*big.Int, error) { +// 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) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] } var _ca []interface{} - _ca = append(_ca, ctx, amount, calldata, feeLimit, maxFeePrice) + _ca = append(_ca, ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -243,19 +247,19 @@ 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, ...types.Opt) (*big.Int, error)); ok { - return rf(ctx, amount, calldata, feeLimit, maxFeePrice, opts...) + 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 { + 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, ...types.Opt) *big.Int); ok { - r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, 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 { + r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, ...types.Opt) error); ok { - r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) error); ok { + r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r1 = ret.Error(1) } @@ -274,21 +278,23 @@ type EvmFeeEstimator_GetMaxCost_Call struct { // - calldata []byte // - feeLimit uint64 // - maxFeePrice *assets.Wei +// - fromAddress *common.Address +// - toAddress *common.Address // - opts ...types.Opt -func (_e *EvmFeeEstimator_Expecter) GetMaxCost(ctx interface{}, amount interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, opts ...interface{}) *EvmFeeEstimator_GetMaxCost_Call { +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}, opts...)...)} + 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, 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 ...types.Opt)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-5) - for i, a := range args[5:] { + variadicArgs := make([]types.Opt, len(args)-7) + for i, a := range args[7:] { if a != nil { variadicArgs[i] = a.(types.Opt) } } - run(args[0].(context.Context), args[1].(assets.Eth), args[2].([]byte), args[3].(uint64), args[4].(*assets.Wei), variadicArgs...) + 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...) }) return _c } @@ -298,7 +304,7 @@ 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, ...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, ...types.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/gas/mocks/fee_estimator_client.go b/core/chains/evm/gas/mocks/fee_estimator_client.go index 8e10107597f..f5ca52ec920 100644 --- a/core/chains/evm/gas/mocks/fee_estimator_client.go +++ b/core/chains/evm/gas/mocks/fee_estimator_client.go @@ -241,6 +241,123 @@ func (_c *FeeEstimatorClient_ConfiguredChainID_Call) RunAndReturn(run func() *bi return _c } +// EstimateGas provides a mock function with given fields: ctx, call +func (_m *FeeEstimatorClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { + ret := _m.Called(ctx, call) + + if len(ret) == 0 { + panic("no return value specified for EstimateGas") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) (uint64, error)); ok { + return rf(ctx, call) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) uint64); ok { + r0 = rf(ctx, call) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg) error); ok { + r1 = rf(ctx, call) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeEstimatorClient_EstimateGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGas' +type FeeEstimatorClient_EstimateGas_Call struct { + *mock.Call +} + +// EstimateGas is a helper method to define mock.On call +// - ctx context.Context +// - call ethereum.CallMsg +func (_e *FeeEstimatorClient_Expecter) EstimateGas(ctx interface{}, call interface{}) *FeeEstimatorClient_EstimateGas_Call { + return &FeeEstimatorClient_EstimateGas_Call{Call: _e.mock.On("EstimateGas", ctx, call)} +} + +func (_c *FeeEstimatorClient_EstimateGas_Call) Run(run func(ctx context.Context, call ethereum.CallMsg)) *FeeEstimatorClient_EstimateGas_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ethereum.CallMsg)) + }) + return _c +} + +func (_c *FeeEstimatorClient_EstimateGas_Call) Return(_a0 uint64, _a1 error) *FeeEstimatorClient_EstimateGas_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeEstimatorClient_EstimateGas_Call) RunAndReturn(run func(context.Context, ethereum.CallMsg) (uint64, error)) *FeeEstimatorClient_EstimateGas_Call { + _c.Call.Return(run) + return _c +} + +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *FeeEstimatorClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeEstimatorClient_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type FeeEstimatorClient_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *FeeEstimatorClient_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *FeeEstimatorClient_FeeHistory_Call { + return &FeeEstimatorClient_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *FeeEstimatorClient_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *FeeEstimatorClient_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *FeeEstimatorClient_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *FeeEstimatorClient_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *FeeEstimatorClient_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *FeeEstimatorClient_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // HeadByNumber provides a mock function with given fields: ctx, n func (_m *FeeEstimatorClient) HeadByNumber(ctx context.Context, n *big.Int) (*types.Head, error) { ret := _m.Called(ctx, n) @@ -300,6 +417,64 @@ func (_c *FeeEstimatorClient_HeadByNumber_Call) RunAndReturn(run func(context.Co return _c } +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *FeeEstimatorClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for SuggestGasPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeEstimatorClient_SuggestGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasPrice' +type FeeEstimatorClient_SuggestGasPrice_Call struct { + *mock.Call +} + +// SuggestGasPrice is a helper method to define mock.On call +// - ctx context.Context +func (_e *FeeEstimatorClient_Expecter) SuggestGasPrice(ctx interface{}) *FeeEstimatorClient_SuggestGasPrice_Call { + return &FeeEstimatorClient_SuggestGasPrice_Call{Call: _e.mock.On("SuggestGasPrice", ctx)} +} + +func (_c *FeeEstimatorClient_SuggestGasPrice_Call) Run(run func(ctx context.Context)) *FeeEstimatorClient_SuggestGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *FeeEstimatorClient_SuggestGasPrice_Call) Return(_a0 *big.Int, _a1 error) *FeeEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeEstimatorClient_SuggestGasPrice_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *FeeEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(run) + return _c +} + // NewFeeEstimatorClient creates a new instance of FeeEstimatorClient. 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 NewFeeEstimatorClient(t interface { diff --git a/core/chains/evm/gas/mocks/fee_history_estimator_client.go b/core/chains/evm/gas/mocks/fee_history_estimator_client.go new file mode 100644 index 00000000000..74862145016 --- /dev/null +++ b/core/chains/evm/gas/mocks/fee_history_estimator_client.go @@ -0,0 +1,157 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + ethereum "github.com/ethereum/go-ethereum" + + mock "github.com/stretchr/testify/mock" +) + +// FeeHistoryEstimatorClient is an autogenerated mock type for the feeHistoryEstimatorClient type +type FeeHistoryEstimatorClient struct { + mock.Mock +} + +type FeeHistoryEstimatorClient_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeHistoryEstimatorClient) EXPECT() *FeeHistoryEstimatorClient_Expecter { + return &FeeHistoryEstimatorClient_Expecter{mock: &_m.Mock} +} + +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *FeeHistoryEstimatorClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeHistoryEstimatorClient_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type FeeHistoryEstimatorClient_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *FeeHistoryEstimatorClient_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *FeeHistoryEstimatorClient_FeeHistory_Call { + return &FeeHistoryEstimatorClient_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *FeeHistoryEstimatorClient_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *FeeHistoryEstimatorClient_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *FeeHistoryEstimatorClient_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *FeeHistoryEstimatorClient_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *FeeHistoryEstimatorClient_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *FeeHistoryEstimatorClient_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *FeeHistoryEstimatorClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for SuggestGasPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeHistoryEstimatorClient_SuggestGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasPrice' +type FeeHistoryEstimatorClient_SuggestGasPrice_Call struct { + *mock.Call +} + +// SuggestGasPrice is a helper method to define mock.On call +// - ctx context.Context +func (_e *FeeHistoryEstimatorClient_Expecter) SuggestGasPrice(ctx interface{}) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + return &FeeHistoryEstimatorClient_SuggestGasPrice_Call{Call: _e.mock.On("SuggestGasPrice", ctx)} +} + +func (_c *FeeHistoryEstimatorClient_SuggestGasPrice_Call) Run(run func(ctx context.Context)) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *FeeHistoryEstimatorClient_SuggestGasPrice_Call) Return(_a0 *big.Int, _a1 error) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeHistoryEstimatorClient_SuggestGasPrice_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeHistoryEstimatorClient creates a new instance of FeeHistoryEstimatorClient. 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 NewFeeHistoryEstimatorClient(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeHistoryEstimatorClient { + mock := &FeeHistoryEstimatorClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 1ff8b66b1d0..cac6efb7271 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" @@ -26,6 +25,9 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) +// EstimateGasBuffer is a multiplier applied to estimated gas when the EstimateLimit feature is enabled +const EstimateGasBuffer = float32(1.15) + // EvmFeeEstimator provides a unified interface that wraps EvmEstimator and can determine if legacy or dynamic fee estimation should be used type EvmFeeEstimator interface { services.Service @@ -33,11 +35,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, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.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, 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 ...feetypes.Opt) (*big.Int, error) } type feeEstimatorClient interface { @@ -46,10 +48,13 @@ type feeEstimatorClient interface { CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error ConfiguredChainID() *big.Int HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) + EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) + SuggestGasPrice(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) } // NewEstimator returns the estimator for a given config -func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, geCfg evmconfig.GasEstimator) (EvmFeeEstimator, error) { +func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, chaintype chaintype.ChainType, geCfg evmconfig.GasEstimator) (EvmFeeEstimator, error) { bh := geCfg.BlockHistory() s := geCfg.Mode() lggr.Infow(fmt.Sprintf("Initializing EVM gas estimator in mode: %s", s), @@ -70,14 +75,16 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, "tipCapMin", geCfg.TipCapMin(), "priceMax", geCfg.PriceMax(), "priceMin", geCfg.PriceMin(), + "estimateLimit", geCfg.EstimateLimit(), + "daOracleAddress", geCfg.DAOracle().OracleAddress(), ) df := geCfg.EIP1559DynamicFees() // create l1Oracle only if it is supported for the chain var l1Oracle rollups.L1Oracle - if rollups.IsRollupWithL1Support(cfg.ChainType()) { + if rollups.IsRollupWithL1Support(chaintype) { var err error - l1Oracle, err = rollups.NewL1GasOracle(lggr, ethClient, cfg.ChainType()) + l1Oracle, err = rollups.NewL1GasOracle(lggr, ethClient, chaintype, geCfg.DAOracle()) if err != nil { return nil, fmt.Errorf("failed to initialize L1 oracle: %w", err) } @@ -94,7 +101,7 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, } case "BlockHistory": newEstimator = func(l logger.Logger) EvmEstimator { - return NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bh, ethClient.ConfiguredChainID(), l1Oracle) + return NewBlockHistoryEstimator(lggr, ethClient, chaintype, geCfg, bh, ethClient.ConfiguredChainID(), l1Oracle) } case "FixedPrice": newEstimator = func(l logger.Logger) EvmEstimator { @@ -104,19 +111,31 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, newEstimator = func(l logger.Logger) EvmEstimator { return NewSuggestedPriceEstimator(lggr, ethClient, geCfg, l1Oracle) } + case "FeeHistory": + newEstimator = func(l logger.Logger) EvmEstimator { + ccfg := FeeHistoryEstimatorConfig{ + BumpPercent: geCfg.BumpPercent(), + CacheTimeout: geCfg.FeeHistory().CacheTimeout(), + EIP1559: geCfg.EIP1559DynamicFees(), + BlockHistorySize: uint64(geCfg.BlockHistory().BlockHistorySize()), + RewardPercentile: float64(geCfg.BlockHistory().TransactionPercentile()), + } + return NewFeeHistoryEstimator(lggr, ethClient, ccfg, ethClient.ConfiguredChainID(), l1Oracle) + } + default: lggr.Warnf("GasEstimator: unrecognised mode '%s', falling back to FixedPriceEstimator", s) newEstimator = func(l logger.Logger) EvmEstimator { return NewFixedPriceEstimator(geCfg, ethClient, bh, lggr, l1Oracle) } } - return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg), nil + return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg, ethClient), nil } // DynamicFee encompasses both FeeCap and TipCap for EIP1559 transactions type DynamicFee struct { - FeeCap *assets.Wei - TipCap *assets.Wei + GasFeeCap *assets.Wei + GasTipCap *assets.Wei } type EvmPriorAttempt struct { @@ -158,20 +177,16 @@ type EvmEstimator interface { var _ feetypes.Fee = (*EvmFee)(nil) type EvmFee struct { - // legacy fees - Legacy *assets.Wei - - // dynamic/EIP1559 fees - DynamicFeeCap *assets.Wei - DynamicTipCap *assets.Wei + GasPrice *assets.Wei + DynamicFee } func (fee EvmFee) String() string { - return fmt.Sprintf("{Legacy: %s, DynamicFeeCap: %s, DynamicTipCap: %s}", fee.Legacy, fee.DynamicFeeCap, fee.DynamicTipCap) + return fmt.Sprintf("{GasPrice: %s, GasFeeCap: %s, GasTipCap: %s}", fee.GasPrice, fee.GasFeeCap, fee.GasTipCap) } func (fee EvmFee) ValidDynamic() bool { - return fee.DynamicFeeCap != nil && fee.DynamicTipCap != nil + return fee.GasFeeCap != nil && fee.GasTipCap != nil } // evmFeeEstimator provides a struct that wraps the EVM specific dynamic and legacy estimators into one estimator that conforms to the generic FeeEstimator @@ -181,17 +196,19 @@ type evmFeeEstimator struct { EvmEstimator EIP1559Enabled bool geCfg GasEstimatorConfig + ethClient feeEstimatorClient } var _ EvmFeeEstimator = (*evmFeeEstimator)(nil) -func NewEvmFeeEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, geCfg GasEstimatorConfig) EvmFeeEstimator { +func NewEvmFeeEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, geCfg GasEstimatorConfig, ethClient feeEstimatorClient) EvmFeeEstimator { lggr = logger.Named(lggr, "WrappedEvmEstimator") return &evmFeeEstimator{ lggr: lggr, EvmEstimator: newEstimator(lggr), EIP1559Enabled: eip1559Enabled, geCfg: geCfg, + ethClient: ethClient, } } @@ -261,7 +278,10 @@ func (e *evmFeeEstimator) L1Oracle() rollups.L1Oracle { return e.EvmEstimator.L1Oracle() } -func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint64, err error) { +// 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) { + var chainSpecificFeeLimit uint64 // get dynamic fee if e.EIP1559Enabled { var dynamicFee DynamicFee @@ -269,33 +289,32 @@ func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit if err != nil { return } - chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) - fee.DynamicFeeCap = dynamicFee.FeeCap - fee.DynamicTipCap = dynamicFee.TipCap - return - } - - // get legacy fee - fee.Legacy, chainSpecificFeeLimit, err = e.EvmEstimator.GetLegacyGas(ctx, calldata, feeLimit, maxFeePrice, opts...) - if err != nil { - return + fee.GasFeeCap = dynamicFee.GasFeeCap + fee.GasTipCap = dynamicFee.GasTipCap + chainSpecificFeeLimit = feeLimit + } else { + // get legacy fee + fee.GasPrice, chainSpecificFeeLimit, err = e.EvmEstimator.GetLegacyGas(ctx, calldata, feeLimit, maxFeePrice, opts...) + if err != nil { + return + } } - chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(chainSpecificFeeLimit, e.geCfg.LimitMultiplier()) + estimatedFeeLimit, err = e.estimateFeeLimit(ctx, chainSpecificFeeLimit, calldata, fromAddress, toAddress) return } -func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (*big.Int, error) { - fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, opts...) +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) { + fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) if err != nil { return nil, err } var gasPrice *assets.Wei if e.EIP1559Enabled { - gasPrice = fees.DynamicFeeCap + gasPrice = fees.GasFeeCap } else { - gasPrice = fees.Legacy + gasPrice = fees.GasPrice } fee := new(big.Int).Mul(gasPrice.ToInt(), big.NewInt(int64(gasLimit))) @@ -305,8 +324,8 @@ func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, cal func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLimit uint64, maxFeePrice *assets.Wei, attempts []EvmPriorAttempt) (bumpedFee EvmFee, chainSpecificFeeLimit uint64, err error) { // validate only 1 fee type is present - if (!originalFee.ValidDynamic() && originalFee.Legacy == nil) || (originalFee.ValidDynamic() && originalFee.Legacy != nil) { - err = pkgerrors.New("only one dynamic or legacy fee can be defined") + if (!originalFee.ValidDynamic() && originalFee.GasPrice == nil) || (originalFee.ValidDynamic() && originalFee.GasPrice != nil) { + err = pkgerrors.New("only one dynamic or gas price fee can be defined") return } @@ -316,20 +335,20 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi var bumpedDynamic DynamicFee bumpedDynamic, err = e.EvmEstimator.BumpDynamicFee(ctx, DynamicFee{ - TipCap: originalFee.DynamicTipCap, - FeeCap: originalFee.DynamicFeeCap, + GasTipCap: originalFee.GasTipCap, + GasFeeCap: originalFee.GasFeeCap, }, maxFeePrice, attempts) if err != nil { return } chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) - bumpedFee.DynamicFeeCap = bumpedDynamic.FeeCap - bumpedFee.DynamicTipCap = bumpedDynamic.TipCap + bumpedFee.GasFeeCap = bumpedDynamic.GasFeeCap + bumpedFee.GasTipCap = bumpedDynamic.GasTipCap return } // bump legacy fee - bumpedFee.Legacy, chainSpecificFeeLimit, err = e.EvmEstimator.BumpLegacyGas(ctx, originalFee.Legacy, feeLimit, maxFeePrice, attempts) + bumpedFee.GasPrice, chainSpecificFeeLimit, err = e.EvmEstimator.BumpLegacyGas(ctx, originalFee.GasPrice, feeLimit, maxFeePrice, attempts) if err != nil { return } @@ -337,11 +356,54 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi return } -// Config defines an interface for configuration in the gas package -type Config interface { - ChainType() chaintype.ChainType - FinalityDepth() uint32 - FinalityTagEnabled() bool +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()) + if err != nil { + return estimatedFeeLimit, err + } + // Use provided fee limit by default if EstimateLimit is disabled + if !e.geCfg.EstimateLimit() { + return providedGasLimit, nil + } + // Create call msg for gas limit estimation + // Skip setting Gas to avoid capping the results of the estimation + callMsg := ethereum.CallMsg{ + To: toAddress, + Data: calldata, + } + if fromAddress != nil { + callMsg.From = *fromAddress + } + estimatedGas, estimateErr := e.ethClient.EstimateGas(ctx, callMsg) + if estimateErr != nil { + if providedGasLimit > 0 { + // Do not return error if estimate gas failed, we can still use the provided limit instead since it is an upper limit + e.lggr.Errorw("failed to estimate gas limit. falling back to the provided gas limit with multiplier", "callMsg", callMsg, "providedGasLimitWithMultiplier", providedGasLimit, "error", estimateErr) + return providedGasLimit, nil + } + return estimatedFeeLimit, fmt.Errorf("gas estimation failed and provided gas limit is 0: %w", estimateErr) + } + e.lggr.Debugw("estimated gas", "estimatedGas", estimatedGas, "providedGasLimitWithMultiplier", providedGasLimit) + // Return error if estimated gas without the buffer exceeds the provided gas limit, if provided + // 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 + } + // Apply EstimateGasBuffer to the estimated gas limit + estimatedFeeLimit, err = commonfee.ApplyMultiplier(estimatedGas, EstimateGasBuffer) + if err != nil { + return + } + // If provided gas limit is not 0, fallback to it if the buffer causes the estimated gas limit to exceed it + // The provided gas limit should be used as an upper bound to avoid unexpected behavior for products + if providedGasLimit > 0 && estimatedFeeLimit > providedGasLimit { + e.lggr.Debugw("estimated gas limit with buffer exceeds the provided gas limit with multiplier. falling back to the provided gas limit with multiplier", "estimatedGasLimit", estimatedFeeLimit, "providedGasLimitWithMultiplier", providedGasLimit) + estimatedFeeLimit = providedGasLimit + } + + return } type GasEstimatorConfig interface { @@ -358,36 +420,7 @@ type GasEstimatorConfig interface { PriceMin() *assets.Wei PriceMax() *assets.Wei Mode() string -} - -type BlockHistoryConfig interface { - evmconfig.BlockHistory -} - -// Int64ToHex converts an int64 into go-ethereum's hex representation -func Int64ToHex(n int64) string { - return hexutil.EncodeBig(big.NewInt(n)) -} - -// HexToInt64 performs the inverse of Int64ToHex -// Returns 0 on invalid input -func HexToInt64(input interface{}) int64 { - switch v := input.(type) { - case string: - big, err := hexutil.DecodeBig(v) - if err != nil { - return 0 - } - return big.Int64() - case []byte: - big, err := hexutil.DecodeBig(string(v)) - if err != nil { - return 0 - } - return big.Int64() - default: - return 0 - } + EstimateLimit() bool } // BumpLegacyGasPriceOnly will increase the price @@ -445,7 +478,7 @@ func BumpDynamicFeeOnly(config bumpConfig, feeCapBufferBlocks uint16, lggr logge // See: https://github.com/ethereum/go-ethereum/issues/24284 func bumpDynamicFee(cfg bumpConfig, feeCapBufferBlocks uint16, lggr logger.SugaredLogger, currentTipCap, currentBaseFee *assets.Wei, originalFee DynamicFee, maxGasPriceWei *assets.Wei) (bumpedFee DynamicFee, err error) { maxGasPrice := getMaxGasPrice(maxGasPriceWei, cfg.PriceMax()) - baselineTipCap := assets.MaxWei(originalFee.TipCap, cfg.TipCapDefault()) + baselineTipCap := assets.MaxWei(originalFee.GasTipCap, cfg.TipCapDefault()) bumpedTipCap := bumpFeePrice(baselineTipCap, cfg.BumpPercent(), cfg.BumpMin()) // Update bumpedTipCap if currentTipCap is higher than bumpedTipCap and within maxGasPrice @@ -453,20 +486,20 @@ func bumpDynamicFee(cfg bumpConfig, feeCapBufferBlocks uint16, lggr logger.Sugar 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", - bumpedTipCap.String(), maxGasPrice, originalFee.TipCap.String(), originalFee.FeeCap.String(), label.NodeConnectivityProblemWarning) - } else if bumpedTipCap.Cmp(originalFee.TipCap) <= 0 { + 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."+ " ACTION REQUIRED: This is a configuration error, you must increase either "+ - "EVM.GasEstimator.BumpPercent or EVM.GasEstimator.BumpMin", bumpedTipCap.String(), originalFee.TipCap.String()) + "EVM.GasEstimator.BumpPercent or EVM.GasEstimator.BumpMin", bumpedTipCap.String(), originalFee.GasTipCap.String()) } // Always bump the FeeCap by at least the bump percentage (should be greater than or // equal to than geth's configured bump minimum which is 10%) // See: https://github.com/ethereum/go-ethereum/blob/bff330335b94af3643ac2fb809793f77de3069d4/core/tx_list.go#L298 - bumpedFeeCap := bumpFeePrice(originalFee.FeeCap, cfg.BumpPercent(), cfg.BumpMin()) + bumpedFeeCap := bumpFeePrice(originalFee.GasFeeCap, cfg.BumpPercent(), cfg.BumpMin()) if currentBaseFee != nil { if currentBaseFee.Cmp(maxGasPrice) > 0 { @@ -479,10 +512,10 @@ 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", - bumpedFeeCap.String(), maxGasPrice, originalFee.TipCap.String(), originalFee.FeeCap.String(), label.NodeConnectivityProblemWarning) + bumpedFeeCap.String(), maxGasPrice, originalFee.GasTipCap.String(), originalFee.GasFeeCap.String(), label.NodeConnectivityProblemWarning) } - return DynamicFee{FeeCap: bumpedFeeCap, TipCap: bumpedTipCap}, nil + return DynamicFee{GasFeeCap: bumpedFeeCap, GasTipCap: bumpedTipCap}, nil } func bumpFeePrice(originalFeePrice *assets.Wei, feeBumpPercent uint16, feeBumpUnits *assets.Wei) *assets.Wei { diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index 92ea901596f..936a4810569 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -1,6 +1,7 @@ package gas_test import ( + "errors" "math/big" "testing" @@ -12,12 +13,15 @@ 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/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" ) func TestWrappedEvmEstimator(t *testing.T) { @@ -28,16 +32,16 @@ func TestWrappedEvmEstimator(t *testing.T) { gasLimit := uint64(10) legacyFee := assets.NewWeiI(10) dynamicFee := gas.DynamicFee{ - FeeCap: assets.NewWeiI(20), - TipCap: assets.NewWeiI(1), + GasFeeCap: assets.NewWeiI(20), + GasTipCap: assets.NewWeiI(1), } limitMultiplier := float32(1.5) est := mocks.NewEvmEstimator(t) est.On("GetDynamicFee", mock.Anything, mock.Anything). - Return(dynamicFee, nil).Twice() + Return(dynamicFee, nil).Times(6) est.On("GetLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything). - Return(legacyFee, gasLimit, nil).Twice() + Return(legacyFee, gasLimit, nil).Times(6) est.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(dynamicFee, nil).Once() est.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). @@ -49,6 +53,9 @@ func TestWrappedEvmEstimator(t *testing.T) { mockEstimatorName := "WrappedEvmEstimator" mockEvmEstimatorName := "WrappedEvmEstimator.MockEstimator" + fromAddress := testutils.NewAddress() + toAddress := testutils.NewAddress() + // L1Oracle returns the correct L1Oracle interface t.Run("L1Oracle", func(t *testing.T) { lggr := logger.Test(t) @@ -59,16 +66,17 @@ func TestWrappedEvmEstimator(t *testing.T) { getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } // expect nil - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, nil, nil) l1Oracle := estimator.L1Oracle() assert.Nil(t, l1Oracle) // expect l1Oracle - oracle, err := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock) + daOracle := rollups.CreateTestDAOracle(t, toml.DAOracleOPStack, "0x420000000000000000000000000000000000000F", "") + oracle, err := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) // cast oracle to L1Oracle interface - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) evmEstimator.On("L1Oracle").Return(oracle).Once() l1Oracle = estimator.L1Oracle() @@ -80,57 +88,55 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - fee, max, err := estimator.GetFee(ctx, nil, 0, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + fee, max, err := estimator.GetFee(ctx, nil, 0, nil, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) - assert.True(t, legacyFee.Equal(fee.Legacy)) - assert.Nil(t, fee.DynamicTipCap) - assert.Nil(t, fee.DynamicFeeCap) + assert.True(t, legacyFee.Equal(fee.GasPrice)) + assert.Nil(t, fee.GasTipCap) + assert.Nil(t, fee.GasFeeCap) // expect dynamic fee data dynamicFees = true - estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil) + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) - assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) - assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap)) - assert.Nil(t, fee.Legacy) + assert.True(t, dynamicFee.GasFeeCap.Equal(fee.GasFeeCap)) + assert.True(t, dynamicFee.GasTipCap.Equal(fee.GasTipCap)) + assert.Nil(t, fee.GasPrice) }) // BumpFee returns bumped fee type based on original fee calculation t.Run("BumpFee", func(t *testing.T) { lggr := logger.Test(t) dynamicFees := false - estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) // expect legacy fee data - fee, max, err := estimator.BumpFee(ctx, gas.EvmFee{Legacy: assets.NewWeiI(0)}, 0, nil, nil) + fee, max, err := estimator.BumpFee(ctx, gas.EvmFee{GasPrice: assets.NewWeiI(0)}, 0, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) - assert.True(t, legacyFee.Equal(fee.Legacy)) - assert.Nil(t, fee.DynamicTipCap) - assert.Nil(t, fee.DynamicFeeCap) + assert.True(t, legacyFee.Equal(fee.GasPrice)) + assert.Nil(t, fee.GasTipCap) + assert.Nil(t, fee.GasFeeCap) // expect dynamic fee data fee, max, err = estimator.BumpFee(ctx, gas.EvmFee{ - DynamicFeeCap: assets.NewWeiI(0), - DynamicTipCap: assets.NewWeiI(0), + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(0), GasTipCap: assets.NewWeiI(0)}, }, gasLimit, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) - assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) - assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap)) - assert.Nil(t, fee.Legacy) + assert.True(t, dynamicFee.GasFeeCap.Equal(fee.GasFeeCap)) + assert.True(t, dynamicFee.GasTipCap.Equal(fee.GasTipCap)) + assert.Nil(t, fee.GasPrice) // expect error _, _, err = estimator.BumpFee(ctx, gas.EvmFee{}, 0, nil, nil) assert.Error(t, err) _, _, err = estimator.BumpFee(ctx, gas.EvmFee{ - Legacy: legacyFee, - DynamicFeeCap: dynamicFee.FeeCap, - DynamicTipCap: dynamicFee.TipCap, + GasPrice: legacyFee, + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWeiI(0), GasTipCap: assets.NewWeiI(0)}, }, 0, nil, nil) assert.Error(t, err) }) @@ -141,8 +147,8 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect legacy fee data dynamicFees := false - estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil, nil) require.NoError(t, err) fee := new(big.Int).Mul(legacyFee.ToInt(), big.NewInt(int64(gasLimit))) fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil) @@ -150,10 +156,10 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil, nil) require.NoError(t, err) - fee = new(big.Int).Mul(dynamicFee.FeeCap.ToInt(), big.NewInt(int64(gasLimit))) + fee = new(big.Int).Mul(dynamicFee.GasFeeCap.ToInt(), big.NewInt(10)) fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil) assert.Equal(t, new(big.Int).Add(val.ToInt(), fee), total) }) @@ -166,7 +172,7 @@ func TestWrappedEvmEstimator(t *testing.T) { estimator := gas.NewEvmFeeEstimator(lggr, func(logger.Logger) gas.EvmEstimator { return evmEstimator - }, false, geCfg) + }, false, geCfg, nil) require.Equal(t, mockEstimatorName, estimator.Name()) require.Equal(t, mockEvmEstimatorName, evmEstimator.Name()) @@ -185,7 +191,7 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator.On("L1Oracle", mock.Anything).Return(nil).Twice() - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err := estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() @@ -193,7 +199,7 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator.On("L1Oracle", mock.Anything).Return(oracle).Twice() - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err = estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() @@ -210,11 +216,11 @@ func TestWrappedEvmEstimator(t *testing.T) { oracle.On("Ready").Return(nil).Twice() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err := estimator.Ready() require.NoError(t, err) - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err = estimator.Ready() require.NoError(t, err) }) @@ -235,7 +241,7 @@ func TestWrappedEvmEstimator(t *testing.T) { oracle.On("HealthReport").Return(map[string]error{oracleKey: oracleError}).Once() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) report := estimator.HealthReport() require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError)) require.Nil(t, report[oracleKey]) @@ -243,10 +249,160 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator.On("L1Oracle").Return(oracle).Once() - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) report = estimator.HealthReport() require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError)) require.True(t, pkgerrors.Is(report[oracleKey], oracleError)) require.NotNil(t, report[mockEstimatorName]) }) + + t.Run("GetFee, estimate gas limit enabled, succeeds", func(t *testing.T) { + estimatedGasLimit := uint64(5) + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, legacyFee.Equal(fee.GasPrice)) + assert.Nil(t, fee.GasTipCap) + assert.Nil(t, fee.GasFeeCap) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, dynamicFee.GasFeeCap.Equal(fee.GasFeeCap)) + assert.True(t, dynamicFee.GasTipCap.Equal(fee.GasTipCap)) + assert.Nil(t, fee.GasPrice) + }) + + t.Run("GetFee, estimate gas limit enabled, estimate exceeds provided limit, returns error", func(t *testing.T) { + estimatedGasLimit := uint64(100) + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(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) + + // 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) + }) + + t.Run("GetFee, estimate gas limit enabled, buffer exceeds provided limit, fallsback to provided limit", func(t *testing.T) { + estimatedGasLimit := uint64(15) // same as provided limit + lggr := logger.Test(t) + dynamicFees := false // expect legacy fee data + geCfg.EstimateLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, legacyFee.Equal(fee.GasPrice)) + assert.Nil(t, fee.GasTipCap) + assert.Nil(t, fee.GasFeeCap) + + dynamicFees = true // expect dynamic fee data + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, dynamicFee.GasFeeCap.Equal(fee.GasFeeCap)) + assert.True(t, dynamicFee.GasTipCap.Equal(fee.GasTipCap)) + assert.Nil(t, fee.GasPrice) + }) + + t.Run("GetFee, estimate gas limit enabled, RPC fails and fallsback to provided gas limit", func(t *testing.T) { + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, legacyFee.Equal(fee.GasPrice)) + assert.Nil(t, fee.GasTipCap) + assert.Nil(t, fee.GasFeeCap) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, dynamicFee.GasFeeCap.Equal(fee.GasFeeCap)) + assert.True(t, dynamicFee.GasTipCap.Equal(fee.GasTipCap)) + assert.Nil(t, fee.GasPrice) + }) + + t.Run("GetFee, estimate gas limit enabled, provided fee limit 0, returns uncapped estimation", func(t *testing.T) { + est.On("GetDynamicFee", mock.Anything, mock.Anything). + Return(dynamicFee, nil).Once() + est.On("GetLegacyGas", mock.Anything, mock.Anything, uint64(0), mock.Anything). + Return(legacyFee, uint64(0), nil).Once() + estimatedGasLimit := uint64(100) // same as provided limit + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err := estimator.GetFee(ctx, []byte{}, uint64(0), nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, legacyFee.Equal(fee.GasPrice)) + assert.Nil(t, fee.GasTipCap) + assert.Nil(t, fee.GasFeeCap) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, 0, nil, &fromAddress, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, dynamicFee.GasFeeCap.Equal(fee.GasFeeCap)) + assert.True(t, dynamicFee.GasTipCap.Equal(fee.GasTipCap)) + assert.Nil(t, fee.GasPrice) + }) + + t.Run("GetFee, estimate gas limit enabled, provided fee limit 0, returns error on failure", func(t *testing.T) { + est.On("GetDynamicFee", mock.Anything, mock.Anything). + Return(dynamicFee, nil).Once() + est.On("GetLegacyGas", mock.Anything, mock.Anything, uint64(0), mock.Anything). + Return(legacyFee, uint64(0), nil).Once() + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + _, _, err := estimator.GetFee(ctx, []byte{}, 0, nil, &fromAddress, &toAddress) + require.Error(t, err) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + _, _, err = estimator.GetFee(ctx, []byte{}, 0, nil, &fromAddress, &toAddress) + require.Error(t, err) + }) } diff --git a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go index c01244db70c..e332d31125f 100644 --- a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go +++ b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go @@ -13,15 +13,11 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) type ArbL1GasOracle interface { @@ -35,7 +31,6 @@ type arbitrumL1Oracle struct { client l1OracleClient pollPeriod time.Duration logger logger.SugaredLogger - chainType chaintype.ChainType l1GasPriceAddress string gasPriceMethod string @@ -93,7 +88,6 @@ func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) (*arbi client: ethClient, pollPeriod: PollPeriod, logger: logger.Sugared(logger.Named(lggr, "L1GasOracle(arbitrum)")), - chainType: chaintype.ChainArbitrum, l1GasPriceAddress: l1GasPriceAddress, gasPriceMethod: gasPriceMethod, @@ -180,24 +174,18 @@ func (o *arbitrumL1Oracle) fetchL1GasPrice(ctx context.Context) (price *big.Int, precompile := common.HexToAddress(o.l1GasPriceAddress) callData, err = o.l1GasPriceMethodAbi.Pack(o.gasPriceMethod) if err != nil { - errMsg := "failed to pack calldata for arbitrum L1 gas price method" - o.logger.Errorf(errMsg) - return nil, fmt.Errorf("%s: %w", errMsg, err) + return nil, fmt.Errorf("failed to pack calldata for arbitrum L1 gas price method: %w", err) } b, err = o.client.CallContract(ctx, ethereum.CallMsg{ To: &precompile, Data: callData, }, nil) if err != nil { - errMsg := "gas oracle contract call failed" - o.logger.Errorf(errMsg) - return nil, fmt.Errorf("%s: %w", errMsg, err) + return nil, fmt.Errorf("gas oracle contract call failed: %w", err) } if len(b) != 32 { // returns uint256; - errMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 32) - o.logger.Criticalf(errMsg) - return nil, fmt.Errorf(errMsg) + return nil, fmt.Errorf("return data length (%d) different than expected (%d)", len(b), 32) } price = new(big.Int).SetBytes(b) return price, nil @@ -225,41 +213,6 @@ func (o *arbitrumL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, return } -// Gets the L1 gas cost for the provided transaction at the specified block num -// If block num is not provided, the value on the latest block num is used -func (o *arbitrumL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { - ctx, cancel := context.WithTimeout(ctx, client.QueryTimeout) - defer cancel() - var callData, b []byte - var err error - - if callData, err = o.l1GasCostMethodAbi.Pack(o.gasCostMethod, tx.To(), false, tx.Data()); err != nil { - return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) - } - - precompile := common.HexToAddress(o.l1GasCostAddress) - b, err = o.client.CallContract(ctx, ethereum.CallMsg{ - To: &precompile, - Data: callData, - }, blockNum) - if err != nil { - errorMsg := fmt.Sprintf("gas oracle contract call failed: %v", err) - o.logger.Errorf(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - - var l1GasCost *big.Int - - if len(b) != 8+2*32 { // returns (uint64 gasEstimateForL1, uint256 baseFee, uint256 l1BaseFeeEstimate); - errorMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 8+2*32) - o.logger.Critical(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - l1GasCost = new(big.Int).SetBytes(b[:8]) - - return assets.NewWei(l1GasCost), nil -} - // callGetPricesInArbGas calls ArbGasInfo.getPricesInArbGas() on the precompile contract ArbGasInfoAddress. // // @return (per L2 tx, per L1 calldata unit, per storage allocation) diff --git a/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go b/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go new file mode 100644 index 00000000000..f0c2036e49b --- /dev/null +++ b/core/chains/evm/gas/rollups/custom_calldata_da_oracle.go @@ -0,0 +1,169 @@ +package rollups + +import ( + "context" + "encoding/hex" + "errors" + "fmt" + "math/big" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/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" +) + +type customCalldataDAOracle struct { + services.StateMachine + client l1OracleClient + pollPeriod time.Duration + logger logger.SugaredLogger + + daOracleConfig evmconfig.DAOracle + daGasPriceMu sync.RWMutex + daGasPrice priceEntry + + chInitialized chan struct{} + chStop services.StopChan + chDone chan struct{} +} + +// NewCustomCalldataDAOracle creates a new custom calldata DA oracle. The CustomCalldataDAOracle fetches gas price from +// whatever function is specified in the DAOracle's CustomGasPriceCalldata field. This allows for more flexibility when +// chains have custom DA gas calculation methods. +func NewCustomCalldataDAOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, daOracleConfig evmconfig.DAOracle) (*customCalldataDAOracle, error) { + if daOracleConfig.OracleType() != toml.DAOracleCustomCalldata { + return nil, fmt.Errorf("expected %s oracle type, got %s", toml.DAOracleCustomCalldata, daOracleConfig.OracleType()) + } + if daOracleConfig.CustomGasPriceCalldata() == "" { + return nil, errors.New("CustomGasPriceCalldata is required") + } + return &customCalldataDAOracle{ + client: ethClient, + pollPeriod: PollPeriod, + logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("CustomCalldataDAOracle(%s)", chainType))), + + daOracleConfig: daOracleConfig, + + chInitialized: make(chan struct{}), + chStop: make(chan struct{}), + chDone: make(chan struct{}), + }, nil +} + +func (o *customCalldataDAOracle) Name() string { + return o.logger.Name() +} + +func (o *customCalldataDAOracle) Start(_ context.Context) error { + return o.StartOnce(o.Name(), func() error { + go o.run() + <-o.chInitialized + return nil + }) +} + +func (o *customCalldataDAOracle) Close() error { + return o.StopOnce(o.Name(), func() error { + close(o.chStop) + <-o.chDone + return nil + }) +} + +func (o *customCalldataDAOracle) HealthReport() map[string]error { + return map[string]error{o.Name(): o.Healthy()} +} + +func (o *customCalldataDAOracle) run() { + defer close(o.chDone) + + o.refresh() + close(o.chInitialized) + + t := services.TickerConfig{ + Initial: o.pollPeriod, + JitterPct: services.DefaultJitter, + }.NewTicker(o.pollPeriod) + defer t.Stop() + + for { + select { + case <-o.chStop: + return + case <-t.C: + o.refresh() + } + } +} + +func (o *customCalldataDAOracle) refresh() { + err := o.refreshWithError() + if err != nil { + o.logger.Criticalw("Failed to refresh gas price", "err", err) + o.SvcErrBuffer.Append(err) + } +} + +func (o *customCalldataDAOracle) refreshWithError() error { + ctx, cancel := o.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + price, err := o.getCustomCalldataGasPrice(ctx) + if err != nil { + return err + } + + o.daGasPriceMu.Lock() + defer o.daGasPriceMu.Unlock() + o.daGasPrice = priceEntry{price: assets.NewWei(price), timestamp: time.Now()} + return nil +} + +func (o *customCalldataDAOracle) GasPrice(_ context.Context) (daGasPrice *assets.Wei, err error) { + var timestamp time.Time + ok := o.IfStarted(func() { + o.daGasPriceMu.RLock() + daGasPrice = o.daGasPrice.price + timestamp = o.daGasPrice.timestamp + o.daGasPriceMu.RUnlock() + }) + if !ok { + return daGasPrice, errors.New("DAGasOracle is not started; cannot estimate gas") + } + if daGasPrice == nil { + return daGasPrice, errors.New("failed to get DA gas price; gas price not set") + } + // Validate the price has been updated within the pollPeriod * 2 + // Allowing double the poll period before declaring the price stale to give ample time for the refresh to process + if time.Since(timestamp) > o.pollPeriod*2 { + return daGasPrice, errors.New("gas price is stale") + } + return +} + +func (o *customCalldataDAOracle) getCustomCalldataGasPrice(ctx context.Context) (*big.Int, error) { + daOracleAddress := o.daOracleConfig.OracleAddress().Address() + calldata := strings.TrimPrefix(o.daOracleConfig.CustomGasPriceCalldata(), "0x") + calldataBytes, err := hex.DecodeString(calldata) + if err != nil { + return nil, fmt.Errorf("failed to decode custom fee method calldata: %w", err) + } + b, err := o.client.CallContract(ctx, ethereum.CallMsg{ + To: &daOracleAddress, + Data: calldataBytes, + }, nil) + if err != nil { + return nil, fmt.Errorf("custom fee method call failed: %w", err) + } + return new(big.Int).SetBytes(b), nil +} diff --git a/core/chains/evm/gas/rollups/custom_calldata_da_oracle_test.go b/core/chains/evm/gas/rollups/custom_calldata_da_oracle_test.go new file mode 100644 index 00000000000..3dcb08d9aeb --- /dev/null +++ b/core/chains/evm/gas/rollups/custom_calldata_da_oracle_test.go @@ -0,0 +1,102 @@ +package rollups + +import ( + "errors" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +func TestCustomCalldataDAOracle_NewCustomCalldata(t *testing.T) { + oracleAddress := utils.RandomAddress().String() + t.Parallel() + + t.Run("throws error if oracle type is not custom_calldata", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + _, err := NewCustomCalldataDAOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracleConfig) + require.Error(t, err) + }) + + t.Run("throws error if CustomGasPriceCalldata is empty", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleCustomCalldata, oracleAddress, "") + _, err := NewCustomCalldataDAOracle(logger.Test(t), ethClient, chaintype.ChainCelo, daOracleConfig) + require.Error(t, err) + }) + + t.Run("correctly creates custom calldata DA oracle", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + calldata := "0x0000000000000000000000000000000000001234" + + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleCustomCalldata, oracleAddress, calldata) + oracle, err := NewCustomCalldataDAOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracleConfig) + require.NoError(t, err) + require.NotNil(t, oracle) + }) +} + +func TestCustomCalldataDAOracle_getCustomCalldataGasPrice(t *testing.T) { + oracleAddress := utils.RandomAddress().String() + t.Parallel() + + t.Run("correctly fetches gas price if DA oracle config has custom calldata", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + expectedPriceHex := "0x32" // 50 + + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleCustomCalldata, oracleAddress, "0x0000000000000000000000000000000000001234") + oracle, err := NewCustomCalldataDAOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracleConfig) + require.NoError(t, err) + + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + callMsg := args.Get(1).(ethereum.CallMsg) + blockNumber := args.Get(2).(*big.Int) + require.NotNil(t, callMsg.To) + require.Equal(t, oracleAddress, callMsg.To.String()) + require.Nil(t, blockNumber) + }).Return(hexutil.MustDecode(expectedPriceHex), nil).Once() + + price, err := oracle.getCustomCalldataGasPrice(tests.Context(t)) + require.NoError(t, err) + require.Equal(t, big.NewInt(50), price) + }) + + t.Run("throws error if custom calldata fails to decode", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleCustomCalldata, oracleAddress, "0xblahblahblah") + oracle, err := NewCustomCalldataDAOracle(logger.Test(t), ethClient, chaintype.ChainCelo, daOracleConfig) + require.NoError(t, err) + + _, err = oracle.getCustomCalldataGasPrice(tests.Context(t)) + require.Error(t, err) + }) + + t.Run("throws error if CallContract call fails", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleCustomCalldata, oracleAddress, "0x0000000000000000000000000000000000000000000000000000000000000032") + oracle, err := NewCustomCalldataDAOracle(logger.Test(t), ethClient, chaintype.ChainCelo, daOracleConfig) + require.NoError(t, err) + + ethClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("RPC failure")).Once() + + _, err = oracle.getCustomCalldataGasPrice(tests.Context(t)) + require.Error(t, err) + }) +} diff --git a/core/chains/evm/gas/rollups/da_oracle_test_helper.go b/core/chains/evm/gas/rollups/da_oracle_test_helper.go new file mode 100644 index 00000000000..6dfa96d3118 --- /dev/null +++ b/core/chains/evm/gas/rollups/da_oracle_test_helper.go @@ -0,0 +1,39 @@ +package rollups + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type TestDAOracle struct { + toml.DAOracle +} + +func (d *TestDAOracle) OracleType() toml.DAOracleType { + return d.DAOracle.OracleType +} + +func (d *TestDAOracle) OracleAddress() *types.EIP55Address { + return d.DAOracle.OracleAddress +} + +func (d *TestDAOracle) CustomGasPriceCalldata() string { + return d.DAOracle.CustomGasPriceCalldata +} + +func CreateTestDAOracle(t *testing.T, oracleType toml.DAOracleType, oracleAddress string, customGasPriceCalldata string) *TestDAOracle { + oracleAddr, err := types.NewEIP55Address(oracleAddress) + require.NoError(t, err) + + return &TestDAOracle{ + DAOracle: toml.DAOracle{ + OracleType: oracleType, + OracleAddress: &oracleAddr, + CustomGasPriceCalldata: customGasPriceCalldata, + }, + } +} diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index f707fab6841..00ca8c47cb0 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -8,7 +8,6 @@ import ( "time" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -16,7 +15,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "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" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ) // L1Oracle provides interface for fetching L1-specific fee components if the chain is an L2. @@ -25,7 +26,6 @@ type L1Oracle interface { services.Service GasPrice(ctx context.Context) (*assets.Wei, error) - GetGasCost(ctx context.Context, tx *types.Transaction, blockNum *big.Int) (*assets.Wei, error) } type l1OracleClient interface { @@ -43,21 +43,39 @@ const ( PollPeriod = 6 * time.Second ) -var supportedChainTypes = []chaintype.ChainType{chaintype.ChainArbitrum, chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll, chaintype.ChainZkSync} +var supportedChainTypes = []chaintype.ChainType{chaintype.ChainArbitrum, chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll, chaintype.ChainZkSync, chaintype.ChainMantle} func IsRollupWithL1Support(chainType chaintype.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) } -func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) (L1Oracle, error) { +func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, daOracle evmconfig.DAOracle) (L1Oracle, error) { if !IsRollupWithL1Support(chainType) { return nil, nil } var l1Oracle L1Oracle var err error + if daOracle != nil { + switch daOracle.OracleType() { + case toml.DAOracleOPStack: + l1Oracle, err = NewOpStackL1GasOracle(lggr, ethClient, chainType, daOracle) + case toml.DAOracleArbitrum: + l1Oracle, err = NewArbitrumL1GasOracle(lggr, ethClient) + case toml.DAOracleZKSync: + l1Oracle = NewZkSyncL1GasOracle(lggr, ethClient) + case toml.DAOracleCustomCalldata: + l1Oracle, err = NewCustomCalldataDAOracle(lggr, ethClient, chainType, daOracle) + } + if err != nil { + return nil, fmt.Errorf("failed to initialize L1 oracle for chaintype %s: %w", chainType, err) + } + if l1Oracle != nil { + return l1Oracle, nil + } + } + + // Going forward all configs should specify a DAOracle config. This is a fall back to maintain backwards compat. switch chainType { - case chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll: - l1Oracle, err = NewOpStackL1GasOracle(lggr, ethClient, chainType) case chaintype.ChainArbitrum: l1Oracle, err = NewArbitrumL1GasOracle(lggr, ethClient) case chaintype.ChainZkSync: diff --git a/core/chains/evm/gas/rollups/l1_oracle_test.go b/core/chains/evm/gas/rollups/l1_oracle_test.go index 7a28523d396..5c8dac1b4f6 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/l1_oracle_test.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -20,6 +19,7 @@ import ( "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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) @@ -30,10 +30,39 @@ func TestL1Oracle(t *testing.T) { t.Run("Unsupported ChainType returns nil", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, utils.RandomAddress().String(), "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo, daOracle) require.NoError(t, err) assert.Nil(t, oracle) }) + + t.Run("DAOracle config is nil, falls back to using chainType", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, nil) + require.NoError(t, err) + assert.NotNil(t, oracle) + }) + + t.Run("DAOracle config is not nil, but OracleType is empty, falls back to using chainType arbitrum", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + + daOracle := CreateTestDAOracle(t, "", utils.RandomAddress().String(), "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracle) + require.NoError(t, err) + assert.NotNil(t, oracle) + assert.Equal(t, oracle.Name(), "L1GasOracle(arbitrum)") + }) + + t.Run("DAOracle config is not nil, but OracleType is empty, falls back to using chainType ZKSync", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + + daOracle := CreateTestDAOracle(t, "", utils.RandomAddress().String(), "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracle) + require.NoError(t, err) + assert.NotNil(t, oracle) + assert.Equal(t, oracle.Name(), "L1GasOracle(zkSync)") + }) } func TestL1Oracle_GasPrice(t *testing.T) { @@ -42,7 +71,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { t.Run("Calling GasPrice on unstarted L1Oracle returns error", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, utils.RandomAddress().String(), "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GasPrice(tests.Context(t)) @@ -65,7 +95,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) + daOracle := CreateTestDAOracle(t, toml.DAOracleArbitrum, "0x0000000000000000000000000000000000000000", "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracle) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -81,7 +112,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - ethClient := setupUpgradeCheck(t, KromaGasOracleAddress, false, false) // Ecotone, Fjord disabled + oracleAddress := utils.RandomAddress().String() + ethClient := setupUpgradeCheck(t, oracleAddress, false, false) // Ecotone, Fjord disabled ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) @@ -93,7 +125,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma, daOracle) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -109,7 +142,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - ethClient := setupUpgradeCheck(t, OPGasOracleAddress, false, false) // Ecotone, Fjord disabled + oracleAddress := utils.RandomAddress().String() + ethClient := setupUpgradeCheck(t, oracleAddress, false, false) // Ecotone, Fjord disabled ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) @@ -121,7 +155,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -136,7 +171,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - ethClient := setupUpgradeCheck(t, ScrollGasOracleAddress, false, false) // Ecotone, Fjord disabled + oracleAddress := utils.RandomAddress().String() + ethClient := setupUpgradeCheck(t, oracleAddress, false, false) // Ecotone, Fjord disabled ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) @@ -148,7 +184,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll, daOracle) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -185,7 +222,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(gasPerPubByteL2).Bytes(), nil) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync) + daOracle := CreateTestDAOracle(t, toml.DAOracleZKSync, utils.RandomAddress().String(), "") + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracle) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -194,130 +232,30 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Equal(t, assets.NewWei(new(big.Int).Mul(gasPriceL2, gasPerPubByteL2)), gasPrice) }) -} - -func TestL1Oracle_GetGasCost(t *testing.T) { - t.Parallel() - - t.Run("Calling GetGasCost on started Arbitrum L1Oracle returns Arbitrum getL1Fee", func(t *testing.T) { - l1GasCost := big.NewInt(100) - baseFee := utils.Uint256ToBytes32(big.NewInt(1000)) - l1BaseFeeEstimate := utils.Uint256ToBytes32(big.NewInt(500)) - blockNum := big.NewInt(1000) - toAddress := utils.RandomAddress() - callData := []byte{1, 2, 3, 4, 5, 6, 7} - l1GasCostMethodAbi, err := abi.JSON(strings.NewReader(GasEstimateL1ComponentAbiString)) - require.NoError(t, err) - - tx := types.NewTx(&types.LegacyTx{ - Nonce: 42, - To: &toAddress, - Data: callData, - }) - result := common.LeftPadBytes(l1GasCost.Bytes(), 8) - result = append(result, baseFee...) - result = append(result, l1BaseFeeEstimate...) + t.Run("Calling GasPrice on started CustomCalldata L1Oracle returns CustomCalldata l1GasPrice", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - var payload []byte - payload, err = l1GasCostMethodAbi.Pack("gasEstimateL1Component", toAddress, false, callData) - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - require.Equal(t, blockNum, blockNumber) - }).Return(result, nil) - - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) - require.NoError(t, err) - - gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) - require.NoError(t, err) - require.Equal(t, assets.NewWei(l1GasCost), gasCost) - }) - - t.Run("Calling GetGasCost on started Kroma L1Oracle returns error", func(t *testing.T) { - blockNum := big.NewInt(1000) - tx := types.NewTx(&types.LegacyTx{}) + mockedPrice := big.NewInt(30) + oracleAddress := utils.RandomAddress().String() - ethClient := mocks.NewL1OracleClient(t) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma) - require.NoError(t, err) - - _, err = oracle.GetGasCost(tests.Context(t), tx, blockNum) - require.Error(t, err, "L1 gas cost not supported for this chain: kroma") - }) - - t.Run("Calling GetGasCost on started OPStack L1Oracle returns OPStack getL1Fee", func(t *testing.T) { - l1GasCost := big.NewInt(100) - blockNum := big.NewInt(1000) - toAddress := utils.RandomAddress() - callData := []byte{1, 2, 3} - l1GasCostMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) - require.NoError(t, err) - - tx := types.NewTx(&types.LegacyTx{ - Nonce: 42, - To: &toAddress, - Data: callData, - }) - - encodedTx, err := tx.MarshalBinary() - require.NoError(t, err) - - ethClient := mocks.NewL1OracleClient(t) ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - var payload []byte - payload, err = l1GasCostMethodAbi.Pack("getL1Fee", encodedTx) - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - require.Equal(t, blockNum, blockNumber) - }).Return(common.BigToHash(l1GasCost).Bytes(), nil) - - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) - require.NoError(t, err) + require.NotNil(t, callMsg.To) + require.Equal(t, oracleAddress, callMsg.To.String()) + require.Nil(t, blockNumber) + }).Return(common.BigToHash(mockedPrice).Bytes(), nil).Once() - gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) - require.NoError(t, err) - require.Equal(t, assets.NewWei(l1GasCost), gasCost) - }) - - t.Run("Calling GetGasCost on started Scroll L1Oracle returns Scroll getL1Fee", func(t *testing.T) { - l1GasCost := big.NewInt(100) - blockNum := big.NewInt(1000) - toAddress := utils.RandomAddress() - callData := []byte{1, 2, 3} - l1GasCostMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) - require.NoError(t, err) - - tx := types.NewTx(&types.LegacyTx{ - Nonce: 42, - To: &toAddress, - Data: callData, - }) - - encodedTx, err := tx.MarshalBinary() - require.NoError(t, err) - - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - var payload []byte - payload, err = l1GasCostMethodAbi.Pack("getL1Fee", encodedTx) - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - require.Equal(t, blockNum, blockNumber) - }).Return(common.BigToHash(l1GasCost).Bytes(), nil) + daOracleConfig := CreateTestDAOracle(t, toml.DAOracleCustomCalldata, oracleAddress, "0x0000000000000000000000000000000000001234") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) + // chainType here shouldn't matter for now since we're checking daOracleConfig oracle type first. Later + // we can consider limiting the chainType to only those that support custom calldata. + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracleConfig) require.NoError(t, err) + servicetest.RunHealthy(t, oracle) - gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) + price, err := oracle.GasPrice(tests.Context(t)) require.NoError(t, err) - require.Equal(t, assets.NewWei(l1GasCost), gasCost) + require.Equal(t, assets.NewWei(mockedPrice), price) }) } diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle.go b/core/chains/evm/gas/rollups/mocks/l1_oracle.go index e82cb4ee903..747df06e83a 100644 --- a/core/chains/evm/gas/rollups/mocks/l1_oracle.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle.go @@ -3,15 +3,11 @@ package mocks import ( - big "math/big" + context "context" assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - context "context" - mock "github.com/stretchr/testify/mock" - - types "github.com/ethereum/go-ethereum/core/types" ) // L1Oracle is an autogenerated mock type for the L1Oracle type @@ -130,66 +126,6 @@ func (_c *L1Oracle_GasPrice_Call) RunAndReturn(run func(context.Context) (*asset return _c } -// GetGasCost provides a mock function with given fields: ctx, tx, blockNum -func (_m *L1Oracle) GetGasCost(ctx context.Context, tx *types.Transaction, blockNum *big.Int) (*assets.Wei, error) { - ret := _m.Called(ctx, tx, blockNum) - - if len(ret) == 0 { - panic("no return value specified for GetGasCost") - } - - var r0 *assets.Wei - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, *big.Int) (*assets.Wei, error)); ok { - return rf(ctx, tx, blockNum) - } - if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, *big.Int) *assets.Wei); ok { - r0 = rf(ctx, tx, blockNum) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*assets.Wei) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *types.Transaction, *big.Int) error); ok { - r1 = rf(ctx, tx, blockNum) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// L1Oracle_GetGasCost_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetGasCost' -type L1Oracle_GetGasCost_Call struct { - *mock.Call -} - -// GetGasCost is a helper method to define mock.On call -// - ctx context.Context -// - tx *types.Transaction -// - blockNum *big.Int -func (_e *L1Oracle_Expecter) GetGasCost(ctx interface{}, tx interface{}, blockNum interface{}) *L1Oracle_GetGasCost_Call { - return &L1Oracle_GetGasCost_Call{Call: _e.mock.On("GetGasCost", ctx, tx, blockNum)} -} - -func (_c *L1Oracle_GetGasCost_Call) Run(run func(ctx context.Context, tx *types.Transaction, blockNum *big.Int)) *L1Oracle_GetGasCost_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*types.Transaction), args[2].(*big.Int)) - }) - return _c -} - -func (_c *L1Oracle_GetGasCost_Call) Return(_a0 *assets.Wei, _a1 error) *L1Oracle_GetGasCost_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *L1Oracle_GetGasCost_Call) RunAndReturn(run func(context.Context, *types.Transaction, *big.Int) (*assets.Wei, error)) *L1Oracle_GetGasCost_Call { - _c.Call.Return(run) - return _c -} - // HealthReport provides a mock function with given fields: func (_m *L1Oracle) HealthReport() map[string]error { ret := _m.Called() diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 6805cd7095b..4f1e8c67cb7 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -14,14 +14,12 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) @@ -31,14 +29,13 @@ type optimismL1Oracle struct { client l1OracleClient pollPeriod time.Duration logger logger.SugaredLogger - chainType chaintype.ChainType - l1OracleAddress string - l1GasPriceMu sync.RWMutex - l1GasPrice priceEntry - isEcotone bool - isFjord bool - upgradeCheckTs time.Time + daOracleConfig evmconfig.DAOracle + l1GasPriceMu sync.RWMutex + l1GasPrice priceEntry + isEcotone bool + isFjord bool + upgradeCheckTs time.Time chInitialised chan struct{} chStop services.StopChan @@ -50,6 +47,7 @@ type optimismL1Oracle struct { blobBaseFeeCalldata []byte blobBaseFeeScalarCalldata []byte decimalsCalldata []byte + tokenRatioCalldata []byte isEcotoneCalldata []byte isEcotoneMethodAbi abi.ABI isFjordCalldata []byte @@ -87,30 +85,9 @@ const ( // decimals is a hex encoded call to: // `function decimals() public pure returns (uint256);` decimalsMethod = "decimals" - // OPGasOracleAddress is the address of the precompiled contract that exists on Optimism and Base. - OPGasOracleAddress = "0x420000000000000000000000000000000000000F" - // KromaGasOracleAddress is the address of the precompiled contract that exists on Kroma. - KromaGasOracleAddress = "0x4200000000000000000000000000000000000005" - // ScrollGasOracleAddress is the address of the precompiled contract that exists on Scroll. - ScrollGasOracleAddress = "0x5300000000000000000000000000000000000002" ) -func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) (*optimismL1Oracle, error) { - var precompileAddress string - switch chainType { - case chaintype.ChainOptimismBedrock: - precompileAddress = OPGasOracleAddress - case chaintype.ChainKroma: - precompileAddress = KromaGasOracleAddress - case chaintype.ChainScroll: - precompileAddress = ScrollGasOracleAddress - default: - return nil, fmt.Errorf("received unsupported chaintype %s", chainType) - } - return newOpStackL1GasOracle(lggr, ethClient, chainType, precompileAddress) -} - -func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, precompileAddress string) (*optimismL1Oracle, error) { +func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, daOracle evmconfig.DAOracle) (*optimismL1Oracle, error) { getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) if err != nil { return nil, fmt.Errorf("failed to parse L1 gas cost method ABI for chain: %s", chainType) @@ -118,71 +95,43 @@ func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy // encode calldata for each method; these calldata will remain the same for each call, we can encode them just once // Encode calldata for l1BaseFee method - l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", l1BaseFeeMethod, chainType, err) - } - l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(l1BaseFeeMethod) + l1BaseFeeCalldata, _, err := encodeCalldata(L1BaseFeeAbiString, l1BaseFeeMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", l1BaseFeeMethod, chainType, err) } // Encode calldata for isEcotone method - isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", isEcotoneMethod, chainType, err) - } - isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(isEcotoneMethod) + isEcotoneCalldata, isEcotoneMethodAbi, err := encodeCalldata(OPIsEcotoneAbiString, isEcotoneMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", isEcotoneMethod, chainType, err) } // Encode calldata for isFjord method - isFjordMethodAbi, err := abi.JSON(strings.NewReader(OPIsFjordAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", isFjordMethod, chainType, err) - } - isFjordCalldata, err := isFjordMethodAbi.Pack(isFjordMethod) + isFjordCalldata, isFjordMethodAbi, err := encodeCalldata(OPIsFjordAbiString, isFjordMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", isFjordMethod, chainType, err) } // Encode calldata for baseFeeScalar method - baseFeeScalarMethodAbi, err := abi.JSON(strings.NewReader(OPBaseFeeScalarAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", baseFeeScalarMethod, chainType, err) - } - baseFeeScalarCalldata, err := baseFeeScalarMethodAbi.Pack(baseFeeScalarMethod) + baseFeeScalarCalldata, _, err := encodeCalldata(OPBaseFeeScalarAbiString, baseFeeScalarMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", baseFeeScalarMethod, chainType, err) } // Encode calldata for blobBaseFee method - blobBaseFeeMethodAbi, err := abi.JSON(strings.NewReader(OPBlobBaseFeeAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", blobBaseFeeMethod, chainType, err) - } - blobBaseFeeCalldata, err := blobBaseFeeMethodAbi.Pack(blobBaseFeeMethod) + blobBaseFeeCalldata, _, err := encodeCalldata(OPBlobBaseFeeAbiString, blobBaseFeeMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", blobBaseFeeMethod, chainType, err) } // Encode calldata for blobBaseFeeScalar method - blobBaseFeeScalarMethodAbi, err := abi.JSON(strings.NewReader(OPBlobBaseFeeScalarAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", blobBaseFeeScalarMethod, chainType, err) - } - blobBaseFeeScalarCalldata, err := blobBaseFeeScalarMethodAbi.Pack(blobBaseFeeScalarMethod) + blobBaseFeeScalarCalldata, _, err := encodeCalldata(OPBlobBaseFeeScalarAbiString, blobBaseFeeScalarMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", blobBaseFeeScalarMethod, chainType, err) } // Encode calldata for decimals method - decimalsMethodAbi, err := abi.JSON(strings.NewReader(OPDecimalsAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", decimalsMethod, chainType, err) - } - decimalsCalldata, err := decimalsMethodAbi.Pack(decimalsMethod) + decimalsCalldata, _, err := encodeCalldata(OPDecimalsAbiString, decimalsMethod) if err != nil { return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", decimalsMethod, chainType, err) } @@ -191,12 +140,11 @@ func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy client: ethClient, pollPeriod: PollPeriod, logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("L1GasOracle(%s)", chainType))), - chainType: chainType, - l1OracleAddress: precompileAddress, - isEcotone: false, - isFjord: false, - upgradeCheckTs: time.Time{}, + daOracleConfig: daOracle, + isEcotone: false, + isFjord: false, + upgradeCheckTs: time.Time{}, chInitialised: make(chan struct{}), chStop: make(chan struct{}), @@ -259,6 +207,7 @@ func (o *optimismL1Oracle) run() { } } } + func (o *optimismL1Oracle) refresh() { err := o.refreshWithError() if err != nil { @@ -304,47 +253,6 @@ func (o *optimismL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, return } -// Gets the L1 gas cost for the provided transaction at the specified block num -// If block num is not provided, the value on the latest block num is used -func (o *optimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { - ctx, cancel := context.WithTimeout(ctx, client.QueryTimeout) - defer cancel() - var callData, b []byte - var err error - if o.chainType == chaintype.ChainKroma { - return nil, fmt.Errorf("L1 gas cost not supported for this chain: %s", o.chainType) - } - // Append rlp-encoded tx - var encodedtx []byte - if encodedtx, err = tx.MarshalBinary(); err != nil { - return nil, fmt.Errorf("failed to marshal tx for gas cost estimation: %w", err) - } - if callData, err = o.getL1FeeMethodAbi.Pack(getL1FeeMethod, encodedtx); err != nil { - return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) - } - - precompile := common.HexToAddress(o.l1OracleAddress) - b, err = o.client.CallContract(ctx, ethereum.CallMsg{ - To: &precompile, - Data: callData, - }, blockNum) - if err != nil { - errorMsg := fmt.Sprintf("gas oracle contract call failed: %v", err) - o.logger.Errorf(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - - var l1GasCost *big.Int - if len(b) != 32 { // returns uint256; - errorMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 32) - o.logger.Critical(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - l1GasCost = new(big.Int).SetBytes(b) - - return assets.NewWei(l1GasCost), nil -} - func (o *optimismL1Oracle) GetDAGasPrice(ctx context.Context) (*big.Int, error) { err := o.checkForUpgrade(ctx) if err != nil { @@ -375,7 +283,7 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.isFjordCalldata), }, "latest", @@ -387,7 +295,7 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.isEcotoneCalldata), }, "latest", @@ -428,7 +336,7 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { } func (o *optimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) { - l1OracleAddress := common.HexToAddress(o.l1OracleAddress) + l1OracleAddress := o.daOracleConfig.OracleAddress().Address() b, err := o.client.CallContract(ctx, ethereum.CallMsg{ To: &l1OracleAddress, Data: o.l1BaseFeeCalldata, @@ -452,7 +360,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.l1BaseFeeCalldata), }, "latest", @@ -464,7 +372,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.baseFeeScalarCalldata), }, "latest", @@ -476,7 +384,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.blobBaseFeeCalldata), }, "latest", @@ -488,7 +396,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.blobBaseFeeScalarCalldata), }, "latest", @@ -500,7 +408,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.l1OracleAddress, + "to": o.daOracleConfig.OracleAddress().String(), "data": hexutil.Bytes(o.decimalsCalldata), }, "latest", @@ -583,3 +491,15 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In return new(big.Int).Div(scaledGasPrice, scale), nil } + +func encodeCalldata(abiString, methodName string) ([]byte, abi.ABI, error) { + methodAbi, err := abi.JSON(strings.NewReader(abiString)) + if err != nil { + return nil, abi.ABI{}, fmt.Errorf("failed to parse ABI: %w", err) + } + calldata, err := methodAbi.Pack(methodName) + if err != nil { + return nil, abi.ABI{}, fmt.Errorf("failed to pack calldata for %s: %w", methodName, err) + } + return calldata, methodAbi, nil +} diff --git a/core/chains/evm/gas/rollups/op_l1_oracle_test.go b/core/chains/evm/gas/rollups/op_l1_oracle_test.go index f5f009f1ea6..0b67cc7178d 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -19,7 +19,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) func TestOPL1Oracle_ReadV1GasPrice(t *testing.T) { @@ -101,7 +103,8 @@ func TestOPL1Oracle_ReadV1GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, "0x0000000000000000000000000000000000001234", "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) @@ -215,7 +218,7 @@ func TestOPL1Oracle_CalculateEcotoneGasPrice(t *testing.T) { baseFeeScalar := big.NewInt(10) blobBaseFeeScalar := big.NewInt(5) decimals := big.NewInt(6) - oracleAddress := common.HexToAddress("0x1234").String() + oracleAddress := utils.RandomAddress().String() t.Parallel() @@ -223,7 +226,8 @@ func TestOPL1Oracle_CalculateEcotoneGasPrice(t *testing.T) { ethClient := setupUpgradeCheck(t, oracleAddress, false, true) mockBatchContractCall(t, ethClient, oracleAddress, baseFee, baseFeeScalar, blobBaseFee, blobBaseFeeScalar, decimals) - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) require.NoError(t, err) @@ -242,7 +246,8 @@ func TestOPL1Oracle_CalculateEcotoneGasPrice(t *testing.T) { rpcElements[1].Result = &badData }).Return(nil).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) @@ -252,7 +257,8 @@ func TestOPL1Oracle_CalculateEcotoneGasPrice(t *testing.T) { ethClient := setupUpgradeCheck(t, oracleAddress, false, true) ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) @@ -267,7 +273,8 @@ func TestOPL1Oracle_CalculateEcotoneGasPrice(t *testing.T) { rpcElements[1].Error = fmt.Errorf("revert") }).Return(nil).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) @@ -280,7 +287,7 @@ func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { baseFeeScalar := big.NewInt(10) blobBaseFeeScalar := big.NewInt(5) decimals := big.NewInt(6) - oracleAddress := common.HexToAddress("0x1234").String() + oracleAddress := utils.RandomAddress().String() t.Parallel() @@ -288,7 +295,8 @@ func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { ethClient := setupUpgradeCheck(t, oracleAddress, true, true) mockBatchContractCall(t, ethClient, oracleAddress, baseFee, baseFeeScalar, blobBaseFee, blobBaseFeeScalar, decimals) - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) require.NoError(t, err) @@ -307,7 +315,8 @@ func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { rpcElements[1].Result = &badData }).Return(nil).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) @@ -317,7 +326,8 @@ func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { ethClient := setupUpgradeCheck(t, oracleAddress, true, true) ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) @@ -332,7 +342,8 @@ func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { rpcElements[1].Error = fmt.Errorf("revert") }).Return(nil).Once() - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") + oracle, err := NewOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) require.NoError(t, err) _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) diff --git a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go index 31d93bc587d..94d2e05ac02 100644 --- a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go +++ b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go @@ -15,11 +15,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" ) // Reads L2-specific precompiles and caches the l1GasPrice set by the L2. @@ -28,7 +25,6 @@ type zkSyncL1Oracle struct { client l1OracleClient pollPeriod time.Duration logger logger.SugaredLogger - chainType chaintype.ChainType systemContextAddress string gasPerPubdataMethod string @@ -65,7 +61,6 @@ func NewZkSyncL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) *zkSyncL client: ethClient, pollPeriod: PollPeriod, logger: logger.Sugared(logger.Named(lggr, "L1GasOracle(zkSync)")), - chainType: chaintype.ChainZkSync, systemContextAddress: SystemContextAddress, gasPerPubdataMethod: SystemContext_gasPerPubdataByteMethod, @@ -181,14 +176,6 @@ func (o *zkSyncL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, er return } -// Gets the L1 gas cost for the provided transaction at the specified block num -// If block num is not provided, the value on the latest block num is used -func (o *zkSyncL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { - //Unused method, so not implemented - // And its not possible to know gas consumption of a transaction before its executed, since zkSync only posts the state difference - return nil, fmt.Errorf("unimplemented") -} - // GetL2GasPrice calls SystemContract.gasPrice() on the zksync system precompile contract. // // @return (The current gasPrice on L2: same as tx.gasPrice) diff --git a/core/chains/evm/gas/suggested_price_estimator_test.go b/core/chains/evm/gas/suggested_price_estimator_test.go index e6dbb80df92..97fe0c17a7d 100644 --- a/core/chains/evm/gas/suggested_price_estimator_test.go +++ b/core/chains/evm/gas/suggested_price_estimator_test.go @@ -131,8 +131,8 @@ func TestSuggestedPriceEstimator(t *testing.T) { o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) fee := gas.DynamicFee{ - FeeCap: assets.NewWeiI(42), - TipCap: assets.NewWeiI(5), + GasFeeCap: assets.NewWeiI(42), + GasTipCap: assets.NewWeiI(5), } _, err := o.BumpDynamicFee(tests.Context(t), fee, maxGasPrice, nil) assert.EqualError(t, err, "dynamic fees are not implemented for this estimator") diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go index 7ac61ab34b0..3cd02b3bf05 100644 --- a/core/chains/evm/headtracker/head_broadcaster_test.go +++ b/core/chains/evm/headtracker/head_broadcaster_test.go @@ -55,11 +55,12 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) chchHeaders := make(chan chan<- *evmtypes.Head, 1) - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + chHead := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Run(func(args mock.Arguments) { - chchHeaders <- args.Get(1).(chan<- *evmtypes.Head) + chchHeaders <- chHead }). - Return(sub, nil) + Return((<-chan *evmtypes.Head)(chHead), sub, nil) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(1), nil) sub.On("Unsubscribe").Return() diff --git a/core/chains/evm/headtracker/head_listener_test.go b/core/chains/evm/headtracker/head_listener_test.go index 2e459af2a2b..25902fa6b1a 100644 --- a/core/chains/evm/headtracker/head_listener_test.go +++ b/core/chains/evm/headtracker/head_listener_test.go @@ -27,7 +27,7 @@ func Test_HeadListener_HappyPath(t *testing.T) { t.Parallel() // Logic: // - spawn a listener instance - // - mock SubscribeNewHead/Err/Unsubscribe to track these calls + // - mock SubscribeToHeads/Err/Unsubscribe to track these calls // - send 3 heads // - ask listener to stop // Asserts: @@ -43,13 +43,12 @@ func Test_HeadListener_HappyPath(t *testing.T) { var headCount atomic.Int32 unsubscribeAwaiter := testutils.NewAwaiter() + chHeads := make(chan *evmtypes.Head) subscribeAwaiter := testutils.NewAwaiter() - var chHeads chan<- *evmtypes.Head var chErr = make(chan error) var chSubErr <-chan error = chErr sub := commonmocks.NewSubscription(t) - ethClient.On("SubscribeNewHead", mock.Anything, mock.AnythingOfType("chan<- *types.Head")).Return(sub, nil).Once().Run(func(args mock.Arguments) { - chHeads = args.Get(1).(chan<- *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything).Return((<-chan *evmtypes.Head)(chHeads), sub, nil).Once().Run(func(args mock.Arguments) { subscribeAwaiter.ItHappened() }) sub.On("Err").Return(chSubErr) @@ -97,13 +96,12 @@ func Test_HeadListener_NotReceivingHeads(t *testing.T) { firstHeadAwaiter := testutils.NewAwaiter() + chHeads := make(chan *evmtypes.Head) subscribeAwaiter := testutils.NewAwaiter() - var chHeads chan<- *evmtypes.Head var chErr = make(chan error) var chSubErr <-chan error = chErr sub := commonmocks.NewSubscription(t) - ethClient.On("SubscribeNewHead", mock.Anything, mock.AnythingOfType("chan<- *types.Head")).Return(sub, nil).Once().Run(func(args mock.Arguments) { - chHeads = args.Get(1).(chan<- *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything).Return((<-chan *evmtypes.Head)(chHeads), sub, nil).Once().Run(func(args mock.Arguments) { subscribeAwaiter.ItHappened() }) sub.On("Err").Return(chSubErr) @@ -161,11 +159,10 @@ func Test_HeadListener_SubscriptionErr(t *testing.T) { // initially and once again after exactly one head has been received sub.On("Err").Return(chSubErr).Twice() + headsCh := make(chan *evmtypes.Head) subscribeAwaiter := testutils.NewAwaiter() - var headsCh chan<- *evmtypes.Head // Initial subscribe - ethClient.On("SubscribeNewHead", mock.Anything, mock.AnythingOfType("chan<- *types.Head")).Return(sub, nil).Once().Run(func(args mock.Arguments) { - headsCh = args.Get(1).(chan<- *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything).Return((<-chan *evmtypes.Head)(headsCh), sub, nil).Once().Run(func(args mock.Arguments) { subscribeAwaiter.ItHappened() }) func() { @@ -199,9 +196,8 @@ func Test_HeadListener_SubscriptionErr(t *testing.T) { sub2.On("Err").Return(chSubErr2) subscribeAwaiter2 := testutils.NewAwaiter() - var headsCh2 chan<- *evmtypes.Head - ethClient.On("SubscribeNewHead", mock.Anything, mock.AnythingOfType("chan<- *types.Head")).Return(sub2, nil).Once().Run(func(args mock.Arguments) { - headsCh2 = args.Get(1).(chan<- *evmtypes.Head) + headsCh2 := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything).Return((<-chan *evmtypes.Head)(headsCh2), sub2, nil).Once().Run(func(args mock.Arguments) { subscribeAwaiter2.ItHappened() }) diff --git a/core/chains/evm/headtracker/head_saver.go b/core/chains/evm/headtracker/head_saver.go index 320e88a19bc..f2613334c49 100644 --- a/core/chains/evm/headtracker/head_saver.go +++ b/core/chains/evm/headtracker/head_saver.go @@ -35,13 +35,12 @@ func NewHeadSaver(lggr logger.Logger, orm ORM, config commontypes.Config, htConf } func (hs *headSaver) Save(ctx context.Context, head *evmtypes.Head) error { - if err := hs.orm.IdempotentInsertHead(ctx, head); err != nil { + // adding new head might form a cycle, so it's better to validate cached chain before persisting it + if err := hs.heads.AddHeads(head); err != nil { return err } - hs.heads.AddHeads(head) - - return nil + return hs.orm.IdempotentInsertHead(ctx, head) } func (hs *headSaver) Load(ctx context.Context, latestFinalized int64) (chain *evmtypes.Head, err error) { @@ -51,7 +50,10 @@ func (hs *headSaver) Load(ctx context.Context, latestFinalized int64) (chain *ev return nil, err } - hs.heads.AddHeads(heads...) + err = hs.heads.AddHeads(heads...) + if err != nil { + return nil, fmt.Errorf("failed to populate cache with loaded heads: %w", err) + } return hs.heads.LatestHead(), nil } diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go index 43e79235e90..266172b67df 100644 --- a/core/chains/evm/headtracker/head_saver_test.go +++ b/core/chains/evm/headtracker/head_saver_test.go @@ -42,6 +42,9 @@ func (h *headTrackerConfig) FinalityTagBypass() bool { func (h *headTrackerConfig) MaxAllowedFinalityDepth() uint32 { return 10000 } +func (h *headTrackerConfig) PersistenceEnabled() bool { + return true +} type config struct { finalityDepth uint32 diff --git a/core/chains/evm/headtracker/head_tracker.go b/core/chains/evm/headtracker/head_tracker.go index f7607189f7e..bb39b3b5c79 100644 --- a/core/chains/evm/headtracker/head_tracker.go +++ b/core/chains/evm/headtracker/head_tracker.go @@ -11,14 +11,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/headtracker" commontypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) func NewHeadTracker( lggr logger.Logger, - ethClient evmclient.Client, + ethClient httypes.Client, config commontypes.Config, htConfig commontypes.HeadTrackerConfig, headBroadcaster httypes.HeadBroadcaster, diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 21ff1b1a929..09c6619f90d 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -12,7 +12,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - gethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/jmoiron/sqlx" "github.com/onsi/gomega" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -21,21 +21,16 @@ import ( "go.uber.org/zap/zaptest/observer" "golang.org/x/exp/maps" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" - - "github.com/jmoiron/sqlx" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "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-common/pkg/utils/mailbox/mailboxtest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + commonht "github.com/smartcontractkit/chainlink/v2/common/headtracker" htmocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" commontypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" @@ -45,11 +40,13 @@ 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/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) -func firstHead(t *testing.T, db *sqlx.DB) (h evmtypes.Head) { - if err := db.Get(&h, `SELECT * FROM evm.heads ORDER BY number ASC LIMIT 1`); err != nil { +func firstHead(t *testing.T, db *sqlx.DB) *evmtypes.Head { + h := new(evmtypes.Head) + if err := db.Get(h, `SELECT * FROM evm.heads ORDER BY number ASC LIMIT 1`); err != nil { t.Fatal(err) } return h @@ -66,9 +63,9 @@ func TestHeadTracker_New(t *testing.T) { mockEth := &testutils.MockEth{ EthClient: ethClient, } - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ethClient.On("SubscribeToHeads", mock.Anything, mock.Anything). Maybe(). - Return(mockEth.NewSub(t), nil) + Return(nil, mockEth.NewSub(t), nil) orm := headtracker.NewORM(*testutils.FixtureChainID, db) assert.Nil(t, orm.IdempotentInsertHead(tests.Context(t), testutils.Head(1))) @@ -148,14 +145,13 @@ func TestHeadTracker_Get(t *testing.T) { mockEth := &testutils.MockEth{ EthClient: ethClient, } - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ethClient.On("SubscribeToHeads", mock.Anything). Maybe(). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { defer close(chStarted) - return mockEth.NewSub(t) + return make(<-chan *evmtypes.Head), mockEth.NewSub(t), nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), nil).Maybe() @@ -201,11 +197,12 @@ func TestHeadTracker_Start_NewHeads(t *testing.T) { ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(0), nil).Once() // for backfill ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(0), nil).Maybe() - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ch := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Run(func(mock.Arguments) { close(chStarted) }). - Return(sub, nil) + Return((<-chan *evmtypes.Head)(ch), sub, nil) ht := createHeadTracker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), orm) ht.Start(t) @@ -222,9 +219,9 @@ func TestHeadTracker_Start(t *testing.T) { FinalityTagEnable *bool MaxAllowedFinalityDepth *uint32 FinalityTagBypass *bool + ORM headtracker.ORM } newHeadTracker := func(t *testing.T, opts opts) *headTrackerUniverse { - db := pgtest.NewSqlxDB(t) config := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { if opts.FinalityTagEnable != nil { c.FinalityTagEnabled = opts.FinalityTagEnable @@ -239,12 +236,15 @@ func TestHeadTracker_Start(t *testing.T) { c.HeadTracker.FinalityTagBypass = opts.FinalityTagBypass } }) - orm := headtracker.NewORM(*testutils.FixtureChainID, db) + if opts.ORM == nil { + db := pgtest.NewSqlxDB(t) + opts.ORM = headtracker.NewORM(*testutils.FixtureChainID, db) + } ethClient := evmtest.NewEthClientMockWithDefaultChain(t) mockEth := &testutils.MockEth{EthClient: ethClient} sub := mockEth.NewSub(t) - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Maybe() - return createHeadTracker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), orm) + ethClient.On("SubscribeToHeads", mock.Anything, mock.Anything).Return(nil, sub, nil).Maybe() + return createHeadTracker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), opts.ORM) } t.Run("Starts even if failed to get initialHead", func(t *testing.T) { ht := newHeadTracker(t, opts{}) @@ -271,13 +271,13 @@ func TestHeadTracker_Start(t *testing.T) { head := testutils.Head(1000) ht.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once() ht.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, nil).Once() - ht.ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("failed to connect")).Maybe() + ht.ethClient.On("SubscribeToHeads", mock.Anything, mock.Anything).Return(nil, nil, errors.New("failed to connect")).Maybe() ht.Start(t) tests.AssertLogEventually(t, ht.observer, "Error handling initial head") }) - t.Run("Happy path (finality tag)", func(t *testing.T) { + happyPathFT := func(t *testing.T, opts opts) { head := testutils.Head(1000) - ht := newHeadTracker(t, opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(false)}) + ht := newHeadTracker(t, opts) ctx := tests.Context(t) require.NoError(t, ht.orm.IdempotentInsertHead(ctx, testutils.Head(799))) ht.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once() @@ -286,10 +286,14 @@ func TestHeadTracker_Start(t *testing.T) { ht.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(finalizedHead, nil).Once() // on backfill ht.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, errors.New("backfill call to finalized failed")).Maybe() - ht.ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("failed to connect")).Maybe() + ht.ethClient.On("SubscribeToHeads", mock.Anything, mock.Anything).Return(nil, nil, errors.New("failed to connect")).Maybe() ht.Start(t) - tests.AssertLogEventually(t, ht.observer, "Loaded chain from DB") - }) + tests.AssertLogEventually(t, ht.observer, "Received new head") + tests.AssertEventually(t, func() bool { + latest := ht.headTracker.LatestChain() + return latest != nil && latest.Number == head.Number + }) + } happyPathFD := func(t *testing.T, opts opts) { head := testutils.Head(1000) ht := newHeadTracker(t, opts) @@ -300,30 +304,48 @@ func TestHeadTracker_Start(t *testing.T) { require.NoError(t, ht.orm.IdempotentInsertHead(ctx, testutils.Head(finalizedHead.Number-1))) // on backfill ht.ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(nil, errors.New("backfill call to finalized failed")).Maybe() - ht.ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("failed to connect")).Maybe() + ht.ethClient.On("SubscribeToHeads", mock.Anything, mock.Anything).Return(nil, nil, errors.New("failed to connect")).Maybe() ht.Start(t) - tests.AssertLogEventually(t, ht.observer, "Loaded chain from DB") + tests.AssertLogEventually(t, ht.observer, "Received new head") + tests.AssertEventually(t, func() bool { + latest := ht.headTracker.LatestChain() + return latest != nil && latest.Number == head.Number + }) } testCases := []struct { Name string Opts opts + Run func(t *testing.T, opts opts) }{ { Name: "Happy path (Chain FT is disabled & HeadTracker's FT is disabled)", Opts: opts{FinalityTagEnable: ptr(false), FinalityTagBypass: ptr(true)}, + Run: happyPathFD, }, { Name: "Happy path (Chain FT is disabled & HeadTracker's FT is enabled, but ignored)", Opts: opts{FinalityTagEnable: ptr(false), FinalityTagBypass: ptr(false)}, + Run: happyPathFD, }, { Name: "Happy path (Chain FT is enabled & HeadTracker's FT is disabled)", Opts: opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(true)}, + Run: happyPathFD, + }, + { + Name: "Happy path (Chain FT is enabled)", + Opts: opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(false)}, + Run: happyPathFT, }, } for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { - happyPathFD(t, tc.Opts) + tc.Run(t, tc.Opts) + }) + t.Run("Disabled Persistence "+tc.Name, func(t *testing.T) { + opts := tc.Opts + opts.ORM = headtracker.NewNullORM() + tc.Run(t, opts) }) } } @@ -339,14 +361,14 @@ func TestHeadTracker_CallsHeadTrackableCallbacks(t *testing.T) { chchHeaders := make(chan testutils.RawSub[*evmtypes.Head], 1) mockEth := &testutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + chHead := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { sub := mockEth.NewSub(t) - chchHeaders <- testutils.NewRawSub(ch, sub.Err()) - return sub + chchHeaders <- testutils.NewRawSub(chHead, sub.Err()) + return chHead, sub, nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(0), nil) ethClient.On("HeadByHash", mock.Anything, mock.Anything).Return(testutils.Head(0), nil).Maybe() @@ -375,16 +397,19 @@ func TestHeadTracker_ReconnectOnError(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) mockEth := &testutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + chHead := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { return mockEth.NewSub(t) }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { + return chHead, mockEth.NewSub(t), nil + }, ) - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("cannot reconnect")) - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ethClient.On("SubscribeToHeads", mock.Anything).Return((<-chan *evmtypes.Head)(chHead), nil, errors.New("cannot reconnect")) + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { return mockEth.NewSub(t) }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { + return chHead, mockEth.NewSub(t), nil + }, ) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(0), nil) checker := &mocks.MockHeadTrackable{} @@ -409,16 +434,16 @@ func TestHeadTracker_ResubscribeOnSubscriptionError(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ch := make(chan *evmtypes.Head) chchHeaders := make(chan testutils.RawSub[*evmtypes.Head], 1) mockEth := &testutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { sub := mockEth.NewSub(t) chchHeaders <- testutils.NewRawSub(ch, sub.Err()) - return sub + return ch, sub, nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(0), nil) ethClient.On("HeadByHash", mock.Anything, mock.Anything).Return(testutils.Head(0), nil).Maybe() @@ -474,14 +499,14 @@ func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) { chchHeaders := make(chan testutils.RawSub[*evmtypes.Head], 1) mockEth := &testutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ch := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { sub := mockEth.NewSub(t) chchHeaders <- testutils.NewRawSub(ch, sub.Err()) - return sub + return ch, sub, nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) orm := headtracker.NewORM(*testutils.FixtureChainID, db) @@ -499,11 +524,11 @@ func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) { headers.TrySend(testutils.Head(1)) }() - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { report := ht.headTracker.HealthReport() services.CopyHealth(report, ht.headBroadcaster.HealthReport()) return !slices.ContainsFunc(maps.Values(report), func(e error) bool { return e != nil }) - }, 5*time.Second, tests.TestInterval).Should(gomega.Equal(true)) + }, 5*time.Second, tests.TestInterval) h, err := orm.LatestHead(tests.Context(t)) require.NoError(t, err) @@ -531,14 +556,14 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) chchHeaders := make(chan testutils.RawSub[*evmtypes.Head], 1) mockEth := &testutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + chHead := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { sub := mockEth.NewSub(t) - chchHeaders <- testutils.NewRawSub(ch, sub.Err()) - return sub + chchHeaders <- testutils.NewRawSub(chHead, sub.Err()) + return chHead, sub, nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) // --------------------- @@ -578,27 +603,10 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) checker.On("OnNewLongestChain", mock.Anything, mock.Anything). Run(func(args mock.Arguments) { h := args.Get(1).(*evmtypes.Head) + // This is the new longest chain [0, 5], check that it came with its parents + assert.Equal(t, uint32(6), h.ChainLength()) + assertChainWithParents(t, blocksForked, 5, 1, h) - assert.Equal(t, int64(5), h.Number) - assert.Equal(t, blocksForked.Head(5).Hash, h.Hash) - - // This is the new longest chain, check that it came with its parents - if !assert.NotNil(t, h.Parent) { - return - } - assert.Equal(t, h.Parent.Hash, blocksForked.Head(4).Hash) - if !assert.NotNil(t, h.Parent.Parent) { - return - } - assert.Equal(t, h.Parent.Parent.Hash, blocksForked.Head(3).Hash) - if !assert.NotNil(t, h.Parent.Parent.Parent) { - return - } - assert.Equal(t, h.Parent.Parent.Parent.Hash, blocksForked.Head(2).Hash) - if !assert.NotNil(t, h.Parent.Parent.Parent.Parent) { - return - } - assert.Equal(t, h.Parent.Parent.Parent.Parent.Hash, blocksForked.Head(1).Hash) lastLongestChainAwaiter.ItHappened() }).Return().Once() @@ -639,6 +647,16 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) } } +func assertChainWithParents(t testing.TB, blocks *blocks, startBN, endBN uint64, h *evmtypes.Head) { + for blockNumber := startBN; blockNumber >= endBN; blockNumber-- { + assert.NotNil(t, h) + assert.Equal(t, blockNumber, uint64(h.Number)) + assert.Equal(t, blocks.Head(blockNumber).Hash, h.Hash) + // move to parent + h = h.Parent.Load() + } +} + func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T) { t.Parallel() @@ -659,14 +677,14 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T chchHeaders := make(chan testutils.RawSub[*evmtypes.Head], 1) mockEth := &testutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + chHead := make(chan *evmtypes.Head) + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { sub := mockEth.NewSub(t) - chchHeaders <- testutils.NewRawSub(ch, sub.Err()) - return sub + chchHeaders <- testutils.NewRawSub(chHead, sub.Err()) + return chHead, sub, nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) // --------------------- @@ -725,34 +743,13 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T checker.On("OnNewLongestChain", mock.Anything, mock.Anything). Run(func(args mock.Arguments) { h := args.Get(1).(*evmtypes.Head) - require.Equal(t, int64(4), h.Number) - require.Equal(t, blocks.Head(4).Hash, h.Hash) - - // Check that the block came with its parents - require.NotNil(t, h.Parent) - require.Equal(t, h.Parent.Hash, blocks.Head(3).Hash) - require.NotNil(t, h.Parent.Parent.Hash) - require.Equal(t, h.Parent.Parent.Hash, blocks.Head(2).Hash) - require.NotNil(t, h.Parent.Parent.Parent) - require.Equal(t, h.Parent.Parent.Parent.Hash, blocks.Head(1).Hash) + assertChainWithParents(t, blocks, 4, 1, h) }).Return().Once() checker.On("OnNewLongestChain", mock.Anything, mock.Anything). Run(func(args mock.Arguments) { h := args.Get(1).(*evmtypes.Head) - - require.Equal(t, int64(5), h.Number) - require.Equal(t, blocksForked.Head(5).Hash, h.Hash) - - // This is the new longest chain, check that it came with its parents - require.NotNil(t, h.Parent) - require.Equal(t, h.Parent.Hash, blocksForked.Head(4).Hash) - require.NotNil(t, h.Parent.Parent) - require.Equal(t, h.Parent.Parent.Hash, blocksForked.Head(3).Hash) - require.NotNil(t, h.Parent.Parent.Parent) - require.Equal(t, h.Parent.Parent.Parent.Hash, blocksForked.Head(2).Hash) - require.NotNil(t, h.Parent.Parent.Parent.Parent) - require.Equal(t, h.Parent.Parent.Parent.Parent.Hash, blocksForked.Head(1).Hash) + assertChainWithParents(t, blocksForked, 5, 1, h) lastLongestChainAwaiter.ItHappened() }).Return().Once() @@ -798,7 +795,20 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T func TestHeadTracker_Backfill(t *testing.T) { t.Parallel() + t.Run("Enabled Persistence", func(t *testing.T) { + testHeadTrackerBackfill(t, func(t *testing.T) headtracker.ORM { + db := pgtest.NewSqlxDB(t) + return headtracker.NewORM(*testutils.FixtureChainID, db) + }) + }) + t.Run("Disabled Persistence", func(t *testing.T) { + testHeadTrackerBackfill(t, func(t *testing.T) headtracker.ORM { + return headtracker.NewNullORM() + }) + }) +} +func testHeadTrackerBackfill(t *testing.T, newORM func(t *testing.T) headtracker.ORM) { // Heads are arranged as follows: // headN indicates an unpersisted ethereum header // hN indicates a persisted head record @@ -811,52 +821,37 @@ func TestHeadTracker_Backfill(t *testing.T) { now := uint64(time.Now().UTC().Unix()) - gethHead0 := &gethTypes.Header{ - Number: big.NewInt(0), - ParentHash: common.BigToHash(big.NewInt(0)), - Time: now, - } - head0 := evmtypes.NewHead(gethHead0.Number, utils.NewHash(), gethHead0.ParentHash, gethHead0.Time, ubig.New(testutils.FixtureChainID)) + head0 := evmtypes.NewHead(big.NewInt(0), utils.NewHash(), common.BigToHash(big.NewInt(0)), now, ubig.New(testutils.FixtureChainID)) - h1 := *testutils.Head(1) + h1 := testutils.Head(1) h1.ParentHash = head0.Hash - gethHead8 := &gethTypes.Header{ - Number: big.NewInt(8), - ParentHash: utils.NewHash(), - Time: now, - } - head8 := evmtypes.NewHead(gethHead8.Number, utils.NewHash(), gethHead8.ParentHash, gethHead8.Time, ubig.New(testutils.FixtureChainID)) + head8 := evmtypes.NewHead(big.NewInt(8), utils.NewHash(), utils.NewHash(), now, ubig.New(testutils.FixtureChainID)) - h9 := *testutils.Head(9) + h9 := testutils.Head(9) h9.ParentHash = head8.Hash - gethHead10 := &gethTypes.Header{ - Number: big.NewInt(10), - ParentHash: h9.Hash, - Time: now, - } - head10 := evmtypes.NewHead(gethHead10.Number, utils.NewHash(), gethHead10.ParentHash, gethHead10.Time, ubig.New(testutils.FixtureChainID)) + head10 := evmtypes.NewHead(big.NewInt(10), utils.NewHash(), h9.Hash, now, ubig.New(testutils.FixtureChainID)) - h11 := *testutils.Head(11) + h11 := testutils.Head(11) h11.ParentHash = head10.Hash - h12 := *testutils.Head(12) + h12 := testutils.Head(12) h12.ParentHash = h11.Hash - h13 := *testutils.Head(13) + h13 := testutils.Head(13) h13.ParentHash = h12.Hash - h14Orphaned := *testutils.Head(14) + h14Orphaned := testutils.Head(14) h14Orphaned.ParentHash = h13.Hash - h14 := *testutils.Head(14) + h14 := testutils.Head(14) h14.ParentHash = h13.Hash - h15 := *testutils.Head(15) + h15 := testutils.Head(15) h15.ParentHash = h14.Hash - heads := []evmtypes.Head{ + heads := []*evmtypes.Head{ h9, h11, h12, @@ -869,7 +864,7 @@ func TestHeadTracker_Backfill(t *testing.T) { ctx := tests.Context(t) type opts struct { - Heads []evmtypes.Head + Heads []*evmtypes.Head FinalityTagEnabled bool FinalizedBlockOffset uint32 FinalityDepth uint32 @@ -886,14 +881,12 @@ func TestHeadTracker_Backfill(t *testing.T) { } }) - db := pgtest.NewSqlxDB(t) - orm := headtracker.NewORM(*testutils.FixtureChainID, db) - for i := range opts.Heads { - require.NoError(t, orm.IdempotentInsertHead(tests.Context(t), &opts.Heads[i])) - } ethClient := testutils.NewEthClientMock(t) ethClient.On("ConfiguredChainID", mock.Anything).Return(evmcfg.EVM().ChainID(), nil) - ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm) + ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), newORM(t)) + for i := range opts.Heads { + require.NoError(t, ht.headSaver.Save(tests.Context(t), opts.Heads[i])) + } _, err := ht.headSaver.Load(tests.Context(t), 0) require.NoError(t, err) return ht @@ -904,74 +897,72 @@ func TestHeadTracker_Backfill(t *testing.T) { const expectedError = "failed to fetch latest finalized block" htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, errors.New(expectedError)).Once() - err := htu.headTracker.Backfill(ctx, &h12) + err := htu.headTracker.Backfill(ctx, h12) require.ErrorContains(t, err, expectedError) }) t.Run("returns error if latestFinalized is not valid", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, nil).Once() - err := htu.headTracker.Backfill(ctx, &h12) + err := htu.headTracker.Backfill(ctx, h12) require.EqualError(t, err, "failed to calculate finalized block: failed to get valid latest finalized block") }) t.Run("Returns error if finality gap is too big", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, MaxAllowedFinalityDepth: 2}) - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h9, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h9, nil).Once() - err := htu.headTracker.Backfill(ctx, &h12) + err := htu.headTracker.Backfill(ctx, h12) require.EqualError(t, err, "gap between latest finalized block (9) and current head (12) is too large (> 2)") }) t.Run("Returns error if finalized head is ahead of canonical", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14Orphaned, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h14Orphaned, nil).Once() - err := htu.headTracker.Backfill(ctx, &h12) + err := htu.headTracker.Backfill(ctx, h12) require.EqualError(t, err, "invariant violation: expected head of canonical chain to be ahead of the latestFinalized") }) t.Run("Returns error if finalizedHead is not present in the canonical chain", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14Orphaned, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h14Orphaned, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15) - require.EqualError(t, err, "expected finalized block to be present in canonical chain") + err := htu.headTracker.Backfill(ctx, h15) + require.ErrorAs(t, err, &commonht.FinalizedMissingError[common.Hash]{}) }) t.Run("Marks all blocks in chain that are older than finalized", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) - assertFinalized := func(expectedFinalized bool, msg string, heads ...evmtypes.Head) { + assertFinalized := func(expectedFinalized bool, msg string, heads ...*evmtypes.Head) { for _, h := range heads { storedHead := htu.headSaver.Chain(h.Hash) - assert.Equal(t, expectedFinalized, storedHead != nil && storedHead.IsFinalized, msg, "block_number", h.Number) + assert.Equal(t, expectedFinalized, storedHead != nil && storedHead.IsFinalized.Load(), msg, "block_number", h.Number) } } - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h14, nil).Once() + err := htu.headTracker.Backfill(ctx, h15) require.NoError(t, err) assertFinalized(true, "expected heads to be marked as finalized after backfill", h14, h13, h12, h11) - assertFinalized(false, "expected heads to remain unfinalized", h15, head10) + assertFinalized(false, "expected heads to remain unfinalized", h15, &head10) }) t.Run("fetches a missing head", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h9, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h9, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil) - err := htu.headTracker.Backfill(ctx, &h12) + err := htu.headTracker.Backfill(ctx, h12) require.NoError(t, err) h := htu.headSaver.Chain(h12.Hash) - assert.Equal(t, int64(12), h.Number) - require.NotNil(t, h.Parent) - assert.Equal(t, int64(11), h.Parent.Number) - require.NotNil(t, h.Parent.Parent) - assert.Equal(t, int64(10), h.Parent.Parent.Number) - require.NotNil(t, h.Parent.Parent.Parent) - assert.Equal(t, int64(9), h.Parent.Parent.Parent.Number) + for expectedBlockNumber := int64(12); expectedBlockNumber >= 9; expectedBlockNumber-- { + require.NotNil(t, h) + assert.Equal(t, expectedBlockNumber, h.Number) + h = h.Parent.Load() + } - writtenHead, err := htu.orm.HeadByHash(tests.Context(t), head10.Hash) + writtenHead := htu.headSaver.Chain(head10.Hash) require.NoError(t, err) assert.Equal(t, int64(10), writtenHead.Number) }) @@ -984,7 +975,7 @@ func TestHeadTracker_Backfill(t *testing.T) { htu.ethClient.On("HeadByHash", mock.Anything, head8.Hash). Return(&head8, nil) - err := htu.headTracker.Backfill(ctx, &h15) + err := htu.headTracker.Backfill(ctx, h15) require.NoError(t, err) h := htu.headSaver.Chain(h15.Hash) @@ -1005,7 +996,7 @@ func TestHeadTracker_Backfill(t *testing.T) { Return(nil, ethereum.NotFound). Once() - err := htu.headTracker.Backfill(ctx, &h12) + err := htu.headTracker.Backfill(ctx, h12) require.Error(t, err) require.ErrorContains(t, err, "fetchAndSaveHead failed: not found") @@ -1027,7 +1018,7 @@ func TestHeadTracker_Backfill(t *testing.T) { cancel() }) - err := htu.headTracker.Backfill(lctx, &h12) + err := htu.headTracker.Backfill(lctx, h12) require.Error(t, err) require.ErrorContains(t, err, "fetchAndSaveHead failed: context canceled") @@ -1039,12 +1030,12 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("abandons backfill and returns error when fetching a block by hash fails, indicating a reorg", func(t *testing.T) { htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h11, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h11, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(h14, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(h13, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(nil, errors.New("not found")).Once() - err := htu.headTracker.Backfill(ctx, &h15) + err := htu.headTracker.Backfill(ctx, h15) require.Error(t, err) require.ErrorContains(t, err, "fetchAndSaveHead failed: not found") @@ -1056,83 +1047,83 @@ func TestHeadTracker_Backfill(t *testing.T) { assert.Equal(t, int64(13), h.EarliestInChain().BlockNumber()) }) t.Run("marks head as finalized, if latestHead = finalizedHead (0 finality depth)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityTagEnabled: true}) + htu := newHeadTrackerUniverse(t, opts{Heads: []*evmtypes.Head{h15}, FinalityTagEnabled: true}) finalizedH15 := h15 // copy h15 to have different addresses - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&finalizedH15, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(finalizedH15, nil).Once() + err := htu.headTracker.Backfill(ctx, h15) require.NoError(t, err) h := htu.headSaver.LatestChain() // Should contain 14, 13 (15 was never added). When trying to get the parent of h13 by hash, a reorg happened and backfill exited. assert.Equal(t, 1, int(h.ChainLength())) - assert.True(t, h.IsFinalized) + assert.True(t, h.IsFinalized.Load()) assert.Equal(t, h15.BlockNumber(), h.BlockNumber()) assert.Equal(t, h15.Hash, h.Hash) }) t.Run("marks block as finalized according to FinalizedBlockOffset (finality tag)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityTagEnabled: true, FinalizedBlockOffset: 2}) - htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14, nil).Once() + htu := newHeadTrackerUniverse(t, opts{Heads: []*evmtypes.Head{h15}, FinalityTagEnabled: true, FinalizedBlockOffset: 2}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h14, nil).Once() // calculateLatestFinalizedBlock fetches blocks at LatestFinalized - FinalizedBlockOffset - htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(h12.Number)).Return(&h12, nil).Once() + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(h12.Number)).Return(h12, nil).Once() // backfill from 15 to 12 - htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(&h12, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15) + htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(h12, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(h13, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(h14, nil).Once() + err := htu.headTracker.Backfill(ctx, h15) require.NoError(t, err) h := htu.headSaver.LatestChain() // h - must contain 15, 14, 13, 12 and only 12 is finalized assert.Equal(t, 4, int(h.ChainLength())) - for ; h.Hash != h12.Hash; h = h.Parent { - assert.False(t, h.IsFinalized) + for ; h.Hash != h12.Hash; h = h.Parent.Load() { + assert.False(t, h.IsFinalized.Load()) } - assert.True(t, h.IsFinalized) + assert.True(t, h.IsFinalized.Load()) assert.Equal(t, h12.BlockNumber(), h.BlockNumber()) assert.Equal(t, h12.Hash, h.Hash) }) t.Run("marks block as finalized according to FinalizedBlockOffset (finality depth)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityDepth: 1, FinalizedBlockOffset: 2}) - htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(12)).Return(&h12, nil).Once() + htu := newHeadTrackerUniverse(t, opts{Heads: []*evmtypes.Head{h15}, FinalityDepth: 1, FinalizedBlockOffset: 2}) + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(12)).Return(h12, nil).Once() // backfill from 15 to 12 - htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(&h12, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15) + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(h14, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(h13, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(h12, nil).Once() + err := htu.headTracker.Backfill(ctx, h15) require.NoError(t, err) h := htu.headSaver.LatestChain() // h - must contain 15, 14, 13, 12 and only 12 is finalized assert.Equal(t, 4, int(h.ChainLength())) - for ; h.Hash != h12.Hash; h = h.Parent { - assert.False(t, h.IsFinalized) + for ; h.Hash != h12.Hash; h = h.Parent.Load() { + assert.False(t, h.IsFinalized.Load()) } - assert.True(t, h.IsFinalized) + assert.True(t, h.IsFinalized.Load()) assert.Equal(t, h12.BlockNumber(), h.BlockNumber()) assert.Equal(t, h12.Hash, h.Hash) }) t.Run("marks block as finalized according to FinalizedBlockOffset even with instant finality", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityDepth: 0, FinalizedBlockOffset: 2}) - htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(13)).Return(&h13, nil).Once() + htu := newHeadTrackerUniverse(t, opts{Heads: []*evmtypes.Head{h15}, FinalityDepth: 0, FinalizedBlockOffset: 2}) + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(13)).Return(h13, nil).Once() // backfill from 15 to 13 - htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() - htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15) + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(h14, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(h13, nil).Once() + err := htu.headTracker.Backfill(ctx, h15) require.NoError(t, err) h := htu.headSaver.LatestChain() // h - must contain 15, 14, 13, only 13 is finalized assert.Equal(t, 3, int(h.ChainLength())) - for ; h.Hash != h13.Hash; h = h.Parent { - assert.False(t, h.IsFinalized) + for ; h.Hash != h13.Hash; h = h.Parent.Load() { + assert.False(t, h.IsFinalized.Load()) } - assert.True(t, h.IsFinalized) + assert.True(t, h.IsFinalized.Load()) assert.Equal(t, h13.BlockNumber(), h.BlockNumber()) assert.Equal(t, h13.Hash, h.Hash) }) @@ -1153,7 +1144,7 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { h13.ParentHash = h12.Hash type opts struct { - Heads []evmtypes.Head + Heads []*evmtypes.Head FinalityTagEnabled bool FinalizedBlockOffset uint32 FinalityDepth uint32 @@ -1169,7 +1160,7 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { db := pgtest.NewSqlxDB(t) orm := headtracker.NewORM(*testutils.FixtureChainID, db) for i := range opts.Heads { - require.NoError(t, orm.IdempotentInsertHead(tests.Context(t), &opts.Heads[i])) + require.NoError(t, orm.IdempotentInsertHead(tests.Context(t), opts.Heads[i])) } ethClient := evmtest.NewEthClientMock(t) ethClient.On("ConfiguredChainID", mock.Anything).Return(testutils.FixtureChainID, nil) @@ -1221,7 +1212,7 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { assert.Equal(t, actualLF, h11) }) t.Run("returns latest finalized block with offset from cache (finality tag)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, FinalizedBlockOffset: 1, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, FinalizedBlockOffset: 1, Heads: []*evmtypes.Head{h13, h12, h11}}) htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h12, nil).Once() @@ -1231,7 +1222,7 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { assert.Equal(t, actualLF.Number, h11.Number) }) t.Run("returns latest finalized block with offset from RPC (finality tag)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, FinalizedBlockOffset: 2, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, FinalizedBlockOffset: 2, Heads: []*evmtypes.Head{h13, h12, h11}}) htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h12, nil).Once() h10 := testutils.Head(10) @@ -1252,7 +1243,7 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { assert.Equal(t, actualLF.Number, h13.Number) }) t.Run("returns latest finalized block with offset from cache (finality depth)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{FinalityDepth: 1, FinalizedBlockOffset: 1, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu := newHeadTrackerUniverse(t, opts{FinalityDepth: 1, FinalizedBlockOffset: 1, Heads: []*evmtypes.Head{h13, h12, h11}}) htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) @@ -1261,7 +1252,7 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { assert.Equal(t, actualLF.Number, h11.Number) }) t.Run("returns latest finalized block with offset from RPC (finality depth)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{FinalityDepth: 1, FinalizedBlockOffset: 2, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu := newHeadTrackerUniverse(t, opts{FinalityDepth: 1, FinalizedBlockOffset: 2, Heads: []*evmtypes.Head{h13, h12, h11}}) htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() h10 := testutils.Head(10) htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(10)).Return(h10, nil).Once() @@ -1273,47 +1264,6 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { }) } -// BenchmarkHeadTracker_Backfill - benchmarks HeadTracker's Backfill with focus on efficiency after initial -// backfill on start up -func BenchmarkHeadTracker_Backfill(b *testing.B) { - evmcfg := testutils.NewTestChainScopedConfig(b, func(c *toml.EVMConfig) { - c.FinalityTagEnabled = ptr(true) - }) - db := pgtest.NewSqlxDB(b) - chainID := big.NewInt(evmclient.NullClientChainID) - orm := headtracker.NewORM(*chainID, db) - ethClient := evmclimocks.NewClient(b) - ethClient.On("ConfiguredChainID").Return(chainID) - ht := createHeadTracker(b, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm) - ctx := tests.Context(b) - makeHash := func(n int64) common.Hash { - return common.BigToHash(big.NewInt(n)) - } - const finalityDepth = 12000 // observed value on Arbitrum - makeBlock := func(n int64) *evmtypes.Head { - return &evmtypes.Head{Number: n, Hash: makeHash(n), ParentHash: makeHash(n - 1)} - } - latest := makeBlock(finalityDepth) - finalized := makeBlock(1) - ethClient.On("HeadByHash", mock.Anything, mock.Anything).Return(func(_ context.Context, hash common.Hash) (*evmtypes.Head, error) { - number := hash.Big().Int64() - return makeBlock(number), nil - }) - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(finalized, nil).Once() - // run initial backfill to populate the database - err := ht.headTracker.Backfill(ctx, latest) - require.NoError(b, err) - b.ResetTimer() - // focus benchmark on processing of a new latest block - for i := 0; i < b.N; i++ { - latest = makeBlock(int64(finalityDepth + i)) - finalized = makeBlock(int64(i + 1)) - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(finalized, nil).Once() - err := ht.headTracker.Backfill(ctx, latest) - require.NoError(b, err) - } -} - func createHeadTracker(t testing.TB, ethClient *evmclimocks.Client, config commontypes.Config, htConfig commontypes.HeadTrackerConfig, orm headtracker.ORM) *headTrackerUniverse { lggr, ob := logger.TestObserved(t, zap.DebugLevel) hb := headtracker.NewHeadBroadcaster(lggr) @@ -1417,15 +1367,15 @@ func (hb *headBuffer) Append(head *evmtypes.Head) { Number: head.Number, Hash: head.Hash, ParentHash: head.ParentHash, - Parent: head.Parent, Timestamp: time.Unix(int64(len(hb.Heads)), 0), EVMChainID: head.EVMChainID, } + cloned.Parent.Store(head.Parent.Load()) hb.Heads = append(hb.Heads, cloned) } type blocks struct { - t *testing.T + t testing.TB Hashes []common.Hash mHashes map[int64]common.Hash Heads map[int64]*evmtypes.Head @@ -1435,7 +1385,7 @@ func (b *blocks) Head(number uint64) *evmtypes.Head { return b.Heads[int64(number)] } -func NewBlocks(t *testing.T, numHashes int) *blocks { +func NewBlocks(t testing.TB, numHashes int) *blocks { hashes := make([]common.Hash, 0) heads := make(map[int64]*evmtypes.Head) for i := int64(0); i < int64(numHashes); i++ { @@ -1445,7 +1395,7 @@ func NewBlocks(t *testing.T, numHashes int) *blocks { heads[i] = &evmtypes.Head{Hash: hash, Number: i, Timestamp: time.Unix(i, 0), EVMChainID: ubig.New(testutils.FixtureChainID)} if i > 0 { parent := heads[i-1] - heads[i].Parent = parent + heads[i].Parent.Store(parent) heads[i].ParentHash = parent.Hash } } @@ -1474,7 +1424,7 @@ func (b *blocks) ForkAt(t *testing.T, blockNum int64, numHashes int) *blocks { } forked.Heads[blockNum].ParentHash = b.Heads[blockNum].ParentHash - forked.Heads[blockNum].Parent = b.Heads[blockNum].Parent + forked.Heads[blockNum].Parent.Store(b.Heads[blockNum].Parent.Load()) return forked } @@ -1488,9 +1438,9 @@ func (b *blocks) NewHead(number uint64) *evmtypes.Head { Number: parent.Number + 1, Hash: testutils.NewHash(), ParentHash: parent.Hash, - Parent: parent, Timestamp: time.Unix(parent.Number+1, 0), EVMChainID: ubig.New(testutils.FixtureChainID), } + head.Parent.Store(parent) return head } diff --git a/core/chains/evm/headtracker/heads.go b/core/chains/evm/headtracker/heads.go index a61e55dcd28..c3492f9a595 100644 --- a/core/chains/evm/headtracker/heads.go +++ b/core/chains/evm/headtracker/heads.go @@ -1,7 +1,8 @@ package headtracker import ( - "sort" + "container/heap" + "fmt" "sync" "github.com/ethereum/go-ethereum/common" @@ -17,7 +18,7 @@ type Heads interface { HeadByHash(hash common.Hash) *evmtypes.Head // AddHeads adds newHeads to the collection, eliminates duplicates, // sorts by head number, fixes parents and cuts off old heads (historyDepth). - AddHeads(newHeads ...*evmtypes.Head) + AddHeads(newHeads ...*evmtypes.Head) error // Count returns number of heads in the collection. Count() int // MarkFinalized - finds `finalized` in the LatestHead and marks it and all direct ancestors as finalized. @@ -26,114 +27,158 @@ type Heads interface { } type heads struct { - heads []*evmtypes.Head - headsMap map[common.Hash]*evmtypes.Head - mu sync.RWMutex + highest *evmtypes.Head + headsAsc *headsHeap + headsByHash map[common.Hash]*evmtypes.Head + headsByParent map[common.Hash]map[common.Hash]*evmtypes.Head + mu sync.RWMutex } func NewHeads() Heads { - return &heads{} + return &heads{ + headsAsc: &headsHeap{}, + headsByHash: make(map[common.Hash]*evmtypes.Head), + headsByParent: map[common.Hash]map[common.Hash]*evmtypes.Head{}, + } } func (h *heads) LatestHead() *evmtypes.Head { h.mu.RLock() defer h.mu.RUnlock() - if len(h.heads) == 0 { - return nil - } - return h.heads[0] + return h.highest } func (h *heads) HeadByHash(hash common.Hash) *evmtypes.Head { h.mu.RLock() defer h.mu.RUnlock() - if h.headsMap == nil { + if h.headsByHash == nil { return nil } - return h.headsMap[hash] + return h.headsByHash[hash] } func (h *heads) Count() int { h.mu.RLock() defer h.mu.RUnlock() - return len(h.heads) + return h.headsAsc.Len() } -// MarkFinalized - marks block with has equal to finalized and all it's direct ancestors as finalized. +// MarkFinalized - marks block with hash equal to finalized and all it's direct ancestors as finalized. // Trims old blocks whose height is smaller than minBlockToKeep func (h *heads) MarkFinalized(finalized common.Hash, minBlockToKeep int64) bool { h.mu.Lock() defer h.mu.Unlock() - if len(h.heads) == 0 { + if len(h.headsByHash) == 0 { return false } - // deep copy to avoid race on head.Parent - h.heads, h.headsMap = deepCopy(h.heads, minBlockToKeep) - - finalizedHead, ok := h.headsMap[finalized] + finalizedHead, ok := h.headsByHash[finalized] if !ok { return false } - for finalizedHead != nil { - finalizedHead.IsFinalized = true - finalizedHead = finalizedHead.Parent + + markFinalized(finalizedHead) + + // remove all blocks that are older than minBlockToKeep + for h.headsAsc.Len() > 0 && h.headsAsc.Peek().Number < minBlockToKeep { + oldBlock := heap.Pop(h.headsAsc).(*evmtypes.Head) + delete(h.headsByHash, oldBlock.Hash) + // clear .Parent in oldBlock's children + for _, oldBlockChildren := range h.headsByParent[oldBlock.Hash] { + oldBlockChildren.Parent.Store(nil) + } + // headsByParent are expected to be of the same height, so we can remove them all at once + delete(h.headsByParent, oldBlock.ParentHash) + } + + if h.highest.Number < minBlockToKeep { + h.highest = nil } return true } -func deepCopy(oldHeads []*evmtypes.Head, minBlockToKeep int64) ([]*evmtypes.Head, map[common.Hash]*evmtypes.Head) { - headsMap := make(map[common.Hash]*evmtypes.Head, len(oldHeads)) - heads := make([]*evmtypes.Head, 0, len(headsMap)) - for _, head := range oldHeads { - if head.Hash == head.ParentHash { - // shouldn't happen but it is untrusted input - continue - } - if head.BlockNumber() < minBlockToKeep { - // trim redundant blocks - continue - } - // copy all head objects to avoid races when a previous head chain is used - // elsewhere (since we mutate Parent here) - headCopy := *head - headCopy.Parent = nil // always build it from scratch in case it points to a head too old to be included - // map eliminates duplicates - // prefer head that was already in heads as it might have been marked as finalized on previous run - if _, ok := headsMap[head.Hash]; !ok { - headsMap[head.Hash] = &headCopy - heads = append(heads, &headCopy) +func markFinalized(head *evmtypes.Head) { + // we can assume that if a head was previously marked as finalized all its ancestors were marked as finalized + for head != nil && !head.IsFinalized.Load() { + head.IsFinalized.Store(true) + head = head.Parent.Load() + } +} + +func (h *heads) ensureNoCycles(newHead *evmtypes.Head) error { + if newHead.ParentHash == newHead.Hash { + return fmt.Errorf("cycle detected: newHeads reference itself newHead(%s)", newHead.String()) + } + if parent, ok := h.headsByHash[newHead.ParentHash]; ok { + if parent.Number >= newHead.Number { + return fmt.Errorf("potential cycle detected while adding newHead as child: %w", newPotentialCycleError(parent, newHead)) } } - // sort the heads as original slice might be out of order - sort.SliceStable(heads, func(i, j int) bool { - // sorting from the highest number to lowest - return heads[i].Number > heads[j].Number - }) - - // assign parents - for i := 0; i < len(heads); i++ { - head := heads[i] - parent, exists := headsMap[head.ParentHash] - if exists { - head.Parent = parent + for _, child := range h.headsByParent[newHead.Hash] { + if newHead.Number >= child.Number { + return fmt.Errorf("potential cycle detected while adding newHead as parent: %w", newPotentialCycleError(newHead, child)) } } - return heads, headsMap + return nil } -func (h *heads) AddHeads(newHeads ...*evmtypes.Head) { +func (h *heads) AddHeads(newHeads ...*evmtypes.Head) error { h.mu.Lock() defer h.mu.Unlock() - // deep copy to avoid race on head.Parent - h.heads, h.headsMap = deepCopy(append(h.heads, newHeads...), 0) + for _, newHead := range newHeads { + // skip blocks that were previously added + if _, ok := h.headsByHash[newHead.Hash]; ok { + continue + } + + if err := h.ensureNoCycles(newHead); err != nil { + return err + } + + // heads now owns the newHead - reset values that are populated by heads + newHead.IsFinalized.Store(false) + newHead.Parent.Store(nil) + + // prefer newer head to set as highest + if h.highest == nil || h.highest.Number <= newHead.Number { + h.highest = newHead + } + + heap.Push(h.headsAsc, newHead) + h.headsByHash[newHead.Hash] = newHead + siblings, ok := h.headsByParent[newHead.ParentHash] + if !ok { + siblings = make(map[common.Hash]*evmtypes.Head) + h.headsByParent[newHead.ParentHash] = siblings + } + siblings[newHead.Hash] = newHead + // populate reference to parent + if parent, ok := h.headsByHash[newHead.ParentHash]; ok { + newHead.Parent.Store(parent) + } + for _, child := range h.headsByParent[newHead.Hash] { + // ensure all children have reference to newHead + child.Parent.Store(newHead) + if child.IsFinalized.Load() { + // mark newHead as finalized if any of its children is finalized + markFinalized(newHead) + } + } + } + + return nil +} + +func newPotentialCycleError(parent, child *evmtypes.Head) error { + return fmt.Errorf("expected head number to strictly decrease in 'child -> parent' relation: "+ + "child(%s), parent(%s)", child.String(), parent.String()) } diff --git a/core/chains/evm/headtracker/heads_test.go b/core/chains/evm/headtracker/heads_test.go index 6c02c528ba2..92e4015d8c3 100644 --- a/core/chains/evm/headtracker/heads_test.go +++ b/core/chains/evm/headtracker/heads_test.go @@ -20,21 +20,29 @@ func TestHeads_LatestHead(t *testing.T) { t.Parallel() heads := headtracker.NewHeads() - heads.AddHeads(testutils.Head(100), testutils.Head(200), testutils.Head(300)) + assert.NoError(t, heads.AddHeads(testutils.Head(100), testutils.Head(200), testutils.Head(300))) latest := heads.LatestHead() require.NotNil(t, latest) require.Equal(t, int64(300), latest.Number) - heads.AddHeads(testutils.Head(250)) + assert.NoError(t, heads.AddHeads(testutils.Head(250))) latest = heads.LatestHead() require.NotNil(t, latest) require.Equal(t, int64(300), latest.Number) - heads.AddHeads(testutils.Head(400)) + assert.NoError(t, heads.AddHeads(testutils.Head(400))) latest = heads.LatestHead() require.NotNil(t, latest) require.Equal(t, int64(400), latest.Number) + + // if heads have the same height, LatestHead prefers most recent + newerH400 := testutils.Head(400) + assert.NoError(t, heads.AddHeads(newerH400)) + latest = heads.LatestHead() + require.NotNil(t, latest) + require.Equal(t, int64(400), latest.Number) + require.Equal(t, newerH400.Hash, latest.Hash) } func TestHeads_HeadByHash(t *testing.T) { @@ -46,7 +54,7 @@ func TestHeads_HeadByHash(t *testing.T) { testutils.Head(300), } heads := headtracker.NewHeads() - heads.AddHeads(testHeads...) + assert.NoError(t, heads.AddHeads(testHeads...)) head := heads.HeadByHash(testHeads[1].Hash) require.NotNil(t, head) @@ -62,10 +70,10 @@ func TestHeads_Count(t *testing.T) { heads := headtracker.NewHeads() require.Zero(t, heads.Count()) - heads.AddHeads(testutils.Head(100), testutils.Head(200), testutils.Head(300)) + assert.NoError(t, heads.AddHeads(testutils.Head(100), testutils.Head(200), testutils.Head(300))) require.Equal(t, 3, heads.Count()) - heads.AddHeads(testutils.Head(400)) + assert.NoError(t, heads.AddHeads(testutils.Head(400))) require.Equal(t, 4, heads.Count()) } @@ -77,11 +85,11 @@ func TestHeads_AddHeads(t *testing.T) { var testHeads []*evmtypes.Head var parentHash common.Hash - for i := 0; i < 5; i++ { - hash := utils.NewHash() + for i := 1; i < 6; i++ { + hash := common.BigToHash(big.NewInt(int64(i))) h := evmtypes.NewHead(big.NewInt(int64(i)), hash, parentHash, uint64(time.Now().Unix()), ubig.NewI(0)) testHeads = append(testHeads, &h) - if i == 2 { + if i == 3 { // uncled block h := evmtypes.NewHead(big.NewInt(int64(i)), uncleHash, parentHash, uint64(time.Now().Unix()), ubig.NewI(0)) testHeads = append(testHeads, &h) @@ -89,10 +97,10 @@ func TestHeads_AddHeads(t *testing.T) { parentHash = hash } - heads.AddHeads(testHeads...) + assert.NoError(t, heads.AddHeads(testHeads...)) require.Equal(t, 6, heads.Count()) // Add duplicates (should be ignored) - heads.AddHeads(testHeads[2:5]...) + assert.NoError(t, heads.AddHeads(testHeads[2:5]...)) require.Equal(t, 6, heads.Count()) head := heads.LatestHead() @@ -102,6 +110,26 @@ func TestHeads_AddHeads(t *testing.T) { head = heads.HeadByHash(uncleHash) require.NotNil(t, head) require.Equal(t, 3, int(head.ChainLength())) + // returns an error, if newHead creates cycle + t.Run("Returns an error, if newHead create cycle", func(t *testing.T) { + cycleHead := &evmtypes.Head{ + Hash: heads.LatestHead().EarliestInChain().ParentHash, + ParentHash: heads.LatestHead().Hash, + } + // 1. try adding in front + cycleHead.Number = heads.LatestHead().Number + 1 + assert.EqualError(t, heads.AddHeads(cycleHead), "potential cycle detected while adding newHead as parent: expected head number to strictly decrease in 'child -> parent' relation: child(Head{Number: 1, Hash: 0x0000000000000000000000000000000000000000000000000000000000000001, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000000}), parent(Head{Number: 6, Hash: 0x0000000000000000000000000000000000000000000000000000000000000000, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000005})") + // 2. try adding to back + cycleHead.Number = heads.LatestHead().EarliestInChain().Number - 1 + assert.EqualError(t, heads.AddHeads(cycleHead), "potential cycle detected while adding newHead as child: expected head number to strictly decrease in 'child -> parent' relation: child(Head{Number: 0, Hash: 0x0000000000000000000000000000000000000000000000000000000000000000, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000005}), parent(Head{Number: 5, Hash: 0x0000000000000000000000000000000000000000000000000000000000000005, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000004})") + // 3. try adding to back with reference to self + cycleHead = &evmtypes.Head{ + Number: 1000, + Hash: common.BigToHash(big.NewInt(1000)), + ParentHash: common.BigToHash(big.NewInt(1000)), + } + assert.EqualError(t, heads.AddHeads(cycleHead), "cycle detected: newHeads reference itself newHead(Head{Number: 1000, Hash: 0x00000000000000000000000000000000000000000000000000000000000003e8, ParentHash: 0x00000000000000000000000000000000000000000000000000000000000003e8})") + }) } func TestHeads_MarkFinalized(t *testing.T) { @@ -110,7 +138,7 @@ func TestHeads_MarkFinalized(t *testing.T) { heads := headtracker.NewHeads() // create chain - // H0 <- H1 <- H2 <- H3 <- H4 <- H5 + // H0 <- H1 <- H2 <- H3 <- H4 <- H5 - Canonical // \ \ // H1Uncle H2Uncle // @@ -127,35 +155,80 @@ func TestHeads_MarkFinalized(t *testing.T) { h5 := newHead(5, h4.Hash) h2Uncle := newHead(2, h1.Hash) - allHeads := []*evmtypes.Head{h0, h1, h1Uncle, h2, h2Uncle, h3, h4, h5} - heads.AddHeads(allHeads...) + assert.NoError(t, heads.AddHeads(h0, h1, h1Uncle, h2, h2Uncle, h3, h4, h5)) // mark h3 and all ancestors as finalized require.True(t, heads.MarkFinalized(h3.Hash, h1.BlockNumber()), "expected MarkFinalized succeed") - // original heads remain unchanged - for _, h := range allHeads { - assert.False(t, h.IsFinalized, "expected original heads to remain unfinalized") - } - // h0 is too old. It should not be available directly or through its children assert.Nil(t, heads.HeadByHash(h0.Hash)) - assert.Nil(t, heads.HeadByHash(h1.Hash).Parent) - assert.Nil(t, heads.HeadByHash(h1Uncle.Hash).Parent) - assert.Nil(t, heads.HeadByHash(h2Uncle.Hash).Parent.Parent) + assert.Nil(t, heads.HeadByHash(h1.Hash).Parent.Load()) + assert.Nil(t, heads.HeadByHash(h1Uncle.Hash).Parent.Load()) + assert.Nil(t, heads.HeadByHash(h2Uncle.Hash).Parent.Load().Parent.Load()) require.False(t, heads.MarkFinalized(utils.NewHash(), 0), "expected false if finalized hash was not found in existing LatestHead chain") ensureProperFinalization := func(t *testing.T) { t.Helper() for _, head := range []*evmtypes.Head{h5, h4} { - require.False(t, heads.HeadByHash(head.Hash).IsFinalized, "expected h4-h5 not to be finalized", head.BlockNumber()) + require.False(t, heads.HeadByHash(head.Hash).IsFinalized.Load(), "expected h4-h5 not to be finalized", head.BlockNumber()) } for _, head := range []*evmtypes.Head{h3, h2, h1} { - require.True(t, heads.HeadByHash(head.Hash).IsFinalized, "expected h3 and all ancestors to be finalized", head.BlockNumber()) + require.True(t, heads.HeadByHash(head.Hash).IsFinalized.Load(), "expected h3 and all ancestors to be finalized", head.BlockNumber()) } - require.False(t, heads.HeadByHash(h2Uncle.Hash).IsFinalized, "expected uncle block not to be marked as finalized") + require.False(t, heads.HeadByHash(h2Uncle.Hash).IsFinalized.Load(), "expected uncle block not to be marked as finalized") } t.Run("blocks were correctly marked as finalized", ensureProperFinalization) - heads.AddHeads(h0, h1, h2, h2Uncle, h3, h4, h5) + assert.NoError(t, heads.AddHeads(h0, h1, h2, h2Uncle, h3, h4, h5)) t.Run("blocks remain finalized after re adding them to the Heads", ensureProperFinalization) + + // ensure that IsFinalized is propagated, when older blocks are added + // 1. remove all blocks older than 3 + heads.MarkFinalized(h3.Hash, 3) + // 2. ensure that h2 and h1 are no longer present + assert.Nil(t, heads.HeadByHash(h2.Hash)) + assert.Nil(t, heads.HeadByHash(h1.Hash)) + // 3. add blocks back, starting from older + assert.NoError(t, heads.AddHeads(h1)) + assert.False(t, heads.HeadByHash(h1.Hash).IsFinalized.Load(), "expected h1 to not be finalized as it was not explicitly marked and there no path to h3") + assert.NoError(t, heads.AddHeads(h2)) + // 4. now h2 and h1 must be marked as finalized + assert.True(t, heads.HeadByHash(h1.Hash).IsFinalized.Load()) + assert.True(t, heads.HeadByHash(h2.Hash).IsFinalized.Load()) +} + +func BenchmarkEarliestHeadInChain(b *testing.B) { + const latestBlockNum = 200_000 + blocks := NewBlocks(b, latestBlockNum+1) + b.ResetTimer() + for i := 0; i < b.N; i++ { + latest := blocks.Head(latestBlockNum) + earliest := latest.EarliestHeadInChain() + // perform sanity check + assert.NotEqual(b, latest.BlockNumber(), earliest.BlockNumber()) + assert.NotEqual(b, latest.BlockHash(), earliest.BlockHash()) + } +} + +// BenchmarkSimulated_Backfill - benchmarks AddHeads & MarkFinalized as if it was performed by HeadTracker's backfill +func BenchmarkHeads_SimulatedBackfill(b *testing.B) { + makeHash := func(n int64) common.Hash { + return common.BigToHash(big.NewInt(n)) + } + makeHead := func(n int64) *evmtypes.Head { + return &evmtypes.Head{Number: n, Hash: makeHash(n), ParentHash: makeHash(n - 1)} + } + + const finalityDepth = 16_000 // observed value on Arbitrum + // populate with initial values + heads := headtracker.NewHeads() + for i := int64(1); i <= finalityDepth; i++ { + assert.NoError(b, heads.AddHeads(makeHead(i))) + } + heads.MarkFinalized(makeHash(1), 1) + // focus benchmark on processing of a new latest block + b.ResetTimer() + for i := int64(1); i <= int64(b.N); i++ { + assert.NoError(b, heads.AddHeads(makeHead(finalityDepth+i))) + heads.MarkFinalized(makeHash(i), i) + } } diff --git a/core/chains/evm/headtracker/heap.go b/core/chains/evm/headtracker/heap.go new file mode 100644 index 00000000000..572ed541dfa --- /dev/null +++ b/core/chains/evm/headtracker/heap.go @@ -0,0 +1,35 @@ +package headtracker + +import evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + +type headsHeap struct { + values []*evmtypes.Head +} + +func (h *headsHeap) Len() int { + return len(h.values) +} + +func (h *headsHeap) Swap(i, j int) { + h.values[i], h.values[j] = h.values[j], h.values[i] +} + +func (h *headsHeap) Less(i, j int) bool { + return h.values[i].Number < h.values[j].Number +} + +func (h *headsHeap) Pop() any { + n := len(h.values) - 1 + old := h.values[n] + h.values[n] = nil + h.values = h.values[:n] + return old +} + +func (h *headsHeap) Push(v any) { + h.values = append(h.values, v.(*evmtypes.Head)) +} + +func (h *headsHeap) Peek() *evmtypes.Head { + return h.values[0] +} diff --git a/core/chains/evm/headtracker/orm.go b/core/chains/evm/headtracker/orm.go index 9d569ade08d..5595fc7366a 100644 --- a/core/chains/evm/headtracker/orm.go +++ b/core/chains/evm/headtracker/orm.go @@ -9,6 +9,7 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) @@ -82,3 +83,29 @@ func (orm *DbORM) HeadByHash(ctx context.Context, hash common.Hash) (head *evmty } return head, err } + +type nullORM struct{} + +func NewNullORM() ORM { + return &nullORM{} +} + +func (orm *nullORM) IdempotentInsertHead(ctx context.Context, head *evmtypes.Head) error { + return nil +} + +func (orm *nullORM) TrimOldHeads(ctx context.Context, minBlockNumber int64) (err error) { + return nil +} + +func (orm *nullORM) LatestHead(ctx context.Context) (head *evmtypes.Head, err error) { + return nil, nil +} + +func (orm *nullORM) LatestHeads(ctx context.Context, minBlockNumer int64) (heads []*evmtypes.Head, err error) { + return nil, nil +} + +func (orm *nullORM) HeadByHash(ctx context.Context, hash common.Hash) (head *evmtypes.Head, err error) { + return nil, nil +} diff --git a/core/chains/evm/headtracker/types/types.go b/core/chains/evm/headtracker/types/types.go index 1a03f3cec6f..ca5a79fc68d 100644 --- a/core/chains/evm/headtracker/types/types.go +++ b/core/chains/evm/headtracker/types/types.go @@ -2,10 +2,13 @@ package types import ( "context" + "math/big" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/common/headtracker" + htrktypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -22,4 +25,5 @@ type ( HeadTrackable = headtracker.HeadTrackable[*evmtypes.Head, common.Hash] HeadListener = headtracker.HeadListener[*evmtypes.Head, common.Hash] HeadBroadcaster = headtracker.HeadBroadcaster[*evmtypes.Head, common.Hash] + Client = htrktypes.Client[*evmtypes.Head, ethereum.Subscription, *big.Int, common.Hash] ) diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go index e7f02d1199c..3e37678bee3 100644 --- a/core/chains/evm/log/broadcaster.go +++ b/core/chains/evm/log/broadcaster.go @@ -590,7 +590,7 @@ func (b *broadcaster) onNewHeads() { b.logger.Errorf("Failed to query for log broadcasts, %v", err) return } - b.registrations.sendLogs(ctx, logs, *latestHead, broadcasts, b.orm) + b.registrations.sendLogs(ctx, logs, latestHead, broadcasts, b.orm) if err := b.orm.SetPendingMinBlock(ctx, nil); err != nil { b.logger.Errorw("Failed to set pending broadcasts number null", "err", err) } @@ -605,7 +605,7 @@ func (b *broadcaster) onNewHeads() { return } - b.registrations.sendLogs(ctx, logs, *latestHead, broadcasts, b.orm) + b.registrations.sendLogs(ctx, logs, latestHead, broadcasts, b.orm) } newMin := b.logPool.deleteOlderLogs(keptDepth) if err := b.orm.SetPendingMinBlock(ctx, newMin); err != nil { diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index df0d54680cd..45248b83947 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -97,7 +97,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, lb := log.NewTestBroadcaster(orm, ethClient, config.EVM(), lggr, highestSeenHead, mailMon) kst := cltest.NewKeyStore(t, db) - cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{ + chainsAndConfig := evmtest.NewLegacyChainsAndConfig(t, evmtest.TestChainOpts{ Client: ethClient, GeneralConfig: globalConfig, DB: db, @@ -107,10 +107,11 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, }) m := make(map[string]legacyevm.Chain) - for _, r := range cc.Slice() { - m[r.Chain().ID().String()] = r.Chain() + for _, r := range chainsAndConfig.Slice() { + m[r.ID().String()] = r } - legacyChains := legacyevm.NewLegacyChains(m, cc.AppConfig().EVMConfigs()) + + legacyChains := chainsAndConfig.NewLegacyChains() pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), legacyChains, db, kst, nil, nil) return &broadcasterHelper{ diff --git a/core/chains/evm/log/registrations.go b/core/chains/evm/log/registrations.go index 68dd93b9d88..01104349a6f 100644 --- a/core/chains/evm/log/registrations.go +++ b/core/chains/evm/log/registrations.go @@ -11,6 +11,7 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" @@ -215,7 +216,7 @@ func (r *registrations) isAddressRegistered(address common.Address) bool { return false } -func (r *registrations) sendLogs(ctx context.Context, logsToSend []logsOnBlock, latestHead evmtypes.Head, broadcasts []LogBroadcast, bc broadcastCreator) { +func (r *registrations) sendLogs(ctx context.Context, logsToSend []logsOnBlock, latestHead *evmtypes.Head, broadcasts []LogBroadcast, bc broadcastCreator) { broadcastsExisting := make(map[LogBroadcastAsKey]bool) for _, b := range broadcasts { broadcastsExisting[b.AsKey()] = b.Consumed @@ -387,7 +388,7 @@ type broadcastCreator interface { CreateBroadcast(ctx context.Context, blockHash common.Hash, blockNumber uint64, logIndex uint, jobID int32) error } -func (r *handler) sendLog(ctx context.Context, log types.Log, latestHead evmtypes.Head, +func (r *handler) sendLog(ctx context.Context, log types.Log, latestHead *evmtypes.Head, broadcasts map[LogBroadcastAsKey]bool, bc broadcastCreator, logger logger.Logger) { diff --git a/core/chains/evm/logpoller/disabled.go b/core/chains/evm/logpoller/disabled.go index f30837bcfee..a29dd5ea11a 100644 --- a/core/chains/evm/logpoller/disabled.go +++ b/core/chains/evm/logpoller/disabled.go @@ -118,7 +118,7 @@ func (d disabled) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, return nil, ErrDisabled } -func (d disabled) FilteredLogs(_ context.Context, _ query.KeyFilter, _ query.LimitAndSort, _ string) ([]Log, error) { +func (d disabled) FilteredLogs(_ context.Context, _ []query.Expression, _ query.LimitAndSort, _ string) ([]Log, error) { return nil, ErrDisabled } diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index dee5d1d1a5d..eeba2b43df4 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "math/big" + "math/rand" "sort" "strings" "sync" @@ -24,11 +25,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/timeutil" "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) @@ -68,7 +70,7 @@ type LogPoller interface { LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) // chainlink-common query filtering - FilteredLogs(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) + FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) } type LogPollerTest interface { @@ -113,6 +115,7 @@ type logPoller struct { backfillBatchSize int64 // batch size to use when backfilling finalized logs rpcBatchSize int64 // batch size to use for fallback RPC calls made in GetBlocks logPrunePageSize int64 + clientErrors config.ClientErrors backupPollerNextBlock int64 // next block to be processed by Backup LogPoller backupPollerBlockDelay int64 // how far behind regular LogPoller should BackupLogPoller run. 0 = disabled @@ -131,7 +134,8 @@ type logPoller struct { // Usually the only way to recover is to manually remove the offending logs and block from the database. // LogPoller keeps running in infinite loop, so whenever the invalid state is removed from the database it should // recover automatically without needing to restart the LogPoller. - finalityViolated *atomic.Bool + finalityViolated atomic.Bool + countBasedLogPruningActive atomic.Bool } type Opts struct { @@ -143,6 +147,7 @@ type Opts struct { KeepFinalizedBlocksDepth int64 BackupPollerBlockDelay int64 LogPrunePageSize int64 + ClientErrors config.ClientErrors } // NewLogPoller creates a log poller. Note there is an assumption @@ -172,9 +177,9 @@ func NewLogPoller(orm ORM, ec Client, lggr logger.Logger, headTracker HeadTracke rpcBatchSize: opts.RpcBatchSize, keepFinalizedBlocksDepth: opts.KeepFinalizedBlocksDepth, logPrunePageSize: opts.LogPrunePageSize, + clientErrors: opts.ClientErrors, filters: make(map[string]Filter), filterDirty: true, // Always build Filter on first call to cache an empty filter if nothing registered yet. - finalityViolated: new(atomic.Bool), } } @@ -212,6 +217,12 @@ func (filter *Filter) Contains(other *Filter) bool { if other == nil { return true } + if other.Retention != filter.Retention { + return false + } + if other.MaxLogsKept != filter.MaxLogsKept { + return false + } addresses := make(map[common.Address]interface{}) for _, addr := range filter.Addresses { addresses[addr] = struct{}{} @@ -277,7 +288,7 @@ func (lp *logPoller) RegisterFilter(ctx context.Context, filter Filter) error { lp.lggr.Warnw("Filter already present, no-op", "name", filter.Name, "filter", filter) return nil } - lp.lggr.Warnw("Updating existing filter with more events or addresses", "name", filter.Name, "filter", filter) + lp.lggr.Warnw("Updating existing filter", "name", filter.Name, "filter", filter) } if err := lp.orm.InsertFilter(ctx, filter); err != nil { @@ -285,6 +296,9 @@ func (lp *logPoller) RegisterFilter(ctx context.Context, filter Filter) error { } lp.filters[filter.Name] = filter lp.filterDirty = true + if filter.MaxLogsKept > 0 { + lp.countBasedLogPruningActive.Store(true) + } return nil } @@ -540,18 +554,47 @@ func (lp *logPoller) GetReplayFromBlock(ctx context.Context, requested int64) (i return mathutil.Min(requested, lastProcessed.BlockNumber), nil } +// loadFilters loads the filters from db, and activates count-based Log Pruning +// if required by any of the filters func (lp *logPoller) loadFilters(ctx context.Context) error { + filters, err := lp.lockAndLoadFilters(ctx) + if err != nil { + return pkgerrors.Wrapf(err, "Failed to load initial filters from db, retrying") + } + if lp.countBasedLogPruningActive.Load() { + return nil + } + for _, filter := range filters { + if filter.MaxLogsKept != 0 { + lp.countBasedLogPruningActive.Store(true) + return nil + } + } + return nil +} + +// lockAndLoadFilters is the part of loadFilters() requiring a filterMu lock +func (lp *logPoller) lockAndLoadFilters(ctx context.Context) (filters map[string]Filter, err error) { lp.filterMu.Lock() defer lp.filterMu.Unlock() - filters, err := lp.orm.LoadFilters(ctx) + filters, err = lp.orm.LoadFilters(ctx) if err != nil { - return pkgerrors.Wrapf(err, "Failed to load initial filters from db, retrying") + return filters, err } lp.filters = filters lp.filterDirty = true - return nil + return filters, nil +} + +// tickStaggeredDelay chooses a uniformly random amount of time to delay between minDelay and minDelay + period +func tickStaggeredDelay(minDelay time.Duration, period time.Duration) <-chan time.Time { + return time.After(minDelay + timeutil.JitterPct(1.0).Apply(period/2)) +} + +func tickWithDefaultJitter(interval time.Duration) <-chan time.Time { + return time.After(services.DefaultJitter.Apply(interval)) } func (lp *logPoller) run() { @@ -594,18 +637,11 @@ func (lp *logPoller) run() { } // Otherwise this is the first poll _ever_ on a new chain. // Only safe thing to do is to start at the first finalized block. - latestBlock, latestFinalizedBlockNumber, err := lp.latestBlocks(ctx) + _, latestFinalizedBlockNumber, err := lp.latestBlocks(ctx) if err != nil { lp.lggr.Warnw("Unable to get latest for first poll", "err", err) continue } - // Do not support polling chains which don't even have finality depth worth of blocks. - // Could conceivably support this but not worth the effort. - // Need last finalized block number to be higher than 0 - if latestFinalizedBlockNumber <= 0 { - lp.lggr.Warnw("Insufficient number of blocks on chain, waiting for finality depth", "err", err, "latest", latestBlock.Number) - continue - } // Starting at the first finalized block. We do not backfill the first finalized block. start = latestFinalizedBlockNumber } else { @@ -638,31 +674,62 @@ func (lp *logPoller) backgroundWorkerRun() { ctx, cancel := lp.stopCh.NewCtx() defer cancel() + blockPruneShortInterval := lp.pollPeriod * 100 + blockPruneInterval := blockPruneShortInterval * 10 + logPruneShortInterval := lp.pollPeriod * 241 // no common factors with 100 + logPruneInterval := logPruneShortInterval * 10 + // Avoid putting too much pressure on the database by staggering the pruning of old blocks and logs. // Usually, node after restart will have some work to boot the plugins and other services. - // Deferring first prune by minutes reduces risk of putting too much pressure on the database. - blockPruneTick := time.After(5 * time.Minute) - logPruneTick := time.After(10 * time.Minute) + // Deferring first prune by at least 5 mins reduces risk of putting too much pressure on the database. + blockPruneTick := tickStaggeredDelay(5*time.Minute, blockPruneInterval) + logPruneTick := tickStaggeredDelay(5*time.Minute, logPruneInterval) + + // Start initial prune of unmatched logs after 5-15 successful expired log prunes, so that not all chains start + // around the same time. After that, every 20 successful expired log prunes. + successfulExpiredLogPrunes := 5 + rand.Intn(10) //nolint:gosec for { select { case <-ctx.Done(): return case <-blockPruneTick: - blockPruneTick = time.After(utils.WithJitter(lp.pollPeriod * 1000)) + lp.lggr.Infow("pruning old blocks") + blockPruneTick = tickWithDefaultJitter(blockPruneInterval) if allRemoved, err := lp.PruneOldBlocks(ctx); err != nil { - lp.lggr.Errorw("Unable to prune old blocks", "err", err) + lp.lggr.Errorw("unable to prune old blocks", "err", err) } else if !allRemoved { // Tick faster when cleanup can't keep up with the pace of new blocks - blockPruneTick = time.After(utils.WithJitter(lp.pollPeriod * 100)) + blockPruneTick = tickWithDefaultJitter(blockPruneShortInterval) + lp.lggr.Warnw("reached page limit while pruning old blocks") + } else { + lp.lggr.Debugw("finished pruning old blocks") } case <-logPruneTick: - logPruneTick = time.After(utils.WithJitter(lp.pollPeriod * 2401)) // = 7^5 avoids common factors with 1000 + logPruneTick = tickWithDefaultJitter(logPruneInterval) + lp.lggr.Infof("pruning expired logs") if allRemoved, err := lp.PruneExpiredLogs(ctx); err != nil { - lp.lggr.Errorw("Unable to prune expired logs", "err", err) + lp.lggr.Errorw("unable to prune expired logs", "err", err) } else if !allRemoved { + lp.lggr.Warnw("reached page limit while pruning expired logs") // Tick faster when cleanup can't keep up with the pace of new logs - logPruneTick = time.After(utils.WithJitter(lp.pollPeriod * 241)) + logPruneTick = tickWithDefaultJitter(logPruneShortInterval) + } else if successfulExpiredLogPrunes >= 20 { + // Only prune unmatched logs if we've successfully pruned all expired logs at least 20 times + // since the last time unmatched logs were pruned + lp.lggr.Infof("finished pruning expired logs: pruning unmatched logs") + if allRemoved, err := lp.PruneUnmatchedLogs(ctx); err != nil { + lp.lggr.Errorw("unable to prune unmatched logs", "err", err) + } else if !allRemoved { + lp.lggr.Warnw("reached page limit while pruning unmatched logs") + logPruneTick = tickWithDefaultJitter(logPruneShortInterval) + } else { + lp.lggr.Debugw("finished pruning unmatched logs") + successfulExpiredLogPrunes = 0 + } + } else { + lp.lggr.Debugw("finished pruning expired logs") + successfulExpiredLogPrunes++ } } } @@ -794,8 +861,6 @@ func (lp *logPoller) blocksFromLogs(ctx context.Context, logs []types.Log, endBl return lp.GetBlocksRange(ctx, numbers) } -const jsonRpcLimitExceeded = -32005 // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md - // backfill will query FilterLogs in batches for logs in the // block range [start, end] and save them to the db. // Retries until ctx cancelled. Will return an error if cancelled @@ -807,13 +872,11 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { gethLogs, err := lp.ec.FilterLogs(ctx, lp.Filter(big.NewInt(from), big.NewInt(to), nil)) if err != nil { - var rpcErr client.JsonError - if pkgerrors.As(err, &rpcErr) { - if rpcErr.Code != jsonRpcLimitExceeded { - lp.lggr.Errorw("Unable to query for logs", "err", err, "from", from, "to", to) - return err - } + if !client.IsTooManyResults(err, lp.clientErrors) { + lp.lggr.Errorw("Unable to query for logs", "err", err, "from", from, "to", to) + return err } + if batchSize == 1 { lp.lggr.Criticalw("Too many log results in a single block, failed to retrieve logs! Node may be running in a degraded state.", "err", err, "from", from, "to", to, "LogBackfillBatchSize", lp.backfillBatchSize) return err @@ -1023,8 +1086,16 @@ func (lp *logPoller) latestBlocks(ctx context.Context) (*evmtypes.Head, int64, e return nil, 0, fmt.Errorf("failed to get latest and latest finalized block from HeadTracker: %w", err) } - lp.lggr.Debugw("Latest blocks read from chain", "latest", latest.Number, "finalized", finalized.BlockNumber()) - return latest, finalized.BlockNumber(), nil + finalizedBN := finalized.BlockNumber() + // This is a dirty trick that allows LogPoller to function properly in tests where chain needs significant time to + // reach finality depth. An alternative to this one-liner is a database migration that drops restriction + // LogPollerBlock.FinalizedBlockNumber > 0 (which we actually want to keep to spot cases when FinalizedBlockNumber was simply not populated) + // and refactoring of queries that assume that restriction still holds. + if finalizedBN == 0 { + finalizedBN = 1 + } + lp.lggr.Debugw("Latest blocks read from chain", "latest", latest.Number, "finalized", finalizedBN) + return latest, finalizedBN, nil } // Find the first place where our chain and their chain have the same block, @@ -1036,7 +1107,7 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He if err != nil { return nil, err } - blockAfterLCA := *current + blockAfterLCA := current // We expect reorgs up to the block after latestFinalizedBlock // 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. @@ -1048,10 +1119,10 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He } if parent.Hash == ourParentBlockHash.BlockHash { // If we do have the blockhash, return blockAfterLCA - return &blockAfterLCA, nil + return blockAfterLCA, nil } // Otherwise get a new parent and update blockAfterLCA. - blockAfterLCA = *parent + blockAfterLCA = parent parent, err = lp.ec.HeadByHash(ctx, parent.ParentHash) if err != nil { return nil, err @@ -1065,7 +1136,8 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He } // PruneOldBlocks removes blocks that are > lp.keepFinalizedBlocksDepth behind the latest finalized block. -// Returns whether all blocks eligible for pruning were removed. If logPrunePageSize is set to 0, it will always return true. +// Returns whether all blocks eligible for pruning were removed. If logPrunePageSize is set to 0, then it +// will always return true unless there is an actual error. func (lp *logPoller) PruneOldBlocks(ctx context.Context) (bool, error) { latestBlock, err := lp.orm.SelectLatestBlock(ctx) if err != nil { @@ -1089,10 +1161,46 @@ func (lp *logPoller) PruneOldBlocks(ctx context.Context) (bool, error) { return lp.logPrunePageSize == 0 || rowsRemoved < lp.logPrunePageSize, err } -// PruneExpiredLogs logs that are older than their retention period defined in Filter. -// Returns whether all logs eligible for pruning were removed. If logPrunePageSize is set to 0, it will always return true. +// PruneExpiredLogs will attempt to remove any logs which have passed their retention period. Returns whether all expired +// logs were removed. If logPrunePageSize is set to 0, it will always return true unless an actual error is encountered func (lp *logPoller) PruneExpiredLogs(ctx context.Context) (bool, error) { + done := true + rowsRemoved, err := lp.orm.DeleteExpiredLogs(ctx, lp.logPrunePageSize) + if err != nil { + lp.lggr.Errorw("Unable to find excess logs for pruning", "err", err) + return false, err + } else if lp.logPrunePageSize != 0 && rowsRemoved == lp.logPrunePageSize { + done = false + } + + if !lp.countBasedLogPruningActive.Load() { + return done, err + } + + rowIDs, err := lp.orm.SelectExcessLogIDs(ctx, lp.logPrunePageSize) + if err != nil { + lp.lggr.Errorw("Unable to find excess logs for pruning", "err", err) + return false, err + } + rowsRemoved, err = lp.orm.DeleteLogsByRowID(ctx, rowIDs) + if err != nil { + lp.lggr.Errorw("Unable to prune excess logs", "err", err) + } else if lp.logPrunePageSize != 0 && rowsRemoved == lp.logPrunePageSize { + done = false + } + return done, err +} + +// PruneUnmatchedLogs will attempt to remove any logs which no longer match a registered filter. Returns whether all unmatched +// logs were removed. If logPrunePageSize is set to 0, it will always return true unless an actual error is encountered +func (lp *logPoller) PruneUnmatchedLogs(ctx context.Context) (bool, error) { + ids, err := lp.orm.SelectUnmatchedLogIDs(ctx, lp.logPrunePageSize) + if err != nil { + return false, err + } + rowsRemoved, err := lp.orm.DeleteLogsByRowID(ctx, ids) + return lp.logPrunePageSize == 0 || rowsRemoved < lp.logPrunePageSize, err } @@ -1518,6 +1626,25 @@ func EvmWord(i uint64) common.Hash { return common.BytesToHash(b) } -func (lp *logPoller) FilteredLogs(ctx context.Context, queryFilter query.KeyFilter, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) { +func (lp *logPoller) FilteredLogs(ctx context.Context, queryFilter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) { return lp.orm.FilteredLogs(ctx, queryFilter, limitAndSort, queryName) } + +// Where is a query.Where wrapper that ignores the Key and returns a slice of query.Expression rather than query.KeyFilter. +// If no expressions are provided, or an error occurs, an empty slice is returned. +func Where(expressions ...query.Expression) ([]query.Expression, error) { + filter, err := query.Where( + "", + expressions..., + ) + + if err != nil { + return []query.Expression{}, err + } + + if filter.Expressions == nil { + return []query.Expression{}, nil + } + + return filter.Expressions, nil +} diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index 448710b93f3..620bbf14f41 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -7,6 +7,7 @@ import ( "math/big" "strings" "sync" + "sync/atomic" "testing" "time" @@ -287,12 +288,14 @@ func TestLogPoller_Replay(t *testing.T) { db := pgtest.NewSqlxDB(t) orm := NewORM(chainID, db, lggr) - head := evmtypes.Head{Number: 4} + var head atomic.Pointer[evmtypes.Head] + head.Store(&evmtypes.Head{Number: 4}) + events := []common.Hash{EmitterABI.Events["Log1"].ID} log1 := types.Log{ Index: 0, BlockHash: common.Hash{}, - BlockNumber: uint64(head.Number), + BlockNumber: uint64(head.Load().Number), Topics: events, Address: addr, TxHash: common.HexToHash("0x1234"), @@ -301,8 +304,7 @@ func TestLogPoller_Replay(t *testing.T) { ec := evmclimocks.NewClient(t) ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(context.Context, *big.Int) (*evmtypes.Head, error) { - headCopy := head - return &headCopy, nil + return head.Load(), nil }) ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Once() ec.On("ConfiguredChainID").Return(chainID, nil) @@ -318,9 +320,9 @@ func TestLogPoller_Replay(t *testing.T) { headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(func(ctx context.Context) (*evmtypes.Head, *evmtypes.Head, error) { - headCopy := head - finalized := &evmtypes.Head{Number: headCopy.Number - lpOpts.FinalityDepth} - return &headCopy, finalized, nil + h := head.Load() + finalized := &evmtypes.Head{Number: h.Number - lpOpts.FinalityDepth} + return h, finalized, nil }) lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) @@ -394,7 +396,7 @@ func TestLogPoller_Replay(t *testing.T) { var wg sync.WaitGroup defer func() { wg.Wait() }() ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) { - head = evmtypes.Head{Number: 4} + head.Store(&evmtypes.Head{Number: 4}) wg.Add(1) go func() { defer wg.Done() @@ -421,7 +423,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 = evmtypes.Head{Number: 5} + head.Store(&evmtypes.Head{Number: 5}) t.Cleanup(lp.reset) servicetest.Run(t, lp) @@ -448,7 +450,7 @@ func TestLogPoller_Replay(t *testing.T) { go func() { defer close(done) - head = evmtypes.Head{Number: 4} // Restore latest block to 4, so this matches the fromBlock requested + head.Store(&evmtypes.Head{Number: 4}) // Restore latest block to 4, so this matches the fromBlock requested select { case lp.replayStart <- 4: case <-ctx.Done(): @@ -469,7 +471,7 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) t.Cleanup(lp.reset) - head = evmtypes.Head{Number: 5} // Latest block must be > lastProcessed in order for SaveAndPollLogs() to call FilterLogs() + head.Store(&evmtypes.Head{Number: 5}) // Latest block must be > lastProcessed in order for SaveAndPollLogs() to call FilterLogs() servicetest.Run(t, lp) select { @@ -482,7 +484,8 @@ func TestLogPoller_Replay(t *testing.T) { // ReplayAsync should return as soon as replayStart is received t.Run("ReplayAsync success", func(t *testing.T) { t.Cleanup(lp.reset) - head = evmtypes.Head{Number: 5} + + head.Store(&evmtypes.Head{Number: 5}) ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) mockBatchCallContext(t, ec) servicetest.Run(t, lp) @@ -496,7 +499,7 @@ func TestLogPoller_Replay(t *testing.T) { ctx := testutils.Context(t) t.Cleanup(lp.reset) servicetest.Run(t, lp) - head = evmtypes.Head{Number: 4} + head.Store(&evmtypes.Head{Number: 4}) anyErr := pkgerrors.New("async error") observedLogs.TakeAll() @@ -528,7 +531,8 @@ func TestLogPoller_Replay(t *testing.T) { err := lp.orm.DeleteLogsAndBlocksAfter(ctx, 0) require.NoError(t, err) - err = lp.orm.InsertBlock(ctx, head.Hash, head.Number, head.Timestamp, head.Number) + h := head.Load() + err = lp.orm.InsertBlock(ctx, h.Hash, h.Number, h.Timestamp, h.Number) require.NoError(t, err) ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) @@ -565,7 +569,8 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) { }) t.Run("headTracker returns valid chain", func(t *testing.T) { headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) - finalizedBlock := &evmtypes.Head{Number: 2, IsFinalized: true} + finalizedBlock := &evmtypes.Head{Number: 2} + finalizedBlock.IsFinalized.Store(true) head := &evmtypes.Head{Number: 10} headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalizedBlock, nil) diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 860b588c771..c4617503f0c 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -26,6 +26,8 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" @@ -36,10 +38,10 @@ import ( "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/internal/cltest/heavyweight" "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" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) func logRuntime(t testing.TB, start time.Time) { @@ -190,7 +192,7 @@ func TestLogPoller_Integration(t *testing.T) { require.Equal(t, 4, len(logs)) // Once the backup poller runs we should also have the log from block 3 - testutils.AssertEventually(t, func() bool { + testutils.RequireEventually(t, func() bool { l, err2 := th.LogPoller.Logs(ctx, 3, 3, EmitterABI.Events["Log1"].ID, th.EmitterAddress1) require.NoError(t, err2) return len(l) == 1 @@ -1516,7 +1518,7 @@ func TestLogPoller_DBErrorHandling(t *testing.T) { time.Sleep(100 * time.Millisecond) require.NoError(t, lp.Start(ctx)) - testutils.AssertEventually(t, func() bool { + testutils.RequireEventually(t, func() bool { return observedLogs.Len() >= 1 }) err = lp.Close() @@ -1542,6 +1544,8 @@ type getLogErrData struct { } func TestTooManyLogResults(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) ec := evmtest.NewEthClientMockWithDefaultChain(t) lggr, obs := logger.TestObserved(t, zapcore.DebugLevel) @@ -1561,89 +1565,126 @@ func TestTooManyLogResults(t *testing.T) { lp := logpoller.NewLogPoller(o, ec, lggr, headTracker, lpOpts) expected := []int64{10, 5, 2, 1} - clientErr := client.JsonError{ + tooLargeErr := client.JsonError{ Code: -32005, Data: getLogErrData{"0x100E698", "0x100E6D4", 10000}, Message: "query returned more than 10000 results. Try with this block range [0x100E698, 0x100E6D4].", } - // Simulate currentBlock = 300 - head := &evmtypes.Head{Number: 300} - finalized := &evmtypes.Head{Number: head.Number - lpOpts.FinalityDepth} - headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() - call1 := ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(ctx context.Context, blockNumber *big.Int) (*evmtypes.Head, error) { + var filterLogsCall *mock.Call + head := &evmtypes.Head{} + finalized := &evmtypes.Head{} + + ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(ctx context.Context, blockNumber *big.Int) (*evmtypes.Head, error) { if blockNumber == nil { require.FailNow(t, "unexpected call to get current head") } return &evmtypes.Head{Number: blockNumber.Int64()}, nil }) - call2 := ec.On("FilterLogs", mock.Anything, mock.Anything).Return(func(ctx context.Context, fq ethereum.FilterQuery) (logs []types.Log, err error) { - if fq.BlockHash != nil { - return []types.Log{}, nil // succeed when single block requested - } - from := fq.FromBlock.Uint64() - to := fq.ToBlock.Uint64() - if to-from >= 4 { - return []types.Log{}, &clientErr // return "too many results" error if block range spans 4 or more blocks - } - return logs, err - }) + t.Run("halves size until small enough, then succeeds", func(t *testing.T) { + // Simulate currentBlock = 300 + head.Number = 300 + finalized.Number = head.Number - lpOpts.FinalityDepth + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() - addr := testutils.NewAddress() - err := lp.RegisterFilter(ctx, logpoller.Filter{ - Name: "Integration test", - EventSigs: []common.Hash{EmitterABI.Events["Log1"].ID}, - Addresses: []common.Address{addr}, - }) - require.NoError(t, err) - lp.PollAndSaveLogs(ctx, 5) - block, err2 := o.SelectLatestBlock(ctx) - require.NoError(t, err2) - assert.Equal(t, int64(298), block.BlockNumber) - - logs := obs.FilterLevelExact(zapcore.WarnLevel).FilterMessageSnippet("halving block range batch size").FilterFieldKey("newBatchSize").All() - // Should have tried again 3 times--first reducing batch size to 10, then 5, then 2 - require.Len(t, logs, 3) - for i, s := range expected[:3] { - assert.Equal(t, s, logs[i].ContextMap()["newBatchSize"]) - } + filterLogsCall = ec.On("FilterLogs", mock.Anything, mock.Anything).Return(func(ctx context.Context, fq ethereum.FilterQuery) (logs []types.Log, err error) { + if fq.BlockHash != nil { + return []types.Log{}, nil // succeed when single block requested + } + from := fq.FromBlock.Uint64() + to := fq.ToBlock.Uint64() + if to-from >= 4 { + return []types.Log{}, tooLargeErr // return "too many results" error if block range spans 4 or more blocks + } + return logs, err + }) - obs.TakeAll() - call1.Unset() - call2.Unset() + addr := testutils.NewAddress() + err := lp.RegisterFilter(ctx, logpoller.Filter{ + Name: "Integration test", + EventSigs: []common.Hash{EmitterABI.Events["Log1"].ID}, + Addresses: []common.Address{addr}, + }) + require.NoError(t, err) + lp.PollAndSaveLogs(ctx, 5) + block, err2 := o.SelectLatestBlock(ctx) + require.NoError(t, err2) + assert.Equal(t, int64(298), block.BlockNumber) - // Now jump to block 500, but return error no matter how small the block range gets. - // Should exit the loop with a critical error instead of hanging. - head = &evmtypes.Head{Number: 500} - finalized = &evmtypes.Head{Number: head.Number - lpOpts.FinalityDepth} - headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() - call1.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(ctx context.Context, blockNumber *big.Int) (*evmtypes.Head, error) { - if blockNumber == nil { - require.FailNow(t, "unexpected call to get current head") + logs := obs.FilterLevelExact(zapcore.WarnLevel).FilterMessageSnippet("halving block range batch size").FilterFieldKey("newBatchSize").All() + // Should have tried again 3 times--first reducing batch size to 10, then 5, then 2 + require.Len(t, logs, 3) + for i, s := range expected[:3] { + assert.Equal(t, s, logs[i].ContextMap()["newBatchSize"]) } - return &evmtypes.Head{Number: blockNumber.Int64()}, nil + filterLogsCall.Unset() }) - call2.On("FilterLogs", mock.Anything, mock.Anything).Return(func(ctx context.Context, fq ethereum.FilterQuery) (logs []types.Log, err error) { - if fq.BlockHash != nil { - return []types.Log{}, nil // succeed when single block requested + + t.Run("Halves size until single block, then reports critical error", func(t *testing.T) { + obs.TakeAll() + + // Now jump to block 500, but return error no matter how small the block range gets. + // Should exit the loop with a critical error instead of hanging. + head.Number = 500 + finalized.Number = head.Number - lpOpts.FinalityDepth + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() + filterLogsCall = ec.On("FilterLogs", mock.Anything, mock.Anything).Return(func(ctx context.Context, fq ethereum.FilterQuery) (logs []types.Log, err error) { + if fq.BlockHash != nil { + return []types.Log{}, nil // succeed when single block requested + } + return []types.Log{}, tooLargeErr // return "too many results" error if block range spans 4 or more blocks + }) + + lp.PollAndSaveLogs(ctx, 298) + block, err := o.SelectLatestBlock(ctx) + if err != nil { + assert.ErrorContains(t, err, "no rows") // In case this subtest is run by itself + } else { + assert.Equal(t, int64(298), block.BlockNumber) + } + warns := obs.FilterMessageSnippet("halving block range").FilterLevelExact(zapcore.WarnLevel).All() + crit := obs.FilterMessageSnippet("failed to retrieve logs").FilterLevelExact(zapcore.DPanicLevel).All() + require.Len(t, warns, 4) + for i, s := range expected { + assert.Equal(t, s, warns[i].ContextMap()["newBatchSize"]) } - return []types.Log{}, &clientErr // return "too many results" error if block range spans 4 or more blocks + + require.Len(t, crit, 1) + assert.Contains(t, crit[0].Message, "Too many log results in a single block") + filterLogsCall.Unset() }) - lp.PollAndSaveLogs(ctx, 298) - block, err2 = o.SelectLatestBlock(ctx) - require.NoError(t, err2) - assert.Equal(t, int64(298), block.BlockNumber) - warns := obs.FilterMessageSnippet("halving block range").FilterLevelExact(zapcore.WarnLevel).All() - crit := obs.FilterMessageSnippet("failed to retrieve logs").FilterLevelExact(zapcore.DPanicLevel).All() - require.Len(t, warns, 4) - for i, s := range expected { - assert.Equal(t, s, warns[i].ContextMap()["newBatchSize"]) - } + t.Run("Unrelated error are retried without adjusting size", func(t *testing.T) { + unrelatedError := fmt.Errorf("Unrelated to the size of the request") + head.Number = 500 + finalized.Number = head.Number - lpOpts.FinalityDepth + + obs.TakeAll() + filterLogsCall = ec.On("FilterLogs", mock.Anything, mock.Anything).Return(func(ctx context.Context, fq ethereum.FilterQuery) (logs []types.Log, err error) { + if fq.BlockHash != nil { + return []types.Log{}, nil // succeed when single block requested + } + return []types.Log{}, unrelatedError // return an unrelated error that should just be retried with same size + }) + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() - require.Len(t, crit, 1) - assert.Contains(t, crit[0].Message, "Too many log results in a single block") + lp.PollAndSaveLogs(ctx, 298) + block, err := o.SelectLatestBlock(ctx) + if err != nil { + assert.ErrorContains(t, err, "no rows") // In case this subtest is run by itself + } else { + assert.Equal(t, int64(298), block.BlockNumber) + } + 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") + }) } func Test_PollAndQueryFinalizedBlocks(t *testing.T) { @@ -1733,7 +1774,7 @@ func Test_PollAndSavePersistsFinalityInBlocks(t *testing.T) { name: "setting last finalized block number to 0 if finality is too deep", useFinalityTag: false, finalityDepth: 20, - expectedFinalizedBlock: 0, + expectedFinalizedBlock: 1, }, { name: "using finality from chain", @@ -2052,3 +2093,39 @@ func TestFindLCA(t *testing.T) { }) } } + +func TestWhere(t *testing.T) { + address := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + eventSig := common.HexToHash("0xabcdef1234567890abcdef1234567890abcdef1234") + ts := time.Now() + + expr1 := logpoller.NewAddressFilter(address) + expr2 := logpoller.NewEventSigFilter(eventSig) + expr3 := query.Timestamp(uint64(ts.Unix()), primitives.Gte) + expr4 := logpoller.NewConfirmationsFilter(evmtypes.Confirmations(0)) + + t.Run("Valid combination of filters", func(t *testing.T) { + result, err := logpoller.Where(expr1, expr2, expr3, expr4) + assert.NoError(t, err) + assert.Equal(t, []query.Expression{expr1, expr2, expr3, expr4}, result) + }) + + t.Run("No expressions (should return empty slice)", func(t *testing.T) { + result, err := logpoller.Where() + assert.NoError(t, err) + assert.Equal(t, []query.Expression{}, result) + }) + + t.Run("Invalid boolean expression", func(t *testing.T) { + invalidExpr := query.Expression{ + BoolExpression: query.BoolExpression{ + Expressions: []query.Expression{}, + }, + } + + result, err := logpoller.Where(invalidExpr) + assert.Error(t, err) + assert.EqualError(t, err, "all boolean expressions should have at least 2 expressions") + assert.Equal(t, []query.Expression{}, result) + }) +} diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index 4ce68839d16..9ae4d9767c9 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -124,7 +124,7 @@ func (_c *LogPoller_DeleteLogsAndBlocksAfter_Call) RunAndReturn(run func(context } // FilteredLogs provides a mock function with given fields: ctx, filter, limitAndSort, queryName -func (_m *LogPoller) FilteredLogs(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) { +func (_m *LogPoller) FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) { ret := _m.Called(ctx, filter, limitAndSort, queryName) if len(ret) == 0 { @@ -133,10 +133,10 @@ func (_m *LogPoller) FilteredLogs(ctx context.Context, filter query.KeyFilter, l var r0 []logpoller.Log var r1 error - if rf, ok := ret.Get(0).(func(context.Context, query.KeyFilter, query.LimitAndSort, string) ([]logpoller.Log, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []query.Expression, query.LimitAndSort, string) ([]logpoller.Log, error)); ok { return rf(ctx, filter, limitAndSort, queryName) } - if rf, ok := ret.Get(0).(func(context.Context, query.KeyFilter, query.LimitAndSort, string) []logpoller.Log); ok { + if rf, ok := ret.Get(0).(func(context.Context, []query.Expression, query.LimitAndSort, string) []logpoller.Log); ok { r0 = rf(ctx, filter, limitAndSort, queryName) } else { if ret.Get(0) != nil { @@ -144,7 +144,7 @@ func (_m *LogPoller) FilteredLogs(ctx context.Context, filter query.KeyFilter, l } } - if rf, ok := ret.Get(1).(func(context.Context, query.KeyFilter, query.LimitAndSort, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, []query.Expression, query.LimitAndSort, string) error); ok { r1 = rf(ctx, filter, limitAndSort, queryName) } else { r1 = ret.Error(1) @@ -160,16 +160,16 @@ type LogPoller_FilteredLogs_Call struct { // FilteredLogs is a helper method to define mock.On call // - ctx context.Context -// - filter query.KeyFilter +// - filter []query.Expression // - limitAndSort query.LimitAndSort // - queryName string func (_e *LogPoller_Expecter) FilteredLogs(ctx interface{}, filter interface{}, limitAndSort interface{}, queryName interface{}) *LogPoller_FilteredLogs_Call { return &LogPoller_FilteredLogs_Call{Call: _e.mock.On("FilteredLogs", ctx, filter, limitAndSort, queryName)} } -func (_c *LogPoller_FilteredLogs_Call) Run(run func(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, queryName string)) *LogPoller_FilteredLogs_Call { +func (_c *LogPoller_FilteredLogs_Call) Run(run func(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string)) *LogPoller_FilteredLogs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(query.KeyFilter), args[2].(query.LimitAndSort), args[3].(string)) + run(args[0].(context.Context), args[1].([]query.Expression), args[2].(query.LimitAndSort), args[3].(string)) }) return _c } @@ -179,7 +179,7 @@ func (_c *LogPoller_FilteredLogs_Call) Return(_a0 []logpoller.Log, _a1 error) *L return _c } -func (_c *LogPoller_FilteredLogs_Call) RunAndReturn(run func(context.Context, query.KeyFilter, query.LimitAndSort, string) ([]logpoller.Log, error)) *LogPoller_FilteredLogs_Call { +func (_c *LogPoller_FilteredLogs_Call) RunAndReturn(run func(context.Context, []query.Expression, query.LimitAndSort, string) ([]logpoller.Log, error)) *LogPoller_FilteredLogs_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go index 782307e7d06..776fe5bf215 100644 --- a/core/chains/evm/logpoller/observability.go +++ b/core/chains/evm/logpoller/observability.go @@ -142,6 +142,24 @@ func (o *ObservedORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64 }) } +func (o *ObservedORM) SelectUnmatchedLogIDs(ctx context.Context, limit int64) (ids []uint64, err error) { + return withObservedQueryAndResults[uint64](o, "SelectUnmatchedLogIDs", func() ([]uint64, error) { + return o.ORM.SelectUnmatchedLogIDs(ctx, limit) + }) +} + +func (o *ObservedORM) SelectExcessLogIDs(ctx context.Context, limit int64) ([]uint64, error) { + return withObservedQueryAndResults[uint64](o, "SelectExcessLogIDs", func() ([]uint64, error) { + return o.ORM.SelectExcessLogIDs(ctx, limit) + }) +} + +func (o *ObservedORM) DeleteLogsByRowID(ctx context.Context, rowIDs []uint64) (int64, error) { + return withObservedExecAndRowsAffected(o, "DeleteLogsByRowID", del, func() (int64, error) { + return o.ORM.DeleteLogsByRowID(ctx, rowIDs) + }) +} + func (o *ObservedORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlock, error) { return withObservedQuery(o, "SelectBlockByNumber", func() (*LogPollerBlock, error) { return o.ORM.SelectBlockByNumber(ctx, n) @@ -262,7 +280,7 @@ func (o *ObservedORM) SelectIndexedLogsTopicRange(ctx context.Context, address c }) } -func (o *ObservedORM) FilteredLogs(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) { +func (o *ObservedORM) FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) { return withObservedQueryAndResults(o, queryName, func() ([]Log, error) { return o.ORM.FilteredLogs(ctx, filter, limitAndSort, queryName) }) diff --git a/core/chains/evm/logpoller/observability_test.go b/core/chains/evm/logpoller/observability_test.go index 4ea7adceab0..27b8a3c3225 100644 --- a/core/chains/evm/logpoller/observability_test.go +++ b/core/chains/evm/logpoller/observability_test.go @@ -120,8 +120,8 @@ func TestCountersAreProperlyPopulatedForWrites(t *testing.T) { rowsAffected, err := orm.DeleteExpiredLogs(ctx, 3) require.NoError(t, err) - require.Equal(t, int64(3), rowsAffected) - assert.Equal(t, 3, counterFromGaugeByLabels(orm.datasetSize, "420", "DeleteExpiredLogs", "delete")) + require.Equal(t, int64(0), rowsAffected) + assert.Equal(t, 0, counterFromGaugeByLabels(orm.datasetSize, "420", "DeleteExpiredLogs", "delete")) rowsAffected, err = orm.DeleteBlocksBefore(ctx, 30, 0) require.NoError(t, err) diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index 22870efccf3..4d7cf33ebec 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -3,6 +3,7 @@ package logpoller import ( "context" "database/sql" + "errors" "fmt" "math/big" "strings" @@ -33,10 +34,13 @@ type ORM interface { LoadFilters(ctx context.Context) (map[string]Filter, error) DeleteFilter(ctx context.Context, name string) error + DeleteLogsByRowID(ctx context.Context, rowIDs []uint64) (int64, error) InsertBlock(ctx context.Context, blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, finalizedBlock int64) error DeleteBlocksBefore(ctx context.Context, end int64, limit int64) (int64, error) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error + SelectUnmatchedLogIDs(ctx context.Context, limit int64) (ids []uint64, err error) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, error) + SelectExcessLogIDs(ctx context.Context, limit int64) (rowIDs []uint64, err error) GetBlocksRange(ctx context.Context, start int64, end int64) ([]LogPollerBlock, error) SelectBlockByNumber(ctx context.Context, blockNumber int64) (*LogPollerBlock, error) @@ -64,7 +68,7 @@ type ORM interface { SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs evmtypes.Confirmations) ([]Log, error) // FilteredLogs accepts chainlink-common filtering DSL. - FilteredLogs(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) + FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]Log, error) } type DSORM struct { @@ -102,9 +106,9 @@ func (o *DSORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNum if err != nil { return err } - query := `INSERT INTO evm.log_poller_blocks - (evm_chain_id, block_hash, block_number, block_timestamp, finalized_block_number, created_at) - VALUES (:evm_chain_id, :block_hash, :block_number, :block_timestamp, :finalized_block_number, NOW()) + query := `INSERT INTO evm.log_poller_blocks + (evm_chain_id, block_hash, block_number, block_timestamp, finalized_block_number, created_at) + VALUES (:evm_chain_id, :block_hash, :block_number, :block_timestamp, :finalized_block_number, NOW()) ON CONFLICT DO NOTHING` _, err = o.ds.NamedExecContext(ctx, query, args) return err @@ -166,7 +170,7 @@ func (o *DSORM) DeleteFilter(ctx context.Context, name string) error { // LoadFilters returns all filters for this chain func (o *DSORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { query := `SELECT name, - ARRAY_AGG(DISTINCT address)::BYTEA[] AS addresses, + ARRAY_AGG(DISTINCT address)::BYTEA[] AS addresses, ARRAY_AGG(DISTINCT event)::BYTEA[] AS event_sigs, ARRAY_AGG(DISTINCT topic2 ORDER BY topic2) FILTER(WHERE topic2 IS NOT NULL) AS topic2, ARRAY_AGG(DISTINCT topic3 ORDER BY topic3) FILTER(WHERE topic3 IS NOT NULL) AS topic3, @@ -185,9 +189,52 @@ func (o *DSORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { return filters, err } +func blocksQuery(clause string) string { + return fmt.Sprintf(`SELECT %s FROM evm.log_poller_blocks %s`, strings.Join(blocksFields[:], ", "), clause) +} +func logsQuery(clause string) string { + return fmt.Sprintf(`SELECT %s FROM evm.logs %s`, strings.Join(logsFields[:], ", "), clause) +} + +func logsQueryWithTablePrefix(tableAlias string, clause string) string { + var s strings.Builder + for i, field := range logsFields { + if i > 0 { + s.WriteString(", ") + } + s.WriteString(fmt.Sprintf("%s.%s", tableAlias, field)) + } + return fmt.Sprintf(`SELECT %s FROM evm.logs AS %s %s`, s.String(), tableAlias, clause) +} + +func withConfs(query string, tableAlias string, confs evmtypes.Confirmations) string { + var lastConfirmedBlock string + + var tablePrefix string + if tableAlias != "" { + tablePrefix = tableAlias + "." + } + if confs == evmtypes.Finalized { + lastConfirmedBlock = `finalized_block_number` + } else { + lastConfirmedBlock = `block_number - :confs` + } + return fmt.Sprintf(`%s %sblock_number <= ( + SELECT %s + FROM evm.log_poller_blocks + WHERE evm_chain_id = :evm_chain_id + ORDER BY block_number DESC LIMIT 1)`, query, tablePrefix, lastConfirmedBlock) +} + +func logsQueryWithConfs(clause string, confs evmtypes.Confirmations) string { + return withConfs(logsQuery(clause), "", confs) +} + func (o *DSORM) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash.Bytes(), ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, + blocksQuery(`WHERE block_hash = $1 AND evm_chain_id = $2`), + hash.Bytes(), ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil @@ -195,7 +242,9 @@ func (o *DSORM) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPo func (o *DSORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, + blocksQuery(`WHERE block_number = $1 AND evm_chain_id = $2`), n, ubig.New(o.chainID), + ); err != nil { return nil, err } return &b, nil @@ -203,7 +252,9 @@ func (o *DSORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlo func (o *DSORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, + blocksQuery(`WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`), ubig.New(o.chainID), + ); err != nil { return nil, err } return &b, nil @@ -211,7 +262,10 @@ func (o *DSORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) func (o *DSORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 AND block_number >= $2 ORDER BY block_number ASC LIMIT 1`, ubig.New(o.chainID), minAllowedBlockNumber); err != nil { + if err := o.ds.GetContext(ctx, &b, + blocksQuery(`WHERE evm_chain_id = $1 AND block_number >= $2 ORDER BY block_number ASC LIMIT 1`), + ubig.New(o.chainID), minAllowedBlockNumber, + ); err != nil { return nil, err } return &b, nil @@ -224,15 +278,11 @@ func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig if err != nil { return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id + query := logsQueryWithConfs( + `WHERE evm_chain_id = :evm_chain_id AND event_sig = :event_sig - AND address = :address - AND block_number <= %s - ORDER BY block_number desc, log_index DESC - LIMIT 1 - `, nestedBlockNumberQuery(confs)) + AND address = :address AND `, confs) + + `ORDER BY block_number desc, log_index DESC LIMIT 1` var l Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -245,31 +295,84 @@ func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig return &l, nil } +type RangeQueryer[T comparable] struct { + chainID *ubig.Big + ds sqlutil.DataSource + query func(ctx context.Context, r *RangeQueryer[T], lower, upper int64) (rowsAffected int64, err error) + acc []T +} + +func NewRangeQueryer[T comparable](evmChainID *big.Int, ds sqlutil.DataSource, query func(ctx context.Context, r *RangeQueryer[T], lower, upper int64) (rowsAffected int64, err error)) *RangeQueryer[T] { + return &RangeQueryer[T]{ + chainID: ubig.New(evmChainID), + ds: ds, + query: query, + } +} + +// ExecPagedQuery runs a query accepting an upper limit block (end) in a fast paged way. limit is the maximum number +// of results to be returned, but it is also used to break the query up into smaller queries restricted to limit # of blocks. +// The first range of blocks will be from MIN(block_number) to MIN(block_number) + limit. The iterative process ends either once +// the limit on results is reached or block_number = end. The query will never be executed on blocks where block_number > end, and +// it will never be executed on block_number = B unless it has also been executed on all blocks with block_number < B +// r.AddResults(moreResults []T) should be called if this is a query returning results (ie, SELECT). These will be accumulated in +// r.acc and can be retrieved later with r.AllResults() +func (r *RangeQueryer[T]) ExecPagedQuery(ctx context.Context, limit, end int64) (rowsAffected int64, err error) { + if limit == 0 { + return r.query(ctx, r, 0, end) + } + + var start int64 + err = r.ds.GetContext(ctx, &start, `SELECT MIN(block_number) FROM evm.log_poller_blocks + WHERE evm_chain_id = $1`, r.chainID) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return 0, nil + } + return 0, err + } + + // Remove up to limit blocks at a time, until we've reached the limit or removed everything eligible for deletion + var upper int64 + for lower := start; rowsAffected < limit; lower = upper + 1 { + upper = lower + limit - 1 + if upper > end { + upper = end + } + + rows, err2 := r.query(ctx, r, lower, upper) + if err2 != nil { + return rowsAffected, err2 + } + rowsAffected += rows + + if upper >= end { + break + } + } + return rowsAffected, nil +} + +func (r *RangeQueryer[T]) AddResults(moreResults []T) { + r.acc = append(r.acc, moreResults...) +} + +func (r *RangeQueryer[T]) AllResults() []T { + return r.acc +} + // DeleteBlocksBefore delete blocks before and including end. When limit is set, it will delete at most limit blocks. // Otherwise, it will delete all blocks at once. func (o *DSORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) (int64, error) { - if limit > 0 { - result, err := o.ds.ExecContext(ctx, - `DELETE FROM evm.log_poller_blocks - WHERE block_number IN ( - SELECT block_number FROM evm.log_poller_blocks - WHERE block_number <= $1 - AND evm_chain_id = $2 - LIMIT $3 - ) - AND evm_chain_id = $2`, - end, ubig.New(o.chainID), limit) + q := NewRangeQueryer[uint64](o.chainID, o.ds, func(ctx context.Context, r *RangeQueryer[uint64], lower, upper int64) (int64, error) { + result, err := r.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= $3`, + r.chainID, lower, upper) if err != nil { return 0, err } return result.RowsAffected() - } - result, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks - WHERE block_number <= $1 AND evm_chain_id = $2`, end, ubig.New(o.chainID)) - if err != nil { - return 0, err - } - return result.RowsAffected() + }) + return q.ExecPagedQuery(ctx, limit, end) } func (o *DSORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { @@ -281,11 +384,11 @@ func (o *DSORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error // If not applied, these queries can become very slow. After some critical number // of logs, Postgres will try to scan all the logs in the index by block_number. // Latency without upper bound filter can be orders of magnitude higher for large number of logs. - _, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks + _, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE evm_chain_id = $1 - AND block_number >= $2 - AND block_number <= (SELECT MAX(block_number) - FROM evm.log_poller_blocks + AND block_number >= $2 + AND block_number <= (SELECT MAX(block_number) + FROM evm.log_poller_blocks WHERE evm_chain_id = $1)`, ubig.New(o.chainID), start) if err != nil { @@ -293,8 +396,8 @@ func (o *DSORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error return err } - _, err = o.ds.ExecContext(ctx, `DELETE FROM evm.logs - WHERE evm_chain_id = $1 + _, err = o.ds.ExecContext(ctx, `DELETE FROM evm.logs + WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= (SELECT MAX(block_number) FROM evm.logs WHERE evm_chain_id = $1)`, ubig.New(o.chainID), start) @@ -314,31 +417,105 @@ type Exp struct { ShouldDelete bool } +func (o *DSORM) SelectUnmatchedLogIDs(ctx context.Context, limit int64) (ids []uint64, err error) { + batchLogsSubQuery := `SELECT id, evm_chain_id, address, event_sig FROM evm.logs + WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= $3` + + query := fmt.Sprintf(` + SELECT l.id FROM (%s) l LEFT JOIN ( + SELECT evm_chain_id, address, event + FROM evm.log_poller_filters + WHERE evm_chain_id = $1 + GROUP BY evm_chain_id, address, event + ) r ON l.evm_chain_id = r.evm_chain_id AND l.address = r.address AND l.event_sig = r.event + WHERE l.evm_chain_id = $1 AND r.evm_chain_id IS NULL + `, batchLogsSubQuery) + + latestBlock, err := o.SelectLatestBlock(ctx) + if err != nil { + return ids, err + } + + r := NewRangeQueryer[uint64](o.chainID, o.ds, func(ctx context.Context, r *RangeQueryer[uint64], lower, upper int64) (int64, error) { + var rowIDs []uint64 + err2 := r.ds.SelectContext(ctx, &rowIDs, query, r.chainID, lower, upper) + if err2 != nil { + return 0, err2 + } + r.AddResults(rowIDs) + return int64(len(rowIDs)), nil + }) + + _, err = r.ExecPagedQuery(ctx, limit, latestBlock.FinalizedBlockNumber) + + return r.AllResults(), err +} + +// SelectExcessLogIDs finds any logs old enough that MaxLogsKept has been exceeded for every filter they match. +func (o *DSORM) SelectExcessLogIDs(ctx context.Context, limit int64) (results []uint64, err error) { + // Roll up the filter table into 1 row per filter + withSubQuery := ` + SELECT name, + ARRAY_AGG(address) AS addresses, ARRAY_AGG(event) AS events, + MAX(max_logs_kept) AS max_logs_kept -- Should all be the same, just need MAX for GROUP BY + FROM evm.log_poller_filters WHERE evm_chain_id=$1 + GROUP BY name` + + // Count logs matching each filter in reverse order, labeling anything after the filter.max_logs_kept'th with old=true + countLogsSubQuery := ` + SELECT l.id, block_number, log_index, max_logs_kept != 0 AND + ROW_NUMBER() OVER(PARTITION BY f.name ORDER BY block_number, log_index DESC) > max_logs_kept AS old + FROM filters f JOIN evm.logs l ON + l.address = ANY(f.addresses) AND l.event_sig = ANY(f.events) + WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= $3 + ` + + // Return all logs considered "old" by every filter they match + query := fmt.Sprintf(`WITH filters AS ( %s ) SELECT id FROM ( %s ) x GROUP BY id, block_number, log_index HAVING BOOL_AND(old)`, + withSubQuery, countLogsSubQuery) + + latestBlock, err := o.SelectLatestBlock(ctx) + if err != nil { + return results, err + } + + r := NewRangeQueryer[uint64](o.chainID, o.ds, func(ctx context.Context, r *RangeQueryer[uint64], lower, upper int64) (int64, error) { + var rowIDs []uint64 + err = r.ds.SelectContext(ctx, &rowIDs, query, r.chainID, lower, upper) + if err != nil { + return 0, err + } + r.AddResults(rowIDs) + return int64(len(rowIDs)), err + }) + _, err = r.ExecPagedQuery(ctx, limit, latestBlock.FinalizedBlockNumber) + + return r.AllResults(), err +} + // DeleteExpiredLogs removes any logs which either: // - don't match any currently registered filters, or // - have a timestamp older than any matching filter's retention, UNLESS there is at // least one matching filter with retention=0 func (o *DSORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, error) { - var err error - var result sql.Result - query := `DELETE FROM evm.logs - WHERE (evm_chain_id, address, event_sig, block_number) IN ( - SELECT l.evm_chain_id, l.address, l.event_sig, l.block_number - FROM evm.logs l - LEFT JOIN ( - SELECT address, event, CASE WHEN MIN(retention) = 0 THEN 0 ELSE MAX(retention) END AS retention - FROM evm.log_poller_filters - WHERE evm_chain_id = $1 - GROUP BY evm_chain_id, address, event - ) r ON l.evm_chain_id = $1 AND l.address = r.address AND l.event_sig = r.event - WHERE r.retention IS NULL OR (r.retention != 0 AND l.block_timestamp <= STATEMENT_TIMESTAMP() - (r.retention / 10^9 * interval '1 second')) %s)` - + limitClause := "" if limit > 0 { - result, err = o.ds.ExecContext(ctx, fmt.Sprintf(query, "LIMIT $2"), ubig.New(o.chainID), limit) - } else { - result, err = o.ds.ExecContext(ctx, fmt.Sprintf(query, ""), ubig.New(o.chainID)) + limitClause = fmt.Sprintf("LIMIT %d", limit) } + query := fmt.Sprintf(` + WITH rows_to_delete AS ( + SELECT l.id + FROM evm.logs l JOIN ( + SELECT evm_chain_id, address, event, MAX(retention) AS retention + FROM evm.log_poller_filters + WHERE evm_chain_id = $1 + GROUP BY evm_chain_id, address, event + HAVING MIN(retention) > 0 + ) r ON l.evm_chain_id = r.evm_chain_id AND l.address = r.address AND l.event_sig = r.event AND + l.block_timestamp <= STATEMENT_TIMESTAMP() - (r.retention / 10^9 * interval '1 second') %s + ) DELETE FROM evm.logs WHERE id IN (SELECT id FROM rows_to_delete)`, limitClause) + result, err := o.ds.ExecContext(ctx, query, ubig.New(o.chainID)) if err != nil { return 0, err } @@ -383,13 +560,13 @@ func (o *DSORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.D end = len(logs) } - query := `INSERT INTO evm.logs - (evm_chain_id, log_index, block_hash, block_number, block_timestamp, address, event_sig, topics, tx_hash, data, created_at) - VALUES - (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW()) + query := `INSERT INTO evm.logs + (evm_chain_id, log_index, block_hash, block_number, block_timestamp, address, event_sig, topics, tx_hash, data, created_at) + VALUES + (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW()) ON CONFLICT DO NOTHING` - _, err := o.ds.NamedExecContext(ctx, query, logs[start:end]) + _, err := tx.NamedExecContext(ctx, query, logs[start:end]) if err != nil { if pkgerrors.Is(err, context.DeadlineExceeded) && batchInsertSize > 500 { // In case of DB timeouts, try to insert again with a smaller batch upto a limit @@ -421,11 +598,11 @@ func (o *DSORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([ return nil, err } - query := `SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND block_number >= :start_block - AND block_number <= :end_block - ORDER BY block_number, log_index` + query := logsQuery(` + WHERE evm_chain_id = :evm_chain_id + AND block_number >= :start_block + AND block_number <= :end_block + ORDER BY block_number, log_index`) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -450,13 +627,13 @@ func (o *DSORM) SelectLogs(ctx context.Context, start, end int64, address common return nil, err } - query := `SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND block_number >= :start_block - AND block_number <= :end_block - ORDER BY block_number, log_index` + query := logsQuery(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND block_number >= :start_block + AND block_number <= :end_block + ORDER BY block_number, log_index`) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -481,14 +658,12 @@ func (o *DSORM) SelectLogsCreatedAfter(ctx context.Context, address common.Addre return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND block_timestamp > :block_timestamp_after - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs( + `WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND block_timestamp > :block_timestamp_after AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -515,12 +690,12 @@ func (o *DSORM) SelectLogsWithSigs(ctx context.Context, start, end int64, addres return nil, err } - query := `SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = ANY(:event_sig_array) - AND block_number BETWEEN :start_block AND :end_block - ORDER BY block_number, log_index` + query := logsQuery(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = ANY(:event_sig_array) + AND block_number BETWEEN :start_block AND :end_block + ORDER BY block_number, log_index`) query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { @@ -543,11 +718,11 @@ func (o *DSORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]L return nil, err } - query := `SELECT * FROM evm.log_poller_blocks - WHERE block_number >= :start_block + query := blocksQuery(` + WHERE block_number >= :start_block AND block_number <= :end_block AND evm_chain_id = :evm_chain_id - ORDER BY block_number ASC` + ORDER BY block_number ASC`) var blocks []LogPollerBlock query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -574,17 +749,17 @@ func (o *DSORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, from return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs WHERE (block_number, address, event_sig) IN ( - SELECT MAX(block_number), address, event_sig FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND event_sig = ANY(:event_sig_array) - AND address = ANY(:address_array) - AND block_number > :start_block - AND block_number <= %s - GROUP BY event_sig, address - ) - ORDER BY block_number ASC`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(`WHERE id IN ( + SELECT LAST_VALUE(id) OVER( + PARTITION BY evm_chain_id, address, event_sig + ORDER BY block_number, log_index + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) FROM evm.logs + WHERE evm_chain_id = :evm_chain_id + AND event_sig = ANY(:event_sig_array) + AND address = ANY(:address_array) + AND block_number >= :start_block AND `, confs) + ` + )` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -609,13 +784,12 @@ func (o *DSORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, if err != nil { return 0, err } - query := fmt.Sprintf(` - SELECT COALESCE(MAX(block_number), 0) FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND event_sig = ANY(:event_sig_array) - AND address = ANY(:address_array) - AND block_number > :start_block - AND block_number <= %s`, nestedBlockNumberQuery(confs)) + + query := withConfs(`SELECT COALESCE(MAX(block_number), 0) FROM evm.logs + WHERE evm_chain_id = :evm_chain_id + AND event_sig = ANY(:event_sig_array) + AND address = ANY(:address_array) + AND block_number >= :start_block AND `, "", confs) var blockNumber int64 query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -640,14 +814,12 @@ func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Addr return nil, err } - query := fmt.Sprintf(`SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND substring(data from 32*:word_index+1 for 32) >= :word_value_min - AND substring(data from 32*:word_index+1 for 32) <= :word_value_max - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(`WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND substring(data from 32*:word_index+1 for 32) >= :word_value_min + AND substring(data from 32*:word_index+1 for 32) <= :word_value_max AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -671,14 +843,12 @@ func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address commo return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND substring(data from 32*:word_index+1 for 32) >= :word_value_min - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND substring(data from 32*:word_index+1 for 32) >= :word_value_min AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -702,15 +872,14 @@ func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Ad if err != nil { return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND substring(data from 32*:word_index_min+1 for 32) <= :word_value - AND substring(data from 32*:word_index_max+1 for 32) >= :word_value - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + + query := logsQueryWithConfs(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND substring(data from 32*:word_index_min+1 for 32) <= :word_value + AND substring(data from 32*:word_index_max+1 for 32) >= :word_value AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -734,14 +903,11 @@ func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address c return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND topics[:topic_index] >= :topic_value_min - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(`WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND topics[:topic_index] >= :topic_value_min AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -766,15 +932,12 @@ func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common. return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND topics[:topic_index] >= :topic_value_min - AND topics[:topic_index] <= :topic_value_max - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(`WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND topics[:topic_index] >= :topic_value_min + AND topics[:topic_index] <= :topic_value_max AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -798,14 +961,12 @@ func (o *DSORM) SelectIndexedLogs(ctx context.Context, address common.Address, e return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND topics[:topic_index] = ANY(:topic_values) - AND block_number <= %s - ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND topics[:topic_index] = ANY(:topic_values) AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -831,14 +992,14 @@ func (o *DSORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end in return nil, err } - query := `SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND topics[:topic_index] = ANY(:topic_values) - AND block_number >= :start_block - AND block_number <= :end_block - ORDER BY block_number, log_index` + query := logsQuery(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND topics[:topic_index] = ANY(:topic_values) + AND block_number >= :start_block + AND block_number <= :end_block + ORDER BY block_number, log_index`) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -864,16 +1025,13 @@ func (o *DSORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address commo return nil, err } - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND topics[:topic_index] = ANY(:topic_values) - AND block_timestamp > :block_timestamp_after - AND block_number <= %s - ORDER BY block_number, log_index - `, nestedBlockNumberQuery(confs)) + query := logsQueryWithConfs(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND topics[:topic_index] = ANY(:topic_values) + AND block_timestamp > :block_timestamp_after AND `, confs) + + `ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -897,12 +1055,12 @@ func (o *DSORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad return nil, err } - query := `SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :event_sig - AND tx_hash = :tx_hash - ORDER BY block_number, log_index` + query := logsQuery(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :event_sig + AND tx_hash = :tx_hash + ORDER BY block_number, log_index`) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -932,25 +1090,22 @@ func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si return nil, err } - nestedQuery := nestedBlockNumberQuery(confs) - query := fmt.Sprintf(` - SELECT * FROM evm.logs - WHERE evm_chain_id = :evm_chain_id - AND address = :address - AND event_sig = :sigA - AND block_number BETWEEN :start_block AND :end_block - AND block_number <= %s - EXCEPT - SELECT a.* FROM evm.logs AS a - INNER JOIN evm.logs B - ON a.evm_chain_id = b.evm_chain_id - AND a.address = b.address - AND a.topics[:topic_index] = b.topics[:topic_index] - AND a.event_sig = :sigA - AND b.event_sig = :sigB - AND b.block_number BETWEEN :start_block AND :end_block - AND b.block_number <= %s - ORDER BY block_number, log_index`, nestedQuery, nestedQuery) + query := logsQueryWithConfs(` + WHERE evm_chain_id = :evm_chain_id + AND address = :address + AND event_sig = :sigA + AND block_number BETWEEN :start_block AND :end_block AND `, confs) + + ` EXCEPT ` + + withConfs(logsQueryWithTablePrefix("a", ` + INNER JOIN evm.logs AS b + ON a.evm_chain_id = b.evm_chain_id + AND a.address = b.address + AND a.topics[:topic_index] = b.topics[:topic_index] + AND a.event_sig = :sigA + AND b.event_sig = :sigB + AND b.block_number BETWEEN :start_block AND :end_block + AND `), "b", confs) + + ` ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -964,9 +1119,8 @@ func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si return logs, nil } -// TODO flaky BCF-3258 -func (o *DSORM) FilteredLogs(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, _ string) ([]Log, error) { - qs, args, err := (&pgDSLParser{}).buildQuery(o.chainID, filter.Expressions, limitAndSort) +func (o *DSORM) FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, _ string) ([]Log, error) { + qs, args, err := (&pgDSLParser{}).buildQuery(o.chainID, filter, limitAndSort) if err != nil { return nil, err } @@ -989,19 +1143,11 @@ func (o *DSORM) FilteredLogs(ctx context.Context, filter query.KeyFilter, limitA return logs, nil } -func nestedBlockNumberQuery(confs evmtypes.Confirmations) string { - if confs == evmtypes.Finalized { - return ` - (SELECT finalized_block_number - FROM evm.log_poller_blocks - WHERE evm_chain_id = :evm_chain_id - ORDER BY block_number DESC LIMIT 1) ` - } - // Intentionally wrap with greatest() function and don't return negative block numbers when :confs > :block_number - // It doesn't impact logic of the outer query, because block numbers are never less or equal to 0 (guarded by log_poller_blocks_block_number_check) - return ` - (SELECT greatest(block_number - :confs, 0) - FROM evm.log_poller_blocks - WHERE evm_chain_id = :evm_chain_id - ORDER BY block_number DESC LIMIT 1) ` +// DeleteLogsByRowID accepts a list of log row id's to delete +func (o *DSORM) DeleteLogsByRowID(ctx context.Context, rowIDs []uint64) (int64, error) { + result, err := o.ds.ExecContext(ctx, `DELETE FROM evm.logs WHERE id = ANY($1)`, rowIDs) + if err != nil { + return 0, err + } + return result.RowsAffected() } diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index 0df34196ff9..6e618ba9cef 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "database/sql" + "errors" "fmt" "math" "math/big" @@ -11,10 +12,11 @@ import ( "testing" "time" + "github.com/stretchr/testify/mock" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/ethereum/go-ethereum/common" - "github.com/jackc/pgx/v4" pkgerrors "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -28,8 +30,8 @@ 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/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) type block struct { @@ -187,6 +189,7 @@ func TestORM_GetBlocks_From_Range_Recent_Blocks(t *testing.T) { } func TestORM(t *testing.T) { + t.Parallel() th := SetupTH(t, lpOpts) o1 := th.ORM o2 := th.ORM2 @@ -320,10 +323,22 @@ func TestORM(t *testing.T) { Data: []byte("hello short retention"), BlockTimestamp: time.Now(), }, + { + EvmChainId: ubig.New(th.ChainID), + LogIndex: 7, + BlockHash: common.HexToHash("0x1239"), + BlockNumber: int64(17), + EventSig: topic, + Topics: [][]byte{topic[:]}, + Address: common.HexToAddress("0x1236"), + TxHash: common.HexToHash("0x1888"), + Data: []byte("hello2 short retention"), + BlockTimestamp: time.Now(), + }, { EvmChainId: ubig.New(th.ChainID), LogIndex: 8, - BlockHash: common.HexToHash("0x1238"), + BlockHash: common.HexToHash("0x1239"), BlockNumber: int64(17), EventSig: topic2, Topics: [][]byte{topic2[:]}, @@ -334,10 +349,39 @@ func TestORM(t *testing.T) { }, })) - t.Log(latest.BlockNumber) + // Insert a couple logs on a different chain, to make sure + // these aren't affected by any operations on the chain LogPoller + // is managing. + require.NoError(t, o2.InsertLogs(ctx, []logpoller.Log{ + { + EvmChainId: ubig.New(th.ChainID2), + LogIndex: 8, + BlockHash: common.HexToHash("0x1238"), + BlockNumber: int64(17), + EventSig: topic2, + Topics: [][]byte{topic2[:]}, + Address: common.HexToAddress("0x1236"), + TxHash: common.HexToHash("0x1888"), + Data: []byte("same log on unrelated chain"), + BlockTimestamp: time.Now(), + }, + { + EvmChainId: ubig.New(th.ChainID2), + LogIndex: 9, + BlockHash: common.HexToHash("0x1999"), + BlockNumber: int64(18), + EventSig: topic, + Topics: [][]byte{topic[:], topic2[:]}, + Address: common.HexToAddress("0x5555"), + TxHash: common.HexToHash("0x1543"), + Data: []byte("different log on unrelated chain"), + BlockTimestamp: time.Now(), + }, + })) + logs, err := o1.SelectLogsByBlockRange(ctx, 1, 17) require.NoError(t, err) - require.Len(t, logs, 8) + require.Len(t, logs, 9) logs, err = o1.SelectLogsByBlockRange(ctx, 10, 10) require.NoError(t, err) @@ -414,7 +458,7 @@ func TestORM(t *testing.T) { require.Equal(t, 2, len(lgs)) require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1237"), 16, time.Now(), 0)) - require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1238"), 17, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1238"), 17, time.Now(), 17)) filter0 := logpoller.Filter{ Name: "permanent retention filter", @@ -452,19 +496,47 @@ func TestORM(t *testing.T) { require.Equal(t, int64(17), latest.BlockNumber) logs, err = o1.SelectLogsByBlockRange(ctx, 1, latest.BlockNumber) require.NoError(t, err) - require.Len(t, logs, 8) + require.Len(t, logs, 9) - // Delete expired logs + // Delete expired logs with page limit time.Sleep(2 * time.Millisecond) // just in case we haven't reached the end of the 1ms retention period - deleted, err := o1.DeleteExpiredLogs(ctx, 0) + deleted, err := o1.DeleteExpiredLogs(ctx, 1) require.NoError(t, err) - assert.Equal(t, int64(4), deleted) + assert.Equal(t, int64(1), deleted) + + // Delete expired logs without page limit + deleted, err = o1.DeleteExpiredLogs(ctx, 0) + require.NoError(t, err) + assert.Equal(t, int64(1), deleted) + + // Select unmatched logs with page limit + ids, err := o1.SelectUnmatchedLogIDs(ctx, 2) + require.NoError(t, err) + assert.Len(t, ids, 2) + + // Select unmatched logs without page limit + ids, err = o1.SelectUnmatchedLogIDs(ctx, 0) + require.NoError(t, err) + assert.Len(t, ids, 3) + + // Delete logs by row id + deleted, err = o1.DeleteLogsByRowID(ctx, ids) + require.NoError(t, err) + assert.Equal(t, int64(3), deleted) + + // Ensure that both of the logs from the second chain are still there + logs, err = o2.SelectLogs(ctx, 0, 100, common.HexToAddress("0x1236"), topic2) + require.NoError(t, err) + assert.Len(t, logs, 1) + logs, err = o2.SelectLogs(ctx, 0, 100, common.HexToAddress("0x5555"), topic) + require.NoError(t, err) + assert.Len(t, logs, 1) logs, err = o1.SelectLogsByBlockRange(ctx, 1, latest.BlockNumber) require.NoError(t, err) - // It should have retained the log matching filter0 (due to ret=0 meaning permanent retention) as well as all - // 3 logs matching filter12 (ret=1 hour). It should have deleted 3 logs not matching any filter, as well as 1 - // of the 2 logs matching filter1 (ret=1ms)--the one that doesn't also match filter12. + // The only log which should be deleted is the one which matches filter1 (ret=1ms) but not filter12 (ret=1 hour) + // Importantly, it shouldn't delete any logs matching only filter0 (ret=0 meaning permanent retention). Anything + // matching filter12 should be kept regardless of what other filters it matches. assert.Len(t, logs, 4) // Delete logs after should delete all logs. @@ -475,16 +547,160 @@ func TestORM(t *testing.T) { assert.Zero(t, len(logs)) } -type PgxLogger struct { - lggr logger.Logger -} +func TestORM_SelectExcessLogs(t *testing.T) { + t.Parallel() + th := SetupTH(t, lpOpts) + o1 := th.ORM + o2 := th.ORM2 + ctx := testutils.Context(t) -func NewPgxLogger(lggr logger.Logger) PgxLogger { - return PgxLogger{lggr} -} + topic := common.HexToHash("0x1599") + topic2 := common.HexToHash("0x1600") + + blockHashes := []common.Hash{common.HexToHash("0x1234"), common.HexToHash("0x1235"), common.HexToHash("0x1236")} + + // Insert blocks for active chain + for i := int64(0); i < 3; i++ { + blockNumber := 10 + i + require.NoError(t, o1.InsertBlock(ctx, blockHashes[i], blockNumber, time.Now(), blockNumber)) + b1, err := o1.SelectBlockByHash(ctx, blockHashes[i]) + require.NoError(t, err) + require.Equal(t, blockNumber, b1.BlockNumber) + } + + // Insert block from a different chain + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1234"), 17, time.Now(), 17)) + b, err := o2.SelectBlockByHash(ctx, common.HexToHash("0x1234")) + require.NoError(t, err) + require.Equal(t, int64(17), b.BlockNumber) + + for i := int64(0); i < 7; i++ { + require.NoError(t, o1.InsertLogs(ctx, []logpoller.Log{ + { + EvmChainId: ubig.New(th.ChainID), + LogIndex: i, + BlockHash: common.HexToHash("0x1234"), + BlockNumber: int64(10), + EventSig: topic, + Topics: [][]byte{topic[:]}, + Address: common.HexToAddress("0x1234"), + TxHash: common.HexToHash("0x1888"), + Data: []byte("hello"), + BlockTimestamp: time.Now(), + }, + { + EvmChainId: ubig.New(th.ChainID), + LogIndex: i, + BlockHash: common.HexToHash("0x1234"), + BlockNumber: int64(11), + EventSig: topic, + Topics: [][]byte{topic[:]}, + Address: common.HexToAddress("0x1235"), + TxHash: common.HexToHash("0x1888"), + Data: []byte("hello"), + BlockTimestamp: time.Now(), + }, + { + EvmChainId: ubig.New(th.ChainID), + LogIndex: i, + BlockHash: common.HexToHash("0x1234"), + BlockNumber: int64(12), + EventSig: topic2, + Topics: [][]byte{topic2[:]}, + Address: common.HexToAddress("0x1235"), + TxHash: common.HexToHash("0x1888"), + Data: []byte("hello"), + BlockTimestamp: time.Now(), + }, + })) + } + + logs, err := o1.SelectLogsByBlockRange(ctx, 1, 12) + require.NoError(t, err) + require.Len(t, logs, 21) + + // Insert a log on a different chain, to make sure + // it's not affected by any operations on the chain LogPoller + // is managing. + require.NoError(t, o2.InsertLogs(ctx, []logpoller.Log{ + { + EvmChainId: ubig.New(th.ChainID2), + LogIndex: 8, + BlockHash: common.HexToHash("0x1238"), + BlockNumber: int64(17), + EventSig: topic2, + Topics: [][]byte{topic2[:]}, + Address: common.HexToAddress("0x1236"), + TxHash: common.HexToHash("0x1888"), + Data: []byte("same log on unrelated chain"), + BlockTimestamp: time.Now(), + }, + })) + + logs, err = o2.SelectLogsByBlockRange(ctx, 1, 17) + require.NoError(t, err) + require.Len(t, logs, 1) + + filter1 := logpoller.Filter{ + Name: "MaxLogsKept = 0 (addr 1234 topic1)", + Addresses: []common.Address{common.HexToAddress("0x1234")}, + EventSigs: types.HashArray{topic}, + MaxLogsKept: 0, + } + + filter12 := logpoller.Filter{ // retain both topic1 and topic2 on contract3 for at least 1ms + Name: "MaxLogsKept = 1 (addr 1235 topic1 & topic2)", + Addresses: []common.Address{common.HexToAddress("0x1235")}, + EventSigs: types.HashArray{topic, topic2}, + Retention: time.Millisecond, + MaxLogsKept: 1, + } + filter2 := logpoller.Filter{ // retain topic2 on contract3 for at least 1 hour + Name: "MaxLogsKept = 5 (addr 1235 topic2)", + Addresses: []common.Address{common.HexToAddress("0x1235")}, + EventSigs: types.HashArray{topic2}, + MaxLogsKept: 5, + } + + // Test inserting filters and reading them back + require.NoError(t, o1.InsertFilter(ctx, filter1)) + require.NoError(t, o1.InsertFilter(ctx, filter12)) + require.NoError(t, o1.InsertFilter(ctx, filter2)) + + filters, err := o1.LoadFilters(ctx) + require.NoError(t, err) + require.Len(t, filters, 3) + assert.Equal(t, filter1, filters["MaxLogsKept = 0 (addr 1234 topic1)"]) + assert.Equal(t, filter12, filters["MaxLogsKept = 1 (addr 1235 topic1 & topic2)"]) + assert.Equal(t, filter2, filters["MaxLogsKept = 5 (addr 1235 topic2)"]) + + ids, err := o1.SelectUnmatchedLogIDs(ctx, 0) + require.NoError(t, err) + require.Len(t, ids, 0) + + // Number of excess logs eligible for pruning: + // 2 of the 7 matching filter2 + 6 of the 7 matching filter12 but not filter2 = 8 total of 21 + + // Test SelectExcessLogIDs with limit less than # blocks + // ( should only consider blocks 10 & 11, returning 6 excess events from block 11 + // but ignoring the 2 in block 12 ) + ids, err = o1.SelectExcessLogIDs(ctx, 2) + require.NoError(t, err) + assert.Len(t, ids, 6) + + // Test SelectExcessLogIDs with limit greater than # blocks: + ids, err = o1.SelectExcessLogIDs(ctx, 4) + require.NoError(t, err) + assert.Len(t, ids, 8) -func (l PgxLogger) Log(ctx context.Context, log pgx.LogLevel, msg string, data map[string]interface{}) { + // Test SelectExcessLogIDs with no limit + ids, err = o1.SelectExcessLogIDs(ctx, 10) + require.NoError(t, err) + assert.Len(t, ids, 8) + deleted, err := o1.DeleteLogsByRowID(ctx, ids) + require.NoError(t, err) + assert.Equal(t, int64(8), deleted) } func TestLogPollerFilters(t *testing.T) { @@ -606,8 +822,8 @@ func TestORM_IndexedLogs(t *testing.T) { } for idx, value := range topicValues { - topicFilters.Expressions[idx] = logpoller.NewEventByTopicFilter(topicIdx, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(value).Hex(), Operator: primitives.Eq}, + topicFilters.Expressions[idx] = logpoller.NewEventByTopicFilter(topicIdx, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(value), Operator: primitives.Eq}, }) } @@ -631,7 +847,7 @@ func TestORM_IndexedLogs(t *testing.T) { require.Equal(t, 1, len(lgs)) assert.Equal(t, logpoller.EvmWord(1).Bytes(), lgs[0].GetTopics()[1].Bytes()) - lgs, err = o1.FilteredLogs(ctx, standardFilter(1, []uint64{1}), limiter, "") + lgs, err = o1.FilteredLogs(ctx, standardFilter(1, []uint64{1}).Expressions, limiter, "") require.NoError(t, err) require.Equal(t, 1, len(lgs)) assert.Equal(t, logpoller.EvmWord(1).Bytes(), lgs[0].GetTopics()[1].Bytes()) @@ -640,19 +856,17 @@ func TestORM_IndexedLogs(t *testing.T) { require.NoError(t, err) assert.Equal(t, 2, len(lgs)) - lgs, err = o1.FilteredLogs(ctx, standardFilter(1, []uint64{1, 2}), limiter, "") + lgs, err = o1.FilteredLogs(ctx, standardFilter(1, []uint64{1, 2}).Expressions, limiter, "") require.NoError(t, err) assert.Equal(t, 2, len(lgs)) - blockRangeFilter := func(start, end string, topicIdx uint64, topicValues []uint64) query.KeyFilter { - return query.KeyFilter{ - Expressions: []query.Expression{ - logpoller.NewAddressFilter(addr), - logpoller.NewEventSigFilter(eventSig), - filtersForTopics(topicIdx, topicValues), - query.Block(start, primitives.Gte), - query.Block(end, primitives.Lte), - }, + blockRangeFilter := func(start, end string, topicIdx uint64, topicValues []uint64) []query.Expression { + return []query.Expression{ + logpoller.NewAddressFilter(addr), + logpoller.NewEventSigFilter(eventSig), + filtersForTopics(topicIdx, topicValues), + query.Block(start, primitives.Gte), + query.Block(end, primitives.Lte), } } @@ -704,30 +918,28 @@ func TestORM_IndexedLogs(t *testing.T) { Expressions: []query.Expression{ logpoller.NewAddressFilter(addr), logpoller.NewEventSigFilter(eventSig), - logpoller.NewEventByTopicFilter(1, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(2).Hex(), Operator: primitives.Gte}, + logpoller.NewEventByTopicFilter(1, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(2), Operator: primitives.Gte}, }), query.Confidence(primitives.Unconfirmed), }, } - lgs, err = o1.FilteredLogs(ctx, filter, limiter, "") + lgs, err = o1.FilteredLogs(ctx, filter.Expressions, limiter, "") require.NoError(t, err) assert.Equal(t, 2, len(lgs)) - rangeFilter := func(topicIdx uint64, min, max uint64) query.KeyFilter { - return query.KeyFilter{ - Expressions: []query.Expression{ - logpoller.NewAddressFilter(addr), - logpoller.NewEventSigFilter(eventSig), - logpoller.NewEventByTopicFilter(topicIdx, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(min).Hex(), Operator: primitives.Gte}, - }), - logpoller.NewEventByTopicFilter(topicIdx, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(max).Hex(), Operator: primitives.Lte}, - }), - query.Confidence(primitives.Unconfirmed), - }, + rangeFilter := func(topicIdx uint64, min, max uint64) []query.Expression { + return []query.Expression{ + logpoller.NewAddressFilter(addr), + logpoller.NewEventSigFilter(eventSig), + logpoller.NewEventByTopicFilter(topicIdx, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(min), Operator: primitives.Gte}, + }), + logpoller.NewEventByTopicFilter(topicIdx, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(max), Operator: primitives.Lte}, + }), + query.Confidence(primitives.Unconfirmed), } } @@ -835,7 +1047,7 @@ func TestORM_SelectIndexedLogsByTxHash(t *testing.T) { }, } - retrievedLogs, err = o1.FilteredLogs(ctx, filter, limiter, "") + retrievedLogs, err = o1.FilteredLogs(ctx, filter.Expressions, limiter, "") require.NoError(t, err) require.Equal(t, 2, len(retrievedLogs)) @@ -876,19 +1088,17 @@ func TestORM_DataWords(t *testing.T) { }, })) - wordFilter := func(wordIdx uint8, word1, word2 uint64) query.KeyFilter { - return query.KeyFilter{ - Expressions: []query.Expression{ - logpoller.NewAddressFilter(addr), - logpoller.NewEventSigFilter(eventSig), - logpoller.NewEventByWordFilter(eventSig, wordIdx, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(word1).Hex(), Operator: primitives.Gte}, - }), - logpoller.NewEventByWordFilter(eventSig, wordIdx, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(word2).Hex(), Operator: primitives.Lte}, - }), - query.Confidence(primitives.Unconfirmed), - }, + wordFilter := func(wordIdx int, word1, word2 uint64) []query.Expression { + return []query.Expression{ + logpoller.NewAddressFilter(addr), + logpoller.NewEventSigFilter(eventSig), + logpoller.NewEventByWordFilter(wordIdx, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(word1), Operator: primitives.Gte}, + }), + logpoller.NewEventByWordFilter(wordIdx, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(word2), Operator: primitives.Lte}, + }), + query.Confidence(primitives.Unconfirmed), } } @@ -947,15 +1157,13 @@ func TestORM_DataWords(t *testing.T) { require.NoError(t, err) assert.Equal(t, 2, len(lgs)) - filter := query.KeyFilter{ - Expressions: []query.Expression{ - logpoller.NewAddressFilter(addr), - logpoller.NewEventSigFilter(eventSig), - logpoller.NewEventByWordFilter(eventSig, 0, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(1).Hex(), Operator: primitives.Gte}, - }), - query.Confidence(primitives.Unconfirmed), - }, + filter := []query.Expression{ + logpoller.NewAddressFilter(addr), + logpoller.NewEventSigFilter(eventSig), + logpoller.NewEventByWordFilter(0, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(1), Operator: primitives.Gte}, + }), + query.Confidence(primitives.Unconfirmed), } lgs, err = o1.FilteredLogs(ctx, filter, limiter, "") @@ -1099,11 +1307,75 @@ func TestORM_SelectLogsWithSigsByBlockRangeFilter(t *testing.T) { }) assertion(t, logs, err, startBlock, endBlock) - logs, err = th.ORM.FilteredLogs(ctx, filter([]common.Hash{topic, topic2}, strconv.Itoa(int(startBlock)), strconv.Itoa(int(endBlock))), limiter, "") + logs, err = th.ORM.FilteredLogs(ctx, filter([]common.Hash{topic, topic2}, strconv.Itoa(int(startBlock)), strconv.Itoa(int(endBlock))).Expressions, limiter, "") assertion(t, logs, err, startBlock, endBlock) } +type mockQueryExecutor struct { + mock.Mock +} + +func (m *mockQueryExecutor) Exec(ctx context.Context, r *logpoller.RangeQueryer[uint64], lower, upper int64) (int64, error) { + res := m.Called(lower, upper) + return int64(res.Int(0)), res.Error(1) +} + +func Test_ExecPagedQuery(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + lggr := logger.Test(t) + chainID := testutils.NewRandomEVMChainID() + db := pgtest.NewSqlxDB(t) + o := logpoller.NewORM(chainID, db, lggr) + + m := mockQueryExecutor{} + + queryError := errors.New("some error") + m.On("Exec", int64(0), int64(0)).Return(0, queryError).Once() + + // Should handle errors gracefully + r := logpoller.NewRangeQueryer(chainID, db, m.Exec) + _, err := r.ExecPagedQuery(ctx, 0, 0) + assert.ErrorIs(t, err, queryError) + + m.On("Exec", int64(0), int64(60)).Return(4, nil).Once() + + // Query should only get executed once with limitBlock=end if called with limit=0 + numResults, err := r.ExecPagedQuery(ctx, 0, 60) + require.NoError(t, err) + assert.Equal(t, int64(4), numResults) + + // Should report actual db errors + _, err = r.ExecPagedQuery(ctx, 300, 1000) + assert.Error(t, err) + + require.NoError(t, o.InsertBlock(ctx, common.HexToHash("0x1234"), 42, time.Now(), 0)) + + m.On("Exec", mock.Anything, mock.Anything).Return(3, nil) + + // Should get called with limitBlock = 342, 642, 942, 1000 + numResults, err = r.ExecPagedQuery(ctx, 300, 1000) + require.NoError(t, err) + assert.Equal(t, int64(12), numResults) // 3 results in each of 4 calls + m.AssertNumberOfCalls(t, "Exec", 6) // 4 new calls, plus the prior 2 + expectedLimitBlocks := [][]int64{{42, 341}, {342, 641}, {642, 941}, {942, 1000}} + for _, expected := range expectedLimitBlocks { + m.AssertCalled(t, "Exec", expected[0], expected[1]) + } + + // Should not go all the way to 1000, but stop after ~ 13 results have + // been returned + numResults, err = r.ExecPagedQuery(ctx, 15, 1000) + require.NoError(t, err) + assert.Equal(t, int64(15), numResults) + m.AssertNumberOfCalls(t, "Exec", 11) + expectedLimitBlocks = [][]int64{{42, 56}, {57, 71}, {72, 86}, {87, 101}, {102, 116}} // upper[n] = 42 + 15 * n - 1 for n = 1, 2, 3, 4, 5, lower[n] = upper[n-1] + 1 + for _, expected := range expectedLimitBlocks { + m.AssertCalled(t, "Exec", expected[0], expected[1]) + } +} + func TestORM_DeleteBlocksBefore(t *testing.T) { th := SetupTH(t, lpOpts) o1 := th.ORM @@ -1161,14 +1433,12 @@ func TestLogPoller_Logs(t *testing.T) { assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000005", lgs[4].BlockHash.String()) assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000005", lgs[5].BlockHash.String()) - logFilter := func(start, end string, address common.Address) query.KeyFilter { - return query.KeyFilter{ - Expressions: []query.Expression{ - logpoller.NewAddressFilter(address), - logpoller.NewEventSigFilter(event1), - query.Block(start, primitives.Gte), - query.Block(end, primitives.Lte), - }, + logFilter := func(start, end string, address common.Address) []query.Expression { + return []query.Expression{ + logpoller.NewAddressFilter(address), + logpoller.NewEventSigFilter(event1), + query.Block(start, primitives.Gte), + query.Block(end, primitives.Lte), } } @@ -1566,7 +1836,7 @@ func TestSelectLatestBlockNumberEventSigsAddrsWithConfs(t *testing.T) { events: []common.Hash{event1, event2}, addrs: []common.Address{address1, address2}, confs: 0, - fromBlock: 3, + fromBlock: 4, expectedBlockNumber: 0, }, { @@ -1677,8 +1947,8 @@ func TestSelectLogsCreatedAfter(t *testing.T) { if len(topicVals) > 0 { exp := make([]query.Expression, len(topicVals)) for idx, val := range topicVals { - exp[idx] = logpoller.NewEventByTopicFilter(uint64(topicIdx), []primitives.ValueComparator{ - {Value: val.String(), Operator: primitives.Eq}, + exp[idx] = logpoller.NewEventByTopicFilter(uint64(topicIdx), []logpoller.HashedValueComparator{ + {Value: val, Operator: primitives.Eq}, }) } @@ -1722,7 +1992,7 @@ func TestSelectLogsCreatedAfter(t *testing.T) { assertion(t, logs, err, tt.expectedLogs) - logs, err = th.ORM.FilteredLogs(ctx, filter(tt.after, tt.confs, 0, nil), limiter, "") + logs, err = th.ORM.FilteredLogs(ctx, filter(tt.after, tt.confs, 0, nil).Expressions, limiter, "") assertion(t, logs, err, tt.expectedLogs) }) @@ -1735,7 +2005,7 @@ func TestSelectLogsCreatedAfter(t *testing.T) { assertion(t, logs, err, tt.expectedLogs) - logs, err = th.ORM.FilteredLogs(ctx, filter(tt.after, tt.confs, 1, []common.Hash{event}), limiter, "") + logs, err = th.ORM.FilteredLogs(ctx, filter(tt.after, tt.confs, 1, []common.Hash{event}).Expressions, limiter, "") assertion(t, logs, err, tt.expectedLogs) }) @@ -1965,11 +2235,11 @@ func TestSelectLogsDataWordBetween(t *testing.T) { Expressions: []query.Expression{ logpoller.NewAddressFilter(address), logpoller.NewEventSigFilter(eventSig), - logpoller.NewEventByWordFilter(eventSig, 0, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(word).Hex(), Operator: primitives.Lte}, + logpoller.NewEventByWordFilter(0, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(word), Operator: primitives.Lte}, }), - logpoller.NewEventByWordFilter(eventSig, 1, []primitives.ValueComparator{ - {Value: logpoller.EvmWord(word).Hex(), Operator: primitives.Gte}, + logpoller.NewEventByWordFilter(1, []logpoller.HashedValueComparator{ + {Value: logpoller.EvmWord(word), Operator: primitives.Gte}, }), query.Confidence(primitives.Unconfirmed), }, @@ -1991,7 +2261,7 @@ func TestSelectLogsDataWordBetween(t *testing.T) { assertion(t, logs, err, tt.expectedLogs) - logs, err = th.ORM.FilteredLogs(ctx, wordFilter(tt.wordValue), limiter, "") + logs, err = th.ORM.FilteredLogs(ctx, wordFilter(tt.wordValue).Expressions, limiter, "") assertion(t, logs, err, tt.expectedLogs) }) diff --git a/core/chains/evm/logpoller/parser.go b/core/chains/evm/logpoller/parser.go index e08ea93da73..9dfa00eaf3e 100644 --- a/core/chains/evm/logpoller/parser.go +++ b/core/chains/evm/logpoller/parser.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -26,6 +27,10 @@ const ( var ( ErrUnexpectedCursorFormat = errors.New("unexpected cursor format") + logsFields = [...]string{"evm_chain_id", "log_index", "block_hash", "block_number", + "address", "event_sig", "topics", "tx_hash", "data", "created_at", "block_timestamp"} + blocksFields = [...]string{"evm_chain_id", "block_hash", "block_number", "block_timestamp", + "finalized_block_number", "created_at"} ) // The parser builds SQL expressions piece by piece for each Accept function call and resets the error and expression @@ -151,11 +156,11 @@ func (v *pgDSLParser) nestedConfQuery(finalized bool, confs uint64) string { } func (v *pgDSLParser) VisitEventByWordFilter(p *eventByWordFilter) { - if len(p.ValueComparers) > 0 { + if len(p.HashedValueComparers) > 0 { wordIdx := v.args.withIndexedField("word_index", p.WordIndex) - comps := make([]string, len(p.ValueComparers)) - for idx, comp := range p.ValueComparers { + comps := make([]string, len(p.HashedValueComparers)) + for idx, comp := range p.HashedValueComparers { comps[idx], v.err = makeComp(comp, v.args, "word_value", wordIdx, "substring(data from 32*:%s+1 for 32) %s :%s") if v.err != nil { return @@ -199,7 +204,7 @@ func (v *pgDSLParser) VisitConfirmationsFilter(p *confirmationsFilter) { } } -func makeComp(comp primitives.ValueComparator, args *queryArgs, field, subfield, pattern string) (string, error) { +func makeComp(comp HashedValueComparator, args *queryArgs, field, subfield, pattern string) (string, error) { cmp, err := cmpOpToString(comp.Operator) if err != nil { return "", err @@ -209,7 +214,7 @@ func makeComp(comp primitives.ValueComparator, args *queryArgs, field, subfield, pattern, subfield, cmp, - args.withIndexedField(field, common.HexToHash(comp.Value)), + args.withIndexedField(field, comp.Value), ), nil } @@ -220,7 +225,7 @@ func (v *pgDSLParser) buildQuery(chainID *big.Int, expressions []query.Expressio v.err = nil // build the query string - clauses := []string{"SELECT evm.logs.* FROM evm.logs"} + clauses := []string{logsQuery("")} where, err := v.whereClause(expressions, limiter) if err != nil { @@ -432,6 +437,12 @@ func orderToString(dir query.SortDirection) (string, error) { } } +// MakeContractReaderCursor is exported to ensure cursor structure remains consistent. +func FormatContractReaderCursor(log Log) string { + return fmt.Sprintf("%d-%d-%s", log.BlockNumber, log.LogIndex, log.TxHash) +} + +// ensure valuesFromCursor remains consistent with the function above that creates a cursor func valuesFromCursor(cursor string) (int64, int, []byte, error) { partCount := 3 @@ -492,17 +503,20 @@ func (f *eventSigFilter) Accept(visitor primitives.Visitor) { } } +type HashedValueComparator struct { + Value common.Hash + Operator primitives.ComparisonOperator +} + type eventByWordFilter struct { - EventSig common.Hash - WordIndex uint8 - ValueComparers []primitives.ValueComparator + WordIndex int + HashedValueComparers []HashedValueComparator } -func NewEventByWordFilter(eventSig common.Hash, wordIndex uint8, valueComparers []primitives.ValueComparator) query.Expression { +func NewEventByWordFilter(wordIndex int, valueComparers []HashedValueComparator) query.Expression { return query.Expression{Primitive: &eventByWordFilter{ - EventSig: eventSig, - WordIndex: wordIndex, - ValueComparers: valueComparers, + WordIndex: wordIndex, + HashedValueComparers: valueComparers, }} } @@ -515,10 +529,10 @@ func (f *eventByWordFilter) Accept(visitor primitives.Visitor) { type eventByTopicFilter struct { Topic uint64 - ValueComparers []primitives.ValueComparator + ValueComparers []HashedValueComparator } -func NewEventByTopicFilter(topicIndex uint64, valueComparers []primitives.ValueComparator) query.Expression { +func NewEventByTopicFilter(topicIndex uint64, valueComparers []HashedValueComparator) query.Expression { return query.Expression{Primitive: &eventByTopicFilter{ Topic: topicIndex, ValueComparers: valueComparers, diff --git a/core/chains/evm/logpoller/parser_test.go b/core/chains/evm/logpoller/parser_test.go index 27af9e83188..8446b3c93ef 100644 --- a/core/chains/evm/logpoller/parser_test.go +++ b/core/chains/evm/logpoller/parser_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -34,7 +35,7 @@ func TestDSLParser(t *testing.T) { result, args, err := parser.buildQuery(chainID, expressions, limiter) require.NoError(t, err) - assert.Equal(t, "SELECT evm.logs.* FROM evm.logs WHERE evm_chain_id = :evm_chain_id ORDER BY "+defaultSort, result) + assert.Equal(t, logsQuery(" WHERE evm_chain_id = :evm_chain_id ORDER BY "+defaultSort), result) assertArgs(t, args, 1) }) @@ -52,15 +53,14 @@ func TestDSLParser(t *testing.T) { limiter := query.NewLimitAndSort(query.CursorLimit("10-5-0x42", query.CursorFollowing, 20)) result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND (address = :address_0 AND event_sig = :event_sig_0 " + - "AND block_number <= " + - "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + - "AND (block_number > :cursor_block_number OR (block_number = :cursor_block_number AND log_index > :cursor_log_index)) " + - "ORDER BY block_number ASC, log_index ASC, tx_hash ASC " + - "LIMIT 20" + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND (address = :address_0 AND event_sig = :event_sig_0 " + + "AND block_number <= " + + "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + + "AND (block_number > :cursor_block_number OR (block_number = :cursor_block_number AND log_index > :cursor_log_index)) " + + "ORDER BY block_number ASC, log_index ASC, tx_hash ASC " + + "LIMIT 20") require.NoError(t, err) assert.Equal(t, expected, result) @@ -80,12 +80,11 @@ func TestDSLParser(t *testing.T) { limiter := query.NewLimitAndSort(query.CountLimit(20)) result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND (address = :address_0 AND event_sig = :event_sig_0) " + - "ORDER BY " + defaultSort + " " + - "LIMIT 20" + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND (address = :address_0 AND event_sig = :event_sig_0) " + + "ORDER BY " + defaultSort + " " + + "LIMIT 20") require.NoError(t, err) assert.Equal(t, expected, result) @@ -102,10 +101,9 @@ func TestDSLParser(t *testing.T) { limiter := query.NewLimitAndSort(query.Limit{}, query.NewSortBySequence(query.Desc)) result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "ORDER BY block_number DESC, log_index DESC, tx_hash DESC" + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "ORDER BY block_number DESC, log_index DESC, tx_hash DESC") require.NoError(t, err) assert.Equal(t, expected, result) @@ -122,10 +120,9 @@ func TestDSLParser(t *testing.T) { limiter := query.NewLimitAndSort(query.Limit{}, query.NewSortByBlock(query.Asc), query.NewSortByTimestamp(query.Desc)) result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "ORDER BY block_number ASC, block_timestamp DESC" + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "ORDER BY block_number ASC, block_timestamp DESC") require.NoError(t, err) assert.Equal(t, expected, result) @@ -147,16 +144,15 @@ func TestDSLParser(t *testing.T) { limiter := query.NewLimitAndSort(query.CursorLimit("10-20-0x42", query.CursorPrevious, 20)) result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND (block_timestamp = :block_timestamp_0 " + - "AND tx_hash = :tx_hash_0 " + - "AND block_number != :block_number_0 " + - "AND block_number <= " + - "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + - "AND (block_number < :cursor_block_number OR (block_number = :cursor_block_number AND log_index < :cursor_log_index)) " + - "ORDER BY block_number DESC, log_index DESC, tx_hash DESC LIMIT 20" + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND (block_timestamp = :block_timestamp_0 " + + "AND tx_hash = :tx_hash_0 " + + "AND block_number != :block_number_0 " + + "AND block_number <= " + + "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + + "AND (block_number < :cursor_block_number OR (block_number = :cursor_block_number AND log_index < :cursor_log_index)) " + + "ORDER BY block_number DESC, log_index DESC, tx_hash DESC LIMIT 20") require.NoError(t, err) assert.Equal(t, expected, result) @@ -175,10 +171,9 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND block_number <= (SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND block_number <= (SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) @@ -194,10 +189,9 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) @@ -213,10 +207,9 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) @@ -233,8 +226,8 @@ func TestDSLParser(t *testing.T) { t.Run("query for event by word", func(t *testing.T) { t.Parallel() - wordFilter := NewEventByWordFilter(common.HexToHash("0x42"), 8, []primitives.ValueComparator{ - {Value: "", Operator: primitives.Gt}, + wordFilter := NewEventByWordFilter(8, []HashedValueComparator{ + {Value: common.HexToHash(""), Operator: primitives.Gt}, }) parser := &pgDSLParser{} @@ -243,10 +236,9 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0 ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0 ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) @@ -257,9 +249,9 @@ func TestDSLParser(t *testing.T) { t.Run("query for event topic", func(t *testing.T) { t.Parallel() - topicFilter := NewEventByTopicFilter(2, []primitives.ValueComparator{ - {Value: "a", Operator: primitives.Gt}, - {Value: "b", Operator: primitives.Lt}, + topicFilter := NewEventByTopicFilter(2, []HashedValueComparator{ + {Value: common.HexToHash("a"), Operator: primitives.Gt}, + {Value: common.HexToHash("b"), Operator: primitives.Lt}, }) parser := &pgDSLParser{} @@ -268,10 +260,9 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND topics[:topic_index_0] > :topic_value_0 AND topics[:topic_index_0] < :topic_value_1 ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND topics[:topic_index_0] > :topic_value_0 AND topics[:topic_index_0] < :topic_value_1 ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) @@ -304,12 +295,11 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND (block_timestamp >= :block_timestamp_0 " + - "AND (tx_hash = :tx_hash_0 " + - "OR block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1))) ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND (block_timestamp >= :block_timestamp_0 " + + "AND (tx_hash = :tx_hash_0 " + + "OR block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1))) ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) @@ -321,9 +311,9 @@ func TestDSLParser(t *testing.T) { t.Run("nested query deep", func(t *testing.T) { t.Parallel() - wordFilter := NewEventByWordFilter(common.HexToHash("0x42"), 8, []primitives.ValueComparator{ - {Value: "a", Operator: primitives.Gt}, - {Value: "b", Operator: primitives.Lte}, + wordFilter := NewEventByWordFilter(8, []HashedValueComparator{ + {Value: common.HexToHash("a"), Operator: primitives.Gt}, + {Value: common.HexToHash("b"), Operator: primitives.Lte}, }) parser := &pgDSLParser{} @@ -353,14 +343,13 @@ func TestDSLParser(t *testing.T) { limiter := query.LimitAndSort{} result, args, err := parser.buildQuery(chainID, expressions, limiter) - expected := "SELECT evm.logs.* " + - "FROM evm.logs " + - "WHERE evm_chain_id = :evm_chain_id " + - "AND (block_timestamp = :block_timestamp_0 " + - "AND (tx_hash = :tx_hash_0 " + - "OR (block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) " + - "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0 " + - "AND substring(data from 32*:word_index_0+1 for 32) <= :word_value_1))) ORDER BY " + defaultSort + expected := logsQuery( + " WHERE evm_chain_id = :evm_chain_id " + + "AND (block_timestamp = :block_timestamp_0 " + + "AND (tx_hash = :tx_hash_0 " + + "OR (block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) " + + "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0 " + + "AND substring(data from 32*:word_index_0+1 for 32) <= :word_value_1))) ORDER BY " + defaultSort) require.NoError(t, err) assert.Equal(t, expected, result) diff --git a/core/chains/evm/testutils/client.go b/core/chains/evm/testutils/client.go index 1e5523fbff9..325e24300be 100644 --- a/core/chains/evm/testutils/client.go +++ b/core/chains/evm/testutils/client.go @@ -6,6 +6,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "strings" "sync" "sync/atomic" "testing" @@ -146,19 +147,52 @@ func (ts *testWSServer) newWSHandler(chainID *big.Int, callback JSONRPCHandler) return } ts.t.Log("Received message", string(data)) + req := gjson.ParseBytes(data) - if !req.IsObject() { - if isSingleObjectArray := req.IsArray() && len(req.Array()) == 1; !isSingleObjectArray { - ts.t.Logf("Request must be object: %v", req.Type) - return - } - req = req.Array()[0] + if req.IsArray() { // Handle batch request + ts.t.Log("Received batch request") + responses := []string{} + for _, reqElem := range req.Array() { + m := reqElem.Get("method") + if m.Type != gjson.String { + ts.t.Logf("Method must be string: %v", m.Type) + continue + } + + var resp JSONRPCResponse + if chainID != nil && m.String() == "eth_chainId" { + resp.Result = `"0x` + chainID.Text(16) + `"` + } else if m.String() == "eth_syncing" { + resp.Result = "false" + } else { + resp = callback(m.String(), reqElem.Get("params")) + } + id := reqElem.Get("id") + var msg string + if resp.Error.Message != "" { + msg = fmt.Sprintf(`{"jsonrpc":"2.0","id":%s,"error":{"code":%d,"message":"%s"}}`, id, resp.Error.Code, resp.Error.Message) + } else { + msg = fmt.Sprintf(`{"jsonrpc":"2.0","id":%s,"result":%s}`, id, resp.Result) + } + responses = append(responses, msg) + } + responseBatch := fmt.Sprintf("[%s]", strings.Join(responses, ",")) + ts.t.Logf("Sending batch response: %v", responseBatch) + ts.mu.Lock() + err = conn.WriteMessage(websocket.BinaryMessage, []byte(responseBatch)) + ts.mu.Unlock() + if err != nil { + ts.t.Logf("Failed to write message: %v", err) + } + return } + // Handle single request if e := req.Get("error"); e.Exists() { ts.t.Logf("Received jsonrpc error: %v", e) continue } + m := req.Get("method") if m.Type != gjson.String { ts.t.Logf("Method must be string: %v", m.Type) diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go index 8566adcb5c5..bcdb28acb53 100644 --- a/core/chains/evm/txmgr/attempts.go +++ b/core/chains/evm/txmgr/attempts.go @@ -34,8 +34,6 @@ type evmTxAttemptBuilder struct { type evmTxAttemptBuilderFeeConfig interface { EIP1559DynamicFees() bool - TipCapMin() *assets.Wei - PriceMin() *assets.Wei PriceMaxKey(common.Address) *assets.Wei LimitDefault() uint64 } @@ -58,7 +56,7 @@ func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr log // 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) { keySpecificMaxGasPriceWei := c.feeConfig.PriceMaxKey(etx.FromAddress) - fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, opts...) + fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, &etx.FromAddress, &etx.ToAddress, opts...) if err != nil { return attempt, fee, feeLimit, true, pkgerrors.Wrap(err, "failed to get fee") // estimator errors are retryable } @@ -71,8 +69,8 @@ func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx, // used in the txm broadcaster + confirmer when tx ix rejected for too low fee or is not included in a timely manner func (c *evmTxAttemptBuilder) NewBumpTxAttempt(ctx context.Context, etx Tx, previousAttempt TxAttempt, priorAttempts []TxAttempt, lggr logger.Logger) (attempt TxAttempt, bumpedFee gas.EvmFee, bumpedFeeLimit uint64, retryable bool, err error) { keySpecificMaxGasPriceWei := c.feeConfig.PriceMaxKey(etx.FromAddress) - - bumpedFee, bumpedFeeLimit, err = c.EvmFeeEstimator.BumpFee(ctx, previousAttempt.TxFee, etx.FeeLimit, keySpecificMaxGasPriceWei, newEvmPriorAttempts(priorAttempts)) + // Use the fee limit from the previous attempt to maintain limits adjusted for 2D fees or by estimation + bumpedFee, bumpedFeeLimit, err = c.EvmFeeEstimator.BumpFee(ctx, previousAttempt.TxFee, previousAttempt.ChainSpecificFeeLimit, keySpecificMaxGasPriceWei, newEvmPriorAttempts(priorAttempts)) if err != nil { return attempt, bumpedFee, bumpedFeeLimit, true, pkgerrors.Wrap(err, "failed to bump fee") // estimator errors are retryable } @@ -116,12 +114,12 @@ func (c *evmTxAttemptBuilder) NewPurgeTxAttempt(ctx context.Context, etx Tx, lgg func (c *evmTxAttemptBuilder) NewCustomTxAttempt(ctx context.Context, etx Tx, fee gas.EvmFee, gasLimit uint64, txType int, lggr logger.Logger) (attempt TxAttempt, retryable bool, err error) { switch txType { case 0x0: // legacy - if fee.Legacy == nil { + if fee.GasPrice == nil { err = pkgerrors.Errorf("Attempt %v is a type 0 transaction but estimator did not return legacy fee bump", attempt.ID) logger.Sugared(lggr).AssumptionViolation(err.Error()) return attempt, false, err // not retryable } - attempt, err = c.newLegacyAttempt(ctx, etx, fee.Legacy, gasLimit) + attempt, err = c.newLegacyAttempt(ctx, etx, fee.GasPrice, gasLimit) return attempt, true, err case 0x2: // dynamic, EIP1559 if !fee.ValidDynamic() { @@ -130,8 +128,8 @@ func (c *evmTxAttemptBuilder) NewCustomTxAttempt(ctx context.Context, etx Tx, fe return attempt, false, err // not retryable } attempt, err = c.newDynamicFeeAttempt(ctx, etx, gas.DynamicFee{ - FeeCap: fee.DynamicFeeCap, - TipCap: fee.DynamicTipCap, + GasFeeCap: fee.GasFeeCap, + GasTipCap: fee.GasTipCap, }, gasLimit) return attempt, true, err default: @@ -147,8 +145,8 @@ func (c *evmTxAttemptBuilder) NewEmptyTxAttempt(ctx context.Context, nonce evmty value := big.NewInt(0) payload := []byte{} - if fee.Legacy == nil { - return attempt, pkgerrors.New("NewEmptyTranscation: legacy fee cannot be nil") + if fee.GasPrice == nil { + return attempt, pkgerrors.New("NewEmptyTranscation: gas price cannot be nil") } tx := newLegacyTransaction( @@ -156,7 +154,7 @@ func (c *evmTxAttemptBuilder) NewEmptyTxAttempt(ctx context.Context, nonce evmty fromAddress, value, feeLimit, - fee.Legacy, + fee.GasPrice, payload, ) @@ -172,7 +170,7 @@ func (c *evmTxAttemptBuilder) NewEmptyTxAttempt(ctx context.Context, nonce evmty } func (c *evmTxAttemptBuilder) newDynamicFeeAttempt(ctx context.Context, etx Tx, fee gas.DynamicFee, gasLimit uint64) (attempt TxAttempt, err error) { - if err = validateDynamicFeeGas(c.feeConfig, c.feeConfig.TipCapMin(), fee, etx); err != nil { + if err = validateDynamicFeeGas(c.feeConfig, fee, etx); err != nil { return attempt, pkgerrors.Wrap(err, "error validating gas") } @@ -182,8 +180,8 @@ func (c *evmTxAttemptBuilder) newDynamicFeeAttempt(ctx context.Context, etx Tx, &etx.Value, gasLimit, &c.chainID, - fee.TipCap, - fee.FeeCap, + fee.GasTipCap, + fee.GasFeeCap, etx.EncodedPayload, ) tx := types.NewTx(&d) @@ -192,8 +190,7 @@ func (c *evmTxAttemptBuilder) newDynamicFeeAttempt(ctx context.Context, etx Tx, return attempt, err } attempt.TxFee = gas.EvmFee{ - DynamicFeeCap: fee.FeeCap, - DynamicTipCap: fee.TipCap, + DynamicFee: gas.DynamicFee{GasFeeCap: fee.GasFeeCap, GasTipCap: fee.GasTipCap}, } attempt.ChainSpecificFeeLimit = gasLimit attempt.TxType = 2 @@ -208,8 +205,8 @@ type keySpecificEstimator interface { // validateDynamicFeeGas is a sanity check - we have other checks elsewhere, but this // makes sure we _never_ create an invalid attempt -func validateDynamicFeeGas(kse keySpecificEstimator, tipCapMinimum *assets.Wei, fee gas.DynamicFee, etx Tx) error { - gasTipCap, gasFeeCap := fee.TipCap, fee.FeeCap +func validateDynamicFeeGas(kse keySpecificEstimator, fee gas.DynamicFee, etx Tx) error { + gasTipCap, gasFeeCap := fee.GasTipCap, fee.GasFeeCap if gasTipCap == nil { panic("gas tip cap missing") @@ -235,11 +232,6 @@ func validateDynamicFeeGas(kse keySpecificEstimator, tipCapMinimum *assets.Wei, if gasFeeCap.Cmp(max) > 0 { return pkgerrors.Errorf("cannot create tx attempt: specified gas fee cap of %s would exceed max configured gas price of %s for key %s", gasFeeCap.String(), max.String(), etx.FromAddress.String()) } - // Tip must be above minimum - minTip := tipCapMinimum - if gasTipCap.Cmp(minTip) < 0 { - return pkgerrors.Errorf("cannot create tx attempt: specified gas tip cap of %s is below min configured gas tip of %s for key %s", gasTipCap.String(), minTip.String(), etx.FromAddress.String()) - } return nil } @@ -257,7 +249,7 @@ func newDynamicFeeTransaction(nonce uint64, to common.Address, value *big.Int, g } func (c *evmTxAttemptBuilder) newLegacyAttempt(ctx context.Context, etx Tx, gasPrice *assets.Wei, gasLimit uint64) (attempt TxAttempt, err error) { - if err = validateLegacyGas(c.feeConfig, c.feeConfig.PriceMin(), gasPrice, etx); err != nil { + if err = validateLegacyGas(c.feeConfig, gasPrice, etx); err != nil { return attempt, pkgerrors.Wrap(err, "error validating gas") } @@ -279,7 +271,7 @@ func (c *evmTxAttemptBuilder) newLegacyAttempt(ctx context.Context, etx Tx, gasP attempt.State = txmgrtypes.TxAttemptInProgress attempt.SignedRawTx = signedTxBytes attempt.TxID = etx.ID - attempt.TxFee = gas.EvmFee{Legacy: gasPrice} + attempt.TxFee = gas.EvmFee{GasPrice: gasPrice} attempt.Hash = hash attempt.TxType = 0 attempt.ChainSpecificFeeLimit = gasLimit @@ -290,7 +282,7 @@ func (c *evmTxAttemptBuilder) newLegacyAttempt(ctx context.Context, etx Tx, gasP // validateLegacyGas is a sanity check - we have other checks elsewhere, but this // makes sure we _never_ create an invalid attempt -func validateLegacyGas(kse keySpecificEstimator, minGasPriceWei, gasPrice *assets.Wei, etx Tx) error { +func validateLegacyGas(kse keySpecificEstimator, gasPrice *assets.Wei, etx Tx) error { if gasPrice == nil { panic("gas price missing") } @@ -298,10 +290,6 @@ func validateLegacyGas(kse keySpecificEstimator, minGasPriceWei, gasPrice *asset if gasPrice.Cmp(max) > 0 { return pkgerrors.Errorf("cannot create tx attempt: specified gas price of %s would exceed max configured gas price of %s for key %s", gasPrice.String(), max.String(), etx.FromAddress.String()) } - min := minGasPriceWei - if gasPrice.Cmp(min) < 0 { - return pkgerrors.Errorf("cannot create tx attempt: specified gas price of %s is below min configured gas price of %s for key %s", gasPrice.String(), min.String(), etx.FromAddress.String()) - } return nil } @@ -351,10 +339,10 @@ func newEvmPriorAttempts(attempts []TxAttempt) (prior []gas.EvmPriorAttempt) { BroadcastBeforeBlockNum: attempts[i].BroadcastBeforeBlockNum, TxHash: attempts[i].Hash, TxType: attempts[i].TxType, - GasPrice: attempts[i].TxFee.Legacy, + GasPrice: attempts[i].TxFee.GasPrice, DynamicFee: gas.DynamicFee{ - FeeCap: attempts[i].TxFee.DynamicFeeCap, - TipCap: attempts[i].TxFee.DynamicTipCap, + GasFeeCap: attempts[i].TxFee.GasFeeCap, + GasTipCap: attempts[i].TxFee.GasTipCap, }, } prior = append(prior, priorAttempt) diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go index 6be8cd7067b..1e9f4abc552 100644 --- a/core/chains/evm/txmgr/attempts_test.go +++ b/core/chains/evm/txmgr/attempts_test.go @@ -140,18 +140,17 @@ func TestTxm_NewDynamicFeeTx(t *testing.T) { feeCfg := newFeeConfig() feeCfg.priceMax = assets.GWei(200) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), feeCfg, kst, nil) - dynamicFee := gas.DynamicFee{TipCap: assets.GWei(100), FeeCap: assets.GWei(200)} + dynamicFee := gas.DynamicFee{GasTipCap: assets.GWei(100), GasFeeCap: assets.GWei(200)} a, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{ - DynamicTipCap: dynamicFee.TipCap, - DynamicFeeCap: dynamicFee.FeeCap, + DynamicFee: gas.DynamicFee{GasTipCap: dynamicFee.GasTipCap, GasFeeCap: dynamicFee.GasFeeCap}, }, 100, 0x2, lggr) require.NoError(t, err) assert.Equal(t, 100, int(a.ChainSpecificFeeLimit)) - assert.Nil(t, a.TxFee.Legacy) - assert.NotNil(t, a.TxFee.DynamicTipCap) - assert.Equal(t, assets.GWei(100).String(), a.TxFee.DynamicTipCap.String()) - assert.NotNil(t, a.TxFee.DynamicFeeCap) - assert.Equal(t, assets.GWei(200).String(), a.TxFee.DynamicFeeCap.String()) + assert.Nil(t, a.TxFee.GasPrice) + assert.NotNil(t, a.TxFee.GasTipCap) + assert.Equal(t, assets.GWei(100).String(), a.TxFee.GasTipCap.String()) + assert.NotNil(t, a.TxFee.GasFeeCap) + assert.Equal(t, assets.GWei(200).String(), a.TxFee.GasFeeCap.String()) }) t.Run("verifies gas tip and fees", func(t *testing.T) { @@ -171,9 +170,6 @@ func TestTxm_NewDynamicFeeTx(t *testing.T) { {"ignores global min gas price", assets.GWei(5), assets.GWei(5), func(c *toml.EVMConfig) { c.GasEstimator.PriceMin = assets.GWei(6) }, ""}, - {"tip cap below min allowed", assets.GWei(5), assets.GWei(5), func(c *toml.EVMConfig) { - c.GasEstimator.TipCapMin = assets.GWei(6) - }, "specified gas tip cap of 5 gwei is below min configured gas tip of 6 gwei"}, } for _, tt := range cases { @@ -181,10 +177,9 @@ func TestTxm_NewDynamicFeeTx(t *testing.T) { t.Run(test.name, func(t *testing.T) { cfg := testutils.NewTestChainScopedConfig(t, test.setCfg) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), cfg.EVM().GasEstimator(), kst, nil) - dynamicFee := gas.DynamicFee{TipCap: test.tipcap, FeeCap: test.feecap} + dynamicFee := gas.DynamicFee{GasTipCap: test.tipcap, GasFeeCap: test.feecap} _, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{ - DynamicTipCap: dynamicFee.TipCap, - DynamicFeeCap: dynamicFee.FeeCap, + DynamicFee: gas.DynamicFee{GasTipCap: dynamicFee.GasTipCap, GasFeeCap: dynamicFee.GasFeeCap}, }, 100, 0x2, lggr) if test.expectError == "" { require.NoError(t, err) @@ -209,17 +204,17 @@ func TestTxm_NewLegacyAttempt(t *testing.T) { t.Run("creates attempt with fields", func(t *testing.T) { var n evmtypes.Nonce - a, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{Legacy: assets.NewWeiI(25)}, 100, 0x0, lggr) + a, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{Sequence: &n, FromAddress: addr}, gas.EvmFee{GasPrice: assets.NewWeiI(25)}, 100, 0x0, lggr) require.NoError(t, err) assert.Equal(t, 100, int(a.ChainSpecificFeeLimit)) - assert.NotNil(t, a.TxFee.Legacy) - assert.Equal(t, "25 wei", a.TxFee.Legacy.String()) - assert.Nil(t, a.TxFee.DynamicTipCap) - assert.Nil(t, a.TxFee.DynamicFeeCap) + assert.NotNil(t, a.TxFee.GasPrice) + assert.Equal(t, "25 wei", a.TxFee.GasPrice.String()) + assert.Nil(t, a.TxFee.GasTipCap) + assert.Nil(t, a.TxFee.GasFeeCap) }) t.Run("verifies max gas price", func(t *testing.T) { - _, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{FromAddress: addr}, gas.EvmFee{Legacy: assets.NewWeiI(100)}, 100, 0x0, lggr) + _, _, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{FromAddress: addr}, gas.EvmFee{GasPrice: assets.NewWeiI(100)}, 100, 0x0, lggr) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("specified gas price of 100 wei would exceed max configured gas price of 50 wei for key %s", addr.String())) }) @@ -238,7 +233,7 @@ func TestTxm_NewPurgeAttempt(t *testing.T) { bumpedLegacy := assets.GWei(30) bumpedDynamicFee := assets.GWei(15) bumpedDynamicTip := assets.GWei(10) - bumpedFee := gas.EvmFee{Legacy: bumpedLegacy, DynamicTipCap: bumpedDynamicTip, DynamicFeeCap: bumpedDynamicFee} + bumpedFee := gas.EvmFee{GasPrice: bumpedLegacy, DynamicFee: gas.DynamicFee{GasTipCap: bumpedDynamicTip, GasFeeCap: bumpedDynamicFee}} est.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bumpedFee, uint64(10_000), nil) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), gc, kst, est) lggr := logger.Test(t) @@ -247,17 +242,17 @@ func TestTxm_NewPurgeAttempt(t *testing.T) { t.Run("creates legacy purge attempt with fields if previous attempt is legacy", func(t *testing.T) { n := evmtypes.Nonce(0) etx := txmgr.Tx{Sequence: &n, FromAddress: addr, EncodedPayload: []byte{1, 2, 3}} - prevAttempt, _, err := cks.NewCustomTxAttempt(ctx, etx, gas.EvmFee{Legacy: bumpedLegacy.Sub(assets.GWei(1))}, 100, 0x0, lggr) + prevAttempt, _, err := cks.NewCustomTxAttempt(ctx, etx, gas.EvmFee{GasPrice: bumpedLegacy.Sub(assets.GWei(1))}, 100, 0x0, lggr) require.NoError(t, err) etx.TxAttempts = append(etx.TxAttempts, prevAttempt) a, err := cks.NewPurgeTxAttempt(ctx, etx, lggr) require.NoError(t, err) // The fee limit is overridden with LimitDefault since purge attempts are just empty attempts require.Equal(t, gc.limitDefault, a.ChainSpecificFeeLimit) - require.NotNil(t, a.TxFee.Legacy) - require.Equal(t, bumpedLegacy.String(), a.TxFee.Legacy.String()) - require.Nil(t, a.TxFee.DynamicTipCap) - require.Nil(t, a.TxFee.DynamicFeeCap) + require.NotNil(t, a.TxFee.GasPrice) + require.Equal(t, bumpedLegacy.String(), a.TxFee.GasPrice.String()) + require.Nil(t, a.TxFee.GasTipCap) + require.Nil(t, a.TxFee.GasFeeCap) require.Equal(t, true, a.IsPurgeAttempt) require.Equal(t, []byte{}, a.Tx.EncodedPayload) require.Equal(t, *big.NewInt(0), a.Tx.Value) @@ -266,18 +261,18 @@ func TestTxm_NewPurgeAttempt(t *testing.T) { t.Run("creates dynamic purge attempt with fields if previous attempt is dynamic", func(t *testing.T) { n := evmtypes.Nonce(0) etx := txmgr.Tx{Sequence: &n, FromAddress: addr, EncodedPayload: []byte{1, 2, 3}} - prevAttempt, _, err := cks.NewCustomTxAttempt(ctx, etx, gas.EvmFee{DynamicTipCap: bumpedDynamicTip.Sub(assets.GWei(1)), DynamicFeeCap: bumpedDynamicFee.Sub(assets.GWei(1))}, 100, 0x2, lggr) + prevAttempt, _, err := cks.NewCustomTxAttempt(ctx, etx, gas.EvmFee{DynamicFee: gas.DynamicFee{GasTipCap: bumpedDynamicTip.Sub(assets.GWei(1)), GasFeeCap: bumpedDynamicFee.Sub(assets.GWei(1))}}, 100, 0x2, lggr) require.NoError(t, err) etx.TxAttempts = append(etx.TxAttempts, prevAttempt) a, err := cks.NewPurgeTxAttempt(ctx, etx, lggr) require.NoError(t, err) // The fee limit is overridden with LimitDefault since purge attempts are just empty attempts require.Equal(t, gc.limitDefault, a.ChainSpecificFeeLimit) - require.Nil(t, a.TxFee.Legacy) - require.NotNil(t, a.TxFee.DynamicTipCap) - require.NotNil(t, a.TxFee.DynamicFeeCap) - require.Equal(t, bumpedDynamicTip.String(), a.TxFee.DynamicTipCap.String()) - require.Equal(t, bumpedDynamicFee.String(), a.TxFee.DynamicFeeCap.String()) + require.Nil(t, a.TxFee.GasPrice) + require.NotNil(t, a.TxFee.GasTipCap) + require.NotNil(t, a.TxFee.GasFeeCap) + require.Equal(t, bumpedDynamicTip.String(), a.TxFee.GasTipCap.String()) + require.Equal(t, bumpedDynamicFee.String(), a.TxFee.GasFeeCap.String()) require.Equal(t, true, a.IsPurgeAttempt) require.Equal(t, []byte{}, a.Tx.EncodedPayload) require.Equal(t, *big.NewInt(0), a.Tx.Value) @@ -286,7 +281,7 @@ func TestTxm_NewPurgeAttempt(t *testing.T) { t.Run("creates bump purge attempt with fields", func(t *testing.T) { n := evmtypes.Nonce(0) etx := txmgr.Tx{Sequence: &n, FromAddress: addr, EncodedPayload: []byte{1, 2, 3}} - prevAttempt, _, err := cks.NewCustomTxAttempt(ctx, etx, gas.EvmFee{Legacy: bumpedLegacy.Sub(assets.GWei(1))}, 100, 0x0, lggr) + prevAttempt, _, err := cks.NewCustomTxAttempt(ctx, etx, gas.EvmFee{GasPrice: bumpedLegacy.Sub(assets.GWei(1))}, 100, 0x0, lggr) require.NoError(t, err) etx.TxAttempts = append(etx.TxAttempts, prevAttempt) purgeAttempt, err := cks.NewPurgeTxAttempt(ctx, etx, lggr) @@ -296,10 +291,10 @@ func TestTxm_NewPurgeAttempt(t *testing.T) { require.NoError(t, err) // The fee limit is overridden with LimitDefault since purge attempts are just empty attempts require.Equal(t, gc.limitDefault, bumpAttempt.ChainSpecificFeeLimit) - require.NotNil(t, bumpAttempt.TxFee.Legacy) - require.Equal(t, bumpedLegacy.String(), bumpAttempt.TxFee.Legacy.String()) - require.Nil(t, bumpAttempt.TxFee.DynamicTipCap) - require.Nil(t, bumpAttempt.TxFee.DynamicFeeCap) + require.NotNil(t, bumpAttempt.TxFee.GasPrice) + require.Equal(t, bumpedLegacy.String(), bumpAttempt.TxFee.GasPrice.String()) + require.Nil(t, bumpAttempt.TxFee.GasTipCap) + require.Nil(t, bumpAttempt.TxFee.GasFeeCap) require.Equal(t, true, bumpAttempt.IsPurgeAttempt) require.Equal(t, []byte{}, bumpAttempt.Tx.EncodedPayload) require.Equal(t, *big.NewInt(0), bumpAttempt.Tx.Value) @@ -313,19 +308,18 @@ func TestTxm_NewCustomTxAttempt_NonRetryableErrors(t *testing.T) { lggr := logger.Test(t) cks := txmgr.NewEvmTxAttemptBuilder(*big.NewInt(1), newFeeConfig(), kst, nil) - dynamicFee := gas.DynamicFee{TipCap: assets.GWei(100), FeeCap: assets.GWei(200)} + dynamicFee := gas.DynamicFee{GasTipCap: assets.GWei(100), GasFeeCap: assets.GWei(200)} legacyFee := assets.NewWeiI(100) t.Run("dynamic fee with legacy tx type", func(t *testing.T) { _, retryable, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{}, gas.EvmFee{ - DynamicTipCap: dynamicFee.TipCap, - DynamicFeeCap: dynamicFee.FeeCap, + DynamicFee: dynamicFee, }, 100, 0x0, lggr) require.Error(t, err) assert.False(t, retryable) }) t.Run("legacy fee with dynamic tx type", func(t *testing.T) { - _, retryable, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{}, gas.EvmFee{Legacy: legacyFee}, 100, 0x2, lggr) + _, retryable, err := cks.NewCustomTxAttempt(tests.Context(t), txmgr.Tx{}, gas.EvmFee{GasPrice: legacyFee}, 100, 0x2, lggr) require.Error(t, err) assert.False(t, retryable) }) @@ -339,7 +333,7 @@ func TestTxm_NewCustomTxAttempt_NonRetryableErrors(t *testing.T) { func TestTxm_EvmTxAttemptBuilder_RetryableEstimatorError(t *testing.T) { est := gasmocks.NewEvmFeeEstimator(t) - est.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) + est.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) est.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) kst := ksmocks.NewEth(t) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index c6c342973bb..bafe46fefc5 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -29,8 +29,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + commmonfee "github.com/smartcontractkit/chainlink/v2/common/fee" 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" @@ -43,11 +45,11 @@ import ( "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/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) // NewEthBroadcaster creates a new txmgr.EthBroadcaster for use in testing. @@ -69,7 +71,7 @@ func NewTestEthBroadcaster( estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), nil, ge.BlockHistory(), lggr, nil) - }, ge.EIP1559DynamicFees(), ge) + }, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, keyStore, estimator) ethBroadcaster := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), gconfig.Database().Listener(), keyStore, txBuilder, nonceTracker, lggr, checkerFactory, nonceAutoSync, "") @@ -343,10 +345,10 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { attempt := earlierTransaction.TxAttempts[0] assert.Equal(t, earlierTransaction.ID, attempt.TxID) - assert.NotNil(t, attempt.TxFee.Legacy) - assert.Nil(t, attempt.TxFee.DynamicTipCap) - assert.Nil(t, attempt.TxFee.DynamicFeeCap) - assert.Equal(t, evmcfg.EVM().GasEstimator().PriceDefault(), attempt.TxFee.Legacy) + assert.NotNil(t, attempt.TxFee.GasPrice) + assert.Nil(t, attempt.TxFee.GasTipCap) + assert.Nil(t, attempt.TxFee.GasFeeCap) + assert.Equal(t, evmcfg.EVM().GasEstimator().PriceDefault(), attempt.TxFee.GasPrice) _, err = txmgr.GetGethSignedTx(attempt.SignedRawTx) require.NoError(t, err) @@ -369,7 +371,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { attempt = laterTransaction.TxAttempts[0] assert.Equal(t, laterTransaction.ID, attempt.TxID) - assert.Equal(t, evmcfg.EVM().GasEstimator().PriceDefault(), attempt.TxFee.Legacy) + assert.Equal(t, evmcfg.EVM().GasEstimator().PriceDefault(), attempt.TxFee.GasPrice) _, err = txmgr.GetGethSignedTx(attempt.SignedRawTx) require.NoError(t, err) @@ -418,9 +420,9 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { attempt := etx.TxAttempts[0] assert.Equal(t, etx.ID, attempt.TxID) - assert.Nil(t, attempt.TxFee.Legacy) - assert.Equal(t, rnd, attempt.TxFee.DynamicTipCap.ToInt().Int64()) - assert.Equal(t, rnd+1, attempt.TxFee.DynamicFeeCap.ToInt().Int64()) + assert.Nil(t, attempt.TxFee.GasPrice) + assert.Equal(t, rnd, attempt.TxFee.GasTipCap.ToInt().Int64()) + assert.Equal(t, rnd+1, attempt.TxFee.GasFeeCap.ToInt().Int64()) _, err = txmgr.GetGethSignedTx(attempt.SignedRawTx) require.NoError(t, err) @@ -642,7 +644,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi chStartEstimate := make(chan struct{}) chBlock := make(chan struct{}) - estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, ccfg.EVM().GasEstimator().PriceMaxKey(fromAddress)).Return(gas.EvmFee{Legacy: assets.GWei(32)}, uint64(500), nil).Run(func(_ mock.Arguments) { + estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, ccfg.EVM().GasEstimator().PriceMaxKey(fromAddress), mock.Anything, mock.Anything).Return(gas.EvmFee{GasPrice: assets.GWei(32)}, uint64(500), nil).Run(func(_ mock.Arguments) { close(chStartEstimate) <-chBlock }).Once() @@ -1177,7 +1179,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("callback set by ctor", func(t *testing.T) { estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, evmcfg.EVM().GasEstimator().BlockHistory(), lggr, nil) - }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator()) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator(), ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress) eb2 := txmgr.NewEvmBroadcaster(txStore, txmClient, txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, lggr, &testCheckerFactory{}, false, "") @@ -1421,7 +1423,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { assert.False(t, etx.Error.Valid) assert.Len(t, etx.TxAttempts, 1) attempt := etx.TxAttempts[0] - assert.Equal(t, "30 gwei", attempt.TxFee.Legacy.String()) + assert.Equal(t, "30 gwei", attempt.TxFee.GasPrice.String()) }) etxUnfinished := txmgr.Tx{ @@ -1488,7 +1490,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { assert.False(t, etx.Error.Valid) assert.Len(t, etx.TxAttempts, 1) attempt := etx.TxAttempts[0] - assert.Equal(t, "20 gwei", attempt.TxFee.Legacy.String()) + assert.Equal(t, "20 gwei", attempt.TxFee.GasPrice.String()) }) t.Run("eth node returns underpriced transaction and bumping gas doesn't increase it", func(t *testing.T) { @@ -1522,7 +1524,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { pgtest.MustExec(t, db, `DELETE FROM evm.txes WHERE nonce = $1`, localNextNonce) }) - t.Run("eth tx is left in progress if eth node returns insufficient eth", func(t *testing.T) { + t.Run("tx is left in progress and its attempt gets replaced with a new re-estimated attempt if node returns insufficient eth", func(t *testing.T) { insufficientEthError := "insufficient funds for transfer" localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) @@ -1618,31 +1620,17 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // configured for the transaction pool. // This is a configuration error by the node operator, since it means they set the base gas level too low. underpricedError := "transaction underpriced" - localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) - // Check gas tip cap verification - evmcfg2 := evmtest.NewChainScopedConfig(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) - c.EVM[0].GasEstimator.TipCapDefault = assets.NewWeiI(0) - })) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() - eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) - - retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress) - require.Error(t, err) - require.Contains(t, err.Error(), "specified gas tip cap of 0 is below min configured gas tip of 1 wei for key") - assert.True(t, retryable) - gasTipCapDefault := assets.NewWeiI(42) - evmcfg2 = evmtest.NewChainScopedConfig(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + evmcfg2 := evmtest.NewChainScopedConfig(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) c.EVM[0].GasEstimator.TipCapDefault = gasTipCapDefault })) - localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress) + localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() - eb2 = NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) + eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) // Second was underpriced but above minimum ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { @@ -1657,7 +1645,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { 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() - retryable, err = eb2.ProcessUnstartedTxs(ctx, fromAddress) + retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress) require.NoError(t, err) assert.False(t, retryable) @@ -1666,6 +1654,73 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { }) } +func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) { + toAddress := testutils.NewAddress() + value := big.Int(assets.NewEthValue(142)) + gasLimit := uint64(242) + encodedPayload := []byte{0, 1} + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewTestGeneralConfig(t) + cfg.EVMConfigs()[0].GasEstimator.EstimateLimit = ptr(true) // Enabled gas limit estimation + limitMultiplier := float32(1.25) + cfg.EVMConfigs()[0].GasEstimator.LimitMultiplier = ptr(decimal.NewFromFloat32(limitMultiplier)) // Set LimitMultiplier for the buffer + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + + config := evmtest.NewChainScopedConfig(t, cfg) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + lggr := logger.Test(t) + txmClient := txmgr.NewEvmTxmClient(ethClient, nil) + nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmClient) + ge := config.EVM().GasEstimator() + estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(ge, nil, ge.BlockHistory(), lggr, nil) + }, ge.EIP1559DynamicFees(), ge, ethClient) + txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, estimator) + eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, nonceTracker, lggr, &testCheckerFactory{}, false, "") + + // Mark instance as test + eb.XXXTestDisableUnstartedTxAutoProcessing() + servicetest.Run(t, eb) + ctx := tests.Context(t) + t.Run("gas limit lowered after estimation", func(t *testing.T) { + estimatedGasLimit := uint64(100) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) + 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() + + // Do the thing + retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) + assert.NoError(t, err) + assert.False(t, retryable) + + dbEtx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + attempt := dbEtx.TxAttempts[0] + require.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), attempt.ChainSpecificFeeLimit) + }) + t.Run("provided gas limit too low, transaction marked as fatal error", func(t *testing.T) { + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(float32(gasLimit)*limitMultiplier)+1, nil).Once() + + // Do the thing + retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) + assert.NoError(t, err) + assert.False(t, retryable) + + 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) + }) +} + func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { toAddress := gethCommon.HexToAddress("0x6C03DDA95a2AEd917EeCc6eddD4b9D16E6380411") value := big.Int(assets.NewEthValue(142)) @@ -1760,15 +1815,15 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { kst := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Disabled: false}.MustInsertWithState(t, kst) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, evmcfg.EVM().GasEstimator().BlockHistory(), lggr, nil) - }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator()) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator(), ethClient) checkerFactory := &testCheckerFactory{} ge := evmcfg.EVM().GasEstimator() t.Run("does nothing if nonce sync is disabled", func(t *testing.T) { - ethClient := testutils.NewEthClientMockWithDefaultChain(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, estimator) kst := ksmocks.NewEth(t) @@ -1838,7 +1893,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { ge := evmcfg.EVM().GasEstimator() estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, ge.BlockHistory(), lggr, nil) - }, ge.EIP1559DynamicFees(), ge) + }, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, estimator) checkerFactory := &txmgr.CheckerFactory{Client: ethClient} ctx := tests.Context(t) @@ -1849,7 +1904,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNonce }), fromAddress).Return(commonclient.Successful, nil).Once() - ethClient.On("SequenceAt", mock.Anything, fromAddress, mock.Anything).Return(evmtypes.Nonce(1), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Once() mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) @@ -1869,8 +1924,8 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNonce }), fromAddress).Return(commonclient.Successful, nil).Twice() - ethClient.On("SequenceAt", mock.Anything, fromAddress, mock.Anything).Return(evmtypes.Nonce(0), nil).Once() - ethClient.On("SequenceAt", mock.Anything, fromAddress, mock.Anything).Return(evmtypes.Nonce(1), nil).Once() + 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() mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) @@ -1891,7 +1946,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { return tx.Nonce() == localNonce }), fromAddress).Return(commonclient.Successful, nil).Times(4) - ethClient.On("SequenceAt", mock.Anything, fromAddress, mock.Anything).Return(evmtypes.Nonce(0), 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) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go index e995080a260..dfaa4e6bfd8 100644 --- a/core/chains/evm/txmgr/client.go +++ b/core/chains/evm/txmgr/client.go @@ -117,7 +117,12 @@ func (c *evmTxmClient) PendingNonceAt(ctx context.Context, fromAddress common.Ad } func (c *evmTxmClient) SequenceAt(ctx context.Context, addr common.Address, blockNum *big.Int) (evmtypes.Nonce, error) { - return c.client.SequenceAt(ctx, addr, blockNum) + nonce, err := c.client.NonceAt(ctx, addr, blockNum) + if nonce > math.MaxInt64 { + return 0, fmt.Errorf("overflow for nonce: %d", nonce) + } + //nolint:gosec // disable G115 + return evmtypes.Nonce(nonce), err } func (c *evmTxmClient) BatchGetReceipts(ctx context.Context, attempts []TxAttempt) (txReceipt []*evmtypes.Receipt, txErr []error, funcErr error) { @@ -174,9 +179,9 @@ func (c *evmTxmClient) CallContract(ctx context.Context, a TxAttempt, blockNumbe From: a.Tx.FromAddress, To: &a.Tx.ToAddress, Gas: a.Tx.FeeLimit, - GasPrice: a.TxFee.Legacy.ToInt(), - GasFeeCap: a.TxFee.DynamicFeeCap.ToInt(), - GasTipCap: a.TxFee.DynamicTipCap.ToInt(), + GasPrice: a.TxFee.GasPrice.ToInt(), + GasFeeCap: a.TxFee.GasFeeCap.ToInt(), + GasTipCap: a.TxFee.GasTipCap.ToInt(), Value: nil, Data: a.Tx.EncodedPayload, AccessList: nil, diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index eaf79b6aba7..03a43a61cf0 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -58,7 +58,7 @@ func newBroadcastLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int64 attempt.State = txmgrtypes.TxAttemptBroadcast if len(gasPrice) > 0 { gp := gasPrice[0] - attempt.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(gp)} + attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(gp)} } return attempt } @@ -84,7 +84,7 @@ func newInProgressLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int6 attempt.State = txmgrtypes.TxAttemptInProgress if len(gasPrice) > 0 { gp := gasPrice[0] - attempt.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(gp)} + attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(gp)} } return attempt } @@ -129,7 +129,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { newEst := func(logger.Logger) gas.EvmEstimator { return estimator } lggr := logger.Test(t) ge := config.EVM().GasEstimator() - feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) @@ -148,27 +148,28 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { err = ec.Start(ctx) require.Error(t, err) - latestFinalizedHead := evmtypes.Head{ - Number: 8, - Hash: testutils.NewHash(), - Parent: nil, - IsFinalized: true, // We are guaranteed to receive a latestFinalizedHead. + latestFinalizedHead := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), } + // We are guaranteed to receive a latestFinalizedHead. + latestFinalizedHead.IsFinalized.Store(true) - head := evmtypes.Head{ + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(latestFinalizedHead) + head := &evmtypes.Head{ Hash: testutils.NewHash(), Number: 10, - Parent: &evmtypes.Head{ - Hash: testutils.NewHash(), - Number: 9, - Parent: &latestFinalizedHead, - }, } + head.Parent.Store(h9) - ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(&head, nil).Once() - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&latestFinalizedHead, nil).Once() + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(latestFinalizedHead, nil).Once() - err = ec.ProcessHead(ctx, &head) + err = ec.ProcessHead(ctx, head) require.NoError(t, err) // Can successfully close once err = ec.Close() @@ -233,7 +234,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { require.Len(t, attempt1_1.Receipts, 0) t.Run("fetches receipt for one unconfirmed eth_tx", func(t *testing.T) { - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) // Transaction not confirmed yet, receipt is nil ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], hashAttempt1_1, "eth_getTransactionReceipt") @@ -262,7 +263,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { TransactionIndex: uint(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) // First transaction confirmed ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], hashAttempt1_1, "eth_getTransactionReceipt") @@ -289,7 +290,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { TransactionIndex: uint(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) // First transaction confirmed ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], hashAttempt1_1, "eth_getTransactionReceipt") @@ -323,7 +324,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && cltest.BatchElemMatchesParams(b[0], attempt1_1.Hash, "eth_getTransactionReceipt") && @@ -365,10 +366,10 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Run("fetches and saves receipts for several attempts in gas price order", func(t *testing.T) { attempt2_2 := newBroadcastLegacyEthTxAttempt(t, etx2.ID) - attempt2_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(10)} + attempt2_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} attempt2_3 := newBroadcastLegacyEthTxAttempt(t, etx2.ID) - attempt2_3.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(20)} + attempt2_3.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(20)} // Insert order deliberately reversed to test sorting by gas price require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2_3)) @@ -382,7 +383,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 3 && cltest.BatchElemMatchesParams(b[2], attempt2_1.Hash, "eth_getTransactionReceipt") && @@ -414,7 +415,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { nonce++ t.Run("ignores receipt missing BlockHash that comes from querying parity too early", func(t *testing.T) { - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) receipt := evmtypes.Receipt{ TxHash: attempt3_1.Hash, Status: uint64(1), @@ -474,7 +475,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { TransactionIndex: ethReceipt.TransactionIndex, Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt3_1.Hash, "eth_getTransactionReceipt") })).Return(nil).Run(func(args mock.Arguments) { @@ -508,7 +509,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Run("on receipt fetch marks in_progress eth_tx_attempt as broadcast", func(t *testing.T) { attempt4_2 := newInProgressLegacyEthTxAttempt(t, etx4.ID) - attempt4_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(10)} + attempt4_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_2)) @@ -519,7 +520,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { TransactionIndex: uint(1), Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) // Second attempt is confirmed ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && @@ -567,7 +568,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { TransactionIndex: uint(1), Status: uint64(0), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) // First attempt is confirmed and reverted ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 1 && @@ -634,7 +635,7 @@ func TestEthConfirmer_CheckForReceipts_batching(t *testing.T) { attempts = append(attempts, attempt) } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && @@ -702,7 +703,7 @@ func TestEthConfirmer_CheckForReceipts_HandlesNonFwdTxsWithForwardingEnabled(t * Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt.Hash, "eth_getTransactionReceipt") @@ -756,7 +757,7 @@ func TestEthConfirmer_CheckForReceipts_only_likely_confirmed(t *testing.T) { attempts = append(attempts, attempt) } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) var captured []rpc.BatchElem ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { @@ -802,7 +803,7 @@ func TestEthConfirmer_CheckForReceipts_should_not_check_for_likely_unconfirmed(t } // latest nonce is lower that all attempts' nonces - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) require.NoError(t, ec.CheckForReceipts(ctx, 42, latestFinalizedBlockNum)) } @@ -820,7 +821,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt_scoped_to_key(t _, fromAddress2_1 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(20), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(20), nil) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) @@ -940,7 +941,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { TransactionIndex: uint(1), Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(4), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(4), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 6 && cltest.BatchElemMatchesParams(b[0], attempt0_2.Hash, "eth_getTransactionReceipt") && @@ -1008,7 +1009,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { TransactionIndex: uint(1), Status: uint64(1), } - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 3 && cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && @@ -1055,7 +1056,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { // eth_txes with nonce 3 is confirmed t.Run("continues to leave eth_txes with state 'confirmed_missing_receipt' unchanged if at least one attempt is above LatestFinalizedBlockNum", func(t *testing.T) { - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && @@ -1097,7 +1098,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { // eth_txes with nonce 3 is confirmed t.Run("marks eth_Txes with state 'confirmed_missing_receipt' as 'errored' if a receipt fails to show up and all attempts are buried deeper than LatestFinalizedBlockNum", func(t *testing.T) { - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(10), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && @@ -1412,7 +1413,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, tooNew, attempt1_1.ID)) attempt1_2 := newBroadcastLegacyEthTxAttempt(t, etx1.ID) attempt1_2.BroadcastBeforeBlockNum = &onTheMoney - attempt1_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(30000)} + attempt1_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(30000)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) t.Run("returns nothing when the transaction is unconfirmed with an attempt that is recent", func(t *testing.T) { @@ -1554,7 +1555,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { attempt3_2 := newBroadcastLegacyEthTxAttempt(t, etx3.ID) attempt3_2.BroadcastBeforeBlockNum = &oldEnough - attempt3_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(30000)} + attempt3_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(30000)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) t.Run("returns the transaction if it is unconfirmed with two attempts that are older than gasBumpThreshold blocks", func(t *testing.T) { @@ -1569,7 +1570,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { attempt3_3 := newBroadcastLegacyEthTxAttempt(t, etx3.ID) attempt3_3.BroadcastBeforeBlockNum = &tooNew - attempt3_3.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(40000)} + attempt3_3.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(40000)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_3)) t.Run("does not return the transaction if it has some older but one newer attempt", func(t *testing.T) { @@ -1594,7 +1595,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { // not be duplicated attempt4_2 := cltest.NewLegacyEthTxAttempt(t, etx4.ID) attempt4_2.State = txmgrtypes.TxAttemptInsufficientFunds - attempt4_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(40000)} + attempt4_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(40000)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_2)) etx5 := mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, nonce, fromAddress) @@ -1606,7 +1607,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etx6 := mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, nonce, fromAddress) attempt6_2 := newBroadcastLegacyEthTxAttempt(t, etx3.ID) attempt6_2.BroadcastBeforeBlockNum = &tooNew - attempt6_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(30001)} + attempt6_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(30001)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt6_2)) t.Run("returns unique attempts requiring resubmission due to insufficient eth, ordered by nonce asc", func(t *testing.T) { @@ -1661,7 +1662,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing 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...")) ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -1711,7 +1712,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing newEst := func(logger.Logger) gas.EvmEstimator { return estimator } // Create confirmer with necessary state ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -1901,7 +1902,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("creates new attempt with higher gas price if transaction has an attempt older than threshold", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(20000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) kst.On("SignTx", mock.Anything, @@ -1931,7 +1932,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // Got the new attempt attempt1_2 = etx.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_2.State) }) @@ -1949,7 +1950,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("creates new attempt with higher gas price if transaction is already in mempool (e.g. due to previous crash before we could save the new attempt)", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(25000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) kst.On("SignTx", mock.Anything, @@ -1978,7 +1979,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // Got the new attempt attempt1_3 = etx.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_3.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_3.TxFee.GasPrice.ToInt().Int64()) assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_3.State) }) @@ -1987,7 +1988,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("saves new attempt even for transaction that has already been confirmed (nonce already used)", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(30000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) receipt := evmtypes.Receipt{BlockNumber: big.NewInt(40)} @@ -2016,7 +2017,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // Got the new attempt attempt1_4 = etx.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_4.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_4.TxFee.GasPrice.ToInt().Int64()) require.Len(t, etx.TxAttempts, 4) require.Equal(t, attempt1_1.ID, etx.TxAttempts[3].ID) @@ -2040,7 +2041,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("saves in-progress attempt on temporary error and returns error", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(20000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt2_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt2_1.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) n := *etx2.Sequence @@ -2107,7 +2108,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("assumes that 'nonce too low' error means confirmed_missing_receipt", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(25000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt2_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt2_1.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) n := *etx2.Sequence @@ -2149,7 +2150,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("saves attempt anyway if replacement transaction is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(42000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_1.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) kst.On("SignTx", mock.Anything, @@ -2178,7 +2179,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { require.Equal(t, attempt3_1.ID, etx3.TxAttempts[1].ID) attempt3_2 = etx3.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_2.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_2.TxFee.GasPrice.ToInt().Int64()) }) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_2.ID)) @@ -2186,7 +2187,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("handles case where transaction is already known somehow", func(t *testing.T) { expectedBumpedGasPrice := big.NewInt(50400000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_1.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) kst.On("SignTx", mock.Anything, @@ -2213,7 +2214,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { require.Len(t, etx3.TxAttempts, 3) attempt3_3 = etx3.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_3.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_3.TxFee.GasPrice.ToInt().Int64()) }) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_3.ID)) @@ -2225,7 +2226,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { temporarilyUnderpricedError := "There are too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee." expectedBumpedGasPrice := big.NewInt(60480000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_2.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_2.TxFee.GasPrice.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) kst.On("SignTx", mock.Anything, @@ -2252,7 +2253,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { require.Len(t, etx3.TxAttempts, 4) attempt3_4 = etx3.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_4.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_4.TxFee.GasPrice.ToInt().Int64()) }) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_4.ID)) @@ -2260,7 +2261,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("resubmits at the old price and does not create a new attempt if one of the bumped transactions would exceed EVM.GasEstimator.PriceMax", func(t *testing.T) { // Set price such that the next bump will exceed EVM.GasEstimator.PriceMax // Existing gas price is: 60480000000 - gasPrice := attempt3_4.TxFee.Legacy.ToInt() + gasPrice := attempt3_4.TxFee.GasPrice.ToInt() gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(60500000000) }) @@ -2282,7 +2283,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // No new tx attempts require.Len(t, etx3.TxAttempts, 4) attempt3_4 = etx3.TxAttempts[0] - assert.Equal(t, gasPrice.Int64(), attempt3_4.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, gasPrice.Int64(), attempt3_4.TxFee.GasPrice.ToInt().Int64()) }) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_4.ID)) @@ -2290,7 +2291,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("resubmits at the old price and does not create a new attempt if the current price is exactly EVM.GasEstimator.PriceMax", func(t *testing.T) { // Set price such that the current price is already at EVM.GasEstimator.PriceMax // Existing gas price is: 60480000000 - gasPrice := attempt3_4.TxFee.Legacy.ToInt() + gasPrice := attempt3_4.TxFee.GasPrice.ToInt() gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(60480000000) }) @@ -2312,7 +2313,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // No new tx attempts require.Len(t, etx3.TxAttempts, 4) attempt3_4 = etx3.TxAttempts[0] - assert.Equal(t, gasPrice.Int64(), attempt3_4.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, gasPrice.Int64(), attempt3_4.TxFee.GasPrice.ToInt().Int64()) }) // The EIP-1559 etx and attempt @@ -2349,9 +2350,9 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // A new, bumped attempt require.Len(t, etx4.TxAttempts, 2) attempt4_2 = etx4.TxAttempts[0] - assert.Nil(t, attempt4_2.TxFee.Legacy) - assert.Equal(t, assets.GWei(42).String(), attempt4_2.TxFee.DynamicTipCap.String()) - assert.Equal(t, assets.GWei(120).String(), attempt4_2.TxFee.DynamicFeeCap.String()) + assert.Nil(t, attempt4_2.TxFee.GasPrice) + assert.Equal(t, assets.GWei(42).String(), attempt4_2.TxFee.GasTipCap.String()) + assert.Equal(t, assets.GWei(120).String(), attempt4_2.TxFee.GasFeeCap.String()) assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_2.State) }) @@ -2379,8 +2380,8 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { // No new tx attempts require.Len(t, etx4.TxAttempts, 2) - assert.Equal(t, assets.GWei(999).Int64(), etx4.TxAttempts[0].TxFee.DynamicTipCap.ToInt().Int64()) - assert.Equal(t, assets.GWei(1000).Int64(), etx4.TxAttempts[0].TxFee.DynamicFeeCap.ToInt().Int64()) + assert.Equal(t, assets.GWei(999).Int64(), etx4.TxAttempts[0].TxFee.GasTipCap.ToInt().Int64()) + assert.Equal(t, assets.GWei(1000).Int64(), etx4.TxAttempts[0].TxFee.GasFeeCap.ToInt().Int64()) }) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1, gas_tip_cap=$2, gas_fee_cap=$3 WHERE id=$4 RETURNING *`, @@ -2389,7 +2390,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("EIP-1559: saves attempt anyway if replacement transaction is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { // NOTE: This test case was empirically impossible when I tried it on eth mainnet (any EIP1559 transaction with a higher tip cap is accepted even if it's only 1 wei more) but appears to be possible on Polygon/Matic, probably due to poor design that applies the 10% minimum to the overall value (base fee + tip cap) expectedBumpedTipCap := assets.GWei(54) - require.Greater(t, expectedBumpedTipCap.Int64(), attempt4_2.TxFee.DynamicTipCap.ToInt().Int64()) + require.Greater(t, expectedBumpedTipCap.Int64(), attempt4_2.TxFee.GasTipCap.ToInt().Int64()) ethTx := *types.NewTx(&types.LegacyTx{}) kst.On("SignTx", mock.Anything, @@ -2419,7 +2420,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { require.Equal(t, attempt4_2.ID, etx4.TxAttempts[1].ID) attempt4_3 := etx4.TxAttempts[0] - assert.Equal(t, expectedBumpedTipCap.Int64(), attempt4_3.TxFee.DynamicTipCap.ToInt().Int64()) + assert.Equal(t, expectedBumpedTipCap.Int64(), attempt4_3.TxFee.GasTipCap.ToInt().Int64()) }) } @@ -2572,7 +2573,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) expectedBumpedGasPrice := big.NewInt(20000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64()) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 @@ -2589,7 +2590,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { // Got the new attempt attempt1_2 = etx.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) assert.Equal(t, txmgrtypes.TxAttemptInsufficientFunds, attempt1_2.State) assert.Nil(t, attempt1_2.BroadcastBeforeBlockNum) }) @@ -2598,7 +2599,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) expectedBumpedGasPrice := big.NewInt(20000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64()) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 @@ -2615,7 +2616,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { // The attempt is still "out of eth" attempt1_2 = etx.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) assert.Equal(t, txmgrtypes.TxAttemptInsufficientFunds, attempt1_2.State) }) @@ -2623,7 +2624,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) expectedBumpedGasPrice := big.NewInt(20000000000) - require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.Legacy.ToInt().Int64()) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64()) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 @@ -2640,7 +2641,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { // Attempt is now 'broadcast' attempt1_2 = etx.TxAttempts[0] - assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.Legacy.ToInt().Int64()) + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_2.State) }) @@ -2742,34 +2743,33 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) latestFinalizedHead := evmtypes.Head{ - Number: 8, - Hash: testutils.NewHash(), - Parent: nil, - IsFinalized: false, // We are guaranteed to receive a latestFinalizedHead. + Number: 8, + Hash: testutils.NewHash(), } - head := evmtypes.Head{ + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) + head := &evmtypes.Head{ Hash: testutils.NewHash(), Number: 10, - Parent: &evmtypes.Head{ - Hash: testutils.NewHash(), - Number: 9, - Parent: &evmtypes.Head{ - Number: 8, - Hash: testutils.NewHash(), - Parent: nil, - }, - }, } + head.Parent.Store(h9) t.Run("does nothing if there aren't any transactions", func(t *testing.T) { - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) }) t.Run("does nothing to unconfirmed transactions", func(t *testing.T) { etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2781,7 +2781,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2791,10 +2791,10 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { t.Run("does nothing to confirmed transactions that only have receipts older than the start of the chain", func(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress) // Add receipt that is older than the lowest block of the chain - mustInsertEthReceipt(t, txStore, head.Parent.Parent.Number-1, testutils.NewHash(), etx.TxAttempts[0].Hash) + mustInsertEthReceipt(t, txStore, h8.Number-1, testutils.NewHash(), etx.TxAttempts[0].Hash) // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2805,7 +2805,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress) attempt := etx.TxAttempts[0] // Include one within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attempt.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attempt.Hash) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { atx, err := txmgr.GetGethSignedTx(attempt.SignedRawTx) @@ -2815,7 +2815,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2830,15 +2830,15 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { attempt := etx.TxAttempts[0] attemptHash := attempt.Hash // Add receipt that is older than the lowest block of the chain - mustInsertEthReceipt(t, txStore, head.Parent.Parent.Number-1, testutils.NewHash(), attemptHash) + mustInsertEthReceipt(t, txStore, h8.Number-1, testutils.NewHash(), attemptHash) // Include one within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attemptHash) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2852,7 +2852,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 6, 1, fromAddress) require.Len(t, etx.TxAttempts, 1) // Sanity check to assert the included attempt has the lowest gas price - require.Less(t, etx.TxAttempts[0].TxFee.Legacy.ToInt().Int64(), int64(30000)) + require.Less(t, etx.TxAttempts[0].TxFee.GasPrice.ToInt().Int64(), int64(30000)) attempt2 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 30000) attempt2.SignedRawTx = hexutil.MustDecode("0xf88c8301f3a98503b9aca000832ab98094f5fff180082d6017036b771ba883025c654bc93580a4daa6d556000000000000000000000000000000000000000000000000000000000000000026a0f25601065ee369b6470c0399a2334afcfbeb0b5c8f3d9a9042e448ed29b5bcbda05b676e00248b85faf4dd889f0e2dcf91eb867e23ac9eeb14a73f9e4c14972cdf") @@ -2862,9 +2862,9 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3)) // Receipt is within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attempt2.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attempt2.Hash) // Receipt is within head height but a different block hash - mustInsertEthReceipt(t, txStore, head.Parent.Number, testutils.NewHash(), attempt3.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attempt3.Hash) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { s, err := txmgr.GetGethSignedTx(attempt3.SignedRawTx) @@ -2873,7 +2873,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { }), fromAddress).Return(commonclient.Successful, nil).Once() // Do the thing - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2893,7 +2893,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { // Add receipt that is higher than head mustInsertEthReceipt(t, txStore, head.Number+1, testutils.NewHash(), attempt.Hash) - require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), &head, latestFinalizedHead.BlockNumber())) + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head, latestFinalizedHead.BlockNumber())) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) @@ -2920,7 +2920,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - gasPriceWei := gas.EvmFee{Legacy: assets.GWei(52)} + gasPriceWei := gas.EvmFee{GasPrice: assets.GWei(52)} overrideGasLimit := uint64(20000) t.Run("rebroadcasts one eth_tx if it falls within in nonce range", func(t *testing.T) { @@ -2929,7 +2929,7 @@ 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.Legacy.Int64() && + tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == overrideGasLimit && reflect.DeepEqual(tx.Data(), etx1.EncodedPayload) && tx.To().String() == etx1.ToAddress.String() @@ -2944,7 +2944,7 @@ 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.Legacy.Int64() && + tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == etx1.FeeLimit && reflect.DeepEqual(tx.Data(), etx1.EncodedPayload) && tx.To().String() == etx1.ToAddress.String() @@ -2958,10 +2958,10 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx1.Sequence) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == overrideGasLimit + return tx.Nonce() == uint64(*etx1.Sequence) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == overrideGasLimit }), mock.Anything).Return(commonclient.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.Legacy.Int64() && tx.Gas() == overrideGasLimit + return tx.Nonce() == uint64(*etx2.Sequence) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == overrideGasLimit }), mock.Anything).Return(commonclient.Successful, nil).Once() require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(1), (2)}, gasPriceWei, fromAddress, overrideGasLimit)) @@ -2981,7 +2981,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { nonce := i ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { return tx.Nonce() == uint64(nonce) && - tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && + tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == overrideGasLimit && *tx.To() == fromAddress && tx.Value().Cmp(big.NewInt(0)) == 0 && @@ -2998,7 +2998,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.Legacy.Int64() && tx.Gas() == config.EVM().GasEstimator().LimitDefault() + return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == config.EVM().GasEstimator().LimitDefault() }), mock.Anything).Return(commonclient.Successful, nil).Once() require.NoError(t, ec.ForceRebroadcast(tests.Context(t), []evmtypes.Nonce{(0)}, gasPriceWei, fromAddress, 0)) @@ -3020,19 +3020,20 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { evmcfg := evmtest.NewChainScopedConfig(t, config) + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) head := evmtypes.Head{ Hash: testutils.NewHash(), Number: 10, - Parent: &evmtypes.Head{ - Hash: testutils.NewHash(), - Number: 9, - Parent: &evmtypes.Head{ - Number: 8, - Hash: testutils.NewHash(), - Parent: nil, - }, - }, } + head.Parent.Store(h9) minConfirmations := int64(2) @@ -3054,7 +3055,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { // It would only be in a state past suspended if the resume callback was called and callback_completed was set to TRUE pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - err := ec.ResumePendingTaskRuns(tests.Context(t), &head) + err := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) require.NoError(t, err) }) @@ -3072,7 +3073,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - err := ec.ResumePendingTaskRuns(tests.Context(t), &head) + err := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) require.NoError(t, err) }) @@ -3100,7 +3101,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { t.Cleanup(func() { <-done }) go func() { defer close(done) - err2 := ec.ResumePendingTaskRuns(tests.Context(t), &head) + err2 := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) if !assert.NoError(t, err2) { return } @@ -3154,7 +3155,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { t.Cleanup(func() { <-done }) go func() { defer close(done) - err2 := ec.ResumePendingTaskRuns(tests.Context(t), &head) + err2 := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) if !assert.NoError(t, err2) { return } @@ -3191,7 +3192,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - err := ec.ResumePendingTaskRuns(tests.Context(t), &head) + err := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) require.Error(t, err) // Retrieve Tx to check if callback completed flag was left unchanged @@ -3215,10 +3216,10 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { // Return 10 gwei as market gas price marketGasPrice := tenGwei - fee := gas.EvmFee{Legacy: marketGasPrice} + fee := gas.EvmFee{GasPrice: marketGasPrice} bumpedLegacy := assets.GWei(30) - bumpedFee := gas.EvmFee{Legacy: bumpedLegacy} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) + bumpedFee := gas.EvmFee{GasPrice: bumpedLegacy} + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) feeEstimator.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bumpedFee, uint64(10_000), nil) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) @@ -3235,6 +3236,11 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), evmcfg.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht) + fn := func(ctx context.Context, id uuid.UUID, result interface{}, err error) error { + require.ErrorContains(t, err, client.TerminallyStuckMsg) + return nil + } + ec.SetResumeCallback(fn) servicetest.Run(t, ec) ctx := tests.Context(t) @@ -3246,16 +3252,17 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { // Create autoPurgeMinAttempts number of attempts to ensure the broadcast attempt count check is not being triggered // Create attempts broadcasted autoPurgeThreshold block ago to ensure broadcast block num check is not being triggered tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, nonce, fromAddress, autoPurgeMinAttempts, blockNum-int64(autoPurgeThreshold), marketGasPrice.Add(oneGwei)) - + // Update tx to signal callback once it is identified as terminally stuck + pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, signal_callback = TRUE WHERE id = $2`, uuid.New(), tx.ID) head := evmtypes.Head{ - Hash: testutils.NewHash(), - Number: blockNum, - IsFinalized: true, + Hash: testutils.NewHash(), + Number: blockNum, } + head.IsFinalized.Store(true) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(&head, nil).Once() ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head, nil).Once() - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() ethClient.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Once() // First call to ProcessHead should: @@ -3273,16 +3280,16 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { latestAttempt := dbTx.TxAttempts[0] require.Equal(t, true, latestAttempt.IsPurgeAttempt) require.Equal(t, limitDefault, latestAttempt.ChainSpecificFeeLimit) - require.Equal(t, bumpedFee.Legacy, latestAttempt.TxFee.Legacy) + require.Equal(t, bumpedFee.GasPrice, latestAttempt.TxFee.GasPrice) head = evmtypes.Head{ - Hash: testutils.NewHash(), - Number: blockNum + 1, - IsFinalized: true, + Hash: testutils.NewHash(), + Number: blockNum + 1, } + head.IsFinalized.Store(true) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(&head, nil).Once() ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head, nil).Once() - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(1), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(1), nil) ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 4 && cltest.BatchElemMatchesParams(b[0], latestAttempt.Hash, "eth_getTransactionReceipt") })).Return(nil).Run(func(args mock.Arguments) { @@ -3307,6 +3314,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { require.NotNil(t, dbTx) require.Equal(t, txmgrcommon.TxFatalError, dbTx.State) require.Equal(t, client.TerminallyStuckMsg, dbTx.Error.String) + require.Equal(t, true, dbTx.CallbackCompleted) }) } @@ -3317,7 +3325,7 @@ func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Cl ge := config.EVM().GasEstimator() estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(ge, nil, ge.BlockHistory(), lggr, nil) - }, ge.EIP1559DynamicFees(), ge) + }, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ks, estimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), estimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 4bdf191376b..b75533e8d05 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -294,15 +294,15 @@ type DbEthTxAttempt struct { func (db *DbEthTxAttempt) FromTxAttempt(attempt *TxAttempt) { db.ID = attempt.ID db.EthTxID = attempt.TxID - db.GasPrice = attempt.TxFee.Legacy + db.GasPrice = attempt.TxFee.GasPrice db.SignedRawTx = attempt.SignedRawTx db.Hash = attempt.Hash db.BroadcastBeforeBlockNum = attempt.BroadcastBeforeBlockNum db.CreatedAt = attempt.CreatedAt db.ChainSpecificGasLimit = attempt.ChainSpecificFeeLimit db.TxType = attempt.TxType - db.GasTipCap = attempt.TxFee.DynamicTipCap - db.GasFeeCap = attempt.TxFee.DynamicFeeCap + db.GasTipCap = attempt.TxFee.GasTipCap + db.GasFeeCap = attempt.TxFee.GasFeeCap db.IsPurgeAttempt = attempt.IsPurgeAttempt // handle state naming difference between generic + EVM @@ -331,9 +331,8 @@ func (db DbEthTxAttempt) ToTxAttempt(attempt *TxAttempt) { attempt.ChainSpecificFeeLimit = db.ChainSpecificGasLimit attempt.TxType = db.TxType attempt.TxFee = gas.EvmFee{ - Legacy: db.GasPrice, - DynamicTipCap: db.GasTipCap, - DynamicFeeCap: db.GasFeeCap, + GasPrice: db.GasPrice, + DynamicFee: gas.DynamicFee{GasTipCap: db.GasTipCap, GasFeeCap: db.GasFeeCap}, } attempt.IsPurgeAttempt = db.IsPurgeAttempt } @@ -669,10 +668,8 @@ func (o *evmTxStore) loadEthTxAttemptsReceipts(ctx context.Context, etx *Tx) (er return o.loadEthTxesAttemptsReceipts(ctx, []*Tx{etx}) } -func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { - if len(etxs) == 0 { - return nil - } +// initEthTxesAttempts takes an input txes slice, return an initialized attempt map and attemptHashes slice +func initEthTxesAttempts(etxs []*Tx) (map[common.Hash]*TxAttempt, [][]byte) { attemptHashM := make(map[common.Hash]*TxAttempt, len(etxs)) // len here is lower bound attemptHashes := make([][]byte, len(etxs)) // len here is lower bound for _, etx := range etxs { @@ -681,6 +678,16 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx attemptHashes = append(attemptHashes, attempt.Hash.Bytes()) } } + + return attemptHashM, attemptHashes +} + +func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx) (err error) { + if len(etxs) == 0 { + return nil + } + + attemptHashM, attemptHashes := initEthTxesAttempts(etxs) var rs []DbReceipt if err = o.q.SelectContext(ctx, &rs, `SELECT * FROM evm.receipts WHERE tx_hash = ANY($1)`, pq.Array(attemptHashes)); err != nil { return pkgerrors.Wrap(err, "loadEthTxesAttemptsReceipts failed to load evm.receipts") @@ -697,6 +704,37 @@ func (o *evmTxStore) loadEthTxesAttemptsReceipts(ctx context.Context, etxs []*Tx return nil } +// loadEthTxesAttemptsWithPartialReceipts loads ethTxes with attempts and partial receipts values for optimization +func (o *evmTxStore) loadEthTxesAttemptsWithPartialReceipts(ctx context.Context, etxs []*Tx) (err error) { + if len(etxs) == 0 { + return nil + } + + attemptHashM, attemptHashes := initEthTxesAttempts(etxs) + var rs []DbReceipt + if err = o.q.SelectContext(ctx, &rs, `SELECT evm.receipts.block_hash, evm.receipts.block_number, evm.receipts.transaction_index, evm.receipts.tx_hash FROM evm.receipts WHERE tx_hash = ANY($1)`, pq.Array(attemptHashes)); err != nil { + return pkgerrors.Wrap(err, "loadEthTxesAttemptsReceipts failed to load evm.receipts") + } + + receipts := make([]*evmtypes.Receipt, len(rs)) + for i := 0; i < len(rs); i++ { + receipts[i] = &evmtypes.Receipt{ + BlockHash: rs[i].BlockHash, + BlockNumber: big.NewInt(rs[i].BlockNumber), + TransactionIndex: rs[i].TransactionIndex, + TxHash: rs[i].TxHash, + } + } + + for _, receipt := range receipts { + attempt := attemptHashM[receipt.TxHash] + // Although the attempts struct supports multiple receipts, the expectation for EVM is that there is only one receipt + // per tx and therefore attempt too. + attempt.Receipts = append(attempt.Receipts, receipt) + } + return nil +} + func loadConfirmedAttemptsReceipts(ctx context.Context, q sqlutil.DataSource, attempts []TxAttempt) error { byHash := make(map[string]*TxAttempt, len(attempts)) hashes := make([][]byte, len(attempts)) @@ -1017,7 +1055,7 @@ WHERE evm.tx_attempts.state = 'in_progress' AND evm.txes.from_address = $1 AND e } // Find confirmed txes requiring callback but have not yet been signaled -func (o *evmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID *big.Int) (receiptsPlus []ReceiptPlus, err error) { +func (o *evmTxStore) FindTxesPendingCallback(ctx context.Context, latest, finalized int64, chainID *big.Int) (receiptsPlus []ReceiptPlus, err error) { var rs []dbReceiptPlus var cancel context.CancelFunc @@ -1028,8 +1066,12 @@ func (o *evmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int64 INNER JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id INNER JOIN evm.receipts ON evm.tx_attempts.hash = evm.receipts.tx_hash WHERE evm.txes.pipeline_task_run_id IS NOT NULL AND evm.txes.signal_callback = TRUE AND evm.txes.callback_completed = FALSE - AND evm.receipts.block_number <= ($1 - evm.txes.min_confirmations) AND evm.txes.evm_chain_id = $2 - `, blockNum, chainID.String()) + AND ( + (evm.txes.min_confirmations IS NOT NULL AND evm.receipts.block_number <= ($1 - evm.txes.min_confirmations)) + OR (evm.txes.min_confirmations IS NULL AND evm.receipts.block_number <= $2) + ) + AND evm.txes.evm_chain_id = $3 + `, latest, finalized, chainID.String()) if err != nil { return nil, fmt.Errorf("failed to retrieve transactions pending pipeline resume callback: %w", err) } @@ -1172,7 +1214,9 @@ ORDER BY nonce ASC if err = orm.LoadTxesAttempts(ctx, etxs); err != nil { return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") } - err = orm.loadEthTxesAttemptsReceipts(ctx, etxs) + + // retrieve tx with attempts and partial receipt values for optimization purpose + err = orm.loadEthTxesAttemptsWithPartialReceipts(ctx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) return etxs, pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed") @@ -2068,24 +2112,18 @@ func (o *evmTxStore) UpdateTxAttemptBroadcastBeforeBlockNum(ctx context.Context, return err } -// Returns all confirmed transactions with receipt block nums older than or equal to the finalized block number +// FindConfirmedTxesReceipts Returns all confirmed transactions with receipt block nums older than or equal to the finalized block number func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []Receipt, err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - err = o.Transact(ctx, true, func(orm *evmTxStore) error { - sql := `SELECT evm.receipts.* FROM evm.receipts + + // note the receipts are partially loaded for performance reason + query := `SELECT evm.receipts.id, evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts INNER JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id WHERE evm.txes.state = 'confirmed' AND evm.receipts.block_number <= $1 AND evm.txes.evm_chain_id = $2` - var dbReceipts []DbReceipt - err = o.q.SelectContext(ctx, &dbReceipts, sql, finalizedBlockNum, chainID.String()) - if len(dbReceipts) == 0 { - return nil - } - receipts = dbReceipts - return nil - }) + err = o.q.SelectContext(ctx, &receipts, query, finalizedBlockNum, chainID.String()) return receipts, err } diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 992bd1f434c..9e1f135e0b2 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -49,7 +49,7 @@ func TestORM_TransactionsWithAttempts(t *testing.T) { blockNum := int64(3) attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast - attempt.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(3)} + attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -94,7 +94,7 @@ func TestORM_Transactions(t *testing.T) { blockNum := int64(3) attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast - attempt.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(3)} + attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -142,7 +142,7 @@ func TestORM(t *testing.T) { attemptL = cltest.NewLegacyEthTxAttempt(t, etx.ID) attemptL.State = txmgrtypes.TxAttemptBroadcast - attemptL.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(42)} + attemptL.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(42)} require.NoError(t, orm.InsertTxAttempt(ctx, &attemptL)) assert.Greater(t, int(attemptL.ID), 0) cltest.AssertCount(t, db, "evm.tx_attempts", 2) @@ -200,7 +200,7 @@ func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { blockNum := int64(3) attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast - attempt.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(3)} + attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum require.NoError(t, orm.InsertTxAttempt(ctx, &attempt)) @@ -264,26 +264,26 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { e3, } attempt1_2 := newBroadcastLegacyEthTxAttempt(t, etxs[0].ID) - attempt1_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(10)} + attempt1_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) attempt3_2 := newInProgressLegacyEthTxAttempt(t, etxs[2].ID) - attempt3_2.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(10)} + attempt3_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) attempt4_2 := cltest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) - attempt4_2.TxFee.DynamicTipCap = assets.NewWeiI(10) - attempt4_2.TxFee.DynamicFeeCap = assets.NewWeiI(20) + attempt4_2.TxFee.GasTipCap = assets.NewWeiI(10) + attempt4_2.TxFee.GasFeeCap = assets.NewWeiI(20) attempt4_2.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_2)) attempt4_4 := cltest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) - attempt4_4.TxFee.DynamicTipCap = assets.NewWeiI(30) - attempt4_4.TxFee.DynamicFeeCap = assets.NewWeiI(40) + attempt4_4.TxFee.GasTipCap = assets.NewWeiI(30) + attempt4_4.TxFee.GasFeeCap = assets.NewWeiI(40) attempt4_4.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_4)) attempt4_3 := cltest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) - attempt4_3.TxFee.DynamicTipCap = assets.NewWeiI(20) - attempt4_3.TxFee.DynamicFeeCap = assets.NewWeiI(30) + attempt4_3.TxFee.GasTipCap = assets.NewWeiI(20) + attempt4_3.TxFee.GasFeeCap = assets.NewWeiI(30) attempt4_3.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_3)) @@ -628,19 +628,20 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { pgtest.MustExec(t, db, `SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`) pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`) + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) head := evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 10, - Parent: &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 9, - Parent: &evmtypes.Head{ - Number: 8, - Hash: utils.NewHash(), - Parent: nil, - }, - }, } + head.Parent.Store(h9) minConfirmations := int64(2) @@ -651,7 +652,7 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress) pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) attempt1 := etx1.TxAttempts[0] - mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt1.Hash) + etxBlockNum := mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt1.Hash).BlockNumber pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr1.ID, minConfirmations, etx1.ID) // Callback to pipeline service completed. Should be ignored @@ -684,10 +685,26 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx5.ID) // Search evm.txes table for tx requiring callback - receiptsPlus, err := txStore.FindTxesPendingCallback(tests.Context(t), head.Number, ethClient.ConfiguredChainID()) + receiptsPlus, err := txStore.FindTxesPendingCallback(tests.Context(t), head.Number, 0, ethClient.ConfiguredChainID()) + require.NoError(t, err) + if assert.Len(t, receiptsPlus, 1) { + assert.Equal(t, tr1.ID, receiptsPlus[0].ID) + } + + // Clear min_confirmations + pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = NULL WHERE id = $1`, etx1.ID) + + // Search evm.txes table for tx requiring callback + receiptsPlus, err = txStore.FindTxesPendingCallback(tests.Context(t), head.Number, 0, ethClient.ConfiguredChainID()) require.NoError(t, err) - assert.Len(t, receiptsPlus, 1) - assert.Equal(t, tr1.ID, receiptsPlus[0].ID) + assert.Empty(t, receiptsPlus) + + // Search evm.txes table for tx requiring callback, with block 1 finalized + receiptsPlus, err = txStore.FindTxesPendingCallback(tests.Context(t), head.Number, etxBlockNum, ethClient.ConfiguredChainID()) + require.NoError(t, err) + if assert.Len(t, receiptsPlus, 1) { + assert.Equal(t, tr1.ID, receiptsPlus[0].ID) + } } func Test_FindTxWithIdempotencyKey(t *testing.T) { @@ -792,19 +809,20 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) head := evmtypes.Head{ - Hash: utils.NewHash(), + Hash: testutils.NewHash(), Number: 10, - Parent: &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 9, - Parent: &evmtypes.Head{ - Number: 8, - Hash: utils.NewHash(), - Parent: nil, - }, - }, } + head.Parent.Store(h9) t.Run("find all transactions confirmed in range", func(t *testing.T) { etx_8 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 700, 8) @@ -816,6 +834,12 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { assert.Equal(t, etxes[0].Sequence, etx_8.Sequence) assert.Equal(t, etxes[1].Sequence, etx_9.Sequence) }) + + t.Run("return empty txes when no transactions in range found", func(t *testing.T) { + etxes, err := txStore.FindTransactionsConfirmedInBlockRange(tests.Context(t), 0, 0, ethClient.ConfiguredChainID()) + require.NoError(t, err) + assert.Len(t, etxes, 0) + }) } func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) { @@ -1064,7 +1088,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin etx3 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) attempt3_2 := cltest.NewLegacyEthTxAttempt(t, etx3.ID) attempt3_2.State = txmgrtypes.TxAttemptInsufficientFunds - attempt3_2.TxFee.Legacy = assets.NewWeiI(100) + attempt3_2.TxFee.GasPrice = assets.NewWeiI(100) require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) etx1 := mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, fromAddress) diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index 6d5fb81782c..60744636159 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ) var _ Finalizer = (*evmFinalizer)(nil) @@ -174,7 +175,7 @@ func (f *evmFinalizer) processFinalizedHead(ctx context.Context, latestFinalized // Find transactions with receipt block nums older than the latest finalized block num and block hashes still in chain for _, receipt := range unfinalizedReceipts { // The tx store query ensures transactions have receipts but leaving this check here for a belts and braces approach - if receipt.Receipt.IsZero() || receipt.Receipt.IsUnmined() { + if receipt.TxHash == utils.EmptyHash || receipt.BlockHash == utils.EmptyHash { f.lggr.AssumptionViolationw("invalid receipt found for confirmed transaction", "receipt", receipt) continue } diff --git a/core/chains/evm/txmgr/finalizer_test.go b/core/chains/evm/txmgr/finalizer_test.go index f83a53bf499..b91121d773f 100644 --- a/core/chains/evm/txmgr/finalizer_test.go +++ b/core/chains/evm/txmgr/finalizer_test.go @@ -39,15 +39,16 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { rpcBatchSize := uint32(1) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) + h99 := &evmtypes.Head{ + Hash: utils.NewHash(), + Number: 99, + } + h99.IsFinalized.Store(true) head := &evmtypes.Head{ Hash: utils.NewHash(), Number: 100, - Parent: &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 99, - IsFinalized: true, - }, } + head.Parent.Store(h99) t.Run("returns not finalized for tx with receipt newer than finalized block", func(t *testing.T) { finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) @@ -71,7 +72,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { // Insert receipt for unfinalized block num mustInsertEthReceipt(t, txStore, head.Number, head.Hash, attemptHash) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent.Load(), nil).Once() err := finalizer.ProcessHead(ctx, head) require.NoError(t, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) @@ -99,9 +100,9 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { } attemptHash := insertTxAndAttemptWithIdempotencyKey(t, txStore, tx, idempotencyKey) // Insert receipt for finalized block num - mustInsertEthReceipt(t, txStore, head.Parent.Number, utils.NewHash(), attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, utils.NewHash(), attemptHash) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent.Load(), nil).Once() err := finalizer.ProcessHead(ctx, head) require.NoError(t, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) @@ -129,9 +130,9 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { } attemptHash := insertTxAndAttemptWithIdempotencyKey(t, txStore, tx, idempotencyKey) // Insert receipt for finalized block num - mustInsertEthReceipt(t, txStore, head.Parent.Number, head.Parent.Hash, attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, head.Parent.Load().Hash, attemptHash) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent.Load(), nil).Once() err := finalizer.ProcessHead(ctx, head) require.NoError(t, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) @@ -160,7 +161,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { attemptHash := insertTxAndAttemptWithIdempotencyKey(t, txStore, tx, idempotencyKey) // Insert receipt for finalized block num receiptBlockHash1 := utils.NewHash() - mustInsertEthReceipt(t, txStore, head.Parent.Number-2, receiptBlockHash1, attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number-2, receiptBlockHash1, attemptHash) idempotencyKey = uuid.New().String() nonce = evmtypes.Nonce(1) tx = &txmgr.Tx{ @@ -176,7 +177,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { attemptHash = insertTxAndAttemptWithIdempotencyKey(t, txStore, tx, idempotencyKey) // Insert receipt for finalized block num receiptBlockHash2 := utils.NewHash() - mustInsertEthReceipt(t, txStore, head.Parent.Number-1, receiptBlockHash2, attemptHash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number-1, receiptBlockHash2, attemptHash) // Separate batch calls will be made for each tx due to RPC batch size set to 1 when finalizer initialized above ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { rpcElements := args.Get(1).([]rpc.BatchElem) @@ -186,20 +187,20 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { require.Equal(t, false, rpcElements[0].Args[1]) reqBlockNum := rpcElements[0].Args[0].(string) - req1BlockNum := hexutil.EncodeBig(big.NewInt(head.Parent.Number - 2)) - req2BlockNum := hexutil.EncodeBig(big.NewInt(head.Parent.Number - 1)) + req1BlockNum := hexutil.EncodeBig(big.NewInt(head.Parent.Load().Number - 2)) + req2BlockNum := hexutil.EncodeBig(big.NewInt(head.Parent.Load().Number - 1)) var headResult evmtypes.Head if req1BlockNum == reqBlockNum { - headResult = evmtypes.Head{Number: head.Parent.Number - 2, Hash: receiptBlockHash1} + headResult = evmtypes.Head{Number: head.Parent.Load().Number - 2, Hash: receiptBlockHash1} } else if req2BlockNum == reqBlockNum { - headResult = evmtypes.Head{Number: head.Parent.Number - 1, Hash: receiptBlockHash2} + headResult = evmtypes.Head{Number: head.Parent.Load().Number - 1, Hash: receiptBlockHash2} } else { require.Fail(t, "unrecognized block hash") } rpcElements[0].Result = &headResult }).Return(nil).Twice() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() - ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(head.Parent.Load(), nil).Once() err := finalizer.ProcessHead(ctx, head) require.NoError(t, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index a9a175e3d94..7800b26e47a 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -1395,9 +1395,9 @@ func (_c *EvmTxStore_FindTxesByMetaFieldAndStates_Call) RunAndReturn(run func(co return _c } -// FindTxesPendingCallback provides a mock function with given fields: ctx, blockNum, chainID -func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int64, chainID *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error) { - ret := _m.Called(ctx, blockNum, chainID) +// 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) ([]types.ReceiptPlus[*evmtypes.Receipt], error) { + ret := _m.Called(ctx, latest, finalized, chainID) if len(ret) == 0 { panic("no return value specified for FindTxesPendingCallback") @@ -1405,19 +1405,19 @@ func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int6 var r0 []types.ReceiptPlus[*evmtypes.Receipt] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)); ok { - return rf(ctx, blockNum, chainID) + 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, *big.Int) []types.ReceiptPlus[*evmtypes.Receipt]); ok { - r0 = rf(ctx, blockNum, chainID) + 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).([]types.ReceiptPlus[*evmtypes.Receipt]) } } - if rf, ok := ret.Get(1).(func(context.Context, int64, *big.Int) error); ok { - r1 = rf(ctx, blockNum, chainID) + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, *big.Int) error); ok { + r1 = rf(ctx, latest, finalized, chainID) } else { r1 = ret.Error(1) } @@ -1432,15 +1432,16 @@ type EvmTxStore_FindTxesPendingCallback_Call struct { // FindTxesPendingCallback is a helper method to define mock.On call // - ctx context.Context -// - blockNum int64 +// - latest int64 +// - finalized int64 // - chainID *big.Int -func (_e *EvmTxStore_Expecter) FindTxesPendingCallback(ctx interface{}, blockNum interface{}, chainID interface{}) *EvmTxStore_FindTxesPendingCallback_Call { - return &EvmTxStore_FindTxesPendingCallback_Call{Call: _e.mock.On("FindTxesPendingCallback", ctx, blockNum, chainID)} +func (_e *EvmTxStore_Expecter) FindTxesPendingCallback(ctx interface{}, latest interface{}, finalized interface{}, chainID interface{}) *EvmTxStore_FindTxesPendingCallback_Call { + return &EvmTxStore_FindTxesPendingCallback_Call{Call: _e.mock.On("FindTxesPendingCallback", ctx, latest, finalized, chainID)} } -func (_c *EvmTxStore_FindTxesPendingCallback_Call) Run(run func(ctx context.Context, blockNum int64, chainID *big.Int)) *EvmTxStore_FindTxesPendingCallback_Call { +func (_c *EvmTxStore_FindTxesPendingCallback_Call) Run(run func(ctx context.Context, latest int64, finalized int64, chainID *big.Int)) *EvmTxStore_FindTxesPendingCallback_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(int64), args[2].(*big.Int)) + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(*big.Int)) }) return _c } @@ -1450,7 +1451,7 @@ func (_c *EvmTxStore_FindTxesPendingCallback_Call) Return(receiptsPlus []types.R return _c } -func (_c *EvmTxStore_FindTxesPendingCallback_Call) RunAndReturn(run func(context.Context, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], 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 } diff --git a/core/chains/evm/txmgr/stuck_tx_detector.go b/core/chains/evm/txmgr/stuck_tx_detector.go index 5d621dc0b20..a8bb18af416 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector.go +++ b/core/chains/evm/txmgr/stuck_tx_detector.go @@ -25,7 +25,7 @@ import ( ) type stuckTxDetectorGasEstimator interface { - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, 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 ...feetypes.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) } type stuckTxDetectorClient interface { @@ -130,6 +130,8 @@ func (d *stuckTxDetector) DetectStuckTransactions(ctx context.Context, enabledAd return d.detectStuckTransactionsScroll(ctx, txs) case chaintype.ChainZkEvm, chaintype.ChainXLayer: return d.detectStuckTransactionsZkEVM(ctx, txs) + case chaintype.ChainZircuit: + return d.detectStuckTransactionsZircuit(ctx, txs, blockNum) default: return d.detectStuckTransactionsHeuristic(ctx, txs, blockNum) } @@ -199,7 +201,7 @@ func (d *stuckTxDetector) detectStuckTransactionsHeuristic(ctx context.Context, defer d.purgeBlockNumLock.RUnlock() // Get gas price from internal gas estimator // Send with max gas price time 2 to prevent the results from being capped. Need the market gas price here. - marketGasPrice, _, err := d.gasEstimator.GetFee(ctx, []byte{}, 0, d.maxPrice.Mul(big.NewInt(2))) + marketGasPrice, _, err := d.gasEstimator.GetFee(ctx, []byte{}, 0, d.maxPrice.Mul(big.NewInt(2)), nil, nil) if err != nil { return txs, fmt.Errorf("failed to get market gas price for overflow detection: %w", err) } @@ -215,10 +217,25 @@ func (d *stuckTxDetector) detectStuckTransactionsHeuristic(ctx context.Context, } // Tx attempts are loaded from newest to oldest oldestBroadcastAttempt, newestBroadcastAttempt, broadcastedAttemptsCount := findBroadcastedAttempts(tx) + d.lggr.Debugf("found %d broadcasted attempts for tx id %d in stuck transaction heuristic", broadcastedAttemptsCount, tx.ID) + + // attempt shouldn't be nil as we validated in FindUnconfirmedTxWithLowestNonce, but added anyway for a "belts and braces" approach + if oldestBroadcastAttempt == nil || newestBroadcastAttempt == nil { + d.lggr.Debugw("failed to find broadcast attempt for tx in stuck transaction heuristic", "tx", tx) + continue + } + + // sanity check + if oldestBroadcastAttempt.BroadcastBeforeBlockNum == nil { + d.lggr.Debugw("BroadcastBeforeBlockNum was not set for broadcast attempt in stuck transaction heuristic", "attempt", oldestBroadcastAttempt) + continue + } + // 2. Check if Threshold amount of blocks have passed since the oldest attempt's broadcast block num if *oldestBroadcastAttempt.BroadcastBeforeBlockNum > blockNum-int64(*d.cfg.Threshold()) { continue } + // 3. Check if the transaction has at least MinAttempts amount of broadcasted attempts if broadcastedAttemptsCount < *d.cfg.MinAttempts() { continue @@ -234,27 +251,28 @@ func (d *stuckTxDetector) detectStuckTransactionsHeuristic(ctx context.Context, } func compareGasFees(attemptGas gas.EvmFee, marketGas gas.EvmFee) int { - if attemptGas.Legacy != nil && marketGas.Legacy != nil { - return attemptGas.Legacy.Cmp(marketGas.Legacy) + if attemptGas.GasPrice != nil && marketGas.GasPrice != nil { + return attemptGas.GasPrice.Cmp(marketGas.GasPrice) } - if attemptGas.DynamicFeeCap.Cmp(marketGas.DynamicFeeCap) == 0 { - return attemptGas.DynamicTipCap.Cmp(marketGas.DynamicTipCap) + if attemptGas.GasFeeCap.Cmp(marketGas.GasFeeCap) == 0 { + return attemptGas.GasTipCap.Cmp(marketGas.GasTipCap) } - return attemptGas.DynamicFeeCap.Cmp(marketGas.DynamicFeeCap) + return attemptGas.GasFeeCap.Cmp(marketGas.GasFeeCap) } // Assumes tx attempts are loaded newest to oldest -func findBroadcastedAttempts(tx Tx) (oldestAttempt TxAttempt, newestAttempt TxAttempt, broadcastedCount uint32) { +func findBroadcastedAttempts(tx Tx) (oldestAttempt *TxAttempt, newestAttempt *TxAttempt, broadcastedCount uint32) { foundNewest := false - for _, attempt := range tx.TxAttempts { + for i := range tx.TxAttempts { + attempt := tx.TxAttempts[i] if attempt.State != types.TxAttemptBroadcast { continue } if !foundNewest { - newestAttempt = attempt + newestAttempt = &attempt foundNewest = true } - oldestAttempt = attempt + oldestAttempt = &attempt broadcastedCount++ } return @@ -270,6 +288,10 @@ type scrollResponse struct { Data map[string]int `json:"data"` } +type zircuitResponse struct { + IsQuarantined bool `json:"isQuarantined"` +} + // Uses the custom Scroll skipped endpoint to determine an overflow transaction func (d *stuckTxDetector) detectStuckTransactionsScroll(ctx context.Context, txs []Tx) ([]Tx, error) { if d.cfg.DetectionApiUrl() == nil { @@ -336,6 +358,84 @@ func (d *stuckTxDetector) detectStuckTransactionsScroll(ctx context.Context, txs return stuckTx, nil } +// return fraud and overflow transactions +func (d *stuckTxDetector) detectStuckTransactionsZircuit(ctx context.Context, txs []Tx, blockNum int64) ([]Tx, error) { + var err error + var fraudTxs, stuckTxs []Tx + fraudTxs, err = d.detectFraudTransactionsZircuit(ctx, txs) + if err != nil { + d.lggr.Errorf("Failed to detect zircuit fraud transactions: %v", err) + } + + stuckTxs, err = d.detectStuckTransactionsHeuristic(ctx, txs, blockNum) + if err != nil { + return txs, err + } + + // prevent duplicate transactions from the fraudTxs and stuckTxs with a map + uniqueTxs := make(map[int64]Tx) + for _, tx := range fraudTxs { + uniqueTxs[tx.ID] = tx + } + + for _, tx := range stuckTxs { + uniqueTxs[tx.ID] = tx + } + + var combinedStuckTxs []Tx + for _, tx := range uniqueTxs { + combinedStuckTxs = append(combinedStuckTxs, tx) + } + + return combinedStuckTxs, nil +} + +// Uses zirc_isQuarantined to check whether the transactions are considered as malicious by the sequencer and +// preventing their inclusion into a block +func (d *stuckTxDetector) detectFraudTransactionsZircuit(ctx context.Context, txs []Tx) ([]Tx, error) { + txReqs := make([]rpc.BatchElem, len(txs)) + txHashMap := make(map[common.Hash]Tx) + txRes := make([]*zircuitResponse, len(txs)) + + // Build batch request elems to perform + for i, tx := range txs { + latestAttemptHash := tx.TxAttempts[0].Hash + var result zircuitResponse + txReqs[i] = rpc.BatchElem{ + Method: "zirc_isQuarantined", + Args: []interface{}{ + latestAttemptHash, + }, + Result: &result, + } + txHashMap[latestAttemptHash] = tx + txRes[i] = &result + } + + // Send batch request + err := d.chainClient.BatchCallContext(ctx, txReqs) + if err != nil { + return nil, fmt.Errorf("failed to check Quarantine transactions in batch: %w", err) + } + + // If the result is not nil, the fraud transaction is flagged as quarantined + var fraudTxs []Tx + for i, req := range txReqs { + txHash := req.Args[0].(common.Hash) + if req.Error != nil { + d.lggr.Errorf("failed to check fraud transaction by hash (%s): %v", txHash.String(), req.Error) + continue + } + + result := txRes[i] + if result != nil && result.IsQuarantined { + tx := txHashMap[txHash] + fraudTxs = append(fraudTxs, tx) + } + } + return fraudTxs, nil +} + // Uses eth_getTransactionByHash to detect that a transaction has been discarded due to overflow // Currently only used by zkEVM but if other chains follow the same behavior in the future func (d *stuckTxDetector) detectStuckTransactionsZkEVM(ctx context.Context, txs []Tx) ([]Tx, error) { @@ -390,7 +490,7 @@ func (d *stuckTxDetector) detectStuckTransactionsZkEVM(ctx context.Context, txs for i, req := range txReqs { txHash := req.Args[0].(common.Hash) if req.Error != nil { - d.lggr.Debugf("failed to get transaction by hash (%s): %v", txHash.String(), req.Error) + d.lggr.Errorf("failed to get transaction by hash (%s): %v", txHash.String(), req.Error) continue } result := *txRes[i] @@ -409,7 +509,6 @@ func (d *stuckTxDetector) SetPurgeBlockNum(fromAddress common.Address, blockNum d.purgeBlockNumMap[fromAddress] = blockNum } -func (d *stuckTxDetector) StuckTxFatalError() *string { - errorMsg := client.TerminallyStuckMsg - return &errorMsg +func (d *stuckTxDetector) StuckTxFatalError() string { + return client.TerminallyStuckMsg } diff --git a/core/chains/evm/txmgr/stuck_tx_detector_test.go b/core/chains/evm/txmgr/stuck_tx_detector_test.go index def49f8e113..c6a0f5a7a41 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector_test.go +++ b/core/chains/evm/txmgr/stuck_tx_detector_test.go @@ -72,8 +72,8 @@ func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) feeEstimator := gasmocks.NewEvmFeeEstimator(t) marketGasPrice := assets.GWei(15) - fee := gas.EvmFee{Legacy: marketGasPrice} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) + fee := gas.EvmFee{GasPrice: marketGasPrice} + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) autoPurgeCfg := testAutoPurgeConfig{ @@ -160,7 +160,7 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - attempt.TxFee.Legacy = assets.NewWeiI(2) + attempt.TxFee.GasPrice = assets.NewWeiI(2) attempt.State = txmgrtypes.TxAttemptInProgress require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) stuckTxs, err := stuckTxDetector.FindUnconfirmedTxWithLowestNonce(ctx, []common.Address{fromAddress}) @@ -172,7 +172,7 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) - attempt.TxFee.Legacy = assets.NewWeiI(2) + attempt.TxFee.GasPrice = assets.NewWeiI(2) attempt.State = txmgrtypes.TxAttemptInsufficientFunds require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) stuckTxs, err := stuckTxDetector.FindUnconfirmedTxWithLowestNonce(ctx, []common.Address{fromAddress}) @@ -193,8 +193,8 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { feeEstimator := gasmocks.NewEvmFeeEstimator(t) // Return 10 gwei as market gas price marketGasPrice := tenGwei - fee := gas.EvmFee{Legacy: marketGasPrice} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) + fee := gas.EvmFee{GasPrice: marketGasPrice} + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) ethClient := testutils.NewEthClientMockWithDefaultChain(t) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) @@ -278,6 +278,117 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { require.NoError(t, err) require.Len(t, txs, 1) }) + + t.Run("detects stuck transaction with empty BroadcastBeforeBlockNum in attempts will be skipped without panic", func(t *testing.T) { + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + enabledAddresses := []common.Address{fromAddress} + mustInsertUnconfirmedTxWithBroadcastAttemptsContainsEmptyBroadcastBeforeBlockNum(t, txStore, 0, fromAddress, autoPurgeMinAttempts, marketGasPrice.Add(oneGwei)) + txs, err := stuckTxDetector.DetectStuckTransactions(ctx, enabledAddresses, blockNum) + require.NoError(t, err) + require.Len(t, txs, 0) + }) +} + +func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ctx := tests.Context(t) + + lggr := logger.Test(t) + feeEstimator := gasmocks.NewEvmFeeEstimator(t) + // Return 10 gwei as market gas price + marketGasPrice := tenGwei + fee := gas.EvmFee{GasPrice: marketGasPrice} + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + autoPurgeThreshold := uint32(5) + autoPurgeMinAttempts := uint32(3) + autoPurgeCfg := testAutoPurgeConfig{ + enabled: true, // Enable auto-purge feature for testing + threshold: &autoPurgeThreshold, + minAttempts: &autoPurgeMinAttempts, + } + blockNum := int64(100) + stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, chaintype.ChainZircuit, assets.NewWei(assets.NewEth(100).ToInt()), autoPurgeCfg, feeEstimator, txStore, ethClient) + + t.Run("returns empty list if no fraud or stuck transactions identified", func(t *testing.T) { + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, blockNum, tenGwei) + attempts := tx.TxAttempts[0] + // Request still returns transaction by hash, transaction not discarded by network and not considered stuck + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + resp, err := json.Marshal(struct { + IsQuarantined bool `json:"isQuarantined"` + }{IsQuarantined: false}) + require.NoError(t, err) + elems[0].Error = json.Unmarshal(resp, elems[0].Result) + }).Once() + + txs, err := stuckTxDetector.DetectStuckTransactions(ctx, []common.Address{fromAddress}, blockNum) + require.NoError(t, err) + require.Len(t, txs, 0) + }) + + t.Run("returns fraud transactions identified", func(t *testing.T) { + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, blockNum, tenGwei) + attempts := tx.TxAttempts[0] + // Request still returns transaction by hash, transaction not discarded by network and not considered stuck + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + resp, err := json.Marshal(struct { + IsQuarantined bool `json:"isQuarantined"` + }{IsQuarantined: true}) + require.NoError(t, err) + elems[0].Error = json.Unmarshal(resp, elems[0].Result) + }).Once() + + txs, err := stuckTxDetector.DetectStuckTransactions(ctx, []common.Address{fromAddress}, blockNum) + require.NoError(t, err) + require.Len(t, txs, 1) + }) + + t.Run("returns the transaction only once if it's identified as both fraud and stuck", func(t *testing.T) { + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, autoPurgeMinAttempts, blockNum-int64(autoPurgeThreshold)+int64(autoPurgeMinAttempts-1), marketGasPrice.Add(oneGwei)) + attempts := tx.TxAttempts[0] + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + resp, err := json.Marshal(struct { + IsQuarantined bool `json:"isQuarantined"` + }{IsQuarantined: true}) + require.NoError(t, err) + elems[0].Error = json.Unmarshal(resp, elems[0].Result) + }).Once() + + txs, err := stuckTxDetector.DetectStuckTransactions(ctx, []common.Address{fromAddress}, blockNum) + require.NoError(t, err) + require.Len(t, txs, 1) + }) + t.Run("returns the stuck tx even if failed to detect fraud tx", func(t *testing.T) { + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + tx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, autoPurgeMinAttempts, blockNum-int64(autoPurgeThreshold)+int64(autoPurgeMinAttempts-1), marketGasPrice.Add(oneGwei)) + attempts := tx.TxAttempts[0] + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + })).Return(fmt.Errorf("failed to fetch rpc")) + + txs, err := stuckTxDetector.DetectStuckTransactions(ctx, []common.Address{fromAddress}, blockNum) + require.NoError(t, err) + require.Len(t, txs, 1) + }) } func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) { @@ -350,7 +461,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) { _, fromAddress1 := cltest.MustInsertRandomKey(t, ethKeyStore) etx1 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress1, 1, blockNum, tenGwei) attempt := cltest.NewLegacyEthTxAttempt(t, etx1.ID) - attempt.TxFee.Legacy = assets.NewWeiI(2) + attempt.TxFee.GasPrice = assets.NewWeiI(2) attempt.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -427,7 +538,24 @@ func mustInsertUnconfirmedTxWithBroadcastAttempts(t *testing.T, txStore txmgr.Te attempt.State = txmgrtypes.TxAttemptBroadcast attempt.BroadcastBeforeBlockNum = &blockNum - attempt.TxFee = gas.EvmFee{Legacy: latestGasPrice.Sub(assets.NewWeiI(i))} + attempt.TxFee = gas.EvmFee{GasPrice: latestGasPrice.Sub(assets.NewWeiI(i))} + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + } + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + return etx +} + +// helper function for edge case where broadcast attempt contains empty pointer +func mustInsertUnconfirmedTxWithBroadcastAttemptsContainsEmptyBroadcastBeforeBlockNum(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, numAttempts uint32, latestGasPrice *assets.Wei) txmgr.Tx { + ctx := tests.Context(t) + etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) + // Insert attempts from oldest to newest + for i := int64(numAttempts - 1); i >= 0; i-- { + attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt.State = txmgrtypes.TxAttemptBroadcast + attempt.BroadcastBeforeBlockNum = nil + attempt.TxFee = gas.EvmFee{GasPrice: latestGasPrice.Sub(assets.NewWeiI(i))} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) } etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go index 8d208744329..960d921e879 100644 --- a/core/chains/evm/txmgr/test_helpers.go +++ b/core/chains/evm/txmgr/test_helpers.go @@ -10,6 +10,8 @@ import ( "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" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/config" ) @@ -72,10 +74,32 @@ type TestGasEstimatorConfig struct { bumpThreshold uint64 } +func (g *TestGasEstimatorConfig) DAOracle() evmconfig.DAOracle { + return &TestDAOracleConfig{} +} + +type TestDAOracleConfig struct { + evmconfig.DAOracle +} + +func (d *TestDAOracleConfig) OracleType() toml.DAOracleType { return toml.DAOracleOPStack } +func (d *TestDAOracleConfig) OracleAddress() *types.EIP55Address { + a, err := types.NewEIP55Address("0x420000000000000000000000000000000000000F") + if err != nil { + panic(err) + } + return &a +} +func (d *TestDAOracleConfig) CustomGasPriceCalldata() string { return "" } + func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory { return &TestBlockHistoryConfig{} } +func (g *TestGasEstimatorConfig) FeeHistory() evmconfig.FeeHistory { + return &TestFeeHistoryConfig{} +} + func (g *TestGasEstimatorConfig) EIP1559DynamicFees() bool { return false } func (g *TestGasEstimatorConfig) LimitDefault() uint64 { return 42 } func (g *TestGasEstimatorConfig) BumpPercent() uint16 { return 42 } @@ -92,6 +116,7 @@ func (g *TestGasEstimatorConfig) LimitTransfer() uint64 { return 42 } func (g *TestGasEstimatorConfig) PriceMax() *assets.Wei { return assets.NewWeiI(42) } func (g *TestGasEstimatorConfig) PriceMin() *assets.Wei { return assets.NewWeiI(42) } func (g *TestGasEstimatorConfig) Mode() string { return "FixedPrice" } +func (g *TestGasEstimatorConfig) EstimateLimit() bool { return false } func (g *TestGasEstimatorConfig) LimitJobType() evmconfig.LimitJobType { return &TestLimitJobTypeConfig{} } @@ -123,6 +148,12 @@ func (b *TestBlockHistoryConfig) BlockHistorySize() uint16 { return 42 func (b *TestBlockHistoryConfig) EIP1559FeeCapBufferBlocks() uint16 { return 42 } func (b *TestBlockHistoryConfig) TransactionPercentile() uint16 { return 42 } +type TestFeeHistoryConfig struct { + evmconfig.FeeHistory +} + +func (b *TestFeeHistoryConfig) CacheTimeout() time.Duration { return 0 * time.Second } + type transactionsConfig struct { evmconfig.Transactions e *TestEvmConfig diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index d4bfbffd12f..c47ca85737b 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -101,7 +101,7 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore) require.NoError(t, err) @@ -127,7 +127,7 @@ func TestTxm_CreateTransaction(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth()) require.NoError(t, err) @@ -409,7 +409,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), etKeyStore) require.NoError(t, err) @@ -501,13 +501,13 @@ func TestTxm_Lifecycle(t *testing.T) { head := cltest.Head(42) finalizedHead := cltest.Head(0) - ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() - ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(finalizedHead, nil).Once() + ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil) + ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(finalizedHead, nil) keyChangeCh := make(chan struct{}) unsub := cltest.NewAwaiter() kst.On("SubscribeToKeyChanges", mock.Anything).Return(keyChangeCh, unsub.ItHappened) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst) require.NoError(t, err) @@ -562,7 +562,7 @@ func TestTxm_Reset(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, addr).Return(uint64(128), nil).Maybe() ethClient.On("PendingNonceAt", mock.Anything, addr2).Return(uint64(44), nil).Maybe() - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, cfg.EVM(), cfg.EVM().GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, cfg.EVM().ChainType(), cfg.EVM().GasEstimator()) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), gcfg.Database(), gcfg.Database().Listener(), kst.Eth()) require.NoError(t, err) @@ -613,20 +613,21 @@ func TestTxm_GetTransactionStatus(t *testing.T) { gcfg := configtest.NewTestGeneralConfig(t) cfg := evmtest.NewChainScopedConfig(t, gcfg) + h99 := &evmtypes.Head{ + Hash: utils.NewHash(), + Number: 99, + } + h99.IsFinalized.Store(true) head := &evmtypes.Head{ Hash: utils.NewHash(), Number: 100, - Parent: &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 99, - IsFinalized: true, - }, } + head.Parent.Store(h99) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() - ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head.Parent, nil).Once() + ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head.Parent.Load(), nil).Once() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil) feeEstimator := gasmocks.NewEvmFeeEstimator(t) feeEstimator.On("Start", mock.Anything).Return(nil).Once() @@ -755,7 +756,7 @@ func TestTxm_GetTransactionStatus(t *testing.T) { err = txStore.InsertTxAttempt(ctx, &attempt) require.NoError(t, err) // Insert receipt for finalized block num - mustInsertEthReceipt(t, txStore, head.Parent.Number, head.Parent.Hash, attempt.Hash) + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, head.Parent.Load().Hash, attempt.Hash) state, err := txm.GetTransactionStatus(ctx, idempotencyKey) require.NoError(t, err) require.Equal(t, commontypes.Finalized, state) diff --git a/core/chains/evm/types/head_test.go b/core/chains/evm/types/head_test.go index 97c536a3444..5d887c43c82 100644 --- a/core/chains/evm/types/head_test.go +++ b/core/chains/evm/types/head_test.go @@ -9,6 +9,11 @@ import ( func TestHead_LatestFinalizedHead(t *testing.T) { t.Parallel() + newFinalizedHead := func(num int64) *Head { + result := &Head{Number: num} + result.IsFinalized.Store(true) + return result + } cases := []struct { Name string Head *Head @@ -21,17 +26,17 @@ func TestHead_LatestFinalizedHead(t *testing.T) { }, { Name: "Chain without finalized returns nil", - Head: &Head{Parent: &Head{Parent: &Head{}}}, + Head: sliceToChain(&Head{}, &Head{}, &Head{}), Finalized: nil, }, { Name: "Returns head if it's finalized", - Head: &Head{Number: 2, IsFinalized: true, Parent: &Head{Number: 1, IsFinalized: true}}, + Head: sliceToChain(newFinalizedHead(2), newFinalizedHead(1)), Finalized: &Head{Number: 2}, }, { Name: "Returns first block in chain if it's finalized", - Head: &Head{Number: 3, IsFinalized: false, Parent: &Head{Number: 2, IsFinalized: true, Parent: &Head{Number: 1, IsFinalized: true}}}, + Head: sliceToChain(&Head{Number: 3}, newFinalizedHead(2), newFinalizedHead(1)), Finalized: &Head{Number: 2}, }, } @@ -48,3 +53,43 @@ func TestHead_LatestFinalizedHead(t *testing.T) { }) } } + +func TestHead_ChainString(t *testing.T) { + cases := []struct { + Name string + Chain *Head + ExpectedResult string + }{ + { + Name: "Empty chain", + ExpectedResult: "->nil", + }, + { + Name: "Single head", + Chain: &Head{Number: 1}, + ExpectedResult: "Head{Number: 1, Hash: 0x0000000000000000000000000000000000000000000000000000000000000000, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000000}->nil", + }, + { + Name: "Multiple heads", + Chain: sliceToChain(&Head{Number: 1}, &Head{Number: 2}, &Head{Number: 3}), + ExpectedResult: "Head{Number: 1, Hash: 0x0000000000000000000000000000000000000000000000000000000000000000, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000000}->Head{Number: 2, Hash: 0x0000000000000000000000000000000000000000000000000000000000000000, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000000}->Head{Number: 3, Hash: 0x0000000000000000000000000000000000000000000000000000000000000000, ParentHash: 0x0000000000000000000000000000000000000000000000000000000000000000}->nil", + }, + } + for _, testCase := range cases { + t.Run(testCase.Name, func(t *testing.T) { + assert.Equal(t, testCase.ExpectedResult, testCase.Chain.ChainString()) + }) + } +} + +func sliceToChain(heads ...*Head) *Head { + if len(heads) == 0 { + return nil + } + + for i := 1; i < len(heads); i++ { + heads[i-1].Parent.Store(heads[i]) + } + + return heads[0] +} diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index a9e5cd5841b..1da8754cec4 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -9,6 +9,7 @@ import ( "math/big" "regexp" "strings" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" @@ -34,7 +35,7 @@ type Head struct { Number int64 L1BlockNumber sql.NullInt64 ParentHash common.Hash - Parent *Head + Parent atomic.Pointer[Head] EVMChainID *ubig.Big Timestamp time.Time CreatedAt time.Time @@ -44,7 +45,7 @@ type Head struct { StateRoot common.Hash Difficulty *big.Int TotalDifficulty *big.Int - IsFinalized bool + IsFinalized atomic.Bool } var _ commontypes.Head[common.Hash] = &Head{} @@ -74,10 +75,11 @@ func (h *Head) GetParentHash() common.Hash { } func (h *Head) GetParent() commontypes.Head[common.Hash] { - if h.Parent == nil { - return nil + if parent := h.Parent.Load(); parent != nil { + return parent } - return h.Parent + // explicitly return nil to avoid *Head(nil) + return nil } func (h *Head) GetTimestamp() time.Time { @@ -90,10 +92,11 @@ func (h *Head) BlockDifficulty() *big.Int { // EarliestInChain recurses through parents until it finds the earliest one func (h *Head) EarliestInChain() *Head { - for h.Parent != nil { - h = h.Parent + var earliestInChain *Head + for cur := h; cur != nil; cur = cur.Parent.Load() { + earliestInChain = cur } - return h + return earliestInChain } // EarliestHeadInChain recurses through parents until it finds the earliest one @@ -103,14 +106,10 @@ func (h *Head) EarliestHeadInChain() commontypes.Head[common.Hash] { // IsInChain returns true if the given hash matches the hash of a head in the chain func (h *Head) IsInChain(blockHash common.Hash) bool { - for { - if h.Hash == blockHash { + for cur := h; cur != nil; cur = cur.Parent.Load() { + if cur.Hash == blockHash { return true } - if h.Parent == nil { - break - } - h = h.Parent } return false } @@ -127,32 +126,19 @@ func (h *Head) HashAtHeight(blockNum int64) common.Hash { } func (h *Head) HeadAtHeight(blockNum int64) (commontypes.Head[common.Hash], error) { - for h != nil { - if h.Number == blockNum { - return h, nil + for cur := h; cur != nil; cur = cur.Parent.Load() { + if cur.Number == blockNum { + return cur, nil } - - h = h.Parent } return nil, fmt.Errorf("failed to find head at height %d", blockNum) } // ChainLength returns the length of the chain followed by recursively looking up parents func (h *Head) ChainLength() uint32 { - if h == nil { - return 0 - } - l := uint32(1) - - for { - if h.Parent == nil { - break - } + l := uint32(0) + for cur := h; cur != nil; cur = cur.Parent.Load() { l++ - if h == h.Parent { - panic("circular reference detected") - } - h = h.Parent } return l } @@ -160,29 +146,19 @@ func (h *Head) ChainLength() uint32 { // ChainHashes returns an array of block hashes by recursively looking up parents func (h *Head) ChainHashes() []common.Hash { var hashes []common.Hash - - for { - hashes = append(hashes, h.Hash) - if h.Parent == nil { - break - } - if h == h.Parent { - panic("circular reference detected") - } - h = h.Parent + for cur := h; cur != nil; cur = cur.Parent.Load() { + hashes = append(hashes, cur.Hash) } + return hashes } func (h *Head) LatestFinalizedHead() commontypes.Head[common.Hash] { - for h != nil { - if h.IsFinalized { - return h + for cur := h; cur != nil; cur = cur.Parent.Load() { + if cur.IsFinalized.Load() { + return cur } - - h = h.Parent } - return nil } @@ -200,18 +176,13 @@ func (h *Head) IsValid() bool { func (h *Head) ChainString() string { var sb strings.Builder - - for { - sb.WriteString(h.String()) - if h.Parent == nil { - break - } - if h == h.Parent { - panic("circular reference detected") + for cur := h; cur != nil; cur = cur.Parent.Load() { + if sb.Len() > 0 { + sb.WriteString("->") } - sb.WriteString("->") - h = h.Parent + sb.WriteString(cur.String()) } + sb.WriteString("->nil") return sb.String() } @@ -255,11 +226,11 @@ func (h *Head) AsSlice(k int) (heads []*Head) { if k < 1 || h == nil { return } - heads = make([]*Head, 1) - heads[0] = h - for len(heads) < k && h.Parent != nil { - h = h.Parent - heads = append(heads, h) + heads = make([]*Head, 0, k) + for cur := h; cur != nil; cur = cur.Parent.Load() { + if len(heads) < k { + heads = append(heads, cur) + } } return } diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go index 6018d68f962..a54f1f58f5b 100644 --- a/core/chains/evm/types/models_test.go +++ b/core/chains/evm/types/models_test.go @@ -116,11 +116,9 @@ func TestEthTxAttempt_GetSignedTx(t *testing.T) { } func TestHead_ChainLength(t *testing.T) { - head := evmtypes.Head{ - Parent: &evmtypes.Head{ - Parent: &evmtypes.Head{}, - }, - } + head := evmtypes.Head{} + head.Parent.Store(&evmtypes.Head{}) + head.Parent.Load().Parent.Store(&evmtypes.Head{}) assert.Equal(t, uint32(3), head.ChainLength()) @@ -134,12 +132,12 @@ func TestHead_AsSlice(t *testing.T) { } h2 := &evmtypes.Head{ Number: 2, - Parent: h1, } + h2.Parent.Store(h1) h3 := &evmtypes.Head{ Number: 3, - Parent: h2, } + h3.Parent.Store(h2) assert.Len(t, (*evmtypes.Head)(nil).AsSlice(0), 0) assert.Len(t, (*evmtypes.Head)(nil).AsSlice(1), 0) @@ -234,36 +232,35 @@ func TestSafeByteSlice_Error(t *testing.T) { } func TestHead_EarliestInChain(t *testing.T) { - head := evmtypes.Head{ + h3 := evmtypes.Head{ Number: 3, - Parent: &evmtypes.Head{ - Number: 2, - Parent: &evmtypes.Head{ - Number: 1, - }, - }, } + h2 := &evmtypes.Head{Number: 2} + h3.Parent.Store(h2) + h1 := &evmtypes.Head{Number: 1} + h2.Parent.Store(h1) - assert.Equal(t, int64(1), head.EarliestInChain().BlockNumber()) + assert.Equal(t, int64(1), h3.EarliestInChain().BlockNumber()) } func TestHead_HeadAtHeight(t *testing.T) { - expectedResult := &evmtypes.Head{ + h1 := &evmtypes.Head{ + Number: 1, + } + h2 := &evmtypes.Head{ Hash: common.BigToHash(big.NewInt(10)), Number: 2, - Parent: &evmtypes.Head{ - Number: 1, - }, } - head := evmtypes.Head{ + h2.Parent.Store(h1) + h3 := evmtypes.Head{ Number: 3, - Parent: expectedResult, } + h3.Parent.Store(h2) - headAtHeight, err := head.HeadAtHeight(2) + headAtHeight, err := h3.HeadAtHeight(2) require.NoError(t, err) - assert.Equal(t, expectedResult, headAtHeight) - _, err = head.HeadAtHeight(0) + assert.Equal(t, h2, headAtHeight) + _, err = h3.HeadAtHeight(0) assert.Error(t, err, "expected to get an error if head is not in the chain") } @@ -271,25 +268,27 @@ func TestHead_IsInChain(t *testing.T) { hash1 := utils.NewHash() hash2 := utils.NewHash() hash3 := utils.NewHash() - - head := evmtypes.Head{ - Number: 3, + h1 := &evmtypes.Head{ + Number: 1, + Hash: hash1, + } + h2 := &evmtypes.Head{ + Hash: hash2, + ParentHash: hash1, + Number: 2, + } + h2.Parent.Store(h1) + h3 := evmtypes.Head{ Hash: hash3, - Parent: &evmtypes.Head{ - Hash: hash2, - Number: 2, - Parent: &evmtypes.Head{ - Hash: hash1, - Number: 1, - }, - }, + Number: 3, } + h3.Parent.Store(h2) - assert.True(t, head.IsInChain(hash1)) - assert.True(t, head.IsInChain(hash2)) - assert.True(t, head.IsInChain(hash3)) - assert.False(t, head.IsInChain(utils.NewHash())) - assert.False(t, head.IsInChain(common.Hash{})) + assert.True(t, h3.IsInChain(hash1)) + assert.True(t, h3.IsInChain(hash2)) + assert.True(t, h3.IsInChain(hash3)) + assert.False(t, h3.IsInChain(utils.NewHash())) + assert.False(t, h3.IsInChain(common.Hash{})) } func TestTxReceipt_ReceiptIndicatesRunLogFulfillment(t *testing.T) { @@ -316,11 +315,11 @@ func TestHead_UnmarshalJSON(t *testing.T) { tests := []struct { name string json string - expected evmtypes.Head + expected *evmtypes.Head }{ {"geth", `{"difficulty":"0xf3a00","extraData":"0xd883010503846765746887676f312e372e318664617277696e","gasLimit":"0xffc001","gasUsed":"0x0","hash":"0x41800b5c3f1717687d85fc9018faac0a6e90b39deaa0b99e7fe4fe796ddeb26a","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0xd1aeb42885a43b72b518182ef893125814811048","mixHash":"0x0f98b15f1a4901a7e9204f3c500a7bd527b3fb2c3340e12176a44b83e414a69e","nonce":"0x0ece08ea8c49dfd9","number":"0x100","parentHash":"0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x218","stateRoot":"0xc7b01007a10da045eacb90385887dd0c38fcb5db7393006bdde24b93873c334b","timestamp":"0x58318da2","totalDifficulty":"0x1f3a00","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]}`, - evmtypes.Head{ + &evmtypes.Head{ Hash: common.HexToHash("0x41800b5c3f1717687d85fc9018faac0a6e90b39deaa0b99e7fe4fe796ddeb26a"), Number: 0x100, ParentHash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"), @@ -332,7 +331,7 @@ func TestHead_UnmarshalJSON(t *testing.T) { }, {"parity", `{"author":"0xd1aeb42885a43b72b518182ef893125814811048","difficulty":"0xf3a00","extraData":"0xd883010503846765746887676f312e372e318664617277696e","gasLimit":"0xffc001","gasUsed":"0x0","hash":"0x41800b5c3f1717687d85fc9018faac0a6e90b39deaa0b99e7fe4fe796ddeb26a","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0xd1aeb42885a43b72b518182ef893125814811048","mixHash":"0x0f98b15f1a4901a7e9204f3c500a7bd527b3fb2c3340e12176a44b83e414a69e","nonce":"0x0ece08ea8c49dfd9","number":"0x100","parentHash":"0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":["0xa00f98b15f1a4901a7e9204f3c500a7bd527b3fb2c3340e12176a44b83e414a69e","0x880ece08ea8c49dfd9"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x218","stateRoot":"0xc7b01007a10da045eacb90385887dd0c38fcb5db7393006bdde24b93873c334b","timestamp":"0x58318da2","totalDifficulty":"0x1f3a00","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]}`, - evmtypes.Head{ + &evmtypes.Head{ Hash: common.HexToHash("0x41800b5c3f1717687d85fc9018faac0a6e90b39deaa0b99e7fe4fe796ddeb26a"), Number: 0x100, ParentHash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"), @@ -344,7 +343,7 @@ func TestHead_UnmarshalJSON(t *testing.T) { }, {"arbitrum", `{"number":"0x15156","hash":"0x752dab43f7a2482db39227d46cd307623b26167841e2207e93e7566ab7ab7871","parentHash":"0x923ad1e27c1d43cb2d2fb09e26d2502ca4b4914a2e0599161d279c6c06117d34","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x71448077f5ce420a8e24db62d4d58e8d8e6ad2c7e76318868e089d41f7e0faf3","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x2c292672b8fc9d223647a2569e19721f0757c96a1421753a93e141f8e56cf504","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x0","gasLimit":"0x11278208","gasUsed":"0x3d1fe9","timestamp":"0x60d0952d","transactions":["0xa1ea93556b93ed3b45cb24f21c8deb584e6a9049c35209242651bf3533c23b98","0xfc6593c45ba92351d17173aa1381e84734d252ab0169887783039212c4a41024","0x85ee9d04fd0ebb5f62191eeb53cb45d9c0945d43eba444c3548de2ac8421682f","0x50d120936473e5b75f6e04829ad4eeca7a1df7d3c5026ebb5d34af936a39b29c"],"uncles":[],"l1BlockNumber":"0x8652f9"}`, - evmtypes.Head{ + &evmtypes.Head{ Hash: common.HexToHash("0x752dab43f7a2482db39227d46cd307623b26167841e2207e93e7566ab7ab7871"), Number: 0x15156, ParentHash: common.HexToHash("0x923ad1e27c1d43cb2d2fb09e26d2502ca4b4914a2e0599161d279c6c06117d34"), @@ -357,7 +356,7 @@ func TestHead_UnmarshalJSON(t *testing.T) { }, {"arbitrum_empty_l1BlockNumber", `{"number":"0x15156","hash":"0x752dab43f7a2482db39227d46cd307623b26167841e2207e93e7566ab7ab7871","parentHash":"0x923ad1e27c1d43cb2d2fb09e26d2502ca4b4914a2e0599161d279c6c06117d34","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x71448077f5ce420a8e24db62d4d58e8d8e6ad2c7e76318868e089d41f7e0faf3","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x2c292672b8fc9d223647a2569e19721f0757c96a1421753a93e141f8e56cf504","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x0","gasLimit":"0x11278208","gasUsed":"0x3d1fe9","timestamp":"0x60d0952d","transactions":["0xa1ea93556b93ed3b45cb24f21c8deb584e6a9049c35209242651bf3533c23b98","0xfc6593c45ba92351d17173aa1381e84734d252ab0169887783039212c4a41024","0x85ee9d04fd0ebb5f62191eeb53cb45d9c0945d43eba444c3548de2ac8421682f","0x50d120936473e5b75f6e04829ad4eeca7a1df7d3c5026ebb5d34af936a39b29c"],"uncles":[]}`, - evmtypes.Head{ + &evmtypes.Head{ Hash: common.HexToHash("0x752dab43f7a2482db39227d46cd307623b26167841e2207e93e7566ab7ab7871"), Number: 0x15156, ParentHash: common.HexToHash("0x923ad1e27c1d43cb2d2fb09e26d2502ca4b4914a2e0599161d279c6c06117d34"), @@ -370,7 +369,7 @@ func TestHead_UnmarshalJSON(t *testing.T) { }, {"not found", `null`, - evmtypes.Head{}, + &evmtypes.Head{}, }, } @@ -395,11 +394,11 @@ func TestHead_UnmarshalJSON(t *testing.T) { func TestHead_MarshalJSON(t *testing.T) { tests := []struct { name string - head evmtypes.Head + head *evmtypes.Head expected string }{ {"happy", - evmtypes.Head{ + &evmtypes.Head{ Hash: common.HexToHash("0x41800b5c3f1717687d85fc9018faac0a6e90b39deaa0b99e7fe4fe796ddeb26a"), Number: 0x100, ParentHash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"), @@ -411,7 +410,7 @@ func TestHead_MarshalJSON(t *testing.T) { `{"hash":"0x41800b5c3f1717687d85fc9018faac0a6e90b39deaa0b99e7fe4fe796ddeb26a","number":"0x100","parentHash":"0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d","timestamp":"0x58318da2","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0xc7b01007a10da045eacb90385887dd0c38fcb5db7393006bdde24b93873c334b"}`, }, {"empty", - evmtypes.Head{}, + &evmtypes.Head{}, `{"number":"0x0"}`, }, } diff --git a/core/chains/evm/utils/big/big.go b/core/chains/evm/utils/big/big.go index 4bb51e27323..5706fda45b6 100644 --- a/core/chains/evm/utils/big/big.go +++ b/core/chains/evm/utils/big/big.go @@ -188,3 +188,8 @@ func (b *Big) Sub(c *Big) *Big { func (b *Big) Mod(c *Big) *Big { return New(bigmath.Mod(b.ToInt(), c.ToInt())) } + +// IsZero returns true if b is zero +func (b *Big) IsZero() bool { + return b.ToInt().Sign() == 0 +} diff --git a/core/chains/evm/utils/utils_test.go b/core/chains/evm/utils/utils_test.go index 829cd314a61..5798726f2dc 100644 --- a/core/chains/evm/utils/utils_test.go +++ b/core/chains/evm/utils/utils_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/multierr" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -211,6 +212,7 @@ func TestRetryWithBackoff(t *testing.T) { var counter atomic.Int32 ctx, cancel := context.WithCancel(tests.Context(t)) + defer cancel() utils.RetryWithBackoff(ctx, func() bool { return false @@ -222,7 +224,7 @@ func TestRetryWithBackoff(t *testing.T) { go utils.RetryWithBackoff(ctx, retry) - assert.Eventually(t, func() bool { + require.Eventually(t, func() bool { return counter.Load() == 3 }, tests.WaitTimeout(t), tests.TestInterval) diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 68ff8d4e111..277d6283690 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math/big" + "strconv" gotoml "github.com/pelletier/go-toml/v2" "go.uber.org/multierr" @@ -130,27 +131,12 @@ type AppConfig interface { toml.HasEVMConfigs } -type ChainRelayExtenderConfig struct { +type ChainRelayOpts struct { Logger logger.Logger KeyStore keystore.Eth ChainOpts } -func (c ChainRelayExtenderConfig) Validate() error { - err := c.ChainOpts.Validate() - if c.Logger == nil { - err = errors.Join(err, errors.New("nil Logger")) - } - if c.KeyStore == nil { - err = errors.Join(err, errors.New("nil Keystore")) - } - - if err != nil { - err = fmt.Errorf("invalid ChainRelayerExtenderConfig: %w", err) - } - return err -} - type ChainOpts struct { AppConfig AppConfig @@ -187,7 +173,7 @@ func (o ChainOpts) Validate() error { return err } -func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayExtenderConfig) (Chain, error) { +func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayOpts) (Chain, error) { err := opts.Validate() if err != nil { return nil, err @@ -202,14 +188,18 @@ func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayExt return newChain(ctx, cfg, chain.Nodes, opts) } -func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Node, opts ChainRelayExtenderConfig) (*chain, error) { +func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Node, opts ChainRelayOpts) (*chain, error) { chainID := cfg.EVM().ChainID() l := opts.Logger var client evmclient.Client if !opts.AppConfig.EVMRPCEnabled() { client = evmclient.NewNullClient(chainID, l) } else if opts.GenEthClient == nil { - client = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), cfg.EVM().NodePool().Errors(), l, chainID, nodes, cfg.EVM().ChainType()) + 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 + } } else { client = opts.GenEthClient(chainID) } @@ -220,7 +210,12 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { headTracker = headtracker.NullTracker } else if opts.GenHeadTracker == nil { - orm := headtracker.NewORM(*chainID, opts.DS) + var orm headtracker.ORM + if cfg.EVM().HeadTracker().PersistenceEnabled() { + orm = headtracker.NewORM(*chainID, opts.DS) + } else { + orm = headtracker.NewNullORM() + } headSaver = headtracker.NewHeadSaver(l, orm, cfg.EVM(), cfg.EVM().HeadTracker()) headTracker = headtracker.NewHeadTracker(l, client, cfg.EVM(), cfg.EVM().HeadTracker(), headBroadcaster, headSaver, opts.MailMon) } else { @@ -241,6 +236,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod KeepFinalizedBlocksDepth: int64(cfg.EVM().LogKeepBlocksDepth()), LogPrunePageSize: int64(cfg.EVM().LogPrunePageSize()), BackupPollerBlockDelay: int64(cfg.EVM().BackupLogPollerBlockDelay()), + ClientErrors: cfg.EVM().NodePool().Errors(), } logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DS, l), client, l, headTracker, lpOpts) } @@ -269,6 +265,8 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod var logBroadcaster log.Broadcaster if !opts.AppConfig.EVMRPCEnabled() { logBroadcaster = &log.NullBroadcaster{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} + } else if !cfg.EVM().LogBroadcasterEnabled() { + logBroadcaster = &log.NullBroadcaster{ErrMsg: fmt.Sprintf("LogBroadcaster disabled for chain %d", chainID)} } else if opts.GenLogBroadcaster == nil { logORM := log.NewORM(opts.DS, *chainID) logBroadcaster = log.NewBroadcaster(logORM, client, cfg.EVM(), l, highestSeenHead, opts.MailMon) @@ -390,6 +388,19 @@ func (c *chain) SendTx(ctx context.Context, from, to string, amount *big.Int, ba return c.Transact(ctx, from, to, amount, balanceCheck) } +func (c *chain) LatestHead(_ context.Context) (types.Head, error) { + latestChain := c.headTracker.LatestChain() + if latestChain == nil { + return types.Head{}, errors.New("latest chain not found") + } + + return types.Head{ + Height: strconv.FormatInt(latestChain.BlockNumber(), 10), + Hash: latestChain.Hash.Bytes(), + Timestamp: uint64(latestChain.Timestamp.Unix()), + }, nil +} + func (c *chain) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { toml, err := c.cfg.EVM().TOMLString() if err != nil { @@ -418,7 +429,6 @@ func (c *chain) listNodeStatuses(start, end int) ([]types.NodeStatus, int, error for _, n := range nodes[start:end] { var ( nodeState string - exists bool ) toml, err := gotoml.Marshal(n) if err != nil { @@ -427,10 +437,11 @@ func (c *chain) listNodeStatuses(start, end int) ([]types.NodeStatus, int, error if states == nil { nodeState = "Unknown" } else { - nodeState, exists = states[*n.Name] - if !exists { - // The node is in the DB and the chain is enabled but it's not running - nodeState = "NotLoaded" + // The node is in the DB and the chain is enabled but it's not running + nodeState = "NotLoaded" + s, exists := states[*n.Name] + if exists { + nodeState = s } } stats = append(stats, types.NodeStatus{ diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index ab116749665..ec7098ab56c 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -22,7 +22,7 @@ func newEvmTxm( client evmclient.Client, lggr logger.Logger, logPoller logpoller.LogPoller, - opts ChainRelayExtenderConfig, + opts ChainRelayOpts, headTracker httypes.HeadTracker, ) (txm txmgr.TxManager, estimator gas.EvmFeeEstimator, @@ -45,7 +45,7 @@ func newEvmTxm( // build estimator from factory if opts.GenGasEstimator == nil { - if estimator, err = gas.NewEstimator(lggr, client, cfg, cfg.GasEstimator()); err != nil { + if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), cfg.GasEstimator()); err != nil { return nil, nil, fmt.Errorf("failed to initialize estimator: %w", err) } } else { diff --git a/core/chains/legacyevm/mocks/chain.go b/core/chains/legacyevm/mocks/chain.go index 777212108cf..3c6bd97d7a9 100644 --- a/core/chains/legacyevm/mocks/chain.go +++ b/core/chains/legacyevm/mocks/chain.go @@ -523,6 +523,62 @@ func (_c *Chain_ID_Call) RunAndReturn(run func() *big.Int) *Chain_ID_Call { return _c } +// LatestHead provides a mock function with given fields: ctx +func (_m *Chain) LatestHead(ctx context.Context) (types.Head, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for LatestHead") + } + + var r0 types.Head + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (types.Head, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) types.Head); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(types.Head) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Chain_LatestHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestHead' +type Chain_LatestHead_Call struct { + *mock.Call +} + +// LatestHead is a helper method to define mock.On call +// - ctx context.Context +func (_e *Chain_Expecter) LatestHead(ctx interface{}) *Chain_LatestHead_Call { + return &Chain_LatestHead_Call{Call: _e.mock.On("LatestHead", ctx)} +} + +func (_c *Chain_LatestHead_Call) Run(run func(ctx context.Context)) *Chain_LatestHead_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Chain_LatestHead_Call) Return(_a0 types.Head, _a1 error) *Chain_LatestHead_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Chain_LatestHead_Call) RunAndReturn(run func(context.Context) (types.Head, error)) *Chain_LatestHead_Call { + _c.Call.Return(run) + return _c +} + // ListNodeStatuses provides a mock function with given fields: ctx, pageSize, pageToken func (_m *Chain) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) ([]types.NodeStatus, string, int, error) { ret := _m.Called(ctx, pageSize, pageToken) diff --git a/core/cmd/cosmos_transaction_commands_test.go b/core/cmd/cosmos_transaction_commands_test.go index c3e6a048103..e41aa83a25a 100644 --- a/core/cmd/cosmos_transaction_commands_test.go +++ b/core/cmd/cosmos_transaction_commands_test.go @@ -26,7 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" ) -var nativeToken = "cosm" +const nativeToken = "cosm" func TestMain(m *testing.M) { @@ -40,6 +40,7 @@ func TestMain(m *testing.M) { } func TestShell_SendCosmosCoins(t *testing.T) { + t.Parallel() ctx := testutils.Context(t) // TODO(BCI-978): cleanup once SetupLocalCosmosNode is updated chainID := cosmostest.RandomChainID() @@ -66,7 +67,7 @@ func TestShell_SendCosmosCoins(t *testing.T) { require.NoError(t, err) require.Eventually(t, func() bool { - coin, err := reader.Balance(from.Address, *cosmosChain.GasToken) + coin, err := reader.Balance(ctx, from.Address, *cosmosChain.GasToken) if !assert.NoError(t, err) { return false } @@ -89,7 +90,7 @@ func TestShell_SendCosmosCoins(t *testing.T) { } { tt := tt t.Run(tt.amount, func(t *testing.T) { - startBal, err := reader.Balance(from.Address, *cosmosChain.GasToken) + startBal, err := reader.Balance(ctx, from.Address, *cosmosChain.GasToken) require.NoError(t, err) set := flag.NewFlagSet("sendcosmoscoins", 0) @@ -121,8 +122,8 @@ func TestShell_SendCosmosCoins(t *testing.T) { require.NoError(t, err) expBal := startBal.Sub(sent) - testutils.AssertEventually(t, func() bool { - endBal, err := reader.Balance(from.Address, *cosmosChain.GasToken) + testutils.RequireEventually(t, func() bool { + endBal, err := reader.Balance(ctx, from.Address, *cosmosChain.GasToken) require.NoError(t, err) t.Logf("%s <= %s", endBal, expBal) return endBal.IsLTE(expBal) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index da153f6884b..1b593dccd84 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -15,7 +15,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "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/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -140,7 +139,7 @@ func TestShell_SendEther_From_Txm(t *testing.T) { ethMock := newEthMockWithTransactionsOnBlocksAssertions(t) ethMock.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) - ethMock.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil).Maybe() + ethMock.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() ethMock.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -204,7 +203,7 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { ethMock := newEthMockWithTransactionsOnBlocksAssertions(t) ethMock.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) - ethMock.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil).Maybe() + ethMock.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() ethMock.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { diff --git a/core/cmd/forwarders_commands_test.go b/core/cmd/forwarders_commands_test.go index b5a96a73aa8..dfd8272d8a4 100644 --- a/core/cmd/forwarders_commands_test.go +++ b/core/cmd/forwarders_commands_test.go @@ -22,7 +22,7 @@ func TestEVMForwarderPresenter_RenderTable(t *testing.T) { t.Parallel() var ( - id = "1" + id = "ID:" address = utils.RandomAddress() evmChainID = big.NewI(4) createdAt = time.Now() diff --git a/core/cmd/prompter.go b/core/cmd/prompter.go index 84f930c6243..a5e67c5692e 100644 --- a/core/cmd/prompter.go +++ b/core/cmd/prompter.go @@ -92,5 +92,5 @@ func withTerminalResetter(f func()) { } func clearLine() { - fmt.Printf("\r" + strings.Repeat(" ", 60) + "\r") + fmt.Print("\r" + strings.Repeat(" ", 60) + "\r") } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 5c864b82cd0..59514d3a1fc 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -23,14 +23,16 @@ import ( "github.com/Masterminds/semver/v3" "github.com/getsentry/sentry-go" "github.com/gin-gonic/gin" + "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/urfave/cli" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" "go.uber.org/multierr" "go.uber.org/zap/zapcore" "golang.org/x/sync/errgroup" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/beholder" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" @@ -43,6 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/llo" "github.com/smartcontractkit/chainlink/v2/core/services/periodicbackup" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" @@ -63,19 +66,59 @@ var ( grpcOpts loop.GRPCOpts ) -func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, logger logger.Logger) error { +func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTelemetry config.Telemetry, lggr logger.Logger) error { // Avoid double initializations, but does not prevent relay methods from being called multiple times. var err error initGlobalsOnce.Do(func() { - prometheus = ginprom.New(ginprom.Namespace("service"), ginprom.Token(cfgProm.AuthToken())) - grpcOpts = loop.NewGRPCOpts(nil) // default prometheus.Registerer - err = loop.SetupTracing(loop.TracingConfig{ - Enabled: cfgTracing.Enabled(), - CollectorTarget: cfgTracing.CollectorTarget(), - NodeAttributes: cfgTracing.Attributes(), - SamplingRatio: cfgTracing.SamplingRatio(), - OnDialError: func(error) { logger.Errorw("Failed to dial", "err", err) }, - }) + err = func() error { + prometheus = ginprom.New(ginprom.Namespace("service"), ginprom.Token(cfgProm.AuthToken())) + grpcOpts = loop.NewGRPCOpts(nil) // default prometheus.Registerer + + otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { + lggr.Errorw("Telemetry error", "err", err) + })) + + tracingCfg := loop.TracingConfig{ + Enabled: cfgTracing.Enabled(), + CollectorTarget: cfgTracing.CollectorTarget(), + NodeAttributes: cfgTracing.Attributes(), + SamplingRatio: cfgTracing.SamplingRatio(), + TLSCertPath: cfgTracing.TLSCertPath(), + OnDialError: func(error) { lggr.Errorw("Failed to dial", "err", err) }, + } + if !cfgTelemetry.Enabled() { + return loop.SetupTracing(tracingCfg) + } + + var attributes []attribute.KeyValue + if tracingCfg.Enabled { + attributes = tracingCfg.Attributes() + } + for k, v := range cfgTelemetry.ResourceAttributes() { + attributes = append(attributes, attribute.String(k, v)) + } + clientCfg := beholder.Config{ + InsecureConnection: cfgTelemetry.InsecureConnection(), + CACertFile: cfgTelemetry.CACertFile(), + OtelExporterGRPCEndpoint: cfgTelemetry.OtelExporterGRPCEndpoint(), + ResourceAttributes: attributes, + TraceSampleRatio: cfgTelemetry.TraceSampleRatio(), + } + if tracingCfg.Enabled { + clientCfg.TraceSpanExporter, err = tracingCfg.NewSpanExporter() + if err != nil { + return err + } + } + var beholderClient *beholder.Client + beholderClient, err = beholder.NewClient(clientCfg) + if err != nil { + return err + } + beholder.SetClient(beholderClient) + beholder.SetGlobalOtelProviders() + return nil + }() }) return err } @@ -138,7 +181,7 @@ type ChainlinkAppFactory struct{} // NewApplication returns a new instance of the node with the given config. func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB) (app chainlink.Application, err error) { - err = initGlobals(cfg.Prometheus(), cfg.Tracing(), appLggr) + err = initGlobals(cfg.Prometheus(), cfg.Tracing(), cfg.Telemetry(), appLggr) if err != nil { appLggr.Errorf("Failed to initialize globals: %v", err) } @@ -158,7 +201,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G keyStore := keystore.New(ds, utils.GetScryptParams(cfg), appLggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), appLggr.Named("Mailbox")) - loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing()) + loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing(), cfg.Telemetry()) mercuryPool := wsrpc.NewPool(appLggr, cache.Config{ LatestReportTTL: cfg.Mercury().Cache().LatestReportTTL(), @@ -168,13 +211,18 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G capabilitiesRegistry := capabilities.NewRegistry(appLggr) + retirementReportCache := llo.NewRetirementReportCache(appLggr, ds) + + unrestrictedClient := clhttp.NewUnrestrictedHTTPClient() // create the relayer-chain interoperators from application configuration relayerFactory := chainlink.RelayerFactory{ - Logger: appLggr, - LoopRegistry: loopRegistry, - GRPCOpts: grpcOpts, - MercuryPool: mercuryPool, - CapabilitiesRegistry: capabilitiesRegistry, + Logger: appLggr, + LoopRegistry: loopRegistry, + GRPCOpts: grpcOpts, + MercuryPool: mercuryPool, + CapabilitiesRegistry: capabilitiesRegistry, + HTTPClient: unrestrictedClient, + RetirementReportCache: retirementReportCache, } evmFactoryCfg := chainlink.EVMFactoryConfig{ @@ -228,7 +276,6 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } restrictedClient := clhttp.NewRestrictedHTTPClient(cfg.Database(), appLggr) - unrestrictedClient := clhttp.NewUnrestrictedHTTPClient() externalInitiatorManager := webhook.NewExternalInitiatorManager(ds, unrestrictedClient) return chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, @@ -246,6 +293,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G LoopRegistry: loopRegistry, GRPCOpts: grpcOpts, MercuryPool: mercuryPool, + RetirementReportCache: retirementReportCache, CapabilitiesRegistry: capabilitiesRegistry, }) } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 604daf75683..0a3ab13113f 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -6,6 +6,7 @@ import ( "database/sql" "fmt" "log" + "math" "math/big" "net/http" "net/url" @@ -22,9 +23,8 @@ import ( gethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/fatih/color" - "github.com/lib/pq" - "github.com/kylelemons/godebug/diff" + "github.com/lib/pq" "github.com/pkg/errors" "github.com/urfave/cli" "go.uber.org/multierr" @@ -684,8 +684,11 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { for i := int64(0); i < totalNonces; i++ { nonces[i] = evmtypes.Nonce(beginningNonce + i) } - err = ec.ForceRebroadcast(ctx, nonces, gas.EvmFee{Legacy: assets.NewWeiI(int64(gasPriceWei))}, address, uint64(overrideGasLimit)) - return s.errorOut(err) + if gasPriceWei <= math.MaxInt64 { + //nolint:gosec // disable G115 + return s.errorOut(ec.ForceRebroadcast(ctx, nonces, gas.EvmFee{GasPrice: assets.NewWeiI(int64(gasPriceWei))}, address, uint64(overrideGasLimit))) + } + return s.errorOut(fmt.Errorf("integer overflow conversion error. GasPrice: %v", gasPriceWei)) } type HealthCheckPresenter struct { diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 8ed48dcaa20..79d2b9f07a6 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -11,13 +11,13 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "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" cmdMocks "github.com/smartcontractkit/chainlink/v2/core/cmd/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -32,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" "github.com/smartcontractkit/chainlink/v2/plugins" gethTypes "github.com/ethereum/go-ethereum/core/types" @@ -42,10 +43,10 @@ import ( "github.com/urfave/cli" ) -func genTestEVMRelayers(t *testing.T, opts legacyevm.ChainRelayExtenderConfig, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators { +func genTestEVMRelayers(t *testing.T, opts legacyevm.ChainRelayOpts, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators { f := chainlink.RelayerFactory{ Logger: opts.Logger, - LoopRegistry: plugins.NewLoopRegistry(opts.Logger, opts.AppConfig.Tracing()), + LoopRegistry: plugins.NewLoopRegistry(opts.Logger, opts.AppConfig.Tracing(), opts.AppConfig.Telemetry()), CapabilitiesRegistry: capabilities.NewRegistry(opts.Logger), } @@ -86,7 +87,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { lggr := logger.TestLogger(t) - opts := legacyevm.ChainRelayExtenderConfig{ + opts := legacyevm.ChainRelayOpts{ Logger: lggr, KeyStore: keyStore.Eth(), ChainOpts: legacyevm.ChainOpts{ @@ -190,7 +191,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(10), nil).Maybe() lggr := logger.TestLogger(t) - opts := legacyevm.ChainRelayExtenderConfig{ + opts := legacyevm.ChainRelayOpts{ Logger: lggr, KeyStore: keyStore.Eth(), ChainOpts: legacyevm.ChainOpts{ diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index 6ecdc4a34de..a93be2fb9ea 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -351,7 +351,7 @@ func TestNewUserCache(t *testing.T) { func TestSetupSolanaRelayer(t *testing.T) { lggr := logger.TestLogger(t) - reg := plugins.NewLoopRegistry(lggr, nil) + reg := plugins.NewLoopRegistry(lggr, nil, nil) ks := mocks.NewSolana(t) // config 3 chains but only enable 2 => should only be 2 relayer @@ -466,7 +466,7 @@ func TestSetupSolanaRelayer(t *testing.T) { func TestSetupStarkNetRelayer(t *testing.T) { lggr := logger.TestLogger(t) - reg := plugins.NewLoopRegistry(lggr, nil) + reg := plugins.NewLoopRegistry(lggr, nil, nil) ks := mocks.NewStarkNet(t) // config 3 chains but only enable 2 => should only be 2 relayer nEnabledChains := 2 diff --git a/core/cmd/solana_node_commands_test.go b/core/cmd/solana_node_commands_test.go index adc699de79b..bc4aa15f7bc 100644 --- a/core/cmd/solana_node_commands_test.go +++ b/core/cmd/solana_node_commands_test.go @@ -20,7 +20,7 @@ import ( func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { for i := range cfgs { - cfgs[i].SetDefaults() + cfgs[i].Chain.SetDefaults() } return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Solana = cfgs @@ -72,17 +72,17 @@ func TestShell_IndexSolanaNodes(t *testing.T) { rt := cmd.RendererTable{b} require.NoError(t, nodes.RenderTable(rt)) renderLines := strings.Split(b.String(), "\n") - assert.Equal(t, 17, len(renderLines)) + assert.Equal(t, 19, len(renderLines)) assert.Contains(t, renderLines[2], "Name") assert.Contains(t, renderLines[2], n1.Name) assert.Contains(t, renderLines[3], "Chain ID") assert.Contains(t, renderLines[3], n1.ChainID) assert.Contains(t, renderLines[4], "State") assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[9], "Name") - assert.Contains(t, renderLines[9], n2.Name) - assert.Contains(t, renderLines[10], "Chain ID") - assert.Contains(t, renderLines[10], n2.ChainID) - assert.Contains(t, renderLines[11], "State") - assert.Contains(t, renderLines[11], n2.State) + assert.Contains(t, renderLines[10], "Name") + assert.Contains(t, renderLines[10], n2.Name) + assert.Contains(t, renderLines[11], "Chain ID") + assert.Contains(t, renderLines[11], n2.ChainID) + assert.Contains(t, renderLines[12], "State") + assert.Contains(t, renderLines[12], n2.State) } diff --git a/core/cmd/solana_transaction_commands_test.go b/core/cmd/solana_transaction_commands_test.go index 79a5513f190..1f0e1b0525d 100644 --- a/core/cmd/solana_transaction_commands_test.go +++ b/core/cmd/solana_transaction_commands_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/cmd" ) +// TODO: move this test to `chainlink-solana` https://smartcontract-it.atlassian.net/browse/NONEVM-790 func TestShell_SolanaSendSol(t *testing.T) { ctx := testutils.Context(t) chainID := "localnet" diff --git a/core/config/app_config.go b/core/config/app_config.go index 112e242636f..4cb7f1f610c 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -56,6 +56,7 @@ type AppConfig interface { Threshold() Threshold WebServer() WebServer Tracing() Tracing + Telemetry() Telemetry } type DatabaseBackupMode string diff --git a/core/config/capabilities_config.go b/core/config/capabilities_config.go index ae542c062c5..b7e5a3b86a7 100644 --- a/core/config/capabilities_config.go +++ b/core/config/capabilities_config.go @@ -11,7 +11,24 @@ type CapabilitiesExternalRegistry interface { RelayID() types.RelayID } +type GatewayConnector interface { + ChainIDForNodeKey() string + NodeAddress() string + DonID() string + Gateways() []ConnectorGateway + WSHandshakeTimeoutMillis() uint32 + AuthMinChallengeLen() int + AuthTimestampToleranceSec() uint32 +} + +type ConnectorGateway interface { + ID() string + URL() string +} + type Capabilities interface { Peering() P2P + Dispatcher() Dispatcher ExternalRegistry() CapabilitiesExternalRegistry + GatewayConnector() GatewayConnector } diff --git a/core/config/dispatcher_config.go b/core/config/dispatcher_config.go new file mode 100644 index 00000000000..ec6f13e8f4a --- /dev/null +++ b/core/config/dispatcher_config.go @@ -0,0 +1,14 @@ +package config + +type DispatcherRateLimit interface { + GlobalRPS() float64 + GlobalBurst() int + PerSenderRPS() float64 + PerSenderBurst() int +} + +type Dispatcher interface { + SupportedVersion() int + ReceiverBufferSize() int + RateLimit() DispatcherRateLimit +} diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index 444804b3826..7d0de98acea 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -97,6 +97,8 @@ RPCBlockQueryDelay = 1 # Default # Block 64 will be treated as finalized by CL Node only when chain's latest finalized block is 65. As chain finalizes blocks in batches of 32, # CL Node has to wait for a whole new batch to be finalized to treat block 64 as finalized. FinalizedBlockOffset = 0 # Default +# LogBroadcasterEnabled is a feature flag for LogBroadcaster, by default it's true. +LogBroadcasterEnabled = true # Default # NoNewFinalizedHeadsThreshold controls how long to wait for new finalized block before `NodePool` marks rpc endpoints as # out-of-sync. Only applicable if `FinalityTagEnabled=true` # @@ -193,6 +195,8 @@ LimitMax = 500_000 # Default LimitMultiplier = '1.0' # Default # LimitTransfer is the gas limit used for an ordinary ETH transfer. LimitTransfer = 21_000 # Default +# EstimateLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. +EstimateLimit = false # Default # BumpMin is the minimum fixed amount of wei by which gas is bumped on each transaction attempt. BumpMin = '5 gwei' # Default # BumpPercent is the percentage by which to bump gas on a transaction that has exceeded `BumpThreshold`. The larger of `BumpPercent` and `BumpMin` is taken for gas bumps. @@ -259,6 +263,14 @@ TipCapDefault = '1 wei' # Default # (Only applies to EIP-1559 transactions) TipCapMin = '1 wei' # Default +[EVM.GasEstimator.DAOracle] +# OracleType refers to the oracle family this config belongs to. Currently the available oracle types are: 'opstack', 'arbitrum', 'zksync', and 'custom_calldata'. +OracleType = 'opstack' # Example +# OracleAddress is the address of the oracle contract. +OracleAddress = '0x420000000000000000000000000000000000000F' # Example +# CustomGasPriceCalldata is optional and can be set to call a custom gas price function at the given OracleAddress. +CustomGasPriceCalldata = '' # Default + [EVM.GasEstimator.LimitJobType] # OCR overrides LimitDefault for OCR jobs. OCR = 100_000 # Example @@ -309,6 +321,15 @@ EIP1559FeeCapBufferBlocks = 13 # Example # Setting it lower will tend to set lower gas prices. TransactionPercentile = 60 # Default +[EVM.GasEstimator.FeeHistory] +# CacheTimeout is the time to wait in order to refresh the cached values stored in the FeeHistory estimator. A small jitter is applied so the timeout won't be exactly the same each time. +# +# You want this value to be close to the block time. For slower chains, like Ethereum, you can set it to 12s, the same as the block time. For faster chains you can skip a block or two +# and set it to two times the block time i.e. on Optimism you can set it to 4s. Ideally, you don't want to go lower than 1s since the RTT times of the RPC requests will be comparable to +# the timeout. The estimator is already adding a buffer to account for a potential increase in prices within one or two blocks. On the other hand, slower frequency will fail to refresh +# the prices and end up in stale values. +CacheTimeout = '10s' # Default + # The head tracker continually listens for new heads from the chain. # # In addition to these settings, it log warnings if `EVM.NoNewHeadsThreshold` is exceeded without any new blocks being emitted. @@ -334,6 +355,11 @@ FinalityTagBypass = true # Default # If actual finality depth exceeds this number, HeadTracker aborts backfill and returns an error. # Has no effect if `FinalityTagsEnabled` = false MaxAllowedFinalityDepth = 10000 # Default +# PersistenceEnabled defines whether HeadTracker needs to store heads in the database. +# Persistence is helpful on chains with large finality depth, where fetching blocks from the latest to the latest finalized takes a lot of time. +# On chains with fast finality, the persistence layer does not improve the chain's load time and only consumes database resources (mainly IO). +# NOTE: persistence should not be disabled for products that use LogBroadcaster, as it might lead to missed on-chain events. +PersistenceEnabled = true # Default [[EVM.KeySpecific]] # Key is the account to apply these settings to @@ -396,6 +422,10 @@ EnforceRepeatableRead = false # Default # trigger declaration of `FinalizedBlockOutOfSync` due to insignificant network delays in broadcasting of the finalized state among RPCs. # RPC will not be picked to handle a request even if this option is set to a nonzero value. DeathDeclarationDelay = '10s' # Default +# NewHeadsPollInterval define an interval for polling new block periodically using http client rather than subscribe to ws feed +# +# Set to 0 to disable. +NewHeadsPollInterval = '0s' # Default # **ADVANCED** # Errors enable the node to provide custom regex patterns to match against error messages from RPCs. [EVM.NodePool.Errors] @@ -427,6 +457,8 @@ TransactionAlreadyMined = '(: |^)transaction already mined' # Example Fatal = '(: |^)fatal' # Example # ServiceUnavailable is a regex pattern to match against service unavailable errors. ServiceUnavailable = '(: |^)service unavailable' # Example +# TooManyResults is a regex pattern to match an eth_getLogs error indicating the result set is too large to return +TooManyResults = '(: |^)too many results' # Example [EVM.OCR] # ContractConfirmations sets `OCR.ContractConfirmations` for this EVM chain. @@ -449,7 +481,7 @@ ObservationGracePeriod = '1s' # Default [[EVM.Nodes]] # Name is a unique (per-chain) identifier for this node. Name = 'foo' # Example -# WSURL is the WS(S) endpoint for this node. Required for primary nodes. +# WSURL is the WS(S) endpoint for this node. Required for primary nodes when `LogBroadcasterEnabled` is `true` WSURL = 'wss://web.socket/test' # Example # HTTPURL is the HTTP(S) endpoint for this node. Required for all nodes. HTTPURL = 'https://foo.web' # Example @@ -467,3 +499,5 @@ GasLimit = 5400000 # Default FromAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example # ForwarderAddress is the keystone forwarder contract address on chain. ForwarderAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example +# GasLimitDefault is the default gas limit for workflow transactions. +GasLimitDefault = 400_000 # Default diff --git a/core/config/docs/chains-solana.toml b/core/config/docs/chains-solana.toml index 9376445061a..626c2f0613f 100644 --- a/core/config/docs/chains-solana.toml +++ b/core/config/docs/chains-solana.toml @@ -36,9 +36,47 @@ ComputeUnitPriceDefault = 0 # Default FeeBumpPeriod = '3s' # Default # BlockHistoryPollPeriod is the rate to poll for blocks in the block history fee estimator BlockHistoryPollPeriod = '5s' # Default +# ComputeUnitLimitDefault is the compute units limit applied to transactions unless overriden during the txm enqueue +ComputeUnitLimitDefault = 200_000 # Default +# EstimateComputeUnitLimit enables or disables compute unit limit estimations per transaction. If estimations return 0 used compute, the ComputeUnitLimitDefault value is used, if set. +EstimateComputeUnitLimit = false # Default + +[Solana.MultiNode] +# Enabled enables the multinode feature. +Enabled = false # Default +# PollFailureThreshold is the number of consecutive poll failures before a node is considered unhealthy. +PollFailureThreshold = 5 # Default +# PollInterval is the rate to poll for node health. +PollInterval = '10s' # Default +# SelectionMode is the method used to select the next best node to use. +SelectionMode = 'PriorityLevel' # Default +# SyncThreshold is the number of blocks behind the best node that a node can be before it is considered out of sync. +SyncThreshold = 5 # Default +# NodeIsSyncingEnabled enables the feature to avoid sending transactions to nodes that are syncing. Not relavant for Solana. +NodeIsSyncingEnabled = false # Default +# LeaseDuration is the max duration a node can be leased for. +LeaseDuration = '1m0s' # Default +# FinalizedBlockPollInterval is the rate to poll for the finalized block. +FinalizedBlockPollInterval = '10s' # Default +# EnforceRepeatableRead enforces the repeatable read guarantee for multinode. +EnforceRepeatableRead = true # Default +# DeathDeclarationDelay is the duration to wait before declaring a node dead. +DeathDeclarationDelay = '10s' # Default +# NodeNoNewHeadsThreshold is the duration to wait before declaring a node unhealthy due to no new heads. +NodeNoNewHeadsThreshold = '10s' # Default +# NoNewFinalizedHeadsThreshold is the duration to wait before declaring a node unhealthy due to no new finalized heads. +NoNewFinalizedHeadsThreshold = '10s' # Default +# FinalityDepth is not used when finality tags are enabled. +FinalityDepth = 0 # Default +# FinalityTagEnabled enables the use of finality tags. +FinalityTagEnabled = true # Default +# FinalizedBlockOffset is the offset from the finalized block to use for finality tags. +FinalizedBlockOffset = 0 # Default [[Solana.Nodes]] # Name is a unique (per-chain) identifier for this node. Name = 'primary' # Example # URL is the HTTP(S) endpoint for this node. URL = 'http://solana.web' # Example +# SendOnly is a multinode config that only sends transactions to a node and does not read state +SendOnly = false # Default diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index d0960779c6c..dde898ed3b1 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -15,6 +15,8 @@ LogPoller = false # Default UICSAKeys = false # Default # CCIP enables the CCIP service. CCIP = true # Default +# MultiFeedsManagers enables support for multiple feeds manager connections. +MultiFeedsManagers = false # Default [Database] # DefaultIdleInTxSessionTimeout is the maximum time allowed for a transaction to be open and idle before timing out. See Postgres `idle_in_transaction_session_timeout` for more details. @@ -87,7 +89,7 @@ LeaseRefreshInterval = '1s' # Default [TelemetryIngress] # UniConn toggles which ws connection style is used. -UniConn = true # Default +UniConn = false # Default # Logging toggles verbose logging of the raw telemetry messages being sent. Logging = false # Default # BufferSize is the number of telemetry messages to buffer before dropping new ones. @@ -450,6 +452,22 @@ NetworkID = 'evm' # Default # ChainID identifies the target chain id where the remote registry is located. ChainID = '1' # Default +[Capabilities.Dispatcher] +# SupportedVersion is the version of the version of message schema. +SupportedVersion = 1 # Default +# ReceiverBufferSize is the size of the buffer for incoming messages. +ReceiverBufferSize = 10000 # Default + +[Capabilities.Dispatcher.RateLimit] +# GlobalRPS is the global rate limit for the dispatcher. +GlobalRPS = 800 # Default +# GlobalBurst is the global burst limit for the dispatcher. +GlobalBurst = 1000 # Default +# PerSenderRPS is the per-sender rate limit for the dispatcher. +PerSenderRPS = 10 # Default +# PerSenderBurst is the per-sender burst limit for the dispatcher. +PerSenderBurst = 50 # Default + [Capabilities.Peering] # IncomingMessageBufferSize is the per-remote number of incoming # messages to buffer. Any additional messages received on top of those @@ -491,6 +509,26 @@ DeltaReconcile = '1m' # Default # but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example +[Capabilities.GatewayConnector] +# ChainIDForNodeKey is the ChainID of the network associated with a private key to be used for authentication with Gateway nodes +ChainIDForNodeKey = '11155111' # Example +# NodeAddress is the address of the desired private key to be used for authentication with Gateway nodes +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' # Example +# DonID is the Id of the Don +DonID = 'example_don' # Example +# WSHandshakeTimeoutMillis is Websocket handshake timeout +WSHandshakeTimeoutMillis = 1000 # Example +# AuthMinChallengeLen is the minimum number of bytes in authentication challenge payload +AuthMinChallengeLen = 10 # Example +# AuthTimestampToleranceSec is Authentication timestamp tolerance +AuthTimestampToleranceSec = 10 # Example + +[[Capabilities.GatewayConnector.Gateways]] +# ID of the Gateway +ID = 'example_gateway' # Example +# URL of the Gateway +URL = 'wss://localhost:8081/node' # Example + [Keeper] # **ADVANCED** # DefaultTransactionQueueDepth controls the queue size for `DropOldestStrategy` in Keeper. Set to 0 to use `SendEvery` strategy instead. @@ -651,3 +689,25 @@ TransmitQueueMaxSize = 10_000 # Default # when sending a message to the mercury server, before aborting and considering # the transmission to be failed. TransmitTimeout = "5s" # Default + +# Telemetry holds OTEL settings. +# This data includes open telemetry metrics, traces, & logs. +# It does not currently include prometheus metrics or standard out logs, but may in the future. +[Telemetry] +# Enabled turns telemetry collection on or off. +Enabled = false # Default +# Endpoint of the OTEL Collector. +Endpoint = 'example.com/collector' # Example +# CACertFile is the file path of the TLS certificate used for secure communication with the OTEL Collector. +# Required unless InescureConnection is true. +CACertFile = 'cert-file' # Example +# InsecureConnection bypasses the TLS CACertFile requirement and uses an insecure connection instead. +# Only available in dev mode. +InsecureConnection = false # Default +# TraceSampleRatio is the rate at which to sample traces. Must be between 0 and 1. +TraceSampleRatio = 0.01 # Default + +# ResourceAttributes are global metadata to include with all telemetry. +[Telemetry.ResourceAttributes] +# foo is an example resource attribute +foo = "bar" # Example diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go index 8f46497cb5f..bb572773c4a 100644 --- a/core/config/docs/docs_test.go +++ b/core/config/docs/docs_test.go @@ -15,6 +15,7 @@ import ( stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" @@ -83,8 +84,12 @@ func TestDoc(t *testing.T) { docDefaults.OperatorFactoryAddress = nil require.Empty(t, docDefaults.Workflow.FromAddress) require.Empty(t, docDefaults.Workflow.ForwarderAddress) + gasLimitDefault := uint64(400_000) + require.Equal(t, &gasLimitDefault, docDefaults.Workflow.GasLimitDefault) + docDefaults.Workflow.FromAddress = nil docDefaults.Workflow.ForwarderAddress = nil + docDefaults.Workflow.GasLimitDefault = &gasLimitDefault docDefaults.NodePool.Errors = evmcfg.ClientErrors{} // Transactions.AutoPurge configs are only set if the feature is enabled @@ -92,6 +97,9 @@ func TestDoc(t *testing.T) { docDefaults.Transactions.AutoPurge.Threshold = nil docDefaults.Transactions.AutoPurge.MinAttempts = nil + // GasEstimator.DAOracle.OracleAddress is only set if DA oracle config is used + docDefaults.GasEstimator.DAOracle.OracleAddress = nil + assertTOML(t, fallbackDefaults, docDefaults) }) diff --git a/core/config/env/env.go b/core/config/env/env.go index 0ebfc357bf3..c34cd7f4f5e 100644 --- a/core/config/env/env.go +++ b/core/config/env/env.go @@ -20,6 +20,7 @@ var ( ThresholdKeyShare = Secret("CL_THRESHOLD_KEY_SHARE") // Migrations env vars EVMChainIDNotNullMigration0195 = "CL_EVM_CHAINID_NOT_NULL_MIGRATION_0195" + CustomDefaults = Var("CL_CHAIN_DEFAULTS") ) // LOOPP commands and vars diff --git a/core/config/feature_config.go b/core/config/feature_config.go index fbb3a4ea541..200a1fd8ed8 100644 --- a/core/config/feature_config.go +++ b/core/config/feature_config.go @@ -4,4 +4,5 @@ type Feature interface { FeedsManager() bool UICSAKeys() bool LogPoller() bool + MultiFeedsManagers() bool } diff --git a/core/config/telemetry_config.go b/core/config/telemetry_config.go new file mode 100644 index 00000000000..5440e70b43b --- /dev/null +++ b/core/config/telemetry_config.go @@ -0,0 +1,10 @@ +package config + +type Telemetry interface { + Enabled() bool + InsecureConnection() bool + CACertFile() string + OtelExporterGRPCEndpoint() string + ResourceAttributes() map[string]string + TraceSampleRatio() float64 +} diff --git a/core/config/toml/types.go b/core/config/toml/types.go index 0c91ddd81a9..497e33d5ddd 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "net/url" + "reflect" "regexp" "strings" @@ -25,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" + configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) @@ -57,6 +59,7 @@ type Core struct { Tracing Tracing `toml:",omitempty"` Mercury Mercury `toml:",omitempty"` Capabilities Capabilities `toml:",omitempty"` + Telemetry Telemetry `toml:",omitempty"` } // SetFrom updates c with any non-nil values from f. (currently TOML field only!) @@ -93,11 +96,12 @@ func (c *Core) SetFrom(f *Core) { c.Sentry.setFrom(&f.Sentry) c.Insecure.setFrom(&f.Insecure) c.Tracing.setFrom(&f.Tracing) + c.Telemetry.setFrom(&f.Telemetry) } func (c *Core) ValidateConfig() (err error) { _, verr := parse.HomeDir(*c.RootDir) - if err != nil { + if verr != nil { err = multierr.Append(err, configutils.ErrInvalid{Name: "RootDir", Value: true, Msg: fmt.Sprintf("Failed to expand RootDir. Please use an explicit path: %s", verr)}) } @@ -105,6 +109,12 @@ func (c *Core) ValidateConfig() (err error) { err = multierr.Append(err, configutils.ErrInvalid{Name: "P2P.V2.Enabled", Value: false, Msg: "P2P required for OCR or OCR2. Please enable P2P or disable OCR/OCR2."}) } + if *c.Tracing.Enabled && *c.Telemetry.Enabled { + if c.Tracing.CollectorTarget == c.Telemetry.Endpoint { + err = multierr.Append(err, configutils.ErrInvalid{Name: "Tracing.CollectorTarget", Value: *c.Tracing.CollectorTarget, Msg: "Same as Telemetry.Endpoint. Must be different or disabled."}) + } + } + return err } @@ -300,10 +310,11 @@ func (p *PrometheusSecrets) validateMerge(f *PrometheusSecrets) (err error) { } type Feature struct { - FeedsManager *bool - LogPoller *bool - UICSAKeys *bool - CCIP *bool + FeedsManager *bool + LogPoller *bool + UICSAKeys *bool + CCIP *bool + MultiFeedsManagers *bool } func (f *Feature) setFrom(f2 *Feature) { @@ -319,6 +330,9 @@ func (f *Feature) setFrom(f2 *Feature) { if v := f2.CCIP; v != nil { f.CCIP = v } + if v := f2.MultiFeedsManagers; v != nil { + f.MultiFeedsManagers = v + } } type Database struct { @@ -1434,14 +1448,103 @@ func (r *ExternalRegistry) setFrom(f *ExternalRegistry) { } } +type Dispatcher struct { + SupportedVersion *int + ReceiverBufferSize *int + RateLimit DispatcherRateLimit +} + +func (d *Dispatcher) setFrom(f *Dispatcher) { + d.RateLimit.setFrom(&f.RateLimit) + + if f.ReceiverBufferSize != nil { + d.ReceiverBufferSize = f.ReceiverBufferSize + } + + if f.SupportedVersion != nil { + d.SupportedVersion = f.SupportedVersion + } +} + +type DispatcherRateLimit struct { + GlobalRPS *float64 + GlobalBurst *int + PerSenderRPS *float64 + PerSenderBurst *int +} + +func (drl *DispatcherRateLimit) setFrom(f *DispatcherRateLimit) { + if f.GlobalRPS != nil { + drl.GlobalRPS = f.GlobalRPS + } + if f.GlobalBurst != nil { + drl.GlobalBurst = f.GlobalBurst + } + if f.PerSenderRPS != nil { + drl.PerSenderRPS = f.PerSenderRPS + } + if f.PerSenderBurst != nil { + drl.PerSenderBurst = f.PerSenderBurst + } +} + +type GatewayConnector struct { + ChainIDForNodeKey *string + NodeAddress *string + DonID *string + Gateways []ConnectorGateway + WSHandshakeTimeoutMillis *uint32 + AuthMinChallengeLen *int + AuthTimestampToleranceSec *uint32 +} + +func (r *GatewayConnector) setFrom(f *GatewayConnector) { + if f.ChainIDForNodeKey != nil { + r.ChainIDForNodeKey = f.ChainIDForNodeKey + } + + if f.NodeAddress != nil { + r.NodeAddress = f.NodeAddress + } + + if f.DonID != nil { + r.DonID = f.DonID + } + + if f.Gateways != nil { + r.Gateways = f.Gateways + } + + if !reflect.ValueOf(f.WSHandshakeTimeoutMillis).IsZero() { + r.WSHandshakeTimeoutMillis = f.WSHandshakeTimeoutMillis + } + + if f.AuthMinChallengeLen != nil { + r.AuthMinChallengeLen = f.AuthMinChallengeLen + } + + if f.AuthTimestampToleranceSec != nil { + r.AuthTimestampToleranceSec = f.AuthTimestampToleranceSec + } +} + +type ConnectorGateway struct { + ID *string + URL *string +} + type Capabilities struct { Peering P2P `toml:",omitempty"` + Dispatcher Dispatcher `toml:",omitempty"` ExternalRegistry ExternalRegistry `toml:",omitempty"` + GatewayConnector GatewayConnector `toml:",omitempty"` } func (c *Capabilities) setFrom(f *Capabilities) { c.Peering.setFrom(&f.Peering) c.ExternalRegistry.setFrom(&f.ExternalRegistry) + c.Dispatcher.setFrom(&f.Dispatcher) + c.GatewayConnector.setFrom(&f.GatewayConnector) } type ThresholdKeyShareSecrets struct { @@ -1481,25 +1584,25 @@ type Tracing struct { func (t *Tracing) setFrom(f *Tracing) { if v := f.Enabled; v != nil { - t.Enabled = f.Enabled + t.Enabled = v } if v := f.CollectorTarget; v != nil { - t.CollectorTarget = f.CollectorTarget + t.CollectorTarget = v } if v := f.NodeID; v != nil { - t.NodeID = f.NodeID + t.NodeID = v } if v := f.Attributes; v != nil { - t.Attributes = f.Attributes + t.Attributes = v } if v := f.SamplingRatio; v != nil { - t.SamplingRatio = f.SamplingRatio + t.SamplingRatio = v } if v := f.Mode; v != nil { - t.Mode = f.Mode + t.Mode = v } if v := f.TLSCertPath; v != nil { - t.TLSCertPath = f.TLSCertPath + t.TLSCertPath = v } } @@ -1553,6 +1656,59 @@ func (t *Tracing) ValidateConfig() (err error) { return err } +type Telemetry struct { + Enabled *bool + CACertFile *string + Endpoint *string + InsecureConnection *bool + ResourceAttributes map[string]string `toml:",omitempty"` + TraceSampleRatio *float64 +} + +func (b *Telemetry) setFrom(f *Telemetry) { + if v := f.Enabled; v != nil { + b.Enabled = v + } + if v := f.CACertFile; v != nil { + b.CACertFile = v + } + if v := f.Endpoint; v != nil { + b.Endpoint = v + } + if v := f.InsecureConnection; v != nil { + b.InsecureConnection = v + } + if v := f.ResourceAttributes; v != nil { + b.ResourceAttributes = v + } + if v := f.TraceSampleRatio; v != nil { + b.TraceSampleRatio = v + } +} + +func (b *Telemetry) ValidateConfig() (err error) { + if b.Enabled == nil || !*b.Enabled { + return nil + } + if b.Endpoint == nil || *b.Endpoint == "" { + err = multierr.Append(err, configutils.ErrMissing{Name: "Endpoint", Msg: "must be set when Telemetry is enabled"}) + } + if b.InsecureConnection != nil && *b.InsecureConnection { + if build.IsProd() { + err = multierr.Append(err, configutils.ErrInvalid{Name: "InsecureConnection", Value: true, Msg: "cannot be used in production builds"}) + } + } else { + if b.CACertFile == nil || *b.CACertFile == "" { + err = multierr.Append(err, configutils.ErrMissing{Name: "CACertFile", Msg: "must be set, unless InsecureConnection is used"}) + } + } + if ratio := b.TraceSampleRatio; ratio != nil && (*ratio < 0 || *ratio > 1) { + err = multierr.Append(err, configutils.ErrInvalid{Name: "TraceSampleRatio", Value: *ratio, Msg: "must be between 0 and 1"}) + } + + return err +} + var hostnameRegex = regexp.MustCompile(`^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$`) // Validates uri is valid external or local URI diff --git a/core/gethwrappers/ccip/deployment_test/deployment_test.go b/core/gethwrappers/ccip/deployment_test/deployment_test.go new file mode 100644 index 00000000000..02f00483651 --- /dev/null +++ b/core/gethwrappers/ccip/deployment_test/deployment_test.go @@ -0,0 +1,95 @@ +package deploymenttest + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +// This tests ensures that all of the compiled contracts can be +// deployed to an actual blockchain (i.e no "max code size exceeded" errors). +// It does not attempt to correctly set up the contracts, so bogus inputs are used. +func TestDeployAllV1_6(t *testing.T) { + owner := testutils.MustNewSimTransactor(t) + chain := backends.NewSimulatedBackend(core.GenesisAlloc{ + owner.From: {Balance: assets.Ether(100).ToInt()}, + }, 30e6) + + // router + _, _, _, err := router.DeployRouter(owner, chain, common.HexToAddress("0x1"), common.HexToAddress("0x2")) + require.NoError(t, err) + chain.Commit() + + // nonce manager + _, _, _, err = nonce_manager.DeployNonceManager(owner, chain, []common.Address{common.HexToAddress("0x1")}) + require.NoError(t, err) + chain.Commit() + + // offramp + _, _, _, err = offramp.DeployOffRamp(owner, chain, offramp.OffRampStaticConfig{ + ChainSelector: 1, + RmnRemote: common.HexToAddress("0x1"), + TokenAdminRegistry: common.HexToAddress("0x2"), + NonceManager: common.HexToAddress("0x3"), + }, offramp.OffRampDynamicConfig{ + FeeQuoter: common.HexToAddress("0x4"), + PermissionLessExecutionThresholdSeconds: uint32((8 * time.Hour).Seconds()), + MessageInterceptor: common.HexToAddress("0x5"), + }, nil) + require.NoError(t, err) + chain.Commit() + + // onramp + _, _, _, err = onramp.DeployOnRamp(owner, chain, onramp.OnRampStaticConfig{ + ChainSelector: 1, + RmnRemote: common.HexToAddress("0x1"), + NonceManager: common.HexToAddress("0x2"), + TokenAdminRegistry: common.HexToAddress("0x3"), + }, onramp.OnRampDynamicConfig{ + FeeQuoter: common.HexToAddress("0x4"), + MessageInterceptor: common.HexToAddress("0x5"), + FeeAggregator: common.HexToAddress("0x6"), + AllowlistAdmin: common.HexToAddress("0x7"), + }, nil) + require.NoError(t, err) + chain.Commit() + + // fee quoter + _, _, _, err = fee_quoter.DeployFeeQuoter( + owner, + chain, + fee_quoter.FeeQuoterStaticConfig{ + MaxFeeJuelsPerMsg: big.NewInt(1e18), + LinkToken: common.HexToAddress("0x1"), + TokenPriceStalenessThreshold: 10, + }, + []common.Address{common.HexToAddress("0x1")}, + []common.Address{common.HexToAddress("0x2")}, + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{}, + []fee_quoter.FeeQuoterDestChainConfigArgs{}) + require.NoError(t, err) + chain.Commit() + + // token admin registry + _, _, _, err = token_admin_registry.DeployTokenAdminRegistry(owner, chain) + require.NoError(t, err) + chain.Commit() + + // TODO: add rmn home and rmn remote +} 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 28e67b0dff7..1553ba62b05 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 @@ -82,8 +82,8 @@ type TokenPoolChainUpdate struct { } var BurnFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":[],\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b50604051620043d9380380620043d98339810160408190526200003491620008c0565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c2816200018f565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c05262000168576040805160008152602081019091526200016890846200023a565b5062000185925050506001600160a01b0385163060001962000397565b5050505062000afc565b336001600160a01b03821603620001e95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200025b576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002e65760008382815181106200027f576200027f620009d0565b60209081029190910101519050620002996002826200047d565b15620002dc576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200025e565b5060005b8151811015620003925760008282815181106200030b576200030b620009d0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000337575062000389565b620003446002826200049d565b1562000387576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002ea565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040f9190620009e6565b6200041b919062000a16565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047791869190620004b416565b50505050565b600062000494836001600160a01b03841662000585565b90505b92915050565b600062000494836001600160a01b03841662000689565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000503906001600160a01b038516908490620006db565b80519091501562000392578080602001905181019062000524919062000a2c565b620003925760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000086565b600081815260018301602052604081205480156200067e576000620005ac60018362000a57565b8554909150600090620005c29060019062000a57565b90508181146200062e576000866000018281548110620005e657620005e6620009d0565b90600052602060002001549050808760000184815481106200060c576200060c620009d0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000642576200064262000a6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000497565b600091505062000497565b6000818152600183016020526040812054620006d25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000497565b50600062000497565b6060620006ec8484600085620006f4565b949350505050565b606082471015620007575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000086565b600080866001600160a01b0316858760405162000775919062000aa9565b60006040518083038185875af1925050503d8060008114620007b4576040519150601f19603f3d011682016040523d82523d6000602084013e620007b9565b606091505b509092509050620007cd87838387620007d8565b979650505050505050565b606083156200084c57825160000362000844576001600160a01b0385163b620008445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000086565b5081620006ec565b620006ec8383815115620008635781518083602001fd5b8060405162461bcd60e51b815260040162000086919062000ac7565b6001600160a01b03811681146200089557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008bb816200087f565b919050565b60008060008060808587031215620008d757600080fd5b8451620008e4816200087f565b602086810151919550906001600160401b03808211156200090457600080fd5b818801915088601f8301126200091957600080fd5b8151818111156200092e576200092e62000898565b8060051b604051601f19603f8301168101818110858211171562000956576200095662000898565b60405291825284820192508381018501918b8311156200097557600080fd5b938501935b828510156200099e576200098e85620008ae565b845293850193928501926200097a565b809850505050505050620009b560408601620008ae565b9150620009c560608601620008ae565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000497576200049762000a00565b60006020828403121562000a3f57600080fd5b8151801515811462000a5057600080fd5b9392505050565b8181038181111562000497576200049762000a00565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa057818101518382015260200162000a86565b50506000910152565b6000825162000abd81846020870162000a83565b9190910192915050565b602081526000825180602084015262000ae881604085016020870162000a83565b601f01601f19169190910160400192915050565b60805160a05160c05161386062000b79600039600081816104960152818161164501526120290152600081816104700152818161147601526118fb01526000818161022301528181610278015281816106ba015281816113960152818161181b01528181611a1301528181611fbf015261221401526138606000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063a7cd63b7116100e3578063c75eea9c1161008c578063dc0bd97111610066578063dc0bd9711461046e578063e0351e1314610494578063f2fde38b146104ba57600080fd5b8063c75eea9c14610435578063cf7401f314610448578063db6327dc1461045b57600080fd5b8063b7946580116100bd578063b7946580146103fa578063c0d786551461040d578063c4bffe2b1461042057600080fd5b8063a7cd63b714610358578063af58d59f1461036d578063b0f479a1146103dc57600080fd5b806354c8a4f3116101455780638926f54f1161011f5780638926f54f146103075780638da5cb5b1461031a5780639a4575b91461033857600080fd5b806354c8a4f3146102d757806378a010b2146102ec57806379ba5097146102ff57600080fd5b806321df0da71161017657806321df0da714610221578063240028e81461026857806339077537146102b557600080fd5b806301ffc9a71461019d5780630a2fd493146101c5578063181f5a77146101e5575b600080fd5b6101b06101ab3660046129b7565b6104cd565b60405190151581526020015b60405180910390f35b6101d86101d3366004612a16565b6105b2565b6040516101bc9190612a95565b6101d86040518060400160405280601f81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e302d6465760081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b6101b0610276366004612ad5565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102c86102c3366004612af2565b610662565b604051905181526020016101bc565b6102ea6102e5366004612b7a565b6107bd565b005b6102ea6102fa366004612be6565b610838565b6102ea6109ac565b6101b0610315366004612a16565b610aa9565b60005473ffffffffffffffffffffffffffffffffffffffff16610243565b61034b610346366004612c69565b610ac0565b6040516101bc9190612ca4565b610360610b67565b6040516101bc9190612d04565b61038061037b366004612a16565b610b78565b6040516101bc919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610243565b6101d8610408366004612a16565b610c4d565b6102ea61041b366004612ad5565b610c78565b610428610d53565b6040516101bc9190612d5e565b610380610443366004612a16565b610e0b565b6102ea610456366004612ec6565b610edd565b6102ea610469366004612f0b565b610ef5565b7f0000000000000000000000000000000000000000000000000000000000000000610243565b7f00000000000000000000000000000000000000000000000000000000000000006101b0565b6102ea6104c8366004612ad5565b61137b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061056057507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105ac57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906105dd90612f4d565b80601f016020809104026020016040519081016040528092919081815260200182805461060990612f4d565b80156106565780601f1061062b57610100808354040283529160200191610656565b820191906000526020600020905b81548152906001019060200180831161063957829003601f168201915b50505050509050919050565b60408051602081019091526000815261068261067d8361304b565b61138f565b6040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152606083013560248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906340c10f1990604401600060405180830381600087803b15801561071357600080fd5b505af1158015610727573d6000803e3d6000fd5b5061073c925050506060830160408401612ad5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161079e91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6107c56115c0565b6108328484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061164392505050565b50505050565b6108406115c0565b61084983610aa9565b610890576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546108b790612f4d565b80601f01602080910402602001604051908101604052809291908181526020018280546108e390612f4d565b80156109305780601f1061090557610100808354040283529160200191610930565b820191906000526020600020905b81548152906001019060200180831161091357829003601f168201915b5050505067ffffffffffffffff861660009081526007602052604090209192505060040161095f838583613190565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf82858560405161099e939291906132aa565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610887565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006105ac600567ffffffffffffffff84166117f9565b6040805180820190915260608082526020820152610ae5610ae08361330e565b611814565b610af282606001356119de565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b4c8460200160208101906104089190612a16565b81526040805160208181019092526000815291015292915050565b6060610b736002611a87565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105ac90611a94565b67ffffffffffffffff811660009081526007602052604090206005018054606091906105dd90612f4d565b610c806115c0565b73ffffffffffffffffffffffffffffffffffffffff8116610ccd576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610d616005611a87565b90506000815167ffffffffffffffff811115610d7f57610d7f612da0565b604051908082528060200260200182016040528015610da8578160200160208202803683370190505b50905060005b8251811015610e0457828181518110610dc957610dc96133b0565b6020026020010151828281518110610de357610de36133b0565b67ffffffffffffffff90921660209283029190910190910152600101610dae565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105ac90611a94565b610ee56115c0565b610ef0838383611b46565b505050565b610efd6115c0565b60005b81811015610ef0576000838383818110610f1c57610f1c6133b0565b9050602002810190610f2e91906133df565b610f379061341d565b9050610f4c8160800151826020015115611c30565b610f5f8160a00151826020015115611c30565b80602001511561125b578051610f819060059067ffffffffffffffff16611d69565b610fc65780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610887565b6040810151511580610fdb5750606081015151155b15611012576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906111f390826134d1565b506060820151600582019061120890826134d1565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061124e94939291906135eb565b60405180910390a1611372565b80516112739060059067ffffffffffffffff16611d75565b6112b85780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610887565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906113216004830182612969565b61132f600583016000612969565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101610f00565b6113836115c0565b61138c81611d81565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146114245760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610887565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa1580156114d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f69190613684565b1561152d576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61153a8160200151611e76565b600061154982602001516105b2565b905080516000148061156d575080805190602001208260a001518051906020012014155b156115aa578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108879190612a95565b6115bc82602001518360600151611f9c565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610887565b565b7f000000000000000000000000000000000000000000000000000000000000000061169a576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156117305760008382815181106116ba576116ba6133b0565b602002602001015190506116d8816002611fe390919063ffffffff16565b156117275760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010161169d565b5060005b8151811015610ef0576000828281518110611751576117516133b0565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361179557506117f1565b6117a0600282612005565b156117ef5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611734565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146118a95760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610887565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611957573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197b9190613684565b156119b2576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119bf8160400151612027565b6119cc81602001516120a6565b61138c816020015182606001516121f4565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b158015611a6c57600080fd5b505af1158015611a80573d6000803e3d6000fd5b5050505050565b6060600061180d83612238565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611b2282606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611b0691906136d0565b85608001516fffffffffffffffffffffffffffffffff16612293565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611b4f83610aa9565b611b91576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610887565b611b9c826000611c30565b67ffffffffffffffff83166000908152600760205260409020611bbf90836122bd565b611bca816000611c30565b67ffffffffffffffff83166000908152600760205260409020611bf090600201826122bd565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611c23939291906136e3565b60405180910390a1505050565b815115611cf75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611c86575060408201516fffffffffffffffffffffffffffffffff16155b15611cbf57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108879190613766565b80156115bc576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611d30575060208201516fffffffffffffffffffffffffffffffff1615155b156115bc57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108879190613766565b600061180d838361245f565b600061180d83836124ae565b3373ffffffffffffffffffffffffffffffffffffffff821603611e00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610887565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611e7f81610aa9565b611ec1576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610887565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015611f40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f649190613684565b61138c576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610887565b67ffffffffffffffff821660009081526007602052604090206115bc90600201827f00000000000000000000000000000000000000000000000000000000000000006125a1565b600061180d8373ffffffffffffffffffffffffffffffffffffffff84166124ae565b600061180d8373ffffffffffffffffffffffffffffffffffffffff841661245f565b7f00000000000000000000000000000000000000000000000000000000000000001561138c57612058600282612924565b61138c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610887565b6120af81610aa9565b6120f1576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610887565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561216a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218e91906137a2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461138c576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610887565b67ffffffffffffffff821660009081526007602052604090206115bc90827f00000000000000000000000000000000000000000000000000000000000000006125a1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561065657602002820191906000526020600020905b8154815260200190600101908083116122745750505050509050919050565b60006122b2856122a384866137bf565b6122ad90876137d6565b612953565b90505b949350505050565b81546000906122e690700100000000000000000000000000000000900463ffffffff16426136d0565b90508015612388576001830154835461232e916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612293565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546123ae916fffffffffffffffffffffffffffffffff9081169116612953565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611c23908490613766565b60008181526001830160205260408120546124a6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105ac565b5060006105ac565b600081815260018301602052604081205480156125975760006124d26001836136d0565b85549091506000906124e6906001906136d0565b905081811461254b576000866000018281548110612506576125066133b0565b9060005260206000200154905080876000018481548110612529576125296133b0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061255c5761255c6137e9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105ac565b60009150506105ac565b825474010000000000000000000000000000000000000000900460ff1615806125c8575081155b156125d257505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061261890700100000000000000000000000000000000900463ffffffff16426136d0565b905080156126d8578183111561265a576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546126949083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612293565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561278f5773ffffffffffffffffffffffffffffffffffffffff8416612737576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610887565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610887565b848310156128a25760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906127d390826136d0565b6127dd878a6136d0565b6127e791906137d6565b6127f19190613818565b905073ffffffffffffffffffffffffffffffffffffffff861661284a576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610887565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610887565b6128ac85846136d0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561180d565b6000818310612962578161180d565b5090919050565b50805461297590612f4d565b6000825580601f10612985575050565b601f01602090049060005260206000209081019061138c91905b808211156129b3576000815560010161299f565b5090565b6000602082840312156129c957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461180d57600080fd5b803567ffffffffffffffff81168114612a1157600080fd5b919050565b600060208284031215612a2857600080fd5b61180d826129f9565b6000815180845260005b81811015612a5757602081850181015186830182015201612a3b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061180d6020830184612a31565b73ffffffffffffffffffffffffffffffffffffffff8116811461138c57600080fd5b8035612a1181612aa8565b600060208284031215612ae757600080fd5b813561180d81612aa8565b600060208284031215612b0457600080fd5b813567ffffffffffffffff811115612b1b57600080fd5b8201610100818503121561180d57600080fd5b60008083601f840112612b4057600080fd5b50813567ffffffffffffffff811115612b5857600080fd5b6020830191508360208260051b8501011115612b7357600080fd5b9250929050565b60008060008060408587031215612b9057600080fd5b843567ffffffffffffffff80821115612ba857600080fd5b612bb488838901612b2e565b90965094506020870135915080821115612bcd57600080fd5b50612bda87828801612b2e565b95989497509550505050565b600080600060408486031215612bfb57600080fd5b612c04846129f9565b9250602084013567ffffffffffffffff80821115612c2157600080fd5b818601915086601f830112612c3557600080fd5b813581811115612c4457600080fd5b876020828501011115612c5657600080fd5b6020830194508093505050509250925092565b600060208284031215612c7b57600080fd5b813567ffffffffffffffff811115612c9257600080fd5b820160a0818503121561180d57600080fd5b602081526000825160406020840152612cc06060840182612a31565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612cfb8282612a31565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612d5257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612d20565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612d5257835167ffffffffffffffff1683529284019291840191600101612d7a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612df357612df3612da0565b60405290565b60405160c0810167ffffffffffffffff81118282101715612df357612df3612da0565b801515811461138c57600080fd5b8035612a1181612e1c565b80356fffffffffffffffffffffffffffffffff81168114612a1157600080fd5b600060608284031215612e6757600080fd5b6040516060810181811067ffffffffffffffff82111715612e8a57612e8a612da0565b6040529050808235612e9b81612e1c565b8152612ea960208401612e35565b6020820152612eba60408401612e35565b60408201525092915050565b600080600060e08486031215612edb57600080fd5b612ee4846129f9565b9250612ef38560208601612e55565b9150612f028560808601612e55565b90509250925092565b60008060208385031215612f1e57600080fd5b823567ffffffffffffffff811115612f3557600080fd5b612f4185828601612b2e565b90969095509350505050565b600181811c90821680612f6157607f821691505b602082108103612f9a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f830112612fb157600080fd5b813567ffffffffffffffff80821115612fcc57612fcc612da0565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561301257613012612da0565b8160405283815286602085880101111561302b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561305e57600080fd5b613066612dcf565b823567ffffffffffffffff8082111561307e57600080fd5b61308a36838701612fa0565b8352613098602086016129f9565b60208401526130a960408601612aca565b6040840152606085013560608401526130c460808601612aca565b608084015260a08501359150808211156130dd57600080fd5b6130e936838701612fa0565b60a084015260c085013591508082111561310257600080fd5b61310e36838701612fa0565b60c084015260e085013591508082111561312757600080fd5b5061313436828601612fa0565b60e08301525092915050565b601f821115610ef0576000816000526020600020601f850160051c810160208610156131695750805b601f850160051c820191505b8181101561318857828155600101613175565b505050505050565b67ffffffffffffffff8311156131a8576131a8612da0565b6131bc836131b68354612f4d565b83613140565b6000601f84116001811461320e57600085156131d85750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611a80565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561325d578685013582556020948501946001909201910161323d565b5086821015613298577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006132bd6040830186612a31565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561332057600080fd5b60405160a0810167ffffffffffffffff828210818311171561334457613344612da0565b81604052843591508082111561335957600080fd5b5061336636828601612fa0565b825250613375602084016129f9565b6020820152604083013561338881612aa8565b60408201526060838101359082015260808301356133a581612aa8565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261341357600080fd5b9190910192915050565b6000610140823603121561343057600080fd5b613438612df9565b613441836129f9565b815261344f60208401612e2a565b6020820152604083013567ffffffffffffffff8082111561346f57600080fd5b61347b36838701612fa0565b6040840152606085013591508082111561349457600080fd5b506134a136828601612fa0565b6060830152506134b43660808501612e55565b60808201526134c63660e08501612e55565b60a082015292915050565b815167ffffffffffffffff8111156134eb576134eb612da0565b6134ff816134f98454612f4d565b84613140565b602080601f831160018114613552576000841561351c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613188565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561359f57888601518255948401946001909101908401613580565b50858210156135db57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261360f81840187612a31565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061364d9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612cfb565b60006020828403121561369657600080fd5b815161180d81612e1c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105ac576105ac6136a1565b67ffffffffffffffff8416815260e0810161372f60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526122b5565b606081016105ac82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156137b457600080fd5b815161180d81612aa8565b80820281158282048414176105ac576105ac6136a1565b808201808211156105ac576105ac6136a1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261384e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b506040516200450b3803806200450b8339810160408190526200003491620008c0565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c2816200018f565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c05262000168576040805160008152602081019091526200016890846200023a565b5062000185925050506001600160a01b0385163060001962000397565b5050505062000afc565b336001600160a01b03821603620001e95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200025b576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002e65760008382815181106200027f576200027f620009d0565b60209081029190910101519050620002996002826200047d565b15620002dc576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200025e565b5060005b8151811015620003925760008282815181106200030b576200030b620009d0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000337575062000389565b620003446002826200049d565b1562000387576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002ea565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040f9190620009e6565b6200041b919062000a16565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047791869190620004b416565b50505050565b600062000494836001600160a01b03841662000585565b90505b92915050565b600062000494836001600160a01b03841662000689565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000503906001600160a01b038516908490620006db565b80519091501562000392578080602001905181019062000524919062000a2c565b620003925760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000086565b600081815260018301602052604081205480156200067e576000620005ac60018362000a57565b8554909150600090620005c29060019062000a57565b90508082146200062e576000866000018281548110620005e657620005e6620009d0565b90600052602060002001549050808760000184815481106200060c576200060c620009d0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000642576200064262000a6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000497565b600091505062000497565b6000818152600183016020526040812054620006d25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000497565b50600062000497565b6060620006ec8484600085620006f4565b949350505050565b606082471015620007575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000086565b600080866001600160a01b0316858760405162000775919062000aa9565b60006040518083038185875af1925050503d8060008114620007b4576040519150601f19603f3d011682016040523d82523d6000602084013e620007b9565b606091505b509092509050620007cd87838387620007d8565b979650505050505050565b606083156200084c57825160000362000844576001600160a01b0385163b620008445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000086565b5081620006ec565b620006ec8383815115620008635781518083602001fd5b8060405162461bcd60e51b815260040162000086919062000ac7565b6001600160a01b03811681146200089557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008bb816200087f565b919050565b60008060008060808587031215620008d757600080fd5b8451620008e4816200087f565b602086810151919550906001600160401b03808211156200090457600080fd5b818801915088601f8301126200091957600080fd5b8151818111156200092e576200092e62000898565b8060051b604051601f19603f8301168101818110858211171562000956576200095662000898565b60405291825284820192508381018501918b8311156200097557600080fd5b938501935b828510156200099e576200098e85620008ae565b845293850193928501926200097a565b809850505050505050620009b560408601620008ae565b9150620009c560608601620008ae565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000497576200049762000a00565b60006020828403121562000a3f57600080fd5b8151801515811462000a5057600080fd5b9392505050565b8181038181111562000497576200049762000a00565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa057818101518382015260200162000a86565b50506000910152565b6000825162000abd81846020870162000a83565b9190910192915050565b602081526000825180602084015262000ae881604085016020870162000a83565b601f01601f19169190910160400192915050565b60805160a05160c05161399262000b79600039600081816104dd01528181611777015261215b0152600081816104b7015281816115a80152611a2d0152600081816102390152818161028e015281816106e0015281816114c80152818161194d01528181611b45015281816120f1015261234601526139926000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc146104a2578063dc0bd971146104b5578063e0351e13146104db578063f2fde38b1461050157600080fd5b8063c4bffe2b14610467578063c75eea9c1461047c578063cf7401f31461048f57600080fd5b8063b0f479a1116100c8578063b0f479a114610423578063b794658014610441578063c0d786551461045457600080fd5b80639a4575b91461037f578063a7cd63b71461039f578063af58d59f146103b457600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103335780637d54534e1461033b5780638926f54f1461034e5780638da5cb5b1461036157600080fd5b806354c8a4f3146102ed5780636d3d1a581461030257806378a010b21461032057600080fd5b806321df0da71161018c57806321df0da714610237578063240028e81461027e57806339077537146102cb57600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612ae9565b610514565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612b48565b6105f9565b6040516101d29190612bc7565b6101ee6040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e30000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c661028c366004612c07565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102de6102d9366004612c24565b6106a9565b604051905181526020016101d2565b6103006102fb366004612cac565b61082f565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610259565b61030061032e366004612d18565b6108aa565b610300610a1e565b610300610349366004612c07565b610b1b565b6101c661035c366004612b48565b610b6a565b60005473ffffffffffffffffffffffffffffffffffffffff16610259565b61039261038d366004612d9b565b610b81565b6040516101d29190612dd6565b6103a7610c28565b6040516101d29190612e36565b6103c76103c2366004612b48565b610c39565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610259565b6101ee61044f366004612b48565b610d0e565b610300610462366004612c07565b610d39565b61046f610e14565b6040516101d29190612e90565b6103c761048a366004612b48565b610ecc565b61030061049d366004612ff8565b610f9e565b6103006104b036600461303d565b611027565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b61030061050f366004612c07565b6114ad565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106249061307f565b80601f01602080910402602001604051908101604052809291908181526020018280546106509061307f565b801561069d5780601f106106725761010080835404028352916020019161069d565b820191906000526020600020905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c96106c48361317d565b6114c1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107156060850160408601612c07565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b506107ae925050506060830160408401612c07565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081091815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108376116f2565b6108a48484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061177592505050565b50505050565b6108b26116f2565b6108bb83610b6a565b610902576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109299061307f565b80601f01602080910402602001604051908101604052809291908181526020018280546109559061307f565b80156109a25780601f10610977576101008083540402835291602001916109a2565b820191906000526020600020905b81548152906001019060200180831161098557829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d18385836132c2565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a10939291906133dc565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f9565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b236116f2565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105f3600567ffffffffffffffff841661192b565b6040805180820190915260608082526020820152610ba6610ba183613440565b611946565b610bb38260600135611b10565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0d84602001602081019061044f9190612b48565b81526040805160208181019092526000815291015292915050565b6060610c346002611bb9565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f390611bc6565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106249061307f565b610d416116f2565b73ffffffffffffffffffffffffffffffffffffffff8116610d8e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e226005611bb9565b90506000815167ffffffffffffffff811115610e4057610e40612ed2565b604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50905060005b8251811015610ec557828181518110610e8a57610e8a6134e2565b6020026020010151828281518110610ea457610ea46134e2565b67ffffffffffffffff90921660209283029190910190910152600101610e6f565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f390611bc6565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fde575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611017576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b611022838383611c78565b505050565b61102f6116f2565b60005b8181101561102257600083838381811061104e5761104e6134e2565b90506020028101906110609190613511565b6110699061354f565b905061107e8160800151826020015115611d62565b6110918160a00151826020015115611d62565b80602001511561138d5780516110b39060059067ffffffffffffffff16611e9b565b6110f85780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b604081015151158061110d5750606081015151155b15611144576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906113259082613603565b506060820151600582019061133a9082613603565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c29550611380949392919061371d565b60405180910390a16114a4565b80516113a59060059067ffffffffffffffff16611ea7565b6113ea5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114536004830182612a9b565b611461600583016000612a9b565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611032565b6114b56116f2565b6114be81611eb3565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115565760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162891906137b6565b1561165f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166c8160200151611fa8565b600061167b82602001516105f9565b905080516000148061169f575080805190602001208260a001518051906020012014155b156116dc578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f99190612bc7565b6116ee826020015183606001516120ce565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f9565b565b7f00000000000000000000000000000000000000000000000000000000000000006117cc576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118625760008382815181106117ec576117ec6134e2565b6020026020010151905061180a81600261211590919063ffffffff16565b156118595760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117cf565b5060005b8151811015611022576000828281518110611883576118836134e2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118c75750611923565b6118d2600282612137565b156119215760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611866565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119db5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906137b6565b15611ae4576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611af18160400151612159565b611afe81602001516121d8565b6114be81602001518260600151612326565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b158015611b9e57600080fd5b505af1158015611bb2573d6000803e3d6000fd5b5050505050565b6060600061193f8361236a565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c5482606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c389190613802565b85608001516fffffffffffffffffffffffffffffffff166123c5565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c8183610b6a565b611cc3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f9565b611cce826000611d62565b67ffffffffffffffff83166000908152600760205260409020611cf190836123ef565b611cfc816000611d62565b67ffffffffffffffff83166000908152600760205260409020611d2290600201826123ef565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d5593929190613815565b60405180910390a1505050565b815115611e295781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611db8575060408201516fffffffffffffffffffffffffffffffff16155b15611df157816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f99190613898565b80156116ee576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e62575060208201516fffffffffffffffffffffffffffffffff1615155b156116ee57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f99190613898565b600061193f8383612591565b600061193f83836125e0565b3373ffffffffffffffffffffffffffffffffffffffff821603611f32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fb181610b6a565b611ff3576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612072573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209691906137b6565b6114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90600201827f00000000000000000000000000000000000000000000000000000000000000006126d3565b600061193f8373ffffffffffffffffffffffffffffffffffffffff84166125e0565b600061193f8373ffffffffffffffffffffffffffffffffffffffff8416612591565b7f0000000000000000000000000000000000000000000000000000000000000000156114be5761218a600282612a56565b6114be576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f9565b6121e181610b6a565b612223576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561229c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c091906138d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90827f00000000000000000000000000000000000000000000000000000000000000006126d3565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069d57602002820191906000526020600020905b8154815260200190600101908083116123a65750505050509050919050565b60006123e4856123d584866138f1565b6123df9087613908565b612a85565b90505b949350505050565b815460009061241890700100000000000000000000000000000000900463ffffffff1642613802565b905080156124ba5760018301548354612460916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166123c5565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546124e0916fffffffffffffffffffffffffffffffff9081169116612a85565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d55908490613898565b60008181526001830160205260408120546125d8575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f3565b5060006105f3565b600081815260018301602052604081205480156126c9576000612604600183613802565b855490915060009061261890600190613802565b905080821461267d576000866000018281548110612638576126386134e2565b906000526020600020015490508087600001848154811061265b5761265b6134e2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268e5761268e61391b565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f3565b60009150506105f3565b825474010000000000000000000000000000000000000000900460ff1615806126fa575081155b1561270457505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061274a90700100000000000000000000000000000000900463ffffffff1642613802565b9050801561280a578183111561278c576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127c69083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166123c5565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128c15773ffffffffffffffffffffffffffffffffffffffff8416612869576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f9565b848310156129d45760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906129059082613802565b61290f878a613802565b6129199190613908565b612923919061394a565b905073ffffffffffffffffffffffffffffffffffffffff861661297c576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f9565b6129de8584613802565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561193f565b6000818310612a94578161193f565b5090919050565b508054612aa79061307f565b6000825580601f10612ab7575050565b601f0160209004906000526020600020908101906114be91905b80821115612ae55760008155600101612ad1565b5090565b600060208284031215612afb57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461193f57600080fd5b803567ffffffffffffffff81168114612b4357600080fd5b919050565b600060208284031215612b5a57600080fd5b61193f82612b2b565b6000815180845260005b81811015612b8957602081850181015186830182015201612b6d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061193f6020830184612b63565b73ffffffffffffffffffffffffffffffffffffffff811681146114be57600080fd5b8035612b4381612bda565b600060208284031215612c1957600080fd5b813561193f81612bda565b600060208284031215612c3657600080fd5b813567ffffffffffffffff811115612c4d57600080fd5b8201610100818503121561193f57600080fd5b60008083601f840112612c7257600080fd5b50813567ffffffffffffffff811115612c8a57600080fd5b6020830191508360208260051b8501011115612ca557600080fd5b9250929050565b60008060008060408587031215612cc257600080fd5b843567ffffffffffffffff80821115612cda57600080fd5b612ce688838901612c60565b90965094506020870135915080821115612cff57600080fd5b50612d0c87828801612c60565b95989497509550505050565b600080600060408486031215612d2d57600080fd5b612d3684612b2b565b9250602084013567ffffffffffffffff80821115612d5357600080fd5b818601915086601f830112612d6757600080fd5b813581811115612d7657600080fd5b876020828501011115612d8857600080fd5b6020830194508093505050509250925092565b600060208284031215612dad57600080fd5b813567ffffffffffffffff811115612dc457600080fd5b820160a0818503121561193f57600080fd5b602081526000825160406020840152612df26060840182612b63565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e2d8282612b63565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612e52565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8457835167ffffffffffffffff1683529284019291840191600101612eac565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612f2557612f25612ed2565b60405290565b60405160c0810167ffffffffffffffff81118282101715612f2557612f25612ed2565b80151581146114be57600080fd5b8035612b4381612f4e565b80356fffffffffffffffffffffffffffffffff81168114612b4357600080fd5b600060608284031215612f9957600080fd5b6040516060810181811067ffffffffffffffff82111715612fbc57612fbc612ed2565b6040529050808235612fcd81612f4e565b8152612fdb60208401612f67565b6020820152612fec60408401612f67565b60408201525092915050565b600080600060e0848603121561300d57600080fd5b61301684612b2b565b92506130258560208601612f87565b91506130348560808601612f87565b90509250925092565b6000806020838503121561305057600080fd5b823567ffffffffffffffff81111561306757600080fd5b61307385828601612c60565b90969095509350505050565b600181811c9082168061309357607f821691505b6020821081036130cc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126130e357600080fd5b813567ffffffffffffffff808211156130fe576130fe612ed2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561314457613144612ed2565b8160405283815286602085880101111561315d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561319057600080fd5b613198612f01565b823567ffffffffffffffff808211156131b057600080fd5b6131bc368387016130d2565b83526131ca60208601612b2b565b60208401526131db60408601612bfc565b6040840152606085013560608401526131f660808601612bfc565b608084015260a085013591508082111561320f57600080fd5b61321b368387016130d2565b60a084015260c085013591508082111561323457600080fd5b613240368387016130d2565b60c084015260e085013591508082111561325957600080fd5b50613266368286016130d2565b60e08301525092915050565b601f821115611022576000816000526020600020601f850160051c8101602086101561329b5750805b601f850160051c820191505b818110156132ba578281556001016132a7565b505050505050565b67ffffffffffffffff8311156132da576132da612ed2565b6132ee836132e8835461307f565b83613272565b6000601f841160018114613340576000851561330a5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611bb2565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561338f578685013582556020948501946001909201910161336f565b50868210156133ca577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133ef6040830186612b63565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561345257600080fd5b60405160a0810167ffffffffffffffff828210818311171561347657613476612ed2565b81604052843591508082111561348b57600080fd5b50613498368286016130d2565b8252506134a760208401612b2b565b602082015260408301356134ba81612bda565b60408201526060838101359082015260808301356134d781612bda565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261354557600080fd5b9190910192915050565b6000610140823603121561356257600080fd5b61356a612f2b565b61357383612b2b565b815261358160208401612f5c565b6020820152604083013567ffffffffffffffff808211156135a157600080fd5b6135ad368387016130d2565b604084015260608501359150808211156135c657600080fd5b506135d3368286016130d2565b6060830152506135e63660808501612f87565b60808201526135f83660e08501612f87565b60a082015292915050565b815167ffffffffffffffff81111561361d5761361d612ed2565b6136318161362b845461307f565b84613272565b602080601f831160018114613684576000841561364e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556132ba565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156136d1578886015182559484019460019091019084016136b2565b508582101561370d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261374181840187612b63565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061377f9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e2d565b6000602082840312156137c857600080fd5b815161193f81612f4e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f3576105f36137d3565b67ffffffffffffffff8416815260e0810161386160208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526123e7565b606081016105f382848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156138e657600080fd5b815161193f81612bda565b80820281158282048414176105f3576105f36137d3565b808201808211156105f3576105f36137d3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082613980577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var BurnFromMintTokenPoolABI = BurnFromMintTokenPoolMetaData.ABI @@ -310,6 +310,28 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetCurrentOutb return _BurnFromMintTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnFromMintTokenPool.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 (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnFromMintTokenPool.CallOpts) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnFromMintTokenPool.CallOpts) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) @@ -624,6 +646,18 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetChainRa return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnFromMintTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnFromMintTokenPool.TransactOpts, rateLimitAdmin) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) } @@ -2644,6 +2678,8 @@ type BurnFromMintTokenPoolInterface interface { GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2678,6 +2714,8 @@ type BurnFromMintTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) 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 70e2f9393e1..244f04596a2 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 @@ -82,8 +82,8 @@ type TokenPoolChainUpdate struct { } var BurnMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":[],\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b5060405162003f8138038062003f8183398101604081905262000034916200054c565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c28162000176565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001685760408051600081526020810190915262000168908462000221565b5050505050505050620006aa565b336001600160a01b03821603620001d05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000242576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002cd5760008382815181106200026657620002666200065c565b60209081029190910101519050620002806002826200037e565b15620002c3576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000245565b5060005b815181101562000379576000828281518110620002f257620002f26200065c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200031e575062000370565b6200032b6002826200039e565b156200036e576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d1565b505050565b600062000395836001600160a01b038416620003b5565b90505b92915050565b600062000395836001600160a01b038416620004b9565b60008181526001830160205260408120548015620004ae576000620003dc60018362000672565b8554909150600090620003f29060019062000672565b90508181146200045e5760008660000182815481106200041657620004166200065c565b90600052602060002001549050808760000184815481106200043c576200043c6200065c565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000472576200047262000694565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000398565b600091505062000398565b6000818152600183016020526040812054620005025750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000398565b50600062000398565b6001600160a01b03811681146200052157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000547816200050b565b919050565b600080600080608085870312156200056357600080fd5b845162000570816200050b565b602086810151919550906001600160401b03808211156200059057600080fd5b818801915088601f830112620005a557600080fd5b815181811115620005ba57620005ba62000524565b8060051b604051601f19603f83011681018181108582111715620005e257620005e262000524565b60405291825284820192508381018501918b8311156200060157600080fd5b938501935b828510156200062a576200061a856200053a565b8452938501939285019262000606565b80985050505050505062000641604086016200053a565b915062000651606086016200053a565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161385a62000727600039600081816104960152818161164501526120230152600081816104700152818161147601526118fb01526000818161022301528181610278015281816106ba015281816113960152818161181b01528181611a0d01528181611fb9015261220e015261385a6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063a7cd63b7116100e3578063c75eea9c1161008c578063dc0bd97111610066578063dc0bd9711461046e578063e0351e1314610494578063f2fde38b146104ba57600080fd5b8063c75eea9c14610435578063cf7401f314610448578063db6327dc1461045b57600080fd5b8063b7946580116100bd578063b7946580146103fa578063c0d786551461040d578063c4bffe2b1461042057600080fd5b8063a7cd63b714610358578063af58d59f1461036d578063b0f479a1146103dc57600080fd5b806354c8a4f3116101455780638926f54f1161011f5780638926f54f146103075780638da5cb5b1461031a5780639a4575b91461033857600080fd5b806354c8a4f3146102d757806378a010b2146102ec57806379ba5097146102ff57600080fd5b806321df0da71161017657806321df0da714610221578063240028e81461026857806339077537146102b557600080fd5b806301ffc9a71461019d5780630a2fd493146101c5578063181f5a77146101e5575b600080fd5b6101b06101ab3660046129b1565b6104cd565b60405190151581526020015b60405180910390f35b6101d86101d3366004612a10565b6105b2565b6040516101bc9190612a8f565b6101d86040518060400160405280601b81526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e302d646576000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b6101b0610276366004612acf565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102c86102c3366004612aec565b610662565b604051905181526020016101bc565b6102ea6102e5366004612b74565b6107bd565b005b6102ea6102fa366004612be0565b610838565b6102ea6109ac565b6101b0610315366004612a10565b610aa9565b60005473ffffffffffffffffffffffffffffffffffffffff16610243565b61034b610346366004612c63565b610ac0565b6040516101bc9190612c9e565b610360610b67565b6040516101bc9190612cfe565b61038061037b366004612a10565b610b78565b6040516101bc919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610243565b6101d8610408366004612a10565b610c4d565b6102ea61041b366004612acf565b610c78565b610428610d53565b6040516101bc9190612d58565b610380610443366004612a10565b610e0b565b6102ea610456366004612ec0565b610edd565b6102ea610469366004612f05565b610ef5565b7f0000000000000000000000000000000000000000000000000000000000000000610243565b7f00000000000000000000000000000000000000000000000000000000000000006101b0565b6102ea6104c8366004612acf565b61137b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061056057507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105ac57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906105dd90612f47565b80601f016020809104026020016040519081016040528092919081815260200182805461060990612f47565b80156106565780601f1061062b57610100808354040283529160200191610656565b820191906000526020600020905b81548152906001019060200180831161063957829003601f168201915b50505050509050919050565b60408051602081019091526000815261068261067d83613045565b61138f565b6040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152606083013560248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906340c10f1990604401600060405180830381600087803b15801561071357600080fd5b505af1158015610727573d6000803e3d6000fd5b5061073c925050506060830160408401612acf565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161079e91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6107c56115c0565b6108328484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061164392505050565b50505050565b6108406115c0565b61084983610aa9565b610890576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546108b790612f47565b80601f01602080910402602001604051908101604052809291908181526020018280546108e390612f47565b80156109305780601f1061090557610100808354040283529160200191610930565b820191906000526020600020905b81548152906001019060200180831161091357829003601f168201915b5050505067ffffffffffffffff861660009081526007602052604090209192505060040161095f83858361318a565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf82858560405161099e939291906132a4565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610887565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006105ac600567ffffffffffffffff84166117f9565b6040805180820190915260608082526020820152610ae5610ae083613308565b611814565b610af282606001356119de565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b4c8460200160208101906104089190612a10565b81526040805160208181019092526000815291015292915050565b6060610b736002611a81565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105ac90611a8e565b67ffffffffffffffff811660009081526007602052604090206005018054606091906105dd90612f47565b610c806115c0565b73ffffffffffffffffffffffffffffffffffffffff8116610ccd576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610d616005611a81565b90506000815167ffffffffffffffff811115610d7f57610d7f612d9a565b604051908082528060200260200182016040528015610da8578160200160208202803683370190505b50905060005b8251811015610e0457828181518110610dc957610dc96133aa565b6020026020010151828281518110610de357610de36133aa565b67ffffffffffffffff90921660209283029190910190910152600101610dae565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105ac90611a8e565b610ee56115c0565b610ef0838383611b40565b505050565b610efd6115c0565b60005b81811015610ef0576000838383818110610f1c57610f1c6133aa565b9050602002810190610f2e91906133d9565b610f3790613417565b9050610f4c8160800151826020015115611c2a565b610f5f8160a00151826020015115611c2a565b80602001511561125b578051610f819060059067ffffffffffffffff16611d63565b610fc65780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610887565b6040810151511580610fdb5750606081015151155b15611012576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906111f390826134cb565b506060820151600582019061120890826134cb565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061124e94939291906135e5565b60405180910390a1611372565b80516112739060059067ffffffffffffffff16611d6f565b6112b85780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610887565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906113216004830182612963565b61132f600583016000612963565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101610f00565b6113836115c0565b61138c81611d7b565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146114245760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610887565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa1580156114d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f6919061367e565b1561152d576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61153a8160200151611e70565b600061154982602001516105b2565b905080516000148061156d575080805190602001208260a001518051906020012014155b156115aa578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108879190612a8f565b6115bc82602001518360600151611f96565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610887565b565b7f000000000000000000000000000000000000000000000000000000000000000061169a576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156117305760008382815181106116ba576116ba6133aa565b602002602001015190506116d8816002611fdd90919063ffffffff16565b156117275760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010161169d565b5060005b8151811015610ef0576000828281518110611751576117516133aa565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361179557506117f1565b6117a0600282611fff565b156117ef5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611734565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146118a95760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610887565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611957573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197b919061367e565b156119b2576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119bf8160400151612021565b6119cc81602001516120a0565b61138c816020015182606001516121ee565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015611a6657600080fd5b505af1158015611a7a573d6000803e3d6000fd5b5050505050565b6060600061180d83612232565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611b1c82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611b0091906136ca565b85608001516fffffffffffffffffffffffffffffffff1661228d565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611b4983610aa9565b611b8b576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610887565b611b96826000611c2a565b67ffffffffffffffff83166000908152600760205260409020611bb990836122b7565b611bc4816000611c2a565b67ffffffffffffffff83166000908152600760205260409020611bea90600201826122b7565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611c1d939291906136dd565b60405180910390a1505050565b815115611cf15781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611c80575060408201516fffffffffffffffffffffffffffffffff16155b15611cb957816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108879190613760565b80156115bc576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611d2a575060208201516fffffffffffffffffffffffffffffffff1615155b156115bc57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108879190613760565b600061180d8383612459565b600061180d83836124a8565b3373ffffffffffffffffffffffffffffffffffffffff821603611dfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610887565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611e7981610aa9565b611ebb576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610887565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e919061367e565b61138c576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610887565b67ffffffffffffffff821660009081526007602052604090206115bc90600201827f000000000000000000000000000000000000000000000000000000000000000061259b565b600061180d8373ffffffffffffffffffffffffffffffffffffffff84166124a8565b600061180d8373ffffffffffffffffffffffffffffffffffffffff8416612459565b7f00000000000000000000000000000000000000000000000000000000000000001561138c5761205260028261291e565b61138c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610887565b6120a981610aa9565b6120eb576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610887565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612164573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612188919061379c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461138c576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610887565b67ffffffffffffffff821660009081526007602052604090206115bc90827f000000000000000000000000000000000000000000000000000000000000000061259b565b60608160000180548060200260200160405190810160405280929190818152602001828054801561065657602002820191906000526020600020905b81548152602001906001019080831161226e5750505050509050919050565b60006122ac8561229d84866137b9565b6122a790876137d0565b61294d565b90505b949350505050565b81546000906122e090700100000000000000000000000000000000900463ffffffff16426136ca565b905080156123825760018301548354612328916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661228d565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546123a8916fffffffffffffffffffffffffffffffff908116911661294d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611c1d908490613760565b60008181526001830160205260408120546124a0575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105ac565b5060006105ac565b600081815260018301602052604081205480156125915760006124cc6001836136ca565b85549091506000906124e0906001906136ca565b9050818114612545576000866000018281548110612500576125006133aa565b9060005260206000200154905080876000018481548110612523576125236133aa565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612556576125566137e3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105ac565b60009150506105ac565b825474010000000000000000000000000000000000000000900460ff1615806125c2575081155b156125cc57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061261290700100000000000000000000000000000000900463ffffffff16426136ca565b905080156126d25781831115612654576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600186015461268e9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661228d565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156127895773ffffffffffffffffffffffffffffffffffffffff8416612731576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610887565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610887565b8483101561289c5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906127cd90826136ca565b6127d7878a6136ca565b6127e191906137d0565b6127eb9190613812565b905073ffffffffffffffffffffffffffffffffffffffff8616612844576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610887565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610887565b6128a685846136ca565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561180d565b600081831061295c578161180d565b5090919050565b50805461296f90612f47565b6000825580601f1061297f575050565b601f01602090049060005260206000209081019061138c91905b808211156129ad5760008155600101612999565b5090565b6000602082840312156129c357600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461180d57600080fd5b803567ffffffffffffffff81168114612a0b57600080fd5b919050565b600060208284031215612a2257600080fd5b61180d826129f3565b6000815180845260005b81811015612a5157602081850181015186830182015201612a35565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061180d6020830184612a2b565b73ffffffffffffffffffffffffffffffffffffffff8116811461138c57600080fd5b8035612a0b81612aa2565b600060208284031215612ae157600080fd5b813561180d81612aa2565b600060208284031215612afe57600080fd5b813567ffffffffffffffff811115612b1557600080fd5b8201610100818503121561180d57600080fd5b60008083601f840112612b3a57600080fd5b50813567ffffffffffffffff811115612b5257600080fd5b6020830191508360208260051b8501011115612b6d57600080fd5b9250929050565b60008060008060408587031215612b8a57600080fd5b843567ffffffffffffffff80821115612ba257600080fd5b612bae88838901612b28565b90965094506020870135915080821115612bc757600080fd5b50612bd487828801612b28565b95989497509550505050565b600080600060408486031215612bf557600080fd5b612bfe846129f3565b9250602084013567ffffffffffffffff80821115612c1b57600080fd5b818601915086601f830112612c2f57600080fd5b813581811115612c3e57600080fd5b876020828501011115612c5057600080fd5b6020830194508093505050509250925092565b600060208284031215612c7557600080fd5b813567ffffffffffffffff811115612c8c57600080fd5b820160a0818503121561180d57600080fd5b602081526000825160406020840152612cba6060840182612a2b565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612cf58282612a2b565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612d4c57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612d1a565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612d4c57835167ffffffffffffffff1683529284019291840191600101612d74565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612ded57612ded612d9a565b60405290565b60405160c0810167ffffffffffffffff81118282101715612ded57612ded612d9a565b801515811461138c57600080fd5b8035612a0b81612e16565b80356fffffffffffffffffffffffffffffffff81168114612a0b57600080fd5b600060608284031215612e6157600080fd5b6040516060810181811067ffffffffffffffff82111715612e8457612e84612d9a565b6040529050808235612e9581612e16565b8152612ea360208401612e2f565b6020820152612eb460408401612e2f565b60408201525092915050565b600080600060e08486031215612ed557600080fd5b612ede846129f3565b9250612eed8560208601612e4f565b9150612efc8560808601612e4f565b90509250925092565b60008060208385031215612f1857600080fd5b823567ffffffffffffffff811115612f2f57600080fd5b612f3b85828601612b28565b90969095509350505050565b600181811c90821680612f5b57607f821691505b602082108103612f94577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f830112612fab57600080fd5b813567ffffffffffffffff80821115612fc657612fc6612d9a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561300c5761300c612d9a565b8160405283815286602085880101111561302557600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561305857600080fd5b613060612dc9565b823567ffffffffffffffff8082111561307857600080fd5b61308436838701612f9a565b8352613092602086016129f3565b60208401526130a360408601612ac4565b6040840152606085013560608401526130be60808601612ac4565b608084015260a08501359150808211156130d757600080fd5b6130e336838701612f9a565b60a084015260c08501359150808211156130fc57600080fd5b61310836838701612f9a565b60c084015260e085013591508082111561312157600080fd5b5061312e36828601612f9a565b60e08301525092915050565b601f821115610ef0576000816000526020600020601f850160051c810160208610156131635750805b601f850160051c820191505b818110156131825782815560010161316f565b505050505050565b67ffffffffffffffff8311156131a2576131a2612d9a565b6131b6836131b08354612f47565b8361313a565b6000601f84116001811461320857600085156131d25750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611a7a565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156132575786850135825560209485019460019092019101613237565b5086821015613292577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006132b76040830186612a2b565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561331a57600080fd5b60405160a0810167ffffffffffffffff828210818311171561333e5761333e612d9a565b81604052843591508082111561335357600080fd5b5061336036828601612f9a565b82525061336f602084016129f3565b6020820152604083013561338281612aa2565b604082015260608381013590820152608083013561339f81612aa2565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261340d57600080fd5b9190910192915050565b6000610140823603121561342a57600080fd5b613432612df3565b61343b836129f3565b815261344960208401612e24565b6020820152604083013567ffffffffffffffff8082111561346957600080fd5b61347536838701612f9a565b6040840152606085013591508082111561348e57600080fd5b5061349b36828601612f9a565b6060830152506134ae3660808501612e4f565b60808201526134c03660e08501612e4f565b60a082015292915050565b815167ffffffffffffffff8111156134e5576134e5612d9a565b6134f9816134f38454612f47565b8461313a565b602080601f83116001811461354c57600084156135165750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613182565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156135995788860151825594840194600190910190840161357a565b50858210156135d557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261360981840187612a2b565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506136479050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612cf5565b60006020828403121561369057600080fd5b815161180d81612e16565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105ac576105ac61369b565b67ffffffffffffffff8416815260e0810161372960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526122af565b606081016105ac82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156137ae57600080fd5b815161180d81612aa2565b80820281158282048414176105ac576105ac61369b565b808201808211156105ac576105ac61369b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082613848577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b50604051620040b3380380620040b383398101604081905262000034916200054c565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c28162000176565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001685760408051600081526020810190915262000168908462000221565b5050505050505050620006aa565b336001600160a01b03821603620001d05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000242576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002cd5760008382815181106200026657620002666200065c565b60209081029190910101519050620002806002826200037e565b15620002c3576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000245565b5060005b815181101562000379576000828281518110620002f257620002f26200065c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200031e575062000370565b6200032b6002826200039e565b156200036e576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d1565b505050565b600062000395836001600160a01b038416620003b5565b90505b92915050565b600062000395836001600160a01b038416620004b9565b60008181526001830160205260408120548015620004ae576000620003dc60018362000672565b8554909150600090620003f29060019062000672565b90508082146200045e5760008660000182815481106200041657620004166200065c565b90600052602060002001549050808760000184815481106200043c576200043c6200065c565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000472576200047262000694565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000398565b600091505062000398565b6000818152600183016020526040812054620005025750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000398565b50600062000398565b6001600160a01b03811681146200052157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000547816200050b565b919050565b600080600080608085870312156200056357600080fd5b845162000570816200050b565b602086810151919550906001600160401b03808211156200059057600080fd5b818801915088601f830112620005a557600080fd5b815181811115620005ba57620005ba62000524565b8060051b604051601f19603f83011681018181108582111715620005e257620005e262000524565b60405291825284820192508381018501918b8311156200060157600080fd5b938501935b828510156200062a576200061a856200053a565b8452938501939285019262000606565b80985050505050505062000641604086016200053a565b915062000651606086016200053a565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161398c62000727600039600081816104dd0152818161177701526121550152600081816104b7015281816115a80152611a2d0152600081816102390152818161028e015281816106e0015281816114c80152818161194d01528181611b3f015281816120eb0152612340015261398c6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc146104a2578063dc0bd971146104b5578063e0351e13146104db578063f2fde38b1461050157600080fd5b8063c4bffe2b14610467578063c75eea9c1461047c578063cf7401f31461048f57600080fd5b8063b0f479a1116100c8578063b0f479a114610423578063b794658014610441578063c0d786551461045457600080fd5b80639a4575b91461037f578063a7cd63b71461039f578063af58d59f146103b457600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103335780637d54534e1461033b5780638926f54f1461034e5780638da5cb5b1461036157600080fd5b806354c8a4f3146102ed5780636d3d1a581461030257806378a010b21461032057600080fd5b806321df0da71161018c57806321df0da714610237578063240028e81461027e57806339077537146102cb57600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612ae3565b610514565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612b42565b6105f9565b6040516101d29190612bc1565b6101ee6040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c661028c366004612c01565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102de6102d9366004612c1e565b6106a9565b604051905181526020016101d2565b6103006102fb366004612ca6565b61082f565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610259565b61030061032e366004612d12565b6108aa565b610300610a1e565b610300610349366004612c01565b610b1b565b6101c661035c366004612b42565b610b6a565b60005473ffffffffffffffffffffffffffffffffffffffff16610259565b61039261038d366004612d95565b610b81565b6040516101d29190612dd0565b6103a7610c28565b6040516101d29190612e30565b6103c76103c2366004612b42565b610c39565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610259565b6101ee61044f366004612b42565b610d0e565b610300610462366004612c01565b610d39565b61046f610e14565b6040516101d29190612e8a565b6103c761048a366004612b42565b610ecc565b61030061049d366004612ff2565b610f9e565b6103006104b0366004613037565b611027565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b61030061050f366004612c01565b6114ad565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061062490613079565b80601f016020809104026020016040519081016040528092919081815260200182805461065090613079565b801561069d5780601f106106725761010080835404028352916020019161069d565b820191906000526020600020905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c96106c483613177565b6114c1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107156060850160408601612c01565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b506107ae925050506060830160408401612c01565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081091815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108376116f2565b6108a48484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061177592505050565b50505050565b6108b26116f2565b6108bb83610b6a565b610902576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff83166000908152600760205260408120600401805461092990613079565b80601f016020809104026020016040519081016040528092919081815260200182805461095590613079565b80156109a25780601f10610977576101008083540402835291602001916109a2565b820191906000526020600020905b81548152906001019060200180831161098557829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d18385836132bc565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a10939291906133d6565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f9565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b236116f2565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105f3600567ffffffffffffffff841661192b565b6040805180820190915260608082526020820152610ba6610ba18361343a565b611946565b610bb38260600135611b10565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0d84602001602081019061044f9190612b42565b81526040805160208181019092526000815291015292915050565b6060610c346002611bb3565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f390611bc0565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061062490613079565b610d416116f2565b73ffffffffffffffffffffffffffffffffffffffff8116610d8e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e226005611bb3565b90506000815167ffffffffffffffff811115610e4057610e40612ecc565b604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50905060005b8251811015610ec557828181518110610e8a57610e8a6134dc565b6020026020010151828281518110610ea457610ea46134dc565b67ffffffffffffffff90921660209283029190910190910152600101610e6f565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f390611bc0565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fde575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611017576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b611022838383611c72565b505050565b61102f6116f2565b60005b8181101561102257600083838381811061104e5761104e6134dc565b9050602002810190611060919061350b565b61106990613549565b905061107e8160800151826020015115611d5c565b6110918160a00151826020015115611d5c565b80602001511561138d5780516110b39060059067ffffffffffffffff16611e95565b6110f85780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b604081015151158061110d5750606081015151155b15611144576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c1790911696151502959095179098559081015194015193811693169091029190911760038201559151909190600482019061132590826135fd565b506060820151600582019061133a90826135fd565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506113809493929190613717565b60405180910390a16114a4565b80516113a59060059067ffffffffffffffff16611ea1565b6113ea5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114536004830182612a95565b611461600583016000612a95565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611032565b6114b56116f2565b6114be81611ead565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115565760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162891906137b0565b1561165f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166c8160200151611fa2565b600061167b82602001516105f9565b905080516000148061169f575080805190602001208260a001518051906020012014155b156116dc578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f99190612bc1565b6116ee826020015183606001516120c8565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f9565b565b7f00000000000000000000000000000000000000000000000000000000000000006117cc576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118625760008382815181106117ec576117ec6134dc565b6020026020010151905061180a81600261210f90919063ffffffff16565b156118595760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117cf565b5060005b8151811015611022576000828281518110611883576118836134dc565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118c75750611923565b6118d2600282612131565b156119215760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611866565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119db5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906137b0565b15611ae4576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611af18160400151612153565b611afe81602001516121d2565b6114be81602001518260600151612320565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015611b9857600080fd5b505af1158015611bac573d6000803e3d6000fd5b5050505050565b6060600061193f83612364565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c4e82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c3291906137fc565b85608001516fffffffffffffffffffffffffffffffff166123bf565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c7b83610b6a565b611cbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f9565b611cc8826000611d5c565b67ffffffffffffffff83166000908152600760205260409020611ceb90836123e9565b611cf6816000611d5c565b67ffffffffffffffff83166000908152600760205260409020611d1c90600201826123e9565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d4f9392919061380f565b60405180910390a1505050565b815115611e235781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611db2575060408201516fffffffffffffffffffffffffffffffff16155b15611deb57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f99190613892565b80156116ee576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e5c575060208201516fffffffffffffffffffffffffffffffff1615155b156116ee57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f99190613892565b600061193f838361258b565b600061193f83836125da565b3373ffffffffffffffffffffffffffffffffffffffff821603611f2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fab81610b6a565b611fed576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561206c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209091906137b0565b6114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90600201827f00000000000000000000000000000000000000000000000000000000000000006126cd565b600061193f8373ffffffffffffffffffffffffffffffffffffffff84166125da565b600061193f8373ffffffffffffffffffffffffffffffffffffffff841661258b565b7f0000000000000000000000000000000000000000000000000000000000000000156114be57612184600282612a50565b6114be576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f9565b6121db81610b6a565b61221d576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ba91906138ce565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90827f00000000000000000000000000000000000000000000000000000000000000006126cd565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069d57602002820191906000526020600020905b8154815260200190600101908083116123a05750505050509050919050565b60006123de856123cf84866138eb565b6123d99087613902565b612a7f565b90505b949350505050565b815460009061241290700100000000000000000000000000000000900463ffffffff16426137fc565b905080156124b4576001830154835461245a916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166123bf565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546124da916fffffffffffffffffffffffffffffffff9081169116612a7f565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d4f908490613892565b60008181526001830160205260408120546125d2575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f3565b5060006105f3565b600081815260018301602052604081205480156126c35760006125fe6001836137fc565b8554909150600090612612906001906137fc565b9050808214612677576000866000018281548110612632576126326134dc565b9060005260206000200154905080876000018481548110612655576126556134dc565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268857612688613915565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f3565b60009150506105f3565b825474010000000000000000000000000000000000000000900460ff1615806126f4575081155b156126fe57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061274490700100000000000000000000000000000000900463ffffffff16426137fc565b905080156128045781831115612786576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127c09083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166123bf565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128bb5773ffffffffffffffffffffffffffffffffffffffff8416612863576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f9565b848310156129ce5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906128ff90826137fc565b612909878a6137fc565b6129139190613902565b61291d9190613944565b905073ffffffffffffffffffffffffffffffffffffffff8616612976576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f9565b6129d885846137fc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561193f565b6000818310612a8e578161193f565b5090919050565b508054612aa190613079565b6000825580601f10612ab1575050565b601f0160209004906000526020600020908101906114be91905b80821115612adf5760008155600101612acb565b5090565b600060208284031215612af557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461193f57600080fd5b803567ffffffffffffffff81168114612b3d57600080fd5b919050565b600060208284031215612b5457600080fd5b61193f82612b25565b6000815180845260005b81811015612b8357602081850181015186830182015201612b67565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061193f6020830184612b5d565b73ffffffffffffffffffffffffffffffffffffffff811681146114be57600080fd5b8035612b3d81612bd4565b600060208284031215612c1357600080fd5b813561193f81612bd4565b600060208284031215612c3057600080fd5b813567ffffffffffffffff811115612c4757600080fd5b8201610100818503121561193f57600080fd5b60008083601f840112612c6c57600080fd5b50813567ffffffffffffffff811115612c8457600080fd5b6020830191508360208260051b8501011115612c9f57600080fd5b9250929050565b60008060008060408587031215612cbc57600080fd5b843567ffffffffffffffff80821115612cd457600080fd5b612ce088838901612c5a565b90965094506020870135915080821115612cf957600080fd5b50612d0687828801612c5a565b95989497509550505050565b600080600060408486031215612d2757600080fd5b612d3084612b25565b9250602084013567ffffffffffffffff80821115612d4d57600080fd5b818601915086601f830112612d6157600080fd5b813581811115612d7057600080fd5b876020828501011115612d8257600080fd5b6020830194508093505050509250925092565b600060208284031215612da757600080fd5b813567ffffffffffffffff811115612dbe57600080fd5b820160a0818503121561193f57600080fd5b602081526000825160406020840152612dec6060840182612b5d565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e278282612b5d565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e7e57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612e4c565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e7e57835167ffffffffffffffff1683529284019291840191600101612ea6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612f1f57612f1f612ecc565b60405290565b60405160c0810167ffffffffffffffff81118282101715612f1f57612f1f612ecc565b80151581146114be57600080fd5b8035612b3d81612f48565b80356fffffffffffffffffffffffffffffffff81168114612b3d57600080fd5b600060608284031215612f9357600080fd5b6040516060810181811067ffffffffffffffff82111715612fb657612fb6612ecc565b6040529050808235612fc781612f48565b8152612fd560208401612f61565b6020820152612fe660408401612f61565b60408201525092915050565b600080600060e0848603121561300757600080fd5b61301084612b25565b925061301f8560208601612f81565b915061302e8560808601612f81565b90509250925092565b6000806020838503121561304a57600080fd5b823567ffffffffffffffff81111561306157600080fd5b61306d85828601612c5a565b90969095509350505050565b600181811c9082168061308d57607f821691505b6020821081036130c6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126130dd57600080fd5b813567ffffffffffffffff808211156130f8576130f8612ecc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561313e5761313e612ecc565b8160405283815286602085880101111561315757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561318a57600080fd5b613192612efb565b823567ffffffffffffffff808211156131aa57600080fd5b6131b6368387016130cc565b83526131c460208601612b25565b60208401526131d560408601612bf6565b6040840152606085013560608401526131f060808601612bf6565b608084015260a085013591508082111561320957600080fd5b613215368387016130cc565b60a084015260c085013591508082111561322e57600080fd5b61323a368387016130cc565b60c084015260e085013591508082111561325357600080fd5b50613260368286016130cc565b60e08301525092915050565b601f821115611022576000816000526020600020601f850160051c810160208610156132955750805b601f850160051c820191505b818110156132b4578281556001016132a1565b505050505050565b67ffffffffffffffff8311156132d4576132d4612ecc565b6132e8836132e28354613079565b8361326c565b6000601f84116001811461333a57600085156133045750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611bac565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156133895786850135825560209485019460019092019101613369565b50868210156133c4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133e96040830186612b5d565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561344c57600080fd5b60405160a0810167ffffffffffffffff828210818311171561347057613470612ecc565b81604052843591508082111561348557600080fd5b50613492368286016130cc565b8252506134a160208401612b25565b602082015260408301356134b481612bd4565b60408201526060838101359082015260808301356134d181612bd4565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261353f57600080fd5b9190910192915050565b6000610140823603121561355c57600080fd5b613564612f25565b61356d83612b25565b815261357b60208401612f56565b6020820152604083013567ffffffffffffffff8082111561359b57600080fd5b6135a7368387016130cc565b604084015260608501359150808211156135c057600080fd5b506135cd368286016130cc565b6060830152506135e03660808501612f81565b60808201526135f23660e08501612f81565b60a082015292915050565b815167ffffffffffffffff81111561361757613617612ecc565b61362b816136258454613079565b8461326c565b602080601f83116001811461367e57600084156136485750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556132b4565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156136cb578886015182559484019460019091019084016136ac565b508582101561370757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261373b81840187612b5d565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506137799050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e27565b6000602082840312156137c257600080fd5b815161193f81612f48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f3576105f36137cd565b67ffffffffffffffff8416815260e0810161385b60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526123e1565b606081016105f382848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156138e057600080fd5b815161193f81612bd4565b80820281158282048414176105f3576105f36137cd565b808201808211156105f3576105f36137cd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261397a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var BurnMintTokenPoolABI = BurnMintTokenPoolMetaData.ABI @@ -310,6 +310,28 @@ func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetCurrentOutboundRate return _BurnMintTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnMintTokenPool.CallOpts, remoteChainSelector) } +func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnMintTokenPool.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 (_BurnMintTokenPool *BurnMintTokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnMintTokenPool.Contract.GetRateLimitAdmin(&_BurnMintTokenPool.CallOpts) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnMintTokenPool.Contract.GetRateLimitAdmin(&_BurnMintTokenPool.CallOpts) +} + func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} err := _BurnMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) @@ -624,6 +646,18 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetChainRateLimite return _BurnMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.SetRateLimitAdmin(&_BurnMintTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.SetRateLimitAdmin(&_BurnMintTokenPool.TransactOpts, rateLimitAdmin) +} + func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) } @@ -2644,6 +2678,8 @@ type BurnMintTokenPoolInterface interface { GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2678,6 +2714,8 @@ type BurnMintTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/burn_mint_token_pool_and_proxy/burn_mint_token_pool_and_proxy.go b/core/gethwrappers/ccip/generated/burn_mint_token_pool_and_proxy/burn_mint_token_pool_and_proxy.go index b7ef3167646..4797421171c 100644 --- a/core/gethwrappers/ccip/generated/burn_mint_token_pool_and_proxy/burn_mint_token_pool_and_proxy.go +++ b/core/gethwrappers/ccip/generated/burn_mint_token_pool_and_proxy/burn_mint_token_pool_and_proxy.go @@ -82,8 +82,8 @@ type TokenPoolChainUpdate struct { } var BurnMintTokenPoolAndProxyMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":[],\"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\":\"contractIPoolPriorTo1_5\",\"name\":\"oldPool\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"LegacyPoolChanged\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"onRampAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"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\":[{\"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\":[{\"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\"},{\"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\":\"contractIPoolPriorTo1_5\",\"name\":\"prevPool\",\"type\":\"address\"}],\"name\":\"setPreviousPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b506040516200481e3803806200481e833981016040819052620000349162000554565b83838383838383833380600081620000935760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c657620000c6816200017e565b5050506001600160a01b0384161580620000e757506001600160a01b038116155b80620000fa57506001600160a01b038216155b1562000119576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016c576040805160008152602081019091526200016c908462000229565b505050505050505050505050620006b2565b336001600160a01b03821603620001d85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008a565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200024a576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002d55760008382815181106200026e576200026e62000664565b602090810291909101015190506200028860028262000386565b15620002cb576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200024d565b5060005b815181101562000381576000828281518110620002fa57620002fa62000664565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000326575062000378565b62000333600282620003a6565b1562000376576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d9565b505050565b60006200039d836001600160a01b038416620003bd565b90505b92915050565b60006200039d836001600160a01b038416620004c1565b60008181526001830160205260408120548015620004b6576000620003e46001836200067a565b8554909150600090620003fa906001906200067a565b9050818114620004665760008660000182815481106200041e576200041e62000664565b906000526020600020015490508087600001848154811062000444576200044462000664565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200047a576200047a6200069c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a0565b6000915050620003a0565b60008181526001830160205260408120546200050a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a0565b506000620003a0565b6001600160a01b03811681146200052957600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b80516200054f8162000513565b919050565b600080600080608085870312156200056b57600080fd5b8451620005788162000513565b602086810151919550906001600160401b03808211156200059857600080fd5b818801915088601f830112620005ad57600080fd5b815181811115620005c257620005c26200052c565b8060051b604051601f19603f83011681018181108582111715620005ea57620005ea6200052c565b60405291825284820192508381018501918b8311156200060957600080fd5b938501935b828510156200063257620006228562000542565b845293850193928501926200060e565b809850505050505050620006496040860162000542565b9150620006596060860162000542565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a057634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c0516140e862000736600039600081816104bc0152818161197001526123c2015260008181610496015281816117080152611c23015260008181610210015281816102650152818161071901528181610d040152818161162801528181611b4301528181611d290152818161235801526125ad01526140e86000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80639a4575b9116100f9578063c4bffe2b11610097578063db6327dc11610071578063db6327dc14610481578063dc0bd97114610494578063e0351e13146104ba578063f2fde38b146104e057600080fd5b8063c4bffe2b14610446578063c75eea9c1461045b578063cf7401f31461046e57600080fd5b8063af58d59f116100d3578063af58d59f14610393578063b0f479a114610402578063b794658014610420578063c0d786551461043357600080fd5b80639a4575b91461034b578063a7cd63b71461036b578063a8d87a3b1461038057600080fd5b806354c8a4f31161016657806383826b2b1161014057806383826b2b146102f45780638926f54f146103075780638da5cb5b1461031a5780639766b9321461033857600080fd5b806354c8a4f3146102c457806378a010b2146102d957806379ba5097146102ec57600080fd5b806321df0da71161019757806321df0da71461020e578063240028e81461025557806339077537146102a257600080fd5b806301ffc9a7146101be5780630a2fd493146101e6578063181f5a7714610206575b600080fd5b6101d16101cc36600461305a565b6104f3565b60405190151581526020015b60405180910390f35b6101f96101f43660046130b9565b6105d8565b6040516101dd9190613142565b6101f9610688565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101dd565b6101d1610263366004613182565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102b56102b036600461319f565b6106a4565b604051905181526020016101dd565b6102d76102d2366004613227565b610831565b005b6102d76102e7366004613293565b6108ac565b6102d7610a20565b6101d1610302366004613316565b610b1d565b6101d16103153660046130b9565b610bea565b60005473ffffffffffffffffffffffffffffffffffffffff16610230565b6102d7610346366004613182565b610c01565b61035e61035936600461334d565b610c90565b6040516101dd9190613388565b610373610e00565b6040516101dd91906133e8565b61023061038e3660046130b9565b503090565b6103a66103a13660046130b9565b610e11565b6040516101dd919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610230565b6101f961042e3660046130b9565b610ee6565b6102d7610441366004613182565b610f11565b61044e610fe5565b6040516101dd9190613442565b6103a66104693660046130b9565b61109d565b6102d761047c3660046135f9565b61116f565b6102d761048f36600461363e565b611187565b7f0000000000000000000000000000000000000000000000000000000000000000610230565b7f00000000000000000000000000000000000000000000000000000000000000006101d1565b6102d76104ee366004613182565b61160d565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061058657507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105d257507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061060390613680565b80601f016020809104026020016040519081016040528092919081815260200182805461062f90613680565b801561067c5780601f106106515761010080835404028352916020019161067c565b820191906000526020600020905b81548152906001019060200180831161065f57829003601f168201915b50505050509050919050565b6040518060600160405280602381526020016140b96023913981565b6040805160208101909152600081526106c46106bf8361376f565b611621565b60085473ffffffffffffffffffffffffffffffffffffffff1661078f576040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152606083013560248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906340c10f1990604401600060405180830381600087803b15801561077257600080fd5b505af1158015610786573d6000803e3d6000fd5b505050506107a0565b6107a061079b8361376f565b611852565b6107b06060830160408401613182565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081291815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108396118eb565b6108a68484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061196e92505050565b50505050565b6108b46118eb565b6108bd83610bea565b610904576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff83166000908152600760205260408120600401805461092b90613680565b80601f016020809104026020016040519081016040528092919081815260200182805461095790613680565b80156109a45780601f10610979576101008083540402835291602001916109a4565b820191906000526020600020905b81548152906001019060200180831161098757829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d38385836138b4565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a12939291906139ce565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610aa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108fb565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600073ffffffffffffffffffffffffffffffffffffffff8216301480610be35750600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86169281019290925273ffffffffffffffffffffffffffffffffffffffff848116602484015216906383826b2b90604401602060405180830381865afa158015610bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be39190613a32565b9392505050565b60006105d2600567ffffffffffffffff8416611b24565b610c096118eb565b6008805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f81accd0a7023865eaa51b3399dd0eafc488bf3ba238402911e1659cfe860f22891015b60405180910390a15050565b6040805180820190915260608082526020820152610cb5610cb083613a4f565b611b3c565b60085473ffffffffffffffffffffffffffffffffffffffff16610d7a576040517f42966c68000000000000000000000000000000000000000000000000000000008152606083013560048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015610d5d57600080fd5b505af1158015610d71573d6000803e3d6000fd5b50505050610d8b565b610d8b610d8683613a4f565b611d06565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610de584602001602081019061042e91906130b9565b81526040805160208181019092526000815291015292915050565b6060610e0c6002611e20565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105d290611e2d565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061060390613680565b610f196118eb565b73ffffffffffffffffffffffffffffffffffffffff8116610f66576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610c84565b60606000610ff36005611e20565b90506000815167ffffffffffffffff81111561101157611011613484565b60405190808252806020026020018201604052801561103a578160200160208202803683370190505b50905060005b82518110156110965782818151811061105b5761105b613af1565b602002602001015182828151811061107557611075613af1565b67ffffffffffffffff90921660209283029190910190910152600101611040565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105d290611e2d565b6111776118eb565b611182838383611edf565b505050565b61118f6118eb565b60005b818110156111825760008383838181106111ae576111ae613af1565b90506020028101906111c09190613b20565b6111c990613b5e565b90506111de8160800151826020015115611fc9565b6111f18160a00151826020015115611fc9565b8060200151156114ed5780516112139060059067ffffffffffffffff16612102565b6112585780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108fb565b604081015151158061126d5750606081015151155b156112a4576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906114859082613c12565b506060820151600582019061149a9082613c12565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506114e09493929190613d2c565b60405180910390a1611604565b80516115059060059067ffffffffffffffff1661210e565b61154a5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108fb565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115b3600483018261300c565b6115c160058301600061300c565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611192565b6116156118eb565b61161e8161211a565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146116b65760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108fb565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611764573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117889190613a32565b156117bf576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117cc816020015161220f565b60006117db82602001516105d8565b90508051600014806117ff575080805190602001208260a001518051906020012014155b1561183c578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108fb9190613142565b61184e82602001518360600151612335565b5050565b6008548151606083015160208401516040517f8627fad600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90941693638627fad6936118b69390923392600401613dc5565b600060405180830381600087803b1580156118d057600080fd5b505af11580156118e4573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461196c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108fb565b565b7f00000000000000000000000000000000000000000000000000000000000000006119c5576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611a5b5760008382815181106119e5576119e5613af1565b60200260200101519050611a0381600261237c90919063ffffffff16565b15611a525760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016119c8565b5060005b8151811015611182576000828281518110611a7c57611a7c613af1565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ac05750611b1c565b611acb60028261239e565b15611b1a5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611a5f565b60008181526001830160205260408120541515610be3565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611bd15760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108fb565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca39190613a32565b15611cda576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ce781604001516123c0565b611cf4816020015161243f565b61161e8160200151826060015161258d565b6008546060820151611d539173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116929116906125d1565b60085460408083015183516060850151602086015193517f9687544500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951694639687544594611dbb94939291600401613e26565b6000604051808303816000875af1158015611dda573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261184e9190810190613e86565b60606000610be38361265e565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611ebb82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611e9f9190613f23565b85608001516fffffffffffffffffffffffffffffffff166126b9565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611ee883610bea565b611f2a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108fb565b611f35826000611fc9565b67ffffffffffffffff83166000908152600760205260409020611f5890836126e3565b611f63816000611fc9565b67ffffffffffffffff83166000908152600760205260409020611f8990600201826126e3565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611fbc93929190613f36565b60405180910390a1505050565b8151156120905781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061201f575060408201516fffffffffffffffffffffffffffffffff16155b1561205857816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108fb9190613fb9565b801561184e576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff161515806120c9575060208201516fffffffffffffffffffffffffffffffff1615155b1561184e57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108fb9190613fb9565b6000610be38383612885565b6000610be383836128d4565b3373ffffffffffffffffffffffffffffffffffffffff821603612199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108fb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61221881610bea565b61225a576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108fb565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156122d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fd9190613a32565b61161e576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108fb565b67ffffffffffffffff8216600090815260076020526040902061184e90600201827f00000000000000000000000000000000000000000000000000000000000000006129c7565b6000610be38373ffffffffffffffffffffffffffffffffffffffff84166128d4565b6000610be38373ffffffffffffffffffffffffffffffffffffffff8416612885565b7f00000000000000000000000000000000000000000000000000000000000000001561161e576123f1600282612d4a565b61161e576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108fb565b61244881610bea565b61248a576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108fb565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125279190613ff5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461161e576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108fb565b67ffffffffffffffff8216600090815260076020526040902061184e90827f00000000000000000000000000000000000000000000000000000000000000006129c7565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611182908490612d79565b60608160000180548060200260200160405190810160405280929190818152602001828054801561067c57602002820191906000526020600020905b81548152602001906001019080831161269a5750505050509050919050565b60006126d8856126c98486614012565b6126d39087614029565b612e85565b90505b949350505050565b815460009061270c90700100000000000000000000000000000000900463ffffffff1642613f23565b905080156127ae5760018301548354612754916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166126b9565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546127d4916fffffffffffffffffffffffffffffffff9081169116612e85565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611fbc908490613fb9565b60008181526001830160205260408120546128cc575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d2565b5060006105d2565b600081815260018301602052604081205480156129bd5760006128f8600183613f23565b855490915060009061290c90600190613f23565b905081811461297157600086600001828154811061292c5761292c613af1565b906000526020600020015490508087600001848154811061294f5761294f613af1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806129825761298261403c565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d2565b60009150506105d2565b825474010000000000000000000000000000000000000000900460ff1615806129ee575081155b156129f857505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612a3e90700100000000000000000000000000000000900463ffffffff1642613f23565b90508015612afe5781831115612a80576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612aba9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166126b9565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612bb55773ffffffffffffffffffffffffffffffffffffffff8416612b5d576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108fb565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108fb565b84831015612cc85760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612bf99082613f23565b612c03878a613f23565b612c0d9190614029565b612c17919061406b565b905073ffffffffffffffffffffffffffffffffffffffff8616612c70576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108fb565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108fb565b612cd28584613f23565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610be3565b6000612ddb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612e9b9092919063ffffffff16565b8051909150156111825780806020019051810190612df99190613a32565b611182576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108fb565b6000818310612e945781610be3565b5090919050565b60606126db8484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051612ecf91906140a6565b60006040518083038185875af1925050503d8060008114612f0c576040519150601f19603f3d011682016040523d82523d6000602084013e612f11565b606091505b5091509150612f2287838387612f2d565b979650505050505050565b60608315612fc3578251600003612fbc5773ffffffffffffffffffffffffffffffffffffffff85163b612fbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108fb565b50816126db565b6126db8383815115612fd85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fb9190613142565b50805461301890613680565b6000825580601f10613028575050565b601f01602090049060005260206000209081019061161e91905b808211156130565760008155600101613042565b5090565b60006020828403121561306c57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610be357600080fd5b803567ffffffffffffffff811681146130b457600080fd5b919050565b6000602082840312156130cb57600080fd5b610be38261309c565b60005b838110156130ef5781810151838201526020016130d7565b50506000910152565b600081518084526131108160208601602086016130d4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610be360208301846130f8565b73ffffffffffffffffffffffffffffffffffffffff8116811461161e57600080fd5b80356130b481613155565b60006020828403121561319457600080fd5b8135610be381613155565b6000602082840312156131b157600080fd5b813567ffffffffffffffff8111156131c857600080fd5b82016101008185031215610be357600080fd5b60008083601f8401126131ed57600080fd5b50813567ffffffffffffffff81111561320557600080fd5b6020830191508360208260051b850101111561322057600080fd5b9250929050565b6000806000806040858703121561323d57600080fd5b843567ffffffffffffffff8082111561325557600080fd5b613261888389016131db565b9096509450602087013591508082111561327a57600080fd5b50613287878288016131db565b95989497509550505050565b6000806000604084860312156132a857600080fd5b6132b18461309c565b9250602084013567ffffffffffffffff808211156132ce57600080fd5b818601915086601f8301126132e257600080fd5b8135818111156132f157600080fd5b87602082850101111561330357600080fd5b6020830194508093505050509250925092565b6000806040838503121561332957600080fd5b6133328361309c565b9150602083013561334281613155565b809150509250929050565b60006020828403121561335f57600080fd5b813567ffffffffffffffff81111561337657600080fd5b820160a08185031215610be357600080fd5b6020815260008251604060208401526133a460608401826130f8565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526133df82826130f8565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561343657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613404565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561343657835167ffffffffffffffff168352928401929184019160010161345e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156134d7576134d7613484565b60405290565b60405160c0810167ffffffffffffffff811182821017156134d7576134d7613484565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561354757613547613484565b604052919050565b801515811461161e57600080fd5b80356130b48161354f565b80356fffffffffffffffffffffffffffffffff811681146130b457600080fd5b60006060828403121561359a57600080fd5b6040516060810181811067ffffffffffffffff821117156135bd576135bd613484565b60405290508082356135ce8161354f565b81526135dc60208401613568565b60208201526135ed60408401613568565b60408201525092915050565b600080600060e0848603121561360e57600080fd5b6136178461309c565b92506136268560208601613588565b91506136358560808601613588565b90509250925092565b6000806020838503121561365157600080fd5b823567ffffffffffffffff81111561366857600080fd5b613674858286016131db565b90969095509350505050565b600181811c9082168061369457607f821691505b6020821081036136cd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600067ffffffffffffffff8211156136ed576136ed613484565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261372a57600080fd5b813561373d613738826136d3565b613500565b81815284602083860101111561375257600080fd5b816020850160208301376000918101602001919091529392505050565b6000610100823603121561378257600080fd5b61378a6134b3565b823567ffffffffffffffff808211156137a257600080fd5b6137ae36838701613719565b83526137bc6020860161309c565b60208401526137cd60408601613177565b6040840152606085013560608401526137e860808601613177565b608084015260a085013591508082111561380157600080fd5b61380d36838701613719565b60a084015260c085013591508082111561382657600080fd5b61383236838701613719565b60c084015260e085013591508082111561384b57600080fd5b5061385836828601613719565b60e08301525092915050565b601f821115611182576000816000526020600020601f850160051c8101602086101561388d5750805b601f850160051c820191505b818110156138ac57828155600101613899565b505050505050565b67ffffffffffffffff8311156138cc576138cc613484565b6138e0836138da8354613680565b83613864565b6000601f84116001811461393257600085156138fc5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556118e4565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156139815786850135825560209485019460019092019101613961565b50868210156139bc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006139e160408301866130f8565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060208284031215613a4457600080fd5b8151610be38161354f565b600060a08236031215613a6157600080fd5b60405160a0810167ffffffffffffffff8282108183111715613a8557613a85613484565b816040528435915080821115613a9a57600080fd5b50613aa736828601613719565b825250613ab66020840161309c565b60208201526040830135613ac981613155565b6040820152606083810135908201526080830135613ae681613155565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613b5457600080fd5b9190910192915050565b60006101408236031215613b7157600080fd5b613b796134dd565b613b828361309c565b8152613b906020840161355d565b6020820152604083013567ffffffffffffffff80821115613bb057600080fd5b613bbc36838701613719565b60408401526060850135915080821115613bd557600080fd5b50613be236828601613719565b606083015250613bf53660808501613588565b6080820152613c073660e08501613588565b60a082015292915050565b815167ffffffffffffffff811115613c2c57613c2c613484565b613c4081613c3a8454613680565b84613864565b602080601f831160018114613c935760008415613c5d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556138ac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613ce057888601518255948401946001909101908401613cc1565b5085821015613d1c57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613d50818401876130f8565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613d8e9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526133df565b60a081526000613dd860a08301876130f8565b73ffffffffffffffffffffffffffffffffffffffff8616602084015284604084015267ffffffffffffffff841660608401528281036080840152600081526020810191505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8516815260a060208201526000613e5560a08301866130f8565b60408301949094525067ffffffffffffffff9190911660608201528082036080909101526000815260200192915050565b600060208284031215613e9857600080fd5b815167ffffffffffffffff811115613eaf57600080fd5b8201601f81018413613ec057600080fd5b8051613ece613738826136d3565b818152856020838501011115613ee357600080fd5b6133df8260208301602086016130d4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105d2576105d2613ef4565b67ffffffffffffffff8416815260e08101613f8260208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526126db565b606081016105d282848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561400757600080fd5b8151610be381613155565b80820281158282048414176105d2576105d2613ef4565b808201808211156105d2576105d2613ef4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000826140a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613b548184602087016130d456fe4275726e4d696e74546f6b656e506f6f6c416e6450726f787920312e352e302d646576a164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"oldPool\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"LegacyPoolChanged\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"onRampAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPreviousPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"getRemotePool\",\"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\":[{\"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\":[{\"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\"},{\"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\":\"contractIPoolPriorTo1_5\",\"name\":\"prevPool\",\"type\":\"address\"}],\"name\":\"setPreviousPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b506040516200497338038062004973833981016040819052620000349162000554565b83838383838383833380600081620000935760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c657620000c6816200017e565b5050506001600160a01b0384161580620000e757506001600160a01b038116155b80620000fa57506001600160a01b038216155b1562000119576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016c576040805160008152602081019091526200016c908462000229565b505050505050505050505050620006b2565b336001600160a01b03821603620001d85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008a565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200024a576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002d55760008382815181106200026e576200026e62000664565b602090810291909101015190506200028860028262000386565b15620002cb576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200024d565b5060005b815181101562000381576000828281518110620002fa57620002fa62000664565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000326575062000378565b62000333600282620003a6565b1562000376576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d9565b505050565b60006200039d836001600160a01b038416620003bd565b90505b92915050565b60006200039d836001600160a01b038416620004c1565b60008181526001830160205260408120548015620004b6576000620003e46001836200067a565b8554909150600090620003fa906001906200067a565b9050808214620004665760008660000182815481106200041e576200041e62000664565b906000526020600020015490508087600001848154811062000444576200044462000664565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200047a576200047a6200069c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a0565b6000915050620003a0565b60008181526001830160205260408120546200050a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a0565b506000620003a0565b6001600160a01b03811681146200052957600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b80516200054f8162000513565b919050565b600080600080608085870312156200056b57600080fd5b8451620005788162000513565b602086810151919550906001600160401b03808211156200059857600080fd5b818801915088601f830112620005ad57600080fd5b815181811115620005c257620005c26200052c565b8060051b604051601f19603f83011681018181108582111715620005ea57620005ea6200052c565b60405291825284820192508381018501918b8311156200060957600080fd5b938501935b828510156200063257620006228562000542565b845293850193928501926200060e565b809850505050505050620006496040860162000542565b9150620006596060860162000542565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a057634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161423d620007366000396000818161056001528181611ae8015261253a01526000818161053a0152818161187b0152611d9b015260008181610265015281816102ba0152818161078001528181610e060152818161179b01528181611cbb01528181611ea1015281816124d00152612725015261423d6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063db6327dc11610071578063db6327dc14610525578063dc0bd97114610538578063e0351e131461055e578063f2fde38b1461058457600080fd5b8063c0d78655146104d7578063c4bffe2b146104ea578063c75eea9c146104ff578063cf7401f31461051257600080fd5b8063a8d87a3b116100de578063a8d87a3b14610424578063af58d59f14610437578063b0f479a1146104a6578063b7946580146104c457600080fd5b80639a4575b9146103d1578063a2b261d8146103f1578063a7cd63b71461040f57600080fd5b80636d3d1a581161017c57806383826b2b1161014b57806383826b2b1461037a5780638926f54f1461038d5780638da5cb5b146103a05780639766b932146103be57600080fd5b80636d3d1a581461032e57806378a010b21461034c57806379ba50971461035f5780637d54534e1461036757600080fd5b806321df0da7116101b857806321df0da714610263578063240028e8146102aa57806339077537146102f757806354c8a4f31461031957600080fd5b806301ffc9a7146101df5780630a2fd49314610207578063181f5a7714610227575b600080fd5b6101f26101ed3660046131d2565b610597565b60405190151581526020015b60405180910390f35b61021a610215366004613231565b61067c565b6040516101fe91906132ba565b61021a6040518060400160405280601f81526020017f4275726e4d696e74546f6b656e506f6f6c416e6450726f787920312e352e300081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102b83660046132fa565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61030a610305366004613317565b61072c565b604051905181526020016101fe565b61032c61032736600461339f565b6108e4565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610285565b61032c61035a36600461340b565b61095f565b61032c610ad3565b61032c6103753660046132fa565b610bd0565b6101f261038836600461348e565b610c1f565b6101f261039b366004613231565b610cec565b60005473ffffffffffffffffffffffffffffffffffffffff16610285565b61032c6103cc3660046132fa565b610d03565b6103e46103df3660046134c5565b610d92565b6040516101fe9190613500565b60095473ffffffffffffffffffffffffffffffffffffffff16610285565b610417610f02565b6040516101fe9190613560565b610285610432366004613231565b503090565b61044a610445366004613231565b610f13565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610285565b61021a6104d2366004613231565b610fe8565b61032c6104e53660046132fa565b611013565b6104f26110e7565b6040516101fe91906135ba565b61044a61050d366004613231565b61119f565b61032c610520366004613771565b611271565b61032c6105333660046137b6565b6112fa565b7f0000000000000000000000000000000000000000000000000000000000000000610285565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61032c6105923660046132fa565b611780565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106a7906137f8565b80601f01602080910402602001604051908101604052809291908181526020018280546106d3906137f8565b80156107205780601f106106f557610100808354040283529160200191610720565b820191906000526020600020905b81548152906001019060200180831161070357829003601f168201915b50505050509050919050565b60408051602081019091526000815261074c610747836138e7565b611794565b60095473ffffffffffffffffffffffffffffffffffffffff166108425773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107b560608501604086016132fa565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561082557600080fd5b505af1158015610839573d6000803e3d6000fd5b50505050610853565b61085361084e836138e7565b6119c5565b61086360608301604084016132fa565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f084606001356040516108c591815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108ec611a63565b61095984848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ae692505050565b50505050565b610967611a63565b61097083610cec565b6109b7576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109de906137f8565b80601f0160208091040260200160405190810160405280929190818152602001828054610a0a906137f8565b8015610a575780601f10610a2c57610100808354040283529160200191610a57565b820191906000526020600020905b815481529060010190602001808311610a3a57829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610a86838583613a2c565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610ac593929190613b46565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016109ae565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd8611a63565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600073ffffffffffffffffffffffffffffffffffffffff8216301480610ce55750600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86169281019290925273ffffffffffffffffffffffffffffffffffffffff848116602484015216906383826b2b90604401602060405180830381865afa158015610cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce59190613baa565b9392505050565b6000610676600567ffffffffffffffff8416611c9c565b610d0b611a63565b6009805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f81accd0a7023865eaa51b3399dd0eafc488bf3ba238402911e1659cfe860f22891015b60405180910390a15050565b6040805180820190915260608082526020820152610db7610db283613bc7565b611cb4565b60095473ffffffffffffffffffffffffffffffffffffffff16610e7c576040517f42966c68000000000000000000000000000000000000000000000000000000008152606083013560048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015610e5f57600080fd5b505af1158015610e73573d6000803e3d6000fd5b50505050610e8d565b610e8d610e8883613bc7565b611e7e565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610ee78460200160208101906104d29190613231565b81526040805160208181019092526000815291015292915050565b6060610f0e6002611f98565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067690611fa5565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106a7906137f8565b61101b611a63565b73ffffffffffffffffffffffffffffffffffffffff8116611068576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610d86565b606060006110f56005611f98565b90506000815167ffffffffffffffff811115611113576111136135fc565b60405190808252806020026020018201604052801561113c578160200160208202803683370190505b50905060005b82518110156111985782818151811061115d5761115d613c69565b602002602001015182828151811061117757611177613c69565b67ffffffffffffffff90921660209283029190910190910152600101611142565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067690611fa5565b60085473ffffffffffffffffffffffffffffffffffffffff1633148015906112b1575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156112ea576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016109ae565b6112f5838383612057565b505050565b611302611a63565b60005b818110156112f557600083838381811061132157611321613c69565b90506020028101906113339190613c98565b61133c90613cd6565b90506113518160800151826020015115612141565b6113648160a00151826020015115612141565b8060200151156116605780516113869060059067ffffffffffffffff1661227a565b6113cb5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016109ae565b60408101515115806113e05750606081015151155b15611417576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906115f89082613d8a565b506060820151600582019061160d9082613d8a565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506116539493929190613ea4565b60405180910390a1611777565b80516116789060059067ffffffffffffffff16612286565b6116bd5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016109ae565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906117266004830182613184565b611734600583016000613184565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611305565b611788611a63565b61179181612292565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146118295760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016109ae565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa1580156118d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fb9190613baa565b15611932576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61193f8160200151612387565b600061194e826020015161067c565b9050805160001480611972575080805190602001208260a001518051906020012014155b156119af578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109ae91906132ba565b6119c1826020015183606001516124ad565b5050565b60095481516040808401516060850151602086015192517f8627fad600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951694638627fad694611a2e9490939291600401613f3d565b600060405180830381600087803b158015611a4857600080fd5b505af1158015611a5c573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016109ae565b565b7f0000000000000000000000000000000000000000000000000000000000000000611b3d576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611bd3576000838281518110611b5d57611b5d613c69565b60200260200101519050611b7b8160026124f490919063ffffffff16565b15611bca5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611b40565b5060005b81518110156112f5576000828281518110611bf457611bf4613c69565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611c385750611c94565b611c43600282612516565b15611c925760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611bd7565b60008181526001830160205260408120541515610ce5565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611d495760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016109ae565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1b9190613baa565b15611e52576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e5f8160400151612538565b611e6c81602001516125b7565b61179181602001518260600151612705565b6009546060820151611ecb9173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692911690612749565b60095460408083015183516060850151602086015193517f9687544500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951694639687544594611f3394939291600401613f9e565b6000604051808303816000875af1158015611f52573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526119c19190810190613ffe565b60606000610ce5836127d6565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261203382606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642612017919061409b565b85608001516fffffffffffffffffffffffffffffffff16612831565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61206083610cec565b6120a2576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016109ae565b6120ad826000612141565b67ffffffffffffffff831660009081526007602052604090206120d0908361285b565b6120db816000612141565b67ffffffffffffffff83166000908152600760205260409020612101906002018261285b565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051612134939291906140ae565b60405180910390a1505050565b8151156122085781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612197575060408201516fffffffffffffffffffffffffffffffff16155b156121d057816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109ae9190614131565b80156119c1576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612241575060208201516fffffffffffffffffffffffffffffffff1615155b156119c157816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109ae9190614131565b6000610ce583836129fd565b6000610ce58383612a4c565b3373ffffffffffffffffffffffffffffffffffffffff821603612311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016109ae565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61239081610cec565b6123d2576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016109ae565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612451573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124759190613baa565b611791576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016109ae565b67ffffffffffffffff821660009081526007602052604090206119c190600201827f0000000000000000000000000000000000000000000000000000000000000000612b3f565b6000610ce58373ffffffffffffffffffffffffffffffffffffffff8416612a4c565b6000610ce58373ffffffffffffffffffffffffffffffffffffffff84166129fd565b7f00000000000000000000000000000000000000000000000000000000000000001561179157612569600282612ec2565b611791576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016109ae565b6125c081610cec565b612602576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016109ae565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561267b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269f919061416d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611791576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016109ae565b67ffffffffffffffff821660009081526007602052604090206119c190827f0000000000000000000000000000000000000000000000000000000000000000612b3f565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526112f5908490612ef1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561072057602002820191906000526020600020905b8154815260200190600101908083116128125750505050509050919050565b600061285085612841848661418a565b61284b90876141a1565b612ffd565b90505b949350505050565b815460009061288490700100000000000000000000000000000000900463ffffffff164261409b565b9050801561292657600183015483546128cc916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612831565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461294c916fffffffffffffffffffffffffffffffff9081169116612ffd565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612134908490614131565b6000818152600183016020526040812054612a4457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610676565b506000610676565b60008181526001830160205260408120548015612b35576000612a7060018361409b565b8554909150600090612a849060019061409b565b9050808214612ae9576000866000018281548110612aa457612aa4613c69565b9060005260206000200154905080876000018481548110612ac757612ac7613c69565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612afa57612afa6141b4565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610676565b6000915050610676565b825474010000000000000000000000000000000000000000900460ff161580612b66575081155b15612b7057505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612bb690700100000000000000000000000000000000900463ffffffff164261409b565b90508015612c765781831115612bf8576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612c329083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612831565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612d2d5773ffffffffffffffffffffffffffffffffffffffff8416612cd5576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016109ae565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016109ae565b84831015612e405760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612d71908261409b565b612d7b878a61409b565b612d8591906141a1565b612d8f91906141e3565b905073ffffffffffffffffffffffffffffffffffffffff8616612de8576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016109ae565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016109ae565b612e4a858461409b565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610ce5565b6000612f53826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130139092919063ffffffff16565b8051909150156112f55780806020019051810190612f719190613baa565b6112f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016109ae565b600081831061300c5781610ce5565b5090919050565b60606128538484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051613047919061421e565b60006040518083038185875af1925050503d8060008114613084576040519150601f19603f3d011682016040523d82523d6000602084013e613089565b606091505b509150915061309a878383876130a5565b979650505050505050565b6060831561313b5782516000036131345773ffffffffffffffffffffffffffffffffffffffff85163b613134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109ae565b5081612853565b61285383838151156131505781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae91906132ba565b508054613190906137f8565b6000825580601f106131a0575050565b601f01602090049060005260206000209081019061179191905b808211156131ce57600081556001016131ba565b5090565b6000602082840312156131e457600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610ce557600080fd5b803567ffffffffffffffff8116811461322c57600080fd5b919050565b60006020828403121561324357600080fd5b610ce582613214565b60005b8381101561326757818101518382015260200161324f565b50506000910152565b6000815180845261328881602086016020860161324c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ce56020830184613270565b73ffffffffffffffffffffffffffffffffffffffff8116811461179157600080fd5b803561322c816132cd565b60006020828403121561330c57600080fd5b8135610ce5816132cd565b60006020828403121561332957600080fd5b813567ffffffffffffffff81111561334057600080fd5b82016101008185031215610ce557600080fd5b60008083601f84011261336557600080fd5b50813567ffffffffffffffff81111561337d57600080fd5b6020830191508360208260051b850101111561339857600080fd5b9250929050565b600080600080604085870312156133b557600080fd5b843567ffffffffffffffff808211156133cd57600080fd5b6133d988838901613353565b909650945060208701359150808211156133f257600080fd5b506133ff87828801613353565b95989497509550505050565b60008060006040848603121561342057600080fd5b61342984613214565b9250602084013567ffffffffffffffff8082111561344657600080fd5b818601915086601f83011261345a57600080fd5b81358181111561346957600080fd5b87602082850101111561347b57600080fd5b6020830194508093505050509250925092565b600080604083850312156134a157600080fd5b6134aa83613214565b915060208301356134ba816132cd565b809150509250929050565b6000602082840312156134d757600080fd5b813567ffffffffffffffff8111156134ee57600080fd5b820160a08185031215610ce557600080fd5b60208152600082516040602084015261351c6060840182613270565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526135578282613270565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156135ae57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161357c565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156135ae57835167ffffffffffffffff16835292840192918401916001016135d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff8111828210171561364f5761364f6135fc565b60405290565b60405160c0810167ffffffffffffffff8111828210171561364f5761364f6135fc565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136bf576136bf6135fc565b604052919050565b801515811461179157600080fd5b803561322c816136c7565b80356fffffffffffffffffffffffffffffffff8116811461322c57600080fd5b60006060828403121561371257600080fd5b6040516060810181811067ffffffffffffffff82111715613735576137356135fc565b6040529050808235613746816136c7565b8152613754602084016136e0565b6020820152613765604084016136e0565b60408201525092915050565b600080600060e0848603121561378657600080fd5b61378f84613214565b925061379e8560208601613700565b91506137ad8560808601613700565b90509250925092565b600080602083850312156137c957600080fd5b823567ffffffffffffffff8111156137e057600080fd5b6137ec85828601613353565b90969095509350505050565b600181811c9082168061380c57607f821691505b602082108103613845577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600067ffffffffffffffff821115613865576138656135fc565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126138a257600080fd5b81356138b56138b08261384b565b613678565b8181528460208386010111156138ca57600080fd5b816020850160208301376000918101602001919091529392505050565b600061010082360312156138fa57600080fd5b61390261362b565b823567ffffffffffffffff8082111561391a57600080fd5b61392636838701613891565b835261393460208601613214565b6020840152613945604086016132ef565b604084015260608501356060840152613960608086016132ef565b608084015260a085013591508082111561397957600080fd5b61398536838701613891565b60a084015260c085013591508082111561399e57600080fd5b6139aa36838701613891565b60c084015260e08501359150808211156139c357600080fd5b506139d036828601613891565b60e08301525092915050565b601f8211156112f5576000816000526020600020601f850160051c81016020861015613a055750805b601f850160051c820191505b81811015613a2457828155600101613a11565b505050505050565b67ffffffffffffffff831115613a4457613a446135fc565b613a5883613a5283546137f8565b836139dc565b6000601f841160018114613aaa5760008515613a745750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611a5c565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613af95786850135825560209485019460019092019101613ad9565b5086821015613b34577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b604081526000613b596040830186613270565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060208284031215613bbc57600080fd5b8151610ce5816136c7565b600060a08236031215613bd957600080fd5b60405160a0810167ffffffffffffffff8282108183111715613bfd57613bfd6135fc565b816040528435915080821115613c1257600080fd5b50613c1f36828601613891565b825250613c2e60208401613214565b60208201526040830135613c41816132cd565b6040820152606083810135908201526080830135613c5e816132cd565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613ccc57600080fd5b9190910192915050565b60006101408236031215613ce957600080fd5b613cf1613655565b613cfa83613214565b8152613d08602084016136d5565b6020820152604083013567ffffffffffffffff80821115613d2857600080fd5b613d3436838701613891565b60408401526060850135915080821115613d4d57600080fd5b50613d5a36828601613891565b606083015250613d6d3660808501613700565b6080820152613d7f3660e08501613700565b60a082015292915050565b815167ffffffffffffffff811115613da457613da46135fc565b613db881613db284546137f8565b846139dc565b602080601f831160018114613e0b5760008415613dd55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613a24565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5857888601518255948401946001909101908401613e39565b5085821015613e9457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ec881840187613270565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f069050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613557565b60a081526000613f5060a0830187613270565b73ffffffffffffffffffffffffffffffffffffffff8616602084015284604084015267ffffffffffffffff841660608401528281036080840152600081526020810191505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8516815260a060208201526000613fcd60a0830186613270565b60408301949094525067ffffffffffffffff9190911660608201528082036080909101526000815260200192915050565b60006020828403121561401057600080fd5b815167ffffffffffffffff81111561402757600080fd5b8201601f8101841361403857600080fd5b80516140466138b08261384b565b81815285602083850101111561405b57600080fd5b61355782602083016020860161324c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106765761067661406c565b67ffffffffffffffff8416815260e081016140fa60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612853565b6060810161067682848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561417f57600080fd5b8151610ce5816132cd565b80820281158282048414176106765761067661406c565b808201808211156106765761067661406c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614219577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613ccc81846020870161324c56fea164736f6c6343000818000a", } var BurnMintTokenPoolAndProxyABI = BurnMintTokenPoolAndProxyMetaData.ABI @@ -332,6 +332,50 @@ func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyCallerSession) GetOnR return _BurnMintTokenPoolAndProxy.Contract.GetOnRamp(&_BurnMintTokenPoolAndProxy.CallOpts, arg0) } +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyCaller) GetPreviousPool(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnMintTokenPoolAndProxy.contract.Call(opts, &out, "getPreviousPool") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxySession) GetPreviousPool() (common.Address, error) { + return _BurnMintTokenPoolAndProxy.Contract.GetPreviousPool(&_BurnMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyCallerSession) GetPreviousPool() (common.Address, error) { + return _BurnMintTokenPoolAndProxy.Contract.GetPreviousPool(&_BurnMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnMintTokenPoolAndProxy.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 (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxySession) GetRateLimitAdmin() (common.Address, error) { + return _BurnMintTokenPoolAndProxy.Contract.GetRateLimitAdmin(&_BurnMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnMintTokenPoolAndProxy.Contract.GetRateLimitAdmin(&_BurnMintTokenPoolAndProxy.CallOpts) +} + func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} err := _BurnMintTokenPoolAndProxy.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) @@ -680,6 +724,18 @@ func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyTransactorSession) Se return _BurnMintTokenPoolAndProxy.Contract.SetPreviousPool(&_BurnMintTokenPoolAndProxy.TransactOpts, prevPool) } +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnMintTokenPoolAndProxy.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxySession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnMintTokenPoolAndProxy.Contract.SetRateLimitAdmin(&_BurnMintTokenPoolAndProxy.TransactOpts, rateLimitAdmin) +} + +func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnMintTokenPoolAndProxy.Contract.SetRateLimitAdmin(&_BurnMintTokenPoolAndProxy.TransactOpts, rateLimitAdmin) +} + func (_BurnMintTokenPoolAndProxy *BurnMintTokenPoolAndProxyTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { return _BurnMintTokenPoolAndProxy.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) } @@ -2826,6 +2882,10 @@ type BurnMintTokenPoolAndProxyInterface interface { GetOnRamp(opts *bind.CallOpts, arg0 uint64) (common.Address, error) + GetPreviousPool(opts *bind.CallOpts) (common.Address, error) + + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2864,6 +2924,8 @@ type BurnMintTokenPoolAndProxyInterface interface { SetPreviousPool(opts *bind.TransactOpts, prevPool common.Address) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_rebasing_token_pool/burn_with_from_mint_rebasing_token_pool.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_rebasing_token_pool/burn_with_from_mint_rebasing_token_pool.go new file mode 100644 index 00000000000..899d3cd65de --- /dev/null +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_rebasing_token_pool/burn_with_from_mint_rebasing_token_pool.go @@ -0,0 +1,2818 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package burn_with_from_mint_rebasing_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 + Allowed bool + RemotePoolAddress []byte + RemoteTokenAddress []byte + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig +} + +var BurnWithFromMintRebasingTokenPoolMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountBurned\",\"type\":\"uint256\"}],\"name\":\"NegativeMintAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b5060405162004742380380620047428339810160408190526200003491620008c8565b83838383838383833380600081620000935760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c657620000c68162000197565b5050506001600160a01b0384161580620000e757506001600160a01b038116155b80620000fa57506001600160a01b038216155b1562000119576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016c576040805160008152602081019091526200016c908462000242565b5062000189925050506001600160a01b038516306000196200039f565b505050505050505062000b04565b336001600160a01b03821603620001f15760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008a565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000263576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002ee576000838281518110620002875762000287620009d8565b60209081029190910101519050620002a160028262000485565b15620002e4576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000266565b5060005b81518110156200039a576000828281518110620003135762000313620009d8565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f575062000391565b6200034c600282620004a5565b156200038f576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002f2565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004179190620009ee565b62000423919062000a1e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047f91869190620004bc16565b50505050565b60006200049c836001600160a01b0384166200058d565b90505b92915050565b60006200049c836001600160a01b03841662000691565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200050b906001600160a01b038516908490620006e3565b8051909150156200039a57808060200190518101906200052c919062000a34565b6200039a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200008a565b6000818152600183016020526040812054801562000686576000620005b460018362000a5f565b8554909150600090620005ca9060019062000a5f565b905080821462000636576000866000018281548110620005ee57620005ee620009d8565b9060005260206000200154905080876000018481548110620006145762000614620009d8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200064a576200064a62000a75565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200049f565b60009150506200049f565b6000818152600183016020526040812054620006da575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200049f565b5060006200049f565b6060620006f48484600085620006fc565b949350505050565b6060824710156200075f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200008a565b600080866001600160a01b031685876040516200077d919062000ab1565b60006040518083038185875af1925050503d8060008114620007bc576040519150601f19603f3d011682016040523d82523d6000602084013e620007c1565b606091505b509092509050620007d587838387620007e0565b979650505050505050565b60608315620008545782516000036200084c576001600160a01b0385163b6200084c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200008a565b5081620006f4565b620006f483838151156200086b5781518083602001fd5b8060405162461bcd60e51b81526004016200008a919062000acf565b6001600160a01b03811681146200089d57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008c38162000887565b919050565b60008060008060808587031215620008df57600080fd5b8451620008ec8162000887565b602086810151919550906001600160401b03808211156200090c57600080fd5b818801915088601f8301126200092157600080fd5b815181811115620009365762000936620008a0565b8060051b604051601f19603f830116810181811085821117156200095e576200095e620008a0565b60405291825284820192508381018501918b8311156200097d57600080fd5b938501935b82851015620009a6576200099685620008b6565b8452938501939285019262000982565b809850505050505050620009bd60408601620008b6565b9150620009cd60608601620008b6565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a0157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200049f576200049f62000a08565b60006020828403121562000a4757600080fd5b8151801515811462000a5857600080fd5b9392505050565b818103818111156200049f576200049f62000a08565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa857818101518382015260200162000a8e565b50506000910152565b6000825162000ac581846020870162000a8b565b9190910192915050565b602081526000825180602084015262000af081604085016020870162000a8b565b601f01601f19169190910160400192915050565b60805160a05160c051613bb362000b8f600039600081816104a901528181611958015261233c015260008181610483015281816117890152611c0e0152600081816102050152818161025a015281816106ca015281816107a50152818161087b015281816116a901528181611b2e01528181611d26015281816122d201526125270152613bb36000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc1461046e578063dc0bd97114610481578063e0351e13146104a7578063f2fde38b146104cd57600080fd5b8063c4bffe2b14610433578063c75eea9c14610448578063cf7401f31461045b57600080fd5b8063b0f479a1116100c8578063b0f479a1146103ef578063b79465801461040d578063c0d786551461042057600080fd5b80639a4575b91461034b578063a7cd63b71461036b578063af58d59f1461038057600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146102ff5780637d54534e146103075780638926f54f1461031a5780638da5cb5b1461032d57600080fd5b806354c8a4f3146102b95780636d3d1a58146102ce57806378a010b2146102ec57600080fd5b806321df0da71161018c57806321df0da714610203578063240028e81461024a578063390775371461029757600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612cca565b6104e0565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612d29565b6105c5565b6040516101d29190612da8565b6101ee610675565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c6610258366004612de8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102aa6102a5366004612e05565b610691565b604051905181526020016101d2565b6102cc6102c7366004612e8d565b610a15565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610225565b6102cc6102fa366004612ef9565b610a90565b6102cc610bff565b6102cc610315366004612de8565b610cfc565b6101c6610328366004612d29565b610d4b565b60005473ffffffffffffffffffffffffffffffffffffffff16610225565b61035e610359366004612f7c565b610d62565b6040516101d29190612fb7565b610373610e09565b6040516101d29190613017565b61039361038e366004612d29565b610e1a565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610225565b6101ee61041b366004612d29565b610eef565b6102cc61042e366004612de8565b610f1a565b61043b610ff5565b6040516101d29190613071565b610393610456366004612d29565b6110ad565b6102cc6104693660046131d9565b61117f565b6102cc61047c36600461321e565b611208565b7f0000000000000000000000000000000000000000000000000000000000000000610225565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b6102cc6104db366004612de8565b61168e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061057357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105bf57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906105f090613260565b80601f016020809104026020016040519081016040528092919081815260200182805461061c90613260565b80156106695780601f1061063e57610100808354040283529160200191610669565b820191906000526020600020905b81548152906001019060200180831161064c57829003601f168201915b50505050509050919050565b604051806060016040528060278152602001613b806027913981565b6040805160208101909152600081526106b16106ac8361335e565b6116a2565b600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166370a082316106ff6060860160408701612de8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078c9190613453565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107da6060860160408701612de8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608601356024820152604401600060405180830381600087803b15801561084a57600080fd5b505af115801561085e573d6000803e3d6000fd5b50600092505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690506370a082316108b26060870160408801612de8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa15801561091b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093f9190613453565b90508181101561099157610953818361349b565b6040517f02164a2d00000000000000000000000000000000000000000000000000000000815260040161098891815260200190565b60405180910390fd5b6109a16060850160408601612de8565b73ffffffffffffffffffffffffffffffffffffffff16337f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f06109e3858561349b565b60405190815260200160405180910390a360405180602001604052808383610a0b919061349b565b9052949350505050565b610a1d6118d3565b610a8a8484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061195692505050565b50505050565b610a986118d3565b610aa183610d4b565b610ae3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610988565b67ffffffffffffffff831660009081526007602052604081206004018054610b0a90613260565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3690613260565b8015610b835780601f10610b5857610100808354040283529160200191610b83565b820191906000526020600020905b815481529060010190602001808311610b6657829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610bb28385836134fe565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610bf193929190613618565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610988565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d046118d3565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105bf600567ffffffffffffffff8416611b0c565b6040805180820190915260608082526020820152610d87610d828361367c565b611b27565b610d948260600135611cf1565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610dee84602001602081019061041b9190612d29565b81526040805160208181019092526000815291015292915050565b6060610e156002611d9a565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105bf90611da7565b67ffffffffffffffff811660009081526007602052604090206005018054606091906105f090613260565b610f226118d3565b73ffffffffffffffffffffffffffffffffffffffff8116610f6f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110036005611d9a565b90506000815167ffffffffffffffff811115611021576110216130b3565b60405190808252806020026020018201604052801561104a578160200160208202803683370190505b50905060005b82518110156110a65782818151811061106b5761106b61371e565b60200260200101518282815181106110855761108561371e565b67ffffffffffffffff90921660209283029190910190910152600101611050565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105bf90611da7565b60085473ffffffffffffffffffffffffffffffffffffffff1633148015906111bf575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156111f8576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610988565b611203838383611e59565b505050565b6112106118d3565b60005b8181101561120357600083838381811061122f5761122f61371e565b9050602002810190611241919061374d565b61124a9061378b565b905061125f8160800151826020015115611f43565b6112728160a00151826020015115611f43565b80602001511561156e5780516112949060059067ffffffffffffffff1661207c565b6112d95780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610988565b60408101515115806112ee5750606081015151155b15611325576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c17909116961515029590951790985590810151940151938116931690910291909117600382015591519091906004820190611506908261383f565b506060820151600582019061151b908261383f565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506115619493929190613959565b60405180910390a1611685565b80516115869060059067ffffffffffffffff16612088565b6115cb5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610988565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906116346004830182612c7c565b611642600583016000612c7c565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611213565b6116966118d3565b61169f81612094565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146117375760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610988565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa1580156117e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180991906139f2565b15611840576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61184d8160200151612189565b600061185c82602001516105c5565b9050805160001480611880575080805190602001208260a001518051906020012014155b156118bd578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109889190612da8565b6118cf826020015183606001516122af565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610988565b565b7f00000000000000000000000000000000000000000000000000000000000000006119ad576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611a435760008382815181106119cd576119cd61371e565b602002602001015190506119eb8160026122f690919063ffffffff16565b15611a3a5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016119b0565b5060005b8151811015611203576000828281518110611a6457611a6461371e565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aa85750611b04565b611ab3600282612318565b15611b025760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611a47565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611bbc5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610988565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8e91906139f2565b15611cc5576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cd2816040015161233a565b611cdf81602001516123b9565b61169f81602001518260600151612507565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b158015611d7f57600080fd5b505af1158015611d93573d6000803e3d6000fd5b5050505050565b60606000611b208361254b565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611e3582606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611e19919061349b565b85608001516fffffffffffffffffffffffffffffffff166125a6565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611e6283610d4b565b611ea4576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610988565b611eaf826000611f43565b67ffffffffffffffff83166000908152600760205260409020611ed290836125d0565b611edd816000611f43565b67ffffffffffffffff83166000908152600760205260409020611f0390600201826125d0565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611f3693929190613a0f565b60405180910390a1505050565b81511561200a5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611f99575060408201516fffffffffffffffffffffffffffffffff16155b15611fd257816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109889190613a92565b80156118cf576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612043575060208201516fffffffffffffffffffffffffffffffff1615155b156118cf57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109889190613a92565b6000611b208383612772565b6000611b2083836127c1565b3373ffffffffffffffffffffffffffffffffffffffff821603612113576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610988565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61219281610d4b565b6121d4576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610988565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612253573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227791906139f2565b61169f576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610988565b67ffffffffffffffff821660009081526007602052604090206118cf90600201827f00000000000000000000000000000000000000000000000000000000000000006128b4565b6000611b208373ffffffffffffffffffffffffffffffffffffffff84166127c1565b6000611b208373ffffffffffffffffffffffffffffffffffffffff8416612772565b7f00000000000000000000000000000000000000000000000000000000000000001561169f5761236b600282612c37565b61169f576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610988565b6123c281610d4b565b612404576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610988565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561247d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a19190613ace565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461169f576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610988565b67ffffffffffffffff821660009081526007602052604090206118cf90827f00000000000000000000000000000000000000000000000000000000000000006128b4565b60608160000180548060200260200160405190810160405280929190818152602001828054801561066957602002820191906000526020600020905b8154815260200190600101908083116125875750505050509050919050565b60006125c5856125b68486613aeb565b6125c09087613b02565b612c66565b90505b949350505050565b81546000906125f990700100000000000000000000000000000000900463ffffffff164261349b565b9050801561269b5760018301548354612641916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166125a6565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546126c1916fffffffffffffffffffffffffffffffff9081169116612c66565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611f36908490613a92565b60008181526001830160205260408120546127b9575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105bf565b5060006105bf565b600081815260018301602052604081205480156128aa5760006127e560018361349b565b85549091506000906127f99060019061349b565b905080821461285e5760008660000182815481106128195761281961371e565b906000526020600020015490508087600001848154811061283c5761283c61371e565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061286f5761286f613b15565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105bf565b60009150506105bf565b825474010000000000000000000000000000000000000000900460ff1615806128db575081155b156128e557505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061292b90700100000000000000000000000000000000900463ffffffff164261349b565b905080156129eb578183111561296d576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546129a79083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166125a6565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612aa25773ffffffffffffffffffffffffffffffffffffffff8416612a4a576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610988565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610988565b84831015612bb55760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612ae6908261349b565b612af0878a61349b565b612afa9190613b02565b612b049190613b44565b905073ffffffffffffffffffffffffffffffffffffffff8616612b5d576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610988565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610988565b612bbf858461349b565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611b20565b6000818310612c755781611b20565b5090919050565b508054612c8890613260565b6000825580601f10612c98575050565b601f01602090049060005260206000209081019061169f91905b80821115612cc65760008155600101612cb2565b5090565b600060208284031215612cdc57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611b2057600080fd5b803567ffffffffffffffff81168114612d2457600080fd5b919050565b600060208284031215612d3b57600080fd5b611b2082612d0c565b6000815180845260005b81811015612d6a57602081850181015186830182015201612d4e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611b206020830184612d44565b73ffffffffffffffffffffffffffffffffffffffff8116811461169f57600080fd5b8035612d2481612dbb565b600060208284031215612dfa57600080fd5b8135611b2081612dbb565b600060208284031215612e1757600080fd5b813567ffffffffffffffff811115612e2e57600080fd5b82016101008185031215611b2057600080fd5b60008083601f840112612e5357600080fd5b50813567ffffffffffffffff811115612e6b57600080fd5b6020830191508360208260051b8501011115612e8657600080fd5b9250929050565b60008060008060408587031215612ea357600080fd5b843567ffffffffffffffff80821115612ebb57600080fd5b612ec788838901612e41565b90965094506020870135915080821115612ee057600080fd5b50612eed87828801612e41565b95989497509550505050565b600080600060408486031215612f0e57600080fd5b612f1784612d0c565b9250602084013567ffffffffffffffff80821115612f3457600080fd5b818601915086601f830112612f4857600080fd5b813581811115612f5757600080fd5b876020828501011115612f6957600080fd5b6020830194508093505050509250925092565b600060208284031215612f8e57600080fd5b813567ffffffffffffffff811115612fa557600080fd5b820160a08185031215611b2057600080fd5b602081526000825160406020840152612fd36060840182612d44565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261300e8282612d44565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561306557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613033565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561306557835167ffffffffffffffff168352928401929184019160010161308d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613106576131066130b3565b60405290565b60405160c0810167ffffffffffffffff81118282101715613106576131066130b3565b801515811461169f57600080fd5b8035612d248161312f565b80356fffffffffffffffffffffffffffffffff81168114612d2457600080fd5b60006060828403121561317a57600080fd5b6040516060810181811067ffffffffffffffff8211171561319d5761319d6130b3565b60405290508082356131ae8161312f565b81526131bc60208401613148565b60208201526131cd60408401613148565b60408201525092915050565b600080600060e084860312156131ee57600080fd5b6131f784612d0c565b92506132068560208601613168565b91506132158560808601613168565b90509250925092565b6000806020838503121561323157600080fd5b823567ffffffffffffffff81111561324857600080fd5b61325485828601612e41565b90969095509350505050565b600181811c9082168061327457607f821691505b6020821081036132ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126132c457600080fd5b813567ffffffffffffffff808211156132df576132df6130b3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613325576133256130b3565b8160405283815286602085880101111561333e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561337157600080fd5b6133796130e2565b823567ffffffffffffffff8082111561339157600080fd5b61339d368387016132b3565b83526133ab60208601612d0c565b60208401526133bc60408601612ddd565b6040840152606085013560608401526133d760808601612ddd565b608084015260a08501359150808211156133f057600080fd5b6133fc368387016132b3565b60a084015260c085013591508082111561341557600080fd5b613421368387016132b3565b60c084015260e085013591508082111561343a57600080fd5b50613447368286016132b3565b60e08301525092915050565b60006020828403121561346557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105bf576105bf61346c565b601f821115611203576000816000526020600020601f850160051c810160208610156134d75750805b601f850160051c820191505b818110156134f6578281556001016134e3565b505050505050565b67ffffffffffffffff831115613516576135166130b3565b61352a836135248354613260565b836134ae565b6000601f84116001811461357c57600085156135465750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611d93565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156135cb57868501358255602094850194600190920191016135ab565b5086821015613606577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152600061362b6040830186612d44565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561368e57600080fd5b60405160a0810167ffffffffffffffff82821081831117156136b2576136b26130b3565b8160405284359150808211156136c757600080fd5b506136d4368286016132b3565b8252506136e360208401612d0c565b602082015260408301356136f681612dbb565b604082015260608381013590820152608083013561371381612dbb565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261378157600080fd5b9190910192915050565b6000610140823603121561379e57600080fd5b6137a661310c565b6137af83612d0c565b81526137bd6020840161313d565b6020820152604083013567ffffffffffffffff808211156137dd57600080fd5b6137e9368387016132b3565b6040840152606085013591508082111561380257600080fd5b5061380f368286016132b3565b6060830152506138223660808501613168565b60808201526138343660e08501613168565b60a082015292915050565b815167ffffffffffffffff811115613859576138596130b3565b61386d816138678454613260565b846134ae565b602080601f8311600181146138c0576000841561388a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556134f6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561390d578886015182559484019460019091019084016138ee565b508582101561394957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261397d81840187612d44565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506139bb9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e083015261300e565b600060208284031215613a0457600080fd5b8151611b208161312f565b67ffffffffffffffff8416815260e08101613a5b60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526125c8565b606081016105bf82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613ae057600080fd5b8151611b2081612dbb565b80820281158282048414176105bf576105bf61346c565b808201808211156105bf576105bf61346c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082613b7a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fe4275726e5769746846726f6d4d696e745265626173696e67546f6b656e506f6f6c20312e352e30a164736f6c6343000818000a", +} + +var BurnWithFromMintRebasingTokenPoolABI = BurnWithFromMintRebasingTokenPoolMetaData.ABI + +var BurnWithFromMintRebasingTokenPoolBin = BurnWithFromMintRebasingTokenPoolMetaData.Bin + +func DeployBurnWithFromMintRebasingTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnWithFromMintRebasingTokenPool, error) { + parsed, err := BurnWithFromMintRebasingTokenPoolMetaData.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(BurnWithFromMintRebasingTokenPoolBin), backend, token, allowlist, rmnProxy, router) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &BurnWithFromMintRebasingTokenPool{address: address, abi: *parsed, BurnWithFromMintRebasingTokenPoolCaller: BurnWithFromMintRebasingTokenPoolCaller{contract: contract}, BurnWithFromMintRebasingTokenPoolTransactor: BurnWithFromMintRebasingTokenPoolTransactor{contract: contract}, BurnWithFromMintRebasingTokenPoolFilterer: BurnWithFromMintRebasingTokenPoolFilterer{contract: contract}}, nil +} + +type BurnWithFromMintRebasingTokenPool struct { + address common.Address + abi abi.ABI + BurnWithFromMintRebasingTokenPoolCaller + BurnWithFromMintRebasingTokenPoolTransactor + BurnWithFromMintRebasingTokenPoolFilterer +} + +type BurnWithFromMintRebasingTokenPoolCaller struct { + contract *bind.BoundContract +} + +type BurnWithFromMintRebasingTokenPoolTransactor struct { + contract *bind.BoundContract +} + +type BurnWithFromMintRebasingTokenPoolFilterer struct { + contract *bind.BoundContract +} + +type BurnWithFromMintRebasingTokenPoolSession struct { + Contract *BurnWithFromMintRebasingTokenPool + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type BurnWithFromMintRebasingTokenPoolCallerSession struct { + Contract *BurnWithFromMintRebasingTokenPoolCaller + CallOpts bind.CallOpts +} + +type BurnWithFromMintRebasingTokenPoolTransactorSession struct { + Contract *BurnWithFromMintRebasingTokenPoolTransactor + TransactOpts bind.TransactOpts +} + +type BurnWithFromMintRebasingTokenPoolRaw struct { + Contract *BurnWithFromMintRebasingTokenPool +} + +type BurnWithFromMintRebasingTokenPoolCallerRaw struct { + Contract *BurnWithFromMintRebasingTokenPoolCaller +} + +type BurnWithFromMintRebasingTokenPoolTransactorRaw struct { + Contract *BurnWithFromMintRebasingTokenPoolTransactor +} + +func NewBurnWithFromMintRebasingTokenPool(address common.Address, backend bind.ContractBackend) (*BurnWithFromMintRebasingTokenPool, error) { + abi, err := abi.JSON(strings.NewReader(BurnWithFromMintRebasingTokenPoolABI)) + if err != nil { + return nil, err + } + contract, err := bindBurnWithFromMintRebasingTokenPool(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPool{address: address, abi: abi, BurnWithFromMintRebasingTokenPoolCaller: BurnWithFromMintRebasingTokenPoolCaller{contract: contract}, BurnWithFromMintRebasingTokenPoolTransactor: BurnWithFromMintRebasingTokenPoolTransactor{contract: contract}, BurnWithFromMintRebasingTokenPoolFilterer: BurnWithFromMintRebasingTokenPoolFilterer{contract: contract}}, nil +} + +func NewBurnWithFromMintRebasingTokenPoolCaller(address common.Address, caller bind.ContractCaller) (*BurnWithFromMintRebasingTokenPoolCaller, error) { + contract, err := bindBurnWithFromMintRebasingTokenPool(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolCaller{contract: contract}, nil +} + +func NewBurnWithFromMintRebasingTokenPoolTransactor(address common.Address, transactor bind.ContractTransactor) (*BurnWithFromMintRebasingTokenPoolTransactor, error) { + contract, err := bindBurnWithFromMintRebasingTokenPool(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolTransactor{contract: contract}, nil +} + +func NewBurnWithFromMintRebasingTokenPoolFilterer(address common.Address, filterer bind.ContractFilterer) (*BurnWithFromMintRebasingTokenPoolFilterer, error) { + contract, err := bindBurnWithFromMintRebasingTokenPool(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolFilterer{contract: contract}, nil +} + +func bindBurnWithFromMintRebasingTokenPool(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BurnWithFromMintRebasingTokenPoolMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BurnWithFromMintRebasingTokenPool.Contract.BurnWithFromMintRebasingTokenPoolCaller.contract.Call(opts, result, method, params...) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.BurnWithFromMintRebasingTokenPoolTransactor.contract.Transfer(opts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.BurnWithFromMintRebasingTokenPoolTransactor.contract.Transact(opts, method, params...) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BurnWithFromMintRebasingTokenPool.Contract.contract.Call(opts, result, method, params...) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.contract.Transfer(opts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.contract.Transact(opts, method, params...) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetAllowList() ([]common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetAllowList(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetAllowList() ([]common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetAllowList(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.contract.Call(opts, &out, "getAllowListEnabled") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetAllowListEnabled() (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetAllowListEnabled(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetAllowListEnabled() (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetAllowListEnabled(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetCurrentInboundRateLimiterState(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetCurrentInboundRateLimiterState(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRateLimitAdmin(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRateLimitAdmin(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRemotePool(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRemotePool(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRemoteToken(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRemoteToken(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetRmnProxy(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetRmnProxy() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRmnProxy(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetRmnProxy() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRmnProxy(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetRouter() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRouter(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetRouter() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetRouter(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetSupportedChains(opts *bind.CallOpts) ([]uint64, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.contract.Call(opts, &out, "getSupportedChains") + + if err != nil { + return *new([]uint64), err + } + + out0 := *abi.ConvertType(out[0], new([]uint64)).(*[]uint64) + + return out0, err + +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetSupportedChains() ([]uint64, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetSupportedChains(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetSupportedChains() ([]uint64, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetSupportedChains(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) GetToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) GetToken() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetToken(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) GetToken() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.GetToken(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.IsSupportedChain(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.IsSupportedChain(&_BurnWithFromMintRebasingTokenPool.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) IsSupportedToken(token common.Address) (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.IsSupportedToken(&_BurnWithFromMintRebasingTokenPool.CallOpts, token) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) IsSupportedToken(token common.Address) (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.IsSupportedToken(&_BurnWithFromMintRebasingTokenPool.CallOpts, token) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) Owner() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.Owner(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) Owner() (common.Address, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.Owner(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SupportsInterface(&_BurnWithFromMintRebasingTokenPool.CallOpts, interfaceId) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SupportsInterface(&_BurnWithFromMintRebasingTokenPool.CallOpts, interfaceId) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _BurnWithFromMintRebasingTokenPool.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) TypeAndVersion() (string, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.TypeAndVersion(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolCallerSession) TypeAndVersion() (string, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.TypeAndVersion(&_BurnWithFromMintRebasingTokenPool.CallOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "acceptOwnership") +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) AcceptOwnership() (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.AcceptOwnership(&_BurnWithFromMintRebasingTokenPool.TransactOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.AcceptOwnership(&_BurnWithFromMintRebasingTokenPool.TransactOpts) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.ApplyAllowListUpdates(&_BurnWithFromMintRebasingTokenPool.TransactOpts, removes, adds) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.ApplyAllowListUpdates(&_BurnWithFromMintRebasingTokenPool.TransactOpts, removes, adds) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "applyChainUpdates", chains) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintRebasingTokenPool.TransactOpts, chains) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintRebasingTokenPool.TransactOpts, chains) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "lockOrBurn", lockOrBurnIn) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.LockOrBurn(&_BurnWithFromMintRebasingTokenPool.TransactOpts, lockOrBurnIn) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.LockOrBurn(&_BurnWithFromMintRebasingTokenPool.TransactOpts, lockOrBurnIn) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "releaseOrMint", releaseOrMintIn) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.ReleaseOrMint(&_BurnWithFromMintRebasingTokenPool.TransactOpts, releaseOrMintIn) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.ReleaseOrMint(&_BurnWithFromMintRebasingTokenPool.TransactOpts, releaseOrMintIn) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintRebasingTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintRebasingTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetRateLimitAdmin(&_BurnWithFromMintRebasingTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetRateLimitAdmin(&_BurnWithFromMintRebasingTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetRemotePool(&_BurnWithFromMintRebasingTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetRemotePool(&_BurnWithFromMintRebasingTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "setRouter", newRouter) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) SetRouter(newRouter common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetRouter(&_BurnWithFromMintRebasingTokenPool.TransactOpts, newRouter) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) SetRouter(newRouter common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.SetRouter(&_BurnWithFromMintRebasingTokenPool.TransactOpts, newRouter) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.contract.Transact(opts, "transferOwnership", to) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.TransferOwnership(&_BurnWithFromMintRebasingTokenPool.TransactOpts, to) +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BurnWithFromMintRebasingTokenPool.Contract.TransferOwnership(&_BurnWithFromMintRebasingTokenPool.TransactOpts, to) +} + +type BurnWithFromMintRebasingTokenPoolAllowListAddIterator struct { + Event *BurnWithFromMintRebasingTokenPoolAllowListAdd + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolAllowListAddIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolAllowListAdd) + 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(BurnWithFromMintRebasingTokenPoolAllowListAdd) + 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 *BurnWithFromMintRebasingTokenPoolAllowListAddIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolAllowListAddIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolAllowListAdd struct { + Sender common.Address + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolAllowListAddIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "AllowListAdd") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolAllowListAddIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolAllowListAdd) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolAllowListAdd) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseAllowListAdd(log types.Log) (*BurnWithFromMintRebasingTokenPoolAllowListAdd, error) { + event := new(BurnWithFromMintRebasingTokenPoolAllowListAdd) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "AllowListAdd", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator struct { + Event *BurnWithFromMintRebasingTokenPoolAllowListRemove + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolAllowListRemove) + 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(BurnWithFromMintRebasingTokenPoolAllowListRemove) + 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 *BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolAllowListRemove struct { + Sender common.Address + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "AllowListRemove") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolAllowListRemove) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolAllowListRemove) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseAllowListRemove(log types.Log) (*BurnWithFromMintRebasingTokenPoolAllowListRemove, error) { + event := new(BurnWithFromMintRebasingTokenPoolAllowListRemove) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "AllowListRemove", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolBurnedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolBurned + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolBurnedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolBurned) + 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(BurnWithFromMintRebasingTokenPoolBurned) + 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 *BurnWithFromMintRebasingTokenPoolBurnedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolBurnedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolBurned struct { + Sender common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintRebasingTokenPoolBurnedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "Burned", senderRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolBurnedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "Burned", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchBurned(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolBurned, sender []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolBurned) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseBurned(log types.Log) (*BurnWithFromMintRebasingTokenPoolBurned, error) { + event := new(BurnWithFromMintRebasingTokenPoolBurned) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "Burned", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolChainAddedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolChainAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolChainAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolChainAdded) + 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(BurnWithFromMintRebasingTokenPoolChainAdded) + 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 *BurnWithFromMintRebasingTokenPoolChainAddedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolChainAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolChainAdded struct { + RemoteChainSelector uint64 + RemoteToken []byte + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterChainAdded(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolChainAddedIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "ChainAdded") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolChainAddedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "ChainAdded", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchChainAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolChainAdded) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolChainAdded) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseChainAdded(log types.Log) (*BurnWithFromMintRebasingTokenPoolChainAdded, error) { + event := new(BurnWithFromMintRebasingTokenPoolChainAdded) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "ChainAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolChainConfiguredIterator struct { + Event *BurnWithFromMintRebasingTokenPoolChainConfigured + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolChainConfiguredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolChainConfigured) + 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(BurnWithFromMintRebasingTokenPoolChainConfigured) + 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 *BurnWithFromMintRebasingTokenPoolChainConfiguredIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolChainConfiguredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolChainConfigured struct { + RemoteChainSelector uint64 + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterChainConfigured(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolChainConfiguredIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "ChainConfigured") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolChainConfiguredIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "ChainConfigured", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolChainConfigured) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolChainConfigured) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseChainConfigured(log types.Log) (*BurnWithFromMintRebasingTokenPoolChainConfigured, error) { + event := new(BurnWithFromMintRebasingTokenPoolChainConfigured) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "ChainConfigured", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolChainRemovedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolChainRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolChainRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolChainRemoved) + 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(BurnWithFromMintRebasingTokenPoolChainRemoved) + 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 *BurnWithFromMintRebasingTokenPoolChainRemovedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolChainRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolChainRemoved struct { + RemoteChainSelector uint64 + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterChainRemoved(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolChainRemovedIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "ChainRemoved") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolChainRemovedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "ChainRemoved", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolChainRemoved) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolChainRemoved) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseChainRemoved(log types.Log) (*BurnWithFromMintRebasingTokenPoolChainRemoved, error) { + event := new(BurnWithFromMintRebasingTokenPoolChainRemoved) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "ChainRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolConfigChangedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolConfigChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolConfigChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolConfigChanged) + 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(BurnWithFromMintRebasingTokenPoolConfigChanged) + 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 *BurnWithFromMintRebasingTokenPoolConfigChangedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolConfigChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolConfigChanged struct { + Config RateLimiterConfig + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolConfigChangedIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "ConfigChanged") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolConfigChangedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolConfigChanged) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolConfigChanged) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseConfigChanged(log types.Log) (*BurnWithFromMintRebasingTokenPoolConfigChanged, error) { + event := new(BurnWithFromMintRebasingTokenPoolConfigChanged) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "ConfigChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolLockedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolLocked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolLockedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolLocked) + 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(BurnWithFromMintRebasingTokenPoolLocked) + 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 *BurnWithFromMintRebasingTokenPoolLockedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolLockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolLocked struct { + Sender common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintRebasingTokenPoolLockedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "Locked", senderRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolLockedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "Locked", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchLocked(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolLocked, sender []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolLocked) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseLocked(log types.Log) (*BurnWithFromMintRebasingTokenPoolLocked, error) { + event := new(BurnWithFromMintRebasingTokenPoolLocked) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "Locked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolMintedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolMinted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolMintedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolMinted) + 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(BurnWithFromMintRebasingTokenPoolMinted) + 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 *BurnWithFromMintRebasingTokenPoolMintedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolMintedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolMinted struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintRebasingTokenPoolMintedIterator, 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 := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "Minted", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolMintedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "Minted", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchMinted(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolMinted, 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 := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolMinted) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseMinted(log types.Log) (*BurnWithFromMintRebasingTokenPoolMinted, error) { + event := new(BurnWithFromMintRebasingTokenPoolMinted) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "Minted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested) + 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(BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested) + 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 *BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator, 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 := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested, 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 := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseOwnershipTransferRequested(log types.Log) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested, error) { + event := new(BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator struct { + Event *BurnWithFromMintRebasingTokenPoolOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolOwnershipTransferred) + 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(BurnWithFromMintRebasingTokenPoolOwnershipTransferred) + 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 *BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator, 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 := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolOwnershipTransferred, 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 := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolOwnershipTransferred) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseOwnershipTransferred(log types.Log) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferred, error) { + event := new(BurnWithFromMintRebasingTokenPoolOwnershipTransferred) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolReleasedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolReleased + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolReleasedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolReleased) + 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(BurnWithFromMintRebasingTokenPoolReleased) + 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 *BurnWithFromMintRebasingTokenPoolReleasedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolReleasedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolReleased struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintRebasingTokenPoolReleasedIterator, 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 := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "Released", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolReleasedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "Released", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolReleased, 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 := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolReleased) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseReleased(log types.Log) (*BurnWithFromMintRebasingTokenPoolReleased, error) { + event := new(BurnWithFromMintRebasingTokenPoolReleased) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "Released", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator struct { + Event *BurnWithFromMintRebasingTokenPoolRemotePoolSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolRemotePoolSet) + 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(BurnWithFromMintRebasingTokenPoolRemotePoolSet) + 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 *BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolRemotePoolSet struct { + RemoteChainSelector uint64 + PreviousPoolAddress []byte + RemotePoolAddress []byte + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.WatchLogs(opts, "RemotePoolSet", 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(BurnWithFromMintRebasingTokenPoolRemotePoolSet) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "RemotePoolSet", 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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnWithFromMintRebasingTokenPoolRemotePoolSet, error) { + event := new(BurnWithFromMintRebasingTokenPoolRemotePoolSet) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolRouterUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolRouterUpdated) + 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(BurnWithFromMintRebasingTokenPoolRouterUpdated) + 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 *BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolRouterUpdated struct { + OldRouter common.Address + NewRouter common.Address + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "RouterUpdated") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "RouterUpdated", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolRouterUpdated) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.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(BurnWithFromMintRebasingTokenPoolRouterUpdated) + if err := _BurnWithFromMintRebasingTokenPool.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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseRouterUpdated(log types.Log) (*BurnWithFromMintRebasingTokenPoolRouterUpdated, error) { + event := new(BurnWithFromMintRebasingTokenPoolRouterUpdated) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "RouterUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintRebasingTokenPoolTokensConsumedIterator struct { + Event *BurnWithFromMintRebasingTokenPoolTokensConsumed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintRebasingTokenPoolTokensConsumedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintRebasingTokenPoolTokensConsumed) + 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(BurnWithFromMintRebasingTokenPoolTokensConsumed) + 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 *BurnWithFromMintRebasingTokenPoolTokensConsumedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintRebasingTokenPoolTokensConsumedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintRebasingTokenPoolTokensConsumed struct { + Tokens *big.Int + Raw types.Log +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) FilterTokensConsumed(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolTokensConsumedIterator, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.FilterLogs(opts, "TokensConsumed") + if err != nil { + return nil, err + } + return &BurnWithFromMintRebasingTokenPoolTokensConsumedIterator{contract: _BurnWithFromMintRebasingTokenPool.contract, event: "TokensConsumed", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolTokensConsumed) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintRebasingTokenPool.contract.WatchLogs(opts, "TokensConsumed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnWithFromMintRebasingTokenPoolTokensConsumed) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "TokensConsumed", 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 (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPoolFilterer) ParseTokensConsumed(log types.Log) (*BurnWithFromMintRebasingTokenPoolTokensConsumed, error) { + event := new(BurnWithFromMintRebasingTokenPoolTokensConsumed) + if err := _BurnWithFromMintRebasingTokenPool.contract.UnpackLog(event, "TokensConsumed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPool) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _BurnWithFromMintRebasingTokenPool.abi.Events["AllowListAdd"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseAllowListAdd(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["AllowListRemove"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseAllowListRemove(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["Burned"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseBurned(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["ChainAdded"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseChainAdded(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["ChainConfigured"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseChainConfigured(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["ChainRemoved"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseChainRemoved(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["ConfigChanged"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseConfigChanged(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["Locked"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseLocked(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["Minted"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseMinted(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["OwnershipTransferRequested"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseOwnershipTransferRequested(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["OwnershipTransferred"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseOwnershipTransferred(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["Released"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseReleased(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["RemotePoolSet"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseRemotePoolSet(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["RouterUpdated"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseRouterUpdated(log) + case _BurnWithFromMintRebasingTokenPool.abi.Events["TokensConsumed"].ID: + return _BurnWithFromMintRebasingTokenPool.ParseTokensConsumed(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (BurnWithFromMintRebasingTokenPoolAllowListAdd) Topic() common.Hash { + return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8") +} + +func (BurnWithFromMintRebasingTokenPoolAllowListRemove) Topic() common.Hash { + return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566") +} + +func (BurnWithFromMintRebasingTokenPoolBurned) Topic() common.Hash { + return common.HexToHash("0x696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7") +} + +func (BurnWithFromMintRebasingTokenPoolChainAdded) Topic() common.Hash { + return common.HexToHash("0x8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2") +} + +func (BurnWithFromMintRebasingTokenPoolChainConfigured) Topic() common.Hash { + return common.HexToHash("0x0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b") +} + +func (BurnWithFromMintRebasingTokenPoolChainRemoved) Topic() common.Hash { + return common.HexToHash("0x5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916") +} + +func (BurnWithFromMintRebasingTokenPoolConfigChanged) Topic() common.Hash { + return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") +} + +func (BurnWithFromMintRebasingTokenPoolLocked) Topic() common.Hash { + return common.HexToHash("0x9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008") +} + +func (BurnWithFromMintRebasingTokenPoolMinted) Topic() common.Hash { + return common.HexToHash("0x9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0") +} + +func (BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (BurnWithFromMintRebasingTokenPoolOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (BurnWithFromMintRebasingTokenPoolReleased) Topic() common.Hash { + return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") +} + +func (BurnWithFromMintRebasingTokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +} + +func (BurnWithFromMintRebasingTokenPoolRouterUpdated) Topic() common.Hash { + return common.HexToHash("0x02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684") +} + +func (BurnWithFromMintRebasingTokenPoolTokensConsumed) Topic() common.Hash { + return common.HexToHash("0x1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a") +} + +func (_BurnWithFromMintRebasingTokenPool *BurnWithFromMintRebasingTokenPool) Address() common.Address { + return _BurnWithFromMintRebasingTokenPool.address +} + +type BurnWithFromMintRebasingTokenPoolInterface 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) + + GetRemotePool(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) + + 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) + + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) + + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + + LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) + + ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*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) + + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*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) (*BurnWithFromMintRebasingTokenPoolAllowListAddIterator, error) + + WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolAllowListAdd) (event.Subscription, error) + + ParseAllowListAdd(log types.Log) (*BurnWithFromMintRebasingTokenPoolAllowListAdd, error) + + FilterAllowListRemove(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolAllowListRemoveIterator, error) + + WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolAllowListRemove) (event.Subscription, error) + + ParseAllowListRemove(log types.Log) (*BurnWithFromMintRebasingTokenPoolAllowListRemove, error) + + FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintRebasingTokenPoolBurnedIterator, error) + + WatchBurned(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolBurned, sender []common.Address) (event.Subscription, error) + + ParseBurned(log types.Log) (*BurnWithFromMintRebasingTokenPoolBurned, error) + + FilterChainAdded(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolChainAddedIterator, error) + + WatchChainAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolChainAdded) (event.Subscription, error) + + ParseChainAdded(log types.Log) (*BurnWithFromMintRebasingTokenPoolChainAdded, error) + + FilterChainConfigured(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolChainConfiguredIterator, error) + + WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolChainConfigured) (event.Subscription, error) + + ParseChainConfigured(log types.Log) (*BurnWithFromMintRebasingTokenPoolChainConfigured, error) + + FilterChainRemoved(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolChainRemovedIterator, error) + + WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolChainRemoved) (event.Subscription, error) + + ParseChainRemoved(log types.Log) (*BurnWithFromMintRebasingTokenPoolChainRemoved, error) + + FilterConfigChanged(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolConfigChangedIterator, error) + + WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolConfigChanged) (event.Subscription, error) + + ParseConfigChanged(log types.Log) (*BurnWithFromMintRebasingTokenPoolConfigChanged, error) + + FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintRebasingTokenPoolLockedIterator, error) + + WatchLocked(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolLocked, sender []common.Address) (event.Subscription, error) + + ParseLocked(log types.Log) (*BurnWithFromMintRebasingTokenPoolLocked, error) + + FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintRebasingTokenPoolMintedIterator, error) + + WatchMinted(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseMinted(log types.Log) (*BurnWithFromMintRebasingTokenPoolMinted, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*BurnWithFromMintRebasingTokenPoolOwnershipTransferred, error) + + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintRebasingTokenPoolReleasedIterator, error) + + WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseReleased(log types.Log) (*BurnWithFromMintRebasingTokenPoolReleased, error) + + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintRebasingTokenPoolRemotePoolSetIterator, error) + + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolSet(log types.Log) (*BurnWithFromMintRebasingTokenPoolRemotePoolSet, error) + + FilterRouterUpdated(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolRouterUpdatedIterator, error) + + WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolRouterUpdated) (event.Subscription, error) + + ParseRouterUpdated(log types.Log) (*BurnWithFromMintRebasingTokenPoolRouterUpdated, error) + + FilterTokensConsumed(opts *bind.FilterOpts) (*BurnWithFromMintRebasingTokenPoolTokensConsumedIterator, error) + + WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintRebasingTokenPoolTokensConsumed) (event.Subscription, error) + + ParseTokensConsumed(log types.Log) (*BurnWithFromMintRebasingTokenPoolTokensConsumed, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} 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 07489bbb01a..5ce5bf9f1d3 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 @@ -82,8 +82,8 @@ type TokenPoolChainUpdate struct { } var BurnWithFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":[],\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b50604051620043e4380380620043e48339810160408190526200003491620008c0565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c2816200018f565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c05262000168576040805160008152602081019091526200016890846200023a565b5062000185925050506001600160a01b0385163060001962000397565b5050505062000afc565b336001600160a01b03821603620001e95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200025b576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002e65760008382815181106200027f576200027f620009d0565b60209081029190910101519050620002996002826200047d565b15620002dc576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200025e565b5060005b8151811015620003925760008282815181106200030b576200030b620009d0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000337575062000389565b620003446002826200049d565b1562000387576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002ea565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040f9190620009e6565b6200041b919062000a16565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047791869190620004b416565b50505050565b600062000494836001600160a01b03841662000585565b90505b92915050565b600062000494836001600160a01b03841662000689565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000503906001600160a01b038516908490620006db565b80519091501562000392578080602001905181019062000524919062000a2c565b620003925760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000086565b600081815260018301602052604081205480156200067e576000620005ac60018362000a57565b8554909150600090620005c29060019062000a57565b90508181146200062e576000866000018281548110620005e657620005e6620009d0565b90600052602060002001549050808760000184815481106200060c576200060c620009d0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000642576200064262000a6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000497565b600091505062000497565b6000818152600183016020526040812054620006d25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000497565b50600062000497565b6060620006ec8484600085620006f4565b949350505050565b606082471015620007575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000086565b600080866001600160a01b0316858760405162000775919062000aa9565b60006040518083038185875af1925050503d8060008114620007b4576040519150601f19603f3d011682016040523d82523d6000602084013e620007b9565b606091505b509092509050620007cd87838387620007d8565b979650505050505050565b606083156200084c57825160000362000844576001600160a01b0385163b620008445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000086565b5081620006ec565b620006ec8383815115620008635781518083602001fd5b8060405162461bcd60e51b815260040162000086919062000ac7565b6001600160a01b03811681146200089557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008bb816200087f565b919050565b60008060008060808587031215620008d757600080fd5b8451620008e4816200087f565b602086810151919550906001600160401b03808211156200090457600080fd5b818801915088601f8301126200091957600080fd5b8151818111156200092e576200092e62000898565b8060051b604051601f19603f8301168101818110858211171562000956576200095662000898565b60405291825284820192508381018501918b8311156200097557600080fd5b938501935b828510156200099e576200098e85620008ae565b845293850193928501926200097a565b809850505050505050620009b560408601620008ae565b9150620009c560608601620008ae565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000497576200049762000a00565b60006020828403121562000a3f57600080fd5b8151801515811462000a5057600080fd5b9392505050565b8181038181111562000497576200049762000a00565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa057818101518382015260200162000a86565b50506000910152565b6000825162000abd81846020870162000a83565b9190910192915050565b602081526000825180602084015262000ae881604085016020870162000a83565b601f01601f19169190910160400192915050565b60805160a05160c05161386b62000b79600039600081816104620152818161162d015261201101526000818161043c0152818161145e01526118e30152600081816101ef01528181610244015281816106a20152818161137e01528181611803015281816119fb01528181611fa701526121fc015261386b6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063a7cd63b7116100e3578063c75eea9c1161008c578063dc0bd97111610066578063dc0bd9711461043a578063e0351e1314610460578063f2fde38b1461048657600080fd5b8063c75eea9c14610401578063cf7401f314610414578063db6327dc1461042757600080fd5b8063b7946580116100bd578063b7946580146103c6578063c0d78655146103d9578063c4bffe2b146103ec57600080fd5b8063a7cd63b714610324578063af58d59f14610339578063b0f479a1146103a857600080fd5b806354c8a4f3116101455780638926f54f1161011f5780638926f54f146102d35780638da5cb5b146102e65780639a4575b91461030457600080fd5b806354c8a4f3146102a357806378a010b2146102b857806379ba5097146102cb57600080fd5b806321df0da71161017657806321df0da7146101ed578063240028e814610234578063390775371461028157600080fd5b806301ffc9a71461019d5780630a2fd493146101c5578063181f5a77146101e5575b600080fd5b6101b06101ab36600461299f565b610499565b60405190151581526020015b60405180910390f35b6101d86101d33660046129fe565b61057e565b6040516101bc9190612a7d565b6101d861062e565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b6101b0610242366004612abd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61029461028f366004612ada565b61064a565b604051905181526020016101bc565b6102b66102b1366004612b62565b6107a5565b005b6102b66102c6366004612bce565b610820565b6102b6610994565b6101b06102e13660046129fe565b610a91565b60005473ffffffffffffffffffffffffffffffffffffffff1661020f565b610317610312366004612c51565b610aa8565b6040516101bc9190612c8c565b61032c610b4f565b6040516101bc9190612cec565b61034c6103473660046129fe565b610b60565b6040516101bc919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff1661020f565b6101d86103d43660046129fe565b610c35565b6102b66103e7366004612abd565b610c60565b6103f4610d3b565b6040516101bc9190612d46565b61034c61040f3660046129fe565b610df3565b6102b6610422366004612eae565b610ec5565b6102b6610435366004612ef3565b610edd565b7f000000000000000000000000000000000000000000000000000000000000000061020f565b7f00000000000000000000000000000000000000000000000000000000000000006101b0565b6102b6610494366004612abd565b611363565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061052c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061057857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906105a990612f35565b80601f01602080910402602001604051908101604052809291908181526020018280546105d590612f35565b80156106225780601f106105f757610100808354040283529160200191610622565b820191906000526020600020905b81548152906001019060200180831161060557829003601f168201915b50505050509050919050565b60405180606001604052806023815260200161383c6023913981565b60408051602081019091526000815261066a61066583613033565b611377565b6040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152606083013560248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906340c10f1990604401600060405180830381600087803b1580156106fb57600080fd5b505af115801561070f573d6000803e3d6000fd5b50610724925050506060830160408401612abd565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161078691815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6107ad6115a8565b61081a8484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061162b92505050565b50505050565b6108286115a8565b61083183610a91565b610878576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff83166000908152600760205260408120600401805461089f90612f35565b80601f01602080910402602001604051908101604052809291908181526020018280546108cb90612f35565b80156109185780601f106108ed57610100808354040283529160200191610918565b820191906000526020600020905b8154815290600101906020018083116108fb57829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610947838583613178565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf82858560405161098693929190613292565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161086f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000610578600567ffffffffffffffff84166117e1565b6040805180820190915260608082526020820152610acd610ac8836132f6565b6117fc565b610ada82606001356119c6565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b348460200160208101906103d491906129fe565b81526040805160208181019092526000815291015292915050565b6060610b5b6002611a6f565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261057890611a7c565b67ffffffffffffffff811660009081526007602052604090206005018054606091906105a990612f35565b610c686115a8565b73ffffffffffffffffffffffffffffffffffffffff8116610cb5576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610d496005611a6f565b90506000815167ffffffffffffffff811115610d6757610d67612d88565b604051908082528060200260200182016040528015610d90578160200160208202803683370190505b50905060005b8251811015610dec57828181518110610db157610db1613398565b6020026020010151828281518110610dcb57610dcb613398565b67ffffffffffffffff90921660209283029190910190910152600101610d96565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261057890611a7c565b610ecd6115a8565b610ed8838383611b2e565b505050565b610ee56115a8565b60005b81811015610ed8576000838383818110610f0457610f04613398565b9050602002810190610f1691906133c7565b610f1f90613405565b9050610f348160800151826020015115611c18565b610f478160a00151826020015115611c18565b806020015115611243578051610f699060059067ffffffffffffffff16611d51565b610fae5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161086f565b6040810151511580610fc35750606081015151155b15610ffa576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906111db90826134b9565b50606082015160058201906111f090826134b9565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061123694939291906135d3565b60405180910390a161135a565b805161125b9060059067ffffffffffffffff16611d5d565b6112a05780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161086f565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906113096004830182612951565b611317600583016000612951565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101610ee8565b61136b6115a8565b61137481611d69565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161461140c5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161086f565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa1580156114ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114de919061366c565b15611515576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115228160200151611e5e565b6000611531826020015161057e565b9050805160001480611555575080805190602001208260a001518051906020012014155b15611592578160a001516040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161086f9190612a7d565b6115a482602001518360600151611f84565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161086f565b565b7f0000000000000000000000000000000000000000000000000000000000000000611682576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156117185760008382815181106116a2576116a2613398565b602002602001015190506116c0816002611fcb90919063ffffffff16565b1561170f5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611685565b5060005b8151811015610ed857600082828151811061173957611739613398565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361177d57506117d9565b611788600282611fed565b156117d75760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161171c565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146118915760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161086f565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa15801561193f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611963919061366c565b1561199a576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119a7816040015161200f565b6119b4816020015161208e565b611374816020015182606001516121dc565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b158015611a5457600080fd5b505af1158015611a68573d6000803e3d6000fd5b5050505050565b606060006117f583612220565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611b0a82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611aee91906136b8565b85608001516fffffffffffffffffffffffffffffffff1661227b565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611b3783610a91565b611b79576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161086f565b611b84826000611c18565b67ffffffffffffffff83166000908152600760205260409020611ba790836122a5565b611bb2816000611c18565b67ffffffffffffffff83166000908152600760205260409020611bd890600201826122a5565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611c0b939291906136cb565b60405180910390a1505050565b815115611cdf5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611c6e575060408201516fffffffffffffffffffffffffffffffff16155b15611ca757816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161086f919061374e565b80156115a4576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611d18575060208201516fffffffffffffffffffffffffffffffff1615155b156115a457816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161086f919061374e565b60006117f58383612447565b60006117f58383612496565b3373ffffffffffffffffffffffffffffffffffffffff821603611de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161086f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611e6781610a91565b611ea9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161086f565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015611f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4c919061366c565b611374576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161086f565b67ffffffffffffffff821660009081526007602052604090206115a490600201827f0000000000000000000000000000000000000000000000000000000000000000612589565b60006117f58373ffffffffffffffffffffffffffffffffffffffff8416612496565b60006117f58373ffffffffffffffffffffffffffffffffffffffff8416612447565b7f0000000000000000000000000000000000000000000000000000000000000000156113745761204060028261290c565b611374576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161086f565b61209781610a91565b6120d9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161086f565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612152573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612176919061378a565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611374576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161086f565b67ffffffffffffffff821660009081526007602052604090206115a490827f0000000000000000000000000000000000000000000000000000000000000000612589565b60608160000180548060200260200160405190810160405280929190818152602001828054801561062257602002820191906000526020600020905b81548152602001906001019080831161225c5750505050509050919050565b600061229a8561228b84866137a7565b61229590876137be565b61293b565b90505b949350505050565b81546000906122ce90700100000000000000000000000000000000900463ffffffff16426136b8565b905080156123705760018301548354612316916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661227b565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612396916fffffffffffffffffffffffffffffffff908116911661293b565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611c0b90849061374e565b600081815260018301602052604081205461248e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610578565b506000610578565b6000818152600183016020526040812054801561257f5760006124ba6001836136b8565b85549091506000906124ce906001906136b8565b90508181146125335760008660000182815481106124ee576124ee613398565b906000526020600020015490508087600001848154811061251157612511613398565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612544576125446137d1565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610578565b6000915050610578565b825474010000000000000000000000000000000000000000900460ff1615806125b0575081155b156125ba57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061260090700100000000000000000000000000000000900463ffffffff16426136b8565b905080156126c05781831115612642576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600186015461267c9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661227b565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156127775773ffffffffffffffffffffffffffffffffffffffff841661271f576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161086f565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161086f565b8483101561288a5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906127bb90826136b8565b6127c5878a6136b8565b6127cf91906137be565b6127d99190613800565b905073ffffffffffffffffffffffffffffffffffffffff8616612832576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161086f565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161086f565b61289485846136b8565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156117f5565b600081831061294a57816117f5565b5090919050565b50805461295d90612f35565b6000825580601f1061296d575050565b601f01602090049060005260206000209081019061137491905b8082111561299b5760008155600101612987565b5090565b6000602082840312156129b157600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146117f557600080fd5b803567ffffffffffffffff811681146129f957600080fd5b919050565b600060208284031215612a1057600080fd5b6117f5826129e1565b6000815180845260005b81811015612a3f57602081850181015186830182015201612a23565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006117f56020830184612a19565b73ffffffffffffffffffffffffffffffffffffffff8116811461137457600080fd5b80356129f981612a90565b600060208284031215612acf57600080fd5b81356117f581612a90565b600060208284031215612aec57600080fd5b813567ffffffffffffffff811115612b0357600080fd5b820161010081850312156117f557600080fd5b60008083601f840112612b2857600080fd5b50813567ffffffffffffffff811115612b4057600080fd5b6020830191508360208260051b8501011115612b5b57600080fd5b9250929050565b60008060008060408587031215612b7857600080fd5b843567ffffffffffffffff80821115612b9057600080fd5b612b9c88838901612b16565b90965094506020870135915080821115612bb557600080fd5b50612bc287828801612b16565b95989497509550505050565b600080600060408486031215612be357600080fd5b612bec846129e1565b9250602084013567ffffffffffffffff80821115612c0957600080fd5b818601915086601f830112612c1d57600080fd5b813581811115612c2c57600080fd5b876020828501011115612c3e57600080fd5b6020830194508093505050509250925092565b600060208284031215612c6357600080fd5b813567ffffffffffffffff811115612c7a57600080fd5b820160a081850312156117f557600080fd5b602081526000825160406020840152612ca86060840182612a19565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612ce38282612a19565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612d3a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612d08565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612d3a57835167ffffffffffffffff1683529284019291840191600101612d62565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612ddb57612ddb612d88565b60405290565b60405160c0810167ffffffffffffffff81118282101715612ddb57612ddb612d88565b801515811461137457600080fd5b80356129f981612e04565b80356fffffffffffffffffffffffffffffffff811681146129f957600080fd5b600060608284031215612e4f57600080fd5b6040516060810181811067ffffffffffffffff82111715612e7257612e72612d88565b6040529050808235612e8381612e04565b8152612e9160208401612e1d565b6020820152612ea260408401612e1d565b60408201525092915050565b600080600060e08486031215612ec357600080fd5b612ecc846129e1565b9250612edb8560208601612e3d565b9150612eea8560808601612e3d565b90509250925092565b60008060208385031215612f0657600080fd5b823567ffffffffffffffff811115612f1d57600080fd5b612f2985828601612b16565b90969095509350505050565b600181811c90821680612f4957607f821691505b602082108103612f82577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f830112612f9957600080fd5b813567ffffffffffffffff80821115612fb457612fb4612d88565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612ffa57612ffa612d88565b8160405283815286602085880101111561301357600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561304657600080fd5b61304e612db7565b823567ffffffffffffffff8082111561306657600080fd5b61307236838701612f88565b8352613080602086016129e1565b602084015261309160408601612ab2565b6040840152606085013560608401526130ac60808601612ab2565b608084015260a08501359150808211156130c557600080fd5b6130d136838701612f88565b60a084015260c08501359150808211156130ea57600080fd5b6130f636838701612f88565b60c084015260e085013591508082111561310f57600080fd5b5061311c36828601612f88565b60e08301525092915050565b601f821115610ed8576000816000526020600020601f850160051c810160208610156131515750805b601f850160051c820191505b818110156131705782815560010161315d565b505050505050565b67ffffffffffffffff83111561319057613190612d88565b6131a48361319e8354612f35565b83613128565b6000601f8411600181146131f657600085156131c05750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611a68565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156132455786850135825560209485019460019092019101613225565b5086821015613280577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006132a56040830186612a19565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561330857600080fd5b60405160a0810167ffffffffffffffff828210818311171561332c5761332c612d88565b81604052843591508082111561334157600080fd5b5061334e36828601612f88565b82525061335d602084016129e1565b6020820152604083013561337081612a90565b604082015260608381013590820152608083013561338d81612a90565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec18336030181126133fb57600080fd5b9190910192915050565b6000610140823603121561341857600080fd5b613420612de1565b613429836129e1565b815261343760208401612e12565b6020820152604083013567ffffffffffffffff8082111561345757600080fd5b61346336838701612f88565b6040840152606085013591508082111561347c57600080fd5b5061348936828601612f88565b60608301525061349c3660808501612e3d565b60808201526134ae3660e08501612e3d565b60a082015292915050565b815167ffffffffffffffff8111156134d3576134d3612d88565b6134e7816134e18454612f35565b84613128565b602080601f83116001811461353a57600084156135045750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613170565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561358757888601518255948401946001909101908401613568565b50858210156135c357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526135f781840187612a19565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506136359050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612ce3565b60006020828403121561367e57600080fd5b81516117f581612e04565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561057857610578613689565b67ffffffffffffffff8416815260e0810161371760208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261229d565b6060810161057882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561379c57600080fd5b81516117f581612a90565b808202811582820484141761057857610578613689565b8082018082111561057857610578613689565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082613836577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fe4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e302d646576a164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b5060405162004508380380620045088339810160408190526200003491620008c0565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c2816200018f565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c05262000168576040805160008152602081019091526200016890846200023a565b5062000185925050506001600160a01b0385163060001962000397565b5050505062000afc565b336001600160a01b03821603620001e95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200025b576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002e65760008382815181106200027f576200027f620009d0565b60209081029190910101519050620002996002826200047d565b15620002dc576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200025e565b5060005b8151811015620003925760008282815181106200030b576200030b620009d0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000337575062000389565b620003446002826200049d565b1562000387576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002ea565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040f9190620009e6565b6200041b919062000a16565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047791869190620004b416565b50505050565b600062000494836001600160a01b03841662000585565b90505b92915050565b600062000494836001600160a01b03841662000689565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000503906001600160a01b038516908490620006db565b80519091501562000392578080602001905181019062000524919062000a2c565b620003925760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000086565b600081815260018301602052604081205480156200067e576000620005ac60018362000a57565b8554909150600090620005c29060019062000a57565b90508082146200062e576000866000018281548110620005e657620005e6620009d0565b90600052602060002001549050808760000184815481106200060c576200060c620009d0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000642576200064262000a6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000497565b600091505062000497565b6000818152600183016020526040812054620006d25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000497565b50600062000497565b6060620006ec8484600085620006f4565b949350505050565b606082471015620007575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000086565b600080866001600160a01b0316858760405162000775919062000aa9565b60006040518083038185875af1925050503d8060008114620007b4576040519150601f19603f3d011682016040523d82523d6000602084013e620007b9565b606091505b509092509050620007cd87838387620007d8565b979650505050505050565b606083156200084c57825160000362000844576001600160a01b0385163b620008445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000086565b5081620006ec565b620006ec8383815115620008635781518083602001fd5b8060405162461bcd60e51b815260040162000086919062000ac7565b6001600160a01b03811681146200089557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008bb816200087f565b919050565b60008060008060808587031215620008d757600080fd5b8451620008e4816200087f565b602086810151919550906001600160401b03808211156200090457600080fd5b818801915088601f8301126200091957600080fd5b8151818111156200092e576200092e62000898565b8060051b604051601f19603f8301168101818110858211171562000956576200095662000898565b60405291825284820192508381018501918b8311156200097557600080fd5b938501935b828510156200099e576200098e85620008ae565b845293850193928501926200097a565b809850505050505050620009b560408601620008ae565b9150620009c560608601620008ae565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000497576200049762000a00565b60006020828403121562000a3f57600080fd5b8151801515811462000a5057600080fd5b9392505050565b8181038181111562000497576200049762000a00565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa057818101518382015260200162000a86565b50506000910152565b6000825162000abd81846020870162000a83565b9190910192915050565b602081526000825180602084015262000ae881604085016020870162000a83565b601f01601f19169190910160400192915050565b60805160a05160c05161398f62000b79600039600081816104da0152818161177401526121580152600081816104b4015281816115a50152611a2a0152600081816102360152818161028b015281816106dd015281816114c50152818161194a01528181611b42015281816120ee0152612343015261398f6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc1461049f578063dc0bd971146104b2578063e0351e13146104d8578063f2fde38b146104fe57600080fd5b8063c4bffe2b14610464578063c75eea9c14610479578063cf7401f31461048c57600080fd5b8063b0f479a1116100c8578063b0f479a114610420578063b79465801461043e578063c0d786551461045157600080fd5b80639a4575b91461037c578063a7cd63b71461039c578063af58d59f146103b157600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103305780637d54534e146103385780638926f54f1461034b5780638da5cb5b1461035e57600080fd5b806354c8a4f3146102ea5780636d3d1a58146102ff57806378a010b21461031d57600080fd5b806321df0da71161018c57806321df0da714610234578063240028e81461027b57806339077537146102c857600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612ae6565b610511565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612b45565b6105f6565b6040516101d29190612bc4565b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e300060208201526101ee565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c6610289366004612c04565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102db6102d6366004612c21565b6106a6565b604051905181526020016101d2565b6102fd6102f8366004612ca9565b61082c565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610256565b6102fd61032b366004612d15565b6108a7565b6102fd610a1b565b6102fd610346366004612c04565b610b18565b6101c6610359366004612b45565b610b67565b60005473ffffffffffffffffffffffffffffffffffffffff16610256565b61038f61038a366004612d98565b610b7e565b6040516101d29190612dd3565b6103a4610c25565b6040516101d29190612e33565b6103c46103bf366004612b45565b610c36565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610256565b6101ee61044c366004612b45565b610d0b565b6102fd61045f366004612c04565b610d36565b61046c610e11565b6040516101d29190612e8d565b6103c4610487366004612b45565b610ec9565b6102fd61049a366004612ff5565b610f9b565b6102fd6104ad36600461303a565b611024565b7f0000000000000000000000000000000000000000000000000000000000000000610256565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b6102fd61050c366004612c04565b6114aa565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a457507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f057507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106219061307c565b80601f016020809104026020016040519081016040528092919081815260200182805461064d9061307c565b801561069a5780601f1061066f5761010080835404028352916020019161069a565b820191906000526020600020905b81548152906001019060200180831161067d57829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c66106c18361317a565b6114be565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107126060850160408601612c04565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078257600080fd5b505af1158015610796573d6000803e3d6000fd5b506107ab925050506060830160408401612c04565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161080d91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108346116ef565b6108a18484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061177292505050565b50505050565b6108af6116ef565b6108b883610b67565b6108ff576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109269061307c565b80601f01602080910402602001604051908101604052809291908181526020018280546109529061307c565b801561099f5780601f106109745761010080835404028352916020019161099f565b820191906000526020600020905b81548152906001019060200180831161098257829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109ce8385836132bf565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a0d939291906133d9565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f6565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b206116ef565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105f0600567ffffffffffffffff8416611928565b6040805180820190915260608082526020820152610ba3610b9e8361343d565b611943565b610bb08260600135611b0d565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0a84602001602081019061044c9190612b45565b81526040805160208181019092526000815291015292915050565b6060610c316002611bb6565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f090611bc3565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106219061307c565b610d3e6116ef565b73ffffffffffffffffffffffffffffffffffffffff8116610d8b576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e1f6005611bb6565b90506000815167ffffffffffffffff811115610e3d57610e3d612ecf565b604051908082528060200260200182016040528015610e66578160200160208202803683370190505b50905060005b8251811015610ec257828181518110610e8757610e876134df565b6020026020010151828281518110610ea157610ea16134df565b67ffffffffffffffff90921660209283029190910190910152600101610e6c565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f090611bc3565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fdb575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611014576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b61101f838383611c75565b505050565b61102c6116ef565b60005b8181101561101f57600083838381811061104b5761104b6134df565b905060200281019061105d919061350e565b6110669061354c565b905061107b8160800151826020015115611d5f565b61108e8160a00151826020015115611d5f565b80602001511561138a5780516110b09060059067ffffffffffffffff16611e98565b6110f55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f6565b604081015151158061110a5750606081015151155b15611141576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906113229082613600565b50606082015160058201906113379082613600565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061137d949392919061371a565b60405180910390a16114a1565b80516113a29060059067ffffffffffffffff16611ea4565b6113e75780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f6565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114506004830182612a98565b61145e600583016000612a98565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b5060010161102f565b6114b26116ef565b6114bb81611eb0565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115535760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f6565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162591906137b3565b1561165c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116698160200151611fa5565b600061167882602001516105f6565b905080516000148061169c575080805190602001208260a001518051906020012014155b156116d9578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f69190612bc4565b6116eb826020015183606001516120cb565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611770576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f6565b565b7f00000000000000000000000000000000000000000000000000000000000000006117c9576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561185f5760008382815181106117e9576117e96134df565b6020026020010151905061180781600261211290919063ffffffff16565b156118565760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117cc565b5060005b815181101561101f576000828281518110611880576118806134df565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118c45750611920565b6118cf600282612134565b1561191e5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611863565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119d85760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f6565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aaa91906137b3565b15611ae1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611aee8160400151612156565b611afb81602001516121d5565b6114bb81602001518260600151612323565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b5050505050565b6060600061193c83612367565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c5182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c3591906137ff565b85608001516fffffffffffffffffffffffffffffffff166123c2565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c7e83610b67565b611cc0576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f6565b611ccb826000611d5f565b67ffffffffffffffff83166000908152600760205260409020611cee90836123ec565b611cf9816000611d5f565b67ffffffffffffffff83166000908152600760205260409020611d1f90600201826123ec565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d5293929190613812565b60405180910390a1505050565b815115611e265781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611db5575060408201516fffffffffffffffffffffffffffffffff16155b15611dee57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f69190613895565b80156116eb576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e5f575060208201516fffffffffffffffffffffffffffffffff1615155b156116eb57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f69190613895565b600061193c838361258e565b600061193c83836125dd565b3373ffffffffffffffffffffffffffffffffffffffff821603611f2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fae81610b67565b611ff0576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f6565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561206f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209391906137b3565b6114bb576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b67ffffffffffffffff821660009081526007602052604090206116eb90600201827f00000000000000000000000000000000000000000000000000000000000000006126d0565b600061193c8373ffffffffffffffffffffffffffffffffffffffff84166125dd565b600061193c8373ffffffffffffffffffffffffffffffffffffffff841661258e565b7f0000000000000000000000000000000000000000000000000000000000000000156114bb57612187600282612a53565b6114bb576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f6565b6121de81610b67565b612220576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f6565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bd91906138d1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114bb576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b67ffffffffffffffff821660009081526007602052604090206116eb90827f00000000000000000000000000000000000000000000000000000000000000006126d0565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069a57602002820191906000526020600020905b8154815260200190600101908083116123a35750505050509050919050565b60006123e1856123d284866138ee565b6123dc9087613905565b612a82565b90505b949350505050565b815460009061241590700100000000000000000000000000000000900463ffffffff16426137ff565b905080156124b7576001830154835461245d916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166123c2565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546124dd916fffffffffffffffffffffffffffffffff9081169116612a82565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d52908490613895565b60008181526001830160205260408120546125d5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f0565b5060006105f0565b600081815260018301602052604081205480156126c65760006126016001836137ff565b8554909150600090612615906001906137ff565b905080821461267a576000866000018281548110612635576126356134df565b9060005260206000200154905080876000018481548110612658576126586134df565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268b5761268b613918565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f0565b60009150506105f0565b825474010000000000000000000000000000000000000000900460ff1615806126f7575081155b1561270157505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061274790700100000000000000000000000000000000900463ffffffff16426137ff565b905080156128075781831115612789576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127c39083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166123c2565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128be5773ffffffffffffffffffffffffffffffffffffffff8416612866576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f6565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f6565b848310156129d15760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690600090829061290290826137ff565b61290c878a6137ff565b6129169190613905565b6129209190613947565b905073ffffffffffffffffffffffffffffffffffffffff8616612979576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f6565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f6565b6129db85846137ff565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561193c565b6000818310612a91578161193c565b5090919050565b508054612aa49061307c565b6000825580601f10612ab4575050565b601f0160209004906000526020600020908101906114bb91905b80821115612ae25760008155600101612ace565b5090565b600060208284031215612af857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461193c57600080fd5b803567ffffffffffffffff81168114612b4057600080fd5b919050565b600060208284031215612b5757600080fd5b61193c82612b28565b6000815180845260005b81811015612b8657602081850181015186830182015201612b6a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061193c6020830184612b60565b73ffffffffffffffffffffffffffffffffffffffff811681146114bb57600080fd5b8035612b4081612bd7565b600060208284031215612c1657600080fd5b813561193c81612bd7565b600060208284031215612c3357600080fd5b813567ffffffffffffffff811115612c4a57600080fd5b8201610100818503121561193c57600080fd5b60008083601f840112612c6f57600080fd5b50813567ffffffffffffffff811115612c8757600080fd5b6020830191508360208260051b8501011115612ca257600080fd5b9250929050565b60008060008060408587031215612cbf57600080fd5b843567ffffffffffffffff80821115612cd757600080fd5b612ce388838901612c5d565b90965094506020870135915080821115612cfc57600080fd5b50612d0987828801612c5d565b95989497509550505050565b600080600060408486031215612d2a57600080fd5b612d3384612b28565b9250602084013567ffffffffffffffff80821115612d5057600080fd5b818601915086601f830112612d6457600080fd5b813581811115612d7357600080fd5b876020828501011115612d8557600080fd5b6020830194508093505050509250925092565b600060208284031215612daa57600080fd5b813567ffffffffffffffff811115612dc157600080fd5b820160a0818503121561193c57600080fd5b602081526000825160406020840152612def6060840182612b60565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e2a8282612b60565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8157835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612e4f565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8157835167ffffffffffffffff1683529284019291840191600101612ea9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612f2257612f22612ecf565b60405290565b60405160c0810167ffffffffffffffff81118282101715612f2257612f22612ecf565b80151581146114bb57600080fd5b8035612b4081612f4b565b80356fffffffffffffffffffffffffffffffff81168114612b4057600080fd5b600060608284031215612f9657600080fd5b6040516060810181811067ffffffffffffffff82111715612fb957612fb9612ecf565b6040529050808235612fca81612f4b565b8152612fd860208401612f64565b6020820152612fe960408401612f64565b60408201525092915050565b600080600060e0848603121561300a57600080fd5b61301384612b28565b92506130228560208601612f84565b91506130318560808601612f84565b90509250925092565b6000806020838503121561304d57600080fd5b823567ffffffffffffffff81111561306457600080fd5b61307085828601612c5d565b90969095509350505050565b600181811c9082168061309057607f821691505b6020821081036130c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126130e057600080fd5b813567ffffffffffffffff808211156130fb576130fb612ecf565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561314157613141612ecf565b8160405283815286602085880101111561315a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561318d57600080fd5b613195612efe565b823567ffffffffffffffff808211156131ad57600080fd5b6131b9368387016130cf565b83526131c760208601612b28565b60208401526131d860408601612bf9565b6040840152606085013560608401526131f360808601612bf9565b608084015260a085013591508082111561320c57600080fd5b613218368387016130cf565b60a084015260c085013591508082111561323157600080fd5b61323d368387016130cf565b60c084015260e085013591508082111561325657600080fd5b50613263368286016130cf565b60e08301525092915050565b601f82111561101f576000816000526020600020601f850160051c810160208610156132985750805b601f850160051c820191505b818110156132b7578281556001016132a4565b505050505050565b67ffffffffffffffff8311156132d7576132d7612ecf565b6132eb836132e5835461307c565b8361326f565b6000601f84116001811461333d57600085156133075750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611baf565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561338c578685013582556020948501946001909201910161336c565b50868210156133c7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133ec6040830186612b60565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561344f57600080fd5b60405160a0810167ffffffffffffffff828210818311171561347357613473612ecf565b81604052843591508082111561348857600080fd5b50613495368286016130cf565b8252506134a460208401612b28565b602082015260408301356134b781612bd7565b60408201526060838101359082015260808301356134d481612bd7565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261354257600080fd5b9190910192915050565b6000610140823603121561355f57600080fd5b613567612f28565b61357083612b28565b815261357e60208401612f59565b6020820152604083013567ffffffffffffffff8082111561359e57600080fd5b6135aa368387016130cf565b604084015260608501359150808211156135c357600080fd5b506135d0368286016130cf565b6060830152506135e33660808501612f84565b60808201526135f53660e08501612f84565b60a082015292915050565b815167ffffffffffffffff81111561361a5761361a612ecf565b61362e81613628845461307c565b8461326f565b602080601f831160018114613681576000841561364b5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556132b7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156136ce578886015182559484019460019091019084016136af565b508582101561370a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261373e81840187612b60565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061377c9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e2a565b6000602082840312156137c557600080fd5b815161193c81612f4b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f0576105f06137d0565b67ffffffffffffffff8416815260e0810161385e60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526123e4565b606081016105f082848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156138e357600080fd5b815161193c81612bd7565b80820281158282048414176105f0576105f06137d0565b808201808211156105f0576105f06137d0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261397d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var BurnWithFromMintTokenPoolABI = BurnWithFromMintTokenPoolMetaData.ABI @@ -310,6 +310,28 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetCur return _BurnWithFromMintTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPool.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 (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnWithFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnWithFromMintTokenPool.CallOpts) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnWithFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnWithFromMintTokenPool.CallOpts) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) @@ -624,6 +646,18 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Se return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnWithFromMintTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnWithFromMintTokenPool.TransactOpts, rateLimitAdmin) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) } @@ -2644,6 +2678,8 @@ type BurnWithFromMintTokenPoolInterface interface { GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2678,6 +2714,8 @@ type BurnWithFromMintTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool_and_proxy/burn_with_from_mint_token_pool_and_proxy.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool_and_proxy/burn_with_from_mint_token_pool_and_proxy.go new file mode 100644 index 00000000000..c0c6857c73e --- /dev/null +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool_and_proxy/burn_with_from_mint_token_pool_and_proxy.go @@ -0,0 +1,3034 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package burn_with_from_mint_token_pool_and_proxy + +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 + Allowed bool + RemotePoolAddress []byte + RemoteTokenAddress []byte + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig +} + +var BurnWithFromMintTokenPoolAndProxyMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"oldPool\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"LegacyPoolChanged\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"onRampAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPreviousPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"getRemotePool\",\"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\":[{\"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\":[{\"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\"},{\"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\":\"contractIPoolPriorTo1_5\",\"name\":\"prevPool\",\"type\":\"address\"}],\"name\":\"setPreviousPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x60e06040523480156200001157600080fd5b5060405162004dde38038062004dde8339810160408190526200003491620008cc565b83838383838383833380600081620000935760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c657620000c6816200019b565b5050506001600160a01b0384161580620000e757506001600160a01b038116155b80620000fa57506001600160a01b038216155b1562000119576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016c576040805160008152602081019091526200016c908462000246565b50620001919650506001600160a01b038a169450309350600019925050620003a39050565b5050505062000b08565b336001600160a01b03821603620001f55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008a565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000267576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002f25760008382815181106200028b576200028b620009dc565b60209081029190910101519050620002a560028262000489565b15620002e8576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200026a565b5060005b81518110156200039e576000828281518110620003175762000317620009dc565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000343575062000395565b62000350600282620004a9565b1562000393576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002f6565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041b9190620009f2565b62000427919062000a22565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200048391869190620004c016565b50505050565b6000620004a0836001600160a01b03841662000591565b90505b92915050565b6000620004a0836001600160a01b03841662000695565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200050f906001600160a01b038516908490620006e7565b8051909150156200039e578080602001905181019062000530919062000a38565b6200039e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200008a565b600081815260018301602052604081205480156200068a576000620005b860018362000a63565b8554909150600090620005ce9060019062000a63565b90508082146200063a576000866000018281548110620005f257620005f2620009dc565b9060005260206000200154905080876000018481548110620006185762000618620009dc565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200064e576200064e62000a79565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004a3565b6000915050620004a3565b6000818152600183016020526040812054620006de57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004a3565b506000620004a3565b6060620006f8848460008562000700565b949350505050565b606082471015620007635760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200008a565b600080866001600160a01b0316858760405162000781919062000ab5565b60006040518083038185875af1925050503d8060008114620007c0576040519150601f19603f3d011682016040523d82523d6000602084013e620007c5565b606091505b509092509050620007d987838387620007e4565b979650505050505050565b606083156200085857825160000362000850576001600160a01b0385163b620008505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200008a565b5081620006f8565b620006f883838151156200086f5781518083602001fd5b8060405162461bcd60e51b81526004016200008a919062000ad3565b6001600160a01b0381168114620008a157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008c7816200088b565b919050565b60008060008060808587031215620008e357600080fd5b8451620008f0816200088b565b602086810151919550906001600160401b03808211156200091057600080fd5b818801915088601f8301126200092557600080fd5b8151818111156200093a576200093a620008a4565b8060051b604051601f19603f83011681018181108582111715620009625762000962620008a4565b60405291825284820192508381018501918b8311156200098157600080fd5b938501935b82851015620009aa576200099a85620008ba565b8452938501939285019262000986565b809850505050505050620009c160408601620008ba565b9150620009d160608601620008ba565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a0557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004a357620004a362000a0c565b60006020828403121562000a4b57600080fd5b8151801515811462000a5c57600080fd5b9392505050565b81810381811115620004a357620004a362000a0c565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aac57818101518382015260200162000a92565b50506000910152565b6000825162000ac981846020870162000a8f565b9190910192915050565b602081526000825180602084015262000af481604085016020870162000a8f565b601f01601f19169190910160400192915050565b60805160a05160c05161425262000b8c6000396000818161052c01528181611ad60152612528015260008181610506015281816118690152611d89015260008181610231015281816102860152818161076801528181610df40152818161178901528181611ca901528181611e8f015281816124be015261271301526142526000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063db6327dc11610071578063db6327dc146104f1578063dc0bd97114610504578063e0351e131461052a578063f2fde38b1461055057600080fd5b8063c0d78655146104a3578063c4bffe2b146104b6578063c75eea9c146104cb578063cf7401f3146104de57600080fd5b8063a8d87a3b116100de578063a8d87a3b146103f0578063af58d59f14610403578063b0f479a114610472578063b79465801461049057600080fd5b80639a4575b91461039d578063a2b261d8146103bd578063a7cd63b7146103db57600080fd5b80636d3d1a581161017c57806383826b2b1161014b57806383826b2b146103465780638926f54f146103595780638da5cb5b1461036c5780639766b9321461038a57600080fd5b80636d3d1a58146102fa57806378a010b21461031857806379ba50971461032b5780637d54534e1461033357600080fd5b806321df0da7116101b857806321df0da71461022f578063240028e81461027657806339077537146102c357806354c8a4f3146102e557600080fd5b806301ffc9a7146101df5780630a2fd49314610207578063181f5a7714610227575b600080fd5b6101f26101ed3660046131c0565b610563565b60405190151581526020015b60405180910390f35b61021a61021536600461321f565b610648565b6040516101fe91906132a8565b61021a6106f8565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102843660046132e8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102d66102d1366004613305565b610714565b604051905181526020016101fe565b6102f86102f336600461338d565b6108cc565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610251565b6102f86103263660046133f9565b610947565b6102f8610abb565b6102f86103413660046132e8565b610bb8565b6101f261035436600461347c565b610c07565b6101f261036736600461321f565b610cd4565b60005473ffffffffffffffffffffffffffffffffffffffff16610251565b6102f86103983660046132e8565b610ceb565b6103b06103ab3660046134b3565b610d7a565b6040516101fe91906134ee565b60095473ffffffffffffffffffffffffffffffffffffffff16610251565b6103e3610ef0565b6040516101fe919061354e565b6102516103fe36600461321f565b503090565b61041661041136600461321f565b610f01565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610251565b61021a61049e36600461321f565b610fd6565b6102f86104b13660046132e8565b611001565b6104be6110d5565b6040516101fe91906135a8565b6104166104d936600461321f565b61118d565b6102f86104ec36600461375f565b61125f565b6102f86104ff3660046137a4565b6112e8565b7f0000000000000000000000000000000000000000000000000000000000000000610251565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b6102f861055e3660046132e8565b61176e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105f657507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061064257507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610673906137e6565b80601f016020809104026020016040519081016040528092919081815260200182805461069f906137e6565b80156106ec5780601f106106c1576101008083540402835291602001916106ec565b820191906000526020600020905b8154815290600101906020018083116106cf57829003601f168201915b50505050509050919050565b60405180606001604052806027815260200161421f6027913981565b60408051602081019091526000815261073461072f836138d5565b611782565b60095473ffffffffffffffffffffffffffffffffffffffff1661082a5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961079d60608501604086016132e8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561080d57600080fd5b505af1158015610821573d6000803e3d6000fd5b5050505061083b565b61083b610836836138d5565b6119b3565b61084b60608301604084016132e8565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f084606001356040516108ad91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108d4611a51565b61094184848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ad492505050565b50505050565b61094f611a51565b61095883610cd4565b61099f576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109c6906137e6565b80601f01602080910402602001604051908101604052809291908181526020018280546109f2906137e6565b8015610a3f5780601f10610a1457610100808354040283529160200191610a3f565b820191906000526020600020905b815481529060010190602001808311610a2257829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610a6e838583613a1a565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610aad93929190613b34565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610996565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bc0611a51565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600073ffffffffffffffffffffffffffffffffffffffff8216301480610ccd5750600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86169281019290925273ffffffffffffffffffffffffffffffffffffffff848116602484015216906383826b2b90604401602060405180830381865afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd9190613b98565b9392505050565b6000610642600567ffffffffffffffff8416611c8a565b610cf3611a51565b6009805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f81accd0a7023865eaa51b3399dd0eafc488bf3ba238402911e1659cfe860f22891015b60405180910390a15050565b6040805180820190915260608082526020820152610d9f610d9a83613bb5565b611ca2565b60095473ffffffffffffffffffffffffffffffffffffffff16610e6a576040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152606083013560248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b158015610e4d57600080fd5b505af1158015610e61573d6000803e3d6000fd5b50505050610e7b565b610e7b610e7683613bb5565b611e6c565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610ed584602001602081019061049e919061321f565b81526040805160208181019092526000815291015292915050565b6060610efc6002611f86565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261064290611f93565b67ffffffffffffffff81166000908152600760205260409020600501805460609190610673906137e6565b611009611a51565b73ffffffffffffffffffffffffffffffffffffffff8116611056576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610d6e565b606060006110e36005611f86565b90506000815167ffffffffffffffff811115611101576111016135ea565b60405190808252806020026020018201604052801561112a578160200160208202803683370190505b50905060005b82518110156111865782818151811061114b5761114b613c57565b602002602001015182828151811061116557611165613c57565b67ffffffffffffffff90921660209283029190910190910152600101611130565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261064290611f93565b60085473ffffffffffffffffffffffffffffffffffffffff16331480159061129f575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156112d8576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610996565b6112e3838383612045565b505050565b6112f0611a51565b60005b818110156112e357600083838381811061130f5761130f613c57565b90506020028101906113219190613c86565b61132a90613cc4565b905061133f816080015182602001511561212f565b6113528160a0015182602001511561212f565b80602001511561164e5780516113749060059067ffffffffffffffff16612268565b6113b95780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610996565b60408101515115806113ce5750606081015151155b15611405576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906115e69082613d78565b50606082015160058201906115fb9082613d78565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506116419493929190613e92565b60405180910390a1611765565b80516116669060059067ffffffffffffffff16612274565b6116ab5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610996565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906117146004830182613172565b611722600583016000613172565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016112f3565b611776611a51565b61177f81612280565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146118175760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610996565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190613b98565b15611920576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61192d8160200151612375565b600061193c8260200151610648565b9050805160001480611960575080805190602001208260a001518051906020012014155b1561199d578160a001516040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161099691906132a8565b6119af8260200151836060015161249b565b5050565b60095481516040808401516060850151602086015192517f8627fad600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951694638627fad694611a1c9490939291600401613f2b565b600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ad2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610996565b565b7f0000000000000000000000000000000000000000000000000000000000000000611b2b576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611bc1576000838281518110611b4b57611b4b613c57565b60200260200101519050611b698160026124e290919063ffffffff16565b15611bb85760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611b2e565b5060005b81518110156112e3576000828281518110611be257611be2613c57565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611c265750611c82565b611c31600282612504565b15611c805760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611bc5565b60008181526001830160205260408120541515610ccd565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611d375760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610996565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e099190613b98565b15611e40576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e4d8160400151612526565b611e5a81602001516125a5565b61177f816020015182606001516126f3565b6009546060820151611eb99173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692911690612737565b60095460408083015183516060850151602086015193517f9687544500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951694639687544594611f2194939291600401613f8c565b6000604051808303816000875af1158015611f40573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526119af9190810190613fec565b60606000610ccd836127c4565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261202182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426120059190614089565b85608001516fffffffffffffffffffffffffffffffff1661281f565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61204e83610cd4565b612090576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610996565b61209b82600061212f565b67ffffffffffffffff831660009081526007602052604090206120be9083612849565b6120c981600061212f565b67ffffffffffffffff831660009081526007602052604090206120ef9060020182612849565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516121229392919061409c565b60405180910390a1505050565b8151156121f65781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612185575060408201516fffffffffffffffffffffffffffffffff16155b156121be57816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610996919061411f565b80156119af576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff1615158061222f575060208201516fffffffffffffffffffffffffffffffff1615155b156119af57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610996919061411f565b6000610ccd83836129eb565b6000610ccd8383612a3a565b3373ffffffffffffffffffffffffffffffffffffffff8216036122ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610996565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61237e81610cd4565b6123c0576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610996565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561243f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124639190613b98565b61177f576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610996565b67ffffffffffffffff821660009081526007602052604090206119af90600201827f0000000000000000000000000000000000000000000000000000000000000000612b2d565b6000610ccd8373ffffffffffffffffffffffffffffffffffffffff8416612a3a565b6000610ccd8373ffffffffffffffffffffffffffffffffffffffff84166129eb565b7f00000000000000000000000000000000000000000000000000000000000000001561177f57612557600282612eb0565b61177f576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610996565b6125ae81610cd4565b6125f0576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610996565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612669573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268d919061415b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461177f576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610996565b67ffffffffffffffff821660009081526007602052604090206119af90827f0000000000000000000000000000000000000000000000000000000000000000612b2d565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526112e3908490612edf565b6060816000018054806020026020016040519081016040528092919081815260200182805480156106ec57602002820191906000526020600020905b8154815260200190600101908083116128005750505050509050919050565b600061283e8561282f8486614178565b612839908761418f565b612feb565b90505b949350505050565b815460009061287290700100000000000000000000000000000000900463ffffffff1642614089565b9050801561291457600183015483546128ba916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661281f565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461293a916fffffffffffffffffffffffffffffffff9081169116612feb565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061212290849061411f565b6000818152600183016020526040812054612a3257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610642565b506000610642565b60008181526001830160205260408120548015612b23576000612a5e600183614089565b8554909150600090612a7290600190614089565b9050808214612ad7576000866000018281548110612a9257612a92613c57565b9060005260206000200154905080876000018481548110612ab557612ab5613c57565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae857612ae86141a2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610642565b6000915050610642565b825474010000000000000000000000000000000000000000900460ff161580612b54575081155b15612b5e57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612ba490700100000000000000000000000000000000900463ffffffff1642614089565b90508015612c645781831115612be6576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612c209083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661281f565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612d1b5773ffffffffffffffffffffffffffffffffffffffff8416612cc3576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610996565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610996565b84831015612e2e5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612d5f9082614089565b612d69878a614089565b612d73919061418f565b612d7d91906141d1565b905073ffffffffffffffffffffffffffffffffffffffff8616612dd6576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610996565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610996565b612e388584614089565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610ccd565b6000612f41826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130019092919063ffffffff16565b8051909150156112e35780806020019051810190612f5f9190613b98565b6112e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610996565b6000818310612ffa5781610ccd565b5090919050565b60606128418484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051613035919061420c565b60006040518083038185875af1925050503d8060008114613072576040519150601f19603f3d011682016040523d82523d6000602084013e613077565b606091505b509150915061308887838387613093565b979650505050505050565b606083156131295782516000036131225773ffffffffffffffffffffffffffffffffffffffff85163b613122576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610996565b5081612841565b612841838381511561313e5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099691906132a8565b50805461317e906137e6565b6000825580601f1061318e575050565b601f01602090049060005260206000209081019061177f91905b808211156131bc57600081556001016131a8565b5090565b6000602082840312156131d257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610ccd57600080fd5b803567ffffffffffffffff8116811461321a57600080fd5b919050565b60006020828403121561323157600080fd5b610ccd82613202565b60005b8381101561325557818101518382015260200161323d565b50506000910152565b6000815180845261327681602086016020860161323a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ccd602083018461325e565b73ffffffffffffffffffffffffffffffffffffffff8116811461177f57600080fd5b803561321a816132bb565b6000602082840312156132fa57600080fd5b8135610ccd816132bb565b60006020828403121561331757600080fd5b813567ffffffffffffffff81111561332e57600080fd5b82016101008185031215610ccd57600080fd5b60008083601f84011261335357600080fd5b50813567ffffffffffffffff81111561336b57600080fd5b6020830191508360208260051b850101111561338657600080fd5b9250929050565b600080600080604085870312156133a357600080fd5b843567ffffffffffffffff808211156133bb57600080fd5b6133c788838901613341565b909650945060208701359150808211156133e057600080fd5b506133ed87828801613341565b95989497509550505050565b60008060006040848603121561340e57600080fd5b61341784613202565b9250602084013567ffffffffffffffff8082111561343457600080fd5b818601915086601f83011261344857600080fd5b81358181111561345757600080fd5b87602082850101111561346957600080fd5b6020830194508093505050509250925092565b6000806040838503121561348f57600080fd5b61349883613202565b915060208301356134a8816132bb565b809150509250929050565b6000602082840312156134c557600080fd5b813567ffffffffffffffff8111156134dc57600080fd5b820160a08185031215610ccd57600080fd5b60208152600082516040602084015261350a606084018261325e565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152613545828261325e565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561359c57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161356a565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561359c57835167ffffffffffffffff16835292840192918401916001016135c4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff8111828210171561363d5761363d6135ea565b60405290565b60405160c0810167ffffffffffffffff8111828210171561363d5761363d6135ea565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136ad576136ad6135ea565b604052919050565b801515811461177f57600080fd5b803561321a816136b5565b80356fffffffffffffffffffffffffffffffff8116811461321a57600080fd5b60006060828403121561370057600080fd5b6040516060810181811067ffffffffffffffff82111715613723576137236135ea565b6040529050808235613734816136b5565b8152613742602084016136ce565b6020820152613753604084016136ce565b60408201525092915050565b600080600060e0848603121561377457600080fd5b61377d84613202565b925061378c85602086016136ee565b915061379b85608086016136ee565b90509250925092565b600080602083850312156137b757600080fd5b823567ffffffffffffffff8111156137ce57600080fd5b6137da85828601613341565b90969095509350505050565b600181811c908216806137fa57607f821691505b602082108103613833577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600067ffffffffffffffff821115613853576138536135ea565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261389057600080fd5b81356138a361389e82613839565b613666565b8181528460208386010111156138b857600080fd5b816020850160208301376000918101602001919091529392505050565b600061010082360312156138e857600080fd5b6138f0613619565b823567ffffffffffffffff8082111561390857600080fd5b6139143683870161387f565b835261392260208601613202565b6020840152613933604086016132dd565b60408401526060850135606084015261394e608086016132dd565b608084015260a085013591508082111561396757600080fd5b6139733683870161387f565b60a084015260c085013591508082111561398c57600080fd5b6139983683870161387f565b60c084015260e08501359150808211156139b157600080fd5b506139be3682860161387f565b60e08301525092915050565b601f8211156112e3576000816000526020600020601f850160051c810160208610156139f35750805b601f850160051c820191505b81811015613a12578281556001016139ff565b505050505050565b67ffffffffffffffff831115613a3257613a326135ea565b613a4683613a4083546137e6565b836139ca565b6000601f841160018114613a985760008515613a625750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611a4a565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613ae75786850135825560209485019460019092019101613ac7565b5086821015613b22577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b604081526000613b47604083018661325e565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060208284031215613baa57600080fd5b8151610ccd816136b5565b600060a08236031215613bc757600080fd5b60405160a0810167ffffffffffffffff8282108183111715613beb57613beb6135ea565b816040528435915080821115613c0057600080fd5b50613c0d3682860161387f565b825250613c1c60208401613202565b60208201526040830135613c2f816132bb565b6040820152606083810135908201526080830135613c4c816132bb565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613cba57600080fd5b9190910192915050565b60006101408236031215613cd757600080fd5b613cdf613643565b613ce883613202565b8152613cf6602084016136c3565b6020820152604083013567ffffffffffffffff80821115613d1657600080fd5b613d223683870161387f565b60408401526060850135915080821115613d3b57600080fd5b50613d483682860161387f565b606083015250613d5b36608085016136ee565b6080820152613d6d3660e085016136ee565b60a082015292915050565b815167ffffffffffffffff811115613d9257613d926135ea565b613da681613da084546137e6565b846139ca565b602080601f831160018114613df95760008415613dc35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613a12565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e4657888601518255948401946001909101908401613e27565b5085821015613e8257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613eb68184018761325e565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613ef49050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613545565b60a081526000613f3e60a083018761325e565b73ffffffffffffffffffffffffffffffffffffffff8616602084015284604084015267ffffffffffffffff841660608401528281036080840152600081526020810191505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8516815260a060208201526000613fbb60a083018661325e565b60408301949094525067ffffffffffffffff9190911660608201528082036080909101526000815260200192915050565b600060208284031215613ffe57600080fd5b815167ffffffffffffffff81111561401557600080fd5b8201601f8101841361402657600080fd5b805161403461389e82613839565b81815285602083850101111561404957600080fd5b61354582602083016020860161323a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106425761064261405a565b67ffffffffffffffff8416815260e081016140e860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612841565b6060810161064282848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561416d57600080fd5b8151610ccd816132bb565b80820281158282048414176106425761064261405a565b808201808211156106425761064261405a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614207577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613cba81846020870161323a56fe4275726e5769746846726f6d4d696e74546f6b656e506f6f6c416e6450726f787920312e352e30a164736f6c6343000818000a", +} + +var BurnWithFromMintTokenPoolAndProxyABI = BurnWithFromMintTokenPoolAndProxyMetaData.ABI + +var BurnWithFromMintTokenPoolAndProxyBin = BurnWithFromMintTokenPoolAndProxyMetaData.Bin + +func DeployBurnWithFromMintTokenPoolAndProxy(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnWithFromMintTokenPoolAndProxy, error) { + parsed, err := BurnWithFromMintTokenPoolAndProxyMetaData.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(BurnWithFromMintTokenPoolAndProxyBin), backend, token, allowlist, rmnProxy, router) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &BurnWithFromMintTokenPoolAndProxy{address: address, abi: *parsed, BurnWithFromMintTokenPoolAndProxyCaller: BurnWithFromMintTokenPoolAndProxyCaller{contract: contract}, BurnWithFromMintTokenPoolAndProxyTransactor: BurnWithFromMintTokenPoolAndProxyTransactor{contract: contract}, BurnWithFromMintTokenPoolAndProxyFilterer: BurnWithFromMintTokenPoolAndProxyFilterer{contract: contract}}, nil +} + +type BurnWithFromMintTokenPoolAndProxy struct { + address common.Address + abi abi.ABI + BurnWithFromMintTokenPoolAndProxyCaller + BurnWithFromMintTokenPoolAndProxyTransactor + BurnWithFromMintTokenPoolAndProxyFilterer +} + +type BurnWithFromMintTokenPoolAndProxyCaller struct { + contract *bind.BoundContract +} + +type BurnWithFromMintTokenPoolAndProxyTransactor struct { + contract *bind.BoundContract +} + +type BurnWithFromMintTokenPoolAndProxyFilterer struct { + contract *bind.BoundContract +} + +type BurnWithFromMintTokenPoolAndProxySession struct { + Contract *BurnWithFromMintTokenPoolAndProxy + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type BurnWithFromMintTokenPoolAndProxyCallerSession struct { + Contract *BurnWithFromMintTokenPoolAndProxyCaller + CallOpts bind.CallOpts +} + +type BurnWithFromMintTokenPoolAndProxyTransactorSession struct { + Contract *BurnWithFromMintTokenPoolAndProxyTransactor + TransactOpts bind.TransactOpts +} + +type BurnWithFromMintTokenPoolAndProxyRaw struct { + Contract *BurnWithFromMintTokenPoolAndProxy +} + +type BurnWithFromMintTokenPoolAndProxyCallerRaw struct { + Contract *BurnWithFromMintTokenPoolAndProxyCaller +} + +type BurnWithFromMintTokenPoolAndProxyTransactorRaw struct { + Contract *BurnWithFromMintTokenPoolAndProxyTransactor +} + +func NewBurnWithFromMintTokenPoolAndProxy(address common.Address, backend bind.ContractBackend) (*BurnWithFromMintTokenPoolAndProxy, error) { + abi, err := abi.JSON(strings.NewReader(BurnWithFromMintTokenPoolAndProxyABI)) + if err != nil { + return nil, err + } + contract, err := bindBurnWithFromMintTokenPoolAndProxy(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxy{address: address, abi: abi, BurnWithFromMintTokenPoolAndProxyCaller: BurnWithFromMintTokenPoolAndProxyCaller{contract: contract}, BurnWithFromMintTokenPoolAndProxyTransactor: BurnWithFromMintTokenPoolAndProxyTransactor{contract: contract}, BurnWithFromMintTokenPoolAndProxyFilterer: BurnWithFromMintTokenPoolAndProxyFilterer{contract: contract}}, nil +} + +func NewBurnWithFromMintTokenPoolAndProxyCaller(address common.Address, caller bind.ContractCaller) (*BurnWithFromMintTokenPoolAndProxyCaller, error) { + contract, err := bindBurnWithFromMintTokenPoolAndProxy(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyCaller{contract: contract}, nil +} + +func NewBurnWithFromMintTokenPoolAndProxyTransactor(address common.Address, transactor bind.ContractTransactor) (*BurnWithFromMintTokenPoolAndProxyTransactor, error) { + contract, err := bindBurnWithFromMintTokenPoolAndProxy(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyTransactor{contract: contract}, nil +} + +func NewBurnWithFromMintTokenPoolAndProxyFilterer(address common.Address, filterer bind.ContractFilterer) (*BurnWithFromMintTokenPoolAndProxyFilterer, error) { + contract, err := bindBurnWithFromMintTokenPoolAndProxy(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyFilterer{contract: contract}, nil +} + +func bindBurnWithFromMintTokenPoolAndProxy(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BurnWithFromMintTokenPoolAndProxyMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BurnWithFromMintTokenPoolAndProxy.Contract.BurnWithFromMintTokenPoolAndProxyCaller.contract.Call(opts, result, method, params...) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.BurnWithFromMintTokenPoolAndProxyTransactor.contract.Transfer(opts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.BurnWithFromMintTokenPoolAndProxyTransactor.contract.Transact(opts, method, params...) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BurnWithFromMintTokenPoolAndProxy.Contract.contract.Call(opts, result, method, params...) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.contract.Transfer(opts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.contract.Transact(opts, method, params...) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetAllowList() ([]common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetAllowList(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetAllowList() ([]common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetAllowList(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "getAllowListEnabled") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetAllowListEnabled() (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetAllowListEnabled(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetAllowListEnabled() (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetAllowListEnabled(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetCurrentInboundRateLimiterState(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetCurrentInboundRateLimiterState(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetCurrentOutboundRateLimiterState(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetCurrentOutboundRateLimiterState(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetOnRamp(opts *bind.CallOpts, arg0 uint64) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "getOnRamp", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetOnRamp(arg0 uint64) (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetOnRamp(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, arg0) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetOnRamp(arg0 uint64) (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetOnRamp(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, arg0) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetPreviousPool(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "getPreviousPool") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetPreviousPool() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetPreviousPool(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetPreviousPool() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetPreviousPool(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetRateLimitAdmin() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRateLimitAdmin(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRateLimitAdmin(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRemotePool(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRemotePool(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRemoteToken(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRemoteToken(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetRmnProxy(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetRmnProxy() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRmnProxy(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetRmnProxy() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRmnProxy(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetRouter() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRouter(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetRouter() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetRouter(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetSupportedChains(opts *bind.CallOpts) ([]uint64, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "getSupportedChains") + + if err != nil { + return *new([]uint64), err + } + + out0 := *abi.ConvertType(out[0], new([]uint64)).(*[]uint64) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetSupportedChains() ([]uint64, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetSupportedChains(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetSupportedChains() ([]uint64, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetSupportedChains(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) GetToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) GetToken() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetToken(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) GetToken() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.GetToken(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) IsOffRamp(opts *bind.CallOpts, sourceChainSelector uint64, offRamp common.Address) (bool, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "isOffRamp", sourceChainSelector, offRamp) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) IsOffRamp(sourceChainSelector uint64, offRamp common.Address) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.IsOffRamp(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, sourceChainSelector, offRamp) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) IsOffRamp(sourceChainSelector uint64, offRamp common.Address) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.IsOffRamp(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, sourceChainSelector, offRamp) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) IsSupportedChain(remoteChainSelector uint64) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.IsSupportedChain(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.IsSupportedChain(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, remoteChainSelector) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) IsSupportedToken(token common.Address) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.IsSupportedToken(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, token) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) IsSupportedToken(token common.Address) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.IsSupportedToken(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, token) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) Owner() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.Owner(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) Owner() (common.Address, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.Owner(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SupportsInterface(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, interfaceId) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SupportsInterface(&_BurnWithFromMintTokenPoolAndProxy.CallOpts, interfaceId) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _BurnWithFromMintTokenPoolAndProxy.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) TypeAndVersion() (string, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.TypeAndVersion(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyCallerSession) TypeAndVersion() (string, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.TypeAndVersion(&_BurnWithFromMintTokenPoolAndProxy.CallOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "acceptOwnership") +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) AcceptOwnership() (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.AcceptOwnership(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.AcceptOwnership(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "applyAllowListUpdates", removes, adds) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.ApplyAllowListUpdates(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, removes, adds) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.ApplyAllowListUpdates(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, removes, adds) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "applyChainUpdates", chains) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, chains) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, chains) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "lockOrBurn", lockOrBurnIn) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.LockOrBurn(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, lockOrBurnIn) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.LockOrBurn(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, lockOrBurnIn) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "releaseOrMint", releaseOrMintIn) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.ReleaseOrMint(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, releaseOrMintIn) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.ReleaseOrMint(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, releaseOrMintIn) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) SetPreviousPool(opts *bind.TransactOpts, prevPool common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "setPreviousPool", prevPool) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) SetPreviousPool(prevPool common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetPreviousPool(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, prevPool) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) SetPreviousPool(prevPool common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetPreviousPool(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, prevPool) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetRateLimitAdmin(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, rateLimitAdmin) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetRateLimitAdmin(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, rateLimitAdmin) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetRemotePool(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetRemotePool(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "setRouter", newRouter) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) SetRouter(newRouter common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetRouter(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, newRouter) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) SetRouter(newRouter common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.SetRouter(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, newRouter) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.contract.Transact(opts, "transferOwnership", to) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.TransferOwnership(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, to) +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BurnWithFromMintTokenPoolAndProxy.Contract.TransferOwnership(&_BurnWithFromMintTokenPoolAndProxy.TransactOpts, to) +} + +type BurnWithFromMintTokenPoolAndProxyAllowListAddIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyAllowListAdd + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyAllowListAddIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyAllowListAdd) + 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(BurnWithFromMintTokenPoolAndProxyAllowListAdd) + 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 *BurnWithFromMintTokenPoolAndProxyAllowListAddIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyAllowListAddIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyAllowListAdd struct { + Sender common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyAllowListAddIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "AllowListAdd") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyAllowListAddIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyAllowListAdd) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyAllowListAdd) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseAllowListAdd(log types.Log) (*BurnWithFromMintTokenPoolAndProxyAllowListAdd, error) { + event := new(BurnWithFromMintTokenPoolAndProxyAllowListAdd) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "AllowListAdd", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyAllowListRemove + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyAllowListRemove) + 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(BurnWithFromMintTokenPoolAndProxyAllowListRemove) + 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 *BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyAllowListRemove struct { + Sender common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "AllowListRemove") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyAllowListRemove) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyAllowListRemove) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseAllowListRemove(log types.Log) (*BurnWithFromMintTokenPoolAndProxyAllowListRemove, error) { + event := new(BurnWithFromMintTokenPoolAndProxyAllowListRemove) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "AllowListRemove", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyBurnedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyBurned + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyBurnedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyBurned) + 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(BurnWithFromMintTokenPoolAndProxyBurned) + 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 *BurnWithFromMintTokenPoolAndProxyBurnedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyBurnedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyBurned struct { + Sender common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintTokenPoolAndProxyBurnedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "Burned", senderRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyBurnedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "Burned", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchBurned(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyBurned, sender []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyBurned) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseBurned(log types.Log) (*BurnWithFromMintTokenPoolAndProxyBurned, error) { + event := new(BurnWithFromMintTokenPoolAndProxyBurned) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "Burned", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyChainAddedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyChainAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyChainAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyChainAdded) + 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(BurnWithFromMintTokenPoolAndProxyChainAdded) + 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 *BurnWithFromMintTokenPoolAndProxyChainAddedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyChainAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyChainAdded struct { + RemoteChainSelector uint64 + RemoteToken []byte + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterChainAdded(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyChainAddedIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "ChainAdded") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyChainAddedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "ChainAdded", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchChainAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyChainAdded) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyChainAdded) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseChainAdded(log types.Log) (*BurnWithFromMintTokenPoolAndProxyChainAdded, error) { + event := new(BurnWithFromMintTokenPoolAndProxyChainAdded) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "ChainAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyChainConfigured + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyChainConfigured) + 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(BurnWithFromMintTokenPoolAndProxyChainConfigured) + 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 *BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyChainConfigured struct { + RemoteChainSelector uint64 + OutboundRateLimiterConfig RateLimiterConfig + InboundRateLimiterConfig RateLimiterConfig + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterChainConfigured(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "ChainConfigured") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "ChainConfigured", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyChainConfigured) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyChainConfigured) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseChainConfigured(log types.Log) (*BurnWithFromMintTokenPoolAndProxyChainConfigured, error) { + event := new(BurnWithFromMintTokenPoolAndProxyChainConfigured) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "ChainConfigured", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyChainRemovedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyChainRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyChainRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyChainRemoved) + 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(BurnWithFromMintTokenPoolAndProxyChainRemoved) + 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 *BurnWithFromMintTokenPoolAndProxyChainRemovedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyChainRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyChainRemoved struct { + RemoteChainSelector uint64 + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterChainRemoved(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyChainRemovedIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "ChainRemoved") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyChainRemovedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "ChainRemoved", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyChainRemoved) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyChainRemoved) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseChainRemoved(log types.Log) (*BurnWithFromMintTokenPoolAndProxyChainRemoved, error) { + event := new(BurnWithFromMintTokenPoolAndProxyChainRemoved) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "ChainRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyConfigChangedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyConfigChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyConfigChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyConfigChanged) + 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(BurnWithFromMintTokenPoolAndProxyConfigChanged) + 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 *BurnWithFromMintTokenPoolAndProxyConfigChangedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyConfigChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyConfigChanged struct { + Config RateLimiterConfig + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyConfigChangedIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "ConfigChanged") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyConfigChangedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyConfigChanged) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyConfigChanged) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseConfigChanged(log types.Log) (*BurnWithFromMintTokenPoolAndProxyConfigChanged, error) { + event := new(BurnWithFromMintTokenPoolAndProxyConfigChanged) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "ConfigChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) + 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(BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) + 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 *BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged struct { + OldPool common.Address + NewPool common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterLegacyPoolChanged(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "LegacyPoolChanged") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "LegacyPoolChanged", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchLegacyPoolChanged(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.WatchLogs(opts, "LegacyPoolChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "LegacyPoolChanged", 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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseLegacyPoolChanged(log types.Log) (*BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged, error) { + event := new(BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "LegacyPoolChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyLockedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyLocked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyLockedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyLocked) + 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(BurnWithFromMintTokenPoolAndProxyLocked) + 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 *BurnWithFromMintTokenPoolAndProxyLockedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyLockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyLocked struct { + Sender common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintTokenPoolAndProxyLockedIterator, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "Locked", senderRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyLockedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "Locked", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchLocked(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyLocked, sender []common.Address) (event.Subscription, error) { + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyLocked) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseLocked(log types.Log) (*BurnWithFromMintTokenPoolAndProxyLocked, error) { + event := new(BurnWithFromMintTokenPoolAndProxyLocked) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "Locked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyMintedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyMinted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyMintedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyMinted) + 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(BurnWithFromMintTokenPoolAndProxyMinted) + 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 *BurnWithFromMintTokenPoolAndProxyMintedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyMintedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyMinted struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintTokenPoolAndProxyMintedIterator, 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 := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "Minted", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyMintedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "Minted", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchMinted(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyMinted, 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 := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyMinted) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseMinted(log types.Log) (*BurnWithFromMintTokenPoolAndProxyMinted, error) { + event := new(BurnWithFromMintTokenPoolAndProxyMinted) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "Minted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested) + 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(BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested) + 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 *BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator, 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 := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested, 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 := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseOwnershipTransferRequested(log types.Log) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested, error) { + event := new(BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyOwnershipTransferred) + 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(BurnWithFromMintTokenPoolAndProxyOwnershipTransferred) + 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 *BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator, 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 := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyOwnershipTransferred, 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 := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyOwnershipTransferred) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseOwnershipTransferred(log types.Log) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferred, error) { + event := new(BurnWithFromMintTokenPoolAndProxyOwnershipTransferred) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyReleasedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyReleased + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyReleasedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyReleased) + 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(BurnWithFromMintTokenPoolAndProxyReleased) + 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 *BurnWithFromMintTokenPoolAndProxyReleasedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyReleasedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyReleased struct { + Sender common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintTokenPoolAndProxyReleasedIterator, 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 := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "Released", senderRule, recipientRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyReleasedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "Released", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyReleased, 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 := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyReleased) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseReleased(log types.Log) (*BurnWithFromMintTokenPoolAndProxyReleased, error) { + event := new(BurnWithFromMintTokenPoolAndProxyReleased) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "Released", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyRemotePoolSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyRemotePoolSet) + 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(BurnWithFromMintTokenPoolAndProxyRemotePoolSet) + 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 *BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyRemotePoolSet struct { + RemoteChainSelector uint64 + PreviousPoolAddress []byte + RemotePoolAddress []byte + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.WatchLogs(opts, "RemotePoolSet", 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(BurnWithFromMintTokenPoolAndProxyRemotePoolSet) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "RemotePoolSet", 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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseRemotePoolSet(log types.Log) (*BurnWithFromMintTokenPoolAndProxyRemotePoolSet, error) { + event := new(BurnWithFromMintTokenPoolAndProxyRemotePoolSet) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyRouterUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyRouterUpdated) + 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(BurnWithFromMintTokenPoolAndProxyRouterUpdated) + 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 *BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyRouterUpdated struct { + OldRouter common.Address + NewRouter common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "RouterUpdated") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "RouterUpdated", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyRouterUpdated) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.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(BurnWithFromMintTokenPoolAndProxyRouterUpdated) + if err := _BurnWithFromMintTokenPoolAndProxy.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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseRouterUpdated(log types.Log) (*BurnWithFromMintTokenPoolAndProxyRouterUpdated, error) { + event := new(BurnWithFromMintTokenPoolAndProxyRouterUpdated) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "RouterUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator struct { + Event *BurnWithFromMintTokenPoolAndProxyTokensConsumed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolAndProxyTokensConsumed) + 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(BurnWithFromMintTokenPoolAndProxyTokensConsumed) + 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 *BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolAndProxyTokensConsumed struct { + Tokens *big.Int + Raw types.Log +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) FilterTokensConsumed(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.FilterLogs(opts, "TokensConsumed") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator{contract: _BurnWithFromMintTokenPoolAndProxy.contract, event: "TokensConsumed", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyTokensConsumed) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPoolAndProxy.contract.WatchLogs(opts, "TokensConsumed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnWithFromMintTokenPoolAndProxyTokensConsumed) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "TokensConsumed", 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 (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxyFilterer) ParseTokensConsumed(log types.Log) (*BurnWithFromMintTokenPoolAndProxyTokensConsumed, error) { + event := new(BurnWithFromMintTokenPoolAndProxyTokensConsumed) + if err := _BurnWithFromMintTokenPoolAndProxy.contract.UnpackLog(event, "TokensConsumed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxy) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["AllowListAdd"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseAllowListAdd(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["AllowListRemove"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseAllowListRemove(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["Burned"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseBurned(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["ChainAdded"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseChainAdded(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["ChainConfigured"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseChainConfigured(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["ChainRemoved"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseChainRemoved(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["ConfigChanged"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseConfigChanged(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["LegacyPoolChanged"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseLegacyPoolChanged(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["Locked"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseLocked(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["Minted"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseMinted(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["OwnershipTransferRequested"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseOwnershipTransferRequested(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["OwnershipTransferred"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseOwnershipTransferred(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["Released"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseReleased(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["RemotePoolSet"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseRemotePoolSet(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["RouterUpdated"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseRouterUpdated(log) + case _BurnWithFromMintTokenPoolAndProxy.abi.Events["TokensConsumed"].ID: + return _BurnWithFromMintTokenPoolAndProxy.ParseTokensConsumed(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (BurnWithFromMintTokenPoolAndProxyAllowListAdd) Topic() common.Hash { + return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8") +} + +func (BurnWithFromMintTokenPoolAndProxyAllowListRemove) Topic() common.Hash { + return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566") +} + +func (BurnWithFromMintTokenPoolAndProxyBurned) Topic() common.Hash { + return common.HexToHash("0x696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7") +} + +func (BurnWithFromMintTokenPoolAndProxyChainAdded) Topic() common.Hash { + return common.HexToHash("0x8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2") +} + +func (BurnWithFromMintTokenPoolAndProxyChainConfigured) Topic() common.Hash { + return common.HexToHash("0x0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b") +} + +func (BurnWithFromMintTokenPoolAndProxyChainRemoved) Topic() common.Hash { + return common.HexToHash("0x5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916") +} + +func (BurnWithFromMintTokenPoolAndProxyConfigChanged) Topic() common.Hash { + return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") +} + +func (BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) Topic() common.Hash { + return common.HexToHash("0x81accd0a7023865eaa51b3399dd0eafc488bf3ba238402911e1659cfe860f228") +} + +func (BurnWithFromMintTokenPoolAndProxyLocked) Topic() common.Hash { + return common.HexToHash("0x9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008") +} + +func (BurnWithFromMintTokenPoolAndProxyMinted) Topic() common.Hash { + return common.HexToHash("0x9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0") +} + +func (BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (BurnWithFromMintTokenPoolAndProxyOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (BurnWithFromMintTokenPoolAndProxyReleased) Topic() common.Hash { + return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") +} + +func (BurnWithFromMintTokenPoolAndProxyRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +} + +func (BurnWithFromMintTokenPoolAndProxyRouterUpdated) Topic() common.Hash { + return common.HexToHash("0x02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684") +} + +func (BurnWithFromMintTokenPoolAndProxyTokensConsumed) Topic() common.Hash { + return common.HexToHash("0x1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a") +} + +func (_BurnWithFromMintTokenPoolAndProxy *BurnWithFromMintTokenPoolAndProxy) Address() common.Address { + return _BurnWithFromMintTokenPoolAndProxy.address +} + +type BurnWithFromMintTokenPoolAndProxyInterface 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) + + GetOnRamp(opts *bind.CallOpts, arg0 uint64) (common.Address, error) + + GetPreviousPool(opts *bind.CallOpts) (common.Address, error) + + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + + GetRemotePool(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) + + IsOffRamp(opts *bind.CallOpts, sourceChainSelector uint64, offRamp common.Address) (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) + + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) + + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + + LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) + + ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + + SetPreviousPool(opts *bind.TransactOpts, prevPool common.Address) (*types.Transaction, error) + + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*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) (*BurnWithFromMintTokenPoolAndProxyAllowListAddIterator, error) + + WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyAllowListAdd) (event.Subscription, error) + + ParseAllowListAdd(log types.Log) (*BurnWithFromMintTokenPoolAndProxyAllowListAdd, error) + + FilterAllowListRemove(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyAllowListRemoveIterator, error) + + WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyAllowListRemove) (event.Subscription, error) + + ParseAllowListRemove(log types.Log) (*BurnWithFromMintTokenPoolAndProxyAllowListRemove, error) + + FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintTokenPoolAndProxyBurnedIterator, error) + + WatchBurned(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyBurned, sender []common.Address) (event.Subscription, error) + + ParseBurned(log types.Log) (*BurnWithFromMintTokenPoolAndProxyBurned, error) + + FilterChainAdded(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyChainAddedIterator, error) + + WatchChainAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyChainAdded) (event.Subscription, error) + + ParseChainAdded(log types.Log) (*BurnWithFromMintTokenPoolAndProxyChainAdded, error) + + FilterChainConfigured(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyChainConfiguredIterator, error) + + WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyChainConfigured) (event.Subscription, error) + + ParseChainConfigured(log types.Log) (*BurnWithFromMintTokenPoolAndProxyChainConfigured, error) + + FilterChainRemoved(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyChainRemovedIterator, error) + + WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyChainRemoved) (event.Subscription, error) + + ParseChainRemoved(log types.Log) (*BurnWithFromMintTokenPoolAndProxyChainRemoved, error) + + FilterConfigChanged(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyConfigChangedIterator, error) + + WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyConfigChanged) (event.Subscription, error) + + ParseConfigChanged(log types.Log) (*BurnWithFromMintTokenPoolAndProxyConfigChanged, error) + + FilterLegacyPoolChanged(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyLegacyPoolChangedIterator, error) + + WatchLegacyPoolChanged(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged) (event.Subscription, error) + + ParseLegacyPoolChanged(log types.Log) (*BurnWithFromMintTokenPoolAndProxyLegacyPoolChanged, error) + + FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*BurnWithFromMintTokenPoolAndProxyLockedIterator, error) + + WatchLocked(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyLocked, sender []common.Address) (event.Subscription, error) + + ParseLocked(log types.Log) (*BurnWithFromMintTokenPoolAndProxyLocked, error) + + FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintTokenPoolAndProxyMintedIterator, error) + + WatchMinted(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseMinted(log types.Log) (*BurnWithFromMintTokenPoolAndProxyMinted, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*BurnWithFromMintTokenPoolAndProxyOwnershipTransferred, error) + + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintTokenPoolAndProxyReleasedIterator, error) + + WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseReleased(log types.Log) (*BurnWithFromMintTokenPoolAndProxyReleased, error) + + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolAndProxyRemotePoolSetIterator, error) + + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolSet(log types.Log) (*BurnWithFromMintTokenPoolAndProxyRemotePoolSet, error) + + FilterRouterUpdated(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyRouterUpdatedIterator, error) + + WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyRouterUpdated) (event.Subscription, error) + + ParseRouterUpdated(log types.Log) (*BurnWithFromMintTokenPoolAndProxyRouterUpdated, error) + + FilterTokensConsumed(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolAndProxyTokensConsumedIterator, error) + + WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolAndProxyTokensConsumed) (event.Subscription, error) + + ParseTokensConsumed(log types.Log) (*BurnWithFromMintTokenPoolAndProxyTokensConsumed, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index e35a8726dec..3c2d44cd302 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -47,7 +47,6 @@ type CCIPConfigTypesOCR3Config struct { F uint8 OffchainConfigVersion uint64 OfframpAddress []byte - BootstrapP2PIds [][32]byte P2pIds [][32]byte Signers [][]byte Transmitters [][]byte @@ -61,8 +60,8 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { } var CCIPConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigNotSetForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"set\",\"type\":\"bytes32[]\"}],\"name\":\"NotASortedSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"subset\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"superset\",\"type\":\"bytes32[]\"}],\"name\":\"NotASubset\",\"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\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyTransmitters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"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\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"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\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"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\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620043cc380380620043cc83398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160a01b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160a01b0381168114620001a957600080fd5b9392505050565b6080516141f9620001d360003960008181610e4e01526110e301526141f96000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80638da5cb5b11610076578063f2fde38b1161005b578063f2fde38b146101bc578063f442c89a146101cf578063fba64a7c146101e257600080fd5b80638da5cb5b1461017f578063ddc042a8146101a757600080fd5b80634bd0473f116100a75780634bd0473f1461013457806379ba5097146101545780638318ed5d1461015e57600080fd5b806301ffc9a7146100c3578063181f5a77146100eb575b600080fd5b6100d66100d1366004612f77565b6101f5565b60405190151581526020015b60405180910390f35b6101276040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100e2919061301d565b610147610142366004613061565b61028e565b6040516100e2919061318d565b61015c61075e565b005b61012761016c36600461336a565b5060408051602081019091526000815290565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e2565b6101af610860565b6040516100e291906133cb565b61015c6101ca36600461345b565b610a52565b61015c6101dd3660046134dd565b610a66565b61015c6101f0366004613561565b610e36565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea72100000000000000000000000000000000000000000000000000000000148061028857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff821660009081526005602052604081206060918360018111156102b8576102b8613096565b60018111156102c9576102c9613096565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561075257600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561033c5761033c613096565b600181111561034d5761034d613096565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103a59061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546103d19061361e565b801561041e5780601f106103f35761010080835404028352916020019161041e565b820191906000526020600020905b81548152906001019060200180831161040157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561047657602002820191906000526020600020905b815481526020019060010190808311610462575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156104ce57602002820191906000526020600020905b8154815260200190600101908083116104ba575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156105a857838290600052602060002001805461051b9061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546105479061361e565b80156105945780601f1061056957610100808354040283529160200191610594565b820191906000526020600020905b81548152906001019060200180831161057757829003601f168201915b5050505050815260200190600101906104fc565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156106815783829060005260206000200180546105f49061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546106209061361e565b801561066d5780601f106106425761010080835404028352916020019161066d565b820191906000526020600020905b81548152906001019060200180831161065057829003601f168201915b5050505050815260200190600101906105d5565b5050505081526020016006820180546106999061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546106c59061361e565b80156107125780601f106106e757610100808354040283529160200191610712565b820191906000526020600020905b8154815290600101906020018083116106f557829003601f168201915b505050919092525050508152600782015467ffffffffffffffff1660208083019190915260089092015460409091015290825260019290920191016102f7565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6060600061086e6003610ef7565b9050600061087c6003610f0b565b67ffffffffffffffff81111561089457610894613671565b6040519080825280602002602001820160405280156108cd57816020015b6108ba612d08565b8152602001906001900390816108b25790505b50905060005b8251811015610a4b5760008382815181106108f0576108f06136a0565b60209081029190910181015160408051808201825267ffffffffffffffff83168082526000908152600285528290208251815460808188028301810190955260608201818152959750929586019490939192849284919084018282801561097657602002820191906000526020600020905b815481526020019060010190808311610962575b5050509183525050600182015460ff1660208201526002820180546040909201916109a09061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546109cc9061361e565b8015610a195780601f106109ee57610100808354040283529160200191610a19565b820191906000526020600020905b8154815290600101906020018083116109fc57829003601f168201915b505050505081525050815250838381518110610a3757610a376136a0565b6020908102919091010152506001016108d3565b5092915050565b610a5a610f15565b610a6381610f98565b50565b610a6e610f15565b60005b83811015610c5457610ab5858583818110610a8e57610a8e6136a0565b9050602002016020810190610aa391906136cf565b60039067ffffffffffffffff1661108d565b610b1f57848482818110610acb57610acb6136a0565b9050602002016020810190610ae091906136cf565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107db565b60026000868684818110610b3557610b356136a0565b9050602002016020810190610b4a91906136cf565b67ffffffffffffffff1681526020810191909152604001600090812090610b718282612d50565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ba9600283016000612d6e565b5050610be7858583818110610bc057610bc06136a0565b9050602002016020810190610bd591906136cf565b60039067ffffffffffffffff166110a5565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610c1b57610c1b6136a0565b9050602002016020810190610c3091906136cf565b60405167ffffffffffffffff909116815260200160405180910390a1600101610a71565b5060005b81811015610e2f576000838383818110610c7457610c746136a0565b9050602002810190610c8691906136ea565b610c94906020810190613728565b610c9d9061392a565b80519091506000858585818110610cb657610cb66136a0565b9050602002810190610cc891906136ea565b610cd69060208101906136cf565b905060005b8251811015610d0e57610d06838281518110610cf957610cf96136a0565b60200260200101516110b1565b600101610cdb565b50826020015160ff16600003610d50576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120845180518693610d80928492910190612da8565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610dcd9082613a11565b50610de791506003905067ffffffffffffffff83166111ca565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08184604051610e19929190613b2b565b60405180910390a1505050806001019050610c58565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610ea5576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610eb384860186613bd6565b9050600080610ec1836111d6565b8151919350915015610ed957610ed98460008461142f565b805115610eec57610eec8460018361142f565b505050505050505050565b60606000610f0483611c10565b9392505050565b6000610288825490565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107db565b565b3373ffffffffffffffffffffffffffffffffffffffff821603611017576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107db565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f04565b6000610f048383611c6c565b6040517f50c946fe000000000000000000000000000000000000000000000000000000008152600481018290526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906350c946fe90602401600060405180830381865afa15801561113f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111859190810190613e47565b60808101519091506111c6576040517f8907a4fa000000000000000000000000000000000000000000000000000000008152600481018390526024016107db565b5050565b6000610f048383611d5f565b606080600460ff1683511115611218576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61129c6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161122e57505060408051600280825260608201909252919350602082015b6113346040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112c657905050905060008060005b855181101561142257600086828151811061136c5761136c6136a0565b602002602001015160000151600181111561138957611389613096565b036113d6578581815181106113a0576113a06136a0565b60200260200101518584815181106113ba576113ba6136a0565b6020026020010181905250826113cf90613f4e565b925061141a565b8581815181106113e8576113e86136a0565b6020026020010151848381518110611402576114026136a0565b60200260200101819052508161141790613f4e565b91505b60010161134f565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561145757611457613096565b600181111561146857611468613096565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156118f157600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156114db576114db613096565b60018111156114ec576114ec613096565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115449061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546115709061361e565b80156115bd5780601f10611592576101008083540402835291602001916115bd565b820191906000526020600020905b8154815290600101906020018083116115a057829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561161557602002820191906000526020600020905b815481526020019060010190808311611601575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561166d57602002820191906000526020600020905b815481526020019060010190808311611659575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156117475783829060005260206000200180546116ba9061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546116e69061361e565b80156117335780601f1061170857610100808354040283529160200191611733565b820191906000526020600020905b81548152906001019060200180831161171657829003601f168201915b50505050508152602001906001019061169b565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156118205783829060005260206000200180546117939061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546117bf9061361e565b801561180c5780601f106117e15761010080835404028352916020019161180c565b820191906000526020600020905b8154815290600101906020018083116117ef57829003601f168201915b505050505081526020019060010190611774565b5050505081526020016006820180546118389061361e565b80601f01602080910402602001604051908101604052809291908181526020018280546118649061361e565b80156118b15780601f10611886576101008083540402835291602001916118b1565b820191906000526020600020905b81548152906001019060200180831161189457829003601f168201915b505050919092525050508152600782015467ffffffffffffffff166020808301919091526008909201546040909101529082526001929092019101611496565b50505050905060006119038251611dae565b905060006119118451611dae565b905061191d8282611e00565b600061192c8785878686611ebc565b905061193884826122a8565b63ffffffff871660009081526005602052604081209087600181111561196057611960613096565b600181111561197157611971613096565b8152602001908152602001600020600061198b9190612df3565b60005b8151811015611c065763ffffffff88166000908152600560205260408120908860018111156119bf576119bf613096565b60018111156119d0576119d0613096565b81526020019081526020016000208282815181106119f0576119f06136a0565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611a5a57611a5a613096565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b299082613a11565b5060a08201518051611b45916002840191602090910190612da8565b5060c08201518051611b61916003840191602090910190612da8565b5060e08201518051611b7d916004840191602090910190612e14565b506101008201518051611b9a916005840191602090910190612e14565b506101208201516006820190611bb09082613a11565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117905560409091015160089091015560010161198e565b5050505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c6057602002820191906000526020600020905b815481526020019060010190808311611c4c575b50505050509050919050565b60008181526001830160205260408120548015611d55576000611c90600183613f86565b8554909150600090611ca490600190613f86565b9050818114611d09576000866000018281548110611cc457611cc46136a0565b9060005260206000200154905080876000018481548110611ce757611ce76136a0565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d1a57611d1a613f99565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610288565b6000915050610288565b6000818152600183016020526040812054611da657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610288565b506000610288565b60006002821115611dee576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107db565b81600281111561028857610288613096565b6000826002811115611e1457611e14613096565b826002811115611e2657611e26613096565b611e309190613fc8565b90508060011480611e7c5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611e7c57506002836002811115611e7a57611e7a613096565b145b15611e8657505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107db929190613ff8565b60606000845167ffffffffffffffff811115611eda57611eda613671565b604051908082528060200260200182016040528015611f03578160200160208202803683370190505b5090506000846002811115611f1a57611f1a613096565b148015611f3857506001836002811115611f3657611f36613096565b145b15611f7957600181600081518110611f5257611f526136a0565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506120e1565b6001846002811115611f8d57611f8d613096565b148015611fab57506002836002811115611fa957611fa9613096565b145b156120425785600081518110611fc357611fc36136a0565b60200260200101516020015181600081518110611fe257611fe26136a0565b602002602001019067ffffffffffffffff16908167ffffffffffffffff168152505085600081518110612017576120176136a0565b602002602001015160200151600161202f9190614013565b81600181518110611f5257611f526136a0565b600284600281111561205657612056613096565b1480156120745750600183600281111561207257612072613096565b145b156120ab578560018151811061208c5761208c6136a0565b60200260200101516020015181600081518110611f5257611f526136a0565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107db929190613ff8565b6000855167ffffffffffffffff8111156120fd576120fd613671565b6040519080825280602002602001820160405280156121b357816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161211b5790505b50905060005b825181101561229c576121e48782815181106121d7576121d76136a0565b6020026020010151612627565b6040518060600160405280888381518110612201576122016136a0565b60200260200101518152602001848381518110612220576122206136a0565b602002602001015167ffffffffffffffff1681526020016122748b86858151811061224d5761224d6136a0565b60200260200101518b8681518110612267576122676136a0565b6020026020010151612a2d565b815250828281518110612289576122896136a0565b60209081029190910101526001016121b9565b50979650505050505050565b81518151811580156122ba5750806001145b1561235c57826000815181106122d2576122d26136a0565b60200260200101516020015167ffffffffffffffff166001146123565782600081518110612302576123026136a0565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107db565b50505050565b81600114801561236c5750806002145b156125225783600081518110612384576123846136a0565b602002602001015160400151836000815181106123a3576123a36136a0565b6020026020010151604001511461242f57826000815181106123c7576123c76136a0565b602002602001015160400151846000815181106123e6576123e66136a0565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107db929190918252602082015260400190565b83600081518110612442576124426136a0565b602002602001015160200151600161245a9190614013565b67ffffffffffffffff1683600181518110612477576124776136a0565b60200260200101516020015167ffffffffffffffff161461235657826001815181106124a5576124a56136a0565b602002602001015160200151846000815181106124c4576124c46136a0565b60200260200101516020015160016124dc9190614013565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107db565b8160021480156125325750806001145b156125f5578360018151811061254a5761254a6136a0565b60200260200101516040015183600081518110612569576125696136a0565b60200260200101516040015114612356578260008151811061258d5761258d6136a0565b602002602001015160400151846001815181106125ac576125ac6136a0565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107db929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff1660000361266f576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561268457612684613096565b141580156126a557506001815160018111156126a2576126a2613096565b14155b156126dc576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80608001515160000361271b576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127369060039067ffffffffffffffff1661108d565b61277e5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107db565b60e081015151601f10156127be576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010081015151601f10156127ff576040517f645960ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015167ffffffffffffffff1660009081526002909152604081206001015461282f9060ff166003614034565b61283a906001614050565b60ff1690508082610100015151101561289157610100820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107db565b816040015160ff166000036128d2576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516128e2906003614034565b60ff168260e001515111612922576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160e00151518260c00151511415806129465750816101000151518260c001515114155b156129a15760c08201515160e083015151610100840151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107db565b8160c00151518260a001515111156129e5576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129f78260a001518360c00151612b02565b60005b8260e0015151811015612a2857612a208360c001518281518110610cf957610cf96136a0565b6001016129fa565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d6101200151604051602001612a819c9b9a999897969594939291906140d4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b81511580612b0f57508051155b15612b46576040517fe249684100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b4f82612c7d565b612b5881612c7d565b6000805b835182108015612b6c5750825181105b15612c3e57828181518110612b8357612b836136a0565b6020026020010151848381518110612b9d57612b9d6136a0565b60200260200101511115612bbb57612bb481613f4e565b9050612b5c565b828181518110612bcd57612bcd6136a0565b6020026020010151848381518110612be757612be76136a0565b602002602001015103612c0857612bfd82613f4e565b9150612bb481613f4e565b83836040517fd671700c0000000000000000000000000000000000000000000000000000000081526004016107db9291906141b4565b83518210156123565783836040517fd671700c0000000000000000000000000000000000000000000000000000000081526004016107db9291906141b4565b60015b81518110156111c65781612c95600183613f86565b81518110612ca557612ca56136a0565b6020026020010151828281518110612cbf57612cbf6136a0565b602002602001015111612d0057816040517f1bc41b420000000000000000000000000000000000000000000000000000000081526004016107db91906141d9565b600101612c80565b6040518060400160405280600067ffffffffffffffff168152602001612d4b604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610a639190612e66565b508054612d7a9061361e565b6000825580601f10612d8a575050565b601f016020900490600052602060002090810190610a639190612e66565b828054828255906000526020600020908101928215612de3579160200282015b82811115612de3578251825591602001919060010190612dc8565b50612def929150612e66565b5090565b5080546000825560090290600052602060002090810190610a639190612e7b565b828054828255906000526020600020908101928215612e5a579160200282015b82811115612e5a5782518290612e4a9082613a11565b5091602001919060010190612e34565b50612def929150612f3c565b5b80821115612def5760008155600101612e67565b80821115612def5780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612eba6001830182612d6e565b612ec8600283016000612d50565b612ed6600383016000612d50565b612ee4600483016000612f59565b612ef2600583016000612f59565b612f00600683016000612d6e565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612e7b565b80821115612def576000612f508282612d6e565b50600101612f3c565b5080546000825590600052602060002090810190610a639190612f3c565b600060208284031215612f8957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f0457600080fd5b6000815180845260005b81811015612fdf57602081850181015186830182015201612fc3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f046020830184612fb9565b63ffffffff81168114610a6357600080fd5b803561304d81613030565b919050565b80356002811061304d57600080fd5b6000806040838503121561307457600080fd5b823561307f81613030565b915061308d60208401613052565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600281106130d5576130d5613096565b9052565b60008151808452602080850194506020840160005b8381101561310a578151875295820195908201906001016130ee565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015613180577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261316e838351612fb9565b98840198925090830190600101613134565b5090979650505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561335c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151606081518186526131fb82870182516130c5565b8981015160806132168189018367ffffffffffffffff169052565b8a830151915060a061322c818a018460ff169052565b938301519360c0925061324a8984018667ffffffffffffffff169052565b818401519450610140915060e082818b015261326a6101a08b0187612fb9565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d01526132a988856130d9565b97508587015195506101209350818c890301848d01526132c988876130d9565b9750828701519550818c890301858d01526132e48887613115565b975080870151955050808b8803016101608c01526133028786613115565b9650828601519550808b8803016101808c015250505050506133248282612fb9565b915050888201516133408a87018267ffffffffffffffff169052565b50908701519387019390935293860193908601906001016131b6565b509098975050505050505050565b60006020828403121561337c57600080fd5b8135610f0481613030565b600081516060845261339c60608501826130d9565b905060ff6020840151166020850152604083015184820360408601526133c28282612fb9565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561335c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261344887850182613387565b95880195935050908601906001016133f4565b60006020828403121561346d57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f0457600080fd5b60008083601f8401126134a357600080fd5b50813567ffffffffffffffff8111156134bb57600080fd5b6020830191508360208260051b85010111156134d657600080fd5b9250929050565b600080600080604085870312156134f357600080fd5b843567ffffffffffffffff8082111561350b57600080fd5b61351788838901613491565b9096509450602087013591508082111561353057600080fd5b5061353d87828801613491565b95989497509550505050565b803567ffffffffffffffff8116811461304d57600080fd5b6000806000806000806080878903121561357a57600080fd5b863567ffffffffffffffff8082111561359257600080fd5b61359e8a838b01613491565b909850965060208901359150808211156135b757600080fd5b818901915089601f8301126135cb57600080fd5b8135818111156135da57600080fd5b8a60208285010111156135ec57600080fd5b60208301965080955050505061360460408801613549565b915061361260608801613042565b90509295509295509295565b600181811c9082168061363257607f821691505b60208210810361366b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156136e157600080fd5b610f0482613549565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261371e57600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261371e57600080fd5b604051610140810167ffffffffffffffff8111828210171561378057613780613671565b60405290565b60405160e0810167ffffffffffffffff8111828210171561378057613780613671565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156137f0576137f0613671565b604052919050565b600067ffffffffffffffff82111561381257613812613671565b5060051b60200190565b600082601f83011261382d57600080fd5b8135602061384261383d836137f8565b6137a9565b8083825260208201915060208460051b87010193508684111561386457600080fd5b602086015b848110156138805780358352918301918301613869565b509695505050505050565b803560ff8116811461304d57600080fd5b600082601f8301126138ad57600080fd5b813567ffffffffffffffff8111156138c7576138c7613671565b6138f860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016137a9565b81815284602083860101111561390d57600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561393c57600080fd5b6040516060810167ffffffffffffffff828210818311171561396057613960613671565b81604052843591508082111561397557600080fd5b6139813683870161381c565b835261398f6020860161388b565b602084015260408501359150808211156139a857600080fd5b506139b53682860161389c565b60408301525092915050565b601f821115612a28576000816000526020600020601f850160051c810160208610156139ea5750805b601f850160051c820191505b81811015613a09578281556001016139f6565b505050505050565b815167ffffffffffffffff811115613a2b57613a2b613671565b613a3f81613a39845461361e565b846139c1565b602080601f831160018114613a925760008415613a5c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613a09565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613adf57888601518255948401946001909101908401613ac0565b5085821015613b1b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613b4e6040830184613387565b949350505050565b600082601f830112613b6757600080fd5b81356020613b7761383d836137f8565b82815260059290921b84018101918181019086841115613b9657600080fd5b8286015b8481101561388057803567ffffffffffffffff811115613bba5760008081fd5b613bc88986838b010161389c565b845250918301918301613b9a565b60006020808385031215613be957600080fd5b823567ffffffffffffffff80821115613c0157600080fd5b818501915085601f830112613c1557600080fd5b8135613c2361383d826137f8565b81815260059190911b83018401908481019088831115613c4257600080fd5b8585015b83811015613dd057803585811115613c5d57600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613c9257600080fd5b613c9a61375c565b613ca5898301613052565b8152613cb360408301613549565b89820152613cc36060830161388b565b6040820152613cd460808301613549565b606082015260a082013587811115613ceb57600080fd5b613cf98d8b8386010161389c565b60808301525060c082013587811115613d1157600080fd5b613d1f8d8b8386010161381c565b60a08301525060e082013587811115613d3757600080fd5b613d458d8b8386010161381c565b60c0830152506101008083013588811115613d5f57600080fd5b613d6d8e8c83870101613b56565b60e0840152506101208084013589811115613d8757600080fd5b613d958f8d83880101613b56565b8385015250610140840135915088821115613daf57600080fd5b613dbd8e8c8487010161389c565b9083015250845250918601918601613c46565b5098975050505050505050565b805161304d81613030565b600082601f830112613df957600080fd5b81516020613e0961383d836137f8565b8083825260208201915060208460051b870101935086841115613e2b57600080fd5b602086015b848110156138805780518352918301918301613e30565b600060208284031215613e5957600080fd5b815167ffffffffffffffff80821115613e7157600080fd5b9083019060e08286031215613e8557600080fd5b613e8d613786565b613e9683613ddd565b8152613ea460208401613ddd565b6020820152613eb560408401613ddd565b6040820152606083015160608201526080830151608082015260a083015182811115613ee057600080fd5b613eec87828601613de8565b60a08301525060c083015182811115613f0457600080fd5b613f1087828601613de8565b60c08301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f7f57613f7f613f1f565b5060010190565b8181038181111561028857610288613f1f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715610a4b57610a4b613f1f565b600381106130d5576130d5613096565b604081016140068285613fe8565b610f046020830184613fe8565b67ffffffffffffffff818116838216019080821115610a4b57610a4b613f1f565b60ff8181168382160290811690818114610a4b57610a4b613f1f565b60ff818116838216019081111561028857610288613f1f565b60008282518085526020808601955060208260051b8401016020860160005b84811015613180577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189526140c2838351612fb9565b98840198925090830190600101614088565b67ffffffffffffffff8d16815263ffffffff8c1660208201526140fa604082018c6130c5565b6101806060820152600061411261018083018c612fb9565b67ffffffffffffffff8b16608084015282810360a0840152614134818b6130d9565b905082810360c0840152614148818a6130d9565b905082810360e084015261415c8189614069565b90508281036101008401526141718188614069565b60ff8716610120850152905067ffffffffffffffff85166101408401528281036101608401526141a18185612fb9565b9f9e505050505050505050505050505050565b6040815260006141c760408301856130d9565b82810360208401526133c281856130d9565b602081526000610f0460208301846130d956fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"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\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"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\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"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\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"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\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162004080380380620040808339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613e7f620002016000396000818160f801528181610ea701526111170152613e7f6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004612cbd565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed9190612d63565b610199610194366004612da7565b6102e1565b6040516100ed9190612ec6565b6101ae610759565b005b6101796101be366004613082565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd36600461309f565b61085b565b6040516100ed9190613105565b6101ae61021d366004613195565b610adc565b6101ae610230366004613217565b610af0565b6101ae61024336600461329b565b610e8f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b612ddc565b600181111561031c5761031c612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561074d57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561038f5761038f612ddc565b60018111156103a0576103a0612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461042490613358565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105a357838290600052602060002001805461051690613358565b80601f016020809104026020016040519081016040528092919081815260200182805461054290613358565b801561058f5780601f106105645761010080835404028352916020019161058f565b820191906000526020600020905b81548152906001019060200180831161057257829003601f168201915b5050505050815260200190600101906104f7565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561067c5783829060005260206000200180546105ef90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461061b90613358565b80156106685780601f1061063d57610100808354040283529160200191610668565b820191906000526020600020905b81548152906001019060200180831161064b57829003601f168201915b5050505050815260200190600101906105d0565b50505050815260200160058201805461069490613358565b80601f01602080910402602001604051908101604052809291908181526020018280546106c090613358565b801561070d5780601f106106e25761010080835404028352916020019161070d565b820191906000526020600020905b8154815290600101906020018083116106f057829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108696003610f4a565b9050600061087784866133da565b90508315806108865750818110155b156108c65760408051600080825260208201909252906108bc565b6108a9612a5c565b8152602001906001900390816108a15790505b50925050506102db565b60006108d28583613420565b9050828111156108df5750815b60006108eb8383613433565b67ffffffffffffffff811115610903576109036133f1565b60405190808252806020026020018201604052801561093c57816020015b610929612a5c565b8152602001906001900390816109215790505b509050600061094b6003610f54565b9050835b83811015610acf57600082828151811061096b5761096b613446565b60209081029190910181015160408051808201825267ffffffffffffffff8316808252600090815260028552829020825181546080818802830181019095526060820181815295975092958601949093919284928491908401828280156109f157602002820191906000526020600020905b8154815260200190600101908083116109dd575b5050509183525050600182015460ff166020820152600282018054604090920191610a1b90613358565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4790613358565b8015610a945780601f10610a6957610100808354040283529160200191610a94565b820191906000526020600020905b815481529060010190602001808311610a7757829003601f168201915b50505091909252505050905284610aab8885613433565b81518110610abb57610abb613446565b60209081029190910101525060010161094f565b5090979650505050505050565b610ae4610f68565b610aed81610feb565b50565b610af8610f68565b60005b83811015610cde57610b3f858583818110610b1857610b18613446565b9050602002016020810190610b2d9190613475565b60039067ffffffffffffffff166110e0565b610ba957848482818110610b5557610b55613446565b9050602002016020810190610b6a9190613475565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60026000868684818110610bbf57610bbf613446565b9050602002016020810190610bd49190613475565b67ffffffffffffffff1681526020810191909152604001600090812090610bfb8282612aa4565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c33600283016000612ac2565b5050610c71858583818110610c4a57610c4a613446565b9050602002016020810190610c5f9190613475565b60039067ffffffffffffffff166110f8565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610ca557610ca5613446565b9050602002016020810190610cba9190613475565b60405167ffffffffffffffff909116815260200160405180910390a1600101610afb565b5060005b81811015610e88576000838383818110610cfe57610cfe613446565b9050602002810190610d109190613490565b610d1e9060208101906134ce565b610d27906136d0565b90506000848484818110610d3d57610d3d613446565b9050602002810190610d4f9190613490565b610d5d906020810190613475565b9050610d6c8260000151611104565b816020015160ff16600003610dad576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610ddd928492910190612afc565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e2a90826137b7565b50610e4491506003905067ffffffffffffffff8316611250565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610e769291906138d1565b60405180910390a15050600101610ce2565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610efe576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f15610f108688018861397c565b61125c565b8151919350915015610f2d57610f2d836000846114a7565b805115610f4057610f40836001836114a7565b5050505050505050565b60006102db825490565b60606000610f6183611c09565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d6565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361106a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f61565b6000610f618383611c65565b60005b815181101561124c5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe84848151811061116357611163613446565b60200260200101516040518263ffffffff1660e01b815260040161118991815260200190565b600060405180830381865afa1580156111a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111ec9190810190613bc7565b60800151036112445781818151811061120757611207613446565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107d691815260200190565b600101611107565b5050565b6000610f618383611d5f565b606080600460ff168351111561129e576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61131b6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112b457505060408051600280825260608201909252919350602082015b6113ac6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161134557905050905060008060005b855181101561149a5760008682815181106113e4576113e4613446565b602002602001015160000151600181111561140157611401612ddc565b0361144e5785818151811061141857611418613446565b602002602001015185848151811061143257611432613446565b60200260200101819052508261144790613c9f565b9250611492565b85818151811061146057611460613446565b602002602001015184838151811061147a5761147a613446565b60200260200101819052508161148f90613c9f565b91505b6001016113c7565b5090835281529092909150565b63ffffffff83166000908152600560205260408120818460018111156114cf576114cf612ddc565b60018111156114e0576114e0612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561191157600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561155357611553612ddc565b600181111561156457611564612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115bc90613358565b80601f01602080910402602001604051908101604052809291908181526020018280546115e890613358565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561168d57602002820191906000526020600020905b815481526020019060010190808311611679575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156117675783829060005260206000200180546116da90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461170690613358565b80156117535780601f1061172857610100808354040283529160200191611753565b820191906000526020600020905b81548152906001019060200180831161173657829003601f168201915b5050505050815260200190600101906116bb565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118405783829060005260206000200180546117b390613358565b80601f01602080910402602001604051908101604052809291908181526020018280546117df90613358565b801561182c5780601f106118015761010080835404028352916020019161182c565b820191906000526020600020905b81548152906001019060200180831161180f57829003601f168201915b505050505081526020019060010190611794565b50505050815260200160058201805461185890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461188490613358565b80156118d15780601f106118a6576101008083540402835291602001916118d1565b820191906000526020600020905b8154815290600101906020018083116118b457829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161150e565b50505050905060006119238251611dae565b905060006119318451611dae565b905061193d8282611e00565b600061194c8785878686611ebc565b905061195884826122a0565b63ffffffff871660009081526005602052604081209087600181111561198057611980612ddc565b600181111561199157611991612ddc565b815260200190815260200160002060006119ab9190612b47565b60005b8151811015610f405763ffffffff88166000908152600560205260408120908860018111156119df576119df612ddc565b60018111156119f0576119f0612ddc565b8152602001908152602001600020828281518110611a1057611a10613446565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611a7a57611a7a612ddc565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b4990826137b7565b5060a08201518051611b65916002840191602090910190612afc565b5060c08201518051611b81916003840191602090910190612b68565b5060e08201518051611b9d916004840191602090910190612b68565b506101008201516005820190611bb390826137b7565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119ae565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c5957602002820191906000526020600020905b815481526020019060010190808311611c45575b50505050509050919050565b60008181526001830160205260408120548015611d4e576000611c89600183613433565b8554909150600090611c9d90600190613433565b9050808214611d02576000866000018281548110611cbd57611cbd613446565b9060005260206000200154905080876000018481548110611ce057611ce0613446565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d1357611d13613cd7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611da6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611dee576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107d6565b8160028111156102db576102db612ddc565b6000826002811115611e1457611e14612ddc565b826002811115611e2657611e26612ddc565b611e309190613d06565b90508060011480611e7c5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611e7c57506002836002811115611e7a57611e7a612ddc565b145b15611e8657505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b60606000845167ffffffffffffffff811115611eda57611eda6133f1565b604051908082528060200260200182016040528015611f03578160200160208202803683370190505b5090506000846002811115611f1a57611f1a612ddc565b148015611f3857506001836002811115611f3657611f36612ddc565b145b15611f7957600181600081518110611f5257611f52613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506120e1565b6001846002811115611f8d57611f8d612ddc565b148015611fab57506002836002811115611fa957611fa9612ddc565b145b156120425785600081518110611fc357611fc3613446565b60200260200101516020015181600081518110611fe257611fe2613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061201757612017613446565b602002602001015160200151600161202f9190613d51565b81600181518110611f5257611f52613446565b600284600281111561205657612056612ddc565b1480156120745750600183600281111561207257612072612ddc565b145b156120ab578560018151811061208c5761208c613446565b60200260200101516020015181600081518110611f5257611f52613446565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b6000855167ffffffffffffffff8111156120fd576120fd6133f1565b6040519080825280602002602001820160405280156121ab57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161211b5790505b50905060005b8251811015612294576121dc8782815181106121cf576121cf613446565b602002602001015161261f565b60405180606001604052808883815181106121f9576121f9613446565b6020026020010151815260200184838151811061221857612218613446565b602002602001015167ffffffffffffffff16815260200161226c8b86858151811061224557612245613446565b60200260200101518b868151811061225f5761225f613446565b602002602001015161298e565b81525082828151811061228157612281613446565b60209081029190910101526001016121b1565b50979650505050505050565b81518151811580156122b25750806001145b1561235457826000815181106122ca576122ca613446565b60200260200101516020015167ffffffffffffffff1660011461234e57826000815181106122fa576122fa613446565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107d6565b50505050565b8160011480156123645750806002145b1561251a578360008151811061237c5761237c613446565b6020026020010151604001518360008151811061239b5761239b613446565b6020026020010151604001511461242757826000815181106123bf576123bf613446565b602002602001015160400151846000815181106123de576123de613446565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b8360008151811061243a5761243a613446565b60200260200101516020015160016124529190613d51565b67ffffffffffffffff168360018151811061246f5761246f613446565b60200260200101516020015167ffffffffffffffff161461234e578260018151811061249d5761249d613446565b602002602001015160200151846000815181106124bc576124bc613446565b60200260200101516020015160016124d49190613d51565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107d6565b81600214801561252a5750806001145b156125ed578360018151811061254257612542613446565b6020026020010151604001518360008151811061256157612561613446565b6020026020010151604001511461234e578260008151811061258557612585613446565b602002602001015160400151846001815181106125a4576125a4613446565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612667576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561267c5761267c612ddc565b1415801561269d575060018151600181111561269a5761269a612ddc565b14155b156126d4576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612711575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b15612748576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127639060039067ffffffffffffffff166110e0565b6127ab5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60208082015167ffffffffffffffff166000908152600290915260408120600101546127db9060ff166003613d72565b6127e6906001613d8e565b60ff169050808260e0015151101561283b5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107d6565b60c08201515161010081111561287d576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151518114158061289657508260e00151518114155b156128f05760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107d6565b826040015160ff16600003612931576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612941906003613d72565b60ff16811161297c576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129898360a00151611104565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c61010001516040516020016129db9b9a99989796959493929190613da7565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612a9f604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610aed9190612bba565b508054612ace90613358565b6000825580601f10612ade575050565b601f016020900490600052602060002090810190610aed9190612bba565b828054828255906000526020600020908101928215612b37579160200282015b82811115612b37578251825591602001919060010190612b1c565b50612b43929150612bba565b5090565b5080546000825560080290600052602060002090810190610aed9190612bcf565b828054828255906000526020600020908101928215612bae579160200282015b82811115612bae5782518290612b9e90826137b7565b5091602001919060010190612b88565b50612b43929150612c82565b5b80821115612b435760008155600101612bbb565b80821115612b435780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c0e6001830182612ac2565b612c1c600283016000612aa4565b612c2a600383016000612c9f565b612c38600483016000612c9f565b612c46600583016000612ac2565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612bcf565b80821115612b43576000612c968282612ac2565b50600101612c82565b5080546000825590600052602060002090810190610aed9190612c82565b600060208284031215612ccf57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f6157600080fd5b6000815180845260005b81811015612d2557602081850181015186830182015201612d09565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f616020830184612cff565b63ffffffff81168114610aed57600080fd5b8035612d9381612d76565b919050565b803560028110612d9357600080fd5b60008060408385031215612dba57600080fd5b8235612dc581612d76565b9150612dd360208401612d98565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e1b57612e1b612ddc565b9052565b60008151808452602080850194506020840160005b83811015612e5057815187529582019590820190600101612e34565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610acf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612eb4838351612cff565b98840198925090830190600101612e7a565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612f348287018251612e0b565b898101516080612f4f8189018367ffffffffffffffff169052565b8a830151915060a0612f65818a018460ff169052565b938301519360c09250612f838984018667ffffffffffffffff169052565b818401519450610120915060e082818b0152612fa36101808b0187612cff565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d0152612fe28885612e1f565b958701518c87038301868e0152959750612ffc8887612e5b565b9750828701519550818c8903016101408d01526130198887612e5b565b975080870151965050808b8803016101608c0152505050505061303c8282612cff565b915050888201516130588a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612eef565b509098975050505050505050565b60006020828403121561309457600080fd5b8135610f6181612d76565b600080604083850312156130b257600080fd5b50508035926020909101359150565b60008151606084526130d66060850182612e1f565b905060ff6020840151166020850152604083015184820360408601526130fc8282612cff565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff168452870151878401879052613182878501826130c1565b958801959350509086019060010161312e565b6000602082840312156131a757600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f6157600080fd5b60008083601f8401126131dd57600080fd5b50813567ffffffffffffffff8111156131f557600080fd5b6020830191508360208260051b850101111561321057600080fd5b9250929050565b6000806000806040858703121561322d57600080fd5b843567ffffffffffffffff8082111561324557600080fd5b613251888389016131cb565b9096509450602087013591508082111561326a57600080fd5b50613277878288016131cb565b95989497509550505050565b803567ffffffffffffffff81168114612d9357600080fd5b600080600080600080608087890312156132b457600080fd5b863567ffffffffffffffff808211156132cc57600080fd5b6132d88a838b016131cb565b909850965060208901359150808211156132f157600080fd5b818901915089601f83011261330557600080fd5b81358181111561331457600080fd5b8a602082850101111561332657600080fd5b60208301965080955050505061333e60408801613283565b915061334c60608801612d88565b90509295509295509295565b600181811c9082168061336c57607f821691505b6020821081036133a5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db6133ab565b818103818111156102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561348757600080fd5b610f6182613283565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126134c457600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126134c457600080fd5b604051610120810167ffffffffffffffff81118282101715613526576135266133f1565b60405290565b60405160e0810167ffffffffffffffff81118282101715613526576135266133f1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613596576135966133f1565b604052919050565b600067ffffffffffffffff8211156135b8576135b86133f1565b5060051b60200190565b600082601f8301126135d357600080fd5b813560206135e86135e38361359e565b61354f565b8083825260208201915060208460051b87010193508684111561360a57600080fd5b602086015b84811015613626578035835291830191830161360f565b509695505050505050565b803560ff81168114612d9357600080fd5b600082601f83011261365357600080fd5b813567ffffffffffffffff81111561366d5761366d6133f1565b61369e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161354f565b8181528460208386010111156136b357600080fd5b816020850160208301376000918101602001919091529392505050565b6000606082360312156136e257600080fd5b6040516060810167ffffffffffffffff8282108183111715613706576137066133f1565b81604052843591508082111561371b57600080fd5b613727368387016135c2565b835261373560208601613631565b6020840152604085013591508082111561374e57600080fd5b5061375b36828601613642565b60408301525092915050565b601f821115612989576000816000526020600020601f850160051c810160208610156137905750805b601f850160051c820191505b818110156137af5782815560010161379c565b505050505050565b815167ffffffffffffffff8111156137d1576137d16133f1565b6137e5816137df8454613358565b84613767565b602080601f83116001811461383857600084156138025750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137af565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561388557888601518255948401946001909101908401613866565b50858210156138c157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006138f460408301846130c1565b949350505050565b600082601f83011261390d57600080fd5b8135602061391d6135e38361359e565b82815260059290921b8401810191818101908684111561393c57600080fd5b8286015b8481101561362657803567ffffffffffffffff8111156139605760008081fd5b61396e8986838b0101613642565b845250918301918301613940565b6000602080838503121561398f57600080fd5b823567ffffffffffffffff808211156139a757600080fd5b818501915085601f8301126139bb57600080fd5b81356139c96135e38261359e565b81815260059190911b830184019084810190888311156139e857600080fd5b8585015b83811015613b5057803585811115613a0357600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613a3957600080fd5b613a41613502565b613a4c8a8401612d98565b8152613a5a60408401613283565b8a820152613a6a60608401613631565b6040820152613a7b60808401613283565b606082015260a083013588811115613a9257600080fd5b613aa08e8c83870101613642565b60808301525060c083013588811115613ab857600080fd5b613ac68e8c838701016135c2565b60a08301525060e083013588811115613adf5760008081fd5b613aed8e8c838701016138fc565b60c0830152506101008084013589811115613b085760008081fd5b613b168f8d838801016138fc565b60e084015250918301359188831115613b2f5760008081fd5b613b3d8e8c85870101613642565b90820152855250509186019186016139ec565b5098975050505050505050565b8051612d9381612d76565b600082601f830112613b7957600080fd5b81516020613b896135e38361359e565b8083825260208201915060208460051b870101935086841115613bab57600080fd5b602086015b848110156136265780518352918301918301613bb0565b600060208284031215613bd957600080fd5b815167ffffffffffffffff80821115613bf157600080fd5b9083019060e08286031215613c0557600080fd5b613c0d61352c565b613c1683613b5d565b8152613c2460208401613b5d565b6020820152613c3560408401613b5d565b6040820152606083015160608201526080830151608082015260a083015182811115613c6057600080fd5b613c6c87828601613b68565b60a08301525060c083015182811115613c8457600080fd5b613c9087828601613b68565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613cd057613cd06133ab565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611d5857611d586133ab565b60038110612e1b57612e1b612ddc565b60408101613d448285613d26565b610f616020830184613d26565b67ffffffffffffffff818116838216019080821115611d5857611d586133ab565b60ff8181168382160290811690818114611d5857611d586133ab565b60ff81811683821601908111156102db576102db6133ab565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613dd2604084018d612e0b565b806060840152613de48184018c612cff565b67ffffffffffffffff8b166080850152905082810360a0840152613e08818a612e1f565b905082810360c0840152613e1c8189612e5b565b905082810360e0840152613e308188612e5b565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613e608185612cff565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI @@ -201,9 +200,9 @@ func (_CCIPConfig *CCIPConfigTransactorRaw) Transact(opts *bind.TransactOpts, me return _CCIPConfig.Contract.contract.Transact(opts, method, params...) } -func (_CCIPConfig *CCIPConfigCaller) GetAllChainConfigs(opts *bind.CallOpts) ([]CCIPConfigTypesChainConfigInfo, error) { +func (_CCIPConfig *CCIPConfigCaller) GetAllChainConfigs(opts *bind.CallOpts, pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) { var out []interface{} - err := _CCIPConfig.contract.Call(opts, &out, "getAllChainConfigs") + err := _CCIPConfig.contract.Call(opts, &out, "getAllChainConfigs", pageIndex, pageSize) if err != nil { return *new([]CCIPConfigTypesChainConfigInfo), err @@ -215,12 +214,12 @@ func (_CCIPConfig *CCIPConfigCaller) GetAllChainConfigs(opts *bind.CallOpts) ([] } -func (_CCIPConfig *CCIPConfigSession) GetAllChainConfigs() ([]CCIPConfigTypesChainConfigInfo, error) { - return _CCIPConfig.Contract.GetAllChainConfigs(&_CCIPConfig.CallOpts) +func (_CCIPConfig *CCIPConfigSession) GetAllChainConfigs(pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) { + return _CCIPConfig.Contract.GetAllChainConfigs(&_CCIPConfig.CallOpts, pageIndex, pageSize) } -func (_CCIPConfig *CCIPConfigCallerSession) GetAllChainConfigs() ([]CCIPConfigTypesChainConfigInfo, error) { - return _CCIPConfig.Contract.GetAllChainConfigs(&_CCIPConfig.CallOpts) +func (_CCIPConfig *CCIPConfigCallerSession) GetAllChainConfigs(pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) { + return _CCIPConfig.Contract.GetAllChainConfigs(&_CCIPConfig.CallOpts, pageIndex, pageSize) } func (_CCIPConfig *CCIPConfigCaller) GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) { @@ -245,6 +244,28 @@ func (_CCIPConfig *CCIPConfigCallerSession) GetCapabilityConfiguration(arg0 uint return _CCIPConfig.Contract.GetCapabilityConfiguration(&_CCIPConfig.CallOpts, arg0) } +func (_CCIPConfig *CCIPConfigCaller) GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "getCapabilityRegistry") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) GetCapabilityRegistry() (common.Address, error) { + return _CCIPConfig.Contract.GetCapabilityRegistry(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCallerSession) GetCapabilityRegistry() (common.Address, error) { + return _CCIPConfig.Contract.GetCapabilityRegistry(&_CCIPConfig.CallOpts) +} + func (_CCIPConfig *CCIPConfigCaller) GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) { var out []interface{} err := _CCIPConfig.contract.Call(opts, &out, "getOCRConfig", donId, pluginType) @@ -1047,10 +1068,12 @@ func (_CCIPConfig *CCIPConfig) Address() common.Address { } type CCIPConfigInterface interface { - GetAllChainConfigs(opts *bind.CallOpts) ([]CCIPConfigTypesChainConfigInfo, error) + GetAllChainConfigs(opts *bind.CallOpts, pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) + GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) + GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) Owner(opts *bind.CallOpts) (common.Address, error) 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 new file mode 100644 index 00000000000..7886793aa08 --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go @@ -0,0 +1,282 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_encoding_utils + +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 CCIPHomeOCR3Config struct { + PluginType uint8 + ChainSelector uint64 + FRoleDON uint8 + OffchainConfigVersion uint64 + OfframpAddress []byte + RmnHomeAddress []byte + Nodes []CCIPHomeOCR3Node + OffchainConfig []byte +} + +type CCIPHomeOCR3Node struct { + P2pId [32]byte + SignerKey []byte + TransmitterKey []byte +} + +type IRMNRemoteSignature struct { + R [32]byte + S [32]byte +} + +type InternalGasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas *big.Int +} + +type InternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + +type InternalPriceUpdates struct { + TokenPriceUpdates []InternalTokenPriceUpdate + GasPriceUpdates []InternalGasPriceUpdate +} + +type InternalTokenPriceUpdate struct { + SourceToken common.Address + UsdPerToken *big.Int +} + +type OffRampCommitReport struct { + PriceUpdates InternalPriceUpdates + MerkleRoots []InternalMerkleRoot + RmnSignatures []IRMNRemoteSignature + RmnRawVs *big.Int +} + +type RMNRemoteReport struct { + DestChainId *big.Int + DestChainSelector uint64 + RmnRemoteContractAddress common.Address + OfframpAddress common.Address + RmnHomeContractConfigDigest [32]byte + MerkleRoots []InternalMerkleRoot +} + +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\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"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\"}]", +} + +var EncodingUtilsABI = EncodingUtilsMetaData.ABI + +type EncodingUtils struct { + address common.Address + abi abi.ABI + EncodingUtilsCaller + EncodingUtilsTransactor + EncodingUtilsFilterer +} + +type EncodingUtilsCaller struct { + contract *bind.BoundContract +} + +type EncodingUtilsTransactor struct { + contract *bind.BoundContract +} + +type EncodingUtilsFilterer struct { + contract *bind.BoundContract +} + +type EncodingUtilsSession struct { + Contract *EncodingUtils + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type EncodingUtilsCallerSession struct { + Contract *EncodingUtilsCaller + CallOpts bind.CallOpts +} + +type EncodingUtilsTransactorSession struct { + Contract *EncodingUtilsTransactor + TransactOpts bind.TransactOpts +} + +type EncodingUtilsRaw struct { + Contract *EncodingUtils +} + +type EncodingUtilsCallerRaw struct { + Contract *EncodingUtilsCaller +} + +type EncodingUtilsTransactorRaw struct { + Contract *EncodingUtilsTransactor +} + +func NewEncodingUtils(address common.Address, backend bind.ContractBackend) (*EncodingUtils, error) { + abi, err := abi.JSON(strings.NewReader(EncodingUtilsABI)) + if err != nil { + return nil, err + } + contract, err := bindEncodingUtils(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &EncodingUtils{address: address, abi: abi, EncodingUtilsCaller: EncodingUtilsCaller{contract: contract}, EncodingUtilsTransactor: EncodingUtilsTransactor{contract: contract}, EncodingUtilsFilterer: EncodingUtilsFilterer{contract: contract}}, nil +} + +func NewEncodingUtilsCaller(address common.Address, caller bind.ContractCaller) (*EncodingUtilsCaller, error) { + contract, err := bindEncodingUtils(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EncodingUtilsCaller{contract: contract}, nil +} + +func NewEncodingUtilsTransactor(address common.Address, transactor bind.ContractTransactor) (*EncodingUtilsTransactor, error) { + contract, err := bindEncodingUtils(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EncodingUtilsTransactor{contract: contract}, nil +} + +func NewEncodingUtilsFilterer(address common.Address, filterer bind.ContractFilterer) (*EncodingUtilsFilterer, error) { + contract, err := bindEncodingUtils(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &EncodingUtilsFilterer{contract: contract}, nil +} + +func bindEncodingUtils(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EncodingUtilsMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_EncodingUtils *EncodingUtilsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EncodingUtils.Contract.EncodingUtilsCaller.contract.Call(opts, result, method, params...) +} + +func (_EncodingUtils *EncodingUtilsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EncodingUtils.Contract.EncodingUtilsTransactor.contract.Transfer(opts) +} + +func (_EncodingUtils *EncodingUtilsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EncodingUtils.Contract.EncodingUtilsTransactor.contract.Transact(opts, method, params...) +} + +func (_EncodingUtils *EncodingUtilsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EncodingUtils.Contract.contract.Call(opts, result, method, params...) +} + +func (_EncodingUtils *EncodingUtilsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EncodingUtils.Contract.contract.Transfer(opts) +} + +func (_EncodingUtils *EncodingUtilsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EncodingUtils.Contract.contract.Transact(opts, method, params...) +} + +func (_EncodingUtils *EncodingUtilsCaller) ExposeCommitReport(opts *bind.CallOpts, commitReport OffRampCommitReport) ([]byte, error) { + var out []interface{} + err := _EncodingUtils.contract.Call(opts, &out, "exposeCommitReport", commitReport) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_EncodingUtils *EncodingUtilsSession) ExposeCommitReport(commitReport OffRampCommitReport) ([]byte, error) { + return _EncodingUtils.Contract.ExposeCommitReport(&_EncodingUtils.CallOpts, commitReport) +} + +func (_EncodingUtils *EncodingUtilsCallerSession) ExposeCommitReport(commitReport OffRampCommitReport) ([]byte, error) { + return _EncodingUtils.Contract.ExposeCommitReport(&_EncodingUtils.CallOpts, commitReport) +} + +func (_EncodingUtils *EncodingUtilsCaller) ExposeOCR3Config(opts *bind.CallOpts, config []CCIPHomeOCR3Config) ([]byte, error) { + var out []interface{} + err := _EncodingUtils.contract.Call(opts, &out, "exposeOCR3Config", config) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_EncodingUtils *EncodingUtilsSession) ExposeOCR3Config(config []CCIPHomeOCR3Config) ([]byte, error) { + return _EncodingUtils.Contract.ExposeOCR3Config(&_EncodingUtils.CallOpts, config) +} + +func (_EncodingUtils *EncodingUtilsCallerSession) ExposeOCR3Config(config []CCIPHomeOCR3Config) ([]byte, error) { + return _EncodingUtils.Contract.ExposeOCR3Config(&_EncodingUtils.CallOpts, config) +} + +func (_EncodingUtils *EncodingUtilsTransactor) ExposeRmnReport(opts *bind.TransactOpts, rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) { + return _EncodingUtils.contract.Transact(opts, "exposeRmnReport", rmnReportVersion, rmnReport) +} + +func (_EncodingUtils *EncodingUtilsSession) ExposeRmnReport(rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) { + return _EncodingUtils.Contract.ExposeRmnReport(&_EncodingUtils.TransactOpts, rmnReportVersion, rmnReport) +} + +func (_EncodingUtils *EncodingUtilsTransactorSession) ExposeRmnReport(rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) { + return _EncodingUtils.Contract.ExposeRmnReport(&_EncodingUtils.TransactOpts, rmnReportVersion, rmnReport) +} + +func (_EncodingUtils *EncodingUtils) Address() common.Address { + return _EncodingUtils.address +} + +type EncodingUtilsInterface interface { + ExposeCommitReport(opts *bind.CallOpts, commitReport OffRampCommitReport) ([]byte, error) + + ExposeOCR3Config(opts *bind.CallOpts, config []CCIPHomeOCR3Config) ([]byte, error) + + ExposeRmnReport(opts *bind.TransactOpts, rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go b/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go new file mode 100644 index 00000000000..64e2fbd98bc --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go @@ -0,0 +1,1894 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_home + +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 CCIPHomeChainConfig struct { + Readers [][32]byte + FChain uint8 + Config []byte +} + +type CCIPHomeChainConfigArgs struct { + ChainSelector uint64 + ChainConfig CCIPHomeChainConfig +} + +type CCIPHomeOCR3Config struct { + PluginType uint8 + ChainSelector uint64 + FRoleDON uint8 + OffchainConfigVersion uint64 + OfframpAddress []byte + RmnHomeAddress []byte + Nodes []CCIPHomeOCR3Node + OffchainConfig []byte +} + +type CCIPHomeOCR3Node struct { + P2pId [32]byte + SignerKey []byte + TransmitterKey []byte +} + +type CCIPHomeVersionedConfig struct { + Version uint32 + ConfigDigest [32]byte + Config CCIPHomeOCR3Config +} + +var CCIPHomeMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"currentActiveDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"currentCandidateDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"proposedActiveDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"proposedCandidateDigest\",\"type\":\"bytes32\"}],\"name\":\"InvalidStateTransition\",\"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\":\"OnlyCapabilitiesRegistryCanCall\",\"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\":\"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: "0x60a06040526006805463ffffffff191690553480156200001e57600080fd5b5060405162004dbe38038062004dbe8339810160408190526200004191620001b3565b3380600081620000985760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000cb57620000cb8162000108565b5050506001600160a01b038116620000f6576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001e5565b336001600160a01b03821603620001625760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001c657600080fd5b81516001600160a01b0381168114620001de57600080fd5b9392505050565b608051614baf6200020f60003960008181610180015281816122360152612cf20152614baf6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063b74b235611610081578063f2fde38b11610066578063f2fde38b14610356578063f442c89a14610369578063fba64a7c1461037c57600080fd5b8063b74b235614610323578063bae4e0fa1461034357600080fd5b80638318ed5d116100b25780638318ed5d146102d15780638da5cb5b146102f2578063922ea4061461031057600080fd5b806379ba5097146102c15780637ac0d41e146102c957600080fd5b80633df45a72116101245780635a837f97116101095780635a837f97146102785780635f1edd9c1461028d5780637524051a146102ae57600080fd5b80633df45a721461022f5780634851d5491461025057600080fd5b806301ffc9a714610156578063020330e61461017e578063181f5a77146101c557806333d9704a1461020e575b600080fd5b610169610164366004613091565b61038f565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610175565b6102016040518060400160405280601281526020017f43434950486f6d6520312e362e302d646576000000000000000000000000000081525081565b6040516101759190613123565b61022161021c366004613170565b610428565b6040516101759291906133aa565b61024261023d3660046133ce565b610922565b604051610175929190613407565b61026361025e3660046133ce565b611222565b60408051928352602083019190915201610175565b61028b61028636600461342c565b611318565b005b6102a061029b3660046133ce565b61162b565b604051908152602001610175565b61028b6102bc366004613170565b6116a2565b61028b61188d565b6102a061198a565b6102016102df366004613472565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff166101a0565b6102a061031e3660046133ce565b61199b565b61033661033136600461348f565b6119ec565b6040516101759190613528565b6102a06103513660046135c6565b611c6d565b61028b610364366004613636565b611e6b565b61028b6103773660046136b1565b611e7f565b61028b61038a36600461373e565b61221e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea72100000000000000000000000000000000000000000000000000000000148061042257507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b610430612f1a565b6000805b60028110156109145763ffffffff861660009081526005602052604081208591876001811115610466576104666131b1565b6001811115610477576104776131b1565b81526020019081526020016000208260028110610496576104966137fb565b60070201600101541480156104aa57508315155b1561090c5763ffffffff86166000908152600560205260408120908660018111156104d7576104d76131b1565b60018111156104e8576104e86131b1565b81526020019081526020016000208160028110610507576105076137fb565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054939592949386938501929190829060ff1687811115610560576105606131b1565b6001811115610571576105716131b1565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916105c99061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546105f59061382a565b80156106425780601f1061061757610100808354040283529160200191610642565b820191906000526020600020905b81548152906001019060200180831161062557829003601f168201915b5050505050815260200160028201805461065b9061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546106879061382a565b80156106d45780601f106106a9576101008083540402835291602001916106d4565b820191906000526020600020905b8154815290600101906020018083116106b757829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561086257838290600052602060002090600302016040518060600160405290816000820154815260200160018201805461073f9061382a565b80601f016020809104026020016040519081016040528092919081815260200182805461076b9061382a565b80156107b85780601f1061078d576101008083540402835291602001916107b8565b820191906000526020600020905b81548152906001019060200180831161079b57829003601f168201915b505050505081526020016002820180546107d19061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546107fd9061382a565b801561084a5780601f1061081f5761010080835404028352916020019161084a565b820191906000526020600020905b81548152906001019060200180831161082d57829003601f168201915b50505050508152505081526020019060010190610702565b50505050815260200160048201805461087a9061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546108a69061382a565b80156108f35780601f106108c8576101008083540402835291602001916108f3565b820191906000526020600020905b8154815290600101906020018083116108d657829003601f168201915b505050505081525050815250509150925092505061091a565b600101610434565b50600090505b935093915050565b61092a612f1a565b610932612f1a565b63ffffffff841660009081526005602052604081208185600181111561095a5761095a6131b1565b600181111561096b5761096b6131b1565b815260200190815260200160002061098386866124db565b63ffffffff1660028110610999576109996137fb565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054949593949386019391929091839160ff909116908111156109f4576109f46131b1565b6001811115610a0557610a056131b1565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610a5d9061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610a899061382a565b8015610ad65780601f10610aab57610100808354040283529160200191610ad6565b820191906000526020600020905b815481529060010190602001808311610ab957829003601f168201915b50505050508152602001600282018054610aef9061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1b9061382a565b8015610b685780601f10610b3d57610100808354040283529160200191610b68565b820191906000526020600020905b815481529060010190602001808311610b4b57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610cf6578382906000526020600020906003020160405180606001604052908160008201548152602001600182018054610bd39061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bff9061382a565b8015610c4c5780601f10610c2157610100808354040283529160200191610c4c565b820191906000526020600020905b815481529060010190602001808311610c2f57829003601f168201915b50505050508152602001600282018054610c659061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610c919061382a565b8015610cde5780601f10610cb357610100808354040283529160200191610cde565b820191906000526020600020905b815481529060010190602001808311610cc157829003601f168201915b50505050508152505081526020019060010190610b96565b505050508152602001600482018054610d0e9061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3a9061382a565b8015610d875780601f10610d5c57610100808354040283529160200191610d87565b820191906000526020600020905b815481529060010190602001808311610d6a57829003601f168201915b50505091909252505050905250602081015190915015610da5578092505b63ffffffff8516600090815260056020526040812081866001811115610dcd57610dcd6131b1565b6001811115610dde57610dde6131b1565b8152602001908152602001600020610df68787612532565b63ffffffff1660028110610e0c57610e0c6137fb565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054949593949386019391929091839160ff90911690811115610e6757610e676131b1565b6001811115610e7857610e786131b1565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610ed09061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610efc9061382a565b8015610f495780601f10610f1e57610100808354040283529160200191610f49565b820191906000526020600020905b815481529060010190602001808311610f2c57829003601f168201915b50505050508152602001600282018054610f629061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8e9061382a565b8015610fdb5780601f10610fb057610100808354040283529160200191610fdb565b820191906000526020600020905b815481529060010190602001808311610fbe57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156111695783829060005260206000209060030201604051806060016040529081600082015481526020016001820180546110469061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546110729061382a565b80156110bf5780601f10611094576101008083540402835291602001916110bf565b820191906000526020600020905b8154815290600101906020018083116110a257829003601f168201915b505050505081526020016002820180546110d89061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546111049061382a565b80156111515780601f1061112657610100808354040283529160200191611151565b820191906000526020600020905b81548152906001019060200180831161113457829003601f168201915b50505050508152505081526020019060010190611009565b5050505081526020016004820180546111819061382a565b80601f01602080910402602001604051908101604052809291908181526020018280546111ad9061382a565b80156111fa5780601f106111cf576101008083540402835291602001916111fa565b820191906000526020600020905b8154815290600101906020018083116111dd57829003601f168201915b50505091909252505050905250602081015190915015611218578092505b50505b9250929050565b63ffffffff8216600090815260056020526040812081908184600181111561124c5761124c6131b1565b600181111561125d5761125d6131b1565b815260200190815260200160002061127585856124db565b63ffffffff166002811061128b5761128b6137fb565b6007020160010154600560008663ffffffff1663ffffffff16815260200190815260200160002060008560018111156112c6576112c66131b1565b60018111156112d7576112d76131b1565b81526020019081526020016000206112ef8686612532565b63ffffffff1660028110611305576113056137fb565b6007020160010154915091509250929050565b61132061258d565b8115801561132c575080155b15611363576040517f7b4d1e4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061136f8585612532565b63ffffffff86811660009081526005602052604081209290911692508491908660018111156113a0576113a06131b1565b60018111156113b1576113b16131b1565b815260200190815260200160002082600281106113d0576113d06137fb565b6007020160010154146114845763ffffffff8516600090815260056020526040812090856001811115611405576114056131b1565b6001811115611416576114166131b1565b81526020019081526020016000208160028110611435576114356137fb565b6007020160010154836040517f93df584c00000000000000000000000000000000000000000000000000000000815260040161147b929190918252602082015260400190565b60405180910390fd5b63ffffffff85166000908152600560205260408120818660018111156114ac576114ac6131b1565b60018111156114bd576114bd6131b1565b81526020019081526020016000206114d587876124db565b63ffffffff16600281106114eb576114eb6137fb565b6007020190508281600101541461153e5760018101546040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091526024810184905260440161147b565b6000600180830182905563ffffffff881682526007602052604082209091878381111561156d5761156d6131b1565b600181111561157e5761157e6131b1565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000811663ffffffff918216939093181691909117905582156115f85760405183907f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b890600090a25b60405184907ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e90600090a2505050505050565b63ffffffff8216600090815260056020526040812081836001811115611653576116536131b1565b6001811115611664576116646131b1565b815260200190815260200160002061167c84846124db565b63ffffffff1660028110611692576116926137fb565b6007020160010154905092915050565b6116aa61258d565b806116e1576040517f0849d8cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116ed8484612532565b63ffffffff858116600090815260056020526040812092909116925083919085600181111561171e5761171e6131b1565b600181111561172f5761172f6131b1565b8152602001908152602001600020826002811061174e5761174e6137fb565b6007020160010154146117f95763ffffffff8416600090815260056020526040812090846001811115611783576117836131b1565b6001811115611794576117946131b1565b815260200190815260200160002081600281106117b3576117b36137fb565b6007020160010154826040517f93df584c00000000000000000000000000000000000000000000000000000000815260040161147b929190918252602082015260400190565b60405182907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a263ffffffff841660009081526005602052604081209084600181111561184c5761184c6131b1565b600181111561185d5761185d6131b1565b8152602001908152602001600020816002811061187c5761187c6137fb565b600702016001016000905550505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461190e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161147b565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600061199660036125c8565b905090565b63ffffffff82166000908152600560205260408120818360018111156119c3576119c36131b1565b60018111156119d4576119d46131b1565b815260200190815260200160002061167c8484612532565b606060006119fa60036125c8565b90506000611a0884866138ac565b9050831580611a175750818110155b15611a57576040805160008082526020820190925290611a4d565b611a3a612f96565b815260200190600190039081611a325790505b5092505050610422565b6000611a6385836138f2565b905082811115611a705750815b6000611a7c8383613905565b67ffffffffffffffff811115611a9457611a946138c3565b604051908082528060200260200182016040528015611acd57816020015b611aba612f96565b815260200190600190039081611ab25790505b5090506000611adc60036125d2565b9050835b83811015611c60576000828281518110611afc57611afc6137fb565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015611b8257602002820191906000526020600020905b815481526020019060010190808311611b6e575b5050509183525050600182015460ff166020820152600282018054604090920191611bac9061382a565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd89061382a565b8015611c255780601f10611bfa57610100808354040283529160200191611c25565b820191906000526020600020905b815481529060010190602001808311611c0857829003601f168201915b50505091909252505050905284611c3c8885613905565b81518110611c4c57611c4c6137fb565b602090810291909101015250600101611ae0565b5090979650505050505050565b6000611c7761258d565b611c88611c8384613b3e565b6125e6565b6000611c94868661199b565b9050828114611cd9576040517f93df584c000000000000000000000000000000000000000000000000000000008152600481018290526024810184905260440161147b565b8015611d0b5760405183907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a25b60068054600091908290611d249063ffffffff16613c3a565b91906101000a81548163ffffffff021916908363ffffffff16021790559050611d6e878787604051602001611d599190613f16565b60405160208183030381529060405284612a54565b63ffffffff881660009081526005602052604081209194509081886001811115611d9a57611d9a6131b1565b6001811115611dab57611dab6131b1565b8152602001908152602001600020611dc38989612532565b63ffffffff1660028110611dd957611dd96137fb565b600702016001810185905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff841617815590508560028201611e2382826143fc565b905050837f94f085b7c57ec2a270befd0b7b2ec7452580040edee8bb0fb04609c81f0359c68388604051611e589291906145c3565b60405180910390a2505050949350505050565b611e73612b14565b611e7c81612b95565b50565b611e87612b14565b60005b8381101561206d57611ece858583818110611ea757611ea76137fb565b9050602002016020810190611ebc91906145ea565b60039067ffffffffffffffff16612c8a565b611f3857848482818110611ee457611ee46137fb565b9050602002016020810190611ef991906145ea565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161147b565b60026000868684818110611f4e57611f4e6137fb565b9050602002016020810190611f6391906145ea565b67ffffffffffffffff1681526020810191909152604001600090812090611f8a8282612fd9565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611fc2600283016000612ff7565b5050612000858583818110611fd957611fd96137fb565b9050602002016020810190611fee91906145ea565b60039067ffffffffffffffff16612ca2565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110612034576120346137fb565b905060200201602081019061204991906145ea565b60405167ffffffffffffffff909116815260200160405180910390a1600101611e8a565b5060005b8181101561221757600083838381811061208d5761208d6137fb565b905060200281019061209f9190614607565b6120ad90602081019061415f565b6120b69061463b565b905060008484848181106120cc576120cc6137fb565b90506020028101906120de9190614607565b6120ec9060208101906145ea565b90506120fb8260000151612cae565b816020015160ff1660000361213c576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8116600090815260026020908152604090912083518051859361216c928492910190613031565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055604082015160028201906121b9908261470d565b506121d391506003905067ffffffffffffffff8316612d70565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051612205929190614809565b60405180910390a15050600101612071565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461228d576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061229c600482868861482c565b6122a591614856565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167fbae4e0fa000000000000000000000000000000000000000000000000000000001480159061233b57507fffffffff0000000000000000000000000000000000000000000000000000000081167f7524051a0000000000000000000000000000000000000000000000000000000014155b801561238957507fffffffff0000000000000000000000000000000000000000000000000000000081167f5a837f970000000000000000000000000000000000000000000000000000000014155b156123e4576040517f12ba286f0000000000000000000000000000000000000000000000000000000081527fffffffff000000000000000000000000000000000000000000000000000000008216600482015260240161147b565b60006123f460246004878961482c565b810190612401919061489e565b90508263ffffffff168114612452576040517f8a6e4ce800000000000000000000000000000000000000000000000000000000815263ffffffff80831660048301528416602482015260440161147b565b6000803073ffffffffffffffffffffffffffffffffffffffff16888860405161247c9291906148b7565b6000604051808303816000865af19150503d80600081146124b9576040519150601f19603f3d011682016040523d82523d6000602084013e6124be565b606091505b5091509150816124cf573d60208201fd5b50505050505050505050565b63ffffffff8216600090815260076020526040812081836001811115612503576125036131b1565b6001811115612514576125146131b1565b815260208101919091526040016000205463ffffffff169392505050565b63ffffffff821660009081526007602052604081208183600181111561255a5761255a6131b1565b600181111561256b5761256b6131b1565b815260208101919091526040016000205463ffffffff16600118905092915050565b3330146125c6576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610422825490565b606060006125df83612d7c565b9392505050565b806020015167ffffffffffffffff1660000361262e576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081516001811115612643576126436131b1565b141580156126645750600181516001811115612661576126616131b1565b14155b1561269b576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101515115806126d8575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b1561270f576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a081015151158061274c5750604080516000602082015201604051602081830303815290604052805190602001208160a0015180519060200120145b15612783576040517fdee9857400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015161279e9060039067ffffffffffffffff16612c8a565b6127e65760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161147b565b60408082015160208084015167ffffffffffffffff1660009081526002909152919091206001015460ff918216911681811115612859576040517f2db22040000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161147b565b60c08301515161010081111561289b576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128a68360036138ac565b81116128de576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808267ffffffffffffffff8111156128fa576128fa6138c3565b604051908082528060200260200182016040528015612923578160200160208202803683370190505b50905060005b838110156129e35760008760c001518281518110612949576129496137fb565b6020026020010151905080604001515160001461296e578361296a816148c7565b9450505b602081015151158061297f57508051155b156129b857806040517f9fa4031400000000000000000000000000000000000000000000000000000000815260040161147b91906148ff565b80600001518383815181106129cf576129cf6137fb565b602090810291909101015250600101612929565b5060006129f18560036138ac565b6129fc9060016138f2565b905080831015612a42576040517f548dd21f000000000000000000000000000000000000000000000000000000008152600481018490526024810182905260440161147b565b612a4b82612cae565b50505050505050565b6040516000907dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90612ab2907f45564d000000000000000000000000000000000000000000000000000000000090469030908a908a908990602001614912565b60408051601f1981840301815290829052612ad191869060200161496b565b60408051808303601f190181529190528051602090910120167e0a0000000000000000000000000000000000000000000000000000000000001795945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146125c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161147b565b3373ffffffffffffffffffffffffffffffffffffffff821603612c14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161147b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205415156125df565b60006125df8383612dd8565b805115611e7c576040517f05a5196600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906305a5196690612d2790849060040161499a565b600060405180830381865afa158015612d44573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d6c9190810190614a17565b5050565b60006125df8383612ecb565b606081600001805480602002602001604051908101604052809291908181526020018280548015612dcc57602002820191906000526020600020905b815481526020019060010190808311612db8575b50505050509050919050565b60008181526001830160205260408120548015612ec1576000612dfc600183613905565b8554909150600090612e1090600190613905565b9050808214612e75576000866000018281548110612e3057612e306137fb565b9060005260206000200154905080876000018481548110612e5357612e536137fb565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e8657612e86614b73565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610422565b6000915050610422565b6000818152600183016020526040812054612f1257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610422565b506000610422565b6040805160608101825260008082526020820152908101612f916040805161010081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff168152602001606081526020016060815260200160608152602001606081525090565b905290565b6040518060400160405280600067ffffffffffffffff168152602001612f91604051806060016040528060608152602001600060ff168152602001606081525090565b5080546000825590600052602060002090810190611e7c919061307c565b5080546130039061382a565b6000825580601f10613013575050565b601f016020900490600052602060002090810190611e7c919061307c565b82805482825590600052602060002090810192821561306c579160200282015b8281111561306c578251825591602001919060010190613051565b5061307892915061307c565b5090565b5b80821115613078576000815560010161307d565b6000602082840312156130a357600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146125df57600080fd5b60005b838110156130ee5781810151838201526020016130d6565b50506000910152565b6000815180845261310f8160208601602086016130d3565b601f01601f19169290920160200192915050565b6020815260006125df60208301846130f7565b63ffffffff81168114611e7c57600080fd5b803561315381613136565b919050565b60028110611e7c57600080fd5b803561315381613158565b60008060006060848603121561318557600080fd5b833561319081613136565b925060208401356131a081613158565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613217577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b80518252600060208201516060602085015261323a60608501826130f7565b90506040830151848203604086015261325382826130f7565b95945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015611c6057601f1986840301895261329783835161321b565b9884019892509083019060010161327b565b63ffffffff81511682526020810151602083015260006040820151606060408501526132d96060850182516131e0565b602081015167ffffffffffffffff8116608086015250604081015160ff811660a086015250606081015167ffffffffffffffff811660c08601525060808101516101008060e08701526133306101608701836130f7565b915060a08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa080888503018389015261336b84836130f7565b935060c085015192508088850301610120890152613389848461325c565b935060e08501519450808885030161014089015250505061325381836130f7565b6040815260006133bd60408301856132a9565b905082151560208301529392505050565b600080604083850312156133e157600080fd5b82356133ec81613136565b915060208301356133fc81613158565b809150509250929050565b60408152600061341a60408301856132a9565b828103602084015261325381856132a9565b6000806000806080858703121561344257600080fd5b843561344d81613136565b9350602085013561345d81613158565b93969395505050506040820135916060013590565b60006020828403121561348457600080fd5b81356125df81613136565b600080604083850312156134a257600080fd5b50508035926020909101359150565b60008151808452602080850194506020840160005b838110156134e2578151875295820195908201906001016134c6565b509495945050505050565b600081516060845261350260608501826134b1565b905060ff60208401511660208501526040830151848203604086015261325382826130f7565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156135b8578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526135a5878501826134ed565b9588019593505090860190600101613551565b509098975050505050505050565b600080600080608085870312156135dc57600080fd5b84356135e781613136565b935060208501356135f781613158565b9250604085013567ffffffffffffffff81111561361357600080fd5b8501610100818803121561362657600080fd5b9396929550929360600135925050565b60006020828403121561364857600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146125df57600080fd5b60008083601f84011261367e57600080fd5b50813567ffffffffffffffff81111561369657600080fd5b6020830191508360208260051b850101111561121b57600080fd5b600080600080604085870312156136c757600080fd5b843567ffffffffffffffff808211156136df57600080fd5b6136eb8883890161366c565b9096509450602087013591508082111561370457600080fd5b506137118782880161366c565b95989497509550505050565b67ffffffffffffffff81168114611e7c57600080fd5b80356131538161371d565b6000806000806000806080878903121561375757600080fd5b863567ffffffffffffffff8082111561376f57600080fd5b61377b8a838b0161366c565b9098509650602089013591508082111561379457600080fd5b818901915089601f8301126137a857600080fd5b8135818111156137b757600080fd5b8a60208285010111156137c957600080fd5b6020830196508095505050506137e160408801613733565b91506137ef60608801613148565b90509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061383e57607f821691505b602082108103613877577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176104225761042261387d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156104225761042261387d565b818103818111156104225761042261387d565b6040516060810167ffffffffffffffff8111828210171561393b5761393b6138c3565b60405290565b604051610100810167ffffffffffffffff8111828210171561393b5761393b6138c3565b604051601f8201601f1916810167ffffffffffffffff8111828210171561398e5761398e6138c3565b604052919050565b60ff81168114611e7c57600080fd5b803561315381613996565b600082601f8301126139c157600080fd5b813567ffffffffffffffff8111156139db576139db6138c3565b6139ee6020601f19601f84011601613965565b818152846020838601011115613a0357600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115613a3a57613a3a6138c3565b5060051b60200190565b600082601f830112613a5557600080fd5b81356020613a6a613a6583613a20565b613965565b82815260059290921b84018101918181019086841115613a8957600080fd5b8286015b84811015613b3357803567ffffffffffffffff80821115613aae5760008081fd5b8189019150606080601f19848d03011215613ac95760008081fd5b613ad1613918565b87840135815260408085013584811115613aeb5760008081fd5b613af98e8b838901016139b0565b838b015250918401359183831115613b115760008081fd5b613b1f8d8a858801016139b0565b908201528652505050918301918301613a8d565b509695505050505050565b60006101008236031215613b5157600080fd5b613b59613941565b613b6283613165565b8152613b7060208401613733565b6020820152613b81604084016139a5565b6040820152613b9260608401613733565b6060820152608083013567ffffffffffffffff80821115613bb257600080fd5b613bbe368387016139b0565b608084015260a0850135915080821115613bd757600080fd5b613be3368387016139b0565b60a084015260c0850135915080821115613bfc57600080fd5b613c0836838701613a44565b60c084015260e0850135915080821115613c2157600080fd5b50613c2e368286016139b0565b60e08301525092915050565b600063ffffffff808316818103613c5357613c5361387d565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c9257600080fd5b830160208101925035905067ffffffffffffffff811115613cb257600080fd5b80360382131561121b57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d2157600080fd5b830160208101925035905067ffffffffffffffff811115613d4157600080fd5b8060051b360382131561121b57600080fd5b60008383855260208086019550808560051b830101846000805b88811015613e1157601f19868503018a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1893603018112613daf578283fd5b8801803585526060613dc387830183613c5d565b8289890152613dd58389018284613cc1565b925050506040613de781840184613c5d565b935087830382890152613dfb838583613cc1565b9d89019d97505050938601935050600101613d6d565b509198975050505050505050565b6000610100613e3684613e3185613165565b6131e0565b613e4260208401613733565b67ffffffffffffffff166020850152613e5d604084016139a5565b60ff166040850152613e7160608401613733565b67ffffffffffffffff166060850152613e8d6080840184613c5d565b826080870152613ea08387018284613cc1565b92505050613eb160a0840184613c5d565b85830360a0870152613ec4838284613cc1565b92505050613ed560c0840184613cec565b85830360c0870152613ee8838284613d53565b92505050613ef960e0840184613c5d565b85830360e0870152613f0c838284613cc1565b9695505050505050565b6020815260006125df6020830184613e1f565b600081356104228161371d565b6000813561042281613996565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613f7857600080fd5b83018035915067ffffffffffffffff821115613f9357600080fd5b60200191503681900382131561121b57600080fd5b5b81811015612d6c5760008155600101613fa9565b601f821115613ff657806000526020600020601f840160051c81016020851015613fe45750805b612217601f850160051c830182613fa8565b505050565b67ffffffffffffffff831115614013576140136138c3565b61402783614021835461382a565b83613fbd565b6000601f84116001811461407957600085156140435750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612217565b600083815260209020601f19861690835b828110156140aa578685013582556020948501946001909201910161408a565b50868210156140e5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261412c57600080fd5b83018035915067ffffffffffffffff82111561414757600080fd5b6020019150600581901b360382131561121b57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261419357600080fd5b9190910192915050565b6141a7815461382a565b8015612d6c57601f8111600181146141c157505060009055565b8260005260206000206141df601f840160051c820160018301613fa8565b60008085559055505050565b81358155600180820160206142036020860186613f43565b67ffffffffffffffff81111561421b5761421b6138c3565b61422f81614229865461382a565b86613fbd565b6000601f821160018114614281576000831561424b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1786556142f6565b600086815260209020601f19841690835b828110156142af5786850135825593870193908901908701614292565b50848210156142ea577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19848701351681555b505060018360011b0186555b5050505050505061430a6040830183613f43565b614318818360028601613ffb565b50505050565b68010000000000000000831115614337576143376138c3565b8054838255808410156143b65760038160030260038104831461435c5761435c61387d565b856003026003810487146143725761437261387d565b6000858152602081209283019291909101905b828210156143b15780825561439c6001830161419d565b6143a86002830161419d565b90830190614385565b505050505b5060008181526020812083915b858110156143f4576143de6143d8848761415f565b836141eb565b60209290920191600391909101906001016143c3565b505050505050565b813561440781613158565b6002811061443e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541660ff82168117835550506144b561447b60208401613f29565b82547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1660089190911b68ffffffffffffffff0016178255565b6144ff6144c460408401613f36565b82547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1660489190911b69ff00000000000000000016178255565b61455161450e60608401613f29565b82547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178255565b61455e6080830183613f43565b61456c818360018601613ffb565b505061457b60a0830183613f43565b614589818360028601613ffb565b505061459860c08301836140f7565b6145a681836003860161431e565b50506145b560e0830183613f43565b614318818360048601613ffb565b63ffffffff831681526040602082015260006145e26040830184613e1f565b949350505050565b6000602082840312156145fc57600080fd5b81356125df8161371d565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261419357600080fd5b60006060823603121561464d57600080fd5b614655613918565b823567ffffffffffffffff8082111561466d57600080fd5b9084019036601f83011261468057600080fd5b81356020614690613a6583613a20565b82815260059290921b840181019181810190368411156146af57600080fd5b948201945b838610156146cd578535825294820194908201906146b4565b8652506146db8782016139a5565b908501525060408501359150808211156146f457600080fd5b50614701368286016139b0565b60408301525092915050565b815167ffffffffffffffff811115614727576147276138c3565b61473b81614735845461382a565b84613fbd565b602080601f83116001811461478e57600084156147585750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556143f4565b600085815260208120601f198616915b828110156147bd5788860151825594840194600190910190840161479e565b50858210156147f957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006145e260408301846134ed565b6000808585111561483c57600080fd5b8386111561484957600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156148965780818660040360031b1b83161692505b505092915050565b6000602082840312156148b057600080fd5b5035919050565b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036148f8576148f861387d565b5060010190565b6020815260006125df602083018461321b565b8681526020810186905273ffffffffffffffffffffffffffffffffffffffff8516604082015263ffffffff848116606083015260c082019061495760808401866131e0565b80841660a084015250979650505050505050565b6000835161497d8184602088016130d3565b8351908301906149918183602088016130d3565b01949350505050565b6020815260006125df60208301846134b1565b805161315381613136565b600082601f8301126149c957600080fd5b815160206149d9613a6583613a20565b8083825260208201915060208460051b8701019350868411156149fb57600080fd5b602086015b84811015613b335780518352918301918301614a00565b60006020808385031215614a2a57600080fd5b825167ffffffffffffffff80821115614a4257600080fd5b818501915085601f830112614a5657600080fd5b8151614a64613a6582613a20565b81815260059190911b83018401908481019088831115614a8357600080fd5b8585015b83811015614b6657805185811115614a9e57600080fd5b8601610100818c03601f1901811315614ab657600080fd5b614abe613941565b614ac98a84016149ad565b8152614ad7604084016149ad565b8a820152614ae7606084016149ad565b60408201526080830151606082015260a0830151608082015260c083015160a082015260e08084015189811115614b1e5760008081fd5b614b2c8f8d838801016149b8565b60c084015250918301519188831115614b455760008081fd5b614b538e8c858701016149b8565b9082015285525050918601918601614a87565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", +} + +var CCIPHomeABI = CCIPHomeMetaData.ABI + +var CCIPHomeBin = CCIPHomeMetaData.Bin + +func DeployCCIPHome(auth *bind.TransactOpts, backend bind.ContractBackend, capabilitiesRegistry common.Address) (common.Address, *types.Transaction, *CCIPHome, error) { + parsed, err := CCIPHomeMetaData.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(CCIPHomeBin), backend, capabilitiesRegistry) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CCIPHome{address: address, abi: *parsed, CCIPHomeCaller: CCIPHomeCaller{contract: contract}, CCIPHomeTransactor: CCIPHomeTransactor{contract: contract}, CCIPHomeFilterer: CCIPHomeFilterer{contract: contract}}, nil +} + +type CCIPHome struct { + address common.Address + abi abi.ABI + CCIPHomeCaller + CCIPHomeTransactor + CCIPHomeFilterer +} + +type CCIPHomeCaller struct { + contract *bind.BoundContract +} + +type CCIPHomeTransactor struct { + contract *bind.BoundContract +} + +type CCIPHomeFilterer struct { + contract *bind.BoundContract +} + +type CCIPHomeSession struct { + Contract *CCIPHome + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CCIPHomeCallerSession struct { + Contract *CCIPHomeCaller + CallOpts bind.CallOpts +} + +type CCIPHomeTransactorSession struct { + Contract *CCIPHomeTransactor + TransactOpts bind.TransactOpts +} + +type CCIPHomeRaw struct { + Contract *CCIPHome +} + +type CCIPHomeCallerRaw struct { + Contract *CCIPHomeCaller +} + +type CCIPHomeTransactorRaw struct { + Contract *CCIPHomeTransactor +} + +func NewCCIPHome(address common.Address, backend bind.ContractBackend) (*CCIPHome, error) { + abi, err := abi.JSON(strings.NewReader(CCIPHomeABI)) + if err != nil { + return nil, err + } + contract, err := bindCCIPHome(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CCIPHome{address: address, abi: abi, CCIPHomeCaller: CCIPHomeCaller{contract: contract}, CCIPHomeTransactor: CCIPHomeTransactor{contract: contract}, CCIPHomeFilterer: CCIPHomeFilterer{contract: contract}}, nil +} + +func NewCCIPHomeCaller(address common.Address, caller bind.ContractCaller) (*CCIPHomeCaller, error) { + contract, err := bindCCIPHome(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CCIPHomeCaller{contract: contract}, nil +} + +func NewCCIPHomeTransactor(address common.Address, transactor bind.ContractTransactor) (*CCIPHomeTransactor, error) { + contract, err := bindCCIPHome(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CCIPHomeTransactor{contract: contract}, nil +} + +func NewCCIPHomeFilterer(address common.Address, filterer bind.ContractFilterer) (*CCIPHomeFilterer, error) { + contract, err := bindCCIPHome(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CCIPHomeFilterer{contract: contract}, nil +} + +func bindCCIPHome(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CCIPHomeMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CCIPHome *CCIPHomeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPHome.Contract.CCIPHomeCaller.contract.Call(opts, result, method, params...) +} + +func (_CCIPHome *CCIPHomeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPHome.Contract.CCIPHomeTransactor.contract.Transfer(opts) +} + +func (_CCIPHome *CCIPHomeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPHome.Contract.CCIPHomeTransactor.contract.Transact(opts, method, params...) +} + +func (_CCIPHome *CCIPHomeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPHome.Contract.contract.Call(opts, result, method, params...) +} + +func (_CCIPHome *CCIPHomeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPHome.Contract.contract.Transfer(opts) +} + +func (_CCIPHome *CCIPHomeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPHome.Contract.contract.Transact(opts, method, params...) +} + +func (_CCIPHome *CCIPHomeCaller) GetActiveDigest(opts *bind.CallOpts, donId uint32, pluginType uint8) ([32]byte, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getActiveDigest", donId, pluginType) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) GetActiveDigest(donId uint32, pluginType uint8) ([32]byte, error) { + return _CCIPHome.Contract.GetActiveDigest(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetActiveDigest(donId uint32, pluginType uint8) ([32]byte, error) { + return _CCIPHome.Contract.GetActiveDigest(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCaller) GetAllChainConfigs(opts *bind.CallOpts, pageIndex *big.Int, pageSize *big.Int) ([]CCIPHomeChainConfigArgs, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getAllChainConfigs", pageIndex, pageSize) + + if err != nil { + return *new([]CCIPHomeChainConfigArgs), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPHomeChainConfigArgs)).(*[]CCIPHomeChainConfigArgs) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) GetAllChainConfigs(pageIndex *big.Int, pageSize *big.Int) ([]CCIPHomeChainConfigArgs, error) { + return _CCIPHome.Contract.GetAllChainConfigs(&_CCIPHome.CallOpts, pageIndex, pageSize) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetAllChainConfigs(pageIndex *big.Int, pageSize *big.Int) ([]CCIPHomeChainConfigArgs, error) { + return _CCIPHome.Contract.GetAllChainConfigs(&_CCIPHome.CallOpts, pageIndex, pageSize) +} + +func (_CCIPHome *CCIPHomeCaller) GetAllConfigs(opts *bind.CallOpts, donId uint32, pluginType uint8) (GetAllConfigs, + + error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getAllConfigs", donId, pluginType) + + outstruct := new(GetAllConfigs) + if err != nil { + return *outstruct, err + } + + outstruct.ActiveConfig = *abi.ConvertType(out[0], new(CCIPHomeVersionedConfig)).(*CCIPHomeVersionedConfig) + outstruct.CandidateConfig = *abi.ConvertType(out[1], new(CCIPHomeVersionedConfig)).(*CCIPHomeVersionedConfig) + + return *outstruct, err + +} + +func (_CCIPHome *CCIPHomeSession) GetAllConfigs(donId uint32, pluginType uint8) (GetAllConfigs, + + error) { + return _CCIPHome.Contract.GetAllConfigs(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetAllConfigs(donId uint32, pluginType uint8) (GetAllConfigs, + + error) { + return _CCIPHome.Contract.GetAllConfigs(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCaller) GetCandidateDigest(opts *bind.CallOpts, donId uint32, pluginType uint8) ([32]byte, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getCandidateDigest", donId, pluginType) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) GetCandidateDigest(donId uint32, pluginType uint8) ([32]byte, error) { + return _CCIPHome.Contract.GetCandidateDigest(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetCandidateDigest(donId uint32, pluginType uint8) ([32]byte, error) { + return _CCIPHome.Contract.GetCandidateDigest(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCaller) GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getCapabilityConfiguration", arg0) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPHome.Contract.GetCapabilityConfiguration(&_CCIPHome.CallOpts, arg0) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPHome.Contract.GetCapabilityConfiguration(&_CCIPHome.CallOpts, arg0) +} + +func (_CCIPHome *CCIPHomeCaller) GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getCapabilityRegistry") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) GetCapabilityRegistry() (common.Address, error) { + return _CCIPHome.Contract.GetCapabilityRegistry(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetCapabilityRegistry() (common.Address, error) { + return _CCIPHome.Contract.GetCapabilityRegistry(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCaller) GetConfig(opts *bind.CallOpts, donId uint32, pluginType uint8, configDigest [32]byte) (GetConfig, + + error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getConfig", donId, pluginType, configDigest) + + outstruct := new(GetConfig) + if err != nil { + return *outstruct, err + } + + outstruct.VersionedConfig = *abi.ConvertType(out[0], new(CCIPHomeVersionedConfig)).(*CCIPHomeVersionedConfig) + outstruct.Ok = *abi.ConvertType(out[1], new(bool)).(*bool) + + return *outstruct, err + +} + +func (_CCIPHome *CCIPHomeSession) GetConfig(donId uint32, pluginType uint8, configDigest [32]byte) (GetConfig, + + error) { + return _CCIPHome.Contract.GetConfig(&_CCIPHome.CallOpts, donId, pluginType, configDigest) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetConfig(donId uint32, pluginType uint8, configDigest [32]byte) (GetConfig, + + error) { + return _CCIPHome.Contract.GetConfig(&_CCIPHome.CallOpts, donId, pluginType, configDigest) +} + +func (_CCIPHome *CCIPHomeCaller) GetConfigDigests(opts *bind.CallOpts, donId uint32, pluginType uint8) (GetConfigDigests, + + error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getConfigDigests", donId, pluginType) + + outstruct := new(GetConfigDigests) + if err != nil { + return *outstruct, err + } + + outstruct.ActiveConfigDigest = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.CandidateConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_CCIPHome *CCIPHomeSession) GetConfigDigests(donId uint32, pluginType uint8) (GetConfigDigests, + + error) { + return _CCIPHome.Contract.GetConfigDigests(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetConfigDigests(donId uint32, pluginType uint8) (GetConfigDigests, + + error) { + return _CCIPHome.Contract.GetConfigDigests(&_CCIPHome.CallOpts, donId, pluginType) +} + +func (_CCIPHome *CCIPHomeCaller) GetNumChainConfigurations(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "getNumChainConfigurations") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) GetNumChainConfigurations() (*big.Int, error) { + return _CCIPHome.Contract.GetNumChainConfigurations(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCallerSession) GetNumChainConfigurations() (*big.Int, error) { + return _CCIPHome.Contract.GetNumChainConfigurations(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPHome.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 (_CCIPHome *CCIPHomeSession) Owner() (common.Address, error) { + return _CCIPHome.Contract.Owner(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCallerSession) Owner() (common.Address, error) { + return _CCIPHome.Contract.Owner(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _CCIPHome.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 (_CCIPHome *CCIPHomeSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _CCIPHome.Contract.SupportsInterface(&_CCIPHome.CallOpts, interfaceId) +} + +func (_CCIPHome *CCIPHomeCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _CCIPHome.Contract.SupportsInterface(&_CCIPHome.CallOpts, interfaceId) +} + +func (_CCIPHome *CCIPHomeCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CCIPHome.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CCIPHome *CCIPHomeSession) TypeAndVersion() (string, error) { + return _CCIPHome.Contract.TypeAndVersion(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeCallerSession) TypeAndVersion() (string, error) { + return _CCIPHome.Contract.TypeAndVersion(&_CCIPHome.CallOpts) +} + +func (_CCIPHome *CCIPHomeTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "acceptOwnership") +} + +func (_CCIPHome *CCIPHomeSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPHome.Contract.AcceptOwnership(&_CCIPHome.TransactOpts) +} + +func (_CCIPHome *CCIPHomeTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPHome.Contract.AcceptOwnership(&_CCIPHome.TransactOpts) +} + +func (_CCIPHome *CCIPHomeTransactor) ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPHomeChainConfigArgs) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "applyChainConfigUpdates", chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPHome *CCIPHomeSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPHomeChainConfigArgs) (*types.Transaction, error) { + return _CCIPHome.Contract.ApplyChainConfigUpdates(&_CCIPHome.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPHome *CCIPHomeTransactorSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPHomeChainConfigArgs) (*types.Transaction, error) { + return _CCIPHome.Contract.ApplyChainConfigUpdates(&_CCIPHome.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPHome *CCIPHomeTransactor) BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, update []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "beforeCapabilityConfigSet", arg0, update, arg2, donId) +} + +func (_CCIPHome *CCIPHomeSession) BeforeCapabilityConfigSet(arg0 [][32]byte, update []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPHome.Contract.BeforeCapabilityConfigSet(&_CCIPHome.TransactOpts, arg0, update, arg2, donId) +} + +func (_CCIPHome *CCIPHomeTransactorSession) BeforeCapabilityConfigSet(arg0 [][32]byte, update []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPHome.Contract.BeforeCapabilityConfigSet(&_CCIPHome.TransactOpts, arg0, update, arg2, donId) +} + +func (_CCIPHome *CCIPHomeTransactor) PromoteCandidateAndRevokeActive(opts *bind.TransactOpts, donId uint32, pluginType uint8, digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "promoteCandidateAndRevokeActive", donId, pluginType, digestToPromote, digestToRevoke) +} + +func (_CCIPHome *CCIPHomeSession) PromoteCandidateAndRevokeActive(donId uint32, pluginType uint8, digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) { + return _CCIPHome.Contract.PromoteCandidateAndRevokeActive(&_CCIPHome.TransactOpts, donId, pluginType, digestToPromote, digestToRevoke) +} + +func (_CCIPHome *CCIPHomeTransactorSession) PromoteCandidateAndRevokeActive(donId uint32, pluginType uint8, digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) { + return _CCIPHome.Contract.PromoteCandidateAndRevokeActive(&_CCIPHome.TransactOpts, donId, pluginType, digestToPromote, digestToRevoke) +} + +func (_CCIPHome *CCIPHomeTransactor) RevokeCandidate(opts *bind.TransactOpts, donId uint32, pluginType uint8, configDigest [32]byte) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "revokeCandidate", donId, pluginType, configDigest) +} + +func (_CCIPHome *CCIPHomeSession) RevokeCandidate(donId uint32, pluginType uint8, configDigest [32]byte) (*types.Transaction, error) { + return _CCIPHome.Contract.RevokeCandidate(&_CCIPHome.TransactOpts, donId, pluginType, configDigest) +} + +func (_CCIPHome *CCIPHomeTransactorSession) RevokeCandidate(donId uint32, pluginType uint8, configDigest [32]byte) (*types.Transaction, error) { + return _CCIPHome.Contract.RevokeCandidate(&_CCIPHome.TransactOpts, donId, pluginType, configDigest) +} + +func (_CCIPHome *CCIPHomeTransactor) SetCandidate(opts *bind.TransactOpts, donId uint32, pluginType uint8, config CCIPHomeOCR3Config, digestToOverwrite [32]byte) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "setCandidate", donId, pluginType, config, digestToOverwrite) +} + +func (_CCIPHome *CCIPHomeSession) SetCandidate(donId uint32, pluginType uint8, config CCIPHomeOCR3Config, digestToOverwrite [32]byte) (*types.Transaction, error) { + return _CCIPHome.Contract.SetCandidate(&_CCIPHome.TransactOpts, donId, pluginType, config, digestToOverwrite) +} + +func (_CCIPHome *CCIPHomeTransactorSession) SetCandidate(donId uint32, pluginType uint8, config CCIPHomeOCR3Config, digestToOverwrite [32]byte) (*types.Transaction, error) { + return _CCIPHome.Contract.SetCandidate(&_CCIPHome.TransactOpts, donId, pluginType, config, digestToOverwrite) +} + +func (_CCIPHome *CCIPHomeTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CCIPHome.contract.Transact(opts, "transferOwnership", to) +} + +func (_CCIPHome *CCIPHomeSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPHome.Contract.TransferOwnership(&_CCIPHome.TransactOpts, to) +} + +func (_CCIPHome *CCIPHomeTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPHome.Contract.TransferOwnership(&_CCIPHome.TransactOpts, to) +} + +type CCIPHomeActiveConfigRevokedIterator struct { + Event *CCIPHomeActiveConfigRevoked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeActiveConfigRevokedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeActiveConfigRevoked) + 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(CCIPHomeActiveConfigRevoked) + 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 *CCIPHomeActiveConfigRevokedIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeActiveConfigRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeActiveConfigRevoked struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterActiveConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeActiveConfigRevokedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "ActiveConfigRevoked", configDigestRule) + if err != nil { + return nil, err + } + return &CCIPHomeActiveConfigRevokedIterator{contract: _CCIPHome.contract, event: "ActiveConfigRevoked", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchActiveConfigRevoked(opts *bind.WatchOpts, sink chan<- *CCIPHomeActiveConfigRevoked, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.WatchLogs(opts, "ActiveConfigRevoked", 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(CCIPHomeActiveConfigRevoked) + if err := _CCIPHome.contract.UnpackLog(event, "ActiveConfigRevoked", 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 (_CCIPHome *CCIPHomeFilterer) ParseActiveConfigRevoked(log types.Log) (*CCIPHomeActiveConfigRevoked, error) { + event := new(CCIPHomeActiveConfigRevoked) + if err := _CCIPHome.contract.UnpackLog(event, "ActiveConfigRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeCandidateConfigRevokedIterator struct { + Event *CCIPHomeCandidateConfigRevoked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeCandidateConfigRevokedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeCandidateConfigRevoked) + 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(CCIPHomeCandidateConfigRevoked) + 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 *CCIPHomeCandidateConfigRevokedIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeCandidateConfigRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeCandidateConfigRevoked struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterCandidateConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeCandidateConfigRevokedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "CandidateConfigRevoked", configDigestRule) + if err != nil { + return nil, err + } + return &CCIPHomeCandidateConfigRevokedIterator{contract: _CCIPHome.contract, event: "CandidateConfigRevoked", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchCandidateConfigRevoked(opts *bind.WatchOpts, sink chan<- *CCIPHomeCandidateConfigRevoked, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.WatchLogs(opts, "CandidateConfigRevoked", 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(CCIPHomeCandidateConfigRevoked) + if err := _CCIPHome.contract.UnpackLog(event, "CandidateConfigRevoked", 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 (_CCIPHome *CCIPHomeFilterer) ParseCandidateConfigRevoked(log types.Log) (*CCIPHomeCandidateConfigRevoked, error) { + event := new(CCIPHomeCandidateConfigRevoked) + if err := _CCIPHome.contract.UnpackLog(event, "CandidateConfigRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeCapabilityConfigurationSetIterator struct { + Event *CCIPHomeCapabilityConfigurationSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeCapabilityConfigurationSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeCapabilityConfigurationSet) + 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(CCIPHomeCapabilityConfigurationSet) + 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 *CCIPHomeCapabilityConfigurationSetIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeCapabilityConfigurationSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeCapabilityConfigurationSet struct { + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPHomeCapabilityConfigurationSetIterator, error) { + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return &CCIPHomeCapabilityConfigurationSetIterator{contract: _CCIPHome.contract, event: "CapabilityConfigurationSet", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPHomeCapabilityConfigurationSet) (event.Subscription, error) { + + logs, sub, err := _CCIPHome.contract.WatchLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPHomeCapabilityConfigurationSet) + if err := _CCIPHome.contract.UnpackLog(event, "CapabilityConfigurationSet", 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 (_CCIPHome *CCIPHomeFilterer) ParseCapabilityConfigurationSet(log types.Log) (*CCIPHomeCapabilityConfigurationSet, error) { + event := new(CCIPHomeCapabilityConfigurationSet) + if err := _CCIPHome.contract.UnpackLog(event, "CapabilityConfigurationSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeChainConfigRemovedIterator struct { + Event *CCIPHomeChainConfigRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeChainConfigRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeChainConfigRemoved) + 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(CCIPHomeChainConfigRemoved) + 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 *CCIPHomeChainConfigRemovedIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeChainConfigRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeChainConfigRemoved struct { + ChainSelector uint64 + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPHomeChainConfigRemovedIterator, error) { + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return &CCIPHomeChainConfigRemovedIterator{contract: _CCIPHome.contract, event: "ChainConfigRemoved", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPHomeChainConfigRemoved) (event.Subscription, error) { + + logs, sub, err := _CCIPHome.contract.WatchLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPHomeChainConfigRemoved) + if err := _CCIPHome.contract.UnpackLog(event, "ChainConfigRemoved", 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 (_CCIPHome *CCIPHomeFilterer) ParseChainConfigRemoved(log types.Log) (*CCIPHomeChainConfigRemoved, error) { + event := new(CCIPHomeChainConfigRemoved) + if err := _CCIPHome.contract.UnpackLog(event, "ChainConfigRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeChainConfigSetIterator struct { + Event *CCIPHomeChainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeChainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeChainConfigSet) + 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(CCIPHomeChainConfigSet) + 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 *CCIPHomeChainConfigSetIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeChainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeChainConfigSet struct { + ChainSelector uint64 + ChainConfig CCIPHomeChainConfig + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPHomeChainConfigSetIterator, error) { + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return &CCIPHomeChainConfigSetIterator{contract: _CCIPHome.contract, event: "ChainConfigSet", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPHomeChainConfigSet) (event.Subscription, error) { + + logs, sub, err := _CCIPHome.contract.WatchLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPHomeChainConfigSet) + if err := _CCIPHome.contract.UnpackLog(event, "ChainConfigSet", 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 (_CCIPHome *CCIPHomeFilterer) ParseChainConfigSet(log types.Log) (*CCIPHomeChainConfigSet, error) { + event := new(CCIPHomeChainConfigSet) + if err := _CCIPHome.contract.UnpackLog(event, "ChainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeConfigPromotedIterator struct { + Event *CCIPHomeConfigPromoted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeConfigPromotedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeConfigPromoted) + 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(CCIPHomeConfigPromoted) + 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 *CCIPHomeConfigPromotedIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeConfigPromotedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeConfigPromoted struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterConfigPromoted(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeConfigPromotedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "ConfigPromoted", configDigestRule) + if err != nil { + return nil, err + } + return &CCIPHomeConfigPromotedIterator{contract: _CCIPHome.contract, event: "ConfigPromoted", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchConfigPromoted(opts *bind.WatchOpts, sink chan<- *CCIPHomeConfigPromoted, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.WatchLogs(opts, "ConfigPromoted", 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(CCIPHomeConfigPromoted) + if err := _CCIPHome.contract.UnpackLog(event, "ConfigPromoted", 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 (_CCIPHome *CCIPHomeFilterer) ParseConfigPromoted(log types.Log) (*CCIPHomeConfigPromoted, error) { + event := new(CCIPHomeConfigPromoted) + if err := _CCIPHome.contract.UnpackLog(event, "ConfigPromoted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeConfigSetIterator struct { + Event *CCIPHomeConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeConfigSet) + 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(CCIPHomeConfigSet) + 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 *CCIPHomeConfigSetIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeConfigSet struct { + ConfigDigest [32]byte + Version uint32 + Config CCIPHomeOCR3Config + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeConfigSetIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.contract.FilterLogs(opts, "ConfigSet", configDigestRule) + if err != nil { + return nil, err + } + return &CCIPHomeConfigSetIterator{contract: _CCIPHome.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPHomeConfigSet, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _CCIPHome.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(CCIPHomeConfigSet) + if err := _CCIPHome.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 (_CCIPHome *CCIPHomeFilterer) ParseConfigSet(log types.Log) (*CCIPHomeConfigSet, error) { + event := new(CCIPHomeConfigSet) + if err := _CCIPHome.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeOwnershipTransferRequestedIterator struct { + Event *CCIPHomeOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeOwnershipTransferRequested) + 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(CCIPHomeOwnershipTransferRequested) + 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 *CCIPHomeOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPHomeOwnershipTransferRequestedIterator, 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 := _CCIPHome.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPHomeOwnershipTransferRequestedIterator{contract: _CCIPHome.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPHomeOwnershipTransferRequested, 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 := _CCIPHome.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(CCIPHomeOwnershipTransferRequested) + if err := _CCIPHome.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 (_CCIPHome *CCIPHomeFilterer) ParseOwnershipTransferRequested(log types.Log) (*CCIPHomeOwnershipTransferRequested, error) { + event := new(CCIPHomeOwnershipTransferRequested) + if err := _CCIPHome.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPHomeOwnershipTransferredIterator struct { + Event *CCIPHomeOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPHomeOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPHomeOwnershipTransferred) + 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(CCIPHomeOwnershipTransferred) + 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 *CCIPHomeOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CCIPHomeOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPHomeOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPHome *CCIPHomeFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPHomeOwnershipTransferredIterator, 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 := _CCIPHome.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPHomeOwnershipTransferredIterator{contract: _CCIPHome.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CCIPHome *CCIPHomeFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPHomeOwnershipTransferred, 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 := _CCIPHome.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(CCIPHomeOwnershipTransferred) + if err := _CCIPHome.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 (_CCIPHome *CCIPHomeFilterer) ParseOwnershipTransferred(log types.Log) (*CCIPHomeOwnershipTransferred, error) { + event := new(CCIPHomeOwnershipTransferred) + if err := _CCIPHome.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetAllConfigs struct { + ActiveConfig CCIPHomeVersionedConfig + CandidateConfig CCIPHomeVersionedConfig +} +type GetConfig struct { + VersionedConfig CCIPHomeVersionedConfig + Ok bool +} +type GetConfigDigests struct { + ActiveConfigDigest [32]byte + CandidateConfigDigest [32]byte +} + +func (_CCIPHome *CCIPHome) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CCIPHome.abi.Events["ActiveConfigRevoked"].ID: + return _CCIPHome.ParseActiveConfigRevoked(log) + case _CCIPHome.abi.Events["CandidateConfigRevoked"].ID: + return _CCIPHome.ParseCandidateConfigRevoked(log) + case _CCIPHome.abi.Events["CapabilityConfigurationSet"].ID: + return _CCIPHome.ParseCapabilityConfigurationSet(log) + case _CCIPHome.abi.Events["ChainConfigRemoved"].ID: + return _CCIPHome.ParseChainConfigRemoved(log) + case _CCIPHome.abi.Events["ChainConfigSet"].ID: + return _CCIPHome.ParseChainConfigSet(log) + case _CCIPHome.abi.Events["ConfigPromoted"].ID: + return _CCIPHome.ParseConfigPromoted(log) + case _CCIPHome.abi.Events["ConfigSet"].ID: + return _CCIPHome.ParseConfigSet(log) + case _CCIPHome.abi.Events["OwnershipTransferRequested"].ID: + return _CCIPHome.ParseOwnershipTransferRequested(log) + case _CCIPHome.abi.Events["OwnershipTransferred"].ID: + return _CCIPHome.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CCIPHomeActiveConfigRevoked) Topic() common.Hash { + return common.HexToHash("0x0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b8") +} + +func (CCIPHomeCandidateConfigRevoked) Topic() common.Hash { + return common.HexToHash("0x53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b") +} + +func (CCIPHomeCapabilityConfigurationSet) Topic() common.Hash { + return common.HexToHash("0x84ad7751b744c9e2ee77da1d902b428aec7f0a343d67a24bbe2142e6f58a8d0f") +} + +func (CCIPHomeChainConfigRemoved) Topic() common.Hash { + return common.HexToHash("0x2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0") +} + +func (CCIPHomeChainConfigSet) Topic() common.Hash { + return common.HexToHash("0x05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e0") +} + +func (CCIPHomeConfigPromoted) Topic() common.Hash { + return common.HexToHash("0xfc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e") +} + +func (CCIPHomeConfigSet) Topic() common.Hash { + return common.HexToHash("0x94f085b7c57ec2a270befd0b7b2ec7452580040edee8bb0fb04609c81f0359c6") +} + +func (CCIPHomeOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CCIPHomeOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CCIPHome *CCIPHome) Address() common.Address { + return _CCIPHome.address +} + +type CCIPHomeInterface interface { + GetActiveDigest(opts *bind.CallOpts, donId uint32, pluginType uint8) ([32]byte, error) + + GetAllChainConfigs(opts *bind.CallOpts, pageIndex *big.Int, pageSize *big.Int) ([]CCIPHomeChainConfigArgs, error) + + GetAllConfigs(opts *bind.CallOpts, donId uint32, pluginType uint8) (GetAllConfigs, + + error) + + GetCandidateDigest(opts *bind.CallOpts, donId uint32, pluginType uint8) ([32]byte, error) + + GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) + + GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) + + GetConfig(opts *bind.CallOpts, donId uint32, pluginType uint8, configDigest [32]byte) (GetConfig, + + error) + + GetConfigDigests(opts *bind.CallOpts, donId uint32, pluginType uint8) (GetConfigDigests, + + error) + + GetNumChainConfigurations(opts *bind.CallOpts) (*big.Int, 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) + + ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPHomeChainConfigArgs) (*types.Transaction, error) + + BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, update []byte, arg2 uint64, donId uint32) (*types.Transaction, error) + + PromoteCandidateAndRevokeActive(opts *bind.TransactOpts, donId uint32, pluginType uint8, digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) + + RevokeCandidate(opts *bind.TransactOpts, donId uint32, pluginType uint8, configDigest [32]byte) (*types.Transaction, error) + + SetCandidate(opts *bind.TransactOpts, donId uint32, pluginType uint8, config CCIPHomeOCR3Config, digestToOverwrite [32]byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterActiveConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeActiveConfigRevokedIterator, error) + + WatchActiveConfigRevoked(opts *bind.WatchOpts, sink chan<- *CCIPHomeActiveConfigRevoked, configDigest [][32]byte) (event.Subscription, error) + + ParseActiveConfigRevoked(log types.Log) (*CCIPHomeActiveConfigRevoked, error) + + FilterCandidateConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeCandidateConfigRevokedIterator, error) + + WatchCandidateConfigRevoked(opts *bind.WatchOpts, sink chan<- *CCIPHomeCandidateConfigRevoked, configDigest [][32]byte) (event.Subscription, error) + + ParseCandidateConfigRevoked(log types.Log) (*CCIPHomeCandidateConfigRevoked, error) + + FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPHomeCapabilityConfigurationSetIterator, error) + + WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPHomeCapabilityConfigurationSet) (event.Subscription, error) + + ParseCapabilityConfigurationSet(log types.Log) (*CCIPHomeCapabilityConfigurationSet, error) + + FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPHomeChainConfigRemovedIterator, error) + + WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPHomeChainConfigRemoved) (event.Subscription, error) + + ParseChainConfigRemoved(log types.Log) (*CCIPHomeChainConfigRemoved, error) + + FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPHomeChainConfigSetIterator, error) + + WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPHomeChainConfigSet) (event.Subscription, error) + + ParseChainConfigSet(log types.Log) (*CCIPHomeChainConfigSet, error) + + FilterConfigPromoted(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeConfigPromotedIterator, error) + + WatchConfigPromoted(opts *bind.WatchOpts, sink chan<- *CCIPHomeConfigPromoted, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigPromoted(log types.Log) (*CCIPHomeConfigPromoted, error) + + FilterConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*CCIPHomeConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPHomeConfigSet, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*CCIPHomeConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPHomeOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPHomeOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CCIPHomeOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPHomeOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPHomeOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CCIPHomeOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} 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 fdef1385280..c5c451a3e8a 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 @@ -30,26 +30,9 @@ var ( _ = abi.ConvertType ) -type EVM2EVMMultiOffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []EVM2EVMMultiOffRampMerkleRoot -} - -type EVM2EVMMultiOffRampInterval struct { - Min uint64 - Max uint64 -} - -type EVM2EVMMultiOffRampMerkleRoot struct { - SourceChainSelector uint64 - Interval EVM2EVMMultiOffRampInterval - MerkleRoot [32]byte -} - -type EVM2EVMMultiOffRampSourceChainConfig struct { - IsEnabled bool - MinSeqNr uint64 - OnRamp []byte +type IRMNRemoteSignature struct { + R [32]byte + S [32]byte } type InternalEVM2AnyRampMessage struct { @@ -60,7 +43,16 @@ type InternalEVM2AnyRampMessage struct { ExtraArgs []byte FeeToken common.Address FeeTokenAmount *big.Int - TokenAmounts []InternalRampTokenAmount + FeeValueJuels *big.Int + TokenAmounts []InternalEVM2AnyTokenTransfer +} + +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte } type InternalGasPriceUpdate struct { @@ -68,6 +60,14 @@ type InternalGasPriceUpdate struct { UsdPerUnitGas *big.Int } +type InternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + type InternalPriceUpdates struct { TokenPriceUpdates []InternalTokenPriceUpdate GasPriceUpdates []InternalGasPriceUpdate @@ -81,21 +81,28 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int -} - type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int } +type OffRampCommitReport struct { + PriceUpdates InternalPriceUpdates + MerkleRoots []InternalMerkleRoot + RmnSignatures []IRMNRemoteSignature + RmnRawVs *big.Int +} + +type OffRampSourceChainConfig struct { + Router common.Address + IsEnabled bool + MinSeqNr uint64 + OnRamp []byte +} + var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"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\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"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\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.CommitReport\",\"name\":\"report\",\"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\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"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\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"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\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506110cc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80634cf66e361461005c578063a65558f614610071578063e44302b714610084578063e9d68a8e14610097578063f831af81146100c0575b600080fd5b61006f61006a366004610462565b6100d3565b005b61006f61007f3660046106c7565b610128565b61006f610092366004610965565b61016d565b6100aa6100a5366004610acd565b6101a7565b6040516100b79190610b35565b60405180910390f35b61006f6100ce366004610b76565b610297565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610119929190610c1e565b60405180910390a45050505050565b816001600160401b03167f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29826040516101619190610d06565b60405180910390a25050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161019c9190610ec0565b60405180910390a150565b6040805160608082018352600080835260208084018290528385018390526001600160401b0386811683528282529185902085519384018652805460ff81161515855261010090049092169083015260018101805493949293919284019161020e90610f75565b80601f016020809104026020016040519081016040528092919081815260200182805461023a90610f75565b80156102875780601f1061025c57610100808354040283529160200191610287565b820191906000526020600020905b81548152906001019060200180831161026a57829003601f168201915b5050505050815250509050919050565b6001600160401b038281166000908152602081815260409182902084518154928601516001600160481b0319909316901515610100600160481b03191617610100929094169190910292909217825582015182919060018201906102fb9082611000565b5050505050565b80356001600160401b038116811461031957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156103565761035661031e565b60405290565b60405161010081016001600160401b03811182821017156103565761035661031e565b604080519081016001600160401b03811182821017156103565761035661031e565b604051606081016001600160401b03811182821017156103565761035661031e565b604051601f8201601f191681016001600160401b03811182821017156103eb576103eb61031e565b604052919050565b600082601f83011261040457600080fd5b81356001600160401b0381111561041d5761041d61031e565b610430601f8201601f19166020016103c3565b81815284602083860101111561044557600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561047a57600080fd5b61048386610302565b945061049160208701610302565b9350604086013592506060860135600481106104ac57600080fd5b915060808601356001600160401b038111156104c757600080fd5b6104d3888289016103f3565b9150509295509295909350565b600060a082840312156104f257600080fd5b60405160a081016001600160401b03811182821017156105145761051461031e565b6040528235815290508061052a60208401610302565b602082015261053b60408401610302565b604082015261054c60608401610302565b606082015261055d60808401610302565b60808201525092915050565b80356001600160a01b038116811461031957600080fd5b60006001600160401b038211156105995761059961031e565b5060051b60200190565b600082601f8301126105b457600080fd5b813560206105c96105c483610580565b6103c3565b82815260059290921b840181019181810190868411156105e857600080fd5b8286015b848110156106bc5780356001600160401b038082111561060c5760008081fd5b908801906080828b03601f19018113156106265760008081fd5b61062e610334565b87840135838111156106405760008081fd5b61064e8d8a838801016103f3565b825250604080850135848111156106655760008081fd5b6106738e8b838901016103f3565b8a840152506060808601358581111561068c5760008081fd5b61069a8f8c838a01016103f3565b92840192909252949092013593810193909352505083529183019183016105ec565b509695505050505050565b600080604083850312156106da57600080fd5b6106e383610302565b915060208301356001600160401b03808211156106ff57600080fd5b90840190610180828703121561071457600080fd5b61071c61035c565b61072687846104e0565b815261073460a08401610569565b602082015260c08301358281111561074b57600080fd5b610757888286016103f3565b60408301525060e08301358281111561076f57600080fd5b61077b888286016103f3565b6060830152506101008301358281111561079457600080fd5b6107a0888286016103f3565b6080830152506107b36101208401610569565b60a082015261014083013560c0820152610160830135828111156107d657600080fd5b6107e2888286016105a3565b60e0830152508093505050509250929050565b80356001600160e01b038116811461031957600080fd5b600082601f83011261081d57600080fd5b8135602061082d6105c483610580565b82815260069290921b8401810191818101908684111561084c57600080fd5b8286015b848110156106bc57604081890312156108695760008081fd5b61087161037f565b61087a82610302565b81526108878583016107f5565b81860152835291830191604001610850565b600082601f8301126108aa57600080fd5b813560206108ba6105c483610580565b82815260079290921b840181019181810190868411156108d957600080fd5b8286015b848110156106bc5780880360808112156108f75760008081fd5b6108ff6103a1565b61090883610302565b8152604080601f198401121561091e5760008081fd5b61092661037f565b9250610933878501610302565b8352610940818501610302565b83880152818701929092526060830135918101919091528352918301916080016108dd565b6000602080838503121561097857600080fd5b82356001600160401b038082111561098f57600080fd5b818501915060408083880312156109a557600080fd5b6109ad61037f565b8335838111156109bc57600080fd5b84016040818a0312156109ce57600080fd5b6109d661037f565b8135858111156109e557600080fd5b8201601f81018b136109f657600080fd5b8035610a046105c482610580565b81815260069190911b8201890190898101908d831115610a2357600080fd5b928a01925b82841015610a715787848f031215610a405760008081fd5b610a4861037f565b610a5185610569565b8152610a5e8c86016107f5565b818d0152825292870192908a0190610a28565b845250505081870135935084841115610a8957600080fd5b610a958a85840161080c565b8188015282525083850135915082821115610aaf57600080fd5b610abb88838601610899565b85820152809550505050505092915050565b600060208284031215610adf57600080fd5b610ae882610302565b9392505050565b6000815180845260005b81811015610b1557602081850181015186830182015201610af9565b506000602082860101526020601f19601f83011685010191505092915050565b6020815281511515602082015260018060401b03602083015116604082015260006040830151606080840152610b6e6080840182610aef565b949350505050565b60008060408385031215610b8957600080fd5b610b9283610302565b915060208301356001600160401b0380821115610bae57600080fd5b9084019060608287031215610bc257600080fd5b610bca6103a1565b82358015158114610bda57600080fd5b8152610be860208401610302565b6020820152604083013582811115610bff57600080fd5b610c0b888286016103f3565b6040830152508093505050509250929050565b600060048410610c3e57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610b6e6040830184610aef565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610cf957601f19868403018952815160808151818652610ca582870182610aef565b9150508582015185820387870152610cbd8282610aef565b91505060408083015186830382880152610cd78382610aef565b6060948501519790940196909652505098840198925090830190600101610c7f565b5090979650505050505050565b60208152610d53602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610d6760c0840182610c55565b5060408301516101808060e0850152610d846101a0850183610aef565b91506060850151601f198086850301610100870152610da38483610aef565b9350608087015191508086850301610120870152610dc18483610aef565b935060a08701519150610dd8610140870183610c55565b60c087015161016087015260e0870151915080868503018387015250610dfe8382610c62565b9695505050505050565b60008151808452602080850194506020840160005b83811015610e5657815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e1d565b509495945050505050565b600081518084526020808501945080840160005b83811015610e5657815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101610e75565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610f2e57835180516001600160a01b031683528701516001600160e01b031687830152928601926001929092019190840190610ef3565b5093850151878503605f1901608089015293610f4a8186610e08565b945050505050818501519150601f19848203016040850152610f6c8183610e61565b95945050505050565b600181811c90821680610f8957607f821691505b602082108103610fa957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610ffb576000816000526020600020601f850160051c81016020861015610fd85750805b601f850160051c820191505b81811015610ff757828155600101610fe4565b5050505b505050565b81516001600160401b038111156110195761101961031e565b61102d816110278454610f75565b84610faf565b602080601f831160018114611062576000841561104a5750858301515b600019600386901b1c1916600185901b178555610ff7565b600085815260208120601f198616915b8281101561109157888601518255948401946001909101908401611072565b50858210156110af5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + 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\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"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\":[{\"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\":\"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: "0x608060405234801561001057600080fd5b506118cd806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063c1a5a35511610076578063c92236251161005b578063c92236251461017c578063e83eabba1461018f578063e9d68a8e146101a257600080fd5b8063c1a5a35514610114578063c7c1cba11461016957600080fd5b8063198b821c146100a85780634bf78697146100bd5780639041be3d146100d057806393df286714610101575b600080fd5b6100bb6100b6366004610a4d565b6101c2565b005b6100bb6100cb366004610d93565b610204565b6100e36100de366004610ece565b61025d565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6100bb61010f366004610f39565b61028d565b6100bb610122366004610f9a565b67ffffffffffffffff918216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b6100bb610177366004610fcd565b610308565b6100e361018a36600461105f565b610365565b6100bb61019d3660046110b2565b6103b1565b6101b56101b0366004610ece565b61049b565b6040516100f891906111d2565b602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926101f9929091611329565b60405180910390a150565b80600001516060015167ffffffffffffffff168267ffffffffffffffff167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f328360405161025191906114e4565b60405180910390a35050565b67ffffffffffffffff8082166000908152600160208190526040822054919261028792169061163c565b92915050565b67ffffffffffffffff84166000908152600260205260409081902090518491906102ba908590859061168b565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550505050565b848667ffffffffffffffff168867ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b87878787604051610354949392919061169b565b60405180910390a450505050505050565b67ffffffffffffffff8316600090815260026020526040808220905161038e908590859061168b565b9081526040519081900360200190205467ffffffffffffffff1690509392505050565b67ffffffffffffffff808316600090815260208181526040918290208451815492860151938601519094167501000000000000000000000000000000000000000000027fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff93151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090931673ffffffffffffffffffffffffffffffffffffffff9095169490941791909117919091169190911781556060820151829190600182019061049490826117a6565b5050505050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff87811684528383529286902086519485018752805473ffffffffffffffffffffffffffffffffffffffff8116865274010000000000000000000000000000000000000000810460ff16151593860193909352750100000000000000000000000000000000000000000090920490921694830194909452600184018054939492939184019161055790611702565b80601f016020809104026020016040519081016040528092919081815260200182805461058390611702565b80156105d05780601f106105a5576101008083540402835291602001916105d0565b820191906000526020600020905b8154815290600101906020018083116105b357829003601f168201915b5050505050815250509050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610632576106326105e0565b60405290565b60405160a0810167ffffffffffffffff81118282101715610632576106326105e0565b6040516080810167ffffffffffffffff81118282101715610632576106326105e0565b604051610120810167ffffffffffffffff81118282101715610632576106326105e0565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156106e9576106e96105e0565b604052919050565b600067ffffffffffffffff82111561070b5761070b6105e0565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461073757600080fd5b50565b803561074581610715565b919050565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461074557600080fd5b803567ffffffffffffffff8116811461074557600080fd5b600082601f83011261079f57600080fd5b813560206107b46107af836106f1565b6106a2565b82815260069290921b840181019181810190868411156107d357600080fd5b8286015b8481101561082057604081890312156107f05760008081fd5b6107f861060f565b61080182610776565b815261080e85830161074a565b818601528352918301916040016107d7565b509695505050505050565b600082601f83011261083c57600080fd5b813567ffffffffffffffff811115610856576108566105e0565b61088760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016106a2565b81815284602083860101111561089c57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126108ca57600080fd5b813560206108da6107af836106f1565b82815260059290921b840181019181810190868411156108f957600080fd5b8286015b8481101561082057803567ffffffffffffffff8082111561091e5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156109575760008081fd5b61095f610638565b61096a888501610776565b8152604080850135848111156109805760008081fd5b61098e8e8b8389010161082b565b8a84015250606093506109a2848601610776565b9082015260806109b3858201610776565b938201939093529201359082015283529183019183016108fd565b600082601f8301126109df57600080fd5b813560206109ef6107af836106f1565b82815260069290921b84018101918181019086841115610a0e57600080fd5b8286015b848110156108205760408189031215610a2b5760008081fd5b610a3361060f565b813581528482013585820152835291830191604001610a12565b60006020808385031215610a6057600080fd5b823567ffffffffffffffff80821115610a7857600080fd5b9084019060808287031215610a8c57600080fd5b610a9461065b565b823582811115610aa357600080fd5b83016040818903811315610ab657600080fd5b610abe61060f565b823585811115610acd57600080fd5b8301601f81018b13610ade57600080fd5b8035610aec6107af826106f1565b81815260069190911b8201890190898101908d831115610b0b57600080fd5b928a01925b82841015610b5b5785848f031215610b285760008081fd5b610b3061060f565b8435610b3b81610715565b8152610b48858d0161074a565b818d0152825292850192908a0190610b10565b845250505082870135915084821115610b7357600080fd5b610b7f8a83850161078e565b81880152835250508284013582811115610b9857600080fd5b610ba4888286016108b9565b85830152506040830135935081841115610bbd57600080fd5b610bc9878585016109ce565b6040820152606083013560608201528094505050505092915050565b600060a08284031215610bf757600080fd5b610bff610638565b905081358152610c1160208301610776565b6020820152610c2260408301610776565b6040820152610c3360608301610776565b6060820152610c4460808301610776565b608082015292915050565b600082601f830112610c6057600080fd5b81356020610c706107af836106f1565b82815260059290921b84018101918181019086841115610c8f57600080fd5b8286015b8481101561082057803567ffffffffffffffff80821115610cb45760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610ced5760008081fd5b610cf5610638565b610d0088850161073a565b815260408085013584811115610d165760008081fd5b610d248e8b8389010161082b565b8a8401525060608086013585811115610d3d5760008081fd5b610d4b8f8c838a010161082b565b83850152506080915081860135818401525082850135925083831115610d715760008081fd5b610d7f8d8a8588010161082b565b908201528652505050918301918301610c93565b60008060408385031215610da657600080fd5b610daf83610776565b9150602083013567ffffffffffffffff80821115610dcc57600080fd5b908401906101a08287031215610de157600080fd5b610de961067e565b610df38784610be5565b8152610e0160a0840161073a565b602082015260c083013582811115610e1857600080fd5b610e248882860161082b565b60408301525060e083013582811115610e3c57600080fd5b610e488882860161082b565b6060830152506101008084013583811115610e6257600080fd5b610e6e8982870161082b565b608084015250610e81610120850161073a565b60a083015261014084013560c083015261016084013560e083015261018084013583811115610eaf57600080fd5b610ebb89828701610c4f565b8284015250508093505050509250929050565b600060208284031215610ee057600080fd5b610ee982610776565b9392505050565b60008083601f840112610f0257600080fd5b50813567ffffffffffffffff811115610f1a57600080fd5b602083019150836020828501011115610f3257600080fd5b9250929050565b60008060008060608587031215610f4f57600080fd5b610f5885610776565b9350610f6660208601610776565b9250604085013567ffffffffffffffff811115610f8257600080fd5b610f8e87828801610ef0565b95989497509550505050565b60008060408385031215610fad57600080fd5b610fb683610776565b9150610fc460208401610776565b90509250929050565b600080600080600080600060e0888a031215610fe857600080fd5b610ff188610776565b9650610fff60208901610776565b9550604088013594506060880135935060808801356004811061102157600080fd5b925060a088013567ffffffffffffffff81111561103d57600080fd5b6110498a828b0161082b565b92505060c0880135905092959891949750929550565b60008060006040848603121561107457600080fd5b61107d84610776565b9250602084013567ffffffffffffffff81111561109957600080fd5b6110a586828701610ef0565b9497909650939450505050565b600080604083850312156110c557600080fd5b6110ce83610776565b9150602083013567ffffffffffffffff808211156110eb57600080fd5b90840190608082870312156110ff57600080fd5b61110761065b565b823561111281610715565b81526020830135801515811461112757600080fd5b602082015261113860408401610776565b604082015260608301358281111561114f57600080fd5b61115b8882860161082b565b6060830152508093505050509250929050565b6000815180845260005b8181101561119457602081850181015186830182015201611178565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261122d60a084018261116e565b949350505050565b805160408084528151848201819052600092602091908201906060870190855b818110156112ae578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101611255565b50508583015187820388850152805180835290840192506000918401905b8083101561131d578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906112cc565b50979650505050505050565b60006040808301604084528086518083526060925060608601915060608160051b8701016020808a0160005b848110156113e1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652815160a067ffffffffffffffff8083511687528583015182878901526113ac8389018261116e565b848d01518316898e01528b8501519092168b890152506080928301519290960191909152509482019490820190600101611355565b5050878203908801526113f48189611235565b9998505050505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156114d7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526114808287018261116e565b9150506040808301518683038288015261149a838261116e565b925050506060808301518187015250608080830151925085820381870152506114c3818361116e565b9a86019a945050509083019060010161141e565b5090979650505050505050565b6020815261153560208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161155e60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e085015261157b6101c085018361116e565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526115b9858461116e565b94506080880151925081878603016101208801526115d7858461116e565b945060a0880151925061160361014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e08801516101808801528701518685039091018387015290506116328382611401565b9695505050505050565b67ffffffffffffffff818116838216019080821115611684577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b8183823760009101908152919050565b8481526000600485106116d7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b846020830152608060408301526116f1608083018561116e565b905082606083015295945050505050565b600181811c9082168061171657607f821691505b60208210810361174f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156117a1576000816000526020600020601f850160051c8101602086101561177e5750805b601f850160051c820191505b8181101561179d5782815560010161178a565b5050505b505050565b815167ffffffffffffffff8111156117c0576117c06105e0565b6117d4816117ce8454611702565b84611755565b602080601f83116001811461182757600084156117f15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561179d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561187457888601518255948401946001909101908401611855565b50858210156118b057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -234,78 +241,146 @@ func (_CCIPReaderTester *CCIPReaderTesterTransactorRaw) Transact(opts *bind.Tran return _CCIPReaderTester.Contract.contract.Transact(opts, method, params...) } -func (_CCIPReaderTester *CCIPReaderTesterCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { +func (_CCIPReaderTester *CCIPReaderTesterCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) { + var out []interface{} + err := _CCIPReaderTester.contract.Call(opts, &out, "getExpectedNextSequenceNumber", destChainSelector) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { + return _CCIPReaderTester.Contract.GetExpectedNextSequenceNumber(&_CCIPReaderTester.CallOpts, destChainSelector) +} + +func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { + return _CCIPReaderTester.Contract.GetExpectedNextSequenceNumber(&_CCIPReaderTester.CallOpts, destChainSelector) +} + +func (_CCIPReaderTester *CCIPReaderTesterCaller) GetInboundNonce(opts *bind.CallOpts, sourceChainSelector uint64, sender []byte) (uint64, error) { + var out []interface{} + err := _CCIPReaderTester.contract.Call(opts, &out, "getInboundNonce", sourceChainSelector, sender) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) GetInboundNonce(sourceChainSelector uint64, sender []byte) (uint64, error) { + return _CCIPReaderTester.Contract.GetInboundNonce(&_CCIPReaderTester.CallOpts, sourceChainSelector, sender) +} + +func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetInboundNonce(sourceChainSelector uint64, sender []byte) (uint64, error) { + return _CCIPReaderTester.Contract.GetInboundNonce(&_CCIPReaderTester.CallOpts, sourceChainSelector, sender) +} + +func (_CCIPReaderTester *CCIPReaderTesterCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) { var out []interface{} err := _CCIPReaderTester.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) if err != nil { - return *new(EVM2EVMMultiOffRampSourceChainConfig), err + return *new(OffRampSourceChainConfig), err } - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOffRampSourceChainConfig)).(*EVM2EVMMultiOffRampSourceChainConfig) + out0 := *abi.ConvertType(out[0], new(OffRampSourceChainConfig)).(*OffRampSourceChainConfig) return out0, err } -func (_CCIPReaderTester *CCIPReaderTesterSession) GetSourceChainConfig(sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { +func (_CCIPReaderTester *CCIPReaderTesterSession) GetSourceChainConfig(sourceChainSelector uint64) (OffRampSourceChainConfig, error) { return _CCIPReaderTester.Contract.GetSourceChainConfig(&_CCIPReaderTester.CallOpts, sourceChainSelector) } -func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetSourceChainConfig(sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { +func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetSourceChainConfig(sourceChainSelector uint64) (OffRampSourceChainConfig, error) { return _CCIPReaderTester.Contract.GetSourceChainConfig(&_CCIPReaderTester.CallOpts, sourceChainSelector) } -func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitCCIPSendRequested(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { - return _CCIPReaderTester.contract.Transact(opts, "emitCCIPSendRequested", destChainSelector, message) +func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitCCIPMessageSent(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "emitCCIPMessageSent", destChainSelector, message) } -func (_CCIPReaderTester *CCIPReaderTesterSession) EmitCCIPSendRequested(destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { - return _CCIPReaderTester.Contract.EmitCCIPSendRequested(&_CCIPReaderTester.TransactOpts, destChainSelector, message) +func (_CCIPReaderTester *CCIPReaderTesterSession) EmitCCIPMessageSent(destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitCCIPMessageSent(&_CCIPReaderTester.TransactOpts, destChainSelector, message) } -func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitCCIPSendRequested(destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { - return _CCIPReaderTester.Contract.EmitCCIPSendRequested(&_CCIPReaderTester.TransactOpts, destChainSelector, message) +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitCCIPMessageSent(destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitCCIPMessageSent(&_CCIPReaderTester.TransactOpts, destChainSelector, message) } -func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitCommitReportAccepted(opts *bind.TransactOpts, report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) { +func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitCommitReportAccepted(opts *bind.TransactOpts, report OffRampCommitReport) (*types.Transaction, error) { return _CCIPReaderTester.contract.Transact(opts, "emitCommitReportAccepted", report) } -func (_CCIPReaderTester *CCIPReaderTesterSession) EmitCommitReportAccepted(report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) { +func (_CCIPReaderTester *CCIPReaderTesterSession) EmitCommitReportAccepted(report OffRampCommitReport) (*types.Transaction, error) { return _CCIPReaderTester.Contract.EmitCommitReportAccepted(&_CCIPReaderTester.TransactOpts, report) } -func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitCommitReportAccepted(report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) { +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitCommitReportAccepted(report OffRampCommitReport) (*types.Transaction, error) { return _CCIPReaderTester.Contract.EmitCommitReportAccepted(&_CCIPReaderTester.TransactOpts, report) } -func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) { - return _CCIPReaderTester.contract.Transact(opts, "emitExecutionStateChanged", sourceChainSelector, sequenceNumber, messageId, state, returnData) +func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, messageHash [32]byte, state uint8, returnData []byte, gasUsed *big.Int) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "emitExecutionStateChanged", sourceChainSelector, sequenceNumber, messageId, messageHash, state, returnData, gasUsed) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) EmitExecutionStateChanged(sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, messageHash [32]byte, state uint8, returnData []byte, gasUsed *big.Int) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, messageHash, state, returnData, gasUsed) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitExecutionStateChanged(sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, messageHash [32]byte, state uint8, returnData []byte, gasUsed *big.Int) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, messageHash, state, returnData, gasUsed) } -func (_CCIPReaderTester *CCIPReaderTesterSession) EmitExecutionStateChanged(sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) { - return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, state, returnData) +func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetDestChainSeqNr(opts *bind.TransactOpts, destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "setDestChainSeqNr", destChainSelector, sequenceNumber) } -func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitExecutionStateChanged(sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) { - return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, state, returnData) +func (_CCIPReaderTester *CCIPReaderTesterSession) SetDestChainSeqNr(destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetDestChainSeqNr(&_CCIPReaderTester.TransactOpts, destChainSelector, sequenceNumber) } -func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) { +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetDestChainSeqNr(destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetDestChainSeqNr(&_CCIPReaderTester.TransactOpts, destChainSelector, sequenceNumber) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetInboundNonce(opts *bind.TransactOpts, sourceChainSelector uint64, testNonce uint64, sender []byte) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "setInboundNonce", sourceChainSelector, testNonce, sender) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) SetInboundNonce(sourceChainSelector uint64, testNonce uint64, sender []byte) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetInboundNonce(&_CCIPReaderTester.TransactOpts, sourceChainSelector, testNonce, sender) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetInboundNonce(sourceChainSelector uint64, testNonce uint64, sender []byte) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetInboundNonce(&_CCIPReaderTester.TransactOpts, sourceChainSelector, testNonce, sender) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) { return _CCIPReaderTester.contract.Transact(opts, "setSourceChainConfig", sourceChainSelector, sourceChainConfig) } -func (_CCIPReaderTester *CCIPReaderTesterSession) SetSourceChainConfig(sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) { +func (_CCIPReaderTester *CCIPReaderTesterSession) SetSourceChainConfig(sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) { return _CCIPReaderTester.Contract.SetSourceChainConfig(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sourceChainConfig) } -func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetSourceChainConfig(sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) { +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetSourceChainConfig(sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) { return _CCIPReaderTester.Contract.SetSourceChainConfig(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sourceChainConfig) } -type CCIPReaderTesterCCIPSendRequestedIterator struct { - Event *CCIPReaderTesterCCIPSendRequested +type CCIPReaderTesterCCIPMessageSentIterator struct { + Event *CCIPReaderTesterCCIPMessageSent contract *bind.BoundContract event string @@ -316,7 +391,7 @@ type CCIPReaderTesterCCIPSendRequestedIterator struct { fail error } -func (it *CCIPReaderTesterCCIPSendRequestedIterator) Next() bool { +func (it *CCIPReaderTesterCCIPMessageSentIterator) Next() bool { if it.fail != nil { return false @@ -325,7 +400,7 @@ func (it *CCIPReaderTesterCCIPSendRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(CCIPReaderTesterCCIPSendRequested) + it.Event = new(CCIPReaderTesterCCIPMessageSent) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -340,7 +415,7 @@ func (it *CCIPReaderTesterCCIPSendRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(CCIPReaderTesterCCIPSendRequested) + it.Event = new(CCIPReaderTesterCCIPMessageSent) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -355,43 +430,52 @@ func (it *CCIPReaderTesterCCIPSendRequestedIterator) Next() bool { } } -func (it *CCIPReaderTesterCCIPSendRequestedIterator) Error() error { +func (it *CCIPReaderTesterCCIPMessageSentIterator) Error() error { return it.fail } -func (it *CCIPReaderTesterCCIPSendRequestedIterator) Close() error { +func (it *CCIPReaderTesterCCIPMessageSentIterator) Close() error { it.sub.Unsubscribe() return nil } -type CCIPReaderTesterCCIPSendRequested struct { +type CCIPReaderTesterCCIPMessageSent struct { DestChainSelector uint64 + SequenceNumber uint64 Message InternalEVM2AnyRampMessage Raw types.Log } -func (_CCIPReaderTester *CCIPReaderTesterFilterer) FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*CCIPReaderTesterCCIPSendRequestedIterator, error) { +func (_CCIPReaderTester *CCIPReaderTesterFilterer) FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64, sequenceNumber []uint64) (*CCIPReaderTesterCCIPMessageSentIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } - logs, sub, err := _CCIPReaderTester.contract.FilterLogs(opts, "CCIPSendRequested", destChainSelectorRule) + logs, sub, err := _CCIPReaderTester.contract.FilterLogs(opts, "CCIPMessageSent", destChainSelectorRule, sequenceNumberRule) if err != nil { return nil, err } - return &CCIPReaderTesterCCIPSendRequestedIterator{contract: _CCIPReaderTester.contract, event: "CCIPSendRequested", logs: logs, sub: sub}, nil + return &CCIPReaderTesterCCIPMessageSentIterator{contract: _CCIPReaderTester.contract, event: "CCIPMessageSent", logs: logs, sub: sub}, nil } -func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) { +func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchCCIPMessageSent(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCCIPMessageSent, destChainSelector []uint64, sequenceNumber []uint64) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } - logs, sub, err := _CCIPReaderTester.contract.WatchLogs(opts, "CCIPSendRequested", destChainSelectorRule) + logs, sub, err := _CCIPReaderTester.contract.WatchLogs(opts, "CCIPMessageSent", destChainSelectorRule, sequenceNumberRule) if err != nil { return nil, err } @@ -401,8 +485,8 @@ func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchCCIPSendRequested(opts * select { case log := <-logs: - event := new(CCIPReaderTesterCCIPSendRequested) - if err := _CCIPReaderTester.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { + event := new(CCIPReaderTesterCCIPMessageSent) + if err := _CCIPReaderTester.contract.UnpackLog(event, "CCIPMessageSent", log); err != nil { return err } event.Raw = log @@ -423,9 +507,9 @@ func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchCCIPSendRequested(opts * }), nil } -func (_CCIPReaderTester *CCIPReaderTesterFilterer) ParseCCIPSendRequested(log types.Log) (*CCIPReaderTesterCCIPSendRequested, error) { - event := new(CCIPReaderTesterCCIPSendRequested) - if err := _CCIPReaderTester.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { +func (_CCIPReaderTester *CCIPReaderTesterFilterer) ParseCCIPMessageSent(log types.Log) (*CCIPReaderTesterCCIPMessageSent, error) { + event := new(CCIPReaderTesterCCIPMessageSent) + if err := _CCIPReaderTester.contract.UnpackLog(event, "CCIPMessageSent", log); err != nil { return nil, err } event.Raw = log @@ -493,8 +577,9 @@ func (it *CCIPReaderTesterCommitReportAcceptedIterator) Close() error { } type CCIPReaderTesterCommitReportAccepted struct { - Report EVM2EVMMultiOffRampCommitReport - Raw types.Log + MerkleRoots []InternalMerkleRoot + PriceUpdates InternalPriceUpdates + Raw types.Log } func (_CCIPReaderTester *CCIPReaderTesterFilterer) FilterCommitReportAccepted(opts *bind.FilterOpts) (*CCIPReaderTesterCommitReportAcceptedIterator, error) { @@ -613,8 +698,10 @@ type CCIPReaderTesterExecutionStateChanged struct { SourceChainSelector uint64 SequenceNumber uint64 MessageId [32]byte + MessageHash [32]byte State uint8 ReturnData []byte + GasUsed *big.Int Raw types.Log } @@ -698,8 +785,8 @@ func (_CCIPReaderTester *CCIPReaderTesterFilterer) ParseExecutionStateChanged(lo func (_CCIPReaderTester *CCIPReaderTester) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _CCIPReaderTester.abi.Events["CCIPSendRequested"].ID: - return _CCIPReaderTester.ParseCCIPSendRequested(log) + case _CCIPReaderTester.abi.Events["CCIPMessageSent"].ID: + return _CCIPReaderTester.ParseCCIPMessageSent(log) case _CCIPReaderTester.abi.Events["CommitReportAccepted"].ID: return _CCIPReaderTester.ParseCommitReportAccepted(log) case _CCIPReaderTester.abi.Events["ExecutionStateChanged"].ID: @@ -710,16 +797,16 @@ func (_CCIPReaderTester *CCIPReaderTester) ParseLog(log types.Log) (generated.Ab } } -func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0x0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29") +func (CCIPReaderTesterCCIPMessageSent) Topic() common.Hash { + return common.HexToHash("0x192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f32") } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0x3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d") + return common.HexToHash("0x35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4") } func (CCIPReaderTesterExecutionStateChanged) Topic() common.Hash { - return common.HexToHash("0x8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df2") + return common.HexToHash("0x05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b") } func (_CCIPReaderTester *CCIPReaderTester) Address() common.Address { @@ -727,21 +814,29 @@ func (_CCIPReaderTester *CCIPReaderTester) Address() common.Address { } type CCIPReaderTesterInterface interface { - GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) + GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) + + GetInboundNonce(opts *bind.CallOpts, sourceChainSelector uint64, sender []byte) (uint64, error) + + GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) + + EmitCCIPMessageSent(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) + + EmitCommitReportAccepted(opts *bind.TransactOpts, report OffRampCommitReport) (*types.Transaction, error) - EmitCCIPSendRequested(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) + EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, messageHash [32]byte, state uint8, returnData []byte, gasUsed *big.Int) (*types.Transaction, error) - EmitCommitReportAccepted(opts *bind.TransactOpts, report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) + SetDestChainSeqNr(opts *bind.TransactOpts, destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) - EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) + SetInboundNonce(opts *bind.TransactOpts, sourceChainSelector uint64, testNonce uint64, sender []byte) (*types.Transaction, error) - SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) + SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) - FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*CCIPReaderTesterCCIPSendRequestedIterator, error) + FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64, sequenceNumber []uint64) (*CCIPReaderTesterCCIPMessageSentIterator, error) - WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) + WatchCCIPMessageSent(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCCIPMessageSent, destChainSelector []uint64, sequenceNumber []uint64) (event.Subscription, error) - ParseCCIPSendRequested(log types.Log) (*CCIPReaderTesterCCIPSendRequested, error) + ParseCCIPMessageSent(log types.Log) (*CCIPReaderTesterCCIPMessageSent, error) FilterCommitReportAccepted(opts *bind.FilterOpts) (*CCIPReaderTesterCommitReportAcceptedIterator, error) diff --git a/core/gethwrappers/ccip/generated/commit_store/commit_store.go b/core/gethwrappers/ccip/generated/commit_store/commit_store.go index 940f4208d43..b0082a3f0bf 100644 --- a/core/gethwrappers/ccip/generated/commit_store/commit_store.go +++ b/core/gethwrappers/ccip/generated/commit_store/commit_store.go @@ -69,7 +69,7 @@ type InternalTokenPriceUpdate struct { var CommitStoreMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structCommitStore.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"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\":\"enumOCR2Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"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\":\"rmnProxy\",\"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\":false,\"internalType\":\"uint40\",\"name\":\"oldEpochAndRound\",\"type\":\"uint40\"},{\"indexed\":false,\"internalType\":\"uint40\",\"name\":\"newEpochAndRound\",\"type\":\"uint40\"}],\"name\":\"LatestPriceEpochAndRoundSet\",\"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\":\"uint64\",\"name\":\"oldSeqNum\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newSeqNum\",\"type\":\"uint64\"}],\"name\":\"SequenceNumberSet\",\"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\":\"rmnProxy\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isUnpausedAndNotCursed\",\"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\"}]", - Bin: "0x61014060405260098054600165ff000000000160401b03191660011790553480156200002a57600080fd5b506040516200378e3803806200378e8339810160408190526200004d9162000272565b600033808281620000a55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d857620000d88162000192565b50505015156080524660a05260408101516001600160a01b0316158062000107575080516001600160401b0316155b806200011e575060208101516001600160401b0316155b8062000135575060608101516001600160a01b0316155b156200015457604051631fc5f15f60e11b815260040160405180910390fd5b80516001600160401b0390811660c05260208201511660e05260408101516001600160a01b0390811661010052606090910151166101205262000306565b336001600160a01b03821603620001ec5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009c565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160401b03811681146200025557600080fd5b919050565b80516001600160a01b03811681146200025557600080fd5b6000608082840312156200028557600080fd5b604051608081016001600160401b0381118282101715620002b657634e487b7160e01b600052604160045260246000fd5b604052620002c4836200023d565b8152620002d4602084016200023d565b6020820152620002e7604084016200025a565b6040820152620002fa606084016200025a565b60608201529392505050565b60805160a05160c05160e05161010051610120516133f26200039c60003960008181610262015281816116c80152818161187c01528181611acb0152611fa50152600081816102260152611aa40152600081816101f60152818161168201528181611a7d0152611f620152600081816101c60152611a4e0152600081816110c801526111140152600061118f01526133f26000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806379ba5097116100e3578063afcb95d71161008c578063f2fde38b11610066578063f2fde38b146104e3578063f47a8690146104f6578063ff888fb11461050957600080fd5b8063afcb95d7146104a8578063b1dc65a4146104c8578063e89d039f146104db57600080fd5b80638da5cb5b116100bd5780638da5cb5b1461044d578063a7206cd614610475578063ad7a22f81461049557600080fd5b806379ba50971461040d57806381ff7048146104155780638456cb591461044557600080fd5b806332048875116101455780635c975abb1161011f5780635c975abb14610391578063666cab8d146103b95780637437ff9f146103ce57600080fd5b806332048875146103565780633f4ba83a146103775780634120fccd1461037f57600080fd5b8063181f5a7711610176578063181f5a77146102e55780631ef381741461032e57806329b980e41461034357600080fd5b806306285c691461019257806310c374ed146102b5575b600080fd5b61029f60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102ac9190612583565b60405180910390f35b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102ac565b6103216040518060400160405280601581526020017f436f6d6d697453746f726520312e352e302d646576000000000000000000000081525081565b6040516102ac9190612640565b61034161033c366004612897565b61051c565b005b610341610351366004612964565b610c00565b6103696103643660046129d7565b610c90565b6040519081526020016102ac565b610341610d86565b60095467ffffffffffffffff166102cc565b6009546d0100000000000000000000000000900460ff165b60405190151581526020016102ac565b6103c1610dec565b6040516102ac9190612a9d565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102ac565b610341610e5b565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102ac565b610341610f58565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ac565b610369610483366004612ab0565b6000908152600a602052604090205490565b6103416104a3366004612ac9565b610fc8565b6040805160018152600060208201819052918101919091526060016102ac565b6103416104d6366004612ae4565b611043565b6103a961165a565b6103416104f1366004612bc9565b61176e565b610341610504366004612be6565b611782565b6103a9610517366004612ab0565b611819565b855185518560ff16601f83111561056b5760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b60405180910390fd5b806000036105a85760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b8183146105e45760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b6105ef816003612cc7565b831161062a5760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b6106326118ed565b61063b86611970565b60065460005b8181101561072f57600560006006838154811061066057610660612cde565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600780546005929190849081106106d0576106d0612cde565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101610641565b50895160005b81811015610aa85760008c828151811061075157610751612cde565b602002602001015190506000600281111561076e5761076e612c28565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff1660028111156107ad576107ad612c28565b146107e75760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b73ffffffffffffffffffffffffffffffffffffffff8116610834576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156108e4576108e4612c28565b021790555090505060008c838151811061090057610900612cde565b602002602001015190506000600281111561091d5761091d612c28565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561095c5761095c612c28565b146109965760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b73ffffffffffffffffffffffffffffffffffffffff81166109e3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610a9357610a93612c28565b02179055509050505050806001019050610735565b508a51610abc9060069060208e01906124c5565b508951610ad09060079060208d01906124c5565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610b56914691309190600090610b289063ffffffff16612d0d565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e611b20565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610bea99989796959493929190612d30565b60405180910390a1505050505050505050505050565b610c086118ed565b6009805464ffffffffff838116680100000000000000008181027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917ff0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf56545644491015b60405180910390a15050565b6009546000906d0100000000000000000000000000900460ff1615610ce1576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d5287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250611bcb915050565b9050610d5d81611819565b610d6b576000915050610d7d565b6000908152600a602052604090205490505b95945050505050565b610d8e6118ed565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60606007805480602002602001604051908101604052809291908181526020018280548015610e5157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e26575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610562565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f606118ed565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610de2565b610fd06118ed565b6009805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000083168117909355604080519190921680825260208201939093527fea59e8027e41fda1525220008cf2416797405065eb21b0ebd417bfc6d361b8de9101610c84565b611052878760208b0135611eec565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146110c55780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610562565b467f000000000000000000000000000000000000000000000000000000000000000014611146576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610562565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f0000000000000000000000000000000000000000000000000000000000000000156111e8576002826020015183604001516111c99190612dc6565b6111d39190612ddf565b6111de906001612dc6565b60ff1690506111fe565b60208201516111f8906001612dc6565b60ff1690505b868114611237576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868514611270576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156112b3576112b3612c28565b60028111156112c4576112c4612c28565b90525090506002816020015160028111156112e1576112e1612c28565b14801561132857506007816000015160ff168154811061130357611303612cde565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61135e576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600061136c866020612cc7565b611377896020612cc7565b6113838c610144612e28565b61138d9190612e28565b6113979190612e28565b90503681146113db576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610562565b5060008a8a6040516113ee929190612e3b565b604051908190038120611405918e90602001612e4b565b60405160208183030381529060405280519060200120905061142561254f565b8860005b818110156116495760006001858a846020811061144857611448612cde565b61145591901a601b612dc6565b8f8f8681811061146757611467612cde565b905060200201358e8e8781811061148057611480612cde565b90506020020135604051600081526020016040526040516114bd949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156114df573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff808216865293975091955092939284019161010090910416600281111561156257611562612c28565b600281111561157357611573612c28565b905250905060018160200151600281111561159057611590612c28565b146115c7576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106115de576115de612cde565b60200201511561161a576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061163557611635612cde565b911515602090920201525050600101611429565b505050505050505050505050505050565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117489190612e5f565b15801561176957506009546d0100000000000000000000000000900460ff16155b905090565b6117766118ed565b61177f81612355565b50565b61178a6118ed565b60005b818110156118145760008383838181106117a9576117a9612cde565b9050602002013590506117bb81611819565b61180b576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12906118029083815260200190565b60405180910390a15b5060010161178d565b505050565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa1580156118c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e79190612e5f565b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461196e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610562565b565b6000818060200190518101906119869190612e81565b805190915073ffffffffffffffffffffffffffffffffffffffff166119d7576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff90811682527f00000000000000000000000000000000000000000000000000000000000000001660208201527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec391610c84918490612ecd565b6000808a8a8a8a8a8a8a8a8a604051602001611b4499989796959493929190612f4a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b8251825160009190818303611c0c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590611c2057506101018111155b611c56576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115611cb7576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003611ce45786600081518110611cd257611cd2612cde565b60200260200101519350505050611ee5565b60008167ffffffffffffffff811115611cff57611cff612653565b604051908082528060200260200182016040528015611d28578160200160208202803683370190505b50905060008080805b85811015611e6b5760006001821b8b811603611d8c5788851015611d75578c5160018601958e918110611d6657611d66612cde565b60200260200101519050611dae565b8551600185019487918110611d6657611d66612cde565b8b5160018401938d918110611da357611da3612cde565b602002602001015190505b600089861015611dde578d5160018701968f918110611dcf57611dcf612cde565b60200260200101519050611e00565b8651600186019588918110611df557611df5612cde565b602002602001015190505b82851115611e3a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e44828261244a565b878481518110611e5657611e56612cde565b60209081029190910101525050600101611d31565b506001850382148015611e7d57508683145b8015611e8857508581145b611ebe576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001860381518110611ed357611ed3612cde565b60200260200101519750505050505050505b9392505050565b6009546d0100000000000000000000000000900460ff1615611f3a576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120259190612e5f565b1561205c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061206a838501856130d6565b8051515190915015158061208357508051602001515115155b156121bb5760095464ffffffffff8084166801000000000000000090920416101561218057600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f3937306f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90921691633937306f9161213a91600401613329565b600060405180830381600087803b15801561215457600080fd5b505af1158015612168573d6000803e3d6000fd5b50505050604081015161217b5750505050565b6121bb565b60408101516121bb576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff90811691161415806121f6575060208082015190810151905167ffffffffffffffff9182169116115b156122335780602001516040517fbb1ae18d000000000000000000000000000000000000000000000000000000008152600401610562919061333c565b604081015161226e576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a6020522054156122b7576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015101516122ca906001613361565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517f291698c01aa71f912280535d88a00d2c59fb63530a3f5d0098560468acb9ebf590612347908390613389565b60405180910390a150505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036123d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610562565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081831061248c5760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120611ee5565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120611ee5565b82805482825590600052602060002090810192821561253f579160200282015b8281111561253f57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906124e5565b5061254b92915061256e565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b8082111561254b576000815560010161256f565b608081016118e7828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b81811015612602576020818501810151868301820152016125e6565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611ee560208301846125dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156126a5576126a5612653565b60405290565b6040516060810167ffffffffffffffff811182821017156126a5576126a5612653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561271557612715612653565b604052919050565b600067ffffffffffffffff82111561273757612737612653565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461177f57600080fd5b600082601f83011261277457600080fd5b813560206127896127848361271d565b6126ce565b8083825260208201915060208460051b8701019350868411156127ab57600080fd5b602086015b848110156127d05780356127c381612741565b83529183019183016127b0565b509695505050505050565b803560ff811681146127ec57600080fd5b919050565b600082601f83011261280257600080fd5b813567ffffffffffffffff81111561281c5761281c612653565b61284d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016126ce565b81815284602083860101111561286257600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146127ec57600080fd5b60008060008060008060c087890312156128b057600080fd5b863567ffffffffffffffff808211156128c857600080fd5b6128d48a838b01612763565b975060208901359150808211156128ea57600080fd5b6128f68a838b01612763565b965061290460408a016127db565b9550606089013591508082111561291a57600080fd5b6129268a838b016127f1565b945061293460808a0161287f565b935060a089013591508082111561294a57600080fd5b5061295789828a016127f1565b9150509295509295509295565b60006020828403121561297657600080fd5b813564ffffffffff81168114611ee557600080fd5b60008083601f84011261299d57600080fd5b50813567ffffffffffffffff8111156129b557600080fd5b6020830191508360208260051b85010111156129d057600080fd5b9250929050565b6000806000806000606086880312156129ef57600080fd5b853567ffffffffffffffff80821115612a0757600080fd5b612a1389838a0161298b565b90975095506020880135915080821115612a2c57600080fd5b50612a398882890161298b565b96999598509660400135949350505050565b60008151808452602080850194506020840160005b83811015612a9257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612a60565b509495945050505050565b602081526000611ee56020830184612a4b565b600060208284031215612ac257600080fd5b5035919050565b600060208284031215612adb57600080fd5b611ee58261287f565b60008060008060008060008060e0898b031215612b0057600080fd5b606089018a811115612b1157600080fd5b8998503567ffffffffffffffff80821115612b2b57600080fd5b818b0191508b601f830112612b3f57600080fd5b813581811115612b4e57600080fd5b8c6020828501011115612b6057600080fd5b6020830199508098505060808b0135915080821115612b7e57600080fd5b612b8a8c838d0161298b565b909750955060a08b0135915080821115612ba357600080fd5b50612bb08b828c0161298b565b999c989b50969995989497949560c00135949350505050565b600060208284031215612bdb57600080fd5b8135611ee581612741565b60008060208385031215612bf957600080fd5b823567ffffffffffffffff811115612c1057600080fd5b612c1c8582860161298b565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310612c92577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176118e7576118e7612c98565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103612d2657612d26612c98565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612d608184018a612a4b565b90508281036080840152612d748189612a4b565b905060ff871660a084015282810360c0840152612d9181876125dc565b905067ffffffffffffffff851660e0840152828103610100840152612db681856125dc565b9c9b505050505050505050505050565b60ff81811683821601908111156118e7576118e7612c98565b600060ff831680612e19577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b808201808211156118e7576118e7612c98565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612e7157600080fd5b81518015158114611ee557600080fd5b600060208284031215612e9357600080fd5b6040516020810181811067ffffffffffffffff82111715612eb657612eb6612653565b6040528251612ec481612741565b81529392505050565b60a08101612f26828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152612f918285018b612a4b565b91508382036080850152612fa5828a612a4b565b915060ff881660a085015283820360c0850152612fc282886125dc565b90861660e08501528381036101008501529050612db681856125dc565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146127ec57600080fd5b600082601f83011261301c57600080fd5b8135602061302c6127848361271d565b82815260069290921b8401810191818101908684111561304b57600080fd5b8286015b848110156127d057604081890312156130685760008081fd5b613070612682565b6130798261287f565b8152613086858301612fdf565b8186015283529183019160400161304f565b6000604082840312156130aa57600080fd5b6130b2612682565b90506130bd8261287f565b81526130cb6020830161287f565b602082015292915050565b600060208083850312156130e957600080fd5b823567ffffffffffffffff8082111561310157600080fd5b908401906080828703121561311557600080fd5b61311d6126ab565b82358281111561312c57600080fd5b8301604081890381131561313f57600080fd5b613147612682565b82358581111561315657600080fd5b8301601f81018b1361316757600080fd5b80356131756127848261271d565b81815260069190911b8201890190898101908d83111561319457600080fd5b928a01925b828410156131e45785848f0312156131b15760008081fd5b6131b9612682565b84356131c481612741565b81526131d1858d01612fdf565b818d0152825292850192908a0190613199565b8452505050828701359150848211156131fc57600080fd5b6132088a83850161300b565b8188015283525061321d905087848601613098565b93810193909352506060013560408201529392505050565b805160408084528151848201819052600092602091908201906060870190855b818110156132ae578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101613255565b50508583015187820388850152805180835290840192506000918401905b8083101561331d578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906132cc565b50979650505050505050565b602081526000611ee56020830184613235565b604081016118e78284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff81811683821601908082111561338257613382612c98565b5092915050565b6020815260008251608060208401526133a560a0840182613235565b905060208401516133d06040850182805167ffffffffffffffff908116835260209182015116910152565b5060408401516080840152809150509291505056fea164736f6c6343000818000a", + Bin: "0x61014060405260098054600165ff000000000160401b03191660011790553480156200002a57600080fd5b506040516200378e3803806200378e8339810160408190526200004d9162000272565b600033808281620000a55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d857620000d88162000192565b50505015156080524660a05260408101516001600160a01b0316158062000107575080516001600160401b0316155b806200011e575060208101516001600160401b0316155b8062000135575060608101516001600160a01b0316155b156200015457604051631fc5f15f60e11b815260040160405180910390fd5b80516001600160401b0390811660c05260208201511660e05260408101516001600160a01b0390811661010052606090910151166101205262000306565b336001600160a01b03821603620001ec5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009c565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160401b03811681146200025557600080fd5b919050565b80516001600160a01b03811681146200025557600080fd5b6000608082840312156200028557600080fd5b604051608081016001600160401b0381118282101715620002b657634e487b7160e01b600052604160045260246000fd5b604052620002c4836200023d565b8152620002d4602084016200023d565b6020820152620002e7604084016200025a565b6040820152620002fa606084016200025a565b60608201529392505050565b60805160a05160c05160e05161010051610120516133f26200039c60003960008181610262015281816116c80152818161187c01528181611acb0152611fa50152600081816102260152611aa40152600081816101f60152818161168201528181611a7d0152611f620152600081816101c60152611a4e0152600081816110c801526111140152600061118f01526133f26000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806379ba5097116100e3578063afcb95d71161008c578063f2fde38b11610066578063f2fde38b146104e3578063f47a8690146104f6578063ff888fb11461050957600080fd5b8063afcb95d7146104a8578063b1dc65a4146104c8578063e89d039f146104db57600080fd5b80638da5cb5b116100bd5780638da5cb5b1461044d578063a7206cd614610475578063ad7a22f81461049557600080fd5b806379ba50971461040d57806381ff7048146104155780638456cb591461044557600080fd5b806332048875116101455780635c975abb1161011f5780635c975abb14610391578063666cab8d146103b95780637437ff9f146103ce57600080fd5b806332048875146103565780633f4ba83a146103775780634120fccd1461037f57600080fd5b8063181f5a7711610176578063181f5a77146102e55780631ef381741461032e57806329b980e41461034357600080fd5b806306285c691461019257806310c374ed146102b5575b600080fd5b61029f60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102ac9190612583565b60405180910390f35b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102ac565b6103216040518060400160405280601181526020017f436f6d6d697453746f726520312e352e3000000000000000000000000000000081525081565b6040516102ac9190612640565b61034161033c366004612897565b61051c565b005b610341610351366004612964565b610c00565b6103696103643660046129d7565b610c90565b6040519081526020016102ac565b610341610d86565b60095467ffffffffffffffff166102cc565b6009546d0100000000000000000000000000900460ff165b60405190151581526020016102ac565b6103c1610dec565b6040516102ac9190612a9d565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102ac565b610341610e5b565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102ac565b610341610f58565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ac565b610369610483366004612ab0565b6000908152600a602052604090205490565b6103416104a3366004612ac9565b610fc8565b6040805160018152600060208201819052918101919091526060016102ac565b6103416104d6366004612ae4565b611043565b6103a961165a565b6103416104f1366004612bc9565b61176e565b610341610504366004612be6565b611782565b6103a9610517366004612ab0565b611819565b855185518560ff16601f83111561056b5760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b60405180910390fd5b806000036105a85760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b8183146105e45760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b6105ef816003612cc7565b831161062a5760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b6106326118ed565b61063b86611970565b60065460005b8181101561072f57600560006006838154811061066057610660612cde565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600780546005929190849081106106d0576106d0612cde565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101610641565b50895160005b81811015610aa85760008c828151811061075157610751612cde565b602002602001015190506000600281111561076e5761076e612c28565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff1660028111156107ad576107ad612c28565b146107e75760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b73ffffffffffffffffffffffffffffffffffffffff8116610834576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156108e4576108e4612c28565b021790555090505060008c838151811061090057610900612cde565b602002602001015190506000600281111561091d5761091d612c28565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561095c5761095c612c28565b146109965760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b73ffffffffffffffffffffffffffffffffffffffff81166109e3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610a9357610a93612c28565b02179055509050505050806001019050610735565b508a51610abc9060069060208e01906124c5565b508951610ad09060079060208d01906124c5565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610b56914691309190600090610b289063ffffffff16612d0d565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e611b20565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610bea99989796959493929190612d30565b60405180910390a1505050505050505050505050565b610c086118ed565b6009805464ffffffffff838116680100000000000000008181027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917ff0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf56545644491015b60405180910390a15050565b6009546000906d0100000000000000000000000000900460ff1615610ce1576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d5287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250611bcb915050565b9050610d5d81611819565b610d6b576000915050610d7d565b6000908152600a602052604090205490505b95945050505050565b610d8e6118ed565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60606007805480602002602001604051908101604052809291908181526020018280548015610e5157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e26575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610562565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f606118ed565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610de2565b610fd06118ed565b6009805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000083168117909355604080519190921680825260208201939093527fea59e8027e41fda1525220008cf2416797405065eb21b0ebd417bfc6d361b8de9101610c84565b611052878760208b0135611eec565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146110c55780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610562565b467f000000000000000000000000000000000000000000000000000000000000000014611146576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610562565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f0000000000000000000000000000000000000000000000000000000000000000156111e8576002826020015183604001516111c99190612dc6565b6111d39190612ddf565b6111de906001612dc6565b60ff1690506111fe565b60208201516111f8906001612dc6565b60ff1690505b868114611237576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868514611270576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156112b3576112b3612c28565b60028111156112c4576112c4612c28565b90525090506002816020015160028111156112e1576112e1612c28565b14801561132857506007816000015160ff168154811061130357611303612cde565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61135e576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600061136c866020612cc7565b611377896020612cc7565b6113838c610144612e28565b61138d9190612e28565b6113979190612e28565b90503681146113db576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610562565b5060008a8a6040516113ee929190612e3b565b604051908190038120611405918e90602001612e4b565b60405160208183030381529060405280519060200120905061142561254f565b8860005b818110156116495760006001858a846020811061144857611448612cde565b61145591901a601b612dc6565b8f8f8681811061146757611467612cde565b905060200201358e8e8781811061148057611480612cde565b90506020020135604051600081526020016040526040516114bd949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156114df573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff808216865293975091955092939284019161010090910416600281111561156257611562612c28565b600281111561157357611573612c28565b905250905060018160200151600281111561159057611590612c28565b146115c7576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106115de576115de612cde565b60200201511561161a576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061163557611635612cde565b911515602090920201525050600101611429565b505050505050505050505050505050565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117489190612e5f565b15801561176957506009546d0100000000000000000000000000900460ff16155b905090565b6117766118ed565b61177f81612355565b50565b61178a6118ed565b60005b818110156118145760008383838181106117a9576117a9612cde565b9050602002013590506117bb81611819565b61180b576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12906118029083815260200190565b60405180910390a15b5060010161178d565b505050565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa1580156118c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e79190612e5f565b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461196e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610562565b565b6000818060200190518101906119869190612e81565b805190915073ffffffffffffffffffffffffffffffffffffffff166119d7576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff90811682527f00000000000000000000000000000000000000000000000000000000000000001660208201527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec391610c84918490612ecd565b6000808a8a8a8a8a8a8a8a8a604051602001611b4499989796959493929190612f4a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b8251825160009190818303611c0c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590611c2057506101018111155b611c56576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115611cb7576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003611ce45786600081518110611cd257611cd2612cde565b60200260200101519350505050611ee5565b60008167ffffffffffffffff811115611cff57611cff612653565b604051908082528060200260200182016040528015611d28578160200160208202803683370190505b50905060008080805b85811015611e6b5760006001821b8b811603611d8c5788851015611d75578c5160018601958e918110611d6657611d66612cde565b60200260200101519050611dae565b8551600185019487918110611d6657611d66612cde565b8b5160018401938d918110611da357611da3612cde565b602002602001015190505b600089861015611dde578d5160018701968f918110611dcf57611dcf612cde565b60200260200101519050611e00565b8651600186019588918110611df557611df5612cde565b602002602001015190505b82851115611e3a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e44828261244a565b878481518110611e5657611e56612cde565b60209081029190910101525050600101611d31565b506001850382148015611e7d57508683145b8015611e8857508581145b611ebe576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001860381518110611ed357611ed3612cde565b60200260200101519750505050505050505b9392505050565b6009546d0100000000000000000000000000900460ff1615611f3a576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120259190612e5f565b1561205c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061206a838501856130d6565b8051515190915015158061208357508051602001515115155b156121bb5760095464ffffffffff8084166801000000000000000090920416101561218057600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f3937306f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90921691633937306f9161213a91600401613329565b600060405180830381600087803b15801561215457600080fd5b505af1158015612168573d6000803e3d6000fd5b50505050604081015161217b5750505050565b6121bb565b60408101516121bb576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff90811691161415806121f6575060208082015190810151905167ffffffffffffffff9182169116115b156122335780602001516040517fbb1ae18d000000000000000000000000000000000000000000000000000000008152600401610562919061333c565b604081015161226e576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a6020522054156122b7576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015101516122ca906001613361565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517f291698c01aa71f912280535d88a00d2c59fb63530a3f5d0098560468acb9ebf590612347908390613389565b60405180910390a150505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036123d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610562565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081831061248c5760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120611ee5565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120611ee5565b82805482825590600052602060002090810192821561253f579160200282015b8281111561253f57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906124e5565b5061254b92915061256e565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b8082111561254b576000815560010161256f565b608081016118e7828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b81811015612602576020818501810151868301820152016125e6565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611ee560208301846125dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156126a5576126a5612653565b60405290565b6040516060810167ffffffffffffffff811182821017156126a5576126a5612653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561271557612715612653565b604052919050565b600067ffffffffffffffff82111561273757612737612653565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461177f57600080fd5b600082601f83011261277457600080fd5b813560206127896127848361271d565b6126ce565b8083825260208201915060208460051b8701019350868411156127ab57600080fd5b602086015b848110156127d05780356127c381612741565b83529183019183016127b0565b509695505050505050565b803560ff811681146127ec57600080fd5b919050565b600082601f83011261280257600080fd5b813567ffffffffffffffff81111561281c5761281c612653565b61284d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016126ce565b81815284602083860101111561286257600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146127ec57600080fd5b60008060008060008060c087890312156128b057600080fd5b863567ffffffffffffffff808211156128c857600080fd5b6128d48a838b01612763565b975060208901359150808211156128ea57600080fd5b6128f68a838b01612763565b965061290460408a016127db565b9550606089013591508082111561291a57600080fd5b6129268a838b016127f1565b945061293460808a0161287f565b935060a089013591508082111561294a57600080fd5b5061295789828a016127f1565b9150509295509295509295565b60006020828403121561297657600080fd5b813564ffffffffff81168114611ee557600080fd5b60008083601f84011261299d57600080fd5b50813567ffffffffffffffff8111156129b557600080fd5b6020830191508360208260051b85010111156129d057600080fd5b9250929050565b6000806000806000606086880312156129ef57600080fd5b853567ffffffffffffffff80821115612a0757600080fd5b612a1389838a0161298b565b90975095506020880135915080821115612a2c57600080fd5b50612a398882890161298b565b96999598509660400135949350505050565b60008151808452602080850194506020840160005b83811015612a9257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612a60565b509495945050505050565b602081526000611ee56020830184612a4b565b600060208284031215612ac257600080fd5b5035919050565b600060208284031215612adb57600080fd5b611ee58261287f565b60008060008060008060008060e0898b031215612b0057600080fd5b606089018a811115612b1157600080fd5b8998503567ffffffffffffffff80821115612b2b57600080fd5b818b0191508b601f830112612b3f57600080fd5b813581811115612b4e57600080fd5b8c6020828501011115612b6057600080fd5b6020830199508098505060808b0135915080821115612b7e57600080fd5b612b8a8c838d0161298b565b909750955060a08b0135915080821115612ba357600080fd5b50612bb08b828c0161298b565b999c989b50969995989497949560c00135949350505050565b600060208284031215612bdb57600080fd5b8135611ee581612741565b60008060208385031215612bf957600080fd5b823567ffffffffffffffff811115612c1057600080fd5b612c1c8582860161298b565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310612c92577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176118e7576118e7612c98565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103612d2657612d26612c98565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612d608184018a612a4b565b90508281036080840152612d748189612a4b565b905060ff871660a084015282810360c0840152612d9181876125dc565b905067ffffffffffffffff851660e0840152828103610100840152612db681856125dc565b9c9b505050505050505050505050565b60ff81811683821601908111156118e7576118e7612c98565b600060ff831680612e19577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b808201808211156118e7576118e7612c98565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612e7157600080fd5b81518015158114611ee557600080fd5b600060208284031215612e9357600080fd5b6040516020810181811067ffffffffffffffff82111715612eb657612eb6612653565b6040528251612ec481612741565b81529392505050565b60a08101612f26828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152612f918285018b612a4b565b91508382036080850152612fa5828a612a4b565b915060ff881660a085015283820360c0850152612fc282886125dc565b90861660e08501528381036101008501529050612db681856125dc565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146127ec57600080fd5b600082601f83011261301c57600080fd5b8135602061302c6127848361271d565b82815260069290921b8401810191818101908684111561304b57600080fd5b8286015b848110156127d057604081890312156130685760008081fd5b613070612682565b6130798261287f565b8152613086858301612fdf565b8186015283529183019160400161304f565b6000604082840312156130aa57600080fd5b6130b2612682565b90506130bd8261287f565b81526130cb6020830161287f565b602082015292915050565b600060208083850312156130e957600080fd5b823567ffffffffffffffff8082111561310157600080fd5b908401906080828703121561311557600080fd5b61311d6126ab565b82358281111561312c57600080fd5b8301604081890381131561313f57600080fd5b613147612682565b82358581111561315657600080fd5b8301601f81018b1361316757600080fd5b80356131756127848261271d565b81815260069190911b8201890190898101908d83111561319457600080fd5b928a01925b828410156131e45785848f0312156131b15760008081fd5b6131b9612682565b84356131c481612741565b81526131d1858d01612fdf565b818d0152825292850192908a0190613199565b8452505050828701359150848211156131fc57600080fd5b6132088a83850161300b565b8188015283525061321d905087848601613098565b93810193909352506060013560408201529392505050565b805160408084528151848201819052600092602091908201906060870190855b818110156132ae578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101613255565b50508583015187820388850152805180835290840192506000918401905b8083101561331d578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906132cc565b50979650505050505050565b602081526000611ee56020830184613235565b604081016118e78284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff81811683821601908082111561338257613382612c98565b5092915050565b6020815260008251608060208401526133a560a0840182613235565b905060208401516133d06040850182805167ffffffffffffffff908116835260209182015116910152565b5060408401516080840152809150509291505056fea164736f6c6343000818000a", } var CommitStoreABI = CommitStoreMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/commit_store_1_0_0/commit_store_1_0_0.go b/core/gethwrappers/ccip/generated/commit_store_1_0_0/commit_store_1_0_0.go deleted file mode 100644 index 30716b257cb..00000000000 --- a/core/gethwrappers/ccip/generated/commit_store_1_0_0/commit_store_1_0_0.go +++ /dev/null @@ -1,1951 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package commit_store_1_0_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 CommitStoreCommitReport struct { - PriceUpdates InternalPriceUpdates - Interval CommitStoreInterval - MerkleRoot [32]byte -} - -type CommitStoreDynamicConfig struct { - PriceRegistry common.Address -} - -type CommitStoreInterval struct { - Min uint64 - Max uint64 -} - -type CommitStoreStaticConfig struct { - ChainSelector uint64 - SourceChainSelector uint64 - OnRamp common.Address - ArmProxy common.Address -} - -type InternalPriceUpdates struct { - TokenPriceUpdates []InternalTokenPriceUpdate - DestChainSelector uint64 - UsdPerUnitGas *big.Int -} - -type InternalTokenPriceUpdate struct { - SourceToken common.Address - UsdPerToken *big.Int -} - -var CommitStoreMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"uint192\",\"name\":\"usdPerToken\",\"type\":\"uint192\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint192\",\"name\":\"usdPerUnitGas\",\"type\":\"uint192\"}],\"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\"}]", - Bin: "0x61014060405260098054600165ff000000000160401b03191660011790553480156200002a57600080fd5b5060405162003788380380620037888339810160408190526200004d9162000272565b600033808281620000a55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d857620000d88162000192565b50505015156080524660a05260408101516001600160a01b0316158062000107575080516001600160401b0316155b806200011e575060208101516001600160401b0316155b8062000135575060608101516001600160a01b0316155b156200015457604051631fc5f15f60e11b815260040160405180910390fd5b80516001600160401b0390811660c05260208201511660e05260408101516001600160a01b0390811661010052606090910151166101205262000306565b336001600160a01b03821603620001ec5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009c565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160401b03811681146200025557600080fd5b919050565b80516001600160a01b03811681146200025557600080fd5b6000608082840312156200028557600080fd5b604051608081016001600160401b0381118282101715620002b657634e487b7160e01b600052604160045260246000fd5b604052620002c4836200023d565b8152620002d4602084016200023d565b6020820152620002e7604084016200025a565b6040820152620002fa606084016200025a565b60608201529392505050565b60805160a05160c05160e05161010051610120516133f3620003956000396000818161026d01528181610537015281816111730152818161199f01528181611bee015261206b0152600081816102310152611bc70152600081816102010152611ba00152600081816101d10152611b710152600081816112ee015261133a015260006113b501526133f36000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806379ba5097116100e3578063ad7a22f81161008c578063f2fde38b11610066578063f2fde38b146104fa578063f47a86901461050d578063ff888fb11461052057600080fd5b8063ad7a22f8146104b4578063afcb95d7146104c7578063b1dc65a4146104e757600080fd5b80638da5cb5b116100bd5780638da5cb5b146104645780638db94e441461048c578063a7206cd61461049457600080fd5b806379ba50971461042457806381ff70481461042c5780638456cb591461045c57600080fd5b806332048875116101455780635c975abb1161011f5780635c975abb146103b4578063666cab8d146103d05780637437ff9f146103e557600080fd5b806332048875146103795780633f4ba83a1461039a5780634120fccd146103a257600080fd5b8063181f5a7711610176578063181f5a77146103085780631ef381741461035157806329b980e41461036657600080fd5b806306285c691461019d5780630a6cd30d146102c057806310c374ed146102d8575b600080fd5b6102aa60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102b7919061265f565b60405180910390f35b6102c8610533565b60405190151581526020016102b7565b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102b7565b6103446040518060400160405280601181526020017f436f6d6d697453746f726520312e302e3000000000000000000000000000000081525081565b6040516102b7919061271c565b61036461035f36600461296f565b6105ca565b005b610364610374366004612a3c565b610deb565b61038c610387366004612aaf565b610e37565b6040519081526020016102b7565b610364610f2d565b60095467ffffffffffffffff166102ef565b6009546d0100000000000000000000000000900460ff166102c8565b6103d8610f93565b6040516102b79190612b74565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102b7565b610364611002565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102b7565b6103646110ff565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b7565b6102c861116f565b61038c6104a2366004612b87565b6000908152600a602052604090205490565b6103646104c2366004612ba0565b611226565b6040805160018152600060208201819052918101919091526060016102b7565b6103646104f5366004612bbb565b611269565b610364610508366004612ca0565b611889565b61036461051b366004612cbd565b61189d565b6102c861052e366004612b87565b61193c565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c49190612cff565b15905090565b855185518560ff16601f831115610642576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e6572730000000000000000000000000000000060448201526064015b60405180910390fd5b806000036106ac576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610639565b81831461073a576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610639565b610745816003612d50565b83116107ad576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610639565b6107b5611a10565b6107be86611a93565b60065460005b818110156108ba5760056000600683815481106107e3576107e3612d67565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556007805460059291908490811061085357610853612d67565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556108b381612d96565b90506107c4565b50895160005b81811015610c935760008c82815181106108dc576108dc612d67565b60200260200101519050600060028111156108f9576108f9612dce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561093857610938612dce565b1461099f576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610639565b73ffffffffffffffffffffffffffffffffffffffff81166109ec576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610a9c57610a9c612dce565b021790555090505060008c8381518110610ab857610ab8612d67565b6020026020010151905060006002811115610ad557610ad5612dce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff166002811115610b1457610b14612dce565b14610b7b576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610639565b73ffffffffffffffffffffffffffffffffffffffff8116610bc8576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610c7857610c78612dce565b0217905550905050505080610c8c90612d96565b90506108c0565b508a51610ca79060069060208e01906125a1565b508951610cbb9060079060208d01906125a1565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610d41914691309190600090610d139063ffffffff16612dfd565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e611c4f565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610dd599989796959493929190612e20565b60405180910390a1505050505050505050505050565b610df3611a10565b6009805464ffffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff909216919091179055565b6009546000906d0100000000000000000000000000900460ff1615610e88576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610ef987878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250611cfa915050565b9050610f048161193c565b610f12576000915050610f24565b6000908152600a602052604090205490505b95945050505050565b610f35611a10565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60606007805480602002602001604051908101604052809291908181526020018280548015610ff857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610fcd575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610639565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611107611a10565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610f89565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112009190612cff565b15801561122157506009546d0100000000000000000000000000900460ff16155b905090565b61122e611a10565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b611278878760208b013561201b565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146112eb5780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610639565b467f00000000000000000000000000000000000000000000000000000000000000001461136c576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610639565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f00000000000000000000000000000000000000000000000000000000000000001561140e576002826020015183604001516113ef9190612eb6565b6113f99190612ecf565b611404906001612eb6565b60ff169050611424565b602082015161141e906001612eb6565b60ff1690505b86811461145d576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868514611496576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156114d9576114d9612dce565b60028111156114ea576114ea612dce565b905250905060028160200151600281111561150757611507612dce565b14801561154e57506007816000015160ff168154811061152957611529612d67565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b611584576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000611592866020612d50565b61159d896020612d50565b6115a98c610144612f18565b6115b39190612f18565b6115bd9190612f18565b9050368114611601576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610639565b5060008a8a604051611614929190612f2b565b60405190819003812061162b918e90602001612f3b565b60405160208183030381529060405280519060200120905061164b61262b565b8860005b818110156118785760006001858a846020811061166e5761166e612d67565b61167b91901a601b612eb6565b8f8f8681811061168d5761168d612d67565b905060200201358e8e878181106116a6576116a6612d67565b90506020020135604051600081526020016040526040516116e3949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611705573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff808216865293975091955092939284019161010090910416600281111561178857611788612dce565b600281111561179957611799612dce565b90525090506001816020015160028111156117b6576117b6612dce565b146117ed576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061180457611804612d67565b602002015115611840576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061185b5761185b612d67565b9115156020909202015250611871905081612d96565b905061164f565b505050505050505050505050505050565b611891611a10565b61189a81612431565b50565b6118a5611a10565b60005b818110156119375760008383838181106118c4576118c4612d67565b9050602002013590506118d68161193c565b611926576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f129061191d9083815260200190565b60405180910390a15b5061193081612d96565b90506118a8565b505050565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa1580156119e6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0a9190612cff565b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610639565b565b600081806020019051810190611aa99190612f4f565b805190915073ffffffffffffffffffffffffffffffffffffffff16611afa576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff90811682527f00000000000000000000000000000000000000000000000000000000000000001660208201527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec391611c43918490612f9b565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a604051602001611c7399989796959493929190613018565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b8251825160009190818303611d3b576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590611d4f57506101018111155b611d85576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115611de6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003611e135786600081518110611e0157611e01612d67565b60200260200101519350505050612014565b60008167ffffffffffffffff811115611e2e57611e2e61272f565b604051908082528060200260200182016040528015611e57578160200160208202803683370190505b50905060008080805b85811015611f9a5760006001821b8b811603611ebb5788851015611ea4578c5160018601958e918110611e9557611e95612d67565b60200260200101519050611edd565b8551600185019487918110611e9557611e95612d67565b8b5160018401938d918110611ed257611ed2612d67565b602002602001015190505b600089861015611f0d578d5160018701968f918110611efe57611efe612d67565b60200260200101519050611f2f565b8651600186019588918110611f2457611f24612d67565b602002602001015190505b82851115611f69576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f738282612526565b878481518110611f8557611f85612d67565b60209081029190910101525050600101611e60565b506001850382148015611fac57508683145b8015611fb757508581145b611fed576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600186038151811061200257612002612d67565b60200260200101519750505050505050505b9392505050565b6009546d0100000000000000000000000000900460ff1615612069576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f89190612cff565b1561212f576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061213d83850185613113565b8051515190915015158061215f575080516020015167ffffffffffffffff1615155b156122975760095464ffffffffff8084166801000000000000000090920416101561225c57600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f866548c900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163866548c9916122169160040161332a565b600060405180830381600087803b15801561223057600080fd5b505af1158015612244573d6000803e3d6000fd5b5050505060408101516122575750505050565b612297565b6040810151612297576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff90811691161415806122d2575060208082015190810151905167ffffffffffffffff9182169116115b1561230f5780602001516040517fbb1ae18d000000000000000000000000000000000000000000000000000000008152600401610639919061333d565b604081015161234a576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a602052205415612393576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015101516123a6906001613362565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517fe81b49e583122eb290c46fc255c962b9a2dec468816c00fb7a2e6ebc42dc92d49061242390839061338a565b60405180910390a150505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036124b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610639565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008183106125685760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120612014565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120612014565b82805482825590600052602060002090810192821561261b579160200282015b8281111561261b57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906125c1565b5061262792915061264a565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115612627576000815560010161264b565b60808101611a0a828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b818110156126de576020818501810151868301820152016126c2565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061201460208301846126b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156127815761278161272f565b60405290565b6040516060810167ffffffffffffffff811182821017156127815761278161272f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127f1576127f161272f565b604052919050565b600067ffffffffffffffff8211156128135761281361272f565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461189a57600080fd5b600082601f83011261285057600080fd5b81356020612865612860836127f9565b6127aa565b82815260059290921b8401810191818101908684111561288457600080fd5b8286015b848110156128a857803561289b8161281d565b8352918301918301612888565b509695505050505050565b803560ff811681146128c457600080fd5b919050565b600082601f8301126128da57600080fd5b813567ffffffffffffffff8111156128f4576128f461272f565b61292560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016127aa565b81815284602083860101111561293a57600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146128c457600080fd5b60008060008060008060c0878903121561298857600080fd5b863567ffffffffffffffff808211156129a057600080fd5b6129ac8a838b0161283f565b975060208901359150808211156129c257600080fd5b6129ce8a838b0161283f565b96506129dc60408a016128b3565b955060608901359150808211156129f257600080fd5b6129fe8a838b016128c9565b9450612a0c60808a01612957565b935060a0890135915080821115612a2257600080fd5b50612a2f89828a016128c9565b9150509295509295509295565b600060208284031215612a4e57600080fd5b813564ffffffffff8116811461201457600080fd5b60008083601f840112612a7557600080fd5b50813567ffffffffffffffff811115612a8d57600080fd5b6020830191508360208260051b8501011115612aa857600080fd5b9250929050565b600080600080600060608688031215612ac757600080fd5b853567ffffffffffffffff80821115612adf57600080fd5b612aeb89838a01612a63565b90975095506020880135915080821115612b0457600080fd5b50612b1188828901612a63565b96999598509660400135949350505050565b600081518084526020808501945080840160005b83811015612b6957815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612b37565b509495945050505050565b6020815260006120146020830184612b23565b600060208284031215612b9957600080fd5b5035919050565b600060208284031215612bb257600080fd5b61201482612957565b60008060008060008060008060e0898b031215612bd757600080fd5b606089018a811115612be857600080fd5b8998503567ffffffffffffffff80821115612c0257600080fd5b818b0191508b601f830112612c1657600080fd5b813581811115612c2557600080fd5b8c6020828501011115612c3757600080fd5b6020830199508098505060808b0135915080821115612c5557600080fd5b612c618c838d01612a63565b909750955060a08b0135915080821115612c7a57600080fd5b50612c878b828c01612a63565b999c989b50969995989497949560c00135949350505050565b600060208284031215612cb257600080fd5b81356120148161281d565b60008060208385031215612cd057600080fd5b823567ffffffffffffffff811115612ce757600080fd5b612cf385828601612a63565b90969095509350505050565b600060208284031215612d1157600080fd5b8151801515811461201457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611a0a57611a0a612d21565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612dc757612dc7612d21565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600063ffffffff808316818103612e1657612e16612d21565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612e508184018a612b23565b90508281036080840152612e648189612b23565b905060ff871660a084015282810360c0840152612e8181876126b8565b905067ffffffffffffffff851660e0840152828103610100840152612ea681856126b8565b9c9b505050505050505050505050565b60ff8181168382160190811115611a0a57611a0a612d21565b600060ff831680612f09577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b80820180821115611a0a57611a0a612d21565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612f6157600080fd5b6040516020810181811067ffffffffffffffff82111715612f8457612f8461272f565b6040528251612f928161281d565b81529392505050565b60a08101612ff4828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b16604085015281606085015261305f8285018b612b23565b91508382036080850152613073828a612b23565b915060ff881660a085015283820360c085015261309082886126b8565b90861660e08501528381036101008501529050612ea681856126b8565b803577ffffffffffffffffffffffffffffffffffffffffffffffff811681146128c457600080fd5b6000604082840312156130e757600080fd5b6130ef61275e565b90506130fa82612957565b815261310860208301612957565b602082015292915050565b6000602080838503121561312657600080fd5b823567ffffffffffffffff8082111561313e57600080fd5b908401906080828703121561315257600080fd5b61315a612787565b82358281111561316957600080fd5b83016060818903121561317b57600080fd5b613183612787565b81358481111561319257600080fd5b82019350601f840189136131a557600080fd5b83356131b3612860826127f9565b81815260069190911b8501870190878101908b8311156131d257600080fd5b958801955b82871015613226576040878d0312156131f05760008081fd5b6131f861275e565b87356132038161281d565b8152613210888b016130ad565b818b0152825260409690960195908801906131d7565b8352506132369050828701612957565b86820152613246604083016130ad565b604082015282525061325a878486016130d5565b93810193909352506060013560408201529392505050565b805160608084528151908401819052600091602091908201906080860190845b818110156132e9578351805173ffffffffffffffffffffffffffffffffffffffff16845285015177ffffffffffffffffffffffffffffffffffffffffffffffff168584015292840192604090920191600101613292565b505067ffffffffffffffff83860151168387015260408501519250610f24604087018477ffffffffffffffffffffffffffffffffffffffffffffffff169052565b6020815260006120146020830184613272565b60408101611a0a8284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff81811683821601908082111561338357613383612d21565b5092915050565b6020815260008251608060208401526133a660a0840182613272565b905060208401516133d16040850182805167ffffffffffffffff908116835260209182015116910152565b5060408401516080840152809150509291505056fea164736f6c6343000813000a", -} - -var CommitStoreABI = CommitStoreMetaData.ABI - -var CommitStoreBin = CommitStoreMetaData.Bin - -func DeployCommitStore(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig CommitStoreStaticConfig) (common.Address, *types.Transaction, *CommitStore, error) { - parsed, err := CommitStoreMetaData.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(CommitStoreBin), backend, staticConfig) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &CommitStore{CommitStoreCaller: CommitStoreCaller{contract: contract}, CommitStoreTransactor: CommitStoreTransactor{contract: contract}, CommitStoreFilterer: CommitStoreFilterer{contract: contract}}, nil -} - -type CommitStore struct { - address common.Address - abi abi.ABI - CommitStoreCaller - CommitStoreTransactor - CommitStoreFilterer -} - -type CommitStoreCaller struct { - contract *bind.BoundContract -} - -type CommitStoreTransactor struct { - contract *bind.BoundContract -} - -type CommitStoreFilterer struct { - contract *bind.BoundContract -} - -type CommitStoreSession struct { - Contract *CommitStore - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type CommitStoreCallerSession struct { - Contract *CommitStoreCaller - CallOpts bind.CallOpts -} - -type CommitStoreTransactorSession struct { - Contract *CommitStoreTransactor - TransactOpts bind.TransactOpts -} - -type CommitStoreRaw struct { - Contract *CommitStore -} - -type CommitStoreCallerRaw struct { - Contract *CommitStoreCaller -} - -type CommitStoreTransactorRaw struct { - Contract *CommitStoreTransactor -} - -func NewCommitStore(address common.Address, backend bind.ContractBackend) (*CommitStore, error) { - abi, err := abi.JSON(strings.NewReader(CommitStoreABI)) - if err != nil { - return nil, err - } - contract, err := bindCommitStore(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &CommitStore{address: address, abi: abi, CommitStoreCaller: CommitStoreCaller{contract: contract}, CommitStoreTransactor: CommitStoreTransactor{contract: contract}, CommitStoreFilterer: CommitStoreFilterer{contract: contract}}, nil -} - -func NewCommitStoreCaller(address common.Address, caller bind.ContractCaller) (*CommitStoreCaller, error) { - contract, err := bindCommitStore(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &CommitStoreCaller{contract: contract}, nil -} - -func NewCommitStoreTransactor(address common.Address, transactor bind.ContractTransactor) (*CommitStoreTransactor, error) { - contract, err := bindCommitStore(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &CommitStoreTransactor{contract: contract}, nil -} - -func NewCommitStoreFilterer(address common.Address, filterer bind.ContractFilterer) (*CommitStoreFilterer, error) { - contract, err := bindCommitStore(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &CommitStoreFilterer{contract: contract}, nil -} - -func bindCommitStore(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := CommitStoreMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_CommitStore *CommitStoreRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CommitStore.Contract.CommitStoreCaller.contract.Call(opts, result, method, params...) -} - -func (_CommitStore *CommitStoreRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStore.Contract.CommitStoreTransactor.contract.Transfer(opts) -} - -func (_CommitStore *CommitStoreRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CommitStore.Contract.CommitStoreTransactor.contract.Transact(opts, method, params...) -} - -func (_CommitStore *CommitStoreCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CommitStore.Contract.contract.Call(opts, result, method, params...) -} - -func (_CommitStore *CommitStoreTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStore.Contract.contract.Transfer(opts) -} - -func (_CommitStore *CommitStoreTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CommitStore.Contract.contract.Transact(opts, method, params...) -} - -func (_CommitStore *CommitStoreCaller) GetDynamicConfig(opts *bind.CallOpts) (CommitStoreDynamicConfig, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(CommitStoreDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(CommitStoreDynamicConfig)).(*CommitStoreDynamicConfig) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) GetDynamicConfig() (CommitStoreDynamicConfig, error) { - return _CommitStore.Contract.GetDynamicConfig(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) GetDynamicConfig() (CommitStoreDynamicConfig, error) { - return _CommitStore.Contract.GetDynamicConfig(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "getExpectedNextSequenceNumber") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _CommitStore.Contract.GetExpectedNextSequenceNumber(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _CommitStore.Contract.GetExpectedNextSequenceNumber(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) GetLatestPriceEpochAndRound(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "getLatestPriceEpochAndRound") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) GetLatestPriceEpochAndRound() (uint64, error) { - return _CommitStore.Contract.GetLatestPriceEpochAndRound(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) GetLatestPriceEpochAndRound() (uint64, error) { - return _CommitStore.Contract.GetLatestPriceEpochAndRound(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) GetMerkleRoot(opts *bind.CallOpts, root [32]byte) (*big.Int, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "getMerkleRoot", root) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) GetMerkleRoot(root [32]byte) (*big.Int, error) { - return _CommitStore.Contract.GetMerkleRoot(&_CommitStore.CallOpts, root) -} - -func (_CommitStore *CommitStoreCallerSession) GetMerkleRoot(root [32]byte) (*big.Int, error) { - return _CommitStore.Contract.GetMerkleRoot(&_CommitStore.CallOpts, root) -} - -func (_CommitStore *CommitStoreCaller) GetStaticConfig(opts *bind.CallOpts) (CommitStoreStaticConfig, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(CommitStoreStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(CommitStoreStaticConfig)).(*CommitStoreStaticConfig) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) GetStaticConfig() (CommitStoreStaticConfig, error) { - return _CommitStore.Contract.GetStaticConfig(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) GetStaticConfig() (CommitStoreStaticConfig, error) { - return _CommitStore.Contract.GetStaticConfig(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "getTransmitters") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) GetTransmitters() ([]common.Address, error) { - return _CommitStore.Contract.GetTransmitters(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) GetTransmitters() ([]common.Address, error) { - return _CommitStore.Contract.GetTransmitters(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) IsARMHealthy(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "isARMHealthy") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) IsARMHealthy() (bool, error) { - return _CommitStore.Contract.IsARMHealthy(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) IsARMHealthy() (bool, error) { - return _CommitStore.Contract.IsARMHealthy(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "isBlessed", root) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) IsBlessed(root [32]byte) (bool, error) { - return _CommitStore.Contract.IsBlessed(&_CommitStore.CallOpts, root) -} - -func (_CommitStore *CommitStoreCallerSession) IsBlessed(root [32]byte) (bool, error) { - return _CommitStore.Contract.IsBlessed(&_CommitStore.CallOpts, root) -} - -func (_CommitStore *CommitStoreCaller) IsUnpausedAndARMHealthy(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "isUnpausedAndARMHealthy") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) IsUnpausedAndARMHealthy() (bool, error) { - return _CommitStore.Contract.IsUnpausedAndARMHealthy(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) IsUnpausedAndARMHealthy() (bool, error) { - return _CommitStore.Contract.IsUnpausedAndARMHealthy(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) { - var out []interface{} - err := _CommitStore.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 (_CommitStore *CommitStoreSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _CommitStore.Contract.LatestConfigDetails(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _CommitStore.Contract.LatestConfigDetails(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) { - var out []interface{} - err := _CommitStore.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 (_CommitStore *CommitStoreSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _CommitStore.Contract.LatestConfigDigestAndEpoch(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _CommitStore.Contract.LatestConfigDigestAndEpoch(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CommitStore.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 (_CommitStore *CommitStoreSession) Owner() (common.Address, error) { - return _CommitStore.Contract.Owner(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) Owner() (common.Address, error) { - return _CommitStore.Contract.Owner(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) Paused(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "paused") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) Paused() (bool, error) { - return _CommitStore.Contract.Paused(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) Paused() (bool, error) { - return _CommitStore.Contract.Paused(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) TypeAndVersion() (string, error) { - return _CommitStore.Contract.TypeAndVersion(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCallerSession) TypeAndVersion() (string, error) { - return _CommitStore.Contract.TypeAndVersion(&_CommitStore.CallOpts) -} - -func (_CommitStore *CommitStoreCaller) Verify(opts *bind.CallOpts, hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) { - var out []interface{} - err := _CommitStore.contract.Call(opts, &out, "verify", hashedLeaves, proofs, proofFlagBits) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_CommitStore *CommitStoreSession) Verify(hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) { - return _CommitStore.Contract.Verify(&_CommitStore.CallOpts, hashedLeaves, proofs, proofFlagBits) -} - -func (_CommitStore *CommitStoreCallerSession) Verify(hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) { - return _CommitStore.Contract.Verify(&_CommitStore.CallOpts, hashedLeaves, proofs, proofFlagBits) -} - -func (_CommitStore *CommitStoreTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "acceptOwnership") -} - -func (_CommitStore *CommitStoreSession) AcceptOwnership() (*types.Transaction, error) { - return _CommitStore.Contract.AcceptOwnership(&_CommitStore.TransactOpts) -} - -func (_CommitStore *CommitStoreTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _CommitStore.Contract.AcceptOwnership(&_CommitStore.TransactOpts) -} - -func (_CommitStore *CommitStoreTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "pause") -} - -func (_CommitStore *CommitStoreSession) Pause() (*types.Transaction, error) { - return _CommitStore.Contract.Pause(&_CommitStore.TransactOpts) -} - -func (_CommitStore *CommitStoreTransactorSession) Pause() (*types.Transaction, error) { - return _CommitStore.Contract.Pause(&_CommitStore.TransactOpts) -} - -func (_CommitStore *CommitStoreTransactor) ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset [][32]byte) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "resetUnblessedRoots", rootToReset) -} - -func (_CommitStore *CommitStoreSession) ResetUnblessedRoots(rootToReset [][32]byte) (*types.Transaction, error) { - return _CommitStore.Contract.ResetUnblessedRoots(&_CommitStore.TransactOpts, rootToReset) -} - -func (_CommitStore *CommitStoreTransactorSession) ResetUnblessedRoots(rootToReset [][32]byte) (*types.Transaction, error) { - return _CommitStore.Contract.ResetUnblessedRoots(&_CommitStore.TransactOpts, rootToReset) -} - -func (_CommitStore *CommitStoreTransactor) SetLatestPriceEpochAndRound(opts *bind.TransactOpts, latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "setLatestPriceEpochAndRound", latestPriceEpochAndRound) -} - -func (_CommitStore *CommitStoreSession) SetLatestPriceEpochAndRound(latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStore.Contract.SetLatestPriceEpochAndRound(&_CommitStore.TransactOpts, latestPriceEpochAndRound) -} - -func (_CommitStore *CommitStoreTransactorSession) SetLatestPriceEpochAndRound(latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStore.Contract.SetLatestPriceEpochAndRound(&_CommitStore.TransactOpts, latestPriceEpochAndRound) -} - -func (_CommitStore *CommitStoreTransactor) SetMinSeqNr(opts *bind.TransactOpts, minSeqNr uint64) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "setMinSeqNr", minSeqNr) -} - -func (_CommitStore *CommitStoreSession) SetMinSeqNr(minSeqNr uint64) (*types.Transaction, error) { - return _CommitStore.Contract.SetMinSeqNr(&_CommitStore.TransactOpts, minSeqNr) -} - -func (_CommitStore *CommitStoreTransactorSession) SetMinSeqNr(minSeqNr uint64) (*types.Transaction, error) { - return _CommitStore.Contract.SetMinSeqNr(&_CommitStore.TransactOpts, minSeqNr) -} - -func (_CommitStore *CommitStoreTransactor) SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "setOCR2Config", signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_CommitStore *CommitStoreSession) SetOCR2Config(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _CommitStore.Contract.SetOCR2Config(&_CommitStore.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_CommitStore *CommitStoreTransactorSession) SetOCR2Config(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _CommitStore.Contract.SetOCR2Config(&_CommitStore.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_CommitStore *CommitStoreTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "transferOwnership", to) -} - -func (_CommitStore *CommitStoreSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CommitStore.Contract.TransferOwnership(&_CommitStore.TransactOpts, to) -} - -func (_CommitStore *CommitStoreTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CommitStore.Contract.TransferOwnership(&_CommitStore.TransactOpts, to) -} - -func (_CommitStore *CommitStoreTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) -} - -func (_CommitStore *CommitStoreSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _CommitStore.Contract.Transmit(&_CommitStore.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_CommitStore *CommitStoreTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _CommitStore.Contract.Transmit(&_CommitStore.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_CommitStore *CommitStoreTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStore.contract.Transact(opts, "unpause") -} - -func (_CommitStore *CommitStoreSession) Unpause() (*types.Transaction, error) { - return _CommitStore.Contract.Unpause(&_CommitStore.TransactOpts) -} - -func (_CommitStore *CommitStoreTransactorSession) Unpause() (*types.Transaction, error) { - return _CommitStore.Contract.Unpause(&_CommitStore.TransactOpts) -} - -type CommitStoreConfigSetIterator struct { - Event *CommitStoreConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreConfigSet) - 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(CommitStoreConfigSet) - 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 *CommitStoreConfigSetIterator) Error() error { - return it.fail -} - -func (it *CommitStoreConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreConfigSet struct { - StaticConfig CommitStoreStaticConfig - DynamicConfig CommitStoreDynamicConfig - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterConfigSet(opts *bind.FilterOpts) (*CommitStoreConfigSetIterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &CommitStoreConfigSetIterator{contract: _CommitStore.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CommitStoreConfigSet) (event.Subscription, error) { - - logs, sub, err := _CommitStore.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(CommitStoreConfigSet) - if err := _CommitStore.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 (_CommitStore *CommitStoreFilterer) ParseConfigSet(log types.Log) (*CommitStoreConfigSet, error) { - event := new(CommitStoreConfigSet) - if err := _CommitStore.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreConfigSet0Iterator struct { - Event *CommitStoreConfigSet0 - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreConfigSet0Iterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreConfigSet0) - 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(CommitStoreConfigSet0) - 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 *CommitStoreConfigSet0Iterator) Error() error { - return it.fail -} - -func (it *CommitStoreConfigSet0Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreConfigSet0 struct { - PreviousConfigBlockNumber uint32 - ConfigDigest [32]byte - ConfigCount uint64 - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterConfigSet0(opts *bind.FilterOpts) (*CommitStoreConfigSet0Iterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "ConfigSet0") - if err != nil { - return nil, err - } - return &CommitStoreConfigSet0Iterator{contract: _CommitStore.contract, event: "ConfigSet0", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *CommitStoreConfigSet0) (event.Subscription, error) { - - logs, sub, err := _CommitStore.contract.WatchLogs(opts, "ConfigSet0") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreConfigSet0) - if err := _CommitStore.contract.UnpackLog(event, "ConfigSet0", 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 (_CommitStore *CommitStoreFilterer) ParseConfigSet0(log types.Log) (*CommitStoreConfigSet0, error) { - event := new(CommitStoreConfigSet0) - if err := _CommitStore.contract.UnpackLog(event, "ConfigSet0", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreOwnershipTransferRequestedIterator struct { - Event *CommitStoreOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreOwnershipTransferRequested) - 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(CommitStoreOwnershipTransferRequested) - 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 *CommitStoreOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreOwnershipTransferRequestedIterator, 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 := _CommitStore.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &CommitStoreOwnershipTransferRequestedIterator{contract: _CommitStore.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CommitStoreOwnershipTransferRequested, 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 := _CommitStore.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(CommitStoreOwnershipTransferRequested) - if err := _CommitStore.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 (_CommitStore *CommitStoreFilterer) ParseOwnershipTransferRequested(log types.Log) (*CommitStoreOwnershipTransferRequested, error) { - event := new(CommitStoreOwnershipTransferRequested) - if err := _CommitStore.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreOwnershipTransferredIterator struct { - Event *CommitStoreOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreOwnershipTransferred) - 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(CommitStoreOwnershipTransferred) - 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 *CommitStoreOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *CommitStoreOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreOwnershipTransferredIterator, 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 := _CommitStore.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &CommitStoreOwnershipTransferredIterator{contract: _CommitStore.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CommitStoreOwnershipTransferred, 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 := _CommitStore.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(CommitStoreOwnershipTransferred) - if err := _CommitStore.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 (_CommitStore *CommitStoreFilterer) ParseOwnershipTransferred(log types.Log) (*CommitStoreOwnershipTransferred, error) { - event := new(CommitStoreOwnershipTransferred) - if err := _CommitStore.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStorePausedIterator struct { - Event *CommitStorePaused - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStorePausedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStorePaused) - 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(CommitStorePaused) - 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 *CommitStorePausedIterator) Error() error { - return it.fail -} - -func (it *CommitStorePausedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStorePaused struct { - Account common.Address - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterPaused(opts *bind.FilterOpts) (*CommitStorePausedIterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "Paused") - if err != nil { - return nil, err - } - return &CommitStorePausedIterator{contract: _CommitStore.contract, event: "Paused", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *CommitStorePaused) (event.Subscription, error) { - - logs, sub, err := _CommitStore.contract.WatchLogs(opts, "Paused") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStorePaused) - if err := _CommitStore.contract.UnpackLog(event, "Paused", 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 (_CommitStore *CommitStoreFilterer) ParsePaused(log types.Log) (*CommitStorePaused, error) { - event := new(CommitStorePaused) - if err := _CommitStore.contract.UnpackLog(event, "Paused", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreReportAcceptedIterator struct { - Event *CommitStoreReportAccepted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreReportAcceptedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreReportAccepted) - 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(CommitStoreReportAccepted) - 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 *CommitStoreReportAcceptedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreReportAcceptedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreReportAccepted struct { - Report CommitStoreCommitReport - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterReportAccepted(opts *bind.FilterOpts) (*CommitStoreReportAcceptedIterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "ReportAccepted") - if err != nil { - return nil, err - } - return &CommitStoreReportAcceptedIterator{contract: _CommitStore.contract, event: "ReportAccepted", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchReportAccepted(opts *bind.WatchOpts, sink chan<- *CommitStoreReportAccepted) (event.Subscription, error) { - - logs, sub, err := _CommitStore.contract.WatchLogs(opts, "ReportAccepted") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreReportAccepted) - if err := _CommitStore.contract.UnpackLog(event, "ReportAccepted", 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 (_CommitStore *CommitStoreFilterer) ParseReportAccepted(log types.Log) (*CommitStoreReportAccepted, error) { - event := new(CommitStoreReportAccepted) - if err := _CommitStore.contract.UnpackLog(event, "ReportAccepted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreRootRemovedIterator struct { - Event *CommitStoreRootRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreRootRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreRootRemoved) - 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(CommitStoreRootRemoved) - 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 *CommitStoreRootRemovedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreRootRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreRootRemoved struct { - Root [32]byte - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterRootRemoved(opts *bind.FilterOpts) (*CommitStoreRootRemovedIterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "RootRemoved") - if err != nil { - return nil, err - } - return &CommitStoreRootRemovedIterator{contract: _CommitStore.contract, event: "RootRemoved", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *CommitStoreRootRemoved) (event.Subscription, error) { - - logs, sub, err := _CommitStore.contract.WatchLogs(opts, "RootRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreRootRemoved) - if err := _CommitStore.contract.UnpackLog(event, "RootRemoved", 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 (_CommitStore *CommitStoreFilterer) ParseRootRemoved(log types.Log) (*CommitStoreRootRemoved, error) { - event := new(CommitStoreRootRemoved) - if err := _CommitStore.contract.UnpackLog(event, "RootRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreTransmittedIterator struct { - Event *CommitStoreTransmitted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreTransmittedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreTransmitted) - 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(CommitStoreTransmitted) - 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 *CommitStoreTransmittedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreTransmittedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreTransmitted struct { - ConfigDigest [32]byte - Epoch uint32 - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterTransmitted(opts *bind.FilterOpts) (*CommitStoreTransmittedIterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "Transmitted") - if err != nil { - return nil, err - } - return &CommitStoreTransmittedIterator{contract: _CommitStore.contract, event: "Transmitted", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *CommitStoreTransmitted) (event.Subscription, error) { - - logs, sub, err := _CommitStore.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(CommitStoreTransmitted) - if err := _CommitStore.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 (_CommitStore *CommitStoreFilterer) ParseTransmitted(log types.Log) (*CommitStoreTransmitted, error) { - event := new(CommitStoreTransmitted) - if err := _CommitStore.contract.UnpackLog(event, "Transmitted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreUnpausedIterator struct { - Event *CommitStoreUnpaused - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreUnpausedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreUnpaused) - 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(CommitStoreUnpaused) - 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 *CommitStoreUnpausedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreUnpausedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreUnpaused struct { - Account common.Address - Raw types.Log -} - -func (_CommitStore *CommitStoreFilterer) FilterUnpaused(opts *bind.FilterOpts) (*CommitStoreUnpausedIterator, error) { - - logs, sub, err := _CommitStore.contract.FilterLogs(opts, "Unpaused") - if err != nil { - return nil, err - } - return &CommitStoreUnpausedIterator{contract: _CommitStore.contract, event: "Unpaused", logs: logs, sub: sub}, nil -} - -func (_CommitStore *CommitStoreFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *CommitStoreUnpaused) (event.Subscription, error) { - - logs, sub, err := _CommitStore.contract.WatchLogs(opts, "Unpaused") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreUnpaused) - if err := _CommitStore.contract.UnpackLog(event, "Unpaused", 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 (_CommitStore *CommitStoreFilterer) ParseUnpaused(log types.Log) (*CommitStoreUnpaused, error) { - event := new(CommitStoreUnpaused) - if err := _CommitStore.contract.UnpackLog(event, "Unpaused", 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 (_CommitStore *CommitStore) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _CommitStore.abi.Events["ConfigSet"].ID: - return _CommitStore.ParseConfigSet(log) - case _CommitStore.abi.Events["ConfigSet0"].ID: - return _CommitStore.ParseConfigSet0(log) - case _CommitStore.abi.Events["OwnershipTransferRequested"].ID: - return _CommitStore.ParseOwnershipTransferRequested(log) - case _CommitStore.abi.Events["OwnershipTransferred"].ID: - return _CommitStore.ParseOwnershipTransferred(log) - case _CommitStore.abi.Events["Paused"].ID: - return _CommitStore.ParsePaused(log) - case _CommitStore.abi.Events["ReportAccepted"].ID: - return _CommitStore.ParseReportAccepted(log) - case _CommitStore.abi.Events["RootRemoved"].ID: - return _CommitStore.ParseRootRemoved(log) - case _CommitStore.abi.Events["Transmitted"].ID: - return _CommitStore.ParseTransmitted(log) - case _CommitStore.abi.Events["Unpaused"].ID: - return _CommitStore.ParseUnpaused(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (CommitStoreConfigSet) Topic() common.Hash { - return common.HexToHash("0xc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec3") -} - -func (CommitStoreConfigSet0) Topic() common.Hash { - return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") -} - -func (CommitStoreOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (CommitStoreOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (CommitStorePaused) Topic() common.Hash { - return common.HexToHash("0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258") -} - -func (CommitStoreReportAccepted) Topic() common.Hash { - return common.HexToHash("0xe81b49e583122eb290c46fc255c962b9a2dec468816c00fb7a2e6ebc42dc92d4") -} - -func (CommitStoreRootRemoved) Topic() common.Hash { - return common.HexToHash("0x202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12") -} - -func (CommitStoreTransmitted) Topic() common.Hash { - return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") -} - -func (CommitStoreUnpaused) Topic() common.Hash { - return common.HexToHash("0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa") -} - -func (_CommitStore *CommitStore) Address() common.Address { - return _CommitStore.address -} - -type CommitStoreInterface interface { - GetDynamicConfig(opts *bind.CallOpts) (CommitStoreDynamicConfig, error) - - GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) - - GetLatestPriceEpochAndRound(opts *bind.CallOpts) (uint64, error) - - GetMerkleRoot(opts *bind.CallOpts, root [32]byte) (*big.Int, error) - - GetStaticConfig(opts *bind.CallOpts) (CommitStoreStaticConfig, error) - - GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) - - IsARMHealthy(opts *bind.CallOpts) (bool, error) - - IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) - - IsUnpausedAndARMHealthy(opts *bind.CallOpts) (bool, error) - - LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) - - LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - Paused(opts *bind.CallOpts) (bool, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - Verify(opts *bind.CallOpts, hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - Pause(opts *bind.TransactOpts) (*types.Transaction, error) - - ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset [][32]byte) (*types.Transaction, error) - - SetLatestPriceEpochAndRound(opts *bind.TransactOpts, latestPriceEpochAndRound *big.Int) (*types.Transaction, error) - - SetMinSeqNr(opts *bind.TransactOpts, minSeqNr uint64) (*types.Transaction, error) - - SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - - Unpause(opts *bind.TransactOpts) (*types.Transaction, error) - - FilterConfigSet(opts *bind.FilterOpts) (*CommitStoreConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CommitStoreConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*CommitStoreConfigSet, error) - - FilterConfigSet0(opts *bind.FilterOpts) (*CommitStoreConfigSet0Iterator, error) - - WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *CommitStoreConfigSet0) (event.Subscription, error) - - ParseConfigSet0(log types.Log) (*CommitStoreConfigSet0, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CommitStoreOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*CommitStoreOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CommitStoreOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*CommitStoreOwnershipTransferred, error) - - FilterPaused(opts *bind.FilterOpts) (*CommitStorePausedIterator, error) - - WatchPaused(opts *bind.WatchOpts, sink chan<- *CommitStorePaused) (event.Subscription, error) - - ParsePaused(log types.Log) (*CommitStorePaused, error) - - FilterReportAccepted(opts *bind.FilterOpts) (*CommitStoreReportAcceptedIterator, error) - - WatchReportAccepted(opts *bind.WatchOpts, sink chan<- *CommitStoreReportAccepted) (event.Subscription, error) - - ParseReportAccepted(log types.Log) (*CommitStoreReportAccepted, error) - - FilterRootRemoved(opts *bind.FilterOpts) (*CommitStoreRootRemovedIterator, error) - - WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *CommitStoreRootRemoved) (event.Subscription, error) - - ParseRootRemoved(log types.Log) (*CommitStoreRootRemoved, error) - - FilterTransmitted(opts *bind.FilterOpts) (*CommitStoreTransmittedIterator, error) - - WatchTransmitted(opts *bind.WatchOpts, sink chan<- *CommitStoreTransmitted) (event.Subscription, error) - - ParseTransmitted(log types.Log) (*CommitStoreTransmitted, error) - - FilterUnpaused(opts *bind.FilterOpts) (*CommitStoreUnpausedIterator, error) - - WatchUnpaused(opts *bind.WatchOpts, sink chan<- *CommitStoreUnpaused) (event.Subscription, error) - - ParseUnpaused(log types.Log) (*CommitStoreUnpaused, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/commit_store_helper/commit_store_helper.go b/core/gethwrappers/ccip/generated/commit_store_helper/commit_store_helper.go index b314d6c75b4..3c9b22d67d5 100644 --- a/core/gethwrappers/ccip/generated/commit_store_helper/commit_store_helper.go +++ b/core/gethwrappers/ccip/generated/commit_store_helper/commit_store_helper.go @@ -69,7 +69,7 @@ type InternalTokenPriceUpdate struct { var CommitStoreHelperMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structCommitStore.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"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\":\"enumOCR2Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"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\":\"rmnProxy\",\"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\":false,\"internalType\":\"uint40\",\"name\":\"oldEpochAndRound\",\"type\":\"uint40\"},{\"indexed\":false,\"internalType\":\"uint40\",\"name\":\"newEpochAndRound\",\"type\":\"uint40\"}],\"name\":\"LatestPriceEpochAndRoundSet\",\"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\":\"uint64\",\"name\":\"oldSeqNum\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newSeqNum\",\"type\":\"uint64\"}],\"name\":\"SequenceNumberSet\",\"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\":\"rmnProxy\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isUnpausedAndNotCursed\",\"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\":\"bytes\",\"name\":\"commitReport\",\"type\":\"bytes\"},{\"internalType\":\"uint40\",\"name\":\"epochAndRound\",\"type\":\"uint40\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\"}]", - Bin: "0x61014060405260098054600165ff000000000160401b03191660011790553480156200002a57600080fd5b506040516200382a3803806200382a8339810160408190526200004d9162000274565b80600033808281620000a65760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d957620000d98162000194565b50505015156080524660a05260408101516001600160a01b0316158062000108575080516001600160401b0316155b806200011f575060208101516001600160401b0316155b8062000136575060608101516001600160a01b0316155b156200015557604051631fc5f15f60e11b815260040160405180910390fd5b80516001600160401b0390811660c05260208201511660e05260408101516001600160a01b039081166101005260609091015116610120525062000308565b336001600160a01b03821603620001ee5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009d565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160401b03811681146200025757600080fd5b919050565b80516001600160a01b03811681146200025757600080fd5b6000608082840312156200028757600080fd5b604051608081016001600160401b0381118282101715620002b857634e487b7160e01b600052604160045260246000fd5b604052620002c6836200023f565b8152620002d6602084016200023f565b6020820152620002e9604084016200025c565b6040820152620002fc606084016200025c565b60608201529392505050565b60805160a05160c05160e051610100516101205161348c6200039e6000396000818161026d015281816116f6015281816118a5015281816119cf0152611f5d0152600081816102310152611f36015260008181610201015281816116b00152818161198c0152611f0f0152600081816101d10152611ee00152600081816110f60152611142015260006111bd015261348c6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806379ba5097116100e3578063afcb95d71161008c578063f2fde38b11610066578063f2fde38b14610501578063f47a869014610514578063ff888fb11461052757600080fd5b8063afcb95d7146104c6578063b1dc65a4146104e6578063e89d039f146104f957600080fd5b80638da5cb5b116100bd5780638da5cb5b1461046b578063a7206cd614610493578063ad7a22f8146104b357600080fd5b806379ba50971461042b57806381ff7048146104335780638456cb591461046357600080fd5b806332048875116101455780635c975abb1161011f5780635c975abb146103af578063666cab8d146103d75780637437ff9f146103ec57600080fd5b806332048875146103745780633f4ba83a146103955780634120fccd1461039d57600080fd5b80631dc18e56116101765780631dc18e56146103395780631ef381741461034e57806329b980e41461036157600080fd5b806306285c691461019d57806310c374ed146102c0578063181f5a77146102f0575b600080fd5b6102aa60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102b791906125ac565b60405180910390f35b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102b7565b61032c6040518060400160405280601581526020017f436f6d6d697453746f726520312e352e302d646576000000000000000000000081525081565b6040516102b79190612669565b61034c6103473660046126df565b61053a565b005b61034c61035c366004612972565b61054a565b61034c61036f366004612a3f565b610c2e565b610387610382366004612a9f565b610cbe565b6040519081526020016102b7565b61034c610db4565b60095467ffffffffffffffff166102d7565b6009546d0100000000000000000000000000900460ff165b60405190151581526020016102b7565b6103df610e1a565b6040516102b79190612b65565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102b7565b61034c610e89565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102b7565b61034c610f86565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b7565b6103876104a1366004612b78565b6000908152600a602052604090205490565b61034c6104c1366004612b91565b610ff6565b6040805160018152600060208201819052918101919091526060016102b7565b61034c6104f4366004612bac565b611071565b6103c7611688565b61034c61050f366004612c63565b61179c565b61034c610522366004612c80565b6117b0565b6103c7610535366004612b78565b611842565b610545838383611916565b505050565b855185518560ff16601f8311156105995760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b60405180910390fd5b806000036105d65760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b8183146106125760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b61061d816003612d61565b83116106585760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b610660611d7f565b61066986611e02565b60065460005b8181101561075d57600560006006838154811061068e5761068e612d78565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600780546005929190849081106106fe576106fe612d78565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161066f565b50895160005b81811015610ad65760008c828151811061077f5761077f612d78565b602002602001015190506000600281111561079c5761079c612cc2565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff1660028111156107db576107db612cc2565b146108155760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b73ffffffffffffffffffffffffffffffffffffffff8116610862576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561091257610912612cc2565b021790555090505060008c838151811061092e5761092e612d78565b602002602001015190506000600281111561094b5761094b612cc2565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561098a5761098a612cc2565b146109c45760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b73ffffffffffffffffffffffffffffffffffffffff8116610a11576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610ac157610ac1612cc2565b02179055509050505050806001019050610763565b508a51610aea9060069060208e01906124ee565b508951610afe9060079060208d01906124ee565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610b84914691309190600090610b569063ffffffff16612da7565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e611fb2565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610c1899989796959493929190612dca565b60405180910390a1505050505050505050505050565b610c36611d7f565b6009805464ffffffffff838116680100000000000000008181027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917ff0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf56545644491015b60405180910390a15050565b6009546000906d0100000000000000000000000000900460ff1615610d0f576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d8087878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a92508991829185019084908082843760009201919091525088925061205d915050565b9050610d8b81611842565b610d99576000915050610dab565b6000908152600a602052604090205490505b95945050505050565b610dbc611d7f565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60606007805480602002602001604051908101604052809291908181526020018280548015610e7f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e54575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610590565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f8e611d7f565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610e10565b610ffe611d7f565b6009805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000083168117909355604080519190921680825260208201939093527fea59e8027e41fda1525220008cf2416797405065eb21b0ebd417bfc6d361b8de9101610cb2565b611080878760208b0135611916565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146110f35780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610590565b467f000000000000000000000000000000000000000000000000000000000000000014611174576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610590565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f000000000000000000000000000000000000000000000000000000000000000015611216576002826020015183604001516111f79190612e60565b6112019190612e79565b61120c906001612e60565b60ff16905061122c565b6020820151611226906001612e60565b60ff1690505b868114611265576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86851461129e576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156112e1576112e1612cc2565b60028111156112f2576112f2612cc2565b905250905060028160200151600281111561130f5761130f612cc2565b14801561135657506007816000015160ff168154811061133157611331612d78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61138c576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600061139a866020612d61565b6113a5896020612d61565b6113b18c610144612ec2565b6113bb9190612ec2565b6113c59190612ec2565b9050368114611409576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610590565b5060008a8a60405161141c929190612ed5565b604051908190038120611433918e90602001612ee5565b604051602081830303815290604052805190602001209050611453612578565b8860005b818110156116775760006001858a846020811061147657611476612d78565b61148391901a601b612e60565b8f8f8681811061149557611495612d78565b905060200201358e8e878181106114ae576114ae612d78565b90506020020135604051600081526020016040526040516114eb949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561150d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff808216865293975091955092939284019161010090910416600281111561159057611590612cc2565b60028111156115a1576115a1612cc2565b90525090506001816020015160028111156115be576115be612cc2565b146115f5576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061160c5761160c612d78565b602002015115611648576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061166357611663612d78565b911515602090920201525050600101611457565b505050505050505050505050505050565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611752573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117769190612ef9565b15801561179757506009546d0100000000000000000000000000900460ff16155b905090565b6117a4611d7f565b6117ad8161237e565b50565b6117b8611d7f565b60005b818110156105455760008383838181106117d7576117d7612d78565b9050602002013590506117e981611842565b611839576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12906118309083815260200190565b60405180910390a15b506001016117bb565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa1580156118ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119109190612ef9565b92915050565b6009546d0100000000000000000000000000900460ff1615611964576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4f9190612ef9565b15611a86576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611a9483850185613012565b80515151909150151580611aad57508051602001515115155b15611be55760095464ffffffffff80841668010000000000000000909204161015611baa57600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f3937306f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90921691633937306f91611b6491600401613265565b600060405180830381600087803b158015611b7e57600080fd5b505af1158015611b92573d6000803e3d6000fd5b505050506040810151611ba55750505050565b611be5565b6040810151611be5576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff9081169116141580611c20575060208082015190810151905167ffffffffffffffff9182169116115b15611c5d5780602001516040517fbb1ae18d0000000000000000000000000000000000000000000000000000000081526004016105909190613278565b6040810151611c98576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a602052205415611ce1576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201510151611cf490600161329d565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517f291698c01aa71f912280535d88a00d2c59fb63530a3f5d0098560468acb9ebf590611d719083906132c5565b60405180910390a150505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611e00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610590565b565b600081806020019051810190611e189190613321565b805190915073ffffffffffffffffffffffffffffffffffffffff16611e69576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff90811682527f00000000000000000000000000000000000000000000000000000000000000001660208201527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec391610cb291849061336d565b6000808a8a8a8a8a8a8a8a8a604051602001611fd6999897969594939291906133ea565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b825182516000919081830361209e576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010182118015906120b257506101018111155b6120e8576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115612149576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003612176578660008151811061216457612164612d78565b60200260200101519350505050612377565b60008167ffffffffffffffff81111561219157612191612733565b6040519080825280602002602001820160405280156121ba578160200160208202803683370190505b50905060008080805b858110156122fd5760006001821b8b81160361221e5788851015612207578c5160018601958e9181106121f8576121f8612d78565b60200260200101519050612240565b85516001850194879181106121f8576121f8612d78565b8b5160018401938d91811061223557612235612d78565b602002602001015190505b600089861015612270578d5160018701968f91811061226157612261612d78565b60200260200101519050612292565b865160018601958891811061228757612287612d78565b602002602001015190505b828511156122cc576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122d68282612473565b8784815181106122e8576122e8612d78565b602090810291909101015250506001016121c3565b50600185038214801561230f57508683145b801561231a57508581145b612350576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600186038151811061236557612365612d78565b60200260200101519750505050505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036123fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610590565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008183106124b55760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120612377565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120612377565b828054828255906000526020600020908101928215612568579160200282015b8281111561256857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061250e565b50612574929150612597565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b808211156125745760008155600101612598565b60808101611910828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b8181101561262b5760208185018101518683018201520161260f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006123776020830184612605565b60008083601f84011261268e57600080fd5b50813567ffffffffffffffff8111156126a657600080fd5b6020830191508360208285010111156126be57600080fd5b9250929050565b803564ffffffffff811681146126da57600080fd5b919050565b6000806000604084860312156126f457600080fd5b833567ffffffffffffffff81111561270b57600080fd5b6127178682870161267c565b909450925061272a9050602085016126c5565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561278557612785612733565b60405290565b6040516060810167ffffffffffffffff8111828210171561278557612785612733565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127f5576127f5612733565b604052919050565b600067ffffffffffffffff82111561281757612817612733565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146117ad57600080fd5b600082601f83011261285457600080fd5b81356020612869612864836127fd565b6127ae565b8083825260208201915060208460051b87010193508684111561288b57600080fd5b602086015b848110156128b05780356128a381612821565b8352918301918301612890565b509695505050505050565b803560ff811681146126da57600080fd5b600082601f8301126128dd57600080fd5b813567ffffffffffffffff8111156128f7576128f7612733565b61292860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016127ae565b81815284602083860101111561293d57600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146126da57600080fd5b60008060008060008060c0878903121561298b57600080fd5b863567ffffffffffffffff808211156129a357600080fd5b6129af8a838b01612843565b975060208901359150808211156129c557600080fd5b6129d18a838b01612843565b96506129df60408a016128bb565b955060608901359150808211156129f557600080fd5b612a018a838b016128cc565b9450612a0f60808a0161295a565b935060a0890135915080821115612a2557600080fd5b50612a3289828a016128cc565b9150509295509295509295565b600060208284031215612a5157600080fd5b612377826126c5565b60008083601f840112612a6c57600080fd5b50813567ffffffffffffffff811115612a8457600080fd5b6020830191508360208260051b85010111156126be57600080fd5b600080600080600060608688031215612ab757600080fd5b853567ffffffffffffffff80821115612acf57600080fd5b612adb89838a01612a5a565b90975095506020880135915080821115612af457600080fd5b50612b0188828901612a5a565b96999598509660400135949350505050565b60008151808452602080850194506020840160005b83811015612b5a57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612b28565b509495945050505050565b6020815260006123776020830184612b13565b600060208284031215612b8a57600080fd5b5035919050565b600060208284031215612ba357600080fd5b6123778261295a565b60008060008060008060008060e0898b031215612bc857600080fd5b606089018a811115612bd957600080fd5b8998503567ffffffffffffffff80821115612bf357600080fd5b612bff8c838d0161267c565b909950975060808b0135915080821115612c1857600080fd5b612c248c838d01612a5a565b909750955060a08b0135915080821115612c3d57600080fd5b50612c4a8b828c01612a5a565b999c989b50969995989497949560c00135949350505050565b600060208284031215612c7557600080fd5b813561237781612821565b60008060208385031215612c9357600080fd5b823567ffffffffffffffff811115612caa57600080fd5b612cb685828601612a5a565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310612d2c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761191057611910612d32565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103612dc057612dc0612d32565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612dfa8184018a612b13565b90508281036080840152612e0e8189612b13565b905060ff871660a084015282810360c0840152612e2b8187612605565b905067ffffffffffffffff851660e0840152828103610100840152612e508185612605565b9c9b505050505050505050505050565b60ff818116838216019081111561191057611910612d32565b600060ff831680612eb3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b8082018082111561191057611910612d32565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612f0b57600080fd5b8151801515811461237757600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146126da57600080fd5b600082601f830112612f5857600080fd5b81356020612f68612864836127fd565b82815260069290921b84018101918181019086841115612f8757600080fd5b8286015b848110156128b05760408189031215612fa45760008081fd5b612fac612762565b612fb58261295a565b8152612fc2858301612f1b565b81860152835291830191604001612f8b565b600060408284031215612fe657600080fd5b612fee612762565b9050612ff98261295a565b81526130076020830161295a565b602082015292915050565b6000602080838503121561302557600080fd5b823567ffffffffffffffff8082111561303d57600080fd5b908401906080828703121561305157600080fd5b61305961278b565b82358281111561306857600080fd5b8301604081890381131561307b57600080fd5b613083612762565b82358581111561309257600080fd5b8301601f81018b136130a357600080fd5b80356130b1612864826127fd565b81815260069190911b8201890190898101908d8311156130d057600080fd5b928a01925b828410156131205785848f0312156130ed5760008081fd5b6130f5612762565b843561310081612821565b815261310d858d01612f1b565b818d0152825292850192908a01906130d5565b84525050508287013591508482111561313857600080fd5b6131448a838501612f47565b81880152835250613159905087848601612fd4565b93810193909352506060013560408201529392505050565b805160408084528151848201819052600092602091908201906060870190855b818110156131ea578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101613191565b50508583015187820388850152805180835290840192506000918401905b80831015613259578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685830152928401926001929092019190850190613208565b50979650505050505050565b6020815260006123776020830184613171565b604081016119108284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff8181168382160190808211156132be576132be612d32565b5092915050565b6020815260008251608060208401526132e160a0840182613171565b9050602084015161330c6040850182805167ffffffffffffffff908116835260209182015116910152565b50604084015160808401528091505092915050565b60006020828403121561333357600080fd5b6040516020810181811067ffffffffffffffff8211171561335657613356612733565b604052825161336481612821565b81529392505050565b60a081016133c6828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526134318285018b612b13565b91508382036080850152613445828a612b13565b915060ff881660a085015283820360c08501526134628288612605565b90861660e08501528381036101008501529050612e50818561260556fea164736f6c6343000818000a", + Bin: "0x61014060405260098054600165ff000000000160401b03191660011790553480156200002a57600080fd5b506040516200382a3803806200382a8339810160408190526200004d9162000274565b80600033808281620000a65760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d957620000d98162000194565b50505015156080524660a05260408101516001600160a01b0316158062000108575080516001600160401b0316155b806200011f575060208101516001600160401b0316155b8062000136575060608101516001600160a01b0316155b156200015557604051631fc5f15f60e11b815260040160405180910390fd5b80516001600160401b0390811660c05260208201511660e05260408101516001600160a01b039081166101005260609091015116610120525062000308565b336001600160a01b03821603620001ee5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009d565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160401b03811681146200025757600080fd5b919050565b80516001600160a01b03811681146200025757600080fd5b6000608082840312156200028757600080fd5b604051608081016001600160401b0381118282101715620002b857634e487b7160e01b600052604160045260246000fd5b604052620002c6836200023f565b8152620002d6602084016200023f565b6020820152620002e9604084016200025c565b6040820152620002fc606084016200025c565b60608201529392505050565b60805160a05160c05160e051610100516101205161348c6200039e6000396000818161026d015281816116f6015281816118a5015281816119cf0152611f5d0152600081816102310152611f36015260008181610201015281816116b00152818161198c0152611f0f0152600081816101d10152611ee00152600081816110f60152611142015260006111bd015261348c6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806379ba5097116100e3578063afcb95d71161008c578063f2fde38b11610066578063f2fde38b14610501578063f47a869014610514578063ff888fb11461052757600080fd5b8063afcb95d7146104c6578063b1dc65a4146104e6578063e89d039f146104f957600080fd5b80638da5cb5b116100bd5780638da5cb5b1461046b578063a7206cd614610493578063ad7a22f8146104b357600080fd5b806379ba50971461042b57806381ff7048146104335780638456cb591461046357600080fd5b806332048875116101455780635c975abb1161011f5780635c975abb146103af578063666cab8d146103d75780637437ff9f146103ec57600080fd5b806332048875146103745780633f4ba83a146103955780634120fccd1461039d57600080fd5b80631dc18e56116101765780631dc18e56146103395780631ef381741461034e57806329b980e41461036157600080fd5b806306285c691461019d57806310c374ed146102c0578063181f5a77146102f0575b600080fd5b6102aa60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102b791906125ac565b60405180910390f35b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102b7565b61032c6040518060400160405280601181526020017f436f6d6d697453746f726520312e352e3000000000000000000000000000000081525081565b6040516102b79190612669565b61034c6103473660046126df565b61053a565b005b61034c61035c366004612972565b61054a565b61034c61036f366004612a3f565b610c2e565b610387610382366004612a9f565b610cbe565b6040519081526020016102b7565b61034c610db4565b60095467ffffffffffffffff166102d7565b6009546d0100000000000000000000000000900460ff165b60405190151581526020016102b7565b6103df610e1a565b6040516102b79190612b65565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102b7565b61034c610e89565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102b7565b61034c610f86565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b7565b6103876104a1366004612b78565b6000908152600a602052604090205490565b61034c6104c1366004612b91565b610ff6565b6040805160018152600060208201819052918101919091526060016102b7565b61034c6104f4366004612bac565b611071565b6103c7611688565b61034c61050f366004612c63565b61179c565b61034c610522366004612c80565b6117b0565b6103c7610535366004612b78565b611842565b610545838383611916565b505050565b855185518560ff16601f8311156105995760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b60405180910390fd5b806000036105d65760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b8183146106125760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b61061d816003612d61565b83116106585760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b610660611d7f565b61066986611e02565b60065460005b8181101561075d57600560006006838154811061068e5761068e612d78565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600780546005929190849081106106fe576106fe612d78565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161066f565b50895160005b81811015610ad65760008c828151811061077f5761077f612d78565b602002602001015190506000600281111561079c5761079c612cc2565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff1660028111156107db576107db612cc2565b146108155760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b73ffffffffffffffffffffffffffffffffffffffff8116610862576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561091257610912612cc2565b021790555090505060008c838151811061092e5761092e612d78565b602002602001015190506000600281111561094b5761094b612cc2565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561098a5761098a612cc2565b146109c45760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105909190612cf1565b73ffffffffffffffffffffffffffffffffffffffff8116610a11576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610ac157610ac1612cc2565b02179055509050505050806001019050610763565b508a51610aea9060069060208e01906124ee565b508951610afe9060079060208d01906124ee565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610b84914691309190600090610b569063ffffffff16612da7565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e611fb2565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610c1899989796959493929190612dca565b60405180910390a1505050505050505050505050565b610c36611d7f565b6009805464ffffffffff838116680100000000000000008181027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917ff0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf56545644491015b60405180910390a15050565b6009546000906d0100000000000000000000000000900460ff1615610d0f576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d8087878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a92508991829185019084908082843760009201919091525088925061205d915050565b9050610d8b81611842565b610d99576000915050610dab565b6000908152600a602052604090205490505b95945050505050565b610dbc611d7f565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60606007805480602002602001604051908101604052809291908181526020018280548015610e7f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e54575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610590565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f8e611d7f565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610e10565b610ffe611d7f565b6009805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000083168117909355604080519190921680825260208201939093527fea59e8027e41fda1525220008cf2416797405065eb21b0ebd417bfc6d361b8de9101610cb2565b611080878760208b0135611916565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146110f35780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610590565b467f000000000000000000000000000000000000000000000000000000000000000014611174576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610590565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f000000000000000000000000000000000000000000000000000000000000000015611216576002826020015183604001516111f79190612e60565b6112019190612e79565b61120c906001612e60565b60ff16905061122c565b6020820151611226906001612e60565b60ff1690505b868114611265576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86851461129e576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156112e1576112e1612cc2565b60028111156112f2576112f2612cc2565b905250905060028160200151600281111561130f5761130f612cc2565b14801561135657506007816000015160ff168154811061133157611331612d78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61138c576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600061139a866020612d61565b6113a5896020612d61565b6113b18c610144612ec2565b6113bb9190612ec2565b6113c59190612ec2565b9050368114611409576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610590565b5060008a8a60405161141c929190612ed5565b604051908190038120611433918e90602001612ee5565b604051602081830303815290604052805190602001209050611453612578565b8860005b818110156116775760006001858a846020811061147657611476612d78565b61148391901a601b612e60565b8f8f8681811061149557611495612d78565b905060200201358e8e878181106114ae576114ae612d78565b90506020020135604051600081526020016040526040516114eb949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561150d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff808216865293975091955092939284019161010090910416600281111561159057611590612cc2565b60028111156115a1576115a1612cc2565b90525090506001816020015160028111156115be576115be612cc2565b146115f5576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061160c5761160c612d78565b602002015115611648576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061166357611663612d78565b911515602090920201525050600101611457565b505050505050505050505050505050565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611752573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117769190612ef9565b15801561179757506009546d0100000000000000000000000000900460ff16155b905090565b6117a4611d7f565b6117ad8161237e565b50565b6117b8611d7f565b60005b818110156105455760008383838181106117d7576117d7612d78565b9050602002013590506117e981611842565b611839576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12906118309083815260200190565b60405180910390a15b506001016117bb565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa1580156118ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119109190612ef9565b92915050565b6009546d0100000000000000000000000000900460ff1615611964576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4f9190612ef9565b15611a86576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611a9483850185613012565b80515151909150151580611aad57508051602001515115155b15611be55760095464ffffffffff80841668010000000000000000909204161015611baa57600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f3937306f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90921691633937306f91611b6491600401613265565b600060405180830381600087803b158015611b7e57600080fd5b505af1158015611b92573d6000803e3d6000fd5b505050506040810151611ba55750505050565b611be5565b6040810151611be5576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff9081169116141580611c20575060208082015190810151905167ffffffffffffffff9182169116115b15611c5d5780602001516040517fbb1ae18d0000000000000000000000000000000000000000000000000000000081526004016105909190613278565b6040810151611c98576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a602052205415611ce1576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201510151611cf490600161329d565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517f291698c01aa71f912280535d88a00d2c59fb63530a3f5d0098560468acb9ebf590611d719083906132c5565b60405180910390a150505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611e00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610590565b565b600081806020019051810190611e189190613321565b805190915073ffffffffffffffffffffffffffffffffffffffff16611e69576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff90811682527f00000000000000000000000000000000000000000000000000000000000000001660208201527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec391610cb291849061336d565b6000808a8a8a8a8a8a8a8a8a604051602001611fd6999897969594939291906133ea565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b825182516000919081830361209e576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010182118015906120b257506101018111155b6120e8576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115612149576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003612176578660008151811061216457612164612d78565b60200260200101519350505050612377565b60008167ffffffffffffffff81111561219157612191612733565b6040519080825280602002602001820160405280156121ba578160200160208202803683370190505b50905060008080805b858110156122fd5760006001821b8b81160361221e5788851015612207578c5160018601958e9181106121f8576121f8612d78565b60200260200101519050612240565b85516001850194879181106121f8576121f8612d78565b8b5160018401938d91811061223557612235612d78565b602002602001015190505b600089861015612270578d5160018701968f91811061226157612261612d78565b60200260200101519050612292565b865160018601958891811061228757612287612d78565b602002602001015190505b828511156122cc576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122d68282612473565b8784815181106122e8576122e8612d78565b602090810291909101015250506001016121c3565b50600185038214801561230f57508683145b801561231a57508581145b612350576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600186038151811061236557612365612d78565b60200260200101519750505050505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036123fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610590565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008183106124b55760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120612377565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120612377565b828054828255906000526020600020908101928215612568579160200282015b8281111561256857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061250e565b50612574929150612597565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b808211156125745760008155600101612598565b60808101611910828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b8181101561262b5760208185018101518683018201520161260f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006123776020830184612605565b60008083601f84011261268e57600080fd5b50813567ffffffffffffffff8111156126a657600080fd5b6020830191508360208285010111156126be57600080fd5b9250929050565b803564ffffffffff811681146126da57600080fd5b919050565b6000806000604084860312156126f457600080fd5b833567ffffffffffffffff81111561270b57600080fd5b6127178682870161267c565b909450925061272a9050602085016126c5565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561278557612785612733565b60405290565b6040516060810167ffffffffffffffff8111828210171561278557612785612733565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127f5576127f5612733565b604052919050565b600067ffffffffffffffff82111561281757612817612733565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146117ad57600080fd5b600082601f83011261285457600080fd5b81356020612869612864836127fd565b6127ae565b8083825260208201915060208460051b87010193508684111561288b57600080fd5b602086015b848110156128b05780356128a381612821565b8352918301918301612890565b509695505050505050565b803560ff811681146126da57600080fd5b600082601f8301126128dd57600080fd5b813567ffffffffffffffff8111156128f7576128f7612733565b61292860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016127ae565b81815284602083860101111561293d57600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146126da57600080fd5b60008060008060008060c0878903121561298b57600080fd5b863567ffffffffffffffff808211156129a357600080fd5b6129af8a838b01612843565b975060208901359150808211156129c557600080fd5b6129d18a838b01612843565b96506129df60408a016128bb565b955060608901359150808211156129f557600080fd5b612a018a838b016128cc565b9450612a0f60808a0161295a565b935060a0890135915080821115612a2557600080fd5b50612a3289828a016128cc565b9150509295509295509295565b600060208284031215612a5157600080fd5b612377826126c5565b60008083601f840112612a6c57600080fd5b50813567ffffffffffffffff811115612a8457600080fd5b6020830191508360208260051b85010111156126be57600080fd5b600080600080600060608688031215612ab757600080fd5b853567ffffffffffffffff80821115612acf57600080fd5b612adb89838a01612a5a565b90975095506020880135915080821115612af457600080fd5b50612b0188828901612a5a565b96999598509660400135949350505050565b60008151808452602080850194506020840160005b83811015612b5a57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612b28565b509495945050505050565b6020815260006123776020830184612b13565b600060208284031215612b8a57600080fd5b5035919050565b600060208284031215612ba357600080fd5b6123778261295a565b60008060008060008060008060e0898b031215612bc857600080fd5b606089018a811115612bd957600080fd5b8998503567ffffffffffffffff80821115612bf357600080fd5b612bff8c838d0161267c565b909950975060808b0135915080821115612c1857600080fd5b612c248c838d01612a5a565b909750955060a08b0135915080821115612c3d57600080fd5b50612c4a8b828c01612a5a565b999c989b50969995989497949560c00135949350505050565b600060208284031215612c7557600080fd5b813561237781612821565b60008060208385031215612c9357600080fd5b823567ffffffffffffffff811115612caa57600080fd5b612cb685828601612a5a565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310612d2c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761191057611910612d32565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103612dc057612dc0612d32565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612dfa8184018a612b13565b90508281036080840152612e0e8189612b13565b905060ff871660a084015282810360c0840152612e2b8187612605565b905067ffffffffffffffff851660e0840152828103610100840152612e508185612605565b9c9b505050505050505050505050565b60ff818116838216019081111561191057611910612d32565b600060ff831680612eb3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b8082018082111561191057611910612d32565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612f0b57600080fd5b8151801515811461237757600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146126da57600080fd5b600082601f830112612f5857600080fd5b81356020612f68612864836127fd565b82815260069290921b84018101918181019086841115612f8757600080fd5b8286015b848110156128b05760408189031215612fa45760008081fd5b612fac612762565b612fb58261295a565b8152612fc2858301612f1b565b81860152835291830191604001612f8b565b600060408284031215612fe657600080fd5b612fee612762565b9050612ff98261295a565b81526130076020830161295a565b602082015292915050565b6000602080838503121561302557600080fd5b823567ffffffffffffffff8082111561303d57600080fd5b908401906080828703121561305157600080fd5b61305961278b565b82358281111561306857600080fd5b8301604081890381131561307b57600080fd5b613083612762565b82358581111561309257600080fd5b8301601f81018b136130a357600080fd5b80356130b1612864826127fd565b81815260069190911b8201890190898101908d8311156130d057600080fd5b928a01925b828410156131205785848f0312156130ed5760008081fd5b6130f5612762565b843561310081612821565b815261310d858d01612f1b565b818d0152825292850192908a01906130d5565b84525050508287013591508482111561313857600080fd5b6131448a838501612f47565b81880152835250613159905087848601612fd4565b93810193909352506060013560408201529392505050565b805160408084528151848201819052600092602091908201906060870190855b818110156131ea578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101613191565b50508583015187820388850152805180835290840192506000918401905b80831015613259578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685830152928401926001929092019190850190613208565b50979650505050505050565b6020815260006123776020830184613171565b604081016119108284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff8181168382160190808211156132be576132be612d32565b5092915050565b6020815260008251608060208401526132e160a0840182613171565b9050602084015161330c6040850182805167ffffffffffffffff908116835260209182015116910152565b50604084015160808401528091505092915050565b60006020828403121561333357600080fd5b6040516020810181811067ffffffffffffffff8211171561335657613356612733565b604052825161336481612821565b81529392505050565b60a081016133c6828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526134318285018b612b13565b91508382036080850152613445828a612b13565b915060ff881660a085015283820360c08501526134628288612605565b90861660e08501528381036101008501529050612e50818561260556fea164736f6c6343000818000a", } var CommitStoreHelperABI = CommitStoreHelperMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/commit_store_helper_1_0_0/commit_store_helper_1_0_0.go b/core/gethwrappers/ccip/generated/commit_store_helper_1_0_0/commit_store_helper_1_0_0.go deleted file mode 100644 index 5a1e15b2530..00000000000 --- a/core/gethwrappers/ccip/generated/commit_store_helper_1_0_0/commit_store_helper_1_0_0.go +++ /dev/null @@ -1,1966 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package commit_store_helper_1_0_0 - -import ( - "errors" - "fmt" - "math/big" - "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/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 CommitStoreCommitReport struct { - PriceUpdates InternalPriceUpdates - Interval CommitStoreInterval - MerkleRoot [32]byte -} - -type CommitStoreDynamicConfig struct { - PriceRegistry common.Address -} - -type CommitStoreInterval struct { - Min uint64 - Max uint64 -} - -type CommitStoreStaticConfig struct { - ChainSelector uint64 - SourceChainSelector uint64 - OnRamp common.Address - ArmProxy common.Address -} - -type InternalPriceUpdates struct { - TokenPriceUpdates []InternalTokenPriceUpdate - DestChainSelector uint64 - UsdPerUnitGas *big.Int -} - -type InternalTokenPriceUpdate struct { - SourceToken common.Address - UsdPerToken *big.Int -} - -var CommitStoreHelperMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"uint192\",\"name\":\"usdPerToken\",\"type\":\"uint192\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint192\",\"name\":\"usdPerUnitGas\",\"type\":\"uint192\"}],\"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\":\"bytes\",\"name\":\"commitReport\",\"type\":\"bytes\"},{\"internalType\":\"uint40\",\"name\":\"epochAndRound\",\"type\":\"uint40\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\"}]", - Bin: "0x61014060405260098054600165ff000000000160401b03191660011790553480156200002a57600080fd5b5060405162003824380380620038248339810160408190526200004d9162000274565b80600033808281620000a65760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d957620000d98162000194565b50505015156080524660a05260408101516001600160a01b0316158062000108575080516001600160401b0316155b806200011f575060208101516001600160401b0316155b8062000136575060608101516001600160a01b0316155b156200015557604051631fc5f15f60e11b815260040160405180910390fd5b80516001600160401b0390811660c05260208201511660e05260408101516001600160a01b039081166101005260609091015116610120525062000308565b336001600160a01b03821603620001ee5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009d565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160401b03811681146200025757600080fd5b919050565b80516001600160a01b03811681146200025757600080fd5b6000608082840312156200028757600080fd5b604051608081016001600160401b0381118282101715620002b857634e487b7160e01b600052604160045260246000fd5b604052620002c6836200023f565b8152620002d6602084016200023f565b6020820152620002e9604084016200025c565b6040820152620002fc606084016200025c565b60608201529392505050565b60805160a05160c05160e051610100516101205161348d620003976000396000818161027801528181610555015281816111a1015281816119c801528181611a89015261202d01526000818161023c015261200601526000818161020c0152611fdf0152600081816101dc0152611fb001526000818161131c0152611368015260006113e3015261348d6000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80637437ff9f116100ee578063a7206cd611610097578063b1dc65a411610071578063b1dc65a414610505578063f2fde38b14610518578063f47a86901461052b578063ff888fb11461053e57600080fd5b8063a7206cd6146104b2578063ad7a22f8146104d2578063afcb95d7146104e557600080fd5b80638456cb59116100c85780638456cb591461047a5780638da5cb5b146104825780638db94e44146104aa57600080fd5b80637437ff9f1461040357806379ba50971461044257806381ff70481461044a57600080fd5b806329b980e4116101505780634120fccd1161012a5780634120fccd146103c05780635c975abb146103d2578063666cab8d146103ee57600080fd5b806329b980e41461038457806332048875146103975780633f4ba83a146103b857600080fd5b8063181f5a7711610181578063181f5a77146103135780631dc18e561461035c5780631ef381741461037157600080fd5b806306285c69146101a85780630a6cd30d146102cb57806310c374ed146102e3575b600080fd5b6102b560408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102c29190612688565b60405180910390f35b6102d3610551565b60405190151581526020016102c2565b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102c2565b61034f6040518060400160405280601181526020017f436f6d6d697453746f726520312e302e3000000000000000000000000000000081525081565b6040516102c29190612745565b61036f61036a3660046127bb565b6105e8565b005b61036f61037f366004612a4a565b6105f8565b61036f610392366004612b17565b610e19565b6103aa6103a5366004612b77565b610e65565b6040519081526020016102c2565b61036f610f5b565b60095467ffffffffffffffff166102fa565b6009546d0100000000000000000000000000900460ff166102d3565b6103f6610fc1565b6040516102c29190612c3c565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102c2565b61036f611030565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102c2565b61036f61112d565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102c2565b6102d361119d565b6103aa6104c0366004612c4f565b6000908152600a602052604090205490565b61036f6104e0366004612c68565b611254565b6040805160018152600060208201819052918101919091526060016102c2565b61036f610513366004612c83565b611297565b61036f610526366004612d3a565b6118b7565b61036f610539366004612d57565b6118cb565b6102d361054c366004612c4f565b611965565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e29190612d99565b15905090565b6105f3838383611a39565b505050565b855185518560ff16601f831115610670576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e6572730000000000000000000000000000000060448201526064015b60405180910390fd5b806000036106da576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610667565b818314610768576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610667565b610773816003612dea565b83116107db576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610667565b6107e3611e4f565b6107ec86611ed2565b60065460005b818110156108e857600560006006838154811061081157610811612e01565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556007805460059291908490811061088157610881612e01565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556108e181612e30565b90506107f2565b50895160005b81811015610cc15760008c828151811061090a5761090a612e01565b602002602001015190506000600281111561092757610927612e68565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561096657610966612e68565b146109cd576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610667565b73ffffffffffffffffffffffffffffffffffffffff8116610a1a576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610aca57610aca612e68565b021790555090505060008c8381518110610ae657610ae6612e01565b6020026020010151905060006002811115610b0357610b03612e68565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff166002811115610b4257610b42612e68565b14610ba9576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610667565b73ffffffffffffffffffffffffffffffffffffffff8116610bf6576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610ca657610ca6612e68565b0217905550905050505080610cba90612e30565b90506108ee565b508a51610cd59060069060208e01906125ca565b508951610ce99060079060208d01906125ca565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610d6f914691309190600090610d419063ffffffff16612e97565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e61208e565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610e0399989796959493929190612eba565b60405180910390a1505050505050505050505050565b610e21611e4f565b6009805464ffffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff909216919091179055565b6009546000906d0100000000000000000000000000900460ff1615610eb6576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f2787878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250612139915050565b9050610f3281611965565b610f40576000915050610f52565b6000908152600a602052604090205490505b95945050505050565b610f63611e4f565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6060600780548060200260200160405190810160405280929190818152602001828054801561102657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ffb575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff1633146110b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610667565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611135611e4f565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610fb7565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122e9190612d99565b15801561124f57506009546d0100000000000000000000000000900460ff16155b905090565b61125c611e4f565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6112a6878760208b0135611a39565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146113195780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610667565b467f00000000000000000000000000000000000000000000000000000000000000001461139a576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610667565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f00000000000000000000000000000000000000000000000000000000000000001561143c5760028260200151836040015161141d9190612f50565b6114279190612f69565b611432906001612f50565b60ff169050611452565b602082015161144c906001612f50565b60ff1690505b86811461148b576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8685146114c4576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561150757611507612e68565b600281111561151857611518612e68565b905250905060028160200151600281111561153557611535612e68565b14801561157c57506007816000015160ff168154811061155757611557612e01565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6115b2576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006115c0866020612dea565b6115cb896020612dea565b6115d78c610144612fb2565b6115e19190612fb2565b6115eb9190612fb2565b905036811461162f576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610667565b5060008a8a604051611642929190612fc5565b604051908190038120611659918e90602001612fd5565b604051602081830303815290604052805190602001209050611679612654565b8860005b818110156118a65760006001858a846020811061169c5761169c612e01565b6116a991901a601b612f50565b8f8f868181106116bb576116bb612e01565b905060200201358e8e878181106116d4576116d4612e01565b9050602002013560405160008152602001604052604051611711949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611733573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff80821686529397509195509293928401916101009091041660028111156117b6576117b6612e68565b60028111156117c7576117c7612e68565b90525090506001816020015160028111156117e4576117e4612e68565b1461181b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061183257611832612e01565b60200201511561186e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061188957611889612e01565b911515602090920201525061189f905081612e30565b905061167d565b505050505050505050505050505050565b6118bf611e4f565b6118c88161245a565b50565b6118d3611e4f565b60005b818110156105f35760008383838181106118f2576118f2612e01565b90506020020135905061190481611965565b611954576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f129061194b9083815260200190565b60405180910390a15b5061195e81612e30565b90506118d6565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a339190612d99565b92915050565b6009546d0100000000000000000000000000900460ff1615611a87576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b169190612d99565b15611b4d576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611b5b8385018561304f565b80515151909150151580611b7d575080516020015167ffffffffffffffff1615155b15611cb55760095464ffffffffff80841668010000000000000000909204161015611c7a57600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f866548c900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163866548c991611c3491600401613266565b600060405180830381600087803b158015611c4e57600080fd5b505af1158015611c62573d6000803e3d6000fd5b505050506040810151611c755750505050565b611cb5565b6040810151611cb5576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff9081169116141580611cf0575060208082015190810151905167ffffffffffffffff9182169116115b15611d2d5780602001516040517fbb1ae18d0000000000000000000000000000000000000000000000000000000081526004016106679190613279565b6040810151611d68576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a602052205415611db1576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201510151611dc490600161329e565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517fe81b49e583122eb290c46fc255c962b9a2dec468816c00fb7a2e6ebc42dc92d490611e419083906132c6565b60405180910390a150505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ed0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610667565b565b600081806020019051810190611ee89190613322565b805190915073ffffffffffffffffffffffffffffffffffffffff16611f39576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff90811682527f00000000000000000000000000000000000000000000000000000000000000001660208201527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec39161208291849061336e565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a6040516020016120b2999897969594939291906133eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b825182516000919081830361217a576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610101821180159061218e57506101018111155b6121c4576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115612225576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003612252578660008151811061224057612240612e01565b60200260200101519350505050612453565b60008167ffffffffffffffff81111561226d5761226d61280f565b604051908082528060200260200182016040528015612296578160200160208202803683370190505b50905060008080805b858110156123d95760006001821b8b8116036122fa57888510156122e3578c5160018601958e9181106122d4576122d4612e01565b6020026020010151905061231c565b85516001850194879181106122d4576122d4612e01565b8b5160018401938d91811061231157612311612e01565b602002602001015190505b60008986101561234c578d5160018701968f91811061233d5761233d612e01565b6020026020010151905061236e565b865160018601958891811061236357612363612e01565b602002602001015190505b828511156123a8576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123b2828261254f565b8784815181106123c4576123c4612e01565b6020908102919091010152505060010161229f565b5060018503821480156123eb57508683145b80156123f657508581145b61242c576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600186038151811061244157612441612e01565b60200260200101519750505050505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036124d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610667565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008183106125915760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120612453565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120612453565b828054828255906000526020600020908101928215612644579160200282015b8281111561264457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906125ea565b50612650929150612673565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b808211156126505760008155600101612674565b60808101611a33828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b81811015612707576020818501810151868301820152016126eb565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061245360208301846126e1565b60008083601f84011261276a57600080fd5b50813567ffffffffffffffff81111561278257600080fd5b60208301915083602082850101111561279a57600080fd5b9250929050565b803564ffffffffff811681146127b657600080fd5b919050565b6000806000604084860312156127d057600080fd5b833567ffffffffffffffff8111156127e757600080fd5b6127f386828701612758565b90945092506128069050602085016127a1565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156128615761286161280f565b60405290565b6040516060810167ffffffffffffffff811182821017156128615761286161280f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156128d1576128d161280f565b604052919050565b600067ffffffffffffffff8211156128f3576128f361280f565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146118c857600080fd5b600082601f83011261293057600080fd5b81356020612945612940836128d9565b61288a565b82815260059290921b8401810191818101908684111561296457600080fd5b8286015b8481101561298857803561297b816128fd565b8352918301918301612968565b509695505050505050565b803560ff811681146127b657600080fd5b600082601f8301126129b557600080fd5b813567ffffffffffffffff8111156129cf576129cf61280f565b612a0060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161288a565b818152846020838601011115612a1557600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146127b657600080fd5b60008060008060008060c08789031215612a6357600080fd5b863567ffffffffffffffff80821115612a7b57600080fd5b612a878a838b0161291f565b97506020890135915080821115612a9d57600080fd5b612aa98a838b0161291f565b9650612ab760408a01612993565b95506060890135915080821115612acd57600080fd5b612ad98a838b016129a4565b9450612ae760808a01612a32565b935060a0890135915080821115612afd57600080fd5b50612b0a89828a016129a4565b9150509295509295509295565b600060208284031215612b2957600080fd5b612453826127a1565b60008083601f840112612b4457600080fd5b50813567ffffffffffffffff811115612b5c57600080fd5b6020830191508360208260051b850101111561279a57600080fd5b600080600080600060608688031215612b8f57600080fd5b853567ffffffffffffffff80821115612ba757600080fd5b612bb389838a01612b32565b90975095506020880135915080821115612bcc57600080fd5b50612bd988828901612b32565b96999598509660400135949350505050565b600081518084526020808501945080840160005b83811015612c3157815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612bff565b509495945050505050565b6020815260006124536020830184612beb565b600060208284031215612c6157600080fd5b5035919050565b600060208284031215612c7a57600080fd5b61245382612a32565b60008060008060008060008060e0898b031215612c9f57600080fd5b606089018a811115612cb057600080fd5b8998503567ffffffffffffffff80821115612cca57600080fd5b612cd68c838d01612758565b909950975060808b0135915080821115612cef57600080fd5b612cfb8c838d01612b32565b909750955060a08b0135915080821115612d1457600080fd5b50612d218b828c01612b32565b999c989b50969995989497949560c00135949350505050565b600060208284031215612d4c57600080fd5b8135612453816128fd565b60008060208385031215612d6a57600080fd5b823567ffffffffffffffff811115612d8157600080fd5b612d8d85828601612b32565b90969095509350505050565b600060208284031215612dab57600080fd5b8151801515811461245357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611a3357611a33612dbb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612e6157612e61612dbb565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600063ffffffff808316818103612eb057612eb0612dbb565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612eea8184018a612beb565b90508281036080840152612efe8189612beb565b905060ff871660a084015282810360c0840152612f1b81876126e1565b905067ffffffffffffffff851660e0840152828103610100840152612f4081856126e1565b9c9b505050505050505050505050565b60ff8181168382160190811115611a3357611a33612dbb565b600060ff831680612fa3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b80820180821115611a3357611a33612dbb565b8183823760009101908152919050565b828152606082602083013760800192915050565b803577ffffffffffffffffffffffffffffffffffffffffffffffff811681146127b657600080fd5b60006040828403121561302357600080fd5b61302b61283e565b905061303682612a32565b815261304460208301612a32565b602082015292915050565b6000602080838503121561306257600080fd5b823567ffffffffffffffff8082111561307a57600080fd5b908401906080828703121561308e57600080fd5b613096612867565b8235828111156130a557600080fd5b8301606081890312156130b757600080fd5b6130bf612867565b8135848111156130ce57600080fd5b82019350601f840189136130e157600080fd5b83356130ef612940826128d9565b81815260069190911b8501870190878101908b83111561310e57600080fd5b958801955b82871015613162576040878d03121561312c5760008081fd5b61313461283e565b873561313f816128fd565b815261314c888b01612fe9565b818b015282526040969096019590880190613113565b8352506131729050828701612a32565b8682015261318260408301612fe9565b604082015282525061319687848601613011565b93810193909352506060013560408201529392505050565b805160608084528151908401819052600091602091908201906080860190845b81811015613225578351805173ffffffffffffffffffffffffffffffffffffffff16845285015177ffffffffffffffffffffffffffffffffffffffffffffffff1685840152928401926040909201916001016131ce565b505067ffffffffffffffff83860151168387015260408501519250610f52604087018477ffffffffffffffffffffffffffffffffffffffffffffffff169052565b60208152600061245360208301846131ae565b60408101611a338284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff8181168382160190808211156132bf576132bf612dbb565b5092915050565b6020815260008251608060208401526132e260a08401826131ae565b9050602084015161330d6040850182805167ffffffffffffffff908116835260209182015116910152565b50604084015160808401528091505092915050565b60006020828403121561333457600080fd5b6040516020810181811067ffffffffffffffff821117156133575761335761280f565b6040528251613365816128fd565b81529392505050565b60a081016133c7828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526134328285018b612beb565b91508382036080850152613446828a612beb565b915060ff881660a085015283820360c085015261346382886126e1565b90861660e08501528381036101008501529050612f4081856126e156fea164736f6c6343000813000a", -} - -var CommitStoreHelperABI = CommitStoreHelperMetaData.ABI - -var CommitStoreHelperBin = CommitStoreHelperMetaData.Bin - -func DeployCommitStoreHelper(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig CommitStoreStaticConfig) (common.Address, *types.Transaction, *CommitStoreHelper, error) { - parsed, err := CommitStoreHelperMetaData.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(CommitStoreHelperBin), backend, staticConfig) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &CommitStoreHelper{CommitStoreHelperCaller: CommitStoreHelperCaller{contract: contract}, CommitStoreHelperTransactor: CommitStoreHelperTransactor{contract: contract}, CommitStoreHelperFilterer: CommitStoreHelperFilterer{contract: contract}}, nil -} - -type CommitStoreHelper struct { - address common.Address - abi abi.ABI - CommitStoreHelperCaller - CommitStoreHelperTransactor - CommitStoreHelperFilterer -} - -type CommitStoreHelperCaller struct { - contract *bind.BoundContract -} - -type CommitStoreHelperTransactor struct { - contract *bind.BoundContract -} - -type CommitStoreHelperFilterer struct { - contract *bind.BoundContract -} - -type CommitStoreHelperSession struct { - Contract *CommitStoreHelper - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type CommitStoreHelperCallerSession struct { - Contract *CommitStoreHelperCaller - CallOpts bind.CallOpts -} - -type CommitStoreHelperTransactorSession struct { - Contract *CommitStoreHelperTransactor - TransactOpts bind.TransactOpts -} - -type CommitStoreHelperRaw struct { - Contract *CommitStoreHelper -} - -type CommitStoreHelperCallerRaw struct { - Contract *CommitStoreHelperCaller -} - -type CommitStoreHelperTransactorRaw struct { - Contract *CommitStoreHelperTransactor -} - -func NewCommitStoreHelper(address common.Address, backend bind.ContractBackend) (*CommitStoreHelper, error) { - abi, err := abi.JSON(strings.NewReader(CommitStoreHelperABI)) - if err != nil { - return nil, err - } - contract, err := bindCommitStoreHelper(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &CommitStoreHelper{address: address, abi: abi, CommitStoreHelperCaller: CommitStoreHelperCaller{contract: contract}, CommitStoreHelperTransactor: CommitStoreHelperTransactor{contract: contract}, CommitStoreHelperFilterer: CommitStoreHelperFilterer{contract: contract}}, nil -} - -func NewCommitStoreHelperCaller(address common.Address, caller bind.ContractCaller) (*CommitStoreHelperCaller, error) { - contract, err := bindCommitStoreHelper(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &CommitStoreHelperCaller{contract: contract}, nil -} - -func NewCommitStoreHelperTransactor(address common.Address, transactor bind.ContractTransactor) (*CommitStoreHelperTransactor, error) { - contract, err := bindCommitStoreHelper(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &CommitStoreHelperTransactor{contract: contract}, nil -} - -func NewCommitStoreHelperFilterer(address common.Address, filterer bind.ContractFilterer) (*CommitStoreHelperFilterer, error) { - contract, err := bindCommitStoreHelper(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &CommitStoreHelperFilterer{contract: contract}, nil -} - -func bindCommitStoreHelper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := CommitStoreHelperMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_CommitStoreHelper *CommitStoreHelperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CommitStoreHelper.Contract.CommitStoreHelperCaller.contract.Call(opts, result, method, params...) -} - -func (_CommitStoreHelper *CommitStoreHelperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.CommitStoreHelperTransactor.contract.Transfer(opts) -} - -func (_CommitStoreHelper *CommitStoreHelperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.CommitStoreHelperTransactor.contract.Transact(opts, method, params...) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CommitStoreHelper.Contract.contract.Call(opts, result, method, params...) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.contract.Transfer(opts) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.contract.Transact(opts, method, params...) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) GetDynamicConfig(opts *bind.CallOpts) (CommitStoreDynamicConfig, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(CommitStoreDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(CommitStoreDynamicConfig)).(*CommitStoreDynamicConfig) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) GetDynamicConfig() (CommitStoreDynamicConfig, error) { - return _CommitStoreHelper.Contract.GetDynamicConfig(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) GetDynamicConfig() (CommitStoreDynamicConfig, error) { - return _CommitStoreHelper.Contract.GetDynamicConfig(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "getExpectedNextSequenceNumber") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _CommitStoreHelper.Contract.GetExpectedNextSequenceNumber(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _CommitStoreHelper.Contract.GetExpectedNextSequenceNumber(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) GetLatestPriceEpochAndRound(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "getLatestPriceEpochAndRound") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) GetLatestPriceEpochAndRound() (uint64, error) { - return _CommitStoreHelper.Contract.GetLatestPriceEpochAndRound(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) GetLatestPriceEpochAndRound() (uint64, error) { - return _CommitStoreHelper.Contract.GetLatestPriceEpochAndRound(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) GetMerkleRoot(opts *bind.CallOpts, root [32]byte) (*big.Int, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "getMerkleRoot", root) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) GetMerkleRoot(root [32]byte) (*big.Int, error) { - return _CommitStoreHelper.Contract.GetMerkleRoot(&_CommitStoreHelper.CallOpts, root) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) GetMerkleRoot(root [32]byte) (*big.Int, error) { - return _CommitStoreHelper.Contract.GetMerkleRoot(&_CommitStoreHelper.CallOpts, root) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) GetStaticConfig(opts *bind.CallOpts) (CommitStoreStaticConfig, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(CommitStoreStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(CommitStoreStaticConfig)).(*CommitStoreStaticConfig) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) GetStaticConfig() (CommitStoreStaticConfig, error) { - return _CommitStoreHelper.Contract.GetStaticConfig(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) GetStaticConfig() (CommitStoreStaticConfig, error) { - return _CommitStoreHelper.Contract.GetStaticConfig(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "getTransmitters") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) GetTransmitters() ([]common.Address, error) { - return _CommitStoreHelper.Contract.GetTransmitters(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) GetTransmitters() ([]common.Address, error) { - return _CommitStoreHelper.Contract.GetTransmitters(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) IsARMHealthy(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "isARMHealthy") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) IsARMHealthy() (bool, error) { - return _CommitStoreHelper.Contract.IsARMHealthy(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) IsARMHealthy() (bool, error) { - return _CommitStoreHelper.Contract.IsARMHealthy(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "isBlessed", root) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) IsBlessed(root [32]byte) (bool, error) { - return _CommitStoreHelper.Contract.IsBlessed(&_CommitStoreHelper.CallOpts, root) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) IsBlessed(root [32]byte) (bool, error) { - return _CommitStoreHelper.Contract.IsBlessed(&_CommitStoreHelper.CallOpts, root) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) IsUnpausedAndARMHealthy(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "isUnpausedAndARMHealthy") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) IsUnpausedAndARMHealthy() (bool, error) { - return _CommitStoreHelper.Contract.IsUnpausedAndARMHealthy(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) IsUnpausedAndARMHealthy() (bool, error) { - return _CommitStoreHelper.Contract.IsUnpausedAndARMHealthy(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) { - var out []interface{} - err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _CommitStoreHelper.Contract.LatestConfigDetails(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _CommitStoreHelper.Contract.LatestConfigDetails(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) { - var out []interface{} - err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _CommitStoreHelper.Contract.LatestConfigDigestAndEpoch(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _CommitStoreHelper.Contract.LatestConfigDigestAndEpoch(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperSession) Owner() (common.Address, error) { - return _CommitStoreHelper.Contract.Owner(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) Owner() (common.Address, error) { - return _CommitStoreHelper.Contract.Owner(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) Paused(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "paused") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) Paused() (bool, error) { - return _CommitStoreHelper.Contract.Paused(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) Paused() (bool, error) { - return _CommitStoreHelper.Contract.Paused(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) TypeAndVersion() (string, error) { - return _CommitStoreHelper.Contract.TypeAndVersion(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) TypeAndVersion() (string, error) { - return _CommitStoreHelper.Contract.TypeAndVersion(&_CommitStoreHelper.CallOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperCaller) Verify(opts *bind.CallOpts, hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) { - var out []interface{} - err := _CommitStoreHelper.contract.Call(opts, &out, "verify", hashedLeaves, proofs, proofFlagBits) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_CommitStoreHelper *CommitStoreHelperSession) Verify(hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) { - return _CommitStoreHelper.Contract.Verify(&_CommitStoreHelper.CallOpts, hashedLeaves, proofs, proofFlagBits) -} - -func (_CommitStoreHelper *CommitStoreHelperCallerSession) Verify(hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) { - return _CommitStoreHelper.Contract.Verify(&_CommitStoreHelper.CallOpts, hashedLeaves, proofs, proofFlagBits) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "acceptOwnership") -} - -func (_CommitStoreHelper *CommitStoreHelperSession) AcceptOwnership() (*types.Transaction, error) { - return _CommitStoreHelper.Contract.AcceptOwnership(&_CommitStoreHelper.TransactOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _CommitStoreHelper.Contract.AcceptOwnership(&_CommitStoreHelper.TransactOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "pause") -} - -func (_CommitStoreHelper *CommitStoreHelperSession) Pause() (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Pause(&_CommitStoreHelper.TransactOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) Pause() (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Pause(&_CommitStoreHelper.TransactOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) Report(opts *bind.TransactOpts, commitReport []byte, epochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "report", commitReport, epochAndRound) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) Report(commitReport []byte, epochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Report(&_CommitStoreHelper.TransactOpts, commitReport, epochAndRound) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) Report(commitReport []byte, epochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Report(&_CommitStoreHelper.TransactOpts, commitReport, epochAndRound) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset [][32]byte) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "resetUnblessedRoots", rootToReset) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) ResetUnblessedRoots(rootToReset [][32]byte) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.ResetUnblessedRoots(&_CommitStoreHelper.TransactOpts, rootToReset) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) ResetUnblessedRoots(rootToReset [][32]byte) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.ResetUnblessedRoots(&_CommitStoreHelper.TransactOpts, rootToReset) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) SetLatestPriceEpochAndRound(opts *bind.TransactOpts, latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "setLatestPriceEpochAndRound", latestPriceEpochAndRound) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) SetLatestPriceEpochAndRound(latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.SetLatestPriceEpochAndRound(&_CommitStoreHelper.TransactOpts, latestPriceEpochAndRound) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) SetLatestPriceEpochAndRound(latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.SetLatestPriceEpochAndRound(&_CommitStoreHelper.TransactOpts, latestPriceEpochAndRound) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) SetMinSeqNr(opts *bind.TransactOpts, minSeqNr uint64) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "setMinSeqNr", minSeqNr) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) SetMinSeqNr(minSeqNr uint64) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.SetMinSeqNr(&_CommitStoreHelper.TransactOpts, minSeqNr) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) SetMinSeqNr(minSeqNr uint64) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.SetMinSeqNr(&_CommitStoreHelper.TransactOpts, minSeqNr) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "setOCR2Config", signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) SetOCR2Config(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.SetOCR2Config(&_CommitStoreHelper.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) SetOCR2Config(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.SetOCR2Config(&_CommitStoreHelper.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "transferOwnership", to) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.TransferOwnership(&_CommitStoreHelper.TransactOpts, to) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.TransferOwnership(&_CommitStoreHelper.TransactOpts, to) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) -} - -func (_CommitStoreHelper *CommitStoreHelperSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Transmit(&_CommitStoreHelper.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Transmit(&_CommitStoreHelper.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CommitStoreHelper.contract.Transact(opts, "unpause") -} - -func (_CommitStoreHelper *CommitStoreHelperSession) Unpause() (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Unpause(&_CommitStoreHelper.TransactOpts) -} - -func (_CommitStoreHelper *CommitStoreHelperTransactorSession) Unpause() (*types.Transaction, error) { - return _CommitStoreHelper.Contract.Unpause(&_CommitStoreHelper.TransactOpts) -} - -type CommitStoreHelperConfigSetIterator struct { - Event *CommitStoreHelperConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperConfigSet) - 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(CommitStoreHelperConfigSet) - 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 *CommitStoreHelperConfigSetIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperConfigSet struct { - StaticConfig CommitStoreStaticConfig - DynamicConfig CommitStoreDynamicConfig - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterConfigSet(opts *bind.FilterOpts) (*CommitStoreHelperConfigSetIterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &CommitStoreHelperConfigSetIterator{contract: _CommitStoreHelper.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperConfigSet) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.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(CommitStoreHelperConfigSet) - if err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseConfigSet(log types.Log) (*CommitStoreHelperConfigSet, error) { - event := new(CommitStoreHelperConfigSet) - if err := _CommitStoreHelper.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperConfigSet0Iterator struct { - Event *CommitStoreHelperConfigSet0 - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperConfigSet0Iterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperConfigSet0) - 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(CommitStoreHelperConfigSet0) - 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 *CommitStoreHelperConfigSet0Iterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperConfigSet0Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperConfigSet0 struct { - PreviousConfigBlockNumber uint32 - ConfigDigest [32]byte - ConfigCount uint64 - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterConfigSet0(opts *bind.FilterOpts) (*CommitStoreHelperConfigSet0Iterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "ConfigSet0") - if err != nil { - return nil, err - } - return &CommitStoreHelperConfigSet0Iterator{contract: _CommitStoreHelper.contract, event: "ConfigSet0", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperConfigSet0) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.contract.WatchLogs(opts, "ConfigSet0") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreHelperConfigSet0) - if err := _CommitStoreHelper.contract.UnpackLog(event, "ConfigSet0", 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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseConfigSet0(log types.Log) (*CommitStoreHelperConfigSet0, error) { - event := new(CommitStoreHelperConfigSet0) - if err := _CommitStoreHelper.contract.UnpackLog(event, "ConfigSet0", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperOwnershipTransferRequestedIterator struct { - Event *CommitStoreHelperOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperOwnershipTransferRequested) - 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(CommitStoreHelperOwnershipTransferRequested) - 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 *CommitStoreHelperOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreHelperOwnershipTransferRequestedIterator, 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 := _CommitStoreHelper.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &CommitStoreHelperOwnershipTransferRequestedIterator{contract: _CommitStoreHelper.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperOwnershipTransferRequested, 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 := _CommitStoreHelper.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(CommitStoreHelperOwnershipTransferRequested) - if err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseOwnershipTransferRequested(log types.Log) (*CommitStoreHelperOwnershipTransferRequested, error) { - event := new(CommitStoreHelperOwnershipTransferRequested) - if err := _CommitStoreHelper.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperOwnershipTransferredIterator struct { - Event *CommitStoreHelperOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperOwnershipTransferred) - 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(CommitStoreHelperOwnershipTransferred) - 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 *CommitStoreHelperOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreHelperOwnershipTransferredIterator, 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 := _CommitStoreHelper.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &CommitStoreHelperOwnershipTransferredIterator{contract: _CommitStoreHelper.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperOwnershipTransferred, 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 := _CommitStoreHelper.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(CommitStoreHelperOwnershipTransferred) - if err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseOwnershipTransferred(log types.Log) (*CommitStoreHelperOwnershipTransferred, error) { - event := new(CommitStoreHelperOwnershipTransferred) - if err := _CommitStoreHelper.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperPausedIterator struct { - Event *CommitStoreHelperPaused - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperPausedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperPaused) - 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(CommitStoreHelperPaused) - 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 *CommitStoreHelperPausedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperPausedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperPaused struct { - Account common.Address - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterPaused(opts *bind.FilterOpts) (*CommitStoreHelperPausedIterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "Paused") - if err != nil { - return nil, err - } - return &CommitStoreHelperPausedIterator{contract: _CommitStoreHelper.contract, event: "Paused", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperPaused) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.contract.WatchLogs(opts, "Paused") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreHelperPaused) - if err := _CommitStoreHelper.contract.UnpackLog(event, "Paused", 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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParsePaused(log types.Log) (*CommitStoreHelperPaused, error) { - event := new(CommitStoreHelperPaused) - if err := _CommitStoreHelper.contract.UnpackLog(event, "Paused", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperReportAcceptedIterator struct { - Event *CommitStoreHelperReportAccepted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperReportAcceptedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperReportAccepted) - 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(CommitStoreHelperReportAccepted) - 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 *CommitStoreHelperReportAcceptedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperReportAcceptedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperReportAccepted struct { - Report CommitStoreCommitReport - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterReportAccepted(opts *bind.FilterOpts) (*CommitStoreHelperReportAcceptedIterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "ReportAccepted") - if err != nil { - return nil, err - } - return &CommitStoreHelperReportAcceptedIterator{contract: _CommitStoreHelper.contract, event: "ReportAccepted", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchReportAccepted(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperReportAccepted) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.contract.WatchLogs(opts, "ReportAccepted") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreHelperReportAccepted) - if err := _CommitStoreHelper.contract.UnpackLog(event, "ReportAccepted", 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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseReportAccepted(log types.Log) (*CommitStoreHelperReportAccepted, error) { - event := new(CommitStoreHelperReportAccepted) - if err := _CommitStoreHelper.contract.UnpackLog(event, "ReportAccepted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperRootRemovedIterator struct { - Event *CommitStoreHelperRootRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperRootRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperRootRemoved) - 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(CommitStoreHelperRootRemoved) - 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 *CommitStoreHelperRootRemovedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperRootRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperRootRemoved struct { - Root [32]byte - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterRootRemoved(opts *bind.FilterOpts) (*CommitStoreHelperRootRemovedIterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "RootRemoved") - if err != nil { - return nil, err - } - return &CommitStoreHelperRootRemovedIterator{contract: _CommitStoreHelper.contract, event: "RootRemoved", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperRootRemoved) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.contract.WatchLogs(opts, "RootRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreHelperRootRemoved) - if err := _CommitStoreHelper.contract.UnpackLog(event, "RootRemoved", 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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseRootRemoved(log types.Log) (*CommitStoreHelperRootRemoved, error) { - event := new(CommitStoreHelperRootRemoved) - if err := _CommitStoreHelper.contract.UnpackLog(event, "RootRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperTransmittedIterator struct { - Event *CommitStoreHelperTransmitted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperTransmittedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperTransmitted) - 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(CommitStoreHelperTransmitted) - 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 *CommitStoreHelperTransmittedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperTransmittedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperTransmitted struct { - ConfigDigest [32]byte - Epoch uint32 - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterTransmitted(opts *bind.FilterOpts) (*CommitStoreHelperTransmittedIterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "Transmitted") - if err != nil { - return nil, err - } - return &CommitStoreHelperTransmittedIterator{contract: _CommitStoreHelper.contract, event: "Transmitted", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperTransmitted) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.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(CommitStoreHelperTransmitted) - if err := _CommitStoreHelper.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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseTransmitted(log types.Log) (*CommitStoreHelperTransmitted, error) { - event := new(CommitStoreHelperTransmitted) - if err := _CommitStoreHelper.contract.UnpackLog(event, "Transmitted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CommitStoreHelperUnpausedIterator struct { - Event *CommitStoreHelperUnpaused - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CommitStoreHelperUnpausedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CommitStoreHelperUnpaused) - 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(CommitStoreHelperUnpaused) - 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 *CommitStoreHelperUnpausedIterator) Error() error { - return it.fail -} - -func (it *CommitStoreHelperUnpausedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CommitStoreHelperUnpaused struct { - Account common.Address - Raw types.Log -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) FilterUnpaused(opts *bind.FilterOpts) (*CommitStoreHelperUnpausedIterator, error) { - - logs, sub, err := _CommitStoreHelper.contract.FilterLogs(opts, "Unpaused") - if err != nil { - return nil, err - } - return &CommitStoreHelperUnpausedIterator{contract: _CommitStoreHelper.contract, event: "Unpaused", logs: logs, sub: sub}, nil -} - -func (_CommitStoreHelper *CommitStoreHelperFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperUnpaused) (event.Subscription, error) { - - logs, sub, err := _CommitStoreHelper.contract.WatchLogs(opts, "Unpaused") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CommitStoreHelperUnpaused) - if err := _CommitStoreHelper.contract.UnpackLog(event, "Unpaused", 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 (_CommitStoreHelper *CommitStoreHelperFilterer) ParseUnpaused(log types.Log) (*CommitStoreHelperUnpaused, error) { - event := new(CommitStoreHelperUnpaused) - if err := _CommitStoreHelper.contract.UnpackLog(event, "Unpaused", 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 (_CommitStoreHelper *CommitStoreHelper) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _CommitStoreHelper.abi.Events["ConfigSet"].ID: - return _CommitStoreHelper.ParseConfigSet(log) - case _CommitStoreHelper.abi.Events["ConfigSet0"].ID: - return _CommitStoreHelper.ParseConfigSet0(log) - case _CommitStoreHelper.abi.Events["OwnershipTransferRequested"].ID: - return _CommitStoreHelper.ParseOwnershipTransferRequested(log) - case _CommitStoreHelper.abi.Events["OwnershipTransferred"].ID: - return _CommitStoreHelper.ParseOwnershipTransferred(log) - case _CommitStoreHelper.abi.Events["Paused"].ID: - return _CommitStoreHelper.ParsePaused(log) - case _CommitStoreHelper.abi.Events["ReportAccepted"].ID: - return _CommitStoreHelper.ParseReportAccepted(log) - case _CommitStoreHelper.abi.Events["RootRemoved"].ID: - return _CommitStoreHelper.ParseRootRemoved(log) - case _CommitStoreHelper.abi.Events["Transmitted"].ID: - return _CommitStoreHelper.ParseTransmitted(log) - case _CommitStoreHelper.abi.Events["Unpaused"].ID: - return _CommitStoreHelper.ParseUnpaused(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (CommitStoreHelperConfigSet) Topic() common.Hash { - return common.HexToHash("0xc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec3") -} - -func (CommitStoreHelperConfigSet0) Topic() common.Hash { - return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") -} - -func (CommitStoreHelperOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (CommitStoreHelperOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (CommitStoreHelperPaused) Topic() common.Hash { - return common.HexToHash("0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258") -} - -func (CommitStoreHelperReportAccepted) Topic() common.Hash { - return common.HexToHash("0xe81b49e583122eb290c46fc255c962b9a2dec468816c00fb7a2e6ebc42dc92d4") -} - -func (CommitStoreHelperRootRemoved) Topic() common.Hash { - return common.HexToHash("0x202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12") -} - -func (CommitStoreHelperTransmitted) Topic() common.Hash { - return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") -} - -func (CommitStoreHelperUnpaused) Topic() common.Hash { - return common.HexToHash("0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa") -} - -func (_CommitStoreHelper *CommitStoreHelper) Address() common.Address { - return _CommitStoreHelper.address -} - -type CommitStoreHelperInterface interface { - GetDynamicConfig(opts *bind.CallOpts) (CommitStoreDynamicConfig, error) - - GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) - - GetLatestPriceEpochAndRound(opts *bind.CallOpts) (uint64, error) - - GetMerkleRoot(opts *bind.CallOpts, root [32]byte) (*big.Int, error) - - GetStaticConfig(opts *bind.CallOpts) (CommitStoreStaticConfig, error) - - GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) - - IsARMHealthy(opts *bind.CallOpts) (bool, error) - - IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) - - IsUnpausedAndARMHealthy(opts *bind.CallOpts) (bool, error) - - LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) - - LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - Paused(opts *bind.CallOpts) (bool, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - Verify(opts *bind.CallOpts, hashedLeaves [][32]byte, proofs [][32]byte, proofFlagBits *big.Int) (*big.Int, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - Pause(opts *bind.TransactOpts) (*types.Transaction, error) - - Report(opts *bind.TransactOpts, commitReport []byte, epochAndRound *big.Int) (*types.Transaction, error) - - ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset [][32]byte) (*types.Transaction, error) - - SetLatestPriceEpochAndRound(opts *bind.TransactOpts, latestPriceEpochAndRound *big.Int) (*types.Transaction, error) - - SetMinSeqNr(opts *bind.TransactOpts, minSeqNr uint64) (*types.Transaction, error) - - SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - - Unpause(opts *bind.TransactOpts) (*types.Transaction, error) - - FilterConfigSet(opts *bind.FilterOpts) (*CommitStoreHelperConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*CommitStoreHelperConfigSet, error) - - FilterConfigSet0(opts *bind.FilterOpts) (*CommitStoreHelperConfigSet0Iterator, error) - - WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperConfigSet0) (event.Subscription, error) - - ParseConfigSet0(log types.Log) (*CommitStoreHelperConfigSet0, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreHelperOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*CommitStoreHelperOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CommitStoreHelperOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*CommitStoreHelperOwnershipTransferred, error) - - FilterPaused(opts *bind.FilterOpts) (*CommitStoreHelperPausedIterator, error) - - WatchPaused(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperPaused) (event.Subscription, error) - - ParsePaused(log types.Log) (*CommitStoreHelperPaused, error) - - FilterReportAccepted(opts *bind.FilterOpts) (*CommitStoreHelperReportAcceptedIterator, error) - - WatchReportAccepted(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperReportAccepted) (event.Subscription, error) - - ParseReportAccepted(log types.Log) (*CommitStoreHelperReportAccepted, error) - - FilterRootRemoved(opts *bind.FilterOpts) (*CommitStoreHelperRootRemovedIterator, error) - - WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperRootRemoved) (event.Subscription, error) - - ParseRootRemoved(log types.Log) (*CommitStoreHelperRootRemoved, error) - - FilterTransmitted(opts *bind.FilterOpts) (*CommitStoreHelperTransmittedIterator, error) - - WatchTransmitted(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperTransmitted) (event.Subscription, error) - - ParseTransmitted(log types.Log) (*CommitStoreHelperTransmitted, error) - - FilterUnpaused(opts *bind.FilterOpts) (*CommitStoreHelperUnpausedIterator, error) - - WatchUnpaused(opts *bind.WatchOpts, sink chan<- *CommitStoreHelperUnpaused) (event.Subscription, error) - - ParseUnpaused(log types.Log) (*CommitStoreHelperUnpaused, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go deleted file mode 100644 index 9d5e7a4aa78..00000000000 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ /dev/null @@ -1,2367 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package evm_2_evm_multi_offramp - -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 ClientAny2EVMMessage struct { - MessageId [32]byte - SourceChainSelector uint64 - Sender []byte - Data []byte - DestTokenAmounts []ClientEVMTokenAmount -} - -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - -type EVM2EVMMultiOffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []EVM2EVMMultiOffRampMerkleRoot -} - -type EVM2EVMMultiOffRampDynamicConfig struct { - Router common.Address - PermissionLessExecutionThresholdSeconds uint32 - MaxTokenTransferGas uint32 - MaxPoolReleaseOrMintGas uint32 - MessageValidator common.Address - PriceRegistry common.Address -} - -type EVM2EVMMultiOffRampInterval struct { - Min uint64 - Max uint64 -} - -type EVM2EVMMultiOffRampMerkleRoot struct { - SourceChainSelector uint64 - Interval EVM2EVMMultiOffRampInterval - MerkleRoot [32]byte -} - -type EVM2EVMMultiOffRampSourceChainConfig struct { - IsEnabled bool - MinSeqNr uint64 - OnRamp []byte -} - -type EVM2EVMMultiOffRampSourceChainConfigArgs struct { - SourceChainSelector uint64 - IsEnabled bool - OnRamp []byte -} - -type EVM2EVMMultiOffRampStaticConfig struct { - ChainSelector uint64 - RmnProxy common.Address - TokenAdminRegistry common.Address - NonceManager common.Address -} - -type EVM2EVMMultiOffRampUnblessedRoot struct { - SourceChainSelector uint64 - MerkleRoot [32]byte -} - -type InternalAny2EVMRampMessage struct { - Header InternalRampMessageHeader - Sender []byte - Data []byte - Receiver common.Address - GasLimit *big.Int - TokenAmounts []InternalRampTokenAmount -} - -type InternalExecutionReportSingleChain struct { - SourceChainSelector uint64 - Messages []InternalAny2EVMRampMessage - OffchainTokenData [][][]byte - Proofs [][32]byte - ProofFlagBits *big.Int -} - -type InternalGasPriceUpdate struct { - DestChainSelector uint64 - UsdPerUnitGas *big.Int -} - -type InternalPriceUpdates struct { - TokenPriceUpdates []InternalTokenPriceUpdate - GasPriceUpdates []InternalGasPriceUpdate -} - -type InternalRampMessageHeader struct { - MessageId [32]byte - SourceChainSelector uint64 - DestChainSelector uint64 - SequenceNumber uint64 - Nonce uint64 -} - -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int -} - -type InternalTokenPriceUpdate struct { - SourceToken common.Address - UsdPerToken *big.Int -} - -type MultiOCR3BaseConfigInfo struct { - ConfigDigest [32]byte - F uint8 - N uint8 - IsSignatureVerificationEnabled bool -} - -type MultiOCR3BaseOCRConfig struct { - ConfigInfo MultiOCR3BaseConfigInfo - Signers []common.Address - Transmitters []common.Address -} - -type MultiOCR3BaseOCRConfigArgs struct { - ConfigDigest [32]byte - OcrPluginType uint8 - F uint8 - IsSignatureVerificationEnabled bool - Signers []common.Address - Transmitters []common.Address -} - -var EVM2EVMMultiOffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"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\":\"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\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"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\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"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\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"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\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"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\":\"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\":[{\"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\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.CommitReport\",\"name\":\"report\",\"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\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"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\":\"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\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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[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\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"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\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"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\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"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.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"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\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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: "0x6101206040523480156200001257600080fd5b5060405162006af738038062006af78339810160408190526200003591620008e2565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003fc565b50505062000c57565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60a08101516001600160a01b03161580620002c8575080516001600160a01b0316155b15620002e7576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b0319908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b60005b81518110156200064e57600082828151811062000420576200042062000a20565b60200260200101519050600081600001519050806001600160401b03166000036200045e5760405163c656089560e01b815260040160405180910390fd5b6001600160401b03811660009081526007602052604081206001810180549192916200048a9062000a36565b80601f0160208091040260200160405190810160405280929190818152602001828054620004b89062000a36565b8015620005095780601f10620004dd5761010080835404028352916020019162000509565b820191906000526020600020905b815481529060010190602001808311620004eb57829003601f168201915b505050505090506000846040015190508151600003620005ac57805160000362000546576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000556828262000ac7565b508254610100600160481b0319166101001783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005e7565b8080519060200120828051906020012014620005e75760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b6020850151835460ff19169015151783556040516001600160401b038516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba906200063590869062000b93565b60405180910390a25050505050806001019050620003ff565b5050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200068d576200068d62000652565b60405290565b604051608081016001600160401b03811182821017156200068d576200068d62000652565b60405160c081016001600160401b03811182821017156200068d576200068d62000652565b604051601f8201601f191681016001600160401b038111828210171562000708576200070862000652565b604052919050565b80516001600160401b03811681146200072857600080fd5b919050565b80516001600160a01b03811681146200072857600080fd5b805163ffffffff811681146200072857600080fd5b6000601f83601f8401126200076e57600080fd5b825160206001600160401b03808311156200078d576200078d62000652565b8260051b6200079e838201620006dd565b9384528681018301938381019089861115620007b957600080fd5b84890192505b85831015620008d557825184811115620007d95760008081fd5b89016060601f19828d038101821315620007f35760008081fd5b620007fd62000668565b6200080a89850162000710565b81526040808501518015158114620008225760008081fd5b828b01529284015192888411156200083a5760008081fd5b83850194508e603f8601126200085257600093508384fd5b898501519350888411156200086b576200086b62000652565b6200087c8a848e87011601620006dd565b92508383528e81858701011115620008945760008081fd5b60005b84811015620008b4578581018201518482018c01528a0162000897565b5060009383018a0193909352918201528352509184019190840190620007bf565b9998505050505050505050565b6000806000838503610160811215620008fa57600080fd5b60808112156200090957600080fd5b6200091362000693565b6200091e8662000710565b81526200092e602087016200072d565b602082015262000941604087016200072d565b604082015262000954606087016200072d565b6060820152935060c0607f19820112156200096e57600080fd5b5062000979620006b8565b62000987608086016200072d565b81526200099760a0860162000745565b6020820152620009aa60c0860162000745565b6040820152620009bd60e0860162000745565b6060820152620009d161010086016200072d565b6080820152620009e561012086016200072d565b60a08201526101408501519092506001600160401b0381111562000a0857600080fd5b62000a16868287016200075a565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4b57607f821691505b60208210810362000a6c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000ac2576000816000526020600020601f850160051c8101602086101562000a9d5750805b601f850160051c820191505b8181101562000abe5782815560010162000aa9565b5050505b505050565b81516001600160401b0381111562000ae35762000ae362000652565b62000afb8162000af4845462000a36565b8462000a72565b602080601f83116001811462000b33576000841562000b1a5750858301515b600019600386901b1c1916600185901b17855562000abe565b600085815260208120601f198616915b8281101562000b645788860151825594840194600190910190840162000b43565b508582101562000b835787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252825460ff811615158383015260081c6001600160401b0316604083015260608083015260018084018054600093929190849062000bd58162000a36565b80608089015260a0600183166000811462000bf9576001811462000c165762000c48565b60ff19841660a08b015260a083151560051b8b0101945062000c48565b85600052602060002060005b8481101562000c3f5781548c820185015290880190890162000c22565b8b0160a0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615e3162000cc66000396000818161023e0152612c5201526000818161020f0152612f2c0152600081816101e00152818161141801526114cf0152600081816101b001526127cc015260008181611caa0152611cf60152615e316000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063d2a15d351161008c578063f2fde38b11610066578063f2fde38b146105ca578063f716f99f146105dd578063ff888fb1146105f057600080fd5b8063d2a15d3514610584578063e9d68a8e14610597578063ece670b6146105b757600080fd5b8063a12a9870116100bd578063a12a98701461050c578063c673e5841461051f578063ccd37ba31461053f57600080fd5b806385572ffb146104e35780638da5cb5b146104f157600080fd5b8063403b2d631161012f5780637437ff9f116101145780637437ff9f1461038557806379ba5097146104c85780637d4eef60146104d057600080fd5b8063403b2d63146103525780635e36480c1461036557600080fd5b80632d04ab76116101605780632d04ab761461030e578063311cd513146103235780633f4b04aa1461033657600080fd5b806306285c691461017c578063181f5a77146102c5575b600080fd5b61026e60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102bc9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103016040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102bc9190613e9e565b61032161031c366004613f49565b610613565b005b610321610331366004613ffc565b6109d9565b600a5460405167ffffffffffffffff90911681526020016102bc565b610321610360366004614185565b610a42565b610378610373366004614224565b610a56565b6040516102bc9190614281565b61045f6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526004546001600160a01b03808216835263ffffffff74010000000000000000000000000000000000000000830481166020850152780100000000000000000000000000000000000000000000000083048116948401949094527c010000000000000000000000000000000000000000000000000000000090910490921660608201526005548216608082015260065490911660a082015290565b6040516102bc9190600060c0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401528060a08501511660a08401525092915050565b610321610aac565b6103216104de366004614885565b610b6a565b6103216101773660046149b0565b6000546040516001600160a01b0390911681526020016102bc565b61032161051a366004614a04565b610d0a565b61053261052d366004614b1e565b610d1b565b6040516102bc9190614b7e565b61057661054d366004614bf3565b67ffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b6040519081526020016102bc565b610321610592366004614c1d565b610e79565b6105aa6105a5366004614c92565b610f33565b6040516102bc9190614cad565b6103216105c5366004614ce8565b61101c565b6103216105d8366004614d4c565b61136f565b6103216105eb366004614dd1565b611380565b6106036105fe366004614f0f565b6113c2565b60405190151581526020016102bc565b6000610621878901896150ad565b8051515190915015158061063a57508051602001515115155b1561073a57600a5460208a01359067ffffffffffffffff808316911610156106f957600a805467ffffffffffffffff191667ffffffffffffffff831617905560065482516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691633937306f916106c291600401615315565b600060405180830381600087803b1580156106dc57600080fd5b505af11580156106f0573d6000803e3d6000fd5b50505050610738565b816020015151600003610738576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109225760008260200151828151811061076257610762615218565b6020026020010151905060008160000151905061077e81611483565b600061078982611585565b602084015151815491925067ffffffffffffffff908116610100909204161415806107cb575060208084015190810151905167ffffffffffffffff9182169116115b1561081457825160208401516040517feefb0cac00000000000000000000000000000000000000000000000000000000815261080b929190600401615328565b60405180910390fd5b604083015180610850576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff166000908152600960209081526040808320848452909152902054156108c35783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810182905260440161080b565b60208085015101516108d6906001615373565b825468ffffffffffffffff00191661010067ffffffffffffffff92831602179092559251166000908152600960209081526040808320948352939052919091204290555060010161073d565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610952919061539b565b60405180910390a16109ce60008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506115e5915050565b505050505050505050565b610a196109e882840184615438565b6040805160008082526020820190925290610a13565b60608152602001906001900390816109fe5790505b5061195c565b604080516000808252602082019092529050610a3c6001858585858660006115e5565b50505050565b610a4a611a0c565b610a5381611a68565b50565b6000610a646001600461546d565b6002610a71608085615496565b67ffffffffffffffff16610a8591906154bd565b610a8f8585611c60565b901c166003811115610aa357610aa3614257565b90505b92915050565b6001546001600160a01b03163314610b065760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161080b565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b72611ca7565b815181518114610bae576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610cfa576000848281518110610bcd57610bcd615218565b60200260200101519050600081602001515190506000858481518110610bf557610bf5615218565b6020026020010151905080518214610c39576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610ceb576000828281518110610c5857610c58615218565b6020026020010151905080600014610ce25784602001518281518110610c8057610c80615218565b602002602001015160800151811015610ce25784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018390526044810182905260640161080b565b50600101610c3c565b50505050806001019050610bb1565b50610d05838361195c565b505050565b610d12611a0c565b610a5381611d28565b610d5e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610e0757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610de9575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610e6957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e4b575b5050505050815250509050919050565b610e81611a0c565b60005b81811015610d05576000838383818110610ea057610ea0615218565b905060400201803603810190610eb691906154d4565b9050610ec581602001516113c2565b610f2a57805167ffffffffffffffff1660009081526009602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b50600101610e84565b60408051606080820183526000808352602080840182905283850183905267ffffffffffffffff8681168352600782529185902085519384018652805460ff811615158552610100900490921690830152600181018054939492939192840191610f9c9061550d565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc89061550d565b8015610e695780601f10610fea57610100808354040283529160200191610e69565b820191906000526020600020905b815481529060010190602001808311610ff857505050919092525091949350505050565b333014611055576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281611092565b604080518082019091526000808252602082015281526020019060019003908161106b5790505b5060a084015151909150156110c5576110c28360a001518460200151856060015186600001516020015186611fb4565b90505b6040805160a0810182528451518152845160209081015167ffffffffffffffff1681830152808601518351600094840192611101929101613e9e565b60408051601f19818403018152918152908252868101516020830152018390526005549091506001600160a01b0316801561120e576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a19061117b9085906004016155e9565b600060405180830381600087803b15801561119557600080fd5b505af19250505080156111a6575060015b61120e573d8080156111d4576040519150601f19603f3d011682016040523d82523d6000602084013e6111d9565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161080b9190613e9e565b60408501515115801561122357506080850151155b8061123a575060608501516001600160a01b03163b155b8061127a57506060850151611278906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000612092565b155b15611286575050505050565b60048054608087015160608801516040517f3cf9798300000000000000000000000000000000000000000000000000000000815260009485946001600160a01b031693633cf97983936112e1938a93611388939291016155fc565b6000604051808303816000875af1158015611300573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113289190810190615638565b50915091508161136657806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161080b9190613e9e565b50505050505050565b611377611a0c565b610a53816120ae565b611388611a0c565b60005b81518110156113be576113b68282815181106113a9576113a9615218565b6020026020010151612164565b60010161138b565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa15801561145f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa691906156ce565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561151e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154291906156ce565b15610a53576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080b565b67ffffffffffffffff81166000908152600760205260408120805460ff16610aa6576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080b565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906116448760a46156eb565b905082606001511561168c57845161165d9060206154bd565b865161166a9060206154bd565b6116759060a06156eb565b61167f91906156eb565b61168990826156eb565b90505b3681146116ce576040517f8e1192e10000000000000000000000000000000000000000000000000000000081526004810182905236602482015260440161080b565b50815181146117165781516040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440161080b565b61171e611ca7565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561176c5761176c614257565b600281111561177d5761177d614257565b905250905060028160200151600281111561179a5761179a614257565b1480156117ee5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106117d6576117d6615218565b6000918252602090912001546001600160a01b031633145b611824576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561190657602082015161183f9060016156fe565b60ff1685511461187b576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146118b6576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516118c8929190615717565b6040519081900381206118df918b90602001615727565b6040516020818303038152906040528051906020012090506119048a828888886124a8565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611996576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611a05576119fd8582815181106119cb576119cb615218565b6020026020010151846119f7578583815181106119ea576119ea615218565b60200260200101516126bf565b836126bf565b6001016119ad565b5050505050565b6000546001600160a01b03163314611a665760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161080b565b565b60a08101516001600160a01b03161580611a8a575080516001600160a01b0316155b15611ac1576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a177401000000000000000000000000000000000000000063ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16939093177c010000000000000000000000000000000000000000000000000000000093871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff19908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b67ffffffffffffffff8216600090815260086020526040812081611c8560808561573b565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b467f000000000000000000000000000000000000000000000000000000000000000014611a66576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161080b565b60005b81518110156113be576000828281518110611d4857611d48615218565b602002602001015190506000816000015190508067ffffffffffffffff16600003611d9f576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600760205260408120600181018054919291611dca9061550d565b80601f0160208091040260200160405190810160405280929190818152602001828054611df69061550d565b8015611e435780601f10611e1857610100808354040283529160200191611e43565b820191906000526020600020905b815481529060010190602001808311611e2657829003601f168201915b505050505090506000846040015190508151600003611efc578051600003611e97576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301611ea582826157aa565b50825468ffffffffffffffff00191661010017835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611f4f565b8080519060200120828051906020012014611f4f576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8516600482015260240161080b565b6020850151835460ff191690151517835560405167ffffffffffffffff8516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90611f9c90869061586a565b60405180910390a25050505050806001019050611d2b565b6060855167ffffffffffffffff811115611fd057611fd0614050565b60405190808252806020026020018201604052801561201557816020015b6040805180820190915260008082526020820152815260200190600190039081611fee5790505b50905060005b86518110156120885761206387828151811061203957612039615218565b602002602001015187878787868151811061205657612056615218565b6020026020010151612ecb565b82828151811061207557612075615218565b602090810291909101015260010161201b565b5095945050505050565b600061209d836132da565b8015610aa35750610aa3838361333e565b336001600160a01b038216036121065760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161080b565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff1660000361218f576000604051631b3fab5160e11b815260040161080b9190615926565b60208082015160ff808216600090815260029093526040832060018101549293909283921690036121fc57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612251565b6060840151600182015460ff6201000090910416151590151514612251576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff8416600482015260240161080b565b60a08401518051601f60ff82161115612280576001604051631b3fab5160e11b815260040161080b9190615926565b6122e685856003018054806020026020016040519081016040528092919081815260200182805480156122dc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122be575b505050505061340d565b8560600151156124155761235485856002018054806020026020016040519081016040528092919081815260200182805480156122dc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122be57505050505061340d565b6080860151805161236e9060028701906020840190613da8565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f10156123ce576002604051631b3fab5160e11b815260040161080b9190615926565b60408801516123de906003615940565b60ff168160ff1611612406576003604051631b3fab5160e11b815260040161080b9190615926565b61241287836001613476565b50505b61242185836002613476565b81516124369060038601906020850190613da8565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361248f938a939260028b0192919061595c565b60405180910390a16124a0856135f6565b505050505050565b6124b0613e1a565b835160005b818110156126b55760006001888684602081106124d4576124d4615218565b6124e191901a601b6156fe565b8985815181106124f3576124f3615218565b602002602001015189868151811061250d5761250d615218565b60200260200101516040516000815260200160405260405161254b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561256d573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156125ce576125ce614257565b60028111156125df576125df614257565b90525090506001816020015160028111156125fc576125fc614257565b14612633576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061264a5761264a615218565b602002015115612686576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f81106126a1576126a1615218565b9115156020909202015250506001016124b5565b5050505050505050565b81516126ca81611483565b60006126d582611585565b6020850151519091506000819003612718576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460400151518114612756576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561277157612771614050565b60405190808252806020026020018201604052801561279a578160200160208202803683370190505b50905060005b8281101561290f576000876020015182815181106127c0576127c0615218565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461285357805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080b565b6128e9818660010180546128669061550d565b80601f01602080910402602001604051908101604052809291908181526020018280546128929061550d565b80156128df5780601f106128b4576101008083540402835291602001916128df565b820191906000526020600020905b8154815290600101906020018083116128c257829003601f168201915b5050505050613612565b8383815181106128fb576128fb615218565b6020908102919091010152506001016127a0565b506000612926858389606001518a60800151613734565b90508060000361296e576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015260240161080b565b8551151560005b848110156109ce5760008960200151828151811061299557612995615218565b6020026020010151905060006129b389836000015160600151610a56565b905060028160038111156129c9576129c9614257565b03612a20578151606001516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612ec3565b6000816003811115612a3457612a34614257565b1480612a5157506003816003811115612a4f57612a4f614257565b145b612aa2578151606001516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c166004830152909116602482015260440161080b565b8315612b835760045460009074010000000000000000000000000000000000000000900463ffffffff16612ad6874261546d565b1190508080612af657506003826003811115612af457612af4614257565b145b612b38576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b16600482015260240161080b565b8a8481518110612b4a57612b4a615218565b6020026020010151600014612b7d578a8481518110612b6b57612b6b615218565b60200260200101518360800181815250505b50612be9565b6000816003811115612b9757612b97614257565b14612be9578151606001516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c166004830152909116602482015260440161080b565b81516080015167ffffffffffffffff1615612cd7576000816003811115612c1257612c12614257565b03612cd75781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c89928e9291906004016159e2565b6020604051808303816000875af1158015612ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ccc91906156ce565b612cd7575050612ec3565b60008b604001518481518110612cef57612cef615218565b6020026020010151905080518360a001515114612d53578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808d166004830152909116602482015260440161080b565b612d678a846000015160600151600161378a565b600080612d748584613832565b91509150612d8b8c8660000151606001518461378a565b8615612dfb576003826003811115612da557612da5614257565b03612dfb576000846003811115612dbe57612dbe614257565b14612dfb578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261080b91908390600401615a0f565b6002826003811115612e0f57612e0f614257565b14612e69576003826003811115612e2857612e28614257565b14612e69578451606001516040517f926c5a3e00000000000000000000000000000000000000000000000000000000815261080b918e918590600401615a28565b8451805160609091015160405167ffffffffffffffff918216918f16907f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df290612eb59087908790615a4e565b60405180910390a450505050505b600101612975565b60408051808201909152600080825260208201526000612eee87602001516138fc565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f979190615a6e565b90506001600160a01b0381161580612fdf5750612fdd6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000612092565b155b15613021576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240161080b565b6000806131276040518061010001604052808b81526020018967ffffffffffffffff1681526020018a6001600160a01b031681526020018c606001518152602001866001600160a01b031681526020018c6000015181526020018c604001518152602001888152506040516024016130999190615a8b565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f3907753700000000000000000000000000000000000000000000000000000000179052600454859063ffffffff7c01000000000000000000000000000000000000000000000000000000009091041661138860846139a2565b50915091508161316557806040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161080b9190613e9e565b80516020146131ad5780516040517f78ef802400000000000000000000000000000000000000000000000000000000815260206004820152602481019190915260440161080b565b6000818060200190518101906131c39190615b62565b6040516001600160a01b038b166024820152604481018290529091506132709060640160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052600454879063ffffffff78010000000000000000000000000000000000000000000000009091041661138860846139a2565b509093509150826132af57816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161080b9190613e9e565b604080518082019091526001600160a01b039095168552602085015250919250505095945050505050565b6000613306827f01ffc9a70000000000000000000000000000000000000000000000000000000061333e565b8015610aa65750613337827fffffffff0000000000000000000000000000000000000000000000000000000061333e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156133f6575060208210155b80156134025750600081115b979650505050505050565b60005b8151811015610d055760ff83166000908152600360205260408120835190919084908490811061344257613442615218565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613410565b60005b82518160ff161015610a3c576000838260ff168151811061349c5761349c615218565b60200260200101519050600060028111156134b9576134b9614257565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134f8576134f8614257565b14613519576004604051631b3fab5160e11b815260040161080b9190615926565b6001600160a01b038116613559576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561357f5761357f614257565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156135dc576135dc614257565b021790555090505050806135ef90615b7b565b9050613479565b60ff8116610a5357600a805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613658937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615b9a565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136a19794969395929491939101615bcd565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136d89190615cc4565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613742858585613ac8565b905061374d816113c2565b61375b576000915050613782565b67ffffffffffffffff86166000908152600960209081526040808320938352929052205490505b949350505050565b60006002613799608085615496565b67ffffffffffffffff166137ad91906154bd565b905060006137bb8585611c60565b9050816137ca6001600461546d565b901b1916818360038111156137e1576137e1614257565b67ffffffffffffffff871660009081526008602052604081209190921b9290921791829161381060808861573b565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fece670b6000000000000000000000000000000000000000000000000000000008152600090606090309063ece670b6906138769087908790600401615d24565b600060405180830381600087803b15801561389057600080fd5b505af19250505080156138a1575060015b6138e0573d8080156138cf576040519150601f19603f3d011682016040523d82523d6000602084013e6138d4565b606091505b506003925090506138f5565b50506040805160208101909152600081526002905b9250929050565b6000815160201461393b57816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161080b9190613e9e565b6000828060200190518101906139519190615b62565b90506001600160a01b03811180613969575061040081105b15610aa657826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161080b9190613e9e565b6000606060008361ffff1667ffffffffffffffff8111156139c5576139c5614050565b6040519080825280601f01601f1916602001820160405280156139ef576020820181803683370190505b509150863b613a22577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613a55577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613a8e577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613ab15750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b09576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b1d57506101018111155b613b3a576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613b64576040516309bde33960e01b815260040160405180910390fd5b80600003613b915786600081518110613b7f57613b7f615218565b60200260200101519350505050613d60565b60008167ffffffffffffffff811115613bac57613bac614050565b604051908082528060200260200182016040528015613bd5578160200160208202803683370190505b50905060008080805b85811015613cff5760006001821b8b811603613c395788851015613c22578c5160018601958e918110613c1357613c13615218565b60200260200101519050613c5b565b8551600185019487918110613c1357613c13615218565b8b5160018401938d918110613c5057613c50615218565b602002602001015190505b600089861015613c8b578d5160018701968f918110613c7c57613c7c615218565b60200260200101519050613cad565b8651600186019588918110613ca257613ca2615218565b602002602001015190505b82851115613cce576040516309bde33960e01b815260040160405180910390fd5b613cd88282613d67565b878481518110613cea57613cea615218565b60209081029190910101525050600101613bde565b506001850382148015613d1157508683145b8015613d1c57508581145b613d39576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613d4e57613d4e615218565b60200260200101519750505050505050505b9392505050565b6000818310613d7f57613d7a8284613d85565b610aa3565b610aa383835b604080516001602082015290810183905260608101829052600090608001613716565b828054828255906000526020600020908101928215613e0a579160200282015b82811115613e0a578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613dc8565b50613e16929150613e39565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613e165760008155600101613e3a565b60005b83811015613e69578181015183820152602001613e51565b50506000910152565b60008151808452613e8a816020860160208601613e4e565b601f01601f19169290920160200192915050565b602081526000610aa36020830184613e72565b8060608101831015610aa657600080fd5b60008083601f840112613ed457600080fd5b50813567ffffffffffffffff811115613eec57600080fd5b6020830191508360208285010111156138f557600080fd5b60008083601f840112613f1657600080fd5b50813567ffffffffffffffff811115613f2e57600080fd5b6020830191508360208260051b85010111156138f557600080fd5b60008060008060008060008060e0898b031215613f6557600080fd5b613f6f8a8a613eb1565b9750606089013567ffffffffffffffff80821115613f8c57600080fd5b613f988c838d01613ec2565b909950975060808b0135915080821115613fb157600080fd5b613fbd8c838d01613f04565b909750955060a08b0135915080821115613fd657600080fd5b50613fe38b828c01613f04565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561401157600080fd5b61401b8585613eb1565b9250606084013567ffffffffffffffff81111561403757600080fd5b61404386828701613ec2565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561408957614089614050565b60405290565b60405160a0810167ffffffffffffffff8111828210171561408957614089614050565b6040516080810167ffffffffffffffff8111828210171561408957614089614050565b6040516060810167ffffffffffffffff8111828210171561408957614089614050565b6040805190810167ffffffffffffffff8111828210171561408957614089614050565b604051601f8201601f1916810167ffffffffffffffff8111828210171561414457614144614050565b604052919050565b6001600160a01b0381168114610a5357600080fd5b803561416c8161414c565b919050565b803563ffffffff8116811461416c57600080fd5b600060c0828403121561419757600080fd5b61419f614066565b82356141aa8161414c565b81526141b860208401614171565b60208201526141c960408401614171565b60408201526141da60608401614171565b606082015260808301356141ed8161414c565b608082015260a08301356142008161414c565b60a08201529392505050565b803567ffffffffffffffff8116811461416c57600080fd5b6000806040838503121561423757600080fd5b6142408361420c565b915061424e6020840161420c565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b6004811061427d5761427d614257565b9052565b60208101610aa6828461426d565b600067ffffffffffffffff8211156142a9576142a9614050565b5060051b60200190565b600060a082840312156142c557600080fd5b6142cd61408f565b9050813581526142df6020830161420c565b60208201526142f06040830161420c565b60408201526143016060830161420c565b60608201526143126080830161420c565b608082015292915050565b600067ffffffffffffffff82111561433757614337614050565b50601f01601f191660200190565b600082601f83011261435657600080fd5b81356143696143648261431d565b61411b565b81815284602083860101111561437e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126143ac57600080fd5b813560206143bc6143648361428f565b82815260059290921b840181019181810190868411156143db57600080fd5b8286015b848110156144b157803567ffffffffffffffff808211156144005760008081fd5b8189019150608080601f19848d0301121561441b5760008081fd5b6144236140b2565b87840135838111156144355760008081fd5b6144438d8a83880101614345565b8252506040808501358481111561445a5760008081fd5b6144688e8b83890101614345565b8a84015250606080860135858111156144815760008081fd5b61448f8f8c838a0101614345565b92840192909252949092013593810193909352505083529183019183016143df565b509695505050505050565b600061014082840312156144cf57600080fd5b6144d7614066565b90506144e383836142b3565b815260a082013567ffffffffffffffff8082111561450057600080fd5b61450c85838601614345565b602084015260c084013591508082111561452557600080fd5b61453185838601614345565b604084015261454260e08501614161565b6060840152610100840135608084015261012084013591508082111561456757600080fd5b506145748482850161439b565b60a08301525092915050565b600082601f83011261459157600080fd5b813560206145a16143648361428f565b82815260059290921b840181019181810190868411156145c057600080fd5b8286015b848110156144b157803567ffffffffffffffff8111156145e45760008081fd5b6145f28986838b01016144bc565b8452509183019183016145c4565b600082601f83011261461157600080fd5b813560206146216143648361428f565b82815260059290921b8401810191818101908684111561464057600080fd5b8286015b848110156144b157803567ffffffffffffffff8111156146645760008081fd5b6146728986838b0101614345565b845250918301918301614644565b600082601f83011261469157600080fd5b813560206146a16143648361428f565b82815260059290921b840181019181810190868411156146c057600080fd5b8286015b848110156144b157803567ffffffffffffffff8111156146e45760008081fd5b6146f28986838b0101614600565b8452509183019183016146c4565b600082601f83011261471157600080fd5b813560206147216143648361428f565b8083825260208201915060208460051b87010193508684111561474357600080fd5b602086015b848110156144b15780358352918301918301614748565b600082601f83011261477057600080fd5b813560206147806143648361428f565b82815260059290921b8401810191818101908684111561479f57600080fd5b8286015b848110156144b157803567ffffffffffffffff808211156147c45760008081fd5b818901915060a080601f19848d030112156147df5760008081fd5b6147e761408f565b6147f288850161420c565b8152604080850135848111156148085760008081fd5b6148168e8b83890101614580565b8a840152506060808601358581111561482f5760008081fd5b61483d8f8c838a0101614680565b83850152506080915081860135858111156148585760008081fd5b6148668f8c838a0101614700565b91840191909152509190930135908301525083529183019183016147a3565b600080604080848603121561489957600080fd5b833567ffffffffffffffff808211156148b157600080fd5b6148bd8783880161475f565b94506020915081860135818111156148d457600080fd5b8601601f810188136148e557600080fd5b80356148f36143648261428f565b81815260059190911b8201840190848101908a83111561491257600080fd5b8584015b8381101561499e5780358681111561492e5760008081fd5b8501603f81018d136149405760008081fd5b878101356149506143648261428f565b81815260059190911b82018a0190898101908f8311156149705760008081fd5b928b01925b8284101561498e5783358252928a0192908a0190614975565b8652505050918601918601614916565b50809750505050505050509250929050565b6000602082840312156149c257600080fd5b813567ffffffffffffffff8111156149d957600080fd5b820160a08185031215613d6057600080fd5b8015158114610a5357600080fd5b803561416c816149eb565b60006020808385031215614a1757600080fd5b823567ffffffffffffffff80821115614a2f57600080fd5b818501915085601f830112614a4357600080fd5b8135614a516143648261428f565b81815260059190911b83018401908481019088831115614a7057600080fd5b8585015b83811015614b0057803585811115614a8c5760008081fd5b86016060818c03601f1901811315614aa45760008081fd5b614aac6140d5565b614ab78a840161420c565b8152604080840135614ac8816149eb565b828c0152918301359188831115614adf5760008081fd5b614aed8e8c85870101614345565b9082015285525050918601918601614a74565b5098975050505050505050565b803560ff8116811461416c57600080fd5b600060208284031215614b3057600080fd5b610aa382614b0d565b60008151808452602080850194506020840160005b83811015614b735781516001600160a01b031687529582019590820190600101614b4e565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614bcd60e0840182614b39565b90506040840151601f198483030160c0850152614bea8282614b39565b95945050505050565b60008060408385031215614c0657600080fd5b614c0f8361420c565b946020939093013593505050565b60008060208385031215614c3057600080fd5b823567ffffffffffffffff80821115614c4857600080fd5b818501915085601f830112614c5c57600080fd5b813581811115614c6b57600080fd5b8660208260061b8501011115614c8057600080fd5b60209290920196919550909350505050565b600060208284031215614ca457600080fd5b610aa38261420c565b6020815281511515602082015267ffffffffffffffff6020830151166040820152600060408301516060808401526137826080840182613e72565b60008060408385031215614cfb57600080fd5b823567ffffffffffffffff80821115614d1357600080fd5b614d1f868387016144bc565b93506020850135915080821115614d3557600080fd5b50614d4285828601614600565b9150509250929050565b600060208284031215614d5e57600080fd5b8135613d608161414c565b600082601f830112614d7a57600080fd5b81356020614d8a6143648361428f565b8083825260208201915060208460051b870101935086841115614dac57600080fd5b602086015b848110156144b1578035614dc48161414c565b8352918301918301614db1565b60006020808385031215614de457600080fd5b823567ffffffffffffffff80821115614dfc57600080fd5b818501915085601f830112614e1057600080fd5b8135614e1e6143648261428f565b81815260059190911b83018401908481019088831115614e3d57600080fd5b8585015b83811015614b0057803585811115614e5857600080fd5b860160c0818c03601f19011215614e6f5760008081fd5b614e77614066565b8882013581526040614e8a818401614b0d565b8a8301526060614e9b818501614b0d565b8284015260809150614eae8285016149f9565b9083015260a08381013589811115614ec65760008081fd5b614ed48f8d83880101614d69565b838501525060c0840135915088821115614eee5760008081fd5b614efc8e8c84870101614d69565b9083015250845250918601918601614e41565b600060208284031215614f2157600080fd5b5035919050565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461416c57600080fd5b600082601f830112614f6557600080fd5b81356020614f756143648361428f565b82815260069290921b84018101918181019086841115614f9457600080fd5b8286015b848110156144b15760408189031215614fb15760008081fd5b614fb96140f8565b614fc28261420c565b8152614fcf858301614f28565b81860152835291830191604001614f98565b600082601f830112614ff257600080fd5b813560206150026143648361428f565b82815260079290921b8401810191818101908684111561502157600080fd5b8286015b848110156144b157808803608081121561503f5760008081fd5b6150476140d5565b6150508361420c565b8152604080601f19840112156150665760008081fd5b61506e6140f8565b925061507b87850161420c565b835261508881850161420c565b8388015281870192909252606083013591810191909152835291830191608001615025565b600060208083850312156150c057600080fd5b823567ffffffffffffffff808211156150d857600080fd5b818501915060408083880312156150ee57600080fd5b6150f66140f8565b83358381111561510557600080fd5b84016040818a03121561511757600080fd5b61511f6140f8565b81358581111561512e57600080fd5b8201601f81018b1361513f57600080fd5b803561514d6143648261428f565b81815260069190911b8201890190898101908d83111561516c57600080fd5b928a01925b828410156151bc5787848f0312156151895760008081fd5b6151916140f8565b843561519c8161414c565b81526151a9858d01614f28565b818d0152825292870192908a0190615171565b8452505050818701359350848411156151d457600080fd5b6151e08a858401614f54565b81880152825250838501359150828211156151fa57600080fd5b61520688838601614fe1565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561529a57835180516001600160a01b031684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685840152928401929185019160010161524e565b50508583015187820388850152805180835290840192506000918401905b80831015615309578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906152b8565b50979650505050505050565b602081526000610aa3602083018461522e565b67ffffffffffffffff8316815260608101613d606020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153945761539461535d565b5092915050565b6000602080835260608451604080848701526153ba606087018361522e565b87850151878203601f19016040890152805180835290860193506000918601905b80831015614b0057845167ffffffffffffffff81511683528781015161541a89850182805167ffffffffffffffff908116835260209182015116910152565b508401518287015293860193600192909201916080909101906153db565b60006020828403121561544a57600080fd5b813567ffffffffffffffff81111561546157600080fd5b6137828482850161475f565b81810381811115610aa657610aa661535d565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154b1576154b1615480565b92169190910692915050565b8082028115828204841417610aa657610aa661535d565b6000604082840312156154e657600080fd5b6154ee6140f8565b6154f78361420c565b8152602083013560208201528091505092915050565b600181811c9082168061552157607f821691505b60208210810361554157634e487b7160e01b600052602260045260246000fd5b50919050565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261557b60a0870182613e72565b9050606085015186820360608801526155948282613e72565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561530957835180516001600160a01b03168352860151868301529285019260019290920191908401906155b7565b602081526000610aa36020830184615547565b60808152600061560f6080830187615547565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561564d57600080fd5b8351615658816149eb565b602085015190935067ffffffffffffffff81111561567557600080fd5b8401601f8101861361568657600080fd5b80516156946143648261431d565b8181528760208385010111156156a957600080fd5b6156ba826020830160208601613e4e565b809450505050604084015190509250925092565b6000602082840312156156e057600080fd5b8151613d60816149eb565b80820180821115610aa657610aa661535d565b60ff8181168382160190811115610aa657610aa661535d565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff8084168061575657615756615480565b92169190910492915050565b601f821115610d05576000816000526020600020601f850160051c8101602086101561578b5750805b601f850160051c820191505b818110156124a057828155600101615797565b815167ffffffffffffffff8111156157c4576157c4614050565b6157d8816157d2845461550d565b84615762565b602080601f83116001811461580d57600084156157f55750858301515b600019600386901b1c1916600185901b1785556124a0565b600085815260208120601f198616915b8281101561583c5788860151825594840194600190910190840161581d565b508582101561585a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352835460ff81161515602085015267ffffffffffffffff8160081c166040850152506001808501606080860152600081546158aa8161550d565b80608089015260a060018316600081146158cb57600181146158e757615917565b60ff19841660a08b015260a083151560051b8b01019450615917565b85600052602060002060005b8481101561590e5781548c82018501529088019089016158f3565b8b0160a0019550505b50929998505050505050505050565b602081016005831061593a5761593a614257565b91905290565b60ff81811683821602908116908181146153945761539461535d565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b818110156159b65784546001600160a01b031683526001948501949284019201615991565b505084810360608601526159ca8188614b39565b935050505060ff831660808301529695505050505050565b600067ffffffffffffffff808616835280851660208401525060606040830152614bea6060830184613e72565b8281526040602082015260006137826040830184613e72565b67ffffffffffffffff84811682528316602082015260608101613782604083018461426d565b615a58818461426d565b6040602082015260006137826040830184613e72565b600060208284031215615a8057600080fd5b8151613d608161414c565b6020815260008251610100806020850152615aaa610120850183613e72565b91506020850151615ac7604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615b0160a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615b1e8483613e72565b935060c08701519150808685030160e0870152615b3b8483613e72565b935060e0870151915080868503018387015250615b588382613e72565b9695505050505050565b600060208284031215615b7457600080fd5b5051919050565b600060ff821660ff8103615b9157615b9161535d565b60010192915050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152615b586080830184613e72565b86815260c060208201526000615be660c0830188613e72565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615cb757601f19868403018952815160808151818652615c6382870182613e72565b9150508582015185820387870152615c7b8282613e72565b91505060408083015186830382880152615c958382613e72565b6060948501519790940196909652505098840198925090830190600101615c3d565b5090979650505050505050565b602081526000610aa36020830184615c20565b60008282518085526020808601955060208260051b8401016020860160005b84811015615cb757601f19868403018952615d12838351613e72565b98840198925090830190600101615cf6565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615d8c610180850183613e72565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615dc98483613e72565b935060608801519150615de86101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615e0f8282615c20565b9150508281036020840152614bea8185615cd756fea164736f6c6343000818000a", -} - -var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI - -var EVM2EVMMultiOffRampBin = EVM2EVMMultiOffRampMetaData.Bin - -func DeployEVM2EVMMultiOffRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMMultiOffRampStaticConfig, dynamicConfig EVM2EVMMultiOffRampDynamicConfig, sourceChainConfigs []EVM2EVMMultiOffRampSourceChainConfigArgs) (common.Address, *types.Transaction, *EVM2EVMMultiOffRamp, error) { - parsed, err := EVM2EVMMultiOffRampMetaData.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(EVM2EVMMultiOffRampBin), backend, staticConfig, dynamicConfig, sourceChainConfigs) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &EVM2EVMMultiOffRamp{address: address, abi: *parsed, EVM2EVMMultiOffRampCaller: EVM2EVMMultiOffRampCaller{contract: contract}, EVM2EVMMultiOffRampTransactor: EVM2EVMMultiOffRampTransactor{contract: contract}, EVM2EVMMultiOffRampFilterer: EVM2EVMMultiOffRampFilterer{contract: contract}}, nil -} - -type EVM2EVMMultiOffRamp struct { - address common.Address - abi abi.ABI - EVM2EVMMultiOffRampCaller - EVM2EVMMultiOffRampTransactor - EVM2EVMMultiOffRampFilterer -} - -type EVM2EVMMultiOffRampCaller struct { - contract *bind.BoundContract -} - -type EVM2EVMMultiOffRampTransactor struct { - contract *bind.BoundContract -} - -type EVM2EVMMultiOffRampFilterer struct { - contract *bind.BoundContract -} - -type EVM2EVMMultiOffRampSession struct { - Contract *EVM2EVMMultiOffRamp - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type EVM2EVMMultiOffRampCallerSession struct { - Contract *EVM2EVMMultiOffRampCaller - CallOpts bind.CallOpts -} - -type EVM2EVMMultiOffRampTransactorSession struct { - Contract *EVM2EVMMultiOffRampTransactor - TransactOpts bind.TransactOpts -} - -type EVM2EVMMultiOffRampRaw struct { - Contract *EVM2EVMMultiOffRamp -} - -type EVM2EVMMultiOffRampCallerRaw struct { - Contract *EVM2EVMMultiOffRampCaller -} - -type EVM2EVMMultiOffRampTransactorRaw struct { - Contract *EVM2EVMMultiOffRampTransactor -} - -func NewEVM2EVMMultiOffRamp(address common.Address, backend bind.ContractBackend) (*EVM2EVMMultiOffRamp, error) { - abi, err := abi.JSON(strings.NewReader(EVM2EVMMultiOffRampABI)) - if err != nil { - return nil, err - } - contract, err := bindEVM2EVMMultiOffRamp(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRamp{address: address, abi: abi, EVM2EVMMultiOffRampCaller: EVM2EVMMultiOffRampCaller{contract: contract}, EVM2EVMMultiOffRampTransactor: EVM2EVMMultiOffRampTransactor{contract: contract}, EVM2EVMMultiOffRampFilterer: EVM2EVMMultiOffRampFilterer{contract: contract}}, nil -} - -func NewEVM2EVMMultiOffRampCaller(address common.Address, caller bind.ContractCaller) (*EVM2EVMMultiOffRampCaller, error) { - contract, err := bindEVM2EVMMultiOffRamp(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampCaller{contract: contract}, nil -} - -func NewEVM2EVMMultiOffRampTransactor(address common.Address, transactor bind.ContractTransactor) (*EVM2EVMMultiOffRampTransactor, error) { - contract, err := bindEVM2EVMMultiOffRamp(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampTransactor{contract: contract}, nil -} - -func NewEVM2EVMMultiOffRampFilterer(address common.Address, filterer bind.ContractFilterer) (*EVM2EVMMultiOffRampFilterer, error) { - contract, err := bindEVM2EVMMultiOffRamp(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampFilterer{contract: contract}, nil -} - -func bindEVM2EVMMultiOffRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EVM2EVMMultiOffRampMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMMultiOffRamp.Contract.EVM2EVMMultiOffRampCaller.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.EVM2EVMMultiOffRampTransactor.contract.Transfer(opts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.EVM2EVMMultiOffRampTransactor.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMMultiOffRamp.Contract.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.contract.Transfer(opts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "ccipReceive", arg0) - - if err != nil { - return err - } - - return err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) CcipReceive(arg0 ClientAny2EVMMessage) error { - return _EVM2EVMMultiOffRamp.Contract.CcipReceive(&_EVM2EVMMultiOffRamp.CallOpts, arg0) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) CcipReceive(arg0 ClientAny2EVMMessage) error { - return _EVM2EVMMultiOffRamp.Contract.CcipReceive(&_EVM2EVMMultiOffRamp.CallOpts, arg0) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampDynamicConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(EVM2EVMMultiOffRampDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOffRampDynamicConfig)).(*EVM2EVMMultiOffRampDynamicConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetDynamicConfig() (EVM2EVMMultiOffRampDynamicConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.GetDynamicConfig(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetDynamicConfig() (EVM2EVMMultiOffRampDynamicConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.GetDynamicConfig(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetExecutionState(opts *bind.CallOpts, sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getExecutionState", sourceChainSelector, sequenceNumber) - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetExecutionState(sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) { - return _EVM2EVMMultiOffRamp.Contract.GetExecutionState(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector, sequenceNumber) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetExecutionState(sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) { - return _EVM2EVMMultiOffRamp.Contract.GetExecutionState(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector, sequenceNumber) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getLatestPriceSequenceNumber") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetLatestPriceSequenceNumber() (uint64, error) { - return _EVM2EVMMultiOffRamp.Contract.GetLatestPriceSequenceNumber(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetLatestPriceSequenceNumber() (uint64, error) { - return _EVM2EVMMultiOffRamp.Contract.GetLatestPriceSequenceNumber(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetMerkleRoot(opts *bind.CallOpts, sourceChainSelector uint64, root [32]byte) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getMerkleRoot", sourceChainSelector, root) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetMerkleRoot(sourceChainSelector uint64, root [32]byte) (*big.Int, error) { - return _EVM2EVMMultiOffRamp.Contract.GetMerkleRoot(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector, root) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetMerkleRoot(sourceChainSelector uint64, root [32]byte) (*big.Int, error) { - return _EVM2EVMMultiOffRamp.Contract.GetMerkleRoot(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector, root) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) - - if err != nil { - return *new(EVM2EVMMultiOffRampSourceChainConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOffRampSourceChainConfig)).(*EVM2EVMMultiOffRampSourceChainConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetSourceChainConfig(sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.GetSourceChainConfig(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetSourceChainConfig(sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.GetSourceChainConfig(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampStaticConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(EVM2EVMMultiOffRampStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOffRampStaticConfig)).(*EVM2EVMMultiOffRampStaticConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetStaticConfig() (EVM2EVMMultiOffRampStaticConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.GetStaticConfig(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetStaticConfig() (EVM2EVMMultiOffRampStaticConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.GetStaticConfig(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "isBlessed", root) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) IsBlessed(root [32]byte) (bool, error) { - return _EVM2EVMMultiOffRamp.Contract.IsBlessed(&_EVM2EVMMultiOffRamp.CallOpts, root) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) IsBlessed(root [32]byte) (bool, error) { - return _EVM2EVMMultiOffRamp.Contract.IsBlessed(&_EVM2EVMMultiOffRamp.CallOpts, root) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "latestConfigDetails", ocrPluginType) - - if err != nil { - return *new(MultiOCR3BaseOCRConfig), err - } - - out0 := *abi.ConvertType(out[0], new(MultiOCR3BaseOCRConfig)).(*MultiOCR3BaseOCRConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) LatestConfigDetails(ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.LatestConfigDetails(&_EVM2EVMMultiOffRamp.CallOpts, ocrPluginType) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) LatestConfigDetails(ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { - return _EVM2EVMMultiOffRamp.Contract.LatestConfigDetails(&_EVM2EVMMultiOffRamp.CallOpts, ocrPluginType) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) Owner() (common.Address, error) { - return _EVM2EVMMultiOffRamp.Contract.Owner(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) Owner() (common.Address, error) { - return _EVM2EVMMultiOffRamp.Contract.Owner(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) TypeAndVersion() (string, error) { - return _EVM2EVMMultiOffRamp.Contract.TypeAndVersion(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) TypeAndVersion() (string, error) { - return _EVM2EVMMultiOffRamp.Contract.TypeAndVersion(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "acceptOwnership") -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.AcceptOwnership(&_EVM2EVMMultiOffRamp.TransactOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.AcceptOwnership(&_EVM2EVMMultiOffRamp.TransactOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []EVM2EVMMultiOffRampSourceChainConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "applySourceChainConfigUpdates", sourceChainConfigUpdates) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) ApplySourceChainConfigUpdates(sourceChainConfigUpdates []EVM2EVMMultiOffRampSourceChainConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ApplySourceChainConfigUpdates(&_EVM2EVMMultiOffRamp.TransactOpts, sourceChainConfigUpdates) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ApplySourceChainConfigUpdates(sourceChainConfigUpdates []EVM2EVMMultiOffRampSourceChainConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ApplySourceChainConfigUpdates(&_EVM2EVMMultiOffRamp.TransactOpts, sourceChainConfigUpdates) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "commit", reportContext, report, rs, ss, rawVs) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Commit(&_EVM2EVMMultiOffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Commit(&_EVM2EVMMultiOffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "execute", reportContext, report) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Execute(&_EVM2EVMMultiOffRamp.TransactOpts, reportContext, report) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Execute(&_EVM2EVMMultiOffRamp.TransactOpts, reportContext, report) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMMultiOffRamp.TransactOpts, message, offchainTokenData) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMMultiOffRamp.TransactOpts, message, offchainTokenData) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "manuallyExecute", reports, gasLimitOverrides) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) ManuallyExecute(reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ManuallyExecute(&_EVM2EVMMultiOffRamp.TransactOpts, reports, gasLimitOverrides) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ManuallyExecute(reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ManuallyExecute(&_EVM2EVMMultiOffRamp.TransactOpts, reports, gasLimitOverrides) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset []EVM2EVMMultiOffRampUnblessedRoot) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "resetUnblessedRoots", rootToReset) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) ResetUnblessedRoots(rootToReset []EVM2EVMMultiOffRampUnblessedRoot) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ResetUnblessedRoots(&_EVM2EVMMultiOffRamp.TransactOpts, rootToReset) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ResetUnblessedRoots(rootToReset []EVM2EVMMultiOffRampUnblessedRoot) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.ResetUnblessedRoots(&_EVM2EVMMultiOffRamp.TransactOpts, rootToReset) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMMultiOffRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) SetDynamicConfig(dynamicConfig EVM2EVMMultiOffRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetDynamicConfig(&_EVM2EVMMultiOffRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetDynamicConfig(dynamicConfig EVM2EVMMultiOffRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetDynamicConfig(&_EVM2EVMMultiOffRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setOCR3Configs", ocrConfigArgs) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) SetOCR3Configs(ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetOCR3Configs(&_EVM2EVMMultiOffRamp.TransactOpts, ocrConfigArgs) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetOCR3Configs(ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetOCR3Configs(&_EVM2EVMMultiOffRamp.TransactOpts, ocrConfigArgs) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "transferOwnership", to) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.TransferOwnership(&_EVM2EVMMultiOffRamp.TransactOpts, to) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.TransferOwnership(&_EVM2EVMMultiOffRamp.TransactOpts, to) -} - -type EVM2EVMMultiOffRampCommitReportAcceptedIterator struct { - Event *EVM2EVMMultiOffRampCommitReportAccepted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampCommitReportAcceptedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampCommitReportAccepted) - 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(EVM2EVMMultiOffRampCommitReportAccepted) - 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 *EVM2EVMMultiOffRampCommitReportAcceptedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampCommitReportAcceptedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampCommitReportAccepted struct { - Report EVM2EVMMultiOffRampCommitReport - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterCommitReportAccepted(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampCommitReportAcceptedIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "CommitReportAccepted") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampCommitReportAcceptedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "CommitReportAccepted", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampCommitReportAccepted) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "CommitReportAccepted") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampCommitReportAccepted) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "CommitReportAccepted", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseCommitReportAccepted(log types.Log) (*EVM2EVMMultiOffRampCommitReportAccepted, error) { - event := new(EVM2EVMMultiOffRampCommitReportAccepted) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "CommitReportAccepted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampConfigSetIterator struct { - Event *EVM2EVMMultiOffRampConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet) - 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(EVM2EVMMultiOffRampConfigSet) - 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 *EVM2EVMMultiOffRampConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampConfigSet struct { - OcrPluginType uint8 - ConfigDigest [32]byte - Signers []common.Address - Transmitters []common.Address - F uint8 - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.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(EVM2EVMMultiOffRampConfigSet) - if err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMMultiOffRampConfigSet, error) { - event := new(EVM2EVMMultiOffRampConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampDynamicConfigSetIterator struct { - Event *EVM2EVMMultiOffRampDynamicConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampDynamicConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampDynamicConfigSet) - 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(EVM2EVMMultiOffRampDynamicConfigSet) - 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 *EVM2EVMMultiOffRampDynamicConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampDynamicConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampDynamicConfigSet struct { - DynamicConfig EVM2EVMMultiOffRampDynamicConfig - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterDynamicConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampDynamicConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "DynamicConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampDynamicConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "DynamicConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampDynamicConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "DynamicConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampDynamicConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "DynamicConfigSet", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseDynamicConfigSet(log types.Log) (*EVM2EVMMultiOffRampDynamicConfigSet, error) { - event := new(EVM2EVMMultiOffRampDynamicConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "DynamicConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampExecutionStateChangedIterator struct { - Event *EVM2EVMMultiOffRampExecutionStateChanged - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampExecutionStateChanged) - 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(EVM2EVMMultiOffRampExecutionStateChanged) - 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 *EVM2EVMMultiOffRampExecutionStateChangedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampExecutionStateChanged struct { - SourceChainSelector uint64 - SequenceNumber uint64 - MessageId [32]byte - State uint8 - ReturnData []byte - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMMultiOffRampExecutionStateChangedIterator, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } - var sequenceNumberRule []interface{} - for _, sequenceNumberItem := range sequenceNumber { - sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) - } - var messageIdRule []interface{} - for _, messageIdItem := range messageId { - messageIdRule = append(messageIdRule, messageIdItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampExecutionStateChangedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ExecutionStateChanged", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } - var sequenceNumberRule []interface{} - for _, sequenceNumberItem := range sequenceNumber { - sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) - } - var messageIdRule []interface{} - for _, messageIdItem := range messageId { - messageIdRule = append(messageIdRule, messageIdItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampExecutionStateChanged) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseExecutionStateChanged(log types.Log) (*EVM2EVMMultiOffRampExecutionStateChanged, error) { - event := new(EVM2EVMMultiOffRampExecutionStateChanged) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMMultiOffRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampOwnershipTransferRequested) - 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(EVM2EVMMultiOffRampOwnershipTransferRequested) - 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 *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferRequestedIterator, 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 := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampOwnershipTransferRequestedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferRequested, 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 := _EVM2EVMMultiOffRamp.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(EVM2EVMMultiOffRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferRequested, error) { - event := new(EVM2EVMMultiOffRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampOwnershipTransferredIterator struct { - Event *EVM2EVMMultiOffRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampOwnershipTransferred) - 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(EVM2EVMMultiOffRampOwnershipTransferred) - 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 *EVM2EVMMultiOffRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferredIterator, 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 := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampOwnershipTransferredIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferred, 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 := _EVM2EVMMultiOffRamp.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(EVM2EVMMultiOffRampOwnershipTransferred) - if err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferred, error) { - event := new(EVM2EVMMultiOffRampOwnershipTransferred) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampRootRemovedIterator struct { - Event *EVM2EVMMultiOffRampRootRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampRootRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampRootRemoved) - 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(EVM2EVMMultiOffRampRootRemoved) - 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 *EVM2EVMMultiOffRampRootRemovedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampRootRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampRootRemoved struct { - Root [32]byte - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterRootRemoved(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampRootRemovedIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "RootRemoved") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampRootRemovedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "RootRemoved", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampRootRemoved) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "RootRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampRootRemoved) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "RootRemoved", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseRootRemoved(log types.Log) (*EVM2EVMMultiOffRampRootRemoved, error) { - event := new(EVM2EVMMultiOffRampRootRemoved) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "RootRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator struct { - Event *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - 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(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - 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 *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage struct { - SourceChainSelector uint64 - SequenceNumber uint64 - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedAlreadyExecutedMessage(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedAlreadyExecutedMessage") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedAlreadyExecutedMessage", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedAlreadyExecutedMessage(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedAlreadyExecutedMessage") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedAlreadyExecutedMessage(log types.Log) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage, error) { - event := new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampSourceChainConfigSetIterator struct { - Event *EVM2EVMMultiOffRampSourceChainConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSourceChainConfigSet) - 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(EVM2EVMMultiOffRampSourceChainConfigSet) - 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 *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampSourceChainConfigSet struct { - SourceChainSelector uint64 - SourceConfig EVM2EVMMultiOffRampSourceChainConfig - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*EVM2EVMMultiOffRampSourceChainConfigSetIterator, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampSourceChainConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SourceChainConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampSourceChainConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainConfigSet", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainConfigSet(log types.Log) (*EVM2EVMMultiOffRampSourceChainConfigSet, error) { - event := new(EVM2EVMMultiOffRampSourceChainConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampSourceChainSelectorAddedIterator struct { - Event *EVM2EVMMultiOffRampSourceChainSelectorAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSourceChainSelectorAdded) - 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(EVM2EVMMultiOffRampSourceChainSelectorAdded) - 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 *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampSourceChainSelectorAdded struct { - SourceChainSelector uint64 - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSourceChainSelectorAdded(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSourceChainSelectorAddedIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SourceChainSelectorAdded") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampSourceChainSelectorAddedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SourceChainSelectorAdded", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainSelectorAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainSelectorAdded) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SourceChainSelectorAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampSourceChainSelectorAdded) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainSelectorAdded(log types.Log) (*EVM2EVMMultiOffRampSourceChainSelectorAdded, error) { - event := new(EVM2EVMMultiOffRampSourceChainSelectorAdded) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampStaticConfigSetIterator struct { - Event *EVM2EVMMultiOffRampStaticConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampStaticConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampStaticConfigSet) - 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(EVM2EVMMultiOffRampStaticConfigSet) - 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 *EVM2EVMMultiOffRampStaticConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampStaticConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampStaticConfigSet struct { - StaticConfig EVM2EVMMultiOffRampStaticConfig - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterStaticConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampStaticConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "StaticConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampStaticConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "StaticConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchStaticConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampStaticConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "StaticConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampStaticConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "StaticConfigSet", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseStaticConfigSet(log types.Log) (*EVM2EVMMultiOffRampStaticConfigSet, error) { - event := new(EVM2EVMMultiOffRampStaticConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "StaticConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampTransmittedIterator struct { - Event *EVM2EVMMultiOffRampTransmitted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampTransmittedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTransmitted) - 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(EVM2EVMMultiOffRampTransmitted) - 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 *EVM2EVMMultiOffRampTransmittedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampTransmittedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampTransmitted struct { - OcrPluginType uint8 - ConfigDigest [32]byte - SequenceNumber uint64 - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*EVM2EVMMultiOffRampTransmittedIterator, error) { - - var ocrPluginTypeRule []interface{} - for _, ocrPluginTypeItem := range ocrPluginType { - ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "Transmitted", ocrPluginTypeRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampTransmittedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "Transmitted", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) { - - var ocrPluginTypeRule []interface{} - for _, ocrPluginTypeItem := range ocrPluginType { - ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "Transmitted", ocrPluginTypeRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampTransmitted) - if err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTransmitted(log types.Log) (*EVM2EVMMultiOffRampTransmitted, error) { - event := new(EVM2EVMMultiOffRampTransmitted) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Transmitted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _EVM2EVMMultiOffRamp.abi.Events["CommitReportAccepted"].ID: - return _EVM2EVMMultiOffRamp.ParseCommitReportAccepted(log) - case _EVM2EVMMultiOffRamp.abi.Events["ConfigSet"].ID: - return _EVM2EVMMultiOffRamp.ParseConfigSet(log) - case _EVM2EVMMultiOffRamp.abi.Events["DynamicConfigSet"].ID: - return _EVM2EVMMultiOffRamp.ParseDynamicConfigSet(log) - case _EVM2EVMMultiOffRamp.abi.Events["ExecutionStateChanged"].ID: - return _EVM2EVMMultiOffRamp.ParseExecutionStateChanged(log) - case _EVM2EVMMultiOffRamp.abi.Events["OwnershipTransferRequested"].ID: - return _EVM2EVMMultiOffRamp.ParseOwnershipTransferRequested(log) - case _EVM2EVMMultiOffRamp.abi.Events["OwnershipTransferred"].ID: - return _EVM2EVMMultiOffRamp.ParseOwnershipTransferred(log) - case _EVM2EVMMultiOffRamp.abi.Events["RootRemoved"].ID: - return _EVM2EVMMultiOffRamp.ParseRootRemoved(log) - case _EVM2EVMMultiOffRamp.abi.Events["SkippedAlreadyExecutedMessage"].ID: - return _EVM2EVMMultiOffRamp.ParseSkippedAlreadyExecutedMessage(log) - case _EVM2EVMMultiOffRamp.abi.Events["SourceChainConfigSet"].ID: - return _EVM2EVMMultiOffRamp.ParseSourceChainConfigSet(log) - case _EVM2EVMMultiOffRamp.abi.Events["SourceChainSelectorAdded"].ID: - return _EVM2EVMMultiOffRamp.ParseSourceChainSelectorAdded(log) - case _EVM2EVMMultiOffRamp.abi.Events["StaticConfigSet"].ID: - return _EVM2EVMMultiOffRamp.ParseStaticConfigSet(log) - case _EVM2EVMMultiOffRamp.abi.Events["Transmitted"].ID: - return _EVM2EVMMultiOffRamp.ParseTransmitted(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (EVM2EVMMultiOffRampCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0x3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d") -} - -func (EVM2EVMMultiOffRampConfigSet) Topic() common.Hash { - return common.HexToHash("0xab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547") -} - -func (EVM2EVMMultiOffRampDynamicConfigSet) Topic() common.Hash { - return common.HexToHash("0x0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c") -} - -func (EVM2EVMMultiOffRampExecutionStateChanged) Topic() common.Hash { - return common.HexToHash("0x8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df2") -} - -func (EVM2EVMMultiOffRampOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (EVM2EVMMultiOffRampOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (EVM2EVMMultiOffRampRootRemoved) Topic() common.Hash { - return common.HexToHash("0x202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12") -} - -func (EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) Topic() common.Hash { - return common.HexToHash("0x3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c") -} - -func (EVM2EVMMultiOffRampSourceChainConfigSet) Topic() common.Hash { - return common.HexToHash("0x4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba") -} - -func (EVM2EVMMultiOffRampSourceChainSelectorAdded) Topic() common.Hash { - return common.HexToHash("0xf4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb9") -} - -func (EVM2EVMMultiOffRampStaticConfigSet) Topic() common.Hash { - return common.HexToHash("0x683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d8") -} - -func (EVM2EVMMultiOffRampTransmitted) Topic() common.Hash { - return common.HexToHash("0x198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0") -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) Address() common.Address { - return _EVM2EVMMultiOffRamp.address -} - -type EVM2EVMMultiOffRampInterface interface { - CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error - - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampDynamicConfig, error) - - GetExecutionState(opts *bind.CallOpts, sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) - - GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) - - GetMerkleRoot(opts *bind.CallOpts, sourceChainSelector uint64, root [32]byte) (*big.Int, error) - - GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) - - GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampStaticConfig, error) - - IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) - - LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []EVM2EVMMultiOffRampSourceChainConfigArgs) (*types.Transaction, error) - - Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - - Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) - - ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) - - ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) - - ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset []EVM2EVMMultiOffRampUnblessedRoot) (*types.Transaction, error) - - SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMMultiOffRampDynamicConfig) (*types.Transaction, error) - - SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - FilterCommitReportAccepted(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampCommitReportAcceptedIterator, error) - - WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampCommitReportAccepted) (event.Subscription, error) - - ParseCommitReportAccepted(log types.Log) (*EVM2EVMMultiOffRampCommitReportAccepted, error) - - FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*EVM2EVMMultiOffRampConfigSet, error) - - FilterDynamicConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampDynamicConfigSetIterator, error) - - WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampDynamicConfigSet) (event.Subscription, error) - - ParseDynamicConfigSet(log types.Log) (*EVM2EVMMultiOffRampDynamicConfigSet, error) - - FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMMultiOffRampExecutionStateChangedIterator, error) - - WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) - - ParseExecutionStateChanged(log types.Log) (*EVM2EVMMultiOffRampExecutionStateChanged, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferred, error) - - FilterRootRemoved(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampRootRemovedIterator, error) - - WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampRootRemoved) (event.Subscription, error) - - ParseRootRemoved(log types.Log) (*EVM2EVMMultiOffRampRootRemoved, error) - - FilterSkippedAlreadyExecutedMessage(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator, error) - - WatchSkippedAlreadyExecutedMessage(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) (event.Subscription, error) - - ParseSkippedAlreadyExecutedMessage(log types.Log) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage, error) - - FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*EVM2EVMMultiOffRampSourceChainConfigSetIterator, error) - - WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) - - ParseSourceChainConfigSet(log types.Log) (*EVM2EVMMultiOffRampSourceChainConfigSet, error) - - FilterSourceChainSelectorAdded(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSourceChainSelectorAddedIterator, error) - - WatchSourceChainSelectorAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainSelectorAdded) (event.Subscription, error) - - ParseSourceChainSelectorAdded(log types.Log) (*EVM2EVMMultiOffRampSourceChainSelectorAdded, error) - - FilterStaticConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampStaticConfigSetIterator, error) - - WatchStaticConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampStaticConfigSet) (event.Subscription, error) - - ParseStaticConfigSet(log types.Log) (*EVM2EVMMultiOffRampStaticConfigSet, error) - - FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*EVM2EVMMultiOffRampTransmittedIterator, error) - - WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) - - ParseTransmitted(log types.Log) (*EVM2EVMMultiOffRampTransmitted, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go deleted file mode 100644 index e8c07cb93d6..00000000000 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go +++ /dev/null @@ -1,1489 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package evm_2_evm_multi_onramp - -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 ClientEVM2AnyMessage struct { - Receiver []byte - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - ExtraArgs []byte -} - -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - -type EVM2EVMMultiOnRampDynamicConfig struct { - Router common.Address - PriceRegistry common.Address - MessageValidator common.Address - FeeAggregator common.Address -} - -type EVM2EVMMultiOnRampStaticConfig struct { - ChainSelector uint64 - RmnProxy common.Address - NonceManager common.Address - TokenAdminRegistry common.Address -} - -type InternalEVM2AnyRampMessage struct { - Header InternalRampMessageHeader - Sender common.Address - Data []byte - Receiver []byte - ExtraArgs []byte - FeeToken common.Address - FeeTokenAmount *big.Int - TokenAmounts []InternalRampTokenAmount -} - -type InternalRampMessageHeader struct { - MessageId [32]byte - SourceChainSelector uint64 - DestChainSelector uint64 - SequenceNumber uint64 - Nonce uint64 -} - -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int -} - -var EVM2EVMMultiOnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"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\":[{\"indexed\":true,\"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\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"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\":[{\"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\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162003161380380620031618339810160408190526200003591620003db565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200017a565b505082516001600160401b031615905080620000e6575060208201516001600160a01b0316155b80620000fd575060408201516001600160a01b0316155b8062000114575060608201516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b81516001600160401b031660805260208201516001600160a01b0390811660a0526040830151811660c05260608301511660e052620001728162000225565b5050620004d1565b336001600160a01b03821603620001d45760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b031615806200024b575060608101516001600160a01b0316155b156200026a576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b604051608081016001600160401b0381118282101715620003b857634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b0381168114620003d657600080fd5b919050565b600080828403610100811215620003f157600080fd5b60808112156200040057600080fd5b6200040a62000387565b84516001600160401b03811681146200042257600080fd5b81526200043260208601620003be565b60208201526200044560408601620003be565b60408201526200045860608601620003be565b606082015292506080607f19820112156200047257600080fd5b506200047d62000387565b6200048b60808501620003be565b81526200049b60a08501620003be565b6020820152620004ae60c08501620003be565b6040820152620004c160e08501620003be565b6060820152809150509250929050565b60805160a05160c05160e051612c176200054a600039600081816101c00152818161081b015261147901526000818161018401528181610d3801526114520152600081816101480152818161044e015261142801526000818161011801528181610c55015281816110ee01526113fb0152612c176000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806379ba50971161008c578063a6f3ab6c11610066578063a6f3ab6c14610391578063df0aa9e9146103a4578063f2fde38b146103b7578063fbca3b74146103ca57600080fd5b806379ba50971461033f5780638da5cb5b146103475780639041be3d1461036557600080fd5b80633a019940116100bd5780633a0199401461027d57806348a98aa4146102875780637437ff9f146102bf57600080fd5b806306285c69146100e4578063181f5a771461021357806320487ded1461025c575b600080fd5b6101fd60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161020a9190611cf8565b60405180910390f35b61024f6040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161020a9190611dbd565b61026f61026a366004611dfe565b6103ea565b60405190815260200161020a565b6102856105a3565b005b61029a610295366004611e70565b6107d3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161020a565b610332604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161020a9190611ea9565b610285610888565b60005473ffffffffffffffffffffffffffffffffffffffff1661029a565b610378610373366004611ef2565b610985565b60405167ffffffffffffffff909116815260200161020a565b61028561039f366004611fc6565b6109ae565b61026f6103b236600461204b565b6109c2565b6102856103c53660046120b7565b6111a2565b6103dd6103d8366004611ef2565b6111b3565b60405161020a91906120d4565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610495573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b9919061213e565b15610501576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6003546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd90610559908690869060040161226d565b602060405180830381865afa158015610576573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059a91906123b6565b90505b92915050565b600354604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610612573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261065891908101906123cf565b60055490915073ffffffffffffffffffffffffffffffffffffffff1660005b82518110156107ce57600083828151811061069457610694612481565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561070f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073391906123b6565b905080156107c45761075c73ffffffffffffffffffffffffffffffffffffffff831685836111e7565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e836040516107bb91815260200190565b60405180910390a35b5050600101610677565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610864573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059a91906124b0565b60015473ffffffffffffffffffffffffffffffffffffffff163314610909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016104f8565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161059d911660016124fc565b6109b6611274565b6109bf816112f7565b50565b600073ffffffffffffffffffffffffffffffffffffffff8216610a11576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff163314610a62576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045473ffffffffffffffffffffffffffffffffffffffff168015610b08576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610ad5908990899060040161226d565b600060405180830381600087803b158015610aef57600080fd5b505af1158015610b03573d6000803e3d6000fd5b505050505b6003546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a610b3e60808c0160608d016120b7565b8a610b4c60808e018e612524565b6040518663ffffffff1660e01b8152600401610b6c959493929190612589565b600060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610bcf9190810190612651565b91945092509050610be66080890160608a016120b7565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f84604051610c2d91815260200190565b60405180910390a2604080516101a0810182526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528d8116610140850181905283526006602052938220805492948493610160850192918791610caa91166126a8565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186610daa576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015610d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da591906126cf565b610dad565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a8060200190610deb9190612524565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610e2f8b80612524565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610e7660808c018c612524565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610ec060808c0160608d016120b7565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190610ef191906126ec565b905067ffffffffffffffff811115610f0b57610f0b611f0f565b604051908082528060200260200182016040528015610f6757816020015b610f546040518060800160405280606081526020016060815260200160608152602001600081525090565b815260200190600190039081610f295790505b509052905060005b610f7c60408b018b6126ec565b905081101561102b57611002610f9560408c018c6126ec565b83818110610fa557610fa5612481565b905060400201803603810190610fbb9190612754565b8c610fc68d80612524565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506114dc915050565b8260e00151828151811061101857611018612481565b6020908102919091010152600101610f6f565b5060035460e082015173ffffffffffffffffffffffffffffffffffffffff9091169063cc88924c908c9061106260408e018e6126ec565b6040518563ffffffff1660e01b81526004016110819493929190612850565b60006040518083038186803b15801561109957600080fd5b505afa1580156110ad573d6000803e3d6000fd5b505050506080808201839052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c166060820152309181019190915261114a90829060a001604051602081830303815290604052805190602001206117e6565b81515260405167ffffffffffffffff8b16907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab2990611189908490612886565b60405180910390a251519450505050505b949350505050565b6111aa611274565b6109bf816118e6565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526107ce9084906119db565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104f8565b565b602081015173ffffffffffffffffffffffffffffffffffffffff1615806113365750606081015173ffffffffffffffffffffffffffffffffffffffff16155b1561136d576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32916114d19184906129d4565b60405180910390a150565b6115076040518060800160405280606081526020016060815260200160608152602001600081525090565b8460200151600003611545576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115558587600001516107d3565b905073ffffffffffffffffffffffffffffffffffffffff8116158061162557506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611623919061213e565b155b156116775785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016104f8565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b81526004016117169190612a73565b6000604051808303816000875af1158015611735573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261177b9190810190612ae9565b604080516080810190915273ffffffffffffffffffffffffffffffffffffffff841660a08201529091508060c0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c0015160405160200161182896959493929190612b7a565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161185f9190612bdb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104f8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611a3d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ae79092919063ffffffff16565b8051909150156107ce5780806020019051810190611a5b919061213e565b6107ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016104f8565b6060611af68484600085611b00565b90505b9392505050565b606082471015611b92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016104f8565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611bbb9190612bee565b60006040518083038185875af1925050503d8060008114611bf8576040519150601f19603f3d011682016040523d82523d6000602084013e611bfd565b606091505b5091509150611c0e87838387611c19565b979650505050505050565b60608315611caf578251600003611ca85773ffffffffffffffffffffffffffffffffffffffff85163b611ca8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104f8565b508161119a565b61119a8383815115611cc45781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104f89190611dbd565b6080810161059d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b83811015611d6a578181015183820152602001611d52565b50506000910152565b60008151808452611d8b816020860160208601611d4f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061059a6020830184611d73565b67ffffffffffffffff811681146109bf57600080fd5b600060a08284031215611df857600080fd5b50919050565b60008060408385031215611e1157600080fd5b8235611e1c81611dd0565b9150602083013567ffffffffffffffff811115611e3857600080fd5b611e4485828601611de6565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff811681146109bf57600080fd5b60008060408385031215611e8357600080fd5b8235611e8e81611dd0565b91506020830135611e9e81611e4e565b809150509250929050565b6080810161059d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b600060208284031215611f0457600080fd5b8135611af981611dd0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611f6157611f61611f0f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611fae57611fae611f0f565b604052919050565b8035611fc181611e4e565b919050565b600060808284031215611fd857600080fd5b6040516080810181811067ffffffffffffffff82111715611ffb57611ffb611f0f565b604052823561200981611e4e565b8152602083013561201981611e4e565b6020820152604083013561202c81611e4e565b6040820152606083013561203f81611e4e565b60608201529392505050565b6000806000806080858703121561206157600080fd5b843561206c81611dd0565b9350602085013567ffffffffffffffff81111561208857600080fd5b61209487828801611de6565b9350506040850135915060608501356120ac81611e4e565b939692955090935050565b6000602082840312156120c957600080fd5b8135611af981611e4e565b6020808252825182820181905260009190848201906040850190845b8181101561212257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016120f0565b50909695505050505050565b80518015158114611fc157600080fd5b60006020828403121561215057600080fd5b61059a8261212e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261218e57600080fd5b830160208101925035905067ffffffffffffffff8111156121ae57600080fd5b8036038213156121bd57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b8581101561226257813561223081611e4e565b73ffffffffffffffffffffffffffffffffffffffff16875281830135838801526040968701969091019060010161221d565b509495945050505050565b600067ffffffffffffffff80851683526040602084015261228e8485612159565b60a060408601526122a360e0860182846121c4565b9150506122b36020860186612159565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808785030160608801526122e98483856121c4565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe188360301831261232257600080fd5b6020928801928301923591508482111561233b57600080fd5b8160061b360383131561234d57600080fd5b8087850301608088015261236284838561220d565b945061237060608901611fb6565b73ffffffffffffffffffffffffffffffffffffffff811660a0890152935061239b6080890189612159565b94509250808786030160c08801525050611c0e8383836121c4565b6000602082840312156123c857600080fd5b5051919050565b600060208083850312156123e257600080fd5b825167ffffffffffffffff808211156123fa57600080fd5b818501915085601f83011261240e57600080fd5b81518181111561242057612420611f0f565b8060051b9150612431848301611f67565b818152918301840191848101908884111561244b57600080fd5b938501935b83851015612475578451925061246583611e4e565b8282529385019390850190612450565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156124c257600080fd5b8151611af981611e4e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561251d5761251d6124cd565b5092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261255957600080fd5b83018035915067ffffffffffffffff82111561257457600080fd5b6020019150368190038213156121bd57600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000611c0e6080830184866121c4565b600082601f8301126125e057600080fd5b815167ffffffffffffffff8111156125fa576125fa611f0f565b61262b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611f67565b81815284602083860101111561264057600080fd5b61119a826020830160208701611d4f565b60008060006060848603121561266657600080fd5b835192506126766020850161212e565b9150604084015167ffffffffffffffff81111561269257600080fd5b61269e868287016125cf565b9150509250925092565b600067ffffffffffffffff8083168181036126c5576126c56124cd565b6001019392505050565b6000602082840312156126e157600080fd5b8151611af981611dd0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261272157600080fd5b83018035915067ffffffffffffffff82111561273c57600080fd5b6020019150600681901b36038213156121bd57600080fd5b60006040828403121561276657600080fd5b61276e611f3e565b823561277981611e4e565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015612843577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189528151608081518186526127ef82870182611d73565b91505085820151858203878701526128078282611d73565b915050604080830151868303828801526128218382611d73565b60609485015197909401969096525050988401989250908301906001016127ab565b5090979650505050505050565b67ffffffffffffffff85168152606060208201526000612873606083018661278e565b8281036040840152611c0e81858761220d565b602081526128d760208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161290060c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e085015261291d6101a0850183611d73565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261295a8483611d73565b93506080870151915080868503016101208701526129788483611d73565b935060a087015191506129a461014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506129ca838261278e565b9695505050505050565b6101008101612a2c828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611af9565b602081526000825160a06020840152612a8f60c0840182611d73565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600060208284031215612afb57600080fd5b815167ffffffffffffffff80821115612b1357600080fd5b9083019060408286031215612b2757600080fd5b612b2f611f3e565b825182811115612b3e57600080fd5b612b4a878286016125cf565b825250602083015182811115612b5f57600080fd5b612b6b878286016125cf565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c06020840152612baa60c0840189611d73565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061059a602083018461278e565b60008251612c00818460208701611d4f565b919091019291505056fea164736f6c6343000818000a", -} - -var EVM2EVMMultiOnRampABI = EVM2EVMMultiOnRampMetaData.ABI - -var EVM2EVMMultiOnRampBin = EVM2EVMMultiOnRampMetaData.Bin - -func DeployEVM2EVMMultiOnRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMMultiOnRampStaticConfig, dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (common.Address, *types.Transaction, *EVM2EVMMultiOnRamp, error) { - parsed, err := EVM2EVMMultiOnRampMetaData.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(EVM2EVMMultiOnRampBin), backend, staticConfig, dynamicConfig) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &EVM2EVMMultiOnRamp{address: address, abi: *parsed, EVM2EVMMultiOnRampCaller: EVM2EVMMultiOnRampCaller{contract: contract}, EVM2EVMMultiOnRampTransactor: EVM2EVMMultiOnRampTransactor{contract: contract}, EVM2EVMMultiOnRampFilterer: EVM2EVMMultiOnRampFilterer{contract: contract}}, nil -} - -type EVM2EVMMultiOnRamp struct { - address common.Address - abi abi.ABI - EVM2EVMMultiOnRampCaller - EVM2EVMMultiOnRampTransactor - EVM2EVMMultiOnRampFilterer -} - -type EVM2EVMMultiOnRampCaller struct { - contract *bind.BoundContract -} - -type EVM2EVMMultiOnRampTransactor struct { - contract *bind.BoundContract -} - -type EVM2EVMMultiOnRampFilterer struct { - contract *bind.BoundContract -} - -type EVM2EVMMultiOnRampSession struct { - Contract *EVM2EVMMultiOnRamp - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type EVM2EVMMultiOnRampCallerSession struct { - Contract *EVM2EVMMultiOnRampCaller - CallOpts bind.CallOpts -} - -type EVM2EVMMultiOnRampTransactorSession struct { - Contract *EVM2EVMMultiOnRampTransactor - TransactOpts bind.TransactOpts -} - -type EVM2EVMMultiOnRampRaw struct { - Contract *EVM2EVMMultiOnRamp -} - -type EVM2EVMMultiOnRampCallerRaw struct { - Contract *EVM2EVMMultiOnRampCaller -} - -type EVM2EVMMultiOnRampTransactorRaw struct { - Contract *EVM2EVMMultiOnRampTransactor -} - -func NewEVM2EVMMultiOnRamp(address common.Address, backend bind.ContractBackend) (*EVM2EVMMultiOnRamp, error) { - abi, err := abi.JSON(strings.NewReader(EVM2EVMMultiOnRampABI)) - if err != nil { - return nil, err - } - contract, err := bindEVM2EVMMultiOnRamp(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRamp{address: address, abi: abi, EVM2EVMMultiOnRampCaller: EVM2EVMMultiOnRampCaller{contract: contract}, EVM2EVMMultiOnRampTransactor: EVM2EVMMultiOnRampTransactor{contract: contract}, EVM2EVMMultiOnRampFilterer: EVM2EVMMultiOnRampFilterer{contract: contract}}, nil -} - -func NewEVM2EVMMultiOnRampCaller(address common.Address, caller bind.ContractCaller) (*EVM2EVMMultiOnRampCaller, error) { - contract, err := bindEVM2EVMMultiOnRamp(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampCaller{contract: contract}, nil -} - -func NewEVM2EVMMultiOnRampTransactor(address common.Address, transactor bind.ContractTransactor) (*EVM2EVMMultiOnRampTransactor, error) { - contract, err := bindEVM2EVMMultiOnRamp(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampTransactor{contract: contract}, nil -} - -func NewEVM2EVMMultiOnRampFilterer(address common.Address, filterer bind.ContractFilterer) (*EVM2EVMMultiOnRampFilterer, error) { - contract, err := bindEVM2EVMMultiOnRamp(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampFilterer{contract: contract}, nil -} - -func bindEVM2EVMMultiOnRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EVM2EVMMultiOnRampMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMMultiOnRamp.Contract.EVM2EVMMultiOnRampCaller.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.EVM2EVMMultiOnRampTransactor.contract.Transfer(opts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.EVM2EVMMultiOnRampTransactor.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMMultiOnRamp.Contract.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.contract.Transfer(opts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampDynamicConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(EVM2EVMMultiOnRampDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOnRampDynamicConfig)).(*EVM2EVMMultiOnRampDynamicConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetDynamicConfig() (EVM2EVMMultiOnRampDynamicConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetDynamicConfig(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetDynamicConfig() (EVM2EVMMultiOnRampDynamicConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetDynamicConfig(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getExpectedNextSequenceNumber", destChainSelector) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { - return _EVM2EVMMultiOnRamp.Contract.GetExpectedNextSequenceNumber(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { - return _EVM2EVMMultiOnRamp.Contract.GetExpectedNextSequenceNumber(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getFee", destChainSelector, message) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - return _EVM2EVMMultiOnRamp.Contract.GetFee(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector, message) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - return _EVM2EVMMultiOnRamp.Contract.GetFee(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector, message) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetPoolBySourceToken(opts *bind.CallOpts, arg0 uint64, sourceToken common.Address) (common.Address, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getPoolBySourceToken", arg0, sourceToken) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetPoolBySourceToken(arg0 uint64, sourceToken common.Address) (common.Address, error) { - return _EVM2EVMMultiOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMMultiOnRamp.CallOpts, arg0, sourceToken) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetPoolBySourceToken(arg0 uint64, sourceToken common.Address) (common.Address, error) { - return _EVM2EVMMultiOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMMultiOnRamp.CallOpts, arg0, sourceToken) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampStaticConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(EVM2EVMMultiOnRampStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOnRampStaticConfig)).(*EVM2EVMMultiOnRampStaticConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetStaticConfig() (EVM2EVMMultiOnRampStaticConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetStaticConfig(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetStaticConfig() (EVM2EVMMultiOnRampStaticConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetStaticConfig(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetSupportedTokens(opts *bind.CallOpts, arg0 uint64) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getSupportedTokens", arg0) - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetSupportedTokens(arg0 uint64) ([]common.Address, error) { - return _EVM2EVMMultiOnRamp.Contract.GetSupportedTokens(&_EVM2EVMMultiOnRamp.CallOpts, arg0) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetSupportedTokens(arg0 uint64) ([]common.Address, error) { - return _EVM2EVMMultiOnRamp.Contract.GetSupportedTokens(&_EVM2EVMMultiOnRamp.CallOpts, arg0) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) Owner() (common.Address, error) { - return _EVM2EVMMultiOnRamp.Contract.Owner(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) Owner() (common.Address, error) { - return _EVM2EVMMultiOnRamp.Contract.Owner(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) TypeAndVersion() (string, error) { - return _EVM2EVMMultiOnRamp.Contract.TypeAndVersion(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) TypeAndVersion() (string, error) { - return _EVM2EVMMultiOnRamp.Contract.TypeAndVersion(&_EVM2EVMMultiOnRamp.CallOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "acceptOwnership") -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.AcceptOwnership(&_EVM2EVMMultiOnRamp.TransactOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.AcceptOwnership(&_EVM2EVMMultiOnRamp.TransactOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "forwardFromRouter", destChainSelector, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) ForwardFromRouter(destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ForwardFromRouter(&_EVM2EVMMultiOnRamp.TransactOpts, destChainSelector, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) ForwardFromRouter(destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ForwardFromRouter(&_EVM2EVMMultiOnRamp.TransactOpts, destChainSelector, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) SetDynamicConfig(dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.SetDynamicConfig(&_EVM2EVMMultiOnRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) SetDynamicConfig(dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.SetDynamicConfig(&_EVM2EVMMultiOnRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "transferOwnership", to) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.TransferOwnership(&_EVM2EVMMultiOnRamp.TransactOpts, to) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.TransferOwnership(&_EVM2EVMMultiOnRamp.TransactOpts, to) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) WithdrawFeeTokens(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "withdrawFeeTokens") -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) WithdrawFeeTokens() (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.WithdrawFeeTokens(&_EVM2EVMMultiOnRamp.TransactOpts) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) WithdrawFeeTokens() (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.WithdrawFeeTokens(&_EVM2EVMMultiOnRamp.TransactOpts) -} - -type EVM2EVMMultiOnRampAdminSetIterator struct { - Event *EVM2EVMMultiOnRampAdminSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampAdminSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampAdminSet) - 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(EVM2EVMMultiOnRampAdminSet) - 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 *EVM2EVMMultiOnRampAdminSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampAdminSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampAdminSet struct { - NewAdmin common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMMultiOnRampAdminSetIterator, error) { - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampAdminSetIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "AdminSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampAdminSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampAdminSet) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "AdminSet", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseAdminSet(log types.Log) (*EVM2EVMMultiOnRampAdminSet, error) { - event := new(EVM2EVMMultiOnRampAdminSet) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "AdminSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampCCIPSendRequestedIterator struct { - Event *EVM2EVMMultiOnRampCCIPSendRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampCCIPSendRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampCCIPSendRequested) - 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(EVM2EVMMultiOnRampCCIPSendRequested) - 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 *EVM2EVMMultiOnRampCCIPSendRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampCCIPSendRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampCCIPSendRequested struct { - DestChainSelector uint64 - Message InternalEVM2AnyRampMessage - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*EVM2EVMMultiOnRampCCIPSendRequestedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "CCIPSendRequested", destChainSelectorRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampCCIPSendRequestedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "CCIPSendRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "CCIPSendRequested", destChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampCCIPSendRequested) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "CCIPSendRequested", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseCCIPSendRequested(log types.Log) (*EVM2EVMMultiOnRampCCIPSendRequested, error) { - event := new(EVM2EVMMultiOnRampCCIPSendRequested) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampConfigSetIterator struct { - Event *EVM2EVMMultiOnRampConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampConfigSet) - 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(EVM2EVMMultiOnRampConfigSet) - 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 *EVM2EVMMultiOnRampConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampConfigSet struct { - StaticConfig EVM2EVMMultiOnRampStaticConfig - DynamicConfig EVM2EVMMultiOnRampDynamicConfig - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOnRampConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampConfigSetIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOnRamp.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(EVM2EVMMultiOnRampConfigSet) - if err := _EVM2EVMMultiOnRamp.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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMMultiOnRampConfigSet, error) { - event := new(EVM2EVMMultiOnRampConfigSet) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampFeePaidIterator struct { - Event *EVM2EVMMultiOnRampFeePaid - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampFeePaidIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampFeePaid) - 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(EVM2EVMMultiOnRampFeePaid) - 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 *EVM2EVMMultiOnRampFeePaidIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampFeePaidIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampFeePaid struct { - FeeToken common.Address - FeeValueJuels *big.Int - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*EVM2EVMMultiOnRampFeePaidIterator, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "FeePaid", feeTokenRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampFeePaidIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "FeePaid", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeePaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeePaid, feeToken []common.Address) (event.Subscription, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "FeePaid", feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampFeePaid) - if err := _EVM2EVMMultiOnRamp.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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseFeePaid(log types.Log) (*EVM2EVMMultiOnRampFeePaid, error) { - event := new(EVM2EVMMultiOnRampFeePaid) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampFeeTokenWithdrawnIterator struct { - Event *EVM2EVMMultiOnRampFeeTokenWithdrawn - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampFeeTokenWithdrawn) - 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(EVM2EVMMultiOnRampFeeTokenWithdrawn) - 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 *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampFeeTokenWithdrawn struct { - FeeAggregator common.Address - FeeToken common.Address - Amount *big.Int - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*EVM2EVMMultiOnRampFeeTokenWithdrawnIterator, error) { - - var feeAggregatorRule []interface{} - for _, feeAggregatorItem := range feeAggregator { - feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) - } - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampFeeTokenWithdrawnIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "FeeTokenWithdrawn", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) { - - var feeAggregatorRule []interface{} - for _, feeAggregatorItem := range feeAggregator { - feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) - } - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampFeeTokenWithdrawn) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseFeeTokenWithdrawn(log types.Log) (*EVM2EVMMultiOnRampFeeTokenWithdrawn, error) { - event := new(EVM2EVMMultiOnRampFeeTokenWithdrawn) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMMultiOnRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampOwnershipTransferRequested) - 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(EVM2EVMMultiOnRampOwnershipTransferRequested) - 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 *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferRequestedIterator, 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 := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampOwnershipTransferRequestedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferRequested, 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 := _EVM2EVMMultiOnRamp.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(EVM2EVMMultiOnRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOnRamp.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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferRequested, error) { - event := new(EVM2EVMMultiOnRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampOwnershipTransferredIterator struct { - Event *EVM2EVMMultiOnRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampOwnershipTransferred) - 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(EVM2EVMMultiOnRampOwnershipTransferred) - 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 *EVM2EVMMultiOnRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferredIterator, 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 := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampOwnershipTransferredIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferred, 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 := _EVM2EVMMultiOnRamp.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(EVM2EVMMultiOnRampOwnershipTransferred) - if err := _EVM2EVMMultiOnRamp.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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferred, error) { - event := new(EVM2EVMMultiOnRampOwnershipTransferred) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _EVM2EVMMultiOnRamp.abi.Events["AdminSet"].ID: - return _EVM2EVMMultiOnRamp.ParseAdminSet(log) - case _EVM2EVMMultiOnRamp.abi.Events["CCIPSendRequested"].ID: - return _EVM2EVMMultiOnRamp.ParseCCIPSendRequested(log) - case _EVM2EVMMultiOnRamp.abi.Events["ConfigSet"].ID: - return _EVM2EVMMultiOnRamp.ParseConfigSet(log) - case _EVM2EVMMultiOnRamp.abi.Events["FeePaid"].ID: - return _EVM2EVMMultiOnRamp.ParseFeePaid(log) - case _EVM2EVMMultiOnRamp.abi.Events["FeeTokenWithdrawn"].ID: - return _EVM2EVMMultiOnRamp.ParseFeeTokenWithdrawn(log) - case _EVM2EVMMultiOnRamp.abi.Events["OwnershipTransferRequested"].ID: - return _EVM2EVMMultiOnRamp.ParseOwnershipTransferRequested(log) - case _EVM2EVMMultiOnRamp.abi.Events["OwnershipTransferred"].ID: - return _EVM2EVMMultiOnRamp.ParseOwnershipTransferred(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (EVM2EVMMultiOnRampAdminSet) Topic() common.Hash { - return common.HexToHash("0x8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c") -} - -func (EVM2EVMMultiOnRampCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0x0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29") -} - -func (EVM2EVMMultiOnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32") -} - -func (EVM2EVMMultiOnRampFeePaid) Topic() common.Hash { - return common.HexToHash("0x075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f") -} - -func (EVM2EVMMultiOnRampFeeTokenWithdrawn) Topic() common.Hash { - return common.HexToHash("0x508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e") -} - -func (EVM2EVMMultiOnRampOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (EVM2EVMMultiOnRampOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRamp) Address() common.Address { - return _EVM2EVMMultiOnRamp.address -} - -type EVM2EVMMultiOnRampInterface interface { - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampDynamicConfig, error) - - GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) - - GetFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) - - GetPoolBySourceToken(opts *bind.CallOpts, arg0 uint64, sourceToken common.Address) (common.Address, error) - - GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampStaticConfig, error) - - GetSupportedTokens(opts *bind.CallOpts, arg0 uint64) ([]common.Address, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) - - SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - WithdrawFeeTokens(opts *bind.TransactOpts) (*types.Transaction, error) - - FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMMultiOnRampAdminSetIterator, error) - - WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampAdminSet) (event.Subscription, error) - - ParseAdminSet(log types.Log) (*EVM2EVMMultiOnRampAdminSet, error) - - FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*EVM2EVMMultiOnRampCCIPSendRequestedIterator, error) - - WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) - - ParseCCIPSendRequested(log types.Log) (*EVM2EVMMultiOnRampCCIPSendRequested, error) - - FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOnRampConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*EVM2EVMMultiOnRampConfigSet, error) - - FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*EVM2EVMMultiOnRampFeePaidIterator, error) - - WatchFeePaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeePaid, feeToken []common.Address) (event.Subscription, error) - - ParseFeePaid(log types.Log) (*EVM2EVMMultiOnRampFeePaid, error) - - FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*EVM2EVMMultiOnRampFeeTokenWithdrawnIterator, error) - - WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) - - ParseFeeTokenWithdrawn(log types.Log) (*EVM2EVMMultiOnRampFeeTokenWithdrawn, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferred, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_offramp/evm_2_evm_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_offramp/evm_2_evm_offramp.go index e4f47eb0a59..d1bfc5b47a8 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_offramp/evm_2_evm_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_offramp/evm_2_evm_offramp.go @@ -49,8 +49,11 @@ type EVM2EVMOffRampDynamicConfig struct { MaxNumberOfTokensPerMsg uint16 Router common.Address PriceRegistry common.Address - MaxPoolReleaseOrMintGas uint32 - MaxTokenTransferGas uint32 +} + +type EVM2EVMOffRampGasLimitOverride struct { + ReceiverExecutionGasLimit *big.Int + TokenGasOverrides []uint32 } type EVM2EVMOffRampRateLimitToken struct { @@ -106,8 +109,8 @@ type RateLimiterTokenBucket struct { } var EVM2EVMOffRampMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"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\"}],\"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\":\"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\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"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\":\"enumOCR2BaseNoChecks.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\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"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\":\"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\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"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\":\"err\",\"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\":[{\"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\":\"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\":\"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\":[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"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\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"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\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"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\":\"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\":[],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"sourceTokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"destTokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"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\":\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"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\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.RateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.RateLimitToken[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101a06040523480156200001257600080fd5b5060405162006213380380620062138339810160408190526200003591620004ec565b8033806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c081620002ca565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606080870182905298909601519091166080948501819052600380546001600160a01b031916909217600160801b9485021760ff60a01b1916600160a01b90930292909217905502909117600455469052508201516001600160a01b031615806200016f575081516001600160a01b0316155b8062000186575060c08201516001600160a01b0316155b15620001a5576040516342bcdf7f60e11b815260040160405180910390fd5b81600001516001600160a01b0316634120fccd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020e9190620005b5565b6001600160401b03166001146200023857604051636fc2a20760e11b815260040160405180910390fd5b81516001600160a01b0390811660a090815260408401516001600160401b0390811660c0908152602086015190911660e05260608501518316610100526080850151831661014052908401518216610160528301511661018052620002bd7f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b362000375565b6101205250620005da9050565b336001600160a01b03821603620003245760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008160c05160e05161010051604051602001620003bf94939291909384526001600160401b039283166020850152911660408301526001600160a01b0316606082015260800190565b604051602081830303815290604052805190602001209050919050565b60405160e081016001600160401b03811182821017156200040d57634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b03811681146200042b57600080fd5b919050565b80516001600160401b03811681146200042b57600080fd5b80516001600160801b03811681146200042b57600080fd5b6000606082840312156200047357600080fd5b604051606081016001600160401b0381118282101715620004a457634e487b7160e01b600052604160045260246000fd5b806040525080915082518015158114620004bd57600080fd5b8152620004cd6020840162000448565b6020820152620004e06040840162000448565b60408201525092915050565b6000808284036101408112156200050257600080fd5b60e08112156200051157600080fd5b506200051c620003dc565b620005278462000413565b8152620005376020850162000430565b60208201526200054a6040850162000430565b60408201526200055d6060850162000413565b6060820152620005706080850162000413565b60808201526200058360a0850162000413565b60a08201526200059660c0850162000413565b60c08201529150620005ac8460e0850162000460565b90509250929050565b600060208284031215620005c857600080fd5b620005d38262000430565b9392505050565b60805160a05160c05160e0516101005161012051610140516101605161018051615b4a620006c9600039600081816102ec01528181611b1201526133890152600081816102bd01528181611aeb0152611d9d01526000818161028e01528181610ed201528181610f3701528181611ac40152818161234501526123af01526000611f3c01526000818161025f0152611a9a0152600081816101ff0152611a4801526000818161022f01528181611a7201528181611d5a01528181612dc101526134980152600081816101d001528181611a1a015261201c015260008181611cb40152611d000152615b4a6000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806381ff7048116100d8578063afcb95d71161008c578063f077b59211610066578063f077b59214610646578063f2fde38b1461065c578063f52121a51461066f57600080fd5b8063afcb95d714610600578063b1dc65a414610620578063c92b28321461063357600080fd5b8063856c8247116100bd578063856c8247146105b0578063873504d7146105dc5780638da5cb5b146105ef57600080fd5b806381ff70481461057257806385572ffb146105a257600080fd5b8063599f64311161013a578063740f415011610114578063740f4150146104615780637437ff9f1461047457806379ba50971461056a57600080fd5b8063599f643114610414578063666cab8d14610439578063704b6c021461044e57600080fd5b8063181f5a771161016b578063181f5a77146103525780631ef381741461039b578063546719cd146103b057600080fd5b806306285c6914610187578063142a98fc14610332575b600080fd5b61031c6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040518060e001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161032991906141e7565b60405180910390f35b61034561034036600461427d565b610682565b60405161032991906142dd565b61038e6040518060400160405280601881526020017f45564d3245564d4f666652616d7020312e352e302d646576000000000000000081525081565b604051610329919061433b565b6103ae6103a93660046145aa565b6106fd565b005b6103b8610af1565b604051610329919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6002546001600160a01b03165b6040516001600160a01b039091168152602001610329565b610441610ba6565b60405161032991906146bc565b6103ae61045c3660046146cf565b610c08565b6103ae61046f366004614b2f565b610cd1565b61055d6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152506040805160e081018252600a5463ffffffff808216835264010000000082048116602084015261ffff68010000000000000000830416938301939093526001600160a01b036a010000000000000000000090910481166060830152600b549081166080830152740100000000000000000000000000000000000000008104831660a08301527801000000000000000000000000000000000000000000000000900490911660c082015290565b6040516103299190614bea565b6103ae610dc3565b6007546005546040805163ffffffff80851682526401000000009094049093166020840152820152606001610329565b6103ae610182366004614c58565b6105c36105be3660046146cf565b610ea6565b60405167ffffffffffffffff9091168152602001610329565b6103ae6105ea366004614d24565b610fa9565b6000546001600160a01b0316610421565b604080516001815260006020820181905291810191909152606001610329565b6103ae61062e366004614dcd565b611177565b6103ae610641366004614ed2565b611382565b61064e6113ed565b604051610329929190614f22565b6103ae61066a3660046146cf565b611513565b6103ae61067d366004614f47565b611524565b600061069060016004614fd0565b600261069d608085615012565b67ffffffffffffffff166106b19190615039565b601060006106c0608087615050565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c1660038111156106f7576106f761429a565b92915050565b84518460ff16601f82111561074a5760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016107419190615077565b60405180910390fd5b806000036107875760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016107419190615077565b61078f6117c4565b6107988561183a565b60095460005b8181101561080f5760086000600983815481106107bd576107bd615091565b60009182526020808320909101546001600160a01b03168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161079e565b5050865160005b818110156109b257600089828151811061083257610832615091565b602002602001015190506000600281111561084f5761084f61429a565b6001600160a01b038216600090815260086020526040902054610100900460ff1660028111156108815761088161429a565b146108bb5760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016107419190615077565b6001600160a01b0381166108fb576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff8316815260208101600290526001600160a01b03821660009081526008602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561099e5761099e61429a565b021790555090505050806001019050610816565b5087516109c69060099060208b0190614155565b506006805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908a161717905560078054610a4c914691309190600090610a1e9063ffffffff166150c0565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168c8c8c8c8c8c611b72565b6005819055600780544363ffffffff9081166401000000009081027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff841681179094556040519083048216947f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0594610add9487949293918316921691909117908f908f908f908f908f908f906150e3565b60405180910390a150505050505050505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff161515938301939093526004548084166060840152049091166080820152610ba190611bff565b905090565b60606009805480602002602001604051908101604052809291908181526020018280548015610bfe57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610be0575b5050505050905090565b6000546001600160a01b03163314801590610c2e57506002546001600160a01b03163314155b15610c65576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c9060200160405180910390a150565b610cd9611cb1565b81515181518114610d16576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610db3576000838281518110610d3557610d35615091565b6020026020010151905080600014610daa578451805183908110610d5b57610d5b615091565b602002602001015160800151811015610daa576040517f085e39cf0000000000000000000000000000000000000000000000000000000081526004810183905260248101829052604401610741565b50600101610d19565b50610dbe8383611d32565b505050565b6001546001600160a01b03163314610e37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610741565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6001600160a01b0381166000908152600f602052604081205467ffffffffffffffff168082036106f7577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156106f7576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015610f7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa29190615179565b9392505050565b610fb16117c4565b60005b825181101561108457610fee838281518110610fd257610fd2615091565b602002602001015160200151600c6127b590919063ffffffff16565b1561107c577fcbf3cbeaed4ac1d605ed30f4af06c35acaeff2379db7f6146c9cceee83d5878283828151811061102657611026615091565b60200260200101516000015184838151811061104457611044615091565b6020026020010151602001516040516110739291906001600160a01b0392831681529116602082015260400190565b60405180910390a15b600101610fb4565b5060005b8151811015610dbe576110e18282815181106110a6576110a6615091565b6020026020010151602001518383815181106110c4576110c4615091565b602002602001015160000151600c6127ca9092919063ffffffff16565b1561116f577ffc23abf7ddbd3c02b1420dafa2355c56c1a06fbb8723862ac14d6bd74177361a82828151811061111957611119615091565b60200260200101516000015183838151811061113757611137615091565b6020026020010151602001516040516111669291906001600160a01b0392831681529116602082015260400190565b60405180910390a15b600101611088565b61118187876127e8565b6005548835908082146111ca576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610741565b6111d2611cb1565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526008602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561125a5761125a61429a565b600281111561126b5761126b61429a565b90525090506002816020015160028111156112885761128861429a565b1480156112c257506009816000015160ff16815481106112aa576112aa615091565b6000918252602090912001546001600160a01b031633145b6112f8576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000611306856020615039565b611311886020615039565b61131d8b610144615196565b6113279190615196565b6113319190615196565b9050368114611375576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610741565b5050505050505050505050565b6000546001600160a01b031633148015906113a857506002546001600160a01b03163314155b156113df576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113ea60038261280f565b50565b60608060006113fc600c6129f4565b90508067ffffffffffffffff8111156114175761141761434e565b604051908082528060200260200182016040528015611440578160200160208202803683370190505b5092508067ffffffffffffffff81111561145c5761145c61434e565b604051908082528060200260200182016040528015611485578160200160208202803683370190505b50915060005b8181101561150d576000806114a1600c846129ff565b91509150808684815181106114b8576114b8615091565b60200260200101906001600160a01b031690816001600160a01b031681525050818584815181106114eb576114eb615091565b6001600160a01b0390921660209283029190910190910152505060010161148b565b50509091565b61151b6117c4565b6113ea81612a1d565b33301461155d576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516000808252602082019092528161159a565b60408051808201909152600080825260208201528152602001906001900390816115735790505b5061014084015151909150156115fa576115f783610140015184602001516040516020016115d791906001600160a01b0391909116815260200190565b604051602081830303815290604052856040015186610160015186612af8565b90505b6101208301515115801561161057506080830151155b80611627575060408301516001600160a01b03163b155b8061166757506040830151611665906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000612c29565b155b1561167157505050565b600080600a600001600a9054906101000a90046001600160a01b03166001600160a01b0316633cf979836040518060a001604052808861018001518152602001886000015167ffffffffffffffff16815260200188602001516040516020016116e991906001600160a01b0391909116815260200190565b6040516020818303038152906040528152602001886101200151815260200186815250611388886080015189604001516040518563ffffffff1660e01b815260040161173894939291906151ee565b6000604051808303816000875af1158015611757573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261177f91908101906152f8565b5091509150816117bd57806040517f0a8d6e8c000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b5050505050565b6000546001600160a01b03163314611838576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610741565b565b6000818060200190518101906118509190615371565b60608101519091506001600160a01b0316611897576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600a80546020808501516040808701516060808901516001600160a01b039081166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff61ffff9094166801000000000000000002939093167fffff00000000000000000000000000000000000000000000ffffffffffffffff63ffffffff968716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009099169a87169a909a1797909717989098169590951717909455608080870151600b805460a0808b015160c0808d015188167801000000000000000000000000000000000000000000000000027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff9290981674010000000000000000000000000000000000000000027fffffffffffffffff000000000000000000000000000000000000000000000000909416958c16959095179290921791909116949094179055855160e0810187527f00000000000000000000000000000000000000000000000000000000000000008816815267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116958201959095527f0000000000000000000000000000000000000000000000000000000000000000909416848701527f00000000000000000000000000000000000000000000000000000000000000008716948401949094527f00000000000000000000000000000000000000000000000000000000000000008616908301527f00000000000000000000000000000000000000000000000000000000000000008516908201527f000000000000000000000000000000000000000000000000000000000000000090931690830152517ff02fcc22535d64d92d17b995475893d63edd51da163fed74a6ee9b4bc4895cc491611b6691849061540c565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a604051602001611b96999897969594939291906154e8565b60408051601f1981840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c8d82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c719190614fd0565b85608001516fffffffffffffffffffffffffffffffff16612c45565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b467f000000000000000000000000000000000000000000000000000000000000000014611838576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610741565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015611dec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e109190615570565b15611e47576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516000819003611e84576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260200151518114611ec2576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff811115611edd57611edd61434e565b604051908082528060200260200182016040528015611f06578160200160208202803683370190505b50905060005b82811015611fde57600085600001518281518110611f2c57611f2c615091565b60200260200101519050611f60817f0000000000000000000000000000000000000000000000000000000000000000612c64565b838381518110611f7257611f72615091565b602002602001018181525050806101800151838381518110611f9657611f96615091565b602002602001015114611fd5576040517f7185cf6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600101611f0c565b50604080850151606086015191517f320488750000000000000000000000000000000000000000000000000000000081526000926001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692633204887592612052928792916004016155be565b602060405180830381865afa15801561206f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209391906155f4565b9050806000036120cf576040517fea75680100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351151560005b848110156127ac576000876000015182815181106120f6576120f6615091565b60200260200101519050600061210f8260600151610682565b905060028160038111156121255761212561429a565b0361216c57816060015167ffffffffffffffff167fe3dd0bec917c965a133ddb2c84874725ee1e2fd8d763c19efa36d6a11cd82b1f60405160405180910390a250506127a4565b60008160038111156121805761218061429a565b148061219d5750600381600381111561219b5761219b61429a565b145b6121e55760608201516040517f50a6e05200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b83156122a257600a5460009063ffffffff166122018742614fd0565b11905080806122215750600382600381111561221f5761221f61429a565b145b612257576040517f6358b0d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b88848151811061226957612269615091565b602002602001015160001461229c5788848151811061228a5761228a615091565b60200260200101518360800181815250505b506122ff565b60008160038111156122b6576122b661429a565b146122ff5760608201516040517f67d9ba0f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b60c082015167ffffffffffffffff161561257e576020808301516001600160a01b03166000908152600f909152604081205467ffffffffffffffff16908190036124e9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156124e95760208301516040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063856c824790602401602060405180830381865afa1580156123f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241c9190615179565b60c084015190915067ffffffffffffffff1661243982600161560d565b67ffffffffffffffff16146124995782602001516001600160a01b03168360c0015167ffffffffffffffff167fe44a20935573a783dd0d5991c92d7b6a0eb3173566530364db3ec10e9a990b5d60405160405180910390a35050506127a4565b6020838101516001600160a01b03166000908152600f9091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83161790555b60008260038111156124fd576124fd61429a565b0361257c5760c083015167ffffffffffffffff1661251c82600161560d565b67ffffffffffffffff161461257c5782602001516001600160a01b03168360c0015167ffffffffffffffff167fd32ddb11d71e3d63411d37b09f9a8b28664f1cb1338bfd1413c173b0ebf4123760405160405180910390a35050506127a4565b505b60008960200151848151811061259657612596615091565b602002602001015190506125c28360600151846000015185610140015151866101200151518551612dbf565b6125d183606001516001612f39565b6000806125de8584612fe3565b915091506125f0856060015183612f39565b861561265c57600382600381111561260a5761260a61429a565b0361265c5760008460038111156126235761262361429a565b1461265c57806040517fcf19edfd000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b60028260038111156126705761267061429a565b146126c85760038260038111156126895761268961429a565b146126c8578460600151826040517f9e26160300000000000000000000000000000000000000000000000000000000815260040161074192919061562e565b60c085015167ffffffffffffffff16156127505760008460038111156126f0576126f061429a565b03612750576020808601516001600160a01b03166000908152600f90915260408120805467ffffffffffffffff16916127288361564c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b846101800151856060015167ffffffffffffffff167fd4f851956a5d67c3997d1c9205045fef79bae2947fdee7e9e2641abc7391ef658484604051612796929190615669565b60405180910390a350505050505b6001016120d6565b50505050505050565b6000610fa2836001600160a01b0384166132d6565b60006127e0846001600160a01b038516846132e2565b949350505050565b61280b6127f782840184615689565b604080516000815260208101909152611d32565b5050565b815460009061283890700100000000000000000000000000000000900463ffffffff1642614fd0565b905080156128da5760018301548354612880916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612c45565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612900916fffffffffffffffffffffffffffffffff90811691166132f8565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906129e79084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b60405180910390a1505050565b60006106f78261330e565b6000808080612a0e8686613319565b909450925050505b9250929050565b336001600160a01b03821603612a8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610741565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b846000805b8751811015612c0e57612b75888281518110612b1b57612b1b615091565b6020026020010151602001518888888581518110612b3b57612b3b615091565b6020026020010151806020019051810190612b5691906156be565b888681518110612b6857612b68615091565b6020026020010151613328565b838281518110612b8757612b87615091565b6020026020010181905250612bc3838281518110612ba757612ba7615091565b602002602001015160000151600c61374b90919063ffffffff16565b15612c0657612bf9838281518110612bdd57612bdd615091565b6020908102919091010151600b546001600160a01b0316613760565b612c039083615196565b91505b600101612afd565b508015612c1e57612c1e81613881565b505b95945050505050565b6000612c348361388e565b8015610fa25750610fa283836138f2565b6000612c2085612c558486615039565b612c5f9087615196565b6132f8565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001612cfa9897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b6040516020818303038152906040528051906020012085610120015180519060200120866101400151604051602001612d339190615773565b60405160208183030381529060405280519060200120876101600151604051602001612d5f91906157e0565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168467ffffffffffffffff1614612e38576040517f1279ec8a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610741565b600a5468010000000000000000900461ffff16831115612e90576040517f099d3f7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610741565b808314612ed5576040517f8808f8e700000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610741565b600a54640100000000900463ffffffff168211156117bd57600a546040517f8693378900000000000000000000000000000000000000000000000000000000815264010000000090910463ffffffff16600482015260248101839052604401610741565b60006002612f48608085615012565b67ffffffffffffffff16612f5c9190615039565b90506000601081612f6e608087615050565b67ffffffffffffffff168152602081019190915260400160002054905081612f9860016004614fd0565b901b191681836003811115612faf57612faf61429a565b901b178060106000612fc2608088615050565b67ffffffffffffffff16815260208101919091526040016000205550505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a59061302790879087906004016157f3565b600060405180830381600087803b15801561304157600080fd5b505af1925050508015613052575060015b6132bb573d808015613080576040519150601f19603f3d011682016040523d82523d6000602084013e613085565b606091505b5061308f81615956565b7fffffffff00000000000000000000000000000000000000000000000000000000167f0a8d6e8c00000000000000000000000000000000000000000000000000000000148061312757506130e281615956565b7fffffffff00000000000000000000000000000000000000000000000000000000167fe1cd550900000000000000000000000000000000000000000000000000000000145b8061317b575061313681615956565b7fffffffff00000000000000000000000000000000000000000000000000000000167f8d666f6000000000000000000000000000000000000000000000000000000000145b806131cf575061318a81615956565b7fffffffff00000000000000000000000000000000000000000000000000000000167f78ef802400000000000000000000000000000000000000000000000000000000145b8061322357506131de81615956565b7fffffffff00000000000000000000000000000000000000000000000000000000167f0c3b563c00000000000000000000000000000000000000000000000000000000145b80613277575061323281615956565b7fffffffff00000000000000000000000000000000000000000000000000000000167fae9b4ce900000000000000000000000000000000000000000000000000000000145b1561328757600392509050612a16565b806040517fcf19edfd000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b50506040805160208101909152600081526002909250929050565b6000610fa283836139c1565b60006127e084846001600160a01b0385166139de565b60008183106133075781610fa2565b5090919050565b60006106f7826139fb565b6000808080612a0e8686613a06565b6040805180820190915260008082526020820152600061334b8460200151613a31565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa1580156133d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f491906159a6565b90506001600160a01b038116158061343c575061343a6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000612c29565b155b1561347e576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610741565b6000806135986040518061010001604052808b81526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020018a6001600160a01b031681526020018c8152602001866001600160a01b0316815260200189600001518152602001896040015181526020018881525060405160240161351291906159c3565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f3907753700000000000000000000000000000000000000000000000000000000179052600b54859063ffffffff74010000000000000000000000000000000000000000909104166113886084613ad7565b5091509150816135d657806040517fe1cd5509000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b805160201461361e5780516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610741565b60008180602001905181019061363491906155f4565b6040516001600160a01b038b166024820152604481018290529091506136e19060640160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052600b54879063ffffffff7801000000000000000000000000000000000000000000000000909104166113886084613ad7565b5090935091508261372057816040517fe1cd5509000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b604080518082019091526001600160a01b039095168552602085015250919250505095945050505050565b6000610fa2836001600160a01b038416613bfd565b81516040517fd02641a00000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260009182919084169063d02641a0906024016040805180830381865afa1580156137c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ea9190615a9a565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81166000036138535783516040517f9a655f7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610741565b60208401516127e0907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690613c09565b6113ea6003826000613c46565b60006138ba827f01ffc9a7000000000000000000000000000000000000000000000000000000006138f2565b80156106f757506138eb827fffffffff000000000000000000000000000000000000000000000000000000006138f2565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156139aa575060208210155b80156139b65750600081115b979650505050505050565b60008181526002830160205260408120819055610fa28383613f95565b600082815260028401602052604081208290556127e08484613fa1565b60006106f782613fad565b60008080613a148585613fb7565b600081815260029690960160205260409095205494959350505050565b60008151602014613a7057816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b600082806020019051810190613a8691906155f4565b90506001600160a01b03811180613a9e575061040081105b156106f757826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610741919061433b565b6000606060008361ffff1667ffffffffffffffff811115613afa57613afa61434e565b6040519080825280601f01601f191660200182016040528015613b24576020820181803683370190505b509150863b613b57577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b8a577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613bc3577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613be65750835b808352806000602085013e50955095509592505050565b6000610fa28383613fc3565b6000670de0b6b3a7640000613c3c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615039565b610fa29190615afa565b825474010000000000000000000000000000000000000000900460ff161580613c6d575081155b15613c7757505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090613cbd90700100000000000000000000000000000000900463ffffffff1642614fd0565b90508015613d7d5781831115613cff576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154613d399083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612c45565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015613e1a576001600160a01b038416613dcf576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610741565b6040517f1a76572a00000000000000000000000000000000000000000000000000000000815260048101839052602481018690526001600160a01b0385166044820152606401610741565b84831015613f135760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290613e5e9082614fd0565b613e68878a614fd0565b613e729190615196565b613e7c9190615afa565b90506001600160a01b038616613ec8576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610741565b6040517fd0c8d23a00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526001600160a01b0387166044820152606401610741565b613f1d8584614fd0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000610fa28383613fe2565b6000610fa283836140dc565b60006106f7825490565b6000610fa2838361412b565b6000610fa2838360008181526001830160205260408120541515610fa2565b600081815260018301602052604081205480156140cb576000614006600183614fd0565b855490915060009061401a90600190614fd0565b905081811461407f57600086600001828154811061403a5761403a615091565b906000526020600020015490508087600001848154811061405d5761405d615091565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061409057614090615b0e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f7565b60009150506106f7565b5092915050565b6000818152600183016020526040812054614123575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f7565b5060006106f7565b600082600001828154811061414257614142615091565b9060005260206000200154905092915050565b8280548282559060005260206000209081019282156141c2579160200282015b828111156141c257825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909116178255602090920191600190910190614175565b506141ce9291506141d2565b5090565b5b808211156141ce57600081556001016141d3565b60e081016106f782846001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015250508060608301511660608401528060808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b67ffffffffffffffff811681146113ea57600080fd5b803561427881614257565b919050565b60006020828403121561428f57600080fd5b8135610fa281614257565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106142d9576142d961429a565b9052565b602081016106f782846142c9565b60005b838110156143065781810151838201526020016142ee565b50506000910152565b600081518084526143278160208601602086016142eb565b601f01601f19169290920160200192915050565b602081526000610fa2602083018461430f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156143a0576143a061434e565b60405290565b6040516101a0810167ffffffffffffffff811182821017156143a0576143a061434e565b6040516080810167ffffffffffffffff811182821017156143a0576143a061434e565b6040516060810167ffffffffffffffff811182821017156143a0576143a061434e565b60405160e0810167ffffffffffffffff811182821017156143a0576143a061434e565b604051601f8201601f1916810167ffffffffffffffff8111828210171561445c5761445c61434e565b604052919050565b600067ffffffffffffffff82111561447e5761447e61434e565b5060051b60200190565b6001600160a01b03811681146113ea57600080fd5b803561427881614488565b600082601f8301126144b957600080fd5b813560206144ce6144c983614464565b614433565b8083825260208201915060208460051b8701019350868411156144f057600080fd5b602086015b8481101561451557803561450881614488565b83529183019183016144f5565b509695505050505050565b803560ff8116811461427857600080fd5b600067ffffffffffffffff82111561454b5761454b61434e565b50601f01601f191660200190565b600082601f83011261456a57600080fd5b81356145786144c982614531565b81815284602083860101111561458d57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c087890312156145c357600080fd5b863567ffffffffffffffff808211156145db57600080fd5b6145e78a838b016144a8565b975060208901359150808211156145fd57600080fd5b6146098a838b016144a8565b965061461760408a01614520565b9550606089013591508082111561462d57600080fd5b6146398a838b01614559565b945061464760808a0161426d565b935060a089013591508082111561465d57600080fd5b5061466a89828a01614559565b9150509295509295509295565b60008151808452602080850194506020840160005b838110156146b15781516001600160a01b03168752958201959082019060010161468c565b509495945050505050565b602081526000610fa26020830184614677565b6000602082840312156146e157600080fd5b8135610fa281614488565b80151581146113ea57600080fd5b8035614278816146ec565b600082601f83011261471657600080fd5b813560206147266144c983614464565b82815260069290921b8401810191818101908684111561474557600080fd5b8286015b8481101561451557604081890312156147625760008081fd5b61476a61437d565b813561477581614488565b81528185013585820152835291830191604001614749565b600082601f83011261479e57600080fd5b813560206147ae6144c983614464565b82815260059290921b840181019181810190868411156147cd57600080fd5b8286015b8481101561451557803567ffffffffffffffff8111156147f15760008081fd5b6147ff8986838b0101614559565b8452509183019183016147d1565b60006101a0828403121561482057600080fd5b6148286143a6565b90506148338261426d565b81526148416020830161449d565b60208201526148526040830161449d565b60408201526148636060830161426d565b60608201526080820135608082015261487e60a083016146fa565b60a082015261488f60c0830161426d565b60c08201526148a060e0830161449d565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156148cd57600080fd5b6148d986838701614559565b838501526101409250828501359150808211156148f557600080fd5b61490186838701614705565b8385015261016092508285013591508082111561491d57600080fd5b5061492a8582860161478d565b82840152505061018080830135818301525092915050565b600082601f83011261495357600080fd5b813560206149636144c983614464565b82815260059290921b8401810191818101908684111561498257600080fd5b8286015b8481101561451557803567ffffffffffffffff8111156149a65760008081fd5b6149b48986838b010161478d565b845250918301918301614986565b600082601f8301126149d357600080fd5b813560206149e36144c983614464565b8083825260208201915060208460051b870101935086841115614a0557600080fd5b602086015b848110156145155780358352918301918301614a0a565b600060808284031215614a3357600080fd5b614a3b6143ca565b9050813567ffffffffffffffff80821115614a5557600080fd5b818401915084601f830112614a6957600080fd5b81356020614a796144c983614464565b82815260059290921b84018101918181019088841115614a9857600080fd5b8286015b84811015614ad057803586811115614ab45760008081fd5b614ac28b86838b010161480d565b845250918301918301614a9c565b5086525085810135935082841115614ae757600080fd5b614af387858801614942565b90850152506040840135915080821115614b0c57600080fd5b50614b19848285016149c2565b6040830152506060820135606082015292915050565b60008060408385031215614b4257600080fd5b823567ffffffffffffffff80821115614b5a57600080fd5b614b6686838701614a21565b9350602091508185013581811115614b7d57600080fd5b85019050601f81018613614b9057600080fd5b8035614b9e6144c982614464565b81815260059190911b82018301908381019088831115614bbd57600080fd5b928401925b82841015614bdb57833582529284019290840190614bc2565b80955050505050509250929050565b60e081016106f7828463ffffffff80825116835280602083015116602084015261ffff604083015116604084015260608201516001600160a01b03808216606086015280608085015116608086015250508060a08301511660a08401528060c08301511660c0840152505050565b600060208284031215614c6a57600080fd5b813567ffffffffffffffff811115614c8157600080fd5b820160a08185031215610fa257600080fd5b600082601f830112614ca457600080fd5b81356020614cb46144c983614464565b82815260069290921b84018101918181019086841115614cd357600080fd5b8286015b848110156145155760408189031215614cf05760008081fd5b614cf861437d565b8135614d0381614488565b815281850135614d1281614488565b81860152835291830191604001614cd7565b60008060408385031215614d3757600080fd5b823567ffffffffffffffff80821115614d4f57600080fd5b614d5b86838701614c93565b93506020850135915080821115614d7157600080fd5b50614d7e85828601614c93565b9150509250929050565b60008083601f840112614d9a57600080fd5b50813567ffffffffffffffff811115614db257600080fd5b6020830191508360208260051b8501011115612a1657600080fd5b60008060008060008060008060e0898b031215614de957600080fd5b606089018a811115614dfa57600080fd5b8998503567ffffffffffffffff80821115614e1457600080fd5b818b0191508b601f830112614e2857600080fd5b813581811115614e3757600080fd5b8c6020828501011115614e4957600080fd5b6020830199508098505060808b0135915080821115614e6757600080fd5b614e738c838d01614d88565b909750955060a08b0135915080821115614e8c57600080fd5b50614e998b828c01614d88565b999c989b50969995989497949560c00135949350505050565b80356fffffffffffffffffffffffffffffffff8116811461427857600080fd5b600060608284031215614ee457600080fd5b614eec6143ed565b8235614ef7816146ec565b8152614f0560208401614eb2565b6020820152614f1660408401614eb2565b60408201529392505050565b604081526000614f356040830185614677565b8281036020840152612c208185614677565b60008060408385031215614f5a57600080fd5b823567ffffffffffffffff80821115614f7257600080fd5b614f7e8683870161480d565b93506020850135915080821115614f9457600080fd5b50614d7e8582860161478d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106f7576106f7614fa1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff8084168061502d5761502d614fe3565b92169190910692915050565b80820281158282048414176106f7576106f7614fa1565b600067ffffffffffffffff8084168061506b5761506b614fe3565b92169190910492915050565b602081016003831061508b5761508b61429a565b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff8083168181036150d9576150d9614fa1565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526151138184018a614677565b905082810360808401526151278189614677565b905060ff871660a084015282810360c0840152615144818761430f565b905067ffffffffffffffff851660e0840152828103610100840152615169818561430f565b9c9b505050505050505050505050565b60006020828403121561518b57600080fd5b8151610fa281614257565b808201808211156106f7576106f7614fa1565b60008151808452602080850194506020840160005b838110156146b157815180516001600160a01b0316885283015183880152604090960195908201906001016151be565b608081528451608082015267ffffffffffffffff60208601511660a08201526000604086015160a060c084015261522961012084018261430f565b905060608701517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80808584030160e0860152615265838361430f565b92506080890151915080858403016101008601525061528482826151a9565b92505050615298602083018661ffff169052565b836040830152612c2060608301846001600160a01b03169052565b600082601f8301126152c457600080fd5b81516152d26144c982614531565b8181528460208386010111156152e757600080fd5b6127e08260208301602087016142eb565b60008060006060848603121561530d57600080fd5b8351615318816146ec565b602085015190935067ffffffffffffffff81111561533557600080fd5b615341868287016152b3565b925050604084015190509250925092565b805163ffffffff8116811461427857600080fd5b805161427881614488565b600060e0828403121561538357600080fd5b61538b614410565b61539483615352565b81526153a260208401615352565b6020820152604083015161ffff811681146153bc57600080fd5b60408201526153cd60608401615366565b60608201526153de60808401615366565b60808201526153ef60a08401615352565b60a082015261540060c08401615352565b60c08201529392505050565b6101c0810161547d82856001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015250508060608301511660608401528060808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b825163ffffffff90811660e084015260208401518116610100840152604084015161ffff1661012084015260608401516001600160a01b0390811661014085015260808501511661016084015260a0840151811661018084015260c0840151166101a0830152610fa2565b60006101208b83526001600160a01b038b16602084015267ffffffffffffffff808b1660408501528160608501526155228285018b614677565b91508382036080850152615536828a614677565b915060ff881660a085015283820360c0850152615553828861430f565b90861660e08501528381036101008501529050615169818561430f565b60006020828403121561558257600080fd5b8151610fa2816146ec565b60008151808452602080850194506020840160005b838110156146b1578151875295820195908201906001016155a2565b6060815260006155d1606083018661558d565b82810360208401526155e3818661558d565b915050826040830152949350505050565b60006020828403121561560657600080fd5b5051919050565b67ffffffffffffffff8181168382160190808211156140d5576140d5614fa1565b67ffffffffffffffff8316815260408101610fa260208301846142c9565b600067ffffffffffffffff8083168181036150d9576150d9614fa1565b61567381846142c9565b6040602082015260006127e0604083018461430f565b60006020828403121561569b57600080fd5b813567ffffffffffffffff8111156156b257600080fd5b6127e084828501614a21565b6000602082840312156156d057600080fd5b815167ffffffffffffffff808211156156e857600080fd5b90830190606082860312156156fc57600080fd5b6157046143ed565b82518281111561571357600080fd5b61571f878286016152b3565b82525060208301518281111561573457600080fd5b615740878286016152b3565b60208301525060408301518281111561575857600080fd5b615764878286016152b3565b60408301525095945050505050565b602081526000610fa260208301846151a9565b60008282518085526020808601955060208260051b8401016020860160005b848110156157d357601f198684030189526157c183835161430f565b988401989250908301906001016157a5565b5090979650505050505050565b602081526000610fa26020830184615786565b6040815261580e60408201845167ffffffffffffffff169052565b6000602084015161582a60608401826001600160a01b03169052565b5060408401516001600160a01b038116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061588b8185018367ffffffffffffffff169052565b60e086015191506101206158a9818601846001600160a01b03169052565b81870151925061014091508282860152808701519250506101a061016081818701526158d96101e087018561430f565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc061018081888703018189015261591886866151a9565b9550828a015194508188870301848901526159338686615786565b9550808a01516101c089015250505050508281036020840152612c208185615786565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561599e5780818460040360031b1b83161693505b505050919050565b6000602082840312156159b857600080fd5b8151610fa281614488565b60208152600082516101008060208501526159e261012085018361430f565b915060208501516159ff604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615a3960a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615a56848361430f565b935060c08701519150808685030160e0870152615a73848361430f565b935060e0870151915080868503018387015250615a90838261430f565b9695505050505050565b600060408284031215615aac57600080fd5b615ab461437d565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168114615ae057600080fd5b8152615aee60208401615352565b60208201529392505050565b600082615b0957615b09614fe3565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"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\"}],\"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\":\"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\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"DestinationGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"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\":\"enumOCR2BaseNoChecks.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\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"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\":[{\"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\":\"InvalidTokenGasOverride\",\"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\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"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\":[],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"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\":[{\"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\":\"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\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"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\":[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"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\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"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\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"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\":\"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[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"sourceTokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"destTokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"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\":\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"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\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structEVM2EVMOffRamp.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\":[{\"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\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.RateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOffRamp.RateLimitToken[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101a06040523480156200001257600080fd5b506040516200660a3803806200660a8339810160408190526200003591620004ec565b8033806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c081620002ca565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606080870182905298909601519091166080948501819052600380546001600160a01b031916909217600160801b9485021760ff60a01b1916600160a01b90930292909217905502909117600455469052508201516001600160a01b031615806200016f575081516001600160a01b0316155b8062000186575060c08201516001600160a01b0316155b15620001a5576040516342bcdf7f60e11b815260040160405180910390fd5b81600001516001600160a01b0316634120fccd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020e9190620005b5565b6001600160401b03166001146200023857604051636fc2a20760e11b815260040160405180910390fd5b81516001600160a01b0390811660a090815260408401516001600160401b0390811660c0908152602086015190911660e05260608501518316610100526080850151831661014052908401518216610160528301511661018052620002bd7f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b362000375565b6101205250620005da9050565b336001600160a01b03821603620003245760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008160c05160e05161010051604051602001620003bf94939291909384526001600160401b039283166020850152911660408301526001600160a01b0316606082015260800190565b604051602081830303815290604052805190602001209050919050565b60405160e081016001600160401b03811182821017156200040d57634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b03811681146200042b57600080fd5b919050565b80516001600160401b03811681146200042b57600080fd5b80516001600160801b03811681146200042b57600080fd5b6000606082840312156200047357600080fd5b604051606081016001600160401b0381118282101715620004a457634e487b7160e01b600052604160045260246000fd5b806040525080915082518015158114620004bd57600080fd5b8152620004cd6020840162000448565b6020820152620004e06040840162000448565b60408201525092915050565b6000808284036101408112156200050257600080fd5b60e08112156200051157600080fd5b506200051c620003dc565b620005278462000413565b8152620005376020850162000430565b60208201526200054a6040850162000430565b60408201526200055d6060850162000413565b6060820152620005706080850162000413565b60808201526200058360a0850162000413565b60a08201526200059660c0850162000413565b60c08201529150620005ac8460e0850162000460565b90509250929050565b600060208284031215620005c857600080fd5b620005d38262000430565b9392505050565b60805160a05160c05160e0516101005161012051610140516101605161018051615f41620006c9600039600081816102ec01528181611c6a01526133920152600081816102bd01528181611c420152611f2701526000818161028e01528181610d8d01528181610df201528181611c18015281816124a4015261250e015260006120c601526000818161025f0152611bee0152600081816101ff0152611b9201526000818161022f01528181611bc601528181611ee40152818161303b01526134bf0152600081816101d001528181611b6d01526121ac015260008181611e3e0152611e8a0152615f416000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c806385572ffb116100d8578063afcb95d71161008c578063c92b283211610066578063c92b2832146105f3578063f077b59214610606578063f2fde38b1461061c57600080fd5b8063afcb95d7146105ad578063b1dc65a4146105cd578063b6113fce146105e057600080fd5b8063873504d7116100bd578063873504d7146105765780638926c4ee146105895780638da5cb5b1461059c57600080fd5b806385572ffb1461053c578063856c82471461054a57600080fd5b8063599f64311161013a5780637437ff9f116101145780637437ff9f1461046157806379ba50971461050457806381ff70481461050c57600080fd5b8063599f643114610414578063666cab8d14610439578063704b6c021461044e57600080fd5b8063181f5a771161016b578063181f5a77146103525780631ef381741461039b578063546719cd146103b057600080fd5b806306285c6914610187578063142a98fc14610332575b600080fd5b61031c6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040518060e001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516103299190614312565b60405180910390f35b6103456103403660046143a8565b61062f565b6040516103299190614408565b61038e6040518060400160405280601481526020017f45564d3245564d4f666652616d7020312e352e3000000000000000000000000081525081565b6040516103299190614466565b6103ae6103a936600461468f565b6106aa565b005b6103b8610a9e565b604051610329919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6002546001600160a01b03165b6040516001600160a01b039091168152602001610329565b610441610b53565b60405161032991906147a1565b6103ae61045c3660046147b4565b610bb5565b6104f76040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a081018252600a5463ffffffff8082168352640100000000820416602083015268010000000000000000810461ffff16928201929092526a01000000000000000000009091046001600160a01b039081166060830152600b5416608082015290565b60405161032991906147d1565b6103ae610c7e565b6007546005546040805163ffffffff80851682526401000000009094049093166020840152820152606001610329565b6103ae610182366004614827565b61055d6105583660046147b4565b610d61565b60405167ffffffffffffffff9091168152602001610329565b6103ae6105843660046148f3565b610e64565b6103ae610597366004614e1e565b611037565b6000546001600160a01b0316610421565b604080516001815260006020820181905291810191909152606001610329565b6103ae6105db366004614f75565b61129c565b6103ae6105ee36600461505a565b6114a7565b6103ae610601366004615111565b6117e7565b61060e611852565b60405161032992919061517f565b6103ae61062a3660046147b4565b611978565b600061063d600160046151d3565b600261064a608085615215565b67ffffffffffffffff1661065e919061523c565b6010600061066d608087615253565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c1660038111156106a4576106a46143c5565b92915050565b84518460ff16601f8211156106f75760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ee919061527a565b60405180910390fd5b806000036107345760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ee919061527a565b61073c611989565b610745856119ff565b60095460005b818110156107bc57600860006009838154811061076a5761076a615294565b60009182526020808320909101546001600160a01b03168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161074b565b5050865160005b8181101561095f5760008982815181106107df576107df615294565b60200260200101519050600060028111156107fc576107fc6143c5565b6001600160a01b038216600090815260086020526040902054610100900460ff16600281111561082e5761082e6143c5565b146108685760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ee919061527a565b6001600160a01b0381166108a8576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff8316815260208101600290526001600160a01b03821660009081526008602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561094b5761094b6143c5565b0217905550905050508060010190506107c3565b5087516109739060099060208b0190614280565b506006805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908a1617179055600780546109f99146913091906000906109cb9063ffffffff166152c3565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168c8c8c8c8c8c611cc9565b6005819055600780544363ffffffff9081166401000000009081027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff841681179094556040519083048216947f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0594610a8a9487949293918316921691909117908f908f908f908f908f908f906152e6565b60405180910390a150505050505050505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff161515938301939093526004548084166060840152049091166080820152610b4e90611d56565b905090565b60606009805480602002602001604051908101604052809291908181526020018280548015610bab57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b8d575b5050505050905090565b6000546001600160a01b03163314801590610bdb57506002546001600160a01b03163314155b15610c12576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c9060200160405180910390a150565b6001546001600160a01b03163314610cf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106ee565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6001600160a01b0381166000908152600f602052604081205467ffffffffffffffff168082036106a4577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156106a4576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d919061537c565b9392505050565b610e6c611989565b60005b8251811015610f3f57610ea9838281518110610e8d57610e8d615294565b602002602001015160200151600c611e0890919063ffffffff16565b15610f37577fcbf3cbeaed4ac1d605ed30f4af06c35acaeff2379db7f6146c9cceee83d58782838281518110610ee157610ee1615294565b602002602001015160000151848381518110610eff57610eff615294565b602002602001015160200151604051610f2e9291906001600160a01b0392831681529116602082015260400190565b60405180910390a15b600101610e6f565b5060005b815181101561103257610f9c828281518110610f6157610f61615294565b602002602001015160200151838381518110610f7f57610f7f615294565b602002602001015160000151600c611e1d9092919063ffffffff16565b1561102a577ffc23abf7ddbd3c02b1420dafa2355c56c1a06fbb8723862ac14d6bd74177361a828281518110610fd457610fd4615294565b602002602001015160000151838381518110610ff257610ff2615294565b6020026020010151602001516040516110219291906001600160a01b0392831681529116602082015260400190565b60405180910390a15b600101610f43565b505050565b61103f611e3b565b8151518151811461107c576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156112915760008460000151828151811061109f5761109f615294565b6020026020010151905060008483815181106110bd576110bd615294565b60209081029190910101518051909150801561112c57826080015181101561112c5761018083015160808401516040517f9c6db58d00000000000000000000000000000000000000000000000000000000815260048101929092526024820152604481018290526064016106ee565b816020015151836101400151511461118e5761018083015160608401516040517f85d2e5bf000000000000000000000000000000000000000000000000000000008152600481019290925267ffffffffffffffff1660248201526044016106ee565b61016083015160005b846101400151518110156112815760008287815181106111b9576111b9615294565b60200260200101518060200190518101906111d491906153de565b90506000856020015183815181106111ee576111ee615294565b602002602001015163ffffffff169050806000141580156112185750816060015163ffffffff1681105b156112775761018087015160608301516040517fef0c635200000000000000000000000000000000000000000000000000000000815260048101929092526024820185905263ffffffff166044820152606481018290526084016106ee565b5050600101611197565b505050505080600101905061107f565b506110328383611ebc565b6112a6878761290f565b6005548835908082146112ef576040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101829052602481018390526044016106ee565b6112f7611e3b565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526008602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561137f5761137f6143c5565b6002811115611390576113906143c5565b90525090506002816020015160028111156113ad576113ad6143c5565b1480156113e757506009816000015160ff16815481106113cf576113cf615294565b6000918252602090912001546001600160a01b031633145b61141d576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600061142b85602061523c565b61143688602061523c565b6114428b6101446154aa565b61144c91906154aa565b61145691906154aa565b905036811461149a576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106ee565b5050505050505050505050565b3330146114e0576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516000808252602082019092528161151d565b60408051808201909152600080825260208201528152602001906001900390816114f65790505b50905060006115306101408701876154bd565b905011156115a7576115a46115496101408701876154bd565b6115596040890160208a016147b4565b604080516001600160a01b0390921660208301520160408051601f1981840301815291815261158e9060608b01908b016147b4565b61159c6101608b018b615525565b8a8a8a612966565b90505b6115b561012086018661558d565b15905080156115c657506080850135155b806115e857506115dc60608601604087016147b4565b6001600160a01b03163b155b8061163357506116317f85572ffb0000000000000000000000000000000000000000000000000000000061162260608801604089016147b4565b6001600160a01b031690612b8f565b155b1561163e57506117e1565b600a546040805160a08101909152610180870135815260009182916a01000000000000000000009091046001600160a01b031690633cf979839060208082019061168a908c018c6143a8565b67ffffffffffffffff1681526020018a60200160208101906116ac91906147b4565b604080516001600160a01b0390921660208301520160408051601f1981840301815291905281526020016116e46101208c018c61558d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200186905261138860808b013561173960608d0160408e016147b4565b6040518563ffffffff1660e01b81526004016117589493929190615637565b6000604051808303816000875af1158015611777573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261179f91908101906156fc565b5091509150816117dd57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106ee9190614466565b5050505b50505050565b6000546001600160a01b0316331480159061180d57506002546001600160a01b03163314155b15611844576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61184f600382612bab565b50565b6060806000611861600c612d90565b90508067ffffffffffffffff81111561187c5761187c614479565b6040519080825280602002602001820160405280156118a5578160200160208202803683370190505b5092508067ffffffffffffffff8111156118c1576118c1614479565b6040519080825280602002602001820160405280156118ea578160200160208202803683370190505b50915060005b8181101561197257600080611906600c84612d9b565b915091508086848151811061191d5761191d615294565b60200260200101906001600160a01b031690816001600160a01b0316815250508185848151811061195057611950615294565b6001600160a01b039092166020928302919091019091015250506001016118f0565b50509091565b611980611989565b61184f81612db9565b6000546001600160a01b031633146119fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106ee565b565b600081806020019051810190611a159190615756565b60608101519091506001600160a01b0316611a5c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600a805460208085015160408087015160608089015163ffffffff9889167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909716969096176401000000009890941697909702929092177fffff00000000000000000000000000000000000000000000ffffffffffffffff166801000000000000000061ffff909316929092027fffff0000000000000000000000000000000000000000ffffffffffffffffffff16919091176a01000000000000000000006001600160a01b039485160217909355608080860151600b80547fffffffffffffffffffffffff000000000000000000000000000000000000000016918516919091179055835160e0810185527f0000000000000000000000000000000000000000000000000000000000000000841681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff908116938201939093527f0000000000000000000000000000000000000000000000000000000000000000909216828501527f00000000000000000000000000000000000000000000000000000000000000008316948201949094527f00000000000000000000000000000000000000000000000000000000000000008216938101939093527f0000000000000000000000000000000000000000000000000000000000000000811660a08401527f00000000000000000000000000000000000000000000000000000000000000001660c0830152517f7879e20bb60a503429de4a2c912b5904f08a39f2af054c10fb46434b5d61126091611cbd9184906157f5565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a604051602001611ced999897969594939291906158b7565b60408051601f1981840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611de482606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611dc891906151d3565b85608001516fffffffffffffffffffffffffffffffff16612e94565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6000610e5d836001600160a01b038416612ebc565b6000611e33846001600160a01b03851684612ec8565b949350505050565b467f0000000000000000000000000000000000000000000000000000000000000000146119fd576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ee565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060801b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015611f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9a919061593f565b15611fd1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815151600081900361200e576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015151811461204c576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561206757612067614479565b604051908082528060200260200182016040528015612090578160200160208202803683370190505b50905060005b82811015612168576000856000015182815181106120b6576120b6615294565b602002602001015190506120ea817f0000000000000000000000000000000000000000000000000000000000000000612ede565b8383815181106120fc576120fc615294565b60200260200101818152505080610180015183838151811061212057612120615294565b60200260200101511461215f576040517f7185cf6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600101612096565b508251604080860151606087015191517f32048875000000000000000000000000000000000000000000000000000000008152921515926000926001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926332048875926121e29288929160040161598d565b602060405180830381865afa1580156121ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222391906159c3565b90508060000361225f576040517fea75680100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b848110156117dd5760008760000151828151811061228257612282615294565b60200260200101519050600061229b826060015161062f565b905060008160038111156122b1576122b16143c5565b14806122ce575060038160038111156122cc576122cc6143c5565b145b61231457816060015167ffffffffffffffff167fe3dd0bec917c965a133ddb2c84874725ee1e2fd8d763c19efa36d6a11cd82b1f60405160405180910390a25050612907565b606085156123fa5788848151811061232e5761232e615294565b6020908102919091018101510151600a5490915060009063ffffffff1661235587426151d3565b119050808061237557506003836003811115612373576123736143c5565b145b6123ab576040517f6358b0d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8985815181106123bd576123bd615294565b6020026020010151600001516000146123f4578985815181106123e2576123e2615294565b60209081029190910101515160808501525b5061245e565b600082600381111561240e5761240e6143c5565b1461245e57606083015160405167ffffffffffffffff90911681527f67d9ba0f63d427c482c2736300e6d5a34c6691dbcdea8ad35828a1f1ba47e8729060200160405180910390a1505050612907565b60c083015167ffffffffffffffff16156126df576020808401516001600160a01b03166000908152600f909152604081205467ffffffffffffffff1690819003612649577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156126495760208401516040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063856c824790602401602060405180830381865afa158015612557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257b919061537c565b60c085015190915067ffffffffffffffff166125988260016159dc565b67ffffffffffffffff16146125f95783602001516001600160a01b03168460c0015167ffffffffffffffff167fe44a20935573a783dd0d5991c92d7b6a0eb3173566530364db3ec10e9a990b5d60405160405180910390a350505050612907565b6020848101516001600160a01b03166000908152600f9091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83161790555b600083600381111561265d5761265d6143c5565b036126dd5760c084015167ffffffffffffffff1661267c8260016159dc565b67ffffffffffffffff16146126dd5783602001516001600160a01b03168460c0015167ffffffffffffffff167fd32ddb11d71e3d63411d37b09f9a8b28664f1cb1338bfd1413c173b0ebf4123760405160405180910390a350505050612907565b505b60008a6020015185815181106126f7576126f7615294565b602002602001015190506127238460600151856000015186610140015151876101200151518551613039565b612732846060015160016131ba565b600080612740868486613264565b915091506127528660600151836131ba565b88156127be57600382600381111561276c5761276c6143c5565b036127be576000856003811115612785576127856143c5565b146127be57806040517fcf19edfd0000000000000000000000000000000000000000000000000000000081526004016106ee9190614466565b60028260038111156127d2576127d26143c5565b1461282a5760038260038111156127eb576127eb6143c5565b1461282a578560600151826040517f9e2616030000000000000000000000000000000000000000000000000000000081526004016106ee9291906159fd565b60c086015167ffffffffffffffff16156128b2576000856003811115612852576128526143c5565b036128b2576020808701516001600160a01b03166000908152600f90915260408120805467ffffffffffffffff169161288a83615a1b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b856101800151866060015167ffffffffffffffff167fd4f851956a5d67c3997d1c9205045fef79bae2947fdee7e9e2641abc7391ef6584846040516128f8929190615a38565b60405180910390a35050505050505b600101612262565b61296261291e82840184615a58565b604080516000808252602082019092529061295c565b6040805180820190915260008152606060208201528152602001906001900390816129345790505b50611ebc565b5050565b60608989808060200260200160405190810160405280939291908181526020016000905b828210156129b6576129a760408302860136819003810190615a8d565b8152602001906001019061298a565b505050505090506000805b8a811015612b715760008888838181106129dd576129dd615294565b90506020028101906129ef919061558d565b8101906129fc9190615aa9565b90508451600014612a5757848281518110612a1957612a19615294565b602002602001015163ffffffff16600014612a5757848281518110612a4057612a40615294565b602090810291909101015163ffffffff1660608201525b612ad78d8d84818110612a6c57612a6c615294565b905060400201602001358c8c848b8b88818110612a8b57612a8b615294565b9050602002810190612a9d919061558d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061333192505050565b848381518110612ae957612ae9615294565b6020026020010181905250612b25848381518110612b0957612b09615294565b602002602001015160000151600c6136fd90919063ffffffff16565b15612b6857612b5b848381518110612b3f57612b3f615294565b6020908102919091010151600b546001600160a01b0316613712565b612b6590846154aa565b92505b506001016129c1565b508015612b8157612b8181613833565b509998505050505050505050565b6000612b9a83613840565b8015610e5d5750610e5d83836138a4565b8154600090612bd490700100000000000000000000000000000000900463ffffffff16426151d3565b90508015612c765760018301548354612c1c916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e94565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c9c916fffffffffffffffffffffffffffffffff9081169116613974565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612d839084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b60405180910390a1505050565b60006106a48261398a565b6000808080612daa8686613995565b909450925050505b9250929050565b336001600160a01b03821603612e2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106ee565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612eb385612ea4848661523c565b612eae90876154aa565b613974565b95945050505050565b6000610e5d83836139a4565b6000611e3384846001600160a01b0385166139c1565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001612f749897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b6040516020818303038152906040528051906020012085610120015180519060200120866101400151604051602001612fad9190615b65565b60405160208183030381529060405280519060200120876101600151604051602001612fd99190615bd2565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168467ffffffffffffffff16146130b2576040517f1279ec8a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106ee565b600a5468010000000000000000900461ffff1683111561310a576040517f099d3f7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016106ee565b80831461314f576040517f8808f8e700000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016106ee565b600a54640100000000900463ffffffff168211156131b357600a546040517f8693378900000000000000000000000000000000000000000000000000000000815264010000000090910463ffffffff166004820152602481018390526044016106ee565b5050505050565b600060026131c9608085615215565b67ffffffffffffffff166131dd919061523c565b905060006010816131ef608087615253565b67ffffffffffffffff168152602081019190915260400160002054905081613219600160046151d3565b901b191681836003811115613230576132306143c5565b901b178060106000613243608088615253565b67ffffffffffffffff16815260208101919091526040016000205550505050565b6040517fb6113fce000000000000000000000000000000000000000000000000000000008152600090606090309063b6113fce906132aa90889088908890600401615c1c565b600060405180830381600087803b1580156132c457600080fd5b505af19250505080156132d5575060015b613314573d808015613303576040519150601f19603f3d011682016040523d82523d6000602084013e613308565b606091505b50600392509050613329565b50506040805160208101909152600081526002905b935093915050565b6040805180820190915260008082526020820152600061335484602001516139de565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa1580156133d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fd9190615da5565b90506001600160a01b038116158061344557506134436001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000612b8f565b155b15613487576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106ee565b60008061349f8885896060015163ffffffff16613a84565b91509150600080600061359d6040518061010001604052808e81526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020018d6001600160a01b031681526020018f8152602001896001600160a01b031681526020018c6000015181526020018c6040015181526020018b8152506040516024016135399190615dc2565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613bc7565b925092509250826135dc57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106ee9190614466565b81516020146136245781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106ee565b60008280602001905181019061363a91906159c3565b9050866001600160a01b03168c6001600160a01b0316146136cf57600061366b8d8a613666868a6151d3565b613a84565b5090508681108061368557508161368288836151d3565b14155b156136cd576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106ee565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000610e5d836001600160a01b038416613ced565b81516040517fd02641a00000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260009182919084169063d02641a0906024016040805180830381865afa158015613778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061379c9190615e8f565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81166000036138055783516040517f9a655f7b0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024016106ee565b6020840151611e33907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690613cf9565b61184f6003826000613d36565b600061386c827f01ffc9a7000000000000000000000000000000000000000000000000000000006138a4565b80156106a4575061389d827fffffffff000000000000000000000000000000000000000000000000000000006138a4565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561395d575060208210155b80156139695750600081115b979650505050505050565b60008183106139835781610e5d565b5090919050565b60006106a482614085565b6000808080612daa8686614090565b60008181526002830160205260408120819055610e5d83836140bb565b60008281526002840160205260408120829055611e3384846140c7565b60008151602014613a1d57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106ee9190614466565b600082806020019051810190613a3391906159c3565b90506001600160a01b03811180613a4b575061040081105b156106a457826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106ee9190614466565b6000806000806000613b1388604051602401613aaf91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613bc7565b92509250925082613b5257816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106ee9190614466565b6020825114613b9a5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106ee565b81806020019051810190613bae91906159c3565b613bb882886151d3565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613bea57613bea614479565b6040519080825280601f01601f191660200182016040528015613c14576020820181803683370190505b509150863b613c47577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613c7a577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613cb3577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613cd65750835b808352806000602085013e50955095509592505050565b6000610e5d83836140d3565b6000670de0b6b3a7640000613d2c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff861661523c565b610e5d9190615ef1565b825474010000000000000000000000000000000000000000900460ff161580613d5d575081155b15613d6757505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090613dad90700100000000000000000000000000000000900463ffffffff16426151d3565b90508015613e6d5781831115613def576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154613e299083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e94565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015613f0a576001600160a01b038416613ebf576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016106ee565b6040517f1a76572a00000000000000000000000000000000000000000000000000000000815260048101839052602481018690526001600160a01b03851660448201526064016106ee565b848310156140035760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290613f4e90826151d3565b613f58878a6151d3565b613f6291906154aa565b613f6c9190615ef1565b90506001600160a01b038616613fb8576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016106ee565b6040517fd0c8d23a00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526001600160a01b03871660448201526064016106ee565b61400d85846151d3565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60006106a4826140df565b6000808061409e85856140e9565b600081815260029690960160205260409095205494959350505050565b6000610e5d83836140f5565b6000610e5d83836141ef565b6000610e5d838361423e565b60006106a4825490565b6000610e5d8383614256565b600081815260018301602052604081205480156141de5760006141196001836151d3565b855490915060009061412d906001906151d3565b905081811461419257600086600001828154811061414d5761414d615294565b906000526020600020015490508087600001848154811061417057614170615294565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141a3576141a3615f05565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106a4565b60009150506106a4565b5092915050565b6000818152600183016020526040812054614236575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106a4565b5060006106a4565b60008181526001830160205260408120541515610e5d565b600082600001828154811061426d5761426d615294565b9060005260206000200154905092915050565b8280548282559060005260206000209081019282156142ed579160200282015b828111156142ed57825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039091161782556020909201916001909101906142a0565b506142f99291506142fd565b5090565b5b808211156142f957600081556001016142fe565b60e081016106a482846001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015250508060608301511660608401528060808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b67ffffffffffffffff8116811461184f57600080fd5b80356143a381614382565b919050565b6000602082840312156143ba57600080fd5b8135610e5d81614382565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110614404576144046143c5565b9052565b602081016106a482846143f4565b60005b83811015614431578181015183820152602001614419565b50506000910152565b60008151808452614452816020860160208601614416565b601f01601f19169290920160200192915050565b602081526000610e5d602083018461443a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156144cb576144cb614479565b60405290565b6040516080810167ffffffffffffffff811182821017156144cb576144cb614479565b6040516101a0810167ffffffffffffffff811182821017156144cb576144cb614479565b604051601f8201601f1916810167ffffffffffffffff8111828210171561454157614541614479565b604052919050565b600067ffffffffffffffff82111561456357614563614479565b5060051b60200190565b6001600160a01b038116811461184f57600080fd5b80356143a38161456d565b600082601f83011261459e57600080fd5b813560206145b36145ae83614549565b614518565b8083825260208201915060208460051b8701019350868411156145d557600080fd5b602086015b848110156145fa5780356145ed8161456d565b83529183019183016145da565b509695505050505050565b803560ff811681146143a357600080fd5b600067ffffffffffffffff82111561463057614630614479565b50601f01601f191660200190565b600082601f83011261464f57600080fd5b813561465d6145ae82614616565b81815284602083860101111561467257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c087890312156146a857600080fd5b863567ffffffffffffffff808211156146c057600080fd5b6146cc8a838b0161458d565b975060208901359150808211156146e257600080fd5b6146ee8a838b0161458d565b96506146fc60408a01614605565b9550606089013591508082111561471257600080fd5b61471e8a838b0161463e565b945061472c60808a01614398565b935060a089013591508082111561474257600080fd5b5061474f89828a0161463e565b9150509295509295509295565b60008151808452602080850194506020840160005b838110156147965781516001600160a01b031687529582019590820190600101614771565b509495945050505050565b602081526000610e5d602083018461475c565b6000602082840312156147c657600080fd5b8135610e5d8161456d565b60a081016106a4828463ffffffff8082511683528060208301511660208401525061ffff604082015116604083015260608101516001600160a01b03808216606085015280608084015116608085015250505050565b60006020828403121561483957600080fd5b813567ffffffffffffffff81111561485057600080fd5b820160a08185031215610e5d57600080fd5b600082601f83011261487357600080fd5b813560206148836145ae83614549565b82815260069290921b840181019181810190868411156148a257600080fd5b8286015b848110156145fa57604081890312156148bf5760008081fd5b6148c76144a8565b81356148d28161456d565b8152818501356148e18161456d565b818601528352918301916040016148a6565b6000806040838503121561490657600080fd5b823567ffffffffffffffff8082111561491e57600080fd5b61492a86838701614862565b9350602085013591508082111561494057600080fd5b5061494d85828601614862565b9150509250929050565b801515811461184f57600080fd5b80356143a381614957565b60006040828403121561498257600080fd5b61498a6144a8565b905081356149978161456d565b808252506020820135602082015292915050565b600082601f8301126149bc57600080fd5b813560206149cc6145ae83614549565b8083825260208201915060208460061b8701019350868411156149ee57600080fd5b602086015b848110156145fa57614a058882614970565b8352918301916040016149f3565b600082601f830112614a2457600080fd5b81356020614a346145ae83614549565b82815260059290921b84018101918181019086841115614a5357600080fd5b8286015b848110156145fa57803567ffffffffffffffff811115614a775760008081fd5b614a858986838b010161463e565b845250918301918301614a57565b600082601f830112614aa457600080fd5b81356020614ab46145ae83614549565b82815260059290921b84018101918181019086841115614ad357600080fd5b8286015b848110156145fa57803567ffffffffffffffff811115614af75760008081fd5b614b058986838b0101614a13565b845250918301918301614ad7565b600082601f830112614b2457600080fd5b81356020614b346145ae83614549565b8083825260208201915060208460051b870101935086841115614b5657600080fd5b602086015b848110156145fa5780358352918301918301614b5b565b600060808284031215614b8457600080fd5b614b8c6144d1565b9050813567ffffffffffffffff80821115614ba657600080fd5b818401915084601f830112614bba57600080fd5b81356020614bca6145ae83614549565b82815260059290921b84018101918181019088841115614be957600080fd5b8286015b84811015614d4557803586811115614c0457600080fd5b87016101a0818c03601f19011215614c1b57600080fd5b614c236144f4565b614c2e868301614398565b8152614c3c60408301614582565b86820152614c4c60608301614582565b6040820152614c5d60808301614398565b606082015260a08201356080820152614c7860c08301614965565b60a0820152614c8960e08301614398565b60c0820152610100614c9c818401614582565b60e083015261012080840135828401526101409150818401358a811115614cc257600080fd5b614cd08f8a8388010161463e565b828501525050610160808401358a811115614cea57600080fd5b614cf88f8a838801016149ab565b83850152506101809150818401358a811115614d1357600080fd5b614d218f8a83880101614a13565b91840191909152506101a09290920135918101919091528352918301918301614bed565b5086525085810135935082841115614d5c57600080fd5b614d6887858801614a93565b90850152506040840135915080821115614d8157600080fd5b50614d8e84828501614b13565b6040830152506060820135606082015292915050565b63ffffffff8116811461184f57600080fd5b600082601f830112614dc757600080fd5b81356020614dd76145ae83614549565b8083825260208201915060208460051b870101935086841115614df957600080fd5b602086015b848110156145fa578035614e1181614da4565b8352918301918301614dfe565b6000806040808486031215614e3257600080fd5b833567ffffffffffffffff80821115614e4a57600080fd5b614e5687838801614b72565b9450602091508186013581811115614e6d57600080fd5b8601601f81018813614e7e57600080fd5b8035614e8c6145ae82614549565b81815260059190911b8201840190848101908a831115614eab57600080fd5b8584015b83811015614f1e57803586811115614ec75760008081fd5b8501808d03601f1901891315614edd5760008081fd5b614ee56144a8565b8882013581528982013588811115614efd5760008081fd5b614f0b8f8b83860101614db6565b828b015250845250918601918601614eaf565b50809750505050505050509250929050565b60008083601f840112614f4257600080fd5b50813567ffffffffffffffff811115614f5a57600080fd5b6020830191508360208260051b8501011115612db257600080fd5b60008060008060008060008060e0898b031215614f9157600080fd5b606089018a811115614fa257600080fd5b8998503567ffffffffffffffff80821115614fbc57600080fd5b818b0191508b601f830112614fd057600080fd5b813581811115614fdf57600080fd5b8c6020828501011115614ff157600080fd5b6020830199508098505060808b013591508082111561500f57600080fd5b61501b8c838d01614f30565b909750955060a08b013591508082111561503457600080fd5b506150418b828c01614f30565b999c989b50969995989497949560c00135949350505050565b6000806000806060858703121561507057600080fd5b843567ffffffffffffffff8082111561508857600080fd5b908601906101a0828903121561509d57600080fd5b909450602086013590808211156150b357600080fd5b6150bf88838901614f30565b909550935060408701359150808211156150d857600080fd5b506150e587828801614db6565b91505092959194509250565b80356fffffffffffffffffffffffffffffffff811681146143a357600080fd5b60006060828403121561512357600080fd5b6040516060810181811067ffffffffffffffff8211171561514657615146614479565b604052823561515481614957565b8152615162602084016150f1565b6020820152615173604084016150f1565b60408201529392505050565b604081526000615192604083018561475c565b8281036020840152612eb3818561475c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106a4576106a46151a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680615230576152306151e6565b92169190910692915050565b80820281158282048414176106a4576106a46151a4565b600067ffffffffffffffff8084168061526e5761526e6151e6565b92169190910492915050565b602081016003831061528e5761528e6143c5565b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff8083168181036152dc576152dc6151a4565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153168184018a61475c565b9050828103608084015261532a818961475c565b905060ff871660a084015282810360c0840152615347818761443a565b905067ffffffffffffffff851660e084015282810361010084015261536c818561443a565b9c9b505050505050505050505050565b60006020828403121561538e57600080fd5b8151610e5d81614382565b600082601f8301126153aa57600080fd5b81516153b86145ae82614616565b8181528460208386010111156153cd57600080fd5b611e33826020830160208701614416565b6000602082840312156153f057600080fd5b815167ffffffffffffffff8082111561540857600080fd5b908301906080828603121561541c57600080fd5b6154246144d1565b82518281111561543357600080fd5b61543f87828601615399565b82525060208301518281111561545457600080fd5b61546087828601615399565b60208301525060408301518281111561547857600080fd5b61548487828601615399565b6040830152506060830151925061549a83614da4565b6060810192909252509392505050565b808201808211156106a4576106a46151a4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126154f257600080fd5b83018035915067ffffffffffffffff82111561550d57600080fd5b6020019150600681901b3603821315612db257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261555a57600080fd5b83018035915067ffffffffffffffff82111561557557600080fd5b6020019150600581901b3603821315612db257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126155c257600080fd5b83018035915067ffffffffffffffff8211156155dd57600080fd5b602001915036819003821315612db257600080fd5b60008151808452602080850194506020840160005b8381101561479657815180516001600160a01b031688528301518388015260409096019590820190600101615607565b608081528451608082015267ffffffffffffffff60208601511660a08201526000604086015160a060c084015261567261012084018261443a565b905060608701517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80808584030160e08601526156ae838361443a565b9250608089015191508085840301610100860152506156cd82826155f2565b925050506156e1602083018661ffff169052565b836040830152612eb360608301846001600160a01b03169052565b60008060006060848603121561571157600080fd5b835161571c81614957565b602085015190935067ffffffffffffffff81111561573957600080fd5b61574586828701615399565b925050604084015190509250925092565b600060a0828403121561576857600080fd5b60405160a0810181811067ffffffffffffffff8211171561578b5761578b614479565b604052825161579981614da4565b815260208301516157a981614da4565b6020820152604083015161ffff811681146157c357600080fd5b604082015260608301516157d68161456d565b606082015260808301516157e98161456d565b60808201529392505050565b610180810161586682856001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015250508060608301511660608401528060808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b825163ffffffff90811660e0840152602084015116610100830152604083015161ffff1661012083015260608301516001600160a01b03908116610140840152608084015116610160830152610e5d565b60006101208b83526001600160a01b038b16602084015267ffffffffffffffff808b1660408501528160608501526158f18285018b61475c565b91508382036080850152615905828a61475c565b915060ff881660a085015283820360c0850152615922828861443a565b90861660e0850152838103610100850152905061536c818561443a565b60006020828403121561595157600080fd5b8151610e5d81614957565b60008151808452602080850194506020840160005b8381101561479657815187529582019590820190600101615971565b6060815260006159a0606083018661595c565b82810360208401526159b2818661595c565b915050826040830152949350505050565b6000602082840312156159d557600080fd5b5051919050565b67ffffffffffffffff8181168382160190808211156141e8576141e86151a4565b67ffffffffffffffff8316815260408101610e5d60208301846143f4565b600067ffffffffffffffff8083168181036152dc576152dc6151a4565b615a4281846143f4565b604060208201526000611e33604083018461443a565b600060208284031215615a6a57600080fd5b813567ffffffffffffffff811115615a8157600080fd5b611e3384828501614b72565b600060408284031215615a9f57600080fd5b610e5d8383614970565b600060208284031215615abb57600080fd5b813567ffffffffffffffff80821115615ad357600080fd5b9083019060808286031215615ae757600080fd5b615aef6144d1565b823582811115615afe57600080fd5b615b0a8782860161463e565b825250602083013582811115615b1f57600080fd5b615b2b8782860161463e565b602083015250604083013582811115615b4357600080fd5b615b4f8782860161463e565b6040830152506060830135925061549a83614da4565b602081526000610e5d60208301846155f2565b60008282518085526020808601955060208260051b8401016020860160005b84811015615bc557601f19868403018952615bb383835161443a565b98840198925090830190600101615b97565b5090979650505050505050565b602081526000610e5d6020830184615b78565b60008151808452602080850194506020840160005b8381101561479657815163ffffffff1687529582019590820190600101615bfa565b60608152615c3760608201855167ffffffffffffffff169052565b60006020850151615c5360808401826001600160a01b03169052565b5060408501516001600160a01b03811660a084015250606085015167ffffffffffffffff811660c084015250608085015160e083015260a0850151610100615c9e8185018315159052565b60c08701519150610120615cbd8186018467ffffffffffffffff169052565b60e08801519250610140615cdb818701856001600160a01b03169052565b828901519350610160925083838701528189015193506101a091506101808281880152615d0c61020088018661443a565b9450818a015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0808887030184890152615d4886846155f2565b948b01518886039091016101c0890152939450615d658585615b78565b9450808a01516101e0880152505050508281036020840152615d878186615b78565b90508281036040840152615d9b8185615be5565b9695505050505050565b600060208284031215615db757600080fd5b8151610e5d8161456d565b6020815260008251610100806020850152615de161012085018361443a565b91506020850151615dfe604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615e3860a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615e55848361443a565b935060c08701519150808685030160e0870152615e72848361443a565b935060e0870151915080868503018387015250615d9b838261443a565b600060408284031215615ea157600080fd5b615ea96144a8565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168114615ed557600080fd5b81526020830151615ee581614da4565b60208201529392505050565b600082615f0057615f006151e6565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var EVM2EVMOffRampABI = EVM2EVMOffRampMetaData.ABI @@ -568,27 +571,27 @@ func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) AcceptOwnership() (*type return _EVM2EVMOffRamp.Contract.AcceptOwnership(&_EVM2EVMOffRamp.TransactOpts) } -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData) +func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _EVM2EVMOffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData, tokenGasOverrides) } -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMOffRamp.TransactOpts, message, offchainTokenData) +func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _EVM2EVMOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMOffRamp.TransactOpts, message, offchainTokenData, tokenGasOverrides) } -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMOffRamp.TransactOpts, message, offchainTokenData) +func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _EVM2EVMOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMOffRamp.TransactOpts, message, offchainTokenData, tokenGasOverrides) } -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { +func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, report InternalExecutionReport, gasLimitOverrides []EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error) { return _EVM2EVMOffRamp.contract.Transact(opts, "manuallyExecute", report, gasLimitOverrides) } -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ManuallyExecute(report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { +func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ManuallyExecute(report InternalExecutionReport, gasLimitOverrides []EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error) { return _EVM2EVMOffRamp.Contract.ManuallyExecute(&_EVM2EVMOffRamp.TransactOpts, report, gasLimitOverrides) } -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ManuallyExecute(report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { +func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ManuallyExecute(report InternalExecutionReport, gasLimitOverrides []EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error) { return _EVM2EVMOffRamp.Contract.ManuallyExecute(&_EVM2EVMOffRamp.TransactOpts, report, gasLimitOverrides) } @@ -781,6 +784,123 @@ func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseAdminSet(log types.Log) (*EV return event, nil } +type EVM2EVMOffRampAlreadyAttemptedIterator struct { + Event *EVM2EVMOffRampAlreadyAttempted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EVM2EVMOffRampAlreadyAttemptedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EVM2EVMOffRampAlreadyAttempted) + 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(EVM2EVMOffRampAlreadyAttempted) + 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 *EVM2EVMOffRampAlreadyAttemptedIterator) Error() error { + return it.fail +} + +func (it *EVM2EVMOffRampAlreadyAttemptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EVM2EVMOffRampAlreadyAttempted struct { + SequenceNumber uint64 + Raw types.Log +} + +func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterAlreadyAttempted(opts *bind.FilterOpts) (*EVM2EVMOffRampAlreadyAttemptedIterator, error) { + + logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "AlreadyAttempted") + if err != nil { + return nil, err + } + return &EVM2EVMOffRampAlreadyAttemptedIterator{contract: _EVM2EVMOffRamp.contract, event: "AlreadyAttempted", logs: logs, sub: sub}, nil +} + +func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchAlreadyAttempted(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampAlreadyAttempted) (event.Subscription, error) { + + logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "AlreadyAttempted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EVM2EVMOffRampAlreadyAttempted) + if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "AlreadyAttempted", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseAlreadyAttempted(log types.Log) (*EVM2EVMOffRampAlreadyAttempted, error) { + event := new(EVM2EVMOffRampAlreadyAttempted) + if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "AlreadyAttempted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type EVM2EVMOffRampConfigChangedIterator struct { Event *EVM2EVMOffRampConfigChanged @@ -2440,6 +2560,8 @@ func (_EVM2EVMOffRamp *EVM2EVMOffRamp) ParseLog(log types.Log) (generated.Abigen switch log.Topics[0] { case _EVM2EVMOffRamp.abi.Events["AdminSet"].ID: return _EVM2EVMOffRamp.ParseAdminSet(log) + case _EVM2EVMOffRamp.abi.Events["AlreadyAttempted"].ID: + return _EVM2EVMOffRamp.ParseAlreadyAttempted(log) case _EVM2EVMOffRamp.abi.Events["ConfigChanged"].ID: return _EVM2EVMOffRamp.ParseConfigChanged(log) case _EVM2EVMOffRamp.abi.Events["ConfigSet"].ID: @@ -2476,12 +2598,16 @@ func (EVM2EVMOffRampAdminSet) Topic() common.Hash { return common.HexToHash("0x8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c") } +func (EVM2EVMOffRampAlreadyAttempted) Topic() common.Hash { + return common.HexToHash("0x67d9ba0f63d427c482c2736300e6d5a34c6691dbcdea8ad35828a1f1ba47e872") +} + func (EVM2EVMOffRampConfigChanged) Topic() common.Hash { return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") } func (EVM2EVMOffRampConfigSet) Topic() common.Hash { - return common.HexToHash("0xf02fcc22535d64d92d17b995475893d63edd51da163fed74a6ee9b4bc4895cc4") + return common.HexToHash("0x7879e20bb60a503429de4a2c912b5904f08a39f2af054c10fb46434b5d611260") } func (EVM2EVMOffRampConfigSet0) Topic() common.Hash { @@ -2567,9 +2693,9 @@ type EVM2EVMOffRampInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) + ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) - ManuallyExecute(opts *bind.TransactOpts, report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) + ManuallyExecute(opts *bind.TransactOpts, report InternalExecutionReport, gasLimitOverrides []EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error) SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) @@ -2589,6 +2715,12 @@ type EVM2EVMOffRampInterface interface { ParseAdminSet(log types.Log) (*EVM2EVMOffRampAdminSet, error) + FilterAlreadyAttempted(opts *bind.FilterOpts) (*EVM2EVMOffRampAlreadyAttemptedIterator, error) + + WatchAlreadyAttempted(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampAlreadyAttempted) (event.Subscription, error) + + ParseAlreadyAttempted(log types.Log) (*EVM2EVMOffRampAlreadyAttempted, error) + FilterConfigChanged(opts *bind.FilterOpts) (*EVM2EVMOffRampConfigChangedIterator, error) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampConfigChanged) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0/evm_2_evm_offramp_1_0_0.go b/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0/evm_2_evm_offramp_1_0_0.go deleted file mode 100644 index 3f140f8a3a5..00000000000 --- a/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0/evm_2_evm_offramp_1_0_0.go +++ /dev/null @@ -1,2354 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package evm_2_evm_offramp_1_0_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 ClientAny2EVMMessage struct { - MessageId [32]byte - SourceChainSelector uint64 - Sender []byte - Data []byte - DestTokenAmounts []ClientEVMTokenAmount -} - -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - -type EVM2EVMOffRampDynamicConfig struct { - PermissionLessExecutionThresholdSeconds uint32 - Router common.Address - PriceRegistry common.Address - MaxTokensLength uint16 - MaxDataSize uint32 -} - -type EVM2EVMOffRampStaticConfig struct { - CommitStore common.Address - ChainSelector uint64 - SourceChainSelector uint64 - OnRamp common.Address - PrevOffRamp common.Address - ArmProxy common.Address -} - -type InternalEVM2EVMMessage struct { - SourceChainSelector uint64 - SequenceNumber uint64 - FeeTokenAmount *big.Int - Sender common.Address - Nonce uint64 - GasLimit *big.Int - Strict bool - Receiver common.Address - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - MessageId [32]byte -} - -type InternalExecutionReport struct { - Messages []InternalEVM2EVMMessage - OffchainTokenData [][][]byte - Proofs [][32]byte - ProofFlagBits *big.Int -} - -type InternalPoolUpdate struct { - Token common.Address - Pool common.Address -} - -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 -} - -var EVM2EVMOffRampMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenRateLimitError\",\"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\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"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\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"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\":\"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\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"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\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"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\":\"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\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200698638038062006986833981016040819052620000359162000891565b8033806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c08162000478565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606086018190529790950151166080938401819052600380546001600160a01b031916909517600160801b9384021760ff60a01b1916600160a01b90920291909117909355909102909217600455504690528151835114620001705760405162d8548360e71b815260040160405180910390fd5b60608401516001600160a01b0316158062000193575083516001600160a01b0316155b15620001b2576040516342bcdf7f60e11b815260040160405180910390fd5b83600001516001600160a01b0316634120fccd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200021b9190620009a8565b6001600160401b03166001146200024557604051636fc2a20760e11b815260040160405180910390fd5b83516001600160a01b0390811660a090815260408601516001600160401b0390811660c05260208701511660e052606086015182166101005260808601518216610140528501511661016052620002bc7fbdd59ac4dd1d82276c9a9c5d2656546346b9dcdb1f9b4204aed4ec15c23d7d3a62000523565b6101205260005b83518110156200046d576200031d848281518110620002e657620002e6620009c6565b6020026020010151848381518110620003035762000303620009c6565b6020026020010151600c6200058a60201b9092919060201c565b50620003d2838281518110620003375762000337620009c6565b60200260200101516001600160a01b03166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200037d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a39190620009dc565b848381518110620003b857620003b8620009c6565b6020026020010151600f6200058a60201b9092919060201c565b507f95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c848281518110620004095762000409620009c6565b6020026020010151848381518110620004265762000426620009c6565b6020026020010151604051620004529291906001600160a01b0392831681529116602082015260400190565b60405180910390a1620004658162000a03565b9050620002c3565b505050505062000a2b565b336001600160a01b03821603620004d25760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008160c05160e051610100516040516020016200056d94939291909384526001600160401b039283166020850152911660408301526001600160a01b0316606082015260800190565b604051602081830303815290604052805190602001209050919050565b6000620005a2846001600160a01b03851684620005aa565b949350505050565b6000620005a284846001600160a01b03851660008281526002840160205260408120829055620005a284846000620005e38383620005ec565b90505b92915050565b60008181526001830160205260408120546200063557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005e6565b506000620005e6565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156200067957620006796200063e565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006aa57620006aa6200063e565b604052919050565b6001600160a01b0381168114620006c857600080fd5b50565b80516001600160401b0381168114620006e357600080fd5b919050565b60006001600160401b038211156200070457620007046200063e565b5060051b60200190565b600082601f8301126200072057600080fd5b81516020620007396200073383620006e8565b6200067f565b82815260059290921b840181019181810190868411156200075957600080fd5b8286015b84811015620007815780516200077381620006b2565b83529183019183016200075d565b509695505050505050565b600082601f8301126200079e57600080fd5b81516020620007b16200073383620006e8565b82815260059290921b84018101918181019086841115620007d157600080fd5b8286015b8481101562000781578051620007eb81620006b2565b8352918301918301620007d5565b80516001600160801b0381168114620006e357600080fd5b6000606082840312156200082457600080fd5b604051606081016001600160401b03811182821017156200084957620008496200063e565b8060405250809150825180151581146200086257600080fd5b81526200087260208401620007f9565b60208201526200088560408401620007f9565b60408201525092915050565b600080600080848603610160811215620008aa57600080fd5b60c0811215620008b957600080fd5b50620008c462000654565b8551620008d181620006b2565b8152620008e160208701620006cb565b6020820152620008f460408701620006cb565b604082015260608601516200090981620006b2565b606082015260808601516200091e81620006b2565b608082015260a08601516200093381620006b2565b60a082015260c08601519094506001600160401b03808211156200095657600080fd5b62000964888389016200070e565b945060e08701519150808211156200097b57600080fd5b506200098a878288016200078c565b9250506200099d86610100870162000811565b905092959194509250565b600060208284031215620009bb57600080fd5b620005e382620006cb565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009ef57600080fd5b8151620009fc81620006b2565b9392505050565b60006001820162000a2457634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e05161010051610120516101405161016051615e7e62000b0860003960008181610309015281816120ef0152612b0b0152600081816102cd015281816114a001528181611522015281816120c501528181613080015261310701526000612cc4015260008181610291015261209e015260008181610231015261204c01526000818161026101528181612076015281816124650152613a7c0152600081816101f50152818161201e0152612db901526000818161182f0152818161187b01528181611c8f0152611cdb0152615e7e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806381ff7048116100ee578063b1dc65a411610097578063d3c7c2c711610071578063d3c7c2c7146106a7578063d7e2bb50146106af578063e65bf00a146106c2578063f2fde38b146106d557600080fd5b8063b1dc65a41461066e578063b4069b3114610681578063c92b28321461069457600080fd5b80638da5cb5b116100c85780638da5cb5b1461061d578063afa0d3791461063b578063afcb95d71461064e57600080fd5b806381ff7048146105b357806385572ffb146105e3578063856c8247146105f157600080fd5b8063599f64311161015b578063681fba1611610135578063681fba16146104b8578063704b6c02146104cd5780637437ff9f146104e057806379ba5097146105ab57600080fd5b8063599f6431146104515780635d86f14114610490578063666cab8d146104a357600080fd5b80631ef381741161018c5780631ef38174146103c55780633a87ac53146103da578063546719cd146103ed57600080fd5b806306285c69146101b3578063142a98fc1461035c578063181f5a771461037c575b600080fd5b6103466040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161035391906145e8565b60405180910390f35b61036f61036a36600461467f565b6106e8565b6040516103539190614706565b6103b86040518060400160405280601481526020017f45564d3245564d4f666652616d7020312e302e3000000000000000000000000081525081565b6040516103539190614782565b6103d86103d33660046149f0565b610763565b005b6103d86103e8366004614b02565b610c22565b6103f5611032565b604051610353919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610353565b61046b61049e366004614b6e565b6110e7565b6104ab611150565b6040516103539190614bdc565b6104c06111bf565b6040516103539190614bef565b6103d86104db366004614b6e565b611278565b61059e6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a081018252600a5463ffffffff808216835273ffffffffffffffffffffffffffffffffffffffff64010000000090920482166020840152600b549182169383019390935261ffff7401000000000000000000000000000000000000000082041660608301527601000000000000000000000000000000000000000000009004909116608082015290565b6040516103539190614c49565b6103d8611368565b6007546005546040805163ffffffff80851682526401000000009094049093166020840152820152606001610353565b6103d86101ae366004614cac565b6106046105ff366004614b6e565b611465565b60405167ffffffffffffffff9091168152602001610353565b60005473ffffffffffffffffffffffffffffffffffffffff1661046b565b6103d8610649366004614f16565b61158d565b604080516001815260006020820181905291810191909152606001610353565b6103d861067c366004614fbf565b6117d9565b61046b61068f366004614b6e565b611a6a565b6103d86106a23660046150c4565b611b43565b6104c0611bc8565b61046b6106bd366004614b6e565b611c7d565b6103d86106d036600461531b565b611c8c565b6103d86106e3366004614b6e565b611e0e565b60006106f660016004615405565b6002610703608085615447565b67ffffffffffffffff16610717919061546e565b60136000610726608087615485565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c16600381111561075d5761075d61469c565b92915050565b84518460ff16601f8211156107d9576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b80600003610843576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f736974697665000000000000000000000000000060448201526064016107d0565b61084b611e1f565b61085485611ea2565b60095460005b818110156108e0576008600060098381548110610879576108796154ac565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556108d9816154db565b905061085a565b50875160005b81811015610adc5760008a8281518110610902576109026154ac565b602002602001015190506000600281111561091f5761091f61469c565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260086020526040902054610100900460ff16600281111561095e5761095e61469c565b146109c5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d697474657220616464726573730000000060448201526064016107d0565b73ffffffffffffffffffffffffffffffffffffffff8116610a12576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526008602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610ac257610ac261469c565b02179055509050505080610ad5906154db565b90506108e6565b508851610af09060099060208c0190614552565b506006805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b161717905560078054610b76914691309190600090610b489063ffffffff16615513565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d61214f565b6005600001819055506000600760049054906101000a900463ffffffff16905043600760046101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600560000154600760009054906101000a900463ffffffff168e8e8e8e8e8e604051610c0d99989796959493929190615536565b60405180910390a15050505050505050505050565b610c2a611e1f565b60005b83811015610e29576000858583818110610c4957610c496154ac565b610c5f9260206040909202019081019150614b6e565b90506000868684818110610c7557610c756154ac565b9050604002016020016020810190610c8d9190614b6e565b9050610c9a600c836121fa565b610cd0576040517f9c8787c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610cf2600c8461221c565b73ffffffffffffffffffffffffffffffffffffffff1614610d3f576040517f6cc7b99800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d4a600c8361223e565b50610dc58173ffffffffffffffffffffffffffffffffffffffff166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbd91906155cc565b600f9061223e565b506040805173ffffffffffffffffffffffffffffffffffffffff8085168252831660208201527f987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c910160405180910390a1505080610e22906154db565b9050610c2d565b5060005b8181101561102b576000838383818110610e4957610e496154ac565b610e5f9260206040909202019081019150614b6e565b90506000848484818110610e7557610e756154ac565b9050604002016020016020810190610e8d9190614b6e565b905073ffffffffffffffffffffffffffffffffffffffff82161580610ec6575073ffffffffffffffffffffffffffffffffffffffff8116155b15610efd576040517f6c2a418000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f08600c836121fa565b15610f3f576040517f3caf458500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f4b600c8383612260565b50610fc78173ffffffffffffffffffffffffffffffffffffffff166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbe91906155cc565b600f9083612260565b506040805173ffffffffffffffffffffffffffffffffffffffff8085168252831660208201527f95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c910160405180910390a1505080611024906154db565b9050610e2d565b5050505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff1615159383019390935260045480841660608401520490911660808201526110e290612283565b905090565b600080806110f6600c85612335565b9150915081611149576040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016107d0565b9392505050565b606060098054806020026020016040519081016040528092919081815260200182805480156111b557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161118a575b5050505050905090565b60606111cb600f612364565b67ffffffffffffffff8111156111e3576111e3614795565b60405190808252806020026020018201604052801561120c578160200160208202803683370190505b50905060005b8151811015611274576000611228600f8361236f565b5090508083838151811061123e5761123e6154ac565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101525061126d816154db565b9050611212565b5090565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906112b8575060025473ffffffffffffffffffffffffffffffffffffffff163314155b156112ef576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c9060200160405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146113e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107d0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b73ffffffffffffffffffffffffffffffffffffffff811660009081526012602052604081205467ffffffffffffffff16801580156114d857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1615155b1561075d576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114991906155e9565b3330146115c6576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281611603565b60408051808201909152600080825260208201528152602001906001900390816115dc5790505b5061012084015151909150156116625761012083015160608401516040805173ffffffffffffffffffffffffffffffffffffffff909216602083015261165f9291016040516020818303038152906040528560e001518561238b565b90505b60e083015173ffffffffffffffffffffffffffffffffffffffff163b15806116cc575060e08301516116ca9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb00000000000000000000000000000000000000000000000000000000612831565b155b156116d657505050565b600a546000908190640100000000900473ffffffffffffffffffffffffffffffffffffffff16633cf9798361170b878661284d565b6113888860a001518960e001516040518563ffffffff1660e01b81526004016117379493929190615657565b6000604051808303816000875af1158015611756573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261179c9190810190615729565b915091508161102b57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107d09190614782565b6117e387876128fd565b60055488359080821461182c576040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101829052602481018390526044016107d0565b467f0000000000000000000000000000000000000000000000000000000000000000146118ad576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107d0565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526008602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156119355761193561469c565b60028111156119465761194661469c565b90525090506002816020015160028111156119635761196361469c565b1480156119aa57506009816000015160ff1681548110611985576119856154ac565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6119e0576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006119ee85602061546e565b6119f988602061546e565b611a058b6101446157b6565b611a0f91906157b6565b611a1991906157b6565b9050368114611a5d576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016107d0565b5050505050505050505050565b60008080611a79600c85612335565b9150915081611acc576040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016107d0565b8073ffffffffffffffffffffffffffffffffffffffff166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3b91906155cc565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590611b83575060025473ffffffffffffffffffffffffffffffffffffffff163314155b15611bba576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bc5600382612924565b50565b6060611bd4600c612364565b67ffffffffffffffff811115611bec57611bec614795565b604051908082528060200260200182016040528015611c15578160200160208202803683370190505b50905060005b8151811015611274576000611c31600c8361236f565b50905080838381518110611c4757611c476154ac565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015250611c76816154db565b9050611c1b565b600080806110f6600f85612335565b467f000000000000000000000000000000000000000000000000000000000000000014611d17576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff461660248201526044016107d0565b81515181518114611d54576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015611dfe576000838281518110611d7357611d736154ac565b6020026020010151905080600014158015611dac57508451805183908110611d9d57611d9d6154ac565b602002602001015160a0015181105b15611ded576040517f085e39cf00000000000000000000000000000000000000000000000000000000815260048101839052602481018290526044016107d0565b50611df7816154db565b9050611d57565b50611e098383612b09565b505050565b611e16611e1f565b611bc5816134b6565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ea0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d0565b565b600081806020019051810190611eb891906157dd565b602081015190915073ffffffffffffffffffffffffffffffffffffffff16611f0c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600a805460208085015173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff00000000000000000000000000000000000000000000000090931663ffffffff9586161792909217909255604080850151600b80546060808901516080808b0151909916760100000000000000000000000000000000000000000000027fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff61ffff90921674010000000000000000000000000000000000000000027fffffffffffffffffffff00000000000000000000000000000000000000000000909416958816959095179290921791909116929092179055815160c0810183527f00000000000000000000000000000000000000000000000000000000000000008416815267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116958201959095527f0000000000000000000000000000000000000000000000000000000000000000909416848301527f00000000000000000000000000000000000000000000000000000000000000008316908401527f00000000000000000000000000000000000000000000000000000000000000008216938301939093527f00000000000000000000000000000000000000000000000000000000000000001660a082015290517f737ef22d3f6615e342ed21c69e06620dbc5c8a261ed7cfb2ce214806b1f76eda91612143918490615878565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a60405160200161217399989796959493929190615947565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b60006111498373ffffffffffffffffffffffffffffffffffffffff84166135ab565b60006111498373ffffffffffffffffffffffffffffffffffffffff84166135b7565b60006111498373ffffffffffffffffffffffffffffffffffffffff84166135c3565b6000611b3b8473ffffffffffffffffffffffffffffffffffffffff8516846135cf565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261231182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122f59190615405565b85608001516fffffffffffffffffffffffffffffffff166135f2565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6000806123588473ffffffffffffffffffffffffffffffffffffffff8516613611565b915091505b9250929050565b600061075d82613620565b600080808061237e868661362b565b9097909650945050505050565b60606000855167ffffffffffffffff8111156123a9576123a9614795565b6040519080825280602002602001820160405280156123ee57816020015b60408051808201909152600080825260208201528152602001906001900390816123c75790505b50905060005b8651811015612803576000612425888381518110612414576124146154ac565b6020026020010151600001516110e7565b90508073ffffffffffffffffffffffffffffffffffffffff16638627fad688888b8681518110612457576124576154ac565b6020026020010151602001517f00000000000000000000000000000000000000000000000000000000000000008a8881518110612496576124966154ac565b60200260200101516040518663ffffffff1660e01b81526004016124be9594939291906159dc565b600060405180830381600087803b1580156124d857600080fd5b505af19250505080156124e9575060015b61270c573d808015612517576040519150601f19603f3d011682016040523d82523d6000602084013e61251c565b606091505b50600061252882615a3f565b90507f9725942a000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821614806125bb57507ff94ebcd1000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061260757507f15279c08000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061265357507f1a76572a000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061269f57507fd0c8d23a000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b156126d857816040517f30dabb590000000000000000000000000000000000000000000000000000000081526004016107d09190614782565b816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107d09190614782565b8073ffffffffffffffffffffffffffffffffffffffff166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277b91906155cc565b83838151811061278d5761278d6154ac565b602090810291909101015173ffffffffffffffffffffffffffffffffffffffff909116905287518890839081106127c6576127c66154ac565b6020026020010151602001518383815181106127e4576127e46154ac565b6020908102919091018101510152506127fc816154db565b90506123f4565b50600b5461282890829073ffffffffffffffffffffffffffffffffffffffff1661363a565b95945050505050565b600061283c8361381a565b80156111495750611149838361387e565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461016001518152602001846000015167ffffffffffffffff16815260200184606001516040516020016128d2919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101000151815260200183815250905092915050565b61292061290c82840184615a8f565b604080516000815260208101909152612b09565b5050565b815460009061294d90700100000000000000000000000000000000900463ffffffff1642615405565b905080156129ef5760018301548354612995916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166135f2565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a15916fffffffffffffffffffffffffffffffff908116911661394d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612afc9084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b60405180910390a1505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b989190615ac4565b15612bcf576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516000819003612c0c576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260200151518114612c4a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff811115612c6557612c65614795565b604051908082528060200260200182016040528015612c8e578160200160208202803683370190505b50905060005b82811015612d6e57600085600001518281518110612cb457612cb46154ac565b60200260200101519050612ce8817f0000000000000000000000000000000000000000000000000000000000000000613963565b838381518110612cfa57612cfa6154ac565b602002602001018181525050806101600151838381518110612d1e57612d1e6154ac565b602002602001015114612d5d576040517f7185cf6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50612d67816154db565b9050612c94565b50604080850151606086015191517f3204887500000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692633204887592612def92879291600401615b11565b602060405180830381865afa158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615b47565b905080600003612e6c576040517fea75680100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351151560005b848110156134ad57600087600001518281518110612e9357612e936154ac565b602002602001015190506000612eac82602001516106e8565b90506000816003811115612ec257612ec261469c565b1480612edf57506003816003811115612edd57612edd61469c565b145b612f275760208201516040517f50a6e05200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b8315612fe457600a5460009063ffffffff16612f438742615405565b1190508080612f6357506003826003811115612f6157612f6161469c565b145b612f99576040517f6358b0d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b888481518110612fab57612fab6154ac565b6020026020010151600014612fde57888481518110612fcc57612fcc6154ac565b60200260200101518360a00181815250505b50613041565b6000816003811115612ff857612ff861469c565b146130415760208201516040517f67d9ba0f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b606082015173ffffffffffffffffffffffffffffffffffffffff1660009081526012602052604090205467ffffffffffffffff16801580156130b857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1615155b1561325a5760608301516040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063856c824790602401602060405180830381865afa158015613150573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317491906155e9565b608084015190915067ffffffffffffffff16613191826001615b60565b67ffffffffffffffff16146131fe57826060015173ffffffffffffffffffffffffffffffffffffffff16836080015167ffffffffffffffff167fe44a20935573a783dd0d5991c92d7b6a0eb3173566530364db3ec10e9a990b5d60405160405180910390a350505061349d565b606083015173ffffffffffffffffffffffffffffffffffffffff16600090815260126020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83161790555b600082600381111561326e5761326e61469c565b036132fa57608083015167ffffffffffffffff1661328d826001615b60565b67ffffffffffffffff16146132fa57826060015173ffffffffffffffffffffffffffffffffffffffff16836080015167ffffffffffffffff167fd32ddb11d71e3d63411d37b09f9a8b28664f1cb1338bfd1413c173b0ebf4123760405160405180910390a350505061349d565b60008a602001518581518110613312576133126154ac565b60200260200101519050613327848251613a7a565b61333684602001516001613c50565b6000806133438684613cfa565b91509150613355866020015183613c50565b60038260038111156133695761336961469c565b14158015613389575060028260038111156133865761338661469c565b14155b156133c8578560200151826040517f9e2616030000000000000000000000000000000000000000000000000000000081526004016107d0929190615b81565b60008560038111156133dc576133dc61469c565b0361344857606086015173ffffffffffffffffffffffffffffffffffffffff166000908152601260205260408120805467ffffffffffffffff169161342083615b9f565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b856101600151866020015167ffffffffffffffff167fd4f851956a5d67c3997d1c9205045fef79bae2947fdee7e9e2641abc7391ef65848460405161348e929190615bbc565b60405180910390a35050505050505b6134a6816154db565b9050612e73565b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006111498383613e9d565b60006111498383613ea9565b60006111498383613f33565b6000611b3b848473ffffffffffffffffffffffffffffffffffffffff8516613f50565b600061282885613602848661546e565b61360c90876157b6565b61394d565b600080808061237e8686613f6d565b600061075d82613fa7565b600080808061237e8686613fb2565b81516000805b828110156138065760008473ffffffffffffffffffffffffffffffffffffffff1663d02641a0878481518110613678576136786154ac565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016040805180830381865afa1580156136ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137109190615bdc565b51905077ffffffffffffffffffffffffffffffffffffffffffffffff811660000361379e57858281518110613747576137476154ac565b6020908102919091010151516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016107d0565b6137e88683815181106137b3576137b36154ac565b6020026020010151602001518277ffffffffffffffffffffffffffffffffffffffffffffffff16613fdd90919063ffffffff16565b6137f290846157b6565b925050806137ff906154db565b9050613640565b506138146003826000614016565b50505050565b6000613846827f01ffc9a70000000000000000000000000000000000000000000000000000000061387e565b801561075d5750613877827fffffffff0000000000000000000000000000000000000000000000000000000061387e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015613936575060208210155b80156139425750600081115b979650505050505050565b600081831061395c5781611149565b5090919050565b60008060001b828460200151856080015186606001518760e00151886101000151805190602001208961012001516040516020016139a19190615c3a565b604051602081830303815290604052805190602001208a60a001518b60c001518c61014001518d60400151604051602001613a5c9c9b9a999897969594939291909b8c5260208c019a909a5267ffffffffffffffff98891660408c01529690971660608a015273ffffffffffffffffffffffffffffffffffffffff94851660808a015292841660a089015260c088019190915260e0870152610100860152911515610120850152166101408301526101608201526101800190565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16826000015167ffffffffffffffff1614613afa5781516040517f1279ec8a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b600b54610120830151517401000000000000000000000000000000000000000090910461ffff161015613b6b5760208201516040517f099d3f7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b808261012001515114613bbc5760208201516040517f8808f8e700000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b600b546101008301515176010000000000000000000000000000000000000000000090910463ffffffff16101561292057600b54610100830151516040517f8693378900000000000000000000000000000000000000000000000000000000815276010000000000000000000000000000000000000000000090920463ffffffff16600483015260248201526044016107d0565b60006002613c5f608085615447565b67ffffffffffffffff16613c73919061546e565b90506000601381613c85608087615485565b67ffffffffffffffff168152602081019190915260400160002054905081613caf60016004615405565b901b191681836003811115613cc657613cc661469c565b901b178060136000613cd9608088615485565b67ffffffffffffffff16815260208101919091526040016000205550505050565b6040517fafa0d379000000000000000000000000000000000000000000000000000000008152600090606090309063afa0d37990613d3e9087908790600401615cc3565b600060405180830381600087803b158015613d5857600080fd5b505af1925050508015613d69575060015b613e82573d808015613d97576040519150601f19603f3d011682016040523d82523d6000602084013e613d9c565b606091505b50613da681615a3f565b7fffffffff00000000000000000000000000000000000000000000000000000000167f0a8d6e8c000000000000000000000000000000000000000000000000000000001480613e3e5750613df981615a3f565b7fffffffff00000000000000000000000000000000000000000000000000000000167fe1cd550900000000000000000000000000000000000000000000000000000000145b15613e4e5760039250905061235d565b806040517fcf19edfd0000000000000000000000000000000000000000000000000000000081526004016107d09190614782565b50506040805160208101909152600081526002909250929050565b60006111498383614399565b600081815260028301602052604081205480151580613ecd5750613ecd8484613e9d565b611149576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b6579000060448201526064016107d0565b6000818152600283016020526040812081905561114983836143b1565b60008281526002840160205260408120829055611b3b84846143bd565b6000818152600283016020526040812054819080613f9c57613f8f8585613e9d565b92506000915061235d9050565b60019250905061235d565b600061075d826143c9565b60008080613fc085856143d3565b600081815260029690960160205260409095205494959350505050565b6000670de0b6b3a764000061400c8377ffffffffffffffffffffffffffffffffffffffffffffffff861661546e565b6111499190615e2e565b825474010000000000000000000000000000000000000000900460ff16158061403d575081155b1561404757505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061408d90700100000000000000000000000000000000900463ffffffff1642615405565b9050801561414d57818311156140cf576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546141099083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166135f2565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156142045773ffffffffffffffffffffffffffffffffffffffff84166141ac576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016107d0565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016107d0565b848310156143175760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906142489082615405565b614252878a615405565b61425c91906157b6565b6142669190615e2e565b905073ffffffffffffffffffffffffffffffffffffffff86166142bf576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016107d0565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016107d0565b6143218584615405565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60008181526001830160205260408120541515611149565b600061114983836143df565b600061114983836144d9565b600061075d825490565b60006111498383614528565b600081815260018301602052604081205480156144c8576000614403600183615405565b855490915060009061441790600190615405565b905081811461447c576000866000018281548110614437576144376154ac565b906000526020600020015490508087600001848154811061445a5761445a6154ac565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061448d5761448d615e42565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061075d565b600091505061075d565b5092915050565b60008181526001830160205260408120546145205750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561075d565b50600061075d565b600082600001828154811061453f5761453f6154ac565b9060005260206000200154905092915050565b8280548282559060005260206000209081019282156145cc579160200282015b828111156145cc57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614572565b506112749291505b8082111561127457600081556001016145d4565b60c0810161075d828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015250508060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b67ffffffffffffffff81168114611bc557600080fd5b803561467a81614659565b919050565b60006020828403121561469157600080fd5b813561114981614659565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110614702577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161075d82846146cb565b60005b8381101561472f578181015183820152602001614717565b50506000910152565b60008151808452614750816020860160208601614714565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111496020830184614738565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156147e7576147e7614795565b60405290565b604051610180810167ffffffffffffffff811182821017156147e7576147e7614795565b6040516080810167ffffffffffffffff811182821017156147e7576147e7614795565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561487b5761487b614795565b604052919050565b600067ffffffffffffffff82111561489d5761489d614795565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114611bc557600080fd5b803561467a816148a7565b600082601f8301126148e557600080fd5b813560206148fa6148f583614883565b614834565b82815260059290921b8401810191818101908684111561491957600080fd5b8286015b8481101561493d578035614930816148a7565b835291830191830161491d565b509695505050505050565b803560ff8116811461467a57600080fd5b600067ffffffffffffffff82111561497357614973614795565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126149b057600080fd5b81356149be6148f582614959565b8181528460208386010111156149d357600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614a0957600080fd5b863567ffffffffffffffff80821115614a2157600080fd5b614a2d8a838b016148d4565b97506020890135915080821115614a4357600080fd5b614a4f8a838b016148d4565b9650614a5d60408a01614948565b95506060890135915080821115614a7357600080fd5b614a7f8a838b0161499f565b9450614a8d60808a0161466f565b935060a0890135915080821115614aa357600080fd5b50614ab089828a0161499f565b9150509295509295509295565b60008083601f840112614acf57600080fd5b50813567ffffffffffffffff811115614ae757600080fd5b6020830191508360208260061b850101111561235d57600080fd5b60008060008060408587031215614b1857600080fd5b843567ffffffffffffffff80821115614b3057600080fd5b614b3c88838901614abd565b90965094506020870135915080821115614b5557600080fd5b50614b6287828801614abd565b95989497509550505050565b600060208284031215614b8057600080fd5b8135611149816148a7565b600081518084526020808501945080840160005b83811015614bd157815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614b9f565b509495945050505050565b6020815260006111496020830184614b8b565b6020808252825182820181905260009190848201906040850190845b81811015614c3d57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614c0b565b50909695505050505050565b60a0810161075d828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff8082166020860152806040850151166040860152505061ffff6060830151166060840152806080830151166080840152505050565b600060208284031215614cbe57600080fd5b813567ffffffffffffffff811115614cd557600080fd5b820160a0818503121561114957600080fd5b8015158114611bc557600080fd5b803561467a81614ce7565b600082601f830112614d1157600080fd5b81356020614d216148f583614883565b82815260069290921b84018101918181019086841115614d4057600080fd5b8286015b8481101561493d5760408189031215614d5d5760008081fd5b614d656147c4565b8135614d70816148a7565b81528185013585820152835291830191604001614d44565b60006101808284031215614d9b57600080fd5b614da36147ed565b9050614dae8261466f565b8152614dbc6020830161466f565b602082015260408201356040820152614dd7606083016148c9565b6060820152614de86080830161466f565b608082015260a082013560a0820152614e0360c08301614cf5565b60c0820152614e1460e083016148c9565b60e08201526101008083013567ffffffffffffffff80821115614e3657600080fd5b614e428683870161499f565b83850152610120925082850135915080821115614e5e57600080fd5b50614e6b85828601614d00565b828401525050610140614e7f8184016148c9565b818301525061016080830135818301525092915050565b600082601f830112614ea757600080fd5b81356020614eb76148f583614883565b82815260059290921b84018101918181019086841115614ed657600080fd5b8286015b8481101561493d57803567ffffffffffffffff811115614efa5760008081fd5b614f088986838b010161499f565b845250918301918301614eda565b60008060408385031215614f2957600080fd5b823567ffffffffffffffff80821115614f4157600080fd5b614f4d86838701614d88565b93506020850135915080821115614f6357600080fd5b50614f7085828601614e96565b9150509250929050565b60008083601f840112614f8c57600080fd5b50813567ffffffffffffffff811115614fa457600080fd5b6020830191508360208260051b850101111561235d57600080fd5b60008060008060008060008060e0898b031215614fdb57600080fd5b606089018a811115614fec57600080fd5b8998503567ffffffffffffffff8082111561500657600080fd5b818b0191508b601f83011261501a57600080fd5b81358181111561502957600080fd5b8c602082850101111561503b57600080fd5b6020830199508098505060808b013591508082111561505957600080fd5b6150658c838d01614f7a565b909750955060a08b013591508082111561507e57600080fd5b5061508b8b828c01614f7a565b999c989b50969995989497949560c00135949350505050565b80356fffffffffffffffffffffffffffffffff8116811461467a57600080fd5b6000606082840312156150d657600080fd5b6040516060810181811067ffffffffffffffff821117156150f9576150f9614795565b604052823561510781614ce7565b8152615115602084016150a4565b6020820152615126604084016150a4565b60408201529392505050565b600082601f83011261514357600080fd5b813560206151536148f583614883565b82815260059290921b8401810191818101908684111561517257600080fd5b8286015b8481101561493d57803567ffffffffffffffff8111156151965760008081fd5b6151a48986838b0101614e96565b845250918301918301615176565b600082601f8301126151c357600080fd5b813560206151d36148f583614883565b82815260059290921b840181019181810190868411156151f257600080fd5b8286015b8481101561493d57803583529183019183016151f6565b60006080828403121561521f57600080fd5b615227614811565b9050813567ffffffffffffffff8082111561524157600080fd5b818401915084601f83011261525557600080fd5b813560206152656148f583614883565b82815260059290921b8401810191818101908884111561528457600080fd5b8286015b848110156152bc578035868111156152a05760008081fd5b6152ae8b86838b0101614d88565b845250918301918301615288565b50865250858101359350828411156152d357600080fd5b6152df87858801615132565b908501525060408401359150808211156152f857600080fd5b50615305848285016151b2565b6040830152506060820135606082015292915050565b6000806040838503121561532e57600080fd5b823567ffffffffffffffff8082111561534657600080fd5b6153528683870161520d565b935060209150818501358181111561536957600080fd5b85019050601f8101861361537c57600080fd5b803561538a6148f582614883565b81815260059190911b820183019083810190888311156153a957600080fd5b928401925b828410156153c7578335825292840192908401906153ae565b80955050505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561075d5761075d6153d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff8084168061546257615462615418565b92169190910692915050565b808202811582820484141761075d5761075d6153d6565b600067ffffffffffffffff808416806154a0576154a0615418565b92169190910492915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361550c5761550c6153d6565b5060010190565b600063ffffffff80831681810361552c5761552c6153d6565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526155668184018a614b8b565b9050828103608084015261557a8189614b8b565b905060ff871660a084015282810360c08401526155978187614738565b905067ffffffffffffffff851660e08401528281036101008401526155bc8185614738565b9c9b505050505050505050505050565b6000602082840312156155de57600080fd5b8151611149816148a7565b6000602082840312156155fb57600080fd5b815161114981614659565b600081518084526020808501945080840160005b83811015614bd1578151805173ffffffffffffffffffffffffffffffffffffffff168852830151838801526040909601959082019060010161561a565b608081528451608082015267ffffffffffffffff60208601511660a08201526000604086015160a060c0840152615692610120840182614738565b905060608701517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80808584030160e08601526156ce8383614738565b9250608089015191508085840301610100860152506156ed8282615606565b92505050615701602083018661ffff169052565b836040830152612828606083018473ffffffffffffffffffffffffffffffffffffffff169052565b6000806040838503121561573c57600080fd5b825161574781614ce7565b602084015190925067ffffffffffffffff81111561576457600080fd5b8301601f8101851361577557600080fd5b80516157836148f582614959565b81815286602083850101111561579857600080fd5b6157a9826020830160208601614714565b8093505050509250929050565b8082018082111561075d5761075d6153d6565b805163ffffffff8116811461467a57600080fd5b600060a082840312156157ef57600080fd5b60405160a0810181811067ffffffffffffffff8211171561581257615812614795565b60405261581e836157c9565b8152602083015161582e816148a7565b60208201526040830151615841816148a7565b6040820152606083015161ffff8116811461585b57600080fd5b606082015261586c608084016157c9565b60808201529392505050565b61016081016158ea828573ffffffffffffffffffffffffffffffffffffffff808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015250508060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b825163ffffffff90811660c0840152602084015173ffffffffffffffffffffffffffffffffffffffff90811660e0850152604085015116610100840152606084015161ffff16610120840152608084015116610140830152611149565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b16604085015281606085015261598e8285018b614b8b565b915083820360808501526159a2828a614b8b565b915060ff881660a085015283820360c08501526159bf8288614738565b90861660e085015283810361010085015290506155bc8185614738565b60a0815260006159ef60a0830188614738565b73ffffffffffffffffffffffffffffffffffffffff8716602084015285604084015267ffffffffffffffff851660608401528281036080840152615a338185614738565b98975050505050505050565b6000815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015615a875780818460040360031b1b83161693505b505050919050565b600060208284031215615aa157600080fd5b813567ffffffffffffffff811115615ab857600080fd5b611b3b8482850161520d565b600060208284031215615ad657600080fd5b815161114981614ce7565b600081518084526020808501945080840160005b83811015614bd157815187529582019590820190600101615af5565b606081526000615b246060830186615ae1565b8281036020840152615b368186615ae1565b915050826040830152949350505050565b600060208284031215615b5957600080fd5b5051919050565b67ffffffffffffffff8181168382160190808211156144d2576144d26153d6565b67ffffffffffffffff831681526040810161114960208301846146cb565b600067ffffffffffffffff80831681810361552c5761552c6153d6565b615bc681846146cb565b604060208201526000611b3b6040830184614738565b600060408284031215615bee57600080fd5b615bf66147c4565b825177ffffffffffffffffffffffffffffffffffffffffffffffff81168114615c1e57600080fd5b81526020830151615c2e81614659565b60208201529392505050565b6020815260006111496020830184615606565b600082825180855260208086019550808260051b84010181860160005b84811015615cb6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952615ca4838351614738565b98840198925090830190600101615c6a565b5090979650505050505050565b60408152615cde60408201845167ffffffffffffffff169052565b60006020840151615cfb606084018267ffffffffffffffff169052565b5060408401516080830152606084015173ffffffffffffffffffffffffffffffffffffffff811660a084015250608084015167ffffffffffffffff811660c08401525060a084015160e083015260c0840151610100615d5d8185018315159052565b60e08601519150610120615d888186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061018091506101408281870152615da96101c0870185614738565b93508188015191506101607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08786030181880152615de78584615606565b9450818901519250615e108488018473ffffffffffffffffffffffffffffffffffffffff169052565b8801516101a087015250505082810360208401526128288185615c4d565b600082615e3d57615e3d615418565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", -} - -var EVM2EVMOffRampABI = EVM2EVMOffRampMetaData.ABI - -var EVM2EVMOffRampBin = EVM2EVMOffRampMetaData.Bin - -func DeployEVM2EVMOffRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMOffRampStaticConfig, sourceTokens []common.Address, pools []common.Address, rateLimiterConfig RateLimiterConfig) (common.Address, *types.Transaction, *EVM2EVMOffRamp, error) { - parsed, err := EVM2EVMOffRampMetaData.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(EVM2EVMOffRampBin), backend, staticConfig, sourceTokens, pools, rateLimiterConfig) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &EVM2EVMOffRamp{EVM2EVMOffRampCaller: EVM2EVMOffRampCaller{contract: contract}, EVM2EVMOffRampTransactor: EVM2EVMOffRampTransactor{contract: contract}, EVM2EVMOffRampFilterer: EVM2EVMOffRampFilterer{contract: contract}}, nil -} - -type EVM2EVMOffRamp struct { - address common.Address - abi abi.ABI - EVM2EVMOffRampCaller - EVM2EVMOffRampTransactor - EVM2EVMOffRampFilterer -} - -type EVM2EVMOffRampCaller struct { - contract *bind.BoundContract -} - -type EVM2EVMOffRampTransactor struct { - contract *bind.BoundContract -} - -type EVM2EVMOffRampFilterer struct { - contract *bind.BoundContract -} - -type EVM2EVMOffRampSession struct { - Contract *EVM2EVMOffRamp - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type EVM2EVMOffRampCallerSession struct { - Contract *EVM2EVMOffRampCaller - CallOpts bind.CallOpts -} - -type EVM2EVMOffRampTransactorSession struct { - Contract *EVM2EVMOffRampTransactor - TransactOpts bind.TransactOpts -} - -type EVM2EVMOffRampRaw struct { - Contract *EVM2EVMOffRamp -} - -type EVM2EVMOffRampCallerRaw struct { - Contract *EVM2EVMOffRampCaller -} - -type EVM2EVMOffRampTransactorRaw struct { - Contract *EVM2EVMOffRampTransactor -} - -func NewEVM2EVMOffRamp(address common.Address, backend bind.ContractBackend) (*EVM2EVMOffRamp, error) { - abi, err := abi.JSON(strings.NewReader(EVM2EVMOffRampABI)) - if err != nil { - return nil, err - } - contract, err := bindEVM2EVMOffRamp(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &EVM2EVMOffRamp{address: address, abi: abi, EVM2EVMOffRampCaller: EVM2EVMOffRampCaller{contract: contract}, EVM2EVMOffRampTransactor: EVM2EVMOffRampTransactor{contract: contract}, EVM2EVMOffRampFilterer: EVM2EVMOffRampFilterer{contract: contract}}, nil -} - -func NewEVM2EVMOffRampCaller(address common.Address, caller bind.ContractCaller) (*EVM2EVMOffRampCaller, error) { - contract, err := bindEVM2EVMOffRamp(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampCaller{contract: contract}, nil -} - -func NewEVM2EVMOffRampTransactor(address common.Address, transactor bind.ContractTransactor) (*EVM2EVMOffRampTransactor, error) { - contract, err := bindEVM2EVMOffRamp(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampTransactor{contract: contract}, nil -} - -func NewEVM2EVMOffRampFilterer(address common.Address, filterer bind.ContractFilterer) (*EVM2EVMOffRampFilterer, error) { - contract, err := bindEVM2EVMOffRamp(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampFilterer{contract: contract}, nil -} - -func bindEVM2EVMOffRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EVM2EVMOffRampMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMOffRamp.Contract.EVM2EVMOffRampCaller.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.EVM2EVMOffRampTransactor.contract.Transfer(opts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.EVM2EVMOffRampTransactor.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMOffRamp.Contract.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.contract.Transfer(opts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "ccipReceive", arg0) - - if err != nil { - return err - } - - return err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) CcipReceive(arg0 ClientAny2EVMMessage) error { - return _EVM2EVMOffRamp.Contract.CcipReceive(&_EVM2EVMOffRamp.CallOpts, arg0) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) CcipReceive(arg0 ClientAny2EVMMessage) error { - return _EVM2EVMOffRamp.Contract.CcipReceive(&_EVM2EVMOffRamp.CallOpts, arg0) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "currentRateLimiterState") - - if err != nil { - return *new(RateLimiterTokenBucket), err - } - - out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMOffRamp.Contract.CurrentRateLimiterState(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMOffRamp.Contract.CurrentRateLimiterState(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetDestinationToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getDestinationToken", sourceToken) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetDestinationToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetDestinationToken(&_EVM2EVMOffRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetDestinationToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetDestinationToken(&_EVM2EVMOffRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetDestinationTokens(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getDestinationTokens") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetDestinationTokens() ([]common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetDestinationTokens(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetDestinationTokens() ([]common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetDestinationTokens(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMOffRampDynamicConfig, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(EVM2EVMOffRampDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOffRampDynamicConfig)).(*EVM2EVMOffRampDynamicConfig) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetDynamicConfig() (EVM2EVMOffRampDynamicConfig, error) { - return _EVM2EVMOffRamp.Contract.GetDynamicConfig(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetDynamicConfig() (EVM2EVMOffRampDynamicConfig, error) { - return _EVM2EVMOffRamp.Contract.GetDynamicConfig(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetExecutionState(opts *bind.CallOpts, sequenceNumber uint64) (uint8, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getExecutionState", sequenceNumber) - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetExecutionState(sequenceNumber uint64) (uint8, error) { - return _EVM2EVMOffRamp.Contract.GetExecutionState(&_EVM2EVMOffRamp.CallOpts, sequenceNumber) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetExecutionState(sequenceNumber uint64) (uint8, error) { - return _EVM2EVMOffRamp.Contract.GetExecutionState(&_EVM2EVMOffRamp.CallOpts, sequenceNumber) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetPoolByDestToken(opts *bind.CallOpts, destToken common.Address) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getPoolByDestToken", destToken) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetPoolByDestToken(destToken common.Address) (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetPoolByDestToken(&_EVM2EVMOffRamp.CallOpts, destToken) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetPoolByDestToken(destToken common.Address) (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetPoolByDestToken(&_EVM2EVMOffRamp.CallOpts, destToken) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getPoolBySourceToken", sourceToken) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetPoolBySourceToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetPoolBySourceToken(&_EVM2EVMOffRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetPoolBySourceToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetPoolBySourceToken(&_EVM2EVMOffRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getSenderNonce", sender) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetSenderNonce(sender common.Address) (uint64, error) { - return _EVM2EVMOffRamp.Contract.GetSenderNonce(&_EVM2EVMOffRamp.CallOpts, sender) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetSenderNonce(sender common.Address) (uint64, error) { - return _EVM2EVMOffRamp.Contract.GetSenderNonce(&_EVM2EVMOffRamp.CallOpts, sender) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetStaticConfig(opts *bind.CallOpts) (EVM2EVMOffRampStaticConfig, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(EVM2EVMOffRampStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOffRampStaticConfig)).(*EVM2EVMOffRampStaticConfig) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetStaticConfig() (EVM2EVMOffRampStaticConfig, error) { - return _EVM2EVMOffRamp.Contract.GetStaticConfig(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetStaticConfig() (EVM2EVMOffRampStaticConfig, error) { - return _EVM2EVMOffRamp.Contract.GetStaticConfig(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getSupportedTokens") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetSupportedTokens() ([]common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetSupportedTokens(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetSupportedTokens() ([]common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetSupportedTokens(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getTokenLimitAdmin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "getTransmitters") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) GetTransmitters() ([]common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetTransmitters(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) GetTransmitters() ([]common.Address, error) { - return _EVM2EVMOffRamp.Contract.GetTransmitters(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) { - var out []interface{} - err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _EVM2EVMOffRamp.Contract.LatestConfigDetails(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _EVM2EVMOffRamp.Contract.LatestConfigDetails(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) { - var out []interface{} - err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _EVM2EVMOffRamp.Contract.LatestConfigDigestAndEpoch(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _EVM2EVMOffRamp.Contract.LatestConfigDigestAndEpoch(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampSession) Owner() (common.Address, error) { - return _EVM2EVMOffRamp.Contract.Owner(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) Owner() (common.Address, error) { - return _EVM2EVMOffRamp.Contract.Owner(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _EVM2EVMOffRamp.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) TypeAndVersion() (string, error) { - return _EVM2EVMOffRamp.Contract.TypeAndVersion(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampCallerSession) TypeAndVersion() (string, error) { - return _EVM2EVMOffRamp.Contract.TypeAndVersion(&_EVM2EVMOffRamp.CallOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "acceptOwnership") -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.AcceptOwnership(&_EVM2EVMOffRamp.TransactOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.AcceptOwnership(&_EVM2EVMOffRamp.TransactOpts) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ApplyPoolUpdates(opts *bind.TransactOpts, removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "applyPoolUpdates", removes, adds) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ApplyPoolUpdates(removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ApplyPoolUpdates(&_EVM2EVMOffRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ApplyPoolUpdates(removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ApplyPoolUpdates(&_EVM2EVMOffRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMOffRamp.TransactOpts, message, offchainTokenData) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMOffRamp.TransactOpts, message, offchainTokenData) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "manuallyExecute", report, gasLimitOverrides) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) ManuallyExecute(report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ManuallyExecute(&_EVM2EVMOffRamp.TransactOpts, report, gasLimitOverrides) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) ManuallyExecute(report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.ManuallyExecute(&_EVM2EVMOffRamp.TransactOpts, report, gasLimitOverrides) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "setAdmin", newAdmin) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.SetAdmin(&_EVM2EVMOffRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.SetAdmin(&_EVM2EVMOffRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "setOCR2Config", signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) SetOCR2Config(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.SetOCR2Config(&_EVM2EVMOffRamp.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) SetOCR2Config(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.SetOCR2Config(&_EVM2EVMOffRamp.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "setRateLimiterConfig", config) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.SetRateLimiterConfig(&_EVM2EVMOffRamp.TransactOpts, config) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.SetRateLimiterConfig(&_EVM2EVMOffRamp.TransactOpts, config) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "transferOwnership", to) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.TransferOwnership(&_EVM2EVMOffRamp.TransactOpts, to) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.TransferOwnership(&_EVM2EVMOffRamp.TransactOpts, to) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.contract.Transact(opts, "transmit", reportContext, report, rs, ss, arg4) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.Transmit(&_EVM2EVMOffRamp.TransactOpts, reportContext, report, rs, ss, arg4) -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte) (*types.Transaction, error) { - return _EVM2EVMOffRamp.Contract.Transmit(&_EVM2EVMOffRamp.TransactOpts, reportContext, report, rs, ss, arg4) -} - -type EVM2EVMOffRampAdminSetIterator struct { - Event *EVM2EVMOffRampAdminSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampAdminSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampAdminSet) - 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(EVM2EVMOffRampAdminSet) - 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 *EVM2EVMOffRampAdminSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampAdminSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampAdminSet struct { - NewAdmin common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMOffRampAdminSetIterator, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return &EVM2EVMOffRampAdminSetIterator{contract: _EVM2EVMOffRamp.contract, event: "AdminSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampAdminSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOffRampAdminSet) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "AdminSet", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseAdminSet(log types.Log) (*EVM2EVMOffRampAdminSet, error) { - event := new(EVM2EVMOffRampAdminSet) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "AdminSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampConfigSetIterator struct { - Event *EVM2EVMOffRampConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampConfigSet) - 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(EVM2EVMOffRampConfigSet) - 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 *EVM2EVMOffRampConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampConfigSet struct { - StaticConfig EVM2EVMOffRampStaticConfig - DynamicConfig EVM2EVMOffRampDynamicConfig - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMOffRampConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOffRampConfigSetIterator{contract: _EVM2EVMOffRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOffRamp.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(EVM2EVMOffRampConfigSet) - if err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMOffRampConfigSet, error) { - event := new(EVM2EVMOffRampConfigSet) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampConfigSet0Iterator struct { - Event *EVM2EVMOffRampConfigSet0 - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampConfigSet0Iterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampConfigSet0) - 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(EVM2EVMOffRampConfigSet0) - 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 *EVM2EVMOffRampConfigSet0Iterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampConfigSet0Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampConfigSet0 struct { - PreviousConfigBlockNumber uint32 - ConfigDigest [32]byte - ConfigCount uint64 - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterConfigSet0(opts *bind.FilterOpts) (*EVM2EVMOffRampConfigSet0Iterator, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "ConfigSet0") - if err != nil { - return nil, err - } - return &EVM2EVMOffRampConfigSet0Iterator{contract: _EVM2EVMOffRamp.contract, event: "ConfigSet0", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampConfigSet0) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "ConfigSet0") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOffRampConfigSet0) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "ConfigSet0", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseConfigSet0(log types.Log) (*EVM2EVMOffRampConfigSet0, error) { - event := new(EVM2EVMOffRampConfigSet0) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampExecutionStateChangedIterator struct { - Event *EVM2EVMOffRampExecutionStateChanged - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampExecutionStateChangedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampExecutionStateChanged) - 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(EVM2EVMOffRampExecutionStateChanged) - 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 *EVM2EVMOffRampExecutionStateChangedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampExecutionStateChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampExecutionStateChanged struct { - SequenceNumber uint64 - MessageId [32]byte - State uint8 - ReturnData []byte - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterExecutionStateChanged(opts *bind.FilterOpts, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMOffRampExecutionStateChangedIterator, error) { - - var sequenceNumberRule []interface{} - for _, sequenceNumberItem := range sequenceNumber { - sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) - } - var messageIdRule []interface{} - for _, messageIdItem := range messageId { - messageIdRule = append(messageIdRule, messageIdItem) - } - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "ExecutionStateChanged", sequenceNumberRule, messageIdRule) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampExecutionStateChangedIterator{contract: _EVM2EVMOffRamp.contract, event: "ExecutionStateChanged", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampExecutionStateChanged, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { - - var sequenceNumberRule []interface{} - for _, sequenceNumberItem := range sequenceNumber { - sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) - } - var messageIdRule []interface{} - for _, messageIdItem := range messageId { - messageIdRule = append(messageIdRule, messageIdItem) - } - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "ExecutionStateChanged", sequenceNumberRule, messageIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOffRampExecutionStateChanged) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseExecutionStateChanged(log types.Log) (*EVM2EVMOffRampExecutionStateChanged, error) { - event := new(EVM2EVMOffRampExecutionStateChanged) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMOffRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampOwnershipTransferRequested) - 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(EVM2EVMOffRampOwnershipTransferRequested) - 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 *EVM2EVMOffRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOffRampOwnershipTransferRequestedIterator, 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 := _EVM2EVMOffRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampOwnershipTransferRequestedIterator{contract: _EVM2EVMOffRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampOwnershipTransferRequested, 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 := _EVM2EVMOffRamp.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(EVM2EVMOffRampOwnershipTransferRequested) - if err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMOffRampOwnershipTransferRequested, error) { - event := new(EVM2EVMOffRampOwnershipTransferRequested) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampOwnershipTransferredIterator struct { - Event *EVM2EVMOffRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampOwnershipTransferred) - 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(EVM2EVMOffRampOwnershipTransferred) - 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 *EVM2EVMOffRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOffRampOwnershipTransferredIterator, 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 := _EVM2EVMOffRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampOwnershipTransferredIterator{contract: _EVM2EVMOffRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampOwnershipTransferred, 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 := _EVM2EVMOffRamp.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(EVM2EVMOffRampOwnershipTransferred) - if err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMOffRampOwnershipTransferred, error) { - event := new(EVM2EVMOffRampOwnershipTransferred) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampPoolAddedIterator struct { - Event *EVM2EVMOffRampPoolAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampPoolAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampPoolAdded) - 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(EVM2EVMOffRampPoolAdded) - 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 *EVM2EVMOffRampPoolAddedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampPoolAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampPoolAdded struct { - Token common.Address - Pool common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterPoolAdded(opts *bind.FilterOpts) (*EVM2EVMOffRampPoolAddedIterator, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "PoolAdded") - if err != nil { - return nil, err - } - return &EVM2EVMOffRampPoolAddedIterator{contract: _EVM2EVMOffRamp.contract, event: "PoolAdded", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampPoolAdded) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "PoolAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOffRampPoolAdded) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "PoolAdded", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParsePoolAdded(log types.Log) (*EVM2EVMOffRampPoolAdded, error) { - event := new(EVM2EVMOffRampPoolAdded) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "PoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampPoolRemovedIterator struct { - Event *EVM2EVMOffRampPoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampPoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampPoolRemoved) - 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(EVM2EVMOffRampPoolRemoved) - 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 *EVM2EVMOffRampPoolRemovedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampPoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampPoolRemoved struct { - Token common.Address - Pool common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterPoolRemoved(opts *bind.FilterOpts) (*EVM2EVMOffRampPoolRemovedIterator, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "PoolRemoved") - if err != nil { - return nil, err - } - return &EVM2EVMOffRampPoolRemovedIterator{contract: _EVM2EVMOffRamp.contract, event: "PoolRemoved", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampPoolRemoved) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "PoolRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOffRampPoolRemoved) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "PoolRemoved", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParsePoolRemoved(log types.Log) (*EVM2EVMOffRampPoolRemoved, error) { - event := new(EVM2EVMOffRampPoolRemoved) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "PoolRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampSkippedIncorrectNonceIterator struct { - Event *EVM2EVMOffRampSkippedIncorrectNonce - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampSkippedIncorrectNonceIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampSkippedIncorrectNonce) - 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(EVM2EVMOffRampSkippedIncorrectNonce) - 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 *EVM2EVMOffRampSkippedIncorrectNonceIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampSkippedIncorrectNonceIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampSkippedIncorrectNonce struct { - Nonce uint64 - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterSkippedIncorrectNonce(opts *bind.FilterOpts, nonce []uint64, sender []common.Address) (*EVM2EVMOffRampSkippedIncorrectNonceIterator, error) { - - var nonceRule []interface{} - for _, nonceItem := range nonce { - nonceRule = append(nonceRule, nonceItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "SkippedIncorrectNonce", nonceRule, senderRule) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampSkippedIncorrectNonceIterator{contract: _EVM2EVMOffRamp.contract, event: "SkippedIncorrectNonce", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchSkippedIncorrectNonce(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampSkippedIncorrectNonce, nonce []uint64, sender []common.Address) (event.Subscription, error) { - - var nonceRule []interface{} - for _, nonceItem := range nonce { - nonceRule = append(nonceRule, nonceItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "SkippedIncorrectNonce", nonceRule, 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(EVM2EVMOffRampSkippedIncorrectNonce) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "SkippedIncorrectNonce", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseSkippedIncorrectNonce(log types.Log) (*EVM2EVMOffRampSkippedIncorrectNonce, error) { - event := new(EVM2EVMOffRampSkippedIncorrectNonce) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "SkippedIncorrectNonce", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator struct { - Event *EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight) - 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(EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight) - 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 *EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight struct { - Nonce uint64 - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterSkippedSenderWithPreviousRampMessageInflight(opts *bind.FilterOpts, nonce []uint64, sender []common.Address) (*EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error) { - - var nonceRule []interface{} - for _, nonceItem := range nonce { - nonceRule = append(nonceRule, nonceItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "SkippedSenderWithPreviousRampMessageInflight", nonceRule, senderRule) - if err != nil { - return nil, err - } - return &EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator{contract: _EVM2EVMOffRamp.contract, event: "SkippedSenderWithPreviousRampMessageInflight", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchSkippedSenderWithPreviousRampMessageInflight(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, nonce []uint64, sender []common.Address) (event.Subscription, error) { - - var nonceRule []interface{} - for _, nonceItem := range nonce { - nonceRule = append(nonceRule, nonceItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _EVM2EVMOffRamp.contract.WatchLogs(opts, "SkippedSenderWithPreviousRampMessageInflight", nonceRule, 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(EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "SkippedSenderWithPreviousRampMessageInflight", 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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseSkippedSenderWithPreviousRampMessageInflight(log types.Log) (*EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, error) { - event := new(EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight) - if err := _EVM2EVMOffRamp.contract.UnpackLog(event, "SkippedSenderWithPreviousRampMessageInflight", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOffRampTransmittedIterator struct { - Event *EVM2EVMOffRampTransmitted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOffRampTransmittedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOffRampTransmitted) - 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(EVM2EVMOffRampTransmitted) - 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 *EVM2EVMOffRampTransmittedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOffRampTransmittedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOffRampTransmitted struct { - ConfigDigest [32]byte - Epoch uint32 - Raw types.Log -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) FilterTransmitted(opts *bind.FilterOpts) (*EVM2EVMOffRampTransmittedIterator, error) { - - logs, sub, err := _EVM2EVMOffRamp.contract.FilterLogs(opts, "Transmitted") - if err != nil { - return nil, err - } - return &EVM2EVMOffRampTransmittedIterator{contract: _EVM2EVMOffRamp.contract, event: "Transmitted", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampTransmitted) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOffRamp.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(EVM2EVMOffRampTransmitted) - if err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRampFilterer) ParseTransmitted(log types.Log) (*EVM2EVMOffRampTransmitted, error) { - event := new(EVM2EVMOffRampTransmitted) - if err := _EVM2EVMOffRamp.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 (_EVM2EVMOffRamp *EVM2EVMOffRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _EVM2EVMOffRamp.abi.Events["AdminSet"].ID: - return _EVM2EVMOffRamp.ParseAdminSet(log) - case _EVM2EVMOffRamp.abi.Events["ConfigSet"].ID: - return _EVM2EVMOffRamp.ParseConfigSet(log) - case _EVM2EVMOffRamp.abi.Events["ConfigSet0"].ID: - return _EVM2EVMOffRamp.ParseConfigSet0(log) - case _EVM2EVMOffRamp.abi.Events["ExecutionStateChanged"].ID: - return _EVM2EVMOffRamp.ParseExecutionStateChanged(log) - case _EVM2EVMOffRamp.abi.Events["OwnershipTransferRequested"].ID: - return _EVM2EVMOffRamp.ParseOwnershipTransferRequested(log) - case _EVM2EVMOffRamp.abi.Events["OwnershipTransferred"].ID: - return _EVM2EVMOffRamp.ParseOwnershipTransferred(log) - case _EVM2EVMOffRamp.abi.Events["PoolAdded"].ID: - return _EVM2EVMOffRamp.ParsePoolAdded(log) - case _EVM2EVMOffRamp.abi.Events["PoolRemoved"].ID: - return _EVM2EVMOffRamp.ParsePoolRemoved(log) - case _EVM2EVMOffRamp.abi.Events["SkippedIncorrectNonce"].ID: - return _EVM2EVMOffRamp.ParseSkippedIncorrectNonce(log) - case _EVM2EVMOffRamp.abi.Events["SkippedSenderWithPreviousRampMessageInflight"].ID: - return _EVM2EVMOffRamp.ParseSkippedSenderWithPreviousRampMessageInflight(log) - case _EVM2EVMOffRamp.abi.Events["Transmitted"].ID: - return _EVM2EVMOffRamp.ParseTransmitted(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (EVM2EVMOffRampAdminSet) Topic() common.Hash { - return common.HexToHash("0x8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c") -} - -func (EVM2EVMOffRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x737ef22d3f6615e342ed21c69e06620dbc5c8a261ed7cfb2ce214806b1f76eda") -} - -func (EVM2EVMOffRampConfigSet0) Topic() common.Hash { - return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") -} - -func (EVM2EVMOffRampExecutionStateChanged) Topic() common.Hash { - return common.HexToHash("0xd4f851956a5d67c3997d1c9205045fef79bae2947fdee7e9e2641abc7391ef65") -} - -func (EVM2EVMOffRampOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (EVM2EVMOffRampOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (EVM2EVMOffRampPoolAdded) Topic() common.Hash { - return common.HexToHash("0x95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c") -} - -func (EVM2EVMOffRampPoolRemoved) Topic() common.Hash { - return common.HexToHash("0x987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c") -} - -func (EVM2EVMOffRampSkippedIncorrectNonce) Topic() common.Hash { - return common.HexToHash("0xd32ddb11d71e3d63411d37b09f9a8b28664f1cb1338bfd1413c173b0ebf41237") -} - -func (EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight) Topic() common.Hash { - return common.HexToHash("0xe44a20935573a783dd0d5991c92d7b6a0eb3173566530364db3ec10e9a990b5d") -} - -func (EVM2EVMOffRampTransmitted) Topic() common.Hash { - return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") -} - -func (_EVM2EVMOffRamp *EVM2EVMOffRamp) Address() common.Address { - return _EVM2EVMOffRamp.address -} - -type EVM2EVMOffRampInterface interface { - CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error - - CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) - - GetDestinationToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) - - GetDestinationTokens(opts *bind.CallOpts) ([]common.Address, error) - - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMOffRampDynamicConfig, error) - - GetExecutionState(opts *bind.CallOpts, sequenceNumber uint64) (uint8, error) - - GetPoolByDestToken(opts *bind.CallOpts, destToken common.Address) (common.Address, error) - - GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) - - GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) - - GetStaticConfig(opts *bind.CallOpts) (EVM2EVMOffRampStaticConfig, error) - - GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) - - GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) - - GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) - - LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) - - LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ApplyPoolUpdates(opts *bind.TransactOpts, removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) - - ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) - - ManuallyExecute(opts *bind.TransactOpts, report InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) - - SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) - - SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) - - SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte) (*types.Transaction, error) - - FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMOffRampAdminSetIterator, error) - - WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampAdminSet) (event.Subscription, error) - - ParseAdminSet(log types.Log) (*EVM2EVMOffRampAdminSet, error) - - FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMOffRampConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*EVM2EVMOffRampConfigSet, error) - - FilterConfigSet0(opts *bind.FilterOpts) (*EVM2EVMOffRampConfigSet0Iterator, error) - - WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampConfigSet0) (event.Subscription, error) - - ParseConfigSet0(log types.Log) (*EVM2EVMOffRampConfigSet0, error) - - FilterExecutionStateChanged(opts *bind.FilterOpts, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMOffRampExecutionStateChangedIterator, error) - - WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampExecutionStateChanged, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) - - ParseExecutionStateChanged(log types.Log) (*EVM2EVMOffRampExecutionStateChanged, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOffRampOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMOffRampOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOffRampOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*EVM2EVMOffRampOwnershipTransferred, error) - - FilterPoolAdded(opts *bind.FilterOpts) (*EVM2EVMOffRampPoolAddedIterator, error) - - WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampPoolAdded) (event.Subscription, error) - - ParsePoolAdded(log types.Log) (*EVM2EVMOffRampPoolAdded, error) - - FilterPoolRemoved(opts *bind.FilterOpts) (*EVM2EVMOffRampPoolRemovedIterator, error) - - WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampPoolRemoved) (event.Subscription, error) - - ParsePoolRemoved(log types.Log) (*EVM2EVMOffRampPoolRemoved, error) - - FilterSkippedIncorrectNonce(opts *bind.FilterOpts, nonce []uint64, sender []common.Address) (*EVM2EVMOffRampSkippedIncorrectNonceIterator, error) - - WatchSkippedIncorrectNonce(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampSkippedIncorrectNonce, nonce []uint64, sender []common.Address) (event.Subscription, error) - - ParseSkippedIncorrectNonce(log types.Log) (*EVM2EVMOffRampSkippedIncorrectNonce, error) - - FilterSkippedSenderWithPreviousRampMessageInflight(opts *bind.FilterOpts, nonce []uint64, sender []common.Address) (*EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error) - - WatchSkippedSenderWithPreviousRampMessageInflight(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, nonce []uint64, sender []common.Address) (event.Subscription, error) - - ParseSkippedSenderWithPreviousRampMessageInflight(log types.Log) (*EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, error) - - FilterTransmitted(opts *bind.FilterOpts) (*EVM2EVMOffRampTransmittedIterator, error) - - WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMOffRampTransmitted) (event.Subscription, error) - - ParseTransmitted(log types.Log) (*EVM2EVMOffRampTransmitted, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_onramp/evm_2_evm_onramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_onramp/evm_2_evm_onramp.go index be9c2395a05..38a4152c714 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_onramp/evm_2_evm_onramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_onramp/evm_2_evm_onramp.go @@ -56,7 +56,6 @@ type EVM2EVMOnRampDynamicConfig struct { MaxPerMsgGasLimit uint32 DefaultTokenFeeUSDCents uint16 DefaultTokenDestGasOverhead uint32 - DefaultTokenDestBytesOverhead uint32 EnforceOutOfOrder bool } @@ -142,8 +141,8 @@ type RateLimiterTokenBucket struct { } var EVM2EVMOnRampMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"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\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"}],\"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\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidChainSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"}],\"name\":\"InvalidNopAddress\",\"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\":[{\"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\":[{\"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\":\"address\",\"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\":\"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\":[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"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\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"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\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"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\"},{\"internalType\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"transferFeeConfig\",\"type\":\"tuple[]\"}],\"name\":\"TokenTransferFeeConfigSet\",\"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\":[],\"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\":[{\"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\":[],\"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\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"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\":[{\"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\":\"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\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOnRamp.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\":\"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\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"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\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"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\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"internalType\":\"address[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"address[]\"}],\"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\"}]", - Bin: "0x6101a06040523480156200001257600080fd5b50604051620082d4380380620082d4833981016040819052620000359162001b0e565b8333806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c0816200030b565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606086018190529790950151166080909301839052600380546001600160a01b031916909417600160801b9283021760ff60a01b1916600160a01b90910217909255029091176004555085516001600160a01b0316158062000169575060208601516001600160401b0316155b8062000180575060408601516001600160401b0316155b8062000197575060608601516001600160401b0316155b80620001ae575060c08601516001600160a01b0316155b80620001c5575060e08601516001600160a01b0316155b15620001e4576040516306b7c75960e31b815260040160405180910390fd5b60208087015160408089015181517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3948101949094526001600160401b039283169184019190915216606082015230608082015260a00160408051601f198184030181529181528151602092830120608090815288516001600160a01b0390811660e0908152938a01516001600160401b0390811661010052928a015183166101205260608a015190921660a0908152908901516001600160601b031660c090815290890151821661014052880151811661016052908701511661018052620002cd85620003b6565b620002d8836200071a565b604080516000815260208101909152620002f49083906200084a565b620002ff8162000aea565b50505050505062002212565b336001600160a01b03821603620003655760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e08101516001600160a01b0316620003e2576040516306b7c75960e31b815260040160405180910390fd5b602081610180015163ffffffff16101562000427576101808101516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000084565b80600560008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601a6101000a81548161ffff021916908361ffff160217905550608082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548161ffff021916908361ffff16021790555060c08201518160010160026101000a81548161ffff021916908361ffff16021790555060e08201518160010160046101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555061012082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160006101000a81548161ffff021916908361ffff1602179055506101608201518160020160026101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160020160066101000a81548163ffffffff021916908363ffffffff1602179055506101a082015181600201600a6101000a81548160ff0219169083151502179055509050507fe375c8cb6ea9807cd0371503b632b93da5ee0f1f64205db8b5b28b95d6b588b060405180610100016040528060e0516001600160a01b03168152602001610100516001600160401b03168152602001610120516001600160401b0316815260200160a0516001600160401b0316815260200160c0516001600160601b03168152602001610140516001600160a01b03168152602001610160516001600160a01b03168152602001610180516001600160a01b0316815250826040516200070f92919062001da4565b60405180910390a150565b60005b8151811015620008185760008282815181106200073e576200073e62001e69565b60209081029190910181015160408051608080820183528385015163ffffffff9081168352838501516001600160401b03908116848801908152606080880151831686880190815294880151151590860190815296516001600160a01b03166000908152600b90985294909620925183549451925195511515600160a01b0260ff60a01b199688166c010000000000000000000000000296909616600160601b600160a81b031993909716640100000000026001600160601b0319909516911617929092179190911692909217179055506001016200071d565b507f067924bf9277d905a9a4631a06d959bc032ace86b3caa835ae7e403d4f39010e816040516200070f919062001e7f565b60005b825181101562000a095760008382815181106200086e576200086e62001e69565b6020026020010151905060208160a0015163ffffffff161015620008c457805160a08201516040516312766e0160e11b81526001600160a01b03909216600483015263ffffffff16602482015260440162000084565b6040805160e08101825260208381015163ffffffff908116835284840151811682840190815260608087015161ffff9081168688019081526080808a0151861693880193845260a0808b0151871691890191825260c0808c01511515918a019182526001908a018181529b516001600160a01b03166000908152600c9099529990972097518854955192519451915197519a519087166001600160401b031990961695909517640100000000928716929092029190911765ffffffffffff60401b191668010000000000000000939092169290920263ffffffff60501b1916176a0100000000000000000000918416919091021764ffffffffff60701b1916600160701b939092169290920260ff60901b191617600160901b941515949094029390931760ff60981b1916600160981b9315159390930292909217909155016200084d565b507ff5791bc457b3bb990493cf5f655db46c25ccf5764c9b99b8969b4c72ea7df9d08260405162000a3b919062001f0e565b60405180910390a160005b815181101562000aa357600c600083838151811062000a695762000a6962001e69565b6020908102919091018101516001600160a01b0316825281019190915260400160002080546001600160a01b031916905560010162000a46565b5080511562000ae6577ffb95a0042158e60a33e7b5bec100f3d95407b1a71bee6633bd54b8887449750b8160405162000add919062001fa3565b60405180910390a15b5050565b8051604081111562000b0f57604051635ad0867d60e11b815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff161562000b6257600e5463ffffffff6c010000000000000000000000008204166001600160601b039091161062000b625762000b6262000d05565b600062000b70600862000ef1565b90505b801562000bbc57600062000b9662000b8d60018462002008565b60089062000f04565b50905062000ba660088262000f22565b50508062000bb4906200201e565b905062000b73565b506000805b8281101562000c9c57600084828151811062000be15762000be162001e69565b6020026020010151600001519050600085838151811062000c065762000c0662001e69565b602002602001015160200151905060e0516001600160a01b0316826001600160a01b0316148062000c3e57506001600160a01b038216155b1562000c6957604051634de938d160e01b81526001600160a01b038316600482015260240162000084565b62000c7b60088361ffff841662000f40565b5062000c8c61ffff82168562002038565b9350505080600101905062000bc1565b50600e805463ffffffff60601b19166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd249062000cf8908390869062002058565b60405180910390a1505050565b6000546001600160a01b0316331462000d56576002546001600160a01b0316331462000d565762000d3860083362000f60565b62000d565760405163032bb72b60e31b815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff16600081900362000d925760405163990e30bf60e01b815260040160405180910390fd5b600e546001600160601b03168181101562000dc0576040516311a1ee3b60e31b815260040160405180910390fd5b600062000dcc62000f77565b121562000dec57604051631e9acf1760e31b815260040160405180910390fd5b80600062000dfb600862000ef1565b905060005b8181101562000ecb5760008062000e1960088462000f04565b909250905060008762000e36836001600160601b038a16620020c8565b62000e429190620020e2565b905062000e50818762002105565b60e05190965062000e75906001600160a01b0316846001600160601b03841662001005565b6040516001600160601b03821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a250505080600101905062000e00565b5050600e80546001600160601b0319166001600160601b03929092169190911790555050565b600062000efe8262001062565b92915050565b600080808062000f1586866200106f565b9097909650945050505050565b600062000f39836001600160a01b0384166200109c565b9392505050565b600062000f58846001600160a01b03851684620010bb565b949350505050565b600062000f39836001600160a01b038416620010da565b600e5460e0516040516370a0823160e01b81523060048201526000926001600160601b0316916001600160a01b0316906370a0823190602401602060405180830381865afa15801562000fce573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ff4919062002128565b62001000919062002142565b905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663a9059cbb60e01b179091526200105d918591620010e816565b505050565b600062000efe82620011b9565b600080806200107f8585620011c4565b600081815260029690960160205260409095205494959350505050565b6000818152600283016020526040812081905562000f398383620011d2565b6000828152600284016020526040812082905562000f588484620011e0565b600062000f398383620011ee565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062001137906001600160a01b03851690849062001207565b8051909150156200105d578080602001905181019062001158919062002165565b6200105d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000084565b600062000efe825490565b600062000f39838362001218565b600062000f39838362001245565b600062000f39838362001350565b6000818152600183016020526040812054151562000f39565b606062000f588484600085620013a2565b600082600001828154811062001232576200123262001e69565b9060005260206000200154905092915050565b600081815260018301602052604081205480156200133e5760006200126c60018362002008565b8554909150600090620012829060019062002008565b9050818114620012ee576000866000018281548110620012a657620012a662001e69565b9060005260206000200154905080876000018481548110620012cc57620012cc62001e69565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062001302576200130262002183565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000efe565b600091505062000efe565b5092915050565b6000818152600183016020526040812054620013995750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000efe565b50600062000efe565b606082471015620014055760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000084565b600080866001600160a01b03168587604051620014239190620021bf565b60006040518083038185875af1925050503d806000811462001462576040519150601f19603f3d011682016040523d82523d6000602084013e62001467565b606091505b5090925090506200147b8783838762001486565b979650505050505050565b60608315620014fa578251600003620014f2576001600160a01b0385163b620014f25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000084565b508162000f58565b62000f588383815115620015115781518083602001fd5b8060405162461bcd60e51b8152600401620000849190620021dd565b634e487b7160e01b600052604160045260246000fd5b6040516101c081016001600160401b03811182821017156200156957620015696200152d565b60405290565b60405160a081016001600160401b03811182821017156200156957620015696200152d565b60405160e081016001600160401b03811182821017156200156957620015696200152d565b604080519081016001600160401b03811182821017156200156957620015696200152d565b60405161010081016001600160401b03811182821017156200156957620015696200152d565b604051601f8201601f191681016001600160401b03811182821017156200162f576200162f6200152d565b604052919050565b80516001600160a01b03811681146200164f57600080fd5b919050565b80516001600160401b03811681146200164f57600080fd5b805161ffff811681146200164f57600080fd5b805163ffffffff811681146200164f57600080fd5b805180151581146200164f57600080fd5b60006101c08284031215620016b957600080fd5b620016c362001543565b9050620016d08262001637565b8152620016e0602083016200166c565b6020820152620016f3604083016200167f565b604082015262001706606083016200166c565b606082015262001719608083016200167f565b60808201526200172c60a083016200166c565b60a08201526200173f60c083016200166c565b60c08201526200175260e0830162001637565b60e0820152610100620017678184016200167f565b908201526101206200177b8382016200167f565b908201526101406200178f8382016200166c565b90820152610160620017a38382016200167f565b90820152610180620017b78382016200167f565b908201526101a0620017cb83820162001694565b9082015292915050565b80516001600160801b03811681146200164f57600080fd5b6000606082840312156200180057600080fd5b604051606081016001600160401b03811182821017156200182557620018256200152d565b604052905080620018368362001694565b81526200184660208401620017d5565b60208201526200185960408401620017d5565b60408201525092915050565b60006001600160401b038211156200188157620018816200152d565b5060051b60200190565b600082601f8301126200189d57600080fd5b81516020620018b6620018b08362001865565b62001604565b82815260a09283028501820192828201919087851115620018d657600080fd5b8387015b85811015620019635781818a031215620018f45760008081fd5b620018fe6200156f565b620019098262001637565b8152620019188683016200167f565b8682015260406200192b81840162001654565b9082015260606200193e83820162001654565b9082015260806200195183820162001694565b908201528452928401928101620018da565b5090979650505050505050565b600082601f8301126200198257600080fd5b8151602062001995620018b08362001865565b82815260e09283028501820192828201919087851115620019b557600080fd5b8387015b85811015620019635781818a031215620019d35760008081fd5b620019dd62001594565b620019e88262001637565b8152620019f78683016200167f565b86820152604062001a0a8184016200167f565b90820152606062001a1d8382016200166c565b90820152608062001a308382016200167f565b9082015260a062001a438382016200167f565b9082015260c062001a5683820162001694565b908201528452928401928101620019b9565b600082601f83011262001a7a57600080fd5b8151602062001a8d620018b08362001865565b82815260069290921b8401810191818101908684111562001aad57600080fd5b8286015b8481101562001b03576040818903121562001acc5760008081fd5b62001ad6620015b9565b62001ae18262001637565b815262001af08583016200166c565b8186015283529183019160400162001ab1565b509695505050505050565b60008060008060008086880361038081121562001b2a57600080fd5b6101008082121562001b3b57600080fd5b62001b45620015de565b915062001b528962001637565b825262001b6260208a0162001654565b602083015262001b7560408a0162001654565b604083015262001b8860608a0162001654565b606083015260808901516001600160601b038116811462001ba857600080fd5b608083015262001bbb60a08a0162001637565b60a083015262001bce60c08a0162001637565b60c083015262001be160e08a0162001637565b60e083015281975062001bf78a828b01620016a5565b9650505062001c0b886102c08901620017ed565b6103208801519094506001600160401b038082111562001c2a57600080fd5b62001c388a838b016200188b565b945061034089015191508082111562001c5057600080fd5b62001c5e8a838b0162001970565b935061036089015191508082111562001c7657600080fd5b5062001c8589828a0162001a68565b9150509295509295509295565b80516001600160a01b03168252602081015162001cb5602084018261ffff169052565b50604081015162001cce604084018263ffffffff169052565b50606081015162001ce5606084018261ffff169052565b50608081015162001cfe608084018263ffffffff169052565b5060a081015162001d1560a084018261ffff169052565b5060c081015162001d2c60c084018261ffff169052565b5060e081015162001d4860e08401826001600160a01b03169052565b506101008181015163ffffffff90811691840191909152610120808301518216908401526101408083015161ffff16908401526101608083015182169084015261018080830151909116908301526101a0908101511515910152565b82516001600160a01b031681526020808401516001600160401b0390811691830191909152604080850151821690830152606080850151918216908301526102c082019050608084015162001e0460808401826001600160601b03169052565b5060a084015162001e2060a08401826001600160a01b03169052565b5060c084015162001e3c60c08401826001600160a01b03169052565b5060e084015162001e5860e08401826001600160a01b03169052565b5062000f3961010083018462001c92565b634e487b7160e01b600052603260045260246000fd5b602080825282518282018190526000919060409081850190868401855b8281101562001f0157815180516001600160a01b031685528681015163ffffffff1687860152858101516001600160401b03908116878701526060808301519091169086015260809081015115159085015260a0909301929085019060010162001e9c565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b8281101562001f0157815180516001600160a01b031685528681015163ffffffff908116888701528682015181168787015260608083015161ffff169087015260808083015182169087015260a0808301519091169086015260c09081015115159085015260e0909301929085019060010162001f2b565b6020808252825182820181905260009190848201906040850190845b8181101562001fe65783516001600160a01b03168352928401929184019160010162001fbf565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000efe5762000efe62001ff2565b60008162002030576200203062001ff2565b506000190190565b63ffffffff81811683821601908082111562001349576200134962001ff2565b6000604080830163ffffffff8616845260206040602086015281865180845260608701915060208801935060005b81811015620020ba57845180516001600160a01b0316845284015161ffff1684840152938301939185019160010162002086565b509098975050505050505050565b808202811582820484141762000efe5762000efe62001ff2565b6000826200210057634e487b7160e01b600052601260045260246000fd5b500490565b6001600160601b0382811682821603908082111562001349576200134962001ff2565b6000602082840312156200213b57600080fd5b5051919050565b818103600083128015838313168383128216171562001349576200134962001ff2565b6000602082840312156200217857600080fd5b62000f398262001694565b634e487b7160e01b600052603160045260246000fd5b60005b83811015620021b65781810151838201526020016200219c565b50506000910152565b60008251620021d381846020870162002199565b9190910192915050565b6020815260008251806020840152620021fe81604085016020870162002199565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516101005161012051610140516101605161018051615f94620023406000396000818161036101528181610f1801526137a3015260008181610332015281816117160152613774015260008181610303015281816113cc0152818161143101528181611c8901528181611d17015261374501526000818161026f01528181610a4e0152818161183e0152818161223701528181612acf01526136b101526000818161023f01528181611de80152613681015260008181610210015281816110c30152818161164201528181611a5f01528181611b6001528181612666015281816136520152613a410152600081816102cf01528181611c2c015261371101526000818161029f015281816127c101526136e10152600061243f0152615f946000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80637437ff9f116100f9578063c92b283211610097578063eff7cc4811610071578063eff7cc48146109fc578063f25561fd14610a04578063f2fde38b14610a17578063fbca3b7414610a2a57600080fd5b8063c92b2832146109ce578063d09dc339146109e1578063df0aa9e9146109e957600080fd5b8063856c8247116100d3578063856c8247146108a05780638da5cb5b146108b35780639a113c36146108c4578063b06d41bc146109b857600080fd5b80637437ff9f146106c057806376f6ae761461088557806379ba50971461089857600080fd5b806348a98aa411610166578063549e946f11610140578063549e946f1461066957806354b714681461067c578063599f64311461069c578063704b6c02146106ad57600080fd5b806348a98aa4146105c7578063528d4a92146105f2578063546719cd1461060557600080fd5b806320487ded1161019757806320487ded146105705780634120fccd146105915780634816f4f7146105b257600080fd5b806306285c69146101be5780631772047e146103a7578063181f5a7714610527575b600080fd5b6103916040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526040518061010001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161039e9190614ba3565b60405180910390f35b6104bb6103b5366004614bd7565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152506001600160a01b03166000908152600c6020908152604091829020825160e081018452905463ffffffff8082168352640100000000820481169383019390935261ffff68010000000000000000820416938201939093526a01000000000000000000008304821660608201526e0100000000000000000000000000008304909116608082015260ff720100000000000000000000000000000000000083048116151560a0830152730100000000000000000000000000000000000000909204909116151560c082015290565b60405161039e9190600060e08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015260c0830151151560c083015292915050565b6105636040518060400160405280601781526020017f45564d3245564d4f6e52616d7020312e352e302d64657600000000000000000081525081565b60405161039e9190614c44565b61058361057e366004614c85565b610a4a565b60405190815260200161039e565b610599610ea0565b60405167ffffffffffffffff909116815260200161039e565b6105c56105c0366004614e93565b610ec7565b005b6105da6105d5366004614fd0565b610edd565b6040516001600160a01b03909116815260200161039e565b6105c5610600366004615009565b610f8c565b61060d610fa0565b60405161039e919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6105c5610677366004615119565b611032565b600e546040516bffffffffffffffffffffffff909116815260200161039e565b6002546001600160a01b03166105da565b6105c56106bb366004614bd7565b6111ab565b610878604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915250604080516101c0810182526005546001600160a01b038082168352600160a01b820461ffff9081166020850152760100000000000000000000000000000000000000000000830463ffffffff908116958501959095527a0100000000000000000000000000000000000000000000000000008304811660608501527c0100000000000000000000000000000000000000000000000000000000928390048516608085015260065480821660a086015262010000808204831660c0870152640100000000820490931660e086015278010000000000000000000000000000000000000000000000008104861661010086015292909204841661012084015260075491821661014084015281048316610160830152660100000000000081049092166101808201526a010000000000000000000090910460ff1615156101a082015290565b60405161039e9190615242565b6105c5610893366004615251565b611275565b6105c56112d8565b6105996108ae366004614bd7565b6113a1565b6000546001600160a01b03166105da565b61096e6108d2366004614bd7565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b03166000908152600b60209081526040918290208251608081018452905463ffffffff8116825267ffffffffffffffff64010000000082048116938301939093526c0100000000000000000000000081049092169281019290925260ff600160a01b909104161515606082015290565b60408051825163ffffffff16815260208084015167ffffffffffffffff9081169183019190915283830151169181019190915260609182015115159181019190915260800161039e565b6109c061149c565b60405161039e92919061531a565b6105c56109dc36600461535c565b611597565b6105836115ff565b6105836109f73660046153ca565b6116bf565b6105c56124b3565b6105c5610a12366004615436565b612738565b6105c5610a25366004614bd7565b612749565b610a3d610a38366004615535565b61275a565b60405161039e9190615552565b60007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168367ffffffffffffffff1614610aca576040517fd9a9cd6800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6000610ae1610adc608085018561559f565b61278e565b9050610b11610af3602085018561559f565b8351909150610b056040870187615604565b9050846020015161291b565b6000600b81610b266080870160608801614bd7565b6001600160a01b0316815260208082019290925260409081016000208151608081018352905463ffffffff81168252640100000000810467ffffffffffffffff908116948301949094526c01000000000000000000000000810490931691810191909152600160a01b90910460ff16151560608201819052909150610bf357610bb56080850160608601614bd7565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610ac1565b600654600090819064010000000090046001600160a01b031663ffdb4b37610c216080890160608a01614bd7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8a1660248201526044016040805180830381865afa158015610c8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb09190615698565b90925090506000808080610cc760408b018b615604565b90501115610d0157610cf5610ce260808b0160608c01614bd7565b86610cf060408d018d615604565b612a84565b91945092509050610d1d565b8551610d1a9063ffffffff16662386f26fc100006156e1565b92505b60065460009062010000900461ffff1615610d7157610d6e6dffffffffffffffffffffffffffff607087901c16610d5760208d018d61559f565b9050610d6660408e018e615604565b905085612e66565b90505b60208781015160055460009267ffffffffffffffff9092169163ffffffff8716917a010000000000000000000000000000000000000000000000000000900461ffff1690610dc1908f018f61559f565b610dcc9291506156e1565b6005548c51610dfb91760100000000000000000000000000000000000000000000900463ffffffff16906156f8565b610e0591906156f8565b610e0f91906156f8565b610e29906dffffffffffffffffffffffffffff89166156e1565b610e3391906156e1565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682828a6040015167ffffffffffffffff1688610e7091906156e1565b610e7a91906156f8565b610e8491906156f8565b610e8e919061570b565b99505050505050505050505b92915050565b600e54600090610ec290600160801b900467ffffffffffffffff16600161572d565b905090565b610ecf612f36565b610ed98282612f8e565b5050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610f61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f85919061574e565b9392505050565b610f9461330a565b610f9d81613364565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff8082168352600160801b80830463ffffffff166020850152600160a01b90920460ff161515938301939093526004548084166060840152049091166080820152610ec2906137dd565b61103a612f36565b6001600160a01b03811661107a576040517f232cb97f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110846115ff565b905060008112156110c1576040517f02075e0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036111135761110e6001600160a01b038416838361388f565b505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015261110e9083906001600160a01b038616906370a0823190602401602060405180830381865afa158015611176573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119a919061576b565b6001600160a01b038616919061388f565b6000546001600160a01b031633148015906111d157506002546001600160a01b03163314155b15611208576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c906020015b60405180910390a150565b61127d612f36565b610ed98282808060200260200160405190810160405280939291908181526020016000905b828210156112ce576112bf60408302860136819003810190615784565b815260200190600101906112a2565b505050505061390f565b6001546001600160a01b031633146113325760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610ac1565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6001600160a01b038082166000908152600d6020526040812054909167ffffffffffffffff909116907f00000000000000000000000000000000000000000000000000000000000000001615610e9a5780600003610e9a576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015611478573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8591906157c3565b60606000806114ab6008613b75565b90508067ffffffffffffffff8111156114c6576114c6614cd5565b60405190808252806020026020018201604052801561150b57816020015b60408051808201909152600080825260208201528152602001906001900390816114e45790505b50925060005b8181101561157457600080611527600884613b80565b915091506040518060400160405280836001600160a01b031681526020018261ffff1681525086848151811061155f5761155f6157e0565b60209081029190910101525050600101611511565b5050600e5491926c0100000000000000000000000090920463ffffffff16919050565b6000546001600160a01b031633148015906115bd57506002546001600160a01b03163314155b156115f4576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9d600382613b9e565b600e546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000916bffffffffffffffffffffffff16907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b5919061576b565b610ec291906157f6565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608086901b1660048201526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561175d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117819190615816565b156117b8576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382166117f8576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546001600160a01b0316331461183c576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168567ffffffffffffffff16146118b5576040517fd9a9cd6800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610ac1565b60006118c7610adc608087018761559f565b905060006118d86040870187615604565b91506118fe90506118ec602088018861559f565b9050836000015183856020015161291b565b8015611a55576000805b82811015611a435761191d6040890189615604565b8281811061192d5761192d6157e0565b90506040020160200135600003611970576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c600061198160408b018b615604565b84818110611991576119916157e0565b6119a79260206040909202019081019150614bd7565b6001600160a01b031681526020810191909152604001600020547201000000000000000000000000000000000000900460ff1615611a3b57611a2e6119ef60408a018a615604565b838181106119ff576119ff6157e0565b905060400201803603810190611a159190615833565b60065464010000000090046001600160a01b0316613d31565b611a3890836156f8565b91505b600101611908565b508015611a5357611a5381613e52565b505b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016611a8f6080880160608901614bd7565b6001600160a01b031603611af357600e8054869190600090611ac09084906bffffffffffffffffffffffff1661586d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550611c1a565b60065464010000000090046001600160a01b03166241e5be611b1b6080890160608a01614bd7565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015611ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcb919061576b565b600e8054600090611beb9084906bffffffffffffffffffffffff1661586d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b600e546bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811691161115611c87576040517fe5c7a49100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615611dd2576001600160a01b0384166000908152600d602052604081205467ffffffffffffffff169003611dd2576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015611d5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8291906157c3565b6001600160a01b0385166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790555b604080516101a08101825267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526001600160a01b03861660208201526000918101611e65611e2b8a8061559f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e5f92505050565b6001600160a01b03168152602001600e601081819054906101000a900467ffffffffffffffff16611e9590615892565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001846000015181526020016000151581526020018460200151611f3f576001600160a01b0387166000908152600d602052604081208054909190611f159067ffffffffffffffff16615892565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055611f42565b60005b67ffffffffffffffff168152602001611f6160808a0160608b01614bd7565b6001600160a01b03168152602001878152602001888060200190611f85919061559f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001611fcc60408a018a615604565b808060200260200160405190810160405280939291908181526020016000905b828210156120185761200960408302860136819003810190615833565b81526020019060010190611fec565b505050505081526020018367ffffffffffffffff81111561203b5761203b614cd5565b60405190808252806020026020018201604052801561206e57816020015b60608152602001906001900390816120595790505b508152600060209091018190529091505b8281101561243857600061209660408a018a615604565b838181106120a6576120a66157e0565b9050604002018036038101906120bc9190615833565b905060006120ce8b8360000151610edd565b90506001600160a01b038116158061218457506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561215e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121829190615816565b155b156121c95781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610ac1565b6000816001600160a01b0316639a4575b96040518060a001604052808e80600001906121f5919061559f565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020808301919091526001600160a01b03808f16604080850191909152918901516060840152885116608090920191909152517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526122c091906004016158b9565b6000604051808303816000875af11580156122df573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123079190810190615986565b9050602081602001515111156123985782516001600160a01b03166000908152600c602090815260409091205490820151516e01000000000000000000000000000090910463ffffffff1610156123985782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610ac1565b80516123a390613e5f565b5060408051606081019091526001600160a01b03831660808201528060a0810160405160208183030381529060405281526020018260000151815260200182602001518152506040516020016123f99190615a17565b604051602081830303815290604052856101600151858151811061241f5761241f6157e0565b602002602001018190525050505080600101905061207f565b50612463817f0000000000000000000000000000000000000000000000000000000000000000613f05565b6101808201526040517fd0c3c799bf9e2639de44391e7f524d229b2b55f5b1ea94b2bf7da42f7243dddd90612499908390615b0e565b60405180910390a16101800151925050505b949350505050565b6000546001600160a01b03163314612518576002546001600160a01b03163314612518576124e2600833614060565b612518576040517f195db95800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff16600081900361256c576040517f990e30bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e546bffffffffffffffffffffffff16818110156125b7576040517f8d0f71d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006125c16115ff565b12156125f9576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060006126066008613b75565b905060005b818110156126f557600080612621600884613b80565b9092509050600087612641836bffffffffffffffffffffffff8a166156e1565b61264b919061570b565b90506126578187615c43565b955061269b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016846bffffffffffffffffffffffff841661388f565b6040516bffffffffffffffffffffffff821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a250505080600101905061260b565b5050600e80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff929092169190911790555050565b612740612f36565b610f9d81614075565b61275161330a565b610f9d816141e7565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008290036127ef57506040805180820190915267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260006020820152610e9a565b60006127fb8385615c68565b90507fe7e230f0000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601612868576128538360048187615cb0565b8101906128609190615cda565b915050610e9a565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016128e95760408051808201909152806128c98560048189615cb0565b8101906128d69190615d06565b815260006020909101529150610e9a9050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006547801000000000000000000000000000000000000000000000000900463ffffffff1680851115612984576040517f869337890000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610ac1565b6006547c0100000000000000000000000000000000000000000000000000000000900463ffffffff168411156129e6576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554600160a01b900461ffff16831115612a2d576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81612a7d576007546a0100000000000000000000900460ff1615612a7d576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000808083815b81811015612e5a576000878783818110612aa757612aa76157e0565b905060400201803603810190612abd9190615833565b905060006001600160a01b0316612af87f00000000000000000000000000000000000000000000000000000000000000008360000151610edd565b6001600160a01b031603612b465780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610ac1565b80516001600160a01b03166000908152600c6020908152604091829020825160e081018452905463ffffffff8082168352640100000000820481169383019390935261ffff68010000000000000000820416938201939093526a01000000000000000000008304821660608201526e0100000000000000000000000000008304909116608082015260ff720100000000000000000000000000000000000083048116151560a0830152730100000000000000000000000000000000000000909204909116151560c08201819052612c7e57600754612c2f9061ffff16662386f26fc100006156e1565b612c3990886156f8565b600754909750612c559062010000900463ffffffff1687615d1f565b600754909650612c75906601000000000000900463ffffffff1686615d1f565b94505050612e52565b604081015160009061ffff1615612da25760008c6001600160a01b031684600001516001600160a01b031614612d455760065484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526401000000009092041690634ab35b0b90602401602060405180830381865afa158015612d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3e9190615d3c565b9050612d48565b508a5b620186a0836040015161ffff16612d8a8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166142a890919063ffffffff16565b612d9491906156e1565b612d9e919061570b565b9150505b6060820151612db19088615d1f565b9650816080015186612dc39190615d1f565b8251909650600090612de29063ffffffff16662386f26fc100006156e1565b905080821015612e0157612df6818a6156f8565b985050505050612e52565b6000836020015163ffffffff16662386f26fc10000612e2091906156e1565b905080831115612e4057612e34818b6156f8565b99505050505050612e52565b612e4a838b6156f8565b995050505050505b600101612a8b565b50509450945094915050565b60008063ffffffff8316612e7b6080866156e1565b612e87876102206156f8565b612e9191906156f8565b612e9b91906156f8565b6005546006549192506000917c010000000000000000000000000000000000000000000000000000000090910463ffffffff1690612edd9061ffff16846156e1565b612ee791906156f8565b60065490915062010000900461ffff16612f116dffffffffffffffffffffffffffff8916836156e1565b612f1b91906156e1565b612f2b90655af3107a40006156e1565b979650505050505050565b6000546001600160a01b03163314612f8c576002546001600160a01b03163314612f8c576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60005b825181101561321c576000838281518110612fae57612fae6157e0565b6020026020010151905060208160a0015163ffffffff16101561301b57805160a08201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b03909216600483015263ffffffff166024820152604401610ac1565b6040805160e08101825260208381015163ffffffff908116835284840151811682840190815260608087015161ffff9081168688019081526080808a0151861693880193845260a0808b0151871691890191825260c0808c01511515918a019182526001908a018181529b516001600160a01b03166000908152600c9099529990972097518854955192519451915197519a519087167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009096169590951764010000000092871692909202919091177fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff166801000000000000000093909216929092027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff16176a010000000000000000000091841691909102177fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff166e01000000000000000000000000000093909216929092027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1617720100000000000000000000000000000000000094151594909402939093177fffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffff16730100000000000000000000000000000000000000931515939093029290921790915501612f91565b507ff5791bc457b3bb990493cf5f655db46c25ccf5764c9b99b8969b4c72ea7df9d08260405161324c9190615d57565b60405180910390a160005b81518110156132c757600c6000838381518110613276576132766157e0565b6020908102919091018101516001600160a01b0316825281019190915260400160002080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600101613257565b50805115610ed9577ffb95a0042158e60a33e7b5bec100f3d95407b1a71bee6633bd54b8887449750b816040516132fe9190615552565b60405180910390a15050565b6000546001600160a01b03163314612f8c5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610ac1565b60e08101516001600160a01b03166133a8576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081610180015163ffffffff161015613404576101808101516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610ac1565b80600560008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601a6101000a81548161ffff021916908361ffff160217905550608082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548161ffff021916908361ffff16021790555060c08201518160010160026101000a81548161ffff021916908361ffff16021790555060e08201518160010160046101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555061012082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160006101000a81548161ffff021916908361ffff1602179055506101608201518160020160026101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160020160066101000a81548163ffffffff021916908363ffffffff1602179055506101a082015181600201600a6101000a81548160ff0219169083151502179055509050507fe375c8cb6ea9807cd0371503b632b93da5ee0f1f64205db8b5b28b95d6b588b06040518061010001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152508260405161126a929190615df7565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261386b82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261384f9190615e14565b85608001516fffffffffffffffffffffffffffffffff166142e5565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261110e90849061430d565b8051604081111561394c576040517fb5a10cfa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff16156139a057600e5463ffffffff6c010000000000000000000000008204166bffffffffffffffffffffffff909116106139a0576139a06124b3565b60006139ac6008613b75565b90505b80156139ee5760006139cd6139c5600184615e14565b600890613b80565b5090506139db6008826143f2565b5050806139e790615e27565b90506139af565b506000805b82811015613af6576000848281518110613a0f57613a0f6157e0565b60200260200101516000015190506000858381518110613a3157613a316157e0565b60200260200101516020015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161480613a8657506001600160a01b038216155b15613ac8576040517f4de938d10000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610ac1565b613ad860088361ffff8416614407565b50613ae761ffff821685615d1f565b935050508060010190506139f3565b50600e80547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd2490613b689083908690615e5c565b60405180910390a1505050565b6000610e9a8261441d565b6000808080613b8f8686614428565b909450925050505b9250929050565b8154600090613bba90600160801b900463ffffffff1642615e14565b90508015613c425760018301548354613bf5916fffffffffffffffffffffffffffffffff808216928116918591600160801b909104166142e5565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617600160801b4263ffffffff16021783555b60208201518354613c68916fffffffffffffffffffffffffffffffff9081169116614453565b835483511515600160a01b027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff9283161717845560208301516040808501518316600160801b0291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990613b689084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b81516040517fd02641a00000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260009182919084169063d02641a0906024016040805180830381865afa158015613d97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dbb9190615e7b565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116600003613e245783516040517f9a655f7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610ac1565b60208401516124ab907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316906142a8565b610f9d6003826000614469565b60008151602014613e9e57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ac19190614c44565b600082806020019051810190613eb4919061576b565b90506001600160a01b03811180613ecc575061040081105b15610e9a57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ac19190614c44565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001613f9b9897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b6040516020818303038152906040528051906020012085610120015180519060200120866101400151604051602001613fd49190615eae565b604051602081830303815290604052805190602001208761016001516040516020016140009190615ec1565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6000610f85836001600160a01b038416614773565b60005b81518110156141b7576000828281518110614095576140956157e0565b60209081029190910181015160408051608080820183528385015163ffffffff90811683528385015167ffffffffffffffff908116848801908152606080880151831686880190815294880151151590860190815296516001600160a01b03166000908152600b90985294909620925183549451925195511515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9688166c0100000000000000000000000002969096167fffffffffffffffffffffff000000000000000000ffffffffffffffffffffffff93909716640100000000027fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090951691161792909217919091169290921717905550600101614078565b507f067924bf9277d905a9a4631a06d959bc032ace86b3caa835ae7e403d4f39010e8160405161126a9190615ed4565b336001600160a01b0382160361423f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610ac1565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a76400006142db837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166156e1565b610f85919061570b565b6000614304856142f584866156e1565b6142ff90876156f8565b614453565b95945050505050565b6000614362826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661477f9092919063ffffffff16565b80519091501561110e57808060200190518101906143809190615816565b61110e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610ac1565b6000610f85836001600160a01b03841661478e565b60006124ab846001600160a01b038516846147ab565b6000610e9a826147c8565b6000808061443685856147d2565b600081815260029690960160205260409095205494959350505050565b60008183106144625781610f85565b5090919050565b8254600160a01b900460ff16158061447f575081155b1561448957505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906144c290600160801b900463ffffffff1642615e14565b905080156145685781831115614504576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600186015461453190839085908490600160801b90046fffffffffffffffffffffffffffffffff166142e5565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff16600160801b4263ffffffff160217875592505b84821015614605576001600160a01b0384166145ba576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610ac1565b6040517f1a76572a00000000000000000000000000000000000000000000000000000000815260048101839052602481018690526001600160a01b0385166044820152606401610ac1565b848310156146f157600186810154600160801b90046fffffffffffffffffffffffffffffffff1690600090829061463c9082615e14565b614646878a615e14565b61465091906156f8565b61465a919061570b565b90506001600160a01b0386166146a6576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610ac1565b6040517fd0c8d23a00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526001600160a01b0387166044820152606401610ac1565b6146fb8584615e14565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000610f8583836147de565b60606124ab84846000856147f6565b60008181526002830160205260408120819055610f8583836148dd565b600082815260028401602052604081208290556124ab84846148e9565b6000610e9a825490565b6000610f8583836148f5565b60008181526001830160205260408120541515610f85565b60608247101561486e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610ac1565b600080866001600160a01b0316858760405161488a9190615f55565b60006040518083038185875af1925050503d80600081146148c7576040519150601f19603f3d011682016040523d82523d6000602084013e6148cc565b606091505b5091509150612f2b8783838761491f565b6000610f858383614998565b6000610f858383614a92565b600082600001828154811061490c5761490c6157e0565b9060005260206000200154905092915050565b6060831561498e578251600003614987576001600160a01b0385163b6149875760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ac1565b50816124ab565b6124ab8383614ae1565b60008181526001830160205260408120548015614a815760006149bc600183615e14565b85549091506000906149d090600190615e14565b9050818114614a355760008660000182815481106149f0576149f06157e0565b9060005260206000200154905080876000018481548110614a1357614a136157e0565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614a4657614a46615f71565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610e9a565b6000915050610e9a565b5092915050565b6000818152600183016020526040812054614ad957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610e9a565b506000610e9a565b815115614af15781518083602001fd5b8060405162461bcd60e51b8152600401610ac19190614c44565b6001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015280606085015116606086015250506bffffffffffffffffffffffff60808301511660808401528060a08301511660a08401525060c0810151614b8860c08401826001600160a01b03169052565b5060e081015161110e60e08401826001600160a01b03169052565b6101008101610e9a8284614b0b565b6001600160a01b0381168114610f9d57600080fd5b8035614bd281614bb2565b919050565b600060208284031215614be957600080fd5b8135610f8581614bb2565b60005b83811015614c0f578181015183820152602001614bf7565b50506000910152565b60008151808452614c30816020860160208601614bf4565b601f01601f19169290920160200192915050565b602081526000610f856020830184614c18565b67ffffffffffffffff81168114610f9d57600080fd5b600060a08284031215614c7f57600080fd5b50919050565b60008060408385031215614c9857600080fd5b8235614ca381614c57565b9150602083013567ffffffffffffffff811115614cbf57600080fd5b614ccb85828601614c6d565b9150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff81118282101715614d0e57614d0e614cd5565b60405290565b6040516101c0810167ffffffffffffffff81118282101715614d0e57614d0e614cd5565b60405160a0810167ffffffffffffffff81118282101715614d0e57614d0e614cd5565b6040805190810167ffffffffffffffff81118282101715614d0e57614d0e614cd5565b604051601f8201601f1916810167ffffffffffffffff81118282101715614da757614da7614cd5565b604052919050565b600067ffffffffffffffff821115614dc957614dc9614cd5565b5060051b60200190565b63ffffffff81168114610f9d57600080fd5b8035614bd281614dd3565b803561ffff81168114614bd257600080fd5b8015158114610f9d57600080fd5b8035614bd281614e02565b600082601f830112614e2c57600080fd5b81356020614e41614e3c83614daf565b614d7e565b8083825260208201915060208460051b870101935086841115614e6357600080fd5b602086015b84811015614e88578035614e7b81614bb2565b8352918301918301614e68565b509695505050505050565b6000806040808486031215614ea757600080fd5b833567ffffffffffffffff80821115614ebf57600080fd5b818601915086601f830112614ed357600080fd5b81356020614ee3614e3c83614daf565b82815260e0928302850182019282820191908b851115614f0257600080fd5b958301955b84871015614fab5780878d031215614f1f5760008081fd5b614f27614ceb565b8735614f3281614bb2565b815287850135614f4181614dd3565b8186015287890135614f5281614dd3565b818a01526060614f63898201614df0565b90820152608088810135614f7681614dd3565b9082015260a0614f87898201614de5565b9082015260c0614f98898201614e10565b9082015283529586019591830191614f07565b5097505087013593505080831115614fc257600080fd5b5050614ccb85828601614e1b565b60008060408385031215614fe357600080fd5b8235614fee81614c57565b91506020830135614ffe81614bb2565b809150509250929050565b60006101c0828403121561501c57600080fd5b615024614d14565b61502d83614bc7565b815261503b60208401614df0565b602082015261504c60408401614de5565b604082015261505d60608401614df0565b606082015261506e60808401614de5565b608082015261507f60a08401614df0565b60a082015261509060c08401614df0565b60c08201526150a160e08401614bc7565b60e08201526101006150b4818501614de5565b908201526101206150c6848201614de5565b908201526101406150d8848201614df0565b908201526101606150ea848201614de5565b908201526101806150fc848201614de5565b908201526101a061510e848201614e10565b908201529392505050565b6000806040838503121561512c57600080fd5b8235614fee81614bb2565b80516001600160a01b031682526020810151615159602084018261ffff169052565b506040810151615171604084018263ffffffff169052565b506060810151615187606084018261ffff169052565b50608081015161519f608084018263ffffffff169052565b5060a08101516151b560a084018261ffff169052565b5060c08101516151cb60c084018261ffff169052565b5060e08101516151e660e08401826001600160a01b03169052565b506101008181015163ffffffff90811691840191909152610120808301518216908401526101408083015161ffff16908401526101608083015182169084015261018080830151909116908301526101a0908101511515910152565b6101c08101610e9a8284615137565b6000806020838503121561526457600080fd5b823567ffffffffffffffff8082111561527c57600080fd5b818501915085601f83011261529057600080fd5b81358181111561529f57600080fd5b8660208260061b85010111156152b457600080fd5b60209290920196919550909350505050565b60008151808452602080850194506020840160005b8381101561530f57815180516001600160a01b0316885283015161ffff1683880152604090960195908201906001016152db565b509495945050505050565b60408152600061532d60408301856152c6565b90508260208301529392505050565b80356fffffffffffffffffffffffffffffffff81168114614bd257600080fd5b60006060828403121561536e57600080fd5b6040516060810181811067ffffffffffffffff8211171561539157615391614cd5565b604052823561539f81614e02565b81526153ad6020840161533c565b60208201526153be6040840161533c565b60408201529392505050565b600080600080608085870312156153e057600080fd5b84356153eb81614c57565b9350602085013567ffffffffffffffff81111561540757600080fd5b61541387828801614c6d565b93505060408501359150606085013561542b81614bb2565b939692955090935050565b6000602080838503121561544957600080fd5b823567ffffffffffffffff81111561546057600080fd5b8301601f8101851361547157600080fd5b803561547f614e3c82614daf565b81815260a0918202830184019184820191908884111561549e57600080fd5b938501935b838510156155295780858a0312156154bb5760008081fd5b6154c3614d38565b85356154ce81614bb2565b8152858701356154dd81614dd3565b818801526040868101356154f081614c57565b9082015260608681013561550381614c57565b9082015260808681013561551681614e02565b90820152835293840193918501916154a3565b50979650505050505050565b60006020828403121561554757600080fd5b8135610f8581614c57565b6020808252825182820181905260009190848201906040850190845b818110156155935783516001600160a01b03168352928401929184019160010161556e565b50909695505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126155d457600080fd5b83018035915067ffffffffffffffff8211156155ef57600080fd5b602001915036819003821315613b9757600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261563957600080fd5b83018035915067ffffffffffffffff82111561565457600080fd5b6020019150600681901b3603821315613b9757600080fd5b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168114614bd257600080fd5b600080604083850312156156ab57600080fd5b6156b48361566c565b91506156c26020840161566c565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610e9a57610e9a6156cb565b80820180821115610e9a57610e9a6156cb565b60008261572857634e487b7160e01b600052601260045260246000fd5b500490565b67ffffffffffffffff818116838216019080821115614a8b57614a8b6156cb565b60006020828403121561576057600080fd5b8151610f8581614bb2565b60006020828403121561577d57600080fd5b5051919050565b60006040828403121561579657600080fd5b61579e614d5b565b82356157a981614bb2565b81526157b760208401614df0565b60208201529392505050565b6000602082840312156157d557600080fd5b8151610f8581614c57565b634e487b7160e01b600052603260045260246000fd5b8181036000831280158383131683831282161715614a8b57614a8b6156cb565b60006020828403121561582857600080fd5b8151610f8581614e02565b60006040828403121561584557600080fd5b61584d614d5b565b823561585881614bb2565b81526020928301359281019290925250919050565b6bffffffffffffffffffffffff818116838216019080821115614a8b57614a8b6156cb565b600067ffffffffffffffff8083168181036158af576158af6156cb565b6001019392505050565b602081526000825160a060208401526158d560c0840182614c18565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f83011261593357600080fd5b815167ffffffffffffffff81111561594d5761594d614cd5565b6159606020601f19601f84011601614d7e565b81815284602083860101111561597557600080fd5b6124ab826020830160208701614bf4565b60006020828403121561599857600080fd5b815167ffffffffffffffff808211156159b057600080fd5b90830190604082860312156159c457600080fd5b6159cc614d5b565b8251828111156159db57600080fd5b6159e787828601615922565b8252506020830151828111156159fc57600080fd5b615a0887828601615922565b60208301525095945050505050565b602081526000825160606020840152615a336080840182614c18565b90506020840151601f1980858403016040860152615a518383614c18565b92506040860151915080858403016060860152506143048282614c18565b60008151808452602080850194506020840160005b8381101561530f57815180516001600160a01b031688528301518388015260409096019590820190600101615a84565b60008282518085526020808601955060208260051b8401016020860160005b84811015615b0157601f19868403018952615aef838351614c18565b98840198925090830190600101615ad3565b5090979650505050505050565b60208152615b2960208201835167ffffffffffffffff169052565b60006020830151615b4560408401826001600160a01b03169052565b5060408301516001600160a01b038116606084015250606083015167ffffffffffffffff8116608084015250608083015160a083015260a0830151615b8e60c084018215159052565b5060c083015167ffffffffffffffff811660e08401525060e0830151610100615bc1818501836001600160a01b03169052565b840151610120848101919091528401516101a061014080860182905291925090615bef6101c0860184614c18565b9250808601519050601f19610160818786030181880152615c108584615a6f565b945080880151925050610180818786030181880152615c2f8584615ab4565b970151959092019490945250929392505050565b6bffffffffffffffffffffffff828116828216039080821115614a8b57614a8b6156cb565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015615ca85780818660040360031b1b83161692505b505092915050565b60008085851115615cc057600080fd5b83861115615ccd57600080fd5b5050820193919092039150565b600060408284031215615cec57600080fd5b615cf4614d5b565b8235815260208301356157b781614e02565b600060208284031215615d1857600080fd5b5035919050565b63ffffffff818116838216019080821115614a8b57614a8b6156cb565b600060208284031215615d4e57600080fd5b610f858261566c565b602080825282518282018190526000919060409081850190868401855b82811015615dea57815180516001600160a01b031685528681015163ffffffff908116888701528682015181168787015260608083015161ffff169087015260808083015182169087015260a0808301519091169086015260c09081015115159085015260e09093019290850190600101615d74565b5091979650505050505050565b6102c08101615e068285614b0b565b610f85610100830184615137565b81810381811115610e9a57610e9a6156cb565b600081615e3657615e366156cb565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b63ffffffff831681526040602082015260006124ab60408301846152c6565b600060408284031215615e8d57600080fd5b615e95614d5b565b615e9e8361566c565b815260208301516157b781614dd3565b602081526000610f856020830184615a6f565b602081526000610f856020830184615ab4565b602080825282518282018190526000919060409081850190868401855b82811015615dea57815180516001600160a01b031685528681015163ffffffff16878601528581015167ffffffffffffffff908116878701526060808301519091169086015260809081015115159085015260a09093019290850190600101615ef1565b60008251615f67818460208701614bf4565b9190910192915050565b634e487b7160e01b600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"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\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"}],\"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\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidChainSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"nop\",\"type\":\"address\"}],\"name\":\"InvalidNopAddress\",\"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\":[{\"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\":[{\"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\":\"address\",\"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\":\"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\":[{\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"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\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"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\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"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\"},{\"internalType\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"transferFeeConfig\",\"type\":\"tuple[]\"}],\"name\":\"TokenTransferFeeConfigSet\",\"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\":[],\"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\":[{\"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\":[],\"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\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"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\":[{\"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\":\"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\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"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\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMOnRamp.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\":\"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\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"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\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"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\":\"bool\",\"name\":\"aggregateRateLimitEnabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"internalType\":\"address[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"address[]\"}],\"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\"}]", + Bin: "0x6101a06040523480156200001257600080fd5b506040516200822d3803806200822d833981016040819052620000359162001a93565b8333806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c0816200030b565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606086018190529790950151166080909301839052600380546001600160a01b031916909417600160801b9283021760ff60a01b1916600160a01b90910217909255029091176004555085516001600160a01b0316158062000169575060208601516001600160401b0316155b8062000180575060408601516001600160401b0316155b8062000197575060608601516001600160401b0316155b80620001ae575060c08601516001600160a01b0316155b80620001c5575060e08601516001600160a01b0316155b15620001e4576040516306b7c75960e31b815260040160405180910390fd5b60208087015160408089015181517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3948101949094526001600160401b039283169184019190915216606082015230608082015260a00160408051601f198184030181529181528151602092830120608090815288516001600160a01b0390811660e0908152938a01516001600160401b0390811661010052928a015183166101205260608a015190921660a0908152908901516001600160601b031660c090815290890151821661014052880151811661016052908701511661018052620002cd85620003b6565b620002d883620006ad565b604080516000815260208101909152620002f4908390620007dd565b620002ff8162000a83565b5050505050506200218a565b336001600160a01b03821603620003655760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e08101516001600160a01b0316620003e2576040516306b7c75960e31b815260040160405180910390fd5b80600560008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601a6101000a81548161ffff021916908361ffff160217905550608082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548161ffff021916908361ffff16021790555060c08201518160010160026101000a81548161ffff021916908361ffff16021790555060e08201518160010160046101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555061012082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160006101000a81548161ffff021916908361ffff1602179055506101608201518160020160026101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160020160066101000a81548160ff0219169083151502179055509050507f45b5ad483aa608464c2c7f278bd413d284d7790cdc836e40652e23a02770822060405180610100016040528060e0516001600160a01b03168152602001610100516001600160401b03168152602001610120516001600160401b0316815260200160a0516001600160401b0316815260200160c0516001600160601b03168152602001610140516001600160a01b03168152602001610160516001600160a01b03168152602001610180516001600160a01b031681525082604051620006a292919062001d1c565b60405180910390a150565b60005b8151811015620007ab576000828281518110620006d157620006d162001de1565b60209081029190910181015160408051608080820183528385015163ffffffff9081168352838501516001600160401b03908116848801908152606080880151831686880190815294880151151590860190815296516001600160a01b03166000908152600b90985294909620925183549451925195511515600160a01b0260ff60a01b199688166c010000000000000000000000000296909616600160601b600160a81b031993909716640100000000026001600160601b031990951691161792909217919091169290921717905550600101620006b0565b507f067924bf9277d905a9a4631a06d959bc032ace86b3caa835ae7e403d4f39010e81604051620006a2919062001df7565b60005b8251811015620009a257600083828151811062000801576200080162001de1565b60200260200101519050602063ffffffff168160a0015163ffffffff1610156200085d57805160a08201516040516312766e0160e11b81526001600160a01b03909216600483015263ffffffff16602482015260440162000084565b6040805160e08101825260208381015163ffffffff908116835284840151811682840190815260608087015161ffff9081168688019081526080808a0151861693880193845260a0808b0151871691890191825260c0808c01511515918a019182526001908a018181529b516001600160a01b03166000908152600c9099529990972097518854955192519451915197519a519087166001600160401b031990961695909517640100000000928716929092029190911765ffffffffffff60401b191668010000000000000000939092169290920263ffffffff60501b1916176a0100000000000000000000918416919091021764ffffffffff60701b1916600160701b939092169290920260ff60901b191617600160901b941515949094029390931760ff60981b1916600160981b931515939093029290921790915501620007e0565b507ff5791bc457b3bb990493cf5f655db46c25ccf5764c9b99b8969b4c72ea7df9d082604051620009d4919062001e86565b60405180910390a160005b815181101562000a3c57600c600083838151811062000a025762000a0262001de1565b6020908102919091018101516001600160a01b0316825281019190915260400160002080546001600160a01b0319169055600101620009df565b5080511562000a7f577ffb95a0042158e60a33e7b5bec100f3d95407b1a71bee6633bd54b8887449750b8160405162000a76919062001f1b565b60405180910390a15b5050565b8051604081111562000aa857604051635ad0867d60e11b815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff161562000afb57600e5463ffffffff6c010000000000000000000000008204166001600160601b039091161062000afb5762000afb62000c9e565b600062000b09600862000e8a565b90505b801562000b5557600062000b2f62000b2660018462001f80565b60089062000e9d565b50905062000b3f60088262000ebb565b50508062000b4d9062001f96565b905062000b0c565b506000805b8281101562000c3557600084828151811062000b7a5762000b7a62001de1565b6020026020010151600001519050600085838151811062000b9f5762000b9f62001de1565b602002602001015160200151905060e0516001600160a01b0316826001600160a01b0316148062000bd757506001600160a01b038216155b1562000c0257604051634de938d160e01b81526001600160a01b038316600482015260240162000084565b62000c1460088361ffff841662000ed9565b5062000c2561ffff82168562001fb0565b9350505080600101905062000b5a565b50600e805463ffffffff60601b19166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd249062000c91908390869062001fd0565b60405180910390a1505050565b6000546001600160a01b0316331462000cef576002546001600160a01b0316331462000cef5762000cd160083362000ef9565b62000cef5760405163032bb72b60e31b815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff16600081900362000d2b5760405163990e30bf60e01b815260040160405180910390fd5b600e546001600160601b03168181101562000d59576040516311a1ee3b60e31b815260040160405180910390fd5b600062000d6562000f10565b121562000d8557604051631e9acf1760e31b815260040160405180910390fd5b80600062000d94600862000e8a565b905060005b8181101562000e645760008062000db260088462000e9d565b909250905060008762000dcf836001600160601b038a1662002040565b62000ddb91906200205a565b905062000de981876200207d565b60e05190965062000e0e906001600160a01b0316846001600160601b03841662000f9e565b6040516001600160601b03821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a250505080600101905062000d99565b5050600e80546001600160601b0319166001600160601b03929092169190911790555050565b600062000e978262000ffb565b92915050565b600080808062000eae868662001008565b9097909650945050505050565b600062000ed2836001600160a01b03841662001035565b9392505050565b600062000ef1846001600160a01b0385168462001054565b949350505050565b600062000ed2836001600160a01b03841662001073565b600e5460e0516040516370a0823160e01b81523060048201526000926001600160601b0316916001600160a01b0316906370a0823190602401602060405180830381865afa15801562000f67573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f8d9190620020a0565b62000f999190620020ba565b905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663a9059cbb60e01b1790915262000ff69185916200108116565b505050565b600062000e978262001152565b600080806200101885856200115d565b600081815260029690960160205260409095205494959350505050565b6000818152600283016020526040812081905562000ed283836200116b565b6000828152600284016020526040812082905562000ef1848462001179565b600062000ed2838362001187565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620010d0906001600160a01b038516908490620011a0565b80519091501562000ff65780806020019051810190620010f19190620020dd565b62000ff65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000084565b600062000e97825490565b600062000ed28383620011b1565b600062000ed28383620011de565b600062000ed28383620012e9565b6000818152600183016020526040812054151562000ed2565b606062000ef184846000856200133b565b6000826000018281548110620011cb57620011cb62001de1565b9060005260206000200154905092915050565b60008181526001830160205260408120548015620012d75760006200120560018362001f80565b85549091506000906200121b9060019062001f80565b9050808214620012875760008660000182815481106200123f576200123f62001de1565b906000526020600020015490508087600001848154811062001265576200126562001de1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200129b576200129b620020fb565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e97565b600091505062000e97565b5092915050565b6000818152600183016020526040812054620013325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e97565b50600062000e97565b6060824710156200139e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000084565b600080866001600160a01b03168587604051620013bc919062002137565b60006040518083038185875af1925050503d8060008114620013fb576040519150601f19603f3d011682016040523d82523d6000602084013e62001400565b606091505b50909250905062001414878383876200141f565b979650505050505050565b60608315620014935782516000036200148b576001600160a01b0385163b6200148b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000084565b508162000ef1565b62000ef18383815115620014aa5781518083602001fd5b8060405162461bcd60e51b815260040162000084919062002155565b634e487b7160e01b600052604160045260246000fd5b6040516101a081016001600160401b0381118282101715620015025762001502620014c6565b60405290565b60405160a081016001600160401b0381118282101715620015025762001502620014c6565b60405160e081016001600160401b0381118282101715620015025762001502620014c6565b604080519081016001600160401b0381118282101715620015025762001502620014c6565b60405161010081016001600160401b0381118282101715620015025762001502620014c6565b604051601f8201601f191681016001600160401b0381118282101715620015c857620015c8620014c6565b604052919050565b80516001600160a01b0381168114620015e857600080fd5b919050565b80516001600160401b0381168114620015e857600080fd5b805161ffff81168114620015e857600080fd5b805163ffffffff81168114620015e857600080fd5b80518015158114620015e857600080fd5b60006101a082840312156200165257600080fd5b6200165c620014dc565b90506200166982620015d0565b8152620016796020830162001605565b60208201526200168c6040830162001618565b60408201526200169f6060830162001605565b6060820152620016b26080830162001618565b6080820152620016c560a0830162001605565b60a0820152620016d860c0830162001605565b60c0820152620016eb60e08301620015d0565b60e08201526101006200170081840162001618565b908201526101206200171483820162001618565b908201526101406200172883820162001605565b908201526101606200173c83820162001618565b90820152610180620017508382016200162d565b9082015292915050565b80516001600160801b0381168114620015e857600080fd5b6000606082840312156200178557600080fd5b604051606081016001600160401b0381118282101715620017aa57620017aa620014c6565b604052905080620017bb836200162d565b8152620017cb602084016200175a565b6020820152620017de604084016200175a565b60408201525092915050565b60006001600160401b03821115620018065762001806620014c6565b5060051b60200190565b600082601f8301126200182257600080fd5b815160206200183b6200183583620017ea565b6200159d565b82815260a092830285018201928282019190878511156200185b57600080fd5b8387015b85811015620018e85781818a031215620018795760008081fd5b6200188362001508565b6200188e82620015d0565b81526200189d86830162001618565b868201526040620018b0818401620015ed565b908201526060620018c3838201620015ed565b908201526080620018d68382016200162d565b9082015284529284019281016200185f565b5090979650505050505050565b600082601f8301126200190757600080fd5b815160206200191a6200183583620017ea565b82815260e092830285018201928282019190878511156200193a57600080fd5b8387015b85811015620018e85781818a031215620019585760008081fd5b620019626200152d565b6200196d82620015d0565b81526200197c86830162001618565b8682015260406200198f81840162001618565b908201526060620019a283820162001605565b908201526080620019b583820162001618565b9082015260a0620019c883820162001618565b9082015260c0620019db8382016200162d565b9082015284529284019281016200193e565b600082601f830112620019ff57600080fd5b8151602062001a126200183583620017ea565b82815260069290921b8401810191818101908684111562001a3257600080fd5b8286015b8481101562001a88576040818903121562001a515760008081fd5b62001a5b62001552565b62001a6682620015d0565b815262001a7585830162001605565b8186015283529183019160400162001a36565b509695505050505050565b60008060008060008086880361036081121562001aaf57600080fd5b6101008082121562001ac057600080fd5b62001aca62001577565b915062001ad789620015d0565b825262001ae760208a01620015ed565b602083015262001afa60408a01620015ed565b604083015262001b0d60608a01620015ed565b606083015260808901516001600160601b038116811462001b2d57600080fd5b608083015262001b4060a08a01620015d0565b60a083015262001b5360c08a01620015d0565b60c083015262001b6660e08a01620015d0565b60e083015281975062001b7c8a828b016200163e565b9650505062001b90886102a0890162001772565b6103008801519094506001600160401b038082111562001baf57600080fd5b62001bbd8a838b0162001810565b945061032089015191508082111562001bd557600080fd5b62001be38a838b01620018f5565b935061034089015191508082111562001bfb57600080fd5b5062001c0a89828a01620019ed565b9150509295509295509295565b80516001600160a01b03168252602081015162001c3a602084018261ffff169052565b50604081015162001c53604084018263ffffffff169052565b50606081015162001c6a606084018261ffff169052565b50608081015162001c83608084018263ffffffff169052565b5060a081015162001c9a60a084018261ffff169052565b5060c081015162001cb160c084018261ffff169052565b5060e081015162001ccd60e08401826001600160a01b03169052565b506101008181015163ffffffff90811691840191909152610120808301518216908401526101408083015161ffff16908401526101608083015190911690830152610180908101511515910152565b82516001600160a01b031681526020808401516001600160401b0390811691830191909152604080850151821690830152606080850151918216908301526102a082019050608084015162001d7c60808401826001600160601b03169052565b5060a084015162001d9860a08401826001600160a01b03169052565b5060c084015162001db460c08401826001600160a01b03169052565b5060e084015162001dd060e08401826001600160a01b03169052565b5062000ed261010083018462001c17565b634e487b7160e01b600052603260045260246000fd5b602080825282518282018190526000919060409081850190868401855b8281101562001e7957815180516001600160a01b031685528681015163ffffffff1687860152858101516001600160401b03908116878701526060808301519091169086015260809081015115159085015260a0909301929085019060010162001e14565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b8281101562001e7957815180516001600160a01b031685528681015163ffffffff908116888701528682015181168787015260608083015161ffff169087015260808083015182169087015260a0808301519091169086015260c09081015115159085015260e0909301929085019060010162001ea3565b6020808252825182820181905260009190848201906040850190845b8181101562001f5e5783516001600160a01b03168352928401929184019160010162001f37565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000e975762000e9762001f6a565b60008162001fa85762001fa862001f6a565b506000190190565b63ffffffff818116838216019080821115620012e257620012e262001f6a565b6000604080830163ffffffff8616845260206040602086015281865180845260608701915060208801935060005b818110156200203257845180516001600160a01b0316845284015161ffff1684840152938301939185019160010162001ffe565b509098975050505050505050565b808202811582820484141762000e975762000e9762001f6a565b6000826200207857634e487b7160e01b600052601260045260246000fd5b500490565b6001600160601b03828116828216039080821115620012e257620012e262001f6a565b600060208284031215620020b357600080fd5b5051919050565b8181036000831280158383131683831282161715620012e257620012e262001f6a565b600060208284031215620020f057600080fd5b62000ed2826200162d565b634e487b7160e01b600052603160045260246000fd5b60005b838110156200212e57818101518382015260200162002114565b50506000910152565b600082516200214b81846020870162002111565b9190910192915050565b60208152600082518060208401526200217681604085016020870162002111565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516101005161012051610140516101605161018051615f75620022b86000396000818161036101528181610efa0152613786015260008181610332015281816116f80152613757015260008181610303015281816113ae0152818161141301528181611c7401528181611d02015261372801526000818161026f01528181610a30015281816118200152818161222201528181612b42015261369401526000818161023f01528181611dd30152613664015260008181610210015281816110a50152818161162401528181611a4101528181611b42015281816126dd015281816136350152613a240152600081816102cf01528181611c0e01526136f401526000818161029f0152818161283801526136c4015260006124b60152615f756000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80637437ff9f116100f9578063c92b283211610097578063eff7cc4811610071578063eff7cc48146109de578063f25561fd146109e6578063f2fde38b146109f9578063fbca3b7414610a0c57600080fd5b8063c92b2832146109b0578063d09dc339146109c3578063df0aa9e9146109cb57600080fd5b8063856c8247116100d3578063856c8247146108825780638da5cb5b146108955780639a113c36146108a6578063b06d41bc1461099a57600080fd5b80637437ff9f146106c057806376f6ae761461086757806379ba50971461087a57600080fd5b806348a98aa411610166578063549e946f11610140578063549e946f1461066957806354b714681461067c578063599f64311461069c578063704b6c02146106ad57600080fd5b806348a98aa4146105c7578063504bffe0146105f2578063546719cd1461060557600080fd5b806320487ded1161019757806320487ded146105705780634120fccd146105915780634816f4f7146105b257600080fd5b806306285c69146101be5780631772047e146103a7578063181f5a7714610527575b600080fd5b6103916040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526040518061010001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161039e9190614b86565b60405180910390f35b6104bb6103b5366004614bba565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152506001600160a01b03166000908152600c6020908152604091829020825160e081018452905463ffffffff8082168352640100000000820481169383019390935261ffff68010000000000000000820416938201939093526a01000000000000000000008304821660608201526e0100000000000000000000000000008304909116608082015260ff720100000000000000000000000000000000000083048116151560a0830152730100000000000000000000000000000000000000909204909116151560c082015290565b60405161039e9190600060e08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015260c0830151151560c083015292915050565b6105636040518060400160405280601381526020017f45564d3245564d4f6e52616d7020312e352e300000000000000000000000000081525081565b60405161039e9190614c27565b61058361057e366004614c68565b610a2c565b60405190815260200161039e565b610599610e82565b60405167ffffffffffffffff909116815260200161039e565b6105c56105c0366004614e76565b610ea9565b005b6105da6105d5366004614fb3565b610ebf565b6040516001600160a01b03909116815260200161039e565b6105c5610600366004614fec565b610f6e565b61060d610f82565b60405161039e919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6105c56106773660046150ea565b611014565b600e546040516bffffffffffffffffffffffff909116815260200161039e565b6002546001600160a01b03166105da565b6105c56106bb366004614bba565b61118d565b61085a604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915250604080516101a0810182526005546001600160a01b038082168352600160a01b820461ffff9081166020850152760100000000000000000000000000000000000000000000830463ffffffff908116958501959095527a0100000000000000000000000000000000000000000000000000008304811660608501527c0100000000000000000000000000000000000000000000000000000000928390048516608085015260065480821660a086015262010000808204831660c0870152640100000000820490931660e08601527801000000000000000000000000000000000000000000000000810486166101008601529290920484166101208401526007549182166101408401528104909216610160820152660100000000000090910460ff16151561018082015290565b60405161039e9190615206565b6105c5610875366004615215565b611257565b6105c56112ba565b610599610890366004614bba565b611383565b6000546001600160a01b03166105da565b6109506108b4366004614bba565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b03166000908152600b60209081526040918290208251608081018452905463ffffffff8116825267ffffffffffffffff64010000000082048116938301939093526c0100000000000000000000000081049092169281019290925260ff600160a01b909104161515606082015290565b60408051825163ffffffff16815260208084015167ffffffffffffffff9081169183019190915283830151169181019190915260609182015115159181019190915260800161039e565b6109a261147e565b60405161039e9291906152de565b6105c56109be366004615320565b611579565b6105836115e1565b6105836109d936600461538e565b6116a1565b6105c561252a565b6105c56109f43660046153fa565b6127af565b6105c5610a07366004614bba565b6127c0565b610a1f610a1a3660046154f9565b6127d1565b60405161039e9190615516565b60007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168367ffffffffffffffff1614610aac576040517fd9a9cd6800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6000610ac3610abe6080850185615563565b612805565b9050610af3610ad56020850185615563565b8351909150610ae760408701876155c8565b90508460200151612992565b6000600b81610b086080870160608801614bba565b6001600160a01b0316815260208082019290925260409081016000208151608081018352905463ffffffff81168252640100000000810467ffffffffffffffff908116948301949094526c01000000000000000000000000810490931691810191909152600160a01b90910460ff16151560608201819052909150610bd557610b976080850160608601614bba565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610aa3565b600654600090819064010000000090046001600160a01b031663ffdb4b37610c036080890160608a01614bba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8a1660248201526044016040805180830381865afa158015610c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c92919061565c565b90925090506000808080610ca960408b018b6155c8565b90501115610ce357610cd7610cc460808b0160608c01614bba565b86610cd260408d018d6155c8565b612af7565b91945092509050610cff565b8551610cfc9063ffffffff16662386f26fc100006156a5565b92505b60065460009062010000900461ffff1615610d5357610d506dffffffffffffffffffffffffffff607087901c16610d3960208d018d615563565b9050610d4860408e018e6155c8565b905085612ec6565b90505b60208781015160055460009267ffffffffffffffff9092169163ffffffff8716917a010000000000000000000000000000000000000000000000000000900461ffff1690610da3908f018f615563565b610dae9291506156a5565b6005548c51610ddd91760100000000000000000000000000000000000000000000900463ffffffff16906156bc565b610de791906156bc565b610df191906156bc565b610e0b906dffffffffffffffffffffffffffff89166156a5565b610e1591906156a5565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1682828a6040015167ffffffffffffffff1688610e5291906156a5565b610e5c91906156bc565b610e6691906156bc565b610e7091906156cf565b99505050505050505050505b92915050565b600e54600090610ea490600160801b900467ffffffffffffffff1660016156f1565b905090565b610eb1612f97565b610ebb8282612fef565b5050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610f43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f679190615712565b9392505050565b610f76613371565b610f7f816133cb565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff8082168352600160801b80830463ffffffff166020850152600160a01b90920460ff161515938301939093526004548084166060840152049091166080820152610ea4906137c0565b61101c612f97565b6001600160a01b03811661105c576040517f232cb97f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110666115e1565b905060008112156110a3576040517f02075e0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036110f5576110f06001600160a01b0384168383613872565b505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526110f09083906001600160a01b038616906370a0823190602401602060405180830381865afa158015611158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117c919061572f565b6001600160a01b0386169190613872565b6000546001600160a01b031633148015906111b357506002546001600160a01b03163314155b156111ea576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c906020015b60405180910390a150565b61125f612f97565b610ebb8282808060200260200160405190810160405280939291908181526020016000905b828210156112b0576112a160408302860136819003810190615748565b81526020019060010190611284565b50505050506138f2565b6001546001600160a01b031633146113145760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610aa3565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6001600160a01b038082166000908152600d6020526040812054909167ffffffffffffffff909116907f00000000000000000000000000000000000000000000000000000000000000001615610e7c5780600003610e7c576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa15801561145a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f679190615787565b606060008061148d6008613b58565b90508067ffffffffffffffff8111156114a8576114a8614cb8565b6040519080825280602002602001820160405280156114ed57816020015b60408051808201909152600080825260208201528152602001906001900390816114c65790505b50925060005b8181101561155657600080611509600884613b63565b915091506040518060400160405280836001600160a01b031681526020018261ffff16815250868481518110611541576115416157a4565b602090810291909101015250506001016114f3565b5050600e5491926c0100000000000000000000000090920463ffffffff16919050565b6000546001600160a01b0316331480159061159f57506002546001600160a01b03163314155b156115d6576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f7f600382613b81565b600e546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000916bffffffffffffffffffffffff16907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611673573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611697919061572f565b610ea491906157ba565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608086901b1660048201526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561173f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176391906157da565b1561179a576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0382166117da576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546001600160a01b0316331461181e576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168567ffffffffffffffff1614611897576040517fd9a9cd6800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610aa3565b60006118a9610abe6080870187615563565b905060006118ba60408701876155c8565b91506118e090506118ce6020880188615563565b90508360000151838560200151612992565b8015611a37576000805b82811015611a25576118ff60408901896155c8565b8281811061190f5761190f6157a4565b90506040020160200135600003611952576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c600061196360408b018b6155c8565b84818110611973576119736157a4565b6119899260206040909202019081019150614bba565b6001600160a01b031681526020810191909152604001600020547201000000000000000000000000000000000000900460ff1615611a1d57611a106119d160408a018a6155c8565b838181106119e1576119e16157a4565b9050604002018036038101906119f791906157f7565b60065464010000000090046001600160a01b0316613d14565b611a1a90836156bc565b91505b6001016118ea565b508015611a3557611a3581613e35565b505b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016611a716080880160608901614bba565b6001600160a01b031603611ad557600e8054869190600090611aa29084906bffffffffffffffffffffffff16615831565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550611bfc565b60065464010000000090046001600160a01b03166241e5be611afd6080890160608a01614bba565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015611b89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bad919061572f565b600e8054600090611bcd9084906bffffffffffffffffffffffff16615831565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b600e546bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811691161115611c69576040517fe5c7a49100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160200151611dbd577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615611dbd576001600160a01b0384166000908152600d602052604081205467ffffffffffffffff169003611dbd576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015611d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6d9190615787565b6001600160a01b0385166000908152600d6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790555b604080516101a08101825267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526001600160a01b03861660208201526000918101611e50611e168a80615563565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e4292505050565b6001600160a01b03168152602001600e601081819054906101000a900467ffffffffffffffff16611e8090615856565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001846000015181526020016000151581526020018460200151611f2a576001600160a01b0387166000908152600d602052604081208054909190611f009067ffffffffffffffff16615856565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055611f2d565b60005b67ffffffffffffffff168152602001611f4c60808a0160608b01614bba565b6001600160a01b03168152602001878152602001888060200190611f709190615563565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001611fb760408a018a6155c8565b808060200260200160405190810160405280939291908181526020016000905b8282101561200357611ff4604083028601368190038101906157f7565b81526020019060010190611fd7565b505050505081526020018367ffffffffffffffff81111561202657612026614cb8565b60405190808252806020026020018201604052801561205957816020015b60608152602001906001900390816120445790505b508152600060209091018190529091505b828110156124af57600061208160408a018a6155c8565b83818110612091576120916157a4565b9050604002018036038101906120a791906157f7565b905060006120b98b8360000151610ebf565b90506001600160a01b038116158061216f57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015612149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216d91906157da565b155b156121b45781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610aa3565b6000816001600160a01b0316639a4575b96040518060a001604052808e80600001906121e09190615563565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020808301919091526001600160a01b03808f16604080850191909152918901516060840152885116608090920191909152517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526122ab919060040161587d565b6000604051808303816000875af11580156122ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122f2919081019061594a565b9050602063ffffffff1681602001515111156123895782516001600160a01b03166000908152600c602090815260409091205490820151516e01000000000000000000000000000090910463ffffffff1610156123895782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610aa3565b805161239490613e42565b5060408051608081019091526001600160a01b03831660a08201528060c0810160408051808303601f190181529181529082528351602080840191909152808501518383015286516001600160a01b03166000908152600c9091522054606090910190730100000000000000000000000000000000000000900460ff166124295760075462010000900463ffffffff16612458565b84516001600160a01b03166000908152600c60205260409020546a0100000000000000000000900463ffffffff165b63ffffffff16905260405161247091906020016159db565b6040516020818303038152906040528561016001518581518110612496576124966157a4565b602002602001018190525050505080600101905061206a565b506124da817f0000000000000000000000000000000000000000000000000000000000000000613ee8565b6101808201526040517fd0c3c799bf9e2639de44391e7f524d229b2b55f5b1ea94b2bf7da42f7243dddd90612510908390615aef565b60405180910390a16101800151925050505b949350505050565b6000546001600160a01b0316331461258f576002546001600160a01b0316331461258f57612559600833614043565b61258f576040517f195db95800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff1660008190036125e3576040517f990e30bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e546bffffffffffffffffffffffff168181101561262e576040517f8d0f71d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006126386115e1565b1215612670576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600061267d6008613b58565b905060005b8181101561276c57600080612698600884613b63565b90925090506000876126b8836bffffffffffffffffffffffff8a166156a5565b6126c291906156cf565b90506126ce8187615c24565b95506127126001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016846bffffffffffffffffffffffff8416613872565b6040516bffffffffffffffffffffffff821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a2505050806001019050612682565b5050600e80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff929092169190911790555050565b6127b7612f97565b610f7f81614058565b6127c8613371565b610f7f816141ca565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260008082526020820152600082900361286657506040805180820190915267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260006020820152610e7c565b60006128728385615c49565b90507fe7e230f0000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016128df576128ca8360048187615c91565b8101906128d79190615cbb565b915050610e7c565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016129605760408051808201909152806129408560048189615c91565b81019061294d9190615ce7565b815260006020909101529150610e7c9050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006547801000000000000000000000000000000000000000000000000900463ffffffff16808511156129fb576040517f869337890000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610aa3565b6006547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16841115612a5d576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554600160a01b900461ffff16831115612aa4576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81612af0576007546601000000000000900460ff1615612af0576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000808083815b81811015612eba576000878783818110612b1a57612b1a6157a4565b905060400201803603810190612b3091906157f7565b905060006001600160a01b0316612b6b7f00000000000000000000000000000000000000000000000000000000000000008360000151610ebf565b6001600160a01b031603612bb95780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610aa3565b80516001600160a01b03166000908152600c6020908152604091829020825160e081018452905463ffffffff8082168352640100000000820481169383019390935261ffff68010000000000000000820416938201939093526a01000000000000000000008304821660608201526e0100000000000000000000000000008304909116608082015260ff720100000000000000000000000000000000000083048116151560a0830152730100000000000000000000000000000000000000909204909116151560c08201819052612cde57600754612ca29061ffff16662386f26fc100006156a5565b612cac90886156bc565b600754909750612cc89062010000900463ffffffff1687615d00565b9550612cd5602086615d00565b94505050612eb2565b604081015160009061ffff1615612e025760008c6001600160a01b031684600001516001600160a01b031614612da55760065484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526401000000009092041690634ab35b0b90602401602060405180830381865afa158015612d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d9e9190615d1d565b9050612da8565b508a5b620186a0836040015161ffff16612dea8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661428b90919063ffffffff16565b612df491906156a5565b612dfe91906156cf565b9150505b6060820151612e119088615d00565b9650816080015186612e239190615d00565b8251909650600090612e429063ffffffff16662386f26fc100006156a5565b905080821015612e6157612e56818a6156bc565b985050505050612eb2565b6000836020015163ffffffff16662386f26fc10000612e8091906156a5565b905080831115612ea057612e94818b6156bc565b99505050505050612eb2565b612eaa838b6156bc565b995050505050505b600101612afe565b50509450945094915050565b60008063ffffffff8316612edc610180866156a5565b612ee8876102206156bc565b612ef291906156bc565b612efc91906156bc565b6005546006549192506000917c010000000000000000000000000000000000000000000000000000000090910463ffffffff1690612f3e9061ffff16846156a5565b612f4891906156bc565b60065490915062010000900461ffff16612f726dffffffffffffffffffffffffffff8916836156a5565b612f7c91906156a5565b612f8c90655af3107a40006156a5565b979650505050505050565b6000546001600160a01b03163314612fed576002546001600160a01b03163314612fed576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60005b825181101561328357600083828151811061300f5761300f6157a4565b60200260200101519050602063ffffffff168160a0015163ffffffff16101561308257805160a08201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b03909216600483015263ffffffff166024820152604401610aa3565b6040805160e08101825260208381015163ffffffff908116835284840151811682840190815260608087015161ffff9081168688019081526080808a0151861693880193845260a0808b0151871691890191825260c0808c01511515918a019182526001908a018181529b516001600160a01b03166000908152600c9099529990972097518854955192519451915197519a519087167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009096169590951764010000000092871692909202919091177fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff166801000000000000000093909216929092027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff16176a010000000000000000000091841691909102177fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff166e01000000000000000000000000000093909216929092027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1617720100000000000000000000000000000000000094151594909402939093177fffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffff16730100000000000000000000000000000000000000931515939093029290921790915501612ff2565b507ff5791bc457b3bb990493cf5f655db46c25ccf5764c9b99b8969b4c72ea7df9d0826040516132b39190615d38565b60405180910390a160005b815181101561332e57600c60008383815181106132dd576132dd6157a4565b6020908102919091018101516001600160a01b0316825281019190915260400160002080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556001016132be565b50805115610ebb577ffb95a0042158e60a33e7b5bec100f3d95407b1a71bee6633bd54b8887449750b816040516133659190615516565b60405180910390a15050565b6000546001600160a01b03163314612fed5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610aa3565b60e08101516001600160a01b031661340f576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600560008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601a6101000a81548161ffff021916908361ffff160217905550608082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548161ffff021916908361ffff16021790555060c08201518160010160026101000a81548161ffff021916908361ffff16021790555060e08201518160010160046101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555061012082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160006101000a81548161ffff021916908361ffff1602179055506101608201518160020160026101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160020160066101000a81548160ff0219169083151502179055509050507f45b5ad483aa608464c2c7f278bd413d284d7790cdc836e40652e23a0277082206040518061010001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152508260405161124c929190615dd8565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261384e82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426138329190615df5565b85608001516fffffffffffffffffffffffffffffffff166142c8565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526110f09084906142f0565b8051604081111561392f576040517fb5a10cfa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e546c01000000000000000000000000900463ffffffff161561398357600e5463ffffffff6c010000000000000000000000008204166bffffffffffffffffffffffff909116106139835761398361252a565b600061398f6008613b58565b90505b80156139d15760006139b06139a8600184615df5565b600890613b63565b5090506139be6008826143d5565b5050806139ca90615e08565b9050613992565b506000805b82811015613ad95760008482815181106139f2576139f26157a4565b60200260200101516000015190506000858381518110613a1457613a146157a4565b60200260200101516020015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161480613a6957506001600160a01b038216155b15613aab576040517f4de938d10000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610aa3565b613abb60088361ffff84166143ea565b50613aca61ffff821685615d00565b935050508060010190506139d6565b50600e80547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd2490613b4b9083908690615e3d565b60405180910390a1505050565b6000610e7c82614400565b6000808080613b72868661440b565b909450925050505b9250929050565b8154600090613b9d90600160801b900463ffffffff1642615df5565b90508015613c255760018301548354613bd8916fffffffffffffffffffffffffffffffff808216928116918591600160801b909104166142c8565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617600160801b4263ffffffff16021783555b60208201518354613c4b916fffffffffffffffffffffffffffffffff9081169116614436565b835483511515600160a01b027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff9283161717845560208301516040808501518316600160801b0291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990613b4b9084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b81516040517fd02641a00000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260009182919084169063d02641a0906024016040805180830381865afa158015613d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d9e9190615e5c565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116600003613e075783516040517f9a655f7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610aa3565b6020840151612522907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83169061428b565b610f7f600382600061444c565b60008151602014613e8157816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610aa39190614c27565b600082806020019051810190613e97919061572f565b90506001600160a01b03811180613eaf575061040081105b15610e7c57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610aa39190614c27565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001613f7e9897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b6040516020818303038152906040528051906020012085610120015180519060200120866101400151604051602001613fb79190615e8f565b60405160208183030381529060405280519060200120876101600151604051602001613fe39190615ea2565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6000610f67836001600160a01b038416614756565b60005b815181101561419a576000828281518110614078576140786157a4565b60209081029190910181015160408051608080820183528385015163ffffffff90811683528385015167ffffffffffffffff908116848801908152606080880151831686880190815294880151151590860190815296516001600160a01b03166000908152600b90985294909620925183549451925195511515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9688166c0100000000000000000000000002969096167fffffffffffffffffffffff000000000000000000ffffffffffffffffffffffff93909716640100000000027fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009095169116179290921791909116929092171790555060010161405b565b507f067924bf9277d905a9a4631a06d959bc032ace86b3caa835ae7e403d4f39010e8160405161124c9190615eb5565b336001600160a01b038216036142225760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610aa3565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a76400006142be837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166156a5565b610f6791906156cf565b60006142e7856142d884866156a5565b6142e290876156bc565b614436565b95945050505050565b6000614345826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147629092919063ffffffff16565b8051909150156110f0578080602001905181019061436391906157da565b6110f05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aa3565b6000610f67836001600160a01b038416614771565b6000612522846001600160a01b0385168461478e565b6000610e7c826147ab565b6000808061441985856147b5565b600081815260029690960160205260409095205494959350505050565b60008183106144455781610f67565b5090919050565b8254600160a01b900460ff161580614462575081155b1561446c57505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906144a590600160801b900463ffffffff1642615df5565b9050801561454b57818311156144e7576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600186015461451490839085908490600160801b90046fffffffffffffffffffffffffffffffff166142c8565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff16600160801b4263ffffffff160217875592505b848210156145e8576001600160a01b03841661459d576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610aa3565b6040517f1a76572a00000000000000000000000000000000000000000000000000000000815260048101839052602481018690526001600160a01b0385166044820152606401610aa3565b848310156146d457600186810154600160801b90046fffffffffffffffffffffffffffffffff1690600090829061461f9082615df5565b614629878a615df5565b61463391906156bc565b61463d91906156cf565b90506001600160a01b038616614689576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610aa3565b6040517fd0c8d23a00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526001600160a01b0387166044820152606401610aa3565b6146de8584615df5565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000610f6783836147c1565b606061252284846000856147d9565b60008181526002830160205260408120819055610f6783836148c0565b6000828152600284016020526040812082905561252284846148cc565b6000610e7c825490565b6000610f6783836148d8565b60008181526001830160205260408120541515610f67565b6060824710156148515760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610aa3565b600080866001600160a01b0316858760405161486d9190615f36565b60006040518083038185875af1925050503d80600081146148aa576040519150601f19603f3d011682016040523d82523d6000602084013e6148af565b606091505b5091509150612f8c87838387614902565b6000610f67838361497b565b6000610f678383614a75565b60008260000182815481106148ef576148ef6157a4565b9060005260206000200154905092915050565b6060831561497157825160000361496a576001600160a01b0385163b61496a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aa3565b5081612522565b6125228383614ac4565b60008181526001830160205260408120548015614a6457600061499f600183615df5565b85549091506000906149b390600190615df5565b9050808214614a185760008660000182815481106149d3576149d36157a4565b90600052602060002001549050808760000184815481106149f6576149f66157a4565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614a2957614a29615f52565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610e7c565b6000915050610e7c565b5092915050565b6000818152600183016020526040812054614abc57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610e7c565b506000610e7c565b815115614ad45781518083602001fd5b8060405162461bcd60e51b8152600401610aa39190614c27565b6001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015280606085015116606086015250506bffffffffffffffffffffffff60808301511660808401528060a08301511660a08401525060c0810151614b6b60c08401826001600160a01b03169052565b5060e08101516110f060e08401826001600160a01b03169052565b6101008101610e7c8284614aee565b6001600160a01b0381168114610f7f57600080fd5b8035614bb581614b95565b919050565b600060208284031215614bcc57600080fd5b8135610f6781614b95565b60005b83811015614bf2578181015183820152602001614bda565b50506000910152565b60008151808452614c13816020860160208601614bd7565b601f01601f19169290920160200192915050565b602081526000610f676020830184614bfb565b67ffffffffffffffff81168114610f7f57600080fd5b600060a08284031215614c6257600080fd5b50919050565b60008060408385031215614c7b57600080fd5b8235614c8681614c3a565b9150602083013567ffffffffffffffff811115614ca257600080fd5b614cae85828601614c50565b9150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff81118282101715614cf157614cf1614cb8565b60405290565b6040516101a0810167ffffffffffffffff81118282101715614cf157614cf1614cb8565b60405160a0810167ffffffffffffffff81118282101715614cf157614cf1614cb8565b6040805190810167ffffffffffffffff81118282101715614cf157614cf1614cb8565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d8a57614d8a614cb8565b604052919050565b600067ffffffffffffffff821115614dac57614dac614cb8565b5060051b60200190565b63ffffffff81168114610f7f57600080fd5b8035614bb581614db6565b803561ffff81168114614bb557600080fd5b8015158114610f7f57600080fd5b8035614bb581614de5565b600082601f830112614e0f57600080fd5b81356020614e24614e1f83614d92565b614d61565b8083825260208201915060208460051b870101935086841115614e4657600080fd5b602086015b84811015614e6b578035614e5e81614b95565b8352918301918301614e4b565b509695505050505050565b6000806040808486031215614e8a57600080fd5b833567ffffffffffffffff80821115614ea257600080fd5b818601915086601f830112614eb657600080fd5b81356020614ec6614e1f83614d92565b82815260e0928302850182019282820191908b851115614ee557600080fd5b958301955b84871015614f8e5780878d031215614f025760008081fd5b614f0a614cce565b8735614f1581614b95565b815287850135614f2481614db6565b8186015287890135614f3581614db6565b818a01526060614f46898201614dd3565b90820152608088810135614f5981614db6565b9082015260a0614f6a898201614dc8565b9082015260c0614f7b898201614df3565b9082015283529586019591830191614eea565b5097505087013593505080831115614fa557600080fd5b5050614cae85828601614dfe565b60008060408385031215614fc657600080fd5b8235614fd181614c3a565b91506020830135614fe181614b95565b809150509250929050565b60006101a08284031215614fff57600080fd5b615007614cf7565b61501083614baa565b815261501e60208401614dd3565b602082015261502f60408401614dc8565b604082015261504060608401614dd3565b606082015261505160808401614dc8565b608082015261506260a08401614dd3565b60a082015261507360c08401614dd3565b60c082015261508460e08401614baa565b60e0820152610100615097818501614dc8565b908201526101206150a9848201614dc8565b908201526101406150bb848201614dd3565b908201526101606150cd848201614dc8565b908201526101806150df848201614df3565b908201529392505050565b600080604083850312156150fd57600080fd5b8235614fd181614b95565b80516001600160a01b03168252602081015161512a602084018261ffff169052565b506040810151615142604084018263ffffffff169052565b506060810151615158606084018261ffff169052565b506080810151615170608084018263ffffffff169052565b5060a081015161518660a084018261ffff169052565b5060c081015161519c60c084018261ffff169052565b5060e08101516151b760e08401826001600160a01b03169052565b506101008181015163ffffffff90811691840191909152610120808301518216908401526101408083015161ffff16908401526101608083015190911690830152610180908101511515910152565b6101a08101610e7c8284615108565b6000806020838503121561522857600080fd5b823567ffffffffffffffff8082111561524057600080fd5b818501915085601f83011261525457600080fd5b81358181111561526357600080fd5b8660208260061b850101111561527857600080fd5b60209290920196919550909350505050565b60008151808452602080850194506020840160005b838110156152d357815180516001600160a01b0316885283015161ffff16838801526040909601959082019060010161529f565b509495945050505050565b6040815260006152f1604083018561528a565b90508260208301529392505050565b80356fffffffffffffffffffffffffffffffff81168114614bb557600080fd5b60006060828403121561533257600080fd5b6040516060810181811067ffffffffffffffff8211171561535557615355614cb8565b604052823561536381614de5565b815261537160208401615300565b602082015261538260408401615300565b60408201529392505050565b600080600080608085870312156153a457600080fd5b84356153af81614c3a565b9350602085013567ffffffffffffffff8111156153cb57600080fd5b6153d787828801614c50565b9350506040850135915060608501356153ef81614b95565b939692955090935050565b6000602080838503121561540d57600080fd5b823567ffffffffffffffff81111561542457600080fd5b8301601f8101851361543557600080fd5b8035615443614e1f82614d92565b81815260a0918202830184019184820191908884111561546257600080fd5b938501935b838510156154ed5780858a03121561547f5760008081fd5b615487614d1b565b853561549281614b95565b8152858701356154a181614db6565b818801526040868101356154b481614c3a565b908201526060868101356154c781614c3a565b908201526080868101356154da81614de5565b9082015283529384019391850191615467565b50979650505050505050565b60006020828403121561550b57600080fd5b8135610f6781614c3a565b6020808252825182820181905260009190848201906040850190845b818110156155575783516001600160a01b031683529284019291840191600101615532565b50909695505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261559857600080fd5b83018035915067ffffffffffffffff8211156155b357600080fd5b602001915036819003821315613b7a57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126155fd57600080fd5b83018035915067ffffffffffffffff82111561561857600080fd5b6020019150600681901b3603821315613b7a57600080fd5b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168114614bb557600080fd5b6000806040838503121561566f57600080fd5b61567883615630565b915061568660208401615630565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610e7c57610e7c61568f565b80820180821115610e7c57610e7c61568f565b6000826156ec57634e487b7160e01b600052601260045260246000fd5b500490565b67ffffffffffffffff818116838216019080821115614a6e57614a6e61568f565b60006020828403121561572457600080fd5b8151610f6781614b95565b60006020828403121561574157600080fd5b5051919050565b60006040828403121561575a57600080fd5b615762614d3e565b823561576d81614b95565b815261577b60208401614dd3565b60208201529392505050565b60006020828403121561579957600080fd5b8151610f6781614c3a565b634e487b7160e01b600052603260045260246000fd5b8181036000831280158383131683831282161715614a6e57614a6e61568f565b6000602082840312156157ec57600080fd5b8151610f6781614de5565b60006040828403121561580957600080fd5b615811614d3e565b823561581c81614b95565b81526020928301359281019290925250919050565b6bffffffffffffffffffffffff818116838216019080821115614a6e57614a6e61568f565b600067ffffffffffffffff8083168181036158735761587361568f565b6001019392505050565b602081526000825160a0602084015261589960c0840182614bfb565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f8301126158f757600080fd5b815167ffffffffffffffff81111561591157615911614cb8565b6159246020601f19601f84011601614d61565b81815284602083860101111561593957600080fd5b612522826020830160208701614bd7565b60006020828403121561595c57600080fd5b815167ffffffffffffffff8082111561597457600080fd5b908301906040828603121561598857600080fd5b615990614d3e565b82518281111561599f57600080fd5b6159ab878286016158e6565b8252506020830151828111156159c057600080fd5b6159cc878286016158e6565b60208301525095945050505050565b6020815260008251608060208401526159f760a0840182614bfb565b90506020840151601f1980858403016040860152615a158383614bfb565b9250604086015191508085840301606086015250615a338282614bfb565b91505063ffffffff60608501511660808401528091505092915050565b60008151808452602080850194506020840160005b838110156152d357815180516001600160a01b031688528301518388015260409096019590820190600101615a65565b60008282518085526020808601955060208260051b8401016020860160005b84811015615ae257601f19868403018952615ad0838351614bfb565b98840198925090830190600101615ab4565b5090979650505050505050565b60208152615b0a60208201835167ffffffffffffffff169052565b60006020830151615b2660408401826001600160a01b03169052565b5060408301516001600160a01b038116606084015250606083015167ffffffffffffffff8116608084015250608083015160a083015260a0830151615b6f60c084018215159052565b5060c083015167ffffffffffffffff811660e08401525060e0830151610100615ba2818501836001600160a01b03169052565b840151610120848101919091528401516101a061014080860182905291925090615bd06101c0860184614bfb565b9250808601519050601f19610160818786030181880152615bf18584615a50565b945080880151925050610180818786030181880152615c108584615a95565b970151959092019490945250929392505050565b6bffffffffffffffffffffffff828116828216039080821115614a6e57614a6e61568f565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015615c895780818660040360031b1b83161692505b505092915050565b60008085851115615ca157600080fd5b83861115615cae57600080fd5b5050820193919092039150565b600060408284031215615ccd57600080fd5b615cd5614d3e565b82358152602083013561577b81614de5565b600060208284031215615cf957600080fd5b5035919050565b63ffffffff818116838216019080821115614a6e57614a6e61568f565b600060208284031215615d2f57600080fd5b610f6782615630565b602080825282518282018190526000919060409081850190868401855b82811015615dcb57815180516001600160a01b031685528681015163ffffffff908116888701528682015181168787015260608083015161ffff169087015260808083015182169087015260a0808301519091169086015260c09081015115159085015260e09093019290850190600101615d55565b5091979650505050505050565b6102a08101615de78285614aee565b610f67610100830184615108565b81810381811115610e7c57610e7c61568f565b600081615e1757615e1761568f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b63ffffffff83168152604060208201526000612522604083018461528a565b600060408284031215615e6e57600080fd5b615e76614d3e565b615e7f83615630565b8152602083015161577b81614db6565b602081526000610f676020830184615a50565b602081526000610f676020830184615a95565b602080825282518282018190526000919060409081850190868401855b82811015615dcb57815180516001600160a01b031685528681015163ffffffff16878601528581015167ffffffffffffffff908116878701526060808301519091169086015260809081015115159085015260a09093019290850190600101615ed2565b60008251615f48818460208701614bd7565b9190910192915050565b634e487b7160e01b600052603160045260246000fdfea164736f6c6343000818000a", } var EVM2EVMOnRampABI = EVM2EVMOnRampMetaData.ABI @@ -2279,7 +2278,7 @@ func (EVM2EVMOnRampConfigChanged) Topic() common.Hash { } func (EVM2EVMOnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0xe375c8cb6ea9807cd0371503b632b93da5ee0f1f64205db8b5b28b95d6b588b0") + return common.HexToHash("0x45b5ad483aa608464c2c7f278bd413d284d7790cdc836e40652e23a027708220") } func (EVM2EVMOnRampFeeConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0/evm_2_evm_onramp_1_0_0.go b/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0/evm_2_evm_onramp_1_0_0.go deleted file mode 100644 index 6fd05d693a3..00000000000 --- a/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0/evm_2_evm_onramp_1_0_0.go +++ /dev/null @@ -1,2792 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package evm_2_evm_onramp_1_0_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 ClientEVM2AnyMessage struct { - Receiver []byte - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - ExtraArgs []byte -} - -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - -type EVM2EVMOnRampDynamicConfig struct { - Router common.Address - MaxTokensLength uint16 - PriceRegistry common.Address - MaxDataSize uint32 - MaxGasLimit uint64 -} - -type EVM2EVMOnRampFeeTokenConfig struct { - NetworkFeeAmountUSD *big.Int - GasMultiplier uint64 - DestGasOverhead uint32 - DestGasPerPayloadByte uint16 - Enabled bool -} - -type EVM2EVMOnRampFeeTokenConfigArgs struct { - Token common.Address - GasMultiplier uint64 - NetworkFeeAmountUSD *big.Int - DestGasOverhead uint32 - DestGasPerPayloadByte uint16 - Enabled bool -} - -type EVM2EVMOnRampNopAndWeight struct { - Nop common.Address - Weight uint16 -} - -type EVM2EVMOnRampStaticConfig struct { - LinkToken common.Address - ChainSelector uint64 - DestChainSelector uint64 - DefaultTxGasLimit uint64 - MaxNopFeesJuels *big.Int - PrevOnRamp common.Address - ArmProxy common.Address -} - -type EVM2EVMOnRampTokenTransferFeeConfig struct { - MinFee uint32 - MaxFee uint32 - Ratio uint16 -} - -type EVM2EVMOnRampTokenTransferFeeConfigArgs struct { - Token common.Address - MinFee uint32 - MaxFee uint32 - Ratio uint16 -} - -type InternalEVM2EVMMessage struct { - SourceChainSelector uint64 - SequenceNumber uint64 - FeeTokenAmount *big.Int - Sender common.Address - Nonce uint64 - GasLimit *big.Int - Strict bool - Receiver common.Address - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - MessageId [32]byte -} - -type InternalPoolUpdate struct { - Token common.Address - Pool common.Address -} - -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 -} - -var EVM2EVMOnRampMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"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[]\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"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\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"networkFeeAmountUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.FeeTokenConfigArgs[]\",\"name\":\"feeTokenConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"minFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFee\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"}],\"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\":\"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\":\"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\":[],\"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\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"AllowListEnabledSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"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\":\"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\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"networkFeeAmountUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"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\":\"minFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFee\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"transferFeeConfig\",\"type\":\"tuple[]\"}],\"name\":\"TokenTransferFeeConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":[{\"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\":\"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\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"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\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getFeeTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"networkFeeAmountUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"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\":\"minFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFee\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"}],\"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\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"setAllowListEnabled\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"networkFeeAmountUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"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\":\"minFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFee\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"}],\"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\"}]", - Bin: "0x6101806040526012805460ff60c01b191690553480156200001f57600080fd5b50604051620081c9380380620081c9833981016040819052620000429162001eb3565b8333806000816200009a5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000cd57620000cd8162000369565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606086018190529790950151166080909301839052600380546001600160a01b031916909417600160801b9283021760ff60a01b1916600160a01b90910217909255029091176004555087516001600160a01b0316158062000176575060208801516001600160401b0316155b806200018d575060408801516001600160401b0316155b80620001a4575060608801516001600160401b0316155b80620001bb575060c08801516001600160a01b0316155b15620001da576040516306b7c75960e31b815260040160405180910390fd5b6020808901516040808b015181517fbdd59ac4dd1d82276c9a9c5d2656546346b9dcdb1f9b4204aed4ec15c23d7d3a948101949094526001600160401b039283169184019190915216606082015230608082015260a00160408051601f19818403018152918152815160209283012060809081528a516001600160a01b0390811660e052928b01516001600160401b0390811661010052918b015182166101205260608b015190911660a0908152908a01516001600160601b031660c0908152908a01518216610140528901511661016052620002b78762000414565b620002c28362000566565b620002cd82620006d8565b620002d881620007e5565b6040805160008082526020820190925262000323916200031b565b6040805180820190915260008082526020820152815260200190600190039081620002f35790505b508762000a0f565b8451156200035b576012805460ff60c81b1916600160c81b179055604080516000808252602082019092526200035b91508662000d12565b505050505050505062002405565b336001600160a01b03821603620003c35760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000091565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60408101516001600160a01b031662000440576040516306b7c75960e31b815260040160405180910390fd5b8051600580546020808501516001600160a01b039485166001600160b01b031990931692909217600160a01b61ffff909316830217909255604080850151600680546060808901516080808b0151958a166001600160c01b03199094169390931763ffffffff909116909602959095176001600160c01b0316600160c01b6001600160401b039485160217909155825160e080820185525187168152610100518316958101959095526101205182168584015260a080519092169385019390935260c080516001600160601b03169385019390935261014051851690840152610160519093169082015290517fdd226617d8d287f40a64c54741bbcdc492b3e096ef16bc5273a18cb6ab85f124916200055b91849062001fd6565b60405180910390a150565b60005b8151811015620006a65760008282815181106200058a576200058a62002086565b6020908102919091018101516040805160a08082018352828401516001600160601b039081168352848601516001600160401b0390811684880190815260608088015163ffffffff9081168789019081526080808b015161ffff908116948a01948552978b0151151590890190815299516001600160a01b03166000908152600f909b52979099209551865492519751915198511515600160d01b0260ff60d01b1999909616600160c01b0261ffff60c01b1992909a16600160a01b029190911665ffffffffffff60a01b19979093166c01000000000000000000000000026001600160a01b03199092169316929092179190911793909316929092179390931791909116179055506200069e81620020b2565b905062000569565b507ffba339fca97870ffdfaedbae3745db5e6de1a6909dfd0e0dbb56917469ffe236816040516200055b9190620020ce565b60005b8151811015620007b3576000828281518110620006fc57620006fc62002086565b60209081029190910181015160408051606080820183528385015163ffffffff90811683528385015181168387019081529185015161ffff90811684860190815295516001600160a01b031660009081526010909752939095209151825491519451909316680100000000000000000261ffff60401b19948616640100000000026001600160401b03199092169390951692909217919091179190911691909117905550620007ab81620020b2565b9050620006db565b507fcb0c5f472d325cf0c56953fc81870ddd80d0d3c9a3fbfe777002d75f380dfb81816040516200055b91906200216f565b805160408111156200080a57604051635ad0867d60e11b815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff161580159062000854575060125463ffffffff6c010000000000000000000000008204166001600160601b0390911610155b1562000864576200086462000e5d565b60006200087260076200105d565b90505b8015620008be576000620008986200088f600184620021de565b60079062001070565b509050620008a86007826200108e565b505080620008b690620021f4565b905062000875565b506000805b82811015620009a6576000848281518110620008e357620008e362002086565b6020026020010151600001519050600085838151811062000908576200090862002086565b602002602001015160200151905060e0516001600160a01b0316826001600160a01b031614806200094057506001600160a01b038216155b156200096b57604051634de938d160e01b81526001600160a01b038316600482015260240162000091565b6200097d60078361ffff8416620010ac565b506200098e61ffff8216856200220e565b93505050806200099e90620020b2565b9050620008c3565b506012805463ffffffff60601b19166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd249062000a0290839086906200222e565b60405180910390a1505050565b60005b825181101562000b4b57600083828151811062000a335762000a3362002086565b6020026020010151600001519050600084838151811062000a585762000a5862002086565b6020908102919091018101510151905062000a75600a83620010cc565b62000a9f576040516373913ebd60e01b81526001600160a01b038316600482015260240162000091565b6001600160a01b03811662000ab6600a84620010e3565b6001600160a01b03161462000ade57604051630d98f73360e31b815260040160405180910390fd5b62000aeb600a83620010fa565b1562000b3557604080516001600160a01b038085168252831660208201527f987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c910160405180910390a15b50508062000b4390620020b2565b905062000a12565b5060005b815181101562000d0d57600082828151811062000b705762000b7062002086565b6020026020010151600001519050600083838151811062000b955762000b9562002086565b602002602001015160200151905060006001600160a01b0316826001600160a01b0316148062000bcc57506001600160a01b038116155b1562000bea5760405162d8548360e71b815260040160405180910390fd5b806001600160a01b03166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000c29573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c4f91906200229b565b6001600160a01b0316826001600160a01b03161462000c8157604051630d98f73360e31b815260040160405180910390fd5b62000c8f600a838362001111565b1562000cde57604080516001600160a01b038085168252831660208201527f95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c910160405180910390a162000cf7565b604051633caf458560e01b815260040160405180910390fd5b50508062000d0590620020b2565b905062000b4f565b505050565b60005b825181101562000da757600083828151811062000d365762000d3662002086565b6020908102919091010151905062000d50600d8262001129565b1562000d93576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5062000d9f81620020b2565b905062000d15565b5060005b815181101562000d0d57600082828151811062000dcc5762000dcc62002086565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000df8575062000e4a565b62000e05600d8262001140565b1562000e48576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b62000e5581620020b2565b905062000dab565b6000546001600160a01b0316331480159062000e8457506002546001600160a01b03163314155b801562000e9b575062000e9960073362001157565b155b1562000eba5760405163032bb72b60e31b815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff16600081900362000ef65760405163990e30bf60e01b815260040160405180910390fd5b6012546001600160601b03168181101562000f24576040516311a1ee3b60e31b815260040160405180910390fd5b600062000f306200116e565b121562000f5057604051631e9acf1760e31b815260040160405180910390fd5b80600062000f5f60076200105d565b905060005b81811015620010375760008062000f7d60078462001070565b909250905060008762000f9a836001600160601b038a16620022bb565b62000fa69190620022d5565b905062000fb48187620022f8565b60e05190965062000fd9906001600160a01b0316846001600160601b038416620011fc565b6040516001600160601b03821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a2505050806200102f90620020b2565b905062000f64565b5050601280546001600160601b0319166001600160601b03929092169190911790555050565b60006200106a8262001254565b92915050565b600080808062001081868662001261565b9097909650945050505050565b6000620010a5836001600160a01b0384166200128e565b9392505050565b6000620010c4846001600160a01b03851684620012ad565b949350505050565b6000620010a5836001600160a01b038416620012cc565b6000620010a5836001600160a01b038416620012da565b6000620010a5836001600160a01b038416620012e8565b6000620010c4846001600160a01b03851684620012f6565b6000620010a5836001600160a01b0384166200130e565b6000620010a5836001600160a01b03841662001419565b6000620010a5836001600160a01b0384166200146b565b60125460e0516040516370a0823160e01b81523060048201526000926001600160601b0316916001600160a01b0316906370a0823190602401602060405180830381865afa158015620011c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011eb91906200231b565b620011f7919062002335565b905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663a9059cbb60e01b1790915262000d0d9185916200147916565b60006200106a826200154a565b6000808062001271858562001555565b600081815260029690960160205260409095205494959350505050565b60008181526002830160205260408120819055620010a5838362001563565b60008281526002840160205260408120829055620010c4848462001571565b6000620010a583836200146b565b6000620010a583836200157f565b6000620010a583836200128e565b6000620010c484846001600160a01b038516620012ad565b600081815260018301602052604081205480156200140757600062001335600183620021de565b85549091506000906200134b90600190620021de565b9050818114620013b75760008660000182815481106200136f576200136f62002086565b906000526020600020015490508087600001848154811062001395576200139562002086565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620013cb57620013cb62002358565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200106a565b60009150506200106a565b5092915050565b600081815260018301602052604081205462001462575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200106a565b5060006200106a565b6000620010a58383620015f4565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620014c8906001600160a01b0385169084906200160d565b80519091501562000d0d5780806020019051810190620014e991906200236e565b62000d0d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000091565b60006200106a825490565b6000620010a583836200161e565b6000620010a583836200130e565b6000620010a5838362001419565b600081815260028301602052604081205480151580620015a65750620015a684846200146b565b620010a55760405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000604482015260640162000091565b60008181526001830160205260408120541515620010a5565b6060620010c484846000856200164b565b600082600001828154811062001638576200163862002086565b9060005260206000200154905092915050565b606082471015620016ae5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000091565b600080866001600160a01b03168587604051620016cc9190620023b2565b60006040518083038185875af1925050503d80600081146200170b576040519150601f19603f3d011682016040523d82523d6000602084013e62001710565b606091505b50909250905062001724878383876200172f565b979650505050505050565b60608315620017a35782516000036200179b576001600160a01b0385163b6200179b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000091565b5081620010c4565b620010c48383815115620017ba5781518083602001fd5b8060405162461bcd60e51b8152600401620000919190620023d0565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620018115762001811620017d6565b60405290565b60405160c081016001600160401b0381118282101715620018115762001811620017d6565b604051608081016001600160401b0381118282101715620018115762001811620017d6565b604051601f8201601f191681016001600160401b03811182821017156200188c576200188c620017d6565b604052919050565b6001600160a01b0381168114620018aa57600080fd5b50565b80516001600160401b0381168114620018c557600080fd5b919050565b80516001600160601b0381168114620018c557600080fd5b600060e08284031215620018f557600080fd5b60405160e081016001600160401b03811182821017156200191a576200191a620017d6565b806040525080915082516200192f8162001894565b81526200193f60208401620018ad565b60208201526200195260408401620018ad565b60408201526200196560608401620018ad565b60608201526200197860808401620018ca565b608082015260a08301516200198d8162001894565b60a082015260c0830151620019a28162001894565b60c0919091015292915050565b805161ffff81168114620018c557600080fd5b805163ffffffff81168114620018c557600080fd5b600060a08284031215620019ea57600080fd5b60405160a081016001600160401b038111828210171562001a0f5762001a0f620017d6565b8060405250809150825162001a248162001894565b815262001a3460208401620019af565b6020820152604083015162001a498162001894565b604082015262001a5c60608401620019c2565b606082015262001a6f60808401620018ad565b60808201525092915050565b60006001600160401b0382111562001a975762001a97620017d6565b5060051b60200190565b600082601f83011262001ab357600080fd5b8151602062001acc62001ac68362001a7b565b62001861565b82815260069290921b8401810191818101908684111562001aec57600080fd5b8286015b8481101562001b46576040818903121562001b0b5760008081fd5b62001b15620017ec565b815162001b228162001894565b81528185015162001b338162001894565b8186015283529183019160400162001af0565b509695505050505050565b600082601f83011262001b6357600080fd5b8151602062001b7662001ac68362001a7b565b82815260059290921b8401810191818101908684111562001b9657600080fd5b8286015b8481101562001b4657805162001bb08162001894565b835291830191830162001b9a565b80518015158114620018c557600080fd5b80516001600160801b0381168114620018c557600080fd5b60006060828403121562001bfa57600080fd5b604051606081016001600160401b038111828210171562001c1f5762001c1f620017d6565b60405290508062001c308362001bbe565b815262001c406020840162001bcf565b602082015262001c536040840162001bcf565b60408201525092915050565b600082601f83011262001c7157600080fd5b8151602062001c8462001ac68362001a7b565b82815260c0928302850182019282820191908785111562001ca457600080fd5b8387015b8581101562001d465781818a03121562001cc25760008081fd5b62001ccc62001817565b815162001cd98162001894565b815262001ce8828701620018ad565b86820152604062001cfb818401620018ca565b90820152606062001d0e838201620019c2565b90820152608062001d21838201620019af565b9082015260a062001d3483820162001bbe565b90820152845292840192810162001ca8565b5090979650505050505050565b600082601f83011262001d6557600080fd5b8151602062001d7862001ac68362001a7b565b82815260079290921b8401810191818101908684111562001d9857600080fd5b8286015b8481101562001b46576080818903121562001db75760008081fd5b62001dc16200183c565b815162001dce8162001894565b815262001ddd828601620019c2565b85820152604062001df0818401620019c2565b90820152606062001e03838201620019af565b9082015283529183019160800162001d9c565b600082601f83011262001e2857600080fd5b8151602062001e3b62001ac68362001a7b565b82815260069290921b8401810191818101908684111562001e5b57600080fd5b8286015b8481101562001b46576040818903121562001e7a5760008081fd5b62001e84620017ec565b815162001e918162001894565b815262001ea0828601620019af565b8186015283529183019160400162001e5f565b600080600080600080600080610280898b03121562001ed157600080fd5b62001edd8a8a620018e2565b975062001eee8a60e08b01620019d7565b6101808a01519097506001600160401b038082111562001f0d57600080fd5b62001f1b8c838d0162001aa1565b97506101a08b015191508082111562001f3357600080fd5b62001f418c838d0162001b51565b965062001f538c6101c08d0162001be7565b95506102208b015191508082111562001f6b57600080fd5b62001f798c838d0162001c5f565b94506102408b015191508082111562001f9157600080fd5b62001f9f8c838d0162001d53565b93506102608b015191508082111562001fb757600080fd5b5062001fc68b828c0162001e16565b9150509295985092959890939650565b82516001600160a01b0390811682526020808501516001600160401b03908116828501526040808701518216818601526060808801518316818701526080808901516001600160601b03168188015260a0808a015187169088015260c0808a01518716908801528751861660e08801529387015161ffff16610100870152908601519093166101208501529184015163ffffffff16610140840152830151166101608201526101808101620010a5565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620020c757620020c76200209c565b5060010190565b602080825282518282018190526000919060409081850190868401855b828110156200216257815180516001600160a01b03168552868101516001600160401b031687860152858101516001600160601b03168686015260608082015163ffffffff169086015260808082015161ffff169086015260a09081015115159085015260c09093019290850190600101620020eb565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b828110156200216257815180516001600160a01b031685528681015163ffffffff9081168887015286820151168686015260609081015161ffff1690850152608090930192908501906001016200218c565b818103818111156200106a576200106a6200209c565b6000816200220657620022066200209c565b506000190190565b63ffffffff8181168382160190808211156200141257620014126200209c565b6000604080830163ffffffff8616845260208281860152818651808452606087019150828801935060005b818110156200228d57845180516001600160a01b0316845284015161ffff1684840152938301939185019160010162002259565b509098975050505050505050565b600060208284031215620022ae57600080fd5b8151620010a58162001894565b80820281158282048414176200106a576200106a6200209c565b600082620022f357634e487b7160e01b600052601260045260246000fd5b500490565b6001600160601b038281168282160390808211156200141257620014126200209c565b6000602082840312156200232e57600080fd5b5051919050565b81810360008312801583831316838312821617156200141257620014126200209c565b634e487b7160e01b600052603160045260246000fd5b6000602082840312156200238157600080fd5b620010a58262001bbe565b60005b83811015620023a95781810151838201526020016200238f565b50506000910152565b60008251620023c68184602087016200238c565b9190910192915050565b6020815260008251806020840152620023f18160408501602087016200238c565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516101405161016051615cbd6200250c600039600081816103600152818161140a0152612c2001526000818161033101528181611320015281816113880152818161185a015281816118c20152612bf801526000818161029d01528181610af901528181611c520152612b7001526000818161026d0152818161198d0152612b4601526000818161023e01528181610dfa0152818161160d01528181611706015281816121a501528181612b2101528181612d6b015261323c0152600081816102fd015281816117d20152612bc20152600081816102cd015281816122bd0152612b9701526000611b6c0152615cbd6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806376f6ae761161010f578063b06d41bc116100a2578063e0351e1311610071578063e0351e13146108ee578063efeadb6d14610921578063eff7cc4814610934578063f2fde38b1461093c57600080fd5b8063b06d41bc146108b5578063c92b2832146108cb578063d09dc339146108de578063d3c7c2c7146108e657600080fd5b80638da5cb5b116100de5780638da5cb5b146107105780639a113c3614610721578063a7cd63b71461088d578063a7d3e02f146108a257600080fd5b806376f6ae76146106cf578063799c3a67146106e257806379ba5097146106f5578063856c8247146106fd57600080fd5b8063549e946f116101875780635d86f141116101565780635d86f141146105d45780635ebbd9f8146105e7578063704b6c02146105fa5780637437ff9f1461060d57600080fd5b8063549e946f1461056957806354b714681461057c57806354c8a4f31461059c578063599f6431146105af57600080fd5b80633a87ac53116101c35780633a87ac53146104bc5780633a9bf949146104d15780634120fccd146104e4578063546719cd1461050557600080fd5b806306285c69146101f55780631772047e146103a6578063181f5a771461045257806338724a951461049b575b600080fd5b6103906040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040518060e001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161039d9190614822565b60405180910390f35b6104216103b43660046148b3565b6040805160608082018352600080835260208084018290529284018190526001600160a01b039490941684526010825292829020825193840183525463ffffffff80821685526401000000008204169184019190915268010000000000000000900461ffff169082015290565b60408051825163ffffffff9081168252602080850151909116908201529181015161ffff169082015260600161039d565b61048e6040518060400160405280601381526020017f45564d3245564d4f6e52616d7020312e302e300000000000000000000000000081525081565b60405161039d919061493e565b6104ae6104a9366004614963565b61094f565b60405190815260200161039d565b6104cf6104ca366004614b4a565b610c8d565b005b6104cf6104df366004614bef565b610ca3565b6104ec610cb7565b60405167ffffffffffffffff909116815260200161039d565b61050d610ceb565b60405161039d919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6104cf610577366004614c83565b610d9b565b6012546040516bffffffffffffffffffffffff909116815260200161039d565b6104cf6105aa366004614d20565b610f50565b6002546001600160a01b03165b6040516001600160a01b03909116815260200161039d565b6105bc6105e23660046148b3565b610f62565b6104cf6105f5366004614d7a565b610fc1565b6104cf6106083660046148b3565b611027565b6106c26040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526005546001600160a01b038082168352740100000000000000000000000000000000000000009182900461ffff16602084015260065490811693830193909352820463ffffffff166060820152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16608082015290565b60405161039d9190614e58565b6104cf6106dd366004614eb2565b6110f1565b6104cf6106f0366004614f40565b6111a9565b6104cf61120f565b6104ec61070b3660046148b3565b6112f2565b6000546001600160a01b03166105bc565b61082761072f3660046148b3565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506001600160a01b03166000908152600f6020908152604091829020825160a08101845290546bffffffffffffffffffffffff811682526c01000000000000000000000000810467ffffffffffffffff169282019290925274010000000000000000000000000000000000000000820463ffffffff16928101929092527801000000000000000000000000000000000000000000000000810461ffff1660608301527a010000000000000000000000000000000000000000000000000000900460ff161515608082015290565b60405161039d9190600060a0820190506bffffffffffffffffffffffff835116825267ffffffffffffffff602084015116602083015263ffffffff604084015116604083015261ffff606084015116606083015260808301511515608083015292915050565b6108956113fa565b60405161039d919061505e565b6104ae6108b03660046150ab565b611406565b6108bd611d39565b60405161039d929190615159565b6104cf6108d936600461519b565b611e3d565b6104ae611ea5565b610895611eaf565b601254790100000000000000000000000000000000000000000000000000900460ff16604051901515815260200161039d565b6104cf61092f366004615209565b611f60565b6104cf611fe6565b6104cf61094a3660046148b3565b61227d565b600080600f8161096560808601606087016148b3565b6001600160a01b031681526020808201929092526040908101600020815160a08101835290546bffffffffffffffffffffffff811682526c01000000000000000000000000810467ffffffffffffffff169382019390935274010000000000000000000000000000000000000000830463ffffffff16918101919091527801000000000000000000000000000000000000000000000000820461ffff1660608201527a01000000000000000000000000000000000000000000000000000090910460ff16151560808201819052909150610a8c57610a4960808401606085016148b3565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024015b60405180910390fd5b60065460009081906001600160a01b031663ffdb4b37610ab260808801606089016148b3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016040805180830381865afa158015610b3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b61919061524e565b91509150600083600001516bffffffffffffffffffffffff16670de0b6b3a7640000856020015167ffffffffffffffff16866060015161ffff16898060200190610bab9190615281565b610bb6929150615315565b604088015163ffffffff16610bd6610bd160808d018d615281565b61228e565b51610be1919061532c565b610beb919061532c565b610bf59190615315565b610c199077ffffffffffffffffffffffffffffffffffffffffffffffff8616615315565b610c23919061533f565b610c2d919061532c565b9050610c55610c4260808801606089016148b3565b84610c5060408a018a61537a565b612382565b610c7977ffffffffffffffffffffffffffffffffffffffffffffffff8516836125ce565b610c83919061532c565b9695505050505050565b610c95612607565b610c9f828261267d565b5050565b610cab612607565b610cb4816129dd565b50565b601254600090610ce690700100000000000000000000000000000000900467ffffffffffffffff1660016153e2565b905090565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff161515938301939093526004548084166060840152049091166080820152610ce690612c76565b6000546001600160a01b03163314801590610dc157506002546001600160a01b03163314155b15610df8576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161480610e3f57506001600160a01b038116155b15610e76576040517f232cb97f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e80612d28565b1215610eb8576040517f02075e0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610c9f9082906001600160a01b038516906370a0823190602401602060405180830381865afa158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f9190615403565b6001600160a01b0385169190612de8565b610f58612607565b610c9f8282612e68565b6000610f6f600a83612fa3565b610fb0576040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610a83565b610fbb600a83612fb8565b92915050565b6000546001600160a01b03163314801590610fe757506002546001600160a01b03163314155b1561101e576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cb481612fcd565b6000546001600160a01b0316331480159061104d57506002546001600160a01b03163314155b15611084576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c906020015b60405180910390a150565b6000546001600160a01b0316331480159061111757506002546001600160a01b03163314155b1561114e576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c9f8282808060200260200160405190810160405280939291908181526020016000905b8282101561119f576111906040830286013681900381019061541c565b81526020019060010190611173565b5050505050613103565b6000546001600160a01b031633148015906111cf57506002546001600160a01b03163314155b15611206576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cb481613376565b6001546001600160a01b03163314611283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610a83565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6001600160a01b03811660009081526011602052604081205467ffffffffffffffff168015801561134b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b15610fbb576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa1580156113cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f3919061545b565b9392505050565b6060610ce6600d613585565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148a9190615478565b156114c1576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114cb8480615281565b9050602014611512576114de8480615281565b6040517f370d875f000000000000000000000000000000000000000000000000000000008152600401610a839291906154de565b600061151e8580615281565b81019061152b91906154f2565b90506001600160a01b038111806115425750600a81105b15611551576114de8580615281565b6000611563610bd16080880188615281565b905061158f6115756020880188615281565b835190915061158760408a018a61537a565b905087613592565b61160361159f604088018861537a565b808060200260200160405190810160405280939291908181526020016000905b828210156115eb576115dc6040830286013681900381019061550b565b815260200190600101906115bf565b50506006546001600160a01b031692506137b5915050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001661163d60808801606089016148b3565b6001600160a01b0316036116a1576012805486919060009061166e9084906bffffffffffffffffffffffff16615545565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506117c0565b6006546001600160a01b03166241e5be6116c16080890160608a016148b3565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa15801561174d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117719190615403565b601280546000906117919084906bffffffffffffffffffffffff16615545565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b6012546bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169116111561182d576040517fe5c7a49100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03841660009081526011602052604090205467ffffffffffffffff1615801561188557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b1561197d576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015611909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192d919061545b565b6001600160a01b038516600090815260116020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790555b60006040518061018001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020016012601081819054906101000a900467ffffffffffffffff166119dd9061556a565b825467ffffffffffffffff9182166101009390930a8381029083021990911617909255825260208083018a90526001600160a01b03891660408085018290526000918252601190925290812080546060909401939092611a3d911661556a565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200183600001518152602001600015158152602001846001600160a01b03168152602001888060200190611aa39190615281565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001611aea60408a018a61537a565b808060200260200160405190810160405280939291908181526020016000905b82821015611b3657611b276040830286013681900381019061550b565b81526020019060010190611b0a565b5050509183525050602001611b5160808a0160608b016148b3565b6001600160a01b0316815260006020909101529050611b90817f000000000000000000000000000000000000000000000000000000000000000061396e565b61016082015260005b611ba6604089018961537a565b9050811015611cf2576000611bbe60408a018a61537a565b83818110611bce57611bce615591565b905060400201803603810190611be4919061550b565b9050611bf38160000151610f62565b6001600160a01b0316639687544588611c0c8c80615281565b60208087015160408051928301815260008352517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b168152611c7a959493927f0000000000000000000000000000000000000000000000000000000000000000916004016155c0565b6000604051808303816000875af1158015611c99573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611cdf9190810190615618565b505080611ceb906156ca565b9050611b99565b507faffc45517195d6499808c643bd4a7b0ffeedf95bea5852840d7bfcf63f59e82181604051611d229190615746565b60405180910390a161016001519695505050505050565b6060600080611d486007613a78565b90508067ffffffffffffffff811115611d6357611d63614998565b604051908082528060200260200182016040528015611da857816020015b6040805180820190915260008082526020820152815260200190600190039081611d815790505b50925060005b81811015611e1a57600080611dc4600784613a83565b915091506040518060400160405280836001600160a01b031681526020018261ffff16815250868481518110611dfc57611dfc615591565b6020026020010181905250505080611e13906156ca565b9050611dae565b505060125491926c0100000000000000000000000090920463ffffffff16919050565b6000546001600160a01b03163314801590611e6357506002546001600160a01b03163314155b15611e9a576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cb4600382613aa1565b6000610ce6612d28565b60606000611ebd600a613c79565b67ffffffffffffffff811115611ed557611ed5614998565b604051908082528060200260200182016040528015611efe578160200160208202803683370190505b50905060005b8151811015611f5a57611f18600a82613c84565b50828281518110611f2b57611f2b615591565b60200260200101816001600160a01b03166001600160a01b03168152505080611f53906156ca565b9050611f04565b50919050565b611f68612607565b60128054821515790100000000000000000000000000000000000000000000000000027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff9091161790556040517fccf4daf6ab6430389f26b970595dab82a5881ad454770907e415ede27c8df032906110e690831515815260200190565b6000546001600160a01b0316331480159061200c57506002546001600160a01b03163314155b8015612020575061201e600733613c93565b155b15612057576040517f195db95800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff1660008190036120ab576040517f990e30bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012546bffffffffffffffffffffffff16818110156120f6576040517f8d0f71d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612100612d28565b1215612138576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060006121456007613a78565b905060005b8181101561223a57600080612160600784613a83565b9092509050600087612180836bffffffffffffffffffffffff8a16615315565b61218a919061533f565b90506121968187615883565b95506121da6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016846bffffffffffffffffffffffff8416612de8565b6040516bffffffffffffffffffffffff821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a250505080612233906156ca565b905061214a565b5050601280547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff929092169190911790555050565b612285612607565b610cb481613ca8565b60408051602081019091526000815260008290036122e45750604080516020810190915267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152610fbb565b7f97a657c90000000000000000000000000000000000000000000000000000000061230f83856158a8565b7fffffffff000000000000000000000000000000000000000000000000000000001614612368576040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61237582600481866158f0565b8101906113f3919061591a565b6000818082036123965760009150506125c6565b60005b818110156125c35760008585838181106123b5576123b5615591565b9050604002018036038101906123cb919061550b565b80516001600160a01b031660009081526010602090815260408083208151606081018352905463ffffffff8082168352640100000000820416938201939093526801000000000000000090920461ffff16908201819052929350911561252257825189906001600160a01b038c81169116146124cc5760065484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa1580156124a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c9919061595c565b90505b620186a0836040015161ffff1661250a86602001518477ffffffffffffffffffffffffffffffffffffffffffffffff16613d8390919063ffffffff16565b6125149190615315565b61251e919061533f565b9150505b815160009061253e9063ffffffff16662386f26fc10000615315565b90506000836020015163ffffffff16662386f26fc1000061255f9190615315565b9050818310156125715781925061257d565b8083111561257d578092505b6125a177ffffffffffffffffffffffffffffffffffffffffffffffff8c16846125ce565b6125ab908961532c565b97505050505050806125bc906156ca565b9050612399565b50505b949350505050565b600077ffffffffffffffffffffffffffffffffffffffffffffffff83166125fd83670de0b6b3a7640000615315565b6113f3919061533f565b6000546001600160a01b0316331461267b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610a83565b565b60005b82518110156127de57600083828151811061269d5761269d615591565b602002602001015160000151905060008483815181106126bf576126bf615591565b60200260200101516020015190506126e182600a612fa390919063ffffffff16565b612722576040517f73913ebd0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610a83565b6001600160a01b038116612737600a84612fb8565b6001600160a01b031614612777576040517f6cc7b99800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612782600a83613db2565b156127cb57604080516001600160a01b038085168252831660208201527f987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c910160405180910390a15b5050806127d7906156ca565b9050612680565b5060005b81518110156129d85760008282815181106127ff576127ff615591565b6020026020010151600001519050600083838151811061282157612821615591565b602002602001015160200151905060006001600160a01b0316826001600160a01b0316148061285757506001600160a01b038116155b1561288e576040517f6c2a418000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f09190615977565b6001600160a01b0316826001600160a01b03161461293a576040517f6cc7b99800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612946600a8383613dc7565b1561299357604080516001600160a01b038085168252831660208201527f95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c910160405180910390a16129c5565b6040517f3caf458500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050806129d1906156ca565b90506127e2565b505050565b60408101516001600160a01b0316612a21576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600580546020808501516001600160a01b039485167fffffffffffffffffffff00000000000000000000000000000000000000000000909316929092177401000000000000000000000000000000000000000061ffff909316830217909255604080850151600680546060808901516080808b0151958a167fffffffffffffffff0000000000000000000000000000000000000000000000009094169390931763ffffffff9091169096029590951777ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff9485160217909155825160e0810184527f0000000000000000000000000000000000000000000000000000000000000000871681527f00000000000000000000000000000000000000000000000000000000000000008316958101959095527f00000000000000000000000000000000000000000000000000000000000000008216858401527f0000000000000000000000000000000000000000000000000000000000000000909116928401929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16918301919091527f0000000000000000000000000000000000000000000000000000000000000000831660a08301527f000000000000000000000000000000000000000000000000000000000000000090921660c082015290517fdd226617d8d287f40a64c54741bbcdc492b3e096ef16bc5273a18cb6ab85f124916110e6918490615994565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152612d0482606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642612ce89190615a69565b85608001516fffffffffffffffffffffffffffffffff16613ddd565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6012546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000916bffffffffffffffffffffffff16907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dde9190615403565b610ce69190615a7c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526129d8908490613e05565b60005b8251811015612ef9576000838281518110612e8857612e88615591565b60200260200101519050612ea681600d613f0490919063ffffffff16565b15612ee8576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50612ef2816156ca565b9050612e6b565b5060005b81518110156129d8576000828281518110612f1a57612f1a615591565b6020026020010151905060006001600160a01b0316816001600160a01b031603612f445750612f93565b612f4f600d82613f19565b15612f91576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b612f9c816156ca565b9050612efd565b60006113f3836001600160a01b038416613f2e565b60006113f3836001600160a01b038416613f3a565b60005b81518110156130d3576000828281518110612fed57612fed615591565b60209081029190910181015160408051606080820183528385015163ffffffff90811683528385015181168387019081529185015161ffff90811684860190815295516001600160a01b03166000908152601090975293909520915182549151945190931668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff948616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921693909516929092179190911791909116919091179055506130cc816156ca565b9050612fd0565b507fcb0c5f472d325cf0c56953fc81870ddd80d0d3c9a3fbfe777002d75f380dfb81816040516110e69190615a9c565b80516040811115613140576040517fb5a10cfa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff161580159061318e575060125463ffffffff6c010000000000000000000000008204166bffffffffffffffffffffffff90911610155b1561319b5761319b611fe6565b60006131a76007613a78565b90505b80156131e95760006131c86131c0600184615a69565b600790613a83565b5090506131d6600782613f46565b5050806131e290615b16565b90506131aa565b506000805b828110156132f757600084828151811061320a5761320a615591565b6020026020010151600001519050600085838151811061322c5761322c615591565b60200260200101516020015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316148061328157506001600160a01b038216155b156132c3576040517f4de938d10000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610a83565b6132d360078361ffff8416613f5b565b506132e261ffff821685615b4b565b93505050806132f0906156ca565b90506131ee565b50601280547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd24906133699083908690615b68565b60405180910390a1505050565b60005b815181101561355557600082828151811061339657613396615591565b6020908102919091018101516040805160a08082018352828401516bffffffffffffffffffffffff90811683528486015167ffffffffffffffff90811684880190815260608088015163ffffffff9081168789019081526080808b015161ffff908116948a01948552978b0151151590890190815299516001600160a01b03166000908152600f909b529790992095518654925197519151985115157a010000000000000000000000000000000000000000000000000000027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff999096167801000000000000000000000000000000000000000000000000027fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff92909a167401000000000000000000000000000000000000000002919091167fffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff979093166c01000000000000000000000000027fffffffffffffffffffffffff000000000000000000000000000000000000000090921693169290921791909117939093169290921793909317919091161790555061354e816156ca565b9050613379565b507ffba339fca97870ffdfaedbae3745db5e6de1a6909dfd0e0dbb56917469ffe236816040516110e69190615b87565b606060006113f383613f71565b6001600160a01b0381166135d2576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546001600160a01b03163314613616576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065474010000000000000000000000000000000000000000900463ffffffff168085111561367b576040517f869337890000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610a83565b6006547801000000000000000000000000000000000000000000000000900467ffffffffffffffff168411156136dd576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055474010000000000000000000000000000000000000000900461ffff16831115613735576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601254790100000000000000000000000000000000000000000000000000900460ff16801561376c575061376a600d83613fcd565b155b156137ae576040517fd0d259760000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610a83565b5050505050565b81516000805b8281101561395a576000846001600160a01b031663d02641a08784815181106137e6576137e6615591565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b0390911660048201526024016040805180830381865afa15801561384d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138719190615c1f565b51905077ffffffffffffffffffffffffffffffffffffffffffffffff81166000036138f2578582815181106138a8576138a8615591565b6020908102919091010151516040517f9a655f7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610a83565b61393c86838151811061390757613907615591565b6020026020010151602001518277ffffffffffffffffffffffffffffffffffffffffffffffff16613d8390919063ffffffff16565b613946908461532c565b92505080613953906156ca565b90506137bb565b506139686003826000613fef565b50505050565b60008060001b828460200151856080015186606001518760e00151886101000151805190602001208961012001516040516020016139ac9190615c52565b604051602081830303815290604052805190602001208a60a001518b60c001518c61014001518d60400151604051602001613a5a9c9b9a999897969594939291909b8c5260208c019a909a5267ffffffffffffffff98891660408c01529690971660608a01526001600160a01b0394851660808a015292841660a089015260c088019190915260e0870152610100860152911515610120850152166101408301526101608201526101800190565b60405160208183030381529060405280519060200120905092915050565b6000610fbb8261433e565b6000808080613a928686614349565b909450925050505b9250929050565b8154600090613aca90700100000000000000000000000000000000900463ffffffff1642615a69565b90508015613b6c5760018301548354613b12916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416613ddd565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613b92916fffffffffffffffffffffffffffffffff9081169116614374565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906133699084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b6000610fbb82613a78565b6000808080613a928686613a83565b60006113f3836001600160a01b03841661438a565b336001600160a01b03821603613d1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610a83565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a76400006125fd8377ffffffffffffffffffffffffffffffffffffffffffffffff8616615315565b60006113f3836001600160a01b038416614396565b60006125c6846001600160a01b038516846143a2565b6000613dfc85613ded8486615315565b613df7908761532c565b614374565b95945050505050565b6000613e5a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143b89092919063ffffffff16565b8051909150156129d85780806020019051810190613e789190615478565b6129d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a83565b60006113f3836001600160a01b0384166143c7565b60006113f3836001600160a01b0384166144c1565b60006113f3838361438a565b60006113f38383614510565b60006113f3836001600160a01b03841661459a565b60006125c6846001600160a01b038516846145b7565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fc157602002820191906000526020600020905b815481526020019060010190808311613fad575b50505050509050919050565b6001600160a01b038116600090815260018301602052604081205415156113f3565b825474010000000000000000000000000000000000000000900460ff161580614016575081155b1561402057505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061406690700100000000000000000000000000000000900463ffffffff1642615a69565b9050801561412657818311156140a8576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546140e29083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613ddd565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156141c3576001600160a01b038416614178576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610a83565b6040517f1a76572a00000000000000000000000000000000000000000000000000000000815260048101839052602481018690526001600160a01b0385166044820152606401610a83565b848310156142bc5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906142079082615a69565b614211878a615a69565b61421b919061532c565b614225919061533f565b90506001600160a01b038616614271576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610a83565b6040517fd0c8d23a00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526001600160a01b0387166044820152606401610a83565b6142c68584615a69565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000610fbb826145d4565b6000808061435785856145de565b600081815260029690960160205260409095205494959350505050565b600081831061438357816113f3565b5090919050565b60006113f383836145ea565b60006113f3838361459a565b60006125c684846001600160a01b0385166145b7565b60606125c68484600085614602565b600081815260018301602052604081205480156144b05760006143eb600183615a69565b85549091506000906143ff90600190615a69565b905081811461446457600086600001828154811061441f5761441f615591565b906000526020600020015490508087600001848154811061444257614442615591565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061447557614475615c65565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610fbb565b6000915050610fbb565b5092915050565b600081815260018301602052604081205461450857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610fbb565b506000610fbb565b6000818152600283016020526040812054801515806145345750614534848461438a565b6113f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606401610a83565b600081815260028301602052604081208190556113f3838361470e565b600082815260028401602052604081208290556125c6848461471a565b6000610fbb825490565b60006113f38383614726565b600081815260018301602052604081205415156113f3565b606082471015614694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610a83565b600080866001600160a01b031685876040516146b09190615c94565b60006040518083038185875af1925050503d80600081146146ed576040519150601f19603f3d011682016040523d82523d6000602084013e6146f2565b606091505b509150915061470387838387614750565b979650505050505050565b60006113f383836143c7565b60006113f383836144c1565b600082600001828154811061473d5761473d615591565b9060005260206000200154905092915050565b606083156147d95782516000036147d2576001600160a01b0385163b6147d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a83565b50816125c6565b6125c683838151156147ee5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a83919061493e565b60e08101610fbb82846001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015280606085015116606086015250506bffffffffffffffffffffffff60808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b6001600160a01b0381168114610cb457600080fd5b6000602082840312156148c557600080fd5b81356113f38161489e565b60005b838110156148eb5781810151838201526020016148d3565b50506000910152565b6000815180845261490c8160208601602086016148d0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006113f360208301846148f4565b600060a08284031215611f5a57600080fd5b60006020828403121561497557600080fd5b813567ffffffffffffffff81111561498c57600080fd5b6125c684828501614951565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156149ea576149ea614998565b60405290565b6040516080810167ffffffffffffffff811182821017156149ea576149ea614998565b60405160c0810167ffffffffffffffff811182821017156149ea576149ea614998565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614a7d57614a7d614998565b604052919050565b600067ffffffffffffffff821115614a9f57614a9f614998565b5060051b60200190565b600082601f830112614aba57600080fd5b81356020614acf614aca83614a85565b614a36565b82815260069290921b84018101918181019086841115614aee57600080fd5b8286015b84811015614b3f5760408189031215614b0b5760008081fd5b614b136149c7565b8135614b1e8161489e565b815281850135614b2d8161489e565b81860152835291830191604001614af2565b509695505050505050565b60008060408385031215614b5d57600080fd5b823567ffffffffffffffff80821115614b7557600080fd5b614b8186838701614aa9565b93506020850135915080821115614b9757600080fd5b50614ba485828601614aa9565b9150509250929050565b803561ffff81168114614bc057600080fd5b919050565b803563ffffffff81168114614bc057600080fd5b67ffffffffffffffff81168114610cb457600080fd5b600060a08284031215614c0157600080fd5b60405160a0810181811067ffffffffffffffff82111715614c2457614c24614998565b6040528235614c328161489e565b8152614c4060208401614bae565b60208201526040830135614c538161489e565b6040820152614c6460608401614bc5565b60608201526080830135614c7781614bd9565b60808201529392505050565b60008060408385031215614c9657600080fd5b8235614ca18161489e565b91506020830135614cb18161489e565b809150509250929050565b600082601f830112614ccd57600080fd5b81356020614cdd614aca83614a85565b82815260059290921b84018101918181019086841115614cfc57600080fd5b8286015b84811015614b3f578035614d138161489e565b8352918301918301614d00565b60008060408385031215614d3357600080fd5b823567ffffffffffffffff80821115614d4b57600080fd5b614d5786838701614cbc565b93506020850135915080821115614d6d57600080fd5b50614ba485828601614cbc565b60006020808385031215614d8d57600080fd5b823567ffffffffffffffff811115614da457600080fd5b8301601f81018513614db557600080fd5b8035614dc3614aca82614a85565b81815260079190911b82018301908381019087831115614de257600080fd5b928401925b828410156147035760808489031215614e005760008081fd5b614e086149f0565b8435614e138161489e565b8152614e20858701614bc5565b868201526040614e31818701614bc5565b908201526060614e42868201614bae565b9082015282526080939093019290840190614de7565b60a08101610fbb82846001600160a01b0380825116835261ffff60208301511660208401528060408301511660408401525063ffffffff606082015116606083015267ffffffffffffffff60808201511660808301525050565b60008060208385031215614ec557600080fd5b823567ffffffffffffffff80821115614edd57600080fd5b818501915085601f830112614ef157600080fd5b813581811115614f0057600080fd5b8660208260061b8501011115614f1557600080fd5b60209290920196919550909350505050565b8015158114610cb457600080fd5b8035614bc081614f27565b60006020808385031215614f5357600080fd5b823567ffffffffffffffff811115614f6a57600080fd5b8301601f81018513614f7b57600080fd5b8035614f89614aca82614a85565b81815260c09182028301840191848201919088841115614fa857600080fd5b938501935b838510156150525780858a031215614fc55760008081fd5b614fcd614a13565b8535614fd88161489e565b815285870135614fe781614bd9565b818801526040868101356bffffffffffffffffffffffff8116811461500c5760008081fd5b90820152606061501d878201614bc5565b90820152608061502e878201614bae565b9082015260a061503f878201614f35565b9082015283529384019391850191614fad565b50979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561509f5783516001600160a01b03168352928401929184019160010161507a565b50909695505050505050565b6000806000606084860312156150c057600080fd5b833567ffffffffffffffff8111156150d757600080fd5b6150e386828701614951565b9350506020840135915060408401356150fb8161489e565b809150509250925092565b600081518084526020808501945080840160005b8381101561514e57815180516001600160a01b0316885283015161ffff16838801526040909601959082019060010161511a565b509495945050505050565b60408152600061516c6040830185615106565b90508260208301529392505050565b80356fffffffffffffffffffffffffffffffff81168114614bc057600080fd5b6000606082840312156151ad57600080fd5b6040516060810181811067ffffffffffffffff821117156151d0576151d0614998565b60405282356151de81614f27565b81526151ec6020840161517b565b60208201526151fd6040840161517b565b60408201529392505050565b60006020828403121561521b57600080fd5b81356113f381614f27565b805177ffffffffffffffffffffffffffffffffffffffffffffffff81168114614bc057600080fd5b6000806040838503121561526157600080fd5b61526a83615226565b915061527860208401615226565b90509250929050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126152b657600080fd5b83018035915067ffffffffffffffff8211156152d157600080fd5b602001915036819003821315613a9a57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610fbb57610fbb6152e6565b80820180821115610fbb57610fbb6152e6565b600082615375577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126153af57600080fd5b83018035915067ffffffffffffffff8211156153ca57600080fd5b6020019150600681901b3603821315613a9a57600080fd5b67ffffffffffffffff8181168382160190808211156144ba576144ba6152e6565b60006020828403121561541557600080fd5b5051919050565b60006040828403121561542e57600080fd5b6154366149c7565b82356154418161489e565b815261544f60208401614bae565b60208201529392505050565b60006020828403121561546d57600080fd5b81516113f381614bd9565b60006020828403121561548a57600080fd5b81516113f381614f27565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815260006125c6602083018486615495565b60006020828403121561550457600080fd5b5035919050565b60006040828403121561551d57600080fd5b6155256149c7565b82356155308161489e565b81526020928301359281019290925250919050565b6bffffffffffffffffffffffff8181168382160190808211156144ba576144ba6152e6565b600067ffffffffffffffff808316818103615587576155876152e6565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6001600160a01b038716815260a0602082015260006155e360a083018789615495565b85604084015267ffffffffffffffff85166060840152828103608084015261560b81856148f4565b9998505050505050505050565b60006020828403121561562a57600080fd5b815167ffffffffffffffff8082111561564257600080fd5b818401915084601f83011261565657600080fd5b81518181111561566857615668614998565b61569960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614a36565b91508082528560208285010111156156b057600080fd5b6156c18160208401602086016148d0565b50949350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156fb576156fb6152e6565b5060010190565b600081518084526020808501945080840160005b8381101561514e57815180516001600160a01b031688528301518388015260409096019590820190600101615716565b6020815261576160208201835167ffffffffffffffff169052565b6000602083015161577e604084018267ffffffffffffffff169052565b506040830151606083015260608301516157a360808401826001600160a01b03169052565b50608083015167ffffffffffffffff811660a08401525060a083015160c083015260c08301516157d760e084018215159052565b5060e08301516101006157f4818501836001600160a01b03169052565b8085015191505061018061012081818601526158146101a08601846148f4565b92508086015190506101407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086850301818701526158528483615702565b935080870151915050610160615872818701836001600160a01b03169052565b959095015193019290925250919050565b6bffffffffffffffffffffffff8281168282160390808211156144ba576144ba6152e6565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156158e85780818660040360031b1b83161692505b505092915050565b6000808585111561590057600080fd5b8386111561590d57600080fd5b5050820193919092039150565b60006020828403121561592c57600080fd5b6040516020810181811067ffffffffffffffff8211171561594f5761594f614998565b6040529135825250919050565b60006020828403121561596e57600080fd5b6113f382615226565b60006020828403121561598957600080fd5b81516113f38161489e565b6101808101615a1182856001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015280606085015116606086015250506bffffffffffffffffffffffff60808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b82516001600160a01b0390811660e0840152602084015161ffff16610100840152604084015116610120830152606083015163ffffffff16610140830152608083015167ffffffffffffffff166101608301526113f3565b81810381811115610fbb57610fbb6152e6565b81810360008312801583831316838312821617156144ba576144ba6152e6565b602080825282518282018190526000919060409081850190868401855b82811015615b0957815180516001600160a01b031685528681015163ffffffff9081168887015286820151168686015260609081015161ffff169085015260809093019290850190600101615ab9565b5091979650505050505050565b600081615b2557615b256152e6565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b63ffffffff8181168382160190808211156144ba576144ba6152e6565b63ffffffff831681526040602082015260006125c66040830184615106565b602080825282518282018190526000919060409081850190868401855b82811015615b0957815180516001600160a01b031685528681015167ffffffffffffffff1687860152858101516bffffffffffffffffffffffff168686015260608082015163ffffffff169086015260808082015161ffff169086015260a09081015115159085015260c09093019290850190600101615ba4565b600060408284031215615c3157600080fd5b615c396149c7565b615c4283615226565b8152602083015161544f81614bd9565b6020815260006113f36020830184615702565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251615ca68184602087016148d0565b919091019291505056fea164736f6c6343000813000a", -} - -var EVM2EVMOnRampABI = EVM2EVMOnRampMetaData.ABI - -var EVM2EVMOnRampBin = EVM2EVMOnRampMetaData.Bin - -func DeployEVM2EVMOnRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMOnRampStaticConfig, dynamicConfig EVM2EVMOnRampDynamicConfig, tokensAndPools []InternalPoolUpdate, allowlist []common.Address, rateLimiterConfig RateLimiterConfig, feeTokenConfigs []EVM2EVMOnRampFeeTokenConfigArgs, tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs, nopsAndWeights []EVM2EVMOnRampNopAndWeight) (common.Address, *types.Transaction, *EVM2EVMOnRamp, error) { - parsed, err := EVM2EVMOnRampMetaData.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(EVM2EVMOnRampBin), backend, staticConfig, dynamicConfig, tokensAndPools, allowlist, rateLimiterConfig, feeTokenConfigs, tokenTransferFeeConfigArgs, nopsAndWeights) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &EVM2EVMOnRamp{EVM2EVMOnRampCaller: EVM2EVMOnRampCaller{contract: contract}, EVM2EVMOnRampTransactor: EVM2EVMOnRampTransactor{contract: contract}, EVM2EVMOnRampFilterer: EVM2EVMOnRampFilterer{contract: contract}}, nil -} - -type EVM2EVMOnRamp struct { - address common.Address - abi abi.ABI - EVM2EVMOnRampCaller - EVM2EVMOnRampTransactor - EVM2EVMOnRampFilterer -} - -type EVM2EVMOnRampCaller struct { - contract *bind.BoundContract -} - -type EVM2EVMOnRampTransactor struct { - contract *bind.BoundContract -} - -type EVM2EVMOnRampFilterer struct { - contract *bind.BoundContract -} - -type EVM2EVMOnRampSession struct { - Contract *EVM2EVMOnRamp - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type EVM2EVMOnRampCallerSession struct { - Contract *EVM2EVMOnRampCaller - CallOpts bind.CallOpts -} - -type EVM2EVMOnRampTransactorSession struct { - Contract *EVM2EVMOnRampTransactor - TransactOpts bind.TransactOpts -} - -type EVM2EVMOnRampRaw struct { - Contract *EVM2EVMOnRamp -} - -type EVM2EVMOnRampCallerRaw struct { - Contract *EVM2EVMOnRampCaller -} - -type EVM2EVMOnRampTransactorRaw struct { - Contract *EVM2EVMOnRampTransactor -} - -func NewEVM2EVMOnRamp(address common.Address, backend bind.ContractBackend) (*EVM2EVMOnRamp, error) { - abi, err := abi.JSON(strings.NewReader(EVM2EVMOnRampABI)) - if err != nil { - return nil, err - } - contract, err := bindEVM2EVMOnRamp(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &EVM2EVMOnRamp{address: address, abi: abi, EVM2EVMOnRampCaller: EVM2EVMOnRampCaller{contract: contract}, EVM2EVMOnRampTransactor: EVM2EVMOnRampTransactor{contract: contract}, EVM2EVMOnRampFilterer: EVM2EVMOnRampFilterer{contract: contract}}, nil -} - -func NewEVM2EVMOnRampCaller(address common.Address, caller bind.ContractCaller) (*EVM2EVMOnRampCaller, error) { - contract, err := bindEVM2EVMOnRamp(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampCaller{contract: contract}, nil -} - -func NewEVM2EVMOnRampTransactor(address common.Address, transactor bind.ContractTransactor) (*EVM2EVMOnRampTransactor, error) { - contract, err := bindEVM2EVMOnRamp(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampTransactor{contract: contract}, nil -} - -func NewEVM2EVMOnRampFilterer(address common.Address, filterer bind.ContractFilterer) (*EVM2EVMOnRampFilterer, error) { - contract, err := bindEVM2EVMOnRamp(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampFilterer{contract: contract}, nil -} - -func bindEVM2EVMOnRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EVM2EVMOnRampMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMOnRamp.Contract.EVM2EVMOnRampCaller.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.EVM2EVMOnRampTransactor.contract.Transfer(opts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.EVM2EVMOnRampTransactor.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMOnRamp.Contract.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.contract.Transfer(opts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "currentRateLimiterState") - - if err != nil { - return *new(RateLimiterTokenBucket), err - } - - out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMOnRamp.Contract.CurrentRateLimiterState(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMOnRamp.Contract.CurrentRateLimiterState(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetAllowList() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetAllowList(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetAllowList() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetAllowList(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getAllowListEnabled") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetAllowListEnabled() (bool, error) { - return _EVM2EVMOnRamp.Contract.GetAllowListEnabled(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetAllowListEnabled() (bool, error) { - return _EVM2EVMOnRamp.Contract.GetAllowListEnabled(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMOnRampDynamicConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(EVM2EVMOnRampDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampDynamicConfig)).(*EVM2EVMOnRampDynamicConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetDynamicConfig() (EVM2EVMOnRampDynamicConfig, error) { - return _EVM2EVMOnRamp.Contract.GetDynamicConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetDynamicConfig() (EVM2EVMOnRampDynamicConfig, error) { - return _EVM2EVMOnRamp.Contract.GetDynamicConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getExpectedNextSequenceNumber") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetExpectedNextSequenceNumber(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetExpectedNextSequenceNumber(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetFee(opts *bind.CallOpts, message ClientEVM2AnyMessage) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getFee", message) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetFee(message ClientEVM2AnyMessage) (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetFee(&_EVM2EVMOnRamp.CallOpts, message) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetFee(message ClientEVM2AnyMessage) (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetFee(&_EVM2EVMOnRamp.CallOpts, message) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetFeeTokenConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getFeeTokenConfig", token) - - if err != nil { - return *new(EVM2EVMOnRampFeeTokenConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampFeeTokenConfig)).(*EVM2EVMOnRampFeeTokenConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetFeeTokenConfig(token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) { - return _EVM2EVMOnRamp.Contract.GetFeeTokenConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetFeeTokenConfig(token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) { - return _EVM2EVMOnRamp.Contract.GetFeeTokenConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetNopFeesJuels(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getNopFeesJuels") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetNopFeesJuels() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetNopFeesJuels(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetNopFeesJuels() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetNopFeesJuels(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetNops(opts *bind.CallOpts) (GetNops, - - error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getNops") - - outstruct := new(GetNops) - if err != nil { - return *outstruct, err - } - - outstruct.NopsAndWeights = *abi.ConvertType(out[0], new([]EVM2EVMOnRampNopAndWeight)).(*[]EVM2EVMOnRampNopAndWeight) - outstruct.WeightsTotal = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetNops() (GetNops, - - error) { - return _EVM2EVMOnRamp.Contract.GetNops(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetNops() (GetNops, - - error) { - return _EVM2EVMOnRamp.Contract.GetNops(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getPoolBySourceToken", sourceToken) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetPoolBySourceToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMOnRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetPoolBySourceToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMOnRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getSenderNonce", sender) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetSenderNonce(sender common.Address) (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetSenderNonce(&_EVM2EVMOnRamp.CallOpts, sender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetSenderNonce(sender common.Address) (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetSenderNonce(&_EVM2EVMOnRamp.CallOpts, sender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetStaticConfig(opts *bind.CallOpts) (EVM2EVMOnRampStaticConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(EVM2EVMOnRampStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampStaticConfig)).(*EVM2EVMOnRampStaticConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetStaticConfig() (EVM2EVMOnRampStaticConfig, error) { - return _EVM2EVMOnRamp.Contract.GetStaticConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetStaticConfig() (EVM2EVMOnRampStaticConfig, error) { - return _EVM2EVMOnRamp.Contract.GetStaticConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getSupportedTokens") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetSupportedTokens() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetSupportedTokens(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetSupportedTokens() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetSupportedTokens(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getTokenLimitAdmin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getTokenTransferFeeConfig", token) - - if err != nil { - return *new(EVM2EVMOnRampTokenTransferFeeConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampTokenTransferFeeConfig)).(*EVM2EVMOnRampTokenTransferFeeConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetTokenTransferFeeConfig(token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) { - return _EVM2EVMOnRamp.Contract.GetTokenTransferFeeConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetTokenTransferFeeConfig(token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) { - return _EVM2EVMOnRamp.Contract.GetTokenTransferFeeConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampSession) LinkAvailableForPayment() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.LinkAvailableForPayment(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) LinkAvailableForPayment() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.LinkAvailableForPayment(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampSession) Owner() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.Owner(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) Owner() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.Owner(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) TypeAndVersion() (string, error) { - return _EVM2EVMOnRamp.Contract.TypeAndVersion(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) TypeAndVersion() (string, error) { - return _EVM2EVMOnRamp.Contract.TypeAndVersion(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "acceptOwnership") -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.AcceptOwnership(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.AcceptOwnership(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "applyAllowListUpdates", removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyAllowListUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyAllowListUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) ApplyPoolUpdates(opts *bind.TransactOpts, removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "applyPoolUpdates", removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) ApplyPoolUpdates(removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyPoolUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) ApplyPoolUpdates(removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyPoolUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) ForwardFromRouter(opts *bind.TransactOpts, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "forwardFromRouter", message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) ForwardFromRouter(message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ForwardFromRouter(&_EVM2EVMOnRamp.TransactOpts, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) ForwardFromRouter(message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ForwardFromRouter(&_EVM2EVMOnRamp.TransactOpts, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) PayNops(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "payNops") -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) PayNops() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.PayNops(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) PayNops() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.PayNops(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setAdmin", newAdmin) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAdmin(&_EVM2EVMOnRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAdmin(&_EVM2EVMOnRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetAllowListEnabled(opts *bind.TransactOpts, enabled bool) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setAllowListEnabled", enabled) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetAllowListEnabled(enabled bool) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAllowListEnabled(&_EVM2EVMOnRamp.TransactOpts, enabled) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetAllowListEnabled(enabled bool) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAllowListEnabled(&_EVM2EVMOnRamp.TransactOpts, enabled) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetDynamicConfig(dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetDynamicConfig(&_EVM2EVMOnRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetDynamicConfig(dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetDynamicConfig(&_EVM2EVMOnRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetFeeTokenConfig(opts *bind.TransactOpts, feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setFeeTokenConfig", feeTokenConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetFeeTokenConfig(feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetFeeTokenConfig(&_EVM2EVMOnRamp.TransactOpts, feeTokenConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetFeeTokenConfig(feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetFeeTokenConfig(&_EVM2EVMOnRamp.TransactOpts, feeTokenConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetNops(opts *bind.TransactOpts, nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setNops", nopsAndWeights) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetNops(nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetNops(&_EVM2EVMOnRamp.TransactOpts, nopsAndWeights) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetNops(nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetNops(&_EVM2EVMOnRamp.TransactOpts, nopsAndWeights) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setRateLimiterConfig", config) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetRateLimiterConfig(&_EVM2EVMOnRamp.TransactOpts, config) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetRateLimiterConfig(&_EVM2EVMOnRamp.TransactOpts, config) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetTokenTransferFeeConfig(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setTokenTransferFeeConfig", tokenTransferFeeConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetTokenTransferFeeConfig(tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetTokenTransferFeeConfig(&_EVM2EVMOnRamp.TransactOpts, tokenTransferFeeConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetTokenTransferFeeConfig(tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetTokenTransferFeeConfig(&_EVM2EVMOnRamp.TransactOpts, tokenTransferFeeConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "transferOwnership", to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.TransferOwnership(&_EVM2EVMOnRamp.TransactOpts, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.TransferOwnership(&_EVM2EVMOnRamp.TransactOpts, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) WithdrawNonLinkFees(opts *bind.TransactOpts, feeToken common.Address, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "withdrawNonLinkFees", feeToken, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) WithdrawNonLinkFees(feeToken common.Address, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.WithdrawNonLinkFees(&_EVM2EVMOnRamp.TransactOpts, feeToken, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) WithdrawNonLinkFees(feeToken common.Address, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.WithdrawNonLinkFees(&_EVM2EVMOnRamp.TransactOpts, feeToken, to) -} - -type EVM2EVMOnRampAdminSetIterator struct { - Event *EVM2EVMOnRampAdminSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAdminSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAdminSet) - 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(EVM2EVMOnRampAdminSet) - 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 *EVM2EVMOnRampAdminSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAdminSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAdminSet struct { - NewAdmin common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAdminSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAdminSetIterator{contract: _EVM2EVMOnRamp.contract, event: "AdminSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAdminSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampAdminSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AdminSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAdminSet(log types.Log) (*EVM2EVMOnRampAdminSet, error) { - event := new(EVM2EVMOnRampAdminSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AdminSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampAllowListAddIterator struct { - Event *EVM2EVMOnRampAllowListAdd - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAllowListAddIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAllowListAdd) - 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(EVM2EVMOnRampAllowListAdd) - 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 *EVM2EVMOnRampAllowListAddIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAllowListAddIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAllowListAdd struct { - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListAddIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AllowListAdd") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAllowListAddIterator{contract: _EVM2EVMOnRamp.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListAdd) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.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(EVM2EVMOnRampAllowListAdd) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAllowListAdd(log types.Log) (*EVM2EVMOnRampAllowListAdd, error) { - event := new(EVM2EVMOnRampAllowListAdd) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListAdd", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampAllowListEnabledSetIterator struct { - Event *EVM2EVMOnRampAllowListEnabledSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAllowListEnabledSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAllowListEnabledSet) - 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(EVM2EVMOnRampAllowListEnabledSet) - 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 *EVM2EVMOnRampAllowListEnabledSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAllowListEnabledSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAllowListEnabledSet struct { - Enabled bool - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAllowListEnabledSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListEnabledSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AllowListEnabledSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAllowListEnabledSetIterator{contract: _EVM2EVMOnRamp.contract, event: "AllowListEnabledSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAllowListEnabledSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListEnabledSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "AllowListEnabledSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampAllowListEnabledSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListEnabledSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAllowListEnabledSet(log types.Log) (*EVM2EVMOnRampAllowListEnabledSet, error) { - event := new(EVM2EVMOnRampAllowListEnabledSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListEnabledSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampAllowListRemoveIterator struct { - Event *EVM2EVMOnRampAllowListRemove - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAllowListRemoveIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAllowListRemove) - 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(EVM2EVMOnRampAllowListRemove) - 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 *EVM2EVMOnRampAllowListRemoveIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAllowListRemoveIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAllowListRemove struct { - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListRemoveIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AllowListRemove") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAllowListRemoveIterator{contract: _EVM2EVMOnRamp.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListRemove) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.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(EVM2EVMOnRampAllowListRemove) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAllowListRemove(log types.Log) (*EVM2EVMOnRampAllowListRemove, error) { - event := new(EVM2EVMOnRampAllowListRemove) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListRemove", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampCCIPSendRequestedIterator struct { - Event *EVM2EVMOnRampCCIPSendRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampCCIPSendRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampCCIPSendRequested) - 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(EVM2EVMOnRampCCIPSendRequested) - 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 *EVM2EVMOnRampCCIPSendRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampCCIPSendRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampCCIPSendRequested struct { - Message InternalEVM2EVMMessage - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterCCIPSendRequested(opts *bind.FilterOpts) (*EVM2EVMOnRampCCIPSendRequestedIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "CCIPSendRequested") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampCCIPSendRequestedIterator{contract: _EVM2EVMOnRamp.contract, event: "CCIPSendRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampCCIPSendRequested) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "CCIPSendRequested") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampCCIPSendRequested) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "CCIPSendRequested", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseCCIPSendRequested(log types.Log) (*EVM2EVMOnRampCCIPSendRequested, error) { - event := new(EVM2EVMOnRampCCIPSendRequested) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampConfigSetIterator struct { - Event *EVM2EVMOnRampConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampConfigSet) - 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(EVM2EVMOnRampConfigSet) - 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 *EVM2EVMOnRampConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampConfigSet struct { - StaticConfig EVM2EVMOnRampStaticConfig - DynamicConfig EVM2EVMOnRampDynamicConfig - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampConfigSetIterator{contract: _EVM2EVMOnRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.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(EVM2EVMOnRampConfigSet) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMOnRampConfigSet, error) { - event := new(EVM2EVMOnRampConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampFeeConfigSetIterator struct { - Event *EVM2EVMOnRampFeeConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampFeeConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampFeeConfigSet) - 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(EVM2EVMOnRampFeeConfigSet) - 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 *EVM2EVMOnRampFeeConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampFeeConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampFeeConfigSet struct { - FeeConfig []EVM2EVMOnRampFeeTokenConfigArgs - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampFeeConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "FeeConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampFeeConfigSetIterator{contract: _EVM2EVMOnRamp.contract, event: "FeeConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampFeeConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "FeeConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "FeeConfigSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseFeeConfigSet(log types.Log) (*EVM2EVMOnRampFeeConfigSet, error) { - event := new(EVM2EVMOnRampFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "FeeConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampNopPaidIterator struct { - Event *EVM2EVMOnRampNopPaid - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampNopPaidIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampNopPaid) - 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(EVM2EVMOnRampNopPaid) - 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 *EVM2EVMOnRampNopPaidIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampNopPaidIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampNopPaid struct { - Nop common.Address - Amount *big.Int - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterNopPaid(opts *bind.FilterOpts, nop []common.Address) (*EVM2EVMOnRampNopPaidIterator, error) { - - var nopRule []interface{} - for _, nopItem := range nop { - nopRule = append(nopRule, nopItem) - } - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "NopPaid", nopRule) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampNopPaidIterator{contract: _EVM2EVMOnRamp.contract, event: "NopPaid", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchNopPaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopPaid, nop []common.Address) (event.Subscription, error) { - - var nopRule []interface{} - for _, nopItem := range nop { - nopRule = append(nopRule, nopItem) - } - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "NopPaid", nopRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampNopPaid) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopPaid", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseNopPaid(log types.Log) (*EVM2EVMOnRampNopPaid, error) { - event := new(EVM2EVMOnRampNopPaid) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopPaid", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampNopsSetIterator struct { - Event *EVM2EVMOnRampNopsSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampNopsSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampNopsSet) - 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(EVM2EVMOnRampNopsSet) - 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 *EVM2EVMOnRampNopsSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampNopsSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampNopsSet struct { - NopWeightsTotal *big.Int - NopsAndWeights []EVM2EVMOnRampNopAndWeight - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterNopsSet(opts *bind.FilterOpts) (*EVM2EVMOnRampNopsSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "NopsSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampNopsSetIterator{contract: _EVM2EVMOnRamp.contract, event: "NopsSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchNopsSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopsSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "NopsSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampNopsSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopsSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseNopsSet(log types.Log) (*EVM2EVMOnRampNopsSet, error) { - event := new(EVM2EVMOnRampNopsSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopsSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMOnRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampOwnershipTransferRequested) - 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(EVM2EVMOnRampOwnershipTransferRequested) - 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 *EVM2EVMOnRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferRequestedIterator, 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 := _EVM2EVMOnRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampOwnershipTransferRequestedIterator{contract: _EVM2EVMOnRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferRequested, 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 := _EVM2EVMOnRamp.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(EVM2EVMOnRampOwnershipTransferRequested) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMOnRampOwnershipTransferRequested, error) { - event := new(EVM2EVMOnRampOwnershipTransferRequested) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampOwnershipTransferredIterator struct { - Event *EVM2EVMOnRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampOwnershipTransferred) - 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(EVM2EVMOnRampOwnershipTransferred) - 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 *EVM2EVMOnRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferredIterator, 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 := _EVM2EVMOnRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampOwnershipTransferredIterator{contract: _EVM2EVMOnRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferred, 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 := _EVM2EVMOnRamp.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(EVM2EVMOnRampOwnershipTransferred) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMOnRampOwnershipTransferred, error) { - event := new(EVM2EVMOnRampOwnershipTransferred) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampPoolAddedIterator struct { - Event *EVM2EVMOnRampPoolAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampPoolAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampPoolAdded) - 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(EVM2EVMOnRampPoolAdded) - 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 *EVM2EVMOnRampPoolAddedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampPoolAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampPoolAdded struct { - Token common.Address - Pool common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterPoolAdded(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolAddedIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "PoolAdded") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampPoolAddedIterator{contract: _EVM2EVMOnRamp.contract, event: "PoolAdded", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolAdded) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "PoolAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampPoolAdded) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolAdded", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParsePoolAdded(log types.Log) (*EVM2EVMOnRampPoolAdded, error) { - event := new(EVM2EVMOnRampPoolAdded) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampPoolRemovedIterator struct { - Event *EVM2EVMOnRampPoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampPoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampPoolRemoved) - 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(EVM2EVMOnRampPoolRemoved) - 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 *EVM2EVMOnRampPoolRemovedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampPoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampPoolRemoved struct { - Token common.Address - Pool common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterPoolRemoved(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolRemovedIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "PoolRemoved") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampPoolRemovedIterator{contract: _EVM2EVMOnRamp.contract, event: "PoolRemoved", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolRemoved) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "PoolRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampPoolRemoved) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolRemoved", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParsePoolRemoved(log types.Log) (*EVM2EVMOnRampPoolRemoved, error) { - event := new(EVM2EVMOnRampPoolRemoved) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampTokenTransferFeeConfigSetIterator struct { - Event *EVM2EVMOnRampTokenTransferFeeConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampTokenTransferFeeConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampTokenTransferFeeConfigSet) - 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(EVM2EVMOnRampTokenTransferFeeConfigSet) - 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 *EVM2EVMOnRampTokenTransferFeeConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampTokenTransferFeeConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampTokenTransferFeeConfigSet struct { - TransferFeeConfig []EVM2EVMOnRampTokenTransferFeeConfigArgs - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterTokenTransferFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampTokenTransferFeeConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "TokenTransferFeeConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampTokenTransferFeeConfigSetIterator{contract: _EVM2EVMOnRamp.contract, event: "TokenTransferFeeConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchTokenTransferFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampTokenTransferFeeConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "TokenTransferFeeConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampTokenTransferFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseTokenTransferFeeConfigSet(log types.Log) (*EVM2EVMOnRampTokenTransferFeeConfigSet, error) { - event := new(EVM2EVMOnRampTokenTransferFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type GetNops struct { - NopsAndWeights []EVM2EVMOnRampNopAndWeight - WeightsTotal *big.Int -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _EVM2EVMOnRamp.abi.Events["AdminSet"].ID: - return _EVM2EVMOnRamp.ParseAdminSet(log) - case _EVM2EVMOnRamp.abi.Events["AllowListAdd"].ID: - return _EVM2EVMOnRamp.ParseAllowListAdd(log) - case _EVM2EVMOnRamp.abi.Events["AllowListEnabledSet"].ID: - return _EVM2EVMOnRamp.ParseAllowListEnabledSet(log) - case _EVM2EVMOnRamp.abi.Events["AllowListRemove"].ID: - return _EVM2EVMOnRamp.ParseAllowListRemove(log) - case _EVM2EVMOnRamp.abi.Events["CCIPSendRequested"].ID: - return _EVM2EVMOnRamp.ParseCCIPSendRequested(log) - case _EVM2EVMOnRamp.abi.Events["ConfigSet"].ID: - return _EVM2EVMOnRamp.ParseConfigSet(log) - case _EVM2EVMOnRamp.abi.Events["FeeConfigSet"].ID: - return _EVM2EVMOnRamp.ParseFeeConfigSet(log) - case _EVM2EVMOnRamp.abi.Events["NopPaid"].ID: - return _EVM2EVMOnRamp.ParseNopPaid(log) - case _EVM2EVMOnRamp.abi.Events["NopsSet"].ID: - return _EVM2EVMOnRamp.ParseNopsSet(log) - case _EVM2EVMOnRamp.abi.Events["OwnershipTransferRequested"].ID: - return _EVM2EVMOnRamp.ParseOwnershipTransferRequested(log) - case _EVM2EVMOnRamp.abi.Events["OwnershipTransferred"].ID: - return _EVM2EVMOnRamp.ParseOwnershipTransferred(log) - case _EVM2EVMOnRamp.abi.Events["PoolAdded"].ID: - return _EVM2EVMOnRamp.ParsePoolAdded(log) - case _EVM2EVMOnRamp.abi.Events["PoolRemoved"].ID: - return _EVM2EVMOnRamp.ParsePoolRemoved(log) - case _EVM2EVMOnRamp.abi.Events["TokenTransferFeeConfigSet"].ID: - return _EVM2EVMOnRamp.ParseTokenTransferFeeConfigSet(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (EVM2EVMOnRampAdminSet) Topic() common.Hash { - return common.HexToHash("0x8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c") -} - -func (EVM2EVMOnRampAllowListAdd) Topic() common.Hash { - return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8") -} - -func (EVM2EVMOnRampAllowListEnabledSet) Topic() common.Hash { - return common.HexToHash("0xccf4daf6ab6430389f26b970595dab82a5881ad454770907e415ede27c8df032") -} - -func (EVM2EVMOnRampAllowListRemove) Topic() common.Hash { - return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566") -} - -func (EVM2EVMOnRampCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0xaffc45517195d6499808c643bd4a7b0ffeedf95bea5852840d7bfcf63f59e821") -} - -func (EVM2EVMOnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0xdd226617d8d287f40a64c54741bbcdc492b3e096ef16bc5273a18cb6ab85f124") -} - -func (EVM2EVMOnRampFeeConfigSet) Topic() common.Hash { - return common.HexToHash("0xfba339fca97870ffdfaedbae3745db5e6de1a6909dfd0e0dbb56917469ffe236") -} - -func (EVM2EVMOnRampNopPaid) Topic() common.Hash { - return common.HexToHash("0x55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f") -} - -func (EVM2EVMOnRampNopsSet) Topic() common.Hash { - return common.HexToHash("0x8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd24") -} - -func (EVM2EVMOnRampOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (EVM2EVMOnRampOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (EVM2EVMOnRampPoolAdded) Topic() common.Hash { - return common.HexToHash("0x95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c") -} - -func (EVM2EVMOnRampPoolRemoved) Topic() common.Hash { - return common.HexToHash("0x987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c") -} - -func (EVM2EVMOnRampTokenTransferFeeConfigSet) Topic() common.Hash { - return common.HexToHash("0xcb0c5f472d325cf0c56953fc81870ddd80d0d3c9a3fbfe777002d75f380dfb81") -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRamp) Address() common.Address { - return _EVM2EVMOnRamp.address -} - -type EVM2EVMOnRampInterface interface { - CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) - - GetAllowList(opts *bind.CallOpts) ([]common.Address, error) - - GetAllowListEnabled(opts *bind.CallOpts) (bool, error) - - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMOnRampDynamicConfig, error) - - GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) - - GetFee(opts *bind.CallOpts, message ClientEVM2AnyMessage) (*big.Int, error) - - GetFeeTokenConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) - - GetNopFeesJuels(opts *bind.CallOpts) (*big.Int, error) - - GetNops(opts *bind.CallOpts) (GetNops, - - error) - - GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) - - GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) - - GetStaticConfig(opts *bind.CallOpts) (EVM2EVMOnRampStaticConfig, error) - - GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) - - GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) - - GetTokenTransferFeeConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) - - LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - - ApplyPoolUpdates(opts *bind.TransactOpts, removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) - - ForwardFromRouter(opts *bind.TransactOpts, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) - - PayNops(opts *bind.TransactOpts) (*types.Transaction, error) - - SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) - - SetAllowListEnabled(opts *bind.TransactOpts, enabled bool) (*types.Transaction, error) - - SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) - - SetFeeTokenConfig(opts *bind.TransactOpts, feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) - - SetNops(opts *bind.TransactOpts, nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) - - SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) - - SetTokenTransferFeeConfig(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - WithdrawNonLinkFees(opts *bind.TransactOpts, feeToken common.Address, to common.Address) (*types.Transaction, error) - - FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAdminSetIterator, error) - - WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAdminSet) (event.Subscription, error) - - ParseAdminSet(log types.Log) (*EVM2EVMOnRampAdminSet, error) - - FilterAllowListAdd(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListAddIterator, error) - - WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListAdd) (event.Subscription, error) - - ParseAllowListAdd(log types.Log) (*EVM2EVMOnRampAllowListAdd, error) - - FilterAllowListEnabledSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListEnabledSetIterator, error) - - WatchAllowListEnabledSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListEnabledSet) (event.Subscription, error) - - ParseAllowListEnabledSet(log types.Log) (*EVM2EVMOnRampAllowListEnabledSet, error) - - FilterAllowListRemove(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListRemoveIterator, error) - - WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListRemove) (event.Subscription, error) - - ParseAllowListRemove(log types.Log) (*EVM2EVMOnRampAllowListRemove, error) - - FilterCCIPSendRequested(opts *bind.FilterOpts) (*EVM2EVMOnRampCCIPSendRequestedIterator, error) - - WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampCCIPSendRequested) (event.Subscription, error) - - ParseCCIPSendRequested(log types.Log) (*EVM2EVMOnRampCCIPSendRequested, error) - - FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*EVM2EVMOnRampConfigSet, error) - - FilterFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampFeeConfigSetIterator, error) - - WatchFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampFeeConfigSet) (event.Subscription, error) - - ParseFeeConfigSet(log types.Log) (*EVM2EVMOnRampFeeConfigSet, error) - - FilterNopPaid(opts *bind.FilterOpts, nop []common.Address) (*EVM2EVMOnRampNopPaidIterator, error) - - WatchNopPaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopPaid, nop []common.Address) (event.Subscription, error) - - ParseNopPaid(log types.Log) (*EVM2EVMOnRampNopPaid, error) - - FilterNopsSet(opts *bind.FilterOpts) (*EVM2EVMOnRampNopsSetIterator, error) - - WatchNopsSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopsSet) (event.Subscription, error) - - ParseNopsSet(log types.Log) (*EVM2EVMOnRampNopsSet, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMOnRampOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*EVM2EVMOnRampOwnershipTransferred, error) - - FilterPoolAdded(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolAddedIterator, error) - - WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolAdded) (event.Subscription, error) - - ParsePoolAdded(log types.Log) (*EVM2EVMOnRampPoolAdded, error) - - FilterPoolRemoved(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolRemovedIterator, error) - - WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolRemoved) (event.Subscription, error) - - ParsePoolRemoved(log types.Log) (*EVM2EVMOnRampPoolRemoved, error) - - FilterTokenTransferFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampTokenTransferFeeConfigSetIterator, error) - - WatchTokenTransferFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampTokenTransferFeeConfigSet) (event.Subscription, error) - - ParseTokenTransferFeeConfigSet(log types.Log) (*EVM2EVMOnRampTokenTransferFeeConfigSet, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_1_0/evm_2_evm_onramp_1_1_0.go b/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_1_0/evm_2_evm_onramp_1_1_0.go deleted file mode 100644 index fb5aa512ac9..00000000000 --- a/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_1_0/evm_2_evm_onramp_1_1_0.go +++ /dev/null @@ -1,2794 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package evm_2_evm_onramp_1_1_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 ClientEVM2AnyMessage struct { - Receiver []byte - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - ExtraArgs []byte -} - -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - -type EVM2EVMOnRampDynamicConfig struct { - Router common.Address - MaxTokensLength uint16 - DestGasOverhead uint32 - DestGasPerPayloadByte uint16 - PriceRegistry common.Address - MaxDataSize uint32 - MaxGasLimit uint64 -} - -type EVM2EVMOnRampFeeTokenConfig struct { - NetworkFeeUSD uint32 - MinTokenTransferFeeUSD uint32 - MaxTokenTransferFeeUSD uint32 - GasMultiplier uint64 - PremiumMultiplier uint64 - Enabled bool -} - -type EVM2EVMOnRampFeeTokenConfigArgs struct { - Token common.Address - NetworkFeeUSD uint32 - MinTokenTransferFeeUSD uint32 - MaxTokenTransferFeeUSD uint32 - GasMultiplier uint64 - PremiumMultiplier uint64 - Enabled bool -} - -type EVM2EVMOnRampNopAndWeight struct { - Nop common.Address - Weight uint16 -} - -type EVM2EVMOnRampStaticConfig struct { - LinkToken common.Address - ChainSelector uint64 - DestChainSelector uint64 - DefaultTxGasLimit uint64 - MaxNopFeesJuels *big.Int - PrevOnRamp common.Address - ArmProxy common.Address -} - -type EVM2EVMOnRampTokenTransferFeeConfig struct { - Ratio uint16 - DestGasOverhead uint32 -} - -type EVM2EVMOnRampTokenTransferFeeConfigArgs struct { - Token common.Address - Ratio uint16 - DestGasOverhead uint32 -} - -type InternalEVM2EVMMessage struct { - SourceChainSelector uint64 - SequenceNumber uint64 - FeeTokenAmount *big.Int - Sender common.Address - Nonce uint64 - GasLimit *big.Int - Strict bool - Receiver common.Address - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - MessageId [32]byte -} - -type InternalPoolUpdate struct { - Token common.Address - Pool common.Address -} - -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 -} - -var EVM2EVMOnRampMetaData = &bind.MetaData{ - ABI: "[{\"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\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"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[]\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"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\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"minTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMOnRamp.FeeTokenConfigArgs[]\",\"name\":\"feeTokenConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"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\":\"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\":\"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\":[],\"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\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"AllowListEnabledSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"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\":\"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\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"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\":\"networkFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"minTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplier\",\"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\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"transferFeeConfig\",\"type\":\"tuple[]\"}],\"name\":\"TokenTransferFeeConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":[{\"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\":\"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\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"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\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getFeeTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"networkFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"minTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplier\",\"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\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"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\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"setAllowListEnabled\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxTokensLength\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"maxGasLimit\",\"type\":\"uint64\"}],\"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\":\"networkFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"minTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferFeeUSD\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplier\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplier\",\"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\":\"uint16\",\"name\":\"ratio\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"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\"}]", - Bin: "0x6101806040526012805460ff60c01b191690553480156200001f57600080fd5b506040516200834538038062008345833981016040819052620000429162001e90565b8333806000816200009a5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000cd57620000cd8162000369565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606086018190529790950151166080909301839052600380546001600160a01b031916909417600160801b9283021760ff60a01b1916600160a01b90910217909255029091176004555087516001600160a01b0316158062000176575060208801516001600160401b0316155b806200018d575060408801516001600160401b0316155b80620001a4575060608801516001600160401b0316155b80620001bb575060c08801516001600160a01b0316155b15620001da576040516306b7c75960e31b815260040160405180910390fd5b6020808901516040808b015181517fbdd59ac4dd1d82276c9a9c5d2656546346b9dcdb1f9b4204aed4ec15c23d7d3a948101949094526001600160401b039283169184019190915216606082015230608082015260a00160408051601f19818403018152918152815160209283012060809081528a516001600160a01b0390811660e052928b01516001600160401b0390811661010052918b015182166101205260608b015190911660a0908152908a01516001600160601b031660c0908152908a01518216610140528901511661016052620002b78762000414565b620002c2836200059e565b620002cd8262000739565b620002d88162000810565b6040805160008082526020820190925262000323916200031b565b6040805180820190915260008082526020820152815260200190600190039081620002f35790505b508762000a3a565b8451156200035b576012805460ff60c81b1916600160c81b179055604080516000808252602082019092526200035b91508662000d3d565b505050505050505062002407565b336001600160a01b03821603620003c35760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000091565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60808101516001600160a01b031662000440576040516306b7c75960e31b815260040160405180910390fd5b8051600580546020808501516040808701516060808901516001600160a01b039889166001600160b01b031990971696909617600160a01b61ffff95861681029190911765ffffffffffff60b01b1916600160b01b63ffffffff9485160261ffff60d01b191617600160d01b9590971694909402959095179095556080808801516006805460a0808c015160c0808e0151958d166001600160c01b0319909416939093179a16909602989098176001600160c01b0316600160c01b6001600160401b0393841602179055825160e08082018552518916815261010051821695810195909552610120518116858401528351169484019490945284516001600160601b031693830193909352610140518516908201526101605190931691830191909152517f72c6aaba4dde02f77d291123a76185c418ba63f8c217a2d56b08aec84e9bbfb8916200059391849062001fb3565b60405180910390a150565b60005b815181101562000707576000828281518110620005c257620005c26200207f565b6020908102919091018101516040805160c080820183528385015163ffffffff908116835283850151811683870190815260608087015183168587019081526080808901516001600160401b0390811693880193845260a0808b01518216928901928352968a0151151596880196875298516001600160a01b03166000908152600f909a529690982094518554925198519151965194511515600160e01b0260ff60e01b19958916600160a01b0295909516600160a01b600160e81b0319979098166c0100000000000000000000000002600160601b600160a01b0319928516680100000000000000000292909216600160401b600160a01b0319998516640100000000026001600160401b0319909416919094161791909117969096161794909417919091169190911791909117905550620006ff81620020ab565b9050620005a1565b507f2386f61ab5cafc3fed44f9f614f721ab53479ef64067fd16c1a2491b63ddf1a881604051620005939190620020c7565b60005b8151811015620007de5760008282815181106200075d576200075d6200207f565b6020908102919091018101516040805180820182528284015161ffff90811682528284015163ffffffff90811683870190815294516001600160a01b03166000908152601090965292909420905181549351909216620100000265ffffffffffff19909316919093161717905550620007d681620020ab565b90506200073c565b507f4230c60a9725eb5fb992cf6a215398b4e81b4606d4a1e6be8dfe0b60dc172ec1816040516200059391906200217f565b805160408111156200083557604051635ad0867d60e11b815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff16158015906200087f575060125463ffffffff6c010000000000000000000000008204166001600160601b0390911610155b156200088f576200088f62000e88565b60006200089d600762001088565b90505b8015620008e9576000620008c3620008ba600184620021e0565b6007906200109b565b509050620008d3600782620010b9565b505080620008e190620021f6565b9050620008a0565b506000805b82811015620009d15760008482815181106200090e576200090e6200207f565b602002602001015160000151905060008583815181106200093357620009336200207f565b602002602001015160200151905060e0516001600160a01b0316826001600160a01b031614806200096b57506001600160a01b038216155b156200099657604051634de938d160e01b81526001600160a01b038316600482015260240162000091565b620009a860078361ffff8416620010d7565b50620009b961ffff82168562002210565b9350505080620009c990620020ab565b9050620008ee565b506012805463ffffffff60601b19166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd249062000a2d908390869062002230565b60405180910390a1505050565b60005b825181101562000b7657600083828151811062000a5e5762000a5e6200207f565b6020026020010151600001519050600084838151811062000a835762000a836200207f565b6020908102919091018101510151905062000aa0600a83620010f7565b62000aca576040516373913ebd60e01b81526001600160a01b038316600482015260240162000091565b6001600160a01b03811662000ae1600a846200110e565b6001600160a01b03161462000b0957604051630d98f73360e31b815260040160405180910390fd5b62000b16600a8362001125565b1562000b6057604080516001600160a01b038085168252831660208201527f987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c910160405180910390a15b50508062000b6e90620020ab565b905062000a3d565b5060005b815181101562000d3857600082828151811062000b9b5762000b9b6200207f565b6020026020010151600001519050600083838151811062000bc05762000bc06200207f565b602002602001015160200151905060006001600160a01b0316826001600160a01b0316148062000bf757506001600160a01b038116155b1562000c155760405162d8548360e71b815260040160405180910390fd5b806001600160a01b03166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000c54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c7a91906200229d565b6001600160a01b0316826001600160a01b03161462000cac57604051630d98f73360e31b815260040160405180910390fd5b62000cba600a83836200113c565b1562000d0957604080516001600160a01b038085168252831660208201527f95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c910160405180910390a162000d22565b604051633caf458560e01b815260040160405180910390fd5b50508062000d3090620020ab565b905062000b7a565b505050565b60005b825181101562000dd257600083828151811062000d615762000d616200207f565b6020908102919091010151905062000d7b600d8262001154565b1562000dbe576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5062000dca81620020ab565b905062000d40565b5060005b815181101562000d3857600082828151811062000df75762000df76200207f565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000e23575062000e75565b62000e30600d826200116b565b1562000e73576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b62000e8081620020ab565b905062000dd6565b6000546001600160a01b0316331480159062000eaf57506002546001600160a01b03163314155b801562000ec6575062000ec460073362001182565b155b1562000ee55760405163032bb72b60e31b815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff16600081900362000f215760405163990e30bf60e01b815260040160405180910390fd5b6012546001600160601b03168181101562000f4f576040516311a1ee3b60e31b815260040160405180910390fd5b600062000f5b62001199565b121562000f7b57604051631e9acf1760e31b815260040160405180910390fd5b80600062000f8a600762001088565b905060005b81811015620010625760008062000fa86007846200109b565b909250905060008762000fc5836001600160601b038a16620022bd565b62000fd19190620022d7565b905062000fdf8187620022fa565b60e05190965062001004906001600160a01b0316846001600160601b03841662001227565b6040516001600160601b03821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a2505050806200105a90620020ab565b905062000f8f565b5050601280546001600160601b0319166001600160601b03929092169190911790555050565b600062001095826200127f565b92915050565b6000808080620010ac86866200128c565b9097909650945050505050565b6000620010d0836001600160a01b038416620012b9565b9392505050565b6000620010ef846001600160a01b03851684620012d8565b949350505050565b6000620010d0836001600160a01b038416620012f7565b6000620010d0836001600160a01b03841662001305565b6000620010d0836001600160a01b03841662001313565b6000620010ef846001600160a01b0385168462001321565b6000620010d0836001600160a01b03841662001339565b6000620010d0836001600160a01b03841662001444565b6000620010d0836001600160a01b03841662001496565b60125460e0516040516370a0823160e01b81523060048201526000926001600160601b0316916001600160a01b0316906370a0823190602401602060405180830381865afa158015620011f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200121691906200231d565b62001222919062002337565b905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663a9059cbb60e01b1790915262000d38918591620014a416565b6000620010958262001575565b600080806200129c858562001580565b600081815260029690960160205260409095205494959350505050565b60008181526002830160205260408120819055620010d083836200158e565b60008281526002840160205260408120829055620010ef84846200159c565b6000620010d0838362001496565b6000620010d08383620015aa565b6000620010d08383620012b9565b6000620010ef84846001600160a01b038516620012d8565b600081815260018301602052604081205480156200143257600062001360600183620021e0565b85549091506000906200137690600190620021e0565b9050818114620013e25760008660000182815481106200139a576200139a6200207f565b9060005260206000200154905080876000018481548110620013c057620013c06200207f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620013f657620013f66200235a565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062001095565b600091505062001095565b5092915050565b60008181526001830160205260408120546200148d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562001095565b50600062001095565b6000620010d083836200161f565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620014f3906001600160a01b03851690849062001638565b80519091501562000d38578080602001905181019062001514919062002370565b62000d385760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000091565b600062001095825490565b6000620010d0838362001649565b6000620010d0838362001339565b6000620010d0838362001444565b600081815260028301602052604081205480151580620015d15750620015d1848462001496565b620010d05760405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000604482015260640162000091565b60008181526001830160205260408120541515620010d0565b6060620010ef848460008562001676565b60008260000182815481106200166357620016636200207f565b9060005260206000200154905092915050565b606082471015620016d95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000091565b600080866001600160a01b03168587604051620016f79190620023b4565b60006040518083038185875af1925050503d806000811462001736576040519150601f19603f3d011682016040523d82523d6000602084013e6200173b565b606091505b5090925090506200174f878383876200175a565b979650505050505050565b60608315620017ce578251600003620017c6576001600160a01b0385163b620017c65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000091565b5081620010ef565b620010ef8383815115620017e55781518083602001fd5b8060405162461bcd60e51b8152600401620000919190620023d2565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b03811182821017156200183c576200183c62001801565b60405290565b604080519081016001600160401b03811182821017156200183c576200183c62001801565b604051606081016001600160401b03811182821017156200183c576200183c62001801565b604051601f8201601f191681016001600160401b0381118282101715620018b757620018b762001801565b604052919050565b6001600160a01b0381168114620018d557600080fd5b50565b8051620018e581620018bf565b919050565b80516001600160401b0381168114620018e557600080fd5b600060e082840312156200191557600080fd5b6200191f62001817565b905081516200192e81620018bf565b81526200193e60208301620018ea565b60208201526200195160408301620018ea565b60408201526200196460608301620018ea565b606082015260808201516001600160601b03811681146200198457600080fd5b60808201526200199760a08301620018d8565b60a0820152620019aa60c08301620018d8565b60c082015292915050565b805161ffff81168114620018e557600080fd5b805163ffffffff81168114620018e557600080fd5b600060e08284031215620019f057600080fd5b620019fa62001817565b9050815162001a0981620018bf565b815262001a1960208301620019b5565b602082015262001a2c60408301620019c8565b604082015262001a3f60608301620019b5565b6060820152608082015162001a5481620018bf565b608082015262001a6760a08301620019c8565b60a0820152620019aa60c08301620018ea565b60006001600160401b0382111562001a965762001a9662001801565b5060051b60200190565b600082601f83011262001ab257600080fd5b8151602062001acb62001ac58362001a7a565b6200188c565b82815260069290921b8401810191818101908684111562001aeb57600080fd5b8286015b8481101562001b45576040818903121562001b0a5760008081fd5b62001b1462001842565b815162001b2181620018bf565b81528185015162001b3281620018bf565b8186015283529183019160400162001aef565b509695505050505050565b600082601f83011262001b6257600080fd5b8151602062001b7562001ac58362001a7a565b82815260059290921b8401810191818101908684111562001b9557600080fd5b8286015b8481101562001b4557805162001baf81620018bf565b835291830191830162001b99565b80518015158114620018e557600080fd5b80516001600160801b0381168114620018e557600080fd5b60006060828403121562001bf957600080fd5b62001c0362001867565b905062001c108262001bbd565b815262001c206020830162001bce565b602082015262001c336040830162001bce565b604082015292915050565b600082601f83011262001c5057600080fd5b8151602062001c6362001ac58362001a7a565b82815260e0928302850182019282820191908785111562001c8357600080fd5b8387015b8581101562001d385781818a03121562001ca15760008081fd5b62001cab62001817565b815162001cb881620018bf565b815262001cc7828701620019c8565b86820152604062001cda818401620019c8565b90820152606062001ced838201620019c8565b90820152608062001d00838201620018ea565b9082015260a062001d13838201620018ea565b9082015260c062001d2683820162001bbd565b90820152845292840192810162001c87565b5090979650505050505050565b600082601f83011262001d5757600080fd5b8151602062001d6a62001ac58362001a7a565b8281526060928302850182019282820191908785111562001d8a57600080fd5b8387015b8581101562001d385781818a03121562001da85760008081fd5b62001db262001867565b815162001dbf81620018bf565b815262001dce828701620019b5565b86820152604062001de1818401620019c8565b90820152845292840192810162001d8e565b600082601f83011262001e0557600080fd5b8151602062001e1862001ac58362001a7a565b82815260069290921b8401810191818101908684111562001e3857600080fd5b8286015b8481101562001b45576040818903121562001e575760008081fd5b62001e6162001842565b815162001e6e81620018bf565b815262001e7d828601620019b5565b8186015283529183019160400162001e3c565b6000806000806000806000806102c0898b03121562001eae57600080fd5b62001eba8a8a62001902565b975062001ecb8a60e08b01620019dd565b6101c08a01519097506001600160401b038082111562001eea57600080fd5b62001ef88c838d0162001aa0565b97506101e08b015191508082111562001f1057600080fd5b62001f1e8c838d0162001b50565b965062001f308c6102008d0162001be6565b95506102608b015191508082111562001f4857600080fd5b62001f568c838d0162001c3e565b94506102808b015191508082111562001f6e57600080fd5b62001f7c8c838d0162001d45565b93506102a08b015191508082111562001f9457600080fd5b5062001fa38b828c0162001df3565b9150509295985092959890939650565b82516001600160a01b0390811682526020808501516001600160401b03908116828501526040808701518216818601526060808801518316818701526080808901516001600160601b03168188015260a0808a015187168189015260c0808b01518816818a01528951881660e08a01529589015161ffff9081166101008a01529389015163ffffffff9081166101208a015292890151909316610140880152870151909416610160860152850151909216610180840152830151166101a08201526101c08101620010d0565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620020c057620020c062002095565b5060010190565b602080825282518282018190526000919060409081850190868401855b828110156200217257815180516001600160a01b031685528681015163ffffffff9081168887015286820151811687870152606080830151909116908601526080808201516001600160401b03169086015260a08082015162002151878301826001600160401b03169052565b505060c09081015115159085015260e09093019290850190600101620020e4565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b828110156200217257815180516001600160a01b031685528681015161ffff168786015285015163ffffffff1685850152606090930192908501906001016200219c565b8181038181111562001095576200109562002095565b60008162002208576200220862002095565b506000190190565b63ffffffff8181168382160190808211156200143d576200143d62002095565b6000604080830163ffffffff8616845260208281860152818651808452606087019150828801935060005b818110156200228f57845180516001600160a01b0316845284015161ffff168484015293830193918501916001016200225b565b509098975050505050505050565b600060208284031215620022b057600080fd5b8151620010d081620018bf565b808202811582820484141762001095576200109562002095565b600082620022f557634e487b7160e01b600052601260045260246000fd5b500490565b6001600160601b038281168282160390808211156200143d576200143d62002095565b6000602082840312156200233057600080fd5b5051919050565b81810360008312801583831316838312821617156200143d576200143d62002095565b634e487b7160e01b600052603160045260246000fd5b6000602082840312156200238357600080fd5b620010d08262001bbd565b60005b83811015620023ab57818101518382015260200162002391565b50506000910152565b60008251620023c88184602087016200238e565b9190910192915050565b6020815260008251806020840152620023f38160408501602087016200238e565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516101405161016051615e376200250e600039600081816103600152818161148701526135700152600081816103310152818161139d01528181611405015281816119cc01528181611a34015261354901526000818161029d01528181610bcf01528181611dc401526134c301526000818161026d01528181611aff015261349901526000818161023e01528181610f320152818161177f015281816118780152818161237d015281816130380152818161347401526137000152600081816102fd0152818161194401526135130152600081816102cd015281816126c401526134ea01526000611cde0152615e376000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806376f6ae761161010f578063c92b2832116100a2578063e76c0b0611610071578063e76c0b0614610943578063efeadb6d14610956578063eff7cc4814610969578063f2fde38b1461097157600080fd5b8063c92b2832146108ed578063d09dc33914610900578063d3c7c2c714610908578063e0351e131461091057600080fd5b80639a113c36116100de5780639a113c3614610742578063a7cd63b7146108af578063a7d3e02f146108c4578063b06d41bc146108d757600080fd5b806376f6ae761461070357806379ba509714610716578063856c82471461071e5780638da5cb5b1461073157600080fd5b8063549e946f116101875780635d86f141116101565780635d86f141146105ae578063704b6c02146105c15780637132721a146105d45780637437ff9f146105e757600080fd5b8063549e946f1461054357806354b714681461055657806354c8a4f314610576578063599f64311461058957600080fd5b806338724a95116101c357806338724a951461048a5780633a87ac53146104ab5780634120fccd146104be578063546719cd146104df57600080fd5b806306285c69146101f55780631772047e146103a6578063181f5a771461042c578063352e4bc814610475575b600080fd5b6103906040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040518060e001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161039d919061499d565b60405180910390f35b6104076103b4366004614a2e565b6040805180820190915260008082526020820152506001600160a01b031660009081526010602090815260409182902082518084019093525461ffff8116835262010000900463ffffffff169082015290565b60408051825161ffff16815260209283015163ffffffff16928101929092520161039d565b6104686040518060400160405280601381526020017f45564d3245564d4f6e52616d7020312e312e300000000000000000000000000081525081565b60405161039d9190614ab9565b610488610483366004614c1a565b610984565b005b61049d610498366004614d50565b6109ed565b60405190815260200161039d565b6104886104b9366004614e21565b610dd9565b6104c6610def565b60405167ffffffffffffffff909116815260200161039d565b6104e7610e23565b60405161039d919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b610488610551366004614e85565b610ed3565b6012546040516bffffffffffffffffffffffff909116815260200161039d565b610488610584366004614f22565b611088565b6002546001600160a01b03165b6040516001600160a01b03909116815260200161039d565b6105966105bc366004614a2e565b61109a565b6104886105cf366004614a2e565b6110f9565b6104886105e2366004614f8e565b6111c3565b6106f66040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152506040805160e0810182526005546001600160a01b03808216835261ffff740100000000000000000000000000000000000000008084048216602086015263ffffffff76010000000000000000000000000000000000000000000085048116968601969096527a010000000000000000000000000000000000000000000000000000909304166060840152600654908116608084015290810490921660a082015267ffffffffffffffff78010000000000000000000000000000000000000000000000009092049190911660c082015290565b60405161039d9190615026565b6104886107113660046150a1565b6111d4565b61048861128c565b6104c661072c366004614a2e565b61136f565b6000546001600160a01b0316610596565b610845610750366004614a2e565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506001600160a01b03166000908152600f6020908152604091829020825160c081018452905463ffffffff808216835264010000000082048116938301939093526801000000000000000081049092169281019290925267ffffffffffffffff6c0100000000000000000000000082048116606084015274010000000000000000000000000000000000000000820416608083015260ff7c010000000000000000000000000000000000000000000000000000000090910416151560a082015290565b60405161039d9190600060c08201905063ffffffff80845116835280602085015116602084015280604085015116604084015250606083015167ffffffffffffffff8082166060850152806080860151166080850152505060a0830151151560a083015292915050565b6108b7611477565b60405161039d9190615116565b61049d6108d2366004615163565b611483565b6108df611eab565b60405161039d929190615211565b6104886108fb366004615253565b611faf565b61049d612017565b6108b7612021565b601254790100000000000000000000000000000000000000000000000000900460ff16604051901515815260200161039d565b6104886109513660046152a3565b6120d2565b61048861096436600461536c565b612138565b6104886121be565b61048861097f366004614a2e565b612455565b6000546001600160a01b031633148015906109aa57506002546001600160a01b03163314155b156109e1576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ea81612466565b50565b600080610a05610a006080850185615389565b612695565b9050610a30610a176020850185615389565b8351909150610a2960408701876153ee565b9050612789565b6000600f81610a456080870160608801614a2e565b6001600160a01b031681526020808201929092526040908101600020815160c081018352905463ffffffff80821683526401000000008204811694830194909452680100000000000000008104909316918101919091526c01000000000000000000000000820467ffffffffffffffff90811660608301527401000000000000000000000000000000000000000083041660808201527c010000000000000000000000000000000000000000000000000000000090910460ff16151560a08201819052909150610b6257610b1f6080850160608601614a2e565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024015b60405180910390fd5b60065460009081906001600160a01b031663ffdb4b37610b886080890160608a01614a2e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016040805180830381865afa158015610c13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c37919061547e565b909250905060008080610c4d60408a018a6153ee565b90501115610c8657610c7c610c6860808a0160608b01614a2e565b85610c7660408c018c6153ee565b896128ae565b9092509050610ca2565b8451610c9f9063ffffffff16662386f26fc100006154e0565b91505b6080850151610cbb9067ffffffffffffffff16836154e0565b606086015160055491935060009167ffffffffffffffff9091169063ffffffff8416907a010000000000000000000000000000000000000000000000000000900461ffff16610d0d60208d018d615389565b610d189291506154e0565b6005548a51610d4791760100000000000000000000000000000000000000000000900463ffffffff16906154f7565b610d5191906154f7565b610d5b91906154f7565b610d6591906154e0565b610d899077ffffffffffffffffffffffffffffffffffffffffffffffff86166154e0565b9050610dcc670de0b6b3a7640000610da183866154f7565b610dab919061550a565b77ffffffffffffffffffffffffffffffffffffffffffffffff871690612b34565b9998505050505050505050565b610de1612b6d565b610deb8282612be3565b5050565b601254600090610e1e90700100000000000000000000000000000000900467ffffffffffffffff166001615545565b905090565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff161515938301939093526004548084166060840152049091166080820152610e1e90612f43565b6000546001600160a01b03163314801590610ef957506002546001600160a01b03163314155b15610f30576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161480610f7757506001600160a01b038116155b15610fae576040517f232cb97f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610fb8612ff5565b1215610ff0576040517f02075e0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610deb9082906001600160a01b038516906370a0823190602401602060405180830381865afa158015611053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110779190615566565b6001600160a01b03851691906130b5565b611090612b6d565b610deb8282613135565b60006110a7600a83613270565b6110e8576040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610b59565b6110f3600a83613285565b92915050565b6000546001600160a01b0316331480159061111f57506002546001600160a01b03163314155b15611156576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c906020015b60405180910390a150565b6111cb612b6d565b6109ea8161329a565b6000546001600160a01b031633148015906111fa57506002546001600160a01b03163314155b15611231576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610deb8282808060200260200160405190810160405280939291908181526020016000905b82821015611282576112736040830286013681900381019061557f565b81526020019060010190611256565b50505050506135c7565b6001546001600160a01b03163314611300576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610b59565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6001600160a01b03811660009081526011602052604081205467ffffffffffffffff16801580156113c857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b156110f3576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa15801561144c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147091906155be565b9392505050565b6060610e1e600d61383a565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150791906155db565b1561153e576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03821661157e576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601254790100000000000000000000000000000000000000000000000000900460ff1680156115b557506115b3600d83613847565b155b156115f7576040517fd0d259760000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610b59565b6005546001600160a01b0316331461163b576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116458480615389565b905060201461168c576116588480615389565b6040517f370d875f000000000000000000000000000000000000000000000000000000008152600401610b59929190615641565b60006116988580615389565b8101906116a59190615655565b90506001600160a01b038111806116bc5750600a81105b156116cb576116588580615389565b60006116dd610a006080880188615389565b90506117016116ef6020880188615389565b8351909150610a2960408a018a6153ee565b61177561171160408801886153ee565b808060200260200160405190810160405280939291908181526020016000905b8282101561175d5761174e6040830286013681900381019061566e565b81526020019060010190611731565b50506006546001600160a01b03169250613869915050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166117af6080880160608901614a2e565b6001600160a01b03160361181357601280548691906000906117e09084906bffffffffffffffffffffffff166156a8565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550611932565b6006546001600160a01b03166241e5be6118336080890160608a01614a2e565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa1580156118bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e39190615566565b601280546000906119039084906bffffffffffffffffffffffff166156a8565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055505b6012546bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169116111561199f576040517fe5c7a49100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03841660009081526011602052604090205467ffffffffffffffff161580156119f757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b15611aef576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063856c824790602401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f91906155be565b6001600160a01b038516600090815260116020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790555b60006040518061018001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020016012601081819054906101000a900467ffffffffffffffff16611b4f906156cd565b825467ffffffffffffffff9182166101009390930a8381029083021990911617909255825260208083018a90526001600160a01b03891660408085018290526000918252601190925290812080546060909401939092611baf91166156cd565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200183600001518152602001600015158152602001846001600160a01b03168152602001888060200190611c159190615389565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001611c5c60408a018a6153ee565b808060200260200160405190810160405280939291908181526020016000905b82821015611ca857611c996040830286013681900381019061566e565b81526020019060010190611c7c565b5050509183525050602001611cc360808a0160608b01614a2e565b6001600160a01b0316815260006020909101529050611d02817f0000000000000000000000000000000000000000000000000000000000000000613a1c565b61016082015260005b611d1860408901896153ee565b9050811015611e64576000611d3060408a018a6153ee565b83818110611d4057611d406156f4565b905060400201803603810190611d56919061566e565b9050611d65816000015161109a565b6001600160a01b0316639687544588611d7e8c80615389565b60208087015160408051928301815260008352517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b168152611dec959493927f000000000000000000000000000000000000000000000000000000000000000091600401615723565b6000604051808303816000875af1158015611e0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611e51919081019061576e565b505080611e5d90615820565b9050611d0b565b507faffc45517195d6499808c643bd4a7b0ffeedf95bea5852840d7bfcf63f59e82181604051611e94919061589c565b60405180910390a161016001519695505050505050565b6060600080611eba6007613b26565b90508067ffffffffffffffff811115611ed557611ed5614acc565b604051908082528060200260200182016040528015611f1a57816020015b6040805180820190915260008082526020820152815260200190600190039081611ef35790505b50925060005b81811015611f8c57600080611f36600784613b31565b915091506040518060400160405280836001600160a01b031681526020018261ffff16815250868481518110611f6e57611f6e6156f4565b6020026020010181905250505080611f8590615820565b9050611f20565b505060125491926c0100000000000000000000000090920463ffffffff16919050565b6000546001600160a01b03163314801590611fd557506002546001600160a01b03163314155b1561200c576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ea600382613b4f565b6000610e1e612ff5565b6060600061202f600a613d27565b67ffffffffffffffff81111561204757612047614acc565b604051908082528060200260200182016040528015612070578160200160208202803683370190505b50905060005b81518110156120cc5761208a600a82613d32565b5082828151811061209d5761209d6156f4565b60200260200101816001600160a01b03166001600160a01b031681525050806120c590615820565b9050612076565b50919050565b6000546001600160a01b031633148015906120f857506002546001600160a01b03163314155b1561212f576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ea81613d41565b612140612b6d565b60128054821515790100000000000000000000000000000000000000000000000000027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff9091161790556040517fccf4daf6ab6430389f26b970595dab82a5881ad454770907e415ede27c8df032906111b890831515815260200190565b6000546001600160a01b031633148015906121e457506002546001600160a01b03163314155b80156121f857506121f6600733613e28565b155b1561222f576040517f195db95800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff166000819003612283576040517f990e30bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012546bffffffffffffffffffffffff16818110156122ce576040517f8d0f71d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006122d8612ff5565b1215612310576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600061231d6007613b26565b905060005b8181101561241257600080612338600784613b31565b9092509050600087612358836bffffffffffffffffffffffff8a166154e0565b612362919061550a565b905061236e81876159d9565b95506123b26001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016846bffffffffffffffffffffffff84166130b5565b6040516bffffffffffffffffffffffff821681526001600160a01b038416907f55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f9060200160405180910390a25050508061240b90615820565b9050612322565b5050601280547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff929092169190911790555050565b61245d612b6d565b6109ea81613e3d565b60005b8151811015612665576000828281518110612486576124866156f4565b6020908102919091018101516040805160c080820183528385015163ffffffff9081168352838501518116838701908152606080870151831685870190815260808089015167ffffffffffffffff90811693880193845260a0808b01518216928901928352968a0151151596880196875298516001600160a01b03166000908152600f909a5296909820945185549251985191519651945115157c0100000000000000000000000000000000000000000000000000000000027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9589167401000000000000000000000000000000000000000002959095167fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff979098166c01000000000000000000000000027fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff9285166801000000000000000002929092167fffffffffffffffffffffffff000000000000000000000000ffffffffffffffff998516640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090941691909416179190911796909616179490941791909116919091179190911790555061265e81615820565b9050612469565b507f2386f61ab5cafc3fed44f9f614f721ab53479ef64067fd16c1a2491b63ddf1a8816040516111b891906159fe565b60408051602081019091526000815260008290036126eb5750604080516020810190915267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526110f3565b7f97a657c9000000000000000000000000000000000000000000000000000000006127168385615ab5565b7fffffffff00000000000000000000000000000000000000000000000000000000161461276f576040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61277c8260048186615afd565b8101906114709190615b27565b60065474010000000000000000000000000000000000000000900463ffffffff16808411156127ee576040517f869337890000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610b59565b6006547801000000000000000000000000000000000000000000000000900467ffffffffffffffff16831115612850576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055474010000000000000000000000000000000000000000900461ffff168211156128a8576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60008083815b81811015612ac05760008787838181106128d0576128d06156f4565b9050604002018036038101906128e6919061566e565b80516001600160a01b031660009081526010602090815260409182902082518084019093525461ffff8116835263ffffffff620100009091048116918301919091528251929350909161293d91600a919061327016565b6129815781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610b59565b805160009061ffff1615612a8e5760008c6001600160a01b031684600001516001600160a01b031614612a3d5760065484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190615b69565b9050612a40565b508a5b82516020850151620186a09161ffff1690612a769077ffffffffffffffffffffffffffffffffffffffffffffffff851690613f18565b612a8091906154e0565b612a8a919061550a565b9150505b612a9881886154f7565b9650816020015186612aaa9190615b84565b955050505080612ab990615820565b90506128b4565b506000846020015163ffffffff16662386f26fc10000612ae091906154e0565b905080841015612af3579250612b2a9050565b6000856040015163ffffffff16662386f26fc10000612b1291906154e0565b905080851115612b26579350612b2a915050565b5050505b9550959350505050565b600077ffffffffffffffffffffffffffffffffffffffffffffffff8316612b6383670de0b6b3a76400006154e0565b611470919061550a565b6000546001600160a01b03163314612be1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b59565b565b60005b8251811015612d44576000838281518110612c0357612c036156f4565b60200260200101516000015190506000848381518110612c2557612c256156f4565b6020026020010151602001519050612c4782600a61327090919063ffffffff16565b612c88576040517f73913ebd0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610b59565b6001600160a01b038116612c9d600a84613285565b6001600160a01b031614612cdd576040517f6cc7b99800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ce8600a83613f47565b15612d3157604080516001600160a01b038085168252831660208201527f987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c910160405180910390a15b505080612d3d90615820565b9050612be6565b5060005b8151811015612f3e576000828281518110612d6557612d656156f4565b60200260200101516000015190506000838381518110612d8757612d876156f4565b602002602001015160200151905060006001600160a01b0316826001600160a01b03161480612dbd57506001600160a01b038116155b15612df4576040517f6c2a418000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166321df0da76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e569190615ba1565b6001600160a01b0316826001600160a01b031614612ea0576040517f6cc7b99800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612eac600a8383613f5c565b15612ef957604080516001600160a01b038085168252831660208201527f95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c910160405180910390a1612f2b565b6040517f3caf458500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505080612f3790615820565b9050612d48565b505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152612fd182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642612fb59190615bbe565b85608001516fffffffffffffffffffffffffffffffff16613f7a565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6012546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000916bffffffffffffffffffffffff16907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613087573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ab9190615566565b610e1e9190615bd1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612f3e908490613fa2565b60005b82518110156131c6576000838281518110613155576131556156f4565b6020026020010151905061317381600d6140a190919063ffffffff16565b156131b5576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506131bf81615820565b9050613138565b5060005b8151811015612f3e5760008282815181106131e7576131e76156f4565b6020026020010151905060006001600160a01b0316816001600160a01b0316036132115750613260565b61321c600d826140b6565b1561325e576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b61326981615820565b90506131ca565b6000611470836001600160a01b0384166140cb565b6000611470836001600160a01b0384166140d7565b60808101516001600160a01b03166132de576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600580546020808501516040808701516060808901516001600160a01b039889167fffffffffffffffffffff00000000000000000000000000000000000000000000909716969096177401000000000000000000000000000000000000000061ffff9586168102919091177fffffffff000000000000ffffffffffffffffffffffffffffffffffffffffffff1676010000000000000000000000000000000000000000000063ffffffff948516027fffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffff16177a0100000000000000000000000000000000000000000000000000009590971694909402959095179095556080808801516006805460a0808c015160c0808e0151958d167fffffffffffffffff000000000000000000000000000000000000000000000000909416939093179a169096029890981777ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff93841602179055825160e0810184527f0000000000000000000000000000000000000000000000000000000000000000891681527f00000000000000000000000000000000000000000000000000000000000000008216958101959095527f00000000000000000000000000000000000000000000000000000000000000008116858401527f000000000000000000000000000000000000000000000000000000000000000016948401949094527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16938301939093527f00000000000000000000000000000000000000000000000000000000000000008516908201527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517f72c6aaba4dde02f77d291123a76185c418ba63f8c217a2d56b08aec84e9bbfb8916111b8918490615bf1565b80516040811115613604576040517fb5a10cfa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012546c01000000000000000000000000900463ffffffff1615801590613652575060125463ffffffff6c010000000000000000000000008204166bffffffffffffffffffffffff90911610155b1561365f5761365f6121be565b600061366b6007613b26565b90505b80156136ad57600061368c613684600184615bbe565b600790613b31565b50905061369a6007826140e3565b5050806136a690615ce6565b905061366e565b506000805b828110156137bb5760008482815181106136ce576136ce6156f4565b602002602001015160000151905060008583815181106136f0576136f06156f4565b60200260200101516020015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316148061374557506001600160a01b038216155b15613787576040517f4de938d10000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610b59565b61379760078361ffff84166140f8565b506137a661ffff821685615b84565b93505050806137b490615820565b90506136b2565b50601280547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790556040517f8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd249061382d9083908690615d1b565b60405180910390a1505050565b606060006114708361410e565b6001600160a01b03811660009081526001830160205260408120541515611470565b81516000805b82811015613a0e576000846001600160a01b031663d02641a087848151811061389a5761389a6156f4565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b0390911660048201526024016040805180830381865afa158015613901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139259190615d3a565b51905077ffffffffffffffffffffffffffffffffffffffffffffffff81166000036139a65785828151811061395c5761395c6156f4565b6020908102919091010151516040517f9a655f7b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610b59565b6139f08683815181106139bb576139bb6156f4565b6020026020010151602001518277ffffffffffffffffffffffffffffffffffffffffffffffff16613f1890919063ffffffff16565b6139fa90846154f7565b92505080613a0790615820565b905061386f565b506128a8600382600061416a565b60008060001b828460200151856080015186606001518760e0015188610100015180519060200120896101200151604051602001613a5a9190615d6d565b604051602081830303815290604052805190602001208a60a001518b60c001518c61014001518d60400151604051602001613b089c9b9a999897969594939291909b8c5260208c019a909a5267ffffffffffffffff98891660408c01529690971660608a01526001600160a01b0394851660808a015292841660a089015260c088019190915260e0870152610100860152911515610120850152166101408301526101608201526101800190565b60405160208183030381529060405280519060200120905092915050565b60006110f3826144b9565b6000808080613b4086866144c4565b909450925050505b9250929050565b8154600090613b7890700100000000000000000000000000000000900463ffffffff1642615bbe565b90508015613c1a5760018301548354613bc0916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416613f7a565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613c40916fffffffffffffffffffffffffffffffff90811691166144ef565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061382d9084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b60006110f382613b26565b6000808080613b408686613b31565b60005b8151811015613df8576000828281518110613d6157613d616156f4565b6020908102919091018101516040805180820182528284015161ffff90811682528284015163ffffffff90811683870190815294516001600160a01b0316600090815260109096529290942090518154935190921662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909316919093161717905550613df181615820565b9050613d44565b507f4230c60a9725eb5fb992cf6a215398b4e81b4606d4a1e6be8dfe0b60dc172ec1816040516111b89190615d80565b6000611470836001600160a01b038416614505565b336001600160a01b03821603613eaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b59565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a7640000612b638377ffffffffffffffffffffffffffffffffffffffffffffffff86166154e0565b6000611470836001600160a01b038416614511565b6000613f72846001600160a01b0385168461451d565b949350505050565b6000613f9985613f8a84866154e0565b613f9490876154f7565b6144ef565b95945050505050565b6000613ff7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166145339092919063ffffffff16565b805190915015612f3e578080602001905181019061401591906155db565b612f3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b59565b6000611470836001600160a01b038416614542565b6000611470836001600160a01b03841661463c565b60006114708383614505565b6000611470838361468b565b6000611470836001600160a01b038416614715565b6000613f72846001600160a01b03851684614732565b60608160000180548060200260200160405190810160405280929190818152602001828054801561415e57602002820191906000526020600020905b81548152602001906001019080831161414a575b50505050509050919050565b825474010000000000000000000000000000000000000000900460ff161580614191575081155b1561419b57505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906141e190700100000000000000000000000000000000900463ffffffff1642615bbe565b905080156142a15781831115614223576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600186015461425d9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613f7a565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561433e576001600160a01b0384166142f3576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610b59565b6040517f1a76572a00000000000000000000000000000000000000000000000000000000815260048101839052602481018690526001600160a01b0385166044820152606401610b59565b848310156144375760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906143829082615bbe565b61438c878a615bbe565b61439691906154f7565b6143a0919061550a565b90506001600160a01b0386166143ec576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610b59565b6040517fd0c8d23a00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526001600160a01b0387166044820152606401610b59565b6144418584615bbe565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60006110f38261474f565b600080806144d28585614759565b600081815260029690960160205260409095205494959350505050565b60008183106144fe5781611470565b5090919050565b60006114708383614765565b60006114708383614715565b6000613f7284846001600160a01b038516614732565b6060613f72848460008561477d565b6000818152600183016020526040812054801561462b576000614566600183615bbe565b855490915060009061457a90600190615bbe565b90508181146145df57600086600001828154811061459a5761459a6156f4565b90600052602060002001549050808760000184815481106145bd576145bd6156f4565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806145f0576145f0615ddf565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506110f3565b60009150506110f3565b5092915050565b6000818152600183016020526040812054614683575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556110f3565b5060006110f3565b6000818152600283016020526040812054801515806146af57506146af8484614505565b611470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b657900006044820152606401610b59565b600081815260028301602052604081208190556114708383614889565b60008281526002840160205260408120829055613f728484614895565b60006110f3825490565b600061147083836148a1565b60008181526001830160205260408120541515611470565b60608247101561480f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610b59565b600080866001600160a01b0316858760405161482b9190615e0e565b60006040518083038185875af1925050503d8060008114614868576040519150601f19603f3d011682016040523d82523d6000602084013e61486d565b606091505b509150915061487e878383876148cb565b979650505050505050565b60006114708383614542565b6000611470838361463c565b60008260000182815481106148b8576148b86156f4565b9060005260206000200154905092915050565b6060831561495457825160000361494d576001600160a01b0385163b61494d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b59565b5081613f72565b613f7283838151156149695781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b599190614ab9565b60e081016110f382846001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015280606085015116606086015250506bffffffffffffffffffffffff60808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b6001600160a01b03811681146109ea57600080fd5b600060208284031215614a4057600080fd5b813561147081614a19565b60005b83811015614a66578181015183820152602001614a4e565b50506000910152565b60008151808452614a87816020860160208601614a4b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006114706020830184614a6f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff81118282101715614b1e57614b1e614acc565b60405290565b6040805190810167ffffffffffffffff81118282101715614b1e57614b1e614acc565b6040516060810167ffffffffffffffff81118282101715614b1e57614b1e614acc565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614bb157614bb1614acc565b604052919050565b600067ffffffffffffffff821115614bd357614bd3614acc565b5060051b60200190565b803563ffffffff81168114614bf157600080fd5b919050565b67ffffffffffffffff811681146109ea57600080fd5b80151581146109ea57600080fd5b60006020808385031215614c2d57600080fd5b823567ffffffffffffffff811115614c4457600080fd5b8301601f81018513614c5557600080fd5b8035614c68614c6382614bb9565b614b6a565b81815260e09182028301840191848201919088841115614c8757600080fd5b938501935b83851015614d325780858a031215614ca45760008081fd5b614cac614afb565b8535614cb781614a19565b8152614cc4868801614bdd565b878201526040614cd5818801614bdd565b908201526060614ce6878201614bdd565b90820152608086810135614cf981614bf6565b9082015260a086810135614d0c81614bf6565b9082015260c086810135614d1f81614c0c565b9082015283529384019391850191614c8c565b50979650505050505050565b600060a082840312156120cc57600080fd5b600060208284031215614d6257600080fd5b813567ffffffffffffffff811115614d7957600080fd5b613f7284828501614d3e565b600082601f830112614d9657600080fd5b81356020614da6614c6383614bb9565b82815260069290921b84018101918181019086841115614dc557600080fd5b8286015b84811015614e165760408189031215614de25760008081fd5b614dea614b24565b8135614df581614a19565b815281850135614e0481614a19565b81860152835291830191604001614dc9565b509695505050505050565b60008060408385031215614e3457600080fd5b823567ffffffffffffffff80821115614e4c57600080fd5b614e5886838701614d85565b93506020850135915080821115614e6e57600080fd5b50614e7b85828601614d85565b9150509250929050565b60008060408385031215614e9857600080fd5b8235614ea381614a19565b91506020830135614eb381614a19565b809150509250929050565b600082601f830112614ecf57600080fd5b81356020614edf614c6383614bb9565b82815260059290921b84018101918181019086841115614efe57600080fd5b8286015b84811015614e16578035614f1581614a19565b8352918301918301614f02565b60008060408385031215614f3557600080fd5b823567ffffffffffffffff80821115614f4d57600080fd5b614f5986838701614ebe565b93506020850135915080821115614f6f57600080fd5b50614e7b85828601614ebe565b803561ffff81168114614bf157600080fd5b600060e08284031215614fa057600080fd5b614fa8614afb565b8235614fb381614a19565b8152614fc160208401614f7c565b6020820152614fd260408401614bdd565b6040820152614fe360608401614f7c565b60608201526080830135614ff681614a19565b608082015261500760a08401614bdd565b60a082015260c083013561501a81614bf6565b60c08201529392505050565b60e081016110f382846001600160a01b03808251168352602082015161ffff80821660208601526040840151915063ffffffff80831660408701528160608601511660608701528360808601511660808701528060a08601511660a08701525050505067ffffffffffffffff60c08201511660c08301525050565b600080602083850312156150b457600080fd5b823567ffffffffffffffff808211156150cc57600080fd5b818501915085601f8301126150e057600080fd5b8135818111156150ef57600080fd5b8660208260061b850101111561510457600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b818110156151575783516001600160a01b031683529284019291840191600101615132565b50909695505050505050565b60008060006060848603121561517857600080fd5b833567ffffffffffffffff81111561518f57600080fd5b61519b86828701614d3e565b9350506020840135915060408401356151b381614a19565b809150509250925092565b600081518084526020808501945080840160005b8381101561520657815180516001600160a01b0316885283015161ffff1683880152604090960195908201906001016151d2565b509495945050505050565b60408152600061522460408301856151be565b90508260208301529392505050565b80356fffffffffffffffffffffffffffffffff81168114614bf157600080fd5b60006060828403121561526557600080fd5b61526d614b47565b823561527881614c0c565b815261528660208401615233565b602082015261529760408401615233565b60408201529392505050565b600060208083850312156152b657600080fd5b823567ffffffffffffffff8111156152cd57600080fd5b8301601f810185136152de57600080fd5b80356152ec614c6382614bb9565b8181526060918202830184019184820191908884111561530b57600080fd5b938501935b83851015614d325780858a0312156153285760008081fd5b615330614b47565b853561533b81614a19565b8152615348868801614f7c565b878201526040615359818801614bdd565b9082015283529384019391850191615310565b60006020828403121561537e57600080fd5b813561147081614c0c565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126153be57600080fd5b83018035915067ffffffffffffffff8211156153d957600080fd5b602001915036819003821315613b4857600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261542357600080fd5b83018035915067ffffffffffffffff82111561543e57600080fd5b6020019150600681901b3603821315613b4857600080fd5b805177ffffffffffffffffffffffffffffffffffffffffffffffff81168114614bf157600080fd5b6000806040838503121561549157600080fd5b61549a83615456565b91506154a860208401615456565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176110f3576110f36154b1565b808201808211156110f3576110f36154b1565b600082615540577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b67ffffffffffffffff818116838216019080821115614635576146356154b1565b60006020828403121561557857600080fd5b5051919050565b60006040828403121561559157600080fd5b615599614b24565b82356155a481614a19565b81526155b260208401614f7c565b60208201529392505050565b6000602082840312156155d057600080fd5b815161147081614bf6565b6000602082840312156155ed57600080fd5b815161147081614c0c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000613f726020830184866155f8565b60006020828403121561566757600080fd5b5035919050565b60006040828403121561568057600080fd5b615688614b24565b823561569381614a19565b81526020928301359281019290925250919050565b6bffffffffffffffffffffffff818116838216019080821115614635576146356154b1565b600067ffffffffffffffff8083168181036156ea576156ea6154b1565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6001600160a01b038716815260a06020820152600061574660a0830187896155f8565b85604084015267ffffffffffffffff851660608401528281036080840152610dcc8185614a6f565b60006020828403121561578057600080fd5b815167ffffffffffffffff8082111561579857600080fd5b818401915084601f8301126157ac57600080fd5b8151818111156157be576157be614acc565b6157ef60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614b6a565b915080825285602082850101111561580657600080fd5b615817816020840160208601614a4b565b50949350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615851576158516154b1565b5060010190565b600081518084526020808501945080840160005b8381101561520657815180516001600160a01b03168852830151838801526040909601959082019060010161586c565b602081526158b760208201835167ffffffffffffffff169052565b600060208301516158d4604084018267ffffffffffffffff169052565b506040830151606083015260608301516158f960808401826001600160a01b03169052565b50608083015167ffffffffffffffff811660a08401525060a083015160c083015260c083015161592d60e084018215159052565b5060e083015161010061594a818501836001600160a01b03169052565b80850151915050610180610120818186015261596a6101a0860184614a6f565b92508086015190506101407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086850301818701526159a88483615858565b9350808701519150506101606159c8818701836001600160a01b03169052565b959095015193019290925250919050565b6bffffffffffffffffffffffff828116828216039080821115614635576146356154b1565b602080825282518282018190526000919060409081850190868401855b82811015615aa857815180516001600160a01b031685528681015163ffffffff90811688870152868201518116878701526060808301519091169086015260808082015167ffffffffffffffff169086015260a080820151615a888288018267ffffffffffffffff169052565b505060c09081015115159085015260e09093019290850190600101615a1b565b5091979650505050505050565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015615af55780818660040360031b1b83161692505b505092915050565b60008085851115615b0d57600080fd5b83861115615b1a57600080fd5b5050820193919092039150565b600060208284031215615b3957600080fd5b6040516020810181811067ffffffffffffffff82111715615b5c57615b5c614acc565b6040529135825250919050565b600060208284031215615b7b57600080fd5b61147082615456565b63ffffffff818116838216019080821115614635576146356154b1565b600060208284031215615bb357600080fd5b815161147081614a19565b818103818111156110f3576110f36154b1565b8181036000831280158383131683831282161715614635576146356154b1565b6101c08101615c6e82856001600160a01b03808251168352602082015167ffffffffffffffff808216602086015280604085015116604086015280606085015116606086015250506bffffffffffffffffffffffff60808301511660808401528060a08301511660a08401528060c08301511660c0840152505050565b82516001600160a01b0390811660e0840152602084015161ffff908116610100850152604085015163ffffffff9081166101208601526060860151909116610140850152608085015190911661016084015260a08401511661018083015260c083015167ffffffffffffffff166101a0830152611470565b600081615cf557615cf56154b1565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b63ffffffff83168152604060208201526000613f7260408301846151be565b600060408284031215615d4c57600080fd5b615d54614b24565b615d5d83615456565b815260208301516155b281614bf6565b6020815260006114706020830184615858565b602080825282518282018190526000919060409081850190868401855b82811015615aa857815180516001600160a01b031685528681015161ffff168786015285015163ffffffff168585015260609093019290850190600101615d9d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251615e20818460208701614a4b565b919091019291505056fea164736f6c6343000813000a", -} - -var EVM2EVMOnRampABI = EVM2EVMOnRampMetaData.ABI - -var EVM2EVMOnRampBin = EVM2EVMOnRampMetaData.Bin - -func DeployEVM2EVMOnRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMOnRampStaticConfig, dynamicConfig EVM2EVMOnRampDynamicConfig, tokensAndPools []InternalPoolUpdate, allowlist []common.Address, rateLimiterConfig RateLimiterConfig, feeTokenConfigs []EVM2EVMOnRampFeeTokenConfigArgs, tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs, nopsAndWeights []EVM2EVMOnRampNopAndWeight) (common.Address, *types.Transaction, *EVM2EVMOnRamp, error) { - parsed, err := EVM2EVMOnRampMetaData.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(EVM2EVMOnRampBin), backend, staticConfig, dynamicConfig, tokensAndPools, allowlist, rateLimiterConfig, feeTokenConfigs, tokenTransferFeeConfigArgs, nopsAndWeights) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &EVM2EVMOnRamp{EVM2EVMOnRampCaller: EVM2EVMOnRampCaller{contract: contract}, EVM2EVMOnRampTransactor: EVM2EVMOnRampTransactor{contract: contract}, EVM2EVMOnRampFilterer: EVM2EVMOnRampFilterer{contract: contract}}, nil -} - -type EVM2EVMOnRamp struct { - address common.Address - abi abi.ABI - EVM2EVMOnRampCaller - EVM2EVMOnRampTransactor - EVM2EVMOnRampFilterer -} - -type EVM2EVMOnRampCaller struct { - contract *bind.BoundContract -} - -type EVM2EVMOnRampTransactor struct { - contract *bind.BoundContract -} - -type EVM2EVMOnRampFilterer struct { - contract *bind.BoundContract -} - -type EVM2EVMOnRampSession struct { - Contract *EVM2EVMOnRamp - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type EVM2EVMOnRampCallerSession struct { - Contract *EVM2EVMOnRampCaller - CallOpts bind.CallOpts -} - -type EVM2EVMOnRampTransactorSession struct { - Contract *EVM2EVMOnRampTransactor - TransactOpts bind.TransactOpts -} - -type EVM2EVMOnRampRaw struct { - Contract *EVM2EVMOnRamp -} - -type EVM2EVMOnRampCallerRaw struct { - Contract *EVM2EVMOnRampCaller -} - -type EVM2EVMOnRampTransactorRaw struct { - Contract *EVM2EVMOnRampTransactor -} - -func NewEVM2EVMOnRamp(address common.Address, backend bind.ContractBackend) (*EVM2EVMOnRamp, error) { - abi, err := abi.JSON(strings.NewReader(EVM2EVMOnRampABI)) - if err != nil { - return nil, err - } - contract, err := bindEVM2EVMOnRamp(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &EVM2EVMOnRamp{address: address, abi: abi, EVM2EVMOnRampCaller: EVM2EVMOnRampCaller{contract: contract}, EVM2EVMOnRampTransactor: EVM2EVMOnRampTransactor{contract: contract}, EVM2EVMOnRampFilterer: EVM2EVMOnRampFilterer{contract: contract}}, nil -} - -func NewEVM2EVMOnRampCaller(address common.Address, caller bind.ContractCaller) (*EVM2EVMOnRampCaller, error) { - contract, err := bindEVM2EVMOnRamp(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampCaller{contract: contract}, nil -} - -func NewEVM2EVMOnRampTransactor(address common.Address, transactor bind.ContractTransactor) (*EVM2EVMOnRampTransactor, error) { - contract, err := bindEVM2EVMOnRamp(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampTransactor{contract: contract}, nil -} - -func NewEVM2EVMOnRampFilterer(address common.Address, filterer bind.ContractFilterer) (*EVM2EVMOnRampFilterer, error) { - contract, err := bindEVM2EVMOnRamp(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampFilterer{contract: contract}, nil -} - -func bindEVM2EVMOnRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EVM2EVMOnRampMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMOnRamp.Contract.EVM2EVMOnRampCaller.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.EVM2EVMOnRampTransactor.contract.Transfer(opts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.EVM2EVMOnRampTransactor.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _EVM2EVMOnRamp.Contract.contract.Call(opts, result, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.contract.Transfer(opts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.contract.Transact(opts, method, params...) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "currentRateLimiterState") - - if err != nil { - return *new(RateLimiterTokenBucket), err - } - - out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMOnRamp.Contract.CurrentRateLimiterState(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMOnRamp.Contract.CurrentRateLimiterState(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetAllowList() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetAllowList(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetAllowList() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetAllowList(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getAllowListEnabled") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetAllowListEnabled() (bool, error) { - return _EVM2EVMOnRamp.Contract.GetAllowListEnabled(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetAllowListEnabled() (bool, error) { - return _EVM2EVMOnRamp.Contract.GetAllowListEnabled(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMOnRampDynamicConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getDynamicConfig") - - if err != nil { - return *new(EVM2EVMOnRampDynamicConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampDynamicConfig)).(*EVM2EVMOnRampDynamicConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetDynamicConfig() (EVM2EVMOnRampDynamicConfig, error) { - return _EVM2EVMOnRamp.Contract.GetDynamicConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetDynamicConfig() (EVM2EVMOnRampDynamicConfig, error) { - return _EVM2EVMOnRamp.Contract.GetDynamicConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getExpectedNextSequenceNumber") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetExpectedNextSequenceNumber(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetExpectedNextSequenceNumber() (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetExpectedNextSequenceNumber(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetFee(opts *bind.CallOpts, message ClientEVM2AnyMessage) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getFee", message) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetFee(message ClientEVM2AnyMessage) (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetFee(&_EVM2EVMOnRamp.CallOpts, message) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetFee(message ClientEVM2AnyMessage) (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetFee(&_EVM2EVMOnRamp.CallOpts, message) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetFeeTokenConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getFeeTokenConfig", token) - - if err != nil { - return *new(EVM2EVMOnRampFeeTokenConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampFeeTokenConfig)).(*EVM2EVMOnRampFeeTokenConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetFeeTokenConfig(token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) { - return _EVM2EVMOnRamp.Contract.GetFeeTokenConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetFeeTokenConfig(token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) { - return _EVM2EVMOnRamp.Contract.GetFeeTokenConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetNopFeesJuels(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getNopFeesJuels") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetNopFeesJuels() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetNopFeesJuels(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetNopFeesJuels() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.GetNopFeesJuels(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetNops(opts *bind.CallOpts) (GetNops, - - error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getNops") - - outstruct := new(GetNops) - if err != nil { - return *outstruct, err - } - - outstruct.NopsAndWeights = *abi.ConvertType(out[0], new([]EVM2EVMOnRampNopAndWeight)).(*[]EVM2EVMOnRampNopAndWeight) - outstruct.WeightsTotal = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetNops() (GetNops, - - error) { - return _EVM2EVMOnRamp.Contract.GetNops(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetNops() (GetNops, - - error) { - return _EVM2EVMOnRamp.Contract.GetNops(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getPoolBySourceToken", sourceToken) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetPoolBySourceToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMOnRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetPoolBySourceToken(sourceToken common.Address) (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMOnRamp.CallOpts, sourceToken) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getSenderNonce", sender) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetSenderNonce(sender common.Address) (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetSenderNonce(&_EVM2EVMOnRamp.CallOpts, sender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetSenderNonce(sender common.Address) (uint64, error) { - return _EVM2EVMOnRamp.Contract.GetSenderNonce(&_EVM2EVMOnRamp.CallOpts, sender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetStaticConfig(opts *bind.CallOpts) (EVM2EVMOnRampStaticConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(EVM2EVMOnRampStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampStaticConfig)).(*EVM2EVMOnRampStaticConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetStaticConfig() (EVM2EVMOnRampStaticConfig, error) { - return _EVM2EVMOnRamp.Contract.GetStaticConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetStaticConfig() (EVM2EVMOnRampStaticConfig, error) { - return _EVM2EVMOnRamp.Contract.GetStaticConfig(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getSupportedTokens") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetSupportedTokens() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetSupportedTokens(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetSupportedTokens() ([]common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetSupportedTokens(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getTokenLimitAdmin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "getTokenTransferFeeConfig", token) - - if err != nil { - return *new(EVM2EVMOnRampTokenTransferFeeConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMOnRampTokenTransferFeeConfig)).(*EVM2EVMOnRampTokenTransferFeeConfig) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) GetTokenTransferFeeConfig(token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) { - return _EVM2EVMOnRamp.Contract.GetTokenTransferFeeConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) GetTokenTransferFeeConfig(token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) { - return _EVM2EVMOnRamp.Contract.GetTokenTransferFeeConfig(&_EVM2EVMOnRamp.CallOpts, token) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampSession) LinkAvailableForPayment() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.LinkAvailableForPayment(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) LinkAvailableForPayment() (*big.Int, error) { - return _EVM2EVMOnRamp.Contract.LinkAvailableForPayment(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampSession) Owner() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.Owner(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) Owner() (common.Address, error) { - return _EVM2EVMOnRamp.Contract.Owner(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _EVM2EVMOnRamp.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) TypeAndVersion() (string, error) { - return _EVM2EVMOnRamp.Contract.TypeAndVersion(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampCallerSession) TypeAndVersion() (string, error) { - return _EVM2EVMOnRamp.Contract.TypeAndVersion(&_EVM2EVMOnRamp.CallOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "acceptOwnership") -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.AcceptOwnership(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.AcceptOwnership(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "applyAllowListUpdates", removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyAllowListUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyAllowListUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) ApplyPoolUpdates(opts *bind.TransactOpts, removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "applyPoolUpdates", removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) ApplyPoolUpdates(removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyPoolUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) ApplyPoolUpdates(removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ApplyPoolUpdates(&_EVM2EVMOnRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) ForwardFromRouter(opts *bind.TransactOpts, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "forwardFromRouter", message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) ForwardFromRouter(message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ForwardFromRouter(&_EVM2EVMOnRamp.TransactOpts, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) ForwardFromRouter(message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.ForwardFromRouter(&_EVM2EVMOnRamp.TransactOpts, message, feeTokenAmount, originalSender) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) PayNops(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "payNops") -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) PayNops() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.PayNops(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) PayNops() (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.PayNops(&_EVM2EVMOnRamp.TransactOpts) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setAdmin", newAdmin) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAdmin(&_EVM2EVMOnRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAdmin(&_EVM2EVMOnRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetAllowListEnabled(opts *bind.TransactOpts, enabled bool) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setAllowListEnabled", enabled) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetAllowListEnabled(enabled bool) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAllowListEnabled(&_EVM2EVMOnRamp.TransactOpts, enabled) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetAllowListEnabled(enabled bool) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetAllowListEnabled(&_EVM2EVMOnRamp.TransactOpts, enabled) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetDynamicConfig(dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetDynamicConfig(&_EVM2EVMOnRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetDynamicConfig(dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetDynamicConfig(&_EVM2EVMOnRamp.TransactOpts, dynamicConfig) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetFeeTokenConfig(opts *bind.TransactOpts, feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setFeeTokenConfig", feeTokenConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetFeeTokenConfig(feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetFeeTokenConfig(&_EVM2EVMOnRamp.TransactOpts, feeTokenConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetFeeTokenConfig(feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetFeeTokenConfig(&_EVM2EVMOnRamp.TransactOpts, feeTokenConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetNops(opts *bind.TransactOpts, nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setNops", nopsAndWeights) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetNops(nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetNops(&_EVM2EVMOnRamp.TransactOpts, nopsAndWeights) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetNops(nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetNops(&_EVM2EVMOnRamp.TransactOpts, nopsAndWeights) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setRateLimiterConfig", config) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetRateLimiterConfig(&_EVM2EVMOnRamp.TransactOpts, config) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetRateLimiterConfig(&_EVM2EVMOnRamp.TransactOpts, config) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) SetTokenTransferFeeConfig(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "setTokenTransferFeeConfig", tokenTransferFeeConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) SetTokenTransferFeeConfig(tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetTokenTransferFeeConfig(&_EVM2EVMOnRamp.TransactOpts, tokenTransferFeeConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) SetTokenTransferFeeConfig(tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.SetTokenTransferFeeConfig(&_EVM2EVMOnRamp.TransactOpts, tokenTransferFeeConfigArgs) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "transferOwnership", to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.TransferOwnership(&_EVM2EVMOnRamp.TransactOpts, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.TransferOwnership(&_EVM2EVMOnRamp.TransactOpts, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactor) WithdrawNonLinkFees(opts *bind.TransactOpts, feeToken common.Address, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.contract.Transact(opts, "withdrawNonLinkFees", feeToken, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampSession) WithdrawNonLinkFees(feeToken common.Address, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.WithdrawNonLinkFees(&_EVM2EVMOnRamp.TransactOpts, feeToken, to) -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampTransactorSession) WithdrawNonLinkFees(feeToken common.Address, to common.Address) (*types.Transaction, error) { - return _EVM2EVMOnRamp.Contract.WithdrawNonLinkFees(&_EVM2EVMOnRamp.TransactOpts, feeToken, to) -} - -type EVM2EVMOnRampAdminSetIterator struct { - Event *EVM2EVMOnRampAdminSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAdminSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAdminSet) - 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(EVM2EVMOnRampAdminSet) - 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 *EVM2EVMOnRampAdminSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAdminSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAdminSet struct { - NewAdmin common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAdminSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAdminSetIterator{contract: _EVM2EVMOnRamp.contract, event: "AdminSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAdminSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "AdminSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampAdminSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AdminSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAdminSet(log types.Log) (*EVM2EVMOnRampAdminSet, error) { - event := new(EVM2EVMOnRampAdminSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AdminSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampAllowListAddIterator struct { - Event *EVM2EVMOnRampAllowListAdd - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAllowListAddIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAllowListAdd) - 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(EVM2EVMOnRampAllowListAdd) - 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 *EVM2EVMOnRampAllowListAddIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAllowListAddIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAllowListAdd struct { - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListAddIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AllowListAdd") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAllowListAddIterator{contract: _EVM2EVMOnRamp.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListAdd) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.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(EVM2EVMOnRampAllowListAdd) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAllowListAdd(log types.Log) (*EVM2EVMOnRampAllowListAdd, error) { - event := new(EVM2EVMOnRampAllowListAdd) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListAdd", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampAllowListEnabledSetIterator struct { - Event *EVM2EVMOnRampAllowListEnabledSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAllowListEnabledSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAllowListEnabledSet) - 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(EVM2EVMOnRampAllowListEnabledSet) - 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 *EVM2EVMOnRampAllowListEnabledSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAllowListEnabledSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAllowListEnabledSet struct { - Enabled bool - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAllowListEnabledSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListEnabledSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AllowListEnabledSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAllowListEnabledSetIterator{contract: _EVM2EVMOnRamp.contract, event: "AllowListEnabledSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAllowListEnabledSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListEnabledSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "AllowListEnabledSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampAllowListEnabledSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListEnabledSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAllowListEnabledSet(log types.Log) (*EVM2EVMOnRampAllowListEnabledSet, error) { - event := new(EVM2EVMOnRampAllowListEnabledSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListEnabledSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampAllowListRemoveIterator struct { - Event *EVM2EVMOnRampAllowListRemove - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampAllowListRemoveIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampAllowListRemove) - 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(EVM2EVMOnRampAllowListRemove) - 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 *EVM2EVMOnRampAllowListRemoveIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampAllowListRemoveIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampAllowListRemove struct { - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListRemoveIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "AllowListRemove") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampAllowListRemoveIterator{contract: _EVM2EVMOnRamp.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListRemove) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.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(EVM2EVMOnRampAllowListRemove) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseAllowListRemove(log types.Log) (*EVM2EVMOnRampAllowListRemove, error) { - event := new(EVM2EVMOnRampAllowListRemove) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "AllowListRemove", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampCCIPSendRequestedIterator struct { - Event *EVM2EVMOnRampCCIPSendRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampCCIPSendRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampCCIPSendRequested) - 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(EVM2EVMOnRampCCIPSendRequested) - 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 *EVM2EVMOnRampCCIPSendRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampCCIPSendRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampCCIPSendRequested struct { - Message InternalEVM2EVMMessage - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterCCIPSendRequested(opts *bind.FilterOpts) (*EVM2EVMOnRampCCIPSendRequestedIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "CCIPSendRequested") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampCCIPSendRequestedIterator{contract: _EVM2EVMOnRamp.contract, event: "CCIPSendRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampCCIPSendRequested) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "CCIPSendRequested") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampCCIPSendRequested) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "CCIPSendRequested", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseCCIPSendRequested(log types.Log) (*EVM2EVMOnRampCCIPSendRequested, error) { - event := new(EVM2EVMOnRampCCIPSendRequested) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampConfigSetIterator struct { - Event *EVM2EVMOnRampConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampConfigSet) - 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(EVM2EVMOnRampConfigSet) - 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 *EVM2EVMOnRampConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampConfigSet struct { - StaticConfig EVM2EVMOnRampStaticConfig - DynamicConfig EVM2EVMOnRampDynamicConfig - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampConfigSetIterator{contract: _EVM2EVMOnRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.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(EVM2EVMOnRampConfigSet) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMOnRampConfigSet, error) { - event := new(EVM2EVMOnRampConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampFeeConfigSetIterator struct { - Event *EVM2EVMOnRampFeeConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampFeeConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampFeeConfigSet) - 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(EVM2EVMOnRampFeeConfigSet) - 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 *EVM2EVMOnRampFeeConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampFeeConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampFeeConfigSet struct { - FeeConfig []EVM2EVMOnRampFeeTokenConfigArgs - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampFeeConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "FeeConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampFeeConfigSetIterator{contract: _EVM2EVMOnRamp.contract, event: "FeeConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampFeeConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "FeeConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "FeeConfigSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseFeeConfigSet(log types.Log) (*EVM2EVMOnRampFeeConfigSet, error) { - event := new(EVM2EVMOnRampFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "FeeConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampNopPaidIterator struct { - Event *EVM2EVMOnRampNopPaid - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampNopPaidIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampNopPaid) - 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(EVM2EVMOnRampNopPaid) - 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 *EVM2EVMOnRampNopPaidIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampNopPaidIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampNopPaid struct { - Nop common.Address - Amount *big.Int - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterNopPaid(opts *bind.FilterOpts, nop []common.Address) (*EVM2EVMOnRampNopPaidIterator, error) { - - var nopRule []interface{} - for _, nopItem := range nop { - nopRule = append(nopRule, nopItem) - } - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "NopPaid", nopRule) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampNopPaidIterator{contract: _EVM2EVMOnRamp.contract, event: "NopPaid", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchNopPaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopPaid, nop []common.Address) (event.Subscription, error) { - - var nopRule []interface{} - for _, nopItem := range nop { - nopRule = append(nopRule, nopItem) - } - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "NopPaid", nopRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampNopPaid) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopPaid", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseNopPaid(log types.Log) (*EVM2EVMOnRampNopPaid, error) { - event := new(EVM2EVMOnRampNopPaid) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopPaid", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampNopsSetIterator struct { - Event *EVM2EVMOnRampNopsSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampNopsSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampNopsSet) - 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(EVM2EVMOnRampNopsSet) - 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 *EVM2EVMOnRampNopsSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampNopsSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampNopsSet struct { - NopWeightsTotal *big.Int - NopsAndWeights []EVM2EVMOnRampNopAndWeight - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterNopsSet(opts *bind.FilterOpts) (*EVM2EVMOnRampNopsSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "NopsSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampNopsSetIterator{contract: _EVM2EVMOnRamp.contract, event: "NopsSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchNopsSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopsSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "NopsSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampNopsSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopsSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseNopsSet(log types.Log) (*EVM2EVMOnRampNopsSet, error) { - event := new(EVM2EVMOnRampNopsSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "NopsSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMOnRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampOwnershipTransferRequested) - 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(EVM2EVMOnRampOwnershipTransferRequested) - 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 *EVM2EVMOnRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferRequestedIterator, 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 := _EVM2EVMOnRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampOwnershipTransferRequestedIterator{contract: _EVM2EVMOnRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferRequested, 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 := _EVM2EVMOnRamp.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(EVM2EVMOnRampOwnershipTransferRequested) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMOnRampOwnershipTransferRequested, error) { - event := new(EVM2EVMOnRampOwnershipTransferRequested) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampOwnershipTransferredIterator struct { - Event *EVM2EVMOnRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampOwnershipTransferred) - 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(EVM2EVMOnRampOwnershipTransferred) - 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 *EVM2EVMOnRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferredIterator, 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 := _EVM2EVMOnRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMOnRampOwnershipTransferredIterator{contract: _EVM2EVMOnRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferred, 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 := _EVM2EVMOnRamp.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(EVM2EVMOnRampOwnershipTransferred) - if err := _EVM2EVMOnRamp.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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMOnRampOwnershipTransferred, error) { - event := new(EVM2EVMOnRampOwnershipTransferred) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampPoolAddedIterator struct { - Event *EVM2EVMOnRampPoolAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampPoolAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampPoolAdded) - 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(EVM2EVMOnRampPoolAdded) - 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 *EVM2EVMOnRampPoolAddedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampPoolAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampPoolAdded struct { - Token common.Address - Pool common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterPoolAdded(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolAddedIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "PoolAdded") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampPoolAddedIterator{contract: _EVM2EVMOnRamp.contract, event: "PoolAdded", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolAdded) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "PoolAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampPoolAdded) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolAdded", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParsePoolAdded(log types.Log) (*EVM2EVMOnRampPoolAdded, error) { - event := new(EVM2EVMOnRampPoolAdded) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampPoolRemovedIterator struct { - Event *EVM2EVMOnRampPoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampPoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampPoolRemoved) - 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(EVM2EVMOnRampPoolRemoved) - 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 *EVM2EVMOnRampPoolRemovedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampPoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampPoolRemoved struct { - Token common.Address - Pool common.Address - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterPoolRemoved(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolRemovedIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "PoolRemoved") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampPoolRemovedIterator{contract: _EVM2EVMOnRamp.contract, event: "PoolRemoved", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolRemoved) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "PoolRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampPoolRemoved) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolRemoved", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParsePoolRemoved(log types.Log) (*EVM2EVMOnRampPoolRemoved, error) { - event := new(EVM2EVMOnRampPoolRemoved) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "PoolRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMOnRampTokenTransferFeeConfigSetIterator struct { - Event *EVM2EVMOnRampTokenTransferFeeConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMOnRampTokenTransferFeeConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMOnRampTokenTransferFeeConfigSet) - 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(EVM2EVMOnRampTokenTransferFeeConfigSet) - 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 *EVM2EVMOnRampTokenTransferFeeConfigSetIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMOnRampTokenTransferFeeConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMOnRampTokenTransferFeeConfigSet struct { - TransferFeeConfig []EVM2EVMOnRampTokenTransferFeeConfigArgs - Raw types.Log -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) FilterTokenTransferFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampTokenTransferFeeConfigSetIterator, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.FilterLogs(opts, "TokenTransferFeeConfigSet") - if err != nil { - return nil, err - } - return &EVM2EVMOnRampTokenTransferFeeConfigSetIterator{contract: _EVM2EVMOnRamp.contract, event: "TokenTransferFeeConfigSet", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) WatchTokenTransferFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampTokenTransferFeeConfigSet) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMOnRamp.contract.WatchLogs(opts, "TokenTransferFeeConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMOnRampTokenTransferFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigSet", 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 (_EVM2EVMOnRamp *EVM2EVMOnRampFilterer) ParseTokenTransferFeeConfigSet(log types.Log) (*EVM2EVMOnRampTokenTransferFeeConfigSet, error) { - event := new(EVM2EVMOnRampTokenTransferFeeConfigSet) - if err := _EVM2EVMOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type GetNops struct { - NopsAndWeights []EVM2EVMOnRampNopAndWeight - WeightsTotal *big.Int -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _EVM2EVMOnRamp.abi.Events["AdminSet"].ID: - return _EVM2EVMOnRamp.ParseAdminSet(log) - case _EVM2EVMOnRamp.abi.Events["AllowListAdd"].ID: - return _EVM2EVMOnRamp.ParseAllowListAdd(log) - case _EVM2EVMOnRamp.abi.Events["AllowListEnabledSet"].ID: - return _EVM2EVMOnRamp.ParseAllowListEnabledSet(log) - case _EVM2EVMOnRamp.abi.Events["AllowListRemove"].ID: - return _EVM2EVMOnRamp.ParseAllowListRemove(log) - case _EVM2EVMOnRamp.abi.Events["CCIPSendRequested"].ID: - return _EVM2EVMOnRamp.ParseCCIPSendRequested(log) - case _EVM2EVMOnRamp.abi.Events["ConfigSet"].ID: - return _EVM2EVMOnRamp.ParseConfigSet(log) - case _EVM2EVMOnRamp.abi.Events["FeeConfigSet"].ID: - return _EVM2EVMOnRamp.ParseFeeConfigSet(log) - case _EVM2EVMOnRamp.abi.Events["NopPaid"].ID: - return _EVM2EVMOnRamp.ParseNopPaid(log) - case _EVM2EVMOnRamp.abi.Events["NopsSet"].ID: - return _EVM2EVMOnRamp.ParseNopsSet(log) - case _EVM2EVMOnRamp.abi.Events["OwnershipTransferRequested"].ID: - return _EVM2EVMOnRamp.ParseOwnershipTransferRequested(log) - case _EVM2EVMOnRamp.abi.Events["OwnershipTransferred"].ID: - return _EVM2EVMOnRamp.ParseOwnershipTransferred(log) - case _EVM2EVMOnRamp.abi.Events["PoolAdded"].ID: - return _EVM2EVMOnRamp.ParsePoolAdded(log) - case _EVM2EVMOnRamp.abi.Events["PoolRemoved"].ID: - return _EVM2EVMOnRamp.ParsePoolRemoved(log) - case _EVM2EVMOnRamp.abi.Events["TokenTransferFeeConfigSet"].ID: - return _EVM2EVMOnRamp.ParseTokenTransferFeeConfigSet(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (EVM2EVMOnRampAdminSet) Topic() common.Hash { - return common.HexToHash("0x8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c") -} - -func (EVM2EVMOnRampAllowListAdd) Topic() common.Hash { - return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8") -} - -func (EVM2EVMOnRampAllowListEnabledSet) Topic() common.Hash { - return common.HexToHash("0xccf4daf6ab6430389f26b970595dab82a5881ad454770907e415ede27c8df032") -} - -func (EVM2EVMOnRampAllowListRemove) Topic() common.Hash { - return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566") -} - -func (EVM2EVMOnRampCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0xaffc45517195d6499808c643bd4a7b0ffeedf95bea5852840d7bfcf63f59e821") -} - -func (EVM2EVMOnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x72c6aaba4dde02f77d291123a76185c418ba63f8c217a2d56b08aec84e9bbfb8") -} - -func (EVM2EVMOnRampFeeConfigSet) Topic() common.Hash { - return common.HexToHash("0x2386f61ab5cafc3fed44f9f614f721ab53479ef64067fd16c1a2491b63ddf1a8") -} - -func (EVM2EVMOnRampNopPaid) Topic() common.Hash { - return common.HexToHash("0x55fdec2aab60a41fa5abb106670eb1006f5aeaee1ba7afea2bc89b5b3ec7678f") -} - -func (EVM2EVMOnRampNopsSet) Topic() common.Hash { - return common.HexToHash("0x8c337bff38141c507abd25c547606bdde78fe8c12e941ab613f3a565fea6cd24") -} - -func (EVM2EVMOnRampOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (EVM2EVMOnRampOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (EVM2EVMOnRampPoolAdded) Topic() common.Hash { - return common.HexToHash("0x95f865c2808f8b2a85eea2611db7843150ee7835ef1403f9755918a97d76933c") -} - -func (EVM2EVMOnRampPoolRemoved) Topic() common.Hash { - return common.HexToHash("0x987eb3c2f78454541205f72f34839b434c306c9eaf4922efd7c0c3060fdb2e4c") -} - -func (EVM2EVMOnRampTokenTransferFeeConfigSet) Topic() common.Hash { - return common.HexToHash("0x4230c60a9725eb5fb992cf6a215398b4e81b4606d4a1e6be8dfe0b60dc172ec1") -} - -func (_EVM2EVMOnRamp *EVM2EVMOnRamp) Address() common.Address { - return _EVM2EVMOnRamp.address -} - -type EVM2EVMOnRampInterface interface { - CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) - - GetAllowList(opts *bind.CallOpts) ([]common.Address, error) - - GetAllowListEnabled(opts *bind.CallOpts) (bool, error) - - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMOnRampDynamicConfig, error) - - GetExpectedNextSequenceNumber(opts *bind.CallOpts) (uint64, error) - - GetFee(opts *bind.CallOpts, message ClientEVM2AnyMessage) (*big.Int, error) - - GetFeeTokenConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampFeeTokenConfig, error) - - GetNopFeesJuels(opts *bind.CallOpts) (*big.Int, error) - - GetNops(opts *bind.CallOpts) (GetNops, - - error) - - GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) - - GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) - - GetStaticConfig(opts *bind.CallOpts) (EVM2EVMOnRampStaticConfig, error) - - GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) - - GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) - - GetTokenTransferFeeConfig(opts *bind.CallOpts, token common.Address) (EVM2EVMOnRampTokenTransferFeeConfig, error) - - LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - - ApplyPoolUpdates(opts *bind.TransactOpts, removes []InternalPoolUpdate, adds []InternalPoolUpdate) (*types.Transaction, error) - - ForwardFromRouter(opts *bind.TransactOpts, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) - - PayNops(opts *bind.TransactOpts) (*types.Transaction, error) - - SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) - - SetAllowListEnabled(opts *bind.TransactOpts, enabled bool) (*types.Transaction, error) - - SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) - - SetFeeTokenConfig(opts *bind.TransactOpts, feeTokenConfigArgs []EVM2EVMOnRampFeeTokenConfigArgs) (*types.Transaction, error) - - SetNops(opts *bind.TransactOpts, nopsAndWeights []EVM2EVMOnRampNopAndWeight) (*types.Transaction, error) - - SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) - - SetTokenTransferFeeConfig(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []EVM2EVMOnRampTokenTransferFeeConfigArgs) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - WithdrawNonLinkFees(opts *bind.TransactOpts, feeToken common.Address, to common.Address) (*types.Transaction, error) - - FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAdminSetIterator, error) - - WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAdminSet) (event.Subscription, error) - - ParseAdminSet(log types.Log) (*EVM2EVMOnRampAdminSet, error) - - FilterAllowListAdd(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListAddIterator, error) - - WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListAdd) (event.Subscription, error) - - ParseAllowListAdd(log types.Log) (*EVM2EVMOnRampAllowListAdd, error) - - FilterAllowListEnabledSet(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListEnabledSetIterator, error) - - WatchAllowListEnabledSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListEnabledSet) (event.Subscription, error) - - ParseAllowListEnabledSet(log types.Log) (*EVM2EVMOnRampAllowListEnabledSet, error) - - FilterAllowListRemove(opts *bind.FilterOpts) (*EVM2EVMOnRampAllowListRemoveIterator, error) - - WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampAllowListRemove) (event.Subscription, error) - - ParseAllowListRemove(log types.Log) (*EVM2EVMOnRampAllowListRemove, error) - - FilterCCIPSendRequested(opts *bind.FilterOpts) (*EVM2EVMOnRampCCIPSendRequestedIterator, error) - - WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampCCIPSendRequested) (event.Subscription, error) - - ParseCCIPSendRequested(log types.Log) (*EVM2EVMOnRampCCIPSendRequested, error) - - FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*EVM2EVMOnRampConfigSet, error) - - FilterFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampFeeConfigSetIterator, error) - - WatchFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampFeeConfigSet) (event.Subscription, error) - - ParseFeeConfigSet(log types.Log) (*EVM2EVMOnRampFeeConfigSet, error) - - FilterNopPaid(opts *bind.FilterOpts, nop []common.Address) (*EVM2EVMOnRampNopPaidIterator, error) - - WatchNopPaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopPaid, nop []common.Address) (event.Subscription, error) - - ParseNopPaid(log types.Log) (*EVM2EVMOnRampNopPaid, error) - - FilterNopsSet(opts *bind.FilterOpts) (*EVM2EVMOnRampNopsSetIterator, error) - - WatchNopsSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampNopsSet) (event.Subscription, error) - - ParseNopsSet(log types.Log) (*EVM2EVMOnRampNopsSet, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMOnRampOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMOnRampOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*EVM2EVMOnRampOwnershipTransferred, error) - - FilterPoolAdded(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolAddedIterator, error) - - WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolAdded) (event.Subscription, error) - - ParsePoolAdded(log types.Log) (*EVM2EVMOnRampPoolAdded, error) - - FilterPoolRemoved(opts *bind.FilterOpts) (*EVM2EVMOnRampPoolRemovedIterator, error) - - WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampPoolRemoved) (event.Subscription, error) - - ParsePoolRemoved(log types.Log) (*EVM2EVMOnRampPoolRemoved, error) - - FilterTokenTransferFeeConfigSet(opts *bind.FilterOpts) (*EVM2EVMOnRampTokenTransferFeeConfigSetIterator, error) - - WatchTokenTransferFeeConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMOnRampTokenTransferFeeConfigSet) (event.Subscription, error) - - ParseTokenTransferFeeConfigSet(log types.Log) (*EVM2EVMOnRampTokenTransferFeeConfigSet, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go new file mode 100644 index 00000000000..45d4f8b5aba --- /dev/null +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -0,0 +1,3068 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package fee_quoter + +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 AuthorizedCallersAuthorizedCallerArgs struct { + AddedCallers []common.Address + RemovedCallers []common.Address +} + +type ClientEVM2AnyMessage struct { + Receiver []byte + Data []byte + TokenAmounts []ClientEVMTokenAmount + FeeToken common.Address + ExtraArgs []byte +} + +type ClientEVMTokenAmount struct { + Token common.Address + Amount *big.Int +} + +type FeeQuoterDestChainConfig struct { + IsEnabled bool + MaxNumberOfTokensPerMsg uint16 + MaxDataBytes uint32 + MaxPerMsgGasLimit uint32 + DestGasOverhead uint32 + DestGasPerPayloadByte uint16 + DestDataAvailabilityOverheadGas uint32 + DestGasPerDataAvailabilityByte uint16 + DestDataAvailabilityMultiplierBps uint16 + DefaultTokenFeeUSDCents uint16 + DefaultTokenDestGasOverhead uint32 + DefaultTxGasLimit uint32 + GasMultiplierWeiPerEth uint64 + NetworkFeeUSDCents uint32 + GasPriceStalenessThreshold uint32 + EnforceOutOfOrder bool + ChainFamilySelector [4]byte +} + +type FeeQuoterDestChainConfigArgs struct { + DestChainSelector uint64 + DestChainConfig FeeQuoterDestChainConfig +} + +type FeeQuoterPremiumMultiplierWeiPerEthArgs struct { + Token common.Address + PremiumMultiplierWeiPerEth uint64 +} + +type FeeQuoterStaticConfig struct { + MaxFeeJuelsPerMsg *big.Int + LinkToken common.Address + TokenPriceStalenessThreshold uint32 +} + +type FeeQuoterTokenPriceFeedConfig struct { + DataFeedAddress common.Address + TokenDecimals uint8 +} + +type FeeQuoterTokenPriceFeedUpdate struct { + SourceToken common.Address + FeedConfig FeeQuoterTokenPriceFeedConfig +} + +type FeeQuoterTokenTransferFeeConfig struct { + MinFeeUSDCents uint32 + MaxFeeUSDCents uint32 + DeciBps uint16 + DestGasOverhead uint32 + DestBytesOverhead uint32 + IsEnabled bool +} + +type FeeQuoterTokenTransferFeeConfigArgs struct { + DestChainSelector uint64 + TokenTransferFeeConfigs []FeeQuoterTokenTransferFeeConfigSingleTokenArgs +} + +type FeeQuoterTokenTransferFeeConfigRemoveArgs struct { + DestChainSelector uint64 + Token common.Address +} + +type FeeQuoterTokenTransferFeeConfigSingleTokenArgs struct { + Token common.Address + TokenTransferFeeConfig FeeQuoterTokenTransferFeeConfig +} + +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte +} + +type InternalGasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas *big.Int +} + +type InternalPriceUpdates struct { + TokenPriceUpdates []InternalTokenPriceUpdate + GasPriceUpdates []InternalGasPriceUpdate +} + +type InternalTimestampedPackedUint224 struct { + Value *big.Int + Timestamp uint32 +} + +type InternalTokenPriceUpdate struct { + SourceToken common.Address + UsdPerToken *big.Int +} + +type KeystoneFeedsPermissionHandlerPermission struct { + Forwarder common.Address + WorkflowName [10]byte + ReportName [2]byte + WorkflowOwner common.Address + IsAllowed bool +} + +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\":\"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\":\"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\":[],\"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\":[{\"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\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"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\":[],\"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\"}],\"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\":\"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\":\"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\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b506040516200789238038062007892833981016040819052620000349162001870565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000206565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b1565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018b908662000400565b620001968462000548565b620001a18162000619565b620001ac8262000a81565b60408051600080825260208201909252620001f991859190620001f2565b6040805180820190915260008082526020820152815260200190600190039081620001ca5790505b5062000b4d565b5050505050505062001b2e565b336001600160a01b03821603620002605760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000341576000828281518110620002da57620002da6200198f565b60209081029190910101519050620002f460028262000e86565b1562000337576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002b9565b50815160005b8151811015620003fa5760008282815181106200036857620003686200198f565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a6576040516342bcdf7f60e11b815260040160405180910390fd5b620003b360028262000ea6565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000347565b50505050565b60005b8251811015620004a1576200043f8382815181106200042657620004266200198f565b6020026020010151600b62000ebd60201b90919060201c565b1562000498578281815181106200045a576200045a6200198f565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b60010162000403565b5060005b81518110156200054357620004e1828281518110620004c857620004c86200198f565b6020026020010151600b62000ea660201b90919060201c565b156200053a57818181518110620004fc57620004fc6200198f565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101620004a5565b505050565b60005b8151811015620006155760008282815181106200056c576200056c6200198f565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054b565b5050565b60005b8151811015620006155760008282815181106200063d576200063d6200198f565b6020026020010151905060008383815181106200065e576200065e6200198f565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000697575061016081015163ffffffff16155b80620006b957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006d95750806060015163ffffffff1681610160015163ffffffff16115b15620007045760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200078457816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda4626582604051620007769190620019a5565b60405180910390a2620007c8565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007bf9190620019a5565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061c565b60005b81518110156200061557600082828151811062000aa55762000aa56200198f565b6020026020010151600001519050600083838151811062000aca5762000aca6200198f565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a84565b60005b825181101562000dc057600083828151811062000b715762000b716200198f565b6020026020010151905060008160000151905060005b82602001515181101562000db15760008360200151828151811062000bb05762000bb06200198f565b602002602001015160200151905060008460200151838151811062000bd95762000bd96200198f565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c385760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d9e908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b87565b50505080600101905062000b50565b5060005b81518110156200054357600082828151811062000de55762000de56200198f565b6020026020010151600001519050600083838151811062000e0a5762000e0a6200198f565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dc4565b600062000e9d836001600160a01b03841662000ed4565b90505b92915050565b600062000e9d836001600160a01b03841662000fd8565b600062000e9d836001600160a01b0384166200102a565b6000818152600183016020526040812054801562000fcd57600062000efb60018362001af6565b855490915060009062000f119060019062001af6565b905081811462000f7d57600086600001828154811062000f355762000f356200198f565b906000526020600020015490508087600001848154811062000f5b5762000f5b6200198f565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f915762000f9162001b18565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000ea0565b600091505062000ea0565b6000818152600183016020526040812054620010215750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000ea0565b50600062000ea0565b6000818152600183016020526040812054801562000fcd5760006200105160018362001af6565b8554909150600090620010679060019062001af6565b905080821462000f7d57600086600001828154811062000f355762000f356200198f565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620010c657620010c66200108b565b60405290565b60405160c081016001600160401b0381118282101715620010c657620010c66200108b565b60405161022081016001600160401b0381118282101715620010c657620010c66200108b565b604051601f8201601f191681016001600160401b03811182821017156200114257620011426200108b565b604052919050565b80516001600160a01b03811681146200116257600080fd5b919050565b805163ffffffff811681146200116257600080fd5b6000606082840312156200118f57600080fd5b604051606081016001600160401b0381118282101715620011b457620011b46200108b565b604052825190915081906001600160601b0381168114620011d457600080fd5b8152620011e4602084016200114a565b6020820152620011f76040840162001167565b60408201525092915050565b60006001600160401b038211156200121f576200121f6200108b565b5060051b60200190565b600082601f8301126200123b57600080fd5b81516020620012546200124e8362001203565b62001117565b8083825260208201915060208460051b8701019350868411156200127757600080fd5b602086015b848110156200129e5762001290816200114a565b83529183019183016200127c565b509695505050505050565b600082601f830112620012bb57600080fd5b81516020620012ce6200124e8362001203565b82815260609283028501820192828201919087851115620012ee57600080fd5b8387015b858110156200138157808903828112156200130d5760008081fd5b62001317620010a1565b62001322836200114a565b8152604080601f1984011215620013395760008081fd5b62001343620010a1565b9250620013528885016200114a565b835283015160ff81168114620013685760008081fd5b82880152808701919091528452928401928101620012f2565b5090979650505050505050565b80516001600160401b03811681146200116257600080fd5b805161ffff811681146200116257600080fd5b805180151581146200116257600080fd5b600082601f830112620013dc57600080fd5b81516020620013ef6200124e8362001203565b82815260059290921b840181019181810190868411156200140f57600080fd5b8286015b848110156200129e5780516001600160401b03808211156200143457600080fd5b908801906040601f19838c0381018213156200144f57600080fd5b62001459620010a1565b620014668986016200138e565b815282850151848111156200147a57600080fd5b8086019550508c603f8601126200149057600080fd5b888501519350620014a56200124e8562001203565b84815260e09094028501830193898101908e861115620014c457600080fd5b958401955b858710156200159d57868f0360e0811215620014e457600080fd5b620014ee620010a1565b620014f9896200114a565b815260c086830112156200150c57600080fd5b62001516620010cc565b9150620015258d8a0162001167565b825262001534878a0162001167565b8d8301526200154660608a01620013a6565b878301526200155860808a0162001167565b60608301526200156b60a08a0162001167565b60808301526200157e60c08a01620013b9565b60a0830152808d0191909152825260e09690960195908a0190620014c9565b828b01525087525050509284019250830162001413565b600082601f830112620015c657600080fd5b81516020620015d96200124e8362001203565b82815260069290921b84018101918181019086841115620015f957600080fd5b8286015b848110156200129e5760408189031215620016185760008081fd5b62001622620010a1565b6200162d826200114a565b81526200163c8583016200138e565b81860152835291830191604001620015fd565b80516001600160e01b0319811681146200116257600080fd5b600082601f8301126200167a57600080fd5b815160206200168d6200124e8362001203565b8281526102409283028501820192828201919087851115620016ae57600080fd5b8387015b85811015620013815780890382811215620016cd5760008081fd5b620016d7620010a1565b620016e2836200138e565b815261022080601f1984011215620016fa5760008081fd5b62001704620010f1565b925062001713888501620013b9565b8352604062001724818601620013a6565b8985015260606200173781870162001167565b82860152608091506200174c82870162001167565b9085015260a06200175f86820162001167565b8286015260c0915062001774828701620013a6565b9085015260e06200178786820162001167565b8286015261010091506200179d828701620013a6565b90850152610120620017b1868201620013a6565b828601526101409150620017c7828701620013a6565b90850152610160620017db86820162001167565b828601526101809150620017f182870162001167565b908501526101a0620018058682016200138e565b828601526101c091506200181b82870162001167565b908501526101e06200182f86820162001167565b82860152610200915062001845828701620013b9565b90850152620018568583016200164f565b9084015250808701919091528452928401928101620016b2565b6000806000806000806000610120888a0312156200188d57600080fd5b6200189989896200117c565b60608901519097506001600160401b0380821115620018b757600080fd5b620018c58b838c0162001229565b975060808a0151915080821115620018dc57600080fd5b620018ea8b838c0162001229565b965060a08a01519150808211156200190157600080fd5b6200190f8b838c01620012a9565b955060c08a01519150808211156200192657600080fd5b620019348b838c01620013ca565b945060e08a01519150808211156200194b57600080fd5b620019598b838c01620015b4565b93506101008a01519150808211156200197157600080fd5b50620019808a828b0162001668565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019c6602084018261ffff169052565b506040830151620019df604084018263ffffffff169052565b506060830151620019f8606084018263ffffffff169052565b50608083015162001a11608084018263ffffffff169052565b5060a083015162001a2860a084018261ffff169052565b5060c083015162001a4160c084018263ffffffff169052565b5060e083015162001a5860e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000ea057634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615d1162001b81600039600081816102fa01526118750152600081816102be01528181610eb80152610f1801526000818161028a01528181610f410152610fb10152615d116000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c8063770e2dc411610104578063a69c64c0116100a2578063d63d3af211610071578063d63d3af214610ab0578063d8694ccd14610ab8578063f2fde38b14610acb578063ffdb4b3714610ade57600080fd5b8063a69c64c0146109d5578063bf78e03f146109e8578063cdc73d5114610a95578063d02641a014610a9d57600080fd5b8063805f2132116100de578063805f21321461081757806382b49eb01461082a5780638da5cb5b1461099a57806391a2749a146109c257600080fd5b8063770e2dc4146107e957806379ba5097146107fc5780637afac3221461080457600080fd5b8063407e10861161017c5780634ab35b0b1161014b5780634ab35b0b14610457578063514e8cff146104975780636cb5f3dd1461053a5780636def4ce71461054d57600080fd5b8063407e1086146103ee57806341ed29e714610401578063430d138c1461041457806345ac924d1461043757600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec3660046143f1565b610b26565b6040519081526020015b60405180910390f35b61024461021236600461442d565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906144ac565b6103c4610b94565b6040516101fb91906144bf565b6101f1602481565b6103ec6103e7366004614519565b610ba5565b005b6103ec6103fc3660046146bb565b610e5a565b6103ec61040f3660046147ed565b610e6e565b6104276104223660046149c7565b610eb0565b6040516101fb9493929190614abb565b61044a610445366004614b5a565b6110c0565b6040516101fb9190614b9c565b61046a61046536600461442d565b61118b565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61052d6104a5366004614c17565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614c32565b6103ec610548366004614cc3565b611196565b6107dc61055b366004614c17565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101fb9190614ee3565b6103ec6107f73660046150e1565b6111a7565b6103ec6111b9565b6103ec6108123660046153fb565b6112b6565b6103ec61082536600461545f565b6112c8565b61093a6108383660046154cb565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec6109d03660046154f5565b6117b0565b6103ec6109e3366004615586565b6117c1565b610a616109f636600461442d565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101fb565b6103c46117d2565b61052d610aab36600461442d565b6117de565b6101f1601281565b6101f1610ac636600461564b565b61194b565b6103ec610ad936600461442d565b611e83565b610af1610aec3660046156a0565b611e94565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b3182611f4c565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b5885611f4c565b610b80907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856156f9565b610b8a9190615710565b90505b9392505050565b6060610ba06002611fe6565b905090565b610bad611ff3565b6000610bb9828061574b565b9050905060005b81811015610d03576000610bd4848061574b565b83818110610be457610be46157b3565b905060400201803603810190610bfa919061580e565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610cf29290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610bc0565b506000610d13602084018461574b565b9050905060005b81811015610e54576000610d31602086018661574b565b83818110610d4157610d416157b3565b905060400201803603810190610d57919061584b565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e439290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d1a565b50505050565b610e62612038565b610e6b816120b9565b50565b610e76612038565b60005b8151811015610eac57610ea4828281518110610e9757610e976157b3565b60200260200101516121b7565b600101610e79565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1603610f11578a9350610f3f565b610f3c8c8c7f0000000000000000000000000000000000000000000000000000000000000000610b26565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16841115610fe3576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff16906110128c8c84612389565b9050806020015194506110288f8b8b8b8b612532565b925085856110a8836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff8111156110de576110de614554565b60405190808252806020026020018201604052801561112357816020015b60408051808201909152600080825260208201528152602001906001900390816110fc5790505b50905060005b828110156111805761115b868683818110611146576111466157b3565b9050602002016020810190610aab919061442d565b82828151811061116d5761116d6157b3565b6020908102919091010152600101611129565b509150505b92915050565b600061118582611f4c565b61119e612038565b610e6b816128a3565b6111af612038565b610eac8282612d75565b60015473ffffffffffffffffffffffffffffffffffffffff16331461123a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610fda565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6112be612038565b610eac8282613187565b600080600061130c87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132ce92505050565b92509250925061131e338385846132e9565b600061132c8587018761586e565b905060005b81518110156117a557600060076000848481518110611352576113526157b3565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611413578282815181106113bc576113bc6157b3565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fda565b600061145c60128386868151811061142d5761142d6157b3565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613441565b905060066000858581518110611474576114746157b3565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106114e6576114e66157b3565b60200260200101516040015163ffffffff1610156115f057838381518110611510576115106157b3565b60200260200101516000015184848151811061152e5761152e6157b3565b60200260200101516040015160066000878781518110611550576115506157b3565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610fda565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001858581518110611631576116316157b3565b60200260200101516040015163ffffffff168152506006600086868151811061165c5761165c6157b3565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106116f4576116f46157b3565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061174a5761174a6157b3565b6020026020010151604001516040516117939291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a25050600101611331565b505050505050505050565b6117b8612038565b610e6b81613504565b6117c9612038565b610e6b81613690565b6060610ba0600b611fe6565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906118a09042615935565b10156118ac5792915050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611911575092915050565b600061191c8261377a565b9050826020015163ffffffff16816020015163ffffffff1610156119405782611942565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611b85576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fda565b611ba0611b98608085016060860161442d565b600b9061390c565b611bff57611bb4608084016060850161442d565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fda565b6000611c0e604085018561574b565b9150611c6a905082611c236020870187615948565b905083611c308880615948565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061393b92505050565b6000611c84611c7f608087016060880161442d565b611f4c565b90506000611c9787856101c001516139e5565b9050600080808515611cd757611ccb878b611cb860808d0160608e0161442d565b88611cc660408f018f61574b565b613ae5565b91945092509050611cf7565b6101a0870151611cf49063ffffffff16662386f26fc100006156f9565b92505b61010087015160009061ffff1615611d3b57611d38886dffffffffffffffffffffffffffff607088901c16611d2f60208e018e615948565b90508a86613dbd565b90505b61018088015160009067ffffffffffffffff16611d64611d5e60808e018e615948565b8c613e6d565b600001518563ffffffff168b60a0015161ffff168e8060200190611d889190615948565b611d939291506156f9565b8c6080015163ffffffff16611da891906159ad565b611db291906159ad565b611dbc91906159ad565b611dd6906dffffffffffffffffffffffffffff89166156f9565b611de091906156f9565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611e1a919061442d565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611e559067ffffffffffffffff16896156f9565b611e5f91906159ad565b611e6991906159ad565b611e739190615710565b9c9b505050505050505050505050565b611e8b612038565b610e6b81613f2e565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611ef5576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610fda565b611efe84611f4c565b67ffffffffffffffff8416600090815260096020526040902060010154611f40908590700100000000000000000000000000000000900463ffffffff166139e5565b915091505b9250929050565b600080611f58836117de565b9050806020015163ffffffff1660001480611f90575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15611fdf576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610fda565b5192915050565b60606000610b8d83614023565b611ffe60023361390c565b612036576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610fda565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610fda565b60005b8151811015610eac5760008282815181106120d9576120d96157b3565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506120bc565b600061227082600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061237d908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b604080518082019091526000808252602082015260008390036123ca57506040805180820190915267ffffffffffffffff8216815260006020820152610b8d565b60006123d684866159c0565b905060006123e78560048189615a06565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f00000000000000000000000000000000000000000000000000000000001612484578080602001905181019061247b9190615a30565b92505050610b8d565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601612500576040518060400160405280828060200190518101906124ec9190615a5c565b815260006020909101529250610b8d915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b90859081111561258257612582614554565b6040519080825280602002602001820160405280156125b557816020015b60608152602001906001900390816125a05790505b50915060005b858110156128985760008585838181106125d7576125d76157b3565b6125ed926020604090920201908101915061442d565b90506000888884818110612603576126036157b3565b90506020028101906126159190615a75565b612623906040810190615948565b91505060208111156126d35767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff168111156126d3576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610fda565b612743848a8a868181106126e9576126e96157b3565b90506020028101906126fb9190615a75565b612709906020810190615948565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061407f92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b01000000000000000000000000000000000000000000000000000000900490911691906128425781612848565b82606001515b6040805163ffffffff831660208201529192500160405160208183030381529060405288878151811061287d5761287d6157b3565b602002602001018190525050505050508060010190506125bb565b505095945050505050565b60005b8151811015610eac5760008282815181106128c3576128c36157b3565b6020026020010151905060008383815181106128e1576128e16157b3565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061291a575061016081015163ffffffff16155b8061296c57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061298b5750806060015163ffffffff1681610160015163ffffffff16115b156129ce576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610fda565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003612a76578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda4626582604051612a699190614ee3565b60405180910390a2612ab9565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051612ab09190614ee3565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506128a6565b60005b825181101561309e576000838281518110612d9557612d956157b3565b6020026020010151905060008160000151905060005b82602001515181101561309057600083602001518281518110612dd057612dd06157b3565b6020026020010151602001519050600084602001518381518110612df657612df66157b3565b6020026020010151600001519050602063ffffffff16826080015163ffffffff161015612e795760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610fda565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59061307e908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612dab565b505050806001019050612d78565b5060005b81518110156131825760008282815181106130bf576130bf6157b3565b602002602001015160000151905060008383815181106130e1576130e16157b3565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016130a2565b505050565b60005b825181101561322a576131c08382815181106131a8576131a86157b3565b6020026020010151600b6140d190919063ffffffff16565b15613222578281815181106131d7576131d76157b3565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b60010161318a565b5060005b81518110156131825761326482828151811061324c5761324c6157b3565b6020026020010151600b6140f390919063ffffffff16565b156132c65781818151811061327b5761327b6157b3565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010161322e565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff1661343a576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610fda565b5050505050565b60008061344e8486615ab3565b9050600060248260ff1611156134885761346c602460ff8416615935565b61347790600a615bec565b6134819085615710565b90506134ae565b61349660ff83166024615935565b6134a190600a615bec565b6134ab90856156f9565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611942576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b815181101561359f576000828281518110613529576135296157b3565b6020026020010151905061354781600261411590919063ffffffff16565b156135965760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010161350c565b50815160005b8151811015610e545760008282815181106135c2576135c26157b3565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613632576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61363d6002826140f3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016135a5565b60005b8151811015610eac5760008282815181106136b0576136b06157b3565b602002602001015160000151905060008383815181106136d2576136d26157b3565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613693565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156137e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138099190615c12565b50935050925050600082121561384b576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138ca8473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561389b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138bf9190615c62565b876020015185613441565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b8d565b836040015163ffffffff168311156139945760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610fda565b836020015161ffff168211156139d6576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e548461020001518261407f565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169282019290925290831615613add576000816020015163ffffffff1642613a7a9190615935565b90508363ffffffff16811115613adb576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401610fda565b505b519392505050565b6000808083815b81811015613daf576000878783818110613b0857613b086157b3565b905060400201803603810190613b1e9190615c7f565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613c3e576101208d0151613c0b9061ffff16662386f26fc100006156f9565b613c1590886159ad565b96508c610140015186613c289190615cb8565b9550613c35602086615cb8565b94505050613da7565b604081015160009061ffff1615613cf75760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613c9a578351613c9390611f4c565b9050613c9d565b508a5b620186a0836040015161ffff16613cdf8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661413790919063ffffffff16565b613ce991906156f9565b613cf39190615710565b9150505b6060820151613d069088615cb8565b9650816080015186613d189190615cb8565b8251909650600090613d379063ffffffff16662386f26fc100006156f9565b905080821015613d5657613d4b818a6159ad565b985050505050613da7565b6000836020015163ffffffff16662386f26fc10000613d7591906156f9565b905080831115613d9557613d89818b6159ad565b99505050505050613da7565b613d9f838b6159ad565b995050505050505b600101613aec565b505096509650969350505050565b60008063ffffffff8316613dd3610120866156f9565b613ddf876101e06159ad565b613de991906159ad565b613df391906159ad565b905060008760c0015163ffffffff168860e0015161ffff1683613e1691906156f9565b613e2091906159ad565b61010089015190915061ffff16613e476dffffffffffffffffffffffffffff8916836156f9565b613e5191906156f9565b613e6190655af3107a40006156f9565b98975050505050505050565b60408051808201909152600080825260208201526000613e99858585610160015163ffffffff16612389565b9050826060015163ffffffff1681600001511115613ee3576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613ef757508060200151155b15610b8a576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613fad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610fda565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60608160000180548060200260200160405190810160405280929190818152602001828054801561407357602002820191906000526020600020905b81548152602001906001019080831161405f575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610eac5761318281614174565b6000610b8d8373ffffffffffffffffffffffffffffffffffffffff8416614227565b6000610b8d8373ffffffffffffffffffffffffffffffffffffffff8416614321565b6000610b8d8373ffffffffffffffffffffffffffffffffffffffff8416614370565b6000670de0b6b3a764000061416a837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166156f9565b610b8d9190615710565b600081516020146141b357816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fda91906144ac565b6000828060200190518101906141c99190615a5c565b905073ffffffffffffffffffffffffffffffffffffffff8111806141ee575061040081105b1561118557826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fda91906144ac565b6000818152600183016020526040812054801561431057600061424b600183615935565b855490915060009061425f90600190615935565b90508082146142c457600086600001828154811061427f5761427f6157b3565b90600052602060002001549050808760000184815481106142a2576142a26157b3565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142d5576142d5615cd5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611185565b6000915050611185565b5092915050565b600081815260018301602052604081205461436857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611185565b506000611185565b60008181526001830160205260408120548015614310576000614394600183615935565b85549091506000906143a890600190615935565b90508181146142c457600086600001828154811061427f5761427f6157b3565b803573ffffffffffffffffffffffffffffffffffffffff811681146143ec57600080fd5b919050565b60008060006060848603121561440657600080fd5b61440f846143c8565b925060208401359150614424604085016143c8565b90509250925092565b60006020828403121561443f57600080fd5b610b8d826143c8565b6000815180845260005b8181101561446e57602081850181015186830182015201614452565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b8d6020830184614448565b6020808252825182820181905260009190848201906040850190845b8181101561450d57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144db565b50909695505050505050565b60006020828403121561452b57600080fd5b813567ffffffffffffffff81111561454257600080fd5b820160408185031215610b8d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156145a6576145a6614554565b60405290565b60405160a0810167ffffffffffffffff811182821017156145a6576145a6614554565b604051610220810167ffffffffffffffff811182821017156145a6576145a6614554565b60405160c0810167ffffffffffffffff811182821017156145a6576145a6614554565b6040516060810167ffffffffffffffff811182821017156145a6576145a6614554565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561468057614680614554565b604052919050565b600067ffffffffffffffff8211156146a2576146a2614554565b5060051b60200190565b60ff81168114610e6b57600080fd5b600060208083850312156146ce57600080fd5b823567ffffffffffffffff8111156146e557600080fd5b8301601f810185136146f657600080fd5b803561470961470482614688565b614639565b8181526060918202830184019184820191908884111561472857600080fd5b938501935b838510156147c857848903818112156147465760008081fd5b61474e614583565b614757876143c8565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561478b5760008081fd5b614793614583565b92506147a08989016143c8565b83528701356147ae816146ac565b82890152808801919091528352938401939185019161472d565b50979650505050505050565b8015158114610e6b57600080fd5b80356143ec816147d4565b6000602080838503121561480057600080fd5b823567ffffffffffffffff81111561481757600080fd5b8301601f8101851361482857600080fd5b803561483661470482614688565b81815260a0918202830184019184820191908884111561485557600080fd5b938501935b838510156147c85780858a0312156148725760008081fd5b61487a6145ac565b614883866143c8565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146148b85760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146148f15760008081fd5b9082015260606149028782016143c8565b90820152608086810135614915816147d4565b908201528352938401939185019161485a565b803567ffffffffffffffff811681146143ec57600080fd5b60008083601f84011261495257600080fd5b50813567ffffffffffffffff81111561496a57600080fd5b602083019150836020828501011115611f4557600080fd5b60008083601f84011261499457600080fd5b50813567ffffffffffffffff8111156149ac57600080fd5b6020830191508360208260051b8501011115611f4557600080fd5b600080600080600080600080600060c08a8c0312156149e557600080fd5b6149ee8a614928565b98506149fc60208b016143c8565b975060408a0135965060608a013567ffffffffffffffff80821115614a2057600080fd5b614a2c8d838e01614940565b909850965060808c0135915080821115614a4557600080fd5b614a518d838e01614982565b909650945060a08c0135915080821115614a6a57600080fd5b818c0191508c601f830112614a7e57600080fd5b813581811115614a8d57600080fd5b8d60208260061b8501011115614aa257600080fd5b6020830194508093505050509295985092959850929598565b848152600060208515158184015260806040840152614add6080840186614448565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614b49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614b37838351614448565b94870194925090860190600101614afd565b50909b9a5050505050505050505050565b60008060208385031215614b6d57600080fd5b823567ffffffffffffffff811115614b8457600080fd5b614b9085828601614982565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614c0a57614bfa84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614bb9565b5091979650505050505050565b600060208284031215614c2957600080fd5b610b8d82614928565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101611185565b803561ffff811681146143ec57600080fd5b803563ffffffff811681146143ec57600080fd5b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146143ec57600080fd5b60006020808385031215614cd657600080fd5b823567ffffffffffffffff811115614ced57600080fd5b8301601f81018513614cfe57600080fd5b8035614d0c61470482614688565b8181526102409182028301840191848201919088841115614d2c57600080fd5b938501935b838510156147c85784890381811215614d4a5760008081fd5b614d52614583565b614d5b87614928565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614d905760008081fd5b614d986145cf565b9250614da58989016147e2565b83526040614db4818a01614c6d565b8a8501526060614dc5818b01614c7f565b8286015260809150614dd8828b01614c7f565b9085015260a0614de98a8201614c7f565b8286015260c09150614dfc828b01614c6d565b9085015260e0614e0d8a8201614c7f565b828601526101009150614e21828b01614c6d565b90850152610120614e338a8201614c6d565b828601526101409150614e47828b01614c6d565b90850152610160614e598a8201614c7f565b828601526101809150614e6d828b01614c7f565b908501526101a0614e7f8a8201614928565b828601526101c09150614e93828b01614c7f565b908501526101e0614ea58a8201614c7f565b828601526102009150614eb9828b016147e2565b90850152614ec8898301614c93565b90840152508088019190915283529384019391850191614d31565b81511515815261022081016020830151614f03602084018261ffff169052565b506040830151614f1b604084018263ffffffff169052565b506060830151614f33606084018263ffffffff169052565b506080830151614f4b608084018263ffffffff169052565b5060a0830151614f6160a084018261ffff169052565b5060c0830151614f7960c084018263ffffffff169052565b5060e0830151614f8f60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f83011261505a57600080fd5b8135602061506a61470483614688565b82815260069290921b8401810191818101908684111561508957600080fd5b8286015b848110156150d657604081890312156150a65760008081fd5b6150ae614583565b6150b782614928565b81526150c48583016143c8565b8186015283529183019160400161508d565b509695505050505050565b600080604083850312156150f457600080fd5b67ffffffffffffffff8335111561510a57600080fd5b83601f84358501011261511c57600080fd5b61512c6147048435850135614688565b8335840180358083526020808401939260059290921b9091010186101561515257600080fd5b602085358601015b85358601803560051b0160200181101561535f5767ffffffffffffffff8135111561518457600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a030112156151bd57600080fd5b6151c5614583565b6151d160208301614928565b815267ffffffffffffffff604083013511156151ec57600080fd5b88603f60408401358401011261520157600080fd5b6152176147046020604085013585010135614688565b6020604084810135850182810135808552928401939260e00201018b101561523e57600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156153405760e0818d03121561527157600080fd5b615279614583565b615282826143c8565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f030112156152b657600080fd5b6152be6145f3565b6152ca60208401614c7f565b81526152d860408401614c7f565b60208201526152e960608401614c6d565b60408201526152fa60808401614c7f565b606082015261530b60a08401614c7f565b608082015261531d60c08401356147d4565b60c083013560a0820152602082810191909152908452929092019160e001615248565b508060208401525050808552505060208301925060208101905061515a565b5092505067ffffffffffffffff6020840135111561537c57600080fd5b61538c8460208501358501615049565b90509250929050565b600082601f8301126153a657600080fd5b813560206153b661470483614688565b8083825260208201915060208460051b8701019350868411156153d857600080fd5b602086015b848110156150d6576153ee816143c8565b83529183019183016153dd565b6000806040838503121561540e57600080fd5b823567ffffffffffffffff8082111561542657600080fd5b61543286838701615395565b9350602085013591508082111561544857600080fd5b5061545585828601615395565b9150509250929050565b6000806000806040858703121561547557600080fd5b843567ffffffffffffffff8082111561548d57600080fd5b61549988838901614940565b909650945060208701359150808211156154b257600080fd5b506154bf87828801614940565b95989497509550505050565b600080604083850312156154de57600080fd5b6154e783614928565b915061538c602084016143c8565b60006020828403121561550757600080fd5b813567ffffffffffffffff8082111561551f57600080fd5b908301906040828603121561553357600080fd5b61553b614583565b82358281111561554a57600080fd5b61555687828601615395565b82525060208301358281111561556b57600080fd5b61557787828601615395565b60208301525095945050505050565b6000602080838503121561559957600080fd5b823567ffffffffffffffff8111156155b057600080fd5b8301601f810185136155c157600080fd5b80356155cf61470482614688565b81815260069190911b820183019083810190878311156155ee57600080fd5b928401925b82841015615640576040848903121561560c5760008081fd5b615614614583565b61561d856143c8565b815261562a868601614928565b81870152825260409390930192908401906155f3565b979650505050505050565b6000806040838503121561565e57600080fd5b61566783614928565b9150602083013567ffffffffffffffff81111561568357600080fd5b830160a0818603121561569557600080fd5b809150509250929050565b600080604083850312156156b357600080fd5b6156bc836143c8565b915061538c60208401614928565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611185576111856156ca565b600082615746577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261578057600080fd5b83018035915067ffffffffffffffff82111561579b57600080fd5b6020019150600681901b3603821315611f4557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146143ec57600080fd5b60006040828403121561582057600080fd5b615828614583565b615831836143c8565b815261583f602084016157e2565b60208201529392505050565b60006040828403121561585d57600080fd5b615865614583565b61583183614928565b6000602080838503121561588157600080fd5b823567ffffffffffffffff81111561589857600080fd5b8301601f810185136158a957600080fd5b80356158b761470482614688565b818152606091820283018401918482019190888411156158d657600080fd5b938501935b838510156147c85780858a0312156158f35760008081fd5b6158fb614616565b615904866143c8565b81526159118787016157e2565b878201526040615922818801614c7f565b90820152835293840193918501916158db565b81810381811115611185576111856156ca565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261597d57600080fd5b83018035915067ffffffffffffffff82111561599857600080fd5b602001915036819003821315611f4557600080fd5b80820180821115611185576111856156ca565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156150415760049490940360031b84901b1690921692915050565b60008085851115615a1657600080fd5b83861115615a2357600080fd5b5050820193919092039150565b600060408284031215615a4257600080fd5b615a4a614583565b82518152602083015161583f816147d4565b600060208284031215615a6e57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615aa957600080fd5b9190910192915050565b60ff8181168382160190811115611185576111856156ca565b600181815b80851115615b2557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b0b57615b0b6156ca565b80851615615b1857918102915b93841c9390800290615ad1565b509250929050565b600082615b3c57506001611185565b81615b4957506000611185565b8160018114615b5f5760028114615b6957615b85565b6001915050611185565b60ff841115615b7a57615b7a6156ca565b50506001821b611185565b5060208310610133831016604e8410600b8410161715615ba8575081810a611185565b615bb28383615acc565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615be457615be46156ca565b029392505050565b6000610b8d8383615b2d565b805169ffffffffffffffffffff811681146143ec57600080fd5b600080600080600060a08688031215615c2a57600080fd5b615c3386615bf8565b9450602086015193506040860151925060608601519150615c5660808701615bf8565b90509295509295909350565b600060208284031215615c7457600080fd5b8151610b8d816146ac565b600060408284031215615c9157600080fd5b615c99614583565b615ca2836143c8565b8152602083013560208201528091505092915050565b63ffffffff81811683821601908082111561431a5761431a6156ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", +} + +var FeeQuoterABI = FeeQuoterMetaData.ABI + +var FeeQuoterBin = FeeQuoterMetaData.Bin + +func DeployFeeQuoter(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig FeeQuoterStaticConfig, priceUpdaters []common.Address, feeTokens []common.Address, tokenPriceFeeds []FeeQuoterTokenPriceFeedUpdate, tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs, destChainConfigArgs []FeeQuoterDestChainConfigArgs) (common.Address, *types.Transaction, *FeeQuoter, error) { + parsed, err := FeeQuoterMetaData.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(FeeQuoterBin), backend, staticConfig, priceUpdaters, feeTokens, tokenPriceFeeds, tokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs, destChainConfigArgs) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &FeeQuoter{address: address, abi: *parsed, FeeQuoterCaller: FeeQuoterCaller{contract: contract}, FeeQuoterTransactor: FeeQuoterTransactor{contract: contract}, FeeQuoterFilterer: FeeQuoterFilterer{contract: contract}}, nil +} + +type FeeQuoter struct { + address common.Address + abi abi.ABI + FeeQuoterCaller + FeeQuoterTransactor + FeeQuoterFilterer +} + +type FeeQuoterCaller struct { + contract *bind.BoundContract +} + +type FeeQuoterTransactor struct { + contract *bind.BoundContract +} + +type FeeQuoterFilterer struct { + contract *bind.BoundContract +} + +type FeeQuoterSession struct { + Contract *FeeQuoter + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type FeeQuoterCallerSession struct { + Contract *FeeQuoterCaller + CallOpts bind.CallOpts +} + +type FeeQuoterTransactorSession struct { + Contract *FeeQuoterTransactor + TransactOpts bind.TransactOpts +} + +type FeeQuoterRaw struct { + Contract *FeeQuoter +} + +type FeeQuoterCallerRaw struct { + Contract *FeeQuoterCaller +} + +type FeeQuoterTransactorRaw struct { + Contract *FeeQuoterTransactor +} + +func NewFeeQuoter(address common.Address, backend bind.ContractBackend) (*FeeQuoter, error) { + abi, err := abi.JSON(strings.NewReader(FeeQuoterABI)) + if err != nil { + return nil, err + } + contract, err := bindFeeQuoter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &FeeQuoter{address: address, abi: abi, FeeQuoterCaller: FeeQuoterCaller{contract: contract}, FeeQuoterTransactor: FeeQuoterTransactor{contract: contract}, FeeQuoterFilterer: FeeQuoterFilterer{contract: contract}}, nil +} + +func NewFeeQuoterCaller(address common.Address, caller bind.ContractCaller) (*FeeQuoterCaller, error) { + contract, err := bindFeeQuoter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &FeeQuoterCaller{contract: contract}, nil +} + +func NewFeeQuoterTransactor(address common.Address, transactor bind.ContractTransactor) (*FeeQuoterTransactor, error) { + contract, err := bindFeeQuoter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &FeeQuoterTransactor{contract: contract}, nil +} + +func NewFeeQuoterFilterer(address common.Address, filterer bind.ContractFilterer) (*FeeQuoterFilterer, error) { + contract, err := bindFeeQuoter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &FeeQuoterFilterer{contract: contract}, nil +} + +func bindFeeQuoter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FeeQuoterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_FeeQuoter *FeeQuoterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FeeQuoter.Contract.FeeQuoterCaller.contract.Call(opts, result, method, params...) +} + +func (_FeeQuoter *FeeQuoterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeQuoter.Contract.FeeQuoterTransactor.contract.Transfer(opts) +} + +func (_FeeQuoter *FeeQuoterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FeeQuoter.Contract.FeeQuoterTransactor.contract.Transact(opts, method, params...) +} + +func (_FeeQuoter *FeeQuoterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FeeQuoter.Contract.contract.Call(opts, result, method, params...) +} + +func (_FeeQuoter *FeeQuoterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeQuoter.Contract.contract.Transfer(opts) +} + +func (_FeeQuoter *FeeQuoterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FeeQuoter.Contract.contract.Transact(opts, method, params...) +} + +func (_FeeQuoter *FeeQuoterCaller) FEEBASEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "FEE_BASE_DECIMALS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) FEEBASEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.FEEBASEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) FEEBASEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.FEEBASEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) KEYSTONEPRICEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "KEYSTONE_PRICE_DECIMALS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) KEYSTONEPRICEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.KEYSTONEPRICEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) KEYSTONEPRICEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.KEYSTONEPRICEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "convertTokenAmount", fromToken, fromTokenAmount, toToken) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.ConvertTokenAmount(&_FeeQuoter.CallOpts, fromToken, fromTokenAmount, toToken) +} + +func (_FeeQuoter *FeeQuoterCallerSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.ConvertTokenAmount(&_FeeQuoter.CallOpts, fromToken, fromTokenAmount, toToken) +} + +func (_FeeQuoter *FeeQuoterCaller) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getAllAuthorizedCallers") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetAllAuthorizedCallers() ([]common.Address, error) { + return _FeeQuoter.Contract.GetAllAuthorizedCallers(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetAllAuthorizedCallers() ([]common.Address, error) { + return _FeeQuoter.Contract.GetAllAuthorizedCallers(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (FeeQuoterDestChainConfig, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) + + if err != nil { + return *new(FeeQuoterDestChainConfig), err + } + + out0 := *abi.ConvertType(out[0], new(FeeQuoterDestChainConfig)).(*FeeQuoterDestChainConfig) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetDestChainConfig(destChainSelector uint64) (FeeQuoterDestChainConfig, error) { + return _FeeQuoter.Contract.GetDestChainConfig(&_FeeQuoter.CallOpts, destChainSelector) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetDestChainConfig(destChainSelector uint64) (FeeQuoterDestChainConfig, error) { + return _FeeQuoter.Contract.GetDestChainConfig(&_FeeQuoter.CallOpts, destChainSelector) +} + +func (_FeeQuoter *FeeQuoterCaller) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getDestinationChainGasPrice", destChainSelector) + + if err != nil { + return *new(InternalTimestampedPackedUint224), err + } + + out0 := *abi.ConvertType(out[0], new(InternalTimestampedPackedUint224)).(*InternalTimestampedPackedUint224) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetDestinationChainGasPrice(&_FeeQuoter.CallOpts, destChainSelector) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetDestinationChainGasPrice(&_FeeQuoter.CallOpts, destChainSelector) +} + +func (_FeeQuoter *FeeQuoterCaller) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getFeeTokens") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetFeeTokens() ([]common.Address, error) { + return _FeeQuoter.Contract.GetFeeTokens(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetFeeTokens() ([]common.Address, error) { + return _FeeQuoter.Contract.GetFeeTokens(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getPremiumMultiplierWeiPerEth", token) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { + return _FeeQuoter.Contract.GetPremiumMultiplierWeiPerEth(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { + return _FeeQuoter.Contract.GetPremiumMultiplierWeiPerEth(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCaller) GetStaticConfig(opts *bind.CallOpts) (FeeQuoterStaticConfig, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getStaticConfig") + + if err != nil { + return *new(FeeQuoterStaticConfig), err + } + + out0 := *abi.ConvertType(out[0], new(FeeQuoterStaticConfig)).(*FeeQuoterStaticConfig) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetStaticConfig() (FeeQuoterStaticConfig, error) { + return _FeeQuoter.Contract.GetStaticConfig(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetStaticConfig() (FeeQuoterStaticConfig, error) { + return _FeeQuoter.Contract.GetStaticConfig(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, + + error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getTokenAndGasPrices", token, destChainSelector) + + outstruct := new(GetTokenAndGasPrices) + if err != nil { + return *outstruct, err + } + + outstruct.TokenPrice = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.GasPriceValue = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, + + error) { + return _FeeQuoter.Contract.GetTokenAndGasPrices(&_FeeQuoter.CallOpts, token, destChainSelector) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, + + error) { + return _FeeQuoter.Contract.GetTokenAndGasPrices(&_FeeQuoter.CallOpts, token, destChainSelector) +} + +func (_FeeQuoter *FeeQuoterCaller) GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getTokenPrice", token) + + if err != nil { + return *new(InternalTimestampedPackedUint224), err + } + + out0 := *abi.ConvertType(out[0], new(InternalTimestampedPackedUint224)).(*InternalTimestampedPackedUint224) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrice(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrice(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCaller) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (FeeQuoterTokenPriceFeedConfig, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getTokenPriceFeedConfig", token) + + if err != nil { + return *new(FeeQuoterTokenPriceFeedConfig), err + } + + out0 := *abi.ConvertType(out[0], new(FeeQuoterTokenPriceFeedConfig)).(*FeeQuoterTokenPriceFeedConfig) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetTokenPriceFeedConfig(token common.Address) (FeeQuoterTokenPriceFeedConfig, error) { + return _FeeQuoter.Contract.GetTokenPriceFeedConfig(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPriceFeedConfig(token common.Address) (FeeQuoterTokenPriceFeedConfig, error) { + return _FeeQuoter.Contract.GetTokenPriceFeedConfig(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCaller) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getTokenPrices", tokens) + + if err != nil { + return *new([]InternalTimestampedPackedUint224), err + } + + out0 := *abi.ConvertType(out[0], new([]InternalTimestampedPackedUint224)).(*[]InternalTimestampedPackedUint224) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrices(&_FeeQuoter.CallOpts, tokens) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrices(&_FeeQuoter.CallOpts, tokens) +} + +func (_FeeQuoter *FeeQuoterCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getTokenTransferFeeConfig", destChainSelector, token) + + if err != nil { + return *new(FeeQuoterTokenTransferFeeConfig), err + } + + out0 := *abi.ConvertType(out[0], new(FeeQuoterTokenTransferFeeConfig)).(*FeeQuoterTokenTransferFeeConfig) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) { + return _FeeQuoter.Contract.GetTokenTransferFeeConfig(&_FeeQuoter.CallOpts, destChainSelector, token) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) { + return _FeeQuoter.Contract.GetTokenTransferFeeConfig(&_FeeQuoter.CallOpts, destChainSelector, token) +} + +func (_FeeQuoter *FeeQuoterCaller) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getValidatedFee", destChainSelector, message) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedFee(&_FeeQuoter.CallOpts, destChainSelector, message) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedFee(&_FeeQuoter.CallOpts, destChainSelector, message) +} + +func (_FeeQuoter *FeeQuoterCaller) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "getValidatedTokenPrice", token) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedTokenPrice(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCallerSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedTokenPrice(&_FeeQuoter.CallOpts, token) +} + +func (_FeeQuoter *FeeQuoterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FeeQuoter.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 (_FeeQuoter *FeeQuoterSession) Owner() (common.Address, error) { + return _FeeQuoter.Contract.Owner(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) Owner() (common.Address, error) { + return _FeeQuoter.Contract.Owner(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, + + error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) + + outstruct := new(ProcessMessageArgs) + if err != nil { + return *outstruct, err + } + + outstruct.MsgFeeJuels = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.IsOutOfOrderExecution = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.ConvertedExtraArgs = *abi.ConvertType(out[2], new([]byte)).(*[]byte) + outstruct.DestExecDataPerToken = *abi.ConvertType(out[3], new([][]byte)).(*[][]byte) + + return *outstruct, err + +} + +func (_FeeQuoter *FeeQuoterSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, + + error) { + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, + + error) { + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) +} + +func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) TypeAndVersion() (string, error) { + return _FeeQuoter.Contract.TypeAndVersion(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) TypeAndVersion() (string, error) { + return _FeeQuoter.Contract.TypeAndVersion(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "acceptOwnership") +} + +func (_FeeQuoter *FeeQuoterSession) AcceptOwnership() (*types.Transaction, error) { + return _FeeQuoter.Contract.AcceptOwnership(&_FeeQuoter.TransactOpts) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _FeeQuoter.Contract.AcceptOwnership(&_FeeQuoter.TransactOpts) +} + +func (_FeeQuoter *FeeQuoterTransactor) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyAuthorizedCallerUpdates", authorizedCallerArgs) +} + +func (_FeeQuoter *FeeQuoterSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyAuthorizedCallerUpdates(&_FeeQuoter.TransactOpts, authorizedCallerArgs) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyAuthorizedCallerUpdates(&_FeeQuoter.TransactOpts, authorizedCallerArgs) +} + +func (_FeeQuoter *FeeQuoterTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) +} + +func (_FeeQuoter *FeeQuoterSession) ApplyDestChainConfigUpdates(destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyDestChainConfigUpdates(&_FeeQuoter.TransactOpts, destChainConfigArgs) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyDestChainConfigUpdates(&_FeeQuoter.TransactOpts, destChainConfigArgs) +} + +func (_FeeQuoter *FeeQuoterTransactor) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToRemove []common.Address, feeTokensToAdd []common.Address) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyFeeTokensUpdates", feeTokensToRemove, feeTokensToAdd) +} + +func (_FeeQuoter *FeeQuoterSession) ApplyFeeTokensUpdates(feeTokensToRemove []common.Address, feeTokensToAdd []common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyFeeTokensUpdates(&_FeeQuoter.TransactOpts, feeTokensToRemove, feeTokensToAdd) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyFeeTokensUpdates(feeTokensToRemove []common.Address, feeTokensToAdd []common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyFeeTokensUpdates(&_FeeQuoter.TransactOpts, feeTokensToRemove, feeTokensToAdd) +} + +func (_FeeQuoter *FeeQuoterTransactor) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyPremiumMultiplierWeiPerEthUpdates", premiumMultiplierWeiPerEthArgs) +} + +func (_FeeQuoter *FeeQuoterSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_FeeQuoter.TransactOpts, premiumMultiplierWeiPerEthArgs) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_FeeQuoter.TransactOpts, premiumMultiplierWeiPerEthArgs) +} + +func (_FeeQuoter *FeeQuoterTransactor) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyTokenTransferFeeConfigUpdates", tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +} + +func (_FeeQuoter *FeeQuoterSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyTokenTransferFeeConfigUpdates(&_FeeQuoter.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyTokenTransferFeeConfigUpdates(&_FeeQuoter.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +} + +func (_FeeQuoter *FeeQuoterTransactor) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "onReport", metadata, report) +} + +func (_FeeQuoter *FeeQuoterSession) OnReport(metadata []byte, report []byte) (*types.Transaction, error) { + return _FeeQuoter.Contract.OnReport(&_FeeQuoter.TransactOpts, metadata, report) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) OnReport(metadata []byte, report []byte) (*types.Transaction, error) { + return _FeeQuoter.Contract.OnReport(&_FeeQuoter.TransactOpts, metadata, report) +} + +func (_FeeQuoter *FeeQuoterTransactor) SetReportPermissions(opts *bind.TransactOpts, permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "setReportPermissions", permissions) +} + +func (_FeeQuoter *FeeQuoterSession) SetReportPermissions(permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + return _FeeQuoter.Contract.SetReportPermissions(&_FeeQuoter.TransactOpts, permissions) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) SetReportPermissions(permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + return _FeeQuoter.Contract.SetReportPermissions(&_FeeQuoter.TransactOpts, permissions) +} + +func (_FeeQuoter *FeeQuoterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "transferOwnership", to) +} + +func (_FeeQuoter *FeeQuoterSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.TransferOwnership(&_FeeQuoter.TransactOpts, to) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.TransferOwnership(&_FeeQuoter.TransactOpts, to) +} + +func (_FeeQuoter *FeeQuoterTransactor) UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "updatePrices", priceUpdates) +} + +func (_FeeQuoter *FeeQuoterSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdatePrices(&_FeeQuoter.TransactOpts, priceUpdates) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdatePrices(&_FeeQuoter.TransactOpts, priceUpdates) +} + +func (_FeeQuoter *FeeQuoterTransactor) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "updateTokenPriceFeeds", tokenPriceFeedUpdates) +} + +func (_FeeQuoter *FeeQuoterSession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdateTokenPriceFeeds(&_FeeQuoter.TransactOpts, tokenPriceFeedUpdates) +} + +func (_FeeQuoter *FeeQuoterTransactorSession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdateTokenPriceFeeds(&_FeeQuoter.TransactOpts, tokenPriceFeedUpdates) +} + +type FeeQuoterAuthorizedCallerAddedIterator struct { + Event *FeeQuoterAuthorizedCallerAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterAuthorizedCallerAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterAuthorizedCallerAdded) + 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(FeeQuoterAuthorizedCallerAdded) + 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 *FeeQuoterAuthorizedCallerAddedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterAuthorizedCallerAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterAuthorizedCallerAdded struct { + Caller common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerAddedIterator, error) { + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "AuthorizedCallerAdded") + if err != nil { + return nil, err + } + return &FeeQuoterAuthorizedCallerAddedIterator{contract: _FeeQuoter.contract, event: "AuthorizedCallerAdded", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerAdded) (event.Subscription, error) { + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "AuthorizedCallerAdded") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterAuthorizedCallerAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerAdded", 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 (_FeeQuoter *FeeQuoterFilterer) ParseAuthorizedCallerAdded(log types.Log) (*FeeQuoterAuthorizedCallerAdded, error) { + event := new(FeeQuoterAuthorizedCallerAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterAuthorizedCallerRemovedIterator struct { + Event *FeeQuoterAuthorizedCallerRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterAuthorizedCallerRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterAuthorizedCallerRemoved) + 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(FeeQuoterAuthorizedCallerRemoved) + 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 *FeeQuoterAuthorizedCallerRemovedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterAuthorizedCallerRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterAuthorizedCallerRemoved struct { + Caller common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerRemovedIterator, error) { + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "AuthorizedCallerRemoved") + if err != nil { + return nil, err + } + return &FeeQuoterAuthorizedCallerRemovedIterator{contract: _FeeQuoter.contract, event: "AuthorizedCallerRemoved", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error) { + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "AuthorizedCallerRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterAuthorizedCallerRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerRemoved", 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 (_FeeQuoter *FeeQuoterFilterer) ParseAuthorizedCallerRemoved(log types.Log) (*FeeQuoterAuthorizedCallerRemoved, error) { + event := new(FeeQuoterAuthorizedCallerRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterDestChainAddedIterator struct { + Event *FeeQuoterDestChainAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterDestChainAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterDestChainAdded) + 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(FeeQuoterDestChainAdded) + 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 *FeeQuoterDestChainAddedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterDestChainAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterDestChainAdded struct { + DestChainSelector uint64 + DestChainConfig FeeQuoterDestChainConfig + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainAddedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "DestChainAdded", destChainSelectorRule) + if err != nil { + return nil, err + } + return &FeeQuoterDestChainAddedIterator{contract: _FeeQuoter.contract, event: "DestChainAdded", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "DestChainAdded", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterDestChainAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainAdded", 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 (_FeeQuoter *FeeQuoterFilterer) ParseDestChainAdded(log types.Log) (*FeeQuoterDestChainAdded, error) { + event := new(FeeQuoterDestChainAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterDestChainConfigUpdatedIterator struct { + Event *FeeQuoterDestChainConfigUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterDestChainConfigUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterDestChainConfigUpdated) + 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(FeeQuoterDestChainConfigUpdated) + 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 *FeeQuoterDestChainConfigUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterDestChainConfigUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterDestChainConfigUpdated struct { + DestChainSelector uint64 + DestChainConfig FeeQuoterDestChainConfig + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainConfigUpdatedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) + if err != nil { + return nil, err + } + return &FeeQuoterDestChainConfigUpdatedIterator{contract: _FeeQuoter.contract, event: "DestChainConfigUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterDestChainConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainConfigUpdated", 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 (_FeeQuoter *FeeQuoterFilterer) ParseDestChainConfigUpdated(log types.Log) (*FeeQuoterDestChainConfigUpdated, error) { + event := new(FeeQuoterDestChainConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterFeeTokenAddedIterator struct { + Event *FeeQuoterFeeTokenAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterFeeTokenAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterFeeTokenAdded) + 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(FeeQuoterFeeTokenAdded) + 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 *FeeQuoterFeeTokenAddedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterFeeTokenAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterFeeTokenAdded struct { + FeeToken common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenAddedIterator, error) { + + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterFeeTokenAddedIterator{contract: _FeeQuoter.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { + + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterFeeTokenAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenAdded", 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 (_FeeQuoter *FeeQuoterFilterer) ParseFeeTokenAdded(log types.Log) (*FeeQuoterFeeTokenAdded, error) { + event := new(FeeQuoterFeeTokenAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterFeeTokenRemovedIterator struct { + Event *FeeQuoterFeeTokenRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterFeeTokenRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterFeeTokenRemoved) + 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(FeeQuoterFeeTokenRemoved) + 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 *FeeQuoterFeeTokenRemovedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterFeeTokenRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterFeeTokenRemoved struct { + FeeToken common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenRemovedIterator, error) { + + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterFeeTokenRemovedIterator{contract: _FeeQuoter.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { + + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterFeeTokenRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenRemoved", 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 (_FeeQuoter *FeeQuoterFilterer) ParseFeeTokenRemoved(log types.Log) (*FeeQuoterFeeTokenRemoved, error) { + event := new(FeeQuoterFeeTokenRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterOwnershipTransferRequestedIterator struct { + Event *FeeQuoterOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterOwnershipTransferRequested) + 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(FeeQuoterOwnershipTransferRequested) + 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 *FeeQuoterOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferRequestedIterator, 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 := _FeeQuoter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &FeeQuoterOwnershipTransferRequestedIterator{contract: _FeeQuoter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferRequested, 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 := _FeeQuoter.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(FeeQuoterOwnershipTransferRequested) + if err := _FeeQuoter.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 (_FeeQuoter *FeeQuoterFilterer) ParseOwnershipTransferRequested(log types.Log) (*FeeQuoterOwnershipTransferRequested, error) { + event := new(FeeQuoterOwnershipTransferRequested) + if err := _FeeQuoter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterOwnershipTransferredIterator struct { + Event *FeeQuoterOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterOwnershipTransferred) + 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(FeeQuoterOwnershipTransferred) + 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 *FeeQuoterOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferredIterator, 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 := _FeeQuoter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &FeeQuoterOwnershipTransferredIterator{contract: _FeeQuoter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferred, 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 := _FeeQuoter.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(FeeQuoterOwnershipTransferred) + if err := _FeeQuoter.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 (_FeeQuoter *FeeQuoterFilterer) ParseOwnershipTransferred(log types.Log) (*FeeQuoterOwnershipTransferred, error) { + event := new(FeeQuoterOwnershipTransferred) + if err := _FeeQuoter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator struct { + Event *FeeQuoterPremiumMultiplierWeiPerEthUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) + 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(FeeQuoterPremiumMultiplierWeiPerEthUpdated) + 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 *FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterPremiumMultiplierWeiPerEthUpdated struct { + Token common.Address + PremiumMultiplierWeiPerEth uint64 + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator{contract: _FeeQuoter.contract, event: "PremiumMultiplierWeiPerEthUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", 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 (_FeeQuoter *FeeQuoterFilterer) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*FeeQuoterPremiumMultiplierWeiPerEthUpdated, error) { + event := new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterPriceFeedPerTokenUpdatedIterator struct { + Event *FeeQuoterPriceFeedPerTokenUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterPriceFeedPerTokenUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterPriceFeedPerTokenUpdated) + 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(FeeQuoterPriceFeedPerTokenUpdated) + 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 *FeeQuoterPriceFeedPerTokenUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterPriceFeedPerTokenUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterPriceFeedPerTokenUpdated struct { + Token common.Address + PriceFeedConfig FeeQuoterTokenPriceFeedConfig + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPriceFeedPerTokenUpdatedIterator, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterPriceFeedPerTokenUpdatedIterator{contract: _FeeQuoter.contract, event: "PriceFeedPerTokenUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterPriceFeedPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", 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 (_FeeQuoter *FeeQuoterFilterer) ParsePriceFeedPerTokenUpdated(log types.Log) (*FeeQuoterPriceFeedPerTokenUpdated, error) { + event := new(FeeQuoterPriceFeedPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterReportPermissionSetIterator struct { + Event *FeeQuoterReportPermissionSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterReportPermissionSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterReportPermissionSet) + 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(FeeQuoterReportPermissionSet) + 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 *FeeQuoterReportPermissionSetIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterReportPermissionSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterReportPermissionSet struct { + ReportId [32]byte + Permission KeystoneFeedsPermissionHandlerPermission + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*FeeQuoterReportPermissionSetIterator, error) { + + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "ReportPermissionSet", reportIdRule) + if err != nil { + return nil, err + } + return &FeeQuoterReportPermissionSetIterator{contract: _FeeQuoter.contract, event: "ReportPermissionSet", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *FeeQuoterReportPermissionSet, reportId [][32]byte) (event.Subscription, error) { + + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "ReportPermissionSet", 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(FeeQuoterReportPermissionSet) + if err := _FeeQuoter.contract.UnpackLog(event, "ReportPermissionSet", 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 (_FeeQuoter *FeeQuoterFilterer) ParseReportPermissionSet(log types.Log) (*FeeQuoterReportPermissionSet, error) { + event := new(FeeQuoterReportPermissionSet) + if err := _FeeQuoter.contract.UnpackLog(event, "ReportPermissionSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterTokenTransferFeeConfigDeletedIterator struct { + Event *FeeQuoterTokenTransferFeeConfigDeleted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterTokenTransferFeeConfigDeletedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterTokenTransferFeeConfigDeleted) + 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(FeeQuoterTokenTransferFeeConfigDeleted) + 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 *FeeQuoterTokenTransferFeeConfigDeletedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterTokenTransferFeeConfigDeletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterTokenTransferFeeConfigDeleted struct { + DestChainSelector uint64 + Token common.Address + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigDeletedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterTokenTransferFeeConfigDeletedIterator{contract: _FeeQuoter.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterTokenTransferFeeConfigDeleted) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", 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 (_FeeQuoter *FeeQuoterFilterer) ParseTokenTransferFeeConfigDeleted(log types.Log) (*FeeQuoterTokenTransferFeeConfigDeleted, error) { + event := new(FeeQuoterTokenTransferFeeConfigDeleted) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterTokenTransferFeeConfigUpdatedIterator struct { + Event *FeeQuoterTokenTransferFeeConfigUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterTokenTransferFeeConfigUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterTokenTransferFeeConfigUpdated) + 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(FeeQuoterTokenTransferFeeConfigUpdated) + 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 *FeeQuoterTokenTransferFeeConfigUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterTokenTransferFeeConfigUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterTokenTransferFeeConfigUpdated struct { + DestChainSelector uint64 + Token common.Address + TokenTransferFeeConfig FeeQuoterTokenTransferFeeConfig + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigUpdatedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterTokenTransferFeeConfigUpdatedIterator{contract: _FeeQuoter.contract, event: "TokenTransferFeeConfigUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterTokenTransferFeeConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", 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 (_FeeQuoter *FeeQuoterFilterer) ParseTokenTransferFeeConfigUpdated(log types.Log) (*FeeQuoterTokenTransferFeeConfigUpdated, error) { + event := new(FeeQuoterTokenTransferFeeConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterUsdPerTokenUpdatedIterator struct { + Event *FeeQuoterUsdPerTokenUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterUsdPerTokenUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterUsdPerTokenUpdated) + 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(FeeQuoterUsdPerTokenUpdated) + 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 *FeeQuoterUsdPerTokenUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterUsdPerTokenUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterUsdPerTokenUpdated struct { + Token common.Address + Value *big.Int + Timestamp *big.Int + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterUsdPerTokenUpdatedIterator, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "UsdPerTokenUpdated", tokenRule) + if err != nil { + return nil, err + } + return &FeeQuoterUsdPerTokenUpdatedIterator{contract: _FeeQuoter.contract, event: "UsdPerTokenUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "UsdPerTokenUpdated", tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterUsdPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerTokenUpdated", 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 (_FeeQuoter *FeeQuoterFilterer) ParseUsdPerTokenUpdated(log types.Log) (*FeeQuoterUsdPerTokenUpdated, error) { + event := new(FeeQuoterUsdPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type FeeQuoterUsdPerUnitGasUpdatedIterator struct { + Event *FeeQuoterUsdPerUnitGasUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *FeeQuoterUsdPerUnitGasUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(FeeQuoterUsdPerUnitGasUpdated) + 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(FeeQuoterUsdPerUnitGasUpdated) + 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 *FeeQuoterUsdPerUnitGasUpdatedIterator) Error() error { + return it.fail +} + +func (it *FeeQuoterUsdPerUnitGasUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type FeeQuoterUsdPerUnitGasUpdated struct { + DestChain uint64 + Value *big.Int + Timestamp *big.Int + Raw types.Log +} + +func (_FeeQuoter *FeeQuoterFilterer) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*FeeQuoterUsdPerUnitGasUpdatedIterator, error) { + + var destChainRule []interface{} + for _, destChainItem := range destChain { + destChainRule = append(destChainRule, destChainItem) + } + + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "UsdPerUnitGasUpdated", destChainRule) + if err != nil { + return nil, err + } + return &FeeQuoterUsdPerUnitGasUpdatedIterator{contract: _FeeQuoter.contract, event: "UsdPerUnitGasUpdated", logs: logs, sub: sub}, nil +} + +func (_FeeQuoter *FeeQuoterFilterer) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { + + var destChainRule []interface{} + for _, destChainItem := range destChain { + destChainRule = append(destChainRule, destChainItem) + } + + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "UsdPerUnitGasUpdated", destChainRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(FeeQuoterUsdPerUnitGasUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerUnitGasUpdated", 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 (_FeeQuoter *FeeQuoterFilterer) ParseUsdPerUnitGasUpdated(log types.Log) (*FeeQuoterUsdPerUnitGasUpdated, error) { + event := new(FeeQuoterUsdPerUnitGasUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetTokenAndGasPrices struct { + TokenPrice *big.Int + GasPriceValue *big.Int +} +type ProcessMessageArgs struct { + MsgFeeJuels *big.Int + IsOutOfOrderExecution bool + ConvertedExtraArgs []byte + DestExecDataPerToken [][]byte +} + +func (_FeeQuoter *FeeQuoter) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _FeeQuoter.abi.Events["AuthorizedCallerAdded"].ID: + return _FeeQuoter.ParseAuthorizedCallerAdded(log) + case _FeeQuoter.abi.Events["AuthorizedCallerRemoved"].ID: + return _FeeQuoter.ParseAuthorizedCallerRemoved(log) + case _FeeQuoter.abi.Events["DestChainAdded"].ID: + return _FeeQuoter.ParseDestChainAdded(log) + case _FeeQuoter.abi.Events["DestChainConfigUpdated"].ID: + return _FeeQuoter.ParseDestChainConfigUpdated(log) + case _FeeQuoter.abi.Events["FeeTokenAdded"].ID: + return _FeeQuoter.ParseFeeTokenAdded(log) + case _FeeQuoter.abi.Events["FeeTokenRemoved"].ID: + return _FeeQuoter.ParseFeeTokenRemoved(log) + case _FeeQuoter.abi.Events["OwnershipTransferRequested"].ID: + return _FeeQuoter.ParseOwnershipTransferRequested(log) + case _FeeQuoter.abi.Events["OwnershipTransferred"].ID: + return _FeeQuoter.ParseOwnershipTransferred(log) + case _FeeQuoter.abi.Events["PremiumMultiplierWeiPerEthUpdated"].ID: + return _FeeQuoter.ParsePremiumMultiplierWeiPerEthUpdated(log) + case _FeeQuoter.abi.Events["PriceFeedPerTokenUpdated"].ID: + return _FeeQuoter.ParsePriceFeedPerTokenUpdated(log) + case _FeeQuoter.abi.Events["ReportPermissionSet"].ID: + return _FeeQuoter.ParseReportPermissionSet(log) + case _FeeQuoter.abi.Events["TokenTransferFeeConfigDeleted"].ID: + return _FeeQuoter.ParseTokenTransferFeeConfigDeleted(log) + case _FeeQuoter.abi.Events["TokenTransferFeeConfigUpdated"].ID: + return _FeeQuoter.ParseTokenTransferFeeConfigUpdated(log) + case _FeeQuoter.abi.Events["UsdPerTokenUpdated"].ID: + return _FeeQuoter.ParseUsdPerTokenUpdated(log) + case _FeeQuoter.abi.Events["UsdPerUnitGasUpdated"].ID: + return _FeeQuoter.ParseUsdPerUnitGasUpdated(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (FeeQuoterAuthorizedCallerAdded) Topic() common.Hash { + return common.HexToHash("0xeb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef") +} + +func (FeeQuoterAuthorizedCallerRemoved) Topic() common.Hash { + return common.HexToHash("0xc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda77580") +} + +func (FeeQuoterDestChainAdded) Topic() common.Hash { + return common.HexToHash("0x525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265") +} + +func (FeeQuoterDestChainConfigUpdated) Topic() common.Hash { + return common.HexToHash("0x283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a835") +} + +func (FeeQuoterFeeTokenAdded) Topic() common.Hash { + return common.HexToHash("0xdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23") +} + +func (FeeQuoterFeeTokenRemoved) Topic() common.Hash { + return common.HexToHash("0x1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91") +} + +func (FeeQuoterOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (FeeQuoterOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (FeeQuoterPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { + return common.HexToHash("0xbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d") +} + +func (FeeQuoterPriceFeedPerTokenUpdated) Topic() common.Hash { + return common.HexToHash("0x08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464") +} + +func (FeeQuoterReportPermissionSet) Topic() common.Hash { + return common.HexToHash("0x32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3") +} + +func (FeeQuoterTokenTransferFeeConfigDeleted) Topic() common.Hash { + return common.HexToHash("0x4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b") +} + +func (FeeQuoterTokenTransferFeeConfigUpdated) Topic() common.Hash { + return common.HexToHash("0x94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5") +} + +func (FeeQuoterUsdPerTokenUpdated) Topic() common.Hash { + return common.HexToHash("0x52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a") +} + +func (FeeQuoterUsdPerUnitGasUpdated) Topic() common.Hash { + return common.HexToHash("0xdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e") +} + +func (_FeeQuoter *FeeQuoter) Address() common.Address { + return _FeeQuoter.address +} + +type FeeQuoterInterface interface { + FEEBASEDECIMALS(opts *bind.CallOpts) (*big.Int, error) + + KEYSTONEPRICEDECIMALS(opts *bind.CallOpts) (*big.Int, error) + + ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) + + GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) + + GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (FeeQuoterDestChainConfig, error) + + GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) + + GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) + + GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) + + GetStaticConfig(opts *bind.CallOpts) (FeeQuoterStaticConfig, error) + + GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, + + error) + + GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) + + GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (FeeQuoterTokenPriceFeedConfig, error) + + GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) + + GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) + + GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) + + GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, + + error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) + + ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) + + ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToRemove []common.Address, feeTokensToAdd []common.Address) (*types.Transaction, error) + + ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) + + ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) + + OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) + + SetReportPermissions(opts *bind.TransactOpts, permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) + + UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) + + FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerAddedIterator, error) + + WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerAdded) (event.Subscription, error) + + ParseAuthorizedCallerAdded(log types.Log) (*FeeQuoterAuthorizedCallerAdded, error) + + FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerRemovedIterator, error) + + WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error) + + ParseAuthorizedCallerRemoved(log types.Log) (*FeeQuoterAuthorizedCallerRemoved, error) + + FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainAddedIterator, error) + + WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainAdded, destChainSelector []uint64) (event.Subscription, error) + + ParseDestChainAdded(log types.Log) (*FeeQuoterDestChainAdded, error) + + FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainConfigUpdatedIterator, error) + + WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) + + ParseDestChainConfigUpdated(log types.Log) (*FeeQuoterDestChainConfigUpdated, error) + + FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenAddedIterator, error) + + WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) + + ParseFeeTokenAdded(log types.Log) (*FeeQuoterFeeTokenAdded, error) + + FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenRemovedIterator, error) + + WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) + + ParseFeeTokenRemoved(log types.Log) (*FeeQuoterFeeTokenRemoved, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*FeeQuoterOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*FeeQuoterOwnershipTransferred, error) + + FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error) + + WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) + + ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*FeeQuoterPremiumMultiplierWeiPerEthUpdated, error) + + FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPriceFeedPerTokenUpdatedIterator, error) + + WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) + + ParsePriceFeedPerTokenUpdated(log types.Log) (*FeeQuoterPriceFeedPerTokenUpdated, error) + + FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*FeeQuoterReportPermissionSetIterator, error) + + WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *FeeQuoterReportPermissionSet, reportId [][32]byte) (event.Subscription, error) + + ParseReportPermissionSet(log types.Log) (*FeeQuoterReportPermissionSet, error) + + FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigDeletedIterator, error) + + WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) + + ParseTokenTransferFeeConfigDeleted(log types.Log) (*FeeQuoterTokenTransferFeeConfigDeleted, error) + + FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigUpdatedIterator, error) + + WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) + + ParseTokenTransferFeeConfigUpdated(log types.Log) (*FeeQuoterTokenTransferFeeConfigUpdated, error) + + FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterUsdPerTokenUpdatedIterator, error) + + WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) + + ParseUsdPerTokenUpdated(log types.Log) (*FeeQuoterUsdPerTokenUpdated, error) + + FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*FeeQuoterUsdPerUnitGasUpdatedIterator, error) + + WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) + + ParseUsdPerUnitGasUpdated(log types.Log) (*FeeQuoterUsdPerUnitGasUpdated, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} 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 fe2ac3f87e7..275f9c7a389 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 @@ -82,8 +82,8 @@ type TokenPoolChainUpdate struct { } var LockReleaseTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200487838038062004878833981016040819052620000359162000565565b848484833380600081620000905760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c357620000c3816200017e565b5050506001600160a01b0384161580620000e457506001600160a01b038116155b80620000f757506001600160a01b038216155b1562000116576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001695760408051600081526020810190915262000169908462000229565b5050505090151560e05250620006d692505050565b336001600160a01b03821603620001d85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000087565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200024a576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002d55760008382815181106200026e576200026e62000688565b602090810291909101015190506200028860028262000386565b15620002cb576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200024d565b5060005b815181101562000381576000828281518110620002fa57620002fa62000688565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000326575062000378565b62000333600282620003a6565b1562000376576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d9565b505050565b60006200039d836001600160a01b038416620003bd565b90505b92915050565b60006200039d836001600160a01b038416620004c1565b60008181526001830160205260408120548015620004b6576000620003e46001836200069e565b8554909150600090620003fa906001906200069e565b9050818114620004665760008660000182815481106200041e576200041e62000688565b906000526020600020015490508087600001848154811062000444576200044462000688565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200047a576200047a620006c0565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a0565b6000915050620003a0565b60008181526001830160205260408120546200050a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a0565b506000620003a0565b6001600160a01b03811681146200052957600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b80516200054f8162000513565b919050565b805180151581146200054f57600080fd5b600080600080600060a086880312156200057e57600080fd5b85516200058b8162000513565b602087810151919650906001600160401b0380821115620005ab57600080fd5b818901915089601f830112620005c057600080fd5b815181811115620005d557620005d56200052c565b8060051b604051601f19603f83011681018181108582111715620005fd57620005fd6200052c565b60405291825284820192508381018501918c8311156200061c57600080fd5b938501935b828510156200064557620006358562000542565b8452938501939285019262000621565b8099505050505050506200065c6040870162000542565b92506200066c6060870162000554565b91506200067c6080870162000542565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a057634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161410662000772600039600081816104d1015261163801526000818161057e01528181611bd4015261267901526000818161055801528181611a050152611e8a015260008181610285015281816102da0152818161075c0152818161082e015281816108bf015281816116fa0152818161192501528181611daa0152818161260f015261286401526141066000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c80638da5cb5b1161010f578063c4bffe2b116100a2578063dc0bd97111610071578063dc0bd97114610556578063e0351e131461057c578063eb521a4c146105a2578063f2fde38b146105b557600080fd5b8063c4bffe2b14610508578063c75eea9c1461051d578063cf7401f314610530578063db6327dc1461054357600080fd5b8063b0f479a1116100de578063b0f479a11461049e578063b7946580146104bc578063bb98546b146104cf578063c0d78655146104f557600080fd5b80638da5cb5b146103dc5780639a4575b9146103fa578063a7cd63b71461041a578063af58d59f1461042f57600080fd5b8063432a6ba31161018757806378a010b21161015657806378a010b21461039b57806379ba5097146103ae5780637d54534e146103b65780638926f54f146103c957600080fd5b8063432a6ba31461033957806354c8a4f3146103575780636cfd15531461036a5780636d3d1a581461037d57600080fd5b8063181f5a77116101c3578063181f5a771461024757806321df0da714610283578063240028e8146102ca578063390775371461031757600080fd5b806301ffc9a7146101ea5780630a2fd493146102125780630a861f2a14610232575b600080fd5b6101fd6101f836600461320e565b6105c8565b60405190151581526020015b60405180910390f35b61022561022036600461326d565b610624565b60405161020991906132f6565b610245610240366004613309565b6106d4565b005b6102256040518060400160405280601e81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e302d646576000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610209565b6101fd6102d836600461334f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61032a61032536600461336c565b610885565b60405190518152602001610209565b60085473ffffffffffffffffffffffffffffffffffffffff166102a5565b6102456103653660046133f4565b61097b565b61024561037836600461334f565b6109f6565b60095473ffffffffffffffffffffffffffffffffffffffff166102a5565b6102456103a9366004613460565b610a45565b610245610bb4565b6102456103c436600461334f565b610cb1565b6101fd6103d736600461326d565b610d00565b60005473ffffffffffffffffffffffffffffffffffffffff166102a5565b61040d6104083660046134e3565b610d17565b604051610209919061351e565b610422610db1565b604051610209919061357e565b61044261043d36600461326d565b610dc2565b604051610209919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102a5565b6102256104ca36600461326d565b610e97565b7f00000000000000000000000000000000000000000000000000000000000000006101fd565b61024561050336600461334f565b610ec2565b610510610f9d565b60405161020991906135d8565b61044261052b36600461326d565b611055565b61024561053e366004613740565b611127565b610245610551366004613785565b6111b0565b7f00000000000000000000000000000000000000000000000000000000000000006102a5565b7f00000000000000000000000000000000000000000000000000000000000000006101fd565b6102456105b0366004613309565b611636565b6102456105c336600461334f565b611752565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061061e575061061e82611766565b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061064f906137c7565b80601f016020809104026020016040519081016040528092919081815260200182805461067b906137c7565b80156106c85780601f1061069d576101008083540402835291602001916106c8565b820191906000526020600020905b8154815290600101906020018083116106ab57829003601f168201915b50505050509050919050565b60085473ffffffffffffffffffffffffffffffffffffffff16331461072c576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107dc919061381a565b1015610814576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61085573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016338361184a565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108a56108a0836138de565b61191e565b6108ea73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633606085013561184a565b6108fa606083016040840161334f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52846060013560405161095c91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b610983611b4f565b6109f084848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611bd292505050565b50505050565b6109fe611b4f565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610a4d611b4f565b610a5683610d00565b610a98576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610723565b67ffffffffffffffff831660009081526007602052604081206004018054610abf906137c7565b80601f0160208091040260200160405190810160405280929190818152602001828054610aeb906137c7565b8015610b385780601f10610b0d57610100808354040283529160200191610b38565b820191906000526020600020905b815481529060010190602001808311610b1b57829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610b67838583613a23565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610ba693929190613b3e565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610723565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610cb9611b4f565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600061061e600567ffffffffffffffff8416611d88565b6040805180820190915260608082526020820152610d3c610d3783613ba2565b611da3565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610d968460200160208101906104ca919061326d565b81526040805160208181019092526000815291015292915050565b6060610dbd6002611f6d565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261061e90611f7a565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061064f906137c7565b610eca611b4f565b73ffffffffffffffffffffffffffffffffffffffff8116610f17576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610fab6005611f6d565b90506000815167ffffffffffffffff811115610fc957610fc961361a565b604051908082528060200260200182016040528015610ff2578160200160208202803683370190505b50905060005b825181101561104e5782818151811061101357611013613c44565b602002602001015182828151811061102d5761102d613c44565b67ffffffffffffffff90921660209283029190910190910152600101610ff8565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261061e90611f7a565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590611167575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156111a0576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610723565b6111ab83838361202c565b505050565b6111b8611b4f565b60005b818110156111ab5760008383838181106111d7576111d7613c44565b90506020028101906111e99190613c73565b6111f290613cb1565b90506112078160800151826020015115612116565b61121a8160a00151826020015115612116565b80602001511561151657805161123c9060059067ffffffffffffffff1661224f565b6112815780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610723565b60408101515115806112965750606081015151155b156112cd576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906114ae9082613d65565b50606082015160058201906114c39082613d65565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506115099493929190613e7f565b60405180910390a161162d565b805161152e9060059067ffffffffffffffff1661225b565b6115735780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610723565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115dc60048301826131c0565b6115ea6005830160006131c0565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016111bb565b7f000000000000000000000000000000000000000000000000000000000000000061168d576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1633146116e0576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610723565b61172273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612267565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b61175a611b4f565b611763816122c5565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806117f957507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061061e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526111ab9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123ba565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119b35760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610723565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a859190613f18565b15611abc576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ac981602001516124c6565b6000611ad88260200151610624565b9050805160001480611afc575080805190602001208260a001518051906020012014155b15611b39578160a001516040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161072391906132f6565b611b4b826020015183606001516125ec565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610723565b565b7f0000000000000000000000000000000000000000000000000000000000000000611c29576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611cbf576000838281518110611c4957611c49613c44565b60200260200101519050611c6781600261263390919063ffffffff16565b15611cb65760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611c2c565b5060005b81518110156111ab576000828281518110611ce057611ce0613c44565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611d245750611d80565b611d2f600282612655565b15611d7e5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611cc3565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611e385760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610723565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611ee6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0a9190613f18565b15611f41576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f4e8160400151612677565b611f5b81602001516126f6565b61176381602001518260600151612844565b60606000611d9c83612888565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261200882606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611fec9190613f64565b85608001516fffffffffffffffffffffffffffffffff166128e3565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61203583610d00565b612077576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610723565b612082826000612116565b67ffffffffffffffff831660009081526007602052604090206120a5908361290d565b6120b0816000612116565b67ffffffffffffffff831660009081526007602052604090206120d6906002018261290d565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161210993929190613f77565b60405180910390a1505050565b8151156121dd5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061216c575060408201516fffffffffffffffffffffffffffffffff16155b156121a557816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107239190613ffa565b8015611b4b576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612216575060208201516fffffffffffffffffffffffffffffffff1615155b15611b4b57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107239190613ffa565b6000611d9c8383612aaf565b6000611d9c8383612afe565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526109f09085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161189c565b3373ffffffffffffffffffffffffffffffffffffffff821603612344576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610723565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061241c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bf19092919063ffffffff16565b8051909150156111ab578080602001905181019061243a9190613f18565b6111ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610723565b6124cf81610d00565b612511576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610723565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b49190613f18565b611763576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610723565b67ffffffffffffffff82166000908152600760205260409020611b4b90600201827f0000000000000000000000000000000000000000000000000000000000000000612c00565b6000611d9c8373ffffffffffffffffffffffffffffffffffffffff8416612afe565b6000611d9c8373ffffffffffffffffffffffffffffffffffffffff8416612aaf565b7f000000000000000000000000000000000000000000000000000000000000000015611763576126a8600282612f83565b611763576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610723565b6126ff81610d00565b612741576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610723565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156127ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127de9190614036565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611763576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610723565b67ffffffffffffffff82166000908152600760205260409020611b4b90827f0000000000000000000000000000000000000000000000000000000000000000612c00565b6060816000018054806020026020016040519081016040528092919081815260200182805480156106c857602002820191906000526020600020905b8154815260200190600101908083116128c45750505050509050919050565b6000612902856128f38486614053565b6128fd908761406a565b612fb2565b90505b949350505050565b815460009061293690700100000000000000000000000000000000900463ffffffff1642613f64565b905080156129d8576001830154835461297e916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166128e3565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546129fe916fffffffffffffffffffffffffffffffff9081169116612fb2565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612109908490613ffa565b6000818152600183016020526040812054612af65750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561061e565b50600061061e565b60008181526001830160205260408120548015612be7576000612b22600183613f64565b8554909150600090612b3690600190613f64565b9050818114612b9b576000866000018281548110612b5657612b56613c44565b9060005260206000200154905080876000018481548110612b7957612b79613c44565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612bac57612bac61407d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061061e565b600091505061061e565b60606129058484600085612fc8565b825474010000000000000000000000000000000000000000900460ff161580612c27575081155b15612c3157505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612c7790700100000000000000000000000000000000900463ffffffff1642613f64565b90508015612d375781831115612cb9576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612cf39083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166128e3565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612dee5773ffffffffffffffffffffffffffffffffffffffff8416612d96576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610723565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610723565b84831015612f015760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612e329082613f64565b612e3c878a613f64565b612e46919061406a565b612e5091906140ac565b905073ffffffffffffffffffffffffffffffffffffffff8616612ea9576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610723565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610723565b612f0b8584613f64565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d9c565b6000818310612fc15781611d9c565b5090919050565b60608247101561305a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610723565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161308391906140e7565b60006040518083038185875af1925050503d80600081146130c0576040519150601f19603f3d011682016040523d82523d6000602084013e6130c5565b606091505b50915091506130d6878383876130e1565b979650505050505050565b606083156131775782516000036131705773ffffffffffffffffffffffffffffffffffffffff85163b613170576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610723565b5081612905565b612905838381511561318c5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072391906132f6565b5080546131cc906137c7565b6000825580601f106131dc575050565b601f01602090049060005260206000209081019061176391905b8082111561320a57600081556001016131f6565b5090565b60006020828403121561322057600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d9c57600080fd5b803567ffffffffffffffff8116811461326857600080fd5b919050565b60006020828403121561327f57600080fd5b611d9c82613250565b60005b838110156132a357818101518382015260200161328b565b50506000910152565b600081518084526132c4816020860160208601613288565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611d9c60208301846132ac565b60006020828403121561331b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461176357600080fd5b803561326881613322565b60006020828403121561336157600080fd5b8135611d9c81613322565b60006020828403121561337e57600080fd5b813567ffffffffffffffff81111561339557600080fd5b82016101008185031215611d9c57600080fd5b60008083601f8401126133ba57600080fd5b50813567ffffffffffffffff8111156133d257600080fd5b6020830191508360208260051b85010111156133ed57600080fd5b9250929050565b6000806000806040858703121561340a57600080fd5b843567ffffffffffffffff8082111561342257600080fd5b61342e888389016133a8565b9096509450602087013591508082111561344757600080fd5b50613454878288016133a8565b95989497509550505050565b60008060006040848603121561347557600080fd5b61347e84613250565b9250602084013567ffffffffffffffff8082111561349b57600080fd5b818601915086601f8301126134af57600080fd5b8135818111156134be57600080fd5b8760208285010111156134d057600080fd5b6020830194508093505050509250925092565b6000602082840312156134f557600080fd5b813567ffffffffffffffff81111561350c57600080fd5b820160a08185031215611d9c57600080fd5b60208152600082516040602084015261353a60608401826132ac565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261357582826132ac565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156135cc57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161359a565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156135cc57835167ffffffffffffffff16835292840192918401916001016135f4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff8111828210171561366d5761366d61361a565b60405290565b60405160c0810167ffffffffffffffff8111828210171561366d5761366d61361a565b801515811461176357600080fd5b803561326881613696565b80356fffffffffffffffffffffffffffffffff8116811461326857600080fd5b6000606082840312156136e157600080fd5b6040516060810181811067ffffffffffffffff821117156137045761370461361a565b604052905080823561371581613696565b8152613723602084016136af565b6020820152613734604084016136af565b60408201525092915050565b600080600060e0848603121561375557600080fd5b61375e84613250565b925061376d85602086016136cf565b915061377c85608086016136cf565b90509250925092565b6000806020838503121561379857600080fd5b823567ffffffffffffffff8111156137af57600080fd5b6137bb858286016133a8565b90969095509350505050565b600181811c908216806137db57607f821691505b602082108103613814577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561382c57600080fd5b5051919050565b600082601f83011261384457600080fd5b813567ffffffffffffffff8082111561385f5761385f61361a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156138a5576138a561361a565b816040528381528660208588010111156138be57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600061010082360312156138f157600080fd5b6138f9613649565b823567ffffffffffffffff8082111561391157600080fd5b61391d36838701613833565b835261392b60208601613250565b602084015261393c60408601613344565b60408401526060850135606084015261395760808601613344565b608084015260a085013591508082111561397057600080fd5b61397c36838701613833565b60a084015260c085013591508082111561399557600080fd5b6139a136838701613833565b60c084015260e08501359150808211156139ba57600080fd5b506139c736828601613833565b60e08301525092915050565b601f8211156111ab576000816000526020600020601f850160051c810160208610156139fc5750805b601f850160051c820191505b81811015613a1b57828155600101613a08565b505050505050565b67ffffffffffffffff831115613a3b57613a3b61361a565b613a4f83613a4983546137c7565b836139d3565b6000601f841160018114613aa15760008515613a6b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613b37565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613af05786850135825560209485019460019092019101613ad0565b5086821015613b2b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b604081526000613b5160408301866132ac565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a08236031215613bb457600080fd5b60405160a0810167ffffffffffffffff8282108183111715613bd857613bd861361a565b816040528435915080821115613bed57600080fd5b50613bfa36828601613833565b825250613c0960208401613250565b60208201526040830135613c1c81613322565b6040820152606083810135908201526080830135613c3981613322565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613ca757600080fd5b9190910192915050565b60006101408236031215613cc457600080fd5b613ccc613673565b613cd583613250565b8152613ce3602084016136a4565b6020820152604083013567ffffffffffffffff80821115613d0357600080fd5b613d0f36838701613833565b60408401526060850135915080821115613d2857600080fd5b50613d3536828601613833565b606083015250613d4836608085016136cf565b6080820152613d5a3660e085016136cf565b60a082015292915050565b815167ffffffffffffffff811115613d7f57613d7f61361a565b613d9381613d8d84546137c7565b846139d3565b602080601f831160018114613de65760008415613db05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613a1b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e3357888601518255948401946001909101908401613e14565b5085821015613e6f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ea3818401876132ac565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613ee19050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613575565b600060208284031215613f2a57600080fd5b8151611d9c81613696565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561061e5761061e613f35565b67ffffffffffffffff8416815260e08101613fc360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612905565b6060810161061e82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561404857600080fd5b8151611d9c81613322565b808202811582820484141761061e5761061e613f35565b8082018082111561061e5761061e613f35565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000826140e2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613ca781846020870161328856fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x6101006040523480156200001257600080fd5b50604051620049ae380380620049ae833981016040819052620000359162000565565b848484833380600081620000905760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c357620000c3816200017e565b5050506001600160a01b0384161580620000e457506001600160a01b038116155b80620000f757506001600160a01b038216155b1562000116576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001695760408051600081526020810190915262000169908462000229565b5050505090151560e05250620006d692505050565b336001600160a01b03821603620001d85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000087565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200024a576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002d55760008382815181106200026e576200026e62000688565b602090810291909101015190506200028860028262000386565b15620002cb576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200024d565b5060005b815181101562000381576000828281518110620002fa57620002fa62000688565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000326575062000378565b62000333600282620003a6565b1562000376576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d9565b505050565b60006200039d836001600160a01b038416620003bd565b90505b92915050565b60006200039d836001600160a01b038416620004c1565b60008181526001830160205260408120548015620004b6576000620003e46001836200069e565b8554909150600090620003fa906001906200069e565b9050808214620004665760008660000182815481106200041e576200041e62000688565b906000526020600020015490508087600001848154811062000444576200044462000688565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200047a576200047a620006c0565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a0565b6000915050620003a0565b60008181526001830160205260408120546200050a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a0565b506000620003a0565b6001600160a01b03811681146200052957600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b80516200054f8162000513565b919050565b805180151581146200054f57600080fd5b600080600080600060a086880312156200057e57600080fd5b85516200058b8162000513565b602087810151919650906001600160401b0380821115620005ab57600080fd5b818901915089601f830112620005c057600080fd5b815181811115620005d557620005d56200052c565b8060051b604051601f19603f83011681018181108582111715620005fd57620005fd6200052c565b60405291825284820192508381018501918c8311156200061c57600080fd5b938501935b828510156200064557620006358562000542565b8452938501939285019262000621565b8099505050505050506200065c6040870162000542565b92506200066c6060870162000554565b91506200067c6080870162000542565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a057634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161423c62000772600039600081816104ef015261174201526000818161059c01528181611cde015261278301526000818161057601528181611b0f0152611f94015260008181610290015281816102e50152818161077a0152818161084c015281816108ed0152818161180401528181611a2f01528181611eb401528181612719015261296e015261423c6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638da5cb5b1161010f578063c4bffe2b116100a2578063dc0bd97111610071578063dc0bd97114610574578063e0351e131461059a578063eb521a4c146105c0578063f2fde38b146105d357600080fd5b8063c4bffe2b14610526578063c75eea9c1461053b578063cf7401f31461054e578063db6327dc1461056157600080fd5b8063b0f479a1116100de578063b0f479a1146104bc578063b7946580146104da578063bb98546b146104ed578063c0d786551461051357600080fd5b80638da5cb5b146103fa5780639a4575b914610418578063a7cd63b714610438578063af58d59f1461044d57600080fd5b806354c8a4f31161018757806378a010b21161015657806378a010b2146103b957806379ba5097146103cc5780637d54534e146103d45780638926f54f146103e757600080fd5b806354c8a4f31461036257806366320087146103755780636cfd1553146103885780636d3d1a581461039b57600080fd5b806321df0da7116101c357806321df0da71461028e578063240028e8146102d55780633907753714610322578063432a6ba31461034457600080fd5b806301ffc9a7146101f55780630a2fd4931461021d5780630a861f2a1461023d578063181f5a7714610252575b600080fd5b610208610203366004613318565b6105e6565b60405190151581526020015b60405180910390f35b61023061022b366004613377565b610642565b6040516102149190613400565b61025061024b366004613413565b6106f2565b005b6102306040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b6102086102e3366004613459565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b610335610330366004613476565b6108a3565b60405190518152602001610214565b60095473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102506103703660046134fe565b6109a9565b61025061038336600461356a565b610a24565b610250610396366004613459565b610b00565b60085473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102506103c7366004613596565b610b4f565b610250610cbe565b6102506103e2366004613459565b610dbb565b6102086103f5366004613377565b610e0a565b60005473ffffffffffffffffffffffffffffffffffffffff166102b0565b61042b610426366004613619565b610e21565b6040516102149190613654565b610440610ebb565b60405161021491906136b4565b61046061045b366004613377565b610ecc565b604051610214919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102306104e8366004613377565b610fa1565b7f0000000000000000000000000000000000000000000000000000000000000000610208565b610250610521366004613459565b610fcc565b61052e6110a7565b604051610214919061370e565b610460610549366004613377565b61115f565b61025061055c366004613876565b611231565b61025061056f3660046138bb565b6112ba565b7f00000000000000000000000000000000000000000000000000000000000000006102b0565b7f0000000000000000000000000000000000000000000000000000000000000000610208565b6102506105ce366004613413565b611740565b6102506105e1366004613459565b61185c565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061063c575061063c82611870565b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061066d906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610699906138fd565b80156106e65780601f106106bb576101008083540402835291602001916106e6565b820191906000526020600020905b8154815290600101906020018083116106c957829003601f168201915b50505050509050919050565b60095473ffffffffffffffffffffffffffffffffffffffff16331461074a576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fa9190613950565b1015610832576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611954565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c36108be83613a14565b611a28565b6109186108d66060840160408501613459565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906060850135611954565b6109286060830160408401613459565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52846060013560405161098a91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6109b1611c59565b610a1e84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611cdc92505050565b50505050565b610a2c611c59565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610a9457600080fd5b505af1158015610aa8573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610af491815260200190565b60405180910390a25050565b610b08611c59565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610b57611c59565b610b6083610e0a565b610ba2576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610741565b67ffffffffffffffff831660009081526007602052604081206004018054610bc9906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610bf5906138fd565b8015610c425780601f10610c1757610100808354040283529160200191610c42565b820191906000526020600020905b815481529060010190602001808311610c2557829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610c71838583613b59565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610cb093929190613c74565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610741565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610dc3611c59565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600061063c600567ffffffffffffffff8416611e92565b6040805180820190915260608082526020820152610e46610e4183613cd8565b611ead565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610ea08460200160208101906104e89190613377565b81526040805160208181019092526000815291015292915050565b6060610ec76002612077565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261063c90612084565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061066d906138fd565b610fd4611c59565b73ffffffffffffffffffffffffffffffffffffffff8116611021576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110b56005612077565b90506000815167ffffffffffffffff8111156110d3576110d3613750565b6040519080825280602002602001820160405280156110fc578160200160208202803683370190505b50905060005b82518110156111585782818151811061111d5761111d613d7a565b602002602001015182828151811061113757611137613d7a565b67ffffffffffffffff90921660209283029190910190910152600101611102565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261063c90612084565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590611271575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156112aa576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b6112b5838383612136565b505050565b6112c2611c59565b60005b818110156112b55760008383838181106112e1576112e1613d7a565b90506020028101906112f39190613da9565b6112fc90613de7565b90506113118160800151826020015115612220565b6113248160a00151826020015115612220565b8060200151156116205780516113469060059067ffffffffffffffff16612359565b61138b5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b60408101515115806113a05750606081015151155b156113d7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906115b89082613e9b565b50606082015160058201906115cd9082613e9b565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506116139493929190613fb5565b60405180910390a1611737565b80516116389060059067ffffffffffffffff16612365565b61167d5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906116e660048301826132ca565b6116f46005830160006132ca565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016112c5565b7f0000000000000000000000000000000000000000000000000000000000000000611797576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60095473ffffffffffffffffffffffffffffffffffffffff1633146117ea576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b61182c73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612371565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611864611c59565b61186d816123cf565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061190357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061063c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112b59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526124c4565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611abd5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610741565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8f919061404e565b15611bc6576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bd381602001516125d0565b6000611be28260200151610642565b9050805160001480611c06575080805190602001208260a001518051906020012014155b15611c43578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016107419190613400565b611c55826020015183606001516126f6565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611cda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610741565b565b7f0000000000000000000000000000000000000000000000000000000000000000611d33576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611dc9576000838281518110611d5357611d53613d7a565b60200260200101519050611d7181600261273d90919063ffffffff16565b15611dc05760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611d36565b5060005b81518110156112b5576000828281518110611dea57611dea613d7a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e2e5750611e8a565b611e3960028261275f565b15611e885760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611dcd565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611f425760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610741565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611ff0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612014919061404e565b1561204b576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120588160400151612781565b6120658160200151612800565b61186d8160200151826060015161294e565b60606000611ea683612992565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261211282606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426120f6919061409a565b85608001516fffffffffffffffffffffffffffffffff166129ed565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61213f83610e0a565b612181576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610741565b61218c826000612220565b67ffffffffffffffff831660009081526007602052604090206121af9083612a17565b6121ba816000612220565b67ffffffffffffffff831660009081526007602052604090206121e09060020182612a17565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051612213939291906140ad565b60405180910390a1505050565b8151156122e75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612276575060408201516fffffffffffffffffffffffffffffffff16155b156122af57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107419190614130565b8015611c55576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612320575060208201516fffffffffffffffffffffffffffffffff1615155b15611c5557816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107419190614130565b6000611ea68383612bb9565b6000611ea68383612c08565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610a1e9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119a6565b3373ffffffffffffffffffffffffffffffffffffffff82160361244e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610741565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612526826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612cfb9092919063ffffffff16565b8051909150156112b55780806020019051810190612544919061404e565b6112b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610741565b6125d981610e0a565b61261b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610741565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561269a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126be919061404e565b61186d576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b67ffffffffffffffff82166000908152600760205260409020611c5590600201827f0000000000000000000000000000000000000000000000000000000000000000612d0a565b6000611ea68373ffffffffffffffffffffffffffffffffffffffff8416612c08565b6000611ea68373ffffffffffffffffffffffffffffffffffffffff8416612bb9565b7f00000000000000000000000000000000000000000000000000000000000000001561186d576127b260028261308d565b61186d576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610741565b61280981610e0a565b61284b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610741565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156128c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e8919061416c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461186d576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b67ffffffffffffffff82166000908152600760205260409020611c5590827f0000000000000000000000000000000000000000000000000000000000000000612d0a565b6060816000018054806020026020016040519081016040528092919081815260200182805480156106e657602002820191906000526020600020905b8154815260200190600101908083116129ce5750505050509050919050565b6000612a0c856129fd8486614189565b612a0790876141a0565b6130bc565b90505b949350505050565b8154600090612a4090700100000000000000000000000000000000900463ffffffff164261409a565b90508015612ae25760018301548354612a88916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166129ed565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612b08916fffffffffffffffffffffffffffffffff90811691166130bc565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612213908490614130565b6000818152600183016020526040812054612c005750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561063c565b50600061063c565b60008181526001830160205260408120548015612cf1576000612c2c60018361409a565b8554909150600090612c409060019061409a565b9050808214612ca5576000866000018281548110612c6057612c60613d7a565b9060005260206000200154905080876000018481548110612c8357612c83613d7a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612cb657612cb66141b3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061063c565b600091505061063c565b6060612a0f84846000856130d2565b825474010000000000000000000000000000000000000000900460ff161580612d31575081155b15612d3b57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612d8190700100000000000000000000000000000000900463ffffffff164261409a565b90508015612e415781831115612dc3576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612dfd9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166129ed565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612ef85773ffffffffffffffffffffffffffffffffffffffff8416612ea0576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610741565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610741565b8483101561300b5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f3c908261409a565b612f46878a61409a565b612f5091906141a0565b612f5a91906141e2565b905073ffffffffffffffffffffffffffffffffffffffff8616612fb3576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610741565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610741565b613015858461409a565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611ea6565b60008183106130cb5781611ea6565b5090919050565b606082471015613164576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610741565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161318d919061421d565b60006040518083038185875af1925050503d80600081146131ca576040519150601f19603f3d011682016040523d82523d6000602084013e6131cf565b606091505b50915091506131e0878383876131eb565b979650505050505050565b6060831561328157825160000361327a5773ffffffffffffffffffffffffffffffffffffffff85163b61327a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610741565b5081612a0f565b612a0f83838151156132965781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107419190613400565b5080546132d6906138fd565b6000825580601f106132e6575050565b601f01602090049060005260206000209081019061186d91905b808211156133145760008155600101613300565b5090565b60006020828403121561332a57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611ea657600080fd5b803567ffffffffffffffff8116811461337257600080fd5b919050565b60006020828403121561338957600080fd5b611ea68261335a565b60005b838110156133ad578181015183820152602001613395565b50506000910152565b600081518084526133ce816020860160208601613392565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ea660208301846133b6565b60006020828403121561342557600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461186d57600080fd5b80356133728161342c565b60006020828403121561346b57600080fd5b8135611ea68161342c565b60006020828403121561348857600080fd5b813567ffffffffffffffff81111561349f57600080fd5b82016101008185031215611ea657600080fd5b60008083601f8401126134c457600080fd5b50813567ffffffffffffffff8111156134dc57600080fd5b6020830191508360208260051b85010111156134f757600080fd5b9250929050565b6000806000806040858703121561351457600080fd5b843567ffffffffffffffff8082111561352c57600080fd5b613538888389016134b2565b9096509450602087013591508082111561355157600080fd5b5061355e878288016134b2565b95989497509550505050565b6000806040838503121561357d57600080fd5b82356135888161342c565b946020939093013593505050565b6000806000604084860312156135ab57600080fd5b6135b48461335a565b9250602084013567ffffffffffffffff808211156135d157600080fd5b818601915086601f8301126135e557600080fd5b8135818111156135f457600080fd5b87602082850101111561360657600080fd5b6020830194508093505050509250925092565b60006020828403121561362b57600080fd5b813567ffffffffffffffff81111561364257600080fd5b820160a08185031215611ea657600080fd5b60208152600082516040602084015261367060608401826133b6565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526136ab82826133b6565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561370257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016136d0565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561370257835167ffffffffffffffff168352928401929184019160010161372a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156137a3576137a3613750565b60405290565b60405160c0810167ffffffffffffffff811182821017156137a3576137a3613750565b801515811461186d57600080fd5b8035613372816137cc565b80356fffffffffffffffffffffffffffffffff8116811461337257600080fd5b60006060828403121561381757600080fd5b6040516060810181811067ffffffffffffffff8211171561383a5761383a613750565b604052905080823561384b816137cc565b8152613859602084016137e5565b602082015261386a604084016137e5565b60408201525092915050565b600080600060e0848603121561388b57600080fd5b6138948461335a565b92506138a38560208601613805565b91506138b28560808601613805565b90509250925092565b600080602083850312156138ce57600080fd5b823567ffffffffffffffff8111156138e557600080fd5b6138f1858286016134b2565b90969095509350505050565b600181811c9082168061391157607f821691505b60208210810361394a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561396257600080fd5b5051919050565b600082601f83011261397a57600080fd5b813567ffffffffffffffff8082111561399557613995613750565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156139db576139db613750565b816040528381528660208588010111156139f457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101008236031215613a2757600080fd5b613a2f61377f565b823567ffffffffffffffff80821115613a4757600080fd5b613a5336838701613969565b8352613a616020860161335a565b6020840152613a726040860161344e565b604084015260608501356060840152613a8d6080860161344e565b608084015260a0850135915080821115613aa657600080fd5b613ab236838701613969565b60a084015260c0850135915080821115613acb57600080fd5b613ad736838701613969565b60c084015260e0850135915080821115613af057600080fd5b50613afd36828601613969565b60e08301525092915050565b601f8211156112b5576000816000526020600020601f850160051c81016020861015613b325750805b601f850160051c820191505b81811015613b5157828155600101613b3e565b505050505050565b67ffffffffffffffff831115613b7157613b71613750565b613b8583613b7f83546138fd565b83613b09565b6000601f841160018114613bd75760008515613ba15750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613c6d565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613c265786850135825560209485019460019092019101613c06565b5086821015613c61577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b604081526000613c8760408301866133b6565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a08236031215613cea57600080fd5b60405160a0810167ffffffffffffffff8282108183111715613d0e57613d0e613750565b816040528435915080821115613d2357600080fd5b50613d3036828601613969565b825250613d3f6020840161335a565b60208201526040830135613d528161342c565b6040820152606083810135908201526080830135613d6f8161342c565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613ddd57600080fd5b9190910192915050565b60006101408236031215613dfa57600080fd5b613e026137a9565b613e0b8361335a565b8152613e19602084016137da565b6020820152604083013567ffffffffffffffff80821115613e3957600080fd5b613e4536838701613969565b60408401526060850135915080821115613e5e57600080fd5b50613e6b36828601613969565b606083015250613e7e3660808501613805565b6080820152613e903660e08501613805565b60a082015292915050565b815167ffffffffffffffff811115613eb557613eb5613750565b613ec981613ec384546138fd565b84613b09565b602080601f831160018114613f1c5760008415613ee65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b51565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613f6957888601518255948401946001909101908401613f4a565b5085821015613fa557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613fd9818401876133b6565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506140179050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526136ab565b60006020828403121561406057600080fd5b8151611ea6816137cc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561063c5761063c61406b565b67ffffffffffffffff8416815260e081016140f960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612a0f565b6060810161063c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561417e57600080fd5b8151611ea68161342c565b808202811582820484141761063c5761063c61406b565b8082018082111561063c5761063c61406b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614218577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613ddd81846020870161339256fea164736f6c6343000818000a", } var LockReleaseTokenPoolABI = LockReleaseTokenPoolMetaData.ABI @@ -750,6 +750,18 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetRouter(ne return _LockReleaseTokenPool.Contract.SetRouter(&_LockReleaseTokenPool.TransactOpts, newRouter) } +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) TransferLiquidity(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "transferLiquidity", from, amount) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) TransferLiquidity(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.TransferLiquidity(&_LockReleaseTokenPool.TransactOpts, from, amount) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) TransferLiquidity(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.TransferLiquidity(&_LockReleaseTokenPool.TransactOpts, from, amount) +} + func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "transferOwnership", to) } @@ -1881,6 +1893,134 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseLiquidityRemoved return event, nil } +type LockReleaseTokenPoolLiquidityTransferredIterator struct { + Event *LockReleaseTokenPoolLiquidityTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LockReleaseTokenPoolLiquidityTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LockReleaseTokenPoolLiquidityTransferred) + 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(LockReleaseTokenPoolLiquidityTransferred) + 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 *LockReleaseTokenPoolLiquidityTransferredIterator) Error() error { + return it.fail +} + +func (it *LockReleaseTokenPoolLiquidityTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LockReleaseTokenPoolLiquidityTransferred struct { + From common.Address + Amount *big.Int + Raw types.Log +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterLiquidityTransferred(opts *bind.FilterOpts, from []common.Address) (*LockReleaseTokenPoolLiquidityTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + + logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "LiquidityTransferred", fromRule) + if err != nil { + return nil, err + } + return &LockReleaseTokenPoolLiquidityTransferredIterator{contract: _LockReleaseTokenPool.contract, event: "LiquidityTransferred", logs: logs, sub: sub}, nil +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchLiquidityTransferred(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolLiquidityTransferred, from []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + + logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "LiquidityTransferred", fromRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LockReleaseTokenPoolLiquidityTransferred) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "LiquidityTransferred", 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 (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseLiquidityTransferred(log types.Log) (*LockReleaseTokenPoolLiquidityTransferred, error) { + event := new(LockReleaseTokenPoolLiquidityTransferred) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "LiquidityTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type LockReleaseTokenPoolLockedIterator struct { Event *LockReleaseTokenPoolLocked @@ -2939,6 +3079,8 @@ func (_LockReleaseTokenPool *LockReleaseTokenPool) ParseLog(log types.Log) (gene return _LockReleaseTokenPool.ParseLiquidityAdded(log) case _LockReleaseTokenPool.abi.Events["LiquidityRemoved"].ID: return _LockReleaseTokenPool.ParseLiquidityRemoved(log) + case _LockReleaseTokenPool.abi.Events["LiquidityTransferred"].ID: + return _LockReleaseTokenPool.ParseLiquidityTransferred(log) case _LockReleaseTokenPool.abi.Events["Locked"].ID: return _LockReleaseTokenPool.ParseLocked(log) case _LockReleaseTokenPool.abi.Events["Minted"].ID: @@ -2997,6 +3139,10 @@ func (LockReleaseTokenPoolLiquidityRemoved) Topic() common.Hash { return common.HexToHash("0xc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf9840171719") } +func (LockReleaseTokenPoolLiquidityTransferred) Topic() common.Hash { + return common.HexToHash("0x6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db62") +} + func (LockReleaseTokenPoolLocked) Topic() common.Hash { return common.HexToHash("0x9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008") } @@ -3092,6 +3238,8 @@ type LockReleaseTokenPoolInterface interface { SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) + TransferLiquidity(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) WithdrawLiquidity(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) @@ -3150,6 +3298,12 @@ type LockReleaseTokenPoolInterface interface { ParseLiquidityRemoved(log types.Log) (*LockReleaseTokenPoolLiquidityRemoved, error) + FilterLiquidityTransferred(opts *bind.FilterOpts, from []common.Address) (*LockReleaseTokenPoolLiquidityTransferredIterator, error) + + WatchLiquidityTransferred(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolLiquidityTransferred, from []common.Address) (event.Subscription, error) + + ParseLiquidityTransferred(log types.Log) (*LockReleaseTokenPoolLiquidityTransferred, error) + FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*LockReleaseTokenPoolLockedIterator, error) WatchLocked(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolLocked, sender []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generated/lock_release_token_pool_and_proxy/lock_release_token_pool_and_proxy.go b/core/gethwrappers/ccip/generated/lock_release_token_pool_and_proxy/lock_release_token_pool_and_proxy.go index 15dd411741d..94c80882d4e 100644 --- a/core/gethwrappers/ccip/generated/lock_release_token_pool_and_proxy/lock_release_token_pool_and_proxy.go +++ b/core/gethwrappers/ccip/generated/lock_release_token_pool_and_proxy/lock_release_token_pool_and_proxy.go @@ -82,8 +82,8 @@ type TokenPoolChainUpdate struct { } var LockReleaseTokenPoolAndProxyMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"oldPool\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"LegacyPoolChanged\",\"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\":\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"onRampAddress\",\"type\":\"address\"}],\"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\":\"getRemotePool\",\"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\":[{\"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\":[{\"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\"},{\"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\":\"contractIPoolPriorTo1_5\",\"name\":\"prevPool\",\"type\":\"address\"}],\"name\":\"setPreviousPool\",\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004e1b38038062004e1b83398101604081905262000035916200056d565b84848483838383833380600081620000945760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c757620000c78162000186565b5050506001600160a01b0384161580620000e857506001600160a01b038116155b80620000fb57506001600160a01b038216155b156200011a576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016d576040805160008152602081019091526200016d908462000231565b5050505094151560e05250620006de9650505050505050565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008b565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000252576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002dd57600083828151811062000276576200027662000690565b60209081029190910101519050620002906002826200038e565b15620002d3576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000255565b5060005b81518110156200038957600082828151811062000302576200030262000690565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200032e575062000380565b6200033b600282620003ae565b156200037e576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002e1565b505050565b6000620003a5836001600160a01b038416620003c5565b90505b92915050565b6000620003a5836001600160a01b038416620004c9565b60008181526001830160205260408120548015620004be576000620003ec600183620006a6565b85549091506000906200040290600190620006a6565b90508181146200046e57600086600001828154811062000426576200042662000690565b90600052602060002001549050808760000184815481106200044c576200044c62000690565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004825762000482620006c8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a8565b6000915050620003a8565b60008181526001830160205260408120546200051257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a8565b506000620003a8565b6001600160a01b03811681146200053157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000557816200051b565b919050565b805180151581146200055757600080fd5b600080600080600060a086880312156200058657600080fd5b855162000593816200051b565b602087810151919650906001600160401b0380821115620005b357600080fd5b818901915089601f830112620005c857600080fd5b815181811115620005dd57620005dd62000534565b8060051b604051601f19603f8301168101818110858211171562000605576200060562000534565b60405291825284820192508381018501918c8311156200062457600080fd5b938501935b828510156200064d576200063d856200054a565b8452938501939285019262000629565b80995050505050505062000664604087016200054a565b925062000674606087016200055c565b915062000684608087016200054a565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161469a620007816000396000818161051701526118510152600081816105c401528181611e860152612a4201526000818161059e01528181611c1e0152612139015260008181610292015281816102e7015281816107a2015281816108740152818161093e0152818161191301528181611b3e015281816120590152818161223f015281816129d80152612c2d015261469a6000f3fe608060405234801561001057600080fd5b50600436106102265760003560e01c80639766b9321161012a578063c0d78655116100bd578063db6327dc1161008c578063e0351e1311610071578063e0351e13146105c2578063eb521a4c146105e8578063f2fde38b146105fb57600080fd5b8063db6327dc14610589578063dc0bd9711461059c57600080fd5b8063c0d786551461053b578063c4bffe2b1461054e578063c75eea9c14610563578063cf7401f31461057657600080fd5b8063af58d59f116100f9578063af58d59f14610475578063b0f479a1146104e4578063b794658014610502578063bb98546b1461051557600080fd5b80639766b9321461041a5780639a4575b91461042d578063a7cd63b71461044d578063a8d87a3b1461046257600080fd5b806354c8a4f3116101bd57806379ba50971161018c57806383826b2b1161017157806383826b2b146103d65780638926f54f146103e95780638da5cb5b146103fc57600080fd5b806379ba5097146103bb5780637d54534e146103c357600080fd5b806354c8a4f3146103645780636cfd1553146103775780636d3d1a581461038a57806378a010b2146103a857600080fd5b806321df0da7116101f957806321df0da714610290578063240028e8146102d75780633907753714610324578063432a6ba31461034657600080fd5b806301ffc9a71461022b5780630a2fd493146102535780630a861f2a14610273578063181f5a7714610288575b600080fd5b61023e6102393660046135d7565b61060e565b60405190151581526020015b60405180910390f35b610266610261366004613636565b61066a565b60405161024a91906136bf565b6102866102813660046136d2565b61071a565b005b6102666108cb565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161024a565b61023e6102e5366004613718565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b610337610332366004613735565b6108e7565b6040519051815260200161024a565b60095473ffffffffffffffffffffffffffffffffffffffff166102b2565b6102866103723660046137bd565b610a10565b610286610385366004613718565b610a8b565b600a5473ffffffffffffffffffffffffffffffffffffffff166102b2565b6102866103b6366004613829565b610ada565b610286610c49565b6102866103d1366004613718565b610d46565b61023e6103e43660046138ac565b610d95565b61023e6103f7366004613636565b610e62565b60005473ffffffffffffffffffffffffffffffffffffffff166102b2565b610286610428366004613718565b610e79565b61044061043b3660046138e3565b610f08565b60405161024a919061391e565b610455610fd1565b60405161024a919061397e565b6102b2610470366004613636565b503090565b610488610483366004613636565b610fe2565b60405161024a919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102b2565b610266610510366004613636565b6110b7565b7f000000000000000000000000000000000000000000000000000000000000000061023e565b610286610549366004613718565b6110e2565b6105566111b6565b60405161024a91906139d8565b610488610571366004613636565b61126e565b610286610584366004613b8f565b611340565b610286610597366004613bd4565b6113c9565b7f00000000000000000000000000000000000000000000000000000000000000006102b2565b7f000000000000000000000000000000000000000000000000000000000000000061023e565b6102866105f63660046136d2565b61184f565b610286610609366004613718565b61196b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061066457506106648261197f565b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061069590613c16565b80601f01602080910402602001604051908101604052809291908181526020018280546106c190613c16565b801561070e5780601f106106e35761010080835404028352916020019161070e565b820191906000526020600020905b8154815290600101906020018083116106f157829003601f168201915b50505050509050919050565b60095473ffffffffffffffffffffffffffffffffffffffff163314610772576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108229190613c69565b101561085a576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61089b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611a63565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040518060600160405280602681526020016146686026913981565b60408051602081019091526000815261090761090283613d1e565b611b37565b60085473ffffffffffffffffffffffffffffffffffffffff1661096e5761096973ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016336060850135611a63565b61097f565b61097f61097a83613d1e565b611d68565b61098f6060830160408401613718565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f5284606001356040516109f191815260200190565b60405180910390a3506040805160208101909152606090910135815290565b610a18611e01565b610a8584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611e8492505050565b50505050565b610a93611e01565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610ae2611e01565b610aeb83610e62565b610b2d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610769565b67ffffffffffffffff831660009081526007602052604081206004018054610b5490613c16565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8090613c16565b8015610bcd5780601f10610ba257610100808354040283529160200191610bcd565b820191906000526020600020905b815481529060010190602001808311610bb057829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610bfc838583613e63565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610c3b93929190613f7d565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610769565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d4e611e01565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600073ffffffffffffffffffffffffffffffffffffffff8216301480610e5b5750600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86169281019290925273ffffffffffffffffffffffffffffffffffffffff848116602484015216906383826b2b90604401602060405180830381865afa158015610e37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5b9190613fe1565b9392505050565b6000610664600567ffffffffffffffff841661203a565b610e81611e01565b6008805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f81accd0a7023865eaa51b3399dd0eafc488bf3ba238402911e1659cfe860f22891015b60405180910390a15050565b6040805180820190915260608082526020820152610f2d610f2883613ffe565b612052565b60085473ffffffffffffffffffffffffffffffffffffffff1615610f5c57610f5c610f5783613ffe565b61221c565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610fb68460200160208101906105109190613636565b81526040805160208181019092526000815291015292915050565b6060610fdd6002612336565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261066490612343565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061069590613c16565b6110ea611e01565b73ffffffffffffffffffffffffffffffffffffffff8116611137576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610efc565b606060006111c46005612336565b90506000815167ffffffffffffffff8111156111e2576111e2613a1a565b60405190808252806020026020018201604052801561120b578160200160208202803683370190505b50905060005b82518110156112675782818151811061122c5761122c6140a0565b6020026020010151828281518110611246576112466140a0565b67ffffffffffffffff90921660209283029190910190910152600101611211565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261066490612343565b600a5473ffffffffffffffffffffffffffffffffffffffff163314801590611380575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156113b9576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610769565b6113c48383836123f5565b505050565b6113d1611e01565b60005b818110156113c45760008383838181106113f0576113f06140a0565b905060200281019061140291906140cf565b61140b9061410d565b905061142081608001518260200151156124df565b6114338160a001518260200151156124df565b80602001511561172f5780516114559060059067ffffffffffffffff16612618565b61149a5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610769565b60408101515115806114af5750606081015151155b156114e6576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906116c790826141c1565b50606082015160058201906116dc90826141c1565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061172294939291906142db565b60405180910390a1611846565b80516117479060059067ffffffffffffffff16612624565b61178c5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610769565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906117f56004830182613589565b611803600583016000613589565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016113d4565b7f00000000000000000000000000000000000000000000000000000000000000006118a6576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60095473ffffffffffffffffffffffffffffffffffffffff1633146118f9576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610769565b61193b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612630565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611973611e01565b61197c8161268e565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611a1257507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061066457507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526113c49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612783565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611bcc5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610769565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9e9190613fe1565b15611cd5576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ce2816020015161288f565b6000611cf1826020015161066a565b9050805160001480611d15575080805190602001208260a001518051906020012014155b15611d52578160a001516040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161076991906136bf565b611d64826020015183606001516129b5565b5050565b6008548151606083015160208401516040517f8627fad600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90941693638627fad693611dcc9390923392600401614374565b600060405180830381600087803b158015611de657600080fd5b505af1158015611dfa573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611e82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610769565b565b7f0000000000000000000000000000000000000000000000000000000000000000611edb576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611f71576000838281518110611efb57611efb6140a0565b60200260200101519050611f198160026129fc90919063ffffffff16565b15611f685760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611ede565b5060005b81518110156113c4576000828281518110611f9257611f926140a0565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611fd65750612032565b611fe1600282612a1e565b156120305760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611f75565b60008181526001830160205260408120541515610e5b565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146120e75760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610769565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612195573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b99190613fe1565b156121f0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121fd8160400151612a40565b61220a8160200151612abf565b61197c81602001518260600151612c0d565b60085460608201516122699173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692911690611a63565b60085460408083015183516060850151602086015193517f9687544500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909516946396875445946122d1949392916004016143d5565b6000604051808303816000875af11580156122f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611d649190810190614435565b60606000610e5b83612c51565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526123d182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426123b591906144d2565b85608001516fffffffffffffffffffffffffffffffff16612cac565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6123fe83610e62565b612440576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610769565b61244b8260006124df565b67ffffffffffffffff8316600090815260076020526040902061246e9083612cd6565b6124798160006124df565b67ffffffffffffffff8316600090815260076020526040902061249f9060020182612cd6565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516124d2939291906144e5565b60405180910390a1505050565b8151156125a65781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612535575060408201516fffffffffffffffffffffffffffffffff16155b1561256e57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107699190614568565b8015611d64576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff161515806125df575060208201516fffffffffffffffffffffffffffffffff1615155b15611d6457816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107699190614568565b6000610e5b8383612e78565b6000610e5b8383612ec7565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610a859085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611ab5565b3373ffffffffffffffffffffffffffffffffffffffff82160361270d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610769565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006127e5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612fba9092919063ffffffff16565b8051909150156113c457808060200190518101906128039190613fe1565b6113c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610769565b61289881610e62565b6128da576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610769565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297d9190613fe1565b61197c576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610769565b67ffffffffffffffff82166000908152600760205260409020611d6490600201827f0000000000000000000000000000000000000000000000000000000000000000612fc9565b6000610e5b8373ffffffffffffffffffffffffffffffffffffffff8416612ec7565b6000610e5b8373ffffffffffffffffffffffffffffffffffffffff8416612e78565b7f00000000000000000000000000000000000000000000000000000000000000001561197c57612a7160028261334c565b61197c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610769565b612ac881610e62565b612b0a576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610769565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612b83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba791906145a4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461197c576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610769565b67ffffffffffffffff82166000908152600760205260409020611d6490827f0000000000000000000000000000000000000000000000000000000000000000612fc9565b60608160000180548060200260200160405190810160405280929190818152602001828054801561070e57602002820191906000526020600020905b815481526020019060010190808311612c8d5750505050509050919050565b6000612ccb85612cbc84866145c1565b612cc690876145d8565b61337b565b90505b949350505050565b8154600090612cff90700100000000000000000000000000000000900463ffffffff16426144d2565b90508015612da15760018301548354612d47916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612cac565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612dc7916fffffffffffffffffffffffffffffffff908116911661337b565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906124d2908490614568565b6000818152600183016020526040812054612ebf57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610664565b506000610664565b60008181526001830160205260408120548015612fb0576000612eeb6001836144d2565b8554909150600090612eff906001906144d2565b9050818114612f64576000866000018281548110612f1f57612f1f6140a0565b9060005260206000200154905080876000018481548110612f4257612f426140a0565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612f7557612f756145eb565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610664565b6000915050610664565b6060612cce8484600085613391565b825474010000000000000000000000000000000000000000900460ff161580612ff0575081155b15612ffa57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061304090700100000000000000000000000000000000900463ffffffff16426144d2565b905080156131005781831115613082576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546130bc9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612cac565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156131b75773ffffffffffffffffffffffffffffffffffffffff841661315f576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610769565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610769565b848310156132ca5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906131fb90826144d2565b613205878a6144d2565b61320f91906145d8565b613219919061461a565b905073ffffffffffffffffffffffffffffffffffffffff8616613272576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610769565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610769565b6132d485846144d2565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610e5b565b600081831061338a5781610e5b565b5090919050565b606082471015613423576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610769565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161344c9190614655565b60006040518083038185875af1925050503d8060008114613489576040519150601f19603f3d011682016040523d82523d6000602084013e61348e565b606091505b509150915061349f878383876134aa565b979650505050505050565b606083156135405782516000036135395773ffffffffffffffffffffffffffffffffffffffff85163b613539576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610769565b5081612cce565b612cce83838151156135555781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161076991906136bf565b50805461359590613c16565b6000825580601f106135a5575050565b601f01602090049060005260206000209081019061197c91905b808211156135d357600081556001016135bf565b5090565b6000602082840312156135e957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e5b57600080fd5b803567ffffffffffffffff8116811461363157600080fd5b919050565b60006020828403121561364857600080fd5b610e5b82613619565b60005b8381101561366c578181015183820152602001613654565b50506000910152565b6000815180845261368d816020860160208601613651565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610e5b6020830184613675565b6000602082840312156136e457600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461197c57600080fd5b8035613631816136eb565b60006020828403121561372a57600080fd5b8135610e5b816136eb565b60006020828403121561374757600080fd5b813567ffffffffffffffff81111561375e57600080fd5b82016101008185031215610e5b57600080fd5b60008083601f84011261378357600080fd5b50813567ffffffffffffffff81111561379b57600080fd5b6020830191508360208260051b85010111156137b657600080fd5b9250929050565b600080600080604085870312156137d357600080fd5b843567ffffffffffffffff808211156137eb57600080fd5b6137f788838901613771565b9096509450602087013591508082111561381057600080fd5b5061381d87828801613771565b95989497509550505050565b60008060006040848603121561383e57600080fd5b61384784613619565b9250602084013567ffffffffffffffff8082111561386457600080fd5b818601915086601f83011261387857600080fd5b81358181111561388757600080fd5b87602082850101111561389957600080fd5b6020830194508093505050509250925092565b600080604083850312156138bf57600080fd5b6138c883613619565b915060208301356138d8816136eb565b809150509250929050565b6000602082840312156138f557600080fd5b813567ffffffffffffffff81111561390c57600080fd5b820160a08185031215610e5b57600080fd5b60208152600082516040602084015261393a6060840182613675565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526139758282613675565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156139cc57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161399a565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139cc57835167ffffffffffffffff16835292840192918401916001016139f4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613a6d57613a6d613a1a565b60405290565b60405160c0810167ffffffffffffffff81118282101715613a6d57613a6d613a1a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613add57613add613a1a565b604052919050565b801515811461197c57600080fd5b803561363181613ae5565b80356fffffffffffffffffffffffffffffffff8116811461363157600080fd5b600060608284031215613b3057600080fd5b6040516060810181811067ffffffffffffffff82111715613b5357613b53613a1a565b6040529050808235613b6481613ae5565b8152613b7260208401613afe565b6020820152613b8360408401613afe565b60408201525092915050565b600080600060e08486031215613ba457600080fd5b613bad84613619565b9250613bbc8560208601613b1e565b9150613bcb8560808601613b1e565b90509250925092565b60008060208385031215613be757600080fd5b823567ffffffffffffffff811115613bfe57600080fd5b613c0a85828601613771565b90969095509350505050565b600181811c90821680613c2a57607f821691505b602082108103613c63577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215613c7b57600080fd5b5051919050565b600067ffffffffffffffff821115613c9c57613c9c613a1a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613cd957600080fd5b8135613cec613ce782613c82565b613a96565b818152846020838601011115613d0157600080fd5b816020850160208301376000918101602001919091529392505050565b60006101008236031215613d3157600080fd5b613d39613a49565b823567ffffffffffffffff80821115613d5157600080fd5b613d5d36838701613cc8565b8352613d6b60208601613619565b6020840152613d7c6040860161370d565b604084015260608501356060840152613d976080860161370d565b608084015260a0850135915080821115613db057600080fd5b613dbc36838701613cc8565b60a084015260c0850135915080821115613dd557600080fd5b613de136838701613cc8565b60c084015260e0850135915080821115613dfa57600080fd5b50613e0736828601613cc8565b60e08301525092915050565b601f8211156113c4576000816000526020600020601f850160051c81016020861015613e3c5750805b601f850160051c820191505b81811015613e5b57828155600101613e48565b505050505050565b67ffffffffffffffff831115613e7b57613e7b613a1a565b613e8f83613e898354613c16565b83613e13565b6000601f841160018114613ee15760008515613eab5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611dfa565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613f305786850135825560209485019460019092019101613f10565b5086821015613f6b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b604081526000613f906040830186613675565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060208284031215613ff357600080fd5b8151610e5b81613ae5565b600060a0823603121561401057600080fd5b60405160a0810167ffffffffffffffff828210818311171561403457614034613a1a565b81604052843591508082111561404957600080fd5b5061405636828601613cc8565b82525061406560208401613619565b60208201526040830135614078816136eb565b6040820152606083810135908201526080830135614095816136eb565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261410357600080fd5b9190910192915050565b6000610140823603121561412057600080fd5b614128613a73565b61413183613619565b815261413f60208401613af3565b6020820152604083013567ffffffffffffffff8082111561415f57600080fd5b61416b36838701613cc8565b6040840152606085013591508082111561418457600080fd5b5061419136828601613cc8565b6060830152506141a43660808501613b1e565b60808201526141b63660e08501613b1e565b60a082015292915050565b815167ffffffffffffffff8111156141db576141db613a1a565b6141ef816141e98454613c16565b84613e13565b602080601f831160018114614242576000841561420c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613e5b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561428f57888601518255948401946001909101908401614270565b50858210156142cb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526142ff81840187613675565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061433d9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613975565b60a08152600061438760a0830187613675565b73ffffffffffffffffffffffffffffffffffffffff8616602084015284604084015267ffffffffffffffff841660608401528281036080840152600081526020810191505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8516815260a06020820152600061440460a0830186613675565b60408301949094525067ffffffffffffffff9190911660608201528082036080909101526000815260200192915050565b60006020828403121561444757600080fd5b815167ffffffffffffffff81111561445e57600080fd5b8201601f8101841361446f57600080fd5b805161447d613ce782613c82565b81815285602083850101111561449257600080fd5b613975826020830160208601613651565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610664576106646144a3565b67ffffffffffffffff8416815260e0810161453160208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612cce565b6060810161066482848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156145b657600080fd5b8151610e5b816136eb565b8082028115828204841417610664576106646144a3565b80820180821115610664576106646144a3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614650577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000825161410381846020870161365156fe4c6f636b52656c65617365546f6b656e506f6f6c416e6450726f787920312e352e302d646576a164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"oldPool\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractIPoolPriorTo1_5\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"LegacyPoolChanged\",\"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\":\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"onRampAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPreviousPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"getRemotePool\",\"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\":[{\"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\":[{\"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\"},{\"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\":\"contractIPoolPriorTo1_5\",\"name\":\"prevPool\",\"type\":\"address\"}],\"name\":\"setPreviousPool\",\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x6101006040523480156200001257600080fd5b5060405162004f4338038062004f4383398101604081905262000035916200056d565b84848483838383833380600081620000945760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c757620000c78162000186565b5050506001600160a01b0384161580620000e857506001600160a01b038116155b80620000fb57506001600160a01b038216155b156200011a576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016d576040805160008152602081019091526200016d908462000231565b5050505094151560e05250620006de9650505050505050565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008b565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000252576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002dd57600083828151811062000276576200027662000690565b60209081029190910101519050620002906002826200038e565b15620002d3576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000255565b5060005b81518110156200038957600082828151811062000302576200030262000690565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200032e575062000380565b6200033b600282620003ae565b156200037e576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002e1565b505050565b6000620003a5836001600160a01b038416620003c5565b90505b92915050565b6000620003a5836001600160a01b038416620004c9565b60008181526001830160205260408120548015620004be576000620003ec600183620006a6565b85549091506000906200040290600190620006a6565b90508082146200046e57600086600001828154811062000426576200042662000690565b90600052602060002001549050808760000184815481106200044c576200044c62000690565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004825762000482620006c8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a8565b6000915050620003a8565b60008181526001830160205260408120546200051257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a8565b506000620003a8565b6001600160a01b03811681146200053157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000557816200051b565b919050565b805180151581146200055757600080fd5b600080600080600060a086880312156200058657600080fd5b855162000593816200051b565b602087810151919650906001600160401b0380821115620005b357600080fd5b818901915089601f830112620005c857600080fd5b815181811115620005dd57620005dd62000534565b8060051b604051601f19603f8301168101818110858211171562000605576200060562000534565b60405291825284820192508381018501918c8311156200062457600080fd5b938501935b828510156200064d576200063d856200054a565b8452938501939285019262000629565b80995050505050505062000664604087016200054a565b925062000674606087016200055c565b915062000684608087016200054a565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e0516147c2620007816000396000818161057e015261195401526000818161062b01528181611f8e0152612b4a01526000818161060501528181611d2101526122410152600081816102c80152818161031d01528181610809015281816108db015281816109b501528181611a1601528181611c41015281816121610152818161234701528181612ae00152612d3501526147c26000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c80639766b93211610145578063c0d78655116100bd578063db6327dc1161008c578063e0351e1311610071578063e0351e1314610629578063eb521a4c1461064f578063f2fde38b1461066257600080fd5b8063db6327dc146105f0578063dc0bd9711461060357600080fd5b8063c0d78655146105a2578063c4bffe2b146105b5578063c75eea9c146105ca578063cf7401f3146105dd57600080fd5b8063a8d87a3b11610114578063b0f479a1116100f9578063b0f479a11461054b578063b794658014610569578063bb98546b1461057c57600080fd5b8063a8d87a3b146104c9578063af58d59f146104dc57600080fd5b80639766b932146104635780639a4575b914610476578063a2b261d814610496578063a7cd63b7146104b457600080fd5b806366320087116101d857806379ba5097116101a757806383826b2b1161018c57806383826b2b1461041f5780638926f54f146104325780638da5cb5b1461044557600080fd5b806379ba5097146104045780637d54534e1461040c57600080fd5b806366320087146103ad5780636cfd1553146103c05780636d3d1a58146103d357806378a010b2146103f157600080fd5b806321df0da71161022f5780633907753711610214578063390775371461035a578063432a6ba31461037c57806354c8a4f31461039a57600080fd5b806321df0da7146102c6578063240028e81461030d57600080fd5b806301ffc9a7146102615780630a2fd493146102895780630a861f2a146102a9578063181f5a77146102be575b600080fd5b61027461026f3660046136df565b610675565b60405190151581526020015b60405180910390f35b61029c61029736600461373e565b6106d1565b60405161028091906137c7565b6102bc6102b73660046137da565b610781565b005b61029c610932565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610280565b61027461031b366004613820565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61036d61036836600461383d565b61094e565b60405190518152602001610280565b600a5473ffffffffffffffffffffffffffffffffffffffff166102e8565b6102bc6103a83660046138c5565b610a87565b6102bc6103bb366004613931565b610b02565b6102bc6103ce366004613820565b610b8e565b60085473ffffffffffffffffffffffffffffffffffffffff166102e8565b6102bc6103ff36600461395d565b610bdd565b6102bc610d4c565b6102bc61041a366004613820565b610e49565b61027461042d3660046139e0565b610e98565b61027461044036600461373e565b610f65565b60005473ffffffffffffffffffffffffffffffffffffffff166102e8565b6102bc610471366004613820565b610f7c565b610489610484366004613a17565b61100b565b6040516102809190613a52565b60095473ffffffffffffffffffffffffffffffffffffffff166102e8565b6104bc6110d4565b6040516102809190613ab2565b6102e86104d736600461373e565b503090565b6104ef6104ea36600461373e565b6110e5565b604051610280919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102e8565b61029c61057736600461373e565b6111ba565b7f0000000000000000000000000000000000000000000000000000000000000000610274565b6102bc6105b0366004613820565b6111e5565b6105bd6112b9565b6040516102809190613b0c565b6104ef6105d836600461373e565b611371565b6102bc6105eb366004613cc3565b611443565b6102bc6105fe366004613d08565b6114cc565b7f00000000000000000000000000000000000000000000000000000000000000006102e8565b7f0000000000000000000000000000000000000000000000000000000000000000610274565b6102bc61065d3660046137da565b611952565b6102bc610670366004613820565b611a6e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d405660000000000000000000000000000000000000000000000000000000014806106cb57506106cb82611a82565b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106fc90613d4a565b80601f016020809104026020016040519081016040528092919081815260200182805461072890613d4a565b80156107755780601f1061074a57610100808354040283529160200191610775565b820191906000526020600020905b81548152906001019060200180831161075857829003601f168201915b50505050509050919050565b600a5473ffffffffffffffffffffffffffffffffffffffff1633146107d9576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610865573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108899190613d9d565b10156108c1576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61090273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611b66565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040518060600160405280602281526020016147946022913981565b60408051602081019091526000815261096e61096983613e52565b611c3a565b60095473ffffffffffffffffffffffffffffffffffffffff166109e5576109e061099e6060840160408501613820565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906060850135611b66565b6109f6565b6109f66109f183613e52565b611e6b565b610a066060830160408401613820565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f528460600135604051610a6891815260200190565b60405180910390a3506040805160208101909152606090910135815290565b610a8f611f09565b610afc84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611f8c92505050565b50505050565b610b0a611f09565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610b7257600080fd5b505af1158015610b86573d6000803e3d6000fd5b505050505050565b610b96611f09565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610be5611f09565b610bee83610f65565b610c30576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016107d0565b67ffffffffffffffff831660009081526007602052604081206004018054610c5790613d4a565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8390613d4a565b8015610cd05780601f10610ca557610100808354040283529160200191610cd0565b820191906000526020600020905b815481529060010190602001808311610cb357829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610cff838583613f8f565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610d3e939291906140a9565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107d0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e51611f09565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600073ffffffffffffffffffffffffffffffffffffffff8216301480610f5e5750600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86169281019290925273ffffffffffffffffffffffffffffffffffffffff848116602484015216906383826b2b90604401602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e919061410d565b9392505050565b60006106cb600567ffffffffffffffff8416612142565b610f84611f09565b6009805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f81accd0a7023865eaa51b3399dd0eafc488bf3ba238402911e1659cfe860f22891015b60405180910390a15050565b604080518082019091526060808252602082015261103061102b8361412a565b61215a565b60095473ffffffffffffffffffffffffffffffffffffffff161561105f5761105f61105a8361412a565b612324565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a260405180604001604052806110b9846020016020810190610577919061373e565b81526040805160208181019092526000815291015292915050565b60606110e0600261243e565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526106cb9061244b565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106fc90613d4a565b6111ed611f09565b73ffffffffffffffffffffffffffffffffffffffff811661123a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610fff565b606060006112c7600561243e565b90506000815167ffffffffffffffff8111156112e5576112e5613b4e565b60405190808252806020026020018201604052801561130e578160200160208202803683370190505b50905060005b825181101561136a5782818151811061132f5761132f6141cc565b6020026020010151828281518110611349576113496141cc565b67ffffffffffffffff90921660209283029190910190910152600101611314565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526106cb9061244b565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590611483575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156114bc576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016107d0565b6114c78383836124fd565b505050565b6114d4611f09565b60005b818110156114c75760008383838181106114f3576114f36141cc565b905060200281019061150591906141fb565b61150e90614239565b905061152381608001518260200151156125e7565b6115368160a001518260200151156125e7565b8060200151156118325780516115589060059067ffffffffffffffff16612720565b61159d5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b60408101515115806115b25750606081015151155b156115e9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906117ca90826142ed565b50606082015160058201906117df90826142ed565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506118259493929190614407565b60405180910390a1611949565b805161184a9060059067ffffffffffffffff1661272c565b61188f5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d0565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906118f86004830182613691565b611906600583016000613691565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016114d7565b7f00000000000000000000000000000000000000000000000000000000000000006119a9576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff1633146119fc576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016107d0565b611a3e73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612738565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611a76611f09565b611a7f81612796565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611b1557507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806106cb57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526114c79084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261288b565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611ccf5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016107d0565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da1919061410d565b15611dd8576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611de58160200151612997565b6000611df482602001516106d1565b9050805160001480611e18575080805190602001208260a001518051906020012014155b15611e55578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016107d091906137c7565b611e6782602001518360600151612abd565b5050565b60095481516040808401516060850151602086015192517f8627fad600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90951694638627fad694611ed494909392916004016144a0565b600060405180830381600087803b158015611eee57600080fd5b505af1158015611f02573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611f8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d0565b565b7f0000000000000000000000000000000000000000000000000000000000000000611fe3576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015612079576000838281518110612003576120036141cc565b60200260200101519050612021816002612b0490919063ffffffff16565b156120705760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611fe6565b5060005b81518110156114c757600082828151811061209a5761209a6141cc565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120de575061213a565b6120e9600282612b26565b156121385760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161207d565b60008181526001830160205260408120541515610f5e565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146121ef5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016107d0565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa15801561229d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c1919061410d565b156122f8576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123058160400151612b48565b6123128160200151612bc7565b611a7f81602001518260600151612d15565b60095460608201516123719173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692911690611b66565b60095460408083015183516060850151602086015193517f9687544500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909516946396875445946123d994939291600401614501565b6000604051808303816000875af11580156123f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611e679190810190614561565b60606000610f5e83612d59565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526124d982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426124bd91906145fe565b85608001516fffffffffffffffffffffffffffffffff16612db4565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61250683610f65565b612548576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016107d0565b6125538260006125e7565b67ffffffffffffffff831660009081526007602052604090206125769083612dde565b6125818160006125e7565b67ffffffffffffffff831660009081526007602052604090206125a79060020182612dde565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516125da93929190614611565b60405180910390a1505050565b8151156126ae5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061263d575060408201516fffffffffffffffffffffffffffffffff16155b1561267657816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107d09190614694565b8015611e67576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff161515806126e7575060208201516fffffffffffffffffffffffffffffffff1615155b15611e6757816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107d09190614694565b6000610f5e8383612f80565b6000610f5e8383612fcf565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610afc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611bb8565b3373ffffffffffffffffffffffffffffffffffffffff821603612815576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006128ed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130c29092919063ffffffff16565b8051909150156114c7578080602001905181019061290b919061410d565b6114c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107d0565b6129a081610f65565b6129e2576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016107d0565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a85919061410d565b611a7f576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016107d0565b67ffffffffffffffff82166000908152600760205260409020611e6790600201827f00000000000000000000000000000000000000000000000000000000000000006130d1565b6000610f5e8373ffffffffffffffffffffffffffffffffffffffff8416612fcf565b6000610f5e8373ffffffffffffffffffffffffffffffffffffffff8416612f80565b7f000000000000000000000000000000000000000000000000000000000000000015611a7f57612b79600282613454565b611a7f576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016107d0565b612bd081610f65565b612c12576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016107d0565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612caf91906146d0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a7f576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016107d0565b67ffffffffffffffff82166000908152600760205260409020611e6790827f00000000000000000000000000000000000000000000000000000000000000006130d1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561077557602002820191906000526020600020905b815481526020019060010190808311612d955750505050509050919050565b6000612dd385612dc484866146ed565b612dce9087614704565b613483565b90505b949350505050565b8154600090612e0790700100000000000000000000000000000000900463ffffffff16426145fe565b90508015612ea95760018301548354612e4f916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612db4565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612ecf916fffffffffffffffffffffffffffffffff9081169116613483565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906125da908490614694565b6000818152600183016020526040812054612fc7575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106cb565b5060006106cb565b600081815260018301602052604081205480156130b8576000612ff36001836145fe565b8554909150600090613007906001906145fe565b905080821461306c576000866000018281548110613027576130276141cc565b906000526020600020015490508087600001848154811061304a5761304a6141cc565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061307d5761307d614717565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106cb565b60009150506106cb565b6060612dd68484600085613499565b825474010000000000000000000000000000000000000000900460ff1615806130f8575081155b1561310257505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061314890700100000000000000000000000000000000900463ffffffff16426145fe565b90508015613208578183111561318a576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546131c49083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612db4565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156132bf5773ffffffffffffffffffffffffffffffffffffffff8416613267576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016107d0565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016107d0565b848310156133d25760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690600090829061330390826145fe565b61330d878a6145fe565b6133179190614704565b6133219190614746565b905073ffffffffffffffffffffffffffffffffffffffff861661337a576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016107d0565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016107d0565b6133dc85846145fe565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610f5e565b60008183106134925781610f5e565b5090919050565b60608247101561352b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107d0565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516135549190614781565b60006040518083038185875af1925050503d8060008114613591576040519150601f19603f3d011682016040523d82523d6000602084013e613596565b606091505b50915091506135a7878383876135b2565b979650505050505050565b606083156136485782516000036136415773ffffffffffffffffffffffffffffffffffffffff85163b613641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107d0565b5081612dd6565b612dd6838381511561365d5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d091906137c7565b50805461369d90613d4a565b6000825580601f106136ad575050565b601f016020900490600052602060002090810190611a7f91905b808211156136db57600081556001016136c7565b5090565b6000602082840312156136f157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f5e57600080fd5b803567ffffffffffffffff8116811461373957600080fd5b919050565b60006020828403121561375057600080fd5b610f5e82613721565b60005b8381101561377457818101518382015260200161375c565b50506000910152565b60008151808452613795816020860160208601613759565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f5e602083018461377d565b6000602082840312156137ec57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114611a7f57600080fd5b8035613739816137f3565b60006020828403121561383257600080fd5b8135610f5e816137f3565b60006020828403121561384f57600080fd5b813567ffffffffffffffff81111561386657600080fd5b82016101008185031215610f5e57600080fd5b60008083601f84011261388b57600080fd5b50813567ffffffffffffffff8111156138a357600080fd5b6020830191508360208260051b85010111156138be57600080fd5b9250929050565b600080600080604085870312156138db57600080fd5b843567ffffffffffffffff808211156138f357600080fd5b6138ff88838901613879565b9096509450602087013591508082111561391857600080fd5b5061392587828801613879565b95989497509550505050565b6000806040838503121561394457600080fd5b823561394f816137f3565b946020939093013593505050565b60008060006040848603121561397257600080fd5b61397b84613721565b9250602084013567ffffffffffffffff8082111561399857600080fd5b818601915086601f8301126139ac57600080fd5b8135818111156139bb57600080fd5b8760208285010111156139cd57600080fd5b6020830194508093505050509250925092565b600080604083850312156139f357600080fd5b6139fc83613721565b91506020830135613a0c816137f3565b809150509250929050565b600060208284031215613a2957600080fd5b813567ffffffffffffffff811115613a4057600080fd5b820160a08185031215610f5e57600080fd5b602081526000825160406020840152613a6e606084018261377d565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152613aa9828261377d565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015613b0057835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613ace565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613b0057835167ffffffffffffffff1683529284019291840191600101613b28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613ba157613ba1613b4e565b60405290565b60405160c0810167ffffffffffffffff81118282101715613ba157613ba1613b4e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c1157613c11613b4e565b604052919050565b8015158114611a7f57600080fd5b803561373981613c19565b80356fffffffffffffffffffffffffffffffff8116811461373957600080fd5b600060608284031215613c6457600080fd5b6040516060810181811067ffffffffffffffff82111715613c8757613c87613b4e565b6040529050808235613c9881613c19565b8152613ca660208401613c32565b6020820152613cb760408401613c32565b60408201525092915050565b600080600060e08486031215613cd857600080fd5b613ce184613721565b9250613cf08560208601613c52565b9150613cff8560808601613c52565b90509250925092565b60008060208385031215613d1b57600080fd5b823567ffffffffffffffff811115613d3257600080fd5b613d3e85828601613879565b90969095509350505050565b600181811c90821680613d5e57607f821691505b602082108103613d97577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215613daf57600080fd5b5051919050565b600067ffffffffffffffff821115613dd057613dd0613b4e565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613e0d57600080fd5b8135613e20613e1b82613db6565b613bca565b818152846020838601011115613e3557600080fd5b816020850160208301376000918101602001919091529392505050565b60006101008236031215613e6557600080fd5b613e6d613b7d565b823567ffffffffffffffff80821115613e8557600080fd5b613e9136838701613dfc565b8352613e9f60208601613721565b6020840152613eb060408601613815565b604084015260608501356060840152613ecb60808601613815565b608084015260a0850135915080821115613ee457600080fd5b613ef036838701613dfc565b60a084015260c0850135915080821115613f0957600080fd5b613f1536838701613dfc565b60c084015260e0850135915080821115613f2e57600080fd5b50613f3b36828601613dfc565b60e08301525092915050565b601f8211156114c7576000816000526020600020601f850160051c81016020861015613f705750805b601f850160051c820191505b81811015610b8657828155600101613f7c565b67ffffffffffffffff831115613fa757613fa7613b4e565b613fbb83613fb58354613d4a565b83613f47565b6000601f84116001811461400d5760008515613fd75750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611f02565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561405c578685013582556020948501946001909201910161403c565b5086821015614097577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006140bc604083018661377d565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b60006020828403121561411f57600080fd5b8151610f5e81613c19565b600060a0823603121561413c57600080fd5b60405160a0810167ffffffffffffffff828210818311171561416057614160613b4e565b81604052843591508082111561417557600080fd5b5061418236828601613dfc565b82525061419160208401613721565b602082015260408301356141a4816137f3565b60408201526060838101359082015260808301356141c1816137f3565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261422f57600080fd5b9190910192915050565b6000610140823603121561424c57600080fd5b614254613ba7565b61425d83613721565b815261426b60208401613c27565b6020820152604083013567ffffffffffffffff8082111561428b57600080fd5b61429736838701613dfc565b604084015260608501359150808211156142b057600080fd5b506142bd36828601613dfc565b6060830152506142d03660808501613c52565b60808201526142e23660e08501613c52565b60a082015292915050565b815167ffffffffffffffff81111561430757614307613b4e565b61431b816143158454613d4a565b84613f47565b602080601f83116001811461436e57600084156143385750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610b86565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156143bb5788860151825594840194600190910190840161439c565b50858210156143f757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261442b8184018761377d565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506144699050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613aa9565b60a0815260006144b360a083018761377d565b73ffffffffffffffffffffffffffffffffffffffff8616602084015284604084015267ffffffffffffffff841660608401528281036080840152600081526020810191505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8516815260a06020820152600061453060a083018661377d565b60408301949094525067ffffffffffffffff9190911660608201528082036080909101526000815260200192915050565b60006020828403121561457357600080fd5b815167ffffffffffffffff81111561458a57600080fd5b8201601f8101841361459b57600080fd5b80516145a9613e1b82613db6565b8181528560208385010111156145be57600080fd5b613aa9826020830160208601613759565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106cb576106cb6145cf565b67ffffffffffffffff8416815260e0810161465d60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612dd6565b606081016106cb82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156146e257600080fd5b8151610f5e816137f3565b80820281158282048414176106cb576106cb6145cf565b808201808211156106cb576106cb6145cf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261477c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000825161422f81846020870161375956fe4c6f636b52656c65617365546f6b656e506f6f6c416e6450726f787920312e352e30a164736f6c6343000818000a", } var LockReleaseTokenPoolAndProxyABI = LockReleaseTokenPoolAndProxyMetaData.ABI @@ -354,6 +354,28 @@ func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyCallerSession) return _LockReleaseTokenPoolAndProxy.Contract.GetOnRamp(&_LockReleaseTokenPoolAndProxy.CallOpts, arg0) } +func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyCaller) GetPreviousPool(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _LockReleaseTokenPoolAndProxy.contract.Call(opts, &out, "getPreviousPool") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxySession) GetPreviousPool() (common.Address, error) { + return _LockReleaseTokenPoolAndProxy.Contract.GetPreviousPool(&_LockReleaseTokenPoolAndProxy.CallOpts) +} + +func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyCallerSession) GetPreviousPool() (common.Address, error) { + return _LockReleaseTokenPoolAndProxy.Contract.GetPreviousPool(&_LockReleaseTokenPoolAndProxy.CallOpts) +} + func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _LockReleaseTokenPoolAndProxy.contract.Call(opts, &out, "getRateLimitAdmin") @@ -806,6 +828,18 @@ func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyTransactorSessi return _LockReleaseTokenPoolAndProxy.Contract.SetRouter(&_LockReleaseTokenPoolAndProxy.TransactOpts, newRouter) } +func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyTransactor) TransferLiquidity(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) { + return _LockReleaseTokenPoolAndProxy.contract.Transact(opts, "transferLiquidity", from, amount) +} + +func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxySession) TransferLiquidity(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _LockReleaseTokenPoolAndProxy.Contract.TransferLiquidity(&_LockReleaseTokenPoolAndProxy.TransactOpts, from, amount) +} + +func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyTransactorSession) TransferLiquidity(from common.Address, amount *big.Int) (*types.Transaction, error) { + return _LockReleaseTokenPoolAndProxy.Contract.TransferLiquidity(&_LockReleaseTokenPoolAndProxy.TransactOpts, from, amount) +} + func (_LockReleaseTokenPoolAndProxy *LockReleaseTokenPoolAndProxyTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _LockReleaseTokenPoolAndProxy.contract.Transact(opts, "transferOwnership", to) } @@ -3226,6 +3260,8 @@ type LockReleaseTokenPoolAndProxyInterface interface { GetOnRamp(opts *bind.CallOpts, arg0 uint64) (common.Address, error) + GetPreviousPool(opts *bind.CallOpts) (common.Address, error) + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) GetRebalancer(opts *bind.CallOpts) (common.Address, error) @@ -3278,6 +3314,8 @@ type LockReleaseTokenPoolAndProxyInterface interface { SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) + TransferLiquidity(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) WithdrawLiquidity(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 52434b50493..5b482517191 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -43,7 +43,23 @@ type InternalAny2EVMRampMessage struct { Data []byte Receiver common.Address GasLimit *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalAny2EVMTokenTransfer +} + +type InternalAny2EVMTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress common.Address + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int +} + +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte } type InternalRampMessageHeader struct { @@ -54,16 +70,9 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int -} - 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\":\"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\":\"implicitMetadataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"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\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"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\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"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\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"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: "0x608060405234801561001057600080fd5b50610de7806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd1461019e578063c7ca9a18146101f5578063e733d2091461020857600080fd5b8063a91d3aeb14610150578063b17df7141461016357600080fd5b8063902e94a0146100a85780639511afaa146100d157806399df8d05146100f2578063a1e747df1461013d575b600080fd5b6100bb6100b63660046107d9565b61021b565b6040516100c8919061087a565b60405180910390f35b6100e46100df366004610958565b610244565b6040519081526020016100c8565b6100bb610100366004610a62565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100bb61014b366004610a9d565b610257565b6100bb61015e366004610b05565b610289565b61018f610171366004610b86565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100c8565b6101d86101ac366004610baf565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100c8565b6100bb610203366004610bdb565b6102c1565b6100bb610216366004610c2f565b6102d2565b60608160405160200161022e9190610c71565b6040516020818303038152906040529050919050565b600061025083836102dd565b9392505050565b6060848484846040516020016102709493929190610d3d565b6040516020818303038152906040529050949350505050565b60608686868686866040516020016102a696959493929190610d7a565b60405160208183030381529060405290509695505050505050565b60606102cc8261043a565b92915050565b60606102cc826104fc565b815160208082015160409283015192516000938493610323937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610d3d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761038a9794969395929491939101610d7a565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016103c19190610c71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c90000000000000000000000000000000000000000000000000000000090604401610479565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561058557610585610533565b60405290565b60405160c0810167ffffffffffffffff8111828210171561058557610585610533565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156105f5576105f5610533565b604052919050565b600082601f83011261060e57600080fd5b813567ffffffffffffffff81111561062857610628610533565b61065960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016105ae565b81815284602083860101111561066e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261069c57600080fd5b8135602067ffffffffffffffff808311156106b9576106b9610533565b8260051b6106c88382016105ae565b93845285810183019383810190888611156106e257600080fd5b84880192505b858310156107cd578235848111156107005760008081fd5b88016080818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018113156107365760008081fd5b61073e610562565b87830135878111156107505760008081fd5b61075e8d8a838701016105fd565b825250604080840135888111156107755760008081fd5b6107838e8b838801016105fd565b8a840152506060808501358981111561079c5760008081fd5b6107aa8f8c838901016105fd565b9284019290925293909201359281019290925250825291840191908401906106e8565b98975050505050505050565b6000602082840312156107eb57600080fd5b813567ffffffffffffffff81111561080257600080fd5b61080e8482850161068b565b949350505050565b6000815180845260005b8181101561083c57602081850181015186830182015201610820565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006102506020830184610816565b803567ffffffffffffffff811681146108a557600080fd5b919050565b600060a082840312156108bc57600080fd5b60405160a0810181811067ffffffffffffffff821117156108df576108df610533565b604052823581529050806108f56020840161088d565b60208201526109066040840161088d565b60408201526109176060840161088d565b60608201526109286080840161088d565b60808201525092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108a557600080fd5b6000806040838503121561096b57600080fd5b823567ffffffffffffffff8082111561098357600080fd5b90840190610140828703121561099857600080fd5b6109a061058b565b6109aa87846108aa565b815260a0830135828111156109be57600080fd5b6109ca888286016105fd565b60208301525060c0830135828111156109e257600080fd5b6109ee888286016105fd565b604083015250610a0060e08401610934565b6060820152610100830135608082015261012083013582811115610a2357600080fd5b610a2f8882860161068b565b60a08301525093506020850135915080821115610a4b57600080fd5b50610a58858286016105fd565b9150509250929050565b600080600080600060a08688031215610a7a57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610ab357600080fd5b84359350610ac36020860161088d565b9250610ad16040860161088d565b9150606085013567ffffffffffffffff811115610aed57600080fd5b610af9878288016105fd565b91505092959194509250565b60008060008060008060c08789031215610b1e57600080fd5b86359550602087013567ffffffffffffffff811115610b3c57600080fd5b610b4889828a016105fd565b955050610b5760408801610934565b9350610b656060880161088d565b925060808701359150610b7a60a0880161088d565b90509295509295509295565b600060208284031215610b9857600080fd5b5035919050565b803580151581146108a557600080fd5b60008060408385031215610bc257600080fd5b82359150610bd260208401610b9f565b90509250929050565b600060408284031215610bed57600080fd5b6040516040810181811067ffffffffffffffff82111715610c1057610c10610533565b60405282358152610c2360208401610b9f565b60208201529392505050565b600060208284031215610c4157600080fd5b6040516020810181811067ffffffffffffffff82111715610c6457610c64610533565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610d2f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160808151818652610cde82870182610816565b915050888201518582038a870152610cf68282610816565b9150508782015185820389870152610d0e8282610816565b60609384015196909301959095525094870194925090860190600101610c9a565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610d706080830184610816565b9695505050505050565b86815260c060208201526000610d9360c0830188610816565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", + 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", } var MessageHasherABI = MessageHasherMetaData.ABI @@ -246,9 +255,9 @@ func (_MessageHasher *MessageHasherCallerSession) DecodeEVMExtraArgsV2(gasLimit return _MessageHasher.Contract.DecodeEVMExtraArgsV2(&_MessageHasher.CallOpts, gasLimit, allowOutOfOrderExecution) } -func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV1(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV1) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeAny2EVMTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeEVMExtraArgsV1", extraArgs) + err := _MessageHasher.contract.Call(opts, &out, "encodeAny2EVMTokenAmountsHashPreimage", tokenAmounts) if err != nil { return *new([]byte), err @@ -260,17 +269,17 @@ func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV1(opts *bind.CallO } -func (_MessageHasher *MessageHasherSession) EncodeEVMExtraArgsV1(extraArgs ClientEVMExtraArgsV1) ([]byte, error) { - return _MessageHasher.Contract.EncodeEVMExtraArgsV1(&_MessageHasher.CallOpts, extraArgs) +func (_MessageHasher *MessageHasherSession) EncodeAny2EVMTokenAmountsHashPreimage(tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeAny2EVMTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmounts) } -func (_MessageHasher *MessageHasherCallerSession) EncodeEVMExtraArgsV1(extraArgs ClientEVMExtraArgsV1) ([]byte, error) { - return _MessageHasher.Contract.EncodeEVMExtraArgsV1(&_MessageHasher.CallOpts, extraArgs) +func (_MessageHasher *MessageHasherCallerSession) EncodeAny2EVMTokenAmountsHashPreimage(tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeAny2EVMTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmounts) } -func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV2(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV2) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeEVM2AnyTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeEVMExtraArgsV2", extraArgs) + err := _MessageHasher.contract.Call(opts, &out, "encodeEVM2AnyTokenAmountsHashPreimage", tokenAmount) if err != nil { return *new([]byte), err @@ -282,17 +291,17 @@ func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV2(opts *bind.CallO } -func (_MessageHasher *MessageHasherSession) EncodeEVMExtraArgsV2(extraArgs ClientEVMExtraArgsV2) ([]byte, error) { - return _MessageHasher.Contract.EncodeEVMExtraArgsV2(&_MessageHasher.CallOpts, extraArgs) +func (_MessageHasher *MessageHasherSession) EncodeEVM2AnyTokenAmountsHashPreimage(tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVM2AnyTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmount) } -func (_MessageHasher *MessageHasherCallerSession) EncodeEVMExtraArgsV2(extraArgs ClientEVMExtraArgsV2) ([]byte, error) { - return _MessageHasher.Contract.EncodeEVMExtraArgsV2(&_MessageHasher.CallOpts, extraArgs) +func (_MessageHasher *MessageHasherCallerSession) EncodeEVM2AnyTokenAmountsHashPreimage(tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVM2AnyTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmount) } -func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV1(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV1) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeFinalHashPreimage", leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) + err := _MessageHasher.contract.Call(opts, &out, "encodeEVMExtraArgsV1", extraArgs) if err != nil { return *new([]byte), err @@ -304,17 +313,17 @@ func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.Ca } -func (_MessageHasher *MessageHasherSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) +func (_MessageHasher *MessageHasherSession) EncodeEVMExtraArgsV1(extraArgs ClientEVMExtraArgsV1) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV1(&_MessageHasher.CallOpts, extraArgs) } -func (_MessageHasher *MessageHasherCallerSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) +func (_MessageHasher *MessageHasherCallerSession) EncodeEVMExtraArgsV1(extraArgs ClientEVMExtraArgsV1) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV1(&_MessageHasher.CallOpts, extraArgs) } -func (_MessageHasher *MessageHasherCaller) EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV2(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV2) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeFixedSizeFieldsHashPreimage", messageId, sender, receiver, sequenceNumber, gasLimit, nonce) + err := _MessageHasher.contract.Call(opts, &out, "encodeEVMExtraArgsV2", extraArgs) if err != nil { return *new([]byte), err @@ -326,17 +335,17 @@ func (_MessageHasher *MessageHasherCaller) EncodeFixedSizeFieldsHashPreimage(opt } -func (_MessageHasher *MessageHasherSession) EncodeFixedSizeFieldsHashPreimage(messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { - return _MessageHasher.Contract.EncodeFixedSizeFieldsHashPreimage(&_MessageHasher.CallOpts, messageId, sender, receiver, sequenceNumber, gasLimit, nonce) +func (_MessageHasher *MessageHasherSession) EncodeEVMExtraArgsV2(extraArgs ClientEVMExtraArgsV2) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV2(&_MessageHasher.CallOpts, extraArgs) } -func (_MessageHasher *MessageHasherCallerSession) EncodeFixedSizeFieldsHashPreimage(messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { - return _MessageHasher.Contract.EncodeFixedSizeFieldsHashPreimage(&_MessageHasher.CallOpts, messageId, sender, receiver, sequenceNumber, gasLimit, nonce) +func (_MessageHasher *MessageHasherCallerSession) EncodeEVMExtraArgsV2(extraArgs ClientEVMExtraArgsV2) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV2(&_MessageHasher.CallOpts, extraArgs) } -func (_MessageHasher *MessageHasherCaller) EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, metaDataHash [32]byte, fixedSizeFieldsHash [32]byte, senderHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeMetadataHashPreimage", any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) + err := _MessageHasher.contract.Call(opts, &out, "encodeFinalHashPreimage", leafDomainSeparator, metaDataHash, fixedSizeFieldsHash, senderHash, dataHash, tokenAmountsHash) if err != nil { return *new([]byte), err @@ -348,17 +357,17 @@ func (_MessageHasher *MessageHasherCaller) EncodeMetadataHashPreimage(opts *bind } -func (_MessageHasher *MessageHasherSession) EncodeMetadataHashPreimage(any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) +func (_MessageHasher *MessageHasherSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, metaDataHash [32]byte, fixedSizeFieldsHash [32]byte, senderHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, metaDataHash, fixedSizeFieldsHash, senderHash, dataHash, tokenAmountsHash) } -func (_MessageHasher *MessageHasherCallerSession) EncodeMetadataHashPreimage(any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) +func (_MessageHasher *MessageHasherCallerSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, metaDataHash [32]byte, fixedSizeFieldsHash [32]byte, senderHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, metaDataHash, fixedSizeFieldsHash, senderHash, dataHash, tokenAmountsHash) } -func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage", rampTokenAmounts) + err := _MessageHasher.contract.Call(opts, &out, "encodeFixedSizeFieldsHashPreimage", messageId, receiver, sequenceNumber, gasLimit, nonce) if err != nil { return *new([]byte), err @@ -370,12 +379,34 @@ func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts * } -func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage(rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { - return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, rampTokenAmounts) +func (_MessageHasher *MessageHasherSession) EncodeFixedSizeFieldsHashPreimage(messageId [32]byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { + return _MessageHasher.Contract.EncodeFixedSizeFieldsHashPreimage(&_MessageHasher.CallOpts, messageId, receiver, sequenceNumber, gasLimit, nonce) } -func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage(rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { - return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, rampTokenAmounts) +func (_MessageHasher *MessageHasherCallerSession) EncodeFixedSizeFieldsHashPreimage(messageId [32]byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { + return _MessageHasher.Contract.EncodeFixedSizeFieldsHashPreimage(&_MessageHasher.CallOpts, messageId, receiver, sequenceNumber, gasLimit, nonce) +} + +func (_MessageHasher *MessageHasherCaller) EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRampHash [32]byte) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeMetadataHashPreimage", any2EVMMessageHash, sourceChainSelector, destChainSelector, onRampHash) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeMetadataHashPreimage(any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRampHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRampHash) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeMetadataHashPreimage(any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRampHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRampHash) } func (_MessageHasher *MessageHasherCaller) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) { @@ -409,17 +440,19 @@ type MessageHasherInterface interface { DecodeEVMExtraArgsV2(opts *bind.CallOpts, gasLimit *big.Int, allowOutOfOrderExecution bool) (ClientEVMExtraArgsV2, error) + EncodeAny2EVMTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) + + EncodeEVM2AnyTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) + EncodeEVMExtraArgsV1(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV1) ([]byte, error) EncodeEVMExtraArgsV2(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV2) ([]byte, error) - EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) - - EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) + EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, metaDataHash [32]byte, fixedSizeFieldsHash [32]byte, senderHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) - EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) + EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) - EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) + EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRampHash [32]byte) ([]byte, error) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) diff --git a/core/gethwrappers/ccip/generated/mock_arm_contract/mock_arm_contract.go b/core/gethwrappers/ccip/generated/mock_rmn_contract/mock_rmn_contract.go similarity index 68% rename from core/gethwrappers/ccip/generated/mock_arm_contract/mock_arm_contract.go rename to core/gethwrappers/ccip/generated/mock_rmn_contract/mock_rmn_contract.go index fff63bef801..21aa223e75d 100644 --- a/core/gethwrappers/ccip/generated/mock_arm_contract/mock_arm_contract.go +++ b/core/gethwrappers/ccip/generated/mock_rmn_contract/mock_rmn_contract.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package mock_arm_contract +package mock_rmn_contract import ( "errors" @@ -55,17 +55,17 @@ type RMNVoter struct { CurseWeight uint8 } -var MockARMContractMetaData = &bind.MetaData{ +var MockRMNContractMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"CustomError\",\"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\":\"getConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"blessVoteAddr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curseUnvoteAddr\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"blessWeight\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"curseWeight\",\"type\":\"uint8\"}],\"internalType\":\"structRMN.Voter[]\",\"name\":\"voters\",\"type\":\"tuple[]\"},{\"internalType\":\"uint16\",\"name\":\"blessWeightThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"curseWeightThreshold\",\"type\":\"uint16\"}],\"internalType\":\"structRMN.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\":\"\",\"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\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"cursesHash\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"forceUnvote\",\"type\":\"bool\"}],\"internalType\":\"structRMN.UnvoteToCurseRecord[]\",\"name\":\"\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"ownerUnvoteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"cursesHash\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"forceUnvote\",\"type\":\"bool\"}],\"internalType\":\"structRMN.UnvoteToCurseRecord[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"ownerUnvoteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"setRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"voteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"voteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610ed7806101576000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063618af128116100815780637a7c27491161005b5780637a7c2749146102b55780638da5cb5b146102c8578063f2fde38b146102f057600080fd5b8063618af1281461020a578063794860871461024357806379ba5097146102ad57600080fd5b8063397796f7116100b2578063397796f7146101ba5780633f42ab73146101c25780634d616771146101d957600080fd5b8063119a3527146100d9578063257174dc1461012b5780632cbc26bb14610192575b600080fd5b6101296100e73660046107fe565b50600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b005b6101296101393660046109db565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550565b6101a56101a0366004610a29565b610303565b60405190151581526020015b60405180910390f35b6101a56103b7565b6101ca610424565b6040516101b193929190610a4b565b6101a56101e7366004610b1e565b5060015474010000000000000000000000000000000000000000900460ff161590565b610129610218366004610b36565b50600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b610129610251366004610b73565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550565b610129610565565b6101296102c3366004610b96565b610662565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b1565b6101296102fe366004610c49565b610672565b60006002805461031290610c64565b1590506103575760026040517f5a4ff67100000000000000000000000000000000000000000000000000000000815260040161034e9190610cb1565b60405180910390fd5b60015474010000000000000000000000000000000000000000900460ff16806103b157507fffffffffffffffffffffffffffffffff00000000000000000000000000000000821660009081526006602052604090205460ff165b92915050565b6000600280546103c690610c64565b1590506104025760026040517f5a4ff67100000000000000000000000000000000000000000000000000000000815260040161034e9190610cb1565b5060015474010000000000000000000000000000000000000000900460ff1690565b6040805160608082018352815260006020820181905291810182905281906005546040805160038054608060208202840181019094526060830181815263ffffffff8087169664010000000090041694929392849284929184919060009085015b828210156105315760008481526020908190206040805160a08101825260038602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001808301548216858701526002909201549081169284019290925260ff74010000000000000000000000000000000000000000830481166060850152750100000000000000000000000000000000000000000090920490911660808301529083529092019101610485565b505050908252506001919091015461ffff808216602084015262010000909104166040909101529296919550919350915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161034e565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600261066e8282610db0565b5050565b61067a610686565b61068381610709565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610707576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161034e565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161034e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020828403121561081057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561086957610869610817565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156108b6576108b6610817565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108e257600080fd5b919050565b600082601f8301126108f857600080fd5b8135602067ffffffffffffffff82111561091457610914610817565b610922818360051b0161086f565b8281526060928302850182019282820191908785111561094157600080fd5b8387015b8581101561099e5781818a03121561095d5760008081fd5b610965610846565b61096e826108be565b81528582013586820152604080830135801515811461098d5760008081fd5b908201528452928401928101610945565b5090979650505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146108e257600080fd5b600080604083850312156109ee57600080fd5b823567ffffffffffffffff811115610a0557600080fd5b610a11858286016108e7565b925050610a20602084016109ab565b90509250929050565b600060208284031215610a3b57600080fd5b610a44826109ab565b9392505050565b63ffffffff84811682528316602080830191909152606060408084018290528451848301839052805160c0860181905260009491820190859060e08801905b80831015610af1578351805173ffffffffffffffffffffffffffffffffffffffff9081168452868201518116878501528782015116878401528781015160ff908116898501526080918201511690830152928401926001929092019160a090910190610a8a565b509288015161ffff908116608089015260409098015190971660a090960195909552979650505050505050565b600060408284031215610b3057600080fd5b50919050565b600060208284031215610b4857600080fd5b813567ffffffffffffffff811115610b5f57600080fd5b610b6b848285016108e7565b949350505050565b60008060408385031215610b8657600080fd5b82359150610a20602084016109ab565b60006020808385031215610ba957600080fd5b823567ffffffffffffffff80821115610bc157600080fd5b818501915085601f830112610bd557600080fd5b813581811115610be757610be7610817565b610c17847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161086f565b91508082528684828501011115610c2d57600080fd5b8084840185840137600090820190930192909252509392505050565b600060208284031215610c5b57600080fd5b610a44826108be565b600181811c90821680610c7857607f821691505b602082108103610b30577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454610cc581610c64565b8060208701526040600180841660008114610ce75760018114610d2157610d51565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550610d51565b89600052602060002060005b85811015610d485781548b8201860152908301908801610d2d565b8a016040019650505b509398975050505050505050565b601f821115610dab576000816000526020600020601f850160051c81016020861015610d885750805b601f850160051c820191505b81811015610da757828155600101610d94565b5050505b505050565b815167ffffffffffffffff811115610dca57610dca610817565b610dde81610dd88454610c64565b84610d5f565b602080601f831160018114610e315760008415610dfb5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610da7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610e7e57888601518255948401946001909101908401610e5f565b5085821015610eba57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } -var MockARMContractABI = MockARMContractMetaData.ABI +var MockRMNContractABI = MockRMNContractMetaData.ABI -var MockARMContractBin = MockARMContractMetaData.Bin +var MockRMNContractBin = MockRMNContractMetaData.Bin -func DeployMockARMContract(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *MockARMContract, error) { - parsed, err := MockARMContractMetaData.GetAbi() +func DeployMockRMNContract(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *MockRMNContract, error) { + parsed, err := MockRMNContractMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -73,134 +73,134 @@ func DeployMockARMContract(auth *bind.TransactOpts, backend bind.ContractBackend return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MockARMContractBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MockRMNContractBin), backend) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &MockARMContract{address: address, abi: *parsed, MockARMContractCaller: MockARMContractCaller{contract: contract}, MockARMContractTransactor: MockARMContractTransactor{contract: contract}, MockARMContractFilterer: MockARMContractFilterer{contract: contract}}, nil + return address, tx, &MockRMNContract{address: address, abi: *parsed, MockRMNContractCaller: MockRMNContractCaller{contract: contract}, MockRMNContractTransactor: MockRMNContractTransactor{contract: contract}, MockRMNContractFilterer: MockRMNContractFilterer{contract: contract}}, nil } -type MockARMContract struct { +type MockRMNContract struct { address common.Address abi abi.ABI - MockARMContractCaller - MockARMContractTransactor - MockARMContractFilterer + MockRMNContractCaller + MockRMNContractTransactor + MockRMNContractFilterer } -type MockARMContractCaller struct { +type MockRMNContractCaller struct { contract *bind.BoundContract } -type MockARMContractTransactor struct { +type MockRMNContractTransactor struct { contract *bind.BoundContract } -type MockARMContractFilterer struct { +type MockRMNContractFilterer struct { contract *bind.BoundContract } -type MockARMContractSession struct { - Contract *MockARMContract +type MockRMNContractSession struct { + Contract *MockRMNContract CallOpts bind.CallOpts TransactOpts bind.TransactOpts } -type MockARMContractCallerSession struct { - Contract *MockARMContractCaller +type MockRMNContractCallerSession struct { + Contract *MockRMNContractCaller CallOpts bind.CallOpts } -type MockARMContractTransactorSession struct { - Contract *MockARMContractTransactor +type MockRMNContractTransactorSession struct { + Contract *MockRMNContractTransactor TransactOpts bind.TransactOpts } -type MockARMContractRaw struct { - Contract *MockARMContract +type MockRMNContractRaw struct { + Contract *MockRMNContract } -type MockARMContractCallerRaw struct { - Contract *MockARMContractCaller +type MockRMNContractCallerRaw struct { + Contract *MockRMNContractCaller } -type MockARMContractTransactorRaw struct { - Contract *MockARMContractTransactor +type MockRMNContractTransactorRaw struct { + Contract *MockRMNContractTransactor } -func NewMockARMContract(address common.Address, backend bind.ContractBackend) (*MockARMContract, error) { - abi, err := abi.JSON(strings.NewReader(MockARMContractABI)) +func NewMockRMNContract(address common.Address, backend bind.ContractBackend) (*MockRMNContract, error) { + abi, err := abi.JSON(strings.NewReader(MockRMNContractABI)) if err != nil { return nil, err } - contract, err := bindMockARMContract(address, backend, backend, backend) + contract, err := bindMockRMNContract(address, backend, backend, backend) if err != nil { return nil, err } - return &MockARMContract{address: address, abi: abi, MockARMContractCaller: MockARMContractCaller{contract: contract}, MockARMContractTransactor: MockARMContractTransactor{contract: contract}, MockARMContractFilterer: MockARMContractFilterer{contract: contract}}, nil + return &MockRMNContract{address: address, abi: abi, MockRMNContractCaller: MockRMNContractCaller{contract: contract}, MockRMNContractTransactor: MockRMNContractTransactor{contract: contract}, MockRMNContractFilterer: MockRMNContractFilterer{contract: contract}}, nil } -func NewMockARMContractCaller(address common.Address, caller bind.ContractCaller) (*MockARMContractCaller, error) { - contract, err := bindMockARMContract(address, caller, nil, nil) +func NewMockRMNContractCaller(address common.Address, caller bind.ContractCaller) (*MockRMNContractCaller, error) { + contract, err := bindMockRMNContract(address, caller, nil, nil) if err != nil { return nil, err } - return &MockARMContractCaller{contract: contract}, nil + return &MockRMNContractCaller{contract: contract}, nil } -func NewMockARMContractTransactor(address common.Address, transactor bind.ContractTransactor) (*MockARMContractTransactor, error) { - contract, err := bindMockARMContract(address, nil, transactor, nil) +func NewMockRMNContractTransactor(address common.Address, transactor bind.ContractTransactor) (*MockRMNContractTransactor, error) { + contract, err := bindMockRMNContract(address, nil, transactor, nil) if err != nil { return nil, err } - return &MockARMContractTransactor{contract: contract}, nil + return &MockRMNContractTransactor{contract: contract}, nil } -func NewMockARMContractFilterer(address common.Address, filterer bind.ContractFilterer) (*MockARMContractFilterer, error) { - contract, err := bindMockARMContract(address, nil, nil, filterer) +func NewMockRMNContractFilterer(address common.Address, filterer bind.ContractFilterer) (*MockRMNContractFilterer, error) { + contract, err := bindMockRMNContract(address, nil, nil, filterer) if err != nil { return nil, err } - return &MockARMContractFilterer{contract: contract}, nil + return &MockRMNContractFilterer{contract: contract}, nil } -func bindMockARMContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := MockARMContractMetaData.GetAbi() +func bindMockRMNContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := MockRMNContractMetaData.GetAbi() if err != nil { return nil, err } return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -func (_MockARMContract *MockARMContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _MockARMContract.Contract.MockARMContractCaller.contract.Call(opts, result, method, params...) +func (_MockRMNContract *MockRMNContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockRMNContract.Contract.MockRMNContractCaller.contract.Call(opts, result, method, params...) } -func (_MockARMContract *MockARMContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _MockARMContract.Contract.MockARMContractTransactor.contract.Transfer(opts) +func (_MockRMNContract *MockRMNContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockRMNContract.Contract.MockRMNContractTransactor.contract.Transfer(opts) } -func (_MockARMContract *MockARMContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _MockARMContract.Contract.MockARMContractTransactor.contract.Transact(opts, method, params...) +func (_MockRMNContract *MockRMNContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockRMNContract.Contract.MockRMNContractTransactor.contract.Transact(opts, method, params...) } -func (_MockARMContract *MockARMContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _MockARMContract.Contract.contract.Call(opts, result, method, params...) +func (_MockRMNContract *MockRMNContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockRMNContract.Contract.contract.Call(opts, result, method, params...) } -func (_MockARMContract *MockARMContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _MockARMContract.Contract.contract.Transfer(opts) +func (_MockRMNContract *MockRMNContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockRMNContract.Contract.contract.Transfer(opts) } -func (_MockARMContract *MockARMContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _MockARMContract.Contract.contract.Transact(opts, method, params...) +func (_MockRMNContract *MockRMNContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockRMNContract.Contract.contract.Transact(opts, method, params...) } -func (_MockARMContract *MockARMContractCaller) GetConfigDetails(opts *bind.CallOpts) (GetConfigDetails, +func (_MockRMNContract *MockRMNContractCaller) GetConfigDetails(opts *bind.CallOpts) (GetConfigDetails, error) { var out []interface{} - err := _MockARMContract.contract.Call(opts, &out, "getConfigDetails") + err := _MockRMNContract.contract.Call(opts, &out, "getConfigDetails") outstruct := new(GetConfigDetails) if err != nil { @@ -215,21 +215,21 @@ func (_MockARMContract *MockARMContractCaller) GetConfigDetails(opts *bind.CallO } -func (_MockARMContract *MockARMContractSession) GetConfigDetails() (GetConfigDetails, +func (_MockRMNContract *MockRMNContractSession) GetConfigDetails() (GetConfigDetails, error) { - return _MockARMContract.Contract.GetConfigDetails(&_MockARMContract.CallOpts) + return _MockRMNContract.Contract.GetConfigDetails(&_MockRMNContract.CallOpts) } -func (_MockARMContract *MockARMContractCallerSession) GetConfigDetails() (GetConfigDetails, +func (_MockRMNContract *MockRMNContractCallerSession) GetConfigDetails() (GetConfigDetails, error) { - return _MockARMContract.Contract.GetConfigDetails(&_MockARMContract.CallOpts) + return _MockRMNContract.Contract.GetConfigDetails(&_MockRMNContract.CallOpts) } -func (_MockARMContract *MockARMContractCaller) IsBlessed(opts *bind.CallOpts, arg0 IRMNTaggedRoot) (bool, error) { +func (_MockRMNContract *MockRMNContractCaller) IsBlessed(opts *bind.CallOpts, arg0 IRMNTaggedRoot) (bool, error) { var out []interface{} - err := _MockARMContract.contract.Call(opts, &out, "isBlessed", arg0) + err := _MockRMNContract.contract.Call(opts, &out, "isBlessed", arg0) if err != nil { return *new(bool), err @@ -241,17 +241,17 @@ func (_MockARMContract *MockARMContractCaller) IsBlessed(opts *bind.CallOpts, ar } -func (_MockARMContract *MockARMContractSession) IsBlessed(arg0 IRMNTaggedRoot) (bool, error) { - return _MockARMContract.Contract.IsBlessed(&_MockARMContract.CallOpts, arg0) +func (_MockRMNContract *MockRMNContractSession) IsBlessed(arg0 IRMNTaggedRoot) (bool, error) { + return _MockRMNContract.Contract.IsBlessed(&_MockRMNContract.CallOpts, arg0) } -func (_MockARMContract *MockARMContractCallerSession) IsBlessed(arg0 IRMNTaggedRoot) (bool, error) { - return _MockARMContract.Contract.IsBlessed(&_MockARMContract.CallOpts, arg0) +func (_MockRMNContract *MockRMNContractCallerSession) IsBlessed(arg0 IRMNTaggedRoot) (bool, error) { + return _MockRMNContract.Contract.IsBlessed(&_MockRMNContract.CallOpts, arg0) } -func (_MockARMContract *MockARMContractCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { +func (_MockRMNContract *MockRMNContractCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { var out []interface{} - err := _MockARMContract.contract.Call(opts, &out, "isCursed", subject) + err := _MockRMNContract.contract.Call(opts, &out, "isCursed", subject) if err != nil { return *new(bool), err @@ -263,17 +263,17 @@ func (_MockARMContract *MockARMContractCaller) IsCursed(opts *bind.CallOpts, sub } -func (_MockARMContract *MockARMContractSession) IsCursed(subject [16]byte) (bool, error) { - return _MockARMContract.Contract.IsCursed(&_MockARMContract.CallOpts, subject) +func (_MockRMNContract *MockRMNContractSession) IsCursed(subject [16]byte) (bool, error) { + return _MockRMNContract.Contract.IsCursed(&_MockRMNContract.CallOpts, subject) } -func (_MockARMContract *MockARMContractCallerSession) IsCursed(subject [16]byte) (bool, error) { - return _MockARMContract.Contract.IsCursed(&_MockARMContract.CallOpts, subject) +func (_MockRMNContract *MockRMNContractCallerSession) IsCursed(subject [16]byte) (bool, error) { + return _MockRMNContract.Contract.IsCursed(&_MockRMNContract.CallOpts, subject) } -func (_MockARMContract *MockARMContractCaller) IsCursed0(opts *bind.CallOpts) (bool, error) { +func (_MockRMNContract *MockRMNContractCaller) IsCursed0(opts *bind.CallOpts) (bool, error) { var out []interface{} - err := _MockARMContract.contract.Call(opts, &out, "isCursed0") + err := _MockRMNContract.contract.Call(opts, &out, "isCursed0") if err != nil { return *new(bool), err @@ -285,17 +285,17 @@ func (_MockARMContract *MockARMContractCaller) IsCursed0(opts *bind.CallOpts) (b } -func (_MockARMContract *MockARMContractSession) IsCursed0() (bool, error) { - return _MockARMContract.Contract.IsCursed0(&_MockARMContract.CallOpts) +func (_MockRMNContract *MockRMNContractSession) IsCursed0() (bool, error) { + return _MockRMNContract.Contract.IsCursed0(&_MockRMNContract.CallOpts) } -func (_MockARMContract *MockARMContractCallerSession) IsCursed0() (bool, error) { - return _MockARMContract.Contract.IsCursed0(&_MockARMContract.CallOpts) +func (_MockRMNContract *MockRMNContractCallerSession) IsCursed0() (bool, error) { + return _MockRMNContract.Contract.IsCursed0(&_MockRMNContract.CallOpts) } -func (_MockARMContract *MockARMContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { +func (_MockRMNContract *MockRMNContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _MockARMContract.contract.Call(opts, &out, "owner") + err := _MockRMNContract.contract.Call(opts, &out, "owner") if err != nil { return *new(common.Address), err @@ -307,100 +307,100 @@ func (_MockARMContract *MockARMContractCaller) Owner(opts *bind.CallOpts) (commo } -func (_MockARMContract *MockARMContractSession) Owner() (common.Address, error) { - return _MockARMContract.Contract.Owner(&_MockARMContract.CallOpts) +func (_MockRMNContract *MockRMNContractSession) Owner() (common.Address, error) { + return _MockRMNContract.Contract.Owner(&_MockRMNContract.CallOpts) } -func (_MockARMContract *MockARMContractCallerSession) Owner() (common.Address, error) { - return _MockARMContract.Contract.Owner(&_MockARMContract.CallOpts) +func (_MockRMNContract *MockRMNContractCallerSession) Owner() (common.Address, error) { + return _MockRMNContract.Contract.Owner(&_MockRMNContract.CallOpts) } -func (_MockARMContract *MockARMContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "acceptOwnership") +func (_MockRMNContract *MockRMNContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "acceptOwnership") } -func (_MockARMContract *MockARMContractSession) AcceptOwnership() (*types.Transaction, error) { - return _MockARMContract.Contract.AcceptOwnership(&_MockARMContract.TransactOpts) +func (_MockRMNContract *MockRMNContractSession) AcceptOwnership() (*types.Transaction, error) { + return _MockRMNContract.Contract.AcceptOwnership(&_MockRMNContract.TransactOpts) } -func (_MockARMContract *MockARMContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _MockARMContract.Contract.AcceptOwnership(&_MockARMContract.TransactOpts) +func (_MockRMNContract *MockRMNContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _MockRMNContract.Contract.AcceptOwnership(&_MockRMNContract.TransactOpts) } -func (_MockARMContract *MockARMContractTransactor) OwnerUnvoteToCurse(opts *bind.TransactOpts, arg0 []RMNUnvoteToCurseRecord, subject [16]byte) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "ownerUnvoteToCurse", arg0, subject) +func (_MockRMNContract *MockRMNContractTransactor) OwnerUnvoteToCurse(opts *bind.TransactOpts, arg0 []RMNUnvoteToCurseRecord, subject [16]byte) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "ownerUnvoteToCurse", arg0, subject) } -func (_MockARMContract *MockARMContractSession) OwnerUnvoteToCurse(arg0 []RMNUnvoteToCurseRecord, subject [16]byte) (*types.Transaction, error) { - return _MockARMContract.Contract.OwnerUnvoteToCurse(&_MockARMContract.TransactOpts, arg0, subject) +func (_MockRMNContract *MockRMNContractSession) OwnerUnvoteToCurse(arg0 []RMNUnvoteToCurseRecord, subject [16]byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.OwnerUnvoteToCurse(&_MockRMNContract.TransactOpts, arg0, subject) } -func (_MockARMContract *MockARMContractTransactorSession) OwnerUnvoteToCurse(arg0 []RMNUnvoteToCurseRecord, subject [16]byte) (*types.Transaction, error) { - return _MockARMContract.Contract.OwnerUnvoteToCurse(&_MockARMContract.TransactOpts, arg0, subject) +func (_MockRMNContract *MockRMNContractTransactorSession) OwnerUnvoteToCurse(arg0 []RMNUnvoteToCurseRecord, subject [16]byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.OwnerUnvoteToCurse(&_MockRMNContract.TransactOpts, arg0, subject) } -func (_MockARMContract *MockARMContractTransactor) OwnerUnvoteToCurse0(opts *bind.TransactOpts, arg0 []RMNUnvoteToCurseRecord) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "ownerUnvoteToCurse0", arg0) +func (_MockRMNContract *MockRMNContractTransactor) OwnerUnvoteToCurse0(opts *bind.TransactOpts, arg0 []RMNUnvoteToCurseRecord) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "ownerUnvoteToCurse0", arg0) } -func (_MockARMContract *MockARMContractSession) OwnerUnvoteToCurse0(arg0 []RMNUnvoteToCurseRecord) (*types.Transaction, error) { - return _MockARMContract.Contract.OwnerUnvoteToCurse0(&_MockARMContract.TransactOpts, arg0) +func (_MockRMNContract *MockRMNContractSession) OwnerUnvoteToCurse0(arg0 []RMNUnvoteToCurseRecord) (*types.Transaction, error) { + return _MockRMNContract.Contract.OwnerUnvoteToCurse0(&_MockRMNContract.TransactOpts, arg0) } -func (_MockARMContract *MockARMContractTransactorSession) OwnerUnvoteToCurse0(arg0 []RMNUnvoteToCurseRecord) (*types.Transaction, error) { - return _MockARMContract.Contract.OwnerUnvoteToCurse0(&_MockARMContract.TransactOpts, arg0) +func (_MockRMNContract *MockRMNContractTransactorSession) OwnerUnvoteToCurse0(arg0 []RMNUnvoteToCurseRecord) (*types.Transaction, error) { + return _MockRMNContract.Contract.OwnerUnvoteToCurse0(&_MockRMNContract.TransactOpts, arg0) } -func (_MockARMContract *MockARMContractTransactor) SetRevert(opts *bind.TransactOpts, err []byte) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "setRevert", err) +func (_MockRMNContract *MockRMNContractTransactor) SetRevert(opts *bind.TransactOpts, err []byte) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "setRevert", err) } -func (_MockARMContract *MockARMContractSession) SetRevert(err []byte) (*types.Transaction, error) { - return _MockARMContract.Contract.SetRevert(&_MockARMContract.TransactOpts, err) +func (_MockRMNContract *MockRMNContractSession) SetRevert(err []byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.SetRevert(&_MockRMNContract.TransactOpts, err) } -func (_MockARMContract *MockARMContractTransactorSession) SetRevert(err []byte) (*types.Transaction, error) { - return _MockARMContract.Contract.SetRevert(&_MockARMContract.TransactOpts, err) +func (_MockRMNContract *MockRMNContractTransactorSession) SetRevert(err []byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.SetRevert(&_MockRMNContract.TransactOpts, err) } -func (_MockARMContract *MockARMContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "transferOwnership", to) +func (_MockRMNContract *MockRMNContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "transferOwnership", to) } -func (_MockARMContract *MockARMContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _MockARMContract.Contract.TransferOwnership(&_MockARMContract.TransactOpts, to) +func (_MockRMNContract *MockRMNContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _MockRMNContract.Contract.TransferOwnership(&_MockRMNContract.TransactOpts, to) } -func (_MockARMContract *MockARMContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _MockARMContract.Contract.TransferOwnership(&_MockARMContract.TransactOpts, to) +func (_MockRMNContract *MockRMNContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _MockRMNContract.Contract.TransferOwnership(&_MockRMNContract.TransactOpts, to) } -func (_MockARMContract *MockARMContractTransactor) VoteToCurse(opts *bind.TransactOpts, arg0 [32]byte) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "voteToCurse", arg0) +func (_MockRMNContract *MockRMNContractTransactor) VoteToCurse(opts *bind.TransactOpts, arg0 [32]byte) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "voteToCurse", arg0) } -func (_MockARMContract *MockARMContractSession) VoteToCurse(arg0 [32]byte) (*types.Transaction, error) { - return _MockARMContract.Contract.VoteToCurse(&_MockARMContract.TransactOpts, arg0) +func (_MockRMNContract *MockRMNContractSession) VoteToCurse(arg0 [32]byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.VoteToCurse(&_MockRMNContract.TransactOpts, arg0) } -func (_MockARMContract *MockARMContractTransactorSession) VoteToCurse(arg0 [32]byte) (*types.Transaction, error) { - return _MockARMContract.Contract.VoteToCurse(&_MockARMContract.TransactOpts, arg0) +func (_MockRMNContract *MockRMNContractTransactorSession) VoteToCurse(arg0 [32]byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.VoteToCurse(&_MockRMNContract.TransactOpts, arg0) } -func (_MockARMContract *MockARMContractTransactor) VoteToCurse0(opts *bind.TransactOpts, arg0 [32]byte, subject [16]byte) (*types.Transaction, error) { - return _MockARMContract.contract.Transact(opts, "voteToCurse0", arg0, subject) +func (_MockRMNContract *MockRMNContractTransactor) VoteToCurse0(opts *bind.TransactOpts, arg0 [32]byte, subject [16]byte) (*types.Transaction, error) { + return _MockRMNContract.contract.Transact(opts, "voteToCurse0", arg0, subject) } -func (_MockARMContract *MockARMContractSession) VoteToCurse0(arg0 [32]byte, subject [16]byte) (*types.Transaction, error) { - return _MockARMContract.Contract.VoteToCurse0(&_MockARMContract.TransactOpts, arg0, subject) +func (_MockRMNContract *MockRMNContractSession) VoteToCurse0(arg0 [32]byte, subject [16]byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.VoteToCurse0(&_MockRMNContract.TransactOpts, arg0, subject) } -func (_MockARMContract *MockARMContractTransactorSession) VoteToCurse0(arg0 [32]byte, subject [16]byte) (*types.Transaction, error) { - return _MockARMContract.Contract.VoteToCurse0(&_MockARMContract.TransactOpts, arg0, subject) +func (_MockRMNContract *MockRMNContractTransactorSession) VoteToCurse0(arg0 [32]byte, subject [16]byte) (*types.Transaction, error) { + return _MockRMNContract.Contract.VoteToCurse0(&_MockRMNContract.TransactOpts, arg0, subject) } -type MockARMContractOwnershipTransferRequestedIterator struct { - Event *MockARMContractOwnershipTransferRequested +type MockRMNContractOwnershipTransferRequestedIterator struct { + Event *MockRMNContractOwnershipTransferRequested contract *bind.BoundContract event string @@ -411,7 +411,7 @@ type MockARMContractOwnershipTransferRequestedIterator struct { fail error } -func (it *MockARMContractOwnershipTransferRequestedIterator) Next() bool { +func (it *MockRMNContractOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -420,7 +420,7 @@ func (it *MockARMContractOwnershipTransferRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(MockARMContractOwnershipTransferRequested) + it.Event = new(MockRMNContractOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -435,7 +435,7 @@ func (it *MockARMContractOwnershipTransferRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(MockARMContractOwnershipTransferRequested) + it.Event = new(MockRMNContractOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -450,22 +450,22 @@ func (it *MockARMContractOwnershipTransferRequestedIterator) Next() bool { } } -func (it *MockARMContractOwnershipTransferRequestedIterator) Error() error { +func (it *MockRMNContractOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *MockARMContractOwnershipTransferRequestedIterator) Close() error { +func (it *MockRMNContractOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type MockARMContractOwnershipTransferRequested struct { +type MockRMNContractOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_MockARMContract *MockARMContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockARMContractOwnershipTransferRequestedIterator, error) { +func (_MockRMNContract *MockRMNContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockRMNContractOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -476,14 +476,14 @@ func (_MockARMContract *MockARMContractFilterer) FilterOwnershipTransferRequeste toRule = append(toRule, toItem) } - logs, sub, err := _MockARMContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _MockRMNContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &MockARMContractOwnershipTransferRequestedIterator{contract: _MockARMContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &MockRMNContractOwnershipTransferRequestedIterator{contract: _MockRMNContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MockARMContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_MockRMNContract *MockRMNContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MockRMNContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -494,7 +494,7 @@ func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferRequested toRule = append(toRule, toItem) } - logs, sub, err := _MockARMContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _MockRMNContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -504,8 +504,8 @@ func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferRequested select { case log := <-logs: - event := new(MockARMContractOwnershipTransferRequested) - if err := _MockARMContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(MockRMNContractOwnershipTransferRequested) + if err := _MockRMNContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -526,17 +526,17 @@ func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferRequested }), nil } -func (_MockARMContract *MockARMContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*MockARMContractOwnershipTransferRequested, error) { - event := new(MockARMContractOwnershipTransferRequested) - if err := _MockARMContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_MockRMNContract *MockRMNContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*MockRMNContractOwnershipTransferRequested, error) { + event := new(MockRMNContractOwnershipTransferRequested) + if err := _MockRMNContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type MockARMContractOwnershipTransferredIterator struct { - Event *MockARMContractOwnershipTransferred +type MockRMNContractOwnershipTransferredIterator struct { + Event *MockRMNContractOwnershipTransferred contract *bind.BoundContract event string @@ -547,7 +547,7 @@ type MockARMContractOwnershipTransferredIterator struct { fail error } -func (it *MockARMContractOwnershipTransferredIterator) Next() bool { +func (it *MockRMNContractOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -556,7 +556,7 @@ func (it *MockARMContractOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(MockARMContractOwnershipTransferred) + it.Event = new(MockRMNContractOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -571,7 +571,7 @@ func (it *MockARMContractOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(MockARMContractOwnershipTransferred) + it.Event = new(MockRMNContractOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -586,22 +586,22 @@ func (it *MockARMContractOwnershipTransferredIterator) Next() bool { } } -func (it *MockARMContractOwnershipTransferredIterator) Error() error { +func (it *MockRMNContractOwnershipTransferredIterator) Error() error { return it.fail } -func (it *MockARMContractOwnershipTransferredIterator) Close() error { +func (it *MockRMNContractOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type MockARMContractOwnershipTransferred struct { +type MockRMNContractOwnershipTransferred struct { From common.Address To common.Address Raw types.Log } -func (_MockARMContract *MockARMContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockARMContractOwnershipTransferredIterator, error) { +func (_MockRMNContract *MockRMNContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockRMNContractOwnershipTransferredIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -612,14 +612,14 @@ func (_MockARMContract *MockARMContractFilterer) FilterOwnershipTransferred(opts toRule = append(toRule, toItem) } - logs, sub, err := _MockARMContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _MockRMNContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &MockARMContractOwnershipTransferredIterator{contract: _MockARMContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &MockRMNContractOwnershipTransferredIterator{contract: _MockRMNContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MockARMContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_MockRMNContract *MockRMNContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MockRMNContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -630,7 +630,7 @@ func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferred(opts toRule = append(toRule, toItem) } - logs, sub, err := _MockARMContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _MockRMNContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -640,8 +640,8 @@ func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferred(opts select { case log := <-logs: - event := new(MockARMContractOwnershipTransferred) - if err := _MockARMContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(MockRMNContractOwnershipTransferred) + if err := _MockRMNContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -662,9 +662,9 @@ func (_MockARMContract *MockARMContractFilterer) WatchOwnershipTransferred(opts }), nil } -func (_MockARMContract *MockARMContractFilterer) ParseOwnershipTransferred(log types.Log) (*MockARMContractOwnershipTransferred, error) { - event := new(MockARMContractOwnershipTransferred) - if err := _MockARMContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_MockRMNContract *MockRMNContractFilterer) ParseOwnershipTransferred(log types.Log) (*MockRMNContractOwnershipTransferred, error) { + event := new(MockRMNContractOwnershipTransferred) + if err := _MockRMNContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log @@ -677,31 +677,31 @@ type GetConfigDetails struct { Config RMNConfig } -func (_MockARMContract *MockARMContract) ParseLog(log types.Log) (generated.AbigenLog, error) { +func (_MockRMNContract *MockRMNContract) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _MockARMContract.abi.Events["OwnershipTransferRequested"].ID: - return _MockARMContract.ParseOwnershipTransferRequested(log) - case _MockARMContract.abi.Events["OwnershipTransferred"].ID: - return _MockARMContract.ParseOwnershipTransferred(log) + case _MockRMNContract.abi.Events["OwnershipTransferRequested"].ID: + return _MockRMNContract.ParseOwnershipTransferRequested(log) + case _MockRMNContract.abi.Events["OwnershipTransferred"].ID: + return _MockRMNContract.ParseOwnershipTransferred(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (MockARMContractOwnershipTransferRequested) Topic() common.Hash { +func (MockRMNContractOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } -func (MockARMContractOwnershipTransferred) Topic() common.Hash { +func (MockRMNContractOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (_MockARMContract *MockARMContract) Address() common.Address { - return _MockARMContract.address +func (_MockRMNContract *MockRMNContract) Address() common.Address { + return _MockRMNContract.address } -type MockARMContractInterface interface { +type MockRMNContractInterface interface { GetConfigDetails(opts *bind.CallOpts) (GetConfigDetails, error) @@ -728,17 +728,17 @@ type MockARMContractInterface interface { VoteToCurse0(opts *bind.TransactOpts, arg0 [32]byte, subject [16]byte) (*types.Transaction, error) - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockARMContractOwnershipTransferRequestedIterator, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockRMNContractOwnershipTransferRequestedIterator, error) - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MockARMContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MockRMNContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferRequested(log types.Log) (*MockARMContractOwnershipTransferRequested, error) + ParseOwnershipTransferRequested(log types.Log) (*MockRMNContractOwnershipTransferRequested, error) - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockARMContractOwnershipTransferredIterator, error) + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MockRMNContractOwnershipTransferredIterator, error) - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MockARMContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MockRMNContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferred(log types.Log) (*MockARMContractOwnershipTransferred, error) + ParseOwnershipTransferred(log types.Log) (*MockRMNContractOwnershipTransferred, error) ParseLog(log types.Log) (generated.AbigenLog, error) 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 cdd66b76cbe..4d095a97da2 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 @@ -32,7 +32,7 @@ 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: "0x60e060405234801561001057600080fd5b5060405161083c38038061083c83398101604081905261002f91610063565b63ffffffff909116608052600080546001600160401b03191660011790556001600160a01b031660a081905260c0526100b2565b6000806040838503121561007657600080fd5b825163ffffffff8116811461008a57600080fd5b60208401519092506001600160a01b03811681146100a757600080fd5b809150509250929050565b60805160a05160c0516107486100f460003960008181610129015281816104aa015261056a01526000607901526000818160fa01526102d801526107486000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063a250c66a11610050578063a250c66a14610124578063f856ddb61461014b578063fb8406a91461015e57600080fd5b80632c121921146100775780637eccf63e146100c35780639cdbb181146100f0575b600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6000546100d79067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100ba565b60405163ffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ba565b6100997f000000000000000000000000000000000000000000000000000000000000000081565b6100d76101593660046105ad565b610193565b6101857f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f681565b6040519081526020016100ba565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810186905260009073ffffffffffffffffffffffffffffffffffffffff8416906323b872dd906064016020604051808303816000875af115801561020f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102339190610621565b506040517f42966c680000000000000000000000000000000000000000000000000000000081526004810187905273ffffffffffffffffffffffffffffffffffffffff8416906342966c6890602401600060405180830381600087803b15801561029c57600080fd5b505af11580156102b0573d6000803e3d6000fd5b50506040517fffffffff000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060e01b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b16602482015260388101879052605881018990523360788201526000925060980190506040516020818303038152906040529050610386867f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f68584610466565b600080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169182179055604080518981526020810188905263ffffffff8916918101919091527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f6606082015260808101859052339173ffffffffffffffffffffffffffffffffffffffff8716917f2fa9ca894982930190727e75500a97d8dc500233a5065e0f3126c48fbe0343c09060a00160405180910390a4505060005467ffffffffffffffff1695945050505050565b60008261052d576040517f0ba469bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690630ba469bc906104e3908890889087906004016106ae565b6020604051808303816000875af1158015610502573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052691906106dc565b90506105a5565b6040517ff7259a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f7259a75906104e3908890889088908890600401610706565b949350505050565b600080600080600060a086880312156105c557600080fd5b85359450602086013563ffffffff811681146105e057600080fd5b935060408601359250606086013573ffffffffffffffffffffffffffffffffffffffff8116811461061057600080fd5b949793965091946080013592915050565b60006020828403121561063357600080fd5b8151801515811461064357600080fd5b9392505050565b6000815180845260005b8181101561067057602081850181015186830182015201610654565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b63ffffffff841681528260208201526060604082015260006106d3606083018461064a565b95945050505050565b6000602082840312156106ee57600080fd5b815167ffffffffffffffff8116811461064357600080fd5b63ffffffff85168152836020820152826040820152608060608201526000610731608083018461064a565b969550505050505056fea164736f6c6343000818000a", + Bin: "0x60e060405234801561001057600080fd5b5060405161082d38038061082d83398101604081905261002f91610063565b63ffffffff909116608052600080546001600160401b03191660011790556001600160a01b031660a081905260c0526100b2565b6000806040838503121561007657600080fd5b825163ffffffff8116811461008a57600080fd5b60208401519092506001600160a01b03811681146100a757600080fd5b809150509250929050565b60805160a05160c0516107396100f4600039600081816101290152818161049b015261055b01526000607901526000818160fa01526102b801526107396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063a250c66a11610050578063a250c66a14610124578063f856ddb61461014b578063fb8406a91461015e57600080fd5b80632c121921146100775780637eccf63e146100c35780639cdbb181146100f0575b600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6000546100d79067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100ba565b60405163ffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ba565b6100997f000000000000000000000000000000000000000000000000000000000000000081565b6100d761015936600461059e565b610193565b6101857f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f681565b6040519081526020016100ba565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810186905260009073ffffffffffffffffffffffffffffffffffffffff8416906323b872dd906064016020604051808303816000875af115801561020f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102339190610612565b506040517f42966c680000000000000000000000000000000000000000000000000000000081526004810187905273ffffffffffffffffffffffffffffffffffffffff8416906342966c6890602401600060405180830381600087803b15801561029c57600080fd5b505af11580156102b0573d6000803e3d6000fd5b5050604080517f000000000000000000000000000000000000000000000000000000000000000060e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015273ffffffffffffffffffffffffffffffffffffffff8716602482015260448101889052606481018a9052336084808301919091528251808303909101815260a490910190915291506103779050867f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f68584610457565b600080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169182179055604080518981526020810188905263ffffffff8916918101919091527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f6606082015260808101859052339173ffffffffffffffffffffffffffffffffffffffff8716917f2fa9ca894982930190727e75500a97d8dc500233a5065e0f3126c48fbe0343c09060a00160405180910390a4505060005467ffffffffffffffff1695945050505050565b60008261051e576040517f0ba469bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690630ba469bc906104d49088908890879060040161069f565b6020604051808303816000875af11580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051791906106cd565b9050610596565b6040517ff7259a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f7259a75906104d49088908890889088906004016106f7565b949350505050565b600080600080600060a086880312156105b657600080fd5b85359450602086013563ffffffff811681146105d157600080fd5b935060408601359250606086013573ffffffffffffffffffffffffffffffffffffffff8116811461060157600080fd5b949793965091946080013592915050565b60006020828403121561062457600080fd5b8151801515811461063457600080fd5b9392505050565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b63ffffffff841681528260208201526060604082015260006106c4606083018461063b565b95945050505050565b6000602082840312156106df57600080fd5b815167ffffffffffffffff8116811461063457600080fd5b63ffffffff85168152836020820152826040820152608060608201526000610722608083018461063b565b969550505050505056fea164736f6c6343000818000a", } 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 b31a834407b..c3f12bab371 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 @@ -32,7 +32,7 @@ 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: "0x60e060405234801561001057600080fd5b5060405161097b38038061097b83398101604081905261002f91610076565b63ffffffff928316608052911660a0526000805460ff191660011790556001600160a01b031660c0526100ca565b805163ffffffff8116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005d565b92506100a26020850161005d565b60408501519092506001600160a01b03811681146100bf57600080fd5b809150509250925092565b60805160a05160c0516108756101066000396000610256015260008181610140015261046001526000818160c0015261043f01526108756000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638371744e1161005b5780638371744e146101255780638d3638f41461013e5780639e31ddb614610164578063f7259a75146101a557600080fd5b80630ba469bc1461008d57806354fd4d50146100be57806357ecfd28146100f55780637a64293514610118575b600080fd5b6100a061009b366004610552565b6101b8565b60405167ffffffffffffffff90911681526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405163ffffffff90911681526020016100b5565b6101086101033660046105ac565b6101e1565b60405190151581526020016100b5565b6000546101089060ff1681565b6000546100a090610100900467ffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000000006100e0565b6101a361017236600461060c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b005b6100a06101b3366004610635565b6102c2565b600080806101c4610372565b9050336101d688888584868b8b6103d4565b509695505050505050565b6000806101f260546040878961069d565b6101fb916106c7565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815260609190911c60048201819052683635c9adc5dea000006024830152915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561029a57600080fd5b505af11580156102ae573d6000803e3d6000fd5b505060005460ff1698975050505050505050565b600083610356576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f44657374696e6174696f6e2063616c6c6572206d757374206265206e6f6e7a6560448201527f726f00000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610360610372565b9050336101d688888884868a8a6103d4565b60008054610100900467ffffffffffffffff1661039081600161070f565b6000805467ffffffffffffffff92909216610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff909216919091179055919050565b8561043b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f526563697069656e74206d757374206265206e6f6e7a65726f00000000000000604482015260640161034d565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008986888b8b898960405160200161049e9998979695949392919061075e565b60405160208183030381529060405290507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036816040516104de91906107fb565b60405180910390a15050505050505050565b803563ffffffff8116811461050457600080fd5b919050565b60008083601f84011261051b57600080fd5b50813567ffffffffffffffff81111561053357600080fd5b60208301915083602082850101111561054b57600080fd5b9250929050565b6000806000806060858703121561056857600080fd5b610571856104f0565b935060208501359250604085013567ffffffffffffffff81111561059457600080fd5b6105a087828801610509565b95989497509550505050565b600080600080604085870312156105c257600080fd5b843567ffffffffffffffff808211156105da57600080fd5b6105e688838901610509565b909650945060208701359150808211156105ff57600080fd5b506105a087828801610509565b60006020828403121561061e57600080fd5b8135801515811461062e57600080fd5b9392505050565b60008060008060006080868803121561064d57600080fd5b610656866104f0565b94506020860135935060408601359250606086013567ffffffffffffffff81111561068057600080fd5b61068c88828901610509565b969995985093965092949392505050565b600080858511156106ad57600080fd5b838611156106ba57600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156107075780818660140360031b1b83161692505b505092915050565b67ffffffffffffffff818116838216019080821115610757577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b60007fffffffff00000000000000000000000000000000000000000000000000000000808c60e01b168352808b60e01b166004840152808a60e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008860c01b16600c83015286601483015285603483015284605483015282846074840137506000910160740190815298975050505050505050565b60006020808352835180602085015260005b818110156108295785810183015185820160400152820161080d565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000818000a", + Bin: "0x60e060405234801561001057600080fd5b5060405161097338038061097383398101604081905261002f91610076565b63ffffffff928316608052911660a0526000805460ff191660011790556001600160a01b031660c0526100ca565b805163ffffffff8116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005d565b92506100a26020850161005d565b60408501519092506001600160a01b03811681146100bf57600080fd5b809150509250925092565b60805160a05160c05161086d610106600039600061024e015260008181610140015261045801526000818160c00152610437015261086d6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638371744e1161005b5780638371744e146101255780638d3638f41461013e5780639e31ddb614610164578063f7259a75146101a557600080fd5b80630ba469bc1461008d57806354fd4d50146100be57806357ecfd28146100f55780637a64293514610118575b600080fd5b6100a061009b36600461054a565b6101b8565b60405167ffffffffffffffff90911681526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405163ffffffff90911681526020016100b5565b6101086101033660046105a4565b6101e1565b60405190151581526020016100b5565b6000546101089060ff1681565b6000546100a090610100900467ffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000000006100e0565b6101a3610172366004610604565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b005b6100a06101b336600461062d565b6102ba565b600080806101c461036a565b9050336101d688888584868b8b6103cc565b509695505050505050565b6000806101f260b860a48789610695565b6101fb916106bf565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815260609190911c6004820181905260016024830152915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561029257600080fd5b505af11580156102a6573d6000803e3d6000fd5b505060005460ff1698975050505050505050565b60008361034e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f44657374696e6174696f6e2063616c6c6572206d757374206265206e6f6e7a6560448201527f726f00000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600061035861036a565b9050336101d688888884868a8a6103cc565b60008054610100900467ffffffffffffffff16610388816001610707565b6000805467ffffffffffffffff92909216610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff909216919091179055919050565b85610433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f526563697069656e74206d757374206265206e6f6e7a65726f000000000000006044820152606401610345565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008986888b8b898960405160200161049699989796959493929190610756565b60405160208183030381529060405290507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036816040516104d691906107f3565b60405180910390a15050505050505050565b803563ffffffff811681146104fc57600080fd5b919050565b60008083601f84011261051357600080fd5b50813567ffffffffffffffff81111561052b57600080fd5b60208301915083602082850101111561054357600080fd5b9250929050565b6000806000806060858703121561056057600080fd5b610569856104e8565b935060208501359250604085013567ffffffffffffffff81111561058c57600080fd5b61059887828801610501565b95989497509550505050565b600080600080604085870312156105ba57600080fd5b843567ffffffffffffffff808211156105d257600080fd5b6105de88838901610501565b909650945060208701359150808211156105f757600080fd5b5061059887828801610501565b60006020828403121561061657600080fd5b8135801515811461062657600080fd5b9392505050565b60008060008060006080868803121561064557600080fd5b61064e866104e8565b94506020860135935060408601359250606086013567ffffffffffffffff81111561067857600080fd5b61068488828901610501565b969995985093965092949392505050565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156106ff5780818660140360031b1b83161692505b505092915050565b67ffffffffffffffff81811683821601908082111561074f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b60007fffffffff00000000000000000000000000000000000000000000000000000000808c60e01b168352808b60e01b166004840152808a60e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008860c01b16600c83015286601483015285603483015284605483015282846074840137506000910160740190815298975050505050505050565b60006020808352835180602085015260005b8181101561082157858101830151858201604001528201610805565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000818000a", } 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 9fca2d1d369..e1942e68dab 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 @@ -63,7 +63,7 @@ type MultiAggregateRateLimiterLocalRateLimitToken struct { type MultiAggregateRateLimiterRateLimitTokenArgs struct { LocalTokenArgs MultiAggregateRateLimiterLocalRateLimitToken - RemoteToken [32]byte + RemoteToken []byte } type MultiAggregateRateLimiterRateLimiterConfigArgs struct { @@ -87,15 +87,15 @@ type RateLimiterTokenBucket struct { } var MultiAggregateRateLimiterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"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\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"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\":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\":\"newPriceRegistry\",\"type\":\"address\"}],\"name\":\"PriceRegistrySet\",\"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\":\"bytes32\",\"name\":\"remoteToken\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"remoteTokens\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPriceRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"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\":\"newPriceRegistry\",\"type\":\"address\"}],\"name\":\"setPriceRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"bytes32\",\"name\":\"remoteToken\",\"type\":\"bytes32\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitTokenArgs[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b5060405162002e2f38038062002e2f833981016040819052620000349162000538565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000102565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001ad565b50620000fa82620002fc565b50506200066f565b336001600160a01b038216036200015c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b81518110156200023d576000828281518110620001d657620001d662000621565b60209081029190910101519050620001f060028262000378565b1562000233576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620001b5565b50815160005b8151811015620002f657600082828151811062000264576200026462000621565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002a2576040516342bcdf7f60e11b815260040160405180910390fd5b620002af60028262000398565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000243565b50505050565b6001600160a01b03811662000324576040516342bcdf7f60e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527fdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df99060200160405180910390a150565b60006200038f836001600160a01b038416620003af565b90505b92915050565b60006200038f836001600160a01b038416620004b3565b60008181526001830160205260408120548015620004a8576000620003d660018362000637565b8554909150600090620003ec9060019062000637565b90508181146200045857600086600001828154811062000410576200041062000621565b906000526020600020015490508087600001848154811062000436576200043662000621565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200046c576200046c62000659565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000392565b600091505062000392565b6000818152600183016020526040812054620004fc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000392565b50600062000392565b80516001600160a01b03811681146200051d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200054c57600080fd5b620005578362000505565b602084810151919350906001600160401b03808211156200057757600080fd5b818601915086601f8301126200058c57600080fd5b815181811115620005a157620005a162000522565b8060051b604051601f19603f83011681018181108582111715620005c957620005c962000522565b604052918252848201925083810185019189831115620005e857600080fd5b938501935b828510156200061157620006018562000505565b84529385019392850192620005ed565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039257634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6127b0806200067f6000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806379ba50971161008c57806391a2749a1161006657806391a2749a14610232578063e0a0e50614610245578063f2fde38b14610258578063fe843cd01461026b57600080fd5b806379ba5097146101f95780637c8b5e9a146102015780638da5cb5b1461021457600080fd5b80632451a627116100bd5780632451a627146101b0578063508ee9de146101c5578063537e304e146101d857600080fd5b806308d450a1146100e45780630a35bcc4146100f95780630d6c107e14610171575b600080fd5b6100f76100f2366004611ef5565b61027e565b005b61010c610107366004611fd5565b61029d565b604051610168919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b60055473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610168565b6101b8610362565b604051610168919061205a565b6100f76101d336600461206d565b610373565b6101eb6101e6366004612088565b610384565b6040516101689291906120a3565b6100f76104e7565b6100f761020f3660046121c4565b6105e9565b60005473ffffffffffffffffffffffffffffffffffffffff1661018b565b6100f76102403660046122f5565b610838565b6100f7610253366004612386565b610849565b6100f761026636600461206d565b6108be565b6100f76102793660046123fb565b6108cf565b610286610c0e565b61029a816020015182608001516000610c53565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526103596102d58484610d2a565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff16151593830193909352600190930154808316606083015292909204166080820152610d5a565b90505b92915050565b606061036e6002610e0c565b905090565b61037b610e20565b61029a81610ea1565b67ffffffffffffffff8116600090815260046020526040812060609182916103ab90610f67565b90508067ffffffffffffffff8111156103c6576103c6611c66565b6040519080825280602002602001820160405280156103ef578160200160208202803683370190505b5092508067ffffffffffffffff81111561040b5761040b611c66565b604051908082528060200260200182016040528015610434578160200160208202803683370190505b50915060005b818110156104e05767ffffffffffffffff8516600090815260046020526040812081906104679084610f72565b915091508186848151811061047e5761047e61252f565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808584815181106104cb576104cb61252f565b6020908102919091010152505060010161043a565b5050915091565b60015473ffffffffffffffffffffffffffffffffffffffff16331461056d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6105f1610e20565b60005b82518110156106cf5760008382815181106106115761061161252f565b602002602001015160200151905060008483815181106106335761063361252f565b6020908102919091018101515167ffffffffffffffff81166000908152600490925260409091209091506106679083610f90565b156106c5576040805167ffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff841660208201527f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed6910160405180910390a15b50506001016105f4565b5060005b81518110156108335760008282815181106106f0576106f061252f565b602002602001015160000151905060008383815181106107125761071261252f565b6020026020010151602001519050600082602001519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610762575081155b15610799576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff811660009081526004602052604090206107bf908385610fb2565b15610824576040805167ffffffffffffffff831681526020810185905273ffffffffffffffffffffffffffffffffffffffff84168183015290517ffd96f5ca8894a9584abba5645131a95480f9340bd5e0046ceff789111ff16c6d9181900360600190a15b505050508060010190506106d3565b505050565b610840610e20565b61029a81610fdd565b610851610c0e565b6108ba82610862604084018461255e565b808060200260200160405190810160405280939291908181526020016000905b828210156108ae5761089f604083028601368190038101906125c6565b81526020019060010190610882565b50505050506001610c53565b5050565b6108c6610e20565b61029a81611169565b6108d7610e20565b60005b81518110156108ba5760008282815181106108f7576108f761252f565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003610951576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160006109628383610d2a565b8054909150700100000000000000000000000000000000900463ffffffff16600003610bb0576040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff421692840192909252875115158385015251811660608301529186015190911660808201528215610ac95767ffffffffffffffff8416600090815260066020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000941515949094029390931790925560608401516080850151908316921690920217600390910155610baa565b67ffffffffffffffff84166000908152600660209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b50610bba565b610bba818561125e565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b978386604051610bf69291906125e2565b60405180910390a250505050508060010190506108da565b610c1960023361140d565b610c51576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610564565b565b6000610c5f8483610d2a565b805490915074010000000000000000000000000000000000000000900460ff1615610d24576000805b8451811015610d0f57610cd3858281518110610ca657610ca661252f565b6020908102919091018101515167ffffffffffffffff89166000908152600490925260409091209061143c565b15610d0757610cfa858281518110610ced57610ced61252f565b602002602001015161145e565b610d049083612655565b91505b600101610c88565b508015610d2257610d228282600061159a565b505b50505050565b67ffffffffffffffff821660009081526006602052604081208215610d5357600201905061035c565b905061035c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610de882606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642610dcc9190612668565b85608001516fffffffffffffffffffffffffffffffff1661191d565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60606000610e1983611945565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610564565b73ffffffffffffffffffffffffffffffffffffffff8116610eee576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df99060200160405180910390a150565b600061035c826119a1565b6000808080610f8186866119ac565b909450925050505b9250929050565b60006103598373ffffffffffffffffffffffffffffffffffffffff84166119d7565b6000610fd58473ffffffffffffffffffffffffffffffffffffffff8516846119f4565b949350505050565b602081015160005b81518110156110785760008282815181106110025761100261252f565b60200260200101519050611020816002611a1190919063ffffffff16565b1561106f5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101610fe5565b50815160005b8151811015610d2457600082828151811061109b5761109b61252f565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361110b576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611116600282611a33565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161107e565b3373ffffffffffffffffffffffffffffffffffffffff8216036111e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610564565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b815460009061128790700100000000000000000000000000000000900463ffffffff1642612668565b9050801561132957600183015483546112cf916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661191d565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461134f916fffffffffffffffffffffffffffffffff9081169116611a55565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061140090849061267b565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610359565b60006103598373ffffffffffffffffffffffffffffffffffffffff8416611a6b565b60055481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa1580156114d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f691906126b7565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660000361156c5782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610564565b6020830151610e19907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690611a77565b825474010000000000000000000000000000000000000000900460ff1615806115c1575081155b156115cb57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061161190700100000000000000000000000000000000900463ffffffff1642612668565b905080156116d15781831115611653576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600186015461168d9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661191d565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156117885773ffffffffffffffffffffffffffffffffffffffff8416611730576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610564565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610564565b8483101561189b5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906117cc9082612668565b6117d6878a612668565b6117e09190612655565b6117ea9190612722565b905073ffffffffffffffffffffffffffffffffffffffff8616611843576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610564565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610564565b6118a58584612668565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600061193c8561192d848661275d565b6119379087612655565b611a55565b95945050505050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561199557602002820191906000526020600020905b815481526020019060010190808311611981575b50505050509050919050565b600061035c82611ab4565b600080806119ba8585611abe565b600081815260029690960160205260409095205494959350505050565b600081815260028301602052604081208190556103598383611aca565b60008281526002840160205260408120829055610fd58484611ad6565b60006103598373ffffffffffffffffffffffffffffffffffffffff8416611ae2565b60006103598373ffffffffffffffffffffffffffffffffffffffff8416611bd5565b6000818310611a645781610359565b5090919050565b60006103598383611c24565b6000670de0b6b3a7640000611aaa837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff861661275d565b6103599190612722565b600061035c825490565b60006103598383611c3c565b60006103598383611ae2565b60006103598383611bd5565b60008181526001830160205260408120548015611bcb576000611b06600183612668565b8554909150600090611b1a90600190612668565b9050818114611b7f576000866000018281548110611b3a57611b3a61252f565b9060005260206000200154905080876000018481548110611b5d57611b5d61252f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611b9057611b90612774565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061035c565b600091505061035c565b6000818152600183016020526040812054611c1c5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561035c565b50600061035c565b60008181526001830160205260408120541515610359565b6000826000018281548110611c5357611c5361252f565b9060005260206000200154905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611cb857611cb8611c66565b60405290565b60405160a0810167ffffffffffffffff81118282101715611cb857611cb8611c66565b6040516060810167ffffffffffffffff81118282101715611cb857611cb8611c66565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d4b57611d4b611c66565b604052919050565b803567ffffffffffffffff81168114611d6b57600080fd5b919050565b600082601f830112611d8157600080fd5b813567ffffffffffffffff811115611d9b57611d9b611c66565b611dcc60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d04565b818152846020838601011115611de157600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115611e1857611e18611c66565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d6b57600080fd5b600060408284031215611e5857600080fd5b611e60611c95565b9050611e6b82611e22565b81526020820135602082015292915050565b600082601f830112611e8e57600080fd5b81356020611ea3611e9e83611dfe565b611d04565b8083825260208201915060208460061b870101935086841115611ec557600080fd5b602086015b84811015611eea57611edc8882611e46565b835291830191604001611eca565b509695505050505050565b600060208284031215611f0757600080fd5b813567ffffffffffffffff80821115611f1f57600080fd5b9083019060a08286031215611f3357600080fd5b611f3b611cbe565b82358152611f4b60208401611d53565b6020820152604083013582811115611f6257600080fd5b611f6e87828601611d70565b604083015250606083013582811115611f8657600080fd5b611f9287828601611d70565b606083015250608083013582811115611faa57600080fd5b611fb687828601611e7d565b60808301525095945050505050565b80358015158114611d6b57600080fd5b60008060408385031215611fe857600080fd5b611ff183611d53565b9150611fff60208401611fc5565b90509250929050565b60008151808452602080850194506020840160005b8381101561204f57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161201d565b509495945050505050565b6020815260006103596020830184612008565b60006020828403121561207f57600080fd5b61035982611e22565b60006020828403121561209a57600080fd5b61035982611d53565b6040815260006120b66040830185612008565b82810360208481019190915284518083528582019282019060005b818110156120ed578451835293830193918301916001016120d1565b5090979650505050505050565b60006040828403121561210c57600080fd5b612114611c95565b905061211f82611d53565b815261212d60208301611e22565b602082015292915050565b600082601f83011261214957600080fd5b81356020612159611e9e83611dfe565b80838252602082019150606060206060860288010194508785111561217d57600080fd5b602087015b858110156120ed5781818a03121561219a5760008081fd5b6121a2611c95565b6121ac8a836120fa565b81526040820135868201528452928401928101612182565b60008060408084860312156121d857600080fd5b833567ffffffffffffffff808211156121f057600080fd5b818601915086601f83011261220457600080fd5b81356020612214611e9e83611dfe565b8083825260208201915060208460061b87010193508a84111561223657600080fd5b6020860195505b8386101561225e5761224f8b876120fa565b8252948601949082019061223d565b9750505050602086013592508083111561227757600080fd5b505061228585828601612138565b9150509250929050565b600082601f8301126122a057600080fd5b813560206122b0611e9e83611dfe565b8083825260208201915060208460051b8701019350868411156122d257600080fd5b602086015b84811015611eea576122e881611e22565b83529183019183016122d7565b60006020828403121561230757600080fd5b813567ffffffffffffffff8082111561231f57600080fd5b908301906040828603121561233357600080fd5b61233b611c95565b82358281111561234a57600080fd5b6123568782860161228f565b82525060208301358281111561236b57600080fd5b6123778782860161228f565b60208301525095945050505050565b6000806040838503121561239957600080fd5b6123a283611d53565b9150602083013567ffffffffffffffff8111156123be57600080fd5b830160a081860312156123d057600080fd5b809150509250929050565b80356fffffffffffffffffffffffffffffffff81168114611d6b57600080fd5b6000602080838503121561240e57600080fd5b823567ffffffffffffffff81111561242557600080fd5b8301601f8101851361243657600080fd5b8035612444611e9e82611dfe565b81815260a0918202830184019184820191908884111561246357600080fd5b938501935b8385101561252357848903818112156124815760008081fd5b612489611ce1565b61249287611d53565b815261249f888801611fc5565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156124d75760008081fd5b6124df611ce1565b93506124ec828a01611fc5565b84526124f9818a016123db565b8a8501525061250a608089016123db565b8382015281019190915283529384019391850191612468565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261259357600080fd5b83018035915067ffffffffffffffff8211156125ae57600080fd5b6020019150600681901b3603821315610f8957600080fd5b6000604082840312156125d857600080fd5b6103598383611e46565b821515815260808101610e1960208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561035c5761035c612626565b8181038181111561035c5761035c612626565b6060810161035c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000604082840312156126c957600080fd5b6126d1611c95565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146126fd57600080fd5b8152602083015163ffffffff8116811461271657600080fd5b60208201529392505050565b600082612758577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761035c5761035c612626565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + 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\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"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: "0x60806040523480156200001157600080fd5b506040516200327338038062003273833981016040819052620000349162000538565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000102565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001ad565b50620000fa82620002fc565b50506200066f565b336001600160a01b038216036200015c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b81518110156200023d576000828281518110620001d657620001d662000621565b60209081029190910101519050620001f060028262000378565b1562000233576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620001b5565b50815160005b8151811015620002f657600082828151811062000264576200026462000621565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002a2576040516342bcdf7f60e11b815260040160405180910390fd5b620002af60028262000398565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000243565b50505050565b6001600160a01b03811662000324576040516342bcdf7f60e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b60006200038f836001600160a01b038416620003af565b90505b92915050565b60006200038f836001600160a01b038416620004b3565b60008181526001830160205260408120548015620004a8576000620003d660018362000637565b8554909150600090620003ec9060019062000637565b90508181146200045857600086600001828154811062000410576200041062000621565b906000526020600020015490508087600001848154811062000436576200043662000621565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200046c576200046c62000659565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000392565b600091505062000392565b6000818152600183016020526040812054620004fc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000392565b50600062000392565b80516001600160a01b03811681146200051d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200054c57600080fd5b620005578362000505565b602084810151919350906001600160401b03808211156200057757600080fd5b818601915086601f8301126200058c57600080fd5b815181811115620005a157620005a162000522565b8060051b604051601f19603f83011681018181108582111715620005c957620005c962000522565b604052918252848201925083810185019189831115620005e857600080fd5b938501935b828510156200061157620006018562000505565b84529385019392850192620005ed565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039257634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b612bf4806200067f6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638da5cb5b1161008c578063e145291611610066578063e145291614610247578063e835232b14610265578063f2fde38b14610278578063fe843cd01461028b57600080fd5b80638da5cb5b146101e257806391a2749a14610221578063e0a0e5061461023457600080fd5b80631af18b7b116100c85780631af18b7b146101915780632451a627146101a4578063537e304e146101b957806379ba5097146101da57600080fd5b806308d450a1146100ef5780630a35bcc414610104578063181f5a771461017c575b600080fd5b6101026100fd366004612003565b61029e565b005b6101176101123660046120e3565b6102bd565b604051610173919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b610184610382565b604051610173919061217a565b61010261019f3660046122b4565b61039e565b6101ac6105ca565b60405161017391906123d1565b6101cc6101c73660046123e4565b6105db565b6040516101739291906123ff565b610102610748565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b61010261022f3660046124f5565b61084a565b610102610242366004612586565b61085b565b60055473ffffffffffffffffffffffffffffffffffffffff166101fc565b6101026102733660046125db565b6108d0565b6101026102863660046125db565b6108e1565b610102610299366004612616565b6108f2565b6102a6610c31565b6102ba816020015182608001516000610c76565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526103796102f58484610d4d565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff16151593830193909352600190930154808316606083015292909204166080820152610d7d565b90505b92915050565b604051806060016040528060238152602001612bc56023913981565b6103a6610e2f565b60005b82518110156104845760008382815181106103c6576103c661274a565b602002602001015160200151905060008483815181106103e8576103e861274a565b6020908102919091018101515167ffffffffffffffff811660009081526004909252604090912090915061041c9083610eb0565b1561047a576040805167ffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff841660208201527f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed6910160405180910390a15b50506001016103a9565b5060005b81518110156105c55760008282815181106104a5576104a561274a565b602002602001015160000151905060008383815181106104c7576104c761274a565b6020026020010151602001519050600082602001519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061051857508151155b1561054f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff81166000908152600460205260409020610575908385610ed2565b156105b6577fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c58184846040516105ad93929190612779565b60405180910390a15b50505050806001019050610488565b505050565b60606105d66002610eff565b905090565b67ffffffffffffffff81166000908152600460205260408120606091829161060290610f0c565b90508067ffffffffffffffff81111561061d5761061d611d74565b604051908082528060200260200182016040528015610646578160200160208202803683370190505b5092508067ffffffffffffffff81111561066257610662611d74565b60405190808252806020026020018201604052801561069557816020015b60608152602001906001900390816106805790505b50915060005b818110156107415767ffffffffffffffff8516600090815260046020526040812081906106c89084610f17565b91509150818684815181106106df576106df61274a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508085848151811061072c5761072c61274a565b6020908102919091010152505060010161069b565b5050915091565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610852610e2f565b6102ba81610f36565b610863610c31565b6108cc8261087460408401846127c2565b808060200260200160405190810160405280939291908181526020016000905b828210156108c0576108b16040830286013681900381019061282a565b81526020019060010190610894565b50505050506001610c76565b5050565b6108d8610e2f565b6102ba816110c2565b6108e9610e2f565b6102ba81611188565b6108fa610e2f565b60005b81518110156108cc57600082828151811061091a5761091a61274a565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003610974576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160006109858383610d4d565b8054909150700100000000000000000000000000000000900463ffffffff16600003610bd3576040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff421692840192909252875115158385015251811660608301529186015190911660808201528215610aec5767ffffffffffffffff8416600090815260066020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000941515949094029390931790925560608401516080850151908316921690920217600390910155610bcd565b67ffffffffffffffff84166000908152600660209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b50610bdd565b610bdd818561127d565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b978386604051610c19929190612846565b60405180910390a250505050508060010190506108fd565b610c3c60023361142c565b610c74576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024016107c5565b565b6000610c828483610d4d565b805490915074010000000000000000000000000000000000000000900460ff1615610d47576000805b8451811015610d3257610cf6858281518110610cc957610cc961274a565b6020908102919091018101515167ffffffffffffffff89166000908152600490925260409091209061145b565b15610d2a57610d1d858281518110610d1057610d1061274a565b602002602001015161147d565b610d2790836128b9565b91505b600101610cab565b508015610d4557610d45828260006115b9565b505b50505050565b67ffffffffffffffff821660009081526006602052604081208215610d7657600201905061037c565b905061037c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610e0b82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642610def91906128cc565b85608001516fffffffffffffffffffffffffffffffff1661193c565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107c5565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611964565b6000610ef58473ffffffffffffffffffffffffffffffffffffffff851684611988565b90505b9392505050565b60606000610ef8836119ad565b600061037c82611a09565b600060608180610f278686611a14565b909450925050505b9250929050565b602081015160005b8151811015610fd1576000828281518110610f5b57610f5b61274a565b60200260200101519050610f79816002611ad190919063ffffffff16565b15610fc85760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101610f3e565b50815160005b8151811015610d47576000828281518110610ff457610ff461274a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611064576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61106f600282611af3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610fd7565b73ffffffffffffffffffffffffffffffffffffffff811661110f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff821603611207576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107c5565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b81546000906112a690700100000000000000000000000000000000900463ffffffff16426128cc565b9050801561134857600183015483546112ee916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661193c565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461136e916fffffffffffffffffffffffffffffffff9081169116611b15565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061141f9084906128df565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610379565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611b2b565b60055481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa1580156114f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611515919061291b565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660000361158b5782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016107c5565b6020830151610ef8907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690611b37565b825474010000000000000000000000000000000000000000900460ff1615806115e0575081155b156115ea57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061163090700100000000000000000000000000000000900463ffffffff16426128cc565b905080156116f05781831115611672576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546116ac9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661193c565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156117a75773ffffffffffffffffffffffffffffffffffffffff841661174f576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016107c5565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016107c5565b848310156118ba5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906117eb90826128cc565b6117f5878a6128cc565b6117ff91906128b9565b6118099190612986565b905073ffffffffffffffffffffffffffffffffffffffff8616611862576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016107c5565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016107c5565b6118c485846128cc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600061195b8561194c84866129c1565b61195690876128b9565b611b15565b95945050505050565b6000818152600283016020526040812061197e9082611d26565b6103798383611b74565b600082815260028401602052604081206119a28382612a7b565b50610ef58484611b80565b6060816000018054806020026020016040519081016040528092919081815260200182805480156119fd57602002820191906000526020600020905b8154815260200190600101908083116119e9575b50505050509050919050565b600061037c82611b8c565b6000606081611a238585611b96565b60008181526002870160205260409020805491925082918190611a45906129d8565b80601f0160208091040260200160405190810160405280929190818152602001828054611a71906129d8565b8015611abe5780601f10611a9357610100808354040283529160200191611abe565b820191906000526020600020905b815481529060010190602001808311611aa157829003601f168201915b5050505050905092509250509250929050565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611ba2565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c95565b6000818310611b245781610379565b5090919050565b60006103798383611ce4565b6000670de0b6b3a7640000611b6a837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166129c1565b6103799190612986565b60006103798383611ba2565b60006103798383611c95565b600061037c825490565b60006103798383611cfc565b60008181526001830160205260408120548015611c8b576000611bc66001836128cc565b8554909150600090611bda906001906128cc565b9050818114611c3f576000866000018281548110611bfa57611bfa61274a565b9060005260206000200154905080876000018481548110611c1d57611c1d61274a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c5057611c50612b95565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061037c565b600091505061037c565b6000818152600183016020526040812054611cdc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037c565b50600061037c565b60008181526001830160205260408120541515610379565b6000826000018281548110611d1357611d1361274a565b9060005260206000200154905092915050565b508054611d32906129d8565b6000825580601f10611d42575050565b601f0160209004906000526020600020908101906102ba91905b80821115611d705760008155600101611d5c565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611dc657611dc6611d74565b60405290565b60405160a0810167ffffffffffffffff81118282101715611dc657611dc6611d74565b6040516060810167ffffffffffffffff81118282101715611dc657611dc6611d74565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e5957611e59611d74565b604052919050565b803567ffffffffffffffff81168114611e7957600080fd5b919050565b600082601f830112611e8f57600080fd5b813567ffffffffffffffff811115611ea957611ea9611d74565b611eda60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611e12565b818152846020838601011115611eef57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115611f2657611f26611d74565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611e7957600080fd5b600060408284031215611f6657600080fd5b611f6e611da3565b9050611f7982611f30565b81526020820135602082015292915050565b600082601f830112611f9c57600080fd5b81356020611fb1611fac83611f0c565b611e12565b8083825260208201915060208460061b870101935086841115611fd357600080fd5b602086015b84811015611ff857611fea8882611f54565b835291830191604001611fd8565b509695505050505050565b60006020828403121561201557600080fd5b813567ffffffffffffffff8082111561202d57600080fd5b9083019060a0828603121561204157600080fd5b612049611dcc565b8235815261205960208401611e61565b602082015260408301358281111561207057600080fd5b61207c87828601611e7e565b60408301525060608301358281111561209457600080fd5b6120a087828601611e7e565b6060830152506080830135828111156120b857600080fd5b6120c487828601611f8b565b60808301525095945050505050565b80358015158114611e7957600080fd5b600080604083850312156120f657600080fd5b6120ff83611e61565b915061210d602084016120d3565b90509250929050565b6000815180845260005b8181101561213c57602081850181015186830182015201612120565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006103796020830184612116565b60006040828403121561219f57600080fd5b6121a7611da3565b90506121b282611e61565b81526121c060208301611f30565b602082015292915050565b600082601f8301126121dc57600080fd5b813560206121ec611fac83611f0c565b82815260059290921b8401810191818101908684111561220b57600080fd5b8286015b84811015611ff857803567ffffffffffffffff808211156122305760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156122695760008081fd5b612271611da3565b61227d8c89860161218d565b81529083013590828211156122925760008081fd5b6122a08c8984870101611e7e565b81890152865250505091830191830161220f565b60008060408084860312156122c857600080fd5b833567ffffffffffffffff808211156122e057600080fd5b818601915086601f8301126122f457600080fd5b81356020612304611fac83611f0c565b8083825260208201915060208460061b87010193508a84111561232657600080fd5b6020860195505b8386101561234e5761233f8b8761218d565b8252948601949082019061232d565b9750505050602086013592508083111561236757600080fd5b5050612375858286016121cb565b9150509250929050565b60008151808452602080850194506020840160005b838110156123c657815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612394565b509495945050505050565b602081526000610379602083018461237f565b6000602082840312156123f657600080fd5b61037982611e61565b604081526000612412604083018561237f565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015612480577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087840301855261246e838351612116565b94860194925090850190600101612434565b50909998505050505050505050565b600082601f8301126124a057600080fd5b813560206124b0611fac83611f0c565b8083825260208201915060208460051b8701019350868411156124d257600080fd5b602086015b84811015611ff8576124e881611f30565b83529183019183016124d7565b60006020828403121561250757600080fd5b813567ffffffffffffffff8082111561251f57600080fd5b908301906040828603121561253357600080fd5b61253b611da3565b82358281111561254a57600080fd5b6125568782860161248f565b82525060208301358281111561256b57600080fd5b6125778782860161248f565b60208301525095945050505050565b6000806040838503121561259957600080fd5b6125a283611e61565b9150602083013567ffffffffffffffff8111156125be57600080fd5b830160a081860312156125d057600080fd5b809150509250929050565b6000602082840312156125ed57600080fd5b61037982611f30565b80356fffffffffffffffffffffffffffffffff81168114611e7957600080fd5b6000602080838503121561262957600080fd5b823567ffffffffffffffff81111561264057600080fd5b8301601f8101851361265157600080fd5b803561265f611fac82611f0c565b81815260a0918202830184019184820191908884111561267e57600080fd5b938501935b8385101561273e578489038181121561269c5760008081fd5b6126a4611def565b6126ad87611e61565b81526126ba8888016120d3565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156126f25760008081fd5b6126fa611def565b9350612707828a016120d3565b8452612714818a016125f6565b8a85015250612725608089016125f6565b8382015281019190915283529384019391850191612683565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8416815260606020820152600061279c6060830185612116565b905073ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126127f757600080fd5b83018035915067ffffffffffffffff82111561281257600080fd5b6020019150600681901b3603821315610f2f57600080fd5b60006040828403121561283c57600080fd5b6103798383611f54565b821515815260808101610ef860208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561037c5761037c61288a565b8181038181111561037c5761037c61288a565b6060810161037c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006040828403121561292d57600080fd5b612935611da3565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461296157600080fd5b8152602083015163ffffffff8116811461297a57600080fd5b60208201529392505050565b6000826129bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761037c5761037c61288a565b600181811c908216806129ec57607f821691505b602082108103612a25577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105c5576000816000526020600020601f850160051c81016020861015612a545750805b601f850160051c820191505b81811015612a7357828155600101612a60565b505050505050565b815167ffffffffffffffff811115612a9557612a95611d74565b612aa981612aa384546129d8565b84612a2b565b602080601f831160018114612afc5760008415612ac65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612a73565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612b4957888601518255948401946001909101908401612b2a565b5085821015612b8557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4d756c7469416767726567617465526174654c696d6974657220312e362e302d646576a164736f6c6343000818000a", } var MultiAggregateRateLimiterABI = MultiAggregateRateLimiterMetaData.ABI var MultiAggregateRateLimiterBin = MultiAggregateRateLimiterMetaData.Bin -func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.ContractBackend, priceRegistry common.Address, authorizedCallers []common.Address) (common.Address, *types.Transaction, *MultiAggregateRateLimiter, error) { +func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.ContractBackend, feeQuoter common.Address, authorizedCallers []common.Address) (common.Address, *types.Transaction, *MultiAggregateRateLimiter, error) { parsed, err := MultiAggregateRateLimiterMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -104,7 +104,7 @@ func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.Contr return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MultiAggregateRateLimiterBin), backend, priceRegistry, authorizedCallers) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MultiAggregateRateLimiterBin), backend, feeQuoter, authorizedCallers) if err != nil { return common.Address{}, nil, nil, err } @@ -283,7 +283,7 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetAllRateLim } outstruct.LocalTokens = *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - outstruct.RemoteTokens = *abi.ConvertType(out[1], new([][32]byte)).(*[][32]byte) + outstruct.RemoteTokens = *abi.ConvertType(out[1], new([][]byte)).(*[][]byte) return *outstruct, err @@ -301,9 +301,9 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetAll return _MultiAggregateRateLimiter.Contract.GetAllRateLimitTokens(&_MultiAggregateRateLimiter.CallOpts, remoteChainSelector) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetPriceRegistry(opts *bind.CallOpts) (common.Address, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetFeeQuoter(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getPriceRegistry") + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getFeeQuoter") if err != nil { return *new(common.Address), err @@ -315,12 +315,12 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetPriceRegis } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetPriceRegistry() (common.Address, error) { - return _MultiAggregateRateLimiter.Contract.GetPriceRegistry(&_MultiAggregateRateLimiter.CallOpts) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetFeeQuoter() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetFeeQuoter(&_MultiAggregateRateLimiter.CallOpts) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetPriceRegistry() (common.Address, error) { - return _MultiAggregateRateLimiter.Contract.GetPriceRegistry(&_MultiAggregateRateLimiter.CallOpts) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetFeeQuoter() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetFeeQuoter(&_MultiAggregateRateLimiter.CallOpts) } func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { @@ -345,6 +345,28 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) Owner( return _MultiAggregateRateLimiter.Contract.Owner(&_MultiAggregateRateLimiter.CallOpts) } +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) TypeAndVersion() (string, error) { + return _MultiAggregateRateLimiter.Contract.TypeAndVersion(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) TypeAndVersion() (string, error) { + return _MultiAggregateRateLimiter.Contract.TypeAndVersion(&_MultiAggregateRateLimiter.CallOpts) +} + func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { return _MultiAggregateRateLimiter.contract.Transact(opts, "acceptOwnership") } @@ -405,16 +427,16 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) On return _MultiAggregateRateLimiter.Contract.OnOutboundMessage(&_MultiAggregateRateLimiter.TransactOpts, destChainSelector, message) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) SetPriceRegistry(opts *bind.TransactOpts, newPriceRegistry common.Address) (*types.Transaction, error) { - return _MultiAggregateRateLimiter.contract.Transact(opts, "setPriceRegistry", newPriceRegistry) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) SetFeeQuoter(opts *bind.TransactOpts, newFeeQuoter common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "setFeeQuoter", newFeeQuoter) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) SetPriceRegistry(newPriceRegistry common.Address) (*types.Transaction, error) { - return _MultiAggregateRateLimiter.Contract.SetPriceRegistry(&_MultiAggregateRateLimiter.TransactOpts, newPriceRegistry) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) SetFeeQuoter(newFeeQuoter common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.SetFeeQuoter(&_MultiAggregateRateLimiter.TransactOpts, newFeeQuoter) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) SetPriceRegistry(newPriceRegistry common.Address) (*types.Transaction, error) { - return _MultiAggregateRateLimiter.Contract.SetPriceRegistry(&_MultiAggregateRateLimiter.TransactOpts, newPriceRegistry) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) SetFeeQuoter(newFeeQuoter common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.SetFeeQuoter(&_MultiAggregateRateLimiter.TransactOpts, newFeeQuoter) } func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { @@ -792,8 +814,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseConfig return event, nil } -type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { - Event *MultiAggregateRateLimiterOwnershipTransferRequested +type MultiAggregateRateLimiterFeeQuoterSetIterator struct { + Event *MultiAggregateRateLimiterFeeQuoterSet contract *bind.BoundContract event string @@ -804,7 +826,7 @@ type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { fail error } -func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bool { +func (it *MultiAggregateRateLimiterFeeQuoterSetIterator) Next() bool { if it.fail != nil { return false @@ -813,7 +835,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bo if it.done { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) + it.Event = new(MultiAggregateRateLimiterFeeQuoterSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -828,7 +850,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bo select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) + it.Event = new(MultiAggregateRateLimiterFeeQuoterSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -843,51 +865,32 @@ func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bo } } -func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Error() error { +func (it *MultiAggregateRateLimiterFeeQuoterSetIterator) Error() error { return it.fail } -func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Close() error { +func (it *MultiAggregateRateLimiterFeeQuoterSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type MultiAggregateRateLimiterOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log +type MultiAggregateRateLimiterFeeQuoterSet struct { + NewFeeQuoter common.Address + Raw types.Log } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterFeeQuoterSet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterFeeQuoterSetIterator, error) { - logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "FeeQuoterSet") if err != nil { return nil, err } - return &MultiAggregateRateLimiterOwnershipTransferRequestedIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &MultiAggregateRateLimiterFeeQuoterSetIterator{contract: _MultiAggregateRateLimiter.contract, event: "FeeQuoterSet", logs: logs, sub: sub}, nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, 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) - } +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchFeeQuoterSet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterFeeQuoterSet) (event.Subscription, error) { - logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "FeeQuoterSet") if err != nil { return nil, err } @@ -897,8 +900,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners select { case log := <-logs: - event := new(MultiAggregateRateLimiterOwnershipTransferRequested) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(MultiAggregateRateLimiterFeeQuoterSet) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "FeeQuoterSet", log); err != nil { return err } event.Raw = log @@ -919,17 +922,17 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners }), nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferRequested(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferRequested, error) { - event := new(MultiAggregateRateLimiterOwnershipTransferRequested) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseFeeQuoterSet(log types.Log) (*MultiAggregateRateLimiterFeeQuoterSet, error) { + event := new(MultiAggregateRateLimiterFeeQuoterSet) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "FeeQuoterSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type MultiAggregateRateLimiterOwnershipTransferredIterator struct { - Event *MultiAggregateRateLimiterOwnershipTransferred +type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { + Event *MultiAggregateRateLimiterOwnershipTransferRequested contract *bind.BoundContract event string @@ -940,7 +943,7 @@ type MultiAggregateRateLimiterOwnershipTransferredIterator struct { fail error } -func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -949,7 +952,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -964,7 +967,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -979,22 +982,22 @@ func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { } } -func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Error() error { +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Close() error { +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type MultiAggregateRateLimiterOwnershipTransferred struct { +type MultiAggregateRateLimiterOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferredIterator, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1005,14 +1008,14 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwner toRule = append(toRule, toItem) } - logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &MultiAggregateRateLimiterOwnershipTransferredIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &MultiAggregateRateLimiterOwnershipTransferRequestedIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1023,7 +1026,7 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners toRule = append(toRule, toItem) } - logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -1033,8 +1036,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners select { case log := <-logs: - event := new(MultiAggregateRateLimiterOwnershipTransferred) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(MultiAggregateRateLimiterOwnershipTransferRequested) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -1055,17 +1058,17 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners }), nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) { - event := new(MultiAggregateRateLimiterOwnershipTransferred) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferRequested(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferRequested, error) { + event := new(MultiAggregateRateLimiterOwnershipTransferRequested) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type MultiAggregateRateLimiterPriceRegistrySetIterator struct { - Event *MultiAggregateRateLimiterPriceRegistrySet +type MultiAggregateRateLimiterOwnershipTransferredIterator struct { + Event *MultiAggregateRateLimiterOwnershipTransferred contract *bind.BoundContract event string @@ -1076,7 +1079,7 @@ type MultiAggregateRateLimiterPriceRegistrySetIterator struct { fail error } -func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -1085,7 +1088,7 @@ func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterPriceRegistrySet) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1100,7 +1103,7 @@ func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterPriceRegistrySet) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1115,32 +1118,51 @@ func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { } } -func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Error() error { +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Error() error { return it.fail } -func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Close() error { +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type MultiAggregateRateLimiterPriceRegistrySet struct { - NewPriceRegistry common.Address - Raw types.Log +type MultiAggregateRateLimiterOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterPriceRegistrySet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterPriceRegistrySetIterator, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferredIterator, error) { - logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "PriceRegistrySet") + 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 := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &MultiAggregateRateLimiterPriceRegistrySetIterator{contract: _MultiAggregateRateLimiter.contract, event: "PriceRegistrySet", logs: logs, sub: sub}, nil + return &MultiAggregateRateLimiterOwnershipTransferredIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceRegistrySet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterPriceRegistrySet) (event.Subscription, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferred, 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 := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "PriceRegistrySet") + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -1150,8 +1172,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceR select { case log := <-logs: - event := new(MultiAggregateRateLimiterPriceRegistrySet) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "PriceRegistrySet", log); err != nil { + event := new(MultiAggregateRateLimiterOwnershipTransferred) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -1172,9 +1194,9 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceR }), nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParsePriceRegistrySet(log types.Log) (*MultiAggregateRateLimiterPriceRegistrySet, error) { - event := new(MultiAggregateRateLimiterPriceRegistrySet) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "PriceRegistrySet", log); err != nil { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) { + event := new(MultiAggregateRateLimiterOwnershipTransferred) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log @@ -1372,7 +1394,7 @@ func (it *MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator) Close() type MultiAggregateRateLimiterTokenAggregateRateLimitAdded struct { RemoteChainSelector uint64 - RemoteToken [32]byte + RemoteToken []byte LocalToken common.Address Raw types.Log } @@ -1666,7 +1688,7 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseTokens type GetAllRateLimitTokens struct { LocalTokens []common.Address - RemoteTokens [][32]byte + RemoteTokens [][]byte } func (_MultiAggregateRateLimiter *MultiAggregateRateLimiter) ParseLog(log types.Log) (generated.AbigenLog, error) { @@ -1677,12 +1699,12 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiter) ParseLog(log types. return _MultiAggregateRateLimiter.ParseAuthorizedCallerRemoved(log) case _MultiAggregateRateLimiter.abi.Events["ConfigChanged"].ID: return _MultiAggregateRateLimiter.ParseConfigChanged(log) + case _MultiAggregateRateLimiter.abi.Events["FeeQuoterSet"].ID: + return _MultiAggregateRateLimiter.ParseFeeQuoterSet(log) case _MultiAggregateRateLimiter.abi.Events["OwnershipTransferRequested"].ID: return _MultiAggregateRateLimiter.ParseOwnershipTransferRequested(log) case _MultiAggregateRateLimiter.abi.Events["OwnershipTransferred"].ID: return _MultiAggregateRateLimiter.ParseOwnershipTransferred(log) - case _MultiAggregateRateLimiter.abi.Events["PriceRegistrySet"].ID: - return _MultiAggregateRateLimiter.ParsePriceRegistrySet(log) case _MultiAggregateRateLimiter.abi.Events["RateLimiterConfigUpdated"].ID: return _MultiAggregateRateLimiter.ParseRateLimiterConfigUpdated(log) case _MultiAggregateRateLimiter.abi.Events["TokenAggregateRateLimitAdded"].ID: @@ -1709,6 +1731,10 @@ func (MultiAggregateRateLimiterConfigChanged) Topic() common.Hash { return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") } +func (MultiAggregateRateLimiterFeeQuoterSet) Topic() common.Hash { + return common.HexToHash("0x7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac") +} + func (MultiAggregateRateLimiterOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1717,16 +1743,12 @@ func (MultiAggregateRateLimiterOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (MultiAggregateRateLimiterPriceRegistrySet) Topic() common.Hash { - return common.HexToHash("0xdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df9") -} - func (MultiAggregateRateLimiterRateLimiterConfigUpdated) Topic() common.Hash { return common.HexToHash("0xf14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b97") } func (MultiAggregateRateLimiterTokenAggregateRateLimitAdded) Topic() common.Hash { - return common.HexToHash("0xfd96f5ca8894a9584abba5645131a95480f9340bd5e0046ceff789111ff16c6d") + return common.HexToHash("0xad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c5") } func (MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) Topic() common.Hash { @@ -1750,10 +1772,12 @@ type MultiAggregateRateLimiterInterface interface { error) - GetPriceRegistry(opts *bind.CallOpts) (common.Address, error) + GetFeeQuoter(opts *bind.CallOpts) (common.Address, error) Owner(opts *bind.CallOpts) (common.Address, error) + TypeAndVersion(opts *bind.CallOpts) (string, error) + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) @@ -1764,7 +1788,7 @@ type MultiAggregateRateLimiterInterface interface { OnOutboundMessage(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*types.Transaction, error) - SetPriceRegistry(opts *bind.TransactOpts, newPriceRegistry common.Address) (*types.Transaction, error) + SetFeeQuoter(opts *bind.TransactOpts, newFeeQuoter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -1788,6 +1812,12 @@ type MultiAggregateRateLimiterInterface interface { ParseConfigChanged(log types.Log) (*MultiAggregateRateLimiterConfigChanged, error) + FilterFeeQuoterSet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterFeeQuoterSetIterator, error) + + WatchFeeQuoterSet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterFeeQuoterSet) (event.Subscription, error) + + ParseFeeQuoterSet(log types.Log) (*MultiAggregateRateLimiterFeeQuoterSet, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) @@ -1800,12 +1830,6 @@ type MultiAggregateRateLimiterInterface interface { ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) - FilterPriceRegistrySet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterPriceRegistrySetIterator, error) - - WatchPriceRegistrySet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterPriceRegistrySet) (event.Subscription, error) - - ParsePriceRegistrySet(log types.Log) (*MultiAggregateRateLimiterPriceRegistrySet, error) - FilterRateLimiterConfigUpdated(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator, error) WatchRateLimiterConfigUpdated(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterRateLimiterConfigUpdated, remoteChainSelector []uint64) (event.Subscription, error) 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 d51e398b433..bd0cb8898df 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 @@ -59,7 +59,7 @@ type MultiOCR3BaseOracle struct { var MultiOCR3HelperMetaData = &bind.MetaData{ ABI: "[{\"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\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"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[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\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"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: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611db66200017760003960008181610efc0152610f480152611db66000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e300000000000000060208201529051610102919061153c565b60405180910390f35b61011e610119366004611603565b61020b565b005b61013361012e366004611691565b61023a565b60405161010291906116f3565b61011e61014e366004611766565b6102ca565b61011e61034d565b61011e610169366004611819565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d3366004611819565b61044f565b604051610102919061188d565b61011e6101f3366004611920565b6105c7565b61011e610206366004611a8c565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad6116c4565b60028111156102be576102be6116c4565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611bf5565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611c53565b90508260600151156106c4578451610695906020611c66565b86516106a2906020611c66565b6106ad9060a0611c53565b6106b79190611c53565b6106c19082611c53565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610ef9565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a46116c4565b60028111156107b5576107b56116c4565b90525090506002816020015160028111156107d2576107d26116c4565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611bf5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c7d565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611c96565b604051908190038120610924918b90602001611ca6565b6040516020818303038152906040528051906020012090506109498a82888888610f7a565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a08401518051601f60ff82161115610c675760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b610cda8585600301805480602002602001604051908101604052809291908181526020018280548015610cd057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca5575b50505050506111b2565b856060015115610e4857610d558585600201805480602002602001604051908101604052809291908181526020018280548015610cd05760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca55750505050506111b2565b60808601518051610d6f906002870190602084019061147e565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015610de85760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b6040880151610df8906003611cd4565b60ff168160ff1611610e395760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b610e458783600161124a565b50505b610e548583600261124a565b8151610e69906003860190602085019061147e565b506040868101516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ee0938a939260028b01929190611cf7565b60405180910390a1610ef185611445565b505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b610f82611508565b835160005b81811015610343576000600188868460208110610fa657610fa6611bf5565b610fb391901a601b611c7d565b898581518110610fc557610fc5611bf5565b6020026020010151898681518110610fdf57610fdf611bf5565b60200260200101516040516000815260200160405260405161101d949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561103f573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110cb576110cb6116c4565b60028111156110dc576110dc6116c4565b90525090506001816020015160028111156110f9576110f96116c4565b14611130576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061114757611147611bf5565b602002015115611183576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061119e5761119e611bf5565b911515602090920201525050600101610f87565b60005b81518110156112455760ff8316600090815260036020526040812083519091908490849081106111e7576111e7611bf5565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016111b5565b505050565b60005b82518160ff161015610234576000838260ff168151811061127057611270611bf5565b602002602001015190506000600281111561128d5761128d6116c4565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915290205461010090041660028111156112d9576112d96116c4565b146113135760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b73ffffffffffffffffffffffffffffffffffffffff8116611360576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff168152602001846002811115611386576113866116c4565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561142b5761142b6116c4565b0217905550905050508061143e90611d8a565b905061124d565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114f8579160200282015b828111156114f857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061149e565b50611504929150611527565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b808211156115045760008155600101611528565b60006020808352835180602085015260005b8181101561156a5785810183015185820160400152820161154e565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f8401126115cc57600080fd5b50813567ffffffffffffffff8111156115e457600080fd5b6020830191508360208285010111156115fc57600080fd5b9250929050565b60008060006080848603121561161857600080fd5b61162285856115a9565b9250606084013567ffffffffffffffff81111561163e57600080fd5b61164a868287016115ba565b9497909650939450505050565b803560ff8116811461166857600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461166857600080fd5b600080604083850312156116a457600080fd5b6116ad83611657565b91506116bb6020840161166d565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff1681526020820151604082019060038110611714576117146116c4565b8060208401525092915050565b60008083601f84011261173357600080fd5b50813567ffffffffffffffff81111561174b57600080fd5b6020830191508360208260051b85010111156115fc57600080fd5b60008060008060008060008060e0898b03121561178257600080fd5b61178c8a8a6115a9565b9750606089013567ffffffffffffffff808211156117a957600080fd5b6117b58c838d016115ba565b909950975060808b01359150808211156117ce57600080fd5b6117da8c838d01611721565b909750955060a08b01359150808211156117f357600080fd5b506118008b828c01611721565b999c989b50969995989497949560c00135949350505050565b60006020828403121561182b57600080fd5b61183482611657565b9392505050565b60008151808452602080850194506020840160005b8381101561188257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611850565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526118dc60e084018261183b565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c0850152611917828261183b565b95945050505050565b60006020828403121561193257600080fd5b6118348261166d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561198d5761198d61193b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156119da576119da61193b565b604052919050565b600067ffffffffffffffff8211156119fc576119fc61193b565b5060051b60200190565b8035801515811461166857600080fd5b600082601f830112611a2757600080fd5b81356020611a3c611a37836119e2565b611993565b8083825260208201915060208460051b870101935086841115611a5e57600080fd5b602086015b84811015611a8157611a748161166d565b8352918301918301611a63565b509695505050505050565b60006020808385031215611a9f57600080fd5b823567ffffffffffffffff80821115611ab757600080fd5b818501915085601f830112611acb57600080fd5b8135611ad9611a37826119e2565b81815260059190911b83018401908481019088831115611af857600080fd5b8585015b83811015611be857803585811115611b1357600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611b485760008081fd5b611b5061196a565b8882013581526040611b63818401611657565b8a8301526060611b74818501611657565b8284015260809150611b87828501611a06565b9083015260a08381013589811115611b9f5760008081fd5b611bad8f8d83880101611a16565b838501525060c0840135915088821115611bc75760008081fd5b611bd58e8c84870101611a16565b9083015250845250918601918601611afc565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611c24565b80820281158282048414176102c4576102c4611c24565b60ff81811683821601908111156102c4576102c4611c24565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160058310611cce57611cce6116c4565b91905290565b60ff8181168382160290811690818114611cf057611cf0611c24565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611d5e57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611d2c565b50508481036060860152611d72818861183b565b935050505060ff831660808301529695505050505050565b600060ff821660ff8103611da057611da0611c24565b6001019291505056fea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611db56200017760003960008181610f6d0152610fb90152611db56000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e300000000000000060208201529051610102919061155a565b60405180910390f35b61011e610119366004611621565b61020b565b005b61013361012e3660046116af565b61023a565b6040516101029190611711565b61011e61014e366004611784565b6102ca565b61011e61034d565b61011e610169366004611837565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d3366004611837565b61044f565b60405161010291906118ab565b61011e6101f336600461193e565b6105c7565b61011e610206366004611aaa565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad6116e2565b60028111156102be576102be6116e2565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611c13565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611c71565b90508260600151156106c4578451610695906020611c84565b86516106a2906020611c84565b6106ad9060a0611c71565b6106b79190611c71565b6106c19082611c71565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610f6a565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a46116e2565b60028111156107b5576107b56116e2565b90525090506002816020015160028111156107d2576107d26116e2565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611c13565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c9b565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611cb4565b604051908190038120610924918b90602001611cc4565b6040516020818303038152906040528051906020012090506109498a82888888610feb565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a084015180516101001015610c645760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b8051600003610ca25760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b610d158484600301805480602002602001604051908101604052809291908181526020018280548015610d0b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ce0575b50505050506111fb565b846060015115610eba57610d908484600201805480602002602001604051908101604052809291908181526020018280548015610d0b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ce05750505050506111fb565b608085015180516101001015610dd55760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b6040860151610de5906003611cf2565b60ff16815111610e245760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b815181511015610e635760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610eab90600286019060208401906114bb565b50610eb885826001611293565b505b610ec684826002611293565b8051610edb90600385019060208401906114bb565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610f529389939260028a01929190611d15565b60405180910390a1610f6384611482565b5050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b8251600090815b8181101561034357600060018886846020811061101157611011611c13565b61101e91901a601b611c9b565b89858151811061103057611030611c13565b602002602001015189868151811061104a5761104a611c13565b602002602001015160405160008152602001604052604051611088949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156110aa573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115611136576111366116e2565b6002811115611147576111476116e2565b9052509050600181602001516002811115611164576111646116e2565b1461119b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b8516156111de576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610ff2565b60005b815181101561128e5760ff83166000908152600360205260408120835190919084908490811061123057611230611c13565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016111fe565b505050565b60005b82518110156102345760008382815181106112b3576112b3611c13565b60200260200101519050600060028111156112d0576112d06116e2565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561131c5761131c6116e2565b146113565760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b73ffffffffffffffffffffffffffffffffffffffff81166113a3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156113c9576113c96116e2565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561146e5761146e6116e2565b021790555090505050806001019050611296565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b828054828255906000526020600020908101928215611535579160200282015b8281111561153557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906114db565b50611541929150611545565b5090565b5b808211156115415760008155600101611546565b60006020808352835180602085015260005b818110156115885785810183015185820160400152820161156c565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f8401126115ea57600080fd5b50813567ffffffffffffffff81111561160257600080fd5b60208301915083602082850101111561161a57600080fd5b9250929050565b60008060006080848603121561163657600080fd5b61164085856115c7565b9250606084013567ffffffffffffffff81111561165c57600080fd5b611668868287016115d8565b9497909650939450505050565b803560ff8116811461168657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461168657600080fd5b600080604083850312156116c257600080fd5b6116cb83611675565b91506116d96020840161168b565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff1681526020820151604082019060038110611732576117326116e2565b8060208401525092915050565b60008083601f84011261175157600080fd5b50813567ffffffffffffffff81111561176957600080fd5b6020830191508360208260051b850101111561161a57600080fd5b60008060008060008060008060e0898b0312156117a057600080fd5b6117aa8a8a6115c7565b9750606089013567ffffffffffffffff808211156117c757600080fd5b6117d38c838d016115d8565b909950975060808b01359150808211156117ec57600080fd5b6117f88c838d0161173f565b909750955060a08b013591508082111561181157600080fd5b5061181e8b828c0161173f565b999c989b50969995989497949560c00135949350505050565b60006020828403121561184957600080fd5b61185282611675565b9392505050565b60008151808452602080850194506020840160005b838110156118a057815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161186e565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526118fa60e0840182611859565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526119358282611859565b95945050505050565b60006020828403121561195057600080fd5b6118528261168b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156119ab576119ab611959565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156119f8576119f8611959565b604052919050565b600067ffffffffffffffff821115611a1a57611a1a611959565b5060051b60200190565b8035801515811461168657600080fd5b600082601f830112611a4557600080fd5b81356020611a5a611a5583611a00565b6119b1565b8083825260208201915060208460051b870101935086841115611a7c57600080fd5b602086015b84811015611a9f57611a928161168b565b8352918301918301611a81565b509695505050505050565b60006020808385031215611abd57600080fd5b823567ffffffffffffffff80821115611ad557600080fd5b818501915085601f830112611ae957600080fd5b8135611af7611a5582611a00565b81815260059190911b83018401908481019088831115611b1657600080fd5b8585015b83811015611c0657803585811115611b3157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611b665760008081fd5b611b6e611988565b8882013581526040611b81818401611675565b8a8301526060611b92818501611675565b8284015260809150611ba5828501611a24565b9083015260a08381013589811115611bbd5760008081fd5b611bcb8f8d83880101611a34565b838501525060c0840135915088821115611be55760008081fd5b611bf38e8c84870101611a34565b9083015250845250918601918601611b1a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611c42565b80820281158282048414176102c4576102c4611c42565b60ff81811683821601908111156102c4576102c4611c42565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160068310611cec57611cec6116e2565b91905290565b60ff8181168382160290811690818114611d0e57611d0e611c42565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611d7c57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611d4a565b50508481036060860152611d908188611859565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } 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 14979b4fe30..e87afc6bdac 100644 --- a/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go +++ b/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go @@ -41,13 +41,14 @@ type NonceManagerPreviousRamps struct { } type NonceManagerPreviousRampsArgs struct { - RemoteChainSelector uint64 - PrevRamps NonceManagerPreviousRamps + RemoteChainSelector uint64 + OverrideExistingRamps bool + PrevRamps NonceManagerPreviousRamps } var NonceManagerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\"},{\"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\"}]", - Bin: "0x60806040523480156200001157600080fd5b5060405162001ad538038062001ad58339810160408190526200003491620004b0565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620000f6565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001a1565b5050620005d0565b336001600160a01b03821603620001505760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000231576000828281518110620001ca57620001ca62000582565b60209081029190910101519050620001e4600282620002f0565b1562000227576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620001a9565b50815160005b8151811015620002ea57600082828151811062000258576200025862000582565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000296576040516342bcdf7f60e11b815260040160405180910390fd5b620002a360028262000310565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000237565b50505050565b600062000307836001600160a01b03841662000327565b90505b92915050565b600062000307836001600160a01b0384166200042b565b60008181526001830160205260408120548015620004205760006200034e60018362000598565b8554909150600090620003649060019062000598565b9050818114620003d057600086600001828154811062000388576200038862000582565b9060005260206000200154905080876000018481548110620003ae57620003ae62000582565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620003e457620003e4620005ba565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200030a565b60009150506200030a565b600081815260018301602052604081205462000474575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200030a565b5060006200030a565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b0381168114620004ab57600080fd5b919050565b60006020808385031215620004c457600080fd5b82516001600160401b0380821115620004dc57600080fd5b818501915085601f830112620004f157600080fd5b8151818111156200050657620005066200047d565b8060051b604051601f19603f830116810181811085821117156200052e576200052e6200047d565b6040529182528482019250838101850191888311156200054d57600080fd5b938501935b828510156200057657620005668562000493565b8452938501939285019262000552565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200030a57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6114f580620005e06000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c806391a2749a11610081578063e0e03cae1161005b578063e0e03cae14610228578063ea458c0c1461024b578063f2fde38b1461025e57600080fd5b806391a2749a146101d6578063bf18402a146101e9578063c92236251461021557600080fd5b806379ba5097116100b257806379ba50971461019157806384d8acf71461019b5780638da5cb5b146101ae57600080fd5b80632451a627146100ce578063294b5630146100ec575b600080fd5b6100d6610271565b6040516100e39190610f2e565b60405180910390f35b61015d6100fa366004610f9e565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff9081168452600190910154169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff90811682526020938401511692810192909252016100e3565b610199610282565b005b6101996101a9366004610fbb565b610384565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e3565b6101996101e4366004611146565b610560565b6101fc6101f73660046111ed565b610574565b60405167ffffffffffffffff90911681526020016100e3565b6101fc61022336600461126f565b610589565b61023b6102363660046112c4565b6105a0565b60405190151581526020016100e3565b6101fc6102593660046111ed565b6106a9565b61019961026c366004611329565b61073d565b606061027d600261074e565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610308576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61038c61075b565b60005b8181101561055b57368383838181106103aa576103aa611346565b606002919091019150600090506004816103c76020850185610f9e565b67ffffffffffffffff1681526020810191909152604001600020805490915073ffffffffffffffffffffffffffffffffffffffff161515806104225750600181015473ffffffffffffffffffffffffffffffffffffffff1615155b15610459576040517fc6117ae200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104696040830160208401611329565b81547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff919091161781556104b96060830160408401611329565b6001820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561050d6020830183610f9e565b67ffffffffffffffff167fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c3319836020016040516105499190611375565b60405180910390a2505060010161038f565b505050565b61056861075b565b610571816107de565b50565b60006105808383610970565b90505b92915050565b6000610596848484610a8d565b90505b9392505050565b60006105aa610bde565b60006105b7868585610a8d565b6105c29060016113ec565b90508467ffffffffffffffff168167ffffffffffffffff1614610626577f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f86868686604051610614949392919061140d565b60405180910390a160009150506106a1565b67ffffffffffffffff86166000908152600660205260409081902090518291906106539087908790611479565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550600190505b949350505050565b60006106b3610bde565b60006106bf8484610970565b6106ca9060016113ec565b67ffffffffffffffff808616600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902080549183167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905591505092915050565b61074561075b565b61057181610c21565b6060600061059983610d16565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102ff565b565b602081015160005b815181101561087957600082828151811061080357610803611346565b60200260200101519050610821816002610d7290919063ffffffff16565b156108705760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016107e6565b50815160005b815181101561096a57600082828151811061089c5761089c611346565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361090c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610917600282610d94565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161087f565b50505050565b67ffffffffffffffff808316600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091168082036105805767ffffffffffffffff841660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff168015610a85576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015282169063856c824790602401602060405180830381865afa158015610a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7c9190611489565b92505050610583565b509392505050565b67ffffffffffffffff83166000908152600660205260408082209051829190610ab99086908690611479565b9081526040519081900360200190205467ffffffffffffffff16905060008190036105965767ffffffffffffffff851660009081526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff168015610bd55773ffffffffffffffffffffffffffffffffffffffff811663856c8247610b3f86880188611329565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610ba8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bcc9190611489565b92505050610599565b50949350505050565b610be9600233610db6565b6107dc576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024016102ff565b3373ffffffffffffffffffffffffffffffffffffffff821603610ca0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102ff565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015610d6657602002820191906000526020600020905b815481526020019060010190808311610d52575b50505050509050919050565b60006105808373ffffffffffffffffffffffffffffffffffffffff8416610de5565b60006105808373ffffffffffffffffffffffffffffffffffffffff8416610edf565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610580565b60008181526001830160205260408120548015610ece576000610e096001836114a6565b8554909150600090610e1d906001906114a6565b9050818114610e82576000866000018281548110610e3d57610e3d611346565b9060005260206000200154905080876000018481548110610e6057610e60611346565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e9357610e936114b9565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610583565b6000915050610583565b5092915050565b6000818152600183016020526040812054610f2657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610583565b506000610583565b6020808252825182820181905260009190848201906040850190845b81811015610f7c57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f4a565b50909695505050505050565b67ffffffffffffffff8116811461057157600080fd5b600060208284031215610fb057600080fd5b813561058081610f88565b60008060208385031215610fce57600080fd5b823567ffffffffffffffff80821115610fe657600080fd5b818501915085601f830112610ffa57600080fd5b81358181111561100957600080fd5b86602060608302850101111561101e57600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057157600080fd5b600082601f83011261109257600080fd5b8135602067ffffffffffffffff808311156110af576110af611030565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156110f2576110f2611030565b604052938452602081870181019490810192508785111561111257600080fd5b6020870191505b8482101561113b57813561112c8161105f565b83529183019190830190611119565b979650505050505050565b60006020828403121561115857600080fd5b813567ffffffffffffffff8082111561117057600080fd5b908301906040828603121561118457600080fd5b60405160408101818110838211171561119f5761119f611030565b6040528235828111156111b157600080fd5b6111bd87828601611081565b8252506020830135828111156111d257600080fd5b6111de87828601611081565b60208301525095945050505050565b6000806040838503121561120057600080fd5b823561120b81610f88565b9150602083013561121b8161105f565b809150509250929050565b60008083601f84011261123857600080fd5b50813567ffffffffffffffff81111561125057600080fd5b60208301915083602082850101111561126857600080fd5b9250929050565b60008060006040848603121561128457600080fd5b833561128f81610f88565b9250602084013567ffffffffffffffff8111156112ab57600080fd5b6112b786828701611226565b9497909650939450505050565b600080600080606085870312156112da57600080fd5b84356112e581610f88565b935060208501356112f581610f88565b9250604085013567ffffffffffffffff81111561131157600080fd5b61131d87828801611226565b95989497509550505050565b60006020828403121561133b57600080fd5b81356105808161105f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040810182356113848161105f565b73ffffffffffffffffffffffffffffffffffffffff90811683526020840135906113ad8261105f565b8082166020850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115610ed857610ed86113bd565b600067ffffffffffffffff8087168352808616602084015250606060408301528260608301528284608084013760006080848401015260807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905095945050505050565b8183823760009101908152919050565b60006020828403121561149b57600080fd5b815161058081610f88565b81810381811115610583576105836113bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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: "0x60806040523480156200001157600080fd5b5060405162001bcc38038062001bcc8339810160408190526200003491620004b0565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620000f6565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001a1565b5050620005d0565b336001600160a01b03821603620001505760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000231576000828281518110620001ca57620001ca62000582565b60209081029190910101519050620001e4600282620002f0565b1562000227576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620001a9565b50815160005b8151811015620002ea57600082828151811062000258576200025862000582565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000296576040516342bcdf7f60e11b815260040160405180910390fd5b620002a360028262000310565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000237565b50505050565b600062000307836001600160a01b03841662000327565b90505b92915050565b600062000307836001600160a01b0384166200042b565b60008181526001830160205260408120548015620004205760006200034e60018362000598565b8554909150600090620003649060019062000598565b9050818114620003d057600086600001828154811062000388576200038862000582565b9060005260206000200154905080876000018481548110620003ae57620003ae62000582565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620003e457620003e4620005ba565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200030a565b60009150506200030a565b600081815260018301602052604081205462000474575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200030a565b5060006200030a565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b0381168114620004ab57600080fd5b919050565b60006020808385031215620004c457600080fd5b82516001600160401b0380821115620004dc57600080fd5b818501915085601f830112620004f157600080fd5b8151818111156200050657620005066200047d565b8060051b604051601f19603f830116810181811085821117156200052e576200052e6200047d565b6040529182528482019250838101850191888311156200054d57600080fd5b938501935b828510156200057657620005668562000493565b8452938501939285019262000552565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200030a57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6115ec80620005e06000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806391a2749a11610081578063e0e03cae1161005b578063e0e03cae1461027c578063ea458c0c1461029f578063f2fde38b146102b257600080fd5b806391a2749a1461022a578063bf18402a1461023d578063c92236251461026957600080fd5b806379ba5097116100b257806379ba5097146101e55780637a75a094146101ef5780638da5cb5b1461020257600080fd5b8063181f5a77146100d95780632451a6271461012b578063294b563014610140575b600080fd5b6101156040518060400160405280601681526020017f4e6f6e63654d616e6167657220312e362e302d6465760000000000000000000081525081565b6040516101229190610f96565b60405180910390f35b6101336102c5565b6040516101229190611003565b6101b161014e366004611073565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff9081168452600190910154169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610122565b6101ed6102d6565b005b6101ed6101fd366004611090565b6103d8565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b6101ed61023836600461121b565b6105c8565b61025061024b3660046112c2565b6105dc565b60405167ffffffffffffffff9091168152602001610122565b610250610277366004611344565b6105f1565b61028f61028a366004611399565b610608565b6040519015158152602001610122565b6102506102ad3660046112c2565b610711565b6101ed6102c03660046113fe565b6107a5565b60606102d160026107b6565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331461035c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6103e06107c3565b60005b818110156105c357368383838181106103fe576103fe61141b565b6080029190910191506000905060048161041b6020850185611073565b67ffffffffffffffff1681526020810191909152604001600020805490915073ffffffffffffffffffffffffffffffffffffffff161515806104765750600181015473ffffffffffffffffffffffffffffffffffffffff1615155b156104c15761048b604083016020840161144a565b6104c1576040517fc6117ae200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104d160608301604084016113fe565b81547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9190911617815561052160808301606084016113fe565b6001820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790556105756020830183611073565b67ffffffffffffffff167fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c3319836040016040516105b1919061146c565b60405180910390a250506001016103e3565b505050565b6105d06107c3565b6105d981610846565b50565b60006105e883836109d8565b90505b92915050565b60006105fe848484610af5565b90505b9392505050565b6000610612610c46565b600061061f868585610af5565b61062a9060016114e3565b90508467ffffffffffffffff168167ffffffffffffffff161461068e577f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f8686868660405161067c9493929190611504565b60405180910390a16000915050610709565b67ffffffffffffffff86166000908152600660205260409081902090518291906106bb9087908790611570565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550600190505b949350505050565b600061071b610c46565b600061072784846109d8565b6107329060016114e3565b67ffffffffffffffff808616600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902080549183167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905591505092915050565b6107ad6107c3565b6105d981610c89565b6060600061060183610d7e565b60005473ffffffffffffffffffffffffffffffffffffffff163314610844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610353565b565b602081015160005b81518110156108e157600082828151811061086b5761086b61141b565b60200260200101519050610889816002610dda90919063ffffffff16565b156108d85760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010161084e565b50815160005b81518110156109d25760008282815181106109045761090461141b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610974576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097f600282610dfc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016108e7565b50505050565b67ffffffffffffffff808316600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091168082036105e85767ffffffffffffffff841660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff168015610aed576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015282169063856c824790602401602060405180830381865afa158015610ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae49190611580565b925050506105eb565b509392505050565b67ffffffffffffffff83166000908152600660205260408082209051829190610b219086908690611570565b9081526040519081900360200190205467ffffffffffffffff16905060008190036105fe5767ffffffffffffffff851660009081526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff168015610c3d5773ffffffffffffffffffffffffffffffffffffffff811663856c8247610ba7868801886113fe565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610c10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c349190611580565b92505050610601565b50949350505050565b610c51600233610e1e565b610844576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610353565b3373ffffffffffffffffffffffffffffffffffffffff821603610d08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610353565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015610dce57602002820191906000526020600020905b815481526020019060010190808311610dba575b50505050509050919050565b60006105e88373ffffffffffffffffffffffffffffffffffffffff8416610e4d565b60006105e88373ffffffffffffffffffffffffffffffffffffffff8416610f47565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156105e8565b60008181526001830160205260408120548015610f36576000610e7160018361159d565b8554909150600090610e859060019061159d565b9050818114610eea576000866000018281548110610ea557610ea561141b565b9060005260206000200154905080876000018481548110610ec857610ec861141b565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610efb57610efb6115b0565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105eb565b60009150506105eb565b5092915050565b6000818152600183016020526040812054610f8e575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105eb565b5060006105eb565b60006020808352835180602085015260005b81811015610fc457858101830151858201604001528201610fa8565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b8181101561105157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161101f565b50909695505050505050565b67ffffffffffffffff811681146105d957600080fd5b60006020828403121561108557600080fd5b81356105e88161105d565b600080602083850312156110a357600080fd5b823567ffffffffffffffff808211156110bb57600080fd5b818501915085601f8301126110cf57600080fd5b8135818111156110de57600080fd5b8660208260071b85010111156110f357600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105d957600080fd5b600082601f83011261116757600080fd5b8135602067ffffffffffffffff8083111561118457611184611105565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156111c7576111c7611105565b60405293845260208187018101949081019250878511156111e757600080fd5b6020870191505b8482101561121057813561120181611134565b835291830191908301906111ee565b979650505050505050565b60006020828403121561122d57600080fd5b813567ffffffffffffffff8082111561124557600080fd5b908301906040828603121561125957600080fd5b60405160408101818110838211171561127457611274611105565b60405282358281111561128657600080fd5b61129287828601611156565b8252506020830135828111156112a757600080fd5b6112b387828601611156565b60208301525095945050505050565b600080604083850312156112d557600080fd5b82356112e08161105d565b915060208301356112f081611134565b809150509250929050565b60008083601f84011261130d57600080fd5b50813567ffffffffffffffff81111561132557600080fd5b60208301915083602082850101111561133d57600080fd5b9250929050565b60008060006040848603121561135957600080fd5b83356113648161105d565b9250602084013567ffffffffffffffff81111561138057600080fd5b61138c868287016112fb565b9497909650939450505050565b600080600080606085870312156113af57600080fd5b84356113ba8161105d565b935060208501356113ca8161105d565b9250604085013567ffffffffffffffff8111156113e657600080fd5b6113f2878288016112fb565b95989497509550505050565b60006020828403121561141057600080fd5b81356105e881611134565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561145c57600080fd5b813580151581146105e857600080fd5b60408101823561147b81611134565b73ffffffffffffffffffffffffffffffffffffffff90811683526020840135906114a482611134565b8082166020850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115610f4057610f406114b4565b600067ffffffffffffffff8087168352808616602084015250606060408301528260608301528284608084013760006080848401015260807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905095945050505050565b8183823760009101908152919050565b60006020828403121561159257600080fd5b81516105e88161105d565b818103818111156105eb576105eb6114b4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var NonceManagerABI = NonceManagerMetaData.ABI @@ -296,6 +297,28 @@ func (_NonceManager *NonceManagerCallerSession) Owner() (common.Address, error) return _NonceManager.Contract.Owner(&_NonceManager.CallOpts) } +func (_NonceManager *NonceManagerCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _NonceManager.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_NonceManager *NonceManagerSession) TypeAndVersion() (string, error) { + return _NonceManager.Contract.TypeAndVersion(&_NonceManager.CallOpts) +} + +func (_NonceManager *NonceManagerCallerSession) TypeAndVersion() (string, error) { + return _NonceManager.Contract.TypeAndVersion(&_NonceManager.CallOpts) +} + func (_NonceManager *NonceManagerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { return _NonceManager.contract.Transact(opts, "acceptOwnership") } @@ -1180,6 +1203,8 @@ type NonceManagerInterface interface { Owner(opts *bind.CallOpts) (common.Address, error) + TypeAndVersion(opts *bind.CallOpts) (string, error) + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go b/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go deleted file mode 100644 index 399ae5dbd62..00000000000 --- a/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go +++ /dev/null @@ -1,196 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package ocr3_config_encoder - -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 CCIPConfigTypesOCR3Config struct { - PluginType uint8 - ChainSelector uint64 - F uint8 - OffchainConfigVersion uint64 - OfframpAddress []byte - BootstrapP2PIds [][32]byte - P2pIds [][32]byte - Signers [][]byte - Transmitters [][]byte - OffchainConfig []byte -} - -var IOCR3ConfigEncoderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"exposeOCR3Config\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", -} - -var IOCR3ConfigEncoderABI = IOCR3ConfigEncoderMetaData.ABI - -type IOCR3ConfigEncoder struct { - address common.Address - abi abi.ABI - IOCR3ConfigEncoderCaller - IOCR3ConfigEncoderTransactor - IOCR3ConfigEncoderFilterer -} - -type IOCR3ConfigEncoderCaller struct { - contract *bind.BoundContract -} - -type IOCR3ConfigEncoderTransactor struct { - contract *bind.BoundContract -} - -type IOCR3ConfigEncoderFilterer struct { - contract *bind.BoundContract -} - -type IOCR3ConfigEncoderSession struct { - Contract *IOCR3ConfigEncoder - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type IOCR3ConfigEncoderCallerSession struct { - Contract *IOCR3ConfigEncoderCaller - CallOpts bind.CallOpts -} - -type IOCR3ConfigEncoderTransactorSession struct { - Contract *IOCR3ConfigEncoderTransactor - TransactOpts bind.TransactOpts -} - -type IOCR3ConfigEncoderRaw struct { - Contract *IOCR3ConfigEncoder -} - -type IOCR3ConfigEncoderCallerRaw struct { - Contract *IOCR3ConfigEncoderCaller -} - -type IOCR3ConfigEncoderTransactorRaw struct { - Contract *IOCR3ConfigEncoderTransactor -} - -func NewIOCR3ConfigEncoder(address common.Address, backend bind.ContractBackend) (*IOCR3ConfigEncoder, error) { - abi, err := abi.JSON(strings.NewReader(IOCR3ConfigEncoderABI)) - if err != nil { - return nil, err - } - contract, err := bindIOCR3ConfigEncoder(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &IOCR3ConfigEncoder{address: address, abi: abi, IOCR3ConfigEncoderCaller: IOCR3ConfigEncoderCaller{contract: contract}, IOCR3ConfigEncoderTransactor: IOCR3ConfigEncoderTransactor{contract: contract}, IOCR3ConfigEncoderFilterer: IOCR3ConfigEncoderFilterer{contract: contract}}, nil -} - -func NewIOCR3ConfigEncoderCaller(address common.Address, caller bind.ContractCaller) (*IOCR3ConfigEncoderCaller, error) { - contract, err := bindIOCR3ConfigEncoder(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &IOCR3ConfigEncoderCaller{contract: contract}, nil -} - -func NewIOCR3ConfigEncoderTransactor(address common.Address, transactor bind.ContractTransactor) (*IOCR3ConfigEncoderTransactor, error) { - contract, err := bindIOCR3ConfigEncoder(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &IOCR3ConfigEncoderTransactor{contract: contract}, nil -} - -func NewIOCR3ConfigEncoderFilterer(address common.Address, filterer bind.ContractFilterer) (*IOCR3ConfigEncoderFilterer, error) { - contract, err := bindIOCR3ConfigEncoder(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &IOCR3ConfigEncoderFilterer{contract: contract}, nil -} - -func bindIOCR3ConfigEncoder(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IOCR3ConfigEncoderMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IOCR3ConfigEncoder.Contract.IOCR3ConfigEncoderCaller.contract.Call(opts, result, method, params...) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IOCR3ConfigEncoder.Contract.IOCR3ConfigEncoderTransactor.contract.Transfer(opts) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IOCR3ConfigEncoder.Contract.IOCR3ConfigEncoderTransactor.contract.Transact(opts, method, params...) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IOCR3ConfigEncoder.Contract.contract.Call(opts, result, method, params...) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IOCR3ConfigEncoder.Contract.contract.Transfer(opts) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IOCR3ConfigEncoder.Contract.contract.Transact(opts, method, params...) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderCaller) ExposeOCR3Config(opts *bind.CallOpts, config []CCIPConfigTypesOCR3Config) ([]byte, error) { - var out []interface{} - err := _IOCR3ConfigEncoder.contract.Call(opts, &out, "exposeOCR3Config", config) - - if err != nil { - return *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return out0, err - -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderSession) ExposeOCR3Config(config []CCIPConfigTypesOCR3Config) ([]byte, error) { - return _IOCR3ConfigEncoder.Contract.ExposeOCR3Config(&_IOCR3ConfigEncoder.CallOpts, config) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoderCallerSession) ExposeOCR3Config(config []CCIPConfigTypesOCR3Config) ([]byte, error) { - return _IOCR3ConfigEncoder.Contract.ExposeOCR3Config(&_IOCR3ConfigEncoder.CallOpts, config) -} - -func (_IOCR3ConfigEncoder *IOCR3ConfigEncoder) Address() common.Address { - return _IOCR3ConfigEncoder.address -} - -type IOCR3ConfigEncoderInterface interface { - ExposeOCR3Config(opts *bind.CallOpts, config []CCIPConfigTypesOCR3Config) ([]byte, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go new file mode 100644 index 00000000000..8705ccf4b5f --- /dev/null +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -0,0 +1,2608 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package offramp + +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 ClientAny2EVMMessage struct { + MessageId [32]byte + SourceChainSelector uint64 + Sender []byte + Data []byte + DestTokenAmounts []ClientEVMTokenAmount +} + +type ClientEVMTokenAmount struct { + Token common.Address + Amount *big.Int +} + +type InternalAny2EVMRampMessage struct { + Header InternalRampMessageHeader + Sender []byte + Data []byte + Receiver common.Address + GasLimit *big.Int + TokenAmounts []InternalAny2EVMTokenTransfer +} + +type InternalAny2EVMTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress common.Address + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int +} + +type InternalExecutionReport struct { + SourceChainSelector uint64 + Messages []InternalAny2EVMRampMessage + OffchainTokenData [][][]byte + Proofs [][32]byte + ProofFlagBits *big.Int +} + +type InternalGasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas *big.Int +} + +type InternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + +type InternalPriceUpdates struct { + TokenPriceUpdates []InternalTokenPriceUpdate + GasPriceUpdates []InternalGasPriceUpdate +} + +type InternalRampMessageHeader struct { + MessageId [32]byte + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + +type InternalTokenPriceUpdate struct { + SourceToken common.Address + UsdPerToken *big.Int +} + +type MultiOCR3BaseConfigInfo struct { + ConfigDigest [32]byte + F uint8 + N uint8 + IsSignatureVerificationEnabled bool +} + +type MultiOCR3BaseOCRConfig struct { + ConfigInfo MultiOCR3BaseConfigInfo + Signers []common.Address + Transmitters []common.Address +} + +type MultiOCR3BaseOCRConfigArgs struct { + ConfigDigest [32]byte + OcrPluginType uint8 + F uint8 + IsSignatureVerificationEnabled bool + Signers []common.Address + Transmitters []common.Address +} + +type OffRampDynamicConfig struct { + FeeQuoter common.Address + PermissionLessExecutionThresholdSeconds uint32 + MessageInterceptor common.Address +} + +type OffRampGasLimitOverride struct { + ReceiverExecutionGasLimit *big.Int + TokenGasOverrides []uint32 +} + +type OffRampSourceChainConfig struct { + Router common.Address + IsEnabled bool + MinSeqNr uint64 + OnRamp []byte +} + +type OffRampSourceChainConfigArgs struct { + Router common.Address + SourceChainSelector uint64 + IsEnabled bool + OnRamp []byte +} + +type OffRampStaticConfig struct { + ChainSelector uint64 + RmnRemote common.Address + TokenAdminRegistry common.Address + NonceManager common.Address +} + +var OffRampMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"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\":\"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\":[{\"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\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"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\":\"SignatureVerificationDisabled\",\"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\":\"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\":\"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\":\"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[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\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"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\":\"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\":\"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\":\"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: "0x6101206040523480156200001257600080fd5b5060405162006c5638038062006c56833981016040819052620000359162000885565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000c0c565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005d0576000828281518110620003915762000391620009c2565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260086020526040902060608301516001820180546200042690620009d8565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d828262000a69565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200057c60066001600160401b038516620005d4565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005b8919062000b35565b60405180910390a25050505080600101905062000370565b5050565b6000620005e28383620005eb565b90505b92915050565b60008181526001830160205260408120546200063457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005e5565b506000620005e5565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200067857620006786200063d565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006a957620006a96200063d565b604052919050565b80516001600160401b0381168114620006c957600080fd5b919050565b6001600160a01b0381168114620006e457600080fd5b50565b6000601f83601f840112620006fb57600080fd5b825160206001600160401b03808311156200071a576200071a6200063d565b8260051b6200072b8382016200067e565b93845286810183019383810190898611156200074657600080fd5b84890192505b858310156200087857825184811115620007665760008081fd5b89016080601f19828d038101821315620007805760008081fd5b6200078a62000653565b888401516200079981620006ce565b81526040620007aa858201620006b1565b8a8301526060808601518015158114620007c45760008081fd5b83830152938501519389851115620007dc5760008081fd5b84860195508f603f870112620007f457600094508485fd5b8a8601519450898511156200080d576200080d6200063d565b6200081e8b858f880116016200067e565b93508484528f82868801011115620008365760008081fd5b60005b8581101562000856578681018301518582018d01528b0162000839565b5060009484018b0194909452509182015283525091840191908401906200074c565b9998505050505050505050565b60008060008385036101008112156200089d57600080fd5b6080811215620008ac57600080fd5b620008b662000653565b620008c186620006b1565b81526020860151620008d381620006ce565b60208201526040860151620008e881620006ce565b60408201526060860151620008fd81620006ce565b606082810191909152909450607f19820112156200091a57600080fd5b50604051606081016001600160401b0380821183831017156200094157620009416200063d565b81604052608087015191506200095782620006ce565b90825260a08601519063ffffffff821682146200097357600080fd5b81602084015260c087015191506200098b82620006ce565b6040830182905260e087015192945080831115620009a857600080fd5b5050620009b886828701620006e7565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009ed57607f821691505b60208210810362000a0e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000a64576000816000526020600020601f850160051c8101602086101562000a3f5750805b601f850160051c820191505b8181101562000a605782815560010162000a4b565b5050505b505050565b81516001600160401b0381111562000a855762000a856200063d565b62000a9d8162000a968454620009d8565b8462000a14565b602080601f83116001811462000ad5576000841562000abc5750858301515b600019600386901b1c1916600185901b17855562000a60565b600085815260208120601f198616915b8281101562000b065788860151825594840194600190910190840162000ae5565b508582101562000b255787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b8a81620009d8565b8060a089015260c0600183166000811462000bae576001811462000bcb5762000bfd565b60ff19841660c08b015260c083151560051b8b0101945062000bfd565b85600052602060002060005b8481101562000bf45781548c820185015290880190890162000bd7565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fd462000c82600039600081816102470152612ca70152600081816102180152612f960152600081816101e9015281816105890152818161073b01526126590152600081816101ba01526128a7015260008181611d7e0152611db10152615fd46000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c80636f9e320f116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e146104ed578063f2fde38b1461050d578063f716f99f1461052057600080fd5b8063c673e58414610489578063ccd37ba3146104a957600080fd5b806379ba5097116100b257806379ba50971461045857806385572ffb146104605780638da5cb5b1461046e57600080fd5b80636f9e320f146103b35780637437ff9f146103c657600080fd5b80633f4b04aa116101245780635e36480c116101095780635e36480c1461036d5780635e7bb0081461038d57806360987c20146103a057600080fd5b80633f4b04aa1461033c5780635215505b1461035757600080fd5b8063181f5a7711610155578063181f5a77146102cd5780632d04ab7614610316578063311cd5131461032957600080fd5b806304666f9c1461017157806306285c6914610186575b600080fd5b61018461017f366004613eeb565b610533565b005b61027760408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102c4919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103096040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102c49190614059565b610184610324366004614109565b610547565b6101846103373660046141bb565b610a4e565b600b546040516001600160401b0390911681526020016102c4565b61035f610ab7565b6040516102c4929190614255565b61038061037b3660046142f6565b610d12565b6040516102c49190614353565b61018461039b3660046148bc565b610d67565b6101846103ae366004614b00565b610ff6565b6101846103c1366004614b94565b6112d6565b610422604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102c4565b6101846112e7565b61018461016c366004614c03565b6000546040516001600160a01b0390911681526020016102c4565b61049c610497366004614c4e565b611398565b6040516102c49190614cae565b6104df6104b7366004614d23565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b6040519081526020016102c4565b6105006104fb366004614d4d565b6114f6565b6040516102c49190614d68565b61018461051b366004614d7b565b611602565b61018461052e366004614e00565b611613565b61053b611655565b610544816116b1565b50565b600061055587890189615155565b602081015151909150156105f257602081015160408083015160608401519151638d8741cb60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693638d8741cb936105c193309390919060040161538a565b60006040518083038186803b1580156105d957600080fd5b505afa1580156105ed573d6000803e3d6000fd5b505050505b8051515115158061060857508051602001515115155b156106d457600b5460208a0135906001600160401b03808316911610156106ac57600b805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106759291016154d7565b600060405180830381600087803b15801561068f57600080fd5b505af11580156106a3573d6000803e3d6000fd5b505050506106d2565b8160200151516000036106d257604051632261116760e01b815260040160405180910390fd5b505b60005b81602001515181101561098f576000826020015182815181106106fc576106fc615405565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a691906154ea565b156107d457604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107df82611918565b9050806001016040516107f29190615541565b60405180910390208360200151805190602001201461082f5782602001518160010160405163b80d8fa960e01b81526004016107cb929190615634565b60408301518154600160a81b90046001600160401b039081169116141580610870575082606001516001600160401b031683604001516001600160401b0316115b156108b557825160408085015160608601519151636af0786b60e11b81526001600160401b0393841660048201529083166024820152911660448201526064016107cb565b6080830151806108d85760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a60209081526040808320848452909152902054156109305783516040516332cf0cbf60e01b81526001600160401b039091166004820152602481018290526044016107cb565b606084015161094090600161566f565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016106d7565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926109c7929091615696565b60405180910390a1610a4360008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611964915050565b505050505050505050565b610a8e610a5d828401846156bb565b6040805160008082526020820190925290610a88565b6060815260200190600190039081610a735790505b50611c5d565b604080516000808252602082019092529050610ab1600185858585866000611964565b50505050565b6060806000610ac66006611d20565b6001600160401b03811115610add57610add613d2d565b604051908082528060200260200182016040528015610b2e57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610afb5790505b5090506000610b3d6006611d20565b6001600160401b03811115610b5457610b54613d2d565b604051908082528060200260200182016040528015610b7d578160200160208202803683370190505b50905060005b610b8d6006611d20565b811015610d0957610b9f600682611d2a565b828281518110610bb157610bb1615405565b60200260200101906001600160401b031690816001600160401b03168152505060086000838381518110610be757610be7615405565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b90920490931691810191909152600182018054919291606084019190610c6290615507565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8e90615507565b8015610cdb5780601f10610cb057610100808354040283529160200191610cdb565b820191906000526020600020905b815481529060010190602001808311610cbe57829003601f168201915b505050505081525050838281518110610cf657610cf6615405565b6020908102919091010152600101610b83565b50939092509050565b6000610d20600160046156ef565b6002610d2d608085615718565b6001600160401b0316610d40919061573e565b610d4a8585611d36565b901c166003811115610d5e57610d5e614329565b90505b92915050565b610d6f611d7b565b815181518114610d92576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610fe6576000848281518110610db157610db1615405565b60200260200101519050600081602001515190506000858481518110610dd957610dd9615405565b6020026020010151905080518214610e04576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610fd7576000828281518110610e2357610e23615405565b6020026020010151600001519050600085602001518381518110610e4957610e49615405565b6020026020010151905081600014610e9d578060800151821015610e9d578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064016107cb565b838381518110610eaf57610eaf615405565b602002602001015160200151518160a001515114610efc57805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b031660248201526044016107cb565b60005b8160a0015151811015610fc9576000858581518110610f2057610f20615405565b6020026020010151602001518281518110610f3d57610f3d615405565b602002602001015163ffffffff16905080600014610fc05760008360a001518381518110610f6d57610f6d615405565b60200260200101516040015163ffffffff16905080821015610fbe578351516040516348e617b360e01b815260048101919091526024810184905260448101829052606481018390526084016107cb565b505b50600101610eff565b505050806001019050610e07565b50505050806001019050610d95565b50610ff18383611c5d565b505050565b333014611016576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281611053565b604080518082019091526000808252602082015281526020019060019003908161102c5790505b5060a08701515190915015611089576110868660a001518760200151886060015189600001516020015189898989611de3565b90505b6040805160a081018252875151815287516020908101516001600160401b0316818301528089015183516000948401926110c4929101614059565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b0316801561119f576040516308d450a160e01b81526001600160a01b038216906308d450a1906111259085906004016157f6565b600060405180830381600087803b15801561113f57600080fd5b505af1925050508015611150575060015b61119f573d80801561117e576040519150601f19603f3d011682016040523d82523d6000602084013e611183565b606091505b50806040516309c2532560e01b81526004016107cb9190614059565b6040880151511580156111b457506080880151155b806111cb575060608801516001600160a01b03163b155b806111f2575060608801516111f0906001600160a01b03166385572ffb60e01b611f94565b155b156111ff575050506112cf565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf979839261125d9289926113889291600401615809565b6000604051808303816000875af115801561127c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112a49190810190615845565b5091509150816112c957806040516302a35ba360e21b81526004016107cb9190614059565b50505050505b5050505050565b6112de611655565b61054481611fb0565b6001546001600160a01b031633146113415760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107cb565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113db6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561148457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611466575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156114e657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114c8575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161158290615507565b80601f01602080910402602001604051908101604052809291908181526020018280546115ae90615507565b80156114e65780601f106115d0576101008083540402835291602001916114e6565b820191906000526020600020905b8154815290600101906020018083116115de57505050919092525091949350505050565b61160a611655565b6105448161208f565b61161b611655565b60005b81518110156116515761164982828151811061163c5761163c615405565b6020026020010151612138565b60010161161e565b5050565b6000546001600160a01b031633146116af5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107cb565b565b60005b81518110156116515760008282815181106116d1576116d1615405565b60200260200101519050600081602001519050806001600160401b031660000361170e5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316611736576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600860205260409020606083015160018201805461176290615507565b90506000036117c457815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611801565b8154600160a81b90046001600160401b031660011461180157604051632105803760e11b81526001600160401b03841660048201526024016107cb565b805115806118365750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b15611854576040516342bcdf7f60e11b815260040160405180910390fd5b60018201611862828261592a565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171782556118c760066001600160401b038516612462565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b8360405161190191906159e9565b60405180910390a2505050508060010190506116b4565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff16610d615760405163ed053c5960e01b81526001600160401b03841660048201526024016107cb565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119c38760a4615a37565b9050826060015115611a0b5784516119dc90602061573e565b86516119e990602061573e565b6119f49060a0615a37565b6119fe9190615a37565b611a089082615a37565b90505b368114611a3457604051638e1192e160e01b8152600481018290523660248201526044016107cb565b5081518114611a635781516040516324f7d61360e21b81526004810191909152602481018290526044016107cb565b611a6b611d7b565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611ab957611ab9614329565b6002811115611aca57611aca614329565b9052509050600281602001516002811115611ae757611ae7614329565b148015611b3b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b2357611b23615405565b6000918252602090912001546001600160a01b031633145b611b5857604051631b41e11d60e31b815260040160405180910390fd5b50816060015115611c08576020820151611b73906001615a4a565b60ff16855114611b96576040516371253a2560e01b815260040160405180910390fd5b8351855114611bb85760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611bca929190615a63565b604051908190038120611be1918b90602001615a73565b604051602081830303815290604052805190602001209050611c068a8288888861246e565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611c7f5760405163c2e5347d60e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611cc2565b604080518082019091526000815260606020820152815260200190600190039081611c9a5790505b50905060005b84518110156112cf57611d18858281518110611ce657611ce6615405565b602002602001015184611d1257858381518110611d0557611d05615405565b602002602001015161262b565b8361262b565b600101611cc8565b6000610d61825490565b6000610d5e8383612f31565b6001600160401b038216600090815260096020526040812081611d5a608085615a87565b6001600160401b031681526020810191909152604001600020549392505050565b467f0000000000000000000000000000000000000000000000000000000000000000146116af57604051630f01ce8560e01b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107cb565b606088516001600160401b03811115611dfe57611dfe613d2d565b604051908082528060200260200182016040528015611e4357816020015b6040805180820190915260008082526020820152815260200190600190039081611e1c5790505b509050811560005b8a51811015611f865781611ee357848482818110611e6b57611e6b615405565b9050602002016020810190611e809190615aad565b63ffffffff1615611ee357848482818110611e9d57611e9d615405565b9050602002016020810190611eb29190615aad565b8b8281518110611ec457611ec4615405565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611f618b8281518110611ef857611ef8615405565b60200260200101518b8b8b8b8b87818110611f1557611f15615405565b9050602002810190611f279190615ac8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f5b92505050565b838281518110611f7357611f73615405565b6020908102919091010152600101611e4b565b505098975050505050505050565b6000611f9f8361323b565b8015610d5e5750610d5e8383613286565b80516001600160a01b0316611fd8576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b336001600160a01b038216036120e75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107cb565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003612163576000604051631b3fab5160e11b81526004016107cb9190615b0e565b60208082015160ff808216600090815260029093526040832060018101549293909283921690036121b4576060840151600182018054911515620100000262ff0000199092169190911790556121f0565b6060840151600182015460ff62010000909104161515901515146121f0576040516321fd80df60e21b815260ff841660048201526024016107cb565b60a08401518051610100101561221c576001604051631b3fab5160e11b81526004016107cb9190615b0e565b8051600003612241576005604051631b3fab5160e11b81526004016107cb9190615b0e565b6122a7848460030180548060200260200160405190810160405280929190818152602001828054801561229d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161227f575b5050505050613328565b8460600151156123d757612315848460020180548060200260200160405190810160405280929190818152602001828054801561229d576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161227f575050505050613328565b608085015180516101001015612341576002604051631b3fab5160e11b81526004016107cb9190615b0e565b6040860151612351906003615b28565b60ff16815111612377576003604051631b3fab5160e11b81526004016107cb9190615b0e565b81518151101561239d576001604051631b3fab5160e11b81526004016107cb9190615b0e565b805160018401805461ff00191661010060ff8416021790556123c89060028601906020840190613cb3565b506123d585826001613391565b505b6123e384826002613391565b80516123f89060038501906020840190613cb3565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124519389939260028a01929190615b44565b60405180910390a16112cf846134ec565b6000610d5e8383613543565b8251600090815b8181101561262157600060018886846020811061249457612494615405565b6124a191901a601b615a4a565b8985815181106124b3576124b3615405565b60200260200101518986815181106124cd576124cd615405565b60200260200101516040516000815260200160405260405161250b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561252d573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561258e5761258e614329565b600281111561259f5761259f614329565b90525090506001816020015160028111156125bc576125bc614329565b146125da57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561260457604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612475565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156126a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126cc91906154ea565b1561273d5780156126fb57604051637edeb53960e11b81526001600160401b03831660048201526024016107cb565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061274883611918565b600101805461275690615507565b80601f016020809104026020016040519081016040528092919081815260200182805461278290615507565b80156127cf5780601f106127a4576101008083540402835291602001916127cf565b820191906000526020600020905b8154815290600101906020018083116127b257829003601f168201915b5050506020880151519293505050600081900361280d57855160405163676cf24b60e11b81526001600160401b0390911660048201526024016107cb565b8560400151518114612832576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561284c5761284c613d2d565b604051908082528060200260200182016040528015612875578160200160208202803683370190505b50905060005b82811015612a195760008860200151828151811061289b5761289b615405565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146129125780516040908101519051631c21951160e11b81526001600160401b0390911660048201526024016107cb565b866001600160401b03168160000151602001516001600160401b03161461296657805160200151604051636c95f1eb60e01b81526001600160401b03808a16600483015290911660248201526044016107cb565b6129f3817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f83600001516020015184600001516040015189805190602001206040516020016129d894939291909384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613592565b838381518110612a0557612a05615405565b60209081029190910101525060010161287b565b506000612a3086838a606001518b6080015161369a565b905080600003612a5e57604051633ee8bd3f60e11b81526001600160401b03871660048201526024016107cb565b60005b83811015610a435760005a905060008a602001518381518110612a8657612a86615405565b602002602001015190506000612aa48a836000015160600151610d12565b90506000816003811115612aba57612aba614329565b1480612ad757506003816003811115612ad557612ad5614329565b145b612b2d57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612f29565b60608915612c0c578b8581518110612b4757612b47615405565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff16612b7588426156ef565b1190508080612b9557506003836003811115612b9357612b93614329565b145b612bbd576040516354e7e43160e11b81526001600160401b038d1660048201526024016107cb565b8c8681518110612bcf57612bcf615405565b602002602001015160000151600014612c06578c8681518110612bf457612bf4615405565b60209081029190910101515160808501525b50612c78565b6000826003811115612c2057612c20614329565b14612c7857825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612f29565b8251608001516001600160401b031615612d51576000826003811115612ca057612ca0614329565b03612d51577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612d0193929190615bf6565b6020604051808303816000875af1158015612d20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4491906154ea565b612d515750505050612f29565b60008d604001518681518110612d6957612d69615405565b6020026020010151905080518460a001515114612db357835160600151604051631cfe6d8b60e01b81526001600160401b03808f16600483015290911660248201526044016107cb565b612dc78c85600001516060015160016136d7565b600080612dd586848661377c565b91509150612dec8e876000015160600151846136d7565b8c15612e43576003826003811115612e0657612e06614329565b03612e43576000856003811115612e1f57612e1f614329565b14612e4357855151604051632b11b8d960e01b81526107cb91908390600401615c22565b6002826003811115612e5757612e57614329565b14612e9c576003826003811115612e7057612e70614329565b14612e9c578d866000015160600151836040516349362d1f60e11b81526004016107cb93929190615c3b565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612ef457612ef4615405565b602002602001015186865a612f09908f6156ef565b604051612f199493929190615c60565b60405180910390a4505050505050505b600101612a61565b6000826000018281548110612f4857612f48615405565b9060005260206000200154905092915050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130039190615c97565b90506001600160a01b038116158061303257506130306001600160a01b03821663aff2afbf60e01b611f94565b155b1561305b5760405163ae9b4ce960e01b81526001600160a01b03821660048201526024016107cb565b60008061307388858c6040015163ffffffff16613830565b9150915060008060006131266040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b8152506040516024016130f09190615cb4565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613913565b9250925092508261314c578160405163e1cd550960e01b81526004016107cb9190614059565b815160201461317b578151604051631e3be00960e21b81526020600482015260248101919091526044016107cb565b6000828060200190518101906131919190615d80565b9050866001600160a01b03168c6001600160a01b03161461320d5760006131c28d8a6131bd868a6156ef565b613830565b509050868110806131dc5750816131d988836156ef565b14155b1561320b5760405163a966e21f60e01b81526004810183905260248101889052604481018290526064016107cb565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061324e826301ffc9a760e01b613286565b8015610d61575061327f827fffffffff00000000000000000000000000000000000000000000000000000000613286565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015613311575060208210155b801561331d5750600081115b979650505050505050565b60005b8151811015610ff15760ff83166000908152600360205260408120835190919084908490811061335d5761335d615405565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161332b565b60005b8251811015610ab15760008382815181106133b1576133b1615405565b60200260200101519050600060028111156133ce576133ce614329565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561340d5761340d614329565b1461342e576004604051631b3fab5160e11b81526004016107cb9190615b0e565b6001600160a01b0381166134555760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561347b5761347b614329565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156134d8576134d8614329565b021790555090505050806001019050613394565b60ff81166105445760ff8082166000908152600260205260409020600101546201000090041661352f57604051631e8ed32560e21b815260040160405180910390fd5b600b805467ffffffffffffffff1916905550565b600081815260018301602052604081205461358a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d61565b506000610d61565b8151805160608085015190830151608080870151940151604051600095869588956135f695919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016136399190615e3a565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b6000806136a88585856139ed565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b600060026136e6608085615718565b6001600160401b03166136f9919061573e565b905060006137078585611d36565b905081613716600160046156ef565b901b19168183600381111561372d5761372d614329565b6001600160401b03871660009081526009602052604081209190921b9290921791829161375b608088615a87565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c20906137a990889088908890600401615ed1565b600060405180830381600087803b1580156137c357600080fd5b505af19250505080156137d4575060015b613813573d808015613802576040519150601f19603f3d011682016040523d82523d6000602084013e613807565b606091505b50600392509050613828565b50506040805160208101909152600081526002905b935093915050565b60008060008060006138918860405160240161385b91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613913565b925092509250826138b7578160405163e1cd550960e01b81526004016107cb9190614059565b60208251146138e6578151604051631e3be00960e21b81526020600482015260248101919091526044016107cb565b818060200190518101906138fa9190615d80565b61390482886156ef565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561393557613935613d2d565b6040519080825280601f01601f19166020018201604052801561395f576020820181803683370190505b509150863b6139795763030ed58f60e21b60005260046000fd5b5a8581101561399357632be8ca8b60e21b60005260046000fd5b85900360408104810387106139b3576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156139d65750835b808352806000602085013e50955095509592505050565b8251825160009190818303613a1557604051630469ac9960e21b815260040160405180910390fd5b6101018211801590613a2957506101018111155b613a46576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613a70576040516309bde33960e01b815260040160405180910390fd5b80600003613a9d5786600081518110613a8b57613a8b615405565b60200260200101519350505050613c6b565b6000816001600160401b03811115613ab757613ab7613d2d565b604051908082528060200260200182016040528015613ae0578160200160208202803683370190505b50905060008080805b85811015613c0a5760006001821b8b811603613b445788851015613b2d578c5160018601958e918110613b1e57613b1e615405565b60200260200101519050613b66565b8551600185019487918110613b1e57613b1e615405565b8b5160018401938d918110613b5b57613b5b615405565b602002602001015190505b600089861015613b96578d5160018701968f918110613b8757613b87615405565b60200260200101519050613bb8565b8651600186019588918110613bad57613bad615405565b602002602001015190505b82851115613bd9576040516309bde33960e01b815260040160405180910390fd5b613be38282613c72565b878481518110613bf557613bf5615405565b60209081029190910101525050600101613ae9565b506001850382148015613c1c57508683145b8015613c2757508581145b613c44576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613c5957613c59615405565b60200260200101519750505050505050505b9392505050565b6000818310613c8a57613c858284613c90565b610d5e565b610d5e83835b60408051600160208201529081018390526060810182905260009060800161367c565b828054828255906000526020600020908101928215613d08579160200282015b82811115613d0857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613cd3565b50613d14929150613d18565b5090565b5b80821115613d145760008155600101613d19565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613d6557613d65613d2d565b60405290565b60405160a081016001600160401b0381118282101715613d6557613d65613d2d565b60405160c081016001600160401b0381118282101715613d6557613d65613d2d565b604080519081016001600160401b0381118282101715613d6557613d65613d2d565b604051601f8201601f191681016001600160401b0381118282101715613df957613df9613d2d565b604052919050565b60006001600160401b03821115613e1a57613e1a613d2d565b5060051b60200190565b6001600160a01b038116811461054457600080fd5b80356001600160401b0381168114613e5057600080fd5b919050565b801515811461054457600080fd5b8035613e5081613e55565b60006001600160401b03821115613e8757613e87613d2d565b50601f01601f191660200190565b600082601f830112613ea657600080fd5b8135613eb9613eb482613e6e565b613dd1565b818152846020838601011115613ece57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613efe57600080fd5b82356001600160401b0380821115613f1557600080fd5b818501915085601f830112613f2957600080fd5b8135613f37613eb482613e01565b81815260059190911b83018401908481019088831115613f5657600080fd5b8585015b83811015613ffc57803585811115613f725760008081fd5b86016080818c03601f1901811315613f8a5760008081fd5b613f92613d43565b89830135613f9f81613e24565b81526040613fae848201613e39565b8b830152606080850135613fc181613e55565b83830152928401359289841115613fda57600091508182fd5b613fe88f8d86880101613e95565b908301525085525050918601918601613f5a565b5098975050505050505050565b60005b8381101561402457818101518382015260200161400c565b50506000910152565b60008151808452614045816020860160208601614009565b601f01601f19169290920160200192915050565b602081526000610d5e602083018461402d565b8060608101831015610d6157600080fd5b60008083601f84011261408f57600080fd5b5081356001600160401b038111156140a657600080fd5b6020830191508360208285010111156140be57600080fd5b9250929050565b60008083601f8401126140d757600080fd5b5081356001600160401b038111156140ee57600080fd5b6020830191508360208260051b85010111156140be57600080fd5b60008060008060008060008060e0898b03121561412557600080fd5b61412f8a8a61406c565b975060608901356001600160401b038082111561414b57600080fd5b6141578c838d0161407d565b909950975060808b013591508082111561417057600080fd5b61417c8c838d016140c5565b909750955060a08b013591508082111561419557600080fd5b506141a28b828c016140c5565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156141d057600080fd5b6141da858561406c565b925060608401356001600160401b038111156141f557600080fd5b6142018682870161407d565b9497909650939450505050565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526136cf608085018261402d565b604080825283519082018190526000906020906060840190828701845b828110156142975781516001600160401b031684529284019290840190600101614272565b50505083810382850152845180825282820190600581901b8301840187850160005b838110156142e757601f198684030185526142d583835161420e565b948701949250908601906001016142b9565b50909998505050505050505050565b6000806040838503121561430957600080fd5b61431283613e39565b915061432060208401613e39565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b6004811061434f5761434f614329565b9052565b60208101610d61828461433f565b600060a0828403121561437357600080fd5b61437b613d6b565b90508135815261438d60208301613e39565b602082015261439e60408301613e39565b60408201526143af60608301613e39565b60608201526143c060808301613e39565b608082015292915050565b8035613e5081613e24565b803563ffffffff81168114613e5057600080fd5b600082601f8301126143fb57600080fd5b8135602061440b613eb483613e01565b82815260059290921b8401810191818101908684111561442a57600080fd5b8286015b848110156144fa5780356001600160401b038082111561444e5760008081fd5b9088019060a0828b03601f19018113156144685760008081fd5b614470613d6b565b87840135838111156144825760008081fd5b6144908d8a83880101613e95565b8252506040808501356144a281613e24565b828a015260606144b38682016143d6565b828401526080915081860135858111156144cd5760008081fd5b6144db8f8c838a0101613e95565b918401919091525091909301359083015250835291830191830161442e565b509695505050505050565b6000610140828403121561451857600080fd5b614520613d8d565b905061452c8383614361565b815260a08201356001600160401b038082111561454857600080fd5b61455485838601613e95565b602084015260c084013591508082111561456d57600080fd5b61457985838601613e95565b604084015261458a60e085016143cb565b606084015261010084013560808401526101208401359150808211156145af57600080fd5b506145bc848285016143ea565b60a08301525092915050565b600082601f8301126145d957600080fd5b813560206145e9613eb483613e01565b82815260059290921b8401810191818101908684111561460857600080fd5b8286015b848110156144fa5780356001600160401b0381111561462b5760008081fd5b6146398986838b0101614505565b84525091830191830161460c565b600082601f83011261465857600080fd5b81356020614668613eb483613e01565b82815260059290921b8401810191818101908684111561468757600080fd5b8286015b848110156144fa5780356001600160401b03808211156146aa57600080fd5b818901915089603f8301126146be57600080fd5b858201356146ce613eb482613e01565b81815260059190911b830160400190878101908c8311156146ee57600080fd5b604085015b838110156147275780358581111561470a57600080fd5b6147198f6040838a0101613e95565b8452509189019189016146f3565b5087525050509284019250830161468b565b600082601f83011261474a57600080fd5b8135602061475a613eb483613e01565b8083825260208201915060208460051b87010193508684111561477c57600080fd5b602086015b848110156144fa5780358352918301918301614781565b600082601f8301126147a957600080fd5b813560206147b9613eb483613e01565b82815260059290921b840181019181810190868411156147d857600080fd5b8286015b848110156144fa5780356001600160401b03808211156147fc5760008081fd5b9088019060a0828b03601f19018113156148165760008081fd5b61481e613d6b565b614829888501613e39565b81526040808501358481111561483f5760008081fd5b61484d8e8b838901016145c8565b8a84015250606080860135858111156148665760008081fd5b6148748f8c838a0101614647565b838501525060809150818601358581111561488f5760008081fd5b61489d8f8c838a0101614739565b91840191909152509190930135908301525083529183019183016147dc565b600080604083850312156148cf57600080fd5b6001600160401b03833511156148e457600080fd5b6148f18484358501614798565b91506001600160401b036020840135111561490b57600080fd5b6020830135830184601f82011261492157600080fd5b61492e613eb48235613e01565b81358082526020808301929160051b84010187101561494c57600080fd5b602083015b6020843560051b850101811015614af2576001600160401b038135111561497757600080fd5b87603f82358601011261498957600080fd5b61499c613eb46020833587010135613e01565b81358501602081810135808452908301929160059190911b016040018a10156149c457600080fd5b604083358701015b83358701602081013560051b01604001811015614ae2576001600160401b03813511156149f857600080fd5b833587018135016040818d03603f19011215614a1357600080fd5b614a1b613daf565b604082013581526001600160401b0360608301351115614a3a57600080fd5b8c605f606084013584010112614a4f57600080fd5b6040606083013583010135614a66613eb482613e01565b808282526020820191508f60608460051b6060880135880101011115614a8b57600080fd5b6060808601358601015b60608460051b606088013588010101811015614ac257614ab4816143d6565b835260209283019201614a95565b5080602085015250505080855250506020830192506020810190506149cc565b5084525060209283019201614951565b508093505050509250929050565b600080600080600060608688031215614b1857600080fd5b85356001600160401b0380821115614b2f57600080fd5b614b3b89838a01614505565b96506020880135915080821115614b5157600080fd5b614b5d89838a016140c5565b90965094506040880135915080821115614b7657600080fd5b50614b83888289016140c5565b969995985093965092949392505050565b600060608284031215614ba657600080fd5b604051606081018181106001600160401b0382111715614bc857614bc8613d2d565b6040528235614bd681613e24565b8152614be4602084016143d6565b60208201526040830135614bf781613e24565b60408201529392505050565b600060208284031215614c1557600080fd5b81356001600160401b03811115614c2b57600080fd5b820160a08185031215613c6b57600080fd5b803560ff81168114613e5057600080fd5b600060208284031215614c6057600080fd5b610d5e82614c3d565b60008151808452602080850194506020840160005b83811015614ca35781516001600160a01b031687529582019590820190600101614c7e565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cfd60e0840182614c69565b90506040840151601f198483030160c0850152614d1a8282614c69565b95945050505050565b60008060408385031215614d3657600080fd5b614d3f83613e39565b946020939093013593505050565b600060208284031215614d5f57600080fd5b610d5e82613e39565b602081526000610d5e602083018461420e565b600060208284031215614d8d57600080fd5b8135613c6b81613e24565b600082601f830112614da957600080fd5b81356020614db9613eb483613e01565b8083825260208201915060208460051b870101935086841115614ddb57600080fd5b602086015b848110156144fa578035614df381613e24565b8352918301918301614de0565b60006020808385031215614e1357600080fd5b82356001600160401b0380821115614e2a57600080fd5b818501915085601f830112614e3e57600080fd5b8135614e4c613eb482613e01565b81815260059190911b83018401908481019088831115614e6b57600080fd5b8585015b83811015613ffc57803585811115614e8657600080fd5b860160c0818c03601f19011215614e9d5760008081fd5b614ea5613d8d565b8882013581526040614eb8818401614c3d565b8a8301526060614ec9818501614c3d565b8284015260809150614edc828501613e63565b9083015260a08381013589811115614ef45760008081fd5b614f028f8d83880101614d98565b838501525060c0840135915088821115614f1c5760008081fd5b614f2a8e8c84870101614d98565b9083015250845250918601918601614e6f565b80356001600160e01b0381168114613e5057600080fd5b600082601f830112614f6557600080fd5b81356020614f75613eb483613e01565b82815260069290921b84018101918181019086841115614f9457600080fd5b8286015b848110156144fa5760408189031215614fb15760008081fd5b614fb9613daf565b614fc282613e39565b8152614fcf858301614f3d565b81860152835291830191604001614f98565b600082601f830112614ff257600080fd5b81356020615002613eb483613e01565b82815260059290921b8401810191818101908684111561502157600080fd5b8286015b848110156144fa5780356001600160401b03808211156150455760008081fd5b9088019060a0828b03601f190181131561505f5760008081fd5b615067613d6b565b615072888501613e39565b8152604080850135848111156150885760008081fd5b6150968e8b83890101613e95565b8a84015250606093506150aa848601613e39565b9082015260806150bb858201613e39565b93820193909352920135908201528352918301918301615025565b600082601f8301126150e757600080fd5b813560206150f7613eb483613e01565b82815260069290921b8401810191818101908684111561511657600080fd5b8286015b848110156144fa57604081890312156151335760008081fd5b61513b613daf565b81358152848201358582015283529183019160400161511a565b6000602080838503121561516857600080fd5b82356001600160401b038082111561517f57600080fd5b908401906080828703121561519357600080fd5b61519b613d43565b8235828111156151aa57600080fd5b830160408189038113156151bd57600080fd5b6151c5613daf565b8235858111156151d457600080fd5b8301601f81018b136151e557600080fd5b80356151f3613eb482613e01565b81815260069190911b8201890190898101908d83111561521257600080fd5b928a01925b828410156152625785848f03121561522f5760008081fd5b615237613daf565b843561524281613e24565b815261524f858d01614f3d565b818d0152825292850192908a0190615217565b84525050508287013591508482111561527a57600080fd5b6152868a838501614f54565b8188015283525050828401358281111561529f57600080fd5b6152ab88828601614fe1565b858301525060408301359350818411156152c457600080fd5b6152d0878585016150d6565b6040820152606083013560608201528094505050505092915050565b600082825180855260208086019550808260051b84010181860160005b8481101561537d57601f19868403018952815160a06001600160401b038083511686528683015182888801526153418388018261402d565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615309565b5090979650505050505050565b6001600160a01b0385168152600060206080818401526153ad60808401876152ec565b83810360408581019190915286518083528388019284019060005b818110156153ed578451805184528601518684015293850193918301916001016153c8565b50508094505050505082606083015295945050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561547257835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161543b565b50508583015187820388850152805180835290840192506000918401905b808310156154cb57835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615490565b50979650505050505050565b602081526000610d5e602083018461541b565b6000602082840312156154fc57600080fd5b8151613c6b81613e55565b600181811c9082168061551b57607f821691505b60208210810361553b57634e487b7160e01b600052602260045260246000fd5b50919050565b600080835461554f81615507565b60018281168015615567576001811461557c576155ab565b60ff19841687528215158302870194506155ab565b8760005260208060002060005b858110156155a25781548a820152908401908201615589565b50505082870194505b50929695505050505050565b600081546155c481615507565b8085526020600183811680156155e157600181146155fb57615629565b60ff1985168884015283151560051b880183019550615629565b866000528260002060005b858110156156215781548a8201860152908301908401615606565b890184019650505b505050505092915050565b604081526000615647604083018561402d565b8281036020840152614d1a81856155b7565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561568f5761568f615659565b5092915050565b6040815260006156a960408301856152ec565b8281036020840152614d1a818561541b565b6000602082840312156156cd57600080fd5b81356001600160401b038111156156e357600080fd5b6136cf84828501614798565b81810381811115610d6157610d61615659565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061573257615732615702565b92169190910692915050565b8082028115828204841417610d6157610d61615659565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261578860a087018261402d565b9050606085015186820360608801526157a1828261402d565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156154cb57835180516001600160a01b03168352860151868301529285019260019290920191908401906157c4565b602081526000610d5e6020830184615755565b60808152600061581c6080830187615755565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561585a57600080fd5b835161586581613e55565b60208501519093506001600160401b0381111561588157600080fd5b8401601f8101861361589257600080fd5b80516158a0613eb482613e6e565b8181528760208385010111156158b557600080fd5b6158c6826020830160208601614009565b809450505050604084015190509250925092565b601f821115610ff1576000816000526020600020601f850160051c810160208610156159035750805b601f850160051c820191505b818110156159225782815560010161590f565b505050505050565b81516001600160401b0381111561594357615943613d2d565b615957816159518454615507565b846158da565b602080601f83116001811461598c57600084156159745750858301515b600019600386901b1c1916600185901b178555615922565b600085815260208120601f198616915b828110156159bb5788860151825594840194600190910190840161599c565b50858210156159d95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610d5e60a08301600185016155b7565b80820180821115610d6157610d61615659565b60ff8181168382160190811115610d6157610d61615659565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b0380841680615aa157615aa1615702565b92169190910492915050565b600060208284031215615abf57600080fd5b610d5e826143d6565b6000808335601e19843603018112615adf57600080fd5b8301803591506001600160401b03821115615af957600080fd5b6020019150368190038213156140be57600080fd5b6020810160068310615b2257615b22614329565b91905290565b60ff818116838216029081169081811461568f5761568f615659565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b9c5784546001600160a01b031683526001948501949284019201615b77565b50508481036060860152865180825290820192508187019060005b81811015615bdc5782516001600160a01b031685529383019391830191600101615bb7565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614d1a606083018461402d565b8281526040602082015260006136cf604083018461402d565b6001600160401b03848116825283166020820152606081016136cf604083018461433f565b848152615c70602082018561433f565b608060408201526000615c86608083018561402d565b905082606083015295945050505050565b600060208284031215615ca957600080fd5b8151613c6b81613e24565b6020815260008251610100806020850152615cd361012085018361402d565b91506020850151615cef60408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615d2960a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d46848361402d565b935060c08701519150808685030160e0870152615d63848361402d565b935060e0870151915080868503018387015250615bec838261402d565b600060208284031215615d9257600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561537d57601f19868403018952815160a08151818652615ddc8287018261402d565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615e18838261402d565b6080948501519790940196909652505098840198925090830190600101615db6565b602081526000610d5e6020830184615d99565b60008282518085526020808601955060208260051b8401016020860160005b8481101561537d57601f19868403018952615e8883835161402d565b98840198925090830190600101615e6c565b60008151808452602080850194506020840160005b83811015614ca357815163ffffffff1687529582019590820190600101615eaf565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615f396101a085018361402d565b91506040870151605f198086850301610120870152615f58848361402d565b935060608901519150615f75838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615f9e8282615d99565b9150508281036020840152615fb38186615e4d565b90508281036040840152615bec8185615e9a56fea164736f6c6343000818000a", +} + +var OffRampABI = OffRampMetaData.ABI + +var OffRampBin = OffRampMetaData.Bin + +func DeployOffRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig OffRampStaticConfig, dynamicConfig OffRampDynamicConfig, sourceChainConfigs []OffRampSourceChainConfigArgs) (common.Address, *types.Transaction, *OffRamp, error) { + parsed, err := OffRampMetaData.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(OffRampBin), backend, staticConfig, dynamicConfig, sourceChainConfigs) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OffRamp{address: address, abi: *parsed, OffRampCaller: OffRampCaller{contract: contract}, OffRampTransactor: OffRampTransactor{contract: contract}, OffRampFilterer: OffRampFilterer{contract: contract}}, nil +} + +type OffRamp struct { + address common.Address + abi abi.ABI + OffRampCaller + OffRampTransactor + OffRampFilterer +} + +type OffRampCaller struct { + contract *bind.BoundContract +} + +type OffRampTransactor struct { + contract *bind.BoundContract +} + +type OffRampFilterer struct { + contract *bind.BoundContract +} + +type OffRampSession struct { + Contract *OffRamp + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OffRampCallerSession struct { + Contract *OffRampCaller + CallOpts bind.CallOpts +} + +type OffRampTransactorSession struct { + Contract *OffRampTransactor + TransactOpts bind.TransactOpts +} + +type OffRampRaw struct { + Contract *OffRamp +} + +type OffRampCallerRaw struct { + Contract *OffRampCaller +} + +type OffRampTransactorRaw struct { + Contract *OffRampTransactor +} + +func NewOffRamp(address common.Address, backend bind.ContractBackend) (*OffRamp, error) { + abi, err := abi.JSON(strings.NewReader(OffRampABI)) + if err != nil { + return nil, err + } + contract, err := bindOffRamp(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OffRamp{address: address, abi: abi, OffRampCaller: OffRampCaller{contract: contract}, OffRampTransactor: OffRampTransactor{contract: contract}, OffRampFilterer: OffRampFilterer{contract: contract}}, nil +} + +func NewOffRampCaller(address common.Address, caller bind.ContractCaller) (*OffRampCaller, error) { + contract, err := bindOffRamp(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OffRampCaller{contract: contract}, nil +} + +func NewOffRampTransactor(address common.Address, transactor bind.ContractTransactor) (*OffRampTransactor, error) { + contract, err := bindOffRamp(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OffRampTransactor{contract: contract}, nil +} + +func NewOffRampFilterer(address common.Address, filterer bind.ContractFilterer) (*OffRampFilterer, error) { + contract, err := bindOffRamp(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OffRampFilterer{contract: contract}, nil +} + +func bindOffRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OffRampMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_OffRamp *OffRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OffRamp.Contract.OffRampCaller.contract.Call(opts, result, method, params...) +} + +func (_OffRamp *OffRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OffRamp.Contract.OffRampTransactor.contract.Transfer(opts) +} + +func (_OffRamp *OffRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OffRamp.Contract.OffRampTransactor.contract.Transact(opts, method, params...) +} + +func (_OffRamp *OffRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OffRamp.Contract.contract.Call(opts, result, method, params...) +} + +func (_OffRamp *OffRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OffRamp.Contract.contract.Transfer(opts) +} + +func (_OffRamp *OffRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OffRamp.Contract.contract.Transact(opts, method, params...) +} + +func (_OffRamp *OffRampCaller) CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "ccipReceive", arg0) + + if err != nil { + return err + } + + return err + +} + +func (_OffRamp *OffRampSession) CcipReceive(arg0 ClientAny2EVMMessage) error { + return _OffRamp.Contract.CcipReceive(&_OffRamp.CallOpts, arg0) +} + +func (_OffRamp *OffRampCallerSession) CcipReceive(arg0 ClientAny2EVMMessage) error { + return _OffRamp.Contract.CcipReceive(&_OffRamp.CallOpts, arg0) +} + +func (_OffRamp *OffRampCaller) GetAllSourceChainConfigs(opts *bind.CallOpts) ([]uint64, []OffRampSourceChainConfig, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getAllSourceChainConfigs") + + if err != nil { + return *new([]uint64), *new([]OffRampSourceChainConfig), err + } + + out0 := *abi.ConvertType(out[0], new([]uint64)).(*[]uint64) + out1 := *abi.ConvertType(out[1], new([]OffRampSourceChainConfig)).(*[]OffRampSourceChainConfig) + + return out0, out1, err + +} + +func (_OffRamp *OffRampSession) GetAllSourceChainConfigs() ([]uint64, []OffRampSourceChainConfig, error) { + return _OffRamp.Contract.GetAllSourceChainConfigs(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCallerSession) GetAllSourceChainConfigs() ([]uint64, []OffRampSourceChainConfig, error) { + return _OffRamp.Contract.GetAllSourceChainConfigs(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCaller) GetDynamicConfig(opts *bind.CallOpts) (OffRampDynamicConfig, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getDynamicConfig") + + if err != nil { + return *new(OffRampDynamicConfig), err + } + + out0 := *abi.ConvertType(out[0], new(OffRampDynamicConfig)).(*OffRampDynamicConfig) + + return out0, err + +} + +func (_OffRamp *OffRampSession) GetDynamicConfig() (OffRampDynamicConfig, error) { + return _OffRamp.Contract.GetDynamicConfig(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCallerSession) GetDynamicConfig() (OffRampDynamicConfig, error) { + return _OffRamp.Contract.GetDynamicConfig(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCaller) GetExecutionState(opts *bind.CallOpts, sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getExecutionState", sourceChainSelector, sequenceNumber) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_OffRamp *OffRampSession) GetExecutionState(sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) { + return _OffRamp.Contract.GetExecutionState(&_OffRamp.CallOpts, sourceChainSelector, sequenceNumber) +} + +func (_OffRamp *OffRampCallerSession) GetExecutionState(sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) { + return _OffRamp.Contract.GetExecutionState(&_OffRamp.CallOpts, sourceChainSelector, sequenceNumber) +} + +func (_OffRamp *OffRampCaller) GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getLatestPriceSequenceNumber") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_OffRamp *OffRampSession) GetLatestPriceSequenceNumber() (uint64, error) { + return _OffRamp.Contract.GetLatestPriceSequenceNumber(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCallerSession) GetLatestPriceSequenceNumber() (uint64, error) { + return _OffRamp.Contract.GetLatestPriceSequenceNumber(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCaller) GetMerkleRoot(opts *bind.CallOpts, sourceChainSelector uint64, root [32]byte) (*big.Int, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getMerkleRoot", sourceChainSelector, root) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_OffRamp *OffRampSession) GetMerkleRoot(sourceChainSelector uint64, root [32]byte) (*big.Int, error) { + return _OffRamp.Contract.GetMerkleRoot(&_OffRamp.CallOpts, sourceChainSelector, root) +} + +func (_OffRamp *OffRampCallerSession) GetMerkleRoot(sourceChainSelector uint64, root [32]byte) (*big.Int, error) { + return _OffRamp.Contract.GetMerkleRoot(&_OffRamp.CallOpts, sourceChainSelector, root) +} + +func (_OffRamp *OffRampCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) + + if err != nil { + return *new(OffRampSourceChainConfig), err + } + + out0 := *abi.ConvertType(out[0], new(OffRampSourceChainConfig)).(*OffRampSourceChainConfig) + + return out0, err + +} + +func (_OffRamp *OffRampSession) GetSourceChainConfig(sourceChainSelector uint64) (OffRampSourceChainConfig, error) { + return _OffRamp.Contract.GetSourceChainConfig(&_OffRamp.CallOpts, sourceChainSelector) +} + +func (_OffRamp *OffRampCallerSession) GetSourceChainConfig(sourceChainSelector uint64) (OffRampSourceChainConfig, error) { + return _OffRamp.Contract.GetSourceChainConfig(&_OffRamp.CallOpts, sourceChainSelector) +} + +func (_OffRamp *OffRampCaller) GetStaticConfig(opts *bind.CallOpts) (OffRampStaticConfig, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "getStaticConfig") + + if err != nil { + return *new(OffRampStaticConfig), err + } + + out0 := *abi.ConvertType(out[0], new(OffRampStaticConfig)).(*OffRampStaticConfig) + + return out0, err + +} + +func (_OffRamp *OffRampSession) GetStaticConfig() (OffRampStaticConfig, error) { + return _OffRamp.Contract.GetStaticConfig(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCallerSession) GetStaticConfig() (OffRampStaticConfig, error) { + return _OffRamp.Contract.GetStaticConfig(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCaller) LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "latestConfigDetails", ocrPluginType) + + if err != nil { + return *new(MultiOCR3BaseOCRConfig), err + } + + out0 := *abi.ConvertType(out[0], new(MultiOCR3BaseOCRConfig)).(*MultiOCR3BaseOCRConfig) + + return out0, err + +} + +func (_OffRamp *OffRampSession) LatestConfigDetails(ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { + return _OffRamp.Contract.LatestConfigDetails(&_OffRamp.CallOpts, ocrPluginType) +} + +func (_OffRamp *OffRampCallerSession) LatestConfigDetails(ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { + return _OffRamp.Contract.LatestConfigDetails(&_OffRamp.CallOpts, ocrPluginType) +} + +func (_OffRamp *OffRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OffRamp.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 (_OffRamp *OffRampSession) Owner() (common.Address, error) { + return _OffRamp.Contract.Owner(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCallerSession) Owner() (common.Address, error) { + return _OffRamp.Contract.Owner(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _OffRamp.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_OffRamp *OffRampSession) TypeAndVersion() (string, error) { + return _OffRamp.Contract.TypeAndVersion(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampCallerSession) TypeAndVersion() (string, error) { + return _OffRamp.Contract.TypeAndVersion(&_OffRamp.CallOpts) +} + +func (_OffRamp *OffRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "acceptOwnership") +} + +func (_OffRamp *OffRampSession) AcceptOwnership() (*types.Transaction, error) { + return _OffRamp.Contract.AcceptOwnership(&_OffRamp.TransactOpts) +} + +func (_OffRamp *OffRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _OffRamp.Contract.AcceptOwnership(&_OffRamp.TransactOpts) +} + +func (_OffRamp *OffRampTransactor) ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "applySourceChainConfigUpdates", sourceChainConfigUpdates) +} + +func (_OffRamp *OffRampSession) ApplySourceChainConfigUpdates(sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) { + return _OffRamp.Contract.ApplySourceChainConfigUpdates(&_OffRamp.TransactOpts, sourceChainConfigUpdates) +} + +func (_OffRamp *OffRampTransactorSession) ApplySourceChainConfigUpdates(sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) { + return _OffRamp.Contract.ApplySourceChainConfigUpdates(&_OffRamp.TransactOpts, sourceChainConfigUpdates) +} + +func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "commit", reportContext, report, rs, ss, rawVs) +} + +func (_OffRamp *OffRampSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_OffRamp *OffRampTransactorSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "execute", reportContext, report) +} + +func (_OffRamp *OffRampSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { + return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) +} + +func (_OffRamp *OffRampTransactorSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { + return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) +} + +func (_OffRamp *OffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData, tokenGasOverrides) +} + +func (_OffRamp *OffRampSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _OffRamp.Contract.ExecuteSingleMessage(&_OffRamp.TransactOpts, message, offchainTokenData, tokenGasOverrides) +} + +func (_OffRamp *OffRampTransactorSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _OffRamp.Contract.ExecuteSingleMessage(&_OffRamp.TransactOpts, message, offchainTokenData, tokenGasOverrides) +} + +func (_OffRamp *OffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReport, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "manuallyExecute", reports, gasLimitOverrides) +} + +func (_OffRamp *OffRampSession) ManuallyExecute(reports []InternalExecutionReport, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) { + return _OffRamp.Contract.ManuallyExecute(&_OffRamp.TransactOpts, reports, gasLimitOverrides) +} + +func (_OffRamp *OffRampTransactorSession) ManuallyExecute(reports []InternalExecutionReport, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) { + return _OffRamp.Contract.ManuallyExecute(&_OffRamp.TransactOpts, reports, gasLimitOverrides) +} + +func (_OffRamp *OffRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) +} + +func (_OffRamp *OffRampSession) SetDynamicConfig(dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) { + return _OffRamp.Contract.SetDynamicConfig(&_OffRamp.TransactOpts, dynamicConfig) +} + +func (_OffRamp *OffRampTransactorSession) SetDynamicConfig(dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) { + return _OffRamp.Contract.SetDynamicConfig(&_OffRamp.TransactOpts, dynamicConfig) +} + +func (_OffRamp *OffRampTransactor) SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "setOCR3Configs", ocrConfigArgs) +} + +func (_OffRamp *OffRampSession) SetOCR3Configs(ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { + return _OffRamp.Contract.SetOCR3Configs(&_OffRamp.TransactOpts, ocrConfigArgs) +} + +func (_OffRamp *OffRampTransactorSession) SetOCR3Configs(ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { + return _OffRamp.Contract.SetOCR3Configs(&_OffRamp.TransactOpts, ocrConfigArgs) +} + +func (_OffRamp *OffRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "transferOwnership", to) +} + +func (_OffRamp *OffRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OffRamp.Contract.TransferOwnership(&_OffRamp.TransactOpts, to) +} + +func (_OffRamp *OffRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OffRamp.Contract.TransferOwnership(&_OffRamp.TransactOpts, to) +} + +type OffRampAlreadyAttemptedIterator struct { + Event *OffRampAlreadyAttempted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampAlreadyAttemptedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampAlreadyAttempted) + 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(OffRampAlreadyAttempted) + 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 *OffRampAlreadyAttemptedIterator) Error() error { + return it.fail +} + +func (it *OffRampAlreadyAttemptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampAlreadyAttempted struct { + SourceChainSelector uint64 + SequenceNumber uint64 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterAlreadyAttempted(opts *bind.FilterOpts) (*OffRampAlreadyAttemptedIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "AlreadyAttempted") + if err != nil { + return nil, err + } + return &OffRampAlreadyAttemptedIterator{contract: _OffRamp.contract, event: "AlreadyAttempted", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchAlreadyAttempted(opts *bind.WatchOpts, sink chan<- *OffRampAlreadyAttempted) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "AlreadyAttempted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampAlreadyAttempted) + if err := _OffRamp.contract.UnpackLog(event, "AlreadyAttempted", 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 (_OffRamp *OffRampFilterer) ParseAlreadyAttempted(log types.Log) (*OffRampAlreadyAttempted, error) { + event := new(OffRampAlreadyAttempted) + if err := _OffRamp.contract.UnpackLog(event, "AlreadyAttempted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampCommitReportAcceptedIterator struct { + Event *OffRampCommitReportAccepted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampCommitReportAcceptedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampCommitReportAccepted) + 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(OffRampCommitReportAccepted) + 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 *OffRampCommitReportAcceptedIterator) Error() error { + return it.fail +} + +func (it *OffRampCommitReportAcceptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampCommitReportAccepted struct { + MerkleRoots []InternalMerkleRoot + PriceUpdates InternalPriceUpdates + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterCommitReportAccepted(opts *bind.FilterOpts) (*OffRampCommitReportAcceptedIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "CommitReportAccepted") + if err != nil { + return nil, err + } + return &OffRampCommitReportAcceptedIterator{contract: _OffRamp.contract, event: "CommitReportAccepted", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *OffRampCommitReportAccepted) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "CommitReportAccepted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampCommitReportAccepted) + if err := _OffRamp.contract.UnpackLog(event, "CommitReportAccepted", 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 (_OffRamp *OffRampFilterer) ParseCommitReportAccepted(log types.Log) (*OffRampCommitReportAccepted, error) { + event := new(OffRampCommitReportAccepted) + if err := _OffRamp.contract.UnpackLog(event, "CommitReportAccepted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampConfigSetIterator struct { + Event *OffRampConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampConfigSet) + 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(OffRampConfigSet) + 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 *OffRampConfigSetIterator) Error() error { + return it.fail +} + +func (it *OffRampConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampConfigSet struct { + OcrPluginType uint8 + ConfigDigest [32]byte + Signers []common.Address + Transmitters []common.Address + F uint8 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*OffRampConfigSetIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &OffRampConfigSetIterator{contract: _OffRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampConfigSet) (event.Subscription, error) { + + logs, sub, err := _OffRamp.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(OffRampConfigSet) + if err := _OffRamp.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 (_OffRamp *OffRampFilterer) ParseConfigSet(log types.Log) (*OffRampConfigSet, error) { + event := new(OffRampConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampDynamicConfigSetIterator struct { + Event *OffRampDynamicConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampDynamicConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampDynamicConfigSet) + 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(OffRampDynamicConfigSet) + 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 *OffRampDynamicConfigSetIterator) Error() error { + return it.fail +} + +func (it *OffRampDynamicConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampDynamicConfigSet struct { + DynamicConfig OffRampDynamicConfig + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterDynamicConfigSet(opts *bind.FilterOpts) (*OffRampDynamicConfigSetIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "DynamicConfigSet") + if err != nil { + return nil, err + } + return &OffRampDynamicConfigSetIterator{contract: _OffRamp.contract, event: "DynamicConfigSet", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampDynamicConfigSet) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "DynamicConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampDynamicConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "DynamicConfigSet", 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 (_OffRamp *OffRampFilterer) ParseDynamicConfigSet(log types.Log) (*OffRampDynamicConfigSet, error) { + event := new(OffRampDynamicConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "DynamicConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampExecutionStateChangedIterator struct { + Event *OffRampExecutionStateChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampExecutionStateChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampExecutionStateChanged) + 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(OffRampExecutionStateChanged) + 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 *OffRampExecutionStateChangedIterator) Error() error { + return it.fail +} + +func (it *OffRampExecutionStateChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampExecutionStateChanged struct { + SourceChainSelector uint64 + SequenceNumber uint64 + MessageId [32]byte + MessageHash [32]byte + State uint8 + ReturnData []byte + GasUsed *big.Int + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*OffRampExecutionStateChangedIterator, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) + if err != nil { + return nil, err + } + return &OffRampExecutionStateChangedIterator{contract: _OffRamp.contract, event: "ExecutionStateChanged", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *OffRampExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampExecutionStateChanged) + if err := _OffRamp.contract.UnpackLog(event, "ExecutionStateChanged", 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 (_OffRamp *OffRampFilterer) ParseExecutionStateChanged(log types.Log) (*OffRampExecutionStateChanged, error) { + event := new(OffRampExecutionStateChanged) + if err := _OffRamp.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampOwnershipTransferRequestedIterator struct { + Event *OffRampOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampOwnershipTransferRequested) + 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(OffRampOwnershipTransferRequested) + 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 *OffRampOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *OffRampOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OffRampOwnershipTransferRequestedIterator, 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 := _OffRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &OffRampOwnershipTransferRequestedIterator{contract: _OffRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OffRampOwnershipTransferRequested, 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 := _OffRamp.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(OffRampOwnershipTransferRequested) + if err := _OffRamp.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 (_OffRamp *OffRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*OffRampOwnershipTransferRequested, error) { + event := new(OffRampOwnershipTransferRequested) + if err := _OffRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampOwnershipTransferredIterator struct { + Event *OffRampOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampOwnershipTransferred) + 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(OffRampOwnershipTransferred) + 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 *OffRampOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *OffRampOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OffRampOwnershipTransferredIterator, 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 := _OffRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &OffRampOwnershipTransferredIterator{contract: _OffRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OffRampOwnershipTransferred, 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 := _OffRamp.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(OffRampOwnershipTransferred) + if err := _OffRamp.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 (_OffRamp *OffRampFilterer) ParseOwnershipTransferred(log types.Log) (*OffRampOwnershipTransferred, error) { + event := new(OffRampOwnershipTransferred) + if err := _OffRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampRootRemovedIterator struct { + Event *OffRampRootRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampRootRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampRootRemoved) + 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(OffRampRootRemoved) + 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 *OffRampRootRemovedIterator) Error() error { + return it.fail +} + +func (it *OffRampRootRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampRootRemoved struct { + Root [32]byte + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterRootRemoved(opts *bind.FilterOpts) (*OffRampRootRemovedIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "RootRemoved") + if err != nil { + return nil, err + } + return &OffRampRootRemovedIterator{contract: _OffRamp.contract, event: "RootRemoved", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *OffRampRootRemoved) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "RootRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampRootRemoved) + if err := _OffRamp.contract.UnpackLog(event, "RootRemoved", 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 (_OffRamp *OffRampFilterer) ParseRootRemoved(log types.Log) (*OffRampRootRemoved, error) { + event := new(OffRampRootRemoved) + if err := _OffRamp.contract.UnpackLog(event, "RootRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampSkippedAlreadyExecutedMessageIterator struct { + Event *OffRampSkippedAlreadyExecutedMessage + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampSkippedAlreadyExecutedMessageIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampSkippedAlreadyExecutedMessage) + 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(OffRampSkippedAlreadyExecutedMessage) + 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 *OffRampSkippedAlreadyExecutedMessageIterator) Error() error { + return it.fail +} + +func (it *OffRampSkippedAlreadyExecutedMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampSkippedAlreadyExecutedMessage struct { + SourceChainSelector uint64 + SequenceNumber uint64 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterSkippedAlreadyExecutedMessage(opts *bind.FilterOpts) (*OffRampSkippedAlreadyExecutedMessageIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "SkippedAlreadyExecutedMessage") + if err != nil { + return nil, err + } + return &OffRampSkippedAlreadyExecutedMessageIterator{contract: _OffRamp.contract, event: "SkippedAlreadyExecutedMessage", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchSkippedAlreadyExecutedMessage(opts *bind.WatchOpts, sink chan<- *OffRampSkippedAlreadyExecutedMessage) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "SkippedAlreadyExecutedMessage") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampSkippedAlreadyExecutedMessage) + if err := _OffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", 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 (_OffRamp *OffRampFilterer) ParseSkippedAlreadyExecutedMessage(log types.Log) (*OffRampSkippedAlreadyExecutedMessage, error) { + event := new(OffRampSkippedAlreadyExecutedMessage) + if err := _OffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampSkippedReportExecutionIterator struct { + Event *OffRampSkippedReportExecution + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampSkippedReportExecutionIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampSkippedReportExecution) + 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(OffRampSkippedReportExecution) + 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 *OffRampSkippedReportExecutionIterator) Error() error { + return it.fail +} + +func (it *OffRampSkippedReportExecutionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampSkippedReportExecution struct { + SourceChainSelector uint64 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterSkippedReportExecution(opts *bind.FilterOpts) (*OffRampSkippedReportExecutionIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "SkippedReportExecution") + if err != nil { + return nil, err + } + return &OffRampSkippedReportExecutionIterator{contract: _OffRamp.contract, event: "SkippedReportExecution", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchSkippedReportExecution(opts *bind.WatchOpts, sink chan<- *OffRampSkippedReportExecution) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "SkippedReportExecution") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampSkippedReportExecution) + if err := _OffRamp.contract.UnpackLog(event, "SkippedReportExecution", 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 (_OffRamp *OffRampFilterer) ParseSkippedReportExecution(log types.Log) (*OffRampSkippedReportExecution, error) { + event := new(OffRampSkippedReportExecution) + if err := _OffRamp.contract.UnpackLog(event, "SkippedReportExecution", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampSourceChainConfigSetIterator struct { + Event *OffRampSourceChainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampSourceChainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampSourceChainConfigSet) + 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(OffRampSourceChainConfigSet) + 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 *OffRampSourceChainConfigSetIterator) Error() error { + return it.fail +} + +func (it *OffRampSourceChainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampSourceChainConfigSet struct { + SourceChainSelector uint64 + SourceConfig OffRampSourceChainConfig + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*OffRampSourceChainConfigSetIterator, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) + if err != nil { + return nil, err + } + return &OffRampSourceChainConfigSetIterator{contract: _OffRamp.contract, event: "SourceChainConfigSet", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampSourceChainConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "SourceChainConfigSet", 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 (_OffRamp *OffRampFilterer) ParseSourceChainConfigSet(log types.Log) (*OffRampSourceChainConfigSet, error) { + event := new(OffRampSourceChainConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "SourceChainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampSourceChainSelectorAddedIterator struct { + Event *OffRampSourceChainSelectorAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampSourceChainSelectorAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampSourceChainSelectorAdded) + 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(OffRampSourceChainSelectorAdded) + 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 *OffRampSourceChainSelectorAddedIterator) Error() error { + return it.fail +} + +func (it *OffRampSourceChainSelectorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampSourceChainSelectorAdded struct { + SourceChainSelector uint64 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterSourceChainSelectorAdded(opts *bind.FilterOpts) (*OffRampSourceChainSelectorAddedIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "SourceChainSelectorAdded") + if err != nil { + return nil, err + } + return &OffRampSourceChainSelectorAddedIterator{contract: _OffRamp.contract, event: "SourceChainSelectorAdded", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchSourceChainSelectorAdded(opts *bind.WatchOpts, sink chan<- *OffRampSourceChainSelectorAdded) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "SourceChainSelectorAdded") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampSourceChainSelectorAdded) + if err := _OffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", 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 (_OffRamp *OffRampFilterer) ParseSourceChainSelectorAdded(log types.Log) (*OffRampSourceChainSelectorAdded, error) { + event := new(OffRampSourceChainSelectorAdded) + if err := _OffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampStaticConfigSetIterator struct { + Event *OffRampStaticConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampStaticConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampStaticConfigSet) + 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(OffRampStaticConfigSet) + 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 *OffRampStaticConfigSetIterator) Error() error { + return it.fail +} + +func (it *OffRampStaticConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampStaticConfigSet struct { + StaticConfig OffRampStaticConfig + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterStaticConfigSet(opts *bind.FilterOpts) (*OffRampStaticConfigSetIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "StaticConfigSet") + if err != nil { + return nil, err + } + return &OffRampStaticConfigSetIterator{contract: _OffRamp.contract, event: "StaticConfigSet", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchStaticConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampStaticConfigSet) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "StaticConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampStaticConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "StaticConfigSet", 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 (_OffRamp *OffRampFilterer) ParseStaticConfigSet(log types.Log) (*OffRampStaticConfigSet, error) { + event := new(OffRampStaticConfigSet) + if err := _OffRamp.contract.UnpackLog(event, "StaticConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OffRampTransmittedIterator struct { + Event *OffRampTransmitted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampTransmittedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampTransmitted) + 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(OffRampTransmitted) + 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 *OffRampTransmittedIterator) Error() error { + return it.fail +} + +func (it *OffRampTransmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampTransmitted struct { + OcrPluginType uint8 + ConfigDigest [32]byte + SequenceNumber uint64 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*OffRampTransmittedIterator, error) { + + var ocrPluginTypeRule []interface{} + for _, ocrPluginTypeItem := range ocrPluginType { + ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) + } + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "Transmitted", ocrPluginTypeRule) + if err != nil { + return nil, err + } + return &OffRampTransmittedIterator{contract: _OffRamp.contract, event: "Transmitted", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *OffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) { + + var ocrPluginTypeRule []interface{} + for _, ocrPluginTypeItem := range ocrPluginType { + ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) + } + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "Transmitted", ocrPluginTypeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampTransmitted) + if err := _OffRamp.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 (_OffRamp *OffRampFilterer) ParseTransmitted(log types.Log) (*OffRampTransmitted, error) { + event := new(OffRampTransmitted) + if err := _OffRamp.contract.UnpackLog(event, "Transmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_OffRamp *OffRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _OffRamp.abi.Events["AlreadyAttempted"].ID: + return _OffRamp.ParseAlreadyAttempted(log) + case _OffRamp.abi.Events["CommitReportAccepted"].ID: + return _OffRamp.ParseCommitReportAccepted(log) + case _OffRamp.abi.Events["ConfigSet"].ID: + return _OffRamp.ParseConfigSet(log) + case _OffRamp.abi.Events["DynamicConfigSet"].ID: + return _OffRamp.ParseDynamicConfigSet(log) + case _OffRamp.abi.Events["ExecutionStateChanged"].ID: + return _OffRamp.ParseExecutionStateChanged(log) + case _OffRamp.abi.Events["OwnershipTransferRequested"].ID: + return _OffRamp.ParseOwnershipTransferRequested(log) + case _OffRamp.abi.Events["OwnershipTransferred"].ID: + return _OffRamp.ParseOwnershipTransferred(log) + case _OffRamp.abi.Events["RootRemoved"].ID: + return _OffRamp.ParseRootRemoved(log) + case _OffRamp.abi.Events["SkippedAlreadyExecutedMessage"].ID: + return _OffRamp.ParseSkippedAlreadyExecutedMessage(log) + case _OffRamp.abi.Events["SkippedReportExecution"].ID: + return _OffRamp.ParseSkippedReportExecution(log) + case _OffRamp.abi.Events["SourceChainConfigSet"].ID: + return _OffRamp.ParseSourceChainConfigSet(log) + case _OffRamp.abi.Events["SourceChainSelectorAdded"].ID: + return _OffRamp.ParseSourceChainSelectorAdded(log) + case _OffRamp.abi.Events["StaticConfigSet"].ID: + return _OffRamp.ParseStaticConfigSet(log) + case _OffRamp.abi.Events["Transmitted"].ID: + return _OffRamp.ParseTransmitted(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OffRampAlreadyAttempted) Topic() common.Hash { + return common.HexToHash("0x3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120") +} + +func (OffRampCommitReportAccepted) Topic() common.Hash { + return common.HexToHash("0x35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4") +} + +func (OffRampConfigSet) Topic() common.Hash { + return common.HexToHash("0xab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547") +} + +func (OffRampDynamicConfigSet) Topic() common.Hash { + return common.HexToHash("0xa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d") +} + +func (OffRampExecutionStateChanged) Topic() common.Hash { + return common.HexToHash("0x05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b") +} + +func (OffRampOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (OffRampOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (OffRampRootRemoved) Topic() common.Hash { + return common.HexToHash("0x202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12") +} + +func (OffRampSkippedAlreadyExecutedMessage) Topic() common.Hash { + return common.HexToHash("0x3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c") +} + +func (OffRampSkippedReportExecution) Topic() common.Hash { + return common.HexToHash("0xaab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d894933") +} + +func (OffRampSourceChainConfigSet) Topic() common.Hash { + return common.HexToHash("0x49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b") +} + +func (OffRampSourceChainSelectorAdded) Topic() common.Hash { + return common.HexToHash("0xf4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb9") +} + +func (OffRampStaticConfigSet) Topic() common.Hash { + return common.HexToHash("0x683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d8") +} + +func (OffRampTransmitted) Topic() common.Hash { + return common.HexToHash("0x198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0") +} + +func (_OffRamp *OffRamp) Address() common.Address { + return _OffRamp.address +} + +type OffRampInterface interface { + CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error + + GetAllSourceChainConfigs(opts *bind.CallOpts) ([]uint64, []OffRampSourceChainConfig, error) + + GetDynamicConfig(opts *bind.CallOpts) (OffRampDynamicConfig, error) + + GetExecutionState(opts *bind.CallOpts, sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) + + GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) + + GetMerkleRoot(opts *bind.CallOpts, sourceChainSelector uint64, root [32]byte) (*big.Int, error) + + GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) + + GetStaticConfig(opts *bind.CallOpts) (OffRampStaticConfig, error) + + LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) + + Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + + Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) + + ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) + + ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReport, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) + + SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) + + SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterAlreadyAttempted(opts *bind.FilterOpts) (*OffRampAlreadyAttemptedIterator, error) + + WatchAlreadyAttempted(opts *bind.WatchOpts, sink chan<- *OffRampAlreadyAttempted) (event.Subscription, error) + + ParseAlreadyAttempted(log types.Log) (*OffRampAlreadyAttempted, error) + + FilterCommitReportAccepted(opts *bind.FilterOpts) (*OffRampCommitReportAcceptedIterator, error) + + WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *OffRampCommitReportAccepted) (event.Subscription, error) + + ParseCommitReportAccepted(log types.Log) (*OffRampCommitReportAccepted, error) + + FilterConfigSet(opts *bind.FilterOpts) (*OffRampConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*OffRampConfigSet, error) + + FilterDynamicConfigSet(opts *bind.FilterOpts) (*OffRampDynamicConfigSetIterator, error) + + WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampDynamicConfigSet) (event.Subscription, error) + + ParseDynamicConfigSet(log types.Log) (*OffRampDynamicConfigSet, error) + + FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*OffRampExecutionStateChangedIterator, error) + + WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *OffRampExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) + + ParseExecutionStateChanged(log types.Log) (*OffRampExecutionStateChanged, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OffRampOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OffRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*OffRampOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OffRampOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OffRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*OffRampOwnershipTransferred, error) + + FilterRootRemoved(opts *bind.FilterOpts) (*OffRampRootRemovedIterator, error) + + WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *OffRampRootRemoved) (event.Subscription, error) + + ParseRootRemoved(log types.Log) (*OffRampRootRemoved, error) + + FilterSkippedAlreadyExecutedMessage(opts *bind.FilterOpts) (*OffRampSkippedAlreadyExecutedMessageIterator, error) + + WatchSkippedAlreadyExecutedMessage(opts *bind.WatchOpts, sink chan<- *OffRampSkippedAlreadyExecutedMessage) (event.Subscription, error) + + ParseSkippedAlreadyExecutedMessage(log types.Log) (*OffRampSkippedAlreadyExecutedMessage, error) + + FilterSkippedReportExecution(opts *bind.FilterOpts) (*OffRampSkippedReportExecutionIterator, error) + + WatchSkippedReportExecution(opts *bind.WatchOpts, sink chan<- *OffRampSkippedReportExecution) (event.Subscription, error) + + ParseSkippedReportExecution(log types.Log) (*OffRampSkippedReportExecution, error) + + FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*OffRampSourceChainConfigSetIterator, error) + + WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) + + ParseSourceChainConfigSet(log types.Log) (*OffRampSourceChainConfigSet, error) + + FilterSourceChainSelectorAdded(opts *bind.FilterOpts) (*OffRampSourceChainSelectorAddedIterator, error) + + WatchSourceChainSelectorAdded(opts *bind.WatchOpts, sink chan<- *OffRampSourceChainSelectorAdded) (event.Subscription, error) + + ParseSourceChainSelectorAdded(log types.Log) (*OffRampSourceChainSelectorAdded, error) + + FilterStaticConfigSet(opts *bind.FilterOpts) (*OffRampStaticConfigSetIterator, error) + + WatchStaticConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampStaticConfigSet) (event.Subscription, error) + + ParseStaticConfigSet(log types.Log) (*OffRampStaticConfigSet, error) + + FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*OffRampTransmittedIterator, error) + + WatchTransmitted(opts *bind.WatchOpts, sink chan<- *OffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) + + ParseTransmitted(log types.Log) (*OffRampTransmitted, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go new file mode 100644 index 00000000000..9a7ca14fc59 --- /dev/null +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -0,0 +1,1937 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package onramp + +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 ClientEVM2AnyMessage struct { + Receiver []byte + Data []byte + TokenAmounts []ClientEVMTokenAmount + FeeToken common.Address + ExtraArgs []byte +} + +type ClientEVMTokenAmount struct { + Token common.Address + Amount *big.Int +} + +type InternalEVM2AnyRampMessage struct { + Header InternalRampMessageHeader + Sender common.Address + Data []byte + Receiver []byte + ExtraArgs []byte + FeeToken common.Address + FeeTokenAmount *big.Int + FeeValueJuels *big.Int + TokenAmounts []InternalEVM2AnyTokenTransfer +} + +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte +} + +type InternalRampMessageHeader struct { + MessageId [32]byte + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + +type OnRampAllowlistConfigArgs struct { + DestChainSelector uint64 + AllowlistEnabled bool + AddedAllowlistedSenders []common.Address + RemovedAllowlistedSenders []common.Address +} + +type OnRampDestChainConfigArgs struct { + DestChainSelector uint64 + Router common.Address + AllowlistEnabled bool +} + +type OnRampDynamicConfig struct { + FeeQuoter common.Address + ReentrancyGuardEntered bool + MessageInterceptor common.Address + FeeAggregator common.Address + AllowlistAdmin common.Address +} + +type OnRampStaticConfig struct { + ChainSelector uint64 + RmnRemote common.Address + NonceManager common.Address + TokenAdminRegistry common.Address +} + +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\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"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\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"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\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"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\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620043173803806200431783398101604081905262000035916200076e565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b5050506200086f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200053057600082828151811062000404576200040462000859565b60200260200101519050600083838151811062000425576200042562000859565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b0381811660008181526006602090815260409182902086820151815488850151600160401b600160e81b031990911669010000000000000000006001600160a01b0390931692830260ff60401b19161768010000000000000000911515820217808455855197811688529387019190915260ff920491909116151591840191909152917fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200056f576200056f62000534565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620005a057620005a062000534565b604052919050565b80516001600160401b0381168114620005c057600080fd5b919050565b6001600160a01b0381168114620005db57600080fd5b50565b80518015158114620005c057600080fd5b600060a082840312156200060257600080fd5b60405160a081016001600160401b038111828210171562000627576200062762000534565b806040525080915082516200063c81620005c5565b81526200064c60208401620005de565b602082015260408301516200066181620005c5565b604082015260608301516200067681620005c5565b606082015260808301516200068b81620005c5565b6080919091015292915050565b600082601f830112620006aa57600080fd5b815160206001600160401b03821115620006c857620006c862000534565b620006d8818360051b0162000575565b82815260609283028501820192828201919087851115620006f857600080fd5b8387015b85811015620007615781818a031215620007165760008081fd5b620007206200054a565b6200072b82620005a8565b8152858201516200073c81620005c5565b8187015260406200074f838201620005de565b908201528452928401928101620006fc565b5090979650505050505050565b60008060008385036101408112156200078657600080fd5b60808112156200079557600080fd5b50604051608081016001600160401b038082118383101715620007bc57620007bc62000534565b81604052620007cb87620005a8565b835260208701519150620007df82620005c5565b81602084015260408701519150620007f782620005c5565b816040840152606087015191506200080f82620005c5565b816060840152829550620008278860808901620005ef565b94506101208701519250808311156200083f57600080fd5b50506200084f8682870162000698565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613a2f620008e860003960008181610217015281816109f40152611c290152600081816101db015281816115ee0152611c0201526000818161019f015281816106020152611bd801526000818161016f015281816111750152818161170b0152611bb40152613a2f6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063c9b146b311610081578063df0aa9e911610066578063df0aa9e914610558578063f2fde38b1461056b578063fbca3b741461057e57600080fd5b8063c9b146b3146104f8578063d77d5ed01461050b57600080fd5b806379ba5097146104855780638da5cb5b1461048d5780639041be3d146104ab578063972b4612146104d757600080fd5b806327e936f11161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806327e936f1146102e95780633a019940146102fc57600080fd5b806306285c691461013b578063181f5a771461026a57806320487ded146102b35780632716072b146102d4575b600080fd5b61025460408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b604051610261919061271f565b60405180910390f35b6102a66040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b60405161026191906127e4565b6102c66102c1366004612825565b61059e565b604051908152602001610261565b6102e76102e2366004612993565b610757565b005b6102e76102f7366004612a81565b61076b565b6102e761077c565b610317610312366004612b19565b6109ac565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610261565b61039f61034a366004612b52565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610261565b6104786040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102619190612b6f565b6102e7610a61565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b6104be6104b9366004612b52565b610b5e565b60405167ffffffffffffffff9091168152602001610261565b6104ea6104e5366004612b52565b610b87565b604051610261929190612c1a565b6102e7610506366004612c35565b610bcb565b610317610519366004612b52565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102c6610566366004612caa565b610ee2565b6102e7610579366004612d16565b6117f0565b61059161058c366004612b52565b611801565b6040516102619190612d33565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190612d46565b156106b5576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd9061070d9086908690600401612e6c565b602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190612fb5565b90505b92915050565b61075f611835565b610768816118b8565b50565b610773611835565b61076881611a5b565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa1580156107eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108319190810190612fce565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b82518110156109a757600083828151811061086d5761086d61305d565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa1580156108e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090c9190612fb5565b9050801561099d5761093573ffffffffffffffffffffffffffffffffffffffff83168583611c8b565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161099491815260200190565b60405180910390a35b5050600101610850565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610a3d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e919061308c565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106ac565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120549091610751911660016130d8565b67ffffffffffffffff8116600090815260066020526040812080546060916801000000000000000090910460ff1690610bc290600101611d18565b91509150915091565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c3b5760055473ffffffffffffffffffffffffffffffffffffffff163314610c3b576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156109a7576000838383818110610c5a57610c5a61305d565b9050602002810190610c6c91906130f9565b610c75906131aa565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff90911617815590820151519192509015610e3557816020015115610df45760005b826040015151811015610da457600083604001518281518110610d0e57610d0e61305d565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d8d5783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106ac565b610d9a6001840182611d2c565b5050600101610ce9565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc32818360400151604051610de79190612d33565b60405180910390a2610e35565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106ac565b60005b826060015151811015610e8157610e7883606001518281518110610e5e57610e5e61305d565b602002602001015183600101611d4e90919063ffffffff16565b50600101610e38565b5060608201515115610ed857816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610ecf9190612d33565b60405180910390a25b5050600101610c3e565b60025460009074010000000000000000000000000000000000000000900460ff1615610f3a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fdf576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615611050576110026001820184611d70565b611050576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106ac565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146110ad576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611153576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690611120908a908a90600401612e6c565b600060405180830381600087803b15801561113a57600080fd5b505af115801561114e573d6000803e3d6000fd5b505050505b50604080516101c081019091526000610120820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101408501528981166101608501528454929392839291610180840191879187916111c1911661325b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018780602001906112359190613282565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016112798880613282565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112d56080890160608a01612d16565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020016000815260200187806040019061130d91906132e7565b905067ffffffffffffffff81111561132757611327612875565b6040519080825280602002602001820160405280156113a057816020015b61138d6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113455790505b509052905060006113b460408801886132e7565b808060200260200160405190810160405280939291908181526020016000905b82821015611400576113f16040830286013681900381019061334f565b815260200190600101906113d4565b5050505050905060005b61141760408901896132e7565b90508110156114b1576114878282815181106114355761143561305d565b60209081029190910101518a61144b8b80613282565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611d9f915050565b836101000151828151811061149e5761149e61305d565b602090810291909101015260010161140a565b50600254600090606090819073ffffffffffffffffffffffffffffffffffffffff1663430d138c8c6114e860808e018e8601612d16565b8c8e80608001906114f99190613282565b8b61010001518b6040518863ffffffff1660e01b8152600401611522979695949392919061346c565b600060405180830381865afa15801561153f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611585919081019061359e565b60e08901939093529094509250905082611660576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c16600482015273ffffffffffffffffffffffffffffffffffffffff89811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611637573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165b9190613691565b611663565b60005b855167ffffffffffffffff909116608091820152850182905260005b856101000151518110156116d55781818151811061169f5761169f61305d565b602002602001015186610100015182815181106116be576116be61305d565b60209081029190910101516080015260010161167f565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c16606082015230608082015261176590869060a001604051602081830303815290604052805190602001206120b6565b85515284516060015160405167ffffffffffffffff918216918d16907f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f32906117ae9089906136ae565b60405180910390a35050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055505051519150505b949350505050565b6117f8611835565b61076881612208565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106ac565b565b60005b8151811015611a575760008282815181106118d8576118d861305d565b6020026020010151905060008383815181106118f6576118f661305d565b60200260200101516000015190508067ffffffffffffffff16600003611954576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106ac565b67ffffffffffffffff818116600081815260066020908152604091829020868201518154888501517fffffff000000000000000000000000000000000000000000ffffffffffffffff909116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff9093169283027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff161768010000000000000000911515820217808455855197811688529387019190915260ff920491909116151591840191909152917fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118bb565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a975750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611aa3575080602001515b15611ada576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c80918490613806565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526109a79084906122fd565b60606000611d2583612409565b9392505050565b600061074e8373ffffffffffffffffffffffffffffffffffffffff8416612465565b600061074e8373ffffffffffffffffffffffffffffffffffffffff84166124b4565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561074e565b611de76040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e25576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e358587600001516109ac565b905073ffffffffffffffffffffffffffffffffffffffff81161580611f0557506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f039190612d46565b155b15611f575785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106ac565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611ff691906138b4565b6000604051808303816000875af1158015612015573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261205b919081019061392a565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff90941684528151602080860191909152918201518482015288820151606085015280519182019052600081526080830152509050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c0015160405160200161213495949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b6040516020818303038152906040528051906020012085606001518051906020012086604001518051906020012087610100015160405160200161217891906139bb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106ac565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061235f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125ae9092919063ffffffff16565b8051909150156109a7578080602001905181019061237d9190612d46565b6109a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106ac565b60608160000180548060200260200160405190810160405280929190818152602001828054801561245957602002820191906000526020600020905b815481526020019060010190808311612445575b50505050509050919050565b60008181526001830160205260408120546124ac57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610751565b506000610751565b6000818152600183016020526040812054801561259d5760006124d86001836139ce565b85549091506000906124ec906001906139ce565b905080821461255157600086600001828154811061250c5761250c61305d565b906000526020600020015490508087600001848154811061252f5761252f61305d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612562576125626139e1565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610751565b6000915050610751565b5092915050565b60606117e88484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125e29190613a10565b60006040518083038185875af1925050503d806000811461261f576040519150601f19603f3d011682016040523d82523d6000602084013e612624565b606091505b509150915061263587838387612640565b979650505050505050565b606083156126d65782516000036126cf5773ffffffffffffffffffffffffffffffffffffffff85163b6126cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106ac565b50816117e8565b6117e883838151156126eb5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ac91906127e4565b60808101610751828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b83811015612791578181015183820152602001612779565b50506000910152565b600081518084526127b2816020860160208601612776565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061074e602083018461279a565b67ffffffffffffffff8116811461076857600080fd5b600060a0828403121561281f57600080fd5b50919050565b6000806040838503121561283857600080fd5b8235612843816127f7565b9150602083013567ffffffffffffffff81111561285f57600080fd5b61286b8582860161280d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156128c7576128c7612875565b60405290565b6040805190810167ffffffffffffffff811182821017156128c7576128c7612875565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561293757612937612875565b604052919050565b600067ffffffffffffffff82111561295957612959612875565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461076857600080fd5b801515811461076857600080fd5b600060208083850312156129a657600080fd5b823567ffffffffffffffff8111156129bd57600080fd5b8301601f810185136129ce57600080fd5b80356129e16129dc8261293f565b6128f0565b81815260609182028301840191848201919088841115612a0057600080fd5b938501935b83851015612a655780858a031215612a1d5760008081fd5b612a256128a4565b8535612a30816127f7565b815285870135612a3f81612963565b81880152604086810135612a5281612985565b9082015283529384019391850191612a05565b50979650505050505050565b8035612a7c81612963565b919050565b600060a08284031215612a9357600080fd5b60405160a0810181811067ffffffffffffffff82111715612ab657612ab6612875565b6040528235612ac481612963565b81526020830135612ad481612985565b60208201526040830135612ae781612963565b60408201526060830135612afa81612963565b60608201526080830135612b0d81612963565b60808201529392505050565b60008060408385031215612b2c57600080fd5b8235612b37816127f7565b91506020830135612b4781612963565b809150509250929050565b600060208284031215612b6457600080fd5b8135611d25816127f7565b60a08101610751828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b60008151808452602080850194506020840160005b83811015612c0f57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612bdd565b509495945050505050565b82151581526040602082015260006117e86040830184612bc8565b60008060208385031215612c4857600080fd5b823567ffffffffffffffff80821115612c6057600080fd5b818501915085601f830112612c7457600080fd5b813581811115612c8357600080fd5b8660208260051b8501011115612c9857600080fd5b60209290920196919550909350505050565b60008060008060808587031215612cc057600080fd5b8435612ccb816127f7565b9350602085013567ffffffffffffffff811115612ce757600080fd5b612cf38782880161280d565b935050604085013591506060850135612d0b81612963565b939692955090935050565b600060208284031215612d2857600080fd5b8135611d2581612963565b60208152600061074e6020830184612bc8565b600060208284031215612d5857600080fd5b8151611d2581612985565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d9857600080fd5b830160208101925035905067ffffffffffffffff811115612db857600080fd5b803603821315612dc757600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c0f578135612e3a81612963565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612e27565b600067ffffffffffffffff808516835260406020840152612e8d8485612d63565b60a06040860152612ea260e086018284612dce565b915050612eb26020860186612d63565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612ee8848385612dce565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612f2157600080fd5b60209288019283019235915084821115612f3a57600080fd5b8160061b3603831315612f4c57600080fd5b80878503016080880152612f61848385612e17565b9450612f6f60608901612a71565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612f9a6080890189612d63565b94509250808786030160c08801525050612635838383612dce565b600060208284031215612fc757600080fd5b5051919050565b60006020808385031215612fe157600080fd5b825167ffffffffffffffff811115612ff857600080fd5b8301601f8101851361300957600080fd5b80516130176129dc8261293f565b81815260059190911b8201830190838101908783111561303657600080fd5b928401925b8284101561263557835161304e81612963565b8252928401929084019061303b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561309e57600080fd5b8151611d2581612963565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156125a7576125a76130a9565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261312d57600080fd5b9190910192915050565b600082601f83011261314857600080fd5b813560206131586129dc8361293f565b8083825260208201915060208460051b87010193508684111561317a57600080fd5b602086015b8481101561319f57803561319281612963565b835291830191830161317f565b509695505050505050565b6000608082360312156131bc57600080fd5b6040516080810167ffffffffffffffff82821081831117156131e0576131e0612875565b81604052843591506131f1826127f7565b90825260208401359061320382612985565b816020840152604085013591508082111561321d57600080fd5b61322936838701613137565b6040840152606085013591508082111561324257600080fd5b5061324f36828601613137565b60608301525092915050565b600067ffffffffffffffff808316818103613278576132786130a9565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126132b757600080fd5b83018035915067ffffffffffffffff8211156132d257600080fd5b602001915036819003821315612dc757600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261331c57600080fd5b83018035915067ffffffffffffffff82111561333757600080fd5b6020019150600681901b3603821315612dc757600080fd5b60006040828403121561336157600080fd5b6133696128cd565b823561337481612963565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561345f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526134088287018261279a565b91505060408083015186830382880152613422838261279a565b9250505060608083015181870152506080808301519250858203818701525061344b818361279a565b9a86019a94505050908301906001016133a6565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c060608601526134b660c08601898b612dce565b85810360808701526134c88189613389565b86810360a0880152875180825285890192509085019060005b818110156135085783518051871684528701518784015292860192918401916001016134e1565b50909e9d5050505050505050505050505050565b600082601f83011261352d57600080fd5b815167ffffffffffffffff81111561354757613547612875565b61357860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016128f0565b81815284602083860101111561358d57600080fd5b6117e8826020830160208701612776565b600080600080608085870312156135b457600080fd5b845193506020808601516135c781612985565b604087015190945067ffffffffffffffff808211156135e557600080fd5b6135f189838a0161351c565b9450606088015191508082111561360757600080fd5b818801915088601f83011261361b57600080fd5b81516136296129dc8261293f565b81815260059190911b8301840190848101908b83111561364857600080fd5b8585015b83811015613680578051858111156136645760008081fd5b6136728e89838a010161351c565b84525091860191860161364c565b50989b979a50959850505050505050565b6000602082840312156136a357600080fd5b8151611d25816127f7565b602081526136ff60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161372860c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526137456101c085018361279a565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152613783858461279a565b94506080880151925081878603016101208801526137a1858461279a565b945060a088015192506137cd61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e08801516101808801528701518685039091018387015290506137fc8382613389565b9695505050505050565b610120810161385e828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d25565b602081526000825160a060208401526138d060c084018261279a565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561393c57600080fd5b815167ffffffffffffffff8082111561395457600080fd5b908301906040828603121561396857600080fd5b6139706128cd565b82518281111561397f57600080fd5b61398b8782860161351c565b8252506020830151828111156139a057600080fd5b6139ac8782860161351c565b60208301525095945050505050565b60208152600061074e6020830184613389565b81810381811115610751576107516130a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825161312d81846020870161277656fea164736f6c6343000818000a", +} + +var OnRampABI = OnRampMetaData.ABI + +var OnRampBin = OnRampMetaData.Bin + +func DeployOnRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig OnRampStaticConfig, dynamicConfig OnRampDynamicConfig, destChainConfigArgs []OnRampDestChainConfigArgs) (common.Address, *types.Transaction, *OnRamp, error) { + parsed, err := OnRampMetaData.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(OnRampBin), backend, staticConfig, dynamicConfig, destChainConfigArgs) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OnRamp{address: address, abi: *parsed, OnRampCaller: OnRampCaller{contract: contract}, OnRampTransactor: OnRampTransactor{contract: contract}, OnRampFilterer: OnRampFilterer{contract: contract}}, nil +} + +type OnRamp struct { + address common.Address + abi abi.ABI + OnRampCaller + OnRampTransactor + OnRampFilterer +} + +type OnRampCaller struct { + contract *bind.BoundContract +} + +type OnRampTransactor struct { + contract *bind.BoundContract +} + +type OnRampFilterer struct { + contract *bind.BoundContract +} + +type OnRampSession struct { + Contract *OnRamp + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OnRampCallerSession struct { + Contract *OnRampCaller + CallOpts bind.CallOpts +} + +type OnRampTransactorSession struct { + Contract *OnRampTransactor + TransactOpts bind.TransactOpts +} + +type OnRampRaw struct { + Contract *OnRamp +} + +type OnRampCallerRaw struct { + Contract *OnRampCaller +} + +type OnRampTransactorRaw struct { + Contract *OnRampTransactor +} + +func NewOnRamp(address common.Address, backend bind.ContractBackend) (*OnRamp, error) { + abi, err := abi.JSON(strings.NewReader(OnRampABI)) + if err != nil { + return nil, err + } + contract, err := bindOnRamp(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OnRamp{address: address, abi: abi, OnRampCaller: OnRampCaller{contract: contract}, OnRampTransactor: OnRampTransactor{contract: contract}, OnRampFilterer: OnRampFilterer{contract: contract}}, nil +} + +func NewOnRampCaller(address common.Address, caller bind.ContractCaller) (*OnRampCaller, error) { + contract, err := bindOnRamp(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OnRampCaller{contract: contract}, nil +} + +func NewOnRampTransactor(address common.Address, transactor bind.ContractTransactor) (*OnRampTransactor, error) { + contract, err := bindOnRamp(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OnRampTransactor{contract: contract}, nil +} + +func NewOnRampFilterer(address common.Address, filterer bind.ContractFilterer) (*OnRampFilterer, error) { + contract, err := bindOnRamp(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OnRampFilterer{contract: contract}, nil +} + +func bindOnRamp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OnRampMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_OnRamp *OnRampRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OnRamp.Contract.OnRampCaller.contract.Call(opts, result, method, params...) +} + +func (_OnRamp *OnRampRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OnRamp.Contract.OnRampTransactor.contract.Transfer(opts) +} + +func (_OnRamp *OnRampRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OnRamp.Contract.OnRampTransactor.contract.Transact(opts, method, params...) +} + +func (_OnRamp *OnRampCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OnRamp.Contract.contract.Call(opts, result, method, params...) +} + +func (_OnRamp *OnRampTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OnRamp.Contract.contract.Transfer(opts) +} + +func (_OnRamp *OnRampTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OnRamp.Contract.contract.Transact(opts, method, params...) +} + +func (_OnRamp *OnRampCaller) GetAllowedSendersList(opts *bind.CallOpts, destChainSelector uint64) (GetAllowedSendersList, + + error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getAllowedSendersList", destChainSelector) + + outstruct := new(GetAllowedSendersList) + if err != nil { + return *outstruct, err + } + + outstruct.IsEnabled = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ConfiguredAddresses = *abi.ConvertType(out[1], new([]common.Address)).(*[]common.Address) + + return *outstruct, err + +} + +func (_OnRamp *OnRampSession) GetAllowedSendersList(destChainSelector uint64) (GetAllowedSendersList, + + error) { + return _OnRamp.Contract.GetAllowedSendersList(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCallerSession) GetAllowedSendersList(destChainSelector uint64) (GetAllowedSendersList, + + error) { + return _OnRamp.Contract.GetAllowedSendersList(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (GetDestChainConfig, + + error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) + + outstruct := new(GetDestChainConfig) + if err != nil { + return *outstruct, err + } + + outstruct.SequenceNumber = *abi.ConvertType(out[0], new(uint64)).(*uint64) + outstruct.AllowlistEnabled = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.Router = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_OnRamp *OnRampSession) GetDestChainConfig(destChainSelector uint64) (GetDestChainConfig, + + error) { + return _OnRamp.Contract.GetDestChainConfig(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCallerSession) GetDestChainConfig(destChainSelector uint64) (GetDestChainConfig, + + error) { + return _OnRamp.Contract.GetDestChainConfig(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCaller) GetDynamicConfig(opts *bind.CallOpts) (OnRampDynamicConfig, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getDynamicConfig") + + if err != nil { + return *new(OnRampDynamicConfig), err + } + + out0 := *abi.ConvertType(out[0], new(OnRampDynamicConfig)).(*OnRampDynamicConfig) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetDynamicConfig() (OnRampDynamicConfig, error) { + return _OnRamp.Contract.GetDynamicConfig(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCallerSession) GetDynamicConfig() (OnRampDynamicConfig, error) { + return _OnRamp.Contract.GetDynamicConfig(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getExpectedNextSequenceNumber", destChainSelector) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { + return _OnRamp.Contract.GetExpectedNextSequenceNumber(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCallerSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { + return _OnRamp.Contract.GetExpectedNextSequenceNumber(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCaller) GetFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getFee", destChainSelector, message) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _OnRamp.Contract.GetFee(&_OnRamp.CallOpts, destChainSelector, message) +} + +func (_OnRamp *OnRampCallerSession) GetFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _OnRamp.Contract.GetFee(&_OnRamp.CallOpts, destChainSelector, message) +} + +func (_OnRamp *OnRampCaller) GetPoolBySourceToken(opts *bind.CallOpts, arg0 uint64, sourceToken common.Address) (common.Address, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getPoolBySourceToken", arg0, sourceToken) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetPoolBySourceToken(arg0 uint64, sourceToken common.Address) (common.Address, error) { + return _OnRamp.Contract.GetPoolBySourceToken(&_OnRamp.CallOpts, arg0, sourceToken) +} + +func (_OnRamp *OnRampCallerSession) GetPoolBySourceToken(arg0 uint64, sourceToken common.Address) (common.Address, error) { + return _OnRamp.Contract.GetPoolBySourceToken(&_OnRamp.CallOpts, arg0, sourceToken) +} + +func (_OnRamp *OnRampCaller) GetRouter(opts *bind.CallOpts, destChainSelector uint64) (common.Address, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getRouter", destChainSelector) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetRouter(destChainSelector uint64) (common.Address, error) { + return _OnRamp.Contract.GetRouter(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCallerSession) GetRouter(destChainSelector uint64) (common.Address, error) { + return _OnRamp.Contract.GetRouter(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCaller) GetStaticConfig(opts *bind.CallOpts) (OnRampStaticConfig, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getStaticConfig") + + if err != nil { + return *new(OnRampStaticConfig), err + } + + out0 := *abi.ConvertType(out[0], new(OnRampStaticConfig)).(*OnRampStaticConfig) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetStaticConfig() (OnRampStaticConfig, error) { + return _OnRamp.Contract.GetStaticConfig(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCallerSession) GetStaticConfig() (OnRampStaticConfig, error) { + return _OnRamp.Contract.GetStaticConfig(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCaller) GetSupportedTokens(opts *bind.CallOpts, arg0 uint64) ([]common.Address, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getSupportedTokens", arg0) + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetSupportedTokens(arg0 uint64) ([]common.Address, error) { + return _OnRamp.Contract.GetSupportedTokens(&_OnRamp.CallOpts, arg0) +} + +func (_OnRamp *OnRampCallerSession) GetSupportedTokens(arg0 uint64) ([]common.Address, error) { + return _OnRamp.Contract.GetSupportedTokens(&_OnRamp.CallOpts, arg0) +} + +func (_OnRamp *OnRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OnRamp.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 (_OnRamp *OnRampSession) Owner() (common.Address, error) { + return _OnRamp.Contract.Owner(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCallerSession) Owner() (common.Address, error) { + return _OnRamp.Contract.Owner(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_OnRamp *OnRampSession) TypeAndVersion() (string, error) { + return _OnRamp.Contract.TypeAndVersion(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampCallerSession) TypeAndVersion() (string, error) { + return _OnRamp.Contract.TypeAndVersion(&_OnRamp.CallOpts) +} + +func (_OnRamp *OnRampTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "acceptOwnership") +} + +func (_OnRamp *OnRampSession) AcceptOwnership() (*types.Transaction, error) { + return _OnRamp.Contract.AcceptOwnership(&_OnRamp.TransactOpts) +} + +func (_OnRamp *OnRampTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _OnRamp.Contract.AcceptOwnership(&_OnRamp.TransactOpts) +} + +func (_OnRamp *OnRampTransactor) ApplyAllowlistUpdates(opts *bind.TransactOpts, allowlistConfigArgsItems []OnRampAllowlistConfigArgs) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "applyAllowlistUpdates", allowlistConfigArgsItems) +} + +func (_OnRamp *OnRampSession) ApplyAllowlistUpdates(allowlistConfigArgsItems []OnRampAllowlistConfigArgs) (*types.Transaction, error) { + return _OnRamp.Contract.ApplyAllowlistUpdates(&_OnRamp.TransactOpts, allowlistConfigArgsItems) +} + +func (_OnRamp *OnRampTransactorSession) ApplyAllowlistUpdates(allowlistConfigArgsItems []OnRampAllowlistConfigArgs) (*types.Transaction, error) { + return _OnRamp.Contract.ApplyAllowlistUpdates(&_OnRamp.TransactOpts, allowlistConfigArgsItems) +} + +func (_OnRamp *OnRampTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []OnRampDestChainConfigArgs) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) +} + +func (_OnRamp *OnRampSession) ApplyDestChainConfigUpdates(destChainConfigArgs []OnRampDestChainConfigArgs) (*types.Transaction, error) { + return _OnRamp.Contract.ApplyDestChainConfigUpdates(&_OnRamp.TransactOpts, destChainConfigArgs) +} + +func (_OnRamp *OnRampTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []OnRampDestChainConfigArgs) (*types.Transaction, error) { + return _OnRamp.Contract.ApplyDestChainConfigUpdates(&_OnRamp.TransactOpts, destChainConfigArgs) +} + +func (_OnRamp *OnRampTransactor) ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "forwardFromRouter", destChainSelector, message, feeTokenAmount, originalSender) +} + +func (_OnRamp *OnRampSession) ForwardFromRouter(destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { + return _OnRamp.Contract.ForwardFromRouter(&_OnRamp.TransactOpts, destChainSelector, message, feeTokenAmount, originalSender) +} + +func (_OnRamp *OnRampTransactorSession) ForwardFromRouter(destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { + return _OnRamp.Contract.ForwardFromRouter(&_OnRamp.TransactOpts, destChainSelector, message, feeTokenAmount, originalSender) +} + +func (_OnRamp *OnRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OnRampDynamicConfig) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) +} + +func (_OnRamp *OnRampSession) SetDynamicConfig(dynamicConfig OnRampDynamicConfig) (*types.Transaction, error) { + return _OnRamp.Contract.SetDynamicConfig(&_OnRamp.TransactOpts, dynamicConfig) +} + +func (_OnRamp *OnRampTransactorSession) SetDynamicConfig(dynamicConfig OnRampDynamicConfig) (*types.Transaction, error) { + return _OnRamp.Contract.SetDynamicConfig(&_OnRamp.TransactOpts, dynamicConfig) +} + +func (_OnRamp *OnRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "transferOwnership", to) +} + +func (_OnRamp *OnRampSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OnRamp.Contract.TransferOwnership(&_OnRamp.TransactOpts, to) +} + +func (_OnRamp *OnRampTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OnRamp.Contract.TransferOwnership(&_OnRamp.TransactOpts, to) +} + +func (_OnRamp *OnRampTransactor) WithdrawFeeTokens(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "withdrawFeeTokens") +} + +func (_OnRamp *OnRampSession) WithdrawFeeTokens() (*types.Transaction, error) { + return _OnRamp.Contract.WithdrawFeeTokens(&_OnRamp.TransactOpts) +} + +func (_OnRamp *OnRampTransactorSession) WithdrawFeeTokens() (*types.Transaction, error) { + return _OnRamp.Contract.WithdrawFeeTokens(&_OnRamp.TransactOpts) +} + +type OnRampAllowListAdminSetIterator struct { + Event *OnRampAllowListAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampAllowListAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListAdminSet) + 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(OnRampAllowListAdminSet) + 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 *OnRampAllowListAdminSetIterator) Error() error { + return it.fail +} + +func (it *OnRampAllowListAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampAllowListAdminSet struct { + AllowlistAdmin common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterAllowListAdminSet(opts *bind.FilterOpts, allowlistAdmin []common.Address) (*OnRampAllowListAdminSetIterator, error) { + + var allowlistAdminRule []interface{} + for _, allowlistAdminItem := range allowlistAdmin { + allowlistAdminRule = append(allowlistAdminRule, allowlistAdminItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "AllowListAdminSet", allowlistAdminRule) + if err != nil { + return nil, err + } + return &OnRampAllowListAdminSetIterator{contract: _OnRamp.contract, event: "AllowListAdminSet", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchAllowListAdminSet(opts *bind.WatchOpts, sink chan<- *OnRampAllowListAdminSet, allowlistAdmin []common.Address) (event.Subscription, error) { + + var allowlistAdminRule []interface{} + for _, allowlistAdminItem := range allowlistAdmin { + allowlistAdminRule = append(allowlistAdminRule, allowlistAdminItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "AllowListAdminSet", allowlistAdminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampAllowListAdminSet) + if err := _OnRamp.contract.UnpackLog(event, "AllowListAdminSet", 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 (_OnRamp *OnRampFilterer) ParseAllowListAdminSet(log types.Log) (*OnRampAllowListAdminSet, error) { + event := new(OnRampAllowListAdminSet) + if err := _OnRamp.contract.UnpackLog(event, "AllowListAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampAllowListSendersAddedIterator struct { + Event *OnRampAllowListSendersAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampAllowListSendersAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListSendersAdded) + 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(OnRampAllowListSendersAdded) + 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 *OnRampAllowListSendersAddedIterator) Error() error { + return it.fail +} + +func (it *OnRampAllowListSendersAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampAllowListSendersAdded struct { + DestChainSelector uint64 + Senders []common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterAllowListSendersAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersAddedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "AllowListSendersAdded", destChainSelectorRule) + if err != nil { + return nil, err + } + return &OnRampAllowListSendersAddedIterator{contract: _OnRamp.contract, event: "AllowListSendersAdded", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchAllowListSendersAdded(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersAdded, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "AllowListSendersAdded", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampAllowListSendersAdded) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersAdded", 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 (_OnRamp *OnRampFilterer) ParseAllowListSendersAdded(log types.Log) (*OnRampAllowListSendersAdded, error) { + event := new(OnRampAllowListSendersAdded) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampAllowListSendersRemovedIterator struct { + Event *OnRampAllowListSendersRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampAllowListSendersRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListSendersRemoved) + 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(OnRampAllowListSendersRemoved) + 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 *OnRampAllowListSendersRemovedIterator) Error() error { + return it.fail +} + +func (it *OnRampAllowListSendersRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampAllowListSendersRemoved struct { + DestChainSelector uint64 + Senders []common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterAllowListSendersRemoved(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersRemovedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "AllowListSendersRemoved", destChainSelectorRule) + if err != nil { + return nil, err + } + return &OnRampAllowListSendersRemovedIterator{contract: _OnRamp.contract, event: "AllowListSendersRemoved", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchAllowListSendersRemoved(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersRemoved, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "AllowListSendersRemoved", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampAllowListSendersRemoved) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersRemoved", 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 (_OnRamp *OnRampFilterer) ParseAllowListSendersRemoved(log types.Log) (*OnRampAllowListSendersRemoved, error) { + event := new(OnRampAllowListSendersRemoved) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampCCIPMessageSentIterator struct { + Event *OnRampCCIPMessageSent + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampCCIPMessageSentIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampCCIPMessageSent) + 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(OnRampCCIPMessageSent) + 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 *OnRampCCIPMessageSentIterator) Error() error { + return it.fail +} + +func (it *OnRampCCIPMessageSentIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampCCIPMessageSent struct { + DestChainSelector uint64 + SequenceNumber uint64 + Message InternalEVM2AnyRampMessage + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64, sequenceNumber []uint64) (*OnRampCCIPMessageSentIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "CCIPMessageSent", destChainSelectorRule, sequenceNumberRule) + if err != nil { + return nil, err + } + return &OnRampCCIPMessageSentIterator{contract: _OnRamp.contract, event: "CCIPMessageSent", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchCCIPMessageSent(opts *bind.WatchOpts, sink chan<- *OnRampCCIPMessageSent, destChainSelector []uint64, sequenceNumber []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "CCIPMessageSent", destChainSelectorRule, sequenceNumberRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampCCIPMessageSent) + if err := _OnRamp.contract.UnpackLog(event, "CCIPMessageSent", 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 (_OnRamp *OnRampFilterer) ParseCCIPMessageSent(log types.Log) (*OnRampCCIPMessageSent, error) { + event := new(OnRampCCIPMessageSent) + if err := _OnRamp.contract.UnpackLog(event, "CCIPMessageSent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampConfigSetIterator struct { + Event *OnRampConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampConfigSet) + 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(OnRampConfigSet) + 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 *OnRampConfigSetIterator) Error() error { + return it.fail +} + +func (it *OnRampConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampConfigSet struct { + StaticConfig OnRampStaticConfig + DynamicConfig OnRampDynamicConfig + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*OnRampConfigSetIterator, error) { + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &OnRampConfigSetIterator{contract: _OnRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OnRampConfigSet) (event.Subscription, error) { + + logs, sub, err := _OnRamp.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(OnRampConfigSet) + if err := _OnRamp.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 (_OnRamp *OnRampFilterer) ParseConfigSet(log types.Log) (*OnRampConfigSet, error) { + event := new(OnRampConfigSet) + if err := _OnRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampDestChainConfigSetIterator struct { + Event *OnRampDestChainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampDestChainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampDestChainConfigSet) + 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(OnRampDestChainConfigSet) + 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 *OnRampDestChainConfigSetIterator) Error() error { + return it.fail +} + +func (it *OnRampDestChainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampDestChainConfigSet struct { + DestChainSelector uint64 + SequenceNumber uint64 + Router common.Address + AllowlistEnabled bool + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterDestChainConfigSet(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampDestChainConfigSetIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "DestChainConfigSet", destChainSelectorRule) + if err != nil { + return nil, err + } + return &OnRampDestChainConfigSetIterator{contract: _OnRamp.contract, event: "DestChainConfigSet", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchDestChainConfigSet(opts *bind.WatchOpts, sink chan<- *OnRampDestChainConfigSet, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "DestChainConfigSet", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampDestChainConfigSet) + if err := _OnRamp.contract.UnpackLog(event, "DestChainConfigSet", 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 (_OnRamp *OnRampFilterer) ParseDestChainConfigSet(log types.Log) (*OnRampDestChainConfigSet, error) { + event := new(OnRampDestChainConfigSet) + if err := _OnRamp.contract.UnpackLog(event, "DestChainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampFeeTokenWithdrawnIterator struct { + Event *OnRampFeeTokenWithdrawn + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampFeeTokenWithdrawnIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampFeeTokenWithdrawn) + 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(OnRampFeeTokenWithdrawn) + 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 *OnRampFeeTokenWithdrawnIterator) Error() error { + return it.fail +} + +func (it *OnRampFeeTokenWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampFeeTokenWithdrawn struct { + FeeAggregator common.Address + FeeToken common.Address + Amount *big.Int + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*OnRampFeeTokenWithdrawnIterator, error) { + + var feeAggregatorRule []interface{} + for _, feeAggregatorItem := range feeAggregator { + feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) + } + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) + if err != nil { + return nil, err + } + return &OnRampFeeTokenWithdrawnIterator{contract: _OnRamp.contract, event: "FeeTokenWithdrawn", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *OnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) { + + var feeAggregatorRule []interface{} + for _, feeAggregatorItem := range feeAggregator { + feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) + } + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampFeeTokenWithdrawn) + if err := _OnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", 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 (_OnRamp *OnRampFilterer) ParseFeeTokenWithdrawn(log types.Log) (*OnRampFeeTokenWithdrawn, error) { + event := new(OnRampFeeTokenWithdrawn) + if err := _OnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampOwnershipTransferRequestedIterator struct { + Event *OnRampOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampOwnershipTransferRequested) + 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(OnRampOwnershipTransferRequested) + 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 *OnRampOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *OnRampOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OnRampOwnershipTransferRequestedIterator, 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 := _OnRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &OnRampOwnershipTransferRequestedIterator{contract: _OnRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OnRampOwnershipTransferRequested, 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 := _OnRamp.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(OnRampOwnershipTransferRequested) + if err := _OnRamp.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 (_OnRamp *OnRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*OnRampOwnershipTransferRequested, error) { + event := new(OnRampOwnershipTransferRequested) + if err := _OnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampOwnershipTransferredIterator struct { + Event *OnRampOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampOwnershipTransferred) + 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(OnRampOwnershipTransferred) + 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 *OnRampOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *OnRampOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OnRampOwnershipTransferredIterator, 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 := _OnRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &OnRampOwnershipTransferredIterator{contract: _OnRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OnRampOwnershipTransferred, 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 := _OnRamp.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(OnRampOwnershipTransferred) + if err := _OnRamp.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 (_OnRamp *OnRampFilterer) ParseOwnershipTransferred(log types.Log) (*OnRampOwnershipTransferred, error) { + event := new(OnRampOwnershipTransferred) + if err := _OnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetAllowedSendersList struct { + IsEnabled bool + ConfiguredAddresses []common.Address +} +type GetDestChainConfig struct { + SequenceNumber uint64 + AllowlistEnabled bool + Router common.Address +} + +func (_OnRamp *OnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _OnRamp.abi.Events["AllowListAdminSet"].ID: + return _OnRamp.ParseAllowListAdminSet(log) + case _OnRamp.abi.Events["AllowListSendersAdded"].ID: + return _OnRamp.ParseAllowListSendersAdded(log) + case _OnRamp.abi.Events["AllowListSendersRemoved"].ID: + return _OnRamp.ParseAllowListSendersRemoved(log) + case _OnRamp.abi.Events["CCIPMessageSent"].ID: + return _OnRamp.ParseCCIPMessageSent(log) + case _OnRamp.abi.Events["ConfigSet"].ID: + return _OnRamp.ParseConfigSet(log) + case _OnRamp.abi.Events["DestChainConfigSet"].ID: + return _OnRamp.ParseDestChainConfigSet(log) + case _OnRamp.abi.Events["FeeTokenWithdrawn"].ID: + return _OnRamp.ParseFeeTokenWithdrawn(log) + case _OnRamp.abi.Events["OwnershipTransferRequested"].ID: + return _OnRamp.ParseOwnershipTransferRequested(log) + case _OnRamp.abi.Events["OwnershipTransferred"].ID: + return _OnRamp.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OnRampAllowListAdminSet) Topic() common.Hash { + return common.HexToHash("0xb8c9b44ae5b5e3afb195f67391d9ff50cb904f9c0fa5fd520e497a97c1aa5a1e") +} + +func (OnRampAllowListSendersAdded) Topic() common.Hash { + return common.HexToHash("0x330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281") +} + +func (OnRampAllowListSendersRemoved) Topic() common.Hash { + return common.HexToHash("0xc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d421586") +} + +func (OnRampCCIPMessageSent) Topic() common.Hash { + return common.HexToHash("0x192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f32") +} + +func (OnRampConfigSet) Topic() common.Hash { + return common.HexToHash("0xc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f1") +} + +func (OnRampDestChainConfigSet) Topic() common.Hash { + return common.HexToHash("0xd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef5") +} + +func (OnRampFeeTokenWithdrawn) Topic() common.Hash { + return common.HexToHash("0x508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e") +} + +func (OnRampOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (OnRampOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_OnRamp *OnRamp) Address() common.Address { + return _OnRamp.address +} + +type OnRampInterface interface { + GetAllowedSendersList(opts *bind.CallOpts, destChainSelector uint64) (GetAllowedSendersList, + + error) + + GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (GetDestChainConfig, + + error) + + GetDynamicConfig(opts *bind.CallOpts) (OnRampDynamicConfig, error) + + GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) + + GetFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) + + GetPoolBySourceToken(opts *bind.CallOpts, arg0 uint64, sourceToken common.Address) (common.Address, error) + + GetRouter(opts *bind.CallOpts, destChainSelector uint64) (common.Address, error) + + GetStaticConfig(opts *bind.CallOpts) (OnRampStaticConfig, error) + + GetSupportedTokens(opts *bind.CallOpts, arg0 uint64) ([]common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplyAllowlistUpdates(opts *bind.TransactOpts, allowlistConfigArgsItems []OnRampAllowlistConfigArgs) (*types.Transaction, error) + + ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []OnRampDestChainConfigArgs) (*types.Transaction, error) + + ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) + + SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OnRampDynamicConfig) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + WithdrawFeeTokens(opts *bind.TransactOpts) (*types.Transaction, error) + + FilterAllowListAdminSet(opts *bind.FilterOpts, allowlistAdmin []common.Address) (*OnRampAllowListAdminSetIterator, error) + + WatchAllowListAdminSet(opts *bind.WatchOpts, sink chan<- *OnRampAllowListAdminSet, allowlistAdmin []common.Address) (event.Subscription, error) + + ParseAllowListAdminSet(log types.Log) (*OnRampAllowListAdminSet, error) + + FilterAllowListSendersAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersAddedIterator, error) + + WatchAllowListSendersAdded(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersAdded, destChainSelector []uint64) (event.Subscription, error) + + ParseAllowListSendersAdded(log types.Log) (*OnRampAllowListSendersAdded, error) + + FilterAllowListSendersRemoved(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersRemovedIterator, error) + + WatchAllowListSendersRemoved(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersRemoved, destChainSelector []uint64) (event.Subscription, error) + + ParseAllowListSendersRemoved(log types.Log) (*OnRampAllowListSendersRemoved, error) + + FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64, sequenceNumber []uint64) (*OnRampCCIPMessageSentIterator, error) + + WatchCCIPMessageSent(opts *bind.WatchOpts, sink chan<- *OnRampCCIPMessageSent, destChainSelector []uint64, sequenceNumber []uint64) (event.Subscription, error) + + ParseCCIPMessageSent(log types.Log) (*OnRampCCIPMessageSent, error) + + FilterConfigSet(opts *bind.FilterOpts) (*OnRampConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OnRampConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*OnRampConfigSet, error) + + FilterDestChainConfigSet(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampDestChainConfigSetIterator, error) + + WatchDestChainConfigSet(opts *bind.WatchOpts, sink chan<- *OnRampDestChainConfigSet, destChainSelector []uint64) (event.Subscription, error) + + ParseDestChainConfigSet(log types.Log) (*OnRampDestChainConfigSet, error) + + FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*OnRampFeeTokenWithdrawnIterator, error) + + WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *OnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) + + ParseFeeTokenWithdrawn(log types.Log) (*OnRampFeeTokenWithdrawn, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OnRampOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OnRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*OnRampOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OnRampOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OnRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*OnRampOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} 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 4387dd3080c..08ae9cc0cca 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\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"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\"},{\"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\":\"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\":\"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: "0x60a06040523480156200001157600080fd5b50604051620013d8380380620013d8833981016040819052620000349162000263565b33806000846001600160a01b03811662000069576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c75760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000060565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fa57620000fa816200019f565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000170573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001969190620002a2565b505050620002cd565b336001600160a01b03821603620001f95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200026057600080fd5b50565b600080604083850312156200027757600080fd5b825162000284816200024a565b602084015190925062000297816200024a565b809150509250929050565b600060208284031215620002b557600080fd5b81518015158114620002c657600080fd5b9392505050565b6080516110e1620002f7600039600081816102290152818161058e01526108f201526110e16000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80638da5cb5b11610097578063b5a1101111610066578063b5a1101114610270578063bee518a414610283578063ca709a25146102c1578063f2fde38b146102df57600080fd5b80638da5cb5b146101f65780639d2aede514610214578063b0f479a114610227578063b187bd261461024d57600080fd5b80632874d8bf116100d35780632874d8bf146101945780632b6e5d631461019c57806379ba5097146101db57806385572ffb146101e357600080fd5b806301ffc9a71461010557806316c38b3c1461012d578063181f5a77146101425780631892b90614610181575b600080fd5b610118610113366004610af5565b6102f2565b60405190151581526020015b60405180910390f35b61014061013b366004610b3e565b61038b565b005b604080518082018252601281527f50696e67506f6e6744656d6f20312e322e300000000000000000000000000000602082015290516101249190610bc4565b61014061018f366004610bf4565b6103dd565b610140610438565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b610140610474565b6101406101f1366004610c0f565b610576565b60005473ffffffffffffffffffffffffffffffffffffffff166101b6565b610140610222366004610c6e565b6105fb565b7f00000000000000000000000000000000000000000000000000000000000000006101b6565b60025474010000000000000000000000000000000000000000900460ff16610118565b61014061027e366004610c89565b61064a565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff9091168152602001610124565b60035473ffffffffffffffffffffffffffffffffffffffff166101b6565b6101406102ed366004610c6e565b6106ec565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061038557507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6103936106fd565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6103e56106fd565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104406106fd565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055610472600161077e565b565b60015473ffffffffffffffffffffffffffffffffffffffff1633146104fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146105e7576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024016104f1565b6105f86105f382610ebf565b6109aa565b50565b6106036106fd565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6106526106fd565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6106f46106fd565b6105f881610a00565b60005473ffffffffffffffffffffffffffffffffffffffff163314610472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104f1565b806001166001036107c1576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a16107f5565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b60008160405160200161080a91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a08301825260025473ffffffffffffffffffffffffffffffffffffffff1660c0808501919091528251808503909101815260e084018352835260208084018290528251600080825291810184529194509291820190836108b8565b60408051808201909152600080825260208201528152602001906001900390816108915790505b50815260035473ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080519182018152600082529091015290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9600160149054906101000a900467ffffffffffffffff16836040518363ffffffff1660e01b8152600401610961929190610f6c565b6020604051808303816000875af1158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190611081565b50505050565b600081606001518060200190518101906109c49190611081565b60025490915074010000000000000000000000000000000000000000900460ff166109fc576109fc6109f782600161109a565b61077e565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104f1565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610b0757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610b3757600080fd5b9392505050565b600060208284031215610b5057600080fd5b81358015158114610b3757600080fd5b6000815180845260005b81811015610b8657602081850181015186830182015201610b6a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b376020830184610b60565b803567ffffffffffffffff81168114610bef57600080fd5b919050565b600060208284031215610c0657600080fd5b610b3782610bd7565b600060208284031215610c2157600080fd5b813567ffffffffffffffff811115610c3857600080fd5b820160a08185031215610b3757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610bef57600080fd5b600060208284031215610c8057600080fd5b610b3782610c4a565b60008060408385031215610c9c57600080fd5b610ca583610bd7565b9150610cb360208401610c4a565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610d0e57610d0e610cbc565b60405290565b60405160a0810167ffffffffffffffff81118282101715610d0e57610d0e610cbc565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610d7e57610d7e610cbc565b604052919050565b600082601f830112610d9757600080fd5b813567ffffffffffffffff811115610db157610db1610cbc565b610de260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610d37565b818152846020838601011115610df757600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610e2557600080fd5b8135602067ffffffffffffffff821115610e4157610e41610cbc565b610e4f818360051b01610d37565b82815260069290921b84018101918181019086841115610e6e57600080fd5b8286015b84811015610eb45760408189031215610e8b5760008081fd5b610e93610ceb565b610e9c82610c4a565b81528185013585820152835291830191604001610e72565b509695505050505050565b600060a08236031215610ed157600080fd5b610ed9610d14565b82358152610ee960208401610bd7565b6020820152604083013567ffffffffffffffff80821115610f0957600080fd5b610f1536838701610d86565b60408401526060850135915080821115610f2e57600080fd5b610f3a36838701610d86565b60608401526080850135915080821115610f5357600080fd5b50610f6036828601610e14565b60808301525092915050565b6000604067ffffffffffffffff851683526020604081850152845160a06040860152610f9b60e0860182610b60565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878403016060880152610fd68383610b60565b6040890151888203830160808a01528051808352908601945060009350908501905b80841015611037578451805173ffffffffffffffffffffffffffffffffffffffff16835286015186830152938501936001939093019290860190610ff8565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506110738187610b60565b9a9950505050505050505050565b60006020828403121561109357600080fd5b5051919050565b80820180821115610385577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"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: "0x60a06040523480156200001157600080fd5b506040516200159d3803806200159d833981016040819052620000349162000263565b33806000846001600160a01b03811662000069576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c75760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000060565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fa57620000fa816200019f565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000170573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001969190620002a2565b505050620002cd565b336001600160a01b03821603620001f95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200026057600080fd5b50565b600080604083850312156200027757600080fd5b825162000284816200024a565b602084015190925062000297816200024a565b809150509250929050565b600060208284031215620002b557600080fd5b81518015158114620002c657600080fd5b9392505050565b6080516112a6620002f760003960008181610295015281816106860152610ab901526112a66000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80638da5cb5b116100b2578063b187bd2611610081578063bee518a411610066578063bee518a4146102ef578063ca709a251461032d578063f2fde38b1461034b57600080fd5b8063b187bd26146102b9578063b5a11011146102dc57600080fd5b80638da5cb5b1461023f5780639d2aede51461025d578063ae90de5514610270578063b0f479a11461029357600080fd5b80632874d8bf11610109578063665ed537116100ee578063665ed5371461021157806379ba50971461022457806385572ffb1461022c57600080fd5b80632874d8bf146101ca5780632b6e5d63146101d257600080fd5b806301ffc9a71461013b57806316c38b3c14610163578063181f5a77146101785780631892b906146101b7575b600080fd5b61014e610149366004610cba565b61035e565b60405190151581526020015b60405180910390f35b610176610171366004610d03565b6103f7565b005b604080518082018252601281527f50696e67506f6e6744656d6f20312e352e3000000000000000000000000000006020820152905161015a9190610d89565b6101766101c5366004610db9565b610449565b6101766104a4565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161015a565b61017661021f366004610d03565b6104e0565b61017661056c565b61017661023a366004610dd4565b61066e565b60005473ffffffffffffffffffffffffffffffffffffffff166101ec565b61017661026b366004610e33565b6106f3565b60035474010000000000000000000000000000000000000000900460ff1661014e565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b60025474010000000000000000000000000000000000000000900460ff1661014e565b6101766102ea366004610e4e565b610742565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161015a565b60035473ffffffffffffffffffffffffffffffffffffffff166101ec565b610176610359366004610e33565b6107e4565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb0000000000000000000000000000000000000000000000000000000014806103f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6103ff6107f5565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104516107f5565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104ac6107f5565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556104de6001610876565b565b6104e86107f5565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061056190831515815260200190565b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106df576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024016105e9565b6106f06106eb82611084565b610b6f565b50565b6106fb6107f5565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61074a6107f5565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6107ec6107f5565b6106f081610bc5565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105e9565b806001166001036108b9576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a16108ed565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e0810160405160208183030381529060405281526020018360405160200161094591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052815260200160006040519080825280602002602001820160405280156109bf57816020015b60408051808201909152600080825260208201528152602001906001900390816109985790505b50815260035473ffffffffffffffffffffffffffffffffffffffff811660208084019190915260408051808201825262030d408082527401000000000000000000000000000000000000000090940460ff16151590830190815281516024810194909452511515604480850191909152815180850390910181526064909301815290820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf1000000000000000000000000000000000000000000000000000000000179052909101526001546040517f96f4e9f90000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916396f4e9f991610b27917401000000000000000000000000000000000000000090910467ffffffffffffffff16908590600401611131565b6020604051808303816000875af1158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611246565b505050565b60008160600151806020019051810190610b899190611246565b60025490915074010000000000000000000000000000000000000000900460ff16610bc157610bc1610bbc82600161125f565b610876565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610c44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105e9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610ccc57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cfc57600080fd5b9392505050565b600060208284031215610d1557600080fd5b81358015158114610cfc57600080fd5b6000815180845260005b81811015610d4b57602081850181015186830182015201610d2f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610cfc6020830184610d25565b803567ffffffffffffffff81168114610db457600080fd5b919050565b600060208284031215610dcb57600080fd5b610cfc82610d9c565b600060208284031215610de657600080fd5b813567ffffffffffffffff811115610dfd57600080fd5b820160a08185031215610cfc57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610db457600080fd5b600060208284031215610e4557600080fd5b610cfc82610e0f565b60008060408385031215610e6157600080fd5b610e6a83610d9c565b9150610e7860208401610e0f565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610ed357610ed3610e81565b60405290565b60405160a0810167ffffffffffffffff81118282101715610ed357610ed3610e81565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610f4357610f43610e81565b604052919050565b600082601f830112610f5c57600080fd5b813567ffffffffffffffff811115610f7657610f76610e81565b610fa760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610efc565b818152846020838601011115610fbc57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610fea57600080fd5b8135602067ffffffffffffffff82111561100657611006610e81565b611014818360051b01610efc565b82815260069290921b8401810191818101908684111561103357600080fd5b8286015b8481101561107957604081890312156110505760008081fd5b611058610eb0565b61106182610e0f565b81528185013585820152835291830191604001611037565b509695505050505050565b600060a0823603121561109657600080fd5b61109e610ed9565b823581526110ae60208401610d9c565b6020820152604083013567ffffffffffffffff808211156110ce57600080fd5b6110da36838701610f4b565b604084015260608501359150808211156110f357600080fd5b6110ff36838701610f4b565b6060840152608085013591508082111561111857600080fd5b5061112536828601610fd9565b60808301525092915050565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261116060e0860182610d25565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087840301606088015261119b8383610d25565b6040890151888203830160808a01528051808352908601945060009350908501905b808410156111fc578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906111bd565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506112388187610d25565b9a9950505050505050505050565b60006020828403121561125857600080fd5b5051919050565b808201808211156103f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", } var PingPongDemoABI = PingPongDemoMetaData.ABI @@ -250,6 +250,28 @@ func (_PingPongDemo *PingPongDemoCallerSession) GetFeeToken() (common.Address, e return _PingPongDemo.Contract.GetFeeToken(&_PingPongDemo.CallOpts) } +func (_PingPongDemo *PingPongDemoCaller) GetOutOfOrderExecution(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _PingPongDemo.contract.Call(opts, &out, "getOutOfOrderExecution") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_PingPongDemo *PingPongDemoSession) GetOutOfOrderExecution() (bool, error) { + return _PingPongDemo.Contract.GetOutOfOrderExecution(&_PingPongDemo.CallOpts) +} + +func (_PingPongDemo *PingPongDemoCallerSession) GetOutOfOrderExecution() (bool, error) { + return _PingPongDemo.Contract.GetOutOfOrderExecution(&_PingPongDemo.CallOpts) +} + func (_PingPongDemo *PingPongDemoCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _PingPongDemo.contract.Call(opts, &out, "getRouter") @@ -420,6 +442,18 @@ func (_PingPongDemo *PingPongDemoTransactorSession) SetCounterpartChainSelector( return _PingPongDemo.Contract.SetCounterpartChainSelector(&_PingPongDemo.TransactOpts, chainSelector) } +func (_PingPongDemo *PingPongDemoTransactor) SetOutOfOrderExecution(opts *bind.TransactOpts, outOfOrderExecution bool) (*types.Transaction, error) { + return _PingPongDemo.contract.Transact(opts, "setOutOfOrderExecution", outOfOrderExecution) +} + +func (_PingPongDemo *PingPongDemoSession) SetOutOfOrderExecution(outOfOrderExecution bool) (*types.Transaction, error) { + return _PingPongDemo.Contract.SetOutOfOrderExecution(&_PingPongDemo.TransactOpts, outOfOrderExecution) +} + +func (_PingPongDemo *PingPongDemoTransactorSession) SetOutOfOrderExecution(outOfOrderExecution bool) (*types.Transaction, error) { + return _PingPongDemo.Contract.SetOutOfOrderExecution(&_PingPongDemo.TransactOpts, outOfOrderExecution) +} + func (_PingPongDemo *PingPongDemoTransactor) SetPaused(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) { return _PingPongDemo.contract.Transact(opts, "setPaused", pause) } @@ -456,6 +490,123 @@ func (_PingPongDemo *PingPongDemoTransactorSession) TransferOwnership(to common. return _PingPongDemo.Contract.TransferOwnership(&_PingPongDemo.TransactOpts, to) } +type PingPongDemoOutOfOrderExecutionChangeIterator struct { + Event *PingPongDemoOutOfOrderExecutionChange + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PingPongDemoOutOfOrderExecutionChangeIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PingPongDemoOutOfOrderExecutionChange) + 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(PingPongDemoOutOfOrderExecutionChange) + 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 *PingPongDemoOutOfOrderExecutionChangeIterator) Error() error { + return it.fail +} + +func (it *PingPongDemoOutOfOrderExecutionChangeIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PingPongDemoOutOfOrderExecutionChange struct { + IsOutOfOrder bool + Raw types.Log +} + +func (_PingPongDemo *PingPongDemoFilterer) FilterOutOfOrderExecutionChange(opts *bind.FilterOpts) (*PingPongDemoOutOfOrderExecutionChangeIterator, error) { + + logs, sub, err := _PingPongDemo.contract.FilterLogs(opts, "OutOfOrderExecutionChange") + if err != nil { + return nil, err + } + return &PingPongDemoOutOfOrderExecutionChangeIterator{contract: _PingPongDemo.contract, event: "OutOfOrderExecutionChange", logs: logs, sub: sub}, nil +} + +func (_PingPongDemo *PingPongDemoFilterer) WatchOutOfOrderExecutionChange(opts *bind.WatchOpts, sink chan<- *PingPongDemoOutOfOrderExecutionChange) (event.Subscription, error) { + + logs, sub, err := _PingPongDemo.contract.WatchLogs(opts, "OutOfOrderExecutionChange") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PingPongDemoOutOfOrderExecutionChange) + if err := _PingPongDemo.contract.UnpackLog(event, "OutOfOrderExecutionChange", 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 (_PingPongDemo *PingPongDemoFilterer) ParseOutOfOrderExecutionChange(log types.Log) (*PingPongDemoOutOfOrderExecutionChange, error) { + event := new(PingPongDemoOutOfOrderExecutionChange) + if err := _PingPongDemo.contract.UnpackLog(event, "OutOfOrderExecutionChange", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type PingPongDemoOwnershipTransferRequestedIterator struct { Event *PingPongDemoOwnershipTransferRequested @@ -964,6 +1115,8 @@ func (_PingPongDemo *PingPongDemoFilterer) ParsePong(log types.Log) (*PingPongDe func (_PingPongDemo *PingPongDemo) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { + case _PingPongDemo.abi.Events["OutOfOrderExecutionChange"].ID: + return _PingPongDemo.ParseOutOfOrderExecutionChange(log) case _PingPongDemo.abi.Events["OwnershipTransferRequested"].ID: return _PingPongDemo.ParseOwnershipTransferRequested(log) case _PingPongDemo.abi.Events["OwnershipTransferred"].ID: @@ -978,6 +1131,10 @@ func (_PingPongDemo *PingPongDemo) ParseLog(log types.Log) (generated.AbigenLog, } } +func (PingPongDemoOutOfOrderExecutionChange) Topic() common.Hash { + return common.HexToHash("0x05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd9") +} + func (PingPongDemoOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1005,6 +1162,8 @@ type PingPongDemoInterface interface { GetFeeToken(opts *bind.CallOpts) (common.Address, error) + GetOutOfOrderExecution(opts *bind.CallOpts) (bool, error) + GetRouter(opts *bind.CallOpts) (common.Address, error) IsPaused(opts *bind.CallOpts) (bool, error) @@ -1025,12 +1184,20 @@ type PingPongDemoInterface interface { SetCounterpartChainSelector(opts *bind.TransactOpts, chainSelector uint64) (*types.Transaction, error) + SetOutOfOrderExecution(opts *bind.TransactOpts, outOfOrderExecution bool) (*types.Transaction, error) + SetPaused(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) StartPingPong(opts *bind.TransactOpts) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + FilterOutOfOrderExecutionChange(opts *bind.FilterOpts) (*PingPongDemoOutOfOrderExecutionChangeIterator, error) + + WatchOutOfOrderExecutionChange(opts *bind.WatchOpts, sink chan<- *PingPongDemoOutOfOrderExecutionChange) (event.Subscription, error) + + ParseOutOfOrderExecutionChange(log types.Log) (*PingPongDemoOutOfOrderExecutionChange, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PingPongDemoOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PingPongDemoOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generated/price_registry/price_registry.go b/core/gethwrappers/ccip/generated/price_registry/price_registry.go deleted file mode 100644 index 19f1bd4a190..00000000000 --- a/core/gethwrappers/ccip/generated/price_registry/price_registry.go +++ /dev/null @@ -1,3141 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package price_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 AuthorizedCallersAuthorizedCallerArgs struct { - AddedCallers []common.Address - RemovedCallers []common.Address -} - -type ClientEVM2AnyMessage struct { - Receiver []byte - Data []byte - TokenAmounts []ClientEVMTokenAmount - FeeToken common.Address - ExtraArgs []byte -} - -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - -type IPriceRegistryTokenPriceFeedConfig struct { - DataFeedAddress common.Address - TokenDecimals uint8 -} - -type InternalGasPriceUpdate struct { - DestChainSelector uint64 - UsdPerUnitGas *big.Int -} - -type InternalPriceUpdates struct { - TokenPriceUpdates []InternalTokenPriceUpdate - GasPriceUpdates []InternalGasPriceUpdate -} - -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int -} - -type InternalTimestampedPackedUint224 struct { - Value *big.Int - Timestamp uint32 -} - -type InternalTokenPriceUpdate struct { - SourceToken common.Address - UsdPerToken *big.Int -} - -type PriceRegistryDestChainConfig struct { - IsEnabled bool - MaxNumberOfTokensPerMsg uint16 - MaxDataBytes uint32 - MaxPerMsgGasLimit uint32 - DestGasOverhead uint32 - DestGasPerPayloadByte uint16 - DestDataAvailabilityOverheadGas uint32 - DestGasPerDataAvailabilityByte uint16 - DestDataAvailabilityMultiplierBps uint16 - DefaultTokenFeeUSDCents uint16 - DefaultTokenDestGasOverhead uint32 - DefaultTokenDestBytesOverhead uint32 - DefaultTxGasLimit uint32 - GasMultiplierWeiPerEth uint64 - NetworkFeeUSDCents uint32 - EnforceOutOfOrder bool - ChainFamilySelector [4]byte -} - -type PriceRegistryDestChainConfigArgs struct { - DestChainSelector uint64 - DestChainConfig PriceRegistryDestChainConfig -} - -type PriceRegistryPremiumMultiplierWeiPerEthArgs struct { - Token common.Address - PremiumMultiplierWeiPerEth uint64 -} - -type PriceRegistryStaticConfig struct { - MaxFeeJuelsPerMsg *big.Int - LinkToken common.Address - StalenessThreshold uint32 -} - -type PriceRegistryTokenPriceFeedUpdate struct { - SourceToken common.Address - FeedConfig IPriceRegistryTokenPriceFeedConfig -} - -type PriceRegistryTokenTransferFeeConfig struct { - MinFeeUSDCents uint32 - MaxFeeUSDCents uint32 - DeciBps uint16 - DestGasOverhead uint32 - DestBytesOverhead uint32 - IsEnabled bool -} - -type PriceRegistryTokenTransferFeeConfigArgs struct { - DestChainSelector uint64 - TokenTransferFeeConfigs []PriceRegistryTokenTransferFeeConfigSingleTokenArgs -} - -type PriceRegistryTokenTransferFeeConfigRemoveArgs struct { - DestChainSelector uint64 - Token common.Address -} - -type PriceRegistryTokenTransferFeeConfigSingleTokenArgs struct { - Token common.Address - TokenTransferFeeConfig PriceRegistryTokenTransferFeeConfig -} - -var PriceRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.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\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.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\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.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\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"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\"},{\"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\":[],\"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\":[{\"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\":[],\"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\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.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\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.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\"}],\"indexed\":false,\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterSet\",\"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\":\"structPriceRegistry.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\":\"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\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.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\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structPriceRegistry.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\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.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\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.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\":\"structIPriceRegistry.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\":\"structPriceRegistry.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\":[],\"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\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"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\"},{\"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\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"validatePoolReturnData\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620069373803806200693783398101604081905262000034916200180a565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a99565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b65565b5050505050505062001ac8565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001929565b60209081029190910101519050620002f560028262000e98565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001929565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000eb8565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001929565b6020026020010151600c62000eb860201b90919060201c565b1562000499578281815181106200045b576200045b62001929565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001929565b6020026020010151600c62000e9860201b90919060201c565b156200053b57818181518110620004fd57620004fd62001929565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001929565b6020908102919091018101518051818301516001600160a01b0380831660008181526006875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001929565b6020026020010151905060008383815181106200065f576200065f62001929565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061018081015163ffffffff16155b80620006ba57506102008101516001600160e01b031916630a04b54b60e21b14155b80620006d15750602081610160015163ffffffff16105b80620006f15750806060015163ffffffff1681610180015163ffffffff16115b156200071c5760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260086020526040812060010154600160a81b900460e01b6001600160e01b03191690036200079c57816001600160401b03167fa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577826040516200078e91906200193f565b60405180910390a2620007e0565b816001600160401b03167fa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad9382604051620007d791906200193f565b60405180910390a25b8060086000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101a08201518160010160086101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000abd5762000abd62001929565b6020026020010151600001519050600083838151811062000ae25762000ae262001929565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a9c565b60005b825181101562000dd257600083828151811062000b895762000b8962001929565b6020026020010151905060008160000151905060005b82602001515181101562000dc35760008360200151828151811062000bc85762000bc862001929565b602002602001015160200151905060008460200151838151811062000bf15762000bf162001929565b60200260200101516000015190506020826080015163ffffffff16101562000c4a5760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526009602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000db0908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b9f565b50505080600101905062000b68565b5060005b81518110156200054457600082828151811062000df75762000df762001929565b6020026020010151600001519050600083838151811062000e1c5762000e1c62001929565b6020908102919091018101518101516001600160401b03841660008181526009845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd6565b600062000eaf836001600160a01b03841662000ecf565b90505b92915050565b600062000eaf836001600160a01b03841662000fd3565b6000818152600183016020526040812054801562000fc857600062000ef660018362001a90565b855490915060009062000f0c9060019062001a90565b905081811462000f7857600086600001828154811062000f305762000f3062001929565b906000526020600020015490508087600001848154811062000f565762000f5662001929565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f8c5762000f8c62001ab2565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb2565b600091505062000eb2565b60008181526001830160205260408120546200101c5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb2565b50600062000eb2565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171562001060576200106062001025565b60405290565b60405160c081016001600160401b038111828210171562001060576200106062001025565b60405161022081016001600160401b038111828210171562001060576200106062001025565b604051601f8201601f191681016001600160401b0381118282101715620010dc57620010dc62001025565b604052919050565b80516001600160a01b0381168114620010fc57600080fd5b919050565b805163ffffffff81168114620010fc57600080fd5b6000606082840312156200112957600080fd5b604051606081016001600160401b03811182821017156200114e576200114e62001025565b604052825190915081906001600160601b03811681146200116e57600080fd5b81526200117e60208401620010e4565b6020820152620011916040840162001101565b60408201525092915050565b60006001600160401b03821115620011b957620011b962001025565b5060051b60200190565b600082601f830112620011d557600080fd5b81516020620011ee620011e8836200119d565b620010b1565b8083825260208201915060208460051b8701019350868411156200121157600080fd5b602086015b8481101562001238576200122a81620010e4565b835291830191830162001216565b509695505050505050565b600082601f8301126200125557600080fd5b8151602062001268620011e8836200119d565b828152606092830285018201928282019190878511156200128857600080fd5b8387015b858110156200131b5780890382811215620012a75760008081fd5b620012b16200103b565b620012bc83620010e4565b8152604080601f1984011215620012d35760008081fd5b620012dd6200103b565b9250620012ec888501620010e4565b835283015160ff81168114620013025760008081fd5b828801528087019190915284529284019281016200128c565b5090979650505050505050565b80516001600160401b0381168114620010fc57600080fd5b805161ffff81168114620010fc57600080fd5b80518015158114620010fc57600080fd5b600082601f8301126200137657600080fd5b8151602062001389620011e8836200119d565b82815260059290921b84018101918181019086841115620013a957600080fd5b8286015b84811015620012385780516001600160401b0380821115620013ce57600080fd5b908801906040601f19838c038101821315620013e957600080fd5b620013f36200103b565b6200140089860162001328565b815282850151848111156200141457600080fd5b8086019550508c603f8601126200142a57600080fd5b8885015193506200143f620011e8856200119d565b84815260e09094028501830193898101908e8611156200145e57600080fd5b958401955b858710156200153757868f0360e08112156200147e57600080fd5b620014886200103b565b6200149389620010e4565b815260c08683011215620014a657600080fd5b620014b062001066565b9150620014bf8d8a0162001101565b8252620014ce878a0162001101565b8d830152620014e060608a0162001340565b87830152620014f260808a0162001101565b60608301526200150560a08a0162001101565b60808301526200151860c08a0162001353565b60a0830152808d0191909152825260e09690960195908a019062001463565b828b015250875250505092840192508301620013ad565b600082601f8301126200156057600080fd5b8151602062001573620011e8836200119d565b82815260069290921b840181019181810190868411156200159357600080fd5b8286015b84811015620012385760408189031215620015b25760008081fd5b620015bc6200103b565b620015c782620010e4565b8152620015d685830162001328565b8186015283529183019160400162001597565b80516001600160e01b031981168114620010fc57600080fd5b600082601f8301126200161457600080fd5b8151602062001627620011e8836200119d565b82815261024092830285018201928282019190878511156200164857600080fd5b8387015b858110156200131b5780890382811215620016675760008081fd5b620016716200103b565b6200167c8362001328565b815261022080601f1984011215620016945760008081fd5b6200169e6200108b565b9250620016ad88850162001353565b83526040620016be81860162001340565b898501526060620016d181870162001101565b8286015260809150620016e682870162001101565b9085015260a0620016f986820162001101565b8286015260c091506200170e82870162001340565b9085015260e06200172186820162001101565b8286015261010091506200173782870162001340565b908501526101206200174b86820162001340565b8286015261014091506200176182870162001340565b908501526101606200177586820162001101565b8286015261018091506200178b82870162001101565b908501526101a06200179f86820162001101565b828601526101c09150620017b582870162001328565b908501526101e0620017c986820162001101565b828601526102009150620017df82870162001353565b90850152620017f0858301620015e9565b90840152508087019190915284529284019281016200164c565b6000806000806000806000610120888a0312156200182757600080fd5b62001833898962001116565b60608901519097506001600160401b03808211156200185157600080fd5b6200185f8b838c01620011c3565b975060808a01519150808211156200187657600080fd5b620018848b838c01620011c3565b965060a08a01519150808211156200189b57600080fd5b620018a98b838c0162001243565b955060c08a0151915080821115620018c057600080fd5b620018ce8b838c0162001364565b945060e08a0151915080821115620018e557600080fd5b620018f38b838c016200154e565b93506101008a01519150808211156200190b57600080fd5b506200191a8a828b0162001602565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b8151151581526102208101602083015162001960602084018261ffff169052565b50604083015162001979604084018263ffffffff169052565b50606083015162001992606084018263ffffffff169052565b506080830151620019ab608084018263ffffffff169052565b5060a0830151620019c260a084018261ffff169052565b5060c0830151620019db60c084018263ffffffff169052565b5060e0830151620019f260e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501518216908401526101a0808501516001600160401b0316908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb257634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051614e1562001b22600039600081816102d901528181611ad30152611b3c01526000818161029d0152818161104e01526110ae015260008181610269015281816110d701526111470152614e156000f3fe608060405234801561001057600080fd5b50600436106101b85760003560e01c80637afac322116100f9578063cc88924c11610097578063d8694ccd11610071578063d8694ccd14610a5c578063f2fde38b14610a6f578063f700042a14610a82578063ffdb4b3714610a9557600080fd5b8063cc88924c14610a2e578063cdc73d5114610a41578063d02641a014610a4957600080fd5b806391a2749a116100d357806391a2749a14610939578063a69c64c01461094c578063bf78e03f1461095f578063c4276bfc14610a0c57600080fd5b80637afac3221461078e57806382b49eb0146107a15780638da5cb5b1461091157600080fd5b8063407e108611610166578063514e8cff11610140578063514e8cff146104385780636def4ce7146104db578063770e2dc41461077357806379ba50971461078657600080fd5b8063407e1086146103c557806345ac924d146103d85780634ab35b0b146103f857600080fd5b8063181f5a7711610197578063181f5a77146103525780632451a6271461039b5780633937306f146103b057600080fd5b806241e5be146101bd578063061877e3146101e357806306285c691461023c575b600080fd5b6101d06101cb366004613802565b610add565b6040519081526020015b60405180910390f35b6102236101f136600461383e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101da565b610306604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101da565b61038e6040518060400160405280601781526020017f5072696365526567697374727920312e362e302d64657600000000000000000081525081565b6040516101da91906138bd565b6103a3610b4b565b6040516101da91906138d0565b6103c36103be36600461392a565b610b5c565b005b6103c36103d3366004613a86565b610e11565b6103eb6103e6366004613be4565b610e25565b6040516101da9190613c26565b61040b61040636600461383e565b610ef0565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101da565b6104ce610446366004613cb9565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101da9190613cd4565b6107666104e9366004613cb9565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260086020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b010000000000000000000000000000000000000000000000000000009092048616610140840152600190930154808616610160840152640100000000810486166101808401526801000000000000000081049096166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101da9190613d0f565b6103c3610781366004613f4c565b610efb565b6103c3610f11565b6103c361079c366004614266565b611013565b6108b16107af3660046142ca565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff91909116600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101da9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101da565b6103c36109473660046142f4565b611025565b6103c361095a366004614385565b611036565b6109d861096d36600461383e565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526006825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101da565b610a1f610a1a36600461444a565b611047565b6040516101da939291906144e5565b6103c3610a3c36600461450f565b611245565b6103a361141b565b6104ce610a5736600461383e565b611427565b6101d0610a6a3660046145aa565b611523565b6103c3610a7d36600461383e565b6119dd565b6103c3610a9036600461462f565b6119ee565b610aa8610aa336600461484f565b6119ff565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101da565b6000610ae882611b8a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b0f85611b8a565b610b37907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856148a8565b610b4191906148bf565b90505b9392505050565b6060610b576002611c24565b905090565b610b64611c31565b6000610b7082806148fa565b9050905060005b81811015610cba576000610b8b84806148fa565b83818110610b9b57610b9b614962565b905060400201803603810190610bb191906149bd565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610ca99290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610b77565b506000610cca60208401846148fa565b9050905060005b81811015610e0b576000610ce860208601866148fa565b83818110610cf857610cf8614962565b905060400201803603810190610d0e91906149fa565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600490975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610dfa9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610cd1565b50505050565b610e19611c76565b610e2281611cf7565b50565b60608160008167ffffffffffffffff811115610e4357610e43613965565b604051908082528060200260200182016040528015610e8857816020015b6040805180820190915260008082526020820152815260200190600190039081610e615790505b50905060005b82811015610ee557610ec0868683818110610eab57610eab614962565b9050602002016020810190610a57919061383e565b828281518110610ed257610ed2614962565b6020908102919091010152600101610e8e565b509150505b92915050565b6000610eea82611b8a565b610f03611c76565b610f0d8282611df5565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61101b611c76565b610f0d8282612201565b61102d611c76565b610e2281612348565b61103e611c76565b610e22816124d4565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036110a7578592506110d5565b6110d287877f0000000000000000000000000000000000000000000000000000000000000000610add565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611174576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610f8e565b67ffffffffffffffff8816600090815260086020526040812060010154640100000000900463ffffffff16906111ab8787846125be565b9050806020015193508484611232836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b67ffffffffffffffff85166000908152600860205260408120600101547501000000000000000000000000000000000000000000900460e01b905b8481101561141257600084848381811061129c5761129c614962565b6112b2926020604090920201908101915061383e565b905060008787848181106112c8576112c8614962565b90506020028101906112da9190614a1d565b6112e8906040810190614a5b565b91505060208111156113985767ffffffffffffffff8916600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115611398576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610f8e565b611408848989868181106113ae576113ae614962565b90506020028101906113c09190614a1d565b6113ce906020810190614a5b565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061276792505050565b5050600101611280565b50505050505050565b6060610b57600c611c24565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600660209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff16908201529061151a57505073ffffffffffffffffffffffffffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b44816127b9565b67ffffffffffffffff8083166000908152600860209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b010000000000000000000000000000000000000000000000000000009093048616610140850152600190940154808616610160850152640100000000810486166101808501526801000000000000000081049098166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611759576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610f8e565b600061176860408501856148fa565b91506117c490508261177d6020870187614a5b565b90508361178a8880614a5b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506129fc92505050565b60006007816117d9608088016060890161383e565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff169150806118286118226080890160608a0161383e565b896119ff565b909250905060008080861561186e57611862888c61184c60808e0160608f0161383e565b888e806040019061185d91906148fa565b612aa6565b9194509250905061188e565b6101c088015161188b9063ffffffff16662386f26fc100006148a8565b92505b61010088015160009061ffff16156118d2576118cf896dffffffffffffffffffffffffffff607088901c166118c660208f018f614a5b565b90508b86612d84565b90505b6101a089015160009067ffffffffffffffff166118fb6118f560808f018f614a5b565b8d612e33565b600001518563ffffffff168c60a0015161ffff168f806020019061191f9190614a5b565b61192a9291506148a8565b8d6080015163ffffffff1661193f9190614ac0565b6119499190614ac0565b6119539190614ac0565b61196d906dffffffffffffffffffffffffffff89166148a8565b61197791906148a8565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff871682826119ae67ffffffffffffffff8c16896148a8565b6119b89190614ac0565b6119c29190614ac0565b6119cc91906148bf565b9d9c50505050505050505050505050565b6119e5611c76565b610e2281612ef4565b6119f6611c76565b610e2281612fe9565b67ffffffffffffffff811660009081526004602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203611ab7576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610f8e565b6000816020015163ffffffff1642611acf9190614ad3565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115611b70576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610f8e565b611b7986611b8a565b9151919350909150505b9250929050565b600080611b9683611427565b9050806020015163ffffffff1660001480611bce575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15611c1d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610f8e565b5192915050565b60606000610b44836134d1565b611c3c60023361352d565b611c74576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610f8e565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314611c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610f8e565b60005b8151811015610f0d576000828281518110611d1757611d17614962565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526006875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050611cfa565b60005b8251811015612118576000838281518110611e1557611e15614962565b6020026020010151905060008160000151905060005b82602001515181101561210a57600083602001518281518110611e5057611e50614962565b6020026020010151602001519050600084602001518381518110611e7657611e76614962565b60200260200101516000015190506020826080015163ffffffff161015611ef35760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610f8e565b67ffffffffffffffff8416600081815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906120f8908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611e2b565b505050806001019050611df8565b5060005b81518110156121fc57600082828151811061213957612139614962565b6020026020010151600001519050600083838151811061215b5761215b614962565b60209081029190910181015181015167ffffffffffffffff8416600081815260098452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010161211c565b505050565b60005b82518110156122a45761223a83828151811061222257612222614962565b6020026020010151600c61355c90919063ffffffff16565b1561229c5782818151811061225157612251614962565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612204565b5060005b81518110156121fc576122de8282815181106122c6576122c6614962565b6020026020010151600c61357e90919063ffffffff16565b15612340578181815181106122f5576122f5614962565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016122a8565b602081015160005b81518110156123e357600082828151811061236d5761236d614962565b6020026020010151905061238b81600261357e90919063ffffffff16565b156123da5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612350565b50815160005b8151811015610e0b57600082828151811061240657612406614962565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612476576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61248160028261355c565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016123e9565b60005b8151811015610f0d5760008282815181106124f4576124f4614962565b6020026020010151600001519050600083838151811061251657612516614962565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016124d7565b604080518082019091526000808252602082015260008390036125ff57506040805180820190915267ffffffffffffffff8216815260006020820152610b44565b600061260b8486614ae6565b9050600061261c8560048189614b2c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016126b957808060200190518101906126b09190614b56565b92505050610b44565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601612735576040518060400160405280828060200190518101906127219190614b82565b815260006020909101529250610b44915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610f0d576121fc816135a0565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128479190614bb5565b5050509150506000811215612888576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000819050600085602001518473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129039190614c05565b61290d9190614c22565b905060248160ff16111561294257612926602482614c3b565b61293190600a614d74565b61293b90836148bf565b9150612965565b61294d816024614c3b565b61295890600a614d74565b61296290836148a8565b91505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156129bb576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff42166020820152949350505050565b836040015163ffffffff16831115612a555760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610f8e565b836020015161ffff16821115612a97576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0b84610200015182612767565b6000808083815b81811015612d76576000878783818110612ac957612ac9614962565b905060400201803603810190612adf9190614d83565b67ffffffffffffffff8c166000908152600960209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090612c05576101208d0151612bcc9061ffff16662386f26fc100006148a8565b612bd69088614ac0565b96508c610140015186612be99190614dbc565b95508c610160015185612bfc9190614dbc565b94505050612d6e565b604081015160009061ffff1615612cbe5760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614612c61578351612c5a90611b8a565b9050612c64565b508a5b620186a0836040015161ffff16612ca68660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661365390919063ffffffff16565b612cb091906148a8565b612cba91906148bf565b9150505b6060820151612ccd9088614dbc565b9650816080015186612cdf9190614dbc565b8251909650600090612cfe9063ffffffff16662386f26fc100006148a8565b905080821015612d1d57612d12818a614ac0565b985050505050612d6e565b6000836020015163ffffffff16662386f26fc10000612d3c91906148a8565b905080831115612d5c57612d50818b614ac0565b99505050505050612d6e565b612d66838b614ac0565b995050505050505b600101612aad565b505096509650969350505050565b60008063ffffffff8316612d9960e0866148a8565b612da5876101c0614ac0565b612daf9190614ac0565b612db99190614ac0565b905060008760c0015163ffffffff168860e0015161ffff1683612ddc91906148a8565b612de69190614ac0565b61010089015190915061ffff16612e0d6dffffffffffffffffffffffffffff8916836148a8565b612e1791906148a8565b612e2790655af3107a40006148a8565b98975050505050505050565b60408051808201909152600080825260208201526000612e5f858585610180015163ffffffff166125be565b9050826060015163ffffffff1681600001511115612ea9576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015612ebd57508060200151155b15610b41576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603612f73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610f8e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015610f0d57600082828151811061300957613009614962565b60200260200101519050600083838151811061302757613027614962565b60200260200101516000015190506000826020015190508167ffffffffffffffff1660001480613060575061018081015163ffffffff16155b806130b257506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806130c85750602081610160015163ffffffff16105b806130e75750806060015163ffffffff1681610180015163ffffffff16115b1561312a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610f8e565b67ffffffffffffffff82166000908152600860205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036131d2578167ffffffffffffffff167fa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577826040516131c59190613d0f565b60405180910390a2613215565b8167ffffffffffffffff167fa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad938260405161320c9190613d0f565b60405180910390a25b80600860008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101a08201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612fec565b60608160000180548060200260200160405190810160405280929190818152602001828054801561352157602002820191906000526020600020905b81548152602001906001019080831161350d575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b44565b6000610b448373ffffffffffffffffffffffffffffffffffffffff8416613690565b6000610b448373ffffffffffffffffffffffffffffffffffffffff84166136df565b600081516020146135df57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610f8e91906138bd565b6000828060200190518101906135f59190614b82565b905073ffffffffffffffffffffffffffffffffffffffff81118061361a575061040081105b15610eea57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610f8e91906138bd565b6000670de0b6b3a7640000613686837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166148a8565b610b4491906148bf565b60008181526001830160205260408120546136d757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610eea565b506000610eea565b600081815260018301602052604081205480156137c8576000613703600183614ad3565b855490915060009061371790600190614ad3565b905081811461377c57600086600001828154811061373757613737614962565b906000526020600020015490508087600001848154811061375a5761375a614962565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061378d5761378d614dd9565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610eea565b6000915050610eea565b5092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137fd57600080fd5b919050565b60008060006060848603121561381757600080fd5b613820846137d9565b925060208401359150613835604085016137d9565b90509250925092565b60006020828403121561385057600080fd5b610b44826137d9565b6000815180845260005b8181101561387f57602081850181015186830182015201613863565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b446020830184613859565b6020808252825182820181905260009190848201906040850190845b8181101561391e57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016138ec565b50909695505050505050565b60006020828403121561393c57600080fd5b813567ffffffffffffffff81111561395357600080fd5b820160408185031215610b4457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156139b7576139b7613965565b60405290565b60405160c0810167ffffffffffffffff811182821017156139b7576139b7613965565b604051610220810167ffffffffffffffff811182821017156139b7576139b7613965565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a4b57613a4b613965565b604052919050565b600067ffffffffffffffff821115613a6d57613a6d613965565b5060051b60200190565b60ff81168114610e2257600080fd5b60006020808385031215613a9957600080fd5b823567ffffffffffffffff811115613ab057600080fd5b8301601f81018513613ac157600080fd5b8035613ad4613acf82613a53565b613a04565b81815260609182028301840191848201919088841115613af357600080fd5b938501935b83851015613b935784890381811215613b115760008081fd5b613b19613994565b613b22876137d9565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215613b565760008081fd5b613b5e613994565b9250613b6b8989016137d9565b8352870135613b7981613a77565b828901528088019190915283529384019391850191613af8565b50979650505050505050565b60008083601f840112613bb157600080fd5b50813567ffffffffffffffff811115613bc957600080fd5b6020830191508360208260051b8501011115611b8357600080fd5b60008060208385031215613bf757600080fd5b823567ffffffffffffffff811115613c0e57600080fd5b613c1a85828601613b9f565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015613c9457613c8484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101613c43565b5091979650505050505050565b803567ffffffffffffffff811681146137fd57600080fd5b600060208284031215613ccb57600080fd5b610b4482613ca1565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610eea565b81511515815261022081016020830151613d2f602084018261ffff169052565b506040830151613d47604084018263ffffffff169052565b506060830151613d5f606084018263ffffffff169052565b506080830151613d77608084018263ffffffff169052565b5060a0830151613d8d60a084018261ffff169052565b5060c0830151613da560c084018263ffffffff169052565b5060e0830151613dbb60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501518216908401526101a08085015167ffffffffffffffff16908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146137fd57600080fd5b803561ffff811681146137fd57600080fd5b8015158114610e2257600080fd5b80356137fd81613e9b565b600082601f830112613ec557600080fd5b81356020613ed5613acf83613a53565b82815260069290921b84018101918181019086841115613ef457600080fd5b8286015b84811015613f415760408189031215613f115760008081fd5b613f19613994565b613f2282613ca1565b8152613f2f8583016137d9565b81860152835291830191604001613ef8565b509695505050505050565b60008060408385031215613f5f57600080fd5b67ffffffffffffffff83351115613f7557600080fd5b83601f843585010112613f8757600080fd5b613f97613acf8435850135613a53565b8335840180358083526020808401939260059290921b90910101861015613fbd57600080fd5b602085358601015b85358601803560051b016020018110156141ca5767ffffffffffffffff81351115613fef57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561402857600080fd5b614030613994565b61403c60208301613ca1565b815267ffffffffffffffff6040830135111561405757600080fd5b88603f60408401358401011261406c57600080fd5b614082613acf6020604085013585010135613a53565b6020604084810135850182810135808552928401939260e00201018b10156140a957600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156141ab5760e0818d0312156140dc57600080fd5b6140e4613994565b6140ed826137d9565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f0301121561412157600080fd5b6141296139bd565b61413560208401613e75565b815261414360408401613e75565b602082015261415460608401613e89565b604082015261416560808401613e75565b606082015261417660a08401613e75565b608082015261418860c0840135613e9b565b60c083013560a0820152602082810191909152908452929092019160e0016140b3565b5080602084015250508085525050602083019250602081019050613fc5565b5092505067ffffffffffffffff602084013511156141e757600080fd5b6141f78460208501358501613eb4565b90509250929050565b600082601f83011261421157600080fd5b81356020614221613acf83613a53565b8083825260208201915060208460051b87010193508684111561424357600080fd5b602086015b84811015613f4157614259816137d9565b8352918301918301614248565b6000806040838503121561427957600080fd5b823567ffffffffffffffff8082111561429157600080fd5b61429d86838701614200565b935060208501359150808211156142b357600080fd5b506142c085828601614200565b9150509250929050565b600080604083850312156142dd57600080fd5b6142e683613ca1565b91506141f7602084016137d9565b60006020828403121561430657600080fd5b813567ffffffffffffffff8082111561431e57600080fd5b908301906040828603121561433257600080fd5b61433a613994565b82358281111561434957600080fd5b61435587828601614200565b82525060208301358281111561436a57600080fd5b61437687828601614200565b60208301525095945050505050565b6000602080838503121561439857600080fd5b823567ffffffffffffffff8111156143af57600080fd5b8301601f810185136143c057600080fd5b80356143ce613acf82613a53565b81815260069190911b820183019083810190878311156143ed57600080fd5b928401925b8284101561443f576040848903121561440b5760008081fd5b614413613994565b61441c856137d9565b8152614429868601613ca1565b81870152825260409390930192908401906143f2565b979650505050505050565b60008060008060006080868803121561446257600080fd5b61446b86613ca1565b9450614479602087016137d9565b935060408601359250606086013567ffffffffffffffff8082111561449d57600080fd5b818801915088601f8301126144b157600080fd5b8135818111156144c057600080fd5b8960208285010111156144d257600080fd5b9699959850939650602001949392505050565b83815282151560208201526060604082015260006145066060830184613859565b95945050505050565b60008060008060006060868803121561452757600080fd5b61453086613ca1565b9450602086013567ffffffffffffffff8082111561454d57600080fd5b61455989838a01613b9f565b9096509450604088013591508082111561457257600080fd5b818801915088601f83011261458657600080fd5b81358181111561459557600080fd5b8960208260061b85010111156144d257600080fd5b600080604083850312156145bd57600080fd5b6145c683613ca1565b9150602083013567ffffffffffffffff8111156145e257600080fd5b830160a081860312156145f457600080fd5b809150509250929050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146137fd57600080fd5b6000602080838503121561464257600080fd5b823567ffffffffffffffff81111561465957600080fd5b8301601f8101851361466a57600080fd5b8035614678613acf82613a53565b818152610240918202830184019184820191908884111561469857600080fd5b938501935b83851015613b9357848903818112156146b65760008081fd5b6146be613994565b6146c787613ca1565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156146fc5760008081fd5b6147046139e0565b9250614711898901613ea9565b83526040614720818a01613e89565b8a8501526060614731818b01613e75565b8286015260809150614744828b01613e75565b9085015260a06147558a8201613e75565b8286015260c09150614768828b01613e89565b9085015260e06147798a8201613e75565b82860152610100915061478d828b01613e89565b9085015261012061479f8a8201613e89565b8286015261014091506147b3828b01613e89565b908501526101606147c58a8201613e75565b8286015261018091506147d9828b01613e75565b908501526101a06147eb8a8201613e75565b828601526101c091506147ff828b01613ca1565b908501526101e06148118a8201613e75565b828601526102009150614825828b01613ea9565b908501526148348983016145ff565b9084015250808801919091528352938401939185019161469d565b6000806040838503121561486257600080fd5b61486b836137d9565b91506141f760208401613ca1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610eea57610eea614879565b6000826148f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261492f57600080fd5b83018035915067ffffffffffffffff82111561494a57600080fd5b6020019150600681901b3603821315611b8357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146137fd57600080fd5b6000604082840312156149cf57600080fd5b6149d7613994565b6149e0836137d9565b81526149ee60208401614991565b60208201529392505050565b600060408284031215614a0c57600080fd5b614a14613994565b6149e083613ca1565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614a5157600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614a9057600080fd5b83018035915067ffffffffffffffff821115614aab57600080fd5b602001915036819003821315611b8357600080fd5b80820180821115610eea57610eea614879565b81810381811115610eea57610eea614879565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015613e6d5760049490940360031b84901b1690921692915050565b60008085851115614b3c57600080fd5b83861115614b4957600080fd5b5050820193919092039150565b600060408284031215614b6857600080fd5b614b70613994565b8251815260208301516149ee81613e9b565b600060208284031215614b9457600080fd5b5051919050565b805169ffffffffffffffffffff811681146137fd57600080fd5b600080600080600060a08688031215614bcd57600080fd5b614bd686614b9b565b9450602086015193506040860151925060608601519150614bf960808701614b9b565b90509295509295909350565b600060208284031215614c1757600080fd5b8151610b4481613a77565b60ff8181168382160190811115610eea57610eea614879565b60ff8281168282160390811115610eea57610eea614879565b600181815b80851115614cad57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614c9357614c93614879565b80851615614ca057918102915b93841c9390800290614c59565b509250929050565b600082614cc457506001610eea565b81614cd157506000610eea565b8160018114614ce75760028114614cf157614d0d565b6001915050610eea565b60ff841115614d0257614d02614879565b50506001821b610eea565b5060208310610133831016604e8410600b8410161715614d30575081810a610eea565b614d3a8383614c54565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614d6c57614d6c614879565b029392505050565b6000610b4460ff841683614cb5565b600060408284031215614d9557600080fd5b614d9d613994565b614da6836137d9565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156137d2576137d2614879565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", -} - -var PriceRegistryABI = PriceRegistryMetaData.ABI - -var PriceRegistryBin = PriceRegistryMetaData.Bin - -func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig PriceRegistryStaticConfig, priceUpdaters []common.Address, feeTokens []common.Address, tokenPriceFeeds []PriceRegistryTokenPriceFeedUpdate, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (common.Address, *types.Transaction, *PriceRegistry, error) { - parsed, err := PriceRegistryMetaData.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(PriceRegistryBin), backend, staticConfig, priceUpdaters, feeTokens, tokenPriceFeeds, tokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs, destChainConfigArgs) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &PriceRegistry{address: address, abi: *parsed, PriceRegistryCaller: PriceRegistryCaller{contract: contract}, PriceRegistryTransactor: PriceRegistryTransactor{contract: contract}, PriceRegistryFilterer: PriceRegistryFilterer{contract: contract}}, nil -} - -type PriceRegistry struct { - address common.Address - abi abi.ABI - PriceRegistryCaller - PriceRegistryTransactor - PriceRegistryFilterer -} - -type PriceRegistryCaller struct { - contract *bind.BoundContract -} - -type PriceRegistryTransactor struct { - contract *bind.BoundContract -} - -type PriceRegistryFilterer struct { - contract *bind.BoundContract -} - -type PriceRegistrySession struct { - Contract *PriceRegistry - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type PriceRegistryCallerSession struct { - Contract *PriceRegistryCaller - CallOpts bind.CallOpts -} - -type PriceRegistryTransactorSession struct { - Contract *PriceRegistryTransactor - TransactOpts bind.TransactOpts -} - -type PriceRegistryRaw struct { - Contract *PriceRegistry -} - -type PriceRegistryCallerRaw struct { - Contract *PriceRegistryCaller -} - -type PriceRegistryTransactorRaw struct { - Contract *PriceRegistryTransactor -} - -func NewPriceRegistry(address common.Address, backend bind.ContractBackend) (*PriceRegistry, error) { - abi, err := abi.JSON(strings.NewReader(PriceRegistryABI)) - if err != nil { - return nil, err - } - contract, err := bindPriceRegistry(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &PriceRegistry{address: address, abi: abi, PriceRegistryCaller: PriceRegistryCaller{contract: contract}, PriceRegistryTransactor: PriceRegistryTransactor{contract: contract}, PriceRegistryFilterer: PriceRegistryFilterer{contract: contract}}, nil -} - -func NewPriceRegistryCaller(address common.Address, caller bind.ContractCaller) (*PriceRegistryCaller, error) { - contract, err := bindPriceRegistry(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &PriceRegistryCaller{contract: contract}, nil -} - -func NewPriceRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*PriceRegistryTransactor, error) { - contract, err := bindPriceRegistry(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &PriceRegistryTransactor{contract: contract}, nil -} - -func NewPriceRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*PriceRegistryFilterer, error) { - contract, err := bindPriceRegistry(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &PriceRegistryFilterer{contract: contract}, nil -} - -func bindPriceRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := PriceRegistryMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_PriceRegistry *PriceRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _PriceRegistry.Contract.PriceRegistryCaller.contract.Call(opts, result, method, params...) -} - -func (_PriceRegistry *PriceRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.Contract.PriceRegistryTransactor.contract.Transfer(opts) -} - -func (_PriceRegistry *PriceRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PriceRegistry.Contract.PriceRegistryTransactor.contract.Transact(opts, method, params...) -} - -func (_PriceRegistry *PriceRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _PriceRegistry.Contract.contract.Call(opts, result, method, params...) -} - -func (_PriceRegistry *PriceRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.Contract.contract.Transfer(opts) -} - -func (_PriceRegistry *PriceRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PriceRegistry.Contract.contract.Transact(opts, method, params...) -} - -func (_PriceRegistry *PriceRegistryCaller) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "convertTokenAmount", fromToken, fromTokenAmount, toToken) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.ConvertTokenAmount(&_PriceRegistry.CallOpts, fromToken, fromTokenAmount, toToken) -} - -func (_PriceRegistry *PriceRegistryCallerSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.ConvertTokenAmount(&_PriceRegistry.CallOpts, fromToken, fromTokenAmount, toToken) -} - -func (_PriceRegistry *PriceRegistryCaller) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getAllAuthorizedCallers") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetAllAuthorizedCallers() ([]common.Address, error) { - return _PriceRegistry.Contract.GetAllAuthorizedCallers(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetAllAuthorizedCallers() ([]common.Address, error) { - return _PriceRegistry.Contract.GetAllAuthorizedCallers(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (PriceRegistryDestChainConfig, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) - - if err != nil { - return *new(PriceRegistryDestChainConfig), err - } - - out0 := *abi.ConvertType(out[0], new(PriceRegistryDestChainConfig)).(*PriceRegistryDestChainConfig) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetDestChainConfig(destChainSelector uint64) (PriceRegistryDestChainConfig, error) { - return _PriceRegistry.Contract.GetDestChainConfig(&_PriceRegistry.CallOpts, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetDestChainConfig(destChainSelector uint64) (PriceRegistryDestChainConfig, error) { - return _PriceRegistry.Contract.GetDestChainConfig(&_PriceRegistry.CallOpts, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCaller) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getDestinationChainGasPrice", destChainSelector) - - if err != nil { - return *new(InternalTimestampedPackedUint224), err - } - - out0 := *abi.ConvertType(out[0], new(InternalTimestampedPackedUint224)).(*InternalTimestampedPackedUint224) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetDestinationChainGasPrice(&_PriceRegistry.CallOpts, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetDestinationChainGasPrice(&_PriceRegistry.CallOpts, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCaller) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getFeeTokens") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetFeeTokens() ([]common.Address, error) { - return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetFeeTokens() ([]common.Address, error) { - return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getPremiumMultiplierWeiPerEth", token) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { - return _PriceRegistry.Contract.GetPremiumMultiplierWeiPerEth(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { - return _PriceRegistry.Contract.GetPremiumMultiplierWeiPerEth(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCaller) GetStaticConfig(opts *bind.CallOpts) (PriceRegistryStaticConfig, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getStaticConfig") - - if err != nil { - return *new(PriceRegistryStaticConfig), err - } - - out0 := *abi.ConvertType(out[0], new(PriceRegistryStaticConfig)).(*PriceRegistryStaticConfig) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetStaticConfig() (PriceRegistryStaticConfig, error) { - return _PriceRegistry.Contract.GetStaticConfig(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetStaticConfig() (PriceRegistryStaticConfig, error) { - return _PriceRegistry.Contract.GetStaticConfig(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenAndGasPrices", token, destChainSelector) - - outstruct := new(GetTokenAndGasPrices) - if err != nil { - return *outstruct, err - } - - outstruct.TokenPrice = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.GasPriceValue = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) { - return _PriceRegistry.Contract.GetTokenAndGasPrices(&_PriceRegistry.CallOpts, token, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) { - return _PriceRegistry.Contract.GetTokenAndGasPrices(&_PriceRegistry.CallOpts, token, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPrice", token) - - if err != nil { - return *new(InternalTimestampedPackedUint224), err - } - - out0 := *abi.ConvertType(out[0], new(InternalTimestampedPackedUint224)).(*InternalTimestampedPackedUint224) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPriceFeedConfig", token) - - if err != nil { - return *new(IPriceRegistryTokenPriceFeedConfig), err - } - - out0 := *abi.ConvertType(out[0], new(IPriceRegistryTokenPriceFeedConfig)).(*IPriceRegistryTokenPriceFeedConfig) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenPriceFeedConfig(token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) { - return _PriceRegistry.Contract.GetTokenPriceFeedConfig(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPriceFeedConfig(token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) { - return _PriceRegistry.Contract.GetTokenPriceFeedConfig(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPrices", tokens) - - if err != nil { - return *new([]InternalTimestampedPackedUint224), err - } - - out0 := *abi.ConvertType(out[0], new([]InternalTimestampedPackedUint224)).(*[]InternalTimestampedPackedUint224) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenTransferFeeConfig", destChainSelector, token) - - if err != nil { - return *new(PriceRegistryTokenTransferFeeConfig), err - } - - out0 := *abi.ConvertType(out[0], new(PriceRegistryTokenTransferFeeConfig)).(*PriceRegistryTokenTransferFeeConfig) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { - return _PriceRegistry.Contract.GetTokenTransferFeeConfig(&_PriceRegistry.CallOpts, destChainSelector, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { - return _PriceRegistry.Contract.GetTokenTransferFeeConfig(&_PriceRegistry.CallOpts, destChainSelector, token) -} - -func (_PriceRegistry *PriceRegistryCaller) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getValidatedFee", destChainSelector, message) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedFee(&_PriceRegistry.CallOpts, destChainSelector, message) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedFee(&_PriceRegistry.CallOpts, destChainSelector, message) -} - -func (_PriceRegistry *PriceRegistryCaller) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getValidatedTokenPrice", token) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _PriceRegistry.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 (_PriceRegistry *PriceRegistrySession) Owner() (common.Address, error) { - return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) Owner() (common.Address, error) { - return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, - - error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs) - - outstruct := new(ProcessMessageArgs) - if err != nil { - return *outstruct, err - } - - outstruct.MsgFeeJuels = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.IsOutOfOrderExecution = *abi.ConvertType(out[1], new(bool)).(*bool) - outstruct.ConvertedExtraArgs = *abi.ConvertType(out[2], new([]byte)).(*[]byte) - - return *outstruct, err - -} - -func (_PriceRegistry *PriceRegistrySession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, - - error) { - return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) -} - -func (_PriceRegistry *PriceRegistryCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, - - error) { - return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) -} - -func (_PriceRegistry *PriceRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) TypeAndVersion() (string, error) { - return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) TypeAndVersion() (string, error) { - return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "validatePoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) - - if err != nil { - return err - } - - return err - -} - -func (_PriceRegistry *PriceRegistrySession) ValidatePoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { - return _PriceRegistry.Contract.ValidatePoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) ValidatePoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { - return _PriceRegistry.Contract.ValidatePoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) -} - -func (_PriceRegistry *PriceRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "acceptOwnership") -} - -func (_PriceRegistry *PriceRegistrySession) AcceptOwnership() (*types.Transaction, error) { - return _PriceRegistry.Contract.AcceptOwnership(&_PriceRegistry.TransactOpts) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _PriceRegistry.Contract.AcceptOwnership(&_PriceRegistry.TransactOpts) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyAuthorizedCallerUpdates", authorizedCallerArgs) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyAuthorizedCallerUpdates(&_PriceRegistry.TransactOpts, authorizedCallerArgs) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyAuthorizedCallerUpdates(&_PriceRegistry.TransactOpts, authorizedCallerArgs) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyDestChainConfigUpdates(destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyDestChainConfigUpdates(&_PriceRegistry.TransactOpts, destChainConfigArgs) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyDestChainConfigUpdates(&_PriceRegistry.TransactOpts, destChainConfigArgs) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyFeeTokensUpdates", feeTokensToAdd, feeTokensToRemove) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyPremiumMultiplierWeiPerEthUpdates", premiumMultiplierWeiPerEthArgs) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_PriceRegistry.TransactOpts, premiumMultiplierWeiPerEthArgs) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_PriceRegistry.TransactOpts, premiumMultiplierWeiPerEthArgs) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyTokenTransferFeeConfigUpdates", tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyTokenTransferFeeConfigUpdates(&_PriceRegistry.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyTokenTransferFeeConfigUpdates(&_PriceRegistry.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) -} - -func (_PriceRegistry *PriceRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "transferOwnership", to) -} - -func (_PriceRegistry *PriceRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.TransferOwnership(&_PriceRegistry.TransactOpts, to) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.TransferOwnership(&_PriceRegistry.TransactOpts, to) -} - -func (_PriceRegistry *PriceRegistryTransactor) UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "updatePrices", priceUpdates) -} - -func (_PriceRegistry *PriceRegistrySession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdatePrices(&_PriceRegistry.TransactOpts, priceUpdates) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdatePrices(&_PriceRegistry.TransactOpts, priceUpdates) -} - -func (_PriceRegistry *PriceRegistryTransactor) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "updateTokenPriceFeeds", tokenPriceFeedUpdates) -} - -func (_PriceRegistry *PriceRegistrySession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdateTokenPriceFeeds(&_PriceRegistry.TransactOpts, tokenPriceFeedUpdates) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdateTokenPriceFeeds(&_PriceRegistry.TransactOpts, tokenPriceFeedUpdates) -} - -type PriceRegistryAuthorizedCallerAddedIterator struct { - Event *PriceRegistryAuthorizedCallerAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryAuthorizedCallerAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryAuthorizedCallerAdded) - 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(PriceRegistryAuthorizedCallerAdded) - 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 *PriceRegistryAuthorizedCallerAddedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryAuthorizedCallerAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryAuthorizedCallerAdded struct { - Caller common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerAddedIterator, error) { - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "AuthorizedCallerAdded") - if err != nil { - return nil, err - } - return &PriceRegistryAuthorizedCallerAddedIterator{contract: _PriceRegistry.contract, event: "AuthorizedCallerAdded", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) { - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "AuthorizedCallerAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryAuthorizedCallerAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerAdded", 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 (_PriceRegistry *PriceRegistryFilterer) ParseAuthorizedCallerAdded(log types.Log) (*PriceRegistryAuthorizedCallerAdded, error) { - event := new(PriceRegistryAuthorizedCallerAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryAuthorizedCallerRemovedIterator struct { - Event *PriceRegistryAuthorizedCallerRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryAuthorizedCallerRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryAuthorizedCallerRemoved) - 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(PriceRegistryAuthorizedCallerRemoved) - 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 *PriceRegistryAuthorizedCallerRemovedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryAuthorizedCallerRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryAuthorizedCallerRemoved struct { - Caller common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerRemovedIterator, error) { - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "AuthorizedCallerRemoved") - if err != nil { - return nil, err - } - return &PriceRegistryAuthorizedCallerRemovedIterator{contract: _PriceRegistry.contract, event: "AuthorizedCallerRemoved", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error) { - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "AuthorizedCallerRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryAuthorizedCallerRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerRemoved", 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 (_PriceRegistry *PriceRegistryFilterer) ParseAuthorizedCallerRemoved(log types.Log) (*PriceRegistryAuthorizedCallerRemoved, error) { - event := new(PriceRegistryAuthorizedCallerRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryDestChainAddedIterator struct { - Event *PriceRegistryDestChainAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryDestChainAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryDestChainAdded) - 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(PriceRegistryDestChainAdded) - 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 *PriceRegistryDestChainAddedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryDestChainAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryDestChainAdded struct { - DestChainSelector uint64 - DestChainConfig PriceRegistryDestChainConfig - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainAddedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "DestChainAdded", destChainSelectorRule) - if err != nil { - return nil, err - } - return &PriceRegistryDestChainAddedIterator{contract: _PriceRegistry.contract, event: "DestChainAdded", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "DestChainAdded", destChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryDestChainAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainAdded", 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 (_PriceRegistry *PriceRegistryFilterer) ParseDestChainAdded(log types.Log) (*PriceRegistryDestChainAdded, error) { - event := new(PriceRegistryDestChainAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryDestChainConfigUpdatedIterator struct { - Event *PriceRegistryDestChainConfigUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryDestChainConfigUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryDestChainConfigUpdated) - 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(PriceRegistryDestChainConfigUpdated) - 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 *PriceRegistryDestChainConfigUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryDestChainConfigUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryDestChainConfigUpdated struct { - DestChainSelector uint64 - DestChainConfig PriceRegistryDestChainConfig - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainConfigUpdatedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) - if err != nil { - return nil, err - } - return &PriceRegistryDestChainConfigUpdatedIterator{contract: _PriceRegistry.contract, event: "DestChainConfigUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryDestChainConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainConfigUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseDestChainConfigUpdated(log types.Log) (*PriceRegistryDestChainConfigUpdated, error) { - event := new(PriceRegistryDestChainConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryFeeTokenAddedIterator struct { - Event *PriceRegistryFeeTokenAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenAdded) - 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(PriceRegistryFeeTokenAdded) - 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 *PriceRegistryFeeTokenAddedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryFeeTokenAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryFeeTokenAdded struct { - FeeToken common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryFeeTokenAddedIterator{contract: _PriceRegistry.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", 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 (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) { - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryFeeTokenRemovedIterator struct { - Event *PriceRegistryFeeTokenRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenRemoved) - 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(PriceRegistryFeeTokenRemoved) - 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 *PriceRegistryFeeTokenRemovedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryFeeTokenRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryFeeTokenRemoved struct { - FeeToken common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryFeeTokenRemovedIterator{contract: _PriceRegistry.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", 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 (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) { - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryOwnershipTransferRequestedIterator struct { - Event *PriceRegistryOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferRequested) - 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(PriceRegistryOwnershipTransferRequested) - 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 *PriceRegistryOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, 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 := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &PriceRegistryOwnershipTransferRequestedIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, 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 := _PriceRegistry.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(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.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 (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) { - event := new(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryOwnershipTransferredIterator struct { - Event *PriceRegistryOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferred) - 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(PriceRegistryOwnershipTransferred) - 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 *PriceRegistryOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferredIterator, 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 := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &PriceRegistryOwnershipTransferredIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferred, 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 := _PriceRegistry.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(PriceRegistryOwnershipTransferred) - if err := _PriceRegistry.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 (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) { - event := new(PriceRegistryOwnershipTransferred) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator struct { - Event *PriceRegistryPremiumMultiplierWeiPerEthUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) - 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(PriceRegistryPremiumMultiplierWeiPerEthUpdated) - 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 *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryPremiumMultiplierWeiPerEthUpdated struct { - Token common.Address - PremiumMultiplierWeiPerEth uint64 - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator{contract: _PriceRegistry.contract, event: "PremiumMultiplierWeiPerEthUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) { - event := new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryPriceFeedPerTokenUpdatedIterator struct { - Event *PriceRegistryPriceFeedPerTokenUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryPriceFeedPerTokenUpdated) - 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(PriceRegistryPriceFeedPerTokenUpdated) - 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 *PriceRegistryPriceFeedPerTokenUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryPriceFeedPerTokenUpdated struct { - Token common.Address - PriceFeedConfig IPriceRegistryTokenPriceFeedConfig - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPriceFeedPerTokenUpdatedIterator, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryPriceFeedPerTokenUpdatedIterator{contract: _PriceRegistry.contract, event: "PriceFeedPerTokenUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryPriceFeedPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePriceFeedPerTokenUpdated(log types.Log) (*PriceRegistryPriceFeedPerTokenUpdated, error) { - event := new(PriceRegistryPriceFeedPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryPriceUpdaterRemovedIterator struct { - Event *PriceRegistryPriceUpdaterRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryPriceUpdaterRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryPriceUpdaterRemoved) - 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(PriceRegistryPriceUpdaterRemoved) - 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 *PriceRegistryPriceUpdaterRemovedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryPriceUpdaterRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryPriceUpdaterRemoved struct { - PriceUpdater common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterPriceUpdaterRemoved(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterRemovedIterator, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PriceUpdaterRemoved", priceUpdaterRule) - if err != nil { - return nil, err - } - return &PriceRegistryPriceUpdaterRemovedIterator{contract: _PriceRegistry.contract, event: "PriceUpdaterRemoved", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchPriceUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterRemoved, priceUpdater []common.Address) (event.Subscription, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PriceUpdaterRemoved", priceUpdaterRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryPriceUpdaterRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterRemoved", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePriceUpdaterRemoved(log types.Log) (*PriceRegistryPriceUpdaterRemoved, error) { - event := new(PriceRegistryPriceUpdaterRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryPriceUpdaterSetIterator struct { - Event *PriceRegistryPriceUpdaterSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryPriceUpdaterSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryPriceUpdaterSet) - 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(PriceRegistryPriceUpdaterSet) - 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 *PriceRegistryPriceUpdaterSetIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryPriceUpdaterSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryPriceUpdaterSet struct { - PriceUpdater common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterPriceUpdaterSet(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterSetIterator, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PriceUpdaterSet", priceUpdaterRule) - if err != nil { - return nil, err - } - return &PriceRegistryPriceUpdaterSetIterator{contract: _PriceRegistry.contract, event: "PriceUpdaterSet", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchPriceUpdaterSet(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterSet, priceUpdater []common.Address) (event.Subscription, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PriceUpdaterSet", priceUpdaterRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryPriceUpdaterSet) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterSet", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePriceUpdaterSet(log types.Log) (*PriceRegistryPriceUpdaterSet, error) { - event := new(PriceRegistryPriceUpdaterSet) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryTokenTransferFeeConfigDeletedIterator struct { - Event *PriceRegistryTokenTransferFeeConfigDeleted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryTokenTransferFeeConfigDeleted) - 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(PriceRegistryTokenTransferFeeConfigDeleted) - 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 *PriceRegistryTokenTransferFeeConfigDeletedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryTokenTransferFeeConfigDeleted struct { - DestChainSelector uint64 - Token common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigDeletedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryTokenTransferFeeConfigDeletedIterator{contract: _PriceRegistry.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryTokenTransferFeeConfigDeleted) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", 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 (_PriceRegistry *PriceRegistryFilterer) ParseTokenTransferFeeConfigDeleted(log types.Log) (*PriceRegistryTokenTransferFeeConfigDeleted, error) { - event := new(PriceRegistryTokenTransferFeeConfigDeleted) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryTokenTransferFeeConfigUpdatedIterator struct { - Event *PriceRegistryTokenTransferFeeConfigUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryTokenTransferFeeConfigUpdated) - 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(PriceRegistryTokenTransferFeeConfigUpdated) - 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 *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryTokenTransferFeeConfigUpdated struct { - DestChainSelector uint64 - Token common.Address - TokenTransferFeeConfig PriceRegistryTokenTransferFeeConfig - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryTokenTransferFeeConfigUpdatedIterator{contract: _PriceRegistry.contract, event: "TokenTransferFeeConfigUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryTokenTransferFeeConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseTokenTransferFeeConfigUpdated(log types.Log) (*PriceRegistryTokenTransferFeeConfigUpdated, error) { - event := new(PriceRegistryTokenTransferFeeConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryUsdPerTokenUpdatedIterator struct { - Event *PriceRegistryUsdPerTokenUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerTokenUpdated) - 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(PriceRegistryUsdPerTokenUpdated) - 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 *PriceRegistryUsdPerTokenUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryUsdPerTokenUpdated struct { - Token common.Address - Value *big.Int - Timestamp *big.Int - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "UsdPerTokenUpdated", tokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryUsdPerTokenUpdatedIterator{contract: _PriceRegistry.contract, event: "UsdPerTokenUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "UsdPerTokenUpdated", tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryUsdPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerTokenUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseUsdPerTokenUpdated(log types.Log) (*PriceRegistryUsdPerTokenUpdated, error) { - event := new(PriceRegistryUsdPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryUsdPerUnitGasUpdatedIterator struct { - Event *PriceRegistryUsdPerUnitGasUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerUnitGasUpdated) - 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(PriceRegistryUsdPerUnitGasUpdated) - 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 *PriceRegistryUsdPerUnitGasUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryUsdPerUnitGasUpdated struct { - DestChain uint64 - Value *big.Int - Timestamp *big.Int - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*PriceRegistryUsdPerUnitGasUpdatedIterator, error) { - - var destChainRule []interface{} - for _, destChainItem := range destChain { - destChainRule = append(destChainRule, destChainItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "UsdPerUnitGasUpdated", destChainRule) - if err != nil { - return nil, err - } - return &PriceRegistryUsdPerUnitGasUpdatedIterator{contract: _PriceRegistry.contract, event: "UsdPerUnitGasUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { - - var destChainRule []interface{} - for _, destChainItem := range destChain { - destChainRule = append(destChainRule, destChainItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "UsdPerUnitGasUpdated", destChainRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryUsdPerUnitGasUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerUnitGasUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseUsdPerUnitGasUpdated(log types.Log) (*PriceRegistryUsdPerUnitGasUpdated, error) { - event := new(PriceRegistryUsdPerUnitGasUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type GetTokenAndGasPrices struct { - TokenPrice *big.Int - GasPriceValue *big.Int -} -type ProcessMessageArgs struct { - MsgFeeJuels *big.Int - IsOutOfOrderExecution bool - ConvertedExtraArgs []byte -} - -func (_PriceRegistry *PriceRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _PriceRegistry.abi.Events["AuthorizedCallerAdded"].ID: - return _PriceRegistry.ParseAuthorizedCallerAdded(log) - case _PriceRegistry.abi.Events["AuthorizedCallerRemoved"].ID: - return _PriceRegistry.ParseAuthorizedCallerRemoved(log) - case _PriceRegistry.abi.Events["DestChainAdded"].ID: - return _PriceRegistry.ParseDestChainAdded(log) - case _PriceRegistry.abi.Events["DestChainConfigUpdated"].ID: - return _PriceRegistry.ParseDestChainConfigUpdated(log) - case _PriceRegistry.abi.Events["FeeTokenAdded"].ID: - return _PriceRegistry.ParseFeeTokenAdded(log) - case _PriceRegistry.abi.Events["FeeTokenRemoved"].ID: - return _PriceRegistry.ParseFeeTokenRemoved(log) - case _PriceRegistry.abi.Events["OwnershipTransferRequested"].ID: - return _PriceRegistry.ParseOwnershipTransferRequested(log) - case _PriceRegistry.abi.Events["OwnershipTransferred"].ID: - return _PriceRegistry.ParseOwnershipTransferred(log) - case _PriceRegistry.abi.Events["PremiumMultiplierWeiPerEthUpdated"].ID: - return _PriceRegistry.ParsePremiumMultiplierWeiPerEthUpdated(log) - case _PriceRegistry.abi.Events["PriceFeedPerTokenUpdated"].ID: - return _PriceRegistry.ParsePriceFeedPerTokenUpdated(log) - case _PriceRegistry.abi.Events["PriceUpdaterRemoved"].ID: - return _PriceRegistry.ParsePriceUpdaterRemoved(log) - case _PriceRegistry.abi.Events["PriceUpdaterSet"].ID: - return _PriceRegistry.ParsePriceUpdaterSet(log) - case _PriceRegistry.abi.Events["TokenTransferFeeConfigDeleted"].ID: - return _PriceRegistry.ParseTokenTransferFeeConfigDeleted(log) - case _PriceRegistry.abi.Events["TokenTransferFeeConfigUpdated"].ID: - return _PriceRegistry.ParseTokenTransferFeeConfigUpdated(log) - case _PriceRegistry.abi.Events["UsdPerTokenUpdated"].ID: - return _PriceRegistry.ParseUsdPerTokenUpdated(log) - case _PriceRegistry.abi.Events["UsdPerUnitGasUpdated"].ID: - return _PriceRegistry.ParseUsdPerUnitGasUpdated(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (PriceRegistryAuthorizedCallerAdded) Topic() common.Hash { - return common.HexToHash("0xeb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef") -} - -func (PriceRegistryAuthorizedCallerRemoved) Topic() common.Hash { - return common.HexToHash("0xc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda77580") -} - -func (PriceRegistryDestChainAdded) Topic() common.Hash { - return common.HexToHash("0xa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577") -} - -func (PriceRegistryDestChainConfigUpdated) Topic() common.Hash { - return common.HexToHash("0xa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad93") -} - -func (PriceRegistryFeeTokenAdded) Topic() common.Hash { - return common.HexToHash("0xdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23") -} - -func (PriceRegistryFeeTokenRemoved) Topic() common.Hash { - return common.HexToHash("0x1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91") -} - -func (PriceRegistryOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (PriceRegistryOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (PriceRegistryPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { - return common.HexToHash("0xbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d") -} - -func (PriceRegistryPriceFeedPerTokenUpdated) Topic() common.Hash { - return common.HexToHash("0x08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464") -} - -func (PriceRegistryPriceUpdaterRemoved) Topic() common.Hash { - return common.HexToHash("0xff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c") -} - -func (PriceRegistryPriceUpdaterSet) Topic() common.Hash { - return common.HexToHash("0x34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b8") -} - -func (PriceRegistryTokenTransferFeeConfigDeleted) Topic() common.Hash { - return common.HexToHash("0x4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b") -} - -func (PriceRegistryTokenTransferFeeConfigUpdated) Topic() common.Hash { - return common.HexToHash("0x94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5") -} - -func (PriceRegistryUsdPerTokenUpdated) Topic() common.Hash { - return common.HexToHash("0x52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a") -} - -func (PriceRegistryUsdPerUnitGasUpdated) Topic() common.Hash { - return common.HexToHash("0xdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e") -} - -func (_PriceRegistry *PriceRegistry) Address() common.Address { - return _PriceRegistry.address -} - -type PriceRegistryInterface interface { - ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) - - GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) - - GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (PriceRegistryDestChainConfig, error) - - GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) - - GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) - - GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) - - GetStaticConfig(opts *bind.CallOpts) (PriceRegistryStaticConfig, error) - - GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) - - GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) - - GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) - - GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) - - GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) - - GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) - - GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, - - error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) - - ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) - - ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) - - ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) - - ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) - - UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) - - FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerAddedIterator, error) - - WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) - - ParseAuthorizedCallerAdded(log types.Log) (*PriceRegistryAuthorizedCallerAdded, error) - - FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerRemovedIterator, error) - - WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error) - - ParseAuthorizedCallerRemoved(log types.Log) (*PriceRegistryAuthorizedCallerRemoved, error) - - FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainAddedIterator, error) - - WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) - - ParseDestChainAdded(log types.Log) (*PriceRegistryDestChainAdded, error) - - FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainConfigUpdatedIterator, error) - - WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) - - ParseDestChainConfigUpdated(log types.Log) (*PriceRegistryDestChainConfigUpdated, error) - - FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) - - WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) - - ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) - - FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) - - WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) - - ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) - - FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) - - WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) - - ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) - - FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPriceFeedPerTokenUpdatedIterator, error) - - WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) - - ParsePriceFeedPerTokenUpdated(log types.Log) (*PriceRegistryPriceFeedPerTokenUpdated, error) - - FilterPriceUpdaterRemoved(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterRemovedIterator, error) - - WatchPriceUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterRemoved, priceUpdater []common.Address) (event.Subscription, error) - - ParsePriceUpdaterRemoved(log types.Log) (*PriceRegistryPriceUpdaterRemoved, error) - - FilterPriceUpdaterSet(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterSetIterator, error) - - WatchPriceUpdaterSet(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterSet, priceUpdater []common.Address) (event.Subscription, error) - - ParsePriceUpdaterSet(log types.Log) (*PriceRegistryPriceUpdaterSet, error) - - FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigDeletedIterator, error) - - WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) - - ParseTokenTransferFeeConfigDeleted(log types.Log) (*PriceRegistryTokenTransferFeeConfigDeleted, error) - - FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) - - WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) - - ParseTokenTransferFeeConfigUpdated(log types.Log) (*PriceRegistryTokenTransferFeeConfigUpdated, error) - - FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) - - WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) - - ParseUsdPerTokenUpdated(log types.Log) (*PriceRegistryUsdPerTokenUpdated, error) - - FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*PriceRegistryUsdPerUnitGasUpdatedIterator, error) - - WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) - - ParseUsdPerUnitGasUpdated(log types.Log) (*PriceRegistryUsdPerUnitGasUpdated, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/price_registry_1_0_0/price_registry.go b/core/gethwrappers/ccip/generated/price_registry_1_0_0/price_registry.go deleted file mode 100644 index 212d01aee44..00000000000 --- a/core/gethwrappers/ccip/generated/price_registry_1_0_0/price_registry.go +++ /dev/null @@ -1,1665 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package price_registry_1_0_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 InternalPriceUpdates struct { - TokenPriceUpdates []InternalTokenPriceUpdate - DestChainSelector uint64 - UsdPerUnitGas *big.Int -} - -type InternalTimestampedUint192Value struct { - Value *big.Int - Timestamp uint64 -} - -type InternalTokenPriceUpdate struct { - SourceToken common.Address - UsdPerToken *big.Int -} - -var PriceRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStalenessThreshold\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpdaterOrOwner\",\"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\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleTokenPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"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\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterSet\",\"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\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"priceUpdatersToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdatersToRemove\",\"type\":\"address[]\"}],\"name\":\"applyPriceUpdatersUpdates\",\"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\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint192\",\"name\":\"value\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.TimestampedUint192Value\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPriceUpdaters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStalenessThreshold\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint192\",\"name\":\"tokenPrice\",\"type\":\"uint192\"},{\"internalType\":\"uint192\",\"name\":\"gasPriceValue\",\"type\":\"uint192\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint192\",\"name\":\"value\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.TimestampedUint192Value\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint192\",\"name\":\"value\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.TimestampedUint192Value[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"stateMutability\":\"view\",\"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\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"usdPerToken\",\"type\":\"uint192\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint192\",\"name\":\"usdPerUnitGas\",\"type\":\"uint192\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200217d3803806200217d8339810160408190526200003491620006fe565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000133565b5050604080516000815260208101909152620000dd91508490620001de565b604080516000815260208101909152620000f99083906200033a565b8063ffffffff166000036200012157604051631151410960e11b815260040160405180910390fd5b63ffffffff1660805250620007fa9050565b336001600160a01b038216036200018d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b825181101562000289576200021d83828151811062000204576200020462000786565b602002602001015160046200049160201b90919060201c565b15620002765782818151811062000238576200023862000786565b60200260200101516001600160a01b03167f34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b860405160405180910390a25b6200028181620007b2565b9050620001e1565b5060005b81518110156200033557620002c9828281518110620002b057620002b062000786565b60200260200101516004620004b160201b90919060201c565b156200032257818181518110620002e457620002e462000786565b60200260200101516001600160a01b03167fff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c60405160405180910390a25b6200032d81620007b2565b90506200028d565b505050565b60005b8251811015620003e5576200037983828151811062000360576200036062000786565b602002602001015160066200049160201b90919060201c565b15620003d25782818151811062000394576200039462000786565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b620003dd81620007b2565b90506200033d565b5060005b81518110156200033557620004258282815181106200040c576200040c62000786565b60200260200101516006620004b160201b90919060201c565b156200047e5781818151811062000440576200044062000786565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6200048981620007b2565b9050620003e9565b6000620004a8836001600160a01b038416620004c8565b90505b92915050565b6000620004a8836001600160a01b0384166200051a565b60008181526001830160205260408120546200051157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004ab565b506000620004ab565b600081815260018301602052604081205480156200061357600062000541600183620007ce565b85549091506000906200055790600190620007ce565b9050818114620005c35760008660000182815481106200057b576200057b62000786565b9060005260206000200154905080876000018481548110620005a157620005a162000786565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620005d757620005d7620007e4565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004ab565b6000915050620004ab565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200064c57600080fd5b919050565b600082601f8301126200066357600080fd5b815160206001600160401b03808311156200068257620006826200061e565b8260051b604051601f19603f83011681018181108482111715620006aa57620006aa6200061e565b604052938452858101830193838101925087851115620006c957600080fd5b83870191505b84821015620006f357620006e38262000634565b83529183019190830190620006cf565b979650505050505050565b6000806000606084860312156200071457600080fd5b83516001600160401b03808211156200072c57600080fd5b6200073a8783880162000651565b945060208601519150808211156200075157600080fd5b50620007608682870162000651565b925050604084015163ffffffff811681146200077b57600080fd5b809150509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620007c757620007c76200079c565b5060010190565b81810381811115620004ab57620004ab6200079c565b634e487b7160e01b600052603160045260246000fd5b60805161194b620008326000396000818161028501528181610a5201528181610abb01528181610c180152610c8d015261194b6000f3fe608060405234801561001057600080fd5b50600436106100f45760003560e01c8063866548c911610097578063cdc73d5111610066578063cdc73d51146102c4578063d02641a0146102cc578063f2fde38b1461036a578063ffdb4b371461037d57600080fd5b8063866548c9146102405780638da5cb5b14610253578063a6c94a731461027b578063bfcd4566146102af57600080fd5b8063514e8cff116100d3578063514e8cff1461017b57806352877af01461021057806379ba5097146102255780637afac3221461022d57600080fd5b806241e5be146100f957806345ac924d1461011f5780634ab35b0b1461013f575b600080fd5b61010c61010736600461133e565b6103c1565b6040519081526020015b60405180910390f35b61013261012d36600461137a565b610425565b60405161011691906113ef565b61015261014d36600461146a565b6104f9565b60405177ffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610116565b61020361018936600461149d565b6040805180820182526000808252602091820181905267ffffffffffffffff93841681526002825282902082518084019093525477ffffffffffffffffffffffffffffffffffffffffffffffff81168352780100000000000000000000000000000000000000000000000090049092169181019190915290565b60405161011691906114b8565b61022361021e3660046115e2565b610504565b005b61022361051a565b61022361023b3660046115e2565b61061c565b61022361024e366004611646565b61062e565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610116565b60405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610116565b6102b7610951565b6040516101169190611681565b6102b7610962565b6102036102da36600461146a565b60408051808201909152600080825260208201525073ffffffffffffffffffffffffffffffffffffffff1660009081526003602090815260409182902082518084019093525477ffffffffffffffffffffffffffffffffffffffffffffffff811683527801000000000000000000000000000000000000000000000000900467ffffffffffffffff169082015290565b61022361037836600461146a565b61096e565b61039061038b3660046116db565b610982565b6040805177ffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610116565b60006103cc82610b09565b77ffffffffffffffffffffffffffffffffffffffffffffffff166103ef85610b09565b6104139077ffffffffffffffffffffffffffffffffffffffffffffffff168561173d565b61041d9190611754565b949350505050565b60608160008167ffffffffffffffff811115610443576104436114f3565b60405190808252806020026020018201604052801561048857816020015b60408051808201909152600080825260208201528152602001906001900390816104615790505b50905060005b828110156104ee576104c08686838181106104ab576104ab61178f565b90506020020160208101906102da919061146a565b8282815181106104d2576104d261178f565b6020026020010181905250806104e7906117be565b905061048e565b509150505b92915050565b60006104f382610b09565b61050c610cc9565b6105168282610d4c565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610624610cc9565b6105168282610ea8565b60005473ffffffffffffffffffffffffffffffffffffffff16331480159061065e575061065c600433610fff565b155b15610695576040517f46f0815400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106a182806117f6565b9050905060005b818110156107eb5760006106bc84806117f6565b838181106106cc576106cc61178f565b9050604002018036038101906106e29190611886565b6040805180820182526020808401805177ffffffffffffffffffffffffffffffffffffffffffffffff908116845267ffffffffffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff908116600090815260039097529588902096519051909216780100000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926107d292909177ffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a2506107e4816117be565b90506106a8565b506107fc604083016020840161149d565b67ffffffffffffffff161561051657604051806040016040528083604001602081019061082991906118e1565b77ffffffffffffffffffffffffffffffffffffffffffffffff1681526020014267ffffffffffffffff168152506002600084602001602081019061086d919061149d565b67ffffffffffffffff9081168252602080830193909352604091820160002084519484015190911678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff909416939093179092556108e191840190840161149d565b67ffffffffffffffff167fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e61091c60608501604086016118e1565b6040805177ffffffffffffffffffffffffffffffffffffffffffffffff90921682524260208301520160405180910390a25050565b606061095d6004611031565b905090565b606061095d6006611031565b610976610cc9565b61097f8161103e565b50565b67ffffffffffffffff808216600090815260026020908152604080832081518083019092525477ffffffffffffffffffffffffffffffffffffffffffffffff8116825278010000000000000000000000000000000000000000000000009004909316908301819052909182918203610a32576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610597565b6000816020015167ffffffffffffffff1642610a4e91906118fc565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115610aef576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610597565b610af886610b09565b9151919350909150505b9250929050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020908152604080832081518083019092525477ffffffffffffffffffffffffffffffffffffffffffffffff811682527801000000000000000000000000000000000000000000000000900467ffffffffffffffff16918101829052901580610ba95750805177ffffffffffffffffffffffffffffffffffffffffffffffff16155b15610bf8576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610597565b6000816020015167ffffffffffffffff1642610c1491906118fc565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115610cc1576040517fc65fdfca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610597565b505192915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610597565b565b60005b8251811015610df757610d85838281518110610d6d57610d6d61178f565b6020026020010151600461113390919063ffffffff16565b15610de757828181518110610d9c57610d9c61178f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b860405160405180910390a25b610df0816117be565b9050610d4f565b5060005b8151811015610ea357610e31828281518110610e1957610e1961178f565b6020026020010151600461115590919063ffffffff16565b15610e9357818181518110610e4857610e4861178f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c60405160405180910390a25b610e9c816117be565b9050610dfb565b505050565b60005b8251811015610f5357610ee1838281518110610ec957610ec961178f565b6020026020010151600661113390919063ffffffff16565b15610f4357828181518110610ef857610ef861178f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b610f4c816117be565b9050610eab565b5060005b8151811015610ea357610f8d828281518110610f7557610f7561178f565b6020026020010151600661115590919063ffffffff16565b15610fef57818181518110610fa457610fa461178f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b610ff8816117be565b9050610f57565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b6060600061102a83611177565b3373ffffffffffffffffffffffffffffffffffffffff8216036110bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610597565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061102a8373ffffffffffffffffffffffffffffffffffffffff84166111d3565b600061102a8373ffffffffffffffffffffffffffffffffffffffff8416611222565b6060816000018054806020026020016040519081016040528092919081815260200182805480156111c757602002820191906000526020600020905b8154815260200190600101908083116111b3575b50505050509050919050565b600081815260018301602052604081205461121a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556104f3565b5060006104f3565b6000818152600183016020526040812054801561130b5760006112466001836118fc565b855490915060009061125a906001906118fc565b90508181146112bf57600086600001828154811061127a5761127a61178f565b906000526020600020015490508087600001848154811061129d5761129d61178f565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806112d0576112d061190f565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506104f3565b60009150506104f3565b803573ffffffffffffffffffffffffffffffffffffffff8116811461133957600080fd5b919050565b60008060006060848603121561135357600080fd5b61135c84611315565b92506020840135915061137160408501611315565b90509250925092565b6000806020838503121561138d57600080fd5b823567ffffffffffffffff808211156113a557600080fd5b818501915085601f8301126113b957600080fd5b8135818111156113c857600080fd5b8660208260051b85010111156113dd57600080fd5b60209290920196919550909350505050565b602080825282518282018190526000919060409081850190868401855b8281101561145d5761144d848351805177ffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015167ffffffffffffffff16910152565b928401929085019060010161140c565b5091979650505050505050565b60006020828403121561147c57600080fd5b61102a82611315565b803567ffffffffffffffff8116811461133957600080fd5b6000602082840312156114af57600080fd5b61102a82611485565b815177ffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015167ffffffffffffffff1690820152604081016104f3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261153357600080fd5b8135602067ffffffffffffffff80831115611550576115506114f3565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108482111715611593576115936114f3565b6040529384528581018301938381019250878511156115b157600080fd5b83870191505b848210156115d7576115c882611315565b835291830191908301906115b7565b979650505050505050565b600080604083850312156115f557600080fd5b823567ffffffffffffffff8082111561160d57600080fd5b61161986838701611522565b9350602085013591508082111561162f57600080fd5b5061163c85828601611522565b9150509250929050565b60006020828403121561165857600080fd5b813567ffffffffffffffff81111561166f57600080fd5b82016060818503121561102a57600080fd5b6020808252825182820181905260009190848201906040850190845b818110156116cf57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161169d565b50909695505050505050565b600080604083850312156116ee57600080fd5b6116f783611315565b915061170560208401611485565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176104f3576104f361170e565b60008261178a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036117ef576117ef61170e565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261182b57600080fd5b83018035915067ffffffffffffffff82111561184657600080fd5b6020019150600681901b3603821315610b0257600080fd5b803577ffffffffffffffffffffffffffffffffffffffffffffffff8116811461133957600080fd5b60006040828403121561189857600080fd5b6040516040810181811067ffffffffffffffff821117156118bb576118bb6114f3565b6040526118c783611315565b81526118d56020840161185e565b60208201529392505050565b6000602082840312156118f357600080fd5b61102a8261185e565b818103818111156104f3576104f361170e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", -} - -var PriceRegistryABI = PriceRegistryMetaData.ABI - -var PriceRegistryBin = PriceRegistryMetaData.Bin - -func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, priceUpdaters []common.Address, feeTokens []common.Address, stalenessThreshold uint32) (common.Address, *types.Transaction, *PriceRegistry, error) { - parsed, err := PriceRegistryMetaData.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(PriceRegistryBin), backend, priceUpdaters, feeTokens, stalenessThreshold) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &PriceRegistry{PriceRegistryCaller: PriceRegistryCaller{contract: contract}, PriceRegistryTransactor: PriceRegistryTransactor{contract: contract}, PriceRegistryFilterer: PriceRegistryFilterer{contract: contract}}, nil -} - -type PriceRegistry struct { - address common.Address - abi abi.ABI - PriceRegistryCaller - PriceRegistryTransactor - PriceRegistryFilterer -} - -type PriceRegistryCaller struct { - contract *bind.BoundContract -} - -type PriceRegistryTransactor struct { - contract *bind.BoundContract -} - -type PriceRegistryFilterer struct { - contract *bind.BoundContract -} - -type PriceRegistrySession struct { - Contract *PriceRegistry - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type PriceRegistryCallerSession struct { - Contract *PriceRegistryCaller - CallOpts bind.CallOpts -} - -type PriceRegistryTransactorSession struct { - Contract *PriceRegistryTransactor - TransactOpts bind.TransactOpts -} - -type PriceRegistryRaw struct { - Contract *PriceRegistry -} - -type PriceRegistryCallerRaw struct { - Contract *PriceRegistryCaller -} - -type PriceRegistryTransactorRaw struct { - Contract *PriceRegistryTransactor -} - -func NewPriceRegistry(address common.Address, backend bind.ContractBackend) (*PriceRegistry, error) { - abi, err := abi.JSON(strings.NewReader(PriceRegistryABI)) - if err != nil { - return nil, err - } - contract, err := bindPriceRegistry(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &PriceRegistry{address: address, abi: abi, PriceRegistryCaller: PriceRegistryCaller{contract: contract}, PriceRegistryTransactor: PriceRegistryTransactor{contract: contract}, PriceRegistryFilterer: PriceRegistryFilterer{contract: contract}}, nil -} - -func NewPriceRegistryCaller(address common.Address, caller bind.ContractCaller) (*PriceRegistryCaller, error) { - contract, err := bindPriceRegistry(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &PriceRegistryCaller{contract: contract}, nil -} - -func NewPriceRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*PriceRegistryTransactor, error) { - contract, err := bindPriceRegistry(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &PriceRegistryTransactor{contract: contract}, nil -} - -func NewPriceRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*PriceRegistryFilterer, error) { - contract, err := bindPriceRegistry(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &PriceRegistryFilterer{contract: contract}, nil -} - -func bindPriceRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := PriceRegistryMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_PriceRegistry *PriceRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _PriceRegistry.Contract.PriceRegistryCaller.contract.Call(opts, result, method, params...) -} - -func (_PriceRegistry *PriceRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.Contract.PriceRegistryTransactor.contract.Transfer(opts) -} - -func (_PriceRegistry *PriceRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PriceRegistry.Contract.PriceRegistryTransactor.contract.Transact(opts, method, params...) -} - -func (_PriceRegistry *PriceRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _PriceRegistry.Contract.contract.Call(opts, result, method, params...) -} - -func (_PriceRegistry *PriceRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.Contract.contract.Transfer(opts) -} - -func (_PriceRegistry *PriceRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PriceRegistry.Contract.contract.Transact(opts, method, params...) -} - -func (_PriceRegistry *PriceRegistryCaller) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "convertTokenAmount", fromToken, fromTokenAmount, toToken) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.ConvertTokenAmount(&_PriceRegistry.CallOpts, fromToken, fromTokenAmount, toToken) -} - -func (_PriceRegistry *PriceRegistryCallerSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.ConvertTokenAmount(&_PriceRegistry.CallOpts, fromToken, fromTokenAmount, toToken) -} - -func (_PriceRegistry *PriceRegistryCaller) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedUint192Value, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getDestinationChainGasPrice", destChainSelector) - - if err != nil { - return *new(InternalTimestampedUint192Value), err - } - - out0 := *abi.ConvertType(out[0], new(InternalTimestampedUint192Value)).(*InternalTimestampedUint192Value) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedUint192Value, error) { - return _PriceRegistry.Contract.GetDestinationChainGasPrice(&_PriceRegistry.CallOpts, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedUint192Value, error) { - return _PriceRegistry.Contract.GetDestinationChainGasPrice(&_PriceRegistry.CallOpts, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCaller) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getFeeTokens") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetFeeTokens() ([]common.Address, error) { - return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetFeeTokens() ([]common.Address, error) { - return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) GetPriceUpdaters(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getPriceUpdaters") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetPriceUpdaters() ([]common.Address, error) { - return _PriceRegistry.Contract.GetPriceUpdaters(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetPriceUpdaters() ([]common.Address, error) { - return _PriceRegistry.Contract.GetPriceUpdaters(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) GetStalenessThreshold(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getStalenessThreshold") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetStalenessThreshold() (*big.Int, error) { - return _PriceRegistry.Contract.GetStalenessThreshold(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetStalenessThreshold() (*big.Int, error) { - return _PriceRegistry.Contract.GetStalenessThreshold(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenAndGasPrices", token, destChainSelector) - - outstruct := new(GetTokenAndGasPrices) - if err != nil { - return *outstruct, err - } - - outstruct.TokenPrice = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.GasPriceValue = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) { - return _PriceRegistry.Contract.GetTokenAndGasPrices(&_PriceRegistry.CallOpts, token, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) { - return _PriceRegistry.Contract.GetTokenAndGasPrices(&_PriceRegistry.CallOpts, token, destChainSelector) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedUint192Value, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPrice", token) - - if err != nil { - return *new(InternalTimestampedUint192Value), err - } - - out0 := *abi.ConvertType(out[0], new(InternalTimestampedUint192Value)).(*InternalTimestampedUint192Value) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenPrice(token common.Address) (InternalTimestampedUint192Value, error) { - return _PriceRegistry.Contract.GetTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrice(token common.Address) (InternalTimestampedUint192Value, error) { - return _PriceRegistry.Contract.GetTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCaller) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedUint192Value, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPrices", tokens) - - if err != nil { - return *new([]InternalTimestampedUint192Value), err - } - - out0 := *abi.ConvertType(out[0], new([]InternalTimestampedUint192Value)).(*[]InternalTimestampedUint192Value) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedUint192Value, error) { - return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedUint192Value, error) { - return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) -} - -func (_PriceRegistry *PriceRegistryCaller) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { - var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getValidatedTokenPrice", token) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_PriceRegistry *PriceRegistrySession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCallerSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedTokenPrice(&_PriceRegistry.CallOpts, token) -} - -func (_PriceRegistry *PriceRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _PriceRegistry.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 (_PriceRegistry *PriceRegistrySession) Owner() (common.Address, error) { - return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryCallerSession) Owner() (common.Address, error) { - return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) -} - -func (_PriceRegistry *PriceRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "acceptOwnership") -} - -func (_PriceRegistry *PriceRegistrySession) AcceptOwnership() (*types.Transaction, error) { - return _PriceRegistry.Contract.AcceptOwnership(&_PriceRegistry.TransactOpts) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _PriceRegistry.Contract.AcceptOwnership(&_PriceRegistry.TransactOpts) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyFeeTokensUpdates", feeTokensToAdd, feeTokensToRemove) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) -} - -func (_PriceRegistry *PriceRegistryTransactor) ApplyPriceUpdatersUpdates(opts *bind.TransactOpts, priceUpdatersToAdd []common.Address, priceUpdatersToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyPriceUpdatersUpdates", priceUpdatersToAdd, priceUpdatersToRemove) -} - -func (_PriceRegistry *PriceRegistrySession) ApplyPriceUpdatersUpdates(priceUpdatersToAdd []common.Address, priceUpdatersToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyPriceUpdatersUpdates(&_PriceRegistry.TransactOpts, priceUpdatersToAdd, priceUpdatersToRemove) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyPriceUpdatersUpdates(priceUpdatersToAdd []common.Address, priceUpdatersToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyPriceUpdatersUpdates(&_PriceRegistry.TransactOpts, priceUpdatersToAdd, priceUpdatersToRemove) -} - -func (_PriceRegistry *PriceRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "transferOwnership", to) -} - -func (_PriceRegistry *PriceRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.TransferOwnership(&_PriceRegistry.TransactOpts, to) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.TransferOwnership(&_PriceRegistry.TransactOpts, to) -} - -func (_PriceRegistry *PriceRegistryTransactor) UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "updatePrices", priceUpdates) -} - -func (_PriceRegistry *PriceRegistrySession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdatePrices(&_PriceRegistry.TransactOpts, priceUpdates) -} - -func (_PriceRegistry *PriceRegistryTransactorSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdatePrices(&_PriceRegistry.TransactOpts, priceUpdates) -} - -type PriceRegistryFeeTokenAddedIterator struct { - Event *PriceRegistryFeeTokenAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenAdded) - 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(PriceRegistryFeeTokenAdded) - 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 *PriceRegistryFeeTokenAddedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryFeeTokenAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryFeeTokenAdded struct { - FeeToken common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryFeeTokenAddedIterator{contract: _PriceRegistry.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", 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 (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) { - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryFeeTokenRemovedIterator struct { - Event *PriceRegistryFeeTokenRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenRemoved) - 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(PriceRegistryFeeTokenRemoved) - 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 *PriceRegistryFeeTokenRemovedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryFeeTokenRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryFeeTokenRemoved struct { - FeeToken common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryFeeTokenRemovedIterator{contract: _PriceRegistry.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", 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 (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) { - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryOwnershipTransferRequestedIterator struct { - Event *PriceRegistryOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferRequested) - 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(PriceRegistryOwnershipTransferRequested) - 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 *PriceRegistryOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, 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 := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &PriceRegistryOwnershipTransferRequestedIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, 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 := _PriceRegistry.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(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.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 (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) { - event := new(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryOwnershipTransferredIterator struct { - Event *PriceRegistryOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferred) - 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(PriceRegistryOwnershipTransferred) - 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 *PriceRegistryOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferredIterator, 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 := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &PriceRegistryOwnershipTransferredIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferred, 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 := _PriceRegistry.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(PriceRegistryOwnershipTransferred) - if err := _PriceRegistry.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 (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) { - event := new(PriceRegistryOwnershipTransferred) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryPriceUpdaterRemovedIterator struct { - Event *PriceRegistryPriceUpdaterRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryPriceUpdaterRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryPriceUpdaterRemoved) - 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(PriceRegistryPriceUpdaterRemoved) - 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 *PriceRegistryPriceUpdaterRemovedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryPriceUpdaterRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryPriceUpdaterRemoved struct { - PriceUpdater common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterPriceUpdaterRemoved(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterRemovedIterator, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PriceUpdaterRemoved", priceUpdaterRule) - if err != nil { - return nil, err - } - return &PriceRegistryPriceUpdaterRemovedIterator{contract: _PriceRegistry.contract, event: "PriceUpdaterRemoved", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchPriceUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterRemoved, priceUpdater []common.Address) (event.Subscription, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PriceUpdaterRemoved", priceUpdaterRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryPriceUpdaterRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterRemoved", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePriceUpdaterRemoved(log types.Log) (*PriceRegistryPriceUpdaterRemoved, error) { - event := new(PriceRegistryPriceUpdaterRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryPriceUpdaterSetIterator struct { - Event *PriceRegistryPriceUpdaterSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryPriceUpdaterSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryPriceUpdaterSet) - 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(PriceRegistryPriceUpdaterSet) - 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 *PriceRegistryPriceUpdaterSetIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryPriceUpdaterSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryPriceUpdaterSet struct { - PriceUpdater common.Address - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterPriceUpdaterSet(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterSetIterator, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PriceUpdaterSet", priceUpdaterRule) - if err != nil { - return nil, err - } - return &PriceRegistryPriceUpdaterSetIterator{contract: _PriceRegistry.contract, event: "PriceUpdaterSet", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchPriceUpdaterSet(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterSet, priceUpdater []common.Address) (event.Subscription, error) { - - var priceUpdaterRule []interface{} - for _, priceUpdaterItem := range priceUpdater { - priceUpdaterRule = append(priceUpdaterRule, priceUpdaterItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PriceUpdaterSet", priceUpdaterRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryPriceUpdaterSet) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterSet", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePriceUpdaterSet(log types.Log) (*PriceRegistryPriceUpdaterSet, error) { - event := new(PriceRegistryPriceUpdaterSet) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceUpdaterSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryUsdPerTokenUpdatedIterator struct { - Event *PriceRegistryUsdPerTokenUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerTokenUpdated) - 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(PriceRegistryUsdPerTokenUpdated) - 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 *PriceRegistryUsdPerTokenUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryUsdPerTokenUpdated struct { - Token common.Address - Value *big.Int - Timestamp *big.Int - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "UsdPerTokenUpdated", tokenRule) - if err != nil { - return nil, err - } - return &PriceRegistryUsdPerTokenUpdatedIterator{contract: _PriceRegistry.contract, event: "UsdPerTokenUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "UsdPerTokenUpdated", tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryUsdPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerTokenUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseUsdPerTokenUpdated(log types.Log) (*PriceRegistryUsdPerTokenUpdated, error) { - event := new(PriceRegistryUsdPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type PriceRegistryUsdPerUnitGasUpdatedIterator struct { - Event *PriceRegistryUsdPerUnitGasUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerUnitGasUpdated) - 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(PriceRegistryUsdPerUnitGasUpdated) - 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 *PriceRegistryUsdPerUnitGasUpdatedIterator) Error() error { - return it.fail -} - -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type PriceRegistryUsdPerUnitGasUpdated struct { - DestChain uint64 - Value *big.Int - Timestamp *big.Int - Raw types.Log -} - -func (_PriceRegistry *PriceRegistryFilterer) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*PriceRegistryUsdPerUnitGasUpdatedIterator, error) { - - var destChainRule []interface{} - for _, destChainItem := range destChain { - destChainRule = append(destChainRule, destChainItem) - } - - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "UsdPerUnitGasUpdated", destChainRule) - if err != nil { - return nil, err - } - return &PriceRegistryUsdPerUnitGasUpdatedIterator{contract: _PriceRegistry.contract, event: "UsdPerUnitGasUpdated", logs: logs, sub: sub}, nil -} - -func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { - - var destChainRule []interface{} - for _, destChainItem := range destChain { - destChainRule = append(destChainRule, destChainItem) - } - - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "UsdPerUnitGasUpdated", destChainRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(PriceRegistryUsdPerUnitGasUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerUnitGasUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseUsdPerUnitGasUpdated(log types.Log) (*PriceRegistryUsdPerUnitGasUpdated, error) { - event := new(PriceRegistryUsdPerUnitGasUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type GetTokenAndGasPrices struct { - TokenPrice *big.Int - GasPriceValue *big.Int -} - -func (_PriceRegistry *PriceRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _PriceRegistry.abi.Events["FeeTokenAdded"].ID: - return _PriceRegistry.ParseFeeTokenAdded(log) - case _PriceRegistry.abi.Events["FeeTokenRemoved"].ID: - return _PriceRegistry.ParseFeeTokenRemoved(log) - case _PriceRegistry.abi.Events["OwnershipTransferRequested"].ID: - return _PriceRegistry.ParseOwnershipTransferRequested(log) - case _PriceRegistry.abi.Events["OwnershipTransferred"].ID: - return _PriceRegistry.ParseOwnershipTransferred(log) - case _PriceRegistry.abi.Events["PriceUpdaterRemoved"].ID: - return _PriceRegistry.ParsePriceUpdaterRemoved(log) - case _PriceRegistry.abi.Events["PriceUpdaterSet"].ID: - return _PriceRegistry.ParsePriceUpdaterSet(log) - case _PriceRegistry.abi.Events["UsdPerTokenUpdated"].ID: - return _PriceRegistry.ParseUsdPerTokenUpdated(log) - case _PriceRegistry.abi.Events["UsdPerUnitGasUpdated"].ID: - return _PriceRegistry.ParseUsdPerUnitGasUpdated(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (PriceRegistryFeeTokenAdded) Topic() common.Hash { - return common.HexToHash("0xdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23") -} - -func (PriceRegistryFeeTokenRemoved) Topic() common.Hash { - return common.HexToHash("0x1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91") -} - -func (PriceRegistryOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (PriceRegistryOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (PriceRegistryPriceUpdaterRemoved) Topic() common.Hash { - return common.HexToHash("0xff7dbb85c77ca68ca1f894d6498570e3d5095cd19466f07ee8d222b337e4068c") -} - -func (PriceRegistryPriceUpdaterSet) Topic() common.Hash { - return common.HexToHash("0x34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b8") -} - -func (PriceRegistryUsdPerTokenUpdated) Topic() common.Hash { - return common.HexToHash("0x52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a") -} - -func (PriceRegistryUsdPerUnitGasUpdated) Topic() common.Hash { - return common.HexToHash("0xdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e") -} - -func (_PriceRegistry *PriceRegistry) Address() common.Address { - return _PriceRegistry.address -} - -type PriceRegistryInterface interface { - ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) - - GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedUint192Value, error) - - GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) - - GetPriceUpdaters(opts *bind.CallOpts) ([]common.Address, error) - - GetStalenessThreshold(opts *bind.CallOpts) (*big.Int, error) - - GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, - - error) - - GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedUint192Value, error) - - GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedUint192Value, error) - - GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) - - ApplyPriceUpdatersUpdates(opts *bind.TransactOpts, priceUpdatersToAdd []common.Address, priceUpdatersToRemove []common.Address) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) - - FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) - - WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) - - ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) - - FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) - - WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) - - ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) - - FilterPriceUpdaterRemoved(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterRemovedIterator, error) - - WatchPriceUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterRemoved, priceUpdater []common.Address) (event.Subscription, error) - - ParsePriceUpdaterRemoved(log types.Log) (*PriceRegistryPriceUpdaterRemoved, error) - - FilterPriceUpdaterSet(opts *bind.FilterOpts, priceUpdater []common.Address) (*PriceRegistryPriceUpdaterSetIterator, error) - - WatchPriceUpdaterSet(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceUpdaterSet, priceUpdater []common.Address) (event.Subscription, error) - - ParsePriceUpdaterSet(log types.Log) (*PriceRegistryPriceUpdaterSet, error) - - FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) - - WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) - - ParseUsdPerTokenUpdated(log types.Log) (*PriceRegistryUsdPerTokenUpdated, error) - - FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*PriceRegistryUsdPerUnitGasUpdatedIterator, error) - - WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) - - ParseUsdPerUnitGasUpdated(log types.Log) (*PriceRegistryUsdPerUnitGasUpdated, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/ccip/generated/price_registry_1_2_0/price_registry.go b/core/gethwrappers/ccip/generated/price_registry_1_2_0/price_registry.go index 64e16bd1dcf..30b1b26da94 100644 --- a/core/gethwrappers/ccip/generated/price_registry_1_2_0/price_registry.go +++ b/core/gethwrappers/ccip/generated/price_registry_1_2_0/price_registry.go @@ -1690,4 +1690,4 @@ type PriceRegistryInterface interface { ParseLog(log types.Log) (generated.AbigenLog, error) Address() common.Address -} \ No newline at end of file +} 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 bab8100d6f8..121135075db 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 @@ -32,7 +32,7 @@ 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\"},{\"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\":\"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: "0x60a060405234801561001057600080fd5b5060405161048938038061048983398101604081905261002f91610067565b6001600160a01b03811661005657604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b0316608052610097565b60006020828403121561007957600080fd5b81516001600160a01b038116811461009057600080fd5b9392505050565b6080516103d76100b2600039600061023201526103d76000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063181f5a771461004657806396ea2f7a14610064578063ff12c35414610079575b600080fd5b61004e61008c565b60405161005b91906102d7565b60405180910390f35b610077610072366004610366565b6100a8565b005b610077610087366004610366565b610123565b6040518060600160405280602381526020016103a86023913981565b610120818273ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061011b919061038a565b610172565b50565b610120818273ffffffffffffffffffffffffffffffffffffffff16638fd6a6ac6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100f7573d6000803e3d6000fd5b73ffffffffffffffffffffffffffffffffffffffff811633146101e5576040517fc454d18200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301528316602482015260440160405180910390fd5b6040517fe677ae3700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063e677ae3790604401600060405180830381600087803b15801561027657600080fd5b505af115801561028a573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8085169350851691507f09590fb70af4b833346363965e043a9339e8c7d378b8a2b903c75c277faec4f990600090a35050565b60006020808352835180602085015260005b81811015610305578581018301518582016040015282016102e9565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461012057600080fd5b60006020828403121561037857600080fd5b813561038381610344565b9392505050565b60006020828403121561039c57600080fd5b81516103838161034456fe52656769737472794d6f64756c654f776e6572437573746f6d20312e352e302d646576a164736f6c6343000818000a", + Bin: "0x60a060405234801561001057600080fd5b5060405161047e38038061047e83398101604081905261002f91610067565b6001600160a01b03811661005657604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b0316608052610097565b60006020828403121561007957600080fd5b81516001600160a01b038116811461009057600080fd5b9392505050565b6080516103cc6100b2600039600061024a01526103cc6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063181f5a771461004657806396ea2f7a14610098578063ff12c354146100ad575b600080fd5b6100826040518060400160405280601f81526020017f52656769737472794d6f64756c654f776e6572437573746f6d20312e352e300081525081565b60405161008f91906102ef565b60405180910390f35b6100ab6100a636600461037e565b6100c0565b005b6100ab6100bb36600461037e565b61013b565b610138818273ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061013391906103a2565b61018a565b50565b610138818273ffffffffffffffffffffffffffffffffffffffff16638fd6a6ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010f573d6000803e3d6000fd5b73ffffffffffffffffffffffffffffffffffffffff811633146101fd576040517fc454d18200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301528316602482015260440160405180910390fd5b6040517fe677ae3700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063e677ae3790604401600060405180830381600087803b15801561028e57600080fd5b505af11580156102a2573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8085169350851691507f09590fb70af4b833346363965e043a9339e8c7d378b8a2b903c75c277faec4f990600090a35050565b60006020808352835180602085015260005b8181101561031d57858101830151858201604001528201610301565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461013857600080fd5b60006020828403121561039057600080fd5b813561039b8161035c565b9392505050565b6000602082840312156103b457600080fd5b815161039b8161035c56fea164736f6c6343000818000a", } 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 1648ea9ba51..45e49035b05 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -30,20 +30,9 @@ var ( _ = abi.ConvertType ) -type EVM2EVMMultiOffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []EVM2EVMMultiOffRampMerkleRoot -} - -type EVM2EVMMultiOffRampInterval struct { - Min uint64 - Max uint64 -} - -type EVM2EVMMultiOffRampMerkleRoot struct { - SourceChainSelector uint64 - Interval EVM2EVMMultiOffRampInterval - MerkleRoot [32]byte +type IRMNRemoteSignature struct { + R [32]byte + S [32]byte } type InternalAny2EVMRampMessage struct { @@ -52,10 +41,18 @@ type InternalAny2EVMRampMessage struct { Data []byte Receiver common.Address GasLimit *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalAny2EVMTokenTransfer +} + +type InternalAny2EVMTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress common.Address + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int } -type InternalExecutionReportSingleChain struct { +type InternalExecutionReport struct { SourceChainSelector uint64 Messages []InternalAny2EVMRampMessage OffchainTokenData [][][]byte @@ -68,6 +65,14 @@ type InternalGasPriceUpdate struct { UsdPerUnitGas *big.Int } +type InternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + type InternalPriceUpdates struct { TokenPriceUpdates []InternalTokenPriceUpdate GasPriceUpdates []InternalGasPriceUpdate @@ -81,21 +86,21 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int -} - type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int } +type OffRampCommitReport struct { + PriceUpdates InternalPriceUpdates + MerkleRoots []InternalMerkleRoot + RmnSignatures []IRMNRemoteSignature + RmnRawVs *big.Int +} + 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\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"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.ExecutionReportSingleChain[]\",\"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\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"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.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061124f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e61004936600461024f565b610084565b60405161005b91906104f5565b60405180910390f35b61007761007236600461024f565b6100a0565b60405161005b91906107ae565b60608180602001905181019061009a9190610dc3565b92915050565b604080516080810182526060918101828152828201839052815260208101919091528180602001905181019061009a91906110d9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715610128576101286100d6565b60405290565b6040516080810167ffffffffffffffff81118282101715610128576101286100d6565b60405160c0810167ffffffffffffffff81118282101715610128576101286100d6565b6040805190810167ffffffffffffffff81118282101715610128576101286100d6565b6040516060810167ffffffffffffffff81118282101715610128576101286100d6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610201576102016100d6565b604052919050565b600067ffffffffffffffff821115610223576102236100d6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561026157600080fd5b813567ffffffffffffffff81111561027857600080fd5b8201601f8101841361028957600080fd5b803561029c61029782610209565b6101ba565b8181528560208385010111156102b157600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102ea5781810151838201526020016102d2565b50506000910152565b6000815180845261030b8160208601602086016102cf565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103f2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895281516080815181865261039e828701826102f3565b91505085820151858203878701526103b682826102f3565b915050604080830151868303828801526103d083826102f3565b606094850151979094019690965250509884019892509083019060010161035a565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104aa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049357858a83030184526104818286516102f3565b948c0194938c01939150600101610467565b509e8a019e9750505093870193505060010161041f565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104ea578151875295820195908201906001016104ce565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610686577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106096101408901826102f3565b9050604082015188820360c08a015261062282826102f3565b915050606082015161064c60e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a08201519150878103610120890152610672818361033d565b97505050928c0192918c0191600101610589565b5050505050604082015187820360408901526106a282826103ff565b915050606082015187820360608901526106bc82826104b9565b6080938401519890930197909752509450928501929085019060010161051c565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104ea578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106ff565b600081518084526020808501945080840160005b838110156104ea578151805167ffffffffffffffff90811689528482015180518216868b0152850151166040808a01919091520151606088015260809096019590820190600101610762565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b8083101561083e578351805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16878301529286019260019290920191908401906107e1565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa00160808901529361087881866106ea565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526108b8818361074e565b95945050505050565b600067ffffffffffffffff8211156108db576108db6100d6565b5060051b60200190565b805167ffffffffffffffff811681146108fd57600080fd5b919050565b600060a0828403121561091457600080fd5b61091c610105565b90508151815261092e602083016108e5565b602082015261093f604083016108e5565b6040820152610950606083016108e5565b6060820152610961608083016108e5565b608082015292915050565b600082601f83011261097d57600080fd5b815161098b61029782610209565b8181528460208386010111156109a057600080fd5b6109b18260208301602087016102cf565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146108fd57600080fd5b600082601f8301126109ee57600080fd5b815160206109fe610297836108c1565b82815260059290921b84018101918181019086841115610a1d57600080fd5b8286015b84811015610b1157805167ffffffffffffffff80821115610a425760008081fd5b81890191506080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610a7b5760008081fd5b610a8361012e565b8784015183811115610a955760008081fd5b610aa38d8a8388010161096c565b82525060408085015184811115610aba5760008081fd5b610ac88e8b8389010161096c565b8a8401525060608086015185811115610ae15760008081fd5b610aef8f8c838a010161096c565b9284019290925294909201519381019390935250508352918301918301610a21565b509695505050505050565b600082601f830112610b2d57600080fd5b81516020610b3d610297836108c1565b82815260059290921b84018101918181019086841115610b5c57600080fd5b8286015b84811015610b1157805167ffffffffffffffff80821115610b815760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610bbb5760008081fd5b610bc3610151565b610bcf8c898601610902565b815260c084015183811115610be45760008081fd5b610bf28d8a8388010161096c565b898301525060e084015183811115610c0a5760008081fd5b610c188d8a8388010161096c565b604083015250610c2b61010085016109b9565b60608201526101208401516080820152908301519082821115610c4e5760008081fd5b610c5c8c89848701016109dd565b60a08201528652505050918301918301610b60565b600082601f830112610c8257600080fd5b81516020610c92610297836108c1565b82815260059290921b84018101918181019086841115610cb157600080fd5b8286015b84811015610b1157805167ffffffffffffffff80821115610cd557600080fd5b818901915089603f830112610ce957600080fd5b85820151610cf9610297826108c1565b81815260059190911b830160400190878101908c831115610d1957600080fd5b604085015b83811015610d5257805185811115610d3557600080fd5b610d448f6040838a010161096c565b845250918901918901610d1e565b50875250505092840192508301610cb5565b600082601f830112610d7557600080fd5b81516020610d85610297836108c1565b8083825260208201915060208460051b870101935086841115610da757600080fd5b602086015b84811015610b115780518352918301918301610dac565b60006020808385031215610dd657600080fd5b825167ffffffffffffffff80821115610dee57600080fd5b818501915085601f830112610e0257600080fd5b8151610e10610297826108c1565b81815260059190911b83018401908481019088831115610e2f57600080fd5b8585015b83811015610f2957805185811115610e4a57600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610e7f5760008081fd5b610e87610105565b610e928983016108e5565b815260408083015188811115610ea85760008081fd5b610eb68e8c83870101610b1c565b8b8401525060608084015189811115610ecf5760008081fd5b610edd8f8d83880101610c71565b8385015250608091508184015189811115610ef85760008081fd5b610f068f8d83880101610d64565b918401919091525060a09290920151918101919091528352918601918601610e33565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146108fd57600080fd5b600082601f830112610f7357600080fd5b81516020610f83610297836108c1565b82815260069290921b84018101918181019086841115610fa257600080fd5b8286015b84811015610b115760408189031215610fbf5760008081fd5b610fc7610174565b610fd0826108e5565b8152610fdd858301610f36565b81860152835291830191604001610fa6565b600082601f83011261100057600080fd5b81516020611010610297836108c1565b82815260079290921b8401810191818101908684111561102f57600080fd5b8286015b84811015610b1157808803608081121561104d5760008081fd5b611055610197565b61105e836108e5565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156110925760008081fd5b61109a610174565b92506110a78785016108e5565b83526110b48185016108e5565b8388015281870192909252606083015191810191909152835291830191608001611033565b600060208083850312156110ec57600080fd5b825167ffffffffffffffff8082111561110457600080fd5b8185019150604080838803121561111a57600080fd5b611122610174565b83518381111561113157600080fd5b84016040818a03121561114357600080fd5b61114b610174565b81518581111561115a57600080fd5b8201601f81018b1361116b57600080fd5b8051611179610297826108c1565b81815260069190911b8201890190898101908d83111561119857600080fd5b928a01925b828410156111e65787848f0312156111b55760008081fd5b6111bd610174565b6111c6856109b9565b81526111d38c8601610f36565b818d0152825292870192908a019061119d565b8452505050818701519350848411156111fe57600080fd5b61120a8a858401610f62565b818801528252508385015191508282111561122457600080fd5b61123088838601610fef565b8582015280955050505050509291505056fea164736f6c6343000818000a", + 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[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"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: "0x608060405234801561001057600080fd5b506113e8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e61004936600461023a565b610084565b60405161005b91906104f7565b60405180910390f35b61007761007236600461023a565b6100a0565b60405161005b919061083c565b60608180602001905181019061009a9190610e85565b92915050565b6040805160c08101825260606080820181815260a08301829052825260208083018290529282018190526000908201528251909161009a9184018101908401611245565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715610136576101366100e4565b60405290565b60405160c0810167ffffffffffffffff81118282101715610136576101366100e4565b6040805190810167ffffffffffffffff81118282101715610136576101366100e4565b6040516080810167ffffffffffffffff81118282101715610136576101366100e4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101ec576101ec6100e4565b604052919050565b600067ffffffffffffffff82111561020e5761020e6100e4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024c57600080fd5b813567ffffffffffffffff81111561026357600080fd5b8201601f8101841361027457600080fd5b8035610287610282826101f4565b6101a5565b81815285602083850101111561029c57600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600081518084526102f68160208601602086016102ba565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103f4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610389828701826102de565b91505073ffffffffffffffffffffffffffffffffffffffff868301511686860152604063ffffffff81840151168187015250606080830151868303828801526103d283826102de565b6080948501519790940196909652505098840198925090830190600101610345565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104ac577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049557858a83030184526104838286516102de565b948c0194938c01939150600101610469565b509e8a019e97505050938701935050600101610421565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104ec578151875295820195908201906001016104d0565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106df577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610688577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a089015261060b6101408901826102de565b9050604082015188820360c08a015261062482826102de565b915050606082015161064e60e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a082015191508781036101208901526106748183610328565b97505050928c0192918c019160010161058b565b5050505050604082015187820360408901526106a48282610401565b915050606082015187820360608901526106be82826104bb565b6080938401519890930197909752509450928501929085019060010161051e565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104ec578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168388015260409096019590820190600101610701565b600082825180855260208086019550808260051b84010181860160005b848110156103f4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107c4838801826102de565b6040858101518416908901526060808601519093169288019290925250608092830151929095019190915250978301979083019060010161076d565b60008151808452602080850194506020840160005b838110156104ec578151805188528301518388015260409096019590820190600101610815565b602080825282516080838301528051604060a08501819052815160e08601819052600094939284019185916101008801905b808410156108cb578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168783015293860193600193909301929082019061086e565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160c08901529361090581866106ec565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808583030160408601526109468284610750565b92506040860151915080858403016060860152506109648282610800565b915050606084015160808401528091505092915050565b600067ffffffffffffffff821115610995576109956100e4565b5060051b60200190565b805167ffffffffffffffff811681146109b757600080fd5b919050565b600060a082840312156109ce57600080fd5b6109d6610113565b9050815181526109e86020830161099f565b60208201526109f96040830161099f565b6040820152610a0a6060830161099f565b6060820152610a1b6080830161099f565b608082015292915050565b600082601f830112610a3757600080fd5b8151610a45610282826101f4565b818152846020838601011115610a5a57600080fd5b610a6b8260208301602087016102ba565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146109b757600080fd5b600082601f830112610aa857600080fd5b81516020610ab86102828361097b565b82815260059290921b84018101918181019086841115610ad757600080fd5b8286015b84811015610bd357805167ffffffffffffffff80821115610afc5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b355760008081fd5b610b3d610113565b8784015183811115610b4f5760008081fd5b610b5d8d8a83880101610a26565b8252506040610b6d818601610a73565b8983015260608086015163ffffffff81168114610b8a5760008081fd5b808385015250608091508186015185811115610ba65760008081fd5b610bb48f8c838a0101610a26565b9184019190915250919093015190830152508352918301918301610adb565b509695505050505050565b600082601f830112610bef57600080fd5b81516020610bff6102828361097b565b82815260059290921b84018101918181019086841115610c1e57600080fd5b8286015b84811015610bd357805167ffffffffffffffff80821115610c435760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c7d5760008081fd5b610c8561013c565b610c918c8986016109bc565b815260c084015183811115610ca65760008081fd5b610cb48d8a83880101610a26565b898301525060e084015183811115610ccc5760008081fd5b610cda8d8a83880101610a26565b604083015250610ced6101008501610a73565b60608201526101208401516080820152908301519082821115610d105760008081fd5b610d1e8c8984870101610a97565b60a08201528652505050918301918301610c22565b600082601f830112610d4457600080fd5b81516020610d546102828361097b565b82815260059290921b84018101918181019086841115610d7357600080fd5b8286015b84811015610bd357805167ffffffffffffffff80821115610d9757600080fd5b818901915089603f830112610dab57600080fd5b85820151610dbb6102828261097b565b81815260059190911b830160400190878101908c831115610ddb57600080fd5b604085015b83811015610e1457805185811115610df757600080fd5b610e068f6040838a0101610a26565b845250918901918901610de0565b50875250505092840192508301610d77565b600082601f830112610e3757600080fd5b81516020610e476102828361097b565b8083825260208201915060208460051b870101935086841115610e6957600080fd5b602086015b84811015610bd35780518352918301918301610e6e565b60006020808385031215610e9857600080fd5b825167ffffffffffffffff80821115610eb057600080fd5b818501915085601f830112610ec457600080fd5b8151610ed26102828261097b565b81815260059190911b83018401908481019088831115610ef157600080fd5b8585015b83811015610feb57805185811115610f0c57600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f415760008081fd5b610f49610113565b610f5489830161099f565b815260408083015188811115610f6a5760008081fd5b610f788e8c83870101610bde565b8b8401525060608084015189811115610f915760008081fd5b610f9f8f8d83880101610d33565b8385015250608091508184015189811115610fba5760008081fd5b610fc88f8d83880101610e26565b918401919091525060a09290920151918101919091528352918601918601610ef5565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146109b757600080fd5b600082601f83011261103557600080fd5b815160206110456102828361097b565b82815260069290921b8401810191818101908684111561106457600080fd5b8286015b84811015610bd357604081890312156110815760008081fd5b61108961015f565b6110928261099f565b815261109f858301610ff8565b81860152835291830191604001611068565b600082601f8301126110c257600080fd5b815160206110d26102828361097b565b82815260059290921b840181019181810190868411156110f157600080fd5b8286015b84811015610bd357805167ffffffffffffffff808211156111165760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561114f5760008081fd5b611157610113565b61116288850161099f565b8152604080850151848111156111785760008081fd5b6111868e8b83890101610a26565b8a840152506060935061119a84860161099f565b9082015260806111ab85820161099f565b938201939093529201519082015283529183019183016110f5565b600082601f8301126111d757600080fd5b815160206111e76102828361097b565b82815260069290921b8401810191818101908684111561120657600080fd5b8286015b84811015610bd357604081890312156112235760008081fd5b61122b61015f565b81518152848201518582015283529183019160400161120a565b6000602080838503121561125857600080fd5b825167ffffffffffffffff8082111561127057600080fd5b908401906080828703121561128457600080fd5b61128c610182565b82518281111561129b57600080fd5b830160408189038113156112ae57600080fd5b6112b661015f565b8251858111156112c557600080fd5b8301601f81018b136112d657600080fd5b80516112e46102828261097b565b81815260069190911b8201890190898101908d83111561130357600080fd5b928a01925b828410156113515785848f0312156113205760008081fd5b61132861015f565b61133185610a73565b815261133e8c8601610ff8565b818d0152825292850192908a0190611308565b84525050508287015191508482111561136957600080fd5b6113758a838501611024565b8188015283525050828401518281111561138e57600080fd5b61139a888286016110b1565b858301525060408301519350818411156113b357600080fd5b6113bf878585016111c6565b604082015260608301516060820152809450505050509291505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI @@ -234,47 +239,47 @@ func (_ReportCodec *ReportCodecTransactorRaw) Transact(opts *bind.TransactOpts, return _ReportCodec.Contract.contract.Transact(opts, method, params...) } -func (_ReportCodec *ReportCodecCaller) DecodeCommitReport(opts *bind.CallOpts, report []byte) (EVM2EVMMultiOffRampCommitReport, error) { +func (_ReportCodec *ReportCodecCaller) DecodeCommitReport(opts *bind.CallOpts, report []byte) (OffRampCommitReport, error) { var out []interface{} err := _ReportCodec.contract.Call(opts, &out, "decodeCommitReport", report) if err != nil { - return *new(EVM2EVMMultiOffRampCommitReport), err + return *new(OffRampCommitReport), err } - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOffRampCommitReport)).(*EVM2EVMMultiOffRampCommitReport) + out0 := *abi.ConvertType(out[0], new(OffRampCommitReport)).(*OffRampCommitReport) return out0, err } -func (_ReportCodec *ReportCodecSession) DecodeCommitReport(report []byte) (EVM2EVMMultiOffRampCommitReport, error) { +func (_ReportCodec *ReportCodecSession) DecodeCommitReport(report []byte) (OffRampCommitReport, error) { return _ReportCodec.Contract.DecodeCommitReport(&_ReportCodec.CallOpts, report) } -func (_ReportCodec *ReportCodecCallerSession) DecodeCommitReport(report []byte) (EVM2EVMMultiOffRampCommitReport, error) { +func (_ReportCodec *ReportCodecCallerSession) DecodeCommitReport(report []byte) (OffRampCommitReport, error) { return _ReportCodec.Contract.DecodeCommitReport(&_ReportCodec.CallOpts, report) } -func (_ReportCodec *ReportCodecCaller) DecodeExecuteReport(opts *bind.CallOpts, report []byte) ([]InternalExecutionReportSingleChain, error) { +func (_ReportCodec *ReportCodecCaller) DecodeExecuteReport(opts *bind.CallOpts, report []byte) ([]InternalExecutionReport, error) { var out []interface{} err := _ReportCodec.contract.Call(opts, &out, "decodeExecuteReport", report) if err != nil { - return *new([]InternalExecutionReportSingleChain), err + return *new([]InternalExecutionReport), err } - out0 := *abi.ConvertType(out[0], new([]InternalExecutionReportSingleChain)).(*[]InternalExecutionReportSingleChain) + out0 := *abi.ConvertType(out[0], new([]InternalExecutionReport)).(*[]InternalExecutionReport) return out0, err } -func (_ReportCodec *ReportCodecSession) DecodeExecuteReport(report []byte) ([]InternalExecutionReportSingleChain, error) { +func (_ReportCodec *ReportCodecSession) DecodeExecuteReport(report []byte) ([]InternalExecutionReport, error) { return _ReportCodec.Contract.DecodeExecuteReport(&_ReportCodec.CallOpts, report) } -func (_ReportCodec *ReportCodecCallerSession) DecodeExecuteReport(report []byte) ([]InternalExecutionReportSingleChain, error) { +func (_ReportCodec *ReportCodecCallerSession) DecodeExecuteReport(report []byte) ([]InternalExecutionReport, error) { return _ReportCodec.Contract.DecodeExecuteReport(&_ReportCodec.CallOpts, report) } @@ -339,7 +344,7 @@ func (it *ReportCodecCommitReportDecodedIterator) Close() error { } type ReportCodecCommitReportDecoded struct { - Report EVM2EVMMultiOffRampCommitReport + Report OffRampCommitReport Raw types.Log } @@ -456,7 +461,7 @@ func (it *ReportCodecExecuteReportDecodedIterator) Close() error { } type ReportCodecExecuteReportDecoded struct { - Report []InternalExecutionReportSingleChain + Report []InternalExecutionReport Raw types.Log } @@ -525,11 +530,11 @@ func (_ReportCodec *ReportCodec) ParseLog(log types.Log) (generated.AbigenLog, e } func (ReportCodecCommitReportDecoded) Topic() common.Hash { - return common.HexToHash("0x1b2cb5e9d31bdaabb2ae07532436ae669406f84003ca27179b4dfb72f127f7dc") + return common.HexToHash("0x39ecb9cbf9994ec2d914cd3ec4bff76f953a004c8f16cd9d8fdd5e620b956834") } func (ReportCodecExecuteReportDecoded) Topic() common.Hash { - return common.HexToHash("0x7f4f1032eaaa1f5c3fc02d56071d69a09a2595d9a5fa4704f0eb298792908abb") + return common.HexToHash("0x9467c8093a35a72f74398d5b6e351d67dc82eddc378efc6177eafb4fc7a01d39") } func (_ReportCodec *ReportCodec) Address() common.Address { @@ -537,9 +542,9 @@ func (_ReportCodec *ReportCodec) Address() common.Address { } type ReportCodecInterface interface { - DecodeCommitReport(opts *bind.CallOpts, report []byte) (EVM2EVMMultiOffRampCommitReport, error) + DecodeCommitReport(opts *bind.CallOpts, report []byte) (OffRampCommitReport, error) - DecodeExecuteReport(opts *bind.CallOpts, report []byte) ([]InternalExecutionReportSingleChain, error) + DecodeExecuteReport(opts *bind.CallOpts, report []byte) ([]InternalExecutionReport, error) FilterCommitReportDecoded(opts *bind.FilterOpts) (*ReportCodecCommitReportDecodedIterator, error) diff --git a/core/gethwrappers/ccip/generated/arm_contract/arm_contract.go b/core/gethwrappers/ccip/generated/rmn_contract/rmn_contract.go similarity index 75% rename from core/gethwrappers/ccip/generated/arm_contract/arm_contract.go rename to core/gethwrappers/ccip/generated/rmn_contract/rmn_contract.go index e5cb17ded07..e314f0243a9 100644 --- a/core/gethwrappers/ccip/generated/arm_contract/arm_contract.go +++ b/core/gethwrappers/ccip/generated/rmn_contract/rmn_contract.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package arm_contract +package rmn_contract import ( "errors" @@ -68,17 +68,17 @@ type RMNVoter struct { CurseWeight uint8 } -var ARMContractMetaData = &bind.MetaData{ +var RMNContractMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"blessVoteAddr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"blessWeight\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"curseWeight\",\"type\":\"uint8\"}],\"internalType\":\"structRMN.Voter[]\",\"name\":\"voters\",\"type\":\"tuple[]\"},{\"internalType\":\"uint16\",\"name\":\"blessWeightThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"curseWeightThreshold\",\"type\":\"uint16\"}],\"internalType\":\"structRMN.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"internalType\":\"bytes16\",\"name\":\"curseId\",\"type\":\"bytes16\"}],\"name\":\"ReusedCurseId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubjectsMustBeStrictlyIncreasing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"}],\"name\":\"UnauthorizedVoter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnvoteToCurseNoop\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VoteToBlessForbiddenDuringActiveGlobalCurse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VoteToBlessNoop\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VoteToCurseNoop\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"}],\"name\":\"AlreadyBlessed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"}],\"name\":\"AlreadyVotedToBless\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"blessVoteAddr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"blessWeight\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"curseWeight\",\"type\":\"uint8\"}],\"internalType\":\"structRMN.Voter[]\",\"name\":\"voters\",\"type\":\"tuple[]\"},{\"internalType\":\"uint16\",\"name\":\"blessWeightThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"curseWeightThreshold\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"structRMN.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"CurseLifted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"}],\"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\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"}],\"name\":\"PermaBlessedCommitStoreAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"}],\"name\":\"PermaBlessedCommitStoreRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"indexed\":false,\"internalType\":\"bytes28\",\"name\":\"onchainCursesHash\",\"type\":\"bytes28\"},{\"indexed\":false,\"internalType\":\"bytes28\",\"name\":\"cursesHash\",\"type\":\"bytes28\"}],\"name\":\"SkippedUnvoteToCurse\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"wasBlessed\",\"type\":\"bool\"}],\"name\":\"TaggedRootBlessVotesReset\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"accumulatedWeight\",\"type\":\"uint16\"}],\"name\":\"TaggedRootBlessed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"weight\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes28\",\"name\":\"cursesHash\",\"type\":\"bytes28\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"remainingAccumulatedWeight\",\"type\":\"uint16\"}],\"name\":\"UnvotedToCurse\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"weight\",\"type\":\"uint8\"}],\"name\":\"VotedToBless\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"voter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"indexed\":false,\"internalType\":\"bytes16\",\"name\":\"curseId\",\"type\":\"bytes16\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"weight\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes28\",\"name\":\"cursesHash\",\"type\":\"bytes28\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"accumulatedWeight\",\"type\":\"uint16\"}],\"name\":\"VotedToCurse\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"}],\"name\":\"getBlessProgress\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"blessVoteAddrs\",\"type\":\"address[]\"},{\"internalType\":\"uint16\",\"name\":\"accumulatedWeight\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"blessed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"blessVoteAddr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"blessWeight\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"curseWeight\",\"type\":\"uint8\"}],\"internalType\":\"structRMN.Voter[]\",\"name\":\"voters\",\"type\":\"tuple[]\"},{\"internalType\":\"uint16\",\"name\":\"blessWeightThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"curseWeightThreshold\",\"type\":\"uint16\"}],\"internalType\":\"structRMN.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"getCurseProgress\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"curseVoteAddrs\",\"type\":\"address[]\"},{\"internalType\":\"bytes28[]\",\"name\":\"cursesHashes\",\"type\":\"bytes28[]\"},{\"internalType\":\"uint16\",\"name\":\"accumulatedWeight\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"cursed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjectsCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPermaBlessedCommitStores\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getRecordedCurseRelatedOps\",\"outputs\":[{\"components\":[{\"internalType\":\"enumRMN.RecordedCurseRelatedOpTag\",\"name\":\"tag\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"cursed\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"internalType\":\"bytes16\",\"name\":\"curseId\",\"type\":\"bytes16\"}],\"internalType\":\"structRMN.RecordedCurseRelatedOp[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRecordedCurseRelatedOpsCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":[{\"internalType\":\"bytes16\",\"name\":\"curseId\",\"type\":\"bytes16\"},{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"ownerCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"ownerRemoveThenAddPermaBlessedCommitStores\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMN.TaggedRoot[]\",\"name\":\"taggedRoots\",\"type\":\"tuple[]\"}],\"name\":\"ownerResetBlessVotes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"internalType\":\"bytes28\",\"name\":\"cursesHash\",\"type\":\"bytes28\"}],\"internalType\":\"structRMN.UnvoteToCurseRequest\",\"name\":\"unit\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"forceUnvote\",\"type\":\"bool\"}],\"internalType\":\"structRMN.OwnerUnvoteToCurseRequest[]\",\"name\":\"ownerUnvoteToCurseRequests\",\"type\":\"tuple[]\"}],\"name\":\"ownerUnvoteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"blessVoteAddr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curseVoteAddr\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"blessWeight\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"curseWeight\",\"type\":\"uint8\"}],\"internalType\":\"structRMN.Voter[]\",\"name\":\"voters\",\"type\":\"tuple[]\"},{\"internalType\":\"uint16\",\"name\":\"blessWeightThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"curseWeightThreshold\",\"type\":\"uint16\"}],\"internalType\":\"structRMN.Config\",\"name\":\"config\",\"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\":[{\"components\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"},{\"internalType\":\"bytes28\",\"name\":\"cursesHash\",\"type\":\"bytes28\"}],\"internalType\":\"structRMN.UnvoteToCurseRequest[]\",\"name\":\"unvoteToCurseRequests\",\"type\":\"tuple[]\"}],\"name\":\"unvoteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMN.TaggedRoot[]\",\"name\":\"taggedRoots\",\"type\":\"tuple[]\"}],\"name\":\"voteToBless\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"curseId\",\"type\":\"bytes16\"},{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"voteToCurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b506040516200596238038062005962833981016040819052620000349162000aff565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000138565b505060408051608081018252600080825260208201819052918101919091526001600160c81b03606082015290506001620000fb81601062000c7d565b82606001516001600160c81b0316901c6001600160c81b0316101562000125576200012562000c99565b506200013181620001e3565b5062000e14565b336001600160a01b03821603620001925760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee816200071d565b6200020c576040516306b7c75960e31b815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b60025415620003465760028054600091906200025a9060019062000c7d565b815481106200026d576200026d62000caf565b6000918252602080832060408051608081018252600294850290920180546001600160a01b0390811680855260019092015480821685870190815260ff600160a01b8304811687870152600160a81b909204909116606086015291875260058552828720805465ffffffffffff19169055905116855260099092529220805461ffff191690558054919250908062000309576200030962000cc5565b60008281526020902060026000199092019182020180546001600160a01b031916815560010180546001600160b01b03191690559055506200023b565b60005b81515181101562000403578151805160029190839081106200036f576200036f62000caf565b602090810291909101810151825460018181018555600094855293839020825160029092020180546001600160a01b039283166001600160a01b0319909116178155928201519284018054604084015160609094015160ff908116600160a81b0260ff60a81b1991909516600160a01b026001600160a81b0319909216959093169490941793909317161790550162000349565b50600480546000906200041c9063ffffffff1662000cdb565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff821610156200054157600083600001518260ff16815181106200046c576200046c62000caf565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff90811684880190815289821685870190815287516001600160a01b03908116600090815260058b5288812097518854945193518616650100000000000260ff60281b199487166401000000000264ffffffffff1990961691909716179390931791909116939093179094558587015190911683526009909552919020805491909201519092166101000261ffff1990921691909117600117905550620005398162000d01565b905062000440565b506001600160a01b0360005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7805461ffff191660011790556004805463ffffffff4381166401000000000263ffffffff60201b1990921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990620005db90859062000d23565b60405180910390a26040805160c08101825260048082526001600160401b03421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7018054939490939092849260ff19909216919084908111156200067c576200067c62000dce565b021790555060208201518154604084015160608501516001600160a01b03166a010000000000000000000002600160501b600160f01b031991151569010000000000000000000260ff60481b196001600160401b039095166101000294909416610100600160501b031990931692909217929092179190911617815560808083015160a090930151811c600160801b0292901c919091176001909101555050565b80515160009015806200073257508151516010105b80620007445750602082015161ffff16155b80620007565750604082015161ffff16155b156200076457506000919050565b600080600084600001515160026200077d919062000de4565b6001600160401b0381111562000797576200079762000a24565b604051908082528060200260200182016040528015620007c1578160200160208202803683370190505b50905060005b8551518110156200095457600086600001518281518110620007ed57620007ed62000caf565b6020026020010151905060006001600160a01b031681600001516001600160a01b0316148062000828575060208101516001600160a01b0316155b806200083f575060208101516001600160a01b0316155b8062000858575060208101516001600160a01b03908116145b806200087a5750604081015160ff161580156200087a5750606081015160ff16155b156200088d575060009695505050505050565b8051836200089d84600262000de4565b620008aa90600062000dfe565b81518110620008bd57620008bd62000caf565b6001600160a01b0390921660209283029190910182015281015183620008e584600262000de4565b620008f290600162000dfe565b8151811062000905576200090562000caf565b6001600160a01b03909216602092830291909101909101526040810151620009319060ff168662000dfe565b9450806060015160ff168462000948919062000dfe565b935050600101620007c7565b5060005b8151811015620009f957600082828151811062000979576200097962000caf565b60200260200101519050600082600162000994919062000dfe565b90505b8351811015620009ee57838181518110620009b657620009b662000caf565b60200260200101516001600160a01b0316826001600160a01b031603620009e557506000979650505050505050565b60010162000997565b505060010162000958565b50846020015161ffff16831015801562000a1b5750846040015161ffff168210155b95945050505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000a5f5762000a5f62000a24565b60405290565b604051608081016001600160401b038111828210171562000a5f5762000a5f62000a24565b604051601f8201601f191681016001600160401b038111828210171562000ab55762000ab562000a24565b604052919050565b80516001600160a01b038116811462000ad557600080fd5b919050565b805160ff8116811462000ad557600080fd5b805161ffff8116811462000ad557600080fd5b6000602080838503121562000b1357600080fd5b82516001600160401b038082111562000b2b57600080fd5b8185019150606080838803121562000b4257600080fd5b62000b4c62000a3a565b83518381111562000b5c57600080fd5b8401601f8101891362000b6e57600080fd5b80518481111562000b835762000b8362000a24565b62000b93878260051b0162000a8a565b818152878101955060079190911b82018701908a82111562000bb457600080fd5b918701915b8183101562000c33576080838c03121562000bd45760008081fd5b62000bde62000a65565b62000be98462000abd565b815262000bf889850162000abd565b89820152604062000c0b81860162000ada565b9082015262000c1c84870162000ada565b818701528652948701946080929092019162000bb9565b83525062000c45905084860162000aec565b8582015262000c576040850162000aec565b6040820152979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c935762000c9362000c67565b92915050565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600063ffffffff80831681810362000cf75762000cf762000c67565b6001019392505050565b600060ff821660ff810362000d1a5762000d1a62000c67565b60010192915050565b60006020808352608080840185516060808588015282825180855260a0890191508684019450600093505b8084101562000da157845180516001600160a01b03908116845288820151168884015260408082015160ff9081169185019190915290840151168383015293860193600193909301929085019062000d4e565b509488015161ffff8116604089015294604089015161ffff811660608a0152955098975050505050505050565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141762000c935762000c9362000c67565b8082018082111562000c935762000c9362000c67565b614b3e8062000e246000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c8063631ec73e116100d8578063979986111161008c578063d927f26711610066578063d927f26714610354578063f2fde38b14610374578063f33f28951461038757600080fd5b8063979986111461030b578063ba86a1f01461031e578063bd147ef41461033157600080fd5b806379ba5097116100bd57806379ba5097146102d35780638da5cb5b146102db578063970b8fc21461030357600080fd5b8063631ec73e146102ad5780636ba0526d146102c057600080fd5b8063397796f71161013a5780634102e4f4116101145780634102e4f4146102745780634d61677114610287578063586abe3c1461029a57600080fd5b8063397796f7146102425780633d0cf6101461024a5780633f42ab731461025d57600080fd5b8063181f5a771161016b578063181f5a77146101ba5780632cbc26bb14610203578063328d716c1461022657600080fd5b80630b009be21461018757806315c65588146101a5575b600080fd5b61018f6103a9565b60405161019c9190613e3f565b60405180910390f35b6101b86101b3366004613fdd565b6103ba565b005b6101f66040518060400160405280600d81526020017f524d4e20312e352e302d6465760000000000000000000000000000000000000081525081565b60405161019c9190614083565b6102166102113660046140f0565b6104e6565b604051901515815260200161019c565b600b5467ffffffffffffffff165b60405190815260200161019c565b6102166105b1565b6101b86102583660046141a0565b61068b565b6102656107ff565b60405161019c939291906142b3565b6101b86102823660046142ff565b610929565b610216610295366004614439565b61093d565b6101b86102a8366004614451565b6109cd565b6101b86102bb3660046144fc565b610a87565b6101b86102ce366004614451565b610ca0565b6101b8610d13565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b600c54610234565b6101b86103193660046145d0565b610e10565b6101b861032c3660046145d0565b611368565b61034461033f3660046140f0565b61150d565b60405161019c9493929190614645565b6103676103623660046146b6565b611946565b60405161019c9190614707565b6101b8610382366004614800565b611b68565b61039a610395366004614439565b611b79565b60405161019c9392919061481b565b60606103b56007611de1565b905090565b336000818152600960205260409020805460ff16610421576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b60045463ffffffff166000805b85518110156104a757600086828151811061044b5761044b614849565b602002602001015190506000610465858360000151611df5565b905060008061047b6001888b8760008d89611fd6565b91509150801561048d5761048d614878565b85806104965750815b95505050505080600101905061042e565b50806104df576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600b5460009067ffffffffffffffff16810361050457506000919050565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806105a657507fffffffffffffffffffffffffffffffff0000000000000000000000000000000082166000908152600a602052604090205468010000000000000000900460ff165b92915050565b919050565b600b5460009067ffffffffffffffff1681036105cd5750600090565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806103b55750507f0100000000000000000000000000000000000000000000000000000000000000600052600a6020527f1d4cd6d2639449a552dbfb463b59316946d78c518b3170daa4a4c217bef019ba5468010000000000000000900460ff1690565b6106936126a4565b60005b8251811015610746576106cc8382815181106106b4576106b4614849565b6020026020010151600761272790919063ffffffff16565b1561073e577fdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b4483828151811061070457610704614849565b6020026020010151604051610735919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b600101610696565b5060005b81518110156107fa5761078082828151811061076857610768614849565b6020026020010151600761274990919063ffffffff16565b156107f2577f66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb158282815181106107b8576107b8614849565b60200260200101516040516107e9919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b60010161074a565b505050565b6040805160608082018352808252600060208084018290528385018290526004548551600280549384028201608090810190985294810183815263ffffffff808416986401000000009094041696959194919385939192859285015b828210156108f95760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161085b565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015292939192919050565b6109316126a4565b61093a8161276b565b50565b600060068161099b610954368690038601866148a7565b80516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b815260208101919091526040016000205460ff16806105a657506105a66109c56020840184614800565b600790612eef565b337fffffffffffffffffffffffff000000000000000000000000000000000000000181016109fd576109fd614878565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260409020805460ff16610a75576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610418565b610a8182858584612f1e565b50505050565b610a8f6126a4565b600454600090819063ffffffff16815b8451811015610b66576000858281518110610abc57610abc614849565b602002602001015190506000610ada84836020015160000151611df5565b9050600080610b3d600087866000015187602001518860400151600960008b6000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002089611fd6565b915091508680610b4a5750815b96508780610b555750805b975050505050806001019050610a9f565b508215610c615760408051600280546080602082028401810190945260608301818152610c61948492849160009085015b82821015610c355760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101610b97565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015261276b565b8180610c6a5750825b610a81576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca86126a4565b73ffffffffffffffffffffffffffffffffffffffff60005260096020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7610a8182858584612f1e565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610418565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e397f01000000000000000000000000000001000000000000000000000000000000006104e6565b15610e70576040517fcde2d97c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454336000908152600560209081526040918290208251606081018452905463ffffffff81811680845260ff64010000000084048116958501959095526501000000000090920490931693820193909352921691908214610f00576040517f85412e7f000000000000000000000000000000000000000000000000000000008152336004820152602401610418565b600160005b8481101561132f576000868683818110610f2157610f21614849565b905060400201803603810190610f3791906148a7565b90506000610f868280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b6000818152600660209081526040918290208251608081018452905460ff81161580158352610100820463ffffffff169383019390935265010000000000810461ffff169382019390935267010000000000000090920478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015291925090611062573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf18560405161105291906148e0565b60405180910390a3505050611327565b8663ffffffff16816020015163ffffffff16146110a8575060408051608081018252600080825263ffffffff89166020830152918101829052606081019190915261110c565b6110ba816060015187604001516136d6565b1561110c573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead8560405161105291906148e0565b6000945061112281606001518760400151613718565b78ffffffffffffffffffffffffffffffffffffffffffffffffff166060820152602086015160408201805160ff9092169161115e90839061493c565b61ffff1690525060208681015160408051865173ffffffffffffffffffffffffffffffffffffffff168152868401519381019390935260ff9091168282015251339163ffffffff8a16917f2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb979181900360600190a3600354604082015161ffff91821691161061125757600181526040808201518151855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015261ffff90911681830152905163ffffffff8916917f8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9919081900360600190a25b60009182526006602090815260409283902082518154928401519484015160609094015178ffffffffffffffffffffffffffffffffffffffffffffffffff166701000000000000000266ffffffffffffff61ffff90951665010000000000029490941664ffffffffff63ffffffff909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090941693909317179390931617179055505b600101610f05565b5080156104df576040517f604c767700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113706126a4565b60045463ffffffff1660005b82811015610a8157600084848381811061139857611398614849565b9050604002018036038101906113ae91906148a7565b905060006113fd8280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b60008181526006602081815260408084208151608081018352815460ff811615158252610100810463ffffffff90811683870190815265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015287875294909352939093558051925193945092878216911614806114945750805b156114fe5760408051855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015282151581830152905163ffffffff8816917f7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba919081900360600190a25b5050505080600101905061137c565b600454604080516002805460806020820284018101909452606083810182815290958695600095869563ffffffff9093169486949193928492918491879085015b828210156115ec5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161154e565b505050908252506001919091015461ffff80821660208085019190915262010000909204166040928301527fffffffffffffffffffffffffffffffff000000000000000000000000000000008a166000908152600a909152908120805460ff6801000000000000000082041696509293509163ffffffff80861691161080156116725750845b6000965090508560015b60028111611939578451515b6000808760000151518310156116e35787518051849081106116ac576116ac614849565b6020026020010151602001519150876000015183815181106116d0576116d0614849565b602002602001015160600151905061170a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060005b73ffffffffffffffffffffffffffffffffffffffff82166000908152600188016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915290878061177a57508a63ffffffff16826000015163ffffffff16145b8061179a575073ffffffffffffffffffffffffffffffffffffffff848116145b80156117b05750602082015163ffffffff191615155b9050801561186d57856001036117d0576117c987614957565b965061186d565b85600203610182576117e560ff84168e61493c565b9c506117f08761498f565b9650838f888151811061180557611805614849565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081602001518e888151811061185657611856614849565b63ffffffff19909216602092830291909101909101525b84156118835761187c8561498f565b945061188c565b50505050611895565b50505050611688565b81600103611928578267ffffffffffffffff8111156118b6576118b6613e52565b6040519080825280602002602001820160405280156118df578160200160208202803683370190505b509a508267ffffffffffffffff8111156118fb576118fb613e52565b604051908082528060200260200182016040528015611924578160200160208202803683370190505b5099505b5061193281614957565b905061167c565b5050505050509193509193565b600c5460609060009061195984866149c4565b11611965575081611988565b600c5484101561198457600c5461197d9085906149d7565b9050611988565b5060005b60008167ffffffffffffffff8111156119a3576119a3613e52565b604051908082528060200260200182016040528015611a2157816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816119c15790505b50905060005b82811015611b5f57600c611a3b82886149c4565b81548110611a4b57611a4b614849565b600091825260209091206040805160c081019091526002909202018054829060ff166004811115611a7e57611a7e6146d8565b6004811115611a8f57611a8f6146d8565b81528154610100810467ffffffffffffffff1660208301526901000000000000000000810460ff16151560408301526a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff166060820152600190910154608081811b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682850152700100000000000000000000000000000000909204901b1660a0909101528251839083908110611b4c57611b4c614849565b6020908102919091010152600101611a27565b50949350505050565b611b706126a4565b61093a8161373b565b606060008080611b91610954368790038701876148a7565b6000818152600660209081526040918290208251608081018452905460ff81161515808352610100820463ffffffff90811694840185905265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff166060830152600454909650939450929091169003611dd85760408101516060820151909450611c3281613830565b60ff1667ffffffffffffffff811115611c4d57611c4d613e52565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b506002805460408051602080840282018101909252828152939950600093929190849084015b82821015611d3a5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101611c9c565b5050505090506000805b82518160ff161015611dd357611d5a84826136d6565b15611dc357828160ff1681518110611d7457611d74614849565b602002602001015160000151898381518110611d9257611d92614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611dc082614957565b91505b611dcc816149ea565b9050611d44565b505050505b50509193909250565b60606000611dee8361389f565b9392505050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166000908152600a60205260408120805463ffffffff858116911614611dee57805463ffffffff19811663ffffffff861690811783556003547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909216176201000090910461ffff1664010000000002177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1680825568010000000000000000900460ff1615611dee57600260005b8154811015611fcd576000826000018281548110611ee657611ee6614849565b6000918252602080832060016002909302018281015473ffffffffffffffffffffffffffffffffffffffff1684529187019052604090912080549192509063ffffffff808a169116108015611f4d57508054640100000000900460201b63ffffffff191615155b15611fc357805463ffffffff191663ffffffff891617815560018201548554750100000000000000000000000000000000000000000090910460ff16908690600690611fa89084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff1602179055505b5050600101611ec6565b50509392505050565b6000806001896001811115611fed57611fed6146d8565b148061200a57506000896001811115612008576120086146d8565b145b61201657612016614878565b8480612037575073ffffffffffffffffffffffffffffffffffffffff878116145b80612056575073ffffffffffffffffffffffffffffffffffffffff8716155b1561207c57600089600181111561206f5761206f6146d8565b1461207c5761207c614878565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260018401602090815260409182902082518084019093525463ffffffff811683526401000000009004811b63ffffffff191690820152845460ff16801561210d575073ffffffffffffffffffffffffffffffffffffffff888116148061210d57508863ffffffff16816000015163ffffffff16145b80156121235750602081015163ffffffff191615155b801561214b5750866020015163ffffffff1916816020015163ffffffff1916148061214b5750855b156122765773ffffffffffffffffffffffffffffffffffffffff881660009081526001858101602052604082209190915585548554919450610100900460ff169085906006906121aa9084906601000000000000900461ffff16614a09565b825461010092830a61ffff818102199092169282160291909117909255895188546020808d01518a54604080517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090961686529590930460ff169184019190915263ffffffff1916828401526601000000000000900490921660608301525173ffffffffffffffffffffffffffffffffffffffff8b16925063ffffffff8c16917fa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8919081900360800190a35b6000808b600181111561228b5761228b6146d8565b1480156122b3575083806122b3575073ffffffffffffffffffffffffffffffffffffffff8916155b90508080156122cf5750845468010000000000000000900460ff165b80156122e157506122df856138fb565b155b156123b45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555600b80546001945060009061232a9067ffffffffffffffff16614a24565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd88600001516040516123ab91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390a15b83806123bd5750825b15612605576000808c60018111156123d7576123d76146d8565b036123f25787156123ea5750600361240f565b50600261240f565b60018c6001811115612406576124066146d8565b03610182575060015b600c6040518060c0016040528083600481111561242e5761242e6146d8565b81526020014267ffffffffffffffff168152885468010000000000000000900460ff16151560208083019190915273ffffffffffffffffffffffffffffffffffffffff8e1660408301528c517fffffffffffffffffffffffffffffffff00000000000000000000000000000000166060830152600060809092018290528354600180820186559483529120825160029092020180549293909283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836004811115612500576125006146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019091015550612696565b8751602080840151818b0151604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909516855263ffffffff1992831693850193909352169082015273ffffffffffffffffffffffffffffffffffffffff8a16907fbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc9060600160405180910390a25b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612725576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610418565b565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff841661395c565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff8416613a56565b61277481613aa5565b6127aa576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b6002541561298e5760028054600091906127f5906001906149d7565b8154811061280557612805614849565b60009182526020808320604080516080810182526002948502909201805473ffffffffffffffffffffffffffffffffffffffff90811680855260019092015480821685870190815260ff740100000000000000000000000000000000000000008304811687870152750100000000000000000000000000000000000000000090920490911660608601529187526005855282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000016905590511685526009909252922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690558054919250908061290457612904614a66565b60008281526020902060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019182020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010180547fffffffffffffffffffff000000000000000000000000000000000000000000001690559055506127d9565b60005b815151811015612ac1578151805160029190839081106129b3576129b3614849565b6020908102919091018101518254600181810185556000948552938390208251600290920201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178155928201519284018054604084015160609094015160ff9081167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9190951674010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009092169590931694909417939093171617905501612991565b5060048054600090612ad89063ffffffff16614a95565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff82161015612c5557600083600001518260ff1681518110612b2457612b24614849565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff908116848801908152898216858701908152875173ffffffffffffffffffffffffffffffffffffffff908116600090815260058b528881209751885494519351861665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169190971617939093179190911693909317909455858701519091168352600990955291902080549190920151909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117600117905550612c4e816149ea565b9050612afc565b5073ffffffffffffffffffffffffffffffffffffffff60005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660011790556004805463ffffffff438116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990612d2f908590614ab8565b60405180910390a26040805160c081018252600480825267ffffffffffffffff421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805493949093909284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921691908490811115612dec57612dec6146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c919091176001909101555050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611dee565b8151600003612f59576040517f55e9b08b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018201602052604090205460ff1615613007576040517f078f340000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166024820152604401610418565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018281016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905560045463ffffffff16905b83518110156136ce57600181101580156130ed575083818151811061309657613096614849565b60200260200101516fffffffffffffffffffffffffffffffff1916846001836130bf91906149d7565b815181106130cf576130cf614849565b60200260200101516fffffffffffffffffffffffffffffffff191610155b15613124576040517f2432d8ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084828151811061313857613138614849565b60200260200101519050600061314e8483611df5565b73ffffffffffffffffffffffffffffffffffffffff8981166000818152600184016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915293945091148015906131be5750815163ffffffff8088169116105b806131d25750602082015163ffffffff1916155b15613225575085548254600091610100900460ff169084906006906132069084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff16021790555061322c565b5060208101515b60408051808201825263ffffffff88168152815163ffffffff1984166020828101919091527fffffffffffffffffffffffffffffffff000000000000000000000000000000008d16828501528351808303850181526060909201909352805190830120909182019063ffffffff1916905273ffffffffffffffffffffffffffffffffffffffff8b166000818152600186016020908152604090912083518285015190921c6401000000000263ffffffff92831617905589549294509091908816907f8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a9087908d9060ff610100909104166133234290565b6020898101518b54604080517fffffffffffffffffffffffffffffffff000000000000000000000000000000009889168152979096169287019290925260ff9093169385019390935267ffffffffffffffff16606084015263ffffffff191660808301526601000000000000900461ffff1660a082015260c00160405180910390a363ffffffff1981161580156133c85750825468010000000000000000900460ff16155b80156133d857506133d8836138fb565b156134c35782547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000178355600b80546000906134289067ffffffffffffffff16614acb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508563ffffffff167fcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde8561347e4290565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316835267ffffffffffffffff90911660208301520160405180910390a25b6040805160c081018252600080825267ffffffffffffffff42166020830152855460ff680100000000000000009091041615159282019290925273ffffffffffffffffffffffffffffffffffffffff8c1660608201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000086811660808301528b1660a0820152600c80546001808201835591909352815160029093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805492939092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908360048111156135c0576135c06146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019182015594909401935061306f92505050565b505050505050565b600060108260ff16106136eb576136eb614878565b50600160ff82161b821678ffffffffffffffffffffffffffffffffffffffffffffffffff16151592915050565b600060108260ff161061372d5761372d614878565b50600160ff919091161b1790565b3373ffffffffffffffffffffffffffffffffffffffff8216036137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610418565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006201000078ffffffffffffffffffffffffffffffffffffffffffffffffff83161061385f5761385f614878565b78ffffffffffffffffffffffffffffffffffffffffffffffffff8216156105ac5761388b600183614ae8565b90911690613898816149ea565b905061385f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156138ef57602002820191906000526020600020905b8154815260200190600101908083116138db575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff600090815260018201602090815260408220546401000000009004901b63ffffffff19161515806105a65750505461ffff64010000000082048116660100000000000090920416101590565b60008181526001830160205260408120548015613a455760006139806001836149d7565b8554909150600090613994906001906149d7565b90508181146139f95760008660000182815481106139b4576139b4614849565b90600052602060002001549050808760000184815481106139d7576139d7614849565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613a0a57613a0a614a66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105a6565b60009150506105a6565b5092915050565b6000818152600183016020526040812054613a9d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105a6565b5060006105a6565b8051516000901580613ab957508151516010105b80613aca5750602082015161ffff16155b80613adb5750604082015161ffff16155b15613ae857506000919050565b60008060008460000151516002613aff9190614b1a565b67ffffffffffffffff811115613b1757613b17613e52565b604051908082528060200260200182016040528015613b40578160200160208202803683370190505b50905060005b855151811015613d1157600086600001518281518110613b6857613b68614849565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480613bc95750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613bec5750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613c115750602081015173ffffffffffffffffffffffffffffffffffffffff908116145b80613c315750604081015160ff16158015613c315750606081015160ff16155b15613c43575060009695505050505050565b805183613c51846002614b1a565b613c5c9060006149c4565b81518110613c6c57613c6c614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015281015183613c9f846002614b1a565b613caa9060016149c4565b81518110613cba57613cba614849565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040810151613cf19060ff16866149c4565b9450806060015160ff1684613d0691906149c4565b935050600101613b46565b5060005b8151811015613dc3576000828281518110613d3257613d32614849565b602002602001015190506000826001613d4b91906149c4565b90505b8351811015613db957838181518110613d6957613d69614849565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613db157506000979650505050505050565b600101613d4e565b5050600101613d15565b50846020015161ffff168310158015613de45750846040015161ffff168210155b95945050505050565b60008151808452602080850194506020840160005b83811015613e3457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e02565b509495945050505050565b602081526000611dee6020830184613ded565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613ea457613ea4613e52565b60405290565b6040516060810167ffffffffffffffff81118282101715613ea457613ea4613e52565b6040516080810167ffffffffffffffff81118282101715613ea457613ea4613e52565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f3757613f37613e52565b604052919050565b600067ffffffffffffffff821115613f5957613f59613e52565b5060051b60200190565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146105ac57600080fd5b600060408284031215613fa557600080fd5b613fad613e81565b9050613fb882613f63565b8152602082013563ffffffff1981168114613fd257600080fd5b602082015292915050565b60006020808385031215613ff057600080fd5b823567ffffffffffffffff81111561400757600080fd5b8301601f8101851361401857600080fd5b803561402b61402682613f3f565b613ef0565b8082825260208201915060208360061b85010192508783111561404d57600080fd5b6020840193505b82841015614078576140668885613f93565b82528482019150604084019350614054565b979650505050505050565b60006020808352835180602085015260005b818110156140b157858101830151858201604001528201614095565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561410257600080fd5b611dee82613f63565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ac57600080fd5b600082601f83011261414057600080fd5b8135602061415061402683613f3f565b8083825260208201915060208460051b87010193508684111561417257600080fd5b602086015b84811015614195576141888161410b565b8352918301918301614177565b509695505050505050565b600080604083850312156141b357600080fd5b823567ffffffffffffffff808211156141cb57600080fd5b6141d78683870161412f565b935060208501359150808211156141ed57600080fd5b506141fa8582860161412f565b9150509250929050565b8051606080845281518482018190526000926080916020918201918388019190865b82811015614280578451805173ffffffffffffffffffffffffffffffffffffffff908116865283820151168386015260408082015160ff908116918701919091529088015116878501529381019392850192600101614226565b508781015161ffff81168a83015295505050604086015193506142a9604088018561ffff169052565b9695505050505050565b600063ffffffff808616835280851660208401525060606040830152613de46060830184614204565b803560ff811681146105ac57600080fd5b803561ffff811681146105ac57600080fd5b6000602080838503121561431257600080fd5b823567ffffffffffffffff8082111561432a57600080fd5b8185019150606080838803121561434057600080fd5b614348613eaa565b83358381111561435757600080fd5b84019250601f8301881361436a57600080fd5b823561437861402682613f3f565b81815260079190911b8401860190868101908a83111561439757600080fd5b948701945b82861015614409576080868c0312156143b55760008081fd5b6143bd613ecd565b6143c68761410b565b81526143d389880161410b565b8982015260406143e48189016142dc565b908201526143f38787016142dc565b818701528252608095909501949087019061439c565b83525061441990508486016142ed565b85820152614429604085016142ed565b6040820152979650505050505050565b60006040828403121561444b57600080fd5b50919050565b6000806040838503121561446457600080fd5b61446d83613f63565b915060208084013567ffffffffffffffff81111561448a57600080fd5b8401601f8101861361449b57600080fd5b80356144a961402682613f3f565b81815260059190911b820183019083810190888311156144c857600080fd5b928401925b828410156144ed576144de84613f63565b825292840192908401906144cd565b80955050505050509250929050565b6000602080838503121561450f57600080fd5b823567ffffffffffffffff81111561452657600080fd5b8301601f8101851361453757600080fd5b803561454561402682613f3f565b81815260079190911b8201830190838101908783111561456457600080fd5b928401925b8284101561407857608084890312156145825760008081fd5b61458a613eaa565b6145938561410b565b81526145a189878701613f93565b86820152606085013580151581146145b95760008081fd5b604082015282526080939093019290840190614569565b600080602083850312156145e357600080fd5b823567ffffffffffffffff808211156145fb57600080fd5b818501915085601f83011261460f57600080fd5b81358181111561461e57600080fd5b8660208260061b850101111561463357600080fd5b60209290920196919550909350505050565b6080815260006146586080830187613ded565b82810360208481019190915286518083528782019282019060005b8181101561469657845163ffffffff191683529383019391830191600101614673565b505061ffff96909616604085015250505090151560609091015292915050565b600080604083850312156146c957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156147f2578251805160058110614766577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015167ffffffffffffffff16888701528681015115158787015260608082015173ffffffffffffffffffffffffffffffffffffffff16908701526080808201517fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169188019190915260a091820151169086015260c09094019391860191600101614725565b509298975050505050505050565b60006020828403121561481257600080fd5b611dee8261410b565b60608152600061482e6060830186613ded565b61ffff94909416602083015250901515604090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000604082840312156148b957600080fd5b6148c1613e81565b6148ca8361410b565b8152602083013560208201528091505092915050565b815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604081016105a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff818116838216019080821115613a4f57613a4f61490d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149885761498861490d565b5060010190565b60008161499e5761499e61490d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b808201808211156105a6576105a661490d565b818103818111156105a6576105a661490d565b600060ff821660ff8103614a0057614a0061490d565b60010192915050565b61ffff828116828216039080821115613a4f57613a4f61490d565b600067ffffffffffffffff821680614a3e57614a3e61490d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff808316818103614aae57614aae61490d565b6001019392505050565b602081526000611dee6020830184614204565b600067ffffffffffffffff808316818103614aae57614aae61490d565b78ffffffffffffffffffffffffffffffffffffffffffffffffff828116828216039080821115613a4f57613a4f61490d565b80820281158282048414176105a6576105a661490d56fea164736f6c6343000818000a", + Bin: "0x60806040523480156200001157600080fd5b506040516200596238038062005962833981016040819052620000349162000aff565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000138565b505060408051608081018252600080825260208201819052918101919091526001600160c81b03606082015290506001620000fb81601062000c7d565b82606001516001600160c81b0316901c6001600160c81b0316101562000125576200012562000c99565b506200013181620001e3565b5062000e14565b336001600160a01b03821603620001925760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620001ee816200071d565b6200020c576040516306b7c75960e31b815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b60025415620003465760028054600091906200025a9060019062000c7d565b815481106200026d576200026d62000caf565b6000918252602080832060408051608081018252600294850290920180546001600160a01b0390811680855260019092015480821685870190815260ff600160a01b8304811687870152600160a81b909204909116606086015291875260058552828720805465ffffffffffff19169055905116855260099092529220805461ffff191690558054919250908062000309576200030962000cc5565b60008281526020902060026000199092019182020180546001600160a01b031916815560010180546001600160b01b03191690559055506200023b565b60005b81515181101562000403578151805160029190839081106200036f576200036f62000caf565b602090810291909101810151825460018181018555600094855293839020825160029092020180546001600160a01b039283166001600160a01b0319909116178155928201519284018054604084015160609094015160ff908116600160a81b0260ff60a81b1991909516600160a01b026001600160a81b0319909216959093169490941793909317161790550162000349565b50600480546000906200041c9063ffffffff1662000cdb565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff821610156200054157600083600001518260ff16815181106200046c576200046c62000caf565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff90811684880190815289821685870190815287516001600160a01b03908116600090815260058b5288812097518854945193518616650100000000000260ff60281b199487166401000000000264ffffffffff1990961691909716179390931791909116939093179094558587015190911683526009909552919020805491909201519092166101000261ffff1990921691909117600117905550620005398162000d01565b905062000440565b506001600160a01b0360005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7805461ffff191660011790556004805463ffffffff4381166401000000000263ffffffff60201b1990921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990620005db90859062000d23565b60405180910390a26040805160c08101825260048082526001600160401b03421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7018054939490939092849260ff19909216919084908111156200067c576200067c62000dce565b021790555060208201518154604084015160608501516001600160a01b03166a010000000000000000000002600160501b600160f01b031991151569010000000000000000000260ff60481b196001600160401b039095166101000294909416610100600160501b031990931692909217929092179190911617815560808083015160a090930151811c600160801b0292901c919091176001909101555050565b80515160009015806200073257508151516010105b80620007445750602082015161ffff16155b80620007565750604082015161ffff16155b156200076457506000919050565b600080600084600001515160026200077d919062000de4565b6001600160401b0381111562000797576200079762000a24565b604051908082528060200260200182016040528015620007c1578160200160208202803683370190505b50905060005b8551518110156200095457600086600001518281518110620007ed57620007ed62000caf565b6020026020010151905060006001600160a01b031681600001516001600160a01b0316148062000828575060208101516001600160a01b0316155b806200083f575060208101516001600160a01b0316155b8062000858575060208101516001600160a01b03908116145b806200087a5750604081015160ff161580156200087a5750606081015160ff16155b156200088d575060009695505050505050565b8051836200089d84600262000de4565b620008aa90600062000dfe565b81518110620008bd57620008bd62000caf565b6001600160a01b0390921660209283029190910182015281015183620008e584600262000de4565b620008f290600162000dfe565b8151811062000905576200090562000caf565b6001600160a01b03909216602092830291909101909101526040810151620009319060ff168662000dfe565b9450806060015160ff168462000948919062000dfe565b935050600101620007c7565b5060005b8151811015620009f957600082828151811062000979576200097962000caf565b60200260200101519050600082600162000994919062000dfe565b90505b8351811015620009ee57838181518110620009b657620009b662000caf565b60200260200101516001600160a01b0316826001600160a01b031603620009e557506000979650505050505050565b60010162000997565b505060010162000958565b50846020015161ffff16831015801562000a1b5750846040015161ffff168210155b95945050505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000a5f5762000a5f62000a24565b60405290565b604051608081016001600160401b038111828210171562000a5f5762000a5f62000a24565b604051601f8201601f191681016001600160401b038111828210171562000ab55762000ab562000a24565b604052919050565b80516001600160a01b038116811462000ad557600080fd5b919050565b805160ff8116811462000ad557600080fd5b805161ffff8116811462000ad557600080fd5b6000602080838503121562000b1357600080fd5b82516001600160401b038082111562000b2b57600080fd5b8185019150606080838803121562000b4257600080fd5b62000b4c62000a3a565b83518381111562000b5c57600080fd5b8401601f8101891362000b6e57600080fd5b80518481111562000b835762000b8362000a24565b62000b93878260051b0162000a8a565b818152878101955060079190911b82018701908a82111562000bb457600080fd5b918701915b8183101562000c33576080838c03121562000bd45760008081fd5b62000bde62000a65565b62000be98462000abd565b815262000bf889850162000abd565b89820152604062000c0b81860162000ada565b9082015262000c1c84870162000ada565b818701528652948701946080929092019162000bb9565b83525062000c45905084860162000aec565b8582015262000c576040850162000aec565b6040820152979650505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c935762000c9362000c67565b92915050565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600063ffffffff80831681810362000cf75762000cf762000c67565b6001019392505050565b600060ff821660ff810362000d1a5762000d1a62000c67565b60010192915050565b60006020808352608080840185516060808588015282825180855260a0890191508684019450600093505b8084101562000da157845180516001600160a01b03908116845288820151168884015260408082015160ff9081169185019190915290840151168383015293860193600193909301929085019062000d4e565b509488015161ffff8116604089015294604089015161ffff811660608a0152955098975050505050505050565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141762000c935762000c9362000c67565b8082018082111562000c935762000c9362000c67565b614b3e8062000e246000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c8063631ec73e116100d8578063979986111161008c578063d927f26711610066578063d927f26714610354578063f2fde38b14610374578063f33f28951461038757600080fd5b8063979986111461030b578063ba86a1f01461031e578063bd147ef41461033157600080fd5b806379ba5097116100bd57806379ba5097146102d35780638da5cb5b146102db578063970b8fc21461030357600080fd5b8063631ec73e146102ad5780636ba0526d146102c057600080fd5b8063397796f71161013a5780634102e4f4116101145780634102e4f4146102745780634d61677114610287578063586abe3c1461029a57600080fd5b8063397796f7146102425780633d0cf6101461024a5780633f42ab731461025d57600080fd5b8063181f5a771161016b578063181f5a77146101ba5780632cbc26bb14610203578063328d716c1461022657600080fd5b80630b009be21461018757806315c65588146101a5575b600080fd5b61018f6103a9565b60405161019c9190613e3f565b60405180910390f35b6101b86101b3366004613fdd565b6103ba565b005b6101f66040518060400160405280600981526020017f524d4e20312e352e30000000000000000000000000000000000000000000000081525081565b60405161019c9190614083565b6102166102113660046140f0565b6104e6565b604051901515815260200161019c565b600b5467ffffffffffffffff165b60405190815260200161019c565b6102166105b1565b6101b86102583660046141a0565b61068b565b6102656107ff565b60405161019c939291906142b3565b6101b86102823660046142ff565b610929565b610216610295366004614439565b61093d565b6101b86102a8366004614451565b6109cd565b6101b86102bb3660046144fc565b610a87565b6101b86102ce366004614451565b610ca0565b6101b8610d13565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019c565b600c54610234565b6101b86103193660046145d0565b610e10565b6101b861032c3660046145d0565b611368565b61034461033f3660046140f0565b61150d565b60405161019c9493929190614645565b6103676103623660046146b6565b611946565b60405161019c9190614707565b6101b8610382366004614800565b611b68565b61039a610395366004614439565b611b79565b60405161019c9392919061481b565b60606103b56007611de1565b905090565b336000818152600960205260409020805460ff16610421576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b60045463ffffffff166000805b85518110156104a757600086828151811061044b5761044b614849565b602002602001015190506000610465858360000151611df5565b905060008061047b6001888b8760008d89611fd6565b91509150801561048d5761048d614878565b85806104965750815b95505050505080600101905061042e565b50806104df576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600b5460009067ffffffffffffffff16810361050457506000919050565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806105a657507fffffffffffffffffffffffffffffffff0000000000000000000000000000000082166000908152600a602052604090205468010000000000000000900460ff165b92915050565b919050565b600b5460009067ffffffffffffffff1681036105cd5750600090565b7f0100000000000000000000000000000100000000000000000000000000000000600052600a6020527fcf943f0e419056430919a3fdfd72276bc0b123ebdd670f4152b82bffbfb8bb385468010000000000000000900460ff16806103b55750507f0100000000000000000000000000000000000000000000000000000000000000600052600a6020527f1d4cd6d2639449a552dbfb463b59316946d78c518b3170daa4a4c217bef019ba5468010000000000000000900460ff1690565b6106936126a4565b60005b8251811015610746576106cc8382815181106106b4576106b4614849565b6020026020010151600761272790919063ffffffff16565b1561073e577fdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b4483828151811061070457610704614849565b6020026020010151604051610735919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b600101610696565b5060005b81518110156107fa5761078082828151811061076857610768614849565b6020026020010151600761274990919063ffffffff16565b156107f2577f66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb158282815181106107b8576107b8614849565b60200260200101516040516107e9919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a15b60010161074a565b505050565b6040805160608082018352808252600060208084018290528385018290526004548551600280549384028201608090810190985294810183815263ffffffff808416986401000000009094041696959194919385939192859285015b828210156108f95760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161085b565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015292939192919050565b6109316126a4565b61093a8161276b565b50565b600060068161099b610954368690038601866148a7565b80516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b815260208101919091526040016000205460ff16806105a657506105a66109c56020840184614800565b600790612eef565b337fffffffffffffffffffffffff000000000000000000000000000000000000000181016109fd576109fd614878565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260409020805460ff16610a75576040517f85412e7f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610418565b610a8182858584612f1e565b50505050565b610a8f6126a4565b600454600090819063ffffffff16815b8451811015610b66576000858281518110610abc57610abc614849565b602002602001015190506000610ada84836020015160000151611df5565b9050600080610b3d600087866000015187602001518860400151600960008b6000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002089611fd6565b915091508680610b4a5750815b96508780610b555750805b975050505050806001019050610a9f565b508215610c615760408051600280546080602082028401810190945260608301818152610c61948492849160009085015b82821015610c355760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101610b97565b505050908252506001919091015461ffff8082166020840152620100009091041660409091015261276b565b8180610c6a5750825b610a81576040517ffb106b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca86126a4565b73ffffffffffffffffffffffffffffffffffffffff60005260096020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a7610a8182858584612f1e565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610418565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e397f01000000000000000000000000000001000000000000000000000000000000006104e6565b15610e70576040517fcde2d97c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454336000908152600560209081526040918290208251606081018452905463ffffffff81811680845260ff64010000000084048116958501959095526501000000000090920490931693820193909352921691908214610f00576040517f85412e7f000000000000000000000000000000000000000000000000000000008152336004820152602401610418565b600160005b8481101561132f576000868683818110610f2157610f21614849565b905060400201803603810190610f3791906148a7565b90506000610f868280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b6000818152600660209081526040918290208251608081018452905460ff81161580158352610100820463ffffffff169383019390935265010000000000810461ffff169382019390935267010000000000000090920478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015291925090611062573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf18560405161105291906148e0565b60405180910390a3505050611327565b8663ffffffff16816020015163ffffffff16146110a8575060408051608081018252600080825263ffffffff89166020830152918101829052606081019190915261110c565b6110ba816060015187604001516136d6565b1561110c573373ffffffffffffffffffffffffffffffffffffffff168763ffffffff167f6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead8560405161105291906148e0565b6000945061112281606001518760400151613718565b78ffffffffffffffffffffffffffffffffffffffffffffffffff166060820152602086015160408201805160ff9092169161115e90839061493c565b61ffff1690525060208681015160408051865173ffffffffffffffffffffffffffffffffffffffff168152868401519381019390935260ff9091168282015251339163ffffffff8a16917f2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb979181900360600190a3600354604082015161ffff91821691161061125757600181526040808201518151855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015261ffff90911681830152905163ffffffff8916917f8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9919081900360600190a25b60009182526006602090815260409283902082518154928401519484015160609094015178ffffffffffffffffffffffffffffffffffffffffffffffffff166701000000000000000266ffffffffffffff61ffff90951665010000000000029490941664ffffffffff63ffffffff909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090941693909317179390931617179055505b600101610f05565b5080156104df576040517f604c767700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113706126a4565b60045463ffffffff1660005b82811015610a8157600084848381811061139857611398614849565b9050604002018036038101906113ae91906148a7565b905060006113fd8280516020918201516040805173ffffffffffffffffffffffffffffffffffffffff909316838501528281019190915280518083038201815260609092019052805191012090565b60008181526006602081815260408084208151608081018352815460ff811615158252610100810463ffffffff90811683870190815265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff16606083015287875294909352939093558051925193945092878216911614806114945750805b156114fe5760408051855173ffffffffffffffffffffffffffffffffffffffff1681526020808701519082015282151581830152905163ffffffff8816917f7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba919081900360600190a25b5050505080600101905061137c565b600454604080516002805460806020820284018101909452606083810182815290958695600095869563ffffffff9093169486949193928492918491879085015b828210156115ec5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff740100000000000000000000000000000000000000008204811693850193909352750100000000000000000000000000000000000000000090049091166060830152908352909201910161154e565b505050908252506001919091015461ffff80821660208085019190915262010000909204166040928301527fffffffffffffffffffffffffffffffff000000000000000000000000000000008a166000908152600a909152908120805460ff6801000000000000000082041696509293509163ffffffff80861691161080156116725750845b6000965090508560015b60028111611939578451515b6000808760000151518310156116e35787518051849081106116ac576116ac614849565b6020026020010151602001519150876000015183815181106116d0576116d0614849565b602002602001015160600151905061170a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060005b73ffffffffffffffffffffffffffffffffffffffff82166000908152600188016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915290878061177a57508a63ffffffff16826000015163ffffffff16145b8061179a575073ffffffffffffffffffffffffffffffffffffffff848116145b80156117b05750602082015163ffffffff191615155b9050801561186d57856001036117d0576117c987614957565b965061186d565b85600203610182576117e560ff84168e61493c565b9c506117f08761498f565b9650838f888151811061180557611805614849565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505081602001518e888151811061185657611856614849565b63ffffffff19909216602092830291909101909101525b84156118835761187c8561498f565b945061188c565b50505050611895565b50505050611688565b81600103611928578267ffffffffffffffff8111156118b6576118b6613e52565b6040519080825280602002602001820160405280156118df578160200160208202803683370190505b509a508267ffffffffffffffff8111156118fb576118fb613e52565b604051908082528060200260200182016040528015611924578160200160208202803683370190505b5099505b5061193281614957565b905061167c565b5050505050509193509193565b600c5460609060009061195984866149c4565b11611965575081611988565b600c5484101561198457600c5461197d9085906149d7565b9050611988565b5060005b60008167ffffffffffffffff8111156119a3576119a3613e52565b604051908082528060200260200182016040528015611a2157816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816119c15790505b50905060005b82811015611b5f57600c611a3b82886149c4565b81548110611a4b57611a4b614849565b600091825260209091206040805160c081019091526002909202018054829060ff166004811115611a7e57611a7e6146d8565b6004811115611a8f57611a8f6146d8565b81528154610100810467ffffffffffffffff1660208301526901000000000000000000810460ff16151560408301526a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff166060820152600190910154608081811b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090811682850152700100000000000000000000000000000000909204901b1660a0909101528251839083908110611b4c57611b4c614849565b6020908102919091010152600101611a27565b50949350505050565b611b706126a4565b61093a8161373b565b606060008080611b91610954368790038701876148a7565b6000818152600660209081526040918290208251608081018452905460ff81161515808352610100820463ffffffff90811694840185905265010000000000830461ffff169584019590955267010000000000000090910478ffffffffffffffffffffffffffffffffffffffffffffffffff166060830152600454909650939450929091169003611dd85760408101516060820151909450611c3281613830565b60ff1667ffffffffffffffff811115611c4d57611c4d613e52565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b506002805460408051602080840282018101909252828152939950600093929190849084015b82821015611d3a5760008481526020908190206040805160808101825260028602909201805473ffffffffffffffffffffffffffffffffffffffff90811684526001918201549081168486015260ff7401000000000000000000000000000000000000000082048116938501939093527501000000000000000000000000000000000000000000900490911660608301529083529092019101611c9c565b5050505090506000805b82518160ff161015611dd357611d5a84826136d6565b15611dc357828160ff1681518110611d7457611d74614849565b602002602001015160000151898381518110611d9257611d92614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152611dc082614957565b91505b611dcc816149ea565b9050611d44565b505050505b50509193909250565b60606000611dee8361389f565b9392505050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166000908152600a60205260408120805463ffffffff858116911614611dee57805463ffffffff19811663ffffffff861690811783556003547fffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000909216176201000090910461ffff1664010000000002177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1680825568010000000000000000900460ff1615611dee57600260005b8154811015611fcd576000826000018281548110611ee657611ee6614849565b6000918252602080832060016002909302018281015473ffffffffffffffffffffffffffffffffffffffff1684529187019052604090912080549192509063ffffffff808a169116108015611f4d57508054640100000000900460201b63ffffffff191615155b15611fc357805463ffffffff191663ffffffff891617815560018201548554750100000000000000000000000000000000000000000090910460ff16908690600690611fa89084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff1602179055505b5050600101611ec6565b50509392505050565b6000806001896001811115611fed57611fed6146d8565b148061200a57506000896001811115612008576120086146d8565b145b61201657612016614878565b8480612037575073ffffffffffffffffffffffffffffffffffffffff878116145b80612056575073ffffffffffffffffffffffffffffffffffffffff8716155b1561207c57600089600181111561206f5761206f6146d8565b1461207c5761207c614878565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260018401602090815260409182902082518084019093525463ffffffff811683526401000000009004811b63ffffffff191690820152845460ff16801561210d575073ffffffffffffffffffffffffffffffffffffffff888116148061210d57508863ffffffff16816000015163ffffffff16145b80156121235750602081015163ffffffff191615155b801561214b5750866020015163ffffffff1916816020015163ffffffff1916148061214b5750855b156122765773ffffffffffffffffffffffffffffffffffffffff881660009081526001858101602052604082209190915585548554919450610100900460ff169085906006906121aa9084906601000000000000900461ffff16614a09565b825461010092830a61ffff818102199092169282160291909117909255895188546020808d01518a54604080517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090961686529590930460ff169184019190915263ffffffff1916828401526601000000000000900490921660608301525173ffffffffffffffffffffffffffffffffffffffff8b16925063ffffffff8c16917fa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8919081900360800190a35b6000808b600181111561228b5761228b6146d8565b1480156122b3575083806122b3575073ffffffffffffffffffffffffffffffffffffffff8916155b90508080156122cf5750845468010000000000000000900460ff165b80156122e157506122df856138fb565b155b156123b45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555600b80546001945060009061232a9067ffffffffffffffff16614a24565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd88600001516040516123ab91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390a15b83806123bd5750825b15612605576000808c60018111156123d7576123d76146d8565b036123f25787156123ea5750600361240f565b50600261240f565b60018c6001811115612406576124066146d8565b03610182575060015b600c6040518060c0016040528083600481111561242e5761242e6146d8565b81526020014267ffffffffffffffff168152885468010000000000000000900460ff16151560208083019190915273ffffffffffffffffffffffffffffffffffffffff8e1660408301528c517fffffffffffffffffffffffffffffffff00000000000000000000000000000000166060830152600060809092018290528354600180820186559483529120825160029092020180549293909283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836004811115612500576125006146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019091015550612696565b8751602080840151818b0151604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909516855263ffffffff1992831693850193909352169082015273ffffffffffffffffffffffffffffffffffffffff8a16907fbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc9060600160405180910390a25b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612725576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610418565b565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff841661395c565b6000611dee8373ffffffffffffffffffffffffffffffffffffffff8416613a56565b61277481613aa5565b6127aa576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160038054604084015161ffff908116620100000263ffffffff199092169316929092179190911790555b6002541561298e5760028054600091906127f5906001906149d7565b8154811061280557612805614849565b60009182526020808320604080516080810182526002948502909201805473ffffffffffffffffffffffffffffffffffffffff90811680855260019092015480821685870190815260ff740100000000000000000000000000000000000000008304811687870152750100000000000000000000000000000000000000000090920490911660608601529187526005855282872080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000016905590511685526009909252922080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690558054919250908061290457612904614a66565b60008281526020902060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019182020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010180547fffffffffffffffffffff000000000000000000000000000000000000000000001690559055506127d9565b60005b815151811015612ac1578151805160029190839081106129b3576129b3614849565b6020908102919091018101518254600181810185556000948552938390208251600290920201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178155928201519284018054604084015160609094015160ff9081167501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9190951674010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009092169590931694909417939093171617905501612991565b5060048054600090612ad89063ffffffff16614a95565b82546101009290920a63ffffffff8181021990931691831602179091556004541660005b82515160ff82161015612c5557600083600001518260ff1681518110612b2457612b24614849565b602090810291909101810151604080516060808201835263ffffffff80891683528385015160ff908116848801908152898216858701908152875173ffffffffffffffffffffffffffffffffffffffff908116600090815260058b528881209751885494519351861665010000000000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff948716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169190971617939093179190911693909317909455858701519091168352600990955291902080549190920151909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117600117905550612c4e816149ea565b9050612afc565b5073ffffffffffffffffffffffffffffffffffffffff60005260096020527f3bddde647ecb7992f4c710d4e1d59d07614508581f7c22c879a79d28544538a780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660011790556004805463ffffffff438116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117909155604051908216907f8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a990612d2f908590614ab8565b60405180910390a26040805160c081018252600480825267ffffffffffffffff421660208301526000928201839052606082018390526080820183905260a08201839052600c80546001808201835591909452825160029094027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805493949093909284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921691908490811115612dec57612dec6146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c919091176001909101555050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611dee565b8151600003612f59576040517f55e9b08b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018201602052604090205460ff1615613007576040517f078f340000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166024820152604401610418565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008316600090815260018281016020526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905560045463ffffffff16905b83518110156136ce57600181101580156130ed575083818151811061309657613096614849565b60200260200101516fffffffffffffffffffffffffffffffff1916846001836130bf91906149d7565b815181106130cf576130cf614849565b60200260200101516fffffffffffffffffffffffffffffffff191610155b15613124576040517f2432d8ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084828151811061313857613138614849565b60200260200101519050600061314e8483611df5565b73ffffffffffffffffffffffffffffffffffffffff8981166000818152600184016020908152604080832081518083019092525463ffffffff811682526401000000009004821b63ffffffff19169181019190915293945091148015906131be5750815163ffffffff8088169116105b806131d25750602082015163ffffffff1916155b15613225575085548254600091610100900460ff169084906006906132069084906601000000000000900461ffff1661493c565b92506101000a81548161ffff021916908361ffff16021790555061322c565b5060208101515b60408051808201825263ffffffff88168152815163ffffffff1984166020828101919091527fffffffffffffffffffffffffffffffff000000000000000000000000000000008d16828501528351808303850181526060909201909352805190830120909182019063ffffffff1916905273ffffffffffffffffffffffffffffffffffffffff8b166000818152600186016020908152604090912083518285015190921c6401000000000263ffffffff92831617905589549294509091908816907f8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a9087908d9060ff610100909104166133234290565b6020898101518b54604080517fffffffffffffffffffffffffffffffff000000000000000000000000000000009889168152979096169287019290925260ff9093169385019390935267ffffffffffffffff16606084015263ffffffff191660808301526601000000000000900461ffff1660a082015260c00160405180910390a363ffffffff1981161580156133c85750825468010000000000000000900460ff16155b80156133d857506133d8836138fb565b156134c35782547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000178355600b80546000906134289067ffffffffffffffff16614acb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508563ffffffff167fcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde8561347e4290565b604080517fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316835267ffffffffffffffff90911660208301520160405180910390a25b6040805160c081018252600080825267ffffffffffffffff42166020830152855460ff680100000000000000009091041615159282019290925273ffffffffffffffffffffffffffffffffffffffff8c1660608201527fffffffffffffffffffffffffffffffff0000000000000000000000000000000086811660808301528b1660a0820152600c80546001808201835591909352815160029093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805492939092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908360048111156135c0576135c06146d8565b0217905550602082015181546040840151606085015173ffffffffffffffffffffffffffffffffffffffff166a0100000000000000000000027fffff0000000000000000000000000000000000000000ffffffffffffffffffff9115156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff67ffffffffffffffff90951661010002949094167fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90931692909217929092179190911617815560808083015160a090930151811c7001000000000000000000000000000000000292901c9190911760019182015594909401935061306f92505050565b505050505050565b600060108260ff16106136eb576136eb614878565b50600160ff82161b821678ffffffffffffffffffffffffffffffffffffffffffffffffff16151592915050565b600060108260ff161061372d5761372d614878565b50600160ff919091161b1790565b3373ffffffffffffffffffffffffffffffffffffffff8216036137ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610418565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006201000078ffffffffffffffffffffffffffffffffffffffffffffffffff83161061385f5761385f614878565b78ffffffffffffffffffffffffffffffffffffffffffffffffff8216156105ac5761388b600183614ae8565b90911690613898816149ea565b905061385f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156138ef57602002820191906000526020600020905b8154815260200190600101908083116138db575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff600090815260018201602090815260408220546401000000009004901b63ffffffff19161515806105a65750505461ffff64010000000082048116660100000000000090920416101590565b60008181526001830160205260408120548015613a455760006139806001836149d7565b8554909150600090613994906001906149d7565b90508082146139f95760008660000182815481106139b4576139b4614849565b90600052602060002001549050808760000184815481106139d7576139d7614849565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613a0a57613a0a614a66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105a6565b60009150506105a6565b5092915050565b6000818152600183016020526040812054613a9d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105a6565b5060006105a6565b8051516000901580613ab957508151516010105b80613aca5750602082015161ffff16155b80613adb5750604082015161ffff16155b15613ae857506000919050565b60008060008460000151516002613aff9190614b1a565b67ffffffffffffffff811115613b1757613b17613e52565b604051908082528060200260200182016040528015613b40578160200160208202803683370190505b50905060005b855151811015613d1157600086600001518281518110613b6857613b68614849565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480613bc95750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613bec5750602081015173ffffffffffffffffffffffffffffffffffffffff16155b80613c115750602081015173ffffffffffffffffffffffffffffffffffffffff908116145b80613c315750604081015160ff16158015613c315750606081015160ff16155b15613c43575060009695505050505050565b805183613c51846002614b1a565b613c5c9060006149c4565b81518110613c6c57613c6c614849565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015281015183613c9f846002614b1a565b613caa9060016149c4565b81518110613cba57613cba614849565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526040810151613cf19060ff16866149c4565b9450806060015160ff1684613d0691906149c4565b935050600101613b46565b5060005b8151811015613dc3576000828281518110613d3257613d32614849565b602002602001015190506000826001613d4b91906149c4565b90505b8351811015613db957838181518110613d6957613d69614849565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613db157506000979650505050505050565b600101613d4e565b5050600101613d15565b50846020015161ffff168310158015613de45750846040015161ffff168210155b95945050505050565b60008151808452602080850194506020840160005b83811015613e3457815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613e02565b509495945050505050565b602081526000611dee6020830184613ded565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613ea457613ea4613e52565b60405290565b6040516060810167ffffffffffffffff81118282101715613ea457613ea4613e52565b6040516080810167ffffffffffffffff81118282101715613ea457613ea4613e52565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f3757613f37613e52565b604052919050565b600067ffffffffffffffff821115613f5957613f59613e52565b5060051b60200190565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146105ac57600080fd5b600060408284031215613fa557600080fd5b613fad613e81565b9050613fb882613f63565b8152602082013563ffffffff1981168114613fd257600080fd5b602082015292915050565b60006020808385031215613ff057600080fd5b823567ffffffffffffffff81111561400757600080fd5b8301601f8101851361401857600080fd5b803561402b61402682613f3f565b613ef0565b8082825260208201915060208360061b85010192508783111561404d57600080fd5b6020840193505b82841015614078576140668885613f93565b82528482019150604084019350614054565b979650505050505050565b60006020808352835180602085015260005b818110156140b157858101830151858201604001528201614095565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561410257600080fd5b611dee82613f63565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ac57600080fd5b600082601f83011261414057600080fd5b8135602061415061402683613f3f565b8083825260208201915060208460051b87010193508684111561417257600080fd5b602086015b84811015614195576141888161410b565b8352918301918301614177565b509695505050505050565b600080604083850312156141b357600080fd5b823567ffffffffffffffff808211156141cb57600080fd5b6141d78683870161412f565b935060208501359150808211156141ed57600080fd5b506141fa8582860161412f565b9150509250929050565b8051606080845281518482018190526000926080916020918201918388019190865b82811015614280578451805173ffffffffffffffffffffffffffffffffffffffff908116865283820151168386015260408082015160ff908116918701919091529088015116878501529381019392850192600101614226565b508781015161ffff81168a83015295505050604086015193506142a9604088018561ffff169052565b9695505050505050565b600063ffffffff808616835280851660208401525060606040830152613de46060830184614204565b803560ff811681146105ac57600080fd5b803561ffff811681146105ac57600080fd5b6000602080838503121561431257600080fd5b823567ffffffffffffffff8082111561432a57600080fd5b8185019150606080838803121561434057600080fd5b614348613eaa565b83358381111561435757600080fd5b84019250601f8301881361436a57600080fd5b823561437861402682613f3f565b81815260079190911b8401860190868101908a83111561439757600080fd5b948701945b82861015614409576080868c0312156143b55760008081fd5b6143bd613ecd565b6143c68761410b565b81526143d389880161410b565b8982015260406143e48189016142dc565b908201526143f38787016142dc565b818701528252608095909501949087019061439c565b83525061441990508486016142ed565b85820152614429604085016142ed565b6040820152979650505050505050565b60006040828403121561444b57600080fd5b50919050565b6000806040838503121561446457600080fd5b61446d83613f63565b915060208084013567ffffffffffffffff81111561448a57600080fd5b8401601f8101861361449b57600080fd5b80356144a961402682613f3f565b81815260059190911b820183019083810190888311156144c857600080fd5b928401925b828410156144ed576144de84613f63565b825292840192908401906144cd565b80955050505050509250929050565b6000602080838503121561450f57600080fd5b823567ffffffffffffffff81111561452657600080fd5b8301601f8101851361453757600080fd5b803561454561402682613f3f565b81815260079190911b8201830190838101908783111561456457600080fd5b928401925b8284101561407857608084890312156145825760008081fd5b61458a613eaa565b6145938561410b565b81526145a189878701613f93565b86820152606085013580151581146145b95760008081fd5b604082015282526080939093019290840190614569565b600080602083850312156145e357600080fd5b823567ffffffffffffffff808211156145fb57600080fd5b818501915085601f83011261460f57600080fd5b81358181111561461e57600080fd5b8660208260061b850101111561463357600080fd5b60209290920196919550909350505050565b6080815260006146586080830187613ded565b82810360208481019190915286518083528782019282019060005b8181101561469657845163ffffffff191683529383019391830191600101614673565b505061ffff96909616604085015250505090151560609091015292915050565b600080604083850312156146c957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156147f2578251805160058110614766577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015167ffffffffffffffff16888701528681015115158787015260608082015173ffffffffffffffffffffffffffffffffffffffff16908701526080808201517fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169188019190915260a091820151169086015260c09094019391860191600101614725565b509298975050505050505050565b60006020828403121561481257600080fd5b611dee8261410b565b60608152600061482e6060830186613ded565b61ffff94909416602083015250901515604090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000604082840312156148b957600080fd5b6148c1613e81565b6148ca8361410b565b8152602083013560208201528091505092915050565b815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604081016105a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff818116838216019080821115613a4f57613a4f61490d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149885761498861490d565b5060010190565b60008161499e5761499e61490d565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b808201808211156105a6576105a661490d565b818103818111156105a6576105a661490d565b600060ff821660ff8103614a0057614a0061490d565b60010192915050565b61ffff828116828216039080821115613a4f57613a4f61490d565b600067ffffffffffffffff821680614a3e57614a3e61490d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600063ffffffff808316818103614aae57614aae61490d565b6001019392505050565b602081526000611dee6020830184614204565b600067ffffffffffffffff808316818103614aae57614aae61490d565b78ffffffffffffffffffffffffffffffffffffffffffffffffff828116828216039080821115613a4f57613a4f61490d565b80820281158282048414176105a6576105a661490d56fea164736f6c6343000818000a", } -var ARMContractABI = ARMContractMetaData.ABI +var RMNContractABI = RMNContractMetaData.ABI -var ARMContractBin = ARMContractMetaData.Bin +var RMNContractBin = RMNContractMetaData.Bin -func DeployARMContract(auth *bind.TransactOpts, backend bind.ContractBackend, config RMNConfig) (common.Address, *types.Transaction, *ARMContract, error) { - parsed, err := ARMContractMetaData.GetAbi() +func DeployRMNContract(auth *bind.TransactOpts, backend bind.ContractBackend, config RMNConfig) (common.Address, *types.Transaction, *RMNContract, error) { + parsed, err := RMNContractMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -86,134 +86,134 @@ func DeployARMContract(auth *bind.TransactOpts, backend bind.ContractBackend, co return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ARMContractBin), backend, config) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNContractBin), backend, config) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &ARMContract{address: address, abi: *parsed, ARMContractCaller: ARMContractCaller{contract: contract}, ARMContractTransactor: ARMContractTransactor{contract: contract}, ARMContractFilterer: ARMContractFilterer{contract: contract}}, nil + return address, tx, &RMNContract{address: address, abi: *parsed, RMNContractCaller: RMNContractCaller{contract: contract}, RMNContractTransactor: RMNContractTransactor{contract: contract}, RMNContractFilterer: RMNContractFilterer{contract: contract}}, nil } -type ARMContract struct { +type RMNContract struct { address common.Address abi abi.ABI - ARMContractCaller - ARMContractTransactor - ARMContractFilterer + RMNContractCaller + RMNContractTransactor + RMNContractFilterer } -type ARMContractCaller struct { +type RMNContractCaller struct { contract *bind.BoundContract } -type ARMContractTransactor struct { +type RMNContractTransactor struct { contract *bind.BoundContract } -type ARMContractFilterer struct { +type RMNContractFilterer struct { contract *bind.BoundContract } -type ARMContractSession struct { - Contract *ARMContract +type RMNContractSession struct { + Contract *RMNContract CallOpts bind.CallOpts TransactOpts bind.TransactOpts } -type ARMContractCallerSession struct { - Contract *ARMContractCaller +type RMNContractCallerSession struct { + Contract *RMNContractCaller CallOpts bind.CallOpts } -type ARMContractTransactorSession struct { - Contract *ARMContractTransactor +type RMNContractTransactorSession struct { + Contract *RMNContractTransactor TransactOpts bind.TransactOpts } -type ARMContractRaw struct { - Contract *ARMContract +type RMNContractRaw struct { + Contract *RMNContract } -type ARMContractCallerRaw struct { - Contract *ARMContractCaller +type RMNContractCallerRaw struct { + Contract *RMNContractCaller } -type ARMContractTransactorRaw struct { - Contract *ARMContractTransactor +type RMNContractTransactorRaw struct { + Contract *RMNContractTransactor } -func NewARMContract(address common.Address, backend bind.ContractBackend) (*ARMContract, error) { - abi, err := abi.JSON(strings.NewReader(ARMContractABI)) +func NewRMNContract(address common.Address, backend bind.ContractBackend) (*RMNContract, error) { + abi, err := abi.JSON(strings.NewReader(RMNContractABI)) if err != nil { return nil, err } - contract, err := bindARMContract(address, backend, backend, backend) + contract, err := bindRMNContract(address, backend, backend, backend) if err != nil { return nil, err } - return &ARMContract{address: address, abi: abi, ARMContractCaller: ARMContractCaller{contract: contract}, ARMContractTransactor: ARMContractTransactor{contract: contract}, ARMContractFilterer: ARMContractFilterer{contract: contract}}, nil + return &RMNContract{address: address, abi: abi, RMNContractCaller: RMNContractCaller{contract: contract}, RMNContractTransactor: RMNContractTransactor{contract: contract}, RMNContractFilterer: RMNContractFilterer{contract: contract}}, nil } -func NewARMContractCaller(address common.Address, caller bind.ContractCaller) (*ARMContractCaller, error) { - contract, err := bindARMContract(address, caller, nil, nil) +func NewRMNContractCaller(address common.Address, caller bind.ContractCaller) (*RMNContractCaller, error) { + contract, err := bindRMNContract(address, caller, nil, nil) if err != nil { return nil, err } - return &ARMContractCaller{contract: contract}, nil + return &RMNContractCaller{contract: contract}, nil } -func NewARMContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ARMContractTransactor, error) { - contract, err := bindARMContract(address, nil, transactor, nil) +func NewRMNContractTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNContractTransactor, error) { + contract, err := bindRMNContract(address, nil, transactor, nil) if err != nil { return nil, err } - return &ARMContractTransactor{contract: contract}, nil + return &RMNContractTransactor{contract: contract}, nil } -func NewARMContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ARMContractFilterer, error) { - contract, err := bindARMContract(address, nil, nil, filterer) +func NewRMNContractFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNContractFilterer, error) { + contract, err := bindRMNContract(address, nil, nil, filterer) if err != nil { return nil, err } - return &ARMContractFilterer{contract: contract}, nil + return &RMNContractFilterer{contract: contract}, nil } -func bindARMContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ARMContractMetaData.GetAbi() +func bindRMNContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RMNContractMetaData.GetAbi() if err != nil { return nil, err } return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -func (_ARMContract *ARMContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ARMContract.Contract.ARMContractCaller.contract.Call(opts, result, method, params...) +func (_RMNContract *RMNContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNContract.Contract.RMNContractCaller.contract.Call(opts, result, method, params...) } -func (_ARMContract *ARMContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ARMContract.Contract.ARMContractTransactor.contract.Transfer(opts) +func (_RMNContract *RMNContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNContract.Contract.RMNContractTransactor.contract.Transfer(opts) } -func (_ARMContract *ARMContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ARMContract.Contract.ARMContractTransactor.contract.Transact(opts, method, params...) +func (_RMNContract *RMNContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNContract.Contract.RMNContractTransactor.contract.Transact(opts, method, params...) } -func (_ARMContract *ARMContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ARMContract.Contract.contract.Call(opts, result, method, params...) +func (_RMNContract *RMNContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNContract.Contract.contract.Call(opts, result, method, params...) } -func (_ARMContract *ARMContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ARMContract.Contract.contract.Transfer(opts) +func (_RMNContract *RMNContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNContract.Contract.contract.Transfer(opts) } -func (_ARMContract *ARMContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ARMContract.Contract.contract.Transact(opts, method, params...) +func (_RMNContract *RMNContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNContract.Contract.contract.Transact(opts, method, params...) } -func (_ARMContract *ARMContractCaller) GetBlessProgress(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (GetBlessProgress, +func (_RMNContract *RMNContractCaller) GetBlessProgress(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (GetBlessProgress, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getBlessProgress", taggedRoot) + err := _RMNContract.contract.Call(opts, &out, "getBlessProgress", taggedRoot) outstruct := new(GetBlessProgress) if err != nil { @@ -228,23 +228,23 @@ func (_ARMContract *ARMContractCaller) GetBlessProgress(opts *bind.CallOpts, tag } -func (_ARMContract *ARMContractSession) GetBlessProgress(taggedRoot IRMNTaggedRoot) (GetBlessProgress, +func (_RMNContract *RMNContractSession) GetBlessProgress(taggedRoot IRMNTaggedRoot) (GetBlessProgress, error) { - return _ARMContract.Contract.GetBlessProgress(&_ARMContract.CallOpts, taggedRoot) + return _RMNContract.Contract.GetBlessProgress(&_RMNContract.CallOpts, taggedRoot) } -func (_ARMContract *ARMContractCallerSession) GetBlessProgress(taggedRoot IRMNTaggedRoot) (GetBlessProgress, +func (_RMNContract *RMNContractCallerSession) GetBlessProgress(taggedRoot IRMNTaggedRoot) (GetBlessProgress, error) { - return _ARMContract.Contract.GetBlessProgress(&_ARMContract.CallOpts, taggedRoot) + return _RMNContract.Contract.GetBlessProgress(&_RMNContract.CallOpts, taggedRoot) } -func (_ARMContract *ARMContractCaller) GetConfigDetails(opts *bind.CallOpts) (GetConfigDetails, +func (_RMNContract *RMNContractCaller) GetConfigDetails(opts *bind.CallOpts) (GetConfigDetails, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getConfigDetails") + err := _RMNContract.contract.Call(opts, &out, "getConfigDetails") outstruct := new(GetConfigDetails) if err != nil { @@ -259,23 +259,23 @@ func (_ARMContract *ARMContractCaller) GetConfigDetails(opts *bind.CallOpts) (Ge } -func (_ARMContract *ARMContractSession) GetConfigDetails() (GetConfigDetails, +func (_RMNContract *RMNContractSession) GetConfigDetails() (GetConfigDetails, error) { - return _ARMContract.Contract.GetConfigDetails(&_ARMContract.CallOpts) + return _RMNContract.Contract.GetConfigDetails(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) GetConfigDetails() (GetConfigDetails, +func (_RMNContract *RMNContractCallerSession) GetConfigDetails() (GetConfigDetails, error) { - return _ARMContract.Contract.GetConfigDetails(&_ARMContract.CallOpts) + return _RMNContract.Contract.GetConfigDetails(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCaller) GetCurseProgress(opts *bind.CallOpts, subject [16]byte) (GetCurseProgress, +func (_RMNContract *RMNContractCaller) GetCurseProgress(opts *bind.CallOpts, subject [16]byte) (GetCurseProgress, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getCurseProgress", subject) + err := _RMNContract.contract.Call(opts, &out, "getCurseProgress", subject) outstruct := new(GetCurseProgress) if err != nil { @@ -291,21 +291,21 @@ func (_ARMContract *ARMContractCaller) GetCurseProgress(opts *bind.CallOpts, sub } -func (_ARMContract *ARMContractSession) GetCurseProgress(subject [16]byte) (GetCurseProgress, +func (_RMNContract *RMNContractSession) GetCurseProgress(subject [16]byte) (GetCurseProgress, error) { - return _ARMContract.Contract.GetCurseProgress(&_ARMContract.CallOpts, subject) + return _RMNContract.Contract.GetCurseProgress(&_RMNContract.CallOpts, subject) } -func (_ARMContract *ARMContractCallerSession) GetCurseProgress(subject [16]byte) (GetCurseProgress, +func (_RMNContract *RMNContractCallerSession) GetCurseProgress(subject [16]byte) (GetCurseProgress, error) { - return _ARMContract.Contract.GetCurseProgress(&_ARMContract.CallOpts, subject) + return _RMNContract.Contract.GetCurseProgress(&_RMNContract.CallOpts, subject) } -func (_ARMContract *ARMContractCaller) GetCursedSubjectsCount(opts *bind.CallOpts) (*big.Int, error) { +func (_RMNContract *RMNContractCaller) GetCursedSubjectsCount(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getCursedSubjectsCount") + err := _RMNContract.contract.Call(opts, &out, "getCursedSubjectsCount") if err != nil { return *new(*big.Int), err @@ -317,17 +317,17 @@ func (_ARMContract *ARMContractCaller) GetCursedSubjectsCount(opts *bind.CallOpt } -func (_ARMContract *ARMContractSession) GetCursedSubjectsCount() (*big.Int, error) { - return _ARMContract.Contract.GetCursedSubjectsCount(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractSession) GetCursedSubjectsCount() (*big.Int, error) { + return _RMNContract.Contract.GetCursedSubjectsCount(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) GetCursedSubjectsCount() (*big.Int, error) { - return _ARMContract.Contract.GetCursedSubjectsCount(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractCallerSession) GetCursedSubjectsCount() (*big.Int, error) { + return _RMNContract.Contract.GetCursedSubjectsCount(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCaller) GetPermaBlessedCommitStores(opts *bind.CallOpts) ([]common.Address, error) { +func (_RMNContract *RMNContractCaller) GetPermaBlessedCommitStores(opts *bind.CallOpts) ([]common.Address, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getPermaBlessedCommitStores") + err := _RMNContract.contract.Call(opts, &out, "getPermaBlessedCommitStores") if err != nil { return *new([]common.Address), err @@ -339,17 +339,17 @@ func (_ARMContract *ARMContractCaller) GetPermaBlessedCommitStores(opts *bind.Ca } -func (_ARMContract *ARMContractSession) GetPermaBlessedCommitStores() ([]common.Address, error) { - return _ARMContract.Contract.GetPermaBlessedCommitStores(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractSession) GetPermaBlessedCommitStores() ([]common.Address, error) { + return _RMNContract.Contract.GetPermaBlessedCommitStores(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) GetPermaBlessedCommitStores() ([]common.Address, error) { - return _ARMContract.Contract.GetPermaBlessedCommitStores(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractCallerSession) GetPermaBlessedCommitStores() ([]common.Address, error) { + return _RMNContract.Contract.GetPermaBlessedCommitStores(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCaller) GetRecordedCurseRelatedOps(opts *bind.CallOpts, offset *big.Int, limit *big.Int) ([]RMNRecordedCurseRelatedOp, error) { +func (_RMNContract *RMNContractCaller) GetRecordedCurseRelatedOps(opts *bind.CallOpts, offset *big.Int, limit *big.Int) ([]RMNRecordedCurseRelatedOp, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getRecordedCurseRelatedOps", offset, limit) + err := _RMNContract.contract.Call(opts, &out, "getRecordedCurseRelatedOps", offset, limit) if err != nil { return *new([]RMNRecordedCurseRelatedOp), err @@ -361,17 +361,17 @@ func (_ARMContract *ARMContractCaller) GetRecordedCurseRelatedOps(opts *bind.Cal } -func (_ARMContract *ARMContractSession) GetRecordedCurseRelatedOps(offset *big.Int, limit *big.Int) ([]RMNRecordedCurseRelatedOp, error) { - return _ARMContract.Contract.GetRecordedCurseRelatedOps(&_ARMContract.CallOpts, offset, limit) +func (_RMNContract *RMNContractSession) GetRecordedCurseRelatedOps(offset *big.Int, limit *big.Int) ([]RMNRecordedCurseRelatedOp, error) { + return _RMNContract.Contract.GetRecordedCurseRelatedOps(&_RMNContract.CallOpts, offset, limit) } -func (_ARMContract *ARMContractCallerSession) GetRecordedCurseRelatedOps(offset *big.Int, limit *big.Int) ([]RMNRecordedCurseRelatedOp, error) { - return _ARMContract.Contract.GetRecordedCurseRelatedOps(&_ARMContract.CallOpts, offset, limit) +func (_RMNContract *RMNContractCallerSession) GetRecordedCurseRelatedOps(offset *big.Int, limit *big.Int) ([]RMNRecordedCurseRelatedOp, error) { + return _RMNContract.Contract.GetRecordedCurseRelatedOps(&_RMNContract.CallOpts, offset, limit) } -func (_ARMContract *ARMContractCaller) GetRecordedCurseRelatedOpsCount(opts *bind.CallOpts) (*big.Int, error) { +func (_RMNContract *RMNContractCaller) GetRecordedCurseRelatedOpsCount(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "getRecordedCurseRelatedOpsCount") + err := _RMNContract.contract.Call(opts, &out, "getRecordedCurseRelatedOpsCount") if err != nil { return *new(*big.Int), err @@ -383,17 +383,17 @@ func (_ARMContract *ARMContractCaller) GetRecordedCurseRelatedOpsCount(opts *bin } -func (_ARMContract *ARMContractSession) GetRecordedCurseRelatedOpsCount() (*big.Int, error) { - return _ARMContract.Contract.GetRecordedCurseRelatedOpsCount(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractSession) GetRecordedCurseRelatedOpsCount() (*big.Int, error) { + return _RMNContract.Contract.GetRecordedCurseRelatedOpsCount(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) GetRecordedCurseRelatedOpsCount() (*big.Int, error) { - return _ARMContract.Contract.GetRecordedCurseRelatedOpsCount(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractCallerSession) GetRecordedCurseRelatedOpsCount() (*big.Int, error) { + return _RMNContract.Contract.GetRecordedCurseRelatedOpsCount(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCaller) IsBlessed(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (bool, error) { +func (_RMNContract *RMNContractCaller) IsBlessed(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (bool, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "isBlessed", taggedRoot) + err := _RMNContract.contract.Call(opts, &out, "isBlessed", taggedRoot) if err != nil { return *new(bool), err @@ -405,17 +405,17 @@ func (_ARMContract *ARMContractCaller) IsBlessed(opts *bind.CallOpts, taggedRoot } -func (_ARMContract *ARMContractSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { - return _ARMContract.Contract.IsBlessed(&_ARMContract.CallOpts, taggedRoot) +func (_RMNContract *RMNContractSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { + return _RMNContract.Contract.IsBlessed(&_RMNContract.CallOpts, taggedRoot) } -func (_ARMContract *ARMContractCallerSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { - return _ARMContract.Contract.IsBlessed(&_ARMContract.CallOpts, taggedRoot) +func (_RMNContract *RMNContractCallerSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { + return _RMNContract.Contract.IsBlessed(&_RMNContract.CallOpts, taggedRoot) } -func (_ARMContract *ARMContractCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { +func (_RMNContract *RMNContractCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "isCursed", subject) + err := _RMNContract.contract.Call(opts, &out, "isCursed", subject) if err != nil { return *new(bool), err @@ -427,17 +427,17 @@ func (_ARMContract *ARMContractCaller) IsCursed(opts *bind.CallOpts, subject [16 } -func (_ARMContract *ARMContractSession) IsCursed(subject [16]byte) (bool, error) { - return _ARMContract.Contract.IsCursed(&_ARMContract.CallOpts, subject) +func (_RMNContract *RMNContractSession) IsCursed(subject [16]byte) (bool, error) { + return _RMNContract.Contract.IsCursed(&_RMNContract.CallOpts, subject) } -func (_ARMContract *ARMContractCallerSession) IsCursed(subject [16]byte) (bool, error) { - return _ARMContract.Contract.IsCursed(&_ARMContract.CallOpts, subject) +func (_RMNContract *RMNContractCallerSession) IsCursed(subject [16]byte) (bool, error) { + return _RMNContract.Contract.IsCursed(&_RMNContract.CallOpts, subject) } -func (_ARMContract *ARMContractCaller) IsCursed0(opts *bind.CallOpts) (bool, error) { +func (_RMNContract *RMNContractCaller) IsCursed0(opts *bind.CallOpts) (bool, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "isCursed0") + err := _RMNContract.contract.Call(opts, &out, "isCursed0") if err != nil { return *new(bool), err @@ -449,17 +449,17 @@ func (_ARMContract *ARMContractCaller) IsCursed0(opts *bind.CallOpts) (bool, err } -func (_ARMContract *ARMContractSession) IsCursed0() (bool, error) { - return _ARMContract.Contract.IsCursed0(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractSession) IsCursed0() (bool, error) { + return _RMNContract.Contract.IsCursed0(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) IsCursed0() (bool, error) { - return _ARMContract.Contract.IsCursed0(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractCallerSession) IsCursed0() (bool, error) { + return _RMNContract.Contract.IsCursed0(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { +func (_RMNContract *RMNContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "owner") + err := _RMNContract.contract.Call(opts, &out, "owner") if err != nil { return *new(common.Address), err @@ -471,17 +471,17 @@ func (_ARMContract *ARMContractCaller) Owner(opts *bind.CallOpts) (common.Addres } -func (_ARMContract *ARMContractSession) Owner() (common.Address, error) { - return _ARMContract.Contract.Owner(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractSession) Owner() (common.Address, error) { + return _RMNContract.Contract.Owner(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) Owner() (common.Address, error) { - return _ARMContract.Contract.Owner(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractCallerSession) Owner() (common.Address, error) { + return _RMNContract.Contract.Owner(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { +func (_RMNContract *RMNContractCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} - err := _ARMContract.contract.Call(opts, &out, "typeAndVersion") + err := _RMNContract.contract.Call(opts, &out, "typeAndVersion") if err != nil { return *new(string), err @@ -493,136 +493,136 @@ func (_ARMContract *ARMContractCaller) TypeAndVersion(opts *bind.CallOpts) (stri } -func (_ARMContract *ARMContractSession) TypeAndVersion() (string, error) { - return _ARMContract.Contract.TypeAndVersion(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractSession) TypeAndVersion() (string, error) { + return _RMNContract.Contract.TypeAndVersion(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractCallerSession) TypeAndVersion() (string, error) { - return _ARMContract.Contract.TypeAndVersion(&_ARMContract.CallOpts) +func (_RMNContract *RMNContractCallerSession) TypeAndVersion() (string, error) { + return _RMNContract.Contract.TypeAndVersion(&_RMNContract.CallOpts) } -func (_ARMContract *ARMContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "acceptOwnership") +func (_RMNContract *RMNContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "acceptOwnership") } -func (_ARMContract *ARMContractSession) AcceptOwnership() (*types.Transaction, error) { - return _ARMContract.Contract.AcceptOwnership(&_ARMContract.TransactOpts) +func (_RMNContract *RMNContractSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNContract.Contract.AcceptOwnership(&_RMNContract.TransactOpts) } -func (_ARMContract *ARMContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _ARMContract.Contract.AcceptOwnership(&_ARMContract.TransactOpts) +func (_RMNContract *RMNContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNContract.Contract.AcceptOwnership(&_RMNContract.TransactOpts) } -func (_ARMContract *ARMContractTransactor) OwnerCurse(opts *bind.TransactOpts, curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "ownerCurse", curseId, subjects) +func (_RMNContract *RMNContractTransactor) OwnerCurse(opts *bind.TransactOpts, curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "ownerCurse", curseId, subjects) } -func (_ARMContract *ARMContractSession) OwnerCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerCurse(&_ARMContract.TransactOpts, curseId, subjects) +func (_RMNContract *RMNContractSession) OwnerCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerCurse(&_RMNContract.TransactOpts, curseId, subjects) } -func (_ARMContract *ARMContractTransactorSession) OwnerCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerCurse(&_ARMContract.TransactOpts, curseId, subjects) +func (_RMNContract *RMNContractTransactorSession) OwnerCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerCurse(&_RMNContract.TransactOpts, curseId, subjects) } -func (_ARMContract *ARMContractTransactor) OwnerRemoveThenAddPermaBlessedCommitStores(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "ownerRemoveThenAddPermaBlessedCommitStores", removes, adds) +func (_RMNContract *RMNContractTransactor) OwnerRemoveThenAddPermaBlessedCommitStores(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "ownerRemoveThenAddPermaBlessedCommitStores", removes, adds) } -func (_ARMContract *ARMContractSession) OwnerRemoveThenAddPermaBlessedCommitStores(removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerRemoveThenAddPermaBlessedCommitStores(&_ARMContract.TransactOpts, removes, adds) +func (_RMNContract *RMNContractSession) OwnerRemoveThenAddPermaBlessedCommitStores(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerRemoveThenAddPermaBlessedCommitStores(&_RMNContract.TransactOpts, removes, adds) } -func (_ARMContract *ARMContractTransactorSession) OwnerRemoveThenAddPermaBlessedCommitStores(removes []common.Address, adds []common.Address) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerRemoveThenAddPermaBlessedCommitStores(&_ARMContract.TransactOpts, removes, adds) +func (_RMNContract *RMNContractTransactorSession) OwnerRemoveThenAddPermaBlessedCommitStores(removes []common.Address, adds []common.Address) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerRemoveThenAddPermaBlessedCommitStores(&_RMNContract.TransactOpts, removes, adds) } -func (_ARMContract *ARMContractTransactor) OwnerResetBlessVotes(opts *bind.TransactOpts, taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "ownerResetBlessVotes", taggedRoots) +func (_RMNContract *RMNContractTransactor) OwnerResetBlessVotes(opts *bind.TransactOpts, taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "ownerResetBlessVotes", taggedRoots) } -func (_ARMContract *ARMContractSession) OwnerResetBlessVotes(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerResetBlessVotes(&_ARMContract.TransactOpts, taggedRoots) +func (_RMNContract *RMNContractSession) OwnerResetBlessVotes(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerResetBlessVotes(&_RMNContract.TransactOpts, taggedRoots) } -func (_ARMContract *ARMContractTransactorSession) OwnerResetBlessVotes(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerResetBlessVotes(&_ARMContract.TransactOpts, taggedRoots) +func (_RMNContract *RMNContractTransactorSession) OwnerResetBlessVotes(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerResetBlessVotes(&_RMNContract.TransactOpts, taggedRoots) } -func (_ARMContract *ARMContractTransactor) OwnerUnvoteToCurse(opts *bind.TransactOpts, ownerUnvoteToCurseRequests []RMNOwnerUnvoteToCurseRequest) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "ownerUnvoteToCurse", ownerUnvoteToCurseRequests) +func (_RMNContract *RMNContractTransactor) OwnerUnvoteToCurse(opts *bind.TransactOpts, ownerUnvoteToCurseRequests []RMNOwnerUnvoteToCurseRequest) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "ownerUnvoteToCurse", ownerUnvoteToCurseRequests) } -func (_ARMContract *ARMContractSession) OwnerUnvoteToCurse(ownerUnvoteToCurseRequests []RMNOwnerUnvoteToCurseRequest) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerUnvoteToCurse(&_ARMContract.TransactOpts, ownerUnvoteToCurseRequests) +func (_RMNContract *RMNContractSession) OwnerUnvoteToCurse(ownerUnvoteToCurseRequests []RMNOwnerUnvoteToCurseRequest) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerUnvoteToCurse(&_RMNContract.TransactOpts, ownerUnvoteToCurseRequests) } -func (_ARMContract *ARMContractTransactorSession) OwnerUnvoteToCurse(ownerUnvoteToCurseRequests []RMNOwnerUnvoteToCurseRequest) (*types.Transaction, error) { - return _ARMContract.Contract.OwnerUnvoteToCurse(&_ARMContract.TransactOpts, ownerUnvoteToCurseRequests) +func (_RMNContract *RMNContractTransactorSession) OwnerUnvoteToCurse(ownerUnvoteToCurseRequests []RMNOwnerUnvoteToCurseRequest) (*types.Transaction, error) { + return _RMNContract.Contract.OwnerUnvoteToCurse(&_RMNContract.TransactOpts, ownerUnvoteToCurseRequests) } -func (_ARMContract *ARMContractTransactor) SetConfig(opts *bind.TransactOpts, config RMNConfig) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "setConfig", config) +func (_RMNContract *RMNContractTransactor) SetConfig(opts *bind.TransactOpts, config RMNConfig) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "setConfig", config) } -func (_ARMContract *ARMContractSession) SetConfig(config RMNConfig) (*types.Transaction, error) { - return _ARMContract.Contract.SetConfig(&_ARMContract.TransactOpts, config) +func (_RMNContract *RMNContractSession) SetConfig(config RMNConfig) (*types.Transaction, error) { + return _RMNContract.Contract.SetConfig(&_RMNContract.TransactOpts, config) } -func (_ARMContract *ARMContractTransactorSession) SetConfig(config RMNConfig) (*types.Transaction, error) { - return _ARMContract.Contract.SetConfig(&_ARMContract.TransactOpts, config) +func (_RMNContract *RMNContractTransactorSession) SetConfig(config RMNConfig) (*types.Transaction, error) { + return _RMNContract.Contract.SetConfig(&_RMNContract.TransactOpts, config) } -func (_ARMContract *ARMContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "transferOwnership", to) +func (_RMNContract *RMNContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "transferOwnership", to) } -func (_ARMContract *ARMContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _ARMContract.Contract.TransferOwnership(&_ARMContract.TransactOpts, to) +func (_RMNContract *RMNContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNContract.Contract.TransferOwnership(&_RMNContract.TransactOpts, to) } -func (_ARMContract *ARMContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _ARMContract.Contract.TransferOwnership(&_ARMContract.TransactOpts, to) +func (_RMNContract *RMNContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNContract.Contract.TransferOwnership(&_RMNContract.TransactOpts, to) } -func (_ARMContract *ARMContractTransactor) UnvoteToCurse(opts *bind.TransactOpts, unvoteToCurseRequests []RMNUnvoteToCurseRequest) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "unvoteToCurse", unvoteToCurseRequests) +func (_RMNContract *RMNContractTransactor) UnvoteToCurse(opts *bind.TransactOpts, unvoteToCurseRequests []RMNUnvoteToCurseRequest) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "unvoteToCurse", unvoteToCurseRequests) } -func (_ARMContract *ARMContractSession) UnvoteToCurse(unvoteToCurseRequests []RMNUnvoteToCurseRequest) (*types.Transaction, error) { - return _ARMContract.Contract.UnvoteToCurse(&_ARMContract.TransactOpts, unvoteToCurseRequests) +func (_RMNContract *RMNContractSession) UnvoteToCurse(unvoteToCurseRequests []RMNUnvoteToCurseRequest) (*types.Transaction, error) { + return _RMNContract.Contract.UnvoteToCurse(&_RMNContract.TransactOpts, unvoteToCurseRequests) } -func (_ARMContract *ARMContractTransactorSession) UnvoteToCurse(unvoteToCurseRequests []RMNUnvoteToCurseRequest) (*types.Transaction, error) { - return _ARMContract.Contract.UnvoteToCurse(&_ARMContract.TransactOpts, unvoteToCurseRequests) +func (_RMNContract *RMNContractTransactorSession) UnvoteToCurse(unvoteToCurseRequests []RMNUnvoteToCurseRequest) (*types.Transaction, error) { + return _RMNContract.Contract.UnvoteToCurse(&_RMNContract.TransactOpts, unvoteToCurseRequests) } -func (_ARMContract *ARMContractTransactor) VoteToBless(opts *bind.TransactOpts, taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "voteToBless", taggedRoots) +func (_RMNContract *RMNContractTransactor) VoteToBless(opts *bind.TransactOpts, taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "voteToBless", taggedRoots) } -func (_ARMContract *ARMContractSession) VoteToBless(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { - return _ARMContract.Contract.VoteToBless(&_ARMContract.TransactOpts, taggedRoots) +func (_RMNContract *RMNContractSession) VoteToBless(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { + return _RMNContract.Contract.VoteToBless(&_RMNContract.TransactOpts, taggedRoots) } -func (_ARMContract *ARMContractTransactorSession) VoteToBless(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { - return _ARMContract.Contract.VoteToBless(&_ARMContract.TransactOpts, taggedRoots) +func (_RMNContract *RMNContractTransactorSession) VoteToBless(taggedRoots []IRMNTaggedRoot) (*types.Transaction, error) { + return _RMNContract.Contract.VoteToBless(&_RMNContract.TransactOpts, taggedRoots) } -func (_ARMContract *ARMContractTransactor) VoteToCurse(opts *bind.TransactOpts, curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { - return _ARMContract.contract.Transact(opts, "voteToCurse", curseId, subjects) +func (_RMNContract *RMNContractTransactor) VoteToCurse(opts *bind.TransactOpts, curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { + return _RMNContract.contract.Transact(opts, "voteToCurse", curseId, subjects) } -func (_ARMContract *ARMContractSession) VoteToCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { - return _ARMContract.Contract.VoteToCurse(&_ARMContract.TransactOpts, curseId, subjects) +func (_RMNContract *RMNContractSession) VoteToCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { + return _RMNContract.Contract.VoteToCurse(&_RMNContract.TransactOpts, curseId, subjects) } -func (_ARMContract *ARMContractTransactorSession) VoteToCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { - return _ARMContract.Contract.VoteToCurse(&_ARMContract.TransactOpts, curseId, subjects) +func (_RMNContract *RMNContractTransactorSession) VoteToCurse(curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) { + return _RMNContract.Contract.VoteToCurse(&_RMNContract.TransactOpts, curseId, subjects) } -type ARMContractAlreadyBlessedIterator struct { - Event *ARMContractAlreadyBlessed +type RMNContractAlreadyBlessedIterator struct { + Event *RMNContractAlreadyBlessed contract *bind.BoundContract event string @@ -633,7 +633,7 @@ type ARMContractAlreadyBlessedIterator struct { fail error } -func (it *ARMContractAlreadyBlessedIterator) Next() bool { +func (it *RMNContractAlreadyBlessedIterator) Next() bool { if it.fail != nil { return false @@ -642,7 +642,7 @@ func (it *ARMContractAlreadyBlessedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractAlreadyBlessed) + it.Event = new(RMNContractAlreadyBlessed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -657,7 +657,7 @@ func (it *ARMContractAlreadyBlessedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractAlreadyBlessed) + it.Event = new(RMNContractAlreadyBlessed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -672,23 +672,23 @@ func (it *ARMContractAlreadyBlessedIterator) Next() bool { } } -func (it *ARMContractAlreadyBlessedIterator) Error() error { +func (it *RMNContractAlreadyBlessedIterator) Error() error { return it.fail } -func (it *ARMContractAlreadyBlessedIterator) Close() error { +func (it *RMNContractAlreadyBlessedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractAlreadyBlessed struct { +type RMNContractAlreadyBlessed struct { ConfigVersion uint32 Voter common.Address TaggedRoot IRMNTaggedRoot Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterAlreadyBlessed(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractAlreadyBlessedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterAlreadyBlessed(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractAlreadyBlessedIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -699,14 +699,14 @@ func (_ARMContract *ARMContractFilterer) FilterAlreadyBlessed(opts *bind.FilterO voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "AlreadyBlessed", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "AlreadyBlessed", configVersionRule, voterRule) if err != nil { return nil, err } - return &ARMContractAlreadyBlessedIterator{contract: _ARMContract.contract, event: "AlreadyBlessed", logs: logs, sub: sub}, nil + return &RMNContractAlreadyBlessedIterator{contract: _RMNContract.contract, event: "AlreadyBlessed", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchAlreadyBlessed(opts *bind.WatchOpts, sink chan<- *ARMContractAlreadyBlessed, configVersion []uint32, voter []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchAlreadyBlessed(opts *bind.WatchOpts, sink chan<- *RMNContractAlreadyBlessed, configVersion []uint32, voter []common.Address) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -717,7 +717,7 @@ func (_ARMContract *ARMContractFilterer) WatchAlreadyBlessed(opts *bind.WatchOpt voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "AlreadyBlessed", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "AlreadyBlessed", configVersionRule, voterRule) if err != nil { return nil, err } @@ -727,8 +727,8 @@ func (_ARMContract *ARMContractFilterer) WatchAlreadyBlessed(opts *bind.WatchOpt select { case log := <-logs: - event := new(ARMContractAlreadyBlessed) - if err := _ARMContract.contract.UnpackLog(event, "AlreadyBlessed", log); err != nil { + event := new(RMNContractAlreadyBlessed) + if err := _RMNContract.contract.UnpackLog(event, "AlreadyBlessed", log); err != nil { return err } event.Raw = log @@ -749,17 +749,17 @@ func (_ARMContract *ARMContractFilterer) WatchAlreadyBlessed(opts *bind.WatchOpt }), nil } -func (_ARMContract *ARMContractFilterer) ParseAlreadyBlessed(log types.Log) (*ARMContractAlreadyBlessed, error) { - event := new(ARMContractAlreadyBlessed) - if err := _ARMContract.contract.UnpackLog(event, "AlreadyBlessed", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseAlreadyBlessed(log types.Log) (*RMNContractAlreadyBlessed, error) { + event := new(RMNContractAlreadyBlessed) + if err := _RMNContract.contract.UnpackLog(event, "AlreadyBlessed", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractAlreadyVotedToBlessIterator struct { - Event *ARMContractAlreadyVotedToBless +type RMNContractAlreadyVotedToBlessIterator struct { + Event *RMNContractAlreadyVotedToBless contract *bind.BoundContract event string @@ -770,7 +770,7 @@ type ARMContractAlreadyVotedToBlessIterator struct { fail error } -func (it *ARMContractAlreadyVotedToBlessIterator) Next() bool { +func (it *RMNContractAlreadyVotedToBlessIterator) Next() bool { if it.fail != nil { return false @@ -779,7 +779,7 @@ func (it *ARMContractAlreadyVotedToBlessIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractAlreadyVotedToBless) + it.Event = new(RMNContractAlreadyVotedToBless) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -794,7 +794,7 @@ func (it *ARMContractAlreadyVotedToBlessIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractAlreadyVotedToBless) + it.Event = new(RMNContractAlreadyVotedToBless) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -809,23 +809,23 @@ func (it *ARMContractAlreadyVotedToBlessIterator) Next() bool { } } -func (it *ARMContractAlreadyVotedToBlessIterator) Error() error { +func (it *RMNContractAlreadyVotedToBlessIterator) Error() error { return it.fail } -func (it *ARMContractAlreadyVotedToBlessIterator) Close() error { +func (it *RMNContractAlreadyVotedToBlessIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractAlreadyVotedToBless struct { +type RMNContractAlreadyVotedToBless struct { ConfigVersion uint32 Voter common.Address TaggedRoot IRMNTaggedRoot Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterAlreadyVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractAlreadyVotedToBlessIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterAlreadyVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractAlreadyVotedToBlessIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -836,14 +836,14 @@ func (_ARMContract *ARMContractFilterer) FilterAlreadyVotedToBless(opts *bind.Fi voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "AlreadyVotedToBless", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "AlreadyVotedToBless", configVersionRule, voterRule) if err != nil { return nil, err } - return &ARMContractAlreadyVotedToBlessIterator{contract: _ARMContract.contract, event: "AlreadyVotedToBless", logs: logs, sub: sub}, nil + return &RMNContractAlreadyVotedToBlessIterator{contract: _RMNContract.contract, event: "AlreadyVotedToBless", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchAlreadyVotedToBless(opts *bind.WatchOpts, sink chan<- *ARMContractAlreadyVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchAlreadyVotedToBless(opts *bind.WatchOpts, sink chan<- *RMNContractAlreadyVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -854,7 +854,7 @@ func (_ARMContract *ARMContractFilterer) WatchAlreadyVotedToBless(opts *bind.Wat voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "AlreadyVotedToBless", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "AlreadyVotedToBless", configVersionRule, voterRule) if err != nil { return nil, err } @@ -864,8 +864,8 @@ func (_ARMContract *ARMContractFilterer) WatchAlreadyVotedToBless(opts *bind.Wat select { case log := <-logs: - event := new(ARMContractAlreadyVotedToBless) - if err := _ARMContract.contract.UnpackLog(event, "AlreadyVotedToBless", log); err != nil { + event := new(RMNContractAlreadyVotedToBless) + if err := _RMNContract.contract.UnpackLog(event, "AlreadyVotedToBless", log); err != nil { return err } event.Raw = log @@ -886,17 +886,17 @@ func (_ARMContract *ARMContractFilterer) WatchAlreadyVotedToBless(opts *bind.Wat }), nil } -func (_ARMContract *ARMContractFilterer) ParseAlreadyVotedToBless(log types.Log) (*ARMContractAlreadyVotedToBless, error) { - event := new(ARMContractAlreadyVotedToBless) - if err := _ARMContract.contract.UnpackLog(event, "AlreadyVotedToBless", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseAlreadyVotedToBless(log types.Log) (*RMNContractAlreadyVotedToBless, error) { + event := new(RMNContractAlreadyVotedToBless) + if err := _RMNContract.contract.UnpackLog(event, "AlreadyVotedToBless", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractConfigSetIterator struct { - Event *ARMContractConfigSet +type RMNContractConfigSetIterator struct { + Event *RMNContractConfigSet contract *bind.BoundContract event string @@ -907,7 +907,7 @@ type ARMContractConfigSetIterator struct { fail error } -func (it *ARMContractConfigSetIterator) Next() bool { +func (it *RMNContractConfigSetIterator) Next() bool { if it.fail != nil { return false @@ -916,7 +916,7 @@ func (it *ARMContractConfigSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractConfigSet) + it.Event = new(RMNContractConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -931,7 +931,7 @@ func (it *ARMContractConfigSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractConfigSet) + it.Event = new(RMNContractConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -946,43 +946,43 @@ func (it *ARMContractConfigSetIterator) Next() bool { } } -func (it *ARMContractConfigSetIterator) Error() error { +func (it *RMNContractConfigSetIterator) Error() error { return it.fail } -func (it *ARMContractConfigSetIterator) Close() error { +func (it *RMNContractConfigSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractConfigSet struct { +type RMNContractConfigSet struct { ConfigVersion uint32 Config RMNConfig Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterConfigSet(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractConfigSetIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterConfigSet(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractConfigSetIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "ConfigSet", configVersionRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "ConfigSet", configVersionRule) if err != nil { return nil, err } - return &ARMContractConfigSetIterator{contract: _ARMContract.contract, event: "ConfigSet", logs: logs, sub: sub}, nil + return &RMNContractConfigSetIterator{contract: _RMNContract.contract, event: "ConfigSet", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *ARMContractConfigSet, configVersion []uint32) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNContractConfigSet, configVersion []uint32) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "ConfigSet", configVersionRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "ConfigSet", configVersionRule) if err != nil { return nil, err } @@ -992,8 +992,8 @@ func (_ARMContract *ARMContractFilterer) WatchConfigSet(opts *bind.WatchOpts, si select { case log := <-logs: - event := new(ARMContractConfigSet) - if err := _ARMContract.contract.UnpackLog(event, "ConfigSet", log); err != nil { + event := new(RMNContractConfigSet) + if err := _RMNContract.contract.UnpackLog(event, "ConfigSet", log); err != nil { return err } event.Raw = log @@ -1014,17 +1014,17 @@ func (_ARMContract *ARMContractFilterer) WatchConfigSet(opts *bind.WatchOpts, si }), nil } -func (_ARMContract *ARMContractFilterer) ParseConfigSet(log types.Log) (*ARMContractConfigSet, error) { - event := new(ARMContractConfigSet) - if err := _ARMContract.contract.UnpackLog(event, "ConfigSet", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseConfigSet(log types.Log) (*RMNContractConfigSet, error) { + event := new(RMNContractConfigSet) + if err := _RMNContract.contract.UnpackLog(event, "ConfigSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractCurseLiftedIterator struct { - Event *ARMContractCurseLifted +type RMNContractCurseLiftedIterator struct { + Event *RMNContractCurseLifted contract *bind.BoundContract event string @@ -1035,7 +1035,7 @@ type ARMContractCurseLiftedIterator struct { fail error } -func (it *ARMContractCurseLiftedIterator) Next() bool { +func (it *RMNContractCurseLiftedIterator) Next() bool { if it.fail != nil { return false @@ -1044,7 +1044,7 @@ func (it *ARMContractCurseLiftedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractCurseLifted) + it.Event = new(RMNContractCurseLifted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1059,7 +1059,7 @@ func (it *ARMContractCurseLiftedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractCurseLifted) + it.Event = new(RMNContractCurseLifted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1074,32 +1074,32 @@ func (it *ARMContractCurseLiftedIterator) Next() bool { } } -func (it *ARMContractCurseLiftedIterator) Error() error { +func (it *RMNContractCurseLiftedIterator) Error() error { return it.fail } -func (it *ARMContractCurseLiftedIterator) Close() error { +func (it *RMNContractCurseLiftedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractCurseLifted struct { +type RMNContractCurseLifted struct { Subject [16]byte Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterCurseLifted(opts *bind.FilterOpts) (*ARMContractCurseLiftedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterCurseLifted(opts *bind.FilterOpts) (*RMNContractCurseLiftedIterator, error) { - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "CurseLifted") + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "CurseLifted") if err != nil { return nil, err } - return &ARMContractCurseLiftedIterator{contract: _ARMContract.contract, event: "CurseLifted", logs: logs, sub: sub}, nil + return &RMNContractCurseLiftedIterator{contract: _RMNContract.contract, event: "CurseLifted", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchCurseLifted(opts *bind.WatchOpts, sink chan<- *ARMContractCurseLifted) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchCurseLifted(opts *bind.WatchOpts, sink chan<- *RMNContractCurseLifted) (event.Subscription, error) { - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "CurseLifted") + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "CurseLifted") if err != nil { return nil, err } @@ -1109,8 +1109,8 @@ func (_ARMContract *ARMContractFilterer) WatchCurseLifted(opts *bind.WatchOpts, select { case log := <-logs: - event := new(ARMContractCurseLifted) - if err := _ARMContract.contract.UnpackLog(event, "CurseLifted", log); err != nil { + event := new(RMNContractCurseLifted) + if err := _RMNContract.contract.UnpackLog(event, "CurseLifted", log); err != nil { return err } event.Raw = log @@ -1131,17 +1131,17 @@ func (_ARMContract *ARMContractFilterer) WatchCurseLifted(opts *bind.WatchOpts, }), nil } -func (_ARMContract *ARMContractFilterer) ParseCurseLifted(log types.Log) (*ARMContractCurseLifted, error) { - event := new(ARMContractCurseLifted) - if err := _ARMContract.contract.UnpackLog(event, "CurseLifted", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseCurseLifted(log types.Log) (*RMNContractCurseLifted, error) { + event := new(RMNContractCurseLifted) + if err := _RMNContract.contract.UnpackLog(event, "CurseLifted", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractCursedIterator struct { - Event *ARMContractCursed +type RMNContractCursedIterator struct { + Event *RMNContractCursed contract *bind.BoundContract event string @@ -1152,7 +1152,7 @@ type ARMContractCursedIterator struct { fail error } -func (it *ARMContractCursedIterator) Next() bool { +func (it *RMNContractCursedIterator) Next() bool { if it.fail != nil { return false @@ -1161,7 +1161,7 @@ func (it *ARMContractCursedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractCursed) + it.Event = new(RMNContractCursed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1176,7 +1176,7 @@ func (it *ARMContractCursedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractCursed) + it.Event = new(RMNContractCursed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1191,44 +1191,44 @@ func (it *ARMContractCursedIterator) Next() bool { } } -func (it *ARMContractCursedIterator) Error() error { +func (it *RMNContractCursedIterator) Error() error { return it.fail } -func (it *ARMContractCursedIterator) Close() error { +func (it *RMNContractCursedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractCursed struct { +type RMNContractCursed struct { ConfigVersion uint32 Subject [16]byte BlockTimestamp uint64 Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterCursed(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractCursedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterCursed(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractCursedIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "Cursed", configVersionRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "Cursed", configVersionRule) if err != nil { return nil, err } - return &ARMContractCursedIterator{contract: _ARMContract.contract, event: "Cursed", logs: logs, sub: sub}, nil + return &RMNContractCursedIterator{contract: _RMNContract.contract, event: "Cursed", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchCursed(opts *bind.WatchOpts, sink chan<- *ARMContractCursed, configVersion []uint32) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchCursed(opts *bind.WatchOpts, sink chan<- *RMNContractCursed, configVersion []uint32) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "Cursed", configVersionRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "Cursed", configVersionRule) if err != nil { return nil, err } @@ -1238,8 +1238,8 @@ func (_ARMContract *ARMContractFilterer) WatchCursed(opts *bind.WatchOpts, sink select { case log := <-logs: - event := new(ARMContractCursed) - if err := _ARMContract.contract.UnpackLog(event, "Cursed", log); err != nil { + event := new(RMNContractCursed) + if err := _RMNContract.contract.UnpackLog(event, "Cursed", log); err != nil { return err } event.Raw = log @@ -1260,17 +1260,17 @@ func (_ARMContract *ARMContractFilterer) WatchCursed(opts *bind.WatchOpts, sink }), nil } -func (_ARMContract *ARMContractFilterer) ParseCursed(log types.Log) (*ARMContractCursed, error) { - event := new(ARMContractCursed) - if err := _ARMContract.contract.UnpackLog(event, "Cursed", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseCursed(log types.Log) (*RMNContractCursed, error) { + event := new(RMNContractCursed) + if err := _RMNContract.contract.UnpackLog(event, "Cursed", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractOwnershipTransferRequestedIterator struct { - Event *ARMContractOwnershipTransferRequested +type RMNContractOwnershipTransferRequestedIterator struct { + Event *RMNContractOwnershipTransferRequested contract *bind.BoundContract event string @@ -1281,7 +1281,7 @@ type ARMContractOwnershipTransferRequestedIterator struct { fail error } -func (it *ARMContractOwnershipTransferRequestedIterator) Next() bool { +func (it *RMNContractOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -1290,7 +1290,7 @@ func (it *ARMContractOwnershipTransferRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractOwnershipTransferRequested) + it.Event = new(RMNContractOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1305,7 +1305,7 @@ func (it *ARMContractOwnershipTransferRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractOwnershipTransferRequested) + it.Event = new(RMNContractOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1320,22 +1320,22 @@ func (it *ARMContractOwnershipTransferRequestedIterator) Next() bool { } } -func (it *ARMContractOwnershipTransferRequestedIterator) Error() error { +func (it *RMNContractOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *ARMContractOwnershipTransferRequestedIterator) Close() error { +func (it *RMNContractOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractOwnershipTransferRequested struct { +type RMNContractOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMContractOwnershipTransferRequestedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNContractOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1346,14 +1346,14 @@ func (_ARMContract *ARMContractFilterer) FilterOwnershipTransferRequested(opts * toRule = append(toRule, toItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &ARMContractOwnershipTransferRequestedIterator{contract: _ARMContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &RMNContractOwnershipTransferRequestedIterator{contract: _RMNContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ARMContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1364,7 +1364,7 @@ func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferRequested(opts *b toRule = append(toRule, toItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -1374,8 +1374,8 @@ func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferRequested(opts *b select { case log := <-logs: - event := new(ARMContractOwnershipTransferRequested) - if err := _ARMContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(RMNContractOwnershipTransferRequested) + if err := _RMNContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -1396,17 +1396,17 @@ func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferRequested(opts *b }), nil } -func (_ARMContract *ARMContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*ARMContractOwnershipTransferRequested, error) { - event := new(ARMContractOwnershipTransferRequested) - if err := _ARMContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNContractOwnershipTransferRequested, error) { + event := new(RMNContractOwnershipTransferRequested) + if err := _RMNContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractOwnershipTransferredIterator struct { - Event *ARMContractOwnershipTransferred +type RMNContractOwnershipTransferredIterator struct { + Event *RMNContractOwnershipTransferred contract *bind.BoundContract event string @@ -1417,7 +1417,7 @@ type ARMContractOwnershipTransferredIterator struct { fail error } -func (it *ARMContractOwnershipTransferredIterator) Next() bool { +func (it *RMNContractOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -1426,7 +1426,7 @@ func (it *ARMContractOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractOwnershipTransferred) + it.Event = new(RMNContractOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1441,7 +1441,7 @@ func (it *ARMContractOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractOwnershipTransferred) + it.Event = new(RMNContractOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1456,22 +1456,22 @@ func (it *ARMContractOwnershipTransferredIterator) Next() bool { } } -func (it *ARMContractOwnershipTransferredIterator) Error() error { +func (it *RMNContractOwnershipTransferredIterator) Error() error { return it.fail } -func (it *ARMContractOwnershipTransferredIterator) Close() error { +func (it *RMNContractOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractOwnershipTransferred struct { +type RMNContractOwnershipTransferred struct { From common.Address To common.Address Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMContractOwnershipTransferredIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNContractOwnershipTransferredIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1482,14 +1482,14 @@ func (_ARMContract *ARMContractFilterer) FilterOwnershipTransferred(opts *bind.F toRule = append(toRule, toItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &ARMContractOwnershipTransferredIterator{contract: _ARMContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &RMNContractOwnershipTransferredIterator{contract: _RMNContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ARMContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1500,7 +1500,7 @@ func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferred(opts *bind.Wa toRule = append(toRule, toItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -1510,8 +1510,8 @@ func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferred(opts *bind.Wa select { case log := <-logs: - event := new(ARMContractOwnershipTransferred) - if err := _ARMContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(RMNContractOwnershipTransferred) + if err := _RMNContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -1532,17 +1532,17 @@ func (_ARMContract *ARMContractFilterer) WatchOwnershipTransferred(opts *bind.Wa }), nil } -func (_ARMContract *ARMContractFilterer) ParseOwnershipTransferred(log types.Log) (*ARMContractOwnershipTransferred, error) { - event := new(ARMContractOwnershipTransferred) - if err := _ARMContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseOwnershipTransferred(log types.Log) (*RMNContractOwnershipTransferred, error) { + event := new(RMNContractOwnershipTransferred) + if err := _RMNContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractPermaBlessedCommitStoreAddedIterator struct { - Event *ARMContractPermaBlessedCommitStoreAdded +type RMNContractPermaBlessedCommitStoreAddedIterator struct { + Event *RMNContractPermaBlessedCommitStoreAdded contract *bind.BoundContract event string @@ -1553,7 +1553,7 @@ type ARMContractPermaBlessedCommitStoreAddedIterator struct { fail error } -func (it *ARMContractPermaBlessedCommitStoreAddedIterator) Next() bool { +func (it *RMNContractPermaBlessedCommitStoreAddedIterator) Next() bool { if it.fail != nil { return false @@ -1562,7 +1562,7 @@ func (it *ARMContractPermaBlessedCommitStoreAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractPermaBlessedCommitStoreAdded) + it.Event = new(RMNContractPermaBlessedCommitStoreAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1577,7 +1577,7 @@ func (it *ARMContractPermaBlessedCommitStoreAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractPermaBlessedCommitStoreAdded) + it.Event = new(RMNContractPermaBlessedCommitStoreAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1592,32 +1592,32 @@ func (it *ARMContractPermaBlessedCommitStoreAddedIterator) Next() bool { } } -func (it *ARMContractPermaBlessedCommitStoreAddedIterator) Error() error { +func (it *RMNContractPermaBlessedCommitStoreAddedIterator) Error() error { return it.fail } -func (it *ARMContractPermaBlessedCommitStoreAddedIterator) Close() error { +func (it *RMNContractPermaBlessedCommitStoreAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractPermaBlessedCommitStoreAdded struct { +type RMNContractPermaBlessedCommitStoreAdded struct { CommitStore common.Address Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterPermaBlessedCommitStoreAdded(opts *bind.FilterOpts) (*ARMContractPermaBlessedCommitStoreAddedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterPermaBlessedCommitStoreAdded(opts *bind.FilterOpts) (*RMNContractPermaBlessedCommitStoreAddedIterator, error) { - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "PermaBlessedCommitStoreAdded") + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "PermaBlessedCommitStoreAdded") if err != nil { return nil, err } - return &ARMContractPermaBlessedCommitStoreAddedIterator{contract: _ARMContract.contract, event: "PermaBlessedCommitStoreAdded", logs: logs, sub: sub}, nil + return &RMNContractPermaBlessedCommitStoreAddedIterator{contract: _RMNContract.contract, event: "PermaBlessedCommitStoreAdded", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchPermaBlessedCommitStoreAdded(opts *bind.WatchOpts, sink chan<- *ARMContractPermaBlessedCommitStoreAdded) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchPermaBlessedCommitStoreAdded(opts *bind.WatchOpts, sink chan<- *RMNContractPermaBlessedCommitStoreAdded) (event.Subscription, error) { - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "PermaBlessedCommitStoreAdded") + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "PermaBlessedCommitStoreAdded") if err != nil { return nil, err } @@ -1627,8 +1627,8 @@ func (_ARMContract *ARMContractFilterer) WatchPermaBlessedCommitStoreAdded(opts select { case log := <-logs: - event := new(ARMContractPermaBlessedCommitStoreAdded) - if err := _ARMContract.contract.UnpackLog(event, "PermaBlessedCommitStoreAdded", log); err != nil { + event := new(RMNContractPermaBlessedCommitStoreAdded) + if err := _RMNContract.contract.UnpackLog(event, "PermaBlessedCommitStoreAdded", log); err != nil { return err } event.Raw = log @@ -1649,17 +1649,17 @@ func (_ARMContract *ARMContractFilterer) WatchPermaBlessedCommitStoreAdded(opts }), nil } -func (_ARMContract *ARMContractFilterer) ParsePermaBlessedCommitStoreAdded(log types.Log) (*ARMContractPermaBlessedCommitStoreAdded, error) { - event := new(ARMContractPermaBlessedCommitStoreAdded) - if err := _ARMContract.contract.UnpackLog(event, "PermaBlessedCommitStoreAdded", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParsePermaBlessedCommitStoreAdded(log types.Log) (*RMNContractPermaBlessedCommitStoreAdded, error) { + event := new(RMNContractPermaBlessedCommitStoreAdded) + if err := _RMNContract.contract.UnpackLog(event, "PermaBlessedCommitStoreAdded", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractPermaBlessedCommitStoreRemovedIterator struct { - Event *ARMContractPermaBlessedCommitStoreRemoved +type RMNContractPermaBlessedCommitStoreRemovedIterator struct { + Event *RMNContractPermaBlessedCommitStoreRemoved contract *bind.BoundContract event string @@ -1670,7 +1670,7 @@ type ARMContractPermaBlessedCommitStoreRemovedIterator struct { fail error } -func (it *ARMContractPermaBlessedCommitStoreRemovedIterator) Next() bool { +func (it *RMNContractPermaBlessedCommitStoreRemovedIterator) Next() bool { if it.fail != nil { return false @@ -1679,7 +1679,7 @@ func (it *ARMContractPermaBlessedCommitStoreRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractPermaBlessedCommitStoreRemoved) + it.Event = new(RMNContractPermaBlessedCommitStoreRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1694,7 +1694,7 @@ func (it *ARMContractPermaBlessedCommitStoreRemovedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractPermaBlessedCommitStoreRemoved) + it.Event = new(RMNContractPermaBlessedCommitStoreRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1709,32 +1709,32 @@ func (it *ARMContractPermaBlessedCommitStoreRemovedIterator) Next() bool { } } -func (it *ARMContractPermaBlessedCommitStoreRemovedIterator) Error() error { +func (it *RMNContractPermaBlessedCommitStoreRemovedIterator) Error() error { return it.fail } -func (it *ARMContractPermaBlessedCommitStoreRemovedIterator) Close() error { +func (it *RMNContractPermaBlessedCommitStoreRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractPermaBlessedCommitStoreRemoved struct { +type RMNContractPermaBlessedCommitStoreRemoved struct { CommitStore common.Address Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterPermaBlessedCommitStoreRemoved(opts *bind.FilterOpts) (*ARMContractPermaBlessedCommitStoreRemovedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterPermaBlessedCommitStoreRemoved(opts *bind.FilterOpts) (*RMNContractPermaBlessedCommitStoreRemovedIterator, error) { - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "PermaBlessedCommitStoreRemoved") + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "PermaBlessedCommitStoreRemoved") if err != nil { return nil, err } - return &ARMContractPermaBlessedCommitStoreRemovedIterator{contract: _ARMContract.contract, event: "PermaBlessedCommitStoreRemoved", logs: logs, sub: sub}, nil + return &RMNContractPermaBlessedCommitStoreRemovedIterator{contract: _RMNContract.contract, event: "PermaBlessedCommitStoreRemoved", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchPermaBlessedCommitStoreRemoved(opts *bind.WatchOpts, sink chan<- *ARMContractPermaBlessedCommitStoreRemoved) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchPermaBlessedCommitStoreRemoved(opts *bind.WatchOpts, sink chan<- *RMNContractPermaBlessedCommitStoreRemoved) (event.Subscription, error) { - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "PermaBlessedCommitStoreRemoved") + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "PermaBlessedCommitStoreRemoved") if err != nil { return nil, err } @@ -1744,8 +1744,8 @@ func (_ARMContract *ARMContractFilterer) WatchPermaBlessedCommitStoreRemoved(opt select { case log := <-logs: - event := new(ARMContractPermaBlessedCommitStoreRemoved) - if err := _ARMContract.contract.UnpackLog(event, "PermaBlessedCommitStoreRemoved", log); err != nil { + event := new(RMNContractPermaBlessedCommitStoreRemoved) + if err := _RMNContract.contract.UnpackLog(event, "PermaBlessedCommitStoreRemoved", log); err != nil { return err } event.Raw = log @@ -1766,17 +1766,17 @@ func (_ARMContract *ARMContractFilterer) WatchPermaBlessedCommitStoreRemoved(opt }), nil } -func (_ARMContract *ARMContractFilterer) ParsePermaBlessedCommitStoreRemoved(log types.Log) (*ARMContractPermaBlessedCommitStoreRemoved, error) { - event := new(ARMContractPermaBlessedCommitStoreRemoved) - if err := _ARMContract.contract.UnpackLog(event, "PermaBlessedCommitStoreRemoved", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParsePermaBlessedCommitStoreRemoved(log types.Log) (*RMNContractPermaBlessedCommitStoreRemoved, error) { + event := new(RMNContractPermaBlessedCommitStoreRemoved) + if err := _RMNContract.contract.UnpackLog(event, "PermaBlessedCommitStoreRemoved", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractSkippedUnvoteToCurseIterator struct { - Event *ARMContractSkippedUnvoteToCurse +type RMNContractSkippedUnvoteToCurseIterator struct { + Event *RMNContractSkippedUnvoteToCurse contract *bind.BoundContract event string @@ -1787,7 +1787,7 @@ type ARMContractSkippedUnvoteToCurseIterator struct { fail error } -func (it *ARMContractSkippedUnvoteToCurseIterator) Next() bool { +func (it *RMNContractSkippedUnvoteToCurseIterator) Next() bool { if it.fail != nil { return false @@ -1796,7 +1796,7 @@ func (it *ARMContractSkippedUnvoteToCurseIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractSkippedUnvoteToCurse) + it.Event = new(RMNContractSkippedUnvoteToCurse) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1811,7 +1811,7 @@ func (it *ARMContractSkippedUnvoteToCurseIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractSkippedUnvoteToCurse) + it.Event = new(RMNContractSkippedUnvoteToCurse) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1826,16 +1826,16 @@ func (it *ARMContractSkippedUnvoteToCurseIterator) Next() bool { } } -func (it *ARMContractSkippedUnvoteToCurseIterator) Error() error { +func (it *RMNContractSkippedUnvoteToCurseIterator) Error() error { return it.fail } -func (it *ARMContractSkippedUnvoteToCurseIterator) Close() error { +func (it *RMNContractSkippedUnvoteToCurseIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractSkippedUnvoteToCurse struct { +type RMNContractSkippedUnvoteToCurse struct { Voter common.Address Subject [16]byte OnchainCursesHash [28]byte @@ -1843,28 +1843,28 @@ type ARMContractSkippedUnvoteToCurse struct { Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterSkippedUnvoteToCurse(opts *bind.FilterOpts, voter []common.Address) (*ARMContractSkippedUnvoteToCurseIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterSkippedUnvoteToCurse(opts *bind.FilterOpts, voter []common.Address) (*RMNContractSkippedUnvoteToCurseIterator, error) { var voterRule []interface{} for _, voterItem := range voter { voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "SkippedUnvoteToCurse", voterRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "SkippedUnvoteToCurse", voterRule) if err != nil { return nil, err } - return &ARMContractSkippedUnvoteToCurseIterator{contract: _ARMContract.contract, event: "SkippedUnvoteToCurse", logs: logs, sub: sub}, nil + return &RMNContractSkippedUnvoteToCurseIterator{contract: _RMNContract.contract, event: "SkippedUnvoteToCurse", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchSkippedUnvoteToCurse(opts *bind.WatchOpts, sink chan<- *ARMContractSkippedUnvoteToCurse, voter []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchSkippedUnvoteToCurse(opts *bind.WatchOpts, sink chan<- *RMNContractSkippedUnvoteToCurse, voter []common.Address) (event.Subscription, error) { var voterRule []interface{} for _, voterItem := range voter { voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "SkippedUnvoteToCurse", voterRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "SkippedUnvoteToCurse", voterRule) if err != nil { return nil, err } @@ -1874,8 +1874,8 @@ func (_ARMContract *ARMContractFilterer) WatchSkippedUnvoteToCurse(opts *bind.Wa select { case log := <-logs: - event := new(ARMContractSkippedUnvoteToCurse) - if err := _ARMContract.contract.UnpackLog(event, "SkippedUnvoteToCurse", log); err != nil { + event := new(RMNContractSkippedUnvoteToCurse) + if err := _RMNContract.contract.UnpackLog(event, "SkippedUnvoteToCurse", log); err != nil { return err } event.Raw = log @@ -1896,17 +1896,17 @@ func (_ARMContract *ARMContractFilterer) WatchSkippedUnvoteToCurse(opts *bind.Wa }), nil } -func (_ARMContract *ARMContractFilterer) ParseSkippedUnvoteToCurse(log types.Log) (*ARMContractSkippedUnvoteToCurse, error) { - event := new(ARMContractSkippedUnvoteToCurse) - if err := _ARMContract.contract.UnpackLog(event, "SkippedUnvoteToCurse", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseSkippedUnvoteToCurse(log types.Log) (*RMNContractSkippedUnvoteToCurse, error) { + event := new(RMNContractSkippedUnvoteToCurse) + if err := _RMNContract.contract.UnpackLog(event, "SkippedUnvoteToCurse", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractTaggedRootBlessVotesResetIterator struct { - Event *ARMContractTaggedRootBlessVotesReset +type RMNContractTaggedRootBlessVotesResetIterator struct { + Event *RMNContractTaggedRootBlessVotesReset contract *bind.BoundContract event string @@ -1917,7 +1917,7 @@ type ARMContractTaggedRootBlessVotesResetIterator struct { fail error } -func (it *ARMContractTaggedRootBlessVotesResetIterator) Next() bool { +func (it *RMNContractTaggedRootBlessVotesResetIterator) Next() bool { if it.fail != nil { return false @@ -1926,7 +1926,7 @@ func (it *ARMContractTaggedRootBlessVotesResetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractTaggedRootBlessVotesReset) + it.Event = new(RMNContractTaggedRootBlessVotesReset) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1941,7 +1941,7 @@ func (it *ARMContractTaggedRootBlessVotesResetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractTaggedRootBlessVotesReset) + it.Event = new(RMNContractTaggedRootBlessVotesReset) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1956,44 +1956,44 @@ func (it *ARMContractTaggedRootBlessVotesResetIterator) Next() bool { } } -func (it *ARMContractTaggedRootBlessVotesResetIterator) Error() error { +func (it *RMNContractTaggedRootBlessVotesResetIterator) Error() error { return it.fail } -func (it *ARMContractTaggedRootBlessVotesResetIterator) Close() error { +func (it *RMNContractTaggedRootBlessVotesResetIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractTaggedRootBlessVotesReset struct { +type RMNContractTaggedRootBlessVotesReset struct { ConfigVersion uint32 TaggedRoot IRMNTaggedRoot WasBlessed bool Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterTaggedRootBlessVotesReset(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractTaggedRootBlessVotesResetIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterTaggedRootBlessVotesReset(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractTaggedRootBlessVotesResetIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "TaggedRootBlessVotesReset", configVersionRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "TaggedRootBlessVotesReset", configVersionRule) if err != nil { return nil, err } - return &ARMContractTaggedRootBlessVotesResetIterator{contract: _ARMContract.contract, event: "TaggedRootBlessVotesReset", logs: logs, sub: sub}, nil + return &RMNContractTaggedRootBlessVotesResetIterator{contract: _RMNContract.contract, event: "TaggedRootBlessVotesReset", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchTaggedRootBlessVotesReset(opts *bind.WatchOpts, sink chan<- *ARMContractTaggedRootBlessVotesReset, configVersion []uint32) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchTaggedRootBlessVotesReset(opts *bind.WatchOpts, sink chan<- *RMNContractTaggedRootBlessVotesReset, configVersion []uint32) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "TaggedRootBlessVotesReset", configVersionRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "TaggedRootBlessVotesReset", configVersionRule) if err != nil { return nil, err } @@ -2003,8 +2003,8 @@ func (_ARMContract *ARMContractFilterer) WatchTaggedRootBlessVotesReset(opts *bi select { case log := <-logs: - event := new(ARMContractTaggedRootBlessVotesReset) - if err := _ARMContract.contract.UnpackLog(event, "TaggedRootBlessVotesReset", log); err != nil { + event := new(RMNContractTaggedRootBlessVotesReset) + if err := _RMNContract.contract.UnpackLog(event, "TaggedRootBlessVotesReset", log); err != nil { return err } event.Raw = log @@ -2025,17 +2025,17 @@ func (_ARMContract *ARMContractFilterer) WatchTaggedRootBlessVotesReset(opts *bi }), nil } -func (_ARMContract *ARMContractFilterer) ParseTaggedRootBlessVotesReset(log types.Log) (*ARMContractTaggedRootBlessVotesReset, error) { - event := new(ARMContractTaggedRootBlessVotesReset) - if err := _ARMContract.contract.UnpackLog(event, "TaggedRootBlessVotesReset", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseTaggedRootBlessVotesReset(log types.Log) (*RMNContractTaggedRootBlessVotesReset, error) { + event := new(RMNContractTaggedRootBlessVotesReset) + if err := _RMNContract.contract.UnpackLog(event, "TaggedRootBlessVotesReset", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractTaggedRootBlessedIterator struct { - Event *ARMContractTaggedRootBlessed +type RMNContractTaggedRootBlessedIterator struct { + Event *RMNContractTaggedRootBlessed contract *bind.BoundContract event string @@ -2046,7 +2046,7 @@ type ARMContractTaggedRootBlessedIterator struct { fail error } -func (it *ARMContractTaggedRootBlessedIterator) Next() bool { +func (it *RMNContractTaggedRootBlessedIterator) Next() bool { if it.fail != nil { return false @@ -2055,7 +2055,7 @@ func (it *ARMContractTaggedRootBlessedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractTaggedRootBlessed) + it.Event = new(RMNContractTaggedRootBlessed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2070,7 +2070,7 @@ func (it *ARMContractTaggedRootBlessedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractTaggedRootBlessed) + it.Event = new(RMNContractTaggedRootBlessed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2085,44 +2085,44 @@ func (it *ARMContractTaggedRootBlessedIterator) Next() bool { } } -func (it *ARMContractTaggedRootBlessedIterator) Error() error { +func (it *RMNContractTaggedRootBlessedIterator) Error() error { return it.fail } -func (it *ARMContractTaggedRootBlessedIterator) Close() error { +func (it *RMNContractTaggedRootBlessedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractTaggedRootBlessed struct { +type RMNContractTaggedRootBlessed struct { ConfigVersion uint32 TaggedRoot IRMNTaggedRoot AccumulatedWeight uint16 Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterTaggedRootBlessed(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractTaggedRootBlessedIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterTaggedRootBlessed(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractTaggedRootBlessedIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "TaggedRootBlessed", configVersionRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "TaggedRootBlessed", configVersionRule) if err != nil { return nil, err } - return &ARMContractTaggedRootBlessedIterator{contract: _ARMContract.contract, event: "TaggedRootBlessed", logs: logs, sub: sub}, nil + return &RMNContractTaggedRootBlessedIterator{contract: _RMNContract.contract, event: "TaggedRootBlessed", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchTaggedRootBlessed(opts *bind.WatchOpts, sink chan<- *ARMContractTaggedRootBlessed, configVersion []uint32) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchTaggedRootBlessed(opts *bind.WatchOpts, sink chan<- *RMNContractTaggedRootBlessed, configVersion []uint32) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { configVersionRule = append(configVersionRule, configVersionItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "TaggedRootBlessed", configVersionRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "TaggedRootBlessed", configVersionRule) if err != nil { return nil, err } @@ -2132,8 +2132,8 @@ func (_ARMContract *ARMContractFilterer) WatchTaggedRootBlessed(opts *bind.Watch select { case log := <-logs: - event := new(ARMContractTaggedRootBlessed) - if err := _ARMContract.contract.UnpackLog(event, "TaggedRootBlessed", log); err != nil { + event := new(RMNContractTaggedRootBlessed) + if err := _RMNContract.contract.UnpackLog(event, "TaggedRootBlessed", log); err != nil { return err } event.Raw = log @@ -2154,17 +2154,17 @@ func (_ARMContract *ARMContractFilterer) WatchTaggedRootBlessed(opts *bind.Watch }), nil } -func (_ARMContract *ARMContractFilterer) ParseTaggedRootBlessed(log types.Log) (*ARMContractTaggedRootBlessed, error) { - event := new(ARMContractTaggedRootBlessed) - if err := _ARMContract.contract.UnpackLog(event, "TaggedRootBlessed", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseTaggedRootBlessed(log types.Log) (*RMNContractTaggedRootBlessed, error) { + event := new(RMNContractTaggedRootBlessed) + if err := _RMNContract.contract.UnpackLog(event, "TaggedRootBlessed", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractUnvotedToCurseIterator struct { - Event *ARMContractUnvotedToCurse +type RMNContractUnvotedToCurseIterator struct { + Event *RMNContractUnvotedToCurse contract *bind.BoundContract event string @@ -2175,7 +2175,7 @@ type ARMContractUnvotedToCurseIterator struct { fail error } -func (it *ARMContractUnvotedToCurseIterator) Next() bool { +func (it *RMNContractUnvotedToCurseIterator) Next() bool { if it.fail != nil { return false @@ -2184,7 +2184,7 @@ func (it *ARMContractUnvotedToCurseIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractUnvotedToCurse) + it.Event = new(RMNContractUnvotedToCurse) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2199,7 +2199,7 @@ func (it *ARMContractUnvotedToCurseIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractUnvotedToCurse) + it.Event = new(RMNContractUnvotedToCurse) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2214,16 +2214,16 @@ func (it *ARMContractUnvotedToCurseIterator) Next() bool { } } -func (it *ARMContractUnvotedToCurseIterator) Error() error { +func (it *RMNContractUnvotedToCurseIterator) Error() error { return it.fail } -func (it *ARMContractUnvotedToCurseIterator) Close() error { +func (it *RMNContractUnvotedToCurseIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractUnvotedToCurse struct { +type RMNContractUnvotedToCurse struct { ConfigVersion uint32 Voter common.Address Subject [16]byte @@ -2233,7 +2233,7 @@ type ARMContractUnvotedToCurse struct { Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterUnvotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractUnvotedToCurseIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterUnvotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractUnvotedToCurseIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -2244,14 +2244,14 @@ func (_ARMContract *ARMContractFilterer) FilterUnvotedToCurse(opts *bind.FilterO voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "UnvotedToCurse", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "UnvotedToCurse", configVersionRule, voterRule) if err != nil { return nil, err } - return &ARMContractUnvotedToCurseIterator{contract: _ARMContract.contract, event: "UnvotedToCurse", logs: logs, sub: sub}, nil + return &RMNContractUnvotedToCurseIterator{contract: _RMNContract.contract, event: "UnvotedToCurse", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchUnvotedToCurse(opts *bind.WatchOpts, sink chan<- *ARMContractUnvotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchUnvotedToCurse(opts *bind.WatchOpts, sink chan<- *RMNContractUnvotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -2262,7 +2262,7 @@ func (_ARMContract *ARMContractFilterer) WatchUnvotedToCurse(opts *bind.WatchOpt voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "UnvotedToCurse", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "UnvotedToCurse", configVersionRule, voterRule) if err != nil { return nil, err } @@ -2272,8 +2272,8 @@ func (_ARMContract *ARMContractFilterer) WatchUnvotedToCurse(opts *bind.WatchOpt select { case log := <-logs: - event := new(ARMContractUnvotedToCurse) - if err := _ARMContract.contract.UnpackLog(event, "UnvotedToCurse", log); err != nil { + event := new(RMNContractUnvotedToCurse) + if err := _RMNContract.contract.UnpackLog(event, "UnvotedToCurse", log); err != nil { return err } event.Raw = log @@ -2294,17 +2294,17 @@ func (_ARMContract *ARMContractFilterer) WatchUnvotedToCurse(opts *bind.WatchOpt }), nil } -func (_ARMContract *ARMContractFilterer) ParseUnvotedToCurse(log types.Log) (*ARMContractUnvotedToCurse, error) { - event := new(ARMContractUnvotedToCurse) - if err := _ARMContract.contract.UnpackLog(event, "UnvotedToCurse", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseUnvotedToCurse(log types.Log) (*RMNContractUnvotedToCurse, error) { + event := new(RMNContractUnvotedToCurse) + if err := _RMNContract.contract.UnpackLog(event, "UnvotedToCurse", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractVotedToBlessIterator struct { - Event *ARMContractVotedToBless +type RMNContractVotedToBlessIterator struct { + Event *RMNContractVotedToBless contract *bind.BoundContract event string @@ -2315,7 +2315,7 @@ type ARMContractVotedToBlessIterator struct { fail error } -func (it *ARMContractVotedToBlessIterator) Next() bool { +func (it *RMNContractVotedToBlessIterator) Next() bool { if it.fail != nil { return false @@ -2324,7 +2324,7 @@ func (it *ARMContractVotedToBlessIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractVotedToBless) + it.Event = new(RMNContractVotedToBless) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2339,7 +2339,7 @@ func (it *ARMContractVotedToBlessIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractVotedToBless) + it.Event = new(RMNContractVotedToBless) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2354,16 +2354,16 @@ func (it *ARMContractVotedToBlessIterator) Next() bool { } } -func (it *ARMContractVotedToBlessIterator) Error() error { +func (it *RMNContractVotedToBlessIterator) Error() error { return it.fail } -func (it *ARMContractVotedToBlessIterator) Close() error { +func (it *RMNContractVotedToBlessIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractVotedToBless struct { +type RMNContractVotedToBless struct { ConfigVersion uint32 Voter common.Address TaggedRoot IRMNTaggedRoot @@ -2371,7 +2371,7 @@ type ARMContractVotedToBless struct { Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractVotedToBlessIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractVotedToBlessIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -2382,14 +2382,14 @@ func (_ARMContract *ARMContractFilterer) FilterVotedToBless(opts *bind.FilterOpt voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "VotedToBless", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "VotedToBless", configVersionRule, voterRule) if err != nil { return nil, err } - return &ARMContractVotedToBlessIterator{contract: _ARMContract.contract, event: "VotedToBless", logs: logs, sub: sub}, nil + return &RMNContractVotedToBlessIterator{contract: _RMNContract.contract, event: "VotedToBless", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchVotedToBless(opts *bind.WatchOpts, sink chan<- *ARMContractVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchVotedToBless(opts *bind.WatchOpts, sink chan<- *RMNContractVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -2400,7 +2400,7 @@ func (_ARMContract *ARMContractFilterer) WatchVotedToBless(opts *bind.WatchOpts, voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "VotedToBless", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "VotedToBless", configVersionRule, voterRule) if err != nil { return nil, err } @@ -2410,8 +2410,8 @@ func (_ARMContract *ARMContractFilterer) WatchVotedToBless(opts *bind.WatchOpts, select { case log := <-logs: - event := new(ARMContractVotedToBless) - if err := _ARMContract.contract.UnpackLog(event, "VotedToBless", log); err != nil { + event := new(RMNContractVotedToBless) + if err := _RMNContract.contract.UnpackLog(event, "VotedToBless", log); err != nil { return err } event.Raw = log @@ -2432,17 +2432,17 @@ func (_ARMContract *ARMContractFilterer) WatchVotedToBless(opts *bind.WatchOpts, }), nil } -func (_ARMContract *ARMContractFilterer) ParseVotedToBless(log types.Log) (*ARMContractVotedToBless, error) { - event := new(ARMContractVotedToBless) - if err := _ARMContract.contract.UnpackLog(event, "VotedToBless", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseVotedToBless(log types.Log) (*RMNContractVotedToBless, error) { + event := new(RMNContractVotedToBless) + if err := _RMNContract.contract.UnpackLog(event, "VotedToBless", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMContractVotedToCurseIterator struct { - Event *ARMContractVotedToCurse +type RMNContractVotedToCurseIterator struct { + Event *RMNContractVotedToCurse contract *bind.BoundContract event string @@ -2453,7 +2453,7 @@ type ARMContractVotedToCurseIterator struct { fail error } -func (it *ARMContractVotedToCurseIterator) Next() bool { +func (it *RMNContractVotedToCurseIterator) Next() bool { if it.fail != nil { return false @@ -2462,7 +2462,7 @@ func (it *ARMContractVotedToCurseIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMContractVotedToCurse) + it.Event = new(RMNContractVotedToCurse) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2477,7 +2477,7 @@ func (it *ARMContractVotedToCurseIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMContractVotedToCurse) + it.Event = new(RMNContractVotedToCurse) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2492,16 +2492,16 @@ func (it *ARMContractVotedToCurseIterator) Next() bool { } } -func (it *ARMContractVotedToCurseIterator) Error() error { +func (it *RMNContractVotedToCurseIterator) Error() error { return it.fail } -func (it *ARMContractVotedToCurseIterator) Close() error { +func (it *RMNContractVotedToCurseIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMContractVotedToCurse struct { +type RMNContractVotedToCurse struct { ConfigVersion uint32 Voter common.Address Subject [16]byte @@ -2513,7 +2513,7 @@ type ARMContractVotedToCurse struct { Raw types.Log } -func (_ARMContract *ARMContractFilterer) FilterVotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractVotedToCurseIterator, error) { +func (_RMNContract *RMNContractFilterer) FilterVotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractVotedToCurseIterator, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -2524,14 +2524,14 @@ func (_ARMContract *ARMContractFilterer) FilterVotedToCurse(opts *bind.FilterOpt voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.FilterLogs(opts, "VotedToCurse", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.FilterLogs(opts, "VotedToCurse", configVersionRule, voterRule) if err != nil { return nil, err } - return &ARMContractVotedToCurseIterator{contract: _ARMContract.contract, event: "VotedToCurse", logs: logs, sub: sub}, nil + return &RMNContractVotedToCurseIterator{contract: _RMNContract.contract, event: "VotedToCurse", logs: logs, sub: sub}, nil } -func (_ARMContract *ARMContractFilterer) WatchVotedToCurse(opts *bind.WatchOpts, sink chan<- *ARMContractVotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) { +func (_RMNContract *RMNContractFilterer) WatchVotedToCurse(opts *bind.WatchOpts, sink chan<- *RMNContractVotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) { var configVersionRule []interface{} for _, configVersionItem := range configVersion { @@ -2542,7 +2542,7 @@ func (_ARMContract *ARMContractFilterer) WatchVotedToCurse(opts *bind.WatchOpts, voterRule = append(voterRule, voterItem) } - logs, sub, err := _ARMContract.contract.WatchLogs(opts, "VotedToCurse", configVersionRule, voterRule) + logs, sub, err := _RMNContract.contract.WatchLogs(opts, "VotedToCurse", configVersionRule, voterRule) if err != nil { return nil, err } @@ -2552,8 +2552,8 @@ func (_ARMContract *ARMContractFilterer) WatchVotedToCurse(opts *bind.WatchOpts, select { case log := <-logs: - event := new(ARMContractVotedToCurse) - if err := _ARMContract.contract.UnpackLog(event, "VotedToCurse", log); err != nil { + event := new(RMNContractVotedToCurse) + if err := _RMNContract.contract.UnpackLog(event, "VotedToCurse", log); err != nil { return err } event.Raw = log @@ -2574,9 +2574,9 @@ func (_ARMContract *ARMContractFilterer) WatchVotedToCurse(opts *bind.WatchOpts, }), nil } -func (_ARMContract *ARMContractFilterer) ParseVotedToCurse(log types.Log) (*ARMContractVotedToCurse, error) { - event := new(ARMContractVotedToCurse) - if err := _ARMContract.contract.UnpackLog(event, "VotedToCurse", log); err != nil { +func (_RMNContract *RMNContractFilterer) ParseVotedToCurse(log types.Log) (*RMNContractVotedToCurse, error) { + event := new(RMNContractVotedToCurse) + if err := _RMNContract.contract.UnpackLog(event, "VotedToCurse", log); err != nil { return nil, err } event.Raw = log @@ -2600,109 +2600,109 @@ type GetCurseProgress struct { Cursed bool } -func (_ARMContract *ARMContract) ParseLog(log types.Log) (generated.AbigenLog, error) { +func (_RMNContract *RMNContract) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _ARMContract.abi.Events["AlreadyBlessed"].ID: - return _ARMContract.ParseAlreadyBlessed(log) - case _ARMContract.abi.Events["AlreadyVotedToBless"].ID: - return _ARMContract.ParseAlreadyVotedToBless(log) - case _ARMContract.abi.Events["ConfigSet"].ID: - return _ARMContract.ParseConfigSet(log) - case _ARMContract.abi.Events["CurseLifted"].ID: - return _ARMContract.ParseCurseLifted(log) - case _ARMContract.abi.Events["Cursed"].ID: - return _ARMContract.ParseCursed(log) - case _ARMContract.abi.Events["OwnershipTransferRequested"].ID: - return _ARMContract.ParseOwnershipTransferRequested(log) - case _ARMContract.abi.Events["OwnershipTransferred"].ID: - return _ARMContract.ParseOwnershipTransferred(log) - case _ARMContract.abi.Events["PermaBlessedCommitStoreAdded"].ID: - return _ARMContract.ParsePermaBlessedCommitStoreAdded(log) - case _ARMContract.abi.Events["PermaBlessedCommitStoreRemoved"].ID: - return _ARMContract.ParsePermaBlessedCommitStoreRemoved(log) - case _ARMContract.abi.Events["SkippedUnvoteToCurse"].ID: - return _ARMContract.ParseSkippedUnvoteToCurse(log) - case _ARMContract.abi.Events["TaggedRootBlessVotesReset"].ID: - return _ARMContract.ParseTaggedRootBlessVotesReset(log) - case _ARMContract.abi.Events["TaggedRootBlessed"].ID: - return _ARMContract.ParseTaggedRootBlessed(log) - case _ARMContract.abi.Events["UnvotedToCurse"].ID: - return _ARMContract.ParseUnvotedToCurse(log) - case _ARMContract.abi.Events["VotedToBless"].ID: - return _ARMContract.ParseVotedToBless(log) - case _ARMContract.abi.Events["VotedToCurse"].ID: - return _ARMContract.ParseVotedToCurse(log) + case _RMNContract.abi.Events["AlreadyBlessed"].ID: + return _RMNContract.ParseAlreadyBlessed(log) + case _RMNContract.abi.Events["AlreadyVotedToBless"].ID: + return _RMNContract.ParseAlreadyVotedToBless(log) + case _RMNContract.abi.Events["ConfigSet"].ID: + return _RMNContract.ParseConfigSet(log) + case _RMNContract.abi.Events["CurseLifted"].ID: + return _RMNContract.ParseCurseLifted(log) + case _RMNContract.abi.Events["Cursed"].ID: + return _RMNContract.ParseCursed(log) + case _RMNContract.abi.Events["OwnershipTransferRequested"].ID: + return _RMNContract.ParseOwnershipTransferRequested(log) + case _RMNContract.abi.Events["OwnershipTransferred"].ID: + return _RMNContract.ParseOwnershipTransferred(log) + case _RMNContract.abi.Events["PermaBlessedCommitStoreAdded"].ID: + return _RMNContract.ParsePermaBlessedCommitStoreAdded(log) + case _RMNContract.abi.Events["PermaBlessedCommitStoreRemoved"].ID: + return _RMNContract.ParsePermaBlessedCommitStoreRemoved(log) + case _RMNContract.abi.Events["SkippedUnvoteToCurse"].ID: + return _RMNContract.ParseSkippedUnvoteToCurse(log) + case _RMNContract.abi.Events["TaggedRootBlessVotesReset"].ID: + return _RMNContract.ParseTaggedRootBlessVotesReset(log) + case _RMNContract.abi.Events["TaggedRootBlessed"].ID: + return _RMNContract.ParseTaggedRootBlessed(log) + case _RMNContract.abi.Events["UnvotedToCurse"].ID: + return _RMNContract.ParseUnvotedToCurse(log) + case _RMNContract.abi.Events["VotedToBless"].ID: + return _RMNContract.ParseVotedToBless(log) + case _RMNContract.abi.Events["VotedToCurse"].ID: + return _RMNContract.ParseVotedToCurse(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (ARMContractAlreadyBlessed) Topic() common.Hash { +func (RMNContractAlreadyBlessed) Topic() common.Hash { return common.HexToHash("0x274d6d5b916b0a53974b7ab86c844b97a2e03a60f658cd9a4b1c028b604d7bf1") } -func (ARMContractAlreadyVotedToBless) Topic() common.Hash { +func (RMNContractAlreadyVotedToBless) Topic() common.Hash { return common.HexToHash("0x6dfbb745226fa630aeb1b9557d17d508ddb789a04f0cb873ec16e58beb8beead") } -func (ARMContractConfigSet) Topic() common.Hash { +func (RMNContractConfigSet) Topic() common.Hash { return common.HexToHash("0x8c49fda8177c5c8c768eb39634bc6773695c7181711537b822451c12b2efd2a9") } -func (ARMContractCurseLifted) Topic() common.Hash { +func (RMNContractCurseLifted) Topic() common.Hash { return common.HexToHash("0x65d0e78c3625f0956f58610cf0fb157eaf627683258875ef29af2f71d25ac8fd") } -func (ARMContractCursed) Topic() common.Hash { +func (RMNContractCursed) Topic() common.Hash { return common.HexToHash("0xcfdbfd8ce9a56b5f7c202c0e102184d24f47ca87121dc165063fc4c290957bde") } -func (ARMContractOwnershipTransferRequested) Topic() common.Hash { +func (RMNContractOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } -func (ARMContractOwnershipTransferred) Topic() common.Hash { +func (RMNContractOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (ARMContractPermaBlessedCommitStoreAdded) Topic() common.Hash { +func (RMNContractPermaBlessedCommitStoreAdded) Topic() common.Hash { return common.HexToHash("0x66b4b4752c65ae8cd2f3a0a48c7dc8b2118c60d5ea15514992eb2ddf56c9cb15") } -func (ARMContractPermaBlessedCommitStoreRemoved) Topic() common.Hash { +func (RMNContractPermaBlessedCommitStoreRemoved) Topic() common.Hash { return common.HexToHash("0xdca892154bbc36d0c05ccd01b3d0411875cb1b841fcdeebb384e5d0d6eb06b44") } -func (ARMContractSkippedUnvoteToCurse) Topic() common.Hash { +func (RMNContractSkippedUnvoteToCurse) Topic() common.Hash { return common.HexToHash("0xbabb0d7099e6ca14a29fad2a2cfb4fda2bd30f97cb3c27e546174bfb4277c1cc") } -func (ARMContractTaggedRootBlessVotesReset) Topic() common.Hash { +func (RMNContractTaggedRootBlessVotesReset) Topic() common.Hash { return common.HexToHash("0x7d15a6eebaa019ea7d5b7d38937c51ebd3befbfdf51bb630a694fd28635bbcba") } -func (ARMContractTaggedRootBlessed) Topic() common.Hash { +func (RMNContractTaggedRootBlessed) Topic() common.Hash { return common.HexToHash("0x8257378aa73bf8e4ada848713526584a3dcee0fd3db3beed7397f7a7f5067cc9") } -func (ARMContractUnvotedToCurse) Topic() common.Hash { +func (RMNContractUnvotedToCurse) Topic() common.Hash { return common.HexToHash("0xa96a155bd67c927a6c056befbd979b78465e2b2f1276bf7d4e90a31d4f430aa8") } -func (ARMContractVotedToBless) Topic() common.Hash { +func (RMNContractVotedToBless) Topic() common.Hash { return common.HexToHash("0x2a08a2bd2798f0aae9a843f0f4ad4de488c1b3d5f04049940cfed736ad69fb97") } -func (ARMContractVotedToCurse) Topic() common.Hash { +func (RMNContractVotedToCurse) Topic() common.Hash { return common.HexToHash("0x8137bc8a8d712aaa27bfc6506d5566ac405618bd53f9831b8ca6b6fe5442ee7a") } -func (_ARMContract *ARMContract) Address() common.Address { - return _ARMContract.address +func (_RMNContract *RMNContract) Address() common.Address { + return _RMNContract.address } -type ARMContractInterface interface { +type RMNContractInterface interface { GetBlessProgress(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (GetBlessProgress, error) @@ -2753,95 +2753,95 @@ type ARMContractInterface interface { VoteToCurse(opts *bind.TransactOpts, curseId [16]byte, subjects [][16]byte) (*types.Transaction, error) - FilterAlreadyBlessed(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractAlreadyBlessedIterator, error) + FilterAlreadyBlessed(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractAlreadyBlessedIterator, error) - WatchAlreadyBlessed(opts *bind.WatchOpts, sink chan<- *ARMContractAlreadyBlessed, configVersion []uint32, voter []common.Address) (event.Subscription, error) + WatchAlreadyBlessed(opts *bind.WatchOpts, sink chan<- *RMNContractAlreadyBlessed, configVersion []uint32, voter []common.Address) (event.Subscription, error) - ParseAlreadyBlessed(log types.Log) (*ARMContractAlreadyBlessed, error) + ParseAlreadyBlessed(log types.Log) (*RMNContractAlreadyBlessed, error) - FilterAlreadyVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractAlreadyVotedToBlessIterator, error) + FilterAlreadyVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractAlreadyVotedToBlessIterator, error) - WatchAlreadyVotedToBless(opts *bind.WatchOpts, sink chan<- *ARMContractAlreadyVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) + WatchAlreadyVotedToBless(opts *bind.WatchOpts, sink chan<- *RMNContractAlreadyVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) - ParseAlreadyVotedToBless(log types.Log) (*ARMContractAlreadyVotedToBless, error) + ParseAlreadyVotedToBless(log types.Log) (*RMNContractAlreadyVotedToBless, error) - FilterConfigSet(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractConfigSetIterator, error) + FilterConfigSet(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractConfigSetIterator, error) - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *ARMContractConfigSet, configVersion []uint32) (event.Subscription, error) + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNContractConfigSet, configVersion []uint32) (event.Subscription, error) - ParseConfigSet(log types.Log) (*ARMContractConfigSet, error) + ParseConfigSet(log types.Log) (*RMNContractConfigSet, error) - FilterCurseLifted(opts *bind.FilterOpts) (*ARMContractCurseLiftedIterator, error) + FilterCurseLifted(opts *bind.FilterOpts) (*RMNContractCurseLiftedIterator, error) - WatchCurseLifted(opts *bind.WatchOpts, sink chan<- *ARMContractCurseLifted) (event.Subscription, error) + WatchCurseLifted(opts *bind.WatchOpts, sink chan<- *RMNContractCurseLifted) (event.Subscription, error) - ParseCurseLifted(log types.Log) (*ARMContractCurseLifted, error) + ParseCurseLifted(log types.Log) (*RMNContractCurseLifted, error) - FilterCursed(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractCursedIterator, error) + FilterCursed(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractCursedIterator, error) - WatchCursed(opts *bind.WatchOpts, sink chan<- *ARMContractCursed, configVersion []uint32) (event.Subscription, error) + WatchCursed(opts *bind.WatchOpts, sink chan<- *RMNContractCursed, configVersion []uint32) (event.Subscription, error) - ParseCursed(log types.Log) (*ARMContractCursed, error) + ParseCursed(log types.Log) (*RMNContractCursed, error) - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMContractOwnershipTransferRequestedIterator, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNContractOwnershipTransferRequestedIterator, error) - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ARMContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferRequested(log types.Log) (*ARMContractOwnershipTransferRequested, error) + ParseOwnershipTransferRequested(log types.Log) (*RMNContractOwnershipTransferRequested, error) - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMContractOwnershipTransferredIterator, error) + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNContractOwnershipTransferredIterator, error) - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ARMContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferred(log types.Log) (*ARMContractOwnershipTransferred, error) + ParseOwnershipTransferred(log types.Log) (*RMNContractOwnershipTransferred, error) - FilterPermaBlessedCommitStoreAdded(opts *bind.FilterOpts) (*ARMContractPermaBlessedCommitStoreAddedIterator, error) + FilterPermaBlessedCommitStoreAdded(opts *bind.FilterOpts) (*RMNContractPermaBlessedCommitStoreAddedIterator, error) - WatchPermaBlessedCommitStoreAdded(opts *bind.WatchOpts, sink chan<- *ARMContractPermaBlessedCommitStoreAdded) (event.Subscription, error) + WatchPermaBlessedCommitStoreAdded(opts *bind.WatchOpts, sink chan<- *RMNContractPermaBlessedCommitStoreAdded) (event.Subscription, error) - ParsePermaBlessedCommitStoreAdded(log types.Log) (*ARMContractPermaBlessedCommitStoreAdded, error) + ParsePermaBlessedCommitStoreAdded(log types.Log) (*RMNContractPermaBlessedCommitStoreAdded, error) - FilterPermaBlessedCommitStoreRemoved(opts *bind.FilterOpts) (*ARMContractPermaBlessedCommitStoreRemovedIterator, error) + FilterPermaBlessedCommitStoreRemoved(opts *bind.FilterOpts) (*RMNContractPermaBlessedCommitStoreRemovedIterator, error) - WatchPermaBlessedCommitStoreRemoved(opts *bind.WatchOpts, sink chan<- *ARMContractPermaBlessedCommitStoreRemoved) (event.Subscription, error) + WatchPermaBlessedCommitStoreRemoved(opts *bind.WatchOpts, sink chan<- *RMNContractPermaBlessedCommitStoreRemoved) (event.Subscription, error) - ParsePermaBlessedCommitStoreRemoved(log types.Log) (*ARMContractPermaBlessedCommitStoreRemoved, error) + ParsePermaBlessedCommitStoreRemoved(log types.Log) (*RMNContractPermaBlessedCommitStoreRemoved, error) - FilterSkippedUnvoteToCurse(opts *bind.FilterOpts, voter []common.Address) (*ARMContractSkippedUnvoteToCurseIterator, error) + FilterSkippedUnvoteToCurse(opts *bind.FilterOpts, voter []common.Address) (*RMNContractSkippedUnvoteToCurseIterator, error) - WatchSkippedUnvoteToCurse(opts *bind.WatchOpts, sink chan<- *ARMContractSkippedUnvoteToCurse, voter []common.Address) (event.Subscription, error) + WatchSkippedUnvoteToCurse(opts *bind.WatchOpts, sink chan<- *RMNContractSkippedUnvoteToCurse, voter []common.Address) (event.Subscription, error) - ParseSkippedUnvoteToCurse(log types.Log) (*ARMContractSkippedUnvoteToCurse, error) + ParseSkippedUnvoteToCurse(log types.Log) (*RMNContractSkippedUnvoteToCurse, error) - FilterTaggedRootBlessVotesReset(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractTaggedRootBlessVotesResetIterator, error) + FilterTaggedRootBlessVotesReset(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractTaggedRootBlessVotesResetIterator, error) - WatchTaggedRootBlessVotesReset(opts *bind.WatchOpts, sink chan<- *ARMContractTaggedRootBlessVotesReset, configVersion []uint32) (event.Subscription, error) + WatchTaggedRootBlessVotesReset(opts *bind.WatchOpts, sink chan<- *RMNContractTaggedRootBlessVotesReset, configVersion []uint32) (event.Subscription, error) - ParseTaggedRootBlessVotesReset(log types.Log) (*ARMContractTaggedRootBlessVotesReset, error) + ParseTaggedRootBlessVotesReset(log types.Log) (*RMNContractTaggedRootBlessVotesReset, error) - FilterTaggedRootBlessed(opts *bind.FilterOpts, configVersion []uint32) (*ARMContractTaggedRootBlessedIterator, error) + FilterTaggedRootBlessed(opts *bind.FilterOpts, configVersion []uint32) (*RMNContractTaggedRootBlessedIterator, error) - WatchTaggedRootBlessed(opts *bind.WatchOpts, sink chan<- *ARMContractTaggedRootBlessed, configVersion []uint32) (event.Subscription, error) + WatchTaggedRootBlessed(opts *bind.WatchOpts, sink chan<- *RMNContractTaggedRootBlessed, configVersion []uint32) (event.Subscription, error) - ParseTaggedRootBlessed(log types.Log) (*ARMContractTaggedRootBlessed, error) + ParseTaggedRootBlessed(log types.Log) (*RMNContractTaggedRootBlessed, error) - FilterUnvotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractUnvotedToCurseIterator, error) + FilterUnvotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractUnvotedToCurseIterator, error) - WatchUnvotedToCurse(opts *bind.WatchOpts, sink chan<- *ARMContractUnvotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) + WatchUnvotedToCurse(opts *bind.WatchOpts, sink chan<- *RMNContractUnvotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) - ParseUnvotedToCurse(log types.Log) (*ARMContractUnvotedToCurse, error) + ParseUnvotedToCurse(log types.Log) (*RMNContractUnvotedToCurse, error) - FilterVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractVotedToBlessIterator, error) + FilterVotedToBless(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractVotedToBlessIterator, error) - WatchVotedToBless(opts *bind.WatchOpts, sink chan<- *ARMContractVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) + WatchVotedToBless(opts *bind.WatchOpts, sink chan<- *RMNContractVotedToBless, configVersion []uint32, voter []common.Address) (event.Subscription, error) - ParseVotedToBless(log types.Log) (*ARMContractVotedToBless, error) + ParseVotedToBless(log types.Log) (*RMNContractVotedToBless, error) - FilterVotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*ARMContractVotedToCurseIterator, error) + FilterVotedToCurse(opts *bind.FilterOpts, configVersion []uint32, voter []common.Address) (*RMNContractVotedToCurseIterator, error) - WatchVotedToCurse(opts *bind.WatchOpts, sink chan<- *ARMContractVotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) + WatchVotedToCurse(opts *bind.WatchOpts, sink chan<- *RMNContractVotedToCurse, configVersion []uint32, voter []common.Address) (event.Subscription, error) - ParseVotedToCurse(log types.Log) (*ARMContractVotedToCurse, error) + ParseVotedToCurse(log types.Log) (*RMNContractVotedToCurse, error) ParseLog(log types.Log) (generated.AbigenLog, error) diff --git a/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go b/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go new file mode 100644 index 00000000000..18f1ca488b3 --- /dev/null +++ b/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go @@ -0,0 +1,1508 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package rmn_home + +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 RMNHomeDynamicConfig struct { + SourceChains []RMNHomeSourceChain + OffchainConfig []byte +} + +type RMNHomeNode struct { + PeerId [32]byte + OffchainPublicKey [32]byte +} + +type RMNHomeSourceChain struct { + ChainSelector uint64 + MinObservers uint64 + ObserverNodesBitmap *big.Int +} + +type RMNHomeStaticConfig struct { + Nodes []RMNHomeNode + OffchainConfig []byte +} + +type RMNHomeVersionedConfig struct { + Version uint32 + ConfigDigest [32]byte + StaticConfig RMNHomeStaticConfig + DynamicConfig RMNHomeDynamicConfig +} + +var RMNHomeMetaData = &bind.MetaData{ + ABI: "[{\"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\":\"MinObserversTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOpStateTransitionNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfBoundsNodesLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfBoundsObserverNodeIndex\",\"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\":\"minObservers\",\"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\":\"minObservers\",\"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\":\"minObservers\",\"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\":\"minObservers\",\"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\":\"minObservers\",\"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\":\"minObservers\",\"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\":\"minObservers\",\"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: "0x6080604052600e80546001600160401b03191690553480156200002157600080fd5b503380600081620000795760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000ac57620000ac81620000b5565b50505062000160565b336001600160a01b038216036200010f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000070565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6128f180620001706000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c80636dd5b69d1161008c5780638c76967f116100665780638c76967f146101d45780638da5cb5b146101e7578063f2fde38b1461020f578063fb4022d41461022257600080fd5b80636dd5b69d14610196578063736be802146101b757806379ba5097146101cc57600080fd5b80633567e6b4116100bd5780633567e6b41461015b57806338354c5c14610178578063635079561461018057600080fd5b8063118dbac5146100e4578063123e65db1461010a578063181f5a7714610112575b600080fd5b6100f76100f23660046118e4565b610235565b6040519081526020015b60405180910390f35b6100f7610418565b61014e6040518060400160405280601181526020017f524d4e486f6d6520312e362e302d64657600000000000000000000000000000081525081565b60405161010191906119bf565b610163610457565b60408051928352602083019190915201610101565b6100f76104d8565b6101886104f7565b604051610101929190611b2a565b6101a96101a4366004611b4f565b610a79565b604051610101929190611b68565b6101ca6101c5366004611b8c565b610d5d565b005b6101ca610e79565b6101ca6101e2366004611bd1565b610f76565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610101565b6101ca61021d366004611bf3565b611189565b6101ca610230366004611b4f565b61119d565b600061023f6112b9565b61025961024b85611da5565b61025485611ea6565b61133c565b60006102636104d8565b90508281146102ad576040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101829052602481018490526044015b60405180910390fd5b80156102df5760405183907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a25b600e80546000919082906102f89063ffffffff16611fbb565b91906101000a81548163ffffffff021916908363ffffffff160217905590506103408660405160200161032b9190612166565b604051602081830303815290604052826114b4565b600e54909350600090600290640100000000900463ffffffff1660011863ffffffff166002811061037357610373612179565b600602016001810185905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8416178155905086600282016103bd82826123c6565b50869050600482016103cf82826125c5565b905050837ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf083898960405161040693929190612809565b60405180910390a25050509392505050565b60006002610434600e5463ffffffff6401000000009091041690565b63ffffffff166002811061044a5761044a612179565b6006020160010154905090565b6000806002610474600e5463ffffffff6401000000009091041690565b63ffffffff166002811061048a5761048a612179565b600602016001015460026104b2600e54600163ffffffff640100000000909204919091161890565b63ffffffff16600281106104c8576104c8612179565b6006020160010154915091509091565b600e54600090600290640100000000900463ffffffff16600118610434565b6104ff611866565b610507611866565b60006002610523600e5463ffffffff6401000000009091041690565b63ffffffff166002811061053957610539612179565b6040805160808101825260069290920292909201805463ffffffff16825260018101546020808401919091528351600283018054606093810283018401875282870181815295969495948701949293919284929091849160009085015b828210156105dc57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610596565b5050505081526020016001820180546105f49061220d565b80601f01602080910402602001604051908101604052809291908181526020018280546106209061220d565b801561066d5780601f106106425761010080835404028352916020019161066d565b820191906000526020600020905b81548152906001019060200180831161065057829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561070f5760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff80821685526801000000000000000090910416838501526001908101549183019190915290835290920191016106af565b5050505081526020016001820180546107279061220d565b80601f01602080910402602001604051908101604052809291908181526020018280546107539061220d565b80156107a05780601f10610775576101008083540402835291602001916107a0565b820191906000526020600020905b81548152906001019060200180831161078357829003601f168201915b505050919092525050509052506020810151909150156107be578092505b600e54600090600290640100000000900463ffffffff1660011863ffffffff16600281106107ee576107ee612179565b6040805160808101825260069290920292909201805463ffffffff16825260018101546020808401919091528351600283018054606093810283018401875282870181815295969495948701949293919284929091849160009085015b828210156108915783829060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061084b565b5050505081526020016001820180546108a99061220d565b80601f01602080910402602001604051908101604052809291908181526020018280546108d59061220d565b80156109225780601f106108f757610100808354040283529160200191610922565b820191906000526020600020905b81548152906001019060200180831161090557829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b828210156109c45760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff8082168552680100000000000000009091041683850152600190810154918301919091529083529092019101610964565b5050505081526020016001820180546109dc9061220d565b80601f0160208091040260200160405190810160405280929190818152602001828054610a089061220d565b8015610a555780601f10610a2a57610100808354040283529160200191610a55565b820191906000526020600020905b815481529060010190602001808311610a3857829003601f168201915b50505091909252505050905250602081015190915015610a73578092505b50509091565b610a81611866565b6000805b6002811015610d52578360028260028110610aa257610aa2612179565b6006020160010154148015610ab657508315155b15610d4a5760028160028110610ace57610ace612179565b6040805160808101825260069290920292909201805463ffffffff16825260018082015460208085019190915284516002840180546060938102830184018852828801818152959794969588958701948492849160009085015b82821015610b6e57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610b28565b505050508152602001600182018054610b869061220d565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb29061220d565b8015610bff5780601f10610bd457610100808354040283529160200191610bff565b820191906000526020600020905b815481529060010190602001808311610be257829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b82821015610ca15760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff8082168552680100000000000000009091041683850152600190810154918301919091529083529092019101610c41565b505050508152602001600182018054610cb99061220d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce59061220d565b8015610d325780601f10610d0757610100808354040283529160200191610d32565b820191906000526020600020905b815481529060010190602001808311610d1557829003601f168201915b50505091909252505050905250969095509350505050565b600101610a85565b509092600092509050565b610d656112b9565b60005b6002811015610e3f578160028260028110610d8557610d85612179565b6006020160010154148015610d9957508115155b15610e3757610dd0610daa84611ea6565b60028360028110610dbd57610dbd612179565b60060201600201600001805490506115bc565b8260028260028110610de457610de4612179565b600602016004018181610df791906125c5565b905050817f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e629484604051610e2a9190612844565b60405180910390a2505050565b600101610d68565b506040517fd0b2c031000000000000000000000000000000000000000000000000000000008152600481018290526024016102a4565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102a4565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f7e6112b9565b81158015610f8a575080155b15610fc1576040517f7b4d1e4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54600163ffffffff6401000000009092048216181682600282818110610feb57610feb612179565b600602016001015414611051576002816002811061100b5761100b612179565b6006020160010154836040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016102a4929190918252602082015260400190565b6000600261106d600e5463ffffffff6401000000009091041690565b63ffffffff166002811061108357611083612179565b600602019050828160010154146110d65760018101546040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018490526044016102a4565b6000600180830191909155600e805463ffffffff6401000000008083048216909418169092027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117905582156111585760405183907f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b890600090a25b60405184907ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e90600090a250505050565b6111916112b9565b61119a81611771565b50565b6111a56112b9565b806111dc576040517f0849d8cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54600163ffffffff640100000000909204821618168160028281811061120657611206612179565b60060201600101541461126c576002816002811061122657611226612179565b6006020160010154826040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016102a4929190918252602082015260400190565b60405182907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a2600281600281106112aa576112aa612179565b60060201600101600090555050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102a4565b565b815151610100101561137a576040517faf26d5e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251518110156114a4576000611394826001612857565b90505b83515181101561149b5783518051829081106113b5576113b5612179565b602002602001015160000151846000015183815181106113d7576113d7612179565b6020026020010151600001510361141a576040517f221a8ae800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835180518290811061142e5761142e612179565b6020026020010151602001518460000151838151811061145057611450612179565b60200260200101516020015103611493576040517fae00651d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101611397565b5060010161137d565b50610e75818360000151516115bc565b604080517f45564d00000000000000000000000000000000000000000000000000000000006020820152469181019190915230606082015263ffffffff821660808201526000907dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261155b91869060200161286a565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181529190528051602090910120167e0b0000000000000000000000000000000000000000000000000000000000001790505b92915050565b81515160005b8181101561176b576000846000015182815181106115e2576115e2612179565b6020026020010151905060008260016115fb9190612857565b90505b8381101561167e57855180518290811061161a5761161a612179565b60200260200101516000015167ffffffffffffffff16826000015167ffffffffffffffff1603611676576040517f3857f84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016115fe565b5060408101518061169186610100612899565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff901c8216146116ed576040517f2847b60600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b811561171557611701600183612899565b9091169061170e816128ac565b90506116f0565b80836020015167ffffffffffffffff16111561175d576040517f4ff924ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050508060010190506115c2565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036117f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102a4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060800160405280600063ffffffff168152602001600080191681526020016118a5604051806040016040528060608152602001606081525090565b81526020016118c7604051806040016040528060608152602001606081525090565b905290565b6000604082840312156118de57600080fd5b50919050565b6000806000606084860312156118f957600080fd5b833567ffffffffffffffff8082111561191157600080fd5b61191d878388016118cc565b9450602086013591508082111561193357600080fd5b50611940868287016118cc565b925050604084013590509250925092565b60005b8381101561196c578181015183820152602001611954565b50506000910152565b6000815180845261198d816020860160208601611951565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006119d26020830184611975565b9392505050565b8051604080845281518482018190526000926060916020918201918388019190865b82811015611a35578451805167ffffffffffffffff90811686528382015116838601528701518785015293810193928501926001016119fb565b50808801519550888303818a01525050611a4f8185611975565b979650505050505050565b63ffffffff81511682526000602080830151818501526040808401516080604087015260c0860181516040608089015281815180845260e08a0191508683019350600092505b80831015611ac95783518051835287015187830152928601926001929092019190850190611aa0565b50948301518886037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a08a015294611b038187611975565b9550505050505060608301518482036060860152611b2182826119d9565b95945050505050565b604081526000611b3d6040830185611a5a565b8281036020840152611b218185611a5a565b600060208284031215611b6157600080fd5b5035919050565b604081526000611b7b6040830185611a5a565b905082151560208301529392505050565b60008060408385031215611b9f57600080fd5b823567ffffffffffffffff811115611bb657600080fd5b611bc2858286016118cc565b95602094909401359450505050565b60008060408385031215611be457600080fd5b50508035926020909101359150565b600060208284031215611c0557600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146119d257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611c7b57611c7b611c29565b60405290565b6040516060810167ffffffffffffffff81118282101715611c7b57611c7b611c29565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611ceb57611ceb611c29565b604052919050565b600067ffffffffffffffff821115611d0d57611d0d611c29565b5060051b60200190565b600082601f830112611d2857600080fd5b813567ffffffffffffffff811115611d4257611d42611c29565b611d7360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ca4565b818152846020838601011115611d8857600080fd5b816020850160208301376000918101602001919091529392505050565b60006040808336031215611db857600080fd5b611dc0611c58565b833567ffffffffffffffff80821115611dd857600080fd5b9085019036601f830112611deb57600080fd5b81356020611e00611dfb83611cf3565b611ca4565b82815260069290921b84018101918181019036841115611e1f57600080fd5b948201945b83861015611e5f57878636031215611e3c5760008081fd5b611e44611c58565b86358152838701358482015282529487019490820190611e24565b86525087810135955082861115611e7557600080fd5b611e8136878a01611d17565b90850152509195945050505050565b67ffffffffffffffff8116811461119a57600080fd5b60006040808336031215611eb957600080fd5b611ec1611c58565b833567ffffffffffffffff80821115611ed957600080fd5b9085019036601f830112611eec57600080fd5b81356020611efc611dfb83611cf3565b82815260609283028501820192828201919036851115611f1b57600080fd5b958301955b84871015611f7557808736031215611f385760008081fd5b611f40611c81565b8735611f4b81611e90565b815287850135611f5a81611e90565b81860152878a01358a82015283529586019591830191611f20565b5086525087810135955082861115611e7557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103611fd457611fd4611f8c565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261201357600080fd5b830160208101925035905067ffffffffffffffff81111561203357600080fd5b80360382131561204257600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000604080840183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18536030181126120cb57600080fd5b8401602081810191359067ffffffffffffffff8211156120ea57600080fd5b8160061b36038313156120fc57600080fd5b6040885292819052909160009190606088015b82841015612135578435815281850135828201529385019360019390930192850161210f565b6121426020890189611fde565b9650945088810360208a0152612159818787612049565b9998505050505050505050565b6020815260006119d26020830184612092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126121dd57600080fd5b83018035915067ffffffffffffffff8211156121f857600080fd5b60200191503681900382131561204257600080fd5b600181811c9082168061222157607f821691505b6020821081036118de577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156122a6576000816000526020600020601f850160051c810160208610156122835750805b601f850160051c820191505b818110156122a25782815560010161228f565b5050505b505050565b67ffffffffffffffff8311156122c3576122c3611c29565b6122d7836122d1835461220d565b8361225a565b6000601f84116001811461232957600085156122f35750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556123bf565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156123785786850135825560209485019460019092019101612358565b50868210156123b3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181126123f857600080fd5b8201803567ffffffffffffffff81111561241157600080fd5b6020820191508060061b360382131561242957600080fd5b6801000000000000000081111561244257612442611c29565b8254818455808210156124cf5760017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316831461248357612483611f8c565b808416841461249457612494611f8c565b5060008560005260206000208360011b81018560011b820191505b808210156124ca5782825582848301556002820191506124af565b505050505b5060008381526020902060005b8281101561250857833582556020840135600183015560409390930192600291909101906001016124dc565b5050505061251960208301836121a8565b61176b8183600186016122ab565b813561253281611e90565b67ffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008216178355602084013561257681611e90565b6fffffffffffffffff00000000000000008160401b16837fffffffffffffffffffffffffffffffff00000000000000000000000000000000841617178455505050604082013560018201555050565b81357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181126125f757600080fd5b8201803567ffffffffffffffff81111561261057600080fd5b6020820191506060808202360383131561262957600080fd5b6801000000000000000082111561264257612642611c29565b8354828555808310156126cf5760017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316831461268357612683611f8c565b808516851461269457612694611f8c565b5060008660005260206000208360011b81018660011b820191505b808210156126ca5782825582848301556002820191506126af565b505050505b5060008481526020902060005b83811015612701576126ee8583612527565b93820193600291909101906001016126dc565b505050505061251960208301836121a8565b6000604080840183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261274c57600080fd5b8401602081810191359067ffffffffffffffff8083111561276c57600080fd5b6060808402360385131561277f57600080fd5b60408a529483905292936000939060608a015b848610156127d65786356127a581611e90565b83168152868401356127b681611e90565b831681850152868801358882015295810195600195909501948101612792565b6127e360208b018b611fde565b985096508a810360208c01526127fa818989612049565b9b9a5050505050505050505050565b63ffffffff841681526060602082015260006128286060830185612092565b828103604084015261283a8185612713565b9695505050505050565b6020815260006119d26020830184612713565b808201808211156115b6576115b6611f8c565b6000835161287c818460208801611951565b835190830190612890818360208801611951565b01949350505050565b818103818111156115b6576115b6611f8c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036128dd576128dd611f8c565b506001019056fea164736f6c6343000818000a", +} + +var RMNHomeABI = RMNHomeMetaData.ABI + +var RMNHomeBin = RMNHomeMetaData.Bin + +func DeployRMNHome(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *RMNHome, error) { + parsed, err := RMNHomeMetaData.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(RMNHomeBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &RMNHome{address: address, abi: *parsed, RMNHomeCaller: RMNHomeCaller{contract: contract}, RMNHomeTransactor: RMNHomeTransactor{contract: contract}, RMNHomeFilterer: RMNHomeFilterer{contract: contract}}, nil +} + +type RMNHome struct { + address common.Address + abi abi.ABI + RMNHomeCaller + RMNHomeTransactor + RMNHomeFilterer +} + +type RMNHomeCaller struct { + contract *bind.BoundContract +} + +type RMNHomeTransactor struct { + contract *bind.BoundContract +} + +type RMNHomeFilterer struct { + contract *bind.BoundContract +} + +type RMNHomeSession struct { + Contract *RMNHome + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type RMNHomeCallerSession struct { + Contract *RMNHomeCaller + CallOpts bind.CallOpts +} + +type RMNHomeTransactorSession struct { + Contract *RMNHomeTransactor + TransactOpts bind.TransactOpts +} + +type RMNHomeRaw struct { + Contract *RMNHome +} + +type RMNHomeCallerRaw struct { + Contract *RMNHomeCaller +} + +type RMNHomeTransactorRaw struct { + Contract *RMNHomeTransactor +} + +func NewRMNHome(address common.Address, backend bind.ContractBackend) (*RMNHome, error) { + abi, err := abi.JSON(strings.NewReader(RMNHomeABI)) + if err != nil { + return nil, err + } + contract, err := bindRMNHome(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &RMNHome{address: address, abi: abi, RMNHomeCaller: RMNHomeCaller{contract: contract}, RMNHomeTransactor: RMNHomeTransactor{contract: contract}, RMNHomeFilterer: RMNHomeFilterer{contract: contract}}, nil +} + +func NewRMNHomeCaller(address common.Address, caller bind.ContractCaller) (*RMNHomeCaller, error) { + contract, err := bindRMNHome(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RMNHomeCaller{contract: contract}, nil +} + +func NewRMNHomeTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNHomeTransactor, error) { + contract, err := bindRMNHome(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RMNHomeTransactor{contract: contract}, nil +} + +func NewRMNHomeFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNHomeFilterer, error) { + contract, err := bindRMNHome(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RMNHomeFilterer{contract: contract}, nil +} + +func bindRMNHome(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RMNHomeMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_RMNHome *RMNHomeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNHome.Contract.RMNHomeCaller.contract.Call(opts, result, method, params...) +} + +func (_RMNHome *RMNHomeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNHome.Contract.RMNHomeTransactor.contract.Transfer(opts) +} + +func (_RMNHome *RMNHomeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNHome.Contract.RMNHomeTransactor.contract.Transact(opts, method, params...) +} + +func (_RMNHome *RMNHomeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNHome.Contract.contract.Call(opts, result, method, params...) +} + +func (_RMNHome *RMNHomeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNHome.Contract.contract.Transfer(opts) +} + +func (_RMNHome *RMNHomeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNHome.Contract.contract.Transact(opts, method, params...) +} + +func (_RMNHome *RMNHomeCaller) GetActiveDigest(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _RMNHome.contract.Call(opts, &out, "getActiveDigest") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_RMNHome *RMNHomeSession) GetActiveDigest() ([32]byte, error) { + return _RMNHome.Contract.GetActiveDigest(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCallerSession) GetActiveDigest() ([32]byte, error) { + return _RMNHome.Contract.GetActiveDigest(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCaller) GetAllConfigs(opts *bind.CallOpts) (GetAllConfigs, + + error) { + var out []interface{} + err := _RMNHome.contract.Call(opts, &out, "getAllConfigs") + + outstruct := new(GetAllConfigs) + if err != nil { + return *outstruct, err + } + + outstruct.ActiveConfig = *abi.ConvertType(out[0], new(RMNHomeVersionedConfig)).(*RMNHomeVersionedConfig) + outstruct.CandidateConfig = *abi.ConvertType(out[1], new(RMNHomeVersionedConfig)).(*RMNHomeVersionedConfig) + + return *outstruct, err + +} + +func (_RMNHome *RMNHomeSession) GetAllConfigs() (GetAllConfigs, + + error) { + return _RMNHome.Contract.GetAllConfigs(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCallerSession) GetAllConfigs() (GetAllConfigs, + + error) { + return _RMNHome.Contract.GetAllConfigs(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCaller) GetCandidateDigest(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _RMNHome.contract.Call(opts, &out, "getCandidateDigest") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_RMNHome *RMNHomeSession) GetCandidateDigest() ([32]byte, error) { + return _RMNHome.Contract.GetCandidateDigest(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCallerSession) GetCandidateDigest() ([32]byte, error) { + return _RMNHome.Contract.GetCandidateDigest(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCaller) GetConfig(opts *bind.CallOpts, configDigest [32]byte) (GetConfig, + + error) { + var out []interface{} + err := _RMNHome.contract.Call(opts, &out, "getConfig", configDigest) + + outstruct := new(GetConfig) + if err != nil { + return *outstruct, err + } + + outstruct.VersionedConfig = *abi.ConvertType(out[0], new(RMNHomeVersionedConfig)).(*RMNHomeVersionedConfig) + outstruct.Ok = *abi.ConvertType(out[1], new(bool)).(*bool) + + return *outstruct, err + +} + +func (_RMNHome *RMNHomeSession) GetConfig(configDigest [32]byte) (GetConfig, + + error) { + return _RMNHome.Contract.GetConfig(&_RMNHome.CallOpts, configDigest) +} + +func (_RMNHome *RMNHomeCallerSession) GetConfig(configDigest [32]byte) (GetConfig, + + error) { + return _RMNHome.Contract.GetConfig(&_RMNHome.CallOpts, configDigest) +} + +func (_RMNHome *RMNHomeCaller) GetConfigDigests(opts *bind.CallOpts) (GetConfigDigests, + + error) { + var out []interface{} + err := _RMNHome.contract.Call(opts, &out, "getConfigDigests") + + outstruct := new(GetConfigDigests) + if err != nil { + return *outstruct, err + } + + outstruct.ActiveConfigDigest = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.CandidateConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_RMNHome *RMNHomeSession) GetConfigDigests() (GetConfigDigests, + + error) { + return _RMNHome.Contract.GetConfigDigests(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCallerSession) GetConfigDigests() (GetConfigDigests, + + error) { + return _RMNHome.Contract.GetConfigDigests(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RMNHome.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 (_RMNHome *RMNHomeSession) Owner() (common.Address, error) { + return _RMNHome.Contract.Owner(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCallerSession) Owner() (common.Address, error) { + return _RMNHome.Contract.Owner(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _RMNHome.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_RMNHome *RMNHomeSession) TypeAndVersion() (string, error) { + return _RMNHome.Contract.TypeAndVersion(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeCallerSession) TypeAndVersion() (string, error) { + return _RMNHome.Contract.TypeAndVersion(&_RMNHome.CallOpts) +} + +func (_RMNHome *RMNHomeTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNHome.contract.Transact(opts, "acceptOwnership") +} + +func (_RMNHome *RMNHomeSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNHome.Contract.AcceptOwnership(&_RMNHome.TransactOpts) +} + +func (_RMNHome *RMNHomeTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNHome.Contract.AcceptOwnership(&_RMNHome.TransactOpts) +} + +func (_RMNHome *RMNHomeTransactor) PromoteCandidateAndRevokeActive(opts *bind.TransactOpts, digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) { + return _RMNHome.contract.Transact(opts, "promoteCandidateAndRevokeActive", digestToPromote, digestToRevoke) +} + +func (_RMNHome *RMNHomeSession) PromoteCandidateAndRevokeActive(digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.PromoteCandidateAndRevokeActive(&_RMNHome.TransactOpts, digestToPromote, digestToRevoke) +} + +func (_RMNHome *RMNHomeTransactorSession) PromoteCandidateAndRevokeActive(digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.PromoteCandidateAndRevokeActive(&_RMNHome.TransactOpts, digestToPromote, digestToRevoke) +} + +func (_RMNHome *RMNHomeTransactor) RevokeCandidate(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { + return _RMNHome.contract.Transact(opts, "revokeCandidate", configDigest) +} + +func (_RMNHome *RMNHomeSession) RevokeCandidate(configDigest [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.RevokeCandidate(&_RMNHome.TransactOpts, configDigest) +} + +func (_RMNHome *RMNHomeTransactorSession) RevokeCandidate(configDigest [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.RevokeCandidate(&_RMNHome.TransactOpts, configDigest) +} + +func (_RMNHome *RMNHomeTransactor) SetCandidate(opts *bind.TransactOpts, staticConfig RMNHomeStaticConfig, dynamicConfig RMNHomeDynamicConfig, digestToOverwrite [32]byte) (*types.Transaction, error) { + return _RMNHome.contract.Transact(opts, "setCandidate", staticConfig, dynamicConfig, digestToOverwrite) +} + +func (_RMNHome *RMNHomeSession) SetCandidate(staticConfig RMNHomeStaticConfig, dynamicConfig RMNHomeDynamicConfig, digestToOverwrite [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.SetCandidate(&_RMNHome.TransactOpts, staticConfig, dynamicConfig, digestToOverwrite) +} + +func (_RMNHome *RMNHomeTransactorSession) SetCandidate(staticConfig RMNHomeStaticConfig, dynamicConfig RMNHomeDynamicConfig, digestToOverwrite [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.SetCandidate(&_RMNHome.TransactOpts, staticConfig, dynamicConfig, digestToOverwrite) +} + +func (_RMNHome *RMNHomeTransactor) SetDynamicConfig(opts *bind.TransactOpts, newDynamicConfig RMNHomeDynamicConfig, currentDigest [32]byte) (*types.Transaction, error) { + return _RMNHome.contract.Transact(opts, "setDynamicConfig", newDynamicConfig, currentDigest) +} + +func (_RMNHome *RMNHomeSession) SetDynamicConfig(newDynamicConfig RMNHomeDynamicConfig, currentDigest [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.SetDynamicConfig(&_RMNHome.TransactOpts, newDynamicConfig, currentDigest) +} + +func (_RMNHome *RMNHomeTransactorSession) SetDynamicConfig(newDynamicConfig RMNHomeDynamicConfig, currentDigest [32]byte) (*types.Transaction, error) { + return _RMNHome.Contract.SetDynamicConfig(&_RMNHome.TransactOpts, newDynamicConfig, currentDigest) +} + +func (_RMNHome *RMNHomeTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RMNHome.contract.Transact(opts, "transferOwnership", to) +} + +func (_RMNHome *RMNHomeSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNHome.Contract.TransferOwnership(&_RMNHome.TransactOpts, to) +} + +func (_RMNHome *RMNHomeTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNHome.Contract.TransferOwnership(&_RMNHome.TransactOpts, to) +} + +type RMNHomeActiveConfigRevokedIterator struct { + Event *RMNHomeActiveConfigRevoked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeActiveConfigRevokedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeActiveConfigRevoked) + 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(RMNHomeActiveConfigRevoked) + 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 *RMNHomeActiveConfigRevokedIterator) Error() error { + return it.fail +} + +func (it *RMNHomeActiveConfigRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeActiveConfigRevoked struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterActiveConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeActiveConfigRevokedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.FilterLogs(opts, "ActiveConfigRevoked", configDigestRule) + if err != nil { + return nil, err + } + return &RMNHomeActiveConfigRevokedIterator{contract: _RMNHome.contract, event: "ActiveConfigRevoked", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchActiveConfigRevoked(opts *bind.WatchOpts, sink chan<- *RMNHomeActiveConfigRevoked, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.WatchLogs(opts, "ActiveConfigRevoked", 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(RMNHomeActiveConfigRevoked) + if err := _RMNHome.contract.UnpackLog(event, "ActiveConfigRevoked", 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 (_RMNHome *RMNHomeFilterer) ParseActiveConfigRevoked(log types.Log) (*RMNHomeActiveConfigRevoked, error) { + event := new(RMNHomeActiveConfigRevoked) + if err := _RMNHome.contract.UnpackLog(event, "ActiveConfigRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNHomeCandidateConfigRevokedIterator struct { + Event *RMNHomeCandidateConfigRevoked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeCandidateConfigRevokedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeCandidateConfigRevoked) + 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(RMNHomeCandidateConfigRevoked) + 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 *RMNHomeCandidateConfigRevokedIterator) Error() error { + return it.fail +} + +func (it *RMNHomeCandidateConfigRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeCandidateConfigRevoked struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterCandidateConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeCandidateConfigRevokedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.FilterLogs(opts, "CandidateConfigRevoked", configDigestRule) + if err != nil { + return nil, err + } + return &RMNHomeCandidateConfigRevokedIterator{contract: _RMNHome.contract, event: "CandidateConfigRevoked", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchCandidateConfigRevoked(opts *bind.WatchOpts, sink chan<- *RMNHomeCandidateConfigRevoked, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.WatchLogs(opts, "CandidateConfigRevoked", 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(RMNHomeCandidateConfigRevoked) + if err := _RMNHome.contract.UnpackLog(event, "CandidateConfigRevoked", 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 (_RMNHome *RMNHomeFilterer) ParseCandidateConfigRevoked(log types.Log) (*RMNHomeCandidateConfigRevoked, error) { + event := new(RMNHomeCandidateConfigRevoked) + if err := _RMNHome.contract.UnpackLog(event, "CandidateConfigRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNHomeConfigPromotedIterator struct { + Event *RMNHomeConfigPromoted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeConfigPromotedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeConfigPromoted) + 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(RMNHomeConfigPromoted) + 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 *RMNHomeConfigPromotedIterator) Error() error { + return it.fail +} + +func (it *RMNHomeConfigPromotedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeConfigPromoted struct { + ConfigDigest [32]byte + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterConfigPromoted(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeConfigPromotedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.FilterLogs(opts, "ConfigPromoted", configDigestRule) + if err != nil { + return nil, err + } + return &RMNHomeConfigPromotedIterator{contract: _RMNHome.contract, event: "ConfigPromoted", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchConfigPromoted(opts *bind.WatchOpts, sink chan<- *RMNHomeConfigPromoted, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.WatchLogs(opts, "ConfigPromoted", 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(RMNHomeConfigPromoted) + if err := _RMNHome.contract.UnpackLog(event, "ConfigPromoted", 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 (_RMNHome *RMNHomeFilterer) ParseConfigPromoted(log types.Log) (*RMNHomeConfigPromoted, error) { + event := new(RMNHomeConfigPromoted) + if err := _RMNHome.contract.UnpackLog(event, "ConfigPromoted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNHomeConfigSetIterator struct { + Event *RMNHomeConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeConfigSet) + 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(RMNHomeConfigSet) + 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 *RMNHomeConfigSetIterator) Error() error { + return it.fail +} + +func (it *RMNHomeConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeConfigSet struct { + ConfigDigest [32]byte + Version uint32 + StaticConfig RMNHomeStaticConfig + DynamicConfig RMNHomeDynamicConfig + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeConfigSetIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.FilterLogs(opts, "ConfigSet", configDigestRule) + if err != nil { + return nil, err + } + return &RMNHomeConfigSetIterator{contract: _RMNHome.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNHomeConfigSet, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.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(RMNHomeConfigSet) + if err := _RMNHome.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 (_RMNHome *RMNHomeFilterer) ParseConfigSet(log types.Log) (*RMNHomeConfigSet, error) { + event := new(RMNHomeConfigSet) + if err := _RMNHome.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNHomeDynamicConfigSetIterator struct { + Event *RMNHomeDynamicConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeDynamicConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeDynamicConfigSet) + 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(RMNHomeDynamicConfigSet) + 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 *RMNHomeDynamicConfigSetIterator) Error() error { + return it.fail +} + +func (it *RMNHomeDynamicConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeDynamicConfigSet struct { + ConfigDigest [32]byte + DynamicConfig RMNHomeDynamicConfig + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterDynamicConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeDynamicConfigSetIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.FilterLogs(opts, "DynamicConfigSet", configDigestRule) + if err != nil { + return nil, err + } + return &RMNHomeDynamicConfigSetIterator{contract: _RMNHome.contract, event: "DynamicConfigSet", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *RMNHomeDynamicConfigSet, configDigest [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + + logs, sub, err := _RMNHome.contract.WatchLogs(opts, "DynamicConfigSet", 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(RMNHomeDynamicConfigSet) + if err := _RMNHome.contract.UnpackLog(event, "DynamicConfigSet", 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 (_RMNHome *RMNHomeFilterer) ParseDynamicConfigSet(log types.Log) (*RMNHomeDynamicConfigSet, error) { + event := new(RMNHomeDynamicConfigSet) + if err := _RMNHome.contract.UnpackLog(event, "DynamicConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNHomeOwnershipTransferRequestedIterator struct { + Event *RMNHomeOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeOwnershipTransferRequested) + 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(RMNHomeOwnershipTransferRequested) + 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 *RMNHomeOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *RMNHomeOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNHomeOwnershipTransferRequestedIterator, 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 := _RMNHome.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &RMNHomeOwnershipTransferRequestedIterator{contract: _RMNHome.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNHomeOwnershipTransferRequested, 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 := _RMNHome.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(RMNHomeOwnershipTransferRequested) + if err := _RMNHome.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 (_RMNHome *RMNHomeFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNHomeOwnershipTransferRequested, error) { + event := new(RMNHomeOwnershipTransferRequested) + if err := _RMNHome.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNHomeOwnershipTransferredIterator struct { + Event *RMNHomeOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNHomeOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNHomeOwnershipTransferred) + 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(RMNHomeOwnershipTransferred) + 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 *RMNHomeOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *RMNHomeOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNHomeOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RMNHome *RMNHomeFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNHomeOwnershipTransferredIterator, 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 := _RMNHome.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &RMNHomeOwnershipTransferredIterator{contract: _RMNHome.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_RMNHome *RMNHomeFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNHomeOwnershipTransferred, 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 := _RMNHome.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(RMNHomeOwnershipTransferred) + if err := _RMNHome.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 (_RMNHome *RMNHomeFilterer) ParseOwnershipTransferred(log types.Log) (*RMNHomeOwnershipTransferred, error) { + event := new(RMNHomeOwnershipTransferred) + if err := _RMNHome.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetAllConfigs struct { + ActiveConfig RMNHomeVersionedConfig + CandidateConfig RMNHomeVersionedConfig +} +type GetConfig struct { + VersionedConfig RMNHomeVersionedConfig + Ok bool +} +type GetConfigDigests struct { + ActiveConfigDigest [32]byte + CandidateConfigDigest [32]byte +} + +func (_RMNHome *RMNHome) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _RMNHome.abi.Events["ActiveConfigRevoked"].ID: + return _RMNHome.ParseActiveConfigRevoked(log) + case _RMNHome.abi.Events["CandidateConfigRevoked"].ID: + return _RMNHome.ParseCandidateConfigRevoked(log) + case _RMNHome.abi.Events["ConfigPromoted"].ID: + return _RMNHome.ParseConfigPromoted(log) + case _RMNHome.abi.Events["ConfigSet"].ID: + return _RMNHome.ParseConfigSet(log) + case _RMNHome.abi.Events["DynamicConfigSet"].ID: + return _RMNHome.ParseDynamicConfigSet(log) + case _RMNHome.abi.Events["OwnershipTransferRequested"].ID: + return _RMNHome.ParseOwnershipTransferRequested(log) + case _RMNHome.abi.Events["OwnershipTransferred"].ID: + return _RMNHome.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (RMNHomeActiveConfigRevoked) Topic() common.Hash { + return common.HexToHash("0x0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b8") +} + +func (RMNHomeCandidateConfigRevoked) Topic() common.Hash { + return common.HexToHash("0x53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b") +} + +func (RMNHomeConfigPromoted) Topic() common.Hash { + return common.HexToHash("0xfc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e") +} + +func (RMNHomeConfigSet) Topic() common.Hash { + return common.HexToHash("0xf6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf0") +} + +func (RMNHomeDynamicConfigSet) Topic() common.Hash { + return common.HexToHash("0x1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e6294") +} + +func (RMNHomeOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (RMNHomeOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_RMNHome *RMNHome) Address() common.Address { + return _RMNHome.address +} + +type RMNHomeInterface interface { + GetActiveDigest(opts *bind.CallOpts) ([32]byte, error) + + GetAllConfigs(opts *bind.CallOpts) (GetAllConfigs, + + error) + + GetCandidateDigest(opts *bind.CallOpts) ([32]byte, error) + + GetConfig(opts *bind.CallOpts, configDigest [32]byte) (GetConfig, + + error) + + GetConfigDigests(opts *bind.CallOpts) (GetConfigDigests, + + error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + PromoteCandidateAndRevokeActive(opts *bind.TransactOpts, digestToPromote [32]byte, digestToRevoke [32]byte) (*types.Transaction, error) + + RevokeCandidate(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) + + SetCandidate(opts *bind.TransactOpts, staticConfig RMNHomeStaticConfig, dynamicConfig RMNHomeDynamicConfig, digestToOverwrite [32]byte) (*types.Transaction, error) + + SetDynamicConfig(opts *bind.TransactOpts, newDynamicConfig RMNHomeDynamicConfig, currentDigest [32]byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterActiveConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeActiveConfigRevokedIterator, error) + + WatchActiveConfigRevoked(opts *bind.WatchOpts, sink chan<- *RMNHomeActiveConfigRevoked, configDigest [][32]byte) (event.Subscription, error) + + ParseActiveConfigRevoked(log types.Log) (*RMNHomeActiveConfigRevoked, error) + + FilterCandidateConfigRevoked(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeCandidateConfigRevokedIterator, error) + + WatchCandidateConfigRevoked(opts *bind.WatchOpts, sink chan<- *RMNHomeCandidateConfigRevoked, configDigest [][32]byte) (event.Subscription, error) + + ParseCandidateConfigRevoked(log types.Log) (*RMNHomeCandidateConfigRevoked, error) + + FilterConfigPromoted(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeConfigPromotedIterator, error) + + WatchConfigPromoted(opts *bind.WatchOpts, sink chan<- *RMNHomeConfigPromoted, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigPromoted(log types.Log) (*RMNHomeConfigPromoted, error) + + FilterConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNHomeConfigSet, configDigest [][32]byte) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*RMNHomeConfigSet, error) + + FilterDynamicConfigSet(opts *bind.FilterOpts, configDigest [][32]byte) (*RMNHomeDynamicConfigSetIterator, error) + + WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *RMNHomeDynamicConfigSet, configDigest [][32]byte) (event.Subscription, error) + + ParseDynamicConfigSet(log types.Log) (*RMNHomeDynamicConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNHomeOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNHomeOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*RMNHomeOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNHomeOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNHomeOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*RMNHomeOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/arm_proxy_contract/arm_proxy_contract.go b/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go similarity index 60% rename from core/gethwrappers/ccip/generated/arm_proxy_contract/arm_proxy_contract.go rename to core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go index e2ba9246216..18fd9898d81 100644 --- a/core/gethwrappers/ccip/generated/arm_proxy_contract/arm_proxy_contract.go +++ b/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package arm_proxy_contract +package rmn_proxy_contract import ( "errors" @@ -30,17 +30,17 @@ var ( _ = abi.ConvertType ) -var ARMProxyContractMetaData = &bind.MetaData{ +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 ARMProxyContractABI = ARMProxyContractMetaData.ABI +var RMNProxyContractABI = RMNProxyContractMetaData.ABI -var ARMProxyContractBin = ARMProxyContractMetaData.Bin +var RMNProxyContractBin = RMNProxyContractMetaData.Bin -func DeployARMProxyContract(auth *bind.TransactOpts, backend bind.ContractBackend, arm common.Address) (common.Address, *types.Transaction, *ARMProxyContract, error) { - parsed, err := ARMProxyContractMetaData.GetAbi() +func DeployRMNProxyContract(auth *bind.TransactOpts, backend bind.ContractBackend, arm common.Address) (common.Address, *types.Transaction, *RMNProxyContract, error) { + parsed, err := RMNProxyContractMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -48,132 +48,132 @@ func DeployARMProxyContract(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(ARMProxyContractBin), backend, arm) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNProxyContractBin), backend, arm) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &ARMProxyContract{address: address, abi: *parsed, ARMProxyContractCaller: ARMProxyContractCaller{contract: contract}, ARMProxyContractTransactor: ARMProxyContractTransactor{contract: contract}, ARMProxyContractFilterer: ARMProxyContractFilterer{contract: contract}}, nil + return address, tx, &RMNProxyContract{address: address, abi: *parsed, RMNProxyContractCaller: RMNProxyContractCaller{contract: contract}, RMNProxyContractTransactor: RMNProxyContractTransactor{contract: contract}, RMNProxyContractFilterer: RMNProxyContractFilterer{contract: contract}}, nil } -type ARMProxyContract struct { +type RMNProxyContract struct { address common.Address abi abi.ABI - ARMProxyContractCaller - ARMProxyContractTransactor - ARMProxyContractFilterer + RMNProxyContractCaller + RMNProxyContractTransactor + RMNProxyContractFilterer } -type ARMProxyContractCaller struct { +type RMNProxyContractCaller struct { contract *bind.BoundContract } -type ARMProxyContractTransactor struct { +type RMNProxyContractTransactor struct { contract *bind.BoundContract } -type ARMProxyContractFilterer struct { +type RMNProxyContractFilterer struct { contract *bind.BoundContract } -type ARMProxyContractSession struct { - Contract *ARMProxyContract +type RMNProxyContractSession struct { + Contract *RMNProxyContract CallOpts bind.CallOpts TransactOpts bind.TransactOpts } -type ARMProxyContractCallerSession struct { - Contract *ARMProxyContractCaller +type RMNProxyContractCallerSession struct { + Contract *RMNProxyContractCaller CallOpts bind.CallOpts } -type ARMProxyContractTransactorSession struct { - Contract *ARMProxyContractTransactor +type RMNProxyContractTransactorSession struct { + Contract *RMNProxyContractTransactor TransactOpts bind.TransactOpts } -type ARMProxyContractRaw struct { - Contract *ARMProxyContract +type RMNProxyContractRaw struct { + Contract *RMNProxyContract } -type ARMProxyContractCallerRaw struct { - Contract *ARMProxyContractCaller +type RMNProxyContractCallerRaw struct { + Contract *RMNProxyContractCaller } -type ARMProxyContractTransactorRaw struct { - Contract *ARMProxyContractTransactor +type RMNProxyContractTransactorRaw struct { + Contract *RMNProxyContractTransactor } -func NewARMProxyContract(address common.Address, backend bind.ContractBackend) (*ARMProxyContract, error) { - abi, err := abi.JSON(strings.NewReader(ARMProxyContractABI)) +func NewRMNProxyContract(address common.Address, backend bind.ContractBackend) (*RMNProxyContract, error) { + abi, err := abi.JSON(strings.NewReader(RMNProxyContractABI)) if err != nil { return nil, err } - contract, err := bindARMProxyContract(address, backend, backend, backend) + contract, err := bindRMNProxyContract(address, backend, backend, backend) if err != nil { return nil, err } - return &ARMProxyContract{address: address, abi: abi, ARMProxyContractCaller: ARMProxyContractCaller{contract: contract}, ARMProxyContractTransactor: ARMProxyContractTransactor{contract: contract}, ARMProxyContractFilterer: ARMProxyContractFilterer{contract: contract}}, nil + return &RMNProxyContract{address: address, abi: abi, RMNProxyContractCaller: RMNProxyContractCaller{contract: contract}, RMNProxyContractTransactor: RMNProxyContractTransactor{contract: contract}, RMNProxyContractFilterer: RMNProxyContractFilterer{contract: contract}}, nil } -func NewARMProxyContractCaller(address common.Address, caller bind.ContractCaller) (*ARMProxyContractCaller, error) { - contract, err := bindARMProxyContract(address, caller, nil, nil) +func NewRMNProxyContractCaller(address common.Address, caller bind.ContractCaller) (*RMNProxyContractCaller, error) { + contract, err := bindRMNProxyContract(address, caller, nil, nil) if err != nil { return nil, err } - return &ARMProxyContractCaller{contract: contract}, nil + return &RMNProxyContractCaller{contract: contract}, nil } -func NewARMProxyContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ARMProxyContractTransactor, error) { - contract, err := bindARMProxyContract(address, nil, transactor, nil) +func NewRMNProxyContractTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNProxyContractTransactor, error) { + contract, err := bindRMNProxyContract(address, nil, transactor, nil) if err != nil { return nil, err } - return &ARMProxyContractTransactor{contract: contract}, nil + return &RMNProxyContractTransactor{contract: contract}, nil } -func NewARMProxyContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ARMProxyContractFilterer, error) { - contract, err := bindARMProxyContract(address, nil, nil, filterer) +func NewRMNProxyContractFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNProxyContractFilterer, error) { + contract, err := bindRMNProxyContract(address, nil, nil, filterer) if err != nil { return nil, err } - return &ARMProxyContractFilterer{contract: contract}, nil + return &RMNProxyContractFilterer{contract: contract}, nil } -func bindARMProxyContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ARMProxyContractMetaData.GetAbi() +func bindRMNProxyContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RMNProxyContractMetaData.GetAbi() if err != nil { return nil, err } return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -func (_ARMProxyContract *ARMProxyContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ARMProxyContract.Contract.ARMProxyContractCaller.contract.Call(opts, result, method, params...) +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 (_ARMProxyContract *ARMProxyContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ARMProxyContract.Contract.ARMProxyContractTransactor.contract.Transfer(opts) +func (_RMNProxyContract *RMNProxyContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNProxyContract.Contract.RMNProxyContractTransactor.contract.Transfer(opts) } -func (_ARMProxyContract *ARMProxyContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ARMProxyContract.Contract.ARMProxyContractTransactor.contract.Transact(opts, method, params...) +func (_RMNProxyContract *RMNProxyContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNProxyContract.Contract.RMNProxyContractTransactor.contract.Transact(opts, method, params...) } -func (_ARMProxyContract *ARMProxyContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ARMProxyContract.Contract.contract.Call(opts, result, 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 (_ARMProxyContract *ARMProxyContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ARMProxyContract.Contract.contract.Transfer(opts) +func (_RMNProxyContract *RMNProxyContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNProxyContract.Contract.contract.Transfer(opts) } -func (_ARMProxyContract *ARMProxyContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ARMProxyContract.Contract.contract.Transact(opts, method, params...) +func (_RMNProxyContract *RMNProxyContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNProxyContract.Contract.contract.Transact(opts, method, params...) } -func (_ARMProxyContract *ARMProxyContractCaller) GetARM(opts *bind.CallOpts) (common.Address, error) { +func (_RMNProxyContract *RMNProxyContractCaller) GetARM(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _ARMProxyContract.contract.Call(opts, &out, "getARM") + err := _RMNProxyContract.contract.Call(opts, &out, "getARM") if err != nil { return *new(common.Address), err @@ -185,17 +185,17 @@ func (_ARMProxyContract *ARMProxyContractCaller) GetARM(opts *bind.CallOpts) (co } -func (_ARMProxyContract *ARMProxyContractSession) GetARM() (common.Address, error) { - return _ARMProxyContract.Contract.GetARM(&_ARMProxyContract.CallOpts) +func (_RMNProxyContract *RMNProxyContractSession) GetARM() (common.Address, error) { + return _RMNProxyContract.Contract.GetARM(&_RMNProxyContract.CallOpts) } -func (_ARMProxyContract *ARMProxyContractCallerSession) GetARM() (common.Address, error) { - return _ARMProxyContract.Contract.GetARM(&_ARMProxyContract.CallOpts) +func (_RMNProxyContract *RMNProxyContractCallerSession) GetARM() (common.Address, error) { + return _RMNProxyContract.Contract.GetARM(&_RMNProxyContract.CallOpts) } -func (_ARMProxyContract *ARMProxyContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { +func (_RMNProxyContract *RMNProxyContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _ARMProxyContract.contract.Call(opts, &out, "owner") + err := _RMNProxyContract.contract.Call(opts, &out, "owner") if err != nil { return *new(common.Address), err @@ -207,17 +207,17 @@ func (_ARMProxyContract *ARMProxyContractCaller) Owner(opts *bind.CallOpts) (com } -func (_ARMProxyContract *ARMProxyContractSession) Owner() (common.Address, error) { - return _ARMProxyContract.Contract.Owner(&_ARMProxyContract.CallOpts) +func (_RMNProxyContract *RMNProxyContractSession) Owner() (common.Address, error) { + return _RMNProxyContract.Contract.Owner(&_RMNProxyContract.CallOpts) } -func (_ARMProxyContract *ARMProxyContractCallerSession) Owner() (common.Address, error) { - return _ARMProxyContract.Contract.Owner(&_ARMProxyContract.CallOpts) +func (_RMNProxyContract *RMNProxyContractCallerSession) Owner() (common.Address, error) { + return _RMNProxyContract.Contract.Owner(&_RMNProxyContract.CallOpts) } -func (_ARMProxyContract *ARMProxyContractCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { +func (_RMNProxyContract *RMNProxyContractCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} - err := _ARMProxyContract.contract.Call(opts, &out, "typeAndVersion") + err := _RMNProxyContract.contract.Call(opts, &out, "typeAndVersion") if err != nil { return *new(string), err @@ -229,64 +229,64 @@ func (_ARMProxyContract *ARMProxyContractCaller) TypeAndVersion(opts *bind.CallO } -func (_ARMProxyContract *ARMProxyContractSession) TypeAndVersion() (string, error) { - return _ARMProxyContract.Contract.TypeAndVersion(&_ARMProxyContract.CallOpts) +func (_RMNProxyContract *RMNProxyContractSession) TypeAndVersion() (string, error) { + return _RMNProxyContract.Contract.TypeAndVersion(&_RMNProxyContract.CallOpts) } -func (_ARMProxyContract *ARMProxyContractCallerSession) TypeAndVersion() (string, error) { - return _ARMProxyContract.Contract.TypeAndVersion(&_ARMProxyContract.CallOpts) +func (_RMNProxyContract *RMNProxyContractCallerSession) TypeAndVersion() (string, error) { + return _RMNProxyContract.Contract.TypeAndVersion(&_RMNProxyContract.CallOpts) } -func (_ARMProxyContract *ARMProxyContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ARMProxyContract.contract.Transact(opts, "acceptOwnership") +func (_RMNProxyContract *RMNProxyContractTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNProxyContract.contract.Transact(opts, "acceptOwnership") } -func (_ARMProxyContract *ARMProxyContractSession) AcceptOwnership() (*types.Transaction, error) { - return _ARMProxyContract.Contract.AcceptOwnership(&_ARMProxyContract.TransactOpts) +func (_RMNProxyContract *RMNProxyContractSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNProxyContract.Contract.AcceptOwnership(&_RMNProxyContract.TransactOpts) } -func (_ARMProxyContract *ARMProxyContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _ARMProxyContract.Contract.AcceptOwnership(&_ARMProxyContract.TransactOpts) +func (_RMNProxyContract *RMNProxyContractTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNProxyContract.Contract.AcceptOwnership(&_RMNProxyContract.TransactOpts) } -func (_ARMProxyContract *ARMProxyContractTransactor) SetARM(opts *bind.TransactOpts, arm common.Address) (*types.Transaction, error) { - return _ARMProxyContract.contract.Transact(opts, "setARM", arm) +func (_RMNProxyContract *RMNProxyContractTransactor) SetARM(opts *bind.TransactOpts, arm common.Address) (*types.Transaction, error) { + return _RMNProxyContract.contract.Transact(opts, "setARM", arm) } -func (_ARMProxyContract *ARMProxyContractSession) SetARM(arm common.Address) (*types.Transaction, error) { - return _ARMProxyContract.Contract.SetARM(&_ARMProxyContract.TransactOpts, arm) +func (_RMNProxyContract *RMNProxyContractSession) SetARM(arm common.Address) (*types.Transaction, error) { + return _RMNProxyContract.Contract.SetARM(&_RMNProxyContract.TransactOpts, arm) } -func (_ARMProxyContract *ARMProxyContractTransactorSession) SetARM(arm common.Address) (*types.Transaction, error) { - return _ARMProxyContract.Contract.SetARM(&_ARMProxyContract.TransactOpts, arm) +func (_RMNProxyContract *RMNProxyContractTransactorSession) SetARM(arm common.Address) (*types.Transaction, error) { + return _RMNProxyContract.Contract.SetARM(&_RMNProxyContract.TransactOpts, arm) } -func (_ARMProxyContract *ARMProxyContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _ARMProxyContract.contract.Transact(opts, "transferOwnership", to) +func (_RMNProxyContract *RMNProxyContractTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RMNProxyContract.contract.Transact(opts, "transferOwnership", to) } -func (_ARMProxyContract *ARMProxyContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _ARMProxyContract.Contract.TransferOwnership(&_ARMProxyContract.TransactOpts, to) +func (_RMNProxyContract *RMNProxyContractSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNProxyContract.Contract.TransferOwnership(&_RMNProxyContract.TransactOpts, to) } -func (_ARMProxyContract *ARMProxyContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _ARMProxyContract.Contract.TransferOwnership(&_ARMProxyContract.TransactOpts, to) +func (_RMNProxyContract *RMNProxyContractTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNProxyContract.Contract.TransferOwnership(&_RMNProxyContract.TransactOpts, to) } -func (_ARMProxyContract *ARMProxyContractTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { - return _ARMProxyContract.contract.RawTransact(opts, calldata) +func (_RMNProxyContract *RMNProxyContractTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _RMNProxyContract.contract.RawTransact(opts, calldata) } -func (_ARMProxyContract *ARMProxyContractSession) Fallback(calldata []byte) (*types.Transaction, error) { - return _ARMProxyContract.Contract.Fallback(&_ARMProxyContract.TransactOpts, calldata) +func (_RMNProxyContract *RMNProxyContractSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _RMNProxyContract.Contract.Fallback(&_RMNProxyContract.TransactOpts, calldata) } -func (_ARMProxyContract *ARMProxyContractTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { - return _ARMProxyContract.Contract.Fallback(&_ARMProxyContract.TransactOpts, calldata) +func (_RMNProxyContract *RMNProxyContractTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _RMNProxyContract.Contract.Fallback(&_RMNProxyContract.TransactOpts, calldata) } -type ARMProxyContractARMSetIterator struct { - Event *ARMProxyContractARMSet +type RMNProxyContractARMSetIterator struct { + Event *RMNProxyContractARMSet contract *bind.BoundContract event string @@ -297,7 +297,7 @@ type ARMProxyContractARMSetIterator struct { fail error } -func (it *ARMProxyContractARMSetIterator) Next() bool { +func (it *RMNProxyContractARMSetIterator) Next() bool { if it.fail != nil { return false @@ -306,7 +306,7 @@ func (it *ARMProxyContractARMSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMProxyContractARMSet) + it.Event = new(RMNProxyContractARMSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -321,7 +321,7 @@ func (it *ARMProxyContractARMSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMProxyContractARMSet) + it.Event = new(RMNProxyContractARMSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -336,32 +336,32 @@ func (it *ARMProxyContractARMSetIterator) Next() bool { } } -func (it *ARMProxyContractARMSetIterator) Error() error { +func (it *RMNProxyContractARMSetIterator) Error() error { return it.fail } -func (it *ARMProxyContractARMSetIterator) Close() error { +func (it *RMNProxyContractARMSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMProxyContractARMSet struct { +type RMNProxyContractARMSet struct { Arm common.Address Raw types.Log } -func (_ARMProxyContract *ARMProxyContractFilterer) FilterARMSet(opts *bind.FilterOpts) (*ARMProxyContractARMSetIterator, error) { +func (_RMNProxyContract *RMNProxyContractFilterer) FilterARMSet(opts *bind.FilterOpts) (*RMNProxyContractARMSetIterator, error) { - logs, sub, err := _ARMProxyContract.contract.FilterLogs(opts, "ARMSet") + logs, sub, err := _RMNProxyContract.contract.FilterLogs(opts, "ARMSet") if err != nil { return nil, err } - return &ARMProxyContractARMSetIterator{contract: _ARMProxyContract.contract, event: "ARMSet", logs: logs, sub: sub}, nil + return &RMNProxyContractARMSetIterator{contract: _RMNProxyContract.contract, event: "ARMSet", logs: logs, sub: sub}, nil } -func (_ARMProxyContract *ARMProxyContractFilterer) WatchARMSet(opts *bind.WatchOpts, sink chan<- *ARMProxyContractARMSet) (event.Subscription, error) { +func (_RMNProxyContract *RMNProxyContractFilterer) WatchARMSet(opts *bind.WatchOpts, sink chan<- *RMNProxyContractARMSet) (event.Subscription, error) { - logs, sub, err := _ARMProxyContract.contract.WatchLogs(opts, "ARMSet") + logs, sub, err := _RMNProxyContract.contract.WatchLogs(opts, "ARMSet") if err != nil { return nil, err } @@ -371,8 +371,8 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchARMSet(opts *bind.WatchO select { case log := <-logs: - event := new(ARMProxyContractARMSet) - if err := _ARMProxyContract.contract.UnpackLog(event, "ARMSet", log); err != nil { + event := new(RMNProxyContractARMSet) + if err := _RMNProxyContract.contract.UnpackLog(event, "ARMSet", log); err != nil { return err } event.Raw = log @@ -393,17 +393,17 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchARMSet(opts *bind.WatchO }), nil } -func (_ARMProxyContract *ARMProxyContractFilterer) ParseARMSet(log types.Log) (*ARMProxyContractARMSet, error) { - event := new(ARMProxyContractARMSet) - if err := _ARMProxyContract.contract.UnpackLog(event, "ARMSet", log); err != nil { +func (_RMNProxyContract *RMNProxyContractFilterer) ParseARMSet(log types.Log) (*RMNProxyContractARMSet, error) { + event := new(RMNProxyContractARMSet) + if err := _RMNProxyContract.contract.UnpackLog(event, "ARMSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMProxyContractOwnershipTransferRequestedIterator struct { - Event *ARMProxyContractOwnershipTransferRequested +type RMNProxyContractOwnershipTransferRequestedIterator struct { + Event *RMNProxyContractOwnershipTransferRequested contract *bind.BoundContract event string @@ -414,7 +414,7 @@ type ARMProxyContractOwnershipTransferRequestedIterator struct { fail error } -func (it *ARMProxyContractOwnershipTransferRequestedIterator) Next() bool { +func (it *RMNProxyContractOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -423,7 +423,7 @@ func (it *ARMProxyContractOwnershipTransferRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMProxyContractOwnershipTransferRequested) + it.Event = new(RMNProxyContractOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -438,7 +438,7 @@ func (it *ARMProxyContractOwnershipTransferRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMProxyContractOwnershipTransferRequested) + it.Event = new(RMNProxyContractOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -453,22 +453,22 @@ func (it *ARMProxyContractOwnershipTransferRequestedIterator) Next() bool { } } -func (it *ARMProxyContractOwnershipTransferRequestedIterator) Error() error { +func (it *RMNProxyContractOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *ARMProxyContractOwnershipTransferRequestedIterator) Close() error { +func (it *RMNProxyContractOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMProxyContractOwnershipTransferRequested struct { +type RMNProxyContractOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_ARMProxyContract *ARMProxyContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMProxyContractOwnershipTransferRequestedIterator, error) { +func (_RMNProxyContract *RMNProxyContractFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -479,14 +479,14 @@ func (_ARMProxyContract *ARMProxyContractFilterer) FilterOwnershipTransferReques toRule = append(toRule, toItem) } - logs, sub, err := _ARMProxyContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _RMNProxyContract.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &ARMProxyContractOwnershipTransferRequestedIterator{contract: _ARMProxyContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &RMNProxyContractOwnershipTransferRequestedIterator{contract: _RMNProxyContract.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ARMProxyContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -497,7 +497,7 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferRequest toRule = append(toRule, toItem) } - logs, sub, err := _ARMProxyContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _RMNProxyContract.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -507,8 +507,8 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferRequest select { case log := <-logs: - event := new(ARMProxyContractOwnershipTransferRequested) - if err := _ARMProxyContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(RMNProxyContractOwnershipTransferRequested) + if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -529,17 +529,17 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferRequest }), nil } -func (_ARMProxyContract *ARMProxyContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*ARMProxyContractOwnershipTransferRequested, error) { - event := new(ARMProxyContractOwnershipTransferRequested) - if err := _ARMProxyContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_RMNProxyContract *RMNProxyContractFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNProxyContractOwnershipTransferRequested, error) { + event := new(RMNProxyContractOwnershipTransferRequested) + if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type ARMProxyContractOwnershipTransferredIterator struct { - Event *ARMProxyContractOwnershipTransferred +type RMNProxyContractOwnershipTransferredIterator struct { + Event *RMNProxyContractOwnershipTransferred contract *bind.BoundContract event string @@ -550,7 +550,7 @@ type ARMProxyContractOwnershipTransferredIterator struct { fail error } -func (it *ARMProxyContractOwnershipTransferredIterator) Next() bool { +func (it *RMNProxyContractOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -559,7 +559,7 @@ func (it *ARMProxyContractOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ARMProxyContractOwnershipTransferred) + it.Event = new(RMNProxyContractOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -574,7 +574,7 @@ func (it *ARMProxyContractOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(ARMProxyContractOwnershipTransferred) + it.Event = new(RMNProxyContractOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -589,22 +589,22 @@ func (it *ARMProxyContractOwnershipTransferredIterator) Next() bool { } } -func (it *ARMProxyContractOwnershipTransferredIterator) Error() error { +func (it *RMNProxyContractOwnershipTransferredIterator) Error() error { return it.fail } -func (it *ARMProxyContractOwnershipTransferredIterator) Close() error { +func (it *RMNProxyContractOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type ARMProxyContractOwnershipTransferred struct { +type RMNProxyContractOwnershipTransferred struct { From common.Address To common.Address Raw types.Log } -func (_ARMProxyContract *ARMProxyContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMProxyContractOwnershipTransferredIterator, error) { +func (_RMNProxyContract *RMNProxyContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferredIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -615,14 +615,14 @@ func (_ARMProxyContract *ARMProxyContractFilterer) FilterOwnershipTransferred(op toRule = append(toRule, toItem) } - logs, sub, err := _ARMProxyContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _RMNProxyContract.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &ARMProxyContractOwnershipTransferredIterator{contract: _ARMProxyContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &RMNProxyContractOwnershipTransferredIterator{contract: _RMNProxyContract.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ARMProxyContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_RMNProxyContract *RMNProxyContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -633,7 +633,7 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferred(opt toRule = append(toRule, toItem) } - logs, sub, err := _ARMProxyContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _RMNProxyContract.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -643,8 +643,8 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferred(opt select { case log := <-logs: - event := new(ARMProxyContractOwnershipTransferred) - if err := _ARMProxyContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(RMNProxyContractOwnershipTransferred) + if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -665,46 +665,46 @@ func (_ARMProxyContract *ARMProxyContractFilterer) WatchOwnershipTransferred(opt }), nil } -func (_ARMProxyContract *ARMProxyContractFilterer) ParseOwnershipTransferred(log types.Log) (*ARMProxyContractOwnershipTransferred, error) { - event := new(ARMProxyContractOwnershipTransferred) - if err := _ARMProxyContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_RMNProxyContract *RMNProxyContractFilterer) ParseOwnershipTransferred(log types.Log) (*RMNProxyContractOwnershipTransferred, error) { + event := new(RMNProxyContractOwnershipTransferred) + if err := _RMNProxyContract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log return event, nil } -func (_ARMProxyContract *ARMProxyContract) ParseLog(log types.Log) (generated.AbigenLog, error) { +func (_RMNProxyContract *RMNProxyContract) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _ARMProxyContract.abi.Events["ARMSet"].ID: - return _ARMProxyContract.ParseARMSet(log) - case _ARMProxyContract.abi.Events["OwnershipTransferRequested"].ID: - return _ARMProxyContract.ParseOwnershipTransferRequested(log) - case _ARMProxyContract.abi.Events["OwnershipTransferred"].ID: - return _ARMProxyContract.ParseOwnershipTransferred(log) + 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) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (ARMProxyContractARMSet) Topic() common.Hash { +func (RMNProxyContractARMSet) Topic() common.Hash { return common.HexToHash("0xef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab") } -func (ARMProxyContractOwnershipTransferRequested) Topic() common.Hash { +func (RMNProxyContractOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } -func (ARMProxyContractOwnershipTransferred) Topic() common.Hash { +func (RMNProxyContractOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (_ARMProxyContract *ARMProxyContract) Address() common.Address { - return _ARMProxyContract.address +func (_RMNProxyContract *RMNProxyContract) Address() common.Address { + return _RMNProxyContract.address } -type ARMProxyContractInterface interface { +type RMNProxyContractInterface interface { GetARM(opts *bind.CallOpts) (common.Address, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -719,23 +719,23 @@ type ARMProxyContractInterface interface { Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) - FilterARMSet(opts *bind.FilterOpts) (*ARMProxyContractARMSetIterator, error) + FilterARMSet(opts *bind.FilterOpts) (*RMNProxyContractARMSetIterator, error) - WatchARMSet(opts *bind.WatchOpts, sink chan<- *ARMProxyContractARMSet) (event.Subscription, error) + WatchARMSet(opts *bind.WatchOpts, sink chan<- *RMNProxyContractARMSet) (event.Subscription, error) - ParseARMSet(log types.Log) (*ARMProxyContractARMSet, error) + ParseARMSet(log types.Log) (*RMNProxyContractARMSet, error) - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMProxyContractOwnershipTransferRequestedIterator, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferRequestedIterator, error) - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ARMProxyContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferRequested(log types.Log) (*ARMProxyContractOwnershipTransferRequested, error) + ParseOwnershipTransferRequested(log types.Log) (*RMNProxyContractOwnershipTransferRequested, error) - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ARMProxyContractOwnershipTransferredIterator, error) + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNProxyContractOwnershipTransferredIterator, error) - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ARMProxyContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNProxyContractOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferred(log types.Log) (*ARMProxyContractOwnershipTransferred, error) + ParseOwnershipTransferred(log types.Log) (*RMNProxyContractOwnershipTransferred, 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 new file mode 100644 index 00000000000..da84ba9c8cf --- /dev/null +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -0,0 +1,1235 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package rmn_remote + +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 IRMNRemoteSignature struct { + R [32]byte + S [32]byte +} + +type InternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + +type RMNRemoteConfig struct { + RmnHomeContractConfigDigest [32]byte + Signers []RMNRemoteSigner + MinSigners uint64 +} + +type RMNRemoteSigner struct { + OnchainPublicKey common.Address + NodeIndex uint64 +} + +var RMNRemoteMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"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\":\"minSigners\",\"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\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"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\":\"minSigners\",\"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[]\"},{\"internalType\":\"uint256\",\"name\":\"rawVs\",\"type\":\"uint256\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200216a3803806200216a8339810160408190526200003491620001a9565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fe565b505050806001600160401b0316600003620000ec5760405163273e150360e21b815260040160405180910390fd5b6001600160401b0316608052620001db565b336001600160a01b03821603620001585760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001bc57600080fd5b81516001600160401b0381168114620001d457600080fd5b9392505050565b608051611f6c620001fe6000396000818161027a0152610acb0152611f6c6000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806379ba509711610097578063d881e09211610066578063d881e09214610257578063eaa83ddd1461026c578063f2fde38b146102a4578063f8bb876e146102b757600080fd5b806379ba5097146102015780638d8741cb146102095780638da5cb5b1461021c5780639a19b3291461024457600080fd5b8063397796f7116100d3578063397796f7146101a557806362eed415146101ad5780636509a954146101c05780636d2d3993146101ee57600080fd5b8063181f5a7714610105578063198f0f77146101575780631add205f1461016c5780632cbc26bb14610182575b600080fd5b6101416040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161014e91906113b9565b60405180910390f35b61016a6101653660046113cc565b6102ca565b005b610174610676565b60405161014e929190611407565b6101956101903660046114e5565b61076e565b604051901515815260200161014e565b6101956107cb565b61016a6101bb3660046114e5565b610845565b6040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf53815260200161014e565b61016a6101fc3660046114e5565b6108b9565b61016a610929565b61016a61021736600461156e565b610a2b565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014e565b61016a6102523660046116f5565b610d7f565b61025f610e7c565b60405161014e9190611792565b60405167ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161014e565b61016a6102b23660046117f8565b610e88565b61016a6102c53660046116f5565b610e9c565b6102d2610f8e565b60015b6102e26020830183611815565b90508110156103b2576102f86020830183611815565b828181106103085761030861187d565b905060400201602001602081019061032091906118cd565b67ffffffffffffffff166103376020840184611815565b610342600185611919565b8181106103515761035161187d565b905060400201602001602081019061036991906118cd565b67ffffffffffffffff16106103aa576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016102d5565b506103c06020820182611815565b90506103d260608301604084016118cd565b67ffffffffffffffff161115610414576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b80156104a65760086000600361042f600185611919565b8154811061043f5761043f61187d565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561049f8161192c565b9050610418565b5060005b6104b76020830183611815565b90508110156105ec57600860006104d16020850185611815565b848181106104e1576104e161187d565b6104f792602060409092020190810191506117f8565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff1615610558576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016008600061056b6020860186611815565b8581811061057b5761057b61187d565b61059192602060409092020190810191506117f8565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556001016104aa565b508060026105fa8282611a1a565b5050600580546000919082906106159063ffffffff16611b55565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c8360405161066a9190611b78565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b82821015610745576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff16818301528252600190920191016106d7565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b600061077a6006611011565b60000361078957506000919050565b61079460068361101b565b806107c557506107c560067f010000000000000000000000000000010000000000000000000000000000000061101b565b92915050565b60006107d76006611011565b6000036107e45750600090565b61080f60067f010000000000000000000000000000000000000000000000000000000000000061101b565b80610840575061084060067f010000000000000000000000000000010000000000000000000000000000000061101b565b905090565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061087b5761087b61187d565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216602092830291909101909101526108b581610e9c565b5050565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106108ef576108ef61187d565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216602092830291909101909101526108b581610d7f565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60055463ffffffff16600003610a6d576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045467ffffffffffffffff16821015610ab3576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8716606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610b4f888a611c82565b9052604051610b62929190602001611de2565b60405160208183030381529060405280519060200120905060008060005b85811015610d7357600184610b9a82841b8816601b611f17565b898985818110610bac57610bac61187d565b905060400201600001358a8a86818110610bc857610bc861187d565b9050604002016020013560405160008152602001604052604051610c08949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610c2a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610ca2576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610d07576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610d66576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610b80565b50505050505050505050565b610d87610f8e565b60005b8151811015610e4157610dc0828281518110610da857610da861187d565b6020026020010151600661105990919063ffffffff16565b610e3957818181518110610dd657610dd661187d565b60200260200101516040517f73281fa10000000000000000000000000000000000000000000000000000000081526004016109a691907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610d8a565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610e719190611792565b60405180910390a150565b60606108406006611087565b610e90610f8e565b610e9981611094565b50565b610ea4610f8e565b60005b8151811015610f5e57610edd828281518110610ec557610ec561187d565b6020026020010151600661118990919063ffffffff16565b610f5657818181518110610ef357610ef361187d565b60200260200101516040517f19d5c79b0000000000000000000000000000000000000000000000000000000081526004016109a691907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610ea7565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610e719190611792565b60005473ffffffffffffffffffffffffffffffffffffffff16331461100f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016109a6565b565b60006107c5825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b6000611052837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166111b7565b60606000611052836112aa565b3373ffffffffffffffffffffffffffffffffffffffff821603611113576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016109a6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611052837fffffffffffffffffffffffffffffffff000000000000000000000000000000008416611306565b600081815260018301602052604081205480156112a05760006111db600183611919565b85549091506000906111ef90600190611919565b905080821461125457600086600001828154811061120f5761120f61187d565b90600052602060002001549050808760000184815481106112325761123261187d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061126557611265611f30565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107c5565b60009150506107c5565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112fa57602002820191906000526020600020905b8154815260200190600101908083116112e6575b50505050509050919050565b600081815260018301602052604081205461134d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107c5565b5060006107c5565b6000815180845260005b8181101561137b5760208185018101518683018201520161135f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006110526020830184611355565b6000602082840312156113de57600080fd5b813567ffffffffffffffff8111156113f557600080fd5b82016060818503121561105257600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b8083101561148c578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff1685830152928401926001929092019190850190611443565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146114e057600080fd5b919050565b6000602082840312156114f757600080fd5b611052826114b0565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9957600080fd5b60008083601f84011261153457600080fd5b50813567ffffffffffffffff81111561154c57600080fd5b6020830191508360208260061b850101111561156757600080fd5b9250929050565b6000806000806000806080878903121561158757600080fd5b863561159281611500565b9550602087013567ffffffffffffffff808211156115af57600080fd5b818901915089601f8301126115c357600080fd5b8135818111156115d257600080fd5b8a60208260051b85010111156115e757600080fd5b60208301975080965050604089013591508082111561160557600080fd5b5061161289828a01611522565b979a9699509497949695606090950135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561167c5761167c61162a565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156116c9576116c961162a565b604052919050565b600067ffffffffffffffff8211156116eb576116eb61162a565b5060051b60200190565b6000602080838503121561170857600080fd5b823567ffffffffffffffff81111561171f57600080fd5b8301601f8101851361173057600080fd5b803561174361173e826116d1565b611682565b81815260059190911b8201830190838101908783111561176257600080fd5b928401925b8284101561178757611778846114b0565b82529284019290840190611767565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117ec5783517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016835292840192918401916001016117ae565b50909695505050505050565b60006020828403121561180a57600080fd5b813561105281611500565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261184a57600080fd5b83018035915067ffffffffffffffff82111561186557600080fd5b6020019150600681901b360382131561156757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff81168114610e9957600080fd5b80356114e0816118ac565b6000602082840312156118df57600080fd5b8135611052816118ac565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156107c5576107c56118ea565b60008161193b5761193b6118ea565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600081356107c5816118ac565b813561197981611500565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356119c9816118ac565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611a5857600080fd5b8401803567ffffffffffffffff811115611a7157600080fd5b6020820191508060061b3603821315611a8957600080fd5b68010000000000000000811115611aa257611aa261162a565b825481845580821015611ad7576000848152602081208381019083015b80821015611ad35782825590870190611abf565b5050505b50600092835260208320925b81811015611b0757611af5838561196e565b92840192604092909201918401611ae3565b50505050506108b5611b1b60408401611961565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611b6e57611b6e6118ea565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611bbd57600080fd5b8501828101903567ffffffffffffffff80821115611bda57600080fd5b8160061b3603831315611bec57600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611c57578535611c1a81611500565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611c3f816118ac565b83168188015294810194600194909401938101611c07565b611c6360408b016118c2565b67ffffffffffffffff811660608b015296509998505050505050505050565b6000611c9061173e846116d1565b80848252602080830192508560051b850136811115611cae57600080fd5b855b81811015611dd657803567ffffffffffffffff80821115611cd15760008081fd5b818901915060a08236031215611ce75760008081fd5b611cef611659565b8235611cfa816118ac565b81528286013582811115611d0e5760008081fd5b8301601f3681830112611d215760008081fd5b813584811115611d3357611d3361162a565b611d62897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08484011601611682565b94508085523689828501011115611d7b57600091508182fd5b808984018a8701376000898287010152505050818682015260409150611da28284016118c2565b8282015260609150611db58284016118c2565b91810191909152608091820135918101919091528552938201938201611cb0565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b81811015611f04577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c0152611ed3858c0182611355565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a5298509689019692890192600101611e87565b50969d9c50505050505050505050505050565b60ff81811683821601908111156107c5576107c56118ea565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", +} + +var RMNRemoteABI = RMNRemoteMetaData.ABI + +var RMNRemoteBin = RMNRemoteMetaData.Bin + +func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, localChainSelector uint64) (common.Address, *types.Transaction, *RMNRemote, error) { + parsed, err := RMNRemoteMetaData.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(RMNRemoteBin), backend, localChainSelector) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &RMNRemote{address: address, abi: *parsed, RMNRemoteCaller: RMNRemoteCaller{contract: contract}, RMNRemoteTransactor: RMNRemoteTransactor{contract: contract}, RMNRemoteFilterer: RMNRemoteFilterer{contract: contract}}, nil +} + +type RMNRemote struct { + address common.Address + abi abi.ABI + RMNRemoteCaller + RMNRemoteTransactor + RMNRemoteFilterer +} + +type RMNRemoteCaller struct { + contract *bind.BoundContract +} + +type RMNRemoteTransactor struct { + contract *bind.BoundContract +} + +type RMNRemoteFilterer struct { + contract *bind.BoundContract +} + +type RMNRemoteSession struct { + Contract *RMNRemote + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type RMNRemoteCallerSession struct { + Contract *RMNRemoteCaller + CallOpts bind.CallOpts +} + +type RMNRemoteTransactorSession struct { + Contract *RMNRemoteTransactor + TransactOpts bind.TransactOpts +} + +type RMNRemoteRaw struct { + Contract *RMNRemote +} + +type RMNRemoteCallerRaw struct { + Contract *RMNRemoteCaller +} + +type RMNRemoteTransactorRaw struct { + Contract *RMNRemoteTransactor +} + +func NewRMNRemote(address common.Address, backend bind.ContractBackend) (*RMNRemote, error) { + abi, err := abi.JSON(strings.NewReader(RMNRemoteABI)) + if err != nil { + return nil, err + } + contract, err := bindRMNRemote(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &RMNRemote{address: address, abi: abi, RMNRemoteCaller: RMNRemoteCaller{contract: contract}, RMNRemoteTransactor: RMNRemoteTransactor{contract: contract}, RMNRemoteFilterer: RMNRemoteFilterer{contract: contract}}, nil +} + +func NewRMNRemoteCaller(address common.Address, caller bind.ContractCaller) (*RMNRemoteCaller, error) { + contract, err := bindRMNRemote(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RMNRemoteCaller{contract: contract}, nil +} + +func NewRMNRemoteTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNRemoteTransactor, error) { + contract, err := bindRMNRemote(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RMNRemoteTransactor{contract: contract}, nil +} + +func NewRMNRemoteFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNRemoteFilterer, error) { + contract, err := bindRMNRemote(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RMNRemoteFilterer{contract: contract}, nil +} + +func bindRMNRemote(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RMNRemoteMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_RMNRemote *RMNRemoteRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNRemote.Contract.RMNRemoteCaller.contract.Call(opts, result, method, params...) +} + +func (_RMNRemote *RMNRemoteRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.Contract.RMNRemoteTransactor.contract.Transfer(opts) +} + +func (_RMNRemote *RMNRemoteRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNRemote.Contract.RMNRemoteTransactor.contract.Transact(opts, method, params...) +} + +func (_RMNRemote *RMNRemoteCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNRemote.Contract.contract.Call(opts, result, method, params...) +} + +func (_RMNRemote *RMNRemoteTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.Contract.contract.Transfer(opts) +} + +func (_RMNRemote *RMNRemoteTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNRemote.Contract.contract.Transact(opts, method, params...) +} + +func (_RMNRemote *RMNRemoteCaller) GetCursedSubjects(opts *bind.CallOpts) ([][16]byte, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getCursedSubjects") + + if err != nil { + return *new([][16]byte), err + } + + out0 := *abi.ConvertType(out[0], new([][16]byte)).(*[][16]byte) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) GetCursedSubjects() ([][16]byte, error) { + return _RMNRemote.Contract.GetCursedSubjects(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetCursedSubjects() ([][16]byte, error) { + return _RMNRemote.Contract.GetCursedSubjects(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) GetLocalChainSelector(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getLocalChainSelector") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) GetLocalChainSelector() (uint64, error) { + return _RMNRemote.Contract.GetLocalChainSelector(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetLocalChainSelector() (uint64, error) { + return _RMNRemote.Contract.GetLocalChainSelector(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) GetReportDigestHeader(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getReportDigestHeader") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) GetReportDigestHeader() ([32]byte, error) { + return _RMNRemote.Contract.GetReportDigestHeader(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetReportDigestHeader() ([32]byte, error) { + return _RMNRemote.Contract.GetReportDigestHeader(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) GetVersionedConfig(opts *bind.CallOpts) (GetVersionedConfig, + + error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getVersionedConfig") + + outstruct := new(GetVersionedConfig) + if err != nil { + return *outstruct, err + } + + outstruct.Version = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.Config = *abi.ConvertType(out[1], new(RMNRemoteConfig)).(*RMNRemoteConfig) + + return *outstruct, err + +} + +func (_RMNRemote *RMNRemoteSession) GetVersionedConfig() (GetVersionedConfig, + + error) { + return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetVersionedConfig() (GetVersionedConfig, + + error) { + return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "isCursed", subject) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) IsCursed(subject [16]byte) (bool, error) { + return _RMNRemote.Contract.IsCursed(&_RMNRemote.CallOpts, subject) +} + +func (_RMNRemote *RMNRemoteCallerSession) IsCursed(subject [16]byte) (bool, error) { + return _RMNRemote.Contract.IsCursed(&_RMNRemote.CallOpts, subject) +} + +func (_RMNRemote *RMNRemoteCaller) IsCursed0(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "isCursed0") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) IsCursed0() (bool, error) { + return _RMNRemote.Contract.IsCursed0(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) IsCursed0() (bool, error) { + return _RMNRemote.Contract.IsCursed0(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RMNRemote.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 (_RMNRemote *RMNRemoteSession) Owner() (common.Address, error) { + return _RMNRemote.Contract.Owner(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) Owner() (common.Address, error) { + return _RMNRemote.Contract.Owner(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) TypeAndVersion() (string, error) { + return _RMNRemote.Contract.TypeAndVersion(&_RMNRemote.CallOpts) +} + +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, rawVs *big.Int) error { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "verify", offrampAddress, merkleRoots, signatures, rawVs) + + if err != nil { + return err + } + + return err + +} + +func (_RMNRemote *RMNRemoteSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature, rawVs *big.Int) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures, rawVs) +} + +func (_RMNRemote *RMNRemoteCallerSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature, rawVs *big.Int) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures, rawVs) +} + +func (_RMNRemote *RMNRemoteTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "acceptOwnership") +} + +func (_RMNRemote *RMNRemoteSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNRemote.Contract.AcceptOwnership(&_RMNRemote.TransactOpts) +} + +func (_RMNRemote *RMNRemoteTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNRemote.Contract.AcceptOwnership(&_RMNRemote.TransactOpts) +} + +func (_RMNRemote *RMNRemoteTransactor) Curse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "curse", subject) +} + +func (_RMNRemote *RMNRemoteSession) Curse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Curse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactor) Curse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "curse0", subjects) +} + +func (_RMNRemote *RMNRemoteSession) Curse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse0(&_RMNRemote.TransactOpts, subjects) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Curse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse0(&_RMNRemote.TransactOpts, subjects) +} + +func (_RMNRemote *RMNRemoteTransactor) SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "setConfig", newConfig) +} + +func (_RMNRemote *RMNRemoteSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +} + +func (_RMNRemote *RMNRemoteTransactorSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +} + +func (_RMNRemote *RMNRemoteTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "transferOwnership", to) +} + +func (_RMNRemote *RMNRemoteSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNRemote.Contract.TransferOwnership(&_RMNRemote.TransactOpts, to) +} + +func (_RMNRemote *RMNRemoteTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNRemote.Contract.TransferOwnership(&_RMNRemote.TransactOpts, to) +} + +func (_RMNRemote *RMNRemoteTransactor) Uncurse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "uncurse", subject) +} + +func (_RMNRemote *RMNRemoteSession) Uncurse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Uncurse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactor) Uncurse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "uncurse0", subjects) +} + +func (_RMNRemote *RMNRemoteSession) Uncurse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse0(&_RMNRemote.TransactOpts, subjects) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Uncurse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse0(&_RMNRemote.TransactOpts, subjects) +} + +type RMNRemoteConfigSetIterator struct { + Event *RMNRemoteConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteConfigSet) + 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(RMNRemoteConfigSet) + 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 *RMNRemoteConfigSetIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteConfigSet struct { + Version uint32 + Config RMNRemoteConfig + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterConfigSet(opts *bind.FilterOpts, version []uint32) (*RMNRemoteConfigSetIterator, error) { + + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "ConfigSet", versionRule) + if err != nil { + return nil, err + } + return &RMNRemoteConfigSetIterator{contract: _RMNRemote.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet, version []uint32) (event.Subscription, error) { + + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "ConfigSet", versionRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteConfigSet) + if err := _RMNRemote.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 (_RMNRemote *RMNRemoteFilterer) ParseConfigSet(log types.Log) (*RMNRemoteConfigSet, error) { + event := new(RMNRemoteConfigSet) + if err := _RMNRemote.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNRemoteCursedIterator struct { + Event *RMNRemoteCursed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteCursedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteCursed) + 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(RMNRemoteCursed) + 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 *RMNRemoteCursedIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteCursedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteCursed struct { + Subjects [][16]byte + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterCursed(opts *bind.FilterOpts) (*RMNRemoteCursedIterator, error) { + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "Cursed") + if err != nil { + return nil, err + } + return &RMNRemoteCursedIterator{contract: _RMNRemote.contract, event: "Cursed", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchCursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteCursed) (event.Subscription, error) { + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "Cursed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteCursed) + if err := _RMNRemote.contract.UnpackLog(event, "Cursed", 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 (_RMNRemote *RMNRemoteFilterer) ParseCursed(log types.Log) (*RMNRemoteCursed, error) { + event := new(RMNRemoteCursed) + if err := _RMNRemote.contract.UnpackLog(event, "Cursed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNRemoteOwnershipTransferRequestedIterator struct { + Event *RMNRemoteOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteOwnershipTransferRequested) + 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(RMNRemoteOwnershipTransferRequested) + 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 *RMNRemoteOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferRequestedIterator, 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 := _RMNRemote.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &RMNRemoteOwnershipTransferRequestedIterator{contract: _RMNRemote.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferRequested, 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 := _RMNRemote.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(RMNRemoteOwnershipTransferRequested) + if err := _RMNRemote.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 (_RMNRemote *RMNRemoteFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNRemoteOwnershipTransferRequested, error) { + event := new(RMNRemoteOwnershipTransferRequested) + if err := _RMNRemote.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNRemoteOwnershipTransferredIterator struct { + Event *RMNRemoteOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteOwnershipTransferred) + 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(RMNRemoteOwnershipTransferred) + 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 *RMNRemoteOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferredIterator, 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 := _RMNRemote.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &RMNRemoteOwnershipTransferredIterator{contract: _RMNRemote.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferred, 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 := _RMNRemote.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(RMNRemoteOwnershipTransferred) + if err := _RMNRemote.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 (_RMNRemote *RMNRemoteFilterer) ParseOwnershipTransferred(log types.Log) (*RMNRemoteOwnershipTransferred, error) { + event := new(RMNRemoteOwnershipTransferred) + if err := _RMNRemote.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNRemoteUncursedIterator struct { + Event *RMNRemoteUncursed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteUncursedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteUncursed) + 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(RMNRemoteUncursed) + 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 *RMNRemoteUncursedIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteUncursedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteUncursed struct { + Subjects [][16]byte + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterUncursed(opts *bind.FilterOpts) (*RMNRemoteUncursedIterator, error) { + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "Uncursed") + if err != nil { + return nil, err + } + return &RMNRemoteUncursedIterator{contract: _RMNRemote.contract, event: "Uncursed", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchUncursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteUncursed) (event.Subscription, error) { + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "Uncursed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteUncursed) + if err := _RMNRemote.contract.UnpackLog(event, "Uncursed", 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 (_RMNRemote *RMNRemoteFilterer) ParseUncursed(log types.Log) (*RMNRemoteUncursed, error) { + event := new(RMNRemoteUncursed) + if err := _RMNRemote.contract.UnpackLog(event, "Uncursed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetVersionedConfig struct { + Version uint32 + Config RMNRemoteConfig +} + +func (_RMNRemote *RMNRemote) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _RMNRemote.abi.Events["ConfigSet"].ID: + return _RMNRemote.ParseConfigSet(log) + case _RMNRemote.abi.Events["Cursed"].ID: + return _RMNRemote.ParseCursed(log) + case _RMNRemote.abi.Events["OwnershipTransferRequested"].ID: + return _RMNRemote.ParseOwnershipTransferRequested(log) + case _RMNRemote.abi.Events["OwnershipTransferred"].ID: + return _RMNRemote.ParseOwnershipTransferred(log) + case _RMNRemote.abi.Events["Uncursed"].ID: + return _RMNRemote.ParseUncursed(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (RMNRemoteConfigSet) Topic() common.Hash { + return common.HexToHash("0x7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c") +} + +func (RMNRemoteCursed) Topic() common.Hash { + return common.HexToHash("0x1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f74") +} + +func (RMNRemoteOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (RMNRemoteOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (RMNRemoteUncursed) Topic() common.Hash { + return common.HexToHash("0x0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba1") +} + +func (_RMNRemote *RMNRemote) Address() common.Address { + return _RMNRemote.address +} + +type RMNRemoteInterface interface { + GetCursedSubjects(opts *bind.CallOpts) ([][16]byte, error) + + GetLocalChainSelector(opts *bind.CallOpts) (uint64, error) + + GetReportDigestHeader(opts *bind.CallOpts) ([32]byte, error) + + GetVersionedConfig(opts *bind.CallOpts) (GetVersionedConfig, + + error) + + IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) + + IsCursed0(opts *bind.CallOpts) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature, rawVs *big.Int) error + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + Curse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) + + Curse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + Uncurse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) + + Uncurse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts, version []uint32) (*RMNRemoteConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet, version []uint32) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*RMNRemoteConfigSet, error) + + FilterCursed(opts *bind.FilterOpts) (*RMNRemoteCursedIterator, error) + + WatchCursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteCursed) (event.Subscription, error) + + ParseCursed(log types.Log) (*RMNRemoteCursed, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*RMNRemoteOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*RMNRemoteOwnershipTransferred, error) + + FilterUncursed(opts *bind.FilterOpts) (*RMNRemoteUncursedIterator, error) + + WatchUncursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteUncursed) (event.Subscription, error) + + ParseUncursed(log types.Log) (*RMNRemoteUncursed, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/router/router.go b/core/gethwrappers/ccip/generated/router/router.go index c53d4824b16..9a0d4a40559 100644 --- a/core/gethwrappers/ccip/generated/router/router.go +++ b/core/gethwrappers/ccip/generated/router/router.go @@ -63,7 +63,7 @@ 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: "0x60a06040523480156200001157600080fd5b5060405162002d2838038062002d288339810160408190526200003491620001af565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e7565b5050600280546001600160a01b0319166001600160a01b039485161790555016608052620001e7565b336001600160a01b03821603620001415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001aa57600080fd5b919050565b60008060408385031215620001c357600080fd5b620001ce8362000192565b9150620001de6020840162000192565b90509250929050565b608051612b1762000211600039600081816101f9015281816105e10152610af20152612b176000f3fe6080604052600436106101295760003560e01c80638da5cb5b116100a5578063a8d87a3b11610074578063e861e90711610059578063e861e90714610409578063f2fde38b14610434578063fbca3b741461045457600080fd5b8063a8d87a3b1461039c578063da5fcac8146103e957600080fd5b80638da5cb5b146102ed57806396f4e9f914610318578063a40e69c71461032b578063a48a90581461034d57600080fd5b806352cb60ca116100fc578063787350e3116100e1578063787350e31461028057806379ba5097146102a857806383826b2b146102bd57600080fd5b806352cb60ca1461023e5780635f3e849f1461026057600080fd5b8063181f5a771461012e57806320487ded1461018d5780633cf97983146101bb5780635246492f146101ea575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280600c81526020017f526f7574657220312e322e30000000000000000000000000000000000000000081525081565b6040516101849190611f3c565b60405180910390f35b34801561019957600080fd5b506101ad6101a83660046121ad565b610481565b604051908152602001610184565b3480156101c757600080fd5b506101db6101d63660046122aa565b6105d9565b60405161018493929190612322565b3480156101f657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561024a57600080fd5b5061025e61025936600461234d565b610836565b005b34801561026c57600080fd5b5061025e61027b36600461236a565b610885565b34801561028c57600080fd5b50610295608481565b60405161ffff9091168152602001610184565b3480156102b457600080fd5b5061025e6109d3565b3480156102c957600080fd5b506102dd6102d83660046123ab565b610ad0565b6040519015158152602001610184565b3480156102f957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610219565b6101ad6103263660046121ad565b610aee565b34801561033757600080fd5b50610340611087565b60405161018491906123e2565b34801561035957600080fd5b506102dd610368366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b3480156103a857600080fd5b506102196103b7366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b3480156103f557600080fd5b5061025e6104043660046124b8565b61118b565b34801561041557600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff16610219565b34801561044057600080fd5b5061025e61044f36600461234d565b611490565b34801561046057600080fd5b5061047461046f366004612451565b6114a4565b6040516101849190612552565b606081015160009073ffffffffffffffffffffffffffffffffffffffff166104c25760025473ffffffffffffffffffffffffffffffffffffffff1660608301525b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff168061053a576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216906320487ded9061058e9087908790600401612689565b602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf91906126ac565b9150505b92915050565b6000606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e91906126c5565b156106a5576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106be6106b86040890160208a01612451565b33610ad0565b6106f4576040517fd2316ede00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006385572ffb60e01b8860405160240161070f91906127f4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905061079c8186888a60846115c4565b919550935091507f9b877de93ea9895756e337442c657f95a34fc68e7eb988bdfa693d5be83016b688356107d660408b0160208c01612451565b83516020850120604051610823939291339193845267ffffffffffffffff92909216602084015273ffffffffffffffffffffffffffffffffffffffff166040830152606082015260800190565b60405180910390a1509450945094915050565b61083e6116ea565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61088d6116ea565b73ffffffffffffffffffffffffffffffffffffffff82166108f2576040517f26a78f8f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610531565b73ffffffffffffffffffffffffffffffffffffffff83166109ad5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610967576040519150601f19603f3d011682016040523d82523d6000602084013e61096c565b606091505b50509050806109a7576040517fe417b80b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6109ce73ffffffffffffffffffffffffffffffffffffffff8416838361176d565b505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610531565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000610ae7610adf8484611841565b600490611885565b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f91906126c5565b15610bb6576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610c29576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610531565b606083015160009073ffffffffffffffffffffffffffffffffffffffff16610dbb5760025473ffffffffffffffffffffffffffffffffffffffff90811660608601526040517f20487ded000000000000000000000000000000000000000000000000000000008152908316906320487ded90610cab9088908890600401612689565b602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec91906126ac565b905080341015610d28576040517f07da6ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b349050836060015173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505050506060850151610db6915073ffffffffffffffffffffffffffffffffffffffff16838361176d565b610eb2565b3415610df3576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906320487ded90610e479088908890600401612689565b602060405180830381865afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906126ac565b6060850151909150610eb29073ffffffffffffffffffffffffffffffffffffffff1633848461189d565b60005b846040015151811015610fe257600085604001518281518110610eda57610eda612900565b6020908102919091010151516040517f48a98aa400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8916600482015273ffffffffffffffffffffffffffffffffffffffff8083166024830152919250610fd9913391908716906348a98aa490604401602060405180830381865afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f90919061292f565b88604001518581518110610fa657610fa6612900565b6020026020010151602001518473ffffffffffffffffffffffffffffffffffffffff1661189d909392919063ffffffff16565b50600101610eb5565b506040517fdf0aa9e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063df0aa9e99061103b90889088908690339060040161294c565b6020604051808303816000875af115801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e91906126ac565b95945050505050565b6060600061109560046118fb565b90506000815167ffffffffffffffff8111156110b3576110b3611f6c565b6040519080825280602002602001820160405280156110f857816020015b60408051808201909152600080825260208201528152602001906001900390816110d15790505b50905060005b825181101561118457600083828151811061111b5761111b612900565b60200260200101519050604051806040016040528060a083901c67ffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681525083838151811061117057611170612900565b6020908102919091010152506001016110fe565b5092915050565b6111936116ea565b60005b8581101561126f5760008787838181106111b2576111b2612900565b9050604002018036038101906111c8919061299c565b60208181018051835167ffffffffffffffff90811660009081526003855260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055855193519051921682529394509216917f1f7d0ec248b80e5c0dde0ee531c4fc8fdb6ce9a2b3d90f560c74acd6a7202f23910160405180910390a250600101611196565b5060005b838110156113a757600085858381811061128f5761128f612900565b6112a59260206040909202019081019150612451565b905060008686848181106112bb576112bb612900565b90506040020160200160208101906112d3919061234d565b90506112ea6112e28383611841565b600490611908565b611348576040517f4964779000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152604401610531565b60405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa823809efda3ba66c873364eec120fa0923d9fabda73bc97dd5663341e2d9bcb9060200160405180910390a25050600101611273565b5060005b818110156114875760008383838181106113c7576113c7612900565b6113dd9260206040909202019081019150612451565b905060008484848181106113f3576113f3612900565b905060400201602001602081019061140b919061234d565b905061142261141a8383611841565b600490611914565b1561147d5760405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa4bdf64ebdf3316320601a081916a75aa144bcef6c4beeb0e9fb1982cacc6b949060200160405180910390a25b50506001016113ab565b50505050505050565b6114986116ea565b6114a181611920565b50565b60606114de8267ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b6114f8576040805160008082526020820190925290611184565b67ffffffffffffffff8216600081815260036020526040908190205490517ffbca3b74000000000000000000000000000000000000000000000000000000008152600481019290925273ffffffffffffffffffffffffffffffffffffffff169063fbca3b7490602401600060405180830381865afa15801561157e573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d391908101906129db565b6000606060008361ffff1667ffffffffffffffff8111156115e7576115e7611f6c565b6040519080825280601f01601f191660200182016040528015611611576020820181803683370190505b509150863b611644577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015611677577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b85900360408104810387106116b0577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156116d35750835b808352806000602085013e50955095509592505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461176b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610531565b565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109ce9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a15565b6000610ae773ffffffffffffffffffffffffffffffffffffffff83167bffffffffffffffff000000000000000000000000000000000000000060a086901b16612a99565b60008181526001830160205260408120541515610ae7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526109a79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016117bf565b60606000610ae783611b21565b6000610ae78383611b7d565b6000610ae78383611c70565b3373ffffffffffffffffffffffffffffffffffffffff82160361199f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610531565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611a77826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611cbf9092919063ffffffff16565b8051909150156109ce5780806020019051810190611a9591906126c5565b6109ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610531565b606081600001805480602002602001604051908101604052809291908181526020018280548015611b7157602002820191906000526020600020905b815481526020019060010190808311611b5d575b50505050509050919050565b60008181526001830160205260408120548015611c66576000611ba1600183612aac565b8554909150600090611bb590600190612aac565b9050818114611c1a576000866000018281548110611bd557611bd5612900565b9060005260206000200154905080876000018481548110611bf857611bf8612900565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c2b57611c2b612abf565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d3565b60009150506105d3565b6000818152600183016020526040812054611cb7575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d3565b5060006105d3565b6060611cce8484600085611cd6565b949350505050565b606082471015611d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610531565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611d919190612aee565b60006040518083038185875af1925050503d8060008114611dce576040519150601f19603f3d011682016040523d82523d6000602084013e611dd3565b606091505b5091509150611de487838387611def565b979650505050505050565b60608315611e85578251600003611e7e5773ffffffffffffffffffffffffffffffffffffffff85163b611e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610531565b5081611cce565b611cce8383815115611e9a5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105319190611f3c565b60005b83811015611ee9578181015183820152602001611ed1565b50506000910152565b60008151808452611f0a816020860160208601611ece565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ae76020830184611ef2565b803567ffffffffffffffff81168114611f6757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b60405290565b60405160a0810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561202e5761202e611f6c565b604052919050565b600082601f83011261204757600080fd5b813567ffffffffffffffff81111561206157612061611f6c565b61209260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fe7565b8181528460208386010111156120a757600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156120de576120de611f6c565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146114a157600080fd5b8035611f67816120e8565b600082601f83011261212657600080fd5b8135602061213b612136836120c4565b611fe7565b82815260069290921b8401810191818101908684111561215a57600080fd5b8286015b848110156121a257604081890312156121775760008081fd5b61217f611f9b565b813561218a816120e8565b8152818501358582015283529183019160400161215e565b509695505050505050565b600080604083850312156121c057600080fd5b6121c983611f4f565b9150602083013567ffffffffffffffff808211156121e657600080fd5b9084019060a082870312156121fa57600080fd5b612202611fc4565b82358281111561221157600080fd5b61221d88828601612036565b82525060208301358281111561223257600080fd5b61223e88828601612036565b60208301525060408301358281111561225657600080fd5b61226288828601612115565b6040830152506122746060840161210a565b606082015260808301358281111561228b57600080fd5b61229788828601612036565b6080830152508093505050509250929050565b600080600080608085870312156122c057600080fd5b843567ffffffffffffffff8111156122d757600080fd5b850160a081880312156122e957600080fd5b9350602085013561ffff8116811461230057600080fd5b9250604085013591506060850135612317816120e8565b939692955090935050565b831515815260606020820152600061233d6060830185611ef2565b9050826040830152949350505050565b60006020828403121561235f57600080fd5b8135610ae7816120e8565b60008060006060848603121561237f57600080fd5b833561238a816120e8565b9250602084013561239a816120e8565b929592945050506040919091013590565b600080604083850312156123be57600080fd5b6123c783611f4f565b915060208301356123d7816120e8565b809150509250929050565b602080825282518282018190526000919060409081850190868401855b82811015612444578151805167ffffffffffffffff16855286015173ffffffffffffffffffffffffffffffffffffffff168685015292840192908501906001016123ff565b5091979650505050505050565b60006020828403121561246357600080fd5b610ae782611f4f565b60008083601f84011261247e57600080fd5b50813567ffffffffffffffff81111561249657600080fd5b6020830191508360208260061b85010111156124b157600080fd5b9250929050565b600080600080600080606087890312156124d157600080fd5b863567ffffffffffffffff808211156124e957600080fd5b6124f58a838b0161246c565b9098509650602089013591508082111561250e57600080fd5b61251a8a838b0161246c565b9096509450604089013591508082111561253357600080fd5b5061254089828a0161246c565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b818110156125a057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161256e565b50909695505050505050565b6000815160a084526125c160a0850182611ef2565b9050602080840151858303828701526125da8382611ef2565b60408681015188830389830152805180845290850195509092506000918401905b8083101561263a578551805173ffffffffffffffffffffffffffffffffffffffff168352850151858301529484019460019290920191908301906125fb565b5060608701519450612664606089018673ffffffffffffffffffffffffffffffffffffffff169052565b60808701519450878103608089015261267d8186611ef2565b98975050505050505050565b67ffffffffffffffff83168152604060208201526000611cce60408301846125ac565b6000602082840312156126be57600080fd5b5051919050565b6000602082840312156126d757600080fd5b81518015158114610ae757600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261271c57600080fd5b830160208101925035905067ffffffffffffffff81111561273c57600080fd5b8036038213156124b157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156127e95781356127b7816120e8565b73ffffffffffffffffffffffffffffffffffffffff1687528183013583880152604096870196909101906001016127a4565b509495945050505050565b6020815281356020820152600061280d60208401611f4f565b67ffffffffffffffff808216604085015261282b60408601866126e7565b925060a0606086015261284260c08601848361274b565b92505061285260608601866126e7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08087860301608088015261288885838561274b565b9450608088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030183126128c157600080fd5b602092880192830192359150838211156128da57600080fd5b8160061b36038313156128ec57600080fd5b8685030160a0870152611de4848284612794565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561294157600080fd5b8151610ae7816120e8565b67ffffffffffffffff8516815260806020820152600061296f60808301866125ac565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b6000604082840312156129ae57600080fd5b6129b6611f9b565b6129bf83611f4f565b815260208301356129cf816120e8565b60208201529392505050565b600060208083850312156129ee57600080fd5b825167ffffffffffffffff811115612a0557600080fd5b8301601f81018513612a1657600080fd5b8051612a24612136826120c4565b81815260059190911b82018301908381019087831115612a4357600080fd5b928401925b82841015611de4578351612a5b816120e8565b82529284019290840190612a48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156105d3576105d3612a6a565b818103818111156105d3576105d3612a6a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b00818460208701611ece565b919091019291505056fea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b5060405162002d2838038062002d288339810160408190526200003491620001af565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e7565b5050600280546001600160a01b0319166001600160a01b039485161790555016608052620001e7565b336001600160a01b03821603620001415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001aa57600080fd5b919050565b60008060408385031215620001c357600080fd5b620001ce8362000192565b9150620001de6020840162000192565b90509250929050565b608051612b1762000211600039600081816101f9015281816105e10152610af20152612b176000f3fe6080604052600436106101295760003560e01c80638da5cb5b116100a5578063a8d87a3b11610074578063e861e90711610059578063e861e90714610409578063f2fde38b14610434578063fbca3b741461045457600080fd5b8063a8d87a3b1461039c578063da5fcac8146103e957600080fd5b80638da5cb5b146102ed57806396f4e9f914610318578063a40e69c71461032b578063a48a90581461034d57600080fd5b806352cb60ca116100fc578063787350e3116100e1578063787350e31461028057806379ba5097146102a857806383826b2b146102bd57600080fd5b806352cb60ca1461023e5780635f3e849f1461026057600080fd5b8063181f5a771461012e57806320487ded1461018d5780633cf97983146101bb5780635246492f146101ea575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280600c81526020017f526f7574657220312e322e30000000000000000000000000000000000000000081525081565b6040516101849190611f3c565b60405180910390f35b34801561019957600080fd5b506101ad6101a83660046121ad565b610481565b604051908152602001610184565b3480156101c757600080fd5b506101db6101d63660046122aa565b6105d9565b60405161018493929190612322565b3480156101f657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561024a57600080fd5b5061025e61025936600461234d565b610836565b005b34801561026c57600080fd5b5061025e61027b36600461236a565b610885565b34801561028c57600080fd5b50610295608481565b60405161ffff9091168152602001610184565b3480156102b457600080fd5b5061025e6109d3565b3480156102c957600080fd5b506102dd6102d83660046123ab565b610ad0565b6040519015158152602001610184565b3480156102f957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610219565b6101ad6103263660046121ad565b610aee565b34801561033757600080fd5b50610340611087565b60405161018491906123e2565b34801561035957600080fd5b506102dd610368366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b3480156103a857600080fd5b506102196103b7366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b3480156103f557600080fd5b5061025e6104043660046124b8565b61118b565b34801561041557600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff16610219565b34801561044057600080fd5b5061025e61044f36600461234d565b611490565b34801561046057600080fd5b5061047461046f366004612451565b6114a4565b6040516101849190612552565b606081015160009073ffffffffffffffffffffffffffffffffffffffff166104c25760025473ffffffffffffffffffffffffffffffffffffffff1660608301525b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff168061053a576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216906320487ded9061058e9087908790600401612689565b602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf91906126ac565b9150505b92915050565b6000606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e91906126c5565b156106a5576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106be6106b86040890160208a01612451565b33610ad0565b6106f4576040517fd2316ede00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006385572ffb60e01b8860405160240161070f91906127f4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905061079c8186888a60846115c4565b919550935091507f9b877de93ea9895756e337442c657f95a34fc68e7eb988bdfa693d5be83016b688356107d660408b0160208c01612451565b83516020850120604051610823939291339193845267ffffffffffffffff92909216602084015273ffffffffffffffffffffffffffffffffffffffff166040830152606082015260800190565b60405180910390a1509450945094915050565b61083e6116ea565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61088d6116ea565b73ffffffffffffffffffffffffffffffffffffffff82166108f2576040517f26a78f8f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610531565b73ffffffffffffffffffffffffffffffffffffffff83166109ad5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610967576040519150601f19603f3d011682016040523d82523d6000602084013e61096c565b606091505b50509050806109a7576040517fe417b80b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6109ce73ffffffffffffffffffffffffffffffffffffffff8416838361176d565b505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610531565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000610ae7610adf8484611841565b600490611885565b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f91906126c5565b15610bb6576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610c29576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610531565b606083015160009073ffffffffffffffffffffffffffffffffffffffff16610dbb5760025473ffffffffffffffffffffffffffffffffffffffff90811660608601526040517f20487ded000000000000000000000000000000000000000000000000000000008152908316906320487ded90610cab9088908890600401612689565b602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec91906126ac565b905080341015610d28576040517f07da6ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b349050836060015173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505050506060850151610db6915073ffffffffffffffffffffffffffffffffffffffff16838361176d565b610eb2565b3415610df3576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906320487ded90610e479088908890600401612689565b602060405180830381865afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906126ac565b6060850151909150610eb29073ffffffffffffffffffffffffffffffffffffffff1633848461189d565b60005b846040015151811015610fe257600085604001518281518110610eda57610eda612900565b6020908102919091010151516040517f48a98aa400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8916600482015273ffffffffffffffffffffffffffffffffffffffff8083166024830152919250610fd9913391908716906348a98aa490604401602060405180830381865afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f90919061292f565b88604001518581518110610fa657610fa6612900565b6020026020010151602001518473ffffffffffffffffffffffffffffffffffffffff1661189d909392919063ffffffff16565b50600101610eb5565b506040517fdf0aa9e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063df0aa9e99061103b90889088908690339060040161294c565b6020604051808303816000875af115801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e91906126ac565b95945050505050565b6060600061109560046118fb565b90506000815167ffffffffffffffff8111156110b3576110b3611f6c565b6040519080825280602002602001820160405280156110f857816020015b60408051808201909152600080825260208201528152602001906001900390816110d15790505b50905060005b825181101561118457600083828151811061111b5761111b612900565b60200260200101519050604051806040016040528060a083901c67ffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681525083838151811061117057611170612900565b6020908102919091010152506001016110fe565b5092915050565b6111936116ea565b60005b8581101561126f5760008787838181106111b2576111b2612900565b9050604002018036038101906111c8919061299c565b60208181018051835167ffffffffffffffff90811660009081526003855260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055855193519051921682529394509216917f1f7d0ec248b80e5c0dde0ee531c4fc8fdb6ce9a2b3d90f560c74acd6a7202f23910160405180910390a250600101611196565b5060005b838110156113a757600085858381811061128f5761128f612900565b6112a59260206040909202019081019150612451565b905060008686848181106112bb576112bb612900565b90506040020160200160208101906112d3919061234d565b90506112ea6112e28383611841565b600490611908565b611348576040517f4964779000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152604401610531565b60405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa823809efda3ba66c873364eec120fa0923d9fabda73bc97dd5663341e2d9bcb9060200160405180910390a25050600101611273565b5060005b818110156114875760008383838181106113c7576113c7612900565b6113dd9260206040909202019081019150612451565b905060008484848181106113f3576113f3612900565b905060400201602001602081019061140b919061234d565b905061142261141a8383611841565b600490611914565b1561147d5760405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa4bdf64ebdf3316320601a081916a75aa144bcef6c4beeb0e9fb1982cacc6b949060200160405180910390a25b50506001016113ab565b50505050505050565b6114986116ea565b6114a181611920565b50565b60606114de8267ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b6114f8576040805160008082526020820190925290611184565b67ffffffffffffffff8216600081815260036020526040908190205490517ffbca3b74000000000000000000000000000000000000000000000000000000008152600481019290925273ffffffffffffffffffffffffffffffffffffffff169063fbca3b7490602401600060405180830381865afa15801561157e573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d391908101906129db565b6000606060008361ffff1667ffffffffffffffff8111156115e7576115e7611f6c565b6040519080825280601f01601f191660200182016040528015611611576020820181803683370190505b509150863b611644577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015611677577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b85900360408104810387106116b0577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156116d35750835b808352806000602085013e50955095509592505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461176b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610531565b565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109ce9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a15565b6000610ae773ffffffffffffffffffffffffffffffffffffffff83167bffffffffffffffff000000000000000000000000000000000000000060a086901b16612a99565b60008181526001830160205260408120541515610ae7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526109a79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016117bf565b60606000610ae783611b21565b6000610ae78383611b7d565b6000610ae78383611c70565b3373ffffffffffffffffffffffffffffffffffffffff82160361199f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610531565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611a77826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611cbf9092919063ffffffff16565b8051909150156109ce5780806020019051810190611a9591906126c5565b6109ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610531565b606081600001805480602002602001604051908101604052809291908181526020018280548015611b7157602002820191906000526020600020905b815481526020019060010190808311611b5d575b50505050509050919050565b60008181526001830160205260408120548015611c66576000611ba1600183612aac565b8554909150600090611bb590600190612aac565b9050808214611c1a576000866000018281548110611bd557611bd5612900565b9060005260206000200154905080876000018481548110611bf857611bf8612900565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c2b57611c2b612abf565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d3565b60009150506105d3565b6000818152600183016020526040812054611cb7575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d3565b5060006105d3565b6060611cce8484600085611cd6565b949350505050565b606082471015611d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610531565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611d919190612aee565b60006040518083038185875af1925050503d8060008114611dce576040519150601f19603f3d011682016040523d82523d6000602084013e611dd3565b606091505b5091509150611de487838387611def565b979650505050505050565b60608315611e85578251600003611e7e5773ffffffffffffffffffffffffffffffffffffffff85163b611e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610531565b5081611cce565b611cce8383815115611e9a5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105319190611f3c565b60005b83811015611ee9578181015183820152602001611ed1565b50506000910152565b60008151808452611f0a816020860160208601611ece565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ae76020830184611ef2565b803567ffffffffffffffff81168114611f6757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b60405290565b60405160a0810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561202e5761202e611f6c565b604052919050565b600082601f83011261204757600080fd5b813567ffffffffffffffff81111561206157612061611f6c565b61209260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fe7565b8181528460208386010111156120a757600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156120de576120de611f6c565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146114a157600080fd5b8035611f67816120e8565b600082601f83011261212657600080fd5b8135602061213b612136836120c4565b611fe7565b82815260069290921b8401810191818101908684111561215a57600080fd5b8286015b848110156121a257604081890312156121775760008081fd5b61217f611f9b565b813561218a816120e8565b8152818501358582015283529183019160400161215e565b509695505050505050565b600080604083850312156121c057600080fd5b6121c983611f4f565b9150602083013567ffffffffffffffff808211156121e657600080fd5b9084019060a082870312156121fa57600080fd5b612202611fc4565b82358281111561221157600080fd5b61221d88828601612036565b82525060208301358281111561223257600080fd5b61223e88828601612036565b60208301525060408301358281111561225657600080fd5b61226288828601612115565b6040830152506122746060840161210a565b606082015260808301358281111561228b57600080fd5b61229788828601612036565b6080830152508093505050509250929050565b600080600080608085870312156122c057600080fd5b843567ffffffffffffffff8111156122d757600080fd5b850160a081880312156122e957600080fd5b9350602085013561ffff8116811461230057600080fd5b9250604085013591506060850135612317816120e8565b939692955090935050565b831515815260606020820152600061233d6060830185611ef2565b9050826040830152949350505050565b60006020828403121561235f57600080fd5b8135610ae7816120e8565b60008060006060848603121561237f57600080fd5b833561238a816120e8565b9250602084013561239a816120e8565b929592945050506040919091013590565b600080604083850312156123be57600080fd5b6123c783611f4f565b915060208301356123d7816120e8565b809150509250929050565b602080825282518282018190526000919060409081850190868401855b82811015612444578151805167ffffffffffffffff16855286015173ffffffffffffffffffffffffffffffffffffffff168685015292840192908501906001016123ff565b5091979650505050505050565b60006020828403121561246357600080fd5b610ae782611f4f565b60008083601f84011261247e57600080fd5b50813567ffffffffffffffff81111561249657600080fd5b6020830191508360208260061b85010111156124b157600080fd5b9250929050565b600080600080600080606087890312156124d157600080fd5b863567ffffffffffffffff808211156124e957600080fd5b6124f58a838b0161246c565b9098509650602089013591508082111561250e57600080fd5b61251a8a838b0161246c565b9096509450604089013591508082111561253357600080fd5b5061254089828a0161246c565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b818110156125a057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161256e565b50909695505050505050565b6000815160a084526125c160a0850182611ef2565b9050602080840151858303828701526125da8382611ef2565b60408681015188830389830152805180845290850195509092506000918401905b8083101561263a578551805173ffffffffffffffffffffffffffffffffffffffff168352850151858301529484019460019290920191908301906125fb565b5060608701519450612664606089018673ffffffffffffffffffffffffffffffffffffffff169052565b60808701519450878103608089015261267d8186611ef2565b98975050505050505050565b67ffffffffffffffff83168152604060208201526000611cce60408301846125ac565b6000602082840312156126be57600080fd5b5051919050565b6000602082840312156126d757600080fd5b81518015158114610ae757600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261271c57600080fd5b830160208101925035905067ffffffffffffffff81111561273c57600080fd5b8036038213156124b157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156127e95781356127b7816120e8565b73ffffffffffffffffffffffffffffffffffffffff1687528183013583880152604096870196909101906001016127a4565b509495945050505050565b6020815281356020820152600061280d60208401611f4f565b67ffffffffffffffff808216604085015261282b60408601866126e7565b925060a0606086015261284260c08601848361274b565b92505061285260608601866126e7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08087860301608088015261288885838561274b565b9450608088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030183126128c157600080fd5b602092880192830192359150838211156128da57600080fd5b8160061b36038313156128ec57600080fd5b8685030160a0870152611de4848284612794565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561294157600080fd5b8151610ae7816120e8565b67ffffffffffffffff8516815260806020820152600061296f60808301866125ac565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b6000604082840312156129ae57600080fd5b6129b6611f9b565b6129bf83611f4f565b815260208301356129cf816120e8565b60208201529392505050565b600060208083850312156129ee57600080fd5b825167ffffffffffffffff811115612a0557600080fd5b8301601f81018513612a1657600080fd5b8051612a24612136826120c4565b81815260059190911b82018301908381019087831115612a4357600080fd5b928401925b82841015611de4578351612a5b816120e8565b82529284019290840190612a48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156105d3576105d3612a6a565b818103818111156105d3576105d3612a6a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b00818460208701611ece565b919091019291505056fea164736f6c6343000818000a", } var RouterABI = RouterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go b/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go index d6e2db6bf37..274f72bae38 100644 --- a/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go +++ b/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go @@ -44,8 +44,8 @@ type ClientEVMTokenAmount struct { } var SelfFundedPingPongMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"roundTripsBeforeFunding\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"countIncrBeforeFunding\",\"type\":\"uint8\"}],\"name\":\"CountIncrBeforeFundingSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Funded\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"fundPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCountIncrBeforeFunding\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"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\":\"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\":\"uint8\",\"name\":\"countIncrBeforeFunding\",\"type\":\"uint8\"}],\"name\":\"setCountIncrBeforeFunding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"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\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200182238038062001822833981016040819052620000349162000291565b828233806000846001600160a01b0381166200006b576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c95760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000062565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fc57620000fc81620001cd565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000172573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001989190620002ea565b505050806002620001aa919062000315565b600360146101000a81548160ff021916908360ff16021790555050505062000347565b336001600160a01b03821603620002275760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000062565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200028e57600080fd5b50565b600080600060608486031215620002a757600080fd5b8351620002b48162000278565b6020850151909350620002c78162000278565b604085015190925060ff81168114620002df57600080fd5b809150509250925092565b600060208284031215620002fd57600080fd5b815180151581146200030e57600080fd5b9392505050565b60ff81811683821602908116908181146200034057634e487b7160e01b600052601160045260246000fd5b5092915050565b6080516114aa62000378600039600081816102970152818161063f0152818161072c0152610c2201526114aa6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80638f491cba116100cd578063bee518a411610081578063e6c725f511610066578063e6c725f51461034d578063ef686d8e1461037d578063f2fde38b1461039057600080fd5b8063bee518a4146102f1578063ca709a251461032f57600080fd5b8063b0f479a1116100b2578063b0f479a114610295578063b187bd26146102bb578063b5a11011146102de57600080fd5b80638f491cba1461026f5780639d2aede51461028257600080fd5b80632874d8bf1161012457806379ba50971161010957806379ba50971461023657806385572ffb1461023e5780638da5cb5b1461025157600080fd5b80632874d8bf146101ef5780632b6e5d63146101f757600080fd5b806301ffc9a71461015657806316c38b3c1461017e578063181f5a77146101935780631892b906146101dc575b600080fd5b610169610164366004610e24565b6103a3565b60405190151581526020015b60405180910390f35b61019161018c366004610e6d565b61043c565b005b6101cf6040518060400160405280601881526020017f53656c6646756e64656450696e67506f6e6720312e322e30000000000000000081525081565b6040516101759190610ef3565b6101916101ea366004610f23565b61048e565b6101916104e9565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610175565b610191610525565b61019161024c366004610f3e565b610627565b60005473ffffffffffffffffffffffffffffffffffffffff16610211565b61019161027d366004610f79565b6106ac565b610191610290366004610fb4565b61088b565b7f0000000000000000000000000000000000000000000000000000000000000000610211565b60025474010000000000000000000000000000000000000000900460ff16610169565b6101916102ec366004610fd1565b6108da565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff9091168152602001610175565b60035473ffffffffffffffffffffffffffffffffffffffff16610211565b60035474010000000000000000000000000000000000000000900460ff1660405160ff9091168152602001610175565b61019161038b366004611008565b61097c565b61019161039e366004610fb4565b610a04565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061043657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b610444610a15565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b610496610a15565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104f1610a15565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556105236001610a96565b565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610698576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024016105a2565b6106a96106a482611230565b610cd9565b50565b60035474010000000000000000000000000000000000000000900460ff1615806106f2575060035474010000000000000000000000000000000000000000900460ff1681105b156106fa5750565b6003546001906107259074010000000000000000000000000000000000000000900460ff16836112dd565b116106a9577f00000000000000000000000000000000000000000000000000000000000000006001546040517fa8d87a3b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910467ffffffffffffffff16600482015273ffffffffffffffffffffffffffffffffffffffff919091169063a8d87a3b90602401602060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108009190611318565b73ffffffffffffffffffffffffffffffffffffffff1663eff7cc486040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561084757600080fd5b505af115801561085b573d6000803e3d6000fd5b50506040517f302777af5d26fab9dd5120c5f1307c65193ebc51daf33244ada4365fab10602c925060009150a150565b610893610a15565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6108e2610a15565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b610984610a15565b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f4768dbf8645b24c54f2887651545d24f748c0d0d1d4c689eb810fb19f0befcf39060200160405180910390a150565b610a0c610a15565b6106a981610d2f565b60005473ffffffffffffffffffffffffffffffffffffffff163314610523576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105a2565b80600116600103610ad9576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a1610b0d565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b610b16816106ac565b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e08101604051602081830303815290604052815260200183604051602001610b6e91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905281526020016000604051908082528060200260200182016040528015610be857816020015b6040805180820190915260008082526020820152815260200190600190039081610bc15790505b50815260035473ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080519182018152600082529091015290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9600160149054906101000a900467ffffffffffffffff16836040518363ffffffff1660e01b8152600401610c91929190611335565b6020604051808303816000875af1158015610cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd4919061144a565b505050565b60008160600151806020019051810190610cf3919061144a565b60025490915074010000000000000000000000000000000000000000900460ff16610d2b57610d2b610d26826001611463565b610a96565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610dae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105a2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610e3657600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e6657600080fd5b9392505050565b600060208284031215610e7f57600080fd5b81358015158114610e6657600080fd5b6000815180845260005b81811015610eb557602081850181015186830182015201610e99565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610e666020830184610e8f565b803567ffffffffffffffff81168114610f1e57600080fd5b919050565b600060208284031215610f3557600080fd5b610e6682610f06565b600060208284031215610f5057600080fd5b813567ffffffffffffffff811115610f6757600080fd5b820160a08185031215610e6657600080fd5b600060208284031215610f8b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a957600080fd5b600060208284031215610fc657600080fd5b8135610e6681610f92565b60008060408385031215610fe457600080fd5b610fed83610f06565b91506020830135610ffd81610f92565b809150509250929050565b60006020828403121561101a57600080fd5b813560ff81168114610e6657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561107d5761107d61102b565b60405290565b60405160a0810167ffffffffffffffff8111828210171561107d5761107d61102b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110ed576110ed61102b565b604052919050565b600082601f83011261110657600080fd5b813567ffffffffffffffff8111156111205761112061102b565b61115160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016110a6565b81815284602083860101111561116657600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261119457600080fd5b8135602067ffffffffffffffff8211156111b0576111b061102b565b6111be818360051b016110a6565b82815260069290921b840181019181810190868411156111dd57600080fd5b8286015b8481101561122557604081890312156111fa5760008081fd5b61120261105a565b813561120d81610f92565b815281850135858201528352918301916040016111e1565b509695505050505050565b600060a0823603121561124257600080fd5b61124a611083565b8235815261125a60208401610f06565b6020820152604083013567ffffffffffffffff8082111561127a57600080fd5b611286368387016110f5565b6040840152606085013591508082111561129f57600080fd5b6112ab368387016110f5565b606084015260808501359150808211156112c457600080fd5b506112d136828601611183565b60808301525092915050565b600082611313577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60006020828403121561132a57600080fd5b8151610e6681610f92565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261136460e0860182610e8f565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087840301606088015261139f8383610e8f565b6040890151888203830160808a01528051808352908601945060009350908501905b80841015611400578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906113c1565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a0152955061143c8187610e8f565b9a9950505050505050505050565b60006020828403121561145c57600080fd5b5051919050565b80820180821115610436577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"roundTripsBeforeFunding\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"countIncrBeforeFunding\",\"type\":\"uint8\"}],\"name\":\"CountIncrBeforeFundingSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Funded\",\"type\":\"event\"},{\"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\":[{\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"fundPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCountIncrBeforeFunding\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"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\":\"uint8\",\"name\":\"countIncrBeforeFunding\",\"type\":\"uint8\"}],\"name\":\"setCountIncrBeforeFunding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200190938038062001909833981016040819052620000349162000291565b828233806000846001600160a01b0381166200006b576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c95760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000062565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fc57620000fc81620001cd565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000172573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001989190620002ea565b505050806002620001aa919062000315565b600360156101000a81548160ff021916908360ff16021790555050505062000347565b336001600160a01b03821603620002275760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000062565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200028e57600080fd5b50565b600080600060608486031215620002a757600080fd5b8351620002b48162000278565b6020850151909350620002c78162000278565b604085015190925060ff81168114620002df57600080fd5b809150509250925092565b600060208284031215620002fd57600080fd5b815180151581146200030e57600080fd5b9392505050565b60ff81811683821602908116908181146200034057634e487b7160e01b600052601160045260246000fd5b5092915050565b60805161159162000378600039600081816102f301528181610728015281816108180152610d0901526115916000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c80638f491cba116100d8578063b5a110111161008c578063e6c725f511610066578063e6c725f5146103a9578063ef686d8e146103da578063f2fde38b146103ed57600080fd5b8063b5a110111461033a578063bee518a41461034d578063ca709a251461038b57600080fd5b8063ae90de55116100bd578063ae90de55146102ce578063b0f479a1146102f1578063b187bd261461031757600080fd5b80638f491cba146102a85780639d2aede5146102bb57600080fd5b80632b6e5d631161012f57806379ba50971161011457806379ba50971461026f57806385572ffb146102775780638da5cb5b1461028a57600080fd5b80632b6e5d631461021d578063665ed5371461025c57600080fd5b8063181f5a7711610160578063181f5a77146101b95780631892b906146102025780632874d8bf1461021557600080fd5b806301ffc9a71461017c57806316c38b3c146101a4575b600080fd5b61018f61018a366004610f0b565b610400565b60405190151581526020015b60405180910390f35b6101b76101b2366004610f54565b610499565b005b6101f56040518060400160405280601881526020017f53656c6646756e64656450696e67506f6e6720312e352e30000000000000000081525081565b60405161019b9190610fda565b6101b761021036600461100a565b6104eb565b6101b7610546565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101b761026a366004610f54565b610582565b6101b761060e565b6101b7610285366004611025565b610710565b60005473ffffffffffffffffffffffffffffffffffffffff16610237565b6101b76102b6366004611060565b610795565b6101b76102c936600461109b565b610977565b60035474010000000000000000000000000000000000000000900460ff1661018f565b7f0000000000000000000000000000000000000000000000000000000000000000610237565b60025474010000000000000000000000000000000000000000900460ff1661018f565b6101b76103483660046110b8565b6109c6565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161019b565b60035473ffffffffffffffffffffffffffffffffffffffff16610237565b6003547501000000000000000000000000000000000000000000900460ff1660405160ff909116815260200161019b565b6101b76103e83660046110ef565b610a68565b6101b76103fb36600461109b565b610aeb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061049357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6104a1610afc565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104f3610afc565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61054e610afc565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556105806001610b7d565b565b61058a610afc565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061060390831515815260200190565b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff163314610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610781576040517fd7f7333400000000000000000000000000000000000000000000000000000000815233600482015260240161068b565b61079261078d82611317565b610dc0565b50565b6003547501000000000000000000000000000000000000000000900460ff1615806107dd57506003547501000000000000000000000000000000000000000000900460ff1681105b156107e55750565b600354600190610811907501000000000000000000000000000000000000000000900460ff16836113c4565b11610792577f00000000000000000000000000000000000000000000000000000000000000006001546040517fa8d87a3b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910467ffffffffffffffff16600482015273ffffffffffffffffffffffffffffffffffffffff919091169063a8d87a3b90602401602060405180830381865afa1580156108c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ec91906113ff565b73ffffffffffffffffffffffffffffffffffffffff1663eff7cc486040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561093357600080fd5b505af1158015610947573d6000803e3d6000fd5b50506040517f302777af5d26fab9dd5120c5f1307c65193ebc51daf33244ada4365fab10602c925060009150a150565b61097f610afc565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6109ce610afc565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b610a70610afc565b600380547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f4768dbf8645b24c54f2887651545d24f748c0d0d1d4c689eb810fb19f0befcf390602001610603565b610af3610afc565b61079281610e16565b60005473ffffffffffffffffffffffffffffffffffffffff163314610580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161068b565b80600116600103610bc0576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a1610bf4565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b610bfd81610795565b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e08101604051602081830303815290604052815260200183604051602001610c5591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905281526020016000604051908082528060200260200182016040528015610ccf57816020015b6040805180820190915260008082526020820152815260200190600190039081610ca85790505b50815260035473ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080519182018152600082529091015290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9600160149054906101000a900467ffffffffffffffff16836040518363ffffffff1660e01b8152600401610d7892919061141c565b6020604051808303816000875af1158015610d97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbb9190611531565b505050565b60008160600151806020019051810190610dda9190611531565b60025490915074010000000000000000000000000000000000000000900460ff16610e1257610e12610e0d82600161154a565b610b7d565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161068b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610f1d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f4d57600080fd5b9392505050565b600060208284031215610f6657600080fd5b81358015158114610f4d57600080fd5b6000815180845260005b81811015610f9c57602081850181015186830182015201610f80565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f4d6020830184610f76565b803567ffffffffffffffff8116811461100557600080fd5b919050565b60006020828403121561101c57600080fd5b610f4d82610fed565b60006020828403121561103757600080fd5b813567ffffffffffffffff81111561104e57600080fd5b820160a08185031215610f4d57600080fd5b60006020828403121561107257600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461079257600080fd5b6000602082840312156110ad57600080fd5b8135610f4d81611079565b600080604083850312156110cb57600080fd5b6110d483610fed565b915060208301356110e481611079565b809150509250929050565b60006020828403121561110157600080fd5b813560ff81168114610f4d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561116457611164611112565b60405290565b60405160a0810167ffffffffffffffff8111828210171561116457611164611112565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156111d4576111d4611112565b604052919050565b600082601f8301126111ed57600080fd5b813567ffffffffffffffff81111561120757611207611112565b61123860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161118d565b81815284602083860101111561124d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261127b57600080fd5b8135602067ffffffffffffffff82111561129757611297611112565b6112a5818360051b0161118d565b82815260069290921b840181019181810190868411156112c457600080fd5b8286015b8481101561130c57604081890312156112e15760008081fd5b6112e9611141565b81356112f481611079565b815281850135858201528352918301916040016112c8565b509695505050505050565b600060a0823603121561132957600080fd5b61133161116a565b8235815261134160208401610fed565b6020820152604083013567ffffffffffffffff8082111561136157600080fd5b61136d368387016111dc565b6040840152606085013591508082111561138657600080fd5b611392368387016111dc565b606084015260808501359150808211156113ab57600080fd5b506113b83682860161126a565b60808301525092915050565b6000826113fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60006020828403121561141157600080fd5b8151610f4d81611079565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261144b60e0860182610f76565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808784030160608801526114868383610f76565b6040890151888203830160808a01528051808352908601945060009350908501905b808410156114e7578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906114a8565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506115238187610f76565b9a9950505050505050505050565b60006020828403121561154357600080fd5b5051919050565b80820180821115610493577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", } var SelfFundedPingPongABI = SelfFundedPingPongMetaData.ABI @@ -272,6 +272,28 @@ func (_SelfFundedPingPong *SelfFundedPingPongCallerSession) GetFeeToken() (commo return _SelfFundedPingPong.Contract.GetFeeToken(&_SelfFundedPingPong.CallOpts) } +func (_SelfFundedPingPong *SelfFundedPingPongCaller) GetOutOfOrderExecution(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _SelfFundedPingPong.contract.Call(opts, &out, "getOutOfOrderExecution") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_SelfFundedPingPong *SelfFundedPingPongSession) GetOutOfOrderExecution() (bool, error) { + return _SelfFundedPingPong.Contract.GetOutOfOrderExecution(&_SelfFundedPingPong.CallOpts) +} + +func (_SelfFundedPingPong *SelfFundedPingPongCallerSession) GetOutOfOrderExecution() (bool, error) { + return _SelfFundedPingPong.Contract.GetOutOfOrderExecution(&_SelfFundedPingPong.CallOpts) +} + func (_SelfFundedPingPong *SelfFundedPingPongCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _SelfFundedPingPong.contract.Call(opts, &out, "getRouter") @@ -466,6 +488,18 @@ func (_SelfFundedPingPong *SelfFundedPingPongTransactorSession) SetCounterpartCh return _SelfFundedPingPong.Contract.SetCounterpartChainSelector(&_SelfFundedPingPong.TransactOpts, chainSelector) } +func (_SelfFundedPingPong *SelfFundedPingPongTransactor) SetOutOfOrderExecution(opts *bind.TransactOpts, outOfOrderExecution bool) (*types.Transaction, error) { + return _SelfFundedPingPong.contract.Transact(opts, "setOutOfOrderExecution", outOfOrderExecution) +} + +func (_SelfFundedPingPong *SelfFundedPingPongSession) SetOutOfOrderExecution(outOfOrderExecution bool) (*types.Transaction, error) { + return _SelfFundedPingPong.Contract.SetOutOfOrderExecution(&_SelfFundedPingPong.TransactOpts, outOfOrderExecution) +} + +func (_SelfFundedPingPong *SelfFundedPingPongTransactorSession) SetOutOfOrderExecution(outOfOrderExecution bool) (*types.Transaction, error) { + return _SelfFundedPingPong.Contract.SetOutOfOrderExecution(&_SelfFundedPingPong.TransactOpts, outOfOrderExecution) +} + func (_SelfFundedPingPong *SelfFundedPingPongTransactor) SetPaused(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) { return _SelfFundedPingPong.contract.Transact(opts, "setPaused", pause) } @@ -735,6 +769,123 @@ func (_SelfFundedPingPong *SelfFundedPingPongFilterer) ParseFunded(log types.Log return event, nil } +type SelfFundedPingPongOutOfOrderExecutionChangeIterator struct { + Event *SelfFundedPingPongOutOfOrderExecutionChange + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *SelfFundedPingPongOutOfOrderExecutionChangeIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(SelfFundedPingPongOutOfOrderExecutionChange) + 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(SelfFundedPingPongOutOfOrderExecutionChange) + 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 *SelfFundedPingPongOutOfOrderExecutionChangeIterator) Error() error { + return it.fail +} + +func (it *SelfFundedPingPongOutOfOrderExecutionChangeIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type SelfFundedPingPongOutOfOrderExecutionChange struct { + IsOutOfOrder bool + Raw types.Log +} + +func (_SelfFundedPingPong *SelfFundedPingPongFilterer) FilterOutOfOrderExecutionChange(opts *bind.FilterOpts) (*SelfFundedPingPongOutOfOrderExecutionChangeIterator, error) { + + logs, sub, err := _SelfFundedPingPong.contract.FilterLogs(opts, "OutOfOrderExecutionChange") + if err != nil { + return nil, err + } + return &SelfFundedPingPongOutOfOrderExecutionChangeIterator{contract: _SelfFundedPingPong.contract, event: "OutOfOrderExecutionChange", logs: logs, sub: sub}, nil +} + +func (_SelfFundedPingPong *SelfFundedPingPongFilterer) WatchOutOfOrderExecutionChange(opts *bind.WatchOpts, sink chan<- *SelfFundedPingPongOutOfOrderExecutionChange) (event.Subscription, error) { + + logs, sub, err := _SelfFundedPingPong.contract.WatchLogs(opts, "OutOfOrderExecutionChange") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(SelfFundedPingPongOutOfOrderExecutionChange) + if err := _SelfFundedPingPong.contract.UnpackLog(event, "OutOfOrderExecutionChange", 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 (_SelfFundedPingPong *SelfFundedPingPongFilterer) ParseOutOfOrderExecutionChange(log types.Log) (*SelfFundedPingPongOutOfOrderExecutionChange, error) { + event := new(SelfFundedPingPongOutOfOrderExecutionChange) + if err := _SelfFundedPingPong.contract.UnpackLog(event, "OutOfOrderExecutionChange", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type SelfFundedPingPongOwnershipTransferRequestedIterator struct { Event *SelfFundedPingPongOwnershipTransferRequested @@ -1247,6 +1398,8 @@ func (_SelfFundedPingPong *SelfFundedPingPong) ParseLog(log types.Log) (generate return _SelfFundedPingPong.ParseCountIncrBeforeFundingSet(log) case _SelfFundedPingPong.abi.Events["Funded"].ID: return _SelfFundedPingPong.ParseFunded(log) + case _SelfFundedPingPong.abi.Events["OutOfOrderExecutionChange"].ID: + return _SelfFundedPingPong.ParseOutOfOrderExecutionChange(log) case _SelfFundedPingPong.abi.Events["OwnershipTransferRequested"].ID: return _SelfFundedPingPong.ParseOwnershipTransferRequested(log) case _SelfFundedPingPong.abi.Events["OwnershipTransferred"].ID: @@ -1269,6 +1422,10 @@ func (SelfFundedPingPongFunded) Topic() common.Hash { return common.HexToHash("0x302777af5d26fab9dd5120c5f1307c65193ebc51daf33244ada4365fab10602c") } +func (SelfFundedPingPongOutOfOrderExecutionChange) Topic() common.Hash { + return common.HexToHash("0x05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd9") +} + func (SelfFundedPingPongOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1298,6 +1455,8 @@ type SelfFundedPingPongInterface interface { GetFeeToken(opts *bind.CallOpts) (common.Address, error) + GetOutOfOrderExecution(opts *bind.CallOpts) (bool, error) + GetRouter(opts *bind.CallOpts) (common.Address, error) IsPaused(opts *bind.CallOpts) (bool, error) @@ -1322,6 +1481,8 @@ type SelfFundedPingPongInterface interface { SetCounterpartChainSelector(opts *bind.TransactOpts, chainSelector uint64) (*types.Transaction, error) + SetOutOfOrderExecution(opts *bind.TransactOpts, outOfOrderExecution bool) (*types.Transaction, error) + SetPaused(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) StartPingPong(opts *bind.TransactOpts) (*types.Transaction, error) @@ -1340,6 +1501,12 @@ type SelfFundedPingPongInterface interface { ParseFunded(log types.Log) (*SelfFundedPingPongFunded, error) + FilterOutOfOrderExecutionChange(opts *bind.FilterOpts) (*SelfFundedPingPongOutOfOrderExecutionChangeIterator, error) + + WatchOutOfOrderExecutionChange(opts *bind.WatchOpts, sink chan<- *SelfFundedPingPongOutOfOrderExecutionChange) (event.Subscription, error) + + ParseOutOfOrderExecutionChange(log types.Log) (*SelfFundedPingPongOutOfOrderExecutionChange, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*SelfFundedPingPongOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *SelfFundedPingPongOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) 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 189b4b600b4..7e81051aa34 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\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidTokenPoolToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"OnlyAdministrator\",\"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\":\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"disabled\",\"type\":\"bool\"}],\"name\":\"DisableReRegistrationSet\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"RemovedAdministrator\",\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611449806101576000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637d3f255211610097578063cb67e3b111610066578063cb67e3b1146102bc578063ddadfa8e14610374578063e677ae3714610387578063f2fde38b1461039a57600080fd5b80637d3f2552146101e05780638da5cb5b14610203578063bbe4f6db14610242578063c1af6e031461027f57600080fd5b80634e847fc7116100d35780634e847fc7146101925780635e63547a146101a557806372d64a81146101c557806379ba5097146101d857600080fd5b806310cbcf1814610105578063156194da1461011a578063181f5a771461012d5780633dc457721461017f575b600080fd5b61011861011336600461116c565b6103ad565b005b61011861012836600461116c565b61040a565b6101696040518060400160405280601c81526020017f546f6b656e41646d696e526567697374727920312e352e302d6465760000000081525081565b6040516101769190611187565b60405180910390f35b61011861018d36600461116c565b61050f565b6101186101a03660046111f4565b610573565b6101b86101b3366004611227565b6107d3565b604051610176919061129c565b6101b86101d336600461130e565b6108cc565b6101186109e2565b6101f36101ee36600461116c565b610adf565b6040519015158152602001610176565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610176565b61021d61025036600461116c565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260026020819052604090912001541690565b6101f361028d3660046111f4565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020526040902054821691161490565b6103356102ca36600461116c565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff948516815260028084529084902084519283018552805486168352600181015486169383019390935291909101549092169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff90811682526020808501518216908301529282015190921690820152606001610176565b6101186103823660046111f4565b610aec565b6101186103953660046111f4565b610bf6565b6101186103a836600461116c565b610dbe565b6103b5610dcf565b6103c0600582610e52565b156104075760405173ffffffffffffffffffffffffffffffffffffffff8216907f93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f890600090a25b50565b73ffffffffffffffffffffffffffffffffffffffff808216600090815260026020526040902060018101549091163314610493576040517f3edffe7500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff831660248201526044015b60405180910390fd5b8054337fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117835560018301805490921690915560405173ffffffffffffffffffffffffffffffffffffffff8416907f399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a790600090a35050565b610517610dcf565b610522600582610e7b565b156104075760405173ffffffffffffffffffffffffffffffffffffffff821681527f3cabf004338366bfeaeb610ad827cb58d16b588017c509501f2c97c83caae7b29060200160405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526002602052604090205483911633146105f3576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8216158015906106a557506040517f240028e800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283169063240028e890602401602060405180830381865afa15801561067f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a39190611338565b155b156106f4576040517f962b60e600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020819052604090912090810180548584167fffffffffffffffffffffffff0000000000000000000000000000000000000000821681179092559192919091169081146107cc578373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f754449ec3aff3bd528bfce43ae9319c4a381b67fcd1d20097b3b24dacaecc35d60405160405180910390a45b5050505050565b606060008267ffffffffffffffff8111156107f0576107f061135a565b604051908082528060200260200182016040528015610819578160200160208202803683370190505b50905060005b838110156108c2576002600086868481811061083d5761083d611389565b9050602002016020810190610852919061116c565b73ffffffffffffffffffffffffffffffffffffffff9081168252602082019290925260400160002060020154835191169083908390811061089557610895611389565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161081f565b5090505b92915050565b606060006108da6003610e9d565b9050808467ffffffffffffffff16106108f357506108c6565b67ffffffffffffffff80841690829061090e908716836113e7565b111561092b5761092867ffffffffffffffff8616836113fa565b90505b8067ffffffffffffffff8111156109445761094461135a565b60405190808252806020026020018201604052801561096d578160200160208202803683370190505b50925060005b818110156109d95761099a6109928267ffffffffffffffff89166113e7565b600390610ea7565b8482815181106109ac576109ac611389565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101610973565b50505092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161048a565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108c6600583610eb3565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020548391163314610b6c576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152600260205260408082206001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001695881695861790559051909392339290917fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b7169190a450505050565b610bff33610adf565b158015610c24575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15610c5d576040517f51ca1ec300000000000000000000000000000000000000000000000000000000815233600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff8116610caa576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020805490911615610d24576040517f45ed80e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b6001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610d71600384610e7b565b5060405173ffffffffffffffffffffffffffffffffffffffff808416916000918616907fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b716908390a4505050565b610dc6610dcf565b61040781610ee2565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161048a565b565b6000610e748373ffffffffffffffffffffffffffffffffffffffff8416610fd7565b9392505050565b6000610e748373ffffffffffffffffffffffffffffffffffffffff84166110ca565b60006108c6825490565b6000610e748383611119565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610e74565b3373ffffffffffffffffffffffffffffffffffffffff821603610f61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161048a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205480156110c0576000610ffb6001836113fa565b855490915060009061100f906001906113fa565b905081811461107457600086600001828154811061102f5761102f611389565b906000526020600020015490508087600001848154811061105257611052611389565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806110855761108561140d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c6565b60009150506108c6565b6000818152600183016020526040812054611111575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c6565b5060006108c6565b600082600001828154811061113057611130611389565b9060005260206000200154905092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461116757600080fd5b919050565b60006020828403121561117e57600080fd5b610e7482611143565b60006020808352835180602085015260005b818110156111b557858101830151858201604001528201611199565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561120757600080fd5b61121083611143565b915061121e60208401611143565b90509250929050565b6000806020838503121561123a57600080fd5b823567ffffffffffffffff8082111561125257600080fd5b818501915085601f83011261126657600080fd5b81358181111561127557600080fd5b8660208260051b850101111561128a57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b818110156112ea57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016112b8565b50909695505050505050565b803567ffffffffffffffff8116811461116757600080fd5b6000806040838503121561132157600080fd5b61132a836112f6565b915061121e602084016112f6565b60006020828403121561134a57600080fd5b81518015158114610e7457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108c6576108c66113b8565b818103818111156108c6576108c66113b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidTokenPoolToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"OnlyAdministrator\",\"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\":\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611449806101576000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637d3f255211610097578063cb67e3b111610066578063cb67e3b1146102bc578063ddadfa8e14610374578063e677ae3714610387578063f2fde38b1461039a57600080fd5b80637d3f2552146101e05780638da5cb5b14610203578063bbe4f6db14610242578063c1af6e031461027f57600080fd5b80634e847fc7116100d35780634e847fc7146101925780635e63547a146101a557806372d64a81146101c557806379ba5097146101d857600080fd5b806310cbcf1814610105578063156194da1461011a578063181f5a771461012d5780633dc457721461017f575b600080fd5b61011861011336600461116c565b6103ad565b005b61011861012836600461116c565b61040a565b6101696040518060400160405280601881526020017f546f6b656e41646d696e526567697374727920312e352e30000000000000000081525081565b6040516101769190611187565b60405180910390f35b61011861018d36600461116c565b61050f565b6101186101a03660046111f4565b610573565b6101b86101b3366004611227565b6107d3565b604051610176919061129c565b6101b86101d336600461130e565b6108cc565b6101186109e2565b6101f36101ee36600461116c565b610adf565b6040519015158152602001610176565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610176565b61021d61025036600461116c565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260026020819052604090912001541690565b6101f361028d3660046111f4565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020526040902054821691161490565b6103356102ca36600461116c565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff948516815260028084529084902084519283018552805486168352600181015486169383019390935291909101549092169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff90811682526020808501518216908301529282015190921690820152606001610176565b6101186103823660046111f4565b610aec565b6101186103953660046111f4565b610bf6565b6101186103a836600461116c565b610dbe565b6103b5610dcf565b6103c0600582610e52565b156104075760405173ffffffffffffffffffffffffffffffffffffffff8216907f93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f890600090a25b50565b73ffffffffffffffffffffffffffffffffffffffff808216600090815260026020526040902060018101549091163314610493576040517f3edffe7500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff831660248201526044015b60405180910390fd5b8054337fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117835560018301805490921690915560405173ffffffffffffffffffffffffffffffffffffffff8416907f399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a790600090a35050565b610517610dcf565b610522600582610e7b565b156104075760405173ffffffffffffffffffffffffffffffffffffffff821681527f3cabf004338366bfeaeb610ad827cb58d16b588017c509501f2c97c83caae7b29060200160405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526002602052604090205483911633146105f3576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8216158015906106a557506040517f240028e800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283169063240028e890602401602060405180830381865afa15801561067f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a39190611338565b155b156106f4576040517f962b60e600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020819052604090912090810180548584167fffffffffffffffffffffffff0000000000000000000000000000000000000000821681179092559192919091169081146107cc578373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f754449ec3aff3bd528bfce43ae9319c4a381b67fcd1d20097b3b24dacaecc35d60405160405180910390a45b5050505050565b606060008267ffffffffffffffff8111156107f0576107f061135a565b604051908082528060200260200182016040528015610819578160200160208202803683370190505b50905060005b838110156108c2576002600086868481811061083d5761083d611389565b9050602002016020810190610852919061116c565b73ffffffffffffffffffffffffffffffffffffffff9081168252602082019290925260400160002060020154835191169083908390811061089557610895611389565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161081f565b5090505b92915050565b606060006108da6003610e9d565b9050808467ffffffffffffffff16106108f357506108c6565b67ffffffffffffffff80841690829061090e908716836113e7565b111561092b5761092867ffffffffffffffff8616836113fa565b90505b8067ffffffffffffffff8111156109445761094461135a565b60405190808252806020026020018201604052801561096d578160200160208202803683370190505b50925060005b818110156109d95761099a6109928267ffffffffffffffff89166113e7565b600390610ea7565b8482815181106109ac576109ac611389565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101610973565b50505092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161048a565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108c6600583610eb3565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020548391163314610b6c576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152600260205260408082206001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001695881695861790559051909392339290917fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b7169190a450505050565b610bff33610adf565b158015610c24575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15610c5d576040517f51ca1ec300000000000000000000000000000000000000000000000000000000815233600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff8116610caa576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020805490911615610d24576040517f45ed80e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b6001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610d71600384610e7b565b5060405173ffffffffffffffffffffffffffffffffffffffff808416916000918616907fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b716908390a4505050565b610dc6610dcf565b61040781610ee2565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161048a565b565b6000610e748373ffffffffffffffffffffffffffffffffffffffff8416610fd7565b9392505050565b6000610e748373ffffffffffffffffffffffffffffffffffffffff84166110ca565b60006108c6825490565b6000610e748383611119565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610e74565b3373ffffffffffffffffffffffffffffffffffffffff821603610f61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161048a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205480156110c0576000610ffb6001836113fa565b855490915060009061100f906001906113fa565b905080821461107457600086600001828154811061102f5761102f611389565b906000526020600020015490508087600001848154811061105257611052611389565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806110855761108561140d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c6565b60009150506108c6565b6000818152600183016020526040812054611111575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c6565b5060006108c6565b600082600001828154811061113057611130611389565b9060005260206000200154905092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461116757600080fd5b919050565b60006020828403121561117e57600080fd5b610e7482611143565b60006020808352835180602085015260005b818110156111b557858101830151858201604001528201611199565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561120757600080fd5b61121083611143565b915061121e60208401611143565b90509250929050565b6000806020838503121561123a57600080fd5b823567ffffffffffffffff8082111561125257600080fd5b818501915085601f83011261126657600080fd5b81358181111561127557600080fd5b8660208260051b850101111561128a57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b818110156112ea57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016112b8565b50909695505050505050565b803567ffffffffffffffff8116811461116757600080fd5b6000806040838503121561132157600080fd5b61132a836112f6565b915061121e602084016112f6565b60006020828403121561134a57600080fd5b81518015158114610e7457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108c6576108c66113b8565b818103818111156108c6576108c66113b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var TokenAdminRegistryABI = TokenAdminRegistryMetaData.ABI @@ -730,134 +730,6 @@ func (_TokenAdminRegistry *TokenAdminRegistryFilterer) ParseAdministratorTransfe return event, nil } -type TokenAdminRegistryDisableReRegistrationSetIterator struct { - Event *TokenAdminRegistryDisableReRegistrationSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *TokenAdminRegistryDisableReRegistrationSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(TokenAdminRegistryDisableReRegistrationSet) - 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(TokenAdminRegistryDisableReRegistrationSet) - 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 *TokenAdminRegistryDisableReRegistrationSetIterator) Error() error { - return it.fail -} - -func (it *TokenAdminRegistryDisableReRegistrationSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type TokenAdminRegistryDisableReRegistrationSet struct { - Token common.Address - Disabled bool - Raw types.Log -} - -func (_TokenAdminRegistry *TokenAdminRegistryFilterer) FilterDisableReRegistrationSet(opts *bind.FilterOpts, token []common.Address) (*TokenAdminRegistryDisableReRegistrationSetIterator, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _TokenAdminRegistry.contract.FilterLogs(opts, "DisableReRegistrationSet", tokenRule) - if err != nil { - return nil, err - } - return &TokenAdminRegistryDisableReRegistrationSetIterator{contract: _TokenAdminRegistry.contract, event: "DisableReRegistrationSet", logs: logs, sub: sub}, nil -} - -func (_TokenAdminRegistry *TokenAdminRegistryFilterer) WatchDisableReRegistrationSet(opts *bind.WatchOpts, sink chan<- *TokenAdminRegistryDisableReRegistrationSet, token []common.Address) (event.Subscription, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _TokenAdminRegistry.contract.WatchLogs(opts, "DisableReRegistrationSet", tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(TokenAdminRegistryDisableReRegistrationSet) - if err := _TokenAdminRegistry.contract.UnpackLog(event, "DisableReRegistrationSet", 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 (_TokenAdminRegistry *TokenAdminRegistryFilterer) ParseDisableReRegistrationSet(log types.Log) (*TokenAdminRegistryDisableReRegistrationSet, error) { - event := new(TokenAdminRegistryDisableReRegistrationSet) - if err := _TokenAdminRegistry.contract.UnpackLog(event, "DisableReRegistrationSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - type TokenAdminRegistryOwnershipTransferRequestedIterator struct { Event *TokenAdminRegistryOwnershipTransferRequested @@ -1519,131 +1391,12 @@ func (_TokenAdminRegistry *TokenAdminRegistryFilterer) ParseRegistryModuleRemove return event, nil } -type TokenAdminRegistryRemovedAdministratorIterator struct { - Event *TokenAdminRegistryRemovedAdministrator - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *TokenAdminRegistryRemovedAdministratorIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(TokenAdminRegistryRemovedAdministrator) - 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(TokenAdminRegistryRemovedAdministrator) - 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 *TokenAdminRegistryRemovedAdministratorIterator) Error() error { - return it.fail -} - -func (it *TokenAdminRegistryRemovedAdministratorIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type TokenAdminRegistryRemovedAdministrator struct { - Token common.Address - Raw types.Log -} - -func (_TokenAdminRegistry *TokenAdminRegistryFilterer) FilterRemovedAdministrator(opts *bind.FilterOpts) (*TokenAdminRegistryRemovedAdministratorIterator, error) { - - logs, sub, err := _TokenAdminRegistry.contract.FilterLogs(opts, "RemovedAdministrator") - if err != nil { - return nil, err - } - return &TokenAdminRegistryRemovedAdministratorIterator{contract: _TokenAdminRegistry.contract, event: "RemovedAdministrator", logs: logs, sub: sub}, nil -} - -func (_TokenAdminRegistry *TokenAdminRegistryFilterer) WatchRemovedAdministrator(opts *bind.WatchOpts, sink chan<- *TokenAdminRegistryRemovedAdministrator) (event.Subscription, error) { - - logs, sub, err := _TokenAdminRegistry.contract.WatchLogs(opts, "RemovedAdministrator") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(TokenAdminRegistryRemovedAdministrator) - if err := _TokenAdminRegistry.contract.UnpackLog(event, "RemovedAdministrator", 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 (_TokenAdminRegistry *TokenAdminRegistryFilterer) ParseRemovedAdministrator(log types.Log) (*TokenAdminRegistryRemovedAdministrator, error) { - event := new(TokenAdminRegistryRemovedAdministrator) - if err := _TokenAdminRegistry.contract.UnpackLog(event, "RemovedAdministrator", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - func (_TokenAdminRegistry *TokenAdminRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { case _TokenAdminRegistry.abi.Events["AdministratorTransferRequested"].ID: return _TokenAdminRegistry.ParseAdministratorTransferRequested(log) case _TokenAdminRegistry.abi.Events["AdministratorTransferred"].ID: return _TokenAdminRegistry.ParseAdministratorTransferred(log) - case _TokenAdminRegistry.abi.Events["DisableReRegistrationSet"].ID: - return _TokenAdminRegistry.ParseDisableReRegistrationSet(log) case _TokenAdminRegistry.abi.Events["OwnershipTransferRequested"].ID: return _TokenAdminRegistry.ParseOwnershipTransferRequested(log) case _TokenAdminRegistry.abi.Events["OwnershipTransferred"].ID: @@ -1654,8 +1407,6 @@ func (_TokenAdminRegistry *TokenAdminRegistry) ParseLog(log types.Log) (generate return _TokenAdminRegistry.ParseRegistryModuleAdded(log) case _TokenAdminRegistry.abi.Events["RegistryModuleRemoved"].ID: return _TokenAdminRegistry.ParseRegistryModuleRemoved(log) - case _TokenAdminRegistry.abi.Events["RemovedAdministrator"].ID: - return _TokenAdminRegistry.ParseRemovedAdministrator(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) @@ -1670,10 +1421,6 @@ func (TokenAdminRegistryAdministratorTransferred) Topic() common.Hash { return common.HexToHash("0x399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a7") } -func (TokenAdminRegistryDisableReRegistrationSet) Topic() common.Hash { - return common.HexToHash("0x4f1ce406d38233729d1052ad9f0c2b56bd742cd4fb59781573b51fa1f268a92e") -} - func (TokenAdminRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1694,10 +1441,6 @@ func (TokenAdminRegistryRegistryModuleRemoved) Topic() common.Hash { return common.HexToHash("0x93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f8") } -func (TokenAdminRegistryRemovedAdministrator) Topic() common.Hash { - return common.HexToHash("0x7b309bf0232684e703b0a791653cc857835761a0365ccade0e2aa66ef02ca530") -} - func (_TokenAdminRegistry *TokenAdminRegistry) Address() common.Address { return _TokenAdminRegistry.address } @@ -1747,12 +1490,6 @@ type TokenAdminRegistryInterface interface { ParseAdministratorTransferred(log types.Log) (*TokenAdminRegistryAdministratorTransferred, error) - FilterDisableReRegistrationSet(opts *bind.FilterOpts, token []common.Address) (*TokenAdminRegistryDisableReRegistrationSetIterator, error) - - WatchDisableReRegistrationSet(opts *bind.WatchOpts, sink chan<- *TokenAdminRegistryDisableReRegistrationSet, token []common.Address) (event.Subscription, error) - - ParseDisableReRegistrationSet(log types.Log) (*TokenAdminRegistryDisableReRegistrationSet, error) - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*TokenAdminRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *TokenAdminRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) @@ -1783,12 +1520,6 @@ type TokenAdminRegistryInterface interface { ParseRegistryModuleRemoved(log types.Log) (*TokenAdminRegistryRegistryModuleRemoved, error) - FilterRemovedAdministrator(opts *bind.FilterOpts) (*TokenAdminRegistryRemovedAdministratorIterator, error) - - WatchRemovedAdministrator(opts *bind.WatchOpts, sink chan<- *TokenAdminRegistryRemovedAdministrator) (event.Subscription, error) - - ParseRemovedAdministrator(log types.Log) (*TokenAdminRegistryRemovedAdministrator, error) - ParseLog(log types.Log) (generated.AbigenLog, error) Address() common.Address diff --git a/core/gethwrappers/ccip/generated/token_pool/token_pool.go b/core/gethwrappers/ccip/generated/token_pool/token_pool.go index 0fb4c4e087a..0bca23641c3 100644 --- a/core/gethwrappers/ccip/generated/token_pool/token_pool.go +++ b/core/gethwrappers/ccip/generated/token_pool/token_pool.go @@ -82,7 +82,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\":[{\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"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\":[{\"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\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":[{\"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\"},{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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\"}]", } var TokenPoolABI = TokenPoolMetaData.ABI @@ -291,6 +291,28 @@ func (_TokenPool *TokenPoolCallerSession) GetCurrentOutboundRateLimiterState(rem return _TokenPool.Contract.GetCurrentOutboundRateLimiterState(&_TokenPool.CallOpts, remoteChainSelector) } +func (_TokenPool *TokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _TokenPool.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 (_TokenPool *TokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _TokenPool.Contract.GetRateLimitAdmin(&_TokenPool.CallOpts) +} + +func (_TokenPool *TokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _TokenPool.Contract.GetRateLimitAdmin(&_TokenPool.CallOpts) +} + func (_TokenPool *TokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} err := _TokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) @@ -583,6 +605,18 @@ func (_TokenPool *TokenPoolTransactorSession) SetChainRateLimiterConfig(remoteCh return _TokenPool.Contract.SetChainRateLimiterConfig(&_TokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_TokenPool *TokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_TokenPool *TokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _TokenPool.Contract.SetRateLimitAdmin(&_TokenPool.TransactOpts, rateLimitAdmin) +} + +func (_TokenPool *TokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _TokenPool.Contract.SetRateLimitAdmin(&_TokenPool.TransactOpts, rateLimitAdmin) +} + func (_TokenPool *TokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) } @@ -2480,6 +2514,8 @@ type TokenPoolInterface interface { GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2512,6 +2548,8 @@ type TokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) 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 new file mode 100644 index 00000000000..f9bd3b56efa --- /dev/null +++ b/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go @@ -0,0 +1,333 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package usdc_reader_tester + +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 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", +} + +var USDCReaderTesterABI = USDCReaderTesterMetaData.ABI + +var USDCReaderTesterBin = USDCReaderTesterMetaData.Bin + +func DeployUSDCReaderTester(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *USDCReaderTester, error) { + parsed, err := USDCReaderTesterMetaData.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(USDCReaderTesterBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &USDCReaderTester{address: address, abi: *parsed, USDCReaderTesterCaller: USDCReaderTesterCaller{contract: contract}, USDCReaderTesterTransactor: USDCReaderTesterTransactor{contract: contract}, USDCReaderTesterFilterer: USDCReaderTesterFilterer{contract: contract}}, nil +} + +type USDCReaderTester struct { + address common.Address + abi abi.ABI + USDCReaderTesterCaller + USDCReaderTesterTransactor + USDCReaderTesterFilterer +} + +type USDCReaderTesterCaller struct { + contract *bind.BoundContract +} + +type USDCReaderTesterTransactor struct { + contract *bind.BoundContract +} + +type USDCReaderTesterFilterer struct { + contract *bind.BoundContract +} + +type USDCReaderTesterSession struct { + Contract *USDCReaderTester + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type USDCReaderTesterCallerSession struct { + Contract *USDCReaderTesterCaller + CallOpts bind.CallOpts +} + +type USDCReaderTesterTransactorSession struct { + Contract *USDCReaderTesterTransactor + TransactOpts bind.TransactOpts +} + +type USDCReaderTesterRaw struct { + Contract *USDCReaderTester +} + +type USDCReaderTesterCallerRaw struct { + Contract *USDCReaderTesterCaller +} + +type USDCReaderTesterTransactorRaw struct { + Contract *USDCReaderTesterTransactor +} + +func NewUSDCReaderTester(address common.Address, backend bind.ContractBackend) (*USDCReaderTester, error) { + abi, err := abi.JSON(strings.NewReader(USDCReaderTesterABI)) + if err != nil { + return nil, err + } + contract, err := bindUSDCReaderTester(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &USDCReaderTester{address: address, abi: abi, USDCReaderTesterCaller: USDCReaderTesterCaller{contract: contract}, USDCReaderTesterTransactor: USDCReaderTesterTransactor{contract: contract}, USDCReaderTesterFilterer: USDCReaderTesterFilterer{contract: contract}}, nil +} + +func NewUSDCReaderTesterCaller(address common.Address, caller bind.ContractCaller) (*USDCReaderTesterCaller, error) { + contract, err := bindUSDCReaderTester(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &USDCReaderTesterCaller{contract: contract}, nil +} + +func NewUSDCReaderTesterTransactor(address common.Address, transactor bind.ContractTransactor) (*USDCReaderTesterTransactor, error) { + contract, err := bindUSDCReaderTester(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &USDCReaderTesterTransactor{contract: contract}, nil +} + +func NewUSDCReaderTesterFilterer(address common.Address, filterer bind.ContractFilterer) (*USDCReaderTesterFilterer, error) { + contract, err := bindUSDCReaderTester(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &USDCReaderTesterFilterer{contract: contract}, nil +} + +func bindUSDCReaderTester(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := USDCReaderTesterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_USDCReaderTester *USDCReaderTesterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _USDCReaderTester.Contract.USDCReaderTesterCaller.contract.Call(opts, result, method, params...) +} + +func (_USDCReaderTester *USDCReaderTesterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _USDCReaderTester.Contract.USDCReaderTesterTransactor.contract.Transfer(opts) +} + +func (_USDCReaderTester *USDCReaderTesterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _USDCReaderTester.Contract.USDCReaderTesterTransactor.contract.Transact(opts, method, params...) +} + +func (_USDCReaderTester *USDCReaderTesterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _USDCReaderTester.Contract.contract.Call(opts, result, method, params...) +} + +func (_USDCReaderTester *USDCReaderTesterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _USDCReaderTester.Contract.contract.Transfer(opts) +} + +func (_USDCReaderTester *USDCReaderTesterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _USDCReaderTester.Contract.contract.Transact(opts, method, params...) +} + +func (_USDCReaderTester *USDCReaderTesterTransactor) EmitMessageSent(opts *bind.TransactOpts, version uint32, sourceDomain uint32, destinationDomain uint32, recipient [32]byte, destinationCaller [32]byte, sender [32]byte, nonce uint64, messageBody []byte) (*types.Transaction, error) { + return _USDCReaderTester.contract.Transact(opts, "emitMessageSent", version, sourceDomain, destinationDomain, recipient, destinationCaller, sender, nonce, messageBody) +} + +func (_USDCReaderTester *USDCReaderTesterSession) EmitMessageSent(version uint32, sourceDomain uint32, destinationDomain uint32, recipient [32]byte, destinationCaller [32]byte, sender [32]byte, nonce uint64, messageBody []byte) (*types.Transaction, error) { + return _USDCReaderTester.Contract.EmitMessageSent(&_USDCReaderTester.TransactOpts, version, sourceDomain, destinationDomain, recipient, destinationCaller, sender, nonce, messageBody) +} + +func (_USDCReaderTester *USDCReaderTesterTransactorSession) EmitMessageSent(version uint32, sourceDomain uint32, destinationDomain uint32, recipient [32]byte, destinationCaller [32]byte, sender [32]byte, nonce uint64, messageBody []byte) (*types.Transaction, error) { + return _USDCReaderTester.Contract.EmitMessageSent(&_USDCReaderTester.TransactOpts, version, sourceDomain, destinationDomain, recipient, destinationCaller, sender, nonce, messageBody) +} + +type USDCReaderTesterMessageSentIterator struct { + Event *USDCReaderTesterMessageSent + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *USDCReaderTesterMessageSentIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(USDCReaderTesterMessageSent) + 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(USDCReaderTesterMessageSent) + 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 *USDCReaderTesterMessageSentIterator) Error() error { + return it.fail +} + +func (it *USDCReaderTesterMessageSentIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type USDCReaderTesterMessageSent struct { + Arg0 []byte + Raw types.Log +} + +func (_USDCReaderTester *USDCReaderTesterFilterer) FilterMessageSent(opts *bind.FilterOpts) (*USDCReaderTesterMessageSentIterator, error) { + + logs, sub, err := _USDCReaderTester.contract.FilterLogs(opts, "MessageSent") + if err != nil { + return nil, err + } + return &USDCReaderTesterMessageSentIterator{contract: _USDCReaderTester.contract, event: "MessageSent", logs: logs, sub: sub}, nil +} + +func (_USDCReaderTester *USDCReaderTesterFilterer) WatchMessageSent(opts *bind.WatchOpts, sink chan<- *USDCReaderTesterMessageSent) (event.Subscription, error) { + + logs, sub, err := _USDCReaderTester.contract.WatchLogs(opts, "MessageSent") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(USDCReaderTesterMessageSent) + if err := _USDCReaderTester.contract.UnpackLog(event, "MessageSent", 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 (_USDCReaderTester *USDCReaderTesterFilterer) ParseMessageSent(log types.Log) (*USDCReaderTesterMessageSent, error) { + event := new(USDCReaderTesterMessageSent) + if err := _USDCReaderTester.contract.UnpackLog(event, "MessageSent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_USDCReaderTester *USDCReaderTester) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _USDCReaderTester.abi.Events["MessageSent"].ID: + return _USDCReaderTester.ParseMessageSent(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (USDCReaderTesterMessageSent) Topic() common.Hash { + return common.HexToHash("0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036") +} + +func (_USDCReaderTester *USDCReaderTester) Address() common.Address { + return _USDCReaderTester.address +} + +type USDCReaderTesterInterface interface { + EmitMessageSent(opts *bind.TransactOpts, version uint32, sourceDomain uint32, destinationDomain uint32, recipient [32]byte, destinationCaller [32]byte, sender [32]byte, nonce uint64, messageBody []byte) (*types.Transaction, error) + + FilterMessageSent(opts *bind.FilterOpts) (*USDCReaderTesterMessageSentIterator, error) + + WatchMessageSent(opts *bind.WatchOpts, sink chan<- *USDCReaderTesterMessageSent) (event.Subscription, error) + + ParseMessageSent(log types.Log) (*USDCReaderTesterMessageSent, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} 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 1e15b6b6cde..3e754d5cb78 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 @@ -95,8 +95,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\":[{\"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\":\"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\":\"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\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"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\":\"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\"}],\"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\"},{\"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\":[{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x6101406040523480156200001257600080fd5b506040516200559338038062005593833981016040819052620000359162000b4c565b838383833380600081620000905760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c357620000c3816200041b565b5050506001600160a01b0384161580620000e457506001600160a01b038116155b80620000f757506001600160a01b038216155b1562000116576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016957604080516000815260208101909152620001699084620004c6565b5050506001600160a01b038616905062000196576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fd919062000c72565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000240573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000266919062000c99565b905063ffffffff81161562000297576040516334697c6b60e11b815263ffffffff8216600482015260240162000087565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fe919062000c99565b905063ffffffff8116156200032f576040516316ba39c560e31b815263ffffffff8216600482015260240162000087565b6001600160a01b0380891660e05283166101008190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa15801562000381573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a7919062000c99565b63ffffffff166101205260e051608051620003d1916001600160a01b039091169060001962000623565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000de6565b336001600160a01b03821603620004755760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000087565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620004e7576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005725760008382815181106200050b576200050b62000cc1565b602090810291909101015190506200052560028262000709565b1562000568576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620004ea565b5060005b81518110156200061e57600082828151811062000597576200059762000cc1565b6020026020010151905060006001600160a01b0316816001600160a01b031603620005c3575062000615565b620005d060028262000729565b1562000613576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000576565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa15801562000675573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200069b919062000cd7565b620006a7919062000d07565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915291925062000703918691906200074016565b50505050565b600062000720836001600160a01b03841662000811565b90505b92915050565b600062000720836001600160a01b03841662000915565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200078f906001600160a01b03851690849062000967565b8051909150156200061e5780806020019051810190620007b0919062000d1d565b6200061e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000087565b600081815260018301602052604081205480156200090a5760006200083860018362000d41565b85549091506000906200084e9060019062000d41565b9050818114620008ba57600086600001828154811062000872576200087262000cc1565b906000526020600020015490508087600001848154811062000898576200089862000cc1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620008ce57620008ce62000d57565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000723565b600091505062000723565b60008181526001830160205260408120546200095e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000723565b50600062000723565b606062000978848460008562000980565b949350505050565b606082471015620009e35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000087565b600080866001600160a01b0316858760405162000a01919062000d93565b60006040518083038185875af1925050503d806000811462000a40576040519150601f19603f3d011682016040523d82523d6000602084013e62000a45565b606091505b50909250905062000a598783838762000a64565b979650505050505050565b6060831562000ad857825160000362000ad0576001600160a01b0385163b62000ad05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000087565b508162000978565b62000978838381511562000aef5781518083602001fd5b8060405162461bcd60e51b815260040162000087919062000db1565b6001600160a01b038116811462000b2157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b478162000b0b565b919050565b600080600080600060a0868803121562000b6557600080fd5b855162000b728162000b0b565b8095505060208087015162000b878162000b0b565b60408801519095506001600160401b038082111562000ba557600080fd5b818901915089601f83011262000bba57600080fd5b81518181111562000bcf5762000bcf62000b24565b8060051b604051601f19603f8301168101818110858211171562000bf75762000bf762000b24565b60405291825284820192508381018501918c83111562000c1657600080fd5b938501935b8285101562000c3f5762000c2f8562000b3a565b8452938501939285019262000c1b565b80985050505050505062000c566060870162000b3a565b915062000c666080870162000b3a565b90509295509295909350565b60006020828403121562000c8557600080fd5b815162000c928162000b0b565b9392505050565b60006020828403121562000cac57600080fd5b815163ffffffff8116811462000c9257600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000cea57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000723576200072362000cf1565b60006020828403121562000d3057600080fd5b8151801515811462000c9257600080fd5b8181038181111562000723576200072362000cf1565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000d8a57818101518382015260200162000d70565b50506000910152565b6000825162000da781846020870162000d6d565b9190910192915050565b602081526000825180602084015262000dd281604085016020870162000d6d565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516146ed62000ea66000396000818161036c0152818161116601528181611d6d0152611dcb01526000818161062f0152610a31015260008181610345015261107a0152600081816105f301528181611ef5015261293c01526000818161052f01528181611b6b01526121ab015260008181610279015281816102ce01528181610af70152818161104701528181611a8b015281816120cb015281816127c60152612b2701526146ed6000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c80639fdf13ff11610104578063c75eea9c116100a2578063dfadfa3511610071578063dfadfa3514610553578063e0351e13146105f1578063f2fde38b14610617578063fbf84dd71461062a57600080fd5b8063c75eea9c146104f4578063cf7401f314610507578063db6327dc1461051a578063dc0bd9711461052d57600080fd5b8063b0f479a1116100de578063b0f479a11461049b578063b7946580146104b9578063c0d78655146104cc578063c4bffe2b146104df57600080fd5b80639fdf13ff1461040f578063a7cd63b714610417578063af58d59f1461042c57600080fd5b806354c8a4f31161017c57806379ba50971161014b57806379ba5097146103b65780638926f54f146103be5780638da5cb5b146103d15780639a4575b9146103ef57600080fd5b806354c8a4f31461032d5780636155cda0146103405780636b716b0d1461036757806378a010b2146103a357600080fd5b8063181f5a77116101b8578063181f5a771461023b57806321df0da714610277578063240028e8146102be578063390775371461030b57600080fd5b806241d3c1146101de57806301ffc9a7146101f35780630a2fd4931461021b575b600080fd5b6101f16101ec3660046134d1565b610651565b005b610206610201366004613546565b6107ee565b60405190151581526020015b60405180910390f35b61022e6102293660046135ae565b6108d3565b6040516102129190613639565b61022e6040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e342e300000000000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610212565b6102066102cc366004613679565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61031e610319366004613696565b610983565b60405190518152602001610212565b6101f161033b36600461371e565b610bb5565b6102997f000000000000000000000000000000000000000000000000000000000000000081565b61038e7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610212565b6101f16103b136600461378a565b610c30565b6101f1610d9f565b6102066103cc3660046135ae565b610e9c565b60005473ffffffffffffffffffffffffffffffffffffffff16610299565b6104026103fd36600461380f565b610eb3565b604051610212919061384a565b61038e600081565b61041f6111e0565b60405161021291906138aa565b61043f61043a3660046135ae565b6111f1565b604051610212919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610299565b61022e6104c73660046135ae565b6112c6565b6101f16104da366004613679565b6112f1565b6104e76113c5565b6040516102129190613904565b61043f6105023660046135ae565b61147d565b6101f1610515366004613a8f565b61154f565b6101f1610528366004613ad6565b611567565b7f0000000000000000000000000000000000000000000000000000000000000000610299565b6105c76105613660046135ae565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600882529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610212565b7f0000000000000000000000000000000000000000000000000000000000000000610206565b6101f1610625366004613679565b6119ed565b6102997f000000000000000000000000000000000000000000000000000000000000000081565b610659611a01565b60005b818110156107b057600083838381811061067857610678613b18565b90506080020180360381019061068e9190613b5b565b805190915015806106ab5750604081015167ffffffffffffffff16155b1561071a57604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600890925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090951691909316179290921790550161065c565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5682826040516107e2929190613bd5565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061088157507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806108cd57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906108fe90613c5c565b80601f016020809104026020016040519081016040528092919081815260200182805461092a90613c5c565b80156109775780601f1061094c57610100808354040283529160200191610977565b820191906000526020600020905b81548152906001019060200180831161095a57829003601f168201915b50505050509050919050565b6040805160208101909152600081526109a361099e83613d5a565b611a84565b60006109b260c0840184613e4f565b8101906109bf9190613eb4565b905060006109d060e0850185613e4f565b8101906109dd9190613ef3565b90506109ed816000015183611cb5565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610a6492600401613f84565b6020604051808303816000875af1158015610a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa79190613fa9565b610add576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016336060870135611e66565b610b326060850160408601613679565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9491815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b610bbd611a01565b610c2a84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef392505050565b50505050565b610c38611a01565b610c4183610e9c565b610c83576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610711565b67ffffffffffffffff831660009081526007602052604081206004018054610caa90613c5c565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd690613c5c565b8015610d235780601f10610cf857610100808354040283529160200191610d23565b820191906000526020600020905b815481529060010190602001808311610d0657829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610d5283858361400e565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610d9193929190614172565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610711565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108cd600567ffffffffffffffff84166120a9565b6040805180820190915260608082526020820152610ed8610ed3836141a2565b6120c4565b6000600881610eed60408601602087016135ae565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610f9457610f5560408401602085016135ae565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610711565b610f9e8380613e4f565b9050602014610fe557610fb18380613e4f565b6040517fa3c8cf09000000000000000000000000000000000000000000000000000000008152600401610711929190614246565b602081015181516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060860135600482015263ffffffff90921660248301526044820181905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091526000917f00000000000000000000000000000000000000000000000000000000000000009091169063f856ddb69060a4016020604051808303816000875af11580156110c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e9919061425a565b6040516060860135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a260405180604001604052806111468660200160208101906104c791906135ae565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529052949350505050565b60606111ec600261228e565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526108cd9061229b565b67ffffffffffffffff811660009081526007602052604090206005018054606091906108fe90613c5c565b6112f9611a01565b73ffffffffffffffffffffffffffffffffffffffff8116611346576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f168491016107e2565b606060006113d3600561228e565b90506000815167ffffffffffffffff8111156113f1576113f1613946565b60405190808252806020026020018201604052801561141a578160200160208202803683370190505b50905060005b82518110156114765782818151811061143b5761143b613b18565b602002602001015182828151811061145557611455613b18565b67ffffffffffffffff90921660209283029190910190910152600101611420565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526108cd9061229b565b611557611a01565b61156283838361234d565b505050565b61156f611a01565b60005b8181101561156257600083838381811061158e5761158e613b18565b90506020028101906115a09190614277565b6115a9906142b5565b90506115be8160800151826020015115612437565b6115d18160a00151826020015115612437565b8060200151156118cd5780516115f39060059067ffffffffffffffff16612570565b6116385780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610711565b604081015151158061164d5750606081015151155b15611684576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906118659082614369565b506060820151600582019061187a9082614369565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506118c09493929190614483565b60405180910390a16119e4565b80516118e59060059067ffffffffffffffff1661257c565b61192a5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610711565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906119936004830182613483565b6119a1600583016000613483565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611572565b6119f5611a01565b6119fe81612588565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610711565b565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611b195760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610711565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611beb9190613fa9565b15611c22576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c2f816020015161267d565b6000611c3e82602001516108d3565b9050805160001480611c62575080805190602001208260a001518051906020012014155b15611c9f578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016107119190613639565b611cb1826020015183606001516127a3565b5050565b600482015163ffffffff811615611d00576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610711565b6008830151600c8401516014850151602085015163ffffffff808516911614611d6b5760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff91821660048201529084166024820152604401610711565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff1614611e00576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610711565b845167ffffffffffffffff828116911614611e5e5784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff91821660048201529082166024820152604401610711565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526115629084906127ea565b7f0000000000000000000000000000000000000000000000000000000000000000611f4a576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fe0576000838281518110611f6a57611f6a613b18565b60200260200101519050611f888160026128f690919063ffffffff16565b15611fd75760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f4d565b5060005b815181101561156257600082828151811061200157612001613b18565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361204557506120a1565b612050600282612918565b1561209f5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe4565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146121595760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610711565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612207573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222b9190613fa9565b15612262576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61226f816040015161293a565b61227c81602001516129b9565b6119fe81602001518260600151612b07565b606060006120bd83612b4b565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261232982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261230d919061454b565b85608001516fffffffffffffffffffffffffffffffff16612ba6565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61235683610e9c565b612398576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610711565b6123a3826000612437565b67ffffffffffffffff831660009081526007602052604090206123c69083612bd0565b6123d1816000612437565b67ffffffffffffffff831660009081526007602052604090206123f79060020182612bd0565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161242a9392919061455e565b60405180910390a1505050565b8151156124fe5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061248d575060408201516fffffffffffffffffffffffffffffffff16155b156124c657816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161071191906145e1565b8015611cb1576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612537575060208201516fffffffffffffffffffffffffffffffff1615155b15611cb157816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161071191906145e1565b60006120bd8383612d72565b60006120bd8383612dc1565b3373ffffffffffffffffffffffffffffffffffffffff821603612607576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610711565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61268681610e9c565b6126c8576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610711565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061276b9190613fa9565b6119fe576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610711565b67ffffffffffffffff82166000908152600760205260409020611cb190600201827f0000000000000000000000000000000000000000000000000000000000000000612eb4565b600061284c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132379092919063ffffffff16565b805190915015611562578080602001905181019061286a9190613fa9565b611562576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610711565b60006120bd8373ffffffffffffffffffffffffffffffffffffffff8416612dc1565b60006120bd8373ffffffffffffffffffffffffffffffffffffffff8416612d72565b7f0000000000000000000000000000000000000000000000000000000000000000156119fe5761296b600282613246565b6119fe576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610711565b6129c281610e9c565b612a04576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610711565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa1919061461d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119fe576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610711565b67ffffffffffffffff82166000908152600760205260409020611cb190827f0000000000000000000000000000000000000000000000000000000000000000612eb4565b60608160000180548060200260200160405190810160405280929190818152602001828054801561097757602002820191906000526020600020905b815481526020019060010190808311612b875750505050509050919050565b6000612bc585612bb6848661463a565b612bc09087614651565b613275565b90505b949350505050565b8154600090612bf990700100000000000000000000000000000000900463ffffffff164261454b565b90508015612c9b5760018301548354612c41916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612ba6565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612cc1916fffffffffffffffffffffffffffffffff9081169116613275565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061242a9084906145e1565b6000818152600183016020526040812054612db9575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108cd565b5060006108cd565b60008181526001830160205260408120548015612eaa576000612de560018361454b565b8554909150600090612df99060019061454b565b9050818114612e5e576000866000018281548110612e1957612e19613b18565b9060005260206000200154905080876000018481548110612e3c57612e3c613b18565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e6f57612e6f614664565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108cd565b60009150506108cd565b825474010000000000000000000000000000000000000000900460ff161580612edb575081155b15612ee557505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f2b90700100000000000000000000000000000000900463ffffffff164261454b565b90508015612feb5781831115612f6d576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fa79083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612ba6565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130a25773ffffffffffffffffffffffffffffffffffffffff841661304a576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610711565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610711565b848310156131b55760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130e6908261454b565b6130f0878a61454b565b6130fa9190614651565b6131049190614693565b905073ffffffffffffffffffffffffffffffffffffffff861661315d576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610711565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610711565b6131bf858461454b565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6060612bc8848460008561328b565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156120bd565b600081831061328457816120bd565b5090919050565b60608247101561331d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610711565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161334691906146ce565b60006040518083038185875af1925050503d8060008114613383576040519150601f19603f3d011682016040523d82523d6000602084013e613388565b606091505b5091509150613399878383876133a4565b979650505050505050565b6060831561343a5782516000036134335773ffffffffffffffffffffffffffffffffffffffff85163b613433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610711565b5081612bc8565b612bc8838381511561344f5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107119190613639565b50805461348f90613c5c565b6000825580601f1061349f575050565b601f0160209004906000526020600020908101906119fe91905b808211156134cd57600081556001016134b9565b5090565b600080602083850312156134e457600080fd5b823567ffffffffffffffff808211156134fc57600080fd5b818501915085601f83011261351057600080fd5b81358181111561351f57600080fd5b8660208260071b850101111561353457600080fd5b60209290920196919550909350505050565b60006020828403121561355857600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146120bd57600080fd5b67ffffffffffffffff811681146119fe57600080fd5b80356135a981613588565b919050565b6000602082840312156135c057600080fd5b81356120bd81613588565b60005b838110156135e65781810151838201526020016135ce565b50506000910152565b600081518084526136078160208601602086016135cb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006120bd60208301846135ef565b73ffffffffffffffffffffffffffffffffffffffff811681146119fe57600080fd5b80356135a98161364c565b60006020828403121561368b57600080fd5b81356120bd8161364c565b6000602082840312156136a857600080fd5b813567ffffffffffffffff8111156136bf57600080fd5b820161010081850312156120bd57600080fd5b60008083601f8401126136e457600080fd5b50813567ffffffffffffffff8111156136fc57600080fd5b6020830191508360208260051b850101111561371757600080fd5b9250929050565b6000806000806040858703121561373457600080fd5b843567ffffffffffffffff8082111561374c57600080fd5b613758888389016136d2565b9096509450602087013591508082111561377157600080fd5b5061377e878288016136d2565b95989497509550505050565b60008060006040848603121561379f57600080fd5b83356137aa81613588565b9250602084013567ffffffffffffffff808211156137c757600080fd5b818601915086601f8301126137db57600080fd5b8135818111156137ea57600080fd5b8760208285010111156137fc57600080fd5b6020830194508093505050509250925092565b60006020828403121561382157600080fd5b813567ffffffffffffffff81111561383857600080fd5b820160a081850312156120bd57600080fd5b60208152600082516040602084015261386660608401826135ef565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526138a182826135ef565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156138f857835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016138c6565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156138f857835167ffffffffffffffff1683529284019291840191600101613920565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff8111828210171561399957613999613946565b60405290565b6040805190810167ffffffffffffffff8111828210171561399957613999613946565b60405160c0810167ffffffffffffffff8111828210171561399957613999613946565b80151581146119fe57600080fd5b80356135a9816139e5565b80356fffffffffffffffffffffffffffffffff811681146135a957600080fd5b600060608284031215613a3057600080fd5b6040516060810181811067ffffffffffffffff82111715613a5357613a53613946565b6040529050808235613a64816139e5565b8152613a72602084016139fe565b6020820152613a83604084016139fe565b60408201525092915050565b600080600060e08486031215613aa457600080fd5b8335613aaf81613588565b9250613abe8560208601613a1e565b9150613acd8560808601613a1e565b90509250925092565b60008060208385031215613ae957600080fd5b823567ffffffffffffffff811115613b0057600080fd5b613b0c858286016136d2565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff811681146135a957600080fd5b600060808284031215613b6d57600080fd5b6040516080810181811067ffffffffffffffff82111715613b9057613b90613946565b60405282358152613ba360208401613b47565b60208201526040830135613bb681613588565b60408201526060830135613bc9816139e5565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613c4f578135835263ffffffff613c07868401613b47565b168584015283820135613c1981613588565b67ffffffffffffffff1683850152606082810135613c36816139e5565b1515908401526080928301929190910190600101613beb565b5090979650505050505050565b600181811c90821680613c7057607f821691505b602082108103613ca9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f830112613cc057600080fd5b813567ffffffffffffffff80821115613cdb57613cdb613946565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613d2157613d21613946565b81604052838152866020858801011115613d3a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101008236031215613d6d57600080fd5b613d75613975565b823567ffffffffffffffff80821115613d8d57600080fd5b613d9936838701613caf565b8352613da76020860161359e565b6020840152613db86040860161366e565b604084015260608501356060840152613dd36080860161366e565b608084015260a0850135915080821115613dec57600080fd5b613df836838701613caf565b60a084015260c0850135915080821115613e1157600080fd5b613e1d36838701613caf565b60c084015260e0850135915080821115613e3657600080fd5b50613e4336828601613caf565b60e08301525092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613e8457600080fd5b83018035915067ffffffffffffffff821115613e9f57600080fd5b60200191503681900382131561371757600080fd5b600060408284031215613ec657600080fd5b613ece61399f565b8235613ed981613588565b8152613ee760208401613b47565b60208201529392505050565b600060208284031215613f0557600080fd5b813567ffffffffffffffff80821115613f1d57600080fd5b9083019060408286031215613f3157600080fd5b613f3961399f565b823582811115613f4857600080fd5b613f5487828601613caf565b825250602083013582811115613f6957600080fd5b613f7587828601613caf565b60208301525095945050505050565b604081526000613f9760408301856135ef565b82810360208401526138a181856135ef565b600060208284031215613fbb57600080fd5b81516120bd816139e5565b601f821115611562576000816000526020600020601f850160051c81016020861015613fef5750805b601f850160051c820191505b81811015611e5e57828155600101613ffb565b67ffffffffffffffff83111561402657614026613946565b61403a836140348354613c5c565b83613fc6565b6000601f84116001811461408c57600085156140565750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614122565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156140db57868501358255602094850194600190920191016140bb565b5086821015614116577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60408152600061418560408301866135ef565b8281036020840152614198818587614129565b9695505050505050565b600060a082360312156141b457600080fd5b60405160a0810167ffffffffffffffff82821081831117156141d8576141d8613946565b8160405284359150808211156141ed57600080fd5b506141fa36828601613caf565b825250602083013561420b81613588565b6020820152604083013561421e8161364c565b604082015260608381013590820152608083013561423b8161364c565b608082015292915050565b602081526000612bc8602083018486614129565b60006020828403121561426c57600080fd5b81516120bd81613588565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec18336030181126142ab57600080fd5b9190910192915050565b600061014082360312156142c857600080fd5b6142d06139c2565b6142d98361359e565b81526142e7602084016139f3565b6020820152604083013567ffffffffffffffff8082111561430757600080fd5b61431336838701613caf565b6040840152606085013591508082111561432c57600080fd5b5061433936828601613caf565b60608301525061434c3660808501613a1e565b608082015261435e3660e08501613a1e565b60a082015292915050565b815167ffffffffffffffff81111561438357614383613946565b614397816143918454613c5c565b84613fc6565b602080601f8311600181146143ea57600084156143b45750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611e5e565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561443757888601518255948401946001909101908401614418565b508582101561447357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526144a7818401876135ef565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506144e59050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526138a1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108cd576108cd61451c565b67ffffffffffffffff8416815260e081016145aa60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612bc8565b606081016108cd82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561462f57600080fd5b81516120bd8161364c565b80820281158282048414176108cd576108cd61451c565b808201808211156108cd576108cd61451c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000826146c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082516142ab8184602087016135cb56fea164736f6c6343000818000a", + 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\":[{\"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\":\"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\":\"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\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"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\":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\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"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\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"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\":\"chains\",\"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\":\"getRemotePool\",\"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\":\"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\"}],\"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\"},{\"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\":[{\"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\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"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: "0x6101406040523480156200001257600080fd5b50604051620052c6380380620052c6833981016040819052620000359162000b4c565b838383833380600081620000905760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c357620000c3816200041b565b5050506001600160a01b0384161580620000e457506001600160a01b038116155b80620000f757506001600160a01b038216155b1562000116576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016957604080516000815260208101909152620001699084620004c6565b5050506001600160a01b038616905062000196576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fd919062000c72565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000240573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000266919062000c99565b905063ffffffff81161562000297576040516334697c6b60e11b815263ffffffff8216600482015260240162000087565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fe919062000c99565b905063ffffffff8116156200032f576040516316ba39c560e31b815263ffffffff8216600482015260240162000087565b6001600160a01b0380891660e05283166101008190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa15801562000381573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a7919062000c99565b63ffffffff166101205260e051608051620003d1916001600160a01b039091169060001962000623565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000de6565b336001600160a01b03821603620004755760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000087565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620004e7576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005725760008382815181106200050b576200050b62000cc1565b602090810291909101015190506200052560028262000709565b1562000568576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620004ea565b5060005b81518110156200061e57600082828151811062000597576200059762000cc1565b6020026020010151905060006001600160a01b0316816001600160a01b031603620005c3575062000615565b620005d060028262000729565b1562000613576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000576565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa15801562000675573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200069b919062000cd7565b620006a7919062000d07565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915291925062000703918691906200074016565b50505050565b600062000720836001600160a01b03841662000811565b90505b92915050565b600062000720836001600160a01b03841662000915565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200078f906001600160a01b03851690849062000967565b8051909150156200061e5780806020019051810190620007b0919062000d1d565b6200061e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000087565b600081815260018301602052604081205480156200090a5760006200083860018362000d41565b85549091506000906200084e9060019062000d41565b9050808214620008ba57600086600001828154811062000872576200087262000cc1565b906000526020600020015490508087600001848154811062000898576200089862000cc1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620008ce57620008ce62000d57565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000723565b600091505062000723565b60008181526001830160205260408120546200095e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000723565b50600062000723565b606062000978848460008562000980565b949350505050565b606082471015620009e35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000087565b600080866001600160a01b0316858760405162000a01919062000d93565b60006040518083038185875af1925050503d806000811462000a40576040519150601f19603f3d011682016040523d82523d6000602084013e62000a45565b606091505b50909250905062000a598783838762000a64565b979650505050505050565b6060831562000ad857825160000362000ad0576001600160a01b0385163b62000ad05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000087565b508162000978565b62000978838381511562000aef5781518083602001fd5b8060405162461bcd60e51b815260040162000087919062000db1565b6001600160a01b038116811462000b2157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b478162000b0b565b919050565b600080600080600060a0868803121562000b6557600080fd5b855162000b728162000b0b565b8095505060208087015162000b878162000b0b565b60408801519095506001600160401b038082111562000ba557600080fd5b818901915089601f83011262000bba57600080fd5b81518181111562000bcf5762000bcf62000b24565b8060051b604051601f19603f8301168101818110858211171562000bf75762000bf762000b24565b60405291825284820192508381018501918c83111562000c1657600080fd5b938501935b8285101562000c3f5762000c2f8562000b3a565b8452938501939285019262000c1b565b80985050505050505062000c566060870162000b3a565b915062000c666080870162000b3a565b90509295509295909350565b60006020828403121562000c8557600080fd5b815162000c928162000b0b565b9392505050565b60006020828403121562000cac57600080fd5b815163ffffffff8116811462000c9257600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000cea57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000723576200072362000cf1565b60006020828403121562000d3057600080fd5b8151801515811462000c9257600080fd5b8181038181111562000723576200072362000cf1565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000d8a57818101518382015260200162000d70565b50506000910152565b6000825162000da781846020870162000d6d565b9190910192915050565b602081526000825180602084015262000dd281604085016020870162000d6d565b601f01601f19169190910160400192915050565b60805160a05160c05160e051610100516101205161442762000e9f60003960008181610382015281816111d101528181611e4a0152611ea80152600081816106760152610a7801526000818161035b01526110e701526000818161063a01528181611f45015261288001526000818161057601528181611c4801526121fb01526000818161028f015281816102e4015281816110b101528181611b680152818161211b015281816128160152612a6b01526144276000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c80639a4575b91161010f578063c75eea9c116100a2578063dfadfa3511610071578063dfadfa351461059a578063e0351e1314610638578063f2fde38b1461065e578063fbf84dd71461067157600080fd5b8063c75eea9c1461053b578063cf7401f31461054e578063db6327dc14610561578063dc0bd9711461057457600080fd5b8063b0f479a1116100de578063b0f479a1146104e2578063b794658014610500578063c0d7865514610513578063c4bffe2b1461052657600080fd5b80639a4575b9146104365780639fdf13ff14610456578063a7cd63b71461045e578063af58d59f1461047357600080fd5b80636155cda01161018757806379ba50971161015657806379ba5097146103ea5780637d54534e146103f25780638926f54f146104055780638da5cb5b1461041857600080fd5b80636155cda0146103565780636b716b0d1461037d5780636d3d1a58146103b957806378a010b2146103d757600080fd5b806321df0da7116101c357806321df0da71461028d578063240028e8146102d4578063390775371461032157806354c8a4f31461034357600080fd5b806241d3c1146101f457806301ffc9a7146102095780630a2fd49314610231578063181f5a7714610251575b600080fd5b61020761020236600461320e565b610698565b005b61021c610217366004613283565b610835565b60405190151581526020015b60405180910390f35b61024461023f3660046132eb565b61091a565b604051610228919061336c565b6102446040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e300000000000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610228565b61021c6102e23660046133ac565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61033461032f3660046133c9565b6109ca565b60405190518152602001610228565b610207610351366004613451565b610bb7565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6103a47f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610228565b60085473ffffffffffffffffffffffffffffffffffffffff166102af565b6102076103e53660046134bd565b610c32565b610207610da1565b6102076104003660046133ac565b610e9e565b61021c6104133660046132eb565b610eed565b60005473ffffffffffffffffffffffffffffffffffffffff166102af565b610449610444366004613542565b610f04565b604051610228919061357d565b6103a4600081565b61046661124c565b60405161022891906135dd565b6104866104813660046132eb565b61125d565b604051610228919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102af565b61024461050e3660046132eb565b611332565b6102076105213660046133ac565b61135d565b61052e611431565b6040516102289190613637565b6104866105493660046132eb565b6114e9565b61020761055c3660046137c2565b6115bb565b61020761056f366004613809565b611644565b7f00000000000000000000000000000000000000000000000000000000000000006102af565b61060e6105a83660046132eb565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600982529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610228565b7f000000000000000000000000000000000000000000000000000000000000000061021c565b61020761066c3660046133ac565b611aca565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6106a0611ade565b60005b818110156107f75760008383838181106106bf576106bf61384b565b9050608002018036038101906106d5919061388e565b805190915015806106f25750604081015167ffffffffffffffff16155b1561076157604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600990925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169190931617929092179055016106a3565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee568282604051610829929190613908565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806108c857507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061091457507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906109459061398f565b80601f01602080910402602001604051908101604052809291908181526020018280546109719061398f565b80156109be5780601f10610993576101008083540402835291602001916109be565b820191906000526020600020905b8154815290600101906020018083116109a157829003601f168201915b50505050509050919050565b6040805160208101909152600081526109ea6109e583613a8d565b611b61565b60006109f960c0840184613b82565b810190610a069190613be7565b90506000610a1760e0850185613b82565b810190610a249190613c26565b9050610a34816000015183611d92565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aab92600401613cb7565b6020604051808303816000875af1158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee9190613cdc565b610b24576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3460608501604086016133ac565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9691815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b610bbf611ade565b610c2c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611f4392505050565b50505050565b610c3a611ade565b610c4383610eed565b610c85576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610758565b67ffffffffffffffff831660009081526007602052604081206004018054610cac9061398f565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd89061398f565b8015610d255780601f10610cfa57610100808354040283529160200191610d25565b820191906000526020600020905b815481529060010190602001808311610d0857829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610d54838583613d41565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610d9393929190613ea5565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610758565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ea6611ade565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000610914600567ffffffffffffffff84166120f9565b6040805180820190915260608082526020820152610f29610f2483613ed5565b612114565b6000600981610f3e60408601602087016132eb565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610fe557610fa660408401602085016132eb565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b610fef8380613b82565b9050602014611036576110028380613b82565b6040517fa3c8cf09000000000000000000000000000000000000000000000000000000008152600401610758929190613f79565b60006110428480613b82565b81019061104f9190613f8d565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af1158015611130573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111549190613fa6565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a260405180604001604052806111b187602001602081019061050e91906132eb565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b606061125860026122de565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610914906122eb565b67ffffffffffffffff811660009081526007602052604090206005018054606091906109459061398f565b611365611ade565b73ffffffffffffffffffffffffffffffffffffffff81166113b2576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610829565b6060600061143f60056122de565b90506000815167ffffffffffffffff81111561145d5761145d613679565b604051908082528060200260200182016040528015611486578160200160208202803683370190505b50905060005b82518110156114e2578281815181106114a7576114a761384b565b60200260200101518282815181106114c1576114c161384b565b67ffffffffffffffff9092166020928302919091019091015260010161148c565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610914906122eb565b60085473ffffffffffffffffffffffffffffffffffffffff1633148015906115fb575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611634576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b61163f83838361239d565b505050565b61164c611ade565b60005b8181101561163f57600083838381811061166b5761166b61384b565b905060200281019061167d9190613fc3565b61168690614001565b905061169b8160800151826020015115612487565b6116ae8160a00151826020015115612487565b8060200151156119aa5780516116d09060059067ffffffffffffffff166125c0565b6117155780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b604081015151158061172a5750606081015151155b15611761576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c1790911696151502959095179098559081015194015193811693169091029190911760038201559151909190600482019061194290826140b5565b506060820151600582019061195790826140b5565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061199d94939291906141cf565b60405180910390a1611ac1565b80516119c29060059067ffffffffffffffff166125cc565b611a075780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a7060048301826131c0565b611a7e6005830160006131c0565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b5060010161164f565b611ad2611ade565b611adb816125d8565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611b5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610758565b565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611bf65760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610758565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc89190613cdc565b15611cff576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d0c81602001516126cd565b6000611d1b826020015161091a565b9050805160001480611d3f575080805190602001208260a001518051906020012014155b15611d7c578160a001516040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610758919061336c565b611d8e826020015183606001516127f3565b5050565b600482015163ffffffff811615611ddd576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610758565b6008830151600c8401516014850151602085015163ffffffff808516911614611e485760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff91821660048201529084166024820152604401610758565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff1614611edd576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610758565b845167ffffffffffffffff828116911614611f3b5784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff91821660048201529082166024820152604401610758565b505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611f9a576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015612030576000838281518110611fba57611fba61384b565b60200260200101519050611fd881600261283a90919063ffffffff16565b156120275760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f9d565b5060005b815181101561163f5760008282815181106120515761205161384b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361209557506120f1565b6120a060028261285c565b156120ef5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612034565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146121a95760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610758565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227b9190613cdc565b156122b2576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122bf816040015161287e565b6122cc81602001516128fd565b611adb81602001518260600151612a4b565b6060600061210d83612a8f565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261237982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261235d9190614297565b85608001516fffffffffffffffffffffffffffffffff16612aea565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6123a683610eed565b6123e8576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610758565b6123f3826000612487565b67ffffffffffffffff831660009081526007602052604090206124169083612b14565b612421816000612487565b67ffffffffffffffff831660009081526007602052604090206124479060020182612b14565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161247a939291906142aa565b60405180910390a1505050565b81511561254e5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806124dd575060408201516fffffffffffffffffffffffffffffffff16155b1561251657816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610758919061432d565b8015611d8e576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612587575060208201516fffffffffffffffffffffffffffffffff1615155b15611d8e57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610758919061432d565b600061210d8383612cb6565b600061210d8383612d05565b3373ffffffffffffffffffffffffffffffffffffffff821603612657576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610758565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6126d681610eed565b612718576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610758565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612797573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127bb9190613cdc565b611adb576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b67ffffffffffffffff82166000908152600760205260409020611d8e90600201827f0000000000000000000000000000000000000000000000000000000000000000612df8565b600061210d8373ffffffffffffffffffffffffffffffffffffffff8416612d05565b600061210d8373ffffffffffffffffffffffffffffffffffffffff8416612cb6565b7f000000000000000000000000000000000000000000000000000000000000000015611adb576128af60028261317b565b611adb576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610758565b61290681610eed565b612948576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610758565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156129c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e59190614369565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611adb576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b67ffffffffffffffff82166000908152600760205260409020611d8e90827f0000000000000000000000000000000000000000000000000000000000000000612df8565b6060816000018054806020026020016040519081016040528092919081815260200182805480156109be57602002820191906000526020600020905b815481526020019060010190808311612acb5750505050509050919050565b6000612b0985612afa8486614386565b612b04908761439d565b6131aa565b90505b949350505050565b8154600090612b3d90700100000000000000000000000000000000900463ffffffff1642614297565b90508015612bdf5760018301548354612b85916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612aea565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c05916fffffffffffffffffffffffffffffffff90811691166131aa565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061247a90849061432d565b6000818152600183016020526040812054612cfd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610914565b506000610914565b60008181526001830160205260408120548015612dee576000612d29600183614297565b8554909150600090612d3d90600190614297565b9050808214612da2576000866000018281548110612d5d57612d5d61384b565b9060005260206000200154905080876000018481548110612d8057612d8061384b565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612db357612db36143b0565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610914565b6000915050610914565b825474010000000000000000000000000000000000000000900460ff161580612e1f575081155b15612e2957505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612e6f90700100000000000000000000000000000000900463ffffffff1642614297565b90508015612f2f5781831115612eb1576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612eeb9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612aea565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612fe65773ffffffffffffffffffffffffffffffffffffffff8416612f8e576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610758565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610758565b848310156130f95760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690600090829061302a9082614297565b613034878a614297565b61303e919061439d565b61304891906143df565b905073ffffffffffffffffffffffffffffffffffffffff86166130a1576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610758565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610758565b6131038584614297565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561210d565b60008183106131b9578161210d565b5090919050565b5080546131cc9061398f565b6000825580601f106131dc575050565b601f016020900490600052602060002090810190611adb91905b8082111561320a57600081556001016131f6565b5090565b6000806020838503121561322157600080fd5b823567ffffffffffffffff8082111561323957600080fd5b818501915085601f83011261324d57600080fd5b81358181111561325c57600080fd5b8660208260071b850101111561327157600080fd5b60209290920196919550909350505050565b60006020828403121561329557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461210d57600080fd5b67ffffffffffffffff81168114611adb57600080fd5b80356132e6816132c5565b919050565b6000602082840312156132fd57600080fd5b813561210d816132c5565b6000815180845260005b8181101561332e57602081850181015186830182015201613312565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061210d6020830184613308565b73ffffffffffffffffffffffffffffffffffffffff81168114611adb57600080fd5b80356132e68161337f565b6000602082840312156133be57600080fd5b813561210d8161337f565b6000602082840312156133db57600080fd5b813567ffffffffffffffff8111156133f257600080fd5b8201610100818503121561210d57600080fd5b60008083601f84011261341757600080fd5b50813567ffffffffffffffff81111561342f57600080fd5b6020830191508360208260051b850101111561344a57600080fd5b9250929050565b6000806000806040858703121561346757600080fd5b843567ffffffffffffffff8082111561347f57600080fd5b61348b88838901613405565b909650945060208701359150808211156134a457600080fd5b506134b187828801613405565b95989497509550505050565b6000806000604084860312156134d257600080fd5b83356134dd816132c5565b9250602084013567ffffffffffffffff808211156134fa57600080fd5b818601915086601f83011261350e57600080fd5b81358181111561351d57600080fd5b87602082850101111561352f57600080fd5b6020830194508093505050509250925092565b60006020828403121561355457600080fd5b813567ffffffffffffffff81111561356b57600080fd5b820160a0818503121561210d57600080fd5b6020815260008251604060208401526135996060840182613308565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526135d48282613308565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561362b57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016135f9565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561362b57835167ffffffffffffffff1683529284019291840191600101613653565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156136cc576136cc613679565b60405290565b6040805190810167ffffffffffffffff811182821017156136cc576136cc613679565b60405160c0810167ffffffffffffffff811182821017156136cc576136cc613679565b8015158114611adb57600080fd5b80356132e681613718565b80356fffffffffffffffffffffffffffffffff811681146132e657600080fd5b60006060828403121561376357600080fd5b6040516060810181811067ffffffffffffffff8211171561378657613786613679565b604052905080823561379781613718565b81526137a560208401613731565b60208201526137b660408401613731565b60408201525092915050565b600080600060e084860312156137d757600080fd5b83356137e2816132c5565b92506137f18560208601613751565b91506138008560808601613751565b90509250925092565b6000806020838503121561381c57600080fd5b823567ffffffffffffffff81111561383357600080fd5b61383f85828601613405565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff811681146132e657600080fd5b6000608082840312156138a057600080fd5b6040516080810181811067ffffffffffffffff821117156138c3576138c3613679565b604052823581526138d66020840161387a565b602082015260408301356138e9816132c5565b604082015260608301356138fc81613718565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613982578135835263ffffffff61393a86840161387a565b16858401528382013561394c816132c5565b67ffffffffffffffff168385015260608281013561396981613718565b151590840152608092830192919091019060010161391e565b5090979650505050505050565b600181811c908216806139a357607f821691505b6020821081036139dc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126139f357600080fd5b813567ffffffffffffffff80821115613a0e57613a0e613679565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613a5457613a54613679565b81604052838152866020858801011115613a6d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101008236031215613aa057600080fd5b613aa86136a8565b823567ffffffffffffffff80821115613ac057600080fd5b613acc368387016139e2565b8352613ada602086016132db565b6020840152613aeb604086016133a1565b604084015260608501356060840152613b06608086016133a1565b608084015260a0850135915080821115613b1f57600080fd5b613b2b368387016139e2565b60a084015260c0850135915080821115613b4457600080fd5b613b50368387016139e2565b60c084015260e0850135915080821115613b6957600080fd5b50613b76368286016139e2565b60e08301525092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613bb757600080fd5b83018035915067ffffffffffffffff821115613bd257600080fd5b60200191503681900382131561344a57600080fd5b600060408284031215613bf957600080fd5b613c016136d2565b8235613c0c816132c5565b8152613c1a6020840161387a565b60208201529392505050565b600060208284031215613c3857600080fd5b813567ffffffffffffffff80821115613c5057600080fd5b9083019060408286031215613c6457600080fd5b613c6c6136d2565b823582811115613c7b57600080fd5b613c87878286016139e2565b825250602083013582811115613c9c57600080fd5b613ca8878286016139e2565b60208301525095945050505050565b604081526000613cca6040830185613308565b82810360208401526135d48185613308565b600060208284031215613cee57600080fd5b815161210d81613718565b601f82111561163f576000816000526020600020601f850160051c81016020861015613d225750805b601f850160051c820191505b81811015611f3b57828155600101613d2e565b67ffffffffffffffff831115613d5957613d59613679565b613d6d83613d67835461398f565b83613cf9565b6000601f841160018114613dbf5760008515613d895750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613e55565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613e0e5786850135825560209485019460019092019101613dee565b5086821015613e49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081526000613eb86040830186613308565b8281036020840152613ecb818587613e5c565b9695505050505050565b600060a08236031215613ee757600080fd5b60405160a0810167ffffffffffffffff8282108183111715613f0b57613f0b613679565b816040528435915080821115613f2057600080fd5b50613f2d368286016139e2565b8252506020830135613f3e816132c5565b60208201526040830135613f518161337f565b6040820152606083810135908201526080830135613f6e8161337f565b608082015292915050565b602081526000612b0c602083018486613e5c565b600060208284031215613f9f57600080fd5b5035919050565b600060208284031215613fb857600080fd5b815161210d816132c5565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613ff757600080fd5b9190910192915050565b6000610140823603121561401457600080fd5b61401c6136f5565b614025836132db565b815261403360208401613726565b6020820152604083013567ffffffffffffffff8082111561405357600080fd5b61405f368387016139e2565b6040840152606085013591508082111561407857600080fd5b50614085368286016139e2565b6060830152506140983660808501613751565b60808201526140aa3660e08501613751565b60a082015292915050565b815167ffffffffffffffff8111156140cf576140cf613679565b6140e3816140dd845461398f565b84613cf9565b602080601f83116001811461413657600084156141005750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611f3b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561418357888601518255948401946001909101908401614164565b50858210156141bf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526141f381840187613308565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506142319050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526135d4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561091457610914614268565b67ffffffffffffffff8416815260e081016142f660208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612b0c565b6060810161091482848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561437b57600080fd5b815161210d8161337f565b808202811582820484141761091457610914614268565b8082018082111561091457610914614268565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614415577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var USDCTokenPoolABI = USDCTokenPoolMetaData.ABI @@ -367,6 +367,28 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) GetDomain(chainSelector uint64 return _USDCTokenPool.Contract.GetDomain(&_USDCTokenPool.CallOpts, chainSelector) } +func (_USDCTokenPool *USDCTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _USDCTokenPool.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 (_USDCTokenPool *USDCTokenPoolSession) GetRateLimitAdmin() (common.Address, error) { + return _USDCTokenPool.Contract.GetRateLimitAdmin(&_USDCTokenPool.CallOpts) +} + +func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) { + return _USDCTokenPool.Contract.GetRateLimitAdmin(&_USDCTokenPool.CallOpts) +} + func (_USDCTokenPool *USDCTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} err := _USDCTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) @@ -759,6 +781,18 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetDomains(domains []USDCT return _USDCTokenPool.Contract.SetDomains(&_USDCTokenPool.TransactOpts, domains) } +func (_USDCTokenPool *USDCTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) +} + +func (_USDCTokenPool *USDCTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _USDCTokenPool.Contract.SetRateLimitAdmin(&_USDCTokenPool.TransactOpts, rateLimitAdmin) +} + +func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) { + return _USDCTokenPool.Contract.SetRateLimitAdmin(&_USDCTokenPool.TransactOpts, rateLimitAdmin) +} + func (_USDCTokenPool *USDCTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) } @@ -3029,6 +3063,8 @@ type USDCTokenPoolInterface interface { GetDomain(opts *bind.CallOpts, chainSelector uint64) (USDCTokenPoolDomain, error) + GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3071,6 +3107,8 @@ type USDCTokenPoolInterface interface { SetDomains(opts *bind.TransactOpts, domains []USDCTokenPoolDomainUpdate) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) 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 663eacb5ddb..2ddd0279913 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,37 +1,32 @@ GETH_VERSION: 1.13.8 -arm_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 1a0abacf84def916519013f713b667f106434a091af8b9f441e12cc90aa2cdf8 -arm_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 -burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin d0708a0ae657eb7df01a5177ff4d5850c5823c821f5f6bbd0a468b3982330b13 -burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin fcb85edfc871504a5146db2e3951193c2de089fe491dd7a2fbc755fd92725cac -burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 17bcd03828f43f50028bc4d66fdfb0cf576aaf28895d8f86c6ff598159a0cd64 -burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6f40135e1488097eafa843839a719fe9a3c21354565b64eb377a24a0a55782ef -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin c06c1cf1d004a803585a2c9d7a71ee5997b5fca86c2e111335cb8b930d9e3b5a -commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin ddc26c10c2a52b59624faae9005827b09b98db4566887a736005e8cc37cf8a51 -commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 +burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 1e60c28ad796a220a38043b369dec8d9bffe23e1c7d9895760e30672872afd06 +burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 3e8e3358f0bb520af069a7d37ea625940a88461a54418b1d5925eabced8c74df +burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 734c2a0ea8f1224b5f01ed849410209e74b4e3427e8bfddb8ff5dd8ead5f2d8d +ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin a074f2ecf2749a1d5afc4cd9bfa48677f09c2be4e076776f87c6feb767432ecb +ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin 8c603a0de19c4649d69bdd18774ee3b5edfd24c696aabdb7cdb982bd8e304829 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 5db06eb7fad07ec0d1ae5ac8d39f61398687fe3cda8290716ce0cd8fb9dca1ab ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 25a7bf3aa46252844c7afabc15db1051e7b6a717e296fc4c6e2f2f93d16033c5 -evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 9478aedc9f0072fbdafb54a6f82248de1efbcd7bdff18a90d8556b9aaff67455 -evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin a8c23c9280a713544eae0a0b8841a9caf97e616338d31ebc62501d8b4ab0eed6 -evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 116d5cb8447a1af61664a8d1db2d76086c042a3228337bc5cd49b9abd3e815f7 -lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 95a93517b01f51c35d82711a0015995f4804820ed67f6b46b785c4c94815df93 -lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin 05e308151b5adc9ba8d33385b8f82d55aad638652fe50e3ea8b09b1d0bbfd367 +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 3eb799751e92bb09cf94c8ad9245c620026c3a8a0a0fffee8c3921f8fcd37eb8 +lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 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 1d5146d43e1b99cd2d6f9f06475be19087e4349f7cee0fdbbf134ba65e967c93 -mock_arm_contract: ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.abi ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.bin e7a3a6c3eda5fb882e16bcc2b4340f78523acb67907bcdcaf3c8ffc51488688e -mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin e0cf17a38b438239fc6294ddca88f86b6c39e4542aefd9815b2d92987191b8bd -mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin 33bdad70822e889de7c720ed20085cf9cd3f8eba8b68f26bd6535197749595fe +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 abb0ecb1ed8621f26e43b39f5fa25f3d0b6d6c184fa37c404c4389605ecb74e7 -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin aa299e0c2659d53aad4eace4d66be0e734b1366008593669cf30361ff529da6a -nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 78b58f4f192db7496e2b6de805d6a2c918b98d4fa62f3c7ed145ef3b5657a40d -ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 1588313bb5e781d181a825247d30828f59007700f36b4b9b00391592b06ff4b4 -price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 09cdd37920d6f605c8a264f805bdba183813517169b2b5df4547e995d9ce73f7 -registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 7b2a47349d3fdb8d8b4e206d68577219deca7fabd1e893686fa8f118ad980d2d -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin c07af8433bf8dbc7981725b18922a9c4e2dea068dd204bc62adc0e926cb499c3 -router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 42576577e81beea9a069bd9229caaa9a71227fbaef3871a1a2e69fd218216290 -self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 86e169636e5633854ed0b709c804066b615040bceba25aa5137450fbe6f76fa3 -token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin fb06d2cf5f7476e512c6fb7aab8eab43545efd7f0f6ca133c64ff4e3963902c4 -token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 47a83e91b28ad1381a2a5882e2adfe168809a63a8f533ab1631f174550c64bed -usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin a54136ed9bffc74fff830c5066dbfcee6db1f31d636795317267d6baf1e0427a +multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 0b541232e49727e947dc164eadf35963c66e67576f21baa0ecaa06a8833148ed +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 04b6b261dd71925670bf4d904aaf7bf08543452009feefb88e07d4c49d12e969 +nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin eb234dfb57c6dc64f83cfbf9d78a27939a7241fd0de41342d41c919c156a3633 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 9964a45e079950719c13a9485bf4d479e2a87a5f395c4fef645a8520b0ac42e6 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 4766632d0938b33bfa04f30a5e6b301a944b6920dc1101ce8230e6b23706e898 +ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b +registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 695b4798f1e9d6f1442f7e6d7c499d23464d9237f325effde132913c404607f7 +rmn_home: ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.bin fc2ba87d987b4e4d6e0c63b3ffb6d515fae1ab27778f6a0a6ed927d8d6aeaf8f +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 8d7f0e4581acac5c6b42c7cca1c06e699fdcf9dbca782dde153b7d190cdbe9bc +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 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb +token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 7c01fd89f5153baa4d7409d14beabb3f861abfbf8880d3c6d06802cc398570f9 +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 8e7eae4c7277ce4a0092cca815c046cc49094028c23d2d113de9335fa4358030 weth9: ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin 2970d79a0ca6dd6279cde130de45e56c8790ed695eae477fb5ba4c1bb75b720d diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index 870ac2dd579..9d6fa7c4645 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -2,47 +2,43 @@ // golang packages, using abigen. package ccip -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin CommitStore commit_store -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin CommitStoreHelper commit_store_helper +//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 + +// 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/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin BurnMintTokenPoolAndProxy burn_mint_token_pool_and_proxy -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin LockReleaseTokenPoolAndProxy lock_release_token_pool_and_proxy //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/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin ARMContract arm_contract -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin ARMProxyContract arm_proxy_contract -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.abi ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.bin MockARMContract mock_arm_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/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/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin 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/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin EVM2EVMOnRamp evm_2_evm_onramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin EVM2EVMMultiOnRamp evm_2_evm_multi_onramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin EVM2EVMOffRamp evm_2_evm_offramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin EVM2EVMMultiOffRamp evm_2_evm_multi_offramp -//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/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin PriceRegistry price_registry -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin CCIPConfig ccip_config -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin IOCR3ConfigEncoder ocr3_config_encoder -//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/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/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin SelfFundedPingPong self_funded_ping_pong //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 -// Customer contracts -//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 +// 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: 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 6da66583e6e..29afadefd99 100644 --- a/core/gethwrappers/ccip/mocks/evm2_evm_off_ramp_interface.go +++ b/core/gethwrappers/ccip/mocks/evm2_evm_off_ramp_interface.go @@ -3,8 +3,6 @@ package mock_contracts import ( - big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" common "github.com/ethereum/go-ethereum/common" @@ -240,9 +238,9 @@ func (_c *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call) RunAndReturn(run return _c } -// ExecuteSingleMessage provides a mock function with given fields: opts, message, offchainTokenData -func (_m *EVM2EVMOffRampInterface) ExecuteSingleMessage(opts *bind.TransactOpts, message evm_2_evm_offramp.InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - ret := _m.Called(opts, message, offchainTokenData) +// ExecuteSingleMessage provides a mock function with given fields: opts, message, offchainTokenData, tokenGasOverrides +func (_m *EVM2EVMOffRampInterface) ExecuteSingleMessage(opts *bind.TransactOpts, message evm_2_evm_offramp.InternalEVM2EVMMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + ret := _m.Called(opts, message, offchainTokenData, tokenGasOverrides) if len(ret) == 0 { panic("no return value specified for ExecuteSingleMessage") @@ -250,19 +248,19 @@ func (_m *EVM2EVMOffRampInterface) ExecuteSingleMessage(opts *bind.TransactOpts, var r0 *types.Transaction var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte) (*types.Transaction, error)); ok { - return rf(opts, message, offchainTokenData) + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte, []uint32) (*types.Transaction, error)); ok { + return rf(opts, message, offchainTokenData, tokenGasOverrides) } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte) *types.Transaction); ok { - r0 = rf(opts, message, offchainTokenData) + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte, []uint32) *types.Transaction); ok { + r0 = rf(opts, message, offchainTokenData, tokenGasOverrides) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*types.Transaction) } } - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte) error); ok { - r1 = rf(opts, message, offchainTokenData) + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte, []uint32) error); ok { + r1 = rf(opts, message, offchainTokenData, tokenGasOverrides) } else { r1 = ret.Error(1) } @@ -279,13 +277,14 @@ type EVM2EVMOffRampInterface_ExecuteSingleMessage_Call struct { // - opts *bind.TransactOpts // - message evm_2_evm_offramp.InternalEVM2EVMMessage // - offchainTokenData [][]byte -func (_e *EVM2EVMOffRampInterface_Expecter) ExecuteSingleMessage(opts interface{}, message interface{}, offchainTokenData interface{}) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { - return &EVM2EVMOffRampInterface_ExecuteSingleMessage_Call{Call: _e.mock.On("ExecuteSingleMessage", opts, message, offchainTokenData)} +// - tokenGasOverrides []uint32 +func (_e *EVM2EVMOffRampInterface_Expecter) ExecuteSingleMessage(opts interface{}, message interface{}, offchainTokenData interface{}, tokenGasOverrides interface{}) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { + return &EVM2EVMOffRampInterface_ExecuteSingleMessage_Call{Call: _e.mock.On("ExecuteSingleMessage", opts, message, offchainTokenData, tokenGasOverrides)} } -func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) Run(run func(opts *bind.TransactOpts, message evm_2_evm_offramp.InternalEVM2EVMMessage, offchainTokenData [][]byte)) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { +func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) Run(run func(opts *bind.TransactOpts, message evm_2_evm_offramp.InternalEVM2EVMMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32)) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp.InternalEVM2EVMMessage), args[2].([][]byte)) + run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp.InternalEVM2EVMMessage), args[2].([][]byte), args[3].([]uint32)) }) return _c } @@ -295,7 +294,7 @@ func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) Return(_a0 *types.T return _c } -func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { +func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp.InternalEVM2EVMMessage, [][]byte, []uint32) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { _c.Call.Return(run) return _c } @@ -358,6 +357,64 @@ func (_c *EVM2EVMOffRampInterface_FilterAdminSet_Call) RunAndReturn(run func(*bi return _c } +// FilterAlreadyAttempted provides a mock function with given fields: opts +func (_m *EVM2EVMOffRampInterface) FilterAlreadyAttempted(opts *bind.FilterOpts) (*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FilterAlreadyAttempted") + } + + var r0 *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAlreadyAttempted' +type EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call struct { + *mock.Call +} + +// FilterAlreadyAttempted is a helper method to define mock.On call +// - opts *bind.FilterOpts +func (_e *EVM2EVMOffRampInterface_Expecter) FilterAlreadyAttempted(opts interface{}) *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call { + return &EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call{Call: _e.mock.On("FilterAlreadyAttempted", opts)} +} + +func (_c *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts)) + }) + return _c +} + +func (_c *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call) Return(_a0 *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator, _a1 error) *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttemptedIterator, error)) *EVM2EVMOffRampInterface_FilterAlreadyAttempted_Call { + _c.Call.Return(run) + return _c +} + // FilterConfigChanged provides a mock function with given fields: opts func (_m *EVM2EVMOffRampInterface) FilterConfigChanged(opts *bind.FilterOpts) (*evm_2_evm_offramp.EVM2EVMOffRampConfigChangedIterator, error) { ret := _m.Called(opts) @@ -1634,7 +1691,7 @@ func (_c *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call) RunAndReturn( } // ManuallyExecute provides a mock function with given fields: opts, report, gasLimitOverrides -func (_m *EVM2EVMOffRampInterface) ManuallyExecute(opts *bind.TransactOpts, report evm_2_evm_offramp.InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { +func (_m *EVM2EVMOffRampInterface) ManuallyExecute(opts *bind.TransactOpts, report evm_2_evm_offramp.InternalExecutionReport, gasLimitOverrides []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error) { ret := _m.Called(opts, report, gasLimitOverrides) if len(ret) == 0 { @@ -1643,10 +1700,10 @@ func (_m *EVM2EVMOffRampInterface) ManuallyExecute(opts *bind.TransactOpts, repo var r0 *types.Transaction var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []*big.Int) (*types.Transaction, error)); ok { + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error)); ok { return rf(opts, report, gasLimitOverrides) } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []*big.Int) *types.Transaction); ok { + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride) *types.Transaction); ok { r0 = rf(opts, report, gasLimitOverrides) } else { if ret.Get(0) != nil { @@ -1654,7 +1711,7 @@ func (_m *EVM2EVMOffRampInterface) ManuallyExecute(opts *bind.TransactOpts, repo } } - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []*big.Int) error); ok { + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride) error); ok { r1 = rf(opts, report, gasLimitOverrides) } else { r1 = ret.Error(1) @@ -1671,14 +1728,14 @@ type EVM2EVMOffRampInterface_ManuallyExecute_Call struct { // ManuallyExecute is a helper method to define mock.On call // - opts *bind.TransactOpts // - report evm_2_evm_offramp.InternalExecutionReport -// - gasLimitOverrides []*big.Int +// - gasLimitOverrides []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride func (_e *EVM2EVMOffRampInterface_Expecter) ManuallyExecute(opts interface{}, report interface{}, gasLimitOverrides interface{}) *EVM2EVMOffRampInterface_ManuallyExecute_Call { return &EVM2EVMOffRampInterface_ManuallyExecute_Call{Call: _e.mock.On("ManuallyExecute", opts, report, gasLimitOverrides)} } -func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) Run(run func(opts *bind.TransactOpts, report evm_2_evm_offramp.InternalExecutionReport, gasLimitOverrides []*big.Int)) *EVM2EVMOffRampInterface_ManuallyExecute_Call { +func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) Run(run func(opts *bind.TransactOpts, report evm_2_evm_offramp.InternalExecutionReport, gasLimitOverrides []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride)) *EVM2EVMOffRampInterface_ManuallyExecute_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp.InternalExecutionReport), args[2].([]*big.Int)) + run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp.InternalExecutionReport), args[2].([]evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride)) }) return _c } @@ -1688,7 +1745,7 @@ func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) Return(_a0 *types.Transa return _c } -func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []*big.Int) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ManuallyExecute_Call { +func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp.InternalExecutionReport, []evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ManuallyExecute_Call { _c.Call.Return(run) return _c } @@ -1809,6 +1866,64 @@ func (_c *EVM2EVMOffRampInterface_ParseAdminSet_Call) RunAndReturn(run func(type return _c } +// ParseAlreadyAttempted provides a mock function with given fields: log +func (_m *EVM2EVMOffRampInterface) ParseAlreadyAttempted(log types.Log) (*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseAlreadyAttempted") + } + + var r0 *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAlreadyAttempted' +type EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call struct { + *mock.Call +} + +// ParseAlreadyAttempted is a helper method to define mock.On call +// - log types.Log +func (_e *EVM2EVMOffRampInterface_Expecter) ParseAlreadyAttempted(log interface{}) *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call { + return &EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call{Call: _e.mock.On("ParseAlreadyAttempted", log)} +} + +func (_c *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call) Return(_a0 *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted, _a1 error) *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted, error)) *EVM2EVMOffRampInterface_ParseAlreadyAttempted_Call { + _c.Call.Return(run) + return _c +} + // ParseConfigChanged provides a mock function with given fields: log func (_m *EVM2EVMOffRampInterface) ParseConfigChanged(log types.Log) (*evm_2_evm_offramp.EVM2EVMOffRampConfigChanged, error) { ret := _m.Called(log) @@ -3100,6 +3215,65 @@ func (_c *EVM2EVMOffRampInterface_WatchAdminSet_Call) RunAndReturn(run func(*bin return _c } +// WatchAlreadyAttempted provides a mock function with given fields: opts, sink +func (_m *EVM2EVMOffRampInterface) WatchAlreadyAttempted(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted) (event.Subscription, error) { + ret := _m.Called(opts, sink) + + if len(ret) == 0 { + panic("no return value specified for WatchAlreadyAttempted") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted) (event.Subscription, error)); ok { + return rf(opts, sink) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted) event.Subscription); ok { + r0 = rf(opts, sink) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted) error); ok { + r1 = rf(opts, sink) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAlreadyAttempted' +type EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call struct { + *mock.Call +} + +// WatchAlreadyAttempted is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted +func (_e *EVM2EVMOffRampInterface_Expecter) WatchAlreadyAttempted(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call { + return &EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call{Call: _e.mock.On("WatchAlreadyAttempted", opts, sink)} +} + +func (_c *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted)) *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted)) + }) + return _c +} + +func (_c *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp.EVM2EVMOffRampAlreadyAttempted) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchAlreadyAttempted_Call { + _c.Call.Return(run) + return _c +} + // WatchConfigChanged provides a mock function with given fields: opts, sink func (_m *EVM2EVMOffRampInterface) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp.EVM2EVMOffRampConfigChanged) (event.Subscription, error) { ret := _m.Called(opts, sink) diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go new file mode 100644 index 00000000000..184bfeda77e --- /dev/null +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -0,0 +1,4566 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mock_contracts + +import ( + big "math/big" + + bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + common "github.com/ethereum/go-ethereum/common" + + event "github.com/ethereum/go-ethereum/event" + + fee_quoter "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + + generated "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" + + mock "github.com/stretchr/testify/mock" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// FeeQuoterInterface is an autogenerated mock type for the FeeQuoterInterface type +type FeeQuoterInterface struct { + mock.Mock +} + +type FeeQuoterInterface_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeQuoterInterface) EXPECT() *FeeQuoterInterface_Expecter { + return &FeeQuoterInterface_Expecter{mock: &_m.Mock} +} + +// AcceptOwnership provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for AcceptOwnership") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts) (*types.Transaction, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts) *types.Transaction); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_AcceptOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AcceptOwnership' +type FeeQuoterInterface_AcceptOwnership_Call struct { + *mock.Call +} + +// AcceptOwnership is a helper method to define mock.On call +// - opts *bind.TransactOpts +func (_e *FeeQuoterInterface_Expecter) AcceptOwnership(opts interface{}) *FeeQuoterInterface_AcceptOwnership_Call { + return &FeeQuoterInterface_AcceptOwnership_Call{Call: _e.mock.On("AcceptOwnership", opts)} +} + +func (_c *FeeQuoterInterface_AcceptOwnership_Call) Run(run func(opts *bind.TransactOpts)) *FeeQuoterInterface_AcceptOwnership_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_AcceptOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_AcceptOwnership_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind.TransactOpts) (*types.Transaction, error)) *FeeQuoterInterface_AcceptOwnership_Call { + _c.Call.Return(run) + return _c +} + +// Address provides a mock function with given fields: +func (_m *FeeQuoterInterface) Address() common.Address { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Address") + } + + var r0 common.Address + if rf, ok := ret.Get(0).(func() common.Address); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Address) + } + } + + return r0 +} + +// FeeQuoterInterface_Address_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Address' +type FeeQuoterInterface_Address_Call struct { + *mock.Call +} + +// Address is a helper method to define mock.On call +func (_e *FeeQuoterInterface_Expecter) Address() *FeeQuoterInterface_Address_Call { + return &FeeQuoterInterface_Address_Call{Call: _e.mock.On("Address")} +} + +func (_c *FeeQuoterInterface_Address_Call) Run(run func()) *FeeQuoterInterface_Address_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *FeeQuoterInterface_Address_Call) Return(_a0 common.Address) *FeeQuoterInterface_Address_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *FeeQuoterInterface_Address_Call) RunAndReturn(run func() common.Address) *FeeQuoterInterface_Address_Call { + _c.Call.Return(run) + return _c +} + +// ApplyAuthorizedCallerUpdates provides a mock function with given fields: opts, authorizedCallerArgs +func (_m *FeeQuoterInterface) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs fee_quoter.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + ret := _m.Called(opts, authorizedCallerArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyAuthorizedCallerUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)); ok { + return rf(opts, authorizedCallerArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) *types.Transaction); ok { + r0 = rf(opts, authorizedCallerArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) error); ok { + r1 = rf(opts, authorizedCallerArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyAuthorizedCallerUpdates' +type FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call struct { + *mock.Call +} + +// ApplyAuthorizedCallerUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - authorizedCallerArgs fee_quoter.AuthorizedCallersAuthorizedCallerArgs +func (_e *FeeQuoterInterface_Expecter) ApplyAuthorizedCallerUpdates(opts interface{}, authorizedCallerArgs interface{}) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + return &FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call{Call: _e.mock.On("ApplyAuthorizedCallerUpdates", opts, authorizedCallerArgs)} +} + +func (_c *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call) Run(run func(opts *bind.TransactOpts, authorizedCallerArgs fee_quoter.AuthorizedCallersAuthorizedCallerArgs)) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].(fee_quoter.AuthorizedCallersAuthorizedCallerArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyDestChainConfigUpdates provides a mock function with given fields: opts, destChainConfigArgs +func (_m *FeeQuoterInterface) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + ret := _m.Called(opts, destChainConfigArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyDestChainConfigUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) (*types.Transaction, error)); ok { + return rf(opts, destChainConfigArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) *types.Transaction); ok { + r0 = rf(opts, destChainConfigArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) error); ok { + r1 = rf(opts, destChainConfigArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyDestChainConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyDestChainConfigUpdates' +type FeeQuoterInterface_ApplyDestChainConfigUpdates_Call struct { + *mock.Call +} + +// ApplyDestChainConfigUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - destChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs +func (_e *FeeQuoterInterface_Expecter) ApplyDestChainConfigUpdates(opts interface{}, destChainConfigArgs interface{}) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + return &FeeQuoterInterface_ApplyDestChainConfigUpdates_Call{Call: _e.mock.On("ApplyDestChainConfigUpdates", opts, destChainConfigArgs)} +} + +func (_c *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, destChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs)) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterDestChainConfigArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyFeeTokensUpdates provides a mock function with given fields: opts, feeTokensToRemove, feeTokensToAdd +func (_m *FeeQuoterInterface) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToRemove []common.Address, feeTokensToAdd []common.Address) (*types.Transaction, error) { + ret := _m.Called(opts, feeTokensToRemove, feeTokensToAdd) + + if len(ret) == 0 { + panic("no return value specified for ApplyFeeTokensUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)); ok { + return rf(opts, feeTokensToRemove, feeTokensToAdd) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) *types.Transaction); ok { + r0 = rf(opts, feeTokensToRemove, feeTokensToAdd) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []common.Address, []common.Address) error); ok { + r1 = rf(opts, feeTokensToRemove, feeTokensToAdd) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyFeeTokensUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyFeeTokensUpdates' +type FeeQuoterInterface_ApplyFeeTokensUpdates_Call struct { + *mock.Call +} + +// ApplyFeeTokensUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - feeTokensToRemove []common.Address +// - feeTokensToAdd []common.Address +func (_e *FeeQuoterInterface_Expecter) ApplyFeeTokensUpdates(opts interface{}, feeTokensToRemove interface{}, feeTokensToAdd interface{}) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + return &FeeQuoterInterface_ApplyFeeTokensUpdates_Call{Call: _e.mock.On("ApplyFeeTokensUpdates", opts, feeTokensToRemove, feeTokensToAdd)} +} + +func (_c *FeeQuoterInterface_ApplyFeeTokensUpdates_Call) Run(run func(opts *bind.TransactOpts, feeTokensToRemove []common.Address, feeTokensToAdd []common.Address)) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]common.Address), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyFeeTokensUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyFeeTokensUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyPremiumMultiplierWeiPerEthUpdates provides a mock function with given fields: opts, premiumMultiplierWeiPerEthArgs +func (_m *FeeQuoterInterface) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + ret := _m.Called(opts, premiumMultiplierWeiPerEthArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyPremiumMultiplierWeiPerEthUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)); ok { + return rf(opts, premiumMultiplierWeiPerEthArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) *types.Transaction); ok { + r0 = rf(opts, premiumMultiplierWeiPerEthArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) error); ok { + r1 = rf(opts, premiumMultiplierWeiPerEthArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyPremiumMultiplierWeiPerEthUpdates' +type FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call struct { + *mock.Call +} + +// ApplyPremiumMultiplierWeiPerEthUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - premiumMultiplierWeiPerEthArgs []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs +func (_e *FeeQuoterInterface_Expecter) ApplyPremiumMultiplierWeiPerEthUpdates(opts interface{}, premiumMultiplierWeiPerEthArgs interface{}) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + return &FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call{Call: _e.mock.On("ApplyPremiumMultiplierWeiPerEthUpdates", opts, premiumMultiplierWeiPerEthArgs)} +} + +func (_c *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Run(run func(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs)) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyTokenTransferFeeConfigUpdates provides a mock function with given fields: opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs +func (_m *FeeQuoterInterface) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + ret := _m.Called(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + + if len(ret) == 0 { + panic("no return value specified for ApplyTokenTransferFeeConfigUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)); ok { + return rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) *types.Transaction); ok { + r0 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) error); ok { + r1 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyTokenTransferFeeConfigUpdates' +type FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call struct { + *mock.Call +} + +// ApplyTokenTransferFeeConfigUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs +// - tokensToUseDefaultFeeConfigs []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs +func (_e *FeeQuoterInterface_Expecter) ApplyTokenTransferFeeConfigUpdates(opts interface{}, tokenTransferFeeConfigArgs interface{}, tokensToUseDefaultFeeConfigs interface{}) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + return &FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call{Call: _e.mock.On("ApplyTokenTransferFeeConfigUpdates", opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs)} +} + +func (_c *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs)) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterTokenTransferFeeConfigArgs), args[2].([]fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ConvertTokenAmount provides a mock function with given fields: opts, fromToken, fromTokenAmount, toToken +func (_m *FeeQuoterInterface) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + ret := _m.Called(opts, fromToken, fromTokenAmount, toToken) + + if len(ret) == 0 { + panic("no return value specified for ConvertTokenAmount") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)); ok { + return rf(opts, fromToken, fromTokenAmount, toToken) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) *big.Int); ok { + r0 = rf(opts, fromToken, fromTokenAmount, toToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) error); ok { + r1 = rf(opts, fromToken, fromTokenAmount, toToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ConvertTokenAmount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConvertTokenAmount' +type FeeQuoterInterface_ConvertTokenAmount_Call struct { + *mock.Call +} + +// ConvertTokenAmount is a helper method to define mock.On call +// - opts *bind.CallOpts +// - fromToken common.Address +// - fromTokenAmount *big.Int +// - toToken common.Address +func (_e *FeeQuoterInterface_Expecter) ConvertTokenAmount(opts interface{}, fromToken interface{}, fromTokenAmount interface{}, toToken interface{}) *FeeQuoterInterface_ConvertTokenAmount_Call { + return &FeeQuoterInterface_ConvertTokenAmount_Call{Call: _e.mock.On("ConvertTokenAmount", opts, fromToken, fromTokenAmount, toToken)} +} + +func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) Run(run func(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address)) *FeeQuoterInterface_ConvertTokenAmount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(*big.Int), args[3].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_ConvertTokenAmount_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)) *FeeQuoterInterface_ConvertTokenAmount_Call { + _c.Call.Return(run) + return _c +} + +// FEEBASEDECIMALS provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) FEEBASEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FEEBASEDECIMALS") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (*big.Int, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) *big.Int); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FEEBASEDECIMALS_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FEEBASEDECIMALS' +type FeeQuoterInterface_FEEBASEDECIMALS_Call struct { + *mock.Call +} + +// FEEBASEDECIMALS is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) FEEBASEDECIMALS(opts interface{}) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + return &FeeQuoterInterface_FEEBASEDECIMALS_Call{Call: _e.mock.On("FEEBASEDECIMALS", opts)} +} + +func (_c *FeeQuoterInterface_FEEBASEDECIMALS_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FEEBASEDECIMALS_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FEEBASEDECIMALS_Call) RunAndReturn(run func(*bind.CallOpts) (*big.Int, error)) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + _c.Call.Return(run) + return _c +} + +// FilterAuthorizedCallerAdded provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FilterAuthorizedCallerAdded") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *fee_quoter.FeeQuoterAuthorizedCallerAddedIterator); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerAdded' +type FeeQuoterInterface_FilterAuthorizedCallerAdded_Call struct { + *mock.Call +} + +// FilterAuthorizedCallerAdded is a helper method to define mock.On call +// - opts *bind.FilterOpts +func (_e *FeeQuoterInterface_Expecter) FilterAuthorizedCallerAdded(opts interface{}) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + return &FeeQuoterInterface_FilterAuthorizedCallerAdded_Call{Call: _e.mock.On("FilterAuthorizedCallerAdded", opts)} +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call) Run(run func(opts *bind.FilterOpts)) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, _a1 error) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error)) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + _c.Call.Return(run) + return _c +} + +// FilterAuthorizedCallerRemoved provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FilterAuthorizedCallerRemoved") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerRemoved' +type FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call struct { + *mock.Call +} + +// FilterAuthorizedCallerRemoved is a helper method to define mock.On call +// - opts *bind.FilterOpts +func (_e *FeeQuoterInterface_Expecter) FilterAuthorizedCallerRemoved(opts interface{}) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + return &FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call{Call: _e.mock.On("FilterAuthorizedCallerRemoved", opts)} +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call) Run(run func(opts *bind.FilterOpts)) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, _a1 error) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, error)) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + _c.Call.Return(run) + return _c +} + +// FilterDestChainAdded provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*fee_quoter.FeeQuoterDestChainAddedIterator, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for FilterDestChainAdded") + } + + var r0 *fee_quoter.FeeQuoterDestChainAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainAddedIterator, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *fee_quoter.FeeQuoterDestChainAddedIterator); ok { + r0 = rf(opts, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainAdded' +type FeeQuoterInterface_FilterDestChainAdded_Call struct { + *mock.Call +} + +// FilterDestChainAdded is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) FilterDestChainAdded(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_FilterDestChainAdded_Call { + return &FeeQuoterInterface_FilterDestChainAdded_Call{Call: _e.mock.On("FilterDestChainAdded", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_FilterDestChainAdded_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *FeeQuoterInterface_FilterDestChainAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainAdded_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainAddedIterator, _a1 error) *FeeQuoterInterface_FilterDestChainAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainAddedIterator, error)) *FeeQuoterInterface_FilterDestChainAdded_Call { + _c.Call.Return(run) + return _c +} + +// FilterDestChainConfigUpdated provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for FilterDestChainConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterDestChainConfigUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *fee_quoter.FeeQuoterDestChainConfigUpdatedIterator); ok { + r0 = rf(opts, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainConfigUpdated' +type FeeQuoterInterface_FilterDestChainConfigUpdated_Call struct { + *mock.Call +} + +// FilterDestChainConfigUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) FilterDestChainConfigUpdated(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + return &FeeQuoterInterface_FilterDestChainConfigUpdated_Call{Call: _e.mock.On("FilterDestChainConfigUpdated", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_FilterDestChainConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, error)) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterFeeTokenAdded provides a mock function with given fields: opts, feeToken +func (_m *FeeQuoterInterface) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*fee_quoter.FeeQuoterFeeTokenAddedIterator, error) { + ret := _m.Called(opts, feeToken) + + if len(ret) == 0 { + panic("no return value specified for FilterFeeTokenAdded") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenAddedIterator, error)); ok { + return rf(opts, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterFeeTokenAddedIterator); ok { + r0 = rf(opts, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenAdded' +type FeeQuoterInterface_FilterFeeTokenAdded_Call struct { + *mock.Call +} + +// FilterFeeTokenAdded is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterFeeTokenAdded(opts interface{}, feeToken interface{}) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + return &FeeQuoterInterface_FilterFeeTokenAdded_Call{Call: _e.mock.On("FilterFeeTokenAdded", opts, feeToken)} +} + +func (_c *FeeQuoterInterface_FilterFeeTokenAdded_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenAdded_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenAddedIterator, _a1 error) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenAddedIterator, error)) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + _c.Call.Return(run) + return _c +} + +// FilterFeeTokenRemoved provides a mock function with given fields: opts, feeToken +func (_m *FeeQuoterInterface) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*fee_quoter.FeeQuoterFeeTokenRemovedIterator, error) { + ret := _m.Called(opts, feeToken) + + if len(ret) == 0 { + panic("no return value specified for FilterFeeTokenRemoved") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenRemovedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenRemovedIterator, error)); ok { + return rf(opts, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterFeeTokenRemovedIterator); ok { + r0 = rf(opts, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenRemovedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenRemoved' +type FeeQuoterInterface_FilterFeeTokenRemoved_Call struct { + *mock.Call +} + +// FilterFeeTokenRemoved is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterFeeTokenRemoved(opts interface{}, feeToken interface{}) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + return &FeeQuoterInterface_FilterFeeTokenRemoved_Call{Call: _e.mock.On("FilterFeeTokenRemoved", opts, feeToken)} +} + +func (_c *FeeQuoterInterface_FilterFeeTokenRemoved_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenRemovedIterator, _a1 error) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenRemoved_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenRemovedIterator, error)) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + _c.Call.Return(run) + return _c +} + +// FilterOwnershipTransferRequested provides a mock function with given fields: opts, from, to +func (_m *FeeQuoterInterface) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, error) { + ret := _m.Called(opts, from, to) + + if len(ret) == 0 { + panic("no return value specified for FilterOwnershipTransferRequested") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferRequestedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, error)); ok { + return rf(opts, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *fee_quoter.FeeQuoterOwnershipTransferRequestedIterator); ok { + r0 = rf(opts, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { + r1 = rf(opts, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferRequested' +type FeeQuoterInterface_FilterOwnershipTransferRequested_Call struct { + *mock.Call +} + +// FilterOwnershipTransferRequested is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterOwnershipTransferRequested(opts interface{}, from interface{}, to interface{}) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + return &FeeQuoterInterface_FilterOwnershipTransferRequested_Call{Call: _e.mock.On("FilterOwnershipTransferRequested", opts, from, to)} +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferRequested_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferRequested_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, _a1 error) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, error)) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + _c.Call.Return(run) + return _c +} + +// FilterOwnershipTransferred provides a mock function with given fields: opts, from, to +func (_m *FeeQuoterInterface) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferredIterator, error) { + ret := _m.Called(opts, from, to) + + if len(ret) == 0 { + panic("no return value specified for FilterOwnershipTransferred") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferredIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferredIterator, error)); ok { + return rf(opts, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *fee_quoter.FeeQuoterOwnershipTransferredIterator); ok { + r0 = rf(opts, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferredIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { + r1 = rf(opts, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferred' +type FeeQuoterInterface_FilterOwnershipTransferred_Call struct { + *mock.Call +} + +// FilterOwnershipTransferred is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterOwnershipTransferred(opts interface{}, from interface{}, to interface{}) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + return &FeeQuoterInterface_FilterOwnershipTransferred_Call{Call: _e.mock.On("FilterOwnershipTransferred", opts, from, to)} +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferred_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferred_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferredIterator, _a1 error) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferred_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferredIterator, error)) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + _c.Call.Return(run) + return _c +} + +// FilterPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterPremiumMultiplierWeiPerEthUpdated") + } + + var r0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPremiumMultiplierWeiPerEthUpdated' +type FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call struct { + *mock.Call +} + +// FilterPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterPremiumMultiplierWeiPerEthUpdated(opts interface{}, token interface{}) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + return &FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("FilterPremiumMultiplierWeiPerEthUpdated", opts, token)} +} + +func (_c *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error)) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterPriceFeedPerTokenUpdated provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterPriceFeedPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPriceFeedPerTokenUpdated' +type FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call struct { + *mock.Call +} + +// FilterPriceFeedPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterPriceFeedPerTokenUpdated(opts interface{}, token interface{}) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + return &FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("FilterPriceFeedPerTokenUpdated", opts, token)} +} + +func (_c *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, error)) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterReportPermissionSet provides a mock function with given fields: opts, reportId +func (_m *FeeQuoterInterface) FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*fee_quoter.FeeQuoterReportPermissionSetIterator, error) { + ret := _m.Called(opts, reportId) + + if len(ret) == 0 { + panic("no return value specified for FilterReportPermissionSet") + } + + var r0 *fee_quoter.FeeQuoterReportPermissionSetIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, [][32]byte) (*fee_quoter.FeeQuoterReportPermissionSetIterator, error)); ok { + return rf(opts, reportId) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, [][32]byte) *fee_quoter.FeeQuoterReportPermissionSetIterator); ok { + r0 = rf(opts, reportId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterReportPermissionSetIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, [][32]byte) error); ok { + r1 = rf(opts, reportId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterReportPermissionSet' +type FeeQuoterInterface_FilterReportPermissionSet_Call struct { + *mock.Call +} + +// FilterReportPermissionSet is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - reportId [][32]byte +func (_e *FeeQuoterInterface_Expecter) FilterReportPermissionSet(opts interface{}, reportId interface{}) *FeeQuoterInterface_FilterReportPermissionSet_Call { + return &FeeQuoterInterface_FilterReportPermissionSet_Call{Call: _e.mock.On("FilterReportPermissionSet", opts, reportId)} +} + +func (_c *FeeQuoterInterface_FilterReportPermissionSet_Call) Run(run func(opts *bind.FilterOpts, reportId [][32]byte)) *FeeQuoterInterface_FilterReportPermissionSet_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([][32]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterReportPermissionSet_Call) Return(_a0 *fee_quoter.FeeQuoterReportPermissionSetIterator, _a1 error) *FeeQuoterInterface_FilterReportPermissionSet_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterReportPermissionSet_Call) RunAndReturn(run func(*bind.FilterOpts, [][32]byte) (*fee_quoter.FeeQuoterReportPermissionSetIterator, error)) *FeeQuoterInterface_FilterReportPermissionSet_Call { + _c.Call.Return(run) + return _c +} + +// FilterTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, destChainSelector, token +func (_m *FeeQuoterInterface) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for FilterTokenTransferFeeConfigDeleted") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator); ok { + r0 = rf(opts, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigDeleted' +type FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call struct { + *mock.Call +} + +// FilterTokenTransferFeeConfigDeleted is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterTokenTransferFeeConfigDeleted(opts interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + return &FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigDeleted", opts, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, _a1 error) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, error)) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(run) + return _c +} + +// FilterTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, destChainSelector, token +func (_m *FeeQuoterInterface) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for FilterTokenTransferFeeConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator); ok { + r0 = rf(opts, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigUpdated' +type FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call struct { + *mock.Call +} + +// FilterTokenTransferFeeConfigUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterTokenTransferFeeConfigUpdated(opts interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + return &FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigUpdated", opts, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, error)) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterUsdPerTokenUpdated provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterUsdPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerTokenUpdated' +type FeeQuoterInterface_FilterUsdPerTokenUpdated_Call struct { + *mock.Call +} + +// FilterUsdPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterUsdPerTokenUpdated(opts interface{}, token interface{}) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + return &FeeQuoterInterface_FilterUsdPerTokenUpdated_Call{Call: _e.mock.On("FilterUsdPerTokenUpdated", opts, token)} +} + +func (_c *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, error)) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterUsdPerUnitGasUpdated provides a mock function with given fields: opts, destChain +func (_m *FeeQuoterInterface) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, error) { + ret := _m.Called(opts, destChain) + + if len(ret) == 0 { + panic("no return value specified for FilterUsdPerUnitGasUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, error)); ok { + return rf(opts, destChain) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator); ok { + r0 = rf(opts, destChain) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChain) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerUnitGasUpdated' +type FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call struct { + *mock.Call +} + +// FilterUsdPerUnitGasUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChain []uint64 +func (_e *FeeQuoterInterface_Expecter) FilterUsdPerUnitGasUpdated(opts interface{}, destChain interface{}) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + return &FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call{Call: _e.mock.On("FilterUsdPerUnitGasUpdated", opts, destChain)} +} + +func (_c *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.FilterOpts, destChain []uint64)) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, error)) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + _c.Call.Return(run) + return _c +} + +// GetAllAuthorizedCallers provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for GetAllAuthorizedCallers") + } + + var r0 []common.Address + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Address) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetAllAuthorizedCallers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllAuthorizedCallers' +type FeeQuoterInterface_GetAllAuthorizedCallers_Call struct { + *mock.Call +} + +// GetAllAuthorizedCallers is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) GetAllAuthorizedCallers(opts interface{}) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + return &FeeQuoterInterface_GetAllAuthorizedCallers_Call{Call: _e.mock.On("GetAllAuthorizedCallers", opts)} +} + +func (_c *FeeQuoterInterface_GetAllAuthorizedCallers_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetAllAuthorizedCallers_Call) Return(_a0 []common.Address, _a1 error) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetAllAuthorizedCallers_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + _c.Call.Return(run) + return _c +} + +// GetDestChainConfig provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (fee_quoter.FeeQuoterDestChainConfig, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetDestChainConfig") + } + + var r0 fee_quoter.FeeQuoterDestChainConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (fee_quoter.FeeQuoterDestChainConfig, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) fee_quoter.FeeQuoterDestChainConfig); ok { + r0 = rf(opts, destChainSelector) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterDestChainConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetDestChainConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestChainConfig' +type FeeQuoterInterface_GetDestChainConfig_Call struct { + *mock.Call +} + +// GetDestChainConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +func (_e *FeeQuoterInterface_Expecter) GetDestChainConfig(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_GetDestChainConfig_Call { + return &FeeQuoterInterface_GetDestChainConfig_Call{Call: _e.mock.On("GetDestChainConfig", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_GetDestChainConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *FeeQuoterInterface_GetDestChainConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetDestChainConfig_Call) Return(_a0 fee_quoter.FeeQuoterDestChainConfig, _a1 error) *FeeQuoterInterface_GetDestChainConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetDestChainConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (fee_quoter.FeeQuoterDestChainConfig, error)) *FeeQuoterInterface_GetDestChainConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetDestinationChainGasPrice provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (fee_quoter.InternalTimestampedPackedUint224, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetDestinationChainGasPrice") + } + + var r0 fee_quoter.InternalTimestampedPackedUint224 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (fee_quoter.InternalTimestampedPackedUint224, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) fee_quoter.InternalTimestampedPackedUint224); ok { + r0 = rf(opts, destChainSelector) + } else { + r0 = ret.Get(0).(fee_quoter.InternalTimestampedPackedUint224) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetDestinationChainGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestinationChainGasPrice' +type FeeQuoterInterface_GetDestinationChainGasPrice_Call struct { + *mock.Call +} + +// GetDestinationChainGasPrice is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +func (_e *FeeQuoterInterface_Expecter) GetDestinationChainGasPrice(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + return &FeeQuoterInterface_GetDestinationChainGasPrice_Call{Call: _e.mock.On("GetDestinationChainGasPrice", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_GetDestinationChainGasPrice_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetDestinationChainGasPrice_Call) Return(_a0 fee_quoter.InternalTimestampedPackedUint224, _a1 error) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetDestinationChainGasPrice_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (fee_quoter.InternalTimestampedPackedUint224, error)) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + _c.Call.Return(run) + return _c +} + +// GetFeeTokens provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for GetFeeTokens") + } + + var r0 []common.Address + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Address) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetFeeTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeTokens' +type FeeQuoterInterface_GetFeeTokens_Call struct { + *mock.Call +} + +// GetFeeTokens is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) GetFeeTokens(opts interface{}) *FeeQuoterInterface_GetFeeTokens_Call { + return &FeeQuoterInterface_GetFeeTokens_Call{Call: _e.mock.On("GetFeeTokens", opts)} +} + +func (_c *FeeQuoterInterface_GetFeeTokens_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_GetFeeTokens_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetFeeTokens_Call) Return(_a0 []common.Address, _a1 error) *FeeQuoterInterface_GetFeeTokens_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetFeeTokens_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *FeeQuoterInterface_GetFeeTokens_Call { + _c.Call.Return(run) + return _c +} + +// GetPremiumMultiplierWeiPerEth provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetPremiumMultiplierWeiPerEth") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (uint64, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) uint64); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPremiumMultiplierWeiPerEth' +type FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call struct { + *mock.Call +} + +// GetPremiumMultiplierWeiPerEth is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetPremiumMultiplierWeiPerEth(opts interface{}, token interface{}) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + return &FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call{Call: _e.mock.On("GetPremiumMultiplierWeiPerEth", opts, token)} +} + +func (_c *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call) Return(_a0 uint64, _a1 error) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (uint64, error)) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + _c.Call.Return(run) + return _c +} + +// GetStaticConfig provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) GetStaticConfig(opts *bind.CallOpts) (fee_quoter.FeeQuoterStaticConfig, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for GetStaticConfig") + } + + var r0 fee_quoter.FeeQuoterStaticConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (fee_quoter.FeeQuoterStaticConfig, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) fee_quoter.FeeQuoterStaticConfig); ok { + r0 = rf(opts) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterStaticConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetStaticConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStaticConfig' +type FeeQuoterInterface_GetStaticConfig_Call struct { + *mock.Call +} + +// GetStaticConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) GetStaticConfig(opts interface{}) *FeeQuoterInterface_GetStaticConfig_Call { + return &FeeQuoterInterface_GetStaticConfig_Call{Call: _e.mock.On("GetStaticConfig", opts)} +} + +func (_c *FeeQuoterInterface_GetStaticConfig_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_GetStaticConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetStaticConfig_Call) Return(_a0 fee_quoter.FeeQuoterStaticConfig, _a1 error) *FeeQuoterInterface_GetStaticConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetStaticConfig_Call) RunAndReturn(run func(*bind.CallOpts) (fee_quoter.FeeQuoterStaticConfig, error)) *FeeQuoterInterface_GetStaticConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenAndGasPrices provides a mock function with given fields: opts, token, destChainSelector +func (_m *FeeQuoterInterface) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (fee_quoter.GetTokenAndGasPrices, error) { + ret := _m.Called(opts, token, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetTokenAndGasPrices") + } + + var r0 fee_quoter.GetTokenAndGasPrices + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) (fee_quoter.GetTokenAndGasPrices, error)); ok { + return rf(opts, token, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) fee_quoter.GetTokenAndGasPrices); ok { + r0 = rf(opts, token, destChainSelector) + } else { + r0 = ret.Get(0).(fee_quoter.GetTokenAndGasPrices) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, uint64) error); ok { + r1 = rf(opts, token, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenAndGasPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenAndGasPrices' +type FeeQuoterInterface_GetTokenAndGasPrices_Call struct { + *mock.Call +} + +// GetTokenAndGasPrices is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +// - destChainSelector uint64 +func (_e *FeeQuoterInterface_Expecter) GetTokenAndGasPrices(opts interface{}, token interface{}, destChainSelector interface{}) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + return &FeeQuoterInterface_GetTokenAndGasPrices_Call{Call: _e.mock.On("GetTokenAndGasPrices", opts, token, destChainSelector)} +} + +func (_c *FeeQuoterInterface_GetTokenAndGasPrices_Call) Run(run func(opts *bind.CallOpts, token common.Address, destChainSelector uint64)) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenAndGasPrices_Call) Return(_a0 fee_quoter.GetTokenAndGasPrices, _a1 error) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenAndGasPrices_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, uint64) (fee_quoter.GetTokenAndGasPrices, error)) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenPrice provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetTokenPrice(opts *bind.CallOpts, token common.Address) (fee_quoter.InternalTimestampedPackedUint224, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPrice") + } + + var r0 fee_quoter.InternalTimestampedPackedUint224 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (fee_quoter.InternalTimestampedPackedUint224, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) fee_quoter.InternalTimestampedPackedUint224); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(fee_quoter.InternalTimestampedPackedUint224) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrice' +type FeeQuoterInterface_GetTokenPrice_Call struct { + *mock.Call +} + +// GetTokenPrice is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenPrice(opts interface{}, token interface{}) *FeeQuoterInterface_GetTokenPrice_Call { + return &FeeQuoterInterface_GetTokenPrice_Call{Call: _e.mock.On("GetTokenPrice", opts, token)} +} + +func (_c *FeeQuoterInterface_GetTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetTokenPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrice_Call) Return(_a0 fee_quoter.InternalTimestampedPackedUint224, _a1 error) *FeeQuoterInterface_GetTokenPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (fee_quoter.InternalTimestampedPackedUint224, error)) *FeeQuoterInterface_GetTokenPrice_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenPriceFeedConfig provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (fee_quoter.FeeQuoterTokenPriceFeedConfig, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPriceFeedConfig") + } + + var r0 fee_quoter.FeeQuoterTokenPriceFeedConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (fee_quoter.FeeQuoterTokenPriceFeedConfig, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) fee_quoter.FeeQuoterTokenPriceFeedConfig); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterTokenPriceFeedConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenPriceFeedConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPriceFeedConfig' +type FeeQuoterInterface_GetTokenPriceFeedConfig_Call struct { + *mock.Call +} + +// GetTokenPriceFeedConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenPriceFeedConfig(opts interface{}, token interface{}) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + return &FeeQuoterInterface_GetTokenPriceFeedConfig_Call{Call: _e.mock.On("GetTokenPriceFeedConfig", opts, token)} +} + +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Return(_a0 fee_quoter.FeeQuoterTokenPriceFeedConfig, _a1 error) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (fee_quoter.FeeQuoterTokenPriceFeedConfig, error)) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenPrices provides a mock function with given fields: opts, tokens +func (_m *FeeQuoterInterface) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]fee_quoter.InternalTimestampedPackedUint224, error) { + ret := _m.Called(opts, tokens) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPrices") + } + + var r0 []fee_quoter.InternalTimestampedPackedUint224 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) ([]fee_quoter.InternalTimestampedPackedUint224, error)); ok { + return rf(opts, tokens) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) []fee_quoter.InternalTimestampedPackedUint224); ok { + r0 = rf(opts, tokens) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]fee_quoter.InternalTimestampedPackedUint224) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, []common.Address) error); ok { + r1 = rf(opts, tokens) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrices' +type FeeQuoterInterface_GetTokenPrices_Call struct { + *mock.Call +} + +// GetTokenPrices is a helper method to define mock.On call +// - opts *bind.CallOpts +// - tokens []common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenPrices(opts interface{}, tokens interface{}) *FeeQuoterInterface_GetTokenPrices_Call { + return &FeeQuoterInterface_GetTokenPrices_Call{Call: _e.mock.On("GetTokenPrices", opts, tokens)} +} + +func (_c *FeeQuoterInterface_GetTokenPrices_Call) Run(run func(opts *bind.CallOpts, tokens []common.Address)) *FeeQuoterInterface_GetTokenPrices_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrices_Call) Return(_a0 []fee_quoter.InternalTimestampedPackedUint224, _a1 error) *FeeQuoterInterface_GetTokenPrices_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrices_Call) RunAndReturn(run func(*bind.CallOpts, []common.Address) ([]fee_quoter.InternalTimestampedPackedUint224, error)) *FeeQuoterInterface_GetTokenPrices_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenTransferFeeConfig provides a mock function with given fields: opts, destChainSelector, token +func (_m *FeeQuoterInterface) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (fee_quoter.FeeQuoterTokenTransferFeeConfig, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenTransferFeeConfig") + } + + var r0 fee_quoter.FeeQuoterTokenTransferFeeConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) (fee_quoter.FeeQuoterTokenTransferFeeConfig, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) fee_quoter.FeeQuoterTokenTransferFeeConfig); ok { + r0 = rf(opts, destChainSelector, token) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterTokenTransferFeeConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenTransferFeeConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenTransferFeeConfig' +type FeeQuoterInterface_GetTokenTransferFeeConfig_Call struct { + *mock.Call +} + +// GetTokenTransferFeeConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenTransferFeeConfig(opts interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + return &FeeQuoterInterface_GetTokenTransferFeeConfig_Call{Call: _e.mock.On("GetTokenTransferFeeConfig", opts, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_GetTokenTransferFeeConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, token common.Address)) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenTransferFeeConfig_Call) Return(_a0 fee_quoter.FeeQuoterTokenTransferFeeConfig, _a1 error) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenTransferFeeConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address) (fee_quoter.FeeQuoterTokenTransferFeeConfig, error)) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetValidatedFee provides a mock function with given fields: opts, destChainSelector, message +func (_m *FeeQuoterInterface) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message fee_quoter.ClientEVM2AnyMessage) (*big.Int, error) { + ret := _m.Called(opts, destChainSelector, message) + + if len(ret) == 0 { + panic("no return value specified for GetValidatedFee") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) (*big.Int, error)); ok { + return rf(opts, destChainSelector, message) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) *big.Int); ok { + r0 = rf(opts, destChainSelector, message) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) error); ok { + r1 = rf(opts, destChainSelector, message) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetValidatedFee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedFee' +type FeeQuoterInterface_GetValidatedFee_Call struct { + *mock.Call +} + +// GetValidatedFee is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - message fee_quoter.ClientEVM2AnyMessage +func (_e *FeeQuoterInterface_Expecter) GetValidatedFee(opts interface{}, destChainSelector interface{}, message interface{}) *FeeQuoterInterface_GetValidatedFee_Call { + return &FeeQuoterInterface_GetValidatedFee_Call{Call: _e.mock.On("GetValidatedFee", opts, destChainSelector, message)} +} + +func (_c *FeeQuoterInterface_GetValidatedFee_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, message fee_quoter.ClientEVM2AnyMessage)) *FeeQuoterInterface_GetValidatedFee_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(fee_quoter.ClientEVM2AnyMessage)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedFee_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_GetValidatedFee_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedFee_Call) RunAndReturn(run func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) (*big.Int, error)) *FeeQuoterInterface_GetValidatedFee_Call { + _c.Call.Return(run) + return _c +} + +// GetValidatedTokenPrice provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetValidatedTokenPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (*big.Int, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) *big.Int); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetValidatedTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedTokenPrice' +type FeeQuoterInterface_GetValidatedTokenPrice_Call struct { + *mock.Call +} + +// GetValidatedTokenPrice is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetValidatedTokenPrice(opts interface{}, token interface{}) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + return &FeeQuoterInterface_GetValidatedTokenPrice_Call{Call: _e.mock.On("GetValidatedTokenPrice", opts, token)} +} + +func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (*big.Int, error)) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + _c.Call.Return(run) + return _c +} + +// KEYSTONEPRICEDECIMALS provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) KEYSTONEPRICEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for KEYSTONEPRICEDECIMALS") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (*big.Int, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) *big.Int); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'KEYSTONEPRICEDECIMALS' +type FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call struct { + *mock.Call +} + +// KEYSTONEPRICEDECIMALS is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) KEYSTONEPRICEDECIMALS(opts interface{}) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + return &FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call{Call: _e.mock.On("KEYSTONEPRICEDECIMALS", opts)} +} + +func (_c *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call) RunAndReturn(run func(*bind.CallOpts) (*big.Int, error)) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + _c.Call.Return(run) + return _c +} + +// OnReport provides a mock function with given fields: opts, metadata, report +func (_m *FeeQuoterInterface) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { + ret := _m.Called(opts, metadata, report) + + if len(ret) == 0 { + panic("no return value specified for OnReport") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []byte, []byte) (*types.Transaction, error)); ok { + return rf(opts, metadata, report) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []byte, []byte) *types.Transaction); ok { + r0 = rf(opts, metadata, report) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []byte, []byte) error); ok { + r1 = rf(opts, metadata, report) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_OnReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnReport' +type FeeQuoterInterface_OnReport_Call struct { + *mock.Call +} + +// OnReport is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - metadata []byte +// - report []byte +func (_e *FeeQuoterInterface_Expecter) OnReport(opts interface{}, metadata interface{}, report interface{}) *FeeQuoterInterface_OnReport_Call { + return &FeeQuoterInterface_OnReport_Call{Call: _e.mock.On("OnReport", opts, metadata, report)} +} + +func (_c *FeeQuoterInterface_OnReport_Call) Run(run func(opts *bind.TransactOpts, metadata []byte, report []byte)) *FeeQuoterInterface_OnReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]byte), args[2].([]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_OnReport_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_OnReport_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_OnReport_Call) RunAndReturn(run func(*bind.TransactOpts, []byte, []byte) (*types.Transaction, error)) *FeeQuoterInterface_OnReport_Call { + _c.Call.Return(run) + return _c +} + +// Owner provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) Owner(opts *bind.CallOpts) (common.Address, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for Owner") + } + + var r0 common.Address + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (common.Address, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) common.Address); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Address) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_Owner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Owner' +type FeeQuoterInterface_Owner_Call struct { + *mock.Call +} + +// Owner is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) Owner(opts interface{}) *FeeQuoterInterface_Owner_Call { + return &FeeQuoterInterface_Owner_Call{Call: _e.mock.On("Owner", opts)} +} + +func (_c *FeeQuoterInterface_Owner_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_Owner_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_Owner_Call) Return(_a0 common.Address, _a1 error) *FeeQuoterInterface_Owner_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_Owner_Call) RunAndReturn(run func(*bind.CallOpts) (common.Address, error)) *FeeQuoterInterface_Owner_Call { + _c.Call.Return(run) + return _c +} + +// ParseAuthorizedCallerAdded provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseAuthorizedCallerAdded(log types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseAuthorizedCallerAdded") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterAuthorizedCallerAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerAdded' +type FeeQuoterInterface_ParseAuthorizedCallerAdded_Call struct { + *mock.Call +} + +// ParseAuthorizedCallerAdded is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseAuthorizedCallerAdded(log interface{}) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + return &FeeQuoterInterface_ParseAuthorizedCallerAdded_Call{Call: _e.mock.On("ParseAuthorizedCallerAdded", log)} +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerAdded, _a1 error) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerAdded, error)) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + _c.Call.Return(run) + return _c +} + +// ParseAuthorizedCallerRemoved provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseAuthorizedCallerRemoved(log types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerRemoved, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseAuthorizedCallerRemoved") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerRemoved + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerRemoved, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterAuthorizedCallerRemoved); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerRemoved) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerRemoved' +type FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call struct { + *mock.Call +} + +// ParseAuthorizedCallerRemoved is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseAuthorizedCallerRemoved(log interface{}) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + return &FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call{Call: _e.mock.On("ParseAuthorizedCallerRemoved", log)} +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerRemoved, _a1 error) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerRemoved, error)) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + _c.Call.Return(run) + return _c +} + +// ParseDestChainAdded provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseDestChainAdded(log types.Log) (*fee_quoter.FeeQuoterDestChainAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseDestChainAdded") + } + + var r0 *fee_quoter.FeeQuoterDestChainAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterDestChainAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterDestChainAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainAdded' +type FeeQuoterInterface_ParseDestChainAdded_Call struct { + *mock.Call +} + +// ParseDestChainAdded is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseDestChainAdded(log interface{}) *FeeQuoterInterface_ParseDestChainAdded_Call { + return &FeeQuoterInterface_ParseDestChainAdded_Call{Call: _e.mock.On("ParseDestChainAdded", log)} +} + +func (_c *FeeQuoterInterface_ParseDestChainAdded_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseDestChainAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainAdded_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainAdded, _a1 error) *FeeQuoterInterface_ParseDestChainAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainAdded_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterDestChainAdded, error)) *FeeQuoterInterface_ParseDestChainAdded_Call { + _c.Call.Return(run) + return _c +} + +// ParseDestChainConfigUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseDestChainConfigUpdated(log types.Log) (*fee_quoter.FeeQuoterDestChainConfigUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseDestChainConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterDestChainConfigUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterDestChainConfigUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterDestChainConfigUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainConfigUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainConfigUpdated' +type FeeQuoterInterface_ParseDestChainConfigUpdated_Call struct { + *mock.Call +} + +// ParseDestChainConfigUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseDestChainConfigUpdated(log interface{}) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + return &FeeQuoterInterface_ParseDestChainConfigUpdated_Call{Call: _e.mock.On("ParseDestChainConfigUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseDestChainConfigUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainConfigUpdated, _a1 error) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainConfigUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterDestChainConfigUpdated, error)) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseFeeTokenAdded provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseFeeTokenAdded(log types.Log) (*fee_quoter.FeeQuoterFeeTokenAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseFeeTokenAdded") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterFeeTokenAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterFeeTokenAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenAdded' +type FeeQuoterInterface_ParseFeeTokenAdded_Call struct { + *mock.Call +} + +// ParseFeeTokenAdded is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseFeeTokenAdded(log interface{}) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + return &FeeQuoterInterface_ParseFeeTokenAdded_Call{Call: _e.mock.On("ParseFeeTokenAdded", log)} +} + +func (_c *FeeQuoterInterface_ParseFeeTokenAdded_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenAdded_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenAdded, _a1 error) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenAdded_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterFeeTokenAdded, error)) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + _c.Call.Return(run) + return _c +} + +// ParseFeeTokenRemoved provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseFeeTokenRemoved(log types.Log) (*fee_quoter.FeeQuoterFeeTokenRemoved, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseFeeTokenRemoved") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenRemoved + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterFeeTokenRemoved, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterFeeTokenRemoved); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenRemoved) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenRemoved' +type FeeQuoterInterface_ParseFeeTokenRemoved_Call struct { + *mock.Call +} + +// ParseFeeTokenRemoved is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseFeeTokenRemoved(log interface{}) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + return &FeeQuoterInterface_ParseFeeTokenRemoved_Call{Call: _e.mock.On("ParseFeeTokenRemoved", log)} +} + +func (_c *FeeQuoterInterface_ParseFeeTokenRemoved_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenRemoved, _a1 error) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenRemoved_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterFeeTokenRemoved, error)) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + _c.Call.Return(run) + return _c +} + +// ParseLog provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseLog(log types.Log) (generated.AbigenLog, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseLog") + } + + var r0 generated.AbigenLog + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (generated.AbigenLog, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) generated.AbigenLog); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(generated.AbigenLog) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseLog_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseLog' +type FeeQuoterInterface_ParseLog_Call struct { + *mock.Call +} + +// ParseLog is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseLog(log interface{}) *FeeQuoterInterface_ParseLog_Call { + return &FeeQuoterInterface_ParseLog_Call{Call: _e.mock.On("ParseLog", log)} +} + +func (_c *FeeQuoterInterface_ParseLog_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseLog_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseLog_Call) Return(_a0 generated.AbigenLog, _a1 error) *FeeQuoterInterface_ParseLog_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseLog_Call) RunAndReturn(run func(types.Log) (generated.AbigenLog, error)) *FeeQuoterInterface_ParseLog_Call { + _c.Call.Return(run) + return _c +} + +// ParseOwnershipTransferRequested provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseOwnershipTransferRequested(log types.Log) (*fee_quoter.FeeQuoterOwnershipTransferRequested, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseOwnershipTransferRequested") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferRequested + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferRequested, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterOwnershipTransferRequested); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferRequested) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferRequested' +type FeeQuoterInterface_ParseOwnershipTransferRequested_Call struct { + *mock.Call +} + +// ParseOwnershipTransferRequested is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseOwnershipTransferRequested(log interface{}) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + return &FeeQuoterInterface_ParseOwnershipTransferRequested_Call{Call: _e.mock.On("ParseOwnershipTransferRequested", log)} +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferRequested_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferRequested_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferRequested, _a1 error) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferRequested_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferRequested, error)) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + _c.Call.Return(run) + return _c +} + +// ParseOwnershipTransferred provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseOwnershipTransferred(log types.Log) (*fee_quoter.FeeQuoterOwnershipTransferred, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseOwnershipTransferred") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferred + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferred, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterOwnershipTransferred); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferred) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferred' +type FeeQuoterInterface_ParseOwnershipTransferred_Call struct { + *mock.Call +} + +// ParseOwnershipTransferred is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseOwnershipTransferred(log interface{}) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + return &FeeQuoterInterface_ParseOwnershipTransferred_Call{Call: _e.mock.On("ParseOwnershipTransferred", log)} +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferred_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferred_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferred, _a1 error) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferred_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferred, error)) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + _c.Call.Return(run) + return _c +} + +// ParsePremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParsePremiumMultiplierWeiPerEthUpdated") + } + + var r0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePremiumMultiplierWeiPerEthUpdated' +type FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call struct { + *mock.Call +} + +// ParsePremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParsePremiumMultiplierWeiPerEthUpdated(log interface{}) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + return &FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("ParsePremiumMultiplierWeiPerEthUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, _a1 error) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, error)) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParsePriceFeedPerTokenUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParsePriceFeedPerTokenUpdated(log types.Log) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParsePriceFeedPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePriceFeedPerTokenUpdated' +type FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call struct { + *mock.Call +} + +// ParsePriceFeedPerTokenUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParsePriceFeedPerTokenUpdated(log interface{}) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + return &FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call{Call: _e.mock.On("ParsePriceFeedPerTokenUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, _a1 error) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, error)) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseReportPermissionSet provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseReportPermissionSet(log types.Log) (*fee_quoter.FeeQuoterReportPermissionSet, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseReportPermissionSet") + } + + var r0 *fee_quoter.FeeQuoterReportPermissionSet + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterReportPermissionSet, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterReportPermissionSet); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterReportPermissionSet) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseReportPermissionSet' +type FeeQuoterInterface_ParseReportPermissionSet_Call struct { + *mock.Call +} + +// ParseReportPermissionSet is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseReportPermissionSet(log interface{}) *FeeQuoterInterface_ParseReportPermissionSet_Call { + return &FeeQuoterInterface_ParseReportPermissionSet_Call{Call: _e.mock.On("ParseReportPermissionSet", log)} +} + +func (_c *FeeQuoterInterface_ParseReportPermissionSet_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseReportPermissionSet_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseReportPermissionSet_Call) Return(_a0 *fee_quoter.FeeQuoterReportPermissionSet, _a1 error) *FeeQuoterInterface_ParseReportPermissionSet_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseReportPermissionSet_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterReportPermissionSet, error)) *FeeQuoterInterface_ParseReportPermissionSet_Call { + _c.Call.Return(run) + return _c +} + +// ParseTokenTransferFeeConfigDeleted provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseTokenTransferFeeConfigDeleted(log types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseTokenTransferFeeConfigDeleted") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigDeleted' +type FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call struct { + *mock.Call +} + +// ParseTokenTransferFeeConfigDeleted is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseTokenTransferFeeConfigDeleted(log interface{}) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + return &FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigDeleted", log)} +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, _a1 error) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, error)) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(run) + return _c +} + +// ParseTokenTransferFeeConfigUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseTokenTransferFeeConfigUpdated(log types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseTokenTransferFeeConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigUpdated' +type FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call struct { + *mock.Call +} + +// ParseTokenTransferFeeConfigUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseTokenTransferFeeConfigUpdated(log interface{}) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + return &FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, _a1 error) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, error)) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseUsdPerTokenUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseUsdPerTokenUpdated(log types.Log) (*fee_quoter.FeeQuoterUsdPerTokenUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseUsdPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerTokenUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterUsdPerTokenUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterUsdPerTokenUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerTokenUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerTokenUpdated' +type FeeQuoterInterface_ParseUsdPerTokenUpdated_Call struct { + *mock.Call +} + +// ParseUsdPerTokenUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseUsdPerTokenUpdated(log interface{}) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + return &FeeQuoterInterface_ParseUsdPerTokenUpdated_Call{Call: _e.mock.On("ParseUsdPerTokenUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerTokenUpdated, _a1 error) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterUsdPerTokenUpdated, error)) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseUsdPerUnitGasUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseUsdPerUnitGasUpdated(log types.Log) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseUsdPerUnitGasUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterUsdPerUnitGasUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerUnitGasUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerUnitGasUpdated' +type FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call struct { + *mock.Call +} + +// ParseUsdPerUnitGasUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseUsdPerUnitGasUpdated(log interface{}) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + return &FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call{Call: _e.mock.On("ParseUsdPerUnitGasUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, _a1 error) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdated, error)) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts +func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []fee_quoter.InternalEVM2AnyTokenTransfer, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error) { + ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) + + if len(ret) == 0 { + panic("no return value specified for ProcessMessageArgs") + } + + var r0 fee_quoter.ProcessMessageArgs + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)); ok { + return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) fee_quoter.ProcessMessageArgs); ok { + r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) + } else { + r0 = ret.Get(0).(fee_quoter.ProcessMessageArgs) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) error); ok { + r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ProcessMessageArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessMessageArgs' +type FeeQuoterInterface_ProcessMessageArgs_Call struct { + *mock.Call +} + +// ProcessMessageArgs is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - feeToken common.Address +// - feeTokenAmount *big.Int +// - extraArgs []byte +// - onRampTokenTransfers []fee_quoter.InternalEVM2AnyTokenTransfer +// - sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount +func (_e *FeeQuoterInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}, onRampTokenTransfers interface{}, sourceTokenAmounts interface{}) *FeeQuoterInterface_ProcessMessageArgs_Call { + return &FeeQuoterInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts)} +} + +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []fee_quoter.InternalEVM2AnyTokenTransfer, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount)) *FeeQuoterInterface_ProcessMessageArgs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte), args[5].([]fee_quoter.InternalEVM2AnyTokenTransfer), args[6].([]fee_quoter.ClientEVMTokenAmount)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Return(_a0 fee_quoter.ProcessMessageArgs, _a1 error) *FeeQuoterInterface_ProcessMessageArgs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)) *FeeQuoterInterface_ProcessMessageArgs_Call { + _c.Call.Return(run) + return _c +} + +// SetReportPermissions provides a mock function with given fields: opts, permissions +func (_m *FeeQuoterInterface) SetReportPermissions(opts *bind.TransactOpts, permissions []fee_quoter.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + ret := _m.Called(opts, permissions) + + if len(ret) == 0 { + panic("no return value specified for SetReportPermissions") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error)); ok { + return rf(opts, permissions) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) *types.Transaction); ok { + r0 = rf(opts, permissions) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) error); ok { + r1 = rf(opts, permissions) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_SetReportPermissions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetReportPermissions' +type FeeQuoterInterface_SetReportPermissions_Call struct { + *mock.Call +} + +// SetReportPermissions is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - permissions []fee_quoter.KeystoneFeedsPermissionHandlerPermission +func (_e *FeeQuoterInterface_Expecter) SetReportPermissions(opts interface{}, permissions interface{}) *FeeQuoterInterface_SetReportPermissions_Call { + return &FeeQuoterInterface_SetReportPermissions_Call{Call: _e.mock.On("SetReportPermissions", opts, permissions)} +} + +func (_c *FeeQuoterInterface_SetReportPermissions_Call) Run(run func(opts *bind.TransactOpts, permissions []fee_quoter.KeystoneFeedsPermissionHandlerPermission)) *FeeQuoterInterface_SetReportPermissions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.KeystoneFeedsPermissionHandlerPermission)) + }) + return _c +} + +func (_c *FeeQuoterInterface_SetReportPermissions_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_SetReportPermissions_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_SetReportPermissions_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error)) *FeeQuoterInterface_SetReportPermissions_Call { + _c.Call.Return(run) + return _c +} + +// TransferOwnership provides a mock function with given fields: opts, to +func (_m *FeeQuoterInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + ret := _m.Called(opts, to) + + if len(ret) == 0 { + panic("no return value specified for TransferOwnership") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) (*types.Transaction, error)); ok { + return rf(opts, to) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) *types.Transaction); ok { + r0 = rf(opts, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, common.Address) error); ok { + r1 = rf(opts, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_TransferOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransferOwnership' +type FeeQuoterInterface_TransferOwnership_Call struct { + *mock.Call +} + +// TransferOwnership is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - to common.Address +func (_e *FeeQuoterInterface_Expecter) TransferOwnership(opts interface{}, to interface{}) *FeeQuoterInterface_TransferOwnership_Call { + return &FeeQuoterInterface_TransferOwnership_Call{Call: _e.mock.On("TransferOwnership", opts, to)} +} + +func (_c *FeeQuoterInterface_TransferOwnership_Call) Run(run func(opts *bind.TransactOpts, to common.Address)) *FeeQuoterInterface_TransferOwnership_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_TransferOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_TransferOwnership_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_TransferOwnership_Call) RunAndReturn(run func(*bind.TransactOpts, common.Address) (*types.Transaction, error)) *FeeQuoterInterface_TransferOwnership_Call { + _c.Call.Return(run) + return _c +} + +// TypeAndVersion provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) TypeAndVersion(opts *bind.CallOpts) (string, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for TypeAndVersion") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (string, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) string); ok { + r0 = rf(opts) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_TypeAndVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TypeAndVersion' +type FeeQuoterInterface_TypeAndVersion_Call struct { + *mock.Call +} + +// TypeAndVersion is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) TypeAndVersion(opts interface{}) *FeeQuoterInterface_TypeAndVersion_Call { + return &FeeQuoterInterface_TypeAndVersion_Call{Call: _e.mock.On("TypeAndVersion", opts)} +} + +func (_c *FeeQuoterInterface_TypeAndVersion_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_TypeAndVersion_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_TypeAndVersion_Call) Return(_a0 string, _a1 error) *FeeQuoterInterface_TypeAndVersion_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_TypeAndVersion_Call) RunAndReturn(run func(*bind.CallOpts) (string, error)) *FeeQuoterInterface_TypeAndVersion_Call { + _c.Call.Return(run) + return _c +} + +// UpdatePrices provides a mock function with given fields: opts, priceUpdates +func (_m *FeeQuoterInterface) UpdatePrices(opts *bind.TransactOpts, priceUpdates fee_quoter.InternalPriceUpdates) (*types.Transaction, error) { + ret := _m.Called(opts, priceUpdates) + + if len(ret) == 0 { + panic("no return value specified for UpdatePrices") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) (*types.Transaction, error)); ok { + return rf(opts, priceUpdates) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) *types.Transaction); ok { + r0 = rf(opts, priceUpdates) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) error); ok { + r1 = rf(opts, priceUpdates) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_UpdatePrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdatePrices' +type FeeQuoterInterface_UpdatePrices_Call struct { + *mock.Call +} + +// UpdatePrices is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - priceUpdates fee_quoter.InternalPriceUpdates +func (_e *FeeQuoterInterface_Expecter) UpdatePrices(opts interface{}, priceUpdates interface{}) *FeeQuoterInterface_UpdatePrices_Call { + return &FeeQuoterInterface_UpdatePrices_Call{Call: _e.mock.On("UpdatePrices", opts, priceUpdates)} +} + +func (_c *FeeQuoterInterface_UpdatePrices_Call) Run(run func(opts *bind.TransactOpts, priceUpdates fee_quoter.InternalPriceUpdates)) *FeeQuoterInterface_UpdatePrices_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].(fee_quoter.InternalPriceUpdates)) + }) + return _c +} + +func (_c *FeeQuoterInterface_UpdatePrices_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_UpdatePrices_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_UpdatePrices_Call) RunAndReturn(run func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) (*types.Transaction, error)) *FeeQuoterInterface_UpdatePrices_Call { + _c.Call.Return(run) + return _c +} + +// UpdateTokenPriceFeeds provides a mock function with given fields: opts, tokenPriceFeedUpdates +func (_m *FeeQuoterInterface) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []fee_quoter.FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + ret := _m.Called(opts, tokenPriceFeedUpdates) + + if len(ret) == 0 { + panic("no return value specified for UpdateTokenPriceFeeds") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error)); ok { + return rf(opts, tokenPriceFeedUpdates) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) *types.Transaction); ok { + r0 = rf(opts, tokenPriceFeedUpdates) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) error); ok { + r1 = rf(opts, tokenPriceFeedUpdates) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_UpdateTokenPriceFeeds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTokenPriceFeeds' +type FeeQuoterInterface_UpdateTokenPriceFeeds_Call struct { + *mock.Call +} + +// UpdateTokenPriceFeeds is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - tokenPriceFeedUpdates []fee_quoter.FeeQuoterTokenPriceFeedUpdate +func (_e *FeeQuoterInterface_Expecter) UpdateTokenPriceFeeds(opts interface{}, tokenPriceFeedUpdates interface{}) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + return &FeeQuoterInterface_UpdateTokenPriceFeeds_Call{Call: _e.mock.On("UpdateTokenPriceFeeds", opts, tokenPriceFeedUpdates)} +} + +func (_c *FeeQuoterInterface_UpdateTokenPriceFeeds_Call) Run(run func(opts *bind.TransactOpts, tokenPriceFeedUpdates []fee_quoter.FeeQuoterTokenPriceFeedUpdate)) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterTokenPriceFeedUpdate)) + }) + return _c +} + +func (_c *FeeQuoterInterface_UpdateTokenPriceFeeds_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_UpdateTokenPriceFeeds_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error)) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + _c.Call.Return(run) + return _c +} + +// WatchAuthorizedCallerAdded provides a mock function with given fields: opts, sink +func (_m *FeeQuoterInterface) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) (event.Subscription, error) { + ret := _m.Called(opts, sink) + + if len(ret) == 0 { + panic("no return value specified for WatchAuthorizedCallerAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) (event.Subscription, error)); ok { + return rf(opts, sink) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) event.Subscription); ok { + r0 = rf(opts, sink) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) error); ok { + r1 = rf(opts, sink) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerAdded' +type FeeQuoterInterface_WatchAuthorizedCallerAdded_Call struct { + *mock.Call +} + +// WatchAuthorizedCallerAdded is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded +func (_e *FeeQuoterInterface_Expecter) WatchAuthorizedCallerAdded(opts interface{}, sink interface{}) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + return &FeeQuoterInterface_WatchAuthorizedCallerAdded_Call{Call: _e.mock.On("WatchAuthorizedCallerAdded", opts, sink)} +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded)) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) (event.Subscription, error)) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + _c.Call.Return(run) + return _c +} + +// WatchAuthorizedCallerRemoved provides a mock function with given fields: opts, sink +func (_m *FeeQuoterInterface) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error) { + ret := _m.Called(opts, sink) + + if len(ret) == 0 { + panic("no return value specified for WatchAuthorizedCallerRemoved") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error)); ok { + return rf(opts, sink) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) event.Subscription); ok { + r0 = rf(opts, sink) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) error); ok { + r1 = rf(opts, sink) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerRemoved' +type FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call struct { + *mock.Call +} + +// WatchAuthorizedCallerRemoved is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved +func (_e *FeeQuoterInterface_Expecter) WatchAuthorizedCallerRemoved(opts interface{}, sink interface{}) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + return &FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call{Call: _e.mock.On("WatchAuthorizedCallerRemoved", opts, sink)} +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved)) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error)) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + _c.Call.Return(run) + return _c +} + +// WatchDestChainAdded provides a mock function with given fields: opts, sink, destChainSelector +func (_m *FeeQuoterInterface) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for WatchDestChainAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) error); ok { + r1 = rf(opts, sink, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainAdded' +type FeeQuoterInterface_WatchDestChainAdded_Call struct { + *mock.Call +} + +// WatchDestChainAdded is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterDestChainAdded +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) WatchDestChainAdded(opts interface{}, sink interface{}, destChainSelector interface{}) *FeeQuoterInterface_WatchDestChainAdded_Call { + return &FeeQuoterInterface_WatchDestChainAdded_Call{Call: _e.mock.On("WatchDestChainAdded", opts, sink, destChainSelector)} +} + +func (_c *FeeQuoterInterface_WatchDestChainAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainAdded, destChainSelector []uint64)) *FeeQuoterInterface_WatchDestChainAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterDestChainAdded), args[2].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainAdded_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchDestChainAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) (event.Subscription, error)) *FeeQuoterInterface_WatchDestChainAdded_Call { + _c.Call.Return(run) + return _c +} + +// WatchDestChainConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector +func (_m *FeeQuoterInterface) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for WatchDestChainConfigUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) error); ok { + r1 = rf(opts, sink, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainConfigUpdated' +type FeeQuoterInterface_WatchDestChainConfigUpdated_Call struct { + *mock.Call +} + +// WatchDestChainConfigUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) WatchDestChainConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + return &FeeQuoterInterface_WatchDestChainConfigUpdated_Call{Call: _e.mock.On("WatchDestChainConfigUpdated", opts, sink, destChainSelector)} +} + +func (_c *FeeQuoterInterface_WatchDestChainConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, destChainSelector []uint64)) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated), args[2].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) (event.Subscription, error)) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchFeeTokenAdded provides a mock function with given fields: opts, sink, feeToken +func (_m *FeeQuoterInterface) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, feeToken) + + if len(ret) == 0 { + panic("no return value specified for WatchFeeTokenAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) error); ok { + r1 = rf(opts, sink, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenAdded' +type FeeQuoterInterface_WatchFeeTokenAdded_Call struct { + *mock.Call +} + +// WatchFeeTokenAdded is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterFeeTokenAdded +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchFeeTokenAdded(opts interface{}, sink interface{}, feeToken interface{}) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + return &FeeQuoterInterface_WatchFeeTokenAdded_Call{Call: _e.mock.On("WatchFeeTokenAdded", opts, sink, feeToken)} +} + +func (_c *FeeQuoterInterface_WatchFeeTokenAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenAdded, feeToken []common.Address)) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterFeeTokenAdded), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenAdded_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + _c.Call.Return(run) + return _c +} + +// WatchFeeTokenRemoved provides a mock function with given fields: opts, sink, feeToken +func (_m *FeeQuoterInterface) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, feeToken) + + if len(ret) == 0 { + panic("no return value specified for WatchFeeTokenRemoved") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) error); ok { + r1 = rf(opts, sink, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenRemoved' +type FeeQuoterInterface_WatchFeeTokenRemoved_Call struct { + *mock.Call +} + +// WatchFeeTokenRemoved is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterFeeTokenRemoved +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchFeeTokenRemoved(opts interface{}, sink interface{}, feeToken interface{}) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + return &FeeQuoterInterface_WatchFeeTokenRemoved_Call{Call: _e.mock.On("WatchFeeTokenRemoved", opts, sink, feeToken)} +} + +func (_c *FeeQuoterInterface_WatchFeeTokenRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, feeToken []common.Address)) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterFeeTokenRemoved), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenRemoved_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + _c.Call.Return(run) + return _c +} + +// WatchOwnershipTransferRequested provides a mock function with given fields: opts, sink, from, to +func (_m *FeeQuoterInterface) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, from, to) + + if len(ret) == 0 { + panic("no return value specified for WatchOwnershipTransferRequested") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) error); ok { + r1 = rf(opts, sink, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferRequested' +type FeeQuoterInterface_WatchOwnershipTransferRequested_Call struct { + *mock.Call +} + +// WatchOwnershipTransferRequested is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchOwnershipTransferRequested(opts interface{}, sink interface{}, from interface{}, to interface{}) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + return &FeeQuoterInterface_WatchOwnershipTransferRequested_Call{Call: _e.mock.On("WatchOwnershipTransferRequested", opts, sink, from, to)} +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferRequested_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address)) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested), args[2].([]common.Address), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferRequested_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + _c.Call.Return(run) + return _c +} + +// WatchOwnershipTransferred provides a mock function with given fields: opts, sink, from, to +func (_m *FeeQuoterInterface) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, from, to) + + if len(ret) == 0 { + panic("no return value specified for WatchOwnershipTransferred") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) error); ok { + r1 = rf(opts, sink, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferred' +type FeeQuoterInterface_WatchOwnershipTransferred_Call struct { + *mock.Call +} + +// WatchOwnershipTransferred is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterOwnershipTransferred +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchOwnershipTransferred(opts interface{}, sink interface{}, from interface{}, to interface{}) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + return &FeeQuoterInterface_WatchOwnershipTransferred_Call{Call: _e.mock.On("WatchOwnershipTransferred", opts, sink, from, to)} +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferred_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address)) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterOwnershipTransferred), args[2].([]common.Address), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferred_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferred_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + _c.Call.Return(run) + return _c +} + +// WatchPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, sink, token +func (_m *FeeQuoterInterface) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchPremiumMultiplierWeiPerEthUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPremiumMultiplierWeiPerEthUpdated' +type FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call struct { + *mock.Call +} + +// WatchPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchPremiumMultiplierWeiPerEthUpdated(opts interface{}, sink interface{}, token interface{}) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + return &FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("WatchPremiumMultiplierWeiPerEthUpdated", opts, sink, token)} +} + +func (_c *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address)) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchPriceFeedPerTokenUpdated provides a mock function with given fields: opts, sink, token +func (_m *FeeQuoterInterface) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchPriceFeedPerTokenUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPriceFeedPerTokenUpdated' +type FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call struct { + *mock.Call +} + +// WatchPriceFeedPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchPriceFeedPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + return &FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("WatchPriceFeedPerTokenUpdated", opts, sink, token)} +} + +func (_c *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, token []common.Address)) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchReportPermissionSet provides a mock function with given fields: opts, sink, reportId +func (_m *FeeQuoterInterface) WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterReportPermissionSet, reportId [][32]byte) (event.Subscription, error) { + ret := _m.Called(opts, sink, reportId) + + if len(ret) == 0 { + panic("no return value specified for WatchReportPermissionSet") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) (event.Subscription, error)); ok { + return rf(opts, sink, reportId) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) event.Subscription); ok { + r0 = rf(opts, sink, reportId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) error); ok { + r1 = rf(opts, sink, reportId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchReportPermissionSet' +type FeeQuoterInterface_WatchReportPermissionSet_Call struct { + *mock.Call +} + +// WatchReportPermissionSet is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterReportPermissionSet +// - reportId [][32]byte +func (_e *FeeQuoterInterface_Expecter) WatchReportPermissionSet(opts interface{}, sink interface{}, reportId interface{}) *FeeQuoterInterface_WatchReportPermissionSet_Call { + return &FeeQuoterInterface_WatchReportPermissionSet_Call{Call: _e.mock.On("WatchReportPermissionSet", opts, sink, reportId)} +} + +func (_c *FeeQuoterInterface_WatchReportPermissionSet_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterReportPermissionSet, reportId [][32]byte)) *FeeQuoterInterface_WatchReportPermissionSet_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterReportPermissionSet), args[2].([][32]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchReportPermissionSet_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchReportPermissionSet_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchReportPermissionSet_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) (event.Subscription, error)) *FeeQuoterInterface_WatchReportPermissionSet_Call { + _c.Call.Return(run) + return _c +} + +// WatchTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, sink, destChainSelector, token +func (_m *FeeQuoterInterface) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for WatchTokenTransferFeeConfigDeleted") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) error); ok { + r1 = rf(opts, sink, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigDeleted' +type FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call struct { + *mock.Call +} + +// WatchTokenTransferFeeConfigDeleted is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchTokenTransferFeeConfigDeleted(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + return &FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigDeleted", opts, sink, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted), args[2].([]uint64), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(run) + return _c +} + +// WatchTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector, token +func (_m *FeeQuoterInterface) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for WatchTokenTransferFeeConfigUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) error); ok { + r1 = rf(opts, sink, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigUpdated' +type FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call struct { + *mock.Call +} + +// WatchTokenTransferFeeConfigUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchTokenTransferFeeConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + return &FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigUpdated", opts, sink, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated), args[2].([]uint64), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchUsdPerTokenUpdated provides a mock function with given fields: opts, sink, token +func (_m *FeeQuoterInterface) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchUsdPerTokenUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerTokenUpdated' +type FeeQuoterInterface_WatchUsdPerTokenUpdated_Call struct { + *mock.Call +} + +// WatchUsdPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchUsdPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + return &FeeQuoterInterface_WatchUsdPerTokenUpdated_Call{Call: _e.mock.On("WatchUsdPerTokenUpdated", opts, sink, token)} +} + +func (_c *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, token []common.Address)) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchUsdPerUnitGasUpdated provides a mock function with given fields: opts, sink, destChain +func (_m *FeeQuoterInterface) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChain) + + if len(ret) == 0 { + panic("no return value specified for WatchUsdPerUnitGasUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChain) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChain) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) error); ok { + r1 = rf(opts, sink, destChain) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerUnitGasUpdated' +type FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call struct { + *mock.Call +} + +// WatchUsdPerUnitGasUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated +// - destChain []uint64 +func (_e *FeeQuoterInterface_Expecter) WatchUsdPerUnitGasUpdated(opts interface{}, sink interface{}, destChain interface{}) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + return &FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call{Call: _e.mock.On("WatchUsdPerUnitGasUpdated", opts, sink, destChain)} +} + +func (_c *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, destChain []uint64)) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated), args[2].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeQuoterInterface creates a new instance of FeeQuoterInterface. 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 NewFeeQuoterInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeQuoterInterface { + mock := &FeeQuoterInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/gethwrappers/ccip/mocks/price_registry_interface.go b/core/gethwrappers/ccip/mocks/price_registry_interface.go deleted file mode 100644 index 8c2834acce3..00000000000 --- a/core/gethwrappers/ccip/mocks/price_registry_interface.go +++ /dev/null @@ -1,4555 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mock_contracts - -import ( - big "math/big" - - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - common "github.com/ethereum/go-ethereum/common" - - event "github.com/ethereum/go-ethereum/event" - - generated "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" - - mock "github.com/stretchr/testify/mock" - - price_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" - - types "github.com/ethereum/go-ethereum/core/types" -) - -// PriceRegistryInterface is an autogenerated mock type for the PriceRegistryInterface type -type PriceRegistryInterface struct { - mock.Mock -} - -type PriceRegistryInterface_Expecter struct { - mock *mock.Mock -} - -func (_m *PriceRegistryInterface) EXPECT() *PriceRegistryInterface_Expecter { - return &PriceRegistryInterface_Expecter{mock: &_m.Mock} -} - -// AcceptOwnership provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for AcceptOwnership") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts) (*types.Transaction, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts) *types.Transaction); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_AcceptOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AcceptOwnership' -type PriceRegistryInterface_AcceptOwnership_Call struct { - *mock.Call -} - -// AcceptOwnership is a helper method to define mock.On call -// - opts *bind.TransactOpts -func (_e *PriceRegistryInterface_Expecter) AcceptOwnership(opts interface{}) *PriceRegistryInterface_AcceptOwnership_Call { - return &PriceRegistryInterface_AcceptOwnership_Call{Call: _e.mock.On("AcceptOwnership", opts)} -} - -func (_c *PriceRegistryInterface_AcceptOwnership_Call) Run(run func(opts *bind.TransactOpts)) *PriceRegistryInterface_AcceptOwnership_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_AcceptOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_AcceptOwnership_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind.TransactOpts) (*types.Transaction, error)) *PriceRegistryInterface_AcceptOwnership_Call { - _c.Call.Return(run) - return _c -} - -// Address provides a mock function with given fields: -func (_m *PriceRegistryInterface) Address() common.Address { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Address") - } - - var r0 common.Address - if rf, ok := ret.Get(0).(func() common.Address); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - return r0 -} - -// PriceRegistryInterface_Address_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Address' -type PriceRegistryInterface_Address_Call struct { - *mock.Call -} - -// Address is a helper method to define mock.On call -func (_e *PriceRegistryInterface_Expecter) Address() *PriceRegistryInterface_Address_Call { - return &PriceRegistryInterface_Address_Call{Call: _e.mock.On("Address")} -} - -func (_c *PriceRegistryInterface_Address_Call) Run(run func()) *PriceRegistryInterface_Address_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *PriceRegistryInterface_Address_Call) Return(_a0 common.Address) *PriceRegistryInterface_Address_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *PriceRegistryInterface_Address_Call) RunAndReturn(run func() common.Address) *PriceRegistryInterface_Address_Call { - _c.Call.Return(run) - return _c -} - -// ApplyAuthorizedCallerUpdates provides a mock function with given fields: opts, authorizedCallerArgs -func (_m *PriceRegistryInterface) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs price_registry.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - ret := _m.Called(opts, authorizedCallerArgs) - - if len(ret) == 0 { - panic("no return value specified for ApplyAuthorizedCallerUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)); ok { - return rf(opts, authorizedCallerArgs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) *types.Transaction); ok { - r0 = rf(opts, authorizedCallerArgs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) error); ok { - r1 = rf(opts, authorizedCallerArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyAuthorizedCallerUpdates' -type PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call struct { - *mock.Call -} - -// ApplyAuthorizedCallerUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - authorizedCallerArgs price_registry.AuthorizedCallersAuthorizedCallerArgs -func (_e *PriceRegistryInterface_Expecter) ApplyAuthorizedCallerUpdates(opts interface{}, authorizedCallerArgs interface{}) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - return &PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call{Call: _e.mock.On("ApplyAuthorizedCallerUpdates", opts, authorizedCallerArgs)} -} - -func (_c *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call) Run(run func(opts *bind.TransactOpts, authorizedCallerArgs price_registry.AuthorizedCallersAuthorizedCallerArgs)) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(price_registry.AuthorizedCallersAuthorizedCallerArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyDestChainConfigUpdates provides a mock function with given fields: opts, destChainConfigArgs -func (_m *PriceRegistryInterface) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - ret := _m.Called(opts, destChainConfigArgs) - - if len(ret) == 0 { - panic("no return value specified for ApplyDestChainConfigUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error)); ok { - return rf(opts, destChainConfigArgs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) *types.Transaction); ok { - r0 = rf(opts, destChainConfigArgs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) error); ok { - r1 = rf(opts, destChainConfigArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyDestChainConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyDestChainConfigUpdates' -type PriceRegistryInterface_ApplyDestChainConfigUpdates_Call struct { - *mock.Call -} - -// ApplyDestChainConfigUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs -func (_e *PriceRegistryInterface_Expecter) ApplyDestChainConfigUpdates(opts interface{}, destChainConfigArgs interface{}) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - return &PriceRegistryInterface_ApplyDestChainConfigUpdates_Call{Call: _e.mock.On("ApplyDestChainConfigUpdates", opts, destChainConfigArgs)} -} - -func (_c *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs)) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryDestChainConfigArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyFeeTokensUpdates provides a mock function with given fields: opts, feeTokensToAdd, feeTokensToRemove -func (_m *PriceRegistryInterface) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - ret := _m.Called(opts, feeTokensToAdd, feeTokensToRemove) - - if len(ret) == 0 { - panic("no return value specified for ApplyFeeTokensUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)); ok { - return rf(opts, feeTokensToAdd, feeTokensToRemove) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) *types.Transaction); ok { - r0 = rf(opts, feeTokensToAdd, feeTokensToRemove) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, feeTokensToAdd, feeTokensToRemove) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyFeeTokensUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyFeeTokensUpdates' -type PriceRegistryInterface_ApplyFeeTokensUpdates_Call struct { - *mock.Call -} - -// ApplyFeeTokensUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - feeTokensToAdd []common.Address -// - feeTokensToRemove []common.Address -func (_e *PriceRegistryInterface_Expecter) ApplyFeeTokensUpdates(opts interface{}, feeTokensToAdd interface{}, feeTokensToRemove interface{}) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - return &PriceRegistryInterface_ApplyFeeTokensUpdates_Call{Call: _e.mock.On("ApplyFeeTokensUpdates", opts, feeTokensToAdd, feeTokensToRemove)} -} - -func (_c *PriceRegistryInterface_ApplyFeeTokensUpdates_Call) Run(run func(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address)) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyFeeTokensUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyFeeTokensUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyPremiumMultiplierWeiPerEthUpdates provides a mock function with given fields: opts, premiumMultiplierWeiPerEthArgs -func (_m *PriceRegistryInterface) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - ret := _m.Called(opts, premiumMultiplierWeiPerEthArgs) - - if len(ret) == 0 { - panic("no return value specified for ApplyPremiumMultiplierWeiPerEthUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)); ok { - return rf(opts, premiumMultiplierWeiPerEthArgs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) *types.Transaction); ok { - r0 = rf(opts, premiumMultiplierWeiPerEthArgs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) error); ok { - r1 = rf(opts, premiumMultiplierWeiPerEthArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyPremiumMultiplierWeiPerEthUpdates' -type PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call struct { - *mock.Call -} - -// ApplyPremiumMultiplierWeiPerEthUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs -func (_e *PriceRegistryInterface_Expecter) ApplyPremiumMultiplierWeiPerEthUpdates(opts interface{}, premiumMultiplierWeiPerEthArgs interface{}) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - return &PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call{Call: _e.mock.On("ApplyPremiumMultiplierWeiPerEthUpdates", opts, premiumMultiplierWeiPerEthArgs)} -} - -func (_c *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Run(run func(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs)) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyTokenTransferFeeConfigUpdates provides a mock function with given fields: opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs -func (_m *PriceRegistryInterface) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - ret := _m.Called(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - - if len(ret) == 0 { - panic("no return value specified for ApplyTokenTransferFeeConfigUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)); ok { - return rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) *types.Transaction); ok { - r0 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) error); ok { - r1 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyTokenTransferFeeConfigUpdates' -type PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call struct { - *mock.Call -} - -// ApplyTokenTransferFeeConfigUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs -// - tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs -func (_e *PriceRegistryInterface_Expecter) ApplyTokenTransferFeeConfigUpdates(opts interface{}, tokenTransferFeeConfigArgs interface{}, tokensToUseDefaultFeeConfigs interface{}) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - return &PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call{Call: _e.mock.On("ApplyTokenTransferFeeConfigUpdates", opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs)} -} - -func (_c *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs)) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryTokenTransferFeeConfigArgs), args[2].([]price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ConvertTokenAmount provides a mock function with given fields: opts, fromToken, fromTokenAmount, toToken -func (_m *PriceRegistryInterface) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - ret := _m.Called(opts, fromToken, fromTokenAmount, toToken) - - if len(ret) == 0 { - panic("no return value specified for ConvertTokenAmount") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)); ok { - return rf(opts, fromToken, fromTokenAmount, toToken) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) *big.Int); ok { - r0 = rf(opts, fromToken, fromTokenAmount, toToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) error); ok { - r1 = rf(opts, fromToken, fromTokenAmount, toToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ConvertTokenAmount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConvertTokenAmount' -type PriceRegistryInterface_ConvertTokenAmount_Call struct { - *mock.Call -} - -// ConvertTokenAmount is a helper method to define mock.On call -// - opts *bind.CallOpts -// - fromToken common.Address -// - fromTokenAmount *big.Int -// - toToken common.Address -func (_e *PriceRegistryInterface_Expecter) ConvertTokenAmount(opts interface{}, fromToken interface{}, fromTokenAmount interface{}, toToken interface{}) *PriceRegistryInterface_ConvertTokenAmount_Call { - return &PriceRegistryInterface_ConvertTokenAmount_Call{Call: _e.mock.On("ConvertTokenAmount", opts, fromToken, fromTokenAmount, toToken)} -} - -func (_c *PriceRegistryInterface_ConvertTokenAmount_Call) Run(run func(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address)) *PriceRegistryInterface_ConvertTokenAmount_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(*big.Int), args[3].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ConvertTokenAmount_Call) Return(_a0 *big.Int, _a1 error) *PriceRegistryInterface_ConvertTokenAmount_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ConvertTokenAmount_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)) *PriceRegistryInterface_ConvertTokenAmount_Call { - _c.Call.Return(run) - return _c -} - -// FilterAuthorizedCallerAdded provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerAddedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterAuthorizedCallerAdded") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerAddedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *price_registry.PriceRegistryAuthorizedCallerAddedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerAdded' -type PriceRegistryInterface_FilterAuthorizedCallerAdded_Call struct { - *mock.Call -} - -// FilterAuthorizedCallerAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *PriceRegistryInterface_Expecter) FilterAuthorizedCallerAdded(opts interface{}) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - return &PriceRegistryInterface_FilterAuthorizedCallerAdded_Call{Call: _e.mock.On("FilterAuthorizedCallerAdded", opts)} -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call) Run(run func(opts *bind.FilterOpts)) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerAddedIterator, _a1 error) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerAddedIterator, error)) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterAuthorizedCallerRemoved provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerRemovedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterAuthorizedCallerRemoved") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerRemovedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerRemovedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *price_registry.PriceRegistryAuthorizedCallerRemovedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerRemovedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerRemoved' -type PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call struct { - *mock.Call -} - -// FilterAuthorizedCallerRemoved is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *PriceRegistryInterface_Expecter) FilterAuthorizedCallerRemoved(opts interface{}) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - return &PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call{Call: _e.mock.On("FilterAuthorizedCallerRemoved", opts)} -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call) Run(run func(opts *bind.FilterOpts)) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerRemovedIterator, _a1 error) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerRemovedIterator, error)) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - _c.Call.Return(run) - return _c -} - -// FilterDestChainAdded provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for FilterDestChainAdded") - } - - var r0 *price_registry.PriceRegistryDestChainAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryDestChainAddedIterator); ok { - r0 = rf(opts, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainAdded' -type PriceRegistryInterface_FilterDestChainAdded_Call struct { - *mock.Call -} - -// FilterDestChainAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) FilterDestChainAdded(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_FilterDestChainAdded_Call { - return &PriceRegistryInterface_FilterDestChainAdded_Call{Call: _e.mock.On("FilterDestChainAdded", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_FilterDestChainAdded_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *PriceRegistryInterface_FilterDestChainAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainAdded_Call) Return(_a0 *price_registry.PriceRegistryDestChainAddedIterator, _a1 error) *PriceRegistryInterface_FilterDestChainAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error)) *PriceRegistryInterface_FilterDestChainAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterDestChainConfigUpdated provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for FilterDestChainConfigUpdated") - } - - var r0 *price_registry.PriceRegistryDestChainConfigUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryDestChainConfigUpdatedIterator); ok { - r0 = rf(opts, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainConfigUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainConfigUpdated' -type PriceRegistryInterface_FilterDestChainConfigUpdated_Call struct { - *mock.Call -} - -// FilterDestChainConfigUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) FilterDestChainConfigUpdated(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - return &PriceRegistryInterface_FilterDestChainConfigUpdated_Call{Call: _e.mock.On("FilterDestChainConfigUpdated", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_FilterDestChainConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryDestChainConfigUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error)) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterFeeTokenAdded provides a mock function with given fields: opts, feeToken -func (_m *PriceRegistryInterface) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error) { - ret := _m.Called(opts, feeToken) - - if len(ret) == 0 { - panic("no return value specified for FilterFeeTokenAdded") - } - - var r0 *price_registry.PriceRegistryFeeTokenAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error)); ok { - return rf(opts, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryFeeTokenAddedIterator); ok { - r0 = rf(opts, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenAdded' -type PriceRegistryInterface_FilterFeeTokenAdded_Call struct { - *mock.Call -} - -// FilterFeeTokenAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterFeeTokenAdded(opts interface{}, feeToken interface{}) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - return &PriceRegistryInterface_FilterFeeTokenAdded_Call{Call: _e.mock.On("FilterFeeTokenAdded", opts, feeToken)} -} - -func (_c *PriceRegistryInterface_FilterFeeTokenAdded_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenAdded_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenAddedIterator, _a1 error) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error)) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterFeeTokenRemoved provides a mock function with given fields: opts, feeToken -func (_m *PriceRegistryInterface) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*price_registry.PriceRegistryFeeTokenRemovedIterator, error) { - ret := _m.Called(opts, feeToken) - - if len(ret) == 0 { - panic("no return value specified for FilterFeeTokenRemoved") - } - - var r0 *price_registry.PriceRegistryFeeTokenRemovedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenRemovedIterator, error)); ok { - return rf(opts, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryFeeTokenRemovedIterator); ok { - r0 = rf(opts, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenRemovedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenRemoved' -type PriceRegistryInterface_FilterFeeTokenRemoved_Call struct { - *mock.Call -} - -// FilterFeeTokenRemoved is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterFeeTokenRemoved(opts interface{}, feeToken interface{}) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - return &PriceRegistryInterface_FilterFeeTokenRemoved_Call{Call: _e.mock.On("FilterFeeTokenRemoved", opts, feeToken)} -} - -func (_c *PriceRegistryInterface_FilterFeeTokenRemoved_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenRemoved_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenRemovedIterator, _a1 error) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenRemoved_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenRemovedIterator, error)) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - _c.Call.Return(run) - return _c -} - -// FilterOwnershipTransferRequested provides a mock function with given fields: opts, from, to -func (_m *PriceRegistryInterface) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*price_registry.PriceRegistryOwnershipTransferRequestedIterator, error) { - ret := _m.Called(opts, from, to) - - if len(ret) == 0 { - panic("no return value specified for FilterOwnershipTransferRequested") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferRequestedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferRequestedIterator, error)); ok { - return rf(opts, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *price_registry.PriceRegistryOwnershipTransferRequestedIterator); ok { - r0 = rf(opts, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferRequestedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferRequested' -type PriceRegistryInterface_FilterOwnershipTransferRequested_Call struct { - *mock.Call -} - -// FilterOwnershipTransferRequested is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterOwnershipTransferRequested(opts interface{}, from interface{}, to interface{}) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - return &PriceRegistryInterface_FilterOwnershipTransferRequested_Call{Call: _e.mock.On("FilterOwnershipTransferRequested", opts, from, to)} -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferRequested_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferRequested_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferRequestedIterator, _a1 error) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferRequestedIterator, error)) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// FilterOwnershipTransferred provides a mock function with given fields: opts, from, to -func (_m *PriceRegistryInterface) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*price_registry.PriceRegistryOwnershipTransferredIterator, error) { - ret := _m.Called(opts, from, to) - - if len(ret) == 0 { - panic("no return value specified for FilterOwnershipTransferred") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferredIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferredIterator, error)); ok { - return rf(opts, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *price_registry.PriceRegistryOwnershipTransferredIterator); ok { - r0 = rf(opts, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferredIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferred' -type PriceRegistryInterface_FilterOwnershipTransferred_Call struct { - *mock.Call -} - -// FilterOwnershipTransferred is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterOwnershipTransferred(opts interface{}, from interface{}, to interface{}) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - return &PriceRegistryInterface_FilterOwnershipTransferred_Call{Call: _e.mock.On("FilterOwnershipTransferred", opts, from, to)} -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferred_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferred_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferredIterator, _a1 error) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferred_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferredIterator, error)) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// FilterPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for FilterPremiumMultiplierWeiPerEthUpdated") - } - - var r0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPremiumMultiplierWeiPerEthUpdated' -type PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call struct { - *mock.Call -} - -// FilterPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterPremiumMultiplierWeiPerEthUpdated(opts interface{}, token interface{}) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - return &PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("FilterPremiumMultiplierWeiPerEthUpdated", opts, token)} -} - -func (_c *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error)) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterPriceFeedPerTokenUpdated provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for FilterPriceFeedPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPriceFeedPerTokenUpdated' -type PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call struct { - *mock.Call -} - -// FilterPriceFeedPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterPriceFeedPerTokenUpdated(opts interface{}, token interface{}) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - return &PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("FilterPriceFeedPerTokenUpdated", opts, token)} -} - -func (_c *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error)) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterPriceUpdaterRemoved provides a mock function with given fields: opts, priceUpdater -func (_m *PriceRegistryInterface) FilterPriceUpdaterRemoved(opts *bind.FilterOpts, priceUpdater []common.Address) (*price_registry.PriceRegistryPriceUpdaterRemovedIterator, error) { - ret := _m.Called(opts, priceUpdater) - - if len(ret) == 0 { - panic("no return value specified for FilterPriceUpdaterRemoved") - } - - var r0 *price_registry.PriceRegistryPriceUpdaterRemovedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceUpdaterRemovedIterator, error)); ok { - return rf(opts, priceUpdater) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPriceUpdaterRemovedIterator); ok { - r0 = rf(opts, priceUpdater) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceUpdaterRemovedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, priceUpdater) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterPriceUpdaterRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPriceUpdaterRemoved' -type PriceRegistryInterface_FilterPriceUpdaterRemoved_Call struct { - *mock.Call -} - -// FilterPriceUpdaterRemoved is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - priceUpdater []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterPriceUpdaterRemoved(opts interface{}, priceUpdater interface{}) *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call { - return &PriceRegistryInterface_FilterPriceUpdaterRemoved_Call{Call: _e.mock.On("FilterPriceUpdaterRemoved", opts, priceUpdater)} -} - -func (_c *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call) Run(run func(opts *bind.FilterOpts, priceUpdater []common.Address)) *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call) Return(_a0 *price_registry.PriceRegistryPriceUpdaterRemovedIterator, _a1 error) *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceUpdaterRemovedIterator, error)) *PriceRegistryInterface_FilterPriceUpdaterRemoved_Call { - _c.Call.Return(run) - return _c -} - -// FilterPriceUpdaterSet provides a mock function with given fields: opts, priceUpdater -func (_m *PriceRegistryInterface) FilterPriceUpdaterSet(opts *bind.FilterOpts, priceUpdater []common.Address) (*price_registry.PriceRegistryPriceUpdaterSetIterator, error) { - ret := _m.Called(opts, priceUpdater) - - if len(ret) == 0 { - panic("no return value specified for FilterPriceUpdaterSet") - } - - var r0 *price_registry.PriceRegistryPriceUpdaterSetIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceUpdaterSetIterator, error)); ok { - return rf(opts, priceUpdater) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPriceUpdaterSetIterator); ok { - r0 = rf(opts, priceUpdater) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceUpdaterSetIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, priceUpdater) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterPriceUpdaterSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPriceUpdaterSet' -type PriceRegistryInterface_FilterPriceUpdaterSet_Call struct { - *mock.Call -} - -// FilterPriceUpdaterSet is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - priceUpdater []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterPriceUpdaterSet(opts interface{}, priceUpdater interface{}) *PriceRegistryInterface_FilterPriceUpdaterSet_Call { - return &PriceRegistryInterface_FilterPriceUpdaterSet_Call{Call: _e.mock.On("FilterPriceUpdaterSet", opts, priceUpdater)} -} - -func (_c *PriceRegistryInterface_FilterPriceUpdaterSet_Call) Run(run func(opts *bind.FilterOpts, priceUpdater []common.Address)) *PriceRegistryInterface_FilterPriceUpdaterSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceUpdaterSet_Call) Return(_a0 *price_registry.PriceRegistryPriceUpdaterSetIterator, _a1 error) *PriceRegistryInterface_FilterPriceUpdaterSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceUpdaterSet_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceUpdaterSetIterator, error)) *PriceRegistryInterface_FilterPriceUpdaterSet_Call { - _c.Call.Return(run) - return _c -} - -// FilterTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, destChainSelector, token -func (_m *PriceRegistryInterface) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error) { - ret := _m.Called(opts, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for FilterTokenTransferFeeConfigDeleted") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error)); ok { - return rf(opts, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator); ok { - r0 = rf(opts, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { - r1 = rf(opts, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigDeleted' -type PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call struct { - *mock.Call -} - -// FilterTokenTransferFeeConfigDeleted is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterTokenTransferFeeConfigDeleted(opts interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - return &PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigDeleted", opts, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, _a1 error) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error)) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(run) - return _c -} - -// FilterTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, destChainSelector, token -func (_m *PriceRegistryInterface) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) { - ret := _m.Called(opts, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for FilterTokenTransferFeeConfigUpdated") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error)); ok { - return rf(opts, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator); ok { - r0 = rf(opts, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { - r1 = rf(opts, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigUpdated' -type PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call struct { - *mock.Call -} - -// FilterTokenTransferFeeConfigUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterTokenTransferFeeConfigUpdated(opts interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - return &PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigUpdated", opts, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error)) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterUsdPerTokenUpdated provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for FilterUsdPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerTokenUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryUsdPerTokenUpdatedIterator); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerTokenUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerTokenUpdated' -type PriceRegistryInterface_FilterUsdPerTokenUpdated_Call struct { - *mock.Call -} - -// FilterUsdPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterUsdPerTokenUpdated(opts interface{}, token interface{}) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - return &PriceRegistryInterface_FilterUsdPerTokenUpdated_Call{Call: _e.mock.On("FilterUsdPerTokenUpdated", opts, token)} -} - -func (_c *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerTokenUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error)) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterUsdPerUnitGasUpdated provides a mock function with given fields: opts, destChain -func (_m *PriceRegistryInterface) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, error) { - ret := _m.Called(opts, destChain) - - if len(ret) == 0 { - panic("no return value specified for FilterUsdPerUnitGasUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, error)); ok { - return rf(opts, destChain) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator); ok { - r0 = rf(opts, destChain) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { - r1 = rf(opts, destChain) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerUnitGasUpdated' -type PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call struct { - *mock.Call -} - -// FilterUsdPerUnitGasUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChain []uint64 -func (_e *PriceRegistryInterface_Expecter) FilterUsdPerUnitGasUpdated(opts interface{}, destChain interface{}) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - return &PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call{Call: _e.mock.On("FilterUsdPerUnitGasUpdated", opts, destChain)} -} - -func (_c *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.FilterOpts, destChain []uint64)) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, error)) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - _c.Call.Return(run) - return _c -} - -// GetAllAuthorizedCallers provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetAllAuthorizedCallers") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetAllAuthorizedCallers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllAuthorizedCallers' -type PriceRegistryInterface_GetAllAuthorizedCallers_Call struct { - *mock.Call -} - -// GetAllAuthorizedCallers is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) GetAllAuthorizedCallers(opts interface{}) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - return &PriceRegistryInterface_GetAllAuthorizedCallers_Call{Call: _e.mock.On("GetAllAuthorizedCallers", opts)} -} - -func (_c *PriceRegistryInterface_GetAllAuthorizedCallers_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetAllAuthorizedCallers_Call) Return(_a0 []common.Address, _a1 error) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetAllAuthorizedCallers_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - _c.Call.Return(run) - return _c -} - -// GetDestChainConfig provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (price_registry.PriceRegistryDestChainConfig, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for GetDestChainConfig") - } - - var r0 price_registry.PriceRegistryDestChainConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (price_registry.PriceRegistryDestChainConfig, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) price_registry.PriceRegistryDestChainConfig); ok { - r0 = rf(opts, destChainSelector) - } else { - r0 = ret.Get(0).(price_registry.PriceRegistryDestChainConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetDestChainConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestChainConfig' -type PriceRegistryInterface_GetDestChainConfig_Call struct { - *mock.Call -} - -// GetDestChainConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -func (_e *PriceRegistryInterface_Expecter) GetDestChainConfig(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_GetDestChainConfig_Call { - return &PriceRegistryInterface_GetDestChainConfig_Call{Call: _e.mock.On("GetDestChainConfig", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_GetDestChainConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *PriceRegistryInterface_GetDestChainConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetDestChainConfig_Call) Return(_a0 price_registry.PriceRegistryDestChainConfig, _a1 error) *PriceRegistryInterface_GetDestChainConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetDestChainConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (price_registry.PriceRegistryDestChainConfig, error)) *PriceRegistryInterface_GetDestChainConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetDestinationChainGasPrice provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (price_registry.InternalTimestampedPackedUint224, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for GetDestinationChainGasPrice") - } - - var r0 price_registry.InternalTimestampedPackedUint224 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (price_registry.InternalTimestampedPackedUint224, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) price_registry.InternalTimestampedPackedUint224); ok { - r0 = rf(opts, destChainSelector) - } else { - r0 = ret.Get(0).(price_registry.InternalTimestampedPackedUint224) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetDestinationChainGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestinationChainGasPrice' -type PriceRegistryInterface_GetDestinationChainGasPrice_Call struct { - *mock.Call -} - -// GetDestinationChainGasPrice is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -func (_e *PriceRegistryInterface_Expecter) GetDestinationChainGasPrice(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - return &PriceRegistryInterface_GetDestinationChainGasPrice_Call{Call: _e.mock.On("GetDestinationChainGasPrice", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_GetDestinationChainGasPrice_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetDestinationChainGasPrice_Call) Return(_a0 price_registry.InternalTimestampedPackedUint224, _a1 error) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetDestinationChainGasPrice_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (price_registry.InternalTimestampedPackedUint224, error)) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - _c.Call.Return(run) - return _c -} - -// GetFeeTokens provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetFeeTokens") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetFeeTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeTokens' -type PriceRegistryInterface_GetFeeTokens_Call struct { - *mock.Call -} - -// GetFeeTokens is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) GetFeeTokens(opts interface{}) *PriceRegistryInterface_GetFeeTokens_Call { - return &PriceRegistryInterface_GetFeeTokens_Call{Call: _e.mock.On("GetFeeTokens", opts)} -} - -func (_c *PriceRegistryInterface_GetFeeTokens_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_GetFeeTokens_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetFeeTokens_Call) Return(_a0 []common.Address, _a1 error) *PriceRegistryInterface_GetFeeTokens_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetFeeTokens_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *PriceRegistryInterface_GetFeeTokens_Call { - _c.Call.Return(run) - return _c -} - -// GetPremiumMultiplierWeiPerEth provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetPremiumMultiplierWeiPerEth") - } - - var r0 uint64 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (uint64, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) uint64); ok { - r0 = rf(opts, token) - } else { - r0 = ret.Get(0).(uint64) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPremiumMultiplierWeiPerEth' -type PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call struct { - *mock.Call -} - -// GetPremiumMultiplierWeiPerEth is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetPremiumMultiplierWeiPerEth(opts interface{}, token interface{}) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - return &PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call{Call: _e.mock.On("GetPremiumMultiplierWeiPerEth", opts, token)} -} - -func (_c *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call) Return(_a0 uint64, _a1 error) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (uint64, error)) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - _c.Call.Return(run) - return _c -} - -// GetStaticConfig provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetStaticConfig(opts *bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetStaticConfig") - } - - var r0 price_registry.PriceRegistryStaticConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) price_registry.PriceRegistryStaticConfig); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(price_registry.PriceRegistryStaticConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetStaticConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStaticConfig' -type PriceRegistryInterface_GetStaticConfig_Call struct { - *mock.Call -} - -// GetStaticConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) GetStaticConfig(opts interface{}) *PriceRegistryInterface_GetStaticConfig_Call { - return &PriceRegistryInterface_GetStaticConfig_Call{Call: _e.mock.On("GetStaticConfig", opts)} -} - -func (_c *PriceRegistryInterface_GetStaticConfig_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_GetStaticConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetStaticConfig_Call) Return(_a0 price_registry.PriceRegistryStaticConfig, _a1 error) *PriceRegistryInterface_GetStaticConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetStaticConfig_Call) RunAndReturn(run func(*bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error)) *PriceRegistryInterface_GetStaticConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenAndGasPrices provides a mock function with given fields: opts, token, destChainSelector -func (_m *PriceRegistryInterface) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (price_registry.GetTokenAndGasPrices, error) { - ret := _m.Called(opts, token, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for GetTokenAndGasPrices") - } - - var r0 price_registry.GetTokenAndGasPrices - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) (price_registry.GetTokenAndGasPrices, error)); ok { - return rf(opts, token, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) price_registry.GetTokenAndGasPrices); ok { - r0 = rf(opts, token, destChainSelector) - } else { - r0 = ret.Get(0).(price_registry.GetTokenAndGasPrices) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, uint64) error); ok { - r1 = rf(opts, token, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenAndGasPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenAndGasPrices' -type PriceRegistryInterface_GetTokenAndGasPrices_Call struct { - *mock.Call -} - -// GetTokenAndGasPrices is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -// - destChainSelector uint64 -func (_e *PriceRegistryInterface_Expecter) GetTokenAndGasPrices(opts interface{}, token interface{}, destChainSelector interface{}) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - return &PriceRegistryInterface_GetTokenAndGasPrices_Call{Call: _e.mock.On("GetTokenAndGasPrices", opts, token, destChainSelector)} -} - -func (_c *PriceRegistryInterface_GetTokenAndGasPrices_Call) Run(run func(opts *bind.CallOpts, token common.Address, destChainSelector uint64)) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenAndGasPrices_Call) Return(_a0 price_registry.GetTokenAndGasPrices, _a1 error) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenAndGasPrices_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, uint64) (price_registry.GetTokenAndGasPrices, error)) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenPrice provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetTokenPrice(opts *bind.CallOpts, token common.Address) (price_registry.InternalTimestampedPackedUint224, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetTokenPrice") - } - - var r0 price_registry.InternalTimestampedPackedUint224 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (price_registry.InternalTimestampedPackedUint224, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) price_registry.InternalTimestampedPackedUint224); ok { - r0 = rf(opts, token) - } else { - r0 = ret.Get(0).(price_registry.InternalTimestampedPackedUint224) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrice' -type PriceRegistryInterface_GetTokenPrice_Call struct { - *mock.Call -} - -// GetTokenPrice is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenPrice(opts interface{}, token interface{}) *PriceRegistryInterface_GetTokenPrice_Call { - return &PriceRegistryInterface_GetTokenPrice_Call{Call: _e.mock.On("GetTokenPrice", opts, token)} -} - -func (_c *PriceRegistryInterface_GetTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetTokenPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrice_Call) Return(_a0 price_registry.InternalTimestampedPackedUint224, _a1 error) *PriceRegistryInterface_GetTokenPrice_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (price_registry.InternalTimestampedPackedUint224, error)) *PriceRegistryInterface_GetTokenPrice_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenPriceFeedConfig provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (price_registry.IPriceRegistryTokenPriceFeedConfig, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetTokenPriceFeedConfig") - } - - var r0 price_registry.IPriceRegistryTokenPriceFeedConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (price_registry.IPriceRegistryTokenPriceFeedConfig, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) price_registry.IPriceRegistryTokenPriceFeedConfig); ok { - r0 = rf(opts, token) - } else { - r0 = ret.Get(0).(price_registry.IPriceRegistryTokenPriceFeedConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenPriceFeedConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPriceFeedConfig' -type PriceRegistryInterface_GetTokenPriceFeedConfig_Call struct { - *mock.Call -} - -// GetTokenPriceFeedConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenPriceFeedConfig(opts interface{}, token interface{}) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - return &PriceRegistryInterface_GetTokenPriceFeedConfig_Call{Call: _e.mock.On("GetTokenPriceFeedConfig", opts, token)} -} - -func (_c *PriceRegistryInterface_GetTokenPriceFeedConfig_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPriceFeedConfig_Call) Return(_a0 price_registry.IPriceRegistryTokenPriceFeedConfig, _a1 error) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPriceFeedConfig_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (price_registry.IPriceRegistryTokenPriceFeedConfig, error)) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenPrices provides a mock function with given fields: opts, tokens -func (_m *PriceRegistryInterface) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]price_registry.InternalTimestampedPackedUint224, error) { - ret := _m.Called(opts, tokens) - - if len(ret) == 0 { - panic("no return value specified for GetTokenPrices") - } - - var r0 []price_registry.InternalTimestampedPackedUint224 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) ([]price_registry.InternalTimestampedPackedUint224, error)); ok { - return rf(opts, tokens) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) []price_registry.InternalTimestampedPackedUint224); ok { - r0 = rf(opts, tokens) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]price_registry.InternalTimestampedPackedUint224) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, []common.Address) error); ok { - r1 = rf(opts, tokens) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrices' -type PriceRegistryInterface_GetTokenPrices_Call struct { - *mock.Call -} - -// GetTokenPrices is a helper method to define mock.On call -// - opts *bind.CallOpts -// - tokens []common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenPrices(opts interface{}, tokens interface{}) *PriceRegistryInterface_GetTokenPrices_Call { - return &PriceRegistryInterface_GetTokenPrices_Call{Call: _e.mock.On("GetTokenPrices", opts, tokens)} -} - -func (_c *PriceRegistryInterface_GetTokenPrices_Call) Run(run func(opts *bind.CallOpts, tokens []common.Address)) *PriceRegistryInterface_GetTokenPrices_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrices_Call) Return(_a0 []price_registry.InternalTimestampedPackedUint224, _a1 error) *PriceRegistryInterface_GetTokenPrices_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrices_Call) RunAndReturn(run func(*bind.CallOpts, []common.Address) ([]price_registry.InternalTimestampedPackedUint224, error)) *PriceRegistryInterface_GetTokenPrices_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenTransferFeeConfig provides a mock function with given fields: opts, destChainSelector, token -func (_m *PriceRegistryInterface) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error) { - ret := _m.Called(opts, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for GetTokenTransferFeeConfig") - } - - var r0 price_registry.PriceRegistryTokenTransferFeeConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error)); ok { - return rf(opts, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) price_registry.PriceRegistryTokenTransferFeeConfig); ok { - r0 = rf(opts, destChainSelector, token) - } else { - r0 = ret.Get(0).(price_registry.PriceRegistryTokenTransferFeeConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address) error); ok { - r1 = rf(opts, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenTransferFeeConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenTransferFeeConfig' -type PriceRegistryInterface_GetTokenTransferFeeConfig_Call struct { - *mock.Call -} - -// GetTokenTransferFeeConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenTransferFeeConfig(opts interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - return &PriceRegistryInterface_GetTokenTransferFeeConfig_Call{Call: _e.mock.On("GetTokenTransferFeeConfig", opts, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_GetTokenTransferFeeConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, token common.Address)) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenTransferFeeConfig_Call) Return(_a0 price_registry.PriceRegistryTokenTransferFeeConfig, _a1 error) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenTransferFeeConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error)) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetValidatedFee provides a mock function with given fields: opts, destChainSelector, message -func (_m *PriceRegistryInterface) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message price_registry.ClientEVM2AnyMessage) (*big.Int, error) { - ret := _m.Called(opts, destChainSelector, message) - - if len(ret) == 0 { - panic("no return value specified for GetValidatedFee") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) (*big.Int, error)); ok { - return rf(opts, destChainSelector, message) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) *big.Int); ok { - r0 = rf(opts, destChainSelector, message) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) error); ok { - r1 = rf(opts, destChainSelector, message) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetValidatedFee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedFee' -type PriceRegistryInterface_GetValidatedFee_Call struct { - *mock.Call -} - -// GetValidatedFee is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - message price_registry.ClientEVM2AnyMessage -func (_e *PriceRegistryInterface_Expecter) GetValidatedFee(opts interface{}, destChainSelector interface{}, message interface{}) *PriceRegistryInterface_GetValidatedFee_Call { - return &PriceRegistryInterface_GetValidatedFee_Call{Call: _e.mock.On("GetValidatedFee", opts, destChainSelector, message)} -} - -func (_c *PriceRegistryInterface_GetValidatedFee_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, message price_registry.ClientEVM2AnyMessage)) *PriceRegistryInterface_GetValidatedFee_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(price_registry.ClientEVM2AnyMessage)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedFee_Call) Return(_a0 *big.Int, _a1 error) *PriceRegistryInterface_GetValidatedFee_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedFee_Call) RunAndReturn(run func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) (*big.Int, error)) *PriceRegistryInterface_GetValidatedFee_Call { - _c.Call.Return(run) - return _c -} - -// GetValidatedTokenPrice provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetValidatedTokenPrice") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (*big.Int, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) *big.Int); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetValidatedTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedTokenPrice' -type PriceRegistryInterface_GetValidatedTokenPrice_Call struct { - *mock.Call -} - -// GetValidatedTokenPrice is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetValidatedTokenPrice(opts interface{}, token interface{}) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - return &PriceRegistryInterface_GetValidatedTokenPrice_Call{Call: _e.mock.On("GetValidatedTokenPrice", opts, token)} -} - -func (_c *PriceRegistryInterface_GetValidatedTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedTokenPrice_Call) Return(_a0 *big.Int, _a1 error) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (*big.Int, error)) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - _c.Call.Return(run) - return _c -} - -// Owner provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) Owner(opts *bind.CallOpts) (common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for Owner") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_Owner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Owner' -type PriceRegistryInterface_Owner_Call struct { - *mock.Call -} - -// Owner is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) Owner(opts interface{}) *PriceRegistryInterface_Owner_Call { - return &PriceRegistryInterface_Owner_Call{Call: _e.mock.On("Owner", opts)} -} - -func (_c *PriceRegistryInterface_Owner_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_Owner_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_Owner_Call) Return(_a0 common.Address, _a1 error) *PriceRegistryInterface_Owner_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_Owner_Call) RunAndReturn(run func(*bind.CallOpts) (common.Address, error)) *PriceRegistryInterface_Owner_Call { - _c.Call.Return(run) - return _c -} - -// ParseAuthorizedCallerAdded provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseAuthorizedCallerAdded(log types.Log) (*price_registry.PriceRegistryAuthorizedCallerAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseAuthorizedCallerAdded") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryAuthorizedCallerAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerAdded' -type PriceRegistryInterface_ParseAuthorizedCallerAdded_Call struct { - *mock.Call -} - -// ParseAuthorizedCallerAdded is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseAuthorizedCallerAdded(log interface{}) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - return &PriceRegistryInterface_ParseAuthorizedCallerAdded_Call{Call: _e.mock.On("ParseAuthorizedCallerAdded", log)} -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerAdded, _a1 error) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerAdded, error)) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParseAuthorizedCallerRemoved provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseAuthorizedCallerRemoved(log types.Log) (*price_registry.PriceRegistryAuthorizedCallerRemoved, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseAuthorizedCallerRemoved") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerRemoved - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerRemoved, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryAuthorizedCallerRemoved); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerRemoved) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerRemoved' -type PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call struct { - *mock.Call -} - -// ParseAuthorizedCallerRemoved is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseAuthorizedCallerRemoved(log interface{}) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - return &PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call{Call: _e.mock.On("ParseAuthorizedCallerRemoved", log)} -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerRemoved, _a1 error) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerRemoved, error)) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - _c.Call.Return(run) - return _c -} - -// ParseDestChainAdded provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseDestChainAdded(log types.Log) (*price_registry.PriceRegistryDestChainAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseDestChainAdded") - } - - var r0 *price_registry.PriceRegistryDestChainAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryDestChainAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryDestChainAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainAdded' -type PriceRegistryInterface_ParseDestChainAdded_Call struct { - *mock.Call -} - -// ParseDestChainAdded is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseDestChainAdded(log interface{}) *PriceRegistryInterface_ParseDestChainAdded_Call { - return &PriceRegistryInterface_ParseDestChainAdded_Call{Call: _e.mock.On("ParseDestChainAdded", log)} -} - -func (_c *PriceRegistryInterface_ParseDestChainAdded_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseDestChainAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainAdded_Call) Return(_a0 *price_registry.PriceRegistryDestChainAdded, _a1 error) *PriceRegistryInterface_ParseDestChainAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainAdded_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryDestChainAdded, error)) *PriceRegistryInterface_ParseDestChainAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParseDestChainConfigUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseDestChainConfigUpdated(log types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseDestChainConfigUpdated") - } - - var r0 *price_registry.PriceRegistryDestChainConfigUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryDestChainConfigUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainConfigUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainConfigUpdated' -type PriceRegistryInterface_ParseDestChainConfigUpdated_Call struct { - *mock.Call -} - -// ParseDestChainConfigUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseDestChainConfigUpdated(log interface{}) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - return &PriceRegistryInterface_ParseDestChainConfigUpdated_Call{Call: _e.mock.On("ParseDestChainConfigUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseDestChainConfigUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryDestChainConfigUpdated, _a1 error) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainConfigUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error)) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseFeeTokenAdded provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseFeeTokenAdded(log types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseFeeTokenAdded") - } - - var r0 *price_registry.PriceRegistryFeeTokenAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryFeeTokenAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenAdded' -type PriceRegistryInterface_ParseFeeTokenAdded_Call struct { - *mock.Call -} - -// ParseFeeTokenAdded is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseFeeTokenAdded(log interface{}) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - return &PriceRegistryInterface_ParseFeeTokenAdded_Call{Call: _e.mock.On("ParseFeeTokenAdded", log)} -} - -func (_c *PriceRegistryInterface_ParseFeeTokenAdded_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenAdded_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenAdded, _a1 error) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenAdded_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error)) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParseFeeTokenRemoved provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseFeeTokenRemoved(log types.Log) (*price_registry.PriceRegistryFeeTokenRemoved, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseFeeTokenRemoved") - } - - var r0 *price_registry.PriceRegistryFeeTokenRemoved - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryFeeTokenRemoved, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryFeeTokenRemoved); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenRemoved) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenRemoved' -type PriceRegistryInterface_ParseFeeTokenRemoved_Call struct { - *mock.Call -} - -// ParseFeeTokenRemoved is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseFeeTokenRemoved(log interface{}) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - return &PriceRegistryInterface_ParseFeeTokenRemoved_Call{Call: _e.mock.On("ParseFeeTokenRemoved", log)} -} - -func (_c *PriceRegistryInterface_ParseFeeTokenRemoved_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenRemoved_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenRemoved, _a1 error) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenRemoved_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryFeeTokenRemoved, error)) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - _c.Call.Return(run) - return _c -} - -// ParseLog provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseLog(log types.Log) (generated.AbigenLog, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseLog") - } - - var r0 generated.AbigenLog - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (generated.AbigenLog, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) generated.AbigenLog); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(generated.AbigenLog) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseLog_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseLog' -type PriceRegistryInterface_ParseLog_Call struct { - *mock.Call -} - -// ParseLog is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseLog(log interface{}) *PriceRegistryInterface_ParseLog_Call { - return &PriceRegistryInterface_ParseLog_Call{Call: _e.mock.On("ParseLog", log)} -} - -func (_c *PriceRegistryInterface_ParseLog_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseLog_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseLog_Call) Return(_a0 generated.AbigenLog, _a1 error) *PriceRegistryInterface_ParseLog_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseLog_Call) RunAndReturn(run func(types.Log) (generated.AbigenLog, error)) *PriceRegistryInterface_ParseLog_Call { - _c.Call.Return(run) - return _c -} - -// ParseOwnershipTransferRequested provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseOwnershipTransferRequested(log types.Log) (*price_registry.PriceRegistryOwnershipTransferRequested, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseOwnershipTransferRequested") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferRequested - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryOwnershipTransferRequested, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryOwnershipTransferRequested); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferRequested) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferRequested' -type PriceRegistryInterface_ParseOwnershipTransferRequested_Call struct { - *mock.Call -} - -// ParseOwnershipTransferRequested is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseOwnershipTransferRequested(log interface{}) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - return &PriceRegistryInterface_ParseOwnershipTransferRequested_Call{Call: _e.mock.On("ParseOwnershipTransferRequested", log)} -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferRequested_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferRequested_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferRequested, _a1 error) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferRequested_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryOwnershipTransferRequested, error)) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// ParseOwnershipTransferred provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseOwnershipTransferred(log types.Log) (*price_registry.PriceRegistryOwnershipTransferred, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseOwnershipTransferred") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferred - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryOwnershipTransferred, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryOwnershipTransferred); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferred) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferred' -type PriceRegistryInterface_ParseOwnershipTransferred_Call struct { - *mock.Call -} - -// ParseOwnershipTransferred is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseOwnershipTransferred(log interface{}) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - return &PriceRegistryInterface_ParseOwnershipTransferred_Call{Call: _e.mock.On("ParseOwnershipTransferred", log)} -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferred_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferred_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferred, _a1 error) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferred_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryOwnershipTransferred, error)) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// ParsePremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePremiumMultiplierWeiPerEthUpdated") - } - - var r0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePremiumMultiplierWeiPerEthUpdated' -type PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call struct { - *mock.Call -} - -// ParsePremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParsePremiumMultiplierWeiPerEthUpdated(log interface{}) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - return &PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("ParsePremiumMultiplierWeiPerEthUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, _a1 error) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error)) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParsePriceFeedPerTokenUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParsePriceFeedPerTokenUpdated(log types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePriceFeedPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryPriceFeedPerTokenUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPriceFeedPerTokenUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceFeedPerTokenUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePriceFeedPerTokenUpdated' -type PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call struct { - *mock.Call -} - -// ParsePriceFeedPerTokenUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParsePriceFeedPerTokenUpdated(log interface{}) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - return &PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call{Call: _e.mock.On("ParsePriceFeedPerTokenUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryPriceFeedPerTokenUpdated, _a1 error) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error)) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParsePriceUpdaterRemoved provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParsePriceUpdaterRemoved(log types.Log) (*price_registry.PriceRegistryPriceUpdaterRemoved, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePriceUpdaterRemoved") - } - - var r0 *price_registry.PriceRegistryPriceUpdaterRemoved - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPriceUpdaterRemoved, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPriceUpdaterRemoved); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceUpdaterRemoved) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParsePriceUpdaterRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePriceUpdaterRemoved' -type PriceRegistryInterface_ParsePriceUpdaterRemoved_Call struct { - *mock.Call -} - -// ParsePriceUpdaterRemoved is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParsePriceUpdaterRemoved(log interface{}) *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call { - return &PriceRegistryInterface_ParsePriceUpdaterRemoved_Call{Call: _e.mock.On("ParsePriceUpdaterRemoved", log)} -} - -func (_c *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call) Return(_a0 *price_registry.PriceRegistryPriceUpdaterRemoved, _a1 error) *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryPriceUpdaterRemoved, error)) *PriceRegistryInterface_ParsePriceUpdaterRemoved_Call { - _c.Call.Return(run) - return _c -} - -// ParsePriceUpdaterSet provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParsePriceUpdaterSet(log types.Log) (*price_registry.PriceRegistryPriceUpdaterSet, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePriceUpdaterSet") - } - - var r0 *price_registry.PriceRegistryPriceUpdaterSet - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPriceUpdaterSet, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPriceUpdaterSet); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceUpdaterSet) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParsePriceUpdaterSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePriceUpdaterSet' -type PriceRegistryInterface_ParsePriceUpdaterSet_Call struct { - *mock.Call -} - -// ParsePriceUpdaterSet is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParsePriceUpdaterSet(log interface{}) *PriceRegistryInterface_ParsePriceUpdaterSet_Call { - return &PriceRegistryInterface_ParsePriceUpdaterSet_Call{Call: _e.mock.On("ParsePriceUpdaterSet", log)} -} - -func (_c *PriceRegistryInterface_ParsePriceUpdaterSet_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParsePriceUpdaterSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceUpdaterSet_Call) Return(_a0 *price_registry.PriceRegistryPriceUpdaterSet, _a1 error) *PriceRegistryInterface_ParsePriceUpdaterSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceUpdaterSet_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryPriceUpdaterSet, error)) *PriceRegistryInterface_ParsePriceUpdaterSet_Call { - _c.Call.Return(run) - return _c -} - -// ParseTokenTransferFeeConfigDeleted provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseTokenTransferFeeConfigDeleted(log types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseTokenTransferFeeConfigDeleted") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigDeleted - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryTokenTransferFeeConfigDeleted); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigDeleted) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigDeleted' -type PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call struct { - *mock.Call -} - -// ParseTokenTransferFeeConfigDeleted is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseTokenTransferFeeConfigDeleted(log interface{}) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - return &PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigDeleted", log)} -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, _a1 error) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error)) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(run) - return _c -} - -// ParseTokenTransferFeeConfigUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseTokenTransferFeeConfigUpdated(log types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseTokenTransferFeeConfigUpdated") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryTokenTransferFeeConfigUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigUpdated' -type PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call struct { - *mock.Call -} - -// ParseTokenTransferFeeConfigUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseTokenTransferFeeConfigUpdated(log interface{}) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - return &PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, _a1 error) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error)) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseUsdPerTokenUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseUsdPerTokenUpdated(log types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseUsdPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerTokenUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryUsdPerTokenUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerTokenUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerTokenUpdated' -type PriceRegistryInterface_ParseUsdPerTokenUpdated_Call struct { - *mock.Call -} - -// ParseUsdPerTokenUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseUsdPerTokenUpdated(log interface{}) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - return &PriceRegistryInterface_ParseUsdPerTokenUpdated_Call{Call: _e.mock.On("ParseUsdPerTokenUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerTokenUpdated, _a1 error) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error)) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseUsdPerUnitGasUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseUsdPerUnitGasUpdated(log types.Log) (*price_registry.PriceRegistryUsdPerUnitGasUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseUsdPerUnitGasUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerUnitGasUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryUsdPerUnitGasUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryUsdPerUnitGasUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerUnitGasUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerUnitGasUpdated' -type PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call struct { - *mock.Call -} - -// ParseUsdPerUnitGasUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseUsdPerUnitGasUpdated(log interface{}) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - return &PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call{Call: _e.mock.On("ParseUsdPerUnitGasUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerUnitGasUpdated, _a1 error) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryUsdPerUnitGasUpdated, error)) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs -func (_m *PriceRegistryInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (price_registry.ProcessMessageArgs, error) { - ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - - if len(ret) == 0 { - panic("no return value specified for ProcessMessageArgs") - } - - var r0 price_registry.ProcessMessageArgs - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (price_registry.ProcessMessageArgs, error)); ok { - return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) price_registry.ProcessMessageArgs); ok { - r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - } else { - r0 = ret.Get(0).(price_registry.ProcessMessageArgs) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) error); ok { - r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ProcessMessageArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessMessageArgs' -type PriceRegistryInterface_ProcessMessageArgs_Call struct { - *mock.Call -} - -// ProcessMessageArgs is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - feeToken common.Address -// - feeTokenAmount *big.Int -// - extraArgs []byte -func (_e *PriceRegistryInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}) *PriceRegistryInterface_ProcessMessageArgs_Call { - return &PriceRegistryInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs)} -} - -func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte)) *PriceRegistryInterface_ProcessMessageArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) Return(_a0 price_registry.ProcessMessageArgs, _a1 error) *PriceRegistryInterface_ProcessMessageArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (price_registry.ProcessMessageArgs, error)) *PriceRegistryInterface_ProcessMessageArgs_Call { - _c.Call.Return(run) - return _c -} - -// TransferOwnership provides a mock function with given fields: opts, to -func (_m *PriceRegistryInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - ret := _m.Called(opts, to) - - if len(ret) == 0 { - panic("no return value specified for TransferOwnership") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) (*types.Transaction, error)); ok { - return rf(opts, to) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) *types.Transaction); ok { - r0 = rf(opts, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, common.Address) error); ok { - r1 = rf(opts, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_TransferOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransferOwnership' -type PriceRegistryInterface_TransferOwnership_Call struct { - *mock.Call -} - -// TransferOwnership is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - to common.Address -func (_e *PriceRegistryInterface_Expecter) TransferOwnership(opts interface{}, to interface{}) *PriceRegistryInterface_TransferOwnership_Call { - return &PriceRegistryInterface_TransferOwnership_Call{Call: _e.mock.On("TransferOwnership", opts, to)} -} - -func (_c *PriceRegistryInterface_TransferOwnership_Call) Run(run func(opts *bind.TransactOpts, to common.Address)) *PriceRegistryInterface_TransferOwnership_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_TransferOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_TransferOwnership_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_TransferOwnership_Call) RunAndReturn(run func(*bind.TransactOpts, common.Address) (*types.Transaction, error)) *PriceRegistryInterface_TransferOwnership_Call { - _c.Call.Return(run) - return _c -} - -// TypeAndVersion provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) TypeAndVersion(opts *bind.CallOpts) (string, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for TypeAndVersion") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (string, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) string); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_TypeAndVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TypeAndVersion' -type PriceRegistryInterface_TypeAndVersion_Call struct { - *mock.Call -} - -// TypeAndVersion is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) TypeAndVersion(opts interface{}) *PriceRegistryInterface_TypeAndVersion_Call { - return &PriceRegistryInterface_TypeAndVersion_Call{Call: _e.mock.On("TypeAndVersion", opts)} -} - -func (_c *PriceRegistryInterface_TypeAndVersion_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_TypeAndVersion_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_TypeAndVersion_Call) Return(_a0 string, _a1 error) *PriceRegistryInterface_TypeAndVersion_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_TypeAndVersion_Call) RunAndReturn(run func(*bind.CallOpts) (string, error)) *PriceRegistryInterface_TypeAndVersion_Call { - _c.Call.Return(run) - return _c -} - -// UpdatePrices provides a mock function with given fields: opts, priceUpdates -func (_m *PriceRegistryInterface) UpdatePrices(opts *bind.TransactOpts, priceUpdates price_registry.InternalPriceUpdates) (*types.Transaction, error) { - ret := _m.Called(opts, priceUpdates) - - if len(ret) == 0 { - panic("no return value specified for UpdatePrices") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.InternalPriceUpdates) (*types.Transaction, error)); ok { - return rf(opts, priceUpdates) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.InternalPriceUpdates) *types.Transaction); ok { - r0 = rf(opts, priceUpdates) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, price_registry.InternalPriceUpdates) error); ok { - r1 = rf(opts, priceUpdates) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_UpdatePrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdatePrices' -type PriceRegistryInterface_UpdatePrices_Call struct { - *mock.Call -} - -// UpdatePrices is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - priceUpdates price_registry.InternalPriceUpdates -func (_e *PriceRegistryInterface_Expecter) UpdatePrices(opts interface{}, priceUpdates interface{}) *PriceRegistryInterface_UpdatePrices_Call { - return &PriceRegistryInterface_UpdatePrices_Call{Call: _e.mock.On("UpdatePrices", opts, priceUpdates)} -} - -func (_c *PriceRegistryInterface_UpdatePrices_Call) Run(run func(opts *bind.TransactOpts, priceUpdates price_registry.InternalPriceUpdates)) *PriceRegistryInterface_UpdatePrices_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(price_registry.InternalPriceUpdates)) - }) - return _c -} - -func (_c *PriceRegistryInterface_UpdatePrices_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_UpdatePrices_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_UpdatePrices_Call) RunAndReturn(run func(*bind.TransactOpts, price_registry.InternalPriceUpdates) (*types.Transaction, error)) *PriceRegistryInterface_UpdatePrices_Call { - _c.Call.Return(run) - return _c -} - -// UpdateTokenPriceFeeds provides a mock function with given fields: opts, tokenPriceFeedUpdates -func (_m *PriceRegistryInterface) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []price_registry.PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - ret := _m.Called(opts, tokenPriceFeedUpdates) - - if len(ret) == 0 { - panic("no return value specified for UpdateTokenPriceFeeds") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error)); ok { - return rf(opts, tokenPriceFeedUpdates) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) *types.Transaction); ok { - r0 = rf(opts, tokenPriceFeedUpdates) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) error); ok { - r1 = rf(opts, tokenPriceFeedUpdates) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_UpdateTokenPriceFeeds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTokenPriceFeeds' -type PriceRegistryInterface_UpdateTokenPriceFeeds_Call struct { - *mock.Call -} - -// UpdateTokenPriceFeeds is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - tokenPriceFeedUpdates []price_registry.PriceRegistryTokenPriceFeedUpdate -func (_e *PriceRegistryInterface_Expecter) UpdateTokenPriceFeeds(opts interface{}, tokenPriceFeedUpdates interface{}) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - return &PriceRegistryInterface_UpdateTokenPriceFeeds_Call{Call: _e.mock.On("UpdateTokenPriceFeeds", opts, tokenPriceFeedUpdates)} -} - -func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) Run(run func(opts *bind.TransactOpts, tokenPriceFeedUpdates []price_registry.PriceRegistryTokenPriceFeedUpdate)) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryTokenPriceFeedUpdate)) - }) - return _c -} - -func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error)) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - _c.Call.Return(run) - return _c -} - -// ValidatePoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts -func (_m *PriceRegistryInterface) ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount) error { - ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - - if len(ret) == 0 { - panic("no return value specified for ValidatePoolReturnData") - } - - var r0 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error); ok { - r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// PriceRegistryInterface_ValidatePoolReturnData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidatePoolReturnData' -type PriceRegistryInterface_ValidatePoolReturnData_Call struct { - *mock.Call -} - -// ValidatePoolReturnData is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - rampTokenAmounts []price_registry.InternalRampTokenAmount -// - sourceTokenAmounts []price_registry.ClientEVMTokenAmount -func (_e *PriceRegistryInterface_Expecter) ValidatePoolReturnData(opts interface{}, destChainSelector interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *PriceRegistryInterface_ValidatePoolReturnData_Call { - return &PriceRegistryInterface_ValidatePoolReturnData_Call{Call: _e.mock.On("ValidatePoolReturnData", opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts)} -} - -func (_c *PriceRegistryInterface_ValidatePoolReturnData_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount)) *PriceRegistryInterface_ValidatePoolReturnData_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].([]price_registry.InternalRampTokenAmount), args[3].([]price_registry.ClientEVMTokenAmount)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ValidatePoolReturnData_Call) Return(_a0 error) *PriceRegistryInterface_ValidatePoolReturnData_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *PriceRegistryInterface_ValidatePoolReturnData_Call) RunAndReturn(run func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error) *PriceRegistryInterface_ValidatePoolReturnData_Call { - _c.Call.Return(run) - return _c -} - -// WatchAuthorizedCallerAdded provides a mock function with given fields: opts, sink -func (_m *PriceRegistryInterface) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchAuthorizedCallerAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerAdded' -type PriceRegistryInterface_WatchAuthorizedCallerAdded_Call struct { - *mock.Call -} - -// WatchAuthorizedCallerAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded -func (_e *PriceRegistryInterface_Expecter) WatchAuthorizedCallerAdded(opts interface{}, sink interface{}) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - return &PriceRegistryInterface_WatchAuthorizedCallerAdded_Call{Call: _e.mock.On("WatchAuthorizedCallerAdded", opts, sink)} -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded)) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryAuthorizedCallerAdded)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error)) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchAuthorizedCallerRemoved provides a mock function with given fields: opts, sink -func (_m *PriceRegistryInterface) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchAuthorizedCallerRemoved") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerRemoved' -type PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call struct { - *mock.Call -} - -// WatchAuthorizedCallerRemoved is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved -func (_e *PriceRegistryInterface_Expecter) WatchAuthorizedCallerRemoved(opts interface{}, sink interface{}) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - return &PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call{Call: _e.mock.On("WatchAuthorizedCallerRemoved", opts, sink)} -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved)) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error)) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - _c.Call.Return(run) - return _c -} - -// WatchDestChainAdded provides a mock function with given fields: opts, sink, destChainSelector -func (_m *PriceRegistryInterface) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for WatchDestChainAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) error); ok { - r1 = rf(opts, sink, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainAdded' -type PriceRegistryInterface_WatchDestChainAdded_Call struct { - *mock.Call -} - -// WatchDestChainAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryDestChainAdded -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) WatchDestChainAdded(opts interface{}, sink interface{}, destChainSelector interface{}) *PriceRegistryInterface_WatchDestChainAdded_Call { - return &PriceRegistryInterface_WatchDestChainAdded_Call{Call: _e.mock.On("WatchDestChainAdded", opts, sink, destChainSelector)} -} - -func (_c *PriceRegistryInterface_WatchDestChainAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainAdded, destChainSelector []uint64)) *PriceRegistryInterface_WatchDestChainAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryDestChainAdded), args[2].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainAdded_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchDestChainAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) (event.Subscription, error)) *PriceRegistryInterface_WatchDestChainAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchDestChainConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector -func (_m *PriceRegistryInterface) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for WatchDestChainConfigUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) error); ok { - r1 = rf(opts, sink, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainConfigUpdated' -type PriceRegistryInterface_WatchDestChainConfigUpdated_Call struct { - *mock.Call -} - -// WatchDestChainConfigUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) WatchDestChainConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - return &PriceRegistryInterface_WatchDestChainConfigUpdated_Call{Call: _e.mock.On("WatchDestChainConfigUpdated", opts, sink, destChainSelector)} -} - -func (_c *PriceRegistryInterface_WatchDestChainConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated, destChainSelector []uint64)) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryDestChainConfigUpdated), args[2].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) (event.Subscription, error)) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchFeeTokenAdded provides a mock function with given fields: opts, sink, feeToken -func (_m *PriceRegistryInterface) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, feeToken) - - if len(ret) == 0 { - panic("no return value specified for WatchFeeTokenAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) error); ok { - r1 = rf(opts, sink, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenAdded' -type PriceRegistryInterface_WatchFeeTokenAdded_Call struct { - *mock.Call -} - -// WatchFeeTokenAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryFeeTokenAdded -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchFeeTokenAdded(opts interface{}, sink interface{}, feeToken interface{}) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - return &PriceRegistryInterface_WatchFeeTokenAdded_Call{Call: _e.mock.On("WatchFeeTokenAdded", opts, sink, feeToken)} -} - -func (_c *PriceRegistryInterface_WatchFeeTokenAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenAdded, feeToken []common.Address)) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryFeeTokenAdded), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenAdded_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchFeeTokenRemoved provides a mock function with given fields: opts, sink, feeToken -func (_m *PriceRegistryInterface) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, feeToken) - - if len(ret) == 0 { - panic("no return value specified for WatchFeeTokenRemoved") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) error); ok { - r1 = rf(opts, sink, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenRemoved' -type PriceRegistryInterface_WatchFeeTokenRemoved_Call struct { - *mock.Call -} - -// WatchFeeTokenRemoved is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryFeeTokenRemoved -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchFeeTokenRemoved(opts interface{}, sink interface{}, feeToken interface{}) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - return &PriceRegistryInterface_WatchFeeTokenRemoved_Call{Call: _e.mock.On("WatchFeeTokenRemoved", opts, sink, feeToken)} -} - -func (_c *PriceRegistryInterface_WatchFeeTokenRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenRemoved, feeToken []common.Address)) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryFeeTokenRemoved), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenRemoved_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - _c.Call.Return(run) - return _c -} - -// WatchOwnershipTransferRequested provides a mock function with given fields: opts, sink, from, to -func (_m *PriceRegistryInterface) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, from, to) - - if len(ret) == 0 { - panic("no return value specified for WatchOwnershipTransferRequested") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) error); ok { - r1 = rf(opts, sink, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferRequested' -type PriceRegistryInterface_WatchOwnershipTransferRequested_Call struct { - *mock.Call -} - -// WatchOwnershipTransferRequested is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryOwnershipTransferRequested -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchOwnershipTransferRequested(opts interface{}, sink interface{}, from interface{}, to interface{}) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - return &PriceRegistryInterface_WatchOwnershipTransferRequested_Call{Call: _e.mock.On("WatchOwnershipTransferRequested", opts, sink, from, to)} -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferRequested_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address)) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryOwnershipTransferRequested), args[2].([]common.Address), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferRequested_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// WatchOwnershipTransferred provides a mock function with given fields: opts, sink, from, to -func (_m *PriceRegistryInterface) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, from, to) - - if len(ret) == 0 { - panic("no return value specified for WatchOwnershipTransferred") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) error); ok { - r1 = rf(opts, sink, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferred' -type PriceRegistryInterface_WatchOwnershipTransferred_Call struct { - *mock.Call -} - -// WatchOwnershipTransferred is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryOwnershipTransferred -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchOwnershipTransferred(opts interface{}, sink interface{}, from interface{}, to interface{}) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - return &PriceRegistryInterface_WatchOwnershipTransferred_Call{Call: _e.mock.On("WatchOwnershipTransferred", opts, sink, from, to)} -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferred_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address)) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryOwnershipTransferred), args[2].([]common.Address), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferred_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferred_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// WatchPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, sink, token -func (_m *PriceRegistryInterface) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, token) - - if len(ret) == 0 { - panic("no return value specified for WatchPremiumMultiplierWeiPerEthUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) error); ok { - r1 = rf(opts, sink, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPremiumMultiplierWeiPerEthUpdated' -type PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call struct { - *mock.Call -} - -// WatchPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchPremiumMultiplierWeiPerEthUpdated(opts interface{}, sink interface{}, token interface{}) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - return &PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("WatchPremiumMultiplierWeiPerEthUpdated", opts, sink, token)} -} - -func (_c *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address)) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchPriceFeedPerTokenUpdated provides a mock function with given fields: opts, sink, token -func (_m *PriceRegistryInterface) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, token) - - if len(ret) == 0 { - panic("no return value specified for WatchPriceFeedPerTokenUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) error); ok { - r1 = rf(opts, sink, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPriceFeedPerTokenUpdated' -type PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call struct { - *mock.Call -} - -// WatchPriceFeedPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchPriceFeedPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - return &PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("WatchPriceFeedPerTokenUpdated", opts, sink, token)} -} - -func (_c *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, token []common.Address)) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchPriceUpdaterRemoved provides a mock function with given fields: opts, sink, priceUpdater -func (_m *PriceRegistryInterface) WatchPriceUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceUpdaterRemoved, priceUpdater []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, priceUpdater) - - if len(ret) == 0 { - panic("no return value specified for WatchPriceUpdaterRemoved") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterRemoved, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, priceUpdater) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterRemoved, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, priceUpdater) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterRemoved, []common.Address) error); ok { - r1 = rf(opts, sink, priceUpdater) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchPriceUpdaterRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPriceUpdaterRemoved' -type PriceRegistryInterface_WatchPriceUpdaterRemoved_Call struct { - *mock.Call -} - -// WatchPriceUpdaterRemoved is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryPriceUpdaterRemoved -// - priceUpdater []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchPriceUpdaterRemoved(opts interface{}, sink interface{}, priceUpdater interface{}) *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call { - return &PriceRegistryInterface_WatchPriceUpdaterRemoved_Call{Call: _e.mock.On("WatchPriceUpdaterRemoved", opts, sink, priceUpdater)} -} - -func (_c *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceUpdaterRemoved, priceUpdater []common.Address)) *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryPriceUpdaterRemoved), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterRemoved, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchPriceUpdaterRemoved_Call { - _c.Call.Return(run) - return _c -} - -// WatchPriceUpdaterSet provides a mock function with given fields: opts, sink, priceUpdater -func (_m *PriceRegistryInterface) WatchPriceUpdaterSet(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceUpdaterSet, priceUpdater []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, priceUpdater) - - if len(ret) == 0 { - panic("no return value specified for WatchPriceUpdaterSet") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterSet, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, priceUpdater) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterSet, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, priceUpdater) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterSet, []common.Address) error); ok { - r1 = rf(opts, sink, priceUpdater) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchPriceUpdaterSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPriceUpdaterSet' -type PriceRegistryInterface_WatchPriceUpdaterSet_Call struct { - *mock.Call -} - -// WatchPriceUpdaterSet is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryPriceUpdaterSet -// - priceUpdater []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchPriceUpdaterSet(opts interface{}, sink interface{}, priceUpdater interface{}) *PriceRegistryInterface_WatchPriceUpdaterSet_Call { - return &PriceRegistryInterface_WatchPriceUpdaterSet_Call{Call: _e.mock.On("WatchPriceUpdaterSet", opts, sink, priceUpdater)} -} - -func (_c *PriceRegistryInterface_WatchPriceUpdaterSet_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceUpdaterSet, priceUpdater []common.Address)) *PriceRegistryInterface_WatchPriceUpdaterSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryPriceUpdaterSet), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceUpdaterSet_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchPriceUpdaterSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceUpdaterSet_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceUpdaterSet, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchPriceUpdaterSet_Call { - _c.Call.Return(run) - return _c -} - -// WatchTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, sink, destChainSelector, token -func (_m *PriceRegistryInterface) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for WatchTokenTransferFeeConfigDeleted") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) error); ok { - r1 = rf(opts, sink, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigDeleted' -type PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call struct { - *mock.Call -} - -// WatchTokenTransferFeeConfigDeleted is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchTokenTransferFeeConfigDeleted(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - return &PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigDeleted", opts, sink, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted), args[2].([]uint64), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(run) - return _c -} - -// WatchTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector, token -func (_m *PriceRegistryInterface) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for WatchTokenTransferFeeConfigUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) error); ok { - r1 = rf(opts, sink, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigUpdated' -type PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call struct { - *mock.Call -} - -// WatchTokenTransferFeeConfigUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchTokenTransferFeeConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - return &PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigUpdated", opts, sink, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated), args[2].([]uint64), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchUsdPerTokenUpdated provides a mock function with given fields: opts, sink, token -func (_m *PriceRegistryInterface) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, token) - - if len(ret) == 0 { - panic("no return value specified for WatchUsdPerTokenUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) error); ok { - r1 = rf(opts, sink, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerTokenUpdated' -type PriceRegistryInterface_WatchUsdPerTokenUpdated_Call struct { - *mock.Call -} - -// WatchUsdPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchUsdPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - return &PriceRegistryInterface_WatchUsdPerTokenUpdated_Call{Call: _e.mock.On("WatchUsdPerTokenUpdated", opts, sink, token)} -} - -func (_c *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, token []common.Address)) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryUsdPerTokenUpdated), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchUsdPerUnitGasUpdated provides a mock function with given fields: opts, sink, destChain -func (_m *PriceRegistryInterface) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChain) - - if len(ret) == 0 { - panic("no return value specified for WatchUsdPerUnitGasUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)); ok { - return rf(opts, sink, destChain) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) event.Subscription); ok { - r0 = rf(opts, sink, destChain) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) error); ok { - r1 = rf(opts, sink, destChain) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerUnitGasUpdated' -type PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call struct { - *mock.Call -} - -// WatchUsdPerUnitGasUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated -// - destChain []uint64 -func (_e *PriceRegistryInterface_Expecter) WatchUsdPerUnitGasUpdated(opts interface{}, sink interface{}, destChain interface{}) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - return &PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call{Call: _e.mock.On("WatchUsdPerUnitGasUpdated", opts, sink, destChain)} -} - -func (_c *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, destChain []uint64)) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated), args[2].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - _c.Call.Return(run) - return _c -} - -// NewPriceRegistryInterface creates a new instance of PriceRegistryInterface. 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 NewPriceRegistryInterface(t interface { - mock.TestingT - Cleanup(func()) -}) *PriceRegistryInterface { - mock := &PriceRegistryInterface{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/gethwrappers/ccip/mocks/v1_0_0/evm2_evm_off_ramp_interface.go b/core/gethwrappers/ccip/mocks/v1_0_0/evm2_evm_off_ramp_interface.go deleted file mode 100644 index cefb2c26841..00000000000 --- a/core/gethwrappers/ccip/mocks/v1_0_0/evm2_evm_off_ramp_interface.go +++ /dev/null @@ -1,3603 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mock_contracts - -import ( - big "math/big" - - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - common "github.com/ethereum/go-ethereum/common" - - event "github.com/ethereum/go-ethereum/event" - - evm_2_evm_offramp_1_0_0 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0" - - generated "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" - - mock "github.com/stretchr/testify/mock" - - types "github.com/ethereum/go-ethereum/core/types" -) - -// EVM2EVMOffRampInterface is an autogenerated mock type for the EVM2EVMOffRampInterface type -type EVM2EVMOffRampInterface struct { - mock.Mock -} - -type EVM2EVMOffRampInterface_Expecter struct { - mock *mock.Mock -} - -func (_m *EVM2EVMOffRampInterface) EXPECT() *EVM2EVMOffRampInterface_Expecter { - return &EVM2EVMOffRampInterface_Expecter{mock: &_m.Mock} -} - -// AcceptOwnership provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for AcceptOwnership") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts) (*types.Transaction, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts) *types.Transaction); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_AcceptOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AcceptOwnership' -type EVM2EVMOffRampInterface_AcceptOwnership_Call struct { - *mock.Call -} - -// AcceptOwnership is a helper method to define mock.On call -// - opts *bind.TransactOpts -func (_e *EVM2EVMOffRampInterface_Expecter) AcceptOwnership(opts interface{}) *EVM2EVMOffRampInterface_AcceptOwnership_Call { - return &EVM2EVMOffRampInterface_AcceptOwnership_Call{Call: _e.mock.On("AcceptOwnership", opts)} -} - -func (_c *EVM2EVMOffRampInterface_AcceptOwnership_Call) Run(run func(opts *bind.TransactOpts)) *EVM2EVMOffRampInterface_AcceptOwnership_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_AcceptOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_AcceptOwnership_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind.TransactOpts) (*types.Transaction, error)) *EVM2EVMOffRampInterface_AcceptOwnership_Call { - _c.Call.Return(run) - return _c -} - -// Address provides a mock function with given fields: -func (_m *EVM2EVMOffRampInterface) Address() common.Address { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Address") - } - - var r0 common.Address - if rf, ok := ret.Get(0).(func() common.Address); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - return r0 -} - -// EVM2EVMOffRampInterface_Address_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Address' -type EVM2EVMOffRampInterface_Address_Call struct { - *mock.Call -} - -// Address is a helper method to define mock.On call -func (_e *EVM2EVMOffRampInterface_Expecter) Address() *EVM2EVMOffRampInterface_Address_Call { - return &EVM2EVMOffRampInterface_Address_Call{Call: _e.mock.On("Address")} -} - -func (_c *EVM2EVMOffRampInterface_Address_Call) Run(run func()) *EVM2EVMOffRampInterface_Address_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_Address_Call) Return(_a0 common.Address) *EVM2EVMOffRampInterface_Address_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *EVM2EVMOffRampInterface_Address_Call) RunAndReturn(run func() common.Address) *EVM2EVMOffRampInterface_Address_Call { - _c.Call.Return(run) - return _c -} - -// ApplyPoolUpdates provides a mock function with given fields: opts, removes, adds -func (_m *EVM2EVMOffRampInterface) ApplyPoolUpdates(opts *bind.TransactOpts, removes []evm_2_evm_offramp_1_0_0.InternalPoolUpdate, adds []evm_2_evm_offramp_1_0_0.InternalPoolUpdate) (*types.Transaction, error) { - ret := _m.Called(opts, removes, adds) - - if len(ret) == 0 { - panic("no return value specified for ApplyPoolUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate) (*types.Transaction, error)); ok { - return rf(opts, removes, adds) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate) *types.Transaction); ok { - r0 = rf(opts, removes, adds) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate) error); ok { - r1 = rf(opts, removes, adds) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ApplyPoolUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyPoolUpdates' -type EVM2EVMOffRampInterface_ApplyPoolUpdates_Call struct { - *mock.Call -} - -// ApplyPoolUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - removes []evm_2_evm_offramp_1_0_0.InternalPoolUpdate -// - adds []evm_2_evm_offramp_1_0_0.InternalPoolUpdate -func (_e *EVM2EVMOffRampInterface_Expecter) ApplyPoolUpdates(opts interface{}, removes interface{}, adds interface{}) *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call { - return &EVM2EVMOffRampInterface_ApplyPoolUpdates_Call{Call: _e.mock.On("ApplyPoolUpdates", opts, removes, adds)} -} - -func (_c *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call) Run(run func(opts *bind.TransactOpts, removes []evm_2_evm_offramp_1_0_0.InternalPoolUpdate, adds []evm_2_evm_offramp_1_0_0.InternalPoolUpdate)) *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]evm_2_evm_offramp_1_0_0.InternalPoolUpdate), args[2].([]evm_2_evm_offramp_1_0_0.InternalPoolUpdate)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate, []evm_2_evm_offramp_1_0_0.InternalPoolUpdate) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ApplyPoolUpdates_Call { - _c.Call.Return(run) - return _c -} - -// CcipReceive provides a mock function with given fields: opts, arg0 -func (_m *EVM2EVMOffRampInterface) CcipReceive(opts *bind.CallOpts, arg0 evm_2_evm_offramp_1_0_0.ClientAny2EVMMessage) error { - ret := _m.Called(opts, arg0) - - if len(ret) == 0 { - panic("no return value specified for CcipReceive") - } - - var r0 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, evm_2_evm_offramp_1_0_0.ClientAny2EVMMessage) error); ok { - r0 = rf(opts, arg0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// EVM2EVMOffRampInterface_CcipReceive_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CcipReceive' -type EVM2EVMOffRampInterface_CcipReceive_Call struct { - *mock.Call -} - -// CcipReceive is a helper method to define mock.On call -// - opts *bind.CallOpts -// - arg0 evm_2_evm_offramp_1_0_0.ClientAny2EVMMessage -func (_e *EVM2EVMOffRampInterface_Expecter) CcipReceive(opts interface{}, arg0 interface{}) *EVM2EVMOffRampInterface_CcipReceive_Call { - return &EVM2EVMOffRampInterface_CcipReceive_Call{Call: _e.mock.On("CcipReceive", opts, arg0)} -} - -func (_c *EVM2EVMOffRampInterface_CcipReceive_Call) Run(run func(opts *bind.CallOpts, arg0 evm_2_evm_offramp_1_0_0.ClientAny2EVMMessage)) *EVM2EVMOffRampInterface_CcipReceive_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(evm_2_evm_offramp_1_0_0.ClientAny2EVMMessage)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_CcipReceive_Call) Return(_a0 error) *EVM2EVMOffRampInterface_CcipReceive_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *EVM2EVMOffRampInterface_CcipReceive_Call) RunAndReturn(run func(*bind.CallOpts, evm_2_evm_offramp_1_0_0.ClientAny2EVMMessage) error) *EVM2EVMOffRampInterface_CcipReceive_Call { - _c.Call.Return(run) - return _c -} - -// CurrentRateLimiterState provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) CurrentRateLimiterState(opts *bind.CallOpts) (evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for CurrentRateLimiterState") - } - - var r0 evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_CurrentRateLimiterState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CurrentRateLimiterState' -type EVM2EVMOffRampInterface_CurrentRateLimiterState_Call struct { - *mock.Call -} - -// CurrentRateLimiterState is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) CurrentRateLimiterState(opts interface{}) *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call { - return &EVM2EVMOffRampInterface_CurrentRateLimiterState_Call{Call: _e.mock.On("CurrentRateLimiterState", opts)} -} - -func (_c *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call) Return(_a0 evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket, _a1 error) *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call) RunAndReturn(run func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.RateLimiterTokenBucket, error)) *EVM2EVMOffRampInterface_CurrentRateLimiterState_Call { - _c.Call.Return(run) - return _c -} - -// ExecuteSingleMessage provides a mock function with given fields: opts, message, offchainTokenData -func (_m *EVM2EVMOffRampInterface) ExecuteSingleMessage(opts *bind.TransactOpts, message evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - ret := _m.Called(opts, message, offchainTokenData) - - if len(ret) == 0 { - panic("no return value specified for ExecuteSingleMessage") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage, [][]byte) (*types.Transaction, error)); ok { - return rf(opts, message, offchainTokenData) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage, [][]byte) *types.Transaction); ok { - r0 = rf(opts, message, offchainTokenData) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage, [][]byte) error); ok { - r1 = rf(opts, message, offchainTokenData) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ExecuteSingleMessage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExecuteSingleMessage' -type EVM2EVMOffRampInterface_ExecuteSingleMessage_Call struct { - *mock.Call -} - -// ExecuteSingleMessage is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - message evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage -// - offchainTokenData [][]byte -func (_e *EVM2EVMOffRampInterface_Expecter) ExecuteSingleMessage(opts interface{}, message interface{}, offchainTokenData interface{}) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { - return &EVM2EVMOffRampInterface_ExecuteSingleMessage_Call{Call: _e.mock.On("ExecuteSingleMessage", opts, message, offchainTokenData)} -} - -func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) Run(run func(opts *bind.TransactOpts, message evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage, offchainTokenData [][]byte)) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage), args[2].([][]byte)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage, [][]byte) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ExecuteSingleMessage_Call { - _c.Call.Return(run) - return _c -} - -// FilterAdminSet provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) FilterAdminSet(opts *bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterAdminSet") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterAdminSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAdminSet' -type EVM2EVMOffRampInterface_FilterAdminSet_Call struct { - *mock.Call -} - -// FilterAdminSet is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *EVM2EVMOffRampInterface_Expecter) FilterAdminSet(opts interface{}) *EVM2EVMOffRampInterface_FilterAdminSet_Call { - return &EVM2EVMOffRampInterface_FilterAdminSet_Call{Call: _e.mock.On("FilterAdminSet", opts)} -} - -func (_c *EVM2EVMOffRampInterface_FilterAdminSet_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterAdminSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterAdminSet_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator, _a1 error) *EVM2EVMOffRampInterface_FilterAdminSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterAdminSet_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSetIterator, error)) *EVM2EVMOffRampInterface_FilterAdminSet_Call { - _c.Call.Return(run) - return _c -} - -// FilterConfigSet provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) FilterConfigSet(opts *bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterConfigSet") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterConfigSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterConfigSet' -type EVM2EVMOffRampInterface_FilterConfigSet_Call struct { - *mock.Call -} - -// FilterConfigSet is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *EVM2EVMOffRampInterface_Expecter) FilterConfigSet(opts interface{}) *EVM2EVMOffRampInterface_FilterConfigSet_Call { - return &EVM2EVMOffRampInterface_FilterConfigSet_Call{Call: _e.mock.On("FilterConfigSet", opts)} -} - -func (_c *EVM2EVMOffRampInterface_FilterConfigSet_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterConfigSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterConfigSet_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator, _a1 error) *EVM2EVMOffRampInterface_FilterConfigSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterConfigSet_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSetIterator, error)) *EVM2EVMOffRampInterface_FilterConfigSet_Call { - _c.Call.Return(run) - return _c -} - -// FilterConfigSet0 provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) FilterConfigSet0(opts *bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterConfigSet0") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterConfigSet0_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterConfigSet0' -type EVM2EVMOffRampInterface_FilterConfigSet0_Call struct { - *mock.Call -} - -// FilterConfigSet0 is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *EVM2EVMOffRampInterface_Expecter) FilterConfigSet0(opts interface{}) *EVM2EVMOffRampInterface_FilterConfigSet0_Call { - return &EVM2EVMOffRampInterface_FilterConfigSet0_Call{Call: _e.mock.On("FilterConfigSet0", opts)} -} - -func (_c *EVM2EVMOffRampInterface_FilterConfigSet0_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterConfigSet0_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterConfigSet0_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator, _a1 error) *EVM2EVMOffRampInterface_FilterConfigSet0_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterConfigSet0_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0Iterator, error)) *EVM2EVMOffRampInterface_FilterConfigSet0_Call { - _c.Call.Return(run) - return _c -} - -// FilterExecutionStateChanged provides a mock function with given fields: opts, sequenceNumber, messageId -func (_m *EVM2EVMOffRampInterface) FilterExecutionStateChanged(opts *bind.FilterOpts, sequenceNumber []uint64, messageId [][32]byte) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator, error) { - ret := _m.Called(opts, sequenceNumber, messageId) - - if len(ret) == 0 { - panic("no return value specified for FilterExecutionStateChanged") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, [][32]byte) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator, error)); ok { - return rf(opts, sequenceNumber, messageId) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, [][32]byte) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator); ok { - r0 = rf(opts, sequenceNumber, messageId) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, [][32]byte) error); ok { - r1 = rf(opts, sequenceNumber, messageId) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterExecutionStateChanged' -type EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call struct { - *mock.Call -} - -// FilterExecutionStateChanged is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - sequenceNumber []uint64 -// - messageId [][32]byte -func (_e *EVM2EVMOffRampInterface_Expecter) FilterExecutionStateChanged(opts interface{}, sequenceNumber interface{}, messageId interface{}) *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call { - return &EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call{Call: _e.mock.On("FilterExecutionStateChanged", opts, sequenceNumber, messageId)} -} - -func (_c *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call) Run(run func(opts *bind.FilterOpts, sequenceNumber []uint64, messageId [][32]byte)) *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([][32]byte)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator, _a1 error) *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, [][32]byte) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChangedIterator, error)) *EVM2EVMOffRampInterface_FilterExecutionStateChanged_Call { - _c.Call.Return(run) - return _c -} - -// FilterOwnershipTransferRequested provides a mock function with given fields: opts, from, to -func (_m *EVM2EVMOffRampInterface) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator, error) { - ret := _m.Called(opts, from, to) - - if len(ret) == 0 { - panic("no return value specified for FilterOwnershipTransferRequested") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator, error)); ok { - return rf(opts, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator); ok { - r0 = rf(opts, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferRequested' -type EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call struct { - *mock.Call -} - -// FilterOwnershipTransferRequested is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - from []common.Address -// - to []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) FilterOwnershipTransferRequested(opts interface{}, from interface{}, to interface{}) *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call { - return &EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call{Call: _e.mock.On("FilterOwnershipTransferRequested", opts, from, to)} -} - -func (_c *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator, _a1 error) *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequestedIterator, error)) *EVM2EVMOffRampInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// FilterOwnershipTransferred provides a mock function with given fields: opts, from, to -func (_m *EVM2EVMOffRampInterface) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator, error) { - ret := _m.Called(opts, from, to) - - if len(ret) == 0 { - panic("no return value specified for FilterOwnershipTransferred") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator, error)); ok { - return rf(opts, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator); ok { - r0 = rf(opts, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferred' -type EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call struct { - *mock.Call -} - -// FilterOwnershipTransferred is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - from []common.Address -// - to []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) FilterOwnershipTransferred(opts interface{}, from interface{}, to interface{}) *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call { - return &EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call{Call: _e.mock.On("FilterOwnershipTransferred", opts, from, to)} -} - -func (_c *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator, _a1 error) *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferredIterator, error)) *EVM2EVMOffRampInterface_FilterOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// FilterPoolAdded provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) FilterPoolAdded(opts *bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterPoolAdded") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterPoolAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPoolAdded' -type EVM2EVMOffRampInterface_FilterPoolAdded_Call struct { - *mock.Call -} - -// FilterPoolAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *EVM2EVMOffRampInterface_Expecter) FilterPoolAdded(opts interface{}) *EVM2EVMOffRampInterface_FilterPoolAdded_Call { - return &EVM2EVMOffRampInterface_FilterPoolAdded_Call{Call: _e.mock.On("FilterPoolAdded", opts)} -} - -func (_c *EVM2EVMOffRampInterface_FilterPoolAdded_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterPoolAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterPoolAdded_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator, _a1 error) *EVM2EVMOffRampInterface_FilterPoolAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterPoolAdded_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAddedIterator, error)) *EVM2EVMOffRampInterface_FilterPoolAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterPoolRemoved provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) FilterPoolRemoved(opts *bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterPoolRemoved") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterPoolRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPoolRemoved' -type EVM2EVMOffRampInterface_FilterPoolRemoved_Call struct { - *mock.Call -} - -// FilterPoolRemoved is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *EVM2EVMOffRampInterface_Expecter) FilterPoolRemoved(opts interface{}) *EVM2EVMOffRampInterface_FilterPoolRemoved_Call { - return &EVM2EVMOffRampInterface_FilterPoolRemoved_Call{Call: _e.mock.On("FilterPoolRemoved", opts)} -} - -func (_c *EVM2EVMOffRampInterface_FilterPoolRemoved_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterPoolRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterPoolRemoved_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator, _a1 error) *EVM2EVMOffRampInterface_FilterPoolRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterPoolRemoved_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemovedIterator, error)) *EVM2EVMOffRampInterface_FilterPoolRemoved_Call { - _c.Call.Return(run) - return _c -} - -// FilterSkippedIncorrectNonce provides a mock function with given fields: opts, nonce, sender -func (_m *EVM2EVMOffRampInterface) FilterSkippedIncorrectNonce(opts *bind.FilterOpts, nonce []uint64, sender []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator, error) { - ret := _m.Called(opts, nonce, sender) - - if len(ret) == 0 { - panic("no return value specified for FilterSkippedIncorrectNonce") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator, error)); ok { - return rf(opts, nonce, sender) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator); ok { - r0 = rf(opts, nonce, sender) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { - r1 = rf(opts, nonce, sender) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterSkippedIncorrectNonce' -type EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call struct { - *mock.Call -} - -// FilterSkippedIncorrectNonce is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - nonce []uint64 -// - sender []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) FilterSkippedIncorrectNonce(opts interface{}, nonce interface{}, sender interface{}) *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call { - return &EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call{Call: _e.mock.On("FilterSkippedIncorrectNonce", opts, nonce, sender)} -} - -func (_c *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call) Run(run func(opts *bind.FilterOpts, nonce []uint64, sender []common.Address)) *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator, _a1 error) *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonceIterator, error)) *EVM2EVMOffRampInterface_FilterSkippedIncorrectNonce_Call { - _c.Call.Return(run) - return _c -} - -// FilterSkippedSenderWithPreviousRampMessageInflight provides a mock function with given fields: opts, nonce, sender -func (_m *EVM2EVMOffRampInterface) FilterSkippedSenderWithPreviousRampMessageInflight(opts *bind.FilterOpts, nonce []uint64, sender []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error) { - ret := _m.Called(opts, nonce, sender) - - if len(ret) == 0 { - panic("no return value specified for FilterSkippedSenderWithPreviousRampMessageInflight") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error)); ok { - return rf(opts, nonce, sender) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator); ok { - r0 = rf(opts, nonce, sender) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { - r1 = rf(opts, nonce, sender) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterSkippedSenderWithPreviousRampMessageInflight' -type EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call struct { - *mock.Call -} - -// FilterSkippedSenderWithPreviousRampMessageInflight is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - nonce []uint64 -// - sender []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) FilterSkippedSenderWithPreviousRampMessageInflight(opts interface{}, nonce interface{}, sender interface{}) *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call { - return &EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call{Call: _e.mock.On("FilterSkippedSenderWithPreviousRampMessageInflight", opts, nonce, sender)} -} - -func (_c *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call) Run(run func(opts *bind.FilterOpts, nonce []uint64, sender []common.Address)) *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator, _a1 error) *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error)) *EVM2EVMOffRampInterface_FilterSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Return(run) - return _c -} - -// FilterTransmitted provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) FilterTransmitted(opts *bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterTransmitted") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_FilterTransmitted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTransmitted' -type EVM2EVMOffRampInterface_FilterTransmitted_Call struct { - *mock.Call -} - -// FilterTransmitted is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *EVM2EVMOffRampInterface_Expecter) FilterTransmitted(opts interface{}) *EVM2EVMOffRampInterface_FilterTransmitted_Call { - return &EVM2EVMOffRampInterface_FilterTransmitted_Call{Call: _e.mock.On("FilterTransmitted", opts)} -} - -func (_c *EVM2EVMOffRampInterface_FilterTransmitted_Call) Run(run func(opts *bind.FilterOpts)) *EVM2EVMOffRampInterface_FilterTransmitted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterTransmitted_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator, _a1 error) *EVM2EVMOffRampInterface_FilterTransmitted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_FilterTransmitted_Call) RunAndReturn(run func(*bind.FilterOpts) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmittedIterator, error)) *EVM2EVMOffRampInterface_FilterTransmitted_Call { - _c.Call.Return(run) - return _c -} - -// GetDestinationToken provides a mock function with given fields: opts, sourceToken -func (_m *EVM2EVMOffRampInterface) GetDestinationToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) { - ret := _m.Called(opts, sourceToken) - - if len(ret) == 0 { - panic("no return value specified for GetDestinationToken") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (common.Address, error)); ok { - return rf(opts, sourceToken) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) common.Address); ok { - r0 = rf(opts, sourceToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, sourceToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetDestinationToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestinationToken' -type EVM2EVMOffRampInterface_GetDestinationToken_Call struct { - *mock.Call -} - -// GetDestinationToken is a helper method to define mock.On call -// - opts *bind.CallOpts -// - sourceToken common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) GetDestinationToken(opts interface{}, sourceToken interface{}) *EVM2EVMOffRampInterface_GetDestinationToken_Call { - return &EVM2EVMOffRampInterface_GetDestinationToken_Call{Call: _e.mock.On("GetDestinationToken", opts, sourceToken)} -} - -func (_c *EVM2EVMOffRampInterface_GetDestinationToken_Call) Run(run func(opts *bind.CallOpts, sourceToken common.Address)) *EVM2EVMOffRampInterface_GetDestinationToken_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetDestinationToken_Call) Return(_a0 common.Address, _a1 error) *EVM2EVMOffRampInterface_GetDestinationToken_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetDestinationToken_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (common.Address, error)) *EVM2EVMOffRampInterface_GetDestinationToken_Call { - _c.Call.Return(run) - return _c -} - -// GetDestinationTokens provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) GetDestinationTokens(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetDestinationTokens") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetDestinationTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestinationTokens' -type EVM2EVMOffRampInterface_GetDestinationTokens_Call struct { - *mock.Call -} - -// GetDestinationTokens is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) GetDestinationTokens(opts interface{}) *EVM2EVMOffRampInterface_GetDestinationTokens_Call { - return &EVM2EVMOffRampInterface_GetDestinationTokens_Call{Call: _e.mock.On("GetDestinationTokens", opts)} -} - -func (_c *EVM2EVMOffRampInterface_GetDestinationTokens_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_GetDestinationTokens_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetDestinationTokens_Call) Return(_a0 []common.Address, _a1 error) *EVM2EVMOffRampInterface_GetDestinationTokens_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetDestinationTokens_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *EVM2EVMOffRampInterface_GetDestinationTokens_Call { - _c.Call.Return(run) - return _c -} - -// GetDynamicConfig provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) GetDynamicConfig(opts *bind.CallOpts) (evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetDynamicConfig") - } - - var r0 evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetDynamicConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDynamicConfig' -type EVM2EVMOffRampInterface_GetDynamicConfig_Call struct { - *mock.Call -} - -// GetDynamicConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) GetDynamicConfig(opts interface{}) *EVM2EVMOffRampInterface_GetDynamicConfig_Call { - return &EVM2EVMOffRampInterface_GetDynamicConfig_Call{Call: _e.mock.On("GetDynamicConfig", opts)} -} - -func (_c *EVM2EVMOffRampInterface_GetDynamicConfig_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_GetDynamicConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetDynamicConfig_Call) Return(_a0 evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig, _a1 error) *EVM2EVMOffRampInterface_GetDynamicConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetDynamicConfig_Call) RunAndReturn(run func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig, error)) *EVM2EVMOffRampInterface_GetDynamicConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetExecutionState provides a mock function with given fields: opts, sequenceNumber -func (_m *EVM2EVMOffRampInterface) GetExecutionState(opts *bind.CallOpts, sequenceNumber uint64) (uint8, error) { - ret := _m.Called(opts, sequenceNumber) - - if len(ret) == 0 { - panic("no return value specified for GetExecutionState") - } - - var r0 uint8 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (uint8, error)); ok { - return rf(opts, sequenceNumber) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) uint8); ok { - r0 = rf(opts, sequenceNumber) - } else { - r0 = ret.Get(0).(uint8) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { - r1 = rf(opts, sequenceNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetExecutionState_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetExecutionState' -type EVM2EVMOffRampInterface_GetExecutionState_Call struct { - *mock.Call -} - -// GetExecutionState is a helper method to define mock.On call -// - opts *bind.CallOpts -// - sequenceNumber uint64 -func (_e *EVM2EVMOffRampInterface_Expecter) GetExecutionState(opts interface{}, sequenceNumber interface{}) *EVM2EVMOffRampInterface_GetExecutionState_Call { - return &EVM2EVMOffRampInterface_GetExecutionState_Call{Call: _e.mock.On("GetExecutionState", opts, sequenceNumber)} -} - -func (_c *EVM2EVMOffRampInterface_GetExecutionState_Call) Run(run func(opts *bind.CallOpts, sequenceNumber uint64)) *EVM2EVMOffRampInterface_GetExecutionState_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetExecutionState_Call) Return(_a0 uint8, _a1 error) *EVM2EVMOffRampInterface_GetExecutionState_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetExecutionState_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (uint8, error)) *EVM2EVMOffRampInterface_GetExecutionState_Call { - _c.Call.Return(run) - return _c -} - -// GetPoolByDestToken provides a mock function with given fields: opts, destToken -func (_m *EVM2EVMOffRampInterface) GetPoolByDestToken(opts *bind.CallOpts, destToken common.Address) (common.Address, error) { - ret := _m.Called(opts, destToken) - - if len(ret) == 0 { - panic("no return value specified for GetPoolByDestToken") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (common.Address, error)); ok { - return rf(opts, destToken) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) common.Address); ok { - r0 = rf(opts, destToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, destToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetPoolByDestToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPoolByDestToken' -type EVM2EVMOffRampInterface_GetPoolByDestToken_Call struct { - *mock.Call -} - -// GetPoolByDestToken is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destToken common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) GetPoolByDestToken(opts interface{}, destToken interface{}) *EVM2EVMOffRampInterface_GetPoolByDestToken_Call { - return &EVM2EVMOffRampInterface_GetPoolByDestToken_Call{Call: _e.mock.On("GetPoolByDestToken", opts, destToken)} -} - -func (_c *EVM2EVMOffRampInterface_GetPoolByDestToken_Call) Run(run func(opts *bind.CallOpts, destToken common.Address)) *EVM2EVMOffRampInterface_GetPoolByDestToken_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetPoolByDestToken_Call) Return(_a0 common.Address, _a1 error) *EVM2EVMOffRampInterface_GetPoolByDestToken_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetPoolByDestToken_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (common.Address, error)) *EVM2EVMOffRampInterface_GetPoolByDestToken_Call { - _c.Call.Return(run) - return _c -} - -// GetPoolBySourceToken provides a mock function with given fields: opts, sourceToken -func (_m *EVM2EVMOffRampInterface) GetPoolBySourceToken(opts *bind.CallOpts, sourceToken common.Address) (common.Address, error) { - ret := _m.Called(opts, sourceToken) - - if len(ret) == 0 { - panic("no return value specified for GetPoolBySourceToken") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (common.Address, error)); ok { - return rf(opts, sourceToken) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) common.Address); ok { - r0 = rf(opts, sourceToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, sourceToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetPoolBySourceToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPoolBySourceToken' -type EVM2EVMOffRampInterface_GetPoolBySourceToken_Call struct { - *mock.Call -} - -// GetPoolBySourceToken is a helper method to define mock.On call -// - opts *bind.CallOpts -// - sourceToken common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) GetPoolBySourceToken(opts interface{}, sourceToken interface{}) *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call { - return &EVM2EVMOffRampInterface_GetPoolBySourceToken_Call{Call: _e.mock.On("GetPoolBySourceToken", opts, sourceToken)} -} - -func (_c *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call) Run(run func(opts *bind.CallOpts, sourceToken common.Address)) *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call) Return(_a0 common.Address, _a1 error) *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (common.Address, error)) *EVM2EVMOffRampInterface_GetPoolBySourceToken_Call { - _c.Call.Return(run) - return _c -} - -// GetSenderNonce provides a mock function with given fields: opts, sender -func (_m *EVM2EVMOffRampInterface) GetSenderNonce(opts *bind.CallOpts, sender common.Address) (uint64, error) { - ret := _m.Called(opts, sender) - - if len(ret) == 0 { - panic("no return value specified for GetSenderNonce") - } - - var r0 uint64 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (uint64, error)); ok { - return rf(opts, sender) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) uint64); ok { - r0 = rf(opts, sender) - } else { - r0 = ret.Get(0).(uint64) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, sender) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetSenderNonce_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSenderNonce' -type EVM2EVMOffRampInterface_GetSenderNonce_Call struct { - *mock.Call -} - -// GetSenderNonce is a helper method to define mock.On call -// - opts *bind.CallOpts -// - sender common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) GetSenderNonce(opts interface{}, sender interface{}) *EVM2EVMOffRampInterface_GetSenderNonce_Call { - return &EVM2EVMOffRampInterface_GetSenderNonce_Call{Call: _e.mock.On("GetSenderNonce", opts, sender)} -} - -func (_c *EVM2EVMOffRampInterface_GetSenderNonce_Call) Run(run func(opts *bind.CallOpts, sender common.Address)) *EVM2EVMOffRampInterface_GetSenderNonce_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetSenderNonce_Call) Return(_a0 uint64, _a1 error) *EVM2EVMOffRampInterface_GetSenderNonce_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetSenderNonce_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (uint64, error)) *EVM2EVMOffRampInterface_GetSenderNonce_Call { - _c.Call.Return(run) - return _c -} - -// GetStaticConfig provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) GetStaticConfig(opts *bind.CallOpts) (evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetStaticConfig") - } - - var r0 evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetStaticConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStaticConfig' -type EVM2EVMOffRampInterface_GetStaticConfig_Call struct { - *mock.Call -} - -// GetStaticConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) GetStaticConfig(opts interface{}) *EVM2EVMOffRampInterface_GetStaticConfig_Call { - return &EVM2EVMOffRampInterface_GetStaticConfig_Call{Call: _e.mock.On("GetStaticConfig", opts)} -} - -func (_c *EVM2EVMOffRampInterface_GetStaticConfig_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_GetStaticConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetStaticConfig_Call) Return(_a0 evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig, _a1 error) *EVM2EVMOffRampInterface_GetStaticConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetStaticConfig_Call) RunAndReturn(run func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig, error)) *EVM2EVMOffRampInterface_GetStaticConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetSupportedTokens provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) GetSupportedTokens(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetSupportedTokens") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetSupportedTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSupportedTokens' -type EVM2EVMOffRampInterface_GetSupportedTokens_Call struct { - *mock.Call -} - -// GetSupportedTokens is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) GetSupportedTokens(opts interface{}) *EVM2EVMOffRampInterface_GetSupportedTokens_Call { - return &EVM2EVMOffRampInterface_GetSupportedTokens_Call{Call: _e.mock.On("GetSupportedTokens", opts)} -} - -func (_c *EVM2EVMOffRampInterface_GetSupportedTokens_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_GetSupportedTokens_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetSupportedTokens_Call) Return(_a0 []common.Address, _a1 error) *EVM2EVMOffRampInterface_GetSupportedTokens_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetSupportedTokens_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *EVM2EVMOffRampInterface_GetSupportedTokens_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenLimitAdmin provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetTokenLimitAdmin") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenLimitAdmin' -type EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call struct { - *mock.Call -} - -// GetTokenLimitAdmin is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) GetTokenLimitAdmin(opts interface{}) *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call { - return &EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call{Call: _e.mock.On("GetTokenLimitAdmin", opts)} -} - -func (_c *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call) Return(_a0 common.Address, _a1 error) *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call) RunAndReturn(run func(*bind.CallOpts) (common.Address, error)) *EVM2EVMOffRampInterface_GetTokenLimitAdmin_Call { - _c.Call.Return(run) - return _c -} - -// GetTransmitters provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetTransmitters") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_GetTransmitters_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransmitters' -type EVM2EVMOffRampInterface_GetTransmitters_Call struct { - *mock.Call -} - -// GetTransmitters is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) GetTransmitters(opts interface{}) *EVM2EVMOffRampInterface_GetTransmitters_Call { - return &EVM2EVMOffRampInterface_GetTransmitters_Call{Call: _e.mock.On("GetTransmitters", opts)} -} - -func (_c *EVM2EVMOffRampInterface_GetTransmitters_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_GetTransmitters_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetTransmitters_Call) Return(_a0 []common.Address, _a1 error) *EVM2EVMOffRampInterface_GetTransmitters_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_GetTransmitters_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *EVM2EVMOffRampInterface_GetTransmitters_Call { - _c.Call.Return(run) - return _c -} - -// LatestConfigDetails provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) LatestConfigDetails(opts *bind.CallOpts) (evm_2_evm_offramp_1_0_0.LatestConfigDetails, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for LatestConfigDetails") - } - - var r0 evm_2_evm_offramp_1_0_0.LatestConfigDetails - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.LatestConfigDetails, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) evm_2_evm_offramp_1_0_0.LatestConfigDetails); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(evm_2_evm_offramp_1_0_0.LatestConfigDetails) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_LatestConfigDetails_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestConfigDetails' -type EVM2EVMOffRampInterface_LatestConfigDetails_Call struct { - *mock.Call -} - -// LatestConfigDetails is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) LatestConfigDetails(opts interface{}) *EVM2EVMOffRampInterface_LatestConfigDetails_Call { - return &EVM2EVMOffRampInterface_LatestConfigDetails_Call{Call: _e.mock.On("LatestConfigDetails", opts)} -} - -func (_c *EVM2EVMOffRampInterface_LatestConfigDetails_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_LatestConfigDetails_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_LatestConfigDetails_Call) Return(_a0 evm_2_evm_offramp_1_0_0.LatestConfigDetails, _a1 error) *EVM2EVMOffRampInterface_LatestConfigDetails_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_LatestConfigDetails_Call) RunAndReturn(run func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.LatestConfigDetails, error)) *EVM2EVMOffRampInterface_LatestConfigDetails_Call { - _c.Call.Return(run) - return _c -} - -// LatestConfigDigestAndEpoch provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for LatestConfigDigestAndEpoch") - } - - var r0 evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestConfigDigestAndEpoch' -type EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call struct { - *mock.Call -} - -// LatestConfigDigestAndEpoch is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) LatestConfigDigestAndEpoch(opts interface{}) *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call { - return &EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call{Call: _e.mock.On("LatestConfigDigestAndEpoch", opts)} -} - -func (_c *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call) Return(_a0 evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch, _a1 error) *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call) RunAndReturn(run func(*bind.CallOpts) (evm_2_evm_offramp_1_0_0.LatestConfigDigestAndEpoch, error)) *EVM2EVMOffRampInterface_LatestConfigDigestAndEpoch_Call { - _c.Call.Return(run) - return _c -} - -// ManuallyExecute provides a mock function with given fields: opts, report, gasLimitOverrides -func (_m *EVM2EVMOffRampInterface) ManuallyExecute(opts *bind.TransactOpts, report evm_2_evm_offramp_1_0_0.InternalExecutionReport, gasLimitOverrides []*big.Int) (*types.Transaction, error) { - ret := _m.Called(opts, report, gasLimitOverrides) - - if len(ret) == 0 { - panic("no return value specified for ManuallyExecute") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalExecutionReport, []*big.Int) (*types.Transaction, error)); ok { - return rf(opts, report, gasLimitOverrides) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalExecutionReport, []*big.Int) *types.Transaction); ok { - r0 = rf(opts, report, gasLimitOverrides) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalExecutionReport, []*big.Int) error); ok { - r1 = rf(opts, report, gasLimitOverrides) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ManuallyExecute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ManuallyExecute' -type EVM2EVMOffRampInterface_ManuallyExecute_Call struct { - *mock.Call -} - -// ManuallyExecute is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - report evm_2_evm_offramp_1_0_0.InternalExecutionReport -// - gasLimitOverrides []*big.Int -func (_e *EVM2EVMOffRampInterface_Expecter) ManuallyExecute(opts interface{}, report interface{}, gasLimitOverrides interface{}) *EVM2EVMOffRampInterface_ManuallyExecute_Call { - return &EVM2EVMOffRampInterface_ManuallyExecute_Call{Call: _e.mock.On("ManuallyExecute", opts, report, gasLimitOverrides)} -} - -func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) Run(run func(opts *bind.TransactOpts, report evm_2_evm_offramp_1_0_0.InternalExecutionReport, gasLimitOverrides []*big.Int)) *EVM2EVMOffRampInterface_ManuallyExecute_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp_1_0_0.InternalExecutionReport), args[2].([]*big.Int)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_ManuallyExecute_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ManuallyExecute_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.InternalExecutionReport, []*big.Int) (*types.Transaction, error)) *EVM2EVMOffRampInterface_ManuallyExecute_Call { - _c.Call.Return(run) - return _c -} - -// Owner provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) Owner(opts *bind.CallOpts) (common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for Owner") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_Owner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Owner' -type EVM2EVMOffRampInterface_Owner_Call struct { - *mock.Call -} - -// Owner is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) Owner(opts interface{}) *EVM2EVMOffRampInterface_Owner_Call { - return &EVM2EVMOffRampInterface_Owner_Call{Call: _e.mock.On("Owner", opts)} -} - -func (_c *EVM2EVMOffRampInterface_Owner_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_Owner_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_Owner_Call) Return(_a0 common.Address, _a1 error) *EVM2EVMOffRampInterface_Owner_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_Owner_Call) RunAndReturn(run func(*bind.CallOpts) (common.Address, error)) *EVM2EVMOffRampInterface_Owner_Call { - _c.Call.Return(run) - return _c -} - -// ParseAdminSet provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseAdminSet(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseAdminSet") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseAdminSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAdminSet' -type EVM2EVMOffRampInterface_ParseAdminSet_Call struct { - *mock.Call -} - -// ParseAdminSet is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseAdminSet(log interface{}) *EVM2EVMOffRampInterface_ParseAdminSet_Call { - return &EVM2EVMOffRampInterface_ParseAdminSet_Call{Call: _e.mock.On("ParseAdminSet", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseAdminSet_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseAdminSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseAdminSet_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet, _a1 error) *EVM2EVMOffRampInterface_ParseAdminSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseAdminSet_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet, error)) *EVM2EVMOffRampInterface_ParseAdminSet_Call { - _c.Call.Return(run) - return _c -} - -// ParseConfigSet provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseConfigSet(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseConfigSet") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseConfigSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseConfigSet' -type EVM2EVMOffRampInterface_ParseConfigSet_Call struct { - *mock.Call -} - -// ParseConfigSet is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseConfigSet(log interface{}) *EVM2EVMOffRampInterface_ParseConfigSet_Call { - return &EVM2EVMOffRampInterface_ParseConfigSet_Call{Call: _e.mock.On("ParseConfigSet", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseConfigSet_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseConfigSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseConfigSet_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet, _a1 error) *EVM2EVMOffRampInterface_ParseConfigSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseConfigSet_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet, error)) *EVM2EVMOffRampInterface_ParseConfigSet_Call { - _c.Call.Return(run) - return _c -} - -// ParseConfigSet0 provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseConfigSet0(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseConfigSet0") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0 - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseConfigSet0_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseConfigSet0' -type EVM2EVMOffRampInterface_ParseConfigSet0_Call struct { - *mock.Call -} - -// ParseConfigSet0 is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseConfigSet0(log interface{}) *EVM2EVMOffRampInterface_ParseConfigSet0_Call { - return &EVM2EVMOffRampInterface_ParseConfigSet0_Call{Call: _e.mock.On("ParseConfigSet0", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseConfigSet0_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseConfigSet0_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseConfigSet0_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0, _a1 error) *EVM2EVMOffRampInterface_ParseConfigSet0_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseConfigSet0_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0, error)) *EVM2EVMOffRampInterface_ParseConfigSet0_Call { - _c.Call.Return(run) - return _c -} - -// ParseExecutionStateChanged provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseExecutionStateChanged(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseExecutionStateChanged") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseExecutionStateChanged' -type EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call struct { - *mock.Call -} - -// ParseExecutionStateChanged is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseExecutionStateChanged(log interface{}) *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call { - return &EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call{Call: _e.mock.On("ParseExecutionStateChanged", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, _a1 error) *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, error)) *EVM2EVMOffRampInterface_ParseExecutionStateChanged_Call { - _c.Call.Return(run) - return _c -} - -// ParseLog provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseLog(log types.Log) (generated.AbigenLog, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseLog") - } - - var r0 generated.AbigenLog - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (generated.AbigenLog, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) generated.AbigenLog); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(generated.AbigenLog) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseLog_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseLog' -type EVM2EVMOffRampInterface_ParseLog_Call struct { - *mock.Call -} - -// ParseLog is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseLog(log interface{}) *EVM2EVMOffRampInterface_ParseLog_Call { - return &EVM2EVMOffRampInterface_ParseLog_Call{Call: _e.mock.On("ParseLog", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseLog_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseLog_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseLog_Call) Return(_a0 generated.AbigenLog, _a1 error) *EVM2EVMOffRampInterface_ParseLog_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseLog_Call) RunAndReturn(run func(types.Log) (generated.AbigenLog, error)) *EVM2EVMOffRampInterface_ParseLog_Call { - _c.Call.Return(run) - return _c -} - -// ParseOwnershipTransferRequested provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseOwnershipTransferRequested(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseOwnershipTransferRequested") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferRequested' -type EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call struct { - *mock.Call -} - -// ParseOwnershipTransferRequested is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseOwnershipTransferRequested(log interface{}) *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call { - return &EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call{Call: _e.mock.On("ParseOwnershipTransferRequested", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, _a1 error) *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, error)) *EVM2EVMOffRampInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// ParseOwnershipTransferred provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseOwnershipTransferred(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseOwnershipTransferred") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferred' -type EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call struct { - *mock.Call -} - -// ParseOwnershipTransferred is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseOwnershipTransferred(log interface{}) *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call { - return &EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call{Call: _e.mock.On("ParseOwnershipTransferred", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, _a1 error) *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, error)) *EVM2EVMOffRampInterface_ParseOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// ParsePoolAdded provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParsePoolAdded(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePoolAdded") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParsePoolAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePoolAdded' -type EVM2EVMOffRampInterface_ParsePoolAdded_Call struct { - *mock.Call -} - -// ParsePoolAdded is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParsePoolAdded(log interface{}) *EVM2EVMOffRampInterface_ParsePoolAdded_Call { - return &EVM2EVMOffRampInterface_ParsePoolAdded_Call{Call: _e.mock.On("ParsePoolAdded", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParsePoolAdded_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParsePoolAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParsePoolAdded_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded, _a1 error) *EVM2EVMOffRampInterface_ParsePoolAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParsePoolAdded_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded, error)) *EVM2EVMOffRampInterface_ParsePoolAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParsePoolRemoved provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParsePoolRemoved(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePoolRemoved") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParsePoolRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePoolRemoved' -type EVM2EVMOffRampInterface_ParsePoolRemoved_Call struct { - *mock.Call -} - -// ParsePoolRemoved is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParsePoolRemoved(log interface{}) *EVM2EVMOffRampInterface_ParsePoolRemoved_Call { - return &EVM2EVMOffRampInterface_ParsePoolRemoved_Call{Call: _e.mock.On("ParsePoolRemoved", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParsePoolRemoved_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParsePoolRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParsePoolRemoved_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved, _a1 error) *EVM2EVMOffRampInterface_ParsePoolRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParsePoolRemoved_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved, error)) *EVM2EVMOffRampInterface_ParsePoolRemoved_Call { - _c.Call.Return(run) - return _c -} - -// ParseSkippedIncorrectNonce provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseSkippedIncorrectNonce(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseSkippedIncorrectNonce") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseSkippedIncorrectNonce' -type EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call struct { - *mock.Call -} - -// ParseSkippedIncorrectNonce is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseSkippedIncorrectNonce(log interface{}) *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call { - return &EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call{Call: _e.mock.On("ParseSkippedIncorrectNonce", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, _a1 error) *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, error)) *EVM2EVMOffRampInterface_ParseSkippedIncorrectNonce_Call { - _c.Call.Return(run) - return _c -} - -// ParseSkippedSenderWithPreviousRampMessageInflight provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseSkippedSenderWithPreviousRampMessageInflight(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseSkippedSenderWithPreviousRampMessageInflight") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseSkippedSenderWithPreviousRampMessageInflight' -type EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call struct { - *mock.Call -} - -// ParseSkippedSenderWithPreviousRampMessageInflight is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseSkippedSenderWithPreviousRampMessageInflight(log interface{}) *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call { - return &EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call{Call: _e.mock.On("ParseSkippedSenderWithPreviousRampMessageInflight", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, _a1 error) *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, error)) *EVM2EVMOffRampInterface_ParseSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Return(run) - return _c -} - -// ParseTransmitted provides a mock function with given fields: log -func (_m *EVM2EVMOffRampInterface) ParseTransmitted(log types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseTransmitted") - } - - var r0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_ParseTransmitted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTransmitted' -type EVM2EVMOffRampInterface_ParseTransmitted_Call struct { - *mock.Call -} - -// ParseTransmitted is a helper method to define mock.On call -// - log types.Log -func (_e *EVM2EVMOffRampInterface_Expecter) ParseTransmitted(log interface{}) *EVM2EVMOffRampInterface_ParseTransmitted_Call { - return &EVM2EVMOffRampInterface_ParseTransmitted_Call{Call: _e.mock.On("ParseTransmitted", log)} -} - -func (_c *EVM2EVMOffRampInterface_ParseTransmitted_Call) Run(run func(log types.Log)) *EVM2EVMOffRampInterface_ParseTransmitted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseTransmitted_Call) Return(_a0 *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted, _a1 error) *EVM2EVMOffRampInterface_ParseTransmitted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_ParseTransmitted_Call) RunAndReturn(run func(types.Log) (*evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted, error)) *EVM2EVMOffRampInterface_ParseTransmitted_Call { - _c.Call.Return(run) - return _c -} - -// SetAdmin provides a mock function with given fields: opts, newAdmin -func (_m *EVM2EVMOffRampInterface) SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { - ret := _m.Called(opts, newAdmin) - - if len(ret) == 0 { - panic("no return value specified for SetAdmin") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) (*types.Transaction, error)); ok { - return rf(opts, newAdmin) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) *types.Transaction); ok { - r0 = rf(opts, newAdmin) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, common.Address) error); ok { - r1 = rf(opts, newAdmin) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_SetAdmin_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAdmin' -type EVM2EVMOffRampInterface_SetAdmin_Call struct { - *mock.Call -} - -// SetAdmin is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - newAdmin common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) SetAdmin(opts interface{}, newAdmin interface{}) *EVM2EVMOffRampInterface_SetAdmin_Call { - return &EVM2EVMOffRampInterface_SetAdmin_Call{Call: _e.mock.On("SetAdmin", opts, newAdmin)} -} - -func (_c *EVM2EVMOffRampInterface_SetAdmin_Call) Run(run func(opts *bind.TransactOpts, newAdmin common.Address)) *EVM2EVMOffRampInterface_SetAdmin_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_SetAdmin_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_SetAdmin_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_SetAdmin_Call) RunAndReturn(run func(*bind.TransactOpts, common.Address) (*types.Transaction, error)) *EVM2EVMOffRampInterface_SetAdmin_Call { - _c.Call.Return(run) - return _c -} - -// SetOCR2Config provides a mock function with given fields: opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig -func (_m *EVM2EVMOffRampInterface) SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { - ret := _m.Called(opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) - - if len(ret) == 0 { - panic("no return value specified for SetOCR2Config") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address, uint8, []byte, uint64, []byte) (*types.Transaction, error)); ok { - return rf(opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address, uint8, []byte, uint64, []byte) *types.Transaction); ok { - r0 = rf(opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []common.Address, []common.Address, uint8, []byte, uint64, []byte) error); ok { - r1 = rf(opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_SetOCR2Config_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetOCR2Config' -type EVM2EVMOffRampInterface_SetOCR2Config_Call struct { - *mock.Call -} - -// SetOCR2Config is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - signers []common.Address -// - transmitters []common.Address -// - f uint8 -// - onchainConfig []byte -// - offchainConfigVersion uint64 -// - offchainConfig []byte -func (_e *EVM2EVMOffRampInterface_Expecter) SetOCR2Config(opts interface{}, signers interface{}, transmitters interface{}, f interface{}, onchainConfig interface{}, offchainConfigVersion interface{}, offchainConfig interface{}) *EVM2EVMOffRampInterface_SetOCR2Config_Call { - return &EVM2EVMOffRampInterface_SetOCR2Config_Call{Call: _e.mock.On("SetOCR2Config", opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig)} -} - -func (_c *EVM2EVMOffRampInterface_SetOCR2Config_Call) Run(run func(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte)) *EVM2EVMOffRampInterface_SetOCR2Config_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]common.Address), args[2].([]common.Address), args[3].(uint8), args[4].([]byte), args[5].(uint64), args[6].([]byte)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_SetOCR2Config_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_SetOCR2Config_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_SetOCR2Config_Call) RunAndReturn(run func(*bind.TransactOpts, []common.Address, []common.Address, uint8, []byte, uint64, []byte) (*types.Transaction, error)) *EVM2EVMOffRampInterface_SetOCR2Config_Call { - _c.Call.Return(run) - return _c -} - -// SetRateLimiterConfig provides a mock function with given fields: opts, config -func (_m *EVM2EVMOffRampInterface) SetRateLimiterConfig(opts *bind.TransactOpts, config evm_2_evm_offramp_1_0_0.RateLimiterConfig) (*types.Transaction, error) { - ret := _m.Called(opts, config) - - if len(ret) == 0 { - panic("no return value specified for SetRateLimiterConfig") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.RateLimiterConfig) (*types.Transaction, error)); ok { - return rf(opts, config) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.RateLimiterConfig) *types.Transaction); ok { - r0 = rf(opts, config) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.RateLimiterConfig) error); ok { - r1 = rf(opts, config) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_SetRateLimiterConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetRateLimiterConfig' -type EVM2EVMOffRampInterface_SetRateLimiterConfig_Call struct { - *mock.Call -} - -// SetRateLimiterConfig is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - config evm_2_evm_offramp_1_0_0.RateLimiterConfig -func (_e *EVM2EVMOffRampInterface_Expecter) SetRateLimiterConfig(opts interface{}, config interface{}) *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call { - return &EVM2EVMOffRampInterface_SetRateLimiterConfig_Call{Call: _e.mock.On("SetRateLimiterConfig", opts, config)} -} - -func (_c *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call) Run(run func(opts *bind.TransactOpts, config evm_2_evm_offramp_1_0_0.RateLimiterConfig)) *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(evm_2_evm_offramp_1_0_0.RateLimiterConfig)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call) RunAndReturn(run func(*bind.TransactOpts, evm_2_evm_offramp_1_0_0.RateLimiterConfig) (*types.Transaction, error)) *EVM2EVMOffRampInterface_SetRateLimiterConfig_Call { - _c.Call.Return(run) - return _c -} - -// TransferOwnership provides a mock function with given fields: opts, to -func (_m *EVM2EVMOffRampInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - ret := _m.Called(opts, to) - - if len(ret) == 0 { - panic("no return value specified for TransferOwnership") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) (*types.Transaction, error)); ok { - return rf(opts, to) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) *types.Transaction); ok { - r0 = rf(opts, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, common.Address) error); ok { - r1 = rf(opts, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_TransferOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransferOwnership' -type EVM2EVMOffRampInterface_TransferOwnership_Call struct { - *mock.Call -} - -// TransferOwnership is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - to common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) TransferOwnership(opts interface{}, to interface{}) *EVM2EVMOffRampInterface_TransferOwnership_Call { - return &EVM2EVMOffRampInterface_TransferOwnership_Call{Call: _e.mock.On("TransferOwnership", opts, to)} -} - -func (_c *EVM2EVMOffRampInterface_TransferOwnership_Call) Run(run func(opts *bind.TransactOpts, to common.Address)) *EVM2EVMOffRampInterface_TransferOwnership_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_TransferOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_TransferOwnership_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_TransferOwnership_Call) RunAndReturn(run func(*bind.TransactOpts, common.Address) (*types.Transaction, error)) *EVM2EVMOffRampInterface_TransferOwnership_Call { - _c.Call.Return(run) - return _c -} - -// Transmit provides a mock function with given fields: opts, reportContext, report, rs, ss, arg4 -func (_m *EVM2EVMOffRampInterface) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte) (*types.Transaction, error) { - ret := _m.Called(opts, reportContext, report, rs, ss, arg4) - - if len(ret) == 0 { - panic("no return value specified for Transmit") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, [3][32]byte, []byte, [][32]byte, [][32]byte, [32]byte) (*types.Transaction, error)); ok { - return rf(opts, reportContext, report, rs, ss, arg4) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, [3][32]byte, []byte, [][32]byte, [][32]byte, [32]byte) *types.Transaction); ok { - r0 = rf(opts, reportContext, report, rs, ss, arg4) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, [3][32]byte, []byte, [][32]byte, [][32]byte, [32]byte) error); ok { - r1 = rf(opts, reportContext, report, rs, ss, arg4) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_Transmit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Transmit' -type EVM2EVMOffRampInterface_Transmit_Call struct { - *mock.Call -} - -// Transmit is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - reportContext [3][32]byte -// - report []byte -// - rs [][32]byte -// - ss [][32]byte -// - arg4 [32]byte -func (_e *EVM2EVMOffRampInterface_Expecter) Transmit(opts interface{}, reportContext interface{}, report interface{}, rs interface{}, ss interface{}, arg4 interface{}) *EVM2EVMOffRampInterface_Transmit_Call { - return &EVM2EVMOffRampInterface_Transmit_Call{Call: _e.mock.On("Transmit", opts, reportContext, report, rs, ss, arg4)} -} - -func (_c *EVM2EVMOffRampInterface_Transmit_Call) Run(run func(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte)) *EVM2EVMOffRampInterface_Transmit_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([3][32]byte), args[2].([]byte), args[3].([][32]byte), args[4].([][32]byte), args[5].([32]byte)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_Transmit_Call) Return(_a0 *types.Transaction, _a1 error) *EVM2EVMOffRampInterface_Transmit_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_Transmit_Call) RunAndReturn(run func(*bind.TransactOpts, [3][32]byte, []byte, [][32]byte, [][32]byte, [32]byte) (*types.Transaction, error)) *EVM2EVMOffRampInterface_Transmit_Call { - _c.Call.Return(run) - return _c -} - -// TypeAndVersion provides a mock function with given fields: opts -func (_m *EVM2EVMOffRampInterface) TypeAndVersion(opts *bind.CallOpts) (string, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for TypeAndVersion") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (string, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) string); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_TypeAndVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TypeAndVersion' -type EVM2EVMOffRampInterface_TypeAndVersion_Call struct { - *mock.Call -} - -// TypeAndVersion is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *EVM2EVMOffRampInterface_Expecter) TypeAndVersion(opts interface{}) *EVM2EVMOffRampInterface_TypeAndVersion_Call { - return &EVM2EVMOffRampInterface_TypeAndVersion_Call{Call: _e.mock.On("TypeAndVersion", opts)} -} - -func (_c *EVM2EVMOffRampInterface_TypeAndVersion_Call) Run(run func(opts *bind.CallOpts)) *EVM2EVMOffRampInterface_TypeAndVersion_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_TypeAndVersion_Call) Return(_a0 string, _a1 error) *EVM2EVMOffRampInterface_TypeAndVersion_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_TypeAndVersion_Call) RunAndReturn(run func(*bind.CallOpts) (string, error)) *EVM2EVMOffRampInterface_TypeAndVersion_Call { - _c.Call.Return(run) - return _c -} - -// WatchAdminSet provides a mock function with given fields: opts, sink -func (_m *EVM2EVMOffRampInterface) WatchAdminSet(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchAdminSet") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchAdminSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAdminSet' -type EVM2EVMOffRampInterface_WatchAdminSet_Call struct { - *mock.Call -} - -// WatchAdminSet is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet -func (_e *EVM2EVMOffRampInterface_Expecter) WatchAdminSet(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchAdminSet_Call { - return &EVM2EVMOffRampInterface_WatchAdminSet_Call{Call: _e.mock.On("WatchAdminSet", opts, sink)} -} - -func (_c *EVM2EVMOffRampInterface_WatchAdminSet_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet)) *EVM2EVMOffRampInterface_WatchAdminSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchAdminSet_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchAdminSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchAdminSet_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampAdminSet) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchAdminSet_Call { - _c.Call.Return(run) - return _c -} - -// WatchConfigSet provides a mock function with given fields: opts, sink -func (_m *EVM2EVMOffRampInterface) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchConfigSet") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchConfigSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchConfigSet' -type EVM2EVMOffRampInterface_WatchConfigSet_Call struct { - *mock.Call -} - -// WatchConfigSet is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet -func (_e *EVM2EVMOffRampInterface_Expecter) WatchConfigSet(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchConfigSet_Call { - return &EVM2EVMOffRampInterface_WatchConfigSet_Call{Call: _e.mock.On("WatchConfigSet", opts, sink)} -} - -func (_c *EVM2EVMOffRampInterface_WatchConfigSet_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet)) *EVM2EVMOffRampInterface_WatchConfigSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchConfigSet_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchConfigSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchConfigSet_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchConfigSet_Call { - _c.Call.Return(run) - return _c -} - -// WatchConfigSet0 provides a mock function with given fields: opts, sink -func (_m *EVM2EVMOffRampInterface) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchConfigSet0") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchConfigSet0_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchConfigSet0' -type EVM2EVMOffRampInterface_WatchConfigSet0_Call struct { - *mock.Call -} - -// WatchConfigSet0 is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0 -func (_e *EVM2EVMOffRampInterface_Expecter) WatchConfigSet0(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchConfigSet0_Call { - return &EVM2EVMOffRampInterface_WatchConfigSet0_Call{Call: _e.mock.On("WatchConfigSet0", opts, sink)} -} - -func (_c *EVM2EVMOffRampInterface_WatchConfigSet0_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0)) *EVM2EVMOffRampInterface_WatchConfigSet0_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchConfigSet0_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchConfigSet0_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchConfigSet0_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampConfigSet0) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchConfigSet0_Call { - _c.Call.Return(run) - return _c -} - -// WatchExecutionStateChanged provides a mock function with given fields: opts, sink, sequenceNumber, messageId -func (_m *EVM2EVMOffRampInterface) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { - ret := _m.Called(opts, sink, sequenceNumber, messageId) - - if len(ret) == 0 { - panic("no return value specified for WatchExecutionStateChanged") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, []uint64, [][32]byte) (event.Subscription, error)); ok { - return rf(opts, sink, sequenceNumber, messageId) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, []uint64, [][32]byte) event.Subscription); ok { - r0 = rf(opts, sink, sequenceNumber, messageId) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, []uint64, [][32]byte) error); ok { - r1 = rf(opts, sink, sequenceNumber, messageId) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchExecutionStateChanged' -type EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call struct { - *mock.Call -} - -// WatchExecutionStateChanged is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged -// - sequenceNumber []uint64 -// - messageId [][32]byte -func (_e *EVM2EVMOffRampInterface_Expecter) WatchExecutionStateChanged(opts interface{}, sink interface{}, sequenceNumber interface{}, messageId interface{}) *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call { - return &EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call{Call: _e.mock.On("WatchExecutionStateChanged", opts, sink, sequenceNumber, messageId)} -} - -func (_c *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, sequenceNumber []uint64, messageId [][32]byte)) *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged), args[2].([]uint64), args[3].([][32]byte)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampExecutionStateChanged, []uint64, [][32]byte) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchExecutionStateChanged_Call { - _c.Call.Return(run) - return _c -} - -// WatchOwnershipTransferRequested provides a mock function with given fields: opts, sink, from, to -func (_m *EVM2EVMOffRampInterface) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, from, to) - - if len(ret) == 0 { - panic("no return value specified for WatchOwnershipTransferRequested") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, []common.Address, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, []common.Address, []common.Address) error); ok { - r1 = rf(opts, sink, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferRequested' -type EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call struct { - *mock.Call -} - -// WatchOwnershipTransferRequested is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested -// - from []common.Address -// - to []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) WatchOwnershipTransferRequested(opts interface{}, sink interface{}, from interface{}, to interface{}) *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call { - return &EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call{Call: _e.mock.On("WatchOwnershipTransferRequested", opts, sink, from, to)} -} - -func (_c *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, from []common.Address, to []common.Address)) *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested), args[2].([]common.Address), args[3].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// WatchOwnershipTransferred provides a mock function with given fields: opts, sink, from, to -func (_m *EVM2EVMOffRampInterface) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, from, to) - - if len(ret) == 0 { - panic("no return value specified for WatchOwnershipTransferred") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, []common.Address, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, []common.Address, []common.Address) error); ok { - r1 = rf(opts, sink, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferred' -type EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call struct { - *mock.Call -} - -// WatchOwnershipTransferred is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred -// - from []common.Address -// - to []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) WatchOwnershipTransferred(opts interface{}, sink interface{}, from interface{}, to interface{}) *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call { - return &EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call{Call: _e.mock.On("WatchOwnershipTransferred", opts, sink, from, to)} -} - -func (_c *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, from []common.Address, to []common.Address)) *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred), args[2].([]common.Address), args[3].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// WatchPoolAdded provides a mock function with given fields: opts, sink -func (_m *EVM2EVMOffRampInterface) WatchPoolAdded(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchPoolAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchPoolAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPoolAdded' -type EVM2EVMOffRampInterface_WatchPoolAdded_Call struct { - *mock.Call -} - -// WatchPoolAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded -func (_e *EVM2EVMOffRampInterface_Expecter) WatchPoolAdded(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchPoolAdded_Call { - return &EVM2EVMOffRampInterface_WatchPoolAdded_Call{Call: _e.mock.On("WatchPoolAdded", opts, sink)} -} - -func (_c *EVM2EVMOffRampInterface_WatchPoolAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded)) *EVM2EVMOffRampInterface_WatchPoolAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchPoolAdded_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchPoolAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchPoolAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolAdded) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchPoolAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchPoolRemoved provides a mock function with given fields: opts, sink -func (_m *EVM2EVMOffRampInterface) WatchPoolRemoved(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchPoolRemoved") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchPoolRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPoolRemoved' -type EVM2EVMOffRampInterface_WatchPoolRemoved_Call struct { - *mock.Call -} - -// WatchPoolRemoved is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved -func (_e *EVM2EVMOffRampInterface_Expecter) WatchPoolRemoved(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchPoolRemoved_Call { - return &EVM2EVMOffRampInterface_WatchPoolRemoved_Call{Call: _e.mock.On("WatchPoolRemoved", opts, sink)} -} - -func (_c *EVM2EVMOffRampInterface_WatchPoolRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved)) *EVM2EVMOffRampInterface_WatchPoolRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchPoolRemoved_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchPoolRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchPoolRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampPoolRemoved) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchPoolRemoved_Call { - _c.Call.Return(run) - return _c -} - -// WatchSkippedIncorrectNonce provides a mock function with given fields: opts, sink, nonce, sender -func (_m *EVM2EVMOffRampInterface) WatchSkippedIncorrectNonce(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, nonce []uint64, sender []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, nonce, sender) - - if len(ret) == 0 { - panic("no return value specified for WatchSkippedIncorrectNonce") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, []uint64, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, nonce, sender) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, []uint64, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, nonce, sender) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, []uint64, []common.Address) error); ok { - r1 = rf(opts, sink, nonce, sender) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchSkippedIncorrectNonce' -type EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call struct { - *mock.Call -} - -// WatchSkippedIncorrectNonce is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce -// - nonce []uint64 -// - sender []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) WatchSkippedIncorrectNonce(opts interface{}, sink interface{}, nonce interface{}, sender interface{}) *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call { - return &EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call{Call: _e.mock.On("WatchSkippedIncorrectNonce", opts, sink, nonce, sender)} -} - -func (_c *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, nonce []uint64, sender []common.Address)) *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce), args[2].([]uint64), args[3].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedIncorrectNonce, []uint64, []common.Address) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchSkippedIncorrectNonce_Call { - _c.Call.Return(run) - return _c -} - -// WatchSkippedSenderWithPreviousRampMessageInflight provides a mock function with given fields: opts, sink, nonce, sender -func (_m *EVM2EVMOffRampInterface) WatchSkippedSenderWithPreviousRampMessageInflight(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, nonce []uint64, sender []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, nonce, sender) - - if len(ret) == 0 { - panic("no return value specified for WatchSkippedSenderWithPreviousRampMessageInflight") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, []uint64, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, nonce, sender) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, []uint64, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, nonce, sender) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, []uint64, []common.Address) error); ok { - r1 = rf(opts, sink, nonce, sender) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchSkippedSenderWithPreviousRampMessageInflight' -type EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call struct { - *mock.Call -} - -// WatchSkippedSenderWithPreviousRampMessageInflight is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight -// - nonce []uint64 -// - sender []common.Address -func (_e *EVM2EVMOffRampInterface_Expecter) WatchSkippedSenderWithPreviousRampMessageInflight(opts interface{}, sink interface{}, nonce interface{}, sender interface{}) *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call { - return &EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call{Call: _e.mock.On("WatchSkippedSenderWithPreviousRampMessageInflight", opts, sink, nonce, sender)} -} - -func (_c *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, nonce []uint64, sender []common.Address)) *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight), args[2].([]uint64), args[3].([]common.Address)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampSkippedSenderWithPreviousRampMessageInflight, []uint64, []common.Address) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchSkippedSenderWithPreviousRampMessageInflight_Call { - _c.Call.Return(run) - return _c -} - -// WatchTransmitted provides a mock function with given fields: opts, sink -func (_m *EVM2EVMOffRampInterface) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchTransmitted") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EVM2EVMOffRampInterface_WatchTransmitted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTransmitted' -type EVM2EVMOffRampInterface_WatchTransmitted_Call struct { - *mock.Call -} - -// WatchTransmitted is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted -func (_e *EVM2EVMOffRampInterface_Expecter) WatchTransmitted(opts interface{}, sink interface{}) *EVM2EVMOffRampInterface_WatchTransmitted_Call { - return &EVM2EVMOffRampInterface_WatchTransmitted_Call{Call: _e.mock.On("WatchTransmitted", opts, sink)} -} - -func (_c *EVM2EVMOffRampInterface_WatchTransmitted_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted)) *EVM2EVMOffRampInterface_WatchTransmitted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted)) - }) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchTransmitted_Call) Return(_a0 event.Subscription, _a1 error) *EVM2EVMOffRampInterface_WatchTransmitted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EVM2EVMOffRampInterface_WatchTransmitted_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *evm_2_evm_offramp_1_0_0.EVM2EVMOffRampTransmitted) (event.Subscription, error)) *EVM2EVMOffRampInterface_WatchTransmitted_Call { - _c.Call.Return(run) - return _c -} - -// NewEVM2EVMOffRampInterface creates a new instance of EVM2EVMOffRampInterface. 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 NewEVM2EVMOffRampInterface(t interface { - mock.TestingT - Cleanup(func()) -}) *EVM2EVMOffRampInterface { - mock := &EVM2EVMOffRampInterface{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/gethwrappers/generated/arbitrum_module/arbitrum_module.go b/core/gethwrappers/generated/arbitrum_module/arbitrum_module.go index 537fbe21544..ca9b77d563f 100644 --- a/core/gethwrappers/generated/arbitrum_module/arbitrum_module.go +++ b/core/gethwrappers/generated/arbitrum_module/arbitrum_module.go @@ -29,8 +29,8 @@ var ( ) var ArbitrumModuleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061041b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806357e871e71161005057806357e871e71461009a57806385df51fd146100a2578063de9ee35e146100b557600080fd5b8063125441401461006c57806318b8f61314610092575b600080fd5b61007f61007a366004610333565b6100cb565b6040519081526020015b60405180910390f35b61007f610158565b61007f6101cf565b61007f6100b0366004610333565b61021d565b6040805161138881526000602082015201610089565b600080606c73ffffffffffffffffffffffffffffffffffffffff166341b247a86040518163ffffffff1660e01b815260040160c060405180830381865afa15801561011a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061013e919061034c565b50505050915050828161015191906103c5565b9392505050565b6000606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101ca91906103e2565b905090565b6000606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101a6573d6000803e3d6000fd5b600080606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561026c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029091906103e2565b905080831015806102ab57506101006102a984836103fb565b115b156102b95750600092915050565b6040517f2b407a8200000000000000000000000000000000000000000000000000000000815260048101849052606490632b407a8290602401602060405180830381865afa15801561030f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061015191906103e2565b60006020828403121561034557600080fd5b5035919050565b60008060008060008060c0878903121561036557600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176103dc576103dc610396565b92915050565b6000602082840312156103f457600080fd5b5051919050565b818103818111156103dc576103dc61039656fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061044a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637810d12a116100505780637810d12a1461009a57806385df51fd146100ad578063de9ee35e146100c057600080fd5b8063125441401461006c57806357e871e714610092575b600080fd5b61007f61007a366004610368565b6100d6565b6040519081526020015b60405180910390f35b61007f610163565b61007f6100a8366004610368565b6101da565b61007f6100bb366004610368565b610252565b6040805161138881526000602082015201610089565b600080606c73ffffffffffffffffffffffffffffffffffffffff166341b247a86040518163ffffffff1660e01b815260040160c060405180830381865afa158015610125573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101499190610381565b50505050915050828161015c91906103fa565b9392505050565b6000606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d59190610411565b905090565b6000606c73ffffffffffffffffffffffffffffffffffffffff1663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610228573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024c9190610411565b92915050565b600080606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c59190610411565b905080831015806102e057506101006102de848361042a565b115b156102ee5750600092915050565b6040517f2b407a8200000000000000000000000000000000000000000000000000000000815260048101849052606490632b407a8290602401602060405180830381865afa158015610344573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061015c9190610411565b60006020828403121561037a57600080fd5b5035919050565b60008060008060008060c0878903121561039a57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761024c5761024c6103cb565b60006020828403121561042357600080fd5b5051919050565b8181038181111561024c5761024c6103cb56fea164736f6c6343000813000a", } var ArbitrumModuleABI = ArbitrumModuleMetaData.ABI @@ -213,9 +213,9 @@ func (_ArbitrumModule *ArbitrumModuleCallerSession) BlockNumber() (*big.Int, err return _ArbitrumModule.Contract.BlockNumber(&_ArbitrumModule.CallOpts) } -func (_ArbitrumModule *ArbitrumModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) { +func (_ArbitrumModule *ArbitrumModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { var out []interface{} - err := _ArbitrumModule.contract.Call(opts, &out, "getCurrentL1Fee") + err := _ArbitrumModule.contract.Call(opts, &out, "getCurrentL1Fee", arg0) if err != nil { return *new(*big.Int), err @@ -227,12 +227,12 @@ func (_ArbitrumModule *ArbitrumModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts } -func (_ArbitrumModule *ArbitrumModuleSession) GetCurrentL1Fee() (*big.Int, error) { - return _ArbitrumModule.Contract.GetCurrentL1Fee(&_ArbitrumModule.CallOpts) +func (_ArbitrumModule *ArbitrumModuleSession) GetCurrentL1Fee(arg0 *big.Int) (*big.Int, error) { + return _ArbitrumModule.Contract.GetCurrentL1Fee(&_ArbitrumModule.CallOpts, arg0) } -func (_ArbitrumModule *ArbitrumModuleCallerSession) GetCurrentL1Fee() (*big.Int, error) { - return _ArbitrumModule.Contract.GetCurrentL1Fee(&_ArbitrumModule.CallOpts) +func (_ArbitrumModule *ArbitrumModuleCallerSession) GetCurrentL1Fee(arg0 *big.Int) (*big.Int, error) { + return _ArbitrumModule.Contract.GetCurrentL1Fee(&_ArbitrumModule.CallOpts, arg0) } func (_ArbitrumModule *ArbitrumModuleCaller) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, @@ -301,7 +301,7 @@ type ArbitrumModuleInterface interface { BlockNumber(opts *bind.CallOpts) (*big.Int, error) - GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) + GetCurrentL1Fee(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, diff --git a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go index acbf11155db..c2a808d5545 100644 --- a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go @@ -57,7 +57,7 @@ type AutomationRegistryBase23PaymentReceipt struct { var AutomationRegistryLogicBMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicC2_3\",\"name\":\"logicC\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"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\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162005d2238038062005d2283398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516155e86200073a60003960008181610182015261022f0152600081816120e7015261228d01526000612bb30152600050506000612ee901526000613c5d01526000612fc3015260008181610c4701528181610d0801528181610dd30152612c7401526155e86000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e2366004614490565b610511565b3480156101f357600080fd5b50610207610202366004614604565b610617565b6040516102179493929190614723565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f3660046147a5565b6108f5565b3480156102a057600080fd5b506101c56102af3660046147f1565b610957565b3480156102c057600080fd5b506101c56102cf36600461480a565b610b09565b3480156102e057600080fd5b506101c56102ef366004614836565b610d7c565b34801561030057600080fd5b5061031461030f366004614604565b61102a565b6040516102179796959493929190614877565b34801561033357600080fd5b506101c56103423660046147f1565b61178e565b34801561035357600080fd5b506101c5610362366004614490565b611824565b34801561037357600080fd5b506101c5611c9c565b34801561038857600080fd5b506101c56103973660046147f1565b611d99565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e23660046147a5565b611f4e565b6101c56103f53660046148c5565b611fa3565b34801561040657600080fd5b506101c561041536600461490d565b612365565b34801561042657600080fd5b506101c5610435366004614932565b612464565b34801561044657600080fd5b5061045a6104553660046147a5565b612545565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046147f1565b6126f0565b34801561049d57600080fd5b506101c56104ac3660046147a5565b61291d565b3480156104bd57600080fd5b506102076104cc3660046149ac565b6129d4565b3480156104dd57600080fd5b506101c56104ec366004614a8e565b612a96565b3480156104fd57600080fd5b5061031461050c3660046147f1565b612aaa565b61051a82612ae6565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b9b565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a09190614abb565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e09190614ad8565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614b23565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614b8b565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ae6565b6000838152601d60205260409020610917828483614c70565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614dd4565b60405180910390a2505050565b61096081612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612c0c565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c72565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614de8565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c72565b128015610e835750600060255460ff166001811115610e8157610e816146b9565b145b15610eba576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190614e03565b610f649190614b23565b905080821115610faa576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fcb73ffffffffffffffffffffffffffffffffffffffff85168484612d41565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061103e612b9b565b60006110498a612e1a565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a001511561140c5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611782915050565b606083015163ffffffff908116146114565750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611782915050565b8251156114955750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611782915050565b61149e84612ec5565b8094508198508299505050506114c38e858786604001518b8b888a61010001516130b7565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115255750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611782915050565b505060006115348d858e613427565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115af9190614abb565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115ef9190614ad8565b60006040518083038160008787f1925050503d806000811461162d576040519150601f19603f3d011682016040523d82523d6000602084013e611632565b606091505b50915091505a611642908b614b23565b9950816116c8576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116a75750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611782915050565b604090930151929a50600399505063ffffffff909116955061178292505050565b808060200190518101906116dc9190614b8b565b909d509b508c6117165750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611782915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff1610156117705750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611782915050565b5050506040015163ffffffff16945050505b92959891949750929550565b611796613607565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561187c576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff811661190b576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a4b576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adf9190614e03565b816060015163ffffffff161115611b22576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b8d908290614b23565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611c109116846bffffffffffffffffffffffff8416612d41565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611da281612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611edc576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611f1e600283613658565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f5783612ae6565b6000838152601e60205260409020611f70828483614c70565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614dd4565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120df576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b341561217b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461216f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61217834613664565b91505b818160c0015161218b9190614e1c565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205461221b91841690614e41565b61010082015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604081209190915534900361228b576101008101516122869073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff8616613706565b61231b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b15801561230157600080fd5b505af1158015612315573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff1610806123a2575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123d9576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e282612ae6565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61246c613607565b6000828152600460205260409020546601000000000000900463ffffffff908116146124c4576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906125128282614e65565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124589190614eec565b600080612550612b9b565b601454760100000000000000000000000000000000000000000000900460ff16156125a7576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126e393899089908190840183828082843760009201919091525061376a92505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461282c576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612889576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61292683612ae6565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612988576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526007602052604090206129a1828483614c70565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614dd4565b600060606000806000634b56a42e60e01b8888886040516024016129fa93929190614f23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a838982610617565b929c919b50995090975095505050505050565b612a9e613985565b612aa781613a06565b50565b600060606000806000806000612acf886040518060200160405280600081525061102a565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b43576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612aa7576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612c0a576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612c188383613afb565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d329190614e03565b612d3c9190614fb9565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612e159084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b4a565b505050565b6000818160045b600f811015612ea7577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e5f57612e5f614fd9565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e9557506000949350505050565b80612e9f81615008565b915050612e21565b5081600f1a6001811115612ebd57612ebd6146b9565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f76919061505a565b5094509092505050600081131580612f8d57508142105b80612fae5750828015612fae5750612fa58242614b23565b8463ffffffff16105b15612fbd576019549650612fc1565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561302c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613050919061505a565b509450909250505060008113158061306757508142105b806130885750828015613088575061307f8242614b23565b8463ffffffff16105b1561309757601a54955061309b565b8095505b86866130a68a613c56565b965096509650505050509193909250565b60008080808960018111156130ce576130ce6146b9565b036130dd575062017f98613132565b60018960018111156130f1576130f16146b9565b0361310057506201de84613132565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a60800151600161314591906150aa565b6131539060ff1660406150c3565b601854613181906103a49074010000000000000000000000000000000000000000900463ffffffff16614e41565b61318b9190614e41565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322091906150da565b90925090508183613232836018614e41565b61323c91906150c3565b60808f015161324c9060016150aa565b61325b9060ff166115e06150c3565b6132659190614e41565b61326f9190614e41565b6132799085614e41565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190614e03565b8d6060015161ffff1661332391906150c3565b945050505060006133348b86613d47565b60008d815260046020526040902054909150610100900460ff16156133995760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006134038c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ec3565b6020810151815191925061341691614e1c565b9d9c50505050505050505050505050565b6060600083600181111561343d5761343d6146b9565b03613506576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009161348291602401615199565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050613600565b600183600181111561351a5761351a6146b9565b03613100576000828060200190518101906135359190615212565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161357a918491602401615322565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506136009050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612c18838361420a565b60006bffffffffffffffffffffffff821115613702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137649085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d93565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137c7576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061383c9085906024016153ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061390f9087908790600401615400565b60408051808303816000875af115801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190615419565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b4257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612c1b565b506000612c1b565b6000613bac826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166142fd9092919063ffffffff16565b805190915015612e155780806020019051810190613bca9190614de8565b612e15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cea919061505a565b50935050925050600082131580613d0057508042105b80613d3057506000846040015162ffffff16118015613d305750613d248142614b23565b846040015162ffffff16105b15613d40575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e58919061505a565b50935050925050600082131580613e6e57508042105b80613e9e57506000866040015162ffffff16118015613e9e5750613e928142614b23565b866040015162ffffff16105b15613eb25760018301546060850152613eba565b606084018290525b50505092915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613f2e91906150c3565b90508361010001518015613f415750803a105b15613f4957503a5b600060128311613f5a576001613f70565b613f65601284614b23565b613f7090600a615565565b9050600060128410613f83576001613f99565b613f8e846012614b23565b613f9990600a615565565b905060008660a00151876040015188602001518960000151613fbb9190614e41565b613fc590876150c3565b613fcf9190614e41565b613fd991906150c3565b9050614035828860e0015160600151613ff291906150c3565b6001848a60e001516060015161400891906150c3565b6140129190614b23565b61401c86856150c3565b6140269190614e41565b6140309190615571565b613664565b6bffffffffffffffffffffffff1686526080870151614058906140309083615571565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906140919062ffffff16683635c9adc5dea000006150c3565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b6140c491906150c3565b6140ce9190614e41565b6140d891906150c3565b6140e291906150c3565b6140ec9190615571565b6140f69190614e41565b9050614139848a60e001516060015161410f91906150c3565b6001868c60e001516060015161412591906150c3565b61412f9190614b23565b61401c88856150c3565b6bffffffffffffffffffffffff166020890152608089015161415f906140309083615571565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a01919091528901516141a290613664565b6bffffffffffffffffffffffff1660a0808a01919091528901516141c590613664565b6bffffffffffffffffffffffff1660c089015260e0890151606001516141ea90613664565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b600081815260018301602052604081205480156142f357600061422e600183614b23565b855490915060009061424290600190614b23565b90508181146142a757600086600001828154811061426257614262614fd9565b906000526020600020015490508087600001848154811061428557614285614fd9565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142b8576142b86155ac565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612c1b565b6000915050612c1b565b6060612ebd8484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516143319190614ad8565b60006040518083038185875af1925050503d806000811461436e576040519150601f19603f3d011682016040523d82523d6000602084013e614373565b606091505b50915091506143848783838761438f565b979650505050505050565b6060831561442557825160000361441e5773ffffffffffffffffffffffffffffffffffffffff85163b61441e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612ebd565b612ebd838381511561443a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906153ed565b73ffffffffffffffffffffffffffffffffffffffff81168114612aa757600080fd5b600080604083850312156144a357600080fd5b8235915060208301356144b58161446e565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715614513576145136144c0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614560576145606144c0565b604052919050565b600067ffffffffffffffff821115614582576145826144c0565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126145bf57600080fd5b81356145d26145cd82614568565b614519565b8181528460208386010111156145e757600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561461757600080fd5b82359150602083013567ffffffffffffffff81111561463557600080fd5b614641858286016145ae565b9150509250929050565b60005b8381101561466657818101518382015260200161464e565b50506000910152565b6000815180845261468781602086016020860161464b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061471f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061473e608083018661466f565b905061474d60408301856146e8565b82606083015295945050505050565b60008083601f84011261476e57600080fd5b50813567ffffffffffffffff81111561478657600080fd5b60208301915083602082850101111561479e57600080fd5b9250929050565b6000806000604084860312156147ba57600080fd5b83359250602084013567ffffffffffffffff8111156147d857600080fd5b6147e48682870161475c565b9497909650939450505050565b60006020828403121561480357600080fd5b5035919050565b6000806040838503121561481d57600080fd5b82356148288161446e565b946020939093013593505050565b60008060006060848603121561484b57600080fd5b83356148568161446e565b925060208401356148668161446e565b929592945050506040919091013590565b871515815260e06020820152600061489260e083018961466f565b90506148a160408301886146e8565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156148d857600080fd5b8235915060208301356bffffffffffffffffffffffff811681146144b557600080fd5b63ffffffff81168114612aa757600080fd5b6000806040838503121561492057600080fd5b8235915060208301356144b5816148fb565b600080828403606081121561494657600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561497a57600080fd5b506020830190509250929050565b600067ffffffffffffffff8211156149a2576149a26144c0565b5060051b60200190565b600080600080606085870312156149c257600080fd5b8435935060208086013567ffffffffffffffff808211156149e257600080fd5b818801915088601f8301126149f657600080fd5b8135614a046145cd82614988565b81815260059190911b8301840190848101908b831115614a2357600080fd5b8585015b83811015614a5b57803585811115614a3f5760008081fd5b614a4d8e89838a01016145ae565b845250918601918601614a27565b50975050506040880135925080831115614a7457600080fd5b5050614a828782880161475c565b95989497509550505050565b600060208284031215614aa057600080fd5b81356136008161446e565b8051614ab68161446e565b919050565b600060208284031215614acd57600080fd5b81516136008161446e565b60008251614aea81846020870161464b565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612c1b57612c1b614af4565b80518015158114614ab657600080fd5b600082601f830112614b5757600080fd5b8151614b656145cd82614568565b818152846020838601011115614b7a57600080fd5b612ebd82602083016020870161464b565b60008060408385031215614b9e57600080fd5b614ba783614b36565b9150602083015167ffffffffffffffff811115614bc357600080fd5b61464185828601614b46565b600181811c90821680614be357607f821691505b602082108103614c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612e1557600081815260208120601f850160051c81016020861015614c495750805b601f850160051c820191505b81811015614c6857828155600101614c55565b505050505050565b67ffffffffffffffff831115614c8857614c886144c0565b614c9c83614c968354614bcf565b83614c22565b6000601f841160018114614cee5760008515614cb85750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614d84565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614d3d5786850135825560209485019460019092019101614d1d565b5086821015614d78577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612ebd602083018486614d8b565b600060208284031215614dfa57600080fd5b612c1882614b36565b600060208284031215614e1557600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d4057613d40614af4565b80820180821115612c1b57612c1b614af4565b62ffffff81168114612aa757600080fd5b8135614e70816148fb565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614eb081614e54565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614efb816148fb565b63ffffffff1682526020830135614f1181614e54565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614f98577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614f8686835161466f565b95509382019390820190600101614f4c565b505085840381870152505050614faf818587614d8b565b9695505050505050565b8181036000831280158383131683831282161715613d4057613d40614af4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361503957615039614af4565b5060010190565b805169ffffffffffffffffffff81168114614ab657600080fd5b600080600080600060a0868803121561507257600080fd5b61507b86615040565b945060208601519350604086015192506060860151915061509e60808701615040565b90509295509295909350565b60ff8181168382160190811115612c1b57612c1b614af4565b8082028115828204841417612c1b57612c1b614af4565b600080604083850312156150ed57600080fd5b505080516020909101519092909150565b6000815461510b81614bcf565b80855260206001838116801561512857600181146151605761518e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061518e565b866000528260002060005b858110156151865781548a820186015290830190840161516b565b890184019650505b505050505092915050565b602081526000612c1860208301846150fe565b600082601f8301126151bd57600080fd5b815160206151cd6145cd83614988565b82815260059290921b840181019181810190868411156151ec57600080fd5b8286015b8481101561520757805183529183019183016151f0565b509695505050505050565b60006020828403121561522457600080fd5b815167ffffffffffffffff8082111561523c57600080fd5b90830190610100828603121561525157600080fd5b6152596144ef565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261529160a08401614aab565b60a082015260c0830151828111156152a857600080fd5b6152b4878286016151ac565b60c08301525060e0830151828111156152cc57600080fd5b6152d887828601614b46565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015615317578151875295820195908201906001016152fb565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c08401516101008081850152506153936101408401826152e7565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526153cf828261466f565b91505082810360208401526153e481856150fe565b95945050505050565b602081526000612c18602083018461466f565b828152604060208201526000612ebd604083018461466f565b6000806040838503121561542c57600080fd5b61543583614b36565b9150602083015190509250929050565b600181815b8085111561549e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561548457615484614af4565b8085161561549157918102915b93841c939080029061544a565b509250929050565b6000826154b557506001612c1b565b816154c257506000612c1b565b81600181146154d857600281146154e2576154fe565b6001915050612c1b565b60ff8411156154f3576154f3614af4565b50506001821b612c1b565b5060208310610133831016604e8410600b8410161715615521575081810a612c1b565b61552b8383615445565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561555d5761555d614af4565b029392505050565b6000612c1883836154a6565b6000826155a7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b5060405162005d2238038062005d2283398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516155e86200073a60003960008181610182015261022f0152600081816120e7015261228d01526000612bb30152600050506000612ee901526000613c5d01526000612fc3015260008181610c4701528181610d0801528181610dd30152612c7401526155e86000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e2366004614490565b610511565b3480156101f357600080fd5b50610207610202366004614604565b610617565b6040516102179493929190614723565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f3660046147a5565b6108f5565b3480156102a057600080fd5b506101c56102af3660046147f1565b610957565b3480156102c057600080fd5b506101c56102cf36600461480a565b610b09565b3480156102e057600080fd5b506101c56102ef366004614836565b610d7c565b34801561030057600080fd5b5061031461030f366004614604565b61102a565b6040516102179796959493929190614877565b34801561033357600080fd5b506101c56103423660046147f1565b61178e565b34801561035357600080fd5b506101c5610362366004614490565b611824565b34801561037357600080fd5b506101c5611c9c565b34801561038857600080fd5b506101c56103973660046147f1565b611d99565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e23660046147a5565b611f4e565b6101c56103f53660046148c5565b611fa3565b34801561040657600080fd5b506101c561041536600461490d565b612365565b34801561042657600080fd5b506101c5610435366004614932565b612464565b34801561044657600080fd5b5061045a6104553660046147a5565b612545565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046147f1565b6126f0565b34801561049d57600080fd5b506101c56104ac3660046147a5565b61291d565b3480156104bd57600080fd5b506102076104cc3660046149ac565b6129d4565b3480156104dd57600080fd5b506101c56104ec366004614a8e565b612a96565b3480156104fd57600080fd5b5061031461050c3660046147f1565b612aaa565b61051a82612ae6565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b9b565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a09190614abb565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e09190614ad8565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614b23565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614b8b565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ae6565b6000838152601d60205260409020610917828483614c70565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614dd4565b60405180910390a2505050565b61096081612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612c0c565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c72565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614de8565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c72565b128015610e835750600060255460ff166001811115610e8157610e816146b9565b145b15610eba576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190614e03565b610f649190614b23565b905080821115610faa576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fcb73ffffffffffffffffffffffffffffffffffffffff85168484612d41565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061103e612b9b565b60006110498a612e1a565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a001511561140c5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611782915050565b606083015163ffffffff908116146114565750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611782915050565b8251156114955750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611782915050565b61149e84612ec5565b8094508198508299505050506114c38e858786604001518b8b888a61010001516130b7565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115255750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611782915050565b505060006115348d858e613427565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115af9190614abb565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115ef9190614ad8565b60006040518083038160008787f1925050503d806000811461162d576040519150601f19603f3d011682016040523d82523d6000602084013e611632565b606091505b50915091505a611642908b614b23565b9950816116c8576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116a75750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611782915050565b604090930151929a50600399505063ffffffff909116955061178292505050565b808060200190518101906116dc9190614b8b565b909d509b508c6117165750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611782915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff1610156117705750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611782915050565b5050506040015163ffffffff16945050505b92959891949750929550565b611796613607565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561187c576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff811661190b576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a4b576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adf9190614e03565b816060015163ffffffff161115611b22576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b8d908290614b23565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611c109116846bffffffffffffffffffffffff8416612d41565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611da281612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611edc576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611f1e600283613658565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f5783612ae6565b6000838152601e60205260409020611f70828483614c70565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614dd4565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120df576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b341561217b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461216f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61217834613664565b91505b818160c0015161218b9190614e1c565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205461221b91841690614e41565b61010082015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604081209190915534900361228b576101008101516122869073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff8616613706565b61231b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b15801561230157600080fd5b505af1158015612315573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff1610806123a2575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123d9576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e282612ae6565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61246c613607565b6000828152600460205260409020546601000000000000900463ffffffff908116146124c4576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906125128282614e65565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124589190614eec565b600080612550612b9b565b601454760100000000000000000000000000000000000000000000900460ff16156125a7576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126e393899089908190840183828082843760009201919091525061376a92505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461282c576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612889576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61292683612ae6565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612988576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526007602052604090206129a1828483614c70565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614dd4565b600060606000806000634b56a42e60e01b8888886040516024016129fa93929190614f23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a838982610617565b929c919b50995090975095505050505050565b612a9e613985565b612aa781613a06565b50565b600060606000806000806000612acf886040518060200160405280600081525061102a565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b43576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612aa7576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612c0a576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612c188383613afb565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d329190614e03565b612d3c9190614fb9565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612e159084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b4a565b505050565b6000818160045b600f811015612ea7577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e5f57612e5f614fd9565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e9557506000949350505050565b80612e9f81615008565b915050612e21565b5081600f1a6001811115612ebd57612ebd6146b9565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f76919061505a565b5094509092505050600081131580612f8d57508142105b80612fae5750828015612fae5750612fa58242614b23565b8463ffffffff16105b15612fbd576019549650612fc1565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561302c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613050919061505a565b509450909250505060008113158061306757508142105b806130885750828015613088575061307f8242614b23565b8463ffffffff16105b1561309757601a54955061309b565b8095505b86866130a68a613c56565b965096509650505050509193909250565b60008080808960018111156130ce576130ce6146b9565b036130dd575062017f98613132565b60018960018111156130f1576130f16146b9565b0361310057506201e26c613132565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a60800151600161314591906150aa565b6131539060ff1660406150c3565b601854613181906103a49074010000000000000000000000000000000000000000900463ffffffff16614e41565b61318b9190614e41565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322091906150da565b90925090508183613232836018614e41565b61323c91906150c3565b60808f015161324c9060016150aa565b61325b9060ff166115e06150c3565b6132659190614e41565b61326f9190614e41565b6132799085614e41565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190614e03565b8d6060015161ffff1661332391906150c3565b945050505060006133348b86613d47565b60008d815260046020526040902054909150610100900460ff16156133995760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006134038c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ec3565b6020810151815191925061341691614e1c565b9d9c50505050505050505050505050565b6060600083600181111561343d5761343d6146b9565b03613506576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009161348291602401615199565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050613600565b600183600181111561351a5761351a6146b9565b03613100576000828060200190518101906135359190615212565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161357a918491602401615322565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506136009050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612c18838361420a565b60006bffffffffffffffffffffffff821115613702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137649085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d93565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137c7576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061383c9085906024016153ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061390f9087908790600401615400565b60408051808303816000875af115801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190615419565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b4257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612c1b565b506000612c1b565b6000613bac826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166142fd9092919063ffffffff16565b805190915015612e155780806020019051810190613bca9190614de8565b612e15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cea919061505a565b50935050925050600082131580613d0057508042105b80613d3057506000846040015162ffffff16118015613d305750613d248142614b23565b846040015162ffffff16105b15613d40575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e58919061505a565b50935050925050600082131580613e6e57508042105b80613e9e57506000866040015162ffffff16118015613e9e5750613e928142614b23565b866040015162ffffff16105b15613eb25760018301546060850152613eba565b606084018290525b50505092915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613f2e91906150c3565b90508361010001518015613f415750803a105b15613f4957503a5b600060128311613f5a576001613f70565b613f65601284614b23565b613f7090600a615565565b9050600060128410613f83576001613f99565b613f8e846012614b23565b613f9990600a615565565b905060008660a00151876040015188602001518960000151613fbb9190614e41565b613fc590876150c3565b613fcf9190614e41565b613fd991906150c3565b9050614035828860e0015160600151613ff291906150c3565b6001848a60e001516060015161400891906150c3565b6140129190614b23565b61401c86856150c3565b6140269190614e41565b6140309190615571565b613664565b6bffffffffffffffffffffffff1686526080870151614058906140309083615571565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906140919062ffffff16683635c9adc5dea000006150c3565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b6140c491906150c3565b6140ce9190614e41565b6140d891906150c3565b6140e291906150c3565b6140ec9190615571565b6140f69190614e41565b9050614139848a60e001516060015161410f91906150c3565b6001868c60e001516060015161412591906150c3565b61412f9190614b23565b61401c88856150c3565b6bffffffffffffffffffffffff166020890152608089015161415f906140309083615571565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a01919091528901516141a290613664565b6bffffffffffffffffffffffff1660a0808a01919091528901516141c590613664565b6bffffffffffffffffffffffff1660c089015260e0890151606001516141ea90613664565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b600081815260018301602052604081205480156142f357600061422e600183614b23565b855490915060009061424290600190614b23565b90508181146142a757600086600001828154811061426257614262614fd9565b906000526020600020015490508087600001848154811061428557614285614fd9565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142b8576142b86155ac565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612c1b565b6000915050612c1b565b6060612ebd8484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516143319190614ad8565b60006040518083038185875af1925050503d806000811461436e576040519150601f19603f3d011682016040523d82523d6000602084013e614373565b606091505b50915091506143848783838761438f565b979650505050505050565b6060831561442557825160000361441e5773ffffffffffffffffffffffffffffffffffffffff85163b61441e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612ebd565b612ebd838381511561443a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906153ed565b73ffffffffffffffffffffffffffffffffffffffff81168114612aa757600080fd5b600080604083850312156144a357600080fd5b8235915060208301356144b58161446e565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715614513576145136144c0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614560576145606144c0565b604052919050565b600067ffffffffffffffff821115614582576145826144c0565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126145bf57600080fd5b81356145d26145cd82614568565b614519565b8181528460208386010111156145e757600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561461757600080fd5b82359150602083013567ffffffffffffffff81111561463557600080fd5b614641858286016145ae565b9150509250929050565b60005b8381101561466657818101518382015260200161464e565b50506000910152565b6000815180845261468781602086016020860161464b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061471f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061473e608083018661466f565b905061474d60408301856146e8565b82606083015295945050505050565b60008083601f84011261476e57600080fd5b50813567ffffffffffffffff81111561478657600080fd5b60208301915083602082850101111561479e57600080fd5b9250929050565b6000806000604084860312156147ba57600080fd5b83359250602084013567ffffffffffffffff8111156147d857600080fd5b6147e48682870161475c565b9497909650939450505050565b60006020828403121561480357600080fd5b5035919050565b6000806040838503121561481d57600080fd5b82356148288161446e565b946020939093013593505050565b60008060006060848603121561484b57600080fd5b83356148568161446e565b925060208401356148668161446e565b929592945050506040919091013590565b871515815260e06020820152600061489260e083018961466f565b90506148a160408301886146e8565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156148d857600080fd5b8235915060208301356bffffffffffffffffffffffff811681146144b557600080fd5b63ffffffff81168114612aa757600080fd5b6000806040838503121561492057600080fd5b8235915060208301356144b5816148fb565b600080828403606081121561494657600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561497a57600080fd5b506020830190509250929050565b600067ffffffffffffffff8211156149a2576149a26144c0565b5060051b60200190565b600080600080606085870312156149c257600080fd5b8435935060208086013567ffffffffffffffff808211156149e257600080fd5b818801915088601f8301126149f657600080fd5b8135614a046145cd82614988565b81815260059190911b8301840190848101908b831115614a2357600080fd5b8585015b83811015614a5b57803585811115614a3f5760008081fd5b614a4d8e89838a01016145ae565b845250918601918601614a27565b50975050506040880135925080831115614a7457600080fd5b5050614a828782880161475c565b95989497509550505050565b600060208284031215614aa057600080fd5b81356136008161446e565b8051614ab68161446e565b919050565b600060208284031215614acd57600080fd5b81516136008161446e565b60008251614aea81846020870161464b565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612c1b57612c1b614af4565b80518015158114614ab657600080fd5b600082601f830112614b5757600080fd5b8151614b656145cd82614568565b818152846020838601011115614b7a57600080fd5b612ebd82602083016020870161464b565b60008060408385031215614b9e57600080fd5b614ba783614b36565b9150602083015167ffffffffffffffff811115614bc357600080fd5b61464185828601614b46565b600181811c90821680614be357607f821691505b602082108103614c1c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612e1557600081815260208120601f850160051c81016020861015614c495750805b601f850160051c820191505b81811015614c6857828155600101614c55565b505050505050565b67ffffffffffffffff831115614c8857614c886144c0565b614c9c83614c968354614bcf565b83614c22565b6000601f841160018114614cee5760008515614cb85750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614d84565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614d3d5786850135825560209485019460019092019101614d1d565b5086821015614d78577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612ebd602083018486614d8b565b600060208284031215614dfa57600080fd5b612c1882614b36565b600060208284031215614e1557600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d4057613d40614af4565b80820180821115612c1b57612c1b614af4565b62ffffff81168114612aa757600080fd5b8135614e70816148fb565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614eb081614e54565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614efb816148fb565b63ffffffff1682526020830135614f1181614e54565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614f98577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614f8686835161466f565b95509382019390820190600101614f4c565b505085840381870152505050614faf818587614d8b565b9695505050505050565b8181036000831280158383131683831282161715613d4057613d40614af4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361503957615039614af4565b5060010190565b805169ffffffffffffffffffff81168114614ab657600080fd5b600080600080600060a0868803121561507257600080fd5b61507b86615040565b945060208601519350604086015192506060860151915061509e60808701615040565b90509295509295909350565b60ff8181168382160190811115612c1b57612c1b614af4565b8082028115828204841417612c1b57612c1b614af4565b600080604083850312156150ed57600080fd5b505080516020909101519092909150565b6000815461510b81614bcf565b80855260206001838116801561512857600181146151605761518e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061518e565b866000528260002060005b858110156151865781548a820186015290830190840161516b565b890184019650505b505050505092915050565b602081526000612c1860208301846150fe565b600082601f8301126151bd57600080fd5b815160206151cd6145cd83614988565b82815260059290921b840181019181810190868411156151ec57600080fd5b8286015b8481101561520757805183529183019183016151f0565b509695505050505050565b60006020828403121561522457600080fd5b815167ffffffffffffffff8082111561523c57600080fd5b90830190610100828603121561525157600080fd5b6152596144ef565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261529160a08401614aab565b60a082015260c0830151828111156152a857600080fd5b6152b4878286016151ac565b60c08301525060e0830151828111156152cc57600080fd5b6152d887828601614b46565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015615317578151875295820195908201906001016152fb565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c08401516101008081850152506153936101408401826152e7565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526153cf828261466f565b91505082810360208401526153e481856150fe565b95945050505050565b602081526000612c18602083018461466f565b828152604060208201526000612ebd604083018461466f565b6000806040838503121561542c57600080fd5b61543583614b36565b9150602083015190509250929050565b600181815b8085111561549e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561548457615484614af4565b8085161561549157918102915b93841c939080029061544a565b509250929050565b6000826154b557506001612c1b565b816154c257506000612c1b565b81600181146154d857600281146154e2576154fe565b6001915050612c1b565b60ff8411156154f3576154f3614af4565b50506001821b612c1b565b5060208310610133831016604e8410600b8410161715615521575081810a612c1b565b61552b8383615445565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561555d5761555d614af4565b029392505050565b6000612c1883836154a6565b6000826155a7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", } var AutomationRegistryLogicBABI = AutomationRegistryLogicBMetaData.ABI diff --git a/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go index e32d6890ddd..d5e6d9d64ff 100644 --- a/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go @@ -151,7 +151,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { var AutomationRegistryLogicCMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkUSDFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeUSDFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fastGasFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"automationForwarderLogic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowedReadOnlyAddress\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.PayoutMode\",\"name\":\"payoutMode\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"wrappedNativeTokenAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"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\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getAvailableERC20ForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"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\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverridesEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"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\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"contractIAutomationForwarder\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"enumAutomationRegistryBase2_3.PayoutMode\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"enumAutomationRegistryBase2_3.MigrationPermission\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"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\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.MigrationPermission\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101606040523480156200001257600080fd5b5060405162005c8738038062005c87833981016040819052620000359162000309565b87878787878787873380600081620000945760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c757620000c78162000241565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff191660018381811115620001185762000118620003b6565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000179573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019f9190620003cc565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002099190620003cc565b60ff16146200022b576040516301f86e1760e41b815260040160405180910390fd5b50505050505050505050505050505050620003f8565b336001600160a01b038216036200029b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008b565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200030457600080fd5b919050565b600080600080600080600080610100898b0312156200032757600080fd5b6200033289620002ec565b97506200034260208a01620002ec565b96506200035260408a01620002ec565b95506200036260608a01620002ec565b94506200037260808a01620002ec565b93506200038260a08a01620002ec565b925060c0890151600281106200039757600080fd5b9150620003a760e08a01620002ec565b90509295985092959890939650565b634e487b7160e01b600052602160045260246000fd5b600060208284031215620003df57600080fd5b815160ff81168114620003f157600080fd5b9392505050565b60805160a05160c05160e051610100516101205161014051615803620004846000396000610b7001526000610ad2015260006107be0152600081816109a001526135b60152600081816109540152613e3201526000818161051d0152613690015260008181610c1801528181611df00152818161256b015281816125c80152613af601526158036000f3fe608060405234801561001057600080fd5b50600436106103d05760003560e01c80638ed02bab116101ff578063c3f909d41161011a578063eb5dcd6c116100ad578063f5a418461161007c578063f5a4184614610eb4578063f777ff0614610f35578063faa3e99614610f3c578063ffd242bd14610f8257600080fd5b8063eb5dcd6c14610de5578063ec4de4ba14610df8578063ed56b3e114610e2e578063f2fde38b14610ea157600080fd5b8063d09dc339116100e9578063d09dc33914610c3c578063d763264814610c44578063d85aa07c14610c57578063e80a3d4414610c5f57600080fd5b8063c3f909d414610bd6578063c5b964e014610beb578063c7c3a19a14610bf6578063ca30e60314610c1657600080fd5b8063aab9edd611610192578063b3596c2311610161578063b3596c23146107e2578063b6511a2a14610ba7578063b657bc9c14610bae578063ba87666814610bc157600080fd5b8063aab9edd614610b57578063abc76ae014610b66578063ac4dc59a14610b6e578063b121e14714610b9457600080fd5b8063a08714c0116101ce578063a08714c014610ad0578063a538b2eb14610af6578063a710b22114610b3c578063a87f45fe14610b4f57600080fd5b80638ed02bab14610a5c5780639089daa414610a7a57806393f6ebcf14610a8f5780639e0a99ed14610ac857600080fd5b806343cc055c116102ef5780636209e1e91161028257806379ba50971161025157806379ba5097146109ea57806379ea9943146109f25780638456cb5914610a365780638da5cb5b14610a3e57600080fd5b80636209e1e91461098b5780636709d0e51461099e578063671d36ed146109c45780636eec02a2146109d757600080fd5b80635425d8ac116102be5780635425d8ac146107bc57806357359584146107e2578063614486af146109525780636181d82d1461097857600080fd5b806343cc055c1461074957806344cb70b8146107705780634ca16c52146107935780635147cd591461079c57600080fd5b8063207b6516116103675780633b9cce59116103365780633b9cce59146106c05780633f4ba83a146106d3578063421d183b146106db57806343b46e5f1461074157600080fd5b8063207b651614610508578063226cf83c1461051b578063232c1cc5146105625780633408f73a1461056957600080fd5b8063187256e8116103a3578063187256e81461043b57806319d97a941461044e5780631e0104391461046e5780631efcf646146104d057600080fd5b8063050ee65d146103d557806306e3b632146103ed5780630b7d33e61461040d5780631865c57d14610422575b600080fd5b6201de845b6040519081526020015b60405180910390f35b6104006103fb36600461447a565b610f8a565b6040516103e491906144d7565b61042061041b366004614533565b6110a7565b005b61042a611108565b6040516103e495949392919061472b565b61042061044936600461486c565b611508565b61046161045c3660046148a9565b611579565b6040516103e49190614926565b6104b361047c3660046148a9565b60009081526004602052604090206001015470010000000000000000000000000000000090046bffffffffffffffffffffffff1690565b6040516bffffffffffffffffffffffff90911681526020016103e4565b6104f86104de3660046148a9565b600090815260046020526040902054610100900460ff1690565b60405190151581526020016103e4565b6104616105163660046148a9565b61161b565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103e4565b60186103da565b6106b36040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915250604080516101608101825260165473ffffffffffffffffffffffffffffffffffffffff808216835263ffffffff740100000000000000000000000000000000000000008084048216602086015278010000000000000000000000000000000000000000000000008085048316968601969096527c010000000000000000000000000000000000000000000000000000000093849004821660608601526017548084166080870152818104831660a0870152868104831660c087015293909304811660e085015260185491821661010085015291810482166101208401529290920490911661014082015290565b6040516103e49190614939565b6104206106ce366004614a63565b611638565b61042061188e565b6106ee6106e9366004614ad8565b6118f4565b60408051951515865260ff90941660208601526bffffffffffffffffffffffff9283169385019390935216606083015273ffffffffffffffffffffffffffffffffffffffff16608082015260a0016103e4565b610420611a13565b6014547801000000000000000000000000000000000000000000000000900460ff166104f8565b6104f861077e3660046148a9565b60009081526008602052604090205460ff1690565b62017f986103da565b6107af6107aa3660046148a9565b611eaa565b6040516103e49190614b34565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6108d46107f0366004614ad8565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525073ffffffffffffffffffffffffffffffffffffffff908116600090815260226020908152604091829020825160c081018452815463ffffffff81168252640100000000810462ffffff16938201939093526701000000000000008304909416928401929092527b01000000000000000000000000000000000000000000000000000000900460ff16606083015260018101546080830152600201546bffffffffffffffffffffffff1660a082015290565b6040516103e49190600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104b3610986366004614b47565b611eb5565b610461610999366004614ad8565b612010565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104206109d2366004614ba7565b612043565b6103da6109e5366004614ad8565b6120c3565b61042061216d565b61053d610a003660046148a9565b6000908152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61042061226f565b60005473ffffffffffffffffffffffffffffffffffffffff1661053d565b60155473ffffffffffffffffffffffffffffffffffffffff1661053d565b610a826122e8565b6040516103e49190614be3565b61053d610a9d3660046148a9565b60009081526004602052604090206002015473ffffffffffffffffffffffffffffffffffffffff1690565b6103a46103da565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104f8610b04366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260226020526040902054670100000000000000900416151590565b610420610b4a366004614c4c565b6123fa565b610420612728565b604051600481526020016103e4565b6115e06103da565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b610420610ba2366004614ad8565b61275a565b60326103da565b6104b3610bbc3660046148a9565b612852565b610bc9612979565b6040516103e49190614c7a565b610bde6129e8565b6040516103e49190614cd4565b60255460ff166107af565b610c09610c043660046148a9565b612bd0565b6040516103e49190614e5b565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6103da612fe0565b6104b3610c523660046148a9565b612fef565b601b546103da565b610dd86040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091525060408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff750100000000000000000000000000000000000000000083048116608083015276010000000000000000000000000000000000000000000083048116151560a08301527701000000000000000000000000000000000000000000000083048116151560c08301527801000000000000000000000000000000000000000000000000909204909116151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290565b6040516103e49190614f92565b610420610df3366004614c4c565b612ffa565b6103da610e06366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205490565b610e88610e3c366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602090815260409182902082518084019093525460ff8082161515808552610100909204169290910182905291565b60408051921515835260ff9091166020830152016103e4565b610420610eaf366004614ad8565b613159565b610f0f610ec23660046148a9565b60408051808201909152600080825260208201525060009081526023602090815260409182902082518084019093525463ffffffff81168352640100000000900462ffffff169082015290565b60408051825163ffffffff16815260209283015162ffffff1692810192909252016103e4565b60406103da565b610f75610f4a366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff166000908152601c602052604090205460ff1690565b6040516103e49190615062565b6103da61316d565b60606000610f986002613175565b9050808410610fd3576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610fdf84866150a5565b905081811180610fed575083155b610ff75780610ff9565b815b9050600061100786836150b8565b67ffffffffffffffff81111561101f5761101f6150cb565b604051908082528060200260200182016040528015611048578160200160208202803683370190505b50905060005b815181101561109b5761106c61106488836150a5565b60029061317f565b82828151811061107e5761107e6150fa565b60209081029190910101528061109381615129565b91505061104e565b50925050505b92915050565b6110af61318b565b6000838152601f602052604090206110c8828483615203565b50827f2fd8d70753a007014349d4591843cc031c2dd7a260d7dd82eca8253686ae776983836040516110fb92919061531e565b60405180910390a2505050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810191909152604080516101e08101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a08201526101c081019190915260408051610140810182526016547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1681526000602082018190529181018290526014546bffffffffffffffffffffffff16606080830191909152918291608081016112416002613175565b81526017547401000000000000000000000000000000000000000080820463ffffffff908116602080860191909152780100000000000000000000000000000000000000000000000080850483166040808801919091526013546060808901919091526014546c01000000000000000000000000810486166080808b0191909152760100000000000000000000000000000000000000000000820460ff16151560a09a8b015283516101e0810185526000808252968101879052601654898104891695820195909552700100000000000000000000000000000000830462ffffff169381019390935273010000000000000000000000000000000000000090910461ffff169082015296870192909252808204831660c08701527c0100000000000000000000000000000000000000000000000000000000909404821660e086015260185492830482166101008601529290910416610120830152601954610140830152601a5461016083015273ffffffffffffffffffffffffffffffffffffffff166101808201529095506101a081016113dc60096131de565b815260175473ffffffffffffffffffffffffffffffffffffffff16602091820152601454600d80546040805182860281018601909152818152949850899489949293600e93750100000000000000000000000000000000000000000090910460ff1692859183018282801561148757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161145c575b50505050509250818054806020026020016040519081016040528092919081815260200182805480156114f057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116114c5575b50505050509150945094509450945094509091929394565b6115106131eb565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601c6020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561157057611570614af5565b02179055505050565b6000818152601f6020526040902080546060919061159690615161565b80601f01602080910402602001604051908101604052809291908181526020018280546115c290615161565b801561160f5780601f106115e45761010080835404028352916020019161160f565b820191906000526020600020905b8154815290600101906020018083116115f257829003601f168201915b50505050509050919050565b6000818152601d6020526040902080546060919061159690615161565b6116406131eb565b600e54811461167b576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b600e5481101561184d576000600e828154811061169d5761169d6150fa565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526011909252604083205491935016908585858181106116e7576116e76150fa565b90506020020160208101906116fc9190614ad8565b905073ffffffffffffffffffffffffffffffffffffffff8116158061178f575073ffffffffffffffffffffffffffffffffffffffff82161580159061176d57508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561178f575073ffffffffffffffffffffffffffffffffffffffff81811614155b156117c6576040517fb387a23800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff818116146118375773ffffffffffffffffffffffffffffffffffffffff838116600090815260116020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169183169190911790555b505050808061184590615129565b91505061167e565b507fa46de38886467c59be07a0675f14781206a5477d871628af46c2443822fcb725600e83836040516118829392919061536b565b60405180910390a15050565b6118966131eb565b601480547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e0100000000000000000000000000009004909116606082015282918291829182919082906119ba5760608201516014546000916119a6916bffffffffffffffffffffffff1661541d565b600e549091506119b69082615471565b9150505b8151602083015160408401516119d190849061549c565b6060949094015173ffffffffffffffffffffffffffffffffffffffff9a8b16600090815260116020526040902054929b919a9499509750921694509092505050565b611a1b61326c565b600060255460ff166001811115611a3457611a34614af5565b03611a6b576040517fe0262d7400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600e546bffffffffffffffffffffffff909116906000611a8e600f613175565b90506000611a9c82846150a5565b905060008167ffffffffffffffff811115611ab957611ab96150cb565b604051908082528060200260200182016040528015611ae2578160200160208202803683370190505b50905060008267ffffffffffffffff811115611b0057611b006150cb565b604051908082528060200260200182016040528015611b29578160200160208202803683370190505b50905060005b85811015611c5b576000600e8281548110611b4c57611b4c6150fa565b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff169150611b7a828a8a6132bd565b9050806bffffffffffffffffffffffff16858481518110611b9d57611b9d6150fa565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff808416600090815260119092526040909120548551911690859085908110611beb57611beb6150fa565b73ffffffffffffffffffffffffffffffffffffffff92831660209182029290920181019190915292166000908152600b909252506040902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905580611c5381615129565b915050611b2f565b5060005b84811015611dd8576000611c74600f8361317f565b73ffffffffffffffffffffffffffffffffffffffff8082166000818152600b602090815260408083208151608081018352905460ff80821615158352610100820416828501526bffffffffffffffffffffffff6201000082048116838501526e0100000000000000000000000000009091041660608201529383526011909152902054929350911684611d078a866150a5565b81518110611d1757611d176150fa565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260408101516bffffffffffffffffffffffff1685611d5a8a866150a5565b81518110611d6a57611d6a6150fa565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff9092166000908152600b909252506040902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905580611dd081615129565b915050611c5f565b5073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166000908152602160205260408120819055611e2b600f613175565b90505b8015611e6857611e55611e4d611e456001846150b8565b600f9061317f565b600f906134c5565b5080611e60816154c1565b915050611e2e565b507f5af23b715253628d12b660b27a4f3fc626562ea8a55040aa99ab3dc178989fad8183604051611e9a9291906154f6565b60405180910390a1505050505050565b60006110a1826134e7565b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff750100000000000000000000000000000000000000000083048116608083015276010000000000000000000000000000000000000000000083048116151560a08301527701000000000000000000000000000000000000000000000083048116151560c08301527801000000000000000000000000000000000000000000000000909204909116151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152600090818080611fed84613592565b92509250925061200389858a8a8787878d613784565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040902080546060919061159690615161565b61204b61318b565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602080526040902061207a828483615203565b508273ffffffffffffffffffffffffffffffffffffffff167f7c44b4eb59ee7873514e7e43e7718c269d872965938b288aa143befca62f99d283836040516110fb92919061531e565b73ffffffffffffffffffffffffffffffffffffffff81166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa15801561213f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121639190615524565b6110a191906150b8565b60015473ffffffffffffffffffffffffffffffffffffffff1633146121f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6122776131eb565b601480547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff167601000000000000000000000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016118ea565b600e5460609060008167ffffffffffffffff811115612309576123096150cb565b60405190808252806020026020018201604052801561234e57816020015b60408051808201909152600080825260208201528152602001906001900390816123275790505b50905060005b828110156123f3576000600e8281548110612371576123716150fa565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526011835260409384902054845180860190955281855290911691830182905285519093509091908590859081106123d3576123d36150fa565b6020026020010181905250505080806123eb90615129565b915050612354565b5092915050565b73ffffffffffffffffffffffffffffffffffffffff8116612447576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160255460ff16600181111561246057612460614af5565b03612497576040517f4a3578fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601160205260409020541633146124f7576040517fcebf515b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600e5460009161251a9185916bffffffffffffffffffffffff16906132bd565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600b6020908152604080832080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff1690557f000000000000000000000000000000000000000000000000000000000000000090931682526021905220549091506125b1906bffffffffffffffffffffffff8316906150b8565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166000818152602160205260408082209490945592517fa9059cbb00000000000000000000000000000000000000000000000000000000815291851660048301526bffffffffffffffffffffffff841660248301529063a9059cbb906044016020604051808303816000875af1158015612666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268a919061553d565b9050806126c3576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405133815273ffffffffffffffffffffffffffffffffffffffff808516916bffffffffffffffffffffffff8516918716907f9819093176a1851202c7bcfa46845809b4e47c261866550e94ed3775d2f406989060200160405180910390a450505050565b6127306131eb565b602580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152601260205260409020541633146127ba576040517f6752e7aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81811660008181526011602090815260408083208054337fffffffffffffffffffffffff000000000000000000000000000000000000000080831682179093556012909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915261297283612962816134e7565b8360400151846101000151611eb5565b9392505050565b606060248054806020026020016040519081016040528092919081815260200182805480156129de57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116129b3575b5050505050905090565b604080516102008101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a082018390526101c08201526101e0810191909152604080516102008101825260165463ffffffff74010000000000000000000000000000000000000000808304821684527801000000000000000000000000000000000000000000000000808404831660208601526017547c0100000000000000000000000000000000000000000000000000000000810484169686019690965273ffffffffffffffffffffffffffffffffffffffff938416606086015260145460ff828204161515608087015262ffffff70010000000000000000000000000000000082041660a0870152601854928304841660c087015290820490921660e085015293821661010084015261ffff7301000000000000000000000000000000000000009091041661012083015291909116610140820152601954610160820152601a54610180820152601b546101a08201526101c08101612baa60096131de565b815260155473ffffffffffffffffffffffffffffffffffffffff16602090910152919050565b604080516101408101825260008082526020820181905260609282018390528282018190526080820181905260a0820181905260c0820181905260e082018190526101008201526101208101919091526000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a010000000000000000000090910481166080830181905260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c0100000000000000000000000000000000000000000000000000000000900490941660e08301526002909201549091169281019290925290919015612da557816080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da0919061555f565b612da8565b60005b90506040518061014001604052808273ffffffffffffffffffffffffffffffffffffffff168152602001836040015163ffffffff168152602001600760008781526020019081526020016000208054612e0090615161565b80601f0160208091040260200160405190810160405280929190818152602001828054612e2c90615161565b8015612e795780601f10612e4e57610100808354040283529160200191612e79565b820191906000526020600020905b815481529060010190602001808311612e5c57829003601f168201915b505050505081526020018360c001516bffffffffffffffffffffffff1681526020016005600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001836060015163ffffffff1667ffffffffffffffff1681526020018360e0015163ffffffff1681526020018360a001516bffffffffffffffffffffffff168152602001836000015115158152602001601e60008781526020019081526020016000208054612f5690615161565b80601f0160208091040260200160405190810160405280929190818152602001828054612f8290615161565b8015612fcf5780601f10612fa457610100808354040283529160200191612fcf565b820191906000526020600020905b815481529060010190602001808311612fb257829003601f168201915b505050505081525092505050919050565b6000612fea613af4565b905090565b60006110a182612852565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526011602052604090205416331461305a576040517fcebf515b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216036130a9576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601260205260409020548116908216146131555773ffffffffffffffffffffffffffffffffffffffff82811660008181526012602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169486169485179055513392917f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836791a45b5050565b6131616131eb565b61316a81613bbe565b50565b6000612fea60025b60006110a1825490565b60006129728383613cb3565b60175473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6060600061297283613cdd565b60005473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016121ea565b60185473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134b9576000816060015185613355919061541d565b905060006133638583615471565b90508083604001818151613377919061549c565b6bffffffffffffffffffffffff16905250613392858261557c565b836060018181516133a3919061549c565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60006129728373ffffffffffffffffffffffffffffffffffffffff8416613d38565b6000818160045b600f811015613574577fff00000000000000000000000000000000000000000000000000000000000000821683826020811061352c5761352c6150fa565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461356257506000949350505050565b8061356c81615129565b9150506134ee565b5081600f1a600181111561358a5761358a614af5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561361f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364391906155c3565b509450909250505060008113158061365a57508142105b8061367b575082801561367b575061367282426150b8565b8463ffffffff16105b1561368a57601954965061368e565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156136f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371d91906155c3565b509450909250505060008113158061373457508142105b806137555750828015613755575061374c82426150b8565b8463ffffffff16105b1561376457601a549550613768565b8095505b86866137738a613e2b565b965096509650505050509193909250565b600080808089600181111561379b5761379b614af5565b036137aa575062017f986137ff565b60018960018111156137be576137be614af5565b036137cd57506201de846137ff565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016138129190615613565b6138209060ff16604061562c565b60185461384e906103a49074010000000000000000000000000000000000000000900463ffffffff166150a5565b61385891906150a5565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156138c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ed9190615643565b909250905081836138ff8360186150a5565b613909919061562c565b60808f0151613919906001615613565b6139289060ff166115e061562c565b61393291906150a5565b61393c91906150a5565b61394690856150a5565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156139b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dd9190615524565b8d6060015161ffff166139f0919061562c565b94505050506000613a018b86613f15565b60008d815260046020526040902054909150610100900460ff1615613a665760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b6000613ad08c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250614091565b60208101518151919250613ae39161549c565b9d9c50505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015613b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb49190615524565b612fea9190615667565b3373ffffffffffffffffffffffffffffffffffffffff821603613c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016121ea565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613cca57613cca6150fa565b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561160f57602002820191906000526020600020905b815481526020019060010190808311613d195750505050509050919050565b60008181526001830160205260408120548015613e21576000613d5c6001836150b8565b8554909150600090613d70906001906150b8565b9050818114613dd5576000866000018281548110613d9057613d906150fa565b9060005260206000200154905080876000018481548110613db357613db36150fa565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613de657613de6615687565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506110a1565b60009150506110a1565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613e9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ebf91906155c3565b50935050925050600082131580613ed557508042105b80613f0557506000846040015162ffffff16118015613f055750613ef981426150b8565b846040015162ffffff16105b156123f3575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015614002573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061402691906155c3565b5093505092505060008213158061403c57508042105b8061406c57506000866040015162ffffff1611801561406c575061406081426150b8565b866040015162ffffff16105b156140805760018301546060850152614088565b606084018290525b50505092915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516140fc919061562c565b9050836101000151801561410f5750803a105b1561411757503a5b60006012831161412857600161413e565b6141336012846150b8565b61413e90600a6157d6565b9050600060128410614151576001614167565b61415c8460126150b8565b61416790600a6157d6565b905060008660a0015187604001518860200151896000015161418991906150a5565b614193908761562c565b61419d91906150a5565b6141a7919061562c565b9050614203828860e00151606001516141c0919061562c565b6001848a60e00151606001516141d6919061562c565b6141e091906150b8565b6141ea868561562c565b6141f491906150a5565b6141fe91906157e2565b6143d8565b6bffffffffffffffffffffffff1686526080870151614226906141fe90836157e2565b6bffffffffffffffffffffffff1660408088019190915260e0880151015160009061425f9062ffffff16683635c9adc5dea0000061562c565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b614292919061562c565b61429c91906150a5565b6142a6919061562c565b6142b0919061562c565b6142ba91906157e2565b6142c491906150a5565b9050614307848a60e00151606001516142dd919061562c565b6001868c60e00151606001516142f3919061562c565b6142fd91906150b8565b6141ea888561562c565b6bffffffffffffffffffffffff166020890152608089015161432d906141fe90836157e2565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a0191909152890151614370906143d8565b6bffffffffffffffffffffffff1660a0808a0191909152890151614393906143d8565b6bffffffffffffffffffffffff1660c089015260e0890151606001516143b8906143d8565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff821115614476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016121ea565b5090565b6000806040838503121561448d57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b838110156144cc578151875295820195908201906001016144b0565b509495945050505050565b602081526000612972602083018461449c565b60008083601f8401126144fc57600080fd5b50813567ffffffffffffffff81111561451457600080fd5b60208301915083602082850101111561452c57600080fd5b9250929050565b60008060006040848603121561454857600080fd5b83359250602084013567ffffffffffffffff81111561456657600080fd5b614572868287016144ea565b9497909650939450505050565b600081518084526020808501945080840160005b838110156144cc57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614593565b805163ffffffff16825260006101e060208301516145eb602086018263ffffffff169052565b506040830151614603604086018263ffffffff169052565b50606083015161461a606086018262ffffff169052565b506080830151614630608086018261ffff169052565b5060a083015161465060a08601826bffffffffffffffffffffffff169052565b5060c083015161466860c086018263ffffffff169052565b5060e083015161468060e086018263ffffffff169052565b506101008381015163ffffffff908116918601919091526101208085015190911690850152610140808401519085015261016080840151908501526101808084015173ffffffffffffffffffffffffffffffffffffffff16908501526101a0808401518186018390526146f58387018261457f565b925050506101c0808401516147218287018273ffffffffffffffffffffffffffffffffffffffff169052565b5090949350505050565b855163ffffffff16815260006101c0602088015161475960208501826bffffffffffffffffffffffff169052565b5060408801516040840152606088015161478360608501826bffffffffffffffffffffffff169052565b506080880151608084015260a08801516147a560a085018263ffffffff169052565b5060c08801516147bd60c085018263ffffffff169052565b5060e088015160e0840152610100808901516147e08286018263ffffffff169052565b5050610120888101511515908401526101408301819052614803818401886145c5565b9050828103610160840152614818818761457f565b905082810361018084015261482d818661457f565b9150506148406101a083018460ff169052565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461316a57600080fd5b6000806040838503121561487f57600080fd5b823561488a8161484a565b915060208301356004811061489e57600080fd5b809150509250929050565b6000602082840312156148bb57600080fd5b5035919050565b6000815180845260005b818110156148e8576020818501810151868301820152016148cc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061297260208301846148c2565b815173ffffffffffffffffffffffffffffffffffffffff1681526101608101602083015161496f602084018263ffffffff169052565b506040830151614987604084018263ffffffff169052565b50606083015161499f606084018263ffffffff169052565b5060808301516149c7608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08301516149df60a084018263ffffffff169052565b5060c08301516149f760c084018263ffffffff169052565b5060e0830151614a0f60e084018263ffffffff169052565b506101008381015173ffffffffffffffffffffffffffffffffffffffff81168483015250506101208381015163ffffffff81168483015250506101408381015163ffffffff8116848301525b505092915050565b60008060208385031215614a7657600080fd5b823567ffffffffffffffff80821115614a8e57600080fd5b818501915085601f830112614aa257600080fd5b813581811115614ab157600080fd5b8660208260051b8501011115614ac657600080fd5b60209290920196919550909350505050565b600060208284031215614aea57600080fd5b81356129728161484a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061316a5761316a614af5565b60208101614b4183614b24565b91905290565b60008060008060808587031215614b5d57600080fd5b84359350602085013560028110614b7357600080fd5b9250604085013563ffffffff81168114614b8c57600080fd5b91506060850135614b9c8161484a565b939692955090935050565b600080600060408486031215614bbc57600080fd5b8335614bc78161484a565b9250602084013567ffffffffffffffff81111561456657600080fd5b602080825282518282018190526000919060409081850190868401855b82811015614c3f578151805173ffffffffffffffffffffffffffffffffffffffff90811686529087015116868501529284019290850190600101614c00565b5091979650505050505050565b60008060408385031215614c5f57600080fd5b8235614c6a8161484a565b9150602083013561489e8161484a565b6020808252825182820181905260009190848201906040850190845b81811015614cc857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614c96565b50909695505050505050565b60208152614ceb60208201835163ffffffff169052565b60006020830151614d04604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e0830151610100614d838185018363ffffffff169052565b8401519050610120614dac8482018373ffffffffffffffffffffffffffffffffffffffff169052565b8401519050610140614dc38482018361ffff169052565b8401519050610160614dec8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e080860182905291925090614e3461022086018461457f565b9086015173ffffffffffffffffffffffffffffffffffffffff811683870152909250614721565b60208152614e8260208201835173ffffffffffffffffffffffffffffffffffffffff169052565b60006020830151614e9b604084018263ffffffff169052565b506040830151610140806060850152614eb86101608501836148c2565b91506060850151614ed960808601826bffffffffffffffffffffffff169052565b50608085015173ffffffffffffffffffffffffffffffffffffffff811660a08601525060a085015167ffffffffffffffff811660c08601525060c085015163ffffffff811660e08601525060e0850151610100614f45818701836bffffffffffffffffffffffff169052565b8601519050610120614f5a8682018315159052565b8601518584037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00183870152905061484083826148c2565b6000610120820190506bffffffffffffffffffffffff835116825263ffffffff60208401511660208301526040830151614fd3604084018262ffffff169052565b506060830151614fe9606084018261ffff169052565b506080830151614ffe608084018260ff169052565b5060a083015161501260a084018215159052565b5060c083015161502660c084018215159052565b5060e083015161503a60e084018215159052565b506101008381015173ffffffffffffffffffffffffffffffffffffffff811684830152614a5b565b6020810160048310614b4157614b41614af5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156110a1576110a1615076565b818103818111156110a1576110a1615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361515a5761515a615076565b5060010190565b600181811c9082168061517557607f821691505b6020821081036151ae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156151fe57600081815260208120601f850160051c810160208610156151db5750805b601f850160051c820191505b818110156151fa578281556001016151e7565b5050505b505050565b67ffffffffffffffff83111561521b5761521b6150cb565b61522f836152298354615161565b836151b4565b6000601f841160018114615281576000851561524b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355615317565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156152d057868501358255602094850194600190920191016152b0565b508682101561530b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b6000604082016040835280865480835260608501915087600052602092508260002060005b828110156153c257815473ffffffffffffffffffffffffffffffffffffffff1684529284019260019182019101615390565b505050838103828501528481528590820160005b868110156154115782356153e98161484a565b73ffffffffffffffffffffffffffffffffffffffff16825291830191908301906001016153d6565b50979650505050505050565b6bffffffffffffffffffffffff8281168282160390808211156123f3576123f3615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006bffffffffffffffffffffffff8084168061549057615490615442565b92169190910492915050565b6bffffffffffffffffffffffff8181168382160190808211156123f3576123f3615076565b6000816154d0576154d0615076565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b604081526000615509604083018561457f565b828103602084015261551b818561449c565b95945050505050565b60006020828403121561553657600080fd5b5051919050565b60006020828403121561554f57600080fd5b8151801515811461297257600080fd5b60006020828403121561557157600080fd5b81516129728161484a565b6bffffffffffffffffffffffff818116838216028082169190828114614a5b57614a5b615076565b805169ffffffffffffffffffff811681146155be57600080fd5b919050565b600080600080600060a086880312156155db57600080fd5b6155e4866155a4565b9450602086015193506040860151925060608601519150615607608087016155a4565b90509295509295909350565b60ff81811683821601908111156110a1576110a1615076565b80820281158282048414176110a1576110a1615076565b6000806040838503121561565657600080fd5b505080516020909101519092909150565b81810360008312801583831316838312821617156123f3576123f3615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600181815b8085111561570f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156156f5576156f5615076565b8085161561570257918102915b93841c93908002906156bb565b509250929050565b600082615726575060016110a1565b81615733575060006110a1565b816001811461574957600281146157535761576f565b60019150506110a1565b60ff84111561576457615764615076565b50506001821b6110a1565b5060208310610133831016604e8410600b8410161715615792575081810a6110a1565b61579c83836156b6565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156157ce576157ce615076565b029392505050565b60006129728383615717565b6000826157f1576157f1615442565b50049056fea164736f6c6343000813000a", + Bin: "0x6101606040523480156200001257600080fd5b5060405162005c8738038062005c87833981016040819052620000359162000309565b87878787878787873380600081620000945760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c757620000c78162000241565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff191660018381811115620001185762000118620003b6565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000179573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019f9190620003cc565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002099190620003cc565b60ff16146200022b576040516301f86e1760e41b815260040160405180910390fd5b50505050505050505050505050505050620003f8565b336001600160a01b038216036200029b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008b565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200030457600080fd5b919050565b600080600080600080600080610100898b0312156200032757600080fd5b6200033289620002ec565b97506200034260208a01620002ec565b96506200035260408a01620002ec565b95506200036260608a01620002ec565b94506200037260808a01620002ec565b93506200038260a08a01620002ec565b925060c0890151600281106200039757600080fd5b9150620003a760e08a01620002ec565b90509295985092959890939650565b634e487b7160e01b600052602160045260246000fd5b600060208284031215620003df57600080fd5b815160ff81168114620003f157600080fd5b9392505050565b60805160a05160c05160e051610100516101205161014051615803620004846000396000610b7001526000610ad2015260006107be0152600081816109a001526135b60152600081816109540152613e3201526000818161051d0152613690015260008181610c1801528181611df00152818161256b015281816125c80152613af601526158036000f3fe608060405234801561001057600080fd5b50600436106103d05760003560e01c80638ed02bab116101ff578063c3f909d41161011a578063eb5dcd6c116100ad578063f5a418461161007c578063f5a4184614610eb4578063f777ff0614610f35578063faa3e99614610f3c578063ffd242bd14610f8257600080fd5b8063eb5dcd6c14610de5578063ec4de4ba14610df8578063ed56b3e114610e2e578063f2fde38b14610ea157600080fd5b8063d09dc339116100e9578063d09dc33914610c3c578063d763264814610c44578063d85aa07c14610c57578063e80a3d4414610c5f57600080fd5b8063c3f909d414610bd6578063c5b964e014610beb578063c7c3a19a14610bf6578063ca30e60314610c1657600080fd5b8063aab9edd611610192578063b3596c2311610161578063b3596c23146107e2578063b6511a2a14610ba7578063b657bc9c14610bae578063ba87666814610bc157600080fd5b8063aab9edd614610b57578063abc76ae014610b66578063ac4dc59a14610b6e578063b121e14714610b9457600080fd5b8063a08714c0116101ce578063a08714c014610ad0578063a538b2eb14610af6578063a710b22114610b3c578063a87f45fe14610b4f57600080fd5b80638ed02bab14610a5c5780639089daa414610a7a57806393f6ebcf14610a8f5780639e0a99ed14610ac857600080fd5b806343cc055c116102ef5780636209e1e91161028257806379ba50971161025157806379ba5097146109ea57806379ea9943146109f25780638456cb5914610a365780638da5cb5b14610a3e57600080fd5b80636209e1e91461098b5780636709d0e51461099e578063671d36ed146109c45780636eec02a2146109d757600080fd5b80635425d8ac116102be5780635425d8ac146107bc57806357359584146107e2578063614486af146109525780636181d82d1461097857600080fd5b806343cc055c1461074957806344cb70b8146107705780634ca16c52146107935780635147cd591461079c57600080fd5b8063207b6516116103675780633b9cce59116103365780633b9cce59146106c05780633f4ba83a146106d3578063421d183b146106db57806343b46e5f1461074157600080fd5b8063207b651614610508578063226cf83c1461051b578063232c1cc5146105625780633408f73a1461056957600080fd5b8063187256e8116103a3578063187256e81461043b57806319d97a941461044e5780631e0104391461046e5780631efcf646146104d057600080fd5b8063050ee65d146103d557806306e3b632146103ed5780630b7d33e61461040d5780631865c57d14610422575b600080fd5b6201e26c5b6040519081526020015b60405180910390f35b6104006103fb36600461447a565b610f8a565b6040516103e491906144d7565b61042061041b366004614533565b6110a7565b005b61042a611108565b6040516103e495949392919061472b565b61042061044936600461486c565b611508565b61046161045c3660046148a9565b611579565b6040516103e49190614926565b6104b361047c3660046148a9565b60009081526004602052604090206001015470010000000000000000000000000000000090046bffffffffffffffffffffffff1690565b6040516bffffffffffffffffffffffff90911681526020016103e4565b6104f86104de3660046148a9565b600090815260046020526040902054610100900460ff1690565b60405190151581526020016103e4565b6104616105163660046148a9565b61161b565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103e4565b60186103da565b6106b36040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915250604080516101608101825260165473ffffffffffffffffffffffffffffffffffffffff808216835263ffffffff740100000000000000000000000000000000000000008084048216602086015278010000000000000000000000000000000000000000000000008085048316968601969096527c010000000000000000000000000000000000000000000000000000000093849004821660608601526017548084166080870152818104831660a0870152868104831660c087015293909304811660e085015260185491821661010085015291810482166101208401529290920490911661014082015290565b6040516103e49190614939565b6104206106ce366004614a63565b611638565b61042061188e565b6106ee6106e9366004614ad8565b6118f4565b60408051951515865260ff90941660208601526bffffffffffffffffffffffff9283169385019390935216606083015273ffffffffffffffffffffffffffffffffffffffff16608082015260a0016103e4565b610420611a13565b6014547801000000000000000000000000000000000000000000000000900460ff166104f8565b6104f861077e3660046148a9565b60009081526008602052604090205460ff1690565b62017f986103da565b6107af6107aa3660046148a9565b611eaa565b6040516103e49190614b34565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6108d46107f0366004614ad8565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525073ffffffffffffffffffffffffffffffffffffffff908116600090815260226020908152604091829020825160c081018452815463ffffffff81168252640100000000810462ffffff16938201939093526701000000000000008304909416928401929092527b01000000000000000000000000000000000000000000000000000000900460ff16606083015260018101546080830152600201546bffffffffffffffffffffffff1660a082015290565b6040516103e49190600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104b3610986366004614b47565b611eb5565b610461610999366004614ad8565b612010565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104206109d2366004614ba7565b612043565b6103da6109e5366004614ad8565b6120c3565b61042061216d565b61053d610a003660046148a9565b6000908152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61042061226f565b60005473ffffffffffffffffffffffffffffffffffffffff1661053d565b60155473ffffffffffffffffffffffffffffffffffffffff1661053d565b610a826122e8565b6040516103e49190614be3565b61053d610a9d3660046148a9565b60009081526004602052604090206002015473ffffffffffffffffffffffffffffffffffffffff1690565b6103a46103da565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104f8610b04366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260226020526040902054670100000000000000900416151590565b610420610b4a366004614c4c565b6123fa565b610420612728565b604051600481526020016103e4565b6115e06103da565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b610420610ba2366004614ad8565b61275a565b60326103da565b6104b3610bbc3660046148a9565b612852565b610bc9612979565b6040516103e49190614c7a565b610bde6129e8565b6040516103e49190614cd4565b60255460ff166107af565b610c09610c043660046148a9565b612bd0565b6040516103e49190614e5b565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6103da612fe0565b6104b3610c523660046148a9565b612fef565b601b546103da565b610dd86040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091525060408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff750100000000000000000000000000000000000000000083048116608083015276010000000000000000000000000000000000000000000083048116151560a08301527701000000000000000000000000000000000000000000000083048116151560c08301527801000000000000000000000000000000000000000000000000909204909116151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290565b6040516103e49190614f92565b610420610df3366004614c4c565b612ffa565b6103da610e06366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205490565b610e88610e3c366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602090815260409182902082518084019093525460ff8082161515808552610100909204169290910182905291565b60408051921515835260ff9091166020830152016103e4565b610420610eaf366004614ad8565b613159565b610f0f610ec23660046148a9565b60408051808201909152600080825260208201525060009081526023602090815260409182902082518084019093525463ffffffff81168352640100000000900462ffffff169082015290565b60408051825163ffffffff16815260209283015162ffffff1692810192909252016103e4565b60406103da565b610f75610f4a366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff166000908152601c602052604090205460ff1690565b6040516103e49190615062565b6103da61316d565b60606000610f986002613175565b9050808410610fd3576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610fdf84866150a5565b905081811180610fed575083155b610ff75780610ff9565b815b9050600061100786836150b8565b67ffffffffffffffff81111561101f5761101f6150cb565b604051908082528060200260200182016040528015611048578160200160208202803683370190505b50905060005b815181101561109b5761106c61106488836150a5565b60029061317f565b82828151811061107e5761107e6150fa565b60209081029190910101528061109381615129565b91505061104e565b50925050505b92915050565b6110af61318b565b6000838152601f602052604090206110c8828483615203565b50827f2fd8d70753a007014349d4591843cc031c2dd7a260d7dd82eca8253686ae776983836040516110fb92919061531e565b60405180910390a2505050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810191909152604080516101e08101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a08201526101c081019190915260408051610140810182526016547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1681526000602082018190529181018290526014546bffffffffffffffffffffffff16606080830191909152918291608081016112416002613175565b81526017547401000000000000000000000000000000000000000080820463ffffffff908116602080860191909152780100000000000000000000000000000000000000000000000080850483166040808801919091526013546060808901919091526014546c01000000000000000000000000810486166080808b0191909152760100000000000000000000000000000000000000000000820460ff16151560a09a8b015283516101e0810185526000808252968101879052601654898104891695820195909552700100000000000000000000000000000000830462ffffff169381019390935273010000000000000000000000000000000000000090910461ffff169082015296870192909252808204831660c08701527c0100000000000000000000000000000000000000000000000000000000909404821660e086015260185492830482166101008601529290910416610120830152601954610140830152601a5461016083015273ffffffffffffffffffffffffffffffffffffffff166101808201529095506101a081016113dc60096131de565b815260175473ffffffffffffffffffffffffffffffffffffffff16602091820152601454600d80546040805182860281018601909152818152949850899489949293600e93750100000000000000000000000000000000000000000090910460ff1692859183018282801561148757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161145c575b50505050509250818054806020026020016040519081016040528092919081815260200182805480156114f057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116114c5575b50505050509150945094509450945094509091929394565b6115106131eb565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601c6020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561157057611570614af5565b02179055505050565b6000818152601f6020526040902080546060919061159690615161565b80601f01602080910402602001604051908101604052809291908181526020018280546115c290615161565b801561160f5780601f106115e45761010080835404028352916020019161160f565b820191906000526020600020905b8154815290600101906020018083116115f257829003601f168201915b50505050509050919050565b6000818152601d6020526040902080546060919061159690615161565b6116406131eb565b600e54811461167b576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b600e5481101561184d576000600e828154811061169d5761169d6150fa565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526011909252604083205491935016908585858181106116e7576116e76150fa565b90506020020160208101906116fc9190614ad8565b905073ffffffffffffffffffffffffffffffffffffffff8116158061178f575073ffffffffffffffffffffffffffffffffffffffff82161580159061176d57508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561178f575073ffffffffffffffffffffffffffffffffffffffff81811614155b156117c6576040517fb387a23800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff818116146118375773ffffffffffffffffffffffffffffffffffffffff838116600090815260116020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169183169190911790555b505050808061184590615129565b91505061167e565b507fa46de38886467c59be07a0675f14781206a5477d871628af46c2443822fcb725600e83836040516118829392919061536b565b60405180910390a15050565b6118966131eb565b601480547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e0100000000000000000000000000009004909116606082015282918291829182919082906119ba5760608201516014546000916119a6916bffffffffffffffffffffffff1661541d565b600e549091506119b69082615471565b9150505b8151602083015160408401516119d190849061549c565b6060949094015173ffffffffffffffffffffffffffffffffffffffff9a8b16600090815260116020526040902054929b919a9499509750921694509092505050565b611a1b61326c565b600060255460ff166001811115611a3457611a34614af5565b03611a6b576040517fe0262d7400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600e546bffffffffffffffffffffffff909116906000611a8e600f613175565b90506000611a9c82846150a5565b905060008167ffffffffffffffff811115611ab957611ab96150cb565b604051908082528060200260200182016040528015611ae2578160200160208202803683370190505b50905060008267ffffffffffffffff811115611b0057611b006150cb565b604051908082528060200260200182016040528015611b29578160200160208202803683370190505b50905060005b85811015611c5b576000600e8281548110611b4c57611b4c6150fa565b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff169150611b7a828a8a6132bd565b9050806bffffffffffffffffffffffff16858481518110611b9d57611b9d6150fa565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff808416600090815260119092526040909120548551911690859085908110611beb57611beb6150fa565b73ffffffffffffffffffffffffffffffffffffffff92831660209182029290920181019190915292166000908152600b909252506040902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905580611c5381615129565b915050611b2f565b5060005b84811015611dd8576000611c74600f8361317f565b73ffffffffffffffffffffffffffffffffffffffff8082166000818152600b602090815260408083208151608081018352905460ff80821615158352610100820416828501526bffffffffffffffffffffffff6201000082048116838501526e0100000000000000000000000000009091041660608201529383526011909152902054929350911684611d078a866150a5565b81518110611d1757611d176150fa565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260408101516bffffffffffffffffffffffff1685611d5a8a866150a5565b81518110611d6a57611d6a6150fa565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff9092166000908152600b909252506040902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905580611dd081615129565b915050611c5f565b5073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166000908152602160205260408120819055611e2b600f613175565b90505b8015611e6857611e55611e4d611e456001846150b8565b600f9061317f565b600f906134c5565b5080611e60816154c1565b915050611e2e565b507f5af23b715253628d12b660b27a4f3fc626562ea8a55040aa99ab3dc178989fad8183604051611e9a9291906154f6565b60405180910390a1505050505050565b60006110a1826134e7565b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff750100000000000000000000000000000000000000000083048116608083015276010000000000000000000000000000000000000000000083048116151560a08301527701000000000000000000000000000000000000000000000083048116151560c08301527801000000000000000000000000000000000000000000000000909204909116151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152600090818080611fed84613592565b92509250925061200389858a8a8787878d613784565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040902080546060919061159690615161565b61204b61318b565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602080526040902061207a828483615203565b508273ffffffffffffffffffffffffffffffffffffffff167f7c44b4eb59ee7873514e7e43e7718c269d872965938b288aa143befca62f99d283836040516110fb92919061531e565b73ffffffffffffffffffffffffffffffffffffffff81166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa15801561213f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121639190615524565b6110a191906150b8565b60015473ffffffffffffffffffffffffffffffffffffffff1633146121f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6122776131eb565b601480547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff167601000000000000000000000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016118ea565b600e5460609060008167ffffffffffffffff811115612309576123096150cb565b60405190808252806020026020018201604052801561234e57816020015b60408051808201909152600080825260208201528152602001906001900390816123275790505b50905060005b828110156123f3576000600e8281548110612371576123716150fa565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526011835260409384902054845180860190955281855290911691830182905285519093509091908590859081106123d3576123d36150fa565b6020026020010181905250505080806123eb90615129565b915050612354565b5092915050565b73ffffffffffffffffffffffffffffffffffffffff8116612447576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160255460ff16600181111561246057612460614af5565b03612497576040517f4a3578fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601160205260409020541633146124f7576040517fcebf515b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600e5460009161251a9185916bffffffffffffffffffffffff16906132bd565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600b6020908152604080832080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff1690557f000000000000000000000000000000000000000000000000000000000000000090931682526021905220549091506125b1906bffffffffffffffffffffffff8316906150b8565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166000818152602160205260408082209490945592517fa9059cbb00000000000000000000000000000000000000000000000000000000815291851660048301526bffffffffffffffffffffffff841660248301529063a9059cbb906044016020604051808303816000875af1158015612666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268a919061553d565b9050806126c3576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405133815273ffffffffffffffffffffffffffffffffffffffff808516916bffffffffffffffffffffffff8516918716907f9819093176a1851202c7bcfa46845809b4e47c261866550e94ed3775d2f406989060200160405180910390a450505050565b6127306131eb565b602580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152601260205260409020541633146127ba576040517f6752e7aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81811660008181526011602090815260408083208054337fffffffffffffffffffffffff000000000000000000000000000000000000000080831682179093556012909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915261297283612962816134e7565b8360400151846101000151611eb5565b9392505050565b606060248054806020026020016040519081016040528092919081815260200182805480156129de57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116129b3575b5050505050905090565b604080516102008101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a082018390526101c08201526101e0810191909152604080516102008101825260165463ffffffff74010000000000000000000000000000000000000000808304821684527801000000000000000000000000000000000000000000000000808404831660208601526017547c0100000000000000000000000000000000000000000000000000000000810484169686019690965273ffffffffffffffffffffffffffffffffffffffff938416606086015260145460ff828204161515608087015262ffffff70010000000000000000000000000000000082041660a0870152601854928304841660c087015290820490921660e085015293821661010084015261ffff7301000000000000000000000000000000000000009091041661012083015291909116610140820152601954610160820152601a54610180820152601b546101a08201526101c08101612baa60096131de565b815260155473ffffffffffffffffffffffffffffffffffffffff16602090910152919050565b604080516101408101825260008082526020820181905260609282018390528282018190526080820181905260a0820181905260c0820181905260e082018190526101008201526101208101919091526000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a010000000000000000000090910481166080830181905260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c0100000000000000000000000000000000000000000000000000000000900490941660e08301526002909201549091169281019290925290919015612da557816080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da0919061555f565b612da8565b60005b90506040518061014001604052808273ffffffffffffffffffffffffffffffffffffffff168152602001836040015163ffffffff168152602001600760008781526020019081526020016000208054612e0090615161565b80601f0160208091040260200160405190810160405280929190818152602001828054612e2c90615161565b8015612e795780601f10612e4e57610100808354040283529160200191612e79565b820191906000526020600020905b815481529060010190602001808311612e5c57829003601f168201915b505050505081526020018360c001516bffffffffffffffffffffffff1681526020016005600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001836060015163ffffffff1667ffffffffffffffff1681526020018360e0015163ffffffff1681526020018360a001516bffffffffffffffffffffffff168152602001836000015115158152602001601e60008781526020019081526020016000208054612f5690615161565b80601f0160208091040260200160405190810160405280929190818152602001828054612f8290615161565b8015612fcf5780601f10612fa457610100808354040283529160200191612fcf565b820191906000526020600020905b815481529060010190602001808311612fb257829003601f168201915b505050505081525092505050919050565b6000612fea613af4565b905090565b60006110a182612852565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526011602052604090205416331461305a576040517fcebf515b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216036130a9576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601260205260409020548116908216146131555773ffffffffffffffffffffffffffffffffffffffff82811660008181526012602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169486169485179055513392917f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836791a45b5050565b6131616131eb565b61316a81613bbe565b50565b6000612fea60025b60006110a1825490565b60006129728383613cb3565b60175473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6060600061297283613cdd565b60005473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016121ea565b60185473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134b9576000816060015185613355919061541d565b905060006133638583615471565b90508083604001818151613377919061549c565b6bffffffffffffffffffffffff16905250613392858261557c565b836060018181516133a3919061549c565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60006129728373ffffffffffffffffffffffffffffffffffffffff8416613d38565b6000818160045b600f811015613574577fff00000000000000000000000000000000000000000000000000000000000000821683826020811061352c5761352c6150fa565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461356257506000949350505050565b8061356c81615129565b9150506134ee565b5081600f1a600181111561358a5761358a614af5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561361f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364391906155c3565b509450909250505060008113158061365a57508142105b8061367b575082801561367b575061367282426150b8565b8463ffffffff16105b1561368a57601954965061368e565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156136f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371d91906155c3565b509450909250505060008113158061373457508142105b806137555750828015613755575061374c82426150b8565b8463ffffffff16105b1561376457601a549550613768565b8095505b86866137738a613e2b565b965096509650505050509193909250565b600080808089600181111561379b5761379b614af5565b036137aa575062017f986137ff565b60018960018111156137be576137be614af5565b036137cd57506201e26c6137ff565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016138129190615613565b6138209060ff16604061562c565b60185461384e906103a49074010000000000000000000000000000000000000000900463ffffffff166150a5565b61385891906150a5565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156138c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ed9190615643565b909250905081836138ff8360186150a5565b613909919061562c565b60808f0151613919906001615613565b6139289060ff166115e061562c565b61393291906150a5565b61393c91906150a5565b61394690856150a5565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156139b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dd9190615524565b8d6060015161ffff166139f0919061562c565b94505050506000613a018b86613f15565b60008d815260046020526040902054909150610100900460ff1615613a665760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b6000613ad08c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250614091565b60208101518151919250613ae39161549c565b9d9c50505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015613b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb49190615524565b612fea9190615667565b3373ffffffffffffffffffffffffffffffffffffffff821603613c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016121ea565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613cca57613cca6150fa565b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561160f57602002820191906000526020600020905b815481526020019060010190808311613d195750505050509050919050565b60008181526001830160205260408120548015613e21576000613d5c6001836150b8565b8554909150600090613d70906001906150b8565b9050818114613dd5576000866000018281548110613d9057613d906150fa565b9060005260206000200154905080876000018481548110613db357613db36150fa565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613de657613de6615687565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506110a1565b60009150506110a1565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613e9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ebf91906155c3565b50935050925050600082131580613ed557508042105b80613f0557506000846040015162ffffff16118015613f055750613ef981426150b8565b846040015162ffffff16105b156123f3575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015614002573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061402691906155c3565b5093505092505060008213158061403c57508042105b8061406c57506000866040015162ffffff1611801561406c575061406081426150b8565b866040015162ffffff16105b156140805760018301546060850152614088565b606084018290525b50505092915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516140fc919061562c565b9050836101000151801561410f5750803a105b1561411757503a5b60006012831161412857600161413e565b6141336012846150b8565b61413e90600a6157d6565b9050600060128410614151576001614167565b61415c8460126150b8565b61416790600a6157d6565b905060008660a0015187604001518860200151896000015161418991906150a5565b614193908761562c565b61419d91906150a5565b6141a7919061562c565b9050614203828860e00151606001516141c0919061562c565b6001848a60e00151606001516141d6919061562c565b6141e091906150b8565b6141ea868561562c565b6141f491906150a5565b6141fe91906157e2565b6143d8565b6bffffffffffffffffffffffff1686526080870151614226906141fe90836157e2565b6bffffffffffffffffffffffff1660408088019190915260e0880151015160009061425f9062ffffff16683635c9adc5dea0000061562c565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b614292919061562c565b61429c91906150a5565b6142a6919061562c565b6142b0919061562c565b6142ba91906157e2565b6142c491906150a5565b9050614307848a60e00151606001516142dd919061562c565b6001868c60e00151606001516142f3919061562c565b6142fd91906150b8565b6141ea888561562c565b6bffffffffffffffffffffffff166020890152608089015161432d906141fe90836157e2565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a0191909152890151614370906143d8565b6bffffffffffffffffffffffff1660a0808a0191909152890151614393906143d8565b6bffffffffffffffffffffffff1660c089015260e0890151606001516143b8906143d8565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff821115614476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016121ea565b5090565b6000806040838503121561448d57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b838110156144cc578151875295820195908201906001016144b0565b509495945050505050565b602081526000612972602083018461449c565b60008083601f8401126144fc57600080fd5b50813567ffffffffffffffff81111561451457600080fd5b60208301915083602082850101111561452c57600080fd5b9250929050565b60008060006040848603121561454857600080fd5b83359250602084013567ffffffffffffffff81111561456657600080fd5b614572868287016144ea565b9497909650939450505050565b600081518084526020808501945080840160005b838110156144cc57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614593565b805163ffffffff16825260006101e060208301516145eb602086018263ffffffff169052565b506040830151614603604086018263ffffffff169052565b50606083015161461a606086018262ffffff169052565b506080830151614630608086018261ffff169052565b5060a083015161465060a08601826bffffffffffffffffffffffff169052565b5060c083015161466860c086018263ffffffff169052565b5060e083015161468060e086018263ffffffff169052565b506101008381015163ffffffff908116918601919091526101208085015190911690850152610140808401519085015261016080840151908501526101808084015173ffffffffffffffffffffffffffffffffffffffff16908501526101a0808401518186018390526146f58387018261457f565b925050506101c0808401516147218287018273ffffffffffffffffffffffffffffffffffffffff169052565b5090949350505050565b855163ffffffff16815260006101c0602088015161475960208501826bffffffffffffffffffffffff169052565b5060408801516040840152606088015161478360608501826bffffffffffffffffffffffff169052565b506080880151608084015260a08801516147a560a085018263ffffffff169052565b5060c08801516147bd60c085018263ffffffff169052565b5060e088015160e0840152610100808901516147e08286018263ffffffff169052565b5050610120888101511515908401526101408301819052614803818401886145c5565b9050828103610160840152614818818761457f565b905082810361018084015261482d818661457f565b9150506148406101a083018460ff169052565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461316a57600080fd5b6000806040838503121561487f57600080fd5b823561488a8161484a565b915060208301356004811061489e57600080fd5b809150509250929050565b6000602082840312156148bb57600080fd5b5035919050565b6000815180845260005b818110156148e8576020818501810151868301820152016148cc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061297260208301846148c2565b815173ffffffffffffffffffffffffffffffffffffffff1681526101608101602083015161496f602084018263ffffffff169052565b506040830151614987604084018263ffffffff169052565b50606083015161499f606084018263ffffffff169052565b5060808301516149c7608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08301516149df60a084018263ffffffff169052565b5060c08301516149f760c084018263ffffffff169052565b5060e0830151614a0f60e084018263ffffffff169052565b506101008381015173ffffffffffffffffffffffffffffffffffffffff81168483015250506101208381015163ffffffff81168483015250506101408381015163ffffffff8116848301525b505092915050565b60008060208385031215614a7657600080fd5b823567ffffffffffffffff80821115614a8e57600080fd5b818501915085601f830112614aa257600080fd5b813581811115614ab157600080fd5b8660208260051b8501011115614ac657600080fd5b60209290920196919550909350505050565b600060208284031215614aea57600080fd5b81356129728161484a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061316a5761316a614af5565b60208101614b4183614b24565b91905290565b60008060008060808587031215614b5d57600080fd5b84359350602085013560028110614b7357600080fd5b9250604085013563ffffffff81168114614b8c57600080fd5b91506060850135614b9c8161484a565b939692955090935050565b600080600060408486031215614bbc57600080fd5b8335614bc78161484a565b9250602084013567ffffffffffffffff81111561456657600080fd5b602080825282518282018190526000919060409081850190868401855b82811015614c3f578151805173ffffffffffffffffffffffffffffffffffffffff90811686529087015116868501529284019290850190600101614c00565b5091979650505050505050565b60008060408385031215614c5f57600080fd5b8235614c6a8161484a565b9150602083013561489e8161484a565b6020808252825182820181905260009190848201906040850190845b81811015614cc857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614c96565b50909695505050505050565b60208152614ceb60208201835163ffffffff169052565b60006020830151614d04604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e0830151610100614d838185018363ffffffff169052565b8401519050610120614dac8482018373ffffffffffffffffffffffffffffffffffffffff169052565b8401519050610140614dc38482018361ffff169052565b8401519050610160614dec8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e080860182905291925090614e3461022086018461457f565b9086015173ffffffffffffffffffffffffffffffffffffffff811683870152909250614721565b60208152614e8260208201835173ffffffffffffffffffffffffffffffffffffffff169052565b60006020830151614e9b604084018263ffffffff169052565b506040830151610140806060850152614eb86101608501836148c2565b91506060850151614ed960808601826bffffffffffffffffffffffff169052565b50608085015173ffffffffffffffffffffffffffffffffffffffff811660a08601525060a085015167ffffffffffffffff811660c08601525060c085015163ffffffff811660e08601525060e0850151610100614f45818701836bffffffffffffffffffffffff169052565b8601519050610120614f5a8682018315159052565b8601518584037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00183870152905061484083826148c2565b6000610120820190506bffffffffffffffffffffffff835116825263ffffffff60208401511660208301526040830151614fd3604084018262ffffff169052565b506060830151614fe9606084018261ffff169052565b506080830151614ffe608084018260ff169052565b5060a083015161501260a084018215159052565b5060c083015161502660c084018215159052565b5060e083015161503a60e084018215159052565b506101008381015173ffffffffffffffffffffffffffffffffffffffff811684830152614a5b565b6020810160048310614b4157614b41614af5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156110a1576110a1615076565b818103818111156110a1576110a1615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361515a5761515a615076565b5060010190565b600181811c9082168061517557607f821691505b6020821081036151ae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156151fe57600081815260208120601f850160051c810160208610156151db5750805b601f850160051c820191505b818110156151fa578281556001016151e7565b5050505b505050565b67ffffffffffffffff83111561521b5761521b6150cb565b61522f836152298354615161565b836151b4565b6000601f841160018114615281576000851561524b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355615317565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156152d057868501358255602094850194600190920191016152b0565b508682101561530b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b6000604082016040835280865480835260608501915087600052602092508260002060005b828110156153c257815473ffffffffffffffffffffffffffffffffffffffff1684529284019260019182019101615390565b505050838103828501528481528590820160005b868110156154115782356153e98161484a565b73ffffffffffffffffffffffffffffffffffffffff16825291830191908301906001016153d6565b50979650505050505050565b6bffffffffffffffffffffffff8281168282160390808211156123f3576123f3615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006bffffffffffffffffffffffff8084168061549057615490615442565b92169190910492915050565b6bffffffffffffffffffffffff8181168382160190808211156123f3576123f3615076565b6000816154d0576154d0615076565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b604081526000615509604083018561457f565b828103602084015261551b818561449c565b95945050505050565b60006020828403121561553657600080fd5b5051919050565b60006020828403121561554f57600080fd5b8151801515811461297257600080fd5b60006020828403121561557157600080fd5b81516129728161484a565b6bffffffffffffffffffffffff818116838216028082169190828114614a5b57614a5b615076565b805169ffffffffffffffffffff811681146155be57600080fd5b919050565b600080600080600060a086880312156155db57600080fd5b6155e4866155a4565b9450602086015193506040860151925060608601519150615607608087016155a4565b90509295509295909350565b60ff81811683821601908111156110a1576110a1615076565b80820281158282048414176110a1576110a1615076565b6000806040838503121561565657600080fd5b505080516020909101519092909150565b81810360008312801583831316838312821617156123f3576123f3615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600181815b8085111561570f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156156f5576156f5615076565b8085161561570257918102915b93841c93908002906156bb565b509250929050565b600082615726575060016110a1565b81615733575060006110a1565b816001811461574957600281146157535761576f565b60019150506110a1565b60ff84111561576457615764615076565b50506001821b6110a1565b5060208310610133831016604e8410600b8410161715615792575081810a6110a1565b61579c83836156b6565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156157ce576157ce615076565b029392505050565b60006129728383615717565b6000826157f1576157f1615442565b50049056fea164736f6c6343000813000a", } var AutomationRegistryLogicCABI = AutomationRegistryLogicCMetaData.ABI diff --git a/core/gethwrappers/generated/automation_registry_wrapper_2_2/automation_registry_wrapper_2_2.go b/core/gethwrappers/generated/automation_registry_wrapper_2_2/automation_registry_wrapper_2_2.go index eb385cf7b03..a7fcf430b3f 100644 --- a/core/gethwrappers/generated/automation_registry_wrapper_2_2/automation_registry_wrapper_2_2.go +++ b/core/gethwrappers/generated/automation_registry_wrapper_2_2/automation_registry_wrapper_2_2.go @@ -52,7 +52,7 @@ type AutomationRegistryBase22OnchainConfig struct { var AutomationRegistryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicB2_2\",\"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\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxCheckDataSizeCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxPerformDataSizeCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"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\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentGreaterThanAllLINK\",\"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\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"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\"},{\"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\":\"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\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"OwnerFundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"internalType\":\"structAutomationRegistryBase2_2.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"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: "0x6101406040523480156200001257600080fd5b506040516200524a3803806200524a8339810160408190526200003591620003b1565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b9190620003b1565b826001600160a01b031663b10b673c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001009190620003b1565b836001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001659190620003b1565b846001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca9190620003b1565b856001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f9190620003b1565b3380600081620002865760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620002b957620002b981620002ed565b5050506001600160a01b0394851660805292841660a05290831660c052821660e052811661010052166101205250620003d8565b336001600160a01b03821603620003475760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200027d565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620003ae57600080fd5b50565b600060208284031215620003c457600080fd5b8151620003d18162000398565b9392505050565b60805160a05160c05160e0516101005161012051614e25620004256000396000818160c9015261017c01526000611bb8015260005050600050506000505060006104c20152614e256000f3fe6080604052600436106100c75760003560e01c8063aed2e92911610074578063e3d0e7121161004e578063e3d0e71214610348578063f2fde38b14610368578063f75f6b1114610388576100c7565b8063aed2e929146102a3578063afcb95d7146102da578063b1dc65a414610328576100c7565b806381ff7048116100a557806381ff7048146101d65780638da5cb5b14610258578063a4c0ed3614610283576100c7565b8063181f5a771461010e578063349e8cca1461016d57806379ba5097146101c1575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610107573d6000f35b3d6000fd5b005b34801561011a57600080fd5b506101576040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e322e30000000000000000081525081565b6040516101649190613b21565b60405180910390f35b34801561017957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610164565b3480156101cd57600080fd5b5061010c6103a8565b3480156101e257600080fd5b5061023560155460115463ffffffff780100000000000000000000000000000000000000000000000083048116937c01000000000000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610164565b34801561026457600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661019c565b34801561028f57600080fd5b5061010c61029e366004613baf565b6104aa565b3480156102af57600080fd5b506102c36102be366004613c0b565b6106c6565b604080519215158352602083019190915201610164565b3480156102e657600080fd5b50601154601254604080516000815260208101939093527401000000000000000000000000000000000000000090910463ffffffff1690820152606001610164565b34801561033457600080fd5b5061010c610343366004613c9c565b61083c565b34801561035457600080fd5b5061010c610363366004613f6d565b610b77565b34801561037457600080fd5b5061010c61038336600461403a565b610ba0565b34801561039457600080fd5b5061010c6103a336600461423e565b610bb4565b60015473ffffffffffffffffffffffffffffffffffffffff16331461042e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610519576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610553576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610561828401846142cd565b60008181526004602052604090205490915065010000000000900463ffffffff908116146105bb576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600101546105f69085906c0100000000000000000000000090046bffffffffffffffffffffffff16614315565b600082815260046020526040902060010180546bffffffffffffffffffffffff929092166c01000000000000000000000000027fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff90921691909117905560195461066190859061433a565b6019556040516bffffffffffffffffffffffff8516815273ffffffffffffffffffffffffffffffffffffffff86169082907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a35050505050565b6000806106d1611ba0565b6012547e01000000000000000000000000000000000000000000000000000000000000900460ff1615610730576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825160e081018452815460ff811615158252610100810463ffffffff908116838601819052650100000000008304821684880152690100000000000000000090920473ffffffffffffffffffffffffffffffffffffffff16606084018190526001909401546bffffffffffffffffffffffff80821660808601526c0100000000000000000000000082041660a0850152780100000000000000000000000000000000000000000000000090041660c08301528451601f8901859004850281018501909552878552909361082f938990899081908401838280828437600092019190915250611c1192505050565b9097909650945050505050565b60005a60408051610160810182526012546bffffffffffffffffffffffff8116825263ffffffff6c010000000000000000000000008204811660208401527001000000000000000000000000000000008204811693830193909352740100000000000000000000000000000000000000008104909216606082015262ffffff7801000000000000000000000000000000000000000000000000830416608082015261ffff7b0100000000000000000000000000000000000000000000000000000083041660a082015260ff7d0100000000000000000000000000000000000000000000000000000000008304811660c08301527e010000000000000000000000000000000000000000000000000000000000008304811615801560e08401527f01000000000000000000000000000000000000000000000000000000000000009093048116151561010080840191909152601354918216151561012084015273ffffffffffffffffffffffffffffffffffffffff9104166101408201529192506109f2576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16610a3b576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6011548a3514610a77576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c0810151610a8790600161437c565b60ff1686141580610a985750858414155b15610acf576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610adf8a8a8a8a8a8a8a8a611e3a565b6000610aeb8a8a6120a3565b905060208b0135600881901c63ffffffff16610b0884848761215e565b836060015163ffffffff168163ffffffff161115610b6857601280547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b610b9886868686806020019051810190610b91919061443b565b8686610bb4565b505050505050565b610ba8612add565b610bb181612b5e565b50565b610bbc612add565b601f86511115610bf8576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360ff16600003610c35576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84518651141580610c545750610c4c8460036145bd565b60ff16865111155b15610c8b576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601254600e546bffffffffffffffffffffffff9091169060005b816bffffffffffffffffffffffff16811015610d0d57610cfa600e8281548110610cd157610cd161434d565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168484612c53565b5080610d05816145d9565b915050610ca5565b5060008060005b836bffffffffffffffffffffffff16811015610e1657600d8181548110610d3d57610d3d61434d565b600091825260209091200154600e805473ffffffffffffffffffffffffffffffffffffffff90921694509082908110610d7857610d7861434d565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8681168452600c8352604080852080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559116808452600b90925290912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055915080610e0e816145d9565b915050610d14565b50610e23600d6000613a00565b610e2f600e6000613a00565b604080516080810182526000808252602082018190529181018290526060810182905290805b8c5181101561129857600c60008e8381518110610e7457610e7461434d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615610edf576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168d8281518110610f0957610f0961434d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610f5e576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008f8481518110610f8f57610f8f61434d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558b518c90829081106110375761103761434d565b60200260200101519150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036110a7576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909350611162576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001835260ff80821660208086019182526bffffffffffffffffffffffff808b166060880190815273ffffffffffffffffffffffffffffffffffffffff87166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169490941717919091169290921791909117905580611290816145d9565b915050610e55565b50508a516112ae9150600d9060208d0190613a1e565b5088516112c290600e9060208c0190613a1e565b50604051806101600160405280856bffffffffffffffffffffffff168152602001886000015163ffffffff168152602001886020015163ffffffff168152602001600063ffffffff168152602001886060015162ffffff168152602001886080015161ffff1681526020018960ff1681526020016012600001601e9054906101000a900460ff16151581526020016012600001601f9054906101000a900460ff161515815260200188610200015115158152602001886101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601260008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160000160186101000a81548162ffffff021916908362ffffff16021790555060a082015181600001601b6101000a81548161ffff021916908361ffff16021790555060c082015181600001601d6101000a81548160ff021916908360ff16021790555060e082015181600001601e6101000a81548160ff02191690831515021790555061010082015181600001601f6101000a81548160ff0219169083151502179055506101208201518160010160006101000a81548160ff0219169083151502179055506101408201518160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506040518061018001604052808860a001516bffffffffffffffffffffffff16815260200188610180015173ffffffffffffffffffffffffffffffffffffffff168152602001601460010160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001886040015163ffffffff1681526020018860c0015163ffffffff168152602001601460010160149054906101000a900463ffffffff1663ffffffff168152602001601460010160189054906101000a900463ffffffff1663ffffffff1681526020016014600101601c9054906101000a900463ffffffff1663ffffffff1681526020018860e0015163ffffffff16815260200188610100015163ffffffff16815260200188610120015163ffffffff168152602001886101c0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550606082015181600101600c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160106101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160020160046101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160086101000a81548163ffffffff021916908363ffffffff16021790555061016082015181600201600c6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555090505086610140015160178190555086610160015160188190555060006014600101601c9054906101000a900463ffffffff169050876101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119879190614611565b601580547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601891611a02918591780100000000000000000000000000000000000000000000000090041661462a565b92506101000a81548163ffffffff021916908363ffffffff160217905550600088604051602001611a339190614698565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601554909150611a9c90469030907801000000000000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f612e5b565b60115560005b611aac6009612f05565b811015611adc57611ac9611ac1600983612f0f565b600990612f22565b5080611ad4816145d9565b915050611aa2565b5060005b896101a0015151811015611b3357611b208a6101a001518281518110611b0857611b0861434d565b60200260200101516009612f4490919063ffffffff16565b5080611b2b816145d9565b915050611ae0565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0582601154601460010160189054906101000a900463ffffffff168f8f8f878f8f604051611b8a9998979695949392919061483c565b60405180910390a1505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611c0f576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60125460009081907f0100000000000000000000000000000000000000000000000000000000000000900460ff1615611c76576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601280547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790556040517f4585e33b0000000000000000000000000000000000000000000000000000000090611cf2908590602401613b21565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d1690611dc590879087906004016148d2565b60408051808303816000875af1158015611de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0791906148eb565b601280547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60008787604051611e4c929190614919565b604051908190038120611e63918b90602001614929565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b8881101561203a57600185878360208110611ecf57611ecf61434d565b611edc91901a601b61437c565b8c8c85818110611eee57611eee61434d565b905060200201358b8b86818110611f0757611f0761434d565b9050602002013560405160008152602001604052604051611f44949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611f66573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612014576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b840193508080612032906145d9565b915050611eb2565b50827e01010101010101010101010101010101010101010101010101010101010101841614612095576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6120dc6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006120ea83850185614a1a565b604081015151606082015151919250908114158061210d57508082608001515114155b8061211d5750808260a001515114155b15612154576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090505b92915050565b600082604001515167ffffffffffffffff81111561217e5761217e613d53565b60405190808252806020026020018201604052801561223a57816020015b604080516101c081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161219c5790505b50905060006040518060800160405280600061ffff1681526020016000815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152509050600085610140015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fc9190614611565b9050600086610140015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123749190614611565b905060005b8660400151518110156127c35760046000886040015183815181106123a0576123a061434d565b6020908102919091018101518252818101929092526040908101600020815160e081018352815460ff811615158252610100810463ffffffff90811695830195909552650100000000008104851693820193909352690100000000000000000090920473ffffffffffffffffffffffffffffffffffffffff166060830152600101546bffffffffffffffffffffffff80821660808401526c0100000000000000000000000082041660a08301527801000000000000000000000000000000000000000000000000900490911660c082015285518690839081106124855761248561434d565b6020026020010151600001819052506124ba876040015182815181106124ad576124ad61434d565b6020026020010151612f66565b8582815181106124cc576124cc61434d565b60200260200101516060019060018111156124e9576124e9614b07565b908160018111156124fc576124fc614b07565b81525050612560876040015182815181106125195761251961434d565b602002602001015184896080015184815181106125385761253861434d565b60200260200101518885815181106125525761255261434d565b60200260200101518c613011565b8683815181106125725761257261434d565b602002602001015160200187848151811061258f5761258f61434d565b602002602001015160c00182815250821515151581525050508481815181106125ba576125ba61434d565b602002602001015160200151156125ea576001846000018181516125de9190614b36565b61ffff169052506125ef565b6127b1565b6126558582815181106126045761260461434d565b602002602001015160000151606001518860600151838151811061262a5761262a61434d565b60200260200101518960a0015184815181106126485761264861434d565b6020026020010151611c11565b8683815181106126675761266761434d565b60200260200101516040018784815181106126845761268461434d565b602090810291909101015160800191909152901515905260c08801516126ab90600161437c565b6126b99060ff166040614b51565b6103a48860a0015183815181106126d2576126d261434d565b6020026020010151516126e5919061433a565b6126ef919061433a565b8582815181106127015761270161434d565b602002602001015160a00181815250508481815181106127235761272361434d565b602002602001015160a0015184602001818151612740919061433a565b90525084518590829081106127575761275761434d565b6020026020010151608001518661276e9190614b68565b95506127b1876040015182815181106127895761278961434d565b6020026020010151848784815181106127a4576127a461434d565b6020026020010151613130565b806127bb816145d9565b915050612379565b50825161ffff166000036127da5750505050505050565b6155f06127e8366010614b51565b5a6127f39088614b68565b6127fd919061433a565b612807919061433a565b8351909550611b589061281e9061ffff1687614baa565b612828919061433a565b945060008060005b886040015151811015612a0c5786818151811061284f5761284f61434d565b602002602001015160200151156129fa576128e88a8a60400151838151811061287a5761287a61434d565b60200260200101518984815181106128945761289461434d565b6020026020010151608001518c600001518d602001518d8c602001518e89815181106128c2576128c261434d565b602002602001015160a001518c6128d99190614b51565b6128e39190614baa565b613235565b6060880180519295509093508391612901908390614315565b6bffffffffffffffffffffffff16905250604086018051849190612926908390614315565b6bffffffffffffffffffffffff16905250865187908290811061294b5761294b61434d565b60200260200101516040015115158960400151828151811061296f5761296f61434d565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b84866129a49190614315565b8a85815181106129b6576129b661434d565b6020026020010151608001518c8e6080015187815181106129d9576129d961434d565b60200260200101516040516129f19493929190614bbe565b60405180910390a35b80612a04816145d9565b915050612830565b505050604083810151336000908152600b602052919091208054600290612a489084906201000090046bffffffffffffffffffffffff16614315565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260600151601260000160008282829054906101000a90046bffffffffffffffffffffffff16612aa69190614315565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611c0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610425565b3373ffffffffffffffffffffffffffffffffffffffff821603612bdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610425565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e0100000000000000000000000000009004909116606082015290612e4f576000816060015185612ceb9190614bfb565b90506000612cf98583614c20565b90508083604001818151612d0d9190614315565b6bffffffffffffffffffffffff16905250612d288582614c4b565b83606001818151612d399190614315565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b6000808a8a8a8a8a8a8a8a8a604051602001612e7f99989796959493929190614c7b565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b6000612158825490565b6000612f1b83836133b8565b9392505050565b6000612f1b8373ffffffffffffffffffffffffffffffffffffffff84166133e2565b6000612f1b8373ffffffffffffffffffffffffffffffffffffffff84166134dc565b6000818160045b600f811015612ff3577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612fab57612fab61434d565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612fe157506000949350505050565b80612feb816145d9565b915050612f6d565b5081600f1a600181111561300957613009614b07565b949350505050565b60008080808560600151600181111561302c5761302c614b07565b036130525761303e888888888861352b565b61304d57600092509050613126565b6130ca565b60018560600151600181111561306a5761306a614b07565b0361309857600061307d898989886136b6565b92509050806130925750600092509050613126565b506130ca565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516040015163ffffffff16871061311f57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd56368760405161310c9190613b21565b60405180910390a2600092509050613126565b6001925090505b9550959350505050565b60008160600151600181111561314857613148614b07565b036131ac57600083815260046020526040902060010180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156131c4576131c4614b07565b036132305760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b600080613248898886868a8a60016138c4565b60008a8152600460205260408120600101549294509092506c010000000000000000000000009091046bffffffffffffffffffffffff169061328a8385614315565b9050836bffffffffffffffffffffffff16826bffffffffffffffffffffffff1610156132be575091506000905081806132f1565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff1610156132f15750806132ee8482614bfb565b92505b60008a81526004602052604090206001018054829190600c906133339084906c0100000000000000000000000090046bffffffffffffffffffffffff16614bfb565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008c81526004602052604081206001018054859450909261337c91859116614315565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505097509795505050505050565b60008260000182815481106133cf576133cf61434d565b9060005260206000200154905092915050565b600081815260018301602052604081205480156134cb576000613406600183614b68565b855490915060009061341a90600190614b68565b905081811461347f57600086600001828154811061343a5761343a61434d565b906000526020600020015490508087600001848154811061345d5761345d61434d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061349057613490614d10565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612158565b6000915050612158565b5092915050565b600081815260018301602052604081205461352357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612158565b506000612158565b600080848060200190518101906135429190614d3f565b845160c00151815191925063ffffffff9081169116101561359f57867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88660405161358d9190613b21565b60405180910390a260009150506136ad565b826101200151801561366057506020810151158015906136605750602081015161014084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365d9190614611565b14155b806136725750805163ffffffff168611155b156136a757867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018660405161358d9190613b21565b60019150505b95945050505050565b6000806000848060200190518101906136cf9190614d97565b905060008782600001518360200151846040015160405160200161373194939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b604051602081830303815290604052805190602001209050846101200151801561380d575060808201511580159061380d5750608082015161014086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156137e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380a9190614611565b14155b80613822575086826060015163ffffffff1610155b1561386c57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516138579190613b21565b60405180910390a26000935091506138bb9050565b60008181526008602052604090205460ff16156138b357877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516138579190613b21565b600193509150505b94509492505050565b60008060008960a0015161ffff16866138dd9190614b51565b90508380156138eb5750803a105b156138f357503a5b600085886139018b8d61433a565b61390b9085614b51565b613915919061433a565b61392790670de0b6b3a7640000614b51565b6139319190614baa565b905060008b6040015163ffffffff1664e8d4a510006139509190614b51565b60208d0151889063ffffffff168b6139688f88614b51565b613972919061433a565b61398090633b9aca00614b51565b61398a9190614b51565b6139949190614baa565b61399e919061433a565b90506b033b2e3c9fd0803ce80000006139b7828461433a565b11156139ef576040517f2ad7547a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b909b909a5098505050505050505050565b5080546000825590600052602060002090810190610bb19190613aa8565b828054828255906000526020600020908101928215613a98579160200282015b82811115613a9857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a3e565b50613aa4929150613aa8565b5090565b5b80821115613aa45760008155600101613aa9565b6000815180845260005b81811015613ae357602081850181015186830182015201613ac7565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612f1b6020830184613abd565b73ffffffffffffffffffffffffffffffffffffffff81168114610bb157600080fd5b8035613b6181613b34565b919050565b60008083601f840112613b7857600080fd5b50813567ffffffffffffffff811115613b9057600080fd5b602083019150836020828501011115613ba857600080fd5b9250929050565b60008060008060608587031215613bc557600080fd5b8435613bd081613b34565b935060208501359250604085013567ffffffffffffffff811115613bf357600080fd5b613bff87828801613b66565b95989497509550505050565b600080600060408486031215613c2057600080fd5b83359250602084013567ffffffffffffffff811115613c3e57600080fd5b613c4a86828701613b66565b9497909650939450505050565b60008083601f840112613c6957600080fd5b50813567ffffffffffffffff811115613c8157600080fd5b6020830191508360208260051b8501011115613ba857600080fd5b60008060008060008060008060e0898b031215613cb857600080fd5b606089018a811115613cc957600080fd5b8998503567ffffffffffffffff80821115613ce357600080fd5b613cef8c838d01613b66565b909950975060808b0135915080821115613d0857600080fd5b613d148c838d01613c57565b909750955060a08b0135915080821115613d2d57600080fd5b50613d3a8b828c01613c57565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610220810167ffffffffffffffff81118282101715613da657613da6613d53565b60405290565b60405160c0810167ffffffffffffffff81118282101715613da657613da6613d53565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e1657613e16613d53565b604052919050565b600067ffffffffffffffff821115613e3857613e38613d53565b5060051b60200190565b600082601f830112613e5357600080fd5b81356020613e68613e6383613e1e565b613dcf565b82815260059290921b84018101918181019086841115613e8757600080fd5b8286015b84811015613eab578035613e9e81613b34565b8352918301918301613e8b565b509695505050505050565b803560ff81168114613b6157600080fd5b600082601f830112613ed857600080fd5b813567ffffffffffffffff811115613ef257613ef2613d53565b613f2360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613dcf565b818152846020838601011115613f3857600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff81168114613b6157600080fd5b60008060008060008060c08789031215613f8657600080fd5b863567ffffffffffffffff80821115613f9e57600080fd5b613faa8a838b01613e42565b97506020890135915080821115613fc057600080fd5b613fcc8a838b01613e42565b9650613fda60408a01613eb6565b95506060890135915080821115613ff057600080fd5b613ffc8a838b01613ec7565b945061400a60808a01613f55565b935060a089013591508082111561402057600080fd5b5061402d89828a01613ec7565b9150509295509295509295565b60006020828403121561404c57600080fd5b8135612f1b81613b34565b63ffffffff81168114610bb157600080fd5b8035613b6181614057565b62ffffff81168114610bb157600080fd5b8035613b6181614074565b61ffff81168114610bb157600080fd5b8035613b6181614090565b6bffffffffffffffffffffffff81168114610bb157600080fd5b8035613b61816140ab565b8015158114610bb157600080fd5b8035613b61816140d0565b600061022082840312156140fc57600080fd5b614104613d82565b905061410f82614069565b815261411d60208301614069565b602082015261412e60408301614069565b604082015261413f60608301614085565b6060820152614150608083016140a0565b608082015261416160a083016140c5565b60a082015261417260c08301614069565b60c082015261418360e08301614069565b60e0820152610100614196818401614069565b908201526101206141a8838201614069565b90820152610140828101359082015261016080830135908201526101806141d0818401613b56565b908201526101a08281013567ffffffffffffffff8111156141f057600080fd5b6141fc85828601613e42565b8284015250506101c0614210818401613b56565b908201526101e0614222838201613b56565b908201526102006142348382016140de565b9082015292915050565b60008060008060008060c0878903121561425757600080fd5b863567ffffffffffffffff8082111561426f57600080fd5b61427b8a838b01613e42565b9750602089013591508082111561429157600080fd5b61429d8a838b01613e42565b96506142ab60408a01613eb6565b955060608901359150808211156142c157600080fd5b613ffc8a838b016140e9565b6000602082840312156142df57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff8181168382160190808211156134d5576134d56142e6565b80820180821115612158576121586142e6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff8181168382160190811115612158576121586142e6565b8051613b6181614057565b8051613b6181614074565b8051613b6181614090565b8051613b61816140ab565b8051613b6181613b34565b600082601f8301126143dd57600080fd5b815160206143ed613e6383613e1e565b82815260059290921b8401810191818101908684111561440c57600080fd5b8286015b84811015613eab57805161442381613b34565b8352918301918301614410565b8051613b61816140d0565b60006020828403121561444d57600080fd5b815167ffffffffffffffff8082111561446557600080fd5b90830190610220828603121561447a57600080fd5b614482613d82565b61448b83614395565b815261449960208401614395565b60208201526144aa60408401614395565b60408201526144bb606084016143a0565b60608201526144cc608084016143ab565b60808201526144dd60a084016143b6565b60a08201526144ee60c08401614395565b60c08201526144ff60e08401614395565b60e0820152610100614512818501614395565b90820152610120614524848201614395565b908201526101408381015190820152610160808401519082015261018061454c8185016143c1565b908201526101a0838101518381111561456457600080fd5b614570888287016143cc565b8284015250506101c091506145868284016143c1565b828201526101e0915061459a8284016143c1565b8282015261020091506145ae828401614430565b91810191909152949350505050565b60ff81811683821602908116908181146134d5576134d56142e6565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361460a5761460a6142e6565b5060010190565b60006020828403121561462357600080fd5b5051919050565b63ffffffff8181168382160190808211156134d5576134d56142e6565b600081518084526020808501945080840160005b8381101561468d57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161465b565b509495945050505050565b602081526146af60208201835163ffffffff169052565b600060208301516146c8604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015162ffffff8116608084015250608083015161ffff811660a08401525060a08301516bffffffffffffffffffffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006147418185018363ffffffff169052565b840151905061012061475a8482018363ffffffff169052565b84015190506101406147738482018363ffffffff169052565b840151610160848101919091528401516101808085019190915284015190506101a06147b68185018373ffffffffffffffffffffffffffffffffffffffff169052565b808501519150506102206101c081818601526147d6610240860184614647565b908601519092506101e06148018682018373ffffffffffffffffffffffffffffffffffffffff169052565b860151905061020061482a8682018373ffffffffffffffffffffffffffffffffffffffff169052565b90950151151593019290925250919050565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261486c8184018a614647565b905082810360808401526148808189614647565b905060ff871660a084015282810360c084015261489d8187613abd565b905067ffffffffffffffff851660e08401528281036101008401526148c28185613abd565b9c9b505050505050505050505050565b8281526040602082015260006130096040830184613abd565b600080604083850312156148fe57600080fd5b8251614909816140d0565b6020939093015192949293505050565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261495057600080fd5b81356020614960613e6383613e1e565b82815260059290921b8401810191818101908684111561497f57600080fd5b8286015b84811015613eab5780358352918301918301614983565b600082601f8301126149ab57600080fd5b813560206149bb613e6383613e1e565b82815260059290921b840181019181810190868411156149da57600080fd5b8286015b84811015613eab57803567ffffffffffffffff8111156149fe5760008081fd5b614a0c8986838b0101613ec7565b8452509183019183016149de565b600060208284031215614a2c57600080fd5b813567ffffffffffffffff80821115614a4457600080fd5b9083019060c08286031215614a5857600080fd5b614a60613dac565b8235815260208301356020820152604083013582811115614a8057600080fd5b614a8c8782860161493f565b604083015250606083013582811115614aa457600080fd5b614ab08782860161493f565b606083015250608083013582811115614ac857600080fd5b614ad48782860161499a565b60808301525060a083013582811115614aec57600080fd5b614af88782860161499a565b60a08301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b61ffff8181168382160190808211156134d5576134d56142e6565b8082028115828204841417612158576121586142e6565b81810381811115612158576121586142e6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614bb957614bb9614b7b565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000614bf16080830184613abd565b9695505050505050565b6bffffffffffffffffffffffff8281168282160390808211156134d5576134d56142e6565b60006bffffffffffffffffffffffff80841680614c3f57614c3f614b7b565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114614c7357614c736142e6565b505092915050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614cc28285018b614647565b91508382036080850152614cd6828a614647565b915060ff881660a085015283820360c0850152614cf38288613abd565b90861660e085015283810361010085015290506148c28185613abd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060408284031215614d5157600080fd5b6040516040810181811067ffffffffffffffff82111715614d7457614d74613d53565b6040528251614d8281614057565b81526020928301519281019290925250919050565b600060a08284031215614da957600080fd5b60405160a0810181811067ffffffffffffffff82111715614dcc57614dcc613d53565b806040525082518152602083015160208201526040830151614ded81614057565b60408201526060830151614e0081614057565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", + Bin: "0x6101406040523480156200001257600080fd5b506040516200526d3803806200526d8339810160408190526200003591620003b1565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b9190620003b1565b826001600160a01b031663b10b673c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001009190620003b1565b836001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001659190620003b1565b846001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca9190620003b1565b856001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f9190620003b1565b3380600081620002865760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620002b957620002b981620002ed565b5050506001600160a01b0394851660805292841660a05290831660c052821660e052811661010052166101205250620003d8565b336001600160a01b03821603620003475760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200027d565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620003ae57600080fd5b50565b600060208284031215620003c457600080fd5b8151620003d18162000398565b9392505050565b60805160a05160c05160e0516101005161012051614e48620004256000396000818160c9015261017c01526000611bb8015260005050600050506000505060006104c20152614e486000f3fe6080604052600436106100c75760003560e01c8063aed2e92911610074578063e3d0e7121161004e578063e3d0e71214610348578063f2fde38b14610368578063f75f6b1114610388576100c7565b8063aed2e929146102a3578063afcb95d7146102da578063b1dc65a414610328576100c7565b806381ff7048116100a557806381ff7048146101d65780638da5cb5b14610258578063a4c0ed3614610283576100c7565b8063181f5a771461010e578063349e8cca1461016d57806379ba5097146101c1575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610107573d6000f35b3d6000fd5b005b34801561011a57600080fd5b506101576040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e322e30000000000000000081525081565b6040516101649190613b44565b60405180910390f35b34801561017957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610164565b3480156101cd57600080fd5b5061010c6103a8565b3480156101e257600080fd5b5061023560155460115463ffffffff780100000000000000000000000000000000000000000000000083048116937c01000000000000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610164565b34801561026457600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661019c565b34801561028f57600080fd5b5061010c61029e366004613bd2565b6104aa565b3480156102af57600080fd5b506102c36102be366004613c2e565b6106c6565b604080519215158352602083019190915201610164565b3480156102e657600080fd5b50601154601254604080516000815260208101939093527401000000000000000000000000000000000000000090910463ffffffff1690820152606001610164565b34801561033457600080fd5b5061010c610343366004613cbf565b61083c565b34801561035457600080fd5b5061010c610363366004613f90565b610b77565b34801561037457600080fd5b5061010c61038336600461405d565b610ba0565b34801561039457600080fd5b5061010c6103a3366004614261565b610bb4565b60015473ffffffffffffffffffffffffffffffffffffffff16331461042e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610519576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610553576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610561828401846142f0565b60008181526004602052604090205490915065010000000000900463ffffffff908116146105bb576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600101546105f69085906c0100000000000000000000000090046bffffffffffffffffffffffff16614338565b600082815260046020526040902060010180546bffffffffffffffffffffffff929092166c01000000000000000000000000027fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff90921691909117905560195461066190859061435d565b6019556040516bffffffffffffffffffffffff8516815273ffffffffffffffffffffffffffffffffffffffff86169082907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a35050505050565b6000806106d1611ba0565b6012547e01000000000000000000000000000000000000000000000000000000000000900460ff1615610730576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825160e081018452815460ff811615158252610100810463ffffffff908116838601819052650100000000008304821684880152690100000000000000000090920473ffffffffffffffffffffffffffffffffffffffff16606084018190526001909401546bffffffffffffffffffffffff80821660808601526c0100000000000000000000000082041660a0850152780100000000000000000000000000000000000000000000000090041660c08301528451601f8901859004850281018501909552878552909361082f938990899081908401838280828437600092019190915250611c1192505050565b9097909650945050505050565b60005a60408051610160810182526012546bffffffffffffffffffffffff8116825263ffffffff6c010000000000000000000000008204811660208401527001000000000000000000000000000000008204811693830193909352740100000000000000000000000000000000000000008104909216606082015262ffffff7801000000000000000000000000000000000000000000000000830416608082015261ffff7b0100000000000000000000000000000000000000000000000000000083041660a082015260ff7d0100000000000000000000000000000000000000000000000000000000008304811660c08301527e010000000000000000000000000000000000000000000000000000000000008304811615801560e08401527f01000000000000000000000000000000000000000000000000000000000000009093048116151561010080840191909152601354918216151561012084015273ffffffffffffffffffffffffffffffffffffffff9104166101408201529192506109f2576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16610a3b576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6011548a3514610a77576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c0810151610a8790600161439f565b60ff1686141580610a985750858414155b15610acf576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610adf8a8a8a8a8a8a8a8a611e3a565b6000610aeb8a8a6120a3565b905060208b0135600881901c63ffffffff16610b0884848761215e565b836060015163ffffffff168163ffffffff161115610b6857601280547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b610b9886868686806020019051810190610b91919061445e565b8686610bb4565b505050505050565b610ba8612b00565b610bb181612b81565b50565b610bbc612b00565b601f86511115610bf8576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360ff16600003610c35576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84518651141580610c545750610c4c8460036145e0565b60ff16865111155b15610c8b576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601254600e546bffffffffffffffffffffffff9091169060005b816bffffffffffffffffffffffff16811015610d0d57610cfa600e8281548110610cd157610cd1614370565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168484612c76565b5080610d05816145fc565b915050610ca5565b5060008060005b836bffffffffffffffffffffffff16811015610e1657600d8181548110610d3d57610d3d614370565b600091825260209091200154600e805473ffffffffffffffffffffffffffffffffffffffff90921694509082908110610d7857610d78614370565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff8681168452600c8352604080852080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559116808452600b90925290912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055915080610e0e816145fc565b915050610d14565b50610e23600d6000613a23565b610e2f600e6000613a23565b604080516080810182526000808252602082018190529181018290526060810182905290805b8c5181101561129857600c60008e8381518110610e7457610e74614370565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615610edf576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168d8281518110610f0957610f09614370565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610f5e576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008f8481518110610f8f57610f8f614370565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558b518c908290811061103757611037614370565b60200260200101519150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036110a7576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909350611162576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001835260ff80821660208086019182526bffffffffffffffffffffffff808b166060880190815273ffffffffffffffffffffffffffffffffffffffff87166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169490941717919091169290921791909117905580611290816145fc565b915050610e55565b50508a516112ae9150600d9060208d0190613a41565b5088516112c290600e9060208c0190613a41565b50604051806101600160405280856bffffffffffffffffffffffff168152602001886000015163ffffffff168152602001886020015163ffffffff168152602001600063ffffffff168152602001886060015162ffffff168152602001886080015161ffff1681526020018960ff1681526020016012600001601e9054906101000a900460ff16151581526020016012600001601f9054906101000a900460ff161515815260200188610200015115158152602001886101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601260008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160000160186101000a81548162ffffff021916908362ffffff16021790555060a082015181600001601b6101000a81548161ffff021916908361ffff16021790555060c082015181600001601d6101000a81548160ff021916908360ff16021790555060e082015181600001601e6101000a81548160ff02191690831515021790555061010082015181600001601f6101000a81548160ff0219169083151502179055506101208201518160010160006101000a81548160ff0219169083151502179055506101408201518160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506040518061018001604052808860a001516bffffffffffffffffffffffff16815260200188610180015173ffffffffffffffffffffffffffffffffffffffff168152602001601460010160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001886040015163ffffffff1681526020018860c0015163ffffffff168152602001601460010160149054906101000a900463ffffffff1663ffffffff168152602001601460010160189054906101000a900463ffffffff1663ffffffff1681526020016014600101601c9054906101000a900463ffffffff1663ffffffff1681526020018860e0015163ffffffff16815260200188610100015163ffffffff16815260200188610120015163ffffffff168152602001886101c0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550606082015181600101600c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160106101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548163ffffffff021916908363ffffffff1602179055506101208201518160020160046101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160086101000a81548163ffffffff021916908363ffffffff16021790555061016082015181600201600c6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555090505086610140015160178190555086610160015160188190555060006014600101601c9054906101000a900463ffffffff169050876101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119879190614634565b601580547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601891611a02918591780100000000000000000000000000000000000000000000000090041661464d565b92506101000a81548163ffffffff021916908363ffffffff160217905550600088604051602001611a3391906146bb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601554909150611a9c90469030907801000000000000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f612e7e565b60115560005b611aac6009612f28565b811015611adc57611ac9611ac1600983612f32565b600990612f45565b5080611ad4816145fc565b915050611aa2565b5060005b896101a0015151811015611b3357611b208a6101a001518281518110611b0857611b08614370565b60200260200101516009612f6790919063ffffffff16565b5080611b2b816145fc565b915050611ae0565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0582601154601460010160189054906101000a900463ffffffff168f8f8f878f8f604051611b8a9998979695949392919061485f565b60405180910390a1505050505050505050505050565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611c0f576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60125460009081907f0100000000000000000000000000000000000000000000000000000000000000900460ff1615611c76576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601280547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790556040517f4585e33b0000000000000000000000000000000000000000000000000000000090611cf2908590602401613b44565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d1690611dc590879087906004016148f5565b60408051808303816000875af1158015611de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e07919061490e565b601280547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60008787604051611e4c92919061493c565b604051908190038120611e63918b9060200161494c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b8881101561203a57600185878360208110611ecf57611ecf614370565b611edc91901a601b61439f565b8c8c85818110611eee57611eee614370565b905060200201358b8b86818110611f0757611f07614370565b9050602002013560405160008152602001604052604051611f44949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611f66573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612014576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b840193508080612032906145fc565b915050611eb2565b50827e01010101010101010101010101010101010101010101010101010101010101841614612095576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6120dc6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006120ea83850185614a3d565b604081015151606082015151919250908114158061210d57508082608001515114155b8061211d5750808260a001515114155b15612154576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090505b92915050565b600082604001515167ffffffffffffffff81111561217e5761217e613d76565b60405190808252806020026020018201604052801561223a57816020015b604080516101c081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161219c5790505b50905060006040518060800160405280600061ffff1681526020016000815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152509050600085610140015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fc9190614634565b6101408701516040517f7810d12a00000000000000000000000000000000000000000000000000000000815236600482015291925060009173ffffffffffffffffffffffffffffffffffffffff90911690637810d12a90602401602060405180830381865afa158015612373573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123979190614634565b905060005b8660400151518110156127e65760046000886040015183815181106123c3576123c3614370565b6020908102919091018101518252818101929092526040908101600020815160e081018352815460ff811615158252610100810463ffffffff90811695830195909552650100000000008104851693820193909352690100000000000000000090920473ffffffffffffffffffffffffffffffffffffffff166060830152600101546bffffffffffffffffffffffff80821660808401526c0100000000000000000000000082041660a08301527801000000000000000000000000000000000000000000000000900490911660c082015285518690839081106124a8576124a8614370565b6020026020010151600001819052506124dd876040015182815181106124d0576124d0614370565b6020026020010151612f89565b8582815181106124ef576124ef614370565b602002602001015160600190600181111561250c5761250c614b2a565b9081600181111561251f5761251f614b2a565b815250506125838760400151828151811061253c5761253c614370565b6020026020010151848960800151848151811061255b5761255b614370565b602002602001015188858151811061257557612575614370565b60200260200101518c613034565b86838151811061259557612595614370565b60200260200101516020018784815181106125b2576125b2614370565b602002602001015160c00182815250821515151581525050508481815181106125dd576125dd614370565b6020026020010151602001511561260d576001846000018181516126019190614b59565b61ffff16905250612612565b6127d4565b61267885828151811061262757612627614370565b602002602001015160000151606001518860600151838151811061264d5761264d614370565b60200260200101518960a00151848151811061266b5761266b614370565b6020026020010151611c11565b86838151811061268a5761268a614370565b60200260200101516040018784815181106126a7576126a7614370565b602090810291909101015160800191909152901515905260c08801516126ce90600161439f565b6126dc9060ff166040614b74565b6103a48860a0015183815181106126f5576126f5614370565b602002602001015151612708919061435d565b612712919061435d565b85828151811061272457612724614370565b602002602001015160a001818152505084818151811061274657612746614370565b602002602001015160a0015184602001818151612763919061435d565b905250845185908290811061277a5761277a614370565b602002602001015160800151866127919190614b8b565b95506127d4876040015182815181106127ac576127ac614370565b6020026020010151848784815181106127c7576127c7614370565b6020026020010151613153565b806127de816145fc565b91505061239c565b50825161ffff166000036127fd5750505050505050565b6155f061280b366010614b74565b5a6128169088614b8b565b612820919061435d565b61282a919061435d565b8351909550611b58906128419061ffff1687614bcd565b61284b919061435d565b945060008060005b886040015151811015612a2f5786818151811061287257612872614370565b60200260200101516020015115612a1d5761290b8a8a60400151838151811061289d5761289d614370565b60200260200101518984815181106128b7576128b7614370565b6020026020010151608001518c600001518d602001518d8c602001518e89815181106128e5576128e5614370565b602002602001015160a001518c6128fc9190614b74565b6129069190614bcd565b613258565b6060880180519295509093508391612924908390614338565b6bffffffffffffffffffffffff16905250604086018051849190612949908390614338565b6bffffffffffffffffffffffff16905250865187908290811061296e5761296e614370565b60200260200101516040015115158960400151828151811061299257612992614370565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b84866129c79190614338565b8a85815181106129d9576129d9614370565b6020026020010151608001518c8e6080015187815181106129fc576129fc614370565b6020026020010151604051612a149493929190614be1565b60405180910390a35b80612a27816145fc565b915050612853565b505050604083810151336000908152600b602052919091208054600290612a6b9084906201000090046bffffffffffffffffffffffff16614338565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260600151601260000160008282829054906101000a90046bffffffffffffffffffffffff16612ac99190614338565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611c0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610425565b3373ffffffffffffffffffffffffffffffffffffffff821603612c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610425565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e0100000000000000000000000000009004909116606082015290612e72576000816060015185612d0e9190614c1e565b90506000612d1c8583614c43565b90508083604001818151612d309190614338565b6bffffffffffffffffffffffff16905250612d4b8582614c6e565b83606001818151612d5c9190614338565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b6000808a8a8a8a8a8a8a8a8a604051602001612ea299989796959493929190614c9e565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b6000612158825490565b6000612f3e83836133db565b9392505050565b6000612f3e8373ffffffffffffffffffffffffffffffffffffffff8416613405565b6000612f3e8373ffffffffffffffffffffffffffffffffffffffff84166134ff565b6000818160045b600f811015613016577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612fce57612fce614370565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461300457506000949350505050565b8061300e816145fc565b915050612f90565b5081600f1a600181111561302c5761302c614b2a565b949350505050565b60008080808560600151600181111561304f5761304f614b2a565b0361307557613061888888888861354e565b61307057600092509050613149565b6130ed565b60018560600151600181111561308d5761308d614b2a565b036130bb5760006130a0898989886136d9565b92509050806130b55750600092509050613149565b506130ed565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516040015163ffffffff16871061314257877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd56368760405161312f9190613b44565b60405180910390a2600092509050613149565b6001925090505b9550959350505050565b60008160600151600181111561316b5761316b614b2a565b036131cf57600083815260046020526040902060010180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156131e7576131e7614b2a565b036132535760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008061326b898886868a8a60016138e7565b60008a8152600460205260408120600101549294509092506c010000000000000000000000009091046bffffffffffffffffffffffff16906132ad8385614338565b9050836bffffffffffffffffffffffff16826bffffffffffffffffffffffff1610156132e157509150600090508180613314565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff1610156133145750806133118482614c1e565b92505b60008a81526004602052604090206001018054829190600c906133569084906c0100000000000000000000000090046bffffffffffffffffffffffff16614c1e565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008c81526004602052604081206001018054859450909261339f91859116614338565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505097509795505050505050565b60008260000182815481106133f2576133f2614370565b9060005260206000200154905092915050565b600081815260018301602052604081205480156134ee576000613429600183614b8b565b855490915060009061343d90600190614b8b565b90508181146134a257600086600001828154811061345d5761345d614370565b906000526020600020015490508087600001848154811061348057613480614370565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806134b3576134b3614d33565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612158565b6000915050612158565b5092915050565b600081815260018301602052604081205461354657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612158565b506000612158565b600080848060200190518101906135659190614d62565b845160c00151815191925063ffffffff908116911610156135c257867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8866040516135b09190613b44565b60405180910390a260009150506136d0565b826101200151801561368357506020810151158015906136835750602081015161014084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561365c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136809190614634565b14155b806136955750805163ffffffff168611155b156136ca57867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301866040516135b09190613b44565b60019150505b95945050505050565b6000806000848060200190518101906136f29190614dba565b905060008782600001518360200151846040015160405160200161375494939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b604051602081830303815290604052805190602001209050846101200151801561383057506080820151158015906138305750608082015161014086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382d9190614634565b14155b80613845575086826060015163ffffffff1610155b1561388f57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018760405161387a9190613b44565b60405180910390a26000935091506138de9050565b60008181526008602052604090205460ff16156138d657877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88760405161387a9190613b44565b600193509150505b94509492505050565b60008060008960a0015161ffff16866139009190614b74565b905083801561390e5750803a105b1561391657503a5b600085886139248b8d61435d565b61392e9085614b74565b613938919061435d565b61394a90670de0b6b3a7640000614b74565b6139549190614bcd565b905060008b6040015163ffffffff1664e8d4a510006139739190614b74565b60208d0151889063ffffffff168b61398b8f88614b74565b613995919061435d565b6139a390633b9aca00614b74565b6139ad9190614b74565b6139b79190614bcd565b6139c1919061435d565b90506b033b2e3c9fd0803ce80000006139da828461435d565b1115613a12576040517f2ad7547a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b909b909a5098505050505050505050565b5080546000825590600052602060002090810190610bb19190613acb565b828054828255906000526020600020908101928215613abb579160200282015b82811115613abb57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a61565b50613ac7929150613acb565b5090565b5b80821115613ac75760008155600101613acc565b6000815180845260005b81811015613b0657602081850181015186830182015201613aea565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612f3e6020830184613ae0565b73ffffffffffffffffffffffffffffffffffffffff81168114610bb157600080fd5b8035613b8481613b57565b919050565b60008083601f840112613b9b57600080fd5b50813567ffffffffffffffff811115613bb357600080fd5b602083019150836020828501011115613bcb57600080fd5b9250929050565b60008060008060608587031215613be857600080fd5b8435613bf381613b57565b935060208501359250604085013567ffffffffffffffff811115613c1657600080fd5b613c2287828801613b89565b95989497509550505050565b600080600060408486031215613c4357600080fd5b83359250602084013567ffffffffffffffff811115613c6157600080fd5b613c6d86828701613b89565b9497909650939450505050565b60008083601f840112613c8c57600080fd5b50813567ffffffffffffffff811115613ca457600080fd5b6020830191508360208260051b8501011115613bcb57600080fd5b60008060008060008060008060e0898b031215613cdb57600080fd5b606089018a811115613cec57600080fd5b8998503567ffffffffffffffff80821115613d0657600080fd5b613d128c838d01613b89565b909950975060808b0135915080821115613d2b57600080fd5b613d378c838d01613c7a565b909750955060a08b0135915080821115613d5057600080fd5b50613d5d8b828c01613c7a565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610220810167ffffffffffffffff81118282101715613dc957613dc9613d76565b60405290565b60405160c0810167ffffffffffffffff81118282101715613dc957613dc9613d76565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e3957613e39613d76565b604052919050565b600067ffffffffffffffff821115613e5b57613e5b613d76565b5060051b60200190565b600082601f830112613e7657600080fd5b81356020613e8b613e8683613e41565b613df2565b82815260059290921b84018101918181019086841115613eaa57600080fd5b8286015b84811015613ece578035613ec181613b57565b8352918301918301613eae565b509695505050505050565b803560ff81168114613b8457600080fd5b600082601f830112613efb57600080fd5b813567ffffffffffffffff811115613f1557613f15613d76565b613f4660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613df2565b818152846020838601011115613f5b57600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff81168114613b8457600080fd5b60008060008060008060c08789031215613fa957600080fd5b863567ffffffffffffffff80821115613fc157600080fd5b613fcd8a838b01613e65565b97506020890135915080821115613fe357600080fd5b613fef8a838b01613e65565b9650613ffd60408a01613ed9565b9550606089013591508082111561401357600080fd5b61401f8a838b01613eea565b945061402d60808a01613f78565b935060a089013591508082111561404357600080fd5b5061405089828a01613eea565b9150509295509295509295565b60006020828403121561406f57600080fd5b8135612f3e81613b57565b63ffffffff81168114610bb157600080fd5b8035613b848161407a565b62ffffff81168114610bb157600080fd5b8035613b8481614097565b61ffff81168114610bb157600080fd5b8035613b84816140b3565b6bffffffffffffffffffffffff81168114610bb157600080fd5b8035613b84816140ce565b8015158114610bb157600080fd5b8035613b84816140f3565b6000610220828403121561411f57600080fd5b614127613da5565b90506141328261408c565b81526141406020830161408c565b60208201526141516040830161408c565b6040820152614162606083016140a8565b6060820152614173608083016140c3565b608082015261418460a083016140e8565b60a082015261419560c0830161408c565b60c08201526141a660e0830161408c565b60e08201526101006141b981840161408c565b908201526101206141cb83820161408c565b90820152610140828101359082015261016080830135908201526101806141f3818401613b79565b908201526101a08281013567ffffffffffffffff81111561421357600080fd5b61421f85828601613e65565b8284015250506101c0614233818401613b79565b908201526101e0614245838201613b79565b90820152610200614257838201614101565b9082015292915050565b60008060008060008060c0878903121561427a57600080fd5b863567ffffffffffffffff8082111561429257600080fd5b61429e8a838b01613e65565b975060208901359150808211156142b457600080fd5b6142c08a838b01613e65565b96506142ce60408a01613ed9565b955060608901359150808211156142e457600080fd5b61401f8a838b0161410c565b60006020828403121561430257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff8181168382160190808211156134f8576134f8614309565b8082018082111561215857612158614309565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561215857612158614309565b8051613b848161407a565b8051613b8481614097565b8051613b84816140b3565b8051613b84816140ce565b8051613b8481613b57565b600082601f83011261440057600080fd5b81516020614410613e8683613e41565b82815260059290921b8401810191818101908684111561442f57600080fd5b8286015b84811015613ece57805161444681613b57565b8352918301918301614433565b8051613b84816140f3565b60006020828403121561447057600080fd5b815167ffffffffffffffff8082111561448857600080fd5b90830190610220828603121561449d57600080fd5b6144a5613da5565b6144ae836143b8565b81526144bc602084016143b8565b60208201526144cd604084016143b8565b60408201526144de606084016143c3565b60608201526144ef608084016143ce565b608082015261450060a084016143d9565b60a082015261451160c084016143b8565b60c082015261452260e084016143b8565b60e08201526101006145358185016143b8565b908201526101206145478482016143b8565b908201526101408381015190820152610160808401519082015261018061456f8185016143e4565b908201526101a0838101518381111561458757600080fd5b614593888287016143ef565b8284015250506101c091506145a98284016143e4565b828201526101e091506145bd8284016143e4565b8282015261020091506145d1828401614453565b91810191909152949350505050565b60ff81811683821602908116908181146134f8576134f8614309565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361462d5761462d614309565b5060010190565b60006020828403121561464657600080fd5b5051919050565b63ffffffff8181168382160190808211156134f8576134f8614309565b600081518084526020808501945080840160005b838110156146b057815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161467e565b509495945050505050565b602081526146d260208201835163ffffffff169052565b600060208301516146eb604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015162ffffff8116608084015250608083015161ffff811660a08401525060a08301516bffffffffffffffffffffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006147648185018363ffffffff169052565b840151905061012061477d8482018363ffffffff169052565b84015190506101406147968482018363ffffffff169052565b840151610160848101919091528401516101808085019190915284015190506101a06147d98185018373ffffffffffffffffffffffffffffffffffffffff169052565b808501519150506102206101c081818601526147f961024086018461466a565b908601519092506101e06148248682018373ffffffffffffffffffffffffffffffffffffffff169052565b860151905061020061484d8682018373ffffffffffffffffffffffffffffffffffffffff169052565b90950151151593019290925250919050565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261488f8184018a61466a565b905082810360808401526148a3818961466a565b905060ff871660a084015282810360c08401526148c08187613ae0565b905067ffffffffffffffff851660e08401528281036101008401526148e58185613ae0565b9c9b505050505050505050505050565b82815260406020820152600061302c6040830184613ae0565b6000806040838503121561492157600080fd5b825161492c816140f3565b6020939093015192949293505050565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261497357600080fd5b81356020614983613e8683613e41565b82815260059290921b840181019181810190868411156149a257600080fd5b8286015b84811015613ece57803583529183019183016149a6565b600082601f8301126149ce57600080fd5b813560206149de613e8683613e41565b82815260059290921b840181019181810190868411156149fd57600080fd5b8286015b84811015613ece57803567ffffffffffffffff811115614a215760008081fd5b614a2f8986838b0101613eea565b845250918301918301614a01565b600060208284031215614a4f57600080fd5b813567ffffffffffffffff80821115614a6757600080fd5b9083019060c08286031215614a7b57600080fd5b614a83613dcf565b8235815260208301356020820152604083013582811115614aa357600080fd5b614aaf87828601614962565b604083015250606083013582811115614ac757600080fd5b614ad387828601614962565b606083015250608083013582811115614aeb57600080fd5b614af7878286016149bd565b60808301525060a083013582811115614b0f57600080fd5b614b1b878286016149bd565b60a08301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b61ffff8181168382160190808211156134f8576134f8614309565b808202811582820484141761215857612158614309565b8181038181111561215857612158614309565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614bdc57614bdc614b9e565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000614c146080830184613ae0565b9695505050505050565b6bffffffffffffffffffffffff8281168282160390808211156134f8576134f8614309565b60006bffffffffffffffffffffffff80841680614c6257614c62614b9e565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114614c9657614c96614309565b505092915050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614ce58285018b61466a565b91508382036080850152614cf9828a61466a565b915060ff881660a085015283820360c0850152614d168288613ae0565b90861660e085015283810361010085015290506148e58185613ae0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060408284031215614d7457600080fd5b6040516040810181811067ffffffffffffffff82111715614d9757614d97613d76565b6040528251614da58161407a565b81526020928301519281019290925250919050565b600060a08284031215614dcc57600080fd5b60405160a0810181811067ffffffffffffffff82111715614def57614def613d76565b806040525082518152602083015160208201526040830151614e108161407a565b60408201526060830151614e238161407a565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI 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 1d460036fa0..97f0cfb113a 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: "0x6101806040523480156200001257600080fd5b506040516200651f3803806200651f83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615e07620007186000396000818160b30152610186015260005050600050506000505060005050600061379a015260005050600081816113710152612dc30152615e076000f3fe6080604052600436106100b15760003560e01c80638da5cb5b11610069578063b1dc65a41161004e578063b1dc65a4146102cb578063e3d0e712146102eb578063f2fde38b1461030b576100b1565b80638da5cb5b1461025a578063afcb95d714610285576100b1565b8063349e8cca1161009a578063349e8cca1461017757806379ba5097146101cb57806381ff7048146101e0576100b1565b80630870d3a1146100f8578063181f5a7714610118575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100f1573d6000f35b3d6000fd5b005b34801561010457600080fd5b506100f6610113366004614b7b565b61032b565b34801561012457600080fd5b506101616040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b60405161016e9190614cf7565b60405180910390f35b34801561018357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016e565b3480156101d757600080fd5b506100f6610c0f565b3480156101ec57600080fd5b5061023760175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff94851681529390921660208401529082015260600161016e565b34801561026657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101a6565b34801561029157600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff169082015260600161016e565b3480156102d757600080fd5b506100f66102e6366004614d56565b610d11565b3480156102f757600080fd5b506100f6610306366004614e3b565b611051565b34801561031757600080fd5b506100f6610326366004614f08565b61108b565b61033361109f565b601f8851111561036f576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103ac576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103cb57506103c3866003614f54565b60ff16885111155b15610402576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461043d576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104478282611122565b610451888861175a565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506000601660010160189054906101000a900463ffffffff1690506000866101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107259190614f70565b6017549091506000906107579074010000000000000000000000000000000000000000900463ffffffff166001614f89565b9050604051806101600160405280896060015173ffffffffffffffffffffffffffffffffffffffff168152602001896000015163ffffffff168152602001896020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200189610100015173ffffffffffffffffffffffffffffffffffffffff1681526020018263ffffffff1681526020018363ffffffff168152602001896040015163ffffffff16815260200189610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018960c0015163ffffffff1681526020018960e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050876101600151601981905550876101800151601a81905550876101a00151601b81905550600088604051602001610a9a9190614ff7565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610aff904690309074010000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f611e19565b6013556000610b0e6009611ec3565b90505b8015610b4b57610b38610b30610b2860018461517d565b600990611ed3565b600990611ee6565b5080610b4381615190565b915050610b11565b5060005b896101c0015151811015610ba257610b8f8a6101c001518281518110610b7757610b776151c5565b60200260200101516009611f0890919063ffffffff16565b5080610b9a816151f4565b915050610b4f565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0584601354601660010160149054906101000a900463ffffffff168f8f8f878f8f604051610bf99998979695949392919061522c565b60405180910390a1505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005a90506000610d238660406152c2565b610d2f896101446152d9565b610d3991906152d9565b9050368114610d74576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290610ed3576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16610f1c576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548b3514610f58576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151610f689060016152ec565b60ff1687141580610f795750868514155b15610fb0576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc08b8b8b8b8b8b8b8b611f2a565b6000610fcc8b8b612193565b905060208c0135600881901c63ffffffff16610fe984848861224c565b836020015163ffffffff168163ffffffff16111561104157601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b5050505050505050505050505050565b60008060008580602001905181019061106a9190615472565b925092509250611080898989868989888861032b565b505050505050505050565b61109361109f565b61109c81612e39565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c8c565b565b60005b6024548110156111e0576022600060248381548110611146576111466151c5565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169055806111d8816151f4565b915050611125565b506111ed602460006145cf565b60255460ff1660005b8351811015611754576000848281518110611213576112136151c5565b602002602001015190506000848381518110611231576112316151c5565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112aa919061561d565b60ff16816060015160ff161415806113385750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611330919061561d565b60ff16600814155b1561136f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156113db575060018460018111156113d9576113d961563a565b145b15611412576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061144d5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611484576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156114ee576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611737908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a25050808061174c906151f4565b9150506111f6565b50505050565b600e546014546bffffffffffffffffffffffff1660005b600e548110156117cd576117ba600e8281548110611791576117916151c5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168385612f2e565b50806117c5816151f4565b915050611771565b5060255460009060ff16815b600e5481101561193e57600e81815481106117f6576117f66151c5565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611833576118336151c5565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560018260018111156118d5576118d561563a565b14801561191a575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b1561192c5761192a600f84611f08565b505b80611936816151f4565b9150506117d9565b5061194b600d60006145cf565b611957600e60006145cf565b6040805160808101825260008082526020820181905291810182905260608101829052905b8751811015611de757600c600089838151811061199b5761199b6151c5565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611a06576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16888281518110611a3057611a306151c5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611a85576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008a8481518110611ab657611ab66151c5565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558651879082908110611b5e57611b5e6151c5565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611bce576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611c89576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090951694909417179190911692909217919091179055836001811115611dc357611dc361563a565b03611dd557611dd3600f85611ee6565b505b80611ddf816151f4565b91505061197c565b508651611dfb90600d9060208a01906145ed565b508551611e0f90600e9060208901906145ed565b5050505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001611e3d99989796959493929190615669565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b6000611ecd825490565b92915050565b6000611edf8383613136565b9392505050565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff8416613160565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff841661325a565b60008787604051611f3c9291906156fe565b604051908190038120611f53918b9060200161570e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b8881101561212a57600185878360208110611fbf57611fbf6151c5565b611fcc91901a601b6152ec565b8c8c85818110611fde57611fde6151c5565b905060200201358b8b86818110611ff757611ff76151c5565b9050602002013560405160008152602001604052604051612034949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612056573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612104576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b840193508080612122906151f4565b915050611fa2565b50827e01010101010101010101010101010101010101010101010101010101010101841614612185576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6121cc6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006121da838501856157ff565b60408101515160608201515191925090811415806121fd57508082608001515114155b8061220d5750808260a001515114155b15612244576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561226c5761226c614684565b60405190808252806020026020018201604052801561233857816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161228a5790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fa9190614f70565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa15801561244e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124729190614f70565b905060005b86604001515181101561290257600460008860400151838151811061249e5761249e6151c5565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106125c1576125c16151c5565b6020026020010151600001819052506125f6876040015182815181106125e9576125e96151c5565b60200260200101516132a9565b858281518110612608576126086151c5565b60200260200101516060019060018111156126255761262561563a565b908160018111156126385761263861563a565b8152505061269c87604001518281518110612655576126556151c5565b60200260200101518489608001518481518110612674576126746151c5565b602002602001015188858151811061268e5761268e6151c5565b60200260200101518c613354565b8683815181106126ae576126ae6151c5565b60200260200101516020018784815181106126cb576126cb6151c5565b602002602001015160c00182815250821515151581525050508481815181106126f6576126f66151c5565b602002602001015160200151156127265760018460000181815161271a91906158ec565b61ffff1690525061272b565b6128f0565b612791858281518110612740576127406151c5565b6020026020010151600001516080015188606001518381518110612766576127666151c5565b60200260200101518960a001518481518110612784576127846151c5565b6020026020010151613473565b8683815181106127a3576127a36151c5565b60200260200101516040018784815181106127c0576127c06151c5565b60200260200101516080018281525082151515158152505050876080015160016127ea91906152ec565b6127f89060ff1660406152c2565b6103a48860a001518381518110612811576128116151c5565b60200260200101515161282491906152d9565b61282e91906152d9565b858281518110612840576128406151c5565b602002602001015160a0018181525050848181518110612862576128626151c5565b602002602001015160a001518460600181815161287f91906152d9565b9052508451859082908110612896576128966151c5565b602002602001015160800151866128ad919061517d565b95506128f0876040015182815181106128c8576128c86151c5565b6020026020010151848784815181106128e3576128e36151c5565b602002602001015161368e565b806128fa816151f4565b915050612477565b50825161ffff166000036129195750505050505050565b61c8006129273660106152c2565b5a612932908861517d565b61293c91906152d9565b61294691906152d9565b83519095506137789061295d9061ffff1687615936565b61296791906152d9565b604080516080810182526000808252602082018190529181018290526060810182905291965061299689613793565b905060005b886040015151811015612cd2578681815181106129ba576129ba6151c5565b60200260200101516020015115612cc057801580612a525750866129df60018361517d565b815181106129ef576129ef6151c5565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612a2857612a286151c5565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612a8657612a838a888381518110612a6d57612a6d6151c5565b602002602001015160000151610100015161387d565b92505b6000612ba48b6040518061012001604052808b8681518110612aaa57612aaa6151c5565b60200260200101516080015181526020018c81526020018a606001518c8781518110612ad857612ad86151c5565b602002602001015160a001518a612aef91906152c2565b612af99190615936565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612b2a57612b2a6151c5565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612b7957612b796151c5565b60200260200101518b8681518110612b9357612b936151c5565b6020026020010151600001516139f9565b9050806060015187604001818151612bbc919061594a565b6bffffffffffffffffffffffff169052506040810151602088018051612be390839061594a565b6bffffffffffffffffffffffff169052508751889083908110612c0857612c086151c5565b60200260200101516040015115158a604001518381518110612c2c57612c2c6151c5565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83602001518460000151612c69919061594a565b8b8681518110612c7b57612c7b6151c5565b6020026020010151608001518d8f608001518881518110612c9e57612c9e6151c5565b6020026020010151604051612cb6949392919061596f565b60405180910390a3505b80612cca816151f4565b91505061299b565b505050602083810151336000908152600b90925260409091208054600290612d0f9084906201000090046bffffffffffffffffffffffff1661594a565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff16612d6d919061594a565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555082604001518360200151612daf919061594a565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612e2b91906152d9565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612eb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c8c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e010000000000000000000000000000900490911660608201529061312a576000816060015185612fc691906159ac565b90506000612fd485836159d1565b90508083604001818151612fe8919061594a565b6bffffffffffffffffffffffff1690525061300385826159fc565b83606001818151613014919061594a565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b600082600001828154811061314d5761314d6151c5565b9060005260206000200154905092915050565b6000818152600183016020526040812054801561324957600061318460018361517d565b85549091506000906131989060019061517d565b90508181146131fd5760008660000182815481106131b8576131b86151c5565b90600052602060002001549050808760000184815481106131db576131db6151c5565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061320e5761320e615a2c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ecd565b6000915050611ecd565b5092915050565b60008181526001830160205260408120546132a157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ecd565b506000611ecd565b6000818160045b600f811015613336577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106132ee576132ee6151c5565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461332457506000949350505050565b8061332e816151f4565b9150506132b0565b5081600f1a600181111561334c5761334c61563a565b949350505050565b60008080808560600151600181111561336f5761336f61563a565b03613395576133818888888888613e68565b61339057600092509050613469565b61340d565b6001856060015160018111156133ad576133ad61563a565b036133db5760006133c089898988613ff2565b92509050806133d55750600092509050613469565b5061340d565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061346257877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd56368760405161344f9190614cf7565b60405180910390a2600092509050613469565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156134d0576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b0000000000000000000000000000000000000000000000000000000090613545908590602401614cf7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906136189087908790600401615a5b565b60408051808303816000875af1158015613636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365a9190615a74565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b6000816060015160018111156136a6576136a661563a565b0361370a57600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156137225761372261563a565b0361378e5760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138279190615abc565b5093505092505060008213158061383d57508042105b8061386d57506000846040015162ffffff1611801561386d5750613861814261517d565b846040015162ffffff16105b15613253575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa15801561396a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398e9190615abc565b509350509250506000821315806139a457508042105b806139d457506000866040015162ffffff161180156139d457506139c8814261517d565b866040015162ffffff16105b156139e857600183015460608501526139f0565b606084018290525b50505092915050565b604080516101008101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e08201529082015115613a8f5760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613a9b86866141ff565b60c0840151602082015182519293509091600091613ab89161594a565b60e08801515190915060ff16600060128210613ad5576001613aeb565b613ae082601261517d565b613aeb90600a615c2c565b9050600060128311613afe576001613b14565b613b0960128461517d565b613b1490600a615c2c565b905085600001516bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613bbc57849350613b90818b60800151613b5491906152c2565b838c60e0015160600151886bffffffffffffffffffffffff16613b7791906152c2565b613b8191906152c2565b613b8b9190615936565b61452d565b6bffffffffffffffffffffffff9081166040880152600060608801819052602088015285168652613ce2565b836bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613ce257849350613c4a86604001516bffffffffffffffffffffffff16828c60800151613c0991906152c2565b848d60e0015160600151896bffffffffffffffffffffffff16613c2c91906152c2565b613c3691906152c2565b613c409190615936565b613b8b919061517d565b6bffffffffffffffffffffffff1660608088019190915260e08b01510151613cce90613c779084906152c2565b6001848d60e0015160600151613c8d91906152c2565b613c97919061517d565b838d608001518a606001516bffffffffffffffffffffffff16613cba91906152c2565b613cc491906152c2565b613b8191906152d9565b6bffffffffffffffffffffffff1660208701525b60008981526004602052604090206001018054859190601090613d2890849070010000000000000000000000000000000090046bffffffffffffffffffffffff166159ac565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008b81526004602052604081206001018054928816935091613d839084906fffffffffffffffffffffffffffffffff16615c38565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550836bffffffffffffffffffffffff16602160008c60c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613e1a919061517d565b92505081905550887f801ba6ed51146ffe3e99d1dbd9dd0f4de6292e78a9a34c39c0183de17b3f40fc87604051613e519190615c61565b60405180910390a250939998505050505050505050565b60008084806020019051810190613e7f9190615d21565b845160e00151815191925063ffffffff90811691161015613edc57867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e886604051613eca9190614cf7565b60405180910390a26000915050613fe9565b8260e001518015613f9c5750602081015115801590613f9c5750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f999190614f70565b14155b80613fae5750805163ffffffff168611155b15613fe357867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc30186604051613eca9190614cf7565b60019150505b95945050505050565b60008060008480602001905181019061400b9190615d79565b905060008782600001518360200151846040015160405160200161406d94939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e00151801561414857506080820151158015906141485750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614121573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141459190614f70565b14155b8061415d575086826060015163ffffffff1610155b156141a757877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516141929190614cf7565b60405180910390a26000935091506141f69050565b60008181526008602052604090205460ff16156141ee57877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516141929190614cf7565b600193509150505b94509492505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff16846060015161426a91906152c2565b9050836101000151801561427d5750803a105b1561428557503a5b6000601283116142965760016142ac565b6142a160128461517d565b6142ac90600a615c2c565b90506000601284106142bf5760016142d5565b6142ca84601261517d565b6142d590600a615c2c565b905060008660a001518760400151886020015189600001516142f791906152d9565b61430190876152c2565b61430b91906152d9565b61431591906152c2565b9050614358828860e001516060015161432e91906152c2565b6001848a60e001516060015161434491906152c2565b61434e919061517d565b613cc486856152c2565b6bffffffffffffffffffffffff168652608087015161437b90613b8b9083615936565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906143b49062ffffff16683635c9adc5dea000006152c2565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b6143e791906152c2565b6143f191906152d9565b6143fb91906152c2565b61440591906152c2565b61440f9190615936565b61441991906152d9565b905061445c848a60e001516060015161443291906152c2565b6001868c60e001516060015161444891906152c2565b614452919061517d565b613cc488856152c2565b6bffffffffffffffffffffffff166020890152608089015161448290613b8b9083615936565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a01919091528901516144c59061452d565b6bffffffffffffffffffffffff1660a0808a01919091528901516144e89061452d565b6bffffffffffffffffffffffff1660c089015260e08901516060015161450d9061452d565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff8211156145cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610c8c565b5090565b508054600082559060005260206000209081019061109c919061466f565b828054828255906000526020600020908101928215614667579160200282015b8281111561466757825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061460d565b506145cb9291505b5b808211156145cb5760008155600101614670565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff811182821017156146d7576146d7614684565b60405290565b60405160c0810167ffffffffffffffff811182821017156146d7576146d7614684565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561474757614747614684565b604052919050565b600067ffffffffffffffff82111561476957614769614684565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461109c57600080fd5b80356147a081614773565b919050565b600082601f8301126147b657600080fd5b813560206147cb6147c68361474f565b614700565b82815260059290921b840181019181810190868411156147ea57600080fd5b8286015b8481101561480e57803561480181614773565b83529183019183016147ee565b509695505050505050565b60ff8116811461109c57600080fd5b80356147a081614819565b63ffffffff8116811461109c57600080fd5b80356147a081614833565b801515811461109c57600080fd5b80356147a081614850565b62ffffff8116811461109c57600080fd5b80356147a081614869565b61ffff8116811461109c57600080fd5b80356147a081614885565b600061020082840312156148b357600080fd5b6148bb6146b3565b90506148c682614845565b81526148d460208301614845565b60208201526148e560408301614845565b60408201526148f660608301614795565b60608201526149076080830161485e565b608082015261491860a0830161487a565b60a082015261492960c08301614845565b60c082015261493a60e08301614845565b60e082015261010061494d818401614795565b9082015261012061495f838201614895565b90820152610140614971838201614795565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff8111156149b257600080fd5b6149be858286016147a5565b8284015250506101e06149d2818401614795565b9082015292915050565b803567ffffffffffffffff811681146147a057600080fd5b600082601f830112614a0557600080fd5b813567ffffffffffffffff811115614a1f57614a1f614684565b614a5060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614700565b818152846020838601011115614a6557600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461109c57600080fd5b600082601f830112614aad57600080fd5b81356020614abd6147c68361474f565b82815260c09283028501820192828201919087851115614adc57600080fd5b8387015b85811015614b6e5781818a031215614af85760008081fd5b614b006146dd565b8135614b0b81614833565b815281860135614b1a81614869565b81870152604082810135614b2d81614773565b90820152606082810135614b4081614819565b908201526080828101359082015260a080830135614b5d81614a82565b908201528452928401928101614ae0565b5090979650505050505050565b600080600080600080600080610100898b031215614b9857600080fd5b883567ffffffffffffffff80821115614bb057600080fd5b614bbc8c838d016147a5565b995060208b0135915080821115614bd257600080fd5b614bde8c838d016147a5565b9850614bec60408c01614828565b975060608b0135915080821115614c0257600080fd5b614c0e8c838d016148a0565b9650614c1c60808c016149dc565b955060a08b0135915080821115614c3257600080fd5b614c3e8c838d016149f4565b945060c08b0135915080821115614c5457600080fd5b614c608c838d016147a5565b935060e08b0135915080821115614c7657600080fd5b50614c838b828c01614a9c565b9150509295985092959890939650565b6000815180845260005b81811015614cb957602081850181015186830182015201614c9d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611edf6020830184614c93565b60008083601f840112614d1c57600080fd5b50813567ffffffffffffffff811115614d3457600080fd5b6020830191508360208260051b8501011115614d4f57600080fd5b9250929050565b60008060008060008060008060e0898b031215614d7257600080fd5b606089018a811115614d8357600080fd5b8998503567ffffffffffffffff80821115614d9d57600080fd5b818b0191508b601f830112614db157600080fd5b813581811115614dc057600080fd5b8c6020828501011115614dd257600080fd5b6020830199508098505060808b0135915080821115614df057600080fd5b614dfc8c838d01614d0a565b909750955060a08b0135915080821115614e1557600080fd5b50614e228b828c01614d0a565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614e5457600080fd5b863567ffffffffffffffff80821115614e6c57600080fd5b614e788a838b016147a5565b97506020890135915080821115614e8e57600080fd5b614e9a8a838b016147a5565b9650614ea860408a01614828565b95506060890135915080821115614ebe57600080fd5b614eca8a838b016149f4565b9450614ed860808a016149dc565b935060a0890135915080821115614eee57600080fd5b50614efb89828a016149f4565b9150509295509295509295565b600060208284031215614f1a57600080fd5b8135611edf81614773565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216029081169081811461325357613253614f25565b600060208284031215614f8257600080fd5b5051919050565b63ffffffff81811683821601908082111561325357613253614f25565b600081518084526020808501945080840160005b83811015614fec57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614fba565b509495945050505050565b6020815261500e60208201835163ffffffff169052565b60006020830151615027604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006150a68185018363ffffffff169052565b84015190506101206150cf8482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406150e68482018361ffff169052565b840151905061016061510f8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e080860182905291925090615157610220860184614fa6565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b81810381811115611ecd57611ecd614f25565b60008161519f5761519f614f25565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361522557615225614f25565b5060010190565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261525c8184018a614fa6565b905082810360808401526152708189614fa6565b905060ff871660a084015282810360c084015261528d8187614c93565b905067ffffffffffffffff851660e08401528281036101008401526152b28185614c93565b9c9b505050505050505050505050565b8082028115828204841417611ecd57611ecd614f25565b80820180821115611ecd57611ecd614f25565b60ff8181168382160190811115611ecd57611ecd614f25565b80516147a081614833565b80516147a081614773565b80516147a081614850565b80516147a081614869565b80516147a081614885565b600082601f83011261534d57600080fd5b8151602061535d6147c68361474f565b82815260059290921b8401810191818101908684111561537c57600080fd5b8286015b8481101561480e57805161539381614773565b8352918301918301615380565b600082601f8301126153b157600080fd5b815160206153c16147c68361474f565b82815260c092830285018201928282019190878511156153e057600080fd5b8387015b85811015614b6e5781818a0312156153fc5760008081fd5b6154046146dd565b815161540f81614833565b81528186015161541e81614869565b8187015260408281015161543181614773565b9082015260608281015161544481614819565b908201526080828101519082015260a08083015161546181614a82565b9082015284529284019281016153e4565b60008060006060848603121561548757600080fd5b835167ffffffffffffffff8082111561549f57600080fd5b9085019061020082880312156154b457600080fd5b6154bc6146b3565b6154c583615305565b81526154d360208401615305565b60208201526154e460408401615305565b60408201526154f560608401615310565b60608201526155066080840161531b565b608082015261551760a08401615326565b60a082015261552860c08401615305565b60c082015261553960e08401615305565b60e082015261010061554c818501615310565b9082015261012061555e848201615331565b90820152610140615570848201615310565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c080840151838111156155a957600080fd5b6155b58a82870161533c565b8284015250506101e06155c9818501615310565b9082015260208701519095509150808211156155e457600080fd5b6155f08783880161533c565b9350604086015191508082111561560657600080fd5b50615613868287016153a0565b9150509250925092565b60006020828403121561562f57600080fd5b8151611edf81614819565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526156b08285018b614fa6565b915083820360808501526156c4828a614fa6565b915060ff881660a085015283820360c08501526156e18288614c93565b90861660e085015283810361010085015290506152b28185614c93565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261573557600080fd5b813560206157456147c68361474f565b82815260059290921b8401810191818101908684111561576457600080fd5b8286015b8481101561480e5780358352918301918301615768565b600082601f83011261579057600080fd5b813560206157a06147c68361474f565b82815260059290921b840181019181810190868411156157bf57600080fd5b8286015b8481101561480e57803567ffffffffffffffff8111156157e35760008081fd5b6157f18986838b01016149f4565b8452509183019183016157c3565b60006020828403121561581157600080fd5b813567ffffffffffffffff8082111561582957600080fd5b9083019060c0828603121561583d57600080fd5b6158456146dd565b823581526020830135602082015260408301358281111561586557600080fd5b61587187828601615724565b60408301525060608301358281111561588957600080fd5b61589587828601615724565b6060830152506080830135828111156158ad57600080fd5b6158b98782860161577f565b60808301525060a0830135828111156158d157600080fd5b6158dd8782860161577f565b60a08301525095945050505050565b61ffff81811683821601908082111561325357613253614f25565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261594557615945615907565b500490565b6bffffffffffffffffffffffff81811683821601908082111561325357613253614f25565b6bffffffffffffffffffffffff851681528360208201528260408201526080606082015260006159a26080830184614c93565b9695505050505050565b6bffffffffffffffffffffffff82811682821603908082111561325357613253614f25565b60006bffffffffffffffffffffffff808416806159f0576159f0615907565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615a2457615a24614f25565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b82815260406020820152600061334c6040830184614c93565b60008060408385031215615a8757600080fd5b8251615a9281614850565b6020939093015192949293505050565b805169ffffffffffffffffffff811681146147a057600080fd5b600080600080600060a08688031215615ad457600080fd5b615add86615aa2565b9450602086015193506040860151925060608601519150615b0060808701615aa2565b90509295509295909350565b600181815b80851115615b6557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b4b57615b4b614f25565b80851615615b5857918102915b93841c9390800290615b11565b509250929050565b600082615b7c57506001611ecd565b81615b8957506000611ecd565b8160018114615b9f5760028114615ba957615bc5565b6001915050611ecd565b60ff841115615bba57615bba614f25565b50506001821b611ecd565b5060208310610133831016604e8410600b8410161715615be8575081810a611ecd565b615bf28383615b0c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615c2457615c24614f25565b029392505050565b6000611edf8383615b6d565b6fffffffffffffffffffffffffffffffff81811683821601908082111561325357613253614f25565b6000610100820190506bffffffffffffffffffffffff8084511683528060208501511660208401528060408501511660408401528060608501511660608401525073ffffffffffffffffffffffffffffffffffffffff608084015116608083015260a0830151615ce160a08401826bffffffffffffffffffffffff169052565b5060c0830151615d0160c08401826bffffffffffffffffffffffff169052565b5060e083015161325360e08401826bffffffffffffffffffffffff169052565b600060408284031215615d3357600080fd5b6040516040810181811067ffffffffffffffff82111715615d5657615d56614684565b6040528251615d6481614833565b81526020928301519281019290925250919050565b600060a08284031215615d8b57600080fd5b60405160a0810181811067ffffffffffffffff82111715615dae57615dae614684565b806040525082518152602083015160208201526040830151615dcf81614833565b60408201526060830151615de281614833565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b50604051620065423803806200654283398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615e2a620007186000396000818160b3015261018601526000505060005050600050506000505060006137bd015260005050600081816113710152612de60152615e2a6000f3fe6080604052600436106100b15760003560e01c80638da5cb5b11610069578063b1dc65a41161004e578063b1dc65a4146102cb578063e3d0e712146102eb578063f2fde38b1461030b576100b1565b80638da5cb5b1461025a578063afcb95d714610285576100b1565b8063349e8cca1161009a578063349e8cca1461017757806379ba5097146101cb57806381ff7048146101e0576100b1565b80630870d3a1146100f8578063181f5a7714610118575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100f1573d6000f35b3d6000fd5b005b34801561010457600080fd5b506100f6610113366004614b9e565b61032b565b34801561012457600080fd5b506101616040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b60405161016e9190614d1a565b60405180910390f35b34801561018357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016e565b3480156101d757600080fd5b506100f6610c0f565b3480156101ec57600080fd5b5061023760175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff94851681529390921660208401529082015260600161016e565b34801561026657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101a6565b34801561029157600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff169082015260600161016e565b3480156102d757600080fd5b506100f66102e6366004614d79565b610d11565b3480156102f757600080fd5b506100f6610306366004614e5e565b611051565b34801561031757600080fd5b506100f6610326366004614f2b565b61108b565b61033361109f565b601f8851111561036f576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103ac576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103cb57506103c3866003614f77565b60ff16885111155b15610402576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461043d576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104478282611122565b610451888861175a565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506000601660010160189054906101000a900463ffffffff1690506000866101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107259190614f93565b6017549091506000906107579074010000000000000000000000000000000000000000900463ffffffff166001614fac565b9050604051806101600160405280896060015173ffffffffffffffffffffffffffffffffffffffff168152602001896000015163ffffffff168152602001896020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200189610100015173ffffffffffffffffffffffffffffffffffffffff1681526020018263ffffffff1681526020018363ffffffff168152602001896040015163ffffffff16815260200189610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018960c0015163ffffffff1681526020018960e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050876101600151601981905550876101800151601a81905550876101a00151601b81905550600088604051602001610a9a919061501a565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610aff904690309074010000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f611e19565b6013556000610b0e6009611ec3565b90505b8015610b4b57610b38610b30610b286001846151a0565b600990611ed3565b600990611ee6565b5080610b43816151b3565b915050610b11565b5060005b896101c0015151811015610ba257610b8f8a6101c001518281518110610b7757610b776151e8565b60200260200101516009611f0890919063ffffffff16565b5080610b9a81615217565b915050610b4f565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0584601354601660010160149054906101000a900463ffffffff168f8f8f878f8f604051610bf99998979695949392919061524f565b60405180910390a1505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005a90506000610d238660406152e5565b610d2f896101446152fc565b610d3991906152fc565b9050368114610d74576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290610ed3576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16610f1c576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548b3514610f58576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151610f6890600161530f565b60ff1687141580610f795750868514155b15610fb0576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc08b8b8b8b8b8b8b8b611f2a565b6000610fcc8b8b612193565b905060208c0135600881901c63ffffffff16610fe984848861224c565b836020015163ffffffff168163ffffffff16111561104157601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b5050505050505050505050505050565b60008060008580602001905181019061106a9190615495565b925092509250611080898989868989888861032b565b505050505050505050565b61109361109f565b61109c81612e5c565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c8c565b565b60005b6024548110156111e0576022600060248381548110611146576111466151e8565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169055806111d881615217565b915050611125565b506111ed602460006145f2565b60255460ff1660005b8351811015611754576000848281518110611213576112136151e8565b602002602001015190506000848381518110611231576112316151e8565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112aa9190615640565b60ff16816060015160ff161415806113385750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113309190615640565b60ff16600814155b1561136f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156113db575060018460018111156113d9576113d961565d565b145b15611412576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061144d5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611484576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156114ee576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611737908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a25050808061174c90615217565b9150506111f6565b50505050565b600e546014546bffffffffffffffffffffffff1660005b600e548110156117cd576117ba600e8281548110611791576117916151e8565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168385612f51565b50806117c581615217565b915050611771565b5060255460009060ff16815b600e5481101561193e57600e81815481106117f6576117f66151e8565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611833576118336151e8565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560018260018111156118d5576118d561565d565b14801561191a575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b1561192c5761192a600f84611f08565b505b8061193681615217565b9150506117d9565b5061194b600d60006145f2565b611957600e60006145f2565b6040805160808101825260008082526020820181905291810182905260608101829052905b8751811015611de757600c600089838151811061199b5761199b6151e8565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611a06576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16888281518110611a3057611a306151e8565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611a85576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008a8481518110611ab657611ab66151e8565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558651879082908110611b5e57611b5e6151e8565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611bce576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611c89576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090951694909417179190911692909217919091179055836001811115611dc357611dc361565d565b03611dd557611dd3600f85611ee6565b505b80611ddf81615217565b91505061197c565b508651611dfb90600d9060208a0190614610565b508551611e0f90600e906020890190614610565b5050505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001611e3d9998979695949392919061568c565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b6000611ecd825490565b92915050565b6000611edf8383613159565b9392505050565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff8416613183565b6000611edf8373ffffffffffffffffffffffffffffffffffffffff841661327d565b60008787604051611f3c929190615721565b604051908190038120611f53918b90602001615731565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b8881101561212a57600185878360208110611fbf57611fbf6151e8565b611fcc91901a601b61530f565b8c8c85818110611fde57611fde6151e8565b905060200201358b8b86818110611ff757611ff76151e8565b9050602002013560405160008152602001604052604051612034949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612056573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612104576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061212290615217565b915050611fa2565b50827e01010101010101010101010101010101010101010101010101010101010101841614612185576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6121cc6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006121da83850185615822565b60408101515160608201515191925090811415806121fd57508082608001515114155b8061220d5750808260a001515114155b15612244576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561226c5761226c6146a7565b60405190808252806020026020018201604052801561233857816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161228a5790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fa9190614f93565b6101008701516040517f7810d12a00000000000000000000000000000000000000000000000000000000815236600482015291925060009173ffffffffffffffffffffffffffffffffffffffff90911690637810d12a90602401602060405180830381865afa158015612471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124959190614f93565b905060005b8660400151518110156129255760046000886040015183815181106124c1576124c16151e8565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106125e4576125e46151e8565b6020026020010151600001819052506126198760400151828151811061260c5761260c6151e8565b60200260200101516132cc565b85828151811061262b5761262b6151e8565b60200260200101516060019060018111156126485761264861565d565b9081600181111561265b5761265b61565d565b815250506126bf87604001518281518110612678576126786151e8565b60200260200101518489608001518481518110612697576126976151e8565b60200260200101518885815181106126b1576126b16151e8565b60200260200101518c613377565b8683815181106126d1576126d16151e8565b60200260200101516020018784815181106126ee576126ee6151e8565b602002602001015160c0018281525082151515158152505050848181518110612719576127196151e8565b602002602001015160200151156127495760018460000181815161273d919061590f565b61ffff1690525061274e565b612913565b6127b4858281518110612763576127636151e8565b6020026020010151600001516080015188606001518381518110612789576127896151e8565b60200260200101518960a0015184815181106127a7576127a76151e8565b6020026020010151613496565b8683815181106127c6576127c66151e8565b60200260200101516040018784815181106127e3576127e36151e8565b602002602001015160800182815250821515151581525050508760800151600161280d919061530f565b61281b9060ff1660406152e5565b6103a48860a001518381518110612834576128346151e8565b60200260200101515161284791906152fc565b61285191906152fc565b858281518110612863576128636151e8565b602002602001015160a0018181525050848181518110612885576128856151e8565b602002602001015160a00151846060018181516128a291906152fc565b90525084518590829081106128b9576128b96151e8565b602002602001015160800151866128d091906151a0565b9550612913876040015182815181106128eb576128eb6151e8565b602002602001015184878481518110612906576129066151e8565b60200260200101516136b1565b8061291d81615217565b91505061249a565b50825161ffff1660000361293c5750505050505050565b61c80061294a3660106152e5565b5a61295590886151a0565b61295f91906152fc565b61296991906152fc565b8351909550613778906129809061ffff1687615959565b61298a91906152fc565b60408051608081018252600080825260208201819052918101829052606081018290529196506129b9896137b6565b905060005b886040015151811015612cf5578681815181106129dd576129dd6151e8565b60200260200101516020015115612ce357801580612a75575086612a026001836151a0565b81518110612a1257612a126151e8565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612a4b57612a4b6151e8565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612aa957612aa68a888381518110612a9057612a906151e8565b60200260200101516000015161010001516138a0565b92505b6000612bc78b6040518061012001604052808b8681518110612acd57612acd6151e8565b60200260200101516080015181526020018c81526020018a606001518c8781518110612afb57612afb6151e8565b602002602001015160a001518a612b1291906152e5565b612b1c9190615959565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612b4d57612b4d6151e8565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612b9c57612b9c6151e8565b60200260200101518b8681518110612bb657612bb66151e8565b602002602001015160000151613a1c565b9050806060015187604001818151612bdf919061596d565b6bffffffffffffffffffffffff169052506040810151602088018051612c0690839061596d565b6bffffffffffffffffffffffff169052508751889083908110612c2b57612c2b6151e8565b60200260200101516040015115158a604001518381518110612c4f57612c4f6151e8565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83602001518460000151612c8c919061596d565b8b8681518110612c9e57612c9e6151e8565b6020026020010151608001518d8f608001518881518110612cc157612cc16151e8565b6020026020010151604051612cd99493929190615992565b60405180910390a3505b80612ced81615217565b9150506129be565b505050602083810151336000908152600b90925260409091208054600290612d329084906201000090046bffffffffffffffffffffffff1661596d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff16612d90919061596d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555082604001518360200151612dd2919061596d565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612e4e91906152fc565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612edb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c8c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e010000000000000000000000000000900490911660608201529061314d576000816060015185612fe991906159cf565b90506000612ff785836159f4565b9050808360400181815161300b919061596d565b6bffffffffffffffffffffffff169052506130268582615a1f565b83606001818151613037919061596d565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b6000826000018281548110613170576131706151e8565b9060005260206000200154905092915050565b6000818152600183016020526040812054801561326c5760006131a76001836151a0565b85549091506000906131bb906001906151a0565b90508181146132205760008660000182815481106131db576131db6151e8565b90600052602060002001549050808760000184815481106131fe576131fe6151e8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061323157613231615a4f565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ecd565b6000915050611ecd565b5092915050565b60008181526001830160205260408120546132c457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ecd565b506000611ecd565b6000818160045b600f811015613359577fff000000000000000000000000000000000000000000000000000000000000008216838260208110613311576133116151e8565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461334757506000949350505050565b8061335181615217565b9150506132d3565b5081600f1a600181111561336f5761336f61565d565b949350505050565b6000808080856060015160018111156133925761339261565d565b036133b8576133a48888888888613e8b565b6133b35760009250905061348c565b613430565b6001856060015160018111156133d0576133d061565d565b036133fe5760006133e389898988614015565b92509050806133f8575060009250905061348c565b50613430565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061348557877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516134729190614d1a565b60405180910390a260009250905061348c565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156134f3576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b0000000000000000000000000000000000000000000000000000000090613568908590602401614d1a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061363b9087908790600401615a7e565b60408051808303816000875af1158015613659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367d9190615a97565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b6000816060015160018111156136c9576136c961565d565b0361372d57600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156137455761374561565d565b036137b15760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613826573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384a9190615adf565b5093505092505060008213158061386057508042105b8061389057506000846040015162ffffff16118015613890575061388481426151a0565b846040015162ffffff16105b15613276575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa15801561398d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139b19190615adf565b509350509250506000821315806139c757508042105b806139f757506000866040015162ffffff161180156139f757506139eb81426151a0565b866040015162ffffff16105b15613a0b5760018301546060850152613a13565b606084018290525b50505092915050565b604080516101008101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e08201529082015115613ab25760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613abe8686614222565b60c0840151602082015182519293509091600091613adb9161596d565b60e08801515190915060ff16600060128210613af8576001613b0e565b613b038260126151a0565b613b0e90600a615c4f565b9050600060128311613b21576001613b37565b613b2c6012846151a0565b613b3790600a615c4f565b905085600001516bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613bdf57849350613bb3818b60800151613b7791906152e5565b838c60e0015160600151886bffffffffffffffffffffffff16613b9a91906152e5565b613ba491906152e5565b613bae9190615959565b614550565b6bffffffffffffffffffffffff9081166040880152600060608801819052602088015285168652613d05565b836bffffffffffffffffffffffff16856bffffffffffffffffffffffff161015613d0557849350613c6d86604001516bffffffffffffffffffffffff16828c60800151613c2c91906152e5565b848d60e0015160600151896bffffffffffffffffffffffff16613c4f91906152e5565b613c5991906152e5565b613c639190615959565b613bae91906151a0565b6bffffffffffffffffffffffff1660608088019190915260e08b01510151613cf190613c9a9084906152e5565b6001848d60e0015160600151613cb091906152e5565b613cba91906151a0565b838d608001518a606001516bffffffffffffffffffffffff16613cdd91906152e5565b613ce791906152e5565b613ba491906152fc565b6bffffffffffffffffffffffff1660208701525b60008981526004602052604090206001018054859190601090613d4b90849070010000000000000000000000000000000090046bffffffffffffffffffffffff166159cf565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008b81526004602052604081206001018054928816935091613da69084906fffffffffffffffffffffffffffffffff16615c5b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550836bffffffffffffffffffffffff16602160008c60c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613e3d91906151a0565b92505081905550887f801ba6ed51146ffe3e99d1dbd9dd0f4de6292e78a9a34c39c0183de17b3f40fc87604051613e749190615c84565b60405180910390a250939998505050505050505050565b60008084806020019051810190613ea29190615d44565b845160e00151815191925063ffffffff90811691161015613eff57867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e886604051613eed9190614d1a565b60405180910390a2600091505061400c565b8260e001518015613fbf5750602081015115801590613fbf5750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613f98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fbc9190614f93565b14155b80613fd15750805163ffffffff168611155b1561400657867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc30186604051613eed9190614d1a565b60019150505b95945050505050565b60008060008480602001905181019061402e9190615d9c565b905060008782600001518360200151846040015160405160200161409094939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e00151801561416b575060808201511580159061416b5750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141689190614f93565b14155b80614180575086826060015163ffffffff1610155b156141ca57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516141b59190614d1a565b60405180910390a26000935091506142199050565b60008181526008602052604090205460ff161561421157877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516141b59190614d1a565b600193509150505b94509492505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff16846060015161428d91906152e5565b905083610100015180156142a05750803a105b156142a857503a5b6000601283116142b95760016142cf565b6142c46012846151a0565b6142cf90600a615c4f565b90506000601284106142e25760016142f8565b6142ed8460126151a0565b6142f890600a615c4f565b905060008660a0015187604001518860200151896000015161431a91906152fc565b61432490876152e5565b61432e91906152fc565b61433891906152e5565b905061437b828860e001516060015161435191906152e5565b6001848a60e001516060015161436791906152e5565b61437191906151a0565b613ce786856152e5565b6bffffffffffffffffffffffff168652608087015161439e90613bae9083615959565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906143d79062ffffff16683635c9adc5dea000006152e5565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61440a91906152e5565b61441491906152fc565b61441e91906152e5565b61442891906152e5565b6144329190615959565b61443c91906152fc565b905061447f848a60e001516060015161445591906152e5565b6001868c60e001516060015161446b91906152e5565b61447591906151a0565b613ce788856152e5565b6bffffffffffffffffffffffff16602089015260808901516144a590613bae9083615959565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a01919091528901516144e890614550565b6bffffffffffffffffffffffff1660a0808a019190915289015161450b90614550565b6bffffffffffffffffffffffff1660c089015260e08901516060015161453090614550565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff8211156145ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610c8c565b5090565b508054600082559060005260206000209081019061109c9190614692565b82805482825590600052602060002090810192821561468a579160200282015b8281111561468a57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614630565b506145ee9291505b5b808211156145ee5760008155600101614693565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff811182821017156146fa576146fa6146a7565b60405290565b60405160c0810167ffffffffffffffff811182821017156146fa576146fa6146a7565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561476a5761476a6146a7565b604052919050565b600067ffffffffffffffff82111561478c5761478c6146a7565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461109c57600080fd5b80356147c381614796565b919050565b600082601f8301126147d957600080fd5b813560206147ee6147e983614772565b614723565b82815260059290921b8401810191818101908684111561480d57600080fd5b8286015b8481101561483157803561482481614796565b8352918301918301614811565b509695505050505050565b60ff8116811461109c57600080fd5b80356147c38161483c565b63ffffffff8116811461109c57600080fd5b80356147c381614856565b801515811461109c57600080fd5b80356147c381614873565b62ffffff8116811461109c57600080fd5b80356147c38161488c565b61ffff8116811461109c57600080fd5b80356147c3816148a8565b600061020082840312156148d657600080fd5b6148de6146d6565b90506148e982614868565b81526148f760208301614868565b602082015261490860408301614868565b6040820152614919606083016147b8565b606082015261492a60808301614881565b608082015261493b60a0830161489d565b60a082015261494c60c08301614868565b60c082015261495d60e08301614868565b60e08201526101006149708184016147b8565b908201526101206149828382016148b8565b908201526101406149948382016147b8565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff8111156149d557600080fd5b6149e1858286016147c8565b8284015250506101e06149f58184016147b8565b9082015292915050565b803567ffffffffffffffff811681146147c357600080fd5b600082601f830112614a2857600080fd5b813567ffffffffffffffff811115614a4257614a426146a7565b614a7360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614723565b818152846020838601011115614a8857600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461109c57600080fd5b600082601f830112614ad057600080fd5b81356020614ae06147e983614772565b82815260c09283028501820192828201919087851115614aff57600080fd5b8387015b85811015614b915781818a031215614b1b5760008081fd5b614b23614700565b8135614b2e81614856565b815281860135614b3d8161488c565b81870152604082810135614b5081614796565b90820152606082810135614b638161483c565b908201526080828101359082015260a080830135614b8081614aa5565b908201528452928401928101614b03565b5090979650505050505050565b600080600080600080600080610100898b031215614bbb57600080fd5b883567ffffffffffffffff80821115614bd357600080fd5b614bdf8c838d016147c8565b995060208b0135915080821115614bf557600080fd5b614c018c838d016147c8565b9850614c0f60408c0161484b565b975060608b0135915080821115614c2557600080fd5b614c318c838d016148c3565b9650614c3f60808c016149ff565b955060a08b0135915080821115614c5557600080fd5b614c618c838d01614a17565b945060c08b0135915080821115614c7757600080fd5b614c838c838d016147c8565b935060e08b0135915080821115614c9957600080fd5b50614ca68b828c01614abf565b9150509295985092959890939650565b6000815180845260005b81811015614cdc57602081850181015186830182015201614cc0565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611edf6020830184614cb6565b60008083601f840112614d3f57600080fd5b50813567ffffffffffffffff811115614d5757600080fd5b6020830191508360208260051b8501011115614d7257600080fd5b9250929050565b60008060008060008060008060e0898b031215614d9557600080fd5b606089018a811115614da657600080fd5b8998503567ffffffffffffffff80821115614dc057600080fd5b818b0191508b601f830112614dd457600080fd5b813581811115614de357600080fd5b8c6020828501011115614df557600080fd5b6020830199508098505060808b0135915080821115614e1357600080fd5b614e1f8c838d01614d2d565b909750955060a08b0135915080821115614e3857600080fd5b50614e458b828c01614d2d565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614e7757600080fd5b863567ffffffffffffffff80821115614e8f57600080fd5b614e9b8a838b016147c8565b97506020890135915080821115614eb157600080fd5b614ebd8a838b016147c8565b9650614ecb60408a0161484b565b95506060890135915080821115614ee157600080fd5b614eed8a838b01614a17565b9450614efb60808a016149ff565b935060a0890135915080821115614f1157600080fd5b50614f1e89828a01614a17565b9150509295509295509295565b600060208284031215614f3d57600080fd5b8135611edf81614796565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216029081169081811461327657613276614f48565b600060208284031215614fa557600080fd5b5051919050565b63ffffffff81811683821601908082111561327657613276614f48565b600081518084526020808501945080840160005b8381101561500f57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614fdd565b509495945050505050565b6020815261503160208201835163ffffffff169052565b6000602083015161504a604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006150c98185018363ffffffff169052565b84015190506101206150f28482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406151098482018361ffff169052565b84015190506101606151328482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e08086018290529192509061517a610220860184614fc9565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b81810381811115611ecd57611ecd614f48565b6000816151c2576151c2614f48565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361524857615248614f48565b5060010190565b600061012063ffffffff808d1684528b6020850152808b1660408501525080606084015261527f8184018a614fc9565b905082810360808401526152938189614fc9565b905060ff871660a084015282810360c08401526152b08187614cb6565b905067ffffffffffffffff851660e08401528281036101008401526152d58185614cb6565b9c9b505050505050505050505050565b8082028115828204841417611ecd57611ecd614f48565b80820180821115611ecd57611ecd614f48565b60ff8181168382160190811115611ecd57611ecd614f48565b80516147c381614856565b80516147c381614796565b80516147c381614873565b80516147c38161488c565b80516147c3816148a8565b600082601f83011261537057600080fd5b815160206153806147e983614772565b82815260059290921b8401810191818101908684111561539f57600080fd5b8286015b848110156148315780516153b681614796565b83529183019183016153a3565b600082601f8301126153d457600080fd5b815160206153e46147e983614772565b82815260c0928302850182019282820191908785111561540357600080fd5b8387015b85811015614b915781818a03121561541f5760008081fd5b615427614700565b815161543281614856565b8152818601516154418161488c565b8187015260408281015161545481614796565b908201526060828101516154678161483c565b908201526080828101519082015260a08083015161548481614aa5565b908201528452928401928101615407565b6000806000606084860312156154aa57600080fd5b835167ffffffffffffffff808211156154c257600080fd5b9085019061020082880312156154d757600080fd5b6154df6146d6565b6154e883615328565b81526154f660208401615328565b602082015261550760408401615328565b604082015261551860608401615333565b60608201526155296080840161533e565b608082015261553a60a08401615349565b60a082015261554b60c08401615328565b60c082015261555c60e08401615328565b60e082015261010061556f818501615333565b90820152610120615581848201615354565b90820152610140615593848201615333565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c080840151838111156155cc57600080fd5b6155d88a82870161535f565b8284015250506101e06155ec818501615333565b90820152602087015190955091508082111561560757600080fd5b6156138783880161535f565b9350604086015191508082111561562957600080fd5b50615636868287016153c3565b9150509250925092565b60006020828403121561565257600080fd5b8151611edf8161483c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526156d38285018b614fc9565b915083820360808501526156e7828a614fc9565b915060ff881660a085015283820360c08501526157048288614cb6565b90861660e085015283810361010085015290506152d58185614cb6565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261575857600080fd5b813560206157686147e983614772565b82815260059290921b8401810191818101908684111561578757600080fd5b8286015b84811015614831578035835291830191830161578b565b600082601f8301126157b357600080fd5b813560206157c36147e983614772565b82815260059290921b840181019181810190868411156157e257600080fd5b8286015b8481101561483157803567ffffffffffffffff8111156158065760008081fd5b6158148986838b0101614a17565b8452509183019183016157e6565b60006020828403121561583457600080fd5b813567ffffffffffffffff8082111561584c57600080fd5b9083019060c0828603121561586057600080fd5b615868614700565b823581526020830135602082015260408301358281111561588857600080fd5b61589487828601615747565b6040830152506060830135828111156158ac57600080fd5b6158b887828601615747565b6060830152506080830135828111156158d057600080fd5b6158dc878286016157a2565b60808301525060a0830135828111156158f457600080fd5b615900878286016157a2565b60a08301525095945050505050565b61ffff81811683821601908082111561327657613276614f48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826159685761596861592a565b500490565b6bffffffffffffffffffffffff81811683821601908082111561327657613276614f48565b6bffffffffffffffffffffffff851681528360208201528260408201526080606082015260006159c56080830184614cb6565b9695505050505050565b6bffffffffffffffffffffffff82811682821603908082111561327657613276614f48565b60006bffffffffffffffffffffffff80841680615a1357615a1361592a565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615a4757615a47614f48565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b82815260406020820152600061336f6040830184614cb6565b60008060408385031215615aaa57600080fd5b8251615ab581614873565b6020939093015192949293505050565b805169ffffffffffffffffffff811681146147c357600080fd5b600080600080600060a08688031215615af757600080fd5b615b0086615ac5565b9450602086015193506040860151925060608601519150615b2360808701615ac5565b90509295509295909350565b600181815b80851115615b8857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b6e57615b6e614f48565b80851615615b7b57918102915b93841c9390800290615b34565b509250929050565b600082615b9f57506001611ecd565b81615bac57506000611ecd565b8160018114615bc25760028114615bcc57615be8565b6001915050611ecd565b60ff841115615bdd57615bdd614f48565b50506001821b611ecd565b5060208310610133831016604e8410600b8410161715615c0b575081810a611ecd565b615c158383615b2f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615c4757615c47614f48565b029392505050565b6000611edf8383615b90565b6fffffffffffffffffffffffffffffffff81811683821601908082111561327657613276614f48565b6000610100820190506bffffffffffffffffffffffff8084511683528060208501511660208401528060408501511660408401528060608501511660608401525073ffffffffffffffffffffffffffffffffffffffff608084015116608083015260a0830151615d0460a08401826bffffffffffffffffffffffff169052565b5060c0830151615d2460c08401826bffffffffffffffffffffffff169052565b5060e083015161327660e08401826bffffffffffffffffffffffff169052565b600060408284031215615d5657600080fd5b6040516040810181811067ffffffffffffffff82111715615d7957615d796146a7565b6040528251615d8781614856565b81526020928301519281019290925250919050565b600060a08284031215615dae57600080fd5b60405160a0810181811067ffffffffffffffff82111715615dd157615dd16146a7565b806040525082518152602083015160208201526040830151615df281614856565b60408201526060830151615e0581614856565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI diff --git a/core/gethwrappers/generated/chain_module_base/chain_module_base.go b/core/gethwrappers/generated/chain_module_base/chain_module_base.go index bf98608aab7..19bc49298f5 100644 --- a/core/gethwrappers/generated/chain_module_base/chain_module_base.go +++ b/core/gethwrappers/generated/chain_module_base/chain_module_base.go @@ -29,8 +29,8 @@ var ( ) var ChainModuleBaseMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061015c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806357e871e71161005057806357e871e71461009a57806385df51fd146100a0578063de9ee35e146100b357600080fd5b8063125441401461006c57806318b8f61314610093575b600080fd5b61008061007a3660046100f6565b50600090565b6040519081526020015b60405180910390f35b6000610080565b43610080565b6100806100ae3660046100f6565b6100c9565b6040805161012c8152600060208201520161008a565b600043821015806100e457506101006100e2834361010f565b115b156100f157506000919050565b504090565b60006020828403121561010857600080fd5b5035919050565b81810381811115610149577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l1Fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"maxL1Fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610155806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637810d12a116100505780637810d12a1461006c57806385df51fd14610099578063de9ee35e146100ac57600080fd5b8063125441401461006c57806357e871e714610093575b600080fd5b61008061007a3660046100ef565b50600090565b6040519081526020015b60405180910390f35b43610080565b6100806100a73660046100ef565b6100c2565b6040805161012c8152600060208201520161008a565b600043821015806100dd57506101006100db8343610108565b115b156100ea57506000919050565b504090565b60006020828403121561010157600080fd5b5035919050565b81810381811115610142577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000a", } var ChainModuleBaseABI = ChainModuleBaseMetaData.ABI @@ -213,9 +213,9 @@ func (_ChainModuleBase *ChainModuleBaseCallerSession) BlockNumber() (*big.Int, e return _ChainModuleBase.Contract.BlockNumber(&_ChainModuleBase.CallOpts) } -func (_ChainModuleBase *ChainModuleBaseCaller) GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) { +func (_ChainModuleBase *ChainModuleBaseCaller) GetCurrentL1Fee(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { var out []interface{} - err := _ChainModuleBase.contract.Call(opts, &out, "getCurrentL1Fee") + err := _ChainModuleBase.contract.Call(opts, &out, "getCurrentL1Fee", arg0) if err != nil { return *new(*big.Int), err @@ -227,12 +227,12 @@ func (_ChainModuleBase *ChainModuleBaseCaller) GetCurrentL1Fee(opts *bind.CallOp } -func (_ChainModuleBase *ChainModuleBaseSession) GetCurrentL1Fee() (*big.Int, error) { - return _ChainModuleBase.Contract.GetCurrentL1Fee(&_ChainModuleBase.CallOpts) +func (_ChainModuleBase *ChainModuleBaseSession) GetCurrentL1Fee(arg0 *big.Int) (*big.Int, error) { + return _ChainModuleBase.Contract.GetCurrentL1Fee(&_ChainModuleBase.CallOpts, arg0) } -func (_ChainModuleBase *ChainModuleBaseCallerSession) GetCurrentL1Fee() (*big.Int, error) { - return _ChainModuleBase.Contract.GetCurrentL1Fee(&_ChainModuleBase.CallOpts) +func (_ChainModuleBase *ChainModuleBaseCallerSession) GetCurrentL1Fee(arg0 *big.Int) (*big.Int, error) { + return _ChainModuleBase.Contract.GetCurrentL1Fee(&_ChainModuleBase.CallOpts, arg0) } func (_ChainModuleBase *ChainModuleBaseCaller) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, @@ -301,7 +301,7 @@ type ChainModuleBaseInterface interface { BlockNumber(opts *bind.CallOpts) (*big.Int, error) - GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) + GetCurrentL1Fee(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, diff --git a/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go b/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go index c59a6f0f0d1..aa76f2a79d4 100644 --- a/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go +++ b/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go @@ -30,30 +30,42 @@ var ( _ = abi.ConvertType ) -type InnerTestStruct struct { +type InnerDynamicTestStruct struct { IntVal int64 S string } -type MidLevelTestStruct struct { +type InnerStaticTestStruct struct { + IntVal int64 + A common.Address +} + +type MidLevelDynamicTestStruct struct { + FixedBytes [2]byte + Inner InnerDynamicTestStruct +} + +type MidLevelStaticTestStruct struct { FixedBytes [2]byte - Inner InnerTestStruct + Inner InnerStaticTestStruct } type TestStruct struct { - Field int32 - DifferentField string - OracleId uint8 - OracleIds [32]uint8 - Account common.Address - Accounts []common.Address - BigField *big.Int - NestedStruct MidLevelTestStruct + Field int32 + DifferentField string + OracleId uint8 + OracleIds [32]uint8 + Account common.Address + AccountStr common.Address + Accounts []common.Address + BigField *big.Int + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct } var ChainReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"Triggered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"fieldHash\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"TriggeredEventWithDynamicTopic\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"TriggeredWithFourTopics\",\"type\":\"event\"},{\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"addTestStruct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"NestedStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSliceValue\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"returnSeen\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"NestedStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"value\",\"type\":\"uint64\"}],\"name\":\"setAlterablePrimitiveValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"triggerEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"triggerEventWithDynamicTopic\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"triggerWithFourTopics\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\"}]", - Bin: "0x608060405234801561001057600080fd5b50600180548082018255600082905260048082047fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101805460086003958616810261010090810a8088026001600160401b0391820219909416939093179093558654808801909755848704909301805496909516909202900a91820291021990921691909117905561199c806100a96000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063a90e199811610081578063ef4e1ced1161005b578063ef4e1ced146101de578063f6f871c8146101e5578063fbe9fbf6146101f857600080fd5b8063a90e19981461019b578063ab5e0b38146101ae578063dbfd7332146101cb57600080fd5b8063679004a4116100b2578063679004a41461012a5780636c9a43b61461013f5780637f002d671461018857600080fd5b80632c45576f146100d95780633272b66c1461010257806349eac2ac14610117575b600080fd5b6100ec6100e7366004610ca3565b61020a565b6040516100f99190610e0c565b60405180910390f35b610115610110366004610f4b565b6104e5565b005b610115610125366004611060565b61053a565b61013261083d565b6040516100f99190611152565b61011561014d3660046111a0565b600280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b610115610196366004611060565b6108c9565b6101156101a93660046112d4565b610920565b6107c65b60405167ffffffffffffffff90911681526020016100f9565b6101156101d9366004611389565b61097a565b60036101b2565b6100ec6101f3366004611060565b6109b7565b60025467ffffffffffffffff166101b2565b610212610ac0565b600061021f6001846113cc565b8154811061022f5761022f611406565b6000918252602091829020604080516101008101909152600a90920201805460030b8252600181018054929391929184019161026a90611435565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611435565b80156102e35780601f106102b8576101008083540402835291602001916102e3565b820191906000526020600020905b8154815290600101906020018083116102c657829003601f168201915b5050509183525050600282015460ff166020808301919091526040805161040081018083529190930192916003850191826000855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161031857505050928452505050600482015473ffffffffffffffffffffffffffffffffffffffff1660208083019190915260058301805460408051828502810185018252828152940193928301828280156103d157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116103a6575b5050509183525050600682015460170b6020808301919091526040805180820182526007808601805460f01b7fffff0000000000000000000000000000000000000000000000000000000000001683528351808501855260088801805490930b8152600988018054959097019693959194868301949193928401919061045690611435565b80601f016020809104026020016040519081016040528092919081815260200182805461048290611435565b80156104cf5780601f106104a4576101008083540402835291602001916104cf565b820191906000526020600020905b8154815290600101906020018083116104b257829003601f168201915b5050509190925250505090525090525092915050565b81816040516104f5929190611482565b60405180910390207f3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c67838360405161052e9291906114db565b60405180910390a25050565b60006040518061010001604052808c60030b81526020018b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8a166020808301919091526040805161040081810183529190930192918b9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff8816602080830191909152604080518883028181018401835289825291909301929189918991829190850190849080828437600092019190915250505090825250601785900b602082015260400161062c84611531565b905281546001808201845560009384526020938490208351600a9093020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909316929092178255928201519192909190820190610692908261161e565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560608201516106e09060038301906020610b0f565b5060808201516004820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905560a08201518051610747916005840191602090910190610ba2565b5060c08201516006820180547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560e082015180516007830180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660f09290921c91909117815560208083015180516008860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117815591810151909190600986019061082a908261161e565b5050505050505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156108bf57602002820191906000526020600020906000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001906008019060208260070104928301926001038202915080841161087a5790505b5050505050905090565b8960030b7f7188419dcd8b51877b71766f075f3626586c0ff190e7d056aa65ce9acb649a3d8a8a8a8a8a8a8a8a8a60405161090c9998979695949392919061187d565b60405180910390a250505050505050505050565b808260405161092f9190611937565b6040518091039020846040516109459190611973565b604051908190038120907f7220e4dbe4e9d0ed5f71acd022bc89c26748ac6784f2c548bc17bb8e52af34b090600090a4505050565b8060030b8260030b8460030b7f91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac560405160405180910390a4505050565b6109bf610ac0565b6040518061010001604052808c60030b81526020018b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8a166020808301919091526040805161040081810183529190930192918b9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff8816602080830191909152604080518883028181018401835289825291909301929189918991829190850190849080828437600092019190915250505090825250601785900b6020820152604001610aaf84611531565b90529b9a5050505050505050505050565b6040805161010081018252600080825260606020830181905292820152908101610ae8610c1c565b8152600060208201819052606060408301819052820152608001610b0a610c3b565b905290565b600183019183908215610b925791602002820160005b83821115610b6357835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610b25565b8015610b905782816101000a81549060ff0219169055600101602081600001049283019260010302610b63565b505b50610b9e929150610c8e565b5090565b828054828255906000526020600020908101928215610b92579160200282015b82811115610b9257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190610bc2565b6040518061040001604052806020906020820280368337509192915050565b604051806040016040528060007dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001610b0a6040518060400160405280600060070b8152602001606081525090565b5b80821115610b9e5760008155600101610c8f565b600060208284031215610cb557600080fd5b5035919050565b60005b83811015610cd7578181015183820152602001610cbf565b50506000910152565b60008151808452610cf8816020860160208601610cbc565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b6020808210610d3d5750610d54565b825160ff1685529384019390910190600101610d2e565b50505050565b600081518084526020808501945080840160005b83811015610da057815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610d6e565b509495945050505050565b7fffff00000000000000000000000000000000000000000000000000000000000081511682526000602082015160406020850152805160070b60408501526020810151905060406060850152610e046080850182610ce0565b949350505050565b60208152610e2060208201835160030b9052565b600060208301516104e0806040850152610e3e610500850183610ce0565b91506040850151610e54606086018260ff169052565b506060850151610e676080860182610d2a565b50608085015173ffffffffffffffffffffffffffffffffffffffff1661048085015260a08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840381016104a0870152610ec48483610d5a565b935060c08701519150610edd6104c087018360170b9052565b60e0870151915080868503018387015250610ef88382610dab565b9695505050505050565b60008083601f840112610f1457600080fd5b50813567ffffffffffffffff811115610f2c57600080fd5b602083019150836020828501011115610f4457600080fd5b9250929050565b60008060208385031215610f5e57600080fd5b823567ffffffffffffffff811115610f7557600080fd5b610f8185828601610f02565b90969095509350505050565b8035600381900b8114610f9f57600080fd5b919050565b803560ff81168114610f9f57600080fd5b806104008101831015610fc757600080fd5b92915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f9f57600080fd5b60008083601f84011261100357600080fd5b50813567ffffffffffffffff81111561101b57600080fd5b6020830191508360208260051b8501011115610f4457600080fd5b8035601781900b8114610f9f57600080fd5b60006040828403121561105a57600080fd5b50919050565b6000806000806000806000806000806104e08b8d03121561108057600080fd5b6110898b610f8d565b995060208b013567ffffffffffffffff808211156110a657600080fd5b6110b28e838f01610f02565b909b5099508991506110c660408e01610fa4565b98506110d58e60608f01610fb5565b97506110e46104608e01610fcd565b96506104808d01359150808211156110fb57600080fd5b6111078e838f01610ff1565b909650945084915061111c6104a08e01611036565b93506104c08d013591508082111561113357600080fd5b506111408d828e01611048565b9150509295989b9194979a5092959850565b6020808252825182820181905260009190848201906040850190845b8181101561119457835167ffffffffffffffff168352928401929184019160010161116e565b50909695505050505050565b6000602082840312156111b257600080fd5b813567ffffffffffffffff811681146111ca57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611223576112236111d1565b60405290565b600082601f83011261123a57600080fd5b813567ffffffffffffffff80821115611255576112556111d1565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561129b5761129b6111d1565b816040528381528660208588010111156112b457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600061044084860312156112ea57600080fd5b833567ffffffffffffffff8082111561130257600080fd5b61130e87838801611229565b94506020915086603f87011261132357600080fd5b6040516104008101818110838211171561133f5761133f6111d1565b60405290508061042087018881111561135757600080fd5b8388015b818110156113795761136c81610fa4565b845292840192840161135b565b5095989097509435955050505050565b60008060006060848603121561139e57600080fd5b6113a784610f8d565b92506113b560208501610f8d565b91506113c360408501610f8d565b90509250925092565b81810381811115610fc7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061144957607f821691505b60208210810361105a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610e04602083018486611492565b80357fffff00000000000000000000000000000000000000000000000000000000000081168114610f9f57600080fd5b8035600781900b8114610f9f57600080fd5b60006040823603121561154357600080fd5b61154b611200565b611554836114ef565b8152602083013567ffffffffffffffff8082111561157157600080fd5b81850191506040823603121561158657600080fd5b61158e611200565b6115978361151f565b81526020830135828111156115ab57600080fd5b6115b736828601611229565b60208301525080602085015250505080915050919050565b601f82111561161957600081815260208120601f850160051c810160208610156115f65750805b601f850160051c820191505b8181101561161557828155600101611602565b5050505b505050565b815167ffffffffffffffff811115611638576116386111d1565b61164c816116468454611435565b846115cf565b602080601f83116001811461169f57600084156116695750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611615565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156116ec578886015182559484019460019091019084016116cd565b508582101561172857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8183526000602080850194508260005b85811015610da05773ffffffffffffffffffffffffffffffffffffffff61176e83610fcd565b1687529582019590820190600101611748565b7fffff0000000000000000000000000000000000000000000000000000000000006117ab826114ef565b168252600060208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126117e557600080fd5b6040602085015282016117f78161151f565b60070b604085015260208101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811261183457600080fd5b0160208101903567ffffffffffffffff81111561185057600080fd5b80360382131561185f57600080fd5b60406060860152611874608086018284611492565b95945050505050565b60006104c08083526118928184018c8e611492565b9050602060ff808c1682860152604085018b60005b848110156118cc57836118b983610fa4565b16835291840191908401906001016118a7565b505050505073ffffffffffffffffffffffffffffffffffffffff8816610440840152828103610460840152611902818789611738565b905061191461048084018660170b9052565b8281036104a08401526119278185611781565b9c9b505050505050505050505050565b60008183825b602080821061194c5750611963565b825160ff168452928301929091019060010161193d565b5050506104008201905092915050565b60008251611985818460208701610cbc565b919091019291505056fea164736f6c6343000813000a", + 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]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"},{\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"accountStr\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"accountStr\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"accountStr\",\"type\":\"address\"},{\"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\"}]", + Bin: "0x608060405234801561001057600080fd5b50600180548082018255600082905260048082047fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101805460086003958616810261010090810a8088026001600160401b0391820219909416939093179093558654808801909755848704909301805496909516909202900a918202910219909216919091179055612077806100a96000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c8063679004a41161008c578063ab5e0b3811610066578063ab5e0b38146101df578063dbfd7332146101fc578063ef4e1ced1461020f578063fbe9fbf61461021657600080fd5b8063679004a41461016e5780636c9a43b614610183578063a90e1998146101cc57600080fd5b80633272b66c116100bd5780633272b66c1461013557806338e372ba1461014857806351f3f54d1461015b57600080fd5b8063236aadd6146100e45780632c45576f1461010d57806331a2c37914610120575b600080fd5b6100f76100f2366004611041565b610228565b60405161010491906112b4565b60405180910390f35b6100f761011b36600461141d565b610356565b61013361012e366004611436565b6106c6565b005b610133610143366004611546565b610723565b610133610156366004611041565b610778565b6101336101693660046116a0565b610b60565b610176610bd4565b6040516101049190611751565b61013361019136600461179f565b600280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6101336101da3660046117e1565b610c60565b6107c65b60405167ffffffffffffffff9091168152602001610104565b61013361020a366004611896565b610cba565b60036101e3565b60025467ffffffffffffffff166101e3565b610230610cf7565b6040518061014001604052808e60030b81526020018d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8c166020808301919091526040805161040081810183529190930192918d9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff808b16602080840191909152908a1660408084019190915280518983028181018401909252898152606090930192918a918a91829190850190849080828437600092019190915250505090825250601786900b602082015260400161032d8561191b565b8152602001610341368590038501856119b9565b905290505b9c9b505050505050505050505050565b61035e610cf7565b600061036b600184611a49565b8154811061037b5761037b611a83565b6000918252602091829020604080516101408101909152600d90920201805460030b825260018101805492939192918401916103b690611ab2565b80601f01602080910402602001604051908101604052809291908181526020018280546103e290611ab2565b801561042f5780601f106104045761010080835404028352916020019161042f565b820191906000526020600020905b81548152906001019060200180831161041257829003601f168201915b5050509183525050600282015460ff166020808301919091526040805161040081018083529190930192916003850191826000855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161046457505050928452505050600482015473ffffffffffffffffffffffffffffffffffffffff9081166020808401919091526005840154909116604080840191909152600684018054825181850281018501909352808352606090940193919290919083018282801561053657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161050b575b505050918352505060078281015460170b60208084019190915260408051808201825260088601805460f01b7fffff0000000000000000000000000000000000000000000000000000000000001682528251808401845260098801805490960b8152600a88018054949097019692959194868101949193908401916105ba90611ab2565b80601f01602080910402602001604051908101604052809291908181526020018280546105e690611ab2565b80156106335780601f1061060857610100808354040283529160200191610633565b820191906000526020600020905b81548152906001019060200180831161061657829003601f168201915b505050919092525050509052508152604080518082018252600b84015460f01b7fffff0000000000000000000000000000000000000000000000000000000000001681528151808301909252600c90930154600781900b825268010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1660208083019190915280840191909152015292915050565b8b60030b7f855ac250d95b464eea2a7645e23a88fdab21031016175b7dc4d65e8efc72c2ea8c8c8c8c8c8c8c8c8c8c8c60405161070d9b9a99989796959493929190611c2f565b60405180910390a2505050505050505050505050565b8181604051610733929190611dcc565b60405180910390207f3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c67838360405161076c929190611ddc565b60405180910390a25050565b60006040518061014001604052808e60030b81526020018d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8c166020808301919091526040805161040081810183529190930192918d9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff808b16602080840191909152908a1660408084019190915280518983028181018401909252898152606090930192918a918a91829190850190849080828437600092019190915250505090825250601786900b60208201526040016108778561191b565b815260200161088b368590038501856119b9565b905281546001808201845560009384526020938490208351600d9093020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9093169290921782559282015191929091908201906108f19082611e3f565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055606082015161093f9060038301906020610d7f565b50608082015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560a084015160058401805491909316911617905560c082015180516109ba916006840191602090910190610e12565b5060e08201516007820180547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905561010082015180516008830180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660f09290921c91909117815560208083015180516009860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117815591810151909190600a860190610a9e9082611e3f565b5050505061012092909201518051600b8301805460f09290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092169190911790556020908101518051600c9093018054919092015173ffffffffffffffffffffffffffffffffffffffff1668010000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090911667ffffffffffffffff9093169290921791909117905550505050505050505050505050565b60008888888888888888604051602001610b81989796959493929190611f59565b60405160208183030381529060405290507f1e40927ec0bdc7319f09a53452590433ec395dec3b70b982eba779c740685bfe81604051610bc19190611fff565b60405180910390a1505050505050505050565b60606001805480602002602001604051908101604052809291908181526020018280548015610c5657602002820191906000526020600020906000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020019060080190602082600701049283019260010382029150808411610c115790505b5050505050905090565b8082604051610c6f9190612012565b604051809103902084604051610c85919061204e565b604051908190038120907f7220e4dbe4e9d0ed5f71acd022bc89c26748ac6784f2c548bc17bb8e52af34b090600090a4505050565b8060030b8260030b8460030b7f91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac560405160405180910390a4505050565b6040805161014081018252600080825260606020830181905292820152908101610d1f610e8c565b815260006020820181905260408201819052606080830152608082015260a001610d47610eab565b8152602001610d7a6040805180820182526000808252825180840190935280835260208381019190915290919082015290565b905290565b600183019183908215610e025791602002820160005b83821115610dd357835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610d95565b8015610e005782816101000a81549060ff0219169055600101602081600001049283019260010302610dd3565b505b50610e0e929150610efe565b5090565b828054828255906000526020600020908101928215610e02579160200282015b82811115610e0257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190610e32565b6040518061040001604052806020906020820280368337509192915050565b604051806040016040528060007dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001610d7a6040518060400160405280600060070b8152602001606081525090565b5b80821115610e0e5760008155600101610eff565b8035600381900b8114610f2557600080fd5b919050565b60008083601f840112610f3c57600080fd5b50813567ffffffffffffffff811115610f5457600080fd5b602083019150836020828501011115610f6c57600080fd5b9250929050565b803560ff81168114610f2557600080fd5b806104008101831015610f9657600080fd5b92915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f2557600080fd5b60008083601f840112610fd257600080fd5b50813567ffffffffffffffff811115610fea57600080fd5b6020830191508360208260051b8501011115610f6c57600080fd5b8035601781900b8114610f2557600080fd5b60006040828403121561102957600080fd5b50919050565b60006060828403121561102957600080fd5b6000806000806000806000806000806000806105608d8f03121561106457600080fd5b61106d8d610f13565b9b5067ffffffffffffffff60208e0135111561108857600080fd5b6110988e60208f01358f01610f2a565b909b5099506110a960408e01610f73565b98506110b88e60608f01610f84565b97506110c76104608e01610f9c565b96506110d66104808e01610f9c565b955067ffffffffffffffff6104a08e013511156110f257600080fd5b6111038e6104a08f01358f01610fc0565b90955093506111156104c08e01611005565b925067ffffffffffffffff6104e08e0135111561113157600080fd5b6111428e6104e08f01358f01611017565b91506111528e6105008f0161102f565b90509295989b509295989b509295989b565b60005b8381101561117f578181015183820152602001611167565b50506000910152565b600081518084526111a0816020860160208601611164565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60208082106111e557506111fc565b825160ff16855293840193909101906001016111d6565b50505050565b600081518084526020808501945080840160005b8381101561124857815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611216565b509495945050505050565b7fffff00000000000000000000000000000000000000000000000000000000000081511682526000602082015160406020850152805160070b604085015260208101519050604060608501526112ac6080850182611188565b949350505050565b602081526112c860208201835160030b9052565b6000602083015161056060408401526112e5610580840182611188565b905060408401516112fb606085018260ff169052565b50606084015161130e60808501826111d2565b50608084015173ffffffffffffffffffffffffffffffffffffffff90811661048085015260a0850151166104a084015260c08401518382037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09081016104c086015261137a8383611202565b925060e086015191506113936104e086018360170b9052565b61010086015191508085840301610500860152506113b18282611253565b61012086015180517fffff00000000000000000000000000000000000000000000000000000000000016610520870152602080820151805160070b610540890152015173ffffffffffffffffffffffffffffffffffffffff166105608701529092509050509392505050565b60006020828403121561142f57600080fd5b5035919050565b6000806000806000806000806000806000806105608d8f03121561145957600080fd5b6114628d610f13565b9b5061147060208e01610f73565b9a5067ffffffffffffffff60408e0135111561148b57600080fd5b61149b8e60408f01358f01611017565b99506114aa8e60608f0161102f565b98506114b98e60c08f01610f84565b97506114c86104c08e01610f9c565b96506114d76104e08e01610f9c565b955067ffffffffffffffff6105008e013511156114f357600080fd5b6115048e6105008f01358f01610fc0565b909550935067ffffffffffffffff6105208e0135111561152357600080fd5b6115348e6105208f01358f01610f2a565b90935091506111526105408e01611005565b6000806020838503121561155957600080fd5b823567ffffffffffffffff81111561157057600080fd5b61157c85828601610f2a565b90969095509350505050565b803563ffffffff81168114610f2557600080fd5b803567ffffffffffffffff81168114610f2557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611606576116066115b4565b60405290565b600067ffffffffffffffff80841115611627576116276115b4565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561166d5761166d6115b4565b8160405280935085815286868601111561168657600080fd5b858560208301376000602087830101525050509392505050565b600080600080600080600080610100898b0312156116bd57600080fd5b6116c689611588565b97506116d460208a01611588565b96506116e260408a01611588565b95506116f060608a0161159c565b94506080890135935060a0890135925060c0890135915060e089013567ffffffffffffffff81111561172157600080fd5b8901601f81018b1361173257600080fd5b6117418b82356020840161160c565b9150509295985092959890939650565b6020808252825182820181905260009190848201906040850190845b8181101561179357835167ffffffffffffffff168352928401929184019160010161176d565b50909695505050505050565b6000602082840312156117b157600080fd5b6117ba8261159c565b9392505050565b600082601f8301126117d257600080fd5b6117ba8383356020850161160c565b600080600061044084860312156117f757600080fd5b833567ffffffffffffffff8082111561180f57600080fd5b61181b878388016117c1565b94506020915086603f87011261183057600080fd5b6040516104008101818110838211171561184c5761184c6115b4565b60405290508061042087018881111561186457600080fd5b8388015b818110156118865761187981610f73565b8452928401928401611868565b5095989097509435955050505050565b6000806000606084860312156118ab57600080fd5b6118b484610f13565b92506118c260208501610f13565b91506118d060408501610f13565b90509250925092565b80357fffff00000000000000000000000000000000000000000000000000000000000081168114610f2557600080fd5b8035600781900b8114610f2557600080fd5b60006040823603121561192d57600080fd5b6119356115e3565b61193e836118d9565b8152602083013567ffffffffffffffff8082111561195b57600080fd5b81850191506040823603121561197057600080fd5b6119786115e3565b61198183611909565b815260208301358281111561199557600080fd5b6119a1368286016117c1565b60208301525080602085015250505080915050919050565b600081830360608112156119cc57600080fd5b6119d46115e3565b6119dd846118d9565b815260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083011215611a0f57600080fd5b611a176115e3565b9150611a2560208501611909565b8252611a3360408501610f9c565b6020830152816020820152809250505092915050565b81810381811115610f96577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c90821680611ac657607f821691505b602082108103611029577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b7fffff000000000000000000000000000000000000000000000000000000000000611b72826118d9565b168252611b8160208201611909565b60070b602083015273ffffffffffffffffffffffffffffffffffffffff611baa60408301610f9c565b1660408301525050565b8060005b6020808210611bc757506111fc565b60ff611bd284610f73565b168552938401939190910190600101611bb8565b8183526000602080850194508260005b858110156112485773ffffffffffffffffffffffffffffffffffffffff611c1c83610f9c565b1687529582019590820190600101611bf6565b600061054060ff8e1683528060208401527fffff000000000000000000000000000000000000000000000000000000000000611c6a8e6118d9565b16818401525060208c01357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18d3603018112611ca557600080fd5b60406105608401528c01611cb881611909565b60070b61058084015260208101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112611cf657600080fd5b0160208101903567ffffffffffffffff811115611d1257600080fd5b803603821315611d2157600080fd5b60406105a0850152611d386105c085018284611aff565b915050611d48604084018d611b48565b611d5560a084018c611bb4565b73ffffffffffffffffffffffffffffffffffffffff8a166104a084015273ffffffffffffffffffffffffffffffffffffffff89166104c08401528281036104e0840152611da381888a611be6565b9050828103610500840152611db9818688611aff565b91505061034661052083018460170b9052565b8183823760009101908152919050565b6020815260006112ac602083018486611aff565b601f821115611e3a57600081815260208120601f850160051c81016020861015611e175750805b601f850160051c820191505b81811015611e3657828155600101611e23565b5050505b505050565b815167ffffffffffffffff811115611e5957611e596115b4565b611e6d81611e678454611ab2565b84611df0565b602080601f831160018114611ec05760008415611e8a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611e36565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611f0d57888601518255948401946001909101908401611eee565b5085821015611f4957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffff00000000000000000000000000000000000000000000000000000000808b60e01b168352808a60e01b166004840152808960e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008760c01b16600c8301528560148301528460348301528360548301528251611feb816074850160208701611164565b919091016074019998505050505050505050565b6020815260006117ba6020830184611188565b60008183825b6020808210612027575061203e565b825160ff1684529283019290910190600101612018565b5050506104008201905092915050565b60008251612060818460208701611164565b919091019291505056fea164736f6c6343000813000a", } var ChainReaderTesterABI = ChainReaderTesterMetaData.ABI @@ -302,9 +314,9 @@ func (_ChainReaderTester *ChainReaderTesterCallerSession) GetSliceValue() ([]uin return _ChainReaderTester.Contract.GetSliceValue(&_ChainReaderTester.CallOpts) } -func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) { var out []interface{} - err := _ChainReaderTester.contract.Call(opts, &out, "returnSeen", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) + err := _ChainReaderTester.contract.Call(opts, &out, "returnSeen", field, differentField, oracleId, oracleIds, account, accountStr, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) if err != nil { return *new(TestStruct), err @@ -316,24 +328,24 @@ func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpt } -func (_ChainReaderTester *ChainReaderTesterSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { - return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) { + return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accountStr, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterCallerSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { - return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterCallerSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) { + return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accountStr, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterTransactor) AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.contract.Transact(opts, "addTestStruct", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactor) AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "addTestStruct", field, differentField, oracleId, oracleIds, account, accountStr, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accountStr, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterTransactorSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accountStr, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } func (_ChainReaderTester *ChainReaderTesterTransactor) SetAlterablePrimitiveValue(opts *bind.TransactOpts, value uint64) (*types.Transaction, error) { @@ -348,16 +360,16 @@ func (_ChainReaderTester *ChainReaderTesterTransactorSession) SetAlterablePrimit return _ChainReaderTester.Contract.SetAlterablePrimitiveValue(&_ChainReaderTester.TransactOpts, value) } -func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEvent(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.contract.Transact(opts, "triggerEvent", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEvent(opts *bind.TransactOpts, field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "triggerEvent", field, oracleId, nestedDynamicStruct, nestedStaticStruct, oracleIds, account, accountStr, accounts, differentField, bigField) } -func (_ChainReaderTester *ChainReaderTesterSession) TriggerEvent(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) TriggerEvent(field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, oracleId, nestedDynamicStruct, nestedStaticStruct, oracleIds, account, accountStr, accounts, differentField, bigField) } -func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEvent(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEvent(field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, oracleId, nestedDynamicStruct, nestedStaticStruct, oracleIds, account, accountStr, accounts, differentField, bigField) } func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEventWithDynamicTopic(opts *bind.TransactOpts, field string) (*types.Transaction, error) { @@ -372,6 +384,18 @@ func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEventWithDy return _ChainReaderTester.Contract.TriggerEventWithDynamicTopic(&_ChainReaderTester.TransactOpts, field) } +func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerStaticBytes(opts *bind.TransactOpts, val1 uint32, val2 uint32, val3 uint32, val4 uint64, val5 [32]byte, val6 [32]byte, val7 [32]byte, raw []byte) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "triggerStaticBytes", val1, val2, val3, val4, val5, val6, val7, raw) +} + +func (_ChainReaderTester *ChainReaderTesterSession) TriggerStaticBytes(val1 uint32, val2 uint32, val3 uint32, val4 uint64, val5 [32]byte, val6 [32]byte, val7 [32]byte, raw []byte) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerStaticBytes(&_ChainReaderTester.TransactOpts, val1, val2, val3, val4, val5, val6, val7, raw) +} + +func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerStaticBytes(val1 uint32, val2 uint32, val3 uint32, val4 uint64, val5 [32]byte, val6 [32]byte, val7 [32]byte, raw []byte) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerStaticBytes(&_ChainReaderTester.TransactOpts, val1, val2, val3, val4, val5, val6, val7, raw) +} + func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerWithFourTopics(opts *bind.TransactOpts, field1 int32, field2 int32, field3 int32) (*types.Transaction, error) { return _ChainReaderTester.contract.Transact(opts, "triggerWithFourTopics", field1, field2, field3) } @@ -396,6 +420,123 @@ func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerWithFourTop return _ChainReaderTester.Contract.TriggerWithFourTopicsWithHashed(&_ChainReaderTester.TransactOpts, field1, field2, field3) } +type ChainReaderTesterStaticBytesIterator struct { + Event *ChainReaderTesterStaticBytes + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ChainReaderTesterStaticBytesIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ChainReaderTesterStaticBytes) + 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(ChainReaderTesterStaticBytes) + 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 *ChainReaderTesterStaticBytesIterator) Error() error { + return it.fail +} + +func (it *ChainReaderTesterStaticBytesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ChainReaderTesterStaticBytes struct { + Message []byte + Raw types.Log +} + +func (_ChainReaderTester *ChainReaderTesterFilterer) FilterStaticBytes(opts *bind.FilterOpts) (*ChainReaderTesterStaticBytesIterator, error) { + + logs, sub, err := _ChainReaderTester.contract.FilterLogs(opts, "StaticBytes") + if err != nil { + return nil, err + } + return &ChainReaderTesterStaticBytesIterator{contract: _ChainReaderTester.contract, event: "StaticBytes", logs: logs, sub: sub}, nil +} + +func (_ChainReaderTester *ChainReaderTesterFilterer) WatchStaticBytes(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterStaticBytes) (event.Subscription, error) { + + logs, sub, err := _ChainReaderTester.contract.WatchLogs(opts, "StaticBytes") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ChainReaderTesterStaticBytes) + if err := _ChainReaderTester.contract.UnpackLog(event, "StaticBytes", 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 (_ChainReaderTester *ChainReaderTesterFilterer) ParseStaticBytes(log types.Log) (*ChainReaderTesterStaticBytes, error) { + event := new(ChainReaderTesterStaticBytes) + if err := _ChainReaderTester.contract.UnpackLog(event, "StaticBytes", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type ChainReaderTesterTriggeredIterator struct { Event *ChainReaderTesterTriggered @@ -457,15 +598,17 @@ func (it *ChainReaderTesterTriggeredIterator) Close() error { } type ChainReaderTesterTriggered struct { - Field int32 - DifferentField string - OracleId uint8 - OracleIds [32]uint8 - Account common.Address - Accounts []common.Address - BigField *big.Int - NestedStruct MidLevelTestStruct - Raw types.Log + Field int32 + OracleId uint8 + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct + OracleIds [32]uint8 + Account common.Address + AccountStr common.Address + Accounts []common.Address + DifferentField string + BigField *big.Int + Raw types.Log } func (_ChainReaderTester *ChainReaderTesterFilterer) FilterTriggered(opts *bind.FilterOpts, field []int32) (*ChainReaderTesterTriggeredIterator, error) { @@ -950,6 +1093,8 @@ func (_ChainReaderTester *ChainReaderTesterFilterer) ParseTriggeredWithFourTopic func (_ChainReaderTester *ChainReaderTester) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { + case _ChainReaderTester.abi.Events["StaticBytes"].ID: + return _ChainReaderTester.ParseStaticBytes(log) case _ChainReaderTester.abi.Events["Triggered"].ID: return _ChainReaderTester.ParseTriggered(log) case _ChainReaderTester.abi.Events["TriggeredEventWithDynamicTopic"].ID: @@ -964,8 +1109,12 @@ func (_ChainReaderTester *ChainReaderTester) ParseLog(log types.Log) (generated. } } +func (ChainReaderTesterStaticBytes) Topic() common.Hash { + return common.HexToHash("0x1e40927ec0bdc7319f09a53452590433ec395dec3b70b982eba779c740685bfe") +} + func (ChainReaderTesterTriggered) Topic() common.Hash { - return common.HexToHash("0x7188419dcd8b51877b71766f075f3626586c0ff190e7d056aa65ce9acb649a3d") + return common.HexToHash("0x855ac250d95b464eea2a7645e23a88fdab21031016175b7dc4d65e8efc72c2ea") } func (ChainReaderTesterTriggeredEventWithDynamicTopic) Topic() common.Hash { @@ -995,20 +1144,28 @@ type ChainReaderTesterInterface interface { GetSliceValue(opts *bind.CallOpts) ([]uint64, error) - ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) + ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) - AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) + AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) SetAlterablePrimitiveValue(opts *bind.TransactOpts, value uint64) (*types.Transaction, error) - TriggerEvent(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) + TriggerEvent(opts *bind.TransactOpts, field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accountStr common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) TriggerEventWithDynamicTopic(opts *bind.TransactOpts, field string) (*types.Transaction, error) + TriggerStaticBytes(opts *bind.TransactOpts, val1 uint32, val2 uint32, val3 uint32, val4 uint64, val5 [32]byte, val6 [32]byte, val7 [32]byte, raw []byte) (*types.Transaction, error) + TriggerWithFourTopics(opts *bind.TransactOpts, field1 int32, field2 int32, field3 int32) (*types.Transaction, error) TriggerWithFourTopicsWithHashed(opts *bind.TransactOpts, field1 string, field2 [32]uint8, field3 [32]byte) (*types.Transaction, error) + FilterStaticBytes(opts *bind.FilterOpts) (*ChainReaderTesterStaticBytesIterator, error) + + WatchStaticBytes(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterStaticBytes) (event.Subscription, error) + + ParseStaticBytes(log types.Log) (*ChainReaderTesterStaticBytes, error) + FilterTriggered(opts *bind.FilterOpts, field []int32) (*ChainReaderTesterTriggeredIterator, error) WatchTriggered(opts *bind.WatchOpts, sink chan<- *ChainReaderTesterTriggered, field []int32) (event.Subscription, error) diff --git a/core/gethwrappers/generated/i_chain_module/i_chain_module.go b/core/gethwrappers/generated/i_chain_module/i_chain_module.go index 23cec8fb9c8..e432d912cc5 100644 --- a/core/gethwrappers/generated/i_chain_module/i_chain_module.go +++ b/core/gethwrappers/generated/i_chain_module/i_chain_module.go @@ -29,7 +29,7 @@ var ( ) var IChainModuleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l1Fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"maxL1Fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", } var IChainModuleABI = IChainModuleMetaData.ABI @@ -150,9 +150,9 @@ func (_IChainModule *IChainModuleTransactorRaw) Transact(opts *bind.TransactOpts return _IChainModule.Contract.contract.Transact(opts, method, params...) } -func (_IChainModule *IChainModuleCaller) BlockHash(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { +func (_IChainModule *IChainModuleCaller) BlockHash(opts *bind.CallOpts, blockNumber *big.Int) ([32]byte, error) { var out []interface{} - err := _IChainModule.contract.Call(opts, &out, "blockHash", arg0) + err := _IChainModule.contract.Call(opts, &out, "blockHash", blockNumber) if err != nil { return *new([32]byte), err @@ -164,12 +164,12 @@ func (_IChainModule *IChainModuleCaller) BlockHash(opts *bind.CallOpts, arg0 *bi } -func (_IChainModule *IChainModuleSession) BlockHash(arg0 *big.Int) ([32]byte, error) { - return _IChainModule.Contract.BlockHash(&_IChainModule.CallOpts, arg0) +func (_IChainModule *IChainModuleSession) BlockHash(blockNumber *big.Int) ([32]byte, error) { + return _IChainModule.Contract.BlockHash(&_IChainModule.CallOpts, blockNumber) } -func (_IChainModule *IChainModuleCallerSession) BlockHash(arg0 *big.Int) ([32]byte, error) { - return _IChainModule.Contract.BlockHash(&_IChainModule.CallOpts, arg0) +func (_IChainModule *IChainModuleCallerSession) BlockHash(blockNumber *big.Int) ([32]byte, error) { + return _IChainModule.Contract.BlockHash(&_IChainModule.CallOpts, blockNumber) } func (_IChainModule *IChainModuleCaller) BlockNumber(opts *bind.CallOpts) (*big.Int, error) { @@ -194,9 +194,9 @@ func (_IChainModule *IChainModuleCallerSession) BlockNumber() (*big.Int, error) return _IChainModule.Contract.BlockNumber(&_IChainModule.CallOpts) } -func (_IChainModule *IChainModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) { +func (_IChainModule *IChainModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) { var out []interface{} - err := _IChainModule.contract.Call(opts, &out, "getCurrentL1Fee") + err := _IChainModule.contract.Call(opts, &out, "getCurrentL1Fee", dataSize) if err != nil { return *new(*big.Int), err @@ -208,12 +208,12 @@ func (_IChainModule *IChainModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts) (* } -func (_IChainModule *IChainModuleSession) GetCurrentL1Fee() (*big.Int, error) { - return _IChainModule.Contract.GetCurrentL1Fee(&_IChainModule.CallOpts) +func (_IChainModule *IChainModuleSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _IChainModule.Contract.GetCurrentL1Fee(&_IChainModule.CallOpts, dataSize) } -func (_IChainModule *IChainModuleCallerSession) GetCurrentL1Fee() (*big.Int, error) { - return _IChainModule.Contract.GetCurrentL1Fee(&_IChainModule.CallOpts) +func (_IChainModule *IChainModuleCallerSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _IChainModule.Contract.GetCurrentL1Fee(&_IChainModule.CallOpts, dataSize) } func (_IChainModule *IChainModuleCaller) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, @@ -278,11 +278,11 @@ func (_IChainModule *IChainModule) Address() common.Address { } type IChainModuleInterface interface { - BlockHash(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) + BlockHash(opts *bind.CallOpts, blockNumber *big.Int) ([32]byte, error) BlockNumber(opts *bind.CallOpts) (*big.Int, error) - GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) + GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, diff --git a/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go b/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go index 51b7b753cc7..e8685bc9f60 100644 --- a/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go +++ b/core/gethwrappers/generated/log_upkeep_counter_wrapper/log_upkeep_counter_wrapper.go @@ -42,8 +42,8 @@ type Log struct { } var LogUpkeepCounterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_testRange\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Trigger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"Trigger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"name\":\"Trigger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"}],\"name\":\"Trigger\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eligible\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_testRange\",\"type\":\"uint256\"}],\"name\":\"setSpread\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"testRange\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60806040527f3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d6000557f57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da6001557f1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c86002557f5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e716003553480156100a057600080fd5b50604051610f41380380610f418339810160408190526100bf916100da565b600455600060068190554360055560078190556008556100f3565b6000602082840312156100ec57600080fd5b5051919050565b610e3f806101026000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063806b984f11610076578063b66a261c1161005b578063b66a261c14610139578063be9a655514610156578063d832d92f1461015e57600080fd5b8063806b984f14610127578063917d895f1461013057600080fd5b80634585e33b116100a75780634585e33b1461010057806361bc221a146101155780636250a13a1461011e57600080fd5b80632cb15864146100c357806340691db4146100df575b600080fd5b6100cc60075481565b6040519081526020015b60405180910390f35b6100f26100ed366004610889565b610176565b6040516100d6929190610a7c565b61011361010e366004610817565b610365565b005b6100cc60085481565b6100cc60045481565b6100cc60055481565b6100cc60065481565b6101136101473660046109cb565b60045560006007819055600855565b6101136105d7565b6101666106b1565b60405190151581526020016100d6565b600060606101826106b1565b6101ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6e6f7420656c696769626c65000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6000546101fd60c0860186610bca565b600081811061020e5761020e610dd4565b905060200201351480610246575060015461022c60c0860186610bca565b600081811061023d5761023d610dd4565b90506020020135145b80610276575060025461025c60c0860186610bca565b600081811061026d5761026d610dd4565b90506020020135145b806102a6575060035461028c60c0860186610bca565b600081811061029d5761029d610dd4565b90506020020135145b156102d6576001846040516020016102be9190610af9565b6040516020818303038152906040529150915061035e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f636f756c64206e6f742066696e64206d61746368696e67206576656e7420736960448201527f670000000000000000000000000000000000000000000000000000000000000060648201526084016101e4565b9250929050565b60075461037157436007555b43600555600854610383906001610d76565b600855600554600655600061039a828401846108f6565b90506000548160c001516000815181106103b6576103b6610dd4565b602002602001015114156103f2576040517f3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d90600090a161057f565b6001548160c0015160008151811061040c5761040c610dd4565b6020026020010151141561045457604051600181527f57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da906020015b60405180910390a161057f565b6002548160c0015160008151811061046e5761046e610dd4565b602002602001015114156104b3576040805160018152600260208201527f1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c89101610447565b6003548160c001516000815181106104cd576104cd610dd4565b6020026020010151141561051d576040805160018152600260208201526003918101919091527f5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e7190606001610447565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f636f756c64206e6f742066696e64206d61746368696e6720736967000000000060448201526064016101e4565b60075460055460065460085460408051948552602085019390935291830152606082015232907f8e8112f20a2134e18e591d2cdd68cd86a95d06e6328ede501fc6314f4a5075fa9060800160405180910390a2505050565b6040517f3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d90600090a1604051600181527f57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da9060200160405180910390a16040805160018152600260208201527f1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8910160405180910390a160408051600181526002602082015260038183015290517f5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e719181900360600190a1565b6000600754600014156106c45750600190565b6004546007546106d49043610d8e565b10905090565b803573ffffffffffffffffffffffffffffffffffffffff811681146106fe57600080fd5b919050565b600082601f83011261071457600080fd5b8135602067ffffffffffffffff82111561073057610730610e03565b8160051b61073f828201610c5c565b83815282810190868401838801850189101561075a57600080fd5b600093505b8584101561077d57803583526001939093019291840191840161075f565b50979650505050505050565b600082601f83011261079a57600080fd5b813567ffffffffffffffff8111156107b4576107b4610e03565b6107e560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c5c565b8181528460208386010111156107fa57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806020838503121561082a57600080fd5b823567ffffffffffffffff8082111561084257600080fd5b818501915085601f83011261085657600080fd5b81358181111561086557600080fd5b86602082850101111561087757600080fd5b60209290920196919550909350505050565b6000806040838503121561089c57600080fd5b823567ffffffffffffffff808211156108b457600080fd5b9084019061010082870312156108c957600080fd5b909250602084013590808211156108df57600080fd5b506108ec85828601610789565b9150509250929050565b60006020828403121561090857600080fd5b813567ffffffffffffffff8082111561092057600080fd5b90830190610100828603121561093557600080fd5b61093d610c32565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015261097560a084016106da565b60a082015260c08301358281111561098c57600080fd5b61099887828601610703565b60c08301525060e0830135828111156109b057600080fd5b6109bc87828601610789565b60e08301525095945050505050565b6000602082840312156109dd57600080fd5b5035919050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115610a1657600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b821515815260006020604081840152835180604085015260005b81811015610ab257858101830151858201606001528201610a96565b81811115610ac4576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152608082013560a082015273ffffffffffffffffffffffffffffffffffffffff610b4d60a084016106da565b1660c08201526000610b6260c0840184610cab565b6101008060e0860152610b7a610120860183856109e4565b9250610b8960e0870187610d12565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08685030182870152610bbf848483610a33565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610bff57600080fd5b83018035915067ffffffffffffffff821115610c1a57600080fd5b6020019150600581901b360382131561035e57600080fd5b604051610100810167ffffffffffffffff81118282101715610c5657610c56610e03565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610ca357610ca3610e03565b604052919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610ce057600080fd5b830160208101925035905067ffffffffffffffff811115610d0057600080fd5b8060051b360383131561035e57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610d4757600080fd5b830160208101925035905067ffffffffffffffff811115610d6757600080fd5b80360383131561035e57600080fd5b60008219821115610d8957610d89610da5565b500190565b600082821015610da057610da0610da5565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_testRange\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Trigger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"Trigger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"name\":\"Trigger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"}],\"name\":\"Trigger\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"autoExecution\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eligible\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_auto\",\"type\":\"bool\"}],\"name\":\"setAuto\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_testRange\",\"type\":\"uint256\"}],\"name\":\"setSpread\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"start\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"testRange\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60806040527f3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d6000557f57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da6001557f1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c86002557f5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e716003553480156100a057600080fd5b50604051610fe5380380610fe58339810160408190526100bf916100e7565b600455600060068190554360055560078190556008556009805460ff19166001179055610100565b6000602082840312156100f957600080fd5b5051919050565b610ed68061010f6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063806b984f11610081578063be9a65551161005b578063be9a655514610189578063cf129c7f14610191578063d832d92f146101d057600080fd5b8063806b984f1461015a578063917d895f14610163578063b66a261c1461016c57600080fd5b806353bebdf3116100b257806353bebdf31461012b57806361bc221a146101485780636250a13a1461015157600080fd5b80632cb15864146100d957806340691db4146100f55780634585e33b14610116575b600080fd5b6100e260075481565b6040519081526020015b60405180910390f35b610108610103366004610920565b6101d8565b6040516100ec929190610b13565b6101296101243660046108ae565b6103c7565b005b6009546101389060ff1681565b60405190151581526020016100ec565b6100e260085481565b6100e260045481565b6100e260055481565b6100e260065481565b61012961017a366004610a62565b60045560006007819055600855565b610129610645565b61012961019f366004610885565b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b61013861071f565b600060606101e461071f565b61024f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6e6f7420656c696769626c65000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60005461025f60c0860186610c61565b600081811061027057610270610e6b565b9050602002013514806102a8575060015461028e60c0860186610c61565b600081811061029f5761029f610e6b565b90506020020135145b806102d857506002546102be60c0860186610c61565b60008181106102cf576102cf610e6b565b90506020020135145b8061030857506003546102ee60c0860186610c61565b60008181106102ff576102ff610e6b565b90506020020135145b15610338576001846040516020016103209190610b90565b604051602081830303815290604052915091506103c0565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f636f756c64206e6f742066696e64206d61746368696e67206576656e7420736960448201527f67000000000000000000000000000000000000000000000000000000000000006064820152608401610246565b9250929050565b6007546103d357436007555b436005556008546103e5906001610e0d565b60085560055460065560006103fc8284018461098d565b60095490915060ff16156105ed576000548160c0015160008151811061042457610424610e6b565b60200260200101511415610460576040517f3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d90600090a16105ed565b6001548160c0015160008151811061047a5761047a610e6b565b602002602001015114156104c257604051600181527f57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da906020015b60405180910390a16105ed565b6002548160c001516000815181106104dc576104dc610e6b565b60200260200101511415610521576040805160018152600260208201527f1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c891016104b5565b6003548160c0015160008151811061053b5761053b610e6b565b6020026020010151141561058b576040805160018152600260208201526003918101919091527f5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71906060016104b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f636f756c64206e6f742066696e64206d61746368696e672073696700000000006044820152606401610246565b60075460055460065460085460408051948552602085019390935291830152606082015232907f8e8112f20a2134e18e591d2cdd68cd86a95d06e6328ede501fc6314f4a5075fa9060800160405180910390a2505050565b6040517f3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d90600090a1604051600181527f57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da9060200160405180910390a16040805160018152600260208201527f1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8910160405180910390a160408051600181526002602082015260038183015290517f5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e719181900360600190a1565b6000600754600014156107325750600190565b6004546007546107429043610e25565b10905090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461076c57600080fd5b919050565b600082601f83011261078257600080fd5b8135602067ffffffffffffffff82111561079e5761079e610e9a565b8160051b6107ad828201610cf3565b8381528281019086840183880185018910156107c857600080fd5b600093505b858410156107eb5780358352600193909301929184019184016107cd565b50979650505050505050565b600082601f83011261080857600080fd5b813567ffffffffffffffff81111561082257610822610e9a565b61085360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610cf3565b81815284602083860101111561086857600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561089757600080fd5b813580151581146108a757600080fd5b9392505050565b600080602083850312156108c157600080fd5b823567ffffffffffffffff808211156108d957600080fd5b818501915085601f8301126108ed57600080fd5b8135818111156108fc57600080fd5b86602082850101111561090e57600080fd5b60209290920196919550909350505050565b6000806040838503121561093357600080fd5b823567ffffffffffffffff8082111561094b57600080fd5b90840190610100828703121561096057600080fd5b9092506020840135908082111561097657600080fd5b50610983858286016107f7565b9150509250929050565b60006020828403121561099f57600080fd5b813567ffffffffffffffff808211156109b757600080fd5b9083019061010082860312156109cc57600080fd5b6109d4610cc9565b8235815260208301356020820152604083013560408201526060830135606082015260808301356080820152610a0c60a08401610748565b60a082015260c083013582811115610a2357600080fd5b610a2f87828601610771565b60c08301525060e083013582811115610a4757600080fd5b610a53878286016107f7565b60e08301525095945050505050565b600060208284031215610a7457600080fd5b5035919050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115610aad57600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b821515815260006020604081840152835180604085015260005b81811015610b4957858101830151858201606001528201610b2d565b81811115610b5b576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152608082013560a082015273ffffffffffffffffffffffffffffffffffffffff610be460a08401610748565b1660c08201526000610bf960c0840184610d42565b6101008060e0860152610c1161012086018385610a7b565b9250610c2060e0870187610da9565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08685030182870152610c56848483610aca565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610c9657600080fd5b83018035915067ffffffffffffffff821115610cb157600080fd5b6020019150600581901b36038213156103c057600080fd5b604051610100810167ffffffffffffffff81118282101715610ced57610ced610e9a565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610d3a57610d3a610e9a565b604052919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610d7757600080fd5b830160208101925035905067ffffffffffffffff811115610d9757600080fd5b8060051b36038313156103c057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610dde57600080fd5b830160208101925035905067ffffffffffffffff811115610dfe57600080fd5b8036038313156103c057600080fd5b60008219821115610e2057610e20610e3c565b500190565b600082821015610e3757610e37610e3c565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a", } var LogUpkeepCounterABI = LogUpkeepCounterMetaData.ABI @@ -182,6 +182,28 @@ func (_LogUpkeepCounter *LogUpkeepCounterTransactorRaw) Transact(opts *bind.Tran return _LogUpkeepCounter.Contract.contract.Transact(opts, method, params...) } +func (_LogUpkeepCounter *LogUpkeepCounterCaller) AutoExecution(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _LogUpkeepCounter.contract.Call(opts, &out, "autoExecution") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_LogUpkeepCounter *LogUpkeepCounterSession) AutoExecution() (bool, error) { + return _LogUpkeepCounter.Contract.AutoExecution(&_LogUpkeepCounter.CallOpts) +} + +func (_LogUpkeepCounter *LogUpkeepCounterCallerSession) AutoExecution() (bool, error) { + return _LogUpkeepCounter.Contract.AutoExecution(&_LogUpkeepCounter.CallOpts) +} + func (_LogUpkeepCounter *LogUpkeepCounterCaller) CheckLog(opts *bind.CallOpts, log Log, arg1 []byte) (bool, []byte, error) { var out []interface{} err := _LogUpkeepCounter.contract.Call(opts, &out, "checkLog", log, arg1) @@ -349,6 +371,18 @@ func (_LogUpkeepCounter *LogUpkeepCounterTransactorSession) PerformUpkeep(perfor return _LogUpkeepCounter.Contract.PerformUpkeep(&_LogUpkeepCounter.TransactOpts, performData) } +func (_LogUpkeepCounter *LogUpkeepCounterTransactor) SetAuto(opts *bind.TransactOpts, _auto bool) (*types.Transaction, error) { + return _LogUpkeepCounter.contract.Transact(opts, "setAuto", _auto) +} + +func (_LogUpkeepCounter *LogUpkeepCounterSession) SetAuto(_auto bool) (*types.Transaction, error) { + return _LogUpkeepCounter.Contract.SetAuto(&_LogUpkeepCounter.TransactOpts, _auto) +} + +func (_LogUpkeepCounter *LogUpkeepCounterTransactorSession) SetAuto(_auto bool) (*types.Transaction, error) { + return _LogUpkeepCounter.Contract.SetAuto(&_LogUpkeepCounter.TransactOpts, _auto) +} + func (_LogUpkeepCounter *LogUpkeepCounterTransactor) SetSpread(opts *bind.TransactOpts, _testRange *big.Int) (*types.Transaction, error) { return _LogUpkeepCounter.contract.Transact(opts, "setSpread", _testRange) } @@ -1017,6 +1051,8 @@ func (_LogUpkeepCounter *LogUpkeepCounter) Address() common.Address { } type LogUpkeepCounterInterface interface { + AutoExecution(opts *bind.CallOpts) (bool, error) + CheckLog(opts *bind.CallOpts, log Log, arg1 []byte) (bool, []byte, error) Counter(opts *bind.CallOpts) (*big.Int, error) @@ -1033,6 +1069,8 @@ type LogUpkeepCounterInterface interface { PerformUpkeep(opts *bind.TransactOpts, performData []byte) (*types.Transaction, error) + SetAuto(opts *bind.TransactOpts, _auto bool) (*types.Transaction, error) + SetSpread(opts *bind.TransactOpts, _testRange *big.Int) (*types.Transaction, error) Start(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/generated/optimism_module/optimism_module.go b/core/gethwrappers/generated/optimism_module/optimism_module.go index 009ab6d8cff..89b6a758fcf 100644 --- a/core/gethwrappers/generated/optimism_module/optimism_module.go +++ b/core/gethwrappers/generated/optimism_module/optimism_module.go @@ -29,8 +29,8 @@ var ( ) var OptimismModuleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506104d1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806357e871e71161005057806357e871e71461009a57806385df51fd146100a0578063de9ee35e146100b357600080fd5b8063125441401461006c57806318b8f61314610092575b600080fd5b61007f61007a3660046102e9565b6100ca565b6040519081526020015b60405180910390f35b61007f6101eb565b4361007f565b61007f6100ae3660046102e9565b6102bc565b6040805161ea60815261010e602082015201610089565b6000806100d8836004610331565b67ffffffffffffffff8111156100f0576100f061034e565b6040519080825280601f01601f19166020018201604052801561011a576020820181803683370190505b50905073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e82604051806080016040528060508152602001610475605091396040516020016101789291906103a1565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016101a391906103d0565b602060405180830381865afa1580156101c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e49190610421565b9392505050565b600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e6000366040518060800160405280605081526020016104756050913960405160200161024b9392919061043a565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161027691906103d0565b602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610421565b905090565b600043821015806102d757506101006102d58343610461565b115b156102e457506000919050565b504090565b6000602082840312156102fb57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761034857610348610302565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811015610398578181015183820152602001610380565b50506000910152565b600083516103b381846020880161037d565b8351908301906103c781836020880161037d565b01949350505050565b60208152600082518060208401526103ef81604085016020870161037d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561043357600080fd5b5051919050565b82848237600083820160008152835161045781836020880161037d565b0195945050505050565b818103818111156103485761034861030256feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506103dc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637810d12a116100505780637810d12a1461006c57806385df51fd14610098578063de9ee35e146100ab57600080fd5b8063125441401461006c57806357e871e714610092575b600080fd5b61007f61007a366004610221565b6100c2565b6040519081526020015b60405180910390f35b4361007f565b61007f6100a6366004610221565b6100d3565b6040805161ea60815261010e602082015201610089565b60006100cd82610100565b92915050565b600043821015806100ee57506101006100ec8343610269565b115b156100fb57506000919050565b504090565b60008061010e83600461027c565b67ffffffffffffffff81111561012657610126610293565b6040519080825280601f01601f191660200182016040528015610150576020820181803683370190505b50905073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff166349948e0e82604051806080016040528060508152602001610380605091396040516020016101ae9291906102e6565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016101d99190610315565b602060405180830381865afa1580156101f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061021a9190610366565b9392505050565b60006020828403121561023357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156100cd576100cd61023a565b80820281158282048414176100cd576100cd61023a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156102dd5781810151838201526020016102c5565b50506000910152565b600083516102f88184602088016102c2565b83519083019061030c8183602088016102c2565b01949350505050565b60208152600082518060208401526103348160408501602087016102c2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561037857600080fd5b505191905056feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa164736f6c6343000813000a", } var OptimismModuleABI = OptimismModuleMetaData.ABI @@ -213,9 +213,9 @@ func (_OptimismModule *OptimismModuleCallerSession) BlockNumber() (*big.Int, err return _OptimismModule.Contract.BlockNumber(&_OptimismModule.CallOpts) } -func (_OptimismModule *OptimismModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) { +func (_OptimismModule *OptimismModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) { var out []interface{} - err := _OptimismModule.contract.Call(opts, &out, "getCurrentL1Fee") + err := _OptimismModule.contract.Call(opts, &out, "getCurrentL1Fee", dataSize) if err != nil { return *new(*big.Int), err @@ -227,12 +227,12 @@ func (_OptimismModule *OptimismModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts } -func (_OptimismModule *OptimismModuleSession) GetCurrentL1Fee() (*big.Int, error) { - return _OptimismModule.Contract.GetCurrentL1Fee(&_OptimismModule.CallOpts) +func (_OptimismModule *OptimismModuleSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _OptimismModule.Contract.GetCurrentL1Fee(&_OptimismModule.CallOpts, dataSize) } -func (_OptimismModule *OptimismModuleCallerSession) GetCurrentL1Fee() (*big.Int, error) { - return _OptimismModule.Contract.GetCurrentL1Fee(&_OptimismModule.CallOpts) +func (_OptimismModule *OptimismModuleCallerSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _OptimismModule.Contract.GetCurrentL1Fee(&_OptimismModule.CallOpts, dataSize) } func (_OptimismModule *OptimismModuleCaller) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, @@ -301,7 +301,7 @@ type OptimismModuleInterface interface { BlockNumber(opts *bind.CallOpts) (*big.Int, error) - GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) + GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, diff --git a/core/gethwrappers/generated/optimism_module_v2/optimism_module_v2.go b/core/gethwrappers/generated/optimism_module_v2/optimism_module_v2.go new file mode 100644 index 00000000000..abad079caa3 --- /dev/null +++ b/core/gethwrappers/generated/optimism_module_v2/optimism_module_v2.go @@ -0,0 +1,840 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package optimism_module_v2 + +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 OptimismModuleV2MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"coefficient\",\"type\":\"uint8\"}],\"name\":\"InvalidL1FeeCoefficient\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"coefficient\",\"type\":\"uint8\"}],\"name\":\"L1FeeCoefficientSet\",\"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\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getL1FeeCoefficient\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"coefficient\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"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\":\"uint8\",\"name\":\"coefficient\",\"type\":\"uint8\"}],\"name\":\"setL1FeeCalculation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040526001805460ff60a01b1916601960a21b17905534801561002357600080fd5b50338060008161007a5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156100aa576100aa816100b2565b50505061015b565b336001600160a01b0382160361010a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610071565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61073f8061016a6000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80638da5cb5b11610076578063de9ee35e1161005b578063de9ee35e1461016a578063f22559a014610180578063f2fde38b1461019357600080fd5b80638da5cb5b1461011f578063d10a944e1461014757600080fd5b80637810d12a116100a75780637810d12a146100ef57806379ba50971461010257806385df51fd1461010c57600080fd5b806312544140146100c357806357e871e7146100e9575b600080fd5b6100d66100d136600461060c565b6101a6565b6040519081526020015b60405180910390f35b436100d6565b6100d66100fd36600461060c565b6101b7565b61010a6101f6565b005b6100d661011a36600461060c565b6102f8565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b60015474010000000000000000000000000000000000000000900460ff166100d6565b60408051616d60815260006020820152016100e0565b61010a61018e366004610625565b610325565b61010a6101a136600461064f565b6103f0565b60006101b182610404565b92915050565b600060646101c483610404565b6001546101ec919074010000000000000000000000000000000000000000900460ff166106b4565b6101b191906106cb565b60015473ffffffffffffffffffffffffffffffffffffffff16331461027c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000438210158061031357506101006103118343610706565b115b1561032057506000919050565b504090565b61032d610494565b60648160ff161115610370576040517f1a8a06a000000000000000000000000000000000000000000000000000000000815260ff82166004820152602401610273565b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f29ec9e31de0d3fe0208a7ccb792bbc26a854f123146110daa3a77219cb74a5549060200160405180910390a150565b6103f8610494565b61040181610517565b50565b6040517ff1c7a58b0000000000000000000000000000000000000000000000000000000081526004810182905260009073420000000000000000000000000000000000000f9063f1c7a58b90602401602060405180830381865afa158015610470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b19190610719565b60005473ffffffffffffffffffffffffffffffffffffffff163314610515576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610273565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610273565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020828403121561061e57600080fd5b5035919050565b60006020828403121561063757600080fd5b813560ff8116811461064857600080fd5b9392505050565b60006020828403121561066157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461064857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176101b1576101b1610685565b600082610701577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156101b1576101b1610685565b60006020828403121561072b57600080fd5b505191905056fea164736f6c6343000813000a", +} + +var OptimismModuleV2ABI = OptimismModuleV2MetaData.ABI + +var OptimismModuleV2Bin = OptimismModuleV2MetaData.Bin + +func DeployOptimismModuleV2(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *OptimismModuleV2, error) { + parsed, err := OptimismModuleV2MetaData.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(OptimismModuleV2Bin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OptimismModuleV2{address: address, abi: *parsed, OptimismModuleV2Caller: OptimismModuleV2Caller{contract: contract}, OptimismModuleV2Transactor: OptimismModuleV2Transactor{contract: contract}, OptimismModuleV2Filterer: OptimismModuleV2Filterer{contract: contract}}, nil +} + +type OptimismModuleV2 struct { + address common.Address + abi abi.ABI + OptimismModuleV2Caller + OptimismModuleV2Transactor + OptimismModuleV2Filterer +} + +type OptimismModuleV2Caller struct { + contract *bind.BoundContract +} + +type OptimismModuleV2Transactor struct { + contract *bind.BoundContract +} + +type OptimismModuleV2Filterer struct { + contract *bind.BoundContract +} + +type OptimismModuleV2Session struct { + Contract *OptimismModuleV2 + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OptimismModuleV2CallerSession struct { + Contract *OptimismModuleV2Caller + CallOpts bind.CallOpts +} + +type OptimismModuleV2TransactorSession struct { + Contract *OptimismModuleV2Transactor + TransactOpts bind.TransactOpts +} + +type OptimismModuleV2Raw struct { + Contract *OptimismModuleV2 +} + +type OptimismModuleV2CallerRaw struct { + Contract *OptimismModuleV2Caller +} + +type OptimismModuleV2TransactorRaw struct { + Contract *OptimismModuleV2Transactor +} + +func NewOptimismModuleV2(address common.Address, backend bind.ContractBackend) (*OptimismModuleV2, error) { + abi, err := abi.JSON(strings.NewReader(OptimismModuleV2ABI)) + if err != nil { + return nil, err + } + contract, err := bindOptimismModuleV2(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OptimismModuleV2{address: address, abi: abi, OptimismModuleV2Caller: OptimismModuleV2Caller{contract: contract}, OptimismModuleV2Transactor: OptimismModuleV2Transactor{contract: contract}, OptimismModuleV2Filterer: OptimismModuleV2Filterer{contract: contract}}, nil +} + +func NewOptimismModuleV2Caller(address common.Address, caller bind.ContractCaller) (*OptimismModuleV2Caller, error) { + contract, err := bindOptimismModuleV2(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OptimismModuleV2Caller{contract: contract}, nil +} + +func NewOptimismModuleV2Transactor(address common.Address, transactor bind.ContractTransactor) (*OptimismModuleV2Transactor, error) { + contract, err := bindOptimismModuleV2(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OptimismModuleV2Transactor{contract: contract}, nil +} + +func NewOptimismModuleV2Filterer(address common.Address, filterer bind.ContractFilterer) (*OptimismModuleV2Filterer, error) { + contract, err := bindOptimismModuleV2(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OptimismModuleV2Filterer{contract: contract}, nil +} + +func bindOptimismModuleV2(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OptimismModuleV2MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_OptimismModuleV2 *OptimismModuleV2Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismModuleV2.Contract.OptimismModuleV2Caller.contract.Call(opts, result, method, params...) +} + +func (_OptimismModuleV2 *OptimismModuleV2Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.OptimismModuleV2Transactor.contract.Transfer(opts) +} + +func (_OptimismModuleV2 *OptimismModuleV2Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.OptimismModuleV2Transactor.contract.Transact(opts, method, params...) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismModuleV2.Contract.contract.Call(opts, result, method, params...) +} + +func (_OptimismModuleV2 *OptimismModuleV2TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.contract.Transfer(opts) +} + +func (_OptimismModuleV2 *OptimismModuleV2TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.contract.Transact(opts, method, params...) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) BlockHash(opts *bind.CallOpts, n *big.Int) ([32]byte, error) { + var out []interface{} + err := _OptimismModuleV2.contract.Call(opts, &out, "blockHash", n) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) BlockHash(n *big.Int) ([32]byte, error) { + return _OptimismModuleV2.Contract.BlockHash(&_OptimismModuleV2.CallOpts, n) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) BlockHash(n *big.Int) ([32]byte, error) { + return _OptimismModuleV2.Contract.BlockHash(&_OptimismModuleV2.CallOpts, n) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) BlockNumber(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _OptimismModuleV2.contract.Call(opts, &out, "blockNumber") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) BlockNumber() (*big.Int, error) { + return _OptimismModuleV2.Contract.BlockNumber(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) BlockNumber() (*big.Int, error) { + return _OptimismModuleV2.Contract.BlockNumber(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _OptimismModuleV2.contract.Call(opts, &out, "getCurrentL1Fee", dataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _OptimismModuleV2.Contract.GetCurrentL1Fee(&_OptimismModuleV2.CallOpts, dataSize) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _OptimismModuleV2.Contract.GetCurrentL1Fee(&_OptimismModuleV2.CallOpts, dataSize) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, + + error) { + var out []interface{} + err := _OptimismModuleV2.contract.Call(opts, &out, "getGasOverhead") + + outstruct := new(GetGasOverhead) + if err != nil { + return *outstruct, err + } + + outstruct.ChainModuleFixedOverhead = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.ChainModulePerByteOverhead = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) GetGasOverhead() (GetGasOverhead, + + error) { + return _OptimismModuleV2.Contract.GetGasOverhead(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) GetGasOverhead() (GetGasOverhead, + + error) { + return _OptimismModuleV2.Contract.GetGasOverhead(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) GetL1FeeCoefficient(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _OptimismModuleV2.contract.Call(opts, &out, "getL1FeeCoefficient") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) GetL1FeeCoefficient() (*big.Int, error) { + return _OptimismModuleV2.Contract.GetL1FeeCoefficient(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) GetL1FeeCoefficient() (*big.Int, error) { + return _OptimismModuleV2.Contract.GetL1FeeCoefficient(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) GetMaxL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _OptimismModuleV2.contract.Call(opts, &out, "getMaxL1Fee", dataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) GetMaxL1Fee(dataSize *big.Int) (*big.Int, error) { + return _OptimismModuleV2.Contract.GetMaxL1Fee(&_OptimismModuleV2.CallOpts, dataSize) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) GetMaxL1Fee(dataSize *big.Int) (*big.Int, error) { + return _OptimismModuleV2.Contract.GetMaxL1Fee(&_OptimismModuleV2.CallOpts, dataSize) +} + +func (_OptimismModuleV2 *OptimismModuleV2Caller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismModuleV2.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 (_OptimismModuleV2 *OptimismModuleV2Session) Owner() (common.Address, error) { + return _OptimismModuleV2.Contract.Owner(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2CallerSession) Owner() (common.Address, error) { + return _OptimismModuleV2.Contract.Owner(&_OptimismModuleV2.CallOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2Transactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismModuleV2.contract.Transact(opts, "acceptOwnership") +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) AcceptOwnership() (*types.Transaction, error) { + return _OptimismModuleV2.Contract.AcceptOwnership(&_OptimismModuleV2.TransactOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2TransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _OptimismModuleV2.Contract.AcceptOwnership(&_OptimismModuleV2.TransactOpts) +} + +func (_OptimismModuleV2 *OptimismModuleV2Transactor) SetL1FeeCalculation(opts *bind.TransactOpts, coefficient uint8) (*types.Transaction, error) { + return _OptimismModuleV2.contract.Transact(opts, "setL1FeeCalculation", coefficient) +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) SetL1FeeCalculation(coefficient uint8) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.SetL1FeeCalculation(&_OptimismModuleV2.TransactOpts, coefficient) +} + +func (_OptimismModuleV2 *OptimismModuleV2TransactorSession) SetL1FeeCalculation(coefficient uint8) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.SetL1FeeCalculation(&_OptimismModuleV2.TransactOpts, coefficient) +} + +func (_OptimismModuleV2 *OptimismModuleV2Transactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _OptimismModuleV2.contract.Transact(opts, "transferOwnership", to) +} + +func (_OptimismModuleV2 *OptimismModuleV2Session) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.TransferOwnership(&_OptimismModuleV2.TransactOpts, to) +} + +func (_OptimismModuleV2 *OptimismModuleV2TransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _OptimismModuleV2.Contract.TransferOwnership(&_OptimismModuleV2.TransactOpts, to) +} + +type OptimismModuleV2L1FeeCoefficientSetIterator struct { + Event *OptimismModuleV2L1FeeCoefficientSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OptimismModuleV2L1FeeCoefficientSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OptimismModuleV2L1FeeCoefficientSet) + 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(OptimismModuleV2L1FeeCoefficientSet) + 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 *OptimismModuleV2L1FeeCoefficientSetIterator) Error() error { + return it.fail +} + +func (it *OptimismModuleV2L1FeeCoefficientSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OptimismModuleV2L1FeeCoefficientSet struct { + Coefficient uint8 + Raw types.Log +} + +func (_OptimismModuleV2 *OptimismModuleV2Filterer) FilterL1FeeCoefficientSet(opts *bind.FilterOpts) (*OptimismModuleV2L1FeeCoefficientSetIterator, error) { + + logs, sub, err := _OptimismModuleV2.contract.FilterLogs(opts, "L1FeeCoefficientSet") + if err != nil { + return nil, err + } + return &OptimismModuleV2L1FeeCoefficientSetIterator{contract: _OptimismModuleV2.contract, event: "L1FeeCoefficientSet", logs: logs, sub: sub}, nil +} + +func (_OptimismModuleV2 *OptimismModuleV2Filterer) WatchL1FeeCoefficientSet(opts *bind.WatchOpts, sink chan<- *OptimismModuleV2L1FeeCoefficientSet) (event.Subscription, error) { + + logs, sub, err := _OptimismModuleV2.contract.WatchLogs(opts, "L1FeeCoefficientSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OptimismModuleV2L1FeeCoefficientSet) + if err := _OptimismModuleV2.contract.UnpackLog(event, "L1FeeCoefficientSet", 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 (_OptimismModuleV2 *OptimismModuleV2Filterer) ParseL1FeeCoefficientSet(log types.Log) (*OptimismModuleV2L1FeeCoefficientSet, error) { + event := new(OptimismModuleV2L1FeeCoefficientSet) + if err := _OptimismModuleV2.contract.UnpackLog(event, "L1FeeCoefficientSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OptimismModuleV2OwnershipTransferRequestedIterator struct { + Event *OptimismModuleV2OwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OptimismModuleV2OwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OptimismModuleV2OwnershipTransferRequested) + 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(OptimismModuleV2OwnershipTransferRequested) + 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 *OptimismModuleV2OwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *OptimismModuleV2OwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OptimismModuleV2OwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OptimismModuleV2 *OptimismModuleV2Filterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismModuleV2OwnershipTransferRequestedIterator, 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 := _OptimismModuleV2.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &OptimismModuleV2OwnershipTransferRequestedIterator{contract: _OptimismModuleV2.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_OptimismModuleV2 *OptimismModuleV2Filterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OptimismModuleV2OwnershipTransferRequested, 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 := _OptimismModuleV2.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(OptimismModuleV2OwnershipTransferRequested) + if err := _OptimismModuleV2.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 (_OptimismModuleV2 *OptimismModuleV2Filterer) ParseOwnershipTransferRequested(log types.Log) (*OptimismModuleV2OwnershipTransferRequested, error) { + event := new(OptimismModuleV2OwnershipTransferRequested) + if err := _OptimismModuleV2.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OptimismModuleV2OwnershipTransferredIterator struct { + Event *OptimismModuleV2OwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OptimismModuleV2OwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OptimismModuleV2OwnershipTransferred) + 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(OptimismModuleV2OwnershipTransferred) + 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 *OptimismModuleV2OwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *OptimismModuleV2OwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OptimismModuleV2OwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_OptimismModuleV2 *OptimismModuleV2Filterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismModuleV2OwnershipTransferredIterator, 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 := _OptimismModuleV2.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &OptimismModuleV2OwnershipTransferredIterator{contract: _OptimismModuleV2.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_OptimismModuleV2 *OptimismModuleV2Filterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OptimismModuleV2OwnershipTransferred, 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 := _OptimismModuleV2.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(OptimismModuleV2OwnershipTransferred) + if err := _OptimismModuleV2.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 (_OptimismModuleV2 *OptimismModuleV2Filterer) ParseOwnershipTransferred(log types.Log) (*OptimismModuleV2OwnershipTransferred, error) { + event := new(OptimismModuleV2OwnershipTransferred) + if err := _OptimismModuleV2.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetGasOverhead struct { + ChainModuleFixedOverhead *big.Int + ChainModulePerByteOverhead *big.Int +} + +func (_OptimismModuleV2 *OptimismModuleV2) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _OptimismModuleV2.abi.Events["L1FeeCoefficientSet"].ID: + return _OptimismModuleV2.ParseL1FeeCoefficientSet(log) + case _OptimismModuleV2.abi.Events["OwnershipTransferRequested"].ID: + return _OptimismModuleV2.ParseOwnershipTransferRequested(log) + case _OptimismModuleV2.abi.Events["OwnershipTransferred"].ID: + return _OptimismModuleV2.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OptimismModuleV2L1FeeCoefficientSet) Topic() common.Hash { + return common.HexToHash("0x29ec9e31de0d3fe0208a7ccb792bbc26a854f123146110daa3a77219cb74a554") +} + +func (OptimismModuleV2OwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (OptimismModuleV2OwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_OptimismModuleV2 *OptimismModuleV2) Address() common.Address { + return _OptimismModuleV2.address +} + +type OptimismModuleV2Interface interface { + BlockHash(opts *bind.CallOpts, n *big.Int) ([32]byte, error) + + BlockNumber(opts *bind.CallOpts) (*big.Int, error) + + GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) + + GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, + + error) + + GetL1FeeCoefficient(opts *bind.CallOpts) (*big.Int, error) + + GetMaxL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + SetL1FeeCalculation(opts *bind.TransactOpts, coefficient uint8) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterL1FeeCoefficientSet(opts *bind.FilterOpts) (*OptimismModuleV2L1FeeCoefficientSetIterator, error) + + WatchL1FeeCoefficientSet(opts *bind.WatchOpts, sink chan<- *OptimismModuleV2L1FeeCoefficientSet) (event.Subscription, error) + + ParseL1FeeCoefficientSet(log types.Log) (*OptimismModuleV2L1FeeCoefficientSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismModuleV2OwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OptimismModuleV2OwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*OptimismModuleV2OwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OptimismModuleV2OwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OptimismModuleV2OwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*OptimismModuleV2OwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/generated/scroll_module/scroll_module.go b/core/gethwrappers/generated/scroll_module/scroll_module.go index 702cc39a7ae..e8f48da0d04 100644 --- a/core/gethwrappers/generated/scroll_module/scroll_module.go +++ b/core/gethwrappers/generated/scroll_module/scroll_module.go @@ -5,6 +5,7 @@ package scroll_module import ( "errors" + "fmt" "math/big" "strings" @@ -14,6 +15,7 @@ import ( "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 ( @@ -29,8 +31,8 @@ var ( ) var ScrollModuleMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061050c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806357e871e71161005057806357e871e71461009a57806385df51fd146100a0578063de9ee35e146100b357600080fd5b8063125441401461006c57806318b8f61314610092575b600080fd5b61007f61007a3660046102e8565b6100c9565b6040519081526020015b60405180910390f35b61007f6101ea565b4361007f565b61007f6100ae3660046102e8565b6102bb565b6040805161afc8815260aa602082015201610089565b6000806100d7836004610330565b67ffffffffffffffff8111156100ef576100ef61034d565b6040519080825280601f01601f191660200182016040528015610119576020820181803683370190505b50905073530000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff166349948e0e826040518060c00160405280608c8152602001610474608c91396040516020016101779291906103a0565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016101a291906103cf565b602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610420565b9392505050565b600073530000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff166349948e0e6000366040518060c00160405280608c8152602001610474608c913960405160200161024a93929190610439565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161027591906103cf565b602060405180830381865afa158015610292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b69190610420565b905090565b600043821015806102d657506101006102d48343610460565b115b156102e357506000919050565b504090565b6000602082840312156102fa57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761034757610347610301565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b8381101561039757818101518382015260200161037f565b50506000910152565b600083516103b281846020880161037c565b8351908301906103c681836020880161037c565b01949350505050565b60208152600082518060208401526103ee81604085016020870161037c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561043257600080fd5b5051919050565b82848237600083820160008152835161045681836020880161037c565b0195945050505050565b818103818111156103475761034761030156feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"coefficient\",\"type\":\"uint8\"}],\"name\":\"InvalidL1FeeCoefficient\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"coefficient\",\"type\":\"uint8\"}],\"name\":\"L1FeeCoefficientSet\",\"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\":\"uint256\",\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"blockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getCurrentL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainModuleFixedOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainModulePerByteOverhead\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getL1FeeCoefficient\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"coefficient\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dataSize\",\"type\":\"uint256\"}],\"name\":\"getMaxL1Fee\",\"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\":\"uint8\",\"name\":\"coefficient\",\"type\":\"uint8\"}],\"name\":\"setL1FeeCalculation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040526001805460ff60a01b1916601960a21b17905534801561002357600080fd5b50338060008161007a5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156100aa576100aa816100b2565b50505061015b565b336001600160a01b0382160361010a5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610071565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6109288061016a6000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80638da5cb5b11610076578063de9ee35e1161005b578063de9ee35e1461016a578063f22559a014610180578063f2fde38b1461019357600080fd5b80638da5cb5b1461011f578063d10a944e1461014757600080fd5b80637810d12a116100a75780637810d12a146100ef57806379ba50971461010257806385df51fd1461010c57600080fd5b806312544140146100c357806357e871e7146100e9575b600080fd5b6100d66100d136600461069d565b6101a6565b6040519081526020015b60405180910390f35b436100d6565b6100d66100fd36600461069d565b6101b7565b61010a6101f6565b005b6100d661011a36600461069d565b6102f8565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b60015474010000000000000000000000000000000000000000900460ff166100d6565b6040805161afc8815260aa6020820152016100e0565b61010a61018e3660046106b6565b610325565b61010a6101a13660046106d9565b6103f0565b60006101b182610404565b92915050565b600060646101c483610404565b6001546101ec919074010000000000000000000000000000000000000000900460ff1661073e565b6101b19190610755565b60015473ffffffffffffffffffffffffffffffffffffffff16331461027c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000438210158061031357506101006103118343610790565b115b1561032057506000919050565b504090565b61032d610525565b60648160ff161115610370576040517f1a8a06a000000000000000000000000000000000000000000000000000000000815260ff82166004820152602401610273565b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f29ec9e31de0d3fe0208a7ccb792bbc26a854f123146110daa3a77219cb74a5549060200160405180910390a150565b6103f8610525565b610401816105a8565b50565b60008061041283600461073e565b67ffffffffffffffff81111561042a5761042a6107a3565b6040519080825280601f01601f191660200182016040528015610454576020820181803683370190505b50905073530000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff166349948e0e826040518060c00160405280608c8152602001610890608c91396040516020016104b29291906107f6565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016104dd9190610825565b602060405180830381865afa1580156104fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051e9190610876565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610273565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610627576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610273565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156106af57600080fd5b5035919050565b6000602082840312156106c857600080fd5b813560ff8116811461051e57600080fd5b6000602082840312156106eb57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461051e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176101b1576101b161070f565b60008261078b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156101b1576101b161070f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156107ed5781810151838201526020016107d5565b50506000910152565b600083516108088184602088016107d2565b83519083019061081c8183602088016107d2565b01949350505050565b60208152600082518060208401526108448160408501602087016107d2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561088857600080fd5b505191905056feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa164736f6c6343000813000a", } var ScrollModuleABI = ScrollModuleMetaData.ABI @@ -213,9 +215,9 @@ func (_ScrollModule *ScrollModuleCallerSession) BlockNumber() (*big.Int, error) return _ScrollModule.Contract.BlockNumber(&_ScrollModule.CallOpts) } -func (_ScrollModule *ScrollModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) { +func (_ScrollModule *ScrollModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) { var out []interface{} - err := _ScrollModule.contract.Call(opts, &out, "getCurrentL1Fee") + err := _ScrollModule.contract.Call(opts, &out, "getCurrentL1Fee", dataSize) if err != nil { return *new(*big.Int), err @@ -227,12 +229,12 @@ func (_ScrollModule *ScrollModuleCaller) GetCurrentL1Fee(opts *bind.CallOpts) (* } -func (_ScrollModule *ScrollModuleSession) GetCurrentL1Fee() (*big.Int, error) { - return _ScrollModule.Contract.GetCurrentL1Fee(&_ScrollModule.CallOpts) +func (_ScrollModule *ScrollModuleSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _ScrollModule.Contract.GetCurrentL1Fee(&_ScrollModule.CallOpts, dataSize) } -func (_ScrollModule *ScrollModuleCallerSession) GetCurrentL1Fee() (*big.Int, error) { - return _ScrollModule.Contract.GetCurrentL1Fee(&_ScrollModule.CallOpts) +func (_ScrollModule *ScrollModuleCallerSession) GetCurrentL1Fee(dataSize *big.Int) (*big.Int, error) { + return _ScrollModule.Contract.GetCurrentL1Fee(&_ScrollModule.CallOpts, dataSize) } func (_ScrollModule *ScrollModuleCaller) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, @@ -265,6 +267,28 @@ func (_ScrollModule *ScrollModuleCallerSession) GetGasOverhead() (GetGasOverhead return _ScrollModule.Contract.GetGasOverhead(&_ScrollModule.CallOpts) } +func (_ScrollModule *ScrollModuleCaller) GetL1FeeCoefficient(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _ScrollModule.contract.Call(opts, &out, "getL1FeeCoefficient") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_ScrollModule *ScrollModuleSession) GetL1FeeCoefficient() (*big.Int, error) { + return _ScrollModule.Contract.GetL1FeeCoefficient(&_ScrollModule.CallOpts) +} + +func (_ScrollModule *ScrollModuleCallerSession) GetL1FeeCoefficient() (*big.Int, error) { + return _ScrollModule.Contract.GetL1FeeCoefficient(&_ScrollModule.CallOpts) +} + func (_ScrollModule *ScrollModuleCaller) GetMaxL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) { var out []interface{} err := _ScrollModule.contract.Call(opts, &out, "getMaxL1Fee", dataSize) @@ -287,11 +311,484 @@ func (_ScrollModule *ScrollModuleCallerSession) GetMaxL1Fee(dataSize *big.Int) ( return _ScrollModule.Contract.GetMaxL1Fee(&_ScrollModule.CallOpts, dataSize) } +func (_ScrollModule *ScrollModuleCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ScrollModule.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 (_ScrollModule *ScrollModuleSession) Owner() (common.Address, error) { + return _ScrollModule.Contract.Owner(&_ScrollModule.CallOpts) +} + +func (_ScrollModule *ScrollModuleCallerSession) Owner() (common.Address, error) { + return _ScrollModule.Contract.Owner(&_ScrollModule.CallOpts) +} + +func (_ScrollModule *ScrollModuleTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ScrollModule.contract.Transact(opts, "acceptOwnership") +} + +func (_ScrollModule *ScrollModuleSession) AcceptOwnership() (*types.Transaction, error) { + return _ScrollModule.Contract.AcceptOwnership(&_ScrollModule.TransactOpts) +} + +func (_ScrollModule *ScrollModuleTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _ScrollModule.Contract.AcceptOwnership(&_ScrollModule.TransactOpts) +} + +func (_ScrollModule *ScrollModuleTransactor) SetL1FeeCalculation(opts *bind.TransactOpts, coefficient uint8) (*types.Transaction, error) { + return _ScrollModule.contract.Transact(opts, "setL1FeeCalculation", coefficient) +} + +func (_ScrollModule *ScrollModuleSession) SetL1FeeCalculation(coefficient uint8) (*types.Transaction, error) { + return _ScrollModule.Contract.SetL1FeeCalculation(&_ScrollModule.TransactOpts, coefficient) +} + +func (_ScrollModule *ScrollModuleTransactorSession) SetL1FeeCalculation(coefficient uint8) (*types.Transaction, error) { + return _ScrollModule.Contract.SetL1FeeCalculation(&_ScrollModule.TransactOpts, coefficient) +} + +func (_ScrollModule *ScrollModuleTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _ScrollModule.contract.Transact(opts, "transferOwnership", to) +} + +func (_ScrollModule *ScrollModuleSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _ScrollModule.Contract.TransferOwnership(&_ScrollModule.TransactOpts, to) +} + +func (_ScrollModule *ScrollModuleTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _ScrollModule.Contract.TransferOwnership(&_ScrollModule.TransactOpts, to) +} + +type ScrollModuleL1FeeCoefficientSetIterator struct { + Event *ScrollModuleL1FeeCoefficientSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ScrollModuleL1FeeCoefficientSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ScrollModuleL1FeeCoefficientSet) + 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(ScrollModuleL1FeeCoefficientSet) + 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 *ScrollModuleL1FeeCoefficientSetIterator) Error() error { + return it.fail +} + +func (it *ScrollModuleL1FeeCoefficientSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ScrollModuleL1FeeCoefficientSet struct { + Coefficient uint8 + Raw types.Log +} + +func (_ScrollModule *ScrollModuleFilterer) FilterL1FeeCoefficientSet(opts *bind.FilterOpts) (*ScrollModuleL1FeeCoefficientSetIterator, error) { + + logs, sub, err := _ScrollModule.contract.FilterLogs(opts, "L1FeeCoefficientSet") + if err != nil { + return nil, err + } + return &ScrollModuleL1FeeCoefficientSetIterator{contract: _ScrollModule.contract, event: "L1FeeCoefficientSet", logs: logs, sub: sub}, nil +} + +func (_ScrollModule *ScrollModuleFilterer) WatchL1FeeCoefficientSet(opts *bind.WatchOpts, sink chan<- *ScrollModuleL1FeeCoefficientSet) (event.Subscription, error) { + + logs, sub, err := _ScrollModule.contract.WatchLogs(opts, "L1FeeCoefficientSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ScrollModuleL1FeeCoefficientSet) + if err := _ScrollModule.contract.UnpackLog(event, "L1FeeCoefficientSet", 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 (_ScrollModule *ScrollModuleFilterer) ParseL1FeeCoefficientSet(log types.Log) (*ScrollModuleL1FeeCoefficientSet, error) { + event := new(ScrollModuleL1FeeCoefficientSet) + if err := _ScrollModule.contract.UnpackLog(event, "L1FeeCoefficientSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ScrollModuleOwnershipTransferRequestedIterator struct { + Event *ScrollModuleOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ScrollModuleOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ScrollModuleOwnershipTransferRequested) + 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(ScrollModuleOwnershipTransferRequested) + 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 *ScrollModuleOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *ScrollModuleOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ScrollModuleOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_ScrollModule *ScrollModuleFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ScrollModuleOwnershipTransferRequestedIterator, 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 := _ScrollModule.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &ScrollModuleOwnershipTransferRequestedIterator{contract: _ScrollModule.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_ScrollModule *ScrollModuleFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ScrollModuleOwnershipTransferRequested, 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 := _ScrollModule.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(ScrollModuleOwnershipTransferRequested) + if err := _ScrollModule.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 (_ScrollModule *ScrollModuleFilterer) ParseOwnershipTransferRequested(log types.Log) (*ScrollModuleOwnershipTransferRequested, error) { + event := new(ScrollModuleOwnershipTransferRequested) + if err := _ScrollModule.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ScrollModuleOwnershipTransferredIterator struct { + Event *ScrollModuleOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ScrollModuleOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ScrollModuleOwnershipTransferred) + 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(ScrollModuleOwnershipTransferred) + 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 *ScrollModuleOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *ScrollModuleOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ScrollModuleOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_ScrollModule *ScrollModuleFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ScrollModuleOwnershipTransferredIterator, 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 := _ScrollModule.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &ScrollModuleOwnershipTransferredIterator{contract: _ScrollModule.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_ScrollModule *ScrollModuleFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ScrollModuleOwnershipTransferred, 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 := _ScrollModule.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(ScrollModuleOwnershipTransferred) + if err := _ScrollModule.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 (_ScrollModule *ScrollModuleFilterer) ParseOwnershipTransferred(log types.Log) (*ScrollModuleOwnershipTransferred, error) { + event := new(ScrollModuleOwnershipTransferred) + if err := _ScrollModule.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type GetGasOverhead struct { ChainModuleFixedOverhead *big.Int ChainModulePerByteOverhead *big.Int } +func (_ScrollModule *ScrollModule) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _ScrollModule.abi.Events["L1FeeCoefficientSet"].ID: + return _ScrollModule.ParseL1FeeCoefficientSet(log) + case _ScrollModule.abi.Events["OwnershipTransferRequested"].ID: + return _ScrollModule.ParseOwnershipTransferRequested(log) + case _ScrollModule.abi.Events["OwnershipTransferred"].ID: + return _ScrollModule.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (ScrollModuleL1FeeCoefficientSet) Topic() common.Hash { + return common.HexToHash("0x29ec9e31de0d3fe0208a7ccb792bbc26a854f123146110daa3a77219cb74a554") +} + +func (ScrollModuleOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (ScrollModuleOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + func (_ScrollModule *ScrollModule) Address() common.Address { return _ScrollModule.address } @@ -301,13 +798,43 @@ type ScrollModuleInterface interface { BlockNumber(opts *bind.CallOpts) (*big.Int, error) - GetCurrentL1Fee(opts *bind.CallOpts) (*big.Int, error) + GetCurrentL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) GetGasOverhead(opts *bind.CallOpts) (GetGasOverhead, error) + GetL1FeeCoefficient(opts *bind.CallOpts) (*big.Int, error) + GetMaxL1Fee(opts *bind.CallOpts, dataSize *big.Int) (*big.Int, error) + Owner(opts *bind.CallOpts) (common.Address, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + SetL1FeeCalculation(opts *bind.TransactOpts, coefficient uint8) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterL1FeeCoefficientSet(opts *bind.FilterOpts) (*ScrollModuleL1FeeCoefficientSetIterator, error) + + WatchL1FeeCoefficientSet(opts *bind.WatchOpts, sink chan<- *ScrollModuleL1FeeCoefficientSet) (event.Subscription, error) + + ParseL1FeeCoefficientSet(log types.Log) (*ScrollModuleL1FeeCoefficientSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ScrollModuleOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ScrollModuleOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*ScrollModuleOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ScrollModuleOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ScrollModuleOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*ScrollModuleOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + Address() common.Address } diff --git a/core/gethwrappers/generated/vrf_coordinator_test_v2_5/vrf_coordinator_test_v2_5.go b/core/gethwrappers/generated/vrf_coordinator_test_v2_5/vrf_coordinator_test_v2_5.go new file mode 100644 index 00000000000..6d6d38ef381 --- /dev/null +++ b/core/gethwrappers/generated/vrf_coordinator_test_v2_5/vrf_coordinator_test_v2_5.go @@ -0,0 +1,3994 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_coordinator_test_v2_5 + +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 VRFOldProof struct { + Pk [2]*big.Int + Gamma [2]*big.Int + C *big.Int + S *big.Int + Seed *big.Int + UWitness common.Address + CGammaWitness [2]*big.Int + SHashWitness [2]*big.Int + ZInv *big.Int +} + +type VRFTypesRequestCommitmentV2Plus struct { + BlockNum uint64 + SubId *big.Int + CallbackGasLimit uint32 + NumWords uint32 + Sender common.Address + ExtraArgs []byte +} + +type VRFV2PlusClientRandomWordsRequest struct { + KeyHash [32]byte + SubId *big.Int + RequestConfirmations uint16 + CallbackGasLimit uint32 + NumWords uint32 + ExtraArgs []byte +} + +var VRFCoordinatorTestV25MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorNotRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxGas\",\"type\":\"uint256\"}],\"name\":\"GasPriceExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"max\",\"type\":\"uint8\"}],\"name\":\"InvalidPremiumPercentage\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"flatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeNativePPM\",\"type\":\"uint32\"}],\"name\":\"LinkDiscountTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"have\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"max\",\"type\":\"uint32\"}],\"name\":\"MsgDataTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedOwner\",\"type\":\"address\"}],\"name\":\"MustBeRequestedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"name\":\"FallbackWeiPerUnitLinkUsed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"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\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"name\":\"ProvingKeyDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"nativePayment\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"onlyPremium\",\"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\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"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\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"type\":\"uint256\"}],\"name\":\"SubscriptionCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"SubscriptionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"acceptSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"addConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"cancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createSubscription\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"deregisterMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"deregisterProvingKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRFOld.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFTypes.RequestCommitmentV2Plus\",\"name\":\"rc\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"onlyPremium\",\"type\":\"bool\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subOwner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"name\":\"registerProvingKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"removeConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"requestSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fallbackWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_provingKeys\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162005e6338038062005e6383398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160a01b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160a01b0381168114620001a957600080fd5b9392505050565b608051615c90620001d3600039600081816105d2015261331e0152615c906000f3fe60806040526004361061028c5760003560e01c80638402595e11610164578063b2a7cac5116100c6578063da2f26101161008a578063e72f6e3011610064578063e72f6e3014610904578063ee9d2d3814610924578063f2fde38b1461095157600080fd5b8063da2f261014610854578063dac83d29146108b3578063dc311dd3146108d357600080fd5b8063b2a7cac5146107b4578063bec4c08c146107d4578063caf70c4a146107f4578063cb63179714610814578063d98e620e1461083457600080fd5b80639d40a6fd11610128578063a63e0bfb11610102578063a63e0bfb14610747578063aa433aff14610767578063aefb212f1461078757600080fd5b80639d40a6fd146106da578063a21a23e414610712578063a4c0ed361461072757600080fd5b80638402595e1461064957806386fe91c7146106695780638da5cb5b1461068957806395b55cfc146106a75780639b1c385e146106ba57600080fd5b8063405b84fa1161020d57806364d51a2a116101d157806372e9d565116101ab57806372e9d565146105f457806379ba5097146106145780637a5a2aef1461062957600080fd5b806364d51a2a1461058b57806365982744146105a0578063689c4517146105c057600080fd5b8063405b84fa146104d057806340d6bb82146104f057806341af6c871461051b57806351cff8d91461054b5780635d06b4ab1461056b57600080fd5b806315c48b841161025457806315c48b84146103f157806318e3dd27146104195780631b6b6d23146104585780632f622e6b14610490578063301f42e9146104b057600080fd5b806304104edb14610291578063043bd6ae146102b3578063088070f5146102dc57806308821d58146103b15780630ae09540146103d1575b600080fd5b34801561029d57600080fd5b506102b16102ac366004614f21565b610971565b005b3480156102bf57600080fd5b506102c960105481565b6040519081526020015b60405180910390f35b3480156102e857600080fd5b50600c546103549061ffff81169063ffffffff62010000820481169160ff660100000000000082048116926701000000000000008304811692600160581b8104821692600160781b8204831692600160981b83041691600160b81b8104821691600160c01b9091041689565b6040805161ffff909a168a5263ffffffff98891660208b01529615159689019690965293861660608801529185166080870152841660a08601529290921660c084015260ff91821660e084015216610100820152610120016102d3565b3480156103bd57600080fd5b506102b16103cc366004614f4f565b610aea565b3480156103dd57600080fd5b506102b16103ec366004614f6b565b610ca7565b3480156103fd57600080fd5b5061040660c881565b60405161ffff90911681526020016102d3565b34801561042557600080fd5b50600a5461044090600160601b90046001600160601b031681565b6040516001600160601b0390911681526020016102d3565b34801561046457600080fd5b50600254610478906001600160a01b031681565b6040516001600160a01b0390911681526020016102d3565b34801561049c57600080fd5b506102b16104ab366004614f21565b610cef565b3480156104bc57600080fd5b506104406104cb3660046151cd565b610d95565b3480156104dc57600080fd5b506102b16104eb366004614f6b565b6110ab565b3480156104fc57600080fd5b506105066101f481565b60405163ffffffff90911681526020016102d3565b34801561052757600080fd5b5061053b6105363660046152bb565b61148d565b60405190151581526020016102d3565b34801561055757600080fd5b506102b1610566366004614f21565b611541565b34801561057757600080fd5b506102b1610586366004614f21565b611666565b34801561059757600080fd5b50610406606481565b3480156105ac57600080fd5b506102b16105bb3660046152d4565b611724565b3480156105cc57600080fd5b506104787f000000000000000000000000000000000000000000000000000000000000000081565b34801561060057600080fd5b50600354610478906001600160a01b031681565b34801561062057600080fd5b506102b1611784565b34801561063557600080fd5b506102b1610644366004615302565b611835565b34801561065557600080fd5b506102b1610664366004614f21565b611969565b34801561067557600080fd5b50600a54610440906001600160601b031681565b34801561069557600080fd5b506000546001600160a01b0316610478565b6102b16106b53660046152bb565b611a84565b3480156106c657600080fd5b506102c96106d5366004615336565b611b94565b3480156106e657600080fd5b506007546106fa906001600160401b031681565b6040516001600160401b0390911681526020016102d3565b34801561071e57600080fd5b506102c9611fda565b34801561073357600080fd5b506102b1610742366004615370565b6121c1565b34801561075357600080fd5b506102b161076236600461541b565b612329565b34801561077357600080fd5b506102b16107823660046152bb565b612610565b34801561079357600080fd5b506107a76107a23660046154bc565b612643565b6040516102d39190615519565b3480156107c057600080fd5b506102b16107cf3660046152bb565b612745565b3480156107e057600080fd5b506102b16107ef366004614f6b565b612834565b34801561080057600080fd5b506102c961080f36600461552c565b612927565b34801561082057600080fd5b506102b161082f366004614f6b565b612957565b34801561084057600080fd5b506102c961084f3660046152bb565b612bc5565b34801561086057600080fd5b5061089461086f3660046152bb565b600d6020526000908152604090205460ff81169061010090046001600160401b031682565b6040805192151583526001600160401b039091166020830152016102d3565b3480156108bf57600080fd5b506102b16108ce366004614f6b565b612be6565b3480156108df57600080fd5b506108f36108ee3660046152bb565b612c81565b6040516102d3959493929190615581565b34801561091057600080fd5b506102b161091f366004614f21565b612d5a565b34801561093057600080fd5b506102c961093f3660046152bb565b600f6020526000908152604090205481565b34801561095d57600080fd5b506102b161096c366004614f21565b612f1b565b610979612f2c565b60115460005b81811015610abd57826001600160a01b0316601182815481106109a4576109a46155d6565b6000918252602090912001546001600160a01b031603610aad5760116109cb600184615602565b815481106109db576109db6155d6565b600091825260209091200154601180546001600160a01b039092169183908110610a0757610a076155d6565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506011805480610a4657610a46615615565b6000828152602090819020600019908301810180546001600160a01b03191690559091019091556040516001600160a01b03851681527ff80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af3791015b60405180910390a1505050565b610ab68161562b565b905061097f565b50604051635428d44960e01b81526001600160a01b03831660048201526024015b60405180910390fd5b50565b610af2612f2c565b604080518082018252600091610b21919084906002908390839080828437600092019190915250612927915050565b6000818152600d602090815260409182902082518084019093525460ff811615158084526101009091046001600160401b03169183019190915291925090610b7f57604051631dfd6e1360e21b815260048101839052602401610ade565b6000828152600d60205260408120805468ffffffffffffffffff19169055600e54905b81811015610c515783600e8281548110610bbe57610bbe6155d6565b906000526020600020015403610c4157600e610bdb600184615602565b81548110610beb57610beb6155d6565b9060005260206000200154600e8281548110610c0957610c096155d6565b600091825260209091200155600e805480610c2657610c26615615565b60019003818190600052602060002001600090559055610c51565b610c4a8161562b565b9050610ba2565b507f9b6868e0eb737bcd72205360baa6bfd0ba4e4819a33ade2db384e8a8025639a5838360200151604051610c999291909182526001600160401b0316602082015260400190565b60405180910390a150505050565b81610cb181612f88565b610cb9612fdd565b610cc28361148d565b15610ce057604051631685ecdd60e31b815260040160405180910390fd5b610cea838361300b565b505050565b610cf7612fdd565b610cff612f2c565b600b54600160601b90046001600160601b0316610d1d8115156130ee565b600b80546bffffffffffffffffffffffff60601b19169055600a8054829190600c90610d5a908490600160601b90046001600160601b0316615644565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550610d9182826001600160601b031661310c565b5050565b6000610d9f612fdd565b60005a9050610324361115610dd157604051630f28961b60e01b81523660048201526103246024820152604401610ade565b6000610ddd8686613180565b90506000610df385836000015160200151613431565b60408301516060888101519293509163ffffffff16806001600160401b03811115610e2057610e20614f9b565b604051908082528060200260200182016040528015610e49578160200160208202803683370190505b50925060005b81811015610eb15760408051602081018590529081018290526060016040516020818303038152906040528051906020012060001c848281518110610e9657610e966155d6565b6020908102919091010152610eaa8161562b565b9050610e4f565b5050602080850180516000908152600f9092526040822082905551610ed7908a8561348c565b60208a8101516000908152600690915260409020805491925090601890610f0d90600160c01b90046001600160401b0316615664565b82546101009290920a6001600160401b0381810219909316918316021790915560808a01516001600160a01b03166000908152600460209081526040808320828e01518452909152902080549091600991610f7091600160481b9091041661568a565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555060008960a0015160018b60a0015151610fad9190615602565b81518110610fbd57610fbd6155d6565b60209101015160f81c60011490506000610fd98887848d613530565b909950905080156110245760208088015160105460408051928352928201527f6ca648a381f22ead7e37773d934e64885dcf861fbfbb26c40354cbf0c4662d1a910160405180910390a15b5061103488828c60200151613568565b6020808b015187820151604080518781526001600160601b038d16948101949094528415159084015284151560608401528b1515608084015290917faeb4b4786571e184246d39587f659abf0e26f41f6a3358692250382c0cdb47b79060a00160405180910390a3505050505050505b9392505050565b6110b3612fdd565b6110bc816136c5565b6110e457604051635428d44960e01b81526001600160a01b0382166004820152602401610ade565b6000806000806110f386612c81565b945094505093509350336001600160a01b0316826001600160a01b03161461115d5760405162461bcd60e51b815260206004820152601660248201527f4e6f7420737562736372697074696f6e206f776e6572000000000000000000006044820152606401610ade565b6111668661148d565b156111b35760405162461bcd60e51b815260206004820152601660248201527f50656e64696e67207265717565737420657869737473000000000000000000006044820152606401610ade565b6040805160c0810182526001815260208082018990526001600160a01b03851682840152606082018490526001600160601b038088166080840152861660a083015291519091600091611208918491016156ad565b604051602081830303815290604052905061122288613730565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b0388169061125b908590600401615772565b6000604051808303818588803b15801561127457600080fd5b505af1158015611288573d6000803e3d6000fd5b50506002546001600160a01b0316158015935091506112b1905057506001600160601b03861615155b156113815760025460405163a9059cbb60e01b81526001600160a01b0389811660048301526001600160601b03891660248301529091169063a9059cbb906044016020604051808303816000875af1158015611311573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113359190615785565b6113815760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e647300000000000000000000000000006044820152606401610ade565b600c805466ff0000000000001916660100000000000017905560005b8351811015611430578381815181106113b8576113b86155d6565b6020908102919091010151604051638ea9811760e01b81526001600160a01b038a8116600483015290911690638ea9811790602401600060405180830381600087803b15801561140757600080fd5b505af115801561141b573d6000803e3d6000fd5b50505050806114299061562b565b905061139d565b50600c805466ff00000000000019169055604080516001600160a01b0389168152602081018a90527fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187910160405180910390a15050505050505050565b600081815260056020526040812060020180548083036114b1575060009392505050565b60005b81811015611536576000600460008584815481106114d4576114d46155d6565b60009182526020808320909101546001600160a01b0316835282810193909352604091820181208982529092529020546001600160401b03600160481b90910416111561152657506001949350505050565b61152f8161562b565b90506114b4565b506000949350505050565b611549612fdd565b611551612f2c565b6002546001600160a01b031661157a5760405163c1f0c0a160e01b815260040160405180910390fd5b600b546001600160601b03166115918115156130ee565b600b80546bffffffffffffffffffffffff19169055600a80548291906000906115c49084906001600160601b0316615644565b82546101009290920a6001600160601b0381810219909316918316021790915560025460405163a9059cbb60e01b81526001600160a01b0386811660048301529285166024820152610d91935091169063a9059cbb906044015b6020604051808303816000875af115801561163d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116619190615785565b6130ee565b61166e612f2c565b611677816136c5565b156116a05760405163ac8a27ef60e01b81526001600160a01b0382166004820152602401610ade565b601180546001810182556000919091527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b0383169081179091556040519081527fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af016259060200160405180910390a150565b61172c612f2c565b6002546001600160a01b03161561175657604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b6001546001600160a01b031633146117de5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610ade565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61183d612f2c565b60408051808201825260009161186c919085906002908390839080828437600092019190915250612927915050565b6000818152600d602052604090205490915060ff16156118a257604051634a0b8fa760e01b815260048101829052602401610ade565b60408051808201825260018082526001600160401b0385811660208085018281526000888152600d835287812096518754925168ffffffffffffffffff1990931690151568ffffffffffffffff00191617610100929095169190910293909317909455600e805493840181559091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd9091018490558251848152918201527f9b911b2c240bfbef3b6a8f7ed6ee321d1258bb2a3fe6becab52ac1cd3210afd39101610aa0565b611971612f2c565b600a544790600160601b90046001600160601b0316818111156119b1576040516354ced18160e11b81526004810182905260248101839052604401610ade565b81811015610cea5760006119c58284615602565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d8060008114611a14576040519150601f19603f3d011682016040523d82523d6000602084013e611a19565b606091505b5050905080611a3b5760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b0387168152602081018490527f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c910160405180910390a15050505050565b611a8c612fdd565b600081815260056020526040902054611aad906001600160a01b03166138e2565b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611adc83856157a2565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b0316611b2491906157a2565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e902823484611b7791906157c2565b604080519283526020830191909152015b60405180910390a25050565b6000611b9e612fdd565b602080830135600081815260059092526040909120546001600160a01b0316611bda57604051630fb532db60e11b815260040160405180910390fd5b336000908152600460209081526040808320848452808352928190208151606081018352905460ff811615158083526001600160401b036101008304811695840195909552600160481b9091049093169181019190915290611c58576040516379bfd40160e01b815260048101849052336024820152604401610ade565b600c5461ffff16611c6f60608701604088016157d5565b61ffff161080611c92575060c8611c8c60608701604088016157d5565b61ffff16115b15611cd857611ca760608601604087016157d5565b600c5460405163539c34bb60e11b815261ffff92831660048201529116602482015260c86044820152606401610ade565b600c5462010000900463ffffffff16611cf760808701606088016157f0565b63ffffffff161115611d4757611d1360808601606087016157f0565b600c54604051637aebf00f60e11b815263ffffffff9283166004820152620100009091049091166024820152604401610ade565b6101f4611d5a60a08701608088016157f0565b63ffffffff161115611da057611d7660a08601608087016157f0565b6040516311ce1afb60e21b815263ffffffff90911660048201526101f46024820152604401610ade565b806020018051611daf90615664565b6001600160401b03169052604081018051611dc990615664565b6001600160401b03908116909152602082810151604080518935818501819052338284015260608201899052929094166080808601919091528151808603909101815260a08501825280519084012060c085019290925260e08085018390528151808603909101815261010090940190528251929091019190912060009190955090506000611e6b611e66611e6160a08a018a61580b565b613909565b61398a565b905085611e766139fb565b86611e8760808b0160608c016157f0565b611e9760a08c0160808d016157f0565b3386604051602001611eaf9796959493929190615858565b60405160208183030381529060405280519060200120600f600088815260200190815260200160002081905550336001600160a01b03168588600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e89868c6040016020810190611f2291906157d5565b8d6060016020810190611f3591906157f0565b8e6080016020810190611f4891906157f0565b89604051611f5b969594939291906158af565b60405180910390a45050600092835260209182526040928390208151815493830151929094015168ffffffffffffffffff1990931693151568ffffffffffffffff001916939093176101006001600160401b03928316021770ffffffffffffffff0000000000000000001916600160481b91909216021790555b919050565b6000611fe4612fdd565b6007546001600160401b031633611ffc600143615602565b6040516bffffffffffffffffffffffff19606093841b81166020830152914060348201523090921b1660548201526001600160c01b031960c083901b16606882015260700160408051601f19818403018152919052805160209091012091506120668160016158ee565b6007805467ffffffffffffffff19166001600160401b03928316179055604080516000808252608082018352602080830182815283850183815260608086018581528a86526006855287862093518454935191516001600160601b039182166001600160c01b031990951694909417600160601b91909216021777ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b9290981691909102969096179055835194850184523385528481018281528585018481528884526005835294909220855181546001600160a01b03199081166001600160a01b0392831617835593516001830180549095169116179092559251805192949391926121769260028501920190614e0f565b5061218691506008905084613a7c565b5060405133815283907f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d9060200160405180910390a2505090565b6121c9612fdd565b6002546001600160a01b031633146121f4576040516344b0e3c360e01b815260040160405180910390fd5b6020811461221557604051638129bbcd60e01b815260040160405180910390fd5b6000612223828401846152bb565b600081815260056020526040902054909150612247906001600160a01b03166138e2565b600081815260066020526040812080546001600160601b03169186919061226e83856157a2565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b03166122b691906157a2565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a82878461230991906157c2565b6040805192835260208301919091520160405180910390a2505050505050565b612331612f2c565b60c861ffff8a16111561236b5760405163539c34bb60e11b815261ffff8a1660048201819052602482015260c86044820152606401610ade565b6000851361238f576040516321ea67b360e11b815260048101869052602401610ade565b8363ffffffff168363ffffffff1611156123cc576040516313c06e5960e11b815263ffffffff808516600483015285166024820152604401610ade565b609b60ff831611156123fd57604051631d66288d60e11b815260ff83166004820152609b6024820152604401610ade565b609b60ff8216111561242e57604051631d66288d60e11b815260ff82166004820152609b6024820152604401610ade565b604080516101208101825261ffff8b1680825263ffffffff808c16602084018190526000848601528b8216606085018190528b8316608086018190528a841660a08701819052938a1660c0870181905260ff808b1660e08901819052908a16610100909801889052600c8054600160c01b90990260ff60c01b19600160b81b9093029290921661ffff60b81b19600160981b90940263ffffffff60981b19600160781b9099029890981676ffffffffffffffff00000000000000000000000000000019600160581b9096026effffffff000000000000000000000019670100000000000000909802979097166effffffffffffffffff000000000000196201000090990265ffffffffffff19909c16909a179a909a1796909616979097179390931791909116959095179290921793909316929092179190911790556010869055517f2c6b6b12413678366b05b145c5f00745bdd00e739131ab5de82484a50c9d78b6906125fd908b908b908b908b908b908b908b908b908b9061ffff99909916895263ffffffff97881660208a0152958716604089015293861660608801526080870192909252841660a086015290921660c084015260ff91821660e0840152166101008201526101200190565b60405180910390a1505050505050505050565b612618612f2c565b6000818152600560205260409020546001600160a01b0316612639816138e2565b610d91828261300b565b606060006126516008613a88565b905080841061267357604051631390f2a160e01b815260040160405180910390fd5b600061267f84866157c2565b90508181118061268d575083155b6126975780612699565b815b905060006126a78683615602565b9050806001600160401b038111156126c1576126c1614f9b565b6040519080825280602002602001820160405280156126ea578160200160208202803683370190505b50935060005b8181101561273a5761270d61270588836157c2565b600890613a92565b85828151811061271f5761271f6155d6565b60209081029190910101526127338161562b565b90506126f0565b505050505b92915050565b61274d612fdd565b6000818152600560205260409020546001600160a01b031661276e816138e2565b6000828152600560205260409020600101546001600160a01b031633146127c7576000828152600560205260409081902060010154905163d084e97560e01b81526001600160a01b039091166004820152602401610ade565b6000828152600560209081526040918290208054336001600160a01b03199182168117835560019092018054909116905582516001600160a01b03851681529182015283917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c93869101611b88565b8161283e81612f88565b612846612fdd565b6001600160a01b03821660009081526004602090815260408083208684529091529020805460ff16156128795750505050565b60008481526005602052604090206002018054606319016128ad576040516305a48e0f60e01b815260040160405180910390fd5b8154600160ff199091168117835581549081018255600082815260209081902090910180546001600160a01b0319166001600160a01b03871690811790915560405190815286917f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e191015b60405180910390a25050505050565b60008160405160200161293a9190615931565b604051602081830303815290604052805190602001209050919050565b8161296181612f88565b612969612fdd565b6129728361148d565b1561299057604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b038216600090815260046020908152604080832086845290915290205460ff166129e6576040516379bfd40160e01b8152600481018490526001600160a01b0383166024820152604401610ade565b600083815260056020908152604080832060020180548251818502810185019093528083529192909190830182828015612a4957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612a2b575b50505050509050600060018251612a609190615602565b905060005b8251811015612b6957846001600160a01b0316838281518110612a8a57612a8a6155d6565b60200260200101516001600160a01b031603612b59576000838381518110612ab457612ab46155d6565b6020026020010151905080600560008981526020019081526020016000206002018381548110612ae657612ae66155d6565b600091825260208083209190910180546001600160a01b0319166001600160a01b039490941693909317909255888152600590915260409020600201805480612b3157612b31615615565b600082815260209020810160001990810180546001600160a01b031916905501905550612b69565b612b628161562b565b9050612a65565b506001600160a01b0384166000818152600460209081526040808320898452825291829020805460ff19169055905191825286917f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a79101612918565b600e8181548110612bd557600080fd5b600091825260209091200154905081565b81612bf081612f88565b612bf8612fdd565b600083815260056020526040902060018101546001600160a01b03848116911614612c7b576001810180546001600160a01b0319166001600160a01b03851690811790915560408051338152602081019290925285917f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a191015b60405180910390a25b50505050565b600081815260056020526040812054819081906001600160a01b03166060612ca8826138e2565b600086815260066020908152604080832054600583529281902060020180548251818502810185019093528083526001600160601b0380861695600160601b810490911694600160c01b9091046001600160401b0316938893929091839190830182828015612d4057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612d22575b505050505090509450945094509450945091939590929450565b612d62612f2c565b6002546001600160a01b0316612d8b5760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df8919061593f565b600a549091506001600160601b031681811115612e32576040516354ced18160e11b81526004810182905260248101839052604401610ade565b81811015610cea576000612e468284615602565b60025460405163a9059cbb60e01b81526001600160a01b0387811660048301526024820184905292935091169063a9059cbb906044016020604051808303816000875af1158015612e9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebf9190615785565b612edc57604051631f01ff1360e21b815260040160405180910390fd5b604080516001600160a01b0386168152602081018390527f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b4366009101610c99565b612f23612f2c565b610ae781613a9e565b6000546001600160a01b03163314612f865760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610ade565b565b6000818152600560205260409020546001600160a01b0316612fa9816138e2565b336001600160a01b03821614610d9157604051636c51fda960e11b81526001600160a01b0382166004820152602401610ade565b600c546601000000000000900460ff1615612f865760405163769dd35360e11b815260040160405180910390fd5b60008061301784613730565b60025491935091506001600160a01b03161580159061303e57506001600160601b03821615155b156130865760025460405163a9059cbb60e01b81526001600160a01b0385811660048301526001600160601b038516602483015261308692169063a9059cbb9060440161161e565b61309983826001600160601b031661310c565b604080516001600160a01b03851681526001600160601b03808516602083015283169181019190915284907f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c490606001612c72565b80610ae757604051631e9acf1760e31b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613159576040519150601f19603f3d011682016040523d82523d6000602084013e61315e565b606091505b5050905080610cea5760405163950b247960e01b815260040160405180910390fd5b6040805160a081018252600060608201818152608083018290528252602082018190529181019190915260006131b98460000151612927565b6000818152600d602090815260409182902082518084019093525460ff811615158084526101009091046001600160401b0316918301919091529192509061321757604051631dfd6e1360e21b815260048101839052602401610ade565b6000828660800151604051602001613239929190918252602082015260400190565b60408051601f1981840301815291815281516020928301206000818152600f909352908220549092509081900361328357604051631b44092560e11b815260040160405180910390fd5b85516020808801516040808a015160608b015160808c015160a08d015193516132b2978a979096959101615958565b6040516020818303038152906040528051906020012081146132e75760405163354a450b60e21b815260040160405180910390fd5b60006132f68760000151613b47565b9050806133bf578651604051631d2827a760e31b81526001600160401b0390911660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e9413d3890602401602060405180830381865afa15801561336d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613391919061593f565b9050806133bf57865160405163175dadad60e01b81526001600160401b039091166004820152602401610ade565b60008860800151826040516020016133e1929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c905060006134088a83613c1a565b604080516060810182529788526020880196909652948601949094525092979650505050505050565b6000816001600160401b03163a111561348457821561345a57506001600160401b03811661273f565b60405163435e532d60e11b81523a60048201526001600160401b0383166024820152604401610ade565b503a92915050565b6000806000631fe543e360e01b86856040516024016134ac9291906159ab565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600c805466ff000000000000191666010000000000001790559086015160808701519192506135169163ffffffff9091169083613c85565b600c805466ff000000000000191690559695505050505050565b600080831561354f57613544868685613cd1565b60009150915061355f565b61355a868685613de2565b915091505b94509492505050565b6000818152600660205260409020821561362c5780546001600160601b03600160601b90910481169085168110156135b357604051631e9acf1760e31b815260040160405180910390fd5b6135bd8582615644565b82546bffffffffffffffffffffffff60601b1916600160601b6001600160601b039283168102919091178455600b805488939192600c926136029286929004166157a2565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555050612c7b565b80546001600160601b0390811690851681101561365c57604051631e9acf1760e31b815260040160405180910390fd5b6136668582615644565b82546bffffffffffffffffffffffff19166001600160601b03918216178355600b8054879260009161369a918591166157a2565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050505050565b601154600090815b8181101561372657836001600160a01b0316601182815481106136f2576136f26155d6565b6000918252602090912001546001600160a01b031603613716575060019392505050565b61371f8161562b565b90506136cd565b5060009392505050565b60008181526005602090815260408083206006909252822054600290910180546001600160601b0380841694600160601b90940416925b818110156137dc5760046000848381548110613785576137856155d6565b60009182526020808320909101546001600160a01b0316835282810193909352604091820181208982529092529020805470ffffffffffffffffffffffffffffffffff191690556137d58161562b565b9050613767565b50600085815260056020526040812080546001600160a01b031990811682556001820180549091169055906138146002830182614e74565b5050600085815260066020526040812055613830600886613fd4565b506001600160601b0384161561388357600a805485919060009061385e9084906001600160601b0316615644565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b6001600160601b038316156138db5782600a600c8282829054906101000a90046001600160601b03166138b69190615644565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b5050915091565b6001600160a01b038116610ae757604051630fb532db60e11b815260040160405180910390fd5b6040805160208101909152600081526000829003613936575060408051602081019091526000815261273f565b63125fa26760e31b61394883856159cc565b6001600160e01b0319161461397057604051632923fee760e11b815260040160405180910390fd5b61397d82600481866159fc565b8101906110a49190615a26565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa826040516024016139c391511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b600046613a0781613fe0565b15613a755760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6f919061593f565b91505090565b4391505090565b60006110a48383614003565b600061273f825490565b60006110a48383614052565b336001600160a01b03821603613af65760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610ade565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613b5381613fe0565b15613c0b57610100836001600160401b0316613b6d6139fb565b613b779190615602565b1180613b935750613b866139fb565b836001600160401b031610155b15613ba15750600092915050565b6040516315a03d4160e11b81526001600160401b0384166004820152606490632b407a82906024015b602060405180830381865afa158015613be7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a4919061593f565b50506001600160401b03164090565b6000613c4e8360000151846020015185604001518660600151868860a001518960c001518a60e001518b610100015161407c565b60038360200151604051602001613c66929190615a71565b60408051601f1981840301815291905280516020909101209392505050565b60005a611388811015613c9757600080fd5b611388810390508460408204820311613caf57600080fd5b50823b613cbb57600080fd5b60008083516020850160008789f1949350505050565b600080613d146000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506142a792505050565b905060005a600c54613d34908890600160581b900463ffffffff166157c2565b613d3e9190615602565b613d489086615a85565b600c54909150600090613d6d90600160781b900463ffffffff1664e8d4a51000615a85565b90508415613db957600c548190606490600160b81b900460ff16613d9185876157c2565b613d9b9190615a85565b613da59190615ab2565b613daf91906157c2565b93505050506110a4565b600c548190606490613dd590600160b81b900460ff1682615ac6565b60ff16613d9185876157c2565b600080600080613df0614387565b9150915060008213613e18576040516321ea67b360e11b815260048101839052602401610ade565b6000613e5a6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506142a792505050565b9050600083825a600c54613e7c908d90600160581b900463ffffffff166157c2565b613e869190615602565b613e90908b615a85565b613e9a91906157c2565b613eac90670de0b6b3a7640000615a85565b613eb69190615ab2565b600c54909150600090613edf9063ffffffff600160981b8204811691600160781b900416615adf565b613ef49063ffffffff1664e8d4a51000615a85565b9050600085613f0b83670de0b6b3a7640000615a85565b613f159190615ab2565b905060008915613f5657600c548290606490613f3b90600160c01b900460ff1687615a85565b613f459190615ab2565b613f4f91906157c2565b9050613f96565b600c548290606490613f7290600160c01b900460ff1682615ac6565b613f7f9060ff1687615a85565b613f899190615ab2565b613f9391906157c2565b90505b6b033b2e3c9fd0803ce8000000811115613fc35760405163e80fa38160e01b815260040160405180910390fd5b9b949a509398505050505050505050565b60006110a48383614452565b600061a4b1821480613ff4575062066eed82145b8061273f57505062066eee1490565b600081815260018301602052604081205461404a5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561273f565b50600061273f565b6000826000018281548110614069576140696155d6565b9060005260206000200154905092915050565b6140858961454c565b6140d15760405162461bcd60e51b815260206004820152601a60248201527f7075626c6963206b6579206973206e6f74206f6e2063757276650000000000006044820152606401610ade565b6140da8861454c565b6141265760405162461bcd60e51b815260206004820152601560248201527f67616d6d61206973206e6f74206f6e20637572766500000000000000000000006044820152606401610ade565b61412f8361454c565b61417b5760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610ade565b6141848261454c565b6141d05760405162461bcd60e51b815260206004820152601c60248201527f73486173685769746e657373206973206e6f74206f6e206375727665000000006044820152606401610ade565b6141dc878a8887614625565b6142285760405162461bcd60e51b815260206004820152601960248201527f6164647228632a706b2b732a6729213d5f755769746e657373000000000000006044820152606401610ade565b60006142348a87614748565b90506000614247898b878b8689896147ac565b90506000614258838d8d8a866148d8565b9050808a146142995760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610ade565b505050505050505050505050565b6000466142b381613fe0565b156142f757606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613be7573d6000803e3d6000fd5b61430081614918565b1561437e5773420000000000000000000000000000000000000f6001600160a01b03166349948e0e84604051806080016040528060488152602001615c3c60489139604051602001614353929190615afc565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401613bca9190615772565b50600092915050565b600c5460035460408051633fabe5a360e21b81529051600093849367010000000000000090910463ffffffff169284926001600160a01b039092169163feaf968c9160048082019260a0929091908290030181865afa1580156143ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144129190615b45565b50919650909250505063ffffffff82161580159061443e57506144358142615602565b8263ffffffff16105b9250821561444c5760105493505b50509091565b6000818152600183016020526040812054801561453b576000614476600183615602565b855490915060009061448a90600190615602565b90508181146144ef5760008660000182815481106144aa576144aa6155d6565b90600052602060002001549050808760000184815481106144cd576144cd6155d6565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061450057614500615615565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061273f565b600091505061273f565b5092915050565b80516000906401000003d019116145a55760405162461bcd60e51b815260206004820152601260248201527f696e76616c696420782d6f7264696e61746500000000000000000000000000006044820152606401610ade565b60208201516401000003d019116145fe5760405162461bcd60e51b815260206004820152601260248201527f696e76616c696420792d6f7264696e61746500000000000000000000000000006044820152606401610ade565b60208201516401000003d01990800961461e8360005b602002015161495f565b1492915050565b60006001600160a01b03821661466b5760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b6044820152606401610ade565b60208401516000906001161561468257601c614685565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe19918203925060009190890987516040805160008082526020820180845287905260ff88169282019290925260608101929092526080820183905291925060019060a0016020604051602081039080840390855afa158015614720573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b614750614e92565b61477d6001848460405160200161476993929190615b95565b604051602081830303815290604052614983565b90505b6147898161454c565b61273f5780516040805160208101929092526147a59101614769565b9050614780565b6147b4614e92565b825186516401000003d01991829006919006036148135760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610ade565b61481e8789886149d0565b61486a5760405162461bcd60e51b815260206004820152601660248201527f4669727374206d756c20636865636b206661696c6564000000000000000000006044820152606401610ade565b6148758486856149d0565b6148c15760405162461bcd60e51b815260206004820152601760248201527f5365636f6e64206d756c20636865636b206661696c65640000000000000000006044820152606401610ade565b6148cc868484614afb565b98975050505050505050565b6000600286868685876040516020016148f696959493929190615bb6565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a82148061492a57506101a482145b80614937575062aa37dc82145b80614943575061210582145b80614950575062014a3382145b8061273f57505062014a341490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b61498b614e92565b61499482614bc2565b81526149a96149a4826000614614565b614bfd565b6020820181905260029006600103611fd5576020810180516401000003d019039052919050565b600082600003614a105760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b6044820152606401610ade565b83516020850151600090614a2690600290615c15565b15614a3257601c614a35565b601b5b9050600070014551231950b75fc4402da1732fc9bebe198387096040805160008082526020820180845281905260ff86169282019290925260608101869052608081018390529192509060019060a0016020604051602081039080840390855afa158015614aa7573d6000803e3d6000fd5b505050602060405103519050600086604051602001614ac69190615c29565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614b03614e92565b835160208086015185519186015160009384938493614b2493909190614c1d565b919450925090506401000003d019858209600114614b845760405162461bcd60e51b815260206004820152601960248201527f696e765a206d75737420626520696e7665727365206f66207a000000000000006044820152606401610ade565b60405180604001604052806401000003d01980614ba357614ba3615a9c565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d0198110611fd557604080516020808201939093528151808203840181529082019091528051910120614bca565b600061273f826002614c166401000003d01960016157c2565b901c614cfd565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000614c5d83838585614da2565b9098509050614c6e88828e88614dc6565b9098509050614c7f88828c87614dc6565b90985090506000614c928d878b85614dc6565b9098509050614ca388828686614da2565b9098509050614cb488828e89614dc6565b9098509050818114614ce9576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614ced565b8196505b5050505050509450945094915050565b600080614d08614eb0565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614d3a614ece565b60208160c0846005600019fa925082600003614d985760405162461bcd60e51b815260206004820152601260248201527f6269674d6f64457870206661696c7572652100000000000000000000000000006044820152606401610ade565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b828054828255906000526020600020908101928215614e64579160200282015b82811115614e6457825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614e2f565b50614e70929150614eec565b5090565b5080546000825590600052602060002090810190610ae79190614eec565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b80821115614e705760008155600101614eed565b6001600160a01b0381168114610ae757600080fd5b8035611fd581614f01565b600060208284031215614f3357600080fd5b81356110a481614f01565b806040810183101561273f57600080fd5b600060408284031215614f6157600080fd5b6110a48383614f3e565b60008060408385031215614f7e57600080fd5b823591506020830135614f9081614f01565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715614fd357614fd3614f9b565b60405290565b60405161012081016001600160401b0381118282101715614fd357614fd3614f9b565b604051601f8201601f191681016001600160401b038111828210171561502457615024614f9b565b604052919050565b600082601f83011261503d57600080fd5b604051604081018181106001600160401b038211171561505f5761505f614f9b565b806040525080604084018581111561507657600080fd5b845b81811015615090578035835260209283019201615078565b509195945050505050565b80356001600160401b0381168114611fd557600080fd5b803563ffffffff81168114611fd557600080fd5b600060c082840312156150d857600080fd5b6150e0614fb1565b90506150eb8261509b565b815260208083013581830152615103604084016150b2565b6040830152615114606084016150b2565b6060830152608083013561512781614f01565b608083015260a08301356001600160401b038082111561514657600080fd5b818501915085601f83011261515a57600080fd5b81358181111561516c5761516c614f9b565b61517e601f8201601f19168501614ffc565b9150808252868482850101111561519457600080fd5b80848401858401376000848284010152508060a085015250505092915050565b8015158114610ae757600080fd5b8035611fd5816151b4565b60008060008385036101e08112156151e457600080fd5b6101a0808212156151f457600080fd5b6151fc614fd9565b9150615208878761502c565b8252615217876040880161502c565b60208301526080860135604083015260a0860135606083015260c0860135608083015261524660e08701614f16565b60a083015261010061525a8882890161502c565b60c084015261526d88610140890161502c565b60e0840152610180870135908301529093508401356001600160401b0381111561529657600080fd5b6152a2868287016150c6565b9250506152b26101c085016151c2565b90509250925092565b6000602082840312156152cd57600080fd5b5035919050565b600080604083850312156152e757600080fd5b82356152f281614f01565b91506020830135614f9081614f01565b6000806060838503121561531557600080fd5b61531f8484614f3e565b915061532d6040840161509b565b90509250929050565b60006020828403121561534857600080fd5b81356001600160401b0381111561535e57600080fd5b820160c081850312156110a457600080fd5b6000806000806060858703121561538657600080fd5b843561539181614f01565b93506020850135925060408501356001600160401b03808211156153b457600080fd5b818701915087601f8301126153c857600080fd5b8135818111156153d757600080fd5b8860208285010111156153e957600080fd5b95989497505060200194505050565b803561ffff81168114611fd557600080fd5b803560ff81168114611fd557600080fd5b60008060008060008060008060006101208a8c03121561543a57600080fd5b6154438a6153f8565b985061545160208b016150b2565b975061545f60408b016150b2565b965061546d60608b016150b2565b955060808a0135945061548260a08b016150b2565b935061549060c08b016150b2565b925061549e60e08b0161540a565b91506154ad6101008b0161540a565b90509295985092959850929598565b600080604083850312156154cf57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b8381101561550e578151875295820195908201906001016154f2565b509495945050505050565b6020815260006110a460208301846154de565b60006040828403121561553e57600080fd5b6110a4838361502c565b600081518084526020808501945080840160005b8381101561550e5781516001600160a01b03168752958201959082019060010161555c565b60006001600160601b0380881683528087166020840152506001600160401b03851660408301526001600160a01b038416606083015260a060808301526155cb60a0830184615548565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561273f5761273f6155ec565b634e487b7160e01b600052603160045260246000fd5b60006001820161563d5761563d6155ec565b5060010190565b6001600160601b03828116828216039080821115614545576145456155ec565b60006001600160401b03808316818103615680576156806155ec565b6001019392505050565b60006001600160401b038216806156a3576156a36155ec565b6000190192915050565b6020815260ff8251166020820152602082015160408201526001600160a01b0360408301511660608201526000606083015160c060808401526156f360e0840182615548565b905060808401516001600160601b0380821660a08601528060a08701511660c086015250508091505092915050565b60005b8381101561573d578181015183820152602001615725565b50506000910152565b6000815180845261575e816020860160208601615722565b601f01601f19169290920160200192915050565b6020815260006110a46020830184615746565b60006020828403121561579757600080fd5b81516110a4816151b4565b6001600160601b03818116838216019080821115614545576145456155ec565b8082018082111561273f5761273f6155ec565b6000602082840312156157e757600080fd5b6110a4826153f8565b60006020828403121561580257600080fd5b6110a4826150b2565b6000808335601e1984360301811261582257600080fd5b8301803591506001600160401b0382111561583c57600080fd5b60200191503681900382131561585157600080fd5b9250929050565b878152866020820152856040820152600063ffffffff80871660608401528086166080840152506001600160a01b03841660a083015260e060c08301526158a260e0830184615746565b9998505050505050505050565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a08301526148cc60c0830184615746565b6001600160401b03818116838216019080821115614545576145456155ec565b8060005b6002811015612c7b578151845260209384019390910190600101615912565b6040810161273f828461590e565b60006020828403121561595157600080fd5b5051919050565b8781526001600160401b0387166020820152856040820152600063ffffffff80871660608401528086166080840152506001600160a01b03841660a083015260e060c08301526158a260e0830184615746565b8281526040602082015260006159c460408301846154de565b949350505050565b6001600160e01b031981358181169160048510156159f45780818660040360031b1b83161692505b505092915050565b60008085851115615a0c57600080fd5b83861115615a1957600080fd5b5050820193919092039150565b600060208284031215615a3857600080fd5b604051602081018181106001600160401b0382111715615a5a57615a5a614f9b565b6040528235615a68816151b4565b81529392505050565b828152606081016110a4602083018461590e565b808202811582820484141761273f5761273f6155ec565b634e487b7160e01b600052601260045260246000fd5b600082615ac157615ac1615a9c565b500490565b60ff818116838216019081111561273f5761273f6155ec565b63ffffffff828116828216039080821115614545576145456155ec565b60008351615b0e818460208801615722565b835190830190615b22818360208801615722565b01949350505050565b805169ffffffffffffffffffff81168114611fd557600080fd5b600080600080600060a08688031215615b5d57600080fd5b615b6686615b2b565b9450602086015193506040860151925060608601519150615b8960808701615b2b565b90509295509295909350565b838152615ba5602082018461590e565b606081019190915260800192915050565b868152615bc6602082018761590e565b615bd3606082018661590e565b615be060a082018561590e565b615bed60e082018461590e565b60609190911b6bffffffffffffffffffffffff19166101208201526101340195945050505050565b600082615c2457615c24615a9c565b500690565b615c33818361590e565b60400191905056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a", +} + +var VRFCoordinatorTestV25ABI = VRFCoordinatorTestV25MetaData.ABI + +var VRFCoordinatorTestV25Bin = VRFCoordinatorTestV25MetaData.Bin + +func DeployVRFCoordinatorTestV25(auth *bind.TransactOpts, backend bind.ContractBackend, blockhashStore common.Address) (common.Address, *types.Transaction, *VRFCoordinatorTestV25, error) { + parsed, err := VRFCoordinatorTestV25MetaData.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(VRFCoordinatorTestV25Bin), backend, blockhashStore) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &VRFCoordinatorTestV25{address: address, abi: *parsed, VRFCoordinatorTestV25Caller: VRFCoordinatorTestV25Caller{contract: contract}, VRFCoordinatorTestV25Transactor: VRFCoordinatorTestV25Transactor{contract: contract}, VRFCoordinatorTestV25Filterer: VRFCoordinatorTestV25Filterer{contract: contract}}, nil +} + +type VRFCoordinatorTestV25 struct { + address common.Address + abi abi.ABI + VRFCoordinatorTestV25Caller + VRFCoordinatorTestV25Transactor + VRFCoordinatorTestV25Filterer +} + +type VRFCoordinatorTestV25Caller struct { + contract *bind.BoundContract +} + +type VRFCoordinatorTestV25Transactor struct { + contract *bind.BoundContract +} + +type VRFCoordinatorTestV25Filterer struct { + contract *bind.BoundContract +} + +type VRFCoordinatorTestV25Session struct { + Contract *VRFCoordinatorTestV25 + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VRFCoordinatorTestV25CallerSession struct { + Contract *VRFCoordinatorTestV25Caller + CallOpts bind.CallOpts +} + +type VRFCoordinatorTestV25TransactorSession struct { + Contract *VRFCoordinatorTestV25Transactor + TransactOpts bind.TransactOpts +} + +type VRFCoordinatorTestV25Raw struct { + Contract *VRFCoordinatorTestV25 +} + +type VRFCoordinatorTestV25CallerRaw struct { + Contract *VRFCoordinatorTestV25Caller +} + +type VRFCoordinatorTestV25TransactorRaw struct { + Contract *VRFCoordinatorTestV25Transactor +} + +func NewVRFCoordinatorTestV25(address common.Address, backend bind.ContractBackend) (*VRFCoordinatorTestV25, error) { + abi, err := abi.JSON(strings.NewReader(VRFCoordinatorTestV25ABI)) + if err != nil { + return nil, err + } + contract, err := bindVRFCoordinatorTestV25(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25{address: address, abi: abi, VRFCoordinatorTestV25Caller: VRFCoordinatorTestV25Caller{contract: contract}, VRFCoordinatorTestV25Transactor: VRFCoordinatorTestV25Transactor{contract: contract}, VRFCoordinatorTestV25Filterer: VRFCoordinatorTestV25Filterer{contract: contract}}, nil +} + +func NewVRFCoordinatorTestV25Caller(address common.Address, caller bind.ContractCaller) (*VRFCoordinatorTestV25Caller, error) { + contract, err := bindVRFCoordinatorTestV25(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25Caller{contract: contract}, nil +} + +func NewVRFCoordinatorTestV25Transactor(address common.Address, transactor bind.ContractTransactor) (*VRFCoordinatorTestV25Transactor, error) { + contract, err := bindVRFCoordinatorTestV25(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25Transactor{contract: contract}, nil +} + +func NewVRFCoordinatorTestV25Filterer(address common.Address, filterer bind.ContractFilterer) (*VRFCoordinatorTestV25Filterer, error) { + contract, err := bindVRFCoordinatorTestV25(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25Filterer{contract: contract}, nil +} + +func bindVRFCoordinatorTestV25(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VRFCoordinatorTestV25MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFCoordinatorTestV25.Contract.VRFCoordinatorTestV25Caller.contract.Call(opts, result, method, params...) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.VRFCoordinatorTestV25Transactor.contract.Transfer(opts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.VRFCoordinatorTestV25Transactor.contract.Transact(opts, method, params...) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFCoordinatorTestV25.Contract.contract.Call(opts, result, method, params...) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.contract.Transfer(opts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.contract.Transact(opts, method, params...) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) BLOCKHASHSTORE(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "BLOCKHASH_STORE") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) BLOCKHASHSTORE() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.BLOCKHASHSTORE(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) BLOCKHASHSTORE() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.BLOCKHASHSTORE(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) LINK(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "LINK") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) LINK() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.LINK(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) LINK() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.LINK(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) LINKNATIVEFEED(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "LINK_NATIVE_FEED") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) LINKNATIVEFEED() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.LINKNATIVEFEED(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) LINKNATIVEFEED() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.LINKNATIVEFEED(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) MAXCONSUMERS(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "MAX_CONSUMERS") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) MAXCONSUMERS() (uint16, error) { + return _VRFCoordinatorTestV25.Contract.MAXCONSUMERS(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) MAXCONSUMERS() (uint16, error) { + return _VRFCoordinatorTestV25.Contract.MAXCONSUMERS(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) MAXNUMWORDS(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "MAX_NUM_WORDS") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) MAXNUMWORDS() (uint32, error) { + return _VRFCoordinatorTestV25.Contract.MAXNUMWORDS(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) MAXNUMWORDS() (uint32, error) { + return _VRFCoordinatorTestV25.Contract.MAXNUMWORDS(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) MAXREQUESTCONFIRMATIONS(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "MAX_REQUEST_CONFIRMATIONS") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) MAXREQUESTCONFIRMATIONS() (uint16, error) { + return _VRFCoordinatorTestV25.Contract.MAXREQUESTCONFIRMATIONS(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) MAXREQUESTCONFIRMATIONS() (uint16, error) { + return _VRFCoordinatorTestV25.Contract.MAXREQUESTCONFIRMATIONS(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) GetActiveSubscriptionIds(opts *bind.CallOpts, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "getActiveSubscriptionIds", startIndex, maxCount) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) GetActiveSubscriptionIds(startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.GetActiveSubscriptionIds(&_VRFCoordinatorTestV25.CallOpts, startIndex, maxCount) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) GetActiveSubscriptionIds(startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.GetActiveSubscriptionIds(&_VRFCoordinatorTestV25.CallOpts, startIndex, maxCount) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) GetSubscription(opts *bind.CallOpts, subId *big.Int) (GetSubscription, + + error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "getSubscription", subId) + + outstruct := new(GetSubscription) + if err != nil { + return *outstruct, err + } + + outstruct.Balance = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.NativeBalance = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.ReqCount = *abi.ConvertType(out[2], new(uint64)).(*uint64) + outstruct.SubOwner = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + outstruct.Consumers = *abi.ConvertType(out[4], new([]common.Address)).(*[]common.Address) + + return *outstruct, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) GetSubscription(subId *big.Int) (GetSubscription, + + error) { + return _VRFCoordinatorTestV25.Contract.GetSubscription(&_VRFCoordinatorTestV25.CallOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) GetSubscription(subId *big.Int) (GetSubscription, + + error) { + return _VRFCoordinatorTestV25.Contract.GetSubscription(&_VRFCoordinatorTestV25.CallOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) HashOfKey(opts *bind.CallOpts, publicKey [2]*big.Int) ([32]byte, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "hashOfKey", publicKey) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) HashOfKey(publicKey [2]*big.Int) ([32]byte, error) { + return _VRFCoordinatorTestV25.Contract.HashOfKey(&_VRFCoordinatorTestV25.CallOpts, publicKey) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) HashOfKey(publicKey [2]*big.Int) ([32]byte, error) { + return _VRFCoordinatorTestV25.Contract.HashOfKey(&_VRFCoordinatorTestV25.CallOpts, publicKey) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) Owner() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.Owner(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) Owner() (common.Address, error) { + return _VRFCoordinatorTestV25.Contract.Owner(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) PendingRequestExists(opts *bind.CallOpts, subId *big.Int) (bool, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "pendingRequestExists", subId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) PendingRequestExists(subId *big.Int) (bool, error) { + return _VRFCoordinatorTestV25.Contract.PendingRequestExists(&_VRFCoordinatorTestV25.CallOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) PendingRequestExists(subId *big.Int) (bool, error) { + return _VRFCoordinatorTestV25.Contract.PendingRequestExists(&_VRFCoordinatorTestV25.CallOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) SConfig(opts *bind.CallOpts) (SConfig, + + error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_config") + + outstruct := new(SConfig) + if err != nil { + return *outstruct, err + } + + outstruct.MinimumRequestConfirmations = *abi.ConvertType(out[0], new(uint16)).(*uint16) + outstruct.MaxGasLimit = *abi.ConvertType(out[1], new(uint32)).(*uint32) + outstruct.ReentrancyLock = *abi.ConvertType(out[2], new(bool)).(*bool) + outstruct.StalenessSeconds = *abi.ConvertType(out[3], new(uint32)).(*uint32) + outstruct.GasAfterPaymentCalculation = *abi.ConvertType(out[4], new(uint32)).(*uint32) + outstruct.FulfillmentFlatFeeNativePPM = *abi.ConvertType(out[5], new(uint32)).(*uint32) + outstruct.FulfillmentFlatFeeLinkDiscountPPM = *abi.ConvertType(out[6], new(uint32)).(*uint32) + outstruct.NativePremiumPercentage = *abi.ConvertType(out[7], new(uint8)).(*uint8) + outstruct.LinkPremiumPercentage = *abi.ConvertType(out[8], new(uint8)).(*uint8) + + return *outstruct, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SConfig() (SConfig, + + error) { + return _VRFCoordinatorTestV25.Contract.SConfig(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) SConfig() (SConfig, + + error) { + return _VRFCoordinatorTestV25.Contract.SConfig(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) SCurrentSubNonce(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_currentSubNonce") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SCurrentSubNonce() (uint64, error) { + return _VRFCoordinatorTestV25.Contract.SCurrentSubNonce(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) SCurrentSubNonce() (uint64, error) { + return _VRFCoordinatorTestV25.Contract.SCurrentSubNonce(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) SFallbackWeiPerUnitLink(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_fallbackWeiPerUnitLink") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SFallbackWeiPerUnitLink() (*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.SFallbackWeiPerUnitLink(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) SFallbackWeiPerUnitLink() (*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.SFallbackWeiPerUnitLink(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) SProvingKeyHashes(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_provingKeyHashes", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SProvingKeyHashes(arg0 *big.Int) ([32]byte, error) { + return _VRFCoordinatorTestV25.Contract.SProvingKeyHashes(&_VRFCoordinatorTestV25.CallOpts, arg0) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) SProvingKeyHashes(arg0 *big.Int) ([32]byte, error) { + return _VRFCoordinatorTestV25.Contract.SProvingKeyHashes(&_VRFCoordinatorTestV25.CallOpts, arg0) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (SProvingKeys, + + error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_provingKeys", arg0) + + outstruct := new(SProvingKeys) + if err != nil { + return *outstruct, err + } + + outstruct.Exists = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.MaxGas = *abi.ConvertType(out[1], new(uint64)).(*uint64) + + return *outstruct, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SProvingKeys(arg0 [32]byte) (SProvingKeys, + + error) { + return _VRFCoordinatorTestV25.Contract.SProvingKeys(&_VRFCoordinatorTestV25.CallOpts, arg0) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) SProvingKeys(arg0 [32]byte) (SProvingKeys, + + error) { + return _VRFCoordinatorTestV25.Contract.SProvingKeys(&_VRFCoordinatorTestV25.CallOpts, arg0) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) SRequestCommitments(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_requestCommitments", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SRequestCommitments(arg0 *big.Int) ([32]byte, error) { + return _VRFCoordinatorTestV25.Contract.SRequestCommitments(&_VRFCoordinatorTestV25.CallOpts, arg0) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) SRequestCommitments(arg0 *big.Int) ([32]byte, error) { + return _VRFCoordinatorTestV25.Contract.SRequestCommitments(&_VRFCoordinatorTestV25.CallOpts, arg0) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) STotalBalance(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_totalBalance") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) STotalBalance() (*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.STotalBalance(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) STotalBalance() (*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.STotalBalance(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Caller) STotalNativeBalance(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinatorTestV25.contract.Call(opts, &out, "s_totalNativeBalance") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) STotalNativeBalance() (*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.STotalNativeBalance(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25CallerSession) STotalNativeBalance() (*big.Int, error) { + return _VRFCoordinatorTestV25.Contract.STotalNativeBalance(&_VRFCoordinatorTestV25.CallOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "acceptOwnership") +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) AcceptOwnership() (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.AcceptOwnership(&_VRFCoordinatorTestV25.TransactOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.AcceptOwnership(&_VRFCoordinatorTestV25.TransactOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) AcceptSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "acceptSubscriptionOwnerTransfer", subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) AcceptSubscriptionOwnerTransfer(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.AcceptSubscriptionOwnerTransfer(&_VRFCoordinatorTestV25.TransactOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) AcceptSubscriptionOwnerTransfer(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.AcceptSubscriptionOwnerTransfer(&_VRFCoordinatorTestV25.TransactOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) AddConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "addConsumer", subId, consumer) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) AddConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.AddConsumer(&_VRFCoordinatorTestV25.TransactOpts, subId, consumer) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) AddConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.AddConsumer(&_VRFCoordinatorTestV25.TransactOpts, subId, consumer) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) CancelSubscription(opts *bind.TransactOpts, subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "cancelSubscription", subId, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) CancelSubscription(subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.CancelSubscription(&_VRFCoordinatorTestV25.TransactOpts, subId, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) CancelSubscription(subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.CancelSubscription(&_VRFCoordinatorTestV25.TransactOpts, subId, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "createSubscription") +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) CreateSubscription() (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.CreateSubscription(&_VRFCoordinatorTestV25.TransactOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) CreateSubscription() (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.CreateSubscription(&_VRFCoordinatorTestV25.TransactOpts) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) DeregisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "deregisterMigratableCoordinator", target) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) DeregisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.DeregisterMigratableCoordinator(&_VRFCoordinatorTestV25.TransactOpts, target) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) DeregisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.DeregisterMigratableCoordinator(&_VRFCoordinatorTestV25.TransactOpts, target) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) DeregisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "deregisterProvingKey", publicProvingKey) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) DeregisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.DeregisterProvingKey(&_VRFCoordinatorTestV25.TransactOpts, publicProvingKey) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) DeregisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.DeregisterProvingKey(&_VRFCoordinatorTestV25.TransactOpts, publicProvingKey) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) FulfillRandomWords(opts *bind.TransactOpts, proof VRFOldProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "fulfillRandomWords", proof, rc, onlyPremium) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) FulfillRandomWords(proof VRFOldProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.FulfillRandomWords(&_VRFCoordinatorTestV25.TransactOpts, proof, rc, onlyPremium) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) FulfillRandomWords(proof VRFOldProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.FulfillRandomWords(&_VRFCoordinatorTestV25.TransactOpts, proof, rc, onlyPremium) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) FundSubscriptionWithNative(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "fundSubscriptionWithNative", subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) FundSubscriptionWithNative(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.FundSubscriptionWithNative(&_VRFCoordinatorTestV25.TransactOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) FundSubscriptionWithNative(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.FundSubscriptionWithNative(&_VRFCoordinatorTestV25.TransactOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) Migrate(opts *bind.TransactOpts, subId *big.Int, newCoordinator common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "migrate", subId, newCoordinator) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) Migrate(subId *big.Int, newCoordinator common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.Migrate(&_VRFCoordinatorTestV25.TransactOpts, subId, newCoordinator) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) Migrate(subId *big.Int, newCoordinator common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.Migrate(&_VRFCoordinatorTestV25.TransactOpts, subId, newCoordinator) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "onTokenTransfer", arg0, amount, data) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) OnTokenTransfer(arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.OnTokenTransfer(&_VRFCoordinatorTestV25.TransactOpts, arg0, amount, data) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) OnTokenTransfer(arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.OnTokenTransfer(&_VRFCoordinatorTestV25.TransactOpts, arg0, amount, data) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) OwnerCancelSubscription(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "ownerCancelSubscription", subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) OwnerCancelSubscription(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.OwnerCancelSubscription(&_VRFCoordinatorTestV25.TransactOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) OwnerCancelSubscription(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.OwnerCancelSubscription(&_VRFCoordinatorTestV25.TransactOpts, subId) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RecoverFunds(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "recoverFunds", to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RecoverFunds(to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RecoverFunds(&_VRFCoordinatorTestV25.TransactOpts, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RecoverFunds(to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RecoverFunds(&_VRFCoordinatorTestV25.TransactOpts, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RecoverNativeFunds(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "recoverNativeFunds", to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RecoverNativeFunds(to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RecoverNativeFunds(&_VRFCoordinatorTestV25.TransactOpts, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RecoverNativeFunds(to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RecoverNativeFunds(&_VRFCoordinatorTestV25.TransactOpts, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "registerMigratableCoordinator", target) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RegisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RegisterMigratableCoordinator(&_VRFCoordinatorTestV25.TransactOpts, target) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RegisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RegisterMigratableCoordinator(&_VRFCoordinatorTestV25.TransactOpts, target) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "registerProvingKey", publicProvingKey, maxGas) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RegisterProvingKey(publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RegisterProvingKey(&_VRFCoordinatorTestV25.TransactOpts, publicProvingKey, maxGas) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RegisterProvingKey(publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RegisterProvingKey(&_VRFCoordinatorTestV25.TransactOpts, publicProvingKey, maxGas) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "removeConsumer", subId, consumer) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RemoveConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RemoveConsumer(&_VRFCoordinatorTestV25.TransactOpts, subId, consumer) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RemoveConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RemoveConsumer(&_VRFCoordinatorTestV25.TransactOpts, subId, consumer) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RequestRandomWords(opts *bind.TransactOpts, req VRFV2PlusClientRandomWordsRequest) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "requestRandomWords", req) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RequestRandomWords(req VRFV2PlusClientRandomWordsRequest) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RequestRandomWords(&_VRFCoordinatorTestV25.TransactOpts, req) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RequestRandomWords(req VRFV2PlusClientRandomWordsRequest) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RequestRandomWords(&_VRFCoordinatorTestV25.TransactOpts, req) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) RequestSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "requestSubscriptionOwnerTransfer", subId, newOwner) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) RequestSubscriptionOwnerTransfer(subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RequestSubscriptionOwnerTransfer(&_VRFCoordinatorTestV25.TransactOpts, subId, newOwner) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) RequestSubscriptionOwnerTransfer(subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.RequestSubscriptionOwnerTransfer(&_VRFCoordinatorTestV25.TransactOpts, subId, newOwner) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) SetConfig(opts *bind.TransactOpts, minimumRequestConfirmations uint16, maxGasLimit uint32, stalenessSeconds uint32, gasAfterPaymentCalculation uint32, fallbackWeiPerUnitLink *big.Int, fulfillmentFlatFeeNativePPM uint32, fulfillmentFlatFeeLinkDiscountPPM uint32, nativePremiumPercentage uint8, linkPremiumPercentage uint8) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "setConfig", minimumRequestConfirmations, maxGasLimit, stalenessSeconds, gasAfterPaymentCalculation, fallbackWeiPerUnitLink, fulfillmentFlatFeeNativePPM, fulfillmentFlatFeeLinkDiscountPPM, nativePremiumPercentage, linkPremiumPercentage) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SetConfig(minimumRequestConfirmations uint16, maxGasLimit uint32, stalenessSeconds uint32, gasAfterPaymentCalculation uint32, fallbackWeiPerUnitLink *big.Int, fulfillmentFlatFeeNativePPM uint32, fulfillmentFlatFeeLinkDiscountPPM uint32, nativePremiumPercentage uint8, linkPremiumPercentage uint8) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.SetConfig(&_VRFCoordinatorTestV25.TransactOpts, minimumRequestConfirmations, maxGasLimit, stalenessSeconds, gasAfterPaymentCalculation, fallbackWeiPerUnitLink, fulfillmentFlatFeeNativePPM, fulfillmentFlatFeeLinkDiscountPPM, nativePremiumPercentage, linkPremiumPercentage) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) SetConfig(minimumRequestConfirmations uint16, maxGasLimit uint32, stalenessSeconds uint32, gasAfterPaymentCalculation uint32, fallbackWeiPerUnitLink *big.Int, fulfillmentFlatFeeNativePPM uint32, fulfillmentFlatFeeLinkDiscountPPM uint32, nativePremiumPercentage uint8, linkPremiumPercentage uint8) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.SetConfig(&_VRFCoordinatorTestV25.TransactOpts, minimumRequestConfirmations, maxGasLimit, stalenessSeconds, gasAfterPaymentCalculation, fallbackWeiPerUnitLink, fulfillmentFlatFeeNativePPM, fulfillmentFlatFeeLinkDiscountPPM, nativePremiumPercentage, linkPremiumPercentage) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) SetLINKAndLINKNativeFeed(opts *bind.TransactOpts, link common.Address, linkNativeFeed common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "setLINKAndLINKNativeFeed", link, linkNativeFeed) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) SetLINKAndLINKNativeFeed(link common.Address, linkNativeFeed common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.SetLINKAndLINKNativeFeed(&_VRFCoordinatorTestV25.TransactOpts, link, linkNativeFeed) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) SetLINKAndLINKNativeFeed(link common.Address, linkNativeFeed common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.SetLINKAndLINKNativeFeed(&_VRFCoordinatorTestV25.TransactOpts, link, linkNativeFeed) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "transferOwnership", to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.TransferOwnership(&_VRFCoordinatorTestV25.TransactOpts, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.TransferOwnership(&_VRFCoordinatorTestV25.TransactOpts, to) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "withdraw", recipient) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) Withdraw(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.Withdraw(&_VRFCoordinatorTestV25.TransactOpts, recipient) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) Withdraw(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.Withdraw(&_VRFCoordinatorTestV25.TransactOpts, recipient) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Transactor) WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.contract.Transact(opts, "withdrawNative", recipient) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Session) WithdrawNative(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.WithdrawNative(&_VRFCoordinatorTestV25.TransactOpts, recipient) +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25TransactorSession) WithdrawNative(recipient common.Address) (*types.Transaction, error) { + return _VRFCoordinatorTestV25.Contract.WithdrawNative(&_VRFCoordinatorTestV25.TransactOpts, recipient) +} + +type VRFCoordinatorTestV25ConfigSetIterator struct { + Event *VRFCoordinatorTestV25ConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25ConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25ConfigSet) + 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(VRFCoordinatorTestV25ConfigSet) + 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 *VRFCoordinatorTestV25ConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25ConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25ConfigSet struct { + MinimumRequestConfirmations uint16 + MaxGasLimit uint32 + StalenessSeconds uint32 + GasAfterPaymentCalculation uint32 + FallbackWeiPerUnitLink *big.Int + FulfillmentFlatFeeNativePPM uint32 + FulfillmentFlatFeeLinkDiscountPPM uint32 + NativePremiumPercentage uint8 + LinkPremiumPercentage uint8 + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorTestV25ConfigSetIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25ConfigSetIterator{contract: _VRFCoordinatorTestV25.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25ConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.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(VRFCoordinatorTestV25ConfigSet) + if err := _VRFCoordinatorTestV25.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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseConfigSet(log types.Log) (*VRFCoordinatorTestV25ConfigSet, error) { + event := new(VRFCoordinatorTestV25ConfigSet) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25CoordinatorDeregisteredIterator struct { + Event *VRFCoordinatorTestV25CoordinatorDeregistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25CoordinatorDeregisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25CoordinatorDeregistered) + 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(VRFCoordinatorTestV25CoordinatorDeregistered) + 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 *VRFCoordinatorTestV25CoordinatorDeregisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25CoordinatorDeregisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25CoordinatorDeregistered struct { + CoordinatorAddress common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterCoordinatorDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25CoordinatorDeregisteredIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "CoordinatorDeregistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25CoordinatorDeregisteredIterator{contract: _VRFCoordinatorTestV25.contract, event: "CoordinatorDeregistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchCoordinatorDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25CoordinatorDeregistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "CoordinatorDeregistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25CoordinatorDeregistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "CoordinatorDeregistered", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseCoordinatorDeregistered(log types.Log) (*VRFCoordinatorTestV25CoordinatorDeregistered, error) { + event := new(VRFCoordinatorTestV25CoordinatorDeregistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "CoordinatorDeregistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25CoordinatorRegisteredIterator struct { + Event *VRFCoordinatorTestV25CoordinatorRegistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25CoordinatorRegisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25CoordinatorRegistered) + 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(VRFCoordinatorTestV25CoordinatorRegistered) + 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 *VRFCoordinatorTestV25CoordinatorRegisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25CoordinatorRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25CoordinatorRegistered struct { + CoordinatorAddress common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterCoordinatorRegistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25CoordinatorRegisteredIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "CoordinatorRegistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25CoordinatorRegisteredIterator{contract: _VRFCoordinatorTestV25.contract, event: "CoordinatorRegistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchCoordinatorRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25CoordinatorRegistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "CoordinatorRegistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25CoordinatorRegistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "CoordinatorRegistered", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorTestV25CoordinatorRegistered, error) { + event := new(VRFCoordinatorTestV25CoordinatorRegistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "CoordinatorRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator struct { + Event *VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) + 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(VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) + 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 *VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed struct { + RequestId *big.Int + FallbackWeiPerUnitLink *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterFallbackWeiPerUnitLinkUsed(opts *bind.FilterOpts) (*VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "FallbackWeiPerUnitLinkUsed") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator{contract: _VRFCoordinatorTestV25.contract, event: "FallbackWeiPerUnitLinkUsed", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchFallbackWeiPerUnitLinkUsed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "FallbackWeiPerUnitLinkUsed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "FallbackWeiPerUnitLinkUsed", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseFallbackWeiPerUnitLinkUsed(log types.Log) (*VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed, error) { + event := new(VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "FallbackWeiPerUnitLinkUsed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25FundsRecoveredIterator struct { + Event *VRFCoordinatorTestV25FundsRecovered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25FundsRecoveredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25FundsRecovered) + 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(VRFCoordinatorTestV25FundsRecovered) + 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 *VRFCoordinatorTestV25FundsRecoveredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25FundsRecoveredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25FundsRecovered struct { + To common.Address + Amount *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterFundsRecovered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25FundsRecoveredIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "FundsRecovered") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25FundsRecoveredIterator{contract: _VRFCoordinatorTestV25.contract, event: "FundsRecovered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchFundsRecovered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25FundsRecovered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "FundsRecovered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25FundsRecovered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "FundsRecovered", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseFundsRecovered(log types.Log) (*VRFCoordinatorTestV25FundsRecovered, error) { + event := new(VRFCoordinatorTestV25FundsRecovered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "FundsRecovered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25MigrationCompletedIterator struct { + Event *VRFCoordinatorTestV25MigrationCompleted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25MigrationCompletedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25MigrationCompleted) + 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(VRFCoordinatorTestV25MigrationCompleted) + 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 *VRFCoordinatorTestV25MigrationCompletedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25MigrationCompletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25MigrationCompleted struct { + NewCoordinator common.Address + SubId *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterMigrationCompleted(opts *bind.FilterOpts) (*VRFCoordinatorTestV25MigrationCompletedIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "MigrationCompleted") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25MigrationCompletedIterator{contract: _VRFCoordinatorTestV25.contract, event: "MigrationCompleted", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchMigrationCompleted(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25MigrationCompleted) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "MigrationCompleted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25MigrationCompleted) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "MigrationCompleted", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseMigrationCompleted(log types.Log) (*VRFCoordinatorTestV25MigrationCompleted, error) { + event := new(VRFCoordinatorTestV25MigrationCompleted) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "MigrationCompleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25NativeFundsRecoveredIterator struct { + Event *VRFCoordinatorTestV25NativeFundsRecovered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25NativeFundsRecoveredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25NativeFundsRecovered) + 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(VRFCoordinatorTestV25NativeFundsRecovered) + 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 *VRFCoordinatorTestV25NativeFundsRecoveredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25NativeFundsRecoveredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25NativeFundsRecovered struct { + To common.Address + Amount *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterNativeFundsRecovered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25NativeFundsRecoveredIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "NativeFundsRecovered") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25NativeFundsRecoveredIterator{contract: _VRFCoordinatorTestV25.contract, event: "NativeFundsRecovered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchNativeFundsRecovered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25NativeFundsRecovered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "NativeFundsRecovered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25NativeFundsRecovered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "NativeFundsRecovered", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseNativeFundsRecovered(log types.Log) (*VRFCoordinatorTestV25NativeFundsRecovered, error) { + event := new(VRFCoordinatorTestV25NativeFundsRecovered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "NativeFundsRecovered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25OwnershipTransferRequestedIterator struct { + Event *VRFCoordinatorTestV25OwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25OwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25OwnershipTransferRequested) + 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(VRFCoordinatorTestV25OwnershipTransferRequested) + 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 *VRFCoordinatorTestV25OwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25OwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25OwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorTestV25OwnershipTransferRequestedIterator, 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 := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25OwnershipTransferRequestedIterator{contract: _VRFCoordinatorTestV25.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25OwnershipTransferRequested, 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 := _VRFCoordinatorTestV25.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(VRFCoordinatorTestV25OwnershipTransferRequested) + if err := _VRFCoordinatorTestV25.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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseOwnershipTransferRequested(log types.Log) (*VRFCoordinatorTestV25OwnershipTransferRequested, error) { + event := new(VRFCoordinatorTestV25OwnershipTransferRequested) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25OwnershipTransferredIterator struct { + Event *VRFCoordinatorTestV25OwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25OwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25OwnershipTransferred) + 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(VRFCoordinatorTestV25OwnershipTransferred) + 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 *VRFCoordinatorTestV25OwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25OwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25OwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorTestV25OwnershipTransferredIterator, 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 := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25OwnershipTransferredIterator{contract: _VRFCoordinatorTestV25.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25OwnershipTransferred, 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 := _VRFCoordinatorTestV25.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(VRFCoordinatorTestV25OwnershipTransferred) + if err := _VRFCoordinatorTestV25.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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorTestV25OwnershipTransferred, error) { + event := new(VRFCoordinatorTestV25OwnershipTransferred) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25ProvingKeyDeregisteredIterator struct { + Event *VRFCoordinatorTestV25ProvingKeyDeregistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25ProvingKeyDeregisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25ProvingKeyDeregistered) + 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(VRFCoordinatorTestV25ProvingKeyDeregistered) + 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 *VRFCoordinatorTestV25ProvingKeyDeregisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25ProvingKeyDeregisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25ProvingKeyDeregistered struct { + KeyHash [32]byte + MaxGas uint64 + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterProvingKeyDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25ProvingKeyDeregisteredIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "ProvingKeyDeregistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25ProvingKeyDeregisteredIterator{contract: _VRFCoordinatorTestV25.contract, event: "ProvingKeyDeregistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchProvingKeyDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25ProvingKeyDeregistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "ProvingKeyDeregistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25ProvingKeyDeregistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "ProvingKeyDeregistered", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseProvingKeyDeregistered(log types.Log) (*VRFCoordinatorTestV25ProvingKeyDeregistered, error) { + event := new(VRFCoordinatorTestV25ProvingKeyDeregistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "ProvingKeyDeregistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25ProvingKeyRegisteredIterator struct { + Event *VRFCoordinatorTestV25ProvingKeyRegistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25ProvingKeyRegisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25ProvingKeyRegistered) + 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(VRFCoordinatorTestV25ProvingKeyRegistered) + 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 *VRFCoordinatorTestV25ProvingKeyRegisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25ProvingKeyRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25ProvingKeyRegistered struct { + KeyHash [32]byte + MaxGas uint64 + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterProvingKeyRegistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25ProvingKeyRegisteredIterator, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "ProvingKeyRegistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25ProvingKeyRegisteredIterator{contract: _VRFCoordinatorTestV25.contract, event: "ProvingKeyRegistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25ProvingKeyRegistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "ProvingKeyRegistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25ProvingKeyRegistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "ProvingKeyRegistered", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseProvingKeyRegistered(log types.Log) (*VRFCoordinatorTestV25ProvingKeyRegistered, error) { + event := new(VRFCoordinatorTestV25ProvingKeyRegistered) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "ProvingKeyRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25RandomWordsFulfilledIterator struct { + Event *VRFCoordinatorTestV25RandomWordsFulfilled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25RandomWordsFulfilledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25RandomWordsFulfilled) + 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(VRFCoordinatorTestV25RandomWordsFulfilled) + 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 *VRFCoordinatorTestV25RandomWordsFulfilledIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25RandomWordsFulfilledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25RandomWordsFulfilled struct { + RequestId *big.Int + OutputSeed *big.Int + SubId *big.Int + Payment *big.Int + NativePayment bool + Success bool + OnlyPremium bool + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestId []*big.Int, subId []*big.Int) (*VRFCoordinatorTestV25RandomWordsFulfilledIterator, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "RandomWordsFulfilled", requestIdRule, subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25RandomWordsFulfilledIterator{contract: _VRFCoordinatorTestV25.contract, event: "RandomWordsFulfilled", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25RandomWordsFulfilled, requestId []*big.Int, subId []*big.Int) (event.Subscription, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "RandomWordsFulfilled", requestIdRule, subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25RandomWordsFulfilled) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "RandomWordsFulfilled", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorTestV25RandomWordsFulfilled, error) { + event := new(VRFCoordinatorTestV25RandomWordsFulfilled) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25RandomWordsRequestedIterator struct { + Event *VRFCoordinatorTestV25RandomWordsRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25RandomWordsRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25RandomWordsRequested) + 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(VRFCoordinatorTestV25RandomWordsRequested) + 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 *VRFCoordinatorTestV25RandomWordsRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25RandomWordsRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25RandomWordsRequested struct { + KeyHash [32]byte + RequestId *big.Int + PreSeed *big.Int + SubId *big.Int + MinimumRequestConfirmations uint16 + CallbackGasLimit uint32 + NumWords uint32 + ExtraArgs []byte + Sender common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterRandomWordsRequested(opts *bind.FilterOpts, keyHash [][32]byte, subId []*big.Int, sender []common.Address) (*VRFCoordinatorTestV25RandomWordsRequestedIterator, error) { + + var keyHashRule []interface{} + for _, keyHashItem := range keyHash { + keyHashRule = append(keyHashRule, keyHashItem) + } + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "RandomWordsRequested", keyHashRule, subIdRule, senderRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25RandomWordsRequestedIterator{contract: _VRFCoordinatorTestV25.contract, event: "RandomWordsRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchRandomWordsRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25RandomWordsRequested, keyHash [][32]byte, subId []*big.Int, sender []common.Address) (event.Subscription, error) { + + var keyHashRule []interface{} + for _, keyHashItem := range keyHash { + keyHashRule = append(keyHashRule, keyHashItem) + } + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "RandomWordsRequested", keyHashRule, subIdRule, 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(VRFCoordinatorTestV25RandomWordsRequested) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "RandomWordsRequested", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseRandomWordsRequested(log types.Log) (*VRFCoordinatorTestV25RandomWordsRequested, error) { + event := new(VRFCoordinatorTestV25RandomWordsRequested) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "RandomWordsRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionCanceledIterator struct { + Event *VRFCoordinatorTestV25SubscriptionCanceled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionCanceledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionCanceled) + 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(VRFCoordinatorTestV25SubscriptionCanceled) + 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 *VRFCoordinatorTestV25SubscriptionCanceledIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionCanceledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionCanceled struct { + SubId *big.Int + To common.Address + AmountLink *big.Int + AmountNative *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionCanceled(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionCanceledIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionCanceled", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionCanceledIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionCanceled", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionCanceled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionCanceled, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionCanceled", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionCanceled) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionCanceled", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionCanceled(log types.Log) (*VRFCoordinatorTestV25SubscriptionCanceled, error) { + event := new(VRFCoordinatorTestV25SubscriptionCanceled) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionCanceled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionConsumerAddedIterator struct { + Event *VRFCoordinatorTestV25SubscriptionConsumerAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionConsumerAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionConsumerAdded) + 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(VRFCoordinatorTestV25SubscriptionConsumerAdded) + 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 *VRFCoordinatorTestV25SubscriptionConsumerAddedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionConsumerAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionConsumerAdded struct { + SubId *big.Int + Consumer common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionConsumerAdded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionConsumerAddedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionConsumerAdded", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionConsumerAddedIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionConsumerAdded", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionConsumerAdded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionConsumerAdded, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionConsumerAdded", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionConsumerAdded) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionConsumerAdded", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionConsumerAdded(log types.Log) (*VRFCoordinatorTestV25SubscriptionConsumerAdded, error) { + event := new(VRFCoordinatorTestV25SubscriptionConsumerAdded) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionConsumerAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator struct { + Event *VRFCoordinatorTestV25SubscriptionConsumerRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionConsumerRemoved) + 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(VRFCoordinatorTestV25SubscriptionConsumerRemoved) + 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 *VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionConsumerRemoved struct { + SubId *big.Int + Consumer common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionConsumerRemoved(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionConsumerRemoved", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionConsumerRemoved", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionConsumerRemoved(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionConsumerRemoved, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionConsumerRemoved", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionConsumerRemoved) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionConsumerRemoved", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionConsumerRemoved(log types.Log) (*VRFCoordinatorTestV25SubscriptionConsumerRemoved, error) { + event := new(VRFCoordinatorTestV25SubscriptionConsumerRemoved) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionConsumerRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionCreatedIterator struct { + Event *VRFCoordinatorTestV25SubscriptionCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionCreated) + 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(VRFCoordinatorTestV25SubscriptionCreated) + 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 *VRFCoordinatorTestV25SubscriptionCreatedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionCreated struct { + SubId *big.Int + Owner common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionCreated(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionCreatedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionCreated", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionCreatedIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionCreated", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionCreated(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionCreated, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionCreated", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionCreated) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionCreated", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionCreated(log types.Log) (*VRFCoordinatorTestV25SubscriptionCreated, error) { + event := new(VRFCoordinatorTestV25SubscriptionCreated) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionFundedIterator struct { + Event *VRFCoordinatorTestV25SubscriptionFunded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionFundedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionFunded) + 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(VRFCoordinatorTestV25SubscriptionFunded) + 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 *VRFCoordinatorTestV25SubscriptionFundedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionFundedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionFunded struct { + SubId *big.Int + OldBalance *big.Int + NewBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionFunded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionFundedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionFunded", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionFundedIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionFunded", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionFunded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionFunded, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionFunded", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionFunded) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionFunded", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionFunded(log types.Log) (*VRFCoordinatorTestV25SubscriptionFunded, error) { + event := new(VRFCoordinatorTestV25SubscriptionFunded) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionFunded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator struct { + Event *VRFCoordinatorTestV25SubscriptionFundedWithNative + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionFundedWithNative) + 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(VRFCoordinatorTestV25SubscriptionFundedWithNative) + 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 *VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionFundedWithNative struct { + SubId *big.Int + OldNativeBalance *big.Int + NewNativeBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionFundedWithNative(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionFundedWithNative", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionFundedWithNative", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionFundedWithNative(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionFundedWithNative, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionFundedWithNative", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionFundedWithNative) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionFundedWithNative", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionFundedWithNative(log types.Log) (*VRFCoordinatorTestV25SubscriptionFundedWithNative, error) { + event := new(VRFCoordinatorTestV25SubscriptionFundedWithNative) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionFundedWithNative", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator struct { + Event *VRFCoordinatorTestV25SubscriptionOwnerTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionOwnerTransferRequested) + 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(VRFCoordinatorTestV25SubscriptionOwnerTransferRequested) + 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 *VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionOwnerTransferRequested struct { + SubId *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionOwnerTransferRequested(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionOwnerTransferRequested", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionOwnerTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionOwnerTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionOwnerTransferRequested, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionOwnerTransferRequested", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionOwnerTransferRequested) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionOwnerTransferRequested", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionOwnerTransferRequested(log types.Log) (*VRFCoordinatorTestV25SubscriptionOwnerTransferRequested, error) { + event := new(VRFCoordinatorTestV25SubscriptionOwnerTransferRequested) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionOwnerTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator struct { + Event *VRFCoordinatorTestV25SubscriptionOwnerTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorTestV25SubscriptionOwnerTransferred) + 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(VRFCoordinatorTestV25SubscriptionOwnerTransferred) + 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 *VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorTestV25SubscriptionOwnerTransferred struct { + SubId *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) FilterSubscriptionOwnerTransferred(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.FilterLogs(opts, "SubscriptionOwnerTransferred", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator{contract: _VRFCoordinatorTestV25.contract, event: "SubscriptionOwnerTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) WatchSubscriptionOwnerTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionOwnerTransferred, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinatorTestV25.contract.WatchLogs(opts, "SubscriptionOwnerTransferred", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorTestV25SubscriptionOwnerTransferred) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionOwnerTransferred", 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 (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25Filterer) ParseSubscriptionOwnerTransferred(log types.Log) (*VRFCoordinatorTestV25SubscriptionOwnerTransferred, error) { + event := new(VRFCoordinatorTestV25SubscriptionOwnerTransferred) + if err := _VRFCoordinatorTestV25.contract.UnpackLog(event, "SubscriptionOwnerTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetSubscription struct { + Balance *big.Int + NativeBalance *big.Int + ReqCount uint64 + SubOwner common.Address + Consumers []common.Address +} +type SConfig struct { + MinimumRequestConfirmations uint16 + MaxGasLimit uint32 + ReentrancyLock bool + StalenessSeconds uint32 + GasAfterPaymentCalculation uint32 + FulfillmentFlatFeeNativePPM uint32 + FulfillmentFlatFeeLinkDiscountPPM uint32 + NativePremiumPercentage uint8 + LinkPremiumPercentage uint8 +} +type SProvingKeys struct { + Exists bool + MaxGas uint64 +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _VRFCoordinatorTestV25.abi.Events["ConfigSet"].ID: + return _VRFCoordinatorTestV25.ParseConfigSet(log) + case _VRFCoordinatorTestV25.abi.Events["CoordinatorDeregistered"].ID: + return _VRFCoordinatorTestV25.ParseCoordinatorDeregistered(log) + case _VRFCoordinatorTestV25.abi.Events["CoordinatorRegistered"].ID: + return _VRFCoordinatorTestV25.ParseCoordinatorRegistered(log) + case _VRFCoordinatorTestV25.abi.Events["FallbackWeiPerUnitLinkUsed"].ID: + return _VRFCoordinatorTestV25.ParseFallbackWeiPerUnitLinkUsed(log) + case _VRFCoordinatorTestV25.abi.Events["FundsRecovered"].ID: + return _VRFCoordinatorTestV25.ParseFundsRecovered(log) + case _VRFCoordinatorTestV25.abi.Events["MigrationCompleted"].ID: + return _VRFCoordinatorTestV25.ParseMigrationCompleted(log) + case _VRFCoordinatorTestV25.abi.Events["NativeFundsRecovered"].ID: + return _VRFCoordinatorTestV25.ParseNativeFundsRecovered(log) + case _VRFCoordinatorTestV25.abi.Events["OwnershipTransferRequested"].ID: + return _VRFCoordinatorTestV25.ParseOwnershipTransferRequested(log) + case _VRFCoordinatorTestV25.abi.Events["OwnershipTransferred"].ID: + return _VRFCoordinatorTestV25.ParseOwnershipTransferred(log) + case _VRFCoordinatorTestV25.abi.Events["ProvingKeyDeregistered"].ID: + return _VRFCoordinatorTestV25.ParseProvingKeyDeregistered(log) + case _VRFCoordinatorTestV25.abi.Events["ProvingKeyRegistered"].ID: + return _VRFCoordinatorTestV25.ParseProvingKeyRegistered(log) + case _VRFCoordinatorTestV25.abi.Events["RandomWordsFulfilled"].ID: + return _VRFCoordinatorTestV25.ParseRandomWordsFulfilled(log) + case _VRFCoordinatorTestV25.abi.Events["RandomWordsRequested"].ID: + return _VRFCoordinatorTestV25.ParseRandomWordsRequested(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionCanceled"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionCanceled(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionConsumerAdded"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionConsumerAdded(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionConsumerRemoved"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionConsumerRemoved(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionCreated"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionCreated(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionFunded"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionFunded(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionFundedWithNative"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionFundedWithNative(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionOwnerTransferRequested"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionOwnerTransferRequested(log) + case _VRFCoordinatorTestV25.abi.Events["SubscriptionOwnerTransferred"].ID: + return _VRFCoordinatorTestV25.ParseSubscriptionOwnerTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VRFCoordinatorTestV25ConfigSet) Topic() common.Hash { + return common.HexToHash("0x2c6b6b12413678366b05b145c5f00745bdd00e739131ab5de82484a50c9d78b6") +} + +func (VRFCoordinatorTestV25CoordinatorDeregistered) Topic() common.Hash { + return common.HexToHash("0xf80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af37") +} + +func (VRFCoordinatorTestV25CoordinatorRegistered) Topic() common.Hash { + return common.HexToHash("0xb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af01625") +} + +func (VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) Topic() common.Hash { + return common.HexToHash("0x6ca648a381f22ead7e37773d934e64885dcf861fbfbb26c40354cbf0c4662d1a") +} + +func (VRFCoordinatorTestV25FundsRecovered) Topic() common.Hash { + return common.HexToHash("0x59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600") +} + +func (VRFCoordinatorTestV25MigrationCompleted) Topic() common.Hash { + return common.HexToHash("0xd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187") +} + +func (VRFCoordinatorTestV25NativeFundsRecovered) Topic() common.Hash { + return common.HexToHash("0x4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c") +} + +func (VRFCoordinatorTestV25OwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VRFCoordinatorTestV25OwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VRFCoordinatorTestV25ProvingKeyDeregistered) Topic() common.Hash { + return common.HexToHash("0x9b6868e0eb737bcd72205360baa6bfd0ba4e4819a33ade2db384e8a8025639a5") +} + +func (VRFCoordinatorTestV25ProvingKeyRegistered) Topic() common.Hash { + return common.HexToHash("0x9b911b2c240bfbef3b6a8f7ed6ee321d1258bb2a3fe6becab52ac1cd3210afd3") +} + +func (VRFCoordinatorTestV25RandomWordsFulfilled) Topic() common.Hash { + return common.HexToHash("0xaeb4b4786571e184246d39587f659abf0e26f41f6a3358692250382c0cdb47b7") +} + +func (VRFCoordinatorTestV25RandomWordsRequested) Topic() common.Hash { + return common.HexToHash("0xeb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e") +} + +func (VRFCoordinatorTestV25SubscriptionCanceled) Topic() common.Hash { + return common.HexToHash("0x8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c4") +} + +func (VRFCoordinatorTestV25SubscriptionConsumerAdded) Topic() common.Hash { + return common.HexToHash("0x1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1") +} + +func (VRFCoordinatorTestV25SubscriptionConsumerRemoved) Topic() common.Hash { + return common.HexToHash("0x32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a7") +} + +func (VRFCoordinatorTestV25SubscriptionCreated) Topic() common.Hash { + return common.HexToHash("0x1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d") +} + +func (VRFCoordinatorTestV25SubscriptionFunded) Topic() common.Hash { + return common.HexToHash("0x1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a") +} + +func (VRFCoordinatorTestV25SubscriptionFundedWithNative) Topic() common.Hash { + return common.HexToHash("0x7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e902") +} + +func (VRFCoordinatorTestV25SubscriptionOwnerTransferRequested) Topic() common.Hash { + return common.HexToHash("0x21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a1") +} + +func (VRFCoordinatorTestV25SubscriptionOwnerTransferred) Topic() common.Hash { + return common.HexToHash("0xd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c9386") +} + +func (_VRFCoordinatorTestV25 *VRFCoordinatorTestV25) Address() common.Address { + return _VRFCoordinatorTestV25.address +} + +type VRFCoordinatorTestV25Interface interface { + BLOCKHASHSTORE(opts *bind.CallOpts) (common.Address, error) + + LINK(opts *bind.CallOpts) (common.Address, error) + + LINKNATIVEFEED(opts *bind.CallOpts) (common.Address, error) + + MAXCONSUMERS(opts *bind.CallOpts) (uint16, error) + + MAXNUMWORDS(opts *bind.CallOpts) (uint32, error) + + MAXREQUESTCONFIRMATIONS(opts *bind.CallOpts) (uint16, error) + + GetActiveSubscriptionIds(opts *bind.CallOpts, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) + + GetSubscription(opts *bind.CallOpts, subId *big.Int) (GetSubscription, + + error) + + HashOfKey(opts *bind.CallOpts, publicKey [2]*big.Int) ([32]byte, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + PendingRequestExists(opts *bind.CallOpts, subId *big.Int) (bool, error) + + SConfig(opts *bind.CallOpts) (SConfig, + + error) + + SCurrentSubNonce(opts *bind.CallOpts) (uint64, error) + + SFallbackWeiPerUnitLink(opts *bind.CallOpts) (*big.Int, error) + + SProvingKeyHashes(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) + + SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (SProvingKeys, + + error) + + SRequestCommitments(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) + + STotalBalance(opts *bind.CallOpts) (*big.Int, error) + + STotalNativeBalance(opts *bind.CallOpts) (*big.Int, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AcceptSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) + + AddConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) + + CancelSubscription(opts *bind.TransactOpts, subId *big.Int, to common.Address) (*types.Transaction, error) + + CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) + + DeregisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) + + DeregisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) + + FulfillRandomWords(opts *bind.TransactOpts, proof VRFOldProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) + + FundSubscriptionWithNative(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) + + Migrate(opts *bind.TransactOpts, subId *big.Int, newCoordinator common.Address) (*types.Transaction, error) + + OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + OwnerCancelSubscription(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) + + RecoverFunds(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + RecoverNativeFunds(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) + + RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) + + RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) + + RequestRandomWords(opts *bind.TransactOpts, req VRFV2PlusClientRandomWordsRequest) (*types.Transaction, error) + + RequestSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int, newOwner common.Address) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, minimumRequestConfirmations uint16, maxGasLimit uint32, stalenessSeconds uint32, gasAfterPaymentCalculation uint32, fallbackWeiPerUnitLink *big.Int, fulfillmentFlatFeeNativePPM uint32, fulfillmentFlatFeeLinkDiscountPPM uint32, nativePremiumPercentage uint8, linkPremiumPercentage uint8) (*types.Transaction, error) + + SetLINKAndLINKNativeFeed(opts *bind.TransactOpts, link common.Address, linkNativeFeed common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + Withdraw(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + + WithdrawNative(opts *bind.TransactOpts, recipient common.Address) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorTestV25ConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25ConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*VRFCoordinatorTestV25ConfigSet, error) + + FilterCoordinatorDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25CoordinatorDeregisteredIterator, error) + + WatchCoordinatorDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25CoordinatorDeregistered) (event.Subscription, error) + + ParseCoordinatorDeregistered(log types.Log) (*VRFCoordinatorTestV25CoordinatorDeregistered, error) + + FilterCoordinatorRegistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25CoordinatorRegisteredIterator, error) + + WatchCoordinatorRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25CoordinatorRegistered) (event.Subscription, error) + + ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorTestV25CoordinatorRegistered, error) + + FilterFallbackWeiPerUnitLinkUsed(opts *bind.FilterOpts) (*VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsedIterator, error) + + WatchFallbackWeiPerUnitLinkUsed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed) (event.Subscription, error) + + ParseFallbackWeiPerUnitLinkUsed(log types.Log) (*VRFCoordinatorTestV25FallbackWeiPerUnitLinkUsed, error) + + FilterFundsRecovered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25FundsRecoveredIterator, error) + + WatchFundsRecovered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25FundsRecovered) (event.Subscription, error) + + ParseFundsRecovered(log types.Log) (*VRFCoordinatorTestV25FundsRecovered, error) + + FilterMigrationCompleted(opts *bind.FilterOpts) (*VRFCoordinatorTestV25MigrationCompletedIterator, error) + + WatchMigrationCompleted(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25MigrationCompleted) (event.Subscription, error) + + ParseMigrationCompleted(log types.Log) (*VRFCoordinatorTestV25MigrationCompleted, error) + + FilterNativeFundsRecovered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25NativeFundsRecoveredIterator, error) + + WatchNativeFundsRecovered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25NativeFundsRecovered) (event.Subscription, error) + + ParseNativeFundsRecovered(log types.Log) (*VRFCoordinatorTestV25NativeFundsRecovered, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorTestV25OwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25OwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VRFCoordinatorTestV25OwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorTestV25OwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25OwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorTestV25OwnershipTransferred, error) + + FilterProvingKeyDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25ProvingKeyDeregisteredIterator, error) + + WatchProvingKeyDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25ProvingKeyDeregistered) (event.Subscription, error) + + ParseProvingKeyDeregistered(log types.Log) (*VRFCoordinatorTestV25ProvingKeyDeregistered, error) + + FilterProvingKeyRegistered(opts *bind.FilterOpts) (*VRFCoordinatorTestV25ProvingKeyRegisteredIterator, error) + + WatchProvingKeyRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25ProvingKeyRegistered) (event.Subscription, error) + + ParseProvingKeyRegistered(log types.Log) (*VRFCoordinatorTestV25ProvingKeyRegistered, error) + + FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestId []*big.Int, subId []*big.Int) (*VRFCoordinatorTestV25RandomWordsFulfilledIterator, error) + + WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25RandomWordsFulfilled, requestId []*big.Int, subId []*big.Int) (event.Subscription, error) + + ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorTestV25RandomWordsFulfilled, error) + + FilterRandomWordsRequested(opts *bind.FilterOpts, keyHash [][32]byte, subId []*big.Int, sender []common.Address) (*VRFCoordinatorTestV25RandomWordsRequestedIterator, error) + + WatchRandomWordsRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25RandomWordsRequested, keyHash [][32]byte, subId []*big.Int, sender []common.Address) (event.Subscription, error) + + ParseRandomWordsRequested(log types.Log) (*VRFCoordinatorTestV25RandomWordsRequested, error) + + FilterSubscriptionCanceled(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionCanceledIterator, error) + + WatchSubscriptionCanceled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionCanceled, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionCanceled(log types.Log) (*VRFCoordinatorTestV25SubscriptionCanceled, error) + + FilterSubscriptionConsumerAdded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionConsumerAddedIterator, error) + + WatchSubscriptionConsumerAdded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionConsumerAdded, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionConsumerAdded(log types.Log) (*VRFCoordinatorTestV25SubscriptionConsumerAdded, error) + + FilterSubscriptionConsumerRemoved(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionConsumerRemovedIterator, error) + + WatchSubscriptionConsumerRemoved(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionConsumerRemoved, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionConsumerRemoved(log types.Log) (*VRFCoordinatorTestV25SubscriptionConsumerRemoved, error) + + FilterSubscriptionCreated(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionCreatedIterator, error) + + WatchSubscriptionCreated(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionCreated, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionCreated(log types.Log) (*VRFCoordinatorTestV25SubscriptionCreated, error) + + FilterSubscriptionFunded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionFundedIterator, error) + + WatchSubscriptionFunded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionFunded, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionFunded(log types.Log) (*VRFCoordinatorTestV25SubscriptionFunded, error) + + FilterSubscriptionFundedWithNative(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionFundedWithNativeIterator, error) + + WatchSubscriptionFundedWithNative(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionFundedWithNative, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionFundedWithNative(log types.Log) (*VRFCoordinatorTestV25SubscriptionFundedWithNative, error) + + FilterSubscriptionOwnerTransferRequested(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionOwnerTransferRequestedIterator, error) + + WatchSubscriptionOwnerTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionOwnerTransferRequested, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionOwnerTransferRequested(log types.Log) (*VRFCoordinatorTestV25SubscriptionOwnerTransferRequested, error) + + FilterSubscriptionOwnerTransferred(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorTestV25SubscriptionOwnerTransferredIterator, error) + + WatchSubscriptionOwnerTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorTestV25SubscriptionOwnerTransferred, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionOwnerTransferred(log types.Log) (*VRFCoordinatorTestV25SubscriptionOwnerTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go b/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go index f38435143b9..87849c786f4 100644 --- a/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go +++ b/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go @@ -32,7 +32,7 @@ var ( var WETH9MetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"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\":[{\"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\":\"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: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610114565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610114565b506002805460ff1916601217905534801561006f57600080fd5b506101d3565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561010f57600081815260208120601f850160051c810160208610156100ec5750805b601f850160051c820191505b8181101561010b578281556001016100f8565b5050505b505050565b81516001600160401b0381111561012d5761012d610075565b6101418161013b845461008b565b846100c5565b602080601f831160018114610176576000841561015e5750858301515b600019600386901b1c1916600185901b17855561010b565b600085815260208120601f198616915b828110156101a557888601518255948401946001909101908401610186565b50858210156101c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61099c80620001e36000396000f3fe6080604052600436106100cb5760003560e01c806340c10f1911610074578063a9059cbb1161004e578063a9059cbb14610225578063d0e30db014610245578063dd62ed3e1461024d57600080fd5b806340c10f19146101c357806370a08231146101e357806395d89b411461021057600080fd5b806323b872dd116100a557806323b872dd146101575780632e1a7d4d14610177578063313ce5671461019757600080fd5b806306fdde03146100df578063095ea7b31461010a57806318160ddd1461013a57600080fd5b366100da576100d8610285565b005b600080fd5b3480156100eb57600080fd5b506100f46102e0565b6040516101019190610785565b60405180910390f35b34801561011657600080fd5b5061012a61012536600461081a565b61036e565b6040519015158152602001610101565b34801561014657600080fd5b50475b604051908152602001610101565b34801561016357600080fd5b5061012a610172366004610844565b6103e8565b34801561018357600080fd5b506100d8610192366004610880565b610649565b3480156101a357600080fd5b506002546101b19060ff1681565b60405160ff9091168152602001610101565b3480156101cf57600080fd5b506100d86101de36600461081a565b61071c565b3480156101ef57600080fd5b506101496101fe366004610899565b60036020526000908152604090205481565b34801561021c57600080fd5b506100f461075a565b34801561023157600080fd5b5061012a61024036600461081a565b610767565b6100d861077b565b34801561025957600080fd5b506101496102683660046108b4565b600460209081526000928352604080842090915290825290205481565b33600090815260036020526040812080543492906102a4908490610916565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102ed90610929565b80601f016020809104026020016040519081016040528092919081815260200182805461031990610929565b80156103665780601f1061033b57610100808354040283529160200191610366565b820191906000526020600020905b81548152906001019060200180831161034957829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103d69086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054821115610447576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104ad575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156105625773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561051c576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091528120805484929061055c90849061097c565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260408120805484929061059790849061097c565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080548492906105d1908490610916565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161063791815260200190565b60405180910390a35060019392505050565b33600090815260036020526040902054811115610692576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260036020526040812080548392906106b190849061097c565b9091555050604051339082156108fc029083906000818181858888f193505050501580156106e3573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290610751908490610916565b90915550505050565b600180546102ed90610929565b60006107743384846103e8565b9392505050565b610783610285565b565b600060208083528351808285015260005b818110156107b257858101830151858201604001528201610796565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461081557600080fd5b919050565b6000806040838503121561082d57600080fd5b610836836107f1565b946020939093013593505050565b60008060006060848603121561085957600080fd5b610862846107f1565b9250610870602085016107f1565b9150604084013590509250925092565b60006020828403121561089257600080fd5b5035919050565b6000602082840312156108ab57600080fd5b610774826107f1565b600080604083850312156108c757600080fd5b6108d0836107f1565b91506108de602084016107f1565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103e2576103e26108e7565b600181811c9082168061093d57607f821691505b602082108103610976577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103e2576103e26108e756fea164736f6c6343000813000a", + Bin: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610114565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610114565b506002805460ff1916601217905534801561006f57600080fd5b506101d3565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561010f57600081815260208120601f850160051c810160208610156100ec5750805b601f850160051c820191505b8181101561010b578281556001016100f8565b5050505b505050565b81516001600160401b0381111561012d5761012d610075565b6101418161013b845461008b565b846100c5565b602080601f831160018114610176576000841561015e5750858301515b600019600386901b1c1916600185901b17855561010b565b600085815260208120601f198616915b828110156101a557888601518255948401946001909101908401610186565b50858210156101c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6109b680620001e36000396000f3fe6080604052600436106100cb5760003560e01c806340c10f1911610074578063a9059cbb1161004e578063a9059cbb14610225578063d0e30db014610245578063dd62ed3e1461024d57600080fd5b806340c10f19146101c357806370a08231146101e357806395d89b411461021057600080fd5b806323b872dd116100a557806323b872dd146101575780632e1a7d4d14610177578063313ce5671461019757600080fd5b806306fdde03146100df578063095ea7b31461010a57806318160ddd1461013a57600080fd5b366100da576100d8610285565b005b600080fd5b3480156100eb57600080fd5b506100f46102e0565b604051610101919061079f565b60405180910390f35b34801561011657600080fd5b5061012a610125366004610834565b61036e565b6040519015158152602001610101565b34801561014657600080fd5b50475b604051908152602001610101565b34801561016357600080fd5b5061012a61017236600461085e565b6103e8565b34801561018357600080fd5b506100d861019236600461089a565b610649565b3480156101a357600080fd5b506002546101b19060ff1681565b60405160ff9091168152602001610101565b3480156101cf57600080fd5b506100d86101de366004610834565b610736565b3480156101ef57600080fd5b506101496101fe3660046108b3565b60036020526000908152604090205481565b34801561021c57600080fd5b506100f4610774565b34801561023157600080fd5b5061012a610240366004610834565b610781565b6100d8610795565b34801561025957600080fd5b506101496102683660046108ce565b600460209081526000928352604080842090915290825290205481565b33600090815260036020526040812080543492906102a4908490610930565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102ed90610943565b80601f016020809104026020016040519081016040528092919081815260200182805461031990610943565b80156103665780601f1061033b57610100808354040283529160200191610366565b820191906000526020600020905b81548152906001019060200180831161034957829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103d69086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054821115610447576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104ad575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156105625773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561051c576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091528120805484929061055c908490610996565b90915550505b73ffffffffffffffffffffffffffffffffffffffff841660009081526003602052604081208054849290610597908490610996565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080548492906105d1908490610930565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161063791815260200190565b60405180910390a35060019392505050565b33600090815260036020526040902054811115610692576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260036020526040812080548392906106b1908490610996565b909155505060405133908290600081818185875af1925050503d80600081146106f6576040519150601f19603f3d011682016040523d82523d6000602084013e6106fb565b606091505b50506040518281523391507f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805483929061076b908490610930565b90915550505050565b600180546102ed90610943565b600061078e3384846103e8565b9392505050565b61079d610285565b565b600060208083528351808285015260005b818110156107cc578581018301518582016040015282016107b0565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461082f57600080fd5b919050565b6000806040838503121561084757600080fd5b6108508361080b565b946020939093013593505050565b60008060006060848603121561087357600080fd5b61087c8461080b565b925061088a6020850161080b565b9150604084013590509250925092565b6000602082840312156108ac57600080fd5b5035919050565b6000602082840312156108c557600080fd5b61078e8261080b565b600080604083850312156108e157600080fd5b6108ea8361080b565b91506108f86020840161080b565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103e2576103e2610901565b600181811c9082168061095757607f821691505b602082108103610990577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103e2576103e261090156fea164736f6c6343000813000a", } var WETH9ABI = WETH9MetaData.ABI diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 3299989c582..0beae6fc42e 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,7 +1,7 @@ GETH_VERSION: 1.13.8 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 b76cf77e3e8200c5f292e93af3f620f68f207f83634aacaaee43d682701dfea3 +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 automation_compatible_utils: ../../contracts/solc/v0.8.19/AutomationCompatibleUtils/AutomationCompatibleUtils.abi ../../contracts/solc/v0.8.19/AutomationCompatibleUtils/AutomationCompatibleUtils.bin dfe88f4f40d124b8cb5f36a7e9f9328008ca57f7ec5d07a28d949d569d5f2834 @@ -12,10 +12,10 @@ automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistra automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 73b5cc3ece642abbf6f2a4c9188335b71404f4dd0ad10b761390b6397af6f1c8 automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f -automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin fbf6f6cf4e6858855ff5da847c3baa4859dd997cfae51f2fa0651e4fa15b92c9 -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 6bfe0f54fa7a587a83b6981ffdef28b3cb5e24cae1c95becdf59eed21147d289 -automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 -automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin f8f920a225fdb1e36948dd95bae3aa46ecc2b01fd113480e111960b5e5f95624 +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_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 @@ -23,8 +23,8 @@ batch_blockhash_store: ../../contracts/solc/v0.8.19/BatchBlockhashStore/BatchBlo batch_vrf_coordinator_v2: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/BatchVRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/BatchVRFCoordinatorV2.bin 4512f4313bc5c078215c9241a69045a2a3cfecd6adfcef2f13037183a2d71483 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 39dfce79330e921e5c169051b11c6e5ea15cd4db5a7b09c06aabbe9658148915 -chain_reader_tester: ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.abi ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.bin b207f9e6bf71e445a2664a602677011b87b80bf95c6352fd7869f1a9ddb08a5b +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 c25c1712046dfa691cafa58803e6fbfa163f325e6e3aabf0558f5a9d2ab1065e 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 @@ -35,7 +35,7 @@ gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageW i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 06cc87c122452f63fbe84f65329978f30281613be0caa261e53503d94763e921 i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c -i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa +i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 8ccb8fcfd1ae331a46b4469e1567c380e2a6d2bf21a9976d6c4c655a716aaa42 i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 i_log_automation: ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.bin 296beccb6af655d6fc3a6e676b244831cce2da6688d3afc4f21f8738ae59e03e keeper_consumer_performance_wrapper: ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.abi ../../contracts/solc/v0.8.16/KeeperConsumerPerformance/KeeperConsumerPerformance.bin eeda39f5d3e1c8ffa0fb6cd1803731b98a4bc262d41833458e3fe8b40933ae90 @@ -54,15 +54,15 @@ keeper_registry_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistry2_1/Keep 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 42426bbb83f96dfbe55fc576d6c65020eaeed690e2289cf99b0c4aa810a5f4ec +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 mock_ethusd_aggregator_wrapper: ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.abi ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.bin b9b361f502d2aad32311c60ca86b071de93a024ac488bcfa19725d368cd05d61 offchain_aggregator_wrapper: OffchainAggregator/OffchainAggregator.abi - 5c8d6562e94166d4790f1ee6e4321d359d9f7262e6c5452a712b1f1c896f45cf operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin 88e6baa5d9b255eea02616fbcb2cbe21a25ab46adeb6395f6289d169dec949ae operator_wrapper: ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin 23c3888eaa7259e6adf2153d09abae8f4b1987dc44200363faab1e65483f32d5 -optimism_module: ../../contracts/solc/v0.8.19/OptimismModule/OptimismModule.abi ../../contracts/solc/v0.8.19/OptimismModule/OptimismModule.bin a1f8ee97e12b1b2311db03b94dc52b91f3c2e9a2f8d554031a9c7b41e4432280 +optimism_module_v2: ../../contracts/solc/v0.8.19/OptimismModuleV2/OptimismModuleV2.abi ../../contracts/solc/v0.8.19/OptimismModuleV2/OptimismModuleV2.bin 6bc8f93d3a49b3fdecc169214565e6fe5690427860ca4f674818c611dd719502 perform_data_checker_wrapper: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73 -scroll_module: ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.abi ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.bin 8de157cb7e5bc78146548212803d60926c8483aca7e912d802b7c66dc5d2ab11 +scroll_module: ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.abi ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.bin 0b99b89ff0c8d95a2ab273c93355e572b9e052ce2a9507498a06e0915b541a86 simple_log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin 7557d117a066cd8cf35f635bc085ee11795442073c18f8610ede9037b74fd814 solidity_vrf_consumer_interface_v08: ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.bin b14f9136b15e3dc9d6154d5700f3ed4cf88ddc4f70f20c3bb57fc46050904c8f solidity_vrf_request_id_v08: ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin f2559015d6f3e5d285c57b011be9b2300632e93dd6c4524e58202d6200f09edc @@ -82,6 +82,7 @@ vrf_consumer_v2_plus_upgradeable_example: ../../contracts/solc/v0.8.19/VRFConsum vrf_consumer_v2_upgradeable_example: ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.abi ../../contracts/solc/v0.8.6/VRFConsumerV2UpgradeableExample/VRFConsumerV2UpgradeableExample.bin f1790a9a2f2a04c730593e483459709cb89e897f8a19d7a3ac0cfe6a97265e6e vrf_coordinator_mock: ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.abi ../../contracts/solc/v0.8.6/VRFCoordinatorMock/VRFCoordinatorMock.bin 5c495cf8df1f46d8736b9150cdf174cce358cb8352f60f0d5bb9581e23920501 vrf_coordinator_test_v2: ../../contracts/solc/v0.8.6/VRFCoordinatorTestV2/VRFCoordinatorTestV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorTestV2/VRFCoordinatorTestV2.bin ff6c0056c6181ea75f667beed21ff4610f417dd50ceabf2dec8fa42e84851f50 +vrf_coordinator_test_v2_5: ../../contracts/solc/v0.8.19/VRFCoordinatorTestV2_5/VRFCoordinatorTestV2_5.abi ../../contracts/solc/v0.8.19/VRFCoordinatorTestV2_5/VRFCoordinatorTestV2_5.bin ab793e7d72b2d10d5c80b5358ca98caf5ff8a8686700735b198ed811272d7910 vrf_coordinator_v2: ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.abi ../../contracts/solc/v0.8.6/VRFCoordinatorV2/VRFCoordinatorV2.bin 156fbbc19489383901087c2076648ccd343bcd9a332f1ad25974da834c5be961 vrf_coordinator_v2_5: ../../contracts/solc/v0.8.19/VRFCoordinatorV2_5/VRFCoordinatorV2_5.abi ../../contracts/solc/v0.8.19/VRFCoordinatorV2_5/VRFCoordinatorV2_5.bin 3c766dbdefcc895ad475de96c65b6c48c868b8dc889ee750bba6711b1e5ec41d vrf_coordinator_v2_5_arbitrum: ../../contracts/solc/v0.8.19/VRFCoordinatorV2_5_Arbitrum/VRFCoordinatorV2_5_Arbitrum.abi ../../contracts/solc/v0.8.19/VRFCoordinatorV2_5_Arbitrum/VRFCoordinatorV2_5_Arbitrum.bin 1a2431ee76e307b45f683c439d08b9096a08f08aaf9ca132ea5b36b409962abe @@ -121,4 +122,4 @@ vrfv2plus_wrapper_arbitrum: ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Arbitr vrfv2plus_wrapper_consumer_example: ../../contracts/solc/v0.8.19/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.bin aeb0c681fa264f90971f65cba1e8d41064948070b217c8204a80ac95e1fa2294 vrfv2plus_wrapper_load_test_consumer: ../../contracts/solc/v0.8.19/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.bin 5ca0223d3f6f6073ddfee4f9ddca13ea5f87297eb5f800359d7a1c41d04b6776 vrfv2plus_wrapper_optimism: ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Optimism/VRFV2PlusWrapper_Optimism.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Optimism/VRFV2PlusWrapper_Optimism.bin 12a8c7a96716a5472a8ca712b10ab631085d4f5eb17bd5f7e0d2412556058ce9 -weth9_wrapper: ../../contracts/solc/v0.8.19/WETH9/WETH9.abi ../../contracts/solc/v0.8.19/WETH9/WETH9.bin 7f600a1de0c02a071cb13bcf9eb1dbf11c3e3eccd1e78ed4b4ecb2960f2bb020 +weth9_wrapper: ../../contracts/solc/v0.8.19/WETH9/WETH9.abi ../../contracts/solc/v0.8.19/WETH9/WETH9.bin 393b7b1ea2d1dc5a520a60cc6736dc489726cb0bd1481ea8b22d2872d4a510b1 diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index 95485faf4bb..32db02f2bf7 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -53,7 +53,7 @@ package gethwrappers //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.abi ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.bin AutomationUtils automation_utils_2_3 //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/ArbitrumModule/ArbitrumModule.abi ../../contracts/solc/v0.8.19/ArbitrumModule/ArbitrumModule.bin ArbitrumModule arbitrum_module //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.abi ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.bin ChainModuleBase chain_module_base -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/OptimismModule/OptimismModule.abi ../../contracts/solc/v0.8.19/OptimismModule/OptimismModule.bin OptimismModule optimism_module +//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/OptimismModuleV2/OptimismModuleV2.abi ../../contracts/solc/v0.8.19/OptimismModuleV2/OptimismModuleV2.bin OptimismModuleV2 optimism_module_v2 //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.abi ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.bin ScrollModule scroll_module //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin IChainModule i_chain_module //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin IAutomationV21PlusCommon i_automation_v21_plus_common @@ -143,6 +143,7 @@ package gethwrappers //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/VRFCoordinatorV2_5_Optimism/VRFCoordinatorV2_5_Optimism.abi ../../contracts/solc/v0.8.19/VRFCoordinatorV2_5_Optimism/VRFCoordinatorV2_5_Optimism.bin VRFCoordinatorV2_5_Optimism vrf_coordinator_v2_5_optimism //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Arbitrum/VRFV2PlusWrapper_Arbitrum.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Arbitrum/VRFV2PlusWrapper_Arbitrum.bin VRFV2PlusWrapper_Arbitrum vrfv2plus_wrapper_arbitrum //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Optimism/VRFV2PlusWrapper_Optimism.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapper_Optimism/VRFV2PlusWrapper_Optimism.bin VRFV2PlusWrapper_Optimism vrfv2plus_wrapper_optimism +//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/VRFCoordinatorTestV2_5/VRFCoordinatorTestV2_5.abi ../../contracts/solc/v0.8.19/VRFCoordinatorTestV2_5/VRFCoordinatorTestV2_5.bin VRFCoordinatorTestV2_5 vrf_coordinator_test_v2_5 // 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 diff --git a/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go b/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go index 9245f2c7386..91358b134ac 100644 --- a/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go +++ b/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go @@ -63,16 +63,6 @@ type CapabilitiesRegistryDONInfo struct { CapabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration } -type CapabilitiesRegistryNodeInfo struct { - NodeOperatorId uint32 - ConfigCount uint32 - WorkflowDONId uint32 - Signer [32]byte - P2pId [32]byte - HashedCapabilityIds [][32]byte - CapabilitiesDONIds []*big.Int -} - type CapabilitiesRegistryNodeOperator struct { Admin common.Address Name string @@ -82,12 +72,24 @@ 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\":[],\"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\":false,\"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\":\"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\":[{\"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\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structCapabilitiesRegistry.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\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structCapabilitiesRegistry.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\":\"pure\",\"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\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6150e080620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635d83d967116100ee57806386fa424611610097578063d8bc7b6811610071578063d8bc7b68146103f6578063ddbe4f8214610409578063e29581aa1461041e578063f2fde38b1461043357600080fd5b806386fa42461461039b5780638da5cb5b146103ae5780639cb7c5f4146103d657600080fd5b8063715f5295116100c8578063715f52951461036d57806373ac22b41461038057806379ba50971461039357600080fd5b80635d83d967146103325780635e65e3091461034557806366acaa331461035857600080fd5b8063235374051161015b5780632c01a1e8116101355780632c01a1e8146102cb578063398f3773146102de5780633f2a13c9146102f157806350c946fe1461031257600080fd5b80632353740514610285578063275459f2146102a55780632a852933146102b857600080fd5b80631d05394c1161018c5780631d05394c1461023b578063214502431461025057806322bdbcbc1461026557600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613ea3565b610446565b6040519081526020015b60405180910390f35b6101ec6101e7366004613f07565b61047a565b60405190151581526020016101d0565b604080518082018252601a81527f4361706162696c6974696573526567697374727920312e302e30000000000000602082015290516101d09190613f8e565b61024e610249366004613fe6565b610487565b005b61025861069c565b6040516101d09190614168565b610278610273366004614203565b6107f9565b6040516101d0919061425b565b610298610293366004614203565b6108e6565b6040516101d0919061426e565b61024e6102b3366004613fe6565b61092a565b61024e6102c63660046142a0565b610a01565b61024e6102d9366004613fe6565b610ae1565b61024e6102ec366004613fe6565b610d7d565b6103046102ff366004614343565b610f3c565b6040516101d092919061436d565b610325610320366004613f07565b611128565b6040516101d09190614432565b61024e610340366004613fe6565b611202565b61024e610353366004613fe6565b6112f7565b610360611a1f565b6040516101d09190614445565b61024e61037b366004613fe6565b611c02565b61024e61038e366004613fe6565b611cb4565b61024e612182565b61024e6103a93660046144ba565b61227f565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6103e96103e4366004613f07565b6125bf565b6040516101d09190614609565b61024e61040436600461461c565b6127fa565b6104116128c4565b6040516101d091906146a5565b6104266129b8565b6040516101d0919061471a565b61024e6104413660046147b3565b612ac1565b6000828260405160200161045b92919061436d565b6040516020818303038152906040528051906020012090505b92915050565b6000610474600583612ad5565b61048f612af0565b60005b818110156106975760008383838181106104ae576104ae6147ce565b90506020020160208101906104c39190614203565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61051b83612b73565b8110156105bb57811561057157600c60006105368584612b7d565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556105b3565b6105b18663ffffffff16600c60006105928588612b7d90919063ffffffff16565b8152602001908152602001600020600401612b8990919063ffffffff16565b505b600101610512565b508354640100000000900463ffffffff16600003610612576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff861660048201526024015b60405180910390fd5b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a15050505050806001019050610492565b505050565b600e54606090640100000000900463ffffffff1660006106bd60018361482c565b63ffffffff1667ffffffffffffffff8111156106db576106db613d3d565b60405190808252806020026020018201604052801561076257816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106f95790505b509050600060015b8363ffffffff168163ffffffff1610156107d65763ffffffff8082166000908152600d602052604090205416156107ce576107a481612b95565b8383815181106107b6576107b66147ce565b6020026020010181905250816107cb90614849565b91505b60010161076a565b506107e260018461482c565b63ffffffff1681146107f2578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161085d90614881565b80601f016020809104026020016040519081016040528092919081815260200182805461088990614881565b80156108d65780601f106108ab576101008083540402835291602001916108d6565b820191906000526020600020905b8154815290600101906020018083116108b957829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261047482612b95565b610932612af0565b60005b63ffffffff811682111561069757600083838363ffffffff1681811061095d5761095d6147ce565b90506020020160208101906109729190614203565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559192506109bd6001830182613cd0565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a2506109fa816148d4565b9050610935565b610a09612af0565b63ffffffff8088166000908152600d60205260408120805490926401000000009091041690819003610a6f576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610609565b610ad6888888886040518060a001604052808f63ffffffff16815260200187610a97906148d4565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b166060909201919091529650612e60565b505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610d77576000848483818110610b1b57610b1b6147ce565b602090810292909201356000818152600c90935260409092206001810154929350919050610b78576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610609565b6000610b8682600401612b73565b1115610bdb57610b996004820184612b7d565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610609565b805468010000000000000000900463ffffffff1615610c435780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610609565b83158015610c7d5750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610cb6576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6001810154610cc790600790612b89565b506002810154610cd990600990612b89565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815560018101829055600281018290559060048201818181610d2e8282613d0a565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610d6591815260200190565b60405180910390a15050600101610aff565b50505050565b610d85612af0565b60005b81811015610697576000838383818110610da457610da46147ce565b9050602002810190610db691906148f7565b610dbf90614935565b805190915073ffffffffffffffffffffffffffffffffffffffff16610e10576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610e9c90826149ef565b5050600e8054909150600090610eb79063ffffffff166148d4565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610f2a9190613f8e565b60405180910390a35050600101610d88565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610f8e90614881565b80601f0160208091040260200160405190810160405280929190818152602001828054610fba90614881565b80156110075780601f10610fdc57610100808354040283529160200191611007565b820191906000526020600020905b815481529060010190602001808311610fea57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff1615915061111a905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa1580156110d1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111179190810190614b09565b90505b9093509150505b9250929050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c08101919091526040805160e0810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152835260030190529190912060a08201906111d790613685565b81526020016111fa600c6000868152602001908152602001600020600401613685565b905292915050565b61120a612af0565b60005b81811015610697576000838383818110611229576112296147ce565b905060200201359050611246816003612ad590919063ffffffff16565b61127f576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b61128a600582613692565b6112c3576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a25060010161120d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610d77576000848483818110611331576113316147ce565b90506020028101906113439190614b77565b61134c90614bab565b6040808201516000908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff16855260018101805496975091959394939092840191906113b190614881565b80601f01602080910402602001604051908101604052809291908181526020018280546113dd90614881565b801561142a5780601f106113ff5761010080835404028352916020019161142a565b820191906000526020600020905b81548152906001019060200180831161140d57829003601f168201915b50505091909252505050600183015490915061147a5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b8415801561149f5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156114d8576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6020830151611513576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018201546020840151811461159457602084015161153490600790612ad5565b1561156b576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208401516001840155611580600782612b89565b50602084015161159290600790613692565b505b606084015180516000036115d657806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c7e565b835460009085906004906115f790640100000000900463ffffffff166148d4565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b82518110156116dc5761164f838281518110611637576116376147ce565b60200260200101516003612ad590919063ffffffff16565b61168757826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c7e565b6116d383828151811061169c5761169c6147ce565b60200260200101518760030160008563ffffffff1663ffffffff16815260200190815260200160002061369290919063ffffffff16565b50600101611619565b50845468010000000000000000900463ffffffff16801561183d5763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561177157602002820191906000526020600020905b81548152602001906001019080831161175d575b5050505050905060005b815181101561183a576117d0828281518110611799576117996147ce565b60200260200101518960030160008763ffffffff1663ffffffff168152602001908152602001600020612ad590919063ffffffff16565b611832578181815181106117e6576117e66147ce565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060992919091825263ffffffff16602082015260400190565b60010161177b565b50505b600061184b87600401613685565b905060005b81518163ffffffff161015611991576000828263ffffffff1681518110611879576118796147ce565b60209081029190910181015163ffffffff8082166000908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561190057602002820191906000526020600020905b8154815260200190600101908083116118ec575b5050505050905060005b815181101561197d5761195f828281518110611928576119286147ce565b60200260200101518c60030160008a63ffffffff1663ffffffff168152602001908152602001600020612ad590919063ffffffff16565b611975578181815181106117e6576117e66147ce565b60010161190a565b5050508061198a906148d4565b9050611850565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a018190556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050611315565b600e5460609063ffffffff166000611a3860018361482c565b63ffffffff1667ffffffffffffffff811115611a5657611a56613d3d565b604051908082528060200260200182016040528015611a9c57816020015b604080518082019091526000815260606020820152815260200190600190039081611a745790505b509050600060015b8363ffffffff168163ffffffff161015611bec5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611be45763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611b3890614881565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6490614881565b8015611bb15780601f10611b8657610100808354040283529160200191611bb1565b820191906000526020600020905b815481529060010190602001808311611b9457829003601f168201915b505050505081525050838381518110611bcc57611bcc6147ce565b602002602001018190525081611be190614849565b91505b600101611aa4565b50600e546107e29060019063ffffffff1661482c565b611c0a612af0565b60005b81811015610697576000838383818110611c2957611c296147ce565b9050602002810190611c3b9190614cc2565b611c4490614d05565b90506000611c5a82600001518360200151610446565b9050611c67600382613692565b611ca0576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b611caa818361369e565b5050600101611c0d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610d77576000848483818110611cee57611cee6147ce565b9050602002810190611d009190614b77565b611d0990614bab565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191611d5f90614881565b80601f0160208091040260200160405190810160405280929190818152602001828054611d8b90614881565b8015611dd85780601f10611dad57610100808354040283529160200191611dd8565b820191906000526020600020905b815481529060010190602001808311611dbb57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611e3e5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610609565b83158015611e635750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611e9c576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6040808301516000908152600c60205220600181015415611ef15782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b6040830151611f345782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b60208301511580611f5157506020830151611f5190600790612ad5565b15611f88576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611fca57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c7e565b81548290600490611fe890640100000000900463ffffffff166148d4565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b82518110156120be57612031838281518110611637576116376147ce565b61206957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c7e565b6120b583828151811061207e5761207e6147ce565b60200260200101518560030160008563ffffffff1663ffffffff16815260200190815260200160002061369290919063ffffffff16565b50600101612013565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff91821617845560408601516002850155602086015160018501819055612114916007919061369216565b50604085015161212690600990613692565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611cd2565b60015473ffffffffffffffffffffffffffffffffffffffff163314612203576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610609565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b8281146122c2576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610609565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156125b75760008686838181106122fa576122fa6147ce565b905060200201602081019061230f9190614203565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661237e576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610609565b6000868685818110612392576123926147ce565b90506020028101906123a491906148f7565b6123ad90614935565b805190915073ffffffffffffffffffffffffffffffffffffffff166123fe576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff16331480159061243b57503373ffffffffffffffffffffffffffffffffffffffff861614155b15612474576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b8051825473ffffffffffffffffffffffffffffffffffffffff90811691161415806124f057506020808201516040516124ad9201613f8e565b60405160208183030381529060405280519060200120826001016040516020016124d79190614dab565b6040516020818303038152906040528051906020012014155b156125a957805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020810151600183019061254a90826149ef565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516125a09190613f8e565b60405180910390a35b5050508060010190506122de565b505050505050565b6126006040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e0810182528381526000848152600260209081529290208054919283019161262c90614881565b80601f016020809104026020016040519081016040528092919081815260200182805461265890614881565b80156126a55780601f1061267a576101008083540402835291602001916126a5565b820191906000526020600020905b81548152906001019060200180831161268857829003601f168201915b505050505081526020016002600085815260200190815260200160002060010180546126d090614881565b80601f01602080910402602001604051908101604052809291908181526020018280546126fc90614881565b80156127495780601f1061271e57610100808354040283529160200191612749565b820191906000526020600020905b81548152906001019060200180831161272c57829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff16600381111561277b5761277b614526565b815260008481526002602081815260409092200154910190610100900460ff1660018111156127ac576127ac614526565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff1690830152016127f0600585612ad5565b1515905292915050565b612802612af0565b600e805460009164010000000090910463ffffffff16906004612824836148d4565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff841660808201529091506128ba908990899089908990612e60565b5050505050505050565b606060006128d26003613685565b90506000815167ffffffffffffffff8111156128f0576128f0613d3d565b60405190808252806020026020018201604052801561296257816020015b61294f6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b81526020019060019003908161290e5790505b50905060005b82518110156107f257612993838281518110612986576129866147ce565b60200260200101516125bf565b8282815181106129a5576129a56147ce565b6020908102919091010152600101612968565b606060006129c66009613685565b90506000815167ffffffffffffffff8111156129e4576129e4613d3d565b604051908082528060200260200182016040528015612a6b57816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612a025790505b50905060005b82518110156107f257612a9c838281518110612a8f57612a8f6147ce565b6020026020010151611128565b828281518110612aae57612aae6147ce565b6020908102919091010152600101612a71565b612ac9612af0565b612ad281613932565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612b71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610609565b565b6000610474825490565b6000612ae98383613a27565b6000612ae98383613a51565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612c4657602002820191906000526020600020905b815481526020019060010190808311612c32575b505050505090506000815167ffffffffffffffff811115612c6957612c69613d3d565b604051908082528060200260200182016040528015612caf57816020015b604080518082019091526000815260606020820152815260200190600190039081612c875790505b50905060005b8151811015612dc7576040518060400160405280848381518110612cdb57612cdb6147ce565b60200260200101518152602001856003016000868581518110612d0057612d006147ce565b602002602001015181526020019081526020016000208054612d2190614881565b80601f0160208091040260200160405190810160405280929190818152602001828054612d4d90614881565b8015612d9a5780601f10612d6f57610100808354040283529160200191612d9a565b820191906000526020600020905b815481529060010190602001808311612d7d57829003601f168201915b5050505050815250828281518110612db457612db46147ce565b6020908102919091010152600101612cb5565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a08101612e4e85613685565b81526020019190915295945050505050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580612eb2575060808201518590612ead906001614e59565b60ff16115b15612efb5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610609565b6001826020015163ffffffff161115612fe357815163ffffffff166000908152600d602090815260408220908401516001918201918391612f3c919061482c565b63ffffffff1663ffffffff168152602001908152602001600020905060005b612f6482612b73565b811015612fe057612f93846000015163ffffffff16600c60006105928587600001612b7d90919063ffffffff16565b50600c6000612fa28484612b7d565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055600101612f5b565b50505b60005b8581101561321d57613013878783818110613003576130036147ce565b8592602090910201359050613692565b61307457825187878381811061302b5761302b6147ce565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b8260600151156131cb57825163ffffffff16600c600089898581811061309c5761309c6147ce565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906131165750600c60008888848181106130e7576130e76147ce565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561317857825187878381811061312f5761312f6147ce565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b8251600c6000898985818110613190576131906147ce565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff160217905550613215565b82516132139063ffffffff16600c60008a8a868181106131ed576131ed6147ce565b90506020020135815260200190815260200160002060040161369290919063ffffffff16565b505b600101612fe6565b5060005b8381101561362b573685858381811061323c5761323c6147ce565b905060200281019061324e91906148f7565b905061325c60038235612ad5565b613295576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b6132a160058235612ad5565b156132db576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b80356000908152600384016020526040812080546132f890614881565b905011156133445783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610609565b60005b8781101561344e576133eb8235600c60008c8c8681811061336a5761336a6147ce565b9050602002013581526020019081526020016000206003016000600c60008e8e8881811061339a5761339a6147ce565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612ad590919063ffffffff16565b61344657888882818110613401576134016147ce565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610609565b600101613347565b506002830180546001810182556000918252602091829020833591015561347790820182614e72565b82356000908152600386016020526040902091613495919083614ed7565b50604080850151855163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9094169390931790558551915161362292918435908c908c906135e890880188614e72565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613b4492505050565b50600101613221565b50815160208301516040517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c15817036519261367592909163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b60606000612ae983613c25565b6000612ae98383613c81565b608081015173ffffffffffffffffffffffffffffffffffffffff16156137ec57608081015173ffffffffffffffffffffffffffffffffffffffff163b1580613797575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa158015613771573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137959190614ff2565b155b156137ec5760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610609565b60008281526002602052604090208151829190819061380b90826149ef565b506020820151600182019061382090826149ef565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561386257613862614526565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156138a9576138a9614526565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b3373ffffffffffffffffffffffffffffffffffffffff8216036139b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610609565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613a3e57613a3e6147ce565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613b3a576000613a7560018361500f565b8554909150600090613a899060019061500f565b9050818114613aee576000866000018281548110613aa957613aa96147ce565b9060005260206000200154905080876000018481548110613acc57613acc6147ce565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613aff57613aff615022565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610474565b6000915050610474565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156125b757600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613beb908690869086908b908d90600401615051565b600060405180830381600087803b158015613c0557600080fd5b505af1158015613c19573d6000803e3d6000fd5b50505050505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015613c7557602002820191906000526020600020905b815481526020019060010190808311613c61575b50505050509050919050565b6000818152600183016020526040812054613cc857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610474565b506000610474565b508054613cdc90614881565b6000825580601f10613cec575050565b601f016020900490600052602060002090810190612ad29190613d24565b5080546000825590600052602060002090810190612ad291905b5b80821115613d395760008155600101613d25565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613d8f57613d8f613d3d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613d8f57613d8f613d3d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613dff57613dff613d3d565b604052919050565b600067ffffffffffffffff821115613e2157613e21613d3d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613e5e57600080fd5b8135613e71613e6c82613e07565b613db8565b818152846020838601011115613e8657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613eb657600080fd5b823567ffffffffffffffff80821115613ece57600080fd5b613eda86838701613e4d565b93506020850135915080821115613ef057600080fd5b50613efd85828601613e4d565b9150509250929050565b600060208284031215613f1957600080fd5b5035919050565b60005b83811015613f3b578181015183820152602001613f23565b50506000910152565b60008151808452613f5c816020860160208601613f20565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612ae96020830184613f44565b60008083601f840112613fb357600080fd5b50813567ffffffffffffffff811115613fcb57600080fd5b6020830191508360208260051b850101111561112157600080fd5b60008060208385031215613ff957600080fd5b823567ffffffffffffffff81111561401057600080fd5b61401c85828601613fa1565b90969095509350505050565b60008151808452602080850194506020840160005b838110156140595781518752958201959082019060010161403d565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156140e1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526140cd81860183613f44565b9a86019a9450505090830190600101614081565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261414660e0850182614028565b905060c083015184820360c086015261415f8282614064565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526141cb8583516140ee565b94509285019290850190600101614191565b5092979650505050505050565b803563ffffffff811681146141fe57600080fd5b919050565b60006020828403121561421557600080fd5b612ae9826141ea565b73ffffffffffffffffffffffffffffffffffffffff815116825260006020820151604060208501526142536040850182613f44565b949350505050565b602081526000612ae9602083018461421e565b602081526000612ae960208301846140ee565b8015158114612ad257600080fd5b803560ff811681146141fe57600080fd5b600080600080600080600060a0888a0312156142bb57600080fd5b6142c4886141ea565b9650602088013567ffffffffffffffff808211156142e157600080fd5b6142ed8b838c01613fa1565b909850965060408a013591508082111561430657600080fd5b506143138a828b01613fa1565b909550935050606088013561432781614281565b91506143356080890161428f565b905092959891949750929550565b6000806040838503121561435657600080fd5b61435f836141ea565b946020939093013593505050565b6040815260006143806040830185613f44565b828103602084015261415f8185613f44565b600063ffffffff808351168452602081818501511681860152816040850151166040860152606084015160608601526080840151608086015260a0840151915060e060a08601526143e660e0860183614028565b60c08581015187830391880191909152805180835290830193506000918301905b808310156144275784518252938301936001929092019190830190614407565b509695505050505050565b602081526000612ae96020830184614392565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144a885835161421e565b9450928501929085019060010161446e565b600080600080604085870312156144d057600080fd5b843567ffffffffffffffff808211156144e857600080fd5b6144f488838901613fa1565b9096509450602087013591508082111561450d57600080fd5b5061451a87828801613fa1565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e0602085015261457460e0850182613f44565b90506040830151848203604086015261458d8282613f44565b9150506060830151600481106145a5576145a5614526565b60608501526080830151600281106145bf576145bf614526565b8060808601525060a08301516145ed60a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161460160c086018215159052565b509392505050565b602081526000612ae96020830184614555565b600080600080600080600060a0888a03121561463757600080fd5b873567ffffffffffffffff8082111561464f57600080fd5b61465b8b838c01613fa1565b909950975060208a013591508082111561467457600080fd5b506146818a828b01613fa1565b909650945050604088013561469581614281565b9250606088013561432781614281565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614708858351614555565b945092850192908501906001016146ce565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261477d858351614392565b94509285019290850190600101614743565b803573ffffffffffffffffffffffffffffffffffffffff811681146141fe57600080fd5b6000602082840312156147c557600080fd5b612ae98261478f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156107f2576107f26147fd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361487a5761487a6147fd565b5060010190565b600181811c9082168061489557607f821691505b6020821081036148ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff8083168181036148ed576148ed6147fd565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261492b57600080fd5b9190910192915050565b60006040823603121561494757600080fd5b6040516040810167ffffffffffffffff828210818311171561496b5761496b613d3d565b816040526149788561478f565b8352602085013591508082111561498e57600080fd5b5061499b36828601613e4d565b60208301525092915050565b601f821115610697576000816000526020600020601f850160051c810160208610156149d05750805b601f850160051c820191505b818110156125b7578281556001016149dc565b815167ffffffffffffffff811115614a0957614a09613d3d565b614a1d81614a178454614881565b846149a7565b602080601f831160018114614a705760008415614a3a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556125b7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614abd57888601518255948401946001909101908401614a9e565b5085821015614af957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614b1b57600080fd5b815167ffffffffffffffff811115614b3257600080fd5b8201601f81018413614b4357600080fd5b8051614b51613e6c82613e07565b818152856020838501011115614b6657600080fd5b61415f826020830160208601613f20565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261492b57600080fd5b600060808236031215614bbd57600080fd5b614bc5613d6c565b614bce836141ea565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff80821115614bff57600080fd5b9085019036601f830112614c1257600080fd5b813581811115614c2457614c24613d3d565b8060051b9150614c35848301613db8565b8181529183018401918481019036841115614c4f57600080fd5b938501935b83851015614c6d57843582529385019390850190614c54565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614cb657835183529284019291840191600101614c9a565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261492b57600080fd5b8035600281106141fe57600080fd5b600060a08236031215614d1757600080fd5b614d1f613d95565b823567ffffffffffffffff80821115614d3757600080fd5b614d4336838701613e4d565b83526020850135915080821115614d5957600080fd5b50614d6636828601613e4d565b602083015250604083013560048110614d7e57600080fd5b6040820152614d8f60608401614cf6565b6060820152614da06080840161478f565b608082015292915050565b6000602080835260008454614dbf81614881565b8060208701526040600180841660008114614de15760018114614e1b57614e4b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614e4b565b89600052602060002060005b85811015614e425781548b8201860152908301908801614e27565b8a016040019650505b509398975050505050505050565b60ff8181168382160190811115610474576104746147fd565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614ea757600080fd5b83018035915067ffffffffffffffff821115614ec257600080fd5b60200191503681900382131561112157600080fd5b67ffffffffffffffff831115614eef57614eef613d3d565b614f0383614efd8354614881565b836149a7565b6000601f841160018114614f555760008515614f1f5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614feb565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614fa45786850135825560209485019460019092019101614f84565b5086821015614fdf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60006020828403121561500457600080fd5b8151612ae981614281565b81810381811115610474576104746147fd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86111561508a57600080fd5b8560051b808860a0850137820182810360a090810160208501526150b090820187613f44565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", + 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: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61536d80620001776000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806350c946fe116100f95780638da5cb5b11610097578063ddbe4f8211610071578063ddbe4f821461044d578063e29581aa14610462578063f2fde38b1461046a578063fcdc8efe1461047d57600080fd5b80638da5cb5b146103f25780639cb7c5f41461041a578063d8bc7b681461043a57600080fd5b8063715f5295116100d3578063715f5295146103b157806379ba5097146103c457806384f5ed8a146103cc57806386fa4246146103df57600080fd5b806350c946fe146103695780635d83d9671461038957806366acaa331461039c57600080fd5b806323537405116101665780632c01a1e8116101405780632c01a1e81461030f578063358039f414610322578063398f3773146103355780633f2a13c91461034857600080fd5b806323537405146102c9578063275459f2146102e95780632a852933146102fc57600080fd5b8063181f5a77116101a2578063181f5a77146102365780631d05394c1461027f578063214502431461029457806322bdbcbc146102a957600080fd5b806305a51966146101c95780630fe5800a146101f25780631257001114610213575b600080fd5b6101dc6101d73660046140ab565b6104a3565b6040516101e991906141aa565b60405180910390f35b61020561020036600461436f565b61062c565b6040519081526020016101e9565b6102266102213660046143d3565b61065f565b60405190151581526020016101e9565b6102726040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e302e3100000000000081525081565b6040516101e9919061445a565b61029261028d3660046140ab565b61066c565b005b61029c610874565b6040516101e99190614568565b6102bc6102b73660046145f6565b6109d1565b6040516101e9919061464e565b6102dc6102d73660046145f6565b610abe565b6040516101e99190614661565b6102926102f73660046140ab565b610b02565b61029261030a366004614695565b610bd9565b61029261031d3660046140ab565b610cb9565b6102926103303660046140ab565b610f5c565b6102926103433660046140ab565b6116d1565b61035b610356366004614737565b611890565b6040516101e9929190614761565b61037c6103773660046143d3565b611a7c565b6040516101e99190614786565b6102926103973660046140ab565b611b69565b6103a4611c5e565b6040516101e99190614799565b6102926103bf3660046140ab565b611e41565b610292611ef3565b6102926103da3660046140ab565b611ff0565b6102926103ed36600461480e565b61250b565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e9565b61042d6104283660046143d3565b61284b565b6040516101e99190614955565b610292610448366004614968565b612a86565b610455612b50565b6040516101e991906149ee565b6101dc612c44565b610292610478366004614a87565b612d55565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101e9565b606060008267ffffffffffffffff8111156104c0576104c061422c565b60405190808252806020026020018201604052801561054f57816020015b60408051610100810182526000808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104de5790505b50905060005b838110156106225761057e85858381811061057257610572614aa2565b90506020020135611a7c565b82828151811061059057610590614aa2565b602002602001018190525060008019168282815181106105b2576105b2614aa2565b6020026020010151608001510361061a578484828181106105d5576105d5614aa2565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b60405180910390fd5b600101610555565b5090505b92915050565b60008282604051602001610641929190614761565b60405160208183030381529060405280519060200120905092915050565b6000610626600583612d69565b610674612d84565b60005b8181101561086f57600083838381811061069357610693614aa2565b90506020020160208101906106a891906145f6565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61070083612e07565b8110156107a057811561075657600c600061071b8584612e11565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610798565b6107968663ffffffff16600c60006107778588612e1190919063ffffffff16565b8152602001908152602001600020600501612e1d90919063ffffffff16565b505b6001016106f7565b508354640100000000900463ffffffff166000036107f2576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610611565b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610677565b505050565b600e54606090640100000000900463ffffffff166000610895600183614b00565b63ffffffff1667ffffffffffffffff8111156108b3576108b361422c565b60405190808252806020026020018201604052801561093a57816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108d15790505b509050600060015b8363ffffffff168163ffffffff1610156109ae5763ffffffff8082166000908152600d602052604090205416156109a65761097c81612e29565b83838151811061098e5761098e614aa2565b6020026020010181905250816109a390614b1d565b91505b600101610942565b506109ba600184614b00565b63ffffffff1681146109ca578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a3590614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6190614b55565b8015610aae5780601f10610a8357610100808354040283529160200191610aae565b820191906000526020600020905b815481529060010190602001808311610a9157829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261062682612e29565b610b0a612d84565b60005b63ffffffff811682111561086f57600083838363ffffffff16818110610b3557610b35614aa2565b9050602002016020810190610b4a91906145f6565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b956001830182613ff9565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a250610bd281614ba8565b9050610b0d565b610be1612d84565b63ffffffff8088166000908152600d60205260408120805490926401000000009091041690819003610c47576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610611565b610cae888888886040518060a001604052808f63ffffffff16815260200187610c6f90614ba8565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b1660609092019190915296506130f4565b505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f56576000848483818110610cf357610cf3614aa2565b602090810292909201356000818152600c90935260409092206001810154929350919050610d50576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610611565b6000610d5e82600501612e07565b1115610db357610d716005820184612e11565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610611565b805468010000000000000000900463ffffffff1615610e1b5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610611565b83158015610e555750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e8e576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6001810154610e9f90600790612e1d565b506002810154610eb190600990612e1d565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610f0d8282614033565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f4491815260200190565b60405180910390a15050600101610cd7565b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f56576000848483818110610f9657610f96614aa2565b9050602002810190610fa89190614bcb565b610fb190614c09565b6040808201516000908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff168552600181018054969750919593949390928401919061101690614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461104290614b55565b801561108f5780601f106110645761010080835404028352916020019161108f565b820191906000526020600020905b81548152906001019060200180831161107257829003601f168201915b5050509190925250505060018301549091506110df5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b841580156111045750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561113d576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6020830151611178576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111f957602084015161119990600790612d69565b156111d0576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111e5600782612e1d565b5060208401516111f79060079061390b565b505b606084015161123c5783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6080840151805160000361127e57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b8354600090859060049061129f90640100000000900463ffffffff16614ba8565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b8251811015611384576112f78382815181106112df576112df614aa2565b60200260200101516003612d6990919063ffffffff16565b61132f57826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b61137b83828151811061134457611344614aa2565b60200260200101518760040160008563ffffffff1663ffffffff16815260200190815260200160002061390b90919063ffffffff16565b506001016112c1565b50845468010000000000000000900463ffffffff1680156114e55763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561141957602002820191906000526020600020905b815481526020019060010190808311611405575b5050505050905060005b81518110156114e25761147882828151811061144157611441614aa2565b60200260200101518960040160008763ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b6114da5781818151811061148e5761148e614aa2565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161061192919091825263ffffffff16602082015260400190565b600101611423565b50505b60006114f387600501613917565b905060005b81518163ffffffff161015611639576000828263ffffffff168151811061152157611521614aa2565b60209081029190910181015163ffffffff8082166000908152600d845260408082208054640100000000900490931682526001909201845281812060020180548351818702810187019094528084529395509093919290918301828280156115a857602002820191906000526020600020905b815481526020019060010190808311611594575b5050505050905060005b8151811015611625576116078282815181106115d0576115d0614aa2565b60200260200101518c60040160008a63ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b61161d5781818151811061148e5761148e614aa2565b6001016115b2565b5050508061163290614ba8565b90506114f8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f7a565b6116d9612d84565b60005b8181101561086f5760008383838181106116f8576116f8614aa2565b905060200281019061170a9190614d2a565b61171390614d5e565b805190915073ffffffffffffffffffffffffffffffffffffffff16611764576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117f09082614e18565b5050600e805490915060009061180b9063ffffffff16614ba8565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e846020015160405161187e919061445a565b60405180910390a350506001016116dc565b63ffffffff8083166000908152600d602090815260408083208054640100000000900490941680845260019094018252808320858452600301909152812080546060938493909290916118e290614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461190e90614b55565b801561195b5780601f106119305761010080835404028352916020019161195b565b820191906000526020600020905b81548152906001019060200180831161193e57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a6e905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015611a25573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a6b9190810190614f32565b90505b9093509150505b9250929050565b604080516101008101825260008082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611b3e90613917565b8152602001611b61600c6000868152602001908152602001600020600501613917565b905292915050565b611b71612d84565b60005b8181101561086f576000838383818110611b9057611b90614aa2565b905060200201359050611bad816003612d6990919063ffffffff16565b611be6576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b611bf160058261390b565b611c2a576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250600101611b74565b600e5460609063ffffffff166000611c77600183614b00565b63ffffffff1667ffffffffffffffff811115611c9557611c9561422c565b604051908082528060200260200182016040528015611cdb57816020015b604080518082019091526000815260606020820152815260200190600190039081611cb35790505b509050600060015b8363ffffffff168163ffffffff161015611e2b5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611e235763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d7790614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054611da390614b55565b8015611df05780601f10611dc557610100808354040283529160200191611df0565b820191906000526020600020905b815481529060010190602001808311611dd357829003601f168201915b505050505081525050838381518110611e0b57611e0b614aa2565b602002602001018190525081611e2090614b1d565b91505b600101611ce3565b50600e546109ba9060019063ffffffff16614b00565b611e49612d84565b60005b8181101561086f576000838383818110611e6857611e68614aa2565b9050602002810190611e7a9190614bcb565b611e8390614faf565b90506000611e998260000151836020015161062c565b9050611ea660038261390b565b611edf576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b611ee98183613924565b5050600101611e4c565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610611565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f5657600084848381811061202a5761202a614aa2565b905060200281019061203c9190614bcb565b61204590614c09565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161209b90614b55565b80601f01602080910402602001604051908101604052809291908181526020018280546120c790614b55565b80156121145780601f106120e957610100808354040283529160200191612114565b820191906000526020600020905b8154815290600101906020018083116120f757829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661217a5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610611565b8315801561219f5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156121d8576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6040808301516000908152600c6020522060018101541561222d5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b60408301516122705782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6020830151158061228d5750602083015161228d90600790612d69565b156122c4576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516123075782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6080830151805160000361234957806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b8154829060049061236790640100000000900463ffffffff16614ba8565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b825181101561243d576123b08382815181106112df576112df614aa2565b6123e857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b6124348382815181106123fd576123fd614aa2565b60200260200101518560040160008563ffffffff1663ffffffff16815260200190815260200160002061390b90919063ffffffff16565b50600101612392565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561249d916007919061390b16565b5060408501516124af9060099061390b565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a2505050505080600101905061200e565b82811461254e576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610611565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561284357600086868381811061258657612586614aa2565b905060200201602081019061259b91906145f6565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661260a576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610611565b600086868581811061261e5761261e614aa2565b90506020028101906126309190614d2a565b61263990614d5e565b805190915073ffffffffffffffffffffffffffffffffffffffff1661268a576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff1633148015906126c757503373ffffffffffffffffffffffffffffffffffffffff861614155b15612700576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061277c5750602080820151604051612739920161445a565b60405160208183030381529060405280519060200120826001016040516020016127639190615055565b6040516020818303038152906040528051906020012014155b1561283557805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127d69082614e18565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28836020015160405161282c919061445a565b60405180910390a35b50505080600101905061256a565b505050505050565b61288c6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e081018252838152600084815260026020908152929020805491928301916128b890614b55565b80601f01602080910402602001604051908101604052809291908181526020018280546128e490614b55565b80156129315780601f1061290657610100808354040283529160200191612931565b820191906000526020600020905b81548152906001019060200180831161291457829003601f168201915b5050505050815260200160026000858152602001908152602001600020600101805461295c90614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461298890614b55565b80156129d55780601f106129aa576101008083540402835291602001916129d5565b820191906000526020600020905b8154815290600101906020018083116129b857829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff166003811115612a0757612a0761487a565b815260008481526002602081815260409092200154910190610100900460ff166001811115612a3857612a3861487a565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff169083015201612a7c600585612d69565b1515905292915050565b612a8e612d84565b600e805460009164010000000090910463ffffffff16906004612ab083614ba8565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612b469089908990899089906130f4565b5050505050505050565b60606000612b5e6003613917565b90506000815167ffffffffffffffff811115612b7c57612b7c61422c565b604051908082528060200260200182016040528015612bee57816020015b612bdb6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b815260200190600190039081612b9a5790505b50905060005b82518110156109ca57612c1f838281518110612c1257612c12614aa2565b602002602001015161284b565b828281518110612c3157612c31614aa2565b6020908102919091010152600101612bf4565b60606000612c526009613917565b90506000815167ffffffffffffffff811115612c7057612c7061422c565b604051908082528060200260200182016040528015612cff57816020015b60408051610100810182526000808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c8e5790505b50905060005b82518110156109ca57612d30838281518110612d2357612d23614aa2565b6020026020010151611a7c565b828281518110612d4257612d42614aa2565b6020908102919091010152600101612d05565b612d5d612d84565b612d6681613b0c565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610611565b565b6000610626825490565b6000612d7d8383613c01565b6000612d7d8383613c2b565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612eda57602002820191906000526020600020905b815481526020019060010190808311612ec6575b505050505090506000815167ffffffffffffffff811115612efd57612efd61422c565b604051908082528060200260200182016040528015612f4357816020015b604080518082019091526000815260606020820152815260200190600190039081612f1b5790505b50905060005b815181101561305b576040518060400160405280848381518110612f6f57612f6f614aa2565b60200260200101518152602001856003016000868581518110612f9457612f94614aa2565b602002602001015181526020019081526020016000208054612fb590614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054612fe190614b55565b801561302e5780601f106130035761010080835404028352916020019161302e565b820191906000526020600020905b81548152906001019060200180831161301157829003601f168201915b505050505081525082828151811061304857613048614aa2565b6020908102919091010152600101612f49565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a081016130e285613917565b81526020019190915295945050505050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613146575060808201518590613141906001615103565b60ff16115b1561318f5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610611565b6001826020015163ffffffff16111561327757815163ffffffff166000908152600d6020908152604082209084015160019182019183916131d09190614b00565b63ffffffff1663ffffffff168152602001908152602001600020905060005b6131f882612e07565b81101561327457613227846000015163ffffffff16600c60006107778587600001612e1190919063ffffffff16565b50600c60006132368484612e11565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556001016131ef565b50505b60005b858110156134b1576132a787878381811061329757613297614aa2565b859260209091020135905061390b565b6133085782518787838181106132bf576132bf614aa2565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610611565b82606001511561345f57825163ffffffff16600c600089898581811061333057613330614aa2565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906133aa5750600c600088888481811061337b5761337b614aa2565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561340c5782518787838181106133c3576133c3614aa2565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610611565b8251600c600089898581811061342457613424614aa2565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff1602179055506134a9565b82516134a79063ffffffff16600c60008a8a8681811061348157613481614aa2565b90506020020135815260200190815260200160002060050161390b90919063ffffffff16565b505b60010161327a565b5060005b838110156138bf57368585838181106134d0576134d0614aa2565b90506020028101906134e29190614d2a565b90506134f060038235612d69565b613529576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610611565b61353560058235612d69565b1561356f576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610611565b803560009081526003840160205260408120805461358c90614b55565b905011156135d85783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610611565b60005b878110156136e25761367f8235600c60008c8c868181106135fe576135fe614aa2565b9050602002013581526020019081526020016000206004016000600c60008e8e8881811061362e5761362e614aa2565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b6136da5788888281811061369557613695614aa2565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610611565b6001016135db565b506002830180546001810182556000918252602091829020833591015561370b9082018261511c565b82356000908152600386016020526040902091613729919083615181565b50604080850151855163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516138b692918435908c908c9061387c9088018861511c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d1e92505050565b506001016134b5565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b6000612d7d8383613dff565b60606000612d7d83613e4e565b608081015173ffffffffffffffffffffffffffffffffffffffff16156139c65761397281608001517f78bea72100000000000000000000000000000000000000000000000000000000613eaa565b6139c65760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610611565b6000828152600260205260409020815182919081906139e59082614e18565b50602082015160018201906139fa9082614e18565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836003811115613a3c57613a3c61487a565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613a8357613a8361487a565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613b8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610611565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613c1857613c18614aa2565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613d14576000613c4f60018361529c565b8554909150600090613c639060019061529c565b9050818114613cc8576000866000018281548110613c8357613c83614aa2565b9060005260206000200154905080876000018481548110613ca657613ca6614aa2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613cd957613cd96152af565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610626565b6000915050610626565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff161561284357600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613dc5908690869086908b908d906004016152de565b600060405180830381600087803b158015613ddf57600080fd5b505af1158015613df3573d6000803e3d6000fd5b50505050505050505050565b6000818152600183016020526040812054613e4657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610626565b506000610626565b606081600001805480602002602001604051908101604052809291908181526020018280548015613e9e57602002820191906000526020600020905b815481526020019060010190808311613e8a575b50505050509050919050565b6000613eb583613ec6565b8015612d7d5750612d7d8383613f2a565b6000613ef2827f01ffc9a700000000000000000000000000000000000000000000000000000000613f2a565b80156106265750613f23827fffffffff00000000000000000000000000000000000000000000000000000000613f2a565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015613fe2575060208210155b8015613fee5750600081115b979650505050505050565b50805461400590614b55565b6000825580601f10614015575050565b601f016020900490600052602060002090810190612d66919061404d565b5080546000825590600052602060002090810190612d6691905b5b80821115614062576000815560010161404e565b5090565b60008083601f84011261407857600080fd5b50813567ffffffffffffffff81111561409057600080fd5b6020830191508360208260051b8501011115611a7557600080fd5b600080602083850312156140be57600080fd5b823567ffffffffffffffff8111156140d557600080fd5b6140e185828601614066565b90969095509350505050565b60008151808452602080850194506020840160005b8381101561411e57815187529582019590820190600101614102565b509495945050505050565b600061010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c0860152614187828601826140ed565b91505060e083015184820360e08601526141a182826140ed565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261420d858351614129565b945092850192908501906001016141d3565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561427e5761427e61422c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156142cb576142cb61422c565b604052919050565b600067ffffffffffffffff8211156142ed576142ed61422c565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261432a57600080fd5b813561433d614338826142d3565b614284565b81815284602083860101111561435257600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561438257600080fd5b823567ffffffffffffffff8082111561439a57600080fd5b6143a686838701614319565b935060208501359150808211156143bc57600080fd5b506143c985828601614319565b9150509250929050565b6000602082840312156143e557600080fd5b5035919050565b60005b838110156144075781810151838201526020016143ef565b50506000910152565b600081518084526144288160208601602086016143ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d7d6020830184614410565b600082825180855260208086019550808260051b84010181860160005b848110156144ea578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526144d681860183614410565b9a86019a945050509083019060010161448a565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261454f60e08501826140ed565b905060c083015184820360c08601526141a1828261446d565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526145cb8583516144f7565b94509285019290850190600101614591565b803563ffffffff811681146145f157600080fd5b919050565b60006020828403121561460857600080fd5b612d7d826145dd565b73ffffffffffffffffffffffffffffffffffffffff815116825260006020820151604060208501526146466040850182614410565b949350505050565b602081526000612d7d6020830184614611565b602081526000612d7d60208301846144f7565b803580151581146145f157600080fd5b803560ff811681146145f157600080fd5b600080600080600080600060a0888a0312156146b057600080fd5b6146b9886145dd565b9650602088013567ffffffffffffffff808211156146d657600080fd5b6146e28b838c01614066565b909850965060408a01359150808211156146fb57600080fd5b506147088a828b01614066565b909550935061471b905060608901614674565b915061472960808901614684565b905092959891949750929550565b6000806040838503121561474a57600080fd5b614753836145dd565b946020939093013593505050565b6040815260006147746040830185614410565b82810360208401526141a18185614410565b602081526000612d7d6020830184614129565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526147fc858351614611565b945092850192908501906001016147c2565b6000806000806040858703121561482457600080fd5b843567ffffffffffffffff8082111561483c57600080fd5b61484888838901614066565b9096509450602087013591508082111561486157600080fd5b5061486e87828801614066565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e060208501526148c860e0850182614410565b9050604083015184820360408601526148e18282614410565b9150506060830151600481106148f9576148f961487a565b60608501526080830151600281106149135761491361487a565b8060808601525060a083015161494160a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161062260c086018215159052565b602081526000612d7d60208301846148a9565b600080600080600080600060a0888a03121561498357600080fd5b873567ffffffffffffffff8082111561499b57600080fd5b6149a78b838c01614066565b909950975060208a01359150808211156149c057600080fd5b506149cd8a828b01614066565b90965094506149e0905060408901614674565b925061471b60608901614674565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614a518583516148a9565b94509285019290850190600101614a17565b803573ffffffffffffffffffffffffffffffffffffffff811681146145f157600080fd5b600060208284031215614a9957600080fd5b612d7d82614a63565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156109ca576109ca614ad1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b4e57614b4e614ad1565b5060010190565b600181811c90821680614b6957607f821691505b602082108103614ba2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff808316818103614bc157614bc1614ad1565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614bff57600080fd5b9190910192915050565b600060a08236031215614c1b57600080fd5b614c2361425b565b614c2c836145dd565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614c6757600080fd5b9085019036601f830112614c7a57600080fd5b813581811115614c8c57614c8c61422c565b8060051b9150614c9d848301614284565b8181529183018401918481019036841115614cb757600080fd5b938501935b83851015614cd557843582529385019390850190614cbc565b608087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614d1e57835183529284019291840191600101614d02565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614bff57600080fd5b600060408236031215614d7057600080fd5b6040516040810167ffffffffffffffff8282108183111715614d9457614d9461422c565b81604052614da185614a63565b83526020850135915080821115614db757600080fd5b50614dc436828601614319565b60208301525092915050565b601f82111561086f576000816000526020600020601f850160051c81016020861015614df95750805b601f850160051c820191505b8181101561284357828155600101614e05565b815167ffffffffffffffff811115614e3257614e3261422c565b614e4681614e408454614b55565b84614dd0565b602080601f831160018114614e995760008415614e635750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612843565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614ee657888601518255948401946001909101908401614ec7565b5085821015614f2257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614f4457600080fd5b815167ffffffffffffffff811115614f5b57600080fd5b8201601f81018413614f6c57600080fd5b8051614f7a614338826142d3565b818152856020838501011115614f8f57600080fd5b6141a18260208301602086016143ec565b8035600281106145f157600080fd5b600060a08236031215614fc157600080fd5b614fc961425b565b823567ffffffffffffffff80821115614fe157600080fd5b614fed36838701614319565b8352602085013591508082111561500357600080fd5b5061501036828601614319565b60208301525060408301356004811061502857600080fd5b604082015261503960608401614fa0565b606082015261504a60808401614a63565b608082015292915050565b600060208083526000845461506981614b55565b806020870152604060018084166000811461508b57600181146150c5576150f5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a010195506150f5565b89600052602060002060005b858110156150ec5781548b82018601529083019088016150d1565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561062657610626614ad1565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261515157600080fd5b83018035915067ffffffffffffffff82111561516c57600080fd5b602001915036819003821315611a7557600080fd5b67ffffffffffffffff8311156151995761519961422c565b6151ad836151a78354614b55565b83614dd0565b6000601f8411600181146151ff57600085156151c95750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355615295565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561524e578685013582556020948501946001909201910161522e565b5086821015615289577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8181038181111561062657610626614ad1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86111561531757600080fd5b8560051b808860a0850137820182810360a0908101602085015261533d90820187614410565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", } var CapabilitiesRegistryABI = CapabilitiesRegistryMetaData.ABI @@ -359,25 +361,47 @@ func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetHashedCapabil return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) } -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) { +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(CapabilitiesRegistryNodeInfo), err + return *new(INodeInfoProviderNodeInfo), err } - out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryNodeInfo)).(*CapabilitiesRegistryNodeInfo) + out0 := *abi.ConvertType(out[0], new(INodeInfoProviderNodeInfo)).(*INodeInfoProviderNodeInfo) return out0, err } -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNode(p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) { +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNode(p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) } -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNode(p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) { +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNode(p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) } @@ -425,28 +449,50 @@ func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperators return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) } -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodes(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeInfo, error) { +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodes(opts *bind.CallOpts) ([]INodeInfoProviderNodeInfo, error) { var out []interface{} err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodes") if err != nil { - return *new([]CapabilitiesRegistryNodeInfo), err + return *new([]INodeInfoProviderNodeInfo), err } - out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryNodeInfo)).(*[]CapabilitiesRegistryNodeInfo) + out0 := *abi.ConvertType(out[0], new([]INodeInfoProviderNodeInfo)).(*[]INodeInfoProviderNodeInfo) return out0, err } -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodes() ([]CapabilitiesRegistryNodeInfo, error) { +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodes() ([]INodeInfoProviderNodeInfo, error) { return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) } -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodes() ([]CapabilitiesRegistryNodeInfo, error) { +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) @@ -989,18 +1035,28 @@ type CapabilitiesRegistryConfigSet struct { Raw types.Log } -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterConfigSet(opts *bind.FilterOpts) (*CapabilitiesRegistryConfigSetIterator, error) { +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32) (*CapabilitiesRegistryConfigSetIterator, error) { - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "ConfigSet") + 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) (event.Subscription, error) { +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") + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "ConfigSet", donIdRule) if err != nil { return nil, err } @@ -2180,13 +2236,17 @@ type CapabilitiesRegistryInterface interface { GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) - GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilitiesRegistryNodeInfo, 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) ([]CapabilitiesRegistryNodeInfo, 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) @@ -2232,9 +2292,9 @@ type CapabilitiesRegistryInterface interface { ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) - FilterConfigSet(opts *bind.FilterOpts) (*CapabilitiesRegistryConfigSetIterator, error) + FilterConfigSet(opts *bind.FilterOpts, donId []uint32) (*CapabilitiesRegistryConfigSetIterator, error) - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet) (event.Subscription, error) + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet, donId []uint32) (event.Subscription, error) ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) diff --git a/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go b/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go index 2951835c8d6..8b618fbddb5 100644 --- a/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go +++ b/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go @@ -32,7 +32,7 @@ var ( 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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611281806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063805f21321161005b578063805f2132146101ab5780638da5cb5b146101be578063e3401711146101e6578063f2fde38b146101f957600080fd5b806301ffc9a71461008257806331d98b3f146100ec57806379ba5097146101a1575b600080fd5b6100d7610090366004610dd4565b7fffffffff00000000000000000000000000000000000000000000000000000000167f805f2132000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6101686100fa366004610e1d565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152016100e3565b6101a961020c565b005b6101a96101b9366004610e7f565b61030e565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e3565b6101a96101f4366004610f30565b61068d565b6101a9610207366004610fca565b610acd565b60015473ffffffffffffffffffffffffffffffffffffffff163314610292576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff16610359576040517f3fcc3f17000000000000000000000000000000000000000000000000000000008152336004820152602401610289565b60008061039b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ae192505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff1661042f576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff0000000000000000000000000000000000000000000083166004820152602401610289565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166104a6576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610289565b60006104b4848601866110a7565b905060005b81518110156106835760405180604001604052808383815181106104df576104df6111b9565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001838381518110610520576105206111b9565b60200260200101516040015163ffffffff168152506002600084848151811061054b5761054b6111b9565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905581518290829081106105cd576105cd6111b9565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061060c5761060c6111b9565b60200260200101516020015184848151811061062a5761062a6111b9565b6020026020010151604001516040516106739291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a26001016104b9565b5050505050505050565b610695610af7565b60005b60035463ffffffff821610156107365760006004600060038463ffffffff16815481106106c7576106c76111b9565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561072f816111e8565b9050610698565b5060005b63ffffffff81168611156107de5760016004600089898563ffffffff16818110610766576107666111b9565b905060200201602081019061077b9190610fca565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556107d7816111e8565b905061073a565b506107eb60038787610c6f565b5060005b60055463ffffffff8216101561088d5760006006600060058463ffffffff168154811061081e5761081e6111b9565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610886816111e8565b90506107ef565b5060005b63ffffffff81168411156109355760016006600087878563ffffffff168181106108bd576108bd6111b9565b90506020020160208101906108d29190610fca565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561092e816111e8565b9050610891565b5061094260058585610c6f565b5060005b60075463ffffffff82161015610a035760006008600060078463ffffffff1681548110610975576109756111b9565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556109fc816111e8565b9050610946565b5060005b63ffffffff8116821115610ab75760016008600085858563ffffffff16818110610a3357610a336111b9565b9050602002016020810190610a489190611232565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610ab0816111e8565b9050610a07565b50610ac460078383610cf7565b50505050505050565b610ad5610af7565b610ade81610b7a565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610289565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610bf9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610289565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610ce7579160200282015b82811115610ce75781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610c8f565b50610cf3929150610dbf565b5090565b82805482825590600052602060002090600201600390048101928215610ce75791602002820160005b83821115610d8057833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610d20565b8015610db65782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610d80565b5050610cf39291505b5b80821115610cf35760008155600101610dc0565b600060208284031215610de657600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e1657600080fd5b9392505050565b600060208284031215610e2f57600080fd5b5035919050565b60008083601f840112610e4857600080fd5b50813567ffffffffffffffff811115610e6057600080fd5b602083019150836020828501011115610e7857600080fd5b9250929050565b60008060008060408587031215610e9557600080fd5b843567ffffffffffffffff80821115610ead57600080fd5b610eb988838901610e36565b90965094506020870135915080821115610ed257600080fd5b50610edf87828801610e36565b95989497509550505050565b60008083601f840112610efd57600080fd5b50813567ffffffffffffffff811115610f1557600080fd5b6020830191508360208260051b8501011115610e7857600080fd5b60008060008060008060608789031215610f4957600080fd5b863567ffffffffffffffff80821115610f6157600080fd5b610f6d8a838b01610eeb565b90985096506020890135915080821115610f8657600080fd5b610f928a838b01610eeb565b90965094506040890135915080821115610fab57600080fd5b50610fb889828a01610eeb565b979a9699509497509295939492505050565b600060208284031215610fdc57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e1657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561105257611052611000565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561109f5761109f611000565b604052919050565b600060208083850312156110ba57600080fd5b823567ffffffffffffffff808211156110d257600080fd5b818501915085601f8301126110e657600080fd5b8135818111156110f8576110f8611000565b611106848260051b01611058565b8181528481019250606091820284018501918883111561112557600080fd5b938501935b828510156111ad5780858a0312156111425760008081fd5b61114a61102f565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117d5760008081fd5b8188015260408681013563ffffffff8116811461119a5760008081fd5b908201528452938401939285019261112a565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103611228577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561124457600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610e1657600080fdfea164736f6c6343000818000a", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112d8806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063805f21321161005b578063805f2132146101695780638da5cb5b1461017c578063e3401711146101a4578063f2fde38b146101b757600080fd5b806301ffc9a71461008257806331d98b3f146100aa57806379ba50971461015f575b600080fd5b610095610090366004610e2b565b6101ca565b60405190151581526020015b60405180910390f35b6101266100b8366004610e74565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152016100a1565b610167610263565b005b610167610177366004610ed6565b610365565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a1565b6101676101b2366004610f87565b6106e4565b6101676101c5366004611021565b610b24565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f805f213200000000000000000000000000000000000000000000000000000000148061025d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff166103b0576040517f3fcc3f170000000000000000000000000000000000000000000000000000000081523360048201526024016102e0565b6000806103f286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b3892505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff16610486576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff00000000000000000000000000000000000000000000831660048201526024016102e0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166104fd576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016102e0565b600061050b848601866110fe565b905060005b81518110156106da57604051806040016040528083838151811061053657610536611210565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200183838151811061057757610577611210565b60200260200101516040015163ffffffff16815250600260008484815181106105a2576105a2611210565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055815182908290811061062457610624611210565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061066357610663611210565b60200260200101516020015184848151811061068157610681611210565b6020026020010151604001516040516106ca9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2600101610510565b5050505050505050565b6106ec610b4e565b60005b60035463ffffffff8216101561078d5760006004600060038463ffffffff168154811061071e5761071e611210565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556107868161123f565b90506106ef565b5060005b63ffffffff81168611156108355760016004600089898563ffffffff168181106107bd576107bd611210565b90506020020160208101906107d29190611021565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082e8161123f565b9050610791565b5061084260038787610cc6565b5060005b60055463ffffffff821610156108e45760006006600060058463ffffffff168154811061087557610875611210565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556108dd8161123f565b9050610846565b5060005b63ffffffff811684111561098c5760016006600087878563ffffffff1681811061091457610914611210565b90506020020160208101906109299190611021565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556109858161123f565b90506108e8565b5061099960058585610cc6565b5060005b60075463ffffffff82161015610a5a5760006008600060078463ffffffff16815481106109cc576109cc611210565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610a538161123f565b905061099d565b5060005b63ffffffff8116821115610b0e5760016008600085858563ffffffff16818110610a8a57610a8a611210565b9050602002016020810190610a9f9190611289565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610b078161123f565b9050610a5e565b50610b1b60078383610d4e565b50505050505050565b610b2c610b4e565b610b3581610bd1565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e0565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610c50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610d3e579160200282015b82811115610d3e5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610ce6565b50610d4a929150610e16565b5090565b82805482825590600052602060002090600201600390048101928215610d3e5791602002820160005b83821115610dd757833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610d77565b8015610e0d5782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610dd7565b5050610d4a9291505b5b80821115610d4a5760008155600101610e17565b600060208284031215610e3d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e6d57600080fd5b9392505050565b600060208284031215610e8657600080fd5b5035919050565b60008083601f840112610e9f57600080fd5b50813567ffffffffffffffff811115610eb757600080fd5b602083019150836020828501011115610ecf57600080fd5b9250929050565b60008060008060408587031215610eec57600080fd5b843567ffffffffffffffff80821115610f0457600080fd5b610f1088838901610e8d565b90965094506020870135915080821115610f2957600080fd5b50610f3687828801610e8d565b95989497509550505050565b60008083601f840112610f5457600080fd5b50813567ffffffffffffffff811115610f6c57600080fd5b6020830191508360208260051b8501011115610ecf57600080fd5b60008060008060008060608789031215610fa057600080fd5b863567ffffffffffffffff80821115610fb857600080fd5b610fc48a838b01610f42565b90985096506020890135915080821115610fdd57600080fd5b610fe98a838b01610f42565b9096509450604089013591508082111561100257600080fd5b5061100f89828a01610f42565b979a9699509497509295939492505050565b60006020828403121561103357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156110a9576110a9611057565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110f6576110f6611057565b604052919050565b6000602080838503121561111157600080fd5b823567ffffffffffffffff8082111561112957600080fd5b818501915085601f83011261113d57600080fd5b81358181111561114f5761114f611057565b61115d848260051b016110af565b8181528481019250606091820284018501918883111561117c57600080fd5b938501935b828510156112045780858a0312156111995760008081fd5b6111a1611086565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146111d45760008081fd5b8188015260408681013563ffffffff811681146111f15760008081fd5b9082015284529384019392850192611181565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff80831681810361127f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561129b57600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610e6d57600080fdfea164736f6c6343000818000a", } var KeystoneFeedsConsumerABI = KeystoneFeedsConsumerMetaData.ABI diff --git a/core/gethwrappers/keystone/generated/forwarder/forwarder.go b/core/gethwrappers/keystone/generated/forwarder/forwarder.go index a7a78ab67f9..5c95cfef2b6 100644 --- a/core/gethwrappers/keystone/generated/forwarder/forwarder.go +++ b/core/gethwrappers/keystone/generated/forwarder/forwarder.go @@ -41,7 +41,7 @@ type IRouterTransmissionInfo struct { 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: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000bf565b5050306000908152600360205260409020805460ff19166001179055506200016a565b336001600160a01b03821603620001195760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612141806200017a6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806379ba50971161008c578063abcef55411610066578063abcef5541461035d578063ee59d26c14610396578063ef6e17a0146103a9578063f2fde38b146103bc57600080fd5b806379ba50971461025e5780638864b864146102665780638da5cb5b1461033f57600080fd5b8063272cbd93116100c8578063272cbd9314610179578063354bdd66146101995780634d93172d146102385780635c41d2fe1461024b57600080fd5b806311289565146100ef578063181f5a7714610104578063233fd52d14610156575b600080fd5b6101026100fd3660046119df565b6103cf565b005b6101406040518060400160405280601a81526020017f466f7277617264657220616e6420526f7574657220312e302e3000000000000081525081565b60405161014d9190611a8a565b60405180910390f35b610169610164366004611af7565b610989565b604051901515815260200161014d565b61018c610187366004611b7f565b610e4a565b60405161014d9190611c13565b61022a6101a7366004611b7f565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090509392505050565b60405190815260200161014d565b610102610246366004611cbb565b611050565b610102610259366004611cbb565b6110cc565b61010261114b565b61031a610274366004611b7f565b6040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348501939093527fffff000000000000000000000000000000000000000000000000000000000000919091166054840152805160368185030181526056909301815282519282019290922060009081526004909152205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014d565b60005473ffffffffffffffffffffffffffffffffffffffff1661031a565b61016961036b366004611cbb565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6101026103a4366004611cf1565b611248565b6101026103b7366004611d6f565b611625565b6101026103ca366004611cbb565b6116c5565b606d85101561040a576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061044e89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116d992505050565b67ffffffffffffffff8216600090815260026020526040812080549497509195509193509160ff16908190036104c1576040517fdf3b81ea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b856104cd826001611dd1565b60ff161461051f576104e0816001611dd1565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018790526044016104b8565b60008b8b604051610531929190611df0565b60405190819003812061054a918c908c90602001611e00565b60405160208183030381529060405280519060200120905061056a61186c565b60005b888110156107ec573660008b8b8481811061058a5761058a611e1a565b905060200281019061059c9190611e49565b9092509050604181146105df5781816040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016104b8929190611ef7565b6000600186848460408181106105f7576105f7611e1a565b61060992013560f81c9050601b611dd1565b610617602060008789611f13565b61062091611f3d565b61062e60406020888a611f13565b61063791611f3d565b6040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610685573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8116600090815260028c0160205291822054909350915081900361072b576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b600086826020811061073f5761073f611e1a565b602002015173ffffffffffffffffffffffffffffffffffffffff16146107a9576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b818682602081106107bc576107bc611e1a565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015250506001909201915061056d9050565b50506040805160608f901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603482018990527fffff0000000000000000000000000000000000000000000000000000000000008816605483015282516036818403018152605690920190925280519101206000945030935063233fd52d92509050338d8d8d602d90606d9261088e93929190611f13565b8f8f606d9080926108a193929190611f13565b6040518863ffffffff1660e01b81526004016108c39796959493929190611f79565b6020604051808303816000875af11580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190611fda565b9050817dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916838b73ffffffffffffffffffffffffffffffffffffffff167f3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b584604051610975911515815260200190565b60405180910390a450505050505050505050565b3360009081526003602052604081205460ff166109d2576040517fd79e123d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005a9050619c40811015610a16576040517f0bfecd63000000000000000000000000000000000000000000000000000000008152600481018a90526024016104b8565b6000898152600460209081526040918290208251608081018452905473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000810460ff90811615159383019390935275010000000000000000000000000000000000000000008104909216151592810183905276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660608201529080610ace575080602001515b15610b08576040517fa53dc8ca000000000000000000000000000000000000000000000000000000008152600481018b90526024016104b8565b6000610b16619c4084611ffc565b905089600460008d815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460008d815260200190815260200160002060000160166101000a81548169ffffffffffffffffffff021916908369ffffffffffffffffffff1602179055508873ffffffffffffffffffffffffffffffffffffffff163b600003610c2257505050600088815260046020526040812080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559050610e3f565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f805f213200000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8a16906301ffc9a790602401602060405180830381865afa925050508015610ce6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610ce391810190611fda565b60015b610d3f57505050600088815260046020526040812080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559050610e3f565b5060008089898989604051602401610d5a949392919061200f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f805f21320000000000000000000000000000000000000000000000000000000017815281519192506000918291828f88f191508115610e335760008d815260046020526040902080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b509350610e3f92505050565b979650505050505050565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840183905284519088901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681830152603481018790527fffff000000000000000000000000000000000000000000000000000000000000861660548201528451603681830301815260568201808752815191840191909120808552600490935285842060d68301909652945473ffffffffffffffffffffffffffffffffffffffff811680875274010000000000000000000000000000000000000000820460ff9081161515607685015275010000000000000000000000000000000000000000008304161515609684015276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660b69092019190915292939092909190610fa857506000610fd0565b816020015115610fba57506002610fd0565b8160400151610fca576003610fcd565b60015b90505b6040518060c00160405280848152602001826003811115610ff357610ff3611be4565b8152602001836000015173ffffffffffffffffffffffffffffffffffffffff168152602001836020015115158152602001836040015115158152602001836060015169ffffffffffffffffffff1681525093505050509392505050565b6110586116f4565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d389190a250565b6110d46116f4565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e79190a250565b60015473ffffffffffffffffffffffffffffffffffffffff1633146111cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016104b8565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6112506116f4565b8260ff1660000361128d576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8111156112d2576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f60248201526044016104b8565b6112dd836003612036565b60ff16811161133b57806112f2846003612036565b6112fd906001611dd1565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff1660248201526044016104b8565b67ffffffff00000000602086901b1663ffffffff85161760005b67ffffffffffffffff82166000908152600260205260409020600101548110156113eb5767ffffffffffffffff82166000908152600260208190526040822060018101805491909201929190849081106113b1576113b1611e1a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812055600101611355565b5060005b8281101561156757600084848381811061140b5761140b611e1a565b90506020020160208101906114209190611cbb565b905073ffffffffffffffffffffffffffffffffffffffff8116611487576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b67ffffffffffffffff8316600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205415611513576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b61151e826001612052565b67ffffffffffffffff8416600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff909616845294909101905291909120556001016113ef565b5067ffffffffffffffff8116600090815260026020526040902061158f90600101848461188b565b5067ffffffffffffffff81166000908152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff87161790555163ffffffff86811691908816907f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a4559061161590889088908890612065565b60405180910390a3505050505050565b61162d6116f4565b63ffffffff818116602084811b67ffffffff00000000168217600090815260028252604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051828152928301905291928516917f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455916040516116b99291906120cb565b60405180910390a35050565b6116cd6116f4565b6116d681611777565b50565b60218101516045820151608b90920151909260c09290921c91565b60005473ffffffffffffffffffffffffffffffffffffffff163314611775576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104b8565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036117f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104b8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518061040001604052806020906020820280368337509192915050565b828054828255906000526020600020908101928215611903579160200282015b828111156119035781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906118ab565b5061190f929150611913565b5090565b5b8082111561190f5760008155600101611914565b803573ffffffffffffffffffffffffffffffffffffffff8116811461194c57600080fd5b919050565b60008083601f84011261196357600080fd5b50813567ffffffffffffffff81111561197b57600080fd5b60208301915083602082850101111561199357600080fd5b9250929050565b60008083601f8401126119ac57600080fd5b50813567ffffffffffffffff8111156119c457600080fd5b6020830191508360208260051b850101111561199357600080fd5b60008060008060008060006080888a0312156119fa57600080fd5b611a0388611928565b9650602088013567ffffffffffffffff80821115611a2057600080fd5b611a2c8b838c01611951565b909850965060408a0135915080821115611a4557600080fd5b611a518b838c01611951565b909650945060608a0135915080821115611a6a57600080fd5b50611a778a828b0161199a565b989b979a50959850939692959293505050565b60006020808352835180602085015260005b81811015611ab857858101830151858201604001528201611a9c565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600080600080600080600060a0888a031215611b1257600080fd5b87359650611b2260208901611928565b9550611b3060408901611928565b9450606088013567ffffffffffffffff80821115611b4d57600080fd5b611b598b838c01611951565b909650945060808a0135915080821115611b7257600080fd5b50611a778a828b01611951565b600080600060608486031215611b9457600080fd5b611b9d84611928565b92506020840135915060408401357fffff00000000000000000000000000000000000000000000000000000000000081168114611bd957600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602082015160c082019060048110611c58577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060208401525073ffffffffffffffffffffffffffffffffffffffff604084015116604083015260608301511515606083015260808301511515608083015260a0830151611cb460a084018269ffffffffffffffffffff169052565b5092915050565b600060208284031215611ccd57600080fd5b611cd682611928565b9392505050565b803563ffffffff8116811461194c57600080fd5b600080600080600060808688031215611d0957600080fd5b611d1286611cdd565b9450611d2060208701611cdd565b9350604086013560ff81168114611d3657600080fd5b9250606086013567ffffffffffffffff811115611d5257600080fd5b611d5e8882890161199a565b969995985093965092949392505050565b60008060408385031215611d8257600080fd5b611d8b83611cdd565b9150611d9960208401611cdd565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160190811115611dea57611dea611da2565b92915050565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7e57600080fd5b83018035915067ffffffffffffffff821115611e9957600080fd5b60200191503681900382131561199357600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000611f0b602083018486611eae565b949350505050565b60008085851115611f2357600080fd5b83861115611f3057600080fd5b5050820193919092039150565b80356020831015611dea577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525060a06060830152611fb960a083018688611eae565b8281036080840152611fcc818587611eae565b9a9950505050505050505050565b600060208284031215611fec57600080fd5b81518015158114611cd657600080fd5b81810381811115611dea57611dea611da2565b604081526000612023604083018688611eae565b8281036020840152610e3f818587611eae565b60ff8181168382160290811690818114611cb457611cb4611da2565b80820180821115611dea57611dea611da2565b60ff8416815260406020808301829052908201839052600090849060608401835b868110156120bf5773ffffffffffffffffffffffffffffffffffffffff6120ac85611928565b1682529282019290820190600101612086565b50979650505050505050565b60006040820160ff8516835260206040602085015281855180845260608601915060208701935060005b8181101561212757845173ffffffffffffffffffffffffffffffffffffffff16835293830193918301916001016120f5565b509097965050505050505056fea164736f6c6343000818000a", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000bf565b5050306000908152600360205260409020805460ff19166001179055506200016a565b336001600160a01b03821603620001195760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61218f806200017a6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806379ba50971161008c578063abcef55411610066578063abcef5541461035d578063ee59d26c14610396578063ef6e17a0146103a9578063f2fde38b146103bc57600080fd5b806379ba50971461025e5780638864b864146102665780638da5cb5b1461033f57600080fd5b8063272cbd93116100c8578063272cbd9314610179578063354bdd66146101995780634d93172d146102385780635c41d2fe1461024b57600080fd5b806311289565146100ef578063181f5a7714610104578063233fd52d14610156575b600080fd5b6101026100fd366004611a33565b6103cf565b005b6101406040518060400160405280601a81526020017f466f7277617264657220616e6420526f7574657220312e302e3000000000000081525081565b60405161014d9190611ade565b60405180910390f35b610169610164366004611b4b565b610989565b604051901515815260200161014d565b61018c610187366004611bd3565b610d4a565b60405161014d9190611c67565b61022a6101a7366004611bd3565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090509392505050565b60405190815260200161014d565b610102610246366004611d0f565b610f50565b610102610259366004611d0f565b610fcc565b61010261104b565b61031a610274366004611bd3565b6040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348501939093527fffff000000000000000000000000000000000000000000000000000000000000919091166054840152805160368185030181526056909301815282519282019290922060009081526004909152205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014d565b60005473ffffffffffffffffffffffffffffffffffffffff1661031a565b61016961036b366004611d0f565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6101026103a4366004611d3e565b611148565b6101026103b7366004611dbc565b611525565b6101026103ca366004611d0f565b6115c5565b606d85101561040a576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061044e89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115d992505050565b67ffffffffffffffff8216600090815260026020526040812080549497509195509193509160ff16908190036104c1576040517fdf3b81ea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b856104cd826001611e1e565b60ff161461051f576104e0816001611e1e565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018790526044016104b8565b60008b8b604051610531929190611e37565b60405190819003812061054a918c908c90602001611e47565b60405160208183030381529060405280519060200120905061056a6118c0565b60005b888110156107ec573660008b8b8481811061058a5761058a611e61565b905060200281019061059c9190611e90565b9092509050604181146105df5781816040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016104b8929190611f3e565b6000600186848460408181106105f7576105f7611e61565b61060992013560f81c9050601b611e1e565b610617602060008789611f5a565b61062091611f84565b61062e60406020888a611f5a565b61063791611f84565b6040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610685573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8116600090815260028c0160205291822054909350915081900361072b576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b600086826020811061073f5761073f611e61565b602002015173ffffffffffffffffffffffffffffffffffffffff16146107a9576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b818682602081106107bc576107bc611e61565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015250506001909201915061056d9050565b50506040805160608f901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603482018990527fffff0000000000000000000000000000000000000000000000000000000000008816605483015282516036818403018152605690920190925280519101206000945030935063233fd52d92509050338d8d8d602d90606d9261088e93929190611f5a565b8f8f606d9080926108a193929190611f5a565b6040518863ffffffff1660e01b81526004016108c39796959493929190611fc0565b6020604051808303816000875af11580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190612021565b9050817dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916838b73ffffffffffffffffffffffffffffffffffffffff167f3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b584604051610975911515815260200190565b60405180910390a450505050505050505050565b3360009081526003602052604081205460ff166109d2576040517fd79e123d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109e26113886161a861204a565b5a6109ed919061205d565b90506109fd6113886161a861204a565b610a0a9062015f9061204a565b610a169061271061204a565b811015610a52576040517f0bfecd63000000000000000000000000000000000000000000000000000000008152600481018a90526024016104b8565b6000898152600460209081526040918290208251608081018452905473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000810460ff90811615159383019390935275010000000000000000000000000000000000000000008104909216151592810183905276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660608201529080610b0a575080602001515b15610b44576040517fa53dc8ca000000000000000000000000000000000000000000000000000000008152600481018b90526024016104b8565b60008a8152600460205260409020805469ffffffffffffffffffff84167601000000000000000000000000000000000000000000000275ffff000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8c1617179055610bd9887f805f2132000000000000000000000000000000000000000000000000000000006115f4565b610c3057505050600087815260046020526040812080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610d3f565b60008088888888604051602401610c4a9493929190612070565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f805f213200000000000000000000000000000000000000000000000000000000179052905060006113885a610cd2919061205d565b905060008083516020850160008f86f192508215610d375760008d815260046020526040902080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b509093505050505b979650505050505050565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840183905284519088901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681830152603481018790527fffff000000000000000000000000000000000000000000000000000000000000861660548201528451603681830301815260568201808752815191840191909120808552600490935285842060d68301909652945473ffffffffffffffffffffffffffffffffffffffff811680875274010000000000000000000000000000000000000000820460ff9081161515607685015275010000000000000000000000000000000000000000008304161515609684015276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660b69092019190915292939092909190610ea857506000610ed0565b816020015115610eba57506002610ed0565b8160400151610eca576003610ecd565b60015b90505b6040518060c00160405280848152602001826003811115610ef357610ef3611c38565b8152602001836000015173ffffffffffffffffffffffffffffffffffffffff168152602001836020015115158152602001836040015115158152602001836060015169ffffffffffffffffffff1681525093505050509392505050565b610f58611619565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d389190a250565b610fd4611619565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e79190a250565b60015473ffffffffffffffffffffffffffffffffffffffff1633146110cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016104b8565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611150611619565b8260ff1660000361118d576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8111156111d2576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f60248201526044016104b8565b6111dd836003612097565b60ff16811161123b57806111f2846003612097565b6111fd906001611e1e565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff1660248201526044016104b8565b67ffffffff00000000602086901b1663ffffffff85161760005b67ffffffffffffffff82166000908152600260205260409020600101548110156112eb5767ffffffffffffffff82166000908152600260208190526040822060018101805491909201929190849081106112b1576112b1611e61565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812055600101611255565b5060005b8281101561146757600084848381811061130b5761130b611e61565b90506020020160208101906113209190611d0f565b905073ffffffffffffffffffffffffffffffffffffffff8116611387576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b67ffffffffffffffff8316600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205415611413576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b61141e82600161204a565b67ffffffffffffffff8416600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff909616845294909101905291909120556001016112ef565b5067ffffffffffffffff8116600090815260026020526040902061148f9060010184846118df565b5067ffffffffffffffff81166000908152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff87161790555163ffffffff86811691908816907f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a45590611515908890889088906120b3565b60405180910390a3505050505050565b61152d611619565b63ffffffff818116602084811b67ffffffff00000000168217600090815260028252604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051828152928301905291928516917f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455916040516115b9929190612119565b60405180910390a35050565b6115cd611619565b6115d68161169c565b50565b60218101516045820151608b90920151909260c09290921c91565b60006115ff83611791565b8015611610575061161083836117f5565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104b8565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361171b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104b8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006117bd827f01ffc9a7000000000000000000000000000000000000000000000000000000006117f5565b801561161357506117ee827fffffffff000000000000000000000000000000000000000000000000000000006117f5565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156118ad575060208210155b8015610d3f575015159695505050505050565b6040518061040001604052806020906020820280368337509192915050565b828054828255906000526020600020908101928215611957579160200282015b828111156119575781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906118ff565b50611963929150611967565b5090565b5b808211156119635760008155600101611968565b803573ffffffffffffffffffffffffffffffffffffffff811681146119a057600080fd5b919050565b60008083601f8401126119b757600080fd5b50813567ffffffffffffffff8111156119cf57600080fd5b6020830191508360208285010111156119e757600080fd5b9250929050565b60008083601f840112611a0057600080fd5b50813567ffffffffffffffff811115611a1857600080fd5b6020830191508360208260051b85010111156119e757600080fd5b60008060008060008060006080888a031215611a4e57600080fd5b611a578861197c565b9650602088013567ffffffffffffffff80821115611a7457600080fd5b611a808b838c016119a5565b909850965060408a0135915080821115611a9957600080fd5b611aa58b838c016119a5565b909650945060608a0135915080821115611abe57600080fd5b50611acb8a828b016119ee565b989b979a50959850939692959293505050565b60006020808352835180602085015260005b81811015611b0c57858101830151858201604001528201611af0565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600080600080600080600060a0888a031215611b6657600080fd5b87359650611b766020890161197c565b9550611b846040890161197c565b9450606088013567ffffffffffffffff80821115611ba157600080fd5b611bad8b838c016119a5565b909650945060808a0135915080821115611bc657600080fd5b50611acb8a828b016119a5565b600080600060608486031215611be857600080fd5b611bf18461197c565b92506020840135915060408401357fffff00000000000000000000000000000000000000000000000000000000000081168114611c2d57600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602082015160c082019060048110611cac577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060208401525073ffffffffffffffffffffffffffffffffffffffff604084015116604083015260608301511515606083015260808301511515608083015260a0830151611d0860a084018269ffffffffffffffffffff169052565b5092915050565b600060208284031215611d2157600080fd5b6116108261197c565b803563ffffffff811681146119a057600080fd5b600080600080600060808688031215611d5657600080fd5b611d5f86611d2a565b9450611d6d60208701611d2a565b9350604086013560ff81168114611d8357600080fd5b9250606086013567ffffffffffffffff811115611d9f57600080fd5b611dab888289016119ee565b969995985093965092949392505050565b60008060408385031215611dcf57600080fd5b611dd883611d2a565b9150611de660208401611d2a565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216019081111561161357611613611def565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611ec557600080fd5b83018035915067ffffffffffffffff821115611ee057600080fd5b6020019150368190038213156119e757600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000611f52602083018486611ef5565b949350505050565b60008085851115611f6a57600080fd5b83861115611f7757600080fd5b5050820193919092039150565b80356020831015611613577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525060a0606083015261200060a083018688611ef5565b8281036080840152612013818587611ef5565b9a9950505050505050505050565b60006020828403121561203357600080fd5b8151801515811461204357600080fd5b9392505050565b8082018082111561161357611613611def565b8181038181111561161357611613611def565b604081526000612084604083018688611ef5565b8281036020840152610d3f818587611ef5565b60ff8181168382160290811690818114611d0857611d08611def565b60ff8416815260406020808301829052908201839052600090849060608401835b8681101561210d5773ffffffffffffffffffffffffffffffffffffffff6120fa8561197c565b16825292820192908201906001016120d4565b50979650505050505050565b60006040820160ff8516835260206040602085015281855180845260608601915060208701935060005b8181101561217557845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101612143565b509097965050505050505056fea164736f6c6343000818000a", } var KeystoneForwarderABI = KeystoneForwarderMetaData.ABI diff --git a/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go b/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go index e51f4762d88..a83278f0e42 100644 --- a/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go +++ b/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go @@ -31,8 +31,8 @@ var ( ) var OCR3CapabilityMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"ReportInvalid\",\"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\":\"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\":\"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\":\"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\":\"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\":\"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\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fe180620001606000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80638da5cb5b11610076578063b1dc65a41161005b578063b1dc65a4146101c4578063e3d0e712146101d7578063f2fde38b146101ea57600080fd5b80638da5cb5b1461017c578063afcb95d7146101a457600080fd5b8063181f5a77146100a857806379ba5097146100f057806381411834146100fa57806381ff70481461010f575b600080fd5b604080518082018252600e81527f4b657973746f6e6520312e302e30000000000000000000000000000000000000602082015290516100e79190611883565b60405180910390f35b6100f86101fd565b005b6101026102ff565b6040516100e791906118ef565b61015960015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff9485168152939092166020840152908201526060016100e7565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e7565b6040805160018152600060208201819052918101919091526060016100e7565b6100f86101d236600461194e565b61036e565b6100f86101e5366004611c18565b610975565b6100f86101f8366004611ce5565b6114e0565b60015473ffffffffffffffffffffffffffffffffffffffff163314610283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6060600680548060200260200160405190810160405280929190818152602001828054801561036457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610339575b5050505050905090565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16103cf8a8a8a8a8a8a6114f4565b6003546000906002906103ed9060ff80821691610100900416611d5e565b6103f79190611d7d565b610402906001611d5e565b60ff169050878114610470576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e617475726573000000000000604482015260640161027a565b8786146104ff576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f7265706f727420727320616e64207373206d757374206265206f66206571756160448201527f6c206c656e677468000000000000000000000000000000000000000000000000606482015260840161027a565b3360009081526004602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561054257610542611dc6565b600281111561055357610553611dc6565b905250905060028160200151600281111561057057610570611dc6565b141580156105b957506006816000015160ff168154811061059357610593611d00565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b15610620576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015260640161027a565b5050505061062c611800565b6000808a8a60405161063f929190611df5565b604051908190038120610656918e90602001611e05565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b898110156109575760006001848984602081106106bf576106bf611d00565b6106cc91901a601b611d5e565b8e8e868181106106de576106de611d00565b905060200201358d8d878181106106f7576106f7611d00565b9050602002013560405160008152602001604052604051610734949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610756573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff808216855292965092945084019161010090041660028111156107d6576107d6611dc6565b60028111156107e7576107e7611dc6565b905250925060018360200151600281111561080457610804611dc6565b1461086b576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e0000604482015260640161027a565b8251600090879060ff16601f811061088557610885611d00565b602002015173ffffffffffffffffffffffffffffffffffffffff1614610907576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e6174757265000000000000000000000000604482015260640161027a565b8086846000015160ff16601f811061092157610921611d00565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015261094c600186611d5e565b9450506001016106a0565b505050610968833383858e8e6115ab565b5050505050505050505050565b855185518560ff16601f8311156109e8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e65727300000000000000000000000000000000604482015260640161027a565b80600003610a52576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f7369746976650000000000000000000000000000604482015260640161027a565b818314610ae0576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e00000000000000000000000000000000000000000000000000000000606482015260840161027a565b610aeb816003611e19565b8311610b53576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f20686967680000000000000000604482015260640161027a565b610b5b6115dd565b6040805160c0810182528a8152602081018a905260ff8916918101919091526060810187905267ffffffffffffffff8616608082015260a081018590525b60055415610d4e57600554600090610bb390600190611e30565b9050600060058281548110610bca57610bca611d00565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110610c0457610c04611d00565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080610c8457610c84611e43565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480610ced57610ced611e43565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550610b99915050565b60005b8151518110156112fd57815180516000919083908110610d7357610d73611d00565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610df8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f7369676e6572206d757374206e6f7420626520656d7074790000000000000000604482015260640161027a565b600073ffffffffffffffffffffffffffffffffffffffff1682602001518281518110610e2657610e26611d00565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610eab576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d707479000000604482015260640161027a565b60006004600084600001518481518110610ec757610ec7611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610f1157610f11611dc6565b14610f78576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015260640161027a565b6040805180820190915260ff82168152600160208201528251805160049160009185908110610fa957610fa9611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561104a5761104a611dc6565b02179055506000915061105a9050565b600460008460200151848151811061107457611074611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff1660028111156110be576110be611dc6565b14611125576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015260640161027a565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061115857611158611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156111f9576111f9611dc6565b02179055505082518051600592508390811061121757611217611d00565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558201518051600691908390811061129357611293611d00565b60209081029190910181015182546001808201855560009485529290932090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915501610d51565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916113b591849174010000000000000000000000000000000000000000900416611e72565b92506101000a81548163ffffffff021916908363ffffffff1602179055506114144630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a00151611660565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986114cb988b9891977401000000000000000000000000000000000000000090920463ffffffff16969095919491939192611e96565b60405180910390a15050505050505050505050565b6114e86115dd565b6114f18161170b565b50565b6000611501826020611e19565b61150c856020611e19565b61151888610144611f2c565b6115229190611f2c565b61152c9190611f2c565b611537906000611f2c565b90503681146115a2576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d617463680000000000000000604482015260640161027a565b50505050505050565b6040517f0750181900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461165e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161027a565b565b6000808a8a8a8a8a8a8a8a8a60405160200161168499989796959493929190611f3f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361178a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161027a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b604051806103e00160405280601f906020820280368337509192915050565b6000815180845260005b8181101561184557602081850181015186830182015201611829565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611896602083018461181f565b9392505050565b60008151808452602080850194506020840160005b838110156118e457815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016118b2565b509495945050505050565b602081526000611896602083018461189d565b60008083601f84011261191457600080fd5b50813567ffffffffffffffff81111561192c57600080fd5b6020830191508360208260051b850101111561194757600080fd5b9250929050565b60008060008060008060008060e0898b03121561196a57600080fd5b606089018a81111561197b57600080fd5b8998503567ffffffffffffffff8082111561199557600080fd5b818b0191508b601f8301126119a957600080fd5b8135818111156119b857600080fd5b8c60208285010111156119ca57600080fd5b6020830199508098505060808b01359150808211156119e857600080fd5b6119f48c838d01611902565b909750955060a08b0135915080821115611a0d57600080fd5b50611a1a8b828c01611902565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611aa957611aa9611a33565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611ad557600080fd5b919050565b600082601f830112611aeb57600080fd5b8135602067ffffffffffffffff821115611b0757611b07611a33565b8160051b611b16828201611a62565b9283528481018201928281019087851115611b3057600080fd5b83870192505b84831015611b5657611b4783611ab1565b82529183019190830190611b36565b979650505050505050565b803560ff81168114611ad557600080fd5b600082601f830112611b8357600080fd5b813567ffffffffffffffff811115611b9d57611b9d611a33565b611bce60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611a62565b818152846020838601011115611be357600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff81168114611ad557600080fd5b60008060008060008060c08789031215611c3157600080fd5b863567ffffffffffffffff80821115611c4957600080fd5b611c558a838b01611ada565b97506020890135915080821115611c6b57600080fd5b611c778a838b01611ada565b9650611c8560408a01611b61565b95506060890135915080821115611c9b57600080fd5b611ca78a838b01611b72565b9450611cb560808a01611c00565b935060a0890135915080821115611ccb57600080fd5b50611cd889828a01611b72565b9150509295509295509295565b600060208284031215611cf757600080fd5b61189682611ab1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160190811115611d7757611d77611d2f565b92915050565b600060ff831680611db7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b8082028115828204841417611d7757611d77611d2f565b81810381811115611d7757611d77611d2f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115611e8f57611e8f611d2f565b5092915050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152611ec68184018a61189d565b90508281036080840152611eda818961189d565b905060ff871660a084015282810360c0840152611ef7818761181f565b905067ffffffffffffffff851660e0840152828103610100840152611f1c818561181f565b9c9b505050505050505050505050565b80820180821115611d7757611d77611d2f565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152611f868285018b61189d565b91508382036080850152611f9a828a61189d565b915060ff881660a085015283820360c0850152611fb7828861181f565b90861660e08501528381036101008501529050611f1c818561181f56fea164736f6c6343000818000a", + 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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112bc806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610169578063afcb95d714610191578063b1dc65a4146101b1578063f2fde38b146101c457600080fd5b8063181f5a771461008d57806379ba5097146100df5780637f3c87d3146100e957806381ff7048146100fc575b600080fd5b6100c96040518060400160405280600e81526020017f4b657973746f6e6520312e302e3000000000000000000000000000000000000081525081565b6040516100d69190610b8a565b60405180910390f35b6100e76101d7565b005b6100e76100f7366004610cf8565b6102d9565b61014660015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff9485168152939092166020840152908201526060016100d6565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d6565b6040805160018152600060208201819052918101919091526060016100d6565b6100e76101bf366004610dd4565b6108b7565b6100e76101d2366004610edd565b6108e9565b60015473ffffffffffffffffffffffffffffffffffffffff16331461025d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b868560ff8616601f83111561034a576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610254565b806000036103b4576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610254565b818314610442576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610254565b61044d816003610f27565b83116104b5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610254565b6104bd6108fd565b60005b8a8110156107255760008a8a838181106104dc576104dc610f44565b90506020020160208101906104f19190610edd565b73ffffffffffffffffffffffffffffffffffffffff160361056e576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d7074790000006044820152606401610254565b3660008d8d8481811061058357610583610f44565b90506020028101906105959190610f73565b9092509050600061ffff82165b8082101561071657806105b6836003610fd8565b111561061e576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e76616c6964207369676e6572207075624b657920656e636f64696e6700006044820152606401610254565b60006008858561062f866002610fd8565b81811061063e5761063e610f44565b919091013560f81c90911b90508585610658866001610fd8565b81811061066757610667610f44565b6106789392013560f81c9050610fd8565b90508181610687856003610fd8565b6106919190610fd8565b11156106f9576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e76616c6964207369676e6572207075624b657920656e636f64696e6700006044820152606401610254565b610704816003610fd8565b61070e9084610fd8565b9250506105a2565b505050508060010190506104c0565b50600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8916179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916107d491849174010000000000000000000000000000000000000000900416610feb565b92506101000a81548163ffffffff021916908363ffffffff16021790555061081d4630600160149054906101000a900463ffffffff1663ffffffff168f8f8f8f8f8f8f8f610980565b6002600001819055508b8b9050600260010160016101000a81548160ff021916908360ff1602179055507f36257c6e8d535293ad661e377c0baac536289be6707b8a488ac175ddaa4055c881600260000154600160149054906101000a900463ffffffff168f8f8f8f8f8f8f8f6040516108a19b9a9998979695949392919061117e565b60405180910390a1505050505050505050505050565b6040517f0750181900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108f16108fd565b6108fa81610a31565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461097e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610254565b565b6000808c8c8c8c8c8c8c8c8c8c8c6040516020016109a89b9a99989796959493929190611218565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0e000000000000000000000000000000000000000000000000000000000000179150509b9a5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610ab0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610254565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000815180845260005b81811015610b4c57602081850181015186830182015201610b30565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b9d6020830184610b26565b9392505050565b60008083601f840112610bb657600080fd5b50813567ffffffffffffffff811115610bce57600080fd5b6020830191508360208260051b8501011115610be957600080fd5b9250929050565b803560ff81168114610c0157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c4657600080fd5b813567ffffffffffffffff80821115610c6157610c61610c06565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610ca757610ca7610c06565b81604052838152866020858801011115610cc057600080fd5b836020870160208301376000602085830101528094505050505092915050565b803567ffffffffffffffff81168114610c0157600080fd5b60008060008060008060008060c0898b031215610d1457600080fd5b883567ffffffffffffffff80821115610d2c57600080fd5b610d388c838d01610ba4565b909a50985060208b0135915080821115610d5157600080fd5b610d5d8c838d01610ba4565b9098509650869150610d7160408c01610bf0565b955060608b0135915080821115610d8757600080fd5b610d938c838d01610c35565b9450610da160808c01610ce0565b935060a08b0135915080821115610db757600080fd5b50610dc48b828c01610c35565b9150509295985092959890939650565b60008060008060008060008060e0898b031215610df057600080fd5b606089018a811115610e0157600080fd5b8998503567ffffffffffffffff80821115610e1b57600080fd5b818b0191508b601f830112610e2f57600080fd5b813581811115610e3e57600080fd5b8c6020828501011115610e5057600080fd5b6020830199508098505060808b0135915080821115610e6e57600080fd5b610e7a8c838d01610ba4565b909750955060a08b0135915080821115610e9357600080fd5b50610ea08b828c01610ba4565b999c989b50969995989497949560c00135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610c0157600080fd5b600060208284031215610eef57600080fd5b610b9d82610eb9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f3e57610f3e610ef8565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610fa857600080fd5b83018035915067ffffffffffffffff821115610fc357600080fd5b602001915036819003821315610be957600080fd5b80820180821115610f3e57610f3e610ef8565b63ffffffff81811683821601908082111561100857611008610ef8565b5092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000838385526020808601955060208560051b8301018460005b8781101561111d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126110d357600080fd5b8701848101903567ffffffffffffffff8111156110ef57600080fd5b8036038213156110fe57600080fd5b61110985828461100f565b9a86019a9450505090830190600101611072565b5090979650505050505050565b8183526000602080850194508260005b858110156111735773ffffffffffffffffffffffffffffffffffffffff61116083610eb9565b168752958201959082019060010161113a565b509495945050505050565b600061012063ffffffff808f1684528d6020850152808d166040850152508060608401526111af8184018b8d611058565b905082810360808401526111c481898b61112a565b905060ff871660a084015282810360c08401526111e18187610b26565b905067ffffffffffffffff851660e08401528281036101008401526112068185610b26565b9e9d5050505050505050505050505050565b60006101208d835273ffffffffffffffffffffffffffffffffffffffff8d16602084015267ffffffffffffffff808d1660408501528160608501526112608285018c8e611058565b91508382036080850152611275828a8c61112a565b915060ff881660a085015283820360c08501526112928288610b26565b90861660e085015283810361010085015290506112068185610b2656fea164736f6c6343000818000a", } var OCR3CapabilityABI = OCR3CapabilityMetaData.ABI @@ -255,26 +255,24 @@ func (_OCR3Capability *OCR3CapabilityCallerSession) Owner() (common.Address, err return _OCR3Capability.Contract.Owner(&_OCR3Capability.CallOpts) } -func (_OCR3Capability *OCR3CapabilityCaller) Transmitters(opts *bind.CallOpts) ([]common.Address, error) { +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, "transmitters") + err := _OCR3Capability.contract.Call(opts, &out, "transmit", arg0, arg1, arg2, arg3, arg4) if err != nil { - return *new([]common.Address), err + return err } - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err + return err } -func (_OCR3Capability *OCR3CapabilitySession) Transmitters() ([]common.Address, error) { - return _OCR3Capability.Contract.Transmitters(&_OCR3Capability.CallOpts) +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) Transmitters() ([]common.Address, error) { - return _OCR3Capability.Contract.Transmitters(&_OCR3Capability.CallOpts) +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) { @@ -311,15 +309,15 @@ func (_OCR3Capability *OCR3CapabilityTransactorSession) AcceptOwnership() (*type return _OCR3Capability.Contract.AcceptOwnership(&_OCR3Capability.TransactOpts) } -func (_OCR3Capability *OCR3CapabilityTransactor) SetConfig(opts *bind.TransactOpts, _signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { +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 []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { +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 []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { +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) } @@ -335,18 +333,6 @@ func (_OCR3Capability *OCR3CapabilityTransactorSession) TransferOwnership(to com return _OCR3Capability.Contract.TransferOwnership(&_OCR3Capability.TransactOpts, to) } -func (_OCR3Capability *OCR3CapabilityTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _OCR3Capability.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) -} - -func (_OCR3Capability *OCR3CapabilitySession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _OCR3Capability.Contract.Transmit(&_OCR3Capability.TransactOpts, reportContext, report, rs, ss, rawVs) -} - -func (_OCR3Capability *OCR3CapabilityTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { - return _OCR3Capability.Contract.Transmit(&_OCR3Capability.TransactOpts, reportContext, report, rs, ss, rawVs) -} - type OCR3CapabilityConfigSetIterator struct { Event *OCR3CapabilityConfigSet @@ -411,7 +397,7 @@ type OCR3CapabilityConfigSet struct { PreviousConfigBlockNumber uint32 ConfigDigest [32]byte ConfigCount uint64 - Signers []common.Address + Signers [][]byte Transmitters []common.Address F uint8 OnchainConfig []byte @@ -890,7 +876,7 @@ func (_OCR3Capability *OCR3Capability) ParseLog(log types.Log) (generated.Abigen } func (OCR3CapabilityConfigSet) Topic() common.Hash { - return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") + return common.HexToHash("0x36257c6e8d535293ad661e377c0baac536289be6707b8a488ac175ddaa4055c8") } func (OCR3CapabilityOwnershipTransferRequested) Topic() common.Hash { @@ -920,18 +906,16 @@ type OCR3CapabilityInterface interface { Owner(opts *bind.CallOpts) (common.Address, error) - Transmitters(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 []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*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) - Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - FilterConfigSet(opts *bind.FilterOpts) (*OCR3CapabilityConfigSetIterator, error) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityConfigSet) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 30396c12e70..c6573ab5cb8 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,5 +1,5 @@ GETH_VERSION: 1.13.8 -capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 7e95d72f24940f08ada0ee3b85d894d6bfccfd6c8a3e0ceeff65bae52c899d54 -feeds_consumer: ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin 8c3a2b18a80be41e7c40d2bc3a4c8d1b5e18d55c1fd20ad5af68cebb66109fc5 -forwarder: ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin 45d9b866c64b41c1349a90b6764aee42a6d078b454d38f369b5fe02b23b9d16e -ocr3_capability: ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin 8bf0f53f222efce7143dea6134552eb26ea1eef845407b4475a0d79b7d7ba9f8 +capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 1250614381238d54ec35070c4eaed2884d6fba28ebb75e890600c820e44fc98c +feeds_consumer: ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin 6ac5b12eff3b022a35c3c40d5ed0285bf9bfec0e3669a4b12307332a216048ca +forwarder: ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin 03911334d0c88f8ee8ee2d9832fd312bc8a48c824fcda5c807585af2d0e6a148 +ocr3_capability: ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin 509af20993cc8d7f4e84d55a3f1316d4bb9ab706f9a50a91ac72de96dbc1244e diff --git a/core/gethwrappers/llo-feeds/generated/channel_config_store/channel_config_store.go b/core/gethwrappers/llo-feeds/generated/channel_config_store/channel_config_store.go index 3c67b642273..7dd4407b3a3 100644 --- a/core/gethwrappers/llo-feeds/generated/channel_config_store/channel_config_store.go +++ b/core/gethwrappers/llo-feeds/generated/channel_config_store/channel_config_store.go @@ -30,15 +30,9 @@ var ( _ = abi.ConvertType ) -type IChannelConfigStoreChannelDefinition struct { - ReportFormat uint32 - ChainSelector uint64 - StreamIDs []uint32 -} - var ChannelConfigStoreMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ChannelDefinitionNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyStreamIDs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByEOA\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StagingConfigAlreadyPromoted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroReportFormat\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"channelId\",\"type\":\"uint32\"}],\"name\":\"ChannelDefinitionRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"channelId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"reportFormat\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint32[]\",\"name\":\"streamIDs\",\"type\":\"uint32[]\"}],\"indexed\":false,\"internalType\":\"structIChannelConfigStore.ChannelDefinition\",\"name\":\"channelDefinition\",\"type\":\"tuple\"}],\"name\":\"NewChannelDefinition\",\"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\":\"uint32\",\"name\":\"channelId\",\"type\":\"uint32\"}],\"name\":\"PromoteStagingConfig\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"channelId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"reportFormat\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint32[]\",\"name\":\"streamIDs\",\"type\":\"uint32[]\"}],\"internalType\":\"structIChannelConfigStore.ChannelDefinition\",\"name\":\"channelDefinition\",\"type\":\"tuple\"}],\"name\":\"addChannel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"channelId\",\"type\":\"uint32\"}],\"name\":\"getChannelDefinitions\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"reportFormat\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint32[]\",\"name\":\"streamIDs\",\"type\":\"uint32[]\"}],\"internalType\":\"structIChannelConfigStore.ChannelDefinition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"channelId\",\"type\":\"uint32\"}],\"name\":\"removeChannel\",\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610e4f806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146101535780639682a4501461017b578063f2fde38b1461018e578063f5810719146101a157600080fd5b806301ffc9a71461008d578063181f5a77146100f757806379ba5097146101365780637e37e71914610140575b600080fd5b6100e261009b3660046107d1565b7fffffffff00000000000000000000000000000000000000000000000000000000167f1d344450000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4368616e6e656c436f6e66696753746f726520302e302e300000000000000000602082015290516100ee919061081a565b61013e6101c1565b005b61013e61014e366004610898565b6102c3565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ee565b61013e6101893660046108b5565b6103a3565b61013e61019c36600461090c565b6104f3565b6101b46101af366004610898565b610507565b6040516100ee9190610942565b60015473ffffffffffffffffffffffffffffffffffffffff163314610247576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6102cb610620565b63ffffffff8116600090815260026020526040812060010154900361031c576040517fd1a751e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8116600090815260026020526040812080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168155906103656001830182610798565b505060405163ffffffff821681527f334e877e9691ecae0660510061973bebaa8b4fb37332ed6090052e630c9798619060200160405180910390a150565b6103ab610620565b6103b860408201826109bc565b90506000036103f3576040517f4b620e2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104036040820160208301610a41565b67ffffffffffffffff16600003610446576040517ff89d762900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104536020820182610898565b63ffffffff16600003610492576040517febd3ef0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8216600090815260026020526040902081906104b38282610c37565b9050507f35d63e43dd8abd374a4c4e0b5b02c8294dd20e1f493e7344a1751123d11ecc1482826040516104e7929190610d7f565b60405180910390a15050565b6104fb610620565b610504816106a3565b50565b6040805160608082018352600080835260208301529181019190915233321461055c576040517f74e2cd5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82811660009081526002602090815260409182902082516060810184528154948516815264010000000090940467ffffffffffffffff16848301526001810180548451818502810185018652818152929486019383018282801561061057602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116105d35790505b5050505050815250509050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161023e565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161023e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b50805460008255600701600890049060005260206000209081019061050491905b808211156107cd57600081556001016107b9565b5090565b6000602082840312156107e357600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461081357600080fd5b9392505050565b600060208083528351808285015260005b818110156108475785810183015185820160400152820161082b565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b63ffffffff8116811461050457600080fd5b6000602082840312156108aa57600080fd5b813561081381610886565b600080604083850312156108c857600080fd5b82356108d381610886565b9150602083013567ffffffffffffffff8111156108ef57600080fd5b83016060818603121561090157600080fd5b809150509250929050565b60006020828403121561091e57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461081357600080fd5b600060208083526080830163ffffffff808651168386015267ffffffffffffffff83870151166040860152604086015160608087015282815180855260a0880191508583019450600092505b808310156109b05784518416825293850193600192909201919085019061098e565b50979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126109f157600080fd5b83018035915067ffffffffffffffff821115610a0c57600080fd5b6020019150600581901b3603821315610a2457600080fd5b9250929050565b67ffffffffffffffff8116811461050457600080fd5b600060208284031215610a5357600080fd5b813561081381610a2b565b60008135610a6b81610886565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b68010000000000000000821115610ab957610ab9610a71565b805482825580831015610b3e576000828152602081206007850160031c81016007840160031c82019150601c8660021b168015610b25577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8083018054828460200360031b1c16815550505b505b81811015610b3a57828155600101610b27565b5050505b505050565b67ffffffffffffffff831115610b5b57610b5b610a71565b610b658382610aa0565b60008181526020902082908460031c60005b81811015610bd0576000805b6008811015610bc357610bb2610b9887610a5e565b63ffffffff908116600584901b90811b91901b1984161790565b602096909601959150600101610b83565b5083820155600101610b77565b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff88616808703818814610c2d576000805b82811015610c2757610c16610b9888610a5e565b602097909701969150600101610c02565b50848401555b5050505050505050565b8135610c4281610886565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135610c8281610a2b565b6bffffffffffffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffff00000000000000000000000084161717845550505060408201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112610cf457600080fd5b8201803567ffffffffffffffff811115610d0d57600080fd5b6020820191508060051b3603821315610d2557600080fd5b610d33818360018601610b43565b50505050565b8183526000602080850194508260005b85811015610d74578135610d5c81610886565b63ffffffff1687529582019590820190600101610d49565b509495945050505050565b600063ffffffff8085168352604060208401528335610d9d81610886565b1660408301526020830135610db181610a2b565b67ffffffffffffffff8082166060850152604085013591507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018212610df957600080fd5b6020918501918201913581811115610e1057600080fd5b8060051b3603831315610e2257600080fd5b60606080860152610e3760a086018285610d39565b97965050505050505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"donId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"sha\",\"type\":\"bytes32\"}],\"name\":\"NewChannelDefinition\",\"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\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"sha\",\"type\":\"bytes32\"}],\"name\":\"setChannelDefinitions\",\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6106d2806101576000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806379ba50971161005057806379ba5097146101355780638da5cb5b1461013d578063f2fde38b1461016557600080fd5b806301ffc9a714610077578063181f5a77146100e15780635ba5bac214610120575b600080fd5b6100cc610085366004610483565b7fffffffff00000000000000000000000000000000000000000000000000000000167f5ba5bac2000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4368616e6e656c436f6e66696753746f726520302e302e310000000000000000602082015290516100d891906104cc565b61013361012e366004610538565b610178565b005b6101336101f5565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d8565b6101336101733660046105cc565b6102f7565b61018061030b565b63ffffffff84166000908152600260205260408120805482906101a290610602565b91905081905590508463ffffffff167fe5b641a7879fb491e4e5a35a1ce950f0237b2537ee9b1b1e4fb65e29aff1f5e8828686866040516101e69493929190610661565b60405180910390a25050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461027b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6102ff61030b565b6103088161038e565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461038c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610272565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361040d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610272565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020828403121561049557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146104c557600080fd5b9392505050565b600060208083528351808285015260005b818110156104f9578581018301518582016040015282016104dd565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806000806060858703121561054e57600080fd5b843563ffffffff8116811461056257600080fd5b9350602085013567ffffffffffffffff8082111561057f57600080fd5b818701915087601f83011261059357600080fd5b8135818111156105a257600080fd5b8860208285010111156105b457600080fd5b95986020929092019750949560400135945092505050565b6000602082840312156105de57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146104c557600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361065a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b63ffffffff851681526060602082015282606082015282846080830137600060808483010152600060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011683010190508260408301529594505050505056fea164736f6c6343000813000a", } var ChannelConfigStoreABI = ChannelConfigStoreMetaData.ABI @@ -177,28 +171,6 @@ func (_ChannelConfigStore *ChannelConfigStoreTransactorRaw) Transact(opts *bind. return _ChannelConfigStore.Contract.contract.Transact(opts, method, params...) } -func (_ChannelConfigStore *ChannelConfigStoreCaller) GetChannelDefinitions(opts *bind.CallOpts, channelId uint32) (IChannelConfigStoreChannelDefinition, error) { - var out []interface{} - err := _ChannelConfigStore.contract.Call(opts, &out, "getChannelDefinitions", channelId) - - if err != nil { - return *new(IChannelConfigStoreChannelDefinition), err - } - - out0 := *abi.ConvertType(out[0], new(IChannelConfigStoreChannelDefinition)).(*IChannelConfigStoreChannelDefinition) - - return out0, err - -} - -func (_ChannelConfigStore *ChannelConfigStoreSession) GetChannelDefinitions(channelId uint32) (IChannelConfigStoreChannelDefinition, error) { - return _ChannelConfigStore.Contract.GetChannelDefinitions(&_ChannelConfigStore.CallOpts, channelId) -} - -func (_ChannelConfigStore *ChannelConfigStoreCallerSession) GetChannelDefinitions(channelId uint32) (IChannelConfigStoreChannelDefinition, error) { - return _ChannelConfigStore.Contract.GetChannelDefinitions(&_ChannelConfigStore.CallOpts, channelId) -} - func (_ChannelConfigStore *ChannelConfigStoreCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _ChannelConfigStore.contract.Call(opts, &out, "owner") @@ -277,28 +249,16 @@ func (_ChannelConfigStore *ChannelConfigStoreTransactorSession) AcceptOwnership( return _ChannelConfigStore.Contract.AcceptOwnership(&_ChannelConfigStore.TransactOpts) } -func (_ChannelConfigStore *ChannelConfigStoreTransactor) AddChannel(opts *bind.TransactOpts, channelId uint32, channelDefinition IChannelConfigStoreChannelDefinition) (*types.Transaction, error) { - return _ChannelConfigStore.contract.Transact(opts, "addChannel", channelId, channelDefinition) -} - -func (_ChannelConfigStore *ChannelConfigStoreSession) AddChannel(channelId uint32, channelDefinition IChannelConfigStoreChannelDefinition) (*types.Transaction, error) { - return _ChannelConfigStore.Contract.AddChannel(&_ChannelConfigStore.TransactOpts, channelId, channelDefinition) -} - -func (_ChannelConfigStore *ChannelConfigStoreTransactorSession) AddChannel(channelId uint32, channelDefinition IChannelConfigStoreChannelDefinition) (*types.Transaction, error) { - return _ChannelConfigStore.Contract.AddChannel(&_ChannelConfigStore.TransactOpts, channelId, channelDefinition) -} - -func (_ChannelConfigStore *ChannelConfigStoreTransactor) RemoveChannel(opts *bind.TransactOpts, channelId uint32) (*types.Transaction, error) { - return _ChannelConfigStore.contract.Transact(opts, "removeChannel", channelId) +func (_ChannelConfigStore *ChannelConfigStoreTransactor) SetChannelDefinitions(opts *bind.TransactOpts, donId uint32, url string, sha [32]byte) (*types.Transaction, error) { + return _ChannelConfigStore.contract.Transact(opts, "setChannelDefinitions", donId, url, sha) } -func (_ChannelConfigStore *ChannelConfigStoreSession) RemoveChannel(channelId uint32) (*types.Transaction, error) { - return _ChannelConfigStore.Contract.RemoveChannel(&_ChannelConfigStore.TransactOpts, channelId) +func (_ChannelConfigStore *ChannelConfigStoreSession) SetChannelDefinitions(donId uint32, url string, sha [32]byte) (*types.Transaction, error) { + return _ChannelConfigStore.Contract.SetChannelDefinitions(&_ChannelConfigStore.TransactOpts, donId, url, sha) } -func (_ChannelConfigStore *ChannelConfigStoreTransactorSession) RemoveChannel(channelId uint32) (*types.Transaction, error) { - return _ChannelConfigStore.Contract.RemoveChannel(&_ChannelConfigStore.TransactOpts, channelId) +func (_ChannelConfigStore *ChannelConfigStoreTransactorSession) SetChannelDefinitions(donId uint32, url string, sha [32]byte) (*types.Transaction, error) { + return _ChannelConfigStore.Contract.SetChannelDefinitions(&_ChannelConfigStore.TransactOpts, donId, url, sha) } func (_ChannelConfigStore *ChannelConfigStoreTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { @@ -313,123 +273,6 @@ func (_ChannelConfigStore *ChannelConfigStoreTransactorSession) TransferOwnershi return _ChannelConfigStore.Contract.TransferOwnership(&_ChannelConfigStore.TransactOpts, to) } -type ChannelConfigStoreChannelDefinitionRemovedIterator struct { - Event *ChannelConfigStoreChannelDefinitionRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelConfigStoreChannelDefinitionRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelConfigStoreChannelDefinitionRemoved) - 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(ChannelConfigStoreChannelDefinitionRemoved) - 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 *ChannelConfigStoreChannelDefinitionRemovedIterator) Error() error { - return it.fail -} - -func (it *ChannelConfigStoreChannelDefinitionRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelConfigStoreChannelDefinitionRemoved struct { - ChannelId uint32 - Raw types.Log -} - -func (_ChannelConfigStore *ChannelConfigStoreFilterer) FilterChannelDefinitionRemoved(opts *bind.FilterOpts) (*ChannelConfigStoreChannelDefinitionRemovedIterator, error) { - - logs, sub, err := _ChannelConfigStore.contract.FilterLogs(opts, "ChannelDefinitionRemoved") - if err != nil { - return nil, err - } - return &ChannelConfigStoreChannelDefinitionRemovedIterator{contract: _ChannelConfigStore.contract, event: "ChannelDefinitionRemoved", logs: logs, sub: sub}, nil -} - -func (_ChannelConfigStore *ChannelConfigStoreFilterer) WatchChannelDefinitionRemoved(opts *bind.WatchOpts, sink chan<- *ChannelConfigStoreChannelDefinitionRemoved) (event.Subscription, error) { - - logs, sub, err := _ChannelConfigStore.contract.WatchLogs(opts, "ChannelDefinitionRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(ChannelConfigStoreChannelDefinitionRemoved) - if err := _ChannelConfigStore.contract.UnpackLog(event, "ChannelDefinitionRemoved", 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 (_ChannelConfigStore *ChannelConfigStoreFilterer) ParseChannelDefinitionRemoved(log types.Log) (*ChannelConfigStoreChannelDefinitionRemoved, error) { - event := new(ChannelConfigStoreChannelDefinitionRemoved) - if err := _ChannelConfigStore.contract.UnpackLog(event, "ChannelDefinitionRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - type ChannelConfigStoreNewChannelDefinitionIterator struct { Event *ChannelConfigStoreNewChannelDefinition @@ -491,23 +334,35 @@ func (it *ChannelConfigStoreNewChannelDefinitionIterator) Close() error { } type ChannelConfigStoreNewChannelDefinition struct { - ChannelId uint32 - ChannelDefinition IChannelConfigStoreChannelDefinition - Raw types.Log + DonId *big.Int + Version uint32 + Url string + Sha [32]byte + Raw types.Log } -func (_ChannelConfigStore *ChannelConfigStoreFilterer) FilterNewChannelDefinition(opts *bind.FilterOpts) (*ChannelConfigStoreNewChannelDefinitionIterator, error) { +func (_ChannelConfigStore *ChannelConfigStoreFilterer) FilterNewChannelDefinition(opts *bind.FilterOpts, donId []*big.Int) (*ChannelConfigStoreNewChannelDefinitionIterator, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } - logs, sub, err := _ChannelConfigStore.contract.FilterLogs(opts, "NewChannelDefinition") + logs, sub, err := _ChannelConfigStore.contract.FilterLogs(opts, "NewChannelDefinition", donIdRule) if err != nil { return nil, err } return &ChannelConfigStoreNewChannelDefinitionIterator{contract: _ChannelConfigStore.contract, event: "NewChannelDefinition", logs: logs, sub: sub}, nil } -func (_ChannelConfigStore *ChannelConfigStoreFilterer) WatchNewChannelDefinition(opts *bind.WatchOpts, sink chan<- *ChannelConfigStoreNewChannelDefinition) (event.Subscription, error) { +func (_ChannelConfigStore *ChannelConfigStoreFilterer) WatchNewChannelDefinition(opts *bind.WatchOpts, sink chan<- *ChannelConfigStoreNewChannelDefinition, donId []*big.Int) (event.Subscription, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } - logs, sub, err := _ChannelConfigStore.contract.WatchLogs(opts, "NewChannelDefinition") + logs, sub, err := _ChannelConfigStore.contract.WatchLogs(opts, "NewChannelDefinition", donIdRule) if err != nil { return nil, err } @@ -820,147 +675,22 @@ func (_ChannelConfigStore *ChannelConfigStoreFilterer) ParseOwnershipTransferred return event, nil } -type ChannelConfigStorePromoteStagingConfigIterator struct { - Event *ChannelConfigStorePromoteStagingConfig - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelConfigStorePromoteStagingConfigIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelConfigStorePromoteStagingConfig) - 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(ChannelConfigStorePromoteStagingConfig) - 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 *ChannelConfigStorePromoteStagingConfigIterator) Error() error { - return it.fail -} - -func (it *ChannelConfigStorePromoteStagingConfigIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelConfigStorePromoteStagingConfig struct { - ChannelId uint32 - Raw types.Log -} - -func (_ChannelConfigStore *ChannelConfigStoreFilterer) FilterPromoteStagingConfig(opts *bind.FilterOpts) (*ChannelConfigStorePromoteStagingConfigIterator, error) { - - logs, sub, err := _ChannelConfigStore.contract.FilterLogs(opts, "PromoteStagingConfig") - if err != nil { - return nil, err - } - return &ChannelConfigStorePromoteStagingConfigIterator{contract: _ChannelConfigStore.contract, event: "PromoteStagingConfig", logs: logs, sub: sub}, nil -} - -func (_ChannelConfigStore *ChannelConfigStoreFilterer) WatchPromoteStagingConfig(opts *bind.WatchOpts, sink chan<- *ChannelConfigStorePromoteStagingConfig) (event.Subscription, error) { - - logs, sub, err := _ChannelConfigStore.contract.WatchLogs(opts, "PromoteStagingConfig") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(ChannelConfigStorePromoteStagingConfig) - if err := _ChannelConfigStore.contract.UnpackLog(event, "PromoteStagingConfig", 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 (_ChannelConfigStore *ChannelConfigStoreFilterer) ParsePromoteStagingConfig(log types.Log) (*ChannelConfigStorePromoteStagingConfig, error) { - event := new(ChannelConfigStorePromoteStagingConfig) - if err := _ChannelConfigStore.contract.UnpackLog(event, "PromoteStagingConfig", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - func (_ChannelConfigStore *ChannelConfigStore) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _ChannelConfigStore.abi.Events["ChannelDefinitionRemoved"].ID: - return _ChannelConfigStore.ParseChannelDefinitionRemoved(log) case _ChannelConfigStore.abi.Events["NewChannelDefinition"].ID: return _ChannelConfigStore.ParseNewChannelDefinition(log) case _ChannelConfigStore.abi.Events["OwnershipTransferRequested"].ID: return _ChannelConfigStore.ParseOwnershipTransferRequested(log) case _ChannelConfigStore.abi.Events["OwnershipTransferred"].ID: return _ChannelConfigStore.ParseOwnershipTransferred(log) - case _ChannelConfigStore.abi.Events["PromoteStagingConfig"].ID: - return _ChannelConfigStore.ParsePromoteStagingConfig(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (ChannelConfigStoreChannelDefinitionRemoved) Topic() common.Hash { - return common.HexToHash("0x334e877e9691ecae0660510061973bebaa8b4fb37332ed6090052e630c979861") -} - func (ChannelConfigStoreNewChannelDefinition) Topic() common.Hash { - return common.HexToHash("0x35d63e43dd8abd374a4c4e0b5b02c8294dd20e1f493e7344a1751123d11ecc14") + return common.HexToHash("0xe5b641a7879fb491e4e5a35a1ce950f0237b2537ee9b1b1e4fb65e29aff1f5e8") } func (ChannelConfigStoreOwnershipTransferRequested) Topic() common.Hash { @@ -971,17 +701,11 @@ func (ChannelConfigStoreOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (ChannelConfigStorePromoteStagingConfig) Topic() common.Hash { - return common.HexToHash("0xbdd8ee023f9979bf23e8af6fd7241f484024e83fb0fabd11bb7fd5e9bed7308a") -} - func (_ChannelConfigStore *ChannelConfigStore) Address() common.Address { return _ChannelConfigStore.address } type ChannelConfigStoreInterface interface { - GetChannelDefinitions(opts *bind.CallOpts, channelId uint32) (IChannelConfigStoreChannelDefinition, error) - Owner(opts *bind.CallOpts) (common.Address, error) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) @@ -990,21 +714,13 @@ type ChannelConfigStoreInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddChannel(opts *bind.TransactOpts, channelId uint32, channelDefinition IChannelConfigStoreChannelDefinition) (*types.Transaction, error) - - RemoveChannel(opts *bind.TransactOpts, channelId uint32) (*types.Transaction, error) + SetChannelDefinitions(opts *bind.TransactOpts, donId uint32, url string, sha [32]byte) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - FilterChannelDefinitionRemoved(opts *bind.FilterOpts) (*ChannelConfigStoreChannelDefinitionRemovedIterator, error) - - WatchChannelDefinitionRemoved(opts *bind.WatchOpts, sink chan<- *ChannelConfigStoreChannelDefinitionRemoved) (event.Subscription, error) - - ParseChannelDefinitionRemoved(log types.Log) (*ChannelConfigStoreChannelDefinitionRemoved, error) - - FilterNewChannelDefinition(opts *bind.FilterOpts) (*ChannelConfigStoreNewChannelDefinitionIterator, error) + FilterNewChannelDefinition(opts *bind.FilterOpts, donId []*big.Int) (*ChannelConfigStoreNewChannelDefinitionIterator, error) - WatchNewChannelDefinition(opts *bind.WatchOpts, sink chan<- *ChannelConfigStoreNewChannelDefinition) (event.Subscription, error) + WatchNewChannelDefinition(opts *bind.WatchOpts, sink chan<- *ChannelConfigStoreNewChannelDefinition, donId []*big.Int) (event.Subscription, error) ParseNewChannelDefinition(log types.Log) (*ChannelConfigStoreNewChannelDefinition, error) @@ -1020,12 +736,6 @@ type ChannelConfigStoreInterface interface { ParseOwnershipTransferred(log types.Log) (*ChannelConfigStoreOwnershipTransferred, error) - FilterPromoteStagingConfig(opts *bind.FilterOpts) (*ChannelConfigStorePromoteStagingConfigIterator, error) - - WatchPromoteStagingConfig(opts *bind.WatchOpts, sink chan<- *ChannelConfigStorePromoteStagingConfig) (event.Subscription, error) - - ParsePromoteStagingConfig(log types.Log) (*ChannelConfigStorePromoteStagingConfig, error) - ParseLog(log types.Log) (generated.AbigenLog, error) Address() common.Address diff --git a/core/gethwrappers/llo-feeds/generated/channel_verifier/channel_verifier.go b/core/gethwrappers/llo-feeds/generated/channel_verifier/channel_verifier.go deleted file mode 100644 index 104cab61040..00000000000 --- a/core/gethwrappers/llo-feeds/generated/channel_verifier/channel_verifier.go +++ /dev/null @@ -1,1583 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package channel_verifier - -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 ChannelVerifierMetaData = &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\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"CannotDeactivateLatestConfig\",\"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\":[],\"name\":\"FeedIdEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"InactiveFeed\",\"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\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"InvalidFeed\",\"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\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDeactivated\",\"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\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"FeedActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"FeedDeactivated\",\"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\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"activateFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"deactivateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"deactivateFeed\",\"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\":\"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\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"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\":\"uint256\",\"name\":\"sourceChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sourceAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"newConfigCount\",\"type\":\"uint32\"},{\"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\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"recipientAddressesAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"setConfigFromSource\",\"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\":\"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: "0x60a06040523480156200001157600080fd5b50604051620020ed380380620020ed8339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051611ef9620001f4600039600061051a0152611ef96000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063564a0a7a1161008c5780638da5cb5b116100665780638da5cb5b14610247578063afcb95d71461026f578063eb1dc803146102a4578063f2fde38b146102b757600080fd5b8063564a0a7a146101fc57806379ba50971461020f57806381ff70481461021757600080fd5b8063181f5a77116100c8578063181f5a77146101815780633d3ac1b5146101c35780633dd86430146101d657806354e68a81146101e957600080fd5b806301ffc9a7146100ef5780630d1d79af146101595780630f672ef41461016e575b600080fd5b6101446100fd3660046113d0565b7fffffffff00000000000000000000000000000000000000000000000000000000167f3d3ac1b5000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b61016c610167366004611419565b6102ca565b005b61016c61017c366004611419565b6103d0565b60408051808201909152601581527f4368616e6e656c566572696669657220302e302e30000000000000000000000060208201525b6040516101509190611496565b6101b66101d13660046114d2565b610500565b61016c6101e4366004611419565b610680565b61016c6101f7366004611866565b6106fd565b61016c61020a366004611419565b61080d565b61016c61088d565b6002546003546040805163ffffffff80851682526401000000009094049093166020840152820152606001610150565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610150565b600354600254604080516000815260208101939093526801000000000000000090910463ffffffff1690820152606001610150565b61016c6102b2366004611986565b61098a565b61016c6102c5366004611a79565b610a52565b6102d2610a63565b80610309576040517fe332262700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602052604081205460ff16900361035b576040517f74eb4b93000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6000818152600560205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055517fa543797a0501218bba8a3daf75a71c8df8d1a7f791f4e44d40e43b6450183cea906103c59083815260200190565b60405180910390a150565b6103d8610a63565b8061040f576040517fe332262700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602052604081205460ff16900361045c576040517f74eb4b9300000000000000000000000000000000000000000000000000000000815260048101829052602401610352565b600354810361049a576040517f67863f4400000000000000000000000000000000000000000000000000000000815260048101829052602401610352565b6000818152600560205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055517f5bfaab86edc1b932e3c334327a591c9ded067cb521abae19b95ca927d6076579906103c59083815260200190565b60603373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610571576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808080610583888a018a611a94565b9450945094509450945060008461059990611b6f565b60008181526004602052604090205490915060ff16156105e8576040517f36dbe74800000000000000000000000000000000000000000000000000000000815260048101829052602401610352565b8551600081815260056020526040902061060482878784610ae6565b61060f886002610bda565b86516020880120610624818a89898987610c42565b60405173ffffffffffffffffffffffffffffffffffffffff8c16815284907f58ca9502e98a536e06e72d680fcc251e5d10b72291a281665a2c2dc0ac30fcc59060200160405180910390a250959b9a5050505050505050505050565b610688610a63565b60008181526004602052604090205460ff166106fa5760008181526004602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555182917ff438564f793525caa89c6e3a26d41e16aa39d1e589747595751e3f3df75cb2b491a25b50565b86518560ff168060000361073d576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115610782576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f6024820152604401610352565b61078d816003611c12565b82116107e5578161079f826003611c12565b6107aa906001611c2f565b6040517f9dd9e6d800000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610352565b6107ed610a63565b6107ff8c8c8c8c8c8c8c8c8c8c610ebe565b505050505050505050505050565b610815610a63565b60008181526004602052604090205460ff16156106fa5760008181526004602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917ffc4f79b8c65b6be1773063461984c0974400d1e99654c79477a092ace83fd06191a250565b60015473ffffffffffffffffffffffffffffffffffffffff16331461090e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610352565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b86518560ff16806000036109ca576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115610a0f576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f6024820152604401610352565b610a1a816003611c12565b8211610a2c578161079f826003611c12565b610a34610a63565b610a47463060008c8c8c8c8c8c8c610ebe565b505050505050505050565b610a5a610a63565b6106fa81611230565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610352565b565b8054600090610af99060ff166001611c42565b8254909150610100900460ff16610b3f576040517fd990d62100000000000000000000000000000000000000000000000000000000815260048101869052602401610352565b8060ff16845114610b8b5783516040517f5348a282000000000000000000000000000000000000000000000000000000008152600481019190915260ff82166024820152604401610352565b8251845114610bd357835183516040517ff0d3140800000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610352565b5050505050565b6020820151815463ffffffff600883901c81169168010000000000000000900416811115610c3c5782547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff166801000000000000000063ffffffff8316021783555b50505050565b60008686604051602001610c57929190611c5b565b6040516020818303038152906040528051906020012090506000610c8b604080518082019091526000808252602082015290565b8651600090815b81811015610e5657600186898360208110610caf57610caf611bb4565b610cbc91901a601b611c42565b8c8481518110610cce57610cce611bb4565b60200260200101518c8581518110610ce857610ce8611bb4565b602002602001015160405160008152602001604052604051610d26949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610d48573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526001808d01602090815291859020848601909552845460ff808216865293995093955090850192610100900490911690811115610dcd57610dcd611c97565b6001811115610dde57610dde611c97565b9052509350600184602001516001811115610dfb57610dfb611c97565b14610e32576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015160080260ff166001901b8501945080610e4f90611cc6565b9050610c92565b50837e01010101010101010101010101010101010101010101010101010101010101851614610eb1576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b63ffffffff881615610eff57600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8a16179055610f35565b6002805463ffffffff16906000610f1583611cfe565b91906101000a81548163ffffffff021916908363ffffffff160217905550505b600254600090610f54908c908c9063ffffffff168b8b8b8b8b8b611325565b600081815260056020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8a16176101001790559091505b88518160ff16101561118f576000898260ff1681518110610fb857610fb8611bb4565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611028576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600085815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452600190810190925290912054610100900460ff169081111561107957611079611c97565b14801591506110b4576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff841681526020810160019052600085815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684526001908101835292208351815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00821681178355928501519193919284927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216179061010090849081111561117457611174611c97565b021790555090505050508061118890611d21565b9050610f95565b506002546040517f1074b4b9a073f79bd1f7f5c808348125ce0f25c27188df7efcaa7a08276051b3916111e29163ffffffff640100000000830481169286929116908d908d908d908d908d908d90611dc1565b60405180910390a1600280547fffffffffffffffffffffffffffffffffffffffff0000000000000000ffffffff1664010000000063ffffffff43160217905560035550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036112af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610352565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000808a8a8a8a8a8a8a8a8a60405160200161134999989796959493929190611e57565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b6000602082840312156113e257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461141257600080fd5b9392505050565b60006020828403121561142b57600080fd5b5035919050565b6000815180845260005b818110156114585760208185018101518683018201520161143c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006114126020830184611432565b803573ffffffffffffffffffffffffffffffffffffffff811681146114cd57600080fd5b919050565b6000806000604084860312156114e757600080fd5b833567ffffffffffffffff808211156114ff57600080fd5b818601915086601f83011261151357600080fd5b81358181111561152257600080fd5b87602082850101111561153457600080fd5b60209283019550935061154a91860190506114a9565b90509250925092565b803563ffffffff811681146114cd57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156115b9576115b9611567565b60405290565b6040516060810167ffffffffffffffff811182821017156115b9576115b9611567565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561162957611629611567565b604052919050565b600067ffffffffffffffff82111561164b5761164b611567565b5060051b60200190565b600082601f83011261166657600080fd5b8135602061167b61167683611631565b6115e2565b82815260059290921b8401810191818101908684111561169a57600080fd5b8286015b848110156116bc576116af816114a9565b835291830191830161169e565b509695505050505050565b600082601f8301126116d857600080fd5b813560206116e861167683611631565b82815260059290921b8401810191818101908684111561170757600080fd5b8286015b848110156116bc578035835291830191830161170b565b803560ff811681146114cd57600080fd5b600082601f83011261174457600080fd5b813567ffffffffffffffff81111561175e5761175e611567565b61178f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115e2565b8181528460208386010111156117a457600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146114cd57600080fd5b600082601f8301126117ea57600080fd5b813560206117fa61167683611631565b82815260069290921b8401810191818101908684111561181957600080fd5b8286015b848110156116bc57604081890312156118365760008081fd5b61183e611596565b611847826114a9565b81526118548583016117c1565b8186015283529183019160400161181d565b6000806000806000806000806000806101408b8d03121561188657600080fd5b8a35995061189660208c016114a9565b98506118a460408c01611553565b975060608b013567ffffffffffffffff808211156118c157600080fd5b6118cd8e838f01611655565b985060808d01359150808211156118e357600080fd5b6118ef8e838f016116c7565b97506118fd60a08e01611722565b965060c08d013591508082111561191357600080fd5b61191f8e838f01611733565b955061192d60e08e016117c1565b94506101008d013591508082111561194457600080fd5b6119508e838f01611733565b93506101208d013591508082111561196757600080fd5b506119748d828e016117d9565b9150509295989b9194979a5092959850565b600080600080600080600060e0888a0312156119a157600080fd5b873567ffffffffffffffff808211156119b957600080fd5b6119c58b838c01611655565b985060208a01359150808211156119db57600080fd5b6119e78b838c016116c7565b97506119f560408b01611722565b965060608a0135915080821115611a0b57600080fd5b611a178b838c01611733565b9550611a2560808b016117c1565b945060a08a0135915080821115611a3b57600080fd5b611a478b838c01611733565b935060c08a0135915080821115611a5d57600080fd5b50611a6a8a828b016117d9565b91505092959891949750929550565b600060208284031215611a8b57600080fd5b611412826114a9565b600080600080600060e08688031215611aac57600080fd5b86601f870112611abb57600080fd5b611ac36115bf565b806060880189811115611ad557600080fd5b885b81811015611aef578035845260209384019301611ad7565b5090965035905067ffffffffffffffff80821115611b0c57600080fd5b611b1889838a01611733565b95506080880135915080821115611b2e57600080fd5b611b3a89838a016116c7565b945060a0880135915080821115611b5057600080fd5b50611b5d888289016116c7565b9598949750929560c001359392505050565b80516020808301519190811015611bae577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611c2957611c29611be3565b92915050565b80820180821115611c2957611c29611be3565b60ff8181168382160190811115611c2957611c29611be3565b828152600060208083018460005b6003811015611c8657815183529183019190830190600101611c69565b505050506080820190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611cf757611cf7611be3565b5060010190565b600063ffffffff808316818103611d1757611d17611be3565b6001019392505050565b600060ff821660ff8103611d3757611d37611be3565b60010192915050565b600081518084526020808501945080840160005b83811015611d8657815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611d54565b509495945050505050565b600081518084526020808501945080840160005b83811015611d8657815187529582019590820190600101611da5565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152611df18184018a611d40565b90508281036080840152611e058189611d91565b905060ff871660a084015282810360c0840152611e228187611432565b905067ffffffffffffffff851660e0840152828103610100840152611e478185611432565b9c9b505050505050505050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152611e9e8285018b611d40565b91508382036080850152611eb2828a611d91565b915060ff881660a085015283820360c0850152611ecf8288611432565b90861660e08501528381036101008501529050611e47818561143256fea164736f6c6343000813000a", -} - -var ChannelVerifierABI = ChannelVerifierMetaData.ABI - -var ChannelVerifierBin = ChannelVerifierMetaData.Bin - -func DeployChannelVerifier(auth *bind.TransactOpts, backend bind.ContractBackend, verifierProxyAddr common.Address) (common.Address, *types.Transaction, *ChannelVerifier, error) { - parsed, err := ChannelVerifierMetaData.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(ChannelVerifierBin), backend, verifierProxyAddr) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &ChannelVerifier{address: address, abi: *parsed, ChannelVerifierCaller: ChannelVerifierCaller{contract: contract}, ChannelVerifierTransactor: ChannelVerifierTransactor{contract: contract}, ChannelVerifierFilterer: ChannelVerifierFilterer{contract: contract}}, nil -} - -type ChannelVerifier struct { - address common.Address - abi abi.ABI - ChannelVerifierCaller - ChannelVerifierTransactor - ChannelVerifierFilterer -} - -type ChannelVerifierCaller struct { - contract *bind.BoundContract -} - -type ChannelVerifierTransactor struct { - contract *bind.BoundContract -} - -type ChannelVerifierFilterer struct { - contract *bind.BoundContract -} - -type ChannelVerifierSession struct { - Contract *ChannelVerifier - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type ChannelVerifierCallerSession struct { - Contract *ChannelVerifierCaller - CallOpts bind.CallOpts -} - -type ChannelVerifierTransactorSession struct { - Contract *ChannelVerifierTransactor - TransactOpts bind.TransactOpts -} - -type ChannelVerifierRaw struct { - Contract *ChannelVerifier -} - -type ChannelVerifierCallerRaw struct { - Contract *ChannelVerifierCaller -} - -type ChannelVerifierTransactorRaw struct { - Contract *ChannelVerifierTransactor -} - -func NewChannelVerifier(address common.Address, backend bind.ContractBackend) (*ChannelVerifier, error) { - abi, err := abi.JSON(strings.NewReader(ChannelVerifierABI)) - if err != nil { - return nil, err - } - contract, err := bindChannelVerifier(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &ChannelVerifier{address: address, abi: abi, ChannelVerifierCaller: ChannelVerifierCaller{contract: contract}, ChannelVerifierTransactor: ChannelVerifierTransactor{contract: contract}, ChannelVerifierFilterer: ChannelVerifierFilterer{contract: contract}}, nil -} - -func NewChannelVerifierCaller(address common.Address, caller bind.ContractCaller) (*ChannelVerifierCaller, error) { - contract, err := bindChannelVerifier(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ChannelVerifierCaller{contract: contract}, nil -} - -func NewChannelVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*ChannelVerifierTransactor, error) { - contract, err := bindChannelVerifier(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ChannelVerifierTransactor{contract: contract}, nil -} - -func NewChannelVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*ChannelVerifierFilterer, error) { - contract, err := bindChannelVerifier(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ChannelVerifierFilterer{contract: contract}, nil -} - -func bindChannelVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ChannelVerifierMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_ChannelVerifier *ChannelVerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ChannelVerifier.Contract.ChannelVerifierCaller.contract.Call(opts, result, method, params...) -} - -func (_ChannelVerifier *ChannelVerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ChannelVerifier.Contract.ChannelVerifierTransactor.contract.Transfer(opts) -} - -func (_ChannelVerifier *ChannelVerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ChannelVerifier.Contract.ChannelVerifierTransactor.contract.Transact(opts, method, params...) -} - -func (_ChannelVerifier *ChannelVerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ChannelVerifier.Contract.contract.Call(opts, result, method, params...) -} - -func (_ChannelVerifier *ChannelVerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ChannelVerifier.Contract.contract.Transfer(opts) -} - -func (_ChannelVerifier *ChannelVerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ChannelVerifier.Contract.contract.Transact(opts, method, params...) -} - -func (_ChannelVerifier *ChannelVerifierCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) { - var out []interface{} - err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _ChannelVerifier.Contract.LatestConfigDetails(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCallerSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _ChannelVerifier.Contract.LatestConfigDetails(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) { - var out []interface{} - err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _ChannelVerifier.Contract.LatestConfigDigestAndEpoch(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _ChannelVerifier.Contract.LatestConfigDigestAndEpoch(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierSession) Owner() (common.Address, error) { - return _ChannelVerifier.Contract.Owner(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCallerSession) Owner() (common.Address, error) { - return _ChannelVerifier.Contract.Owner(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _ChannelVerifier.Contract.SupportsInterface(&_ChannelVerifier.CallOpts, interfaceId) -} - -func (_ChannelVerifier *ChannelVerifierCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _ChannelVerifier.Contract.SupportsInterface(&_ChannelVerifier.CallOpts, interfaceId) -} - -func (_ChannelVerifier *ChannelVerifierCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _ChannelVerifier.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_ChannelVerifier *ChannelVerifierSession) TypeAndVersion() (string, error) { - return _ChannelVerifier.Contract.TypeAndVersion(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierCallerSession) TypeAndVersion() (string, error) { - return _ChannelVerifier.Contract.TypeAndVersion(&_ChannelVerifier.CallOpts) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "acceptOwnership") -} - -func (_ChannelVerifier *ChannelVerifierSession) AcceptOwnership() (*types.Transaction, error) { - return _ChannelVerifier.Contract.AcceptOwnership(&_ChannelVerifier.TransactOpts) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _ChannelVerifier.Contract.AcceptOwnership(&_ChannelVerifier.TransactOpts) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) ActivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "activateConfig", configDigest) -} - -func (_ChannelVerifier *ChannelVerifierSession) ActivateConfig(configDigest [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.ActivateConfig(&_ChannelVerifier.TransactOpts, configDigest) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) ActivateConfig(configDigest [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.ActivateConfig(&_ChannelVerifier.TransactOpts, configDigest) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) ActivateFeed(opts *bind.TransactOpts, feedId [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "activateFeed", feedId) -} - -func (_ChannelVerifier *ChannelVerifierSession) ActivateFeed(feedId [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.ActivateFeed(&_ChannelVerifier.TransactOpts, feedId) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) ActivateFeed(feedId [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.ActivateFeed(&_ChannelVerifier.TransactOpts, feedId) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) DeactivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "deactivateConfig", configDigest) -} - -func (_ChannelVerifier *ChannelVerifierSession) DeactivateConfig(configDigest [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.DeactivateConfig(&_ChannelVerifier.TransactOpts, configDigest) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) DeactivateConfig(configDigest [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.DeactivateConfig(&_ChannelVerifier.TransactOpts, configDigest) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) DeactivateFeed(opts *bind.TransactOpts, feedId [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "deactivateFeed", feedId) -} - -func (_ChannelVerifier *ChannelVerifierSession) DeactivateFeed(feedId [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.DeactivateFeed(&_ChannelVerifier.TransactOpts, feedId) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) DeactivateFeed(feedId [32]byte) (*types.Transaction, error) { - return _ChannelVerifier.Contract.DeactivateFeed(&_ChannelVerifier.TransactOpts, feedId) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) SetConfig(opts *bind.TransactOpts, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "setConfig", signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) -} - -func (_ChannelVerifier *ChannelVerifierSession) SetConfig(signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _ChannelVerifier.Contract.SetConfig(&_ChannelVerifier.TransactOpts, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) SetConfig(signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _ChannelVerifier.Contract.SetConfig(&_ChannelVerifier.TransactOpts, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) SetConfigFromSource(opts *bind.TransactOpts, sourceChainId *big.Int, sourceAddress common.Address, newConfigCount uint32, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "setConfigFromSource", sourceChainId, sourceAddress, newConfigCount, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) -} - -func (_ChannelVerifier *ChannelVerifierSession) SetConfigFromSource(sourceChainId *big.Int, sourceAddress common.Address, newConfigCount uint32, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _ChannelVerifier.Contract.SetConfigFromSource(&_ChannelVerifier.TransactOpts, sourceChainId, sourceAddress, newConfigCount, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) SetConfigFromSource(sourceChainId *big.Int, sourceAddress common.Address, newConfigCount uint32, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) { - return _ChannelVerifier.Contract.SetConfigFromSource(&_ChannelVerifier.TransactOpts, sourceChainId, sourceAddress, newConfigCount, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "transferOwnership", to) -} - -func (_ChannelVerifier *ChannelVerifierSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _ChannelVerifier.Contract.TransferOwnership(&_ChannelVerifier.TransactOpts, to) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _ChannelVerifier.Contract.TransferOwnership(&_ChannelVerifier.TransactOpts, to) -} - -func (_ChannelVerifier *ChannelVerifierTransactor) Verify(opts *bind.TransactOpts, signedReport []byte, sender common.Address) (*types.Transaction, error) { - return _ChannelVerifier.contract.Transact(opts, "verify", signedReport, sender) -} - -func (_ChannelVerifier *ChannelVerifierSession) Verify(signedReport []byte, sender common.Address) (*types.Transaction, error) { - return _ChannelVerifier.Contract.Verify(&_ChannelVerifier.TransactOpts, signedReport, sender) -} - -func (_ChannelVerifier *ChannelVerifierTransactorSession) Verify(signedReport []byte, sender common.Address) (*types.Transaction, error) { - return _ChannelVerifier.Contract.Verify(&_ChannelVerifier.TransactOpts, signedReport, sender) -} - -type ChannelVerifierConfigActivatedIterator struct { - Event *ChannelVerifierConfigActivated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierConfigActivatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierConfigActivated) - 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(ChannelVerifierConfigActivated) - 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 *ChannelVerifierConfigActivatedIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierConfigActivatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierConfigActivated struct { - ConfigDigest [32]byte - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterConfigActivated(opts *bind.FilterOpts) (*ChannelVerifierConfigActivatedIterator, error) { - - logs, sub, err := _ChannelVerifier.contract.FilterLogs(opts, "ConfigActivated") - if err != nil { - return nil, err - } - return &ChannelVerifierConfigActivatedIterator{contract: _ChannelVerifier.contract, event: "ConfigActivated", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchConfigActivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierConfigActivated) (event.Subscription, error) { - - logs, sub, err := _ChannelVerifier.contract.WatchLogs(opts, "ConfigActivated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(ChannelVerifierConfigActivated) - if err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierFilterer) ParseConfigActivated(log types.Log) (*ChannelVerifierConfigActivated, error) { - event := new(ChannelVerifierConfigActivated) - if err := _ChannelVerifier.contract.UnpackLog(event, "ConfigActivated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierConfigDeactivatedIterator struct { - Event *ChannelVerifierConfigDeactivated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierConfigDeactivatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierConfigDeactivated) - 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(ChannelVerifierConfigDeactivated) - 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 *ChannelVerifierConfigDeactivatedIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierConfigDeactivatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierConfigDeactivated struct { - ConfigDigest [32]byte - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterConfigDeactivated(opts *bind.FilterOpts) (*ChannelVerifierConfigDeactivatedIterator, error) { - - logs, sub, err := _ChannelVerifier.contract.FilterLogs(opts, "ConfigDeactivated") - if err != nil { - return nil, err - } - return &ChannelVerifierConfigDeactivatedIterator{contract: _ChannelVerifier.contract, event: "ConfigDeactivated", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchConfigDeactivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierConfigDeactivated) (event.Subscription, error) { - - logs, sub, err := _ChannelVerifier.contract.WatchLogs(opts, "ConfigDeactivated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(ChannelVerifierConfigDeactivated) - if err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierFilterer) ParseConfigDeactivated(log types.Log) (*ChannelVerifierConfigDeactivated, error) { - event := new(ChannelVerifierConfigDeactivated) - if err := _ChannelVerifier.contract.UnpackLog(event, "ConfigDeactivated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierConfigSetIterator struct { - Event *ChannelVerifierConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierConfigSet) - 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(ChannelVerifierConfigSet) - 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 *ChannelVerifierConfigSetIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierConfigSet struct { - PreviousConfigBlockNumber uint32 - ConfigDigest [32]byte - ConfigCount uint64 - Signers []common.Address - OffchainTransmitters [][32]byte - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterConfigSet(opts *bind.FilterOpts) (*ChannelVerifierConfigSetIterator, error) { - - logs, sub, err := _ChannelVerifier.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &ChannelVerifierConfigSetIterator{contract: _ChannelVerifier.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *ChannelVerifierConfigSet) (event.Subscription, error) { - - logs, sub, err := _ChannelVerifier.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(ChannelVerifierConfigSet) - if err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierFilterer) ParseConfigSet(log types.Log) (*ChannelVerifierConfigSet, error) { - event := new(ChannelVerifierConfigSet) - if err := _ChannelVerifier.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierFeedActivatedIterator struct { - Event *ChannelVerifierFeedActivated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierFeedActivatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierFeedActivated) - 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(ChannelVerifierFeedActivated) - 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 *ChannelVerifierFeedActivatedIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierFeedActivatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierFeedActivated struct { - FeedId [32]byte - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterFeedActivated(opts *bind.FilterOpts, feedId [][32]byte) (*ChannelVerifierFeedActivatedIterator, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _ChannelVerifier.contract.FilterLogs(opts, "FeedActivated", feedIdRule) - if err != nil { - return nil, err - } - return &ChannelVerifierFeedActivatedIterator{contract: _ChannelVerifier.contract, event: "FeedActivated", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchFeedActivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierFeedActivated, feedId [][32]byte) (event.Subscription, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _ChannelVerifier.contract.WatchLogs(opts, "FeedActivated", 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(ChannelVerifierFeedActivated) - if err := _ChannelVerifier.contract.UnpackLog(event, "FeedActivated", 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 (_ChannelVerifier *ChannelVerifierFilterer) ParseFeedActivated(log types.Log) (*ChannelVerifierFeedActivated, error) { - event := new(ChannelVerifierFeedActivated) - if err := _ChannelVerifier.contract.UnpackLog(event, "FeedActivated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierFeedDeactivatedIterator struct { - Event *ChannelVerifierFeedDeactivated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierFeedDeactivatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierFeedDeactivated) - 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(ChannelVerifierFeedDeactivated) - 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 *ChannelVerifierFeedDeactivatedIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierFeedDeactivatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierFeedDeactivated struct { - FeedId [32]byte - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterFeedDeactivated(opts *bind.FilterOpts, feedId [][32]byte) (*ChannelVerifierFeedDeactivatedIterator, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _ChannelVerifier.contract.FilterLogs(opts, "FeedDeactivated", feedIdRule) - if err != nil { - return nil, err - } - return &ChannelVerifierFeedDeactivatedIterator{contract: _ChannelVerifier.contract, event: "FeedDeactivated", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchFeedDeactivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierFeedDeactivated, feedId [][32]byte) (event.Subscription, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _ChannelVerifier.contract.WatchLogs(opts, "FeedDeactivated", 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(ChannelVerifierFeedDeactivated) - if err := _ChannelVerifier.contract.UnpackLog(event, "FeedDeactivated", 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 (_ChannelVerifier *ChannelVerifierFilterer) ParseFeedDeactivated(log types.Log) (*ChannelVerifierFeedDeactivated, error) { - event := new(ChannelVerifierFeedDeactivated) - if err := _ChannelVerifier.contract.UnpackLog(event, "FeedDeactivated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierOwnershipTransferRequestedIterator struct { - Event *ChannelVerifierOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierOwnershipTransferRequested) - 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(ChannelVerifierOwnershipTransferRequested) - 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 *ChannelVerifierOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ChannelVerifierOwnershipTransferRequestedIterator, 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 := _ChannelVerifier.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &ChannelVerifierOwnershipTransferRequestedIterator{contract: _ChannelVerifier.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ChannelVerifierOwnershipTransferRequested, 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 := _ChannelVerifier.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(ChannelVerifierOwnershipTransferRequested) - if err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierFilterer) ParseOwnershipTransferRequested(log types.Log) (*ChannelVerifierOwnershipTransferRequested, error) { - event := new(ChannelVerifierOwnershipTransferRequested) - if err := _ChannelVerifier.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierOwnershipTransferredIterator struct { - Event *ChannelVerifierOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierOwnershipTransferred) - 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(ChannelVerifierOwnershipTransferred) - 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 *ChannelVerifierOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ChannelVerifierOwnershipTransferredIterator, 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 := _ChannelVerifier.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &ChannelVerifierOwnershipTransferredIterator{contract: _ChannelVerifier.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ChannelVerifierOwnershipTransferred, 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 := _ChannelVerifier.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(ChannelVerifierOwnershipTransferred) - if err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierFilterer) ParseOwnershipTransferred(log types.Log) (*ChannelVerifierOwnershipTransferred, error) { - event := new(ChannelVerifierOwnershipTransferred) - if err := _ChannelVerifier.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type ChannelVerifierReportVerifiedIterator struct { - Event *ChannelVerifierReportVerified - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *ChannelVerifierReportVerifiedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChannelVerifierReportVerified) - 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(ChannelVerifierReportVerified) - 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 *ChannelVerifierReportVerifiedIterator) Error() error { - return it.fail -} - -func (it *ChannelVerifierReportVerifiedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type ChannelVerifierReportVerified struct { - FeedId [32]byte - Requester common.Address - Raw types.Log -} - -func (_ChannelVerifier *ChannelVerifierFilterer) FilterReportVerified(opts *bind.FilterOpts, feedId [][32]byte) (*ChannelVerifierReportVerifiedIterator, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _ChannelVerifier.contract.FilterLogs(opts, "ReportVerified", feedIdRule) - if err != nil { - return nil, err - } - return &ChannelVerifierReportVerifiedIterator{contract: _ChannelVerifier.contract, event: "ReportVerified", logs: logs, sub: sub}, nil -} - -func (_ChannelVerifier *ChannelVerifierFilterer) WatchReportVerified(opts *bind.WatchOpts, sink chan<- *ChannelVerifierReportVerified, feedId [][32]byte) (event.Subscription, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _ChannelVerifier.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(ChannelVerifierReportVerified) - if err := _ChannelVerifier.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 (_ChannelVerifier *ChannelVerifierFilterer) ParseReportVerified(log types.Log) (*ChannelVerifierReportVerified, error) { - event := new(ChannelVerifierReportVerified) - if err := _ChannelVerifier.contract.UnpackLog(event, "ReportVerified", 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 (_ChannelVerifier *ChannelVerifier) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _ChannelVerifier.abi.Events["ConfigActivated"].ID: - return _ChannelVerifier.ParseConfigActivated(log) - case _ChannelVerifier.abi.Events["ConfigDeactivated"].ID: - return _ChannelVerifier.ParseConfigDeactivated(log) - case _ChannelVerifier.abi.Events["ConfigSet"].ID: - return _ChannelVerifier.ParseConfigSet(log) - case _ChannelVerifier.abi.Events["FeedActivated"].ID: - return _ChannelVerifier.ParseFeedActivated(log) - case _ChannelVerifier.abi.Events["FeedDeactivated"].ID: - return _ChannelVerifier.ParseFeedDeactivated(log) - case _ChannelVerifier.abi.Events["OwnershipTransferRequested"].ID: - return _ChannelVerifier.ParseOwnershipTransferRequested(log) - case _ChannelVerifier.abi.Events["OwnershipTransferred"].ID: - return _ChannelVerifier.ParseOwnershipTransferred(log) - case _ChannelVerifier.abi.Events["ReportVerified"].ID: - return _ChannelVerifier.ParseReportVerified(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (ChannelVerifierConfigActivated) Topic() common.Hash { - return common.HexToHash("0xa543797a0501218bba8a3daf75a71c8df8d1a7f791f4e44d40e43b6450183cea") -} - -func (ChannelVerifierConfigDeactivated) Topic() common.Hash { - return common.HexToHash("0x5bfaab86edc1b932e3c334327a591c9ded067cb521abae19b95ca927d6076579") -} - -func (ChannelVerifierConfigSet) Topic() common.Hash { - return common.HexToHash("0x1074b4b9a073f79bd1f7f5c808348125ce0f25c27188df7efcaa7a08276051b3") -} - -func (ChannelVerifierFeedActivated) Topic() common.Hash { - return common.HexToHash("0xf438564f793525caa89c6e3a26d41e16aa39d1e589747595751e3f3df75cb2b4") -} - -func (ChannelVerifierFeedDeactivated) Topic() common.Hash { - return common.HexToHash("0xfc4f79b8c65b6be1773063461984c0974400d1e99654c79477a092ace83fd061") -} - -func (ChannelVerifierOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (ChannelVerifierOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (ChannelVerifierReportVerified) Topic() common.Hash { - return common.HexToHash("0x58ca9502e98a536e06e72d680fcc251e5d10b72291a281665a2c2dc0ac30fcc5") -} - -func (_ChannelVerifier *ChannelVerifier) Address() common.Address { - return _ChannelVerifier.address -} - -type ChannelVerifierInterface interface { - LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) - - LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - 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) - - ActivateFeed(opts *bind.TransactOpts, feedId [32]byte) (*types.Transaction, error) - - DeactivateConfig(opts *bind.TransactOpts, configDigest [32]byte) (*types.Transaction, error) - - DeactivateFeed(opts *bind.TransactOpts, feedId [32]byte) (*types.Transaction, error) - - SetConfig(opts *bind.TransactOpts, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) - - SetConfigFromSource(opts *bind.TransactOpts, sourceChainId *big.Int, sourceAddress common.Address, newConfigCount uint32, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []CommonAddressAndWeight) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - Verify(opts *bind.TransactOpts, signedReport []byte, sender common.Address) (*types.Transaction, error) - - FilterConfigActivated(opts *bind.FilterOpts) (*ChannelVerifierConfigActivatedIterator, error) - - WatchConfigActivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierConfigActivated) (event.Subscription, error) - - ParseConfigActivated(log types.Log) (*ChannelVerifierConfigActivated, error) - - FilterConfigDeactivated(opts *bind.FilterOpts) (*ChannelVerifierConfigDeactivatedIterator, error) - - WatchConfigDeactivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierConfigDeactivated) (event.Subscription, error) - - ParseConfigDeactivated(log types.Log) (*ChannelVerifierConfigDeactivated, error) - - FilterConfigSet(opts *bind.FilterOpts) (*ChannelVerifierConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *ChannelVerifierConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*ChannelVerifierConfigSet, error) - - FilterFeedActivated(opts *bind.FilterOpts, feedId [][32]byte) (*ChannelVerifierFeedActivatedIterator, error) - - WatchFeedActivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierFeedActivated, feedId [][32]byte) (event.Subscription, error) - - ParseFeedActivated(log types.Log) (*ChannelVerifierFeedActivated, error) - - FilterFeedDeactivated(opts *bind.FilterOpts, feedId [][32]byte) (*ChannelVerifierFeedDeactivatedIterator, error) - - WatchFeedDeactivated(opts *bind.WatchOpts, sink chan<- *ChannelVerifierFeedDeactivated, feedId [][32]byte) (event.Subscription, error) - - ParseFeedDeactivated(log types.Log) (*ChannelVerifierFeedDeactivated, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ChannelVerifierOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ChannelVerifierOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*ChannelVerifierOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ChannelVerifierOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ChannelVerifierOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*ChannelVerifierOwnershipTransferred, error) - - FilterReportVerified(opts *bind.FilterOpts, feedId [][32]byte) (*ChannelVerifierReportVerifiedIterator, error) - - WatchReportVerified(opts *bind.WatchOpts, sink chan<- *ChannelVerifierReportVerified, feedId [][32]byte) (event.Subscription, error) - - ParseReportVerified(log types.Log) (*ChannelVerifierReportVerified, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/llo-feeds/generated/configurator/configurator.go b/core/gethwrappers/llo-feeds/generated/configurator/configurator.go new file mode 100644 index 00000000000..d9a1581938f --- /dev/null +++ b/core/gethwrappers/llo-feeds/generated/configurator/configurator.go @@ -0,0 +1,1075 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package configurator + +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 ConfiguratorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"}],\"name\":\"ConfigUnset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetProduction\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetStaging\",\"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\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"onchainConfigLength\",\"type\":\"uint256\"}],\"name\":\"InvalidOnchainLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"InvalidPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProductionContractState\",\"type\":\"bool\"}],\"name\":\"IsGreenProductionMustMatchContractState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"NonZeroPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UnsupportedOnchainConfigVersion\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ProductionConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"retiredConfigDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"PromoteStagingConfig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"StagingConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"promoteStagingConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\":\"setProductionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\":\"setStagingConfig\",\"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\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61144a806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610153578063dfb533d01461017b578063e6e7c5a41461018e578063f2fde38b146101a157600080fd5b806301ffc9a71461008d578063181f5a77146100f7578063790464e01461013657806379ba50971461014b575b600080fd5b6100e261009b366004610d62565b7fffffffff00000000000000000000000000000000000000000000000000000000167f40569294000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601281527f436f6e666967757261746f7220302e352e300000000000000000000000000000602082015290516100ee9190610e0f565b61014961014436600461106b565b6101b4565b005b61014961038d565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ee565b61014961018936600461106b565b61048a565b61014961019c366004611143565b6106ec565b6101496101af366004611178565b6108f8565b85518460ff16806000036101f4576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f82111561023e576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b6102498160036111dd565b82116102a1578161025b8260036111dd565b6102669060016111fa565b6040517f9dd9e6d800000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610235565b6102a961090c565b6040855110156102ea5784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161023591815260200190565b602085015160408601516001821015610332576040517f8f01e0d700000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b801561036d576040517fb96bb76000000000000000000000000000000000000000000000000000000000815260048101829052602401610235565b6103808b46308d8d8d8d8d8d600161098f565b5050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461040e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610235565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b85518460ff16806000036104ca576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f82111561050f576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f6024820152604401610235565b61051a8160036111dd565b821161052c578161025b8260036111dd565b61053461090c565b6040855110156105755784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161023591815260200190565b6020850151604086015160018210156105bd576040517f8f01e0d700000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b60008b81526002602081815260408084208151608081018352815467ffffffffffffffff8116825268010000000000000000810463ffffffff16948201949094526c0100000000000000000000000090930460ff161515838301528151808301928390529293909260608501929091600185019182845b815481526020019060010190808311610634575050505050815250509050600260008d8152602001908152602001600020600101816040015161067857600061067b565b60015b60ff166002811061068e5761068e61120d565b015482146106cb576040517f7d78c2a100000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b6106de8c46308e8e8e8e8e8e600061098f565b505050505050505050505050565b6106f461090c565b600082815260026020526040902080546c01000000000000000000000000900460ff1615158215151461075d576040517f85fa3a370000000000000000000000000000000000000000000000000000000081526004810184905282156024820152604401610235565b805467ffffffffffffffff166000036107a5576040517f90e6f6dc00000000000000000000000000000000000000000000000000000000815260048101849052602401610235565b600060018201836107b75760016107ba565b60005b60ff16600281106107cd576107cd61120d565b015403610811576040517f5b7f6357000000000000000000000000000000000000000000000000000000008152600481018490528215156024820152604401610235565b60008160010183610823576000610826565b60015b60ff16600281106108395761083961120d565b015490508061087f576040517fcaf1e773000000000000000000000000000000000000000000000000000000008152600481018590528315156024820152604401610235565b81547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1683156c010000000000000000000000008102919091178355604051908152819085907f1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f9060200160405180910390a350505050565b61090061090c565b61090981610bbf565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461098d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610235565b565b60008a81526002602052604081208054909190829082906109b99067ffffffffffffffff1661123c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055905060006109f48d8d8d858e8e8e8e8e8e610cb4565b90508315610abc578c7f261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e24788460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610a639a999897969594939291906112f0565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610a9f576000610aa2565b60015b60ff1660028110610ab557610ab561120d565b0155610b78565b8c7fef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e890568460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610b239a999897969594939291906112f0565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610b5f576001610b62565b60005b60ff1660028110610b7557610b7561120d565b01555b505080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004363ffffffff160217905550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610c3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610235565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000808b8b8b8b8b8b8b8b8b8b604051602001610cda9a99989796959493929190611390565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b600060208284031215610d7457600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610da457600080fd5b9392505050565b6000815180845260005b81811015610dd157602081850181015186830182015201610db5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610da46020830184610dab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e9857610e98610e22565b604052919050565b600067ffffffffffffffff821115610eba57610eba610e22565b5060051b60200190565b600082601f830112610ed557600080fd5b813567ffffffffffffffff811115610eef57610eef610e22565b610f2060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610e51565b818152846020838601011115610f3557600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610f6357600080fd5b81356020610f78610f7383610ea0565b610e51565b82815260059290921b84018101918181019086841115610f9757600080fd5b8286015b84811015610fd757803567ffffffffffffffff811115610fbb5760008081fd5b610fc98986838b0101610ec4565b845250918301918301610f9b565b509695505050505050565b600082601f830112610ff357600080fd5b81356020611003610f7383610ea0565b82815260059290921b8401810191818101908684111561102257600080fd5b8286015b84811015610fd75780358352918301918301611026565b803560ff8116811461104e57600080fd5b919050565b803567ffffffffffffffff8116811461104e57600080fd5b600080600080600080600060e0888a03121561108657600080fd5b87359650602088013567ffffffffffffffff808211156110a557600080fd5b6110b18b838c01610f52565b975060408a01359150808211156110c757600080fd5b6110d38b838c01610fe2565b96506110e160608b0161103d565b955060808a01359150808211156110f757600080fd5b6111038b838c01610ec4565b945061111160a08b01611053565b935060c08a013591508082111561112757600080fd5b506111348a828b01610ec4565b91505092959891949750929550565b6000806040838503121561115657600080fd5b823591506020830135801515811461116d57600080fd5b809150509250929050565b60006020828403121561118a57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610da457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176111f4576111f46111ae565b92915050565b808201808211156111f4576111f46111ae565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600067ffffffffffffffff808316818103611259576112596111ae565b6001019392505050565b6000815180845260208085019450848260051b860182860160005b858110156112a8578383038952611296838351610dab565b9885019892509084019060010161127e565b5090979650505050505050565b600081518084526020808501945080840160005b838110156112e5578151875295820195908201906001016112c9565b509495945050505050565b600061014063ffffffff8d1683528b602084015267ffffffffffffffff808c1660408501528160608501526113278285018c611263565b9150838203608085015261133b828b6112b5565b915060ff891660a085015283820360c08501526113588289610dab565b90871660e085015283810361010085015290506113758186610dab565b9150508215156101208301529b9a5050505050505050505050565b60006101408c83528b602084015273ffffffffffffffffffffffffffffffffffffffff8b16604084015267ffffffffffffffff808b1660608501528160808501526113dd8285018b611263565b915083820360a08501526113f1828a6112b5565b915060ff881660c085015283820360e085015261140e8288610dab565b908616610100850152838103610120850152905061142c8185610dab565b9d9c5050505050505050505050505056fea164736f6c6343000813000a", +} + +var ConfiguratorABI = ConfiguratorMetaData.ABI + +var ConfiguratorBin = ConfiguratorMetaData.Bin + +func DeployConfigurator(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Configurator, error) { + parsed, err := ConfiguratorMetaData.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(ConfiguratorBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Configurator{address: address, abi: *parsed, ConfiguratorCaller: ConfiguratorCaller{contract: contract}, ConfiguratorTransactor: ConfiguratorTransactor{contract: contract}, ConfiguratorFilterer: ConfiguratorFilterer{contract: contract}}, nil +} + +type Configurator struct { + address common.Address + abi abi.ABI + ConfiguratorCaller + ConfiguratorTransactor + ConfiguratorFilterer +} + +type ConfiguratorCaller struct { + contract *bind.BoundContract +} + +type ConfiguratorTransactor struct { + contract *bind.BoundContract +} + +type ConfiguratorFilterer struct { + contract *bind.BoundContract +} + +type ConfiguratorSession struct { + Contract *Configurator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type ConfiguratorCallerSession struct { + Contract *ConfiguratorCaller + CallOpts bind.CallOpts +} + +type ConfiguratorTransactorSession struct { + Contract *ConfiguratorTransactor + TransactOpts bind.TransactOpts +} + +type ConfiguratorRaw struct { + Contract *Configurator +} + +type ConfiguratorCallerRaw struct { + Contract *ConfiguratorCaller +} + +type ConfiguratorTransactorRaw struct { + Contract *ConfiguratorTransactor +} + +func NewConfigurator(address common.Address, backend bind.ContractBackend) (*Configurator, error) { + abi, err := abi.JSON(strings.NewReader(ConfiguratorABI)) + if err != nil { + return nil, err + } + contract, err := bindConfigurator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Configurator{address: address, abi: abi, ConfiguratorCaller: ConfiguratorCaller{contract: contract}, ConfiguratorTransactor: ConfiguratorTransactor{contract: contract}, ConfiguratorFilterer: ConfiguratorFilterer{contract: contract}}, nil +} + +func NewConfiguratorCaller(address common.Address, caller bind.ContractCaller) (*ConfiguratorCaller, error) { + contract, err := bindConfigurator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ConfiguratorCaller{contract: contract}, nil +} + +func NewConfiguratorTransactor(address common.Address, transactor bind.ContractTransactor) (*ConfiguratorTransactor, error) { + contract, err := bindConfigurator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ConfiguratorTransactor{contract: contract}, nil +} + +func NewConfiguratorFilterer(address common.Address, filterer bind.ContractFilterer) (*ConfiguratorFilterer, error) { + contract, err := bindConfigurator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ConfiguratorFilterer{contract: contract}, nil +} + +func bindConfigurator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ConfiguratorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_Configurator *ConfiguratorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Configurator.Contract.ConfiguratorCaller.contract.Call(opts, result, method, params...) +} + +func (_Configurator *ConfiguratorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Configurator.Contract.ConfiguratorTransactor.contract.Transfer(opts) +} + +func (_Configurator *ConfiguratorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Configurator.Contract.ConfiguratorTransactor.contract.Transact(opts, method, params...) +} + +func (_Configurator *ConfiguratorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Configurator.Contract.contract.Call(opts, result, method, params...) +} + +func (_Configurator *ConfiguratorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Configurator.Contract.contract.Transfer(opts) +} + +func (_Configurator *ConfiguratorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Configurator.Contract.contract.Transact(opts, method, params...) +} + +func (_Configurator *ConfiguratorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Configurator.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 (_Configurator *ConfiguratorSession) Owner() (common.Address, error) { + return _Configurator.Contract.Owner(&_Configurator.CallOpts) +} + +func (_Configurator *ConfiguratorCallerSession) Owner() (common.Address, error) { + return _Configurator.Contract.Owner(&_Configurator.CallOpts) +} + +func (_Configurator *ConfiguratorCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Configurator.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 (_Configurator *ConfiguratorSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Configurator.Contract.SupportsInterface(&_Configurator.CallOpts, interfaceId) +} + +func (_Configurator *ConfiguratorCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Configurator.Contract.SupportsInterface(&_Configurator.CallOpts, interfaceId) +} + +func (_Configurator *ConfiguratorCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Configurator.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_Configurator *ConfiguratorSession) TypeAndVersion() (string, error) { + return _Configurator.Contract.TypeAndVersion(&_Configurator.CallOpts) +} + +func (_Configurator *ConfiguratorCallerSession) TypeAndVersion() (string, error) { + return _Configurator.Contract.TypeAndVersion(&_Configurator.CallOpts) +} + +func (_Configurator *ConfiguratorTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Configurator.contract.Transact(opts, "acceptOwnership") +} + +func (_Configurator *ConfiguratorSession) AcceptOwnership() (*types.Transaction, error) { + return _Configurator.Contract.AcceptOwnership(&_Configurator.TransactOpts) +} + +func (_Configurator *ConfiguratorTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _Configurator.Contract.AcceptOwnership(&_Configurator.TransactOpts) +} + +func (_Configurator *ConfiguratorTransactor) PromoteStagingConfig(opts *bind.TransactOpts, configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _Configurator.contract.Transact(opts, "promoteStagingConfig", configId, isGreenProduction) +} + +func (_Configurator *ConfiguratorSession) PromoteStagingConfig(configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _Configurator.Contract.PromoteStagingConfig(&_Configurator.TransactOpts, configId, isGreenProduction) +} + +func (_Configurator *ConfiguratorTransactorSession) PromoteStagingConfig(configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _Configurator.Contract.PromoteStagingConfig(&_Configurator.TransactOpts, configId, isGreenProduction) +} + +func (_Configurator *ConfiguratorTransactor) SetProductionConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _Configurator.contract.Transact(opts, "setProductionConfig", configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_Configurator *ConfiguratorSession) SetProductionConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _Configurator.Contract.SetProductionConfig(&_Configurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_Configurator *ConfiguratorTransactorSession) SetProductionConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _Configurator.Contract.SetProductionConfig(&_Configurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_Configurator *ConfiguratorTransactor) SetStagingConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _Configurator.contract.Transact(opts, "setStagingConfig", configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_Configurator *ConfiguratorSession) SetStagingConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _Configurator.Contract.SetStagingConfig(&_Configurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_Configurator *ConfiguratorTransactorSession) SetStagingConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _Configurator.Contract.SetStagingConfig(&_Configurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_Configurator *ConfiguratorTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _Configurator.contract.Transact(opts, "transferOwnership", to) +} + +func (_Configurator *ConfiguratorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Configurator.Contract.TransferOwnership(&_Configurator.TransactOpts, to) +} + +func (_Configurator *ConfiguratorTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Configurator.Contract.TransferOwnership(&_Configurator.TransactOpts, to) +} + +type ConfiguratorOwnershipTransferRequestedIterator struct { + Event *ConfiguratorOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ConfiguratorOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ConfiguratorOwnershipTransferRequested) + 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(ConfiguratorOwnershipTransferRequested) + 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 *ConfiguratorOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *ConfiguratorOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ConfiguratorOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Configurator *ConfiguratorFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ConfiguratorOwnershipTransferRequestedIterator, 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 := _Configurator.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &ConfiguratorOwnershipTransferRequestedIterator{contract: _Configurator.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_Configurator *ConfiguratorFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ConfiguratorOwnershipTransferRequested, 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 := _Configurator.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(ConfiguratorOwnershipTransferRequested) + if err := _Configurator.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 (_Configurator *ConfiguratorFilterer) ParseOwnershipTransferRequested(log types.Log) (*ConfiguratorOwnershipTransferRequested, error) { + event := new(ConfiguratorOwnershipTransferRequested) + if err := _Configurator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ConfiguratorOwnershipTransferredIterator struct { + Event *ConfiguratorOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ConfiguratorOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ConfiguratorOwnershipTransferred) + 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(ConfiguratorOwnershipTransferred) + 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 *ConfiguratorOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *ConfiguratorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ConfiguratorOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Configurator *ConfiguratorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ConfiguratorOwnershipTransferredIterator, 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 := _Configurator.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &ConfiguratorOwnershipTransferredIterator{contract: _Configurator.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_Configurator *ConfiguratorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ConfiguratorOwnershipTransferred, 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 := _Configurator.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(ConfiguratorOwnershipTransferred) + if err := _Configurator.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 (_Configurator *ConfiguratorFilterer) ParseOwnershipTransferred(log types.Log) (*ConfiguratorOwnershipTransferred, error) { + event := new(ConfiguratorOwnershipTransferred) + if err := _Configurator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ConfiguratorProductionConfigSetIterator struct { + Event *ConfiguratorProductionConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ConfiguratorProductionConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ConfiguratorProductionConfigSet) + 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(ConfiguratorProductionConfigSet) + 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 *ConfiguratorProductionConfigSetIterator) Error() error { + return it.fail +} + +func (it *ConfiguratorProductionConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ConfiguratorProductionConfigSet struct { + ConfigId [32]byte + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers [][]byte + OffchainTransmitters [][32]byte + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + IsGreenProduction bool + Raw types.Log +} + +func (_Configurator *ConfiguratorFilterer) FilterProductionConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ConfiguratorProductionConfigSetIterator, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _Configurator.contract.FilterLogs(opts, "ProductionConfigSet", configIdRule) + if err != nil { + return nil, err + } + return &ConfiguratorProductionConfigSetIterator{contract: _Configurator.contract, event: "ProductionConfigSet", logs: logs, sub: sub}, nil +} + +func (_Configurator *ConfiguratorFilterer) WatchProductionConfigSet(opts *bind.WatchOpts, sink chan<- *ConfiguratorProductionConfigSet, configId [][32]byte) (event.Subscription, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _Configurator.contract.WatchLogs(opts, "ProductionConfigSet", configIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ConfiguratorProductionConfigSet) + if err := _Configurator.contract.UnpackLog(event, "ProductionConfigSet", 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 (_Configurator *ConfiguratorFilterer) ParseProductionConfigSet(log types.Log) (*ConfiguratorProductionConfigSet, error) { + event := new(ConfiguratorProductionConfigSet) + if err := _Configurator.contract.UnpackLog(event, "ProductionConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ConfiguratorPromoteStagingConfigIterator struct { + Event *ConfiguratorPromoteStagingConfig + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ConfiguratorPromoteStagingConfigIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ConfiguratorPromoteStagingConfig) + 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(ConfiguratorPromoteStagingConfig) + 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 *ConfiguratorPromoteStagingConfigIterator) Error() error { + return it.fail +} + +func (it *ConfiguratorPromoteStagingConfigIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ConfiguratorPromoteStagingConfig struct { + ConfigId [32]byte + RetiredConfigDigest [32]byte + IsGreenProduction bool + Raw types.Log +} + +func (_Configurator *ConfiguratorFilterer) FilterPromoteStagingConfig(opts *bind.FilterOpts, configId [][32]byte, retiredConfigDigest [][32]byte) (*ConfiguratorPromoteStagingConfigIterator, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + var retiredConfigDigestRule []interface{} + for _, retiredConfigDigestItem := range retiredConfigDigest { + retiredConfigDigestRule = append(retiredConfigDigestRule, retiredConfigDigestItem) + } + + logs, sub, err := _Configurator.contract.FilterLogs(opts, "PromoteStagingConfig", configIdRule, retiredConfigDigestRule) + if err != nil { + return nil, err + } + return &ConfiguratorPromoteStagingConfigIterator{contract: _Configurator.contract, event: "PromoteStagingConfig", logs: logs, sub: sub}, nil +} + +func (_Configurator *ConfiguratorFilterer) WatchPromoteStagingConfig(opts *bind.WatchOpts, sink chan<- *ConfiguratorPromoteStagingConfig, configId [][32]byte, retiredConfigDigest [][32]byte) (event.Subscription, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + var retiredConfigDigestRule []interface{} + for _, retiredConfigDigestItem := range retiredConfigDigest { + retiredConfigDigestRule = append(retiredConfigDigestRule, retiredConfigDigestItem) + } + + logs, sub, err := _Configurator.contract.WatchLogs(opts, "PromoteStagingConfig", configIdRule, retiredConfigDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ConfiguratorPromoteStagingConfig) + if err := _Configurator.contract.UnpackLog(event, "PromoteStagingConfig", 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 (_Configurator *ConfiguratorFilterer) ParsePromoteStagingConfig(log types.Log) (*ConfiguratorPromoteStagingConfig, error) { + event := new(ConfiguratorPromoteStagingConfig) + if err := _Configurator.contract.UnpackLog(event, "PromoteStagingConfig", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ConfiguratorStagingConfigSetIterator struct { + Event *ConfiguratorStagingConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ConfiguratorStagingConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ConfiguratorStagingConfigSet) + 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(ConfiguratorStagingConfigSet) + 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 *ConfiguratorStagingConfigSetIterator) Error() error { + return it.fail +} + +func (it *ConfiguratorStagingConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ConfiguratorStagingConfigSet struct { + ConfigId [32]byte + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers [][]byte + OffchainTransmitters [][32]byte + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + IsGreenProduction bool + Raw types.Log +} + +func (_Configurator *ConfiguratorFilterer) FilterStagingConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ConfiguratorStagingConfigSetIterator, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _Configurator.contract.FilterLogs(opts, "StagingConfigSet", configIdRule) + if err != nil { + return nil, err + } + return &ConfiguratorStagingConfigSetIterator{contract: _Configurator.contract, event: "StagingConfigSet", logs: logs, sub: sub}, nil +} + +func (_Configurator *ConfiguratorFilterer) WatchStagingConfigSet(opts *bind.WatchOpts, sink chan<- *ConfiguratorStagingConfigSet, configId [][32]byte) (event.Subscription, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _Configurator.contract.WatchLogs(opts, "StagingConfigSet", configIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ConfiguratorStagingConfigSet) + if err := _Configurator.contract.UnpackLog(event, "StagingConfigSet", 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 (_Configurator *ConfiguratorFilterer) ParseStagingConfigSet(log types.Log) (*ConfiguratorStagingConfigSet, error) { + event := new(ConfiguratorStagingConfigSet) + if err := _Configurator.contract.UnpackLog(event, "StagingConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_Configurator *Configurator) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _Configurator.abi.Events["OwnershipTransferRequested"].ID: + return _Configurator.ParseOwnershipTransferRequested(log) + case _Configurator.abi.Events["OwnershipTransferred"].ID: + return _Configurator.ParseOwnershipTransferred(log) + case _Configurator.abi.Events["ProductionConfigSet"].ID: + return _Configurator.ParseProductionConfigSet(log) + case _Configurator.abi.Events["PromoteStagingConfig"].ID: + return _Configurator.ParsePromoteStagingConfig(log) + case _Configurator.abi.Events["StagingConfigSet"].ID: + return _Configurator.ParseStagingConfigSet(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (ConfiguratorOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (ConfiguratorOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (ConfiguratorProductionConfigSet) Topic() common.Hash { + return common.HexToHash("0x261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e2478") +} + +func (ConfiguratorPromoteStagingConfig) Topic() common.Hash { + return common.HexToHash("0x1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f") +} + +func (ConfiguratorStagingConfigSet) Topic() common.Hash { + return common.HexToHash("0xef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e89056") +} + +func (_Configurator *Configurator) Address() common.Address { + return _Configurator.address +} + +type ConfiguratorInterface interface { + 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) + + PromoteStagingConfig(opts *bind.TransactOpts, configId [32]byte, isGreenProduction bool) (*types.Transaction, error) + + SetProductionConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) + + SetStagingConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ConfiguratorOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ConfiguratorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*ConfiguratorOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ConfiguratorOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ConfiguratorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*ConfiguratorOwnershipTransferred, error) + + FilterProductionConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ConfiguratorProductionConfigSetIterator, error) + + WatchProductionConfigSet(opts *bind.WatchOpts, sink chan<- *ConfiguratorProductionConfigSet, configId [][32]byte) (event.Subscription, error) + + ParseProductionConfigSet(log types.Log) (*ConfiguratorProductionConfigSet, error) + + FilterPromoteStagingConfig(opts *bind.FilterOpts, configId [][32]byte, retiredConfigDigest [][32]byte) (*ConfiguratorPromoteStagingConfigIterator, error) + + WatchPromoteStagingConfig(opts *bind.WatchOpts, sink chan<- *ConfiguratorPromoteStagingConfig, configId [][32]byte, retiredConfigDigest [][32]byte) (event.Subscription, error) + + ParsePromoteStagingConfig(log types.Log) (*ConfiguratorPromoteStagingConfig, error) + + FilterStagingConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ConfiguratorStagingConfigSetIterator, error) + + WatchStagingConfigSet(opts *bind.WatchOpts, sink chan<- *ConfiguratorStagingConfigSet, configId [][32]byte) (event.Subscription, error) + + ParseStagingConfigSet(log types.Log) (*ConfiguratorStagingConfigSet, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/llo-feeds/generated/destination_fee_manager/destination_fee_manager.go b/core/gethwrappers/llo-feeds/generated/destination_fee_manager/destination_fee_manager.go index b87cf068ac5..fc9cda0b3d0 100644 --- a/core/gethwrappers/llo-feeds/generated/destination_fee_manager/destination_fee_manager.go +++ b/core/gethwrappers/llo-feeds/generated/destination_fee_manager/destination_fee_manager.go @@ -46,8 +46,8 @@ type IDestinationRewardManagerFeePayment struct { } var DestinationFeeManagerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_linkAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_nativeAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_verifierAddress\",\"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\":\"PoolIdMismatch\",\"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\":\"structIDestinationRewardManager.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\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"addVerifier\",\"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_rewardManager\",\"outputs\":[{\"internalType\":\"contractIDestinationRewardManager\",\"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\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"poolIds\",\"type\":\"bytes32[]\"},{\"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\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"removeVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_verifierAddressList\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"address\",\"name\":\"rewardManagerAddress\",\"type\":\"address\"}],\"name\":\"setRewardManager\",\"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\":\"assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"quantity\",\"type\":\"uint192\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b5060405162003c3238038062003c328339810160408190526200003491620002af565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620001e7565b5050506001600160a01b0384161580620000df57506001600160a01b038316155b80620000f257506001600160a01b038216155b806200010557506001600160a01b038116155b15620001245760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03848116608081905284821660a05283821660008181526004602081905260409182902080546001600160a01b03199081169094179055600580549093169486169485179092555163095ea7b360e01b81529081019290925260001960248301529063095ea7b3906044016020604051808303816000875af1158015620001b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001dc91906200030c565b505050505062000337565b336001600160a01b03821603620002415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620002aa57600080fd5b919050565b60008060008060808587031215620002c657600080fd5b620002d18562000292565b9350620002e16020860162000292565b9250620002f16040860162000292565b9150620003016060860162000292565b905092959194509250565b6000602082840312156200031f57600080fd5b815180151581146200033057600080fd5b9392505050565b60805160a051613850620003e26000396000818161033b0152818161151c0152818161177a015281816117d101528181611a7e0152818161248e01526125370152600081816105430152818161098e01528181610a9801528181610e9b015281816111f4015281816114c50152818161165c0152818161179f015281816118280152818161196d015281816119da01528181611a1a01528181612109015261262b01526138506000f3fe60806040526004361061018b5760003560e01c806386968cfd116100d6578063d09dc3391161007f578063ea4b861b11610059578063ea4b861b14610531578063f2fde38b14610565578063f65df9621461058557600080fd5b8063d09dc33914610491578063e03dab1a146104a6578063e389d9a41461051157600080fd5b80639000b3d6116100b05780639000b3d614610431578063ca2dfd0a14610451578063ce7817d11461047157600080fd5b806386968cfd146103b557806387d6d843146103c85780638da5cb5b1461040657600080fd5b80633690750911610138578063638786681161011257806363878668146103295780637700feeb1461035d57806379ba5097146103a057600080fd5b806336907509146102a45780633aa5ac07146102b7578063505380941461030957600080fd5b8063181f5a7711610169578063181f5a77146102225780631d4d84a21461026e57806332f5f7461461028e57600080fd5b8063013f542b1461019057806301ffc9a7146101d0578063153ee55414610200575b600080fd5b34801561019c57600080fd5b506101bd6101ab366004612d9a565b60036020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101dc57600080fd5b506101f06101eb366004612db3565b6105a5565b60405190151581526020016101c7565b34801561020c57600080fd5b5061022061021b366004612e27565b6108ea565b005b34801561022e57600080fd5b50604080518082018252601b81527f44657374696e6174696f6e4665654d616e6167657220312e302e300000000000602082015290516101c79190612e68565b34801561027a57600080fd5b50610220610289366004612edf565b610b0b565b34801561029a57600080fd5b506101bd60065481565b6102206102b2366004613036565b610c9f565b3480156102c357600080fd5b506005546102e49073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c7565b34801561031557600080fd5b50610220610324366004613156565b610f50565b34801561033557600080fd5b506102e47f000000000000000000000000000000000000000000000000000000000000000081565b34801561036957600080fd5b506102e4610378366004612e27565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156103ac57600080fd5b50610220610fea565b6102206103c3366004613171565b6110ec565b3480156103d457600080fd5b506101bd6103e33660046131fd565b600260209081526000938452604080852082529284528284209052825290205481565b34801561041257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166102e4565b34801561043d57600080fd5b5061022061044c366004612e27565b61126d565b34801561045d57600080fd5b5061022061046c366004612e27565b611370565b34801561047d57600080fd5b5061022061048c366004613234565b61146f565b34801561049d57600080fd5b506101bd61162b565b3480156104b257600080fd5b506104c66104c1366004613313565b6116e1565b60408051845173ffffffffffffffffffffffffffffffffffffffff9081168252602095860151868301528451169181019190915292909101516060830152608082015260a0016101c7565b34801561051d57600080fd5b5061022061052c366004612d9a565b611ae0565b34801561053d57600080fd5b506102e47f000000000000000000000000000000000000000000000000000000000000000081565b34801561057157600080fd5b50610220610580366004612e27565b611c95565b34801561059157600080fd5b506102206105a036600461336c565b611ca9565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe03dab1a00000000000000000000000000000000000000000000000000000000148061063857507fffffffff0000000000000000000000000000000000000000000000000000000082167f5053809400000000000000000000000000000000000000000000000000000000145b8061068457507fffffffff0000000000000000000000000000000000000000000000000000000082167fce7817d100000000000000000000000000000000000000000000000000000000145b806106d057507fffffffff0000000000000000000000000000000000000000000000000000000082167f1d4d84a200000000000000000000000000000000000000000000000000000000145b8061071c57507fffffffff0000000000000000000000000000000000000000000000000000000082167fd09dc33900000000000000000000000000000000000000000000000000000000145b8061076857507fffffffff0000000000000000000000000000000000000000000000000000000082167fe389d9a400000000000000000000000000000000000000000000000000000000145b806107b457507fffffffff0000000000000000000000000000000000000000000000000000000082167f9000b3d600000000000000000000000000000000000000000000000000000000145b8061080057507fffffffff0000000000000000000000000000000000000000000000000000000082167fca2dfd0a00000000000000000000000000000000000000000000000000000000145b8061084c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f86968cfd00000000000000000000000000000000000000000000000000000000145b8061089857507fffffffff0000000000000000000000000000000000000000000000000000000082167f3690750900000000000000000000000000000000000000000000000000000000145b806108e457507fffffffff0000000000000000000000000000000000000000000000000000000082167ff65df96200000000000000000000000000000000000000000000000000000000145b92915050565b6108f2611dbd565b73ffffffffffffffffffffffffffffffffffffffff811661093f576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af11580156109d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fd91906133eb565b50600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092556040517f095ea7b300000000000000000000000000000000000000000000000000000000815260048101919091527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015610ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0791906133eb565b5050565b610b13611dbd565b73ffffffffffffffffffffffffffffffffffffffff8316610be85760008273ffffffffffffffffffffffffffffffffffffffff168277ffffffffffffffffffffffffffffffffffffffffffffffff1660405160006040518083038185875af1925050503d8060008114610ba2576040519150601f19603f3d011682016040523d82523d6000602084013e610ba7565b606091505b5050905080610be2576040517fef2af20100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b610c2373ffffffffffffffffffffffffffffffffffffffff84168377ffffffffffffffffffffffffffffffffffffffffffffffff8416611e40565b6040805133815273ffffffffffffffffffffffffffffffffffffffff848116602083015285168183015277ffffffffffffffffffffffffffffffffffffffffffffffff8316606082015290517f7ff78a71698bdb18dcca96f52ab25e0a1b146fb6a49adf8e6845299e49021f299181900360800190a15b505050565b3360008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1614610cfc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85518414610d35576040517e154a0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008467ffffffffffffffff811115610d5057610d50612f2a565b604051908082528060200260200182016040528015610d8957816020015b610d76612d0d565b815260200190600190039081610d6e5790505b5090506000806000805b88811015610f16576000801b8b8281518110610db157610db161340d565b602002602001015103610df0576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000610e248d8d86818110610e0a57610e0a61340d565b9050602002810190610e1c919061343c565b8d8d8d611f14565b9250925092508260200151600014610f025760405180608001604052808f8681518110610e5357610e5361340d565b6020026020010151815260200184815260200183815260200182815250888680610e7c906134d0565b975081518110610e8e57610e8e61340d565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1603610efb57866001019650610f02565b8560010195505b50505080610f0f906134d0565b9050610d93565b5082151580610f2457508115155b15610f3a57610f3585858585612024565b610f44565b610f44853461281e565b50505050505050505050565b610f58611dbd565b670de0b6b3a764000067ffffffffffffffff82161115610fa4576040517f05e8ac2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660068190556040519081527f08f7c0d17932ddb8523bc06754d42ff19ebc77d76a8b9bfde02c28ab1ed3d6399060200160405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff163314611070576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1614611149576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061115b8888888888611f14565b925092509250826020015160000361117f57611177843461281e565b505050611265565b604080516001808252818301909252600091816020015b61119e612d0d565b81526020019060019003908161119657905050905060405180608001604052808b815260200185815260200184815260200183815250816000815181106111e7576111e761340d565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff160361125757610f35858260016000612024565b610f44858260006001612024565b505050505050565b611275611dbd565b73ffffffffffffffffffffffffffffffffffffffff81166112c2576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600460205260409020541615611321576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b611378611dbd565b73ffffffffffffffffffffffffffffffffffffffff81166113c5576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81811660009081526004602052604090205416611423576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b611477611dbd565b670de0b6b3a764000067ffffffffffffffff821611156114c3576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561156b57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b156115a2576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff848116600081815260026020908152604080832088845282528083209487168084529482529182902067ffffffffffffffff86169081905582519485529084015285927f5eba5a8afa39780f0f99b6cbeb95f3da6a7040ca00abd46bdc91a0a060134139910160405180910390a350505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156116b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116dc9190613508565b905090565b604080518082018252600080825260208083018290528351808501855282815280820183905284518086018652838152808301849052855180870190965283865291850183905292938261173488613521565b90507fffff0000000000000000000000000000000000000000000000000000000000008082169081016117cf57505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811683527f0000000000000000000000000000000000000000000000000000000000000000168152909350915060009050611ad7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415801561187757507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b156118ae576040517ff861803000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008b8060200190518101906118c7919061357a565b77ffffffffffffffffffffffffffffffffffffffffffffffff91821698509116955063ffffffff169350505042821015905061192f576040517fb6c405f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808e16600090815260026020908152604080832089845282528083208f851684529091529020547f000000000000000000000000000000000000000000000000000000000000000090911687526119be6119a682670de0b6b3a76400006135e0565b6119b090866135f3565b670de0b6b3a7640000612867565b602088015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116908d1603611a4b5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016885260208088015190890152611ac8565b600654600090611a67906119a690670de0b6b3a764000061360a565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168a529050611ac1611ab783670de0b6b3a76400006135e0565b6119b090836135f3565b60208a0152505b96995094975094955050505050505b93509350939050565b611ae8611dbd565b60008181526003602052604081205490819003611b31576040517f03aad31200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600360205260408082208290558051600180825281830190925290816020015b6040805180820190915260008082526020820152815260200190600190039081611b5657905050905060405180604001604052808481526020018377ffffffffffffffffffffffffffffffffffffffffffffffff1681525081600081518110611bc157611bc161340d565b60209081029190910101526005546040517fb0d9fa1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063b0d9fa1990611c24908490309060040161367d565b600060405180830381600087803b158015611c3e57600080fd5b505af1158015611c52573d6000803e3d6000fd5b50505050827f843f0b103e50b42b08f9d30f12f961845a6d02623730872e24644899c0dd989583604051611c8891815260200190565b60405180910390a2505050565b611c9d611dbd565b611ca68161289f565b50565b3360008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1614801590611cf5575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611d2c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546040517f14060f2300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906314060f2390611d86908690869086906004016136b5565b600060405180830381600087803b158015611da057600080fd5b505af1158015611db4573d6000803e3d6000fd5b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401611067565b565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610c9a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612994565b6040805180820190915260008082526020820152604080518082019091526000808252602082015260003073ffffffffffffffffffffffffffffffffffffffff851603611f8d576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611f9b888a018a613735565b915050600081611faa90613521565b905060007e010000000000000000000000000000000000000000000000000000000000007fffff00000000000000000000000000000000000000000000000000000000000083161461200557612002888a018a612e27565b90505b6120108784836116e1565b955095509550505050955095509592505050565b60008267ffffffffffffffff81111561203f5761203f612f2a565b60405190808252806020026020018201604052801561208457816020015b604080518082019091526000808252602082015281526020019060019003908161205d5790505b50905060008267ffffffffffffffff8111156120a2576120a2612f2a565b6040519080825280602002602001820160405280156120e757816020015b60408051808201909152600080825260208201528152602001906001900390816120c05790505b5090506000808080806120fa888a61360a565b905060005b81811015612449577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b82815181106121505761215061340d565b6020026020010151602001516000015173ffffffffffffffffffffffffffffffffffffffff16036122165760405180604001604052808c83815181106121985761219861340d565b60200260200101516000015181526020018c83815181106121bb576121bb61340d565b6020026020010151604001516020015177ffffffffffffffffffffffffffffffffffffffffffffffff168152508885806121f4906134d0565b9650815181106122065761220661340d565b602002602001018190525061230b565b60405180604001604052808c83815181106122335761223361340d565b60200260200101516000015181526020018c83815181106122565761225661340d565b6020026020010151604001516020015177ffffffffffffffffffffffffffffffffffffffffffffffff1681525087848061228f906134d0565b9550815181106122a1576122a161340d565b60200260200101819052508a81815181106122be576122be61340d565b60200260200101516020015160200151866122d9919061360a565b95508a81815181106122ed576122ed61340d565b6020026020010151604001516020015185612308919061360a565b94505b8a818151811061231d5761231d61340d565b602002602001015160600151600014612439578b73ffffffffffffffffffffffffffffffffffffffff168b82815181106123595761235961340d565b6020026020010151600001517f88b15eb682210089cddf967648e2cb2a4535aeadc8f8f36050922e33c04e71258d84815181106123985761239861340d565b6020026020010151602001518e85815181106123b6576123b661340d565b6020026020010151604001518f86815181106123d4576123d461340d565b60200260200101516060015160405161243093929190835173ffffffffffffffffffffffffffffffffffffffff908116825260209485015185830152835116604082015291909201516060820152608081019190915260a00190565b60405180910390a35b612442816134d0565b90506120ff565b5060003415612517573486111561248c576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156124f457600080fd5b505af1158015612508573d6000803e3d6000fd5b5050505050853403905061255f565b851561255f5761255f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168d3089612aa0565b8751156125f657600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b0d9fa19898e6040518363ffffffff1660e01b81526004016125c392919061367d565b600060405180830381600087803b1580156125dd57600080fd5b505af11580156125f1573d6000803e3d6000fd5b505050505b865115612806576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612687573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ab9190613508565b85111561277b5760005b875181101561273e578781815181106126d0576126d061340d565b60200260200101516020015177ffffffffffffffffffffffffffffffffffffffffffffffff16600360008a848151811061270c5761270c61340d565b60209081029190910181015151825281019190915260400160002080549091019055612737816134d0565b90506126b5565b507ff52e5907b69d97c33392936c12d78b494463b78c5b72df50b4c497eee5720b678760405161276e91906137d9565b60405180910390a1612806565b6005546040517fb0d9fa1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063b0d9fa19906127d3908a90309060040161367d565b600060405180830381600087803b1580156127ed57600080fd5b505af1158015612801573d6000803e3d6000fd5b505050505b6128108c8261281e565b505050505050505050505050565b8015610b075760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610c9a573d6000803e3d6000fd5b60008215612895578161287b6001856135e0565b61288591906137ec565b61289090600161360a565b612898565b60005b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361291e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401611067565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006129f6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612afe9092919063ffffffff16565b805190915015610c9a5780806020019051810190612a1491906133eb565b610c9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611067565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610be29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611e92565b6060612b0d8484600085612b15565b949350505050565b606082471015612ba7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611067565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bd09190613827565b60006040518083038185875af1925050503d8060008114612c0d576040519150601f19603f3d011682016040523d82523d6000602084013e612c12565b606091505b5091509150612c2387838387612c2e565b979650505050505050565b60608315612cc4578251600003612cbd5773ffffffffffffffffffffffffffffffffffffffff85163b612cbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611067565b5081612b0d565b612b0d8383815115612cd95781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110679190612e68565b604051806080016040528060008019168152602001612d556040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b8152602001612d8d6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b8152602001600081525090565b600060208284031215612dac57600080fd5b5035919050565b600060208284031215612dc557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461289857600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611ca657600080fd5b8035612e2281612df5565b919050565b600060208284031215612e3957600080fd5b813561289881612df5565b60005b83811015612e5f578181015183820152602001612e47565b50506000910152565b6020815260008251806020840152612e87816040850160208701612e44565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b77ffffffffffffffffffffffffffffffffffffffffffffffff81168114611ca657600080fd5b600080600060608486031215612ef457600080fd5b8335612eff81612df5565b92506020840135612f0f81612df5565b91506040840135612f1f81612eb9565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612fa057612fa0612f2a565b604052919050565b60008083601f840112612fba57600080fd5b50813567ffffffffffffffff811115612fd257600080fd5b6020830191508360208260051b8501011115612fed57600080fd5b9250929050565b60008083601f84011261300657600080fd5b50813567ffffffffffffffff81111561301e57600080fd5b602083019150836020828501011115612fed57600080fd5b6000806000806000806080878903121561304f57600080fd5b863567ffffffffffffffff8082111561306757600080fd5b818901915089601f83011261307b57600080fd5b813560208282111561308f5761308f612f2a565b8160051b61309e828201612f59565b928352848101820192828101908e8511156130b857600080fd5b958301955b848710156130d6578635825295830195908301906130bd565b9b5050508a0135925050808211156130ed57600080fd5b6130f98a838b01612fa8565b9097509550604089013591508082111561311257600080fd5b5061311f89828a01612ff4565b9094509250613132905060608801612e17565b90509295509295509295565b803567ffffffffffffffff81168114612e2257600080fd5b60006020828403121561316857600080fd5b6128988261313e565b6000806000806000806080878903121561318a57600080fd5b86359550602087013567ffffffffffffffff808211156131a957600080fd5b6131b58a838b01612ff4565b909750955060408901359150808211156131ce57600080fd5b506131db89828a01612ff4565b90945092505060608701356131ef81612df5565b809150509295509295509295565b60008060006060848603121561321257600080fd5b833561321d81612df5565b9250602084013591506040840135612f1f81612df5565b6000806000806080858703121561324a57600080fd5b843561325581612df5565b935060208501359250604085013561326c81612df5565b915061327a6060860161313e565b905092959194509250565b600082601f83011261329657600080fd5b813567ffffffffffffffff8111156132b0576132b0612f2a565b6132e160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612f59565b8181528460208386010111156132f657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561332857600080fd5b833561333381612df5565b9250602084013567ffffffffffffffff81111561334f57600080fd5b61335b86828701613285565b9250506040840135612f1f81612df5565b60008060006040848603121561338157600080fd5b83359250602084013567ffffffffffffffff808211156133a057600080fd5b818601915086601f8301126133b457600080fd5b8135818111156133c357600080fd5b8760208260061b85010111156133d857600080fd5b6020830194508093505050509250925092565b6000602082840312156133fd57600080fd5b8151801515811461289857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261347157600080fd5b83018035915067ffffffffffffffff82111561348c57600080fd5b602001915036819003821315612fed57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613501576135016134a1565b5060010190565b60006020828403121561351a57600080fd5b5051919050565b80516020808301519190811015613560577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b805163ffffffff81168114612e2257600080fd5b60008060008060008060c0878903121561359357600080fd5b865195506135a360208801613566565b94506135b160408801613566565b935060608701516135c181612eb9565b60808801519093506135d281612eb9565b915061313260a08801613566565b818103818111156108e4576108e46134a1565b80820281158282048414176108e4576108e46134a1565b808201808211156108e4576108e46134a1565b600081518084526020808501945080840160005b838110156136725781518051885283015177ffffffffffffffffffffffffffffffffffffffffffffffff168388015260409096019590820190600101613631565b509495945050505050565b604081526000613690604083018561361d565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b8381526040602080830182905282820184905260009190859060608501845b878110156137285783356136e781612df5565b73ffffffffffffffffffffffffffffffffffffffff16825267ffffffffffffffff61371385850161313e565b168284015292840192908401906001016136d4565b5098975050505050505050565b6000806080838503121561374857600080fd5b83601f84011261375757600080fd5b6040516060810167ffffffffffffffff828210818311171561377b5761377b612f2a565b81604052829150606086018781111561379357600080fd5b865b818110156137ad578035845260209384019301613795565b50929450913591808311156137c157600080fd5b50506137cf85828601613285565b9150509250929050565b602081526000612898602083018461361d565b600082613822577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613839818460208701612e44565b919091019291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_linkAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_nativeAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_verifierAddress\",\"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\":\"PoolIdMismatch\",\"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\":\"structIDestinationRewardManager.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\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"addVerifier\",\"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_rewardManager\",\"outputs\":[{\"internalType\":\"contractIDestinationRewardManager\",\"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\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"poolIds\",\"type\":\"bytes32[]\"},{\"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\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"removeVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_verifierAddressList\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"address\",\"name\":\"rewardManagerAddress\",\"type\":\"address\"}],\"name\":\"setRewardManager\",\"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: "0x60c06040523480156200001157600080fd5b5060405162003d4538038062003d458339810160408190526200003491620002ae565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620001e6565b5050506001600160a01b0384161580620000df57506001600160a01b038316155b80620000f257506001600160a01b038216155b806200010557506001600160a01b038116155b15620001245760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03848116608081905284821660a0528382166000818152600560205260409081902080546001600160a01b03199081169093179055600680549092169385169384179091555163095ea7b360e01b8152600481019290925260001960248301529063095ea7b3906044016020604051808303816000875af1158015620001b5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001db91906200030b565b505050505062000336565b336001600160a01b03821603620002405760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620002a957600080fd5b919050565b60008060008060808587031215620002c557600080fd5b620002d08562000291565b9350620002e06020860162000291565b9250620002f06040860162000291565b9150620003006060860162000291565b905092959194509250565b6000602082840312156200031e57600080fd5b815180151581146200032f57600080fd5b9392505050565b60805160a051613956620003ef6000396000818161038901528181610f3d01528181611577015281816117d50152818161182c01528181611b2a0152818161251401526125bd0152600081816105b1015281816108340152818161093e01528181610d4101528181610ee60152818161124f01528181611520015281816116b7015281816117fa0152818161188301528181611a1b01528181611a8601528181611ac60152818161218f01526126b101526139566000f3fe6080604052600436106101a15760003560e01c806379ba5097116100e1578063ce7817d11161008a578063e389d9a411610064578063e389d9a41461057f578063ea4b861b1461059f578063f2fde38b146105d3578063f65df962146105f357600080fd5b8063ce7817d1146104df578063d09dc339146104ff578063e03dab1a1461051457600080fd5b80638da5cb5b116100bb5780638da5cb5b146104745780639000b3d61461049f578063ca2dfd0a146104bf57600080fd5b806379ba50971461040e57806386968cfd1461042357806387d6d8431461043657600080fd5b806332f5f7461161014e57806350538094116101285780635053809414610357578063638786681461037757806376cf3187146103ab5780637700feeb146103cb57600080fd5b806332f5f746146102dc57806336907509146102f25780633aa5ac071461030557600080fd5b8063181f5a771161017f578063181f5a77146102385780631cc7f2d8146102845780631d4d84a2146102bc57600080fd5b8063013f542b146101a657806301ffc9a7146101e6578063153ee55414610216575b600080fd5b3480156101b257600080fd5b506101d36101c1366004612e20565b60046020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101f257600080fd5b50610206610201366004612e39565b610613565b60405190151581526020016101dd565b34801561022257600080fd5b50610236610231366004612ead565b6106ac565b005b34801561024457600080fd5b50604080518082018252601b81527f44657374696e6174696f6e4665654d616e6167657220302e342e300000000000602082015290516101dd9190612eee565b34801561029057600080fd5b506101d361029f366004612f3f565b600360209081526000928352604080842090915290825290205481565b3480156102c857600080fd5b506102366102d7366004612f9e565b6109b1565b3480156102e857600080fd5b506101d360075481565b6102366103003660046130f5565b610b45565b34801561031157600080fd5b506006546103329073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101dd565b34801561036357600080fd5b50610236610372366004613215565b610df6565b34801561038357600080fd5b506103327f000000000000000000000000000000000000000000000000000000000000000081565b3480156103b757600080fd5b506102366103c6366004613230565b610e90565b3480156103d757600080fd5b506103326103e6366004612ead565b60056020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561041a57600080fd5b50610236611045565b610236610431366004613277565b611147565b34801561044257600080fd5b506101d3610451366004613303565b600260209081526000938452604080852082529284528284209052825290205481565b34801561048057600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610332565b3480156104ab57600080fd5b506102366104ba366004612ead565b6112c8565b3480156104cb57600080fd5b506102366104da366004612ead565b6113cb565b3480156104eb57600080fd5b506102366104fa36600461333a565b6114ca565b34801561050b57600080fd5b506101d3611686565b34801561052057600080fd5b5061053461052f366004613419565b61173c565b60408051845173ffffffffffffffffffffffffffffffffffffffff9081168252602095860151868301528451169181019190915292909101516060830152608082015260a0016101dd565b34801561058b57600080fd5b5061023661059a366004612e20565b611b8c565b3480156105ab57600080fd5b506103327f000000000000000000000000000000000000000000000000000000000000000081565b3480156105df57600080fd5b506102366105ee366004612ead565b611d41565b3480156105ff57600080fd5b5061023661060e366004613472565b611d55565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f6993386f0000000000000000000000000000000000000000000000000000000014806106a657507fffffffff0000000000000000000000000000000000000000000000000000000082167f465b009600000000000000000000000000000000000000000000000000000000145b92915050565b6106b4611e43565b73ffffffffffffffffffffffffffffffffffffffff8116610701576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f768ffd3a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa15801561078b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107af91906134f1565b6107e5576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af115801561087f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a391906134f1565b50600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092556040517f095ea7b300000000000000000000000000000000000000000000000000000000815260048101919091527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015610989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ad91906134f1565b5050565b6109b9611e43565b73ffffffffffffffffffffffffffffffffffffffff8316610a8e5760008273ffffffffffffffffffffffffffffffffffffffff168277ffffffffffffffffffffffffffffffffffffffffffffffff1660405160006040518083038185875af1925050503d8060008114610a48576040519150601f19603f3d011682016040523d82523d6000602084013e610a4d565b606091505b5050905080610a88576040517fef2af20100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b610ac973ffffffffffffffffffffffffffffffffffffffff84168377ffffffffffffffffffffffffffffffffffffffffffffffff8416611ec6565b6040805133815273ffffffffffffffffffffffffffffffffffffffff848116602083015285168183015277ffffffffffffffffffffffffffffffffffffffffffffffff8316606082015290517f7ff78a71698bdb18dcca96f52ab25e0a1b146fb6a49adf8e6845299e49021f299181900360800190a15b505050565b3360008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff1614610ba2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85518414610bdb576040517e154a0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008467ffffffffffffffff811115610bf657610bf6612fe9565b604051908082528060200260200182016040528015610c2f57816020015b610c1c612d93565b815260200190600190039081610c145790505b5090506000806000805b88811015610dbc576000801b8b8281518110610c5757610c57613513565b602002602001015103610c96576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000610cca8d8d86818110610cb057610cb0613513565b9050602002810190610cc29190613542565b8d8d8d611f9a565b9250925092508260200151600014610da85760405180608001604052808f8681518110610cf957610cf9613513565b6020026020010151815260200184815260200183815260200182815250888680610d22906135d6565b975081518110610d3457610d34613513565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1603610da157866001019650610da8565b8560010195505b50505080610db5906135d6565b9050610c39565b5082151580610dca57508115155b15610de057610ddb858585856120aa565b610dea565b610dea85346128a4565b50505050505050505050565b610dfe611e43565b670de0b6b3a764000067ffffffffffffffff82161115610e4a576040517f05e8ac2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660078190556040519081527f08f7c0d17932ddb8523bc06754d42ff19ebc77d76a8b9bfde02c28ab1ed3d6399060200160405180910390a150565b610e98611e43565b670de0b6b3a764000067ffffffffffffffff82161115610ee4576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610f8c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15610fc3576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff838116600081815260036020908152604080832094871680845294825280832067ffffffffffffffff87169081905581519586529185019190915290927f5eba5a8afa39780f0f99b6cbeb95f3da6a7040ca00abd46bdc91a0a060134139910160405180910390a3505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146110cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16146111a4576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060006111b68888888888611f9a565b92509250925082602001516000036111da576111d284346128a4565b5050506112c0565b604080516001808252818301909252600091816020015b6111f9612d93565b8152602001906001900390816111f157905050905060405180608001604052808b8152602001858152602001848152602001838152508160008151811061124257611242613513565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff16036112b257610ddb8582600160006120aa565b610dea8582600060016120aa565b505050505050565b6112d0611e43565b73ffffffffffffffffffffffffffffffffffffffff811661131d576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff818116600090815260056020526040902054161561137c576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600081815260056020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b6113d3611e43565b73ffffffffffffffffffffffffffffffffffffffff8116611420576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600560205260409020541661147e576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260056020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6114d2611e43565b670de0b6b3a764000067ffffffffffffffff8216111561151e576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156115c657507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b156115fd576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff848116600081815260026020908152604080832088845282528083209487168084529482529182902067ffffffffffffffff86169081905582519485529084015285927f5eba5a8afa39780f0f99b6cbeb95f3da6a7040ca00abd46bdc91a0a060134139910160405180910390a350505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611737919061360e565b905090565b604080518082018252600080825260208083018290528351808501855282815280820183905284518086018652838152808301849052855180870190965283865291850183905292938261178f88613627565b90507fffff00000000000000000000000000000000000000000000000000000000000080821690810161182a57505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811683527f0000000000000000000000000000000000000000000000000000000000000000168152909350915060009050611b83565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141580156118d257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b15611909576040517ff861803000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008b8060200190518101906119229190613680565b77ffffffffffffffffffffffffffffffffffffffffffffffff91821698509116955063ffffffff169350505042821015905061198a576040517fb6c405f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808e1660009081526002602090815260408083208984528252808320938f1683529290529081205490819003611a04575073ffffffffffffffffffffffffffffffffffffffff808e166000908152600360209081526040808320938f16835292905220545b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168752611a6a611a5282670de0b6b3a76400006136e6565b611a5c90866136f9565b670de0b6b3a76400006128ed565b602088015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116908d1603611af75773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016885260208088015190890152611b74565b600754600090611b1390611a5290670de0b6b3a7640000613710565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168a529050611b6d611b6383670de0b6b3a76400006136e6565b611a5c90836136f9565b60208a0152505b96995094975094955050505050505b93509350939050565b611b94611e43565b60008181526004602052604081205490819003611bdd576040517f03aad31200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460205260408082208290558051600180825281830190925290816020015b6040805180820190915260008082526020820152815260200190600190039081611c0257905050905060405180604001604052808481526020018377ffffffffffffffffffffffffffffffffffffffffffffffff1681525081600081518110611c6d57611c6d613513565b60209081029190910101526006546040517fb0d9fa1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063b0d9fa1990611cd09084903090600401613783565b600060405180830381600087803b158015611cea57600080fd5b505af1158015611cfe573d6000803e3d6000fd5b50505050827f843f0b103e50b42b08f9d30f12f961845a6d02623730872e24644899c0dd989583604051611d3491815260200190565b60405180910390a2505050565b611d49611e43565b611d5281612925565b50565b3360008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff1614611db2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006546040517f14060f2300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906314060f2390611e0c908690869086906004016137bb565b600060405180830381600087803b158015611e2657600080fd5b505af1158015611e3a573d6000803e3d6000fd5b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ec4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016110c2565b565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b409084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a1a565b6040805180820190915260008082526020820152604080518082019091526000808252602082015260003073ffffffffffffffffffffffffffffffffffffffff851603612013576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612021888a018a61383b565b91505060008161203090613627565b905060007e010000000000000000000000000000000000000000000000000000000000007fffff00000000000000000000000000000000000000000000000000000000000083161461208b57612088888a018a612ead565b90505b61209687848361173c565b955095509550505050955095509592505050565b60008267ffffffffffffffff8111156120c5576120c5612fe9565b60405190808252806020026020018201604052801561210a57816020015b60408051808201909152600080825260208201528152602001906001900390816120e35790505b50905060008267ffffffffffffffff81111561212857612128612fe9565b60405190808252806020026020018201604052801561216d57816020015b60408051808201909152600080825260208201528152602001906001900390816121465790505b509050600080808080612180888a613710565b905060005b818110156124cf577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b82815181106121d6576121d6613513565b6020026020010151602001516000015173ffffffffffffffffffffffffffffffffffffffff160361229c5760405180604001604052808c838151811061221e5761221e613513565b60200260200101516000015181526020018c838151811061224157612241613513565b6020026020010151604001516020015177ffffffffffffffffffffffffffffffffffffffffffffffff1681525088858061227a906135d6565b96508151811061228c5761228c613513565b6020026020010181905250612391565b60405180604001604052808c83815181106122b9576122b9613513565b60200260200101516000015181526020018c83815181106122dc576122dc613513565b6020026020010151604001516020015177ffffffffffffffffffffffffffffffffffffffffffffffff16815250878480612315906135d6565b95508151811061232757612327613513565b60200260200101819052508a818151811061234457612344613513565b602002602001015160200151602001518661235f9190613710565b95508a818151811061237357612373613513565b602002602001015160400151602001518561238e9190613710565b94505b8a81815181106123a3576123a3613513565b6020026020010151606001516000146124bf578b73ffffffffffffffffffffffffffffffffffffffff168b82815181106123df576123df613513565b6020026020010151600001517f88b15eb682210089cddf967648e2cb2a4535aeadc8f8f36050922e33c04e71258d848151811061241e5761241e613513565b6020026020010151602001518e858151811061243c5761243c613513565b6020026020010151604001518f868151811061245a5761245a613513565b6020026020010151606001516040516124b693929190835173ffffffffffffffffffffffffffffffffffffffff908116825260209485015185830152835116604082015291909201516060820152608081019190915260a00190565b60405180910390a35b6124c8816135d6565b9050612185565b506000341561259d5734861115612512576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b15801561257a57600080fd5b505af115801561258e573d6000803e3d6000fd5b505050505085340390506125e5565b85156125e5576125e573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168d3089612b26565b87511561267c57600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b0d9fa19898e6040518363ffffffff1660e01b8152600401612649929190613783565b600060405180830381600087803b15801561266357600080fd5b505af1158015612677573d6000803e3d6000fd5b505050505b86511561288c576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561270d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612731919061360e565b8511156128015760005b87518110156127c45787818151811061275657612756613513565b60200260200101516020015177ffffffffffffffffffffffffffffffffffffffffffffffff16600460008a848151811061279257612792613513565b602090810291909101810151518252810191909152604001600020805490910190556127bd816135d6565b905061273b565b507ff52e5907b69d97c33392936c12d78b494463b78c5b72df50b4c497eee5720b67876040516127f491906138df565b60405180910390a161288c565b6006546040517fb0d9fa1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063b0d9fa1990612859908a903090600401613783565b600060405180830381600087803b15801561287357600080fd5b505af1158015612887573d6000803e3d6000fd5b505050505b6128968c826128a4565b505050505050505050505050565b80156109ad5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610b40573d6000803e3d6000fd5b6000821561291b57816129016001856136e6565b61290b91906138f2565b612916906001613710565b61291e565b60005b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036129a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016110c2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612a7c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612b849092919063ffffffff16565b805190915015610b405780806020019051810190612a9a91906134f1565b610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016110c2565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610a889085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611f18565b6060612b938484600085612b9b565b949350505050565b606082471015612c2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016110c2565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612c56919061392d565b60006040518083038185875af1925050503d8060008114612c93576040519150601f19603f3d011682016040523d82523d6000602084013e612c98565b606091505b5091509150612ca987838387612cb4565b979650505050505050565b60608315612d4a578251600003612d435773ffffffffffffffffffffffffffffffffffffffff85163b612d43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016110c2565b5081612b93565b612b938383815115612d5f5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c29190612eee565b604051806080016040528060008019168152602001612ddb6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b8152602001612e136040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b8152602001600081525090565b600060208284031215612e3257600080fd5b5035919050565b600060208284031215612e4b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461291e57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611d5257600080fd5b8035612ea881612e7b565b919050565b600060208284031215612ebf57600080fd5b813561291e81612e7b565b60005b83811015612ee5578181015183820152602001612ecd565b50506000910152565b6020815260008251806020840152612f0d816040850160208701612eca565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215612f5257600080fd5b8235612f5d81612e7b565b91506020830135612f6d81612e7b565b809150509250929050565b77ffffffffffffffffffffffffffffffffffffffffffffffff81168114611d5257600080fd5b600080600060608486031215612fb357600080fd5b8335612fbe81612e7b565b92506020840135612fce81612e7b565b91506040840135612fde81612f78565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561305f5761305f612fe9565b604052919050565b60008083601f84011261307957600080fd5b50813567ffffffffffffffff81111561309157600080fd5b6020830191508360208260051b85010111156130ac57600080fd5b9250929050565b60008083601f8401126130c557600080fd5b50813567ffffffffffffffff8111156130dd57600080fd5b6020830191508360208285010111156130ac57600080fd5b6000806000806000806080878903121561310e57600080fd5b863567ffffffffffffffff8082111561312657600080fd5b818901915089601f83011261313a57600080fd5b813560208282111561314e5761314e612fe9565b8160051b61315d828201613018565b928352848101820192828101908e85111561317757600080fd5b958301955b848710156131955786358252958301959083019061317c565b9b5050508a0135925050808211156131ac57600080fd5b6131b88a838b01613067565b909750955060408901359150808211156131d157600080fd5b506131de89828a016130b3565b90945092506131f1905060608801612e9d565b90509295509295509295565b803567ffffffffffffffff81168114612ea857600080fd5b60006020828403121561322757600080fd5b61291e826131fd565b60008060006060848603121561324557600080fd5b833561325081612e7b565b9250602084013561326081612e7b565b915061326e604085016131fd565b90509250925092565b6000806000806000806080878903121561329057600080fd5b86359550602087013567ffffffffffffffff808211156132af57600080fd5b6132bb8a838b016130b3565b909750955060408901359150808211156132d457600080fd5b506132e189828a016130b3565b90945092505060608701356132f581612e7b565b809150509295509295509295565b60008060006060848603121561331857600080fd5b833561332381612e7b565b9250602084013591506040840135612fde81612e7b565b6000806000806080858703121561335057600080fd5b843561335b81612e7b565b935060208501359250604085013561337281612e7b565b9150613380606086016131fd565b905092959194509250565b600082601f83011261339c57600080fd5b813567ffffffffffffffff8111156133b6576133b6612fe9565b6133e760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613018565b8181528460208386010111156133fc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561342e57600080fd5b833561343981612e7b565b9250602084013567ffffffffffffffff81111561345557600080fd5b6134618682870161338b565b9250506040840135612fde81612e7b565b60008060006040848603121561348757600080fd5b83359250602084013567ffffffffffffffff808211156134a657600080fd5b818601915086601f8301126134ba57600080fd5b8135818111156134c957600080fd5b8760208260061b85010111156134de57600080fd5b6020830194508093505050509250925092565b60006020828403121561350357600080fd5b8151801515811461291e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261357757600080fd5b83018035915067ffffffffffffffff82111561359257600080fd5b6020019150368190038213156130ac57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613607576136076135a7565b5060010190565b60006020828403121561362057600080fd5b5051919050565b80516020808301519190811015613666577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b805163ffffffff81168114612ea857600080fd5b60008060008060008060c0878903121561369957600080fd5b865195506136a96020880161366c565b94506136b76040880161366c565b935060608701516136c781612f78565b60808801519093506136d881612f78565b91506131f160a0880161366c565b818103818111156106a6576106a66135a7565b80820281158282048414176106a6576106a66135a7565b808201808211156106a6576106a66135a7565b600081518084526020808501945080840160005b838110156137785781518051885283015177ffffffffffffffffffffffffffffffffffffffffffffffff168388015260409096019590820190600101613737565b509495945050505050565b6040815260006137966040830185613723565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b8381526040602080830182905282820184905260009190859060608501845b8781101561382e5783356137ed81612e7b565b73ffffffffffffffffffffffffffffffffffffffff16825267ffffffffffffffff6138198585016131fd565b168284015292840192908401906001016137da565b5098975050505050505050565b6000806080838503121561384e57600080fd5b83601f84011261385d57600080fd5b6040516060810167ffffffffffffffff828210818311171561388157613881612fe9565b81604052829150606086018781111561389957600080fd5b865b818110156138b357803584526020938401930161389b565b50929450913591808311156138c757600080fd5b50506138d58582860161338b565b9150509250929050565b60208152600061291e6020830184613723565b600082613928577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000825161393f818460208701612eca565b919091019291505056fea164736f6c6343000813000a", } var DestinationFeeManagerABI = DestinationFeeManagerMetaData.ABI @@ -320,6 +320,28 @@ func (_DestinationFeeManager *DestinationFeeManagerCallerSession) Owner() (commo return _DestinationFeeManager.Contract.Owner(&_DestinationFeeManager.CallOpts) } +func (_DestinationFeeManager *DestinationFeeManagerCaller) SGlobalDiscounts(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _DestinationFeeManager.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 (_DestinationFeeManager *DestinationFeeManagerSession) SGlobalDiscounts(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _DestinationFeeManager.Contract.SGlobalDiscounts(&_DestinationFeeManager.CallOpts, arg0, arg1) +} + +func (_DestinationFeeManager *DestinationFeeManagerCallerSession) SGlobalDiscounts(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _DestinationFeeManager.Contract.SGlobalDiscounts(&_DestinationFeeManager.CallOpts, arg0, arg1) +} + func (_DestinationFeeManager *DestinationFeeManagerCaller) SLinkDeficit(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { var out []interface{} err := _DestinationFeeManager.contract.Call(opts, &out, "s_linkDeficit", arg0) @@ -584,6 +606,18 @@ func (_DestinationFeeManager *DestinationFeeManagerTransactorSession) UpdateSubs return _DestinationFeeManager.Contract.UpdateSubscriberDiscount(&_DestinationFeeManager.TransactOpts, subscriber, feedId, token, discount) } +func (_DestinationFeeManager *DestinationFeeManagerTransactor) UpdateSubscriberGlobalDiscount(opts *bind.TransactOpts, subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) { + return _DestinationFeeManager.contract.Transact(opts, "updateSubscriberGlobalDiscount", subscriber, token, discount) +} + +func (_DestinationFeeManager *DestinationFeeManagerSession) UpdateSubscriberGlobalDiscount(subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) { + return _DestinationFeeManager.Contract.UpdateSubscriberGlobalDiscount(&_DestinationFeeManager.TransactOpts, subscriber, token, discount) +} + +func (_DestinationFeeManager *DestinationFeeManagerTransactorSession) UpdateSubscriberGlobalDiscount(subscriber common.Address, token common.Address, discount uint64) (*types.Transaction, error) { + return _DestinationFeeManager.Contract.UpdateSubscriberGlobalDiscount(&_DestinationFeeManager.TransactOpts, subscriber, token, discount) +} + func (_DestinationFeeManager *DestinationFeeManagerTransactor) Withdraw(opts *bind.TransactOpts, assetAddress common.Address, recipient common.Address, quantity *big.Int) (*types.Transaction, error) { return _DestinationFeeManager.contract.Transact(opts, "withdraw", assetAddress, recipient, quantity) } @@ -1700,6 +1734,8 @@ type DestinationFeeManagerInterface interface { 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) @@ -1734,6 +1770,8 @@ type DestinationFeeManagerInterface interface { 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) (*DestinationFeeManagerDiscountAppliedIterator, error) diff --git a/core/gethwrappers/llo-feeds/generated/destination_reward_manager/destination_reward_manager.go b/core/gethwrappers/llo-feeds/generated/destination_reward_manager/destination_reward_manager.go index 989482fc0ec..75ff7abe7ee 100644 --- a/core/gethwrappers/llo-feeds/generated/destination_reward_manager/destination_reward_manager.go +++ b/core/gethwrappers/llo-feeds/generated/destination_reward_manager/destination_reward_manager.go @@ -42,7 +42,7 @@ type IDestinationRewardManagerFeePayment struct { var DestinationRewardManagerMetaData = &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\":\"structIDestinationRewardManager.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\":\"address\",\"name\":\"newFeeManagerAddress\",\"type\":\"address\"}],\"name\":\"addFeeManager\",\"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\":\"structIDestinationRewardManager.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\":[{\"internalType\":\"address\",\"name\":\"feeManagerAddress\",\"type\":\"address\"}],\"name\":\"removeFeeManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"s_feeManagerAddressList\",\"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\":\"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: "0x60a06040523480156200001157600080fd5b506040516200244c3803806200244c8339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b60805161224a62000202600039600081816103bb0152818161107601526112b1015261224a6000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c806360122608116100cd5780639604d05f11610081578063cd5f729211610066578063cd5f7292146103a3578063ea4b861b146103b6578063f2fde38b146103dd57600080fd5b80639604d05f1461035a578063b0d9fa191461039057600080fd5b80638115c9cc116100b25780638115c9cc146102dd5780638ac85a5c146102f05780638da5cb5b1461031b57600080fd5b806360122608146102aa57806379ba5097146102d557600080fd5b806339ee81e1116101245780634944832f116101095780634944832f146102615780634d32208414610274578063592562011461028757600080fd5b806339ee81e114610213578063472264751461024157600080fd5b806314060f231161015557806314060f23146101ae578063181f5a77146101c15780631f2d32c31461020057600080fd5b806301ffc9a7146101715780630f3c34d114610199575b600080fd5b61018461017f366004611b3d565b6103f0565b60405190151581526020015b60405180910390f35b6101ac6101a7366004611bfd565b610651565b005b6101ac6101bc366004611cef565b61065f565b604080518082018252601381527f5265776172644d616e6167657220312e302e3000000000000000000000000000602082015290516101909190611d5f565b6101ac61020e366004611dd9565b610821565b610233610221366004611df4565b60026020526000908152604090205481565b604051908152602001610190565b61025461024f366004611e0d565b610959565b6040516101909190611e40565b6101ac61026f366004611cef565b610ae3565b6101ac610282366004611e84565b610c2c565b610184610295366004611df4565b60056020526000908152604090205460ff1681565b6102336102b8366004611f03565b600360209081526000928352604080842090915290825290205481565b6101ac610d6b565b6101ac6102eb366004611dd9565b610e6d565b6102336102fe366004611f03565b600460209081526000928352604080842090915290825290205481565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610190565b610335610368366004611dd9565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101ac61039e366004611f2f565b610f1f565b6102336103b1366004611df4565b6110df565b6103357f000000000000000000000000000000000000000000000000000000000000000081565b6101ac6103eb366004611dd9565b611100565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f0f3c34d100000000000000000000000000000000000000000000000000000000148061048357507fffffffff0000000000000000000000000000000000000000000000000000000082167f14060f2300000000000000000000000000000000000000000000000000000000145b806104cf57507fffffffff0000000000000000000000000000000000000000000000000000000082167f4944832f00000000000000000000000000000000000000000000000000000000145b8061051b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f4d32208400000000000000000000000000000000000000000000000000000000145b8061056757507fffffffff0000000000000000000000000000000000000000000000000000000082167f1f2d32c300000000000000000000000000000000000000000000000000000000145b806105b357507fffffffff0000000000000000000000000000000000000000000000000000000082167f8115c9cc00000000000000000000000000000000000000000000000000000000145b806105ff57507fffffffff0000000000000000000000000000000000000000000000000000000082167f4722647500000000000000000000000000000000000000000000000000000000145b8061064b57507fffffffff0000000000000000000000000000000000000000000000000000000082167fb0d9fa1900000000000000000000000000000000000000000000000000000000145b92915050565b61065b3382611114565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906106ab57503360008181526007602052604090205473ffffffffffffffffffffffffffffffffffffffff1614155b156106e2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081900361071d576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526005602052604090205460ff1615610766576040517f0afa7ee800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01849055600084815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690911790556107e2838383670de0b6b3a76400006112df565b827f8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe68383604051610814929190611f9b565b60405180910390a2505050565b6108296114b6565b73ffffffffffffffffffffffffffffffffffffffff8116610876576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81811660009081526007602052604090205416156108d5576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526007602090815260409182902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905590519182527fe45f5e140399b0a7e12971ab020724b828fbed8ac408c420884dc7d1bbe506b4910160405180910390a150565b600654606090600081841161096e5783610970565b815b9050808511156109ac576040517fa22caccc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109b88683612032565b67ffffffffffffffff8111156109d0576109d0611b7f565b6040519080825280602002602001820160405280156109f9578160200160208202803683370190505b5090506000865b83811015610ad657600060068281548110610a1d57610a1d612045565b600091825260208083209091015480835260048252604080842073ffffffffffffffffffffffffffffffffffffffff8f16855290925291205490915015610ac5576000818152600260209081526040808320546003835281842073ffffffffffffffffffffffffffffffffffffffff8f168552909252909120548114610ac35781858580600101965081518110610ab657610ab6612045565b6020026020010181815250505b505b50610acf81612074565b9050610a00565b5090979650505050505050565b610aeb6114b6565b604080516001808252818301909252600091602080830190803683370190505090508381600081518110610b2157610b21612045565b6020026020010181815250506000805b83811015610bde576000858583818110610b4d57610b4d612045565b610b639260206040909202019081019150611dd9565b600088815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902054909150610bc7878785818110610bab57610bab612045565b610bc19260206040909202019081019150611dd9565b86611114565b50929092019150610bd781612074565b9050610b31565b50610beb858585846112df565b847f8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe68585604051610c1d929190611f9b565b60405180910390a25050505050565b82610c4c60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610c9e57506000818152600460209081526040808320338452909152902054155b15610cd5576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252600091602080830190803683370190505090508481600081518110610d0b57610d0b612045565b60200260200101818152505060005b83811015610d6357610d52858583818110610d3757610d37612045565b9050602002016020810190610d4c9190611dd9565b83611114565b50610d5c81612074565b9050610d1a565b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610df1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e756114b6565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526007602052604090205416610ed3576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b3360008181526007602052604090205473ffffffffffffffffffffffffffffffffffffffff1614610f7c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b8381101561105b57848482818110610f9a57610f9a612045565b9050604002016020016020810190610fb291906120d4565b77ffffffffffffffffffffffffffffffffffffffffffffffff1660026000878785818110610fe257610fe2612045565b604090810292909201358352506020820192909252016000208054909101905584848281811061101457611014612045565b905060400201602001602081019061102c91906120d4565b77ffffffffffffffffffffffffffffffffffffffffffffffff16820191508061105490612074565b9050610f80565b5061109e73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016833084611539565b7fa1cc025ea76bacce5d740ee4bc331899375dc2c5f2ab33933aaacbd9ba001b668484846040516110d1939291906120ef565b60405180910390a150505050565b600681815481106110ef57600080fd5b600091825260209091200154905081565b6111086114b6565b6111118161161b565b50565b60008060005b835181101561129057600084828151811061113757611137612045565b6020026020010151905060006002600083815260200190815260200160002054905080600003611168575050611280565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16808552908352818420548685526004845282852091855292528220549083039190670de0b6b3a7640000908302049050806000036111d15750505050611280565b600084815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d16808552925290912084905588519682019689908790811061121c5761121c612045565b60200260200101517f989969655bc1d593922527fe85d71347bb8e12fa423cc71f362dd8ef7cb10ef283604051611273919077ffffffffffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a3505050505b61128981612074565b905061111a565b5080156112d8576112d873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168583611710565b9392505050565b61133a8383808060200260200160405190810160405280939291908181526020016000905b828210156113305761132160408302860136819003810190612176565b81526020019060010190611304565b505050505061176b565b15611371576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b8381101561147557600085858381811061139157611391612045565b90506040020160200160208101906113a991906121d1565b67ffffffffffffffff16905060008686848181106113c9576113c9612045565b6113df9260206040909202019081019150611dd9565b905073ffffffffffffffffffffffffffffffffffffffff811661142e576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600088815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff909416835292905220819055919091019061146e81612074565b9050611375565b508181146114af576040517f84677ce800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611537576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610de8565b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526116159085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611822565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361169a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610de8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526117669084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611593565b505050565b6000805b82518110156118195760006117858260016121ec565b90505b8351811015611810578381815181106117a3576117a3612045565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff168483815181106117d7576117d7612045565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1603611808575060019392505050565b600101611788565b5060010161176f565b50600092915050565b6000611884826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661192e9092919063ffffffff16565b80519091501561176657808060200190518101906118a291906121ff565b611766576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610de8565b606061193d8484600085611945565b949350505050565b6060824710156119d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610de8565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611a009190612221565b60006040518083038185875af1925050503d8060008114611a3d576040519150601f19603f3d011682016040523d82523d6000602084013e611a42565b606091505b5091509150611a5387838387611a5e565b979650505050505050565b60608315611af4578251600003611aed5773ffffffffffffffffffffffffffffffffffffffff85163b611aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610de8565b508161193d565b61193d8383815115611b095781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610de89190611d5f565b600060208284031215611b4f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146112d857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611bf557611bf5611b7f565b604052919050565b60006020808385031215611c1057600080fd5b823567ffffffffffffffff80821115611c2857600080fd5b818501915085601f830112611c3c57600080fd5b813581811115611c4e57611c4e611b7f565b8060051b9150611c5f848301611bae565b8181529183018401918481019088841115611c7957600080fd5b938501935b83851015611c9757843582529385019390850190611c7e565b98975050505050505050565b60008083601f840112611cb557600080fd5b50813567ffffffffffffffff811115611ccd57600080fd5b6020830191508360208260061b8501011115611ce857600080fd5b9250929050565b600080600060408486031215611d0457600080fd5b83359250602084013567ffffffffffffffff811115611d2257600080fd5b611d2e86828701611ca3565b9497909650939450505050565b60005b83811015611d56578181015183820152602001611d3e565b50506000910152565b6020815260008251806020840152611d7e816040850160208701611d3b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611dd457600080fd5b919050565b600060208284031215611deb57600080fd5b6112d882611db0565b600060208284031215611e0657600080fd5b5035919050565b600080600060608486031215611e2257600080fd5b611e2b84611db0565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015611e7857835183529284019291840191600101611e5c565b50909695505050505050565b600080600060408486031215611e9957600080fd5b83359250602084013567ffffffffffffffff80821115611eb857600080fd5b818601915086601f830112611ecc57600080fd5b813581811115611edb57600080fd5b8760208260051b8501011115611ef057600080fd5b6020830194508093505050509250925092565b60008060408385031215611f1657600080fd5b82359150611f2660208401611db0565b90509250929050565b600080600060408486031215611f4457600080fd5b833567ffffffffffffffff811115611f5b57600080fd5b611f6786828701611ca3565b9094509250611f7a905060208501611db0565b90509250925092565b803567ffffffffffffffff81168114611dd457600080fd5b6020808252818101839052600090604080840186845b87811015610ad65773ffffffffffffffffffffffffffffffffffffffff611fd783611db0565b16835267ffffffffffffffff611fee868401611f83565b16838601529183019190830190600101611fb1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561064b5761064b612003565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036120a5576120a5612003565b5060010190565b803577ffffffffffffffffffffffffffffffffffffffffffffffff81168114611dd457600080fd5b6000602082840312156120e657600080fd5b6112d8826120ac565b60408082528181018490526000908560608401835b8781101561214b5782358252602077ffffffffffffffffffffffffffffffffffffffffffffffff6121368286016120ac565b16908301529183019190830190600101612104565b5080935050505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b60006040828403121561218857600080fd5b6040516040810181811067ffffffffffffffff821117156121ab576121ab611b7f565b6040526121b783611db0565b81526121c560208401611f83565b60208201529392505050565b6000602082840312156121e357600080fd5b6112d882611f83565b8082018082111561064b5761064b612003565b60006020828403121561221157600080fd5b815180151581146112d857600080fd5b60008251612233818460208701611d3b565b919091019291505056fea164736f6c6343000813000a", + Bin: "0x60a06040523480156200001157600080fd5b5060405162002205380380620022058339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b60805161200362000202600039600081816103fd01528181610e26015261106101526120036000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c806360122608116100cd5780639604d05f11610081578063cd5f729211610066578063cd5f7292146103e5578063ea4b861b146103f8578063f2fde38b1461041f57600080fd5b80639604d05f1461039c578063b0d9fa19146103d257600080fd5b80638115c9cc116100b25780638115c9cc1461031f5780638ac85a5c146103325780638da5cb5b1461035d57600080fd5b806360122608146102ec57806379ba50971461031757600080fd5b806339ee81e1116101245780634944832f116101095780634944832f146102a35780634d322084146102b657806359256201146102c957600080fd5b806339ee81e114610255578063472264751461028357600080fd5b806314060f231161015557806314060f23146101f0578063181f5a77146102035780631f2d32c31461024257600080fd5b806301ffc9a7146101715780630f3c34d1146101db575b600080fd5b6101c661017f3660046118ef565b7fffffffff00000000000000000000000000000000000000000000000000000000167f768ffd3a000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6101ee6101e93660046119af565b610432565b005b6101ee6101fe366004611aa1565b610440565b604080518082018252601e81527f44657374696e6174696f6e5265776172644d616e6167657220302e342e300000602082015290516101d29190611b11565b6101ee610250366004611b8b565b610602565b610275610263366004611bad565b60026020526000908152604090205481565b6040519081526020016101d2565b610296610291366004611bc6565b61073a565b6040516101d29190611bf9565b6101ee6102b1366004611aa1565b6108c4565b6101ee6102c4366004611c3d565b610a0d565b6101c66102d7366004611bad565b60056020526000908152604090205460ff1681565b6102756102fa366004611cbc565b600360209081526000928352604080842090915290825290205481565b6101ee610b1b565b6101ee61032d366004611b8b565b610c1d565b610275610340366004611cbc565b600460209081526000928352604080842090915290825290205481565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6103776103aa366004611b8b565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101ee6103e0366004611ce8565b610ccf565b6102756103f3366004611bad565b610e8f565b6103777f000000000000000000000000000000000000000000000000000000000000000081565b6101ee61042d366004611b8b565b610eb0565b61043c3382610ec4565b5050565b3360008181526007602052604090205473ffffffffffffffffffffffffffffffffffffffff161480159061048c575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156104c3576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008190036104fe576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526005602052604090205460ff1615610547576040517f0afa7ee800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01849055600084815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690911790556105c3838383670de0b6b3a7640000611091565b827f8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe683836040516105f5929190611d54565b60405180910390a2505050565b61060a611268565b73ffffffffffffffffffffffffffffffffffffffff8116610657576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81811660009081526007602052604090205416156106b6576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526007602090815260409182902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905590519182527fe45f5e140399b0a7e12971ab020724b828fbed8ac408c420884dc7d1bbe506b4910160405180910390a150565b600654606090600081841161074f5783610751565b815b90508085111561078d576040517fa22caccc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107998683611deb565b67ffffffffffffffff8111156107b1576107b1611931565b6040519080825280602002602001820160405280156107da578160200160208202803683370190505b5090506000865b838110156108b7576000600682815481106107fe576107fe611dfe565b600091825260208083209091015480835260048252604080842073ffffffffffffffffffffffffffffffffffffffff8f168552909252912054909150156108a6576000818152600260209081526040808320546003835281842073ffffffffffffffffffffffffffffffffffffffff8f1685529092529091205481146108a4578185858060010196508151811061089757610897611dfe565b6020026020010181815250505b505b506108b081611e2d565b90506107e1565b5090979650505050505050565b6108cc611268565b60408051600180825281830190925260009160208083019080368337019050509050838160008151811061090257610902611dfe565b6020026020010181815250506000805b838110156109bf57600085858381811061092e5761092e611dfe565b6109449260206040909202019081019150611b8b565b600088815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff851684529091529020549091506109a887878581811061098c5761098c611dfe565b6109a29260206040909202019081019150611b8b565b86610ec4565b509290920191506109b881611e2d565b9050610912565b506109cc85858584611091565b847f8f668d6090683f98b3373a8b83d214da45737f7486cb7de554cc07b54e61cfe685856040516109fe929190611d54565b60405180910390a25050505050565b60008381526004602090815260408083203384529091529020548390158015610a4e575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15610a85576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252600091602080830190803683370190505090508481600081518110610abb57610abb611dfe565b60200260200101818152505060005b83811015610b1357610b02858583818110610ae757610ae7611dfe565b9050602002016020810190610afc9190611b8b565b83610ec4565b50610b0c81611e2d565b9050610aca565b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610c25611268565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526007602052604090205416610c83576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b3360008181526007602052604090205473ffffffffffffffffffffffffffffffffffffffff1614610d2c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b83811015610e0b57848482818110610d4a57610d4a611dfe565b9050604002016020016020810190610d629190611e8d565b77ffffffffffffffffffffffffffffffffffffffffffffffff1660026000878785818110610d9257610d92611dfe565b6040908102929092013583525060208201929092520160002080549091019055848482818110610dc457610dc4611dfe565b9050604002016020016020810190610ddc9190611e8d565b77ffffffffffffffffffffffffffffffffffffffffffffffff168201915080610e0490611e2d565b9050610d30565b50610e4e73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168330846112eb565b7fa1cc025ea76bacce5d740ee4bc331899375dc2c5f2ab33933aaacbd9ba001b66848484604051610e8193929190611ea8565b60405180910390a150505050565b60068181548110610e9f57600080fd5b600091825260209091200154905081565b610eb8611268565b610ec1816113cd565b50565b60008060005b8351811015611040576000848281518110610ee757610ee7611dfe565b6020026020010151905060006002600083815260200190815260200160002054905080600003610f18575050611030565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b16808552908352818420548685526004845282852091855292528220549083039190670de0b6b3a764000090830204905080600003610f815750505050611030565b600084815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8d168085529252909120849055885196820196899087908110610fcc57610fcc611dfe565b60200260200101517f989969655bc1d593922527fe85d71347bb8e12fa423cc71f362dd8ef7cb10ef283604051611023919077ffffffffffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a3505050505b61103981611e2d565b9050610eca565b5080156110885761108873ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001685836114c2565b90505b92915050565b6110ec8383808060200260200160405190810160405280939291908181526020016000905b828210156110e2576110d360408302860136819003810190611f2f565b815260200190600101906110b6565b505050505061151d565b15611123576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b8381101561122757600085858381811061114357611143611dfe565b905060400201602001602081019061115b9190611f8a565b67ffffffffffffffff169050600086868481811061117b5761117b611dfe565b6111919260206040909202019081019150611b8b565b905073ffffffffffffffffffffffffffffffffffffffff81166111e0576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600088815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff909416835292905220819055919091019061122081611e2d565b9050611127565b50818114611261576040517f84677ce800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b98565b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526113c79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526115d4565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361144c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b98565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526115189084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611345565b505050565b6000805b82518110156115cb576000611537826001611fa5565b90505b83518110156115c25783818151811061155557611555611dfe565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1684838151811061158957611589611dfe565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff16036115ba575060019392505050565b60010161153a565b50600101611521565b50600092915050565b6000611636826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166116e09092919063ffffffff16565b80519091501561151857808060200190518101906116549190611fb8565b611518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b98565b60606116ef84846000856116f7565b949350505050565b606082471015611789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610b98565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516117b29190611fda565b60006040518083038185875af1925050503d80600081146117ef576040519150601f19603f3d011682016040523d82523d6000602084013e6117f4565b606091505b509150915061180587838387611810565b979650505050505050565b606083156118a657825160000361189f5773ffffffffffffffffffffffffffffffffffffffff85163b61189f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b98565b50816116ef565b6116ef83838151156118bb5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b989190611b11565b60006020828403121561190157600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461108857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156119a7576119a7611931565b604052919050565b600060208083850312156119c257600080fd5b823567ffffffffffffffff808211156119da57600080fd5b818501915085601f8301126119ee57600080fd5b813581811115611a0057611a00611931565b8060051b9150611a11848301611960565b8181529183018401918481019088841115611a2b57600080fd5b938501935b83851015611a4957843582529385019390850190611a30565b98975050505050505050565b60008083601f840112611a6757600080fd5b50813567ffffffffffffffff811115611a7f57600080fd5b6020830191508360208260061b8501011115611a9a57600080fd5b9250929050565b600080600060408486031215611ab657600080fd5b83359250602084013567ffffffffffffffff811115611ad457600080fd5b611ae086828701611a55565b9497909650939450505050565b60005b83811015611b08578181015183820152602001611af0565b50506000910152565b6020815260008251806020840152611b30816040850160208701611aed565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611b8657600080fd5b919050565b600060208284031215611b9d57600080fd5b611ba682611b62565b9392505050565b600060208284031215611bbf57600080fd5b5035919050565b600080600060608486031215611bdb57600080fd5b611be484611b62565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015611c3157835183529284019291840191600101611c15565b50909695505050505050565b600080600060408486031215611c5257600080fd5b83359250602084013567ffffffffffffffff80821115611c7157600080fd5b818601915086601f830112611c8557600080fd5b813581811115611c9457600080fd5b8760208260051b8501011115611ca957600080fd5b6020830194508093505050509250925092565b60008060408385031215611ccf57600080fd5b82359150611cdf60208401611b62565b90509250929050565b600080600060408486031215611cfd57600080fd5b833567ffffffffffffffff811115611d1457600080fd5b611d2086828701611a55565b9094509250611d33905060208501611b62565b90509250925092565b803567ffffffffffffffff81168114611b8657600080fd5b6020808252818101839052600090604080840186845b878110156108b75773ffffffffffffffffffffffffffffffffffffffff611d9083611b62565b16835267ffffffffffffffff611da7868401611d3c565b16838601529183019190830190600101611d6a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561108b5761108b611dbc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611e5e57611e5e611dbc565b5060010190565b803577ffffffffffffffffffffffffffffffffffffffffffffffff81168114611b8657600080fd5b600060208284031215611e9f57600080fd5b611ba682611e65565b60408082528181018490526000908560608401835b87811015611f045782358252602077ffffffffffffffffffffffffffffffffffffffffffffffff611eef828601611e65565b16908301529183019190830190600101611ebd565b5080935050505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b600060408284031215611f4157600080fd5b6040516040810181811067ffffffffffffffff82111715611f6457611f64611931565b604052611f7083611b62565b8152611f7e60208401611d3c565b60208201529392505050565b600060208284031215611f9c57600080fd5b611ba682611d3c565b8082018082111561108b5761108b611dbc565b600060208284031215611fca57600080fd5b8151801515811461108857600080fd5b60008251611fec818460208701611aed565b919091019291505056fea164736f6c6343000813000a", } var DestinationRewardManagerABI = DestinationRewardManagerMetaData.ABI diff --git a/core/gethwrappers/llo-feeds/generated/destination_verifier/destination_verifier.go b/core/gethwrappers/llo-feeds/generated/destination_verifier/destination_verifier.go index 2fa48b7249c..41ae715fe95 100644 --- a/core/gethwrappers/llo-feeds/generated/destination_verifier/destination_verifier.go +++ b/core/gethwrappers/llo-feeds/generated/destination_verifier/destination_verifier.go @@ -36,8 +36,8 @@ type CommonAddressAndWeight struct { } var DestinationVerifierMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifierProxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadActivationTime\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadVerification\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"}],\"name\":\"DonConfigAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DonConfigDoesNotExist\",\"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\":[],\"name\":\"FeeManagerInvalid\",\"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\":\"NoSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VerifierProxyInvalid\",\"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\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"}],\"name\":\"ConfigActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"}],\"name\":\"ConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"recipientAddressesAndWeights\",\"type\":\"tuple[]\"}],\"name\":\"ConfigSet\",\"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\":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\":[],\"name\":\"i_verifierProxy\",\"outputs\":[{\"internalType\":\"contractIDestinationVerifierProxy\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"removeLatestConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_accessController\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessController\",\"type\":\"address\"}],\"name\":\"setAccessController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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\":\"uint256\",\"name\":\"donConfigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"}],\"name\":\"setConfigActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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[]\"},{\"internalType\":\"uint32\",\"name\":\"activationTime\",\"type\":\"uint32\"}],\"name\":\"setConfigWithActivationTime\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"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\":\"bytes\",\"name\":\"signedReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"signedReports\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"verifyBulk\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200379d3803806200379d8339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b60805161359b62000202600039600081816102d70152818161062a0152611064015261359b6000f3fe6080604052600436106100f35760003560e01c80638da5cb5b1161008a578063d7c72e4e11610059578063d7c72e4e146102f9578063f08391d814610319578063f2fde38b14610339578063f9c7bf771461035957600080fd5b80638da5cb5b1461025857806394ba284614610283578063af4fed24146102b0578063b97455c7146102c557600080fd5b8063453ec61b116100c6578063453ec61b146101e1578063472d35b9146102035780635ad72fae1461022357806379ba50971461024357600080fd5b806301ffc9a7146100f8578063181f5a771461012d578063294d2bb11461017c57806338416b5b1461018f575b600080fd5b34801561010457600080fd5b50610118610113366004612622565b610379565b60405190151581526020015b60405180910390f35b34801561013957600080fd5b5060408051808201909152601981527f44657374696e6174696f6e566572696669657220312e302e300000000000000060208201525b60405161012491906126cf565b61016f61018a366004612754565b610626565b34801561019b57600080fd5b506004546101bc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b3480156101ed57600080fd5b506102016101fc3660046129e3565b610873565b005b34801561020f57600080fd5b5061020161021e366004612a57565b61097b565b34801561022f57600080fd5b5061020161023e366004612a80565b610c5c565b34801561024f57600080fd5b50610201610d72565b34801561026457600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101bc565b34801561028f57600080fd5b506005546101bc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102bc57600080fd5b50610201610e6f565b3480156102d157600080fd5b506101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61030c610307366004612ab0565b611060565b6040516101249190612b33565b34801561032557600080fd5b50610201610334366004612a57565b611352565b34801561034557600080fd5b50610201610354366004612a57565b6113d9565b34801561036557600080fd5b50610201610374366004612bc5565b6113ed565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f294d2bb100000000000000000000000000000000000000000000000000000000148061040c57507fffffffff0000000000000000000000000000000000000000000000000000000082167fd7c72e4e00000000000000000000000000000000000000000000000000000000145b8061045857507fffffffff0000000000000000000000000000000000000000000000000000000082167f94ba284600000000000000000000000000000000000000000000000000000000145b806104a457507fffffffff0000000000000000000000000000000000000000000000000000000082167f38416b5b00000000000000000000000000000000000000000000000000000000145b806104f057507fffffffff0000000000000000000000000000000000000000000000000000000082167f453ec61b00000000000000000000000000000000000000000000000000000000145b8061053c57507fffffffff0000000000000000000000000000000000000000000000000000000082167ff9c7bf7700000000000000000000000000000000000000000000000000000000145b8061058857507fffffffff0000000000000000000000000000000000000000000000000000000082167f472d35b900000000000000000000000000000000000000000000000000000000145b806105d457507fffffffff0000000000000000000000000000000000000000000000000000000082167ff08391d800000000000000000000000000000000000000000000000000000000145b8061062057507fffffffff0000000000000000000000000000000000000000000000000000000082167f5ad72fae00000000000000000000000000000000000000000000000000000000145b92915050565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610697576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554829073ffffffffffffffffffffffffffffffffffffffff16801580159061075657506040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636b14daf8906107139085906000903690600401612c95565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612cce565b155b1561078d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008061079b8a8a886114ab565b600454919350915073ffffffffffffffffffffffffffffffffffffffff168015610864578073ffffffffffffffffffffffffffffffffffffffff166386968cfd34848e8e8e8e8e6040518863ffffffff1660e01b815260040161080396959493929190612ceb565b6000604051808303818588803b15801561081c57600080fd5b505af19350505050801561082e575060015b610864576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50909998505050505050505050565b82518260ff16806000036108b3576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156108fd576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b610908816003612d71565b8211610960578161091a826003612d71565b610925906001612d88565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016108f4565b6109686119b0565b61097485858542611a33565b5050505050565b6109836119b0565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f86968cfd00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610a0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a319190612cce565b1580610ae857506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f3690750900000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae69190612cce565b155b80610b9e57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527ff65df96200000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610b78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9c9190612cce565b155b15610bd5576040517f8238941900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f04628abcaa6b1674651352125cb94b65b289145bc2bc4d67720bb7d966372f0391015b60405180910390a15050565b610c646119b0565b6003548210610c9f576040517f5a0d6fe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060038381548110610cb457610cb4612d9b565b600091825260209182902001805484151579010000000000000000000000000000000000000000000000000081027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091178083556040805191811b7fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000168252938101919091529092507f90186a1e77b498ec417ea88bd026cae00d7043c357cc45221777623bda582dd4910160405180910390a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610df3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f4565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e776119b0565b600354600003610eb3576040517f5a0d6fe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003805460009190610ec790600190612dca565b81548110610ed757610ed7612d9b565b600091825260209182902060408051608081018252929091015480821b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001683527801000000000000000000000000000000000000000000000000810460ff9081169484019490945279010000000000000000000000000000000000000000000000000081049093161515908201527a01000000000000000000000000000000000000000000000000000090910463ffffffff166060820152600380549192509080610fa557610fa5612ddd565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffff00000000000000000000000000000000000000000000000000000000000016905501905580516040517f970fd8f3ebdd9a271080aacf9807a5c709be0b448e4047a6fc212b8cc165368d91611055917fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000091909116815260200190565b60405180910390a150565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146110d1576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554829073ffffffffffffffffffffffffffffffffffffffff16801580159061119057506040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636b14daf89061114d9085906000903690600401612c95565b602060405180830381865afa15801561116a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118e9190612cce565b155b156111c7576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008767ffffffffffffffff8111156111e2576111e26127d5565b60405190808252806020026020018201604052801561121557816020015b60608152602001906001900390816112005790505b50905060008867ffffffffffffffff811115611233576112336127d5565b60405190808252806020026020018201604052801561125c578160200160208202803683370190505b50905060005b898110156112ee5760008061129a8d8d8581811061128257611282612d9b565b90506020028101906112949190612e0c565b8b6114ab565b91509150818584815181106112b1576112b1612d9b565b6020026020010181905250808484815181106112cf576112cf612d9b565b6020026020010181815250505050806112e790612e71565b9050611262565b5060045473ffffffffffffffffffffffffffffffffffffffff168015610864578073ffffffffffffffffffffffffffffffffffffffff16633690750934848e8e8e8e8e6040518863ffffffff1660e01b815260040161080396959493929190612ea9565b61135a6119b0565b6005805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f953e92b1a6442e9c3242531154a3f6f6eb00b4e9c719ba8118fa6235e4ce89b69101610c50565b6113e16119b0565b6113ea816120eb565b50565b83518360ff168060000361142d576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115611472576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044016108f4565b61147d816003612d71565b821161148f578161091a826003612d71565b6114976119b0565b6114a386868686611a33565b505050505050565b6060600080808080806114c0898b018b6130db565b94509450945094509450815183511461151257825182516040517ff0d31408000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016108f4565b825160000361154d576040517fc7af40f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008480519060200120866040516020016115699291906131b6565b6040516020818303038152906040528051906020012090506000845167ffffffffffffffff81111561159d5761159d6127d5565b6040519080825280602002602001820160405280156115c6578160200160208202803683370190505b50905060005b85518110156116d4576001838583602081106115ea576115ea612d9b565b6115f791901a601b6131f2565b88848151811061160957611609612d9b565b602002602001015188858151811061162357611623612d9b565b602002602001015160405160008152602001604052604051611661949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611683573d6000803e3d6000fd5b5050506020604051035182828151811061169f5761169f612d9b565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526116cd81612e71565b90506115cc565b506116de816121e0565b15611715576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006117208761228f565b9050600061172d826122b5565b80519091507fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001661178a576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001516117c5576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015160ff16835111611806576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b84518110156119245784818151811061182557611825612d9b565b6020026020010151836000015160405160200161189592919060609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001682527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166014820152602c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600290935291205490925060ff16611914576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61191d81612e71565b905061180a565b5061192e8961320b565b60405173ffffffffffffffffffffffffffffffffffffffff8f1681527f58ca9502e98a536e06e72d680fcc251e5d10b72291a281665a2c2dc0ac30fcc59060200160405180910390a25051969d7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009097169c50959a5050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f4565b565b83518360ff1680600003611a73576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115611ab8576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044016108f4565b611ac3816003612d71565b8211611ad5578161091a826003612d71565b611add6119b0565b611ae6866121e0565b15611b1d576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428363ffffffff161115611b5d576040517f0114c7e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7686600060018951611b719190612dca565b61243a565b60008686604051602001611b8b929190613250565b60405160208183030381529060405280519060200120905060005b8751811015611d3257600073ffffffffffffffffffffffffffffffffffffffff16888281518110611bd957611bd9612d9b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611c2e576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600260008a8481518110611c4657611c46612d9b565b602002602001015185604051602001611cb292919060609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001682527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166014820152602c0190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301208352908201929092520160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611d2b81612e71565b9050611ba6565b506003548015801590611d96575063ffffffff85166003611d54600184612dca565b81548110611d6457611d64612d9b565b6000918252602090912001547a010000000000000000000000000000000000000000000000000000900463ffffffff16115b15611dcd576040517f0114c7e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081118015611e4b57507fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000082166003611e08600184612dca565b81548110611e1857611e18612d9b565b60009182526020909120015460401b7fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016145b15611ea6576040517fc0178c860000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000831660048201526024016108f4565b855115611f3757600480546040517ff65df96200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169163f65df96291611f049186918b910161332e565b600060405180830381600087803b158015611f1e57600080fd5b505af1158015611f32573d6000803e3d6000fd5b505050505b604080516080810182527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000841680825260ff808b1660208401908152600184860181815263ffffffff808d166060880190815260038054948501815560005296517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b90930180549451925197519091167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff97151579010000000000000000000000000000000000000000000000000002979097167fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff929095167801000000000000000000000000000000000000000000000000027fffffffffffffff0000000000000000000000000000000000000000000000000090941692881c929092179290921791909116919091179290921790915590517f2d763a674a99583454a287d792819ffb9ff7e791c23e7745a082701136ce336c906120d9908b908b908b90613371565b60405180910390a25050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361216a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000805b82518110156122865760006121fa826001612d88565b90505b835181101561227d5783818151811061221857612218612d9b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1684838151811061224857612248612d9b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603612275575060019392505050565b6001016121fd565b506001016121e4565b50600092915050565b600080828060200190518101906122a691906133dd565b63ffffffff1695945050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526003545b80156124335761231081613420565b9050836003828154811061232657612326612d9b565b6000918252602090912001547a010000000000000000000000000000000000000000000000000000900463ffffffff161161242e576003818154811061236e5761236e612d9b565b600091825260209182902060408051608081018252929091015480821b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001683527801000000000000000000000000000000000000000000000000810460ff9081169484019490945279010000000000000000000000000000000000000000000000000081049093161515908201527a01000000000000000000000000000000000000000000000000000090910463ffffffff1660608201529150612433565b612301565b5092915050565b818180820361244a575050505050565b60008560026124598787613455565b6124639190613475565b61246d9087613504565b8151811061247d5761247d612d9b565b602002602001015190505b8183136125fc575b8073ffffffffffffffffffffffffffffffffffffffff168684815181106124b9576124b9612d9b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1610156124ef57826124e78161352c565b935050612490565b85828151811061250157612501612d9b565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16101561254e57816125468161355d565b9250506124ef565b8183136125f75785828151811061256757612567612d9b565b602002602001015186848151811061258157612581612d9b565b602002602001015187858151811061259b5761259b612d9b565b602002602001018885815181106125b4576125b4612d9b565b73ffffffffffffffffffffffffffffffffffffffff938416602091820292909201015291169052826125e58161352c565b93505081806125f39061355d565b9250505b612488565b8185121561260f5761260f86868461243a565b838312156114a3576114a386848661243a565b60006020828403121561263457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461266457600080fd5b9392505050565b6000815180845260005b8181101561269157602081850181015186830182015201612675565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612664602083018461266b565b60008083601f8401126126f457600080fd5b50813567ffffffffffffffff81111561270c57600080fd5b60208301915083602082850101111561272457600080fd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461274f57600080fd5b919050565b60008060008060006060868803121561276c57600080fd5b853567ffffffffffffffff8082111561278457600080fd5b61279089838a016126e2565b909750955060208801359150808211156127a957600080fd5b506127b6888289016126e2565b90945092506127c990506040870161272b565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612827576128276127d5565b60405290565b6040516060810167ffffffffffffffff81118282101715612827576128276127d5565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612897576128976127d5565b604052919050565b600067ffffffffffffffff8211156128b9576128b96127d5565b5060051b60200190565b600082601f8301126128d457600080fd5b813560206128e96128e48361289f565b612850565b82815260059290921b8401810191818101908684111561290857600080fd5b8286015b8481101561292a5761291d8161272b565b835291830191830161290c565b509695505050505050565b803560ff8116811461274f57600080fd5b600082601f83011261295757600080fd5b813560206129676128e48361289f565b82815260069290921b8401810191818101908684111561298657600080fd5b8286015b8481101561292a57604081890312156129a35760008081fd5b6129ab612804565b6129b48261272b565b81528482013567ffffffffffffffff811681146129d15760008081fd5b8186015283529183019160400161298a565b6000806000606084860312156129f857600080fd5b833567ffffffffffffffff80821115612a1057600080fd5b612a1c878388016128c3565b9450612a2a60208701612935565b93506040860135915080821115612a4057600080fd5b50612a4d86828701612946565b9150509250925092565b600060208284031215612a6957600080fd5b6126648261272b565b80151581146113ea57600080fd5b60008060408385031215612a9357600080fd5b823591506020830135612aa581612a72565b809150509250929050565b600080600080600060608688031215612ac857600080fd5b853567ffffffffffffffff80821115612ae057600080fd5b818801915088601f830112612af457600080fd5b813581811115612b0357600080fd5b8960208260051b8501011115612b1857600080fd5b6020928301975095509087013590808211156127a957600080fd5b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015612ba6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612b9485835161266b565b94509285019290850190600101612b5a565b5092979650505050505050565b63ffffffff811681146113ea57600080fd5b60008060008060808587031215612bdb57600080fd5b843567ffffffffffffffff80821115612bf357600080fd5b612bff888389016128c3565b9550612c0d60208801612935565b94506040870135915080821115612c2357600080fd5b50612c3087828801612946565b9250506060850135612c4181612bb3565b939692955090935050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff84168152604060208201526000612cc5604083018486612c4c565b95945050505050565b600060208284031215612ce057600080fd5b815161266481612a72565b868152608060208201526000612d05608083018789612c4c565b8281036040840152612d18818688612c4c565b91505073ffffffffffffffffffffffffffffffffffffffff83166060830152979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761062057610620612d42565b8082018082111561062057610620612d42565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8181038181111561062057610620612d42565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612e4157600080fd5b83018035915067ffffffffffffffff821115612e5c57600080fd5b60200191503681900382131561272457600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612ea257612ea2612d42565b5060010190565b6080808252875190820181905260009060209060a0840190828b01845b82811015612ee257815184529284019290840190600101612ec6565b50505083810382850152878152818101600589901b820183018a60005b8b811015612faa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301845281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18e3603018112612f6057600080fd5b8d01868101903567ffffffffffffffff811115612f7c57600080fd5b803603821315612f8b57600080fd5b612f96858284612c4c565b958801959450505090850190600101612eff565b50508581036040870152612fbf81898b612c4c565b945050505050612fe7606083018473ffffffffffffffffffffffffffffffffffffffff169052565b979650505050505050565b600082601f83011261300357600080fd5b813567ffffffffffffffff81111561301d5761301d6127d5565b61304e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612850565b81815284602083860101111561306357600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261309157600080fd5b813560206130a16128e48361289f565b82815260059290921b840181019181810190868411156130c057600080fd5b8286015b8481101561292a57803583529183019183016130c4565b600080600080600060e086880312156130f357600080fd5b86601f87011261310257600080fd5b61310a61282d565b80606088018981111561311c57600080fd5b885b8181101561313657803584526020938401930161311e565b5090965035905067ffffffffffffffff8082111561315357600080fd5b61315f89838a01612ff2565b9550608088013591508082111561317557600080fd5b61318189838a01613080565b945060a088013591508082111561319757600080fd5b506131a488828901613080565b9598949750929560c001359392505050565b828152600060208083018460005b60038110156131e1578151835291830191908301906001016131c4565b505050506080820190509392505050565b60ff818116838216019081111561062057610620612d42565b8051602080830151919081101561324a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b825160009082906020808701845b8381101561329057815173ffffffffffffffffffffffffffffffffffffffff168552938201939082019060010161325e565b5050505060f89390931b7fff000000000000000000000000000000000000000000000000000000000000001683525050600101919050565b600081518084526020808501945080840160005b83811015613323578151805173ffffffffffffffffffffffffffffffffffffffff16885283015167ffffffffffffffff1683880152604090960195908201906001016132dc565b509495945050505050565b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316815260406020820152600061336960408301846132c8565b949350505050565b606080825284519082018190526000906020906080840190828801845b828110156133c057815173ffffffffffffffffffffffffffffffffffffffff168452928401929084019060010161338e565b50505060ff8616828501528381036040850152612fe781866132c8565b6000806000606084860312156133f257600080fd5b83519250602084015161340481612bb3565b604085015190925061341581612bb3565b809150509250925092565b60008161342f5761342f612d42565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b818103600083128015838313168383128216171561243357612433612d42565b6000826134ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156134ff576134ff612d42565b500590565b808201828112600083128015821682158216171561352457613524612d42565b505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612ea257612ea2612d42565b60007f8000000000000000000000000000000000000000000000000000000000000000820361342f5761342f612d4256fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifierProxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadActivationTime\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BadVerification\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"}],\"name\":\"DonConfigAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DonConfigDoesNotExist\",\"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\":[],\"name\":\"FeeManagerInvalid\",\"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\":\"NoSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"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\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"}],\"name\":\"ConfigActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"}],\"name\":\"ConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes24\",\"name\":\"donConfigId\",\"type\":\"bytes24\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"weight\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structCommon.AddressAndWeight[]\",\"name\":\"recipientAddressesAndWeights\",\"type\":\"tuple[]\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"donConfigIndex\",\"type\":\"uint16\"}],\"name\":\"ConfigSet\",\"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\":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\":[],\"name\":\"i_verifierProxy\",\"outputs\":[{\"internalType\":\"contractIDestinationVerifierProxy\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"removeLatestConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_accessController\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessController\",\"type\":\"address\"}],\"name\":\"setAccessController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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\":\"uint256\",\"name\":\"donConfigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"}],\"name\":\"setConfigActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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[]\"},{\"internalType\":\"uint32\",\"name\":\"activationTime\",\"type\":\"uint32\"}],\"name\":\"setConfigWithActivationTime\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"feeManager\",\"type\":\"address\"}],\"name\":\"setFeeManager\",\"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\":\"bytes\",\"name\":\"signedReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"verify\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"signedReports\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"parameterPayload\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"verifyBulk\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620033d8380380620033d88339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e95760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b6080516131d662000202600039600081816102d7015281816104160152610ce201526131d66000f3fe6080604052600436106100f35760003560e01c80638da5cb5b1161008a578063d7c72e4e11610059578063d7c72e4e146102f9578063f08391d814610319578063f2fde38b14610339578063f9c7bf771461035957600080fd5b80638da5cb5b1461025857806394ba284614610283578063af4fed24146102b0578063b97455c7146102c557600080fd5b8063453ec61b116100c6578063453ec61b146101e1578063472d35b9146102035780635ad72fae1461022357806379ba50971461024357600080fd5b806301ffc9a7146100f8578063181f5a771461012d578063294d2bb11461017c57806338416b5b1461018f575b600080fd5b34801561010457600080fd5b50610118610113366004612246565b610379565b60405190151581526020015b60405180910390f35b34801561013957600080fd5b5060408051808201909152601981527f44657374696e6174696f6e566572696669657220302e342e300000000000000060208201525b60405161012491906122f3565b61016f61018a366004612378565b610412565b34801561019b57600080fd5b506004546101bc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b3480156101ed57600080fd5b506102016101fc366004612607565b61065f565b005b34801561020f57600080fd5b5061020161021e36600461267b565b610767565b34801561022f57600080fd5b5061020161023e3660046126a4565b6108da565b34801561024f57600080fd5b506102016109f0565b34801561026457600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101bc565b34801561028f57600080fd5b506005546101bc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102bc57600080fd5b50610201610aed565b3480156102d157600080fd5b506101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61030c6103073660046126d4565b610cde565b6040516101249190612757565b34801561032557600080fd5b5061020161033436600461267b565b610fd0565b34801561034557600080fd5b5061020161035436600461267b565b611057565b34801561036557600080fd5b506102016103743660046127e9565b61106b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167ffecf1f8700000000000000000000000000000000000000000000000000000000148061040c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f527146e200000000000000000000000000000000000000000000000000000000145b92915050565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610483576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554829073ffffffffffffffffffffffffffffffffffffffff16801580159061054257506040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636b14daf8906104ff90859060009036906004016128b9565b602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054091906128f2565b155b15610579576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806105878a8a88611129565b600454919350915073ffffffffffffffffffffffffffffffffffffffff168015610650578073ffffffffffffffffffffffffffffffffffffffff166386968cfd34848e8e8e8e8e6040518863ffffffff1660e01b81526004016105ef9695949392919061290f565b6000604051808303818588803b15801561060857600080fd5b505af19350505050801561061a575060015b610650576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50909998505050505050505050565b82518260ff168060000361069f576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156106e9576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b6106f4816003612995565b821161074c5781610706826003612995565b6107119060016129ac565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016106e0565b61075461162e565b610760858585426116b1565b5050505050565b61076f61162e565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f465b009600000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156107f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081d91906128f2565b610853576040517f8238941900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f04628abcaa6b1674651352125cb94b65b289145bc2bc4d67720bb7d966372f0391015b60405180910390a15050565b6108e261162e565b600354821061091d576040517f5a0d6fe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060038381548110610932576109326129bf565b600091825260209182902001805484151579010000000000000000000000000000000000000000000000000081027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091178083556040805191811b7fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000168252938101919091529092507f90186a1e77b498ec417ea88bd026cae00d7043c357cc45221777623bda582dd4910160405180910390a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106e0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610af561162e565b600354600003610b31576040517f5a0d6fe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003805460009190610b45906001906129ee565b81548110610b5557610b556129bf565b600091825260209182902060408051608081018252929091015480821b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001683527801000000000000000000000000000000000000000000000000810460ff9081169484019490945279010000000000000000000000000000000000000000000000000081049093161515908201527a01000000000000000000000000000000000000000000000000000090910463ffffffff166060820152600380549192509080610c2357610c23612a01565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffff00000000000000000000000000000000000000000000000000000000000016905501905580516040517f970fd8f3ebdd9a271080aacf9807a5c709be0b448e4047a6fc212b8cc165368d91610cd3917fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000091909116815260200190565b60405180910390a150565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610d4f576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554829073ffffffffffffffffffffffffffffffffffffffff168015801590610e0e57506040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636b14daf890610dcb90859060009036906004016128b9565b602060405180830381865afa158015610de8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0c91906128f2565b155b15610e45576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008767ffffffffffffffff811115610e6057610e606123f9565b604051908082528060200260200182016040528015610e9357816020015b6060815260200190600190039081610e7e5790505b50905060008867ffffffffffffffff811115610eb157610eb16123f9565b604051908082528060200260200182016040528015610eda578160200160208202803683370190505b50905060005b89811015610f6c57600080610f188d8d85818110610f0057610f006129bf565b9050602002810190610f129190612a30565b8b611129565b9150915081858481518110610f2f57610f2f6129bf565b602002602001018190525080848481518110610f4d57610f4d6129bf565b602002602001018181525050505080610f6590612a95565b9050610ee0565b5060045473ffffffffffffffffffffffffffffffffffffffff168015610650578073ffffffffffffffffffffffffffffffffffffffff16633690750934848e8e8e8e8e6040518863ffffffff1660e01b81526004016105ef96959493929190612acd565b610fd861162e565b6005805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f953e92b1a6442e9c3242531154a3f6f6eb00b4e9c719ba8118fa6235e4ce89b691016108ce565b61105f61162e565b61106881611d0f565b50565b83518360ff16806000036110ab576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156110f0576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044016106e0565b6110fb816003612995565b821161110d5781610706826003612995565b61111561162e565b611121868686866116b1565b505050505050565b60606000808080808061113e898b018b612cff565b94509450945094509450815183511461119057825182516040517ff0d31408000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016106e0565b82516000036111cb576040517fc7af40f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008480519060200120866040516020016111e7929190612dda565b6040516020818303038152906040528051906020012090506000845167ffffffffffffffff81111561121b5761121b6123f9565b604051908082528060200260200182016040528015611244578160200160208202803683370190505b50905060005b855181101561135257600183858360208110611268576112686129bf565b61127591901a601b612e16565b888481518110611287576112876129bf565b60200260200101518885815181106112a1576112a16129bf565b6020026020010151604051600081526020016040526040516112df949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611301573d6000803e3d6000fd5b5050506020604051035182828151811061131d5761131d6129bf565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015261134b81612a95565b905061124a565b5061135c81611e04565b15611393576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061139e87611eb3565b905060006113ab82611ed9565b80519091507fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016611408576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060400151611443576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015160ff16835111611484576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b84518110156115a2578481815181106114a3576114a36129bf565b6020026020010151836000015160405160200161151392919060609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001682527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166014820152602c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600290935291205490925060ff16611592576040517f4df18f0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61159b81612a95565b9050611488565b506115ac89612e2f565b60405173ffffffffffffffffffffffffffffffffffffffff8f1681527f58ca9502e98a536e06e72d680fcc251e5d10b72291a281665a2c2dc0ac30fcc59060200160405180910390a25051969d7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009097169c50959a5050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106e0565b565b6116ba84611e04565b156116f1576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428163ffffffff161115611731576040517f0114c7e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61174a8460006001875161174591906129ee565b61205e565b6000848460405160200161175f929190612e74565b60405160208183030381529060405280519060200120905060005b855181101561190657600073ffffffffffffffffffffffffffffffffffffffff168682815181106117ad576117ad6129bf565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611802576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016002600088848151811061181a5761181a6129bf565b60200260200101518560405160200161188692919060609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001682527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166014820152602c0190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301208352908201929092520160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556118ff81612a95565b905061177a565b50600354801580159061196b575063ffffffff831660036119286001846129ee565b81548110611938576119386129bf565b6000918252602090912001547a010000000000000000000000000000000000000000000000000000900463ffffffff1610155b156119a2576040517f0114c7e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081118015611a2057507fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000821660036119dd6001846129ee565b815481106119ed576119ed6129bf565b60009182526020909120015460401b7fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016145b15611a7b576040517fc0178c860000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000831660048201526024016106e0565b835115611b5b5760045473ffffffffffffffffffffffffffffffffffffffff16611ad1576040517f8238941900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517ff65df96200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169163f65df96291611b28918691899101612f52565b600060405180830381600087803b158015611b4257600080fd5b505af1158015611b56573d6000803e3d6000fd5b505050505b604080516080810182527fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000841680825260ff80891660208401908152600184860181815263ffffffff808b166060880190815260038054948501815560005296517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b90930180549451925197519091167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff97151579010000000000000000000000000000000000000000000000000002979097167fffff0000000000ffffffffffffffffffffffffffffffffffffffffffffffffff929095167801000000000000000000000000000000000000000000000000027fffffffffffffff0000000000000000000000000000000000000000000000000090941692881c929092179290921791909116919091179290921790915590517fa7d03f81dd1c1d8a55355fd71e1221d5959b7d9fb171fbb6389f207f63598fa590611cff908990899089908790612f95565b60405180910390a2505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106e0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000805b8251811015611eaa576000611e1e8260016129ac565b90505b8351811015611ea157838181518110611e3c57611e3c6129bf565b602002602001015173ffffffffffffffffffffffffffffffffffffffff16848381518110611e6c57611e6c6129bf565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611e99575060019392505050565b600101611e21565b50600101611e08565b50600092915050565b60008082806020019051810190611eca9190613018565b63ffffffff1695945050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526003545b801561205757611f348161305b565b90508360038281548110611f4a57611f4a6129bf565b6000918252602090912001547a010000000000000000000000000000000000000000000000000000900463ffffffff16116120525760038181548110611f9257611f926129bf565b600091825260209182902060408051608081018252929091015480821b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001683527801000000000000000000000000000000000000000000000000810460ff9081169484019490945279010000000000000000000000000000000000000000000000000081049093161515908201527a01000000000000000000000000000000000000000000000000000090910463ffffffff1660608201529150612057565b611f25565b5092915050565b818180820361206e575050505050565b600085600261207d8787613090565b61208791906130b0565b612091908761313f565b815181106120a1576120a16129bf565b602002602001015190505b818313612220575b8073ffffffffffffffffffffffffffffffffffffffff168684815181106120dd576120dd6129bf565b602002602001015173ffffffffffffffffffffffffffffffffffffffff161015612113578261210b81613167565b9350506120b4565b858281518110612125576121256129bf565b602002602001015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161015612172578161216a81613198565b925050612113565b81831361221b5785828151811061218b5761218b6129bf565b60200260200101518684815181106121a5576121a56129bf565b60200260200101518785815181106121bf576121bf6129bf565b602002602001018885815181106121d8576121d86129bf565b73ffffffffffffffffffffffffffffffffffffffff9384166020918202929092010152911690528261220981613167565b935050818061221790613198565b9250505b6120ac565b818512156122335761223386868461205e565b838312156111215761112186848661205e565b60006020828403121561225857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461228857600080fd5b9392505050565b6000815180845260005b818110156122b557602081850181015186830182015201612299565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612288602083018461228f565b60008083601f84011261231857600080fd5b50813567ffffffffffffffff81111561233057600080fd5b60208301915083602082850101111561234857600080fd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461237357600080fd5b919050565b60008060008060006060868803121561239057600080fd5b853567ffffffffffffffff808211156123a857600080fd5b6123b489838a01612306565b909750955060208801359150808211156123cd57600080fd5b506123da88828901612306565b90945092506123ed90506040870161234f565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561244b5761244b6123f9565b60405290565b6040516060810167ffffffffffffffff8111828210171561244b5761244b6123f9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156124bb576124bb6123f9565b604052919050565b600067ffffffffffffffff8211156124dd576124dd6123f9565b5060051b60200190565b600082601f8301126124f857600080fd5b8135602061250d612508836124c3565b612474565b82815260059290921b8401810191818101908684111561252c57600080fd5b8286015b8481101561254e576125418161234f565b8352918301918301612530565b509695505050505050565b803560ff8116811461237357600080fd5b600082601f83011261257b57600080fd5b8135602061258b612508836124c3565b82815260069290921b840181019181810190868411156125aa57600080fd5b8286015b8481101561254e57604081890312156125c75760008081fd5b6125cf612428565b6125d88261234f565b81528482013567ffffffffffffffff811681146125f55760008081fd5b818601528352918301916040016125ae565b60008060006060848603121561261c57600080fd5b833567ffffffffffffffff8082111561263457600080fd5b612640878388016124e7565b945061264e60208701612559565b9350604086013591508082111561266457600080fd5b506126718682870161256a565b9150509250925092565b60006020828403121561268d57600080fd5b6122888261234f565b801515811461106857600080fd5b600080604083850312156126b757600080fd5b8235915060208301356126c981612696565b809150509250929050565b6000806000806000606086880312156126ec57600080fd5b853567ffffffffffffffff8082111561270457600080fd5b818801915088601f83011261271857600080fd5b81358181111561272757600080fd5b8960208260051b850101111561273c57600080fd5b6020928301975095509087013590808211156123cd57600080fd5b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156127ca577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526127b885835161228f565b9450928501929085019060010161277e565b5092979650505050505050565b63ffffffff8116811461106857600080fd5b600080600080608085870312156127ff57600080fd5b843567ffffffffffffffff8082111561281757600080fd5b612823888389016124e7565b955061283160208801612559565b9450604087013591508082111561284757600080fd5b506128548782880161256a565b9250506060850135612865816127d7565b939692955090935050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006128e9604083018486612870565b95945050505050565b60006020828403121561290457600080fd5b815161228881612696565b868152608060208201526000612929608083018789612870565b828103604084015261293c818688612870565b91505073ffffffffffffffffffffffffffffffffffffffff83166060830152979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761040c5761040c612966565b8082018082111561040c5761040c612966565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8181038181111561040c5761040c612966565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a6557600080fd5b83018035915067ffffffffffffffff821115612a8057600080fd5b60200191503681900382131561234857600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612ac657612ac6612966565b5060010190565b6080808252875190820181905260009060209060a0840190828b01845b82811015612b0657815184529284019290840190600101612aea565b50505083810382850152878152818101600589901b820183018a60005b8b811015612bce577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301845281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18e3603018112612b8457600080fd5b8d01868101903567ffffffffffffffff811115612ba057600080fd5b803603821315612baf57600080fd5b612bba858284612870565b958801959450505090850190600101612b23565b50508581036040870152612be381898b612870565b945050505050612c0b606083018473ffffffffffffffffffffffffffffffffffffffff169052565b979650505050505050565b600082601f830112612c2757600080fd5b813567ffffffffffffffff811115612c4157612c416123f9565b612c7260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612474565b818152846020838601011115612c8757600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112612cb557600080fd5b81356020612cc5612508836124c3565b82815260059290921b84018101918181019086841115612ce457600080fd5b8286015b8481101561254e5780358352918301918301612ce8565b600080600080600060e08688031215612d1757600080fd5b86601f870112612d2657600080fd5b612d2e612451565b806060880189811115612d4057600080fd5b885b81811015612d5a578035845260209384019301612d42565b5090965035905067ffffffffffffffff80821115612d7757600080fd5b612d8389838a01612c16565b95506080880135915080821115612d9957600080fd5b612da589838a01612ca4565b945060a0880135915080821115612dbb57600080fd5b50612dc888828901612ca4565b9598949750929560c001359392505050565b828152600060208083018460005b6003811015612e0557815183529183019190830190600101612de8565b505050506080820190509392505050565b60ff818116838216019081111561040c5761040c612966565b80516020808301519190811015612e6e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160200360031b1b821691505b50919050565b825160009082906020808701845b83811015612eb457815173ffffffffffffffffffffffffffffffffffffffff1685529382019390820190600101612e82565b5050505060f89390931b7fff000000000000000000000000000000000000000000000000000000000000001683525050600101919050565b600081518084526020808501945080840160005b83811015612f47578151805173ffffffffffffffffffffffffffffffffffffffff16885283015167ffffffffffffffff168388015260409096019590820190600101612f00565b509495945050505050565b7fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000083168152604060208201526000612f8d6040830184612eec565b949350505050565b6080808252855190820181905260009060209060a0840190828901845b82811015612fe457815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101612fb2565b50505060ff87168285015283810360408501526130018187612eec565b9250505061ffff8316606083015295945050505050565b60008060006060848603121561302d57600080fd5b83519250602084015161303f816127d7565b6040850151909250613050816127d7565b809150509250925092565b60008161306a5761306a612966565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b818103600083128015838313168383128216171561205757612057612966565b6000826130e6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561313a5761313a612966565b500590565b808201828112600083128015821682158216171561315f5761315f612966565b505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612ac657612ac6612966565b60007f8000000000000000000000000000000000000000000000000000000000000000820361306a5761306a61296656fea164736f6c6343000813000a", } var DestinationVerifierABI = DestinationVerifierMetaData.ABI @@ -846,6 +846,7 @@ type DestinationVerifierConfigSet struct { Signers []common.Address F uint8 RecipientAddressesAndWeights []CommonAddressAndWeight + DonConfigIndex uint16 Raw types.Log } @@ -1466,7 +1467,7 @@ func (DestinationVerifierConfigRemoved) Topic() common.Hash { } func (DestinationVerifierConfigSet) Topic() common.Hash { - return common.HexToHash("0x2d763a674a99583454a287d792819ffb9ff7e791c23e7745a082701136ce336c") + return common.HexToHash("0xa7d03f81dd1c1d8a55355fd71e1221d5959b7d9fb171fbb6389f207f63598fa5") } func (DestinationVerifierFeeManagerSet) Topic() common.Hash { diff --git a/core/gethwrappers/llo-feeds/generated/destination_verifier_proxy/destination_verifier_proxy.go b/core/gethwrappers/llo-feeds/generated/destination_verifier_proxy/destination_verifier_proxy.go index a2ae546d9bb..7111fc77639 100644 --- a/core/gethwrappers/llo-feeds/generated/destination_verifier_proxy/destination_verifier_proxy.go +++ b/core/gethwrappers/llo-feeds/generated/destination_verifier_proxy/destination_verifier_proxy.go @@ -32,7 +32,7 @@ var ( var DestinationVerifierProxyMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"VerifierInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"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\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_accessController\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_feeManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"verifierAddress\",\"type\":\"address\"}],\"name\":\"setVerifier\",\"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\":\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61130b806101576000396000f3fe6080604052600436106100b15760003560e01c80638da5cb5b11610069578063f2fde38b1161004e578063f2fde38b146101eb578063f7e83aee1461020b578063f873a61c1461021e57600080fd5b80638da5cb5b146101ab57806394ba2846146101d657600080fd5b806338416b5b1161009a57806338416b5b1461013a5780635437988d1461017457806379ba50971461019657600080fd5b806301ffc9a7146100b6578063181f5a77146100eb575b600080fd5b3480156100c257600080fd5b506100d66100d1366004610c56565b61023e565b60405190151581526020015b60405180910390f35b3480156100f757600080fd5b5060408051808201909152601e81527f44657374696e6174696f6e566572696669657250726f787920312e302e30000060208201525b6040516100e29190610d0d565b34801561014657600080fd5b5061014f6103bb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e2565b34801561018057600080fd5b5061019461018f366004610d42565b610454565b005b3480156101a257600080fd5b506101946107c8565b3480156101b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661014f565b3480156101e257600080fd5b5061014f6108c5565b3480156101f757600080fd5b50610194610206366004610d42565b610935565b61012d610219366004610da8565b610949565b61023161022c366004610e14565b610a18565b6040516100e29190610e95565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5437988d0000000000000000000000000000000000000000000000000000000014806102d157507fffffffff0000000000000000000000000000000000000000000000000000000082167ff7e83aee00000000000000000000000000000000000000000000000000000000145b8061031d57507fffffffff0000000000000000000000000000000000000000000000000000000082167ff873a61c00000000000000000000000000000000000000000000000000000000145b8061036957507fffffffff0000000000000000000000000000000000000000000000000000000082167f38416b5b00000000000000000000000000000000000000000000000000000000145b806103b557507fffffffff0000000000000000000000000000000000000000000000000000000082167f94ba284600000000000000000000000000000000000000000000000000000000145b92915050565b600254604080517f38416b5b000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916338416b5b9160048083019260209291908290030181865afa15801561042b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044f9190610f15565b905090565b61045c610ade565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f94ba284600000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156104e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050a9190610f32565b15806105c157506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f38416b5b00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa15801561059b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bf9190610f32565b155b8061067757506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f294d2bb100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610651573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106759190610f32565b155b8061072d57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fd7c72e4e00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015610707573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072b9190610f32565b155b15610781576040517f96ac86f300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60015473ffffffffffffffffffffffffffffffffffffffff163314610849576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610778565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600254604080517f94ba2846000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916394ba28469160048083019260209291908290030181865afa15801561042b573d6000803e3d6000fd5b61093d610ade565b61094681610b61565b50565b6002546040517f294d2bb100000000000000000000000000000000000000000000000000000000815260609173ffffffffffffffffffffffffffffffffffffffff169063294d2bb19034906109aa9089908990899089903390600401610f9d565b60006040518083038185885af11580156109c8573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a0f91908101906110f5565b95945050505050565b6002546040517fd7c72e4e00000000000000000000000000000000000000000000000000000000815260609173ffffffffffffffffffffffffffffffffffffffff169063d7c72e4e903490610a79908990899089908990339060040161112a565b60006040518083038185885af1158015610a97573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a0f919081019061123b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610778565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610be0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610778565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610c6857600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610c9857600080fd5b9392505050565b60005b83811015610cba578181015183820152602001610ca2565b50506000910152565b60008151808452610cdb816020860160208601610c9f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610c986020830184610cc3565b73ffffffffffffffffffffffffffffffffffffffff8116811461094657600080fd5b600060208284031215610d5457600080fd5b8135610c9881610d20565b60008083601f840112610d7157600080fd5b50813567ffffffffffffffff811115610d8957600080fd5b602083019150836020828501011115610da157600080fd5b9250929050565b60008060008060408587031215610dbe57600080fd5b843567ffffffffffffffff80821115610dd657600080fd5b610de288838901610d5f565b90965094506020870135915080821115610dfb57600080fd5b50610e0887828801610d5f565b95989497509550505050565b60008060008060408587031215610e2a57600080fd5b843567ffffffffffffffff80821115610e4257600080fd5b818701915087601f830112610e5657600080fd5b813581811115610e6557600080fd5b8860208260051b8501011115610e7a57600080fd5b602092830196509450908601359080821115610dfb57600080fd5b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015610f08577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452610ef6858351610cc3565b94509285019290850190600101610ebc565b5092979650505050505050565b600060208284031215610f2757600080fd5b8151610c9881610d20565b600060208284031215610f4457600080fd5b81518015158114610c9857600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000610fb1606083018789610f54565b8281036020840152610fc4818688610f54565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561106357611063610fed565b604052919050565b600082601f83011261107c57600080fd5b815167ffffffffffffffff81111561109657611096610fed565b6110c760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161101c565b8181528460208386010111156110dc57600080fd5b6110ed826020830160208701610c9f565b949350505050565b60006020828403121561110757600080fd5b815167ffffffffffffffff81111561111e57600080fd5b6110ed8482850161106b565b6060808252810185905260006080600587901b8301810190830188835b898110156111f6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c36030181126111a857600080fd5b8b01602081810191359067ffffffffffffffff8211156111c757600080fd5b8136038313156111d657600080fd5b6111e1878385610f54565b96509485019493909301925050600101611147565b505050828103602084015261120c818688610f54565b915050611231604083018473ffffffffffffffffffffffffffffffffffffffff169052565b9695505050505050565b6000602080838503121561124e57600080fd5b825167ffffffffffffffff8082111561126657600080fd5b818501915085601f83011261127a57600080fd5b81518181111561128c5761128c610fed565b8060051b61129b85820161101c565b91825283810185019185810190898411156112b557600080fd5b86860192505b838310156112f1578251858111156112d35760008081fd5b6112e18b89838a010161106b565b83525091860191908601906112bb565b999850505050505050505056fea164736f6c6343000813000a", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610fac806101576000396000f3fe6080604052600436106100b15760003560e01c80638da5cb5b11610069578063f2fde38b1161004e578063f2fde38b1461022d578063f7e83aee1461024d578063f873a61c1461026057600080fd5b80638da5cb5b146101ed57806394ba28461461021857600080fd5b806338416b5b1161009a57806338416b5b1461017c5780635437988d146101b657806379ba5097146101d857600080fd5b806301ffc9a7146100b6578063181f5a771461012d575b600080fd5b3480156100c257600080fd5b506101186100d13660046108f7565b7fffffffff00000000000000000000000000000000000000000000000000000000167ff7574762000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b34801561013957600080fd5b5060408051808201909152601e81527f44657374696e6174696f6e566572696669657250726f787920302e342e30000060208201525b60405161012491906109ae565b34801561018857600080fd5b50610191610280565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b3480156101c257600080fd5b506101d66101d13660046109e3565b610319565b005b3480156101e457600080fd5b506101d6610469565b3480156101f957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610191565b34801561022457600080fd5b50610191610566565b34801561023957600080fd5b506101d66102483660046109e3565b6105d6565b61016f61025b366004610a49565b6105ea565b61027361026e366004610ab5565b6106b9565b6040516101249190610b36565b600254604080517f38416b5b000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916338416b5b9160048083019260209291908290030181865afa1580156102f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103149190610bb6565b905090565b61032161077f565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f527146e200000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156103ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cf9190610bd3565b610422576040517f96ac86f300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60015473ffffffffffffffffffffffffffffffffffffffff1633146104ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610419565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600254604080517f94ba2846000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916394ba28469160048083019260209291908290030181865afa1580156102f0573d6000803e3d6000fd5b6105de61077f565b6105e781610802565b50565b6002546040517f294d2bb100000000000000000000000000000000000000000000000000000000815260609173ffffffffffffffffffffffffffffffffffffffff169063294d2bb190349061064b9089908990899089903390600401610c3e565b60006040518083038185885af1158015610669573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106b09190810190610d96565b95945050505050565b6002546040517fd7c72e4e00000000000000000000000000000000000000000000000000000000815260609173ffffffffffffffffffffffffffffffffffffffff169063d7c72e4e90349061071a9089908990899089903390600401610dcb565b60006040518083038185885af1158015610738573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106b09190810190610edc565b60005473ffffffffffffffffffffffffffffffffffffffff163314610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610419565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610881576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610419565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020828403121561090957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461093957600080fd5b9392505050565b60005b8381101561095b578181015183820152602001610943565b50506000910152565b6000815180845261097c816020860160208601610940565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006109396020830184610964565b73ffffffffffffffffffffffffffffffffffffffff811681146105e757600080fd5b6000602082840312156109f557600080fd5b8135610939816109c1565b60008083601f840112610a1257600080fd5b50813567ffffffffffffffff811115610a2a57600080fd5b602083019150836020828501011115610a4257600080fd5b9250929050565b60008060008060408587031215610a5f57600080fd5b843567ffffffffffffffff80821115610a7757600080fd5b610a8388838901610a00565b90965094506020870135915080821115610a9c57600080fd5b50610aa987828801610a00565b95989497509550505050565b60008060008060408587031215610acb57600080fd5b843567ffffffffffffffff80821115610ae357600080fd5b818701915087601f830112610af757600080fd5b813581811115610b0657600080fd5b8860208260051b8501011115610b1b57600080fd5b602092830196509450908601359080821115610a9c57600080fd5b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015610ba9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452610b97858351610964565b94509285019290850190600101610b5d565b5092979650505050505050565b600060208284031215610bc857600080fd5b8151610939816109c1565b600060208284031215610be557600080fd5b8151801515811461093957600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000610c52606083018789610bf5565b8281036020840152610c65818688610bf5565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610d0457610d04610c8e565b604052919050565b600082601f830112610d1d57600080fd5b815167ffffffffffffffff811115610d3757610d37610c8e565b610d6860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610cbd565b818152846020838601011115610d7d57600080fd5b610d8e826020830160208701610940565b949350505050565b600060208284031215610da857600080fd5b815167ffffffffffffffff811115610dbf57600080fd5b610d8e84828501610d0c565b6060808252810185905260006080600587901b8301810190830188835b89811015610e97577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112610e4957600080fd5b8b01602081810191359067ffffffffffffffff821115610e6857600080fd5b813603831315610e7757600080fd5b610e82878385610bf5565b96509485019493909301925050600101610de8565b5050508281036020840152610ead818688610bf5565b915050610ed2604083018473ffffffffffffffffffffffffffffffffffffffff169052565b9695505050505050565b60006020808385031215610eef57600080fd5b825167ffffffffffffffff80821115610f0757600080fd5b818501915085601f830112610f1b57600080fd5b815181811115610f2d57610f2d610c8e565b8060051b610f3c858201610cbd565b9182528381018501918581019089841115610f5657600080fd5b86860192505b83831015610f9257825185811115610f745760008081fd5b610f828b89838a0101610d0c565b8352509186019190860190610f5c565b999850505050505050505056fea164736f6c6343000813000a", } var DestinationVerifierProxyABI = DestinationVerifierProxyMetaData.ABI diff --git a/core/gethwrappers/llo-feeds/generated/exposed_channel_verifier/exposed_channel_verifier.go b/core/gethwrappers/llo-feeds/generated/exposed_channel_verifier/exposed_channel_verifier.go deleted file mode 100644 index e516b9a247f..00000000000 --- a/core/gethwrappers/llo-feeds/generated/exposed_channel_verifier/exposed_channel_verifier.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 exposed_channel_verifier - -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 ExposedChannelVerifierMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"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: "0x608060405234801561001057600080fd5b5061067e806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b05a355014610030575b600080fd5b61004361003e3660046103f2565b610055565b60405190815260200160405180910390f35b60006100a08b8b8b8b8b8b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92508c91506100af9050565b9b9a5050505050505050505050565b6000808a8a8a8a8a8a8a8a8a6040516020016100d399989796959493929190610594565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461017e57600080fd5b919050565b803567ffffffffffffffff8116811461017e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156102115761021161019b565b604052919050565b600067ffffffffffffffff8211156102335761023361019b565b5060051b60200190565b600082601f83011261024e57600080fd5b8135602061026361025e83610219565b6101ca565b82815260059290921b8401810191818101908684111561028257600080fd5b8286015b848110156102a4576102978161015a565b8352918301918301610286565b509695505050505050565b600082601f8301126102c057600080fd5b813560206102d061025e83610219565b82815260059290921b840181019181810190868411156102ef57600080fd5b8286015b848110156102a457803583529183019183016102f3565b803560ff8116811461017e57600080fd5b60008083601f84011261032d57600080fd5b50813567ffffffffffffffff81111561034557600080fd5b60208301915083602082850101111561035d57600080fd5b9250929050565b600082601f83011261037557600080fd5b813567ffffffffffffffff81111561038f5761038f61019b565b6103c060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016101ca565b8181528460208386010111156103d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101208b8d03121561041257600080fd5b8a35995061042260208c0161015a565b985061043060408c01610183565b975060608b013567ffffffffffffffff8082111561044d57600080fd5b6104598e838f0161023d565b985060808d013591508082111561046f57600080fd5b61047b8e838f016102af565b975061048960a08e0161030a565b965060c08d013591508082111561049f57600080fd5b6104ab8e838f0161031b565b90965094508491506104bf60e08e01610183565b93506101008d01359150808211156104d657600080fd5b506104e38d828e01610364565b9150509295989b9194979a5092959850565b600081518084526020808501945080840160005b8381101561052557815187529582019590820190600101610509565b509495945050505050565b6000815180845260005b818110156105565760208185018101518683018201520161053a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60006101208083018c8452602073ffffffffffffffffffffffffffffffffffffffff808e168287015267ffffffffffffffff8d1660408701528360608701528293508b5180845261014087019450828d01935060005b818110156106085784518316865294830194938301936001016105ea565b5050505050828103608084015261061f81896104f5565b60ff881660a0850152905082810360c084015261063c8187610530565b67ffffffffffffffff861660e085015290508281036101008401526106618185610530565b9c9b50505050505050505050505056fea164736f6c6343000813000a", -} - -var ExposedChannelVerifierABI = ExposedChannelVerifierMetaData.ABI - -var ExposedChannelVerifierBin = ExposedChannelVerifierMetaData.Bin - -func DeployExposedChannelVerifier(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ExposedChannelVerifier, error) { - parsed, err := ExposedChannelVerifierMetaData.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(ExposedChannelVerifierBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &ExposedChannelVerifier{address: address, abi: *parsed, ExposedChannelVerifierCaller: ExposedChannelVerifierCaller{contract: contract}, ExposedChannelVerifierTransactor: ExposedChannelVerifierTransactor{contract: contract}, ExposedChannelVerifierFilterer: ExposedChannelVerifierFilterer{contract: contract}}, nil -} - -type ExposedChannelVerifier struct { - address common.Address - abi abi.ABI - ExposedChannelVerifierCaller - ExposedChannelVerifierTransactor - ExposedChannelVerifierFilterer -} - -type ExposedChannelVerifierCaller struct { - contract *bind.BoundContract -} - -type ExposedChannelVerifierTransactor struct { - contract *bind.BoundContract -} - -type ExposedChannelVerifierFilterer struct { - contract *bind.BoundContract -} - -type ExposedChannelVerifierSession struct { - Contract *ExposedChannelVerifier - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type ExposedChannelVerifierCallerSession struct { - Contract *ExposedChannelVerifierCaller - CallOpts bind.CallOpts -} - -type ExposedChannelVerifierTransactorSession struct { - Contract *ExposedChannelVerifierTransactor - TransactOpts bind.TransactOpts -} - -type ExposedChannelVerifierRaw struct { - Contract *ExposedChannelVerifier -} - -type ExposedChannelVerifierCallerRaw struct { - Contract *ExposedChannelVerifierCaller -} - -type ExposedChannelVerifierTransactorRaw struct { - Contract *ExposedChannelVerifierTransactor -} - -func NewExposedChannelVerifier(address common.Address, backend bind.ContractBackend) (*ExposedChannelVerifier, error) { - abi, err := abi.JSON(strings.NewReader(ExposedChannelVerifierABI)) - if err != nil { - return nil, err - } - contract, err := bindExposedChannelVerifier(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &ExposedChannelVerifier{address: address, abi: abi, ExposedChannelVerifierCaller: ExposedChannelVerifierCaller{contract: contract}, ExposedChannelVerifierTransactor: ExposedChannelVerifierTransactor{contract: contract}, ExposedChannelVerifierFilterer: ExposedChannelVerifierFilterer{contract: contract}}, nil -} - -func NewExposedChannelVerifierCaller(address common.Address, caller bind.ContractCaller) (*ExposedChannelVerifierCaller, error) { - contract, err := bindExposedChannelVerifier(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ExposedChannelVerifierCaller{contract: contract}, nil -} - -func NewExposedChannelVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*ExposedChannelVerifierTransactor, error) { - contract, err := bindExposedChannelVerifier(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ExposedChannelVerifierTransactor{contract: contract}, nil -} - -func NewExposedChannelVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*ExposedChannelVerifierFilterer, error) { - contract, err := bindExposedChannelVerifier(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ExposedChannelVerifierFilterer{contract: contract}, nil -} - -func bindExposedChannelVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ExposedChannelVerifierMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ExposedChannelVerifier.Contract.ExposedChannelVerifierCaller.contract.Call(opts, result, method, params...) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ExposedChannelVerifier.Contract.ExposedChannelVerifierTransactor.contract.Transfer(opts) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ExposedChannelVerifier.Contract.ExposedChannelVerifierTransactor.contract.Transact(opts, method, params...) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ExposedChannelVerifier.Contract.contract.Call(opts, result, method, params...) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ExposedChannelVerifier.Contract.contract.Transfer(opts) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ExposedChannelVerifier.Contract.contract.Transact(opts, method, params...) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierCaller) ExposedConfigDigestFromConfigData(opts *bind.CallOpts, _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 := _ExposedChannelVerifier.contract.Call(opts, &out, "exposedConfigDigestFromConfigData", _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 (_ExposedChannelVerifier *ExposedChannelVerifierSession) ExposedConfigDigestFromConfigData(_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 _ExposedChannelVerifier.Contract.ExposedConfigDigestFromConfigData(&_ExposedChannelVerifier.CallOpts, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifierCallerSession) ExposedConfigDigestFromConfigData(_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 _ExposedChannelVerifier.Contract.ExposedConfigDigestFromConfigData(&_ExposedChannelVerifier.CallOpts, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) -} - -func (_ExposedChannelVerifier *ExposedChannelVerifier) Address() common.Address { - return _ExposedChannelVerifier.address -} - -type ExposedChannelVerifierInterface interface { - ExposedConfigDigestFromConfigData(opts *bind.CallOpts, _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/exposed_configurator/exposed_configurator.go b/core/gethwrappers/llo-feeds/generated/exposed_configurator/exposed_configurator.go new file mode 100644 index 00000000000..756a9fa8432 --- /dev/null +++ b/core/gethwrappers/llo-feeds/generated/exposed_configurator/exposed_configurator.go @@ -0,0 +1,1158 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package exposed_configurator + +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 ConfiguratorConfigurationState struct { + ConfigCount uint64 + LatestConfigBlockNumber uint32 + IsGreenProduction bool + ConfigDigest [2][32]byte +} + +var ExposedConfiguratorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"}],\"name\":\"ConfigUnset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetProduction\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetStaging\",\"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\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"onchainConfigLength\",\"type\":\"uint256\"}],\"name\":\"InvalidOnchainLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"InvalidPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProductionContractState\",\"type\":\"bool\"}],\"name\":\"IsGreenProductionMustMatchContractState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"NonZeroPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UnsupportedOnchainConfigVersion\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ProductionConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"retiredConfigDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"PromoteStagingConfig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"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\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"StagingConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_configId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_contractAddress\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"_configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"_signers\",\"type\":\"bytes[]\"},{\"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\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"}],\"name\":\"exposedReadConfigurationStates\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"},{\"internalType\":\"bytes32[2]\",\"name\":\"configDigest\",\"type\":\"bytes32[2]\"}],\"internalType\":\"structConfigurator.ConfigurationState\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"},{\"internalType\":\"bytes32[2]\",\"name\":\"configDigest\",\"type\":\"bytes32[2]\"}],\"internalType\":\"structConfigurator.ConfigurationState\",\"name\":\"state\",\"type\":\"tuple\"}],\"name\":\"exposedSetConfigurationState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"exposedSetIsGreenProduction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"promoteStagingConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\":\"setProductionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"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\":\"setStagingConfig\",\"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\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611ac080620001586000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063dfb533d01161005b578063dfb533d014610278578063e6e7c5a41461028b578063f2fde38b1461029e57600080fd5b806379ba5097146102285780638da5cb5b1461023057806399a073401461025857600080fd5b8063639fec28116100b2578063639fec28146101a357806369a120eb146101b8578063790464e01461021557600080fd5b806301ffc9a7146100d9578063181f5a771461014357806360e72ec914610182575b600080fd5b61012e6100e73660046110bc565b7fffffffff00000000000000000000000000000000000000000000000000000000167f40569294000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601281527f436f6e666967757261746f7220302e352e3000000000000000000000000000006020820152905161013a9190611169565b61019561019036600461147e565b6102b1565b60405190815260200161013a565b6101b66101b136600461159f565b61030d565b005b6101b66101c6366004611684565b60009182526002602052604090912080549115156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff909216919091179055565b6101b66102233660046116b0565b6103cc565b6101b66105a5565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013a565b61026b610266366004611788565b6106a2565b60405161013a91906117a1565b6101b66102863660046116b0565b610745565b6101b6610299366004611684565b6109a7565b6101b66102ac366004611806565b610bb3565b60006102fd8c8c8c8c8c8c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d9150610bc79050565b9c9b505050505050505050505050565b60008281526002602081815260409283902084518154928601519486015115156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff63ffffffff90961668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090941667ffffffffffffffff90921691909117929092179390931617825560608301518392916103c591600184019161101d565b5050505050565b85518460ff168060000361040c576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115610456576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b610461816003611850565b82116104b95781610473826003611850565b61047e90600161186d565b6040517f9dd9e6d80000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161044d565b6104c1610c75565b6040855110156105025784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161044d91815260200190565b60208501516040860151600182101561054a576040517f8f01e0d70000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b8015610585576040517fb96bb7600000000000000000000000000000000000000000000000000000000081526004810182905260240161044d565b6105988b46308d8d8d8d8d8d6001610cf8565b5050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161044d565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6106aa61105b565b6000828152600260208181526040928390208351608081018552815467ffffffffffffffff8116825268010000000000000000810463ffffffff16938201939093526c0100000000000000000000000090920460ff161515828501528351808501948590529193909260608501929160018501919082845b815481526020019060010190808311610722575050505050815250509050919050565b85518460ff1680600003610785576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156107ca576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f602482015260440161044d565b6107d5816003611850565b82116107e75781610473826003611850565b6107ef610c75565b6040855110156108305784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161044d91815260200190565b602085015160408601516001821015610878576040517f8f01e0d70000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b60008b81526002602081815260408084208151608081018352815467ffffffffffffffff8116825268010000000000000000810463ffffffff16948201949094526c0100000000000000000000000090930460ff161515838301528151808301928390529293909260608501929091600185019182845b8154815260200190600101908083116108ef575050505050815250509050600260008d81526020019081526020016000206001018160400151610933576000610936565b60015b60ff166002811061094957610949611880565b01548214610986576040517f7d78c2a10000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b6109998c46308e8e8e8e8e8e6000610cf8565b505050505050505050505050565b6109af610c75565b600082815260026020526040902080546c01000000000000000000000000900460ff16151582151514610a18576040517f85fa3a37000000000000000000000000000000000000000000000000000000008152600481018490528215602482015260440161044d565b805467ffffffffffffffff16600003610a60576040517f90e6f6dc0000000000000000000000000000000000000000000000000000000081526004810184905260240161044d565b60006001820183610a72576001610a75565b60005b60ff1660028110610a8857610a88611880565b015403610acc576040517f5b7f635700000000000000000000000000000000000000000000000000000000815260048101849052821515602482015260440161044d565b60008160010183610ade576000610ae1565b60015b60ff1660028110610af457610af4611880565b0154905080610b3a576040517fcaf1e77300000000000000000000000000000000000000000000000000000000815260048101859052831515602482015260440161044d565b81547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1683156c010000000000000000000000008102919091178355604051908152819085907f1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f9060200160405180910390a350505050565b610bbb610c75565b610bc481610f28565b50565b6000808b8b8b8b8b8b8b8b8b8b604051602001610bed9a9998979695949392919061193f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161044d565b565b60008a8152600260205260408120805490919082908290610d229067ffffffffffffffff166119ec565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905590506000610d5d8d8d8d858e8e8e8e8e8e610bc7565b90508315610e25578c7f261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e24788460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610dcc9a99989796959493929190611a13565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610e08576000610e0b565b60015b60ff1660028110610e1e57610e1e611880565b0155610ee1565b8c7fef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e890568460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610e8c9a99989796959493929190611a13565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610ec8576001610ecb565b60005b60ff1660028110610ede57610ede611880565b01555b505080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004363ffffffff160217905550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161044d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b826002810192821561104b579160200282015b8281111561104b578251825591602001919060010190611030565b50611057929150611089565b5090565b60408051608081018252600080825260208201819052918101919091526060810161108461109e565b905290565b5b80821115611057576000815560010161108a565b60405180604001604052806002906020820280368337509192915050565b6000602082840312156110ce57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146110fe57600080fd5b9392505050565b6000815180845260005b8181101561112b5760208185018101518683018201520161110f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006110fe6020830184611105565b803573ffffffffffffffffffffffffffffffffffffffff811681146111a057600080fd5b919050565b803567ffffffffffffffff811681146111a057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561120f5761120f6111bd565b60405290565b6040805190810167ffffffffffffffff8111828210171561120f5761120f6111bd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561127f5761127f6111bd565b604052919050565b600067ffffffffffffffff8211156112a1576112a16111bd565b5060051b60200190565b600082601f8301126112bc57600080fd5b813567ffffffffffffffff8111156112d6576112d66111bd565b61130760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611238565b81815284602083860101111561131c57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261134a57600080fd5b8135602061135f61135a83611287565b611238565b82815260059290921b8401810191818101908684111561137e57600080fd5b8286015b848110156113be57803567ffffffffffffffff8111156113a25760008081fd5b6113b08986838b01016112ab565b845250918301918301611382565b509695505050505050565b600082601f8301126113da57600080fd5b813560206113ea61135a83611287565b82815260059290921b8401810191818101908684111561140957600080fd5b8286015b848110156113be578035835291830191830161140d565b803560ff811681146111a057600080fd5b60008083601f84011261144757600080fd5b50813567ffffffffffffffff81111561145f57600080fd5b60208301915083602082850101111561147757600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156114a057600080fd5b8b359a5060208c013599506114b760408d0161117c565b98506114c560608d016111a5565b975067ffffffffffffffff8060808e013511156114e157600080fd5b6114f18e60808f01358f01611339565b97508060a08e0135111561150457600080fd5b6115148e60a08f01358f016113c9565b965061152260c08e01611424565b95508060e08e0135111561153557600080fd5b6115458e60e08f01358f01611435565b90955093506115576101008e016111a5565b9250806101208e0135111561156b57600080fd5b5061157d8d6101208e01358e016112ab565b90509295989b509295989b9093969950565b803580151581146111a057600080fd5b60008082840360c08112156115b357600080fd5b83359250602060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0830112156115e957600080fd5b6115f16111ec565b91506115fe8186016111a5565b8252604085013563ffffffff8116811461161757600080fd5b828201526116276060860161158f565b604083015285609f86011261163b57600080fd5b611643611215565b8060c087018881111561165557600080fd5b608088015b81811015611671578035845292840192840161165a565b5050606084015250929590945092505050565b6000806040838503121561169757600080fd5b823591506116a76020840161158f565b90509250929050565b600080600080600080600060e0888a0312156116cb57600080fd5b87359650602088013567ffffffffffffffff808211156116ea57600080fd5b6116f68b838c01611339565b975060408a013591508082111561170c57600080fd5b6117188b838c016113c9565b965061172660608b01611424565b955060808a013591508082111561173c57600080fd5b6117488b838c016112ab565b945061175660a08b016111a5565b935060c08a013591508082111561176c57600080fd5b506117798a828b016112ab565b91505092959891949750929550565b60006020828403121561179a57600080fd5b5035919050565b600060a08201905067ffffffffffffffff8351168252602063ffffffff81850151168184015260408401511515604084015260608401516060840160005b60028110156117fc578251825291830191908301906001016117df565b5050505092915050565b60006020828403121561181857600080fd5b6110fe8261117c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761186757611867611821565b92915050565b8082018082111561186757611867611821565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b858110156118f75782840389526118e5848351611105565b988501989350908401906001016118cd565b5091979650505050505050565b600081518084526020808501945080840160005b8381101561193457815187529582019590820190600101611918565b509495945050505050565b60006101408c83528b602084015273ffffffffffffffffffffffffffffffffffffffff8b16604084015267ffffffffffffffff808b16606085015281608085015261198c8285018b6118af565b915083820360a08501526119a0828a611904565b915060ff881660c085015283820360e08501526119bd8288611105565b90861661010085015283810361012085015290506119db8185611105565b9d9c50505050505050505050505050565b600067ffffffffffffffff808316818103611a0957611a09611821565b6001019392505050565b600061014063ffffffff8d1683528b602084015267ffffffffffffffff808c166040850152816060850152611a4a8285018c6118af565b91508382036080850152611a5e828b611904565b915060ff891660a085015283820360c0850152611a7b8289611105565b90871660e08501528381036101008501529050611a988186611105565b9150508215156101208301529b9a505050505050505050505056fea164736f6c6343000813000a", +} + +var ExposedConfiguratorABI = ExposedConfiguratorMetaData.ABI + +var ExposedConfiguratorBin = ExposedConfiguratorMetaData.Bin + +func DeployExposedConfigurator(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ExposedConfigurator, error) { + parsed, err := ExposedConfiguratorMetaData.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(ExposedConfiguratorBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ExposedConfigurator{address: address, abi: *parsed, ExposedConfiguratorCaller: ExposedConfiguratorCaller{contract: contract}, ExposedConfiguratorTransactor: ExposedConfiguratorTransactor{contract: contract}, ExposedConfiguratorFilterer: ExposedConfiguratorFilterer{contract: contract}}, nil +} + +type ExposedConfigurator struct { + address common.Address + abi abi.ABI + ExposedConfiguratorCaller + ExposedConfiguratorTransactor + ExposedConfiguratorFilterer +} + +type ExposedConfiguratorCaller struct { + contract *bind.BoundContract +} + +type ExposedConfiguratorTransactor struct { + contract *bind.BoundContract +} + +type ExposedConfiguratorFilterer struct { + contract *bind.BoundContract +} + +type ExposedConfiguratorSession struct { + Contract *ExposedConfigurator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type ExposedConfiguratorCallerSession struct { + Contract *ExposedConfiguratorCaller + CallOpts bind.CallOpts +} + +type ExposedConfiguratorTransactorSession struct { + Contract *ExposedConfiguratorTransactor + TransactOpts bind.TransactOpts +} + +type ExposedConfiguratorRaw struct { + Contract *ExposedConfigurator +} + +type ExposedConfiguratorCallerRaw struct { + Contract *ExposedConfiguratorCaller +} + +type ExposedConfiguratorTransactorRaw struct { + Contract *ExposedConfiguratorTransactor +} + +func NewExposedConfigurator(address common.Address, backend bind.ContractBackend) (*ExposedConfigurator, error) { + abi, err := abi.JSON(strings.NewReader(ExposedConfiguratorABI)) + if err != nil { + return nil, err + } + contract, err := bindExposedConfigurator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ExposedConfigurator{address: address, abi: abi, ExposedConfiguratorCaller: ExposedConfiguratorCaller{contract: contract}, ExposedConfiguratorTransactor: ExposedConfiguratorTransactor{contract: contract}, ExposedConfiguratorFilterer: ExposedConfiguratorFilterer{contract: contract}}, nil +} + +func NewExposedConfiguratorCaller(address common.Address, caller bind.ContractCaller) (*ExposedConfiguratorCaller, error) { + contract, err := bindExposedConfigurator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ExposedConfiguratorCaller{contract: contract}, nil +} + +func NewExposedConfiguratorTransactor(address common.Address, transactor bind.ContractTransactor) (*ExposedConfiguratorTransactor, error) { + contract, err := bindExposedConfigurator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ExposedConfiguratorTransactor{contract: contract}, nil +} + +func NewExposedConfiguratorFilterer(address common.Address, filterer bind.ContractFilterer) (*ExposedConfiguratorFilterer, error) { + contract, err := bindExposedConfigurator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ExposedConfiguratorFilterer{contract: contract}, nil +} + +func bindExposedConfigurator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ExposedConfiguratorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_ExposedConfigurator *ExposedConfiguratorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExposedConfigurator.Contract.ExposedConfiguratorCaller.contract.Call(opts, result, method, params...) +} + +func (_ExposedConfigurator *ExposedConfiguratorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.ExposedConfiguratorTransactor.contract.Transfer(opts) +} + +func (_ExposedConfigurator *ExposedConfiguratorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.ExposedConfiguratorTransactor.contract.Transact(opts, method, params...) +} + +func (_ExposedConfigurator *ExposedConfiguratorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExposedConfigurator.Contract.contract.Call(opts, result, method, params...) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.contract.Transfer(opts) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.contract.Transact(opts, method, params...) +} + +func (_ExposedConfigurator *ExposedConfiguratorCaller) ExposedConfigDigestFromConfigData(opts *bind.CallOpts, _configId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers [][]byte, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) { + var out []interface{} + err := _ExposedConfigurator.contract.Call(opts, &out, "exposedConfigDigestFromConfigData", _configId, _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 (_ExposedConfigurator *ExposedConfiguratorSession) ExposedConfigDigestFromConfigData(_configId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers [][]byte, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) { + return _ExposedConfigurator.Contract.ExposedConfigDigestFromConfigData(&_ExposedConfigurator.CallOpts, _configId, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorCallerSession) ExposedConfigDigestFromConfigData(_configId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers [][]byte, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) { + return _ExposedConfigurator.Contract.ExposedConfigDigestFromConfigData(&_ExposedConfigurator.CallOpts, _configId, _chainId, _contractAddress, _configCount, _signers, _offchainTransmitters, _f, _onchainConfig, _encodedConfigVersion, _encodedConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorCaller) ExposedReadConfigurationStates(opts *bind.CallOpts, configId [32]byte) (ConfiguratorConfigurationState, error) { + var out []interface{} + err := _ExposedConfigurator.contract.Call(opts, &out, "exposedReadConfigurationStates", configId) + + if err != nil { + return *new(ConfiguratorConfigurationState), err + } + + out0 := *abi.ConvertType(out[0], new(ConfiguratorConfigurationState)).(*ConfiguratorConfigurationState) + + return out0, err + +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) ExposedReadConfigurationStates(configId [32]byte) (ConfiguratorConfigurationState, error) { + return _ExposedConfigurator.Contract.ExposedReadConfigurationStates(&_ExposedConfigurator.CallOpts, configId) +} + +func (_ExposedConfigurator *ExposedConfiguratorCallerSession) ExposedReadConfigurationStates(configId [32]byte) (ConfiguratorConfigurationState, error) { + return _ExposedConfigurator.Contract.ExposedReadConfigurationStates(&_ExposedConfigurator.CallOpts, configId) +} + +func (_ExposedConfigurator *ExposedConfiguratorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ExposedConfigurator.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 (_ExposedConfigurator *ExposedConfiguratorSession) Owner() (common.Address, error) { + return _ExposedConfigurator.Contract.Owner(&_ExposedConfigurator.CallOpts) +} + +func (_ExposedConfigurator *ExposedConfiguratorCallerSession) Owner() (common.Address, error) { + return _ExposedConfigurator.Contract.Owner(&_ExposedConfigurator.CallOpts) +} + +func (_ExposedConfigurator *ExposedConfiguratorCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _ExposedConfigurator.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 (_ExposedConfigurator *ExposedConfiguratorSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ExposedConfigurator.Contract.SupportsInterface(&_ExposedConfigurator.CallOpts, interfaceId) +} + +func (_ExposedConfigurator *ExposedConfiguratorCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ExposedConfigurator.Contract.SupportsInterface(&_ExposedConfigurator.CallOpts, interfaceId) +} + +func (_ExposedConfigurator *ExposedConfiguratorCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ExposedConfigurator.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) TypeAndVersion() (string, error) { + return _ExposedConfigurator.Contract.TypeAndVersion(&_ExposedConfigurator.CallOpts) +} + +func (_ExposedConfigurator *ExposedConfiguratorCallerSession) TypeAndVersion() (string, error) { + return _ExposedConfigurator.Contract.TypeAndVersion(&_ExposedConfigurator.CallOpts) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "acceptOwnership") +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) AcceptOwnership() (*types.Transaction, error) { + return _ExposedConfigurator.Contract.AcceptOwnership(&_ExposedConfigurator.TransactOpts) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _ExposedConfigurator.Contract.AcceptOwnership(&_ExposedConfigurator.TransactOpts) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) ExposedSetConfigurationState(opts *bind.TransactOpts, configId [32]byte, state ConfiguratorConfigurationState) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "exposedSetConfigurationState", configId, state) +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) ExposedSetConfigurationState(configId [32]byte, state ConfiguratorConfigurationState) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.ExposedSetConfigurationState(&_ExposedConfigurator.TransactOpts, configId, state) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) ExposedSetConfigurationState(configId [32]byte, state ConfiguratorConfigurationState) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.ExposedSetConfigurationState(&_ExposedConfigurator.TransactOpts, configId, state) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) ExposedSetIsGreenProduction(opts *bind.TransactOpts, configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "exposedSetIsGreenProduction", configId, isGreenProduction) +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) ExposedSetIsGreenProduction(configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.ExposedSetIsGreenProduction(&_ExposedConfigurator.TransactOpts, configId, isGreenProduction) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) ExposedSetIsGreenProduction(configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.ExposedSetIsGreenProduction(&_ExposedConfigurator.TransactOpts, configId, isGreenProduction) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) PromoteStagingConfig(opts *bind.TransactOpts, configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "promoteStagingConfig", configId, isGreenProduction) +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) PromoteStagingConfig(configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.PromoteStagingConfig(&_ExposedConfigurator.TransactOpts, configId, isGreenProduction) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) PromoteStagingConfig(configId [32]byte, isGreenProduction bool) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.PromoteStagingConfig(&_ExposedConfigurator.TransactOpts, configId, isGreenProduction) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) SetProductionConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "setProductionConfig", configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) SetProductionConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.SetProductionConfig(&_ExposedConfigurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) SetProductionConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.SetProductionConfig(&_ExposedConfigurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) SetStagingConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "setStagingConfig", configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) SetStagingConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.SetStagingConfig(&_ExposedConfigurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) SetStagingConfig(configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.SetStagingConfig(&_ExposedConfigurator.TransactOpts, configId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _ExposedConfigurator.contract.Transact(opts, "transferOwnership", to) +} + +func (_ExposedConfigurator *ExposedConfiguratorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.TransferOwnership(&_ExposedConfigurator.TransactOpts, to) +} + +func (_ExposedConfigurator *ExposedConfiguratorTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _ExposedConfigurator.Contract.TransferOwnership(&_ExposedConfigurator.TransactOpts, to) +} + +type ExposedConfiguratorOwnershipTransferRequestedIterator struct { + Event *ExposedConfiguratorOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ExposedConfiguratorOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExposedConfiguratorOwnershipTransferRequested) + 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(ExposedConfiguratorOwnershipTransferRequested) + 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 *ExposedConfiguratorOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *ExposedConfiguratorOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ExposedConfiguratorOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ExposedConfiguratorOwnershipTransferRequestedIterator, 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 := _ExposedConfigurator.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &ExposedConfiguratorOwnershipTransferRequestedIterator{contract: _ExposedConfigurator.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorOwnershipTransferRequested, 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 := _ExposedConfigurator.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(ExposedConfiguratorOwnershipTransferRequested) + if err := _ExposedConfigurator.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 (_ExposedConfigurator *ExposedConfiguratorFilterer) ParseOwnershipTransferRequested(log types.Log) (*ExposedConfiguratorOwnershipTransferRequested, error) { + event := new(ExposedConfiguratorOwnershipTransferRequested) + if err := _ExposedConfigurator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ExposedConfiguratorOwnershipTransferredIterator struct { + Event *ExposedConfiguratorOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ExposedConfiguratorOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExposedConfiguratorOwnershipTransferred) + 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(ExposedConfiguratorOwnershipTransferred) + 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 *ExposedConfiguratorOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *ExposedConfiguratorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ExposedConfiguratorOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ExposedConfiguratorOwnershipTransferredIterator, 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 := _ExposedConfigurator.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &ExposedConfiguratorOwnershipTransferredIterator{contract: _ExposedConfigurator.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorOwnershipTransferred, 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 := _ExposedConfigurator.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(ExposedConfiguratorOwnershipTransferred) + if err := _ExposedConfigurator.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 (_ExposedConfigurator *ExposedConfiguratorFilterer) ParseOwnershipTransferred(log types.Log) (*ExposedConfiguratorOwnershipTransferred, error) { + event := new(ExposedConfiguratorOwnershipTransferred) + if err := _ExposedConfigurator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ExposedConfiguratorProductionConfigSetIterator struct { + Event *ExposedConfiguratorProductionConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ExposedConfiguratorProductionConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExposedConfiguratorProductionConfigSet) + 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(ExposedConfiguratorProductionConfigSet) + 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 *ExposedConfiguratorProductionConfigSetIterator) Error() error { + return it.fail +} + +func (it *ExposedConfiguratorProductionConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ExposedConfiguratorProductionConfigSet struct { + ConfigId [32]byte + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers [][]byte + OffchainTransmitters [][32]byte + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + IsGreenProduction bool + Raw types.Log +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) FilterProductionConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ExposedConfiguratorProductionConfigSetIterator, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _ExposedConfigurator.contract.FilterLogs(opts, "ProductionConfigSet", configIdRule) + if err != nil { + return nil, err + } + return &ExposedConfiguratorProductionConfigSetIterator{contract: _ExposedConfigurator.contract, event: "ProductionConfigSet", logs: logs, sub: sub}, nil +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) WatchProductionConfigSet(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorProductionConfigSet, configId [][32]byte) (event.Subscription, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _ExposedConfigurator.contract.WatchLogs(opts, "ProductionConfigSet", configIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ExposedConfiguratorProductionConfigSet) + if err := _ExposedConfigurator.contract.UnpackLog(event, "ProductionConfigSet", 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 (_ExposedConfigurator *ExposedConfiguratorFilterer) ParseProductionConfigSet(log types.Log) (*ExposedConfiguratorProductionConfigSet, error) { + event := new(ExposedConfiguratorProductionConfigSet) + if err := _ExposedConfigurator.contract.UnpackLog(event, "ProductionConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ExposedConfiguratorPromoteStagingConfigIterator struct { + Event *ExposedConfiguratorPromoteStagingConfig + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ExposedConfiguratorPromoteStagingConfigIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExposedConfiguratorPromoteStagingConfig) + 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(ExposedConfiguratorPromoteStagingConfig) + 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 *ExposedConfiguratorPromoteStagingConfigIterator) Error() error { + return it.fail +} + +func (it *ExposedConfiguratorPromoteStagingConfigIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ExposedConfiguratorPromoteStagingConfig struct { + ConfigId [32]byte + RetiredConfigDigest [32]byte + IsGreenProduction bool + Raw types.Log +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) FilterPromoteStagingConfig(opts *bind.FilterOpts, configId [][32]byte, retiredConfigDigest [][32]byte) (*ExposedConfiguratorPromoteStagingConfigIterator, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + var retiredConfigDigestRule []interface{} + for _, retiredConfigDigestItem := range retiredConfigDigest { + retiredConfigDigestRule = append(retiredConfigDigestRule, retiredConfigDigestItem) + } + + logs, sub, err := _ExposedConfigurator.contract.FilterLogs(opts, "PromoteStagingConfig", configIdRule, retiredConfigDigestRule) + if err != nil { + return nil, err + } + return &ExposedConfiguratorPromoteStagingConfigIterator{contract: _ExposedConfigurator.contract, event: "PromoteStagingConfig", logs: logs, sub: sub}, nil +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) WatchPromoteStagingConfig(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorPromoteStagingConfig, configId [][32]byte, retiredConfigDigest [][32]byte) (event.Subscription, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + var retiredConfigDigestRule []interface{} + for _, retiredConfigDigestItem := range retiredConfigDigest { + retiredConfigDigestRule = append(retiredConfigDigestRule, retiredConfigDigestItem) + } + + logs, sub, err := _ExposedConfigurator.contract.WatchLogs(opts, "PromoteStagingConfig", configIdRule, retiredConfigDigestRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ExposedConfiguratorPromoteStagingConfig) + if err := _ExposedConfigurator.contract.UnpackLog(event, "PromoteStagingConfig", 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 (_ExposedConfigurator *ExposedConfiguratorFilterer) ParsePromoteStagingConfig(log types.Log) (*ExposedConfiguratorPromoteStagingConfig, error) { + event := new(ExposedConfiguratorPromoteStagingConfig) + if err := _ExposedConfigurator.contract.UnpackLog(event, "PromoteStagingConfig", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type ExposedConfiguratorStagingConfigSetIterator struct { + Event *ExposedConfiguratorStagingConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *ExposedConfiguratorStagingConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExposedConfiguratorStagingConfigSet) + 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(ExposedConfiguratorStagingConfigSet) + 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 *ExposedConfiguratorStagingConfigSetIterator) Error() error { + return it.fail +} + +func (it *ExposedConfiguratorStagingConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type ExposedConfiguratorStagingConfigSet struct { + ConfigId [32]byte + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers [][]byte + OffchainTransmitters [][32]byte + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + IsGreenProduction bool + Raw types.Log +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) FilterStagingConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ExposedConfiguratorStagingConfigSetIterator, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _ExposedConfigurator.contract.FilterLogs(opts, "StagingConfigSet", configIdRule) + if err != nil { + return nil, err + } + return &ExposedConfiguratorStagingConfigSetIterator{contract: _ExposedConfigurator.contract, event: "StagingConfigSet", logs: logs, sub: sub}, nil +} + +func (_ExposedConfigurator *ExposedConfiguratorFilterer) WatchStagingConfigSet(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorStagingConfigSet, configId [][32]byte) (event.Subscription, error) { + + var configIdRule []interface{} + for _, configIdItem := range configId { + configIdRule = append(configIdRule, configIdItem) + } + + logs, sub, err := _ExposedConfigurator.contract.WatchLogs(opts, "StagingConfigSet", configIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(ExposedConfiguratorStagingConfigSet) + if err := _ExposedConfigurator.contract.UnpackLog(event, "StagingConfigSet", 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 (_ExposedConfigurator *ExposedConfiguratorFilterer) ParseStagingConfigSet(log types.Log) (*ExposedConfiguratorStagingConfigSet, error) { + event := new(ExposedConfiguratorStagingConfigSet) + if err := _ExposedConfigurator.contract.UnpackLog(event, "StagingConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_ExposedConfigurator *ExposedConfigurator) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _ExposedConfigurator.abi.Events["OwnershipTransferRequested"].ID: + return _ExposedConfigurator.ParseOwnershipTransferRequested(log) + case _ExposedConfigurator.abi.Events["OwnershipTransferred"].ID: + return _ExposedConfigurator.ParseOwnershipTransferred(log) + case _ExposedConfigurator.abi.Events["ProductionConfigSet"].ID: + return _ExposedConfigurator.ParseProductionConfigSet(log) + case _ExposedConfigurator.abi.Events["PromoteStagingConfig"].ID: + return _ExposedConfigurator.ParsePromoteStagingConfig(log) + case _ExposedConfigurator.abi.Events["StagingConfigSet"].ID: + return _ExposedConfigurator.ParseStagingConfigSet(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (ExposedConfiguratorOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (ExposedConfiguratorOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (ExposedConfiguratorProductionConfigSet) Topic() common.Hash { + return common.HexToHash("0x261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e2478") +} + +func (ExposedConfiguratorPromoteStagingConfig) Topic() common.Hash { + return common.HexToHash("0x1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f") +} + +func (ExposedConfiguratorStagingConfigSet) Topic() common.Hash { + return common.HexToHash("0xef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e89056") +} + +func (_ExposedConfigurator *ExposedConfigurator) Address() common.Address { + return _ExposedConfigurator.address +} + +type ExposedConfiguratorInterface interface { + ExposedConfigDigestFromConfigData(opts *bind.CallOpts, _configId [32]byte, _chainId *big.Int, _contractAddress common.Address, _configCount uint64, _signers [][]byte, _offchainTransmitters [][32]byte, _f uint8, _onchainConfig []byte, _encodedConfigVersion uint64, _encodedConfig []byte) ([32]byte, error) + + ExposedReadConfigurationStates(opts *bind.CallOpts, configId [32]byte) (ConfiguratorConfigurationState, 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) + + ExposedSetConfigurationState(opts *bind.TransactOpts, configId [32]byte, state ConfiguratorConfigurationState) (*types.Transaction, error) + + ExposedSetIsGreenProduction(opts *bind.TransactOpts, configId [32]byte, isGreenProduction bool) (*types.Transaction, error) + + PromoteStagingConfig(opts *bind.TransactOpts, configId [32]byte, isGreenProduction bool) (*types.Transaction, error) + + SetProductionConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) + + SetStagingConfig(opts *bind.TransactOpts, configId [32]byte, signers [][]byte, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ExposedConfiguratorOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*ExposedConfiguratorOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ExposedConfiguratorOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*ExposedConfiguratorOwnershipTransferred, error) + + FilterProductionConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ExposedConfiguratorProductionConfigSetIterator, error) + + WatchProductionConfigSet(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorProductionConfigSet, configId [][32]byte) (event.Subscription, error) + + ParseProductionConfigSet(log types.Log) (*ExposedConfiguratorProductionConfigSet, error) + + FilterPromoteStagingConfig(opts *bind.FilterOpts, configId [][32]byte, retiredConfigDigest [][32]byte) (*ExposedConfiguratorPromoteStagingConfigIterator, error) + + WatchPromoteStagingConfig(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorPromoteStagingConfig, configId [][32]byte, retiredConfigDigest [][32]byte) (event.Subscription, error) + + ParsePromoteStagingConfig(log types.Log) (*ExposedConfiguratorPromoteStagingConfig, error) + + FilterStagingConfigSet(opts *bind.FilterOpts, configId [][32]byte) (*ExposedConfiguratorStagingConfigSetIterator, error) + + WatchStagingConfigSet(opts *bind.WatchOpts, sink chan<- *ExposedConfiguratorStagingConfigSet, configId [][32]byte) (event.Subscription, error) + + ParseStagingConfigSet(log types.Log) (*ExposedConfiguratorStagingConfigSet, 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 0eec657b4c7..f7b08f0f478 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,13 +1,15 @@ GETH_VERSION: 1.13.8 -channel_config_store: ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.bin c90e29d9f1a885098982b6175e0447416431b28c605273c807694ac7141e9167 +channel_config_store: ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/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 -destination_fee_manager: ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.abi ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.bin c581af84832b8fd886685f59518bcdb11bd1c9b508d88b07c04d6226e6a2789e -destination_reward_manager: ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.abi ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.bin 6aed4313578f74ede71bcb60674391103d265d96d56d4736a79ef4128f0590f4 -destination_verifier: ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.abi ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.bin 2dc118aecd5c30d34a69354a9fb603beb98d46215a18d31c59f0f7902fd8f4c2 -destination_verifier_proxy: ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.abi ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.bin a4bf230bbba8a7b8e32a85a6161ca1343f7472b257c358a73ac37996809ce1c0 +configurator: ../../../contracts/solc/v0.8.19/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/Configurator/Configurator.bin ee5ed0cd4f42636b6e008a12a8952c0efe3381094974e97269928eb13329c636 +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 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 f43362e7ef7588ecbd4d7ebd45b750cc4308e89c3d9e54fba1383e792213bbef 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 llo_feeds: ../../../contracts/solc/v0.8.19/FeeManager.abi ../../../contracts/solc/v0.8.19/FeeManager.bin cb71e018f67e49d7bc0e194c822204dfd59f79ff42e4fc8fd8ab63f3acd71361 diff --git a/core/gethwrappers/llo-feeds/go_generate.go b/core/gethwrappers/llo-feeds/go_generate.go index 688b503cc1e..5bc29f36dea 100644 --- a/core/gethwrappers/llo-feeds/go_generate.go +++ b/core/gethwrappers/llo-feeds/go_generate.go @@ -10,10 +10,11 @@ package gethwrappers //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 -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ChannelVerifier/ChannelVerifier.abi ../../../contracts/solc/v0.8.19/ChannelVerifier/ChannelVerifier.bin ChannelVerifier channel_verifier -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ExposedChannelVerifier/ExposedChannelVerifier.abi ../../../contracts/solc/v0.8.19/ExposedChannelVerifier/ExposedChannelVerifier.bin ExposedChannelVerifier exposed_channel_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 + +//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 diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 7447d1385f6..785ea2f4e0a 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -37,8 +37,11 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/services/llo" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink-common/pkg/loop" @@ -200,11 +203,12 @@ func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipeline type TestApplication struct { t testing.TB *chainlink.ChainlinkApplication - Logger logger.Logger - Server *httptest.Server - Started bool - Backend *backends.SimulatedBackend - Keys []ethkey.KeyV2 + Logger logger.Logger + Server *httptest.Server + Started bool + Backend *backends.SimulatedBackend + Keys []ethkey.KeyV2 + CapabilityRegistry *capabilities.Registry } // NewApplicationEVMDisabled creates a new application with default config but EVM disabled @@ -212,7 +216,12 @@ type TestApplication struct { func NewApplicationEVMDisabled(t *testing.T) *TestApplication { t.Helper() - c := configtest.NewGeneralConfig(t, nil) + c := configtest.NewGeneralConfig(t, func(config *chainlink.Config, secrets *chainlink.Secrets) { + f := false + for _, c := range config.EVM { + c.Enabled = &f + } + }) return NewApplicationWithConfig(t, c) } @@ -320,6 +329,15 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn auditLogger = audit.NoopLogger } + var newOracleFactoryFn standardcapabilities.NewOracleFactoryFn + for _, dep := range flagsAndDeps { + factoryFn, _ := dep.(standardcapabilities.NewOracleFactoryFn) + if factoryFn != nil { + newOracleFactoryFn = factoryFn + break + } + } + var capabilitiesRegistry *capabilities.Registry capabilitiesRegistry = capabilities.NewRegistry(lggr) for _, dep := range flagsAndDeps { @@ -374,7 +392,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn keyStore := keystore.NewInMemory(ds, utils.FastScryptParams, lggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox")) - loopRegistry := plugins.NewLoopRegistry(lggr, nil) + loopRegistry := plugins.NewLoopRegistry(lggr, nil, nil) mercuryPool := wsrpc.NewPool(lggr, cache.Config{ LatestReportTTL: cfg.Mercury().Cache().LatestReportTTL(), @@ -382,12 +400,16 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn LatestReportDeadline: cfg.Mercury().Cache().LatestReportDeadline(), }) + c := clhttptest.NewTestLocalOnlyHTTPClient() + retirementReportCache := llo.NewRetirementReportCache(lggr, ds) relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: loopRegistry, - GRPCOpts: loop.GRPCOpts{}, - MercuryPool: mercuryPool, - CapabilitiesRegistry: capabilitiesRegistry, + Logger: lggr, + LoopRegistry: loopRegistry, + GRPCOpts: loop.GRPCOpts{}, + MercuryPool: mercuryPool, + CapabilitiesRegistry: capabilitiesRegistry, + HTTPClient: c, + RetirementReportCache: retirementReportCache, } evmOpts := chainlink.EVMFactoryConfig{ @@ -451,7 +473,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn if err != nil { t.Fatal(err) } - c := clhttptest.NewTestLocalOnlyHTTPClient() appInstance, err := chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, MailMon: mailMon, @@ -465,11 +486,13 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn RestrictedHTTPClient: c, UnrestrictedHTTPClient: c, SecretGenerator: MockSecretGenerator{}, - LoopRegistry: plugins.NewLoopRegistry(lggr, nil), + LoopRegistry: plugins.NewLoopRegistry(lggr, nil, nil), MercuryPool: mercuryPool, CapabilitiesRegistry: capabilitiesRegistry, CapabilitiesDispatcher: dispatcher, CapabilitiesPeerWrapper: peerWrapper, + NewOracleFactoryFn: newOracleFactoryFn, + RetirementReportCache: retirementReportCache, }) require.NoError(t, err) @@ -508,8 +531,9 @@ func NewEthMocks(t testing.TB) *evmclimocks.Client { func NewEthMocksWithStartupAssertions(t testing.TB) *evmclimocks.Client { testutils.SkipShort(t, "long test") c := NewEthMocks(t) + chHead := make(<-chan *evmtypes.Head) c.On("Dial", mock.Anything).Maybe().Return(nil) - c.On("SubscribeNewHead", mock.Anything, mock.Anything).Maybe().Return(EmptyMockSubscription(t), nil) + c.On("SubscribeToHeads", mock.Anything).Maybe().Return(chHead, EmptyMockSubscription(t), nil) c.On("SendTransaction", mock.Anything, mock.Anything).Maybe().Return(nil) c.On("HeadByNumber", mock.Anything, mock.Anything).Maybe().Return(Head(0), nil) c.On("ConfiguredChainID").Maybe().Return(&FixtureChainID) @@ -530,8 +554,9 @@ func NewEthMocksWithStartupAssertions(t testing.TB) *evmclimocks.Client { func NewEthMocksWithTransactionsOnBlocksAssertions(t testing.TB) *evmclimocks.Client { testutils.SkipShort(t, "long test") c := NewEthMocks(t) + chHead := make(<-chan *evmtypes.Head) c.On("Dial", mock.Anything).Maybe().Return(nil) - c.On("SubscribeNewHead", mock.Anything, mock.Anything).Maybe().Return(EmptyMockSubscription(t), 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) // Construct chain @@ -948,11 +973,13 @@ func WaitForSpecErrorV2(t *testing.T, ds sqlutil.DataSource, jobID int32, count g := gomega.NewWithT(t) var jse []job.SpecError - g.Eventually(func() []job.SpecError { + if !g.Eventually(func() []job.SpecError { err := ds.SelectContext(ctx, &jse, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jobID) assert.NoError(t, err) return jse - }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.HaveLen(count)) + }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.HaveLen(count)) { + t.Fatal() + } return jse } @@ -1291,7 +1318,7 @@ func MockApplicationEthCalls(t *testing.T, app *TestApplication, ethClient *evmc // Start ethClient.On("Dial", mock.Anything).Return(nil) - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Maybe() + ethClient.On("SubscribeToHeads", mock.Anything).Return(make(<-chan *evmtypes.Head), sub, nil).Maybe() ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, app.GetConfig().EVMConfigs()), nil) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(nil, nil).Maybe() @@ -1383,7 +1410,7 @@ func (b *Blocks) ForkAt(t *testing.T, blockNum int64, numHashes int) *Blocks { } forked.Heads[blockNum].ParentHash = b.Heads[blockNum].ParentHash - forked.Heads[blockNum].Parent = b.Heads[blockNum].Parent + forked.Heads[blockNum].Parent.Store(b.Heads[blockNum].Parent.Load()) return forked } @@ -1397,10 +1424,10 @@ func (b *Blocks) NewHead(number uint64) *evmtypes.Head { Number: parent.Number + 1, Hash: evmutils.NewHash(), ParentHash: parent.Hash, - Parent: parent, Timestamp: time.Unix(parent.Number+1, 0), EVMChainID: ubig.New(&FixtureChainID), } + head.Parent.Store(parent) return head } @@ -1441,7 +1468,7 @@ func NewBlocks(t *testing.T, numHashes int) *Blocks { heads[i] = &evmtypes.Head{Hash: hash, Number: i, Timestamp: time.Unix(i, 0), EVMChainID: ubig.New(&FixtureChainID)} if i > 0 { parent := heads[i-1] - heads[i].Parent = parent + heads[i].Parent.Store(parent) heads[i].ParentHash = parent.Hash } } @@ -1502,14 +1529,13 @@ func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected func WaitForCount(t *testing.T, ds sqlutil.DataSource, tableName string, want int64) { t.Helper() ctx := testutils.Context(t) - g := gomega.NewWithT(t) var count int64 var err error - g.Eventually(func() int64 { + require.Eventually(t, func() bool { err = ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) assert.NoError(t, err) - return count - }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.Equal(want)) + return count == want + }, testutils.WaitTimeout(t), DBPollingInterval) } func AssertCountStays(t testing.TB, ds sqlutil.DataSource, tableName string, want int64) { @@ -1528,12 +1554,11 @@ func AssertCountStays(t testing.TB, ds sqlutil.DataSource, tableName string, wan func AssertRecordEventually(t *testing.T, ds sqlutil.DataSource, model interface{}, stmt string, check func() bool) { t.Helper() ctx := testutils.Context(t) - g := gomega.NewWithT(t) - g.Eventually(func() bool { + require.Eventually(t, func() bool { err := ds.GetContext(ctx, model, stmt) require.NoError(t, err, "unable to find record in DB") return check() - }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), DBPollingInterval) } func MustWebURL(t *testing.T, s string) *models.WebURL { diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index c488dca94a9..3430f7d1057 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/auth" @@ -225,7 +226,7 @@ func NewLegacyEthTxAttempt(t *testing.T, etxID int64) txmgr.TxAttempt { return txmgr.TxAttempt{ ChainSpecificFeeLimit: 42, TxID: etxID, - TxFee: gas.EvmFee{Legacy: gasPrice}, + TxFee: gas.EvmFee{GasPrice: gasPrice}, // Just a random signed raw tx that decodes correctly // Ignore all actual values SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), @@ -241,8 +242,7 @@ func NewDynamicFeeEthTxAttempt(t *testing.T, etxID int64) txmgr.TxAttempt { TxType: 0x2, TxID: etxID, TxFee: gas.EvmFee{ - DynamicTipCap: gasTipCap, - DynamicFeeCap: gasFeeCap, + DynamicFee: gas.DynamicFee{GasTipCap: gasTipCap, GasFeeCap: gasFeeCap}, }, // Just a random signed raw tx that decodes correctly // Ignore all actual values @@ -318,13 +318,13 @@ func MustGenerateRandomKeyState(_ testing.TB) ethkey.State { return ethkey.State{Address: NewEIP55Address()} } -func MustInsertHead(t *testing.T, ds sqlutil.DataSource, number int64) evmtypes.Head { +func MustInsertHead(t *testing.T, ds sqlutil.DataSource, number int64) *evmtypes.Head { h := evmtypes.NewHead(big.NewInt(number), evmutils.NewHash(), evmutils.NewHash(), 0, ubig.New(&FixtureChainID)) horm := headtracker.NewORM(FixtureChainID, ds) err := horm.IdempotentInsertHead(testutils.Context(t), &h) require.NoError(t, err) - return h + return &h } func MustInsertV2JobSpec(t *testing.T, db *sqlx.DB, transmitterAddress common.Address) job.Job { diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 046f21b7f7d..eb25f995052 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -41,6 +41,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -57,7 +58,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/multiwordconsumer_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -69,11 +69,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/web" webauth "github.com/smartcontractkit/chainlink/v2/core/web/auth" ) @@ -1270,7 +1270,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { kst := cltest.NewKeyStore(t, db) require.NoError(t, kst.Unlock(ctx, cltest.Password)) - cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), Client: ethClient, GeneralConfig: cfg}) + chainsAndConfig := evmtest.NewLegacyChainsAndConfig(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), Client: ethClient, GeneralConfig: cfg}) b41 := evmtypes.Block{ Number: 41, @@ -1294,14 +1294,14 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { h42 := evmtypes.Head{Hash: b42.Hash, ParentHash: h41.Hash, Number: 42, EVMChainID: evmChainID} mockEth := &evmtestutils.MockEth{EthClient: ethClient} - ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + ethClient.On("SubscribeToHeads", mock.Anything). Return( - func(ctx context.Context, ch chan<- *evmtypes.Head) ethereum.Subscription { + func(ctx context.Context) (<-chan *evmtypes.Head, ethereum.Subscription, error) { + ch := make(chan *evmtypes.Head) sub := mockEth.NewSub(t) chchNewHeads <- evmtestutils.NewRawSub(ch, sub.Err()) - return sub + return ch, sub, nil }, - func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) // Nonce syncer ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Maybe().Return(uint64(0), nil) @@ -1326,8 +1326,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { ethClient.On("HeadByHash", mock.Anything, h41.Hash).Return(&h41, nil).Maybe() ethClient.On("HeadByHash", mock.Anything, h42.Hash).Return(&h42, nil).Maybe() - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(cc) - for _, re := range cc.Slice() { + for _, re := range chainsAndConfig.Slice() { servicetest.Run(t, re) } var newHeads evmtestutils.RawSub[*evmtypes.Head] @@ -1337,12 +1336,13 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { t.Fatal("timed out waiting for app to subscribe") } + legacyChains := chainsAndConfig.NewLegacyChains() chain := evmtest.MustGetDefaultChain(t, legacyChains) estimator := chain.GasEstimator() - gasPrice, gasLimit, err := estimator.GetFee(testutils.Context(t), nil, 500_000, maxGasPrice) + gasPrice, gasLimit, err := estimator.GetFee(testutils.Context(t), nil, 500_000, maxGasPrice, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(500000), gasLimit) - assert.Equal(t, "41.5 gwei", gasPrice.Legacy.String()) + assert.Equal(t, "41.5 gwei", gasPrice.GasPrice.String()) assert.Equal(t, initialDefaultGasPrice, chain.Config().EVM().GasEstimator().PriceDefault().Int64()) // unchanged // BlockHistoryEstimator new blocks @@ -1359,11 +1359,11 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { h43.ParentHash = h42.Hash newHeads.TrySend(h43) - gomega.NewWithT(t).Eventually(func() string { - gasPrice, _, err := estimator.GetFee(testutils.Context(t), nil, 500000, maxGasPrice) + require.Eventually(t, func() bool { + gasPrice, _, err := estimator.GetFee(testutils.Context(t), nil, 500000, maxGasPrice, nil, nil) require.NoError(t, err) - return gasPrice.Legacy.String() - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("45 gwei")) + return gasPrice.GasPrice.String() == "45 gwei" + }, testutils.WaitTimeout(t), cltest.DBPollingInterval) } func triggerAllKeys(t *testing.T, app *cltest.TestApplication) { diff --git a/core/internal/features/ocr2/features_ocr2_plugin_test.go b/core/internal/features/ocr2/features_ocr2_plugin_test.go index 96a9f32e957..102f4188742 100644 --- a/core/internal/features/ocr2/features_ocr2_plugin_test.go +++ b/core/internal/features/ocr2/features_ocr2_plugin_test.go @@ -6,9 +6,11 @@ import ( "testing" "github.com/smartcontractkit/chainlink/v2/core/config/env" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func TestIntegration_OCR2_plugins(t *testing.T) { t.Setenv(string(env.MedianPlugin.Cmd), "chainlink-feeds") + testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCF-3417") testIntegration_OCR2(t) } diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index d0f157d8bd4..9160310261f 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -43,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -54,6 +53,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) type ocr2Node struct { diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 40f5eee994f..5d8a110cdd3 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -64,19 +64,26 @@ type TestChainOpts struct { GasEstimator gas.EvmFeeEstimator } -// NewChainRelayExtenders returns a simple chain collection with one chain and +// NewLegacyChainsAndConfig returns a simple chain collection with one chain and // allows to mock client/config on that chain -func NewChainRelayExtenders(t testing.TB, testopts TestChainOpts) *evmrelay.ChainRelayerExtenders { - opts := NewChainRelayExtOpts(t, testopts) - cc, err := evmrelay.NewChainRelayerExtenders(testutils.Context(t), opts) +func NewLegacyChainsAndConfig(t testing.TB, testopts TestChainOpts) *evmrelay.LegacyChainsAndConfig { + opts := NewChainOpts(t, testopts) + cc, err := evmrelay.NewLegacyChainsAndConfig(testutils.Context(t), opts) require.NoError(t, err) return cc } -func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainRelayExtenderConfig { +func NewLegacyChains(t testing.TB, testopts TestChainOpts) *legacyevm.LegacyChains { + opts := NewChainOpts(t, testopts) + cc, err := evmrelay.NewLegacyChainsAndConfig(testutils.Context(t), opts) + require.NoError(t, err) + return cc.NewLegacyChains() +} + +func NewChainOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainRelayOpts { require.NotNil(t, testopts.KeyStore) lggr := logger.TestLogger(t) - opts := legacyevm.ChainRelayExtenderConfig{ + opts := legacyevm.ChainRelayOpts{ Logger: lggr, KeyStore: testopts.KeyStore, ChainOpts: legacyevm.ChainOpts{ diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index 45609488b46..0504570365b 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -342,9 +342,14 @@ func IntToHex(n int) string { // risk of spamming const TestInterval = 100 * time.Millisecond -// AssertEventually waits for f to return true -func AssertEventually(t *testing.T, f func() bool) { - assert.Eventually(t, f, WaitTimeout(t), TestInterval/2) +// AssertEventually calls assert.Eventually with default wait and tick durations. +func AssertEventually(t *testing.T, f func() bool) bool { + return assert.Eventually(t, f, WaitTimeout(t), TestInterval/2) +} + +// RequireEventually calls assert.Eventually with default wait and tick durations. +func RequireEventually(t *testing.T, f func() bool) { + require.Eventually(t, f, WaitTimeout(t), TestInterval/2) } // RequireLogMessage fails the test if emitted logs don't contain the given message @@ -368,7 +373,7 @@ func RequireLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg st // observedZapCore, observedLogs := observer.New(zap.DebugLevel) // lggr := logger.TestLogger(t, observedZapCore) func WaitForLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg string) (le observer.LoggedEntry) { - AssertEventually(t, func() bool { + RequireEventually(t, func() bool { for _, l := range observedLogs.All() { if strings.Contains(l.Message, msg) { le = l @@ -380,10 +385,23 @@ func WaitForLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg st return } +func WaitForLogMessageWithField(t *testing.T, observedLogs *observer.ObservedLogs, msg, field, value string) (le observer.LoggedEntry) { + RequireEventually(t, func() bool { + for _, l := range observedLogs.All() { + if strings.Contains(l.Message, msg) && strings.Contains(l.ContextMap()[field].(string), value) { + le = l + return true + } + } + return false + }) + return +} + // WaitForLogMessageCount waits until at least count log message containing the // specified msg is emitted func WaitForLogMessageCount(t *testing.T, observedLogs *observer.ObservedLogs, msg string, count int) { - AssertEventually(t, func() bool { + RequireEventually(t, func() bool { i := 0 for _, l := range observedLogs.All() { if strings.Contains(l.Message, msg) { diff --git a/core/internal/testutils/wasmtest/wasm.go b/core/internal/testutils/wasmtest/wasm.go new file mode 100644 index 00000000000..056a40f56ce --- /dev/null +++ b/core/internal/testutils/wasmtest/wasm.go @@ -0,0 +1,38 @@ +package wasmtest + +import ( + "bytes" + "fmt" + "io" + "os" + "os/exec" + "testing" + + "github.com/andybalholm/brotli" + "github.com/stretchr/testify/require" +) + +func CreateTestBinary(outputPath, path string, compress bool, t *testing.T) []byte { + cmd := exec.Command("go", "build", "-o", path, fmt.Sprintf("github.com/smartcontractkit/chainlink/v2/%s", outputPath)) // #nosec + cmd.Env = append(os.Environ(), "GOOS=wasip1", "GOARCH=wasm") + + output, err := cmd.CombinedOutput() + require.NoError(t, err, string(output)) + + binary, err := os.ReadFile(path) + require.NoError(t, err) + + if !compress { + return binary + } + + var b bytes.Buffer + bwr := brotli.NewWriter(&b) + _, err = bwr.Write(binary) + require.NoError(t, err) + require.NoError(t, bwr.Close()) + + cb, err := io.ReadAll(&b) + require.NoError(t, err) + return cb +} diff --git a/core/monitoring/monitoring.go b/core/monitoring/monitoring.go new file mode 100644 index 00000000000..c1c9cf8d86f --- /dev/null +++ b/core/monitoring/monitoring.go @@ -0,0 +1,115 @@ +package monitoring + +import ( + "context" + "fmt" + + "google.golang.org/protobuf/proto" + + "github.com/smartcontractkit/chainlink-common/pkg/beholder" + beholderpb "github.com/smartcontractkit/chainlink-common/pkg/beholder/pb" + "github.com/smartcontractkit/chainlink-common/pkg/values" +) + +type CustomMessageLabeler struct { + labels map[string]string +} + +func NewCustomMessageLabeler() CustomMessageLabeler { + return CustomMessageLabeler{labels: make(map[string]string)} +} + +// With adds multiple key-value pairs to the CustomMessageLabeler for transmission With SendLogAsCustomMessage +func (c CustomMessageLabeler) With(keyValues ...string) CustomMessageLabeler { + newCustomMessageLabeler := NewCustomMessageLabeler() + + if len(keyValues)%2 != 0 { + // If an odd number of key-value arguments is passed, return the original CustomMessageLabeler unchanged + return c + } + + // Copy existing labels from the current agent + for k, v := range c.labels { + newCustomMessageLabeler.labels[k] = v + } + + // Add new key-value pairs + for i := 0; i < len(keyValues); i += 2 { + key := keyValues[i] + value := keyValues[i+1] + newCustomMessageLabeler.labels[key] = value + } + + return newCustomMessageLabeler +} + +// SendLogAsCustomMessage emits a BaseMessage With msg and labels as data. +// any key in labels that is not part of orderedLabelKeys will not be transmitted +func (c CustomMessageLabeler) SendLogAsCustomMessage(msg string) error { + return sendLogAsCustomMessageW(msg, c.labels) +} + +type MetricsLabeler struct { + Labels map[string]string +} + +func NewMetricsLabeler() MetricsLabeler { + return MetricsLabeler{Labels: make(map[string]string)} +} + +// With adds multiple key-value pairs to the CustomMessageLabeler for transmission With SendLogAsCustomMessage +func (c MetricsLabeler) With(keyValues ...string) MetricsLabeler { + newCustomMetricsLabeler := NewMetricsLabeler() + + if len(keyValues)%2 != 0 { + // If an odd number of key-value arguments is passed, return the original CustomMessageLabeler unchanged + return c + } + + // Copy existing labels from the current agent + for k, v := range c.Labels { + newCustomMetricsLabeler.Labels[k] = v + } + + // Add new key-value pairs + for i := 0; i < len(keyValues); i += 2 { + key := keyValues[i] + value := keyValues[i+1] + newCustomMetricsLabeler.Labels[key] = value + } + + return newCustomMetricsLabeler +} + +func sendLogAsCustomMessageW(msg string, labels map[string]string) error { + // cast to map[string]any + newLabels := map[string]any{} + for k, v := range labels { + newLabels[k] = v + } + + m, err := values.NewMap(newLabels) + if err != nil { + return fmt.Errorf("could not wrap labels to map: %w", err) + } + + // Define a custom protobuf payload to emit + payload := &beholderpb.BaseMessage{ + Msg: msg, + Labels: values.ProtoMap(m), + } + payloadBytes, err := proto.Marshal(payload) + if err != nil { + return fmt.Errorf("sending custom message failed to marshal protobuf: %w", err) + } + + err = beholder.GetEmitter().Emit(context.Background(), payloadBytes, + "beholder_data_schema", "/beholder-base-message/versions/1", // required + "beholder_data_type", "custom_message", + ) + if err != nil { + return fmt.Errorf("sending custom message failed on emit: %w", err) + } + + return nil +} diff --git a/core/monitoring/monitoring_test.go b/core/monitoring/monitoring_test.go new file mode 100644 index 00000000000..7c79c89b1d8 --- /dev/null +++ b/core/monitoring/monitoring_test.go @@ -0,0 +1,16 @@ +package monitoring + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// tests CustomMessageAgent does not share state across new instances created by `With` +func Test_CustomMessageAgent(t *testing.T) { + cma := NewCustomMessageLabeler() + cma1 := cma.With("key1", "value1") + cma2 := cma1.With("key2", "value2") + + assert.NotEqual(t, cma1.labels, cma2.labels) +} diff --git a/core/monitoring/utils.go b/core/monitoring/utils.go new file mode 100644 index 00000000000..ddff32542ee --- /dev/null +++ b/core/monitoring/utils.go @@ -0,0 +1,11 @@ +package monitoring + +import "go.opentelemetry.io/otel/attribute" + +func KvMapToOtelAttributes(kvmap map[string]string) []attribute.KeyValue { + otelKVs := make([]attribute.KeyValue, 0, len(kvmap)) + for k, v := range kvmap { + otelKVs = append(otelKVs, attribute.String(k, v)) + } + return otelKVs +} diff --git a/core/monitoring/utils_test.go b/core/monitoring/utils_test.go new file mode 100644 index 00000000000..878f927890c --- /dev/null +++ b/core/monitoring/utils_test.go @@ -0,0 +1,49 @@ +package monitoring + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/otel/attribute" +) + +func TestKvMapToOtelAttributes(t *testing.T) { + tests := []struct { + name string + input map[string]string + expected []attribute.KeyValue + }{ + { + name: "empty map", + input: map[string]string{}, + expected: []attribute.KeyValue{}, + }, + { + name: "single key-value pair", + input: map[string]string{ + "key1": "value1", + }, + expected: []attribute.KeyValue{ + attribute.String("key1", "value1"), + }, + }, + { + name: "multiple key-value pairs", + input: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + expected: []attribute.KeyValue{ + attribute.String("key1", "value1"), + attribute.String("key2", "value2"), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := KvMapToOtelAttributes(tt.input) + assert.ElementsMatch(t, tt.expected, result, "unexpected KeyValue slice") + }) + } +} diff --git a/core/scripts/chaincli/DEBUGGING.md b/core/scripts/chaincli/DEBUGGING.md index 3696b225cb6..d032228f3ce 100644 --- a/core/scripts/chaincli/DEBUGGING.md +++ b/core/scripts/chaincli/DEBUGGING.md @@ -6,6 +6,9 @@ Use this script to debug and diagnose possible issues with registered upkeeps in Before starting, you will need: +- An archival RPC URL (required) and Tenderly credential (optional) + In order to get an archive URL, it's recommended to go to your Infura or Alchemy account (free tier should do) and get + a RPC URL. - A registered [upkeep](https://docs.chain.link/chainlink-automation/overview/getting-started) - A working [Go](https://go.dev/doc/install) installation, please use this Go [version](https://github.com/smartcontractkit/chainlink/blob/develop/go.mod#L3) diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index eac3233ea58..e60bc8749ff 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -24,6 +24,8 @@ import ( ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" + "github.com/smartcontractkit/chainlink/v2/core/cbor" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" @@ -43,9 +45,14 @@ import ( const ( ConditionTrigger uint8 = iota LogTrigger - expectedTypeAndVersion = "KeeperRegistry 2.1.0" + expectedVersion21 = "KeeperRegistry 2.1.0" + expectedVersion23 = "AutomationRegistry 2.3.0" ) +type UpkeepOffchainConfig struct { + MaxGasPrice *big.Int `json:"maxGasPrice" cbor:"maxGasPrice"` +} + var mercuryPacker = mercury.NewAbiPacker() var packer = encoding.NewAbiPacker() @@ -85,8 +92,8 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failCheckConfig("failed to get typeAndVersion: make sure your registry contract address and archive node are valid", err) } - if typeAndVersion != expectedTypeAndVersion { - failCheckConfig(fmt.Sprintf("invalid registry contract: this command can only debug %s, got: %s", expectedTypeAndVersion, typeAndVersion), nil) + if typeAndVersion != expectedVersion21 && typeAndVersion != expectedVersion23 { + failCheckConfig(fmt.Sprintf("invalid registry contract: this command can only debug %s or %s, got: %s", expectedVersion21, expectedVersion23, typeAndVersion), nil) } // get upkeepID from command args upkeepID := big.NewInt(0) @@ -134,6 +141,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { // do basic checks upkeepInfo = getUpkeepInfoAndRunBasicChecks(v2common, triggerCallOpts, upkeepID, chainID) + cgp, mgp := getGasPrice(ctx, k, upkeepInfo) + log.Printf("CURRENT gas price (you cannot call eth_gasPrice on any non latest block) is %s, this upkeep's MAX gas price is %s\n", cgp, mgp) + log.Printf("If upkeep's max gas price (if configured) is lower than the gas price when this upkeep was previously checked, the simulation will fail and this upkeep won't be performed.\n") + var tmpCheckResult autov2common.CheckUpkeep0 tmpCheckResult, err = v2common.CheckUpkeep0(triggerCallOpts, upkeepID) if err != nil { @@ -208,6 +219,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { // do basic checks upkeepInfo = getUpkeepInfoAndRunBasicChecks(v2common, triggerCallOpts, upkeepID, chainID) + cgp, mgp := getGasPrice(ctx, k, upkeepInfo) + log.Printf("CURRENT gas price (you cannot call eth_gasPrice on any non latest block) is %s, this upkeep's MAX gas price is %s\n", cgp, mgp) + log.Printf("If upkeep's max gas price (if configured) is lower than the gas price when this upkeep was previously checked, the simulation will fail and this upkeep won't be performed.\n") + var rawTriggerConfig []byte rawTriggerConfig, err = v2common.GetUpkeepTriggerConfig(triggerCallOpts, upkeepID) if err != nil { @@ -386,6 +401,36 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { } } +func getGasPrice(ctx context.Context, k *Keeper, upkeepInfo autov2common.IAutomationV21PlusCommonUpkeepInfoLegacy) (*assets.Wei, *assets.Wei) { + var cgp *assets.Wei + var err error + var gp *big.Int + // get gas price, eth_gasPrice does not take arguments, so we cannot access gas price at an older block + gp, err = k.client.SuggestGasPrice(ctx) + if err != nil { + log.Printf("⚠️ failed to get current gas price due to %v", err) + } else { + cgp = assets.NewWei(gp) + log.Printf("current gas price is %s", cgp) + } + + var mgp *assets.Wei + // check if max gas price is configured + if len(upkeepInfo.OffchainConfig) != 0 { + var offchainConfig UpkeepOffchainConfig + err := cbor.ParseDietCBORToStruct(upkeepInfo.OffchainConfig, &offchainConfig) + if err != nil { + log.Printf("failed to parse offchain config bytes to max gas price\n") + } else { + mgp = assets.NewWei(offchainConfig.MaxGasPrice) + } + } else { + log.Printf("offchain config is not configured for this upkeep\n") + } + + return cgp, mgp +} + func getUpkeepInfoAndRunBasicChecks(keeperRegistry21 *autov2common.IAutomationV21PlusCommon, callOpts *bind.CallOpts, upkeepID *big.Int, chainID int64) autov2common.IAutomationV21PlusCommonUpkeepInfoLegacy { // get upkeep info upkeepInfo, err := keeperRegistry21.GetUpkeep(callOpts, upkeepID) diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go index a5b6798836a..d40ee84a312 100644 --- a/core/scripts/chaincli/handler/handler.go +++ b/core/scripts/chaincli/handler/handler.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" @@ -242,7 +243,7 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain var out io.ReadCloser if _, _, err = dockerClient.ImageInspectWithRaw(ctx, h.cfg.PostgresDockerImage); err != nil { log.Println("Pulling Postgres docker image...") - if out, err = dockerClient.ImagePull(ctx, h.cfg.PostgresDockerImage, types.ImagePullOptions{}); err != nil { + if out, err = dockerClient.ImagePull(ctx, h.cfg.PostgresDockerImage, image.PullOptions{}); err != nil { return "", nil, fmt.Errorf("failed to pull Postgres image: %w", err) } out.Close() @@ -298,7 +299,7 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain } // Start container - if err = dockerClient.ContainerStart(ctx, dbContainerResp.ID, types.ContainerStartOptions{}); err != nil { + if err = dockerClient.ContainerStart(ctx, dbContainerResp.ID, container.StartOptions{}); err != nil { return "", nil, fmt.Errorf("failed to start DB container: %w", err) } log.Println("Postgres docker container successfully created and started: ", dbContainerResp.ID) @@ -315,7 +316,7 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain // Pull node image if needed if _, _, err = dockerClient.ImageInspectWithRaw(ctx, h.cfg.ChainlinkDockerImage); err != nil { log.Println("Pulling node docker image...") - if out, err = dockerClient.ImagePull(ctx, h.cfg.ChainlinkDockerImage, types.ImagePullOptions{}); err != nil { + if out, err = dockerClient.ImagePull(ctx, h.cfg.ChainlinkDockerImage, image.PullOptions{}); err != nil { return "", nil, fmt.Errorf("failed to pull node image: %w", err) } out.Close() @@ -392,7 +393,7 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain } // Start container - if err = dockerClient.ContainerStart(ctx, nodeContainerResp.ID, types.ContainerStartOptions{}); err != nil { + if err = dockerClient.ContainerStart(ctx, nodeContainerResp.ID, container.StartOptions{}); err != nil { return "", nil, fmt.Errorf("failed to start node container: %w", err) } @@ -411,7 +412,7 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain if writeLogs { var rdr io.ReadCloser - rdr, err2 := dockerClient.ContainerLogs(ctx, nodeContainerResp.ID, types.ContainerLogsOptions{ + rdr, err2 := dockerClient.ContainerLogs(ctx, nodeContainerResp.ID, container.LogsOptions{ ShowStderr: true, Timestamps: true, }) @@ -440,21 +441,21 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain if err2 := dockerClient.ContainerStop(ctx, nodeContainerResp.ID, container.StopOptions{}); err2 != nil { log.Fatal("Failed to stop node container: ", err2) } - if err2 := dockerClient.ContainerRemove(ctx, nodeContainerResp.ID, types.ContainerRemoveOptions{}); err2 != nil { + if err2 := dockerClient.ContainerRemove(ctx, nodeContainerResp.ID, container.RemoveOptions{}); err2 != nil { log.Fatal("Failed to remove node container: ", err2) } if err2 := dockerClient.ContainerStop(ctx, dbContainerResp.ID, container.StopOptions{}); err2 != nil { log.Fatal("Failed to stop DB container: ", err2) } - if err2 := dockerClient.ContainerRemove(ctx, dbContainerResp.ID, types.ContainerRemoveOptions{}); err2 != nil { + if err2 := dockerClient.ContainerRemove(ctx, dbContainerResp.ID, container.RemoveOptions{}); err2 != nil { log.Fatal("Failed to remove DB container: ", err2) } }, nil } func checkAndRemoveContainer(ctx context.Context, dockerClient *client.Client, containerName string) error { - opts := types.ContainerListOptions{ + opts := container.ListOptions{ Filters: filters.NewArgs(filters.Arg("name", "^/"+regexp.QuoteMeta(containerName)+"$")), } @@ -466,7 +467,7 @@ func checkAndRemoveContainer(ctx context.Context, dockerClient *client.Client, c if len(containers) > 1 { log.Fatal("more than two containers with the same name should not happen") } else if len(containers) > 0 { - if err := dockerClient.ContainerRemove(ctx, containers[0].ID, types.ContainerRemoveOptions{ + if err := dockerClient.ContainerRemove(ctx, containers[0].ID, container.RemoveOptions{ Force: true, }); err != nil { return fmt.Errorf("failed to remove existing container: %w", err) diff --git a/core/scripts/chaincli/handler/keeper_deployer.go b/core/scripts/chaincli/handler/keeper_deployer.go index 9e5a791d6c4..f0689a176de 100644 --- a/core/scripts/chaincli/handler/keeper_deployer.go +++ b/core/scripts/chaincli/handler/keeper_deployer.go @@ -169,6 +169,7 @@ func (d *v20KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactO S, // s []int, oracleIdentities, // oracles []OracleIdentityExtra, offC, // reportingPluginConfig []byte, + nil, 20*time.Millisecond, // maxDurationQuery time.Duration, 1600*time.Millisecond, // maxDurationObservation time.Duration, 800*time.Millisecond, // maxDurationReport time.Duration, sum of MaxDurationQuery/Observation/Report must be less than DeltaProgress @@ -312,6 +313,7 @@ func (d *v21KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactO S, // s []int, oracleIdentities, // oracles []OracleIdentityExtra, offC, // reportingPluginConfig []byte, + nil, 20*time.Millisecond, // maxDurationQuery time.Duration, 1600*time.Millisecond, // maxDurationObservation time.Duration, 20*time.Millisecond, // maxDurationShouldAcceptFinalizedReport time.Duration, diff --git a/core/scripts/chaincli/handler/logs.go b/core/scripts/chaincli/handler/logs.go index 7e4357680b0..779d91a2639 100644 --- a/core/scripts/chaincli/handler/logs.go +++ b/core/scripts/chaincli/handler/logs.go @@ -14,7 +14,7 @@ import ( "sync" "syscall" - "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" ) @@ -34,7 +34,7 @@ func (k *Keeper) streamLogs(ctx context.Context, pattern string, grep, vgrep []s return } - allContainers, err := dockerClient.ContainerList(ctx, types.ContainerListOptions{ + allContainers, err := dockerClient.ContainerList(ctx, container.ListOptions{ All: true, }) if err != nil { @@ -80,7 +80,7 @@ func (k *Keeper) streamLogs(ctx context.Context, pattern string, grep, vgrep []s } func (k *Keeper) containerLogs(ctx context.Context, cli *client.Client, containerID string, logsChan chan<- string, grep, vgrep []string) { - out, err := cli.ContainerLogs(ctx, containerID, types.ContainerLogsOptions{ + out, err := cli.ContainerLogs(ctx, containerID, container.LogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, diff --git a/core/scripts/functions/src/generate_ocr2_config_cmd.go b/core/scripts/functions/src/generate_ocr2_config_cmd.go index 7ac3b68d11d..11fd2198a8e 100644 --- a/core/scripts/functions/src/generate_ocr2_config_cmd.go +++ b/core/scripts/functions/src/generate_ocr2_config_cmd.go @@ -251,6 +251,7 @@ func (g *generateOCR2Config) Run(args []string) { cfg.TransmissionSchedule, identities, reportingPluginConfigBytes, + nil, time.Duration(cfg.MaxDurationQueryMillis)*time.Millisecond, time.Duration(cfg.MaxDurationObservationMillis)*time.Millisecond, time.Duration(cfg.MaxDurationReportMillis)*time.Millisecond, diff --git a/core/scripts/gateway/connector/run_connector.go b/core/scripts/gateway/connector/run_connector.go index 8d74bb88aec..2a2445c1d92 100644 --- a/core/scripts/gateway/connector/run_connector.go +++ b/core/scripts/gateway/connector/run_connector.go @@ -69,7 +69,13 @@ func main() { sampleKey, _ := crypto.HexToECDSA("cd47d3fafdbd652dd2b66c6104fa79b372c13cb01f4a4fbfc36107cce913ac1d") lggr, _ := logger.NewLogger() client := &client{privateKey: sampleKey, lggr: lggr} - connector, _ := connector.NewGatewayConnector(&cfg, client, client, clockwork.NewRealClock(), lggr) + // client acts as a signer here + connector, _ := connector.NewGatewayConnector(&cfg, client, clockwork.NewRealClock(), lggr) + err = connector.AddHandler([]string{"test_method"}, client) + if err != nil { + fmt.Println("error adding handler:", err) + return + } client.connector = connector ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt) diff --git a/core/scripts/gateway/run_gateway.go b/core/scripts/gateway/run_gateway.go index 2daca5190a5..5dbcd02bf56 100644 --- a/core/scripts/gateway/run_gateway.go +++ b/core/scripts/gateway/run_gateway.go @@ -48,7 +48,7 @@ func main() { lggr, _ := logger.NewLogger() - handlerFactory := gateway.NewHandlerFactory(nil, nil, lggr) + handlerFactory := gateway.NewHandlerFactory(nil, nil, nil, lggr) gw, err := gateway.NewGatewayFromConfig(&cfg, handlerFactory, lggr) if err != nil { fmt.Println("error creating Gateway object:", err) diff --git a/core/scripts/gateway/web_api_trigger/invoke_trigger.go b/core/scripts/gateway/web_api_trigger/invoke_trigger.go new file mode 100644 index 00000000000..b06f4db74cf --- /dev/null +++ b/core/scripts/gateway/web_api_trigger/invoke_trigger.go @@ -0,0 +1,156 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "flag" + "fmt" + "io" + "net/http" + "os" + "time" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/joho/godotenv" + + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" +) + +// https://gateway-us-1.chain.link/web-api-trigger +// { +// jsonrpc: "2.0", +// id: "...", +// method: "web-api-trigger", +// params: { +// signature: "...", +// body: { +// don_id: "workflow_123", +// payload: { +// trigger_id: "web-api-trigger@1.0.0", +// trigger_event_id: "action_1234567890", +// timestamp: 1234567890, +// sub-events: [ +// { +// topics: ["daily_price_update"], +// params: { +// bid: "101", +// ask: "102" +// } +// }, +// { +// topics: ["daily_message", "summary"], +// params: { +// message: "all good!", +// } +// }, +// ] +// } +// } +// } +// } + +func main() { + gatewayURL := flag.String("gateway_url", "http://localhost:5002", "Gateway URL") + privateKey := flag.String("private_key", "65456ffb8af4a2b93959256a8e04f6f2fe0943579fb3c9c3350593aabb89023f", "Private key to sign the message with") + messageID := flag.String("id", "12345", "Request ID") + methodName := flag.String("method", "web_api_trigger", "Method name") + donID := flag.String("don_id", "workflow_don_1", "DON ID") + + flag.Parse() + + if privateKey == nil || *privateKey == "" { + if err := godotenv.Load(); err != nil { + panic(err) + } + + privateKeyEnvVar := os.Getenv("PRIVATE_KEY") + privateKey = &privateKeyEnvVar + fmt.Println("Loaded private key from .env") + } + + // validate key and extract address + key, err := crypto.HexToECDSA(*privateKey) + if err != nil { + fmt.Println("error parsing private key", err) + return + } + + address := crypto.PubkeyToAddress(key.PublicKey) + fmt.Printf("Public Address: %s\n", address.Hex()) + + payload := map[string]any{ + "trigger_id": "web-api-trigger@1.0.0", + "trigger_event_id": "action_1234567890", + "timestamp": int(time.Now().Unix()), + "topics": []string{"daily_price_update"}, + "params": map[string]string{ + "bid": "101", + "ask": "102", + }, + } + + payloadJSON, err := json.Marshal(payload) + if err != nil { + fmt.Println("error marshalling JSON payload", err) + return + } + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: *messageID, + Method: *methodName, + DonId: *donID, + Payload: payloadJSON, + }, + } + if err = msg.Sign(key); err != nil { + fmt.Println("error signing message", err) + return + } + + codec := api.JsonRPCCodec{} + rawMsg, err := codec.EncodeRequest(msg) + if err != nil { + fmt.Println("error JSON-RPC encoding", err) + return + } + + createRequest := func() (req *http.Request, err error) { + req, err = http.NewRequestWithContext(context.Background(), "POST", *gatewayURL, bytes.NewBuffer(rawMsg)) + if err == nil { + req.Header.Set("Content-Type", "application/json") + } + return + } + + client := &http.Client{} + + sendRequest := func() { + req, err2 := createRequest() + if err2 != nil { + fmt.Println("error creating a request", err2) + return + } + + resp, err2 := client.Do(req) + if err2 != nil { + fmt.Println("error sending a request", err2) + return + } + defer resp.Body.Close() + + body, err2 := io.ReadAll(resp.Body) + if err2 != nil { + fmt.Println("error sending a request", err2) + return + } + + var prettyJSON bytes.Buffer + if err2 = json.Indent(&prettyJSON, body, "", " "); err2 != nil { + fmt.Println(string(body)) + } else { + fmt.Println(prettyJSON.String()) + } + } + sendRequest() +} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 9f1844693c9..4a2e8ff7d2b 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -1,66 +1,72 @@ module github.com/smartcontractkit/chainlink/core/scripts -go 1.22.5 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ +replace github.com/smartcontractkit/chainlink/integration-tests => ../../integration-tests + require ( - github.com/docker/docker v24.0.7+incompatible - github.com/docker/go-connections v0.4.0 + github.com/docker/docker v27.3.1+incompatible + github.com/docker/go-connections v0.5.0 github.com/ethereum/go-ethereum v1.13.8 github.com/gkampitakis/go-snaps v0.5.4 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/jmoiron/sqlx v1.4.0 - github.com/joho/godotenv v1.4.0 + github.com/joho/godotenv v1.5.1 github.com/jonboulle/clockwork v0.4.0 github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f github.com/montanaflynn/stats v0.7.1 github.com/olekukonko/tablewriter v0.0.5 - github.com/pelletier/go-toml/v2 v2.2.0 - github.com/prometheus/client_golang v1.17.0 + github.com/pelletier/go-toml/v2 v2.2.2 + github.com/prometheus/client_golang v1.20.0 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 + github.com/smartcontractkit/chainlink-automation v0.8.0 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/spf13/cobra v1.8.0 - github.com/spf13/viper v1.15.0 + github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 github.com/umbracle/ethgo v0.1.3 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 github.com/urfave/cli v1.22.14 - google.golang.org/protobuf v1.34.2 - k8s.io/api v0.30.0 - k8s.io/apimachinery v0.30.0 - k8s.io/client-go v0.30.0 + google.golang.org/protobuf v1.35.1 + k8s.io/api v0.31.0 + k8s.io/apimachinery v0.31.0 + k8s.io/client-go v0.31.0 ) 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.3 // indirect - cosmossdk.io/errors v1.0.0 // indirect - cosmossdk.io/math v1.0.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/math v1.3.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/Depado/ginprom v1.8.0 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NethermindEth/juno v0.3.1 // indirect github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect + github.com/andybalholm/brotli v1.1.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/avast/retry-go/v4 v4.6.0 // indirect + github.com/aws/aws-sdk-go v1.54.19 // 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 @@ -68,8 +74,8 @@ require ( github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect @@ -77,26 +83,26 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/errors v1.10.0 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.37.2 // indirect - github.com/cometbft/cometbft-db v0.7.0 // indirect + github.com/cometbft/cometbft v0.37.5 // indirect + github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect - github.com/cosmos/cosmos-sdk v0.47.4 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/cosmos-sdk v0.47.11 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogoproto v1.4.11 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.0.1 // indirect - github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cosmos/iavl v0.20.1 // indirect + github.com/cosmos/ibc-go/v7 v7.5.1 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect @@ -108,25 +114,27 @@ require ( 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 + github.com/distribution/reference v0.6.0 // indirect 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/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/esote/minmaxheap v1.0.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/fatih/color v1.16.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fxamacker/cbor/v2 v2.6.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect + 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/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/gagliardetto/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect - github.com/getsentry/sentry-go v0.19.0 // indirect + github.com/getsentry/sentry-go v0.23.0 // indirect github.com/gin-contrib/cors v1.5.0 // indirect github.com/gin-contrib/expvar v0.0.1 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect @@ -143,52 +151,54 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + 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.15.5 // indirect + github.com/go-playground/validator/v10 v10.22.0 // 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 github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect - github.com/golang-jwt/jwt/v5 v5.2.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.1 // 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 - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect + github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect - github.com/grafana/pyroscope-go v1.1.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect + github.com/grafana/pyroscope-go v1.1.2 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/graph-gophers/dataloader v5.0.0+incompatible // indirect - github.com/graph-gophers/graphql-go v1.3.0 // indirect + github.com/graph-gophers/graphql-go v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect 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/hashicorp/consul/sdk v0.16.0 // indirect + github.com/hashicorp/consul/sdk v0.16.1 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect - github.com/hashicorp/go-retryablehttp v0.7.5 // indirect + github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -197,6 +207,7 @@ require ( github.com/holiman/uint256 v1.2.4 // indirect github.com/huandu/skiplist v1.2.0 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect @@ -209,19 +220,21 @@ require ( github.com/jackc/pgtype v1.14.0 // indirect github.com/jackc/pgx/v4 v4.18.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.3 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect - github.com/leodido/go-urn v1.2.4 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -229,23 +242,23 @@ require ( 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/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mfridman/interpolate v0.0.2 // 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 + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc5 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect 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 @@ -254,42 +267,48 @@ require ( 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.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/prometheus/prometheus v0.48.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.59.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/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.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/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/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f // indirect - github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.7.3 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect + github.com/smartcontractkit/chain-selectors v1.0.27 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect + github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // 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 + github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/jwalterweatherman v1.1.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/stretchr/objx v0.5.2 // indirect - github.com/subosito/gotenv v1.4.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // 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 @@ -310,52 +329,62 @@ require ( github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect - go.etcd.io/bbolt v1.3.7 // 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.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.4.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.4.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/time v0.6.0 // indirect + golang.org/x/tools v0.25.0 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/grpc v1.65.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/grpc v1.66.2 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect 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.120.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect - pgregory.net/rapid v0.5.5 // 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 + pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect @@ -366,10 +395,5 @@ replace ( // replicating the replace directive on cosmos SDK github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 - github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 - - // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 - github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - + github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264 ) diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 35226b0de3d..adfae8ff0d9 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -4,20 +4,12 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR 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.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= @@ -27,9 +19,6 @@ cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= @@ -41,13 +30,9 @@ cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNc cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -58,14 +43,14 @@ 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= cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= -cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca h1:msenprh2BLLRwNT7zN56TbBHOGk/7ARQckXHxXyvjoQ= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca/go.mod h1:PkIAKXZvaxrTRc++z53XMRvFk8AcGGWYHcMIPzVYX9c= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= +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= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -78,7 +63,6 @@ github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo8 github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= @@ -86,10 +70,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/CosmWasm/wasmd v0.40.1 h1:LxbO78t/6S8TkeQlUrJ0m5O87HtAwLx4RGHq3rdrOEU= github.com/CosmWasm/wasmd v0.40.1/go.mod h1:6EOwnv7MpuFaEqxcUOdFV9i4yvrdOciaY6VQ1o7A3yg= github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ= @@ -101,12 +83,11 @@ 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/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb h1:Mv8SscePPyw2ju4igIJAjFgcq5zCQfjgbz53DwYu5mc= @@ -116,18 +97,13 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= 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/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA= 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,6 +114,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax 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.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= @@ -147,13 +125,14 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQVoh6kY+c4b0HUchHjGWBI8288VhH50qxKG3hdEg0= +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.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= -github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +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/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= @@ -173,35 +152,19 @@ github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= 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= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= -github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 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/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.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= @@ -234,43 +197,39 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= -github.com/cockroachdb/apd/v3 v3.1.0/go.mod h1:6qgPBMXjATAdD/VefbRP9NoSLKjbB4LCoA7gN4LpHs4= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= +github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= -github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0= +github.com/cometbft/cometbft v0.37.5/go.mod h1:QC+mU0lBhKn8r9qvmnq53Dmf3DWBt4VtkcKw2C81wxY= +github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= +github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +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/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -282,10 +241,10 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 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.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.4 h1:FVUpEprm58nMmBX4xkRdMDaIG5Nr4yy92HZAfGAw9bg= -github.com/cosmos/cosmos-sdk v0.47.4/go.mod h1:R5n+uM7vguVPFap4pgkdvQCT1nVo/OtPwrlAU40rvok= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.47.11 h1:0Qx7eORw0RJqPv+mvDuU8NQ1LV3nJJKJnPoYblWHolc= +github.com/cosmos/cosmos-sdk v0.47.11/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -293,21 +252,21 @@ github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiK github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= -github.com/cosmos/ibc-go/v7 v7.0.1 h1:NIBNRWjlOoFvFQu1ZlgwkaSeHO5avf4C1YQiWegt8jw= -github.com/cosmos/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab h1:I9ialKTQo7248V827Bba4OuKPmk+FPzmTVHsLXaIJWw= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab/go.mod h1:2CwqasX5dSD7Hbp/9b6lhK6BwoBDCBldx7gPKRukR60= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= +github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/ibc-go/v7 v7.5.1 h1:KqS/g7W7EMX1OtOvufS8lWMJibOKpdgtNNZIU6fAgVU= +github.com/cosmos/ibc-go/v7 v7.5.1/go.mod h1:ktFg5GvKOyrGCqTWtW7Grj5uweU4ZapxrNeVS1CLLbo= +github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= +github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw= +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/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= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= @@ -316,35 +275,27 @@ 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/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/gherkin/go/v22 v22.0.0/go.mod h1:3mJT10B2GGn3MvVPd3FwR7m2u4tLhSRhWUqJU4KN4Fg= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= -github.com/cucumber/common/messages/go/v17 v17.1.1/go.mod h1:bpGxb57tDE385Rb2EohgUadLkAbhoC4IyCFi89u/JQI= 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= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e/go.mod h1:IJgIiGUARc4aOr4bOQ85klmjsShkEEfiRc6q/yBSfo8= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= 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.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= 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/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 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 v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 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= @@ -355,12 +306,14 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn 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= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= 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= @@ -370,36 +323,24 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= 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.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= @@ -411,12 +352,12 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +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/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= @@ -425,16 +366,14 @@ github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtL 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/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= 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/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= -github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= +github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= +github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= @@ -459,8 +398,6 @@ github.com/gkampitakis/go-snaps v0.5.4 h1:GX+dkKmVsRenz7SoTbdIEL4KQARZctkMiZ8ZKp github.com/gkampitakis/go-snaps v0.5.4/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -483,21 +420,20 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -508,41 +444,39 @@ 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.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +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-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= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6lpIc2g= github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= +github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= @@ -556,9 +490,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -566,7 +498,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -586,29 +517,25 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -616,8 +543,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -625,30 +550,23 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -661,18 +579,17 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX 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.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= -github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= +github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= +github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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= @@ -684,8 +601,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf 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.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -695,8 +612,8 @@ github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uM github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= 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= -github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= +github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= +github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= @@ -708,17 +625,18 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 h1:OSQYEsRT3tRttZkk6zyC3aAaliwd7Loi/KgXgXxGtwA= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= -github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= @@ -728,7 +646,6 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -762,12 +679,12 @@ github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -775,11 +692,6 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -829,19 +741,20 @@ 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 v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= 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.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +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= @@ -849,7 +762,6 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -858,30 +770,19 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 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.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -895,13 +796,11 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -910,6 +809,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= +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/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -927,12 +828,9 @@ 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.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 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.8/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.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -940,7 +838,6 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx 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.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 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= @@ -953,14 +850,9 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh 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= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= 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/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 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= @@ -974,6 +866,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -985,8 +879,10 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +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/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= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1001,7 +897,6 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= -github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= 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/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= @@ -1009,16 +904,12 @@ github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ib 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= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= 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-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= -github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= +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= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -1028,30 +919,25 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn 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= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 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.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= -github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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/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= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= -github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= -github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40= +github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -1066,8 +952,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 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= @@ -1078,7 +964,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1091,35 +977,33 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP 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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +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.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= 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.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= -github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= +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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= -github.com/regen-network/gocuke v0.6.2/go.mod h1:zYaqIHZobHyd0xOrHGPQjbhGJsuZ1oElx150u2o1xuk= 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/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -1134,33 +1018,35 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L 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= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= -github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= +github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +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= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= @@ -1180,63 +1066,67 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= -github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= -github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 h1:LAgJTg9Yr/uCo2g7Krp88Dco2U45Y6sbJVl8uKoLkys= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 h1:iT9xlcy7Q98F9QheClGBiU0Ig1A+0UhtFkEdKFHvX/0= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f h1:I9fTBJpHkeldFplXUy71eLIn6A6GxuR4xrABoUeD+CM= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f/go.mod h1:V/86loaFSH0dqqUEHqyXVbyNqDRSjvcf9BRomWFTljU= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 h1:BCHu4pNP6arrcHLEWx61XjLaonOd2coQNyL0NTUcaMc= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827/go.mod h1:OPX+wC2TWQsyLNpR7daMt2vMpmsNcoBxbZyGTHr6tiA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 h1:8ZzsGNhqYxmQ/QMO1fuXO7u9Vpl9YUvPJK+td/ZaBJA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564/go.mod h1:Ml88TJTwZCj6yHDkAEN/EhxVutzSlk+kDZgfibRIqF0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= -github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= +github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+30iWKL/sWq8uyiLHM8k= +github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chainlink-automation v0.8.0 h1:hFz2EHU06bkEfhcqhK8JdjKTWpDOr0XJ6xL9oELDoUg= +github.com/smartcontractkit/chainlink-automation v0.8.0/go.mod h1:ObdjDfgGIaiE48Bb3yYcx1CeGBm392WlEw92U83LlUA= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 h1:BS9i2P/b+PsomEP//bH4j6N2a1DCgLVVzoRw02CnN2s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 h1:qx5p01fqee86cj6EUOCzFc2zILw56v1Q3c5DUuEQWLs= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286/go.mod h1:tsGgeEJc5SUSlfVGSX0wR0EkRU3pM58D6SKF97V68ko= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= +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.4.0 h1:1xTm8UGeDUAjvCXRh08+4xBRX33owH5MqC522JdelM0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 h1:R8F2tpyvN0peK0woG/Spx+IdukxlSSWDDLyFQNkLfUs= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042/go.mod h1:UndTf1YRDBt/4LDauMFou9+vt/M0q6o7u80a9J5Xu+0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +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/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.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= 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/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= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 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.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +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= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +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= @@ -1248,6 +1138,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1258,20 +1149,16 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.2/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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= 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= @@ -1306,10 +1193,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2 github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= @@ -1327,14 +1212,10 @@ 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.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= 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/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= 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= @@ -1342,31 +1223,23 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY 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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= 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-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= 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= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -1377,8 +1250,8 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL 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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= 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= @@ -1399,18 +1272,36 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIX go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 h1:UiRNKd1OgqsLbFwE+wkAWTdiAxXtCBqKIHeBIse4FUA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9/go.mod h1:eqZlW3pJWhjyexnDPrdQxix1pn0wwhI4AO4GKpP/bMI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 h1:0MH3f8lZrflbUWXVxyBg/zviDFdGE062uKh5+fu8Vv0= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0/go.mod h1:Vh68vYiHY5mPdekTr0ox0sALsqjoVy0w3Os278yX5SQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 h1:BJee2iLkfRfl9lc7aFmBwkWxY/RI1RDdXepSF6y8TPE= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0/go.mod h1:DIzlHs3DRscCIBU3Y9YSzPfScwnYnzfnCd4g8zA7bZc= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o= +go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA= +go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= +go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -1441,13 +1332,11 @@ 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.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1456,26 +1345,21 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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-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.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1486,8 +1370,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-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= 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,7 +1385,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1510,14 +1393,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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/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= @@ -1528,64 +1408,45 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r 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= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1593,14 +1454,12 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1638,56 +1497,40 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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= @@ -1695,8 +1538,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1709,22 +1552,19 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1757,33 +1597,16 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= +golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= 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= @@ -1791,6 +1614,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1803,16 +1628,8 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1821,9 +1638,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 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= -google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1843,37 +1657,18 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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= @@ -1886,17 +1681,11 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1905,13 +1694,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1931,10 +1719,8 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a 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.51.1/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/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 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= @@ -1950,34 +1736,32 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= -k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= -k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= -k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= -k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= +k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= +k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= +k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= +k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= @@ -1995,8 +1779,8 @@ modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +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= diff --git a/core/scripts/keystone/src/01_deploy_contracts_cmd.go b/core/scripts/keystone/src/01_deploy_contracts_cmd.go index b3049737956..8c1032c6087 100644 --- a/core/scripts/keystone/src/01_deploy_contracts_cmd.go +++ b/core/scripts/keystone/src/01_deploy_contracts_cmd.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + ksdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" ) @@ -156,7 +157,7 @@ func deploy( func setOCR3Config( env helpers.Environment, - ocrConfig orc2drOracleConfig, + ocrConfig ksdeploy.Orc2drOracleConfig, artefacts string, ) { loadedContracts, err := LoadDeployedContracts(artefacts) 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 3352267d149..f4e394b7da5 100644 --- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -26,89 +26,142 @@ import ( ) type peer struct { - PeerID string - Signer string + PeerID string + Signer string + EncryptionPublicKey string } var ( workflowDonPeers = []peer{ { - PeerID: "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", - Signer: "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d", + PeerID: "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", + Signer: "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d", + EncryptionPublicKey: "0xe7f44e3eedf3527199efec7334183b5384ba0e7c7c57b390b63a3de5a10cd53c", }, { - PeerID: "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", - Signer: "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d", + PeerID: "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", + Signer: "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d", + EncryptionPublicKey: "0x315c6097f89baef3c3ae1503b801aaabf411134ffec66bbe8d1d184540588728", }, { - PeerID: "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", - Signer: "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C", + PeerID: "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", + Signer: "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C", + EncryptionPublicKey: "0xa7a5e118213552a939f310e19167f49e9ad952cfe9d51eaae1ad37d92d9f0583", }, { - PeerID: "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", - Signer: "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF", + PeerID: "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", + Signer: "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF", + EncryptionPublicKey: "0x75f75a86910eed0259e3107b3c368f72c0ad0301bac696fd340916e2437194c3", }, { - PeerID: "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97", - Signer: "0x8F572978673d711b2F061EB7d514BD46EAD6668A", + PeerID: "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97", + Signer: "0x8F572978673d711b2F061EB7d514BD46EAD6668A", + EncryptionPublicKey: "0xd032f1e884a22fd05151f59565f05a4ccbf984afccbbee13469fc25947e69360", }, { - PeerID: "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA", - Signer: "0x21eF07Dfaf8f7C10CB0d53D18b641ee690541f9D", + PeerID: "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA", + Signer: "0x21eF07Dfaf8f7C10CB0d53D18b641ee690541f9D", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", }, { - PeerID: "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX", - Signer: "0x7Fa21F6f716CFaF8f249564D72Ce727253186C89", + PeerID: "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX", + Signer: "0x7Fa21F6f716CFaF8f249564D72Ce727253186C89", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", }, } triggerDonPeers = []peer{ { - PeerID: "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m", - Signer: "0x9CcE7293a4Cc2621b61193135A95928735e4795F", + PeerID: "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m", + Signer: "0x9CcE7293a4Cc2621b61193135A95928735e4795F", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", }, { - PeerID: "12D3KooWS7JSY9fzSfWgbCE1S3W2LNY6ZVpRuun74moVBkKj6utE", - Signer: "0x3c775F20bCB2108C1A818741Ce332Bb5fe0dB925", + PeerID: "12D3KooWS7JSY9fzSfWgbCE1S3W2LNY6ZVpRuun74moVBkKj6utE", + Signer: "0x3c775F20bCB2108C1A818741Ce332Bb5fe0dB925", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", }, { - PeerID: "12D3KooWMMTDXcWhpVnwrdAer1jnVARTmnr3RyT3v7Djg8ZuoBh9", - Signer: "0x50314239e2CF05555ceeD53E7F47eB2A8Eab0dbB", + PeerID: "12D3KooWMMTDXcWhpVnwrdAer1jnVARTmnr3RyT3v7Djg8ZuoBh9", + Signer: "0x50314239e2CF05555ceeD53E7F47eB2A8Eab0dbB", + EncryptionPublicKey: "0xce0e88d12d568653757f1db154f9c503db3d3d7b37cb03d84b61f39f09824cc0", }, { - PeerID: "12D3KooWGzVXsKxXsF4zLgxSDM8Gzx1ywq2pZef4PrHMKuVg4K3P", - Signer: "0xd76A4f98898c3b9A72b244476d7337b50D54BCd8", + PeerID: "12D3KooWGzVXsKxXsF4zLgxSDM8Gzx1ywq2pZef4PrHMKuVg4K3P", + Signer: "0xd76A4f98898c3b9A72b244476d7337b50D54BCd8", + EncryptionPublicKey: "0xce0e88d12d568653757f1db154f9c503db3d3d7b37cb03d84b61f39f09824cc0", }, { - PeerID: "12D3KooWSyjmmzjVtCzwN7bXzZQFmWiJRuVcKBerNjVgL7HdLJBW", - Signer: "0x656A873f6895b8a03Fb112dE927d43FA54B2c92A", + PeerID: "12D3KooWSyjmmzjVtCzwN7bXzZQFmWiJRuVcKBerNjVgL7HdLJBW", + Signer: "0x656A873f6895b8a03Fb112dE927d43FA54B2c92A", + EncryptionPublicKey: "0x91f11910104ff55209d6d344a15eef6a222a54d4973aaebd301807444b555e3f", }, { - PeerID: "12D3KooWLGz9gzhrNsvyM6XnXS3JRkZoQdEzuAvysovnSChNK5ZK", - Signer: "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553", + PeerID: "12D3KooWLGz9gzhrNsvyM6XnXS3JRkZoQdEzuAvysovnSChNK5ZK", + Signer: "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553", + EncryptionPublicKey: "0x20ff771215e567cf7e9a1fea8f2d4df90adc8303794175f79893037ff8808b51", }, { - PeerID: "12D3KooWAvZnvknFAfSiUYjATyhzEJLTeKvAzpcLELHi4ogM3GET", - Signer: "0x91d9b0062265514f012Eb8fABA59372fD9520f56", + PeerID: "12D3KooWAvZnvknFAfSiUYjATyhzEJLTeKvAzpcLELHi4ogM3GET", + Signer: "0x91d9b0062265514f012Eb8fABA59372fD9520f56", + EncryptionPublicKey: "0x54176f154052068943569b676fa7eec7dc836e17bbe743ce56b1c7e205191d9c", }, } targetDonPeers = []peer{ { - PeerID: "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", - Signer: "0x3F82750353Ea7a051ec9bA011BC628284f9a5327", + PeerID: "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", + Signer: "0x3F82750353Ea7a051ec9bA011BC628284f9a5327", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", }, { - PeerID: "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", - Signer: "0xc23545876A208AA0443B1b8d552c7be4FF4b53F0", + PeerID: "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", + Signer: "0xc23545876A208AA0443B1b8d552c7be4FF4b53F0", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", }, { - PeerID: "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", - Signer: "0x82601Fa43d8B1dC1d4eB640451aC86a7CDA37011", + PeerID: "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", + Signer: "0x82601Fa43d8B1dC1d4eB640451aC86a7CDA37011", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", }, { - PeerID: "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", - Signer: "0x1a684B3d8f917fe496b7B1A8b29EDDAED64F649f", + PeerID: "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", + Signer: "0x1a684B3d8f917fe496b7B1A8b29EDDAED64F649f", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", }, } + + aptosTargetDonPeers = []peer{ + { + PeerID: "12D3KooWNBr1AD3vD3dzSLgg1tK56qyJoenDx7EYNnZpbr1g4jD6", + Signer: "a41f9a561ff2266d94240996a76f9c2b3b7d8184", + EncryptionPublicKey: "0xf28fcfaf2933289b3a98d387f6edf85853df32528c094dee9e737f4ca63e5a30", + }, + { + PeerID: "12D3KooWRRgWiZGw5GYsPa62CkwFNKJb5u4hWo4DinnvjG6GE6Nj", + Signer: "e4f3c7204776530fb7833db6f9dbfdb8bd0ec96892965324a71c20d6776f67f0", + EncryptionPublicKey: "0x49c837675372d8f430e69ccd91c43029600c2c6469a2f933c4a1c4bbbc974c6d", + }, + { + PeerID: "12D3KooWKwzgUHw5YbqUsYUVt3yiLSJcqc8ANofUtqHX6qTm7ox2", + Signer: "4071ea00e2e2c76b3406018ba9f66bf6b9aee3a6762e62ac823b1ee91ba7d7b0", + EncryptionPublicKey: "0x8fe005ef16d57091160c0b4373232e7389c321dff971fc0251a39e360d9ac34a", + }, + { + PeerID: "12D3KooWBRux5o2bw1j3SQwEHzCspjkt7Xe3Y3agRUuab2SUnExj", + Signer: "6f5180c7d276876dbe413bf9b0efff7301d1367f39f4bac64180090cab70989b", + EncryptionPublicKey: "0x90dd41db21351c06396761dd683a82c791cd71e536fce246e582a4ef058091ae", + }, + { + PeerID: "12D3KooWFqvDaMSDGa6eMSTF9en6G2c3ZbGLmaA5Xs3AgxVBPb8B", + Signer: "dbce9a6df8a04d54e52a109d01ee9b5d32873b1d2436cf7b7fae61fd6eca46f8", + EncryptionPublicKey: "0x87cf298dd236a307ea887cd5d81eb0b708e3dd48c984c0700bb26c072e427942", + }, + } + + defaultComputeModuleConfig = map[string]any{ + "defaultTickInterval": "100ms", + "defaultTimeout": "300ms", + "defaultMaxMemoryMBs": int64(64), + } ) type deployAndInitializeCapabilitiesRegistryCommand struct{} @@ -157,19 +210,49 @@ func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error 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, + NodeOperatorId: nopID, + P2pId: peerIDB, + Signer: sigb, + EncryptionPublicKey: encKeyB, }, nil } -func newCapabilityConfig() *capabilitiespb.CapabilityConfig { +// 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.Proto(values.EmptyMap()).GetMapValue(), + 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) { + return func(dc *values.Map) { + overrides, err := values.NewMap(m) + if err != nil { + panic(err) + } + for k, v := range overrides.Underlying { + dc.Underlying[k] = v + } } } @@ -226,6 +309,26 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(err) } + cronTrigger := kcr.CapabilitiesRegistryCapability{ + LabelledName: "cron-trigger", + Version: "1.0.0", + CapabilityType: uint8(0), // trigger + } + ctid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, cronTrigger.LabelledName, cronTrigger.Version) + if err != nil { + panic(err) + } + + computeAction := kcr.CapabilitiesRegistryCapability{ + LabelledName: "custom-compute", + Version: "1.0.0", + CapabilityType: uint8(1), // action + } + aid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, computeAction.LabelledName, computeAction.Version) + if err != nil { + panic(err) + } + writeChain := kcr.CapabilitiesRegistryCapability{ LabelledName: "write_ethereum-testnet-sepolia", Version: "1.0.0", @@ -236,6 +339,16 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { log.Printf("failed to call GetHashedCapabilityId: %s", err) } + aptosWriteChain := kcr.CapabilitiesRegistryCapability{ + LabelledName: "write_aptos", + Version: "1.0.0", + CapabilityType: uint8(3), // target + } + awid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, aptosWriteChain.LabelledName, aptosWriteChain.Version) + if err != nil { + log.Printf("failed to call GetHashedCapabilityId: %s", err) + } + ocr := kcr.CapabilitiesRegistryCapability{ LabelledName: "offchain_reporting", Version: "1.0.0", @@ -249,7 +362,10 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { tx, err := reg.AddCapabilities(env.Owner, []kcr.CapabilitiesRegistryCapability{ streamsTrigger, writeChain, + aptosWriteChain, ocr, + cronTrigger, + computeAction, }) if err != nil { log.Printf("failed to call AddCapabilities: %s", err) @@ -282,7 +398,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(innerErr) } - n.HashedCapabilityIds = [][32]byte{ocrid} + n.HashedCapabilityIds = [][32]byte{ocrid, ctid} nodes = append(nodes, n) } @@ -306,6 +422,16 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { nodes = append(nodes, n) } + for _, targetPeer := range aptosTargetDonPeers { + n, innerErr := peerToNode(nopID, targetPeer) + if innerErr != nil { + panic(innerErr) + } + + n.HashedCapabilityIds = [][32]byte{awid} + nodes = append(nodes, n) + } + tx, err = reg.AddNodes(env.Owner, nodes) if err != nil { log.Printf("failed to AddNodes: %s", err) @@ -325,11 +451,25 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(err) } + computeCfg := newCapabilityConfig(withDefaultConfig(defaultComputeModuleConfig)) + ccfgb, err := proto.Marshal(computeCfg) + if err != nil { + panic(err) + } + cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ { CapabilityId: ocrid, Config: ccb, }, + { + CapabilityId: ctid, + Config: ccb, + }, + { + CapabilityId: aid, + Config: ccfgb, + }, } _, err = reg.AddDON(env.Owner, ps, cfgs, true, true, 2) if err != nil { @@ -396,6 +536,35 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { if err != nil { log.Printf("targetDON: failed to AddDON: %s", err) } + + // Aptos target DON + ps, err = peers(aptosTargetDonPeers) + if err != nil { + panic(err) + } + + targetCapabilityConfig = newCapabilityConfig() + targetCapabilityConfig.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, + }, + } + + remoteTargetConfigBytes, err = proto.Marshal(targetCapabilityConfig) + if err != nil { + panic(err) + } + + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: awid, + Config: remoteTargetConfigBytes, + }, + } + _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) + if err != nil { + log.Printf("targetDON: failed to AddDON: %s", err) + } } func deployCapabilitiesRegistry(env helpers.Environment) *kcr.CapabilitiesRegistry { diff --git a/core/scripts/keystone/src/88_gen_jobspecs.go b/core/scripts/keystone/src/88_gen_jobspecs.go index 5f0b9097d2f..4199e3f2b89 100644 --- a/core/scripts/keystone/src/88_gen_jobspecs.go +++ b/core/scripts/keystone/src/88_gen_jobspecs.go @@ -7,6 +7,7 @@ import ( "strings" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + ksdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" ) type spec []string @@ -39,7 +40,7 @@ func genSpecs( bootstrapSpecLines, err := readLines(filepath.Join(templatesDir, bootstrapSpecTemplate)) helpers.PanicErr(err) - bootHost := nodes[0].url.Hostname() + bootHost := nodes[0].remoteURL.Hostname() bootstrapSpecLines = replacePlaceholders( bootstrapSpecLines, chainID, p2pPort, @@ -59,7 +60,7 @@ func genSpecs( ocrConfigContractAddress, bootHost, bootstrapNode, nca[i], ) - oracles = append(oracles, hostSpec{oracleSpecLines, nodes[i].url.Host}) + oracles = append(oracles, hostSpec{oracleSpecLines, nodes[i].remoteURL.Host}) } return donHostSpec{ @@ -73,7 +74,7 @@ func replacePlaceholders( chainID, p2pPort int64, contractAddress, bootHost string, - boot, node NodeKeys, + boot, node ksdeploy.NodeKeys, ) (output []string) { chainIDStr := strconv.FormatInt(chainID, 10) bootstrapper := fmt.Sprintf("%s@%s:%d", boot.P2PPeerID, bootHost, p2pPort) @@ -82,6 +83,7 @@ func replacePlaceholders( 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) } diff --git a/core/scripts/keystone/src/88_gen_ocr3_config.go b/core/scripts/keystone/src/88_gen_ocr3_config.go index 1107df57ca1..6d959e50b41 100644 --- a/core/scripts/keystone/src/88_gen_ocr3_config.go +++ b/core/scripts/keystone/src/88_gen_ocr3_config.go @@ -1,188 +1,19 @@ package src import ( - "crypto/ed25519" - "encoding/hex" - "encoding/json" - "time" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + ksdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" ) -type TopLevelConfigSource struct { - OracleConfig OracleConfigSource -} - -type OracleConfigSource struct { - MaxQueryLengthBytes uint32 - MaxObservationLengthBytes uint32 - MaxReportLengthBytes uint32 - MaxRequestBatchSize uint32 - UniqueReports bool - - DeltaProgressMillis uint32 - DeltaResendMillis uint32 - DeltaInitialMillis uint32 - DeltaRoundMillis uint32 - DeltaGraceMillis uint32 - DeltaCertifiedCommitRequestMillis uint32 - DeltaStageMillis uint32 - MaxRoundsPerEpoch uint64 - TransmissionSchedule []int - - MaxDurationQueryMillis uint32 - MaxDurationObservationMillis uint32 - MaxDurationAcceptMillis uint32 - MaxDurationTransmitMillis uint32 - - MaxFaultyOracles int +func mustReadConfig(fileName string) (output ksdeploy.TopLevelConfigSource) { + return mustParseJSON[ksdeploy.TopLevelConfigSource](fileName) } -type NodeKeys struct { - EthAddress string - P2PPeerID string // p2p_ - OCR2BundleID string // used only in job spec - OCR2OnchainPublicKey string // ocr2on_evm_ - OCR2OffchainPublicKey string // ocr2off_evm_ - OCR2ConfigPublicKey string // ocr2cfg_evm_ - CSAPublicKey string -} - -type orc2drOracleConfig struct { - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte -} - -func (c orc2drOracleConfig) MarshalJSON() ([]byte, error) { - alias := struct { - Signers []string - Transmitters []string - F uint8 - OnchainConfig string - OffchainConfigVersion uint64 - OffchainConfig string - }{ - Signers: make([]string, len(c.Signers)), - Transmitters: make([]string, len(c.Transmitters)), - F: c.F, - OnchainConfig: "0x" + hex.EncodeToString(c.OnchainConfig), - OffchainConfigVersion: c.OffchainConfigVersion, - OffchainConfig: "0x" + hex.EncodeToString(c.OffchainConfig), - } - - for i, signer := range c.Signers { - alias.Signers[i] = signer.Hex() - } - - for i, transmitter := range c.Transmitters { - alias.Transmitters[i] = transmitter.Hex() - } - - return json.Marshal(alias) -} - -func mustReadConfig(fileName string) (output TopLevelConfigSource) { - return mustParseJSON[TopLevelConfigSource](fileName) -} - -func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) orc2drOracleConfig { +func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) ksdeploy.Orc2drOracleConfig { topLevelCfg := mustReadConfig(configFile) cfg := topLevelCfg.OracleConfig nca := downloadNodePubKeys(nodeList, chainID, pubKeysPath) - - onchainPubKeys := []common.Address{} - for _, n := range nca { - onchainPubKeys = append(onchainPubKeys, common.HexToAddress(n.OCR2OnchainPublicKey)) - } - - offchainPubKeysBytes := []types.OffchainPublicKey{} - for _, n := range nca { - pkBytes, err := hex.DecodeString(n.OCR2OffchainPublicKey) - if err != nil { - panic(err) - } - - pkBytesFixed := [ed25519.PublicKeySize]byte{} - nCopied := copy(pkBytesFixed[:], pkBytes) - if nCopied != ed25519.PublicKeySize { - panic("wrong num elements copied from ocr2 offchain public key") - } - - offchainPubKeysBytes = append(offchainPubKeysBytes, types.OffchainPublicKey(pkBytesFixed)) - } - - configPubKeysBytes := []types.ConfigEncryptionPublicKey{} - for _, n := range nca { - pkBytes, err := hex.DecodeString(n.OCR2ConfigPublicKey) - helpers.PanicErr(err) - - pkBytesFixed := [ed25519.PublicKeySize]byte{} - n := copy(pkBytesFixed[:], pkBytes) - if n != ed25519.PublicKeySize { - panic("wrong num elements copied") - } - - configPubKeysBytes = append(configPubKeysBytes, types.ConfigEncryptionPublicKey(pkBytesFixed)) - } - - identities := []confighelper.OracleIdentityExtra{} - for index := range nca { - identities = append(identities, confighelper.OracleIdentityExtra{ - OracleIdentity: confighelper.OracleIdentity{ - OnchainPublicKey: onchainPubKeys[index][:], - OffchainPublicKey: offchainPubKeysBytes[index], - PeerID: nca[index].P2PPeerID, - TransmitAccount: types.Account(nca[index].EthAddress), - }, - ConfigEncryptionPublicKey: configPubKeysBytes[index], - }) - } - - signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( - time.Duration(cfg.DeltaProgressMillis)*time.Millisecond, - time.Duration(cfg.DeltaResendMillis)*time.Millisecond, - time.Duration(cfg.DeltaInitialMillis)*time.Millisecond, - time.Duration(cfg.DeltaRoundMillis)*time.Millisecond, - time.Duration(cfg.DeltaGraceMillis)*time.Millisecond, - time.Duration(cfg.DeltaCertifiedCommitRequestMillis)*time.Millisecond, - time.Duration(cfg.DeltaStageMillis)*time.Millisecond, - cfg.MaxRoundsPerEpoch, - cfg.TransmissionSchedule, - identities, - nil, // empty plugin config - time.Duration(cfg.MaxDurationQueryMillis)*time.Millisecond, - time.Duration(cfg.MaxDurationObservationMillis)*time.Millisecond, - time.Duration(cfg.MaxDurationAcceptMillis)*time.Millisecond, - time.Duration(cfg.MaxDurationTransmitMillis)*time.Millisecond, - cfg.MaxFaultyOracles, - nil, // empty onChain config - ) + c, err := ksdeploy.GenerateOCR3Config(cfg, nca) helpers.PanicErr(err) - - signerAddresses, err := evm.OnchainPublicKeyToAddress(signers) - PanicErr(err) - transmitterAddresses, err := evm.AccountToAddress(transmitters) - PanicErr(err) - - config := orc2drOracleConfig{ - Signers: signerAddresses, - Transmitters: transmitterAddresses, - F: f, - OnchainConfig: onchainConfig, - OffchainConfigVersion: offchainConfigVersion, - OffchainConfig: offchainConfig, - } - - return config + return c } diff --git a/core/scripts/keystone/src/99_fetch_keys.go b/core/scripts/keystone/src/99_fetch_keys.go index b115a7bb94d..9d88ba59643 100644 --- a/core/scripts/keystone/src/99_fetch_keys.go +++ b/core/scripts/keystone/src/99_fetch_keys.go @@ -13,15 +13,17 @@ import ( "github.com/urfave/cli" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + ksdeploy "github.com/smartcontractkit/chainlink/integration-tests/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) []NodeKeys { +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[[]NodeKeys](pubKeysPath) + return mustParseJSON[[]ksdeploy.NodeKeys](pubKeysPath) } nodes := downloadNodeAPICredentials(nodeList) @@ -95,7 +97,7 @@ type ocr2Bundle struct { ConfigPublicKey string `json:"configPublicKey"` } -func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { +func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []ksdeploy.NodeKeys) { for _, n := range nodes { output := &bytes.Buffer{} client, app := newApp(n, output) @@ -118,6 +120,19 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { 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")) + } + aptosAccount := aptosKeys[0].Account + output.Reset() + err = client.ListP2PKeys(&cli.Context{ App: app, }) @@ -130,18 +145,20 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { peerID := strings.TrimPrefix(p2pKeys[0].PeerID, "p2p_") output.Reset() + chainType := "evm" + var ocr2Bundles []ocr2Bundle err = client.ListOCR2KeyBundles(&cli.Context{ App: app, }) helpers.PanicErr(err) helpers.PanicErr(json.Unmarshal(output.Bytes(), &ocr2Bundles)) - ocr2BundleIndex := findEvmOCR2Bundle(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{"evm"}) + err = fs.Parse([]string{chainType}) helpers.PanicErr(err) ocr2CreateBundleCtx := cli.NewContext(app, fs, nil) err = client.CreateOCR2KeyBundle(ocr2CreateBundleCtx) @@ -153,12 +170,35 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { }) helpers.PanicErr(err) helpers.PanicErr(json.Unmarshal(output.Bytes(), &ocr2Bundles)) - ocr2BundleIndex = findEvmOCR2Bundle(ocr2Bundles) + ocr2BundleIndex = findOCR2Bundle(ocr2Bundles, chainType) output.Reset() } 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() + } + + aptosBundle := ocr2Bundles[aptosBundleIndex] + err = client.ListCSAKeys(&cli.Context{ App: app, }) @@ -169,13 +209,16 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []NodeKeys) { helpers.PanicErr(err) output.Reset() - nc := NodeKeys{ + 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, "ocr2cfg_evm_"), - OCR2OnchainPublicKey: strings.TrimPrefix(ocr2Bndl.OnchainPublicKey, "ocr2on_evm_"), - OCR2OffchainPublicKey: strings.TrimPrefix(ocr2Bndl.OffchainPublicKey, "ocr2off_evm_"), + 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, } @@ -191,9 +234,9 @@ func findFirstCSAPublicKey(csaKeyResources []presenters.CSAKeyResource) (string, return "", errors.New("did not find any CSA Key Resources") } -func findEvmOCR2Bundle(ocr2Bundles []ocr2Bundle) int { +func findOCR2Bundle(ocr2Bundles []ocr2Bundle, chainType string) int { for i, b := range ocr2Bundles { - if b.ChainType == "evm" { + if b.ChainType == chainType { return i } } diff --git a/core/scripts/keystone/src/99_nodes.go b/core/scripts/keystone/src/99_nodes.go index 961d58c4b19..68d3621ce63 100644 --- a/core/scripts/keystone/src/99_nodes.go +++ b/core/scripts/keystone/src/99_nodes.go @@ -10,9 +10,10 @@ import ( ) type node struct { - url *url.URL - login string - password string + url *url.URL + remoteURL *url.URL + login string + password string } func (n node) IsTerminal() bool { @@ -50,7 +51,7 @@ func mustReadNodesList(path string) []*node { continue } s := strings.Split(rr, " ") - if len(s) != 3 { + if len(s) != 4 { helpers.PanicErr(errors.New("wrong nodes list format")) } if strings.Contains(s[0], "boot") && hasBoot { @@ -58,11 +59,13 @@ func mustReadNodesList(path string) []*node { } hasBoot = true url, err := url.Parse(s[0]) + remoteURL, err := url.Parse(s[1]) helpers.PanicErr(err) nodes = append(nodes, &node{ - url: url, - login: s[1], - password: s[2], + url: url, + remoteURL: remoteURL, + login: s[2], + password: s[3], }) } return nodes diff --git a/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap b/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap index a4b4e6e3021..c0c7c7d7e67 100755 --- a/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap +++ b/core/scripts/keystone/src/__snapshots__/88_gen_jobspecs_test.snap @@ -10,6 +10,7 @@ relay = "evm" [relayConfig] chainID = "11155111" +providerType = "ocr3-capability" Oracles: Oracle 0: @@ -37,8 +38,10 @@ providerType = "ocr3-capability" telemetryType = "plugin" [onchainSigningStrategy] -strategyName = 'single-chain' +strategyName = 'multi-chain' [onchainSigningStrategy.config] +evm = "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed" +aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfb" -------------------------------- Oracle 1: @@ -66,8 +69,10 @@ providerType = "ocr3-capability" telemetryType = "plugin" [onchainSigningStrategy] -strategyName = 'single-chain' +strategyName = 'multi-chain' [onchainSigningStrategy.config] +evm = "38459ae37f29f2c1fde0f25972a973322be8cada82acf43f464756836725be97" +aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfc" -------------------------------- Oracle 2: @@ -95,8 +100,10 @@ providerType = "ocr3-capability" telemetryType = "plugin" [onchainSigningStrategy] -strategyName = 'single-chain' +strategyName = 'multi-chain' [onchainSigningStrategy.config] +evm = "b5dbc4c9da983cddde2e3226b85807eb7beaf818694a22576af4d80f352702ed" +aptos = "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfd" -------------------------------- Oracle 3: @@ -124,8 +131,10 @@ providerType = "ocr3-capability" telemetryType = "plugin" [onchainSigningStrategy] -strategyName = 'single-chain' +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 index a2ecd236f74..eac3cdaff4c 100755 --- a/core/scripts/keystone/src/__snapshots__/88_gen_ocr3_config_test.snap +++ b/core/scripts/keystone/src/__snapshots__/88_gen_ocr3_config_test.snap @@ -6,11 +6,11 @@ "OffchainConfigVersion": 30, "OnchainConfig": "0x", "Signers": [ - "0xA2402db8E549f094EA31e1C0EDd77623F4cA5b12", - "0x4af19c802B244D1d085492C3946391C965E10519", - "0x61925685d2B80b121537341d063c4E57B2F9323c", - "0xFd97eFD53FC20acc098Fcd746C04d8d7540D97E0", - "0xA0b67Dc5345a71D02B396147AE2cb75dDA63CbE9" + "011400a2402db8e549f094ea31e1c0edd77623f4ca5b12052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4a", + "0114004af19c802b244d1d085492c3946391c965e10519052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4b", + "01140061925685d2b80b121537341d063c4e57b2f9323c052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4c", + "011400fd97efd53fc20acc098fcd746c04d8d7540d97e0052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4d", + "011400a0b67dc5345a71d02b396147ae2cb75dda63cbe9052000ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4e" ], "Transmitters": [ "0xF4e7e516146c8567F8E8be0ED1f1A92798628d35", diff --git a/core/scripts/keystone/src/testdata/NodeList.txt b/core/scripts/keystone/src/testdata/NodeList.txt index 9a895e0f3fa..6fb65dded69 100644 --- a/core/scripts/keystone/src/testdata/NodeList.txt +++ b/core/scripts/keystone/src/testdata/NodeList.txt @@ -1,5 +1,5 @@ -https://crib-henry-keystone-node1.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://crib-henry-keystone-node2.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://crib-henry-keystone-node3.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://crib-henry-keystone-node4.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs -https://crib-henry-keystone-node5.main.stage.cldev.sh notreal@fakeemail.ch fj293fbBnlQ!f9vNs +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 index 7ade3d45ad3..b29e8290895 100644 --- a/core/scripts/keystone/src/testdata/PublicKeys.json +++ b/core/scripts/keystone/src/testdata/PublicKeys.json @@ -1,5 +1,7 @@ [ { + "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfa", + "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4a", "EthAddress": "0xF4e7e516146c8567F8E8be0ED1f1A92798628d35", "P2PPeerID": "12D3KooWNmhKZL1XW4Vv3rNjLXzJ6mqcVerihdijjGYuexPrFUFZ", "OCR2BundleID": "2f92c96da20fbe39c89e59516e3a7473254523316887394e406527c72071d3db", @@ -9,6 +11,8 @@ "CSAPublicKey": "csa_dbae6965bad0b0fa95ecc34a602eee1c0c570ddc29b56502e400d18574b8c3df" }, { + "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfb", + "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4b", "EthAddress": "0x8B60FDcc9CAC8ea476b31d17011CB204471431d9", "P2PPeerID": "12D3KooWFUjV73ZYkAMhS2cVwte3kXDWD8Ybyx3u9CEDHNoeEhBH", "OCR2BundleID": "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed", @@ -18,6 +22,8 @@ "CSAPublicKey": "csa_c5cc655a9c19b69626519c4a72c44a94a3675daeba9c16cc23e010a7a6dac1be" }, { + "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfc", + "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4c", "EthAddress": "0x6620F516F29979B214e2451498a057FDd3a0A85d", "P2PPeerID": "12D3KooWRTtH2WWrztD87Do1kXePSmGjyU4r7mZVWThmqTGgdbUC", "OCR2BundleID": "38459ae37f29f2c1fde0f25972a973322be8cada82acf43f464756836725be97", @@ -27,6 +33,8 @@ "CSAPublicKey": "csa_7407fc90c70895c0fb2bdf385e2e4918364bec1f7a74bad7fdf696bffafbcab8" }, { + "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfd", + "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4d", "EthAddress": "0xFeB61E22FCf4F9740c9D96b05199F195bd61A7c2", "P2PPeerID": "12D3KooWMTZnZtcVK4EJsjkKsV9qXNoNRSjT62CZi3tKkXGaCsGh", "OCR2BundleID": "b5dbc4c9da983cddde2e3226b85807eb7beaf818694a22576af4d80f352702ed", @@ -36,6 +44,8 @@ "CSAPublicKey": "csa_ef55caf17eefc2a9d547b5a3978d396bd237c73af99cd849a4758701122e3cba" }, { + "AptosBundleID": "9bebfa953e7a7522746f72b4023308de36db626f3e0bcb9033407b8a183e8bfe", + "AptosOnchainPublicKey": "ea551e503b93a1c9ae26262b4db8f66db4cbe5ddcb6039e29d2665a634d48e4e", "EthAddress": "0x882Fd04D78A7e7D386Dd5b550f19479E5494B0B2", "P2PPeerID": "12D3KooWRsM9yordRQDhLgbErH8WMMGz1bC1J4hR5gAGvMWu8goN", "OCR2BundleID": "260d5c1a618cdf5324509d7db95f5a117511864ebb9e1f709e8969339eb225af", diff --git a/core/scripts/keystone/templates/bootstrap.toml b/core/scripts/keystone/templates/bootstrap.toml index 1baa43101b6..cdd9065caba 100644 --- a/core/scripts/keystone/templates/bootstrap.toml +++ b/core/scripts/keystone/templates/bootstrap.toml @@ -6,3 +6,4 @@ relay = "evm" [relayConfig] chainID = "{{ chain_id }}" +providerType = "ocr3-capability" diff --git a/core/scripts/keystone/templates/oracle.toml b/core/scripts/keystone/templates/oracle.toml index 6049ad925d4..053baa2223b 100644 --- a/core/scripts/keystone/templates/oracle.toml +++ b/core/scripts/keystone/templates/oracle.toml @@ -21,5 +21,7 @@ providerType = "ocr3-capability" telemetryType = "plugin" [onchainSigningStrategy] -strategyName = 'single-chain' +strategyName = 'multi-chain' [onchainSigningStrategy.config] +evm = "{{ ocr_key_bundle_id }}" +aptos = "{{ aptos_key_bundle_id }}" diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index a37a5391021..f5220f62dd2 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -213,7 +213,7 @@ func main() { for i := range preSeedSlice { ps, err := proof.BigToSeed(preSeedSlice[i]) helpers.PanicErr(err) - extraArgs, err := extraargs.ExtraArgsV1(*nativePayment) + extraArgs, err := extraargs.EncodeV1(*nativePayment) helpers.PanicErr(err) preSeedData := proof.PreSeedDataV2Plus{ PreSeed: ps, @@ -308,7 +308,7 @@ func main() { helpers.PanicErr(err) parsedSubID := parseUInt256String(*subID) - extraArgs, err := extraargs.ExtraArgsV1(*nativePayment) + extraArgs, err := extraargs.EncodeV1(*nativePayment) helpers.PanicErr(err) preSeedData := proof.PreSeedDataV2Plus{ PreSeed: ps, diff --git a/core/scripts/vrfv2plus/testnet/proofs.go b/core/scripts/vrfv2plus/testnet/proofs.go index 23ddc8ecfd6..8f1cef0ca6c 100644 --- a/core/scripts/vrfv2plus/testnet/proofs.go +++ b/core/scripts/vrfv2plus/testnet/proofs.go @@ -54,7 +54,7 @@ var rcTemplate = `{ ` func generateProofForV2Plus(e helpers.Environment) { - deployCmd := flag.NewFlagSet("generate-proof", flag.ExitOnError) + deployCmd := flag.NewFlagSet("generate-proof-v2-plus", flag.ExitOnError) keyHashString := deployCmd.String("key-hash", "", "key hash for VRF request") preSeedString := deployCmd.String("pre-seed", "", "pre-seed for VRF request") @@ -105,7 +105,7 @@ func generateProofForV2Plus(e helpers.Environment) { if !ok { helpers.PanicErr(fmt.Errorf("unable to parse subID: %s %w", *subId, err)) } - extraArgs, err := extraargs.ExtraArgsV1(*nativePayment) + extraArgs, err := extraargs.EncodeV1(*nativePayment) helpers.PanicErr(err) preSeedData := proof.PreSeedDataV2Plus{ PreSeed: preSeed, diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go index b2e978293df..7e395da74c0 100644 --- a/core/services/blockhashstore/bhs_test.go +++ b/core/services/blockhashstore/bhs_test.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -30,8 +29,7 @@ func TestStoreRotatesFromAddresses(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) kst := cltest.NewKeyStore(t, db) require.NoError(t, kst.Unlock(ctx, cltest.Password)) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg, Client: ethClient}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg, Client: ethClient}) chain, err := legacyChains.Get(cltest.FixtureChainID.String()) require.NoError(t, err) lggr := logger.TestLogger(t) diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go index 6bc93546605..437fcc412f7 100644 --- a/core/services/blockhashstore/delegate_test.go +++ b/core/services/blockhashstore/delegate_test.go @@ -26,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func TestDelegate_JobType(t *testing.T) { @@ -61,7 +60,7 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) { lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{}, nil) - relayExtenders := evmtest.NewChainRelayExtenders( + legacyChains := evmtest.NewLegacyChains( t, evmtest.TestChainOpts{ DB: db, @@ -71,7 +70,6 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) { LogPoller: lp, }, ) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) return blockhashstore.NewDelegate(cfg, lggr, legacyChains, kst), &testData{ ethClient: ethClient, ethKeyStore: kst, @@ -163,7 +161,7 @@ func TestDelegate_StartStop(t *testing.T) { err = services[0].Start(testutils.Context(t)) require.NoError(t, err) - assert.Eventually(t, func() bool { + require.Eventually(t, func() bool { return testData.logs.FilterMessage("Starting BHS feeder").Len() > 0 && testData.logs.FilterMessage("Running BHS feeder").Len() > 0 && testData.logs.FilterMessage("BHS feeder run completed successfully").Len() > 0 diff --git a/core/services/ccip/mocks/orm.go b/core/services/ccip/mocks/orm.go index 8a987c21602..0c9086def7e 100644 --- a/core/services/ccip/mocks/orm.go +++ b/core/services/ccip/mocks/orm.go @@ -8,6 +8,8 @@ import ( ccip "github.com/smartcontractkit/chainlink/v2/core/services/ccip" mock "github.com/stretchr/testify/mock" + + time "time" ) // ORM is an autogenerated mock type for the ORM type @@ -23,102 +25,6 @@ func (_m *ORM) EXPECT() *ORM_Expecter { return &ORM_Expecter{mock: &_m.Mock} } -// ClearGasPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, expireSec -func (_m *ORM) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { - ret := _m.Called(ctx, destChainSelector, expireSec) - - if len(ret) == 0 { - panic("no return value specified for ClearGasPricesByDestChain") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, int) error); ok { - r0 = rf(ctx, destChainSelector, expireSec) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ORM_ClearGasPricesByDestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClearGasPricesByDestChain' -type ORM_ClearGasPricesByDestChain_Call struct { - *mock.Call -} - -// ClearGasPricesByDestChain is a helper method to define mock.On call -// - ctx context.Context -// - destChainSelector uint64 -// - expireSec int -func (_e *ORM_Expecter) ClearGasPricesByDestChain(ctx interface{}, destChainSelector interface{}, expireSec interface{}) *ORM_ClearGasPricesByDestChain_Call { - return &ORM_ClearGasPricesByDestChain_Call{Call: _e.mock.On("ClearGasPricesByDestChain", ctx, destChainSelector, expireSec)} -} - -func (_c *ORM_ClearGasPricesByDestChain_Call) Run(run func(ctx context.Context, destChainSelector uint64, expireSec int)) *ORM_ClearGasPricesByDestChain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint64), args[2].(int)) - }) - return _c -} - -func (_c *ORM_ClearGasPricesByDestChain_Call) Return(_a0 error) *ORM_ClearGasPricesByDestChain_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ORM_ClearGasPricesByDestChain_Call) RunAndReturn(run func(context.Context, uint64, int) error) *ORM_ClearGasPricesByDestChain_Call { - _c.Call.Return(run) - return _c -} - -// ClearTokenPricesByDestChain provides a mock function with given fields: ctx, destChainSelector, expireSec -func (_m *ORM) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { - ret := _m.Called(ctx, destChainSelector, expireSec) - - if len(ret) == 0 { - panic("no return value specified for ClearTokenPricesByDestChain") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, int) error); ok { - r0 = rf(ctx, destChainSelector, expireSec) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ORM_ClearTokenPricesByDestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClearTokenPricesByDestChain' -type ORM_ClearTokenPricesByDestChain_Call struct { - *mock.Call -} - -// ClearTokenPricesByDestChain is a helper method to define mock.On call -// - ctx context.Context -// - destChainSelector uint64 -// - expireSec int -func (_e *ORM_Expecter) ClearTokenPricesByDestChain(ctx interface{}, destChainSelector interface{}, expireSec interface{}) *ORM_ClearTokenPricesByDestChain_Call { - return &ORM_ClearTokenPricesByDestChain_Call{Call: _e.mock.On("ClearTokenPricesByDestChain", ctx, destChainSelector, expireSec)} -} - -func (_c *ORM_ClearTokenPricesByDestChain_Call) Run(run func(ctx context.Context, destChainSelector uint64, expireSec int)) *ORM_ClearTokenPricesByDestChain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint64), args[2].(int)) - }) - return _c -} - -func (_c *ORM_ClearTokenPricesByDestChain_Call) Return(_a0 error) *ORM_ClearTokenPricesByDestChain_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ORM_ClearTokenPricesByDestChain_Call) RunAndReturn(run func(context.Context, uint64, int) error) *ORM_ClearTokenPricesByDestChain_Call { - _c.Call.Return(run) - return _c -} - // GetGasPricesByDestChain provides a mock function with given fields: ctx, destChainSelector func (_m *ORM) GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]ccip.GasPrice, error) { ret := _m.Called(ctx, destChainSelector) @@ -237,100 +143,119 @@ func (_c *ORM_GetTokenPricesByDestChain_Call) RunAndReturn(run func(context.Cont return _c } -// InsertGasPricesForDestChain provides a mock function with given fields: ctx, destChainSelector, jobId, gasPrices -func (_m *ORM) InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []ccip.GasPriceUpdate) error { - ret := _m.Called(ctx, destChainSelector, jobId, gasPrices) +// UpsertGasPricesForDestChain provides a mock function with given fields: ctx, destChainSelector, gasPrices +func (_m *ORM) UpsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, gasPrices []ccip.GasPrice) (int64, error) { + ret := _m.Called(ctx, destChainSelector, gasPrices) if len(ret) == 0 { - panic("no return value specified for InsertGasPricesForDestChain") + panic("no return value specified for UpsertGasPricesForDestChain") } - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, int32, []ccip.GasPriceUpdate) error); ok { - r0 = rf(ctx, destChainSelector, jobId, gasPrices) + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []ccip.GasPrice) (int64, error)); ok { + return rf(ctx, destChainSelector, gasPrices) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []ccip.GasPrice) int64); ok { + r0 = rf(ctx, destChainSelector, gasPrices) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(int64) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, uint64, []ccip.GasPrice) error); ok { + r1 = rf(ctx, destChainSelector, gasPrices) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } -// ORM_InsertGasPricesForDestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'InsertGasPricesForDestChain' -type ORM_InsertGasPricesForDestChain_Call struct { +// ORM_UpsertGasPricesForDestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpsertGasPricesForDestChain' +type ORM_UpsertGasPricesForDestChain_Call struct { *mock.Call } -// InsertGasPricesForDestChain is a helper method to define mock.On call +// UpsertGasPricesForDestChain is a helper method to define mock.On call // - ctx context.Context // - destChainSelector uint64 -// - jobId int32 -// - gasPrices []ccip.GasPriceUpdate -func (_e *ORM_Expecter) InsertGasPricesForDestChain(ctx interface{}, destChainSelector interface{}, jobId interface{}, gasPrices interface{}) *ORM_InsertGasPricesForDestChain_Call { - return &ORM_InsertGasPricesForDestChain_Call{Call: _e.mock.On("InsertGasPricesForDestChain", ctx, destChainSelector, jobId, gasPrices)} +// - gasPrices []ccip.GasPrice +func (_e *ORM_Expecter) UpsertGasPricesForDestChain(ctx interface{}, destChainSelector interface{}, gasPrices interface{}) *ORM_UpsertGasPricesForDestChain_Call { + return &ORM_UpsertGasPricesForDestChain_Call{Call: _e.mock.On("UpsertGasPricesForDestChain", ctx, destChainSelector, gasPrices)} } -func (_c *ORM_InsertGasPricesForDestChain_Call) Run(run func(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []ccip.GasPriceUpdate)) *ORM_InsertGasPricesForDestChain_Call { +func (_c *ORM_UpsertGasPricesForDestChain_Call) Run(run func(ctx context.Context, destChainSelector uint64, gasPrices []ccip.GasPrice)) *ORM_UpsertGasPricesForDestChain_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint64), args[2].(int32), args[3].([]ccip.GasPriceUpdate)) + run(args[0].(context.Context), args[1].(uint64), args[2].([]ccip.GasPrice)) }) return _c } -func (_c *ORM_InsertGasPricesForDestChain_Call) Return(_a0 error) *ORM_InsertGasPricesForDestChain_Call { - _c.Call.Return(_a0) +func (_c *ORM_UpsertGasPricesForDestChain_Call) Return(_a0 int64, _a1 error) *ORM_UpsertGasPricesForDestChain_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *ORM_InsertGasPricesForDestChain_Call) RunAndReturn(run func(context.Context, uint64, int32, []ccip.GasPriceUpdate) error) *ORM_InsertGasPricesForDestChain_Call { +func (_c *ORM_UpsertGasPricesForDestChain_Call) RunAndReturn(run func(context.Context, uint64, []ccip.GasPrice) (int64, error)) *ORM_UpsertGasPricesForDestChain_Call { _c.Call.Return(run) return _c } -// InsertTokenPricesForDestChain provides a mock function with given fields: ctx, destChainSelector, jobId, tokenPrices -func (_m *ORM) InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []ccip.TokenPriceUpdate) error { - ret := _m.Called(ctx, destChainSelector, jobId, tokenPrices) +// UpsertTokenPricesForDestChain provides a mock function with given fields: ctx, destChainSelector, tokenPrices, interval +func (_m *ORM) UpsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, tokenPrices []ccip.TokenPrice, interval time.Duration) (int64, error) { + ret := _m.Called(ctx, destChainSelector, tokenPrices, interval) if len(ret) == 0 { - panic("no return value specified for InsertTokenPricesForDestChain") + panic("no return value specified for UpsertTokenPricesForDestChain") } - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, int32, []ccip.TokenPriceUpdate) error); ok { - r0 = rf(ctx, destChainSelector, jobId, tokenPrices) + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []ccip.TokenPrice, time.Duration) (int64, error)); ok { + return rf(ctx, destChainSelector, tokenPrices, interval) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []ccip.TokenPrice, time.Duration) int64); ok { + r0 = rf(ctx, destChainSelector, tokenPrices, interval) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(int64) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, uint64, []ccip.TokenPrice, time.Duration) error); ok { + r1 = rf(ctx, destChainSelector, tokenPrices, interval) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } -// ORM_InsertTokenPricesForDestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'InsertTokenPricesForDestChain' -type ORM_InsertTokenPricesForDestChain_Call struct { +// ORM_UpsertTokenPricesForDestChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpsertTokenPricesForDestChain' +type ORM_UpsertTokenPricesForDestChain_Call struct { *mock.Call } -// InsertTokenPricesForDestChain is a helper method to define mock.On call +// UpsertTokenPricesForDestChain is a helper method to define mock.On call // - ctx context.Context // - destChainSelector uint64 -// - jobId int32 -// - tokenPrices []ccip.TokenPriceUpdate -func (_e *ORM_Expecter) InsertTokenPricesForDestChain(ctx interface{}, destChainSelector interface{}, jobId interface{}, tokenPrices interface{}) *ORM_InsertTokenPricesForDestChain_Call { - return &ORM_InsertTokenPricesForDestChain_Call{Call: _e.mock.On("InsertTokenPricesForDestChain", ctx, destChainSelector, jobId, tokenPrices)} +// - tokenPrices []ccip.TokenPrice +// - interval time.Duration +func (_e *ORM_Expecter) UpsertTokenPricesForDestChain(ctx interface{}, destChainSelector interface{}, tokenPrices interface{}, interval interface{}) *ORM_UpsertTokenPricesForDestChain_Call { + return &ORM_UpsertTokenPricesForDestChain_Call{Call: _e.mock.On("UpsertTokenPricesForDestChain", ctx, destChainSelector, tokenPrices, interval)} } -func (_c *ORM_InsertTokenPricesForDestChain_Call) Run(run func(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []ccip.TokenPriceUpdate)) *ORM_InsertTokenPricesForDestChain_Call { +func (_c *ORM_UpsertTokenPricesForDestChain_Call) Run(run func(ctx context.Context, destChainSelector uint64, tokenPrices []ccip.TokenPrice, interval time.Duration)) *ORM_UpsertTokenPricesForDestChain_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint64), args[2].(int32), args[3].([]ccip.TokenPriceUpdate)) + run(args[0].(context.Context), args[1].(uint64), args[2].([]ccip.TokenPrice), args[3].(time.Duration)) }) return _c } -func (_c *ORM_InsertTokenPricesForDestChain_Call) Return(_a0 error) *ORM_InsertTokenPricesForDestChain_Call { - _c.Call.Return(_a0) +func (_c *ORM_UpsertTokenPricesForDestChain_Call) Return(_a0 int64, _a1 error) *ORM_UpsertTokenPricesForDestChain_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *ORM_InsertTokenPricesForDestChain_Call) RunAndReturn(run func(context.Context, uint64, int32, []ccip.TokenPriceUpdate) error) *ORM_InsertTokenPricesForDestChain_Call { +func (_c *ORM_UpsertTokenPricesForDestChain_Call) RunAndReturn(run func(context.Context, uint64, []ccip.TokenPrice, time.Duration) (int64, error)) *ORM_UpsertTokenPricesForDestChain_Call { _c.Call.Return(run) return _c } diff --git a/core/services/ccip/observability.go b/core/services/ccip/observability.go new file mode 100644 index 00000000000..8a061893ce6 --- /dev/null +++ b/core/services/ccip/observability.go @@ -0,0 +1,115 @@ +package ccip + +import ( + "context" + "strconv" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var ( + sqlLatencyBuckets = []float64{ + float64(10 * time.Millisecond), + float64(20 * time.Millisecond), + float64(30 * time.Millisecond), + float64(40 * time.Millisecond), + float64(50 * time.Millisecond), + float64(70 * time.Millisecond), + float64(90 * time.Millisecond), + float64(100 * time.Millisecond), + float64(200 * time.Millisecond), + float64(300 * time.Millisecond), + float64(400 * time.Millisecond), + float64(500 * time.Millisecond), + float64(750 * time.Millisecond), + float64(1 * time.Second), + } + ccipQueryDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "ccip_orm_query_duration", + Buckets: sqlLatencyBuckets, + }, []string{"query", "destChainSelector"}) + ccipQueryDatasets = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "ccip_orm_dataset_size", + }, []string{"query", "destChainSelector"}) +) + +type observedORM struct { + ORM + queryDuration *prometheus.HistogramVec + datasetSize *prometheus.GaugeVec +} + +var _ ORM = (*observedORM)(nil) + +func NewObservedORM(ds sqlutil.DataSource, lggr logger.Logger) (*observedORM, error) { + delegate, err := NewORM(ds, lggr) + if err != nil { + return nil, err + } + + return &observedORM{ + ORM: delegate, + queryDuration: ccipQueryDuration, + datasetSize: ccipQueryDatasets, + }, nil +} + +func (o *observedORM) GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]GasPrice, error) { + return withObservedQueryAndResults(o, "GetGasPricesByDestChain", destChainSelector, func() ([]GasPrice, error) { + return o.ORM.GetGasPricesByDestChain(ctx, destChainSelector) + }) +} + +func (o *observedORM) GetTokenPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]TokenPrice, error) { + return withObservedQueryAndResults(o, "GetTokenPricesByDestChain", destChainSelector, func() ([]TokenPrice, error) { + return o.ORM.GetTokenPricesByDestChain(ctx, destChainSelector) + }) +} + +func (o *observedORM) UpsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, gasPrices []GasPrice) (int64, error) { + return withObservedQueryAndRowsAffected(o, "UpsertGasPricesForDestChain", destChainSelector, func() (int64, error) { + return o.ORM.UpsertGasPricesForDestChain(ctx, destChainSelector, gasPrices) + }) +} + +func (o *observedORM) UpsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, tokenPrices []TokenPrice, interval time.Duration) (int64, error) { + return withObservedQueryAndRowsAffected(o, "UpsertTokenPricesForDestChain", destChainSelector, func() (int64, error) { + return o.ORM.UpsertTokenPricesForDestChain(ctx, destChainSelector, tokenPrices, interval) + }) +} + +func withObservedQueryAndRowsAffected(o *observedORM, queryName string, chainSelector uint64, query func() (int64, error)) (int64, error) { + rowsAffected, err := withObservedQuery(o, queryName, chainSelector, query) + if err == nil { + o.datasetSize. + WithLabelValues(queryName, strconv.FormatUint(chainSelector, 10)). + Set(float64(rowsAffected)) + } + return rowsAffected, err +} + +func withObservedQueryAndResults[T any](o *observedORM, queryName string, chainSelector uint64, query func() ([]T, error)) ([]T, error) { + results, err := withObservedQuery(o, queryName, chainSelector, query) + if err == nil { + o.datasetSize. + WithLabelValues(queryName, strconv.FormatUint(chainSelector, 10)). + Set(float64(len(results))) + } + return results, err +} + +func withObservedQuery[T any](o *observedORM, queryName string, chainSelector uint64, query func() (T, error)) (T, error) { + queryStarted := time.Now() + defer func() { + o.queryDuration. + WithLabelValues(queryName, strconv.FormatUint(chainSelector, 10)). + Observe(float64(time.Since(queryStarted))) + }() + return query() +} diff --git a/core/services/ccip/observability_test.go b/core/services/ccip/observability_test.go new file mode 100644 index 00000000000..24bfb4a9ec1 --- /dev/null +++ b/core/services/ccip/observability_test.go @@ -0,0 +1,94 @@ +package ccip + +import ( + "math/big" + "testing" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + io_prometheus_client "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func Test_MetricsAreTrackedForAllMethods(t *testing.T) { + ctx := testutils.Context(t) + db := pgtest.NewSqlxDB(t) + ccipORM, err := NewObservedORM(db, logger.TestLogger(t)) + require.NoError(t, err) + + tokenPrices := []TokenPrice{ + { + TokenAddr: "0xA", + TokenPrice: assets.NewWei(big.NewInt(1e18)), + }, + { + TokenAddr: "0xB", + TokenPrice: assets.NewWei(big.NewInt(1e18)), + }, + } + tokensUpserted, err := ccipORM.UpsertTokenPricesForDestChain(ctx, 100, tokenPrices, time.Second) + require.NoError(t, err) + assert.Equal(t, len(tokenPrices), int(tokensUpserted)) + assert.Equal(t, len(tokenPrices), counterFromGaugeByLabels(ccipORM.datasetSize, "UpsertTokenPricesForDestChain", "100")) + assert.Equal(t, 0, counterFromGaugeByLabels(ccipORM.datasetSize, "UpsertTokenPricesForDestChain", "200")) + + tokens, err := ccipORM.GetTokenPricesByDestChain(ctx, 100) + require.NoError(t, err) + assert.Equal(t, len(tokenPrices), len(tokens)) + assert.Equal(t, len(tokenPrices), counterFromGaugeByLabels(ccipORM.datasetSize, "GetTokenPricesByDestChain", "100")) + assert.Equal(t, 1, counterFromHistogramByLabels(t, ccipORM.queryDuration, "GetTokenPricesByDestChain", "100")) + + gasPrices := []GasPrice{ + { + SourceChainSelector: 200, + GasPrice: assets.NewWei(big.NewInt(1e18)), + }, + { + SourceChainSelector: 201, + GasPrice: assets.NewWei(big.NewInt(1e18)), + }, + { + SourceChainSelector: 202, + GasPrice: assets.NewWei(big.NewInt(1e18)), + }, + } + gasUpserted, err := ccipORM.UpsertGasPricesForDestChain(ctx, 100, gasPrices) + require.NoError(t, err) + assert.Equal(t, len(gasPrices), int(gasUpserted)) + assert.Equal(t, len(gasPrices), counterFromGaugeByLabels(ccipORM.datasetSize, "UpsertGasPricesForDestChain", "100")) + assert.Equal(t, 0, counterFromGaugeByLabels(ccipORM.datasetSize, "UpsertGasPricesForDestChain", "200")) + + gas, err := ccipORM.GetGasPricesByDestChain(ctx, 100) + require.NoError(t, err) + assert.Equal(t, len(gasPrices), len(gas)) + assert.Equal(t, len(gasPrices), counterFromGaugeByLabels(ccipORM.datasetSize, "GetGasPricesByDestChain", "100")) + assert.Equal(t, 1, counterFromHistogramByLabels(t, ccipORM.queryDuration, "GetGasPricesByDestChain", "100")) +} + +func counterFromHistogramByLabels(t *testing.T, histogramVec *prometheus.HistogramVec, labels ...string) int { + observer, err := histogramVec.GetMetricWithLabelValues(labels...) + require.NoError(t, err) + + metricCh := make(chan prometheus.Metric, 1) + observer.(prometheus.Histogram).Collect(metricCh) + close(metricCh) + + metric := <-metricCh + pb := &io_prometheus_client.Metric{} + err = metric.Write(pb) + require.NoError(t, err) + + return int(pb.GetHistogram().GetSampleCount()) +} + +func counterFromGaugeByLabels(gaugeVec *prometheus.GaugeVec, labels ...string) int { + value := testutil.ToFloat64(gaugeVec.WithLabelValues(labels...)) + return int(value) +} diff --git a/core/services/ccip/orm.go b/core/services/ccip/orm.go index d074ea7473e..1942c68fef9 100644 --- a/core/services/ccip/orm.go +++ b/core/services/ccip/orm.go @@ -8,65 +8,51 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) type GasPrice struct { SourceChainSelector uint64 GasPrice *assets.Wei - CreatedAt time.Time -} - -type GasPriceUpdate struct { - SourceChainSelector uint64 - GasPrice *assets.Wei } type TokenPrice struct { TokenAddr string TokenPrice *assets.Wei - CreatedAt time.Time -} - -type TokenPriceUpdate struct { - TokenAddr string - TokenPrice *assets.Wei } type ORM interface { GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]GasPrice, error) GetTokenPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]TokenPrice, error) - InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []GasPriceUpdate) error - InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []TokenPriceUpdate) error - - ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error - ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error + UpsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, gasPrices []GasPrice) (int64, error) + UpsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, tokenPrices []TokenPrice, interval time.Duration) (int64, error) } type orm struct { - ds sqlutil.DataSource + ds sqlutil.DataSource + lggr logger.Logger } var _ ORM = (*orm)(nil) -func NewORM(ds sqlutil.DataSource) (ORM, error) { +func NewORM(ds sqlutil.DataSource, lggr logger.Logger) (ORM, error) { if ds == nil { return nil, fmt.Errorf("datasource to CCIP NewORM cannot be nil") } return &orm{ - ds: ds, + ds: ds, + lggr: lggr, }, nil } func (o *orm) GetGasPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]GasPrice, error) { var gasPrices []GasPrice stmt := ` - SELECT DISTINCT ON (source_chain_selector) - source_chain_selector, gas_price, created_at + SELECT source_chain_selector, gas_price FROM ccip.observed_gas_prices - WHERE chain_selector = $1 - ORDER BY source_chain_selector, created_at DESC; + WHERE chain_selector = $1; ` err := o.ds.SelectContext(ctx, &gasPrices, stmt, destChainSelector) if err != nil { @@ -79,82 +65,147 @@ func (o *orm) GetGasPricesByDestChain(ctx context.Context, destChainSelector uin func (o *orm) GetTokenPricesByDestChain(ctx context.Context, destChainSelector uint64) ([]TokenPrice, error) { var tokenPrices []TokenPrice stmt := ` - SELECT DISTINCT ON (token_addr) - token_addr, token_price, created_at + SELECT token_addr, token_price FROM ccip.observed_token_prices - WHERE chain_selector = $1 - ORDER BY token_addr, created_at DESC; + WHERE chain_selector = $1; ` err := o.ds.SelectContext(ctx, &tokenPrices, stmt, destChainSelector) if err != nil { return nil, err } - return tokenPrices, nil } -func (o *orm) InsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, gasPrices []GasPriceUpdate) error { +func (o *orm) UpsertGasPricesForDestChain(ctx context.Context, destChainSelector uint64, gasPrices []GasPrice) (int64, error) { if len(gasPrices) == 0 { - return nil + return 0, nil + } + + uniqueGasUpdates := make(map[string]GasPrice) + for _, gasPrice := range gasPrices { + key := fmt.Sprintf("%d-%d", gasPrice.SourceChainSelector, destChainSelector) + uniqueGasUpdates[key] = gasPrice } - insertData := make([]map[string]interface{}, 0, len(gasPrices)) - for _, price := range gasPrices { + insertData := make([]map[string]interface{}, 0, len(uniqueGasUpdates)) + for _, price := range uniqueGasUpdates { insertData = append(insertData, map[string]interface{}{ "chain_selector": destChainSelector, - "job_id": jobId, "source_chain_selector": price.SourceChainSelector, "gas_price": price.GasPrice, }) } - // using statement_timestamp() to make testing easier - stmt := `INSERT INTO ccip.observed_gas_prices (chain_selector, job_id, source_chain_selector, gas_price, created_at) - VALUES (:chain_selector, :job_id, :source_chain_selector, :gas_price, statement_timestamp());` - _, err := o.ds.NamedExecContext(ctx, stmt, insertData) + stmt := `INSERT INTO ccip.observed_gas_prices (chain_selector, source_chain_selector, gas_price, updated_at) + VALUES (:chain_selector, :source_chain_selector, :gas_price, statement_timestamp()) + ON CONFLICT (source_chain_selector, chain_selector) + DO UPDATE SET gas_price = EXCLUDED.gas_price, updated_at = EXCLUDED.updated_at;` + + result, err := o.ds.NamedExecContext(ctx, stmt, insertData) if err != nil { - err = fmt.Errorf("error inserting gas prices for job %d: %w", jobId, err) + return 0, fmt.Errorf("error inserting gas prices %w", err) } - - return err + return result.RowsAffected() } -func (o *orm) InsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, jobId int32, tokenPrices []TokenPriceUpdate) error { +// UpsertTokenPricesForDestChain inserts or updates only relevant token prices. +// In order to reduce locking an unnecessary writes to the table, we start with fetching current prices. +// If price for a token doesn't change or was updated recently we don't include that token to the upsert query. +// We don't run in TX intentionally, because we don't want to lock the table and conflicts are resolved on the insert level +func (o *orm) UpsertTokenPricesForDestChain(ctx context.Context, destChainSelector uint64, tokenPrices []TokenPrice, interval time.Duration) (int64, error) { if len(tokenPrices) == 0 { - return nil + return 0, nil } - insertData := make([]map[string]interface{}, 0, len(tokenPrices)) - for _, price := range tokenPrices { + tokensToUpdate, err := o.pickOnlyRelevantTokensForUpdate(ctx, destChainSelector, tokenPrices, interval) + if err != nil || len(tokensToUpdate) == 0 { + return 0, err + } + + insertData := make([]map[string]interface{}, 0, len(tokensToUpdate)) + for _, price := range tokensToUpdate { insertData = append(insertData, map[string]interface{}{ "chain_selector": destChainSelector, - "job_id": jobId, "token_addr": price.TokenAddr, "token_price": price.TokenPrice, }) } - // using statement_timestamp() to make testing easier - stmt := `INSERT INTO ccip.observed_token_prices (chain_selector, job_id, token_addr, token_price, created_at) - VALUES (:chain_selector, :job_id, :token_addr, :token_price, statement_timestamp());` - _, err := o.ds.NamedExecContext(ctx, stmt, insertData) + stmt := `INSERT INTO ccip.observed_token_prices (chain_selector, token_addr, token_price, updated_at) + VALUES (:chain_selector, :token_addr, :token_price, statement_timestamp()) + ON CONFLICT (token_addr, chain_selector) + DO UPDATE SET token_price = EXCLUDED.token_price, updated_at = EXCLUDED.updated_at;` + result, err := o.ds.NamedExecContext(ctx, stmt, insertData) if err != nil { - err = fmt.Errorf("error inserting token prices for job %d: %w", jobId, err) + return 0, fmt.Errorf("error inserting token prices %w", err) } - - return err + return result.RowsAffected() } -func (o *orm) ClearGasPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { - stmt := `DELETE FROM ccip.observed_gas_prices WHERE chain_selector = $1 AND created_at < (statement_timestamp() - $2 * interval '1 second')` +// pickOnlyRelevantTokensForUpdate returns only tokens that need to be updated. Multiple jobs can be updating the same tokens, +// in order to reduce table locking and redundant upserts we start with reading the table and checking which tokens are eligible for update. +// A token is eligible for update when time since last update is greater than the interval. +func (o *orm) pickOnlyRelevantTokensForUpdate( + ctx context.Context, + destChainSelector uint64, + tokenPrices []TokenPrice, + interval time.Duration, +) ([]TokenPrice, error) { + tokenPricesByAddress := toTokensByAddress(tokenPrices) + + // Picks only tokens which were recently updated and can be ignored, + // we will filter out these tokens from the upsert query. + stmt := ` + SELECT + token_addr + FROM ccip.observed_token_prices + WHERE + chain_selector = $1 + and token_addr = any($2) + and updated_at >= statement_timestamp() - $3::interval + ` + + pgInterval := fmt.Sprintf("%d milliseconds", interval.Milliseconds()) + args := []interface{}{destChainSelector, tokenAddrsToBytes(tokenPricesByAddress), pgInterval} + var dbTokensToIgnore []string + if err := o.ds.SelectContext(ctx, &dbTokensToIgnore, stmt, args...); err != nil { + return nil, err + } + + tokensToIgnore := make(map[string]struct{}, len(dbTokensToIgnore)) + for _, tk := range dbTokensToIgnore { + tokensToIgnore[tk] = struct{}{} + } - _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, expireSec) - return err + tokenPricesToUpdate := make([]TokenPrice, 0, len(tokenPrices)) + for tokenAddr, tokenPrice := range tokenPricesByAddress { + eligibleForUpdate := false + if _, ok := tokensToIgnore[tokenAddr]; !ok { + eligibleForUpdate = true + tokenPricesToUpdate = append(tokenPricesToUpdate, TokenPrice{TokenAddr: tokenAddr, TokenPrice: tokenPrice}) + } + o.lggr.Debugw( + "Token price eligibility for database update", + "eligibleForUpdate", eligibleForUpdate, + "token", tokenAddr, + "price", tokenPrice, + ) + } + return tokenPricesToUpdate, nil } -func (o *orm) ClearTokenPricesByDestChain(ctx context.Context, destChainSelector uint64, expireSec int) error { - stmt := `DELETE FROM ccip.observed_token_prices WHERE chain_selector = $1 AND created_at < (statement_timestamp() - $2 * interval '1 second')` +func toTokensByAddress(tokens []TokenPrice) map[string]*assets.Wei { + tokensByAddr := make(map[string]*assets.Wei, len(tokens)) + for _, tk := range tokens { + tokensByAddr[tk.TokenAddr] = tk.TokenPrice + } + return tokensByAddr +} - _, err := o.ds.ExecContext(ctx, stmt, destChainSelector, expireSec) - return err +func tokenAddrsToBytes(tokens map[string]*assets.Wei) [][]byte { + addrs := make([][]byte, 0, len(tokens)) + for tkAddr := range tokens { + addrs = append(addrs, []byte(tkAddr)) + } + return addrs } diff --git a/core/services/ccip/orm_test.go b/core/services/ccip/orm_test.go index 7b7b8d82710..e778ddf6ce3 100644 --- a/core/services/ccip/orm_test.go +++ b/core/services/ccip/orm_test.go @@ -15,13 +15,18 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var ( + r = rand.New(rand.NewSource(time.Now().UnixNano())) ) func setupORM(t *testing.T) (ORM, sqlutil.DataSource) { t.Helper() db := pgtest.NewSqlxDB(t) - orm, err := NewORM(db) + orm, err := NewORM(db, logger.TestLogger(t)) require.NoError(t, err) @@ -37,12 +42,12 @@ func generateChainSelectors(n int) []uint64 { return selectors } -func generateGasPriceUpdates(chainSelector uint64, n int) []GasPriceUpdate { - updates := make([]GasPriceUpdate, n) +func generateGasPrices(chainSelector uint64, n int) []GasPrice { + updates := make([]GasPrice, n) for i := 0; i < n; i++ { // gas prices can take up whole range of uint256 uint256Max := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1)) - row := GasPriceUpdate{ + row := GasPrice{ SourceChainSelector: chainSelector, GasPrice: assets.NewWei(new(big.Int).Sub(uint256Max, big.NewInt(int64(i)))), } @@ -61,10 +66,21 @@ func generateTokenAddresses(n int) []string { return addrs } -func generateTokenPriceUpdates(tokenAddr string, n int) []TokenPriceUpdate { - updates := make([]TokenPriceUpdate, n) +func generateRandomTokenPrices(tokenAddrs []string) []TokenPrice { + updates := make([]TokenPrice, 0, len(tokenAddrs)) + for _, addr := range tokenAddrs { + updates = append(updates, TokenPrice{ + TokenAddr: addr, + TokenPrice: assets.NewWei(new(big.Int).Rand(r, big.NewInt(1e18))), + }) + } + return updates +} + +func generateTokenPrices(tokenAddr string, n int) []TokenPrice { + updates := make([]TokenPrice, n) for i := 0; i < n; i++ { - row := TokenPriceUpdate{ + row := TokenPrice{ TokenAddr: tokenAddr, TokenPrice: assets.NewWei(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(int64(i)))), } @@ -134,20 +150,20 @@ func TestORM_InsertAndGetGasPrices(t *testing.T) { sourceSelectors := generateChainSelectors(numSourceChainSelectors) - updates := make(map[uint64][]GasPriceUpdate) + updates := make(map[uint64][]GasPrice) for _, selector := range sourceSelectors { - updates[selector] = generateGasPriceUpdates(selector, numUpdatesPerSourceSelector) + updates[selector] = generateGasPrices(selector, numUpdatesPerSourceSelector) } // 5 jobs, each inserting prices for 10 chains, with 20 updates per chain. - expectedPrices := make(map[uint64]GasPriceUpdate) + expectedPrices := make(map[uint64]GasPrice) for i := 0; i < numJobs; i++ { for selector, updatesPerSelector := range updates { lastIndex := len(updatesPerSelector) - 1 - err := orm.InsertGasPricesForDestChain(ctx, destSelector, int32(i), updatesPerSelector[:lastIndex]) + _, err := orm.UpsertGasPricesForDestChain(ctx, destSelector, updatesPerSelector[:lastIndex]) assert.NoError(t, err) - err = orm.InsertGasPricesForDestChain(ctx, destSelector, int32(i), updatesPerSelector[lastIndex:]) + _, err = orm.UpsertGasPricesForDestChain(ctx, destSelector, updatesPerSelector[lastIndex:]) assert.NoError(t, err) expectedPrices[selector] = updatesPerSelector[lastIndex] @@ -156,7 +172,7 @@ func TestORM_InsertAndGetGasPrices(t *testing.T) { // verify number of rows inserted numRows := getGasTableRowCount(t, db) - assert.Equal(t, numJobs*numSourceChainSelectors*numUpdatesPerSourceSelector, numRows) + assert.Equal(t, numSourceChainSelectors, numRows) prices, err := orm.GetGasPricesByDestChain(ctx, destSelector) assert.NoError(t, err) @@ -170,15 +186,15 @@ func TestORM_InsertAndGetGasPrices(t *testing.T) { } // after the initial inserts, insert new round of prices, 1 price per selector this time - var combinedUpdates []GasPriceUpdate + var combinedUpdates []GasPrice for selector, updatesPerSelector := range updates { combinedUpdates = append(combinedUpdates, updatesPerSelector[0]) expectedPrices[selector] = updatesPerSelector[0] } - err = orm.InsertGasPricesForDestChain(ctx, destSelector, 1, combinedUpdates) + _, err = orm.UpsertGasPricesForDestChain(ctx, destSelector, combinedUpdates) assert.NoError(t, err) - assert.Equal(t, numJobs*numSourceChainSelectors*numUpdatesPerSourceSelector+numSourceChainSelectors, getGasTableRowCount(t, db)) + assert.Equal(t, numSourceChainSelectors, getGasTableRowCount(t, db)) prices, err = orm.GetGasPricesByDestChain(ctx, destSelector) assert.NoError(t, err) @@ -190,7 +206,7 @@ func TestORM_InsertAndGetGasPrices(t *testing.T) { } } -func TestORM_InsertAndDeleteGasPrices(t *testing.T) { +func TestORM_UpsertGasPrices(t *testing.T) { t.Parallel() ctx := testutils.Context(t) @@ -202,13 +218,13 @@ func TestORM_InsertAndDeleteGasPrices(t *testing.T) { sourceSelectors := generateChainSelectors(numSourceChainSelectors) - updates := make(map[uint64][]GasPriceUpdate) + updates := make(map[uint64][]GasPrice) for _, selector := range sourceSelectors { - updates[selector] = generateGasPriceUpdates(selector, numUpdatesPerSourceSelector) + updates[selector] = generateGasPrices(selector, numUpdatesPerSourceSelector) } for _, updatesPerSelector := range updates { - err := orm.InsertGasPricesForDestChain(ctx, destSelector, 1, updatesPerSelector) + _, err := orm.UpsertGasPricesForDestChain(ctx, destSelector, updatesPerSelector) assert.NoError(t, err) } @@ -217,21 +233,11 @@ func TestORM_InsertAndDeleteGasPrices(t *testing.T) { // insert for the 2nd time after interimTimeStamp for _, updatesPerSelector := range updates { - err := orm.InsertGasPricesForDestChain(ctx, destSelector, 1, updatesPerSelector) + _, err := orm.UpsertGasPricesForDestChain(ctx, destSelector, updatesPerSelector) assert.NoError(t, err) } - assert.Equal(t, 2*numSourceChainSelectors*numUpdatesPerSourceSelector, getGasTableRowCount(t, db)) - - // clear by sleepSec should delete rows inserted before it - err := orm.ClearGasPricesByDestChain(ctx, destSelector, sleepSec) - assert.NoError(t, err) - assert.Equal(t, numSourceChainSelectors*numUpdatesPerSourceSelector, getGasTableRowCount(t, db)) - - // clear by 0 expiration seconds should delete all rows - err = orm.ClearGasPricesByDestChain(ctx, destSelector, 0) - assert.NoError(t, err) - assert.Equal(t, 0, getGasTableRowCount(t, db)) + assert.Equal(t, numSourceChainSelectors, getGasTableRowCount(t, db)) } func TestORM_InsertAndGetTokenPrices(t *testing.T) { @@ -247,20 +253,20 @@ func TestORM_InsertAndGetTokenPrices(t *testing.T) { addrs := generateTokenAddresses(numAddresses) - updates := make(map[string][]TokenPriceUpdate) + updates := make(map[string][]TokenPrice) for _, addr := range addrs { - updates[addr] = generateTokenPriceUpdates(addr, numUpdatesPerAddress) + updates[addr] = generateTokenPrices(addr, numUpdatesPerAddress) } // 5 jobs, each inserting prices for 10 chains, with 20 updates per chain. - expectedPrices := make(map[string]TokenPriceUpdate) + expectedPrices := make(map[string]TokenPrice) for i := 0; i < numJobs; i++ { for addr, updatesPerAddr := range updates { lastIndex := len(updatesPerAddr) - 1 - err := orm.InsertTokenPricesForDestChain(ctx, destSelector, int32(i), updatesPerAddr[:lastIndex]) + _, err := orm.UpsertTokenPricesForDestChain(ctx, destSelector, updatesPerAddr[:lastIndex], 0) assert.NoError(t, err) - err = orm.InsertTokenPricesForDestChain(ctx, destSelector, int32(i), updatesPerAddr[lastIndex:]) + _, err = orm.UpsertTokenPricesForDestChain(ctx, destSelector, updatesPerAddr[lastIndex:], 0) assert.NoError(t, err) expectedPrices[addr] = updatesPerAddr[lastIndex] @@ -269,7 +275,7 @@ func TestORM_InsertAndGetTokenPrices(t *testing.T) { // verify number of rows inserted numRows := getTokenTableRowCount(t, db) - assert.Equal(t, numJobs*numAddresses*numUpdatesPerAddress, numRows) + assert.Equal(t, numAddresses, numRows) prices, err := orm.GetTokenPricesByDestChain(ctx, destSelector) assert.NoError(t, err) @@ -283,15 +289,15 @@ func TestORM_InsertAndGetTokenPrices(t *testing.T) { } // after the initial inserts, insert new round of prices, 1 price per selector this time - var combinedUpdates []TokenPriceUpdate + var combinedUpdates []TokenPrice for addr, updatesPerAddr := range updates { combinedUpdates = append(combinedUpdates, updatesPerAddr[0]) expectedPrices[addr] = updatesPerAddr[0] } - err = orm.InsertTokenPricesForDestChain(ctx, destSelector, 1, combinedUpdates) + _, err = orm.UpsertTokenPricesForDestChain(ctx, destSelector, combinedUpdates, 0) assert.NoError(t, err) - assert.Equal(t, numJobs*numAddresses*numUpdatesPerAddress+numAddresses, getTokenTableRowCount(t, db)) + assert.Equal(t, numAddresses, getTokenTableRowCount(t, db)) prices, err = orm.GetTokenPricesByDestChain(ctx, destSelector) assert.NoError(t, err) @@ -303,46 +309,68 @@ func TestORM_InsertAndGetTokenPrices(t *testing.T) { } } -func TestORM_InsertAndDeleteTokenPrices(t *testing.T) { +func TestORM_InsertTokenPricesWhenExpired(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - - orm, db := setupORM(t) + orm, _ := setupORM(t) numAddresses := 10 - numUpdatesPerAddress := 20 - destSelector := uint64(1) - + destSelector := rand.Uint64() addrs := generateTokenAddresses(numAddresses) + initTokenUpdates := generateRandomTokenPrices(addrs) - updates := make(map[string][]TokenPriceUpdate) - for _, addr := range addrs { - updates[addr] = generateTokenPriceUpdates(addr, numUpdatesPerAddress) - } + // Insert the first time, table is initialized + rowsUpdated, err := orm.UpsertTokenPricesForDestChain(ctx, destSelector, initTokenUpdates, time.Minute) + require.NoError(t, err) + assert.Equal(t, int64(numAddresses), rowsUpdated) - for _, updatesPerAddr := range updates { - err := orm.InsertTokenPricesForDestChain(ctx, destSelector, 1, updatesPerAddr) - assert.NoError(t, err) - } + //time.Sleep(100 * time.Millisecond) - sleepSec := 2 - time.Sleep(time.Duration(sleepSec) * time.Second) + // Insert the second time, no updates, because prices haven't changed + rowsUpdated, err = orm.UpsertTokenPricesForDestChain(ctx, destSelector, initTokenUpdates, time.Minute) + require.NoError(t, err) + assert.Equal(t, int64(0), rowsUpdated) - // insert for the 2nd time after interimTimeStamp - for _, updatesPerAddr := range updates { - err := orm.InsertTokenPricesForDestChain(ctx, destSelector, 1, updatesPerAddr) - assert.NoError(t, err) + // There are new prices, but we still haven't reached interval + newPrices := generateRandomTokenPrices(addrs) + rowsUpdated, err = orm.UpsertTokenPricesForDestChain(ctx, destSelector, newPrices, time.Minute) + require.NoError(t, err) + assert.Equal(t, int64(0), rowsUpdated) + + time.Sleep(100 * time.Millisecond) + + // Again with the same new prices, but this time interval is reached + rowsUpdated, err = orm.UpsertTokenPricesForDestChain(ctx, destSelector, newPrices, time.Millisecond) + require.NoError(t, err) + assert.Equal(t, int64(numAddresses), rowsUpdated) + + dbTokenPrices, err := orm.GetTokenPricesByDestChain(ctx, destSelector) + require.NoError(t, err) + assert.Len(t, dbTokenPrices, numAddresses) + + dbTokenPricesByAddr := toTokensByAddress(dbTokenPrices) + for _, tkPrice := range newPrices { + dbToken, ok := dbTokenPricesByAddr[tkPrice.TokenAddr] + assert.True(t, ok) + assert.Equal(t, dbToken, tkPrice.TokenPrice) } +} - assert.Equal(t, 2*numAddresses*numUpdatesPerAddress, getTokenTableRowCount(t, db)) +func Benchmark_UpsertsTheSameTokenPrices(b *testing.B) { + db := pgtest.NewSqlxDB(b) + orm, err := NewORM(db, logger.NullLogger) + require.NoError(b, err) - // clear by sleepSec should delete rows inserted before it - err := orm.ClearTokenPricesByDestChain(ctx, destSelector, sleepSec) - assert.NoError(t, err) - assert.Equal(t, numAddresses*numUpdatesPerAddress, getTokenTableRowCount(t, db)) + ctx := testutils.Context(b) + numAddresses := 50 + destSelector := rand.Uint64() + addrs := generateTokenAddresses(numAddresses) + tokenUpdates := generateRandomTokenPrices(addrs) - // clear by 0 expiration seconds should delete all rows - err = orm.ClearTokenPricesByDestChain(ctx, destSelector, 0) - assert.NoError(t, err) - assert.Equal(t, 0, getTokenTableRowCount(t, db)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, err1 := orm.UpsertTokenPricesForDestChain(ctx, destSelector, tokenUpdates, time.Second) + require.NoError(b, err1) + } } diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index a3f46fc8a9f..a0a50477614 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -14,6 +14,9 @@ import ( "github.com/grafana/pyroscope-go" "github.com/jonboulle/clockwork" "github.com/pkg/errors" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "go.uber.org/multierr" "go.uber.org/zap/zapcore" @@ -23,11 +26,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip" + gatewayconnector "github.com/smartcontractkit/chainlink/v2/core/capabilities/gateway_connector" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -49,6 +52,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/llo" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" @@ -179,9 +183,11 @@ type ApplicationOpts struct { LoopRegistry *plugins.LoopRegistry GRPCOpts loop.GRPCOpts MercuryPool wsrpc.Pool + RetirementReportCache llo.RetirementReportCache CapabilitiesRegistry *capabilities.Registry CapabilitiesDispatcher remotetypes.Dispatcher CapabilitiesPeerWrapper p2ptypes.PeerWrapper + NewOracleFactoryFn standardcapabilities.NewOracleFactoryFn } // NewApplication initializes a new store if one is not already @@ -213,7 +219,10 @@ func NewApplication(opts ApplicationOpts) (Application, error) { externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) signer := externalPeer externalPeerWrapper = externalPeer - remoteDispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) + remoteDispatcher, err := remote.NewDispatcher(cfg.Capabilities().Dispatcher(), externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) + if err != nil { + return nil, fmt.Errorf("could not create dispatcher: %w", err) + } dispatcher = remoteDispatcher } else { dispatcher = opts.CapabilitiesDispatcher @@ -257,6 +266,20 @@ func NewApplication(opts ApplicationOpts) (Application, error) { srvcs = append(srvcs, wfLauncher, registrySyncer) } + } else { + globalLogger.Debug("External registry not configured, skipping registry syncer and starting with an empty registry") + opts.CapabilitiesRegistry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) + } + + var gatewayConnectorWrapper *gatewayconnector.ServiceWrapper + if cfg.Capabilities().GatewayConnector().DonID() != "" { + globalLogger.Debugw("Creating GatewayConnector wrapper", "donID", cfg.Capabilities().GatewayConnector().DonID()) + gatewayConnectorWrapper = gatewayconnector.NewGatewayConnectorServiceWrapper( + cfg.Capabilities().GatewayConnector(), + keyStore.Eth(), + clockwork.NewRealClock(), + globalLogger) + srvcs = append(srvcs, gatewayConnectorWrapper) } // LOOPs can be created as options, in the case of LOOP relayers, or @@ -265,7 +288,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { // we need to initialize in case we serve OCR2 LOOPs loopRegistry := opts.LoopRegistry if loopRegistry == nil { - loopRegistry = plugins.NewLoopRegistry(globalLogger, opts.Config.Tracing()) + loopRegistry = plugins.NewLoopRegistry(globalLogger, opts.Config.Tracing(), opts.Config.Telemetry()) } // If the audit logger is enabled @@ -313,6 +336,9 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if opts.MercuryPool != nil { srvcs = append(srvcs, opts.MercuryPool) } + if opts.RetirementReportCache != nil { + srvcs = append(srvcs, opts.RetirementReportCache) + } // EVM chains are used all over the place. This will need to change for fully EVM extraction // TODO: BCF-2510, BCF-2511 @@ -368,7 +394,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { for i, chain := range legacyEVMChains.Slice() { chainIDs[i] = chain.ID() } - telemReporter := headreporter.NewTelemetryReporter(telemetryManager, chainIDs...) + telemReporter := headreporter.NewTelemetryReporter(telemetryManager, globalLogger, chainIDs...) headReporter := headreporter.NewHeadReporterService(opts.DS, globalLogger, promReporter, telemReporter) srvcs = append(srvcs, headReporter) for _, chain := range legacyEVMChains.Slice() { @@ -432,14 +458,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { pipelineRunner, cfg.JobPipeline(), ), - job.StandardCapabilities: standardcapabilities.NewDelegate( - globalLogger, - opts.DS, jobORM, - opts.CapabilitiesRegistry, - loopRegistrarConfig, - telemetryManager, - pipelineRunner, - opts.RelayerChainInteroperators), } webhookJobRunner = delegates[job.Webhook].(*webhook.Delegate).WebhookJobRunner() ) @@ -479,6 +497,21 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("P2P stack required for OCR or OCR2") } + // If peer wrapper is initialized, Oracle Factory dependency will be available to standard capabilities + delegates[job.StandardCapabilities] = standardcapabilities.NewDelegate( + globalLogger, + opts.DS, jobORM, + opts.CapabilitiesRegistry, + loopRegistrarConfig, + telemetryManager, + pipelineRunner, + opts.RelayerChainInteroperators, + gatewayConnectorWrapper, + keyStore, + peerWrapper, + opts.NewOracleFactoryFn, + ) + if cfg.OCR().Enabled() { delegates[job.OffchainReporting] = ocr.NewDelegate( opts.DS, @@ -502,22 +535,25 @@ func NewApplication(opts ApplicationOpts) (Application, error) { ocr2DelegateConfig := ocr2.NewDelegateConfig(cfg.OCR2(), cfg.Mercury(), cfg.Threshold(), cfg.Insecure(), cfg.JobPipeline(), loopRegistrarConfig) delegates[job.OffchainReporting2] = ocr2.NewDelegate( - opts.DS, - jobORM, - bridgeORM, - mercuryORM, - pipelineRunner, - streamRegistry, - peerWrapper, - telemetryManager, - legacyEVMChains, - globalLogger, + ocr2.DelegateOpts{ + Ds: opts.DS, + JobORM: jobORM, + BridgeORM: bridgeORM, + MercuryORM: mercuryORM, + PipelineRunner: pipelineRunner, + StreamRegistry: streamRegistry, + PeerWrapper: peerWrapper, + MonitoringEndpointGen: telemetryManager, + LegacyChains: legacyEVMChains, + Lggr: globalLogger, + Ks: keyStore.OCR2(), + EthKs: keyStore.Eth(), + Relayers: opts.RelayerChainInteroperators, + MailMon: mailMon, + CapabilitiesRegistry: opts.CapabilitiesRegistry, + RetirementReportCache: opts.RetirementReportCache, + }, ocr2DelegateConfig, - keyStore.OCR2(), - keyStore.Eth(), - opts.RelayerChainInteroperators, - mailMon, - opts.CapabilitiesRegistry, ) delegates[job.Bootstrap] = ocrbootstrap.NewDelegateBootstrap( opts.DS, @@ -532,13 +568,13 @@ func NewApplication(opts ApplicationOpts) (Application, error) { globalLogger, loopRegistrarConfig, pipelineRunner, - opts.RelayerChainInteroperators.LegacyEVMChains(), relayerChainInterops, opts.KeyStore, opts.DS, peerWrapper, telemetryManager, cfg.Capabilities(), + cfg.EVMConfigs(), ) } else { globalLogger.Debug("Off-chain reporting v2 disabled") @@ -571,6 +607,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { jobSpawner, keyStore, cfg, + cfg.Feature(), cfg.Insecure(), cfg.JobPipeline(), cfg.OCR(), @@ -642,6 +679,14 @@ func (app *ChainlinkApplication) Start(ctx context.Context) error { panic("application is already started") } + var span trace.Span + ctx, span = otel.Tracer("").Start(ctx, "Start", trace.WithAttributes( + attribute.String("app-id", app.ID().String()), + attribute.String("version", static.Version), + attribute.String("commit", static.Sha), + )) + defer span.End() + if app.FeedsService != nil { if err := app.FeedsService.Start(ctx); err != nil { app.logger.Errorf("[Feeds Service] Failed to start %v", err) diff --git a/core/services/chainlink/cfgtest/cfgtest.go b/core/services/chainlink/cfgtest/cfgtest.go index 3bf95452650..1dfba71d469 100644 --- a/core/services/chainlink/cfgtest/cfgtest.go +++ b/core/services/chainlink/cfgtest/cfgtest.go @@ -76,7 +76,7 @@ func assertValNotNil(t *testing.T, key string, val reflect.Value) error { t.Helper() k := val.Kind() switch k { //nolint:exhaustive - case reflect.Ptr, reflect.Map: + case reflect.Ptr: if val.IsNil() { return fmt.Errorf("%s: nil", key) } @@ -94,6 +94,9 @@ func assertValNotNil(t *testing.T, key string, val reflect.Value) error { } return assertFieldsNotNil(t, key, val) case reflect.Map: + if val.IsNil() { + return nil // not actually a problem + } return assertValuesNotNil(t, key, val) case reflect.Slice: if val.IsNil() { diff --git a/core/services/chainlink/config_capabilities.go b/core/services/chainlink/config_capabilities.go index c438ca249dd..032eec58bea 100644 --- a/core/services/chainlink/config_capabilities.go +++ b/core/services/chainlink/config_capabilities.go @@ -1,10 +1,9 @@ package chainlink import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" - - "github.com/smartcontractkit/chainlink-common/pkg/types" ) var _ config.Capabilities = (*capabilitiesConfig)(nil) @@ -23,6 +22,52 @@ func (c *capabilitiesConfig) ExternalRegistry() config.CapabilitiesExternalRegis } } +func (c *capabilitiesConfig) Dispatcher() config.Dispatcher { + return &dispatcher{d: c.c.Dispatcher} +} + +type dispatcher struct { + d toml.Dispatcher +} + +func (d *dispatcher) SupportedVersion() int { + return *d.d.SupportedVersion +} + +func (d *dispatcher) ReceiverBufferSize() int { + return *d.d.ReceiverBufferSize +} + +func (d *dispatcher) RateLimit() config.DispatcherRateLimit { + return &dispatcherRateLimit{r: d.d.RateLimit} +} + +type dispatcherRateLimit struct { + r toml.DispatcherRateLimit +} + +func (r *dispatcherRateLimit) GlobalRPS() float64 { + return *r.r.GlobalRPS +} + +func (r *dispatcherRateLimit) GlobalBurst() int { + return *r.r.GlobalBurst +} + +func (r *dispatcherRateLimit) PerSenderRPS() float64 { + return *r.r.PerSenderRPS +} + +func (r *dispatcherRateLimit) PerSenderBurst() int { + return *r.r.PerSenderBurst +} + +func (c *capabilitiesConfig) GatewayConnector() config.GatewayConnector { + return &gatewayConnector{ + c: c.c.GatewayConnector, + } +} + type capabilitiesExternalRegistry struct { c toml.ExternalRegistry } @@ -42,3 +87,50 @@ func (c *capabilitiesExternalRegistry) ChainID() string { func (c *capabilitiesExternalRegistry) Address() string { return *c.c.Address } + +type gatewayConnector struct { + c toml.GatewayConnector +} + +func (c *gatewayConnector) ChainIDForNodeKey() string { + return *c.c.ChainIDForNodeKey +} +func (c *gatewayConnector) NodeAddress() string { + return *c.c.NodeAddress +} + +func (c *gatewayConnector) DonID() string { + return *c.c.DonID +} + +func (c *gatewayConnector) Gateways() []config.ConnectorGateway { + t := make([]config.ConnectorGateway, len(c.c.Gateways)) + for index, element := range c.c.Gateways { + t[index] = &connectorGateway{element} + } + return t +} + +func (c *gatewayConnector) WSHandshakeTimeoutMillis() uint32 { + return *c.c.WSHandshakeTimeoutMillis +} + +func (c *gatewayConnector) AuthMinChallengeLen() int { + return *c.c.AuthMinChallengeLen +} + +func (c *gatewayConnector) AuthTimestampToleranceSec() uint32 { + return *c.c.AuthTimestampToleranceSec +} + +type connectorGateway struct { + c toml.ConnectorGateway +} + +func (c *connectorGateway) ID() string { + return *c.c.ID +} + +func (c *connectorGateway) URL() string { + return *c.c.URL +} diff --git a/core/services/chainlink/config_feature.go b/core/services/chainlink/config_feature.go index 2e968df052d..f5cc8786411 100644 --- a/core/services/chainlink/config_feature.go +++ b/core/services/chainlink/config_feature.go @@ -17,3 +17,7 @@ func (f *featureConfig) LogPoller() bool { func (f *featureConfig) UICSAKeys() bool { return *f.c.UICSAKeys } + +func (f *featureConfig) MultiFeedsManagers() bool { + return *f.c.MultiFeedsManagers +} diff --git a/core/services/chainlink/config_feature_test.go b/core/services/chainlink/config_feature_test.go index bc0418c157b..8fa5884450a 100644 --- a/core/services/chainlink/config_feature_test.go +++ b/core/services/chainlink/config_feature_test.go @@ -18,4 +18,5 @@ func TestFeatureConfig(t *testing.T) { assert.True(t, f.LogPoller()) assert.True(t, f.FeedsManager()) assert.True(t, f.UICSAKeys()) + assert.True(t, f.MultiFeedsManagers()) } diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index 79c92f82145..dd0dc87b59a 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -524,5 +524,8 @@ func (g *generalConfig) Threshold() coreconfig.Threshold { func (g *generalConfig) Tracing() coreconfig.Tracing { return &tracingConfig{s: g.c.Tracing} } +func (g *generalConfig) Telemetry() coreconfig.Telemetry { + return &telemetryConfig{s: g.c.Telemetry} +} var zeroSha256Hash = models.Sha256Hash{} diff --git a/core/services/chainlink/config_telemetry.go b/core/services/chainlink/config_telemetry.go new file mode 100644 index 00000000000..790f2a19953 --- /dev/null +++ b/core/services/chainlink/config_telemetry.go @@ -0,0 +1,43 @@ +package chainlink + +import ( + "github.com/smartcontractkit/chainlink/v2/core/config/toml" +) + +type telemetryConfig struct { + s toml.Telemetry +} + +func (b *telemetryConfig) Enabled() bool { return *b.s.Enabled } + +func (b *telemetryConfig) InsecureConnection() bool { + if b.s.InsecureConnection == nil { + return false + } + return *b.s.InsecureConnection +} + +func (b *telemetryConfig) CACertFile() string { + if b.s.CACertFile == nil { + return "" + } + return *b.s.CACertFile +} + +func (b *telemetryConfig) OtelExporterGRPCEndpoint() string { + if b.s.Endpoint == nil { + return "" + } + return *b.s.Endpoint +} + +func (b *telemetryConfig) ResourceAttributes() map[string]string { + return b.s.ResourceAttributes +} + +func (b *telemetryConfig) TraceSampleRatio() float64 { + if b.s.TraceSampleRatio == nil { + return 0.0 + } + return *b.s.TraceSampleRatio +} diff --git a/core/services/chainlink/config_telemetry_ingress_test.go b/core/services/chainlink/config_telemetry_ingress_test.go index c371b465a2b..64e85b5493e 100644 --- a/core/services/chainlink/config_telemetry_ingress_test.go +++ b/core/services/chainlink/config_telemetry_ingress_test.go @@ -17,7 +17,7 @@ func TestTelemetryIngressConfig(t *testing.T) { ticfg := cfg.TelemetryIngress() assert.True(t, ticfg.Logging()) - assert.True(t, ticfg.UniConn()) + assert.False(t, ticfg.UniConn()) assert.Equal(t, uint(1234), ticfg.BufferSize()) assert.Equal(t, uint(4321), ticfg.MaxBatchSize()) assert.Equal(t, time.Minute, ticfg.SendInterval()) diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 5fc9babe77b..4171c7af164 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -47,6 +47,10 @@ var ( //go:embed testdata/config-multi-chain.toml multiChainTOML string + second = *commoncfg.MustNewDuration(time.Second) + minute = *commoncfg.MustNewDuration(time.Minute) + selectionMode = client.NodeSelectionModeHighestHead + multiChain = Config{ Core: toml.Core{ RootDir: ptr("my/root/dir"), @@ -102,7 +106,7 @@ var ( ChainID: ubig.NewI(1), Chain: evmcfg.Chain{ FinalityDepth: ptr[uint32](26), - FinalityTagEnabled: ptr[bool](false), + FinalityTagEnabled: ptr[bool](true), FinalizedBlockOffset: ptr[uint32](12), }, Nodes: []*evmcfg.Node{ @@ -167,6 +171,25 @@ var ( Chain: solcfg.Chain{ MaxRetries: ptr[int64](12), }, + MultiNode: solcfg.MultiNodeConfig{ + MultiNode: solcfg.MultiNode{ + Enabled: ptr(false), + PollFailureThreshold: ptr[uint32](5), + PollInterval: &second, + SelectionMode: &selectionMode, + SyncThreshold: ptr[uint32](5), + NodeIsSyncingEnabled: ptr(false), + LeaseDuration: &minute, + FinalizedBlockPollInterval: &second, + EnforceRepeatableRead: ptr(true), + DeathDeclarationDelay: &minute, + NodeNoNewHeadsThreshold: &minute, + NoNewFinalizedHeadsThreshold: &minute, + FinalityDepth: ptr[uint32](0), + FinalityTagEnabled: ptr(true), + FinalizedBlockOffset: ptr[uint32](0), + }, + }, Nodes: []*solcfg.Node{ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://mainnet.solana.com")}, }, @@ -176,6 +199,25 @@ var ( Chain: solcfg.Chain{ OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), }, + MultiNode: solcfg.MultiNodeConfig{ + MultiNode: solcfg.MultiNode{ + Enabled: ptr(false), + PollFailureThreshold: ptr[uint32](5), + PollInterval: &second, + SelectionMode: &selectionMode, + SyncThreshold: ptr[uint32](5), + NodeIsSyncingEnabled: ptr(false), + LeaseDuration: &minute, + FinalizedBlockPollInterval: &second, + EnforceRepeatableRead: ptr(true), + DeathDeclarationDelay: &minute, + NodeNoNewHeadsThreshold: &minute, + NoNewFinalizedHeadsThreshold: &minute, + FinalityDepth: ptr[uint32](0), + FinalityTagEnabled: ptr(true), + FinalizedBlockOffset: ptr[uint32](0), + }, + }, Nodes: []*solcfg.Node{ {Name: ptr("secondary"), URL: commoncfg.MustParseURL("http://testnet.solana.com")}, }, @@ -258,10 +300,11 @@ func TestConfig_Marshal(t *testing.T) { } full.Feature = toml.Feature{ - FeedsManager: ptr(true), - LogPoller: ptr(true), - UICSAKeys: ptr(true), - CCIP: ptr(true), + FeedsManager: ptr(true), + LogPoller: ptr(true), + UICSAKeys: ptr(true), + CCIP: ptr(true), + MultiFeedsManagers: ptr(true), } full.Database = toml.Database{ DefaultIdleInTxSessionTimeout: commoncfg.MustNewDuration(time.Minute), @@ -289,7 +332,7 @@ func TestConfig_Marshal(t *testing.T) { }, } full.TelemetryIngress = toml.TelemetryIngress{ - UniConn: ptr(true), + UniConn: ptr(false), Logging: ptr(true), BufferSize: ptr[uint16](1234), MaxBatchSize: ptr[uint16](4321), @@ -451,6 +494,27 @@ func TestConfig_Marshal(t *testing.T) { ChainID: ptr("1"), NetworkID: ptr("evm"), }, + Dispatcher: toml.Dispatcher{ + SupportedVersion: ptr(1), + ReceiverBufferSize: ptr(10000), + RateLimit: toml.DispatcherRateLimit{ + GlobalRPS: ptr(800.0), + GlobalBurst: ptr(1000), + PerSenderRPS: ptr(10.0), + PerSenderBurst: ptr(50), + }, + }, + GatewayConnector: toml.GatewayConnector{ + ChainIDForNodeKey: ptr("11155111"), + NodeAddress: ptr("0x68902d681c28119f9b2531473a417088bf008e59"), + DonID: ptr("example_don"), + WSHandshakeTimeoutMillis: ptr[uint32](100), + AuthMinChallengeLen: ptr[int](10), + AuthTimestampToleranceSec: ptr[uint32](10), + Gateways: []toml.ConnectorGateway{ + {ID: ptr("example_gateway"), URL: ptr("wss://localhost:8081/node")}, + }, + }, } full.Keeper = toml.Keeper{ DefaultTransactionQueueDepth: ptr[uint32](17), @@ -491,6 +555,14 @@ func TestConfig_Marshal(t *testing.T) { Environment: ptr("dev"), Release: ptr("v1.2.3"), } + full.Telemetry = toml.Telemetry{ + Enabled: ptr(true), + CACertFile: ptr("cert-file"), + Endpoint: ptr("example.com/collector"), + InsecureConnection: ptr(true), + ResourceAttributes: map[string]string{"Baz": "test", "Foo": "bar"}, + TraceSampleRatio: ptr(0.01), + } full.EVM = []*evmcfg.EVMConfig{ { ChainID: ubig.NewI(1), @@ -502,9 +574,9 @@ func TestConfig_Marshal(t *testing.T) { }, BlockBackfillDepth: ptr[uint32](100), BlockBackfillSkip: ptr(true), - ChainType: chaintype.NewChainTypeConfig("Optimism"), + ChainType: chaintype.NewConfig("Optimism"), FinalityDepth: ptr[uint32](42), - FinalityTagEnabled: ptr[bool](false), + FinalityTagEnabled: ptr[bool](true), FlagsContractAddress: mustAddress("0xae4E781a6218A8031764928E88d457937A954fC3"), FinalizedBlockOffset: ptr[uint32](16), @@ -520,6 +592,7 @@ func TestConfig_Marshal(t *testing.T) { LimitMax: ptr[uint64](17), LimitMultiplier: mustDecimal("1.234"), LimitTransfer: ptr[uint64](100), + EstimateLimit: ptr(false), TipCapDefault: assets.NewWeiI(2), TipCapMin: assets.NewWeiI(1), PriceDefault: assets.NewWeiI(math.MaxInt64), @@ -543,6 +616,9 @@ func TestConfig_Marshal(t *testing.T) { EIP1559FeeCapBufferBlocks: ptr[uint16](13), TransactionPercentile: ptr[uint16](15), }, + FeeHistory: evmcfg.FeeHistoryEstimator{ + CacheTimeout: &second, + }, }, KeySpecific: []evmcfg.KeySpecific{ @@ -565,6 +641,7 @@ func TestConfig_Marshal(t *testing.T) { NonceAutoSync: ptr(true), NoNewHeadsThreshold: &minute, OperatorFactoryAddress: mustAddress("0xa5B85635Be42F21f94F28034B7DA440EeFF0F418"), + LogBroadcasterEnabled: ptr(true), RPCDefaultBatchSize: ptr[uint32](17), RPCBlockQueryDelay: ptr[uint16](10), NoNewFinalizedHeadsThreshold: &hour, @@ -587,6 +664,7 @@ func TestConfig_Marshal(t *testing.T) { SamplingInterval: &hour, FinalityTagBypass: ptr[bool](false), MaxAllowedFinalityDepth: ptr[uint32](1500), + PersistenceEnabled: ptr(false), }, NodePool: evmcfg.NodePool{ @@ -599,6 +677,7 @@ func TestConfig_Marshal(t *testing.T) { FinalizedBlockPollInterval: &second, EnforceRepeatableRead: ptr(true), DeathDeclarationDelay: &minute, + NewHeadsPollInterval: &zeroSeconds, Errors: evmcfg.ClientErrors{ NonceTooLow: ptr[string]("(: |^)nonce too low"), NonceTooHigh: ptr[string]("(: |^)nonce too high"), @@ -614,6 +693,7 @@ func TestConfig_Marshal(t *testing.T) { TransactionAlreadyMined: ptr[string]("(: |^)transaction already mined"), Fatal: ptr[string]("(: |^)fatal"), ServiceUnavailable: ptr[string]("(: |^)service unavailable"), + TooManyResults: ptr[string]("(: |^)too many results"), }, }, OCR: evmcfg.OCR{ @@ -629,6 +709,9 @@ func TestConfig_Marshal(t *testing.T) { GasLimit: ptr[uint32](540), }, }, + Workflow: evmcfg.Workflow{ + GasLimitDefault: ptr[uint64](400000), + }, }, Nodes: []*evmcfg.Node{ { @@ -653,27 +736,48 @@ func TestConfig_Marshal(t *testing.T) { ChainID: ptr("mainnet"), Enabled: ptr(false), Chain: solcfg.Chain{ - BalancePollPeriod: commoncfg.MustNewDuration(time.Minute), - ConfirmPollPeriod: commoncfg.MustNewDuration(time.Second), - OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), - OCR2CacheTTL: commoncfg.MustNewDuration(time.Hour), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - TxRetryTimeout: commoncfg.MustNewDuration(time.Minute), - TxConfirmTimeout: commoncfg.MustNewDuration(time.Second), - SkipPreflight: ptr(true), - Commitment: ptr("banana"), - MaxRetries: ptr[int64](7), - FeeEstimatorMode: ptr("fixed"), - ComputeUnitPriceMax: ptr[uint64](1000), - ComputeUnitPriceMin: ptr[uint64](10), - ComputeUnitPriceDefault: ptr[uint64](100), - FeeBumpPeriod: commoncfg.MustNewDuration(time.Minute), - BlockHistoryPollPeriod: commoncfg.MustNewDuration(time.Minute), + BalancePollPeriod: commoncfg.MustNewDuration(time.Minute), + ConfirmPollPeriod: commoncfg.MustNewDuration(time.Second), + OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), + OCR2CacheTTL: commoncfg.MustNewDuration(time.Hour), + TxTimeout: commoncfg.MustNewDuration(time.Hour), + TxRetryTimeout: commoncfg.MustNewDuration(time.Minute), + TxConfirmTimeout: commoncfg.MustNewDuration(time.Second), + SkipPreflight: ptr(true), + Commitment: ptr("banana"), + MaxRetries: ptr[int64](7), + FeeEstimatorMode: ptr("fixed"), + ComputeUnitPriceMax: ptr[uint64](1000), + ComputeUnitPriceMin: ptr[uint64](10), + ComputeUnitPriceDefault: ptr[uint64](100), + FeeBumpPeriod: commoncfg.MustNewDuration(time.Minute), + BlockHistoryPollPeriod: commoncfg.MustNewDuration(time.Minute), + ComputeUnitLimitDefault: ptr[uint32](100_000), + EstimateComputeUnitLimit: ptr(false), + }, + MultiNode: solcfg.MultiNodeConfig{ + MultiNode: solcfg.MultiNode{ + Enabled: ptr(false), + PollFailureThreshold: ptr[uint32](5), + PollInterval: &second, + SelectionMode: &selectionMode, + SyncThreshold: ptr[uint32](5), + NodeIsSyncingEnabled: ptr(false), + LeaseDuration: &minute, + FinalizedBlockPollInterval: &second, + EnforceRepeatableRead: ptr(true), + DeathDeclarationDelay: &minute, + NodeNoNewHeadsThreshold: &minute, + NoNewFinalizedHeadsThreshold: &minute, + FinalityDepth: ptr[uint32](0), + FinalityTagEnabled: ptr(true), + FinalizedBlockOffset: ptr[uint32](0), + }, }, Nodes: []*solcfg.Node{ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://solana.web")}, - {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo")}, - {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar")}, + {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo"), SendOnly: true}, + {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar"), SendOnly: true}, }, }, } @@ -773,6 +877,7 @@ FeedsManager = true LogPoller = true UICSAKeys = true CCIP = true +MultiFeedsManagers = true `}, {"Database", Config{Core: toml.Core{Database: full.Database}}, `[Database] DefaultIdleInTxSessionTimeout = '1m0s' @@ -800,7 +905,7 @@ LeaseDuration = '1m0s' LeaseRefreshInterval = '1s' `}, {"TelemetryIngress", Config{Core: toml.Core{TelemetryIngress: full.TelemetryIngress}}, `[TelemetryIngress] -UniConn = true +UniConn = false Logging = true BufferSize = 1234 MaxBatchSize = 4321 @@ -983,7 +1088,7 @@ BlockBackfillDepth = 100 BlockBackfillSkip = true ChainType = 'Optimism' FinalityDepth = 42 -FinalityTagEnabled = false +FinalityTagEnabled = true FlagsContractAddress = '0xae4E781a6218A8031764928E88d457937A954fC3' LinkContractAddress = '0x538aAaB4ea120b2bC2fe5D296852D948F07D849e' LogBackfillBatchSize = 17 @@ -996,6 +1101,7 @@ MinContractPayment = '9.223372036854775807 link' NonceAutoSync = true NoNewHeadsThreshold = '1m0s' OperatorFactoryAddress = '0xa5B85635Be42F21f94F28034B7DA440EeFF0F418' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 17 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 16 @@ -1024,6 +1130,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 @@ -1049,12 +1156,16 @@ CheckInclusionPercentile = 19 EIP1559FeeCapBufferBlocks = 13 TransactionPercentile = 15 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '1s' + [EVM.HeadTracker] HistoryDepth = 15 MaxBufferSize = 17 SamplingInterval = '1h0m0s' MaxAllowedFinalityDepth = 1500 FinalityTagBypass = false +PersistenceEnabled = false [[EVM.KeySpecific]] Key = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' @@ -1072,6 +1183,7 @@ NodeIsSyncingEnabled = true FinalizedBlockPollInterval = '1s' EnforceRepeatableRead = true DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' [EVM.NodePool.Errors] NonceTooLow = '(: |^)nonce too low' @@ -1088,6 +1200,7 @@ L2Full = '(: |^)l2 full' TransactionAlreadyMined = '(: |^)transaction already mined' Fatal = '(: |^)fatal' ServiceUnavailable = '(: |^)service unavailable' +TooManyResults = '(: |^)too many results' [EVM.OCR] ContractConfirmations = 11 @@ -1101,6 +1214,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 540 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'foo' WSURL = 'wss://web.socket/test/foo' @@ -1162,18 +1278,40 @@ ComputeUnitPriceMin = 10 ComputeUnitPriceDefault = 100 FeeBumpPeriod = '1m0s' BlockHistoryPollPeriod = '1m0s' +ComputeUnitLimitDefault = 100000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' URL = 'http://solana.web' +SendOnly = false [[Solana.Nodes]] Name = 'foo' URL = 'http://solana.foo' +SendOnly = true [[Solana.Nodes]] Name = 'bar' URL = 'http://solana.bar' +SendOnly = true `}, {"Starknet", Config{Starknet: full.Starknet}, `[[Starknet]] ChainID = 'foobar' @@ -1237,6 +1375,9 @@ func TestConfig_full(t *testing.T) { if got.EVM[c].Workflow.ForwarderAddress == nil { got.EVM[c].Workflow.ForwarderAddress = &addr } + if got.EVM[c].Workflow.GasLimitDefault == nil { + got.EVM[c].Workflow.GasLimitDefault = ptr(uint64(400000)) + } for n := range got.EVM[c].Nodes { if got.EVM[c].Nodes[n].WSURL == nil { got.EVM[c].Nodes[n].WSURL = new(commoncfg.URL) @@ -1257,6 +1398,9 @@ func TestConfig_full(t *testing.T) { if got.EVM[c].Transactions.AutoPurge.DetectionApiUrl == nil { got.EVM[c].Transactions.AutoPurge.DetectionApiUrl = new(commoncfg.URL) } + if got.EVM[c].GasEstimator.DAOracle.OracleAddress == nil { + got.EVM[c].GasEstimator.DAOracle.OracleAddress = new(types.EIP55Address) + } } cfgtest.AssertFieldsNotNil(t, got) @@ -1287,7 +1431,8 @@ func TestConfig_Validate(t *testing.T) { - 1.ChainID: invalid value (1): duplicate - must be unique - 0.Nodes.1.Name: invalid value (foo): duplicate - must be unique - 3.Nodes.4.WSURL: invalid value (ws://dupe.com): duplicate - must be unique - - 0: 3 errors: + - 0: 4 errors: + - Nodes: missing: 0th node (primary) must have a valid WSURL when LogBroadcaster is enabled - GasEstimator.BumpTxDepth: invalid value (11): must be less than or equal to Transactions.MaxInFlight - GasEstimator: 6 errors: - BumpPercent: invalid value (1): may not be less than Geth's default of 10 @@ -1297,14 +1442,12 @@ func TestConfig_Validate(t *testing.T) { - PriceMax: invalid value (10 gwei): must be greater than or equal to PriceDefault - BlockHistory.BlockHistorySize: invalid value (0): must be greater than or equal to 1 with BlockHistory Mode - Nodes: 2 errors: - - 0: 2 errors: - - WSURL: missing: required for primary nodes - - HTTPURL: missing: required for all nodes + - 0.HTTPURL: missing: required for all nodes - 1.HTTPURL: missing: required for all nodes - 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, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted + - 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 - 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 @@ -1317,21 +1460,22 @@ 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, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted + - 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 - 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.Nodes: 5 errors: - - 0: 3 errors: + - 3: 3 errors: + - Nodes: missing: 0th node (primary) must have a valid WSURL when LogBroadcaster is enabled + - Nodes: missing: 2th node (primary) must have a valid WSURL when LogBroadcaster is enabled + - Nodes: 5 errors: + - 0: 2 errors: - Name: missing: required for all nodes - - WSURL: missing: required for primary nodes - HTTPURL: empty: required for all nodes - 1: 3 errors: - Name: missing: required for all nodes - WSURL: invalid value (http): must be ws or wss - HTTPURL: missing: required for all nodes - - 2: 3 errors: + - 2: 2 errors: - Name: empty: required for all nodes - - WSURL: missing: required for primary nodes - HTTPURL: invalid value (ws): must be http or https - 3.HTTPURL: missing: required for all nodes - 4.HTTPURL: missing: required for all nodes diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index f4594a43225..63a846c6edb 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -1771,6 +1771,53 @@ func (_c *GeneralConfig_StarknetConfigs_Call) RunAndReturn(run func() chainlinkc return _c } +// Telemetry provides a mock function with given fields: +func (_m *GeneralConfig) Telemetry() config.Telemetry { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Telemetry") + } + + var r0 config.Telemetry + if rf, ok := ret.Get(0).(func() config.Telemetry); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(config.Telemetry) + } + } + + return r0 +} + +// GeneralConfig_Telemetry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Telemetry' +type GeneralConfig_Telemetry_Call struct { + *mock.Call +} + +// Telemetry is a helper method to define mock.On call +func (_e *GeneralConfig_Expecter) Telemetry() *GeneralConfig_Telemetry_Call { + return &GeneralConfig_Telemetry_Call{Call: _e.mock.On("Telemetry")} +} + +func (_c *GeneralConfig_Telemetry_Call) Run(run func()) *GeneralConfig_Telemetry_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GeneralConfig_Telemetry_Call) Return(_a0 config.Telemetry) *GeneralConfig_Telemetry_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GeneralConfig_Telemetry_Call) RunAndReturn(run func() config.Telemetry) *GeneralConfig_Telemetry_Call { + _c.Call.Return(run) + return _c +} + // TelemetryIngress provides a mock function with given fields: func (_m *GeneralConfig) TelemetryIngress() config.TelemetryIngress { ret := _m.Called() diff --git a/core/services/chainlink/mocks/relayer_chain_interoperators.go b/core/services/chainlink/mocks/relayer_chain_interoperators.go index 5b0815b6569..13fef0e3180 100644 --- a/core/services/chainlink/mocks/relayer_chain_interoperators.go +++ b/core/services/chainlink/mocks/relayer_chain_interoperators.go @@ -17,7 +17,7 @@ import ( // FakeRelayerChainInteroperators is a fake chainlink.RelayerChainInteroperators. // This exists because mockery generation doesn't understand how to produce an alias instead of the underlying type (which is not exported in this case). type FakeRelayerChainInteroperators struct { - Relayers []loop.Relayer + Relayers map[types.RelayID]loop.Relayer EVMChains legacyevm.LegacyChainContainer Nodes []types.NodeStatus NodesErr error @@ -44,11 +44,17 @@ func (f *FakeRelayerChainInteroperators) Get(id types.RelayID) (loop.Relayer, er } func (f *FakeRelayerChainInteroperators) GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) { - panic("unimplemented") + return f.Relayers, nil } func (f *FakeRelayerChainInteroperators) Slice() []loop.Relayer { - return f.Relayers + var relayers []loop.Relayer + + for _, value := range f.Relayers { + relayers = append(relayers, value) + } + + return relayers } func (f *FakeRelayerChainInteroperators) LegacyCosmosChains() chainlink.LegacyCosmosContainer { diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index ffcfc67b87d..8197b12ec7b 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -8,10 +8,10 @@ import ( "sync" "github.com/smartcontractkit/chainlink-common/pkg/loop" - relay "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -140,7 +140,6 @@ func InitCosmos(ctx context.Context, factory RelayerFactory, config CosmosFactor return fmt.Errorf("failed to setup Cosmos relayer: %w", err2) } legacyMap := make(map[string]cosmos.Chain) - for id, a := range adapters { op.srvs = append(op.srvs, a) op.loopRelayers[id] = a @@ -420,25 +419,24 @@ func NewLegacyCosmos(m map[string]adapters.Chain) *LegacyCosmos { return chains.NewChainsKV[adapters.Chain](m) } -type CosmosLoopRelayerChainer interface { +type LOOPRelayAdapter interface { loop.Relayer Chain() adapters.Chain } -type CosmosLoopRelayerChain struct { +type loopRelayAdapter struct { loop.Relayer chain adapters.Chain } -func NewCosmosLoopRelayerChain(r *cosmos.Relayer, s adapters.Chain) *CosmosLoopRelayerChain { - ra := relay.NewServerAdapter(r, s) - return &CosmosLoopRelayerChain{ - Relayer: ra, - chain: s, +func NewCosmosLOOPRelayerChain(r *cosmos.Relayer) *loopRelayAdapter { + return &loopRelayAdapter{ + Relayer: relay.NewServerAdapter(r), + chain: r.Chain(), } } -func (r *CosmosLoopRelayerChain) Chain() adapters.Chain { +func (r *loopRelayAdapter) Chain() adapters.Chain { return r.chain } -var _ CosmosLoopRelayerChainer = &CosmosLoopRelayerChain{} +var _ LOOPRelayAdapter = &loopRelayAdapter{} diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 5aaf6e16dd4..e83c2881c93 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -176,7 +176,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { factory := chainlink.RelayerFactory{ Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr, nil), + LoopRegistry: plugins.NewLoopRegistry(lggr, nil, nil), GRPCOpts: loop.GRPCOpts{}, CapabilitiesRegistry: capabilities.NewRegistry(lggr), } diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 3ddfe270477..3740878fd19 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -4,11 +4,11 @@ import ( "context" "errors" "fmt" + "net/http" "github.com/pelletier/go-toml/v2" "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" @@ -19,12 +19,14 @@ import ( pkgstarknet "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink" starkchain "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/chain" starkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - corerelay "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/services/llo" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/services/relay/dummy" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" @@ -35,8 +37,10 @@ type RelayerFactory struct { logger.Logger *plugins.LoopRegistry loop.GRPCOpts - MercuryPool wsrpc.Pool - CapabilitiesRegistry coretypes.CapabilitiesRegistry + MercuryPool wsrpc.Pool + CapabilitiesRegistry coretypes.CapabilitiesRegistry + HTTPClient *http.Client + RetirementReportCache llo.RetirementReportCache } type DummyFactoryConfig struct { @@ -53,46 +57,44 @@ type EVMFactoryConfig struct { coreconfig.MercuryTransmitter } -func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[types.RelayID]evmrelay.LoopRelayAdapter, error) { +func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[types.RelayID]evmrelay.LOOPRelayAdapter, error) { // TODO impl EVM loop. For now always 'fallback' to an adapter and embedded chain - relayers := make(map[types.RelayID]evmrelay.LoopRelayAdapter) + relayers := make(map[types.RelayID]evmrelay.LOOPRelayAdapter) lggr := r.Logger.Named("EVM") // override some common opts with the factory values. this seems weird... maybe other signatures should change, or this should take a different type... - ccOpts := legacyevm.ChainRelayExtenderConfig{ + ccOpts := legacyevm.ChainRelayOpts{ Logger: lggr, KeyStore: config.CSAETHKeystore.Eth(), ChainOpts: config.ChainOpts, } - evmRelayExtenders, err := evmrelay.NewChainRelayerExtenders(ctx, ccOpts) + legacyChains, err := evmrelay.NewLegacyChains(ctx, ccOpts) if err != nil { return nil, err } - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(evmRelayExtenders) - for _, ext := range evmRelayExtenders.Slice() { - relayID := types.RelayID{Network: corerelay.NetworkEVM, ChainID: ext.Chain().ID().String()} - chain, err2 := legacyChains.Get(relayID.ChainID) - if err2 != nil { - return nil, err2 - } + for _, chain := range legacyChains { + relayID := types.RelayID{Network: relay.NetworkEVM, ChainID: chain.ID().String()} + chain := chain relayerOpts := evmrelay.RelayerOpts{ - DS: ccOpts.DS, - CSAETHKeystore: config.CSAETHKeystore, - MercuryPool: r.MercuryPool, - TransmitterConfig: config.MercuryTransmitter, - CapabilitiesRegistry: r.CapabilitiesRegistry, + DS: ccOpts.DS, + CSAETHKeystore: config.CSAETHKeystore, + MercuryPool: r.MercuryPool, + TransmitterConfig: config.MercuryTransmitter, + CapabilitiesRegistry: r.CapabilitiesRegistry, + HTTPClient: r.HTTPClient, + RetirementReportCache: r.RetirementReportCache, } - relayer, err2 := evmrelay.NewRelayer(lggr.Named(relayID.ChainID), chain, relayerOpts) + relayer, err2 := evmrelay.NewRelayer(ctx, lggr.Named(relayID.ChainID), chain, relayerOpts) if err2 != nil { err = errors.Join(err, err2) continue } - relayers[relayID] = evmrelay.NewLoopRelayServerAdapter(relayer, ext) + relayers[relayID] = evmrelay.NewLOOPRelayAdapter(relayer) } // always return err because it is accumulating individual errors @@ -114,7 +116,7 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solcfg.TOMLConf unique := make(map[string]struct{}) // create one relayer per chain id for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: corerelay.NetworkSolana, ChainID: *chainCfg.ChainID} + relayID := types.RelayID{Network: relay.NetworkSolana, ChainID: *chainCfg.ChainID} _, alreadyExists := unique[relayID.Name()] if alreadyExists { return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) @@ -163,7 +165,7 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solcfg.TOMLConf if err != nil { return nil, err } - solanaRelayers[relayID] = relay.NewServerAdapter(solana.NewRelayer(lggr, chain, r.CapabilitiesRegistry), chain) + solanaRelayers[relayID] = relay.NewServerAdapter(solana.NewRelayer(lggr, chain, r.CapabilitiesRegistry)) } } return solanaRelayers, nil @@ -187,7 +189,7 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs starkcfg.TO unique := make(map[string]struct{}) // create one relayer per chain id for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: corerelay.NetworkStarkNet, ChainID: *chainCfg.ChainID} + relayID := types.RelayID{Network: relay.NetworkStarkNet, ChainID: *chainCfg.ChainID} _, alreadyExists := unique[relayID.Name()] if alreadyExists { return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) @@ -238,7 +240,7 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs starkcfg.TO return nil, err } - starknetRelayers[relayID] = relay.NewServerAdapter(pkgstarknet.NewRelayer(lggr, chain, r.CapabilitiesRegistry), chain) + starknetRelayers[relayID] = relay.NewServerAdapter(pkgstarknet.NewRelayer(lggr, chain, r.CapabilitiesRegistry)) } } return starknetRelayers, nil @@ -268,12 +270,12 @@ func (c CosmosFactoryConfig) Validate() error { return err } -func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayID]CosmosLoopRelayerChainer, error) { +func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayID]LOOPRelayAdapter, error) { err := config.Validate() if err != nil { return nil, fmt.Errorf("cannot create Cosmos relayer: %w", err) } - relayers := make(map[types.RelayID]CosmosLoopRelayerChainer) + relayers := make(map[types.RelayID]LOOPRelayAdapter) var ( cosmosLggr = r.Logger.Named("Cosmos") @@ -282,7 +284,7 @@ func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayI // create one relayer per chain id for _, chainCfg := range config.TOMLConfigs { - relayID := types.RelayID{Network: corerelay.NetworkCosmos, ChainID: *chainCfg.ChainID} + relayID := types.RelayID{Network: relay.NetworkCosmos, ChainID: *chainCfg.ChainID} lggr := cosmosLggr.Named(relayID.ChainID) @@ -297,7 +299,7 @@ func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayI return nil, fmt.Errorf("failed to load Cosmos chain %q: %w", relayID, err) } - relayers[relayID] = NewCosmosLoopRelayerChain(cosmos.NewRelayer(lggr, chain), chain) + relayers[relayID] = NewCosmosLOOPRelayerChain(cosmos.NewRelayer(lggr, chain)) } return relayers, nil } @@ -310,7 +312,7 @@ type AptosFactoryConfig struct { func (r *RelayerFactory) NewAptos(ks keystore.Aptos, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { plugin := env.NewPlugin("aptos") loopKs := &keystore.AptosLooppSigner{Aptos: ks} - return r.NewLOOPRelayer("Aptos", corerelay.NetworkAptos, plugin, loopKs, chainCfgs) + return r.NewLOOPRelayer("Aptos", relay.NetworkAptos, plugin, loopKs, chainCfgs) } func (r *RelayerFactory) NewLOOPRelayer(name string, network string, plugin env.Plugin, ks coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index f1325d824ea..4cfe5e2086c 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -7,6 +7,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -34,7 +35,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -252,7 +253,36 @@ 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.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 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index d752398f039..44362761bd1 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -7,6 +7,7 @@ FeedsManager = true LogPoller = true UICSAKeys = true CCIP = true +MultiFeedsManagers = true [Database] DefaultIdleInTxSessionTimeout = '1m0s' @@ -34,7 +35,7 @@ LeaseDuration = '1m0s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = true BufferSize = 1234 MaxBatchSize = 4321 @@ -262,11 +263,44 @@ DeltaDial = '1m0s' DeltaReconcile = '2s' ListenAddresses = ['foo', 'bar'] +[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.GatewayConnector] +ChainIDForNodeKey = '11155111' +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' +DonID = 'example_don' +WSHandshakeTimeoutMillis = 100 +AuthMinChallengeLen = 10 +AuthTimestampToleranceSec = 10 + +[[Capabilities.GatewayConnector.Gateways]] +ID = 'example_gateway' +URL = 'wss://localhost:8081/node' + +[Telemetry] +Enabled = true +CACertFile = 'cert-file' +Endpoint = 'example.com/collector' +InsecureConnection = true +TraceSampleRatio = 0.01 + +[Telemetry.ResourceAttributes] +Baz = 'test' +Foo = 'bar' + [[EVM]] ChainID = '1' Enabled = false @@ -275,7 +309,7 @@ BlockBackfillDepth = 100 BlockBackfillSkip = true ChainType = 'Optimism' FinalityDepth = 42 -FinalityTagEnabled = false +FinalityTagEnabled = true FlagsContractAddress = '0xae4E781a6218A8031764928E88d457937A954fC3' LinkContractAddress = '0x538aAaB4ea120b2bC2fe5D296852D948F07D849e' LogBackfillBatchSize = 17 @@ -288,6 +322,7 @@ MinContractPayment = '9.223372036854775807 link' NonceAutoSync = true NoNewHeadsThreshold = '1m0s' OperatorFactoryAddress = '0xa5B85635Be42F21f94F28034B7DA440EeFF0F418' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 17 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 16 @@ -316,6 +351,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 @@ -341,12 +377,16 @@ CheckInclusionPercentile = 19 EIP1559FeeCapBufferBlocks = 13 TransactionPercentile = 15 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '1s' + [EVM.HeadTracker] HistoryDepth = 15 MaxBufferSize = 17 SamplingInterval = '1h0m0s' MaxAllowedFinalityDepth = 1500 FinalityTagBypass = false +PersistenceEnabled = false [[EVM.KeySpecific]] Key = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' @@ -364,6 +404,7 @@ NodeIsSyncingEnabled = true FinalizedBlockPollInterval = '1s' EnforceRepeatableRead = true DeathDeclarationDelay = '1m0s' +NewHeadsPollInterval = '0s' [EVM.NodePool.Errors] NonceTooLow = '(: |^)nonce too low' @@ -380,6 +421,7 @@ L2Full = '(: |^)l2 full' TransactionAlreadyMined = '(: |^)transaction already mined' Fatal = '(: |^)fatal' ServiceUnavailable = '(: |^)service unavailable' +TooManyResults = '(: |^)too many results' [EVM.OCR] ContractConfirmations = 11 @@ -393,6 +435,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 540 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'foo' WSURL = 'wss://web.socket/test/foo' @@ -454,18 +499,40 @@ ComputeUnitPriceMin = 10 ComputeUnitPriceDefault = 100 FeeBumpPeriod = '1m0s' BlockHistoryPollPeriod = '1m0s' +ComputeUnitLimitDefault = 100000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' URL = 'http://solana.web' +SendOnly = false [[Solana.Nodes]] Name = 'foo' URL = 'http://solana.foo' +SendOnly = true [[Solana.Nodes]] Name = 'bar' URL = 'http://solana.bar' +SendOnly = true [[Starknet]] ChainID = 'foobar' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 12427650f42..f9d34ffbde6 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -7,6 +7,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -34,7 +35,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -252,18 +253,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -275,6 +305,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 12 @@ -303,6 +334,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -318,12 +350,16 @@ 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 @@ -335,6 +371,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -348,6 +385,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'primary' WSURL = 'wss://web.socket/mainnet' @@ -375,6 +415,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x8007e24251b1D2Fc518Eb843A701d9cD21fe0aA3' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -403,6 +444,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -418,12 +460,16 @@ 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 @@ -435,6 +481,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -448,6 +495,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 5400000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'foo' WSURL = 'wss://web.socket/test/foo' @@ -458,7 +508,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -469,6 +519,7 @@ MinIncomingConfirmations = 5 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 @@ -497,6 +548,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -512,12 +564,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -529,6 +585,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -542,6 +599,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 5400000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' @@ -600,10 +660,30 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' @@ -623,10 +703,30 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index 5373e0e62d3..e15fd143665 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -38,7 +38,7 @@ CPUProfileRate = 7 [[EVM]] ChainID = '1' FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true FinalizedBlockOffset = 12 [[EVM.Nodes]] @@ -90,17 +90,53 @@ TendermintURL = 'http://bombay.cosmos.com' ChainID = 'mainnet' MaxRetries = 12 +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 + [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' OCR2CachePollPeriod = '1m0s' +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 + [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 0876031fb9a..cb66dcdb349 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -34,7 +34,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" pipeline_mocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func TestDelegate_ServicesForSpec(t *testing.T) { @@ -46,10 +45,9 @@ func TestDelegate_ServicesForSpec(t *testing.T) { }) keyStore := cltest.NewKeyStore(t, db) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) - relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayerExtenders) delegate := directrequest.NewDelegate(lggr, runner, nil, legacyChains, mailMon) t.Run("Spec without DirectRequestSpec", func(t *testing.T) { @@ -86,12 +84,11 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, LogBroadcaster: broadcaster, MailMon: mailMon, KeyStore: keyStore.Eth()}) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, LogBroadcaster: broadcaster, MailMon: mailMon, KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) jobORM := job.NewORM(db, orm, btORM, keyStore, lggr) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) delegate := directrequest.NewDelegate(lggr, runner, orm, legacyChains, mailMon) jb := cltest.MakeDirectRequestJobSpec(t) diff --git a/core/services/feeds/config.go b/core/services/feeds/config.go index e2ec889b23b..626dc862e94 100644 --- a/core/services/feeds/config.go +++ b/core/services/feeds/config.go @@ -12,6 +12,10 @@ type GeneralConfig interface { Insecure() coreconfig.Insecure } +type FeatureConfig interface { + MultiFeedsManagers() bool +} + type JobConfig interface { DefaultHTTPTimeout() commonconfig.Duration } diff --git a/core/services/feeds/connection_manager.go b/core/services/feeds/connection_manager.go index ad7e1318e74..df580c51c59 100644 --- a/core/services/feeds/connection_manager.go +++ b/core/services/feeds/connection_manager.go @@ -5,14 +5,14 @@ import ( "sync" "github.com/pkg/errors" + "google.golang.org/grpc/connectivity" "github.com/smartcontractkit/wsrpc" - "github.com/smartcontractkit/wsrpc/connectivity" "github.com/smartcontractkit/chainlink-common/pkg/services" + pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/recovery" - pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" ) type ConnectionsManager interface { @@ -110,7 +110,12 @@ func (mgr *connectionsManager) Connect(opts ConnectOpts) { return } - defer clientConn.Close() + defer func() { + cerr := clientConn.Close() + if cerr != nil { + mgr.lggr.Warnf("Error closing wsrpc client connection: %v", cerr) + } + }() mgr.lggr.Infow("Connected to Feeds Manager", "feedsManagerID", opts.FeedsManagerID) diff --git a/core/services/feeds/mocks/connections_manager.go b/core/services/feeds/mocks/connections_manager.go index c35c2be6550..2e47bb19d62 100644 --- a/core/services/feeds/mocks/connections_manager.go +++ b/core/services/feeds/mocks/connections_manager.go @@ -3,10 +3,10 @@ package mocks import ( + feedsmanager "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" feeds "github.com/smartcontractkit/chainlink/v2/core/services/feeds" - mock "github.com/stretchr/testify/mock" - proto "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" + mock "github.com/stretchr/testify/mock" ) // ConnectionsManager is an autogenerated mock type for the ConnectionsManager type @@ -134,23 +134,23 @@ func (_c *ConnectionsManager_Disconnect_Call) RunAndReturn(run func(int64) error } // GetClient provides a mock function with given fields: id -func (_m *ConnectionsManager) GetClient(id int64) (proto.FeedsManagerClient, error) { +func (_m *ConnectionsManager) GetClient(id int64) (feedsmanager.FeedsManagerClient, error) { ret := _m.Called(id) if len(ret) == 0 { panic("no return value specified for GetClient") } - var r0 proto.FeedsManagerClient + var r0 feedsmanager.FeedsManagerClient var r1 error - if rf, ok := ret.Get(0).(func(int64) (proto.FeedsManagerClient, error)); ok { + if rf, ok := ret.Get(0).(func(int64) (feedsmanager.FeedsManagerClient, error)); ok { return rf(id) } - if rf, ok := ret.Get(0).(func(int64) proto.FeedsManagerClient); ok { + if rf, ok := ret.Get(0).(func(int64) feedsmanager.FeedsManagerClient); ok { r0 = rf(id) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(proto.FeedsManagerClient) + r0 = ret.Get(0).(feedsmanager.FeedsManagerClient) } } @@ -181,12 +181,12 @@ func (_c *ConnectionsManager_GetClient_Call) Run(run func(id int64)) *Connection return _c } -func (_c *ConnectionsManager_GetClient_Call) Return(_a0 proto.FeedsManagerClient, _a1 error) *ConnectionsManager_GetClient_Call { +func (_c *ConnectionsManager_GetClient_Call) Return(_a0 feedsmanager.FeedsManagerClient, _a1 error) *ConnectionsManager_GetClient_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *ConnectionsManager_GetClient_Call) RunAndReturn(run func(int64) (proto.FeedsManagerClient, error)) *ConnectionsManager_GetClient_Call { +func (_c *ConnectionsManager_GetClient_Call) RunAndReturn(run func(int64) (feedsmanager.FeedsManagerClient, error)) *ConnectionsManager_GetClient_Call { _c.Call.Return(run) return _c } diff --git a/core/services/feeds/mocks/feeds_manager_client.go b/core/services/feeds/mocks/feeds_manager_client.go index e140cf59bee..3a90baafc92 100644 --- a/core/services/feeds/mocks/feeds_manager_client.go +++ b/core/services/feeds/mocks/feeds_manager_client.go @@ -5,7 +5,7 @@ package mocks import ( context "context" - proto "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" + feedsmanager "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" mock "github.com/stretchr/testify/mock" ) @@ -23,27 +23,27 @@ func (_m *FeedsManagerClient) EXPECT() *FeedsManagerClient_Expecter { } // ApprovedJob provides a mock function with given fields: ctx, in -func (_m *FeedsManagerClient) ApprovedJob(ctx context.Context, in *proto.ApprovedJobRequest) (*proto.ApprovedJobResponse, error) { +func (_m *FeedsManagerClient) ApprovedJob(ctx context.Context, in *feedsmanager.ApprovedJobRequest) (*feedsmanager.ApprovedJobResponse, error) { ret := _m.Called(ctx, in) if len(ret) == 0 { panic("no return value specified for ApprovedJob") } - var r0 *proto.ApprovedJobResponse + var r0 *feedsmanager.ApprovedJobResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *proto.ApprovedJobRequest) (*proto.ApprovedJobResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.ApprovedJobRequest) (*feedsmanager.ApprovedJobResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *proto.ApprovedJobRequest) *proto.ApprovedJobResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.ApprovedJobRequest) *feedsmanager.ApprovedJobResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*proto.ApprovedJobResponse) + r0 = ret.Get(0).(*feedsmanager.ApprovedJobResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *proto.ApprovedJobRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *feedsmanager.ApprovedJobRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -59,50 +59,50 @@ type FeedsManagerClient_ApprovedJob_Call struct { // ApprovedJob is a helper method to define mock.On call // - ctx context.Context -// - in *proto.ApprovedJobRequest +// - in *feedsmanager.ApprovedJobRequest func (_e *FeedsManagerClient_Expecter) ApprovedJob(ctx interface{}, in interface{}) *FeedsManagerClient_ApprovedJob_Call { return &FeedsManagerClient_ApprovedJob_Call{Call: _e.mock.On("ApprovedJob", ctx, in)} } -func (_c *FeedsManagerClient_ApprovedJob_Call) Run(run func(ctx context.Context, in *proto.ApprovedJobRequest)) *FeedsManagerClient_ApprovedJob_Call { +func (_c *FeedsManagerClient_ApprovedJob_Call) Run(run func(ctx context.Context, in *feedsmanager.ApprovedJobRequest)) *FeedsManagerClient_ApprovedJob_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*proto.ApprovedJobRequest)) + run(args[0].(context.Context), args[1].(*feedsmanager.ApprovedJobRequest)) }) return _c } -func (_c *FeedsManagerClient_ApprovedJob_Call) Return(_a0 *proto.ApprovedJobResponse, _a1 error) *FeedsManagerClient_ApprovedJob_Call { +func (_c *FeedsManagerClient_ApprovedJob_Call) Return(_a0 *feedsmanager.ApprovedJobResponse, _a1 error) *FeedsManagerClient_ApprovedJob_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeedsManagerClient_ApprovedJob_Call) RunAndReturn(run func(context.Context, *proto.ApprovedJobRequest) (*proto.ApprovedJobResponse, error)) *FeedsManagerClient_ApprovedJob_Call { +func (_c *FeedsManagerClient_ApprovedJob_Call) RunAndReturn(run func(context.Context, *feedsmanager.ApprovedJobRequest) (*feedsmanager.ApprovedJobResponse, error)) *FeedsManagerClient_ApprovedJob_Call { _c.Call.Return(run) return _c } // CancelledJob provides a mock function with given fields: ctx, in -func (_m *FeedsManagerClient) CancelledJob(ctx context.Context, in *proto.CancelledJobRequest) (*proto.CancelledJobResponse, error) { +func (_m *FeedsManagerClient) CancelledJob(ctx context.Context, in *feedsmanager.CancelledJobRequest) (*feedsmanager.CancelledJobResponse, error) { ret := _m.Called(ctx, in) if len(ret) == 0 { panic("no return value specified for CancelledJob") } - var r0 *proto.CancelledJobResponse + var r0 *feedsmanager.CancelledJobResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *proto.CancelledJobRequest) (*proto.CancelledJobResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.CancelledJobRequest) (*feedsmanager.CancelledJobResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *proto.CancelledJobRequest) *proto.CancelledJobResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.CancelledJobRequest) *feedsmanager.CancelledJobResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*proto.CancelledJobResponse) + r0 = ret.Get(0).(*feedsmanager.CancelledJobResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *proto.CancelledJobRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *feedsmanager.CancelledJobRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -118,50 +118,50 @@ type FeedsManagerClient_CancelledJob_Call struct { // CancelledJob is a helper method to define mock.On call // - ctx context.Context -// - in *proto.CancelledJobRequest +// - in *feedsmanager.CancelledJobRequest func (_e *FeedsManagerClient_Expecter) CancelledJob(ctx interface{}, in interface{}) *FeedsManagerClient_CancelledJob_Call { return &FeedsManagerClient_CancelledJob_Call{Call: _e.mock.On("CancelledJob", ctx, in)} } -func (_c *FeedsManagerClient_CancelledJob_Call) Run(run func(ctx context.Context, in *proto.CancelledJobRequest)) *FeedsManagerClient_CancelledJob_Call { +func (_c *FeedsManagerClient_CancelledJob_Call) Run(run func(ctx context.Context, in *feedsmanager.CancelledJobRequest)) *FeedsManagerClient_CancelledJob_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*proto.CancelledJobRequest)) + run(args[0].(context.Context), args[1].(*feedsmanager.CancelledJobRequest)) }) return _c } -func (_c *FeedsManagerClient_CancelledJob_Call) Return(_a0 *proto.CancelledJobResponse, _a1 error) *FeedsManagerClient_CancelledJob_Call { +func (_c *FeedsManagerClient_CancelledJob_Call) Return(_a0 *feedsmanager.CancelledJobResponse, _a1 error) *FeedsManagerClient_CancelledJob_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeedsManagerClient_CancelledJob_Call) RunAndReturn(run func(context.Context, *proto.CancelledJobRequest) (*proto.CancelledJobResponse, error)) *FeedsManagerClient_CancelledJob_Call { +func (_c *FeedsManagerClient_CancelledJob_Call) RunAndReturn(run func(context.Context, *feedsmanager.CancelledJobRequest) (*feedsmanager.CancelledJobResponse, error)) *FeedsManagerClient_CancelledJob_Call { _c.Call.Return(run) return _c } // Healthcheck provides a mock function with given fields: ctx, in -func (_m *FeedsManagerClient) Healthcheck(ctx context.Context, in *proto.HealthcheckRequest) (*proto.HealthcheckResponse, error) { +func (_m *FeedsManagerClient) Healthcheck(ctx context.Context, in *feedsmanager.HealthcheckRequest) (*feedsmanager.HealthcheckResponse, error) { ret := _m.Called(ctx, in) if len(ret) == 0 { panic("no return value specified for Healthcheck") } - var r0 *proto.HealthcheckResponse + var r0 *feedsmanager.HealthcheckResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *proto.HealthcheckRequest) (*proto.HealthcheckResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.HealthcheckRequest) (*feedsmanager.HealthcheckResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *proto.HealthcheckRequest) *proto.HealthcheckResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.HealthcheckRequest) *feedsmanager.HealthcheckResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*proto.HealthcheckResponse) + r0 = ret.Get(0).(*feedsmanager.HealthcheckResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *proto.HealthcheckRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *feedsmanager.HealthcheckRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -177,50 +177,50 @@ type FeedsManagerClient_Healthcheck_Call struct { // Healthcheck is a helper method to define mock.On call // - ctx context.Context -// - in *proto.HealthcheckRequest +// - in *feedsmanager.HealthcheckRequest func (_e *FeedsManagerClient_Expecter) Healthcheck(ctx interface{}, in interface{}) *FeedsManagerClient_Healthcheck_Call { return &FeedsManagerClient_Healthcheck_Call{Call: _e.mock.On("Healthcheck", ctx, in)} } -func (_c *FeedsManagerClient_Healthcheck_Call) Run(run func(ctx context.Context, in *proto.HealthcheckRequest)) *FeedsManagerClient_Healthcheck_Call { +func (_c *FeedsManagerClient_Healthcheck_Call) Run(run func(ctx context.Context, in *feedsmanager.HealthcheckRequest)) *FeedsManagerClient_Healthcheck_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*proto.HealthcheckRequest)) + run(args[0].(context.Context), args[1].(*feedsmanager.HealthcheckRequest)) }) return _c } -func (_c *FeedsManagerClient_Healthcheck_Call) Return(_a0 *proto.HealthcheckResponse, _a1 error) *FeedsManagerClient_Healthcheck_Call { +func (_c *FeedsManagerClient_Healthcheck_Call) Return(_a0 *feedsmanager.HealthcheckResponse, _a1 error) *FeedsManagerClient_Healthcheck_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeedsManagerClient_Healthcheck_Call) RunAndReturn(run func(context.Context, *proto.HealthcheckRequest) (*proto.HealthcheckResponse, error)) *FeedsManagerClient_Healthcheck_Call { +func (_c *FeedsManagerClient_Healthcheck_Call) RunAndReturn(run func(context.Context, *feedsmanager.HealthcheckRequest) (*feedsmanager.HealthcheckResponse, error)) *FeedsManagerClient_Healthcheck_Call { _c.Call.Return(run) return _c } // RejectedJob provides a mock function with given fields: ctx, in -func (_m *FeedsManagerClient) RejectedJob(ctx context.Context, in *proto.RejectedJobRequest) (*proto.RejectedJobResponse, error) { +func (_m *FeedsManagerClient) RejectedJob(ctx context.Context, in *feedsmanager.RejectedJobRequest) (*feedsmanager.RejectedJobResponse, error) { ret := _m.Called(ctx, in) if len(ret) == 0 { panic("no return value specified for RejectedJob") } - var r0 *proto.RejectedJobResponse + var r0 *feedsmanager.RejectedJobResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *proto.RejectedJobRequest) (*proto.RejectedJobResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.RejectedJobRequest) (*feedsmanager.RejectedJobResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *proto.RejectedJobRequest) *proto.RejectedJobResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.RejectedJobRequest) *feedsmanager.RejectedJobResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*proto.RejectedJobResponse) + r0 = ret.Get(0).(*feedsmanager.RejectedJobResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *proto.RejectedJobRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *feedsmanager.RejectedJobRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -236,50 +236,50 @@ type FeedsManagerClient_RejectedJob_Call struct { // RejectedJob is a helper method to define mock.On call // - ctx context.Context -// - in *proto.RejectedJobRequest +// - in *feedsmanager.RejectedJobRequest func (_e *FeedsManagerClient_Expecter) RejectedJob(ctx interface{}, in interface{}) *FeedsManagerClient_RejectedJob_Call { return &FeedsManagerClient_RejectedJob_Call{Call: _e.mock.On("RejectedJob", ctx, in)} } -func (_c *FeedsManagerClient_RejectedJob_Call) Run(run func(ctx context.Context, in *proto.RejectedJobRequest)) *FeedsManagerClient_RejectedJob_Call { +func (_c *FeedsManagerClient_RejectedJob_Call) Run(run func(ctx context.Context, in *feedsmanager.RejectedJobRequest)) *FeedsManagerClient_RejectedJob_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*proto.RejectedJobRequest)) + run(args[0].(context.Context), args[1].(*feedsmanager.RejectedJobRequest)) }) return _c } -func (_c *FeedsManagerClient_RejectedJob_Call) Return(_a0 *proto.RejectedJobResponse, _a1 error) *FeedsManagerClient_RejectedJob_Call { +func (_c *FeedsManagerClient_RejectedJob_Call) Return(_a0 *feedsmanager.RejectedJobResponse, _a1 error) *FeedsManagerClient_RejectedJob_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeedsManagerClient_RejectedJob_Call) RunAndReturn(run func(context.Context, *proto.RejectedJobRequest) (*proto.RejectedJobResponse, error)) *FeedsManagerClient_RejectedJob_Call { +func (_c *FeedsManagerClient_RejectedJob_Call) RunAndReturn(run func(context.Context, *feedsmanager.RejectedJobRequest) (*feedsmanager.RejectedJobResponse, error)) *FeedsManagerClient_RejectedJob_Call { _c.Call.Return(run) return _c } // UpdateNode provides a mock function with given fields: ctx, in -func (_m *FeedsManagerClient) UpdateNode(ctx context.Context, in *proto.UpdateNodeRequest) (*proto.UpdateNodeResponse, error) { +func (_m *FeedsManagerClient) UpdateNode(ctx context.Context, in *feedsmanager.UpdateNodeRequest) (*feedsmanager.UpdateNodeResponse, error) { ret := _m.Called(ctx, in) if len(ret) == 0 { panic("no return value specified for UpdateNode") } - var r0 *proto.UpdateNodeResponse + var r0 *feedsmanager.UpdateNodeResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *proto.UpdateNodeRequest) (*proto.UpdateNodeResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.UpdateNodeRequest) (*feedsmanager.UpdateNodeResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *proto.UpdateNodeRequest) *proto.UpdateNodeResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *feedsmanager.UpdateNodeRequest) *feedsmanager.UpdateNodeResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*proto.UpdateNodeResponse) + r0 = ret.Get(0).(*feedsmanager.UpdateNodeResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *proto.UpdateNodeRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *feedsmanager.UpdateNodeRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -295,24 +295,24 @@ type FeedsManagerClient_UpdateNode_Call struct { // UpdateNode is a helper method to define mock.On call // - ctx context.Context -// - in *proto.UpdateNodeRequest +// - in *feedsmanager.UpdateNodeRequest func (_e *FeedsManagerClient_Expecter) UpdateNode(ctx interface{}, in interface{}) *FeedsManagerClient_UpdateNode_Call { return &FeedsManagerClient_UpdateNode_Call{Call: _e.mock.On("UpdateNode", ctx, in)} } -func (_c *FeedsManagerClient_UpdateNode_Call) Run(run func(ctx context.Context, in *proto.UpdateNodeRequest)) *FeedsManagerClient_UpdateNode_Call { +func (_c *FeedsManagerClient_UpdateNode_Call) Run(run func(ctx context.Context, in *feedsmanager.UpdateNodeRequest)) *FeedsManagerClient_UpdateNode_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*proto.UpdateNodeRequest)) + run(args[0].(context.Context), args[1].(*feedsmanager.UpdateNodeRequest)) }) return _c } -func (_c *FeedsManagerClient_UpdateNode_Call) Return(_a0 *proto.UpdateNodeResponse, _a1 error) *FeedsManagerClient_UpdateNode_Call { +func (_c *FeedsManagerClient_UpdateNode_Call) Return(_a0 *feedsmanager.UpdateNodeResponse, _a1 error) *FeedsManagerClient_UpdateNode_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeedsManagerClient_UpdateNode_Call) RunAndReturn(run func(context.Context, *proto.UpdateNodeRequest) (*proto.UpdateNodeResponse, error)) *FeedsManagerClient_UpdateNode_Call { +func (_c *FeedsManagerClient_UpdateNode_Call) RunAndReturn(run func(context.Context, *feedsmanager.UpdateNodeRequest) (*feedsmanager.UpdateNodeResponse, error)) *FeedsManagerClient_UpdateNode_Call { _c.Call.Return(run) return _c } diff --git a/core/services/feeds/mocks/orm.go b/core/services/feeds/mocks/orm.go index 3fce89eb60a..d6cae81dc6c 100644 --- a/core/services/feeds/mocks/orm.go +++ b/core/services/feeds/mocks/orm.go @@ -6,6 +6,8 @@ import ( context "context" feeds "github.com/smartcontractkit/chainlink/v2/core/services/feeds" + crypto "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" + mock "github.com/stretchr/testify/mock" sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -1269,64 +1271,6 @@ func (_c *ORM_ListChainConfigsByManagerIDs_Call) RunAndReturn(run func(context.C return _c } -// ListJobProposals provides a mock function with given fields: ctx -func (_m *ORM) ListJobProposals(ctx context.Context) ([]feeds.JobProposal, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for ListJobProposals") - } - - var r0 []feeds.JobProposal - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.JobProposal, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) []feeds.JobProposal); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]feeds.JobProposal) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_ListJobProposals_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListJobProposals' -type ORM_ListJobProposals_Call struct { - *mock.Call -} - -// ListJobProposals is a helper method to define mock.On call -// - ctx context.Context -func (_e *ORM_Expecter) ListJobProposals(ctx interface{}) *ORM_ListJobProposals_Call { - return &ORM_ListJobProposals_Call{Call: _e.mock.On("ListJobProposals", ctx)} -} - -func (_c *ORM_ListJobProposals_Call) Run(run func(ctx context.Context)) *ORM_ListJobProposals_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ORM_ListJobProposals_Call) Return(jps []feeds.JobProposal, err error) *ORM_ListJobProposals_Call { - _c.Call.Return(jps, err) - return _c -} - -func (_c *ORM_ListJobProposals_Call) RunAndReturn(run func(context.Context) ([]feeds.JobProposal, error)) *ORM_ListJobProposals_Call { - _c.Call.Return(run) - return _c -} - // ListJobProposalsByManagersIDs provides a mock function with given fields: ctx, ids func (_m *ORM) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]feeds.JobProposal, error) { ret := _m.Called(ctx, ids) @@ -1562,6 +1506,63 @@ func (_c *ORM_ListSpecsByJobProposalIDs_Call) RunAndReturn(run func(context.Cont return _c } +// ManagerExists provides a mock function with given fields: ctx, publicKey +func (_m *ORM) ManagerExists(ctx context.Context, publicKey crypto.PublicKey) (bool, error) { + ret := _m.Called(ctx, publicKey) + + if len(ret) == 0 { + panic("no return value specified for ManagerExists") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, crypto.PublicKey) (bool, error)); ok { + return rf(ctx, publicKey) + } + if rf, ok := ret.Get(0).(func(context.Context, crypto.PublicKey) bool); ok { + r0 = rf(ctx, publicKey) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, crypto.PublicKey) error); ok { + r1 = rf(ctx, publicKey) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ORM_ManagerExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ManagerExists' +type ORM_ManagerExists_Call struct { + *mock.Call +} + +// ManagerExists is a helper method to define mock.On call +// - ctx context.Context +// - publicKey crypto.PublicKey +func (_e *ORM_Expecter) ManagerExists(ctx interface{}, publicKey interface{}) *ORM_ManagerExists_Call { + return &ORM_ManagerExists_Call{Call: _e.mock.On("ManagerExists", ctx, publicKey)} +} + +func (_c *ORM_ManagerExists_Call) Run(run func(ctx context.Context, publicKey crypto.PublicKey)) *ORM_ManagerExists_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(crypto.PublicKey)) + }) + return _c +} + +func (_c *ORM_ManagerExists_Call) Return(_a0 bool, _a1 error) *ORM_ManagerExists_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ORM_ManagerExists_Call) RunAndReturn(run func(context.Context, crypto.PublicKey) (bool, error)) *ORM_ManagerExists_Call { + _c.Call.Return(run) + return _c +} + // RejectSpec provides a mock function with given fields: ctx, id func (_m *ORM) RejectSpec(ctx context.Context, id int64) error { ret := _m.Called(ctx, id) diff --git a/core/services/feeds/mocks/service.go b/core/services/feeds/mocks/service.go index d37c327850d..d84879bb700 100644 --- a/core/services/feeds/mocks/service.go +++ b/core/services/feeds/mocks/service.go @@ -220,62 +220,6 @@ func (_c *Service_CountJobProposalsByStatus_Call) RunAndReturn(run func(context. return _c } -// CountManagers provides a mock function with given fields: ctx -func (_m *Service) CountManagers(ctx context.Context) (int64, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for CountManagers") - } - - var r0 int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (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) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Service_CountManagers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountManagers' -type Service_CountManagers_Call struct { - *mock.Call -} - -// CountManagers is a helper method to define mock.On call -// - ctx context.Context -func (_e *Service_Expecter) CountManagers(ctx interface{}) *Service_CountManagers_Call { - return &Service_CountManagers_Call{Call: _e.mock.On("CountManagers", ctx)} -} - -func (_c *Service_CountManagers_Call) Run(run func(ctx context.Context)) *Service_CountManagers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *Service_CountManagers_Call) Return(_a0 int64, _a1 error) *Service_CountManagers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Service_CountManagers_Call) RunAndReturn(run func(context.Context) (int64, error)) *Service_CountManagers_Call { - _c.Call.Return(run) - return _c -} - // CreateChainConfig provides a mock function with given fields: ctx, cfg func (_m *Service) CreateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { ret := _m.Called(ctx, cfg) @@ -799,64 +743,6 @@ func (_c *Service_ListChainConfigsByManagerIDs_Call) RunAndReturn(run func(conte return _c } -// ListJobProposals provides a mock function with given fields: ctx -func (_m *Service) ListJobProposals(ctx context.Context) ([]feeds.JobProposal, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for ListJobProposals") - } - - var r0 []feeds.JobProposal - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.JobProposal, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) []feeds.JobProposal); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]feeds.JobProposal) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Service_ListJobProposals_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListJobProposals' -type Service_ListJobProposals_Call struct { - *mock.Call -} - -// ListJobProposals is a helper method to define mock.On call -// - ctx context.Context -func (_e *Service_Expecter) ListJobProposals(ctx interface{}) *Service_ListJobProposals_Call { - return &Service_ListJobProposals_Call{Call: _e.mock.On("ListJobProposals", ctx)} -} - -func (_c *Service_ListJobProposals_Call) Run(run func(ctx context.Context)) *Service_ListJobProposals_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *Service_ListJobProposals_Call) Return(_a0 []feeds.JobProposal, _a1 error) *Service_ListJobProposals_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Service_ListJobProposals_Call) RunAndReturn(run func(context.Context) ([]feeds.JobProposal, error)) *Service_ListJobProposals_Call { - _c.Call.Return(run) - return _c -} - // ListJobProposalsByManagersIDs provides a mock function with given fields: ctx, ids func (_m *Service) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]feeds.JobProposal, error) { ret := _m.Called(ctx, ids) diff --git a/core/services/feeds/models.go b/core/services/feeds/models.go index 3fedc98d0f1..a4fbe8745f0 100644 --- a/core/services/feeds/models.go +++ b/core/services/feeds/models.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "gopkg.in/guregu/null.v4" + proto "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -77,7 +78,9 @@ type ChainType string const ( ChainTypeUnknown ChainType = "UNKNOWN" + ChainTypeAptos ChainType = "APTOS" ChainTypeEVM ChainType = "EVM" + ChainTypeSolana ChainType = "SOLANA" ChainTypeStarknet ChainType = "STARKNET" ) @@ -87,11 +90,24 @@ func NewChainType(s string) (ChainType, error) { return ChainTypeEVM, nil case "STARKNET": return ChainTypeStarknet, nil + case "SOLANA": + return ChainTypeSolana, nil + case "APTOS": + return ChainTypeAptos, nil default: return ChainTypeUnknown, errors.New("invalid chain type") } } +// ChainTypeToProtoChainType converts a ChainType to a proto.ChainType. +func ChainTypeToProtoChainType(chainType ChainType) proto.ChainType { + prefixed := "CHAIN_TYPE_" + string(chainType) + if chainType, exists := proto.ChainType_value[prefixed]; exists { + return proto.ChainType(chainType) + } + return proto.ChainType_CHAIN_TYPE_UNSPECIFIED +} + // FeedsManager defines a registered Feeds Manager Service and the connection // information. type FeedsManager struct { diff --git a/core/services/feeds/orm.go b/core/services/feeds/orm.go index d130316fb2d..82d1114a23d 100644 --- a/core/services/feeds/orm.go +++ b/core/services/feeds/orm.go @@ -11,9 +11,12 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + + "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) type ORM interface { + ManagerExists(ctx context.Context, publicKey crypto.PublicKey) (bool, error) CountManagers(ctx context.Context) (int64, error) CreateManager(ctx context.Context, ms *FeedsManager) (int64, error) GetManager(ctx context.Context, id int64) (*FeedsManager, error) @@ -34,7 +37,6 @@ type ORM interface { DeleteProposal(ctx context.Context, id int64) error GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) GetJobProposalByRemoteUUID(ctx context.Context, uuid uuid.UUID) (*JobProposal, error) - ListJobProposals(ctx context.Context) (jps []JobProposal, err error) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) UpdateJobProposalStatus(ctx context.Context, id int64, status JobProposalStatus) error // NEEDED? UpsertJobProposal(ctx context.Context, jp *JobProposal) (int64, error) @@ -74,6 +76,7 @@ func (o *orm) Transact(ctx context.Context, fn func(ORM) error) error { func (o *orm) WithDataSource(ds sqlutil.DataSource) ORM { return &orm{ds} } // Count counts the number of feeds manager records. +// TODO: delete once multiple feeds managers support is released func (o *orm) CountManagers(ctx context.Context) (count int64, err error) { stmt := ` SELECT COUNT(*) @@ -84,6 +87,21 @@ FROM feeds_managers return count, errors.Wrap(err, "CountManagers failed") } +// ManagerExists checks if a feeds manager exists by public key. +func (o *orm) ManagerExists(ctx context.Context, publicKey crypto.PublicKey) (bool, error) { + stmt := ` +SELECT EXISTS ( + SELECT 1 + FROM feeds_managers + WHERE public_key = $1 +); + ` + + var exists bool + err := o.ds.GetContext(ctx, &exists, stmt, publicKey) + return exists, errors.Wrap(err, "ManagerExists failed") +} + // CreateManager creates a feeds manager. func (o *orm) CreateManager(ctx context.Context, ms *FeedsManager) (id int64, err error) { stmt := ` @@ -264,7 +282,8 @@ WHERE id = $1 func (o *orm) ListManagers(ctx context.Context) (mgrs []FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at -FROM feeds_managers; +FROM feeds_managers +ORDER BY created_at; ` err = o.ds.SelectContext(ctx, &mgrs, stmt) @@ -373,17 +392,6 @@ AND status <> $2; return jp, errors.Wrap(err, "GetJobProposalByRemoteUUID failed") } -// ListJobProposals lists all job proposals. -func (o *orm) ListJobProposals(ctx context.Context) (jps []JobProposal, err error) { - stmt := ` -SELECT * -FROM job_proposals; -` - - err = o.ds.SelectContext(ctx, &jps, stmt) - return jps, errors.Wrap(err, "ListJobProposals failed") -} - // ListJobProposalsByManagersIDs gets job proposals by feeds managers IDs. func (o *orm) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { stmt := ` @@ -819,6 +827,7 @@ SELECT exists ( FROM job_proposals INNER JOIN jobs ON job_proposals.external_job_id = jobs.external_job_id WHERE jobs.id = $1 + AND job_proposals.status <> 'deleted' ); ` diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index c4c9ced2ce3..cfe6cef37b9 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -53,7 +52,7 @@ func setupORM(t *testing.T) *TestORM { // Managers -func Test_ORM_CreateManager(t *testing.T) { +func Test_ORM_CreateManager_CountManagers(t *testing.T) { t.Parallel() ctx := testutils.Context(t) @@ -80,6 +79,33 @@ func Test_ORM_CreateManager(t *testing.T) { assert.NotZero(t, id) } +func Test_ORM_CreateManager(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + var ( + orm = setupORM(t) + mgr = &feeds.FeedsManager{ + URI: uri, + Name: name, + PublicKey: publicKey, + } + ) + + exists, err := orm.ManagerExists(ctx, publicKey) + require.NoError(t, err) + require.Equal(t, false, exists) + + id, err := orm.CreateManager(ctx, mgr) + require.NoError(t, err) + + exists, err = orm.ManagerExists(ctx, publicKey) + require.NoError(t, err) + require.Equal(t, true, exists) + + assert.NotZero(t, id) +} + func Test_ORM_GetManager(t *testing.T) { t.Parallel() ctx := testutils.Context(t) @@ -555,39 +581,6 @@ func Test_ORM_GetJobProposal(t *testing.T) { }) } -func Test_ORM_ListJobProposals(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - - orm := setupORM(t) - fmID := createFeedsManager(t, orm) - uuid := uuid.New() - name := null.StringFrom("jp1") - - jp := &feeds.JobProposal{ - Name: name, - RemoteUUID: uuid, - Status: feeds.JobProposalStatusPending, - FeedsManagerID: fmID, - } - - id, err := orm.CreateJobProposal(ctx, jp) - require.NoError(t, err) - - jps, err := orm.ListJobProposals(ctx) - require.NoError(t, err) - require.Len(t, jps, 1) - - actual := jps[0] - assert.Equal(t, id, actual.ID) - assert.Equal(t, name, actual.Name) - assert.Equal(t, uuid, actual.RemoteUUID) - assert.Equal(t, jp.Status, actual.Status) - assert.False(t, actual.ExternalJobID.Valid) - assert.False(t, actual.PendingUpdate) - assert.Equal(t, jp.FeedsManagerID, actual.FeedsManagerID) -} - func Test_ORM_CountJobProposalsByStatus(t *testing.T) { t.Parallel() @@ -1659,6 +1652,14 @@ func Test_ORM_IsJobManaged(t *testing.T) { isManaged, err = orm.IsJobManaged(ctx, int64(j.ID)) require.NoError(t, err) assert.True(t, isManaged) + + // delete the proposal + err = orm.DeleteProposal(ctx, jpID) + require.NoError(t, err) + + isManaged, err = orm.IsJobManaged(ctx, int64(j.ID)) + require.NoError(t, err) + assert.False(t, isManaged) } // Helpers @@ -1698,12 +1699,12 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { ctx := testutils.Context(t) var ( - config = configtest.NewGeneralConfig(t, nil) - keyStore = cltest.NewKeyStore(t, db) - lggr = logger.TestLogger(t) - pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) - bridgeORM = bridges.NewORM(db) - relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) + config = configtest.NewGeneralConfig(t, nil) + keyStore = cltest.NewKeyStore(t, db) + lggr = logger.TestLogger(t) + pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) + bridgeORM = bridges.NewORM(db) + legacyChains = evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) ) orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr) require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) @@ -1715,7 +1716,6 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) jb, err := ocr.ValidatedOracleSpecToml(config, legacyChains, testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ JobID: externalJobID.String(), diff --git a/core/services/feeds/proto/feeds_manager.pb.go b/core/services/feeds/proto/feeds_manager.pb.go deleted file mode 100644 index ee5bcef3938..00000000000 --- a/core/services/feeds/proto/feeds_manager.pb.go +++ /dev/null @@ -1,2400 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.34.1 -// protoc v4.25.3 -// source: pkg/noderpc/proto/feeds_manager.proto - -package proto - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Defines the allowed job types -type JobType int32 - -const ( - JobType_JOB_TYPE_UNSPECIFIED JobType = 0 - JobType_JOB_TYPE_FLUX_MONITOR JobType = 1 - JobType_JOB_TYPE_OCR JobType = 2 - JobType_JOB_TYPE_OCR2 JobType = 3 -) - -// Enum value maps for JobType. -var ( - JobType_name = map[int32]string{ - 0: "JOB_TYPE_UNSPECIFIED", - 1: "JOB_TYPE_FLUX_MONITOR", - 2: "JOB_TYPE_OCR", - 3: "JOB_TYPE_OCR2", - } - JobType_value = map[string]int32{ - "JOB_TYPE_UNSPECIFIED": 0, - "JOB_TYPE_FLUX_MONITOR": 1, - "JOB_TYPE_OCR": 2, - "JOB_TYPE_OCR2": 3, - } -) - -func (x JobType) Enum() *JobType { - p := new(JobType) - *p = x - return p -} - -func (x JobType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (JobType) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_noderpc_proto_feeds_manager_proto_enumTypes[0].Descriptor() -} - -func (JobType) Type() protoreflect.EnumType { - return &file_pkg_noderpc_proto_feeds_manager_proto_enumTypes[0] -} - -func (x JobType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use JobType.Descriptor instead. -func (JobType) EnumDescriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{0} -} - -type ChainType int32 - -const ( - ChainType_CHAIN_TYPE_UNSPECIFIED ChainType = 0 - ChainType_CHAIN_TYPE_EVM ChainType = 1 - ChainType_CHAIN_TYPE_SOLANA ChainType = 2 - ChainType_CHAIN_TYPE_STARKNET ChainType = 3 -) - -// Enum value maps for ChainType. -var ( - ChainType_name = map[int32]string{ - 0: "CHAIN_TYPE_UNSPECIFIED", - 1: "CHAIN_TYPE_EVM", - 2: "CHAIN_TYPE_SOLANA", - 3: "CHAIN_TYPE_STARKNET", - } - ChainType_value = map[string]int32{ - "CHAIN_TYPE_UNSPECIFIED": 0, - "CHAIN_TYPE_EVM": 1, - "CHAIN_TYPE_SOLANA": 2, - "CHAIN_TYPE_STARKNET": 3, - } -) - -func (x ChainType) Enum() *ChainType { - p := new(ChainType) - *p = x - return p -} - -func (x ChainType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ChainType) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_noderpc_proto_feeds_manager_proto_enumTypes[1].Descriptor() -} - -func (ChainType) Type() protoreflect.EnumType { - return &file_pkg_noderpc_proto_feeds_manager_proto_enumTypes[1] -} - -func (x ChainType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ChainType.Descriptor instead. -func (ChainType) EnumDescriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{1} -} - -type Chain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Type ChainType `protobuf:"varint,2,opt,name=type,proto3,enum=cfm.ChainType" json:"type,omitempty"` -} - -func (x *Chain) Reset() { - *x = Chain{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Chain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Chain) ProtoMessage() {} - -func (x *Chain) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Chain.ProtoReflect.Descriptor instead. -func (*Chain) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{0} -} - -func (x *Chain) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Chain) GetType() ChainType { - if x != nil { - return x.Type - } - return ChainType_CHAIN_TYPE_UNSPECIFIED -} - -// An account on a specific blockchain -type Account struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ChainType ChainType `protobuf:"varint,1,opt,name=chain_type,json=chainType,proto3,enum=cfm.ChainType" json:"chain_type,omitempty"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` -} - -func (x *Account) Reset() { - *x = Account{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Account) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Account) ProtoMessage() {} - -func (x *Account) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Account.ProtoReflect.Descriptor instead. -func (*Account) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{1} -} - -func (x *Account) GetChainType() ChainType { - if x != nil { - return x.ChainType - } - return ChainType_CHAIN_TYPE_UNSPECIFIED -} - -func (x *Account) GetChainId() string { - if x != nil { - return x.ChainId - } - return "" -} - -func (x *Account) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -// The config for Flux Monitor on a specific chain -type FluxMonitorConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` -} - -func (x *FluxMonitorConfig) Reset() { - *x = FluxMonitorConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FluxMonitorConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FluxMonitorConfig) ProtoMessage() {} - -func (x *FluxMonitorConfig) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FluxMonitorConfig.ProtoReflect.Descriptor instead. -func (*FluxMonitorConfig) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{2} -} - -func (x *FluxMonitorConfig) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -// The config for OCR1 on a specific chain -type OCR1Config struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - IsBootstrap bool `protobuf:"varint,2,opt,name=is_bootstrap,json=isBootstrap,proto3" json:"is_bootstrap,omitempty"` - P2PKeyBundle *OCR1Config_P2PKeyBundle `protobuf:"bytes,3,opt,name=p2p_key_bundle,json=p2pKeyBundle,proto3" json:"p2p_key_bundle,omitempty"` - OcrKeyBundle *OCR1Config_OCRKeyBundle `protobuf:"bytes,4,opt,name=ocr_key_bundle,json=ocrKeyBundle,proto3" json:"ocr_key_bundle,omitempty"` - Multiaddr string `protobuf:"bytes,5,opt,name=multiaddr,proto3" json:"multiaddr,omitempty"` -} - -func (x *OCR1Config) Reset() { - *x = OCR1Config{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR1Config) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR1Config) ProtoMessage() {} - -func (x *OCR1Config) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR1Config.ProtoReflect.Descriptor instead. -func (*OCR1Config) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{3} -} - -func (x *OCR1Config) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *OCR1Config) GetIsBootstrap() bool { - if x != nil { - return x.IsBootstrap - } - return false -} - -func (x *OCR1Config) GetP2PKeyBundle() *OCR1Config_P2PKeyBundle { - if x != nil { - return x.P2PKeyBundle - } - return nil -} - -func (x *OCR1Config) GetOcrKeyBundle() *OCR1Config_OCRKeyBundle { - if x != nil { - return x.OcrKeyBundle - } - return nil -} - -func (x *OCR1Config) GetMultiaddr() string { - if x != nil { - return x.Multiaddr - } - return "" -} - -// The config for OCR2 on a specific chain -type OCR2Config struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - IsBootstrap bool `protobuf:"varint,2,opt,name=is_bootstrap,json=isBootstrap,proto3" json:"is_bootstrap,omitempty"` - P2PKeyBundle *OCR2Config_P2PKeyBundle `protobuf:"bytes,3,opt,name=p2p_key_bundle,json=p2pKeyBundle,proto3" json:"p2p_key_bundle,omitempty"` - OcrKeyBundle *OCR2Config_OCRKeyBundle `protobuf:"bytes,4,opt,name=ocr_key_bundle,json=ocrKeyBundle,proto3" json:"ocr_key_bundle,omitempty"` - Multiaddr string `protobuf:"bytes,5,opt,name=multiaddr,proto3" json:"multiaddr,omitempty"` - Plugins *OCR2Config_Plugins `protobuf:"bytes,6,opt,name=plugins,proto3" json:"plugins,omitempty"` - ForwarderAddress *string `protobuf:"bytes,7,opt,name=forwarder_address,json=forwarderAddress,proto3,oneof" json:"forwarder_address,omitempty"` -} - -func (x *OCR2Config) Reset() { - *x = OCR2Config{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config) ProtoMessage() {} - -func (x *OCR2Config) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config.ProtoReflect.Descriptor instead. -func (*OCR2Config) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{4} -} - -func (x *OCR2Config) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *OCR2Config) GetIsBootstrap() bool { - if x != nil { - return x.IsBootstrap - } - return false -} - -func (x *OCR2Config) GetP2PKeyBundle() *OCR2Config_P2PKeyBundle { - if x != nil { - return x.P2PKeyBundle - } - return nil -} - -func (x *OCR2Config) GetOcrKeyBundle() *OCR2Config_OCRKeyBundle { - if x != nil { - return x.OcrKeyBundle - } - return nil -} - -func (x *OCR2Config) GetMultiaddr() string { - if x != nil { - return x.Multiaddr - } - return "" -} - -func (x *OCR2Config) GetPlugins() *OCR2Config_Plugins { - if x != nil { - return x.Plugins - } - return nil -} - -func (x *OCR2Config) GetForwarderAddress() string { - if x != nil && x.ForwarderAddress != nil { - return *x.ForwarderAddress - } - return "" -} - -type ChainConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Chain *Chain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` - AccountAddress string `protobuf:"bytes,2,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` - AdminAddress string `protobuf:"bytes,3,opt,name=admin_address,json=adminAddress,proto3" json:"admin_address,omitempty"` - FluxMonitorConfig *FluxMonitorConfig `protobuf:"bytes,4,opt,name=flux_monitor_config,json=fluxMonitorConfig,proto3" json:"flux_monitor_config,omitempty"` - Ocr1Config *OCR1Config `protobuf:"bytes,5,opt,name=ocr1_config,json=ocr1Config,proto3" json:"ocr1_config,omitempty"` - Ocr2Config *OCR2Config `protobuf:"bytes,6,opt,name=ocr2_config,json=ocr2Config,proto3" json:"ocr2_config,omitempty"` - // For EVM chains, we do not need this value and it is kept in the node's - // keystore. For starknet, because the wallet address needs to be deployed - // using this value and this pub key needs to be passed into the starknet - // relayer, we request the node to send this directly to CLO. - AccountAddressPublicKey *string `protobuf:"bytes,7,opt,name=account_address_public_key,json=accountAddressPublicKey,proto3,oneof" json:"account_address_public_key,omitempty"` -} - -func (x *ChainConfig) Reset() { - *x = ChainConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ChainConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ChainConfig) ProtoMessage() {} - -func (x *ChainConfig) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ChainConfig.ProtoReflect.Descriptor instead. -func (*ChainConfig) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{5} -} - -func (x *ChainConfig) GetChain() *Chain { - if x != nil { - return x.Chain - } - return nil -} - -func (x *ChainConfig) GetAccountAddress() string { - if x != nil { - return x.AccountAddress - } - return "" -} - -func (x *ChainConfig) GetAdminAddress() string { - if x != nil { - return x.AdminAddress - } - return "" -} - -func (x *ChainConfig) GetFluxMonitorConfig() *FluxMonitorConfig { - if x != nil { - return x.FluxMonitorConfig - } - return nil -} - -func (x *ChainConfig) GetOcr1Config() *OCR1Config { - if x != nil { - return x.Ocr1Config - } - return nil -} - -func (x *ChainConfig) GetOcr2Config() *OCR2Config { - if x != nil { - return x.Ocr2Config - } - return nil -} - -func (x *ChainConfig) GetAccountAddressPublicKey() string { - if x != nil && x.AccountAddressPublicKey != nil { - return *x.AccountAddressPublicKey - } - return "" -} - -type UpdateNodeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - JobTypes []JobType `protobuf:"varint,1,rep,packed,name=job_types,json=jobTypes,proto3,enum=cfm.JobType" json:"job_types,omitempty"` - ChainId int64 `protobuf:"varint,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // To be removed when all nodes are upgraded to 1.2 - AccountAddresses []string `protobuf:"bytes,3,rep,name=account_addresses,json=accountAddresses,proto3" json:"account_addresses,omitempty"` - IsBootstrapPeer bool `protobuf:"varint,4,opt,name=is_bootstrap_peer,json=isBootstrapPeer,proto3" json:"is_bootstrap_peer,omitempty"` - BootstrapMultiaddr string `protobuf:"bytes,5,opt,name=bootstrap_multiaddr,json=bootstrapMultiaddr,proto3" json:"bootstrap_multiaddr,omitempty"` - Version string `protobuf:"bytes,6,opt,name=version,proto3" json:"version,omitempty"` - ChainIds []int64 `protobuf:"varint,7,rep,packed,name=chain_ids,json=chainIds,proto3" json:"chain_ids,omitempty"` - Accounts []*Account `protobuf:"bytes,8,rep,name=accounts,proto3" json:"accounts,omitempty"` - Chains []*Chain `protobuf:"bytes,9,rep,name=chains,proto3" json:"chains,omitempty"` - ChainConfigs []*ChainConfig `protobuf:"bytes,10,rep,name=chain_configs,json=chainConfigs,proto3" json:"chain_configs,omitempty"` -} - -func (x *UpdateNodeRequest) Reset() { - *x = UpdateNodeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateNodeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateNodeRequest) ProtoMessage() {} - -func (x *UpdateNodeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateNodeRequest.ProtoReflect.Descriptor instead. -func (*UpdateNodeRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{6} -} - -func (x *UpdateNodeRequest) GetJobTypes() []JobType { - if x != nil { - return x.JobTypes - } - return nil -} - -func (x *UpdateNodeRequest) GetChainId() int64 { - if x != nil { - return x.ChainId - } - return 0 -} - -func (x *UpdateNodeRequest) GetAccountAddresses() []string { - if x != nil { - return x.AccountAddresses - } - return nil -} - -func (x *UpdateNodeRequest) GetIsBootstrapPeer() bool { - if x != nil { - return x.IsBootstrapPeer - } - return false -} - -func (x *UpdateNodeRequest) GetBootstrapMultiaddr() string { - if x != nil { - return x.BootstrapMultiaddr - } - return "" -} - -func (x *UpdateNodeRequest) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *UpdateNodeRequest) GetChainIds() []int64 { - if x != nil { - return x.ChainIds - } - return nil -} - -func (x *UpdateNodeRequest) GetAccounts() []*Account { - if x != nil { - return x.Accounts - } - return nil -} - -func (x *UpdateNodeRequest) GetChains() []*Chain { - if x != nil { - return x.Chains - } - return nil -} - -func (x *UpdateNodeRequest) GetChainConfigs() []*ChainConfig { - if x != nil { - return x.ChainConfigs - } - return nil -} - -type UpdateNodeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *UpdateNodeResponse) Reset() { - *x = UpdateNodeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateNodeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateNodeResponse) ProtoMessage() {} - -func (x *UpdateNodeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateNodeResponse.ProtoReflect.Descriptor instead. -func (*UpdateNodeResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{7} -} - -type ApprovedJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *ApprovedJobRequest) Reset() { - *x = ApprovedJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApprovedJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApprovedJobRequest) ProtoMessage() {} - -func (x *ApprovedJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApprovedJobRequest.ProtoReflect.Descriptor instead. -func (*ApprovedJobRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{8} -} - -func (x *ApprovedJobRequest) GetUuid() string { - if x != nil { - return x.Uuid - } - return "" -} - -func (x *ApprovedJobRequest) GetVersion() int64 { - if x != nil { - return x.Version - } - return 0 -} - -type ApprovedJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ApprovedJobResponse) Reset() { - *x = ApprovedJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApprovedJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApprovedJobResponse) ProtoMessage() {} - -func (x *ApprovedJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApprovedJobResponse.ProtoReflect.Descriptor instead. -func (*ApprovedJobResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{9} -} - -type HealthcheckRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *HealthcheckRequest) Reset() { - *x = HealthcheckRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthcheckRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthcheckRequest) ProtoMessage() {} - -func (x *HealthcheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthcheckRequest.ProtoReflect.Descriptor instead. -func (*HealthcheckRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{10} -} - -type HealthcheckResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *HealthcheckResponse) Reset() { - *x = HealthcheckResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthcheckResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthcheckResponse) ProtoMessage() {} - -func (x *HealthcheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthcheckResponse.ProtoReflect.Descriptor instead. -func (*HealthcheckResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{11} -} - -type RejectedJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *RejectedJobRequest) Reset() { - *x = RejectedJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RejectedJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RejectedJobRequest) ProtoMessage() {} - -func (x *RejectedJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RejectedJobRequest.ProtoReflect.Descriptor instead. -func (*RejectedJobRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{12} -} - -func (x *RejectedJobRequest) GetUuid() string { - if x != nil { - return x.Uuid - } - return "" -} - -func (x *RejectedJobRequest) GetVersion() int64 { - if x != nil { - return x.Version - } - return 0 -} - -type RejectedJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RejectedJobResponse) Reset() { - *x = RejectedJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RejectedJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RejectedJobResponse) ProtoMessage() {} - -func (x *RejectedJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RejectedJobResponse.ProtoReflect.Descriptor instead. -func (*RejectedJobResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{13} -} - -type CancelledJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *CancelledJobRequest) Reset() { - *x = CancelledJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CancelledJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelledJobRequest) ProtoMessage() {} - -func (x *CancelledJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelledJobRequest.ProtoReflect.Descriptor instead. -func (*CancelledJobRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{14} -} - -func (x *CancelledJobRequest) GetUuid() string { - if x != nil { - return x.Uuid - } - return "" -} - -func (x *CancelledJobRequest) GetVersion() int64 { - if x != nil { - return x.Version - } - return 0 -} - -type CancelledJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *CancelledJobResponse) Reset() { - *x = CancelledJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CancelledJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelledJobResponse) ProtoMessage() {} - -func (x *CancelledJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelledJobResponse.ProtoReflect.Descriptor instead. -func (*CancelledJobResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{15} -} - -type ProposeJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Spec string `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` - Multiaddrs []string `protobuf:"bytes,3,rep,name=multiaddrs,proto3" json:"multiaddrs,omitempty"` - Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *ProposeJobRequest) Reset() { - *x = ProposeJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProposeJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProposeJobRequest) ProtoMessage() {} - -func (x *ProposeJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProposeJobRequest.ProtoReflect.Descriptor instead. -func (*ProposeJobRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{16} -} - -func (x *ProposeJobRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *ProposeJobRequest) GetSpec() string { - if x != nil { - return x.Spec - } - return "" -} - -func (x *ProposeJobRequest) GetMultiaddrs() []string { - if x != nil { - return x.Multiaddrs - } - return nil -} - -func (x *ProposeJobRequest) GetVersion() int64 { - if x != nil { - return x.Version - } - return 0 -} - -type ProposeJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *ProposeJobResponse) Reset() { - *x = ProposeJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProposeJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProposeJobResponse) ProtoMessage() {} - -func (x *ProposeJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProposeJobResponse.ProtoReflect.Descriptor instead. -func (*ProposeJobResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{17} -} - -func (x *ProposeJobResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type DeleteJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *DeleteJobRequest) Reset() { - *x = DeleteJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteJobRequest) ProtoMessage() {} - -func (x *DeleteJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteJobRequest.ProtoReflect.Descriptor instead. -func (*DeleteJobRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{18} -} - -func (x *DeleteJobRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type DeleteJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *DeleteJobResponse) Reset() { - *x = DeleteJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteJobResponse) ProtoMessage() {} - -func (x *DeleteJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteJobResponse.ProtoReflect.Descriptor instead. -func (*DeleteJobResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{19} -} - -func (x *DeleteJobResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type RevokeJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *RevokeJobRequest) Reset() { - *x = RevokeJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RevokeJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RevokeJobRequest) ProtoMessage() {} - -func (x *RevokeJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RevokeJobRequest.ProtoReflect.Descriptor instead. -func (*RevokeJobRequest) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{20} -} - -func (x *RevokeJobRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type RevokeJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *RevokeJobResponse) Reset() { - *x = RevokeJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RevokeJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RevokeJobResponse) ProtoMessage() {} - -func (x *RevokeJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RevokeJobResponse.ProtoReflect.Descriptor instead. -func (*RevokeJobResponse) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{21} -} - -func (x *RevokeJobResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type OCR1Config_P2PKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PeerId string `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` - PublicKey string `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` -} - -func (x *OCR1Config_P2PKeyBundle) Reset() { - *x = OCR1Config_P2PKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR1Config_P2PKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR1Config_P2PKeyBundle) ProtoMessage() {} - -func (x *OCR1Config_P2PKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR1Config_P2PKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR1Config_P2PKeyBundle) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{3, 0} -} - -func (x *OCR1Config_P2PKeyBundle) GetPeerId() string { - if x != nil { - return x.PeerId - } - return "" -} - -func (x *OCR1Config_P2PKeyBundle) GetPublicKey() string { - if x != nil { - return x.PublicKey - } - return "" -} - -type OCR1Config_OCRKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BundleId string `protobuf:"bytes,1,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` - ConfigPublicKey string `protobuf:"bytes,2,opt,name=config_public_key,json=configPublicKey,proto3" json:"config_public_key,omitempty"` - OffchainPublicKey string `protobuf:"bytes,3,opt,name=offchain_public_key,json=offchainPublicKey,proto3" json:"offchain_public_key,omitempty"` - OnchainSigningAddress string `protobuf:"bytes,4,opt,name=onchain_signing_address,json=onchainSigningAddress,proto3" json:"onchain_signing_address,omitempty"` -} - -func (x *OCR1Config_OCRKeyBundle) Reset() { - *x = OCR1Config_OCRKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR1Config_OCRKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR1Config_OCRKeyBundle) ProtoMessage() {} - -func (x *OCR1Config_OCRKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR1Config_OCRKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR1Config_OCRKeyBundle) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{3, 1} -} - -func (x *OCR1Config_OCRKeyBundle) GetBundleId() string { - if x != nil { - return x.BundleId - } - return "" -} - -func (x *OCR1Config_OCRKeyBundle) GetConfigPublicKey() string { - if x != nil { - return x.ConfigPublicKey - } - return "" -} - -func (x *OCR1Config_OCRKeyBundle) GetOffchainPublicKey() string { - if x != nil { - return x.OffchainPublicKey - } - return "" -} - -func (x *OCR1Config_OCRKeyBundle) GetOnchainSigningAddress() string { - if x != nil { - return x.OnchainSigningAddress - } - return "" -} - -type OCR2Config_P2PKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PeerId string `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` - PublicKey string `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` -} - -func (x *OCR2Config_P2PKeyBundle) Reset() { - *x = OCR2Config_P2PKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config_P2PKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config_P2PKeyBundle) ProtoMessage() {} - -func (x *OCR2Config_P2PKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config_P2PKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR2Config_P2PKeyBundle) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{4, 0} -} - -func (x *OCR2Config_P2PKeyBundle) GetPeerId() string { - if x != nil { - return x.PeerId - } - return "" -} - -func (x *OCR2Config_P2PKeyBundle) GetPublicKey() string { - if x != nil { - return x.PublicKey - } - return "" -} - -type OCR2Config_OCRKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BundleId string `protobuf:"bytes,1,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` - ConfigPublicKey string `protobuf:"bytes,2,opt,name=config_public_key,json=configPublicKey,proto3" json:"config_public_key,omitempty"` - OffchainPublicKey string `protobuf:"bytes,3,opt,name=offchain_public_key,json=offchainPublicKey,proto3" json:"offchain_public_key,omitempty"` - OnchainSigningAddress string `protobuf:"bytes,4,opt,name=onchain_signing_address,json=onchainSigningAddress,proto3" json:"onchain_signing_address,omitempty"` -} - -func (x *OCR2Config_OCRKeyBundle) Reset() { - *x = OCR2Config_OCRKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config_OCRKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config_OCRKeyBundle) ProtoMessage() {} - -func (x *OCR2Config_OCRKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config_OCRKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR2Config_OCRKeyBundle) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{4, 1} -} - -func (x *OCR2Config_OCRKeyBundle) GetBundleId() string { - if x != nil { - return x.BundleId - } - return "" -} - -func (x *OCR2Config_OCRKeyBundle) GetConfigPublicKey() string { - if x != nil { - return x.ConfigPublicKey - } - return "" -} - -func (x *OCR2Config_OCRKeyBundle) GetOffchainPublicKey() string { - if x != nil { - return x.OffchainPublicKey - } - return "" -} - -func (x *OCR2Config_OCRKeyBundle) GetOnchainSigningAddress() string { - if x != nil { - return x.OnchainSigningAddress - } - return "" -} - -type OCR2Config_Plugins struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commit bool `protobuf:"varint,1,opt,name=commit,proto3" json:"commit,omitempty"` - Execute bool `protobuf:"varint,2,opt,name=execute,proto3" json:"execute,omitempty"` - Median bool `protobuf:"varint,3,opt,name=median,proto3" json:"median,omitempty"` - Mercury bool `protobuf:"varint,4,opt,name=mercury,proto3" json:"mercury,omitempty"` - Rebalancer bool `protobuf:"varint,5,opt,name=rebalancer,proto3" json:"rebalancer,omitempty"` -} - -func (x *OCR2Config_Plugins) Reset() { - *x = OCR2Config_Plugins{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config_Plugins) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config_Plugins) ProtoMessage() {} - -func (x *OCR2Config_Plugins) ProtoReflect() protoreflect.Message { - mi := &file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config_Plugins.ProtoReflect.Descriptor instead. -func (*OCR2Config_Plugins) Descriptor() ([]byte, []int) { - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP(), []int{4, 2} -} - -func (x *OCR2Config_Plugins) GetCommit() bool { - if x != nil { - return x.Commit - } - return false -} - -func (x *OCR2Config_Plugins) GetExecute() bool { - if x != nil { - return x.Execute - } - return false -} - -func (x *OCR2Config_Plugins) GetMedian() bool { - if x != nil { - return x.Median - } - return false -} - -func (x *OCR2Config_Plugins) GetMercury() bool { - if x != nil { - return x.Mercury - } - return false -} - -func (x *OCR2Config_Plugins) GetRebalancer() bool { - if x != nil { - return x.Rebalancer - } - return false -} - -var File_pkg_noderpc_proto_feeds_manager_proto protoreflect.FileDescriptor - -var file_pkg_noderpc_proto_feeds_manager_proto_rawDesc = []byte{ - 0x0a, 0x25, 0x70, 0x6b, 0x67, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x63, 0x66, 0x6d, 0x22, 0x3b, 0x0a, 0x05, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x6d, 0x0a, 0x07, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x2d, 0x0a, 0x11, 0x46, 0x6c, 0x75, 0x78, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, - 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xf9, 0x03, 0x0a, 0x0a, 0x4f, 0x43, 0x52, 0x31, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, - 0x72, 0x61, 0x70, 0x12, 0x42, 0x0a, 0x0e, 0x70, 0x32, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x66, - 0x6d, 0x2e, 0x4f, 0x43, 0x52, 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x32, 0x50, - 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, 0x70, 0x32, 0x70, 0x4b, 0x65, - 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x6f, 0x63, 0x72, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4f, 0x43, 0x52, 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x4f, 0x43, 0x52, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, 0x6f, - 0x63, 0x72, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x1a, 0x46, 0x0a, 0x0c, 0x50, 0x32, 0x50, - 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x65, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x1a, 0xbf, 0x01, 0x0a, 0x0c, 0x4f, 0x43, 0x52, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, 0x12, - 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x6f, - 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, - 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x17, 0x6f, - 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6f, 0x6e, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x22, 0x84, 0x06, 0x0a, 0x0a, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, - 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, - 0x42, 0x0a, 0x0e, 0x70, 0x32, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4f, 0x43, - 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x32, 0x50, 0x4b, 0x65, 0x79, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, 0x70, 0x32, 0x70, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x6f, 0x63, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x66, - 0x6d, 0x2e, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4f, 0x43, 0x52, - 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, 0x6f, 0x63, 0x72, 0x4b, 0x65, - 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x61, 0x64, 0x64, 0x72, 0x12, 0x31, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4f, 0x43, 0x52, - 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, - 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x1a, 0x46, 0x0a, 0x0c, 0x50, 0x32, - 0x50, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x65, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x1a, 0xbf, 0x01, 0x0a, 0x0c, 0x4f, 0x43, 0x52, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, - 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, - 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x17, - 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6f, - 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x1a, 0x8d, 0x01, 0x0a, 0x07, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, - 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x72, 0x63, 0x75, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6d, 0x65, 0x72, - 0x63, 0x75, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x72, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x8a, 0x03, 0x0a, 0x0b, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x05, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x66, 0x6d, 0x2e, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x27, 0x0a, 0x0f, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x46, 0x0a, 0x13, 0x66, 0x6c, - 0x75, 0x78, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x46, 0x6c, - 0x75, 0x78, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x11, 0x66, 0x6c, 0x75, 0x78, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x30, 0x0a, 0x0b, 0x6f, 0x63, 0x72, 0x31, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4f, 0x43, - 0x52, 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x6f, 0x63, 0x72, 0x31, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x0b, 0x6f, 0x63, 0x72, 0x32, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x66, 0x6d, 0x2e, - 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x6f, 0x63, 0x72, 0x32, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x1a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x17, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, - 0x09, 0x6a, 0x6f, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, - 0x32, 0x0c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, - 0x6a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, - 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, - 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, 0x42, - 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x13, - 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x73, - 0x74, 0x72, 0x61, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x5f, 0x69, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x03, 0x52, 0x08, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, - 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x22, - 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, - 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x66, 0x6d, 0x2e, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x42, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x15, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x0a, 0x12, 0x52, 0x65, 0x6a, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x52, - 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x43, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x71, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x22, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x11, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x22, 0x22, 0x0a, 0x10, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x2a, 0x63, 0x0a, 0x07, 0x4a, 0x6f, - 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x19, 0x0a, 0x15, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x55, 0x58, - 0x5f, 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x4f, - 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x43, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, - 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x43, 0x52, 0x32, 0x10, 0x03, 0x2a, - 0x6b, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, - 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x48, 0x41, 0x49, - 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x56, 0x4d, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, - 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4f, 0x4c, 0x41, 0x4e, - 0x41, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x4b, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x32, 0xd8, 0x02, 0x0a, - 0x0c, 0x46, 0x65, 0x65, 0x64, 0x73, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x40, 0x0a, - 0x0b, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x63, - 0x66, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x40, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x17, - 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, - 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x40, 0x0a, 0x0b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, - 0x17, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, - 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, - 0x6f, 0x62, 0x12, 0x18, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, - 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, - 0x66, 0x6d, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc4, 0x01, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x63, 0x66, 0x6d, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x66, 0x6d, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x12, - 0x15, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x66, 0x6d, 0x2e, 0x52, 0x65, 0x76, - 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3d, - 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, - 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x66, 0x65, - 0x65, 0x64, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pkg_noderpc_proto_feeds_manager_proto_rawDescOnce sync.Once - file_pkg_noderpc_proto_feeds_manager_proto_rawDescData = file_pkg_noderpc_proto_feeds_manager_proto_rawDesc -) - -func file_pkg_noderpc_proto_feeds_manager_proto_rawDescGZIP() []byte { - file_pkg_noderpc_proto_feeds_manager_proto_rawDescOnce.Do(func() { - file_pkg_noderpc_proto_feeds_manager_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_noderpc_proto_feeds_manager_proto_rawDescData) - }) - return file_pkg_noderpc_proto_feeds_manager_proto_rawDescData -} - -var file_pkg_noderpc_proto_feeds_manager_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_noderpc_proto_feeds_manager_proto_msgTypes = make([]protoimpl.MessageInfo, 27) -var file_pkg_noderpc_proto_feeds_manager_proto_goTypes = []interface{}{ - (JobType)(0), // 0: cfm.JobType - (ChainType)(0), // 1: cfm.ChainType - (*Chain)(nil), // 2: cfm.Chain - (*Account)(nil), // 3: cfm.Account - (*FluxMonitorConfig)(nil), // 4: cfm.FluxMonitorConfig - (*OCR1Config)(nil), // 5: cfm.OCR1Config - (*OCR2Config)(nil), // 6: cfm.OCR2Config - (*ChainConfig)(nil), // 7: cfm.ChainConfig - (*UpdateNodeRequest)(nil), // 8: cfm.UpdateNodeRequest - (*UpdateNodeResponse)(nil), // 9: cfm.UpdateNodeResponse - (*ApprovedJobRequest)(nil), // 10: cfm.ApprovedJobRequest - (*ApprovedJobResponse)(nil), // 11: cfm.ApprovedJobResponse - (*HealthcheckRequest)(nil), // 12: cfm.HealthcheckRequest - (*HealthcheckResponse)(nil), // 13: cfm.HealthcheckResponse - (*RejectedJobRequest)(nil), // 14: cfm.RejectedJobRequest - (*RejectedJobResponse)(nil), // 15: cfm.RejectedJobResponse - (*CancelledJobRequest)(nil), // 16: cfm.CancelledJobRequest - (*CancelledJobResponse)(nil), // 17: cfm.CancelledJobResponse - (*ProposeJobRequest)(nil), // 18: cfm.ProposeJobRequest - (*ProposeJobResponse)(nil), // 19: cfm.ProposeJobResponse - (*DeleteJobRequest)(nil), // 20: cfm.DeleteJobRequest - (*DeleteJobResponse)(nil), // 21: cfm.DeleteJobResponse - (*RevokeJobRequest)(nil), // 22: cfm.RevokeJobRequest - (*RevokeJobResponse)(nil), // 23: cfm.RevokeJobResponse - (*OCR1Config_P2PKeyBundle)(nil), // 24: cfm.OCR1Config.P2PKeyBundle - (*OCR1Config_OCRKeyBundle)(nil), // 25: cfm.OCR1Config.OCRKeyBundle - (*OCR2Config_P2PKeyBundle)(nil), // 26: cfm.OCR2Config.P2PKeyBundle - (*OCR2Config_OCRKeyBundle)(nil), // 27: cfm.OCR2Config.OCRKeyBundle - (*OCR2Config_Plugins)(nil), // 28: cfm.OCR2Config.Plugins -} -var file_pkg_noderpc_proto_feeds_manager_proto_depIdxs = []int32{ - 1, // 0: cfm.Chain.type:type_name -> cfm.ChainType - 1, // 1: cfm.Account.chain_type:type_name -> cfm.ChainType - 24, // 2: cfm.OCR1Config.p2p_key_bundle:type_name -> cfm.OCR1Config.P2PKeyBundle - 25, // 3: cfm.OCR1Config.ocr_key_bundle:type_name -> cfm.OCR1Config.OCRKeyBundle - 26, // 4: cfm.OCR2Config.p2p_key_bundle:type_name -> cfm.OCR2Config.P2PKeyBundle - 27, // 5: cfm.OCR2Config.ocr_key_bundle:type_name -> cfm.OCR2Config.OCRKeyBundle - 28, // 6: cfm.OCR2Config.plugins:type_name -> cfm.OCR2Config.Plugins - 2, // 7: cfm.ChainConfig.chain:type_name -> cfm.Chain - 4, // 8: cfm.ChainConfig.flux_monitor_config:type_name -> cfm.FluxMonitorConfig - 5, // 9: cfm.ChainConfig.ocr1_config:type_name -> cfm.OCR1Config - 6, // 10: cfm.ChainConfig.ocr2_config:type_name -> cfm.OCR2Config - 0, // 11: cfm.UpdateNodeRequest.job_types:type_name -> cfm.JobType - 3, // 12: cfm.UpdateNodeRequest.accounts:type_name -> cfm.Account - 2, // 13: cfm.UpdateNodeRequest.chains:type_name -> cfm.Chain - 7, // 14: cfm.UpdateNodeRequest.chain_configs:type_name -> cfm.ChainConfig - 10, // 15: cfm.FeedsManager.ApprovedJob:input_type -> cfm.ApprovedJobRequest - 12, // 16: cfm.FeedsManager.Healthcheck:input_type -> cfm.HealthcheckRequest - 8, // 17: cfm.FeedsManager.UpdateNode:input_type -> cfm.UpdateNodeRequest - 14, // 18: cfm.FeedsManager.RejectedJob:input_type -> cfm.RejectedJobRequest - 16, // 19: cfm.FeedsManager.CancelledJob:input_type -> cfm.CancelledJobRequest - 18, // 20: cfm.NodeService.ProposeJob:input_type -> cfm.ProposeJobRequest - 20, // 21: cfm.NodeService.DeleteJob:input_type -> cfm.DeleteJobRequest - 22, // 22: cfm.NodeService.RevokeJob:input_type -> cfm.RevokeJobRequest - 11, // 23: cfm.FeedsManager.ApprovedJob:output_type -> cfm.ApprovedJobResponse - 13, // 24: cfm.FeedsManager.Healthcheck:output_type -> cfm.HealthcheckResponse - 9, // 25: cfm.FeedsManager.UpdateNode:output_type -> cfm.UpdateNodeResponse - 15, // 26: cfm.FeedsManager.RejectedJob:output_type -> cfm.RejectedJobResponse - 17, // 27: cfm.FeedsManager.CancelledJob:output_type -> cfm.CancelledJobResponse - 19, // 28: cfm.NodeService.ProposeJob:output_type -> cfm.ProposeJobResponse - 21, // 29: cfm.NodeService.DeleteJob:output_type -> cfm.DeleteJobResponse - 23, // 30: cfm.NodeService.RevokeJob:output_type -> cfm.RevokeJobResponse - 23, // [23:31] is the sub-list for method output_type - 15, // [15:23] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_pkg_noderpc_proto_feeds_manager_proto_init() } -func file_pkg_noderpc_proto_feeds_manager_proto_init() { - if File_pkg_noderpc_proto_feeds_manager_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Chain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Account); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FluxMonitorConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR1Config); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateNodeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateNodeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApprovedJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApprovedJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthcheckRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthcheckResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RejectedJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RejectedJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelledJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelledJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProposeJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProposeJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokeJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokeJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR1Config_P2PKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR1Config_OCRKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config_P2PKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config_OCRKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config_Plugins); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[4].OneofWrappers = []interface{}{} - file_pkg_noderpc_proto_feeds_manager_proto_msgTypes[5].OneofWrappers = []interface{}{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_noderpc_proto_feeds_manager_proto_rawDesc, - NumEnums: 2, - NumMessages: 27, - NumExtensions: 0, - NumServices: 2, - }, - GoTypes: file_pkg_noderpc_proto_feeds_manager_proto_goTypes, - DependencyIndexes: file_pkg_noderpc_proto_feeds_manager_proto_depIdxs, - EnumInfos: file_pkg_noderpc_proto_feeds_manager_proto_enumTypes, - MessageInfos: file_pkg_noderpc_proto_feeds_manager_proto_msgTypes, - }.Build() - File_pkg_noderpc_proto_feeds_manager_proto = out.File - file_pkg_noderpc_proto_feeds_manager_proto_rawDesc = nil - file_pkg_noderpc_proto_feeds_manager_proto_goTypes = nil - file_pkg_noderpc_proto_feeds_manager_proto_depIdxs = nil -} diff --git a/core/services/feeds/proto/feeds_manager_wsrpc.pb.go b/core/services/feeds/proto/feeds_manager_wsrpc.pb.go deleted file mode 100644 index 17fe100b4fc..00000000000 --- a/core/services/feeds/proto/feeds_manager_wsrpc.pb.go +++ /dev/null @@ -1,255 +0,0 @@ -// Code generated by protoc-gen-go-wsrpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-wsrpc v0.0.1 -// - protoc v4.25.3 - -package proto - -import ( - context "context" - wsrpc "github.com/smartcontractkit/wsrpc" -) - -// FeedsManagerClient is the client API for FeedsManager service. -type FeedsManagerClient interface { - ApprovedJob(ctx context.Context, in *ApprovedJobRequest) (*ApprovedJobResponse, error) - Healthcheck(ctx context.Context, in *HealthcheckRequest) (*HealthcheckResponse, error) - UpdateNode(ctx context.Context, in *UpdateNodeRequest) (*UpdateNodeResponse, error) - RejectedJob(ctx context.Context, in *RejectedJobRequest) (*RejectedJobResponse, error) - CancelledJob(ctx context.Context, in *CancelledJobRequest) (*CancelledJobResponse, error) -} - -type feedsManagerClient struct { - cc wsrpc.ClientInterface -} - -func NewFeedsManagerClient(cc wsrpc.ClientInterface) FeedsManagerClient { - return &feedsManagerClient{cc} -} - -func (c *feedsManagerClient) ApprovedJob(ctx context.Context, in *ApprovedJobRequest) (*ApprovedJobResponse, error) { - out := new(ApprovedJobResponse) - err := c.cc.Invoke(ctx, "ApprovedJob", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *feedsManagerClient) Healthcheck(ctx context.Context, in *HealthcheckRequest) (*HealthcheckResponse, error) { - out := new(HealthcheckResponse) - err := c.cc.Invoke(ctx, "Healthcheck", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *feedsManagerClient) UpdateNode(ctx context.Context, in *UpdateNodeRequest) (*UpdateNodeResponse, error) { - out := new(UpdateNodeResponse) - err := c.cc.Invoke(ctx, "UpdateNode", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *feedsManagerClient) RejectedJob(ctx context.Context, in *RejectedJobRequest) (*RejectedJobResponse, error) { - out := new(RejectedJobResponse) - err := c.cc.Invoke(ctx, "RejectedJob", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *feedsManagerClient) CancelledJob(ctx context.Context, in *CancelledJobRequest) (*CancelledJobResponse, error) { - out := new(CancelledJobResponse) - err := c.cc.Invoke(ctx, "CancelledJob", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -// FeedsManagerServer is the server API for FeedsManager service. -type FeedsManagerServer interface { - ApprovedJob(context.Context, *ApprovedJobRequest) (*ApprovedJobResponse, error) - Healthcheck(context.Context, *HealthcheckRequest) (*HealthcheckResponse, error) - UpdateNode(context.Context, *UpdateNodeRequest) (*UpdateNodeResponse, error) - RejectedJob(context.Context, *RejectedJobRequest) (*RejectedJobResponse, error) - CancelledJob(context.Context, *CancelledJobRequest) (*CancelledJobResponse, error) -} - -func RegisterFeedsManagerServer(s wsrpc.ServiceRegistrar, srv FeedsManagerServer) { - s.RegisterService(&FeedsManager_ServiceDesc, srv) -} - -func _FeedsManager_ApprovedJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(ApprovedJobRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(FeedsManagerServer).ApprovedJob(ctx, in) -} - -func _FeedsManager_Healthcheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(HealthcheckRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(FeedsManagerServer).Healthcheck(ctx, in) -} - -func _FeedsManager_UpdateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(UpdateNodeRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(FeedsManagerServer).UpdateNode(ctx, in) -} - -func _FeedsManager_RejectedJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(RejectedJobRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(FeedsManagerServer).RejectedJob(ctx, in) -} - -func _FeedsManager_CancelledJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(CancelledJobRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(FeedsManagerServer).CancelledJob(ctx, in) -} - -// FeedsManager_ServiceDesc is the wsrpc.ServiceDesc for FeedsManager service. -// It's only intended for direct use with wsrpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var FeedsManager_ServiceDesc = wsrpc.ServiceDesc{ - ServiceName: "cfm.FeedsManager", - HandlerType: (*FeedsManagerServer)(nil), - Methods: []wsrpc.MethodDesc{ - { - MethodName: "ApprovedJob", - Handler: _FeedsManager_ApprovedJob_Handler, - }, - { - MethodName: "Healthcheck", - Handler: _FeedsManager_Healthcheck_Handler, - }, - { - MethodName: "UpdateNode", - Handler: _FeedsManager_UpdateNode_Handler, - }, - { - MethodName: "RejectedJob", - Handler: _FeedsManager_RejectedJob_Handler, - }, - { - MethodName: "CancelledJob", - Handler: _FeedsManager_CancelledJob_Handler, - }, - }, -} - -// NodeServiceClient is the client API for NodeService service. -type NodeServiceClient interface { - ProposeJob(ctx context.Context, in *ProposeJobRequest) (*ProposeJobResponse, error) - DeleteJob(ctx context.Context, in *DeleteJobRequest) (*DeleteJobResponse, error) - RevokeJob(ctx context.Context, in *RevokeJobRequest) (*RevokeJobResponse, error) -} - -type nodeServiceClient struct { - cc wsrpc.ClientInterface -} - -func NewNodeServiceClient(cc wsrpc.ClientInterface) NodeServiceClient { - return &nodeServiceClient{cc} -} - -func (c *nodeServiceClient) ProposeJob(ctx context.Context, in *ProposeJobRequest) (*ProposeJobResponse, error) { - out := new(ProposeJobResponse) - err := c.cc.Invoke(ctx, "ProposeJob", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *nodeServiceClient) DeleteJob(ctx context.Context, in *DeleteJobRequest) (*DeleteJobResponse, error) { - out := new(DeleteJobResponse) - err := c.cc.Invoke(ctx, "DeleteJob", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *nodeServiceClient) RevokeJob(ctx context.Context, in *RevokeJobRequest) (*RevokeJobResponse, error) { - out := new(RevokeJobResponse) - err := c.cc.Invoke(ctx, "RevokeJob", in, out) - if err != nil { - return nil, err - } - return out, nil -} - -// NodeServiceServer is the server API for NodeService service. -type NodeServiceServer interface { - ProposeJob(context.Context, *ProposeJobRequest) (*ProposeJobResponse, error) - DeleteJob(context.Context, *DeleteJobRequest) (*DeleteJobResponse, error) - RevokeJob(context.Context, *RevokeJobRequest) (*RevokeJobResponse, error) -} - -func RegisterNodeServiceServer(s wsrpc.ServiceRegistrar, srv NodeServiceServer) { - s.RegisterService(&NodeService_ServiceDesc, srv) -} - -func _NodeService_ProposeJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(ProposeJobRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(NodeServiceServer).ProposeJob(ctx, in) -} - -func _NodeService_DeleteJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(DeleteJobRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(NodeServiceServer).DeleteJob(ctx, in) -} - -func _NodeService_RevokeJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { - in := new(RevokeJobRequest) - if err := dec(in); err != nil { - return nil, err - } - return srv.(NodeServiceServer).RevokeJob(ctx, in) -} - -// NodeService_ServiceDesc is the wsrpc.ServiceDesc for NodeService service. -// It's only intended for direct use with wsrpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var NodeService_ServiceDesc = wsrpc.ServiceDesc{ - ServiceName: "cfm.NodeService", - HandlerType: (*NodeServiceServer)(nil), - Methods: []wsrpc.MethodDesc{ - { - MethodName: "ProposeJob", - Handler: _NodeService_ProposeJob_Handler, - }, - { - MethodName: "DeleteJob", - Handler: _NodeService_DeleteJob_Handler, - }, - { - MethodName: "RevokeJob", - Handler: _NodeService_RevokeJob_Handler, - }, - }, -} diff --git a/core/services/feeds/rpc_handlers.go b/core/services/feeds/rpc_handlers.go index 770d99861e5..a079204534e 100644 --- a/core/services/feeds/rpc_handlers.go +++ b/core/services/feeds/rpc_handlers.go @@ -5,7 +5,7 @@ import ( "github.com/google/uuid" - pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" + pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" ) // RPCHandlers define handlers for RPC method calls from the Feeds Manager diff --git a/core/services/feeds/rpc_handlers_test.go b/core/services/feeds/rpc_handlers_test.go index 1648c05954d..2ba2fc15816 100644 --- a/core/services/feeds/rpc_handlers_test.go +++ b/core/services/feeds/rpc_handlers_test.go @@ -7,10 +7,10 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" + pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" "github.com/smartcontractkit/chainlink/v2/core/services/feeds/mocks" - pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" ) type TestRPCHandlers struct { diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 1733d4a7582..7479f10abb5 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -17,13 +17,15 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + + ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/plugins" + pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" "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/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" - pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -37,11 +39,13 @@ import ( ) var ( - ErrOCR2Disabled = errors.New("ocr2 is disabled") - ErrOCRDisabled = errors.New("ocr is disabled") - ErrSingleFeedsManager = errors.New("only a single feeds manager is supported") - ErrJobAlreadyExists = errors.New("a job for this contract address already exists - please use the 'force' option to replace it") - ErrFeedsManagerDisabled = errors.New("feeds manager is disabled") + ErrOCR2Disabled = errors.New("ocr2 is disabled") + ErrOCRDisabled = errors.New("ocr is disabled") + // TODO: delete once multiple feeds managers support is released + ErrSingleFeedsManager = errors.New("only a single feeds manager is supported") + ErrDuplicateFeedsManager = errors.New("manager was previously registered using the same public key") + ErrJobAlreadyExists = errors.New("a job for this contract address already exists - please use the 'force' option to replace it") + ErrFeedsManagerDisabled = errors.New("feeds manager is disabled") promJobProposalRequest = promauto.NewCounter(prometheus.CounterOpts{ Name: "feeds_job_proposal_requests", @@ -77,7 +81,6 @@ type Service interface { Start(ctx context.Context) error Close() error - CountManagers(ctx context.Context) (int64, error) GetManager(ctx context.Context, id int64) (*FeedsManager, error) ListManagers(ctx context.Context) ([]FeedsManager, error) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) @@ -98,7 +101,6 @@ type Service interface { CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) - ListJobProposals(ctx context.Context) ([]JobProposal, error) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) ApproveSpec(ctx context.Context, id int64, force bool) error @@ -124,6 +126,7 @@ type service struct { ocr2KeyStore keystore.OCR2 jobSpawner job.Spawner gCfg GeneralConfig + featCfg FeatureConfig insecureCfg InsecureConfig jobCfg JobConfig ocrCfg OCRConfig @@ -143,6 +146,7 @@ func NewService( jobSpawner job.Spawner, keyStore keystore.Master, gCfg GeneralConfig, + fCfg FeatureConfig, insecureCfg InsecureConfig, jobCfg JobConfig, ocrCfg OCRConfig, @@ -163,6 +167,7 @@ func NewService( ocr1KeyStore: keyStore.OCR(), ocr2KeyStore: keyStore.OCR2(), gCfg: gCfg, + featCfg: fCfg, insecureCfg: insecureCfg, jobCfg: jobCfg, ocrCfg: ocrCfg, @@ -186,15 +191,23 @@ type RegisterManagerParams struct { // RegisterManager registers a new ManagerService and attempts to establish a // connection. -// -// Only a single feeds manager is currently supported. func (s *service) RegisterManager(ctx context.Context, params RegisterManagerParams) (int64, error) { - count, err := s.CountManagers(ctx) - if err != nil { - return 0, err - } - if count >= 1 { - return 0, ErrSingleFeedsManager + if s.featCfg.MultiFeedsManagers() { + exists, err := s.orm.ManagerExists(ctx, params.PublicKey) + if err != nil { + return 0, err + } + if exists { + return 0, ErrDuplicateFeedsManager + } + } else { + count, err := s.CountManagers(ctx) + if err != nil { + return 0, err + } + if count >= 1 { + return 0, ErrSingleFeedsManager + } } mgr := FeedsManager{ @@ -205,11 +218,11 @@ func (s *service) RegisterManager(ctx context.Context, params RegisterManagerPar var id int64 - err = s.orm.Transact(ctx, func(tx ORM) error { + err := s.orm.Transact(ctx, func(tx ORM) error { var txerr error id, txerr = tx.CreateManager(ctx, &mgr) - if err != nil { + if txerr != nil { return txerr } @@ -219,6 +232,9 @@ func (s *service) RegisterManager(ctx context.Context, params RegisterManagerPar return nil }) + if err != nil { + return 0, err + } privkey, err := s.getCSAPrivateKey() if err != nil { @@ -322,6 +338,7 @@ func (s *service) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsMa } // CountManagers gets the total number of manager services +// TODO: delete once multiple feeds managers support is released func (s *service) CountManagers(ctx context.Context) (int64, error) { return s.orm.CountManagers(ctx) } @@ -418,14 +435,6 @@ func (s *service) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64 return id, nil } -// Lists all JobProposals -// -// When we support multiple feed managers, we will need to change this to filter -// by feeds manager -func (s *service) ListJobProposals(ctx context.Context) ([]JobProposal, error) { - return s.orm.ListJobProposals(ctx) -} - // ListJobProposalsByManagersIDs gets job proposals by feeds managers IDs func (s *service) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { return s.orm.ListJobProposalsByManagersIDs(ctx, ids) @@ -811,6 +820,13 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { return fmt.Errorf("failed while checking for existing workflow job: %w", txerr) } } + case job.CCIP: + existingJobID, txerr = tx.jobORM.FindJobIDByCapabilityNameAndVersion(ctx, *j.CCIPSpec) + // Return an error if the repository errors. If there is a not found + // error we want to continue with approving the job. + if txerr != nil && !errors.Is(txerr, sql.ErrNoRows) { + return fmt.Errorf("failed while checking for existing ccip job: %w", txerr) + } default: return errors.Errorf("unsupported job type when approving job proposal specs: %s", j.Type) } @@ -1020,7 +1036,6 @@ func (s *service) Start(ctx context.Context) error { return err } - // We only support a single feeds manager right now mgrs, err := s.ListManagers(ctx) if err != nil { return err @@ -1031,8 +1046,14 @@ func (s *service) Start(ctx context.Context) error { return nil } - mgr := mgrs[0] - s.connectFeedManager(ctx, mgr, privkey) + if s.featCfg.MultiFeedsManagers() { + s.lggr.Infof("starting connection to %d feeds managers", len(mgrs)) + for _, mgr := range mgrs { + s.connectFeedManager(ctx, mgr, privkey) + } + } else { + s.connectFeedManager(ctx, mgrs[0], privkey) + } if err = s.observeJobProposalCounts(ctx); err != nil { s.lggr.Error("failed to observe job proposal count when starting service", err) @@ -1189,7 +1210,9 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error case job.FluxMonitor: js, err = fluxmonitorv2.ValidatedFluxMonitorSpec(s.jobCfg, spec) case job.Workflow: - js, err = workflows.ValidatedWorkflowJobSpec(spec) + js, err = workflows.ValidatedWorkflowJobSpec(ctx, spec) + case job.CCIP: + js, err = ccip.ValidatedCCIPSpec(spec) default: return nil, errors.Errorf("unknown job type: %s", jobType) } @@ -1202,9 +1225,9 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error // newChainConfigMsg generates a chain config protobuf message. func (s *service) newChainConfigMsg(cfg ChainConfig) (*pb.ChainConfig, error) { - // Only supports EVM Chains - if cfg.ChainType != "EVM" { - return nil, errors.New("unsupported chain type") + protoChainType := ChainTypeToProtoChainType(cfg.ChainType) + if protoChainType == pb.ChainType_CHAIN_TYPE_UNSPECIFIED { + return nil, errors.Errorf("unsupported chain type: %s", cfg.ChainType) } ocr1Cfg, err := s.newOCR1ConfigMsg(cfg.OCR1Config) @@ -1220,7 +1243,7 @@ func (s *service) newChainConfigMsg(cfg ChainConfig) (*pb.ChainConfig, error) { pbChainConfig := pb.ChainConfig{ Chain: &pb.Chain{ Id: cfg.ChainID, - Type: pb.ChainType_CHAIN_TYPE_EVM, + Type: protoChainType, }, AccountAddress: cfg.AccountAddress, AdminAddress: cfg.AdminAddress, @@ -1447,7 +1470,6 @@ func (ns NullService) Close() error { return nil } func (ns NullService) ApproveSpec(ctx context.Context, id int64, force bool) error { return ErrFeedsManagerDisabled } -func (ns NullService) CountManagers(ctx context.Context) (int64, error) { return 0, nil } func (ns NullService) CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) { return nil, ErrFeedsManagerDisabled } diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index 3ee7adc0d70..e7472a5ae54 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -19,6 +19,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + proto "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -32,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" "github.com/smartcontractkit/chainlink/v2/core/services/feeds/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" "github.com/smartcontractkit/chainlink/v2/core/services/job" jobmocks "github.com/smartcontractkit/chainlink/v2/core/services/job/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" @@ -40,7 +40,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" @@ -186,15 +185,14 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * gcfg := configtest.NewGeneralConfig(t, overrideCfg) keyStore := new(ksmocks.Master) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: gcfg, + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: gcfg, HeadTracker: headtracker.NullTracker, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) keyStore.On("Eth").Return(ethKeyStore) keyStore.On("CSA").Return(csaKeystore) keyStore.On("P2P").Return(p2pKeystore) keyStore.On("OCR").Return(ocr1Keystore) keyStore.On("OCR2").Return(ocr2Keystore) - svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), legacyChains, lggr, "1.0.0", nil) + svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Feature(), gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), legacyChains, lggr, "1.0.0", nil) svc.SetConnectionsManager(connMgr) return &TestService{ @@ -265,6 +263,149 @@ func Test_Service_RegisterManager(t *testing.T) { assert.Equal(t, actual, id) } +func Test_Service_RegisterManager_MultiFeedsManager(t *testing.T) { + t.Parallel() + + key := cltest.DefaultCSAKey + + var ( + id = int64(1) + pubKeyHex = "0f17c3bf72de8beef6e2d17a14c0a972f5d7e0e66e70722373f12b88382d40f9" + ) + + var pubKey crypto.PublicKey + _, err := hex.Decode([]byte(pubKeyHex), pubKey) + require.NoError(t, err) + + var ( + mgr = feeds.FeedsManager{ + Name: "FMS", + URI: "localhost:8080", + PublicKey: pubKey, + } + params = feeds.RegisterManagerParams{ + Name: "FMS", + URI: "localhost:8080", + PublicKey: pubKey, + } + ) + + svc := setupTestServiceCfg(t, func(c *chainlink.Config, s *chainlink.Secrets) { + var multiFeedsManagers = true + c.Feature.MultiFeedsManagers = &multiFeedsManagers + }) + ctx := testutils.Context(t) + + svc.orm.On("ManagerExists", ctx, params.PublicKey).Return(false, nil) + svc.orm.On("CreateManager", mock.Anything, &mgr, mock.Anything). + Return(id, nil) + svc.orm.On("CreateBatchChainConfig", mock.Anything, params.ChainConfigs, mock.Anything). + Return([]int64{}, nil) + svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) + // ListManagers runs in a goroutine so it might be called. + svc.orm.On("ListManagers", ctx).Return([]feeds.FeedsManager{mgr}, nil).Maybe() + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) + svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})) + + actual, err := svc.RegisterManager(ctx, params) + // We need to stop the service because the manager will attempt to make a + // connection + svc.Close() + require.NoError(t, err) + + assert.Equal(t, actual, id) +} + +func Test_Service_RegisterManager_InvalidCreateManager(t *testing.T) { + t.Parallel() + + var ( + id = int64(1) + pubKeyHex = "0f17c3bf72de8beef6e2d17a14c0a972f5d7e0e66e70722373f12b88382d40f9" + ) + + var pubKey crypto.PublicKey + _, err := hex.Decode([]byte(pubKeyHex), pubKey) + require.NoError(t, err) + + var ( + mgr = feeds.FeedsManager{ + Name: "FMS", + URI: "localhost:8080", + PublicKey: pubKey, + } + params = feeds.RegisterManagerParams{ + Name: "FMS", + URI: "localhost:8080", + PublicKey: pubKey, + } + ) + + svc := setupTestService(t) + + svc.orm.On("CountManagers", mock.Anything).Return(int64(0), nil) + svc.orm.On("CreateManager", mock.Anything, &mgr, mock.Anything). + Return(id, errors.New("orm error")) + // ListManagers runs in a goroutine so it might be called. + svc.orm.On("ListManagers", testutils.Context(t)).Return([]feeds.FeedsManager{mgr}, nil).Maybe() + + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) + _, err = svc.RegisterManager(testutils.Context(t), params) + // We need to stop the service because the manager will attempt to make a + // connection + svc.Close() + require.Error(t, err) + assert.Equal(t, "orm error", err.Error()) +} + +func Test_Service_RegisterManager_DuplicateFeedsManager(t *testing.T) { + t.Parallel() + + var pubKeyHex = "0f17c3bf72de8beef6e2d17a14c0a972f5d7e0e66e70722373f12b88382d40f9" + var pubKey crypto.PublicKey + _, err := hex.Decode([]byte(pubKeyHex), pubKey) + require.NoError(t, err) + + var ( + mgr = feeds.FeedsManager{ + Name: "FMS", + URI: "localhost:8080", + PublicKey: pubKey, + } + params = feeds.RegisterManagerParams{ + Name: "FMS", + URI: "localhost:8080", + PublicKey: pubKey, + } + ) + + svc := setupTestServiceCfg(t, func(c *chainlink.Config, s *chainlink.Secrets) { + var multiFeedsManagers = true + c.Feature.MultiFeedsManagers = &multiFeedsManagers + }) + ctx := testutils.Context(t) + + svc.orm.On("ManagerExists", ctx, params.PublicKey).Return(true, nil) + // ListManagers runs in a goroutine so it might be called. + svc.orm.On("ListManagers", ctx).Return([]feeds.FeedsManager{mgr}, nil).Maybe() + + _, err = svc.RegisterManager(ctx, params) + // We need to stop the service because the manager will attempt to make a + // connection + svc.Close() + require.Error(t, err) + + assert.Equal(t, "manager was previously registered using the same public key", err.Error()) +} + func Test_Service_ListManagers(t *testing.T) { t.Parallel() ctx := testutils.Context(t) @@ -342,76 +483,94 @@ func Test_Service_ListManagersByIDs(t *testing.T) { assert.Equal(t, mgrs, actual) } -func Test_Service_CountManagers(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - - var ( - count = int64(1) - ) - svc := setupTestService(t) - - svc.orm.On("CountManagers", mock.Anything). - Return(count, nil) - - actual, err := svc.CountManagers(ctx) - require.NoError(t, err) - - assert.Equal(t, count, actual) -} - func Test_Service_CreateChainConfig(t *testing.T) { - var ( - mgr = feeds.FeedsManager{ID: 1} - nodeVersion = &versioning.NodeVersion{ - Version: "1.0.0", - } - cfg = feeds.ChainConfig{ - FeedsManagerID: mgr.ID, - ChainID: "42", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0000000000000000000000000000000000000000", - AccountAddressPublicKey: null.StringFrom("0x0000000000000000000000000000000000000002"), - AdminAddress: "0x0000000000000000000000000000000000000001", - FluxMonitorConfig: feeds.FluxMonitorConfig{ - Enabled: true, - }, - OCR1Config: feeds.OCR1Config{ - Enabled: false, - }, - OCR2Config: feeds.OCR2ConfigModel{ - Enabled: false, - }, - } + tests := []struct { + name string + chainType feeds.ChainType + expectedID int64 + expectedChainType proto.ChainType + }{ + { + name: "EVM Chain Type", + chainType: feeds.ChainTypeEVM, + expectedID: int64(1), + expectedChainType: proto.ChainType_CHAIN_TYPE_EVM, + }, + { + name: "Solana Chain Type", + chainType: feeds.ChainTypeSolana, + expectedID: int64(1), + expectedChainType: proto.ChainType_CHAIN_TYPE_SOLANA, + }, + { + name: "Starknet Chain Type", + chainType: feeds.ChainTypeStarknet, + expectedID: int64(1), + expectedChainType: proto.ChainType_CHAIN_TYPE_STARKNET, + }, + { + name: "Aptos Chain Type", + chainType: feeds.ChainTypeAptos, + expectedID: int64(1), + expectedChainType: proto.ChainType_CHAIN_TYPE_APTOS, + }, + } - svc = setupTestService(t) - ) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var ( + mgr = feeds.FeedsManager{ID: 1} + nodeVersion = &versioning.NodeVersion{ + Version: "1.0.0", + } + cfg = feeds.ChainConfig{ + FeedsManagerID: mgr.ID, + ChainID: "42", + ChainType: tt.chainType, + AccountAddress: "0x0000000000000000000000000000000000000000", + AccountAddressPublicKey: null.StringFrom("0x0000000000000000000000000000000000000002"), + AdminAddress: "0x0000000000000000000000000000000000000001", + FluxMonitorConfig: feeds.FluxMonitorConfig{ + Enabled: true, + }, + OCR1Config: feeds.OCR1Config{ + Enabled: false, + }, + OCR2Config: feeds.OCR2ConfigModel{ + Enabled: false, + }, + } - svc.orm.On("CreateChainConfig", mock.Anything, cfg).Return(int64(1), nil) - svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) - svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) - svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ - Version: nodeVersion.Version, - ChainConfigs: []*proto.ChainConfig{ - { - Chain: &proto.Chain{ - Id: cfg.ChainID, - Type: proto.ChainType_CHAIN_TYPE_EVM, + svc = setupTestService(t) + ) + + svc.orm.On("CreateChainConfig", mock.Anything, cfg).Return(int64(1), nil) + svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) + svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ + Version: nodeVersion.Version, + ChainConfigs: []*proto.ChainConfig{ + { + Chain: &proto.Chain{ + Id: cfg.ChainID, + Type: tt.expectedChainType, + }, + AccountAddress: cfg.AccountAddress, + AccountAddressPublicKey: &cfg.AccountAddressPublicKey.String, + AdminAddress: cfg.AdminAddress, + FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: true}, + Ocr1Config: &proto.OCR1Config{Enabled: false}, + Ocr2Config: &proto.OCR2Config{Enabled: false}, + }, }, - AccountAddress: cfg.AccountAddress, - AccountAddressPublicKey: &cfg.AccountAddressPublicKey.String, - AdminAddress: cfg.AdminAddress, - FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: true}, - Ocr1Config: &proto.OCR1Config{Enabled: false}, - Ocr2Config: &proto.OCR2Config{Enabled: false}, - }, - }, - }).Return(&proto.UpdateNodeResponse{}, nil) + }).Return(&proto.UpdateNodeResponse{}, nil) - actual, err := svc.CreateChainConfig(testutils.Context(t), cfg) - require.NoError(t, err) - assert.Equal(t, int64(1), actual) + actual, err := svc.CreateChainConfig(testutils.Context(t), cfg) + require.NoError(t, err) + assert.Equal(t, tt.expectedID, actual) + }) + } } func Test_Service_CreateChainConfig_InvalidAdminAddress(t *testing.T) { @@ -485,51 +644,82 @@ func Test_Service_ListChainConfigsByManagerIDs(t *testing.T) { } func Test_Service_UpdateChainConfig(t *testing.T) { - var ( - mgr = feeds.FeedsManager{ID: 1} - nodeVersion = &versioning.NodeVersion{ - Version: "1.0.0", - } - cfg = feeds.ChainConfig{ - FeedsManagerID: mgr.ID, - ChainID: "42", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0000000000000000000000000000000000000000", - AccountAddressPublicKey: null.StringFrom("0x0000000000000000000000000000000000000002"), - AdminAddress: "0x0000000000000000000000000000000000000001", - FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: false}, - OCR1Config: feeds.OCR1Config{Enabled: false}, - OCR2Config: feeds.OCR2ConfigModel{Enabled: false}, - } + tests := []struct { + name string + chainType feeds.ChainType + expectedChainType proto.ChainType + }{ + { + name: "EVM Chain Type", + chainType: feeds.ChainTypeEVM, + expectedChainType: proto.ChainType_CHAIN_TYPE_EVM, + }, + { + name: "Solana Chain Type", + chainType: feeds.ChainTypeSolana, + expectedChainType: proto.ChainType_CHAIN_TYPE_SOLANA, + }, + { + name: "Starknet Chain Type", + chainType: feeds.ChainTypeStarknet, + expectedChainType: proto.ChainType_CHAIN_TYPE_STARKNET, + }, + { + name: "Aptos Chain Type", + chainType: feeds.ChainTypeAptos, + expectedChainType: proto.ChainType_CHAIN_TYPE_APTOS, + }, + } - svc = setupTestService(t) - ) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var ( + mgr = feeds.FeedsManager{ID: 1} + nodeVersion = &versioning.NodeVersion{ + Version: "1.0.0", + } + cfg = feeds.ChainConfig{ + FeedsManagerID: mgr.ID, + ChainID: "42", + ChainType: tt.chainType, + AccountAddress: "0x0000000000000000000000000000000000000000", + AccountAddressPublicKey: null.StringFrom("0x0000000000000000000000000000000000000002"), + AdminAddress: "0x0000000000000000000000000000000000000001", + FluxMonitorConfig: feeds.FluxMonitorConfig{Enabled: false}, + OCR1Config: feeds.OCR1Config{Enabled: false}, + OCR2Config: feeds.OCR2ConfigModel{Enabled: false}, + } - svc.orm.On("UpdateChainConfig", mock.Anything, cfg).Return(int64(1), nil) - svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) - svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) - svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ - Version: nodeVersion.Version, - ChainConfigs: []*proto.ChainConfig{ - { - Chain: &proto.Chain{ - Id: cfg.ChainID, - Type: proto.ChainType_CHAIN_TYPE_EVM, + svc = setupTestService(t) + ) + + svc.orm.On("UpdateChainConfig", mock.Anything, cfg).Return(int64(1), nil) + svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) + svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ + Version: nodeVersion.Version, + ChainConfigs: []*proto.ChainConfig{ + { + Chain: &proto.Chain{ + Id: cfg.ChainID, + Type: tt.expectedChainType, + }, + AccountAddress: cfg.AccountAddress, + AdminAddress: cfg.AdminAddress, + AccountAddressPublicKey: &cfg.AccountAddressPublicKey.String, + FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: false}, + Ocr1Config: &proto.OCR1Config{Enabled: false}, + Ocr2Config: &proto.OCR2Config{Enabled: false}, + }, }, - AccountAddress: cfg.AccountAddress, - AdminAddress: cfg.AdminAddress, - AccountAddressPublicKey: &cfg.AccountAddressPublicKey.String, - FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: false}, - Ocr1Config: &proto.OCR1Config{Enabled: false}, - Ocr2Config: &proto.OCR2Config{Enabled: false}, - }, - }, - }).Return(&proto.UpdateNodeResponse{}, nil) + }).Return(&proto.UpdateNodeResponse{}, nil) - actual, err := svc.UpdateChainConfig(testutils.Context(t), cfg) - require.NoError(t, err) - assert.Equal(t, int64(1), actual) + actual, err := svc.UpdateChainConfig(testutils.Context(t), cfg) + require.NoError(t, err) + assert.Equal(t, int64(1), actual) + }) + } } func Test_Service_UpdateChainConfig_InvalidAdminAddress(t *testing.T) { @@ -1369,102 +1559,133 @@ answer1 [type=median index=0]; } func Test_Service_SyncNodeInfo(t *testing.T) { - p2pKey := keystest.NewP2PKeyV2(t) - - ocrKey, err := ocrkey.NewV2() - require.NoError(t, err) - - var ( - multiaddr = "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju" - mgr = &feeds.FeedsManager{ID: 1} - forwarderAddr = "0x0002" - ccfg = feeds.ChainConfig{ - ID: 100, - FeedsManagerID: mgr.ID, - ChainID: "42", - ChainType: feeds.ChainTypeEVM, - AccountAddress: "0x0000", - AdminAddress: "0x0001", - FluxMonitorConfig: feeds.FluxMonitorConfig{ - Enabled: true, - }, - OCR1Config: feeds.OCR1Config{ - Enabled: true, - IsBootstrap: false, - P2PPeerID: null.StringFrom(p2pKey.PeerID().String()), - KeyBundleID: null.StringFrom(ocrKey.GetID()), - }, - OCR2Config: feeds.OCR2ConfigModel{ - Enabled: true, - IsBootstrap: true, - Multiaddr: null.StringFrom(multiaddr), - ForwarderAddress: null.StringFrom(forwarderAddr), - Plugins: feeds.Plugins{ - Commit: true, - Execute: true, - Median: false, - Mercury: true, - Rebalancer: true, - }, - }, - } - chainConfigs = []feeds.ChainConfig{ccfg} - nodeVersion = &versioning.NodeVersion{Version: "1.0.0"} - ) - - svc := setupTestService(t) + tests := []struct { + name string + chainType feeds.ChainType + protoType proto.ChainType + }{ + { + name: "EVM Chain Type", + chainType: feeds.ChainTypeEVM, + protoType: proto.ChainType_CHAIN_TYPE_EVM, + }, + { + name: "Solana Chain Type", + chainType: feeds.ChainTypeSolana, + protoType: proto.ChainType_CHAIN_TYPE_SOLANA, + }, + { + name: "Starknet Chain Type", + chainType: feeds.ChainTypeStarknet, + protoType: proto.ChainType_CHAIN_TYPE_STARKNET, + }, + { + name: "Aptos Chain Type", + chainType: feeds.ChainTypeAptos, + protoType: proto.ChainType_CHAIN_TYPE_APTOS, + }, + } - svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return(chainConfigs, nil) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p2pKey := keystest.NewP2PKeyV2(t) - // OCR1 key fetching - svc.p2pKeystore.On("Get", p2pKey.PeerID()).Return(p2pKey, nil) - svc.ocr1Keystore.On("Get", ocrKey.GetID()).Return(ocrKey, nil) + ocrKey, err := ocrkey.NewV2() + require.NoError(t, err) - svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ - Version: nodeVersion.Version, - ChainConfigs: []*proto.ChainConfig{ - { - Chain: &proto.Chain{ - Id: ccfg.ChainID, - Type: proto.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: ccfg.AccountAddress, - AdminAddress: ccfg.AdminAddress, - FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: true}, - Ocr1Config: &proto.OCR1Config{ - Enabled: true, - IsBootstrap: ccfg.OCR1Config.IsBootstrap, - P2PKeyBundle: &proto.OCR1Config_P2PKeyBundle{ - PeerId: p2pKey.PeerID().String(), - PublicKey: p2pKey.PublicKeyHex(), + var ( + multiaddr = "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju" + mgr = &feeds.FeedsManager{ID: 1} + forwarderAddr = "0x0002" + ccfg = feeds.ChainConfig{ + ID: 100, + FeedsManagerID: mgr.ID, + ChainID: "42", + ChainType: tt.chainType, + AccountAddress: "0x0000", + AdminAddress: "0x0001", + FluxMonitorConfig: feeds.FluxMonitorConfig{ + Enabled: true, }, - OcrKeyBundle: &proto.OCR1Config_OCRKeyBundle{ - BundleId: ocrKey.GetID(), - ConfigPublicKey: ocrkey.ConfigPublicKey(ocrKey.PublicKeyConfig()).String(), - OffchainPublicKey: ocrKey.OffChainSigning.PublicKey().String(), - OnchainSigningAddress: ocrKey.OnChainSigning.Address().String(), + OCR1Config: feeds.OCR1Config{ + Enabled: true, + IsBootstrap: false, + P2PPeerID: null.StringFrom(p2pKey.PeerID().String()), + KeyBundleID: null.StringFrom(ocrKey.GetID()), }, - }, - Ocr2Config: &proto.OCR2Config{ - Enabled: true, - IsBootstrap: ccfg.OCR2Config.IsBootstrap, - Multiaddr: multiaddr, - ForwarderAddress: &forwarderAddr, - Plugins: &proto.OCR2Config_Plugins{ - Commit: ccfg.OCR2Config.Plugins.Commit, - Execute: ccfg.OCR2Config.Plugins.Execute, - Median: ccfg.OCR2Config.Plugins.Median, - Mercury: ccfg.OCR2Config.Plugins.Mercury, - Rebalancer: ccfg.OCR2Config.Plugins.Rebalancer, + OCR2Config: feeds.OCR2ConfigModel{ + Enabled: true, + IsBootstrap: true, + Multiaddr: null.StringFrom(multiaddr), + ForwarderAddress: null.StringFrom(forwarderAddr), + Plugins: feeds.Plugins{ + Commit: true, + Execute: true, + Median: false, + Mercury: true, + Rebalancer: true, + }, + }, + } + chainConfigs = []feeds.ChainConfig{ccfg} + nodeVersion = &versioning.NodeVersion{Version: "1.0.0"} + ) + + svc := setupTestService(t) + + svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return(chainConfigs, nil) + + // OCR1 key fetching + svc.p2pKeystore.On("Get", p2pKey.PeerID()).Return(p2pKey, nil) + svc.ocr1Keystore.On("Get", ocrKey.GetID()).Return(ocrKey, nil) + + svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ + Version: nodeVersion.Version, + ChainConfigs: []*proto.ChainConfig{ + { + Chain: &proto.Chain{ + Id: ccfg.ChainID, + Type: tt.protoType, + }, + AccountAddress: ccfg.AccountAddress, + AdminAddress: ccfg.AdminAddress, + FluxMonitorConfig: &proto.FluxMonitorConfig{Enabled: true}, + Ocr1Config: &proto.OCR1Config{ + Enabled: true, + IsBootstrap: ccfg.OCR1Config.IsBootstrap, + P2PKeyBundle: &proto.OCR1Config_P2PKeyBundle{ + PeerId: p2pKey.PeerID().String(), + PublicKey: p2pKey.PublicKeyHex(), + }, + OcrKeyBundle: &proto.OCR1Config_OCRKeyBundle{ + BundleId: ocrKey.GetID(), + ConfigPublicKey: ocrkey.ConfigPublicKey(ocrKey.PublicKeyConfig()).String(), + OffchainPublicKey: ocrKey.OffChainSigning.PublicKey().String(), + OnchainSigningAddress: ocrKey.OnChainSigning.Address().String(), + }, + }, + Ocr2Config: &proto.OCR2Config{ + Enabled: true, + IsBootstrap: ccfg.OCR2Config.IsBootstrap, + Multiaddr: multiaddr, + ForwarderAddress: &forwarderAddr, + Plugins: &proto.OCR2Config_Plugins{ + Commit: ccfg.OCR2Config.Plugins.Commit, + Execute: ccfg.OCR2Config.Plugins.Execute, + Median: ccfg.OCR2Config.Plugins.Median, + Mercury: ccfg.OCR2Config.Plugins.Mercury, + Rebalancer: ccfg.OCR2Config.Plugins.Rebalancer, + }, + }, }, }, - }, - }, - }).Return(&proto.UpdateNodeResponse{}, nil) + }).Return(&proto.UpdateNodeResponse{}, nil) - err = svc.SyncNodeInfo(testutils.Context(t), mgr.ID) - require.NoError(t, err) + err = svc.SyncNodeInfo(testutils.Context(t), mgr.ID) + require.NoError(t, err) + }) + } } func Test_Service_IsJobManaged(t *testing.T) { @@ -1481,25 +1702,6 @@ func Test_Service_IsJobManaged(t *testing.T) { assert.True(t, isManaged) } -func Test_Service_ListJobProposals(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - - var ( - jp = feeds.JobProposal{} - jps = []feeds.JobProposal{jp} - ) - svc := setupTestService(t) - - svc.orm.On("ListJobProposals", mock.Anything). - Return(jps, nil) - - actual, err := svc.ListJobProposals(ctx) - require.NoError(t, err) - - assert.Equal(t, actual, jps) -} - func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { t.Parallel() ctx := testutils.Context(t) @@ -3805,6 +4007,10 @@ func Test_Service_StartStop(t *testing.T) { ID: 1, URI: "localhost:2000", } + mgr2 = feeds.FeedsManager{ + ID: 2, + URI: "localhost:2001", + } pubKeyHex = "0f17c3bf72de8beef6e2d17a14c0a972f5d7e0e66e70722373f12b88382d40f9" ) @@ -3813,8 +4019,9 @@ func Test_Service_StartStop(t *testing.T) { require.NoError(t, err) tests := []struct { - name string - beforeFunc func(svc *TestService) + name string + enableMultiFeedsManagers bool + beforeFunc func(svc *TestService) }{ { name: "success with a feeds manager connection", @@ -3827,6 +4034,19 @@ func Test_Service_StartStop(t *testing.T) { svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, }, + { + name: "success with multiple feeds managers connection", + enableMultiFeedsManagers: true, + beforeFunc: func(svc *TestService) { + svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) + svc.orm.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{mgr, mgr2}, nil) + svc.connMgr.On("IsConnected", mgr.ID).Return(false) + svc.connMgr.On("IsConnected", mgr2.ID).Return(false) + svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})).Twice() + svc.connMgr.On("Close") + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + }, + }, { name: "success with no registered managers", beforeFunc: func(svc *TestService) { @@ -3843,7 +4063,9 @@ func Test_Service_StartStop(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - svc := setupTestService(t) + svc := setupTestServiceCfg(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Feature.MultiFeedsManagers = &tt.enableMultiFeedsManagers + }) if tt.beforeFunc != nil { tt.beforeFunc(svc) diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 1d1ed676e48..0c6edb5ec63 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -14,7 +14,6 @@ import ( "github.com/onsi/gomega" "github.com/pkg/errors" "github.com/shopspring/decimal" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" @@ -23,13 +22,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" logmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -42,6 +41,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" pipelinemocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) const oracleCount uint8 = 17 @@ -1307,7 +1307,7 @@ func TestFluxMonitor_UsesPreviousRoundStateOnStartup_IdleTimer(t *testing.T) { servicetest.Run(t, fm) - assert.Eventually(t, func() bool { return len(initialPollOccurred) == 1 }, 3*time.Second, 10*time.Millisecond) + require.Eventually(t, func() bool { return len(initialPollOccurred) == 1 }, 3*time.Second, 10*time.Millisecond) if tc.expectedToSubmit { g.Eventually(chRoundState).Should(gomega.BeClosed()) diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index 2dacac54281..40bdf71743d 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -26,6 +26,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -35,7 +36,6 @@ import ( faw "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -45,6 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/web" ) diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index a1a29bf2500..b04c5c130e7 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -37,7 +37,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config" threshold_mocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/threshold/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" evmrelay_mocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types/mocks" s4_mocks "github.com/smartcontractkit/chainlink/v2/core/services/s4/mocks" @@ -86,8 +85,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe db := pgtest.NewSqlxDB(t) kst := cltest.NewKeyStore(t, db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, KeyStore: kst.Eth(), LogBroadcaster: broadcaster, MailMon: mailMon}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, KeyStore: kst.Eth(), LogBroadcaster: broadcaster, MailMon: mailMon}) chain := legacyChains.Slice()[0] lggr := logger.TestLogger(t) diff --git a/core/services/gateway/api/message.go b/core/services/gateway/api/message.go index 5e6c8e49247..86813c26b35 100644 --- a/core/services/gateway/api/message.go +++ b/core/services/gateway/api/message.go @@ -93,7 +93,7 @@ func (m *Message) Sign(privateKey *ecdsa.PrivateKey) error { if m == nil { return errors.New("nil message") } - rawData := getRawMessageBody(&m.Body) + rawData := GetRawMessageBody(&m.Body) signature, err := gw_common.SignData(privateKey, rawData...) if err != nil { return err @@ -107,7 +107,7 @@ func (m *Message) ExtractSigner() (signerAddress []byte, err error) { if m == nil { return nil, errors.New("nil message") } - rawData := getRawMessageBody(&m.Body) + rawData := GetRawMessageBody(&m.Body) signatureBytes, err := hex.DecodeString(m.Signature) if err != nil { return nil, err @@ -115,7 +115,7 @@ func (m *Message) ExtractSigner() (signerAddress []byte, err error) { return gw_common.ExtractSigner(signatureBytes, rawData...) } -func getRawMessageBody(msgBody *MessageBody) [][]byte { +func GetRawMessageBody(msgBody *MessageBody) [][]byte { alignedMessageId := make([]byte, MessageIdMaxLen) copy(alignedMessageId, msgBody.MessageId) alignedMethod := make([]byte, MessageMethodMaxLen) diff --git a/core/services/gateway/config/config.go b/core/services/gateway/config/config.go index a4d94155c8f..02c1b44869f 100644 --- a/core/services/gateway/config/config.go +++ b/core/services/gateway/config/config.go @@ -10,7 +10,9 @@ type GatewayConfig struct { UserServerConfig gw_net.HTTPServerConfig NodeServerConfig gw_net.WebSocketServerConfig ConnectionManagerConfig ConnectionManagerConfig - Dons []DONConfig + // HTTPClientConfig is configuration for outbound HTTP calls to external endpoints + HTTPClientConfig gw_net.HTTPClientConfig + Dons []DONConfig } type ConnectionManagerConfig struct { diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go index 64ae46e6206..18d34007c56 100644 --- a/core/services/gateway/connector/connector.go +++ b/core/services/gateway/connector/connector.go @@ -12,7 +12,7 @@ import ( "github.com/jonboulle/clockwork" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" + commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" @@ -26,7 +26,15 @@ type GatewayConnector interface { job.ServiceCtx network.ConnectionInitiator + AddHandler(methods []string, handler GatewayConnectorHandler) error + // SendToGateway takes a signed message as argument and sends it to the specified gateway SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error + // SignAndSendToGateway signs the message and sends the message to the specified gateway + SignAndSendToGateway(ctx context.Context, gatewayID string, msg *api.MessageBody) error + // GatewayIDs returns the list of Gateway IDs + GatewayIDs() []string + // DonID returns the DON ID + DonID() string } // Signer implementation needs to be provided by a GatewayConnector user (node) @@ -51,7 +59,7 @@ type gatewayConnector struct { clock clockwork.Clock nodeAddress []byte signer Signer - handler GatewayConnectorHandler + handlers map[string]GatewayConnectorHandler gateways map[string]*gatewayState urlToId map[string]string closeWait sync.WaitGroup @@ -76,14 +84,14 @@ type gatewayState struct { wsClient network.WebSocketClient } -func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler GatewayConnectorHandler, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) { - if config == nil || signer == nil || handler == nil || clock == nil || lggr == nil { +func NewGatewayConnector(config *ConnectorConfig, signer Signer, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) { + if config == nil || signer == nil || clock == nil || lggr == nil { return nil, errors.New("nil dependency") } if len(config.DonId) == 0 || len(config.DonId) > network.HandshakeDonIdLen { return nil, errors.New("invalid DON ID") } - addressBytes, err := hex.DecodeString(config.NodeAddress) + addressBytes, err := commonhex.DecodeString(config.NodeAddress) if err != nil { return nil, err } @@ -93,7 +101,7 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler Gateway clock: clock, nodeAddress: addressBytes, signer: signer, - handler: handler, + handlers: make(map[string]GatewayConnectorHandler), shutdownCh: make(chan struct{}), lggr: lggr.Named("GatewayConnector"), } @@ -111,8 +119,9 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler Gateway if err != nil { return nil, err } + l := lggr.With("URL", parsedURL) gateway := &gatewayState{ - conn: network.NewWSConnectionWrapper(lggr), + conn: network.NewWSConnectionWrapper(l), config: gw, url: parsedURL, wsClient: network.NewWebSocketClient(config.WsClientConfig, connector, lggr), @@ -125,6 +134,22 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler Gateway return connector, nil } +func (c *gatewayConnector) AddHandler(methods []string, handler GatewayConnectorHandler) error { + if handler == nil { + return errors.New("cannot add a nil handler") + } + for _, method := range methods { + if _, exists := c.handlers[method]; exists { + return fmt.Errorf("handler for method %s already exists", method) + } + } + // add all or nothing + for _, method := range methods { + c.handlers[method] = handler + } + return nil +} + func (c *gatewayConnector) SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error { data, err := c.codec.EncodeResponse(msg) if err != nil { @@ -140,6 +165,42 @@ func (c *gatewayConnector) SendToGateway(ctx context.Context, gatewayId string, return gateway.conn.Write(ctx, websocket.BinaryMessage, data) } +func (c *gatewayConnector) SignAndSendToGateway(ctx context.Context, gatewayID string, body *api.MessageBody) error { + signature, err := c.signer.Sign(api.GetRawMessageBody(body)...) + if err != nil { + return err + } + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: body.MessageId, + DonId: body.DonId, + Method: body.Method, + Payload: body.Payload, + Receiver: body.Receiver, + Sender: utils.StringToHex(string(c.nodeAddress)), + }, + Signature: utils.StringToHex(string(signature)), + } + + err = c.SendToGateway(ctx, gatewayID, msg) + if err != nil { + return fmt.Errorf("failed to send message to gateway %s: %v", gatewayID, err) + } + return nil +} + +func (c *gatewayConnector) GatewayIDs() []string { + var gids []string + for gid := range c.gateways { + gids = append(gids, gid) + } + return gids +} + +func (c *gatewayConnector) DonID() string { + return c.config.DonId +} + func (c *gatewayConnector) readLoop(gatewayState *gatewayState) { ctx, cancel := c.shutdownCh.NewCtx() defer cancel() @@ -159,7 +220,12 @@ func (c *gatewayConnector) readLoop(gatewayState *gatewayState) { c.lggr.Errorw("failed to validate message signature", "id", gatewayState.config.Id, "err", err) break } - c.handler.HandleGatewayMessage(ctx, gatewayState.config.Id, msg) + handler, exists := c.handlers[msg.Body.Method] + if !exists { + c.lggr.Errorw("no handler for method", "id", gatewayState.config.Id, "method", msg.Body.Method) + break + } + handler.HandleGatewayMessage(ctx, gatewayState.config.Id, msg) } } } @@ -194,9 +260,6 @@ func (c *gatewayConnector) reconnectLoop(gatewayState *gatewayState) { func (c *gatewayConnector) Start(ctx context.Context) error { return c.StartOnce("GatewayConnector", func() error { c.lggr.Info("starting gateway connector") - if err := c.handler.Start(ctx); err != nil { - return err - } for _, gatewayState := range c.gateways { gatewayState := gatewayState if err := gatewayState.conn.Start(ctx); err != nil { @@ -214,11 +277,12 @@ func (c *gatewayConnector) Close() error { return c.StopOnce("GatewayConnector", func() (err error) { c.lggr.Info("closing gateway connector") close(c.shutdownCh) + var errs error for _, gatewayState := range c.gateways { - gatewayState.conn.Close() + errs = errors.Join(errs, gatewayState.conn.Close()) } c.closeWait.Wait() - return c.handler.Close() + return errs }) } diff --git a/core/services/gateway/connector/connector_test.go b/core/services/gateway/connector/connector_test.go index 3dd782c626a..16520a42f41 100644 --- a/core/services/gateway/connector/connector_test.go +++ b/core/services/gateway/connector/connector_test.go @@ -18,7 +18,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" ) -const defaultConfig = ` +const ( + defaultConfig = ` NodeAddress = "0x68902d681c28119f9b2531473a417088bf008e59" DonId = "example_don" AuthMinChallengeLen = 10 @@ -32,6 +33,9 @@ URL = "ws://localhost:8081/node" Id = "another_one" URL = "wss://example.com:8090/node_endpoint" ` + testMethod1 = "test_method_1" + testMethod2 = "test_method_2" +) func parseTOMLConfig(t *testing.T, tomlConfig string) *connector.ConnectorConfig { var cfg connector.ConnectorConfig @@ -40,12 +44,13 @@ func parseTOMLConfig(t *testing.T, tomlConfig string) *connector.ConnectorConfig return &cfg } -func newTestConnector(t *testing.T, config *connector.ConnectorConfig, now time.Time) (connector.GatewayConnector, *mocks.Signer, *mocks.GatewayConnectorHandler) { +func newTestConnector(t *testing.T, config *connector.ConnectorConfig) (connector.GatewayConnector, *mocks.Signer, *mocks.GatewayConnectorHandler) { signer := mocks.NewSigner(t) handler := mocks.NewGatewayConnectorHandler(t) clock := clockwork.NewFakeClock() - connector, err := connector.NewGatewayConnector(config, signer, handler, clock, logger.TestLogger(t)) + connector, err := connector.NewGatewayConnector(config, signer, clock, logger.TestLogger(t)) require.NoError(t, err) + require.NoError(t, connector.AddHandler([]string{testMethod1}, handler)) return connector, signer, handler } @@ -61,7 +66,7 @@ Id = "example_gateway" URL = "ws://localhost:8081/node" `) - newTestConnector(t, tomlConfig, time.Now()) + newTestConnector(t, tomlConfig) } func TestGatewayConnector_NewGatewayConnector_InvalidConfig(t *testing.T) { @@ -103,12 +108,11 @@ URL = "ws://localhost:8081/node" } signer := mocks.NewSigner(t) - handler := mocks.NewGatewayConnectorHandler(t) clock := clockwork.NewFakeClock() for name, config := range invalidCases { config := config t.Run(name, func(t *testing.T) { - _, err := connector.NewGatewayConnector(parseTOMLConfig(t, config), signer, handler, clock, logger.TestLogger(t)) + _, err := connector.NewGatewayConnector(parseTOMLConfig(t, config), signer, clock, logger.TestLogger(t)) require.Error(t, err) }) } @@ -117,9 +121,7 @@ URL = "ws://localhost:8081/node" func TestGatewayConnector_CleanStartAndClose(t *testing.T) { t.Parallel() - connector, signer, handler := newTestConnector(t, parseTOMLConfig(t, defaultConfig), time.Now()) - handler.On("Start", mock.Anything).Return(nil) - handler.On("Close").Return(nil) + connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig)) signer.On("Sign", mock.Anything).Return(nil, errors.New("cannot sign")) servicetest.Run(t, connector) } @@ -127,7 +129,7 @@ func TestGatewayConnector_CleanStartAndClose(t *testing.T) { func TestGatewayConnector_NewAuthHeader_SignerError(t *testing.T) { t.Parallel() - connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig), time.Now()) + connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig)) signer.On("Sign", mock.Anything).Return(nil, errors.New("cannot sign")) url, err := url.Parse("ws://localhost:8081/node") @@ -141,7 +143,7 @@ func TestGatewayConnector_NewAuthHeader_Success(t *testing.T) { testSignature := make([]byte, network.HandshakeSignatureLen) testSignature[1] = 0xfa - connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig), time.Now()) + connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig)) signer.On("Sign", mock.Anything).Return(testSignature, nil) url, err := url.Parse("ws://localhost:8081/node") require.NoError(t, err) @@ -157,7 +159,7 @@ func TestGatewayConnector_ChallengeResponse(t *testing.T) { testSignature := make([]byte, network.HandshakeSignatureLen) testSignature[1] = 0xfa now := time.Now() - connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig), now) + connector, signer, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig)) signer.On("Sign", mock.Anything).Return(testSignature, nil) url, err := url.Parse("ws://localhost:8081/node") require.NoError(t, err) @@ -191,3 +193,12 @@ func TestGatewayConnector_ChallengeResponse(t *testing.T) { _, err = connector.ChallengeResponse(url, network.PackChallenge(&badChallenge)) require.Equal(t, network.ErrAuthInvalidGateway, err) } + +func TestGatewayConnector_AddHandler(t *testing.T) { + t.Parallel() + + connector, _, _ := newTestConnector(t, parseTOMLConfig(t, defaultConfig)) + // testMethod1 already exists + require.Error(t, connector.AddHandler([]string{testMethod1}, mocks.NewGatewayConnectorHandler(t))) + require.NoError(t, connector.AddHandler([]string{testMethod2}, mocks.NewGatewayConnectorHandler(t))) +} diff --git a/core/services/gateway/connector/mocks/gateway_connector.go b/core/services/gateway/connector/mocks/gateway_connector.go index 931aac8c772..9cb5632b313 100644 --- a/core/services/gateway/connector/mocks/gateway_connector.go +++ b/core/services/gateway/connector/mocks/gateway_connector.go @@ -4,6 +4,7 @@ package mocks import ( api "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + connector "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" context "context" @@ -25,6 +26,53 @@ func (_m *GatewayConnector) EXPECT() *GatewayConnector_Expecter { return &GatewayConnector_Expecter{mock: &_m.Mock} } +// AddHandler provides a mock function with given fields: methods, handler +func (_m *GatewayConnector) AddHandler(methods []string, handler connector.GatewayConnectorHandler) error { + ret := _m.Called(methods, handler) + + if len(ret) == 0 { + panic("no return value specified for AddHandler") + } + + var r0 error + if rf, ok := ret.Get(0).(func([]string, connector.GatewayConnectorHandler) error); ok { + r0 = rf(methods, handler) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GatewayConnector_AddHandler_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddHandler' +type GatewayConnector_AddHandler_Call struct { + *mock.Call +} + +// AddHandler is a helper method to define mock.On call +// - methods []string +// - handler connector.GatewayConnectorHandler +func (_e *GatewayConnector_Expecter) AddHandler(methods interface{}, handler interface{}) *GatewayConnector_AddHandler_Call { + return &GatewayConnector_AddHandler_Call{Call: _e.mock.On("AddHandler", methods, handler)} +} + +func (_c *GatewayConnector_AddHandler_Call) Run(run func(methods []string, handler connector.GatewayConnectorHandler)) *GatewayConnector_AddHandler_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]string), args[1].(connector.GatewayConnectorHandler)) + }) + return _c +} + +func (_c *GatewayConnector_AddHandler_Call) Return(_a0 error) *GatewayConnector_AddHandler_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_AddHandler_Call) RunAndReturn(run func([]string, connector.GatewayConnectorHandler) error) *GatewayConnector_AddHandler_Call { + _c.Call.Return(run) + return _c +} + // ChallengeResponse provides a mock function with given fields: _a0, challenge func (_m *GatewayConnector) ChallengeResponse(_a0 *url.URL, challenge []byte) ([]byte, error) { ret := _m.Called(_a0, challenge) @@ -129,6 +177,98 @@ func (_c *GatewayConnector_Close_Call) RunAndReturn(run func() error) *GatewayCo return _c } +// DonID provides a mock function with given fields: +func (_m *GatewayConnector) DonID() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for DonID") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GatewayConnector_DonID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DonID' +type GatewayConnector_DonID_Call struct { + *mock.Call +} + +// DonID is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) DonID() *GatewayConnector_DonID_Call { + return &GatewayConnector_DonID_Call{Call: _e.mock.On("DonID")} +} + +func (_c *GatewayConnector_DonID_Call) Run(run func()) *GatewayConnector_DonID_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_DonID_Call) Return(_a0 string) *GatewayConnector_DonID_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_DonID_Call) RunAndReturn(run func() string) *GatewayConnector_DonID_Call { + _c.Call.Return(run) + return _c +} + +// GatewayIDs provides a mock function with given fields: +func (_m *GatewayConnector) GatewayIDs() []string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GatewayIDs") + } + + var r0 []string + if rf, ok := ret.Get(0).(func() []string); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + return r0 +} + +// GatewayConnector_GatewayIDs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GatewayIDs' +type GatewayConnector_GatewayIDs_Call struct { + *mock.Call +} + +// GatewayIDs is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) GatewayIDs() *GatewayConnector_GatewayIDs_Call { + return &GatewayConnector_GatewayIDs_Call{Call: _e.mock.On("GatewayIDs")} +} + +func (_c *GatewayConnector_GatewayIDs_Call) Run(run func()) *GatewayConnector_GatewayIDs_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_GatewayIDs_Call) Return(_a0 []string) *GatewayConnector_GatewayIDs_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_GatewayIDs_Call) RunAndReturn(run func() []string) *GatewayConnector_GatewayIDs_Call { + _c.Call.Return(run) + return _c +} + // NewAuthHeader provides a mock function with given fields: _a0 func (_m *GatewayConnector) NewAuthHeader(_a0 *url.URL) ([]byte, error) { ret := _m.Called(_a0) @@ -235,6 +375,54 @@ func (_c *GatewayConnector_SendToGateway_Call) RunAndReturn(run func(context.Con return _c } +// SignAndSendToGateway provides a mock function with given fields: ctx, gatewayID, msg +func (_m *GatewayConnector) SignAndSendToGateway(ctx context.Context, gatewayID string, msg *api.MessageBody) error { + ret := _m.Called(ctx, gatewayID, msg) + + if len(ret) == 0 { + panic("no return value specified for SignAndSendToGateway") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, *api.MessageBody) error); ok { + r0 = rf(ctx, gatewayID, msg) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GatewayConnector_SignAndSendToGateway_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SignAndSendToGateway' +type GatewayConnector_SignAndSendToGateway_Call struct { + *mock.Call +} + +// SignAndSendToGateway is a helper method to define mock.On call +// - ctx context.Context +// - gatewayID string +// - msg *api.MessageBody +func (_e *GatewayConnector_Expecter) SignAndSendToGateway(ctx interface{}, gatewayID interface{}, msg interface{}) *GatewayConnector_SignAndSendToGateway_Call { + return &GatewayConnector_SignAndSendToGateway_Call{Call: _e.mock.On("SignAndSendToGateway", ctx, gatewayID, msg)} +} + +func (_c *GatewayConnector_SignAndSendToGateway_Call) Run(run func(ctx context.Context, gatewayID string, msg *api.MessageBody)) *GatewayConnector_SignAndSendToGateway_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(*api.MessageBody)) + }) + return _c +} + +func (_c *GatewayConnector_SignAndSendToGateway_Call) Return(_a0 error) *GatewayConnector_SignAndSendToGateway_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_SignAndSendToGateway_Call) RunAndReturn(run func(context.Context, string, *api.MessageBody) error) *GatewayConnector_SignAndSendToGateway_Call { + _c.Call.Return(run) + return _c +} + // Start provides a mock function with given fields: _a0 func (_m *GatewayConnector) Start(_a0 context.Context) error { ret := _m.Called(_a0) diff --git a/core/services/gateway/delegate.go b/core/services/gateway/delegate.go index 5a30228db4c..ba059b15a35 100644 --- a/core/services/gateway/delegate.go +++ b/core/services/gateway/delegate.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" ) @@ -54,7 +55,11 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services if err2 != nil { return nil, errors.Wrap(err2, "unmarshal gateway config") } - handlerFactory := NewHandlerFactory(d.legacyChains, d.ds, d.lggr) + httpClient, err := network.NewHTTPClient(gatewayConfig.HTTPClientConfig, d.lggr) + if err != nil { + return nil, err + } + handlerFactory := NewHandlerFactory(d.legacyChains, d.ds, httpClient, d.lggr) gateway, err := NewGatewayFromConfig(&gatewayConfig, handlerFactory, d.lggr) if err != nil { return nil, err diff --git a/core/services/gateway/gateway_test.go b/core/services/gateway/gateway_test.go index 3218c5428a2..7a5457c788c 100644 --- a/core/services/gateway/gateway_test.go +++ b/core/services/gateway/gateway_test.go @@ -57,7 +57,7 @@ Address = "0x0001020304050607080900010203040506070809" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.NoError(t, err) } @@ -75,7 +75,7 @@ HandlerName = "dummy" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.Error(t, err) } @@ -89,7 +89,7 @@ HandlerName = "no_such_handler" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.Error(t, err) } @@ -103,7 +103,7 @@ SomeOtherField = "abcd" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.Error(t, err) } @@ -121,7 +121,7 @@ Address = "0xnot_an_address" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.Error(t, err) } @@ -129,7 +129,7 @@ func TestGateway_CleanStartAndClose(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) - gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) } diff --git a/core/services/gateway/handler_factory.go b/core/services/gateway/handler_factory.go index ca6b98e55aa..4d58b95fbca 100644 --- a/core/services/gateway/handler_factory.go +++ b/core/services/gateway/handler_factory.go @@ -9,24 +9,33 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" ) const ( - FunctionsHandlerType HandlerType = "functions" - DummyHandlerType HandlerType = "dummy" + FunctionsHandlerType HandlerType = "functions" + DummyHandlerType HandlerType = "dummy" + WebAPICapabilitiesType HandlerType = "web-api-capabilities" ) type handlerFactory struct { legacyChains legacyevm.LegacyChainContainer ds sqlutil.DataSource lggr logger.Logger + httpClient network.HTTPClient } var _ HandlerFactory = (*handlerFactory)(nil) -func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, ds sqlutil.DataSource, lggr logger.Logger) HandlerFactory { - return &handlerFactory{legacyChains, ds, lggr} +func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, ds sqlutil.DataSource, httpClient network.HTTPClient, lggr logger.Logger) HandlerFactory { + return &handlerFactory{ + legacyChains, + ds, + lggr, + httpClient, + } } func (hf *handlerFactory) NewHandler(handlerType HandlerType, handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON) (handlers.Handler, error) { @@ -35,6 +44,8 @@ func (hf *handlerFactory) NewHandler(handlerType HandlerType, handlerConfig json return functions.NewFunctionsHandlerFromConfig(handlerConfig, donConfig, don, hf.legacyChains, hf.ds, hf.lggr) case DummyHandlerType: return handlers.NewDummyHandler(donConfig, don, hf.lggr) + case WebAPICapabilitiesType: + return capabilities.NewHandler(handlerConfig, donConfig, don, hf.httpClient, hf.lggr) default: return nil, fmt.Errorf("unsupported handler type %s", handlerType) } diff --git a/core/services/gateway/handlers/capabilities/handler.go b/core/services/gateway/handlers/capabilities/handler.go new file mode 100644 index 00000000000..904a64c8896 --- /dev/null +++ b/core/services/gateway/handlers/capabilities/handler.go @@ -0,0 +1,245 @@ +package capabilities + +import ( + "context" + "encoding/json" + "fmt" + "sync" + "time" + + "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/webapicap" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" +) + +const ( + // NOTE: more methods will go here. HTTP trigger/action/target; etc. + MethodWebAPITarget = "web_api_target" + MethodWebAPITrigger = "web_api_trigger" + MethodComputeAction = "compute_action" +) + +type handler struct { + config HandlerConfig + don handlers.DON + donConfig *config.DONConfig + savedCallbacks map[string]*savedCallback + mu sync.Mutex + lggr logger.Logger + httpClient network.HTTPClient + nodeRateLimiter *common.RateLimiter + wg sync.WaitGroup +} + +type HandlerConfig struct { + NodeRateLimiter common.RateLimiterConfig `json:"nodeRateLimiter"` + MaxAllowedMessageAgeSec uint `json:"maxAllowedMessageAgeSec"` +} + +type savedCallback struct { + id string + callbackCh chan<- handlers.UserCallbackPayload +} + +var _ handlers.Handler = (*handler)(nil) + +func NewHandler(handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON, httpClient network.HTTPClient, lggr logger.Logger) (*handler, error) { + var cfg HandlerConfig + err := json.Unmarshal(handlerConfig, &cfg) + if err != nil { + return nil, err + } + nodeRateLimiter, err := common.NewRateLimiter(cfg.NodeRateLimiter) + if err != nil { + return nil, err + } + + return &handler{ + config: cfg, + don: don, + donConfig: donConfig, + lggr: lggr.Named("WebAPIHandler." + donConfig.DonId), + httpClient: httpClient, + nodeRateLimiter: nodeRateLimiter, + wg: sync.WaitGroup{}, + savedCallbacks: make(map[string]*savedCallback), + }, nil +} + +// sendHTTPMessageToClient is an outgoing message from the gateway to external endpoints +// returns message to be sent back to the capability node +func (h *handler) sendHTTPMessageToClient(ctx context.Context, req network.HTTPRequest, msg *api.Message) (*api.Message, error) { + var payload Response + resp, err := h.httpClient.Send(ctx, req) + if err != nil { + return nil, err + } + payload = Response{ + ExecutionError: false, + StatusCode: resp.StatusCode, + Headers: resp.Headers, + Body: resp.Body, + } + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, err + } + + return &api.Message{ + Body: api.MessageBody{ + MessageId: msg.Body.MessageId, + Method: msg.Body.Method, + DonId: msg.Body.DonId, + Payload: payloadBytes, + }, + }, nil +} + +func (h *handler) handleWebAPITriggerMessage(ctx context.Context, msg *api.Message, nodeAddr string) error { + h.mu.Lock() + savedCb, found := h.savedCallbacks[msg.Body.MessageId] + delete(h.savedCallbacks, msg.Body.MessageId) + h.mu.Unlock() + + if found { + // Send first response from a node back to the user, ignore any other ones. + // TODO: in practice, we should wait for at least 2F+1 nodes to respond and then return an aggregated response + // back to the user. + savedCb.callbackCh <- handlers.UserCallbackPayload{Msg: msg, ErrCode: api.NoError, ErrMsg: ""} + close(savedCb.callbackCh) + } + return nil +} + +func (h *handler) handleWebAPIOutgoingMessage(ctx context.Context, msg *api.Message, nodeAddr string) error { + h.lggr.Debugw("handling webAPI outgoing message", "messageId", msg.Body.MessageId, "nodeAddr", nodeAddr) + if !h.nodeRateLimiter.Allow(nodeAddr) { + return fmt.Errorf("rate limit exceeded for node %s", nodeAddr) + } + var payload Request + err := json.Unmarshal(msg.Body.Payload, &payload) + if err != nil { + return err + } + + timeout := time.Duration(payload.TimeoutMs) * time.Millisecond + req := network.HTTPRequest{ + Method: payload.Method, + URL: payload.URL, + Headers: payload.Headers, + Body: payload.Body, + Timeout: timeout, + } + + // send response to node async + h.wg.Add(1) + go func() { + defer h.wg.Done() + // not cancelled when parent is cancelled to ensure the goroutine can finish + newCtx := context.WithoutCancel(ctx) + newCtx, cancel := context.WithTimeout(newCtx, timeout) + defer cancel() + l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method) + respMsg, err := h.sendHTTPMessageToClient(newCtx, req, msg) + if err != nil { + l.Errorw("error while sending HTTP request to external endpoint", "err", err) + payload := Response{ + ExecutionError: true, + ErrorMessage: err.Error(), + } + payloadBytes, err2 := json.Marshal(payload) + if err2 != nil { + // should not happen + l.Errorw("error while marshalling payload", "err", err2) + return + } + respMsg = &api.Message{ + Body: api.MessageBody{ + MessageId: msg.Body.MessageId, + Method: msg.Body.Method, + DonId: msg.Body.DonId, + Payload: payloadBytes, + }, + } + } + // this signature is not verified by the node because + // WS connection between gateway and node are already verified + respMsg.Signature = msg.Signature + + err = h.don.SendToNode(newCtx, nodeAddr, respMsg) + if err != nil { + l.Errorw("failed to send to node", "err", err, "to", nodeAddr) + return + } + l.Debugw("sent response to node", "to", nodeAddr) + }() + return nil +} + +func (h *handler) HandleNodeMessage(ctx context.Context, msg *api.Message, nodeAddr string) error { + switch msg.Body.Method { + case MethodWebAPITrigger: + return h.handleWebAPITriggerMessage(ctx, msg, nodeAddr) + case MethodWebAPITarget, MethodComputeAction: + return h.handleWebAPIOutgoingMessage(ctx, msg, nodeAddr) + default: + return fmt.Errorf("unsupported method: %s", msg.Body.Method) + } +} + +func (h *handler) Start(context.Context) error { + return nil +} + +func (h *handler) Close() error { + h.wg.Wait() + return nil +} + +func (h *handler) HandleUserMessage(ctx context.Context, msg *api.Message, callbackCh chan<- handlers.UserCallbackPayload) error { + h.mu.Lock() + h.savedCallbacks[msg.Body.MessageId] = &savedCallback{msg.Body.MessageId, callbackCh} + don := h.don + h.mu.Unlock() + body := msg.Body + var payload webapicap.TriggerRequestPayload + err := json.Unmarshal(body.Payload, &payload) + if err != nil { + h.lggr.Errorw("error decoding payload", "err", err) + callbackCh <- handlers.UserCallbackPayload{Msg: msg, ErrCode: api.UserMessageParseError, ErrMsg: fmt.Sprintf("error decoding payload %s", err.Error())} + close(callbackCh) + return nil + } + + if payload.Timestamp == 0 { + h.lggr.Errorw("error decoding payload") + callbackCh <- handlers.UserCallbackPayload{Msg: msg, ErrCode: api.UserMessageParseError, ErrMsg: "error decoding payload"} + close(callbackCh) + return nil + } + + if uint(time.Now().Unix())-h.config.MaxAllowedMessageAgeSec > uint(payload.Timestamp) { + callbackCh <- handlers.UserCallbackPayload{Msg: msg, ErrCode: api.HandlerError, ErrMsg: "stale message"} + close(callbackCh) + return nil + } + // TODO: apply allowlist and rate-limiting here + if msg.Body.Method != MethodWebAPITrigger { + h.lggr.Errorw("unsupported method", "method", body.Method) + callbackCh <- handlers.UserCallbackPayload{Msg: msg, ErrCode: api.HandlerError, ErrMsg: fmt.Sprintf("invalid method %s", msg.Body.Method)} + close(callbackCh) + return nil + } + + // Send to all nodes. + for _, member := range h.donConfig.Members { + err = multierr.Combine(err, don.SendToNode(ctx, member.Address, msg)) + } + return err +} diff --git a/core/services/gateway/handlers/capabilities/handler_test.go b/core/services/gateway/handlers/capabilities/handler_test.go new file mode 100644 index 00000000000..eb5d883ac14 --- /dev/null +++ b/core/services/gateway/handlers/capabilities/handler_test.go @@ -0,0 +1,429 @@ +package capabilities + +import ( + "encoding/json" + "errors" + "fmt" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/ethereum/go-ethereum/crypto" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + gwcommon "github.com/smartcontractkit/chainlink/v2/core/services/gateway/common" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" + handlermocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network/mocks" +) + +const ( + defaultSendChannelBufferSize = 1000 + privateKey1 = "65456ffb8af4a2b93959256a8e04f6f2fe0943579fb3c9c3350593aabb89023f" + privateKey2 = "65456ffb8af4a2b93959256a8e04f6f2fe0943579fb3c9c3350593aabb89023e" + triggerID1 = "5" + triggerID2 = "6" + workflowID1 = "15c631d295ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0" + workflowExecutionID1 = "95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0abbadeed" + owner1 = "0x00000000000000000000000000000000000000aa" + address1 = "0x853d51d5d9935964267a5050aC53aa63ECA39bc5" +) + +func setupHandler(t *testing.T) (*handler, *mocks.HTTPClient, *handlermocks.DON, []gwcommon.TestNode) { + lggr := logger.TestLogger(t) + httpClient := mocks.NewHTTPClient(t) + don := handlermocks.NewDON(t) + nodeRateLimiterConfig := common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + } + handlerConfig := HandlerConfig{ + NodeRateLimiter: nodeRateLimiterConfig, + MaxAllowedMessageAgeSec: 30, + } + + cfgBytes, err := json.Marshal(handlerConfig) + require.NoError(t, err) + donConfig := &config.DONConfig{ + Members: []config.NodeConfig{}, + F: 1, + } + nodes := gwcommon.NewTestNodes(t, 2) + for id, n := range nodes { + donConfig.Members = append(donConfig.Members, config.NodeConfig{ + Name: fmt.Sprintf("node_%d", id), + Address: n.Address, + }) + } + handler, err := NewHandler(json.RawMessage(cfgBytes), donConfig, don, httpClient, lggr) + require.NoError(t, err) + return handler, httpClient, don, nodes +} + +func TestHandler_SendHTTPMessageToClient(t *testing.T) { + handler, httpClient, don, nodes := setupHandler(t) + ctx := testutils.Context(t) + nodeAddr := nodes[0].Address + payload := Request{ + Method: "GET", + URL: "http://example.com", + Headers: map[string]string{}, + Body: nil, + TimeoutMs: 2000, + } + payloadBytes, err := json.Marshal(payload) + require.NoError(t, err) + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: "123", + Method: MethodWebAPITarget, + DonId: "testDonId", + Payload: json.RawMessage(payloadBytes), + }, + } + + t.Run("happy case", func(t *testing.T) { + httpClient.EXPECT().Send(mock.Anything, mock.Anything).Return(&network.HTTPResponse{ + StatusCode: 200, + Headers: map[string]string{}, + Body: []byte("response body"), + }, nil).Once() + + don.EXPECT().SendToNode(mock.Anything, nodes[0].Address, mock.MatchedBy(func(m *api.Message) bool { + var payload Response + err2 := json.Unmarshal(m.Body.Payload, &payload) + if err2 != nil { + return false + } + return "123" == m.Body.MessageId && + MethodWebAPITarget == m.Body.Method && + "testDonId" == m.Body.DonId && + 200 == payload.StatusCode && + 0 == len(payload.Headers) && + string(payload.Body) == "response body" && + !payload.ExecutionError + })).Return(nil).Once() + + err = handler.HandleNodeMessage(ctx, msg, nodeAddr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + // ensure all goroutines close + err2 := handler.Close() + require.NoError(t, err2) + return httpClient.AssertExpectations(t) && don.AssertExpectations(t) + }, tests.WaitTimeout(t), 100*time.Millisecond) + }) + + t.Run("http client non-HTTP error", func(t *testing.T) { + httpClient.EXPECT().Send(mock.Anything, mock.Anything).Return(&network.HTTPResponse{ + StatusCode: 404, + Headers: map[string]string{}, + Body: []byte("access denied"), + }, nil).Once() + + don.EXPECT().SendToNode(mock.Anything, nodes[0].Address, mock.MatchedBy(func(m *api.Message) bool { + var payload Response + err2 := json.Unmarshal(m.Body.Payload, &payload) + if err2 != nil { + return false + } + return "123" == m.Body.MessageId && + MethodWebAPITarget == m.Body.Method && + "testDonId" == m.Body.DonId && + 404 == payload.StatusCode && + string(payload.Body) == "access denied" && + 0 == len(payload.Headers) && + !payload.ExecutionError + })).Return(nil).Once() + + err = handler.HandleNodeMessage(ctx, msg, nodeAddr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + // // ensure all goroutines close + err2 := handler.Close() + require.NoError(t, err2) + return httpClient.AssertExpectations(t) && don.AssertExpectations(t) + }, tests.WaitTimeout(t), 100*time.Millisecond) + }) + + t.Run("http client non-HTTP error", func(t *testing.T) { + httpClient.EXPECT().Send(mock.Anything, mock.Anything).Return(nil, fmt.Errorf("error while marshalling")).Once() + + don.EXPECT().SendToNode(mock.Anything, nodes[0].Address, mock.MatchedBy(func(m *api.Message) bool { + var payload Response + err2 := json.Unmarshal(m.Body.Payload, &payload) + if err2 != nil { + return false + } + return "123" == m.Body.MessageId && + MethodWebAPITarget == m.Body.Method && + "testDonId" == m.Body.DonId && + payload.ExecutionError && + "error while marshalling" == payload.ErrorMessage + })).Return(nil).Once() + + err = handler.HandleNodeMessage(ctx, msg, nodeAddr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + // // ensure all goroutines close + err2 := handler.Close() + require.NoError(t, err2) + return httpClient.AssertExpectations(t) && don.AssertExpectations(t) + }, tests.WaitTimeout(t), 100*time.Millisecond) + }) +} + +func triggerRequest(t *testing.T, privateKey string, topics string, methodName string, timestamp string, payload string) *api.Message { + messageID := "12345" + if methodName == "" { + methodName = MethodWebAPITrigger + } + if timestamp == "" { + timestamp = strconv.FormatInt(time.Now().Unix(), 10) + } + donID := "workflow_don_1" + + key, err := crypto.HexToECDSA(privateKey) + require.NoError(t, err) + if payload == "" { + payload = `{ + "trigger_id": "web-api-trigger@1.0.0", + "trigger_event_id": "action_1234567890", + "timestamp": ` + timestamp + `, + "topics": ` + topics + `, + "params": { + "bid": "101", + "ask": "102" + } + } + ` + } + payloadJSON := []byte(payload) + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: messageID, + Method: methodName, + DonId: donID, + Payload: json.RawMessage(payloadJSON), + }, + } + err = msg.Sign(key) + require.NoError(t, err) + return msg +} + +func requireNoChanMsg[T any](t *testing.T, ch <-chan T) { + timedOut := false + select { + case <-ch: + case <-time.After(100 * time.Millisecond): + timedOut = true + } + require.True(t, timedOut) +} + +func TestHandlerReceiveHTTPMessageFromClient(t *testing.T) { + handler, _, don, _ := setupHandler(t) + ctx := testutils.Context(t) + msg := triggerRequest(t, privateKey1, `["daily_price_update"]`, "", "", "") + + t.Run("happy case", func(t *testing.T) { + ch := make(chan handlers.UserCallbackPayload, defaultSendChannelBufferSize) + + // sends to 2 dons + don.On("SendToNode", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + require.Equal(t, msg, args.Get(2)) + }).Return(nil).Once() + don.On("SendToNode", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + require.Equal(t, msg, args.Get(2)) + }).Return(nil).Once() + + err := handler.HandleUserMessage(ctx, msg, ch) + require.NoError(t, err) + requireNoChanMsg(t, ch) + + err = handler.HandleNodeMessage(ctx, msg, "") + require.NoError(t, err) + + resp := <-ch + require.Equal(t, handlers.UserCallbackPayload{Msg: msg, ErrCode: api.NoError, ErrMsg: ""}, resp) + _, open := <-ch + require.Equal(t, open, false) + }) + + t.Run("sad case invalid method", func(t *testing.T) { + invalidMsg := triggerRequest(t, privateKey1, `["daily_price_update"]`, "foo", "", "") + ch := make(chan handlers.UserCallbackPayload, defaultSendChannelBufferSize) + err := handler.HandleUserMessage(ctx, invalidMsg, ch) + require.NoError(t, err) + resp := <-ch + require.Equal(t, handlers.UserCallbackPayload{Msg: invalidMsg, ErrCode: api.HandlerError, ErrMsg: "invalid method foo"}, resp) + _, open := <-ch + require.Equal(t, open, false) + }) + + t.Run("sad case stale message", func(t *testing.T) { + invalidMsg := triggerRequest(t, privateKey1, `["daily_price_update"]`, "", "123456", "") + ch := make(chan handlers.UserCallbackPayload, defaultSendChannelBufferSize) + err := handler.HandleUserMessage(ctx, invalidMsg, ch) + require.NoError(t, err) + resp := <-ch + require.Equal(t, handlers.UserCallbackPayload{Msg: invalidMsg, ErrCode: api.HandlerError, ErrMsg: "stale message"}, resp) + _, open := <-ch + require.Equal(t, open, false) + }) + + t.Run("sad case empty payload", func(t *testing.T) { + invalidMsg := triggerRequest(t, privateKey1, `["daily_price_update"]`, "", "123456", "{}") + ch := make(chan handlers.UserCallbackPayload, defaultSendChannelBufferSize) + err := handler.HandleUserMessage(ctx, invalidMsg, ch) + require.NoError(t, err) + resp := <-ch + require.Equal(t, handlers.UserCallbackPayload{Msg: invalidMsg, ErrCode: api.UserMessageParseError, ErrMsg: "error decoding payload field params in TriggerRequestPayload: required"}, resp) + _, open := <-ch + require.Equal(t, open, false) + }) + + t.Run("sad case invalid payload", func(t *testing.T) { + invalidMsg := triggerRequest(t, privateKey1, `["daily_price_update"]`, "", "123456", `{"foo":"bar"}`) + ch := make(chan handlers.UserCallbackPayload, defaultSendChannelBufferSize) + err := handler.HandleUserMessage(ctx, invalidMsg, ch) + require.NoError(t, err) + resp := <-ch + require.Equal(t, handlers.UserCallbackPayload{Msg: invalidMsg, ErrCode: api.UserMessageParseError, ErrMsg: "error decoding payload field params in TriggerRequestPayload: required"}, resp) + _, open := <-ch + require.Equal(t, open, false) + }) + // TODO: Validate Senders and rate limit chck, pending question in trigger about where senders and rate limits are validated +} + +func TestHandleComputeActionMessage(t *testing.T) { + handler, httpClient, don, nodes := setupHandler(t) + ctx := testutils.Context(t) + nodeAddr := nodes[0].Address + payload := Request{ + Method: "GET", + URL: "http://example.com", + Headers: map[string]string{}, + Body: nil, + TimeoutMs: 2000, + } + payloadBytes, err := json.Marshal(payload) + require.NoError(t, err) + msg := &api.Message{ + Body: api.MessageBody{ + MessageId: "123", + Method: MethodComputeAction, + DonId: "testDonId", + Payload: json.RawMessage(payloadBytes), + }, + } + + t.Run("OK-compute_with_fetch", func(t *testing.T) { + httpClient.EXPECT().Send(mock.Anything, mock.Anything).Return(&network.HTTPResponse{ + StatusCode: 200, + Headers: map[string]string{}, + Body: []byte("response body"), + }, nil).Once() + + don.EXPECT().SendToNode(mock.Anything, nodes[0].Address, mock.MatchedBy(func(m *api.Message) bool { + var payload Response + err2 := json.Unmarshal(m.Body.Payload, &payload) + if err2 != nil { + return false + } + return "123" == m.Body.MessageId && + MethodComputeAction == m.Body.Method && + "testDonId" == m.Body.DonId && + 200 == payload.StatusCode && + 0 == len(payload.Headers) && + string(payload.Body) == "response body" && + !payload.ExecutionError + })).Return(nil).Once() + + err = handler.HandleNodeMessage(ctx, msg, nodeAddr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + // ensure all goroutines close + err2 := handler.Close() + require.NoError(t, err2) + return httpClient.AssertExpectations(t) && don.AssertExpectations(t) + }, tests.WaitTimeout(t), 100*time.Millisecond) + }) + + t.Run("NOK-payload_error_making_external_request", func(t *testing.T) { + httpClient.EXPECT().Send(mock.Anything, mock.Anything).Return(&network.HTTPResponse{ + StatusCode: 404, + Headers: map[string]string{}, + Body: []byte("access denied"), + }, nil).Once() + + don.EXPECT().SendToNode(mock.Anything, nodes[0].Address, mock.MatchedBy(func(m *api.Message) bool { + var payload Response + err2 := json.Unmarshal(m.Body.Payload, &payload) + if err2 != nil { + return false + } + return "123" == m.Body.MessageId && + MethodComputeAction == m.Body.Method && + "testDonId" == m.Body.DonId && + 404 == payload.StatusCode && + string(payload.Body) == "access denied" && + 0 == len(payload.Headers) && + !payload.ExecutionError + })).Return(nil).Once() + + err = handler.HandleNodeMessage(ctx, msg, nodeAddr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + // // ensure all goroutines close + err2 := handler.Close() + require.NoError(t, err2) + return httpClient.AssertExpectations(t) && don.AssertExpectations(t) + }, tests.WaitTimeout(t), 100*time.Millisecond) + }) + + t.Run("NOK-error_outside_payload", func(t *testing.T) { + httpClient.EXPECT().Send(mock.Anything, mock.Anything).Return(nil, errors.New("error while marshalling")).Once() + + don.EXPECT().SendToNode(mock.Anything, nodes[0].Address, mock.MatchedBy(func(m *api.Message) bool { + var payload Response + err2 := json.Unmarshal(m.Body.Payload, &payload) + if err2 != nil { + return false + } + return "123" == m.Body.MessageId && + MethodComputeAction == m.Body.Method && + "testDonId" == m.Body.DonId && + payload.ExecutionError && + "error while marshalling" == payload.ErrorMessage + })).Return(nil).Once() + + err = handler.HandleNodeMessage(ctx, msg, nodeAddr) + require.NoError(t, err) + + require.Eventually(t, func() bool { + // // ensure all goroutines close + err2 := handler.Close() + require.NoError(t, err2) + return httpClient.AssertExpectations(t) && don.AssertExpectations(t) + }, tests.WaitTimeout(t), 100*time.Millisecond) + }) +} diff --git a/core/services/gateway/handlers/capabilities/webapi.go b/core/services/gateway/handlers/capabilities/webapi.go new file mode 100644 index 00000000000..a0213eb8f42 --- /dev/null +++ b/core/services/gateway/handlers/capabilities/webapi.go @@ -0,0 +1,23 @@ +package capabilities + +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. + Headers map[string]string `json:"headers,omitempty"` // HTTP headers, defaults to empty. + Body []byte `json:"body,omitempty"` // HTTP request body + TimeoutMs uint32 `json:"timeoutMs,omitempty"` // Timeout in milliseconds +} + +type Response struct { + ExecutionError bool `json:"executionError"` // true if there were non-HTTP errors. false if HTTP request was sent regardless of status (2xx, 4xx, 5xx) + ErrorMessage string `json:"errorMessage,omitempty"` // error message in case of failure + StatusCode int `json:"statusCode,omitempty"` // HTTP status code + Headers map[string]string `json:"headers,omitempty"` // HTTP headers + Body []byte `json:"body,omitempty"` // HTTP response body +} + +type TriggerResponsePayload struct { + ErrorMessage string `json:"error_message,omitempty"` + // ERROR, ACCEPTED, PENDING, COMPLETED + Status string `json:"status"` +} diff --git a/core/services/gateway/handlers/functions/allowlist/allowlist_test.go b/core/services/gateway/handlers/functions/allowlist/allowlist_test.go index 500985acc31..b8735bbf8af 100644 --- a/core/services/gateway/handlers/functions/allowlist/allowlist_test.go +++ b/core/services/gateway/handlers/functions/allowlist/allowlist_test.go @@ -21,7 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/allowlist" amocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/allowlist/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -376,7 +376,7 @@ func encodeTypeAndVersionResponse(typeAndVersion string) ([]byte, error) { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ codecName: {TypeABI: evmEncoderConfig}, }} - encoder, err := evm.NewCodec(codecConfig) + encoder, err := codec.NewCodec(codecConfig) if err != nil { return nil, err } diff --git a/core/services/gateway/handlers/handler.go b/core/services/gateway/handlers/handler.go index 6994488707f..b9fe4234d25 100644 --- a/core/services/gateway/handlers/handler.go +++ b/core/services/gateway/handlers/handler.go @@ -31,7 +31,8 @@ type Handler interface { // 2. waits on callbackCh with a timeout HandleUserMessage(ctx context.Context, msg *api.Message, callbackCh chan<- UserCallbackPayload) error - // Handlers should not make any assumptions about goroutines calling HandleNodeMessage + // Handlers should not make any assumptions about goroutines calling HandleNodeMessage. + // should be non-blocking HandleNodeMessage(ctx context.Context, msg *api.Message, nodeAddr string) error } diff --git a/core/services/gateway/integration_tests/gateway_integration_test.go b/core/services/gateway/integration_tests/gateway_integration_test.go index 38a6b6ebbca..0ddf47bec04 100644 --- a/core/services/gateway/integration_tests/gateway_integration_test.go +++ b/core/services/gateway/integration_tests/gateway_integration_test.go @@ -10,6 +10,7 @@ import ( "strings" "sync/atomic" "testing" + "time" "github.com/jonboulle/clockwork" "github.com/onsi/gomega" @@ -24,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/gateway/common" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" ) const gatewayConfigTemplate = ` @@ -143,7 +145,12 @@ func TestIntegration_Gateway_NoFullNodes_BasicConnectionAndMessage(t *testing.T) // Launch Gateway lggr := logger.TestLogger(t) gatewayConfig := fmt.Sprintf(gatewayConfigTemplate, nodeKeys.Address) - gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) + c, err := network.NewHTTPClient(network.HTTPClientConfig{ + DefaultTimeout: 5 * time.Second, + MaxResponseBytes: 1000, + }, lggr) + require.NoError(t, err) + gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, c, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) userPort, nodePort := gateway.GetUserPort(), gateway.GetNodePort() @@ -152,8 +159,10 @@ func TestIntegration_Gateway_NoFullNodes_BasicConnectionAndMessage(t *testing.T) // Launch Connector client := &client{privateKey: nodeKeys.PrivateKey} - connector, err := connector.NewGatewayConnector(parseConnectorConfig(t, nodeConfigTemplate, nodeKeys.Address, nodeUrl), client, client, clockwork.NewRealClock(), lggr) + // client acts as a signer here + connector, err := connector.NewGatewayConnector(parseConnectorConfig(t, nodeConfigTemplate, nodeKeys.Address, nodeUrl), client, clockwork.NewRealClock(), lggr) require.NoError(t, err) + require.NoError(t, connector.AddHandler([]string{"test"}, client)) client.connector = connector servicetest.Run(t, connector) diff --git a/core/services/gateway/network/httpclient.go b/core/services/gateway/network/httpclient.go new file mode 100644 index 00000000000..4aecaaed3cd --- /dev/null +++ b/core/services/gateway/network/httpclient.go @@ -0,0 +1,88 @@ +package network + +import ( + "bytes" + "context" + "io" + "net/http" + "strings" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +// HTTPClient interfaces defines a method to send HTTP requests +type HTTPClient interface { + Send(ctx context.Context, req HTTPRequest) (*HTTPResponse, error) +} + +type HTTPClientConfig struct { + MaxResponseBytes uint32 + DefaultTimeout time.Duration +} + +type HTTPRequest struct { + Method string + URL string + Headers map[string]string + Body []byte + Timeout time.Duration +} +type HTTPResponse struct { + StatusCode int // HTTP status code + Headers map[string]string // HTTP headers + Body []byte // HTTP response body +} + +type httpClient struct { + client *http.Client + config HTTPClientConfig + lggr logger.Logger +} + +// 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) { + return &httpClient{ + config: config, + client: &http.Client{ + Timeout: config.DefaultTimeout, + Transport: http.DefaultTransport, + }, + lggr: lggr, + }, nil +} + +func (c *httpClient) Send(ctx context.Context, req HTTPRequest) (*HTTPResponse, error) { + timeoutCtx, cancel := context.WithTimeout(ctx, req.Timeout) + defer cancel() + r, err := http.NewRequestWithContext(timeoutCtx, req.Method, req.URL, bytes.NewBuffer(req.Body)) + if err != nil { + return nil, err + } + + resp, err := c.client.Do(r) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + reader := http.MaxBytesReader(nil, resp.Body, int64(c.config.MaxResponseBytes)) + body, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + headers := make(map[string]string) + for k, v := range resp.Header { + // header values are usually an array of size 1 + // joining them to a single string in case array size is greater than 1 + headers[k] = strings.Join(v, ",") + } + c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "body", string(body), "url", req.URL, "headers", headers) + + return &HTTPResponse{ + Headers: headers, + StatusCode: resp.StatusCode, + Body: body, + }, nil +} diff --git a/core/services/gateway/network/httpclient_test.go b/core/services/gateway/network/httpclient_test.go new file mode 100644 index 00000000000..2f4cc448ef5 --- /dev/null +++ b/core/services/gateway/network/httpclient_test.go @@ -0,0 +1,147 @@ +package network_test + +import ( + "context" + "net/http" + "net/http/httptest" + "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) { + t.Parallel() + + // 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 + expectedError error + expectedResp *network.HTTPResponse + }{ + { + name: "successful request", + setupServer: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, err2 := w.Write([]byte("success")) + require.NoError(t, err2) + })) + }, + request: network.HTTPRequest{ + Method: "GET", + URL: "/", + Headers: map[string]string{}, + Body: nil, + Timeout: 2 * time.Second, + }, + expectedError: nil, + expectedResp: &network.HTTPResponse{ + StatusCode: http.StatusOK, + Headers: map[string]string{"Content-Length": "7"}, + Body: []byte("success"), + }, + }, + { + name: "request timeout", + setupServer: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(10 * time.Second) + w.WriteHeader(http.StatusOK) + _, err2 := w.Write([]byte("success")) + require.NoError(t, err2) + })) + }, + request: network.HTTPRequest{ + Method: "GET", + URL: "/", + Headers: map[string]string{}, + Body: nil, + Timeout: 1 * time.Second, + }, + expectedError: context.DeadlineExceeded, + expectedResp: nil, + }, + { + name: "server error", + setupServer: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + _, err2 := w.Write([]byte("error")) + require.NoError(t, err2) + })) + }, + request: network.HTTPRequest{ + Method: "GET", + URL: "/", + Headers: map[string]string{}, + Body: nil, + Timeout: 2 * time.Second, + }, + expectedError: nil, + expectedResp: &network.HTTPResponse{ + StatusCode: http.StatusInternalServerError, + Headers: map[string]string{"Content-Length": "5"}, + Body: []byte("error"), + }, + }, + { + name: "response too long", + setupServer: func() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, err2 := w.Write(make([]byte, 2048)) + require.NoError(t, err2) + })) + }, + request: network.HTTPRequest{ + Method: "GET", + URL: "/", + Headers: map[string]string{}, + Body: nil, + Timeout: 2 * time.Second, + }, + expectedError: &http.MaxBytesError{}, + expectedResp: nil, + }, + } + + // Execute test cases + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server := tt.setupServer() + defer server.Close() + + tt.request.URL = server.URL + tt.request.URL + + resp, err := client.Send(context.Background(), tt.request) + if tt.expectedError != nil { + require.Error(t, err) + require.ErrorContains(t, err, tt.expectedError.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.expectedResp.StatusCode, resp.StatusCode) + for k, v := range tt.expectedResp.Headers { + value, ok := resp.Headers[k] + require.True(t, ok) + require.Equal(t, v, value) + } + require.Equal(t, tt.expectedResp.Body, resp.Body) + } + }) + } +} diff --git a/core/services/gateway/network/mocks/http_client.go b/core/services/gateway/network/mocks/http_client.go new file mode 100644 index 00000000000..8b5bff2cccf --- /dev/null +++ b/core/services/gateway/network/mocks/http_client.go @@ -0,0 +1,96 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + network "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network" + mock "github.com/stretchr/testify/mock" +) + +// HTTPClient is an autogenerated mock type for the HTTPClient type +type HTTPClient struct { + mock.Mock +} + +type HTTPClient_Expecter struct { + mock *mock.Mock +} + +func (_m *HTTPClient) EXPECT() *HTTPClient_Expecter { + return &HTTPClient_Expecter{mock: &_m.Mock} +} + +// Send provides a mock function with given fields: ctx, req +func (_m *HTTPClient) Send(ctx context.Context, req network.HTTPRequest) (*network.HTTPResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for Send") + } + + var r0 *network.HTTPResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, network.HTTPRequest) (*network.HTTPResponse, error)); ok { + return rf(ctx, req) + } + if rf, ok := ret.Get(0).(func(context.Context, network.HTTPRequest) *network.HTTPResponse); ok { + r0 = rf(ctx, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*network.HTTPResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, network.HTTPRequest) error); ok { + r1 = rf(ctx, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// HTTPClient_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send' +type HTTPClient_Send_Call struct { + *mock.Call +} + +// Send is a helper method to define mock.On call +// - ctx context.Context +// - req network.HTTPRequest +func (_e *HTTPClient_Expecter) Send(ctx interface{}, req interface{}) *HTTPClient_Send_Call { + return &HTTPClient_Send_Call{Call: _e.mock.On("Send", ctx, req)} +} + +func (_c *HTTPClient_Send_Call) Run(run func(ctx context.Context, req network.HTTPRequest)) *HTTPClient_Send_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(network.HTTPRequest)) + }) + return _c +} + +func (_c *HTTPClient_Send_Call) Return(_a0 *network.HTTPResponse, _a1 error) *HTTPClient_Send_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *HTTPClient_Send_Call) RunAndReturn(run func(context.Context, network.HTTPRequest) (*network.HTTPResponse, error)) *HTTPClient_Send_Call { + _c.Call.Return(run) + return _c +} + +// NewHTTPClient creates a new instance of HTTPClient. 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 NewHTTPClient(t interface { + mock.TestingT + Cleanup(func()) +}) *HTTPClient { + mock := &HTTPClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/headreporter/head_reporter.go b/core/services/headreporter/head_reporter.go index f81a6acf913..94de8ae2be9 100644 --- a/core/services/headreporter/head_reporter.go +++ b/core/services/headreporter/head_reporter.go @@ -35,11 +35,12 @@ type ( func NewHeadReporterService(ds sqlutil.DataSource, lggr logger.Logger, reporters ...HeadReporter) *HeadReporterService { return &HeadReporterService{ - ds: ds, - lggr: lggr.Named("HeadReporter"), - newHeads: mailbox.NewSingle[*evmtypes.Head](), - chStop: make(chan struct{}), - reporters: reporters, + ds: ds, + lggr: lggr.Named("HeadReporter"), + newHeads: mailbox.NewSingle[*evmtypes.Head](), + chStop: make(chan struct{}), + reporters: reporters, + reportPeriod: 15 * time.Second, } } diff --git a/core/services/headreporter/head_reporter_test.go b/core/services/headreporter/head_reporter_test.go index ded7e1fb61b..304dd59a478 100644 --- a/core/services/headreporter/head_reporter_test.go +++ b/core/services/headreporter/head_reporter_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -42,4 +43,9 @@ func Test_HeadReporterService(t *testing.T) { require.Eventually(t, func() bool { return reportCalls.Load() == 2 }, 5*time.Second, 100*time.Millisecond) }) + + t.Run("has default report period", func(t *testing.T) { + service := NewHeadReporterService(pgtest.NewSqlxDB(t), logger.TestLogger(t), NewMockHeadReporter(t)) + assert.Equal(t, service.reportPeriod, 15*time.Second) + }) } diff --git a/core/services/headreporter/prometheus_reporter_test.go b/core/services/headreporter/prometheus_reporter_test.go index d96e617fd79..d6fc0f8e938 100644 --- a/core/services/headreporter/prometheus_reporter_test.go +++ b/core/services/headreporter/prometheus_reporter_test.go @@ -109,7 +109,7 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) require.NoError(t, err) lggr := logger.TestLogger(t) lpOpts := logpoller.Opts{ diff --git a/core/services/headreporter/telemetry_reporter.go b/core/services/headreporter/telemetry_reporter.go index d76ce8a6044..0d93ca59a41 100644 --- a/core/services/headreporter/telemetry_reporter.go +++ b/core/services/headreporter/telemetry_reporter.go @@ -10,21 +10,23 @@ import ( "google.golang.org/protobuf/proto" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" ) type telemetryReporter struct { + lggr logger.Logger endpoints map[uint64]commontypes.MonitoringEndpoint } -func NewTelemetryReporter(monitoringEndpointGen telemetry.MonitoringEndpointGenerator, chainIDs ...*big.Int) HeadReporter { +func NewTelemetryReporter(monitoringEndpointGen telemetry.MonitoringEndpointGenerator, lggr logger.Logger, chainIDs ...*big.Int) HeadReporter { endpoints := make(map[uint64]commontypes.MonitoringEndpoint) for _, chainID := range chainIDs { endpoints[chainID.Uint64()] = monitoringEndpointGen.GenMonitoringEndpoint("EVM", chainID.String(), "", synchronization.HeadReport) } - return &telemetryReporter{endpoints: endpoints} + return &telemetryReporter{lggr: lggr.Named("TelemetryReporter"), endpoints: endpoints} } func (t *telemetryReporter) ReportNewHead(ctx context.Context, head *evmtypes.Head) error { @@ -42,6 +44,7 @@ func (t *telemetryReporter) ReportNewHead(ctx context.Context, head *evmtypes.He } } request := &telem.HeadReportRequest{ + ChainID: head.EVMChainID.String(), Latest: &telem.Block{ Timestamp: uint64(head.Timestamp.UTC().Unix()), Number: uint64(head.Number), @@ -55,7 +58,8 @@ func (t *telemetryReporter) ReportNewHead(ctx context.Context, head *evmtypes.He } monitoringEndpoint.SendLog(bytes) if finalized == nil { - return errors.Errorf("No finalized block was found for chain_id=%d", head.EVMChainID.Int64()) + t.lggr.Infow("No finalized block was found", "chainID", head.EVMChainID.Int64(), + "head.number", head.Number, "chainLength", head.ChainLength()) } return nil } diff --git a/core/services/headreporter/telemetry_reporter_test.go b/core/services/headreporter/telemetry_reporter_test.go index c33edab0bcf..6d7f4e3ddef 100644 --- a/core/services/headreporter/telemetry_reporter_test.go +++ b/core/services/headreporter/telemetry_reporter_test.go @@ -13,6 +13,7 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/headreporter" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" @@ -21,28 +22,29 @@ import ( func Test_TelemetryReporter_NewHead(t *testing.T) { head := evmtypes.Head{ - Number: 42, - EVMChainID: ubig.NewI(100), - Hash: common.HexToHash("0x1010"), - Timestamp: time.UnixMilli(1000), - IsFinalized: false, - Parent: &evmtypes.Head{ - Number: 41, - Hash: common.HexToHash("0x1009"), - Timestamp: time.UnixMilli(999), - IsFinalized: true, - }, + Number: 42, + EVMChainID: ubig.NewI(100), + Hash: common.HexToHash("0x1010"), + Timestamp: time.UnixMilli(1000), + } + h41 := &evmtypes.Head{ + Number: 41, + Hash: common.HexToHash("0x1009"), + Timestamp: time.UnixMilli(999), } + h41.IsFinalized.Store(true) + head.Parent.Store(h41) requestBytes, err := proto.Marshal(&telem.HeadReportRequest{ + ChainID: "100", Latest: &telem.Block{ Timestamp: uint64(head.Timestamp.UTC().Unix()), Number: 42, Hash: head.Hash.Hex(), }, Finalized: &telem.Block{ - Timestamp: uint64(head.Parent.Timestamp.UTC().Unix()), + Timestamp: uint64(head.Parent.Load().Timestamp.UTC().Unix()), Number: 41, - Hash: head.Parent.Hash.Hex(), + Hash: head.Parent.Load().Hash.Hex(), }, }) assert.NoError(t, err) @@ -54,7 +56,7 @@ func Test_TelemetryReporter_NewHead(t *testing.T) { monitoringEndpointGen. On("GenMonitoringEndpoint", "EVM", "100", "", synchronization.HeadReport). Return(monitoringEndpoint) - reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, big.NewInt(100)) + reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, logger.TestLogger(t), big.NewInt(100)) err = reporter.ReportNewHead(testutils.Context(t), &head) assert.NoError(t, err) @@ -62,13 +64,13 @@ func Test_TelemetryReporter_NewHead(t *testing.T) { func Test_TelemetryReporter_NewHeadMissingFinalized(t *testing.T) { head := evmtypes.Head{ - Number: 42, - EVMChainID: ubig.NewI(100), - Hash: common.HexToHash("0x1010"), - Timestamp: time.UnixMilli(1000), - IsFinalized: false, + Number: 42, + EVMChainID: ubig.NewI(100), + Hash: common.HexToHash("0x1010"), + Timestamp: time.UnixMilli(1000), } requestBytes, err := proto.Marshal(&telem.HeadReportRequest{ + ChainID: "100", Latest: &telem.Block{ Timestamp: uint64(head.Timestamp.UTC().Unix()), Number: 42, @@ -84,10 +86,10 @@ func Test_TelemetryReporter_NewHeadMissingFinalized(t *testing.T) { monitoringEndpointGen. On("GenMonitoringEndpoint", "EVM", "100", "", synchronization.HeadReport). Return(monitoringEndpoint) - reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, big.NewInt(100)) + reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, logger.TestLogger(t), big.NewInt(100)) err = reporter.ReportNewHead(testutils.Context(t), &head) - assert.Errorf(t, err, "No finalized block was found for chain_id=100") + assert.NoError(t, err) } func Test_TelemetryReporter_NewHead_MissingEndpoint(t *testing.T) { @@ -96,7 +98,7 @@ func Test_TelemetryReporter_NewHead_MissingEndpoint(t *testing.T) { On("GenMonitoringEndpoint", "EVM", "100", "", synchronization.HeadReport). Return(nil) - reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, big.NewInt(100)) + reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, logger.TestLogger(t), big.NewInt(100)) head := evmtypes.Head{Number: 42, EVMChainID: ubig.NewI(100)} diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index 6f9bee66a0c..f801a684643 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -24,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -211,8 +210,7 @@ func makeMinimalHTTPOracleSpec(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralC } s := fmt.Sprintf(minimalNonBootstrapTemplate, contractAddress, transmitterAddress, keyBundle, fetchUrl, timeout) keyStore := cltest.NewKeyStore(t, db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: evmtest.NewEthClientMockWithDefaultChain(t), GeneralConfig: cfg, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, Client: evmtest.NewEthClientMockWithDefaultChain(t), GeneralConfig: cfg, KeyStore: keyStore.Eth()}) _, err := ocr.ValidatedOracleSpecToml(cfg, legacyChains, s) require.NoError(t, err) err = toml.Unmarshal([]byte(s), &os) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 6defdeeb614..14aab17721d 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -26,7 +26,6 @@ import ( 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/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -44,10 +43,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) const mercuryOracleTOML = `name = 'LINK / ETH | 0x0000000000000000000000000000000000000000000000000000000000000001 | verifier_proxy 0x0000000000000000000000000000000000000001' @@ -374,8 +373,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) jb, err := ocr.ValidatedOracleSpecToml(config, legacyChains, testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ TransmitterAddress: address.Hex(), DS1BridgeName: bridge.Name.String(), @@ -782,8 +780,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { TransmitterAddress: address.Hex(), JobID: externalJobID.UUID.String(), }) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) jb, err := ocr.ValidatedOracleSpecToml(config, legacyChains, spec.Toml()) require.NoError(t, err) @@ -1041,8 +1038,7 @@ func Test_FindJobs(t *testing.T) { _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) jb1, err := ocr.ValidatedOracleSpecToml(config, legacyChains, testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ JobID: uuid.New().String(), @@ -1126,8 +1122,7 @@ func Test_FindJob(t *testing.T) { // Must uniquely name the OCR Specs to properly insert a new job in the job table. externalJobID := uuid.New() _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) job, err := ocr.ValidatedOracleSpecToml(config, legacyChains, testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ JobID: externalJobID.String(), @@ -1358,8 +1353,7 @@ func Test_FindPipelineRuns(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1422,8 +1416,7 @@ func Test_PipelineRunsByJobID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1485,8 +1478,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -1600,8 +1592,7 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1725,7 +1716,7 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { jb, err = orm.FindJobWithoutSpecErrors(ctx, jobSpec.ID) require.NoError(t, err) - jbWithErrors, err := orm.FindJobTx(testutils.Context(t), jobSpec.ID) + jbWithErrors, err := orm.FindJob(testutils.Context(t), jobSpec.ID) require.NoError(t, err) assert.Equal(t, len(jb.JobSpecErrors), 0) @@ -1780,8 +1771,7 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1861,6 +1851,7 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { spec: &job.WorkflowSpec{ ID: 1, Workflow: pkgworkflows.WFYamlSpec(t, "workflow01", addr1), + SpecType: job.YamlSpec, }, before: mustInsertWFJob, }, @@ -1881,6 +1872,7 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { var c job.WorkflowSpec c.ID = s.ID c.Workflow = pkgworkflows.WFYamlSpec(t, "workflow99", addr1) // insert with mismatched name + c.SpecType = job.YamlSpec return mustInsertWFJob(t, o, &c) }, }, @@ -1948,18 +1940,21 @@ func Test_ORM_FindJobByWorkflow_Multiple(t *testing.T) { wfYaml1 := pkgworkflows.WFYamlSpec(t, "workflow00", addr1) s1 := job.WorkflowSpec{ Workflow: wfYaml1, + SpecType: job.YamlSpec, } wantJobID1 := mustInsertWFJob(t, o, &s1) wfYaml2 := pkgworkflows.WFYamlSpec(t, "workflow01", addr1) s2 := job.WorkflowSpec{ Workflow: wfYaml2, + SpecType: job.YamlSpec, } wantJobID2 := mustInsertWFJob(t, o, &s2) wfYaml3 := pkgworkflows.WFYamlSpec(t, "workflow00", addr2) s3 := job.WorkflowSpec{ Workflow: wfYaml3, + SpecType: job.YamlSpec, } wantJobID3 := mustInsertWFJob(t, o, &s3) @@ -1976,13 +1971,14 @@ func Test_ORM_FindJobByWorkflow_Multiple(t *testing.T) { assert.EqualValues(t, j.WorkflowSpec.WorkflowID, s.WorkflowID) assert.EqualValues(t, j.WorkflowSpec.WorkflowOwner, s.WorkflowOwner) assert.EqualValues(t, j.WorkflowSpec.WorkflowName, s.WorkflowName) + assert.Equal(t, j.WorkflowSpec.SpecType, job.YamlSpec) } }) } func mustInsertWFJob(t *testing.T, orm job.ORM, s *job.WorkflowSpec) int32 { t.Helper() - err := s.Validate() + err := s.Validate(testutils.Context(t)) require.NoError(t, err, "failed to validate spec %v", s) ctx := testutils.Context(t) _, err = toml.Marshal(s.Workflow) diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go index ca6cc6f832e..f26c9431ff5 100644 --- a/core/services/job/job_pipeline_orm_integration_test.go +++ b/core/services/job/job_pipeline_orm_integration_test.go @@ -20,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -156,8 +155,7 @@ func TestPipelineORM_Integration(t *testing.T) { clearJobsDb(t, db) orm := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{Client: evmtest.NewEthClientMockWithDefaultChain(t), DB: db, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{Client: evmtest.NewEthClientMockWithDefaultChain(t), DB: db, GeneralConfig: config, KeyStore: ethKeyStore}) runner := pipeline.NewRunner(orm, btORM, config.JobPipeline(), cfg.WebServer(), legacyChains, nil, nil, lggr, nil, nil) jobORM := NewTestORM(t, db, orm, btORM, keyStore) diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index 0174d6208cc..15a78abdaf3 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -543,6 +543,63 @@ func (_c *ORM_FindJobIDByAddress_Call) RunAndReturn(run func(context.Context, ty return _c } +// FindJobIDByCapabilityNameAndVersion provides a mock function with given fields: ctx, spec +func (_m *ORM) FindJobIDByCapabilityNameAndVersion(ctx context.Context, spec job.CCIPSpec) (int32, error) { + ret := _m.Called(ctx, spec) + + if len(ret) == 0 { + panic("no return value specified for FindJobIDByCapabilityNameAndVersion") + } + + var r0 int32 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, job.CCIPSpec) (int32, error)); ok { + return rf(ctx, spec) + } + if rf, ok := ret.Get(0).(func(context.Context, job.CCIPSpec) int32); ok { + r0 = rf(ctx, spec) + } else { + r0 = ret.Get(0).(int32) + } + + if rf, ok := ret.Get(1).(func(context.Context, job.CCIPSpec) error); ok { + r1 = rf(ctx, spec) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ORM_FindJobIDByCapabilityNameAndVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindJobIDByCapabilityNameAndVersion' +type ORM_FindJobIDByCapabilityNameAndVersion_Call struct { + *mock.Call +} + +// FindJobIDByCapabilityNameAndVersion is a helper method to define mock.On call +// - ctx context.Context +// - spec job.CCIPSpec +func (_e *ORM_Expecter) FindJobIDByCapabilityNameAndVersion(ctx interface{}, spec interface{}) *ORM_FindJobIDByCapabilityNameAndVersion_Call { + return &ORM_FindJobIDByCapabilityNameAndVersion_Call{Call: _e.mock.On("FindJobIDByCapabilityNameAndVersion", ctx, spec)} +} + +func (_c *ORM_FindJobIDByCapabilityNameAndVersion_Call) Run(run func(ctx context.Context, spec job.CCIPSpec)) *ORM_FindJobIDByCapabilityNameAndVersion_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(job.CCIPSpec)) + }) + return _c +} + +func (_c *ORM_FindJobIDByCapabilityNameAndVersion_Call) Return(_a0 int32, _a1 error) *ORM_FindJobIDByCapabilityNameAndVersion_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ORM_FindJobIDByCapabilityNameAndVersion_Call) RunAndReturn(run func(context.Context, job.CCIPSpec) (int32, error)) *ORM_FindJobIDByCapabilityNameAndVersion_Call { + _c.Call.Return(run) + return _c +} + // FindJobIDByWorkflow provides a mock function with given fields: ctx, spec func (_m *ORM) FindJobIDByWorkflow(ctx context.Context, spec job.WorkflowSpec) (int32, error) { ret := _m.Called(ctx, spec) @@ -659,63 +716,6 @@ func (_c *ORM_FindJobIDsWithBridge_Call) RunAndReturn(run func(context.Context, return _c } -// FindJobTx provides a mock function with given fields: ctx, id -func (_m *ORM) FindJobTx(ctx context.Context, id int32) (job.Job, error) { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for FindJobTx") - } - - var r0 job.Job - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int32) (job.Job, error)); ok { - return rf(ctx, id) - } - if rf, ok := ret.Get(0).(func(context.Context, int32) job.Job); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Get(0).(job.Job) - } - - if rf, ok := ret.Get(1).(func(context.Context, int32) error); ok { - r1 = rf(ctx, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_FindJobTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindJobTx' -type ORM_FindJobTx_Call struct { - *mock.Call -} - -// FindJobTx is a helper method to define mock.On call -// - ctx context.Context -// - id int32 -func (_e *ORM_Expecter) FindJobTx(ctx interface{}, id interface{}) *ORM_FindJobTx_Call { - return &ORM_FindJobTx_Call{Call: _e.mock.On("FindJobTx", ctx, id)} -} - -func (_c *ORM_FindJobTx_Call) Run(run func(ctx context.Context, id int32)) *ORM_FindJobTx_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(int32)) - }) - return _c -} - -func (_c *ORM_FindJobTx_Call) Return(_a0 job.Job, _a1 error) *ORM_FindJobTx_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_FindJobTx_Call) RunAndReturn(run func(context.Context, int32) (job.Job, error)) *ORM_FindJobTx_Call { - _c.Call.Return(run) - return _c -} - // FindJobWithoutSpecErrors provides a mock function with given fields: ctx, id func (_m *ORM) FindJobWithoutSpecErrors(ctx context.Context, id int32) (job.Job, error) { ret := _m.Called(ctx, id) diff --git a/core/services/job/models.go b/core/services/job/models.go index 1c46d08c59c..900e2449e24 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -1,6 +1,7 @@ package job import ( + "context" "database/sql/driver" "encoding/json" "fmt" @@ -14,9 +15,11 @@ import ( "github.com/pkg/errors" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" + commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/types" - pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -857,16 +860,28 @@ type LiquidityBalancerSpec struct { LiquidityBalancerConfig string `toml:"liquidityBalancerConfig" db:"liquidity_balancer_config"` } +type WorkflowSpecType string + +const ( + YamlSpec WorkflowSpecType = "yaml" + WASMFile WorkflowSpecType = "wasm_file" + DefaultSpecType = "" +) + type WorkflowSpec struct { ID int32 `toml:"-"` - Workflow string `toml:"workflow"` // the yaml representation of the workflow + Workflow string `toml:"workflow"` // the raw representation of the workflow + Config string `toml:"config" db:"config"` // the raw representation of the config // fields derived from the yaml spec, used for indexing the database // note: i tried to make these private, but translating them to the database seems to require them to be public - WorkflowID string `toml:"-" db:"workflow_id"` // Derived. Do not modify. the CID of the workflow. - WorkflowOwner string `toml:"-" db:"workflow_owner"` // Derived. Do not modify. the owner of the workflow. - WorkflowName string `toml:"-" db:"workflow_name"` // Derived. Do not modify. the name of the workflow. - CreatedAt time.Time `toml:"-"` - UpdatedAt time.Time `toml:"-"` + WorkflowID string `toml:"-" db:"workflow_id"` // Derived. Do not modify. the CID of the workflow. + WorkflowOwner string `toml:"-" db:"workflow_owner"` // Derived. Do not modify. the owner of the workflow. + WorkflowName string `toml:"-" db:"workflow_name"` // Derived. Do not modify. the name of the workflow. + CreatedAt time.Time `toml:"-"` + UpdatedAt time.Time `toml:"-"` + SpecType WorkflowSpecType `toml:"spec_type" db:"spec_type"` + sdkWorkflow *sdk.WorkflowSpec + rawSpec []byte } var ( @@ -879,14 +894,14 @@ const ( ) // Validate checks the workflow spec for correctness -func (w *WorkflowSpec) Validate() error { - s, err := pkgworkflows.ParseWorkflowSpecYaml(w.Workflow) +func (w *WorkflowSpec) Validate(ctx context.Context) error { + s, err := w.SDKSpec(ctx) if err != nil { - return fmt.Errorf("%w: failed to parse workflow spec %s: %w", ErrInvalidWorkflowYAMLSpec, w.Workflow, err) + return err } + w.WorkflowOwner = strings.TrimPrefix(s.Owner, "0x") // the json schema validation ensures it is a hex string with 0x prefix, but the database does not store the prefix w.WorkflowName = s.Name - w.WorkflowID = s.CID() if len(w.WorkflowID) != workflowIDLen { return fmt.Errorf("%w: incorrect length for id %s: expected %d, got %d", ErrInvalidWorkflowID, w.WorkflowID, workflowIDLen, len(w.WorkflowID)) @@ -895,12 +910,77 @@ func (w *WorkflowSpec) Validate() error { return nil } +func (w *WorkflowSpec) SDKSpec(ctx context.Context) (sdk.WorkflowSpec, error) { + if w.sdkWorkflow != nil { + return *w.sdkWorkflow, nil + } + + workflowSpecFactory, ok := workflowSpecFactories[w.SpecType] + if !ok { + return sdk.WorkflowSpec{}, fmt.Errorf("unknown spec type %s", w.SpecType) + } + spec, rawSpec, cid, err := workflowSpecFactory.Spec(ctx, w.Workflow, w.Config) + if err != nil { + return sdk.WorkflowSpec{}, err + } + w.sdkWorkflow = &spec + w.rawSpec = rawSpec + w.WorkflowID = cid + return spec, nil +} + +func (w *WorkflowSpec) RawSpec(ctx context.Context) ([]byte, error) { + if w.rawSpec != nil { + return w.rawSpec, nil + } + + workflowSpecFactory, ok := workflowSpecFactories[w.SpecType] + if !ok { + return nil, fmt.Errorf("unknown spec type %s", w.SpecType) + } + + rs, err := workflowSpecFactory.RawSpec(ctx, w.Workflow, w.Config) + if err != nil { + return nil, err + } + + w.rawSpec = rs + return rs, nil +} + +type OracleFactoryConfig struct { + Enabled bool `toml:"enabled"` + BootstrapPeers []string `toml:"bootstrap_peers"` // e.g.,["12D3KooWEBVwbfdhKnicois7FTYVsBFGFcoMhMCKXQC57BQyZMhz@localhost:6690"] + OCRContractAddress string `toml:"ocr_contract_address"` // e.g., 0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6 + ChainID string `toml:"chain_id"` // e.g., "31337" + Network string `toml:"network"` // e.g., "evm" +} + +// Value returns this instance serialized for database storage. +func (ofc OracleFactoryConfig) Value() (driver.Value, error) { + return json.Marshal(ofc) +} + +// Scan reads the database value and returns an instance. +func (ofc *OracleFactoryConfig) Scan(value interface{}) error { + if value == nil { + return nil // field is nullable + } + + b, ok := value.([]byte) + if !ok { + return errors.Errorf("expected bytes got %T", value) + } + return json.Unmarshal(b, &ofc) +} + type StandardCapabilitiesSpec struct { - ID int32 - CreatedAt time.Time `toml:"-"` - UpdatedAt time.Time `toml:"-"` - Command string `toml:"command"` - Config string `toml:"config"` + ID int32 + CreatedAt time.Time `toml:"-"` + UpdatedAt time.Time `toml:"-"` + Command string `toml:"command" db:"command"` + Config string `toml:"config" db:"config"` + OracleFactory OracleFactoryConfig `toml:"oracle_factory" db:"oracle_factory"` } func (w *StandardCapabilitiesSpec) GetID() string { diff --git a/core/services/job/models_test.go b/core/services/job/models_test.go index 1f88bb6d38f..9e5d519f502 100644 --- a/core/services/job/models_test.go +++ b/core/services/job/models_test.go @@ -1,4 +1,4 @@ -package job +package job_test import ( _ "embed" @@ -11,6 +11,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types" pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/stretchr/testify/assert" @@ -25,7 +28,7 @@ func TestOCR2OracleSpec_RelayIdentifier(t *testing.T) { type fields struct { Relay string ChainID string - RelayConfig JSONConfig + RelayConfig job.JSONConfig } tests := []struct { name string @@ -69,7 +72,7 @@ func TestOCR2OracleSpec_RelayIdentifier(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - s := &OCR2OracleSpec{ + s := &job.OCR2OracleSpec{ Relay: tt.fields.Relay, ChainID: tt.fields.ChainID, RelayConfig: tt.fields.RelayConfig, @@ -94,7 +97,7 @@ var ( ) func TestOCR2OracleSpec(t *testing.T) { - val := OCR2OracleSpec{ + val := job.OCR2OracleSpec{ Relay: relay.NetworkEVM, PluginType: types.Median, ContractID: "foo", @@ -257,13 +260,13 @@ func TestOCR2OracleSpec(t *testing.T) { }) t.Run("round-trip", func(t *testing.T) { - var gotVal OCR2OracleSpec + var gotVal job.OCR2OracleSpec require.NoError(t, toml.Unmarshal([]byte(compact), &gotVal)) gotB, err := toml.Marshal(gotVal) require.NoError(t, err) require.Equal(t, compact, string(gotB)) t.Run("pretty", func(t *testing.T) { - var gotVal OCR2OracleSpec + var gotVal job.OCR2OracleSpec require.NoError(t, toml.Unmarshal([]byte(pretty), &gotVal)) gotB, err := toml.Marshal(gotVal) require.NoError(t, err) @@ -319,10 +322,10 @@ func TestWorkflowSpec_Validate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - w := &WorkflowSpec{ + w := &job.WorkflowSpec{ Workflow: tt.fields.Workflow, } - err := w.Validate() + err := w.Validate(testutils.Context(t)) require.Equal(t, tt.wantError, err != nil) if !tt.wantError { assert.NotEmpty(t, w.WorkflowID) @@ -331,4 +334,20 @@ func TestWorkflowSpec_Validate(t *testing.T) { } }) } + + t.Run("WASM can validate", func(t *testing.T) { + configLocation := "testdata/config.json" + + w := &job.WorkflowSpec{ + Workflow: createTestBinary(t), + SpecType: job.WASMFile, + Config: configLocation, + } + + err := w.Validate(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "owner", w.WorkflowOwner) + assert.Equal(t, "name", w.WorkflowName) + require.NotEmpty(t, w.WorkflowID) + }) } diff --git a/core/services/job/orm.go b/core/services/job/orm.go index ac3bb655306..f306a68d98b 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -47,7 +47,6 @@ type ORM interface { InsertJob(ctx context.Context, job *Job) error CreateJob(ctx context.Context, jb *Job) error FindJobs(ctx context.Context, offset, limit int) ([]Job, int, error) - FindJobTx(ctx context.Context, id int32) (Job, error) FindJob(ctx context.Context, id int32) (Job, error) FindJobByExternalJobID(ctx context.Context, uuid uuid.UUID) (Job, error) FindJobIDByAddress(ctx context.Context, address evmtypes.EIP55Address, evmChainID *big.Big) (int32, error) @@ -79,6 +78,7 @@ type ORM interface { WithDataSource(source sqlutil.DataSource) ORM FindJobIDByWorkflow(ctx context.Context, spec WorkflowSpec) (int32, error) + FindJobIDByCapabilityNameAndVersion(ctx context.Context, spec CCIPSpec) (int32, error) } type ORMConfig interface { @@ -408,8 +408,8 @@ func (o *orm) CreateJob(ctx context.Context, jb *Job) error { case Stream: // 'stream' type has no associated spec, nothing to do here case Workflow: - sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, workflow_name, created_at, updated_at) - VALUES (:workflow, :workflow_id, :workflow_owner, :workflow_name, NOW(), NOW()) + sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, workflow_name, created_at, updated_at, spec_type, config) + VALUES (:workflow, :workflow_id, :workflow_owner, :workflow_name, NOW(), NOW(), :spec_type, :config) RETURNING id;` specID, err := tx.prepareQuerySpecID(ctx, sql, jb.WorkflowSpec) if err != nil { @@ -417,8 +417,8 @@ func (o *orm) CreateJob(ctx context.Context, jb *Job) error { } jb.WorkflowSpecID = &specID case StandardCapabilities: - sql := `INSERT INTO standardcapabilities_specs (command, config, created_at, updated_at) - VALUES (:command, :config, NOW(), NOW()) + sql := `INSERT INTO standardcapabilities_specs (command, config, oracle_factory, created_at, updated_at) + VALUES (:command, :config, :oracle_factory, NOW(), NOW()) RETURNING id;` specID, err := tx.prepareQuerySpecID(ctx, sql, jb.StandardCapabilitiesSpec) if err != nil { @@ -950,17 +950,13 @@ func LoadConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracleSp return LoadConfigVarsLocalOCR(evmOcrCfg, os, ocrCfg), nil } -func (o *orm) FindJobTx(ctx context.Context, id int32) (Job, error) { - return o.FindJob(ctx, id) -} - // FindJob returns job by ID, with all relations preloaded func (o *orm) FindJob(ctx context.Context, id int32) (jb Job, err error) { err = o.findJob(ctx, &jb, "id", id) return } -// FindJobWithoutSpecErrors returns a job by ID, without loading Spec Errors preloaded +// FindJobWithoutSpecErrors returns a job by ID, without loading SpecVal Errors preloaded func (o *orm) FindJobWithoutSpecErrors(ctx context.Context, id int32) (jb Job, err error) { err = o.transact(ctx, true, func(tx *orm) error { stmt := "SELECT jobs.*, job_pipeline_specs.pipeline_spec_id as pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE jobs.id = $1 LIMIT 1" @@ -1123,6 +1119,18 @@ INNER JOIN workflow_specs ws on jobs.workflow_spec_id = ws.id AND ws.workflow_ow return } +func (o *orm) FindJobIDByCapabilityNameAndVersion(ctx context.Context, spec CCIPSpec) (jobID int32, err error) { + stmt := ` +SELECT jobs.id FROM jobs +INNER JOIN ccip_specs ccip on jobs.ccip_spec_id = ccip.id AND ccip.capability_labelled_name = $1 AND ccip.capability_version = $2 +` + err = o.ds.GetContext(ctx, &jobID, stmt, spec.CapabilityLabelledName, spec.CapabilityVersion) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + err = fmt.Errorf("error searching for job for CCIP (capabilityName,capabilityVersion) ('%s','%s'): %w", spec.CapabilityLabelledName, spec.CapabilityVersion, err) + } + return +} + // PipelineRunsByJobsIDs returns pipeline runs for multiple jobs, not preloading data func (o *orm) PipelineRunsByJobsIDs(ctx context.Context, ids []int32) (runs []pipeline.Run, err error) { err = o.transact(ctx, false, func(tx *orm) error { diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 0b55b14250e..af3a1f5698d 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -44,7 +44,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -84,8 +83,7 @@ func TestRunner(t *testing.T) { require.NoError(t, pipelineORM.Start(ctx)) t.Cleanup(func() { assert.NoError(t, pipelineORM.Close()) }) btORM := bridges.NewORM(db) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) c := clhttptest.NewTestLocalOnlyHTTPClient() runner := pipeline.NewRunner(pipelineORM, btORM, config.JobPipeline(), config.WebServer(), legacyChains, nil, nil, logger.TestLogger(t), c, c) @@ -561,14 +559,13 @@ answer1 [type=median index=0]; c.OCR.CaptureEATelemetry = ptr(tc.specCaptureEATelemetry) }) - relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains = evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains2 := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) kb, err := keyStore.OCR().Create(ctx) require.NoError(t, err) s := fmt.Sprintf(minimalNonBootstrapTemplate, cltest.NewEIP55Address(), transmitterAddress.Hex(), kb.ID(), "http://blah.com", "") - jb, err := ocr.ValidatedOracleSpecToml(config, legacyChains, s) + jb, err := ocr.ValidatedOracleSpecToml(config, legacyChains2, s) require.NoError(t, err) err = toml.Unmarshal([]byte(s), &jb) require.NoError(t, err) @@ -588,7 +585,7 @@ answer1 [type=median index=0]; nil, pw, monitoringEndpoint, - legacyChains, + legacyChains2, lggr, config, servicetest.Run(t, mailboxtest.NewMonitor(t)), diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index 86f0324e6a0..b8144ef86f8 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -5,7 +5,6 @@ import ( "testing" "time" - "github.com/onsi/gomega" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -37,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -66,12 +64,11 @@ func clearDB(t *testing.T, db *sqlx.DB) { } type relayGetter struct { - e evmrelay.EVMChainRelayerExtender r *evmrelayer.Relayer } func (g *relayGetter) Get(id types.RelayID) (loop.Relayer, error) { - return evmrelayer.NewLoopRelayServerAdapter(g.r, g.e), nil + return evmrelayer.NewLOOPRelayAdapter(g.r), nil } func (g *relayGetter) GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) { @@ -102,8 +99,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { }). Return(nil).Maybe() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) t.Run("should respect its dependents", func(t *testing.T) { lggr := logger.TestLogger(t) orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) @@ -250,11 +246,11 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { eventuallyStart.AwaitOrFail(t) // Wait for the claim lock to be taken - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jobs := spawner.ActiveJobs() _, exists := jobs[jobSpecIDA] return exists - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(true)) + }, testutils.WaitTimeout(t), cltest.DBPollingInterval) eventuallyClose := cltest.NewAwaiter() serviceA1.On("Close").Return(nil).Once() @@ -266,11 +262,11 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { eventuallyClose.AwaitOrFail(t) // Wait for the claim lock to be released - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jobs := spawner.ActiveJobs() _, exists := jobs[jobSpecIDA] - return exists - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(false)) + return !exists + }, testutils.WaitTimeout(t), cltest.DBPollingInterval) clearDB(t, db) }) @@ -289,13 +285,11 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { } lggr := logger.TestLogger(t) - relayExtenders := evmtest.NewChainRelayExtenders(t, testopts) - assert.Equal(t, relayExtenders.Len(), 1) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - chain, err := legacyChains.Get("0") - require.NoError(t, err) + legacyChains := evmtest.NewLegacyChains(t, testopts) + assert.Equal(t, legacyChains.Len(), 1) + chain := evmtest.MustGetDefaultChain(t, legacyChains) - evmRelayer, err := evmrelayer.NewRelayer(lggr, chain, evmrelayer.RelayerOpts{ + evmRelayer, err := evmrelayer.NewRelayer(ctx, lggr, chain, evmrelayer.RelayerOpts{ DS: db, CSAETHKeystore: keyStore, CapabilitiesRegistry: capabilities.NewRegistry(lggr), @@ -303,7 +297,6 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { assert.NoError(t, err) testRelayGetter := &relayGetter{ - e: relayExtenders.Slice()[0], r: evmRelayer, } @@ -315,8 +308,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { processConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, func(name string) (*plugins.RegisteredLoop, error) { return nil, nil }, func(loopId string) {}) ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), processConfig) - d := ocr2.NewDelegate(nil, orm, nil, nil, nil, nil, nil, monitoringEndpoint, legacyChains, lggr, ocr2DelegateConfig, - keyStore.OCR2(), ethKeyStore, testRelayGetter, mailMon, capabilities.NewRegistry(lggr)) + d := ocr2.NewDelegate(ocr2.DelegateOpts{JobORM: orm, MonitoringEndpointGen: monitoringEndpoint, LegacyChains: legacyChains, Lggr: lggr, Ks: keyStore.OCR2(), EthKs: ethKeyStore, Relayers: testRelayGetter, MailMon: mailMon, CapabilitiesRegistry: capabilities.NewRegistry(lggr)}, ocr2DelegateConfig) delegateOCR2 := &delegate{jobOCR2Keeper.Type, []job.ServiceCtx{}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ diff --git a/core/services/job/testdata/config.json b/core/services/job/testdata/config.json new file mode 100644 index 00000000000..57cba7a61c7 --- /dev/null +++ b/core/services/job/testdata/config.json @@ -0,0 +1,4 @@ +{ + "Owner": "owner", + "Name": "name" +} \ No newline at end of file diff --git a/core/services/job/testdata/wasm/test_workflow_spec.go b/core/services/job/testdata/wasm/test_workflow_spec.go new file mode 100644 index 00000000000..40b9c0bbb67 --- /dev/null +++ b/core/services/job/testdata/wasm/test_workflow_spec.go @@ -0,0 +1,33 @@ +//go:build wasip1 + +package main + +import ( + "encoding/json" + "log" + + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/testdata/fixtures/capabilities/basictrigger" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { + params := sdk.NewWorkflowParams{} + if err := json.Unmarshal(config, ¶ms); err != nil { + log.Fatal(err) + } + + workflow := sdk.NewWorkflowSpecFactory(params) + + triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} + _ = triggerCfg.New(workflow) + + return workflow +} + +func main() { + runner := wasm.NewRunner() + workflow := BuildWorkflow(runner.Config()) + runner.Run(workflow) +} diff --git a/core/services/job/validate.go b/core/services/job/validate.go index 92a08823fcf..7cd93b91f00 100644 --- a/core/services/job/validate.go +++ b/core/services/job/validate.go @@ -29,6 +29,7 @@ var ( Webhook: {}, Workflow: {}, StandardCapabilities: {}, + CCIP: {}, } ) diff --git a/core/services/job/validate_test.go b/core/services/job/validate_test.go old mode 100644 new mode 100755 diff --git a/core/services/job/wasm_file_spec_factory.go b/core/services/job/wasm_file_spec_factory.go new file mode 100644 index 00000000000..d0fde14adc7 --- /dev/null +++ b/core/services/job/wasm_file_spec_factory.go @@ -0,0 +1,105 @@ +package job + +import ( + "bytes" + "context" + "crypto/sha256" + "errors" + "fmt" + "io" + "os" + "path" + "strings" + + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + + "github.com/andybalholm/brotli" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +type WasmFileSpecFactory struct{} + +func (w WasmFileSpecFactory) Spec(_ context.Context, workflow, configLocation string) (sdk.WorkflowSpec, []byte, string, error) { + config, err := os.ReadFile(configLocation) + if err != nil { + return sdk.WorkflowSpec{}, nil, "", err + } + + compressedBinary, sha, err := w.rawSpecAndSha(workflow, config) + if err != nil { + return sdk.WorkflowSpec{}, nil, "", err + } + + moduleConfig := &host.ModuleConfig{Logger: logger.NullLogger} + spec, err := host.GetWorkflowSpec(moduleConfig, compressedBinary, config) + if err != nil { + return sdk.WorkflowSpec{}, nil, "", err + } else if spec == nil { + return sdk.WorkflowSpec{}, nil, "", errors.New("workflow spec not found when running wasm") + } + + return *spec, compressedBinary, sha, nil +} + +func (w WasmFileSpecFactory) RawSpec(_ context.Context, workflow, configLocation string) ([]byte, error) { + config, err := os.ReadFile(configLocation) + if err != nil { + return nil, err + } + + raw, _, err := w.rawSpecAndSha(workflow, config) + return raw, err +} + +// rawSpecAndSha returns the brotli compressed version of the raw wasm file, alongside the sha256 hash of the raw wasm file +func (w WasmFileSpecFactory) rawSpecAndSha(wf string, config []byte) ([]byte, string, error) { + read, err := os.ReadFile(wf) + if err != nil { + return nil, "", err + } + + extension := strings.ToLower(path.Ext(wf)) + switch extension { + case ".wasm", "": + return w.rawSpecAndShaFromWasm(read, config) + case ".br": + return w.rawSpecAndShaFromBrotli(read, config) + default: + return nil, "", fmt.Errorf("unsupported file type %s", extension) + } +} + +func (w WasmFileSpecFactory) rawSpecAndShaFromBrotli(wasm, config []byte) ([]byte, string, error) { + brr := brotli.NewReader(bytes.NewReader(wasm)) + rawWasm, err := io.ReadAll(brr) + if err != nil { + return nil, "", err + } + + return wasm, w.sha(rawWasm, config), nil +} + +func (w WasmFileSpecFactory) rawSpecAndShaFromWasm(wasm, config []byte) ([]byte, string, error) { + var b bytes.Buffer + bwr := brotli.NewWriter(&b) + if _, err := bwr.Write(wasm); err != nil { + return nil, "", err + } + + if err := bwr.Close(); err != nil { + return nil, "", err + } + + return b.Bytes(), w.sha(wasm, config), nil +} + +func (w WasmFileSpecFactory) sha(wasm, config []byte) string { + sum := sha256.New() + sum.Write(wasm) + sum.Write(config) + return fmt.Sprintf("%x", sum.Sum(nil)) +} + +var _ WorkflowSpecFactory = (*WasmFileSpecFactory)(nil) diff --git a/core/services/job/wasm_file_spec_factory_test.go b/core/services/job/wasm_file_spec_factory_test.go new file mode 100644 index 00000000000..03842db187f --- /dev/null +++ b/core/services/job/wasm_file_spec_factory_test.go @@ -0,0 +1,90 @@ +package job_test + +import ( + "bytes" + "crypto/sha256" + "fmt" + "os" + "os/exec" + "strings" + "testing" + + "github.com/andybalholm/brotli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" +) + +func TestWasmFileSpecFactory(t *testing.T) { + binaryLocation := createTestBinary(t) + configLocation := "testdata/config.json" + config, err := os.ReadFile(configLocation) + require.NoError(t, err) + + rawBinary, err := os.ReadFile(binaryLocation) + require.NoError(t, err) + + b := bytes.Buffer{} + bwr := brotli.NewWriter(&b) + _, err = bwr.Write(rawBinary) + require.NoError(t, err) + + require.NoError(t, bwr.Close()) + + t.Run("Raw binary", func(t *testing.T) { + factory := job.WasmFileSpecFactory{} + actual, rawSpec, actualSha, err2 := factory.Spec(testutils.Context(t), binaryLocation, configLocation) + require.NoError(t, err2) + + expected, err2 := host.GetWorkflowSpec(&host.ModuleConfig{Logger: logger.NullLogger, IsUncompressed: true}, rawBinary, config) + require.NoError(t, err2) + + expectedSha := sha256.New() + expectedSha.Write(rawBinary) + expectedSha.Write(config) + require.Equal(t, fmt.Sprintf("%x", expectedSha.Sum(nil)), actualSha) + + require.Equal(t, *expected, actual) + + assert.Equal(t, b.Bytes(), rawSpec) + }) + + t.Run("Compressed binary", func(t *testing.T) { + brLoc := strings.Replace(binaryLocation, ".wasm", ".br", 1) + compressedBytes := b.Bytes() + require.NoError(t, os.WriteFile(brLoc, compressedBytes, 0600)) + + factory := job.WasmFileSpecFactory{} + actual, rawSpec, actualSha, err2 := factory.Spec(testutils.Context(t), brLoc, configLocation) + require.NoError(t, err2) + + expected, err2 := host.GetWorkflowSpec(&host.ModuleConfig{Logger: logger.NullLogger, IsUncompressed: true}, rawBinary, config) + require.NoError(t, err2) + + expectedSha := sha256.New() + expectedSha.Write(rawBinary) + expectedSha.Write(config) + require.Equal(t, fmt.Sprintf("%x", expectedSha.Sum(nil)), actualSha) + + require.Equal(t, *expected, actual) + + assert.Equal(t, b.Bytes(), rawSpec) + }) +} + +func createTestBinary(t *testing.T) string { + const testBinaryLocation = "testdata/wasm/testmodule.wasm" + + cmd := exec.Command("go", "build", "-o", testBinaryLocation, "github.com/smartcontractkit/chainlink/v2/core/services/job/testdata/wasm") + cmd.Env = append(os.Environ(), "GOOS=wasip1", "GOARCH=wasm") + + output, err := cmd.CombinedOutput() + require.NoError(t, err, string(output)) + + return testBinaryLocation +} diff --git a/core/services/job/workflow_spec_factory.go b/core/services/job/workflow_spec_factory.go new file mode 100644 index 00000000000..031e62a3c26 --- /dev/null +++ b/core/services/job/workflow_spec_factory.go @@ -0,0 +1,18 @@ +package job + +import ( + "context" + + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +type WorkflowSpecFactory interface { + Spec(ctx context.Context, workflow, config string) (sdk.WorkflowSpec, []byte, string, error) + RawSpec(ctx context.Context, workflow, config string) ([]byte, error) +} + +var workflowSpecFactories = map[WorkflowSpecType]WorkflowSpecFactory{ + YamlSpec: YAMLSpecFactory{}, + WASMFile: WasmFileSpecFactory{}, + DefaultSpecType: YAMLSpecFactory{}, +} diff --git a/core/services/job/yaml_spec_factory.go b/core/services/job/yaml_spec_factory.go new file mode 100644 index 00000000000..41548968cf6 --- /dev/null +++ b/core/services/job/yaml_spec_factory.go @@ -0,0 +1,23 @@ +package job + +import ( + "context" + "crypto/sha256" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +type YAMLSpecFactory struct{} + +var _ WorkflowSpecFactory = (*YAMLSpecFactory)(nil) + +func (y YAMLSpecFactory) Spec(_ context.Context, workflow, _ string) (sdk.WorkflowSpec, []byte, string, error) { + spec, err := workflows.ParseWorkflowSpecYaml(workflow) + return spec, []byte(workflow), fmt.Sprintf("%x", sha256.Sum256([]byte(workflow))), err +} + +func (y YAMLSpecFactory) RawSpec(_ context.Context, workflow, _ string) ([]byte, error) { + return []byte(workflow), nil +} diff --git a/core/services/job/yaml_spec_factory_test.go b/core/services/job/yaml_spec_factory_test.go new file mode 100644 index 00000000000..ac127b321a0 --- /dev/null +++ b/core/services/job/yaml_spec_factory_test.go @@ -0,0 +1,79 @@ +package job_test + +import ( + "crypto/sha256" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + commonworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/job" +) + +const anyYamlSpec = ` +name: "wf-name" +owner: "0x00000000000000000000000000000000000000aa" +triggers: + - id: "mercury-trigger@1.0.0" + config: + feedIds: + - "0x1111111111111111111100000000000000000000000000000000000000000000" + - "0x2222222222222222222200000000000000000000000000000000000000000000" + - "0x3333333333333333333300000000000000000000000000000000000000000000" + +consensus: + - id: "offchain_reporting@2.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + +targets: + - id: "write_polygon-testnet-mumbai@3.0.0" + inputs: + report: "$(evm_median.outputs.report)" + config: + address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" + params: ["$(report)"] + abi: "receive(report bytes)" + - id: "write_ethereum-testnet-sepolia@4.0.0" + inputs: + report: "$(evm_median.outputs.report)" + config: + address: "0x54e220867af6683aE6DcBF535B4f952cB5116510" + params: ["$(report)"] + abi: "receive(report bytes)" +` + +func TestYamlSpecFactory_GetSpec(t *testing.T) { + t.Parallel() + + actual, raw, actualSha, err := job.YAMLSpecFactory{}.Spec(testutils.Context(t), anyYamlSpec, "") + require.NoError(t, err) + + expected, err := commonworkflows.ParseWorkflowSpecYaml(anyYamlSpec) + require.NoError(t, err) + + require.Equal(t, expected, actual) + assert.Equal(t, fmt.Sprintf("%x", sha256.Sum256([]byte(anyYamlSpec))), actualSha) + assert.Equal(t, anyYamlSpec, string(raw)) +} diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go index cbbe89b3f21..494e0a16155 100644 --- a/core/services/keeper/integration_test.go +++ b/core/services/keeper/integration_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "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/forwarders" @@ -30,12 +31,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" webpresenters "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go index 439970b381b..2bc5f0de940 100644 --- a/core/services/keeper/orm_test.go +++ b/core/services/keeper/orm_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/onsi/gomega" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -57,11 +56,11 @@ func newUpkeep(registry keeper.Registry, upkeepID int64) keeper.UpkeepRegistrati func waitLastRunHeight(t *testing.T, db *sqlx.DB, upkeep keeper.UpkeepRegistration, height int64) { t.Helper() - gomega.NewWithT(t).Eventually(func() int64 { + require.Eventually(t, func() bool { err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE id = $1`, upkeep.ID) require.NoError(t, err) - return upkeep.LastRunBlockHeight - }, time.Second*2, time.Millisecond*100).Should(gomega.Equal(height)) + return upkeep.LastRunBlockHeight == height + }, time.Second*2, time.Millisecond*100) } func assertLastRunHeight(t *testing.T, db *sqlx.DB, upkeep keeper.UpkeepRegistration, lastRunBlockHeight int64, lastKeeperIndex int64) { diff --git a/core/services/keeper/registry_interface.go b/core/services/keeper/registry_interface.go index c80be29154a..04bcb8e257d 100644 --- a/core/services/keeper/registry_interface.go +++ b/core/services/keeper/registry_interface.go @@ -161,11 +161,11 @@ func (rw *RegistryWrapper) getUpkeepCount(opts *bind.CallOpts) (*big.Int, error) } } -func (rw *RegistryWrapper) GetActiveUpkeepIDs(opts *bind.CallOpts) ([]*big.Int, error) { +func (rw *RegistryWrapper) GetActiveUpkeepIDs(ctx context.Context, opts *bind.CallOpts) ([]*big.Int, error) { if opts == nil || opts.BlockNumber.Int64() == 0 { var head *evmtypes.Head // fetch the current block number so batched GetActiveUpkeepIDs calls can be performed on the same block - head, err := rw.evmClient.HeadByNumber(context.Background(), nil) + head, err := rw.evmClient.HeadByNumber(ctx, nil) if err != nil { return nil, errors.Wrap(err, "failed to fetch EVM block header") } diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index 73a3cb88166..e095615cb26 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) const syncInterval = 1000 * time.Hour // prevents sync timer from triggering during test @@ -44,8 +43,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( lbMock := logmocks.NewBroadcaster(t) lbMock.On("AddDependents", 1).Maybe() j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, LogBroadcaster: lbMock, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, Client: ethClient, LogBroadcaster: lbMock, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) contractAddress := j.KeeperSpec.ContractAddress.Address() diff --git a/core/services/keeper/registry_synchronizer_sync.go b/core/services/keeper/registry_synchronizer_sync.go index 6615d376e2b..f8352a7483a 100644 --- a/core/services/keeper/registry_synchronizer_sync.go +++ b/core/services/keeper/registry_synchronizer_sync.go @@ -44,7 +44,7 @@ func (rs *RegistrySynchronizer) syncRegistry(ctx context.Context) (Registry, err } func (rs *RegistrySynchronizer) fullSyncUpkeeps(ctx context.Context, reg Registry) error { - activeUpkeepIDs, err := rs.registryWrapper.GetActiveUpkeepIDs(nil) + activeUpkeepIDs, err := rs.registryWrapper.GetActiveUpkeepIDs(ctx, nil) if err != nil { return errors.Wrap(err, "unable to get active upkeep IDs") } diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go index 170546287e5..d18a7d809b1 100644 --- a/core/services/keeper/upkeep_executer.go +++ b/core/services/keeper/upkeep_executer.go @@ -162,7 +162,7 @@ func (ex *UpkeepExecuter) processActiveUpkeeps(ctx context.Context) { } var activeUpkeeps []UpkeepRegistration - turnBinary, err2 := ex.turnBlockHashBinary(registry, head, ex.config.TurnLookBack()) + turnBinary, err2 := ex.turnBlockHashBinary(ctx, registry, head, ex.config.TurnLookBack()) if err2 != nil { ex.logger.Error(errors.Wrap(err2, "unable to get turn block number hash")) return @@ -247,9 +247,9 @@ func (ex *UpkeepExecuter) execute(upkeep UpkeepRegistration, head *evmtypes.Head } } -func (ex *UpkeepExecuter) turnBlockHashBinary(registry Registry, head *evmtypes.Head, lookback int64) (string, error) { +func (ex *UpkeepExecuter) turnBlockHashBinary(ctx context.Context, registry Registry, head *evmtypes.Head, lookback int64) (string, error) { turnBlock := head.Number - (head.Number % int64(registry.BlockCountPerTurn)) - lookback - block, err := ex.ethClient.HeadByNumber(context.Background(), big.NewInt(turnBlock)) + block, err := ex.ethClient.HeadByNumber(ctx, big.NewInt(turnBlock)) if err != nil { return "", err } diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index c70a92c725c..a6394646ad5 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -37,7 +37,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func newHead() evmtypes.Head { @@ -48,8 +47,8 @@ func mockEstimator(t *testing.T) gas.EvmFeeEstimator { // note: estimator will only return 1 of legacy or dynamic fees (not both) // assumed to call legacy estimator only estimator := gasmocks.NewEvmFeeEstimator(t) - estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe().Return(gas.EvmFee{ - Legacy: assets.GWei(60), + estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe().Return(gas.EvmFee{ + GasPrice: assets.GWei(60), }, uint32(60), nil) return estimator } @@ -81,8 +80,7 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain ethClient.On("IsL2").Return(false).Maybe() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Maybe().Return(&evmtypes.Head{Number: 1, Hash: utils.NewHash()}, nil) txm := txmmocks.NewMockEvmTxManager(t) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{TxManager: txm, DB: db, Client: ethClient, KeyStore: keyStore.Eth(), GeneralConfig: cfg, GasEstimator: estimator}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{TxManager: txm, DB: db, Client: ethClient, KeyStore: keyStore.Eth(), GeneralConfig: cfg, GasEstimator: estimator}) jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) ch := evmtest.MustGetDefaultChain(t, legacyChains) orm := keeper.NewORM(db, logger.TestLogger(t)) diff --git a/core/services/keystore/chaintype/chaintype.go b/core/services/keystore/chaintype/chaintype.go index 8a12322ebfe..419dfa2d073 100644 --- a/core/services/keystore/chaintype/chaintype.go +++ b/core/services/keystore/chaintype/chaintype.go @@ -36,6 +36,40 @@ func (c ChainTypes) String() (out string) { return sb.String() } +func NewChainType(typ uint8) (ChainType, error) { + switch typ { + case 1: + return EVM, nil + case 2: + return Solana, nil + case 3: + return Cosmos, nil + case 4: + return StarkNet, nil + case 5: + return Aptos, nil + default: + return "", fmt.Errorf("unexpected chaintype.ChainType: %#v", typ) + } +} + +func (c ChainType) Type() (uint8, error) { + switch c { + case EVM: + return 1, nil + case Solana: + return 2, nil + case Cosmos: + return 3, nil + case StarkNet: + return 4, nil + case Aptos: + return 5, 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} diff --git a/core/services/keystore/keys/ethkey/key.go b/core/services/keystore/keys/ethkey/key.go deleted file mode 100644 index 02f256b320d..00000000000 --- a/core/services/keystore/keys/ethkey/key.go +++ /dev/null @@ -1,34 +0,0 @@ -package ethkey - -import ( - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" -) - -// NOTE: This model refers to the OLD key and is only used for migrations -// -// Key holds the private key metadata for a given address that is used to unlock -// said key when given a password. -// -// By default, a key is assumed to represent an ethereum account. -type Key struct { - ID int32 - Address types.EIP55Address - JSON sqlutil.JSON `json:"-"` - CreatedAt time.Time `json:"-"` - UpdatedAt time.Time `json:"-"` - DeletedAt *time.Time `json:"-"` - // IsFunding marks the address as being used for rescuing the node and the pending transactions - // Only one key can be IsFunding=true at a time. - IsFunding bool -} - -// Type returns type of key -func (k Key) Type() string { - if k.IsFunding { - return "funding" - } - return "sending" -} diff --git a/core/services/keystore/keys/ethkey/key_test.go b/core/services/keystore/keys/ethkey/key_test.go deleted file mode 100644 index 9255c0f830f..00000000000 --- a/core/services/keystore/keys/ethkey/key_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package ethkey - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestEthKey_Type(t *testing.T) { - k := Key{ - IsFunding: true, - } - k2 := Key{ - IsFunding: false, - } - - assert.Equal(t, k.Type(), "funding") - assert.Equal(t, k2.Type(), "sending") -} diff --git a/core/services/llo/attested_retirement_report.pb.go b/core/services/llo/attested_retirement_report.pb.go new file mode 100644 index 00000000000..b59f623e984 --- /dev/null +++ b/core/services/llo/attested_retirement_report.pb.go @@ -0,0 +1,213 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.35.1 +// protoc v4.25.1 +// source: attested_retirement_report.proto + +package llo + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type AttestedRetirementReport struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RetirementReport []byte `protobuf:"bytes,1,opt,name=retirementReport,proto3" json:"retirementReport,omitempty"` + SeqNr uint64 `protobuf:"varint,2,opt,name=seqNr,proto3" json:"seqNr,omitempty"` + Sigs []*AttributedOnchainSignature `protobuf:"bytes,3,rep,name=sigs,proto3" json:"sigs,omitempty"` +} + +func (x *AttestedRetirementReport) Reset() { + *x = AttestedRetirementReport{} + mi := &file_attested_retirement_report_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AttestedRetirementReport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AttestedRetirementReport) ProtoMessage() {} + +func (x *AttestedRetirementReport) ProtoReflect() protoreflect.Message { + mi := &file_attested_retirement_report_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AttestedRetirementReport.ProtoReflect.Descriptor instead. +func (*AttestedRetirementReport) Descriptor() ([]byte, []int) { + return file_attested_retirement_report_proto_rawDescGZIP(), []int{0} +} + +func (x *AttestedRetirementReport) GetRetirementReport() []byte { + if x != nil { + return x.RetirementReport + } + return nil +} + +func (x *AttestedRetirementReport) GetSeqNr() uint64 { + if x != nil { + return x.SeqNr + } + return 0 +} + +func (x *AttestedRetirementReport) GetSigs() []*AttributedOnchainSignature { + if x != nil { + return x.Sigs + } + return nil +} + +type AttributedOnchainSignature struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + Signer uint32 `protobuf:"varint,2,opt,name=signer,proto3" json:"signer,omitempty"` +} + +func (x *AttributedOnchainSignature) Reset() { + *x = AttributedOnchainSignature{} + mi := &file_attested_retirement_report_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AttributedOnchainSignature) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AttributedOnchainSignature) ProtoMessage() {} + +func (x *AttributedOnchainSignature) ProtoReflect() protoreflect.Message { + mi := &file_attested_retirement_report_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AttributedOnchainSignature.ProtoReflect.Descriptor instead. +func (*AttributedOnchainSignature) Descriptor() ([]byte, []int) { + return file_attested_retirement_report_proto_rawDescGZIP(), []int{1} +} + +func (x *AttributedOnchainSignature) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *AttributedOnchainSignature) GetSigner() uint32 { + if x != nil { + return x.Signer + } + return 0 +} + +var File_attested_retirement_report_proto protoreflect.FileDescriptor + +var file_attested_retirement_report_proto_rawDesc = []byte{ + 0x0a, 0x20, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x74, 0x69, 0x72, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x03, 0x6c, 0x6c, 0x6f, 0x22, 0x91, 0x01, 0x0a, 0x18, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x74, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x74, 0x69, 0x72, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, + 0x72, 0x65, 0x74, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x33, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6c, 0x6c, 0x6f, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x04, 0x73, 0x69, 0x67, 0x73, 0x22, 0x52, 0x0a, 0x1a, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x42, + 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, + 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x6c, 0x6c, 0x6f, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_attested_retirement_report_proto_rawDescOnce sync.Once + file_attested_retirement_report_proto_rawDescData = file_attested_retirement_report_proto_rawDesc +) + +func file_attested_retirement_report_proto_rawDescGZIP() []byte { + file_attested_retirement_report_proto_rawDescOnce.Do(func() { + file_attested_retirement_report_proto_rawDescData = protoimpl.X.CompressGZIP(file_attested_retirement_report_proto_rawDescData) + }) + return file_attested_retirement_report_proto_rawDescData +} + +var file_attested_retirement_report_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_attested_retirement_report_proto_goTypes = []any{ + (*AttestedRetirementReport)(nil), // 0: llo.AttestedRetirementReport + (*AttributedOnchainSignature)(nil), // 1: llo.AttributedOnchainSignature +} +var file_attested_retirement_report_proto_depIdxs = []int32{ + 1, // 0: llo.AttestedRetirementReport.sigs:type_name -> llo.AttributedOnchainSignature + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_attested_retirement_report_proto_init() } +func file_attested_retirement_report_proto_init() { + if File_attested_retirement_report_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_attested_retirement_report_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_attested_retirement_report_proto_goTypes, + DependencyIndexes: file_attested_retirement_report_proto_depIdxs, + MessageInfos: file_attested_retirement_report_proto_msgTypes, + }.Build() + File_attested_retirement_report_proto = out.File + file_attested_retirement_report_proto_rawDesc = nil + file_attested_retirement_report_proto_goTypes = nil + file_attested_retirement_report_proto_depIdxs = nil +} diff --git a/core/services/llo/attested_retirement_report.proto b/core/services/llo/attested_retirement_report.proto new file mode 100644 index 00000000000..42020b15bb7 --- /dev/null +++ b/core/services/llo/attested_retirement_report.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +option go_package = "github.com/smartcontractkit/chainlink/v2/core/services/llo"; + +package llo; + +message AttestedRetirementReport { + bytes retirementReport = 1; + uint64 seqNr = 2; + repeated AttributedOnchainSignature sigs = 3; +} + +message AttributedOnchainSignature { + bytes signature = 1; + uint32 signer = 2; +} + diff --git a/core/services/llo/bm/dummy_transmitter.go b/core/services/llo/bm/dummy_transmitter.go index c349c9e0ee8..b7fa2bd9e15 100644 --- a/core/services/llo/bm/dummy_transmitter.go +++ b/core/services/llo/bm/dummy_transmitter.go @@ -2,6 +2,7 @@ package bm import ( "context" + "fmt" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -10,12 +11,13 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" + "github.com/smartcontractkit/chainlink-data-streams/llo" + "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/logger" ) // A dummy transmitter useful for benchmarking and testing @@ -39,7 +41,7 @@ type transmitter struct { func NewTransmitter(lggr logger.Logger, fromAccount string) Transmitter { return &transmitter{ - lggr.Named("DummyTransmitter"), + logger.Named(lggr, "DummyTransmitter"), fromAccount, } } @@ -60,21 +62,44 @@ func (t *transmitter) Transmit( sigs []types.AttributedOnchainSignature, ) error { lggr := t.lggr - switch report.Info.ReportFormat { - case llotypes.ReportFormatJSON: - r, err := (llo.JSONReportCodec{}).Decode(report.Report) - if err != nil { - lggr.Debugw("Failed to decode JSON report", "err", err) + { + switch report.Info.ReportFormat { + case llotypes.ReportFormatJSON: + r, err := (llo.JSONReportCodec{}).Decode(report.Report) + if err != nil { + lggr.Debugw(fmt.Sprintf("Failed to decode report with type %s", report.Info.ReportFormat), "err", err) + } else if r.SeqNr > 0 { + lggr = logger.With(lggr, + "report.Report.ConfigDigest", r.ConfigDigest, + "report.Report.SeqNr", r.SeqNr, + "report.Report.ChannelID", r.ChannelID, + "report.Report.ValidAfterSeconds", r.ValidAfterSeconds, + "report.Report.ObservationTimestampSeconds", r.ObservationTimestampSeconds, + "report.Report.Values", r.Values, + "report.Report.Specimen", r.Specimen, + ) + } + case llotypes.ReportFormatEVMPremiumLegacy: + r, err := (evm.ReportCodecPremiumLegacy{}).Decode(report.Report) + if err != nil { + lggr.Debugw(fmt.Sprintf("Failed to decode report with type %s", report.Info.ReportFormat), "err", err) + } else if r.ObservationsTimestamp > 0 { + lggr = logger.With(lggr, + "report.Report.FeedId", r.FeedId, + "report.Report.ObservationsTimestamp", r.ObservationsTimestamp, + "report.Report.BenchmarkPrice", r.BenchmarkPrice, + "report.Report.Bid", r.Bid, + "report.Report.Ask", r.Ask, + "report.Report.ValidFromTimestamp", r.ValidFromTimestamp, + "report.Report.ExpiresAt", r.ExpiresAt, + "report.Report.LinkFee", r.LinkFee, + "report.Report.NativeFee", r.NativeFee, + ) + } + default: + err := fmt.Errorf("unhandled report format: %s", report.Info.ReportFormat) + lggr.Debugw(fmt.Sprintf("Failed to decode report with type %s", report.Info.ReportFormat), "err", err) } - lggr = lggr.With( - "report.Report.ConfigDigest", r.ConfigDigest, - "report.Report.SeqNr", r.SeqNr, - "report.Report.ChannelID", r.ChannelID, - "report.Report.ValidAfterSeconds", r.ValidAfterSeconds, - "report.Report.Values", r.Values, - "report.Report.Specimen", r.Specimen, - ) - default: } transmitSuccessCount.Inc() lggr.Infow("Transmit (dummy)", "digest", digest, "seqNr", seqNr, "report.Report", report.Report, "report.Info", report.Info, "sigs", sigs) @@ -82,7 +107,7 @@ func (t *transmitter) Transmit( } // FromAccount returns the stringified (hex) CSA public key -func (t *transmitter) FromAccount() (ocr2types.Account, error) { +func (t *transmitter) FromAccount(context.Context) (ocr2types.Account, error) { return ocr2types.Account(t.fromAccount), nil } diff --git a/core/services/llo/channel_definition_cache_factory.go b/core/services/llo/channel_definition_cache_factory.go index 51906e0ff1b..0cc2543cdf1 100644 --- a/core/services/llo/channel_definition_cache_factory.go +++ b/core/services/llo/channel_definition_cache_factory.go @@ -2,14 +2,15 @@ package llo import ( "fmt" + "net/http" "sync" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config" ) @@ -19,25 +20,29 @@ type ChannelDefinitionCacheFactory interface { var _ ChannelDefinitionCacheFactory = &channelDefinitionCacheFactory{} -func NewChannelDefinitionCacheFactory(lggr logger.Logger, orm ChannelDefinitionCacheORM, lp logpoller.LogPoller) ChannelDefinitionCacheFactory { +func NewChannelDefinitionCacheFactory(lggr logger.Logger, orm ChannelDefinitionCacheORM, lp logpoller.LogPoller, client *http.Client) ChannelDefinitionCacheFactory { return &channelDefinitionCacheFactory{ lggr, orm, lp, - make(map[common.Address]struct{}), + client, + make(map[common.Address]map[uint32]struct{}), sync.Mutex{}, } } type channelDefinitionCacheFactory struct { - lggr logger.Logger - orm ChannelDefinitionCacheORM - lp logpoller.LogPoller + lggr logger.Logger + orm ChannelDefinitionCacheORM + lp logpoller.LogPoller + client *http.Client - caches map[common.Address]struct{} + caches map[common.Address]map[uint32]struct{} mu sync.Mutex } +// TODO: Test this +// MERC-3653 func (f *channelDefinitionCacheFactory) NewCache(cfg lloconfig.PluginConfig) (llotypes.ChannelDefinitionCache, error) { if cfg.ChannelDefinitions != "" { return NewStaticChannelDefinitionCache(f.lggr, cfg.ChannelDefinitions) @@ -45,14 +50,18 @@ func (f *channelDefinitionCacheFactory) NewCache(cfg lloconfig.PluginConfig) (ll addr := cfg.ChannelDefinitionsContractAddress fromBlock := cfg.ChannelDefinitionsContractFromBlock + donID := cfg.DonID f.mu.Lock() defer f.mu.Unlock() - if _, exists := f.caches[addr]; exists { + if _, exists := f.caches[addr][donID]; exists { // This shouldn't really happen and isn't supported - return nil, fmt.Errorf("cache already exists for contract address %s", addr.Hex()) + return nil, fmt.Errorf("cache already exists for contract address %s and don ID %d", addr.Hex(), donID) } - f.caches[addr] = struct{}{} - return NewChannelDefinitionCache(f.lggr, f.orm, f.lp, addr, fromBlock), nil + if _, exists := f.caches[addr]; !exists { + f.caches[addr] = make(map[uint32]struct{}) + } + f.caches[addr][donID] = struct{}{} + return NewChannelDefinitionCache(f.lggr, f.orm, f.client, f.lp, addr, donID, fromBlock), nil } diff --git a/core/services/llo/cleanup.go b/core/services/llo/cleanup.go new file mode 100644 index 00000000000..c7f8d546db6 --- /dev/null +++ b/core/services/llo/cleanup.go @@ -0,0 +1,28 @@ +package llo + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/mercurytransmitter" +) + +func Cleanup(ctx context.Context, lp LogPoller, addr common.Address, donID uint32, ds sqlutil.DataSource, chainSelector uint64) error { + if (addr != common.Address{} && donID > 0) { + if err := lp.UnregisterFilter(ctx, filterName(addr, donID)); err != nil { + return fmt.Errorf("failed to unregister filter: %w", err) + } + orm := NewChainScopedORM(ds, chainSelector) + if err := orm.CleanupChannelDefinitions(ctx, addr, donID); err != nil { + return fmt.Errorf("failed to cleanup channel definitions: %w", err) + } + } + torm := mercurytransmitter.NewORM(ds, donID) + if err := torm.Cleanup(ctx); err != nil { + return fmt.Errorf("failed to cleanup transmitter: %w", err) + } + return nil +} diff --git a/core/services/llo/cleanup_test.go b/core/services/llo/cleanup_test.go new file mode 100644 index 00000000000..9f00c09d8b3 --- /dev/null +++ b/core/services/llo/cleanup_test.go @@ -0,0 +1,102 @@ +package llo + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/mercurytransmitter" +) + +func makeSampleTransmission(seqNr uint64, sURL string) *mercurytransmitter.Transmission { + return &mercurytransmitter.Transmission{ + ServerURL: sURL, + ConfigDigest: types.ConfigDigest{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c}, + SeqNr: seqNr, + Report: ocr3types.ReportWithInfo[llotypes.ReportInfo]{ + Report: ocrtypes.Report{0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0}, + Info: llotypes.ReportInfo{ + LifeCycleStage: llotypes.LifeCycleStage("production"), + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + }, + }, + Sigs: []types.AttributedOnchainSignature{types.AttributedOnchainSignature{Signature: []uint8{0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x1}, Signer: 0x1}, types.AttributedOnchainSignature{Signature: []uint8{0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0, 0x0}, Signer: 0x3}}, + } +} + +func Test_Cleanup(t *testing.T) { + ctx := testutils.Context(t) + + lp := &mockLogPoller{} + ds := pgtest.NewSqlxDB(t) + + addr1 := common.Address{1, 2, 3} + addr2 := common.Address{4, 5, 6} + donID1 := uint32(1) + donID2 := uint32(2) + chainSelector := uint64(3) + + // add some channel definitions + cdcorm := NewChainScopedORM(ds, chainSelector) + { + err := cdcorm.StoreChannelDefinitions(ctx, addr1, donID1, 1, llotypes.ChannelDefinitions{}, 1) + require.NoError(t, err) + err = cdcorm.StoreChannelDefinitions(ctx, addr2, donID2, 1, llotypes.ChannelDefinitions{}, 1) + require.NoError(t, err) + } + + // add some transmissions + + torm1 := mercurytransmitter.NewORM(ds, donID1) + srvURL1 := "http://example.com/foo" + srvURL2 := "http://example.test/bar" + { + err := torm1.Insert(ctx, []*mercurytransmitter.Transmission{makeSampleTransmission(1, srvURL1), makeSampleTransmission(1, srvURL2)}) + require.NoError(t, err) + } + + torm2 := mercurytransmitter.NewORM(ds, donID2) + { + err := torm2.Insert(ctx, []*mercurytransmitter.Transmission{makeSampleTransmission(2, srvURL1), makeSampleTransmission(2, srvURL2)}) + require.NoError(t, err) + } + + err := Cleanup(ctx, lp, addr1, donID1, ds, chainSelector) + require.NoError(t, err) + + t.Run("unregisters filter", func(t *testing.T) { + assert.Equal(t, []string{"OCR3 LLO ChannelDefinitionCachePoller - 0x0102030000000000000000000000000000000000:1"}, lp.unregisteredFilterNames) + }) + t.Run("removes channel definitions", func(t *testing.T) { + pd, err := cdcorm.LoadChannelDefinitions(ctx, addr1, donID1) + require.NoError(t, err) + assert.Nil(t, pd) + pd, err = cdcorm.LoadChannelDefinitions(ctx, addr2, donID2) + require.NoError(t, err) + assert.NotNil(t, pd) + }) + t.Run("removes transmissions", func(t *testing.T) { + trs, err := torm1.Get(ctx, srvURL1) + require.NoError(t, err) + assert.Len(t, trs, 0) + trs, err = torm1.Get(ctx, srvURL2) + require.NoError(t, err) + assert.Len(t, trs, 0) + + trs, err = torm2.Get(ctx, srvURL1) + require.NoError(t, err) + assert.Len(t, trs, 1) + trs, err = torm2.Get(ctx, srvURL2) + require.NoError(t, err) + assert.Len(t, trs, 1) + }) +} diff --git a/core/services/llo/codecs.go b/core/services/llo/codecs.go new file mode 100644 index 00000000000..7813c8923ea --- /dev/null +++ b/core/services/llo/codecs.go @@ -0,0 +1,18 @@ +package llo + +import ( + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-data-streams/llo" + + "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" +) + +// NOTE: All supported codecs must be specified here +func NewReportCodecs() map[llotypes.ReportFormat]llo.ReportCodec { + codecs := make(map[llotypes.ReportFormat]llo.ReportCodec) + + codecs[llotypes.ReportFormatJSON] = llo.JSONReportCodec{} + codecs[llotypes.ReportFormatEVMPremiumLegacy] = evm.ReportCodecPremiumLegacy{} + + return codecs +} diff --git a/core/services/llo/codecs_test.go b/core/services/llo/codecs_test.go new file mode 100644 index 00000000000..4a7f3f65571 --- /dev/null +++ b/core/services/llo/codecs_test.go @@ -0,0 +1,16 @@ +package llo + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" +) + +func Test_NewReportCodecs(t *testing.T) { + c := NewReportCodecs() + + assert.Contains(t, c, llotypes.ReportFormatJSON, "expected JSON to be supported") + assert.Contains(t, c, llotypes.ReportFormatEVMPremiumLegacy, "expected EVMPremiumLegacy to be supported") +} diff --git a/core/services/llo/data_source.go b/core/services/llo/data_source.go index 20b14edad52..ef333f821a1 100644 --- a/core/services/llo/data_source.go +++ b/core/services/llo/data_source.go @@ -3,20 +3,21 @@ package llo import ( "context" "fmt" - "math/big" "sort" "sync" "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" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/streams" + "github.com/smartcontractkit/chainlink/v2/core/utils" ) var ( @@ -70,10 +71,16 @@ var _ llo.DataSource = &dataSource{} type dataSource struct { lggr logger.Logger registry Registry + + t Telemeter +} + +func NewDataSource(lggr logger.Logger, registry Registry, t Telemeter) llo.DataSource { + return newDataSource(lggr, registry, t) } -func newDataSource(lggr logger.Logger, registry Registry) llo.DataSource { - return &dataSource{lggr.Named("DataSource"), registry} +func newDataSource(lggr logger.Logger, registry Registry, t Telemeter) *dataSource { + return &dataSource{logger.Named(lggr, "DataSource"), registry, t} } // Observe looks up all streams in the registry and populates a map of stream ID => value @@ -81,7 +88,7 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, var wg sync.WaitGroup wg.Add(len(streamValues)) var svmu sync.Mutex - var errors []ErrObservationFailed + var errs []ErrObservationFailed var errmu sync.Mutex if opts.VerboseLogging() { @@ -90,19 +97,19 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, streamIDs = append(streamIDs, streamID) } sort.Slice(streamIDs, func(i, j int) bool { return streamIDs[i] < streamIDs[j] }) - d.lggr.Debugw("Observing streams", "streamIDs", streamIDs, "seqNr", opts.SeqNr()) + d.lggr.Debugw("Observing streams", "streamIDs", streamIDs, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr) } for _, streamID := range maps.Keys(streamValues) { go func(streamID llotypes.StreamID) { defer wg.Done() - var val *big.Int + var val llo.StreamValue stream, exists := d.registry.Get(streamID) if !exists { errmu.Lock() - errors = append(errors, ErrObservationFailed{streamID: streamID, reason: fmt.Sprintf("missing stream: %d", streamID)}) + errs = append(errs, ErrObservationFailed{streamID: streamID, reason: fmt.Sprintf("missing stream: %d", streamID)}) errmu.Unlock() promMissingStreamCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() return @@ -110,25 +117,30 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, run, trrs, err := stream.Run(ctx) if err != nil { errmu.Lock() - errors = append(errors, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "pipeline run failed"}) + errs = append(errs, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "pipeline run failed"}) errmu.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: support types other than *big.Int - // https://smartcontract-it.atlassian.net/browse/MERC-3525 - val, err = streams.ExtractBigInt(trrs) + // 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) if err != nil { errmu.Lock() - errors = append(errors, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "failed to extract big.Int"}) + errs = append(errs, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "failed to extract big.Int"}) errmu.Unlock() return } + d.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, nil) + if val != nil { svmu.Lock() defer svmu.Unlock() - streamValues[streamID] = nil + streamValues[streamID] = val } }(streamID) } @@ -137,25 +149,79 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, // Failed observations are always logged at warn level var failedStreamIDs []streams.StreamID - if len(errors) > 0 { - sort.Slice(errors, func(i, j int) bool { return errors[i].streamID < errors[j].streamID }) - failedStreamIDs = make([]streams.StreamID, len(errors)) - for i, e := range errors { + if len(errs) > 0 { + sort.Slice(errs, func(i, j int) bool { return errs[i].streamID < errs[j].streamID }) + failedStreamIDs = make([]streams.StreamID, len(errs)) + errStrs := make([]string, len(errs)) + for i, e := range errs { + errStrs[i] = e.String() failedStreamIDs[i] = e.streamID } - d.lggr.Warnw("Observation failed for streams", "failedStreamIDs", failedStreamIDs, "errors", errors, "seqNr", opts.SeqNr()) + d.lggr.Warnw("Observation failed for streams", "failedStreamIDs", failedStreamIDs, "errs", errStrs, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr) } if opts.VerboseLogging() { successes := make([]streams.StreamID, 0, len(streamValues)) - for strmID, res := range streamValues { - if res != nil { - successes = append(successes, strmID) - } + for strmID := range streamValues { + successes = append(successes, strmID) } sort.Slice(successes, func(i, j int) bool { return successes[i] < successes[j] }) - d.lggr.Debugw("Observation complete", "successfulStreamIDs", successes, "failedStreamIDs", failedStreamIDs, "values", streamValues, "seqNr", opts.SeqNr()) + d.lggr.Debugw("Observation complete", "successfulStreamIDs", successes, "failedStreamIDs", failedStreamIDs, "configDigest", opts.ConfigDigest(), "values", streamValues, "seqNr", opts.OutCtx().SeqNr) } 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() + + // TODO: Special handling for missing native/link streams? + // https://smartcontract-it.atlassian.net/browse/MERC-5949 + + // 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 3716bb2a583..932c4c0c73a 100644 --- a/core/services/llo/data_source_test.go +++ b/core/services/llo/data_source_test.go @@ -4,9 +4,15 @@ import ( "context" "errors" "math/big" + "sync" "testing" + "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-data-streams/llo" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -34,8 +40,9 @@ func (m *mockRegistry) Get(streamID streams.StreamID) (strm streams.Stream, exis return } -func makeStreamWithSingleResult[T any](res T, err error) *mockStream { +func makeStreamWithSingleResult[T any](runID int64, res T, err error) *mockStream { return &mockStream{ + run: &pipeline.Run{ID: runID}, trrs: []pipeline.TaskRunResult{pipeline.TaskRunResult{Task: &pipeline.MemoTask{}, Result: pipeline.Result{Value: res}}}, err: err, } @@ -51,45 +58,113 @@ func makeStreamValues() llo.StreamValues { type mockOpts struct{} -func (m mockOpts) VerboseLogging() bool { return true } -func (m mockOpts) SeqNr() uint64 { return 42 } +func (m *mockOpts) VerboseLogging() bool { return true } +func (m *mockOpts) SeqNr() uint64 { return 1042 } +func (m *mockOpts) OutCtx() ocr3types.OutcomeContext { + return ocr3types.OutcomeContext{SeqNr: 1042, PreviousOutcome: ocr3types.Outcome([]byte("foo"))} +} +func (m *mockOpts) ConfigDigest() ocr2types.ConfigDigest { + return ocr2types.ConfigDigest{6, 5, 4} +} + +type mockTelemeter struct { + mu sync.Mutex + v3PremiumLegacyPackets []v3PremiumLegacyPacket +} + +type v3PremiumLegacyPacket struct { + run *pipeline.Run + trrs pipeline.TaskRunResults + streamID uint32 + opts llo.DSOpts + val llo.StreamValue + err error +} + +var _ Telemeter = &mockTelemeter{} + +func (m *mockTelemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.TaskRunResults, streamID uint32, opts llo.DSOpts, val llo.StreamValue, err error) { + m.mu.Lock() + defer m.mu.Unlock() + m.v3PremiumLegacyPackets = append(m.v3PremiumLegacyPackets, v3PremiumLegacyPacket{run, trrs, streamID, opts, val, err}) +} func Test_DataSource(t *testing.T) { - t.Skip("waiting on https://github.com/smartcontractkit/chainlink/pull/13780") lggr := logger.TestLogger(t) reg := &mockRegistry{make(map[streams.StreamID]*mockStream)} - ds := newDataSource(lggr, reg) + ds := newDataSource(lggr, reg, NullTelemeter) ctx := testutils.Context(t) + opts := &mockOpts{} t.Run("Observe", func(t *testing.T) { t.Run("doesn't set any values if no streams are defined", func(t *testing.T) { vals := makeStreamValues() - err := ds.Observe(ctx, vals, mockOpts{}) + err := ds.Observe(ctx, vals, opts) assert.NoError(t, err) 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](big.NewInt(2181), nil) - reg.streams[2] = makeStreamWithSingleResult[*big.Int](big.NewInt(40602), nil) - reg.streams[3] = makeStreamWithSingleResult[*big.Int](big.NewInt(15), nil) + 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) vals := makeStreamValues() - err := ds.Observe(ctx, vals, mockOpts{}) + err := ds.Observe(ctx, vals, opts) assert.NoError(t, err) - assert.Equal(t, llo.StreamValues{}, vals) + assert.Equal(t, llo.StreamValues{ + 2: llo.ToDecimal(decimal.NewFromInt(40602)), + 1: llo.ToDecimal(decimal.NewFromInt(2181)), + 3: llo.ToDecimal(decimal.NewFromInt(15)), + }, vals) }) t.Run("observes each stream and returns success/errors", func(t *testing.T) { - reg.streams[1] = makeStreamWithSingleResult[*big.Int](big.NewInt(2181), errors.New("something exploded")) - reg.streams[2] = makeStreamWithSingleResult[*big.Int](big.NewInt(40602), nil) - reg.streams[3] = makeStreamWithSingleResult[*big.Int](nil, errors.New("something exploded 2")) + 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")) + + vals := makeStreamValues() + err := ds.Observe(ctx, vals, opts) + assert.NoError(t, err) + + assert.Equal(t, llo.StreamValues{ + 2: llo.ToDecimal(decimal.NewFromInt(40602)), + 1: nil, + 3: nil, + }, vals) + }) + + t.Run("records telemetry", func(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) vals := makeStreamValues() - err := ds.Observe(ctx, vals, mockOpts{}) + err := ds.Observe(ctx, vals, opts) assert.NoError(t, err) - assert.Equal(t, llo.StreamValues{}, vals) + assert.Equal(t, llo.StreamValues{ + 2: llo.ToDecimal(decimal.NewFromInt(40602)), + 1: llo.ToDecimal(decimal.NewFromInt(2181)), + 3: llo.ToDecimal(decimal.NewFromInt(15)), + }, 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.Equal(t, "2181", pkt.val.(*llo.Decimal).String()) + assert.Nil(t, pkt.err) }) }) } diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index ddcab383efa..70df901c730 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -12,12 +12,13 @@ import ( ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "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" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" + datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -31,42 +32,48 @@ type Closer interface { type delegate struct { services.StateMachine - cfg DelegateConfig - codecs map[llotypes.ReportFormat]llo.ReportCodec + cfg DelegateConfig + reportCodecs map[llotypes.ReportFormat]datastreamsllo.ReportCodec - prrc llo.PredecessorRetirementReportCache - src llo.ShouldRetireCache - ds llo.DataSource + src datastreamsllo.ShouldRetireCache + ds datastreamsllo.DataSource + t services.Service - oracle Closer + oracles []Closer } type DelegateConfig struct { - Logger logger.Logger - DataSource sqlutil.DataSource - Runner streams.Runner - Registry Registry - JobName null.String + Logger logger.Logger + DataSource sqlutil.DataSource + Runner streams.Runner + Registry Registry + JobName null.String + CaptureEATelemetry bool // LLO ChannelDefinitionCache llotypes.ChannelDefinitionCache - ReportingPluginConfig llo.Config + ReportingPluginConfig datastreamsllo.Config + RetirementReportCache RetirementReportCache + RetirementReportCodec datastreamsllo.RetirementReportCodec + ShouldRetireCache datastreamsllo.ShouldRetireCache // OCR3 + TraceLogging bool BinaryNetworkEndpointFactory ocr2types.BinaryNetworkEndpointFactory V2Bootstrappers []ocrcommontypes.BootstrapperLocator - ContractConfigTracker ocr2types.ContractConfigTracker - ContractTransmitter ocr3types.ContractTransmitter[llotypes.ReportInfo] - Database ocr3types.Database - OCRLogger ocrcommontypes.Logger - MonitoringEndpoint ocrcommontypes.MonitoringEndpoint - OffchainConfigDigester ocr2types.OffchainConfigDigester - OffchainKeyring ocr2types.OffchainKeyring - OnchainKeyring ocr3types.OnchainKeyring[llotypes.ReportInfo] - LocalConfig ocr2types.LocalConfig + // One Oracle will be started for each ContractConfigTracker + ContractConfigTrackers []ocr2types.ContractConfigTracker + ContractTransmitter ocr3types.ContractTransmitter[llotypes.ReportInfo] + Database ocr3types.Database + MonitoringEndpoint ocrcommontypes.MonitoringEndpoint + OffchainConfigDigester ocr2types.OffchainConfigDigester + OffchainKeyring ocr2types.OffchainKeyring + OnchainKeyring ocr3types.OnchainKeyring[llotypes.ReportInfo] + LocalConfig ocr2types.LocalConfig } func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { + lggr := logger.Sugared(cfg.Logger).With("jobName", cfg.JobName.ValueOrZero()) if cfg.DataSource == nil { return nil, errors.New("DataSource must not be nil") } @@ -76,51 +83,82 @@ func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { if cfg.Registry == nil { return nil, errors.New("Registry must not be nil") } - codecs := make(map[llotypes.ReportFormat]llo.ReportCodec) - - // NOTE: All codecs must be specified here - codecs[llotypes.ReportFormatJSON] = llo.JSONReportCodec{} + if cfg.RetirementReportCache == nil { + return nil, errors.New("RetirementReportCache must not be nil") + } + if cfg.ShouldRetireCache == nil { + return nil, errors.New("ShouldRetireCache must not be nil") + } + reportCodecs := NewReportCodecs() - // TODO: Do these services need starting? - // https://smartcontract-it.atlassian.net/browse/MERC-3386 - prrc := llo.NewPredecessorRetirementReportCache() - src := llo.NewShouldRetireCache() - ds := newDataSource(cfg.Logger.Named("DataSource"), cfg.Registry) + var t TelemeterService + if cfg.CaptureEATelemetry { + t = NewTelemeterService(lggr, cfg.MonitoringEndpoint) + } else { + t = NullTelemeter + } + ds := newDataSource(logger.Named(lggr, "DataSource"), cfg.Registry, t) - return &delegate{services.StateMachine{}, cfg, codecs, prrc, src, ds, nil}, nil + return &delegate{services.StateMachine{}, cfg, reportCodecs, cfg.ShouldRetireCache, ds, t, []Closer{}}, nil } func (d *delegate) Start(ctx context.Context) error { return d.StartOnce("LLODelegate", func() error { // create the oracle from config values - oracle, err := ocr2plus.NewOracle(ocr2plus.OCR3OracleArgs[llotypes.ReportInfo]{ - BinaryNetworkEndpointFactory: d.cfg.BinaryNetworkEndpointFactory, - V2Bootstrappers: d.cfg.V2Bootstrappers, - ContractConfigTracker: d.cfg.ContractConfigTracker, - ContractTransmitter: d.cfg.ContractTransmitter, - Database: d.cfg.Database, - LocalConfig: d.cfg.LocalConfig, - Logger: d.cfg.OCRLogger, - MonitoringEndpoint: d.cfg.MonitoringEndpoint, - OffchainConfigDigester: d.cfg.OffchainConfigDigester, - OffchainKeyring: d.cfg.OffchainKeyring, - OnchainKeyring: d.cfg.OnchainKeyring, - ReportingPluginFactory: llo.NewPluginFactory( - d.cfg.ReportingPluginConfig, d.prrc, d.src, d.cfg.ChannelDefinitionCache, d.ds, d.cfg.Logger.Named("LLOReportingPlugin"), d.codecs, - ), - MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": d.cfg.JobName.ValueOrZero()}, prometheus.DefaultRegisterer), - }) - - if err != nil { - return fmt.Errorf("%w: failed to create new OCR oracle", err) + if !(len(d.cfg.ContractConfigTrackers) == 1 || len(d.cfg.ContractConfigTrackers) == 2) { + return fmt.Errorf("expected either 1 or 2 ContractConfigTrackers, got: %d", len(d.cfg.ContractConfigTrackers)) + } + var merr error + psrrc := NewPluginScopedRetirementReportCache(d.cfg.RetirementReportCache, d.cfg.OnchainKeyring, d.cfg.RetirementReportCodec) + for i, configTracker := range d.cfg.ContractConfigTrackers { + lggr := logger.Named(d.cfg.Logger, fmt.Sprintf("%d", i)) + switch i { + case 0: + lggr = logger.With(lggr, "instanceType", "Blue") + case 1: + lggr = logger.With(lggr, "instanceType", "Green") + } + ocrLogger := logger.NewOCRWrapper(lggr, d.cfg.TraceLogging, func(msg string) { + // TODO: do we actually need to DB-persist errors? + // MERC-3524 + }) + + oracle, err := ocr2plus.NewOracle(ocr2plus.OCR3OracleArgs[llotypes.ReportInfo]{ + BinaryNetworkEndpointFactory: d.cfg.BinaryNetworkEndpointFactory, + V2Bootstrappers: d.cfg.V2Bootstrappers, + ContractConfigTracker: configTracker, + ContractTransmitter: d.cfg.ContractTransmitter, + Database: d.cfg.Database, + LocalConfig: d.cfg.LocalConfig, + Logger: ocrLogger, + MonitoringEndpoint: d.cfg.MonitoringEndpoint, + OffchainConfigDigester: d.cfg.OffchainConfigDigester, + OffchainKeyring: d.cfg.OffchainKeyring, + OnchainKeyring: d.cfg.OnchainKeyring, + ReportingPluginFactory: datastreamsllo.NewPluginFactory( + d.cfg.ReportingPluginConfig, psrrc, d.src, d.cfg.RetirementReportCodec, d.cfg.ChannelDefinitionCache, d.ds, logger.Named(lggr, "LLOReportingPlugin"), llo.EVMOnchainConfigCodec{}, d.reportCodecs, + ), + MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": d.cfg.JobName.ValueOrZero()}, prometheus.DefaultRegisterer), + }) + + if err != nil { + return fmt.Errorf("%w: failed to create new OCR oracle", err) + } + + d.oracles = append(d.oracles, oracle) + + merr = errors.Join(merr, oracle.Start()) } - d.oracle = oracle - - return oracle.Start() + return merr }) } func (d *delegate) Close() error { - return d.StopOnce("LLODelegate", d.oracle.Close) + return d.StopOnce("LLODelegate", func() (err error) { + for _, oracle := range d.oracles { + err = errors.Join(err, oracle.Close()) + } + return err + }) } diff --git a/core/services/llo/evm/fees.go b/core/services/llo/evm/fees.go new file mode 100644 index 00000000000..b74d68b08d2 --- /dev/null +++ b/core/services/llo/evm/fees.go @@ -0,0 +1,31 @@ +package evm + +import ( + "math/big" + + "github.com/shopspring/decimal" +) + +// FeeScalingFactor indicates the multiplier applied to fees. +// e.g. for a 1e18 multiplier, a LINK fee of 7.42 will be represented as 7.42e18 +// This is what will be baked into the report for use on-chain. +var FeeScalingFactor = decimal.NewFromInt(1e18) + +// NOTE: Inexact divisions will have this degree of precision +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() { + // zero fee if token price or base fee is zero + return big.NewInt(0) + } + + // fee denominated in token + fee := baseUSDFee.DivRound(tokenPriceInUSD, Precision) + + // fee scaled up + fee = fee.Mul(FeeScalingFactor) + + return fee.BigInt() +} diff --git a/core/services/llo/evm/fees_test.go b/core/services/llo/evm/fees_test.go new file mode 100644 index 00000000000..16ee98db7df --- /dev/null +++ b/core/services/llo/evm/fees_test.go @@ -0,0 +1,45 @@ +package evm + +import ( + "math/big" + "testing" + + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_Fees(t *testing.T) { + BaseUSDFee, err := decimal.NewFromString("0.70") + require.NoError(t, err) + t.Run("with token price > 1", func(t *testing.T) { + tokenPriceInUSD := decimal.NewFromInt32(1630) + fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) + expectedFee := big.NewInt(429447852760736) + if fee.Cmp(expectedFee) != 0 { + t.Errorf("Expected fee to be %v, got %v", expectedFee, fee) + } + }) + + t.Run("with token price < 1", func(t *testing.T) { + tokenPriceInUSD := decimal.NewFromFloat32(0.4) + fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) + expectedFee := big.NewInt(1750000000000000000) + if fee.Cmp(expectedFee) != 0 { + t.Errorf("Expected fee to be %v, got %v", expectedFee, fee) + } + }) + + t.Run("with token price == 0", func(t *testing.T) { + tokenPriceInUSD := decimal.NewFromInt32(0) + fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) + assert.Equal(t, big.NewInt(0), fee) + }) + + t.Run("with base fee == 0", func(t *testing.T) { + tokenPriceInUSD := decimal.NewFromInt32(123) + BaseUSDFee = decimal.NewFromInt32(0) + fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) + assert.Equal(t, big.NewInt(0), fee) + }) +} diff --git a/core/services/llo/evm/report_codec.go b/core/services/llo/evm/report_codec.go index b5e13065843..b5a4ef9ffa7 100644 --- a/core/services/llo/evm/report_codec.go +++ b/core/services/llo/evm/report_codec.go @@ -1,6 +1,7 @@ package evm import ( + "context" "errors" "fmt" @@ -48,6 +49,6 @@ func NewReportCodec() ReportCodec { return ReportCodec{} } -func (ReportCodec) Encode(report llo.Report, cd llotypes.ChannelDefinition) ([]byte, error) { +func (ReportCodec) Encode(ctx context.Context, report llo.Report, cd llotypes.ChannelDefinition) ([]byte, error) { return nil, errors.New("not implemented") } diff --git a/core/services/llo/evm/report_codec_premium_legacy.go b/core/services/llo/evm/report_codec_premium_legacy.go new file mode 100644 index 00000000000..572340e53f9 --- /dev/null +++ b/core/services/llo/evm/report_codec_premium_legacy.go @@ -0,0 +1,176 @@ +package evm + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/shopspring/decimal" + + "github.com/smartcontractkit/libocr/offchainreporting2/chains/evmutil" + "github.com/smartcontractkit/libocr/offchainreporting2/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" + "github.com/smartcontractkit/chainlink-data-streams/llo" + + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" + reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" + reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" +) + +var ( + _ llo.ReportCodec = ReportCodecPremiumLegacy{} +) + +type ReportCodecPremiumLegacy struct{ logger.Logger } + +func NewReportCodecPremiumLegacy(lggr logger.Logger) llo.ReportCodec { + return ReportCodecPremiumLegacy{lggr.Named("ReportCodecPremiumLegacy")} +} + +type ReportFormatEVMPremiumLegacyOpts 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"` + // Multiplier is used to scale the bid, benchmark and ask values in the + // report. If not specified, or zero is used, a multiplier of 1 is assumed. + Multiplier *ubig.Big `json:"multiplier"` +} + +func (r *ReportFormatEVMPremiumLegacyOpts) Decode(opts []byte) error { + if len(opts) == 0 { + // special case if opts are unspecified, just use the zero options rather than erroring + return nil + } + return json.Unmarshal(opts, r) +} + +func (r ReportCodecPremiumLegacy) Encode(ctx context.Context, report llo.Report, cd llotypes.ChannelDefinition) ([]byte, error) { + if report.Specimen { + return nil, errors.New("ReportCodecPremiumLegacy does not support encoding specimen reports") + } + nativePrice, linkPrice, quote, err := ExtractReportValues(report) + if err != nil { + return nil, fmt.Errorf("ReportCodecPremiumLegacy cannot encode; got unusable report; %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 := ReportFormatEVMPremiumLegacyOpts{} + if err := (&opts).Decode(cd.Opts); err != nil { + return nil, fmt.Errorf("failed to decode opts; got: '%s'; %w", cd.Opts, err) + } + var multiplier decimal.Decimal + if opts.Multiplier == nil { + multiplier = decimal.NewFromInt(1) + } else if opts.Multiplier.IsZero() { + return nil, errors.New("multiplier, if specified in channel opts, must be non-zero") + } else { + multiplier = decimal.NewFromBigInt(opts.Multiplier.ToInt(), 0) + } + + codec := reportcodecv3.NewReportCodec(opts.FeedID, r.Logger) + + rf := v3.ReportFields{ + ValidFromTimestamp: report.ValidAfterSeconds + 1, + Timestamp: report.ObservationTimestampSeconds, + NativeFee: CalculateFee(nativePrice.Decimal(), opts.BaseUSDFee), + LinkFee: CalculateFee(linkPrice.Decimal(), opts.BaseUSDFee), + ExpiresAt: report.ObservationTimestampSeconds + opts.ExpirationWindow, + BenchmarkPrice: quote.Benchmark.Mul(multiplier).BigInt(), + Bid: quote.Bid.Mul(multiplier).BigInt(), + Ask: quote.Ask.Mul(multiplier).BigInt(), + } + return codec.BuildReport(ctx, rf) +} + +func (r ReportCodecPremiumLegacy) Decode(b []byte) (*reporttypes.Report, error) { + codec := reportcodecv3.NewReportCodec([32]byte{}, r.Logger) + return codec.Decode(b) +} + +// Pack assembles the report values into a payload for verifying on-chain +func (r ReportCodecPremiumLegacy) Pack(digest types.ConfigDigest, seqNr uint64, report ocr2types.Report, sigs []types.AttributedOnchainSignature) ([]byte, error) { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + for i, as := range sigs { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + return nil, fmt.Errorf("eventTransmit(ev): error in SplitSignature: %w", err) + } + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } + reportCtx := LegacyReportContext(digest, seqNr) + rawReportCtx := evmutil.RawReportContext(reportCtx) + + payload, err := mercury.PayloadTypes.Pack(rawReportCtx, []byte(report), rs, ss, vs) + if err != nil { + return nil, fmt.Errorf("abi.Pack failed; %w", err) + } + return payload, nil +} + +// TODO: Test this +// MERC-3524 +func ExtractReportValues(report llo.Report) (nativePrice, linkPrice *llo.Decimal, quote *llo.Quote, err error) { + if len(report.Values) != 3 { + return nil, nil, nil, fmt.Errorf("ReportCodecPremiumLegacy requires exactly 3 values (NativePrice, LinkPrice, Quote{Bid, Mid, Ask}); got report.Values: %#v", report.Values) + } + var is bool + nativePrice, is = report.Values[0].(*llo.Decimal) + if nativePrice == nil { + // Missing price median will cause a zero fee + nativePrice = llo.ToDecimal(decimal.Zero) + } else if !is { + return nil, nil, nil, fmt.Errorf("ReportCodecPremiumLegacy expects first value to be of type *Decimal; got: %T", report.Values[0]) + } + linkPrice, is = report.Values[1].(*llo.Decimal) + if linkPrice == nil { + // Missing price median will cause a zero fee + linkPrice = llo.ToDecimal(decimal.Zero) + } else if !is { + return nil, nil, nil, fmt.Errorf("ReportCodecPremiumLegacy expects second value to be of type *Decimal; got: %T", report.Values[1]) + } + quote, is = report.Values[2].(*llo.Quote) + if !is { + return nil, nil, nil, fmt.Errorf("ReportCodecPremiumLegacy expects third value to be of type *Quote; got: %T", report.Values[2]) + } + return nativePrice, linkPrice, quote, nil +} + +// TODO: Consider embedding the DON ID here? +// MERC-3524 +var LLOExtraHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001") + +func SeqNrToEpochAndRound(seqNr uint64) (epoch uint32, round uint8) { + // Simulate 256 rounds/epoch + epoch = uint32(seqNr / 256) // nolint + round = uint8(seqNr % 256) // nolint + return +} + +func LegacyReportContext(cd ocr2types.ConfigDigest, seqNr uint64) ocr2types.ReportContext { + epoch, round := SeqNrToEpochAndRound(seqNr) + return ocr2types.ReportContext{ + ReportTimestamp: ocr2types.ReportTimestamp{ + ConfigDigest: cd, + Epoch: uint32(epoch), + Round: uint8(round), + }, + ExtraHash: LLOExtraHash, // ExtraHash is always zero for mercury, we use LLOExtraHash here to differentiate from the legacy plugin + } +} diff --git a/core/services/llo/evm/report_codec_premium_legacy_test.go b/core/services/llo/evm/report_codec_premium_legacy_test.go new file mode 100644 index 00000000000..d88a1fc90ce --- /dev/null +++ b/core/services/llo/evm/report_codec_premium_legacy_test.go @@ -0,0 +1,135 @@ +package evm + +import ( + "fmt" + "math/big" + "testing" + + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + + "github.com/smartcontractkit/chainlink-data-streams/llo" +) + +func newValidPremiumLegacyReport() llo.Report { + return llo.Report{ + ConfigDigest: types.ConfigDigest{1, 2, 3}, + SeqNr: 32, + ChannelID: llotypes.ChannelID(31), + ValidAfterSeconds: 28, + ObservationTimestampSeconds: 34, + Values: []llo.StreamValue{llo.ToDecimal(decimal.NewFromInt(35)), llo.ToDecimal(decimal.NewFromInt(36)), &llo.Quote{Bid: decimal.NewFromInt(37), Benchmark: decimal.NewFromInt(38), Ask: decimal.NewFromInt(39)}}, + Specimen: false, + } +} + +func Test_ReportCodecPremiumLegacy(t *testing.T) { + rc := ReportCodecPremiumLegacy{} + + feedID := [32]uint8{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} + cd := llotypes.ChannelDefinition{Opts: llotypes.ChannelOpts(fmt.Sprintf(`{"baseUSDFee":"10.50","expirationWindow":60,"feedId":"0x%x","multiplier":10}`, feedID))} + + t.Run("Encode errors if no values", func(t *testing.T) { + ctx := tests.Context(t) + _, err := rc.Encode(ctx, llo.Report{}, cd) + require.Error(t, err) + + assert.Contains(t, err.Error(), "ReportCodecPremiumLegacy cannot encode; got unusable report; ReportCodecPremiumLegacy requires exactly 3 values (NativePrice, LinkPrice, Quote{Bid, Mid, Ask}); got report.Values: []llo.StreamValue(nil)") + }) + + t.Run("does not encode specimen reports", func(t *testing.T) { + ctx := tests.Context(t) + report := newValidPremiumLegacyReport() + report.Specimen = true + + _, err := rc.Encode(ctx, report, cd) + require.Error(t, err) + assert.EqualError(t, err, "ReportCodecPremiumLegacy does not support encoding specimen reports") + }) + + t.Run("Encode constructs a report from observations", func(t *testing.T) { + ctx := tests.Context(t) + report := newValidPremiumLegacyReport() + + encoded, err := rc.Encode(ctx, report, cd) + require.NoError(t, err) + + assert.Len(t, encoded, 288) + assert.Equal(t, []byte{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x29, 0xd0, 0x69, 0x18, 0x9e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xc, 0x35, 0x49, 0xbb, 0x7d, 0x2a, 0xab, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x86}, encoded) + + decoded, err := reporttypes.Decode(encoded) + require.NoError(t, err) + assert.Equal(t, feedID, decoded.FeedId) + assert.Equal(t, uint32(34), decoded.ObservationsTimestamp) + assert.Equal(t, big.NewInt(380), decoded.BenchmarkPrice) + assert.Equal(t, big.NewInt(370), decoded.Bid) + assert.Equal(t, big.NewInt(390), decoded.Ask) + assert.Equal(t, uint32(29), decoded.ValidFromTimestamp) + assert.Equal(t, uint32(94), decoded.ExpiresAt) + assert.Equal(t, big.NewInt(291666666666666667), decoded.LinkFee) + assert.Equal(t, big.NewInt(300000000000000000), decoded.NativeFee) + + t.Run("Decode decodes the report", func(t *testing.T) { + decoded, err := rc.Decode(encoded) + require.NoError(t, err) + + assert.Equal(t, &reporttypes.Report{ + FeedId: [32]uint8{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + ObservationsTimestamp: 0x22, + BenchmarkPrice: big.NewInt(380), + Bid: big.NewInt(370), + Ask: big.NewInt(390), + ValidFromTimestamp: 0x1d, + ExpiresAt: uint32(94), + LinkFee: big.NewInt(291666666666666667), + NativeFee: big.NewInt(300000000000000000), + }, decoded) + }) + }) + + t.Run("uses zero values if fees are missing", func(t *testing.T) { + ctx := tests.Context(t) + report := llo.Report{ + Values: []llo.StreamValue{nil, nil, &llo.Quote{Bid: decimal.NewFromInt(37), Benchmark: decimal.NewFromInt(38), Ask: decimal.NewFromInt(39)}}, + } + + encoded, err := rc.Encode(ctx, report, cd) + require.NoError(t, err) + + assert.Len(t, encoded, 288) + assert.Equal(t, []byte{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x86}, encoded) + + decoded, err := rc.Decode(encoded) + require.NoError(t, err) + + assert.Equal(t, feedID, decoded.FeedId) + assert.Equal(t, uint32(0), decoded.ObservationsTimestamp) + assert.Equal(t, big.NewInt(380).String(), decoded.BenchmarkPrice.String()) + assert.Equal(t, big.NewInt(370).String(), decoded.Bid.String()) + assert.Equal(t, big.NewInt(390).String(), decoded.Ask.String()) + assert.Equal(t, uint32(1), decoded.ValidFromTimestamp) + assert.Equal(t, uint32(60), decoded.ExpiresAt) + assert.Equal(t, big.NewInt(0).String(), decoded.LinkFee.String()) + assert.Equal(t, big.NewInt(0).String(), decoded.NativeFee.String()) + }) + + t.Run("Decode errors on invalid report", func(t *testing.T) { + _, err := rc.Decode([]byte{1, 2, 3}) + assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") + + longBad := make([]byte, 64) + for i := 0; i < len(longBad); i++ { + longBad[i] = byte(i) + } + _, err = rc.Decode(longBad) + assert.EqualError(t, err, "failed to decode report: abi: improperly encoded uint32 value") + }) +} diff --git a/core/services/llo/generate.go b/core/services/llo/generate.go new file mode 100644 index 00000000000..ae26d695430 --- /dev/null +++ b/core/services/llo/generate.go @@ -0,0 +1,3 @@ +package llo + +//go:generate protoc --go_out=. --go_opt=paths=source_relative attested_retirement_report.proto diff --git a/core/services/llo/keyring.go b/core/services/llo/keyring.go index 042b5e46258..8137a5ac3da 100644 --- a/core/services/llo/keyring.go +++ b/core/services/llo/keyring.go @@ -1,15 +1,19 @@ package llo import ( + "bytes" "fmt" + "sort" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "golang.org/x/exp/maps" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" ) type LLOOnchainKeyring ocr3types.OnchainKeyring[llotypes.ReportInfo] @@ -17,6 +21,11 @@ type LLOOnchainKeyring ocr3types.OnchainKeyring[llotypes.ReportInfo] var _ LLOOnchainKeyring = &onchainKeyring{} type Key interface { + // Legacy Sign/Verify methods needed for v0.3 report compatibility + // New keys can leave these stubbed + Sign(reportCtx ocrtypes.ReportContext, report ocrtypes.Report) ([]byte, error) + Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signature []byte) bool + Sign3(digest ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report) (signature []byte, err error) Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool PublicKey() ocrtypes.OnchainPublicKey @@ -35,12 +44,29 @@ func NewOnchainKeyring(lggr logger.Logger, keys map[llotypes.ReportFormat]Key) L } func (okr *onchainKeyring) PublicKey() types.OnchainPublicKey { - // All public keys combined - var pk []byte - for _, k := range okr.keys { - pk = append(pk, k.PublicKey()...) + // All unique public keys sorted in ascending order and combined into one + // byte string + onchainPublicKey := []byte{} + + keys := maps.Values(okr.keys) + if len(keys) == 0 { + return onchainPublicKey } - return pk + sort.Slice(keys, func(i, j int) bool { + return bytes.Compare(keys[i].PublicKey(), keys[j].PublicKey()) < 0 + }) + + onchainPublicKey = append(onchainPublicKey, keys[0].PublicKey()...) + if len(keys) == 1 { + return onchainPublicKey + } + for i := 1; i < len(keys); i++ { + if keys[i] != keys[i-1] { + onchainPublicKey = append(onchainPublicKey, keys[i].PublicKey()...) + } + } + + return onchainPublicKey } func (okr *onchainKeyring) MaxSignatureLength() (n int) { @@ -52,17 +78,37 @@ func (okr *onchainKeyring) MaxSignatureLength() (n int) { } func (okr *onchainKeyring) Sign(digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo]) (signature []byte, err error) { - rf := r.Info.ReportFormat - if key, exists := okr.keys[rf]; exists { - return key.Sign3(digest, seqNr, r.Report) + switch r.Info.ReportFormat { + case llotypes.ReportFormatEVMPremiumLegacy: + rf := r.Info.ReportFormat + if key, exists := okr.keys[rf]; exists { + // NOTE: Must use legacy Sign method for compatibility with v0.3 report verification + rc := evm.LegacyReportContext(digest, seqNr) + return key.Sign(rc, r.Report) + } + default: + rf := r.Info.ReportFormat + if key, exists := okr.keys[rf]; exists { + return key.Sign3(digest, seqNr, r.Report) + } } return nil, fmt.Errorf("Sign failed; unsupported report format: %q", r.Info.ReportFormat) } func (okr *onchainKeyring) Verify(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool { - rf := r.Info.ReportFormat - if verifier, exists := okr.keys[rf]; exists { - return verifier.Verify3(key, digest, seqNr, r.Report, signature) + switch r.Info.ReportFormat { + case llotypes.ReportFormatEVMPremiumLegacy: + rf := r.Info.ReportFormat + if verifier, exists := okr.keys[rf]; exists { + // NOTE: Must use legacy Verify method for compatibility with v0.3 report verification + rc := evm.LegacyReportContext(digest, seqNr) + return verifier.Verify(key, rc, r.Report, signature) + } + default: + rf := r.Info.ReportFormat + if verifier, exists := okr.keys[rf]; exists { + return verifier.Verify3(key, digest, seqNr, r.Report, signature) + } } okr.lggr.Errorf("Verify failed; unsupported report format: %q", r.Info.ReportFormat) return false diff --git a/core/services/llo/keyring_test.go b/core/services/llo/keyring_test.go new file mode 100644 index 00000000000..44371e14967 --- /dev/null +++ b/core/services/llo/keyring_test.go @@ -0,0 +1,115 @@ +package llo + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + ocr3types "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var _ Key = &mockKey{} + +type mockKey struct { + format llotypes.ReportFormat + verify bool + maxSignatureLen int + sig []byte +} + +func (m *mockKey) Sign(reportCtx ocrtypes.ReportContext, report ocrtypes.Report) ([]byte, error) { + return m.sig, nil +} + +func (m *mockKey) Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signature []byte) bool { + return m.verify +} + +func (m *mockKey) Sign3(digest ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report) (signature []byte, err error) { + return m.sig, nil +} + +func (m *mockKey) Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { + return m.verify +} + +func (m *mockKey) PublicKey() ocrtypes.OnchainPublicKey { + b := make([]byte, m.maxSignatureLen) + for i := 0; i < m.maxSignatureLen; i++ { + b[i] = byte(255) + } + return ocrtypes.OnchainPublicKey(b) +} + +func (m *mockKey) MaxSignatureLength() int { + return m.maxSignatureLen +} + +func (m *mockKey) reset(format llotypes.ReportFormat) { + m.format = format + m.verify = false +} + +func Test_Keyring(t *testing.T) { + lggr := logger.TestLogger(t) + + ks := map[llotypes.ReportFormat]Key{ + llotypes.ReportFormatEVMPremiumLegacy: &mockKey{format: llotypes.ReportFormatEVMPremiumLegacy, maxSignatureLen: 1, sig: []byte("sig-1")}, + llotypes.ReportFormatJSON: &mockKey{format: llotypes.ReportFormatJSON, maxSignatureLen: 2, sig: []byte("sig-2")}, + } + + kr := NewOnchainKeyring(lggr, ks) + + cases := []struct { + format llotypes.ReportFormat + }{ + { + llotypes.ReportFormatEVMPremiumLegacy, + }, + { + llotypes.ReportFormatJSON, + }, + } + + cd, err := ocrtypes.BytesToConfigDigest(testutils.MustRandBytes(32)) + require.NoError(t, err) + seqNr := rand.Uint64() + t.Run("Sign+Verify", func(t *testing.T) { + for _, tc := range cases { + t.Run(tc.format.String(), func(t *testing.T) { + k := ks[tc.format] + defer k.(*mockKey).reset(tc.format) + + sig, err := kr.Sign(cd, seqNr, ocr3types.ReportWithInfo[llotypes.ReportInfo]{Info: llotypes.ReportInfo{ReportFormat: tc.format}}) + require.NoError(t, err) + + assert.Equal(t, []byte(fmt.Sprintf("sig-%d", tc.format)), sig) + + assert.False(t, kr.Verify(nil, cd, seqNr, ocr3types.ReportWithInfo[llotypes.ReportInfo]{Info: llotypes.ReportInfo{ReportFormat: tc.format}}, sig)) + + k.(*mockKey).verify = true + }) + } + }) + + t.Run("MaxSignatureLength", func(t *testing.T) { + assert.Equal(t, 2+1, kr.MaxSignatureLength()) + }) + t.Run("PublicKey", func(t *testing.T) { + b := make([]byte, 2+1) + for i := 0; i < len(b); i++ { + b[i] = byte(255) + } + assert.Equal(t, types.OnchainPublicKey(b), kr.PublicKey()) + }) +} diff --git a/core/services/llo/mercurytransmitter/helpers_test.go b/core/services/llo/mercurytransmitter/helpers_test.go new file mode 100644 index 00000000000..060c07bef45 --- /dev/null +++ b/core/services/llo/mercurytransmitter/helpers_test.go @@ -0,0 +1,47 @@ +package mercurytransmitter + +import ( + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" +) + +func makeSampleReport() ocr3types.ReportWithInfo[llotypes.ReportInfo] { + return ocr3types.ReportWithInfo[llotypes.ReportInfo]{ + Report: ocrtypes.Report{1, 2, 3}, + Info: llotypes.ReportInfo{ + LifeCycleStage: llotypes.LifeCycleStage("production"), + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + }, + } +} + +func makeSampleConfigDigest() ocrtypes.ConfigDigest { + return ocrtypes.ConfigDigest{1, 2, 3, 4, 5, 6} +} +func makeSampleTransmission(seqNr uint64) *Transmission { + // valid with seqnr of 3 + return &Transmission{ + ServerURL: "wss://example.com/mercury", + ConfigDigest: types.ConfigDigest{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c}, + SeqNr: seqNr, + Report: ocr3types.ReportWithInfo[llotypes.ReportInfo]{ + Report: ocrtypes.Report{0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0}, + Info: llotypes.ReportInfo{ + LifeCycleStage: llotypes.LifeCycleStage("production"), + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + }, + }, + Sigs: []types.AttributedOnchainSignature{types.AttributedOnchainSignature{Signature: []uint8{0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x1}, Signer: 0x1}, types.AttributedOnchainSignature{Signature: []uint8{0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0, 0x0}, Signer: 0x3}}, + } +} + +func makeSampleTransmissions() []*Transmission { + return []*Transmission{ + makeSampleTransmission(1001), + makeSampleTransmission(1002), + makeSampleTransmission(1003), + } +} diff --git a/core/services/llo/mercurytransmitter/orm.go b/core/services/llo/mercurytransmitter/orm.go new file mode 100644 index 00000000000..ed8c8843f4c --- /dev/null +++ b/core/services/llo/mercurytransmitter/orm.go @@ -0,0 +1,205 @@ +package mercurytransmitter + +import ( + "context" + "errors" + "fmt" + "math" + + "github.com/lib/pq" + + "github.com/smartcontractkit/libocr/commontypes" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" +) + +// ORM is scoped to a single DON ID +type ORM interface { + DonID() uint32 + Insert(ctx context.Context, transmissions []*Transmission) error + Delete(ctx context.Context, hashes [][32]byte) error + Get(ctx context.Context, serverURL string) ([]*Transmission, error) + Prune(ctx context.Context, serverURL string, maxSize int) error + Cleanup(ctx context.Context) error +} + +type orm struct { + ds sqlutil.DataSource + donID uint32 +} + +func NewORM(ds sqlutil.DataSource, donID uint32) ORM { + return &orm{ds: ds, donID: donID} +} + +func (o *orm) DonID() uint32 { + return o.donID +} + +// Insert inserts the transmissions, ignoring duplicates +func (o *orm) Insert(ctx context.Context, transmissions []*Transmission) error { + if len(transmissions) == 0 { + return nil + } + + type transmission struct { + DonID uint32 `db:"don_id"` + ServerURL string `db:"server_url"` + ConfigDigest ocrtypes.ConfigDigest `db:"config_digest"` + SeqNr int64 `db:"seq_nr"` + Report []byte `db:"report"` + LifecycleStage string `db:"lifecycle_stage"` + ReportFormat uint32 `db:"report_format"` + Signatures [][]byte `db:"signatures"` + Signers []uint8 `db:"signers"` + TransmissionHash []byte `db:"transmission_hash"` + } + records := make([]transmission, len(transmissions)) + for i, t := range transmissions { + signatures := make([][]byte, len(t.Sigs)) + signers := make([]uint8, len(t.Sigs)) + for j, sig := range t.Sigs { + signatures[j] = sig.Signature + signers[j] = uint8(sig.Signer) + } + h := t.Hash() + if t.SeqNr > math.MaxInt64 { + // this is to appease the linter but shouldn't ever happen + return fmt.Errorf("seqNr is too large (got: %d, max: %d)", t.SeqNr, math.MaxInt64) + } + records[i] = transmission{ + DonID: o.donID, + ServerURL: t.ServerURL, + ConfigDigest: t.ConfigDigest, + SeqNr: int64(t.SeqNr), //nolint + Report: t.Report.Report, + LifecycleStage: string(t.Report.Info.LifeCycleStage), + ReportFormat: uint32(t.Report.Info.ReportFormat), + Signatures: signatures, + Signers: signers, + TransmissionHash: h[:], + } + } + + _, err := o.ds.NamedExecContext(ctx, ` + INSERT INTO llo_mercury_transmit_queue (don_id, server_url, config_digest, seq_nr, report, lifecycle_stage, report_format, signatures, signers, transmission_hash) + VALUES (:don_id, :server_url, :config_digest, :seq_nr, :report, :lifecycle_stage, :report_format, :signatures, :signers, :transmission_hash) + ON CONFLICT (transmission_hash) DO NOTHING + `, records) + + if err != nil { + return fmt.Errorf("llo orm: failed to insert transmissions: %w", err) + } + return nil +} + +// Delete deletes the given transmissions +func (o *orm) Delete(ctx context.Context, hashes [][32]byte) error { + if len(hashes) == 0 { + return nil + } + + var pqHashes pq.ByteaArray + for _, hash := range hashes { + pqHashes = append(pqHashes, hash[:]) + } + + _, err := o.ds.ExecContext(ctx, ` + DELETE FROM llo_mercury_transmit_queue + WHERE transmission_hash = ANY($1) + `, pqHashes) + if err != nil { + return fmt.Errorf("llo orm: failed to delete transmissions: %w", err) + } + return nil +} + +// Get returns all transmissions in chronologically descending order +func (o *orm) Get(ctx context.Context, serverURL string) ([]*Transmission, error) { + // The priority queue uses seqnr to sort transmissions so order by + // the same fields here for optimal insertion into the pq. + rows, err := o.ds.QueryContext(ctx, ` + SELECT config_digest, seq_nr, report, lifecycle_stage, report_format, signatures, signers + FROM llo_mercury_transmit_queue + WHERE don_id = $1 AND server_url = $2 + ORDER BY seq_nr DESC, transmission_hash DESC + `, o.donID, serverURL) + if err != nil { + return nil, fmt.Errorf("llo orm: failed to get transmissions: %w", err) + } + defer rows.Close() + + var transmissions []*Transmission + for rows.Next() { + transmission := Transmission{ + ServerURL: serverURL, + } + var digest []byte + var signatures pq.ByteaArray + var signers pq.Int32Array + + err := rows.Scan( + &digest, + &transmission.SeqNr, + &transmission.Report.Report, + &transmission.Report.Info.LifeCycleStage, + &transmission.Report.Info.ReportFormat, + &signatures, + &signers, + ) + if err != nil { + return nil, fmt.Errorf("llo orm: failed to scan transmission: %w", err) + } + transmission.ConfigDigest = ocrtypes.ConfigDigest(digest) + if len(signatures) != len(signers) { + return nil, errors.New("signatures and signers must have the same length") + } + for i, sig := range signatures { + if signers[i] > math.MaxUint8 { + // this is to appease the linter but shouldn't ever happen + return nil, fmt.Errorf("signer is too large (got: %d, max: %d)", signers[i], math.MaxUint8) + } + transmission.Sigs = append(transmission.Sigs, ocrtypes.AttributedOnchainSignature{ + Signature: sig, + Signer: commontypes.OracleID(signers[i]), //nolint + }) + } + + transmissions = append(transmissions, &transmission) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("llo orm: failed to scan transmissions: %w", err) + } + + return transmissions, nil +} + +// Prune keeps at most maxSize rows for the given job ID, +// deleting the oldest transactions. +func (o *orm) Prune(ctx context.Context, serverURL string, maxSize int) error { + // Prune the oldest requests by epoch and round. + _, err := o.ds.ExecContext(ctx, ` + DELETE FROM llo_mercury_transmit_queue + WHERE don_id = $1 AND server_url = $2 AND + transmission_hash NOT IN ( + SELECT transmission_hash + FROM llo_mercury_transmit_queue + WHERE don_id = $1 AND server_url = $2 + ORDER BY seq_nr DESC, transmission_hash DESC + LIMIT $3 + ) + `, o.donID, serverURL, maxSize) + if err != nil { + return fmt.Errorf("llo orm: failed to prune transmissions: %w", err) + } + return nil +} + +func (o *orm) Cleanup(ctx context.Context) error { + _, err := o.ds.ExecContext(ctx, `DELETE FROM llo_mercury_transmit_queue WHERE don_id = $1`, o.donID) + if err != nil { + return fmt.Errorf("llo orm: failed to cleanup transmissions: %w", err) + } + return nil +} diff --git a/core/services/llo/mercurytransmitter/orm_test.go b/core/services/llo/mercurytransmitter/orm_test.go new file mode 100644 index 00000000000..73d5760a9a3 --- /dev/null +++ b/core/services/llo/mercurytransmitter/orm_test.go @@ -0,0 +1,89 @@ +package mercurytransmitter + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" +) + +var ( + sURL = "wss://example.com/mercury" + sURL2 = "wss://mercuryserver.test" + sURL3 = "wss://mercuryserver.example/foo" +) + +func TestORM(t *testing.T) { + ctx := testutils.Context(t) + db := pgtest.NewSqlxDB(t) + + donID := uint32(654321) + orm := NewORM(db, donID) + + t.Run("DonID", func(t *testing.T) { + assert.Equal(t, donID, orm.DonID()) + }) + + transmissions := makeSampleTransmissions()[:2] + + t.Run("Insert", func(t *testing.T) { + err := orm.Insert(ctx, transmissions) + require.NoError(t, err) + }) + t.Run("Get", func(t *testing.T) { + result, err := orm.Get(ctx, sURL) + require.NoError(t, err) + + assert.ElementsMatch(t, transmissions, result) + + result, err = orm.Get(ctx, "other server url") + require.NoError(t, err) + + assert.Empty(t, result) + }) + t.Run("Delete", func(t *testing.T) { + err := orm.Delete(ctx, [][32]byte{transmissions[0].Hash()}) + require.NoError(t, err) + + result, err := orm.Get(ctx, sURL) + require.NoError(t, err) + + require.Len(t, result, 1) + assert.Equal(t, transmissions[1], result[0]) + + err = orm.Delete(ctx, [][32]byte{transmissions[1].Hash()}) + require.NoError(t, err) + + result, err = orm.Get(ctx, sURL) + require.NoError(t, err) + require.Len(t, result, 0) + }) + t.Run("Prune", func(t *testing.T) { + err := orm.Insert(ctx, transmissions) + require.NoError(t, err) + + err = orm.Prune(ctx, sURL, 1) + require.NoError(t, err) + + result, err := orm.Get(ctx, sURL) + require.NoError(t, err) + require.Len(t, result, 1) + assert.Equal(t, transmissions[1], result[0]) + + err = orm.Prune(ctx, sURL, 1) + require.NoError(t, err) + result, err = orm.Get(ctx, sURL) + require.NoError(t, err) + require.Len(t, result, 1) + assert.Equal(t, transmissions[1], result[0]) + + err = orm.Prune(ctx, sURL, 0) + require.NoError(t, err) + result, err = orm.Get(ctx, sURL) + require.NoError(t, err) + require.Len(t, result, 0) + }) +} diff --git a/core/services/llo/mercurytransmitter/persistence_manager.go b/core/services/llo/mercurytransmitter/persistence_manager.go new file mode 100644 index 00000000000..eb36a7d1b80 --- /dev/null +++ b/core/services/llo/mercurytransmitter/persistence_manager.go @@ -0,0 +1,143 @@ +package mercurytransmitter + +import ( + "context" + "sync" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" +) + +var ( + flushDeletesFrequency = time.Second + pruneFrequency = time.Hour +) + +// persistenceManager scopes an ORM to a single serverURL and handles cleanup +// and asynchronous deletion +type persistenceManager struct { + lggr logger.Logger + orm ORM + serverURL string + + once services.StateMachine + stopCh services.StopChan + wg sync.WaitGroup + + deleteMu sync.Mutex + deleteQueue [][32]byte + + maxTransmitQueueSize int + flushDeletesFrequency time.Duration + pruneFrequency time.Duration +} + +func NewPersistenceManager(lggr logger.Logger, orm ORM, serverURL string, maxTransmitQueueSize int, flushDeletesFrequency, pruneFrequency time.Duration) *persistenceManager { + return &persistenceManager{ + orm: orm, + lggr: logger.Sugared(lggr).Named("LLOPersistenceManager").With("serverURL", serverURL), + serverURL: serverURL, + stopCh: make(services.StopChan), + maxTransmitQueueSize: maxTransmitQueueSize, + flushDeletesFrequency: flushDeletesFrequency, + pruneFrequency: pruneFrequency, + } +} + +func (pm *persistenceManager) Start(ctx context.Context) error { + return pm.once.StartOnce("LLOMercuryPersistenceManager", func() error { + pm.wg.Add(2) + go pm.runFlushDeletesLoop() + go pm.runPruneLoop() + return nil + }) +} + +func (pm *persistenceManager) Close() error { + return pm.once.StopOnce("LLOMercuryPersistenceManager", func() error { + close(pm.stopCh) + pm.wg.Wait() + return nil + }) +} + +func (pm *persistenceManager) DonID() uint32 { + return pm.orm.DonID() +} + +func (pm *persistenceManager) AsyncDelete(hash [32]byte) { + pm.addToDeleteQueue(hash) +} + +func (pm *persistenceManager) Load(ctx context.Context) ([]*Transmission, error) { + return pm.orm.Get(ctx, pm.serverURL) +} + +func (pm *persistenceManager) runFlushDeletesLoop() { + defer pm.wg.Done() + + ctx, cancel := pm.stopCh.Ctx(context.Background()) + defer cancel() + + ticker := services.NewTicker(pm.flushDeletesFrequency) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + queuedTransmissionHashes := pm.resetDeleteQueue() + if len(queuedTransmissionHashes) == 0 { + continue + } + if err := pm.orm.Delete(ctx, queuedTransmissionHashes); err != nil { + pm.lggr.Errorw("Failed to delete queued transmit requests", "err", err) + pm.addToDeleteQueue(queuedTransmissionHashes...) + } else { + pm.lggr.Debugw("Deleted queued transmit requests") + } + } + } +} + +func (pm *persistenceManager) runPruneLoop() { + defer pm.wg.Done() + + ctx, cancel := pm.stopCh.NewCtx() + defer cancel() + + ticker := services.NewTicker(pm.pruneFrequency) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + func(ctx context.Context) { + ctx, cancelPrune := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancelPrune() + if err := pm.orm.Prune(ctx, pm.serverURL, pm.maxTransmitQueueSize); err != nil { + pm.lggr.Errorw("Failed to prune transmit requests table", "err", err) + } else { + pm.lggr.Debugw("Pruned transmit requests table") + } + }(ctx) + } + } +} + +func (pm *persistenceManager) addToDeleteQueue(hashes ...[32]byte) { + pm.deleteMu.Lock() + defer pm.deleteMu.Unlock() + pm.deleteQueue = append(pm.deleteQueue, hashes...) +} + +func (pm *persistenceManager) resetDeleteQueue() [][32]byte { + pm.deleteMu.Lock() + defer pm.deleteMu.Unlock() + queue := pm.deleteQueue + pm.deleteQueue = nil + return queue +} diff --git a/core/services/llo/mercurytransmitter/persistence_manager_test.go b/core/services/llo/mercurytransmitter/persistence_manager_test.go new file mode 100644 index 00000000000..b05de429ade --- /dev/null +++ b/core/services/llo/mercurytransmitter/persistence_manager_test.go @@ -0,0 +1,127 @@ +package mercurytransmitter + +import ( + "testing" + "time" + + "github.com/jmoiron/sqlx" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest/observer" + + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func bootstrapPersistenceManager(t *testing.T, donID uint32, db *sqlx.DB) (*persistenceManager, *observer.ObservedLogs) { + t.Helper() + lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) + orm := NewORM(db, donID) + return NewPersistenceManager(lggr, orm, "wss://example.com/mercury", 2, 5*time.Millisecond, 5*time.Millisecond), observedLogs +} + +func TestPersistenceManager(t *testing.T) { + donID1 := uint32(1234) + donID2 := uint32(2345) + + ctx := testutils.Context(t) + db := pgtest.NewSqlxDB(t) + pm, _ := bootstrapPersistenceManager(t, donID1, db) + + transmissions := makeSampleTransmissions() + err := pm.orm.Insert(ctx, transmissions) + require.NoError(t, err) + + result, err := pm.Load(ctx) + require.NoError(t, err) + assert.ElementsMatch(t, transmissions, result) + + err = pm.orm.Delete(ctx, [][32]byte{transmissions[0].Hash()}) + require.NoError(t, err) + + t.Run("scopes load to only transmissions with matching don ID", func(t *testing.T) { + pm2, _ := bootstrapPersistenceManager(t, donID2, db) + result, err = pm2.Load(ctx) + require.NoError(t, err) + + assert.Len(t, result, 0) + }) +} + +func TestPersistenceManagerAsyncDelete(t *testing.T) { + ctx := testutils.Context(t) + donID := uint32(1234) + db := pgtest.NewSqlxDB(t) + pm, observedLogs := bootstrapPersistenceManager(t, donID, db) + + transmissions := makeSampleTransmissions() + err := pm.orm.Insert(ctx, transmissions) + require.NoError(t, err) + + servicetest.Run(t, pm) + + pm.AsyncDelete(transmissions[0].Hash()) + + // Wait for next poll. + observedLogs.TakeAll() + testutils.WaitForLogMessage(t, observedLogs, "Deleted queued transmit requests") + + result, err := pm.Load(ctx) + require.NoError(t, err) + require.Len(t, result, 2) + assert.ElementsMatch(t, transmissions[1:], result) +} + +func TestPersistenceManagerPrune(t *testing.T) { + donID1 := uint32(123456) + donID2 := uint32(654321) + db := pgtest.NewSqlxDB(t) + + ctx := testutils.Context(t) + + transmissions := make([]*Transmission, 45) + for i := uint64(0); i < 45; i++ { + transmissions[i] = makeSampleTransmission(i) + } + + pm, _ := bootstrapPersistenceManager(t, donID1, db) + err := pm.orm.Insert(ctx, transmissions[:25]) + require.NoError(t, err) + + pm2, _ := bootstrapPersistenceManager(t, donID2, db) + err = pm2.orm.Insert(ctx, transmissions[25:]) + require.NoError(t, err) + + pm, observedLogs := bootstrapPersistenceManager(t, donID1, db) + + err = pm.Start(ctx) + require.NoError(t, err) + + // Wait for next poll. + observedLogs.TakeAll() + testutils.WaitForLogMessage(t, observedLogs, "Pruned transmit requests table") + + result, err := pm.Load(ctx) + require.NoError(t, err) + require.ElementsMatch(t, transmissions[23:25], result) + + // Test pruning stops after Close. + err = pm.Close() + require.NoError(t, err) + + err = pm.orm.Insert(ctx, transmissions) + require.NoError(t, err) + + result, err = pm.Load(ctx) + require.NoError(t, err) + require.Len(t, result, 25) + + t.Run("prune was scoped to don ID", func(t *testing.T) { + result, err = pm2.Load(ctx) + require.NoError(t, err) + assert.Len(t, result, 20) + }) +} diff --git a/core/services/llo/mercurytransmitter/queue.go b/core/services/llo/mercurytransmitter/queue.go new file mode 100644 index 00000000000..a5a606c5b32 --- /dev/null +++ b/core/services/llo/mercurytransmitter/queue.go @@ -0,0 +1,250 @@ +package mercurytransmitter + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + heap "github.com/esote/minmaxheap" + "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" +) + +type asyncDeleter interface { + AsyncDelete(hash [32]byte) + DonID() uint32 +} + +var _ services.Service = (*transmitQueue)(nil) + +var transmitQueueLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "llo_transmit_queue_load", + Help: "Current count of items in the transmit queue", +}, + []string{"donID", "serverURL", "capacity"}, +) + +// Prometheus' default interval is 15s, set this to under 7.5s to avoid +// aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency) +const promInterval = 6500 * time.Millisecond + +// TransmitQueue is the high-level package that everything outside of this file should be using +// It stores pending transmissions, yielding the latest (highest priority) first to the caller +type transmitQueue struct { + services.StateMachine + + cond sync.Cond + lggr logger.SugaredLogger + asyncDeleter asyncDeleter + mu *sync.RWMutex + + pq *priorityQueue + maxlen int + closed bool + + // monitor loop + stopMonitor func() + transmitQueueLoad prometheus.Gauge +} + +type TransmitQueue interface { + services.Service + + BlockingPop() (t *Transmission) + Push(t *Transmission) (ok bool) + Init(ts []*Transmission) + IsEmpty() bool +} + +// maxlen controls how many items will be stored in the queue +// 0 means unlimited - be careful, this can cause memory leaks +func NewTransmitQueue(lggr logger.Logger, serverURL string, maxlen int, asyncDeleter asyncDeleter) TransmitQueue { + mu := new(sync.RWMutex) + return &transmitQueue{ + services.StateMachine{}, + sync.Cond{L: mu}, + logger.Sugared(lggr).Named("TransmitQueue"), + asyncDeleter, + mu, + nil, // pq needs to be initialized by calling tq.Init before use + maxlen, + false, + nil, + transmitQueueLoad.WithLabelValues(fmt.Sprintf("%d", asyncDeleter.DonID()), serverURL, fmt.Sprintf("%d", maxlen)), + } +} + +func (tq *transmitQueue) Init(ts []*Transmission) { + pq := priorityQueue(ts) + heap.Init(&pq) // ensure the heap is ordered + tq.pq = &pq +} + +func (tq *transmitQueue) Push(t *Transmission) (ok bool) { + tq.cond.L.Lock() + defer tq.cond.L.Unlock() + + if tq.closed { + return false + } + + if tq.maxlen != 0 && tq.pq.Len() == tq.maxlen { + // evict oldest entry to make room + tq.lggr.Criticalf("Transmit queue is full; dropping oldest transmission (reached max length of %d)", tq.maxlen) + removed := heap.PopMax(tq.pq) + if removed, ok := removed.(*Transmission); ok { + tq.asyncDeleter.AsyncDelete(removed.Hash()) + } + } + + heap.Push(tq.pq, t) + tq.cond.Signal() + + return true +} + +// BlockingPop will block until at least one item is in the heap, and then return it +// If the queue is closed, it will immediately return nil +func (tq *transmitQueue) BlockingPop() (t *Transmission) { + tq.cond.L.Lock() + defer tq.cond.L.Unlock() + if tq.closed { + return nil + } + for t = tq.pop(); t == nil; t = tq.pop() { + tq.cond.Wait() + if tq.closed { + return nil + } + } + return t +} + +func (tq *transmitQueue) IsEmpty() bool { + tq.mu.RLock() + defer tq.mu.RUnlock() + return tq.pq.Len() == 0 +} + +func (tq *transmitQueue) Start(context.Context) error { + return tq.StartOnce("TransmitQueue", func() error { + t := services.NewTicker(promInterval) + wg := new(sync.WaitGroup) + chStop := make(chan struct{}) + tq.stopMonitor = func() { + t.Stop() + close(chStop) + wg.Wait() + } + wg.Add(1) + go tq.monitorLoop(t.C, chStop, wg) + return nil + }) +} + +func (tq *transmitQueue) Close() error { + return tq.StopOnce("TransmitQueue", func() error { + tq.cond.L.Lock() + tq.closed = true + tq.cond.L.Unlock() + tq.cond.Broadcast() + tq.stopMonitor() + return nil + }) +} + +func (tq *transmitQueue) monitorLoop(c <-chan time.Time, chStop <-chan struct{}, wg *sync.WaitGroup) { + defer wg.Done() + + for { + select { + case <-c: + tq.report() + case <-chStop: + return + } + } +} + +func (tq *transmitQueue) report() { + tq.mu.RLock() + length := tq.pq.Len() + tq.mu.RUnlock() + tq.transmitQueueLoad.Set(float64(length)) +} + +func (tq *transmitQueue) Ready() error { + return nil +} +func (tq *transmitQueue) Name() string { return tq.lggr.Name() } +func (tq *transmitQueue) HealthReport() map[string]error { + report := map[string]error{tq.Name(): errors.Join( + tq.status(), + )} + return report +} + +func (tq *transmitQueue) status() (merr error) { + tq.mu.RLock() + length := tq.pq.Len() + closed := tq.closed + tq.mu.RUnlock() + if tq.maxlen != 0 && length > (tq.maxlen/2) { + merr = errors.Join(merr, fmt.Errorf("transmit priority queue is greater than 50%% full (%d/%d)", length, tq.maxlen)) + } + if closed { + merr = errors.New("transmit queue is closed") + } + return merr +} + +// pop latest Transmission from the heap +// Not thread-safe +func (tq *transmitQueue) pop() *Transmission { + if tq.pq.Len() == 0 { + return nil + } + return heap.Pop(tq.pq).(*Transmission) +} + +// HEAP +// Adapted from https://pkg.go.dev/container/heap#example-package-PriorityQueue + +// WARNING: None of these methods are thread-safe, caller must synchronize + +var _ heap.Interface = &priorityQueue{} + +type priorityQueue []*Transmission + +func (pq priorityQueue) Len() int { return len(pq) } + +func (pq priorityQueue) Less(i, j int) bool { + // We want Pop to give us the latest round, so we use greater than here + // i.e. a later seqNr is "less" than an earlier one + return pq[i].SeqNr > pq[j].SeqNr +} + +func (pq priorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] +} + +func (pq *priorityQueue) Pop() any { + n := len(*pq) + if n == 0 { + return nil + } + old := *pq + item := old[n-1] + old[n-1] = nil // avoid memory leak + *pq = old[0 : n-1] + return item +} + +func (pq *priorityQueue) Push(x any) { + *pq = append(*pq, x.(*Transmission)) +} diff --git a/core/services/llo/mercurytransmitter/queue_test.go b/core/services/llo/mercurytransmitter/queue_test.go new file mode 100644 index 00000000000..d19d140d6be --- /dev/null +++ b/core/services/llo/mercurytransmitter/queue_test.go @@ -0,0 +1,105 @@ +package mercurytransmitter + +import ( + "sync" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var _ asyncDeleter = &mockAsyncDeleter{} + +type mockAsyncDeleter struct { + donID uint32 + hashes [][32]byte +} + +func (m *mockAsyncDeleter) AsyncDelete(hash [32]byte) { + m.hashes = append(m.hashes, hash) +} +func (m *mockAsyncDeleter) DonID() uint32 { + return m.donID +} + +func Test_Queue(t *testing.T) { + t.Parallel() + lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.ErrorLevel) + testTransmissions := makeSampleTransmissions() + deleter := &mockAsyncDeleter{} + transmitQueue := NewTransmitQueue(lggr, sURL, 7, deleter) + transmitQueue.Init([]*Transmission{}) + + t.Run("successfully add transmissions to transmit queue", func(t *testing.T) { + for _, tt := range testTransmissions { + ok := transmitQueue.Push(tt) + require.True(t, ok) + } + report := transmitQueue.HealthReport() + assert.Nil(t, report[transmitQueue.Name()]) + }) + + t.Run("transmit queue is more than 50% full", func(t *testing.T) { + transmitQueue.Push(testTransmissions[2]) + report := transmitQueue.HealthReport() + assert.Equal(t, report[transmitQueue.Name()].Error(), "transmit priority queue is greater than 50% full (4/7)") + }) + + t.Run("transmit queue pops the highest priority transmission", func(t *testing.T) { + tr := transmitQueue.BlockingPop() + assert.Equal(t, testTransmissions[2], tr) + }) + + t.Run("transmit queue is full and evicts the oldest transmission", func(t *testing.T) { + // add 5 more transmissions to overflow the queue by 1 + for i := 0; i < 5; i++ { + transmitQueue.Push(testTransmissions[1]) + } + + // expecting testTransmissions[0] to get evicted and not present in the queue anymore + testutils.WaitForLogMessage(t, observedLogs, "Transmit queue is full; dropping oldest transmission (reached max length of 7)") + var transmissions []*Transmission + for i := 0; i < 7; i++ { + tr := transmitQueue.BlockingPop() + transmissions = append(transmissions, tr) + } + + assert.NotContains(t, transmissions, testTransmissions[0]) + require.Len(t, deleter.hashes, 1) + assert.Equal(t, testTransmissions[0].Hash(), deleter.hashes[0]) + }) + + t.Run("transmit queue blocks when empty and resumes when tranmission available", func(t *testing.T) { + assert.True(t, transmitQueue.IsEmpty()) + + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + tr := transmitQueue.BlockingPop() + assert.Equal(t, tr, testTransmissions[0]) + }() + go func() { + defer wg.Done() + transmitQueue.Push(testTransmissions[0]) + }() + wg.Wait() + }) + + t.Run("initializes transmissions", func(t *testing.T) { + expected := makeSampleTransmission(1) + transmissions := []*Transmission{ + expected, + } + transmitQueue := NewTransmitQueue(lggr, sURL, 7, deleter) + transmitQueue.Init(transmissions) + + transmission := transmitQueue.BlockingPop() + assert.Equal(t, expected, transmission) + assert.True(t, transmitQueue.IsEmpty()) + }) +} diff --git a/core/services/llo/mercurytransmitter/server.go b/core/services/llo/mercurytransmitter/server.go new file mode 100644 index 00000000000..72ff8b669ba --- /dev/null +++ b/core/services/llo/mercurytransmitter/server.go @@ -0,0 +1,239 @@ +package mercurytransmitter + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/jpillora/backoff" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + 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-data-streams/llo" + + "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/utils" +) + +var ( + transmitQueueDeleteErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_queue_delete_error_count", + Help: "Running count of DB errors when trying to delete an item from the queue DB", + }, + []string{"donID", "serverURL"}, + ) + transmitQueueInsertErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_queue_insert_error_count", + Help: "Running count of DB errors when trying to insert an item into the queue DB", + }, + []string{"donID", "serverURL"}, + ) + transmitQueuePushErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_queue_push_error_count", + Help: "Running count of DB errors when trying to push an item onto the queue", + }, + []string{"donID", "serverURL"}, + ) + transmitServerErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_server_error_count", + Help: "Number of errored transmissions that failed due to an error returned by the mercury server", + }, + []string{"donID", "serverURL", "code"}, + ) +) + +// A server handles the queue for a given mercury server + +type server struct { + lggr logger.SugaredLogger + + transmitTimeout time.Duration + + c wsrpc.Client + pm *persistenceManager + q TransmitQueue + + deleteQueue chan [32]byte + + url string + + transmitSuccessCount prometheus.Counter + transmitDuplicateCount prometheus.Counter + transmitConnectionErrorCount prometheus.Counter + transmitQueueDeleteErrorCount prometheus.Counter + transmitQueueInsertErrorCount prometheus.Counter + transmitQueuePushErrorCount prometheus.Counter +} + +type QueueConfig interface { + TransmitQueueMaxSize() uint32 + TransmitTimeout() commonconfig.Duration +} + +func newServer(lggr logger.Logger, cfg QueueConfig, client wsrpc.Client, orm ORM, serverURL string) *server { + pm := NewPersistenceManager(lggr, orm, serverURL, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) + donIDStr := fmt.Sprintf("%d", pm.DonID()) + return &server{ + logger.Sugared(lggr), + cfg.TransmitTimeout().Duration(), + client, + pm, + NewTransmitQueue(lggr, serverURL, int(cfg.TransmitQueueMaxSize()), pm), + make(chan [32]byte, int(cfg.TransmitQueueMaxSize())), + serverURL, + transmitSuccessCount.WithLabelValues(donIDStr, serverURL), + transmitDuplicateCount.WithLabelValues(donIDStr, serverURL), + transmitConnectionErrorCount.WithLabelValues(donIDStr, serverURL), + transmitQueueDeleteErrorCount.WithLabelValues(donIDStr, serverURL), + transmitQueueInsertErrorCount.WithLabelValues(donIDStr, serverURL), + transmitQueuePushErrorCount.WithLabelValues(donIDStr, serverURL), + } +} + +func (s *server) HealthReport() map[string]error { + report := map[string]error{} + services.CopyHealth(report, s.c.HealthReport()) + services.CopyHealth(report, s.q.HealthReport()) + return report +} + +func (s *server) runDeleteQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup) { + defer wg.Done() + runloopCtx, cancel := stopCh.Ctx(context.Background()) + defer cancel() + + // Exponential backoff for very rarely occurring errors (DB disconnect etc) + b := backoff.Backoff{ + Min: 1 * time.Second, + Max: 120 * time.Second, + Factor: 2, + Jitter: true, + } + + for { + select { + case hash := <-s.deleteQueue: + for { + if err := s.pm.orm.Delete(runloopCtx, [][32]byte{hash}); err != nil { + s.lggr.Errorw("Failed to delete transmission record", "err", err, "transmissionHash", fmt.Sprintf("%x", hash)) + s.transmitQueueDeleteErrorCount.Inc() + select { + case <-time.After(b.Duration()): + // Wait a backoff duration before trying to delete again + continue + case <-stopCh: + // abort and return immediately on stop even if items remain in queue + return + } + } + break + } + // success + b.Reset() + case <-stopCh: + // abort and return immediately on stop even if items remain in queue + return + } + } +} + +func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, donIDStr string) { + defer wg.Done() + // Exponential backoff with very short retry interval (since latency is a priority) + // 5ms, 10ms, 20ms, 40ms etc + b := backoff.Backoff{ + Min: 5 * time.Millisecond, + Max: 1 * time.Second, + Factor: 2, + Jitter: true, + } + runloopCtx, cancel := stopCh.Ctx(context.Background()) + defer cancel() + for { + t := s.q.BlockingPop() + if t == nil { + // queue was closed + return + } + ctx, cancel := context.WithTimeout(runloopCtx, utils.WithJitter(s.transmitTimeout)) + res, err := s.transmit(ctx, t) + cancel() + if runloopCtx.Err() != nil { + // runloop context is only canceled on transmitter close so we can + // exit the runloop here + return + } else if err != nil { + s.transmitConnectionErrorCount.Inc() + s.lggr.Errorw("Transmit report failed", "err", err, "transmission", t) + if ok := s.q.Push(t); !ok { + s.lggr.Error("Failed to push report to transmit queue; queue is closed") + return + } + // Wait a backoff duration before pulling the most recent transmission + // the heap + select { + case <-time.After(b.Duration()): + continue + case <-stopCh: + return + } + } + + b.Reset() + if res.Error == "" { + s.transmitSuccessCount.Inc() + s.lggr.Debugw("Transmit report success", "transmission", t, "response", res) + } else { + // We don't need to retry here because the mercury server + // has confirmed it received the report. We only need to retry + // on networking/unknown errors + switch res.Code { + case DuplicateReport: + s.transmitSuccessCount.Inc() + s.transmitDuplicateCount.Inc() + s.lggr.Debugw("Transmit report success; duplicate report", "transmission", t, "response", res) + default: + transmitServerErrorCount.WithLabelValues(donIDStr, s.url, fmt.Sprintf("%d", res.Code)).Inc() + s.lggr.Errorw("Transmit report failed; mercury server returned error", "response", res, "transmission", t, "err", res.Error, "code", res.Code) + } + } + + select { + case s.deleteQueue <- t.Hash(): + default: + s.lggr.Criticalw("Delete queue is full", "transmission", t) + } + } +} + +func (s *server) transmit(ctx context.Context, t *Transmission) (*pb.TransmitResponse, error) { + var payload []byte + var err error + + switch t.Report.Info.ReportFormat { + case llotypes.ReportFormatJSON: + payload, err = llo.JSONReportCodec{}.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) + case llotypes.ReportFormatEVMPremiumLegacy: + payload, err = evm.ReportCodecPremiumLegacy{}.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) + default: + return nil, fmt.Errorf("Transmit failed; unsupported report format: %q", t.Report.Info.ReportFormat) + } + + if err != nil { + return nil, fmt.Errorf("Transmit: encode failed; %w", err) + } + + req := &pb.TransmitRequest{ + Payload: payload, + ReportFormat: uint32(t.Report.Info.ReportFormat), + } + + return s.c.Transmit(ctx, req) +} diff --git a/core/services/llo/mercurytransmitter/transmitter.go b/core/services/llo/mercurytransmitter/transmitter.go new file mode 100644 index 00000000000..33090ed9574 --- /dev/null +++ b/core/services/llo/mercurytransmitter/transmitter.go @@ -0,0 +1,254 @@ +package mercurytransmitter + +import ( + "context" + "crypto/ed25519" + "crypto/sha256" + "encoding/binary" + "errors" + "fmt" + "io" + "sync" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + 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 ( + // Mercury server error codes + DuplicateReport = 2 +) + +var ( + transmitSuccessCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_success_count", + Help: "Number of successful transmissions (duplicates are counted as success)", + }, + []string{"donID", "serverURL"}, + ) + transmitDuplicateCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_duplicate_count", + Help: "Number of transmissions where the server told us it was a duplicate", + }, + []string{"donID", "serverURL"}, + ) + transmitConnectionErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_connection_error_count", + Help: "Number of errored transmissions that failed due to problem with the connection", + }, + []string{"donID", "serverURL"}, + ) +) + +type Transmission struct { + ServerURL string + ConfigDigest types.ConfigDigest + SeqNr uint64 + Report ocr3types.ReportWithInfo[llotypes.ReportInfo] + Sigs []types.AttributedOnchainSignature +} + +// Hash takes sha256 hash of all fields +func (t Transmission) Hash() [32]byte { + h := sha256.New() + h.Write([]byte(t.ServerURL)) + h.Write(t.ConfigDigest[:]) + if err := binary.Write(h, binary.BigEndian, t.SeqNr); err != nil { + // This should never happen + panic(err) + } + h.Write(t.Report.Report) + h.Write([]byte(t.Report.Info.LifeCycleStage)) + if err := binary.Write(h, binary.BigEndian, t.Report.Info.ReportFormat); err != nil { + // This should never happen + panic(err) + } + for _, sig := range t.Sigs { + h.Write(sig.Signature) + if err := binary.Write(h, binary.BigEndian, sig.Signer); err != nil { + // This should never happen + panic(err) + } + } + var result [32]byte + h.Sum(result[:0]) + return result +} + +type Transmitter interface { + llotypes.Transmitter + services.Service +} + +var _ Transmitter = (*transmitter)(nil) + +type Config interface { + TransmitQueueMaxSize() uint32 + TransmitTimeout() commonconfig.Duration +} + +type transmitter struct { + services.StateMachine + lggr logger.SugaredLogger + cfg Config + + orm ORM + servers map[string]*server + + donID uint32 + fromAccount string + + stopCh services.StopChan + wg *sync.WaitGroup +} + +type Opts struct { + Lggr logger.Logger + Cfg Config + Clients map[string]wsrpc.Client + FromAccount ed25519.PublicKey + DonID uint32 + ORM ORM +} + +func New(opts Opts) Transmitter { + return newTransmitter(opts) +} + +func newTransmitter(opts Opts) *transmitter { + sugared := logger.Sugared(opts.Lggr).Named("LLOMercuryTransmitter") + servers := make(map[string]*server, len(opts.Clients)) + for serverURL, client := range opts.Clients { + sLggr := sugared.Named(serverURL).With("serverURL", serverURL) + servers[serverURL] = newServer(sLggr, opts.Cfg, client, opts.ORM, serverURL) + } + return &transmitter{ + services.StateMachine{}, + sugared.Named("LLOMercuryTransmitter").With("donID", opts.ORM.DonID()), + opts.Cfg, + opts.ORM, + servers, + opts.DonID, + fmt.Sprintf("%x", opts.FromAccount), + make(services.StopChan), + &sync.WaitGroup{}, + } +} + +func (mt *transmitter) Start(ctx context.Context) (err error) { + return mt.StartOnce("LLOMercuryTransmitter", func() error { + mt.lggr.Debugw("Loading transmit requests from database") + + { + var startClosers []services.StartClose + for _, s := range mt.servers { + transmissions, err := s.pm.Load(ctx) + if err != nil { + return err + } + s.q.Init(transmissions) + // starting pm after loading from it is fine because it simply spawns some garbage collection/prune goroutines + startClosers = append(startClosers, s.c, s.q, s.pm) + + mt.wg.Add(2) + go s.runDeleteQueueLoop(mt.stopCh, mt.wg) + go s.runQueueLoop(mt.stopCh, mt.wg, fmt.Sprintf("%d", mt.donID)) + } + if err := (&services.MultiStart{}).Start(ctx, startClosers...); err != nil { + return err + } + } + + return nil + }) +} + +func (mt *transmitter) Close() error { + return mt.StopOnce("LLOMercuryTransmitter", func() error { + // Drain all the queues first + var qs []io.Closer + for _, s := range mt.servers { + qs = append(qs, s.q) + } + if err := services.CloseAll(qs...); err != nil { + return err + } + + close(mt.stopCh) + mt.wg.Wait() + + // Close all the persistence managers + // Close all the clients + var closers []io.Closer + for _, s := range mt.servers { + closers = append(closers, s.pm) + closers = append(closers, s.c) + } + return services.CloseAll(closers...) + }) +} + +func (mt *transmitter) Name() string { return mt.lggr.Name() } + +func (mt *transmitter) HealthReport() map[string]error { + report := map[string]error{mt.Name(): mt.Healthy()} + for _, s := range mt.servers { + services.CopyHealth(report, s.HealthReport()) + } + return report +} + +// Transmit enqueues the report for transmission to the Mercury servers +func (mt *transmitter) Transmit( + ctx context.Context, + digest types.ConfigDigest, + seqNr uint64, + report ocr3types.ReportWithInfo[llotypes.ReportInfo], + sigs []types.AttributedOnchainSignature) error { + transmissions := make([]*Transmission, 0, len(mt.servers)) + for serverURL := range mt.servers { + transmissions = append(transmissions, &Transmission{ + ServerURL: serverURL, + ConfigDigest: digest, + SeqNr: seqNr, + Report: report, + Sigs: sigs, + }) + } + if err := mt.orm.Insert(ctx, transmissions); err != nil { + return err + } + + g := new(errgroup.Group) + for i := range transmissions { + t := transmissions[i] + mt.lggr.Debugw("LLOMercuryTransmit", "digest", digest.Hex(), "seqNr", seqNr, "reportFormat", report.Info.ReportFormat, "reportLifeCycleStage", report.Info.LifeCycleStage, "transmissionHash", fmt.Sprintf("%x", t.Hash())) + g.Go(func() error { + s := mt.servers[t.ServerURL] + if ok := s.q.Push(t); !ok { + s.transmitQueuePushErrorCount.Inc() + return errors.New("transmit queue is closed") + } + return nil + }) + } + + return g.Wait() +} + +// FromAccount returns the stringified (hex) CSA public key +func (mt *transmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return ocrtypes.Account(mt.fromAccount), nil +} diff --git a/core/services/llo/mercurytransmitter/transmitter_test.go b/core/services/llo/mercurytransmitter/transmitter_test.go new file mode 100644 index 00000000000..db3d0d2e584 --- /dev/null +++ b/core/services/llo/mercurytransmitter/transmitter_test.go @@ -0,0 +1,258 @@ +package mercurytransmitter + +import ( + "context" + "crypto/ed25519" + "sync" + "testing" + "time" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + 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" +) + +type mockCfg struct{} + +func (m mockCfg) TransmitQueueMaxSize() uint32 { + return 10_000 +} + +func (m mockCfg) TransmitTimeout() commonconfig.Duration { + return *commonconfig.MustNewDuration(1 * time.Hour) +} + +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{} + + t.Run("with multiple mercury servers", func(t *testing.T) { + t.Run("transmission successfully enqueued", func(t *testing.T) { + c := &mocks.MockWSRPCClient{} + clients[sURL] = c + clients[sURL2] = c + clients[sURL3] = c + + mt := newTransmitter(Opts{ + Lggr: lggr, + Cfg: mockCfg{}, + Clients: clients, + FromAccount: ed25519.PublicKey{}, + DonID: donID, + ORM: orm, + }) + // init the queue since we skipped starting transmitter + mt.servers[sURL].q.Init([]*Transmission{}) + mt.servers[sURL2].q.Init([]*Transmission{}) + mt.servers[sURL3].q.Init([]*Transmission{}) + + seqNr := uint64(55) + report := makeSampleReport() + digest := makeSampleConfigDigest() + sigs := []types.AttributedOnchainSignature{{ + Signature: []byte{22}, + Signer: commontypes.OracleID(43), + }} + err := mt.Transmit(testutils.Context(t), digest, seqNr, report, sigs) + require.NoError(t, err) + + // ensure it was added to the queue + require.Equal(t, mt.servers[sURL].q.(*transmitQueue).pq.Len(), 1) + assert.Equal(t, &Transmission{ + ServerURL: sURL, + ConfigDigest: digest, + SeqNr: seqNr, + Report: report, + Sigs: sigs, + }, mt.servers[sURL].q.(*transmitQueue).pq.Pop().(*Transmission)) + require.Equal(t, mt.servers[sURL2].q.(*transmitQueue).pq.Len(), 1) + assert.Equal(t, &Transmission{ + ServerURL: sURL2, + ConfigDigest: digest, + SeqNr: seqNr, + Report: report, + Sigs: sigs, + }, mt.servers[sURL2].q.(*transmitQueue).pq.Pop().(*Transmission)) + require.Equal(t, mt.servers[sURL3].q.(*transmitQueue).pq.Len(), 1) + assert.Equal(t, &Transmission{ + ServerURL: sURL3, + ConfigDigest: digest, + SeqNr: seqNr, + Report: report, + Sigs: sigs, + }, mt.servers[sURL3].q.(*transmitQueue).pq.Pop().(*Transmission)) + }) + }) +} + +type mockQ struct { + ch chan *Transmission +} + +func newMockQ() *mockQ { + return &mockQ{make(chan *Transmission, 100)} +} + +func (m *mockQ) Start(context.Context) error { return nil } +func (m *mockQ) Close() error { + m.ch <- nil + return nil +} +func (m *mockQ) Ready() error { return nil } +func (m *mockQ) HealthReport() map[string]error { return nil } +func (m *mockQ) Name() string { return "" } +func (m *mockQ) BlockingPop() (t *Transmission) { + val := <-m.ch + return val +} +func (m *mockQ) Push(t *Transmission) (ok bool) { + m.ch <- t + return true +} +func (m *mockQ) Init(transmissions []*Transmission) {} +func (m *mockQ) IsEmpty() bool { return false } + +func Test_Transmitter_runQueueLoop(t *testing.T) { + donIDStr := "555" + lggr := logger.TestLogger(t) + c := &mocks.MockWSRPCClient{} + db := pgtest.NewSqlxDB(t) + donID := uint32(123456) + orm := NewORM(db, donID) + cfg := mockCfg{} + + s := newServer(lggr, 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 <- in + return &pb.TransmitResponse{Code: 0, Error: ""}, nil + } + q := newMockQ() + s.q = q + wg := &sync.WaitGroup{} + wg.Add(1) + + go s.runQueueLoop(nil, wg, donIDStr) + + transmission := makeSampleTransmission(1) + q.Push(transmission) + + select { + case tr := <-transmit: + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) + case <-time.After(testutils.WaitTimeout(t)): + t.Fatal("expected a transmit request to be sent") + } + + q.Close() + wg.Wait() + }) + + 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 <- in + return &pb.TransmitResponse{Code: DuplicateReport, Error: ""}, nil + } + q := newMockQ() + s.q = q + wg := &sync.WaitGroup{} + wg.Add(1) + + go s.runQueueLoop(nil, wg, donIDStr) + + transmission := makeSampleTransmission(1) + q.Push(transmission) + + select { + case tr := <-transmit: + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) + case <-time.After(testutils.WaitTimeout(t)): + t.Fatal("expected a transmit request to be sent") + } + + q.Close() + 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 <- in + return &pb.TransmitResponse{Code: DuplicateReport, Error: ""}, nil + } + q := newMockQ() + s.q = q + wg := &sync.WaitGroup{} + wg.Add(1) + + go s.runQueueLoop(nil, wg, donIDStr) + + transmission := makeSampleTransmission(1) + q.Push(transmission) + + select { + case tr := <-transmit: + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) + case <-time.After(testutils.WaitTimeout(t)): + t.Fatal("expected a transmit request to be sent") + } + + q.Close() + 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 <- in + return &pb.TransmitResponse{}, errors.New("transmission error") + } + q := newMockQ() + s.q = q + wg := &sync.WaitGroup{} + wg.Add(1) + stopCh := make(chan struct{}, 1) + + go s.runQueueLoop(stopCh, wg, donIDStr) + + transmission := makeSampleTransmission(1) + q.Push(transmission) + + cnt := 0 + Loop: + for { + select { + case tr := <-transmit: + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) + if cnt > 2 { + break Loop + } + cnt++ + case <-time.After(testutils.WaitTimeout(t)): + t.Fatal("expected 3 transmit requests to be sent") + } + } + + close(stopCh) + wg.Wait() + }) +} diff --git a/core/services/llo/never_retire_cache.go b/core/services/llo/never_retire_cache.go new file mode 100644 index 00000000000..864d649bd4f --- /dev/null +++ b/core/services/llo/never_retire_cache.go @@ -0,0 +1,17 @@ +package llo + +import ( + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" +) + +type neverShouldRetireCache struct{} + +func NewNeverShouldRetireCache() llotypes.ShouldRetireCache { + return &neverShouldRetireCache{} +} + +func (n *neverShouldRetireCache) ShouldRetire(digest ocrtypes.ConfigDigest) (bool, error) { + return false, nil +} diff --git a/core/services/llo/null_retirement_report_cache.go b/core/services/llo/null_retirement_report_cache.go new file mode 100644 index 00000000000..e1763e4a178 --- /dev/null +++ b/core/services/llo/null_retirement_report_cache.go @@ -0,0 +1,25 @@ +package llo + +import ( + "context" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" +) + +type NullRetirementReportCache struct{} + +func (n *NullRetirementReportCache) StoreAttestedRetirementReport(ctx context.Context, cd ocr2types.ConfigDigest, retirementReport []byte, sigs []types.AttributedOnchainSignature) error { + return nil +} +func (n *NullRetirementReportCache) StoreConfig(ctx context.Context, cd ocr2types.ConfigDigest, signers [][]byte, f uint8) error { + return nil +} +func (n *NullRetirementReportCache) AttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest) ([]byte, error) { + return nil, nil +} +func (n *NullRetirementReportCache) CheckAttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest, attestedRetirementReport []byte) (datastreamsllo.RetirementReport, error) { + return datastreamsllo.RetirementReport{}, nil +} diff --git a/core/services/llo/onchain_channel_definition_cache.go b/core/services/llo/onchain_channel_definition_cache.go index 4d3fb0e8255..31b3d87bb41 100644 --- a/core/services/llo/onchain_channel_definition_cache.go +++ b/core/services/llo/onchain_channel_definition_cache.go @@ -1,34 +1,53 @@ package llo import ( + "bytes" "context" "database/sql" + "encoding/json" "errors" "fmt" + "io" "maps" + "math/big" + "net/http" "strings" "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "golang.org/x/crypto/sha3" + "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/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/utils" + clhttp "github.com/smartcontractkit/chainlink/v2/core/utils/http" ) -type ChannelDefinitionCacheORM interface { - // TODO: What about delete/cleanup? - // https://smartcontract-it.atlassian.net/browse/MERC-3653 - LoadChannelDefinitions(ctx context.Context, addr common.Address) (dfns llotypes.ChannelDefinitions, blockNum int64, err error) - StoreChannelDefinitions(ctx context.Context, addr common.Address, dfns llotypes.ChannelDefinitions, blockNum int64) (err error) -} +const ( + // MaxChannelDefinitionsFileSize is a sanity limit to avoid OOM for a + // maliciously large file. It should be much larger than any real expected + // channel definitions file. + MaxChannelDefinitionsFileSize = 25 * 1024 * 1024 // 25MB + // How often we query logpoller for new logs + defaultLogPollInterval = 1 * time.Second + // How often we check for failed persistence and attempt to save again + dbPersistLoopInterval = 1 * time.Second + + newChannelDefinitionEventName = "NewChannelDefinition" +) -var channelConfigStoreABI abi.ABI +var ( + channelConfigStoreABI abi.ABI + topicNewChannelDefinition = (channel_config_store.ChannelConfigStoreNewChannelDefinition{}).Topic() + + allTopics = []common.Hash{topicNewChannelDefinition} +) func init() { var err error @@ -38,82 +57,133 @@ func init() { } } +type ChannelDefinitionCacheORM interface { + LoadChannelDefinitions(ctx context.Context, addr common.Address, donID uint32) (pd *PersistedDefinitions, err error) + StoreChannelDefinitions(ctx context.Context, addr common.Address, donID, version uint32, dfns llotypes.ChannelDefinitions, blockNum int64) (err error) + CleanupChannelDefinitions(ctx context.Context, addr common.Address, donID uint32) error +} + var _ llotypes.ChannelDefinitionCache = &channelDefinitionCache{} +type LogPoller interface { + LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) + LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) + RegisterFilter(ctx context.Context, filter logpoller.Filter) error + UnregisterFilter(ctx context.Context, filterName string) error +} + +type Option func(*channelDefinitionCache) + +func WithLogPollInterval(d time.Duration) Option { + return func(c *channelDefinitionCache) { + c.logPollInterval = d + } +} + type channelDefinitionCache struct { services.StateMachine - orm ChannelDefinitionCacheORM + orm ChannelDefinitionCacheORM + client HTTPClient + httpLimit int64 - filterName string - lp logpoller.LogPoller - fromBlock int64 - addr common.Address - lggr logger.Logger + filterName string + lp LogPoller + logPollInterval time.Duration + addr common.Address + donID uint32 + lggr logger.SugaredLogger + initialBlockNum int64 + + newLogMu sync.RWMutex + newLog *channel_config_store.ChannelConfigStoreNewChannelDefinition + newLogCh chan *channel_config_store.ChannelConfigStoreNewChannelDefinition definitionsMu sync.RWMutex definitions llotypes.ChannelDefinitions + definitionsVersion uint32 definitionsBlockNum int64 + persistMu sync.RWMutex + persistedVersion uint32 + wg sync.WaitGroup chStop chan struct{} } -var ( - topicNewChannelDefinition = (channel_config_store.ChannelConfigStoreNewChannelDefinition{}).Topic() - topicChannelDefinitionRemoved = (channel_config_store.ChannelConfigStoreChannelDefinitionRemoved{}).Topic() +type HTTPClient interface { + Do(req *http.Request) (*http.Response, error) +} - allTopics = []common.Hash{topicNewChannelDefinition, topicChannelDefinitionRemoved} -) +func filterName(addr common.Address, donID uint32) string { + return logpoller.FilterName("OCR3 LLO ChannelDefinitionCachePoller", addr.String(), fmt.Sprintf("%d", donID)) +} -func NewChannelDefinitionCache(lggr logger.Logger, orm ChannelDefinitionCacheORM, lp logpoller.LogPoller, addr common.Address, fromBlock int64) llotypes.ChannelDefinitionCache { - filterName := logpoller.FilterName("OCR3 LLO ChannelDefinitionCachePoller", addr.String()) - return &channelDefinitionCache{ - services.StateMachine{}, - orm, - filterName, - lp, - 0, - addr, - lggr.Named("ChannelDefinitionCache").With("addr", addr, "fromBlock", fromBlock), - sync.RWMutex{}, - nil, - fromBlock, - sync.WaitGroup{}, - make(chan struct{}), +func NewChannelDefinitionCache(lggr logger.Logger, orm ChannelDefinitionCacheORM, client HTTPClient, lp logpoller.LogPoller, addr common.Address, donID uint32, fromBlock int64, options ...Option) llotypes.ChannelDefinitionCache { + filterName := logpoller.FilterName("OCR3 LLO ChannelDefinitionCachePoller", addr.String(), donID) + cdc := &channelDefinitionCache{ + orm: orm, + client: client, + httpLimit: MaxChannelDefinitionsFileSize, + filterName: filterName, + lp: lp, + logPollInterval: defaultLogPollInterval, + addr: addr, + donID: donID, + lggr: logger.Sugared(lggr).Named("ChannelDefinitionCache").With("addr", addr, "fromBlock", fromBlock), + newLogCh: make(chan *channel_config_store.ChannelConfigStoreNewChannelDefinition, 1), + initialBlockNum: fromBlock, + chStop: make(chan struct{}), } + for _, option := range options { + option(cdc) + } + return cdc } func (c *channelDefinitionCache) Start(ctx context.Context) error { // Initial load from DB, then async poll from chain thereafter return c.StartOnce("ChannelDefinitionCache", func() (err error) { - err = c.lp.RegisterFilter(ctx, logpoller.Filter{Name: c.filterName, EventSigs: allTopics, Addresses: []common.Address{c.addr}}) + donIDTopic := common.BigToHash(big.NewInt(int64(c.donID))) + err = c.lp.RegisterFilter(ctx, logpoller.Filter{Name: c.filterName, EventSigs: allTopics, Topic2: []common.Hash{donIDTopic}, Addresses: []common.Address{c.addr}}) if err != nil { return err } - if definitions, definitionsBlockNum, err := c.orm.LoadChannelDefinitions(ctx, c.addr); err != nil { + if pd, err := c.orm.LoadChannelDefinitions(ctx, c.addr, c.donID); err != nil { return err - } else if definitions != nil { - c.definitions = definitions - c.definitionsBlockNum = definitionsBlockNum + } else if pd != nil { + c.definitions = pd.Definitions + c.initialBlockNum = pd.BlockNum + 1 + c.definitionsVersion = uint32(pd.Version) } else { // ensure non-nil map ready for assignment later c.definitions = make(llotypes.ChannelDefinitions) - // leave c.definitionsBlockNum as provided fromBlock argument + // leave c.initialBlockNum as provided fromBlock argument } - c.wg.Add(1) - go c.poll() + c.wg.Add(3) + // We have three concurrent loops + // 1. Poll chain for new logs + // 2. Fetch latest definitions from URL and verify SHA, according to latest log + // 3. Retry persisting records to DB, if it failed + go c.pollChainLoop() + go c.fetchLatestLoop() + go c.failedPersistLoop() return nil }) } -// TODO: make this configurable? -const pollInterval = 1 * time.Second +//////////////////////////////////////////////////////////////////// +// Log Polling +//////////////////////////////////////////////////////////////////// -func (c *channelDefinitionCache) poll() { +// pollChainLoop periodically checks logpoller for new logs +func (c *channelDefinitionCache) pollChainLoop() { defer c.wg.Done() - pollT := services.NewTicker(pollInterval) + ctx, cancel := services.StopChan(c.chStop).NewCtx() + defer cancel() + + pollT := services.NewTicker(c.logPollInterval) defer pollT.Stop() for { @@ -121,114 +191,300 @@ func (c *channelDefinitionCache) poll() { case <-c.chStop: return case <-pollT.C: - if n, err := c.fetchFromChain(); err != nil { - // TODO: retry with backoff? - // https://smartcontract-it.atlassian.net/browse/MERC-3653 + // failures will be tried again on the next tick + if err := c.readLogs(ctx); err != nil { c.lggr.Errorw("Failed to fetch channel definitions from chain", "err", err) continue - } else { - if n > 0 { - c.lggr.Infow("Updated channel definitions", "nLogs", n, "definitionsBlockNum", c.definitionsBlockNum) - } else { - c.lggr.Debugw("No new channel definitions", "nLogs", 0, "definitionsBlockNum", c.definitionsBlockNum) - } } } } } -func (c *channelDefinitionCache) fetchFromChain() (nLogs int, err error) { - // TODO: Pass context - ctx, cancel := services.StopChan(c.chStop).NewCtx() - defer cancel() - // https://smartcontract-it.atlassian.net/browse/MERC-3653 - latest, err := c.lp.LatestBlock(ctx) +func (c *channelDefinitionCache) readLogs(ctx context.Context) (err error) { + latestBlock, err := c.lp.LatestBlock(ctx) if errors.Is(err, sql.ErrNoRows) { c.lggr.Debug("Logpoller has no logs yet, skipping poll") - return 0, nil + return nil } else if err != nil { - return 0, err + return err } - toBlock := latest.BlockNumber + toBlock := latestBlock.BlockNumber - fromBlock := c.definitionsBlockNum + fromBlock := c.scanFromBlockNum() if toBlock <= fromBlock { - return 0, nil + return nil } - // NOTE: We assume that log poller returns logs in ascending order chronologically + // NOTE: We assume that log poller returns logs in order of block_num, log_index ASC + // TODO: Could improve performance a little bit here by adding a don ID topic filter + // MERC-3524 logs, err := c.lp.LogsWithSigs(ctx, fromBlock, toBlock, allTopics, c.addr) if err != nil { - // TODO: retry? - // https://smartcontract-it.atlassian.net/browse/MERC-3653 - return 0, err + return err } + for _, log := range logs { - if err = c.applyLog(log); err != nil { - return 0, err + switch log.EventSig { + case topicNewChannelDefinition: + unpacked := new(channel_config_store.ChannelConfigStoreNewChannelDefinition) + + err := channelConfigStoreABI.UnpackIntoInterface(unpacked, newChannelDefinitionEventName, log.Data) + if err != nil { + return fmt.Errorf("failed to unpack log data: %w", err) + } + if len(log.Topics) < 2 { + // should never happen but must guard against unexpected panics + c.lggr.Warnw("Log missing expected topics", "log", log) + continue + } + unpacked.DonId = new(big.Int).SetBytes(log.Topics[1]) + + if unpacked.DonId.Cmp(big.NewInt(int64(c.donID))) != 0 { + // skip logs for other donIDs + continue + } + + c.newLogMu.Lock() + if c.newLog == nil || unpacked.Version > c.newLog.Version { + // assume that donID is correct due to log poller filtering + c.lggr.Infow("Got new channel definitions from chain", "version", unpacked.Version, "blockNumber", log.BlockNumber, "sha", fmt.Sprintf("%x", unpacked.Sha), "url", unpacked.Url) + c.newLog = unpacked + c.newLogCh <- unpacked + } + c.newLogMu.Unlock() + + default: + // ignore unrecognized logs + continue } } - // Use context.Background() here because we want to try to save even if we - // are closing - if err = c.orm.StoreChannelDefinitions(context.Background(), c.addr, c.Definitions(), toBlock); err != nil { - return 0, err + return nil +} + +func (c *channelDefinitionCache) scanFromBlockNum() int64 { + c.newLogMu.RLock() + defer c.newLogMu.RUnlock() + if c.newLog != nil { + return int64(c.newLog.Raw.BlockNumber) + 1 } + return c.initialBlockNum +} + +//////////////////////////////////////////////////////////////////// +// Fetch channel definitions from URL based on latest log +//////////////////////////////////////////////////////////////////// + +// fetchLatestLoop waits for new logs and tries on a loop to fetch the channel definitions from the specified url +func (c *channelDefinitionCache) fetchLatestLoop() { + defer c.wg.Done() + + var fetchCh chan struct{} + + for { + select { + case latest := <-c.newLogCh: + // kill the old retry loop if any + if fetchCh != nil { + close(fetchCh) + } - c.definitionsBlockNum = toBlock + fetchCh = make(chan struct{}) - return len(logs), nil + c.wg.Add(1) + go c.fetchLoop(fetchCh, latest) + + case <-c.chStop: + return + } + } } -func (c *channelDefinitionCache) applyLog(log logpoller.Log) error { - switch log.EventSig { - case topicNewChannelDefinition: - unpacked := new(channel_config_store.ChannelConfigStoreNewChannelDefinition) +func (c *channelDefinitionCache) fetchLoop(closeCh chan struct{}, log *channel_config_store.ChannelConfigStoreNewChannelDefinition) { + defer c.wg.Done() + b := utils.NewHTTPFetchBackoff() + var attemptCnt int + + ctx, cancel := services.StopChan(c.chStop).NewCtx() + defer cancel() - err := channelConfigStoreABI.UnpackIntoInterface(unpacked, "NewChannelDefinition", log.Data) - if err != nil { - return fmt.Errorf("failed to unpack log data: %w", err) + err := c.fetchAndSetChannelDefinitions(ctx, log) + if err == nil { + c.lggr.Debugw("Set new channel definitions", "donID", c.donID, "version", log.Version, "url", log.Url, "sha", fmt.Sprintf("%x", log.Sha)) + return + } + c.lggr.Warnw("Error while fetching channel definitions", "donID", c.donID, "version", log.Version, "url", log.Url, "sha", fmt.Sprintf("%x", log.Sha), "err", err, "attempt", attemptCnt) + + for { + select { + case <-closeCh: + return + case <-time.After(b.Duration()): + attemptCnt++ + err := c.fetchAndSetChannelDefinitions(ctx, log) + if err != nil { + c.lggr.Warnw("Error while fetching channel definitions", "version", log.Version, "url", log.Url, "sha", fmt.Sprintf("%x", log.Sha), "err", err, "attempt", attemptCnt) + continue + } + c.lggr.Debugw("Set new channel definitions", "donID", c.donID, "version", log.Version, "url", log.Url, "sha", fmt.Sprintf("%x", log.Sha)) + return } + } +} + +func (c *channelDefinitionCache) fetchAndSetChannelDefinitions(ctx context.Context, log *channel_config_store.ChannelConfigStoreNewChannelDefinition) error { + c.definitionsMu.RLock() + if log.Version <= c.definitionsVersion { + c.definitionsMu.RUnlock() + return nil + } + c.definitionsMu.RUnlock() + + cd, err := c.fetchChannelDefinitions(ctx, log.Url, log.Sha) + if err != nil { + return err + } + c.definitionsMu.Lock() + if log.Version <= c.definitionsVersion { + c.definitionsMu.Unlock() + return nil + } + c.definitions = cd + c.definitionsBlockNum = int64(log.Raw.BlockNumber) + c.definitionsVersion = log.Version + c.definitionsMu.Unlock() + + if memoryVersion, persistedVersion, err := c.persist(context.Background()); err != nil { + // If this fails, the failedPersistLoop will try again + c.lggr.Warnw("Failed to persist channel definitions", "err", err, "memoryVersion", memoryVersion, "persistedVersion", persistedVersion) + } + + return nil +} - c.applyNewChannelDefinition(unpacked) - case topicChannelDefinitionRemoved: - unpacked := new(channel_config_store.ChannelConfigStoreChannelDefinitionRemoved) +func (c *channelDefinitionCache) fetchChannelDefinitions(ctx context.Context, url string, expectedSha [32]byte) (llotypes.ChannelDefinitions, error) { + request, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, fmt.Errorf("failed to create http.Request; %w", err) + } + request.Header.Set("Content-Type", "application/json") + + httpRequest := clhttp.HTTPRequest{ + Client: c.client, + Request: request, + Config: clhttp.HTTPRequestConfig{SizeLimit: c.httpLimit}, + Logger: c.lggr.Named("HTTPRequest").With("url", url, "expectedSHA", fmt.Sprintf("%x", expectedSha)), + } - err := channelConfigStoreABI.UnpackIntoInterface(unpacked, "ChannelDefinitionRemoved", log.Data) + reader, statusCode, _, err := httpRequest.SendRequestReader() + if err != nil { + return nil, fmt.Errorf("error making http request: %w", err) + } + defer reader.Close() + + if statusCode >= 400 { + // NOTE: Truncate the returned body here as we don't want to spam the + // logs with potentially huge messages + body := http.MaxBytesReader(nil, reader, 1024) + defer body.Close() + bodyBytes, err := io.ReadAll(body) if err != nil { - return fmt.Errorf("failed to unpack log data: %w", err) + return nil, fmt.Errorf("got error from %s: (status code: %d, error reading response body: %w, response body: %s)", url, statusCode, err, bodyBytes) } + return nil, fmt.Errorf("got error from %s: (status code: %d, response body: %s)", url, statusCode, string(bodyBytes)) + } + + var buf bytes.Buffer + // Use a teeReader to avoid excessive copying + teeReader := io.TeeReader(reader, &buf) - c.applyChannelDefinitionRemoved(unpacked) - default: - // don't return error here, we want to ignore unrecognized logs and - // continue rather than interrupting the loop - c.lggr.Errorw("Unexpected log topic", "topic", log.EventSig.Hex()) + hash := sha3.New256() + // Stream the data directly into the hash and copy to buf as we go + if _, err := io.Copy(hash, teeReader); err != nil { + return nil, fmt.Errorf("failed to read from body: %w", err) } - return nil + + actualSha := hash.Sum(nil) + if !bytes.Equal(expectedSha[:], actualSha) { + return nil, fmt.Errorf("SHA3 mismatch: expected %x, got %x", expectedSha, actualSha) + } + + var cd llotypes.ChannelDefinitions + decoder := json.NewDecoder(&buf) + if err := decoder.Decode(&cd); err != nil { + return nil, fmt.Errorf("failed to decode JSON: %w", err) + } + + return cd, nil } -func (c *channelDefinitionCache) applyNewChannelDefinition(log *channel_config_store.ChannelConfigStoreNewChannelDefinition) { - streamIDs := make([]llotypes.StreamID, len(log.ChannelDefinition.StreamIDs)) - copy(streamIDs, log.ChannelDefinition.StreamIDs) - c.definitionsMu.Lock() - defer c.definitionsMu.Unlock() - c.definitions[log.ChannelId] = llotypes.ChannelDefinition{ - ReportFormat: llotypes.ReportFormat(log.ChannelDefinition.ReportFormat), +//////////////////////////////////////////////////////////////////// +// Persistence +//////////////////////////////////////////////////////////////////// + +func (c *channelDefinitionCache) persist(ctx context.Context) (memoryVersion, persistedVersion uint32, err error) { + c.persistMu.RLock() + persistedVersion = c.persistedVersion + c.persistMu.RUnlock() + + c.definitionsMu.RLock() + memoryVersion = c.definitionsVersion + dfns := c.definitions + blockNum := c.definitionsBlockNum + c.definitionsMu.RUnlock() + + if memoryVersion <= persistedVersion { + return + } + + if err = c.orm.StoreChannelDefinitions(ctx, c.addr, c.donID, memoryVersion, dfns, blockNum); err != nil { + return + } + + c.persistMu.Lock() + defer c.persistMu.Unlock() + if memoryVersion > c.persistedVersion { + persistedVersion = memoryVersion + c.persistedVersion = persistedVersion } + + // TODO: we could delete the old logs from logpoller here actually + // https://smartcontract-it.atlassian.net/browse/MERC-3653 + return } -func (c *channelDefinitionCache) applyChannelDefinitionRemoved(log *channel_config_store.ChannelConfigStoreChannelDefinitionRemoved) { - c.definitionsMu.Lock() - defer c.definitionsMu.Unlock() - delete(c.definitions, log.ChannelId) +// Checks persisted version and tries to save if necessary on a periodic timer +// Simple backup in case database persistence fails +func (c *channelDefinitionCache) failedPersistLoop() { + defer c.wg.Done() + + ctx, cancel := services.StopChan(c.chStop).NewCtx() + defer cancel() + + for { + select { + case <-time.After(dbPersistLoopInterval): + if memoryVersion, persistedVersion, err := c.persist(ctx); err != nil { + c.lggr.Warnw("Failed to persist channel definitions", "err", err, "memoryVersion", memoryVersion, "persistedVersion", persistedVersion) + } + case <-c.chStop: + // Try one final persist with a short-ish timeout, then return + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + if memoryVersion, persistedVersion, err := c.persist(ctx); err != nil { + c.lggr.Errorw("Failed to persist channel definitions on shutdown", "err", err, "memoryVersion", memoryVersion, "persistedVersion", persistedVersion) + } + return + } + } } func (c *channelDefinitionCache) Close() error { // TODO: unregister filter (on job delete)? // https://smartcontract-it.atlassian.net/browse/MERC-3653 return c.StopOnce("ChannelDefinitionCache", func() error { + // Cancel all contexts but try one final persist before closing close(c.chStop) c.wg.Wait() return nil diff --git a/core/services/llo/onchain_channel_definition_cache_test.go b/core/services/llo/onchain_channel_definition_cache_test.go index 2fbc0c1b90d..33fc60313c4 100644 --- a/core/services/llo/onchain_channel_definition_cache_test.go +++ b/core/services/llo/onchain_channel_definition_cache_test.go @@ -1,23 +1,464 @@ package llo import ( + "bytes" + "context" + "database/sql" + "errors" + "fmt" + "io" + "math/big" + "math/rand" + "net/http" "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) +type mockLogPoller struct { + latestBlock logpoller.LogPollerBlock + latestBlockErr error + logsWithSigs []logpoller.Log + logsWithSigsErr error + + unregisteredFilterNames []string +} + +func (m *mockLogPoller) RegisterFilter(ctx context.Context, filter logpoller.Filter) error { + return nil +} +func (m *mockLogPoller) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) { + return m.latestBlock, m.latestBlockErr +} +func (m *mockLogPoller) LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { + return m.logsWithSigs, m.logsWithSigsErr +} +func (m *mockLogPoller) UnregisterFilter(ctx context.Context, name string) error { + m.unregisteredFilterNames = append(m.unregisteredFilterNames, name) + return nil +} + +var _ HTTPClient = &mockHTTPClient{} + +type mockHTTPClient struct { + resp *http.Response + err error +} + +func (m *mockHTTPClient) Do(req *http.Request) (*http.Response, error) { + return m.resp, m.err +} + +var _ ChannelDefinitionCacheORM = &mockCDCORM{} + +type mockCDCORM struct { + err error + + lastPersistedAddr common.Address + lastPersistedDonID uint32 + lastPersistedVersion uint32 + lastPersistedDfns llotypes.ChannelDefinitions + lastPersistedBlockNum int64 +} + +func (m *mockCDCORM) LoadChannelDefinitions(ctx context.Context, addr common.Address, donID uint32) (pd *PersistedDefinitions, err error) { + panic("not implemented") +} +func (m *mockCDCORM) StoreChannelDefinitions(ctx context.Context, addr common.Address, donID, version uint32, dfns llotypes.ChannelDefinitions, blockNum int64) (err error) { + m.lastPersistedAddr = addr + m.lastPersistedDonID = donID + m.lastPersistedVersion = version + m.lastPersistedDfns = dfns + m.lastPersistedBlockNum = blockNum + return m.err +} + +func (m *mockCDCORM) CleanupChannelDefinitions(ctx context.Context, addr common.Address, donID uint32) (err error) { + panic("not implemented") +} + +func makeLog(t *testing.T, donID, version uint32, url string, sha [32]byte) logpoller.Log { + data := makeLogData(t, donID, version, url, sha) + return logpoller.Log{EventSig: topicNewChannelDefinition, Topics: [][]byte{topicNewChannelDefinition[:], makeDonIDTopic(donID)}, Data: data} +} + +func makeLogData(t *testing.T, donID, version uint32, url string, sha [32]byte) []byte { + event := channelConfigStoreABI.Events[newChannelDefinitionEventName] + // donID is indexed + // version, url, sha + data, err := event.Inputs.NonIndexed().Pack(version, url, sha) + require.NoError(t, err) + return data +} + +func makeDonIDTopic(donID uint32) []byte { + return common.BigToHash(big.NewInt(int64(donID))).Bytes() +} + func Test_ChannelDefinitionCache(t *testing.T) { - t.Skip("waiting on https://github.com/smartcontractkit/chainlink/pull/13780") - // t.Run("Definitions", func(t *testing.T) { - // // NOTE: this is covered more thoroughly in the integration tests - // dfns := llotypes.ChannelDefinitions(map[llotypes.ChannelID]llotypes.ChannelDefinition{ - // 1: { - // ReportFormat: llotypes.ReportFormat(43), - // ChainSelector: 42, - // StreamIDs: []llotypes.StreamID{1, 2, 3}, - // }, - // }) - - // cdc := &channelDefinitionCache{definitions: dfns} - - // assert.Equal(t, dfns, cdc.Definitions()) - // }) + donID := rand.Uint32() + + t.Run("Definitions", func(t *testing.T) { + // NOTE: this is covered more thoroughly in the integration tests + dfns := llotypes.ChannelDefinitions(map[llotypes.ChannelID]llotypes.ChannelDefinition{ + 1: { + ReportFormat: llotypes.ReportFormat(43), + Streams: []llotypes.Stream{{StreamID: 1, Aggregator: llotypes.AggregatorMedian}, {StreamID: 2, Aggregator: llotypes.AggregatorMode}, {StreamID: 3, Aggregator: llotypes.AggregatorQuote}}, + Opts: llotypes.ChannelOpts{1, 2, 3}, + }, + }) + + cdc := &channelDefinitionCache{definitions: dfns} + + assert.Equal(t, dfns, cdc.Definitions()) + }) + + t.Run("readLogs", func(t *testing.T) { + lp := &mockLogPoller{latestBlockErr: sql.ErrNoRows} + newLogCh := make(chan *channel_config_store.ChannelConfigStoreNewChannelDefinition, 100) + cdc := &channelDefinitionCache{donID: donID, lp: lp, lggr: logger.TestSugared(t), newLogCh: newLogCh} + + t.Run("skips if logpoller has no blocks", func(t *testing.T) { + ctx := tests.Context(t) + err := cdc.readLogs(ctx) + assert.NoError(t, err) + assert.Nil(t, cdc.newLog) + }) + t.Run("returns error on LatestBlock failure", func(t *testing.T) { + ctx := tests.Context(t) + lp.latestBlockErr = errors.New("test error") + + err := cdc.readLogs(ctx) + assert.EqualError(t, err, "test error") + assert.Nil(t, cdc.newLog) + }) + t.Run("does nothing if LatestBlock older or the same as current channel definitions block", func(t *testing.T) { + ctx := tests.Context(t) + lp.latestBlockErr = nil + lp.latestBlock = logpoller.LogPollerBlock{BlockNumber: 42} + cdc.definitionsBlockNum = 43 + + err := cdc.readLogs(ctx) + assert.NoError(t, err) + assert.Nil(t, cdc.newLog) + }) + t.Run("returns error if LogsWithSigs fails", func(t *testing.T) { + ctx := tests.Context(t) + cdc.definitionsBlockNum = 0 + lp.logsWithSigsErr = errors.New("test error 2") + + err := cdc.readLogs(ctx) + assert.EqualError(t, err, "test error 2") + assert.Nil(t, cdc.newLog) + }) + t.Run("ignores logs with different topic", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{{EventSig: common.Hash{1, 2, 3, 4}}} + + err := cdc.readLogs(ctx) + assert.NoError(t, err) + assert.Nil(t, cdc.newLog) + }) + t.Run("returns error if log is malformed", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{{EventSig: topicNewChannelDefinition}} + + err := cdc.readLogs(ctx) + assert.EqualError(t, err, "failed to unpack log data: abi: attempting to unmarshal an empty string while arguments are expected") + assert.Nil(t, cdc.newLog) + }) + t.Run("sets definitions and sends on channel if LogsWithSigs returns new event with a later version", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{makeLog(t, donID, uint32(43), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4})} + + err := cdc.readLogs(ctx) + require.NoError(t, err) + require.NotNil(t, cdc.newLog) + assert.Equal(t, uint32(43), cdc.newLog.Version) + assert.Equal(t, "http://example.com/xxx.json", cdc.newLog.Url) + assert.Equal(t, [32]byte{1, 2, 3, 4}, cdc.newLog.Sha) + assert.Equal(t, int64(donID), cdc.newLog.DonId.Int64()) + + func() { + for { + select { + case log := <-newLogCh: + assert.Equal(t, cdc.newLog, log) + default: + return + } + } + }() + }) + t.Run("does nothing if version older or the same as the one currently set", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{ + makeLog(t, donID, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), + makeLog(t, donID, uint32(43), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), + } + + err := cdc.readLogs(ctx) + require.NoError(t, err) + assert.Equal(t, uint32(43), cdc.newLog.Version) + }) + t.Run("in case of multiple logs, takes the latest", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{ + makeLog(t, donID, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), + makeLog(t, donID, uint32(45), "http://example.com/xxx2.json", [32]byte{2, 2, 3, 4}), + makeLog(t, donID, uint32(44), "http://example.com/xxx3.json", [32]byte{3, 2, 3, 4}), + makeLog(t, donID, uint32(43), "http://example.com/xxx4.json", [32]byte{4, 2, 3, 4}), + } + + err := cdc.readLogs(ctx) + require.NoError(t, err) + assert.Equal(t, uint32(45), cdc.newLog.Version) + assert.Equal(t, "http://example.com/xxx2.json", cdc.newLog.Url) + assert.Equal(t, [32]byte{2, 2, 3, 4}, cdc.newLog.Sha) + assert.Equal(t, int64(donID), cdc.newLog.DonId.Int64()) + + func() { + for { + select { + case log := <-newLogCh: + assert.Equal(t, cdc.newLog, log) + default: + return + } + } + }() + }) + t.Run("ignores logs with incorrect don ID", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{ + makeLog(t, donID+1, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), + } + + err := cdc.readLogs(ctx) + require.NoError(t, err) + assert.Equal(t, uint32(45), cdc.newLog.Version) + + func() { + for { + select { + case log := <-newLogCh: + t.Fatal("did not expect log with wrong donID, got: ", log) + default: + return + } + } + }() + }) + t.Run("ignores logs with wrong number of topics", func(t *testing.T) { + ctx := tests.Context(t) + lp.logsWithSigsErr = nil + lg := makeLog(t, donID, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}) + lg.Topics = lg.Topics[:1] + lp.logsWithSigs = []logpoller.Log{lg} + + err := cdc.readLogs(ctx) + require.NoError(t, err) + assert.Equal(t, uint32(45), cdc.newLog.Version) + + func() { + for { + select { + case log := <-newLogCh: + t.Fatal("did not expect log with missing topics, got: ", log) + default: + return + } + } + }() + }) + }) + + t.Run("fetchChannelDefinitions", func(t *testing.T) { + c := &mockHTTPClient{} + cdc := &channelDefinitionCache{ + lggr: logger.TestSugared(t), + client: c, + httpLimit: 2048, + } + + t.Run("nil ctx returns error", func(t *testing.T) { + _, err := cdc.fetchChannelDefinitions(nil, "notvalid://foos", [32]byte{}) //nolint + assert.EqualError(t, err, "failed to create http.Request; net/http: nil Context") + }) + + t.Run("networking error while making request returns error", func(t *testing.T) { + ctx := tests.Context(t) + c.resp = nil + c.err = errors.New("http request failed") + + _, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", [32]byte{}) + assert.EqualError(t, err, "error making http request: http request failed") + }) + + t.Run("server returns 500 returns error", func(t *testing.T) { + ctx := tests.Context(t) + c.err = nil + c.resp = &http.Response{StatusCode: 500, Body: io.NopCloser(bytes.NewReader([]byte{1, 2, 3}))} + + _, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", [32]byte{}) + assert.EqualError(t, err, "got error from http://example.com/definitions.json: (status code: 500, response body: \x01\x02\x03)") + }) + + var largeBody = make([]byte, 2048) + for i := range largeBody { + largeBody[i] = 'a' + } + + t.Run("server returns 404 returns error (and does not log entirety of huge response body)", func(t *testing.T) { + ctx := tests.Context(t) + c.err = nil + c.resp = &http.Response{StatusCode: 404, Body: io.NopCloser(bytes.NewReader(largeBody))} + + _, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", [32]byte{}) + assert.EqualError(t, err, "got error from http://example.com/definitions.json: (status code: 404, error reading response body: http: request body too large, response body: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)") + }) + + var hugeBody = make([]byte, 8096) + c.resp.Body = io.NopCloser(bytes.NewReader(hugeBody)) + + t.Run("server returns body that is too large", func(t *testing.T) { + ctx := tests.Context(t) + c.err = nil + c.resp = &http.Response{StatusCode: 200, Body: io.NopCloser(bytes.NewReader(hugeBody))} + + _, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", [32]byte{}) + assert.EqualError(t, err, "failed to read from body: http: request body too large") + }) + + t.Run("server returns invalid JSON returns error", func(t *testing.T) { + ctx := tests.Context(t) + c.err = nil + c.resp = &http.Response{StatusCode: 200, Body: io.NopCloser(bytes.NewReader([]byte{1, 2, 3}))} + + _, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", common.HexToHash("0xfd1780a6fc9ee0dab26ceb4b3941ab03e66ccd970d1db91612c66df4515b0a0a")) + assert.EqualError(t, err, "failed to decode JSON: invalid character '\\x01' looking for beginning of value") + }) + + t.Run("SHA mismatch returns error", func(t *testing.T) { + ctx := tests.Context(t) + c.err = nil + c.resp = &http.Response{StatusCode: 200, Body: io.NopCloser(bytes.NewReader([]byte(`{"foo":"bar"}`)))} + + _, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", [32]byte{}) + assert.EqualError(t, err, "SHA3 mismatch: expected 0000000000000000000000000000000000000000000000000000000000000000, got 4d3304d0d87c27a031cbb6bdf95da79b7b4552c3d0bef2e5a94f50810121e1e0") + }) + + t.Run("valid JSON matching SHA returns channel definitions", func(t *testing.T) { + ctx := tests.Context(t) + chainSelector := 4949039107694359620 // arbitrum mainnet + feedID := [32]byte{00, 03, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114} + expirationWindow := 3600 + multiplier := big.NewInt(1e18) + baseUSDFee := 10 + valid := fmt.Sprintf(` +{ + "42": { + "reportFormat": %d, + "chainSelector": %d, + "streams": [{"streamId": 52, "aggregator": %d}, {"streamId": 53, "aggregator": %d}, {"streamId": 55, "aggregator": %d}], + "opts": { + "feedId": "0x%x", + "expirationWindow": %d, + "multiplier": "%s", + "baseUSDFee": "%d" + } + } +}`, llotypes.ReportFormatEVMPremiumLegacy, chainSelector, llotypes.AggregatorMedian, llotypes.AggregatorMedian, llotypes.AggregatorQuote, feedID, expirationWindow, multiplier.String(), baseUSDFee) + + c.err = nil + c.resp = &http.Response{StatusCode: 200, Body: io.NopCloser(bytes.NewReader([]byte(valid)))} + + cd, err := cdc.fetchChannelDefinitions(ctx, "http://example.com/definitions.json", common.HexToHash("0x367bbc75f7b6c9fc66a98ea99f837ea7ac4a3c2d6a9ee284de018bd02c41b52d")) + assert.NoError(t, err) + assert.Equal(t, llotypes.ChannelDefinitions{0x2a: llotypes.ChannelDefinition{ReportFormat: 0x1, Streams: []llotypes.Stream{llotypes.Stream{StreamID: 0x34, Aggregator: 0x1}, llotypes.Stream{StreamID: 0x35, Aggregator: 0x1}, llotypes.Stream{StreamID: 0x37, Aggregator: 0x3}}, Opts: llotypes.ChannelOpts{0x7b, 0x22, 0x62, 0x61, 0x73, 0x65, 0x55, 0x53, 0x44, 0x46, 0x65, 0x65, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x3a, 0x33, 0x36, 0x30, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x65, 0x64, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x30, 0x30, 0x30, 0x33, 0x36, 0x62, 0x34, 0x61, 0x61, 0x37, 0x65, 0x35, 0x37, 0x63, 0x61, 0x37, 0x62, 0x36, 0x38, 0x61, 0x65, 0x31, 0x62, 0x66, 0x34, 0x35, 0x36, 0x35, 0x33, 0x66, 0x35, 0x36, 0x62, 0x36, 0x35, 0x36, 0x66, 0x64, 0x33, 0x61, 0x61, 0x33, 0x33, 0x35, 0x65, 0x66, 0x37, 0x66, 0x61, 0x65, 0x36, 0x39, 0x36, 0x62, 0x36, 0x36, 0x33, 0x66, 0x31, 0x62, 0x38, 0x34, 0x37, 0x32, 0x22, 0x2c, 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d}}}, cd) + }) + }) + + t.Run("persist", func(t *testing.T) { + cdc := &channelDefinitionCache{ + lggr: logger.TestSugared(t), + orm: nil, + addr: testutils.NewAddress(), + donID: donID, + definitions: llotypes.ChannelDefinitions{ + 1: { + ReportFormat: llotypes.ReportFormat(43), + Streams: []llotypes.Stream{{StreamID: 1, Aggregator: llotypes.AggregatorMedian}, {StreamID: 2, Aggregator: llotypes.AggregatorMode}, {StreamID: 3, Aggregator: llotypes.AggregatorQuote}}, + Opts: llotypes.ChannelOpts{1, 2, 3}, + }, + }, + definitionsBlockNum: 142, + } + + t.Run("does nothing if persisted version is up-to-date", func(t *testing.T) { + ctx := tests.Context(t) + cdc.definitionsVersion = 42 + cdc.persistedVersion = 42 + + memoryVersion, persistedVersion, err := cdc.persist(ctx) + assert.NoError(t, err) + assert.Equal(t, uint32(42), memoryVersion) + assert.Equal(t, uint32(42), persistedVersion) + assert.Equal(t, uint32(42), cdc.persistedVersion) + }) + + orm := &mockCDCORM{} + cdc.orm = orm + + t.Run("returns error on db failure and does not update persisted version", func(t *testing.T) { + ctx := tests.Context(t) + cdc.persistedVersion = 42 + cdc.definitionsVersion = 43 + orm.err = errors.New("test error") + + memoryVersion, persistedVersion, err := cdc.persist(ctx) + assert.EqualError(t, err, "test error") + assert.Equal(t, uint32(43), memoryVersion) + assert.Equal(t, uint32(42), persistedVersion) + assert.Equal(t, uint32(42), cdc.persistedVersion) + }) + + t.Run("updates persisted version on success", func(t *testing.T) { + ctx := tests.Context(t) + cdc.definitionsVersion = 43 + orm.err = nil + + memoryVersion, persistedVersion, err := cdc.persist(ctx) + assert.NoError(t, err) + assert.Equal(t, uint32(43), memoryVersion) + assert.Equal(t, uint32(43), persistedVersion) + assert.Equal(t, uint32(43), cdc.persistedVersion) + + assert.Equal(t, cdc.addr, orm.lastPersistedAddr) + assert.Equal(t, cdc.donID, orm.lastPersistedDonID) + assert.Equal(t, cdc.persistedVersion, orm.lastPersistedVersion) + assert.Equal(t, cdc.definitions, orm.lastPersistedDfns) + assert.Equal(t, cdc.definitionsBlockNum, orm.lastPersistedBlockNum) + }) + }) +} + +func Test_filterName(t *testing.T) { + s := filterName(common.Address{1, 2, 3}, 654) + assert.Equal(t, "OCR3 LLO ChannelDefinitionCachePoller - 0x0102030000000000000000000000000000000000:654", s) } diff --git a/core/services/llo/onchain_config.go b/core/services/llo/onchain_config.go deleted file mode 100644 index 7b5cfffaa9f..00000000000 --- a/core/services/llo/onchain_config.go +++ /dev/null @@ -1,21 +0,0 @@ -package llo - -type OnchainConfig struct{} - -type OnchainConfigCodec interface { - Encode(OnchainConfig) ([]byte, error) - Decode([]byte) (OnchainConfig, error) -} - -var _ OnchainConfigCodec = &JSONOnchainConfigCodec{} - -// TODO: Replace this with protobuf, if it is actually used for something -type JSONOnchainConfigCodec struct{} - -func (c *JSONOnchainConfigCodec) Encode(OnchainConfig) ([]byte, error) { - return nil, nil -} - -func (c *JSONOnchainConfigCodec) Decode([]byte) (OnchainConfig, error) { - return OnchainConfig{}, nil -} diff --git a/core/services/llo/orm.go b/core/services/llo/orm.go index 6b14e543268..f98955ff121 100644 --- a/core/services/llo/orm.go +++ b/core/services/llo/orm.go @@ -3,10 +3,9 @@ package llo import ( "context" "database/sql" - "encoding/json" "errors" "fmt" - "math/big" + "time" "github.com/ethereum/go-ethereum/common" @@ -14,52 +13,64 @@ import ( llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" ) -type ORM interface { +type ChainScopedORM interface { ChannelDefinitionCacheORM } -var _ ORM = &orm{} +type PersistedDefinitions struct { + ChainSelector uint64 `db:"chain_selector"` + Address common.Address `db:"addr"` + Definitions llotypes.ChannelDefinitions `db:"definitions"` + // The block number in which the log for this definitions was emitted + BlockNum int64 `db:"block_num"` + DonID uint32 `db:"don_id"` + Version uint32 `db:"version"` + UpdatedAt time.Time `db:"updated_at"` +} + +var _ ChainScopedORM = &chainScopedORM{} -type orm struct { - ds sqlutil.DataSource - evmChainID *big.Int +type chainScopedORM struct { + ds sqlutil.DataSource + chainSelector uint64 } -func NewORM(ds sqlutil.DataSource, evmChainID *big.Int) ORM { - return &orm{ds, evmChainID} +func NewChainScopedORM(ds sqlutil.DataSource, chainSelector uint64) ChainScopedORM { + return &chainScopedORM{ds, chainSelector} } -func (o *orm) LoadChannelDefinitions(ctx context.Context, addr common.Address) (dfns llotypes.ChannelDefinitions, blockNum int64, err error) { - type scd struct { - Definitions []byte `db:"definitions"` - BlockNum int64 `db:"block_num"` - } - var scanned scd - err = o.ds.GetContext(ctx, &scanned, "SELECT definitions, block_num FROM channel_definitions WHERE evm_chain_id = $1 AND addr = $2", o.evmChainID.String(), addr) +func (o *chainScopedORM) LoadChannelDefinitions(ctx context.Context, addr common.Address, donID uint32) (pd *PersistedDefinitions, err error) { + pd = new(PersistedDefinitions) + err = o.ds.GetContext(ctx, pd, "SELECT * FROM channel_definitions WHERE chain_selector = $1 AND addr = $2 AND don_id = $3", o.chainSelector, addr, donID) if errors.Is(err, sql.ErrNoRows) { - return dfns, blockNum, nil + return nil, nil } else if err != nil { - return nil, 0, fmt.Errorf("failed to LoadChannelDefinitions; %w", err) - } - - if err = json.Unmarshal(scanned.Definitions, &dfns); err != nil { - return nil, 0, fmt.Errorf("failed to LoadChannelDefinitions; JSON Unmarshal failure; %w", err) + return nil, fmt.Errorf("failed to LoadChannelDefinitions; %w", err) } - return dfns, scanned.BlockNum, nil + return pd, nil } -// TODO: Test this method -// https://smartcontract-it.atlassian.net/jira/software/c/projects/MERC/issues/MERC-3653 -func (o *orm) StoreChannelDefinitions(ctx context.Context, addr common.Address, dfns llotypes.ChannelDefinitions, blockNum int64) error { +// StoreChannelDefinitions will store a ChannelDefinitions list for a given chain_selector, addr, don_id +// It only updates if the new version is greater than the existing record +func (o *chainScopedORM) StoreChannelDefinitions(ctx context.Context, addr common.Address, donID, version uint32, dfns llotypes.ChannelDefinitions, blockNum int64) error { _, err := o.ds.ExecContext(ctx, ` -INSERT INTO channel_definitions (evm_chain_id, addr, definitions, block_num, updated_at) -VALUES ($1, $2, $3, $4, NOW()) -ON CONFLICT (evm_chain_id, addr) DO UPDATE -SET definitions = $3, block_num = $4, updated_at = NOW() -`, o.evmChainID.String(), addr, dfns, blockNum) +INSERT INTO channel_definitions (chain_selector, addr, don_id, definitions, block_num, version, updated_at) +VALUES ($1, $2, $3, $4, $5, $6, NOW()) +ON CONFLICT (chain_selector, addr, don_id) DO UPDATE +SET definitions = $4, block_num = $5, version = $6, updated_at = NOW() +WHERE EXCLUDED.version > channel_definitions.version +`, o.chainSelector, addr, donID, dfns, blockNum, version) if err != nil { return fmt.Errorf("StoreChannelDefinitions failed: %w", err) } return nil } + +func (o *chainScopedORM) CleanupChannelDefinitions(ctx context.Context, addr common.Address, donID uint32) error { + _, err := o.ds.ExecContext(ctx, "DELETE FROM channel_definitions WHERE chain_selector = $1 AND addr = $2 AND don_id = $3", o.chainSelector, addr, donID) + if err != nil { + return fmt.Errorf("failed to CleanupChannelDefinitions; %w", err) + } + return nil +} diff --git a/core/services/llo/orm_test.go b/core/services/llo/orm_test.go index bc2d88130e6..6a4fd8f4c7d 100644 --- a/core/services/llo/orm_test.go +++ b/core/services/llo/orm_test.go @@ -1,91 +1,156 @@ package llo import ( + "fmt" + "math/rand" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) func Test_ORM(t *testing.T) { - t.Skip("waiting on https://github.com/smartcontractkit/chainlink/pull/13780") - // db := pgtest.NewSqlxDB(t) - // orm := NewORM(db, testutils.FixtureChainID) - // ctx := testutils.Context(t) - - // addr1 := testutils.NewAddress() - // addr2 := testutils.NewAddress() - // addr3 := testutils.NewAddress() - - // t.Run("LoadChannelDefinitions", func(t *testing.T) { - // t.Run("returns zero values if nothing in database", func(t *testing.T) { - // cd, blockNum, err := orm.LoadChannelDefinitions(ctx, addr1) - // require.NoError(t, err) - - // assert.Zero(t, cd) - // assert.Zero(t, blockNum) - // }) - // t.Run("loads channel definitions from database", func(t *testing.T) { - // expectedBlockNum := rand.Int63() - // expectedBlockNum2 := rand.Int63() - // cid1 := rand.Uint32() - // cid2 := rand.Uint32() - - // channelDefsJSON := fmt.Sprintf(` - // { - // "%d": { - // "reportFormat": 42, - // "chainSelector": 142, - // "streamIds": [1, 2] - // }, - // "%d": { - // "reportFormat": 42, - // "chainSelector": 142, - // "streamIds": [1, 3] - // } - // } - // `, cid1, cid2) - // pgtest.MustExec(t, db, ` - // INSERT INTO channel_definitions(addr, evm_chain_id, definitions, block_num, updated_at) - // VALUES ( $1, $2, $3, $4, NOW()) - // `, addr1, testutils.FixtureChainID.String(), channelDefsJSON, expectedBlockNum) - - // pgtest.MustExec(t, db, ` - // INSERT INTO channel_definitions(addr, evm_chain_id, definitions, block_num, updated_at) - // VALUES ( $1, $2, $3, $4, NOW()) - // `, addr2, testutils.FixtureChainID.String(), `{}`, expectedBlockNum2) - - // { - // // alternative chain ID; we expect these ones to be ignored - // pgtest.MustExec(t, db, ` - // INSERT INTO channel_definitions(addr, evm_chain_id, definitions, block_num, updated_at) - // VALUES ( $1, $2, $3, $4, NOW()) - // `, addr1, testutils.SimulatedChainID.String(), channelDefsJSON, expectedBlockNum) - // pgtest.MustExec(t, db, ` - // INSERT INTO channel_definitions(addr, evm_chain_id, definitions, block_num, updated_at) - // VALUES ( $1, $2, $3, $4, NOW()) - // `, addr3, testutils.SimulatedChainID.String(), channelDefsJSON, expectedBlockNum) - // } - - // cd, blockNum, err := orm.LoadChannelDefinitions(ctx, addr1) - // require.NoError(t, err) - - // assert.Equal(t, llotypes.ChannelDefinitions{ - // cid1: llotypes.ChannelDefinition{ - // ReportFormat: 42, - // ChainSelector: 142, - // StreamIDs: []llotypes.StreamID{1, 2}, - // }, - // cid2: llotypes.ChannelDefinition{ - // ReportFormat: 42, - // ChainSelector: 142, - // StreamIDs: []llotypes.StreamID{1, 3}, - // }, - // }, cd) - // assert.Equal(t, expectedBlockNum, blockNum) - - // cd, blockNum, err = orm.LoadChannelDefinitions(ctx, addr2) - // require.NoError(t, err) - - // assert.Equal(t, llotypes.ChannelDefinitions{}, cd) - // assert.Equal(t, expectedBlockNum2, blockNum) - // }) - // }) + const ETHMainnetChainSelector uint64 = 5009297550715157269 + const OtherChainSelector uint64 = 1234567890 + + db := pgtest.NewSqlxDB(t) + orm := NewChainScopedORM(db, ETHMainnetChainSelector) + ctx := testutils.Context(t) + + addr1 := testutils.NewAddress() + addr2 := testutils.NewAddress() + addr3 := testutils.NewAddress() + + donID1 := uint32(1) + donID2 := uint32(2) + + t.Run("LoadChannelDefinitions", func(t *testing.T) { + t.Run("returns zero values if nothing in database", func(t *testing.T) { + pd, err := orm.LoadChannelDefinitions(ctx, addr1, donID1) + assert.NoError(t, err) + assert.Nil(t, pd) + }) + t.Run("loads channel definitions from database for the given don ID", func(t *testing.T) { + expectedBlockNum := rand.Int63() + expectedBlockNum2 := rand.Int63() + cid1 := rand.Uint32() + cid2 := rand.Uint32() + + channelDefsJSON := fmt.Sprintf(` +{ + "%d": { + "reportFormat": 42, + "chainSelector": 142, + "streams": [{"streamId": 1, "aggregator": "median"}, {"streamId": 2, "aggregator": "mode"}], + "opts": {"foo":"bar"} + }, + "%d": { + "reportFormat": 43, + "chainSelector": 142, + "streams": [{"streamId": 1, "aggregator": "median"}, {"streamId": 3, "aggregator": "quote"}] + } +} + `, cid1, cid2) + pgtest.MustExec(t, db, ` + INSERT INTO channel_definitions(addr, chain_selector, don_id, definitions, block_num, version, updated_at) + VALUES ($1, $2, $3, $4, $5, $6, NOW()) + `, addr1, ETHMainnetChainSelector, 1, channelDefsJSON, expectedBlockNum, 1) + + pgtest.MustExec(t, db, ` + INSERT INTO channel_definitions(addr, chain_selector, don_id, definitions, block_num, version, updated_at) + VALUES ($1, $2, $3, $4, $5, $6, NOW()) + `, addr2, ETHMainnetChainSelector, 1, `{}`, expectedBlockNum2, 1) + + { + // alternative chain selector; we expect these ones to be ignored + pgtest.MustExec(t, db, ` + INSERT INTO channel_definitions(addr, chain_selector, don_id, definitions, block_num, version, updated_at) + VALUES ($1, $2, $3, $4, $5, $6, NOW()) + `, addr1, OtherChainSelector, 1, channelDefsJSON, expectedBlockNum, 1) + pgtest.MustExec(t, db, ` + INSERT INTO channel_definitions(addr, chain_selector, don_id, definitions, block_num, version, updated_at) + VALUES ($1, $2, $3, $4, $5, $6, NOW()) + `, addr3, OtherChainSelector, 1, channelDefsJSON, expectedBlockNum, 1) + } + + pd, err := orm.LoadChannelDefinitions(ctx, addr1, donID1) + require.NoError(t, err) + + assert.Equal(t, ETHMainnetChainSelector, pd.ChainSelector) + assert.Equal(t, addr1, pd.Address) + assert.Equal(t, expectedBlockNum, pd.BlockNum) + assert.Equal(t, donID1, pd.DonID) + assert.Equal(t, uint32(1), pd.Version) + assert.Equal(t, llotypes.ChannelDefinitions{ + cid1: llotypes.ChannelDefinition{ + ReportFormat: 42, + Streams: []llotypes.Stream{{StreamID: 1, Aggregator: llotypes.AggregatorMedian}, {StreamID: 2, Aggregator: llotypes.AggregatorMode}}, + Opts: []byte(`{"foo":"bar"}`), + }, + cid2: llotypes.ChannelDefinition{ + ReportFormat: 43, + Streams: []llotypes.Stream{{StreamID: 1, Aggregator: llotypes.AggregatorMedian}, {StreamID: 3, Aggregator: llotypes.AggregatorQuote}}, + }, + }, pd.Definitions) + + // does not load erroneously for a different address + pd, err = orm.LoadChannelDefinitions(ctx, addr2, donID1) + require.NoError(t, err) + + assert.Equal(t, llotypes.ChannelDefinitions{}, pd.Definitions) + assert.Equal(t, expectedBlockNum2, pd.BlockNum) + + // does not load erroneously for a different don ID + pd, err = orm.LoadChannelDefinitions(ctx, addr1, donID2) + require.NoError(t, err) + + assert.Equal(t, (*PersistedDefinitions)(nil), pd) + }) + }) + + t.Run("StoreChannelDefinitions", func(t *testing.T) { + expectedBlockNum := rand.Int63() + cid1 := rand.Uint32() + cid2 := rand.Uint32() + defs := llotypes.ChannelDefinitions{ + cid1: llotypes.ChannelDefinition{ + ReportFormat: llotypes.ReportFormatJSON, + Streams: []llotypes.Stream{{StreamID: 1, Aggregator: llotypes.AggregatorMedian}, {StreamID: 2, Aggregator: llotypes.AggregatorMode}}, + Opts: []byte(`{"foo":"bar"}`), + }, + cid2: llotypes.ChannelDefinition{ + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + Streams: []llotypes.Stream{{StreamID: 1, Aggregator: llotypes.AggregatorMedian}, {StreamID: 3, Aggregator: llotypes.AggregatorQuote}}, + }, + } + + t.Run("stores channel definitions in the database", func(t *testing.T) { + err := orm.StoreChannelDefinitions(ctx, addr1, donID1, 42, defs, expectedBlockNum) + require.NoError(t, err) + + pd, err := orm.LoadChannelDefinitions(ctx, addr1, donID1) + require.NoError(t, err) + assert.Equal(t, ETHMainnetChainSelector, pd.ChainSelector) + assert.Equal(t, addr1, pd.Address) + assert.Equal(t, expectedBlockNum, pd.BlockNum) + assert.Equal(t, donID1, pd.DonID) + assert.Equal(t, uint32(42), pd.Version) + assert.Equal(t, defs, pd.Definitions) + }) + t.Run("does not update if version is older than the database persisted version", func(t *testing.T) { + // try to update with an older version + err := orm.StoreChannelDefinitions(ctx, addr1, donID1, 41, llotypes.ChannelDefinitions{}, expectedBlockNum) + require.NoError(t, err) + + pd, err := orm.LoadChannelDefinitions(ctx, addr1, donID1) + require.NoError(t, err) + assert.Equal(t, uint32(42), pd.Version) + assert.Equal(t, defs, pd.Definitions) + }) + }) } diff --git a/core/services/llo/plugin_scoped_retirement_report_cache.go b/core/services/llo/plugin_scoped_retirement_report_cache.go new file mode 100644 index 00000000000..74370f8d2a2 --- /dev/null +++ b/core/services/llo/plugin_scoped_retirement_report_cache.go @@ -0,0 +1,84 @@ +package llo + +import ( + "fmt" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "google.golang.org/protobuf/proto" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + + datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" +) + +type RetirementReportVerifier interface { + Verify(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool +} + +// PluginScopedRetirementReportCache is a wrapper around RetirementReportCache +// that implements CheckAttestedRetirementReport +// +// This is necessary because while config digest keys are globally unique, +// different plugins may implement different signing/verification strategies +var _ datastreamsllo.PredecessorRetirementReportCache = &pluginScopedRetirementReportCache{} + +type pluginScopedRetirementReportCache struct { + rrc RetirementReportCacheReader + verifier RetirementReportVerifier + codec datastreamsllo.RetirementReportCodec +} + +func NewPluginScopedRetirementReportCache(rrc RetirementReportCacheReader, verifier RetirementReportVerifier, codec datastreamsllo.RetirementReportCodec) datastreamsllo.PredecessorRetirementReportCache { + return &pluginScopedRetirementReportCache{ + rrc: rrc, + verifier: verifier, + codec: codec, + } +} + +func (pr *pluginScopedRetirementReportCache) CheckAttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest, serializedAttestedRetirementReport []byte) (datastreamsllo.RetirementReport, error) { + config, exists := pr.rrc.Config(predecessorConfigDigest) + if !exists { + return datastreamsllo.RetirementReport{}, fmt.Errorf("Verify failed; predecessor config not found for config digest %x", predecessorConfigDigest[:]) + } + + var arr AttestedRetirementReport + if err := proto.Unmarshal(serializedAttestedRetirementReport, &arr); err != nil { + return datastreamsllo.RetirementReport{}, fmt.Errorf("Verify failed; failed to unmarshal protobuf: %w", err) + } + + validSigs := 0 + for _, sig := range arr.Sigs { + // #nosec G115 + if sig.Signer >= uint32(len(config.Signers)) { + return datastreamsllo.RetirementReport{}, fmt.Errorf("Verify failed; attested report signer index out of bounds (got: %d, max: %d)", sig.Signer, len(config.Signers)-1) + } + signer := config.Signers[sig.Signer] + valid := pr.verifier.Verify(types.OnchainPublicKey(signer), predecessorConfigDigest, arr.SeqNr, ocr3types.ReportWithInfo[llotypes.ReportInfo]{ + Report: arr.RetirementReport, + Info: llotypes.ReportInfo{ReportFormat: llotypes.ReportFormatRetirement}, + }, sig.Signature) + if !valid { + continue + } + validSigs++ + } + if validSigs <= int(config.F) { + return datastreamsllo.RetirementReport{}, fmt.Errorf("Verify failed; not enough valid signatures (got: %d, need: %d)", validSigs, config.F+1) + } + decoded, err := pr.codec.Decode(arr.RetirementReport) + if err != nil { + return datastreamsllo.RetirementReport{}, fmt.Errorf("Verify failed; failed to decode retirement report: %w", err) + } + return decoded, nil +} + +func (pr *pluginScopedRetirementReportCache) AttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest) ([]byte, error) { + arr, exists := pr.rrc.AttestedRetirementReport(predecessorConfigDigest) + if !exists { + return nil, nil + } + return arr, nil +} diff --git a/core/services/llo/plugin_scoped_retirement_report_cache_test.go b/core/services/llo/plugin_scoped_retirement_report_cache_test.go new file mode 100644 index 00000000000..e1afb203fd2 --- /dev/null +++ b/core/services/llo/plugin_scoped_retirement_report_cache_test.go @@ -0,0 +1,164 @@ +package llo + +import ( + "errors" + "testing" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + + datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" +) + +type mockRetirementReportCache struct { + arr []byte + cfg Config + exists bool +} + +func (m *mockRetirementReportCache) AttestedRetirementReport(digest ocr2types.ConfigDigest) ([]byte, bool) { + return m.arr, m.exists +} +func (m *mockRetirementReportCache) Config(cd ocr2types.ConfigDigest) (Config, bool) { + return m.cfg, m.exists +} + +type mockVerifier struct { + verify func(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool +} + +func (m *mockVerifier) Verify(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool { + return m.verify(key, digest, seqNr, r, signature) +} + +type mockCodec struct { + decode func([]byte) (datastreamsllo.RetirementReport, error) +} + +func (m *mockCodec) Encode(datastreamsllo.RetirementReport) ([]byte, error) { + panic("not implemented") +} +func (m *mockCodec) Decode(b []byte) (datastreamsllo.RetirementReport, error) { + return m.decode(b) +} + +func Test_PluginScopedRetirementReportCache(t *testing.T) { + rrc := &mockRetirementReportCache{} + v := &mockVerifier{} + c := &mockCodec{} + psrrc := NewPluginScopedRetirementReportCache(rrc, v, c) + exampleDigest := ocr2types.ConfigDigest{1} + exampleDigest2 := ocr2types.ConfigDigest{2} + + exampleUnattestedSerializedRetirementReport := []byte("foo example unattested retirement report") + + validArr := AttestedRetirementReport{ + RetirementReport: exampleUnattestedSerializedRetirementReport, + SeqNr: 42, + Sigs: []*AttributedOnchainSignature{ + { + Signer: 0, + Signature: []byte("bar0"), + }, + { + Signer: 1, + Signature: []byte("bar1"), + }, + { + Signer: 2, + Signature: []byte("bar2"), + }, + { + Signer: 3, + Signature: []byte("bar3"), + }, + }, + } + serializedValidArr, err := proto.Marshal(&validArr) + require.NoError(t, err) + + t.Run("CheckAttestedRetirementReport", func(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + // config missing + _, err := psrrc.CheckAttestedRetirementReport(exampleDigest, []byte("not valid")) + assert.EqualError(t, err, "Verify failed; predecessor config not found for config digest 0100000000000000000000000000000000000000000000000000000000000000") + + rrc.cfg = Config{Digest: exampleDigest} + rrc.exists = true + + // unmarshal failure + _, err = psrrc.CheckAttestedRetirementReport(exampleDigest, []byte("not valid")) + require.Error(t, err) + assert.Contains(t, err.Error(), "Verify failed; failed to unmarshal protobuf: proto") + + // config is invalid (no signers) + _, err = psrrc.CheckAttestedRetirementReport(exampleDigest, serializedValidArr) + assert.EqualError(t, err, "Verify failed; attested report signer index out of bounds (got: 0, max: -1)") + + rrc.cfg = Config{Digest: exampleDigest, Signers: [][]byte{[]byte{0}, []byte{1}, []byte{2}, []byte{3}}, F: 1} + + // no valid sigs + v.verify = func(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool { + return false + } + _, err = psrrc.CheckAttestedRetirementReport(exampleDigest, serializedValidArr) + assert.EqualError(t, err, "Verify failed; not enough valid signatures (got: 0, need: 2)") + + // not enough valid sigs + v.verify = func(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool { + return string(signature) == "bar0" + } + _, err = psrrc.CheckAttestedRetirementReport(exampleDigest, serializedValidArr) + assert.EqualError(t, err, "Verify failed; not enough valid signatures (got: 1, need: 2)") + + // enough valid sigs, but codec decode fails + v.verify = func(key types.OnchainPublicKey, digest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[llotypes.ReportInfo], signature []byte) bool { + if string(signature) == "bar0" || string(signature) == "bar3" { + return true + } + return false + } + c.decode = func([]byte) (datastreamsllo.RetirementReport, error) { + return datastreamsllo.RetirementReport{}, errors.New("codec decode failed") + } + _, err = psrrc.CheckAttestedRetirementReport(exampleDigest, serializedValidArr) + assert.EqualError(t, err, "Verify failed; failed to decode retirement report: codec decode failed") + + exampleRetirementReport := datastreamsllo.RetirementReport{ValidAfterSeconds: map[llotypes.ChannelID]uint32{ + 0: 1, + }, + } + + // enough valid sigs and codec decode succeeds + c.decode = func(b []byte) (datastreamsllo.RetirementReport, error) { + assert.Equal(t, exampleUnattestedSerializedRetirementReport, b) + return exampleRetirementReport, nil + } + decoded, err := psrrc.CheckAttestedRetirementReport(exampleDigest, serializedValidArr) + assert.NoError(t, err) + assert.Equal(t, exampleRetirementReport, decoded) + }) + }) + t.Run("AttestedRetirementReport", func(t *testing.T) { + rrc.arr = []byte("foo") + rrc.exists = true + + // exists + arr, err := psrrc.AttestedRetirementReport(exampleDigest) + assert.NoError(t, err) + assert.Equal(t, rrc.arr, arr) + + rrc.exists = false + + // doesn't exist + arr, err = psrrc.AttestedRetirementReport(exampleDigest2) + assert.NoError(t, err) + assert.Nil(t, arr) + }) +} diff --git a/core/services/llo/retirement_report_cache.go b/core/services/llo/retirement_report_cache.go new file mode 100644 index 00000000000..daf894a056f --- /dev/null +++ b/core/services/llo/retirement_report_cache.go @@ -0,0 +1,151 @@ +package llo + +import ( + "context" + "fmt" + sync "sync" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "google.golang.org/protobuf/proto" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" +) + +// RetirementReportCacheReader is used by the plugin-scoped +// RetirementReportCache +type RetirementReportCacheReader interface { + AttestedRetirementReport(cd ocr2types.ConfigDigest) ([]byte, bool) + Config(cd ocr2types.ConfigDigest) (Config, bool) +} + +// RetirementReportCache is intended to be a global singleton that is wrapped +// by a PluginScopedRetirementReportCache for a given plugin +type RetirementReportCache interface { + services.Service + StoreAttestedRetirementReport(ctx context.Context, cd ocrtypes.ConfigDigest, seqNr uint64, retirementReport []byte, sigs []types.AttributedOnchainSignature) error + StoreConfig(ctx context.Context, cd ocr2types.ConfigDigest, signers [][]byte, f uint8) error + RetirementReportCacheReader +} + +type retirementReportCache struct { + services.Service + eng *services.Engine + + mu sync.RWMutex + arrs map[ocr2types.ConfigDigest][]byte + configs map[ocr2types.ConfigDigest]Config + + orm RetirementReportCacheORM +} + +func NewRetirementReportCache(lggr logger.Logger, ds sqlutil.DataSource) RetirementReportCache { + orm := &retirementReportCacheORM{ds: ds} + return newRetirementReportCache(lggr, orm) +} + +func newRetirementReportCache(lggr logger.Logger, orm RetirementReportCacheORM) *retirementReportCache { + r := &retirementReportCache{ + arrs: make(map[ocr2types.ConfigDigest][]byte), + configs: make(map[ocr2types.ConfigDigest]Config), + orm: orm, + } + r.Service, r.eng = services.Config{ + Name: "RetirementReportCache", + Start: r.start, + }.NewServiceEngine(lggr) + return r +} + +// NOTE: Could do this lazily instead if we wanted to avoid a performance hit +// or potential tables missing etc on application startup (since +// RetirementReportCache is global) +func (r *retirementReportCache) start(ctx context.Context) (err error) { + // Load all attested retirement reports from the ORM + // and store them in the cache + r.arrs, err = r.orm.LoadAttestedRetirementReports(ctx) + if err != nil { + return fmt.Errorf("failed to load attested retirement reports: %w", err) + } + configs, err := r.orm.LoadConfigs(ctx) + if err != nil { + return fmt.Errorf("failed to load configs: %w", err) + } + for _, c := range configs { + r.configs[c.Digest] = c + } + return nil +} + +func (r *retirementReportCache) StoreAttestedRetirementReport(ctx context.Context, cd ocr2types.ConfigDigest, seqNr uint64, retirementReport []byte, sigs []types.AttributedOnchainSignature) error { + r.mu.RLock() + if _, ok := r.arrs[cd]; ok { + r.mu.RUnlock() + return nil + } + r.mu.RUnlock() + + var pbSigs []*AttributedOnchainSignature + for _, s := range sigs { + pbSigs = append(pbSigs, &AttributedOnchainSignature{ + Signer: uint32(s.Signer), + Signature: s.Signature, + }) + } + attestedRetirementReport := AttestedRetirementReport{ + RetirementReport: retirementReport, + SeqNr: seqNr, + Sigs: pbSigs, + } + + serialized, err := proto.Marshal(&attestedRetirementReport) + if err != nil { + return fmt.Errorf("StoreAttestedRetirementReport failed; failed to marshal protobuf: %w", err) + } + + if err := r.orm.StoreAttestedRetirementReport(ctx, cd, serialized); err != nil { + return fmt.Errorf("StoreAttestedRetirementReport failed; failed to persist to ORM: %w", err) + } + + r.mu.Lock() + r.arrs[cd] = serialized + r.mu.Unlock() + + return nil +} + +func (r *retirementReportCache) StoreConfig(ctx context.Context, cd ocr2types.ConfigDigest, signers [][]byte, f uint8) error { + r.mu.RLock() + if _, ok := r.configs[cd]; ok { + r.mu.RUnlock() + return nil + } + r.mu.RUnlock() + + r.mu.Lock() + r.configs[cd] = Config{ + Digest: cd, + Signers: signers, + F: f, + } + r.mu.Unlock() + + return r.orm.StoreConfig(ctx, cd, signers, f) +} + +func (r *retirementReportCache) AttestedRetirementReport(predecessorConfigDigest ocr2types.ConfigDigest) ([]byte, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + arr, exists := r.arrs[predecessorConfigDigest] + return arr, exists +} + +func (r *retirementReportCache) Config(cd ocr2types.ConfigDigest) (Config, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + c, exists := r.configs[cd] + return c, exists +} diff --git a/core/services/llo/retirement_report_cache_test.go b/core/services/llo/retirement_report_cache_test.go new file mode 100644 index 00000000000..616c5e0e519 --- /dev/null +++ b/core/services/llo/retirement_report_cache_test.go @@ -0,0 +1,170 @@ +package llo + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +type mockORM struct { + storedAttestedRetirementReports map[ocr2types.ConfigDigest][]byte + storedConfigs map[ocr2types.ConfigDigest]Config + + err error +} + +func (m *mockORM) StoreAttestedRetirementReport(ctx context.Context, cd ocr2types.ConfigDigest, attestedRetirementReport []byte) error { + m.storedAttestedRetirementReports[cd] = attestedRetirementReport + return m.err +} +func (m *mockORM) LoadAttestedRetirementReports(ctx context.Context) (map[ocr2types.ConfigDigest][]byte, error) { + return m.storedAttestedRetirementReports, m.err +} +func (m *mockORM) StoreConfig(ctx context.Context, cd ocr2types.ConfigDigest, signers [][]byte, f uint8) error { + m.storedConfigs[cd] = Config{Signers: signers, F: f, Digest: cd} + return m.err +} +func (m *mockORM) LoadConfigs(ctx context.Context) ([]Config, error) { + configs := make([]Config, 0, len(m.storedConfigs)) + for _, config := range m.storedConfigs { + configs = append(configs, config) + } + return configs, m.err +} + +func Test_RetirementReportCache(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + orm := &mockORM{ + make(map[ocrtypes.ConfigDigest][]byte), + make(map[ocrtypes.ConfigDigest]Config), + nil, + } + exampleRetirementReport := []byte{1, 2, 3} + exampleRetirementReport2 := []byte{4, 5, 6} + exampleSignatures := []ocrtypes.AttributedOnchainSignature{ + {Signature: []byte("signature0"), Signer: 0}, + {Signature: []byte("signature1"), Signer: 1}, + {Signature: []byte("signature2"), Signer: 2}, + {Signature: []byte("signature3"), Signer: 3}, + } + // this is a serialized protobuf of report with 4 signers + exampleAttestedRetirementReport := []byte{0xa, 0x3, 0x1, 0x2, 0x3, 0x10, 0x64, 0x1a, 0xc, 0xa, 0xa, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x30, 0x1a, 0xe, 0xa, 0xa, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x31, 0x10, 0x1, 0x1a, 0xe, 0xa, 0xa, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x32, 0x10, 0x2, 0x1a, 0xe, 0xa, 0xa, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x33, 0x10, 0x3} + exampleDigest := ocrtypes.ConfigDigest{1} + exampleDigest2 := ocrtypes.ConfigDigest{2} + + seqNr := uint64(100) + + t.Run("start loads from ORM", func(t *testing.T) { + rrc := newRetirementReportCache(lggr, orm) + + t.Run("orm failure, errors", func(t *testing.T) { + orm.err = errors.New("orm failed") + err := rrc.start(ctx) + assert.EqualError(t, err, "failed to load attested retirement reports: orm failed") + }) + t.Run("orm success, loads both configs and attestedRetirementReports from orm", func(t *testing.T) { + orm.err = nil + orm.storedAttestedRetirementReports = map[ocr2types.ConfigDigest][]byte{ + exampleDigest: exampleAttestedRetirementReport, + exampleDigest2: exampleAttestedRetirementReport, + } + config1 := Config{Digest: exampleDigest, Signers: [][]byte{{1}, {2}, {3}, {4}}, F: 1} + config2 := Config{Digest: exampleDigest2, Signers: [][]byte{{5}, {6}, {7}, {8}}, F: 2} + orm.storedConfigs[exampleDigest] = config1 + orm.storedConfigs[exampleDigest2] = config2 + + err := rrc.start(ctx) + assert.NoError(t, err) + + assert.Len(t, rrc.arrs, 2) + assert.Equal(t, exampleAttestedRetirementReport, rrc.arrs[exampleDigest]) + assert.Equal(t, exampleAttestedRetirementReport, rrc.arrs[exampleDigest2]) + + assert.Len(t, rrc.configs, 2) + assert.Equal(t, config1, rrc.configs[exampleDigest]) + assert.Equal(t, config2, rrc.configs[exampleDigest2]) + }) + }) + + t.Run("StoreAttestedRetirementReport", func(t *testing.T) { + rrc := newRetirementReportCache(lggr, orm) + + err := rrc.StoreAttestedRetirementReport(ctx, exampleDigest, seqNr, exampleRetirementReport, exampleSignatures) + assert.NoError(t, err) + + assert.Len(t, rrc.arrs, 1) + assert.Equal(t, exampleAttestedRetirementReport, rrc.arrs[exampleDigest]) + assert.Equal(t, exampleAttestedRetirementReport, orm.storedAttestedRetirementReports[exampleDigest]) + + t.Run("does nothing if retirement report already exists for the given config digest", func(t *testing.T) { + err = rrc.StoreAttestedRetirementReport(ctx, exampleDigest, seqNr, exampleRetirementReport2, exampleSignatures) + assert.NoError(t, err) + assert.Len(t, rrc.arrs, 1) + assert.Equal(t, exampleAttestedRetirementReport, rrc.arrs[exampleDigest]) + }) + + t.Run("returns error if ORM store fails", func(t *testing.T) { + orm.err = errors.New("failed to store") + err = rrc.StoreAttestedRetirementReport(ctx, exampleDigest2, seqNr, exampleRetirementReport, exampleSignatures) + assert.Error(t, err) + + // it wasn't cached + assert.Len(t, rrc.arrs, 1) + }) + + t.Run("second retirement report succeeds when orm starts working again", func(t *testing.T) { + orm.err = nil + err := rrc.StoreAttestedRetirementReport(ctx, exampleDigest2, seqNr, exampleRetirementReport, exampleSignatures) + assert.NoError(t, err) + + assert.Len(t, rrc.arrs, 2) + assert.Equal(t, exampleAttestedRetirementReport, rrc.arrs[exampleDigest2]) + assert.Equal(t, exampleAttestedRetirementReport, orm.storedAttestedRetirementReports[exampleDigest2]) + + assert.Len(t, orm.storedAttestedRetirementReports, 2) + }) + }) + t.Run("AttestedRetirementReport", func(t *testing.T) { + rrc := newRetirementReportCache(lggr, orm) + + attestedRetirementReport, exists := rrc.AttestedRetirementReport(exampleDigest) + assert.False(t, exists) + assert.Nil(t, attestedRetirementReport) + + rrc.arrs[exampleDigest] = exampleAttestedRetirementReport + + attestedRetirementReport, exists = rrc.AttestedRetirementReport(exampleDigest) + assert.True(t, exists) + assert.Equal(t, exampleAttestedRetirementReport, attestedRetirementReport) + }) + t.Run("StoreConfig", func(t *testing.T) { + rrc := newRetirementReportCache(lggr, orm) + + signers := [][]byte{{1}, {2}, {3}, {4}} + + err := rrc.StoreConfig(ctx, exampleDigest, signers, 1) + assert.NoError(t, err) + + assert.Len(t, rrc.configs, 1) + assert.Equal(t, Config{Digest: exampleDigest, Signers: [][]byte{{1}, {2}, {3}, {4}}, F: 1}, rrc.configs[exampleDigest]) + assert.Equal(t, Config{Digest: exampleDigest, Signers: [][]byte{{1}, {2}, {3}, {4}}, F: 1}, orm.storedConfigs[exampleDigest]) + + t.Run("Config", func(t *testing.T) { + config, exists := rrc.Config(exampleDigest) + assert.True(t, exists) + assert.Equal(t, Config{Digest: exampleDigest, Signers: [][]byte{{1}, {2}, {3}, {4}}, F: 1}, config) + }) + }) +} diff --git a/core/services/llo/retirement_report_orm.go b/core/services/llo/retirement_report_orm.go new file mode 100644 index 00000000000..5601e4fcd2f --- /dev/null +++ b/core/services/llo/retirement_report_orm.go @@ -0,0 +1,110 @@ +package llo + +import ( + "context" + "errors" + "fmt" + + "github.com/lib/pq" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" +) + +type RetirementReportCacheORM interface { + StoreAttestedRetirementReport(ctx context.Context, cd ocr2types.ConfigDigest, attestedRetirementReport []byte) error + LoadAttestedRetirementReports(ctx context.Context) (map[ocr2types.ConfigDigest][]byte, error) + StoreConfig(ctx context.Context, cd ocr2types.ConfigDigest, signers [][]byte, f uint8) error + LoadConfigs(ctx context.Context) ([]Config, error) +} + +type retirementReportCacheORM struct { + ds sqlutil.DataSource +} + +func (o *retirementReportCacheORM) StoreAttestedRetirementReport(ctx context.Context, cd ocr2types.ConfigDigest, attestedRetirementReport []byte) error { + _, err := o.ds.ExecContext(ctx, ` +INSERT INTO llo_retirement_report_cache (config_digest, attested_retirement_report, updated_at) +VALUES ($1, $2, NOW()) +ON CONFLICT (config_digest) DO NOTHING +`, cd, attestedRetirementReport) + if err != nil { + return fmt.Errorf("StoreAttestedRetirementReport failed: %w", err) + } + return nil +} + +func (o *retirementReportCacheORM) LoadAttestedRetirementReports(ctx context.Context) (map[ocr2types.ConfigDigest][]byte, error) { + rows, err := o.ds.QueryContext(ctx, "SELECT config_digest, attested_retirement_report FROM llo_retirement_report_cache") + if err != nil { + return nil, fmt.Errorf("LoadAttestedRetirementReports failed: %w", err) + } + defer rows.Close() + + reports := make(map[ocr2types.ConfigDigest][]byte) + for rows.Next() { + var rawCd []byte + var arr []byte + if err := rows.Scan(&rawCd, &arr); err != nil { + return nil, fmt.Errorf("LoadAttestedRetirementReports failed: %w", err) + } + cd, err := ocr2types.BytesToConfigDigest(rawCd) + if err != nil { + return nil, fmt.Errorf("LoadAttestedRetirementReports failed to scan config digest: %w", err) + } + reports[cd] = arr + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("LoadAttestedRetirementReports failed: %w", err) + } + + return reports, nil +} + +func (o *retirementReportCacheORM) StoreConfig(ctx context.Context, cd ocr2types.ConfigDigest, signers [][]byte, f uint8) error { + _, err := o.ds.ExecContext(ctx, `INSERT INTO llo_retirement_report_cache_configs (config_digest, signers, f, updated_at) VALUES ($1, $2, $3, NOW())`, cd, signers, f) + return err +} + +type Config struct { + Digest [32]byte `db:"config_digest"` + Signers pq.ByteaArray `db:"signers"` + F uint8 `db:"f"` +} + +type scannableConfigDigest [32]byte + +func (s *scannableConfigDigest) Scan(src interface{}) error { + b, ok := src.([]byte) + if !ok { + return errors.New("type assertion to []byte failed") + } + + cd, err := ocr2types.BytesToConfigDigest(b) + if err != nil { + return err + } + copy(s[:], cd[:]) + return nil +} + +func (o *retirementReportCacheORM) LoadConfigs(ctx context.Context) (configs []Config, err error) { + type config struct { + Digest scannableConfigDigest `db:"config_digest"` + Signers pq.ByteaArray `db:"signers"` + F uint8 `db:"f"` + } + var rawCfgs []config + err = o.ds.SelectContext(ctx, &rawCfgs, `SELECT config_digest, signers, f FROM llo_retirement_report_cache_configs ORDER BY config_digest`) + if err != nil { + return nil, fmt.Errorf("LoadConfigs failed: %w", err) + } + for _, rawCfg := range rawCfgs { + var cfg Config + copy(cfg.Digest[:], rawCfg.Digest[:]) + cfg.Signers = rawCfg.Signers + cfg.F = rawCfg.F + configs = append(configs, cfg) + } + return +} diff --git a/core/services/llo/retirement_report_orm_test.go b/core/services/llo/retirement_report_orm_test.go new file mode 100644 index 00000000000..835bfaaef76 --- /dev/null +++ b/core/services/llo/retirement_report_orm_test.go @@ -0,0 +1,62 @@ +package llo + +import ( + "testing" + + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" +) + +func Test_RetirementReportCache_ORM(t *testing.T) { + db := pgtest.NewSqlxDB(t) + orm := &retirementReportCacheORM{db} + ctx := tests.Context(t) + + cd := ocr2types.ConfigDigest{1} + attestedRetirementReport := []byte("report1") + cd2 := ocr2types.ConfigDigest{2} + attestedRetirementReport2 := []byte("report2") + + t.Run("StoreAttestedRetirementReport", func(t *testing.T) { + err := orm.StoreAttestedRetirementReport(ctx, cd, attestedRetirementReport) + require.NoError(t, err) + err = orm.StoreAttestedRetirementReport(ctx, cd2, attestedRetirementReport2) + require.NoError(t, err) + }) + t.Run("LoadAttestedRetirementReports", func(t *testing.T) { + arrs, err := orm.LoadAttestedRetirementReports(ctx) + require.NoError(t, err) + + require.Len(t, arrs, 2) + assert.Equal(t, attestedRetirementReport, arrs[cd]) + assert.Equal(t, attestedRetirementReport2, arrs[cd2]) + }) + t.Run("StoreConfig", func(t *testing.T) { + signers := [][]byte{[]byte("signer1"), []byte("signer2")} + err := orm.StoreConfig(ctx, cd, signers, 1) + require.NoError(t, err) + + err = orm.StoreConfig(ctx, cd2, signers, 2) + require.NoError(t, err) + }) + t.Run("LoadConfigs", func(t *testing.T) { + configs, err := orm.LoadConfigs(ctx) + require.NoError(t, err) + + require.Len(t, configs, 2) + assert.Equal(t, Config{ + Digest: cd, + Signers: [][]byte{[]byte("signer1"), []byte("signer2")}, + F: 1, + }, configs[0]) + assert.Equal(t, Config{ + Digest: cd2, + Signers: [][]byte{[]byte("signer1"), []byte("signer2")}, + F: 2, + }, configs[1]) + }) +} diff --git a/core/services/llo/static_channel_definitions_cache.go b/core/services/llo/static_channel_definitions_cache.go index 98ef3642cb7..980625bd599 100644 --- a/core/services/llo/static_channel_definitions_cache.go +++ b/core/services/llo/static_channel_definitions_cache.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) // A CDC that loads a static JSON of channel definitions; useful for @@ -27,7 +27,7 @@ func NewStaticChannelDefinitionCache(lggr logger.Logger, dfnstr string) (llotype if err := json.Unmarshal([]byte(dfnstr), &definitions); err != nil { return nil, err } - return &staticCDC{services.StateMachine{}, lggr.Named("StaticChannelDefinitionCache"), definitions}, nil + return &staticCDC{services.StateMachine{}, logger.Named(lggr, "StaticChannelDefinitionCache"), definitions}, nil } func (s *staticCDC) Start(context.Context) error { diff --git a/core/services/llo/telemetry.go b/core/services/llo/telemetry.go new file mode 100644 index 00000000000..62b586f5cc8 --- /dev/null +++ b/core/services/llo/telemetry.go @@ -0,0 +1,184 @@ +package llo + +import ( + "context" + "errors" + "fmt" + + "github.com/smartcontractkit/libocr/commontypes" + "google.golang.org/protobuf/proto" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-data-streams/llo" + + "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/eautils" + mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" +) + +const adapterLWBAErrorName = "AdapterLWBAError" + +type Telemeter interface { + EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.TaskRunResults, streamID uint32, opts llo.DSOpts, val llo.StreamValue, err error) +} + +type TelemeterService interface { + Telemeter + services.Service +} + +func NewTelemeterService(lggr logger.Logger, monitoringEndpoint commontypes.MonitoringEndpoint) TelemeterService { + if monitoringEndpoint == nil { + return NullTelemeter + } + return newTelemeter(lggr, monitoringEndpoint) +} + +func newTelemeter(lggr logger.Logger, monitoringEndpoint commontypes.MonitoringEndpoint) *telemeter { + chTelemetryObservation := make(chan TelemetryObservation, 100) + t := &telemeter{ + chTelemetryObservation: chTelemetryObservation, + monitoringEndpoint: monitoringEndpoint, + } + t.Service, t.eng = services.Config{ + Name: "LLOTelemeterService", + Start: t.start, + }.NewServiceEngine(lggr) + + return t +} + +type telemeter struct { + services.Service + eng *services.Engine + + monitoringEndpoint commontypes.MonitoringEndpoint + chTelemetryObservation chan TelemetryObservation +} + +func (t *telemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.TaskRunResults, streamID uint32, opts llo.DSOpts, val llo.StreamValue, err error) { + var adapterError *eautils.AdapterError + var dpInvariantViolationDetected bool + if errors.As(err, &adapterError) && adapterError.Name == adapterLWBAErrorName { + dpInvariantViolationDetected = true + } else if err != nil { + // ignore errors + return + } + tObs := TelemetryObservation{run, trrs, streamID, opts, val, dpInvariantViolationDetected} + select { + case t.chTelemetryObservation <- tObs: + default: + } +} + +func (t *telemeter) start(_ context.Context) error { + t.eng.Go(func(ctx context.Context) { + for { + select { + case tObs := <-t.chTelemetryObservation: + t.collectV3PremiumLegacyTelemetry(tObs) + case <-ctx.Done(): + return + } + } + }) + return nil +} + +func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) { + eaTelemetryValues := ocrcommon.ParseMercuryEATelemetry(t.eng.SugaredLogger, d.trrs, mercuryutils.REPORT_V3) + for _, eaTelem := range eaTelemetryValues { + var benchmarkPrice, bidPrice, askPrice int64 + var bp, bid, ask string + switch v := d.val.(type) { + case *llo.Decimal: + benchmarkPrice = v.Decimal().IntPart() + bp = v.Decimal().String() + case *llo.Quote: + benchmarkPrice = v.Benchmark.IntPart() + bp = v.Benchmark.String() + bidPrice = v.Bid.IntPart() + bid = v.Bid.String() + askPrice = v.Ask.IntPart() + ask = v.Ask.String() + } + epoch, round := evm.SeqNrToEpochAndRound(d.opts.OutCtx().SeqNr) + tea := &telem.EnhancedEAMercury{ + DataSource: eaTelem.DataSource, + DpBenchmarkPrice: eaTelem.DpBenchmarkPrice, + DpBid: eaTelem.DpBid, + DpAsk: eaTelem.DpAsk, + DpInvariantViolationDetected: d.dpInvariantViolationDetected, + BridgeTaskRunStartedTimestamp: eaTelem.BridgeTaskRunStartedTimestamp, + BridgeTaskRunEndedTimestamp: eaTelem.BridgeTaskRunEndedTimestamp, + ProviderRequestedTimestamp: eaTelem.ProviderRequestedTimestamp, + ProviderReceivedTimestamp: eaTelem.ProviderReceivedTimestamp, + ProviderDataStreamEstablished: eaTelem.ProviderDataStreamEstablished, + ProviderIndicatedTime: eaTelem.ProviderIndicatedTime, + Feed: fmt.Sprintf("streamID:%d", d.streamID), + ObservationBenchmarkPrice: benchmarkPrice, + ObservationBid: bidPrice, + ObservationAsk: askPrice, + ObservationBenchmarkPriceString: bp, + ObservationBidString: bid, + ObservationAskString: ask, + IsLinkFeed: false, + IsNativeFeed: false, + ConfigDigest: d.opts.ConfigDigest().Hex(), + Round: int64(round), + Epoch: int64(epoch), + AssetSymbol: eaTelem.AssetSymbol, + Version: uint32(1000 + mercuryutils.REPORT_V3), // add 1000 to distinguish between legacy feeds, this can be changed if necessary + } + + bytes, err := proto.Marshal(tea) + if err != nil { + t.eng.SugaredLogger.Warnf("protobuf marshal failed %v", err.Error()) + continue + } + + t.monitoringEndpoint.SendLog(bytes) + } +} + +type TelemetryObservation struct { + run *pipeline.Run + trrs pipeline.TaskRunResults + streamID uint32 + opts llo.DSOpts + val llo.StreamValue + dpInvariantViolationDetected bool +} + +var NullTelemeter TelemeterService = &nullTelemeter{} + +type nullTelemeter struct{} + +func (t *nullTelemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.TaskRunResults, streamID uint32, opts llo.DSOpts, val llo.StreamValue, err error) { +} +func (t *nullTelemeter) Start(context.Context) error { + return nil +} +func (t *nullTelemeter) Close() error { + return nil +} +func (t *nullTelemeter) Healthy() error { + return nil +} +func (t *nullTelemeter) Unhealthy() error { + return nil +} +func (t *nullTelemeter) HealthReport() map[string]error { + return nil +} +func (t *nullTelemeter) Name() string { + return "NullTelemeter" +} +func (t *nullTelemeter) Ready() error { + return nil +} diff --git a/core/services/llo/telemetry_test.go b/core/services/llo/telemetry_test.go new file mode 100644 index 00000000000..ec77e959d24 --- /dev/null +++ b/core/services/llo/telemetry_test.go @@ -0,0 +1,216 @@ +package llo + +import ( + "errors" + "testing" + "time" + + "github.com/shopspring/decimal" + "github.com/smartcontractkit/libocr/commontypes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "gopkg.in/guregu/null.v4" + + "github.com/smartcontractkit/chainlink-data-streams/llo" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/eautils" + "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" +) + +var _ commontypes.MonitoringEndpoint = &mockMonitoringEndpoint{} + +type mockMonitoringEndpoint struct { + chLogs chan []byte +} + +func (m *mockMonitoringEndpoint) SendLog(log []byte) { + m.chLogs <- log +} + +const bridgeResponse = `{ + "meta":{ + "adapterName":"data-source-name" + }, + "timestamps":{ + "providerDataRequestedUnixMs":92233720368547760, + "providerDataReceivedUnixMs":-92233720368547760, + "providerDataStreamEstablishedUnixMs":1, + "providerIndicatedTimeUnixMs":-123456789 + } + }` + +var trrs = pipeline.TaskRunResults{ + pipeline.TaskRunResult{ + Task: &pipeline.BridgeTask{ + Name: "test-bridge-1", + BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), + RequestData: `{"data":{"from":"eth", "to":"usd"}}`, + }, + Result: pipeline.Result{ + Value: bridgeResponse, + }, + CreatedAt: time.Unix(0, 0), + FinishedAt: null.TimeFrom(time.Unix(0, 0)), + }, + pipeline.TaskRunResult{ + Task: &pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "ds1_parse", nil, nil, 1), + }, + Result: pipeline.Result{ + Value: "123456.123456789", + }, + }, + pipeline.TaskRunResult{ + Task: &pipeline.BridgeTask{ + Name: "test-bridge-2", + BaseTask: pipeline.NewBaseTask(0, "ds2", nil, nil, 0), + RequestData: `{"data":{"from":"eth", "to":"usd"}}`, + }, + Result: pipeline.Result{ + Value: bridgeResponse, + }, + CreatedAt: time.Unix(1, 0), + FinishedAt: null.TimeFrom(time.Unix(10, 0)), + }, + pipeline.TaskRunResult{ + Task: &pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "ds2_parse", nil, nil, 1), + }, + Result: pipeline.Result{ + Value: "12345678", + }, + }, + pipeline.TaskRunResult{ + Task: &pipeline.BridgeTask{ + Name: "test-bridge-3", + BaseTask: pipeline.NewBaseTask(0, "ds3", nil, nil, 0), + RequestData: `{"data":{"from":"eth", "to":"usd"}}`, + }, + Result: pipeline.Result{ + Value: bridgeResponse, + }, + CreatedAt: time.Unix(2, 0), + FinishedAt: null.TimeFrom(time.Unix(20, 0)), + }, + pipeline.TaskRunResult{ + Task: &pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "ds3_parse", nil, nil, 1), + }, + Result: pipeline.Result{ + Value: "1234567890", + }, + }, +} + +func Test_Telemeter(t *testing.T) { + lggr := logger.Test(t) + m := &mockMonitoringEndpoint{} + + run := &pipeline.Run{ID: 42} + streamID := uint32(135) + opts := &mockOpts{} + + t.Run("with error", func(t *testing.T) { + tm := newTelemeter(lggr, m) + servicetest.Run(t, tm) + + t.Run("if error is some random failure returns immediately", func(t *testing.T) { + // should return immediately and not even send on the channel + m.chLogs = nil + tm.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, nil, errors.New("test error")) + }) + t.Run("if error is dp invariant violation, sets this flag", func(t *testing.T) { + m.chLogs = make(chan []byte, 100) + adapterError := new(eautils.AdapterError) + adapterError.Name = adapterLWBAErrorName + tm.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, nil, adapterError) + + var i int + for log := range m.chLogs { + decoded := &telem.EnhancedEAMercury{} + require.NoError(t, proto.Unmarshal(log, decoded)) + assert.True(t, decoded.DpInvariantViolationDetected) + if i == 2 { + return + } + i++ + } + }) + }) + t.Run("with decimal value, sets all values correctly", func(t *testing.T) { + tm := newTelemeter(lggr, m) + val := llo.ToDecimal(decimal.NewFromFloat32(102.12)) + servicetest.Run(t, tm) + tm.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, nil) + + var i int + for log := range m.chLogs { + decoded := &telem.EnhancedEAMercury{} + require.NoError(t, proto.Unmarshal(log, decoded)) + assert.Equal(t, int(1003), int(decoded.Version)) + assert.Equal(t, float64(123456.123456789), decoded.DpBenchmarkPrice) + assert.Zero(t, decoded.DpBid) + assert.Zero(t, decoded.DpAsk) + assert.False(t, decoded.DpInvariantViolationDetected) + assert.Zero(t, decoded.CurrentBlockNumber) + assert.Zero(t, decoded.CurrentBlockHash) + assert.Zero(t, decoded.CurrentBlockTimestamp) + assert.Zero(t, decoded.FetchMaxFinalizedTimestamp) + assert.Zero(t, decoded.MaxFinalizedTimestamp) + assert.Zero(t, decoded.ObservationTimestamp) + assert.False(t, decoded.IsLinkFeed) + assert.Zero(t, decoded.LinkPrice) + assert.False(t, decoded.IsNativeFeed) + assert.Zero(t, decoded.NativePrice) + assert.Equal(t, int64(i*1000), decoded.BridgeTaskRunStartedTimestamp) + assert.Equal(t, int64(i*10000), decoded.BridgeTaskRunEndedTimestamp) + assert.Equal(t, int64(92233720368547760), decoded.ProviderRequestedTimestamp) + assert.Equal(t, int64(-92233720368547760), decoded.ProviderReceivedTimestamp) + assert.Equal(t, int64(1), decoded.ProviderDataStreamEstablished) + assert.Equal(t, int64(-123456789), decoded.ProviderIndicatedTime) + assert.Equal(t, "streamID:135", decoded.Feed) + assert.Equal(t, int64(102), decoded.ObservationBenchmarkPrice) + assert.Equal(t, "102.12", decoded.ObservationBenchmarkPriceString) + assert.Zero(t, decoded.ObservationBid) + assert.Zero(t, decoded.ObservationBidString) + assert.Zero(t, decoded.ObservationAsk) + assert.Zero(t, decoded.ObservationAskString) + assert.Zero(t, decoded.ObservationMarketStatus) + assert.Equal(t, "0605040000000000000000000000000000000000000000000000000000000000", decoded.ConfigDigest) + assert.Equal(t, int64(18), decoded.Round) + assert.Equal(t, int64(4), decoded.Epoch) + assert.Equal(t, "eth/usd", decoded.AssetSymbol) + if i == 2 { + return + } + i++ + } + }) + t.Run("with quote value", func(t *testing.T) { + tm := newTelemeter(lggr, m) + val := &llo.Quote{Bid: decimal.NewFromFloat32(102.12), Benchmark: decimal.NewFromFloat32(103.32), Ask: decimal.NewFromFloat32(104.25)} + servicetest.Run(t, tm) + tm.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, nil) + + var i int + for log := range m.chLogs { + decoded := &telem.EnhancedEAMercury{} + require.NoError(t, proto.Unmarshal(log, decoded)) + assert.Equal(t, int64(103), decoded.ObservationBenchmarkPrice) + assert.Equal(t, "103.32", decoded.ObservationBenchmarkPriceString) + assert.Equal(t, int64(102), decoded.ObservationBid) + assert.Equal(t, "102.12", decoded.ObservationBidString) + assert.Equal(t, int64(104), decoded.ObservationAsk) + assert.Equal(t, "104.25", decoded.ObservationAskString) + assert.Zero(t, decoded.ObservationMarketStatus) + if i == 2 { + return + } + i++ + } + }) +} diff --git a/core/services/llo/transmitter.go b/core/services/llo/transmitter.go index b8cfb86de3b..7696c69c291 100644 --- a/core/services/llo/transmitter.go +++ b/core/services/llo/transmitter.go @@ -2,24 +2,26 @@ package llo import ( "context" - "crypto/ed25519" - "errors" "fmt" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink/v2/core/services/llo/mercurytransmitter" + + "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/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" ) // LLO Transmitter implementation, based on // core/services/relay/evm/mercury/transmitter.go +// +// If you need to "fan-out" transmits and send reports to a new destination, +// add a new subTransmitter // TODO: prom metrics (common with mercury/transmitter.go?) // https://smartcontract-it.atlassian.net/browse/MERC-3659 @@ -34,57 +36,72 @@ const ( // transmitTimeout = 5 * time.Second ) -var PayloadTypes = getPayloadTypes() - -func getPayloadTypes() 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: "reportContext", Type: mustNewType("bytes32[2]")}, - {Name: "report", Type: mustNewType("bytes")}, - {Name: "rawRs", Type: mustNewType("bytes32[]")}, - {Name: "rawSs", Type: mustNewType("bytes32[]")}, - {Name: "rawVs", Type: mustNewType("bytes32")}, - }) -} - type Transmitter interface { llotypes.Transmitter services.Service } +type TransmitterRetirementReportCacheWriter interface { + StoreAttestedRetirementReport(ctx context.Context, cd ocrtypes.ConfigDigest, seqNr uint64, retirementReport []byte, sigs []types.AttributedOnchainSignature) error +} + type transmitter struct { services.StateMachine lggr logger.Logger - rpcClient wsrpc.Client fromAccount string + + subTransmitters []Transmitter + retirementReportCache TransmitterRetirementReportCacheWriter } -func NewTransmitter(lggr logger.Logger, rpcClient wsrpc.Client, fromAccount ed25519.PublicKey) Transmitter { +type TransmitterOpts struct { + Lggr logger.Logger + FromAccount string + MercuryTransmitterOpts mercurytransmitter.Opts + RetirementReportCache TransmitterRetirementReportCacheWriter +} + +// The transmitter will handle starting and stopping the subtransmitters +func NewTransmitter(opts TransmitterOpts) Transmitter { + subTransmitters := []Transmitter{ + mercurytransmitter.New(opts.MercuryTransmitterOpts), + } return &transmitter{ services.StateMachine{}, - lggr, - rpcClient, - fmt.Sprintf("%x", fromAccount), + opts.Lggr, + opts.FromAccount, + subTransmitters, + opts.RetirementReportCache, } } func (t *transmitter) Start(ctx context.Context) error { - return nil + return t.StartOnce("llo.Transmitter", func() error { + for _, st := range t.subTransmitters { + if err := st.Start(ctx); err != nil { + return err + } + } + return nil + }) } func (t *transmitter) Close() error { - return nil + return t.StopOnce("llo.Transmitter", func() error { + for _, st := range t.subTransmitters { + if err := st.Close(); err != nil { + return err + } + } + return nil + }) } func (t *transmitter) HealthReport() map[string]error { report := map[string]error{t.Name(): t.Healthy()} - services.CopyHealth(report, t.rpcClient.HealthReport()) + for _, st := range t.subTransmitters { + services.CopyHealth(report, st.HealthReport()) + } return report } @@ -97,10 +114,26 @@ func (t *transmitter) Transmit( report ocr3types.ReportWithInfo[llotypes.ReportInfo], sigs []types.AttributedOnchainSignature, ) (err error) { - return errors.New("not implemented") + if report.Info.ReportFormat == llotypes.ReportFormatRetirement { + // Retirement reports don't get transmitted; rather, they are stored in + // the RetirementReportCache + t.lggr.Debugw("Storing retirement report", "digest", digest, "seqNr", seqNr) + if err := t.retirementReportCache.StoreAttestedRetirementReport(ctx, digest, seqNr, report.Report, sigs); err != nil { + return fmt.Errorf("failed to write retirement report to cache: %w", err) + } + return nil + } + g := new(errgroup.Group) + for _, st := range t.subTransmitters { + st := st + g.Go(func() error { + return st.Transmit(ctx, digest, seqNr, report, sigs) + }) + } + return g.Wait() } // FromAccount returns the stringified (hex) CSA public key -func (t *transmitter) FromAccount() (ocr2types.Account, error) { +func (t *transmitter) FromAccount(ctx context.Context) (ocr2types.Account, error) { return ocr2types.Account(t.fromAccount), nil } diff --git a/core/services/llo/transmitter_test.go b/core/services/llo/transmitter_test.go deleted file mode 100644 index eb231494c0b..00000000000 --- a/core/services/llo/transmitter_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package llo - -import "testing" - -func Test_Transmitter(t *testing.T) { - // TODO: https://smartcontract-it.atlassian.net/browse/MERC-3659 -} diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index d7199874a9f..618567f0bdb 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: + 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: // continue } latestBlockHeight := t.getLatestBlockHeight() diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index f53ceaefa14..cf45822cb37 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -49,7 +49,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "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/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/services/llo" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/ccipcommit" @@ -121,8 +120,9 @@ type Delegate struct { ks keystore.OCR2 ethKs keystore.Eth RelayGetter - isNewlyCreatedJob bool // Set to true if this is a new job freshly added, false if job was present already on node boot. - mailMon *mailbox.Monitor + isNewlyCreatedJob bool // Set to true if this is a new job freshly added, false if job was present already on node boot. + mailMon *mailbox.Monitor + retirementReportCache llo.RetirementReportCache legacyChains legacyevm.LegacyChainContainer // legacy: use relayers instead capabilitiesRegistry core.CapabilitiesRegistry @@ -215,42 +215,48 @@ func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Th var _ job.Delegate = (*Delegate)(nil) +type DelegateOpts struct { + Ds sqlutil.DataSource + JobORM job.ORM + BridgeORM bridges.ORM + MercuryORM evmmercury.ORM + PipelineRunner pipeline.Runner + StreamRegistry streams.Getter + PeerWrapper *ocrcommon.SingletonPeerWrapper + MonitoringEndpointGen telemetry.MonitoringEndpointGenerator + LegacyChains legacyevm.LegacyChainContainer + Lggr logger.Logger + Ks keystore.OCR2 + EthKs keystore.Eth + Relayers RelayGetter + MailMon *mailbox.Monitor + CapabilitiesRegistry core.CapabilitiesRegistry + RetirementReportCache llo.RetirementReportCache +} + func NewDelegate( - ds sqlutil.DataSource, - jobORM job.ORM, - bridgeORM bridges.ORM, - mercuryORM evmmercury.ORM, - pipelineRunner pipeline.Runner, - streamRegistry streams.Getter, - peerWrapper *ocrcommon.SingletonPeerWrapper, - monitoringEndpointGen telemetry.MonitoringEndpointGenerator, - legacyChains legacyevm.LegacyChainContainer, - lggr logger.Logger, + opts DelegateOpts, cfg DelegateConfig, - ks keystore.OCR2, - ethKs keystore.Eth, - relayers RelayGetter, - mailMon *mailbox.Monitor, - capabilitiesRegistry core.CapabilitiesRegistry, ) *Delegate { return &Delegate{ - ds: ds, - jobORM: jobORM, - bridgeORM: bridgeORM, - mercuryORM: mercuryORM, - pipelineRunner: pipelineRunner, - streamRegistry: streamRegistry, - peerWrapper: peerWrapper, - monitoringEndpointGen: monitoringEndpointGen, - legacyChains: legacyChains, + ds: opts.Ds, + jobORM: opts.JobORM, + bridgeORM: opts.BridgeORM, + mercuryORM: opts.MercuryORM, + pipelineRunner: opts.PipelineRunner, + streamRegistry: opts.StreamRegistry, + peerWrapper: opts.PeerWrapper, + monitoringEndpointGen: opts.MonitoringEndpointGen, + legacyChains: opts.LegacyChains, cfg: cfg, - lggr: lggr.Named("OCR2"), - ks: ks, - ethKs: ethKs, - RelayGetter: relayers, + lggr: opts.Lggr.Named("OCR2"), + ks: opts.Ks, + ethKs: opts.EthKs, + RelayGetter: opts.Relayers, isNewlyCreatedJob: false, - mailMon: mailMon, - capabilitiesRegistry: capabilitiesRegistry, + mailMon: opts.MailMon, + capabilitiesRegistry: opts.CapabilitiesRegistry, + retirementReportCache: opts.RetirementReportCache, } } @@ -361,6 +367,18 @@ func (d *Delegate) cleanupEVM(ctx context.Context, jb job.Job, relayID types.Rel d.lggr.Errorw("failed to unregister ccip exec plugin filters", "err", err2, "spec", spec) } return nil + case types.LLO: + var pluginCfg lloconfig.PluginConfig + err = json.Unmarshal(spec.PluginConfig.Bytes(), &pluginCfg) + if err != nil { + return err + } + var chainSelector uint64 + chainSelector, err = chainselectors.SelectorFromChainId(chain.ID().Uint64()) + if err != nil { + return err + } + return llo.Cleanup(ctx, lp, pluginCfg.ChannelDefinitionsContractAddress, pluginCfg.DonID, d.ds, chainSelector) default: return nil } @@ -451,10 +469,12 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi } lggr.Infow("OCR2 job using local config", "BlockchainTimeout", lc.BlockchainTimeout, + "ContractConfigLoadTimeout", lc.ContractConfigLoadTimeout, "ContractConfigConfirmations", lc.ContractConfigConfirmations, "ContractConfigTrackerPollInterval", lc.ContractConfigTrackerPollInterval, "ContractTransmitterTransmitTimeout", lc.ContractTransmitterTransmitTimeout, "DatabaseTimeout", lc.DatabaseTimeout, + "DefaultMaxDurationInitialization", lc.DefaultMaxDurationInitialization, ) bootstrapPeers, err := ocrcommon.GetValidatedBootstrapPeers(spec.P2PV2Bootstrappers, d.peerWrapper.P2PConfig().V2().DefaultBootstrappers()) @@ -621,7 +641,8 @@ func (d *Delegate) newServicesGenericPlugin( provider, err := relayer.NewPluginProvider(ctx, types.RelayArgs{ ExternalJobID: jb.ExternalJobID, - JobID: spec.ID, + JobID: jb.ID, + OracleSpecID: spec.ID, ContractID: spec.ContractID, New: d.isNewlyCreatedJob, RelayConfig: spec.RelayConfig.Bytes(), @@ -772,7 +793,7 @@ func (d *Delegate) newServicesGenericPlugin( } keyBundles[name] = os } - onchainKeyringAdapter, err = ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(keyBundles, kb.PublicKey(), lggr) + onchainKeyringAdapter, err = ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(keyBundles, lggr) if err != nil { return nil, err } @@ -871,6 +892,21 @@ func (d *Delegate) newServicesMercury( lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) + var relayConfig evmrelaytypes.RelayConfig + err = json.Unmarshal(jb.OCR2OracleSpec.RelayConfig.Bytes(), &relayConfig) + if err != nil { + return nil, fmt.Errorf("error while unmarshalling relay config: %w", err) + } + + var telemetryType synchronization.TelemetryType + if relayConfig.EnableTriggerCapability && len(jb.OCR2OracleSpec.PluginConfig) == 0 { + telemetryType = synchronization.OCR3DataFeeds + // First use case for TriggerCapability transmission is Data Feeds, so telemetry should be routed accordingly. + // This is only true if TriggerCapability is the *only* transmission method (PluginConfig is empty). + } else { + telemetryType = synchronization.OCR3Mercury + } + oracleArgsNoPlugin := libocr2.MercuryOracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -879,7 +915,7 @@ func (d *Delegate) newServicesMercury( Database: ocrDB, LocalConfig: lc, Logger: ocrLogger, - MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), synchronization.OCR3Mercury), + MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), telemetryType), OffchainConfigDigester: mercuryProvider.OffchainConfigDigester(), OffchainKeyring: kb, OnchainKeyring: kb, @@ -890,7 +926,7 @@ func (d *Delegate) newServicesMercury( mCfg := mercury.NewMercuryConfig(d.cfg.JobPipeline().MaxSuccessfulRuns(), d.cfg.JobPipeline().ResultWriteQueueDepth(), d.cfg) - mercuryServices, err2 := mercury.NewServices(jb, mercuryProvider, d.pipelineRunner, lggr, oracleArgsNoPlugin, mCfg, chEnhancedTelem, d.mercuryORM, (mercuryutils.FeedID)(*spec.FeedID)) + mercuryServices, err2 := mercury.NewServices(jb, mercuryProvider, d.pipelineRunner, lggr, oracleArgsNoPlugin, mCfg, chEnhancedTelem, d.mercuryORM, (mercuryutils.FeedID)(*spec.FeedID), relayConfig.EnableTriggerCapability) if ocrcommon.ShouldCollectEnhancedTelemetryMercury(jb) { enhancedTelemService := ocrcommon.NewEnhancedTelemetryService(&jb, chEnhancedTelem, make(chan struct{}), d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.FeedID.String(), synchronization.EnhancedEAMercury), lggr.Named("EnhancedTelemetryMercury")) @@ -953,6 +989,7 @@ func (d *Delegate) newServicesLLO( return nil, err } + // Handle key bundle IDs explicitly specified in job spec kbm := make(map[llotypes.ReportFormat]llo.Key) for rfStr, kbid := range pluginCfg.KeyBundleIDs { k, err3 := d.ks.Get(kbid) @@ -965,26 +1002,23 @@ func (d *Delegate) newServicesLLO( } kbm[rf] = k } - // NOTE: This is a bit messy because we assume chain type matches report - // format, and it may not in all cases. We don't yet know what report - // formats we need or how they correspond to chain types, so assume it's - // 1:1 for now but will change in future - // + + // Use the default key bundle if not specified + // NOTE: Only JSON and EVMPremiumLegacy supported for now // https://smartcontract-it.atlassian.net/browse/MERC-3722 - for _, s := range chaintype.SupportedChainTypes { - rf, err3 := llotypes.ReportFormatFromString(string(s)) - if err3 != nil { - return nil, fmt.Errorf("job %d (%s) has a chain type with no matching report format %s: %w", jb.ID, jb.Name.ValueOrZero(), s, err3) - } + // + // 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} { if _, exists := kbm[rf]; !exists { // Use the first if unspecified - kbs, err4 := d.ks.GetAllOfType(s) - if err4 != nil { - return nil, err4 + kbs, err3 := d.ks.GetAllOfType("evm") + if err3 != nil { + return nil, err3 } if len(kbs) == 0 { - // unsupported key type - continue + return nil, fmt.Errorf("no on-chain signing keys found for report format %s", "evm") } else if len(kbs) > 1 { lggr.Debugf("Multiple on-chain signing keys found for report format %s, using the first", rf.String()) } @@ -1000,33 +1034,31 @@ func (d *Delegate) newServicesLLO( lggr.Infof("Using on-chain signing keys for LLO job %d (%s): %v", jb.ID, jb.Name.ValueOrZero(), kbm) kr := llo.NewOnchainKeyring(lggr, kbm) - ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { - lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") - }) - cfg := llo.DelegateConfig{ Logger: lggr, DataSource: d.ds, Runner: d.pipelineRunner, Registry: d.streamRegistry, - JobName: jb.Name, + JobName: jb.Name, + CaptureEATelemetry: jb.OCR2OracleSpec.CaptureEATelemetry, ChannelDefinitionCache: provider.ChannelDefinitionCache(), + RetirementReportCache: d.retirementReportCache, + ShouldRetireCache: provider.ShouldRetireCache(), + RetirementReportCodec: datastreamsllo.StandardRetirementReportCodec{}, + TraceLogging: d.cfg.OCR2().TraceLogging(), BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, ContractTransmitter: provider.ContractTransmitter(), - ContractConfigTracker: provider.ContractConfigTracker(), + ContractConfigTrackers: provider.ContractConfigTrackers(), Database: ocrDB, LocalConfig: lc, - // TODO: Telemetry for llo - // https://smartcontract-it.atlassian.net/browse/MERC-3603 - MonitoringEndpoint: nil, - OffchainConfigDigester: provider.OffchainConfigDigester(), - OffchainKeyring: kb, - OnchainKeyring: kr, - OCRLogger: ocrLogger, + MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, fmt.Sprintf("%d", pluginCfg.DonID), synchronization.EnhancedEAMercury), + OffchainConfigDigester: provider.OffchainConfigDigester(), + OffchainKeyring: kb, + OnchainKeyring: kr, // 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()}, @@ -1035,7 +1067,7 @@ func (d *Delegate) newServicesLLO( if err != nil { return nil, err } - return []job.ServiceCtx{provider, ocrLogger, oracle}, nil + return []job.ServiceCtx{provider, oracle}, nil } func (d *Delegate) newServicesMedian( diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go index 9015928ade1..04693061880 100644 --- a/core/services/ocr2/delegate_test.go +++ b/core/services/ocr2/delegate_test.go @@ -24,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" ) @@ -46,9 +45,8 @@ func TestGetEVMEffectiveTransmitterID(t *testing.T) { lggr := logger.TestLogger(t) txManager := txmmocks.NewMockEvmTxManager(t) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth(), TxManager: txManager}) - require.True(t, relayExtenders.Len() > 0) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth(), TxManager: txManager}) + require.True(t, legacyChains.Len() > 0) type testCase struct { name string diff --git a/core/services/ocr2/plugins/ccip/LICENSE.md b/core/services/ocr2/plugins/ccip/LICENSE.md index b127e1a823a..96fdb2b1392 100644 --- a/core/services/ocr2/plugins/ccip/LICENSE.md +++ b/core/services/ocr2/plugins/ccip/LICENSE.md @@ -9,12 +9,12 @@ Parameters Licensor: SmartContract Chainlink Limited SEZC -Licensed Work: Cross-Chain Interoperability Protocol v1.4 +Licensed Work: Cross-Chain Interoperability Protocol v1.5 The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC -Additional Use Grant: Any uses listed and defined at [v1.4-CCIP-License-grants](../../../../../contracts/src/v0.8/ccip/v1.4-CCIP-License-grants) +Additional Use Grant: Any uses listed and defined at [v1.5-CCIP-License-grants](../../../../../contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md) -Change Date: May 23, 2027 +Change Date: Aug 16, 2028 Change License: MIT diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go index 648f62a23a2..c7a18567d26 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go @@ -56,7 +56,7 @@ func (rf *CommitReportingPluginFactory) UpdateDynamicReaders(ctx context.Context } } - destPriceRegistryReader, err := rf.config.priceRegistryProvider.NewPriceRegistryReader(context.Background(), cciptypes.Address(newPriceRegAddr.String())) + destPriceRegistryReader, err := rf.config.priceRegistryProvider.NewPriceRegistryReader(ctx, cciptypes.Address(newPriceRegAddr.String())) if err != nil { return fmt.Errorf("init dynamic price registry: %w", err) } @@ -71,11 +71,11 @@ type reportingPluginAndInfo struct { } // NewReportingPlugin registers a new ReportingPlugin -func (rf *CommitReportingPluginFactory) NewReportingPlugin(config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { +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 - pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(config), initialRetryDelay, maxDelay) + pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(ctx, config), initialRetryDelay, maxDelay) if err != nil { return nil, types.ReportingPluginInfo{}, err } @@ -85,10 +85,8 @@ func (rf *CommitReportingPluginFactory) NewReportingPlugin(config types.Reportin // NewReportingPluginFn implements the NewReportingPlugin logic. It is defined as a function so that it can easily be // 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(config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { +func (rf *CommitReportingPluginFactory) NewReportingPluginFn(ctx context.Context, config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { return func() (reportingPluginAndInfo, error) { - ctx := context.Background() // todo: consider adding some timeout - destPriceReg, err := rf.config.commitStore.ChangeConfig(ctx, config.OnchainConfig, config.OffchainConfig) if err != nil { return reportingPluginAndInfo{}, err diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go index 825026bd17e..44c63ec87e6 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go @@ -5,11 +5,14 @@ import ( "testing" "time" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/logger" "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" @@ -23,6 +26,7 @@ import ( // first call to each of these functions to fail, then all subsequent calls succeed. We assert that NewReportingPlugin // retries a sufficient number of times to get through the transient errors and eventually succeed. func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { + ctx := tests.Context(t) commitConfig := CommitPluginStaticConfig{} // For this unit test, ensure that there is no delay between retries @@ -95,6 +99,6 @@ func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { reportingConfig.OffchainConfig = []byte{1, 2, 3} // Assert that NewReportingPlugin succeeds despite many transient internal failures (mocked out above) - _, _, err := factory.NewReportingPlugin(reportingConfig) + _, _, err := factory.NewReportingPlugin(ctx, reportingConfig) assert.Equal(t, nil, err) } diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go index e964896ab93..771fdd322f3 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go @@ -69,7 +69,7 @@ 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.PriceGetter + 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) @@ -156,7 +156,7 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c onRampAddress, ) - orm, err := cciporm.NewORM(ds) + orm, err := cciporm.NewObservedORM(ds, lggr) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go index 2f0fc4e7956..55caf88f1c7 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go @@ -453,13 +453,13 @@ func (r *CommitReportingPlugin) selectPriceUpdates(ctx context.Context, now time return nil, nil, err } - return r.calculatePriceUpdates(gasPriceObs, tokenPriceObs, latestGasPrice, latestTokenPrices) + return r.calculatePriceUpdates(ctx, gasPriceObs, tokenPriceObs, latestGasPrice, latestTokenPrices) } // Note priceUpdates must be deterministic. // The provided gasPriceObs and tokenPriceObs should not contain nil values. // The returned latestGasPrice and latestTokenPrices should not contain nil values. -func (r *CommitReportingPlugin) calculatePriceUpdates(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) { +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 for token, tokenPriceObservations := range tokenPriceObs { medianPrice := ccipcalc.BigIntSortedMiddle(tokenPriceObservations) @@ -488,7 +488,7 @@ func (r *CommitReportingPlugin) calculatePriceUpdates(gasPriceObs map[uint64][]* var gasPriceUpdate []cciptypes.GasPrice for chainSelector, gasPriceObservations := range gasPriceObs { - newGasPrice, err := r.gasPriceEstimator.Median(gasPriceObservations) // Compute the median price + 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) } @@ -497,7 +497,7 @@ func (r *CommitReportingPlugin) calculatePriceUpdates(gasPriceObs map[uint64][]* latestGasPrice, exists := latestGasPrice[chainSelector] if exists && latestGasPrice.value != nil { gasPriceUpdatedRecently := time.Since(latestGasPrice.timestamp) < r.offchainConfig.GasPriceHeartBeat - gasPriceDeviated, err := r.gasPriceEstimator.Deviates(newGasPrice, latestGasPrice.value) + gasPriceDeviated, err := r.gasPriceEstimator.Deviates(ctx, newGasPrice, latestGasPrice.value) if err != nil { return nil, nil, err } @@ -708,7 +708,7 @@ func (r *CommitReportingPlugin) isStaleGasPrice(ctx context.Context, lggr logger return false } - gasPriceDeviated, err := r.gasPriceEstimator.Deviates(gasPriceUpdate.Value, latestUpdate.value) + gasPriceDeviated, err := r.gasPriceEstimator.Deviates(ctx, gasPriceUpdate.Value, latestUpdate.value) if err != nil { lggr.Errorw("Gas price is stale because deviation check failed", "err", err) return true diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go index 6cf7e4bec72..93d8de9f892 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go @@ -43,7 +43,6 @@ 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/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_0_0" "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" @@ -1402,6 +1401,7 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) estimator, _ := prices.NewGasPriceEstimatorForCommitPlugin( *estimatorCSVer, evmEstimator, @@ -1433,7 +1433,7 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { } } - gotGas, gotTokens, err := r.calculatePriceUpdates(gasPriceObs, tokenPriceObs, tc.latestGasPrice, tc.latestTokenPrices) + gotGas, gotTokens, err := r.calculatePriceUpdates(ctx, gasPriceObs, tokenPriceObs, tc.latestGasPrice, tc.latestTokenPrices) assert.Equal(t, tc.expGasUpdates, gotGas) assert.Equal(t, tc.expTokenUpdates, gotTokens) @@ -1843,7 +1843,7 @@ func TestCommitReportToEthTxMeta(t *testing.T) { out, err := encodeCommitReport(report) require.NoError(t, err) - fn, err := factory.CommitReportToEthTxMeta(ccipconfig.CommitStore, *semver.MustParse("1.0.0")) + fn, err := factory.CommitReportToEthTxMeta(ccipconfig.CommitStore, *semver.MustParse("1.5.0")) require.NoError(t, err) txMeta, err := fn(out) require.NoError(t, err) @@ -1857,5 +1857,5 @@ func TestCommitReportToEthTxMeta(t *testing.T) { // encodeCommitReport is only used in tests func encodeCommitReport(report cciptypes.CommitStoreReport) ([]byte, error) { commitStoreABI := abihelpers.MustParseABI(commit_store.CommitStoreABI) - return v1_2_0.EncodeCommitReport(abihelpers.MustGetEventInputs(v1_0_0.ReportAccepted, commitStoreABI), report) + return v1_2_0.EncodeCommitReport(abihelpers.MustGetEventInputs(v1_2_0.ReportAccepted, commitStoreABI), report) } diff --git a/core/services/ocr2/plugins/ccip/ccipexec/batching.go b/core/services/ocr2/plugins/ccip/ccipexec/batching.go index b457dd986d4..866a20c4cde 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/batching.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/batching.go @@ -256,7 +256,7 @@ func performCommonChecks( } // Fee boosting - execCostUsd, err1 := batchCtx.gasPriceEstimator.EstimateMsgCostUSD(batchCtx.gasPrice, dstWrappedNativePrice, msg) + execCostUsd, err1 := batchCtx.gasPriceEstimator.EstimateMsgCostUSD(ctx, batchCtx.gasPrice, dstWrappedNativePrice, msg) if err1 != nil { msgLggr.Errorw("Failed to estimate message cost USD", "err", err1) return "", 0, nil, nil, errors.New("failed to estimate message cost USD") diff --git a/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go b/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go index 3647556a6d5..0fd23496974 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go @@ -807,9 +807,9 @@ func runBatchingStrategyTests(t *testing.T, strategy BatchingStrategy, available gasPriceEstimator := prices.NewMockGasPriceEstimatorExec(t) if !tc.skipGasPriceEstimator { if tc.expectedSeqNrs != nil { - gasPriceEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(0), nil) + gasPriceEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(0), nil) } else { - gasPriceEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(0), errors.New("error")) + gasPriceEstimator.On("EstimateMsgCostUSD", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(0), errors.New("error")) } } diff --git a/core/services/ocr2/plugins/ccip/ccipexec/factory.go b/core/services/ocr2/plugins/ccip/ccipexec/factory.go index 97caf2e719c..646121bdba8 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/factory.go @@ -53,7 +53,7 @@ func (rf *ExecutionReportingPluginFactory) UpdateDynamicReaders(ctx context.Cont } } - destPriceRegistryReader, err := rf.config.priceRegistryProvider.NewPriceRegistryReader(context.Background(), newPriceRegAddr) + destPriceRegistryReader, err := rf.config.priceRegistryProvider.NewPriceRegistryReader(ctx, newPriceRegAddr) if err != nil { return err } @@ -68,11 +68,11 @@ type reportingPluginAndInfo struct { } // NewReportingPlugin registers a new ReportingPlugin -func (rf *ExecutionReportingPluginFactory) NewReportingPlugin(config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { +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 - pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(config), initialRetryDelay, maxDelay) + pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(ctx, config), initialRetryDelay, maxDelay) if err != nil { return nil, types.ReportingPluginInfo{}, err } @@ -82,10 +82,8 @@ func (rf *ExecutionReportingPluginFactory) NewReportingPlugin(config types.Repor // NewReportingPluginFn implements the NewReportingPlugin logic. It is defined as a function so that it can easily be // 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(config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { +func (rf *ExecutionReportingPluginFactory) NewReportingPluginFn(ctx context.Context, config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { return func() (reportingPluginAndInfo, error) { - ctx := context.Background() // todo: consider setting a timeout - destPriceRegistry, destWrappedNative, err := rf.config.offRampReader.ChangeConfig(ctx, config.OnchainConfig, config.OffchainConfig) if err != nil { return reportingPluginAndInfo{}, err diff --git a/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go b/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go index 7bbb9be0c69..fe5e0ab1e23 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/factory_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/logger" "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" @@ -22,6 +23,7 @@ import ( // first call to each of these functions to fail, then all subsequent calls succeed. We assert that NewReportingPlugin // retries a sufficient number of times to get through the transient errors and eventually succeed. func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { + ctx := tests.Context(t) execConfig := ExecutionPluginStaticConfig{} // For this unit test, ensure that there is no delay between retries @@ -62,6 +64,6 @@ func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { reportingConfig.OffchainConfig = []byte{1, 2, 3} // Assert that NewReportingPlugin succeeds despite many transient internal failures (mocked out above) - _, _, err := factory.NewReportingPlugin(reportingConfig) + _, _, err := factory.NewReportingPlugin(ctx, reportingConfig) assert.Equal(t, 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 84cb73c6643..ff6371fa2ce 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go @@ -36,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader" ccipdataprovidermocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks" 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_0_0" "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/prices" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" @@ -429,7 +428,7 @@ func TestExecutionReportingPlugin_buildReport(t *testing.T) { p.commitStoreReader = commitStore lp := lpMocks.NewLogPoller(t) - offRampReader, err := v1_0_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) assert.NoError(t, err) p.offRampReader = offRampReader 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 142ba006be6..0a7594324bd 100644 --- a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go +++ b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go @@ -1,10 +1,13 @@ package ccip_test import ( + "context" "encoding/json" "math/big" "testing" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" @@ -19,7 +22,15 @@ import ( ) func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { - ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + ccip.DefaultDestFinalityDepth, + ) tokenPricesUSDPipeline, linkUSD, ethUSD := ccipTH.CreatePricesPipeline(t) defer linkUSD.Close() @@ -29,10 +40,17 @@ func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { } func Test_CLOSpecApprovalFlow_dynamicPriceGetter(t *testing.T) { - ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + ccip.DefaultDestFinalityDepth, + ) //Set up the aggregators here to avoid modifying ccipTH. - srcLinkAddr := ccipTH.Source.LinkToken.Address() dstLinkAddr := ccipTH.Dest.LinkToken.Address() srcNativeAddr, err := ccipTH.Source.Router.GetWrappedNative(nil) require.NoError(t, err) @@ -44,13 +62,6 @@ func Test_CLOSpecApprovalFlow_dynamicPriceGetter(t *testing.T) { require.NoError(t, err) ccipTH.Source.Chain.Commit() - aggSrcLnkAddr, _, aggSrcLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Source.User, ccipTH.Source.Chain, 18, big.NewInt(3e18)) - require.NoError(t, err) - ccipTH.Dest.Chain.Commit() - _, err = aggSrcLnk.UpdateRoundData(ccipTH.Source.User, big.NewInt(50), big.NewInt(8000000), big.NewInt(1000), big.NewInt(1000)) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - aggDstLnkAddr, _, aggDstLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Dest.User, ccipTH.Dest.Chain, 18, big.NewInt(3e18)) require.NoError(t, err) ccipTH.Dest.Chain.Commit() @@ -74,10 +85,6 @@ func Test_CLOSpecApprovalFlow_dynamicPriceGetter(t *testing.T) { priceGetterConfig := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - srcLinkAddr: { - ChainID: ccipTH.Source.ChainID, - AggregatorContractAddress: aggSrcLnkAddr, - }, srcNativeAddr: { ChainID: ccipTH.Source.ChainID, AggregatorContractAddress: aggSrcNatAddr, @@ -125,11 +132,22 @@ func test_CLOSpecApprovalFlow(t *testing.T, ccipTH integrationtesthelpers.CCIPIn _, err = ccipTH.Source.LinkToken.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), new(big.Int).Set(fee)) require.NoError(t, err) - ccipTH.Source.Chain.Commit() + blockHash := ccipTH.Dest.Chain.Commit() + // get the block number + block, err := ccipTH.Dest.Chain.BlockByHash(context.Background(), blockHash) + require.NoError(t, err) + blockNumber := block.Number().Uint64() + 1 // +1 as a block will be mined for the request from EventuallyReportCommitted ccipTH.SendRequest(t, msg) ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum) ccipTH.EventuallyReportCommitted(t, currentSeqNum) + ccipTH.EventuallyPriceRegistryUpdated( + t, + blockNumber, + ccipTH.Source.ChainSelector, + []common.Address{ccipTH.Dest.LinkToken.Address(), ccipTH.Dest.WrappedNative.Address()}, + ccipTH.Source.WrappedNative.Address(), + ) executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum) assert.Len(t, executionLogs, 1) diff --git a/core/services/ocr2/plugins/ccip/exportinternal.go b/core/services/ocr2/plugins/ccip/exportinternal.go index 2a5767ac85d..aecf1a0b163 100644 --- a/core/services/ocr2/plugins/ccip/exportinternal.go +++ b/core/services/ocr2/plugins/ccip/exportinternal.go @@ -7,11 +7,12 @@ import ( "github.com/ethereum/go-ethereum/common" + "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/logger" "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/integration_legacy_test.go b/core/services/ocr2/plugins/ccip/integration_legacy_test.go index 9bc94b5fe45..d89c50b4070 100644 --- a/core/services/ocr2/plugins/ccip/integration_legacy_test.go +++ b/core/services/ocr2/plugins/ccip/integration_legacy_test.go @@ -63,13 +63,6 @@ func TestIntegration_legacy_CCIP(t *testing.T) { require.NoError(t, err) ccipTH.Source.Chain.Commit() - aggSrcLnkAddr, _, aggSrcLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Source.User, ccipTH.Source.Chain, 18, big.NewInt(3e18)) - require.NoError(t, err) - ccipTH.Dest.Chain.Commit() - _, err = aggSrcLnk.UpdateRoundData(ccipTH.Source.User, big.NewInt(50), big.NewInt(8000000), big.NewInt(1000), big.NewInt(1000)) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - aggDstLnkAddr, _, aggDstLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Dest.User, ccipTH.Dest.Chain, 18, big.NewInt(3e18)) require.NoError(t, err) ccipTH.Dest.Chain.Commit() @@ -79,10 +72,6 @@ func TestIntegration_legacy_CCIP(t *testing.T) { priceGetterConfig := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - ccipTH.Source.LinkToken.Address(): { - ChainID: ccipTH.Source.ChainID, - AggregatorContractAddress: aggSrcLnkAddr, - }, ccipTH.Source.WrappedNative.Address(): { ChainID: ccipTH.Source.ChainID, AggregatorContractAddress: aggSrcNatAddr, diff --git a/core/services/ocr2/plugins/ccip/integration_test.go b/core/services/ocr2/plugins/ccip/integration_test.go index 202d2ef2304..d14de4e0ab1 100644 --- a/core/services/ocr2/plugins/ccip/integration_test.go +++ b/core/services/ocr2/plugins/ccip/integration_test.go @@ -9,6 +9,9 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" @@ -46,7 +49,15 @@ func TestIntegration_CCIP(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + ccip.DefaultDestFinalityDepth, + ) tokenPricesUSDPipeline := "" priceGetterConfigJson := "" @@ -66,13 +77,6 @@ func TestIntegration_CCIP(t *testing.T) { require.NoError(t, err) ccipTH.Source.Chain.Commit() - aggSrcLnkAddr, _, aggSrcLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Source.User, ccipTH.Source.Chain, 18, big.NewInt(3e18)) - require.NoError(t, err) - ccipTH.Dest.Chain.Commit() - _, err = aggSrcLnk.UpdateRoundData(ccipTH.Source.User, big.NewInt(50), big.NewInt(8000000), big.NewInt(1000), big.NewInt(1000)) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - aggDstLnkAddr, _, aggDstLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Dest.User, ccipTH.Dest.Chain, 18, big.NewInt(3e18)) require.NoError(t, err) ccipTH.Dest.Chain.Commit() @@ -82,10 +86,6 @@ func TestIntegration_CCIP(t *testing.T) { priceGetterConfig := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - ccipTH.Source.LinkToken.Address(): { - ChainID: ccipTH.Source.ChainID, - AggregatorContractAddress: aggSrcLnkAddr, - }, ccipTH.Source.WrappedNative.Address(): { ChainID: ccipTH.Source.ChainID, AggregatorContractAddress: aggSrcNatAddr, @@ -629,8 +629,6 @@ func TestIntegration_CCIP(t *testing.T) { PriceRegistry: ccipTH.Dest.PriceRegistry.Address(), MaxDataBytes: 1e5, MaxNumberOfTokensPerMsg: 5, - MaxPoolReleaseOrMintGas: 200_000, - MaxTokenTransferGas: 100_000, }) node.EventuallyNodeUsesUpdatedPriceRegistry(t, ccipTH) } @@ -642,3 +640,71 @@ func TestIntegration_CCIP(t *testing.T) { }) } } + +// TestReorg ensures that CCIP works even when a below finality depth reorg happens +func TestReorg(t *testing.T) { + // 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( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + destinationFinalityDepth, + ) + testPricePipeline, linkUSD, ethUSD := ccipTH.CreatePricesPipeline(t) + defer linkUSD.Close() + defer ethUSD.Close() + ccipTH.SetUpNodesAndJobs(t, testPricePipeline, "", "") + + gasLimit := big.NewInt(200_00) + tokenAmount := big.NewInt(1) + + forkBlock, err := ccipTH.Dest.Chain.BlockByNumber(context.Background(), nil) + require.NoError(t, err, "Error while fetching the destination chain current block number") + + // Adjust time to start next blocks with timestamps two hours after the fork block. + // This is critical to have two forks with different block_timestamps. + err = ccipTH.Dest.Chain.AdjustTime(2 * time.Hour) + require.NoError(t, err, "Error while adjusting the destination chain time") + ccipTH.Dest.Chain.Commit() + + // Send request for the first time and make sure it's executed on the destination + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.Dest.User.GasLimit = 100000 + ccipTH.EventuallySendRequested(t, uint64(1)) + ccipTH.EventuallyReportCommitted(t, 1) + executionLog := ccipTH.AllNodesHaveExecutedSeqNums(t, 1, 1) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess) + + currentBlock, err := ccipTH.Dest.Chain.BlockByNumber(context.Background(), nil) + require.NoError(t, err, "Error while fetching the current block number of destination chain") + + // Reorg back to the `forkBlock`. Next blocks in the fork will have block_timestamps right after the fork, + // but before the 2 hours interval defined above for the canonical chain + require.NoError(t, ccipTH.Dest.Chain.Fork(testutils.Context(t), 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++ { + ccipTH.Dest.Chain.Commit() + } + + // State of the chain (block_timestamps) after reorg: + // / --> block1 (02:01) --> block2 (02:02) --> commit report (02:03) --> ... + // forkBlock (00:00) --> block1' (00:01) --> block2' (00:02) --> commit report' (00:03) --> ... + + // CCIP should commit and executed messages that was reorged away + ccipTH.EventuallyReportCommitted(t, 1) + executionLog = ccipTH.AllNodesHaveExecutedSeqNums(t, 1, 1) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess) + + // Sending another message and make sure it's executed on the destination + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.EventuallySendRequested(t, uint64(2)) + ccipTH.EventuallyReportCommitted(t, 2) + executionLog = ccipTH.AllNodesHaveExecutedSeqNums(t, 1, 2) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess) +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go index 4f5ba6cfaea..8372ae47486 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts.go @@ -32,24 +32,7 @@ type BackfillArgs struct { SourceStartBlock, DestStartBlock uint64 } -// GetFilteredSortedLaneTokens returns union of tokens supported on this lane, including fee tokens from the provided price registry -// and the bridgeable tokens from offRamp. Bridgeable tokens are only included if they are configured on the pricegetter -// Fee tokens are not filtered as they must always be priced -func GetFilteredSortedLaneTokens(ctx context.Context, offRamp ccipdata.OffRampReader, priceRegistry cciptypes.PriceRegistryReader, priceGetter cciptypes.PriceGetter) (laneTokens []cciptypes.Address, excludedTokens []cciptypes.Address, err error) { - destFeeTokens, destBridgeableTokens, err := GetDestinationTokens(ctx, offRamp, priceRegistry) - if err != nil { - return nil, nil, fmt.Errorf("get tokens with batch limit: %w", err) - } - - destTokensWithPrice, destTokensWithoutPrice, err := priceGetter.FilterConfiguredTokens(ctx, destBridgeableTokens) - if err != nil { - return nil, nil, fmt.Errorf("filter for priced tokens: %w", err) - } - - return flattenedAndSortedTokens(destFeeTokens, destTokensWithPrice), destTokensWithoutPrice, nil -} - -func flattenedAndSortedTokens(slices ...[]cciptypes.Address) (tokens []cciptypes.Address) { +func FlattenedAndSortedTokens(slices ...[]cciptypes.Address) (tokens []cciptypes.Address) { // fee token can overlap with bridgeable tokens, we need to dedup them to arrive at lane token set tokens = FlattenUniqueSlice(slices...) 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 73a3b834956..6f1cdb4a6af 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipcommon/shortcuts_test.go @@ -3,22 +3,14 @@ package ccipcommon import ( "fmt" "math/rand" - "sort" "strconv" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" - 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/pricegetter" ) func TestGetMessageIDsAsHexString(t *testing.T) { @@ -70,77 +62,47 @@ func TestFlattenUniqueSlice(t *testing.T) { } } -func TestGetFilteredChainTokens(t *testing.T) { - const numTokens = 6 - var tokens []cciptypes.Address - for i := 0; i < numTokens; i++ { - tokens = append(tokens, ccipcalc.EvmAddrToGeneric(utils.RandomAddress())) - } - +func TestFlattenedAndSortedTokens(t *testing.T) { testCases := []struct { - name string - feeTokens []cciptypes.Address - destTokens []cciptypes.Address - expectedChainTokens []cciptypes.Address - expectedFilteredTokens []cciptypes.Address + name string + inputSlices [][]cciptypes.Address + expectedOutput []cciptypes.Address }{ + {name: "empty", inputSlices: nil, expectedOutput: []cciptypes.Address{}}, + {name: "empty 2", inputSlices: [][]cciptypes.Address{}, expectedOutput: []cciptypes.Address{}}, { - name: "empty", - feeTokens: []cciptypes.Address{}, - destTokens: []cciptypes.Address{}, - expectedChainTokens: []cciptypes.Address{}, - expectedFilteredTokens: []cciptypes.Address{}, + name: "single", + inputSlices: [][]cciptypes.Address{{"0x1", "0x2", "0x3"}}, + expectedOutput: []cciptypes.Address{"0x1", "0x2", "0x3"}, }, { - name: "unique tokens", - feeTokens: []cciptypes.Address{tokens[0]}, - destTokens: []cciptypes.Address{tokens[1], tokens[2], tokens[3]}, - expectedChainTokens: []cciptypes.Address{tokens[0], tokens[1], tokens[2], tokens[3]}, - expectedFilteredTokens: []cciptypes.Address{tokens[4], tokens[5]}, + name: "simple", + inputSlices: [][]cciptypes.Address{{"0x1", "0x2", "0x3"}, {"0x2", "0x3", "0x4"}}, + expectedOutput: []cciptypes.Address{"0x1", "0x2", "0x3", "0x4"}, }, { - name: "all tokens", - feeTokens: []cciptypes.Address{tokens[0]}, - destTokens: []cciptypes.Address{tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]}, - expectedChainTokens: []cciptypes.Address{tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]}, - expectedFilteredTokens: []cciptypes.Address{}, - }, - { - name: "overlapping tokens", - feeTokens: []cciptypes.Address{tokens[0]}, - destTokens: []cciptypes.Address{tokens[1], tokens[2], tokens[5], tokens[3], tokens[0], tokens[2], tokens[3], tokens[4], tokens[5], tokens[5]}, - expectedChainTokens: []cciptypes.Address{tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]}, - expectedFilteredTokens: []cciptypes.Address{}, - }, - { - name: "unconfigured tokens", - feeTokens: []cciptypes.Address{tokens[0]}, - destTokens: []cciptypes.Address{tokens[0], tokens[1], tokens[2], tokens[3], tokens[0], tokens[2], tokens[3], tokens[4], tokens[5], tokens[5]}, - expectedChainTokens: []cciptypes.Address{tokens[0], tokens[1], tokens[2], tokens[3], tokens[4]}, - expectedFilteredTokens: []cciptypes.Address{tokens[5]}, + name: "more complex case", + inputSlices: [][]cciptypes.Address{ + {"0x1", "0x3"}, + {"0x2", "0x4", "0x3"}, + {"0x5", "0x2", "0x7", "0xa"}, + }, + expectedOutput: []cciptypes.Address{ + "0x1", + "0x2", + "0x3", + "0x4", + "0x5", + "0x7", + "0xa", + }, }, } - ctx := testutils.Context(t) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - priceRegistry := ccipdatamocks.NewPriceRegistryReader(t) - priceRegistry.On("GetFeeTokens", ctx).Return(tc.feeTokens, nil).Once() - - priceGet := pricegetter.NewMockPriceGetter(t) - priceGet.On("FilterConfiguredTokens", mock.Anything, mock.Anything).Return(tc.expectedChainTokens, tc.expectedFilteredTokens, nil) - - offRamp := ccipdatamocks.NewOffRampReader(t) - offRamp.On("GetTokens", ctx).Return(cciptypes.OffRampTokens{DestinationTokens: tc.destTokens}, nil).Once() - - chainTokens, filteredTokens, err := GetFilteredSortedLaneTokens(ctx, offRamp, priceRegistry, priceGet) - assert.NoError(t, err) - - sort.Slice(tc.expectedChainTokens, func(i, j int) bool { - return tc.expectedChainTokens[i] < tc.expectedChainTokens[j] - }) - assert.Equal(t, tc.expectedChainTokens, chainTokens) - assert.Equal(t, tc.expectedFilteredTokens, filteredTokens) + res := FlattenedAndSortedTokens(tc.inputSlices...) + assert.Equal(t, tc.expectedOutput, res) }) } } 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 57e8df1bde3..32ec1b24ac9 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 @@ -12,8 +12,8 @@ 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/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/ccipcalc" 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 c67c3c15276..ceafdf22721 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.TestLogger(t) + lggr := logger.Test(t) offRamp := utils.RandomAddress() ctx := context.Background() remoteChainSelector := uint64(2000) 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 d1666d548ae..971b507e828 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/provider.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/provider.go @@ -3,10 +3,11 @@ package ccipdataprovider import ( "context" + "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/logger" "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" ) 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 4e134b1f175..f46b1b55b1f 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 @@ -13,7 +13,7 @@ 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/assets" @@ -25,20 +25,16 @@ import ( "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/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_helper_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_helper_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_arm_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_0_0" + "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/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" 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" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -142,7 +138,7 @@ func TestCommitOnchainConfig(t *testing.T) { func TestCommitStoreReaders(t *testing.T) { user, ec := newSim(t) ctx := testutils.Context(t) - lggr := logger.TestLogger(t) + lggr := logger.Test(t) lpOpts := logpoller.Opts{ PollPeriod: 100 * time.Millisecond, FinalityDepth: 2, @@ -157,7 +153,6 @@ func TestCommitStoreReaders(t *testing.T) { lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, pgtest.NewSqlxDB(t), lggr), ec, lggr, headTracker, lpOpts) // Deploy 2 commit store versions - onramp1 := utils.RandomAddress() onramp2 := utils.RandomAddress() // Report rep := cciptypes.CommitStoreReport{ @@ -167,14 +162,7 @@ func TestCommitStoreReaders(t *testing.T) { MerkleRoot: common.HexToHash("0x1"), } er := big.NewInt(1) - armAddr, _, arm, err := mock_arm_contract.DeployMockARMContract(user, ec) - require.NoError(t, err) - addr, _, ch, err := commit_store_helper_1_0_0.DeployCommitStoreHelper(user, ec, commit_store_helper_1_0_0.CommitStoreStaticConfig{ - ChainSelector: testutils.SimulatedChainID.Uint64(), - SourceChainSelector: testutils.SimulatedChainID.Uint64(), - OnRamp: onramp1, - ArmProxy: armAddr, - }) + armAddr, _, arm, err := mock_rmn_contract.DeployMockRMNContract(user, ec) require.NoError(t, err) addr2, _, ch2, err := commit_store_helper_1_2_0.DeployCommitStoreHelper(user, ec, commit_store_helper_1_2_0.CommitStoreStaticConfig{ ChainSelector: testutils.SimulatedChainID.Uint64(), @@ -184,8 +172,6 @@ func TestCommitStoreReaders(t *testing.T) { }) require.NoError(t, err) commitAndGetBlockTs(ec) // Deploy these - pr, _, _, err := price_registry_1_0_0.DeployPriceRegistry(user, ec, []common.Address{addr}, nil, 1e6) - require.NoError(t, err) pr2, _, _, err := price_registry_1_2_0.DeployPriceRegistry(user, ec, []common.Address{addr2}, nil, 1e6) require.NoError(t, err) commitAndGetBlockTs(ec) // Deploy these @@ -194,13 +180,6 @@ func TestCommitStoreReaders(t *testing.T) { ge.On("L1Oracle").Return(lm) maxGasPrice := big.NewInt(1e8) - c10r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr), ec, lp) // ge, maxGasPrice - require.NoError(t, err) - err = c10r.SetGasEstimator(ctx, ge) - require.NoError(t, err) - err = c10r.SetSourceMaxGasPrice(ctx, maxGasPrice) - require.NoError(t, err) - assert.Equal(t, reflect.TypeOf(c10r).String(), reflect.TypeOf(&v1_0_0.CommitStore{}).String()) c12r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr2), ec, lp) require.NoError(t, err) err = c12r.SetGasEstimator(ctx, ge) @@ -212,10 +191,6 @@ func TestCommitStoreReaders(t *testing.T) { // Apply config signers := []common.Address{utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress()} transmitters := []common.Address{utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress()} - onchainConfig, err := abihelpers.EncodeAbiStruct[ccipdata.CommitOnchainConfig](ccipdata.CommitOnchainConfig{ - PriceRegistry: pr, - }) - require.NoError(t, err) sourceFinalityDepth := uint32(1) destFinalityDepth := uint32(2) @@ -227,16 +202,6 @@ func TestCommitStoreReaders(t *testing.T) { InflightCacheExpiry: 3 * time.Hour, PriceReportingDisabled: false, } - offchainConfig, err := ccipconfig.EncodeOffchainConfig[v1_0_0.CommitOffchainConfig](v1_0_0.CommitOffchainConfig{ - SourceFinalityDepth: sourceFinalityDepth, - DestFinalityDepth: destFinalityDepth, - FeeUpdateHeartBeat: *config.MustNewDuration(commonOffchain.GasPriceHeartBeat), - FeeUpdateDeviationPPB: commonOffchain.GasPriceDeviationPPB, - InflightCacheExpiry: *config.MustNewDuration(commonOffchain.InflightCacheExpiry), - }) - require.NoError(t, err) - _, err = ch.SetOCR2Config(user, signers, transmitters, 1, onchainConfig, 1, []byte{}) - require.NoError(t, err) onchainConfig2, err := abihelpers.EncodeAbiStruct[ccipdata.CommitOnchainConfig](ccipdata.CommitOnchainConfig{ PriceRegistry: pr2, }) @@ -256,12 +221,7 @@ func TestCommitStoreReaders(t *testing.T) { require.NoError(t, err) commitAndGetBlockTs(ec) - // Apply report - b, err := c10r.EncodeCommitReport(ctx, rep) - require.NoError(t, err) - _, err = ch.Report(user, b, er) - require.NoError(t, err) - b, err = c12r.EncodeCommitReport(ctx, rep) + b, err := c12r.EncodeCommitReport(ctx, rep) require.NoError(t, err) _, err = ch2.Report(user, b, er) require.NoError(t, err) @@ -271,20 +231,17 @@ func TestCommitStoreReaders(t *testing.T) { lp.PollAndSaveLogs(context.Background(), 1) configs := map[string][][]byte{ - ccipdata.V1_0_0: {onchainConfig, offchainConfig}, ccipdata.V1_2_0: {onchainConfig2, offchainConfig2}, } crs := map[string]ccipdata.CommitStoreReader{ - ccipdata.V1_0_0: c10r, ccipdata.V1_2_0: c12r, } prs := map[string]common.Address{ - ccipdata.V1_0_0: pr, ccipdata.V1_2_0: pr2, } gasPrice := big.NewInt(10) daPrice := big.NewInt(20) - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, assets.NewWei(maxGasPrice)).Return(gas.EvmFee{Legacy: assets.NewWei(gasPrice)}, uint64(0), nil) + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, assets.NewWei(maxGasPrice), (*common.Address)(nil), (*common.Address)(nil)).Return(gas.EvmFee{GasPrice: assets.NewWei(gasPrice)}, uint64(0), nil) lm.On("GasPrice", mock.Anything).Return(assets.NewWei(daPrice), nil) for v, cr := range crs { @@ -412,7 +369,7 @@ func TestNewCommitStoreReader(t *testing.T) { if tc.expectedErr == "" { lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) } - _, err = factory.NewCommitStoreReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp) + _, err = factory.NewCommitStoreReader(logger.Test(t), factory.NewEvmVersionFinder(), addr, c, lp) 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 d431d2863a0..ec4cdded9a7 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 @@ -4,19 +4,17 @@ import ( "github.com/Masterminds/semver/v3" "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/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_0_0" - "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/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/v1_0_0" "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/ccipdata/v1_5_0" ) @@ -47,15 +45,6 @@ func initOrCloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinde lggr.Infow("Initializing CommitStore Reader", "version", version.String()) switch version.String() { - case ccipdata.V1_0_0, ccipdata.V1_1_0: // Versions are identical - cs, err := v1_0_0.NewCommitStore(lggr, evmAddr, ec, lp) - if err != nil { - return nil, err - } - if closeReader { - return nil, cs.Close() - } - return cs, cs.RegisterFilters() case ccipdata.V1_2_0: cs, err := v1_2_0.NewCommitStore(lggr, evmAddr, ec, lp) if err != nil { @@ -84,19 +73,10 @@ func CommitReportToEthTxMeta(typ ccipconfig.ContractType, ver semver.Version) (f return nil, errors.Errorf("expected %v got %v", ccipconfig.CommitStore, typ) } switch ver.String() { - case ccipdata.V1_0_0, ccipdata.V1_1_0: - commitStoreABI := abihelpers.MustParseABI(commit_store_1_0_0.CommitStoreABI) - return func(report []byte) (*txmgr.TxMeta, error) { - commitReport, err := v1_0_0.DecodeCommitReport(abihelpers.MustGetEventInputs(v1_0_0.ReportAccepted, commitStoreABI), report) - if err != nil { - return nil, err - } - return commitReportToEthTxMeta(commitReport) - }, nil case ccipdata.V1_2_0, ccipdata.V1_5_0: commitStoreABI := abihelpers.MustParseABI(commit_store.CommitStoreABI) return func(report []byte) (*txmgr.TxMeta, error) { - commitReport, err := v1_2_0.DecodeCommitReport(abihelpers.MustGetEventInputs(v1_0_0.ReportAccepted, commitStoreABI), report) + commitReport, err := v1_2_0.DecodeCommitReport(abihelpers.MustGetEventInputs(v1_2_0.ReportAccepted, commitStoreABI), report) 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 e1b8ff929c3..6beb6953d1a 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 @@ -9,18 +9,19 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" mocks2 "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/logger" 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_0_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) func TestCommitStore(t *testing.T) { - for _, versionStr := range []string{ccipdata.V1_0_0, ccipdata.V1_2_0} { - lggr := logger.TestLogger(t) + for _, versionStr := range []string{ccipdata.V1_2_0} { + lggr := logger.Test(t) addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) @@ -29,7 +30,7 @@ func TestCommitStore(t *testing.T) { _, err := NewCommitStoreReader(lggr, versionFinder, addr, nil, lp) assert.NoError(t, err) - expFilterName := logpoller.FilterName(v1_0_0.EXEC_REPORT_ACCEPTS, addr) + expFilterName := logpoller.FilterName(v1_2_0.ExecReportAccepts, addr) lp.On("UnregisterFilter", mock.Anything, expFilterName).Return(nil) err = CloseCommitStoreReader(lggr, versionFinder, addr, nil, lp) 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 c6fa63ee820..f0f26fb37f3 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "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/chains/evm/client" @@ -15,13 +16,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "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_offramp_1_0_0" - "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/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/v1_0_0" "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/ccipdata/v1_5_0" ) @@ -52,15 +50,6 @@ func initOrCloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, a lggr.Infow("Initializing OffRamp Reader", "version", version.String(), "destMaxGasPrice", destMaxGasPrice.String()) switch version.String() { - case ccipdata.V1_0_0, ccipdata.V1_1_0: - offRamp, err := v1_0_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) - if err != nil { - return nil, err - } - if closeReader { - return nil, offRamp.Close() - } - return offRamp, offRamp.RegisterFilters() case ccipdata.V1_2_0: offRamp, err := v1_2_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) if err != nil { @@ -90,15 +79,6 @@ func ExecReportToEthTxMeta(ctx context.Context, typ ccipconfig.ContractType, ver return nil, errors.Errorf("expected %v got %v", ccipconfig.EVM2EVMOffRamp, typ) } switch ver.String() { - case ccipdata.V1_0_0, ccipdata.V1_1_0: - offRampABI := abihelpers.MustParseABI(evm_2_evm_offramp_1_0_0.EVM2EVMOffRampABI) - return func(report []byte) (*txmgr.TxMeta, error) { - execReport, err := v1_0_0.DecodeExecReport(ctx, abihelpers.MustGetMethodInputs(ccipdata.ManuallyExecute, offRampABI)[:1], report) - if err != nil { - return nil, err - } - return execReportToEthTxMeta(execReport) - }, nil case ccipdata.V1_2_0, ccipdata.V1_5_0: offRampABI := abihelpers.MustParseABI(evm_2_evm_offramp.EVM2EVMOffRampABI) return func(report []byte) (*txmgr.TxMeta, error) { 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 4b9e57ecfbd..1851a6fb612 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 @@ -7,27 +7,27 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "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" mocks2 "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/logger" 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_0_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) func TestOffRamp(t *testing.T) { - for _, versionStr := range []string{ccipdata.V1_0_0, ccipdata.V1_2_0} { - lggr := logger.TestLogger(t) + for _, versionStr := range []string{ccipdata.V1_2_0} { + lggr := logger.Test(t) addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) expFilterNames := []string{ - logpoller.FilterName(v1_0_0.EXEC_EXECUTION_STATE_CHANGES, addr), - logpoller.FilterName(v1_0_0.EXEC_TOKEN_POOL_ADDED, addr), - logpoller.FilterName(v1_0_0.EXEC_TOKEN_POOL_REMOVED, addr), + logpoller.FilterName(v1_2_0.ExecExecutionStateChanges, addr), + logpoller.FilterName(v1_2_0.ExecTokenPoolAdded, addr), + logpoller.FilterName(v1_2_0.ExecTokenPoolRemoved, addr), } versionFinder := newMockVersionFinder(ccipconfig.EVM2EVMOffRamp, *semver.MustParse(versionStr), nil) 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 e82584ac7cc..e04a34f72de 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp.go @@ -3,16 +3,15 @@ package factory import ( "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/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" + 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" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_1_0" "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/ccipdata/v1_5_0" ) @@ -44,24 +43,6 @@ func initOrCloseOnRampReader(lggr logger.Logger, versionFinder VersionFinder, so lggr.Infof("Initializing onRamp for version %v", version.String()) switch version.String() { - case ccipdata.V1_0_0: - onRamp, err := v1_0_0.NewOnRamp(lggr, sourceSelector, destSelector, onRampAddrEvm, sourceLP, source) - if err != nil { - return nil, err - } - if closeReader { - return nil, onRamp.Close() - } - return onRamp, onRamp.RegisterFilters() - case ccipdata.V1_1_0: - onRamp, err := v1_1_0.NewOnRamp(lggr, sourceSelector, destSelector, onRampAddrEvm, sourceLP, source) - if err != nil { - return nil, err - } - if closeReader { - return nil, onRamp.Close() - } - return onRamp, onRamp.RegisterFilters() case ccipdata.V1_2_0: onRamp, err := v1_2_0.NewOnRamp(lggr, sourceSelector, destSelector, onRampAddrEvm, sourceLP, source) if err != nil { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp_test.go index 8cf47ddc7be..320c8d6c301 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/onramp_test.go @@ -7,19 +7,19 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "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" mocks2 "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/logger" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" ) func TestOnRamp(t *testing.T) { - for _, versionStr := range []string{ccipdata.V1_0_0, ccipdata.V1_1_0, ccipdata.V1_2_0, ccipdata.V1_5_0} { - lggr := logger.TestLogger(t) + for _, versionStr := range []string{ccipdata.V1_2_0, ccipdata.V1_5_0} { + lggr := logger.Test(t) addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry.go index f1fa7c4e81a..cb82e7273bf 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry.go @@ -5,16 +5,14 @@ import ( "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/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" 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/ccipcommon" "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_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -37,23 +35,9 @@ func initOrClosePriceRegistryReader(ctx context.Context, lggr logger.Logger, ver } contractType, version, err := versionFinder.TypeAndVersion(priceRegistryAddress, cl) - isV1_0_0 := ccipcommon.IsTxRevertError(err) || (contractType == ccipconfig.PriceRegistry && version.String() == ccipdata.V1_0_0) - if isV1_0_0 { - lggr.Infof("Assuming %v is 1.0.0 price registry, got %v", priceRegistryEvmAddr, err) - // Unfortunately the v1 price registry doesn't have a method to get the version so assume if it reverts its v1. - pr, err2 := v1_0_0.NewPriceRegistry(lggr, priceRegistryEvmAddr, lp, cl, registerFilters) - if err2 != nil { - return nil, err2 - } - if closeReader { - return nil, pr.Close() - } - return pr, nil - } if err != nil { - return nil, errors.Wrapf(err, "unable to read type and version") + return nil, err } - if contractType != ccipconfig.PriceRegistry { return nil, errors.Errorf("expected %v got %v", ccipconfig.PriceRegistry, contractType) } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry_test.go index b4a9d307147..0e0bf4f3d62 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/price_registry_test.go @@ -9,11 +9,12 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" mocks2 "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" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" ) @@ -21,8 +22,8 @@ import ( func TestPriceRegistry(t *testing.T) { ctx := testutils.Context(t) - for _, versionStr := range []string{ccipdata.V1_0_0, ccipdata.V1_2_0} { - lggr := logger.TestLogger(t) + for _, versionStr := range []string{ccipdata.V1_2_0} { + lggr := logger.Test(t) addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/versionfinder.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/versionfinder.go index ac16fc4df2f..061392ca316 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/versionfinder.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/versionfinder.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" 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/internal/ccipcalc" ) 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 6f14fb8559c..d0b3fe53436 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,6 +12,7 @@ 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/client" @@ -22,17 +23,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_helper" "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_offramp_1_0_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/mock_arm_contract" + "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" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -41,47 +39,6 @@ type offRampReaderTH struct { reader ccipdata.OffRampReader } -func TestExecOnchainConfig100(t *testing.T) { - tests := []struct { - name string - want v1_0_0.ExecOnchainConfig - expectErr bool - }{ - { - name: "encodes and decodes config with all fields set", - want: v1_0_0.ExecOnchainConfig{ - PermissionLessExecutionThresholdSeconds: rand.Uint32(), - Router: utils.RandomAddress(), - PriceRegistry: utils.RandomAddress(), - MaxTokensLength: uint16(rand.Uint32()), - MaxDataSize: rand.Uint32(), - }, - }, - { - name: "encodes and fails decoding config with missing fields", - want: v1_0_0.ExecOnchainConfig{ - PermissionLessExecutionThresholdSeconds: rand.Uint32(), - MaxDataSize: rand.Uint32(), - }, - expectErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - encoded, err := abihelpers.EncodeAbiStruct(tt.want) - require.NoError(t, err) - - decoded, err := abihelpers.DecodeAbiStruct[v1_0_0.ExecOnchainConfig](encoded) - if tt.expectErr { - require.ErrorContains(t, err, "must set") - } else { - require.NoError(t, err) - require.Equal(t, tt.want, decoded) - } - }) - } -} - func TestExecOnchainConfig120(t *testing.T) { tests := []struct { name string @@ -129,14 +86,6 @@ func TestOffRampReaderInit(t *testing.T) { name string version string }{ - { - name: "OffRampReader_V1_0_0", - version: ccipdata.V1_0_0, - }, - { - name: "OffRampReader_V1_1_0", - version: ccipdata.V1_1_0, - }, { name: "OffRampReader_V1_2_0", version: ccipdata.V1_2_0, @@ -158,7 +107,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.TestLogger(t) + log := logger.Test(t) orm := logpoller.NewORM(testutils.SimulatedChainID, pgtest.NewSqlxDB(t), log) lpOpts := logpoller.Opts{ PollPeriod: 100 * time.Millisecond, @@ -181,11 +130,6 @@ func setupOffRampReaderTH(t *testing.T, version string) offRampReaderTH { // Setup offRamp. var offRampAddress common.Address switch version { - case ccipdata.V1_0_0: - offRampAddress = setupOffRampV1_0_0(t, user, bc) - case ccipdata.V1_1_0: - // Version 1.1.0 uses the same contracts as 1.0.0. - offRampAddress = setupOffRampV1_0_0(t, user, bc) case ccipdata.V1_2_0: offRampAddress = setupOffRampV1_2_0(t, user, bc) case ccipdata.V1_5_0: @@ -207,42 +151,6 @@ func setupOffRampReaderTH(t *testing.T, version string) offRampReaderTH { } } -func setupOffRampV1_0_0(t *testing.T, user *bind.TransactOpts, bc *client.SimulatedBackendClient) common.Address { - onRampAddr := utils.RandomAddress() - armAddr := deployMockArm(t, user, bc) - csAddr := deployCommitStore(t, user, bc, onRampAddr, armAddr) - - // Deploy the OffRamp. - staticConfig := evm_2_evm_offramp_1_0_0.EVM2EVMOffRampStaticConfig{ - CommitStore: csAddr, - ChainSelector: testutils.SimulatedChainID.Uint64(), - SourceChainSelector: testutils.SimulatedChainID.Uint64(), - OnRamp: onRampAddr, - PrevOffRamp: common.Address{}, - ArmProxy: armAddr, - } - sourceTokens := []common.Address{} - pools := []common.Address{} - rateLimiterConfig := evm_2_evm_offramp_1_0_0.RateLimiterConfig{ - IsEnabled: false, - Capacity: big.NewInt(0), - Rate: big.NewInt(0), - } - - offRampAddr, tx, offRamp, err := evm_2_evm_offramp_1_0_0.DeployEVM2EVMOffRamp(user, bc, staticConfig, sourceTokens, pools, rateLimiterConfig) - bc.Commit() - require.NoError(t, err) - ccipdata.AssertNonRevert(t, tx, bc, user) - - // Verify the deployed OffRamp. - tav, err := offRamp.TypeAndVersion(&bind.CallOpts{ - Context: testutils.Context(t), - }) - require.NoError(t, err) - require.Equal(t, "EVM2EVMOffRamp 1.0.0", tav) - return offRampAddr -} - func setupOffRampV1_2_0(t *testing.T, user *bind.TransactOpts, bc *client.SimulatedBackendClient) common.Address { onRampAddr := utils.RandomAddress() armAddr := deployMockArm(t, user, bc) @@ -311,7 +219,7 @@ func setupOffRampV1_5_0(t *testing.T, user *bind.TransactOpts, bc *client.Simula Context: testutils.Context(t), }) require.NoError(t, err) - require.Equal(t, "EVM2EVMOffRamp 1.5.0-dev", tav) + require.Equal(t, "EVM2EVMOffRamp 1.5.0", tav) return offRampAddr } @@ -320,7 +228,7 @@ func deployMockArm( user *bind.TransactOpts, bc *client.SimulatedBackendClient, ) common.Address { - armAddr, tx, _, err := mock_arm_contract.DeployMockARMContract(user, bc) + armAddr, tx, _, err := mock_rmn_contract.DeployMockRMNContract(user, bc) require.NoError(t, err) bc.Commit() ccipdata.AssertNonRevert(t, tx, bc, user) @@ -353,7 +261,7 @@ func deployCommitStore( } tav, err := cs.TypeAndVersion(callOpts) require.NoError(t, err) - require.Equal(t, "CommitStore 1.5.0-dev", tav) + require.Equal(t, "CommitStore 1.5.0", tav) return csAddr } @@ -405,7 +313,7 @@ func TestNewOffRampReader(t *testing.T) { addr := ccipcalc.EvmAddrToGeneric(utils.RandomAddress()) lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Maybe() - _, err = factory.NewOffRampReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp, nil, nil, true) + _, err = factory.NewOffRampReader(logger.Test(t), factory.NewEvmVersionFinder(), addr, c, lp, nil, nil, true) if tc.expectedErr != "" { assert.EqualError(t, err, tc.expectedErr) } else { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader_test.go index 9cfe3f628c0..db2e54f96ba 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/onramp_reader_test.go @@ -14,6 +14,8 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclientmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" @@ -21,12 +23,9 @@ import ( 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/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_1_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/internal/testutils/pgtest" - "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" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" @@ -40,7 +39,7 @@ type onRampReaderTH struct { func TestNewOnRampReader_noContractAtAddress(t *testing.T) { _, bc := ccipdata.NewSimulation(t) addr := ccipcalc.EvmAddrToGeneric(utils.RandomAddress()) - _, err := factory.NewOnRampReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), testutils.SimulatedChainID.Uint64(), testutils.SimulatedChainID.Uint64(), addr, lpmocks.NewLogPoller(t), bc) + _, err := factory.NewOnRampReader(logger.Test(t), factory.NewEvmVersionFinder(), testutils.SimulatedChainID.Uint64(), testutils.SimulatedChainID.Uint64(), addr, lpmocks.NewLogPoller(t), bc) assert.EqualError(t, err, fmt.Sprintf("unable to read type and version: error calling typeAndVersion on addr: %s no contract code at given address", addr)) } @@ -49,14 +48,6 @@ func TestOnRampReaderInit(t *testing.T) { name string version string }{ - { - name: "OnRampReader_V1_0_0", - version: ccipdata.V1_0_0, - }, - { - name: "OnRampReader_V1_1_0", - version: ccipdata.V1_1_0, - }, { name: "OnRampReader_V1_2_0", version: ccipdata.V1_2_0, @@ -77,7 +68,7 @@ func TestOnRampReaderInit(t *testing.T) { func setupOnRampReaderTH(t *testing.T, version string) onRampReaderTH { user, bc := ccipdata.NewSimulation(t) - log := logger.TestLogger(t) + log := logger.Test(t) orm := logpoller.NewORM(testutils.SimulatedChainID, pgtest.NewSqlxDB(t), log) lpOpts := logpoller.Opts{ PollPeriod: 100 * time.Millisecond, @@ -100,10 +91,6 @@ func setupOnRampReaderTH(t *testing.T, version string) onRampReaderTH { // Setup onRamp. var onRampAddress common.Address switch version { - case ccipdata.V1_0_0: - onRampAddress = setupOnRampV1_0_0(t, user, bc) - case ccipdata.V1_1_0: - onRampAddress = setupOnRampV1_1_0(t, user, bc) case ccipdata.V1_2_0: onRampAddress = setupOnRampV1_2_0(t, user, bc) case ccipdata.V1_5_0: @@ -122,140 +109,6 @@ func setupOnRampReaderTH(t *testing.T, version string) onRampReaderTH { } } -func setupOnRampV1_0_0(t *testing.T, user *bind.TransactOpts, bc *client.SimulatedBackendClient) common.Address { - linkTokenAddress := common.HexToAddress("0x000011") - staticConfig := evm_2_evm_onramp_1_0_0.EVM2EVMOnRampStaticConfig{ - LinkToken: linkTokenAddress, - ChainSelector: testutils.SimulatedChainID.Uint64(), - DestChainSelector: testutils.SimulatedChainID.Uint64(), - DefaultTxGasLimit: 30000, - MaxNopFeesJuels: big.NewInt(1000000), - PrevOnRamp: common.Address{}, - ArmProxy: utils.RandomAddress(), - } - dynamicConfig := evm_2_evm_onramp_1_0_0.EVM2EVMOnRampDynamicConfig{ - Router: common.HexToAddress("0x000100"), - MaxTokensLength: 4, - PriceRegistry: utils.RandomAddress(), - MaxDataSize: 100000, - MaxGasLimit: 100000, - } - rateLimiterConfig := evm_2_evm_onramp_1_0_0.RateLimiterConfig{ - IsEnabled: false, - Capacity: big.NewInt(5), - Rate: big.NewInt(5), - } - allowList := []common.Address{user.From} - feeTokenConfigs := []evm_2_evm_onramp_1_0_0.EVM2EVMOnRampFeeTokenConfigArgs{ - { - Token: linkTokenAddress, - GasMultiplier: 1, - NetworkFeeAmountUSD: big.NewInt(0), - DestGasOverhead: 50, - DestGasPerPayloadByte: 60, - Enabled: false, - }, - } - tokenTransferConfigArgs := []evm_2_evm_onramp_1_0_0.EVM2EVMOnRampTokenTransferFeeConfigArgs{ - { - Token: utils.RandomAddress(), - MinFee: 10, - MaxFee: 1000, - Ratio: 1, - }, - } - nopsAndWeights := []evm_2_evm_onramp_1_0_0.EVM2EVMOnRampNopAndWeight{ - { - Nop: utils.RandomAddress(), - Weight: 1, - }, - } - tokenAndPool := []evm_2_evm_onramp_1_0_0.InternalPoolUpdate{} - onRampAddress, transaction, _, err := evm_2_evm_onramp_1_0_0.DeployEVM2EVMOnRamp( - user, - bc, - staticConfig, - dynamicConfig, - tokenAndPool, - allowList, - rateLimiterConfig, - feeTokenConfigs, - tokenTransferConfigArgs, - nopsAndWeights, - ) - bc.Commit() - require.NoError(t, err) - ccipdata.AssertNonRevert(t, transaction, bc, user) - return onRampAddress -} - -func setupOnRampV1_1_0(t *testing.T, user *bind.TransactOpts, bc *client.SimulatedBackendClient) common.Address { - linkTokenAddress := common.HexToAddress("0x000011") - staticConfig := evm_2_evm_onramp_1_1_0.EVM2EVMOnRampStaticConfig{ - LinkToken: linkTokenAddress, - ChainSelector: testutils.SimulatedChainID.Uint64(), - DestChainSelector: testutils.SimulatedChainID.Uint64(), - DefaultTxGasLimit: 30000, - MaxNopFeesJuels: big.NewInt(1000000), - PrevOnRamp: common.Address{}, - ArmProxy: utils.RandomAddress(), - } - dynamicConfig := evm_2_evm_onramp_1_1_0.EVM2EVMOnRampDynamicConfig{ - Router: common.HexToAddress("0x000110"), - MaxTokensLength: 4, - PriceRegistry: common.HexToAddress("0x000066"), - MaxDataSize: 100000, - MaxGasLimit: 100000, - } - rateLimiterConfig := evm_2_evm_onramp_1_1_0.RateLimiterConfig{ - IsEnabled: false, - Capacity: big.NewInt(5), - Rate: big.NewInt(5), - } - allowList := []common.Address{user.From} - feeTokenConfigs := []evm_2_evm_onramp_1_1_0.EVM2EVMOnRampFeeTokenConfigArgs{ - { - Token: linkTokenAddress, - NetworkFeeUSD: 0, - MinTokenTransferFeeUSD: 0, - MaxTokenTransferFeeUSD: 0, - GasMultiplier: 0, - PremiumMultiplier: 0, - Enabled: false, - }, - } - tokenTransferConfigArgs := []evm_2_evm_onramp_1_1_0.EVM2EVMOnRampTokenTransferFeeConfigArgs{ - { - Token: linkTokenAddress, - Ratio: 0, - DestGasOverhead: 0, - }, - } - nopsAndWeights := []evm_2_evm_onramp_1_1_0.EVM2EVMOnRampNopAndWeight{ - { - Nop: common.HexToAddress("0x222222222"), - Weight: 1, - }, - } - tokenAndPool := []evm_2_evm_onramp_1_1_0.InternalPoolUpdate{} - onRampAddress, transaction, _, err := evm_2_evm_onramp_1_1_0.DeployEVM2EVMOnRamp( - user, - bc, - staticConfig, - dynamicConfig, - tokenAndPool, - allowList, - rateLimiterConfig, - feeTokenConfigs, - tokenTransferConfigArgs, - nopsAndWeights, - ) - bc.Commit() - require.NoError(t, err) - ccipdata.AssertNonRevert(t, transaction, bc, user) - return onRampAddress -} - func setupOnRampV1_2_0(t *testing.T, user *bind.TransactOpts, bc *client.SimulatedBackendClient) common.Address { linkTokenAddress := common.HexToAddress("0x000011") staticConfig := evm_2_evm_onramp_1_2_0.EVM2EVMOnRampStaticConfig{ @@ -351,8 +204,7 @@ func setupOnRampV1_5_0(t *testing.T, user *bind.TransactOpts, bc *client.Simulat MaxDataBytes: 0, MaxPerMsgGasLimit: 0, DefaultTokenFeeUSDCents: 50, - DefaultTokenDestGasOverhead: 34_000, - DefaultTokenDestBytesOverhead: 500, + DefaultTokenDestGasOverhead: 125_000, } rateLimiterConfig := evm_2_evm_onramp.RateLimiterConfig{ IsEnabled: false, @@ -403,10 +255,6 @@ func setupOnRampV1_5_0(t *testing.T, user *bind.TransactOpts, bc *client.Simulat func testVersionSpecificOnRampReader(t *testing.T, th onRampReaderTH, version string) { switch version { - case ccipdata.V1_0_0: - testOnRampReader(t, th, common.HexToAddress("0x0000000000000000000000000000000000000100")) - case ccipdata.V1_1_0: - testOnRampReader(t, th, common.HexToAddress("0x0000000000000000000000000000000000000110")) case ccipdata.V1_2_0: testOnRampReader(t, th, common.HexToAddress("0x0000000000000000000000000000000000000120")) case ccipdata.V1_5_0: @@ -468,7 +316,7 @@ func TestNewOnRampReader(t *testing.T) { addr := ccipcalc.EvmAddrToGeneric(utils.RandomAddress()) lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Maybe() - _, err = factory.NewOnRampReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), 1, 2, addr, lp, c) + _, err = factory.NewOnRampReader(logger.Test(t), factory.NewEvmVersionFinder(), 1, 2, addr, lp, c) if tc.expectedErr != "" { require.EqualError(t, err, tc.expectedErr) } else { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go index e17b885cff2..1f8d48ddfee 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/price_registry_reader_test.go @@ -17,21 +17,20 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclientmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_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" "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/ccipdata/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -71,7 +70,7 @@ func newSim(t *testing.T) (*bind.TransactOpts, *client.SimulatedBackendClient) { // with a snapshot of data so reader tests can do multi-version assertions. func setupPriceRegistryReaderTH(t *testing.T) priceRegReaderTH { user, ec := newSim(t) - lggr := logger.TestLogger(t) + lggr := logger.Test(t) lpOpts := logpoller.Opts{ PollPeriod: 100 * time.Millisecond, FinalityDepth: 2, @@ -124,23 +123,16 @@ func setupPriceRegistryReaderTH(t *testing.T) priceRegReaderTH { }, } ctx := testutils.Context(t) - addr, _, _, err := price_registry_1_0_0.DeployPriceRegistry(user, ec, nil, feeTokens, 1000) - require.NoError(t, err) addr2, _, _, err := price_registry_1_2_0.DeployPriceRegistry(user, ec, nil, feeTokens, 1000) require.NoError(t, err) commitAndGetBlockTs(ec) // Deploy these - pr10r, err := factory.NewPriceRegistryReader(ctx, lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr), lp, ec) - require.NoError(t, err) - assert.Equal(t, reflect.TypeOf(pr10r).String(), reflect.TypeOf(&v1_0_0.PriceRegistry{}).String()) pr12r, err := factory.NewPriceRegistryReader(ctx, lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr2), lp, ec) require.NoError(t, err) assert.Equal(t, reflect.TypeOf(pr12r).String(), reflect.TypeOf(&v1_2_0.PriceRegistry{}).String()) // Apply block1. - v1_0_0.ApplyPriceRegistryUpdate(t, user, addr, ec, gasPriceUpdatesBlock1, tokenPriceUpdatesBlock1) v1_2_0.ApplyPriceRegistryUpdate(t, user, addr2, ec, gasPriceUpdatesBlock1, tokenPriceUpdatesBlock1) b1 := commitAndGetBlockTs(ec) // Apply block2 - v1_0_0.ApplyPriceRegistryUpdate(t, user, addr, ec, gasPriceUpdatesBlock2, tokenPriceUpdatesBlock2) v1_2_0.ApplyPriceRegistryUpdate(t, user, addr2, ec, gasPriceUpdatesBlock2, tokenPriceUpdatesBlock2) b2 := commitAndGetBlockTs(ec) @@ -153,7 +145,7 @@ func setupPriceRegistryReaderTH(t *testing.T) priceRegReaderTH { lggr: lggr, user: user, readers: map[string]ccipdata.PriceRegistryReader{ - ccipdata.V1_0_0: pr10r, ccipdata.V1_2_0: pr12r, + ccipdata.V1_2_0: pr12r, }, expectedFeeTokens: feeTokens, expectedGasUpdates: map[uint64][]cciptypes.GasPrice{ @@ -255,11 +247,7 @@ func TestNewPriceRegistryReader(t *testing.T) { expectedErr string }{ { - typeAndVersion: "blah", - expectedErr: "unable to read type and version: invalid type and version blah", - }, - { - typeAndVersion: "EVM2EVMOffRamp 1.0.0", + typeAndVersion: "EVM2EVMOffRamp 1.2.0", expectedErr: "expected PriceRegistry got EVM2EVMOffRamp", }, { @@ -285,7 +273,7 @@ func TestNewPriceRegistryReader(t *testing.T) { addr := ccipcalc.EvmAddrToGeneric(utils.RandomAddress()) lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Maybe() - _, err = factory.NewPriceRegistryReader(ctx, logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, lp, c) + _, err = factory.NewPriceRegistryReader(ctx, logger.Test(t), factory.NewEvmVersionFinder(), addr, lp, c) if tc.expectedErr != "" { require.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 a9a07f0879b..3c82948b892 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader.go @@ -6,10 +6,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" + "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" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) const ( @@ -17,7 +18,7 @@ const ( V1_1_0 = "1.1.0" V1_2_0 = "1.2.0" V1_4_0 = "1.4.0" - V1_5_0 = "1.5.0-dev" + V1_5_0 = "1.5.0" V1_6_0 = "1.6.0-dev" ) 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 06766be81ee..0df76873915 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/reader_test.go @@ -10,8 +10,9 @@ 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) { @@ -27,7 +28,7 @@ func Test_parseLogs(t *testing.T) { return &log.Index, nil } - parsedEvents, err := ParseLogs[uint](logs, logger.TestLogger(t), parseFn) + parsedEvents, err := ParseLogs[uint](logs, logger.Test(t), parseFn) require.NoError(t, err) assert.Len(t, parsedEvents, 100) @@ -55,7 +56,7 @@ func Test_parseLogs_withErrors(t *testing.T) { return &log.Index, nil } - log, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel) + log, observed := logger.TestObserved(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/usdc_reader.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader.go index 51ce0db7c04..cd8fd3150ae 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader.go @@ -10,9 +10,10 @@ import ( "github.com/patrickmn/go-cache" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "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" ) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_internal_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_internal_test.go index a5f0a1ffd06..953da52713b 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_internal_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/usdc_reader_internal_test.go @@ -14,6 +14,8 @@ 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/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -21,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestLogPollerClient_GetUSDCMessagePriorToLogIndexInTx(t *testing.T) { @@ -31,7 +32,7 @@ func TestLogPollerClient_GetUSDCMessagePriorToLogIndexInTx(t *testing.T) { expectedData := "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f80000000000000001000000020000000000048d71000000000000000000000000eb08f243e5d3fcff26a9e38ae5520a669f4019d000000000000000000000000023a04d5935ed8bc8e3eb78db3541f0abfb001c6e0000000000000000000000006cb3ed9b441eb674b58495c8b3324b59faff5243000000000000000000000000000000005425890298aed601595a70ab815c96711a31bc65000000000000000000000000ab4f961939bfe6a93567cc57c59eed7084ce2131000000000000000000000000000000000000000000000000000000000000271000000000000000000000000035e08285cfed1ef159236728f843286c55fc08610000000000000000" expectedPostParse := "0x0000000000000001000000020000000000048d71000000000000000000000000eb08f243e5d3fcff26a9e38ae5520a669f4019d000000000000000000000000023a04d5935ed8bc8e3eb78db3541f0abfb001c6e0000000000000000000000006cb3ed9b441eb674b58495c8b3324b59faff5243000000000000000000000000000000005425890298aed601595a70ab815c96711a31bc65000000000000000000000000ab4f961939bfe6a93567cc57c59eed7084ce2131000000000000000000000000000000000000000000000000000000000000271000000000000000000000000035e08285cfed1ef159236728f843286c55fc0861" - lggr := logger.TestLogger(t) + lggr := logger.Test(t) t.Run("multiple found - selected last", func(t *testing.T) { lp := lpmocks.NewLogPoller(t) @@ -136,7 +137,7 @@ func TestParse(t *testing.T) { func TestFilters(t *testing.T) { t.Run("filters of different jobs should be distinct", func(t *testing.T) { - lggr := logger.TestLogger(t) + lggr := logger.Test(t) chainID := testutils.NewRandomEVMChainID() db := pgtest.NewSqlxDB(t) o := logpoller.NewORM(chainID, db, lggr) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/commit_store.go deleted file mode 100644 index 3e58143a284..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/commit_store.go +++ /dev/null @@ -1,456 +0,0 @@ -package v1_0_0 - -import ( - "context" - "fmt" - "math/big" - "sync" - "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/core/types" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - - "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" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_0_0" - "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/ccipcalc" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/logpollerutil" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" -) - -const ( - EXEC_REPORT_ACCEPTS = "Exec report accepts" - ReportAccepted = "ReportAccepted" -) - -var _ ccipdata.CommitStoreReader = &CommitStore{} - -type CommitStore struct { - // Static config - commitStore *commit_store_1_0_0.CommitStore - lggr logger.Logger - lp logpoller.LogPoller - address common.Address - estimator *gas.EvmFeeEstimator - sourceMaxGasPrice *big.Int - filters []logpoller.Filter - reportAcceptedSig common.Hash - reportAcceptedMaxSeqIndex int - commitReportArgs abi.Arguments - - // Dynamic config - configMu sync.RWMutex - gasPriceEstimator prices.ExecGasPriceEstimator - offchainConfig cciptypes.CommitOffchainConfig -} - -func (c *CommitStore) GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) { - legacyConfig, err := c.commitStore.GetStaticConfig(&bind.CallOpts{Context: ctx}) - if err != nil { - return cciptypes.CommitStoreStaticConfig{}, errors.New("Could not get commitStore static config") - } - return cciptypes.CommitStoreStaticConfig{ - ChainSelector: legacyConfig.ChainSelector, - SourceChainSelector: legacyConfig.SourceChainSelector, - OnRamp: ccipcalc.EvmAddrToGeneric(legacyConfig.OnRamp), - ArmProxy: ccipcalc.EvmAddrToGeneric(legacyConfig.ArmProxy), - }, nil -} - -func (c *CommitStore) EncodeCommitReport(_ context.Context, report cciptypes.CommitStoreReport) ([]byte, error) { - return encodeCommitReport(c.commitReportArgs, report) -} - -func encodeCommitReport(commitReportArgs abi.Arguments, report cciptypes.CommitStoreReport) ([]byte, error) { - var tokenPriceUpdates []commit_store_1_0_0.InternalTokenPriceUpdate - for _, tokenPriceUpdate := range report.TokenPrices { - sourceTokenEvmAddr, err := ccipcalc.GenericAddrToEvm(tokenPriceUpdate.Token) - if err != nil { - return nil, err - } - tokenPriceUpdates = append(tokenPriceUpdates, commit_store_1_0_0.InternalTokenPriceUpdate{ - SourceToken: sourceTokenEvmAddr, - UsdPerToken: tokenPriceUpdate.Value, - }) - } - var usdPerUnitGas = big.NewInt(0) - var destChainSelector = uint64(0) - if len(report.GasPrices) > 1 { - return []byte{}, errors.Errorf("CommitStore V1_0_0 can only accept 1 gas price, received: %d", len(report.GasPrices)) - } - if len(report.GasPrices) > 0 { - usdPerUnitGas = report.GasPrices[0].Value - destChainSelector = report.GasPrices[0].DestChainSelector - } - rep := commit_store_1_0_0.CommitStoreCommitReport{ - PriceUpdates: commit_store_1_0_0.InternalPriceUpdates{ - TokenPriceUpdates: tokenPriceUpdates, - UsdPerUnitGas: usdPerUnitGas, - DestChainSelector: destChainSelector, - }, - Interval: commit_store_1_0_0.CommitStoreInterval{Min: report.Interval.Min, Max: report.Interval.Max}, - MerkleRoot: report.MerkleRoot, - } - return commitReportArgs.PackValues([]interface{}{rep}) -} - -func DecodeCommitReport(commitReportArgs abi.Arguments, report []byte) (cciptypes.CommitStoreReport, error) { - unpacked, err := commitReportArgs.Unpack(report) - if err != nil { - return cciptypes.CommitStoreReport{}, err - } - if len(unpacked) != 1 { - return cciptypes.CommitStoreReport{}, errors.New("expected single struct value") - } - - commitReport, ok := unpacked[0].(struct { - PriceUpdates struct { - TokenPriceUpdates []struct { - SourceToken common.Address `json:"sourceToken"` - UsdPerToken *big.Int `json:"usdPerToken"` - } `json:"tokenPriceUpdates"` - DestChainSelector uint64 `json:"destChainSelector"` - UsdPerUnitGas *big.Int `json:"usdPerUnitGas"` - } `json:"priceUpdates"` - Interval struct { - Min uint64 `json:"min"` - Max uint64 `json:"max"` - } `json:"interval"` - MerkleRoot [32]byte `json:"merkleRoot"` - }) - if !ok { - return cciptypes.CommitStoreReport{}, errors.Errorf("invalid commit report got %T", unpacked[0]) - } - - var tokenPriceUpdates []cciptypes.TokenPrice - for _, u := range commitReport.PriceUpdates.TokenPriceUpdates { - tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ - Token: cciptypes.Address(u.SourceToken.String()), - Value: u.UsdPerToken, - }) - } - - var gasPrices []cciptypes.GasPrice - if commitReport.PriceUpdates.DestChainSelector != 0 { - // No gas price update { - gasPrices = append(gasPrices, cciptypes.GasPrice{ - DestChainSelector: commitReport.PriceUpdates.DestChainSelector, - Value: commitReport.PriceUpdates.UsdPerUnitGas, - }) - } - - return cciptypes.CommitStoreReport{ - TokenPrices: tokenPriceUpdates, - GasPrices: gasPrices, - Interval: cciptypes.CommitStoreInterval{ - Min: commitReport.Interval.Min, - Max: commitReport.Interval.Max, - }, - MerkleRoot: commitReport.MerkleRoot, - }, nil -} - -func (c *CommitStore) DecodeCommitReport(_ context.Context, report []byte) (cciptypes.CommitStoreReport, error) { - return DecodeCommitReport(c.commitReportArgs, report) -} - -func (c *CommitStore) IsBlessed(ctx context.Context, root [32]byte) (bool, error) { - return c.commitStore.IsBlessed(&bind.CallOpts{Context: ctx}, root) -} - -func (c *CommitStore) OffchainConfig(context.Context) (cciptypes.CommitOffchainConfig, error) { - c.configMu.RLock() - defer c.configMu.RUnlock() - return c.offchainConfig, nil -} - -func (c *CommitStore) GasPriceEstimator(context.Context) (cciptypes.GasPriceEstimatorCommit, error) { - c.configMu.RLock() - defer c.configMu.RUnlock() - return c.gasPriceEstimator, nil -} - -func (c *CommitStore) SetGasEstimator(ctx context.Context, gpe gas.EvmFeeEstimator) error { - c.configMu.RLock() - defer c.configMu.RUnlock() - c.estimator = &gpe - return nil -} - -func (c *CommitStore) SetSourceMaxGasPrice(ctx context.Context, sourceMaxGasPrice *big.Int) error { - c.configMu.RLock() - defer c.configMu.RUnlock() - c.sourceMaxGasPrice = sourceMaxGasPrice - return nil -} - -// CommitOffchainConfig is a legacy version of CommitOffchainConfig, used for CommitStore version 1.0.0 and 1.1.0 -type CommitOffchainConfig struct { - SourceFinalityDepth uint32 - DestFinalityDepth uint32 - FeeUpdateHeartBeat config.Duration - FeeUpdateDeviationPPB uint32 - InflightCacheExpiry config.Duration - PriceReportingDisabled bool -} - -func (c CommitOffchainConfig) Validate() error { - if c.SourceFinalityDepth == 0 { - return errors.New("must set SourceFinalityDepth") - } - if c.DestFinalityDepth == 0 { - return errors.New("must set DestFinalityDepth") - } - if c.FeeUpdateHeartBeat.Duration() == 0 { - return errors.New("must set FeeUpdateHeartBeat") - } - if c.FeeUpdateDeviationPPB == 0 { - return errors.New("must set FeeUpdateDeviationPPB") - } - if c.InflightCacheExpiry.Duration() == 0 { - return errors.New("must set InflightCacheExpiry") - } - - return nil -} - -func (c *CommitStore) ChangeConfig(_ context.Context, onchainConfig []byte, offchainConfig []byte) (cciptypes.Address, error) { - onchainConfigParsed, err := abihelpers.DecodeAbiStruct[ccipdata.CommitOnchainConfig](onchainConfig) - if err != nil { - return "", err - } - - offchainConfigV1, err := ccipconfig.DecodeOffchainConfig[CommitOffchainConfig](offchainConfig) - if err != nil { - return "", err - } - c.configMu.Lock() - defer c.configMu.Unlock() - - if c.estimator == nil { - return "", fmt.Errorf("this CommitStore estimator is nil. SetGasEstimator should be called before ChangeConfig") - } - - if c.sourceMaxGasPrice == nil { - return "", fmt.Errorf("this CommitStore sourceMaxGasPrice is nil. SetSourceMaxGasPrice should be called before ChangeConfig") - } - - c.gasPriceEstimator = prices.NewExecGasPriceEstimator( - *c.estimator, - c.sourceMaxGasPrice, - int64(offchainConfigV1.FeeUpdateDeviationPPB)) - c.offchainConfig = ccipdata.NewCommitOffchainConfig( - offchainConfigV1.FeeUpdateDeviationPPB, - offchainConfigV1.FeeUpdateHeartBeat.Duration(), - offchainConfigV1.FeeUpdateDeviationPPB, - offchainConfigV1.FeeUpdateHeartBeat.Duration(), - offchainConfigV1.InflightCacheExpiry.Duration(), - offchainConfigV1.PriceReportingDisabled) - c.lggr.Infow("ChangeConfig", - "offchainConfig", offchainConfigV1, - "onchainConfig", onchainConfigParsed, - ) - return cciptypes.Address(onchainConfigParsed.PriceRegistry.String()), nil -} - -func (c *CommitStore) Close() error { - return logpollerutil.UnregisterLpFilters(c.lp, c.filters) -} - -func (c *CommitStore) parseReport(log types.Log) (*cciptypes.CommitStoreReport, error) { - repAccepted, err := c.commitStore.ParseReportAccepted(log) - if err != nil { - return nil, err - } - // Translate to common struct. - var tokenPrices []cciptypes.TokenPrice - for _, tpu := range repAccepted.Report.PriceUpdates.TokenPriceUpdates { - tokenPrices = append(tokenPrices, cciptypes.TokenPrice{ - Token: cciptypes.Address(tpu.SourceToken.String()), - Value: tpu.UsdPerToken, - }) - } - return &cciptypes.CommitStoreReport{ - TokenPrices: tokenPrices, - GasPrices: []cciptypes.GasPrice{{DestChainSelector: repAccepted.Report.PriceUpdates.DestChainSelector, Value: repAccepted.Report.PriceUpdates.UsdPerUnitGas}}, - MerkleRoot: repAccepted.Report.MerkleRoot, - Interval: cciptypes.CommitStoreInterval{Min: repAccepted.Report.Interval.Min, Max: repAccepted.Report.Interval.Max}, - }, nil -} - -func (c *CommitStore) GetCommitReportMatchingSeqNum(ctx context.Context, seqNr uint64, confs int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { - logs, err := c.lp.LogsDataWordBetween( - ctx, - c.reportAcceptedSig, - c.address, - c.reportAcceptedMaxSeqIndex-1, - c.reportAcceptedMaxSeqIndex, - logpoller.EvmWord(seqNr), - evmtypes.Confirmations(confs), - ) - if err != nil { - return nil, err - } - - parsedLogs, err := ccipdata.ParseLogs[cciptypes.CommitStoreReport]( - logs, - c.lggr, - c.parseReport, - ) - if err != nil { - return nil, err - } - - res := make([]cciptypes.CommitStoreReportWithTxMeta, 0, len(parsedLogs)) - for _, log := range parsedLogs { - res = append(res, cciptypes.CommitStoreReportWithTxMeta{ - TxMeta: log.TxMeta, - CommitStoreReport: log.Data, - }) - } - - if len(res) > 1 { - c.lggr.Errorw("More than one report found for seqNr", "seqNr", seqNr, "commitReports", parsedLogs) - return res[:1], nil - } - return res, nil -} - -func (c *CommitStore) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, ts time.Time, confs int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { - latestBlock, err := c.lp.LatestBlock(ctx) - if err != nil { - return nil, err - } - - reportsQuery, err := query.Where( - c.address.String(), - logpoller.NewAddressFilter(c.address), - logpoller.NewEventSigFilter(c.reportAcceptedSig), - query.Timestamp(uint64(ts.Unix()), primitives.Gte), - logpoller.NewConfirmationsFilter(evmtypes.Confirmations(confs)), - ) - if err != nil { - return nil, err - } - - logs, err := c.lp.FilteredLogs( - ctx, - reportsQuery, - query.NewLimitAndSort(query.Limit{}, query.NewSortBySequence(query.Asc)), - "GetAcceptedCommitReportsGteTimestamp", - ) - if err != nil { - return nil, err - } - - parsedLogs, err := ccipdata.ParseLogs[cciptypes.CommitStoreReport](logs, c.lggr, c.parseReport) - if err != nil { - return nil, fmt.Errorf("parse logs: %w", err) - } - - parsedReports := make([]cciptypes.CommitStoreReportWithTxMeta, 0, len(parsedLogs)) - for _, log := range parsedLogs { - parsedReports = append(parsedReports, cciptypes.CommitStoreReportWithTxMeta{ - TxMeta: log.TxMeta.WithFinalityStatus(uint64(latestBlock.FinalizedBlockNumber)), - CommitStoreReport: log.Data, - }) - } - - return parsedReports, nil -} - -func (c *CommitStore) GetExpectedNextSequenceNumber(ctx context.Context) (uint64, error) { - return c.commitStore.GetExpectedNextSequenceNumber(&bind.CallOpts{Context: ctx}) -} - -func (c *CommitStore) GetLatestPriceEpochAndRound(ctx context.Context) (uint64, error) { - return c.commitStore.GetLatestPriceEpochAndRound(&bind.CallOpts{Context: ctx}) -} - -func (c *CommitStore) IsDestChainHealthy(context.Context) (bool, error) { - if err := c.lp.Healthy(); err != nil { - return false, nil - } - return true, nil -} - -func (c *CommitStore) IsDown(ctx context.Context) (bool, error) { - unPausedAndHealthy, err := c.commitStore.IsUnpausedAndARMHealthy(&bind.CallOpts{Context: ctx}) - if err != nil { - return true, err - } - return !unPausedAndHealthy, nil -} - -func (c *CommitStore) VerifyExecutionReport(ctx context.Context, report cciptypes.ExecReport) (bool, error) { - var hashes [][32]byte - for _, msg := range report.Messages { - hashes = append(hashes, msg.Hash) - } - res, err := c.commitStore.Verify(&bind.CallOpts{Context: ctx}, hashes, report.Proofs, report.ProofFlagBits) - if err != nil { - c.lggr.Errorw("Unable to call verify", "messages", report.Messages, "err", err) - return false, nil - } - // No timestamp, means failed to verify root. - if res.Cmp(big.NewInt(0)) == 0 { - c.lggr.Errorw("Root does not verify", "messages", report.Messages) - return false, nil - } - return true, nil -} - -func (c *CommitStore) RegisterFilters() error { - return logpollerutil.RegisterLpFilters(c.lp, c.filters) -} - -func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller) (*CommitStore, error) { - commitStore, err := commit_store_1_0_0.NewCommitStore(addr, ec) - if err != nil { - return nil, err - } - commitStoreABI := abihelpers.MustParseABI(commit_store_1_0_0.CommitStoreABI) - eventSig := abihelpers.MustGetEventID(ReportAccepted, commitStoreABI) - commitReportArgs := abihelpers.MustGetEventInputs(ReportAccepted, commitStoreABI) - filters := []logpoller.Filter{ - { - Name: logpoller.FilterName(EXEC_REPORT_ACCEPTS, addr.String()), - EventSigs: []common.Hash{eventSig}, - Addresses: []common.Address{addr}, - Retention: ccipdata.CommitExecLogsRetention, - }, - } - return &CommitStore{ - commitStore: commitStore, - address: addr, - lggr: lggr, - lp: lp, - - // Note that sourceMaxGasPrice and estimator now have explicit setters (CCIP-2493) - - filters: filters, - commitReportArgs: commitReportArgs, - reportAcceptedSig: eventSig, - // offset || priceUpdatesOffset || minSeqNum || maxSeqNum || merkleRoot - reportAcceptedMaxSeqIndex: 3, - configMu: sync.RWMutex{}, - - // The fields below are initially empty and set on ChangeConfig method - offchainConfig: cciptypes.CommitOffchainConfig{}, - gasPriceEstimator: prices.ExecGasPriceEstimator{}, - }, nil -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/commit_store_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/commit_store_test.go deleted file mode 100644 index 31bcaf8a187..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/commit_store_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package v1_0_0 - -import ( - "math/big" - "math/rand" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - 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" -) - -func TestCommitReportEncoding(t *testing.T) { - ctx := testutils.Context(t) - report := cciptypes.CommitStoreReport{ - TokenPrices: []cciptypes.TokenPrice{ - { - Token: cciptypes.Address(utils.RandomAddress().String()), - Value: big.NewInt(9e18), - }, - }, - GasPrices: []cciptypes.GasPrice{ - { - DestChainSelector: rand.Uint64(), - Value: big.NewInt(2000e9), - }, - }, - MerkleRoot: [32]byte{123}, - Interval: cciptypes.CommitStoreInterval{Min: 1, Max: 10}, - } - - c, err := NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t)) - assert.NoError(t, err) - - encodedReport, err := c.EncodeCommitReport(ctx, report) - require.NoError(t, err) - assert.Greater(t, len(encodedReport), 0) - - decodedReport, err := c.DecodeCommitReport(ctx, encodedReport) - require.NoError(t, err) - require.Equal(t, report.TokenPrices, decodedReport.TokenPrices) - require.Equal(t, report, decodedReport) -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher.go deleted file mode 100644 index 0d1b7f736f6..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher.go +++ /dev/null @@ -1,85 +0,0 @@ -package v1_0_0 - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/chainlink-common/pkg/hashutil" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" -) - -const ( - MetaDataHashPrefix = "EVM2EVMMessageEvent" -) - -var LeafDomainSeparator = [1]byte{0x00} - -type LeafHasher struct { - metaDataHash [32]byte - ctx hashutil.Hasher[[32]byte] - onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp -} - -func GetMetaDataHash[H hashutil.Hash](ctx hashutil.Hasher[H], prefix [32]byte, sourceChainSelector uint64, onRampId common.Address, destChainSelector uint64) H { - paddedOnRamp := common.BytesToHash(onRampId[:]) - return ctx.Hash(utils.ConcatBytes(prefix[:], math.U256Bytes(big.NewInt(0).SetUint64(sourceChainSelector)), math.U256Bytes(big.NewInt(0).SetUint64(destChainSelector)), paddedOnRamp[:])) -} - -func NewLeafHasher(sourceChainSelector uint64, destChainSelector uint64, onRampId common.Address, ctx hashutil.Hasher[[32]byte], onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp) *LeafHasher { - return &LeafHasher{ - metaDataHash: GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector), - ctx: ctx, - onRamp: onRamp, - } -} - -func (t *LeafHasher) HashLeaf(log types.Log) ([32]byte, error) { - message, err := t.onRamp.ParseCCIPSendRequested(log) - if err != nil { - return [32]byte{}, err - } - encodedTokens, err := abihelpers.ABIEncode( - `[ -{"components": [{"name":"token","type":"address"},{"name":"amount","type":"uint256"}], "type":"tuple[]"}]`, message.Message.TokenAmounts) - if err != nil { - return [32]byte{}, err - } - - packedValues, err := abihelpers.ABIEncode( - `[ -{"name": "leafDomainSeparator","type":"bytes1"}, -{"name": "metadataHash", "type":"bytes32"}, -{"name": "sequenceNumber", "type":"uint64"}, -{"name": "nonce", "type":"uint64"}, -{"name": "sender", "type":"address"}, -{"name": "receiver", "type":"address"}, -{"name": "dataHash", "type":"bytes32"}, -{"name": "tokenAmountsHash", "type":"bytes32"}, -{"name": "gasLimit", "type":"uint256"}, -{"name": "strict", "type":"bool"}, -{"name": "feeToken","type": "address"}, -{"name": "feeTokenAmount","type": "uint256"} -]`, - LeafDomainSeparator, - t.metaDataHash, - message.Message.SequenceNumber, - message.Message.Nonce, - message.Message.Sender, - message.Message.Receiver, - t.ctx.Hash(message.Message.Data), - t.ctx.Hash(encodedTokens), - message.Message.GasLimit, - message.Message.Strict, - message.Message.FeeToken, - message.Message.FeeTokenAmount, - ) - if err != nil { - return [32]byte{}, err - } - return t.ctx.Hash(packedValues), nil -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher_test.go deleted file mode 100644 index b1219a27dfa..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/hasher_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package v1_0_0 - -import ( - "encoding/hex" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/hashutil" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" -) - -func TestHasherV1_0_0(t *testing.T) { - sourceChainSelector, destChainSelector := uint64(1), uint64(4) - onRampAddress := common.HexToAddress("0x5550000000000000000000000000000000000001") - onRampABI := abihelpers.MustParseABI(evm_2_evm_onramp_1_0_0.EVM2EVMOnRampABI) - - ramp, err := evm_2_evm_onramp_1_0_0.NewEVM2EVMOnRamp(onRampAddress, nil) - require.NoError(t, err) - hashingCtx := hashutil.NewKeccak() - hasher := NewLeafHasher(sourceChainSelector, destChainSelector, onRampAddress, hashingCtx, ramp) - - message := evm_2_evm_onramp_1_0_0.InternalEVM2EVMMessage{ - SourceChainSelector: sourceChainSelector, - Sender: common.HexToAddress("0x1110000000000000000000000000000000000001"), - Receiver: common.HexToAddress("0x2220000000000000000000000000000000000001"), - SequenceNumber: 1337, - GasLimit: big.NewInt(100), - Strict: false, - Nonce: 1337, - FeeToken: common.Address{}, - FeeTokenAmount: big.NewInt(1), - Data: []byte{}, - TokenAmounts: []evm_2_evm_onramp_1_0_0.ClientEVMTokenAmount{{Token: common.HexToAddress("0x4440000000000000000000000000000000000001"), Amount: big.NewInt(12345678900)}}, - MessageId: [32]byte{}, - } - - data, err := onRampABI.Events[CCIPSendRequestedEventName].Inputs.Pack(message) - require.NoError(t, err) - hash, err := hasher.HashLeaf(types.Log{Topics: []common.Hash{abihelpers.MustGetEventID("CCIPSendRequested", onRampABI)}, Data: data}) - require.NoError(t, err) - - // NOTE: Must match spec - require.Equal(t, "26f282c6ac8231933b1799648d01ff6cec792a33fb37408b4d135968f9168ace", hex.EncodeToString(hash[:])) - - message = evm_2_evm_onramp_1_0_0.InternalEVM2EVMMessage{ - SourceChainSelector: sourceChainSelector, - Sender: common.HexToAddress("0x1110000000000000000000000000000000000001"), - Receiver: common.HexToAddress("0x2220000000000000000000000000000000000001"), - SequenceNumber: 1337, - GasLimit: big.NewInt(100), - Strict: false, - Nonce: 1337, - FeeToken: common.Address{}, - FeeTokenAmount: big.NewInt(1e12), - Data: []byte("foo bar baz"), - TokenAmounts: []evm_2_evm_onramp_1_0_0.ClientEVMTokenAmount{ - {Token: common.HexToAddress("0x4440000000000000000000000000000000000001"), Amount: big.NewInt(12345678900)}, - {Token: common.HexToAddress("0x6660000000000000000000000000000000000001"), Amount: big.NewInt(4204242)}, - }, - MessageId: [32]byte{}, - } - - data, err = onRampABI.Events[CCIPSendRequestedEventName].Inputs.Pack(message) - require.NoError(t, err) - hash, err = hasher.HashLeaf(types.Log{Topics: []common.Hash{abihelpers.MustGetEventID("CCIPSendRequested", onRampABI)}, Data: data}) - require.NoError(t, err) - - // NOTE: Must match spec - require.Equal(t, "05cee92e7cb86a37b6536554828a5b21ff20ac3d4ef821ec47056f1d963313de", hex.EncodeToString(hash[:])) -} - -func TestMetaDataHash(t *testing.T) { - sourceChainSelector, destChainSelector := uint64(1), uint64(4) - onRampAddress := common.HexToAddress("0x5550000000000000000000000000000000000001") - ctx := hashutil.NewKeccak() - hash := GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampAddress, destChainSelector) - require.Equal(t, "1409948abde219f43870c3d6d1c16beabd8878eb5039a3fa765eb56e4b8ded9e", hex.EncodeToString(hash[:])) -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go deleted file mode 100644 index 137cbaf451d..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go +++ /dev/null @@ -1,689 +0,0 @@ -package v1_0_0 - -import ( - "context" - "fmt" - "math/big" - "sync" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" - - mapset "github.com/deckarep/golang-set/v2" - "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/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/logpollerutil" - - "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" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "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/cache" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" -) - -const ( - EXEC_EXECUTION_STATE_CHANGES = "Exec execution state changes" - EXEC_TOKEN_POOL_ADDED = "Token pool added" - EXEC_TOKEN_POOL_REMOVED = "Token pool removed" -) - -var ( - abiOffRamp = abihelpers.MustParseABI(evm_2_evm_offramp_1_0_0.EVM2EVMOffRampABI) - _ ccipdata.OffRampReader = &OffRamp{} - ExecutionStateChangedEvent = abihelpers.MustGetEventID("ExecutionStateChanged", abiOffRamp) - PoolAddedEvent = abihelpers.MustGetEventID("PoolAdded", abiOffRamp) - PoolRemovedEvent = abihelpers.MustGetEventID("PoolRemoved", abiOffRamp) - ExecutionStateChangedSeqNrIndex = 1 -) - -var offRamp_poolAddedPoolRemovedEvents = []common.Hash{PoolAddedEvent, PoolRemovedEvent} - -type ExecOnchainConfig evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig - -func (d ExecOnchainConfig) AbiString() string { - return ` - [ - { - "components": [ - {"name": "permissionLessExecutionThresholdSeconds", "type": "uint32"}, - {"name": "router", "type": "address"}, - {"name": "priceRegistry", "type": "address"}, - {"name": "maxTokensLength", "type": "uint16"}, - {"name": "maxDataSize", "type": "uint32"} - ], - "type": "tuple" - } - ]` -} - -func (d ExecOnchainConfig) Validate() error { - if d.PermissionLessExecutionThresholdSeconds == 0 { - return errors.New("must set PermissionLessExecutionThresholdSeconds") - } - if d.Router == (common.Address{}) { - return errors.New("must set Router address") - } - if d.PriceRegistry == (common.Address{}) { - return errors.New("must set PriceRegistry address") - } - if d.MaxTokensLength == 0 { - return errors.New("must set MaxTokensLength") - } - if d.MaxDataSize == 0 { - return errors.New("must set MaxDataSize") - } - return nil -} - -// ExecOffchainConfig is the configuration for nodes executing committed CCIP messages (v1.0–v1.2). -// It comes from the OffchainConfig field of the corresponding OCR2 plugin configuration. -// NOTE: do not change the JSON format of this struct without consulting with the RDD people first. -type ExecOffchainConfig struct { - // SourceFinalityDepth indicates how many confirmations a transaction should get on the source chain event before we consider it finalized. - SourceFinalityDepth uint32 - // See [ccipdata.ExecOffchainConfig.DestOptimisticConfirmations] - DestOptimisticConfirmations uint32 - // DestFinalityDepth indicates how many confirmations a transaction should get on the destination chain event before we consider it finalized. - DestFinalityDepth uint32 - // See [ccipdata.ExecOffchainConfig.BatchGasLimit] - BatchGasLimit uint32 - // See [ccipdata.ExecOffchainConfig.RelativeBoostPerWaitHour] - RelativeBoostPerWaitHour float64 - // See [ccipdata.ExecOffchainConfig.InflightCacheExpiry] - InflightCacheExpiry config.Duration - // See [ccipdata.ExecOffchainConfig.RootSnoozeTime] - RootSnoozeTime config.Duration - // See [ccipdata.ExecOffchainConfig.BatchingStrategyID] - BatchingStrategyID uint32 - // See [ccipdata.ExecOffchainConfig.MessageVisibilityInterval] - MessageVisibilityInterval config.Duration -} - -func (c ExecOffchainConfig) Validate() error { - if c.SourceFinalityDepth == 0 { - return errors.New("must set SourceFinalityDepth") - } - if c.DestFinalityDepth == 0 { - return errors.New("must set DestFinalityDepth") - } - if c.DestOptimisticConfirmations == 0 { - return errors.New("must set DestOptimisticConfirmations") - } - if c.BatchGasLimit == 0 { - return errors.New("must set BatchGasLimit") - } - if c.RelativeBoostPerWaitHour == 0 { - return errors.New("must set RelativeBoostPerWaitHour") - } - if c.InflightCacheExpiry.Duration() == 0 { - return errors.New("must set InflightCacheExpiry") - } - if c.RootSnoozeTime.Duration() == 0 { - return errors.New("must set RootSnoozeTime") - } - - return nil -} - -type OffRamp struct { - offRampV100 evm_2_evm_offramp_1_0_0.EVM2EVMOffRampInterface - addr common.Address - lp logpoller.LogPoller - Logger logger.Logger - Client client.Client - evmBatchCaller rpclib.EvmBatchCaller - filters []logpoller.Filter - Estimator gas.EvmFeeEstimator - DestMaxGasPrice *big.Int - ExecutionReportArgs abi.Arguments - eventIndex int - eventSig common.Hash - cachedOffRampTokens cache.AutoSync[cciptypes.OffRampTokens] - sourceToDestTokensCache sync.Map - - // Dynamic config - // configMu guards all the dynamic config fields. - configMu sync.RWMutex - gasPriceEstimator prices.GasPriceEstimatorExec - offchainConfig cciptypes.ExecOffchainConfig - onchainConfig cciptypes.ExecOnchainConfig -} - -func (o *OffRamp) GetStaticConfig(ctx context.Context) (cciptypes.OffRampStaticConfig, error) { - if o.offRampV100 == nil { - return cciptypes.OffRampStaticConfig{}, fmt.Errorf("offramp not initialized") - } - c, err := o.offRampV100.GetStaticConfig(&bind.CallOpts{Context: ctx}) - if err != nil { - return cciptypes.OffRampStaticConfig{}, fmt.Errorf("error while retrieving offramp config: %w", err) - } - return cciptypes.OffRampStaticConfig{ - CommitStore: cciptypes.Address(c.CommitStore.String()), - ChainSelector: c.ChainSelector, - SourceChainSelector: c.SourceChainSelector, - OnRamp: cciptypes.Address(c.OnRamp.String()), - PrevOffRamp: cciptypes.Address(c.PrevOffRamp.String()), - ArmProxy: cciptypes.Address(c.ArmProxy.String()), - }, nil -} - -func (o *OffRamp) GetExecutionState(ctx context.Context, sequenceNumber uint64) (uint8, error) { - return o.offRampV100.GetExecutionState(&bind.CallOpts{Context: ctx}, sequenceNumber) -} - -func (o *OffRamp) GetSenderNonce(ctx context.Context, sender cciptypes.Address) (uint64, error) { - evmAddr, err := ccipcalc.GenericAddrToEvm(sender) - if err != nil { - return 0, err - } - return o.offRampV100.GetSenderNonce(&bind.CallOpts{Context: ctx}, evmAddr) -} - -func (o *OffRamp) ListSenderNonces(ctx context.Context, senders []cciptypes.Address) (map[cciptypes.Address]uint64, error) { - if len(senders) == 0 { - return make(map[cciptypes.Address]uint64), nil - } - - evmSenders, err := ccipcalc.GenericAddrsToEvm(senders...) - if err != nil { - return nil, errors.Wrap(err, "failed to convert generic addresses to evm addresses") - } - - evmCalls := make([]rpclib.EvmCall, 0, len(evmSenders)) - for _, evmAddr := range evmSenders { - evmCalls = append(evmCalls, rpclib.NewEvmCall( - abiOffRamp, - "getSenderNonce", - o.addr, - evmAddr, - )) - } - - results, err := o.evmBatchCaller.BatchCall(ctx, 0, evmCalls) - if err != nil { - o.Logger.Errorw("error while batch fetching sender nonces", "err", err, "senders", evmSenders) - return nil, err - } - - nonces, err := rpclib.ParseOutputs[uint64](results, func(d rpclib.DataAndErr) (uint64, error) { - return rpclib.ParseOutput[uint64](d, 0) - }) - if err != nil { - o.Logger.Errorw("error while parsing sender nonces", "err", err, "senders", evmSenders) - return nil, err - } - - if len(senders) != len(nonces) { - o.Logger.Errorw("unexpected number of nonces returned", "senders", evmSenders, "nonces", nonces) - return nil, errors.New("unexpected number of nonces returned") - } - - senderNonce := make(map[cciptypes.Address]uint64, len(senders)) - for i, sender := range senders { - senderNonce[sender] = nonces[i] - } - return senderNonce, nil -} - -func (o *OffRamp) CurrentRateLimiterState(ctx context.Context) (cciptypes.TokenBucketRateLimit, error) { - state, err := o.offRampV100.CurrentRateLimiterState(&bind.CallOpts{Context: ctx}) - if err != nil { - return cciptypes.TokenBucketRateLimit{}, err - } - return cciptypes.TokenBucketRateLimit{ - Tokens: state.Tokens, - LastUpdated: state.LastUpdated, - IsEnabled: state.IsEnabled, - Capacity: state.Capacity, - Rate: state.Rate, - }, nil -} - -func (o *OffRamp) getDestinationTokensFromSourceTokens(ctx context.Context, tokenAddresses []cciptypes.Address) ([]cciptypes.Address, error) { - destTokens := make([]cciptypes.Address, len(tokenAddresses)) - found := make(map[cciptypes.Address]bool) - - for i, tokenAddress := range tokenAddresses { - if v, exists := o.sourceToDestTokensCache.Load(tokenAddress); exists { - if destToken, isAddr := v.(cciptypes.Address); isAddr { - destTokens[i] = destToken - found[tokenAddress] = true - } else { - o.Logger.Errorf("source to dest cache contains invalid type %T", v) - } - } - } - - if len(found) == len(tokenAddresses) { - return destTokens, nil - } - - evmAddrs, err := ccipcalc.GenericAddrsToEvm(tokenAddresses...) - if err != nil { - return nil, err - } - - evmCalls := make([]rpclib.EvmCall, 0, len(tokenAddresses)) - for i, sourceTk := range tokenAddresses { - if !found[sourceTk] { - evmCalls = append(evmCalls, rpclib.NewEvmCall(abiOffRamp, "getDestinationToken", o.addr, evmAddrs[i])) - } - } - - results, err := o.evmBatchCaller.BatchCall(ctx, 0, evmCalls) - if err != nil { - return nil, fmt.Errorf("batch call limit: %w", err) - } - - destTokensFromRpc, err := rpclib.ParseOutputs[common.Address](results, func(d rpclib.DataAndErr) (common.Address, error) { - return rpclib.ParseOutput[common.Address](d, 0) - }) - if err != nil { - return nil, fmt.Errorf("parse outputs: %w", err) - } - - j := 0 - for i, sourceToken := range tokenAddresses { - if !found[sourceToken] { - destTokens[i] = cciptypes.Address(destTokensFromRpc[j].String()) - o.sourceToDestTokensCache.Store(sourceToken, destTokens[i]) - j++ - } - } - - seenDestTokens := mapset.NewSet[cciptypes.Address]() - for _, destToken := range destTokens { - if seenDestTokens.Contains(destToken) { - return nil, fmt.Errorf("offRamp misconfig, destination token %s already exists", destToken) - } - seenDestTokens.Add(destToken) - } - - return destTokens, nil -} - -func (o *OffRamp) GetSourceToDestTokensMapping(ctx context.Context) (map[cciptypes.Address]cciptypes.Address, error) { - tokens, err := o.GetTokens(ctx) - if err != nil { - return nil, err - } - - destTokens, err := o.getDestinationTokensFromSourceTokens(ctx, tokens.SourceTokens) - if err != nil { - return nil, fmt.Errorf("get destination tokens from source tokens: %w", err) - } - - srcToDstTokenMapping := make(map[cciptypes.Address]cciptypes.Address, len(tokens.SourceTokens)) - for i, sourceToken := range tokens.SourceTokens { - srcToDstTokenMapping[sourceToken] = destTokens[i] - } - return srcToDstTokenMapping, nil -} - -func (o *OffRamp) GetTokens(ctx context.Context) (cciptypes.OffRampTokens, error) { - return o.cachedOffRampTokens.Get(ctx, func(ctx context.Context) (cciptypes.OffRampTokens, error) { - destTokens, err := o.offRampV100.GetDestinationTokens(&bind.CallOpts{Context: ctx}) - if err != nil { - return cciptypes.OffRampTokens{}, fmt.Errorf("get destination tokens: %w", err) - } - sourceTokens, err := o.offRampV100.GetSupportedTokens(&bind.CallOpts{Context: ctx}) - if err != nil { - return cciptypes.OffRampTokens{}, err - } - - return cciptypes.OffRampTokens{ - DestinationTokens: ccipcalc.EvmAddrsToGeneric(destTokens...), - SourceTokens: ccipcalc.EvmAddrsToGeneric(sourceTokens...), - }, nil - }) -} - -func (o *OffRamp) GetRouter(ctx context.Context) (cciptypes.Address, error) { - dynamicConfig, err := o.offRampV100.GetDynamicConfig(&bind.CallOpts{Context: ctx}) - if err != nil { - return "", err - } - return ccipcalc.EvmAddrToGeneric(dynamicConfig.Router), nil -} - -func (o *OffRamp) OffchainConfig(ctx context.Context) (cciptypes.ExecOffchainConfig, error) { - o.configMu.RLock() - defer o.configMu.RUnlock() - return o.offchainConfig, nil -} - -func (o *OffRamp) OnchainConfig(ctx context.Context) (cciptypes.ExecOnchainConfig, error) { - o.configMu.RLock() - defer o.configMu.RUnlock() - return o.onchainConfig, nil -} - -func (o *OffRamp) GasPriceEstimator(ctx context.Context) (cciptypes.GasPriceEstimatorExec, error) { - o.configMu.RLock() - defer o.configMu.RUnlock() - return o.gasPriceEstimator, nil -} - -func (o *OffRamp) Address(ctx context.Context) (cciptypes.Address, error) { - return cciptypes.Address(o.addr.String()), nil -} - -func (o *OffRamp) UpdateDynamicConfig(onchainConfig cciptypes.ExecOnchainConfig, offchainConfig cciptypes.ExecOffchainConfig, gasPriceEstimator prices.GasPriceEstimatorExec) { - o.configMu.Lock() - o.onchainConfig = onchainConfig - o.offchainConfig = offchainConfig - o.gasPriceEstimator = gasPriceEstimator - o.configMu.Unlock() -} - -func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, offchainConfigBytes []byte) (cciptypes.Address, cciptypes.Address, error) { - onchainConfigParsed, err := abihelpers.DecodeAbiStruct[ExecOnchainConfig](onchainConfigBytes) - if err != nil { - return "", "", err - } - - offchainConfigParsed, err := ccipconfig.DecodeOffchainConfig[ExecOffchainConfig](offchainConfigBytes) - if err != nil { - return "", "", err - } - destRouter, err := router.NewRouter(onchainConfigParsed.Router, o.Client) - if err != nil { - return "", "", err - } - destWrappedNative, err := destRouter.GetWrappedNative(nil) - if err != nil { - return "", "", err - } - - offchainConfig := cciptypes.ExecOffchainConfig{ - DestOptimisticConfirmations: offchainConfigParsed.DestOptimisticConfirmations, - BatchGasLimit: offchainConfigParsed.BatchGasLimit, - RelativeBoostPerWaitHour: offchainConfigParsed.RelativeBoostPerWaitHour, - InflightCacheExpiry: offchainConfigParsed.InflightCacheExpiry, - RootSnoozeTime: offchainConfigParsed.RootSnoozeTime, - MessageVisibilityInterval: offchainConfigParsed.MessageVisibilityInterval, - BatchingStrategyID: offchainConfigParsed.BatchingStrategyID, - } - onchainConfig := cciptypes.ExecOnchainConfig{ - PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), - Router: cciptypes.Address(onchainConfigParsed.Router.String()), - } - gasPriceEstimator := prices.NewExecGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0) - - o.UpdateDynamicConfig(onchainConfig, offchainConfig, gasPriceEstimator) - - o.Logger.Infow("Starting exec plugin", - "offchainConfig", onchainConfigParsed, - "onchainConfig", offchainConfigParsed) - return cciptypes.Address(onchainConfigParsed.PriceRegistry.String()), - cciptypes.Address(destWrappedNative.String()), nil -} - -func (o *OffRamp) Close() error { - return logpollerutil.UnregisterLpFilters(o.lp, o.filters) -} - -func (o *OffRamp) GetExecutionStateChangesBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, confs int) ([]cciptypes.ExecutionStateChangedWithTxMeta, error) { - latestBlock, err := o.lp.LatestBlock(ctx) - if err != nil { - return nil, fmt.Errorf("get lp latest block: %w", err) - } - - logs, err := o.lp.IndexedLogsTopicRange( - ctx, - o.eventSig, - o.addr, - o.eventIndex, - logpoller.EvmWord(seqNumMin), - logpoller.EvmWord(seqNumMax), - evmtypes.Confirmations(confs), - ) - if err != nil { - return nil, err - } - - parsedLogs, err := ccipdata.ParseLogs[cciptypes.ExecutionStateChanged]( - logs, - o.Logger, - func(log types.Log) (*cciptypes.ExecutionStateChanged, error) { - sc, err1 := o.offRampV100.ParseExecutionStateChanged(log) - if err1 != nil { - return nil, err1 - } - - return &cciptypes.ExecutionStateChanged{ - SequenceNumber: sc.SequenceNumber, - }, nil - }, - ) - if err != nil { - return nil, fmt.Errorf("parse logs: %w", err) - } - - res := make([]cciptypes.ExecutionStateChangedWithTxMeta, 0, len(parsedLogs)) - for _, log := range parsedLogs { - res = append(res, cciptypes.ExecutionStateChangedWithTxMeta{ - TxMeta: log.TxMeta.WithFinalityStatus(uint64(latestBlock.FinalizedBlockNumber)), - ExecutionStateChanged: log.Data, - }) - } - return res, nil -} - -func encodeExecutionReport(args abi.Arguments, report cciptypes.ExecReport) ([]byte, error) { - var msgs []evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage - for _, msg := range report.Messages { - var ta []evm_2_evm_offramp_1_0_0.ClientEVMTokenAmount - for _, tokenAndAmount := range msg.TokenAmounts { - evmTokenAddr, err := ccipcalc.GenericAddrToEvm(tokenAndAmount.Token) - if err != nil { - return nil, err - } - - ta = append(ta, evm_2_evm_offramp_1_0_0.ClientEVMTokenAmount{ - Token: evmTokenAddr, - Amount: tokenAndAmount.Amount, - }) - } - - senderEvmAddr, err := ccipcalc.GenericAddrToEvm(msg.Sender) - if err != nil { - return nil, fmt.Errorf("msg sender is not evm addr: %w", err) - } - - receiverEvmAddr, err := ccipcalc.GenericAddrToEvm(msg.Receiver) - if err != nil { - return nil, fmt.Errorf("msg receiver is not evm addr: %w", err) - } - - feeTokenEvmAddr, err := ccipcalc.GenericAddrToEvm(msg.FeeToken) - if err != nil { - return nil, fmt.Errorf("fee token is not evm addr: %w", err) - } - - msgs = append(msgs, evm_2_evm_offramp_1_0_0.InternalEVM2EVMMessage{ - SourceChainSelector: msg.SourceChainSelector, - Sender: senderEvmAddr, - Receiver: receiverEvmAddr, - SequenceNumber: msg.SequenceNumber, - GasLimit: msg.GasLimit, - Strict: msg.Strict, - Nonce: msg.Nonce, - FeeToken: feeTokenEvmAddr, - FeeTokenAmount: msg.FeeTokenAmount, - Data: msg.Data, - TokenAmounts: ta, - MessageId: msg.MessageID, - }) - } - - rep := evm_2_evm_offramp_1_0_0.InternalExecutionReport{ - Messages: msgs, - OffchainTokenData: report.OffchainTokenData, - Proofs: report.Proofs, - ProofFlagBits: report.ProofFlagBits, - } - return args.PackValues([]interface{}{&rep}) -} - -func (o *OffRamp) EncodeExecutionReport(ctx context.Context, report cciptypes.ExecReport) ([]byte, error) { - return encodeExecutionReport(o.ExecutionReportArgs, report) -} - -func DecodeExecReport(ctx context.Context, args abi.Arguments, report []byte) (cciptypes.ExecReport, error) { - unpacked, err := args.Unpack(report) - if err != nil { - return cciptypes.ExecReport{}, err - } - if len(unpacked) == 0 { - return cciptypes.ExecReport{}, errors.New("assumptionViolation: expected at least one element") - } - - erStruct, ok := unpacked[0].(struct { - Messages []struct { - SourceChainSelector uint64 `json:"sourceChainSelector"` - SequenceNumber uint64 `json:"sequenceNumber"` - FeeTokenAmount *big.Int `json:"feeTokenAmount"` - Sender common.Address `json:"sender"` - Nonce uint64 `json:"nonce"` - GasLimit *big.Int `json:"gasLimit"` - Strict bool `json:"strict"` - Receiver common.Address `json:"receiver"` - Data []uint8 `json:"data"` - TokenAmounts []struct { - Token common.Address `json:"token"` - Amount *big.Int `json:"amount"` - } `json:"tokenAmounts"` - FeeToken common.Address `json:"feeToken"` - MessageId [32]uint8 `json:"messageId"` - } `json:"messages"` - OffchainTokenData [][][]uint8 `json:"offchainTokenData"` - Proofs [][32]uint8 `json:"proofs"` - ProofFlagBits *big.Int `json:"proofFlagBits"` - }) - - if !ok { - return cciptypes.ExecReport{}, fmt.Errorf("got %T", unpacked[0]) - } - messages := make([]cciptypes.EVM2EVMMessage, 0, len(erStruct.Messages)) - for _, msg := range erStruct.Messages { - var tokensAndAmounts []cciptypes.TokenAmount - for _, tokenAndAmount := range msg.TokenAmounts { - tokensAndAmounts = append(tokensAndAmounts, cciptypes.TokenAmount{ - Token: cciptypes.Address(tokenAndAmount.Token.String()), - Amount: tokenAndAmount.Amount, - }) - } - messages = append(messages, cciptypes.EVM2EVMMessage{ - SequenceNumber: msg.SequenceNumber, - GasLimit: msg.GasLimit, - Nonce: msg.Nonce, - MessageID: msg.MessageId, - SourceChainSelector: msg.SourceChainSelector, - Sender: cciptypes.Address(msg.Sender.String()), - Receiver: cciptypes.Address(msg.Receiver.String()), - Strict: msg.Strict, - FeeToken: cciptypes.Address(msg.FeeToken.String()), - FeeTokenAmount: msg.FeeTokenAmount, - Data: msg.Data, - TokenAmounts: tokensAndAmounts, - // TODO: Not needed for plugins, but should be recomputed for consistency. - // Requires the offramp knowing about onramp version - Hash: [32]byte{}, - }) - } - - // Unpack will populate with big.Int{false, } for 0 values, - // which is different from the expected big.NewInt(0). Rebuild to the expected value for this case. - return cciptypes.ExecReport{ - Messages: messages, - OffchainTokenData: erStruct.OffchainTokenData, - Proofs: erStruct.Proofs, - ProofFlagBits: new(big.Int).SetBytes(erStruct.ProofFlagBits.Bytes()), - }, nil -} - -func (o *OffRamp) DecodeExecutionReport(ctx context.Context, report []byte) (cciptypes.ExecReport, error) { - return DecodeExecReport(ctx, o.ExecutionReportArgs, report) -} - -func (o *OffRamp) RegisterFilters() error { - return logpollerutil.RegisterLpFilters(o.lp, o.filters) -} - -func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { - offRamp, err := evm_2_evm_offramp_1_0_0.NewEVM2EVMOffRamp(addr, ec) - if err != nil { - return nil, err - } - - executionStateChangedSequenceNumberIndex := 1 - executionReportArgs := abihelpers.MustGetMethodInputs("manuallyExecute", abiOffRamp)[:1] - filters := []logpoller.Filter{ - { - Name: logpoller.FilterName(EXEC_EXECUTION_STATE_CHANGES, addr.String()), - EventSigs: []common.Hash{ExecutionStateChangedEvent}, - Addresses: []common.Address{addr}, - Retention: ccipdata.CommitExecLogsRetention, - }, - { - Name: logpoller.FilterName(EXEC_TOKEN_POOL_ADDED, addr.String()), - EventSigs: []common.Hash{PoolAddedEvent}, - Addresses: []common.Address{addr}, - Retention: ccipdata.CacheEvictionLogsRetention, - }, - { - Name: logpoller.FilterName(EXEC_TOKEN_POOL_REMOVED, addr.String()), - EventSigs: []common.Hash{PoolRemovedEvent}, - Addresses: []common.Address{addr}, - Retention: ccipdata.CacheEvictionLogsRetention, - }, - } - - return &OffRamp{ - offRampV100: offRamp, - Client: ec, - addr: addr, - Logger: lggr, - lp: lp, - filters: filters, - Estimator: estimator, - DestMaxGasPrice: destMaxGasPrice, - ExecutionReportArgs: executionReportArgs, - eventSig: ExecutionStateChangedEvent, - eventIndex: executionStateChangedSequenceNumberIndex, - configMu: sync.RWMutex{}, - evmBatchCaller: rpclib.NewDynamicLimitedBatchCaller( - lggr, - ec, - rpclib.DefaultRpcBatchSizeLimit, - rpclib.DefaultRpcBatchBackOffMultiplier, - rpclib.DefaultMaxParallelRpcCalls, - ), - cachedOffRampTokens: cache.NewLogpollerEventsBased[cciptypes.OffRampTokens]( - lp, - offRamp_poolAddedPoolRemovedEvents, - offRamp.Address(), - ), - // values set on the fly after ChangeConfig is called - gasPriceEstimator: prices.ExecGasPriceEstimator{}, - offchainConfig: cciptypes.ExecOffchainConfig{}, - onchainConfig: cciptypes.ExecOnchainConfig{}, - }, nil -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go deleted file mode 100644 index d834b792ce4..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package v1_0_0_test - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/require" - - 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/v1_0_0" -) - -func TestExecutionReportEncodingV100(t *testing.T) { - // Note could consider some fancier testing here (fuzz/property) - // but I think that would essentially be testing geth's abi library - // as our encode/decode is a thin wrapper around that. - report := cciptypes.ExecReport{ - Messages: []cciptypes.EVM2EVMMessage{}, - OffchainTokenData: [][][]byte{{}}, - Proofs: [][32]byte{testutils.Random32Byte()}, - ProofFlagBits: big.NewInt(133), - } - - offRamp, err := v1_0_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil) - require.NoError(t, err) - - ctx := testutils.Context(t) - encodeExecutionReport, err := offRamp.EncodeExecutionReport(ctx, report) - require.NoError(t, err) - decodeCommitReport, err := offRamp.DecodeExecutionReport(ctx, encodeExecutionReport) - require.NoError(t, err) - require.Equal(t, report.Proofs, decodeCommitReport.Proofs) - require.Equal(t, report, decodeCommitReport) -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go deleted file mode 100644 index f8b1dc4e615..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package v1_0_0 - -import ( - "fmt" - "math/rand" - "slices" - "testing" - - "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" - - "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" - - evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" - "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/gethwrappers/ccip/generated/evm_2_evm_offramp_1_0_0" - mock_contracts "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/mocks/v1_0_0" - "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/cache" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" -) - -func TestOffRampGetDestinationTokensFromSourceTokens(t *testing.T) { - ctx := testutils.Context(t) - const numSrcTokens = 20 - - testCases := []struct { - name string - outputChangeFn func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr - expErr bool - }{ - { - name: "happy path", - outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { return outputs }, - expErr: false, - }, - { - name: "rpc error", - outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { - outputs[2].Err = fmt.Errorf("some error") - return outputs - }, - expErr: true, - }, - { - name: "unexpected outputs length should be fine if the type is correct", - outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { - outputs[0].Outputs = append(outputs[0].Outputs, "unexpected", 123) - return outputs - }, - expErr: false, - }, - { - name: "different compatible type", - outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { - outputs[0].Outputs = []any{outputs[0].Outputs[0].(common.Address)} - return outputs - }, - expErr: false, - }, - { - name: "different incompatible type", - outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { - outputs[0].Outputs = []any{outputs[0].Outputs[0].(common.Address).Bytes()} - return outputs - }, - expErr: true, - }, - } - - lp := mocks.NewLogPoller(t) - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - batchCaller := rpclibmocks.NewEvmBatchCaller(t) - o := &OffRamp{evmBatchCaller: batchCaller, lp: lp} - srcTks, dstTks, outputs := generateTokensAndOutputs(numSrcTokens) - outputs = tc.outputChangeFn(outputs) - batchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything).Return(outputs, nil) - genericAddrs := ccipcalc.EvmAddrsToGeneric(srcTks...) - actualDstTokens, err := o.getDestinationTokensFromSourceTokens(ctx, genericAddrs) - - if tc.expErr { - assert.Error(t, err) - return - } - - assert.NoError(t, err) - assert.Equal(t, ccipcalc.EvmAddrsToGeneric(dstTks...), actualDstTokens) - }) - } -} - -func TestCachedOffRampTokens(t *testing.T) { - // Test data. - srcTks, dstTks, _ := generateTokensAndOutputs(3) - - // Mock contract wrapper. - mockOffRamp := mock_contracts.NewEVM2EVMOffRampInterface(t) - mockOffRamp.On("GetDestinationTokens", mock.Anything).Return(dstTks, nil) - mockOffRamp.On("GetSupportedTokens", mock.Anything).Return(srcTks, nil) - mockOffRamp.On("Address").Return(utils.RandomAddress()) - - lp := mocks.NewLogPoller(t) - lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: rand.Int63()}, nil) - - offRamp := OffRamp{ - offRampV100: mockOffRamp, - lp: lp, - Logger: logger.TestLogger(t), - Client: evmclimocks.NewClient(t), - evmBatchCaller: rpclibmocks.NewEvmBatchCaller(t), - cachedOffRampTokens: cache.NewLogpollerEventsBased[cciptypes.OffRampTokens]( - lp, - offRamp_poolAddedPoolRemovedEvents, - mockOffRamp.Address(), - ), - } - - ctx := testutils.Context(t) - tokens, err := offRamp.GetTokens(ctx) - require.NoError(t, err) - - // Verify data is properly loaded in the cache. - expectedPools := make(map[cciptypes.Address]cciptypes.Address) - for i := range dstTks { - expectedPools[cciptypes.Address(dstTks[i].String())] = cciptypes.Address(dstTks[i].String()) - } - require.Equal(t, cciptypes.OffRampTokens{ - DestinationTokens: ccipcalc.EvmAddrsToGeneric(dstTks...), - SourceTokens: ccipcalc.EvmAddrsToGeneric(srcTks...), - }, tokens) -} - -func generateTokensAndOutputs(nbTokens uint) ([]common.Address, []common.Address, []rpclib.DataAndErr) { - srcTks := make([]common.Address, nbTokens) - dstTks := make([]common.Address, nbTokens) - outputs := make([]rpclib.DataAndErr, nbTokens) - for i := range srcTks { - srcTks[i] = utils.RandomAddress() - dstTks[i] = utils.RandomAddress() - outputs[i] = rpclib.DataAndErr{ - Outputs: []any{dstTks[i]}, Err: nil, - } - } - return srcTks, dstTks, outputs -} - -func Test_LogsAreProperlyMarkedAsFinalized(t *testing.T) { - minSeqNr := uint64(10) - maxSeqNr := uint64(14) - inputLogs := []logpoller.Log{ - CreateExecutionStateChangeEventLog(t, 10, 2, utils.RandomBytes32()), - CreateExecutionStateChangeEventLog(t, 11, 3, utils.RandomBytes32()), - CreateExecutionStateChangeEventLog(t, 12, 5, utils.RandomBytes32()), - CreateExecutionStateChangeEventLog(t, 14, 7, utils.RandomBytes32()), - } - - tests := []struct { - name string - lastFinalizedBlock uint64 - expectedFinalizedSequenceNr []uint64 - }{ - { - "all logs are finalized", - 10, - []uint64{10, 11, 12, 14}, - }, - { - "some logs are finalized", - 5, - []uint64{10, 11, 12}, - }, - { - "no logs are finalized", - 1, - []uint64{}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - offrampAddress := utils.RandomAddress() - - lp := mocks.NewLogPoller(t) - lp.On("LatestBlock", mock.Anything). - Return(logpoller.LogPollerBlock{FinalizedBlockNumber: int64(tt.lastFinalizedBlock)}, nil) - lp.On("IndexedLogsTopicRange", mock.Anything, ExecutionStateChangedEvent, offrampAddress, 1, logpoller.EvmWord(minSeqNr), logpoller.EvmWord(maxSeqNr), evmtypes.Confirmations(0)). - Return(inputLogs, nil) - - offRamp, err := NewOffRamp(logger.TestLogger(t), offrampAddress, evmclimocks.NewClient(t), lp, nil, nil) - require.NoError(t, err) - logs, err := offRamp.GetExecutionStateChangesBetweenSeqNums(testutils.Context(t), minSeqNr, maxSeqNr, 0) - require.NoError(t, err) - assert.Len(t, logs, len(inputLogs)) - - for _, log := range logs { - assert.Equal(t, slices.Contains(tt.expectedFinalizedSequenceNr, log.SequenceNumber), log.IsFinalized()) - } - }) - } -} - -func TestGetRouter(t *testing.T) { - routerAddr := utils.RandomAddress() - - mockOffRamp := mock_contracts.NewEVM2EVMOffRampInterface(t) - mockOffRamp.On("GetDynamicConfig", mock.Anything).Return(evm_2_evm_offramp_1_0_0.EVM2EVMOffRampDynamicConfig{ - Router: routerAddr, - }, nil) - - offRamp := OffRamp{ - offRampV100: mockOffRamp, - } - - ctx := testutils.Context(t) - gotRouterAddr, err := offRamp.GetRouter(ctx) - require.NoError(t, err) - - gotRouterEvmAddr, err := ccipcalc.GenericAddrToEvm(gotRouterAddr) - require.NoError(t, err) - assert.Equal(t, routerAddr, gotRouterEvmAddr) -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go deleted file mode 100644 index 44fb6ca0630..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go +++ /dev/null @@ -1,232 +0,0 @@ -package v1_0_0 - -import ( - "encoding/json" - "testing" - "time" - - "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" - - "github.com/pkg/errors" - "github.com/stretchr/testify/mock" - "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/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" -) - -func TestExecOffchainConfig100_Encoding(t *testing.T) { - tests := []struct { - name string - want ExecOffchainConfig - expectErr bool - }{ - { - name: "encodes and decodes config with all fields set", - want: ExecOffchainConfig{ - SourceFinalityDepth: 3, - DestOptimisticConfirmations: 6, - DestFinalityDepth: 3, - BatchGasLimit: 5_000_000, - RelativeBoostPerWaitHour: 0.07, - InflightCacheExpiry: *config.MustNewDuration(64 * time.Second), - RootSnoozeTime: *config.MustNewDuration(128 * time.Minute), - MessageVisibilityInterval: *config.MustNewDuration(6 * time.Hour), - }, - }, - { - name: "fails decoding when all fields present but with 0 values", - want: ExecOffchainConfig{ - SourceFinalityDepth: 0, - DestFinalityDepth: 0, - DestOptimisticConfirmations: 0, - BatchGasLimit: 0, - RelativeBoostPerWaitHour: 0, - InflightCacheExpiry: *config.MustNewDuration(0), - RootSnoozeTime: *config.MustNewDuration(0), - MessageVisibilityInterval: *config.MustNewDuration(0), - }, - expectErr: true, - }, - { - name: "fails decoding when all fields are missing", - want: ExecOffchainConfig{}, - expectErr: true, - }, - { - name: "fails decoding when some fields are missing", - want: ExecOffchainConfig{ - SourceFinalityDepth: 99999999, - InflightCacheExpiry: *config.MustNewDuration(64 * time.Second), - }, - expectErr: true, - }, - } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - exp := tc.want - encode, err := ccipconfig.EncodeOffchainConfig(&exp) - require.NoError(t, err) - got, err := ccipconfig.DecodeOffchainConfig[ExecOffchainConfig](encode) - - if tc.expectErr { - require.ErrorContains(t, err, "must set") - } else { - require.NoError(t, err) - require.Equal(t, tc.want, got) - } - }) - } -} - -func TestExecOffchainConfig100_AllFieldsRequired(t *testing.T) { - cfg := ExecOffchainConfig{ - SourceFinalityDepth: 3, - DestOptimisticConfirmations: 6, - DestFinalityDepth: 3, - BatchGasLimit: 5_000_000, - RelativeBoostPerWaitHour: 0.07, - InflightCacheExpiry: *config.MustNewDuration(64 * time.Second), - RootSnoozeTime: *config.MustNewDuration(128 * time.Minute), - BatchingStrategyID: 0, - } - encoded, err := ccipconfig.EncodeOffchainConfig(&cfg) - require.NoError(t, err) - - var configAsMap map[string]any - err = json.Unmarshal(encoded, &configAsMap) - require.NoError(t, err) - for keyToDelete := range configAsMap { - if keyToDelete == "MessageVisibilityInterval" { - continue // this field is optional - } - - partialConfig := make(map[string]any) - for k, v := range configAsMap { - if k != keyToDelete { - partialConfig[k] = v - } - } - encodedPartialConfig, err := json.Marshal(partialConfig) - require.NoError(t, err) - _, err = ccipconfig.DecodeOffchainConfig[ExecOffchainConfig](encodedPartialConfig) - if keyToDelete == "BatchingStrategyID" { - require.NoError(t, err) - } else { - require.ErrorContains(t, err, keyToDelete) - } - } -} - -func Test_GetSendersNonce(t *testing.T) { - sender1 := cciptypes.Address(utils.RandomAddress().String()) - sender2 := cciptypes.Address(utils.RandomAddress().String()) - - tests := []struct { - name string - addresses []cciptypes.Address - batchCaller *rpclibmocks.EvmBatchCaller - expectedResult map[cciptypes.Address]uint64 - expectedError bool - }{ - { - name: "return empty map when input is empty", - addresses: []cciptypes.Address{}, - batchCaller: rpclibmocks.NewEvmBatchCaller(t), - expectedResult: map[cciptypes.Address]uint64{}, - }, - { - name: "return error when batch call fails", - addresses: []cciptypes.Address{sender1}, - batchCaller: func() *rpclibmocks.EvmBatchCaller { - mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) - mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). - Return(nil, errors.New("batch call error")) - return mockBatchCaller - }(), - expectedError: true, - }, - { - name: "return error when nonces dont match senders", - addresses: []cciptypes.Address{sender1, sender2}, - batchCaller: func() *rpclibmocks.EvmBatchCaller { - mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) - results := []rpclib.DataAndErr{ - { - Outputs: []any{uint64(1)}, - Err: nil, - }, - } - mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). - Return(results, nil) - return mockBatchCaller - }(), - expectedError: true, - }, - { - name: "return error when single request from batch fails", - addresses: []cciptypes.Address{sender1, sender2}, - batchCaller: func() *rpclibmocks.EvmBatchCaller { - mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) - results := []rpclib.DataAndErr{ - { - Outputs: []any{uint64(1)}, - Err: nil, - }, - { - Outputs: []any{}, - Err: errors.New("request failed"), - }, - } - mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). - Return(results, nil) - return mockBatchCaller - }(), - expectedError: true, - }, - { - name: "return map of nonce per sender", - addresses: []cciptypes.Address{sender1, sender2}, - batchCaller: func() *rpclibmocks.EvmBatchCaller { - mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) - results := []rpclib.DataAndErr{ - { - Outputs: []any{uint64(1)}, - Err: nil, - }, - { - Outputs: []any{uint64(2)}, - Err: nil, - }, - } - mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). - Return(results, nil) - return mockBatchCaller - }(), - expectedResult: map[cciptypes.Address]uint64{ - sender1: uint64(1), - sender2: uint64(2), - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - offramp := OffRamp{evmBatchCaller: test.batchCaller, Logger: logger.TestLogger(t)} - nonce, err := offramp.ListSenderNonces(testutils.Context(t), test.addresses) - - if test.expectedError { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, test.expectedResult, nonce) - } - }) - } -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go deleted file mode 100644 index 29cb357223b..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go +++ /dev/null @@ -1,240 +0,0 @@ -package v1_0_0 - -import ( - "context" - "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-common/pkg/hashutil" - 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/arm_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0" - "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/cache" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/logpollerutil" -) - -const ( - CCIPSendRequestedEventName = "CCIPSendRequested" - ConfigSetEventName = "ConfigSet" -) - -var _ ccipdata.OnRampReader = &OnRamp{} - -type OnRamp struct { - address common.Address - onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp - lp logpoller.LogPoller - lggr logger.Logger - client client.Client - leafHasher ccipdata.LeafHasherInterface[[32]byte] - sendRequestedEventSig common.Hash - sendRequestedSeqNumberWord int - filters []logpoller.Filter - cachedSourcePriceRegistryAddress cache.AutoSync[cciptypes.Address] - // 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_0_0.EVM2EVMOnRampStaticConfig] - cachedRmnContract cache.OnceCtxFunction[*arm_contract.ARMContract] -} - -func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAddress common.Address, sourceLP logpoller.LogPoller, source client.Client) (*OnRamp, error) { - onRamp, err := evm_2_evm_onramp_1_0_0.NewEVM2EVMOnRamp(onRampAddress, source) - if err != nil { - return nil, err - } - onRampABI := abihelpers.MustParseABI(evm_2_evm_onramp_1_0_0.EVM2EVMOnRampABI) - eventSig := abihelpers.MustGetEventID(CCIPSendRequestedEventName, onRampABI) - configSetEventSig := abihelpers.MustGetEventID(ConfigSetEventName, onRampABI) - filters := []logpoller.Filter{ - { - Name: logpoller.FilterName(ccipdata.COMMIT_CCIP_SENDS, onRampAddress), - EventSigs: []common.Hash{eventSig}, - Addresses: []common.Address{onRampAddress}, - Retention: ccipdata.CommitExecLogsRetention, - }, - { - Name: logpoller.FilterName(ccipdata.CONFIG_CHANGED, onRampAddress), - EventSigs: []common.Hash{configSetEventSig}, - Addresses: []common.Address{onRampAddress}, - Retention: ccipdata.CacheEvictionLogsRetention, - }, - } - cachedStaticConfig := cache.OnceCtxFunction[evm_2_evm_onramp_1_0_0.EVM2EVMOnRampStaticConfig](func(ctx context.Context) (evm_2_evm_onramp_1_0_0.EVM2EVMOnRampStaticConfig, error) { - return onRamp.GetStaticConfig(&bind.CallOpts{Context: ctx}) - }) - cachedRmnContract := cache.OnceCtxFunction[*arm_contract.ARMContract](func(ctx context.Context) (*arm_contract.ARMContract, error) { - staticConfig, err := cachedStaticConfig(ctx) - if err != nil { - return nil, err - } - - return arm_contract.NewARMContract(staticConfig.ArmProxy, source) - }) - return &OnRamp{ - lggr: lggr, - address: onRampAddress, - onRamp: onRamp, - client: source, - filters: filters, - lp: sourceLP, - leafHasher: NewLeafHasher(sourceSelector, destSelector, onRampAddress, hashutil.NewKeccak(), onRamp), - // offset || sourceChainID || seqNum || ... - sendRequestedSeqNumberWord: 2, - sendRequestedEventSig: eventSig, - cachedSourcePriceRegistryAddress: cache.NewLogpollerEventsBased[cciptypes.Address]( - sourceLP, - []common.Hash{configSetEventSig}, - onRampAddress, - ), - cachedStaticConfig: cache.CallOnceOnNoError(cachedStaticConfig), - cachedRmnContract: cache.CallOnceOnNoError(cachedRmnContract), - }, nil -} - -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") - } - legacyDynamicConfig, err := o.onRamp.GetDynamicConfig(nil) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, err - } - return cciptypes.OnRampDynamicConfig{ - Router: cciptypes.Address(legacyDynamicConfig.Router.String()), - MaxNumberOfTokensPerMsg: legacyDynamicConfig.MaxTokensLength, - DestGasOverhead: 0, - DestGasPerPayloadByte: 0, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 0, - DestDataAvailabilityMultiplierBps: 0, - PriceRegistry: cciptypes.Address(legacyDynamicConfig.PriceRegistry.String()), - MaxDataBytes: legacyDynamicConfig.MaxDataSize, - MaxPerMsgGasLimit: uint32(legacyDynamicConfig.MaxGasLimit), - }, 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) - 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, - o.sendRequestedEventSig, - o.address, - o.sendRequestedSeqNumberWord, - logpoller.EvmWord(seqNumMin), - logpoller.EvmWord(seqNumMax), - ccipdata.LogsConfirmations(finalized), - ) - if err != nil { - return nil, err - } - - parsedLogs, err := ccipdata.ParseLogs[cciptypes.EVM2EVMMessage](logs, o.lggr, o.logToMessage) - if err != nil { - return nil, err - } - - res := make([]cciptypes.EVM2EVMMessageWithTxMeta, 0, len(parsedLogs)) - for _, log := range parsedLogs { - res = append(res, cciptypes.EVM2EVMMessageWithTxMeta{ - TxMeta: log.TxMeta, - EVM2EVMMessage: log.Data, - }) - } - return res, nil -} - -func (o *OnRamp) RouterAddress(context.Context) (cciptypes.Address, error) { - config, err := o.onRamp.GetDynamicConfig(nil) - if err != nil { - return "", err - } - return cciptypes.Address(config.Router.String()), nil -} - -func (o *OnRamp) IsSourceChainHealthy(context.Context) (bool, error) { - if err := o.lp.Healthy(); err != nil { - return false, nil - } - return true, nil -} - -func (o *OnRamp) IsSourceCursed(ctx context.Context) (bool, error) { - arm, err := o.cachedRmnContract(ctx) - if err != nil { - return false, fmt.Errorf("intializing Arm contract through the ArmProxy: %w", err) - } - - cursed, err := arm.IsCursed0(&bind.CallOpts{Context: ctx}) - if err != nil { - return false, fmt.Errorf("checking if source Arm is cursed: %w", err) - } - return cursed, nil -} - -func (o *OnRamp) GetUSDCMessagePriorToLogIndexInTx(ctx context.Context, logIndex, offsetFromFinal int64, txHash common.Hash) ([]byte, error) { - return nil, errors.New("USDC not supported in < 1.2.0") -} - -func (o *OnRamp) Close() error { - return logpollerutil.UnregisterLpFilters(o.lp, o.filters) -} - -func (o *OnRamp) RegisterFilters() error { - return logpollerutil.RegisterLpFilters(o.lp, o.filters) -} - -func (o *OnRamp) logToMessage(log types.Log) (*cciptypes.EVM2EVMMessage, error) { - msg, err := o.onRamp.ParseCCIPSendRequested(log) - if err != nil { - return nil, err - } - h, err := o.leafHasher.HashLeaf(log) - if err != nil { - return nil, err - } - tokensAndAmounts := make([]cciptypes.TokenAmount, len(msg.Message.TokenAmounts)) - for i, tokenAndAmount := range msg.Message.TokenAmounts { - tokensAndAmounts[i] = cciptypes.TokenAmount{ - Token: cciptypes.Address(tokenAndAmount.Token.String()), - Amount: tokenAndAmount.Amount, - } - } - return &cciptypes.EVM2EVMMessage{ - SequenceNumber: msg.Message.SequenceNumber, - GasLimit: msg.Message.GasLimit, - Nonce: msg.Message.Nonce, - MessageID: msg.Message.MessageId, - SourceChainSelector: msg.Message.SourceChainSelector, - Sender: cciptypes.Address(msg.Message.Sender.String()), - Receiver: cciptypes.Address(msg.Message.Receiver.String()), - Strict: msg.Message.Strict, - FeeToken: cciptypes.Address(msg.Message.FeeToken.String()), - FeeTokenAmount: msg.Message.FeeTokenAmount, - Data: msg.Message.Data, - TokenAmounts: tokensAndAmounts, - SourceTokenData: make([][]byte, len(msg.Message.TokenAmounts)), // Always empty in 1.0 - Hash: h, - }, nil -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/price_registry.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/price_registry.go deleted file mode 100644 index d2104f985b9..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/price_registry.go +++ /dev/null @@ -1,310 +0,0 @@ -package v1_0_0 - -import ( - "context" - "fmt" - "math/big" - "sync" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/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/logpoller" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" - "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/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/logpollerutil" -) - -var ( - abiERC20 = abihelpers.MustParseABI(erc20.ERC20ABI) - _ ccipdata.PriceRegistryReader = &PriceRegistry{} - // Exposed only for backwards compatibility with tests. - UsdPerUnitGasUpdated = abihelpers.MustGetEventID("UsdPerUnitGasUpdated", abihelpers.MustParseABI(price_registry_1_0_0.PriceRegistryABI)) -) - -type PriceRegistry struct { - priceRegistry price_registry_1_0_0.PriceRegistryInterface - address common.Address - lp logpoller.LogPoller - evmBatchCaller rpclib.EvmBatchCaller - lggr logger.Logger - filters []logpoller.Filter - tokenUpdated common.Hash - gasUpdated common.Hash - feeTokenAdded common.Hash - feeTokenRemoved common.Hash - - feeTokensCache cache.AutoSync[[]common.Address] - tokenDecimalsCache sync.Map -} - -func NewPriceRegistry(lggr logger.Logger, priceRegistryAddr common.Address, lp logpoller.LogPoller, ec client.Client, registerFilters bool) (*PriceRegistry, error) { - priceRegistry, err := price_registry_1_0_0.NewPriceRegistry(priceRegistryAddr, ec) - if err != nil { - return nil, err - } - priceRegABI := abihelpers.MustParseABI(price_registry_1_0_0.PriceRegistryABI) - usdPerTokenUpdated := abihelpers.MustGetEventID("UsdPerTokenUpdated", priceRegABI) - feeTokenRemoved := abihelpers.MustGetEventID("FeeTokenRemoved", priceRegABI) - feeTokenAdded := abihelpers.MustGetEventID("FeeTokenAdded", priceRegABI) - var filters = []logpoller.Filter{ - { - Name: logpoller.FilterName(ccipdata.COMMIT_PRICE_UPDATES, priceRegistryAddr.String()), - EventSigs: []common.Hash{UsdPerUnitGasUpdated, usdPerTokenUpdated}, - Addresses: []common.Address{priceRegistryAddr}, - Retention: ccipdata.PriceUpdatesLogsRetention, - }, - { - Name: logpoller.FilterName(ccipdata.FEE_TOKEN_ADDED, priceRegistryAddr.String()), - EventSigs: []common.Hash{feeTokenAdded}, - Addresses: []common.Address{priceRegistryAddr}, - Retention: ccipdata.CacheEvictionLogsRetention, - }, - { - Name: logpoller.FilterName(ccipdata.FEE_TOKEN_REMOVED, priceRegistryAddr.String()), - EventSigs: []common.Hash{feeTokenRemoved}, - Addresses: []common.Address{priceRegistryAddr}, - Retention: ccipdata.CacheEvictionLogsRetention, - }} - if registerFilters { - err = logpollerutil.RegisterLpFilters(lp, filters) - if err != nil { - return nil, err - } - } - return &PriceRegistry{ - priceRegistry: priceRegistry, - address: priceRegistryAddr, - lp: lp, - evmBatchCaller: rpclib.NewDynamicLimitedBatchCaller( - lggr, - ec, - rpclib.DefaultRpcBatchSizeLimit, - rpclib.DefaultRpcBatchBackOffMultiplier, - rpclib.DefaultMaxParallelRpcCalls, - ), - lggr: lggr, - gasUpdated: UsdPerUnitGasUpdated, - tokenUpdated: usdPerTokenUpdated, - feeTokenRemoved: feeTokenRemoved, - feeTokenAdded: feeTokenAdded, - filters: filters, - feeTokensCache: cache.NewLogpollerEventsBased[[]common.Address]( - lp, - []common.Hash{feeTokenAdded, feeTokenRemoved}, - priceRegistryAddr, - ), - }, nil -} - -func (p *PriceRegistry) GetTokenPrices(ctx context.Context, wantedTokens []cciptypes.Address) ([]cciptypes.TokenPriceUpdate, error) { - evmAddrs, err := ccipcalc.GenericAddrsToEvm(wantedTokens...) - if err != nil { - return nil, err - } - - tps, err := p.priceRegistry.GetTokenPrices(&bind.CallOpts{Context: ctx}, evmAddrs) - if err != nil { - return nil, err - } - var tpu []cciptypes.TokenPriceUpdate - for i, tp := range tps { - tpu = append(tpu, cciptypes.TokenPriceUpdate{ - TokenPrice: cciptypes.TokenPrice{ - Token: cciptypes.Address(evmAddrs[i].String()), - Value: tp.Value, - }, - TimestampUnixSec: big.NewInt(int64(tp.Timestamp)), - }) - } - return tpu, nil -} - -func (p *PriceRegistry) Address(ctx context.Context) (cciptypes.Address, error) { - return cciptypes.Address(p.address.String()), nil -} - -func (p *PriceRegistry) GetFeeTokens(ctx context.Context) ([]cciptypes.Address, error) { - feeTokens, err := p.feeTokensCache.Get(ctx, func(ctx context.Context) ([]common.Address, error) { - return p.priceRegistry.GetFeeTokens(&bind.CallOpts{Context: ctx}) - }) - if err != nil { - return nil, fmt.Errorf("get fee tokens: %w", err) - } - - return ccipcalc.EvmAddrsToGeneric(feeTokens...), nil -} - -func (p *PriceRegistry) Close() error { - return logpollerutil.UnregisterLpFilters(p.lp, p.filters) -} - -func (p *PriceRegistry) GetTokenPriceUpdatesCreatedAfter(ctx context.Context, ts time.Time, confs int) ([]cciptypes.TokenPriceUpdateWithTxMeta, error) { - logs, err := p.lp.LogsCreatedAfter( - ctx, - p.tokenUpdated, - p.address, - ts, - evmtypes.Confirmations(confs), - ) - if err != nil { - return nil, err - } - - parsedLogs, err := ccipdata.ParseLogs[cciptypes.TokenPriceUpdate]( - logs, - p.lggr, - func(log types.Log) (*cciptypes.TokenPriceUpdate, error) { - tp, err1 := p.priceRegistry.ParseUsdPerTokenUpdated(log) - if err1 != nil { - return nil, err1 - } - return &cciptypes.TokenPriceUpdate{ - TokenPrice: cciptypes.TokenPrice{ - Token: cciptypes.Address(tp.Token.String()), - Value: tp.Value, - }, - TimestampUnixSec: tp.Timestamp, - }, nil - }, - ) - if err != nil { - return nil, err - } - - res := make([]cciptypes.TokenPriceUpdateWithTxMeta, 0, len(parsedLogs)) - for _, log := range parsedLogs { - res = append(res, cciptypes.TokenPriceUpdateWithTxMeta{ - TxMeta: log.TxMeta, - TokenPriceUpdate: log.Data, - }) - } - return res, nil -} - -func (p *PriceRegistry) GetGasPriceUpdatesCreatedAfter(ctx context.Context, chainSelector uint64, ts time.Time, confs int) ([]cciptypes.GasPriceUpdateWithTxMeta, error) { - logs, err := p.lp.IndexedLogsCreatedAfter( - ctx, - p.gasUpdated, - p.address, - 1, - []common.Hash{abihelpers.EvmWord(chainSelector)}, - ts, - evmtypes.Confirmations(confs), - ) - if err != nil { - return nil, err - } - return p.parseGasPriceUpdatesLogs(logs) -} - -func (p *PriceRegistry) GetAllGasPriceUpdatesCreatedAfter(ctx context.Context, ts time.Time, confs int) ([]cciptypes.GasPriceUpdateWithTxMeta, error) { - logs, err := p.lp.LogsCreatedAfter( - ctx, - p.gasUpdated, - p.address, - ts, - evmtypes.Confirmations(confs), - ) - if err != nil { - return nil, err - } - return p.parseGasPriceUpdatesLogs(logs) -} - -func (p *PriceRegistry) parseGasPriceUpdatesLogs(logs []logpoller.Log) ([]cciptypes.GasPriceUpdateWithTxMeta, error) { - parsedLogs, err := ccipdata.ParseLogs[cciptypes.GasPriceUpdate]( - logs, - p.lggr, - func(log types.Log) (*cciptypes.GasPriceUpdate, error) { - p, err1 := p.priceRegistry.ParseUsdPerUnitGasUpdated(log) - if err1 != nil { - return nil, err1 - } - return &cciptypes.GasPriceUpdate{ - GasPrice: cciptypes.GasPrice{ - DestChainSelector: p.DestChain, - Value: p.Value, - }, - TimestampUnixSec: p.Timestamp, - }, nil - }, - ) - if err != nil { - return nil, err - } - - res := make([]cciptypes.GasPriceUpdateWithTxMeta, 0, len(parsedLogs)) - for _, log := range parsedLogs { - res = append(res, cciptypes.GasPriceUpdateWithTxMeta{ - TxMeta: log.TxMeta, - GasPriceUpdate: log.Data, - }) - } - return res, nil -} - -func (p *PriceRegistry) GetTokensDecimals(ctx context.Context, tokenAddresses []cciptypes.Address) ([]uint8, error) { - evmAddrs, err := ccipcalc.GenericAddrsToEvm(tokenAddresses...) - if err != nil { - return nil, err - } - - found := make(map[common.Address]bool) - tokenDecimals := make([]uint8, len(evmAddrs)) - for i, tokenAddress := range evmAddrs { - if v, ok := p.tokenDecimalsCache.Load(tokenAddress); ok { - if decimals, isUint8 := v.(uint8); isUint8 { - tokenDecimals[i] = decimals - found[tokenAddress] = true - } else { - p.lggr.Errorf("token decimals cache contains invalid type %T", v) - } - } - } - if len(found) == len(evmAddrs) { - return tokenDecimals, nil - } - - evmCalls := make([]rpclib.EvmCall, 0, len(evmAddrs)) - for _, tokenAddress := range evmAddrs { - if !found[tokenAddress] { - evmCalls = append(evmCalls, rpclib.NewEvmCall(abiERC20, "decimals", tokenAddress)) - } - } - - results, err := p.evmBatchCaller.BatchCall(ctx, 0, evmCalls) - if err != nil { - return nil, fmt.Errorf("batch call limit: %w", err) - } - - decimals, err := rpclib.ParseOutputs[uint8](results, func(d rpclib.DataAndErr) (uint8, error) { - return rpclib.ParseOutput[uint8](d, 0) - }) - if err != nil { - return nil, fmt.Errorf("parse outputs: %w", err) - } - - j := 0 - for i, tokenAddress := range evmAddrs { - if !found[tokenAddress] { - tokenDecimals[i] = decimals[j] - p.tokenDecimalsCache.Store(tokenAddress, tokenDecimals[i]) - j++ - } - } - return tokenDecimals, nil -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/test_helpers.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/test_helpers.go deleted file mode 100644 index 34f832e17fc..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/test_helpers.go +++ /dev/null @@ -1,90 +0,0 @@ -package v1_0_0 - -import ( - "encoding/binary" - "math/big" - "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" - - 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/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_0_0" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" -) - -// ApplyPriceRegistryUpdate is a helper function used in tests only. -func ApplyPriceRegistryUpdate(t *testing.T, user *bind.TransactOpts, addr common.Address, ec client.Client, gasPrice []cciptypes.GasPrice, tokenPrices []cciptypes.TokenPrice) { - require.True(t, len(gasPrice) <= 2) - pr, err := price_registry_1_0_0.NewPriceRegistry(addr, ec) - require.NoError(t, err) - var tps []price_registry_1_0_0.InternalTokenPriceUpdate - for _, tp := range tokenPrices { - evmAddrs, err1 := ccipcalc.GenericAddrsToEvm(tp.Token) - assert.NoError(t, err1) - tps = append(tps, price_registry_1_0_0.InternalTokenPriceUpdate{ - SourceToken: evmAddrs[0], - UsdPerToken: tp.Value, - }) - } - dest := uint64(0) - gas := big.NewInt(0) - if len(gasPrice) >= 1 { - dest = gasPrice[0].DestChainSelector - gas = gasPrice[0].Value - } - _, err = pr.UpdatePrices(user, price_registry_1_0_0.InternalPriceUpdates{ - TokenPriceUpdates: tps, - DestChainSelector: dest, - UsdPerUnitGas: gas, - }) - require.NoError(t, err) - - for i := 1; i < len(gasPrice); i++ { - dest = gasPrice[i].DestChainSelector - gas = gasPrice[i].Value - _, err = pr.UpdatePrices(user, price_registry_1_0_0.InternalPriceUpdates{ - TokenPriceUpdates: []price_registry_1_0_0.InternalTokenPriceUpdate{}, - DestChainSelector: dest, - UsdPerUnitGas: gas, - }) - require.NoError(t, err) - } -} - -func CreateExecutionStateChangeEventLog(t *testing.T, seqNr uint64, blockNumber int64, messageID common.Hash) logpoller.Log { - tAbi, err := evm_2_evm_offramp.EVM2EVMOffRampMetaData.GetAbi() - require.NoError(t, err) - eseEvent, ok := tAbi.Events["ExecutionStateChanged"] - require.True(t, ok) - - logData, err := eseEvent.Inputs.NonIndexed().Pack(uint8(1), []byte("some return data")) - require.NoError(t, err) - seqNrBytes := make([]byte, 8) - binary.BigEndian.PutUint64(seqNrBytes, seqNr) - seqNrTopic := common.BytesToHash(seqNrBytes) - topic0 := evm_2_evm_offramp.EVM2EVMOffRampExecutionStateChanged{}.Topic() - - return logpoller.Log{ - Topics: [][]byte{ - topic0[:], - seqNrTopic[:], - messageID[:], - }, - Data: logData, - LogIndex: 1, - BlockHash: utils.RandomBytes32(), - BlockNumber: blockNumber, - EventSig: topic0, - Address: testutils.NewAddress(), - TxHash: utils.RandomBytes32(), - } -} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_1_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_1_0/onramp.go deleted file mode 100644 index d4d73219fc0..00000000000 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_1_0/onramp.go +++ /dev/null @@ -1,70 +0,0 @@ -package v1_1_0 - -import ( - "context" - "fmt" - - "github.com/ethereum/go-ethereum/common" - - 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_1_0" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "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_0_0" -) - -var _ ccipdata.OnRampReader = &OnRamp{} - -// OnRamp The only difference that the plugins care about in 1.1 is that the dynamic config struct has changed. -type OnRamp struct { - *v1_0_0.OnRamp - onRamp *evm_2_evm_onramp_1_1_0.EVM2EVMOnRamp -} - -func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAddress common.Address, sourceLP logpoller.LogPoller, source client.Client) (*OnRamp, error) { - onRamp, err := evm_2_evm_onramp_1_1_0.NewEVM2EVMOnRamp(onRampAddress, source) - if err != nil { - return nil, err - } - onRamp100, err := v1_0_0.NewOnRamp(lggr, sourceSelector, destSelector, onRampAddress, sourceLP, source) - if err != nil { - return nil, err - } - return &OnRamp{ - OnRamp: onRamp100, - onRamp: onRamp, - }, nil -} - -func (o *OnRamp) RouterAddress(context.Context) (cciptypes.Address, error) { - config, err := o.onRamp.GetDynamicConfig(nil) - if err != nil { - return "", err - } - return cciptypes.Address(config.Router.String()), nil -} - -func (o *OnRamp) GetDynamicConfig(context.Context) (cciptypes.OnRampDynamicConfig, error) { - if o.onRamp == nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") - } - legacyDynamicConfig, err := o.onRamp.GetDynamicConfig(nil) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, err - } - return cciptypes.OnRampDynamicConfig{ - Router: cciptypes.Address(legacyDynamicConfig.Router.String()), - MaxNumberOfTokensPerMsg: legacyDynamicConfig.MaxTokensLength, - DestGasOverhead: legacyDynamicConfig.DestGasOverhead, - DestGasPerPayloadByte: legacyDynamicConfig.DestGasPerPayloadByte, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 0, - DestDataAvailabilityMultiplierBps: 0, - PriceRegistry: cciptypes.Address(legacyDynamicConfig.PriceRegistry.String()), - MaxDataBytes: legacyDynamicConfig.MaxDataSize, - MaxPerMsgGasLimit: uint32(legacyDynamicConfig.MaxGasLimit), - }, nil -} 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 7612e544195..29076e6cd74 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 @@ -14,6 +14,7 @@ import ( "github.com/pkg/errors" "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-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" @@ -23,16 +24,19 @@ 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/gethwrappers/ccip/generated/commit_store_1_2_0" - "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/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/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/logpollerutil" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" ) +const ( + ExecReportAccepts = "Exec report accepts" + ReportAccepted = "ReportAccepted" +) + var _ ccipdata.CommitStoreReader = &CommitStore{} type CommitStore struct { @@ -349,8 +353,7 @@ func (c *CommitStore) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, return nil, err } - reportsQuery, err := query.Where( - c.address.String(), + reportsQuery, err := logpoller.Where( logpoller.NewAddressFilter(c.address), logpoller.NewEventSigFilter(c.reportAcceptedSig), query.Timestamp(uint64(ts.Unix()), primitives.Gte), @@ -436,11 +439,11 @@ func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, l return nil, err } commitStoreABI := abihelpers.MustParseABI(commit_store_1_2_0.CommitStoreABI) - eventSig := abihelpers.MustGetEventID(v1_0_0.ReportAccepted, commitStoreABI) - commitReportArgs := abihelpers.MustGetEventInputs(v1_0_0.ReportAccepted, commitStoreABI) + eventSig := abihelpers.MustGetEventID(ReportAccepted, commitStoreABI) + commitReportArgs := abihelpers.MustGetEventInputs(ReportAccepted, commitStoreABI) filters := []logpoller.Filter{ { - Name: logpoller.FilterName(v1_0_0.EXEC_REPORT_ACCEPTS, addr.String()), + Name: logpoller.FilterName(ExecReportAccepts, addr.String()), EventSigs: []common.Hash{eventSig}, Addresses: []common.Address{addr}, Retention: ccipdata.CommitExecLogsRetention, 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 8b293096339..e0771f33cb9 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,12 @@ 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" ) @@ -48,7 +47,7 @@ func TestCommitReportEncoding(t *testing.T) { Interval: cciptypes.CommitStoreInterval{Min: 1, Max: 10}, } - c, err := NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t)) + c, err := NewCommitStore(logger.Test(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t)) assert.NoError(t, err) encodedReport, err := c.EncodeCommitReport(ctx, report) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher.go index 4739c946c36..29e6c0c7e80 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher.go @@ -1,30 +1,40 @@ package v1_2_0 import ( + "math/big" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/utils" ) const ( MetaDataHashPrefix = "EVM2EVMMessageHashV2" ) +var LeafDomainSeparator = [1]byte{0x00} + type LeafHasher struct { metaDataHash [32]byte ctx hashutil.Hasher[[32]byte] onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp } +func GetMetaDataHash[H hashutil.Hash](ctx hashutil.Hasher[H], prefix [32]byte, sourceChainSelector uint64, onRampID common.Address, destChainSelector uint64) H { + paddedOnRamp := common.BytesToHash(onRampID[:]) + return ctx.Hash(utils.ConcatBytes(prefix[:], math.U256Bytes(big.NewInt(0).SetUint64(sourceChainSelector)), math.U256Bytes(big.NewInt(0).SetUint64(destChainSelector)), paddedOnRamp[:])) +} + func NewLeafHasher(sourceChainSelector uint64, destChainSelector uint64, onRampId common.Address, ctx hashutil.Hasher[[32]byte], onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp) *LeafHasher { return &LeafHasher{ - metaDataHash: v1_0_0.GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector), + metaDataHash: GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector), ctx: ctx, onRamp: onRamp, } @@ -87,7 +97,7 @@ func (t *LeafHasher) HashLeaf(log types.Log) ([32]byte, error) { {"name": "tokenAmountsHash", "type":"bytes32"}, {"name": "sourceTokenDataHash", "type":"bytes32"} ]`, - v1_0_0.LeafDomainSeparator, + LeafDomainSeparator, t.metaDataHash, fixedSizeValuesHash, t.ctx.Hash(message.Data), diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher_test.go index 4bfbf7295e6..7dac6f9bd74 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/hasher_test.go @@ -76,3 +76,11 @@ func TestHasherV1_2_0(t *testing.T) { // NOTE: Must match spec require.Equal(t, "4362a13a42e52ff5ce4324e7184dc7aa41704c3146bc842d35d95b94b32a78b6", hex.EncodeToString(hash[:])) } + +func TestMetaDataHash(t *testing.T) { + sourceChainSelector, destChainSelector := uint64(1), uint64(4) + onRampAddress := common.HexToAddress("0x5550000000000000000000000000000000000001") + ctx := hashutil.NewKeccak() + hash := GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampAddress, destChainSelector) + require.Equal(t, "bf97bd8e2a1dda6e898eeb79b0c69939f335cc712d784eee3d726cc21121de4c", hex.EncodeToString(hash[:])) +} 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 fa00894b380..f2887688965 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 @@ -4,34 +4,50 @@ import ( "context" "fmt" "math/big" + "sync" "time" + mapset "github.com/deckarep/golang-set/v2" "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/pkg/errors" "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/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "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/ccip/generated/evm_2_evm_offramp_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "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/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/v1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/logpollerutil" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" ) +const ( + ExecExecutionStateChanges = "Exec execution state changes" + ExecTokenPoolAdded = "Token pool added" + ExecTokenPoolRemoved = "Token pool removed" +) + var ( - abiOffRamp = abihelpers.MustParseABI(evm_2_evm_offramp_1_2_0.EVM2EVMOffRampABI) - _ ccipdata.OffRampReader = &OffRamp{} + abiOffRamp = abihelpers.MustParseABI(evm_2_evm_offramp_1_2_0.EVM2EVMOffRampABI) + _ ccipdata.OffRampReader = &OffRamp{} + ExecutionStateChangedEvent = abihelpers.MustGetEventID("ExecutionStateChanged", abiOffRamp) + PoolAddedEvent = abihelpers.MustGetEventID("PoolAdded", abiOffRamp) + PoolRemovedEvent = abihelpers.MustGetEventID("PoolRemoved", abiOffRamp) + ExecutionStateChangedSeqNrIndex = 1 + offrampPoolAddedPoolRemovedEvents = []common.Hash{PoolAddedEvent, PoolRemovedEvent} ) type ExecOnchainConfig evm_2_evm_offramp_1_2_0.EVM2EVMOffRampDynamicConfig @@ -120,10 +136,101 @@ func (c JSONExecOffchainConfig) Validate() error { return nil } -// OffRamp In 1.2 we have a different estimator impl type OffRamp struct { - *v1_0_0.OffRamp offRampV120 evm_2_evm_offramp_1_2_0.EVM2EVMOffRampInterface + + addr common.Address + lp logpoller.LogPoller + Logger logger.Logger + Client client.Client + evmBatchCaller rpclib.EvmBatchCaller + filters []logpoller.Filter + Estimator gas.EvmFeeEstimator + DestMaxGasPrice *big.Int + ExecutionReportArgs abi.Arguments + eventIndex int + eventSig common.Hash + cachedOffRampTokens cache.AutoSync[cciptypes.OffRampTokens] + sourceToDestTokensCache sync.Map + + // Dynamic config + // configMu guards all the dynamic config fields. + configMu sync.RWMutex + gasPriceEstimator prices.GasPriceEstimatorExec + offchainConfig cciptypes.ExecOffchainConfig + onchainConfig cciptypes.ExecOnchainConfig +} + +func (o *OffRamp) GetStaticConfig(ctx context.Context) (cciptypes.OffRampStaticConfig, error) { + if o.offRampV120 == nil { + return cciptypes.OffRampStaticConfig{}, fmt.Errorf("offramp not initialized") + } + c, err := o.offRampV120.GetStaticConfig(&bind.CallOpts{Context: ctx}) + if err != nil { + return cciptypes.OffRampStaticConfig{}, fmt.Errorf("error while retrieving offramp config: %w", err) + } + return cciptypes.OffRampStaticConfig{ + CommitStore: cciptypes.Address(c.CommitStore.String()), + ChainSelector: c.ChainSelector, + SourceChainSelector: c.SourceChainSelector, + OnRamp: cciptypes.Address(c.OnRamp.String()), + PrevOffRamp: cciptypes.Address(c.PrevOffRamp.String()), + ArmProxy: cciptypes.Address(c.ArmProxy.String()), + }, nil +} + +func (o *OffRamp) GetSenderNonce(ctx context.Context, sender cciptypes.Address) (uint64, error) { + evmAddr, err := ccipcalc.GenericAddrToEvm(sender) + if err != nil { + return 0, err + } + return o.offRampV120.GetSenderNonce(&bind.CallOpts{Context: ctx}, evmAddr) +} + +func (o *OffRamp) ListSenderNonces(ctx context.Context, senders []cciptypes.Address) (map[cciptypes.Address]uint64, error) { + if len(senders) == 0 { + return make(map[cciptypes.Address]uint64), nil + } + + evmSenders, err := ccipcalc.GenericAddrsToEvm(senders...) + if err != nil { + return nil, errors.Wrap(err, "failed to convert generic addresses to evm addresses") + } + + evmCalls := make([]rpclib.EvmCall, 0, len(evmSenders)) + for _, evmAddr := range evmSenders { + evmCalls = append(evmCalls, rpclib.NewEvmCall( + abiOffRamp, + "getSenderNonce", + o.addr, + evmAddr, + )) + } + + results, err := o.evmBatchCaller.BatchCall(ctx, 0, evmCalls) + if err != nil { + o.Logger.Errorw("error while batch fetching sender nonces", "err", err, "senders", evmSenders) + return nil, err + } + + nonces, err := rpclib.ParseOutputs[uint64](results, func(d rpclib.DataAndErr) (uint64, error) { + return rpclib.ParseOutput[uint64](d, 0) + }) + if err != nil { + o.Logger.Errorw("error while parsing sender nonces", "err", err, "senders", evmSenders) + return nil, err + } + + if len(senders) != len(nonces) { + o.Logger.Errorw("unexpected number of nonces returned", "senders", evmSenders, "nonces", nonces) + return nil, errors.New("unexpected number of nonces returned") + } + + senderNonce := make(map[cciptypes.Address]uint64, len(senders)) + for i, sender := range senders { + senderNonce[sender] = nonces[i] + } + return senderNonce, nil } func (o *OffRamp) CurrentRateLimiterState(ctx context.Context) (cciptypes.TokenBucketRateLimit, error) { @@ -140,6 +247,105 @@ func (o *OffRamp) CurrentRateLimiterState(ctx context.Context) (cciptypes.TokenB }, nil } +func (o *OffRamp) getDestinationTokensFromSourceTokens(ctx context.Context, tokenAddresses []cciptypes.Address) ([]cciptypes.Address, error) { + destTokens := make([]cciptypes.Address, len(tokenAddresses)) + found := make(map[cciptypes.Address]bool) + + for i, tokenAddress := range tokenAddresses { + if v, exists := o.sourceToDestTokensCache.Load(tokenAddress); exists { + if destToken, isAddr := v.(cciptypes.Address); isAddr { + destTokens[i] = destToken + found[tokenAddress] = true + } else { + o.Logger.Errorf("source to dest cache contains invalid type %T", v) + } + } + } + + if len(found) == len(tokenAddresses) { + return destTokens, nil + } + + evmAddrs, err := ccipcalc.GenericAddrsToEvm(tokenAddresses...) + if err != nil { + return nil, err + } + + evmCalls := make([]rpclib.EvmCall, 0, len(tokenAddresses)) + for i, sourceTk := range tokenAddresses { + if !found[sourceTk] { + evmCalls = append(evmCalls, rpclib.NewEvmCall(abiOffRamp, "getDestinationToken", o.addr, evmAddrs[i])) + } + } + + results, err := o.evmBatchCaller.BatchCall(ctx, 0, evmCalls) + if err != nil { + return nil, fmt.Errorf("batch call limit: %w", err) + } + + destTokensFromRPC, err := rpclib.ParseOutputs[common.Address](results, func(d rpclib.DataAndErr) (common.Address, error) { + return rpclib.ParseOutput[common.Address](d, 0) + }) + if err != nil { + return nil, fmt.Errorf("parse outputs: %w", err) + } + + j := 0 + for i, sourceToken := range tokenAddresses { + if !found[sourceToken] { + destTokens[i] = cciptypes.Address(destTokensFromRPC[j].String()) + o.sourceToDestTokensCache.Store(sourceToken, destTokens[i]) + j++ + } + } + + seenDestTokens := mapset.NewSet[cciptypes.Address]() + for _, destToken := range destTokens { + if seenDestTokens.Contains(destToken) { + return nil, fmt.Errorf("offRamp misconfig, destination token %s already exists", destToken) + } + seenDestTokens.Add(destToken) + } + + return destTokens, nil +} + +func (o *OffRamp) GetSourceToDestTokensMapping(ctx context.Context) (map[cciptypes.Address]cciptypes.Address, error) { + tokens, err := o.GetTokens(ctx) + if err != nil { + return nil, err + } + + destTokens, err := o.getDestinationTokensFromSourceTokens(ctx, tokens.SourceTokens) + if err != nil { + return nil, fmt.Errorf("get destination tokens from source tokens: %w", err) + } + + srcToDstTokenMapping := make(map[cciptypes.Address]cciptypes.Address, len(tokens.SourceTokens)) + for i, sourceToken := range tokens.SourceTokens { + srcToDstTokenMapping[sourceToken] = destTokens[i] + } + return srcToDstTokenMapping, nil +} + +func (o *OffRamp) GetTokens(ctx context.Context) (cciptypes.OffRampTokens, error) { + return o.cachedOffRampTokens.Get(ctx, func(ctx context.Context) (cciptypes.OffRampTokens, error) { + destTokens, err := o.offRampV120.GetDestinationTokens(&bind.CallOpts{Context: ctx}) + if err != nil { + return cciptypes.OffRampTokens{}, fmt.Errorf("get destination tokens: %w", err) + } + sourceTokens, err := o.offRampV120.GetSupportedTokens(&bind.CallOpts{Context: ctx}) + if err != nil { + return cciptypes.OffRampTokens{}, err + } + + return cciptypes.OffRampTokens{ + DestinationTokens: ccipcalc.EvmAddrsToGeneric(destTokens...), + SourceTokens: ccipcalc.EvmAddrsToGeneric(sourceTokens...), + }, nil + }) +} + func (o *OffRamp) GetRouter(ctx context.Context) (cciptypes.Address, error) { dynamicConfig, err := o.offRampV120.GetDynamicConfig(&bind.CallOpts{Context: ctx}) if err != nil { @@ -148,6 +354,36 @@ func (o *OffRamp) GetRouter(ctx context.Context) (cciptypes.Address, error) { return ccipcalc.EvmAddrToGeneric(dynamicConfig.Router), nil } +func (o *OffRamp) OffchainConfig(ctx context.Context) (cciptypes.ExecOffchainConfig, error) { + o.configMu.RLock() + defer o.configMu.RUnlock() + return o.offchainConfig, nil +} + +func (o *OffRamp) OnchainConfig(ctx context.Context) (cciptypes.ExecOnchainConfig, error) { + o.configMu.RLock() + defer o.configMu.RUnlock() + return o.onchainConfig, nil +} + +func (o *OffRamp) GasPriceEstimator(ctx context.Context) (cciptypes.GasPriceEstimatorExec, error) { + o.configMu.RLock() + defer o.configMu.RUnlock() + return o.gasPriceEstimator, nil +} + +func (o *OffRamp) Address(ctx context.Context) (cciptypes.Address, error) { + return cciptypes.Address(o.addr.String()), nil +} + +func (o *OffRamp) UpdateDynamicConfig(onchainConfig cciptypes.ExecOnchainConfig, offchainConfig cciptypes.ExecOffchainConfig, gasPriceEstimator prices.GasPriceEstimatorExec) { + o.configMu.Lock() + o.onchainConfig = onchainConfig + o.offchainConfig = offchainConfig + o.gasPriceEstimator = gasPriceEstimator + o.configMu.Unlock() +} + func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, offchainConfigBytes []byte) (cciptypes.Address, cciptypes.Address, error) { // Same as the v1.0.0 method, except for the ExecOnchainConfig type. onchainConfigParsed, err := abihelpers.DecodeAbiStruct[ExecOnchainConfig](onchainConfigBytes) @@ -191,6 +427,64 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o cciptypes.Address(destWrappedNative.String()), nil } +func (o *OffRamp) Close() error { + return logpollerutil.UnregisterLpFilters(o.lp, o.filters) +} +func (o *OffRamp) RegisterFilters() error { + return logpollerutil.RegisterLpFilters(o.lp, o.filters) +} + +func (o *OffRamp) GetExecutionState(ctx context.Context, sequenceNumber uint64) (uint8, error) { + return o.offRampV120.GetExecutionState(&bind.CallOpts{Context: ctx}, sequenceNumber) +} + +func (o *OffRamp) GetExecutionStateChangesBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, confs int) ([]cciptypes.ExecutionStateChangedWithTxMeta, error) { + latestBlock, err := o.lp.LatestBlock(ctx) + if err != nil { + return nil, fmt.Errorf("get lp latest block: %w", err) + } + + logs, err := o.lp.IndexedLogsTopicRange( + ctx, + o.eventSig, + o.addr, + o.eventIndex, + logpoller.EvmWord(seqNumMin), + logpoller.EvmWord(seqNumMax), + evmtypes.Confirmations(confs), + ) + if err != nil { + return nil, err + } + + parsedLogs, err := ccipdata.ParseLogs[cciptypes.ExecutionStateChanged]( + logs, + o.Logger, + func(log types.Log) (*cciptypes.ExecutionStateChanged, error) { + sc, err1 := o.offRampV120.ParseExecutionStateChanged(log) + if err1 != nil { + return nil, err1 + } + + return &cciptypes.ExecutionStateChanged{ + SequenceNumber: sc.SequenceNumber, + }, nil + }, + ) + if err != nil { + return nil, fmt.Errorf("parse logs: %w", err) + } + + res := make([]cciptypes.ExecutionStateChangedWithTxMeta, 0, len(parsedLogs)) + for _, log := range parsedLogs { + res = append(res, cciptypes.ExecutionStateChangedWithTxMeta{ + TxMeta: log.TxMeta.WithFinalityStatus(uint64(latestBlock.FinalizedBlockNumber)), + ExecutionStateChanged: log.Data, + }) + } + return res, nil +} + func EncodeExecutionReport(ctx context.Context, args abi.Arguments, report cciptypes.ExecReport) ([]byte, error) { var msgs []evm_2_evm_offramp_1_2_0.InternalEVM2EVMMessage for _, msg := range report.Messages { @@ -321,20 +615,62 @@ func (o *OffRamp) DecodeExecutionReport(ctx context.Context, report []byte) (cci } func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { - v100, err := v1_0_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice) - if err != nil { - return nil, err - } - offRamp, err := evm_2_evm_offramp_1_2_0.NewEVM2EVMOffRamp(addr, ec) if err != nil { return nil, err } - v100.ExecutionReportArgs = abihelpers.MustGetMethodInputs("manuallyExecute", abiOffRamp)[:1] + executionStateChangedSequenceNumberIndex := 1 + executionReportArgs := abihelpers.MustGetMethodInputs("manuallyExecute", abiOffRamp)[:1] + filters := []logpoller.Filter{ + { + Name: logpoller.FilterName(ExecExecutionStateChanges, addr.String()), + EventSigs: []common.Hash{ExecutionStateChangedEvent}, + Addresses: []common.Address{addr}, + Retention: ccipdata.CommitExecLogsRetention, + }, + { + Name: logpoller.FilterName(ExecTokenPoolAdded, addr.String()), + EventSigs: []common.Hash{PoolAddedEvent}, + Addresses: []common.Address{addr}, + Retention: ccipdata.CacheEvictionLogsRetention, + }, + { + Name: logpoller.FilterName(ExecTokenPoolRemoved, addr.String()), + EventSigs: []common.Hash{PoolRemovedEvent}, + Addresses: []common.Address{addr}, + Retention: ccipdata.CacheEvictionLogsRetention, + }, + } return &OffRamp{ - OffRamp: v100, - offRampV120: offRamp, + offRampV120: offRamp, + Client: ec, + addr: addr, + Logger: lggr, + lp: lp, + filters: filters, + Estimator: estimator, + DestMaxGasPrice: destMaxGasPrice, + ExecutionReportArgs: executionReportArgs, + eventSig: ExecutionStateChangedEvent, + eventIndex: executionStateChangedSequenceNumberIndex, + configMu: sync.RWMutex{}, + evmBatchCaller: rpclib.NewDynamicLimitedBatchCaller( + lggr, + ec, + rpclib.DefaultRpcBatchSizeLimit, + rpclib.DefaultRpcBatchBackOffMultiplier, + rpclib.DefaultMaxParallelRpcCalls, + ), + cachedOffRampTokens: cache.NewLogpollerEventsBased[cciptypes.OffRampTokens]( + lp, + offrampPoolAddedPoolRemovedEvents, + offRamp.Address(), + ), + // values set on the fly after ChangeConfig is called + gasPriceEstimator: prices.ExecGasPriceEstimator{}, + offchainConfig: cciptypes.ExecOffchainConfig{}, + onchainConfig: cciptypes.ExecOnchainConfig{}, }, 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 f87fc8842f6..630b92f67fc 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,11 +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/v1_2_0" ) @@ -25,7 +26,7 @@ func TestExecutionReportEncodingV120(t *testing.T) { ProofFlagBits: big.NewInt(133), } - offRamp, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil) + offRamp, err := v1_2_0.NewOffRamp(logger.Test(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil) 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 98454ce59b2..15c91235b92 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 @@ -1,19 +1,215 @@ package v1_2_0 import ( + "encoding/binary" + "fmt" + "math/rand" + "slices" "testing" + "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/logger" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + + evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "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/gethwrappers/ccip/generated/evm_2_evm_offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" mock_contracts "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/mocks/v1_2_0" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "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/rpclib" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks" ) +func TestOffRampGetDestinationTokensFromSourceTokens(t *testing.T) { + ctx := testutils.Context(t) + const numSrcTokens = 20 + + testCases := []struct { + name string + outputChangeFn func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr + expErr bool + }{ + { + name: "happy path", + outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { return outputs }, + expErr: false, + }, + { + name: "rpc error", + outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { + outputs[2].Err = fmt.Errorf("some error") + return outputs + }, + expErr: true, + }, + { + name: "unexpected outputs length should be fine if the type is correct", + outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { + outputs[0].Outputs = append(outputs[0].Outputs, "unexpected", 123) + return outputs + }, + expErr: false, + }, + { + name: "different compatible type", + outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { + outputs[0].Outputs = []any{outputs[0].Outputs[0].(common.Address)} + return outputs + }, + expErr: false, + }, + { + name: "different incompatible type", + outputChangeFn: func(outputs []rpclib.DataAndErr) []rpclib.DataAndErr { + outputs[0].Outputs = []any{outputs[0].Outputs[0].(common.Address).Bytes()} + return outputs + }, + expErr: true, + }, + } + + lp := mocks.NewLogPoller(t) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + batchCaller := rpclibmocks.NewEvmBatchCaller(t) + o := &OffRamp{evmBatchCaller: batchCaller, lp: lp} + srcTks, dstTks, outputs := generateTokensAndOutputs(numSrcTokens) + outputs = tc.outputChangeFn(outputs) + batchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything).Return(outputs, nil) + genericAddrs := ccipcalc.EvmAddrsToGeneric(srcTks...) + actualDstTokens, err := o.getDestinationTokensFromSourceTokens(ctx, genericAddrs) + + if tc.expErr { + assert.Error(t, err) + return + } + + assert.NoError(t, err) + assert.Equal(t, ccipcalc.EvmAddrsToGeneric(dstTks...), actualDstTokens) + }) + } +} + +func TestCachedOffRampTokens(t *testing.T) { + // Test data. + srcTks, dstTks, _ := generateTokensAndOutputs(3) + + // Mock contract wrapper. + mockOffRamp := mock_contracts.NewEVM2EVMOffRampInterface(t) + mockOffRamp.On("GetDestinationTokens", mock.Anything).Return(dstTks, nil) + mockOffRamp.On("GetSupportedTokens", mock.Anything).Return(srcTks, nil) + mockOffRamp.On("Address").Return(utils.RandomAddress()) + + lp := mocks.NewLogPoller(t) + lp.On("LatestBlock", mock.Anything).Return(logpoller.LogPollerBlock{BlockNumber: rand.Int63()}, nil) + + offRamp := OffRamp{ + offRampV120: mockOffRamp, + lp: lp, + Logger: logger.Test(t), + Client: evmclimocks.NewClient(t), + evmBatchCaller: rpclibmocks.NewEvmBatchCaller(t), + cachedOffRampTokens: cache.NewLogpollerEventsBased[cciptypes.OffRampTokens]( + lp, + offrampPoolAddedPoolRemovedEvents, + mockOffRamp.Address(), + ), + } + + ctx := testutils.Context(t) + tokens, err := offRamp.GetTokens(ctx) + require.NoError(t, err) + + // Verify data is properly loaded in the cache. + expectedPools := make(map[cciptypes.Address]cciptypes.Address) + for i := range dstTks { + expectedPools[cciptypes.Address(dstTks[i].String())] = cciptypes.Address(dstTks[i].String()) + } + require.Equal(t, cciptypes.OffRampTokens{ + DestinationTokens: ccipcalc.EvmAddrsToGeneric(dstTks...), + SourceTokens: ccipcalc.EvmAddrsToGeneric(srcTks...), + }, tokens) +} + +func generateTokensAndOutputs(nbTokens uint) ([]common.Address, []common.Address, []rpclib.DataAndErr) { + srcTks := make([]common.Address, nbTokens) + dstTks := make([]common.Address, nbTokens) + outputs := make([]rpclib.DataAndErr, nbTokens) + for i := range srcTks { + srcTks[i] = utils.RandomAddress() + dstTks[i] = utils.RandomAddress() + outputs[i] = rpclib.DataAndErr{ + Outputs: []any{dstTks[i]}, Err: nil, + } + } + return srcTks, dstTks, outputs +} + +func Test_LogsAreProperlyMarkedAsFinalized(t *testing.T) { + minSeqNr := uint64(10) + maxSeqNr := uint64(14) + inputLogs := []logpoller.Log{ + CreateExecutionStateChangeEventLog(t, 10, 2, utils.RandomBytes32()), + CreateExecutionStateChangeEventLog(t, 11, 3, utils.RandomBytes32()), + CreateExecutionStateChangeEventLog(t, 12, 5, utils.RandomBytes32()), + CreateExecutionStateChangeEventLog(t, 14, 7, utils.RandomBytes32()), + } + + tests := []struct { + name string + lastFinalizedBlock int64 + expectedFinalizedSequenceNr []uint64 + }{ + { + "all logs are finalized", + 10, + []uint64{10, 11, 12, 14}, + }, + { + "some logs are finalized", + 5, + []uint64{10, 11, 12}, + }, + { + "no logs are finalized", + 1, + []uint64{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + offrampAddress := utils.RandomAddress() + + lp := mocks.NewLogPoller(t) + lp.On("LatestBlock", mock.Anything). + Return(logpoller.LogPollerBlock{FinalizedBlockNumber: tt.lastFinalizedBlock}, nil) + 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) + require.NoError(t, err) + logs, err := offRamp.GetExecutionStateChangesBetweenSeqNums(testutils.Context(t), minSeqNr, maxSeqNr, 0) + require.NoError(t, err) + assert.Len(t, logs, len(inputLogs)) + + for _, log := range logs { + assert.Equal(t, slices.Contains(tt.expectedFinalizedSequenceNr, log.SequenceNumber), log.IsFinalized()) + } + }) + } +} + func TestGetRouter(t *testing.T) { routerAddr := utils.RandomAddress() @@ -34,3 +230,32 @@ func TestGetRouter(t *testing.T) { require.NoError(t, err) assert.Equal(t, routerAddr, gotRouterEvmAddr) } + +func CreateExecutionStateChangeEventLog(t *testing.T, seqNr uint64, blockNumber int64, messageID common.Hash) logpoller.Log { + tAbi, err := evm_2_evm_offramp.EVM2EVMOffRampMetaData.GetAbi() + require.NoError(t, err) + eseEvent, ok := tAbi.Events["ExecutionStateChanged"] + require.True(t, ok) + + logData, err := eseEvent.Inputs.NonIndexed().Pack(uint8(1), []byte("some return data")) + require.NoError(t, err) + seqNrBytes := make([]byte, 8) + binary.BigEndian.PutUint64(seqNrBytes, seqNr) + seqNrTopic := common.BytesToHash(seqNrBytes) + topic0 := evm_2_evm_offramp.EVM2EVMOffRampExecutionStateChanged{}.Topic() + + return logpoller.Log{ + Topics: [][]byte{ + topic0[:], + seqNrTopic[:], + messageID[:], + }, + Data: logData, + LogIndex: 1, + BlockHash: utils.RandomBytes32(), + BlockNumber: blockNumber, + EventSig: topic0, + Address: testutils.NewAddress(), + TxHash: utils.RandomBytes32(), + } +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_test.go index 7d174d5db71..a2216c42cca 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_test.go @@ -1,14 +1,22 @@ package v1_2_0 import ( + "errors" "testing" "time" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/config" - + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "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" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" ) func modifyCopy[T any](c T, f func(c *T)) T { @@ -171,3 +179,110 @@ func TestExecOffchainConfig120_ParseRawJson(t *testing.T) { }) } } + +func Test_GetSendersNonce(t *testing.T) { + sender1 := cciptypes.Address(utils.RandomAddress().String()) + sender2 := cciptypes.Address(utils.RandomAddress().String()) + + tests := []struct { + name string + addresses []cciptypes.Address + batchCaller *rpclibmocks.EvmBatchCaller + expectedResult map[cciptypes.Address]uint64 + expectedError bool + }{ + { + name: "return empty map when input is empty", + addresses: []cciptypes.Address{}, + batchCaller: rpclibmocks.NewEvmBatchCaller(t), + expectedResult: map[cciptypes.Address]uint64{}, + }, + { + name: "return error when batch call fails", + addresses: []cciptypes.Address{sender1}, + batchCaller: func() *rpclibmocks.EvmBatchCaller { + mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) + mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). + Return(nil, errors.New("batch call error")) + return mockBatchCaller + }(), + expectedError: true, + }, + { + name: "return error when nonces dont match senders", + addresses: []cciptypes.Address{sender1, sender2}, + batchCaller: func() *rpclibmocks.EvmBatchCaller { + mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) + results := []rpclib.DataAndErr{ + { + Outputs: []any{uint64(1)}, + Err: nil, + }, + } + mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). + Return(results, nil) + return mockBatchCaller + }(), + expectedError: true, + }, + { + name: "return error when single request from batch fails", + addresses: []cciptypes.Address{sender1, sender2}, + batchCaller: func() *rpclibmocks.EvmBatchCaller { + mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) + results := []rpclib.DataAndErr{ + { + Outputs: []any{uint64(1)}, + Err: nil, + }, + { + Outputs: []any{}, + Err: errors.New("request failed"), + }, + } + mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). + Return(results, nil) + return mockBatchCaller + }(), + expectedError: true, + }, + { + name: "return map of nonce per sender", + addresses: []cciptypes.Address{sender1, sender2}, + batchCaller: func() *rpclibmocks.EvmBatchCaller { + mockBatchCaller := rpclibmocks.NewEvmBatchCaller(t) + results := []rpclib.DataAndErr{ + { + Outputs: []any{uint64(1)}, + Err: nil, + }, + { + Outputs: []any{uint64(2)}, + Err: nil, + }, + } + mockBatchCaller.On("BatchCall", mock.Anything, mock.Anything, mock.Anything). + Return(results, nil) + return mockBatchCaller + }(), + expectedResult: map[cciptypes.Address]uint64{ + sender1: uint64(1), + sender2: uint64(2), + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + offramp := OffRamp{evmBatchCaller: test.batchCaller, Logger: logger.Test(t)} + nonce, err := offramp.ListSenderNonces(testutils.Context(t), test.addresses) + + if test.expectedError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, test.expectedResult, nonce) + } + }) + } +} 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 f727d7fd5fa..071e8a8e03e 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 @@ -11,12 +11,13 @@ import ( "github.com/ethereum/go-ethereum/core/types" "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/arm_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" @@ -62,7 +63,7 @@ type OnRamp struct { // 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] - cachedRmnContract cache.OnceCtxFunction[*arm_contract.ARMContract] + cachedRmnContract cache.OnceCtxFunction[*rmn_contract.RMNContract] } func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAddress common.Address, sourceLP logpoller.LogPoller, source client.Client) (*OnRamp, error) { @@ -89,13 +90,13 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd cachedStaticConfig := cache.OnceCtxFunction[evm_2_evm_onramp_1_2_0.EVM2EVMOnRampStaticConfig](func(ctx context.Context) (evm_2_evm_onramp_1_2_0.EVM2EVMOnRampStaticConfig, error) { return onRamp.GetStaticConfig(&bind.CallOpts{Context: ctx}) }) - cachedRmnContract := cache.OnceCtxFunction[*arm_contract.ARMContract](func(ctx context.Context) (*arm_contract.ARMContract, error) { + cachedRmnContract := cache.OnceCtxFunction[*rmn_contract.RMNContract](func(ctx context.Context) (*rmn_contract.RMNContract, error) { staticConfig, err := cachedStaticConfig(ctx) if err != nil { return nil, err } - return arm_contract.NewARMContract(staticConfig.ArmProxy, source) + return rmn_contract.NewRMNContract(staticConfig.ArmProxy, source) }) return &OnRamp{ lggr: lggr, 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 ec912667ac7..bbdf52e23a4 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,11 +8,12 @@ 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" ) @@ -20,7 +21,7 @@ func TestLogPollerClient_GetSendRequestsBetweenSeqNumsV1_2_0(t *testing.T) { onRampAddr := utils.RandomAddress() seqNum := uint64(100) limit := uint64(10) - lggr := logger.TestLogger(t) + lggr := logger.Test(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 9aac30e6123..4c4058922dc 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 @@ -2,42 +2,110 @@ package v1_2_0 import ( "context" + "fmt" "math/big" + "sync" + "time" "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-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" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "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/v1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/logpollerutil" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" ) var ( - _ ccipdata.PriceRegistryReader = &PriceRegistry{} + _ ccipdata.PriceRegistryReader = &PriceRegistry{} + abiERC20 = abihelpers.MustParseABI(erc20.ERC20ABI) + // Exposed only for backwards compatibility with tests. + UsdPerUnitGasUpdated = abihelpers.MustGetEventID("UsdPerUnitGasUpdated", abihelpers.MustParseABI(price_registry_1_2_0.PriceRegistryABI)) ) type PriceRegistry struct { - *v1_0_0.PriceRegistry - pr *price_registry_1_2_0.PriceRegistry + priceRegistry *price_registry_1_2_0.PriceRegistry + address common.Address + lp logpoller.LogPoller + evmBatchCaller rpclib.EvmBatchCaller + lggr logger.Logger + filters []logpoller.Filter + tokenUpdated common.Hash + gasUpdated common.Hash + feeTokenAdded common.Hash + feeTokenRemoved common.Hash + + feeTokensCache cache.AutoSync[[]common.Address] + tokenDecimalsCache sync.Map } func NewPriceRegistry(lggr logger.Logger, priceRegistryAddr common.Address, lp logpoller.LogPoller, ec client.Client, registerFilters bool) (*PriceRegistry, error) { - v100, err := v1_0_0.NewPriceRegistry(lggr, priceRegistryAddr, lp, ec, registerFilters) - if err != nil { - return nil, err - } priceRegistry, err := price_registry_1_2_0.NewPriceRegistry(priceRegistryAddr, ec) if err != nil { return nil, err } + priceRegABI := abihelpers.MustParseABI(price_registry_1_2_0.PriceRegistryABI) + usdPerTokenUpdated := abihelpers.MustGetEventID("UsdPerTokenUpdated", priceRegABI) + feeTokenRemoved := abihelpers.MustGetEventID("FeeTokenRemoved", priceRegABI) + feeTokenAdded := abihelpers.MustGetEventID("FeeTokenAdded", priceRegABI) + var filters = []logpoller.Filter{ + { + Name: logpoller.FilterName(ccipdata.COMMIT_PRICE_UPDATES, priceRegistryAddr.String()), + EventSigs: []common.Hash{UsdPerUnitGasUpdated, usdPerTokenUpdated}, + Addresses: []common.Address{priceRegistryAddr}, + Retention: ccipdata.PriceUpdatesLogsRetention, + }, + { + Name: logpoller.FilterName(ccipdata.FEE_TOKEN_ADDED, priceRegistryAddr.String()), + EventSigs: []common.Hash{feeTokenAdded}, + Addresses: []common.Address{priceRegistryAddr}, + Retention: ccipdata.CacheEvictionLogsRetention, + }, + { + Name: logpoller.FilterName(ccipdata.FEE_TOKEN_REMOVED, priceRegistryAddr.String()), + EventSigs: []common.Hash{feeTokenRemoved}, + Addresses: []common.Address{priceRegistryAddr}, + Retention: ccipdata.CacheEvictionLogsRetention, + }} + if registerFilters { + err = logpollerutil.RegisterLpFilters(lp, filters) + if err != nil { + return nil, err + } + } return &PriceRegistry{ - PriceRegistry: v100, - pr: priceRegistry, + priceRegistry: priceRegistry, + address: priceRegistryAddr, + lp: lp, + evmBatchCaller: rpclib.NewDynamicLimitedBatchCaller( + lggr, + ec, + rpclib.DefaultRpcBatchSizeLimit, + rpclib.DefaultRpcBatchBackOffMultiplier, + rpclib.DefaultMaxParallelRpcCalls, + ), + lggr: lggr, + gasUpdated: UsdPerUnitGasUpdated, + tokenUpdated: usdPerTokenUpdated, + feeTokenRemoved: feeTokenRemoved, + feeTokenAdded: feeTokenAdded, + filters: filters, + feeTokensCache: cache.NewLogpollerEventsBased[[]common.Address]( + lp, + []common.Hash{feeTokenAdded, feeTokenRemoved}, + priceRegistryAddr, + ), }, nil } @@ -50,7 +118,7 @@ func (p *PriceRegistry) GetTokenPrices(ctx context.Context, wantedTokens []ccipt } // Make call using 224 ABI. - tps, err := p.pr.GetTokenPrices(&bind.CallOpts{Context: ctx}, evmAddrs) + tps, err := p.priceRegistry.GetTokenPrices(&bind.CallOpts{Context: ctx}, evmAddrs) if err != nil { return nil, err } @@ -66,3 +134,179 @@ func (p *PriceRegistry) GetTokenPrices(ctx context.Context, wantedTokens []ccipt } return tpu, nil } + +func (p *PriceRegistry) Address(ctx context.Context) (cciptypes.Address, error) { + return cciptypes.Address(p.address.String()), nil +} + +func (p *PriceRegistry) GetFeeTokens(ctx context.Context) ([]cciptypes.Address, error) { + feeTokens, err := p.feeTokensCache.Get(ctx, func(ctx context.Context) ([]common.Address, error) { + return p.priceRegistry.GetFeeTokens(&bind.CallOpts{Context: ctx}) + }) + if err != nil { + return nil, fmt.Errorf("get fee tokens: %w", err) + } + + return ccipcalc.EvmAddrsToGeneric(feeTokens...), nil +} + +func (p *PriceRegistry) Close() error { + return logpollerutil.UnregisterLpFilters(p.lp, p.filters) +} + +func (p *PriceRegistry) GetTokenPriceUpdatesCreatedAfter(ctx context.Context, ts time.Time, confs int) ([]cciptypes.TokenPriceUpdateWithTxMeta, error) { + logs, err := p.lp.LogsCreatedAfter( + ctx, + p.tokenUpdated, + p.address, + ts, + evmtypes.Confirmations(confs), + ) + if err != nil { + return nil, err + } + + parsedLogs, err := ccipdata.ParseLogs[cciptypes.TokenPriceUpdate]( + logs, + p.lggr, + func(log types.Log) (*cciptypes.TokenPriceUpdate, error) { + tp, err1 := p.priceRegistry.ParseUsdPerTokenUpdated(log) + if err1 != nil { + return nil, err1 + } + return &cciptypes.TokenPriceUpdate{ + TokenPrice: cciptypes.TokenPrice{ + Token: cciptypes.Address(tp.Token.String()), + Value: tp.Value, + }, + TimestampUnixSec: tp.Timestamp, + }, nil + }, + ) + if err != nil { + return nil, err + } + + res := make([]cciptypes.TokenPriceUpdateWithTxMeta, 0, len(parsedLogs)) + for _, log := range parsedLogs { + res = append(res, cciptypes.TokenPriceUpdateWithTxMeta{ + TxMeta: log.TxMeta, + TokenPriceUpdate: log.Data, + }) + } + return res, nil +} + +func (p *PriceRegistry) GetGasPriceUpdatesCreatedAfter(ctx context.Context, chainSelector uint64, ts time.Time, confs int) ([]cciptypes.GasPriceUpdateWithTxMeta, error) { + logs, err := p.lp.IndexedLogsCreatedAfter( + ctx, + p.gasUpdated, + p.address, + 1, + []common.Hash{abihelpers.EvmWord(chainSelector)}, + ts, + evmtypes.Confirmations(confs), + ) + if err != nil { + return nil, err + } + return p.parseGasPriceUpdatesLogs(logs) +} + +func (p *PriceRegistry) GetAllGasPriceUpdatesCreatedAfter(ctx context.Context, ts time.Time, confs int) ([]cciptypes.GasPriceUpdateWithTxMeta, error) { + logs, err := p.lp.LogsCreatedAfter( + ctx, + p.gasUpdated, + p.address, + ts, + evmtypes.Confirmations(confs), + ) + if err != nil { + return nil, err + } + return p.parseGasPriceUpdatesLogs(logs) +} + +func (p *PriceRegistry) parseGasPriceUpdatesLogs(logs []logpoller.Log) ([]cciptypes.GasPriceUpdateWithTxMeta, error) { + parsedLogs, err := ccipdata.ParseLogs[cciptypes.GasPriceUpdate]( + logs, + p.lggr, + func(log types.Log) (*cciptypes.GasPriceUpdate, error) { + p, err1 := p.priceRegistry.ParseUsdPerUnitGasUpdated(log) + if err1 != nil { + return nil, err1 + } + return &cciptypes.GasPriceUpdate{ + GasPrice: cciptypes.GasPrice{ + DestChainSelector: p.DestChain, + Value: p.Value, + }, + TimestampUnixSec: p.Timestamp, + }, nil + }, + ) + if err != nil { + return nil, err + } + + res := make([]cciptypes.GasPriceUpdateWithTxMeta, 0, len(parsedLogs)) + for _, log := range parsedLogs { + res = append(res, cciptypes.GasPriceUpdateWithTxMeta{ + TxMeta: log.TxMeta, + GasPriceUpdate: log.Data, + }) + } + return res, nil +} + +func (p *PriceRegistry) GetTokensDecimals(ctx context.Context, tokenAddresses []cciptypes.Address) ([]uint8, error) { + evmAddrs, err := ccipcalc.GenericAddrsToEvm(tokenAddresses...) + if err != nil { + return nil, err + } + + found := make(map[common.Address]bool) + tokenDecimals := make([]uint8, len(evmAddrs)) + for i, tokenAddress := range evmAddrs { + if v, ok := p.tokenDecimalsCache.Load(tokenAddress); ok { + if decimals, isUint8 := v.(uint8); isUint8 { + tokenDecimals[i] = decimals + found[tokenAddress] = true + } else { + p.lggr.Errorf("token decimals cache contains invalid type %T", v) + } + } + } + if len(found) == len(evmAddrs) { + return tokenDecimals, nil + } + + evmCalls := make([]rpclib.EvmCall, 0, len(evmAddrs)) + for _, tokenAddress := range evmAddrs { + if !found[tokenAddress] { + evmCalls = append(evmCalls, rpclib.NewEvmCall(abiERC20, "decimals", tokenAddress)) + } + } + + results, err := p.evmBatchCaller.BatchCall(ctx, 0, evmCalls) + if err != nil { + return nil, fmt.Errorf("batch call limit: %w", err) + } + + decimals, err := rpclib.ParseOutputs[uint8](results, func(d rpclib.DataAndErr) (uint8, error) { + return rpclib.ParseOutput[uint8](d, 0) + }) + if err != nil { + return nil, fmt.Errorf("parse outputs: %w", err) + } + + j := 0 + for i, tokenAddress := range evmAddrs { + if !found[tokenAddress] { + tokenDecimals[i] = decimals[j] + p.tokenDecimalsCache.Store(tokenAddress, tokenDecimals[i]) + j++ + } + } + return tokenDecimals, nil +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go index e7972d5f5fe..fb991be59da 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go @@ -9,37 +9,37 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" ) // ApplyPriceRegistryUpdate is a helper function used in tests only. func ApplyPriceRegistryUpdate(t *testing.T, user *bind.TransactOpts, addr common.Address, ec client.Client, gasPrices []cciptypes.GasPrice, tokenPrices []cciptypes.TokenPrice) common.Hash { require.True(t, len(gasPrices) <= 2) - pr, err := price_registry.NewPriceRegistry(addr, ec) + pr, err := fee_quoter.NewFeeQuoter(addr, ec) require.NoError(t, err) o, err := pr.Owner(nil) require.NoError(t, err) require.Equal(t, user.From, o) - var tps []price_registry.InternalTokenPriceUpdate + var tps []fee_quoter.InternalTokenPriceUpdate for _, tp := range tokenPrices { evmAddrs, err1 := ccipcalc.GenericAddrsToEvm(tp.Token) assert.NoError(t, err1) - tps = append(tps, price_registry.InternalTokenPriceUpdate{ + tps = append(tps, fee_quoter.InternalTokenPriceUpdate{ SourceToken: evmAddrs[0], UsdPerToken: tp.Value, }) } - var gps []price_registry.InternalGasPriceUpdate + var gps []fee_quoter.InternalGasPriceUpdate for _, gp := range gasPrices { - gps = append(gps, price_registry.InternalGasPriceUpdate{ + gps = append(gps, fee_quoter.InternalGasPriceUpdate{ DestChainSelector: gp.DestChainSelector, UsdPerUnitGas: gp.Value, }) } - tx, err := pr.UpdatePrices(user, price_registry.InternalPriceUpdates{ + tx, err := pr.UpdatePrices(user, fee_quoter.InternalPriceUpdates{ TokenPriceUpdates: tps, GasPriceUpdates: gps, }) 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 3bb582f3a21..fd768d4235c 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 @@ -8,10 +8,10 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "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/gethwrappers/ccip/generated/commit_store" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/hasher.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/hasher.go index a00ec376cdb..e70e3c547ea 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/hasher.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/hasher.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) const ( @@ -24,7 +24,7 @@ type LeafHasher struct { func NewLeafHasher(sourceChainSelector uint64, destChainSelector uint64, onRampId common.Address, ctx hashutil.Hasher[[32]byte], onRamp *evm_2_evm_onramp.EVM2EVMOnRamp) *LeafHasher { return &LeafHasher{ - metaDataHash: v1_0_0.GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector), + metaDataHash: v1_2_0.GetMetaDataHash(ctx, ctx.Hash([]byte(MetaDataHashPrefix)), sourceChainSelector, onRampId, destChainSelector), ctx: ctx, onRamp: onRamp, } @@ -87,7 +87,7 @@ func (t *LeafHasher) HashLeaf(log types.Log) ([32]byte, error) { {"name": "tokenAmountsHash", "type":"bytes32"}, {"name": "sourceTokenDataHash", "type":"bytes32"} ]`, - v1_0_0.LeafDomainSeparator, + v1_2_0.LeafDomainSeparator, t.metaDataHash, fixedSizeValuesHash, t.ctx.Hash(message.Data), 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 cac61c67878..0c45f0d6eac 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 @@ -9,13 +9,13 @@ import ( "github.com/ethereum/go-ethereum/common" "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/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/evm_2_evm_offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "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/cache" @@ -43,9 +43,7 @@ func (d ExecOnchainConfig) AbiString() string { {"name": "maxDataBytes", "type": "uint32"}, {"name": "maxNumberOfTokensPerMsg", "type": "uint16"}, {"name": "router", "type": "address"}, - {"name": "priceRegistry", "type": "address"}, - {"name": "maxPoolReleaseOrMintGas", "type": "uint32"}, - {"name": "maxTokenTransferGas", "type": "uint32"} + {"name": "priceRegistry", "type": "address"} ], "type": "tuple" } @@ -65,12 +63,6 @@ func (d ExecOnchainConfig) Validate() error { if d.MaxNumberOfTokensPerMsg == 0 { return errors.New("must set MaxNumberOfTokensPerMsg") } - if d.MaxPoolReleaseOrMintGas == 0 { - return errors.New("must set MaxPoolReleaseOrMintGas") - } - if d.MaxTokenTransferGas == 0 { - return errors.New("must set MaxTokenTransferGas") - } return nil } 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 481933f89ad..ad540ffd648 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 @@ -11,13 +11,13 @@ import ( "github.com/ethereum/go-ethereum/core/types" "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/arm_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" @@ -64,7 +64,7 @@ type OnRamp struct { // 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] - cachedRmnContract cache.OnceCtxFunction[*arm_contract.ARMContract] + cachedRmnContract cache.OnceCtxFunction[*rmn_contract.RMNContract] } func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAddress common.Address, sourceLP logpoller.LogPoller, source client.Client) (*OnRamp, error) { @@ -92,13 +92,13 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd cachedStaticConfig := cache.OnceCtxFunction[evm_2_evm_onramp.EVM2EVMOnRampStaticConfig](func(ctx context.Context) (evm_2_evm_onramp.EVM2EVMOnRampStaticConfig, error) { return onRamp.GetStaticConfig(&bind.CallOpts{Context: ctx}) }) - cachedRmnContract := cache.OnceCtxFunction[*arm_contract.ARMContract](func(ctx context.Context) (*arm_contract.ARMContract, error) { + cachedRmnContract := cache.OnceCtxFunction[*rmn_contract.RMNContract](func(ctx context.Context) (*rmn_contract.RMNContract, error) { staticConfig, err := cachedStaticConfig(ctx) if err != nil { return nil, err } - return arm_contract.NewARMContract(staticConfig.RmnProxy, source) + return rmn_contract.NewRMNContract(staticConfig.RmnProxy, source) }) return &OnRamp{ 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 3ca360c8ff2..277b8fd9003 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,15 +11,15 @@ 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" 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/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_arm_contract" + "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.TestLogger(t) + lggr := logger.Test(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.TestLogger(t), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(t), bc) + onRamp, err := NewOnRamp(logger.Test(t), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(t), bc) require.NoError(t, err) onRamp.cachedStaticConfig = func(ctx context.Context) (evm_2_evm_onramp.EVM2EVMOnRampStaticConfig, error) { @@ -105,7 +105,7 @@ func Test_ProperlyRecognizesPerLaneCurses(t *testing.T) { assert.True(t, isCursed) // Uncursing the chain selector - _, err = mockRMN.OwnerUnvoteToCurse(user, []mock_arm_contract.RMNUnvoteToCurseRecord{}, ccipcommon.SelectorToBytes(destChainSelector)) + _, err = mockRMN.OwnerUnvoteToCurse(user, []mock_rmn_contract.RMNUnvoteToCurseRecord{}, ccipcommon.SelectorToBytes(destChainSelector)) require.NoError(t, err) bc.Commit() @@ -121,7 +121,7 @@ func BenchmarkIsSourceCursedWithCache(b *testing.B) { destChainSelector := uint64(100) onRampAddress, _, _ := setupOnRampV1_5_0(b, user, bc) - onRamp, err := NewOnRamp(logger.TestLogger(b), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(b), bc) + onRamp, err := NewOnRamp(logger.Test(b), 1, destChainSelector, onRampAddress, mocks.NewLogPoller(b), bc) require.NoError(b, err) for i := 0; i < b.N; i++ { @@ -129,8 +129,8 @@ func BenchmarkIsSourceCursedWithCache(b *testing.B) { } } -func setupOnRampV1_5_0(t testing.TB, user *bind.TransactOpts, bc *client.SimulatedBackendClient) (common.Address, *mock_arm_contract.MockARMContract, common.Address) { - rmnAddress, transaction, rmnContract, err := mock_arm_contract.DeployMockARMContract(user, bc) +func setupOnRampV1_5_0(t testing.TB, user *bind.TransactOpts, bc *client.SimulatedBackendClient) (common.Address, *mock_rmn_contract.MockRMNContract, common.Address) { + rmnAddress, transaction, rmnContract, err := mock_rmn_contract.DeployMockRMNContract(user, bc) bc.Commit() require.NoError(t, err) ccipdata.AssertNonRevert(t, transaction, bc, user) @@ -158,8 +158,7 @@ func setupOnRampV1_5_0(t testing.TB, user *bind.TransactOpts, bc *client.Simulat MaxDataBytes: 0, MaxPerMsgGasLimit: 0, DefaultTokenFeeUSDCents: 50, - DefaultTokenDestGasOverhead: 34_000, - DefaultTokenDestBytesOverhead: 500, + DefaultTokenDestGasOverhead: 125_000, } rateLimiterConfig := evm_2_evm_onramp.RateLimiterConfig{ IsEnabled: false, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service.go b/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service.go index 7d7d5bda3ad..e8b9a4de721 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "slices" "sort" "sync" "time" @@ -13,15 +14,16 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" cciporm "github.com/smartcontractkit/chainlink/v2/core/services/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcommon" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/pricegetter" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" + "github.com/smartcontractkit/chainlink/v2/core/utils" ) // PriceService manages DB access for gas and token price data. @@ -42,23 +44,16 @@ type PriceService interface { var _ PriceService = (*priceService)(nil) const ( - // Prices should expire after 10 minutes in DB. Prices should be fresh in the Commit plugin. - // 10 min provides sufficient buffer for the Commit plugin to withstand transient price update outages, while - // surfacing price update outages quickly enough. - priceExpireSec = 600 - // Cleanups are called every 10 minutes. For a given job, on average we may expect 3 token prices and 1 gas price. - // 10 minutes should result in 40 rows being cleaned up per job, it is not a heavy load on DB, so there is no need - // to run cleanup more frequently. We shouldn't clean up less frequently than `priceExpireSec`. - priceCleanupInterval = 600 * time.Second - - // Prices are refreshed every 1 minute, they are sufficiently accurate, and consistent with Commit OCR round time. - priceUpdateInterval = 60 * time.Second + // Gas prices are refreshed every 1 minute, they are sufficiently accurate, and consistent with Commit OCR round time. + gasPriceUpdateInterval = 1 * time.Minute + // Token prices are refreshed every 10 minutes, we only report prices for blue chip tokens, DS&A simulation show + // their prices are stable, 10-minute resolution is accurate enough. + tokenPriceUpdateInterval = 10 * time.Minute ) type priceService struct { - priceExpireSec int - cleanupInterval time.Duration - updateInterval time.Duration + gasUpdateInterval time.Duration + tokenUpdateInterval time.Duration lggr logger.Logger orm cciporm.ORM @@ -67,7 +62,7 @@ type priceService struct { sourceChainSelector uint64 sourceNative cciptypes.Address - priceGetter pricegetter.PriceGetter + priceGetter pricegetter.AllTokensPriceGetter offRampReader ccipdata.OffRampReader gasPriceEstimator prices.GasPriceEstimatorCommit destPriceRegistryReader ccipdata.PriceRegistryReader @@ -87,15 +82,14 @@ func NewPriceService( sourceChainSelector uint64, sourceNative cciptypes.Address, - priceGetter pricegetter.PriceGetter, + priceGetter pricegetter.AllTokensPriceGetter, offRampReader ccipdata.OffRampReader, ) PriceService { ctx, cancel := context.WithCancel(context.Background()) pw := &priceService{ - priceExpireSec: priceExpireSec, - cleanupInterval: utils.WithJitter(priceCleanupInterval), // use WithJitter to avoid multiple services impacting DB at same time - updateInterval: utils.WithJitter(priceUpdateInterval), + gasUpdateInterval: gasPriceUpdateInterval, + tokenUpdateInterval: tokenPriceUpdateInterval, lggr: lggr, orm: orm, @@ -134,25 +128,27 @@ func (p *priceService) Close() error { } func (p *priceService) run() { - cleanupTicker := time.NewTicker(p.cleanupInterval) - updateTicker := time.NewTicker(p.updateInterval) + gasUpdateTicker := time.NewTicker(utils.WithJitter(p.gasUpdateInterval)) + tokenUpdateTicker := time.NewTicker(utils.WithJitter(p.tokenUpdateInterval)) go func() { defer p.wg.Done() + defer gasUpdateTicker.Stop() + defer tokenUpdateTicker.Stop() for { select { case <-p.backgroundCtx.Done(): return - case <-cleanupTicker.C: - err := p.runCleanup(p.backgroundCtx) + case <-gasUpdateTicker.C: + err := p.runGasPriceUpdate(p.backgroundCtx) if err != nil { - p.lggr.Errorw("Error when cleaning up in-db prices in the background", "err", err) + p.lggr.Errorw("Error when updating gas prices in the background", "err", err) } - case <-updateTicker.C: - err := p.runUpdate(p.backgroundCtx) + case <-tokenUpdateTicker.C: + err := p.runTokenPriceUpdate(p.backgroundCtx) if err != nil { - p.lggr.Errorw("Error when updating prices in the background", "err", err) + p.lggr.Errorw("Error when updating token prices in the background", "err", err) } } } @@ -167,8 +163,11 @@ func (p *priceService) UpdateDynamicConfig(ctx context.Context, gasPriceEstimato // Config update may substantially change the prices, refresh the prices immediately, this also makes testing easier // for not having to wait to the full update interval. - if err := p.runUpdate(ctx); err != nil { - p.lggr.Errorw("Error when updating prices after dynamic config update", "err", err) + if err := p.runGasPriceUpdate(ctx); err != nil { + p.lggr.Errorw("Error when updating gas prices after dynamic config update", "err", err) + } + if err := p.runTokenPriceUpdate(ctx); err != nil { + p.lggr.Errorw("Error when updating token prices after dynamic config update", "err", err) } return nil @@ -220,175 +219,225 @@ func (p *priceService) GetGasAndTokenPrices(ctx context.Context, destChainSelect return gasPrices, tokenPrices, nil } -func (p *priceService) runCleanup(ctx context.Context) error { - eg := new(errgroup.Group) +func (p *priceService) runGasPriceUpdate(ctx context.Context) error { + // Protect against concurrent updates of `gasPriceEstimator` and `destPriceRegistryReader` + // Price updates happen infrequently - once every `gasPriceUpdateInterval` seconds. + // It does not happen on any code path that is performance sensitive. + // We can afford to have non-performant unlocks here that is simple and safe. + p.dynamicConfigMu.RLock() + defer p.dynamicConfigMu.RUnlock() - eg.Go(func() error { - err := p.orm.ClearGasPricesByDestChain(ctx, p.destChainSelector, p.priceExpireSec) - if err != nil { - return fmt.Errorf("error clearing gas prices: %w", err) - } + // There may be a period of time between service is started and dynamic config is updated + if p.gasPriceEstimator == nil { + p.lggr.Info("Skipping gas price update due to gasPriceEstimator not ready") return nil - }) + } - eg.Go(func() error { - err := p.orm.ClearTokenPricesByDestChain(ctx, p.destChainSelector, p.priceExpireSec) - if err != nil { - return fmt.Errorf("error clearing token prices: %w", err) - } - return nil - }) + sourceGasPriceUSD, err := p.observeGasPriceUpdates(ctx, p.lggr) + if err != nil { + return fmt.Errorf("failed to observe gas price updates: %w", err) + } + + err = p.writeGasPricesToDB(ctx, sourceGasPriceUSD) + if err != nil { + return fmt.Errorf("failed to write gas prices to db: %w", err) + } - return eg.Wait() + return nil } -func (p *priceService) runUpdate(ctx context.Context) error { - // Protect against concurrent updates of `gasPriceEstimator` and `destPriceRegistryReader` - // Price updates happen infrequently - once every `priceUpdateInterval` seconds. - // It does not happen on any code path that is performance sensitive. - // We can afford to have non-performant unlocks here that is simple and safe. +func (p *priceService) runTokenPriceUpdate(ctx context.Context) error { + // Protect against concurrent updates of `tokenPriceEstimator` and `destPriceRegistryReader` + // Price updates happen infrequently - once every `tokenPriceUpdateInterval` seconds. p.dynamicConfigMu.RLock() defer p.dynamicConfigMu.RUnlock() // There may be a period of time between service is started and dynamic config is updated - if p.gasPriceEstimator == nil || p.destPriceRegistryReader == nil { - p.lggr.Info("Skipping price update due to gasPriceEstimator and/or destPriceRegistry not ready") + if p.destPriceRegistryReader == nil { + p.lggr.Info("Skipping token price update due to destPriceRegistry not ready") return nil } - sourceGasPriceUSD, tokenPricesUSD, err := p.observePriceUpdates(ctx, p.lggr) + tokenPricesUSD, err := p.observeTokenPriceUpdates(ctx, p.lggr) if err != nil { - return fmt.Errorf("failed to observe price updates: %w", err) + return fmt.Errorf("failed to observe token price updates: %w", err) } - err = p.writePricesToDB(ctx, sourceGasPriceUSD, tokenPricesUSD) + err = p.writeTokenPricesToDB(ctx, tokenPricesUSD) if err != nil { - return fmt.Errorf("failed to write prices to db: %w", err) + return fmt.Errorf("failed to write token prices to db: %w", err) } return nil } -func (p *priceService) observePriceUpdates( +func (p *priceService) observeGasPriceUpdates( ctx context.Context, lggr logger.Logger, -) (sourceGasPriceUSD *big.Int, tokenPricesUSD map[cciptypes.Address]*big.Int, err error) { - if p.gasPriceEstimator == nil || p.destPriceRegistryReader == nil { - return nil, nil, fmt.Errorf("gasPriceEstimator and/or destPriceRegistry is not set yet") +) (sourceGasPriceUSD *big.Int, err error) { + if p.gasPriceEstimator == nil { + return nil, fmt.Errorf("gasPriceEstimator is not set yet") } - sortedLaneTokens, filteredLaneTokens, err := ccipcommon.GetFilteredSortedLaneTokens(ctx, p.offRampReader, p.destPriceRegistryReader, p.priceGetter) + // Include wrapped native to identify the source native USD price, notice USD is in 1e18 scale, i.e. $1 = 1e18 + rawTokenPricesUSD, err := p.priceGetter.TokenPricesUSD(ctx, []cciptypes.Address{p.sourceNative}) - lggr.Debugw("Filtered bridgeable tokens with no configured price getter", "filteredLaneTokens", filteredLaneTokens) + if err != nil { + return nil, fmt.Errorf("failed to fetch source native price (%s): %w", p.sourceNative, err) + } + + sourceNativePriceUSD, exists := rawTokenPricesUSD[p.sourceNative] + if !exists { + return nil, fmt.Errorf("missing source native (%s) price", p.sourceNative) + } + sourceGasPrice, err := p.gasPriceEstimator.GetGasPrice(ctx) + if err != nil { + return nil, err + } + if sourceGasPrice == nil { + return nil, fmt.Errorf("missing gas price") + } + sourceGasPriceUSD, err = p.gasPriceEstimator.DenoteInUSD(ctx, sourceGasPrice, sourceNativePriceUSD) if err != nil { - return nil, nil, fmt.Errorf("get destination tokens: %w", err) + return nil, err } - return p.generatePriceUpdates(ctx, lggr, sortedLaneTokens) + lggr.Infow("PriceService observed latest gas price", + "sourceChainSelector", p.sourceChainSelector, + "destChainSelector", p.destChainSelector, + "sourceNative", p.sourceNative, + "gasPriceWei", sourceGasPrice, + "sourceNativePriceUSD", sourceNativePriceUSD, + "sourceGasPriceUSD", sourceGasPriceUSD, + ) + return sourceGasPriceUSD, nil } // All prices are USD ($1=1e18) denominated. All prices must be not nil. +// Jobspec should have the destination tokens (Aggregate Rate Limit, Bps) and 1 source token (source native). +// Not respecting this will error out as we need to fetch the token decimals for all tokens expect sourceNative. +// destTokens is only used to check if sourceNative has the same address as one of the dest tokens. // Return token prices should contain the exact same tokens as in tokenDecimals. -func (p *priceService) generatePriceUpdates( +func (p *priceService) observeTokenPriceUpdates( ctx context.Context, lggr logger.Logger, - sortedLaneTokens []cciptypes.Address, -) (sourceGasPriceUSD *big.Int, tokenPricesUSD map[cciptypes.Address]*big.Int, err error) { - // Include wrapped native in our token query as way to identify the source native USD price. - // notice USD is in 1e18 scale, i.e. $1 = 1e18 - queryTokens := ccipcommon.FlattenUniqueSlice([]cciptypes.Address{p.sourceNative}, sortedLaneTokens) - - rawTokenPricesUSD, err := p.priceGetter.TokenPricesUSD(ctx, queryTokens) +) (tokenPricesUSD map[cciptypes.Address]*big.Int, err error) { + if p.destPriceRegistryReader == nil { + return nil, fmt.Errorf("destPriceRegistry is not set yet") + } + rawTokenPricesUSD, err := p.priceGetter.GetJobSpecTokenPricesUSD(ctx) if err != nil { - return nil, nil, err + return nil, fmt.Errorf("failed to fetch token prices: %w", err) + } + + // Verify no price returned by price getter is nil + for token, price := range rawTokenPricesUSD { + if price == nil { + return nil, fmt.Errorf("Token price is nil for token %s", token) + } } + lggr.Infow("Raw token prices", "rawTokenPrices", rawTokenPricesUSD) - // make sure that we got prices for all the tokens of our query - for _, token := range queryTokens { - if rawTokenPricesUSD[token] == nil { - return nil, nil, fmt.Errorf("missing token price: %+v", token) + sourceNativeEvmAddr, err := ccipcalc.GenericAddrToEvm(p.sourceNative) + if err != nil { + return nil, fmt.Errorf("failed to convert source native to EVM address: %w", err) + } + + // Filter out source native token only if source native not in dest tokens + var finalDestTokens []cciptypes.Address + for token := range rawTokenPricesUSD { + tokenEvmAddr, err2 := ccipcalc.GenericAddrToEvm(token) + if err2 != nil { + return nil, fmt.Errorf("failed to convert token to EVM address: %w", err) + } + + if tokenEvmAddr != sourceNativeEvmAddr { + finalDestTokens = append(finalDestTokens, token) } } - sourceNativePriceUSD, exists := rawTokenPricesUSD[p.sourceNative] - if !exists { - return nil, nil, fmt.Errorf("missing source native (%s) price", p.sourceNative) + fee, bridged, err := ccipcommon.GetDestinationTokens(ctx, p.offRampReader, p.destPriceRegistryReader) + if err != nil { + return nil, fmt.Errorf("get destination tokens: %w", err) } + onchainDestTokens := ccipcommon.FlattenedAndSortedTokens(fee, bridged) + lggr.Debugw("Destination tokens", "destTokens", onchainDestTokens) - destTokensDecimals, err := p.destPriceRegistryReader.GetTokensDecimals(ctx, sortedLaneTokens) + onchainTokensEvmAddr, err := ccipcalc.GenericAddrsToEvm(onchainDestTokens...) if err != nil { - return nil, nil, fmt.Errorf("get tokens decimals: %w", err) + return nil, fmt.Errorf("failed to convert sorted lane tokens to EVM addresses: %w", err) } + // Check for case where sourceNative has same address as one of the dest tokens (example: WETH in Base and Optimism) + hasSameDestAddress := slices.Contains(onchainTokensEvmAddr, sourceNativeEvmAddr) - tokenPricesUSD = make(map[cciptypes.Address]*big.Int, len(rawTokenPricesUSD)) - for i, token := range sortedLaneTokens { - tokenPricesUSD[token] = calculateUsdPer1e18TokenAmount(rawTokenPricesUSD[token], destTokensDecimals[i]) + if hasSameDestAddress { + finalDestTokens = append(finalDestTokens, p.sourceNative) } - sourceGasPrice, err := p.gasPriceEstimator.GetGasPrice(ctx) + // Sort tokens to make the order deterministic, easier for testing and debugging + sort.Slice(finalDestTokens, func(i, j int) bool { + return finalDestTokens[i] < finalDestTokens[j] + }) + + destTokensDecimals, err := p.destPriceRegistryReader.GetTokensDecimals(ctx, finalDestTokens) if err != nil { - return nil, nil, err + return nil, fmt.Errorf("get tokens decimals: %w", err) } - if sourceGasPrice == nil { - return nil, nil, fmt.Errorf("missing gas price") + + if len(destTokensDecimals) != len(finalDestTokens) { + return nil, fmt.Errorf("mismatched token decimals and tokens") } - sourceGasPriceUSD, err = p.gasPriceEstimator.DenoteInUSD(sourceGasPrice, sourceNativePriceUSD) - if err != nil { - return nil, nil, err + + tokenPricesUSD = make(map[cciptypes.Address]*big.Int, len(rawTokenPricesUSD)) + for i, token := range finalDestTokens { + tokenPricesUSD[token] = calculateUsdPer1e18TokenAmount(rawTokenPricesUSD[token], destTokensDecimals[i]) } - lggr.Infow("PriceService observed latest price", + lggr.Infow("PriceService observed latest token prices", "sourceChainSelector", p.sourceChainSelector, "destChainSelector", p.destChainSelector, - "gasPriceWei", sourceGasPrice, - "sourceNativePriceUSD", sourceNativePriceUSD, - "sourceGasPriceUSD", sourceGasPriceUSD, "tokenPricesUSD", tokenPricesUSD, ) - return sourceGasPriceUSD, tokenPricesUSD, nil + return tokenPricesUSD, nil } -func (p *priceService) writePricesToDB( - ctx context.Context, - sourceGasPriceUSD *big.Int, - tokenPricesUSD map[cciptypes.Address]*big.Int, -) (err error) { - eg := new(errgroup.Group) - - if sourceGasPriceUSD != nil { - eg.Go(func() error { - return p.orm.InsertGasPricesForDestChain(ctx, p.destChainSelector, p.jobId, []cciporm.GasPriceUpdate{ - { - SourceChainSelector: p.sourceChainSelector, - GasPrice: assets.NewWei(sourceGasPriceUSD), - }, - }) - }) +func (p *priceService) writeGasPricesToDB(ctx context.Context, sourceGasPriceUSD *big.Int) error { + if sourceGasPriceUSD == nil { + return nil } - if tokenPricesUSD != nil { - var tokenPrices []cciporm.TokenPriceUpdate + _, err := p.orm.UpsertGasPricesForDestChain(ctx, p.destChainSelector, []cciporm.GasPrice{ + { + SourceChainSelector: p.sourceChainSelector, + GasPrice: assets.NewWei(sourceGasPriceUSD), + }, + }) + return err +} - for token, price := range tokenPricesUSD { - tokenPrices = append(tokenPrices, cciporm.TokenPriceUpdate{ - TokenAddr: string(token), - TokenPrice: assets.NewWei(price), - }) - } +func (p *priceService) writeTokenPricesToDB(ctx context.Context, tokenPricesUSD map[cciptypes.Address]*big.Int) error { + if tokenPricesUSD == nil { + return nil + } - // Sort token by addr to make price updates ordering deterministic, easier to testing and debugging - sort.Slice(tokenPrices, func(i, j int) bool { - return tokenPrices[i].TokenAddr < tokenPrices[j].TokenAddr - }) + var tokenPrices []cciporm.TokenPrice - eg.Go(func() error { - return p.orm.InsertTokenPricesForDestChain(ctx, p.destChainSelector, p.jobId, tokenPrices) + for token, price := range tokenPricesUSD { + tokenPrices = append(tokenPrices, cciporm.TokenPrice{ + TokenAddr: string(token), + TokenPrice: assets.NewWei(price), }) } - return eg.Wait() + // Sort token by addr to make price updates ordering deterministic, easier for testing and debugging + sort.Slice(tokenPrices, func(i, j int) bool { + return tokenPrices[i].TokenAddr < tokenPrices[j].TokenAddr + }) + + _, err := p.orm.UpsertTokenPricesForDestChain(ctx, p.destChainSelector, tokenPrices, p.tokenUpdateInterval) + return err } // Input price is USD per full token, with 18 decimal precision diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service_test.go index 0bea8af9a19..d76044b2256 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdb/price_service_test.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" "reflect" + "slices" "sort" "testing" "time" @@ -18,53 +19,45 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" cciporm "github.com/smartcontractkit/chainlink/v2/core/services/ccip" ccipmocks "github.com/smartcontractkit/chainlink/v2/core/services/ccip/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcommon" 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/pricegetter" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" ) -func TestPriceService_priceCleanup(t *testing.T) { +func TestPriceService_writeGasPrices(t *testing.T) { lggr := logger.TestLogger(t) jobId := int32(1) destChainSelector := uint64(12345) sourceChainSelector := uint64(67890) - testCases := []struct { - name string - gasPriceError bool - tokenPriceError bool - expectedErr bool - }{ + gasPrice := big.NewInt(1e18) + + expectedGasPriceUpdate := []cciporm.GasPrice{ { - name: "ORM called successfully", - gasPriceError: false, - tokenPriceError: false, - expectedErr: false, + SourceChainSelector: sourceChainSelector, + GasPrice: assets.NewWei(gasPrice), }, + } + + testCases := []struct { + name string + gasPriceError bool + expectedErr bool + }{ { - name: "gasPrice clear failed", - gasPriceError: true, - tokenPriceError: false, - expectedErr: true, + name: "ORM called successfully", + gasPriceError: false, + expectedErr: false, }, { - name: "tokenPrice clear failed", - gasPriceError: false, - tokenPriceError: true, - expectedErr: true, - }, - { - name: "both ORM calls failed", - gasPriceError: true, - tokenPriceError: true, - expectedErr: true, + name: "gasPrice clear failed", + gasPriceError: true, + expectedErr: true, }, } @@ -73,17 +66,12 @@ func TestPriceService_priceCleanup(t *testing.T) { ctx := tests.Context(t) var gasPricesError error - var tokenPricesError error if tc.gasPriceError { gasPricesError = fmt.Errorf("gas prices error") } - if tc.tokenPriceError { - tokenPricesError = fmt.Errorf("token prices error") - } mockOrm := ccipmocks.NewORM(t) - mockOrm.On("ClearGasPricesByDestChain", ctx, destChainSelector, priceExpireSec).Return(gasPricesError).Once() - mockOrm.On("ClearTokenPricesByDestChain", ctx, destChainSelector, priceExpireSec).Return(tokenPricesError).Once() + mockOrm.On("UpsertGasPricesForDestChain", ctx, destChainSelector, expectedGasPriceUpdate).Return(int64(0), gasPricesError).Once() priceService := NewPriceService( lggr, @@ -95,7 +83,7 @@ func TestPriceService_priceCleanup(t *testing.T) { nil, nil, ).(*priceService) - err := priceService.runCleanup(ctx) + err := priceService.writeGasPricesToDB(ctx, gasPrice) if tc.expectedErr { assert.Error(t, err) } else { @@ -105,25 +93,18 @@ func TestPriceService_priceCleanup(t *testing.T) { } } -func TestPriceService_priceWrite(t *testing.T) { +func TestPriceService_writeTokenPrices(t *testing.T) { lggr := logger.TestLogger(t) jobId := int32(1) destChainSelector := uint64(12345) sourceChainSelector := uint64(67890) - gasPrice := big.NewInt(1e18) tokenPrices := map[cciptypes.Address]*big.Int{ "0x123": big.NewInt(2e18), "0x234": big.NewInt(3e18), } - expectedGasPriceUpdate := []cciporm.GasPriceUpdate{ - { - SourceChainSelector: sourceChainSelector, - GasPrice: assets.NewWei(gasPrice), - }, - } - expectedTokenPriceUpdate := []cciporm.TokenPriceUpdate{ + expectedTokenPriceUpdate := []cciporm.TokenPrice{ { TokenAddr: "0x123", TokenPrice: assets.NewWei(big.NewInt(2e18)), @@ -136,31 +117,16 @@ func TestPriceService_priceWrite(t *testing.T) { testCases := []struct { name string - gasPriceError bool tokenPriceError bool expectedErr bool }{ { name: "ORM called successfully", - gasPriceError: false, tokenPriceError: false, expectedErr: false, }, - { - name: "gasPrice clear failed", - gasPriceError: true, - tokenPriceError: false, - expectedErr: true, - }, { name: "tokenPrice clear failed", - gasPriceError: false, - tokenPriceError: true, - expectedErr: true, - }, - { - name: "both ORM calls failed", - gasPriceError: true, tokenPriceError: true, expectedErr: true, }, @@ -170,18 +136,14 @@ func TestPriceService_priceWrite(t *testing.T) { t.Run(tc.name, func(t *testing.T) { ctx := tests.Context(t) - var gasPricesError error var tokenPricesError error - if tc.gasPriceError { - gasPricesError = fmt.Errorf("gas prices error") - } if tc.tokenPriceError { tokenPricesError = fmt.Errorf("token prices error") } mockOrm := ccipmocks.NewORM(t) - mockOrm.On("InsertGasPricesForDestChain", ctx, destChainSelector, jobId, expectedGasPriceUpdate).Return(gasPricesError).Once() - mockOrm.On("InsertTokenPricesForDestChain", ctx, destChainSelector, jobId, expectedTokenPriceUpdate).Return(tokenPricesError).Once() + mockOrm.On("UpsertTokenPricesForDestChain", ctx, destChainSelector, expectedTokenPriceUpdate, tokenPriceUpdateInterval). + Return(int64(len(expectedTokenPriceUpdate)), tokenPricesError).Once() priceService := NewPriceService( lggr, @@ -193,7 +155,7 @@ func TestPriceService_priceWrite(t *testing.T) { nil, nil, ).(*priceService) - err := priceService.writePricesToDB(ctx, gasPrice, tokenPrices) + err := priceService.writeTokenPricesToDB(ctx, tokenPrices) if tc.expectedErr { assert.Error(t, err) } else { @@ -203,22 +165,15 @@ func TestPriceService_priceWrite(t *testing.T) { } } -func TestPriceService_generatePriceUpdates(t *testing.T) { +func TestPriceService_observeGasPriceUpdates(t *testing.T) { lggr := logger.TestLogger(t) jobId := int32(1) destChainSelector := uint64(12345) sourceChainSelector := uint64(67890) - - const nTokens = 10 - tokens := make([]cciptypes.Address, nTokens) - for i := range tokens { - tokens[i] = cciptypes.Address(utils.RandomAddress().String()) - } - sort.Slice(tokens, func(i, j int) bool { return tokens[i] < tokens[j] }) + sourceNativeToken := cciptypes.Address(utils.RandomAddress().String()) testCases := []struct { name string - tokenDecimals map[cciptypes.Address]uint8 sourceNativeToken cciptypes.Address priceGetterRespData map[cciptypes.Address]*big.Int priceGetterRespErr error @@ -226,29 +181,163 @@ func TestPriceService_generatePriceUpdates(t *testing.T) { feeEstimatorRespErr error maxGasPrice uint64 expSourceGasPriceUSD *big.Int - expTokenPricesUSD map[cciptypes.Address]*big.Int expErr bool }{ { - name: "base", - tokenDecimals: map[cciptypes.Address]uint8{ - tokens[0]: 18, - tokens[1]: 12, - }, - sourceNativeToken: tokens[0], + name: "base", + sourceNativeToken: sourceNativeToken, priceGetterRespData: map[cciptypes.Address]*big.Int{ - tokens[0]: val1e18(100), - tokens[1]: val1e18(200), - tokens[2]: val1e18(300), // price getter returned a price for this token even though we didn't request it (should be skipped) + sourceNativeToken: val1e18(100), }, priceGetterRespErr: nil, feeEstimatorRespFee: big.NewInt(10), feeEstimatorRespErr: nil, maxGasPrice: 1e18, expSourceGasPriceUSD: big.NewInt(1000), + expErr: false, + }, + { + name: "price getter returned an error", + sourceNativeToken: sourceNativeToken, + priceGetterRespData: nil, + priceGetterRespErr: fmt.Errorf("some random network error"), + expErr: true, + }, + { + name: "price getter did not return source native gas price", + sourceNativeToken: sourceNativeToken, + priceGetterRespData: map[cciptypes.Address]*big.Int{ + "0x1": val1e18(100), + }, + priceGetterRespErr: nil, + expErr: true, + }, + { + name: "dynamic fee cap overrides legacy", + sourceNativeToken: sourceNativeToken, + priceGetterRespData: map[cciptypes.Address]*big.Int{ + sourceNativeToken: val1e18(100), + }, + priceGetterRespErr: nil, + feeEstimatorRespFee: big.NewInt(20), + feeEstimatorRespErr: nil, + maxGasPrice: 1e18, + expSourceGasPriceUSD: big.NewInt(2000), + expErr: false, + }, + { + name: "nil gas price", + sourceNativeToken: sourceNativeToken, + priceGetterRespData: map[cciptypes.Address]*big.Int{ + sourceNativeToken: val1e18(100), + }, + feeEstimatorRespFee: nil, + maxGasPrice: 1e18, + expErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + priceGetter := pricegetter.NewMockAllTokensPriceGetter(t) + defer priceGetter.AssertExpectations(t) + + gasPriceEstimator := prices.NewMockGasPriceEstimatorCommit(t) + defer gasPriceEstimator.AssertExpectations(t) + + priceGetter.On("TokenPricesUSD", mock.Anything, []cciptypes.Address{tc.sourceNativeToken}).Return(tc.priceGetterRespData, tc.priceGetterRespErr) + + if tc.maxGasPrice > 0 { + gasPriceEstimator.On("GetGasPrice", mock.Anything).Return(tc.feeEstimatorRespFee, tc.feeEstimatorRespErr) + if tc.feeEstimatorRespFee != nil { + pUSD := ccipcalc.CalculateUsdPerUnitGas(tc.feeEstimatorRespFee, tc.priceGetterRespData[tc.sourceNativeToken]) + gasPriceEstimator.On("DenoteInUSD", mock.Anything, mock.Anything, mock.Anything).Return(pUSD, nil) + } + } + + priceService := NewPriceService( + lggr, + nil, + jobId, + destChainSelector, + sourceChainSelector, + tc.sourceNativeToken, + priceGetter, + nil, + ).(*priceService) + priceService.gasPriceEstimator = gasPriceEstimator + + sourceGasPriceUSD, err := priceService.observeGasPriceUpdates(context.Background(), lggr) + if tc.expErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + assert.True(t, tc.expSourceGasPriceUSD.Cmp(sourceGasPriceUSD) == 0) + }) + } +} + +func TestPriceService_observeTokenPriceUpdates(t *testing.T) { + lggr := logger.TestLogger(t) + jobId := int32(1) + destChainSelector := uint64(12345) + sourceChainSelector := uint64(67890) + sourceNativeToken := cciptypes.Address(utils.RandomAddress().String()) + + const nTokens = 10 + tokens := make([]cciptypes.Address, nTokens) + for i := range tokens { + tokens[i] = cciptypes.Address(utils.RandomAddress().String()) + } + sort.Slice(tokens, func(i, j int) bool { return tokens[i] < tokens[j] }) + + testCases := []struct { + name string + destTokens []cciptypes.Address + tokenDecimals map[cciptypes.Address]uint8 + sourceNativeToken cciptypes.Address + filterOutTokens []cciptypes.Address + priceGetterRespData map[cciptypes.Address]*big.Int + priceGetterRespErr error + expTokenPricesUSD map[cciptypes.Address]*big.Int + expErr bool + expDecimalErr bool + }{ + { + name: "base case with src native token not equals to dest token", + tokenDecimals: map[cciptypes.Address]uint8{ // only destination tokens + tokens[1]: 18, + tokens[2]: 12, + }, + sourceNativeToken: sourceNativeToken, + priceGetterRespData: map[cciptypes.Address]*big.Int{ // should return all tokens (including source native token) + sourceNativeToken: val1e18(100), + tokens[1]: val1e18(200), + tokens[2]: val1e18(300), + }, + priceGetterRespErr: nil, + expTokenPricesUSD: map[cciptypes.Address]*big.Int{ // should only return the tokens in destination chain + tokens[1]: val1e18(200), + tokens[2]: val1e18(300 * 1e6), + }, + expErr: false, + }, + { + name: "base case with src native token equals to dest token", + tokenDecimals: map[cciptypes.Address]uint8{ + sourceNativeToken: 18, + tokens[1]: 12, + }, + sourceNativeToken: sourceNativeToken, + priceGetterRespData: map[cciptypes.Address]*big.Int{ + sourceNativeToken: val1e18(100), + tokens[1]: val1e18(200), + }, + priceGetterRespErr: nil, expTokenPricesUSD: map[cciptypes.Address]*big.Int{ - tokens[0]: val1e18(100), - tokens[1]: val1e18(200 * 1e6), + sourceNativeToken: val1e18(100), + tokens[1]: val1e18(200 * 1e6), }, expErr: false, }, @@ -264,109 +353,119 @@ func TestPriceService_generatePriceUpdates(t *testing.T) { expErr: true, }, { - name: "price getter skipped a requested price", + name: "price getter returns more prices than destTokens", + destTokens: []cciptypes.Address{tokens[1]}, tokenDecimals: map[cciptypes.Address]uint8{ - tokens[0]: 18, tokens[1]: 18, + tokens[2]: 12, + tokens[3]: 18, }, - sourceNativeToken: tokens[0], + sourceNativeToken: sourceNativeToken, priceGetterRespData: map[cciptypes.Address]*big.Int{ - tokens[0]: val1e18(100), + sourceNativeToken: val1e18(100), + tokens[1]: val1e18(200), + tokens[2]: val1e18(300), + tokens[3]: val1e18(400), + }, + expTokenPricesUSD: map[cciptypes.Address]*big.Int{ + tokens[1]: val1e18(200), + tokens[2]: val1e18(300 * 1e6), + tokens[3]: val1e18(400), }, - priceGetterRespErr: nil, - expErr: true, }, { - name: "price getter skipped source native price", + name: "price getter returns more prices with missing decimals", tokenDecimals: map[cciptypes.Address]uint8{ - tokens[0]: 18, tokens[1]: 18, + tokens[2]: 12, }, - sourceNativeToken: tokens[2], + sourceNativeToken: sourceNativeToken, priceGetterRespData: map[cciptypes.Address]*big.Int{ - tokens[0]: val1e18(100), - tokens[1]: val1e18(200), + sourceNativeToken: val1e18(100), + tokens[1]: val1e18(200), + tokens[2]: val1e18(300), + tokens[3]: val1e18(400), }, priceGetterRespErr: nil, expErr: true, + expDecimalErr: true, }, { - name: "dynamic fee cap overrides legacy", + name: "price getter skipped a requested price", tokenDecimals: map[cciptypes.Address]uint8{ tokens[0]: 18, - tokens[1]: 18, }, sourceNativeToken: tokens[0], priceGetterRespData: map[cciptypes.Address]*big.Int{ tokens[0]: val1e18(100), - tokens[1]: val1e18(200), - tokens[2]: val1e18(300), // price getter returned a price for this token even though we didn't request it (should be skipped) }, - priceGetterRespErr: nil, - feeEstimatorRespFee: big.NewInt(20), - feeEstimatorRespErr: nil, - maxGasPrice: 1e18, - expSourceGasPriceUSD: big.NewInt(2000), + priceGetterRespErr: nil, expTokenPricesUSD: map[cciptypes.Address]*big.Int{ tokens[0]: val1e18(100), - tokens[1]: val1e18(200), }, expErr: false, }, { - name: "nil gas price", + name: "nil token price", tokenDecimals: map[cciptypes.Address]uint8{ tokens[0]: 18, tokens[1]: 18, + tokens[2]: 18, }, sourceNativeToken: tokens[0], + filterOutTokens: []cciptypes.Address{tokens[2]}, priceGetterRespData: map[cciptypes.Address]*big.Int{ - tokens[0]: val1e18(100), + tokens[0]: nil, tokens[1]: val1e18(200), - tokens[2]: val1e18(300), // price getter returned a price for this token even though we didn't request it (should be skipped) + tokens[2]: val1e18(300), }, - feeEstimatorRespFee: nil, - maxGasPrice: 1e18, - expErr: true, + expErr: true, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - priceGetter := pricegetter.NewMockPriceGetter(t) + priceGetter := pricegetter.NewMockAllTokensPriceGetter(t) defer priceGetter.AssertExpectations(t) - gasPriceEstimator := prices.NewMockGasPriceEstimatorCommit(t) - defer gasPriceEstimator.AssertExpectations(t) - var destTokens []cciptypes.Address - for tk := range tc.tokenDecimals { - destTokens = append(destTokens, tk) + if len(tc.destTokens) == 0 { + for tk := range tc.tokenDecimals { + destTokens = append(destTokens, tk) + } + } else { + destTokens = tc.destTokens + } + + finalDestTokens := make([]cciptypes.Address, 0, len(destTokens)) + for addr := range tc.priceGetterRespData { + if (tc.sourceNativeToken != addr) || (slices.Contains(destTokens, addr)) { + finalDestTokens = append(finalDestTokens, addr) + } } - sort.Slice(destTokens, func(i, j int) bool { - return destTokens[i] < destTokens[j] + sort.Slice(finalDestTokens, func(i, j int) bool { + return finalDestTokens[i] < finalDestTokens[j] }) + var destDecimals []uint8 - for _, token := range destTokens { + for _, token := range finalDestTokens { destDecimals = append(destDecimals, tc.tokenDecimals[token]) } - queryTokens := ccipcommon.FlattenUniqueSlice([]cciptypes.Address{tc.sourceNativeToken}, destTokens) - - if len(queryTokens) > 0 { - priceGetter.On("TokenPricesUSD", mock.Anything, queryTokens).Return(tc.priceGetterRespData, tc.priceGetterRespErr) - } + priceGetter.On("GetJobSpecTokenPricesUSD", mock.Anything).Return(tc.priceGetterRespData, tc.priceGetterRespErr) - if tc.maxGasPrice > 0 { - gasPriceEstimator.On("GetGasPrice", mock.Anything).Return(tc.feeEstimatorRespFee, tc.feeEstimatorRespErr) - if tc.feeEstimatorRespFee != nil { - pUSD := ccipcalc.CalculateUsdPerUnitGas(tc.feeEstimatorRespFee, tc.expTokenPricesUSD[tc.sourceNativeToken]) - gasPriceEstimator.On("DenoteInUSD", mock.Anything, mock.Anything).Return(pUSD, nil) - } - } + offRampReader := ccipdatamocks.NewOffRampReader(t) + offRampReader.On("GetTokens", mock.Anything).Return(cciptypes.OffRampTokens{ + DestinationTokens: destTokens, + }, nil).Maybe() destPriceReg := ccipdatamocks.NewPriceRegistryReader(t) - destPriceReg.On("GetTokensDecimals", mock.Anything, destTokens).Return(destDecimals, nil).Maybe() + if tc.expDecimalErr { + destPriceReg.On("GetTokensDecimals", mock.Anything, finalDestTokens).Return([]uint8{}, fmt.Errorf("Token not found")).Maybe() + } else { + destPriceReg.On("GetTokensDecimals", mock.Anything, finalDestTokens).Return(destDecimals, nil).Maybe() + } + destPriceReg.On("GetFeeTokens", mock.Anything).Return([]cciptypes.Address{destTokens[0]}, nil).Maybe() priceService := NewPriceService( lggr, @@ -376,18 +475,16 @@ func TestPriceService_generatePriceUpdates(t *testing.T) { sourceChainSelector, tc.sourceNativeToken, priceGetter, - nil, + offRampReader, ).(*priceService) - priceService.gasPriceEstimator = gasPriceEstimator priceService.destPriceRegistryReader = destPriceReg - sourceGasPriceUSD, tokenPricesUSD, err := priceService.generatePriceUpdates(context.Background(), lggr, destTokens) + tokenPricesUSD, err := priceService.observeTokenPriceUpdates(context.Background(), lggr) if tc.expErr { assert.Error(t, err) return } assert.NoError(t, err) - assert.True(t, tc.expSourceGasPriceUSD.Cmp(sourceGasPriceUSD) == 0) assert.True(t, reflect.DeepEqual(tc.expTokenPricesUSD, tokenPricesUSD)) }) } @@ -630,7 +727,7 @@ func setupORM(t *testing.T) cciporm.ORM { t.Helper() db := pgtest.NewSqlxDB(t) - orm, err := cciporm.NewORM(db) + orm, err := cciporm.NewORM(db, logger.TestLogger(t)) require.NoError(t, err) @@ -652,49 +749,60 @@ func checkResultLen(t *testing.T, priceService PriceService, destChainSelector u return nil } -func TestPriceService_priceWriteAndCleanupInBackground(t *testing.T) { +func TestPriceService_priceWriteInBackground(t *testing.T) { lggr := logger.TestLogger(t) jobId := int32(1) destChainSelector := uint64(12345) sourceChainSelector := uint64(67890) ctx := tests.Context(t) - sourceNative := cciptypes.Address("0x123") - feeTokens := []cciptypes.Address{"0x234"} - rampTokens := []cciptypes.Address{"0x345", "0x456"} - rampFilteredTokens := []cciptypes.Address{"0x345"} - rampFilterOutTokens := []cciptypes.Address{"0x456"} + sourceNative := cciptypes.Address(utils.RandomAddress().String()) + feeToken := cciptypes.Address(utils.RandomAddress().String()) + destToken1 := cciptypes.Address(utils.RandomAddress().String()) + destToken2 := cciptypes.Address(utils.RandomAddress().String()) + + feeTokens := []cciptypes.Address{feeToken} + rampTokens := []cciptypes.Address{destToken1, destToken2} - laneTokens := []cciptypes.Address{"0x234", "0x345"} - laneTokenDecimals := []uint8{18, 18} + laneTokens := []cciptypes.Address{sourceNative, feeToken, destToken1, destToken2} + // sort laneTokens + sort.Slice(laneTokens, func(i, j int) bool { + return laneTokens[i] < laneTokens[j] + }) + laneTokenDecimals := []uint8{18, 18, 18, 18} - tokens := []cciptypes.Address{sourceNative, "0x234", "0x345"} - tokenPrices := []int64{2, 3, 4} + tokens := []cciptypes.Address{sourceNative, feeToken, destToken1, destToken2} + tokenPrices := []int64{2, 3, 4, 5} gasPrice := big.NewInt(10) orm := setupORM(t) - priceGetter := pricegetter.NewMockPriceGetter(t) + priceGetter := pricegetter.NewMockAllTokensPriceGetter(t) defer priceGetter.AssertExpectations(t) gasPriceEstimator := prices.NewMockGasPriceEstimatorCommit(t) defer gasPriceEstimator.AssertExpectations(t) - priceGetter.On("TokenPricesUSD", mock.Anything, tokens).Return(map[cciptypes.Address]*big.Int{ + priceGetter.On("TokenPricesUSD", mock.Anything, []cciptypes.Address{sourceNative}).Return(map[cciptypes.Address]*big.Int{ + tokens[0]: val1e18(tokenPrices[0]), + }, nil) + + priceGetter.On("GetJobSpecTokenPricesUSD", mock.Anything).Return(map[cciptypes.Address]*big.Int{ tokens[0]: val1e18(tokenPrices[0]), tokens[1]: val1e18(tokenPrices[1]), tokens[2]: val1e18(tokenPrices[2]), + tokens[3]: val1e18(tokenPrices[3]), }, nil) - priceGetter.On("FilterConfiguredTokens", mock.Anything, rampTokens).Return(rampFilteredTokens, rampFilterOutTokens, nil) + destTokens := append(rampTokens, sourceNative) offRampReader := ccipdatamocks.NewOffRampReader(t) offRampReader.On("GetTokens", mock.Anything).Return(cciptypes.OffRampTokens{ - DestinationTokens: rampTokens, + DestinationTokens: destTokens, }, nil).Maybe() gasPriceEstimator.On("GetGasPrice", mock.Anything).Return(gasPrice, nil) pUSD := ccipcalc.CalculateUsdPerUnitGas(gasPrice, val1e18(tokenPrices[0])) - gasPriceEstimator.On("DenoteInUSD", mock.Anything, mock.Anything).Return(pUSD, nil) + gasPriceEstimator.On("DenoteInUSD", mock.Anything, mock.Anything, mock.Anything).Return(pUSD, nil) destPriceReg := ccipdatamocks.NewPriceRegistryReader(t) destPriceReg.On("GetTokensDecimals", mock.Anything, laneTokens).Return(laneTokenDecimals, nil).Maybe() @@ -711,15 +819,13 @@ func TestPriceService_priceWriteAndCleanupInBackground(t *testing.T) { offRampReader, ).(*priceService) - updateInterval := 2000 * time.Millisecond - cleanupInterval := 3000 * time.Millisecond + gasUpdateInterval := 2000 * time.Millisecond + tokenUpdateInterval := 5000 * time.Millisecond - // run write task every 2 second - priceService.updateInterval = updateInterval - // run cleanup every 3 seconds - priceService.cleanupInterval = cleanupInterval - // expire all prices during every cleanup - priceService.priceExpireSec = 0 + // run gas price task every 2 second + priceService.gasUpdateInterval = gasUpdateInterval + // run token price task every 5 second + priceService.tokenUpdateInterval = tokenUpdateInterval // initially, db is empty assert.NoError(t, checkResultLen(t, priceService, destChainSelector, 0, 0)) @@ -732,24 +838,5 @@ func TestPriceService_priceWriteAndCleanupInBackground(t *testing.T) { assert.NoError(t, err) assert.NoError(t, checkResultLen(t, priceService, destChainSelector, 1, len(laneTokens))) - // eventually prices will be cleaned - assert.Eventually(t, func() bool { - err := checkResultLen(t, priceService, destChainSelector, 0, 0) - return err == nil - }, testutils.WaitTimeout(t), testutils.TestInterval) - - // then prices will be updated again - assert.Eventually(t, func() bool { - err := checkResultLen(t, priceService, destChainSelector, 1, len(laneTokens)) - return err == nil - }, testutils.WaitTimeout(t), testutils.TestInterval) - assert.NoError(t, priceService.Close()) - assert.NoError(t, priceService.runCleanup(ctx)) - - // after stopping PriceService and runCleanup, no more updates are inserted - for i := 0; i < 5; i++ { - time.Sleep(time.Second) - assert.NoError(t, checkResultLen(t, priceService, destChainSelector, 0, 0)) - } } 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 new file mode 100644 index 00000000000..010c955c766 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/all_price_getter_mock.go @@ -0,0 +1,269 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package pricegetter + +import ( + context "context" + big "math/big" + + ccip "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + + mock "github.com/stretchr/testify/mock" +) + +// MockAllTokensPriceGetter is an autogenerated mock type for the AllTokensPriceGetter type +type MockAllTokensPriceGetter struct { + mock.Mock +} + +type MockAllTokensPriceGetter_Expecter struct { + mock *mock.Mock +} + +func (_m *MockAllTokensPriceGetter) EXPECT() *MockAllTokensPriceGetter_Expecter { + return &MockAllTokensPriceGetter_Expecter{mock: &_m.Mock} +} + +// Close provides a mock function with given fields: +func (_m *MockAllTokensPriceGetter) 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 +} + +// MockAllTokensPriceGetter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' +type MockAllTokensPriceGetter_Close_Call struct { + *mock.Call +} + +// Close is a helper method to define mock.On call +func (_e *MockAllTokensPriceGetter_Expecter) Close() *MockAllTokensPriceGetter_Close_Call { + return &MockAllTokensPriceGetter_Close_Call{Call: _e.mock.On("Close")} +} + +func (_c *MockAllTokensPriceGetter_Close_Call) Run(run func()) *MockAllTokensPriceGetter_Close_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockAllTokensPriceGetter_Close_Call) Return(_a0 error) *MockAllTokensPriceGetter_Close_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockAllTokensPriceGetter_Close_Call) RunAndReturn(run func() error) *MockAllTokensPriceGetter_Close_Call { + _c.Call.Return(run) + return _c +} + +// FilterConfiguredTokens provides a mock function with given fields: ctx, tokens +func (_m *MockAllTokensPriceGetter) FilterConfiguredTokens(ctx context.Context, tokens []ccip.Address) ([]ccip.Address, []ccip.Address, error) { + ret := _m.Called(ctx, tokens) + + if len(ret) == 0 { + panic("no return value specified for FilterConfiguredTokens") + } + + var r0 []ccip.Address + var r1 []ccip.Address + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, []ccip.Address) ([]ccip.Address, []ccip.Address, error)); ok { + return rf(ctx, tokens) + } + if rf, ok := ret.Get(0).(func(context.Context, []ccip.Address) []ccip.Address); ok { + r0 = rf(ctx, tokens) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ccip.Address) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []ccip.Address) []ccip.Address); ok { + r1 = rf(ctx, tokens) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]ccip.Address) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, []ccip.Address) error); ok { + r2 = rf(ctx, tokens) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockAllTokensPriceGetter_FilterConfiguredTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterConfiguredTokens' +type MockAllTokensPriceGetter_FilterConfiguredTokens_Call struct { + *mock.Call +} + +// FilterConfiguredTokens is a helper method to define mock.On call +// - ctx context.Context +// - tokens []ccip.Address +func (_e *MockAllTokensPriceGetter_Expecter) FilterConfiguredTokens(ctx interface{}, tokens interface{}) *MockAllTokensPriceGetter_FilterConfiguredTokens_Call { + return &MockAllTokensPriceGetter_FilterConfiguredTokens_Call{Call: _e.mock.On("FilterConfiguredTokens", ctx, tokens)} +} + +func (_c *MockAllTokensPriceGetter_FilterConfiguredTokens_Call) Run(run func(ctx context.Context, tokens []ccip.Address)) *MockAllTokensPriceGetter_FilterConfiguredTokens_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]ccip.Address)) + }) + return _c +} + +func (_c *MockAllTokensPriceGetter_FilterConfiguredTokens_Call) Return(configured []ccip.Address, unconfigured []ccip.Address, err error) *MockAllTokensPriceGetter_FilterConfiguredTokens_Call { + _c.Call.Return(configured, unconfigured, err) + return _c +} + +func (_c *MockAllTokensPriceGetter_FilterConfiguredTokens_Call) RunAndReturn(run func(context.Context, []ccip.Address) ([]ccip.Address, []ccip.Address, error)) *MockAllTokensPriceGetter_FilterConfiguredTokens_Call { + _c.Call.Return(run) + return _c +} + +// GetJobSpecTokenPricesUSD provides a mock function with given fields: ctx +func (_m *MockAllTokensPriceGetter) GetJobSpecTokenPricesUSD(ctx context.Context) (map[ccip.Address]*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetJobSpecTokenPricesUSD") + } + + var r0 map[ccip.Address]*big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (map[ccip.Address]*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) map[ccip.Address]*big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[ccip.Address]*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetJobSpecTokenPricesUSD' +type MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call struct { + *mock.Call +} + +// GetJobSpecTokenPricesUSD is a helper method to define mock.On call +// - ctx context.Context +func (_e *MockAllTokensPriceGetter_Expecter) GetJobSpecTokenPricesUSD(ctx interface{}) *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call { + return &MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call{Call: _e.mock.On("GetJobSpecTokenPricesUSD", ctx)} +} + +func (_c *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call) Run(run func(ctx context.Context)) *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call) Return(_a0 map[ccip.Address]*big.Int, _a1 error) *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call) RunAndReturn(run func(context.Context) (map[ccip.Address]*big.Int, error)) *MockAllTokensPriceGetter_GetJobSpecTokenPricesUSD_Call { + _c.Call.Return(run) + return _c +} + +// TokenPricesUSD provides a mock function with given fields: ctx, tokens +func (_m *MockAllTokensPriceGetter) TokenPricesUSD(ctx context.Context, tokens []ccip.Address) (map[ccip.Address]*big.Int, error) { + ret := _m.Called(ctx, tokens) + + if len(ret) == 0 { + panic("no return value specified for TokenPricesUSD") + } + + var r0 map[ccip.Address]*big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []ccip.Address) (map[ccip.Address]*big.Int, error)); ok { + return rf(ctx, tokens) + } + if rf, ok := ret.Get(0).(func(context.Context, []ccip.Address) map[ccip.Address]*big.Int); ok { + r0 = rf(ctx, tokens) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[ccip.Address]*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []ccip.Address) error); ok { + r1 = rf(ctx, tokens) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockAllTokensPriceGetter_TokenPricesUSD_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TokenPricesUSD' +type MockAllTokensPriceGetter_TokenPricesUSD_Call struct { + *mock.Call +} + +// TokenPricesUSD is a helper method to define mock.On call +// - ctx context.Context +// - tokens []ccip.Address +func (_e *MockAllTokensPriceGetter_Expecter) TokenPricesUSD(ctx interface{}, tokens interface{}) *MockAllTokensPriceGetter_TokenPricesUSD_Call { + return &MockAllTokensPriceGetter_TokenPricesUSD_Call{Call: _e.mock.On("TokenPricesUSD", ctx, tokens)} +} + +func (_c *MockAllTokensPriceGetter_TokenPricesUSD_Call) Run(run func(ctx context.Context, tokens []ccip.Address)) *MockAllTokensPriceGetter_TokenPricesUSD_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]ccip.Address)) + }) + return _c +} + +func (_c *MockAllTokensPriceGetter_TokenPricesUSD_Call) Return(_a0 map[ccip.Address]*big.Int, _a1 error) *MockAllTokensPriceGetter_TokenPricesUSD_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockAllTokensPriceGetter_TokenPricesUSD_Call) RunAndReturn(run func(context.Context, []ccip.Address) (map[ccip.Address]*big.Int, error)) *MockAllTokensPriceGetter_TokenPricesUSD_Call { + _c.Call.Return(run) + return _c +} + +// NewMockAllTokensPriceGetter creates a new instance of MockAllTokensPriceGetter. 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 NewMockAllTokensPriceGetter(t interface { + mock.TestingT + Cleanup(func()) +}) *MockAllTokensPriceGetter { + mock := &MockAllTokensPriceGetter{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go index ed54428bd9b..ac4002f53fb 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go @@ -103,6 +103,11 @@ func (d *DynamicPriceGetter) FilterConfiguredTokens(ctx context.Context, tokens return configured, unconfigured, nil } +// It 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()) +} + // TokenPricesUSD implements the PriceGetter interface. // It returns static prices stored in the price getter, and batch calls aggregators (one per chain) to retrieve aggregator-based prices. func (d *DynamicPriceGetter) TokenPricesUSD(ctx context.Context, tokens []cciptypes.Address) (map[cciptypes.Address]*big.Int, error) { @@ -116,6 +121,18 @@ func (d *DynamicPriceGetter) TokenPricesUSD(ctx context.Context, tokens []ccipty return prices, nil } +func (d *DynamicPriceGetter) getAllTokensDefined() []cciptypes.Address { + tokens := make([]cciptypes.Address, 0) + + for addr := range d.cfg.AggregatorPrices { + tokens = append(tokens, ccipcalc.EvmAddrToGeneric(addr)) + } + for addr := range d.cfg.StaticPrices { + tokens = append(tokens, ccipcalc.EvmAddrToGeneric(addr)) + } + return tokens +} + // performBatchCalls performs batch calls on all chains to retrieve token prices. func (d *DynamicPriceGetter) performBatchCalls(ctx context.Context, batchCallsPerChain map[uint64]*batchCallsForChain, prices map[cciptypes.Address]*big.Int) error { for chainID, batchCalls := range batchCallsPerChain { 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 673b9776c79..78de2699688 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go @@ -25,12 +25,27 @@ type testParameters struct { evmClients map[uint64]DynamicPriceGetterClient tokens []common.Address expectedTokenPrices map[common.Address]big.Int + expectedTokenPricesForAll map[common.Address]big.Int evmCallErr bool invalidConfigErrorExpected bool priceResolutionErrorExpected bool } -func TestDynamicPriceGetter(t *testing.T) { +var ( + TK1 common.Address + TK2 common.Address + TK3 common.Address + TK4 common.Address +) + +func init() { + TK1 = utils.RandomAddress() + TK2 = utils.RandomAddress() + TK3 = utils.RandomAddress() + TK4 = utils.RandomAddress() +} + +func TestDynamicPriceGetterWithEmptyInput(t *testing.T) { tests := []struct { name string param testParameters @@ -63,6 +78,22 @@ func TestDynamicPriceGetter(t *testing.T) { name: "batchCall_returns_err", param: testParamBatchCallReturnsErr(t), }, + { + name: "less_inputs_than_defined_prices", + param: testLessInputsThanDefinedPrices(t), + }, + { + name: "get_all_tokens_aggregator_and_static", + param: testGetAllTokensAggregatorAndStatic(t), + }, + { + name: "get_all_tokens_aggregator_only", + param: testGetAllTokensAggregatorOnly(t), + }, + { + name: "get_all_tokens_static_only", + param: testGetAllTokensStaticOnly(), + }, } for _, test := range tests { @@ -74,34 +105,31 @@ func TestDynamicPriceGetter(t *testing.T) { } require.NoError(t, err) ctx := testutils.Context(t) - // Check configured token - unconfiguredTk := cciptypes.Address(utils.RandomAddress().String()) - cfgTokens, uncfgTokens, err := pg.FilterConfiguredTokens(ctx, []cciptypes.Address{unconfiguredTk}) - require.NoError(t, err) - assert.Equal(t, []cciptypes.Address{}, cfgTokens) - assert.Equal(t, []cciptypes.Address{unconfiguredTk}, uncfgTokens) - // Build list of tokens to query. - tokens := make([]cciptypes.Address, 0, len(test.param.tokens)) - for _, tk := range test.param.tokens { - tokenAddr := ccipcalc.EvmAddrToGeneric(tk) - tokens = append(tokens, tokenAddr) - } - prices, err := pg.TokenPricesUSD(ctx, tokens) - if test.param.evmCallErr { - require.Error(t, err) - return - } + var prices map[cciptypes.Address]*big.Int + var expectedTokens map[common.Address]big.Int + if len(test.param.expectedTokenPricesForAll) == 0 { + prices, err = pg.TokenPricesUSD(ctx, ccipcalc.EvmAddrsToGeneric(test.param.tokens...)) + if test.param.evmCallErr { + require.Error(t, err) + return + } - if test.param.priceResolutionErrorExpected { - require.Error(t, err) - return + if test.param.priceResolutionErrorExpected { + require.Error(t, err) + return + } + expectedTokens = test.param.expectedTokenPrices + } else { + prices, err = pg.GetJobSpecTokenPricesUSD(ctx) + expectedTokens = test.param.expectedTokenPricesForAll } + require.NoError(t, err) - // we expect prices for at least all queried tokens (it is possible that additional tokens are returned). - assert.True(t, len(prices) >= len(test.param.expectedTokenPrices)) + // Ensure all expected prices are present. + assert.True(t, len(prices) == len(expectedTokens)) // Check prices are matching expected result. - for tk, expectedPrice := range test.param.expectedTokenPrices { + for tk, expectedPrice := range expectedTokens { if prices[cciptypes.Address(tk.String())] == nil { assert.Fail(t, "Token price not found") } @@ -113,25 +141,21 @@ func TestDynamicPriceGetter(t *testing.T) { } func testParamAggregatorOnly(t *testing.T) testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() - tk4 := utils.RandomAddress() cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - tk1: { + TK1: { ChainID: 101, AggregatorContractAddress: utils.RandomAddress(), }, - tk2: { + TK2: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, - tk3: { + TK3: { ChainID: 103, AggregatorContractAddress: utils.RandomAddress(), }, - tk4: { + TK4: { ChainID: 104, AggregatorContractAddress: utils.RandomAddress(), }, @@ -177,15 +201,15 @@ func testParamAggregatorOnly(t *testing.T) testParameters { uint64(104): mockClient(t, []uint8{20}, []aggregator_v3_interface.LatestRoundData{round4}), } expectedTokenPrices := map[common.Address]big.Int{ - tk1: *multExp(round1.Answer, 10), // expected in 1e18 format. - tk2: *multExp(round2.Answer, 10), // expected in 1e18 format. - tk3: *round3.Answer, // already in 1e18 format (contract decimals==18). - tk4: *multExp(big.NewInt(1234567890), 8), // expected in 1e18 format. + TK1: *multExp(round1.Answer, 10), // expected in 1e18 format. + TK2: *multExp(round2.Answer, 10), // expected in 1e18 format. + TK3: *round3.Answer, // already in 1e18 format (contract decimals==18). + TK4: *multExp(big.NewInt(1234567890), 8), // expected in 1e18 format. } return testParameters{ cfg: cfg, evmClients: evmClients, - tokens: []common.Address{tk1, tk2, tk3, tk4}, + tokens: []common.Address{TK1, TK2, TK3, TK4}, expectedTokenPrices: expectedTokenPrices, invalidConfigErrorExpected: false, } @@ -193,20 +217,17 @@ func testParamAggregatorOnly(t *testing.T) testParameters { // testParamAggregatorOnlyMulti test with several tokens on chain 102. func testParamAggregatorOnlyMulti(t *testing.T) testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - tk1: { + TK1: { ChainID: 101, AggregatorContractAddress: utils.RandomAddress(), }, - tk2: { + TK2: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, - tk3: { + TK3: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, @@ -241,35 +262,32 @@ func testParamAggregatorOnlyMulti(t *testing.T) testParameters { uint64(102): mockClient(t, []uint8{8, 8}, []aggregator_v3_interface.LatestRoundData{round2, round3}), } expectedTokenPrices := map[common.Address]big.Int{ - tk1: *multExp(round1.Answer, 10), - tk2: *multExp(round2.Answer, 10), - tk3: *multExp(round3.Answer, 10), + TK1: *multExp(round1.Answer, 10), + TK2: *multExp(round2.Answer, 10), + TK3: *multExp(round3.Answer, 10), } return testParameters{ cfg: cfg, evmClients: evmClients, invalidConfigErrorExpected: false, - tokens: []common.Address{tk1, tk2, tk3}, + tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, } } func testParamStaticOnly() testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{}, StaticPrices: map[common.Address]config.StaticPriceConfig{ - tk1: { + TK1: { ChainID: 101, Price: big.NewInt(1_234_000), }, - tk2: { + TK2: { ChainID: 102, Price: big.NewInt(2_234_000), }, - tk3: { + TK3: { ChainID: 103, Price: big.NewInt(3_234_000), }, @@ -278,35 +296,86 @@ func testParamStaticOnly() testParameters { // Real LINK/USD example from OP. evmClients := map[uint64]DynamicPriceGetterClient{} expectedTokenPrices := map[common.Address]big.Int{ - tk1: *cfg.StaticPrices[tk1].Price, - tk2: *cfg.StaticPrices[tk2].Price, - tk3: *cfg.StaticPrices[tk3].Price, + TK1: *cfg.StaticPrices[TK1].Price, + TK2: *cfg.StaticPrices[TK2].Price, + TK3: *cfg.StaticPrices[TK3].Price, } return testParameters{ cfg: cfg, evmClients: evmClients, - tokens: []common.Address{tk1, tk2, tk3}, + tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, } } +func testParamNoAggregatorForToken(t *testing.T) testParameters { + cfg := config.DynamicPriceGetterConfig{ + AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ + TK1: { + ChainID: 101, + AggregatorContractAddress: utils.RandomAddress(), + }, + TK2: { + ChainID: 102, + AggregatorContractAddress: utils.RandomAddress(), + }, + }, + StaticPrices: map[common.Address]config.StaticPriceConfig{ + TK3: { + ChainID: 103, + Price: big.NewInt(1_234_000), + }, + }, + } + // Real LINK/USD example from OP. + round1 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(1000), + Answer: big.NewInt(1396818990), + StartedAt: big.NewInt(1704896575), + UpdatedAt: big.NewInt(1704896575), + AnsweredInRound: big.NewInt(1000), + } + // Real ETH/USD example from OP. + round2 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(2000), + Answer: big.NewInt(238879815123), + StartedAt: big.NewInt(1704897197), + 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}), + } + expectedTokenPrices := map[common.Address]big.Int{ + TK1: *round1.Answer, + TK2: *round2.Answer, + TK3: *cfg.StaticPrices[TK3].Price, + TK4: *big.NewInt(0), + } + return testParameters{ + cfg: cfg, + evmClients: evmClients, + tokens: []common.Address{TK1, TK2, TK3, TK4}, + expectedTokenPrices: expectedTokenPrices, + priceResolutionErrorExpected: true, + } +} + func testParamAggregatorAndStaticValid(t *testing.T) testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - tk1: { + TK1: { ChainID: 101, AggregatorContractAddress: utils.RandomAddress(), }, - tk2: { + TK2: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, }, StaticPrices: map[common.Address]config.StaticPriceConfig{ - tk3: { + TK3: { ChainID: 103, Price: big.NewInt(1_234_000), }, @@ -333,39 +402,36 @@ func testParamAggregatorAndStaticValid(t *testing.T) testParameters { uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), } expectedTokenPrices := map[common.Address]big.Int{ - tk1: *multExp(round1.Answer, 10), - tk2: *multExp(round2.Answer, 10), - tk3: *cfg.StaticPrices[tk3].Price, + TK1: *multExp(round1.Answer, 10), + TK2: *multExp(round2.Answer, 10), + TK3: *cfg.StaticPrices[TK3].Price, } return testParameters{ cfg: cfg, evmClients: evmClients, - tokens: []common.Address{tk1, tk2, tk3}, + tokens: []common.Address{TK1, TK2, TK3}, expectedTokenPrices: expectedTokenPrices, } } func testParamAggregatorAndStaticTokenCollision(t *testing.T) testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - tk1: { + TK1: { ChainID: 101, AggregatorContractAddress: utils.RandomAddress(), }, - tk2: { + TK2: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, - tk3: { + TK3: { ChainID: 103, AggregatorContractAddress: utils.RandomAddress(), }, }, StaticPrices: map[common.Address]config.StaticPriceConfig{ - tk3: { + TK3: { ChainID: 103, Price: big.NewInt(1_234_000), }, @@ -402,29 +468,25 @@ func testParamAggregatorAndStaticTokenCollision(t *testing.T) testParameters { return testParameters{ cfg: cfg, evmClients: evmClients, - tokens: []common.Address{tk1, tk2, tk3}, + tokens: []common.Address{TK1, TK2, TK3}, invalidConfigErrorExpected: true, } } -func testParamNoAggregatorForToken(t *testing.T) testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() - tk4 := utils.RandomAddress() +func testParamBatchCallReturnsErr(t *testing.T) testParameters { cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - tk1: { + TK1: { ChainID: 101, AggregatorContractAddress: utils.RandomAddress(), }, - tk2: { + TK2: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, }, StaticPrices: map[common.Address]config.StaticPriceConfig{ - tk3: { + TK3: { ChainID: 103, Price: big.NewInt(1_234_000), }, @@ -438,6 +500,51 @@ func testParamNoAggregatorForToken(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), + }, + } + return testParameters{ + cfg: cfg, + evmClients: evmClients, + tokens: []common.Address{TK1, TK2, TK3}, + evmCallErr: true, + } +} + +func testLessInputsThanDefinedPrices(t *testing.T) testParameters { + cfg := config.DynamicPriceGetterConfig{ + AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ + TK1: { + ChainID: 101, + AggregatorContractAddress: utils.RandomAddress(), + }, + TK2: { + ChainID: 102, + AggregatorContractAddress: utils.RandomAddress(), + }, + TK3: { + ChainID: 103, + AggregatorContractAddress: utils.RandomAddress(), + }, + }, + StaticPrices: map[common.Address]config.StaticPriceConfig{ + TK4: { + ChainID: 104, + Price: big.NewInt(1_234_000), + }, + }, + } + // Real LINK/USD example from OP. + round1 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(1000), + Answer: big.NewInt(3749350456), + StartedAt: big.NewInt(1704896575), + UpdatedAt: big.NewInt(1704896575), + AnsweredInRound: big.NewInt(1000), + } // Real ETH/USD example from OP. round2 := aggregator_v3_interface.LatestRoundData{ RoundId: big.NewInt(2000), @@ -446,43 +553,51 @@ func testParamNoAggregatorForToken(t *testing.T) testParameters { UpdatedAt: big.NewInt(1704897197), AnsweredInRound: big.NewInt(2000), } + // Real LINK/ETH example from OP. + round3 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(3000), + Answer: big.NewInt(4468862777874802), + StartedAt: big.NewInt(1715743907), + 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}), } expectedTokenPrices := map[common.Address]big.Int{ - tk1: *round1.Answer, - tk2: *round2.Answer, - tk3: *cfg.StaticPrices[tk3].Price, - tk4: *big.NewInt(0), + TK1: *multExp(round1.Answer, 10), + TK2: *multExp(round2.Answer, 10), + TK3: *multExp(round3.Answer, 10), } return testParameters{ - cfg: cfg, - evmClients: evmClients, - tokens: []common.Address{tk1, tk2, tk3, tk4}, - expectedTokenPrices: expectedTokenPrices, - priceResolutionErrorExpected: true, + cfg: cfg, + evmClients: evmClients, + tokens: []common.Address{TK1, TK2, TK3}, + expectedTokenPrices: expectedTokenPrices, } } -func testParamBatchCallReturnsErr(t *testing.T) testParameters { - tk1 := utils.RandomAddress() - tk2 := utils.RandomAddress() - tk3 := utils.RandomAddress() +func testGetAllTokensAggregatorAndStatic(t *testing.T) testParameters { cfg := config.DynamicPriceGetterConfig{ AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - tk1: { + TK1: { ChainID: 101, AggregatorContractAddress: utils.RandomAddress(), }, - tk2: { + TK2: { ChainID: 102, AggregatorContractAddress: utils.RandomAddress(), }, + TK3: { + ChainID: 103, + AggregatorContractAddress: utils.RandomAddress(), + }, }, StaticPrices: map[common.Address]config.StaticPriceConfig{ - tk3: { - ChainID: 103, + TK4: { + ChainID: 104, Price: big.NewInt(1_234_000), }, }, @@ -490,22 +605,133 @@ func testParamBatchCallReturnsErr(t *testing.T) testParameters { // Real LINK/USD example from OP. round1 := aggregator_v3_interface.LatestRoundData{ RoundId: big.NewInt(1000), - Answer: big.NewInt(1396818990), + Answer: big.NewInt(3749350456), StartedAt: big.NewInt(1704896575), UpdatedAt: big.NewInt(1704896575), AnsweredInRound: big.NewInt(1000), } + // Real ETH/USD example from OP. + round2 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(2000), + Answer: big.NewInt(238879815123), + StartedAt: big.NewInt(1704897197), + UpdatedAt: big.NewInt(1704897197), + AnsweredInRound: big.NewInt(2000), + } + // Real LINK/ETH example from OP. + round3 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(3000), + Answer: big.NewInt(4468862777874802), + StartedAt: big.NewInt(1715743907), + 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): { - BatchCaller: mockErrCaller(t), + uint64(102): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round2}), + uint64(103): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round3}), + } + expectedTokenPricesForAll := map[common.Address]big.Int{ + TK1: *multExp(round1.Answer, 10), + TK2: *multExp(round2.Answer, 10), + TK3: *multExp(round3.Answer, 10), + TK4: *cfg.StaticPrices[TK4].Price, + } + return testParameters{ + cfg: cfg, + evmClients: evmClients, + expectedTokenPricesForAll: expectedTokenPricesForAll, + } +} + +func testGetAllTokensAggregatorOnly(t *testing.T) testParameters { + cfg := config.DynamicPriceGetterConfig{ + AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ + TK1: { + ChainID: 101, + AggregatorContractAddress: utils.RandomAddress(), + }, + TK2: { + ChainID: 102, + AggregatorContractAddress: utils.RandomAddress(), + }, + TK3: { + ChainID: 103, + AggregatorContractAddress: utils.RandomAddress(), + }, }, + StaticPrices: map[common.Address]config.StaticPriceConfig{}, + } + // Real LINK/USD example from OP. + round1 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(1000), + Answer: big.NewInt(3749350456), + StartedAt: big.NewInt(1704896575), + UpdatedAt: big.NewInt(1704896575), + AnsweredInRound: big.NewInt(1000), + } + // Real ETH/USD example from OP. + round2 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(2000), + Answer: big.NewInt(238879815123), + StartedAt: big.NewInt(1704897197), + UpdatedAt: big.NewInt(1704897197), + AnsweredInRound: big.NewInt(2000), + } + // Real LINK/ETH example from OP. + round3 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(3000), + Answer: big.NewInt(4468862777874802), + StartedAt: big.NewInt(1715743907), + 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}), + } + expectedTokenPricesForAll := map[common.Address]big.Int{ + TK1: *multExp(round1.Answer, 10), + TK2: *multExp(round2.Answer, 10), + TK3: *multExp(round3.Answer, 10), } return testParameters{ - cfg: cfg, - evmClients: evmClients, - tokens: []common.Address{tk1, tk2, tk3}, - evmCallErr: true, + cfg: cfg, + evmClients: evmClients, + expectedTokenPricesForAll: expectedTokenPricesForAll, + } +} + +func testGetAllTokensStaticOnly() testParameters { + cfg := config.DynamicPriceGetterConfig{ + AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{}, + StaticPrices: map[common.Address]config.StaticPriceConfig{ + TK1: { + ChainID: 101, + Price: big.NewInt(1_234_000), + }, + TK2: { + ChainID: 102, + Price: big.NewInt(2_234_000), + }, + TK3: { + ChainID: 103, + Price: big.NewInt(3_234_000), + }, + }, + } + + evmClients := map[uint64]DynamicPriceGetterClient{} + expectedTokenPricesForAll := map[common.Address]big.Int{ + TK1: *cfg.StaticPrices[TK1].Price, + TK2: *cfg.StaticPrices[TK2].Price, + TK3: *cfg.StaticPrices[TK3].Price, + } + return testParameters{ + cfg: cfg, + evmClients: evmClients, + expectedTokenPricesForAll: expectedTokenPricesForAll, } } diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go index ae9a10deb65..34977eda9f1 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline.go @@ -11,7 +11,6 @@ import ( "github.com/pkg/errors" 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" @@ -60,28 +59,30 @@ func (d *PipelineGetter) FilterConfiguredTokens(ctx context.Context, tokens []cc return configured, unconfigured, nil } -func (d *PipelineGetter) TokenPricesUSD(ctx context.Context, tokens []cciptypes.Address) (map[cciptypes.Address]*big.Int, error) { - _, trrs, err := d.runner.ExecuteRun(ctx, pipeline.Spec{ - ID: d.jobID, - DotDagSource: d.source, - CreatedAt: time.Now(), - JobID: d.jobID, - JobName: d.name, - JobType: "", - }, pipeline.NewVarsFrom(map[string]interface{}{})) +func (d *PipelineGetter) GetJobSpecTokenPricesUSD(ctx context.Context) (map[cciptypes.Address]*big.Int, error) { + prices, err := d.getPricesFromRunner(ctx) if err != nil { return nil, err } - finalResult := trrs.FinalResult() - if finalResult.HasErrors() { - return nil, errors.Errorf("error getting prices %v", finalResult.AllErrors) - } - if len(finalResult.Values) != 1 { - return nil, errors.Errorf("invalid number of price results, expected 1 got %v", len(finalResult.Values)) + + tokenPrices := make(map[cciptypes.Address]*big.Int) + for tokenAddressStr, rawPrice := range prices { + tokenAddressStr := ccipcalc.HexToAddress(tokenAddressStr) + castedPrice, err := parseutil.ParseBigIntFromAny(rawPrice) + if err != nil { + return nil, err + } + + tokenPrices[tokenAddressStr] = castedPrice } - prices, ok := finalResult.Values[0].(map[string]interface{}) - if !ok { - return nil, errors.Errorf("expected map output of price pipeline, got %T", finalResult.Values[0]) + + return tokenPrices, nil +} + +func (d *PipelineGetter) TokenPricesUSD(ctx context.Context, tokens []cciptypes.Address) (map[cciptypes.Address]*big.Int, error) { + prices, err := d.getPricesFromRunner(ctx) + if err != nil { + return nil, err } providedTokensSet := mapset.NewSet(tokens...) @@ -101,7 +102,7 @@ func (d *PipelineGetter) TokenPricesUSD(ctx context.Context, tokens []cciptypes. // The mapping of token address to source of token price has to live offchain. // Best we can do is sanity check that the token price spec covers all our desired execution token prices. for _, token := range tokens { - if _, ok = tokenPrices[token]; !ok { + if _, ok := tokenPrices[token]; !ok { return nil, errors.Errorf("missing token %s from tokensForFeeCoin spec, got %v", token, prices) } } @@ -109,6 +110,33 @@ func (d *PipelineGetter) TokenPricesUSD(ctx context.Context, tokens []cciptypes. return tokenPrices, nil } +func (d *PipelineGetter) getPricesFromRunner(ctx context.Context) (map[string]interface{}, error) { + _, trrs, err := d.runner.ExecuteRun(ctx, pipeline.Spec{ + ID: d.jobID, + DotDagSource: d.source, + CreatedAt: time.Now(), + JobID: d.jobID, + JobName: d.name, + JobType: "", + }, pipeline.NewVarsFrom(map[string]interface{}{})) + if err != nil { + return nil, err + } + finalResult := trrs.FinalResult() + if finalResult.HasErrors() { + return nil, errors.Errorf("error getting prices %v", finalResult.AllErrors) + } + if len(finalResult.Values) != 1 { + return nil, errors.Errorf("invalid number of price results, expected 1 got %v", len(finalResult.Values)) + } + prices, ok := finalResult.Values[0].(map[string]interface{}) + if !ok { + return nil, errors.Errorf("expected map output of price pipeline, got %T", finalResult.Values[0]) + } + + return prices, nil +} + func (d *PipelineGetter) Close() error { return d.runner.Close() } diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline_test.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline_test.go index 37970750732..8aeeff96b57 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline_test.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/pipeline_test.go @@ -57,19 +57,21 @@ func TestDataSource(t *testing.T) { priceGetter := newTestPipelineGetter(t, source) - // USDC & LINK are configured - confTokens, _, err := priceGetter.FilterConfiguredTokens(context.Background(), []cciptypes.Address{linkTokenAddress, usdcTokenAddress}) + // Ask for all prices present in spec. + prices, err := priceGetter.GetJobSpecTokenPricesUSD(context.Background()) require.NoError(t, err) - assert.Equal(t, linkTokenAddress, confTokens[0]) - assert.Equal(t, usdcTokenAddress, confTokens[1]) + assert.Equal(t, prices, map[cciptypes.Address]*big.Int{ + linkTokenAddress: big.NewInt(0).Mul(big.NewInt(200), big.NewInt(1000000000000000000)), + usdcTokenAddress: big.NewInt(0).Mul(big.NewInt(1000), big.NewInt(1000000000000000000)), + }) - // Ask for all prices present in spec. - prices, err := priceGetter.TokenPricesUSD(context.Background(), []cciptypes.Address{ + // Specifically ask for all prices + pricesWithInput, errWithInput := priceGetter.TokenPricesUSD(context.Background(), []cciptypes.Address{ linkTokenAddress, usdcTokenAddress, }) - require.NoError(t, err) - assert.Equal(t, prices, map[cciptypes.Address]*big.Int{ + require.NoError(t, errWithInput) + assert.Equal(t, pricesWithInput, map[cciptypes.Address]*big.Int{ linkTokenAddress: big.NewInt(0).Mul(big.NewInt(200), big.NewInt(1000000000000000000)), usdcTokenAddress: big.NewInt(0).Mul(big.NewInt(1000), big.NewInt(1000000000000000000)), }) diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/pricegetter.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/pricegetter.go index 9ee0e8f3d0a..d4bcfc57b6e 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/pricegetter.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/pricegetter.go @@ -1,7 +1,18 @@ package pricegetter -import cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" +import ( + "context" + "math/big" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" +) type PriceGetter interface { cciptypes.PriceGetter } + +type AllTokensPriceGetter interface { + PriceGetter + // GetJobSpecTokenPricesUSD returns all token prices defined in the jobspec. + GetJobSpecTokenPricesUSD(ctx context.Context) (map[cciptypes.Address]*big.Int, error) +} diff --git a/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go b/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go index 71357029dd2..6c4aabb4355 100644 --- a/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go +++ b/core/services/ocr2/plugins/ccip/internal/rpclib/evm.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) var ErrEmptyOutput = errors.New("rpc call output is empty (make sure that the contract method exists and rpc is healthy)") diff --git a/core/services/ocr2/plugins/ccip/pkg/leafer/leafer.go b/core/services/ocr2/plugins/ccip/pkg/leafer/leafer.go index c334f159fd2..a5ea56f0bbd 100644 --- a/core/services/ocr2/plugins/ccip/pkg/leafer/leafer.go +++ b/core/services/ocr2/plugins/ccip/pkg/leafer/leafer.go @@ -10,9 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" "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/ccipdata/v1_5_0" ) @@ -26,7 +24,6 @@ type LeafHasher interface { type Version string const ( - V1_0_0 Version = "v1_0_0" V1_2_0 Version = "v1_2_0" V1_5_0 Version = "v1_5_0" ) @@ -34,13 +31,6 @@ const ( // MakeLeafHasher is a factory function to construct the onramp implementing the HashLeaf function for a given version. func MakeLeafHasher(ver Version, cl bind.ContractBackend, sourceChainSelector uint64, destChainSelector uint64, onRampId common.Address, ctx hashutil.Hasher[[32]byte]) (LeafHasher, error) { switch ver { - case V1_0_0: - or, err := evm_2_evm_onramp_1_0_0.NewEVM2EVMOnRamp(onRampId, cl) - if err != nil { - return nil, err - } - h := v1_0_0.NewLeafHasher(sourceChainSelector, destChainSelector, onRampId, ctx, or) - return h, nil case V1_2_0: or, err := evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(onRampId, cl) if err != nil { 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 7c75b9bdd99..d0093e5d672 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go @@ -66,7 +66,7 @@ func (g DAGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) return gasPrice, nil } -func (g DAGasPriceEstimator) DenoteInUSD(p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { +func (g DAGasPriceEstimator) DenoteInUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { daGasPrice, execGasPrice, err := g.parseEncodedGasPrice(p) if err != nil { return nil, err @@ -86,7 +86,7 @@ func (g DAGasPriceEstimator) DenoteInUSD(p *big.Int, wrappedNativePrice *big.Int return new(big.Int).Add(daUSD, execUSD), nil } -func (g DAGasPriceEstimator) Median(gasPrices []*big.Int) (*big.Int, error) { +func (g DAGasPriceEstimator) Median(ctx context.Context, gasPrices []*big.Int) (*big.Int, error) { daPrices := make([]*big.Int, len(gasPrices)) execPrices := make([]*big.Int, len(gasPrices)) @@ -107,7 +107,7 @@ func (g DAGasPriceEstimator) Median(gasPrices []*big.Int) (*big.Int, error) { return new(big.Int).Add(daMedian, execMedian), nil } -func (g DAGasPriceEstimator) Deviates(p1, p2 *big.Int) (bool, error) { +func (g DAGasPriceEstimator) Deviates(ctx context.Context, p1, p2 *big.Int) (bool, error) { p1DAGasPrice, p1ExecGasPrice, err := g.parseEncodedGasPrice(p1) if err != nil { return false, err @@ -117,7 +117,7 @@ func (g DAGasPriceEstimator) Deviates(p1, p2 *big.Int) (bool, error) { return false, err } - execDeviates, err := g.execEstimator.Deviates(p1ExecGasPrice, p2ExecGasPrice) + execDeviates, err := g.execEstimator.Deviates(ctx, p1ExecGasPrice, p2ExecGasPrice) if err != nil { return false, err } @@ -128,13 +128,13 @@ func (g DAGasPriceEstimator) Deviates(p1, p2 *big.Int) (bool, error) { return ccipcalc.Deviates(p1DAGasPrice, p2DAGasPrice, g.daDeviationPPB), nil } -func (g DAGasPriceEstimator) EstimateMsgCostUSD(p *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { +func (g DAGasPriceEstimator) EstimateMsgCostUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { daGasPrice, execGasPrice, err := g.parseEncodedGasPrice(p) if err != nil { return nil, err } - execCostUSD, err := g.execEstimator.EstimateMsgCostUSD(execGasPrice, wrappedNativePrice, msg) + execCostUSD, err := g.execEstimator.EstimateMsgCostUSD(ctx, execGasPrice, wrappedNativePrice, msg) if err != nil { return nil, err } 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 2f8616a8669..2772042f68d 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 @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/mock" 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" ) @@ -137,11 +138,12 @@ func TestDAPriceEstimator_DenoteInUSD(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := DAGasPriceEstimator{ priceEncodingLength: daGasPriceEncodingLength, } - gasPrice, err := g.DenoteInUSD(tc.gasPrice, tc.nativePrice) + gasPrice, err := g.DenoteInUSD(ctx, tc.gasPrice, tc.nativePrice) assert.NoError(t, err) assert.True(t, tc.expPrice.Cmp(gasPrice) == 0) }) @@ -222,11 +224,12 @@ func TestDAPriceEstimator_Median(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := DAGasPriceEstimator{ priceEncodingLength: daGasPriceEncodingLength, } - gasPrice, err := g.Median(tc.gasPrices) + gasPrice, err := g.Median(ctx, tc.gasPrices) assert.NoError(t, err) assert.True(t, tc.expMedian.Cmp(gasPrice) == 0) }) @@ -302,6 +305,7 @@ func TestDAPriceEstimator_Deviates(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := DAGasPriceEstimator{ execEstimator: ExecGasPriceEstimator{ deviationPPB: tc.execDeviationPPB, @@ -310,7 +314,7 @@ func TestDAPriceEstimator_Deviates(t *testing.T) { priceEncodingLength: daGasPriceEncodingLength, } - deviated, err := g.Deviates(tc.gasPrice1, tc.gasPrice2) + deviated, err := g.Deviates(ctx, tc.gasPrice1, tc.gasPrice2) assert.NoError(t, err) if tc.expDeviates { assert.True(t, deviated) @@ -420,9 +424,10 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { for _, tc := range testCases { execEstimator := NewMockGasPriceEstimator(t) - execEstimator.On("EstimateMsgCostUSD", mock.Anything, tc.wrappedNativePrice, tc.msg).Return(execCostUSD, nil) + 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) g := DAGasPriceEstimator{ execEstimator: execEstimator, l1Oracle: nil, @@ -432,7 +437,7 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { daMultiplier: tc.daMultiplier, } - costUSD, err := g.EstimateMsgCostUSD(tc.gasPrice, tc.wrappedNativePrice, tc.msg) + costUSD, err := g.EstimateMsgCostUSD(ctx, tc.gasPrice, tc.wrappedNativePrice, tc.msg) assert.NoError(t, err) assert.Equal(t, tc.expUSD, costUSD) }) diff --git a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go index 56e1ddb583e..c6e132e3a75 100644 --- a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go @@ -26,14 +26,14 @@ func NewExecGasPriceEstimator(estimator gas.EvmFeeEstimator, maxGasPrice *big.In } func (g ExecGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) { - gasPriceWei, _, err := g.estimator.GetFee(ctx, nil, 0, assets.NewWei(g.maxGasPrice)) + gasPriceWei, _, err := g.estimator.GetFee(ctx, nil, 0, assets.NewWei(g.maxGasPrice), nil, nil) if err != nil { return nil, err } // Use legacy if no dynamic is available. - gasPrice := gasPriceWei.Legacy.ToInt() - if gasPriceWei.DynamicFeeCap != nil { - gasPrice = gasPriceWei.DynamicFeeCap.ToInt() + gasPrice := gasPriceWei.GasPrice.ToInt() + if gasPriceWei.GasFeeCap != nil { + gasPrice = gasPriceWei.GasFeeCap.ToInt() } if gasPrice == nil { return nil, fmt.Errorf("missing gas price %+v", gasPriceWei) @@ -42,19 +42,19 @@ func (g ExecGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error return gasPrice, nil } -func (g ExecGasPriceEstimator) DenoteInUSD(p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { +func (g ExecGasPriceEstimator) DenoteInUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { return ccipcalc.CalculateUsdPerUnitGas(p, wrappedNativePrice), nil } -func (g ExecGasPriceEstimator) Median(gasPrices []*big.Int) (*big.Int, error) { +func (g ExecGasPriceEstimator) Median(ctx context.Context, gasPrices []*big.Int) (*big.Int, error) { return ccipcalc.BigIntSortedMiddle(gasPrices), nil } -func (g ExecGasPriceEstimator) Deviates(p1 *big.Int, p2 *big.Int) (bool, error) { +func (g ExecGasPriceEstimator) Deviates(ctx context.Context, p1 *big.Int, p2 *big.Int) (bool, error) { return ccipcalc.Deviates(p1, p2, g.deviationPPB), nil } -func (g ExecGasPriceEstimator) EstimateMsgCostUSD(p *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { +func (g ExecGasPriceEstimator) EstimateMsgCostUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { execGasAmount := new(big.Int).Add(big.NewInt(feeBoostingOverheadGas), msg.GasLimit) execGasAmount = new(big.Int).Add(execGasAmount, new(big.Int).Mul(big.NewInt(int64(len(msg.Data))), big.NewInt(execGasPerPayloadByte))) execGasAmount = new(big.Int).Add(execGasAmount, new(big.Int).Mul(big.NewInt(int64(len(msg.TokenAmounts))), big.NewInt(execGasPerToken))) diff --git a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go index e1c2fa03981..b8f6fa978db 100644 --- a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go +++ b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go @@ -5,10 +5,12 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/stretchr/testify/assert" 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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" @@ -28,8 +30,8 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { { name: "gets legacy gas price", sourceFeeEstimatorRespFee: gas.EvmFee{ - Legacy: assets.NewWei(big.NewInt(10)), - DynamicFeeCap: nil, + GasPrice: assets.NewWei(big.NewInt(10)), + DynamicFee: gas.DynamicFee{}, }, sourceFeeEstimatorRespErr: nil, maxGasPrice: big.NewInt(1), @@ -39,8 +41,8 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { { name: "gets dynamic gas price", sourceFeeEstimatorRespFee: gas.EvmFee{ - Legacy: nil, - DynamicFeeCap: assets.NewWei(big.NewInt(20)), + GasPrice: nil, + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWei(big.NewInt(20))}, }, sourceFeeEstimatorRespErr: nil, maxGasPrice: big.NewInt(1), @@ -50,8 +52,8 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { { name: "gets dynamic gas price over legacy gas price", sourceFeeEstimatorRespFee: gas.EvmFee{ - Legacy: assets.NewWei(big.NewInt(10)), - DynamicFeeCap: assets.NewWei(big.NewInt(20)), + GasPrice: assets.NewWei(big.NewInt(10)), + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWei(big.NewInt(20))}, }, sourceFeeEstimatorRespErr: nil, maxGasPrice: big.NewInt(1), @@ -61,8 +63,8 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { { name: "fee estimator error", sourceFeeEstimatorRespFee: gas.EvmFee{ - Legacy: assets.NewWei(big.NewInt(10)), - DynamicFeeCap: nil, + GasPrice: assets.NewWei(big.NewInt(10)), + DynamicFee: gas.DynamicFee{}, }, sourceFeeEstimatorRespErr: errors.New("fee estimator error"), maxGasPrice: big.NewInt(1), @@ -72,8 +74,8 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { { name: "nil gas price error", sourceFeeEstimatorRespFee: gas.EvmFee{ - Legacy: nil, - DynamicFeeCap: nil, + GasPrice: nil, + DynamicFee: gas.DynamicFee{}, }, sourceFeeEstimatorRespErr: nil, maxGasPrice: big.NewInt(1), @@ -85,7 +87,7 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { sourceFeeEstimator := mocks.NewEvmFeeEstimator(t) - sourceFeeEstimator.On("GetFee", ctx, []byte(nil), uint64(0), assets.NewWei(tc.maxGasPrice)).Return( + sourceFeeEstimator.On("GetFee", ctx, []byte(nil), uint64(0), assets.NewWei(tc.maxGasPrice), (*common.Address)(nil), (*common.Address)(nil)).Return( tc.sourceFeeEstimatorRespFee, uint64(0), tc.sourceFeeEstimatorRespErr) g := ExecGasPriceEstimator{ @@ -136,9 +138,10 @@ func TestExecPriceEstimator_DenoteInUSD(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := ExecGasPriceEstimator{} - gasPrice, err := g.DenoteInUSD(tc.gasPrice, tc.nativePrice) + gasPrice, err := g.DenoteInUSD(ctx, tc.gasPrice, tc.nativePrice) assert.NoError(t, err) assert.True(t, tc.expPrice.Cmp(gasPrice) == 0) }) @@ -187,9 +190,10 @@ func TestExecPriceEstimator_Median(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := ExecGasPriceEstimator{} - gasPrice, err := g.Median(tc.gasPrices) + gasPrice, err := g.Median(ctx, tc.gasPrices) assert.NoError(t, err) assert.True(t, tc.expMedian.Cmp(gasPrice) == 0) }) @@ -236,11 +240,12 @@ func TestExecPriceEstimator_Deviates(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := ExecGasPriceEstimator{ deviationPPB: tc.deviationPPB, } - deviated, err := g.Deviates(tc.gasPrice1, tc.gasPrice2) + deviated, err := g.Deviates(ctx, tc.gasPrice1, tc.gasPrice2) assert.NoError(t, err) if tc.expDeviates { assert.True(t, deviated) @@ -341,9 +346,10 @@ func TestExecPriceEstimator_EstimateMsgCostUSD(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := tests.Context(t) g := ExecGasPriceEstimator{} - costUSD, err := g.EstimateMsgCostUSD(tc.gasPrice, tc.wrappedNativePrice, tc.msg) + costUSD, err := g.EstimateMsgCostUSD(ctx, tc.gasPrice, tc.wrappedNativePrice, tc.msg) assert.NoError(t, err) assert.Equal(t, tc.expUSD, costUSD) }) 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 0a366a66ac2..a5d284c327e 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 @@ -22,9 +22,9 @@ func (_m *MockGasPriceEstimatorCommit) EXPECT() *MockGasPriceEstimatorCommit_Exp return &MockGasPriceEstimatorCommit_Expecter{mock: &_m.Mock} } -// DenoteInUSD provides a mock function with given fields: p, wrappedNativePrice -func (_m *MockGasPriceEstimatorCommit) DenoteInUSD(p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { - ret := _m.Called(p, wrappedNativePrice) +// DenoteInUSD provides a mock function with given fields: ctx, p, wrappedNativePrice +func (_m *MockGasPriceEstimatorCommit) DenoteInUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { + ret := _m.Called(ctx, p, wrappedNativePrice) if len(ret) == 0 { panic("no return value specified for DenoteInUSD") @@ -32,19 +32,19 @@ func (_m *MockGasPriceEstimatorCommit) DenoteInUSD(p *big.Int, wrappedNativePric var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) (*big.Int, error)); ok { - return rf(p, wrappedNativePrice) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, error)); ok { + return rf(ctx, p, wrappedNativePrice) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) *big.Int); ok { - r0 = rf(p, wrappedNativePrice) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, p, wrappedNativePrice) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int) error); ok { - r1 = rf(p, wrappedNativePrice) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) error); ok { + r1 = rf(ctx, p, wrappedNativePrice) } else { r1 = ret.Error(1) } @@ -58,15 +58,16 @@ type MockGasPriceEstimatorCommit_DenoteInUSD_Call struct { } // DenoteInUSD is a helper method to define mock.On call +// - ctx context.Context // - p *big.Int // - wrappedNativePrice *big.Int -func (_e *MockGasPriceEstimatorCommit_Expecter) DenoteInUSD(p interface{}, wrappedNativePrice interface{}) *MockGasPriceEstimatorCommit_DenoteInUSD_Call { - return &MockGasPriceEstimatorCommit_DenoteInUSD_Call{Call: _e.mock.On("DenoteInUSD", p, wrappedNativePrice)} +func (_e *MockGasPriceEstimatorCommit_Expecter) DenoteInUSD(ctx interface{}, p interface{}, wrappedNativePrice interface{}) *MockGasPriceEstimatorCommit_DenoteInUSD_Call { + return &MockGasPriceEstimatorCommit_DenoteInUSD_Call{Call: _e.mock.On("DenoteInUSD", ctx, p, wrappedNativePrice)} } -func (_c *MockGasPriceEstimatorCommit_DenoteInUSD_Call) Run(run func(p *big.Int, wrappedNativePrice *big.Int)) *MockGasPriceEstimatorCommit_DenoteInUSD_Call { +func (_c *MockGasPriceEstimatorCommit_DenoteInUSD_Call) Run(run func(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int)) *MockGasPriceEstimatorCommit_DenoteInUSD_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) }) return _c } @@ -76,14 +77,14 @@ func (_c *MockGasPriceEstimatorCommit_DenoteInUSD_Call) Return(_a0 *big.Int, _a1 return _c } -func (_c *MockGasPriceEstimatorCommit_DenoteInUSD_Call) RunAndReturn(run func(*big.Int, *big.Int) (*big.Int, error)) *MockGasPriceEstimatorCommit_DenoteInUSD_Call { +func (_c *MockGasPriceEstimatorCommit_DenoteInUSD_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, error)) *MockGasPriceEstimatorCommit_DenoteInUSD_Call { _c.Call.Return(run) return _c } -// Deviates provides a mock function with given fields: p1, p2 -func (_m *MockGasPriceEstimatorCommit) Deviates(p1 *big.Int, p2 *big.Int) (bool, error) { - ret := _m.Called(p1, p2) +// Deviates provides a mock function with given fields: ctx, p1, p2 +func (_m *MockGasPriceEstimatorCommit) Deviates(ctx context.Context, p1 *big.Int, p2 *big.Int) (bool, error) { + ret := _m.Called(ctx, p1, p2) if len(ret) == 0 { panic("no return value specified for Deviates") @@ -91,17 +92,17 @@ func (_m *MockGasPriceEstimatorCommit) Deviates(p1 *big.Int, p2 *big.Int) (bool, var r0 bool var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) (bool, error)); ok { - return rf(p1, p2) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (bool, error)); ok { + return rf(ctx, p1, p2) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) bool); ok { - r0 = rf(p1, p2) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) bool); ok { + r0 = rf(ctx, p1, p2) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int) error); ok { - r1 = rf(p1, p2) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) error); ok { + r1 = rf(ctx, p1, p2) } else { r1 = ret.Error(1) } @@ -115,15 +116,16 @@ type MockGasPriceEstimatorCommit_Deviates_Call struct { } // Deviates is a helper method to define mock.On call +// - ctx context.Context // - p1 *big.Int // - p2 *big.Int -func (_e *MockGasPriceEstimatorCommit_Expecter) Deviates(p1 interface{}, p2 interface{}) *MockGasPriceEstimatorCommit_Deviates_Call { - return &MockGasPriceEstimatorCommit_Deviates_Call{Call: _e.mock.On("Deviates", p1, p2)} +func (_e *MockGasPriceEstimatorCommit_Expecter) Deviates(ctx interface{}, p1 interface{}, p2 interface{}) *MockGasPriceEstimatorCommit_Deviates_Call { + return &MockGasPriceEstimatorCommit_Deviates_Call{Call: _e.mock.On("Deviates", ctx, p1, p2)} } -func (_c *MockGasPriceEstimatorCommit_Deviates_Call) Run(run func(p1 *big.Int, p2 *big.Int)) *MockGasPriceEstimatorCommit_Deviates_Call { +func (_c *MockGasPriceEstimatorCommit_Deviates_Call) Run(run func(ctx context.Context, p1 *big.Int, p2 *big.Int)) *MockGasPriceEstimatorCommit_Deviates_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) }) return _c } @@ -133,7 +135,7 @@ func (_c *MockGasPriceEstimatorCommit_Deviates_Call) Return(_a0 bool, _a1 error) return _c } -func (_c *MockGasPriceEstimatorCommit_Deviates_Call) RunAndReturn(run func(*big.Int, *big.Int) (bool, error)) *MockGasPriceEstimatorCommit_Deviates_Call { +func (_c *MockGasPriceEstimatorCommit_Deviates_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (bool, error)) *MockGasPriceEstimatorCommit_Deviates_Call { _c.Call.Return(run) return _c } @@ -196,9 +198,9 @@ func (_c *MockGasPriceEstimatorCommit_GetGasPrice_Call) RunAndReturn(run func(co return _c } -// Median provides a mock function with given fields: gasPrices -func (_m *MockGasPriceEstimatorCommit) Median(gasPrices []*big.Int) (*big.Int, error) { - ret := _m.Called(gasPrices) +// Median provides a mock function with given fields: ctx, gasPrices +func (_m *MockGasPriceEstimatorCommit) Median(ctx context.Context, gasPrices []*big.Int) (*big.Int, error) { + ret := _m.Called(ctx, gasPrices) if len(ret) == 0 { panic("no return value specified for Median") @@ -206,19 +208,19 @@ func (_m *MockGasPriceEstimatorCommit) Median(gasPrices []*big.Int) (*big.Int, e var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func([]*big.Int) (*big.Int, error)); ok { - return rf(gasPrices) + if rf, ok := ret.Get(0).(func(context.Context, []*big.Int) (*big.Int, error)); ok { + return rf(ctx, gasPrices) } - if rf, ok := ret.Get(0).(func([]*big.Int) *big.Int); ok { - r0 = rf(gasPrices) + if rf, ok := ret.Get(0).(func(context.Context, []*big.Int) *big.Int); ok { + r0 = rf(ctx, gasPrices) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func([]*big.Int) error); ok { - r1 = rf(gasPrices) + if rf, ok := ret.Get(1).(func(context.Context, []*big.Int) error); ok { + r1 = rf(ctx, gasPrices) } else { r1 = ret.Error(1) } @@ -232,14 +234,15 @@ type MockGasPriceEstimatorCommit_Median_Call struct { } // Median is a helper method to define mock.On call +// - ctx context.Context // - gasPrices []*big.Int -func (_e *MockGasPriceEstimatorCommit_Expecter) Median(gasPrices interface{}) *MockGasPriceEstimatorCommit_Median_Call { - return &MockGasPriceEstimatorCommit_Median_Call{Call: _e.mock.On("Median", gasPrices)} +func (_e *MockGasPriceEstimatorCommit_Expecter) Median(ctx interface{}, gasPrices interface{}) *MockGasPriceEstimatorCommit_Median_Call { + return &MockGasPriceEstimatorCommit_Median_Call{Call: _e.mock.On("Median", ctx, gasPrices)} } -func (_c *MockGasPriceEstimatorCommit_Median_Call) Run(run func(gasPrices []*big.Int)) *MockGasPriceEstimatorCommit_Median_Call { +func (_c *MockGasPriceEstimatorCommit_Median_Call) Run(run func(ctx context.Context, gasPrices []*big.Int)) *MockGasPriceEstimatorCommit_Median_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]*big.Int)) + run(args[0].(context.Context), args[1].([]*big.Int)) }) return _c } @@ -249,7 +252,7 @@ func (_c *MockGasPriceEstimatorCommit_Median_Call) Return(_a0 *big.Int, _a1 erro return _c } -func (_c *MockGasPriceEstimatorCommit_Median_Call) RunAndReturn(run func([]*big.Int) (*big.Int, error)) *MockGasPriceEstimatorCommit_Median_Call { +func (_c *MockGasPriceEstimatorCommit_Median_Call) RunAndReturn(run func(context.Context, []*big.Int) (*big.Int, error)) *MockGasPriceEstimatorCommit_Median_Call { _c.Call.Return(run) return _c } 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 8f778555b17..8eaaed9c7c7 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 @@ -24,9 +24,9 @@ func (_m *MockGasPriceEstimatorExec) EXPECT() *MockGasPriceEstimatorExec_Expecte return &MockGasPriceEstimatorExec_Expecter{mock: &_m.Mock} } -// DenoteInUSD provides a mock function with given fields: p, wrappedNativePrice -func (_m *MockGasPriceEstimatorExec) DenoteInUSD(p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { - ret := _m.Called(p, wrappedNativePrice) +// DenoteInUSD provides a mock function with given fields: ctx, p, wrappedNativePrice +func (_m *MockGasPriceEstimatorExec) DenoteInUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { + ret := _m.Called(ctx, p, wrappedNativePrice) if len(ret) == 0 { panic("no return value specified for DenoteInUSD") @@ -34,19 +34,19 @@ func (_m *MockGasPriceEstimatorExec) DenoteInUSD(p *big.Int, wrappedNativePrice var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) (*big.Int, error)); ok { - return rf(p, wrappedNativePrice) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, error)); ok { + return rf(ctx, p, wrappedNativePrice) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) *big.Int); ok { - r0 = rf(p, wrappedNativePrice) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, p, wrappedNativePrice) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int) error); ok { - r1 = rf(p, wrappedNativePrice) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) error); ok { + r1 = rf(ctx, p, wrappedNativePrice) } else { r1 = ret.Error(1) } @@ -60,15 +60,16 @@ type MockGasPriceEstimatorExec_DenoteInUSD_Call struct { } // DenoteInUSD is a helper method to define mock.On call +// - ctx context.Context // - p *big.Int // - wrappedNativePrice *big.Int -func (_e *MockGasPriceEstimatorExec_Expecter) DenoteInUSD(p interface{}, wrappedNativePrice interface{}) *MockGasPriceEstimatorExec_DenoteInUSD_Call { - return &MockGasPriceEstimatorExec_DenoteInUSD_Call{Call: _e.mock.On("DenoteInUSD", p, wrappedNativePrice)} +func (_e *MockGasPriceEstimatorExec_Expecter) DenoteInUSD(ctx interface{}, p interface{}, wrappedNativePrice interface{}) *MockGasPriceEstimatorExec_DenoteInUSD_Call { + return &MockGasPriceEstimatorExec_DenoteInUSD_Call{Call: _e.mock.On("DenoteInUSD", ctx, p, wrappedNativePrice)} } -func (_c *MockGasPriceEstimatorExec_DenoteInUSD_Call) Run(run func(p *big.Int, wrappedNativePrice *big.Int)) *MockGasPriceEstimatorExec_DenoteInUSD_Call { +func (_c *MockGasPriceEstimatorExec_DenoteInUSD_Call) Run(run func(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int)) *MockGasPriceEstimatorExec_DenoteInUSD_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) }) return _c } @@ -78,14 +79,14 @@ func (_c *MockGasPriceEstimatorExec_DenoteInUSD_Call) Return(_a0 *big.Int, _a1 e return _c } -func (_c *MockGasPriceEstimatorExec_DenoteInUSD_Call) RunAndReturn(run func(*big.Int, *big.Int) (*big.Int, error)) *MockGasPriceEstimatorExec_DenoteInUSD_Call { +func (_c *MockGasPriceEstimatorExec_DenoteInUSD_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, error)) *MockGasPriceEstimatorExec_DenoteInUSD_Call { _c.Call.Return(run) return _c } -// EstimateMsgCostUSD provides a mock function with given fields: p, wrappedNativePrice, msg -func (_m *MockGasPriceEstimatorExec) EstimateMsgCostUSD(p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { - ret := _m.Called(p, wrappedNativePrice, msg) +// EstimateMsgCostUSD provides a mock function with given fields: ctx, p, wrappedNativePrice, msg +func (_m *MockGasPriceEstimatorExec) EstimateMsgCostUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { + ret := _m.Called(ctx, p, wrappedNativePrice, msg) if len(ret) == 0 { panic("no return value specified for EstimateMsgCostUSD") @@ -93,19 +94,19 @@ func (_m *MockGasPriceEstimatorExec) EstimateMsgCostUSD(p *big.Int, wrappedNativ var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)); ok { - return rf(p, wrappedNativePrice, msg) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)); ok { + return rf(ctx, p, wrappedNativePrice, msg) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) *big.Int); ok { - r0 = rf(p, wrappedNativePrice, msg) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) *big.Int); ok { + r0 = rf(ctx, p, wrappedNativePrice, msg) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) error); ok { - r1 = rf(p, wrappedNativePrice, msg) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) error); ok { + r1 = rf(ctx, p, wrappedNativePrice, msg) } else { r1 = ret.Error(1) } @@ -119,16 +120,17 @@ type MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call struct { } // EstimateMsgCostUSD is a helper method to define mock.On call +// - ctx context.Context // - p *big.Int // - wrappedNativePrice *big.Int // - msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta -func (_e *MockGasPriceEstimatorExec_Expecter) EstimateMsgCostUSD(p interface{}, wrappedNativePrice interface{}, msg interface{}) *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call { - return &MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call{Call: _e.mock.On("EstimateMsgCostUSD", p, wrappedNativePrice, msg)} +func (_e *MockGasPriceEstimatorExec_Expecter) EstimateMsgCostUSD(ctx interface{}, p interface{}, wrappedNativePrice interface{}, msg interface{}) *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call { + return &MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call{Call: _e.mock.On("EstimateMsgCostUSD", ctx, p, wrappedNativePrice, msg)} } -func (_c *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call) Run(run func(p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call { +func (_c *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call) Run(run func(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int), args[2].(ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int), args[3].(ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) }) return _c } @@ -138,7 +140,7 @@ func (_c *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call) Return(_a0 *big.Int return _c } -func (_c *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call) RunAndReturn(run func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)) *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call { +func (_c *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)) *MockGasPriceEstimatorExec_EstimateMsgCostUSD_Call { _c.Call.Return(run) return _c } @@ -201,9 +203,9 @@ func (_c *MockGasPriceEstimatorExec_GetGasPrice_Call) RunAndReturn(run func(cont return _c } -// Median provides a mock function with given fields: gasPrices -func (_m *MockGasPriceEstimatorExec) Median(gasPrices []*big.Int) (*big.Int, error) { - ret := _m.Called(gasPrices) +// Median provides a mock function with given fields: ctx, gasPrices +func (_m *MockGasPriceEstimatorExec) Median(ctx context.Context, gasPrices []*big.Int) (*big.Int, error) { + ret := _m.Called(ctx, gasPrices) if len(ret) == 0 { panic("no return value specified for Median") @@ -211,19 +213,19 @@ func (_m *MockGasPriceEstimatorExec) Median(gasPrices []*big.Int) (*big.Int, err var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func([]*big.Int) (*big.Int, error)); ok { - return rf(gasPrices) + if rf, ok := ret.Get(0).(func(context.Context, []*big.Int) (*big.Int, error)); ok { + return rf(ctx, gasPrices) } - if rf, ok := ret.Get(0).(func([]*big.Int) *big.Int); ok { - r0 = rf(gasPrices) + if rf, ok := ret.Get(0).(func(context.Context, []*big.Int) *big.Int); ok { + r0 = rf(ctx, gasPrices) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func([]*big.Int) error); ok { - r1 = rf(gasPrices) + if rf, ok := ret.Get(1).(func(context.Context, []*big.Int) error); ok { + r1 = rf(ctx, gasPrices) } else { r1 = ret.Error(1) } @@ -237,14 +239,15 @@ type MockGasPriceEstimatorExec_Median_Call struct { } // Median is a helper method to define mock.On call +// - ctx context.Context // - gasPrices []*big.Int -func (_e *MockGasPriceEstimatorExec_Expecter) Median(gasPrices interface{}) *MockGasPriceEstimatorExec_Median_Call { - return &MockGasPriceEstimatorExec_Median_Call{Call: _e.mock.On("Median", gasPrices)} +func (_e *MockGasPriceEstimatorExec_Expecter) Median(ctx interface{}, gasPrices interface{}) *MockGasPriceEstimatorExec_Median_Call { + return &MockGasPriceEstimatorExec_Median_Call{Call: _e.mock.On("Median", ctx, gasPrices)} } -func (_c *MockGasPriceEstimatorExec_Median_Call) Run(run func(gasPrices []*big.Int)) *MockGasPriceEstimatorExec_Median_Call { +func (_c *MockGasPriceEstimatorExec_Median_Call) Run(run func(ctx context.Context, gasPrices []*big.Int)) *MockGasPriceEstimatorExec_Median_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]*big.Int)) + run(args[0].(context.Context), args[1].([]*big.Int)) }) return _c } @@ -254,7 +257,7 @@ func (_c *MockGasPriceEstimatorExec_Median_Call) Return(_a0 *big.Int, _a1 error) return _c } -func (_c *MockGasPriceEstimatorExec_Median_Call) RunAndReturn(run func([]*big.Int) (*big.Int, error)) *MockGasPriceEstimatorExec_Median_Call { +func (_c *MockGasPriceEstimatorExec_Median_Call) RunAndReturn(run func(context.Context, []*big.Int) (*big.Int, error)) *MockGasPriceEstimatorExec_Median_Call { _c.Call.Return(run) return _c } 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 a513083319d..6787863572d 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 @@ -24,9 +24,9 @@ func (_m *MockGasPriceEstimator) EXPECT() *MockGasPriceEstimator_Expecter { return &MockGasPriceEstimator_Expecter{mock: &_m.Mock} } -// DenoteInUSD provides a mock function with given fields: p, wrappedNativePrice -func (_m *MockGasPriceEstimator) DenoteInUSD(p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { - ret := _m.Called(p, wrappedNativePrice) +// DenoteInUSD provides a mock function with given fields: ctx, p, wrappedNativePrice +func (_m *MockGasPriceEstimator) DenoteInUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int) (*big.Int, error) { + ret := _m.Called(ctx, p, wrappedNativePrice) if len(ret) == 0 { panic("no return value specified for DenoteInUSD") @@ -34,19 +34,19 @@ func (_m *MockGasPriceEstimator) DenoteInUSD(p *big.Int, wrappedNativePrice *big var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) (*big.Int, error)); ok { - return rf(p, wrappedNativePrice) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, error)); ok { + return rf(ctx, p, wrappedNativePrice) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) *big.Int); ok { - r0 = rf(p, wrappedNativePrice) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, p, wrappedNativePrice) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int) error); ok { - r1 = rf(p, wrappedNativePrice) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) error); ok { + r1 = rf(ctx, p, wrappedNativePrice) } else { r1 = ret.Error(1) } @@ -60,15 +60,16 @@ type MockGasPriceEstimator_DenoteInUSD_Call struct { } // DenoteInUSD is a helper method to define mock.On call +// - ctx context.Context // - p *big.Int // - wrappedNativePrice *big.Int -func (_e *MockGasPriceEstimator_Expecter) DenoteInUSD(p interface{}, wrappedNativePrice interface{}) *MockGasPriceEstimator_DenoteInUSD_Call { - return &MockGasPriceEstimator_DenoteInUSD_Call{Call: _e.mock.On("DenoteInUSD", p, wrappedNativePrice)} +func (_e *MockGasPriceEstimator_Expecter) DenoteInUSD(ctx interface{}, p interface{}, wrappedNativePrice interface{}) *MockGasPriceEstimator_DenoteInUSD_Call { + return &MockGasPriceEstimator_DenoteInUSD_Call{Call: _e.mock.On("DenoteInUSD", ctx, p, wrappedNativePrice)} } -func (_c *MockGasPriceEstimator_DenoteInUSD_Call) Run(run func(p *big.Int, wrappedNativePrice *big.Int)) *MockGasPriceEstimator_DenoteInUSD_Call { +func (_c *MockGasPriceEstimator_DenoteInUSD_Call) Run(run func(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int)) *MockGasPriceEstimator_DenoteInUSD_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) }) return _c } @@ -78,14 +79,14 @@ func (_c *MockGasPriceEstimator_DenoteInUSD_Call) Return(_a0 *big.Int, _a1 error return _c } -func (_c *MockGasPriceEstimator_DenoteInUSD_Call) RunAndReturn(run func(*big.Int, *big.Int) (*big.Int, error)) *MockGasPriceEstimator_DenoteInUSD_Call { +func (_c *MockGasPriceEstimator_DenoteInUSD_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, error)) *MockGasPriceEstimator_DenoteInUSD_Call { _c.Call.Return(run) return _c } -// Deviates provides a mock function with given fields: p1, p2 -func (_m *MockGasPriceEstimator) Deviates(p1 *big.Int, p2 *big.Int) (bool, error) { - ret := _m.Called(p1, p2) +// Deviates provides a mock function with given fields: ctx, p1, p2 +func (_m *MockGasPriceEstimator) Deviates(ctx context.Context, p1 *big.Int, p2 *big.Int) (bool, error) { + ret := _m.Called(ctx, p1, p2) if len(ret) == 0 { panic("no return value specified for Deviates") @@ -93,17 +94,17 @@ func (_m *MockGasPriceEstimator) Deviates(p1 *big.Int, p2 *big.Int) (bool, error var r0 bool var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) (bool, error)); ok { - return rf(p1, p2) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (bool, error)); ok { + return rf(ctx, p1, p2) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int) bool); ok { - r0 = rf(p1, p2) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) bool); ok { + r0 = rf(ctx, p1, p2) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int) error); ok { - r1 = rf(p1, p2) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) error); ok { + r1 = rf(ctx, p1, p2) } else { r1 = ret.Error(1) } @@ -117,15 +118,16 @@ type MockGasPriceEstimator_Deviates_Call struct { } // Deviates is a helper method to define mock.On call +// - ctx context.Context // - p1 *big.Int // - p2 *big.Int -func (_e *MockGasPriceEstimator_Expecter) Deviates(p1 interface{}, p2 interface{}) *MockGasPriceEstimator_Deviates_Call { - return &MockGasPriceEstimator_Deviates_Call{Call: _e.mock.On("Deviates", p1, p2)} +func (_e *MockGasPriceEstimator_Expecter) Deviates(ctx interface{}, p1 interface{}, p2 interface{}) *MockGasPriceEstimator_Deviates_Call { + return &MockGasPriceEstimator_Deviates_Call{Call: _e.mock.On("Deviates", ctx, p1, p2)} } -func (_c *MockGasPriceEstimator_Deviates_Call) Run(run func(p1 *big.Int, p2 *big.Int)) *MockGasPriceEstimator_Deviates_Call { +func (_c *MockGasPriceEstimator_Deviates_Call) Run(run func(ctx context.Context, p1 *big.Int, p2 *big.Int)) *MockGasPriceEstimator_Deviates_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) }) return _c } @@ -135,14 +137,14 @@ func (_c *MockGasPriceEstimator_Deviates_Call) Return(_a0 bool, _a1 error) *Mock return _c } -func (_c *MockGasPriceEstimator_Deviates_Call) RunAndReturn(run func(*big.Int, *big.Int) (bool, error)) *MockGasPriceEstimator_Deviates_Call { +func (_c *MockGasPriceEstimator_Deviates_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (bool, error)) *MockGasPriceEstimator_Deviates_Call { _c.Call.Return(run) return _c } -// EstimateMsgCostUSD provides a mock function with given fields: p, wrappedNativePrice, msg -func (_m *MockGasPriceEstimator) EstimateMsgCostUSD(p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { - ret := _m.Called(p, wrappedNativePrice, msg) +// EstimateMsgCostUSD provides a mock function with given fields: ctx, p, wrappedNativePrice, msg +func (_m *MockGasPriceEstimator) EstimateMsgCostUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { + ret := _m.Called(ctx, p, wrappedNativePrice, msg) if len(ret) == 0 { panic("no return value specified for EstimateMsgCostUSD") @@ -150,19 +152,19 @@ func (_m *MockGasPriceEstimator) EstimateMsgCostUSD(p *big.Int, wrappedNativePri var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)); ok { - return rf(p, wrappedNativePrice, msg) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)); ok { + return rf(ctx, p, wrappedNativePrice, msg) } - if rf, ok := ret.Get(0).(func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) *big.Int); ok { - r0 = rf(p, wrappedNativePrice, msg) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) *big.Int); ok { + r0 = rf(ctx, p, wrappedNativePrice, msg) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) error); ok { - r1 = rf(p, wrappedNativePrice, msg) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) error); ok { + r1 = rf(ctx, p, wrappedNativePrice, msg) } else { r1 = ret.Error(1) } @@ -176,16 +178,17 @@ type MockGasPriceEstimator_EstimateMsgCostUSD_Call struct { } // EstimateMsgCostUSD is a helper method to define mock.On call +// - ctx context.Context // - p *big.Int // - wrappedNativePrice *big.Int // - msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta -func (_e *MockGasPriceEstimator_Expecter) EstimateMsgCostUSD(p interface{}, wrappedNativePrice interface{}, msg interface{}) *MockGasPriceEstimator_EstimateMsgCostUSD_Call { - return &MockGasPriceEstimator_EstimateMsgCostUSD_Call{Call: _e.mock.On("EstimateMsgCostUSD", p, wrappedNativePrice, msg)} +func (_e *MockGasPriceEstimator_Expecter) EstimateMsgCostUSD(ctx interface{}, p interface{}, wrappedNativePrice interface{}, msg interface{}) *MockGasPriceEstimator_EstimateMsgCostUSD_Call { + return &MockGasPriceEstimator_EstimateMsgCostUSD_Call{Call: _e.mock.On("EstimateMsgCostUSD", ctx, p, wrappedNativePrice, msg)} } -func (_c *MockGasPriceEstimator_EstimateMsgCostUSD_Call) Run(run func(p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) *MockGasPriceEstimator_EstimateMsgCostUSD_Call { +func (_c *MockGasPriceEstimator_EstimateMsgCostUSD_Call) Run(run func(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) *MockGasPriceEstimator_EstimateMsgCostUSD_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(*big.Int), args[2].(ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int), args[3].(ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta)) }) return _c } @@ -195,7 +198,7 @@ func (_c *MockGasPriceEstimator_EstimateMsgCostUSD_Call) Return(_a0 *big.Int, _a return _c } -func (_c *MockGasPriceEstimator_EstimateMsgCostUSD_Call) RunAndReturn(run func(*big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)) *MockGasPriceEstimator_EstimateMsgCostUSD_Call { +func (_c *MockGasPriceEstimator_EstimateMsgCostUSD_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int, ccip.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error)) *MockGasPriceEstimator_EstimateMsgCostUSD_Call { _c.Call.Return(run) return _c } @@ -258,9 +261,9 @@ func (_c *MockGasPriceEstimator_GetGasPrice_Call) RunAndReturn(run func(context. return _c } -// Median provides a mock function with given fields: gasPrices -func (_m *MockGasPriceEstimator) Median(gasPrices []*big.Int) (*big.Int, error) { - ret := _m.Called(gasPrices) +// Median provides a mock function with given fields: ctx, gasPrices +func (_m *MockGasPriceEstimator) Median(ctx context.Context, gasPrices []*big.Int) (*big.Int, error) { + ret := _m.Called(ctx, gasPrices) if len(ret) == 0 { panic("no return value specified for Median") @@ -268,19 +271,19 @@ func (_m *MockGasPriceEstimator) Median(gasPrices []*big.Int) (*big.Int, error) var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func([]*big.Int) (*big.Int, error)); ok { - return rf(gasPrices) + if rf, ok := ret.Get(0).(func(context.Context, []*big.Int) (*big.Int, error)); ok { + return rf(ctx, gasPrices) } - if rf, ok := ret.Get(0).(func([]*big.Int) *big.Int); ok { - r0 = rf(gasPrices) + if rf, ok := ret.Get(0).(func(context.Context, []*big.Int) *big.Int); ok { + r0 = rf(ctx, gasPrices) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func([]*big.Int) error); ok { - r1 = rf(gasPrices) + if rf, ok := ret.Get(1).(func(context.Context, []*big.Int) error); ok { + r1 = rf(ctx, gasPrices) } else { r1 = ret.Error(1) } @@ -294,14 +297,15 @@ type MockGasPriceEstimator_Median_Call struct { } // Median is a helper method to define mock.On call +// - ctx context.Context // - gasPrices []*big.Int -func (_e *MockGasPriceEstimator_Expecter) Median(gasPrices interface{}) *MockGasPriceEstimator_Median_Call { - return &MockGasPriceEstimator_Median_Call{Call: _e.mock.On("Median", gasPrices)} +func (_e *MockGasPriceEstimator_Expecter) Median(ctx interface{}, gasPrices interface{}) *MockGasPriceEstimator_Median_Call { + return &MockGasPriceEstimator_Median_Call{Call: _e.mock.On("Median", ctx, gasPrices)} } -func (_c *MockGasPriceEstimator_Median_Call) Run(run func(gasPrices []*big.Int)) *MockGasPriceEstimator_Median_Call { +func (_c *MockGasPriceEstimator_Median_Call) Run(run func(ctx context.Context, gasPrices []*big.Int)) *MockGasPriceEstimator_Median_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]*big.Int)) + run(args[0].(context.Context), args[1].([]*big.Int)) }) return _c } @@ -311,7 +315,7 @@ func (_c *MockGasPriceEstimator_Median_Call) Return(_a0 *big.Int, _a1 error) *Mo return _c } -func (_c *MockGasPriceEstimator_Median_Call) RunAndReturn(run func([]*big.Int) (*big.Int, error)) *MockGasPriceEstimator_Median_Call { +func (_c *MockGasPriceEstimator_Median_Call) RunAndReturn(run func(context.Context, []*big.Int) (*big.Int, error)) *MockGasPriceEstimator_Median_Call { _c.Call.Return(run) return _c } diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index 805c49d91aa..8410e6ff938 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -29,7 +29,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/arm_proxy_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_helper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_helper_1_2_0" @@ -38,8 +37,9 @@ import ( "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" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_arm_contract" + "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/token_admin_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" @@ -97,7 +97,8 @@ func NewCommitOffchainConfig( ExecGasPriceDeviationPPB uint32, TokenPriceHeartBeat config.Duration, TokenPriceDeviationPPB uint32, - InflightCacheExpiry config.Duration) CommitOffchainConfig { + InflightCacheExpiry config.Duration, + priceReportingDisabled bool) CommitOffchainConfig { return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{ GasPriceHeartBeat: GasPriceHeartBeat, DAGasPriceDeviationPPB: DAGasPriceDeviationPPB, @@ -105,6 +106,7 @@ func NewCommitOffchainConfig( TokenPriceHeartBeat: TokenPriceHeartBeat, TokenPriceDeviationPPB: TokenPriceDeviationPPB, InflightCacheExpiry: InflightCacheExpiry, + PriceReportingDisabled: priceReportingDisabled, }} } @@ -124,23 +126,13 @@ type ExecOnchainConfig struct { v1_5_0.ExecOnchainConfig } -func NewExecOnchainConfig( - PermissionLessExecutionThresholdSeconds uint32, - Router common.Address, - PriceRegistry common.Address, - MaxNumberOfTokensPerMsg uint16, - MaxDataBytes uint32, - MaxPoolReleaseOrMintGas uint32, - MaxTokenTransferGas uint32, -) ExecOnchainConfig { +func NewExecOnchainConfig(PermissionLessExecutionThresholdSeconds uint32, Router common.Address, PriceRegistry common.Address, MaxNumberOfTokensPerMsg uint16, MaxDataBytes uint32) ExecOnchainConfig { return ExecOnchainConfig{v1_5_0.ExecOnchainConfig{ PermissionLessExecutionThresholdSeconds: PermissionLessExecutionThresholdSeconds, Router: Router, PriceRegistry: PriceRegistry, MaxNumberOfTokensPerMsg: MaxNumberOfTokensPerMsg, MaxDataBytes: MaxDataBytes, - MaxPoolReleaseOrMintGas: MaxPoolReleaseOrMintGas, - MaxTokenTransferGas: MaxTokenTransferGas, }} } @@ -158,6 +150,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour float64, InflightCacheExpiry config.Duration, RootSnoozeTime config.Duration, + BatchingStrategyID uint32, ) ExecOffchainConfig { return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ DestOptimisticConfirmations: DestOptimisticConfirmations, @@ -165,6 +158,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, InflightCacheExpiry: InflightCacheExpiry, RootSnoozeTime: RootSnoozeTime, + BatchingStrategyID: BatchingStrategyID, }} } @@ -183,10 +177,11 @@ type Common struct { CustomToken *link_token_interface.LinkToken WrappedNative *weth9.WETH9 WrappedNativePool *lock_release_token_pool.LockReleaseTokenPool - ARM *mock_arm_contract.MockARMContract - ARMProxy *arm_proxy_contract.ARMProxyContract + ARM *mock_rmn_contract.MockRMNContract + ARMProxy *rmn_proxy_contract.RMNProxyContract PriceRegistry *price_registry_1_2_0.PriceRegistry TokenAdminRegistry *token_admin_registry.TokenAdminRegistry + FinalityDepth uint32 } type SourceChain struct { @@ -323,8 +318,7 @@ func (c *CCIPContracts) DeployNewOnRamp(t *testing.T) { MaxDataBytes: 1e5, MaxPerMsgGasLimit: 4_000_000, DefaultTokenFeeUSDCents: 50, - DefaultTokenDestGasOverhead: 34_000, - DefaultTokenDestBytesOverhead: 500, + DefaultTokenDestGasOverhead: DefaultTokenDestGasOverhead, }, evm_2_evm_onramp.RateLimiterConfig{ IsEnabled: true, @@ -353,7 +347,7 @@ func (c *CCIPContracts) DeployNewOnRamp(t *testing.T) { MinFeeUSDCents: 50, // $0.5 MaxFeeUSDCents: 1_000_000_00, // $ 1 million DeciBps: 5_0, // 5 bps - DestGasOverhead: 34_000, + DestGasOverhead: 110_000, DestBytesOverhead: 32, AggregateRateLimitEnabled: true, }, @@ -517,6 +511,7 @@ func (c *CCIPContracts) DeriveOCR2Config(t *testing.T, oracles []confighelper.Or []int{1, 1, 1, 1}, oracles, rawOffchainConfig, + nil, 50*time.Millisecond, // Max duration query 1*time.Second, // Max duration observation 100*time.Millisecond, @@ -661,7 +656,8 @@ func SetAdminAndRegisterPool(t *testing.T, chain.Commit() } -func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64) CCIPContracts { +func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64, + sourceFinalityDepth, destFinalityDepth uint32) CCIPContracts { sourceChain, sourceUser := SetupChain(t) destChain, destUser := SetupChain(t) @@ -669,38 +665,38 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh // │ Deploy RMN │ // ================================================================ - armSourceAddress, _, _, err := mock_arm_contract.DeployMockARMContract( + armSourceAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( sourceUser, sourceChain, ) require.NoError(t, err) - sourceARM, err := mock_arm_contract.NewMockARMContract(armSourceAddress, sourceChain) + sourceARM, err := mock_rmn_contract.NewMockRMNContract(armSourceAddress, sourceChain) require.NoError(t, err) - armProxySourceAddress, _, _, err := arm_proxy_contract.DeployARMProxyContract( + armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( sourceUser, sourceChain, armSourceAddress, ) require.NoError(t, err) - sourceARMProxy, err := arm_proxy_contract.NewARMProxyContract(armProxySourceAddress, sourceChain) + sourceARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxySourceAddress, sourceChain) require.NoError(t, err) sourceChain.Commit() - armDestAddress, _, _, err := mock_arm_contract.DeployMockARMContract( + armDestAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( destUser, destChain, ) require.NoError(t, err) - armProxyDestAddress, _, _, err := arm_proxy_contract.DeployARMProxyContract( + armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( destUser, destChain, armDestAddress, ) require.NoError(t, err) destChain.Commit() - destARM, err := mock_arm_contract.NewMockARMContract(armDestAddress, destChain) + destARM, err := mock_rmn_contract.NewMockRMNContract(armDestAddress, destChain) require.NoError(t, err) - destARMProxy, err := arm_proxy_contract.NewARMProxyContract(armProxyDestAddress, destChain) + destARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxyDestAddress, destChain) require.NoError(t, err) // ================================================================ @@ -1048,8 +1044,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh MaxDataBytes: 1e5, MaxPerMsgGasLimit: 4_000_000, DefaultTokenFeeUSDCents: 50, - DefaultTokenDestGasOverhead: 34_000, - DefaultTokenDestBytesOverhead: 500, + DefaultTokenDestGasOverhead: DefaultTokenDestGasOverhead, }, evm_2_evm_onramp.RateLimiterConfig{ IsEnabled: true, @@ -1078,7 +1073,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh MinFeeUSDCents: 50, // $0.5 MaxFeeUSDCents: 1_000_000_00, // $ 1 million DeciBps: 5_0, // 5 bps - DestGasOverhead: 34_000, + DestGasOverhead: 350_000, DestBytesOverhead: 32, AggregateRateLimitEnabled: true, }, @@ -1187,6 +1182,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh WrappedNative: sourceWrapped, WrappedNativePool: sourceWeth9Pool, TokenAdminRegistry: sourceTokenAdminRegistry, + FinalityDepth: sourceFinalityDepth, }, Router: sourceRouter, OnRamp: onRamp, @@ -1206,6 +1202,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh WrappedNative: destWrapped, WrappedNativePool: destWrappedPool, TokenAdminRegistry: destTokenAdminRegistry, + FinalityDepth: destFinalityDepth, }, CommitStoreHelper: commitStoreHelper, CommitStore: commitStore, @@ -1279,13 +1276,14 @@ type ManualExecArgs struct { 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 + 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 + TokenGasOverrides []uint32 } // ApproxDestStartBlock attempts to locate a block in destination chain with timestamp closest to the timestamp of the block @@ -1448,7 +1446,9 @@ func (args *ManualExecArgs) execute(report *commit_store.CommitStoreCommitReport var leaves [][32]byte var curr, prove int var msgs []evm_2_evm_offramp.InternalEVM2EVMMessage - var manualExecGasLimits []*big.Int + + // CCIP-2950 TestHelper for CCIPContracts and initialisation of EVM2EVMOffRampGasLimitOverride + var manualExecGasLimits []*evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride var tokenData [][][]byte sendRequestedIterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ Start: args.SourceStartBlock.Uint64(), @@ -1493,7 +1493,26 @@ func (args *ManualExecArgs) execute(report *commit_store.CommitStoreCommitReport if args.GasLimit != nil { msg.GasLimit = args.GasLimit } - manualExecGasLimits = append(manualExecGasLimits, msg.GasLimit) + + tokenGasOverrides := make([]uint32, len(msg.TokenAmounts)) + + if args.TokenGasOverrides != nil && len(args.TokenGasOverrides) == len(msg.TokenAmounts) { + copy(tokenGasOverrides, args.TokenGasOverrides) + } else { + // Initialize each element in the slice to a new big.Int value in one line using a loop + for i := range tokenGasOverrides { + tokenGasOverrides[i] = 0 + } + } + + // CCIP-2950 create a new object for evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride + evm2evmOffRampGasLimitOverride := &evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride{ + ReceiverExecutionGasLimit: msg.GasLimit, + TokenGasOverrides: tokenGasOverrides, + } + + manualExecGasLimits = append(manualExecGasLimits, evm2evmOffRampGasLimitOverride) + var msgTokenData [][]byte for range sendRequestedIterator.Event.Message.TokenAmounts { msgTokenData = append(msgTokenData, []byte{}) @@ -1532,8 +1551,17 @@ func (args *ManualExecArgs) execute(report *commit_store.CommitStoreCommitReport if err != nil { return nil, err } + + // Convert manualExecGasLimits to a slice of structs before calling ManuallyExecute + manualExecGasLimitOverrides := make([]evm_2_evm_offramp.EVM2EVMOffRampGasLimitOverride, len(manualExecGasLimits)) + for i, limitOverride := range manualExecGasLimits { + if limitOverride != nil { + manualExecGasLimitOverrides[i] = *limitOverride + } + } + // Execute. - return offRamp.ManuallyExecute(args.DestUser, offRampProof, manualExecGasLimits) + return offRamp.ManuallyExecute(args.DestUser, offRampProof, manualExecGasLimitOverrides) } func (c *CCIPContracts) ExecuteMessage( diff --git a/core/services/ocr2/plugins/ccip/testhelpers/config.go b/core/services/ocr2/plugins/ccip/testhelpers/config.go index f70f1954f18..4dcb627347f 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/config.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/config.go @@ -15,6 +15,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0" ) +const ( + DefaultTokenDestGasOverhead = 125_000 +) + var PermissionLessExecutionThresholdSeconds = uint32(FirstBlockAge.Seconds()) func (c *CCIPContracts) CreateDefaultCommitOnchainConfig(t *testing.T) []byte { @@ -37,6 +41,7 @@ func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBe *config.MustNewDuration(feeUpdateHearBeat), 1, *config.MustNewDuration(inflightCacheExpiry), + false, ).Encode() require.NoError(t, err) return config @@ -49,8 +54,6 @@ func (c *CCIPContracts) CreateDefaultExecOnchainConfig(t *testing.T) []byte { PriceRegistry: c.Dest.PriceRegistry.Address(), MaxDataBytes: 1e5, MaxNumberOfTokensPerMsg: 5, - MaxPoolReleaseOrMintGas: 200_000, - MaxTokenTransferGas: 100_000, }) require.NoError(t, err) return config @@ -67,6 +70,7 @@ func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpi 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/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index 177ccf323b7..d0d502e8673 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -7,6 +7,7 @@ import ( "math/big" "net/http" "net/http/httptest" + "slices" "strconv" "strings" "testing" @@ -38,6 +39,8 @@ import ( 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" + "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" @@ -48,14 +51,13 @@ import ( "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/internal/cltest/heavyweight" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_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" - pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" "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" @@ -64,7 +66,6 @@ import ( 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_0_0" "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/ccipdata/v1_5_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" @@ -73,6 +74,7 @@ import ( 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" ) @@ -183,7 +185,7 @@ func (node *Node) EventuallyNodeUsesUpdatedPriceRegistry(t *testing.T, ccipContr ccipContracts.Dest.Chain.Commit() log, err := c.LogPoller().LatestLogByEventSigWithConfs( testutils.Context(t), - v1_0_0.UsdPerUnitGasUpdated, + v1_2_0.UsdPerUnitGasUpdated, ccipContracts.Dest.PriceRegistry.Address(), 0, ) @@ -282,9 +284,9 @@ func (node *Node) EventuallyHasExecutedSeqNums(t *testing.T, ccipContracts *CCIP ccipContracts.Dest.Chain.Commit() lgs, err := c.LogPoller().IndexedLogsTopicRange( testutils.Context(t), - v1_0_0.ExecutionStateChangedEvent, + v1_2_0.ExecutionStateChangedEvent, offRamp, - v1_0_0.ExecutionStateChangedSeqNrIndex, + v1_2_0.ExecutionStateChangedSeqNrIndex, abihelpers.EvmWord(uint64(minSeqNum)), abihelpers.EvmWord(uint64(maxSeqNum)), 1, @@ -310,9 +312,9 @@ func (node *Node) ConsistentlySeqNumHasNotBeenExecuted(t *testing.T, ccipContrac ccipContracts.Dest.Chain.Commit() lgs, err := c.LogPoller().IndexedLogsTopicRange( testutils.Context(t), - v1_0_0.ExecutionStateChangedEvent, + v1_2_0.ExecutionStateChangedEvent, offRamp, - v1_0_0.ExecutionStateChangedSeqNrIndex, + v1_2_0.ExecutionStateChangedSeqNrIndex, abihelpers.EvmWord(uint64(seqNum)), abihelpers.EvmWord(uint64(seqNum)), 1, @@ -369,6 +371,7 @@ func setupNodeCCIP( sourceChainID *big.Int, destChainID *big.Int, bootstrapPeerID string, bootstrapPort int64, + sourceFinalityDepth, destFinalityDepth uint32, ) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { trueRef, falseRef := true, false @@ -402,7 +405,7 @@ func setupNodeCCIP( c.P2P.V2.ListenAddresses = &p2pAddresses c.P2P.V2.AnnounceAddresses = &p2pAddresses - c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID), createConfigV2Chain(destChainID)} + c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID, sourceFinalityDepth), createConfigV2Chain(destChainID, destFinalityDepth)} if bootstrapPeerID != "" { // Supply the bootstrap IP and port as a V2 peer address @@ -456,7 +459,7 @@ func setupNodeCCIP( }, CSAETHKeystore: simEthKeyStore, } - loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing()) + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry()) relayerFactory := chainlink.RelayerFactory{ Logger: lggr, LoopRegistry: loopRegistry, @@ -486,7 +489,7 @@ func setupNodeCCIP( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing()), + LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry()), }) require.NoError(t, err) require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) @@ -524,21 +527,20 @@ func setupNodeCCIP( return app, peerID.Raw(), transmitter, kb } -func createConfigV2Chain(chainId *big.Int) *v2.EVMConfig { +func createConfigV2Chain(chainID *big.Int, finalityDepth uint32) *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 := 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 + sourceC.FinalityDepth = &finalityDepth return &v2.EVMConfig{ - ChainID: (*evmUtils.Big)(chainId), + ChainID: (*evmUtils.Big)(chainID), Enabled: &tr, Chain: sourceC, Nodes: v2.EVMNodes{&v2.Node{}}, @@ -551,9 +553,11 @@ type CCIPIntegrationTestHarness struct { Bootstrap Node } -func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainId, destChainSelector uint64) CCIPIntegrationTestHarness { +func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64, + sourceFinalityDepth, destFinalityDepth uint32) CCIPIntegrationTestHarness { return CCIPIntegrationTestHarness{ - CCIPContracts: testhelpers.SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainId, destChainSelector), + CCIPContracts: testhelpers.SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainID, + destChainSelector, sourceFinalityDepth, destFinalityDepth), } } @@ -762,6 +766,47 @@ func (c *CCIPIntegrationTestHarness) NoNodesHaveExecutedSeqNum(t *testing.T, seq return log } +func (c *CCIPIntegrationTestHarness) EventuallyPriceRegistryUpdated(t *testing.T, block uint64, srcSelector uint64, tokens []common.Address, sourceNative common.Address, priceRegistryOpts ...common.Address) { + var priceRegistry *price_registry_1_2_0.PriceRegistry + var err error + if len(priceRegistryOpts) > 0 { + priceRegistry, err = price_registry_1_2_0.NewPriceRegistry(priceRegistryOpts[0], c.Dest.Chain) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.PriceRegistry, "no priceRegistry configured") + priceRegistry = c.Dest.PriceRegistry + } + + g := gomega.NewGomegaWithT(t) + g.Eventually(func() bool { + it, err := priceRegistry.FilterUsdPerTokenUpdated(&bind.FilterOpts{Start: block}, tokens) + g.Expect(err).NotTo(gomega.HaveOccurred(), "Error filtering UsdPerTokenUpdated event") + + tokensFetched := make([]common.Address, 0, len(tokens)) + for it.Next() { + tokenFetched := it.Event.Token + tokensFetched = append(tokensFetched, tokenFetched) + t.Log("Token price updated", tokenFetched.String(), it.Event.Value.String(), it.Event.Timestamp.String()) + } + + for _, token := range tokens { + if !slices.Contains(tokensFetched, token) { + return false + } + } + + return true + }, testutils.WaitTimeout(t), 10*time.Second).Should(gomega.BeTrue(), "Tokens prices has not been updated") + + g.Eventually(func() bool { + it, err := priceRegistry.FilterUsdPerUnitGasUpdated(&bind.FilterOpts{Start: block}, []uint64{srcSelector}) + g.Expect(err).NotTo(gomega.HaveOccurred(), "Error filtering UsdPerUnitGasUpdated event") + g.Expect(it.Next()).To(gomega.BeTrue(), "No UsdPerUnitGasUpdated event found") + + return true + }, testutils.WaitTimeout(t), 10*time.Second).Should(gomega.BeTrue(), "source gas price has not been updated") +} + func (c *CCIPIntegrationTestHarness) EventuallyCommitReportAccepted(t *testing.T, currentBlock uint64, commitStoreOpts ...common.Address) commit_store.CommitStoreCommitReport { var commitStore *commit_store.CommitStore var err error @@ -885,7 +930,8 @@ func (c *CCIPIntegrationTestHarness) ConsistentlyReportNotCommitted(t *testing.T 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) + big.NewInt(0).SetUint64(c.Dest.ChainID), "", 0, c.Source.FinalityDepth, + c.Dest.FinalityDepth) var ( oracles []confighelper.OracleIdentityExtra nodes []Node @@ -913,6 +959,8 @@ func (c *CCIPIntegrationTestHarness) SetupAndStartNodes(ctx context.Context, t * big.NewInt(0).SetUint64(c.Dest.ChainID), bootstrapPeerID, bootstrapNodePort, + c.Source.FinalityDepth, + c.Dest.FinalityDepth, ) nodes = append(nodes, Node{ App: app, 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 index 4ea5bb18d7e..952cfe2c9e2 100644 --- 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 @@ -28,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/arm_proxy_contract" 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" @@ -37,8 +36,9 @@ import ( "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_arm_contract" + "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" @@ -96,7 +96,8 @@ func NewCommitOffchainConfig( ExecGasPriceDeviationPPB uint32, TokenPriceHeartBeat config.Duration, TokenPriceDeviationPPB uint32, - InflightCacheExpiry config.Duration) CommitOffchainConfig { + InflightCacheExpiry config.Duration, + priceReportingDisabled bool) CommitOffchainConfig { return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{ GasPriceHeartBeat: GasPriceHeartBeat, DAGasPriceDeviationPPB: DAGasPriceDeviationPPB, @@ -104,6 +105,7 @@ func NewCommitOffchainConfig( TokenPriceHeartBeat: TokenPriceHeartBeat, TokenPriceDeviationPPB: TokenPriceDeviationPPB, InflightCacheExpiry: InflightCacheExpiry, + PriceReportingDisabled: priceReportingDisabled, }} } @@ -155,6 +157,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour float64, InflightCacheExpiry config.Duration, RootSnoozeTime config.Duration, + BatchingStrategyID uint32, ) ExecOffchainConfig { return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ DestOptimisticConfirmations: DestOptimisticConfirmations, @@ -162,6 +165,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, InflightCacheExpiry: InflightCacheExpiry, RootSnoozeTime: RootSnoozeTime, + BatchingStrategyID: BatchingStrategyID, }} } @@ -180,8 +184,8 @@ type Common struct { CustomToken *link_token_interface.LinkToken WrappedNative *weth9.WETH9 WrappedNativePool *lock_release_token_pool_1_0_0.LockReleaseTokenPool - ARM *mock_arm_contract.MockARMContract - ARMProxy *arm_proxy_contract.ARMProxyContract + ARM *mock_rmn_contract.MockRMNContract + ARMProxy *rmn_proxy_contract.RMNProxyContract PriceRegistry *price_registry_1_2_0.PriceRegistry } @@ -512,6 +516,7 @@ func (c *CCIPContracts) DeriveOCR2Config(t *testing.T, oracles []confighelper.Or []int{1, 1, 1, 1}, oracles, rawOffchainConfig, + nil, 50*time.Millisecond, // Max duration query 1*time.Second, // Max duration observation 100*time.Millisecond, @@ -787,38 +792,38 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh sourceChain, sourceUser := testhelpers.SetupChain(t) destChain, destUser := testhelpers.SetupChain(t) - armSourceAddress, _, _, err := mock_arm_contract.DeployMockARMContract( + armSourceAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( sourceUser, sourceChain, ) require.NoError(t, err) - sourceARM, err := mock_arm_contract.NewMockARMContract(armSourceAddress, sourceChain) + sourceARM, err := mock_rmn_contract.NewMockRMNContract(armSourceAddress, sourceChain) require.NoError(t, err) - armProxySourceAddress, _, _, err := arm_proxy_contract.DeployARMProxyContract( + armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( sourceUser, sourceChain, armSourceAddress, ) require.NoError(t, err) - sourceARMProxy, err := arm_proxy_contract.NewARMProxyContract(armProxySourceAddress, sourceChain) + sourceARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxySourceAddress, sourceChain) require.NoError(t, err) sourceChain.Commit() - armDestAddress, _, _, err := mock_arm_contract.DeployMockARMContract( + armDestAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( destUser, destChain, ) require.NoError(t, err) - armProxyDestAddress, _, _, err := arm_proxy_contract.DeployARMProxyContract( + armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( destUser, destChain, armDestAddress, ) require.NoError(t, err) destChain.Commit() - destARM, err := mock_arm_contract.NewMockARMContract(armDestAddress, destChain) + destARM, err := mock_rmn_contract.NewMockRMNContract(armDestAddress, destChain) require.NoError(t, err) - destARMProxy, err := arm_proxy_contract.NewARMProxyContract(armProxyDestAddress, destChain) + destARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxyDestAddress, destChain) require.NoError(t, err) // Deploy link token and pool on source chain 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 index 25be1c2a9a9..a69e284e548 100644 --- 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 @@ -38,6 +38,7 @@ import ( 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" "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" @@ -48,14 +49,12 @@ import ( "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/cltest/heavyweight" "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" - pb "github.com/smartcontractkit/chainlink/v2/core/services/feeds/proto" "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" @@ -64,7 +63,6 @@ import ( 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_0_0" "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" @@ -73,6 +71,7 @@ import ( 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" ) @@ -183,7 +182,7 @@ func (node *Node) EventuallyNodeUsesUpdatedPriceRegistry(t *testing.T, ccipContr ccipContracts.Dest.Chain.Commit() log, err := c.LogPoller().LatestLogByEventSigWithConfs( testutils.Context(t), - v1_0_0.UsdPerUnitGasUpdated, + v1_2_0.UsdPerUnitGasUpdated, ccipContracts.Dest.PriceRegistry.Address(), 0, ) @@ -282,9 +281,9 @@ func (node *Node) EventuallyHasExecutedSeqNums(t *testing.T, ccipContracts *CCIP ccipContracts.Dest.Chain.Commit() lgs, err := c.LogPoller().IndexedLogsTopicRange( testutils.Context(t), - v1_0_0.ExecutionStateChangedEvent, + v1_2_0.ExecutionStateChangedEvent, offRamp, - v1_0_0.ExecutionStateChangedSeqNrIndex, + v1_2_0.ExecutionStateChangedSeqNrIndex, abihelpers.EvmWord(uint64(minSeqNum)), abihelpers.EvmWord(uint64(maxSeqNum)), 1, @@ -310,9 +309,9 @@ func (node *Node) ConsistentlySeqNumHasNotBeenExecuted(t *testing.T, ccipContrac ccipContracts.Dest.Chain.Commit() lgs, err := c.LogPoller().IndexedLogsTopicRange( testutils.Context(t), - v1_0_0.ExecutionStateChangedEvent, + v1_2_0.ExecutionStateChangedEvent, offRamp, - v1_0_0.ExecutionStateChangedSeqNrIndex, + v1_2_0.ExecutionStateChangedSeqNrIndex, abihelpers.EvmWord(uint64(seqNum)), abihelpers.EvmWord(uint64(seqNum)), 1, @@ -455,7 +454,7 @@ func setupNodeCCIP( }, CSAETHKeystore: simEthKeyStore, } - loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing()) + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry()) relayerFactory := chainlink.RelayerFactory{ Logger: lggr, LoopRegistry: loopRegistry, @@ -485,7 +484,7 @@ func setupNodeCCIP( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing()), + LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry()), }) ctx := testutils.Context(t) require.NoError(t, err) 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 index 751ae5c1a92..087c21e9333 100644 --- 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 @@ -38,6 +38,7 @@ func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBe *config.MustNewDuration(feeUpdateHearBeat), 1, *config.MustNewDuration(inflightCacheExpiry), + false, ).Encode() require.NoError(t, err) return config @@ -67,6 +68,7 @@ func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpi 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/usdc/usdc.go b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go index fe3a86d2aff..aaa6086fbc9 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go +++ b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go @@ -17,10 +17,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "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/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" diff --git a/core/services/ocr2/plugins/ccip/transmitter/transmitter.go b/core/services/ocr2/plugins/ccip/transmitter/transmitter.go index 3e2962b33a9..24123d03337 100644 --- a/core/services/ocr2/plugins/ccip/transmitter/transmitter.go +++ b/core/services/ocr2/plugins/ccip/transmitter/transmitter.go @@ -11,7 +11,7 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - statuschecker "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" ) type roundRobinKeystore interface { @@ -25,7 +25,7 @@ type txManager interface { type Transmitter interface { CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error - FromAddress() common.Address + FromAddress(context.Context) common.Address } type transmitter struct { @@ -129,7 +129,7 @@ func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common return errors.Wrap(err, "skipped OCR transmission") } -func (t *transmitter) FromAddress() common.Address { +func (t *transmitter) FromAddress(ctx context.Context) common.Address { return t.effectiveTransmitterAddress } diff --git a/core/services/ocr2/plugins/ccip/vars.go b/core/services/ocr2/plugins/ccip/vars.go index a44f5e41d66..82309ef7839 100644 --- a/core/services/ocr2/plugins/ccip/vars.go +++ b/core/services/ocr2/plugins/ccip/vars.go @@ -5,10 +5,12 @@ import ( ) const ( - MaxQueryLength = 0 // empty for both plugins - MaxObservationLength = 250_000 // plugins's Observation should make sure to cap to this limit - CommitPluginLabel = "commit" - ExecPluginLabel = "exec" + MaxQueryLength = 0 // empty for both plugins + MaxObservationLength = 250_000 // plugins's Observation should make sure to cap to this limit + CommitPluginLabel = "commit" + ExecPluginLabel = "exec" + DefaultSourceFinalityDepth = uint32(2) + DefaultDestFinalityDepth = uint32(2) ) var ErrChainIsNotHealthy = errors.New("lane processing is stopped because of healthcheck failure, please see crit logs") diff --git a/core/services/ocr2/plugins/functions/config/config_types.pb.go b/core/services/ocr2/plugins/functions/config/config_types.pb.go index b9debdcd466..2e749c95e38 100644 --- a/core/services/ocr2/plugins/functions/config/config_types.pb.go +++ b/core/services/ocr2/plugins/functions/config/config_types.pb.go @@ -7,10 +7,11 @@ package config import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/core/services/ocr2/plugins/functions/encoding/ocr_types.pb.go b/core/services/ocr2/plugins/functions/encoding/ocr_types.pb.go index 4022076334b..ad60927c3f0 100644 --- a/core/services/ocr2/plugins/functions/encoding/ocr_types.pb.go +++ b/core/services/ocr2/plugins/functions/encoding/ocr_types.pb.go @@ -7,10 +7,11 @@ package encoding import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go index ef81028f20f..9840debf98a 100644 --- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go +++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go @@ -29,6 +29,7 @@ import ( ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -39,7 +40,6 @@ import ( "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/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/functions" @@ -50,6 +50,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) var nilOpts *bind.CallOpts @@ -79,6 +80,7 @@ func SetOracleConfig(t *testing.T, b *backends.SimulatedBackend, owner *bind.Tra S, // S (schedule of randomized transmission order) oracles, reportingPluginConfigBytes, + nil, 200*time.Millisecond, // maxDurationQuery 200*time.Millisecond, // maxDurationObservation 200*time.Millisecond, // maxDurationReport diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go index d6ffa1a3f06..b36d3e37dbc 100644 --- a/core/services/ocr2/plugins/functions/plugin.go +++ b/core/services/ocr2/plugins/functions/plugin.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/functions" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" + hf "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" gwAllowlist "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/allowlist" gwSubscriptions "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/subscriptions" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -174,11 +175,12 @@ func NewFunctionsServices(ctx context.Context, functionsOracleArgs, thresholdOra return nil, errors.Wrap(err, "failed to create a OnchainSubscriptions") } connectorLogger := conf.Logger.Named("GatewayConnector").With("jobName", conf.Job.PipelineSpec.JobName) - connector, err2 := NewConnector(ctx, &pluginConfig, conf.EthKeystore, conf.Chain.ID(), s4Storage, allowlist, rateLimiter, subscriptions, functionsListener, offchainTransmitter, connectorLogger) + connector, handler, err2 := NewConnector(ctx, &pluginConfig, conf.EthKeystore, conf.Chain.ID(), s4Storage, allowlist, rateLimiter, subscriptions, functionsListener, offchainTransmitter, connectorLogger) if err2 != nil { return nil, errors.Wrap(err, "failed to create a GatewayConnector") } allServices = append(allServices, connector) + allServices = append(allServices, handler) } else { listenerLogger.Warn("Insufficient config, GatewayConnector will not be enabled") } @@ -201,29 +203,34 @@ func NewFunctionsServices(ctx context.Context, functionsOracleArgs, thresholdOra return allServices, nil } -func NewConnector(ctx context.Context, pluginConfig *config.PluginConfig, ethKeystore keystore.Eth, chainID *big.Int, s4Storage s4.Storage, allowlist gwAllowlist.OnchainAllowlist, rateLimiter *hc.RateLimiter, subscriptions gwSubscriptions.OnchainSubscriptions, listener functions.FunctionsListener, offchainTransmitter functions.OffchainTransmitter, lggr logger.Logger) (connector.GatewayConnector, error) { +func NewConnector(ctx context.Context, pluginConfig *config.PluginConfig, ethKeystore keystore.Eth, chainID *big.Int, s4Storage s4.Storage, allowlist gwAllowlist.OnchainAllowlist, rateLimiter *hc.RateLimiter, subscriptions gwSubscriptions.OnchainSubscriptions, listener functions.FunctionsListener, offchainTransmitter functions.OffchainTransmitter, lggr logger.Logger) (connector.GatewayConnector, connector.GatewayConnectorHandler, error) { enabledKeys, err := ethKeystore.EnabledKeysForChain(ctx, chainID) if err != nil { - return nil, err + return nil, nil, err } configuredNodeAddress := common.HexToAddress(pluginConfig.GatewayConnectorConfig.NodeAddress) idx := slices.IndexFunc(enabledKeys, func(key ethkey.KeyV2) bool { return key.Address == configuredNodeAddress }) if idx == -1 { - return nil, errors.New("key for configured node address not found") + return nil, nil, errors.New("key for configured node address not found") } signerKey := enabledKeys[idx].ToEcdsaPrivKey() if enabledKeys[idx].ID() != pluginConfig.GatewayConnectorConfig.NodeAddress { - return nil, errors.New("node address mismatch") + return nil, nil, errors.New("node address mismatch") } handler, err := functions.NewFunctionsConnectorHandler(pluginConfig, signerKey, s4Storage, allowlist, rateLimiter, subscriptions, listener, offchainTransmitter, lggr) if err != nil { - return nil, err + return nil, nil, err } - connector, err := connector.NewGatewayConnector(pluginConfig.GatewayConnectorConfig, handler, handler, clockwork.NewRealClock(), lggr) + // handler acts as a signer here + connector, err := connector.NewGatewayConnector(pluginConfig.GatewayConnectorConfig, handler, clockwork.NewRealClock(), lggr) if err != nil { - return nil, err + return nil, nil, err + } + err = connector.AddHandler([]string{hf.MethodSecretsSet, hf.MethodSecretsList, hf.MethodHeartbeat}, handler) + if err != nil { + return nil, nil, err } handler.SetConnector(connector) - return connector, nil + return connector, handler, nil } diff --git a/core/services/ocr2/plugins/functions/plugin_test.go b/core/services/ocr2/plugins/functions/plugin_test.go index fdd20b0a932..b3a120894d0 100644 --- a/core/services/ocr2/plugins/functions/plugin_test.go +++ b/core/services/ocr2/plugins/functions/plugin_test.go @@ -47,7 +47,7 @@ func TestNewConnector_Success(t *testing.T) { config := &config.PluginConfig{ GatewayConnectorConfig: gwcCfg, } - _, err = functions.NewConnector(ctx, config, ethKeystore, chainID, s4Storage, allowlist, rateLimiter, subscriptions, listener, offchainTransmitter, logger.TestLogger(t)) + _, _, err = functions.NewConnector(ctx, config, ethKeystore, chainID, s4Storage, allowlist, rateLimiter, subscriptions, listener, offchainTransmitter, logger.TestLogger(t)) require.NoError(t, err) } @@ -78,6 +78,6 @@ func TestNewConnector_NoKeyForConfiguredAddress(t *testing.T) { config := &config.PluginConfig{ GatewayConnectorConfig: gwcCfg, } - _, err = functions.NewConnector(ctx, config, ethKeystore, chainID, s4Storage, allowlist, rateLimiter, subscriptions, listener, offchainTransmitter, logger.TestLogger(t)) + _, _, err = functions.NewConnector(ctx, config, ethKeystore, chainID, s4Storage, allowlist, rateLimiter, subscriptions, listener, offchainTransmitter, logger.TestLogger(t)) require.Error(t, err) } diff --git a/core/services/ocr2/plugins/functions/reporting.go b/core/services/ocr2/plugins/functions/reporting.go index f485ecb9d34..6236b762e18 100644 --- a/core/services/ocr2/plugins/functions/reporting.go +++ b/core/services/ocr2/plugins/functions/reporting.go @@ -91,7 +91,7 @@ func formatRequestId(requestId []byte) string { } // NewReportingPlugin complies with ReportingPluginFactory -func (f FunctionsReportingPluginFactory) NewReportingPlugin(rpConfig types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { +func (f FunctionsReportingPluginFactory) NewReportingPlugin(ctx context.Context, rpConfig types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { pluginConfig, err := config.DecodeReportingPluginConfig(rpConfig.OffchainConfig) if err != nil { f.Logger.Error("unable to decode reporting plugin config", commontypes.LogFields{ diff --git a/core/services/ocr2/plugins/functions/reporting_test.go b/core/services/ocr2/plugins/functions/reporting_test.go index 7d6686a0b4f..581e2de70b0 100644 --- a/core/services/ocr2/plugins/functions/reporting_test.go +++ b/core/services/ocr2/plugins/functions/reporting_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" functions_srv "github.com/smartcontractkit/chainlink/v2/core/services/functions" @@ -42,7 +43,7 @@ func preparePlugin(t *testing.T, batchSize uint32, maxTotalGasLimit uint32) (typ } pluginConfigBytes, err := config.EncodeReportingPluginConfig(&pluginConfig) require.NoError(t, err) - plugin, _, err := factory.NewReportingPlugin(types.ReportingPluginConfig{ + plugin, _, err := factory.NewReportingPlugin(tests.Context(t), types.ReportingPluginConfig{ N: 4, F: 1, OffchainConfig: pluginConfigBytes, diff --git a/core/services/ocr2/plugins/generic/oraclefactory.go b/core/services/ocr2/plugins/generic/oraclefactory.go new file mode 100644 index 00000000000..7d44a239d2e --- /dev/null +++ b/core/services/ocr2/plugins/generic/oraclefactory.go @@ -0,0 +1,140 @@ +package generic + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "github.com/prometheus/client_golang/prometheus" + ocr "github.com/smartcontractkit/libocr/offchainreporting2plus" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" +) + +type oracleFactory struct { + database ocr3types.Database + jobID int32 + jobName string + jobORM job.ORM + kb ocr2key.KeyBundle + lggr logger.Logger + config job.OracleFactoryConfig + peerWrapper *ocrcommon.SingletonPeerWrapper + relayerSet *RelayerSet + transmitterID string +} + +type OracleFactoryParams struct { + JobID int32 + JobName string + JobORM job.ORM + KB ocr2key.KeyBundle + Logger logger.Logger + Config job.OracleFactoryConfig + PeerWrapper *ocrcommon.SingletonPeerWrapper + RelayerSet *RelayerSet + TransmitterID string +} + +func NewOracleFactory(params OracleFactoryParams) (core.OracleFactory, error) { + return &oracleFactory{ + database: OracleFactoryDB(params.JobID, params.Logger), + jobID: params.JobID, + jobName: params.JobName, + jobORM: params.JobORM, + kb: params.KB, + lggr: params.Logger, + config: params.Config, + peerWrapper: params.PeerWrapper, + relayerSet: params.RelayerSet, + transmitterID: params.TransmitterID, + }, nil +} + +func (of *oracleFactory) NewOracle(ctx context.Context, args core.OracleArgs) (core.Oracle, error) { + if !of.peerWrapper.IsStarted() { + return nil, errors.New("peer wrapper not started") + } + + relayer, err := of.relayerSet.Get(ctx, types.RelayID{Network: of.config.Network, ChainID: of.config.ChainID}) + if err != nil { + return nil, fmt.Errorf("error when getting relayer: %w", err) + } + + var relayConfig = struct { + ChainID string `json:"chainID"` + EffectiveTransmitterID string `json:"effectiveTransmitterID"` + SendingKeys []string `json:"sendingKeys"` + }{ + ChainID: of.config.ChainID, + EffectiveTransmitterID: of.transmitterID, + SendingKeys: []string{of.transmitterID}, + } + relayConfigBytes, err := json.Marshal(relayConfig) + if err != nil { + return nil, fmt.Errorf("error when marshalling relay config: %w", err) + } + + pluginProvider, err := relayer.NewPluginProvider(ctx, core.RelayArgs{ + ContractID: of.config.OCRContractAddress, + ProviderType: "plugin", + RelayConfig: relayConfigBytes, + }, core.PluginArgs{ + TransmitterID: of.transmitterID, + }) + if err != nil { + return nil, fmt.Errorf("error when getting offchain digester: %w", err) + } + + bootstrapPeers, err := ocrcommon.ParseBootstrapPeers(of.config.BootstrapPeers) + if err != nil { + return nil, fmt.Errorf("failed to parse bootstrap peers: %w", err) + } + + oracle, err := ocr.NewOracle(ocr.OCR3OracleArgs[[]byte]{ + // We are relying on the relayer plugin provider for the offchain config digester + // and the contract config tracker to save time. + ContractConfigTracker: pluginProvider.ContractConfigTracker(), + OffchainConfigDigester: pluginProvider.OffchainConfigDigester(), + LocalConfig: args.LocalConfig, + ContractTransmitter: NewContractTransmitter(of.transmitterID, args.ContractTransmitter), + ReportingPluginFactory: args.ReportingPluginFactoryService, + BinaryNetworkEndpointFactory: of.peerWrapper.Peer2, + V2Bootstrappers: bootstrapPeers, + Database: of.database, + Logger: ocrcommon.NewOCRWrapper(of.lggr, true, func(ctx context.Context, msg string) { + logger.Sugared(of.lggr).ErrorIf(of.jobORM.RecordError(ctx, of.jobID, msg), "unable to record error") + }), + MonitoringEndpoint: &telemetry.NoopAgent{}, + OffchainKeyring: of.kb, + OnchainKeyring: ocrcommon.NewOCR3OnchainKeyringAdapter(of.kb), + MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": of.jobName}, prometheus.DefaultRegisterer), + }) + + if err != nil { + return nil, fmt.Errorf("%w: failed to create new OCR oracle", err) + } + + return &adaptedOracle{oracle: oracle}, nil +} + +type adaptedOracle struct { + oracle ocr.Oracle +} + +func (a *adaptedOracle) Start(ctx context.Context) error { + return a.oracle.Start() +} + +func (a *adaptedOracle) Close(ctx context.Context) error { + return a.oracle.Close() +} diff --git a/core/services/ocr2/plugins/generic/oraclefactorydb.go b/core/services/ocr2/plugins/generic/oraclefactorydb.go new file mode 100644 index 00000000000..5db6f8a2ffe --- /dev/null +++ b/core/services/ocr2/plugins/generic/oraclefactorydb.go @@ -0,0 +1,135 @@ +package generic + +import ( + "context" + "encoding/json" + "fmt" + "time" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +type oracleFactoryDb struct { + // The ID is used for logging and error messages + // A single standard capabilities spec can instantiate multiple oracles + // TODO: NewOracle should take a unique identifier for the oracle + specID int32 + lggr logger.SugaredLogger + config *ocrtypes.ContractConfig + states map[ocrtypes.ConfigDigest]*ocrtypes.PersistentState + pendingTransmissions map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission + protocolStates map[ocrtypes.ConfigDigest]map[string][]byte +} + +var ( + _ ocrtypes.Database = &oracleFactoryDb{} +) + +// NewDB returns a new DB scoped to this instanceID +func OracleFactoryDB(specID int32, lggr logger.Logger) *oracleFactoryDb { + return &oracleFactoryDb{ + specID: specID, + lggr: logger.Sugared(lggr.Named("OracleFactoryMemoryDb")), + states: make(map[ocrtypes.ConfigDigest]*ocrtypes.PersistentState), + pendingTransmissions: make(map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission), + protocolStates: make(map[ocrtypes.ConfigDigest]map[string][]byte), + } +} + +func (ofdb *oracleFactoryDb) ReadState(ctx context.Context, cd ocrtypes.ConfigDigest) (ps *ocrtypes.PersistentState, err error) { + ps, ok := ofdb.states[cd] + if !ok { + return nil, fmt.Errorf("state not found for standard capabilities spec ID %d, config digest %s", ofdb.specID, cd) + } + + return ps, nil +} + +func (ofdb *oracleFactoryDb) WriteState(ctx context.Context, cd ocrtypes.ConfigDigest, state ocrtypes.PersistentState) error { + ofdb.states[cd] = &state + return nil +} + +func (ofdb *oracleFactoryDb) ReadConfig(ctx context.Context) (c *ocrtypes.ContractConfig, err error) { + if ofdb.config == nil { + // Returning nil, nil because this is a cache miss + return nil, nil + } + return ofdb.config, nil +} + +func (ofdb *oracleFactoryDb) WriteConfig(ctx context.Context, c ocrtypes.ContractConfig) error { + ofdb.config = &c + + cBytes, err := json.Marshal(c) + if err != nil { + return fmt.Errorf("MemoryDB: WriteConfig failed to marshal config: %w", err) + } + + ofdb.lggr.Debugw("MemoryDB: WriteConfig", "ocrtypes.ContractConfig", string(cBytes)) + + return nil +} + +func (ofdb *oracleFactoryDb) StorePendingTransmission(ctx context.Context, t ocrtypes.ReportTimestamp, tx ocrtypes.PendingTransmission) error { + ofdb.pendingTransmissions[t] = tx + return nil +} + +func (ofdb *oracleFactoryDb) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtypes.ConfigDigest) (map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission, error) { + m := make(map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission) + for k, v := range ofdb.pendingTransmissions { + if k.ConfigDigest == cd { + m[k] = v + } + } + + return m, nil +} + +func (ofdb *oracleFactoryDb) DeletePendingTransmission(ctx context.Context, t ocrtypes.ReportTimestamp) error { + delete(ofdb.pendingTransmissions, t) + return nil +} + +func (ofdb *oracleFactoryDb) DeletePendingTransmissionsOlderThan(ctx context.Context, t time.Time) error { + for k, v := range ofdb.pendingTransmissions { + if v.Time.Before(t) { + delete(ofdb.pendingTransmissions, k) + } + } + + return nil +} + +func (ofdb *oracleFactoryDb) ReadProtocolState( + ctx context.Context, + configDigest ocrtypes.ConfigDigest, + key string, +) ([]byte, error) { + value, ok := ofdb.protocolStates[configDigest][key] + if !ok { + // Previously implementation returned nil if the state is not found + return nil, nil + } + return value, nil +} + +func (ofdb *oracleFactoryDb) WriteProtocolState( + ctx context.Context, + configDigest ocrtypes.ConfigDigest, + key string, + value []byte, +) error { + if value == nil { + delete(ofdb.protocolStates[configDigest], key) + } else { + if ofdb.protocolStates[configDigest] == nil { + ofdb.protocolStates[configDigest] = make(map[string][]byte) + } + ofdb.protocolStates[configDigest][key] = value + } + return nil +} diff --git a/core/services/ocr2/plugins/generic/oraclefactorytransmitter.go b/core/services/ocr2/plugins/generic/oraclefactorytransmitter.go new file mode 100644 index 00000000000..cdf3ae91267 --- /dev/null +++ b/core/services/ocr2/plugins/generic/oraclefactorytransmitter.go @@ -0,0 +1,36 @@ +package generic + +import ( + "context" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +var _ ocr3types.ContractTransmitter[[]byte] = (*contractTransmitter)(nil) + +type contractTransmitter struct { + impl ocr3types.ContractTransmitter[[]byte] + transmitterID string +} + +func NewContractTransmitter(transmitterID string, impl ocr3types.ContractTransmitter[[]byte]) *contractTransmitter { + return &contractTransmitter{ + impl: impl, + transmitterID: transmitterID, + } +} + +func (ct *contractTransmitter) Transmit( + ctx context.Context, + configDigest types.ConfigDigest, + seqNr uint64, + reportWithInfo ocr3types.ReportWithInfo[[]byte], + attributedOnchainSignature []types.AttributedOnchainSignature, +) error { + return ct.impl.Transmit(ctx, configDigest, seqNr, reportWithInfo, attributedOnchainSignature) +} + +func (ct *contractTransmitter) FromAccount(ctx context.Context) (types.Account, error) { + return types.Account(ct.transmitterID), nil +} diff --git a/core/services/ocr2/plugins/generic/relayerset_test.go b/core/services/ocr2/plugins/generic/relayerset_test.go index b5eb16682de..44ed216520f 100644 --- a/core/services/ocr2/plugins/generic/relayerset_test.go +++ b/core/services/ocr2/plugins/generic/relayerset_test.go @@ -158,6 +158,10 @@ func (t *TestRelayer) NewContractReader(_ context.Context, _ []byte) (types.Cont panic("implement me") } +func (t *TestRelayer) LatestHead(_ context.Context) (types.Head, error) { + panic("implement me") +} + func (t *TestRelayer) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { panic("implement me") } diff --git a/core/services/ocr2/plugins/llo/config/config.go b/core/services/ocr2/plugins/llo/config/config.go index 892229c46c8..7bd36b4ff8b 100644 --- a/core/services/ocr2/plugins/llo/config/config.go +++ b/core/services/ocr2/plugins/llo/config/config.go @@ -9,19 +9,18 @@ import ( "fmt" "net/url" "regexp" + "sort" "github.com/ethereum/go-ethereum/common" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config" "github.com/smartcontractkit/chainlink/v2/core/utils" ) type PluginConfig struct { - RawServerURL string `json:"serverURL" toml:"serverURL"` - ServerPubKey utils.PlainHexBytes `json:"serverPubKey" toml:"serverPubKey"` - ChannelDefinitionsContractAddress common.Address `json:"channelDefinitionsContractAddress" toml:"channelDefinitionsContractAddress"` ChannelDefinitionsContractFromBlock int64 `json:"channelDefinitionsContractFromBlock" toml:"channelDefinitionsContractFromBlock"` @@ -39,27 +38,42 @@ type PluginConfig struct { // KeyBundleIDs maps supported keys to their respective bundle IDs // Key must match llo's ReportFormat KeyBundleIDs map[string]string `json:"keyBundleIDs" toml:"keyBundleIDs"` + + DonID uint32 `json:"donID" toml:"donID"` + + // Mercury servers + Servers map[string]utils.PlainHexBytes `json:"servers" toml:"servers"` } func (p *PluginConfig) Unmarshal(data []byte) error { return json.Unmarshal(data, p) } +func (p PluginConfig) GetServers() (servers []mercuryconfig.Server) { + for url, pubKey := range p.Servers { + servers = append(servers, mercuryconfig.Server{URL: wssRegexp.ReplaceAllString(url, ""), PubKey: pubKey}) + } + sort.Slice(servers, func(i, j int) bool { + return servers[i].URL < servers[j].URL + }) + return +} + func (p PluginConfig) Validate() (merr error) { - if p.RawServerURL == "" { - merr = errors.New("llo: ServerURL must be specified") + if p.DonID == 0 { + merr = errors.Join(merr, errors.New("llo: DonID must be specified and not zero")) + } + + if len(p.Servers) == 0 { + merr = errors.Join(merr, errors.New("llo: At least one Mercury server must be specified")) } else { - var normalizedURI string - if schemeRegexp.MatchString(p.RawServerURL) { - normalizedURI = p.RawServerURL - } else { - normalizedURI = fmt.Sprintf("wss://%s", p.RawServerURL) - } - uri, err := url.ParseRequestURI(normalizedURI) - if err != nil { - merr = fmt.Errorf("llo: invalid value for ServerURL: %w", err) - } else if uri.Scheme != "wss" { - merr = fmt.Errorf(`llo: invalid scheme specified for MercuryServer, got: %q (scheme: %q) but expected a websocket url e.g. "192.0.2.2:4242" or "wss://192.0.2.2:4242"`, p.RawServerURL, uri.Scheme) + for serverName, serverPubKey := range p.Servers { + if err := validateURL(serverName); err != nil { + merr = errors.Join(merr, fmt.Errorf("llo: invalid value for ServerURL: %w", err)) + } + if len(serverPubKey) != 32 { + merr = errors.Join(merr, errors.New("llo: ServerPubKey must be a 32-byte hex string")) + } } } @@ -74,21 +88,36 @@ func (p PluginConfig) Validate() (merr error) { if err := json.Unmarshal([]byte(p.ChannelDefinitions), &cd); err != nil { merr = errors.Join(merr, fmt.Errorf("channelDefinitions is invalid JSON: %w", err)) } + // TODO: Verify Opts format here? + // MERC-3524 } else { if p.ChannelDefinitionsContractAddress == (common.Address{}) { merr = errors.Join(merr, errors.New("llo: ChannelDefinitionsContractAddress is required if ChannelDefinitions is not specified")) } } - if len(p.ServerPubKey) != 32 { - merr = errors.Join(merr, errors.New("llo: ServerPubKey is required and must be a 32-byte hex string")) - } - merr = errors.Join(merr, validateKeyBundleIDs(p.KeyBundleIDs)) return merr } +func validateURL(rawServerURL string) error { + var normalizedURI string + if schemeRegexp.MatchString(rawServerURL) { + normalizedURI = rawServerURL + } else { + normalizedURI = fmt.Sprintf("wss://%s", rawServerURL) + } + uri, err := url.ParseRequestURI(normalizedURI) + if err != nil { + return fmt.Errorf(`llo: invalid value for ServerURL, got: %q`, rawServerURL) + } + if uri.Scheme != "wss" { + return fmt.Errorf(`llo: invalid scheme specified for MercuryServer, got: %q (scheme: %q) but expected a websocket url e.g. "192.0.2.2:4242" or "wss://192.0.2.2:4242"`, rawServerURL, uri.Scheme) + } + return nil +} + func validateKeyBundleIDs(keyBundleIDs map[string]string) error { for k, v := range keyBundleIDs { if k == "" { @@ -109,7 +138,3 @@ func validateKeyBundleIDs(keyBundleIDs map[string]string) error { var schemeRegexp = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9+.-]*://`) var wssRegexp = regexp.MustCompile(`^wss://`) - -func (p PluginConfig) ServerURL() string { - return wssRegexp.ReplaceAllString(p.RawServerURL, "") -} diff --git a/core/services/ocr2/plugins/llo/config/config_test.go b/core/services/ocr2/plugins/llo/config/config_test.go index 136fac87a56..096543b2524 100644 --- a/core/services/ocr2/plugins/llo/config/config_test.go +++ b/core/services/ocr2/plugins/llo/config/config_test.go @@ -7,6 +7,8 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/utils" ) func Test_Config(t *testing.T) { @@ -31,8 +33,7 @@ func Test_Config(t *testing.T) { t.Run("with all possible values set", func(t *testing.T) { rawToml := fmt.Sprintf(` - ServerURL = "example.com:80" - ServerPubKey = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" + Servers = { "example.com:80" = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93", "example2.invalid:1234" = "524ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" } BenchmarkMode = true ChannelDefinitionsContractAddress = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ChannelDefinitionsContractFromBlock = 1234 @@ -44,8 +45,8 @@ func Test_Config(t *testing.T) { err := toml.Unmarshal([]byte(rawToml), &mc) require.NoError(t, err) - assert.Equal(t, "example.com:80", mc.RawServerURL) - assert.Equal(t, "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93", mc.ServerPubKey.String()) + assert.Len(t, mc.Servers, 2) + assert.Equal(t, map[string]utils.PlainHexBytes{"example.com:80": utils.PlainHexBytes{0x72, 0x4f, 0xf6, 0xea, 0xe9, 0xe9, 0x0, 0x27, 0xe, 0xdf, 0xff, 0x23, 0x3e, 0x16, 0x32, 0x2a, 0x70, 0xec, 0x6, 0xe1, 0xa6, 0xe6, 0x2a, 0x81, 0xef, 0x13, 0x92, 0x1f, 0x39, 0x8f, 0x6c, 0x93}, "example2.invalid:1234": utils.PlainHexBytes{0x52, 0x4f, 0xf6, 0xea, 0xe9, 0xe9, 0x0, 0x27, 0xe, 0xdf, 0xff, 0x23, 0x3e, 0x16, 0x32, 0x2a, 0x70, 0xec, 0x6, 0xe1, 0xa6, 0xe6, 0x2a, 0x81, 0xef, 0x13, 0x92, 0x1f, 0x39, 0x8f, 0x6c, 0x93}}, mc.Servers) assert.Equal(t, "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", mc.ChannelDefinitionsContractAddress.Hex()) assert.Equal(t, int64(1234), mc.ChannelDefinitionsContractFromBlock) assert.JSONEq(t, cdjson, mc.ChannelDefinitions) @@ -60,8 +61,8 @@ func Test_Config(t *testing.T) { t.Run("with only channelDefinitions", func(t *testing.T) { rawToml := fmt.Sprintf(` - ServerURL = "example.com:80" - ServerPubKey = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" + Servers = { "example.com:80" = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" } + DonID = 12345 ChannelDefinitions = """ %s """`, cdjson) @@ -70,9 +71,9 @@ func Test_Config(t *testing.T) { err := toml.Unmarshal([]byte(rawToml), &mc) require.NoError(t, err) - assert.Equal(t, "example.com:80", mc.RawServerURL) - assert.Equal(t, "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93", mc.ServerPubKey.String()) + assert.Len(t, mc.Servers, 1) assert.JSONEq(t, cdjson, mc.ChannelDefinitions) + assert.Equal(t, uint32(12345), mc.DonID) assert.False(t, mc.BenchmarkMode) err = mc.Validate() @@ -80,17 +81,17 @@ func Test_Config(t *testing.T) { }) t.Run("with only channelDefinitions contract details", func(t *testing.T) { rawToml := ` - ServerURL = "example.com:80" - ServerPubKey = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" + Servers = { "example.com:80" = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" } + DonID = 12345 ChannelDefinitionsContractAddress = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"` var mc PluginConfig err := toml.Unmarshal([]byte(rawToml), &mc) require.NoError(t, err) - assert.Equal(t, "example.com:80", mc.RawServerURL) - assert.Equal(t, "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93", mc.ServerPubKey.String()) + assert.Len(t, mc.Servers, 1) assert.Equal(t, "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", mc.ChannelDefinitionsContractAddress.Hex()) + assert.Equal(t, uint32(12345), mc.DonID) assert.False(t, mc.BenchmarkMode) err = mc.Validate() @@ -98,15 +99,16 @@ func Test_Config(t *testing.T) { }) t.Run("with missing ChannelDefinitionsContractAddress", func(t *testing.T) { rawToml := ` - ServerURL = "example.com:80" - ServerPubKey = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93"` + DonID = 12345 + Servers = { "example.com:80" = "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93" } + ` var mc PluginConfig err := toml.Unmarshal([]byte(rawToml), &mc) require.NoError(t, err) - assert.Equal(t, "example.com:80", mc.RawServerURL) - assert.Equal(t, "724ff6eae9e900270edfff233e16322a70ec06e1a6e62a81ef13921f398f6c93", mc.ServerPubKey.String()) + assert.Len(t, mc.Servers, 1) + assert.Equal(t, uint32(12345), mc.DonID) assert.False(t, mc.BenchmarkMode) err = mc.Validate() @@ -135,8 +137,39 @@ func Test_Config(t *testing.T) { err = mc.Validate() require.Error(t, err) - assert.Contains(t, err.Error(), `invalid scheme specified for MercuryServer, got: "http://example.com" (scheme: "http") but expected a websocket url e.g. "192.0.2.2:4242" or "wss://192.0.2.2:4242"`) - assert.Contains(t, err.Error(), `ServerPubKey is required and must be a 32-byte hex string`) + assert.Contains(t, err.Error(), `DonID must be specified and not zero`) + assert.Contains(t, err.Error(), `At least one Mercury server must be specified`) + assert.Contains(t, err.Error(), `ChannelDefinitionsContractAddress is required if ChannelDefinitions is not specified`) }) }) } + +func Test_PluginConfig_Validate(t *testing.T) { + t.Run("with invalid URLs or keys", func(t *testing.T) { + servers := map[string]utils.PlainHexBytes{ + "not a valid url": utils.PlainHexBytes([]byte{1, 2, 3}), + "mercuryserver.invalid:1234/foo": nil, + } + pc := PluginConfig{Servers: servers} + + err := pc.Validate() + assert.Contains(t, err.Error(), "ServerPubKey must be a 32-byte hex string") + assert.Contains(t, err.Error(), "invalid value for ServerURL: llo: invalid value for ServerURL, got: \"not a valid url\"") + }) +} + +func Test_PluginConfig_GetServers(t *testing.T) { + t.Run("with multiple servers", func(t *testing.T) { + servers := map[string]utils.PlainHexBytes{ + "example.com:80": utils.PlainHexBytes([]byte{1, 2, 3}), + "mercuryserver.invalid:1234/foo": utils.PlainHexBytes([]byte{4, 5, 6}), + } + pc := PluginConfig{Servers: servers} + + require.Len(t, pc.GetServers(), 2) + assert.Equal(t, "example.com:80", pc.GetServers()[0].URL) + assert.Equal(t, utils.PlainHexBytes{1, 2, 3}, pc.GetServers()[0].PubKey) + assert.Equal(t, "mercuryserver.invalid:1234/foo", pc.GetServers()[1].URL) + assert.Equal(t, utils.PlainHexBytes{4, 5, 6}, pc.GetServers()[1].PubKey) + }) +} diff --git a/core/services/ocr2/plugins/llo/helpers_test.go b/core/services/ocr2/plugins/llo/helpers_test.go new file mode 100644 index 00000000000..452b2cde2dc --- /dev/null +++ b/core/services/ocr2/plugins/llo/helpers_test.go @@ -0,0 +1,425 @@ +package llo_test + +import ( + "context" + "crypto/ed25519" + "errors" + "fmt" + "io" + "math/big" + "net" + "net/http" + "net/http/httptest" + "net/url" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/shopspring/decimal" + "github.com/smartcontractkit/wsrpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest/observer" + + "github.com/smartcontractkit/wsrpc/credentials" + "github.com/smartcontractkit/wsrpc/peer" + + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + + "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "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" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" + "github.com/smartcontractkit/chainlink/v2/core/services/streams" + "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" +) + +var _ pb.MercuryServer = &mercuryServer{} + +type request struct { + pk credentials.StaticSizedPublicKey + req *pb.TransmitRequest +} + +func (r request) TransmitterID() ocr2types.Account { + return ocr2types.Account(fmt.Sprintf("%x", r.pk)) +} + +type mercuryServer struct { + privKey ed25519.PrivateKey + reqsCh chan request + t *testing.T +} + +func NewMercuryServer(t *testing.T, privKey ed25519.PrivateKey, reqsCh chan request) *mercuryServer { + return &mercuryServer{privKey, reqsCh, t} +} + +func (s *mercuryServer) 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} + s.reqsCh <- r + + return &pb.TransmitResponse{ + Code: 1, + Error: "", + }, nil +} + +func (s *mercuryServer) 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) { + // Set up the wsrpc 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() + s := wsrpc.NewServer(wsrpc.WithCreds(srv.privKey, pubKeys)) + + // Register mercury implementation with the wsrpc server + pb.RegisterMercuryServer(s, srv) + + // Start serving + go s.Serve(lis) + t.Cleanup(s.Stop) + + return +} + +type Node struct { + App chainlink.Application + ClientPubKey credentials.StaticSizedPublicKey + KeyBundle ocr2key.KeyBundle + ObservedLogs *observer.ObservedLogs +} + +func (node *Node) AddStreamJob(t *testing.T, spec string) (id int32) { + job, err := streams.ValidatedStreamSpec(spec) + require.NoError(t, err) + err = node.App.AddJobV2(testutils.Context(t), &job) + require.NoError(t, err) + return job.ID +} + +func (node *Node) DeleteJob(t *testing.T, id int32) { + err := node.App.DeleteJob(testutils.Context(t), id) + require.NoError(t, err) +} + +func (node *Node) AddLLOJob(t *testing.T, spec string) { + c := node.App.GetConfig() + job, err := validate.ValidatedOracleSpecToml(testutils.Context(t), c.OCR2(), c.Insecure(), spec, nil) + require.NoError(t, err) + err = node.App.AddJobV2(testutils.Context(t), &job) + require.NoError(t, err) +} + +func (node *Node) AddBootstrapJob(t *testing.T, spec string) { + job, err := ocrbootstrap.ValidatedBootstrapSpecToml(spec) + require.NoError(t, err) + err = node.App.AddJobV2(testutils.Context(t), &job) + require.NoError(t, err) +} + +func setupNode( + t *testing.T, + port int, + dbName string, + backend *backends.SimulatedBackend, + csaKey csakey.KeyV2, +) (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) + rdr := keystest.NewRandReaderFromSeed(int64(port)) + ocr2kb = ocr2key.MustNewInsecure(rdr, chaintype.EVM) + + p2paddresses := []string{fmt.Sprintf("127.0.0.1:%d", port)} + + config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + // [JobPipeline] + c.JobPipeline.MaxSuccessfulRuns = ptr(uint64(0)) + c.JobPipeline.VerboseLogging = ptr(true) + + // [Feature] + c.Feature.UICSAKeys = ptr(true) + c.Feature.LogPoller = ptr(true) + c.Feature.FeedsManager = ptr(false) + + // [OCR] + c.OCR.Enabled = ptr(false) + + // [OCR2] + c.OCR2.Enabled = ptr(true) + c.OCR2.ContractPollInterval = commonconfig.MustNewDuration(100 * time.Millisecond) + + // [P2P] + c.P2P.PeerID = ptr(p2pKey.PeerID()) + c.P2P.TraceLogging = ptr(true) + + // [P2P.V2] + c.P2P.V2.Enabled = ptr(true) + c.P2P.V2.AnnounceAddresses = &p2paddresses + c.P2P.V2.ListenAddresses = &p2paddresses + c.P2P.V2.DeltaDial = commonconfig.MustNewDuration(500 * time.Millisecond) + c.P2P.V2.DeltaReconcile = commonconfig.MustNewDuration(5 * time.Second) + + // [Mercury] + c.Mercury.VerboseLogging = ptr(true) + }) + + lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) + if backend != nil { + app = cltest.NewApplicationWithConfigV2OnSimulatedBlockchain(t, config, backend, p2pKey, ocr2kb, csaKey, lggr.Named(dbName)) + } else { + app = cltest.NewApplicationWithConfig(t, config, p2pKey, ocr2kb, csaKey, lggr.Named(dbName)) + } + err := app.Start(testutils.Context(t)) + require.NoError(t, err) + + t.Cleanup(func() { + assert.NoError(t, app.Stop()) + }) + + return app, p2pKey.PeerID().Raw(), csaKey.StaticSizedPublicKey(), ocr2kb, observedLogs +} + +func ptr[T any](t T) *T { return &t } + +func addSingleDecimalStreamJob( + t *testing.T, + node Node, + streamID uint32, + bridgeName string, +) (id int32) { + return node.AddStreamJob(t, fmt.Sprintf(` +type = "stream" +schemaVersion = 1 +name = "strm-spec-%d" +streamID = %d +observationSource = """ + // Benchmark Price + price1 [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + price1_parse [type=jsonparse path="result"]; + + price1 -> price1_parse; +""" + + `, + streamID, + streamID, + bridgeName, + )) +} + +func addQuoteStreamJob( + t *testing.T, + node Node, + streamID uint32, + benchmarkBridgeName string, + bidBridgeName string, + askBridgeName string, +) (id int32) { + return node.AddStreamJob(t, fmt.Sprintf(` +type = "stream" +schemaVersion = 1 +name = "strm-spec-%d" +streamID = %d +observationSource = """ + // Benchmark Price + price1 [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + price1_parse [type=jsonparse path="result" index=0]; + + price1 -> price1_parse; + + // Bid + price2 [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + price2_parse [type=jsonparse path="result" index=1]; + + price2 -> price2_parse; + + // Ask + price3 [type=bridge name="%s" requestData="{\\"data\\":{\\"data\\":\\"foo\\"}}"]; + price3_parse [type=jsonparse path="result" index=2]; + + price3 -> price3_parse; +""" + + `, + streamID, + streamID, + benchmarkBridgeName, + bidBridgeName, + askBridgeName, + )) +} +func addBootstrapJob(t *testing.T, bootstrapNode Node, configuratorAddress common.Address, name string, relayType, relayConfig string) { + bootstrapNode.AddBootstrapJob(t, fmt.Sprintf(` +type = "bootstrap" +relay = "%s" +schemaVersion = 1 +name = "boot-%s" +contractID = "%s" +contractConfigTrackerPollInterval = "1s" + +[relayConfig] +%s +providerType = "llo"`, relayType, name, configuratorAddress.Hex(), relayConfig)) +} + +func addLLOJob( + t *testing.T, + node Node, + configuratorAddr common.Address, + bootstrapPeerID string, + bootstrapNodePort int, + clientPubKey ed25519.PublicKey, + jobName string, + pluginConfig, + relayType, + relayConfig string, +) { + node.AddLLOJob(t, fmt.Sprintf(` +type = "offchainreporting2" +schemaVersion = 1 +name = "%s" +forwardingAllowed = false +maxTaskDuration = "1s" +contractID = "%s" +contractConfigTrackerPollInterval = "1s" +ocrKeyBundleID = "%s" +p2pv2Bootstrappers = [ + "%s" +] +relay = "%s" +pluginType = "llo" +transmitterID = "%x" + +[pluginConfig] +%s + +[relayConfig] +%s`, + jobName, + configuratorAddr.Hex(), + node.KeyBundle.ID(), + fmt.Sprintf("%s@127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), + relayType, + clientPubKey, + pluginConfig, + relayConfig, + )) +} + +func createBridge(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) + require.NoError(t, err) + require.Equal(t, `{"data":{"data":"foo"}}`, string(b)) + + res.WriteHeader(http.StatusOK) + val := p.String() + resp := fmt.Sprintf(`{"result": %s}`, val) + _, err = res.Write([]byte(resp)) + require.NoError(t, err) + })) + t.Cleanup(bridge.Close) + u, _ := url.Parse(bridge.URL) + bridgeName = fmt.Sprintf("bridge-%s-%d", name, i) + require.NoError(t, borm.CreateBridgeType(ctx, &bridges.BridgeType{ + Name: bridges.BridgeName(bridgeName), + URL: models.WebURL(*u), + })) + + return bridgeName +} + +func addOCRJobsEVMPremiumLegacy( + t *testing.T, + streams []Stream, + serverPubKey ed25519.PublicKey, + serverURL string, + configuratorAddress common.Address, + bootstrapPeerID string, + bootstrapNodePort int, + nodes []Node, + configStoreAddress common.Address, + clientPubKeys []ed25519.PublicKey, + pluginConfig, + relayType, + relayConfig string) (jobIDs map[int]map[uint32]int32) { + // node idx => stream id => job id + jobIDs = make(map[int]map[uint32]int32) + // Add OCR jobs - one per feed on each node + for i, node := range nodes { + if jobIDs[i] == nil { + jobIDs[i] = make(map[uint32]int32) + } + for j, strm := range streams { + // assume that streams are native, link and additionals are quote + if j < 2 { + var name string + if j == 0 { + name = "nativeprice" + } else { + name = "linkprice" + } + name = fmt.Sprintf("%s-%d-%d", name, strm.id, j) + bmBridge := createBridge(t, name, i, strm.baseBenchmarkPrice, node.App.BridgeORM()) + jobID := addSingleDecimalStreamJob( + t, + node, + strm.id, + bmBridge, + ) + 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()) + jobID := addQuoteStreamJob( + t, + node, + strm.id, + bmBridge, + bidBridge, + askBridge, + ) + jobIDs[i][strm.id] = jobID + } + } + addLLOJob( + t, + node, + configuratorAddress, + bootstrapPeerID, + bootstrapNodePort, + clientPubKeys[i], + "feed-1", + pluginConfig, + relayType, + relayConfig, + ) + } + return jobIDs +} diff --git a/core/services/ocr2/plugins/llo/integration_test.go b/core/services/ocr2/plugins/llo/integration_test.go new file mode 100644 index 00000000000..7ab735bf122 --- /dev/null +++ b/core/services/ocr2/plugins/llo/integration_test.go @@ -0,0 +1,841 @@ +package llo_test + +import ( + "crypto/ed25519" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "sort" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "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/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/crypto/sha3" + + "github.com/smartcontractkit/libocr/offchainreporting2/types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/wsrpc/credentials" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" + + "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/llo-feeds/generated/channel_config_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/configurator" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/destination_verifier" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/destination_verifier_proxy" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" + lloevm "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/llo" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" + reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" + mercuryverifier "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/verifier" +) + +var ( + fNodes = uint8(1) + nNodes = 4 // number of nodes (not including bootstrap) +) + +func setupBlockchain(t *testing.T) ( + *bind.TransactOpts, + *backends.SimulatedBackend, + *configurator.Configurator, + common.Address, + *destination_verifier.DestinationVerifier, + common.Address, + *destination_verifier_proxy.DestinationVerifierProxy, + common.Address, + *channel_config_store.ChannelConfigStore, + common.Address, + *verifier.Verifier, + common.Address, + *verifier_proxy.VerifierProxy, + common.Address, +) { + steve := testutils.MustNewSimTransactor(t) // config contract deployer and owner + genesisData := core.GenesisAlloc{steve.From: {Balance: assets.Ether(1000).ToInt()}} + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + backend.Commit() + backend.Commit() // ensure starting block number at least 1 + + // Configurator + configuratorAddress, _, configurator, err := configurator.DeployConfigurator(steve, backend) + require.NoError(t, err) + + // DestinationVerifierProxy + destinationVerifierProxyAddr, _, verifierProxy, err := destination_verifier_proxy.DeployDestinationVerifierProxy(steve, backend) + require.NoError(t, err) + // DestinationVerifier + destinationVerifierAddr, _, destinationVerifier, err := destination_verifier.DeployDestinationVerifier(steve, backend, destinationVerifierProxyAddr) + require.NoError(t, err) + // AddVerifier + _, err = verifierProxy.SetVerifier(steve, destinationVerifierAddr) + require.NoError(t, err) + + // Legacy mercury verifier + legacyVerifier, legacyVerifierAddr, legacyVerifierProxy, legacyVerifierProxyAddr := setupLegacyMercuryVerifier(t, steve, backend) + + // ChannelConfigStore + configStoreAddress, _, configStore, err := channel_config_store.DeployChannelConfigStore(steve, backend) + require.NoError(t, err) + + backend.Commit() + + return steve, backend, configurator, configuratorAddress, destinationVerifier, destinationVerifierAddr, verifierProxy, destinationVerifierProxyAddr, configStore, configStoreAddress, legacyVerifier, legacyVerifierAddr, legacyVerifierProxy, legacyVerifierProxyAddr +} + +func setupLegacyMercuryVerifier(t *testing.T, steve *bind.TransactOpts, backend *backends.SimulatedBackend) (*verifier.Verifier, common.Address, *verifier_proxy.VerifierProxy, common.Address) { + linkTokenAddress, _, linkToken, err := link_token_interface.DeployLinkToken(steve, backend) + require.NoError(t, err) + _, err = linkToken.Transfer(steve, steve.From, big.NewInt(1000)) + require.NoError(t, err) + nativeTokenAddress, _, nativeToken, err := link_token_interface.DeployLinkToken(steve, backend) + require.NoError(t, err) + _, err = nativeToken.Transfer(steve, steve.From, big.NewInt(1000)) + require.NoError(t, err) + verifierProxyAddr, _, verifierProxy, err := verifier_proxy.DeployVerifierProxy(steve, backend, common.Address{}) // zero address for access controller disables access control + require.NoError(t, err) + verifierAddress, _, verifier, err := verifier.DeployVerifier(steve, backend, verifierProxyAddr) + require.NoError(t, err) + _, err = verifierProxy.InitializeVerifier(steve, verifierAddress) + require.NoError(t, err) + rewardManagerAddr, _, rewardManager, err := reward_manager.DeployRewardManager(steve, backend, linkTokenAddress) + require.NoError(t, err) + feeManagerAddr, _, _, err := fee_manager.DeployFeeManager(steve, backend, linkTokenAddress, nativeTokenAddress, verifierProxyAddr, rewardManagerAddr) + require.NoError(t, err) + _, err = verifierProxy.SetFeeManager(steve, feeManagerAddr) + require.NoError(t, err) + _, err = rewardManager.SetFeeManager(steve, feeManagerAddr) + require.NoError(t, err) + + return verifier, verifierAddress, verifierProxy, verifierProxyAddr +} + +type Stream struct { + id uint32 + baseBenchmarkPrice decimal.Decimal + baseBid decimal.Decimal + baseAsk decimal.Decimal +} + +const ( + ethStreamID = 52 + linkStreamID = 53 + quoteStreamID1 = 55 + quoteStreamID2 = 56 +) + +var ( + quoteStreamFeedID1 = common.HexToHash(`0x0003111111111111111111111111111111111111111111111111111111111111`) + quoteStreamFeedID2 = common.HexToHash(`0x0003222222222222222222222222222222222222222222222222222222222222`) + ethStream = Stream{ + id: 52, + baseBenchmarkPrice: decimal.NewFromFloat32(2_976.39), + } + linkStream = Stream{ + id: 53, + baseBenchmarkPrice: decimal.NewFromFloat32(13.25), + } + quoteStream1 = Stream{ + id: 55, + baseBenchmarkPrice: decimal.NewFromFloat32(1000.1212), + baseBid: decimal.NewFromFloat32(998.5431), + baseAsk: decimal.NewFromFloat32(1001.6999), + } + quoteStream2 = Stream{ + id: 56, + baseBenchmarkPrice: decimal.NewFromFloat32(500.1212), + baseBid: decimal.NewFromFloat32(499.5431), + baseAsk: decimal.NewFromFloat32(502.6999), + } +) + +func generateBlueGreenConfig(t *testing.T, oracles []confighelper.OracleIdentityExtra, predecessorConfigDigest *ocr2types.ConfigDigest) ( + signers []types.OnchainPublicKey, + transmitters []types.Account, + f uint8, + onchainConfig []byte, + offchainConfigVersion uint64, + offchainConfig []byte, +) { + onchainConfig, err := (&datastreamsllo.EVMOnchainConfigCodec{}).Encode(datastreamsllo.OnchainConfig{ + Version: 1, + PredecessorConfigDigest: predecessorConfigDigest, + }) + require.NoError(t, err) + return generateConfig(t, oracles, onchainConfig) +} + +func generateConfig(t *testing.T, oracles []confighelper.OracleIdentityExtra, inOnchainConfig []byte) ( + signers []types.OnchainPublicKey, + transmitters []types.Account, + f uint8, + outOnchainConfig []byte, + offchainConfigVersion uint64, + offchainConfig []byte, +) { + rawReportingPluginConfig := datastreamsllo.OffchainConfig{} + reportingPluginConfig, err := rawReportingPluginConfig.Encode() + require.NoError(t, err) + + signers, transmitters, f, outOnchainConfig, offchainConfigVersion, offchainConfig, err = ocr3confighelper.ContractSetConfigArgsForTests( + 2*time.Second, // DeltaProgress + 20*time.Second, // DeltaResend + 400*time.Millisecond, // DeltaInitial + 500*time.Millisecond, // DeltaRound + 250*time.Millisecond, // DeltaGrace + 300*time.Millisecond, // DeltaCertifiedCommitRequest + 1*time.Minute, // DeltaStage + 100, // rMax + []int{len(oracles)}, // S + oracles, + reportingPluginConfig, // reportingPluginConfig []byte, + nil, // maxDurationInitialization + 0, // maxDurationQuery + 250*time.Millisecond, // maxDurationObservation + 0, // maxDurationShouldAcceptAttestedReport + 0, // maxDurationShouldTransmitAcceptedReport + int(fNodes), // f + inOnchainConfig, // encoded onchain config + ) + + require.NoError(t, err) + + return +} + +func setLegacyConfig(t *testing.T, donID uint32, steve *bind.TransactOpts, backend *backends.SimulatedBackend, legacyVerifier *verifier.Verifier, legacyVerifierAddr common.Address, nodes []Node, oracles []confighelper.OracleIdentityExtra) ocr2types.ConfigDigest { + onchainConfig, err := (&datastreamsllo.EVMOnchainConfigCodec{}).Encode(datastreamsllo.OnchainConfig{ + Version: 1, + PredecessorConfigDigest: nil, + }) + require.NoError(t, err) + + signers, _, _, onchainConfig, offchainConfigVersion, offchainConfig := generateConfig(t, oracles, onchainConfig) + + signerAddresses, err := evm.OnchainPublicKeyToAddress(signers) + require.NoError(t, err) + offchainTransmitters := make([][32]byte, nNodes) + for i := 0; i < nNodes; i++ { + offchainTransmitters[i] = nodes[i].ClientPubKey + } + donIDPadded := llo.DonIDToBytes32(donID) + _, err = legacyVerifier.SetConfig(steve, donIDPadded, signerAddresses, offchainTransmitters, fNodes, onchainConfig, offchainConfigVersion, offchainConfig, nil) + require.NoError(t, err) + + // libocr requires a few confirmations to accept the config + backend.Commit() + backend.Commit() + backend.Commit() + backend.Commit() + + l, err := legacyVerifier.LatestConfigDigestAndEpoch(&bind.CallOpts{}, donIDPadded) + require.NoError(t, err) + + return l.ConfigDigest +} + +func setStagingConfig(t *testing.T, donID uint32, steve *bind.TransactOpts, backend *backends.SimulatedBackend, configurator *configurator.Configurator, configuratorAddress common.Address, nodes []Node, oracles []confighelper.OracleIdentityExtra, predecessorConfigDigest ocr2types.ConfigDigest) ocr2types.ConfigDigest { + return setBlueGreenConfig(t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, &predecessorConfigDigest) +} + +func setProductionConfig(t *testing.T, donID uint32, steve *bind.TransactOpts, backend *backends.SimulatedBackend, configurator *configurator.Configurator, configuratorAddress common.Address, nodes []Node, oracles []confighelper.OracleIdentityExtra) ocr2types.ConfigDigest { + return setBlueGreenConfig(t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, nil) +} + +func setBlueGreenConfig(t *testing.T, donID uint32, steve *bind.TransactOpts, backend *backends.SimulatedBackend, configurator *configurator.Configurator, configuratorAddress common.Address, nodes []Node, oracles []confighelper.OracleIdentityExtra, predecessorConfigDigest *ocr2types.ConfigDigest) ocr2types.ConfigDigest { + signers, _, _, onchainConfig, offchainConfigVersion, offchainConfig := generateBlueGreenConfig(t, oracles, predecessorConfigDigest) + + var onchainPubKeys [][]byte + for _, signer := range signers { + onchainPubKeys = append(onchainPubKeys, signer) + } + offchainTransmitters := make([][32]byte, nNodes) + for i := 0; i < nNodes; i++ { + offchainTransmitters[i] = nodes[i].ClientPubKey + } + donIDPadded := llo.DonIDToBytes32(donID) + isProduction := predecessorConfigDigest == nil + var err error + if isProduction { + _, err = configurator.SetProductionConfig(steve, donIDPadded, onchainPubKeys, offchainTransmitters, fNodes, onchainConfig, offchainConfigVersion, offchainConfig) + } else { + _, err = configurator.SetStagingConfig(steve, donIDPadded, onchainPubKeys, offchainTransmitters, fNodes, onchainConfig, offchainConfigVersion, offchainConfig) + } + require.NoError(t, err) + + // libocr requires a few confirmations to accept the config + backend.Commit() + backend.Commit() + backend.Commit() + backend.Commit() + + var topic common.Hash + if isProduction { + topic = llo.ProductionConfigSet + } else { + topic = llo.StagingConfigSet + } + logs, err := backend.FilterLogs(testutils.Context(t), ethereum.FilterQuery{Addresses: []common.Address{configuratorAddress}, Topics: [][]common.Hash{[]common.Hash{topic, donIDPadded}}}) + require.NoError(t, err) + require.GreaterOrEqual(t, len(logs), 1) + + cfg, err := mercury.ConfigFromLog(logs[len(logs)-1].Data) + require.NoError(t, err) + + return cfg.ConfigDigest +} + +func promoteStagingConfig(t *testing.T, donID uint32, steve *bind.TransactOpts, backend *backends.SimulatedBackend, configurator *configurator.Configurator, configuratorAddress common.Address, isGreenProduction bool) { + donIDPadded := llo.DonIDToBytes32(donID) + _, err := configurator.PromoteStagingConfig(steve, donIDPadded, isGreenProduction) + require.NoError(t, err) + + // libocr requires a few confirmations to accept the config + backend.Commit() + backend.Commit() + backend.Commit() + backend.Commit() +} + +func TestIntegration_LLO(t *testing.T) { + testStartTimeStamp := time.Now() + multiplier := decimal.New(1, 18) + expirationWindow := time.Hour / time.Second + + reqs := make(chan request, 100000) + serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + serverPubKey := serverKey.PublicKey + srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) + + clientCSAKeys := make([]csakey.KeyV2, nNodes) + clientPubKeys := make([]ed25519.PublicKey, nNodes) + for i := 0; i < nNodes; i++ { + k := big.NewInt(int64(i)) + key := csakey.MustNewV2XXXTestingOnly(k) + clientCSAKeys[i] = key + clientPubKeys[i] = key.PublicKey + } + + steve, backend, configurator, configuratorAddress, verifier, _, verifierProxy, _, configStore, configStoreAddress, legacyVerifier, legacyVerifierAddr, _, _ := setupBlockchain(t) + fromBlock := 1 + + // Setup bootstrap + bootstrapCSAKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + bootstrapNodePort := freeport.GetOne(t) + 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) { + serverURL := startMercuryServer(t, srv, clientPubKeys) + + donID := uint32(995544) + streams := []Stream{ethStream, linkStream, quoteStream1, quoteStream2} + streamMap := make(map[uint32]Stream) + for _, strm := range streams { + streamMap[strm.id] = strm + } + + // Setup oracle nodes + oracles, nodes := setupNodes(t, nNodes, backend, clientCSAKeys, streams) + + chainID := testutils.SimulatedChainID + relayType := "evm" + relayConfig := fmt.Sprintf(` +chainID = "%s" +fromBlock = %d +lloDonID = %d +lloConfigMode = "mercury" +`, chainID, fromBlock, donID) + addBootstrapJob(t, bootstrapNode, legacyVerifierAddr, "job-2", relayType, relayConfig) + + // Channel definitions + channelDefinitions := llotypes.ChannelDefinitions{ + 1: { + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: quoteStreamID1, + Aggregator: llotypes.AggregatorQuote, + }, + }, + Opts: llotypes.ChannelOpts([]byte(fmt.Sprintf(`{"baseUSDFee":"0.1","expirationWindow":%d,"feedId":"0x%x","multiplier":"%s"}`, expirationWindow, quoteStreamFeedID1, multiplier.String()))), + }, + 2: { + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: quoteStreamID2, + Aggregator: llotypes.AggregatorQuote, + }, + }, + Opts: llotypes.ChannelOpts([]byte(fmt.Sprintf(`{"baseUSDFee":"0.1","expirationWindow":%d,"feedId":"0x%x","multiplier":"%s"}`, expirationWindow, quoteStreamFeedID2, multiplier.String()))), + }, + } + + 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) + addOCRJobsEVMPremiumLegacy(t, streams, serverPubKey, serverURL, legacyVerifierAddr, bootstrapPeerID, bootstrapNodePort, nodes, configStoreAddress, clientPubKeys, pluginConfig, relayType, relayConfig) + + // Set config on configurator + setLegacyConfig( + t, donID, steve, backend, legacyVerifier, legacyVerifierAddr, nodes, oracles, + ) + + // Set config on the destination verifier + signerAddresses := make([]common.Address, len(oracles)) + for i, oracle := range oracles { + signerAddresses[i] = common.BytesToAddress(oracle.OracleIdentity.OnchainPublicKey) + } + { + recipientAddressesAndWeights := []destination_verifier.CommonAddressAndWeight{} + + _, err := verifier.SetConfig(steve, signerAddresses, fNodes, recipientAddressesAndWeights) + require.NoError(t, err) + backend.Commit() + } + + t.Run("receives at least one report per channel from each oracle when EAs are at 100% reliability", func(t *testing.T) { + // Expect at least one report per feed from each oracle + seen := make(map[[32]byte]map[credentials.StaticSizedPublicKey]struct{}) + for _, cd := range channelDefinitions { + var opts lloevm.ReportFormatEVMPremiumLegacyOpts + err := json.Unmarshal(cd.Opts, &opts) + require.NoError(t, err) + // feedID will be deleted when all n oracles have reported + seen[opts.FeedID] = make(map[credentials.StaticSizedPublicKey]struct{}, nNodes) + } + for req := range reqs { + v := make(map[string]interface{}) + err := mercury.PayloadTypes.UnpackIntoMap(v, req.req.Payload) + require.NoError(t, err) + report, exists := v["report"] + if !exists { + t.Fatalf("expected payload %#v to contain 'report'", v) + } + reportElems := make(map[string]interface{}) + err = reportcodecv3.ReportTypes.UnpackIntoMap(reportElems, report.([]byte)) + require.NoError(t, err) + + feedID := reportElems["feedId"].([32]uint8) + + if _, exists := seen[feedID]; !exists { + continue // already saw all oracles for this feed + } + + var expectedBm, expectedBid, expectedAsk *big.Int + if feedID == quoteStreamFeedID1 { + expectedBm = quoteStream1.baseBenchmarkPrice.Mul(multiplier).BigInt() + expectedBid = quoteStream1.baseBid.Mul(multiplier).BigInt() + expectedAsk = quoteStream1.baseAsk.Mul(multiplier).BigInt() + } else if feedID == quoteStreamFeedID2 { + expectedBm = quoteStream2.baseBenchmarkPrice.Mul(multiplier).BigInt() + expectedBid = quoteStream2.baseBid.Mul(multiplier).BigInt() + expectedAsk = quoteStream2.baseAsk.Mul(multiplier).BigInt() + } else { + t.Fatalf("unrecognized feedID: 0x%x", feedID) + } + + assert.GreaterOrEqual(t, reportElems["validFromTimestamp"].(uint32), uint32(testStartTimeStamp.Unix())) + assert.GreaterOrEqual(t, int(reportElems["observationsTimestamp"].(uint32)), int(testStartTimeStamp.Unix())) + assert.Equal(t, "33597747607000", reportElems["nativeFee"].(*big.Int).String()) + assert.Equal(t, "7547169811320755", reportElems["linkFee"].(*big.Int).String()) + assert.Equal(t, reportElems["observationsTimestamp"].(uint32)+uint32(expirationWindow), reportElems["expiresAt"].(uint32)) + assert.Equal(t, expectedBm.String(), reportElems["benchmarkPrice"].(*big.Int).String()) + assert.Equal(t, expectedBid.String(), reportElems["bid"].(*big.Int).String()) + assert.Equal(t, expectedAsk.String(), reportElems["ask"].(*big.Int).String()) + + t.Run(fmt.Sprintf("emulate mercury server verifying report (local verification) - node %x", req.pk), func(t *testing.T) { + rv := mercuryverifier.NewVerifier() + + reportSigners, err := rv.Verify(mercuryverifier.SignedReport{ + RawRs: v["rawRs"].([][32]byte), + RawSs: v["rawSs"].([][32]byte), + RawVs: v["rawVs"].([32]byte), + ReportContext: v["reportContext"].([3][32]byte), + Report: v["report"].([]byte), + }, fNodes, signerAddresses) + require.NoError(t, err) + assert.GreaterOrEqual(t, len(reportSigners), int(fNodes+1)) + assert.Subset(t, signerAddresses, reportSigners) + }) + + t.Run(fmt.Sprintf("test on-chain verification - node %x", req.pk), func(t *testing.T) { + t.Run("destination verifier", func(t *testing.T) { + _, err = verifierProxy.Verify(steve, req.req.Payload, []byte{}) + require.NoError(t, err) + }) + }) + + t.Logf("oracle %x reported for 0x%x", req.pk[:], feedID[:]) + + seen[feedID][req.pk] = struct{}{} + if len(seen[feedID]) == nNodes { + t.Logf("all oracles reported for 0x%x", feedID[:]) + delete(seen, feedID) + if len(seen) == 0 { + break // saw all oracles; success! + } + } + } + }) + }) + + t.Run("Blue/Green lifecycle (using JSON report format)", func(t *testing.T) { + 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) + + chainID := testutils.SimulatedChainID + relayType := "evm" + relayConfig := fmt.Sprintf(` +chainID = "%s" +fromBlock = %d +lloDonID = %d +lloConfigMode = "bluegreen" +`, chainID, fromBlock, donID) + addBootstrapJob(t, bootstrapNode, configuratorAddress, "job-3", relayType, relayConfig) + + // Channel definitions + channelDefinitions := llotypes.ChannelDefinitions{ + 1: { + ReportFormat: llotypes.ReportFormatJSON, + Streams: []llotypes.Stream{ + { + StreamID: ethStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + }, + } + 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) + addOCRJobsEVMPremiumLegacy(t, streams, serverPubKey, serverURL, configuratorAddress, bootstrapPeerID, bootstrapNodePort, nodes, configStoreAddress, clientPubKeys, pluginConfig, relayType, relayConfig) + + var blueDigest ocr2types.ConfigDigest + var greenDigest ocr2types.ConfigDigest + + allReports := make(map[types.ConfigDigest][]datastreamsllo.Report) + t.Run("start off with blue=production, green=staging (specimen reports)", func(t *testing.T) { + // Set config on configurator + blueDigest = setProductionConfig( + t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, + ) + + // NOTE: Wait until blue produces a report + + for req := range reqs { + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + + assert.Equal(t, blueDigest, r.ConfigDigest) + assert.False(t, r.Specimen) + assert.Len(t, r.Values, 1) + assert.Equal(t, "2976.39", r.Values[0].(*datastreamsllo.Decimal).String()) + break + } + }) + t.Run("setStagingConfig does not affect production", func(t *testing.T) { + greenDigest = setStagingConfig( + t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, blueDigest, + ) + + // NOTE: Wait until green produces the first "specimen" report + + for req := range reqs { + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + if r.Specimen { + assert.Len(t, r.Values, 1) + assert.Equal(t, "2976.39", r.Values[0].(*datastreamsllo.Decimal).String()) + + assert.Equal(t, greenDigest, r.ConfigDigest) + break + } + assert.Equal(t, blueDigest, r.ConfigDigest) + } + }) + t.Run("promoteStagingConfig flow has clean and gapless hand off from old production to newly promoted staging instance, leaving old production instance in 'retired' state", func(t *testing.T) { + promoteStagingConfig(t, donID, steve, backend, configurator, configuratorAddress, false) + + // 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) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + + if !r.Specimen && r.ConfigDigest == greenDigest { + break + } + } + + initialPromotedGreenReport := allReports[greenDigest][len(allReports[greenDigest])-1] + finalBlueReport := allReports[blueDigest][len(allReports[blueDigest])-1] + + for _, digest := range []ocr2types.ConfigDigest{blueDigest, greenDigest} { + // Transmissions are not guaranteed to be in order + sort.Slice(allReports[digest], func(i, j int) bool { + return allReports[digest][i].SeqNr < allReports[digest][j].SeqNr + }) + seenSeqNr := uint64(0) + highestObservationTs := uint32(0) + highestValidAfterSeconds := uint32(0) + for i := 0; i < len(allReports[digest]); i++ { + r := allReports[digest][i] + switch digest { + case greenDigest: + if i == len(allReports[digest])-1 { + assert.False(t, r.Specimen) + } else { + assert.True(t, r.Specimen) + } + case blueDigest: + assert.False(t, r.Specimen) + } + if r.SeqNr > seenSeqNr { + // skip first one + if highestObservationTs > 0 { + if digest == greenDigest && i == len(allReports[digest])-1 { + // NOTE: This actually CHANGES on the staging + // handover and can go backwards - the gapless + // handover test is handled below + break + } + assert.Equal(t, highestObservationTs, r.ValidAfterSeconds, "%d: (n-1)ObservationsTimestampSeconds->(n)ValidAfterSeconds should be gapless, got: %d vs %d", i, highestObservationTs, r.ValidAfterSeconds) + assert.Greater(t, r.ObservationTimestampSeconds, highestObservationTs, "%d: overlapping/duplicate report ObservationTimestampSeconds, got: %d vs %d", i, r.ObservationTimestampSeconds, highestObservationTs) + assert.Greater(t, r.ValidAfterSeconds, highestValidAfterSeconds, "%d: overlapping/duplicate report ValidAfterSeconds, got: %d vs %d", i, r.ValidAfterSeconds, highestValidAfterSeconds) + assert.Less(t, r.ValidAfterSeconds, r.ObservationTimestampSeconds) + } + seenSeqNr = r.SeqNr + highestObservationTs = r.ObservationTimestampSeconds + highestValidAfterSeconds = r.ValidAfterSeconds + } + } + } + + // Gapless handover + assert.Less(t, finalBlueReport.ValidAfterSeconds, finalBlueReport.ObservationTimestampSeconds) + assert.Equal(t, finalBlueReport.ObservationTimestampSeconds, initialPromotedGreenReport.ValidAfterSeconds) + assert.Less(t, initialPromotedGreenReport.ValidAfterSeconds, initialPromotedGreenReport.ObservationTimestampSeconds) + }) + t.Run("retired instance does not produce reports", func(t *testing.T) { + // NOTE: Wait for five "green" reports to be produced and assert no "blue" reports + + i := 0 + for req := range reqs { + i++ + if i == 5 { + break + } + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + assert.False(t, r.Specimen) + assert.Equal(t, greenDigest, r.ConfigDigest) + } + }) + t.Run("setStagingConfig replaces 'retired' instance with new config and starts producing specimen reports again", func(t *testing.T) { + blueDigest = setStagingConfig( + t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, greenDigest, + ) + + // NOTE: Wait until blue produces the first "specimen" report + + for req := range reqs { + _, _, r, _, err := (datastreamsllo.JSONReportCodec{}).UnpackDecode(req.req.Payload) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + if r.Specimen { + assert.Equal(t, blueDigest, r.ConfigDigest) + break + } + assert.Equal(t, greenDigest, r.ConfigDigest) + } + }) + t.Run("promoteStagingConfig swaps the instances again", func(t *testing.T) { + // TODO: Check that once an instance enters 'retired' state, it + // doesn't produce reports or bother making observations + promoteStagingConfig(t, donID, steve, backend, configurator, configuratorAddress, true) + + // 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) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + + if !r.Specimen && r.ConfigDigest == blueDigest { + break + } + } + + initialPromotedBlueReport := allReports[blueDigest][len(allReports[blueDigest])-1] + finalGreenReport := allReports[greenDigest][len(allReports[greenDigest])-1] + + // Gapless handover + assert.Less(t, finalGreenReport.ValidAfterSeconds, finalGreenReport.ObservationTimestampSeconds) + assert.Equal(t, finalGreenReport.ObservationTimestampSeconds, initialPromotedBlueReport.ValidAfterSeconds) + assert.Less(t, initialPromotedBlueReport.ValidAfterSeconds, initialPromotedBlueReport.ObservationTimestampSeconds) + }) + t.Run("adding a new channel definition is picked up on the fly", func(t *testing.T) { + channelDefinitions[2] = llotypes.ChannelDefinition{ + ReportFormat: llotypes.ReportFormatJSON, + Streams: []llotypes.Stream{ + { + StreamID: linkStreamID, + Aggregator: llotypes.AggregatorMedian, + }, + }, + } + + url, sha := newChannelDefinitionsServer(t, channelDefinitions) + + // Set channel definitions + _, err := configStore.SetChannelDefinitions(steve, donID, url, sha) + require.NoError(t, err) + backend.Commit() + + // 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) + require.NoError(t, err) + + allReports[r.ConfigDigest] = append(allReports[r.ConfigDigest], r) + + // Green is retired, it shouldn't be producing anything + assert.Equal(t, blueDigest, r.ConfigDigest) + assert.False(t, r.Specimen) + + if r.ChannelID == 2 { + assert.Len(t, r.Values, 1) + assert.Equal(t, "13.25", r.Values[0].(*datastreamsllo.Decimal).String()) + break + } + assert.Len(t, r.Values, 1) + assert.Equal(t, "2976.39", r.Values[0].(*datastreamsllo.Decimal).String()) + } + }) + t.Run("deleting the jobs turns off oracles and cleans up resources", func(t *testing.T) { + t.Skip("TODO - MERC-3524") + }) + t.Run("adding new jobs again picks up the correct configs", func(t *testing.T) { + t.Skip("TODO - MERC-3524") + }) + }) +} + +func setupNodes(t *testing.T, nNodes int, backend *backends.SimulatedBackend, clientCSAKeys []csakey.KeyV2, streams []Stream) (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]) + + nodes = append(nodes, Node{ + app, transmitter, kb, observedLogs, + }) + offchainPublicKey, _ := hex.DecodeString(strings.TrimPrefix(kb.OnChainPublicKey(), "0x")) + oracles = append(oracles, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: offchainPublicKey, + TransmitAccount: ocr2types.Account(fmt.Sprintf("%x", transmitter[:])), + OffchainPublicKey: kb.OffchainPublicKey(), + PeerID: peerID, + }, + ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), + }) + } + return +} + +func newChannelDefinitionsServer(t *testing.T, channelDefinitions llotypes.ChannelDefinitions) (url string, sha [32]byte) { + channelDefinitionsJSON, err := json.MarshalIndent(channelDefinitions, "", " ") + require.NoError(t, err) + channelDefinitionsSHA := sha3.Sum256(channelDefinitionsJSON) + + // Set up channel definitions server + channelDefinitionsServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "GET", r.Method) + assert.Equal(t, "application/json", r.Header.Get("Content-Type")) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, err := w.Write(channelDefinitionsJSON) + require.NoError(t, err) + })) + t.Cleanup(channelDefinitionsServer.Close) + return channelDefinitionsServer.URL, channelDefinitionsSHA +} diff --git a/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go b/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go index 9d2d52ce504..30460d4e6af 100644 --- a/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go +++ b/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go @@ -1,215 +1,368 @@ package llo_test import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "math/rand/v2" + "net/http" + "sync" "testing" + "time" + + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "golang.org/x/crypto/sha3" + + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" + "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/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/llo" ) +type mockHTTPClient struct { + resp *http.Response + err error + mu sync.Mutex +} + +func (h *mockHTTPClient) Do(req *http.Request) (*http.Response, error) { + h.mu.Lock() + defer h.mu.Unlock() + return h.resp, h.err +} + +func (h *mockHTTPClient) SetResponse(resp *http.Response, err error) { + h.mu.Lock() + defer h.mu.Unlock() + h.resp = resp + h.err = err +} + +type MockReadCloser struct { + data []byte + mu sync.Mutex + reader *bytes.Reader +} + +func NewMockReadCloser(data []byte) *MockReadCloser { + return &MockReadCloser{ + data: data, + reader: bytes.NewReader(data), + } +} + +// Read reads from the underlying data +func (m *MockReadCloser) Read(p []byte) (int, error) { + m.mu.Lock() + defer m.mu.Unlock() + return m.reader.Read(p) +} + +// Close resets the reader to the beginning of the data +func (m *MockReadCloser) Close() error { + m.mu.Lock() + defer m.mu.Unlock() + _, err := m.reader.Seek(0, io.SeekStart) + return err +} + func Test_ChannelDefinitionCache_Integration(t *testing.T) { - t.Skip("waiting on https://github.com/smartcontractkit/chainlink/pull/13780") - // lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.InfoLevel) - // db := pgtest.NewSqlxDB(t) - // ctx := testutils.Context(t) - // orm := llo.NewORM(db, testutils.SimulatedChainID) - - // steve := testutils.MustNewSimTransactor(t) // config contract deployer and owner - // genesisData := core.GenesisAlloc{steve.From: {Balance: assets.Ether(1000).ToInt()}} - // backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) - // backend.Commit() // ensure starting block number at least 1 - - // ethClient := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) - - // configStoreAddress, _, configStoreContract, err := channel_config_store.DeployChannelConfigStore(steve, backend) - // require.NoError(t, err) - - // channel1 := rand.Uint32() - // channel2 := rand.Uint32() - // channel3 := rand.Uint32() - - // chainSelector, err := chainselectors.SelectorFromChainId(testutils.SimulatedChainID.Uint64()) - // require.NoError(t, err) - - // streamIDs := []uint32{1, 2, 3} - // channel1Def := channel_config_store.IChannelConfigStoreChannelDefinition{ - // ReportFormat: uint32(llotypes.ReportFormatSolana), - // ChainSelector: chainSelector, - // StreamIDs: streamIDs, - // } - // channel2Def := channel_config_store.IChannelConfigStoreChannelDefinition{ - // ReportFormat: uint32(llotypes.ReportFormatEVM), - // ChainSelector: chainSelector, - // StreamIDs: streamIDs, - // } - // channel3Def := channel_config_store.IChannelConfigStoreChannelDefinition{ - // ReportFormat: uint32(llotypes.ReportFormatEVM), - // ChainSelector: chainSelector, - // StreamIDs: append(streamIDs, 4), - // } - - // require.NoError(t, utils.JustError(configStoreContract.AddChannel(steve, channel1, channel1Def))) - // require.NoError(t, utils.JustError(configStoreContract.AddChannel(steve, channel2, channel2Def))) - - // h := backend.Commit() - // channel2Block, err := backend.BlockByHash(ctx, h) - // require.NoError(t, err) - - // t.Run("with zero fromblock", func(t *testing.T) { - // lpOpts := logpoller.Opts{ - // PollPeriod: 100 * time.Millisecond, - // FinalityDepth: 1, - // BackfillBatchSize: 3, - // RpcBatchSize: 2, - // KeepFinalizedBlocksDepth: 1000, - // } - // ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - // lp := logpoller.NewLogPoller( - // logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts) - // servicetest.Run(t, lp) - // cdc := llo.NewChannelDefinitionCache(lggr, orm, lp, configStoreAddress, 0) - - // servicetest.Run(t, cdc) - - // testutils.WaitForLogMessage(t, observedLogs, "Updated channel definitions") - - // dfns := cdc.Definitions() - - // require.Len(t, dfns, 2) - // require.Contains(t, dfns, channel1) - // require.Contains(t, dfns, channel2) - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatSolana, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3}, - // }, dfns[channel1]) - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3}, - // }, dfns[channel2]) - - // // remove solana - // require.NoError(t, utils.JustError(configStoreContract.RemoveChannel(steve, channel1))) - // backend.Commit() - // testutils.WaitForLogMessageCount(t, observedLogs, "Updated channel definitions", 2) - // dfns = cdc.Definitions() - - // require.Len(t, dfns, 1) - // assert.NotContains(t, dfns, channel1) - // require.Contains(t, dfns, channel2) - - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3}, - // }, dfns[channel2]) - - // // add channel3 with additional stream - // require.NoError(t, utils.JustError(configStoreContract.AddChannel(steve, channel3, channel3Def))) - // backend.Commit() - // testutils.WaitForLogMessageCount(t, observedLogs, "Updated channel definitions", 3) - // dfns = cdc.Definitions() - - // require.Len(t, dfns, 2) - // require.Contains(t, dfns, channel2) - // require.Contains(t, dfns, channel3) - - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3}, - // }, dfns[channel2]) - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3, 4}, - // }, dfns[channel3]) - // }) - - // t.Run("loads from ORM", func(t *testing.T) { - // // Override logpoller to always return no logs - // lpOpts := logpoller.Opts{ - // PollPeriod: 100 * time.Millisecond, - // FinalityDepth: 1, - // BackfillBatchSize: 3, - // RpcBatchSize: 2, - // KeepFinalizedBlocksDepth: 1000, - // } - // ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - // lp := &mockLogPoller{ - // LogPoller: logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts), - // LatestBlockFn: func(ctx context.Context) (int64, error) { - // return 0, nil - // }, - // LogsWithSigsFn: func(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { - // return []logpoller.Log{}, nil - // }, - // } - // cdc := llo.NewChannelDefinitionCache(lggr, orm, lp, configStoreAddress, 0) - - // servicetest.Run(t, cdc) - - // dfns := cdc.Definitions() - - // require.Len(t, dfns, 2) - // require.Contains(t, dfns, channel2) - // require.Contains(t, dfns, channel3) - - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3}, - // }, dfns[channel2]) - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3, 4}, - // }, dfns[channel3]) - // }) - - // // clear out DB for next test - // pgtest.MustExec(t, db, `DELETE FROM channel_definitions`) - - // t.Run("with non-zero fromBlock", func(t *testing.T) { - // lpOpts := logpoller.Opts{ - // PollPeriod: 100 * time.Millisecond, - // FinalityDepth: 1, - // BackfillBatchSize: 3, - // RpcBatchSize: 2, - // KeepFinalizedBlocksDepth: 1000, - // } - // ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - // lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts) - // servicetest.Run(t, lp) - // cdc := llo.NewChannelDefinitionCache(lggr, orm, lp, configStoreAddress, channel2Block.Number().Int64()+1) - - // // should only detect events from AFTER channel 2 was added - // servicetest.Run(t, cdc) - - // testutils.WaitForLogMessageCount(t, observedLogs, "Updated channel definitions", 4) - - // dfns := cdc.Definitions() - - // require.Len(t, dfns, 1) - // require.Contains(t, dfns, channel3) - - // assert.Equal(t, llotypes.ChannelDefinition{ - // ReportFormat: llotypes.ReportFormatEVM, - // ChainSelector: chainSelector, - // StreamIDs: []uint32{1, 2, 3, 4}, - // }, dfns[channel3]) - // }) - // } - - // type mockLogPoller struct { - // logpoller.LogPoller - // LatestBlockFn func(ctx context.Context) (int64, error) - // LogsWithSigsFn func(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) - // } - - // func (p *mockLogPoller) LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { - // return p.LogsWithSigsFn(ctx, start, end, eventSigs, address) - // } - // - // func (p *mockLogPoller) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) { - // block, err := p.LatestBlockFn(ctx) - // return logpoller.LogPollerBlock{BlockNumber: block}, err + var ( + invalidDefinitions = []byte(`{{{`) + invalidDefinitionsSHA = sha3.Sum256(invalidDefinitions) + + sampleDefinitions = llotypes.ChannelDefinitions{ + 1: { + ReportFormat: llotypes.ReportFormatJSON, + Streams: []llotypes.Stream{ + { + StreamID: 1, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: 2, + Aggregator: llotypes.AggregatorMode, + }, + }, + }, + 2: { + ReportFormat: llotypes.ReportFormatEVMPremiumLegacy, + Streams: []llotypes.Stream{ + { + StreamID: 1, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: 2, + Aggregator: llotypes.AggregatorMedian, + }, + { + StreamID: 3, + Aggregator: llotypes.AggregatorQuote, + }, + }, + Opts: llotypes.ChannelOpts([]byte(`{"baseUSDFee":"0.1","expirationWindow":86400,"feedId":"0x0003aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","multiplier":"1000000000000000000"}`)), + }, + } + ) + + sampleDefinitionsJSON, err := json.MarshalIndent(sampleDefinitions, "", " ") + require.NoError(t, err) + sampleDefinitionsSHA := sha3.Sum256(sampleDefinitionsJSON) + + lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) + db := pgtest.NewSqlxDB(t) + const ETHMainnetChainSelector uint64 = 5009297550715157269 + orm := llo.NewChainScopedORM(db, ETHMainnetChainSelector) + + steve := testutils.MustNewSimTransactor(t) // config contract deployer and owner + genesisData := core.GenesisAlloc{steve.From: {Balance: assets.Ether(1000).ToInt()}} + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + backend.Commit() // ensure starting block number at least 1 + + ethClient := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) + + configStoreAddress, _, configStoreContract, err := channel_config_store.DeployChannelConfigStore(steve, backend) + require.NoError(t, err) + + lpOpts := logpoller.Opts{ + PollPeriod: 100 * time.Millisecond, + FinalityDepth: 1, + BackfillBatchSize: 3, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 1000, + } + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller( + logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts) + servicetest.Run(t, lp) + + client := &mockHTTPClient{} + donID := rand.Uint32() + + cdc := llo.NewChannelDefinitionCache(lggr, orm, client, lp, configStoreAddress, donID, 0, llo.WithLogPollInterval(100*time.Millisecond)) + servicetest.Run(t, cdc) + + t.Run("before any logs, returns empty Definitions", func(t *testing.T) { + assert.Empty(t, cdc.Definitions()) + }) + + { + rc := NewMockReadCloser(invalidDefinitions) + client.SetResponse(&http.Response{ + StatusCode: 200, + Body: rc, + }, nil) + + url := "http://example.com/foo" + require.NoError(t, utils.JustError(configStoreContract.SetChannelDefinitions(steve, donID, url, sampleDefinitionsSHA))) + + backend.Commit() + } + + t.Run("with sha mismatch, should not update", func(t *testing.T) { + // clear the log messages + t.Cleanup(func() { observedLogs.TakeAll() }) + + testutils.WaitForLogMessage(t, observedLogs, "Got new channel definitions from chain") + le := testutils.WaitForLogMessage(t, observedLogs, "Error while fetching channel definitions") + fields := le.ContextMap() + assert.Contains(t, fields, "err") + assert.Equal(t, fmt.Sprintf("SHA3 mismatch: expected %x, got %x", sampleDefinitionsSHA, invalidDefinitionsSHA), fields["err"]) + + assert.Empty(t, cdc.Definitions()) + }) + + { + rc := NewMockReadCloser(invalidDefinitions) + client.SetResponse(&http.Response{ + StatusCode: 200, + Body: rc, + }, nil) + + url := "http://example.com/foo" + require.NoError(t, utils.JustError(configStoreContract.SetChannelDefinitions(steve, donID, url, invalidDefinitionsSHA))) + backend.Commit() + } + + t.Run("after correcting sha with new channel definitions set on-chain, but with invalid JSON at url, should not update", func(t *testing.T) { + // clear the log messages + t.Cleanup(func() { observedLogs.TakeAll() }) + + testutils.WaitForLogMessage(t, observedLogs, "Got new channel definitions from chain") + testutils.WaitForLogMessageWithField(t, observedLogs, "Error while fetching channel definitions", "err", "failed to decode JSON: invalid character '{' looking for beginning of object key string") + + assert.Empty(t, cdc.Definitions()) + }) + + { + rc := NewMockReadCloser([]byte("not found")) + client.SetResponse(&http.Response{ + StatusCode: 404, + Body: rc, + }, nil) + + url := "http://example.com/foo3" + require.NoError(t, utils.JustError(configStoreContract.SetChannelDefinitions(steve, donID, url, sampleDefinitionsSHA))) + backend.Commit() + } + + t.Run("if server returns 404, should not update", func(t *testing.T) { + // clear the log messages + t.Cleanup(func() { observedLogs.TakeAll() }) + + testutils.WaitForLogMessageWithField(t, observedLogs, "Error while fetching channel definitions", "err", "got error from http://example.com/foo3: (status code: 404, response body: not found)") + }) + + { + rc := NewMockReadCloser([]byte{}) + client.SetResponse(&http.Response{ + StatusCode: 200, + Body: rc, + }, nil) + } + + t.Run("if server starts returning empty body, still does not update", func(t *testing.T) { + // clear the log messages + t.Cleanup(func() { observedLogs.TakeAll() }) + + testutils.WaitForLogMessageWithField(t, observedLogs, "Error while fetching channel definitions", "err", fmt.Sprintf("SHA3 mismatch: expected %x, got %x", sampleDefinitionsSHA, sha3.Sum256([]byte{}))) + }) + + { + rc := NewMockReadCloser(sampleDefinitionsJSON) + client.SetResponse(&http.Response{ + StatusCode: 200, + Body: rc, + }, nil) + } + + t.Run("when URL starts returning valid JSON, updates even without needing new logs", func(t *testing.T) { + // clear the log messages + t.Cleanup(func() { observedLogs.TakeAll() }) + + le := testutils.WaitForLogMessage(t, observedLogs, "Set new channel definitions") + fields := le.ContextMap() + assert.Contains(t, fields, "version") + assert.Contains(t, fields, "url") + assert.Contains(t, fields, "sha") + assert.Contains(t, fields, "donID") + assert.NotContains(t, fields, "err") + + assert.Equal(t, uint32(3), fields["version"]) + assert.Equal(t, "http://example.com/foo3", fields["url"]) + assert.Equal(t, fmt.Sprintf("%x", sampleDefinitionsSHA), fields["sha"]) + assert.Equal(t, donID, fields["donID"]) + + assert.Equal(t, sampleDefinitions, cdc.Definitions()) + + t.Run("latest channel definitions are persisted", func(t *testing.T) { + pd, err := orm.LoadChannelDefinitions(testutils.Context(t), configStoreAddress, donID) + require.NoError(t, err) + assert.Equal(t, ETHMainnetChainSelector, pd.ChainSelector) + assert.Equal(t, configStoreAddress, pd.Address) + assert.Equal(t, sampleDefinitions, pd.Definitions) + assert.Equal(t, donID, pd.DonID) + assert.Equal(t, uint32(3), pd.Version) + }) + + t.Run("new cdc with same config should load from DB", func(t *testing.T) { + // fromBlock far in the future to ensure logs are not used + cdc2 := llo.NewChannelDefinitionCache(lggr, orm, client, lp, configStoreAddress, donID, 1000) + servicetest.Run(t, cdc2) + + assert.Equal(t, sampleDefinitions, cdc.Definitions()) + }) + }) + + { + url := "not a real URL" + require.NoError(t, utils.JustError(configStoreContract.SetChannelDefinitions(steve, donID, url, sampleDefinitionsSHA))) + + backend.Commit() + + client.SetResponse(nil, errors.New("failed; not a real URL")) + } + + t.Run("new log with invalid channel definitions URL does not affect old channel definitions", func(t *testing.T) { + // clear the log messages + t.Cleanup(func() { observedLogs.TakeAll() }) + + le := testutils.WaitForLogMessage(t, observedLogs, "Error while fetching channel definitions") + fields := le.ContextMap() + assert.Contains(t, fields, "err") + assert.Equal(t, "error making http request: failed; not a real URL", fields["err"]) + }) + + { + // add a new definition, it should get loaded + sampleDefinitions[3] = llotypes.ChannelDefinition{ + ReportFormat: llotypes.ReportFormatJSON, + Streams: []llotypes.Stream{ + { + StreamID: 6, + Aggregator: llotypes.AggregatorMedian, + }, + }, + } + var err error + sampleDefinitionsJSON, err = json.MarshalIndent(sampleDefinitions, "", " ") + require.NoError(t, err) + sampleDefinitionsSHA = sha3.Sum256(sampleDefinitionsJSON) + rc := NewMockReadCloser(sampleDefinitionsJSON) + client.SetResponse(&http.Response{ + StatusCode: 200, + Body: rc, + }, nil) + + url := "http://example.com/foo5" + require.NoError(t, utils.JustError(configStoreContract.SetChannelDefinitions(steve, donID, url, sampleDefinitionsSHA))) + + backend.Commit() + } + + t.Run("successfully updates to new channel definitions with new log", func(t *testing.T) { + t.Cleanup(func() { observedLogs.TakeAll() }) + + le := testutils.WaitForLogMessage(t, observedLogs, "Set new channel definitions") + fields := le.ContextMap() + assert.Contains(t, fields, "version") + assert.Contains(t, fields, "url") + assert.Contains(t, fields, "sha") + assert.Contains(t, fields, "donID") + assert.NotContains(t, fields, "err") + + assert.Equal(t, uint32(5), fields["version"]) + assert.Equal(t, "http://example.com/foo5", fields["url"]) + assert.Equal(t, fmt.Sprintf("%x", sampleDefinitionsSHA), fields["sha"]) + assert.Equal(t, donID, fields["donID"]) + + assert.Equal(t, sampleDefinitions, cdc.Definitions()) + }) + + t.Run("latest channel definitions are persisted and overwrite previous value", func(t *testing.T) { + pd, err := orm.LoadChannelDefinitions(testutils.Context(t), configStoreAddress, donID) + require.NoError(t, err) + assert.Equal(t, ETHMainnetChainSelector, pd.ChainSelector) + assert.Equal(t, configStoreAddress, pd.Address) + assert.Equal(t, sampleDefinitions, pd.Definitions) + assert.Equal(t, donID, pd.DonID) + assert.Equal(t, uint32(5), pd.Version) + }) } diff --git a/core/services/ocr2/plugins/median/services.go b/core/services/ocr2/plugins/median/services.go index 897531b82fb..c696bef8607 100644 --- a/core/services/ocr2/plugins/median/services.go +++ b/core/services/ocr2/plugins/median/services.go @@ -63,7 +63,6 @@ func NewMedianServices(ctx context.Context, cfg MedianConfig, chEnhancedTelem chan ocrcommon.EnhancedTelemetryData, errorLog loop.ErrorLog, - ) (srvs []job.ServiceCtx, err error) { var pluginConfig config.PluginConfig err = json.Unmarshal(jb.OCR2OracleSpec.PluginConfig.Bytes(), &pluginConfig) @@ -86,6 +85,7 @@ func NewMedianServices(ctx context.Context, provider, err := relayer.NewPluginProvider(ctx, types.RelayArgs{ ExternalJobID: jb.ExternalJobID, JobID: jb.ID, + OracleSpecID: *jb.OCR2OracleSpecID, ContractID: spec.ContractID, New: isNewlyCreatedJob, RelayConfig: spec.RelayConfig.Bytes(), @@ -167,11 +167,11 @@ func NewMedianServices(ctx context.Context, abort() return } - median := loop.NewMedianService(lggr, telem, cmdFn, medianProvider, dataSource, juelsPerFeeCoinSource, gasPriceSubunitsDataSource, errorLog) + median := loop.NewMedianService(lggr, telem, cmdFn, medianProvider, spec.ContractID, dataSource, juelsPerFeeCoinSource, gasPriceSubunitsDataSource, errorLog) argsNoPlugin.ReportingPluginFactory = median srvs = append(srvs, median) } else { - argsNoPlugin.ReportingPluginFactory, err = median.NewPlugin(lggr).NewMedianFactory(ctx, medianProvider, dataSource, juelsPerFeeCoinSource, gasPriceSubunitsDataSource, errorLog) + argsNoPlugin.ReportingPluginFactory, err = median.NewPlugin(lggr).NewMedianFactory(ctx, medianProvider, spec.ContractID, dataSource, juelsPerFeeCoinSource, gasPriceSubunitsDataSource, errorLog) if err != nil { err = fmt.Errorf("failed to create median factory: %w", err) abort() diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go index 9691e8d4fab..48d320c8de1 100644 --- a/core/services/ocr2/plugins/mercury/helpers_test.go +++ b/core/services/ocr2/plugins/mercury/helpers_test.go @@ -27,9 +27,9 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -42,6 +42,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) var _ pb.MercuryServer = &mercuryServer{} @@ -103,7 +104,7 @@ func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.Publ t.Fatalf("[MAIN] failed to listen: %v", err) } serverURL = lis.Addr().String() - s := wsrpc.NewServer(wsrpc.Creds(srv.privKey, pubKeys)) + s := wsrpc.NewServer(wsrpc.WithCreds(srv.privKey, pubKeys)) // Register mercury implementation with the wsrpc server pb.RegisterMercuryServer(s, srv) @@ -477,8 +478,6 @@ func addV4MercuryJob( bootstrapPeerID string, bootstrapNodePort int, bmBridge, - bidBridge, - askBridge, marketStatusBridge string, servers map[string]string, clientPubKey ed25519.PublicKey, @@ -496,11 +495,11 @@ func addV4MercuryJob( node.AddJob(t, fmt.Sprintf(` type = "offchainreporting2" schemaVersion = 1 -name = "mercury-%[1]d-%[11]s" +name = "mercury-%[1]d-%[9]s" forwardingAllowed = false maxTaskDuration = "1s" contractID = "%[2]s" -feedID = "0x%[10]x" +feedID = "0x%[8]x" contractConfigTrackerPollInterval = "1s" ocrKeyBundleID = "%[3]s" p2pv2Bootstrappers = [ @@ -508,7 +507,7 @@ p2pv2Bootstrappers = [ ] relay = "evm" pluginType = "mercury" -transmitterID = "%[9]x" +transmitterID = "%[7]x" observationSource = """ // Benchmark Price price1 [type=bridge name="%[5]s" timeout="50ms" requestData="{\\"data\\":{\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; @@ -517,31 +516,17 @@ observationSource = """ price1 -> price1_parse -> price1_multiply; - // Bid - bid [type=bridge name="%[6]s" timeout="50ms" requestData="{\\"data\\":{\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; - bid_parse [type=jsonparse path="result"]; - bid_multiply [type=multiply times=100000000 index=1]; - - bid -> bid_parse -> bid_multiply; - - // Ask - ask [type=bridge name="%[7]s" timeout="50ms" requestData="{\\"data\\":{\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; - ask_parse [type=jsonparse path="result"]; - ask_multiply [type=multiply times=100000000 index=2]; - - ask -> ask_parse -> ask_multiply; - // Market Status - marketstatus [type=bridge name="%[14]s" timeout="50ms" requestData="{\\"data\\":{\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; - marketstatus_parse [type=jsonparse path="result" index=3]; + marketstatus [type=bridge name="%[12]s" timeout="50ms" requestData="{\\"data\\":{\\"from\\":\\"ETH\\",\\"to\\":\\"USD\\"}}"]; + marketstatus_parse [type=jsonparse path="result" index=1]; marketstatus -> marketstatus_parse; """ [pluginConfig] -servers = %[8]s -linkFeedID = "0x%[12]x" -nativeFeedID = "0x%[13]x" +servers = %[6]s +linkFeedID = "0x%[10]x" +nativeFeedID = "0x%[11]x" [relayConfig] chainID = 1337 @@ -551,8 +536,6 @@ chainID = 1337 node.KeyBundle.ID(), fmt.Sprintf("%s@127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), bmBridge, - bidBridge, - askBridge, serversStr, clientPubKey, feedID, diff --git a/core/services/ocr2/plugins/mercury/integration_test.go b/core/services/ocr2/plugins/mercury/integration_test.go index 9e34e9da8b4..653ea574631 100644 --- a/core/services/ocr2/plugins/mercury/integration_test.go +++ b/core/services/ocr2/plugins/mercury/integration_test.go @@ -41,7 +41,7 @@ import ( datastreamsmercury "github.com/smartcontractkit/chainlink-data-streams/mercury" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - token "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" @@ -98,11 +98,11 @@ func setupBlockchain(t *testing.T) (*bind.TransactOpts, *backends.SimulatedBacke t.Cleanup(stopMining) // Deploy contracts - linkTokenAddress, _, linkToken, err := token.DeployLinkToken(steve, backend) + linkTokenAddress, _, linkToken, err := link_token_interface.DeployLinkToken(steve, backend) require.NoError(t, err) _, err = linkToken.Transfer(steve, steve.From, big.NewInt(1000)) require.NoError(t, err) - nativeTokenAddress, _, nativeToken, err := token.DeployLinkToken(steve, backend) + nativeTokenAddress, _, nativeToken, err := link_token_interface.DeployLinkToken(steve, backend) require.NoError(t, err) _, err = nativeToken.Transfer(steve, steve.From, big.NewInt(1000)) require.NoError(t, err) @@ -159,7 +159,7 @@ func integration_MercuryV1(t *testing.T) { serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) serverPubKey := serverKey.PublicKey srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs, func() []byte { - report, err := (&reportcodecv1.ReportCodec{}).BuildReport(v1.ReportFields{BenchmarkPrice: big.NewInt(234567), Bid: big.NewInt(1), Ask: big.NewInt(1), CurrentBlockHash: make([]byte, 32)}) + report, err := (&reportcodecv1.ReportCodec{}).BuildReport(ctx, v1.ReportFields{BenchmarkPrice: big.NewInt(234567), Bid: big.NewInt(1), Ask: big.NewInt(1), CurrentBlockHash: make([]byte, 32)}) if err != nil { panic(err) } @@ -284,7 +284,7 @@ func integration_MercuryV1(t *testing.T) { } } // Setup config on contract - onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(rawOnchainConfig) + onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(ctx, rawOnchainConfig) require.NoError(t, err) reportingPluginConfig, err := json.Marshal(rawReportingPluginConfig) @@ -302,8 +302,9 @@ func integration_MercuryV1(t *testing.T) { []int{len(nodes)}, // S oracles, reportingPluginConfig, // reportingPluginConfig []byte, - 250*time.Millisecond, // Max duration observation - int(f), // f + nil, + 250*time.Millisecond, // Max duration observation + int(f), // f onchainConfig, ) @@ -345,6 +346,7 @@ func integration_MercuryV1(t *testing.T) { } t.Run("receives at least one report per feed from each oracle when EAs are at 100% reliability", func(t *testing.T) { + ctx := testutils.Context(t) // Expect at least one report per feed from each oracle seen := make(map[[32]byte]map[credentials.StaticSizedPublicKey]struct{}) for i := range feeds { @@ -372,9 +374,9 @@ func integration_MercuryV1(t *testing.T) { continue // already saw all oracles for this feed } - num, err := (&reportcodecv1.ReportCodec{}).CurrentBlockNumFromReport(ocr2types.Report(report.([]byte))) + num, err := (&reportcodecv1.ReportCodec{}).CurrentBlockNumFromReport(ctx, ocr2types.Report(report.([]byte))) require.NoError(t, err) - currentBlock, err := backend.BlockByNumber(testutils.Context(t), nil) + currentBlock, err := backend.BlockByNumber(ctx, nil) require.NoError(t, err) assert.GreaterOrEqual(t, currentBlock.Number().Int64(), num) @@ -407,6 +409,7 @@ func integration_MercuryV1(t *testing.T) { }) t.Run("receives at least one report per feed from each oracle when EAs are at 80% reliability", func(t *testing.T) { + ctx := testutils.Context(t) pError.Store(20) // 20% chance of EA error // Expect at least one report per feed from each oracle @@ -436,7 +439,7 @@ func integration_MercuryV1(t *testing.T) { continue // already saw all oracles for this feed } - num, err := (&reportcodecv1.ReportCodec{}).CurrentBlockNumFromReport(ocr2types.Report(report.([]byte))) + num, err := (&reportcodecv1.ReportCodec{}).CurrentBlockNumFromReport(ctx, ocr2types.Report(report.([]byte))) require.NoError(t, err) currentBlock, err := backend.BlockByNumber(testutils.Context(t), nil) require.NoError(t, err) @@ -516,7 +519,7 @@ func integration_MercuryV2(t *testing.T) { serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) serverPubKey := serverKey.PublicKey srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs, func() []byte { - report, err := (&reportcodecv2.ReportCodec{}).BuildReport(v2.ReportFields{BenchmarkPrice: big.NewInt(234567), LinkFee: big.NewInt(1), NativeFee: big.NewInt(1)}) + report, err := (&reportcodecv2.ReportCodec{}).BuildReport(ctx, v2.ReportFields{BenchmarkPrice: big.NewInt(234567), LinkFee: big.NewInt(1), NativeFee: big.NewInt(1)}) if err != nil { panic(err) } @@ -635,7 +638,7 @@ func integration_MercuryV2(t *testing.T) { } // Setup config on contract - onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(rawOnchainConfig) + onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(ctx, rawOnchainConfig) require.NoError(t, err) reportingPluginConfig, err := json.Marshal(rawReportingPluginConfig) @@ -653,8 +656,9 @@ func integration_MercuryV2(t *testing.T) { []int{len(nodes)}, // S oracles, reportingPluginConfig, // reportingPluginConfig []byte, - 250*time.Millisecond, // Max duration observation - int(f), // f + nil, + 250*time.Millisecond, // Max duration observation + int(f), // f onchainConfig, ) @@ -810,7 +814,7 @@ func integration_MercuryV3(t *testing.T) { k := csakey.MustNewV2XXXTestingOnly(big.NewInt(int64(-(i + 1)))) reqs := make(chan request, 100) srv := NewMercuryServer(t, ed25519.PrivateKey(k.Raw()), reqs, func() []byte { - report, err := (&reportcodecv3.ReportCodec{}).BuildReport(v3.ReportFields{BenchmarkPrice: big.NewInt(234567), Bid: big.NewInt(1), Ask: big.NewInt(1), LinkFee: big.NewInt(1), NativeFee: big.NewInt(1)}) + report, err := (&reportcodecv3.ReportCodec{}).BuildReport(ctx, v3.ReportFields{BenchmarkPrice: big.NewInt(234567), Bid: big.NewInt(1), Ask: big.NewInt(1), LinkFee: big.NewInt(1), NativeFee: big.NewInt(1)}) if err != nil { panic(err) } @@ -927,7 +931,7 @@ func integration_MercuryV3(t *testing.T) { } // Setup config on contract - onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(rawOnchainConfig) + onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(ctx, rawOnchainConfig) require.NoError(t, err) reportingPluginConfig, err := json.Marshal(rawReportingPluginConfig) @@ -945,8 +949,9 @@ func integration_MercuryV3(t *testing.T) { []int{len(nodes)}, // S oracles, reportingPluginConfig, // reportingPluginConfig []byte, - 250*time.Millisecond, // Max duration observation - int(f), // f + nil, + 250*time.Millisecond, // Max duration observation + int(f), // f onchainConfig, ) @@ -1105,7 +1110,7 @@ func integration_MercuryV4(t *testing.T) { k := csakey.MustNewV2XXXTestingOnly(big.NewInt(int64(-(i + 1)))) reqs := make(chan request, 100) srv := NewMercuryServer(t, ed25519.PrivateKey(k.Raw()), reqs, func() []byte { - report, err := (&reportcodecv4.ReportCodec{}).BuildReport(v4.ReportFields{BenchmarkPrice: big.NewInt(234567), Bid: big.NewInt(1), Ask: big.NewInt(1), LinkFee: big.NewInt(1), NativeFee: big.NewInt(1), MarketStatus: 1}) + report, err := (&reportcodecv4.ReportCodec{}).BuildReport(ctx, v4.ReportFields{BenchmarkPrice: big.NewInt(234567), LinkFee: big.NewInt(1), NativeFee: big.NewInt(1), MarketStatus: 1}) if err != nil { panic(err) } @@ -1205,8 +1210,6 @@ func integration_MercuryV4(t *testing.T) { for i, node := range nodes { for j, feed := range feeds { bmBridge := createBridge(fmt.Sprintf("benchmarkprice-%d", j), i, feed.baseBenchmarkPrice, 0, node.App.BridgeORM()) - bidBridge := createBridge(fmt.Sprintf("bid-%d", j), i, feed.baseBid, 0, node.App.BridgeORM()) - askBridge := createBridge(fmt.Sprintf("ask-%d", j), i, feed.baseAsk, 0, node.App.BridgeORM()) marketStatusBridge := createBridge(fmt.Sprintf("marketstatus-%d", j), i, nil, feed.baseMarketStatus, node.App.BridgeORM()) addV4MercuryJob( @@ -1217,8 +1220,6 @@ func integration_MercuryV4(t *testing.T) { bootstrapPeerID, bootstrapNodePort, bmBridge, - bidBridge, - askBridge, marketStatusBridge, servers, clientPubKeys[i], @@ -1231,7 +1232,7 @@ func integration_MercuryV4(t *testing.T) { } // Setup config on contract - onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(rawOnchainConfig) + onchainConfig, err := (datastreamsmercury.StandardOnchainConfigCodec{}).Encode(ctx, rawOnchainConfig) require.NoError(t, err) reportingPluginConfig, err := json.Marshal(rawReportingPluginConfig) @@ -1249,8 +1250,9 @@ func integration_MercuryV4(t *testing.T) { []int{len(nodes)}, // S oracles, reportingPluginConfig, // reportingPluginConfig []byte, - 250*time.Millisecond, // Max duration observation - int(f), // f + nil, + 250*time.Millisecond, // Max duration observation + int(f), // f onchainConfig, ) @@ -1312,8 +1314,6 @@ func integration_MercuryV4(t *testing.T) { assert.GreaterOrEqual(t, int(reportElems["observationsTimestamp"].(uint32)), int(testStartTimeStamp)) assert.InDelta(t, feed.baseBenchmarkPrice.Int64(), reportElems["benchmarkPrice"].(*big.Int).Int64(), 5000000) - assert.InDelta(t, feed.baseBid.Int64(), reportElems["bid"].(*big.Int).Int64(), 5000000) - assert.InDelta(t, feed.baseAsk.Int64(), reportElems["ask"].(*big.Int).Int64(), 5000000) assert.NotZero(t, reportElems["validFromTimestamp"].(uint32)) assert.GreaterOrEqual(t, reportElems["observationsTimestamp"].(uint32), reportElems["validFromTimestamp"].(uint32)) assert.Equal(t, expectedExpiresAt, reportElems["expiresAt"].(uint32)) diff --git a/core/services/ocr2/plugins/mercury/plugin.go b/core/services/ocr2/plugins/mercury/plugin.go index 0898c1821ec..8a4101804dd 100644 --- a/core/services/ocr2/plugins/mercury/plugin.go +++ b/core/services/ocr2/plugins/mercury/plugin.go @@ -73,27 +73,36 @@ func NewServices( chEnhancedTelem chan ocrcommon.EnhancedTelemetryMercuryData, orm types.DataSourceORM, feedID utils.FeedID, + enableTriggerCapability bool, ) ([]job.ServiceCtx, error) { if jb.PipelineSpec == nil { return nil, errors.New("expected job to have a non-nil PipelineSpec") } + var err error var pluginConfig config.PluginConfig - err := json.Unmarshal(jb.OCR2OracleSpec.PluginConfig.Bytes(), &pluginConfig) - if err != nil { - return nil, errors.WithStack(err) - } - err = config.ValidatePluginConfig(pluginConfig, feedID) - if err != nil { - return nil, err + if len(jb.OCR2OracleSpec.PluginConfig) == 0 { + if !enableTriggerCapability { + return nil, fmt.Errorf("at least one transmission option must be configured") + } + } else { + err = json.Unmarshal(jb.OCR2OracleSpec.PluginConfig.Bytes(), &pluginConfig) + if err != nil { + return nil, errors.WithStack(err) + } + err = config.ValidatePluginConfig(pluginConfig, feedID) + if err != nil { + return nil, err + } } + lggr = lggr.Named("MercuryPlugin").With("jobID", jb.ID, "jobName", jb.Name.ValueOrZero()) // encapsulate all the subservices and ensure we close them all if any fail to start srvs := []job.ServiceCtx{ocr2Provider} abort := func() { - if cerr := services.MultiCloser(srvs).Close(); err != nil { - lggr.Errorw("Error closing unused services", "err", cerr) + if err = services.MultiCloser(srvs).Close(); err != nil { + lggr.Errorw("Error closing unused services", "err", err) } } saver := ocrcommon.NewResultRunSaver(pipelineRunner, lggr, cfg.MaxSuccessfulRuns(), cfg.ResultWriteQueueDepth()) @@ -171,10 +180,22 @@ type factoryCfg struct { feedID utils.FeedID } +func getPluginFeedIDs(pluginConfig config.PluginConfig) (linkFeedID utils.FeedID, nativeFeedID utils.FeedID) { + if pluginConfig.LinkFeedID != nil { + linkFeedID = *pluginConfig.LinkFeedID + } + if pluginConfig.NativeFeedID != nil { + nativeFeedID = *pluginConfig.NativeFeedID + } + return linkFeedID, nativeFeedID +} + func newv4factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job.ServiceCtx, error) { var factory ocr3types.MercuryPluginFactory srvs := make([]job.ServiceCtx, 0) + linkFeedID, nativeFeedID := getPluginFeedIDs(factoryCfg.reportingPluginConfig) + ds := mercuryv4.NewDataSource( factoryCfg.orm, factoryCfg.pipelineRunner, @@ -185,8 +206,8 @@ func newv4factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. factoryCfg.saver, factoryCfg.chEnhancedTelem, factoryCfg.ocr2Provider.MercuryServerFetcher(), - *factoryCfg.reportingPluginConfig.LinkFeedID, - *factoryCfg.reportingPluginConfig.NativeFeedID, + linkFeedID, + nativeFeedID, ) loopCmd := env.MercuryPlugin.Cmd.Get() @@ -212,6 +233,8 @@ func newv3factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. var factory ocr3types.MercuryPluginFactory srvs := make([]job.ServiceCtx, 0) + linkFeedID, nativeFeedID := getPluginFeedIDs(factoryCfg.reportingPluginConfig) + ds := mercuryv3.NewDataSource( factoryCfg.orm, factoryCfg.pipelineRunner, @@ -222,8 +245,8 @@ func newv3factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. factoryCfg.saver, factoryCfg.chEnhancedTelem, factoryCfg.ocr2Provider.MercuryServerFetcher(), - *factoryCfg.reportingPluginConfig.LinkFeedID, - *factoryCfg.reportingPluginConfig.NativeFeedID, + linkFeedID, + nativeFeedID, ) loopCmd := env.MercuryPlugin.Cmd.Get() @@ -249,6 +272,8 @@ func newv2factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. var factory ocr3types.MercuryPluginFactory srvs := make([]job.ServiceCtx, 0) + linkFeedID, nativeFeedID := getPluginFeedIDs(factoryCfg.reportingPluginConfig) + ds := mercuryv2.NewDataSource( factoryCfg.orm, factoryCfg.pipelineRunner, @@ -259,8 +284,8 @@ func newv2factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. factoryCfg.saver, factoryCfg.chEnhancedTelem, factoryCfg.ocr2Provider.MercuryServerFetcher(), - *factoryCfg.reportingPluginConfig.LinkFeedID, - *factoryCfg.reportingPluginConfig.NativeFeedID, + linkFeedID, + nativeFeedID, ) loopCmd := env.MercuryPlugin.Cmd.Get() diff --git a/core/services/ocr2/plugins/mercury/plugin_test.go b/core/services/ocr2/plugins/mercury/plugin_test.go index f9bef4a3f1a..22aaf7522de 100644 --- a/core/services/ocr2/plugins/mercury/plugin_test.go +++ b/core/services/ocr2/plugins/mercury/plugin_test.go @@ -230,13 +230,13 @@ func newServicesTestWrapper(t *testing.T, pluginConfig job.JSONConfig, feedID ut t.Helper() jb := testJob jb.OCR2OracleSpec.PluginConfig = pluginConfig - return mercuryocr2.NewServices(jb, &testProvider{}, nil, logger.TestLogger(t), testArgsNoPlugin, testCfg, nil, &testDataSourceORM{}, feedID) + return mercuryocr2.NewServices(jb, &testProvider{}, nil, logger.TestLogger(t), testArgsNoPlugin, testCfg, nil, &testDataSourceORM{}, feedID, false) } type testProvider struct{} // ChainReader implements types.MercuryProvider. -func (*testProvider) ChainReader() commontypes.ContractReader { panic("unimplemented") } +func (*testProvider) ContractReader() commontypes.ContractReader { panic("unimplemented") } // Close implements types.MercuryProvider. func (*testProvider) Close() error { return nil } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/log_provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/log_provider.go index 50c1e5b7c1a..1764fb7e7c3 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/log_provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/log_provider.go @@ -250,7 +250,7 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR vals := []ocr2keepers.StaleReportLog{} for _, r := range reorged { upkeepId := ocr2keepers.UpkeepIdentifier(r.Id.String()) - checkBlockNumber, err := c.getCheckBlockNumberFromTxHash(r.TxHash, upkeepId) + checkBlockNumber, err := c.getCheckBlockNumberFromTxHash(ctx, r.TxHash, upkeepId) if err != nil { c.logger.Error("error while fetching checkBlockNumber from reorged report log: %w", err) continue @@ -265,7 +265,7 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR } for _, r := range staleUpkeep { upkeepId := ocr2keepers.UpkeepIdentifier(r.Id.String()) - checkBlockNumber, err := c.getCheckBlockNumberFromTxHash(r.TxHash, upkeepId) + checkBlockNumber, err := c.getCheckBlockNumberFromTxHash(ctx, r.TxHash, upkeepId) if err != nil { c.logger.Error("error while fetching checkBlockNumber from stale report log: %w", err) continue @@ -280,7 +280,7 @@ func (c *LogProvider) StaleReportLogs(ctx context.Context) ([]ocr2keepers.StaleR } for _, r := range insufficientFunds { upkeepId := ocr2keepers.UpkeepIdentifier(r.Id.String()) - checkBlockNumber, err := c.getCheckBlockNumberFromTxHash(r.TxHash, upkeepId) + checkBlockNumber, err := c.getCheckBlockNumberFromTxHash(ctx, r.TxHash, upkeepId) if err != nil { c.logger.Error("error while fetching checkBlockNumber from insufficient funds report log: %w", err) continue @@ -411,7 +411,7 @@ func (c *LogProvider) unmarshalInsufficientFundsUpkeepLogs(logs []logpoller.Log) // Fetches the checkBlockNumber for a particular transaction and an upkeep ID. Requires a RPC call to get txData // so this function should not be used heavily -func (c *LogProvider) getCheckBlockNumberFromTxHash(txHash common.Hash, id ocr2keepers.UpkeepIdentifier) (bk ocr2keepers.BlockKey, e error) { +func (c *LogProvider) getCheckBlockNumberFromTxHash(ctx context.Context, txHash common.Hash, id ocr2keepers.UpkeepIdentifier) (bk ocr2keepers.BlockKey, e error) { defer func() { if r := recover(); r != nil { e = fmt.Errorf("recovered from panic in getCheckBlockNumberForUpkeep: %v", r) @@ -425,7 +425,7 @@ func (c *LogProvider) getCheckBlockNumberFromTxHash(txHash common.Hash, id ocr2k } var tx gethtypes.Transaction - err := c.client.CallContext(context.Background(), &tx, "eth_getTransactionByHash", txHash) + err := c.client.CallContext(ctx, &tx, "eth_getTransactionByHash", txHash) if err != nil { return "", err } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/autotelemetry21/custom_telemetry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/autotelemetry21/custom_telemetry.go index 53303553db7..2c997a2d385 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/autotelemetry21/custom_telemetry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/autotelemetry21/custom_telemetry.go @@ -3,6 +3,7 @@ package autotelemetry21 import ( "context" "encoding/hex" + "sync" "time" "google.golang.org/protobuf/proto" @@ -29,6 +30,7 @@ type AutomationCustomTelemetryService struct { lggr logger.Logger configDigest [32]byte contractConfigTracker types.ContractConfigTracker + mu sync.RWMutex } // NewAutomationCustomTelemetryService creates a telemetry service for new blocks and node version @@ -66,8 +68,15 @@ func (e *AutomationCustomTelemetryService) Start(ctx context.Context) error { if err != nil { e.lggr.Errorf("Error occurred while getting newestConfigDetails in configDigest loop %s", err) } + configChanged := false + e.mu.Lock() if newConfigDigest != e.configDigest { e.configDigest = newConfigDigest + configChanged = true + } + e.mu.Unlock() + + if configChanged { e.sendNodeVersionMsg() } case <-hourTicker.C: @@ -121,10 +130,14 @@ func (e *AutomationCustomTelemetryService) Close() error { } func (e *AutomationCustomTelemetryService) sendNodeVersionMsg() { + e.mu.RLock() + configDigest := e.configDigest + e.mu.RUnlock() + vMsg := &telem.NodeVersion{ Timestamp: uint64(time.Now().UTC().UnixMilli()), NodeVersion: static.Version, - ConfigDigest: e.configDigest[:], + ConfigDigest: configDigest[:], } wrappedVMsg := &telem.AutomationTelemWrapper{ Msg: &telem.AutomationTelemWrapper_NodeVersion{ @@ -141,11 +154,15 @@ func (e *AutomationCustomTelemetryService) sendNodeVersionMsg() { } func (e *AutomationCustomTelemetryService) sendBlockNumberMsg(blockKey ocr2keepers.BlockKey) { + e.mu.RLock() + configDigest := e.configDigest + e.mu.RUnlock() + blockNumMsg := &telem.BlockNumber{ Timestamp: uint64(time.Now().UTC().UnixMilli()), BlockNumber: uint64(blockKey.Number), BlockHash: hex.EncodeToString(blockKey.Hash[:]), - ConfigDigest: e.configDigest[:], + ConfigDigest: configDigest[:], } wrappedBlockNumMsg := &telem.AutomationTelemWrapper{ Msg: &telem.AutomationTelemWrapper_BlockNumber{ diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go index d07af8a8de4..21adc12d30e 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go @@ -9,14 +9,13 @@ import ( "github.com/ethereum/go-ethereum/common" - ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "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/logger" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -74,7 +73,7 @@ func NewBlockSubscriber(hb httypes.HeadBroadcaster, lp logpoller.LogPoller, fina blockSize: lookbackDepth, finalityDepth: finalityDepth, latestBlock: atomic.Pointer[ocr2keepers.BlockKey]{}, - lggr: lggr.Named("BlockSubscriber"), + lggr: logger.Named(lggr, "BlockSubscriber"), } } @@ -235,7 +234,7 @@ func (bs *BlockSubscriber) processHead(h *evmtypes.Head) { // head parent is a linked list with EVM finality depth // when re-org happens, new heads will have pointers to the new blocks i := int64(0) - for cp := h; cp != nil; cp = cp.Parent { + for cp := h; cp != nil; cp = cp.Parent.Load() { // we don't stop when a matching (block number/hash) entry is seen in the map because parent linked list may be // cut short during a re-org if head broadcaster backfill is not complete. This can cause some re-orged blocks // left in the map. for example, re-org happens for block 98, 99, 100. next head 101 from broadcaster has parent list diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber_test.go index fefbda77cd7..bdcc37dc6bb 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber_test.go @@ -310,23 +310,22 @@ func TestBlockSubscriber_Start(t *testing.T) { h97 := evmtypes.Head{ Number: 97, Hash: common.HexToHash("0xda2f9d1359eadd7b93338703adc07d942021a78195564038321ef53f23f87333"), - Parent: nil, } h98 := evmtypes.Head{ Number: 98, Hash: common.HexToHash("0xc20c7b47466c081a44a3b168994e89affe85cb894547845d938f923b67c633c0"), - Parent: &h97, } + h98.Parent.Store(&h97) h99 := evmtypes.Head{ Number: 99, Hash: common.HexToHash("0x9bc2b51e147f9cad05f1614b7f1d8181cb24c544cbcf841f3155e54e752a3b44"), - Parent: &h98, } + h99.Parent.Store(&h98) h100 := evmtypes.Head{ Number: 100, Hash: common.HexToHash("0x5e7fadfc14e1cfa9c05a91128c16a20c6cbc3be38b4723c3d482d44bf9c0e07b"), - Parent: &h99, } + h100.Parent.Store(&h99) // no subscribers yet bs.headC <- &h100 @@ -353,8 +352,8 @@ func TestBlockSubscriber_Start(t *testing.T) { h101 := &evmtypes.Head{ Number: 101, Hash: common.HexToHash("0xc20c7b47466c081a44a3b168994e89affe85cb894547845d938f923b67c633c0"), - Parent: &h100, } + h101.Parent.Store(&h100) bs.headC <- h101 time.Sleep(100 * time.Millisecond) @@ -387,24 +386,24 @@ func TestBlockSubscriber_Start(t *testing.T) { new99 := &evmtypes.Head{ Number: 99, Hash: common.HexToHash("0x70c03acc4ddbfb253ba41a25dc13fb21b25da8b63bcd1aa7fb55713d33a36c71"), - Parent: &h98, } + new99.Parent.Store(&h98) new100 := &evmtypes.Head{ Number: 100, Hash: common.HexToHash("0x8a876b62d252e63e16cf3487db3486c0a7c0a8e06bc3792a3b116c5ca480503f"), - Parent: new99, } + new100.Parent.Store(new99) new101 := &evmtypes.Head{ Number: 101, Hash: common.HexToHash("0x41b5842b8847dcf834e39556d2ac51cc7d960a7de9471ec504673d0038fd6c8e"), - Parent: new100, } + new101.Parent.Store(new100) new102 := &evmtypes.Head{ Number: 102, Hash: common.HexToHash("0x9ac1ebc307554cf1bcfcc2a49462278e89d6878d613a33df38a64d0aeac971b5"), - Parent: new101, } + new102.Parent.Store(new101) bs.headC <- new102 diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go index f84a48c1ff8..cec3c8bd20f 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go @@ -6,10 +6,11 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/cbor" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" ) @@ -45,28 +46,28 @@ func CheckGasPrice(ctx context.Context, upkeepId *big.Int, offchainConfigBytes [ } lggr.Debugf("successfully decode offchain config for %s, max gas price is %s", upkeepId.String(), offchainConfig.MaxGasPrice.String()) - fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice))) + fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice)), nil, nil) if err != nil { lggr.Errorw("failed to get fee, gas price check is disabled", "upkeepId", upkeepId.String(), "err", err) return encoding.UpkeepFailureReasonNone } if fee.ValidDynamic() { - lggr.Debugf("current gas price EIP-1559 is fee cap %s, tip cap %s", fee.DynamicFeeCap.String(), fee.DynamicTipCap.String()) - if fee.DynamicFeeCap.Cmp(assets.NewWei(offchainConfig.MaxGasPrice)) > 0 { + lggr.Debugf("current gas price EIP-1559 is fee cap %s, tip cap %s", fee.GasFeeCap.String(), fee.GasTipCap.String()) + if fee.GasFeeCap.Cmp(assets.NewWei(offchainConfig.MaxGasPrice)) > 0 { // current gas price is higher than max gas price - lggr.Warnf("maxGasPrice %s for %s is LOWER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.DynamicFeeCap.Int64()) + lggr.Warnf("maxGasPrice %s for %s is LOWER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.GasFeeCap.Int64()) return encoding.UpkeepFailureReasonGasPriceTooHigh } - lggr.Debugf("maxGasPrice %s for %s is HIGHER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.DynamicFeeCap.Int64()) + lggr.Debugf("maxGasPrice %s for %s is HIGHER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.GasFeeCap.Int64()) } else { - lggr.Debugf("current gas price legacy is %s", fee.Legacy.String()) - if fee.Legacy.Cmp(assets.NewWei(offchainConfig.MaxGasPrice)) > 0 { + lggr.Debugf("current gas price legacy is %s", fee.GasPrice.String()) + if fee.GasPrice.Cmp(assets.NewWei(offchainConfig.MaxGasPrice)) > 0 { // current gas price is higher than max gas price - lggr.Warnf("maxGasPrice %s for %s is LOWER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.Legacy.Int64()) + lggr.Warnf("maxGasPrice %s for %s is LOWER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.GasPrice.Int64()) return encoding.UpkeepFailureReasonGasPriceTooHigh } - lggr.Debugf("maxGasPrice %s for %s is HIGHER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.Legacy.Int64()) + lggr.Debugf("maxGasPrice %s for %s is HIGHER than current gas price %d", offchainConfig.MaxGasPrice.String(), upkeepId.String(), fee.GasPrice.Int64()) } return encoding.UpkeepFailureReasonNone diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go index 9b5640051df..5257260a570 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go @@ -86,24 +86,23 @@ func TestGasPrice_Check(t *testing.T) { ctx := testutils.Context(t) ge := gasMocks.NewEvmFeeEstimator(t) if test.FailedToGetFee { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{}, feeLimit, errors.New("failed to retrieve gas price"), ) } else if test.CurrentLegacyGasPrice != nil { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{ - Legacy: assets.NewWei(test.CurrentLegacyGasPrice), + GasPrice: assets.NewWei(test.CurrentLegacyGasPrice), }, feeLimit, nil, ) } else if test.CurrentDynamicGasPrice != nil { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{ - DynamicFeeCap: assets.NewWei(test.CurrentDynamicGasPrice), - DynamicTipCap: assets.NewWei(big.NewInt(1_000_000_000)), + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWei(test.CurrentDynamicGasPrice), GasTipCap: assets.NewWei(big.NewInt(1_000_000_000))}, }, feeLimit, nil, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1.go index e58d5ad9c93..00a56496a00 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1.go @@ -6,8 +6,9 @@ import ( "sync" "sync/atomic" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/prommetrics" ) @@ -79,7 +80,7 @@ type logBuffer struct { func NewLogBuffer(lggr logger.Logger, lookback, blockRate, logLimit uint32) LogBuffer { return &logBuffer{ - lggr: lggr.Named("KeepersRegistry.LogEventBufferV1"), + lggr: logger.Sugared(lggr).Named("KeepersRegistry").Named("LogEventBufferV1"), opts: newLogBufferOptions(lookback, blockRate, logLimit), lastBlockSeen: new(atomic.Int64), queueIDs: []string{}, @@ -313,7 +314,7 @@ type upkeepLogQueue struct { func newUpkeepLogQueue(lggr logger.Logger, id *big.Int, opts *logBufferOptions) *upkeepLogQueue { return &upkeepLogQueue{ - lggr: lggr.With("upkeepID", id.String()), + lggr: logger.With(lggr, "upkeepID", id.String()), id: id, opts: opts, logs: map[int64][]logpoller.Log{}, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1_test.go index f742d39689c..4c46b9b3fea 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_v1_test.go @@ -54,8 +54,6 @@ func TestLogEventBufferV1_SyncFilters(t *testing.T) { type readableLogger struct { logger.Logger DebugwFn func(msg string, keysAndValues ...interface{}) - NamedFn func(name string) logger.Logger - WithFn func(args ...interface{}) logger.Logger } func (l *readableLogger) Debugw(msg string, keysAndValues ...interface{}) { @@ -74,6 +72,7 @@ func TestLogEventBufferV1_EnqueueViolations(t *testing.T) { t.Run("enqueuing logs for a block older than latest seen logs a message", func(t *testing.T) { logReceived := false readableLogger := &readableLogger{ + Logger: logger.TestLogger(t), DebugwFn: func(msg string, keysAndValues ...interface{}) { if msg == "enqueuing logs from a block older than latest seen block" { logReceived = true @@ -103,6 +102,7 @@ func TestLogEventBufferV1_EnqueueViolations(t *testing.T) { t.Run("enqueuing logs for the same block over multiple calls logs a message", func(t *testing.T) { logReceived := false readableLogger := &readableLogger{ + Logger: logger.TestLogger(t), DebugwFn: func(msg string, keysAndValues ...interface{}) { if msg == "enqueuing logs again for a previously seen block" { logReceived = true diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go index 25cc5e939ba..57b48841a20 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go @@ -4,9 +4,10 @@ import ( "math/big" "time" + "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/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" ) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go index 99426093951..49741b79115 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go @@ -25,12 +25,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" evmregistry21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) func TestIntegration_LogEventProvider(t *testing.T) { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go index f1de1ef5129..50b2ebc0d06 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go @@ -16,13 +16,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/prommetrics" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -111,7 +110,7 @@ type logEventProvider struct { func NewLogProvider(lggr logger.Logger, poller logpoller.LogPoller, chainID *big.Int, packer LogDataPacker, filterStore UpkeepFilterStore, opts LogTriggersOptions) *logEventProvider { return &logEventProvider{ threadCtrl: utils.NewThreadControl(), - lggr: lggr.Named("KeepersRegistry.LogEventProvider"), + lggr: logger.Named(lggr, "KeepersRegistry.LogEventProvider"), packer: packer, buffer: NewLogBuffer(lggr, uint32(opts.LookbackBlocks), opts.BlockRate, opts.LogLimit), poller: poller, @@ -135,7 +134,7 @@ func (p *logEventProvider) SetConfig(cfg ocr2keepers.LogEventProviderConfig) { logLimit = p.opts.defaultLogLimit() } - p.lggr.With("where", "setConfig").Infow("setting config ", "bockRate", blockRate, "logLimit", logLimit) + p.lggr.Infow("setting config", "where", "setConfig", "bockRate", blockRate, "logLimit", logLimit) atomic.StoreUint32(&p.opts.BlockRate, blockRate) atomic.StoreUint32(&p.opts.LogLimit, logLimit) @@ -156,7 +155,7 @@ func (p *logEventProvider) Start(context.Context) error { } p.threadCtrl.Go(func(ctx context.Context) { - lggr := p.lggr.With("where", "scheduler") + lggr := logger.With(p.lggr, "where", "scheduler") p.scheduleReadJobs(ctx, func(ids []*big.Int) { select { @@ -369,7 +368,7 @@ func (p *logEventProvider) startReader(pctx context.Context, readQ <-chan []*big ctx, cancel := context.WithCancel(pctx) defer cancel() - lggr := p.lggr.With("where", "reader") + lggr := logger.With(p.lggr, "where", "reader") for { select { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_life_cycle.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_life_cycle.go index db47ac2ecd8..cbd493bf2e4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_life_cycle.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_life_cycle.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ) @@ -106,7 +108,7 @@ func (p *logEventProvider) register(ctx context.Context, lpFilter logpoller.Filt if err != nil { return fmt.Errorf("failed to get latest block while registering filter: %w", err) } - lggr := p.lggr.With("upkeepID", ufilter.upkeepID.String()) + lggr := logger.With(p.lggr, "upkeepID", ufilter.upkeepID.String()) logPollerHasFilter := p.poller.HasFilter(lpFilter.Name) filterStoreHasFilter := p.filterStore.Has(ufilter.upkeepID) if filterStoreHasFilter { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go index 9e41008ed83..984856bf3cd 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go @@ -14,18 +14,17 @@ import ( "sync/atomic" "time" - "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-automation/pkg/v3/random" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-automation/pkg/v3/random" + "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/prommetrics" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -71,7 +70,7 @@ type logRecoverer struct { services.StateMachine threadCtrl utils.ThreadControl - lggr logger.Logger + lggr logger.SugaredLogger lookbackBlocks *atomic.Int64 blockTime *atomic.Int64 @@ -96,7 +95,7 @@ var _ LogRecoverer = &logRecoverer{} func NewLogRecoverer(lggr logger.Logger, poller logpoller.LogPoller, client client.Client, stateStore core.UpkeepStateReader, packer LogDataPacker, filterStore UpkeepFilterStore, opts LogTriggersOptions) *logRecoverer { rec := &logRecoverer{ - lggr: lggr.Named(LogRecovererServiceName), + lggr: logger.Sugared(lggr).Named(LogRecovererServiceName), threadCtrl: utils.NewThreadControl(), diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go index 5a4b701f61a..17005939219 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams/streams.go @@ -15,11 +15,11 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/patrickmn/go-cache" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" autov2common "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" @@ -119,7 +119,7 @@ func (s *streams) Lookup(ctx context.Context, checkResults []ocr2keepers.CheckRe // buildResult checks if the upkeep is allowed by Mercury and builds a streams lookup request from the check result func (s *streams) buildResult(ctx context.Context, i int, checkResult ocr2keepers.CheckResult, checkResults []ocr2keepers.CheckResult, lookups map[int]*mercury.StreamsLookup) { - lookupLggr := s.lggr.With("where", "StreamsLookup") + lookupLggr := logger.Sugared(s.lggr).With("where", "StreamsLookup") if checkResult.IneligibilityReason != uint8(encoding.UpkeepFailureReasonTargetCheckReverted) { // Streams Lookup only works when upkeep target check reverts prommetrics.AutomationStreamsLookupError.WithLabelValues(prommetrics.StreamsLookupErrorReasonNotReverted).Inc() diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go index 5e954475a8d..c02b7c10de5 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/request.go @@ -11,14 +11,14 @@ import ( "strconv" "time" - automationTypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + "github.com/avast/retry-go/v4" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/avast/retry-go/v4" - "github.com/ethereum/go-ethereum/common/hexutil" + automationTypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/prommetrics" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go index 39a26b6b5d9..c2ffb2172b0 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/request.go @@ -10,14 +10,14 @@ import ( "strings" "time" - automationTypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + "github.com/avast/retry-go/v4" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/avast/retry-go/v4" - "github.com/ethereum/go-ethereum/common/hexutil" + automationTypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/prommetrics" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder.go index 7f29cb3b7ac..c6262899a32 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder.go @@ -3,11 +3,11 @@ package evm import ( "context" - "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - + "github.com/smartcontractkit/chainlink-common/pkg/logger" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" ) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go index 16b8627cf74..25bd7a445e4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go @@ -10,10 +10,6 @@ import ( "sync" "time" - types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -22,19 +18,20 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - + "github.com/smartcontractkit/chainlink-common/pkg/types" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" + types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + "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" + 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" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" @@ -98,7 +95,7 @@ func NewEvmRegistry( return &EvmRegistry{ stopCh: make(chan struct{}), threadCtrl: utils.NewThreadControl(), - lggr: lggr.Named(RegistryServiceName), + lggr: logger.Sugared(lggr).Named(RegistryServiceName), poller: client.LogPoller(), addr: addr, client: client.Client(), @@ -175,7 +172,7 @@ func (c *MercuryConfig) SetPluginRetry(k string, v interface{}, d time.Duration) type EvmRegistry struct { services.StateMachine threadCtrl utils.ThreadControl - lggr logger.Logger + lggr logger.SugaredLogger poller logpoller.LogPoller addr common.Address client client.Client diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go index 6f8785fda78..cb014e1d3ec 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline_test.go @@ -8,10 +8,6 @@ import ( "sync/atomic" "testing" - types3 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - - types2 "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" @@ -20,8 +16,12 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + types2 "github.com/smartcontractkit/chainlink-common/pkg/types" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" + types3 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" gasMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -30,7 +30,6 @@ import ( ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_compatible_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks" @@ -82,7 +81,7 @@ func TestRegistry_GetBlockAndUpkeepId(t *testing.T) { } func TestRegistry_VerifyCheckBlock(t *testing.T) { - lggr := logger.TestLogger(t) + lggr := logger.Test(t) upkeepId := ocr2keepers.UpkeepIdentifier{} upkeepId.FromBigInt(big.NewInt(12345)) tests := []struct { @@ -197,7 +196,7 @@ func TestRegistry_VerifyCheckBlock(t *testing.T) { } bs.latestBlock.Store(tc.latestBlock) e := &EvmRegistry{ - lggr: lggr, + lggr: logger.Sugared(lggr), bs: bs, poller: tc.poller, } @@ -229,7 +228,7 @@ func (p *mockLogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, a } func TestRegistry_VerifyLogExists(t *testing.T) { - lggr := logger.TestLogger(t) + lggr := logger.Test(t) upkeepId := ocr2keepers.UpkeepIdentifier{} upkeepId.FromBigInt(big.NewInt(12345)) @@ -351,7 +350,7 @@ func TestRegistry_VerifyLogExists(t *testing.T) { blocks: tc.blocks, } e := &EvmRegistry{ - lggr: lggr, + lggr: logger.Sugared(lggr), bs: bs, } @@ -379,7 +378,7 @@ func TestRegistry_VerifyLogExists(t *testing.T) { } func TestRegistry_CheckUpkeeps(t *testing.T) { - lggr := logger.TestLogger(t) + lggr := logger.Test(t) uid0 := core.GenUpkeepID(types3.UpkeepType(0), "p0") uid1 := core.GenUpkeepID(types3.UpkeepType(1), "p1") uid2 := core.GenUpkeepID(types3.UpkeepType(1), "p2") @@ -509,7 +508,7 @@ func TestRegistry_CheckUpkeeps(t *testing.T) { } bs.latestBlock.Store(tc.latestBlock) e := &EvmRegistry{ - lggr: lggr, + lggr: logger.Sugared(lggr), bs: bs, poller: tc.poller, } @@ -669,7 +668,7 @@ func TestRegistry_SimulatePerformUpkeeps(t *testing.T) { // setups up an evm registry for tests. func setupEVMRegistry(t *testing.T) *EvmRegistry { - lggr := logger.TestLogger(t) + lggr := logger.Test(t) addr := common.HexToAddress("0x6cA639822c6C241Fa9A7A6b5032F6F7F1C513CAD") keeperRegistryABI, err := abi.JSON(strings.NewReader(ac.IAutomationV21PlusCommonABI)) require.Nil(t, err, "need registry abi") @@ -682,7 +681,7 @@ func setupEVMRegistry(t *testing.T) *EvmRegistry { ge := gasMocks.NewEvmFeeEstimator(t) r := &EvmRegistry{ - lggr: lggr, + lggr: logger.Sugared(lggr), poller: logPoller, addr: addr, client: client, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go index ab530f877ae..1a3f103dd10 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go @@ -15,19 +15,19 @@ import ( "github.com/stretchr/testify/mock" types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" types3 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "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" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" autov2common "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" @@ -546,7 +546,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { ctx := tests.Context(t) - lggr := logger.TestLogger(t) + lggr := logger.Test(t) var hb types3.HeadBroadcaster var lp logpoller.LogPoller @@ -560,7 +560,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) { bs: bs, registry: tc.registry, packer: tc.packer, - lggr: lggr, + lggr: logger.Sugared(lggr), } err := registry.refreshLogTriggerUpkeeps(ctx, tc.ids) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit/event_provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit/event_provider.go index f1a64688044..697f56c866b 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit/event_provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit/event_provider.go @@ -6,18 +6,17 @@ import ( "fmt" "sync" - "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" ) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go index d11970864ad..27a35ddff13 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/scanner.go @@ -8,10 +8,11 @@ import ( "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" ) @@ -43,7 +44,7 @@ func NewPerformedEventsScanner( finalityDepth uint32, ) *performedEventsScanner { return &performedEventsScanner{ - lggr: lggr.Named("EventsScanner"), + lggr: logger.Named(lggr, "EventsScanner"), poller: poller, registryAddress: registryAddress, finalityDepth: finalityDepth, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go index e6486ca56ae..27cac24a9fe 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate/store.go @@ -8,13 +8,12 @@ import ( "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - "github.com/smartcontractkit/chainlink-common/pkg/services" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -84,7 +83,7 @@ type upkeepStateStore struct { func NewUpkeepStateStore(orm ORM, lggr logger.Logger, scanner PerformedLogsScanner) *upkeepStateStore { return &upkeepStateStore{ orm: orm, - lggr: lggr.Named(UpkeepStateStoreServiceName), + lggr: logger.Named(lggr, UpkeepStateStoreServiceName), cache: map[string]*upkeepStateRecord{}, scanner: scanner, retention: CacheExpiration, diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go index 7f74f9a38a5..00c1469abab 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go @@ -716,6 +716,7 @@ func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IK []int{1, 1, 1, 1}, // s []int, oracles, // oracles []OracleIdentityExtra, rawCfg, // reportingPluginConfig []byte, + nil, 20*time.Millisecond, // maxDurationQuery time.Duration, 1600*time.Millisecond, // maxDurationObservation time.Duration, 20*time.Millisecond, // maxDurationShouldAcceptFinalizedReport time.Duration, diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index 2ce9ff3d243..6ce0532f1b6 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -44,7 +44,6 @@ import ( "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/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -59,6 +58,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) const ( @@ -347,7 +347,8 @@ func runKeeperPluginBasic(t *testing.T) { 3, // rMax uint8, []int{1, 1, 1, 1}, oracles, - offC, // reportingPluginConfig []byte, + offC, // reportingPluginConfig []byte, + nil, 20*time.Millisecond, // Max duration query 1600*time.Millisecond, // Max duration observation 800*time.Millisecond, @@ -602,7 +603,8 @@ func TestIntegration_KeeperPluginForwarderEnabled(t *testing.T) { 3, // rMax uint8, []int{1, 1, 1, 1}, oracles, - offC, // reportingPluginConfig []byte, + offC, // reportingPluginConfig []byte, + nil, 50*time.Millisecond, // Max duration query 1*time.Second, // Max duration observation 1*time.Second, diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go index 339d8a89dfb..941e65b7b24 100644 --- a/core/services/ocr2/plugins/ocr2keeper/util.go +++ b/core/services/ocr2/plugins/ocr2keeper/util.go @@ -38,15 +38,11 @@ type Encoder21 interface { ocr2keepers21.Encoder } -var ( - ErrNoChainFromSpec = fmt.Errorf("could not create chain from spec") -) - -func EVMProvider(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth) (evmrelay.OCR2KeeperProvider, error) { +func EVMProvider(ctx context.Context, ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth) (evmrelay.OCR2KeeperProvider, error) { oSpec := spec.OCR2OracleSpec ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(ds, chain, lggr.Named("OCR2KeeperRelayer"), ethKeystore) - keeperProvider, err := ocr2keeperRelayer.NewOCR2KeeperProvider( + keeperProvider, err := ocr2keeperRelayer.NewOCR2KeeperProvider(ctx, types.RelayArgs{ ExternalJobID: spec.ExternalJobID, JobID: oSpec.ID, @@ -79,7 +75,7 @@ func EVMDependencies20( var registry *evmregistry20.EvmRegistry // the provider will be returned as a dependency - if keeperProvider, err = EVMProvider(ds, chain, lggr, spec, ethKeystore); err != nil { + if keeperProvider, err = EVMProvider(ctx, ds, chain, lggr, spec, ethKeystore); err != nil { return nil, nil, nil, nil, err } diff --git a/core/services/ocr2/plugins/promwrapper/factory.go b/core/services/ocr2/plugins/promwrapper/factory.go index c3dffa55013..a3195ed88c9 100644 --- a/core/services/ocr2/plugins/promwrapper/factory.go +++ b/core/services/ocr2/plugins/promwrapper/factory.go @@ -1,6 +1,7 @@ package promwrapper import ( + "context" "math/big" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -15,8 +16,8 @@ type promFactory struct { chainID *big.Int } -func (p *promFactory) NewReportingPlugin(config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { - plugin, info, err := p.wrapped.NewReportingPlugin(config) +func (p *promFactory) NewReportingPlugin(ctx context.Context, config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { + plugin, info, err := p.wrapped.NewReportingPlugin(ctx, config) if err != nil { return nil, types.ReportingPluginInfo{}, err } diff --git a/core/services/ocr2/plugins/s4/factory.go b/core/services/ocr2/plugins/s4/factory.go index 54ed727ad78..3caff4e1866 100644 --- a/core/services/ocr2/plugins/s4/factory.go +++ b/core/services/ocr2/plugins/s4/factory.go @@ -1,6 +1,8 @@ package s4 import ( + "context" + s4_orm "github.com/smartcontractkit/chainlink/v2/core/services/s4" "github.com/smartcontractkit/libocr/commontypes" @@ -20,7 +22,7 @@ type S4ReportingPluginFactory struct { var _ types.ReportingPluginFactory = (*S4ReportingPluginFactory)(nil) // NewReportingPlugin complies with ReportingPluginFactory -func (f S4ReportingPluginFactory) NewReportingPlugin(rpConfig types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { +func (f S4ReportingPluginFactory) NewReportingPlugin(ctx context.Context, rpConfig types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { config, limits, err := f.ConfigDecoder(rpConfig.OffchainConfig) if err != nil { f.Logger.Error("unable to decode reporting plugin config", commontypes.LogFields{ diff --git a/core/services/ocr2/plugins/s4/factory_test.go b/core/services/ocr2/plugins/s4/factory_test.go index 13a36a53823..53129b18796 100644 --- a/core/services/ocr2/plugins/s4/factory_test.go +++ b/core/services/ocr2/plugins/s4/factory_test.go @@ -4,6 +4,7 @@ import ( "errors" "testing" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/s4" s4_mocks "github.com/smartcontractkit/chainlink/v2/core/services/s4/mocks" @@ -42,7 +43,7 @@ func TestS4ReportingPluginFactory_NewReportingPlugin(t *testing.T) { rpConfig := types.ReportingPluginConfig{ OffchainConfig: make([]byte, 100), } - plugin, pluginInfo, err := f.NewReportingPlugin(rpConfig) + plugin, pluginInfo, err := f.NewReportingPlugin(tests.Context(t), rpConfig) require.NoError(t, err) require.NotNil(t, plugin) require.Equal(t, types.ReportingPluginInfo{ @@ -67,7 +68,7 @@ func TestS4ReportingPluginFactory_NewReportingPlugin(t *testing.T) { rpConfig := types.ReportingPluginConfig{ OffchainConfig: make([]byte, 100), } - plugin, _, err := f.NewReportingPlugin(rpConfig) + plugin, _, err := f.NewReportingPlugin(tests.Context(t), rpConfig) require.ErrorContains(t, err, "some error") require.Nil(t, plugin) }) diff --git a/core/services/ocr2/plugins/s4/messages.pb.go b/core/services/ocr2/plugins/s4/messages.pb.go index e629633cb12..66bbeb7dbb6 100644 --- a/core/services/ocr2/plugins/s4/messages.pb.go +++ b/core/services/ocr2/plugins/s4/messages.pb.go @@ -7,10 +7,11 @@ package s4 import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/core/services/ocr2/validate/config.go b/core/services/ocr2/validate/config.go index 62815e19765..54c29e7d057 100644 --- a/core/services/ocr2/validate/config.go +++ b/core/services/ocr2/validate/config.go @@ -45,7 +45,9 @@ func ToLocalConfig(ocr2Config OCR2Config, insConf InsecureConfig, spec job.OCR2O ccTrackerPollInterval = ocr2Config.ContractPollInterval() } lc := types.LocalConfig{ + DefaultMaxDurationInitialization: 30 * time.Second, BlockchainTimeout: blockchainTimeout, + ContractConfigLoadTimeout: blockchainTimeout, ContractConfigConfirmations: ccConfirmations, ContractConfigTrackerPollInterval: ccTrackerPollInterval, ContractTransmitterTransmitTimeout: ocr2Config.ContractTransmitterTransmitTimeout(), diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go index a224249e1e8..7ea34e5ac2d 100644 --- a/core/services/ocr2/validate/validate.go +++ b/core/services/ocr2/validate/validate.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -84,7 +85,6 @@ var ( "relay": {}, "relayConfig": {}, "pluginType": {}, - "pluginConfig": {}, } notExpectedParams = map[string]struct{}{ "isBootstrapPeer": {}, @@ -117,7 +117,7 @@ func validateSpec(ctx context.Context, tree *toml.Tree, spec job.Job, rc plugins // TODO validator for DR-OCR spec: https://smartcontract-it.atlassian.net/browse/FUN-112 return nil case types.Mercury: - return validateOCR2MercurySpec(spec.OCR2OracleSpec.PluginConfig, *spec.OCR2OracleSpec.FeedID) + return validateOCR2MercurySpec(spec.OCR2OracleSpec, *spec.OCR2OracleSpec.FeedID) case types.CCIPExecution: return validateOCR2CCIPExecutionSpec(spec.OCR2OracleSpec.PluginConfig) case types.CCIPCommit: @@ -297,13 +297,26 @@ func validateOCR2KeeperSpec(jsonConfig job.JSONConfig) error { return nil } -func validateOCR2MercurySpec(jsonConfig job.JSONConfig, feedId [32]byte) error { +func validateOCR2MercurySpec(spec *job.OCR2OracleSpec, feedID [32]byte) error { + var relayConfig evmtypes.RelayConfig + err := json.Unmarshal(spec.RelayConfig.Bytes(), &relayConfig) + if err != nil { + return pkgerrors.Wrap(err, "error while unmarshalling relay config") + } + + if len(spec.PluginConfig) == 0 { + if !relayConfig.EnableTriggerCapability { + return pkgerrors.Wrap(err, "at least one transmission option must be configured") + } + return nil + } + var pluginConfig mercuryconfig.PluginConfig - err := json.Unmarshal(jsonConfig.Bytes(), &pluginConfig) + err = json.Unmarshal(spec.PluginConfig.Bytes(), &pluginConfig) if err != nil { return pkgerrors.Wrap(err, "error while unmarshalling plugin config") } - return pkgerrors.Wrap(mercuryconfig.ValidatePluginConfig(pluginConfig, feedId), "Mercury PluginConfig is invalid") + return pkgerrors.Wrap(mercuryconfig.ValidatePluginConfig(pluginConfig, feedID), "Mercury PluginConfig is invalid") } func validateOCR2CCIPExecutionSpec(jsonConfig job.JSONConfig) error { diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go index fdcb68ceecc..ad3a602d0bb 100644 --- a/core/services/ocrbootstrap/delegate.go +++ b/core/services/ocrbootstrap/delegate.go @@ -39,10 +39,16 @@ type Delegate struct { type relayConfig struct { // providerType used for determining which type of contract to track config on ProviderType string `json:"providerType"` + // HACK // Extra fields to enable router proxy contract support. Must match field names of functions' PluginConfig. DONID string `json:"donID"` ContractVersion uint32 `json:"contractVersion"` ContractUpdateCheckFrequencySec uint32 `json:"contractUpdateCheckFrequencySec"` + + // Annoyingly, the pre-existing donID field is already reserved and has a + // special-case usage just for functions. It's also a string and not uint32 + // as Baku requires. + LLODONID uint32 `json:"lloDonID"` } // NewDelegateBootstrap creates a new Delegate @@ -111,7 +117,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] var relayCfg relayConfig if err = json.Unmarshal(spec.RelayConfig.Bytes(), &relayCfg); err != nil { - return nil, err + return nil, fmt.Errorf("failed to unmarshal relay config for bootstrap job: %w", err) } var configProvider types.ConfigProvider @@ -157,10 +163,12 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] lggr := d.lggr.With(ctxVals.Args()...) lggr.Infow("OCR2 job using local config", "BlockchainTimeout", lc.BlockchainTimeout, + "ContractConfigLoadTimeout", lc.ContractConfigLoadTimeout, "ContractConfigConfirmations", lc.ContractConfigConfirmations, "ContractConfigTrackerPollInterval", lc.ContractConfigTrackerPollInterval, "ContractTransmitterTransmitTimeout", lc.ContractTransmitterTransmitTimeout, "DatabaseTimeout", lc.DatabaseTimeout, + "DefaultMaxDurationInitialization", lc.DefaultMaxDurationInitialization, ) ocrLogger := ocrcommon.NewOCRWrapper(lggr.Named("OCRBootstrap"), d.ocr2Cfg.TraceLogging(), func(ctx context.Context, msg string) { logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") diff --git a/core/services/ocrcommon/adapters.go b/core/services/ocrcommon/adapters.go index 53e62be9a07..33e4971bc82 100644 --- a/core/services/ocrcommon/adapters.go +++ b/core/services/ocrcommon/adapters.go @@ -1,8 +1,14 @@ package ocrcommon import ( + "bytes" + "cmp" "context" + "encoding/binary" "fmt" + "io" + "math" + "slices" "github.com/pkg/errors" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" @@ -11,6 +17,7 @@ import ( "google.golang.org/protobuf/types/known/structpb" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) @@ -75,22 +82,102 @@ func (c *OCR3ContractTransmitterAdapter) Transmit(ctx context.Context, digest oc }, r.Report, signatures) } -func (c *OCR3ContractTransmitterAdapter) FromAccount() (ocrtypes.Account, error) { - return c.ct.FromAccount() +func (c *OCR3ContractTransmitterAdapter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return c.ct.FromAccount(ctx) } var _ ocr3types.OnchainKeyring[[]byte] = (*OCR3OnchainKeyringMultiChainAdapter)(nil) +func MarshalMultichainKeyBundle(ost map[string]ocr2key.KeyBundle) (ocrtypes.OnchainPublicKey, error) { + pubKeys := map[string]ocrtypes.OnchainPublicKey{} + for k, b := range ost { + pubKeys[k] = []byte(b.PublicKey()) + } + return MarshalMultichainPublicKey(pubKeys) +} + +func MarshalMultichainPublicKey(ost map[string]ocrtypes.OnchainPublicKey) (ocrtypes.OnchainPublicKey, error) { + var pubKeys [][]byte + for k, pubKey := range ost { + typ, err := chaintype.ChainType(k).Type() + if err != nil { + // skipping unknown key type + continue + } + buf := new(bytes.Buffer) + if err = binary.Write(buf, binary.LittleEndian, typ); err != nil { + return nil, err + } + length := len(pubKey) + if length < 0 || length > math.MaxUint16 { + return nil, fmt.Errorf("pubKey doesn't fit into uint16") + } + if err = binary.Write(buf, binary.LittleEndian, uint16(length)); err != nil { //nolint:gosec + return nil, err + } + _, _ = buf.Write(pubKey) + pubKeys = append(pubKeys, buf.Bytes()) + } + // sort keys based on encoded type to make encoding deterministic + slices.SortFunc(pubKeys, func(a, b []byte) int { return cmp.Compare(a[0], b[0]) }) + return bytes.Join(pubKeys, nil), nil +} + +func UnmarshalMultichainPublicKey(d []byte) (map[string]ocrtypes.OnchainPublicKey, error) { + m := map[string]ocrtypes.OnchainPublicKey{} + buf := bytes.NewReader(d) + + for { + // type + typ, err := buf.ReadByte() + if err != nil { + return nil, err + } + // length + var length uint16 + err = binary.Read(buf, binary.LittleEndian, &length) + if err != nil { + return nil, err + } + // value + pubKey := make([]byte, length) + n, err := buf.Read(pubKey) + if err != nil { + return nil, err + } + if n != int(length) { + return nil, io.EOF + } + + k, err := chaintype.NewChainType(typ) + if err != nil { + // skipping unknown key type + continue + } + m[string(k)] = pubKey + + if buf.Len() == 0 { + break + } + } + + return m, nil +} + type OCR3OnchainKeyringMultiChainAdapter struct { keyBundles map[string]ocr2key.KeyBundle publicKey ocrtypes.OnchainPublicKey lggr logger.Logger } -func NewOCR3OnchainKeyringMultiChainAdapter(ost map[string]ocr2key.KeyBundle, publicKey ocrtypes.OnchainPublicKey, lggr logger.Logger) (*OCR3OnchainKeyringMultiChainAdapter, error) { +func NewOCR3OnchainKeyringMultiChainAdapter(ost map[string]ocr2key.KeyBundle, lggr logger.Logger) (*OCR3OnchainKeyringMultiChainAdapter, error) { if len(ost) == 0 { return nil, errors.New("no key bundles provided") } + publicKey, err := MarshalMultichainKeyBundle(ost) + if err != nil { + return nil, err + } return &OCR3OnchainKeyringMultiChainAdapter{ost, publicKey, lggr}, nil } @@ -98,30 +185,30 @@ func (a *OCR3OnchainKeyringMultiChainAdapter) PublicKey() ocrtypes.OnchainPublic return a.publicKey } -func (a *OCR3OnchainKeyringMultiChainAdapter) getKeyBundleFromInfo(info []byte) (ocr2key.KeyBundle, error) { +func (a *OCR3OnchainKeyringMultiChainAdapter) getKeyBundleFromInfo(info []byte) (string, ocr2key.KeyBundle, error) { unmarshalledInfo := new(structpb.Struct) err := proto.Unmarshal(info, unmarshalledInfo) if err != nil { - return nil, fmt.Errorf("failed to unmarshal report info: %v", err) + return "", nil, fmt.Errorf("failed to unmarshal report info: %v", err) } infoMap := unmarshalledInfo.AsMap() keyBundleName, ok := infoMap["keyBundleName"] if !ok { - return nil, errors.New("keyBundleName not found in report info") + return "", nil, errors.New("keyBundleName not found in report info") } name, ok := keyBundleName.(string) if !ok { - return nil, errors.New("keyBundleName is not a string") + return "", nil, errors.New("keyBundleName is not a string") } kb, ok := a.keyBundles[name] if !ok { - return nil, fmt.Errorf("keyBundle not found: %s", name) + return "", nil, fmt.Errorf("keyBundle not found: %s", name) } - return kb, nil + return name, kb, nil } func (a *OCR3OnchainKeyringMultiChainAdapter) Sign(digest ocrtypes.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[[]byte]) (signature []byte, err error) { - kb, err := a.getKeyBundleFromInfo(r.Info) + _, kb, err := a.getKeyBundleFromInfo(r.Info) if err != nil { return nil, fmt.Errorf("sign: failed to get key bundle from report info: %v", err) } @@ -136,12 +223,22 @@ func (a *OCR3OnchainKeyringMultiChainAdapter) Sign(digest ocrtypes.ConfigDigest, } func (a *OCR3OnchainKeyringMultiChainAdapter) Verify(opk ocrtypes.OnchainPublicKey, digest ocrtypes.ConfigDigest, seqNr uint64, ri ocr3types.ReportWithInfo[[]byte], signature []byte) bool { - kb, err := a.getKeyBundleFromInfo(ri.Info) + kbName, kb, err := a.getKeyBundleFromInfo(ri.Info) if err != nil { a.lggr.Warnf("verify: failed to get key bundle from report info: %v", err) return false } - return kb.Verify(opk, ocrtypes.ReportContext{ + keys, err := UnmarshalMultichainPublicKey(opk) + if err != nil { + a.lggr.Warnf("verify: failed to unmarshal public keys: %v", err) + return false + } + publicKey, ok := keys[kbName] + if !ok { + a.lggr.Warnf("verify: publicKey not found: %v", kbName) + return false + } + return kb.Verify(publicKey, ocrtypes.ReportContext{ ReportTimestamp: ocrtypes.ReportTimestamp{ ConfigDigest: digest, Epoch: uint32(seqNr), diff --git a/core/services/ocrcommon/adapters_test.go b/core/services/ocrcommon/adapters_test.go index e7d45627299..931d1dcf6c5 100644 --- a/core/services/ocrcommon/adapters_test.go +++ b/core/services/ocrcommon/adapters_test.go @@ -2,25 +2,24 @@ package ocrcommon_test import ( "context" - "encoding/json" "fmt" + "math" "reflect" "testing" - "github.com/pelletier/go-toml" "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - keystoreMocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" ) @@ -115,63 +114,116 @@ func TestOCR3OnchainKeyringAdapter(t *testing.T) { require.Equal(t, maxSignatureLength, kr.MaxSignatureLength()) } -type envelope struct { - OnchainSigningStrategy *validate.OCR2OnchainSigningStrategy -} - func TestNewOCR3OnchainKeyringMultiChainAdapter(t *testing.T) { - payload := ` -[onchainSigningStrategy] -strategyName = "single-chain" -[onchainSigningStrategy.config] -evm = "08d14c6eed757414d72055d28de6caf06535806c6a14e450f3a2f1c854420e17" -publicKey = "pub-key" -` - oss := &envelope{} - tree, err := toml.Load(payload) - require.NoError(t, err) - o := map[string]any{} - err = tree.Unmarshal(&o) + evmBundle, err := ocr2key.New(chaintype.EVM) require.NoError(t, err) - b, err := json.Marshal(o) - require.NoError(t, err) - err = json.Unmarshal(b, oss) + + aptosBundle, err := ocr2key.New(chaintype.Aptos) require.NoError(t, err) - reportInfo := ocr3types.ReportWithInfo[[]byte]{ - Report: []byte("multi-chain-report"), + + bundles := map[string]ocr2key.KeyBundle{ + "evm": evmBundle, + "aptos": aptosBundle, } - info, err := structpb.NewStruct(map[string]interface{}{ + adapter, err := ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(bundles, logger.TestLogger(t)) + require.NoError(t, err) + + maxLength := math.Max(float64(evmBundle.MaxSignatureLength()), float64(aptosBundle.MaxSignatureLength())) + assert.Equal(t, int(maxLength), adapter.MaxSignatureLength()) + + // evm signature + info, err := structpb.NewStruct(map[string]any{ "keyBundleName": "evm", }) require.NoError(t, err) - infoB, err := proto.Marshal(info) + + infob, err := proto.Marshal(info) require.NoError(t, err) - reportInfo.Info = infoB + r := ocr3types.ReportWithInfo[[]byte]{ + Report: []byte("report"), + Info: infob, + } - ks := keystoreMocks.NewOCR2(t) - fakeKey := ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "evm") - pk := fakeKey.PublicKey() - ks.On("Get", "pub-key").Return(fakeKey, nil) - ks.On("Get", "08d14c6eed757414d72055d28de6caf06535806c6a14e450f3a2f1c854420e17").Return(fakeKey, nil) - keyBundles := map[string]ocr2key.KeyBundle{} - for name := range oss.OnchainSigningStrategy.ConfigCopy() { - kbID, ostErr := oss.OnchainSigningStrategy.KeyBundleID(name) - require.NoError(t, ostErr) - os, ostErr := ks.Get(kbID) - require.NoError(t, ostErr) - keyBundles[name] = os + sig, err := adapter.Sign(configDigest, seqNr, r) + require.NoError(t, err) + assert.True(t, adapter.Verify(adapter.PublicKey(), configDigest, seqNr, r, sig)) + + // aptos signature + info, err = structpb.NewStruct(map[string]any{ + "keyBundleName": "aptos", + }) + require.NoError(t, err) + + infob, err = proto.Marshal(info) + require.NoError(t, err) + r = ocr3types.ReportWithInfo[[]byte]{ + Report: []byte("report"), + Info: infob, } - adapter, err := ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(keyBundles, pk, logger.TestLogger(t)) + sig, err = adapter.Sign(configDigest, seqNr, r) require.NoError(t, err) - _, err = ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(map[string]ocr2key.KeyBundle{}, pk, logger.TestLogger(t)) + assert.True(t, adapter.Verify(adapter.PublicKey(), configDigest, seqNr, r, sig)) + + // no bundles + _, err = ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(map[string]ocr2key.KeyBundle{}, logger.TestLogger(t)) require.Error(t, err, "no key bundles provided") +} + +func newMultichainAdapter(t *testing.T) *ocrcommon.OCR3OnchainKeyringMultiChainAdapter { + evmBundle, err := ocr2key.New(chaintype.EVM) + require.NoError(t, err) + + aptosBundle, err := ocr2key.New(chaintype.Aptos) + require.NoError(t, err) + + bundles := map[string]ocr2key.KeyBundle{ + "evm": evmBundle, + "aptos": aptosBundle, + } + adapter, err := ocrcommon.NewOCR3OnchainKeyringMultiChainAdapter(bundles, logger.TestLogger(t)) + require.NoError(t, err) + + return adapter +} + +func TestNewOCR3OnchainKeyringMultiChainAdapter_VerifyFromDifferentNodesPublicKeys(t *testing.T) { + firstNodeAdapter := newMultichainAdapter(t) + secondNodeAdapter := newMultichainAdapter(t) - sig, err := adapter.Sign(configDigest, seqNr, reportInfo) - assert.NoError(t, err) - assert.True(t, adapter.Verify(pk, configDigest, seqNr, reportInfo, sig)) - assert.Equal(t, pk, adapter.PublicKey()) - assert.Equal(t, fakeKey.MaxSignatureLength(), adapter.MaxSignatureLength()) + // evm signature + info, err := structpb.NewStruct(map[string]any{ + "keyBundleName": "evm", + }) + require.NoError(t, err) + + infob, err := proto.Marshal(info) + require.NoError(t, err) + r := ocr3types.ReportWithInfo[[]byte]{ + Report: []byte("report"), + Info: infob, + } + + sig, err := firstNodeAdapter.Sign(configDigest, seqNr, r) + require.NoError(t, err) + assert.True(t, secondNodeAdapter.Verify(firstNodeAdapter.PublicKey(), configDigest, seqNr, r, sig)) + + // aptos signature + info, err = structpb.NewStruct(map[string]any{ + "keyBundleName": "aptos", + }) + require.NoError(t, err) + + infob, err = proto.Marshal(info) + require.NoError(t, err) + r = ocr3types.ReportWithInfo[[]byte]{ + Report: []byte("report"), + Info: infob, + } + + sig, err = secondNodeAdapter.Sign(configDigest, seqNr, r) + require.NoError(t, err) + assert.True(t, firstNodeAdapter.Verify(secondNodeAdapter.PublicKey(), configDigest, seqNr, r, sig)) } var _ ocrtypes.ContractTransmitter = (*fakeContractTransmitter)(nil) @@ -207,16 +259,17 @@ func (f fakeContractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) panic("not implemented") } -func (f fakeContractTransmitter) FromAccount() (ocrtypes.Account, error) { +func (f fakeContractTransmitter) FromAccount(context.Context) (ocrtypes.Account, error) { return account, nil } func TestContractTransmitter(t *testing.T) { + ctx := testutils.Context(t) ct := ocrcommon.NewOCR3ContractTransmitterAdapter(fakeContractTransmitter{}) - require.NoError(t, ct.Transmit(context.Background(), configDigest, seqNr, rwi, signatures)) + require.NoError(t, ct.Transmit(ctx, configDigest, seqNr, rwi, signatures)) - a, err := ct.FromAccount() + a, err := ct.FromAccount(ctx) require.NoError(t, err) require.Equal(t, a, account) } diff --git a/core/services/ocrcommon/arbitrum_block_translator.go b/core/services/ocrcommon/arbitrum_block_translator.go index 1b7c3712382..9179fe32270 100644 --- a/core/services/ocrcommon/arbitrum_block_translator.go +++ b/core/services/ocrcommon/arbitrum_block_translator.go @@ -10,9 +10,10 @@ import ( "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -33,7 +34,7 @@ type ArbitrumBlockTranslator struct { func NewArbitrumBlockTranslator(ethClient evmclient.Client, lggr logger.Logger) *ArbitrumBlockTranslator { return &ArbitrumBlockTranslator{ ethClient, - lggr.Named("ArbitrumBlockTranslator"), + logger.Named(lggr, "ArbitrumBlockTranslator"), make(map[int64]int64), sync.RWMutex{}, utils.KeyedMutex{}, diff --git a/core/services/ocrcommon/arbitrum_block_translator_test.go b/core/services/ocrcommon/arbitrum_block_translator_test.go index fa6875fb798..6b9abc93bf7 100644 --- a/core/services/ocrcommon/arbitrum_block_translator_test.go +++ b/core/services/ocrcommon/arbitrum_block_translator_test.go @@ -1,6 +1,7 @@ package ocrcommon_test import ( + "context" "database/sql" "math/big" mrand "math/rand" @@ -34,7 +35,7 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { var changedInL1Block int64 = 5541 latestBlock := blocks[1000] - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() from, to, err := abt.BinarySearch(ctx, changedInL1Block) require.NoError(t, err) @@ -51,11 +52,10 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { var changedInL1Block int64 = 42 latestBlock := blocks[1000] - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() - tmp := new(evmtypes.Head) - client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(tmp, nil).Run(func(args mock.Arguments) { - *tmp = blocks[args[1].(*big.Int).Int64()] + client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(func(_ context.Context, num *big.Int) (*evmtypes.Head, error) { + return blocks[num.Int64()], nil }) _, _, err := abt.BinarySearch(ctx, changedInL1Block) @@ -71,11 +71,10 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { var changedInL1Block int64 = 5043 latestBlock := blocks[1000] - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() - tmp := new(evmtypes.Head) - client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(tmp, nil).Run(func(args mock.Arguments) { - *tmp = blocks[args[1].(*big.Int).Int64()] + client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(func(_ context.Context, num *big.Int) (*evmtypes.Head, error) { + return blocks[num.Int64()], nil }) _, _, err := abt.BinarySearch(ctx, changedInL1Block) @@ -91,12 +90,10 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { var changedInL1Block int64 = 5042 latestBlock := blocks[1000] - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() - tmp := new(evmtypes.Head) - client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(tmp, nil).Run(func(args mock.Arguments) { - h := blocks[args[1].(*big.Int).Int64()] - *tmp = h + client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(func(_ context.Context, num *big.Int) (*evmtypes.Head, error) { + return blocks[num.Int64()], nil }) from, to, err := abt.BinarySearch(ctx, changedInL1Block) @@ -114,12 +111,10 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { var changedInL1Block int64 = 5000 latestBlock := blocks[1000] - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() - tmp := new(evmtypes.Head) - client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(tmp, nil).Run(func(args mock.Arguments) { - h := blocks[args[1].(*big.Int).Int64()] - *tmp = h + client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(func(_ context.Context, num *big.Int) (*evmtypes.Head, error) { + return blocks[num.Int64()], nil }) from, to, err := abt.BinarySearch(ctx, changedInL1Block) @@ -137,12 +132,10 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { var changedInL1Block int64 = 5540 latestBlock := blocks[1000] - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() - tmp := new(evmtypes.Head) - client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(tmp, nil).Run(func(args mock.Arguments) { - h := blocks[args[1].(*big.Int).Int64()] - *tmp = h + client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(func(_ context.Context, num *big.Int) (*evmtypes.Head, error) { + return blocks[num.Int64()], nil }) from, to, err := abt.BinarySearch(ctx, changedInL1Block) @@ -161,12 +154,10 @@ func TestArbitrumBlockTranslator_BinarySearch(t *testing.T) { latestBlock := blocks[1000] // Latest is never cached - client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(&latestBlock, nil).Once() + client.On("HeadByNumber", ctx, (*big.Int)(nil)).Return(latestBlock, nil).Once() - tmp := new(evmtypes.Head) - client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Times(20+18+14).Return(tmp, nil).Run(func(args mock.Arguments) { - h := blocks[args[1].(*big.Int).Int64()] - *tmp = h + client.On("HeadByNumber", ctx, mock.AnythingOfType("*big.Int")).Return(func(_ context.Context, num *big.Int) (*evmtypes.Head, error) { + return blocks[num.Int64()], nil }) // First search, nothing cached (total 21 - bsearch 20) @@ -230,14 +221,14 @@ func TestArbitrumBlockTranslator_NumberToQueryRange(t *testing.T) { }) } -func generateDeterministicL2Blocks() (heads []evmtypes.Head) { +func generateDeterministicL2Blocks() (heads []*evmtypes.Head) { source := mrand.NewSource(0) deterministicRand := mrand.New(source) l2max := 1000 var l1BlockNumber int64 = 5000 var parentHash common.Hash for i := 0; i <= l2max; i++ { - head := evmtypes.Head{ + head := &evmtypes.Head{ Number: int64(i), L1BlockNumber: sql.NullInt64{Int64: l1BlockNumber, Valid: true}, Hash: utils.NewHash(), diff --git a/core/services/ocrcommon/block_translator.go b/core/services/ocrcommon/block_translator.go index d7ceffc5ea7..b25d617e2ab 100644 --- a/core/services/ocrcommon/block_translator.go +++ b/core/services/ocrcommon/block_translator.go @@ -4,10 +4,11 @@ import ( "context" "math/big" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) // BlockTranslator converts emitted block numbers (from block.number) into a @@ -21,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: + case "", chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainKroma, chaintype.ChainMetis, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync, chaintype.ChainZircuit: fallthrough default: return &l1BlockTranslator{} diff --git a/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go index 325311352fb..a33afe5f589 100644 --- a/core/services/ocrcommon/peer_wrapper.go +++ b/core/services/ocrcommon/peer_wrapper.go @@ -55,6 +55,9 @@ type ( // OCR2 peer adapter Peer2 *peerAdapterOCR2 + + // PeerGroupFactory can be used to create PeerGroup instances + PeerGroupFactory ocrnetworking.PeerGroupFactory } ) @@ -102,6 +105,9 @@ func (p *SingletonPeerWrapper) Start(context.Context) error { peer.OCR2BinaryNetworkEndpointFactory(), peer.OCR2BootstrapperFactory(), } + + p.PeerGroupFactory = peer.PeerGroupFactory() + p.peerCloser = peer return nil }) diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go index 2cb4fda9105..810952f455e 100644 --- a/core/services/ocrcommon/telemetry.go +++ b/core/services/ocrcommon/telemetry.go @@ -11,13 +11,13 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "google.golang.org/protobuf/proto" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" v1types "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" v2types "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" v3types "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" v4types "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v4" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" @@ -25,12 +25,20 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" ) -type eaTelemetry struct { +type EATelemetry struct { DataSource string ProviderRequestedTimestamp int64 ProviderReceivedTimestamp int64 ProviderDataStreamEstablished int64 ProviderIndicatedTime int64 + + DpBenchmarkPrice float64 + DpBid float64 + DpAsk float64 + BridgeTaskRunStartedTimestamp int64 + BridgeTaskRunEndedTimestamp int64 + AssetSymbol string + BridgeRequestData string } type EnhancedTelemetryData struct { @@ -144,8 +152,44 @@ func (e *EnhancedTelemetryService[T]) getChainID() string { } } +func ParseMercuryEATelemetry(lggr logger.Logger, trrs pipeline.TaskRunResults, feedVersion mercuryutils.FeedVersion) (eaTelemetryValues []EATelemetry) { + for _, trr := range trrs { + if trr.Task.Type() != pipeline.TaskTypeBridge { + continue + } + bridgeTask := trr.Task.(*pipeline.BridgeTask) + bridgeName := bridgeTask.Name + + bridgeRawResponse, ok := trr.Result.Value.(string) + if !ok { + lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, id=%s, name=%q, expected string got %T", trr.Task.DotID(), bridgeName, trr.Result.Value), "dotID", trr.Task.DotID(), "bridgeName", bridgeName) + continue + } + eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse)) + if err != nil { + lggr.Warnw(fmt.Sprintf("cannot parse EA telemetry, id=%s, name=%q", trr.Task.DotID(), bridgeName), "err", err, "dotID", trr.Task.DotID(), "bridgeName", bridgeName) + } + eaTelem.BridgeRequestData = bridgeTask.RequestData + eaTelem.DpBenchmarkPrice, eaTelem.DpBid, eaTelem.DpAsk = getPricesFromBridgeTask(lggr, trr, trrs, feedVersion) + + eaTelem.BridgeTaskRunStartedTimestamp = trr.CreatedAt.UnixMilli() + eaTelem.BridgeTaskRunEndedTimestamp = trr.FinishedAt.Time.UnixMilli() + + parsedBridgeData := parseBridgeRequestData(bridgeTask.RequestData, feedVersion) + if parsedBridgeData.IsMarketStatus { + // Only collect telemetry for pricing bridges. + continue + } + + eaTelem.AssetSymbol = parsedBridgeData.AssetSymbol + + eaTelemetryValues = append(eaTelemetryValues, eaTelem) + } + return +} + // parseEATelemetry attempts to parse the bridge telemetry -func parseEATelemetry(b []byte) (eaTelemetry, error) { +func parseEATelemetry(b []byte) (EATelemetry, error) { type eaTimestamps struct { ProviderRequestedTimestamp int64 `json:"providerDataRequestedUnixMs"` ProviderReceivedTimestamp int64 `json:"providerDataReceivedUnixMs"` @@ -163,10 +207,10 @@ func parseEATelemetry(b []byte) (eaTelemetry, error) { t := eaTelem{} if err := json.Unmarshal(b, &t); err != nil { - return eaTelemetry{}, err + return EATelemetry{}, err } - return eaTelemetry{ + return EATelemetry{ DataSource: t.TelemMeta.AdapterName, ProviderRequestedTimestamp: t.TelemTimestamps.ProviderRequestedTimestamp, ProviderReceivedTimestamp: t.TelemTimestamps.ProviderReceivedTimestamp, @@ -294,7 +338,7 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d Enhanced var bn int64 var bh string var bt uint64 - // v1+v2+v3 fields + // v1+v2+v3+v4 fields bp := big.NewInt(0) // v1+v3 fields bid := big.NewInt(0) @@ -373,51 +417,26 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d Enhanced if obs.BenchmarkPrice.Err == nil && obs.BenchmarkPrice.Val != nil { bp = obs.BenchmarkPrice.Val } - if obs.Bid.Err == nil && obs.Bid.Val != nil { - bid = obs.Bid.Val - } - if obs.Ask.Err == nil && obs.Ask.Val != nil { - ask = obs.Ask.Val - } if obs.MarketStatus.Err == nil { marketStatus = telem.MarketStatus(obs.MarketStatus.Val) } } - for _, trr := range d.TaskRunResults { - if trr.Task.Type() != pipeline.TaskTypeBridge { - continue - } - bridgeTask := trr.Task.(*pipeline.BridgeTask) - bridgeName := bridgeTask.Name - - bridgeRawResponse, ok := trr.Result.Value.(string) - if !ok { - e.lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, job=%d, id=%s, name=%q, expected string got %T", e.job.ID, trr.Task.DotID(), bridgeName, 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) - } - - assetSymbol := e.getAssetSymbolFromRequestData(bridgeTask.RequestData) - - benchmarkPrice, bidPrice, askPrice := e.getPricesFromResults(trr, d.TaskRunResults, d.FeedVersion) - + eaTelemetryValues := ParseMercuryEATelemetry(logger.Sugared(e.lggr).With("jobID", e.job.ID), d.TaskRunResults, d.FeedVersion) + for _, eaTelem := range eaTelemetryValues { t := &telem.EnhancedEAMercury{ DataSource: eaTelem.DataSource, - DpBenchmarkPrice: benchmarkPrice, - DpBid: bidPrice, - DpAsk: askPrice, + DpBenchmarkPrice: eaTelem.DpBenchmarkPrice, + DpBid: eaTelem.DpBid, + DpAsk: eaTelem.DpAsk, DpInvariantViolationDetected: d.DpInvariantViolationDetected, CurrentBlockNumber: bn, CurrentBlockHash: bh, CurrentBlockTimestamp: bt, FetchMaxFinalizedTimestamp: d.FetchMaxFinalizedTimestamp, MaxFinalizedTimestamp: mfts, - BridgeTaskRunStartedTimestamp: trr.CreatedAt.UnixMilli(), - BridgeTaskRunEndedTimestamp: trr.FinishedAt.Time.UnixMilli(), + BridgeTaskRunStartedTimestamp: eaTelem.BridgeTaskRunStartedTimestamp, + BridgeTaskRunEndedTimestamp: eaTelem.BridgeTaskRunEndedTimestamp, ProviderRequestedTimestamp: eaTelem.ProviderRequestedTimestamp, ProviderReceivedTimestamp: eaTelem.ProviderReceivedTimestamp, ProviderDataStreamEstablished: eaTelem.ProviderDataStreamEstablished, @@ -437,10 +456,11 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d Enhanced ConfigDigest: d.RepTimestamp.ConfigDigest.Hex(), Round: int64(d.RepTimestamp.Round), Epoch: int64(d.RepTimestamp.Epoch), - AssetSymbol: assetSymbol, + BridgeRequestData: eaTelem.BridgeRequestData, + AssetSymbol: eaTelem.AssetSymbol, Version: uint32(d.FeedVersion), } - + e.lggr.Debugw(fmt.Sprintf("EA Telemetry = %+v", t), "feedID", e.job.OCR2OracleSpec.FeedID.Hex(), "jobID", e.job.ID, "datasource", eaTelem.DataSource) bytes, err := proto.Marshal(t) if err != nil { e.lggr.Warnf("protobuf marshal failed %v", err.Error()) @@ -451,11 +471,32 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d Enhanced } } -// getAssetSymbolFromRequestData parses the requestData of the bridge to generate an asset symbol pair -func (e *EnhancedTelemetryService[T]) getAssetSymbolFromRequestData(requestData string) string { +type telemetryAttributes struct { + PriceType *string `json:"priceType"` +} + +func parseTelemetryAttributes(a string) (telemetryAttributes, error) { + attrs := &telemetryAttributes{} + err := json.Unmarshal([]byte(a), attrs) + if err != nil { + return telemetryAttributes{}, err + } + return *attrs, nil +} + +type bridgeRequestData struct { + AssetSymbol string + IsMarketStatus bool +} + +// parseRequestData parses the requestData of the bridge. +func parseBridgeRequestData(requestData string, mercuryVersion mercuryutils.FeedVersion) bridgeRequestData { type reqDataPayload struct { - To string `json:"to"` - From string `json:"from"` + Endpoint *string `json:"endpoint"` + To *string `json:"to"` + From *string `json:"from"` + Address *string `json:"address"` // used for view function ea only + Market *string `json:"market"` // used for market status ea only } type reqData struct { Data reqDataPayload `json:"data"` @@ -464,10 +505,25 @@ func (e *EnhancedTelemetryService[T]) getAssetSymbolFromRequestData(requestData rd := &reqData{} err := json.Unmarshal([]byte(requestData), rd) if err != nil { - return "" + return bridgeRequestData{} + } + + if mercuryVersion == 4 && ((rd.Data.Endpoint != nil && *rd.Data.Endpoint == "market-status") || (rd.Data.Market != nil && *rd.Data.Market != "")) { + return bridgeRequestData{ + AssetSymbol: *rd.Data.Market, + IsMarketStatus: true, + } } - return rd.Data.From + "/" + rd.Data.To + if rd.Data.From != nil && rd.Data.To != nil { + return bridgeRequestData{AssetSymbol: *rd.Data.From + "/" + *rd.Data.To} + } + + if rd.Data.Address != nil { + return bridgeRequestData{AssetSymbol: *rd.Data.Address} + } + + return bridgeRequestData{} } // ShouldCollectEnhancedTelemetryMercury checks if enhanced telemetry should be collected and sent @@ -478,64 +534,131 @@ func ShouldCollectEnhancedTelemetryMercury(jb job.Job) bool { return false } -// getPricesFromResults parses the pipeline.TaskRunResults for pipeline.TaskTypeJSONParse and gets the benchmarkPrice, +const ( + bid = "bid" + ask = "ask" + benchmark = "benchmark" + exchangeRate = "exchangeRate" +) + +func getPricesFromBridgeTask(lggr logger.Logger, bridgeTask pipeline.TaskRunResult, allTasks pipeline.TaskRunResults, mercuryVersion mercuryutils.FeedVersion) (float64, float64, float64) { + var benchmarkPrice, bidPrice, askPrice float64 + + // This will assume that all fields we care about are tagged with the correct priceType + benchmarkPrice, bidPrice, askPrice = getPricesFromBridgeTaskByTelemetryField(lggr, bridgeTask, allTasks) + + // If prices weren't parsed by telemetry fields - attempt to get prices using the legacy method + // This is for backwards compatibility with job specs that don't have the telemetry attributes set + if benchmarkPrice == 0 && bidPrice == 0 && askPrice == 0 { + benchmarkP, bidP, askP := getPricesFromResultsByOrder(lggr, bridgeTask, allTasks, mercuryVersion) + bidPrice = bidP + askPrice = askP + benchmarkPrice = benchmarkP + } + + return benchmarkPrice, bidPrice, askPrice +} + +// CollectTaskRunResultsWithTags collects TaskRunResults for descendent tasks with non-empty TaskTags. +func collectTaskRunResultsWithTags(bridgeTask pipeline.TaskRunResult, allTasks pipeline.TaskRunResults) []pipeline.TaskRunResult { + startTask := bridgeTask.Task + descendants := startTask.GetDescendantTasks() + var taskRunResultsWithTags []pipeline.TaskRunResult + for _, task := range descendants { + trr := allTasks.GetTaskRunResultOf(task) + if trr != nil { + if trr.Task.TaskTags() != "" { + taskRunResultsWithTags = append(taskRunResultsWithTags, *trr) + } + } + } + return taskRunResultsWithTags +} + +// getPricesFromBridgeTaskByTelemetryField attempts to parse prices from via telemetry fields in the TaskTags +func getPricesFromBridgeTaskByTelemetryField(lggr logger.Logger, bridgeTask pipeline.TaskRunResult, allTasks pipeline.TaskRunResults) (float64, float64, float64) { + var benchmarkPrice, bidPrice, askPrice float64 + + // Outputs are the mapped tasks from this task. + var tasksWithTags = collectTaskRunResultsWithTags(bridgeTask, allTasks) + + for _, trr := range tasksWithTags { + attributes, err := parseTelemetryAttributes(trr.Task.TaskTags()) + if err != nil { + lggr.Warnw(fmt.Sprintf("found telemetry attributes but cannot them, taskTags=%s", trr.Task.TaskTags()), "err", err) + continue + } + + if attributes.PriceType != nil { + switch *attributes.PriceType { + case bid: + bidPrice = parsePriceFromTask(lggr, trr) + case ask: + askPrice = parsePriceFromTask(lggr, trr) + case benchmark: + benchmarkPrice = parsePriceFromTask(lggr, trr) + case exchangeRate: + price := parsePriceFromTask(lggr, trr) + benchmarkPrice, bidPrice, askPrice = price, price, price + case "": + lggr.Warnw(fmt.Sprintf("no priceType found in attributes, parsedAttributes=%+v, id %s", attributes, trr.Task.DotID())) + } + } + } + + return benchmarkPrice, bidPrice, askPrice +} + +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 val +} + +// getPricesFromResultsByOrder parses the pipeline.TaskRunResults for pipeline.TaskTypeJSONParse and gets the benchmarkPrice, // bid and ask. This functions expects the pipeline.TaskRunResults to be correctly ordered -func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.TaskRunResult, allTasks pipeline.TaskRunResults, mercuryVersion mercuryutils.FeedVersion) (float64, float64, float64) { +func getPricesFromResultsByOrder(lggr logger.Logger, startTask pipeline.TaskRunResult, allTasks pipeline.TaskRunResults, mercuryVersion mercuryutils.FeedVersion) (float64, float64, float64) { var benchmarkPrice, askPrice, bidPrice float64 - var err error + // We rely on task results to be sorted in the correct order benchmarkPriceTask := allTasks.GetNextTaskOf(startTask) if benchmarkPriceTask == nil { - e.lggr.Warnf("cannot parse enhanced EA telemetry benchmark price, task is nil, job %d", e.job.ID) + lggr.Warn("cannot parse enhanced EA telemetry benchmark price, task is nil") return 0, 0, 0 } if benchmarkPriceTask.Task.Type() == pipeline.TaskTypeJSONParse { - if benchmarkPriceTask.Result.Error != nil { - e.lggr.Warnw(fmt.Sprintf("got error for enhanced EA telemetry benchmark price, job %d, id %s: %s", e.job.ID, benchmarkPriceTask.Task.DotID(), benchmarkPriceTask.Result.Error), "err", benchmarkPriceTask.Result.Error) - } else { - benchmarkPrice, err = getResultFloat64(benchmarkPriceTask) - if err != nil { - e.lggr.Warnw(fmt.Sprintf("cannot parse enhanced EA telemetry benchmark price, job %d, id %s", e.job.ID, benchmarkPriceTask.Task.DotID()), "err", err) - } - } + benchmarkPrice = parsePriceFromTask(lggr, *benchmarkPriceTask) } - // mercury version 2 only supports benchmarkPrice - if mercuryVersion == 2 { + // mercury versions 2 and 4 only supports benchmarkPrice + if mercuryVersion == 2 || mercuryVersion == 4 { return benchmarkPrice, 0, 0 } bidTask := allTasks.GetNextTaskOf(*benchmarkPriceTask) if bidTask == nil { - e.lggr.Warnf("cannot parse enhanced EA telemetry bid price, task is nil, job %d, id %s", e.job.ID, benchmarkPriceTask.Task.DotID()) + lggr.Warnf("cannot parse enhanced EA telemetry bid price, task is nil, id %s", benchmarkPriceTask.Task.DotID()) return benchmarkPrice, 0, 0 } - if bidTask != nil && bidTask.Task.Type() == pipeline.TaskTypeJSONParse { - if bidTask.Result.Error != nil { - e.lggr.Warnw(fmt.Sprintf("got error for enhanced EA telemetry bid price, job %d, id %s: %s", e.job.ID, bidTask.Task.DotID(), bidTask.Result.Error), "err", bidTask.Result.Error) - } else { - bidPrice, err = getResultFloat64(bidTask) - if err != nil { - e.lggr.Warnw(fmt.Sprintf("cannot parse enhanced EA telemetry bid price, job %d, id %s", e.job.ID, bidTask.Task.DotID()), "err", err) - } - } + if bidTask.Task.Type() == pipeline.TaskTypeJSONParse { + bidPrice = parsePriceFromTask(lggr, *bidTask) } askTask := allTasks.GetNextTaskOf(*bidTask) if askTask == nil { - e.lggr.Warnf("cannot parse enhanced EA telemetry ask price, task is nil, job %d, id %s", e.job.ID, benchmarkPriceTask.Task.DotID()) + lggr.Warnf("cannot parse enhanced EA telemetry ask price, task is nil, id %s", benchmarkPriceTask.Task.DotID()) return benchmarkPrice, bidPrice, 0 } - if askTask != nil && askTask.Task.Type() == pipeline.TaskTypeJSONParse { - if bidTask.Result.Error != nil { - e.lggr.Warnw(fmt.Sprintf("got error for enhanced EA telemetry ask price, job %d, id %s: %s", e.job.ID, askTask.Task.DotID(), askTask.Result.Error), "err", askTask.Result.Error) - } else { - askPrice, err = getResultFloat64(askTask) - if err != nil { - e.lggr.Warnw(fmt.Sprintf("cannot parse enhanced EA telemetry ask price, job %d, id %s", e.job.ID, askTask.Task.DotID()), "err", err) - } - } + if askTask.Task.Type() == pipeline.TaskTypeJSONParse { + askPrice = parsePriceFromTask(lggr, *askTask) } return benchmarkPrice, bidPrice, askPrice diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go index f764e7380f8..ed64e45c2db 100644 --- a/core/services/ocrcommon/telemetry_test.go +++ b/core/services/ocrcommon/telemetry_test.go @@ -6,19 +6,19 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/shopspring/decimal" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" "google.golang.org/protobuf/proto" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" mercuryv1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" mercuryv2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" - + mercuryv4 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v4" 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" @@ -273,7 +273,6 @@ func TestSendEATelemetry(t *testing.T) { expectedMessage, _ := proto.Marshal(&expectedTelemetry) wg.Wait() assert.Equal(t, expectedMessage, sentMessage) - //enhancedTelemService.StopOnce("EnhancedTelemetryService", func() error { return nil }) doneCh <- struct{}{} } @@ -445,21 +444,123 @@ var trrsMercuryV2 = pipeline.TaskRunResults{ }, } -func TestGetPricesFromResults(t *testing.T) { - lggr, logs := logger.TestLoggerObserved(t, zap.WarnLevel) - e := EnhancedTelemetryService[EnhancedTelemetryMercuryData]{ - lggr: lggr, - job: &job.Job{ - ID: 0, +var trrsMercuryV4 = pipeline.TaskRunResults{ + pipeline.TaskRunResult{ + Task: &pipeline.BridgeTask{ + Name: "link-usd-test-bridge-v2", + BaseTask: pipeline.NewBaseTask(0, "ds1", nil, nil, 0), + RequestData: `{"data":{"to":"LINK","from":"USD"}}`, + }, + Result: pipeline.Result{ + Value: bridgeResponse, + }, + }, + pipeline.TaskRunResult{ + Task: &pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "ds1_benchmark", nil, nil, 1), + }, + Result: pipeline.Result{ + Value: 123456.123456, + }, + }, + pipeline.TaskRunResult{ + Task: &pipeline.BridgeTask{ + Name: "market-status-bridge", + BaseTask: pipeline.NewBaseTask(2, "ds2", nil, nil, 2), + RequestData: `{"data":{"endpoint":"market-status","market":"forex"}}`, + }, + Result: pipeline.Result{ + Value: bridgeResponse, }, + }, + pipeline.TaskRunResult{ + Task: &pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(3, "market_status", nil, nil, 3), + }, + Result: pipeline.Result{ + Value: 2.0, + }, + }, +} + +func TestGetPricesFromBridgeByTelemetryField(t *testing.T) { + lggr, _ := logger.TestLoggerObserved(t, zap.WarnLevel) + // These are intentionally out of order from the "legacy" method which expects order of `benchmark, bid, ask` + jsonParseTaskBid := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "json_parse_2", nil, nil, 2), + } + jsonParseTaskBid.BaseTask.Tags = `{"priceType": "bid"}` + jsonParseTaskAsk := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(2, "json_parse_3", nil, nil, 3), + } + jsonParseTaskAsk.BaseTask.Tags = `{"priceType": "ask"}` + jsonParseTaskBenchmark := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(3, "json_parse_1", nil, nil, 1), + } + jsonParseTaskBenchmark.BaseTask.Tags = `{"priceType": "benchmark"}` + + bridgeOutputs := []pipeline.Task{&jsonParseTaskAsk, &jsonParseTaskBid, &jsonParseTaskBenchmark} + + bridgeTask := pipeline.BridgeTask{ + Name: "bridge-task", + BaseTask: pipeline.NewBaseTask(0, "bridge", nil, bridgeOutputs, 0), } - benchmarkPrice, bid, ask := e.getPricesFromResults(trrsMercuryV1[0], trrsMercuryV1, 1) + // Create task run results + taskRunResults := pipeline.TaskRunResults{ + pipeline.TaskRunResult{ + Task: &bridgeTask, + Result: pipeline.Result{ + Value: bridgeResponse, + }, + }, + pipeline.TaskRunResult{ + Task: &jsonParseTaskBenchmark, + Result: pipeline.Result{ + Value: "123456.123456", + }, + }, + pipeline.TaskRunResult{ + Task: &jsonParseTaskBid, + Result: pipeline.Result{ + Value: "1234567.1234567", + }, + }, + pipeline.TaskRunResult{ + Task: &jsonParseTaskAsk, + Result: pipeline.Result{ + Value: "321123", + }, + }, + } + + benchmarkPrice, bidPrice, askPrice := getPricesFromBridgeTask(lggr, taskRunResults[0], taskRunResults, 1) + + require.Equal(t, 123456.123456, benchmarkPrice) + require.Equal(t, 1234567.1234567, bidPrice) + require.Equal(t, 321123.0, askPrice) + + // now removing the TaskTags will throw off the parsed order - and we'll be parsing the "incorrect" prices + // according to the legacy ordering approach + jsonParseTaskAsk.BaseTask.Tags = "" + jsonParseTaskBid.BaseTask.Tags = "" + jsonParseTaskBenchmark.BaseTask.Tags = "" + + wrongBenchmarkPrice, wrongBidPrice, wrongAskPrice := getPricesFromBridgeTask(lggr, taskRunResults[0], taskRunResults, 1) + require.Equal(t, 1234567.1234567, wrongBenchmarkPrice) + require.Equal(t, 321123.0, wrongBidPrice) + require.Equal(t, 123456.123456, wrongAskPrice) +} + +func TestGetPricesFromBridgeTaskByOrder(t *testing.T) { + lggr, logs := logger.TestLoggerObserved(t, zap.WarnLevel) + + benchmarkPrice, bid, ask := getPricesFromBridgeTask(lggr, trrsMercuryV1[0], trrsMercuryV1, 1) require.Equal(t, 123456.123456, benchmarkPrice) require.Equal(t, 1234567.1234567, bid) require.Equal(t, float64(321123), ask) - benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercuryV1[0], pipeline.TaskRunResults{}, 1) + benchmarkPrice, bid, ask = getPricesFromBridgeTask(lggr, trrsMercuryV1[0], pipeline.TaskRunResults{}, 1) require.Equal(t, float64(0), benchmarkPrice) require.Equal(t, float64(0), bid) require.Equal(t, float64(0), ask) @@ -467,12 +568,12 @@ func TestGetPricesFromResults(t *testing.T) { require.Contains(t, logs.All()[0].Message, "cannot parse enhanced EA telemetry") tt := trrsMercuryV1[:2] - e.getPricesFromResults(trrsMercuryV1[0], tt, 1) + getPricesFromBridgeTask(lggr, trrsMercuryV1[0], tt, 1) require.Equal(t, 2, logs.Len()) require.Contains(t, logs.All()[1].Message, "cannot parse enhanced EA telemetry bid price, task is nil") tt = trrsMercuryV1[:3] - e.getPricesFromResults(trrsMercuryV1[0], tt, 1) + getPricesFromBridgeTask(lggr, trrsMercuryV1[0], tt, 1) require.Equal(t, 3, logs.Len()) require.Contains(t, logs.All()[2].Message, "cannot parse enhanced EA telemetry ask price, task is nil") @@ -510,16 +611,16 @@ func TestGetPricesFromResults(t *testing.T) { Value: nil, }, }} - benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercuryV1[0], trrs2, 3) + benchmarkPrice, bid, ask = getPricesFromBridgeTask(lggr, trrsMercuryV1[0], trrs2, 3) require.Equal(t, benchmarkPrice, float64(0)) require.Equal(t, bid, float64(0)) require.Equal(t, ask, float64(0)) require.Equal(t, logs.Len(), 6) - require.Contains(t, logs.All()[3].Message, "cannot parse enhanced EA telemetry benchmark price") - require.Contains(t, logs.All()[4].Message, "cannot parse enhanced EA telemetry bid price") - require.Contains(t, logs.All()[5].Message, "cannot parse enhanced EA telemetry ask price") + require.Contains(t, logs.All()[3].Message, "cannot parse EA telemetry price to float64, DOT id ds1_benchmark") + require.Contains(t, logs.All()[4].Message, "cannot parse EA telemetry price to float64, DOT id ds2_bid") + require.Contains(t, logs.All()[5].Message, "cannot parse EA telemetry price to float64, DOT id ds3_ask") - benchmarkPrice, bid, ask = e.getPricesFromResults(trrsMercuryV1[0], trrsMercuryV2, 2) + benchmarkPrice, bid, ask = getPricesFromBridgeTask(lggr, trrsMercuryV1[0], trrsMercuryV2, 2) require.Equal(t, 123456.123456, benchmarkPrice) require.Equal(t, float64(0), bid) require.Equal(t, float64(0), ask) @@ -541,11 +642,180 @@ func TestShouldCollectEnhancedTelemetryMercury(t *testing.T) { require.Equal(t, ShouldCollectEnhancedTelemetryMercury(j), false) } -func TestGetAssetSymbolFromRequestData(t *testing.T) { - e := EnhancedTelemetryService[EnhancedTelemetryMercuryData]{} - require.Equal(t, e.getAssetSymbolFromRequestData(""), "") +func TestParseBridgeRequestData(t *testing.T) { + require.Equal(t, parseBridgeRequestData("", 2), bridgeRequestData{}) + reqData := `{"data":{"to":"LINK","from":"USD"}}` - require.Equal(t, e.getAssetSymbolFromRequestData(reqData), "USD/LINK") + require.Equal(t, parseBridgeRequestData(reqData, 2), bridgeRequestData{AssetSymbol: "USD/LINK"}) + + reqData = `{"data":{"to":"LINK","from":"USD","market":"forex"}}` + require.Equal(t, parseBridgeRequestData(reqData, 2), bridgeRequestData{AssetSymbol: "USD/LINK"}) + + reqData = `{"data":{"endpoint":"market-status","market":"forex"}}` + require.Equal(t, parseBridgeRequestData(reqData, 4), bridgeRequestData{AssetSymbol: "forex", IsMarketStatus: true}) + + reqData = `{"data":{"market":"metals"}}` + require.Equal(t, parseBridgeRequestData(reqData, 4), bridgeRequestData{AssetSymbol: "metals", IsMarketStatus: true}) + + viewFunctionReqData := `{"data":{"address":"0x12345678", "signature": "function stEthPerToken() view returns (int256)"}}` + require.Equal(t, parseBridgeRequestData(viewFunctionReqData, 3), bridgeRequestData{AssetSymbol: "0x12345678"}) +} + +func getViewFunctionTaskRunResults() pipeline.TaskRunResults { + var taskViewFunctionParseValue = func() pipeline.MultiplyTask { + task := pipeline.MultiplyTask{ + BaseTask: pipeline.NewBaseTask(3, "ds1_parse", nil, nil, 3), + Times: "1", + } + task.BaseTask.Tags = `{"priceType": "exchangeRate"}` + return task + }() + + var taskViewFunctionDecode = pipeline.ETHABIDecodeTask{ + ABI: "uint256 data", + BaseTask: pipeline.NewBaseTask(2, "ds1_decode", nil, []pipeline.Task{&taskViewFunctionParseValue}, 2), + } + + var taskViewFunctionJSONParse = pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "ds1_parse", nil, []pipeline.Task{&taskViewFunctionDecode}, 1), + } + + const viewFunctionBridgeResponse = `{ + "data": { + "result": "0x000000000000000000000000000000000000000000000000105ba6a589b23a81" + }, + "statusCode": 200, + "result": "0x000000000000000000000000000000000000000000000000105ba6a589b23a81", + "timestamps": { + "providerDataRequestedUnixMs": 1726243598046, + "providerDataReceivedUnixMs": 1726243598341 + }, + "meta": { + "adapterName": "VIEW_FUNCTION" + } + }` + + var taskViewFunctionBridgeRequest = pipeline.BridgeTask{ + Name: "bridge-view-function", + BaseTask: pipeline.NewBaseTask(0, "ds1", nil, []pipeline.Task{&taskViewFunctionJSONParse}, 0), + RequestData: `{"data":{"address":"0x1234","signature":"function stEthPerToken() external view returns (uint256)"}}`, + } + + return pipeline.TaskRunResults{ + pipeline.TaskRunResult{ + Task: &taskViewFunctionBridgeRequest, + Result: pipeline.Result{ + Value: viewFunctionBridgeResponse, + }, + }, + pipeline.TaskRunResult{ + Task: &taskViewFunctionJSONParse, + Result: pipeline.Result{ + Value: `0x000000000000000000000000000000000000000000000000105ba6a589b23a81`, + }, + }, + pipeline.TaskRunResult{ + Task: &taskViewFunctionDecode, + Result: pipeline.Result{ + Value: map[string]interface{}{ + "data": big.NewInt(1178718957397490305), + }, + }, + }, + pipeline.TaskRunResult{ + Task: &taskViewFunctionParseValue, + Result: pipeline.Result{ + Value: decimal.NewFromInt(1178718957397490305), + }, + }, + } +} + +func TestCollectMercuryEnhancedTelemetryV1ViewFunction(t *testing.T) { + wg := sync.WaitGroup{} + ingressClient := mocks.NewTelemetryService(t) + ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient) + monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.EnhancedEAMercury) + + var sentMessage []byte + ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) { + sentMessage = args[1].([]byte) + wg.Done() + }) + + lggr, _ := logger.TestLoggerObserved(t, zap.WarnLevel) + chTelem := make(chan EnhancedTelemetryMercuryData, 100) + chDone := make(chan struct{}) + feedID := common.HexToHash("0x111") + e := EnhancedTelemetryService[EnhancedTelemetryMercuryData]{ + chDone: chDone, + chTelem: chTelem, + job: &job.Job{ + Type: job.Type(pipeline.OffchainReporting2JobType), + OCR2OracleSpec: &job.OCR2OracleSpec{ + CaptureEATelemetry: true, + FeedID: &feedID, + }, + }, + lggr: lggr, + monitoringEndpoint: monitoringEndpoint, + } + servicetest.Run(t, &e) + + wg.Add(1) + + taskRunResults := getViewFunctionTaskRunResults() + + chTelem <- EnhancedTelemetryMercuryData{ + TaskRunResults: taskRunResults, + V1Observation: &mercuryv1.Observation{ + BenchmarkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(111111)}, + Bid: mercury.ObsResult[*big.Int]{Val: big.NewInt(222222)}, + Ask: mercury.ObsResult[*big.Int]{Val: big.NewInt(333333)}, + CurrentBlockNum: mercury.ObsResult[int64]{Val: 123456789}, + CurrentBlockHash: mercury.ObsResult[[]byte]{Val: common.HexToHash("0x123321").Bytes()}, + CurrentBlockTimestamp: mercury.ObsResult[uint64]{Val: 987654321}, + }, + RepTimestamp: types.ReportTimestamp{ + ConfigDigest: types.ConfigDigest{2}, + Epoch: 11, + Round: 22, + }, + } + + expectedTelemetry := telem.EnhancedEAMercury{ + DataSource: "VIEW_FUNCTION", + DpBenchmarkPrice: 1178718957397490400, + DpBid: 1178718957397490400, + DpAsk: 1178718957397490400, + CurrentBlockNumber: 123456789, + CurrentBlockHash: common.HexToHash("0x123321").String(), + CurrentBlockTimestamp: 987654321, + BridgeTaskRunStartedTimestamp: taskRunResults[0].CreatedAt.UnixMilli(), + BridgeTaskRunEndedTimestamp: taskRunResults[0].FinishedAt.Time.UnixMilli(), + ProviderRequestedTimestamp: 1726243598046, + ProviderReceivedTimestamp: 1726243598341, + ProviderDataStreamEstablished: 0, + ProviderIndicatedTime: 0, + Feed: common.HexToHash("0x111").String(), + ObservationBenchmarkPrice: 111111, + ObservationBid: 222222, + ObservationAsk: 333333, + ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000", + Round: 22, + Epoch: 11, + BridgeRequestData: `{"data":{"address":"0x1234","signature":"function stEthPerToken() external view returns (uint256)"}}`, + AssetSymbol: "0x1234", + ObservationBenchmarkPriceString: "111111", + ObservationBidString: "222222", + ObservationAskString: "333333", + } + + expectedMessage, _ := proto.Marshal(&expectedTelemetry) + wg.Wait() + require.Equal(t, expectedMessage, sentMessage) + + chDone <- struct{}{} } func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) { @@ -619,6 +889,7 @@ func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) { ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000", Round: 22, Epoch: 11, + BridgeRequestData: `{"data":{"to":"LINK","from":"USD"}}`, AssetSymbol: "USD/LINK", ObservationBenchmarkPriceString: "111111", ObservationBidString: "222222", @@ -660,7 +931,7 @@ func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) { wg.Wait() require.Equal(t, 2, logs.Len()) - require.Contains(t, logs.All()[0].Message, `cannot get bridge response from bridge task, job=0, id=ds1, name="test-mercury-bridge-1"`) + require.Contains(t, logs.All()[0].Message, `cannot get bridge response from bridge task, id=ds1, name="test-mercury-bridge-1"`) require.Contains(t, logs.All()[1].Message, "cannot parse EA telemetry") chDone <- struct{}{} } @@ -732,6 +1003,7 @@ func TestCollectMercuryEnhancedTelemetryV2(t *testing.T) { ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000", Round: 22, Epoch: 11, + BridgeRequestData: `{"data":{"to":"LINK","from":"USD"}}`, AssetSymbol: "USD/LINK", ObservationBenchmarkPriceString: "111111", MaxFinalizedTimestamp: 321, @@ -781,3 +1053,81 @@ func TestCollectMercuryEnhancedTelemetryV2(t *testing.T) { require.Contains(t, logs.All()[3].Message, "cannot parse enhanced EA telemetry bid price") chDone <- struct{}{} } + +func TestCollectMercuryEnhancedTelemetryV4(t *testing.T) { + ingressClient := mocks.NewTelemetryService(t) + ingressAgent := telemetry.NewIngressAgentWrapper(ingressClient) + monitoringEndpoint := ingressAgent.GenMonitoringEndpoint("test-network", "test-chainID", "0xa", synchronization.EnhancedEAMercury) + + sentMessageCh := make(chan []byte) + ingressClient.On("Send", mock.Anything, mock.AnythingOfType("[]uint8"), mock.AnythingOfType("string"), mock.AnythingOfType("TelemetryType")).Return().Run(func(args mock.Arguments) { + sentMessageCh <- args[1].([]byte) + }) + + lggr, _ := logger.TestLoggerObserved(t, zap.WarnLevel) + chTelem := make(chan EnhancedTelemetryMercuryData, 100) + chDone := make(chan struct{}) + feedID := common.HexToHash("0x0004") + e := EnhancedTelemetryService[EnhancedTelemetryMercuryData]{ + chDone: chDone, + chTelem: chTelem, + job: &job.Job{ + Type: job.Type(pipeline.OffchainReporting2JobType), + OCR2OracleSpec: &job.OCR2OracleSpec{ + CaptureEATelemetry: true, + FeedID: &feedID, + }, + }, + lggr: lggr, + monitoringEndpoint: monitoringEndpoint, + } + servicetest.Run(t, &e) + + chTelem <- EnhancedTelemetryMercuryData{ + TaskRunResults: trrsMercuryV4, + FeedVersion: 4, + V4Observation: &mercuryv4.Observation{ + BenchmarkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(111111)}, + MarketStatus: mercury.ObsResult[uint32]{Val: 2}, + MaxFinalizedTimestamp: mercury.ObsResult[int64]{Val: 321}, + LinkPrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(4321)}, + NativePrice: mercury.ObsResult[*big.Int]{Val: big.NewInt(54321)}, + }, + RepTimestamp: types.ReportTimestamp{ + ConfigDigest: types.ConfigDigest{2}, + Epoch: 11, + Round: 22, + }, + } + + expectedPricingTelemetry := telem.EnhancedEAMercury{ + DataSource: "data-source-name", + DpBenchmarkPrice: 123456.123456, + BridgeTaskRunStartedTimestamp: trrsMercuryV4[0].CreatedAt.UnixMilli(), + BridgeTaskRunEndedTimestamp: trrsMercuryV4[0].FinishedAt.Time.UnixMilli(), + ProviderRequestedTimestamp: 92233720368547760, + ProviderReceivedTimestamp: -92233720368547760, + ProviderDataStreamEstablished: 1, + ProviderIndicatedTime: -123456789, + Feed: common.HexToHash("0x0004").String(), + ObservationBenchmarkPrice: 111111, + ObservationMarketStatus: 2, + ConfigDigest: "0200000000000000000000000000000000000000000000000000000000000000", + Round: 22, + Epoch: 11, + AssetSymbol: "USD/LINK", + ObservationBenchmarkPriceString: "111111", + MaxFinalizedTimestamp: 321, + LinkPrice: 4321, + NativePrice: 54321, + Version: 4, + BridgeRequestData: `{"data":{"to":"LINK","from":"USD"}}`, + } + expectedPricingMessage, _ := proto.Marshal(&expectedPricingTelemetry) + require.Equal(t, expectedPricingMessage, <-sentMessageCh) + + chDone <- struct{}{} + + // Verify that no other telemetry is sent. + require.Len(t, sentMessageCh, 0) +} diff --git a/core/services/ocrcommon/transmitter.go b/core/services/ocrcommon/transmitter.go index ccd2b010453..5d2de45295f 100644 --- a/core/services/ocrcommon/transmitter.go +++ b/core/services/ocrcommon/transmitter.go @@ -23,7 +23,7 @@ type txManager interface { type Transmitter interface { CreateEthTransaction(ctx context.Context, toAddress common.Address, payload []byte, txMeta *txmgr.TxMeta) error - FromAddress() common.Address + FromAddress(context.Context) common.Address } type transmitter struct { @@ -129,7 +129,7 @@ func (t *transmitter) CreateEthTransaction(ctx context.Context, toAddress common return errors.Wrap(err, "skipped OCR transmission") } -func (t *transmitter) FromAddress() common.Address { +func (t *transmitter) FromAddress(context.Context) common.Address { return t.effectiveTransmitterAddress } @@ -168,13 +168,13 @@ func (t *ocr2FeedsTransmitter) CreateEthTransaction(ctx context.Context, toAddre } // FromAddress for ocr2FeedsTransmitter returns valid forwarder or effectiveTransmitterAddress if forwarders are not set. -func (t *ocr2FeedsTransmitter) FromAddress() common.Address { - roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(context.Background(), t.chainID, t.fromAddresses...) +func (t *ocr2FeedsTransmitter) FromAddress(ctx context.Context) common.Address { + roundRobinFromAddress, err := t.keystore.GetRoundRobinAddress(ctx, t.chainID, t.fromAddresses...) if err != nil { return t.effectiveTransmitterAddress } - forwarderAddress, err := t.GetForwarderForEOAOCR2Feeds(context.Background(), roundRobinFromAddress, t.ocr2Aggregator) + 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 diff --git a/core/services/pg/lease_lock_test.go b/core/services/pg/lease_lock_test.go index 1b4116b5bf9..65bbe3b8610 100644 --- a/core/services/pg/lease_lock_test.go +++ b/core/services/pg/lease_lock_test.go @@ -12,11 +12,11 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) func newLeaseLock(t *testing.T, db *sqlx.DB, cfg pg.LeaseLockConfig) pg.LeaseLock { diff --git a/core/services/pipeline/common.go b/core/services/pipeline/common.go index 1b36c8a664b..50611ee32a4 100644 --- a/core/services/pipeline/common.go +++ b/core/services/pipeline/common.go @@ -11,14 +11,15 @@ import ( "strings" "time" + "github.com/go-viper/mapstructure/v2" "github.com/google/uuid" - "github.com/mitchellh/mapstructure" pkgerrors "github.com/pkg/errors" "gopkg.in/guregu/null.v4" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/logger" cnull "github.com/smartcontractkit/chainlink/v2/core/null" @@ -59,6 +60,8 @@ type ( TaskRetries() uint32 TaskMinBackoff() time.Duration TaskMaxBackoff() time.Duration + TaskTags() string + GetDescendantTasks() []Task } Config interface { @@ -262,6 +265,16 @@ func (trrs TaskRunResults) Terminals() (terminals []TaskRunResult) { return } +// GetNextTaskOf returns the task with the next id or nil if it does not exist +func (trrs *TaskRunResults) GetTaskRunResultOf(task Task) *TaskRunResult { + for _, trr := range *trrs { + if trr.Task.Base().id == task.Base().id { + return &trr + } + } + return nil +} + // GetNextTaskOf returns the task with the next id or nil if it does not exist func (trrs *TaskRunResults) GetNextTaskOf(task TaskRunResult) *TaskRunResult { nextID := task.Task.Base().id + 1 diff --git a/core/services/pipeline/common_test.go b/core/services/pipeline/common_test.go index ce545ec14a0..ed7998b79e3 100644 --- a/core/services/pipeline/common_test.go +++ b/core/services/pipeline/common_test.go @@ -17,6 +17,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) +func TestAtrributesAttribute(t *testing.T) { + a := `ds1 [type=http method=GET tags=<{"attribute1":"value1", "attribute2":42}>];` + p, err := pipeline.Parse(a) + require.NoError(t, err) + task := p.Tasks[0] + assert.Equal(t, "{\"attribute1\":\"value1\", \"attribute2\":42}", task.TaskTags()) +} + func TestTimeoutAttribute(t *testing.T) { t.Parallel() @@ -320,3 +328,69 @@ func TestGetNextTaskOf(t *testing.T) { nextTask = trrs.GetNextTaskOf(*nextTask) assert.Empty(t, nextTask) } + +func TestGetDescendantTasks(t *testing.T) { + t.Parallel() + + t.Run("GetDescendantTasks with multiple levels of tasks", func(t *testing.T) { + l3T2 := pipeline.AnyTask{ + BaseTask: pipeline.NewBaseTask(6, "l3T2", nil, nil, 1), + } + l3T1 := pipeline.MedianTask{ + BaseTask: pipeline.NewBaseTask(5, "l3T1", nil, nil, 1), + } + l2T1 := pipeline.MultiplyTask{ + BaseTask: pipeline.NewBaseTask(4, "l2T1", nil, []pipeline.Task{&l3T1, &l3T2}, 1), + } + l1T1 := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(3, "l1T1", nil, []pipeline.Task{&l2T1}, 2), + } + l1T2 := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(2, "l1T2", nil, nil, 3), + } + l1T3 := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "l1T3", nil, nil, 4), + } + + baseTask := pipeline.BridgeTask{ + Name: "bridge-task", + BaseTask: pipeline.NewBaseTask(0, "baseTask", nil, []pipeline.Task{&l1T1, &l1T2, &l1T3}, 0), + } + + descendents := baseTask.GetDescendantTasks() + assert.Len(t, descendents, 6) + }) + + t.Run("GetDescendantTasks with duplicate tasks defined", func(t *testing.T) { + l2T1 := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(2, "l1T2", nil, nil, 3), + } + l1T1 := pipeline.JSONParseTask{ + BaseTask: pipeline.NewBaseTask(1, "l1T2", nil, []pipeline.Task{&l2T1, &l2T1, &l2T1}, 3), + } + taskWithRepeats := pipeline.BridgeTask{ + Name: "bridge-task", + BaseTask: pipeline.NewBaseTask(0, "taskWithRepeats", nil, []pipeline.Task{&l1T1, &l1T1, &l1T1}, 0), + } + descendents := taskWithRepeats.GetDescendantTasks() + assert.Len(t, descendents, 2) + }) + + t.Run("GetDescendantTasks with nil output tasks", func(t *testing.T) { + taskWithRepeats := pipeline.BridgeTask{ + Name: "bridge-task", + BaseTask: pipeline.NewBaseTask(0, "taskWithRepeats", nil, nil, 0), + } + descendents := taskWithRepeats.GetDescendantTasks() + assert.Len(t, descendents, 0) + }) + + t.Run("GetDescendantTasks with empty list of output tasks", func(t *testing.T) { + taskWithRepeats := pipeline.BridgeTask{ + Name: "bridge-task", + BaseTask: pipeline.NewBaseTask(0, "taskWithRepeats", nil, []pipeline.Task{}, 0), + } + descendents := taskWithRepeats.GetDescendantTasks() + assert.Len(t, descendents, 0) + }) +} diff --git a/core/services/pipeline/getters.go b/core/services/pipeline/getters.go index bbeb0050d68..1dff20f5bf4 100644 --- a/core/services/pipeline/getters.go +++ b/core/services/pipeline/getters.go @@ -147,7 +147,7 @@ func JSONWithVarExprs(jsExpr string, vars Vars, allowErrors bool) GetterFunc { } keypath, is := maybeKeypath.(string) if !is { - return nil, errors.Wrapf(ErrBadInput, fmt.Sprintf("you cannot use %s in your JSON", chainlinkKeyPath)) + return nil, errors.Wrap(ErrBadInput, fmt.Sprintf("you cannot use %s in your JSON", chainlinkKeyPath)) } newVal, err := vars.Get(keypath) if err != nil { diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 877aa9e4aa5..f3d529d87e6 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -21,7 +21,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -30,6 +29,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) type testOnlyORM interface { diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go index 022a77c9471..9b7a21d939b 100644 --- a/core/services/pipeline/runner_test.go +++ b/core/services/pipeline/runner_test.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/jmoiron/sqlx" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -21,8 +22,6 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/bridges" bridgesMocks "github.com/smartcontractkit/chainlink/v2/core/bridges/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -36,14 +35,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" "github.com/smartcontractkit/chainlink/v2/core/utils" - - "github.com/jmoiron/sqlx" ) func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) orm := mocks.NewORM(t) c := clhttptest.NewTestLocalOnlyHTTPClient() r := pipeline.NewRunner(orm, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, logger.TestLogger(t), c, c) @@ -131,6 +127,50 @@ ds5 [type=http method="GET" url="%s" index=2] require.Len(t, errorResults, 3) } +func Test_PipelineRunner_ExecuteEthAbiDecode(t *testing.T) { + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewTestGeneralConfig(t) + + mockResult := `{"data":{"result":"0x000000000000000000000000000000000000000000000000105ba6a589b23a81"}}` + s1 := httptest.NewServer(NewMockHandler(mockResult)) + defer s1.Close() + + bridgeFeedURL, err := url.ParseRequestURI(s1.URL) + require.NoError(t, err) + + _, bt := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{URL: bridgeFeedURL.String()}) + + btORM := bridgesMocks.NewORM(t) + btORM.On("FindBridge", mock.Anything, bt.Name).Return(*bt, nil).Once() + + r, _ := newRunner(t, db, btORM, cfg) + + s := fmt.Sprintf(` + ds1 [type=bridge name="%s" timeout=0 requestData=<{"data": {"address": "0x1234"}}>] + ds1_parse [type=jsonparse path="data,result"] + ds1_decode [type=ethabidecode abi="int256 data" data="$(ds1_parse)"]; + ds1_value [type="multiply" input="$(ds1_decode.data)" times=1] + + ds1->ds1_parse->ds1_decode->ds1_value + +`, bt.Name.String()) + d, err := pipeline.Parse(s) + require.NoError(t, err) + + spec := pipeline.Spec{DotDagSource: s} + vars := pipeline.NewVarsFrom(nil) + + _, trrs, err := r.ExecuteRun(testutils.Context(t), spec, vars) + require.NoError(t, err) + require.Len(t, trrs, len(d.Tasks)) + + finalResults := trrs.FinalResult() + + val := finalResults.Values[0].(decimal.Decimal) + + assert.Equal(t, decimal.NewFromInt(1178718957397490305), val) +} + type taskRunWithVars struct { bridgeName string ds2URL, ds4URL string @@ -468,8 +508,7 @@ func Test_PipelineRunner_HandleFaultsPersistRun(t *testing.T) { Return(nil) cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) lggr := logger.TestLogger(t) r := pipeline.NewRunner(orm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, lggr, nil, nil) @@ -508,8 +547,7 @@ func Test_PipelineRunner_ExecuteAndInsertFinishedRun_SavingTheSpec(t *testing.T) Return(nil) cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) lggr := logger.TestLogger(t) r := pipeline.NewRunner(orm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, lggr, nil, nil) @@ -978,8 +1016,7 @@ func Test_PipelineRunner_ExecuteRun(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) lggr := logger.TestLogger(t) r := pipeline.NewRunner(nil, nil, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, lggr, nil, nil) diff --git a/core/services/pipeline/task.base.go b/core/services/pipeline/task.base.go index 7a62f4e7ff8..3e1db5fcdb5 100644 --- a/core/services/pipeline/task.base.go +++ b/core/services/pipeline/task.base.go @@ -22,6 +22,8 @@ type BaseTask struct { MinBackoff time.Duration `mapstructure:"minBackoff"` MaxBackoff time.Duration `mapstructure:"maxBackoff"` + Tags string `mapstructure:"tags" json:"-"` + uuid uuid.UUID } @@ -77,3 +79,32 @@ func (t BaseTask) TaskMaxBackoff() time.Duration { } return time.Minute } + +func (t BaseTask) TaskTags() string { + return t.Tags +} + +// GetDescendantTasks retrieves all descendant tasks of a given task +func (t BaseTask) GetDescendantTasks() []Task { + if len(t.outputs) == 0 { + return []Task{} + } + var descendants []Task + queue := append([]Task{}, t.outputs...) + visited := make(map[int]bool) + + for len(queue) > 0 { + currentTask := queue[0] + queue = queue[1:] + + taskID := currentTask.ID() + if visited[taskID] { + continue + } + visited[taskID] = true + descendants = append(descendants, currentTask) + queue = append(queue, currentTask.Outputs()...) + } + + return descendants +} diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go index d7519232eb5..cd81f8656fd 100644 --- a/core/services/pipeline/task.bridge_test.go +++ b/core/services/pipeline/task.bridge_test.go @@ -117,6 +117,18 @@ func mustReadFile(t testing.TB, file string) string { return string(content) } +// NewMockHandler returns an http.HandlerFunc that responds with the given payload for any request +func NewMockHandler(payload string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, err := w.Write([]byte(payload)) + if err != nil { + http.Error(w, "Failed to write response", http.StatusInternalServerError) + } + } +} + func fakePriceResponder(t *testing.T, requestData map[string]interface{}, result decimal.Decimal, inputKey string, expectedInput interface{}) http.Handler { t.Helper() diff --git a/core/services/pipeline/task.eth_abi_decode_test.go b/core/services/pipeline/task.eth_abi_decode_test.go index 3c7f5b4776b..565e8b485dd 100644 --- a/core/services/pipeline/task.eth_abi_decode_test.go +++ b/core/services/pipeline/task.eth_abi_decode_test.go @@ -25,6 +25,20 @@ var testsABIDecode = []struct { expectedErrorCause error expectedErrorContains string }{ + { + "uint256", + "uint256 data", + "$(data)", + NewVarsFrom(map[string]interface{}{ + "data": "0x000000000000000000000000000000000000000000000000105ba6a589b23a81", + }), + nil, + map[string]interface{}{ + "data": big.NewInt(1178718957397490305), + }, + nil, + "", + }, { "uint256, bool, int256, string", "uint256 u, bool b, int256 i, string s", diff --git a/core/services/pipeline/task.eth_call_test.go b/core/services/pipeline/task.eth_call_test.go index b21b3065f8c..5106bb12d33 100644 --- a/core/services/pipeline/task.eth_call_test.go +++ b/core/services/pipeline/task.eth_call_test.go @@ -25,7 +25,6 @@ import ( keystoremocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" pipelinemocks "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func TestETHCallTask(t *testing.T) { @@ -313,8 +312,7 @@ func TestETHCallTask(t *testing.T) { var legacyChains legacyevm.LegacyChainContainer if test.expectedErrorCause != nil || test.expectedErrorContains != "" { - exts := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, TxManager: txManager, KeyStore: keyStore}) - legacyChains = evmrelay.NewLegacyChainsFromRelayerExtenders(exts) + legacyChains = evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, TxManager: txManager, KeyStore: keyStore}) } else { legacyChains = cltest.NewLegacyChainsWithMockChain(t, ethClient, cfg) } diff --git a/core/services/pipeline/task.eth_tx.go b/core/services/pipeline/task.eth_tx.go index 964591cacd2..3c340261966 100644 --- a/core/services/pipeline/task.eth_tx.go +++ b/core/services/pipeline/task.eth_tx.go @@ -8,13 +8,14 @@ import ( "strconv" "github.com/ethereum/go-ethereum/common" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" "github.com/pkg/errors" "go.uber.org/multierr" "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -63,11 +64,11 @@ func (t *ETHTxTask) getEvmChainID() string { return t.EVMChainID } -func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { +func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inputs []Result) (Result, RunInfo) { var chainID StringParam err := errors.Wrap(ResolveParam(&chainID, From(VarExpr(t.getEvmChainID(), vars), NonemptyString(t.getEvmChainID()), "")), "evmChainID") if err != nil { - return Result{Error: err}, runInfo + return Result{Error: err}, RunInfo{} } chain, err := t.legacyChains.Get(string(chainID)) @@ -80,7 +81,7 @@ func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inpu txManager := chain.TxManager() _, err = CheckInputs(inputs, -1, -1, 0) if err != nil { - return Result{Error: errors.Wrap(err, "task inputs")}, runInfo + return Result{Error: errors.Wrap(err, "task inputs")}, RunInfo{} } maximumGasLimit := SelectGasLimit(cfg.GasEstimator(), t.jobType, t.specGasLimit) @@ -106,25 +107,20 @@ func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inpu errors.Wrap(ResolveParam(&failOnRevert, From(NonemptyString(t.FailOnRevert), false)), "failOnRevert"), ) if err != nil { - return Result{Error: err}, runInfo - } - var minOutgoingConfirmations uint64 - if min, isSet := maybeMinConfirmations.Uint64(); isSet { - minOutgoingConfirmations = min - } else { - minOutgoingConfirmations = uint64(cfg.FinalityDepth()) + return Result{Error: err}, RunInfo{} } + minOutgoingConfirmations, isMinConfirmationSet := maybeMinConfirmations.Uint64() txMeta, err := decodeMeta(txMetaMap) if err != nil { - return Result{Error: err}, runInfo + return Result{Error: err}, RunInfo{} } txMeta.FailOnRevert = null.BoolFrom(bool(failOnRevert)) setJobIDOnMeta(lggr, vars, txMeta) transmitChecker, err := decodeTransmitChecker(transmitCheckerMap) if err != nil { - return Result{Error: err}, runInfo + return Result{Error: err}, RunInfo{} } fromAddr, err := t.keyStore.GetRoundRobinAddress(ctx, chain.ID(), fromAddrs...) @@ -158,8 +154,11 @@ func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inpu SignalCallback: true, } - if minOutgoingConfirmations > 0 { - // Store the task run ID, so we can resume the pipeline when tx is confirmed + if !isMinConfirmationSet { + // Store the task run ID, so we can resume the pipeline when tx is finalized + txRequest.PipelineTaskRunID = &t.uuid + } else if minOutgoingConfirmations > 0 { + // Store the task run ID, so we can resume the pipeline after minOutgoingConfirmations txRequest.PipelineTaskRunID = &t.uuid txRequest.MinConfirmations = clnull.Uint32From(uint32(minOutgoingConfirmations)) } @@ -169,11 +168,11 @@ func (t *ETHTxTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inpu return Result{Error: errors.Wrapf(ErrTaskRunFailed, "while creating transaction: %v", err)}, retryableRunInfo() } - if minOutgoingConfirmations > 0 { - return Result{}, pendingRunInfo() + if txRequest.PipelineTaskRunID != nil { + return Result{}, RunInfo{IsPending: true} } - return Result{Value: nil}, runInfo + return Result{}, RunInfo{} } func decodeMeta(metaMap MapParam) (*txmgr.TxMeta, error) { diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go index 5b9beeb43e1..57f7976f0ab 100644 --- a/core/services/pipeline/task.eth_tx_test.go +++ b/core/services/pipeline/task.eth_tx_test.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" keystoremocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func TestETHTxTask(t *testing.T) { @@ -579,9 +578,8 @@ func TestETHTxTask(t *testing.T) { }) lggr := logger.TestLogger(t) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, TxManager: txManager, KeyStore: keyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) test.setupClientMocks(keyStore, txManager) task.HelperSetDependencies(legacyChains, keyStore, test.specGasLimit, pipeline.DirectRequestJobType) diff --git a/core/services/registrysyncer/local_registry.go b/core/services/registrysyncer/local_registry.go index d4bf4a49f53..5bec59412f4 100644 --- a/core/services/registrysyncer/local_registry.go +++ b/core/services/registrysyncer/local_registry.go @@ -32,7 +32,7 @@ type LocalRegistry struct { lggr logger.Logger getPeerID func() (p2ptypes.PeerID, error) IDsToDONs map[DonID]DON - IDsToNodes map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo + IDsToNodes map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo IDsToCapabilities map[string]Capability } @@ -40,7 +40,7 @@ func NewLocalRegistry( lggr logger.Logger, getPeerID func() (p2ptypes.PeerID, error), IDsToDONs map[DonID]DON, - IDsToNodes map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo, + IDsToNodes map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo, IDsToCapabilities map[string]Capability, ) LocalRegistry { return LocalRegistry{ diff --git a/core/services/registrysyncer/monitoring.go b/core/services/registrysyncer/monitoring.go new file mode 100644 index 00000000000..0b75e798625 --- /dev/null +++ b/core/services/registrysyncer/monitoring.go @@ -0,0 +1,48 @@ +package registrysyncer + +import ( + "context" + "fmt" + + "go.opentelemetry.io/otel/metric" + + "github.com/smartcontractkit/chainlink-common/pkg/beholder" + "github.com/smartcontractkit/chainlink/v2/core/monitoring" +) + +var remoteRegistrySyncFailureCounter metric.Int64Counter +var launcherFailureCounter metric.Int64Counter + +func initMonitoringResources() (err error) { + remoteRegistrySyncFailureCounter, err = beholder.GetMeter().Int64Counter("RemoteRegistrySyncFailure") + if err != nil { + return fmt.Errorf("failed to register sync failure counter: %w", err) + } + + launcherFailureCounter, err = beholder.GetMeter().Int64Counter("LauncherFailureCounter") + if err != nil { + return fmt.Errorf("failed to register launcher failure counter: %w", err) + } + + return nil +} + +// syncerMetricLabeler wraps monitoring.MetricsLabeler to provide workflow specific utilities +// for monitoring resources +type syncerMetricLabeler struct { + monitoring.MetricsLabeler +} + +func (c syncerMetricLabeler) with(keyValues ...string) syncerMetricLabeler { + return syncerMetricLabeler{c.With(keyValues...)} +} + +func (c syncerMetricLabeler) incrementRemoteRegistryFailureCounter(ctx context.Context) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + remoteRegistrySyncFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c syncerMetricLabeler) incrementLauncherFailureCounter(ctx context.Context) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + launcherFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} diff --git a/core/services/registrysyncer/monitoring_test.go b/core/services/registrysyncer/monitoring_test.go new file mode 100644 index 00000000000..f19f43393a1 --- /dev/null +++ b/core/services/registrysyncer/monitoring_test.go @@ -0,0 +1,19 @@ +package registrysyncer + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/monitoring" +) + +func Test_InitMonitoringResources(t *testing.T) { + require.NoError(t, initMonitoringResources()) +} + +func Test_SyncerMetricsLabeler(t *testing.T) { + testSyncerMetricLabeler := syncerMetricLabeler{monitoring.NewMetricsLabeler()} + testSyncerMetricLabeler2 := testSyncerMetricLabeler.with("foo", "baz") + require.EqualValues(t, testSyncerMetricLabeler2.Labels["foo"], "baz") +} diff --git a/core/services/registrysyncer/orm.go b/core/services/registrysyncer/orm.go index cb08eaafeaf..9c666200752 100644 --- a/core/services/registrysyncer/orm.go +++ b/core/services/registrysyncer/orm.go @@ -20,6 +20,7 @@ type capabilitiesRegistryNodeInfo struct { WorkflowDONId uint32 `json:"workflowDONId"` Signer p2ptypes.PeerID `json:"signer"` P2pId p2ptypes.PeerID `json:"p2pId"` + EncryptionPublicKey [32]byte `json:"encryptionPublicKey"` HashedCapabilityIds []p2ptypes.PeerID `json:"hashedCapabilityIds"` CapabilitiesDONIds []string `json:"capabilitiesDONIds"` } @@ -41,6 +42,7 @@ func (l *LocalRegistry) MarshalJSON() ([]byte, error) { WorkflowDONId: v.WorkflowDONId, Signer: p2ptypes.PeerID(v.Signer[:]), P2pId: p2ptypes.PeerID(v.P2pId[:]), + EncryptionPublicKey: v.EncryptionPublicKey, HashedCapabilityIds: hashedCapabilityIds, CapabilitiesDONIds: capabilitiesDONIds, } @@ -78,7 +80,7 @@ func (l *LocalRegistry) UnmarshalJSON(data []byte) error { l.IDsToDONs = temp.IDsToDONs - l.IDsToNodes = make(map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo) + l.IDsToNodes = make(map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo) for peerID, v := range temp.IDsToNodes { hashedCapabilityIds := make([][32]byte, len(v.HashedCapabilityIds)) for i, id := range v.HashedCapabilityIds { @@ -91,12 +93,13 @@ func (l *LocalRegistry) UnmarshalJSON(data []byte) error { bigInt.SetString(id, 10) capabilitiesDONIds[i] = bigInt } - l.IDsToNodes[peerID] = kcr.CapabilitiesRegistryNodeInfo{ + l.IDsToNodes[peerID] = kcr.INodeInfoProviderNodeInfo{ NodeOperatorId: v.NodeOperatorId, ConfigCount: v.ConfigCount, WorkflowDONId: v.WorkflowDONId, Signer: v.Signer, P2pId: v.P2pId, + EncryptionPublicKey: v.EncryptionPublicKey, HashedCapabilityIds: hashedCapabilityIds, CapabilitiesDONIds: capabilitiesDONIds, } diff --git a/core/services/registrysyncer/orm_test.go b/core/services/registrysyncer/orm_test.go index 03772ea22bf..429bfff664b 100644 --- a/core/services/registrysyncer/orm_test.go +++ b/core/services/registrysyncer/orm_test.go @@ -111,11 +111,12 @@ func generateState(t *testing.T) registrysyncer.LocalRegistry { CapabilityType: capabilities.CapabilityTypeConsensus, }, }, - IDsToNodes: map[types.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + IDsToNodes: map[types.PeerID]kcr.INodeInfoProviderNodeInfo{ nodes[0]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{capabilityID, capabilityID2}, CapabilitiesDONIds: []*big.Int{}, }, @@ -123,6 +124,7 @@ func generateState(t *testing.T) registrysyncer.LocalRegistry { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{capabilityID, capabilityID2}, CapabilitiesDONIds: []*big.Int{}, }, @@ -130,6 +132,7 @@ func generateState(t *testing.T) registrysyncer.LocalRegistry { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{capabilityID, capabilityID2}, CapabilitiesDONIds: []*big.Int{}, }, @@ -137,6 +140,7 @@ func generateState(t *testing.T) registrysyncer.LocalRegistry { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[3], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{capabilityID, capabilityID2}, CapabilitiesDONIds: []*big.Int{}, }, diff --git a/core/services/registrysyncer/syncer.go b/core/services/registrysyncer/syncer.go index ab50c448b5c..d4f343f12bf 100644 --- a/core/services/registrysyncer/syncer.go +++ b/core/services/registrysyncer/syncer.go @@ -44,13 +44,14 @@ type RegistrySyncer interface { type registrySyncer struct { services.StateMachine - stopCh services.StopChan - launchers []Launcher - reader types.ContractReader - initReader func(ctx context.Context, lggr logger.Logger, relayer ContractReaderFactory, registryAddress string) (types.ContractReader, error) - relayer ContractReaderFactory - registryAddress string - getPeerID func() (p2ptypes.PeerID, error) + metrics syncerMetricLabeler + stopCh services.StopChan + launchers []Launcher + reader types.ContractReader + initReader func(ctx context.Context, lggr logger.Logger, relayer ContractReaderFactory, capabilitiesContract types.BoundContract) (types.ContractReader, error) + relayer ContractReaderFactory + capabilitiesContract types.BoundContract + getPeerID func() (p2ptypes.PeerID, error) orm ORM @@ -76,21 +77,24 @@ func New( orm ORM, ) (RegistrySyncer, error) { return ®istrySyncer{ - stopCh: make(services.StopChan), - updateChan: make(chan *LocalRegistry), - lggr: lggr.Named("RegistrySyncer"), - relayer: relayer, - registryAddress: registryAddress, - initReader: newReader, - orm: orm, - getPeerID: getPeerID, + stopCh: make(services.StopChan), + updateChan: make(chan *LocalRegistry), + lggr: lggr.Named("RegistrySyncer"), + relayer: relayer, + capabilitiesContract: types.BoundContract{ + Address: registryAddress, + Name: "CapabilitiesRegistry", + }, + initReader: newReader, + orm: orm, + getPeerID: getPeerID, }, nil } // NOTE: this can't be called while initializing the syncer and needs to be called in the sync loop. // This is because Bind() makes an onchain call to verify that the contract address exists, and if // called during initialization, this results in a "no live nodes" error. -func newReader(ctx context.Context, lggr logger.Logger, relayer ContractReaderFactory, remoteRegistryAddress string) (types.ContractReader, error) { +func newReader(ctx context.Context, lggr logger.Logger, relayer ContractReaderFactory, capabilitiesContract types.BoundContract) (types.ContractReader, error) { contractReaderConfig := evmrelaytypes.ChainReaderConfig{ Contracts: map[string]evmrelaytypes.ChainContractReader{ "CapabilitiesRegistry": { @@ -120,18 +124,18 @@ func newReader(ctx context.Context, lggr logger.Logger, relayer ContractReaderFa return nil, err } - err = cr.Bind(ctx, []types.BoundContract{ - { - Address: remoteRegistryAddress, - Name: "CapabilitiesRegistry", - }, - }) + err = cr.Bind(ctx, []types.BoundContract{capabilitiesContract}) return cr, err } func (s *registrySyncer) Start(ctx context.Context) error { return s.StartOnce("RegistrySyncer", func() error { + err := initMonitoringResources() + if err != nil { + return err + } + s.wg.Add(1) go func() { defer s.wg.Done() @@ -155,7 +159,8 @@ func (s *registrySyncer) syncLoop() { // Sync for a first time outside the loop; this means we'll start a remote // sync immediately once spinning up syncLoop, as by default a ticker will - // fire for the first time at T+N, where N is the interval. + // fire for the first time at T+N, where N is the interval. We do not + // increment RemoteRegistryFailureCounter the first time s.lggr.Debug("starting initial sync with remote registry") err := s.Sync(ctx, true) if err != nil { @@ -171,6 +176,7 @@ func (s *registrySyncer) syncLoop() { err := s.Sync(ctx, false) if err != nil { s.lggr.Errorw("failed to sync with remote registry", "error", err) + s.metrics.incrementRemoteRegistryFailureCounter(ctx) } } } @@ -197,8 +203,9 @@ func (s *registrySyncer) updateStateLoop() { } func (s *registrySyncer) localRegistry(ctx context.Context) (*LocalRegistry, error) { - var caps []kcr.CapabilitiesRegistryCapabilityInfo - err := s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getCapabilities", primitives.Unconfirmed, nil, &caps) + caps := []kcr.CapabilitiesRegistryCapabilityInfo{} + + err := s.reader.GetLatestValue(ctx, s.capabilitiesContract.ReadIdentifier("getCapabilities"), primitives.Unconfirmed, nil, &caps) if err != nil { return nil, err } @@ -215,8 +222,9 @@ func (s *registrySyncer) localRegistry(ctx context.Context) (*LocalRegistry, err hashedIDsToCapabilityIDs[c.HashedId] = cid } - var dons []kcr.CapabilitiesRegistryDONInfo - err = s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getDONs", primitives.Unconfirmed, nil, &dons) + dons := []kcr.CapabilitiesRegistryDONInfo{} + + err = s.reader.GetLatestValue(ctx, s.capabilitiesContract.ReadIdentifier("getDONs"), primitives.Unconfirmed, nil, &dons) if err != nil { return nil, err } @@ -241,13 +249,14 @@ func (s *registrySyncer) localRegistry(ctx context.Context) (*LocalRegistry, err } } - var nodes []kcr.CapabilitiesRegistryNodeInfo - err = s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getNodes", primitives.Unconfirmed, nil, &nodes) + nodes := []kcr.INodeInfoProviderNodeInfo{} + + err = s.reader.GetLatestValue(ctx, s.capabilitiesContract.ReadIdentifier("getNodes"), primitives.Unconfirmed, nil, &nodes) if err != nil { return nil, err } - idsToNodes := map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{} + idsToNodes := map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{} for _, node := range nodes { idsToNodes[node.P2pId] = node } @@ -271,7 +280,7 @@ func (s *registrySyncer) Sync(ctx context.Context, isInitialSync bool) error { } if s.reader == nil { - reader, err := s.initReader(ctx, s.lggr, s.relayer, s.registryAddress) + reader, err := s.initReader(ctx, s.lggr, s.relayer, s.capabilitiesContract) if err != nil { return err } @@ -318,6 +327,7 @@ func (s *registrySyncer) Sync(ctx context.Context, isInitialSync bool) error { lrCopy := deepCopyLocalRegistry(lr) if err := h.Launch(ctx, &lrCopy); err != nil { s.lggr.Errorf("error calling launcher: %s", err) + s.metrics.incrementLauncherFailureCounter(ctx) } } @@ -357,14 +367,15 @@ func deepCopyLocalRegistry(lr *LocalRegistry) LocalRegistry { lrCopy.IDsToCapabilities[id] = cp } - lrCopy.IDsToNodes = make(map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo, len(lr.IDsToNodes)) + lrCopy.IDsToNodes = make(map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo, len(lr.IDsToNodes)) for id, node := range lr.IDsToNodes { - nodeInfo := kcr.CapabilitiesRegistryNodeInfo{ + nodeInfo := kcr.INodeInfoProviderNodeInfo{ NodeOperatorId: node.NodeOperatorId, ConfigCount: node.ConfigCount, WorkflowDONId: node.WorkflowDONId, Signer: node.Signer, P2pId: node.P2pId, + EncryptionPublicKey: node.EncryptionPublicKey, HashedCapabilityIds: make([][32]byte, len(node.HashedCapabilityIds)), CapabilitiesDONIds: make([]*big.Int, len(node.CapabilitiesDONIds)), } @@ -376,15 +387,24 @@ func deepCopyLocalRegistry(lr *LocalRegistry) LocalRegistry { return lrCopy } +type ContractCapabilityType uint8 + +const ( + ContractCapabilityTypeTrigger ContractCapabilityType = iota + ContractCapabilityTypeAction + ContractCapabilityTypeConsensus + ContractCapabilityTypeTarget +) + func toCapabilityType(capabilityType uint8) capabilities.CapabilityType { - switch capabilityType { - case 0: + switch ContractCapabilityType(capabilityType) { + case ContractCapabilityTypeTrigger: return capabilities.CapabilityTypeTrigger - case 1: + case ContractCapabilityTypeAction: return capabilities.CapabilityTypeAction - case 2: + case ContractCapabilityTypeConsensus: return capabilities.CapabilityTypeConsensus - case 3: + case ContractCapabilityTypeTarget: return capabilities.CapabilityTypeTarget default: return capabilities.CapabilityTypeUnknown diff --git a/core/services/registrysyncer/syncer_test.go b/core/services/registrysyncer/syncer_test.go index 2c08a1cdde6..d2a6bda3880 100644 --- a/core/services/registrysyncer/syncer_test.go +++ b/core/services/registrysyncer/syncer_test.go @@ -144,6 +144,7 @@ func (l *launcher) Launch(ctx context.Context, localRegistry *registrysyncer.Loc type orm struct { ormMock *syncerMocks.ORM + mu sync.RWMutex latestLocalRegistryCh chan struct{} addLocalRegistryCh chan struct{} } @@ -159,17 +160,23 @@ func newORM(t *testing.T) *orm { } func (o *orm) Cleanup() { + o.mu.Lock() + defer o.mu.Unlock() close(o.latestLocalRegistryCh) close(o.addLocalRegistryCh) } func (o *orm) AddLocalRegistry(ctx context.Context, localRegistry registrysyncer.LocalRegistry) error { + o.mu.Lock() + defer o.mu.Unlock() o.addLocalRegistryCh <- struct{}{} err := o.ormMock.AddLocalRegistry(ctx, localRegistry) return err } func (o *orm) LatestLocalRegistry(ctx context.Context) (*registrysyncer.LocalRegistry, error) { + o.mu.Lock() + defer o.mu.Unlock() o.latestLocalRegistryCh <- struct{}{} return o.ormMock.LatestLocalRegistry(ctx) } @@ -215,12 +222,17 @@ func TestReader_Integration(t *testing.T) { randomWord(), } + encPubKey1 := randomWord() + encPubKey2 := randomWord() + encPubKey3 := randomWord() + nodes := []kcr.CapabilitiesRegistryNodeParams{ { // The first NodeOperatorId has id 1 since the id is auto-incrementing. NodeOperatorId: uint32(1), Signer: signersSet[0], P2pId: nodeSet[0], + EncryptionPublicKey: encPubKey1, HashedCapabilityIds: [][32]byte{hid}, }, { @@ -228,6 +240,7 @@ func TestReader_Integration(t *testing.T) { NodeOperatorId: uint32(1), Signer: signersSet[1], P2pId: nodeSet[1], + EncryptionPublicKey: encPubKey2, HashedCapabilityIds: [][32]byte{hid}, }, { @@ -235,6 +248,7 @@ func TestReader_Integration(t *testing.T) { NodeOperatorId: uint32(1), Signer: signersSet[2], P2pId: nodeSet[2], + EncryptionPublicKey: encPubKey3, HashedCapabilityIds: [][32]byte{hid}, }, } @@ -309,7 +323,7 @@ func TestReader_Integration(t *testing.T) { assert.Equal(t, expectedDON, gotDon.DON) assert.Equal(t, configb, gotDon.CapabilityConfigurations[cid].Config) - nodesInfo := []kcr.CapabilitiesRegistryNodeInfo{ + nodesInfo := []kcr.INodeInfoProviderNodeInfo{ { // The first NodeOperatorId has id 1 since the id is auto-incrementing. NodeOperatorId: uint32(1), @@ -317,6 +331,7 @@ func TestReader_Integration(t *testing.T) { WorkflowDONId: 1, Signer: signersSet[0], P2pId: nodeSet[0], + EncryptionPublicKey: encPubKey1, HashedCapabilityIds: [][32]byte{hid}, CapabilitiesDONIds: []*big.Int{}, }, @@ -327,6 +342,7 @@ func TestReader_Integration(t *testing.T) { WorkflowDONId: 1, Signer: signersSet[1], P2pId: nodeSet[1], + EncryptionPublicKey: encPubKey2, HashedCapabilityIds: [][32]byte{hid}, CapabilitiesDONIds: []*big.Int{}, }, @@ -337,13 +353,14 @@ func TestReader_Integration(t *testing.T) { WorkflowDONId: 1, Signer: signersSet[2], P2pId: nodeSet[2], + EncryptionPublicKey: encPubKey3, HashedCapabilityIds: [][32]byte{hid}, CapabilitiesDONIds: []*big.Int{}, }, } assert.Len(t, s.IDsToNodes, 3) - assert.Equal(t, map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + assert.Equal(t, map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ nodeSet[0]: nodesInfo[0], nodeSet[1]: nodesInfo[1], nodeSet[2]: nodesInfo[2], @@ -387,6 +404,7 @@ func TestSyncer_DBIntegration(t *testing.T) { NodeOperatorId: uint32(1), Signer: signersSet[0], P2pId: nodeSet[0], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{cid}, }, { @@ -394,6 +412,7 @@ func TestSyncer_DBIntegration(t *testing.T) { NodeOperatorId: uint32(1), Signer: signersSet[1], P2pId: nodeSet[1], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{cid}, }, { @@ -401,6 +420,7 @@ func TestSyncer_DBIntegration(t *testing.T) { NodeOperatorId: uint32(1), Signer: signersSet[2], P2pId: nodeSet[2], + EncryptionPublicKey: randomWord(), HashedCapabilityIds: [][32]byte{cid}, }, } @@ -455,7 +475,7 @@ func TestSyncer_DBIntegration(t *testing.T) { syncer.AddLauncher(l) var latestLocalRegistryCalled, addLocalRegistryCalled bool - timeout := time.After(500 * time.Millisecond) + timeout := time.After(testutils.WaitTimeout(t)) for !latestLocalRegistryCalled || !addLocalRegistryCalled { select { @@ -505,26 +525,30 @@ func TestSyncer_LocalNode(t *testing.T) { }, }, }, - map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + map[p2ptypes.PeerID]kcr.INodeInfoProviderNodeInfo{ workflowDonNodes[0]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[0], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[1]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[1], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[2]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[2], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + EncryptionPublicKey: randomWord(), }, workflowDonNodes[3]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[3], + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + EncryptionPublicKey: randomWord(), }, }, map[string]registrysyncer.Capability{}, diff --git a/core/services/relay/dummy/config_digester.go b/core/services/relay/dummy/config_digester.go index a74e007b0ba..745402135f0 100644 --- a/core/services/relay/dummy/config_digester.go +++ b/core/services/relay/dummy/config_digester.go @@ -1,6 +1,8 @@ package dummy import ( + "context" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ) @@ -16,11 +18,11 @@ func NewOffchainConfigDigester(cd ocrtypes.ConfigDigest) (ocrtypes.OffchainConfi // Compute ConfigDigest for the given ContractConfig. The first two bytes of the // ConfigDigest must be the big-endian encoding of ConfigDigestPrefix! -func (cd *configDigester) ConfigDigest(ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { +func (cd *configDigester) ConfigDigest(context.Context, ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { return cd.configDigest, nil } // This should return the same constant value on every invocation -func (cd *configDigester) ConfigDigestPrefix() (ocrtypes.ConfigDigestPrefix, error) { +func (cd *configDigester) ConfigDigestPrefix(ctx context.Context) (ocrtypes.ConfigDigestPrefix, error) { return ocrtypes.ConfigDigestPrefixFromConfigDigest(cd.configDigest), nil } diff --git a/core/services/relay/dummy/config_provider.go b/core/services/relay/dummy/config_provider.go index 10662ee296d..db36acba830 100644 --- a/core/services/relay/dummy/config_provider.go +++ b/core/services/relay/dummy/config_provider.go @@ -63,7 +63,7 @@ type configProvider struct { } func NewConfigProvider(lggr logger.Logger, cfg RelayConfig) (types.ConfigProvider, error) { - cp := &configProvider{lggr: lggr.Named("DummyConfigProvider")} + cp := &configProvider{lggr: lggr.Named("DummyConfigProvider").Named(cfg.ConfigTracker.ConfigDigest.String())} { contractConfig, err := cfg.ConfigTracker.ToContractConfig() diff --git a/core/services/relay/dummy/config_tracker.go b/core/services/relay/dummy/config_tracker.go index 0ae188361fa..ecd08196e58 100644 --- a/core/services/relay/dummy/config_tracker.go +++ b/core/services/relay/dummy/config_tracker.go @@ -21,7 +21,7 @@ func NewContractConfigTracker(lggr logger.Logger, cfg ConfigTrackerCfg) (ocrtype if err != nil { return nil, err } - return &configTracker{lggr.Named("DummyConfigProvider"), contractConfig, cfg.ChangedInBlock, cfg.BlockHeight}, nil + return &configTracker{lggr.Named("DummyConfigTracker"), contractConfig, cfg.ChangedInBlock, cfg.BlockHeight}, nil } // Notify may optionally emit notification events when the contract's diff --git a/core/services/relay/dummy/llo_provider.go b/core/services/relay/dummy/llo_provider.go index 4aeb21bed8a..1e4c4952577 100644 --- a/core/services/relay/dummy/llo_provider.go +++ b/core/services/relay/dummy/llo_provider.go @@ -11,16 +11,21 @@ import ( relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/llo" ) var _ commontypes.LLOProvider = (*lloProvider)(nil) +type Transmitter interface { + services.Service + llotypes.Transmitter +} + type lloProvider struct { cp commontypes.ConfigProvider - transmitter llo.Transmitter + transmitter Transmitter logger logger.Logger channelDefinitionCache llotypes.ChannelDefinitionCache + shouldRetireCache llotypes.ShouldRetireCache ms services.MultiStart } @@ -28,14 +33,16 @@ type lloProvider struct { func NewLLOProvider( lggr logger.Logger, cp commontypes.ConfigProvider, - transmitter llo.Transmitter, + transmitter Transmitter, channelDefinitionCache llotypes.ChannelDefinitionCache, + shouldRetireCache llotypes.ShouldRetireCache, ) relaytypes.LLOProvider { return &lloProvider{ cp, transmitter, lggr.Named("LLOProvider"), channelDefinitionCache, + shouldRetireCache, services.MultiStart{}, } } @@ -65,18 +72,14 @@ func (p *lloProvider) HealthReport() map[string]error { return report } -func (p *lloProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker { - return p.cp.ContractConfigTracker() +func (p *lloProvider) ContractConfigTrackers() (cps []ocrtypes.ContractConfigTracker) { + return []ocrtypes.ContractConfigTracker{p.cp.ContractConfigTracker()} } func (p *lloProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { return p.cp.OffchainConfigDigester() } -func (p *lloProvider) OnchainConfigCodec() llo.OnchainConfigCodec { - return &llo.JSONOnchainConfigCodec{} -} - func (p *lloProvider) ContractTransmitter() llotypes.Transmitter { return p.transmitter } @@ -84,3 +87,7 @@ func (p *lloProvider) ContractTransmitter() llotypes.Transmitter { func (p *lloProvider) ChannelDefinitionCache() llotypes.ChannelDefinitionCache { return p.channelDefinitionCache } + +func (p *lloProvider) ShouldRetireCache() llotypes.ShouldRetireCache { + return p.shouldRetireCache +} diff --git a/core/services/relay/dummy/relayer.go b/core/services/relay/dummy/relayer.go index cf3aa732c47..3275272b46f 100644 --- a/core/services/relay/dummy/relayer.go +++ b/core/services/relay/dummy/relayer.go @@ -62,7 +62,11 @@ func (r *relayer) NewLLOProvider(ctx context.Context, rargs types.RelayArgs, par if err != nil { return nil, err } - return NewLLOProvider(r.lggr, cp, transmitter, cdc), nil + src := llo.NewNeverShouldRetireCache() + return NewLLOProvider(r.lggr, cp, transmitter, cdc, src), nil +} +func (r *relayer) LatestHead(_ context.Context) (types.Head, error) { + return types.Head{}, nil } func (r *relayer) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { return types.ChainStatus{}, nil diff --git a/core/services/relay/evm/binding.go b/core/services/relay/evm/binding.go deleted file mode 100644 index 412e33c6094..00000000000 --- a/core/services/relay/evm/binding.go +++ /dev/null @@ -1,18 +0,0 @@ -package evm - -import ( - "context" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" -) - -type readBinding interface { - Bind(ctx context.Context, binding commontypes.BoundContract) error - SetCodec(codec commontypes.RemoteCodec) - Register(ctx context.Context) error - Unregister(ctx context.Context) error - GetLatestValue(ctx context.Context, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error - QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) -} diff --git a/core/services/relay/evm/bindings.go b/core/services/relay/evm/bindings.go deleted file mode 100644 index 4d4760db52c..00000000000 --- a/core/services/relay/evm/bindings.go +++ /dev/null @@ -1,120 +0,0 @@ -package evm - -import ( - "context" - "fmt" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" -) - -// bindings manage all contract bindings, key is contract name. - -type bindings struct { - contractBindings map[string]*contractBinding - BatchCaller -} - -func (b bindings) GetReadBinding(contractName, readName string) (readBinding, error) { - // GetReadBindings should only be called after Chain Reader init. - cb, cbExists := b.contractBindings[contractName] - if !cbExists { - return nil, fmt.Errorf("%w: no contract named %s", commontypes.ErrInvalidType, contractName) - } - - rb, rbExists := cb.readBindings[readName] - if !rbExists { - return nil, fmt.Errorf("%w: no readName named %s in contract %s", commontypes.ErrInvalidType, readName, contractName) - } - return rb, nil -} - -// AddReadBinding adds read bindings. Calling this outside of Chain Reader init is not thread safe. -func (b bindings) AddReadBinding(contractName, readName string, rb readBinding) { - cb, cbExists := b.contractBindings[contractName] - if !cbExists { - cb = &contractBinding{ - name: contractName, - readBindings: make(map[string]readBinding), - } - b.contractBindings[contractName] = cb - } - cb.readBindings[readName] = rb -} - -// Bind binds contract addresses to contract bindings and read bindings. -// Bind also registers the common contract polling filter and eventBindings polling filters. -func (b bindings) Bind(ctx context.Context, lp logpoller.LogPoller, boundContracts []commontypes.BoundContract) error { - for _, bc := range boundContracts { - cb, cbExists := b.contractBindings[bc.Name] - if !cbExists { - return fmt.Errorf("%w: no contract named %s", commontypes.ErrInvalidConfig, bc.Name) - } - - if err := cb.Bind(ctx, lp, bc); err != nil { - return err - } - - for _, rb := range cb.readBindings { - if err := rb.Bind(ctx, bc); err != nil { - return err - } - } - } - return nil -} - -func (b bindings) BatchGetLatestValues(ctx context.Context, request commontypes.BatchGetLatestValuesRequest) (commontypes.BatchGetLatestValuesResult, error) { - var batchCall BatchCall - toChainAgnosticMethodName := make(map[string]string) - for contractName, contractBatch := range request { - cb := b.contractBindings[contractName] - for i := range contractBatch { - req := contractBatch[i] - switch rb := cb.readBindings[req.ReadName].(type) { - case *methodBinding: - toChainAgnosticMethodName[rb.method] = req.ReadName - batchCall = append(batchCall, Call{ - ContractAddress: rb.address, - ContractName: cb.name, - MethodName: rb.method, - Params: req.Params, - ReturnVal: req.ReturnVal, - }) - // results here will have chain specific method names. - case *eventBinding: - // TODO Use FilteredLogs to batch? This isn't a priority right now, but should get implemented at some point. - return nil, fmt.Errorf("%w: events are not yet supported in batch get latest values", commontypes.ErrInvalidType) - default: - return nil, fmt.Errorf("%w: missing read binding type for contract: %s read: %s", commontypes.ErrInvalidType, contractName, req.ReadName) - } - } - } - - results, err := b.BatchCall(ctx, 0, batchCall) - if err != nil { - return nil, err - } - - // reconstruct results from batchCall and filteredLogs into common type while maintaining order from request. - batchGetLatestValuesResults := make(commontypes.BatchGetLatestValuesResult) - for contractName, contractResult := range results { - batchGetLatestValuesResults[contractName] = commontypes.ContractBatchResults{} - for _, methodResult := range contractResult { - brr := commontypes.BatchReadResult{ReadName: toChainAgnosticMethodName[methodResult.MethodName]} - brr.SetResult(methodResult.ReturnValue, methodResult.Err) - batchGetLatestValuesResults[contractName] = append(batchGetLatestValuesResults[contractName], brr) - } - } - - return batchGetLatestValuesResults, err -} - -func (b bindings) ForEach(ctx context.Context, fn func(context.Context, *contractBinding) error) error { - for _, cb := range b.contractBindings { - if err := fn(ctx, cb); err != nil { - return err - } - } - return nil -} diff --git a/core/services/relay/evm/cap_encoder.go b/core/services/relay/evm/cap_encoder.go index 790114e4c03..2a6f288a5de 100644 --- a/core/services/relay/evm/cap_encoder.go +++ b/core/services/relay/evm/cap_encoder.go @@ -10,7 +10,9 @@ import ( consensustypes "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/values" + abiutil "github.com/smartcontractkit/chainlink/v2/core/chains/evm/abi" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -47,7 +49,7 @@ func NewEVMEncoder(config *values.Map) (consensustypes.Encoder, error) { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ encoderName: {TypeABI: string(jsonSelector)}, }} - c, err := NewCodec(codecConfig) + c, err := codec.NewCodec(codecConfig) if err != nil { return nil, err } diff --git a/core/services/relay/evm/capabilities/log_event_trigger_test.go b/core/services/relay/evm/capabilities/log_event_trigger_test.go new file mode 100644 index 00000000000..e196ae5bf80 --- /dev/null +++ b/core/services/relay/evm/capabilities/log_event_trigger_test.go @@ -0,0 +1,157 @@ +package logevent_test + +import ( + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "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/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" +) + +// Test for Log Event Trigger Capability happy path for EVM +func TestLogEventTriggerEVMHappyPath(t *testing.T) { + t.Parallel() + th := testutils.NewContractReaderTH(t) + + logEventConfig := logevent.Config{ + ChainID: th.BackendTH.ChainID.String(), + Network: "evm", + LookbackBlocks: 1000, + PollPeriod: 1000, + } + + // Create a new contract reader to return from mock relayer + ctx := coretestutils.Context(t) + + // Fetch latest head from simulated backend to return from mock relayer + height, err := th.BackendTH.EVMClient.LatestBlockHeight(ctx) + require.NoError(t, err) + block, err := th.BackendTH.EVMClient.BlockByNumber(ctx, height) + require.NoError(t, err) + + // Mock relayer to return a New ContractReader instead of gRPC client of a ContractReader + relayer := commonmocks.NewRelayer(t) + relayer.On("NewContractReader", mock.Anything, th.LogEmitterContractReaderCfg).Return(th.LogEmitterContractReader, nil).Once() + relayer.On("LatestHead", mock.Anything).Return(commontypes.Head{ + Height: height.String(), + Hash: block.Hash().Bytes(), + Timestamp: block.Time(), + }, nil).Once() + + // Create Log Event Trigger Service and register trigger + logEventTriggerService, err := logevent.NewTriggerService(ctx, + th.BackendTH.Lggr, + relayer, + logEventConfig) + require.NoError(t, err) + + // Start the service + servicetest.Run(t, logEventTriggerService) + + log1Ch, err := logEventTriggerService.RegisterTrigger(ctx, th.LogEmitterRegRequest) + require.NoError(t, err) + + emitLogTxnAndWaitForLog(t, th, log1Ch, []*big.Int{big.NewInt(10)}) +} + +// Test if Log Event Trigger Capability is able to receive only new logs +// by using cursor and does not receive duplicate logs +func TestLogEventTriggerCursorNewLogs(t *testing.T) { + t.Parallel() + th := testutils.NewContractReaderTH(t) + + logEventConfig := logevent.Config{ + ChainID: th.BackendTH.ChainID.String(), + Network: "evm", + LookbackBlocks: 1000, + PollPeriod: 1000, + } + + // Create a new contract reader to return from mock relayer + ctx := coretestutils.Context(t) + + // Fetch latest head from simulated backend to return from mock relayer + height, err := th.BackendTH.EVMClient.LatestBlockHeight(ctx) + require.NoError(t, err) + block, err := th.BackendTH.EVMClient.BlockByNumber(ctx, height) + require.NoError(t, err) + + // Mock relayer to return a New ContractReader instead of gRPC client of a ContractReader + relayer := commonmocks.NewRelayer(t) + relayer.On("NewContractReader", mock.Anything, th.LogEmitterContractReaderCfg).Return(th.LogEmitterContractReader, nil).Once() + relayer.On("LatestHead", mock.Anything).Return(commontypes.Head{ + Height: height.String(), + Hash: block.Hash().Bytes(), + Timestamp: block.Time(), + }, nil).Once() + + // Create Log Event Trigger Service and register trigger + logEventTriggerService, err := logevent.NewTriggerService(ctx, + th.BackendTH.Lggr, + relayer, + logEventConfig) + require.NoError(t, err) + + // Start the service + servicetest.Run(t, logEventTriggerService) + + log1Ch, err := logEventTriggerService.RegisterTrigger(ctx, th.LogEmitterRegRequest) + require.NoError(t, err) + + emitLogTxnAndWaitForLog(t, th, log1Ch, []*big.Int{big.NewInt(10)}) + + // This confirms that the cursor being tracked by log event trigger capability + // works correctly and does not send old logs again as duplicates to the + // callback channel log1Ch + emitLogTxnAndWaitForLog(t, th, log1Ch, []*big.Int{big.NewInt(11), big.NewInt(12)}) +} + +// Send a transaction to EmitLog contract to emit Log1 events with given +// input parameters and wait for those logs to be received from relayer +// and ContractReader's QueryKey APIs used by Log Event Trigger +func emitLogTxnAndWaitForLog(t *testing.T, + th *testutils.ContractReaderTH, + log1Ch <-chan capabilities.TriggerResponse, + expectedLogVals []*big.Int) { + done := make(chan struct{}) + var err error + go func() { + defer close(done) + _, err = + th.LogEmitterContract.EmitLog1(th.BackendTH.ContractsOwner, expectedLogVals) + assert.NoError(t, err) + th.BackendTH.Backend.Commit() + th.BackendTH.Backend.Commit() + th.BackendTH.Backend.Commit() + }() + + for _, expectedLogVal := range expectedLogVals { + // Wait for logs with a timeout + _, output, err := testutils.WaitForLog(th.BackendTH.Lggr, log1Ch, 15*time.Second) + require.NoError(t, err) + th.BackendTH.Lggr.Infow("EmitLog", "output", output) + + // Verify if valid cursor is returned + cursor, err := testutils.GetStrVal(output, "Cursor") + require.NoError(t, err) + require.True(t, len(cursor) > 60) + + // Verify if Arg0 is correct + actualLogVal, err := testutils.GetBigIntValL2(output, "Data", "Arg0") + require.NoError(t, err) + + require.Equal(t, expectedLogVal.Int64(), actualLogVal.Int64()) + } + + <-done +} diff --git a/core/services/relay/evm/capabilities/testutils/backend.go b/core/services/relay/evm/capabilities/testutils/backend.go new file mode 100644 index 00000000000..ef5761b3e4c --- /dev/null +++ b/core/services/relay/evm/capabilities/testutils/backend.go @@ -0,0 +1,120 @@ +package testutils + +import ( + "context" + "encoding/json" + "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/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + 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" + "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/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +// Test harness with EVM backend and chainlink core services like +// Log Poller and Head Tracker +type EVMBackendTH struct { + // Backend details + Lggr logger.Logger + ChainID *big.Int + Backend *backends.SimulatedBackend + EVMClient evmclient.Client + + ContractsOwner *bind.TransactOpts + ContractsOwnerKey ethkey.KeyV2 + + HeadTracker logpoller.HeadTracker + LogPoller logpoller.LogPoller +} + +// Test harness to create a simulated backend for testing a LOOPCapability +func NewEVMBackendTH(t *testing.T) *EVMBackendTH { + lggr := logger.TestLogger(t) + + ownerKey := cltest.MustGenerateRandomKey(t) + contractsOwner, err := bind.NewKeyedTransactorWithChainID(ownerKey.ToEcdsaPrivKey(), testutils.SimulatedChainID) + require.NoError(t, err) + + // Setup simulated go-ethereum EVM backend + genesisData := core.GenesisAlloc{ + contractsOwner.From: {Balance: assets.Ether(100000).ToInt()}, + } + chainID := testutils.SimulatedChainID + gasLimit := uint32(ethconfig.Defaults.Miner.GasCeil) //nolint:gosec + backend := cltest.NewSimulatedBackend(t, genesisData, gasLimit) + blockTime := time.UnixMilli(int64(backend.Blockchain().CurrentHeader().Time)) //nolint:gosec + err = backend.AdjustTime(time.Since(blockTime) - 24*time.Hour) + require.NoError(t, err) + backend.Commit() + + // Setup backend client + client := evmclient.NewSimulatedBackendClient(t, backend, chainID) + + th := &EVMBackendTH{ + Lggr: lggr, + ChainID: chainID, + Backend: backend, + EVMClient: client, + + ContractsOwner: contractsOwner, + ContractsOwnerKey: ownerKey, + } + th.HeadTracker, th.LogPoller = th.SetupCoreServices(t) + + return th +} + +// Setup core services like log poller and head tracker for the simulated backend +func (th *EVMBackendTH) SetupCoreServices(t *testing.T) (logpoller.HeadTracker, logpoller.LogPoller) { + db := pgtest.NewSqlxDB(t) + const finalityDepth = 2 + ht := headtracker.NewSimulatedHeadTracker(th.EVMClient, false, finalityDepth) + lp := logpoller.NewLogPoller( + logpoller.NewORM(testutils.SimulatedChainID, db, th.Lggr), + th.EVMClient, + th.Lggr, + ht, + logpoller.Opts{ + PollPeriod: 100 * time.Millisecond, + FinalityDepth: finalityDepth, + BackfillBatchSize: 3, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 1000, + }, + ) + require.NoError(t, ht.Start(testutils.Context(t))) + require.NoError(t, lp.Start(testutils.Context(t))) + t.Cleanup(func() { ht.Close() }) + t.Cleanup(func() { lp.Close() }) + return ht, lp +} + +func (th *EVMBackendTH) NewContractReader(ctx context.Context, t *testing.T, cfg []byte) (types.ContractReader, error) { + crCfg := &evmrelaytypes.ChainReaderConfig{} + if err := json.Unmarshal(cfg, crCfg); err != nil { + return nil, err + } + + svc, err := evm.NewChainReaderService(ctx, th.Lggr, th.LogPoller, th.HeadTracker, th.EVMClient, *crCfg) + if err != nil { + return nil, err + } + + return svc, svc.Start(ctx) +} diff --git a/core/services/relay/evm/capabilities/testutils/chain_reader.go b/core/services/relay/evm/capabilities/testutils/chain_reader.go new file mode 100644 index 00000000000..57dc21c426d --- /dev/null +++ b/core/services/relay/evm/capabilities/testutils/chain_reader.go @@ -0,0 +1,169 @@ +package testutils + +import ( + "encoding/json" + "fmt" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + commoncaps "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + 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" + 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" +) + +// Test harness with EVM backend and chainlink core services like +// Log Poller and Head Tracker +type ContractReaderTH struct { + BackendTH *EVMBackendTH + + LogEmitterAddress *common.Address + LogEmitterContract *log_emitter.LogEmitter + LogEmitterContractReader commontypes.ContractReader + LogEmitterRegRequest commoncaps.TriggerRegistrationRequest + LogEmitterContractReaderCfg []byte +} + +// Creates a new test harness for Contract Reader tests +func NewContractReaderTH(t *testing.T) *ContractReaderTH { + backendTH := NewEVMBackendTH(t) + + // Deploy a test contract LogEmitter for testing ContractReader + logEmitterAddress, _, _, err := + log_emitter.DeployLogEmitter(backendTH.ContractsOwner, backendTH.Backend) + require.NoError(t, err) + logEmitter, err := log_emitter.NewLogEmitter(logEmitterAddress, backendTH.Backend) + require.NoError(t, err) + + // Create new contract reader + reqConfig := logeventcap.Config{ + ContractName: "LogEmitter", + ContractAddress: logEmitterAddress.Hex(), + ContractEventName: "Log1", + } + contractReaderCfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + reqConfig.ContractName: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{reqConfig.ContractEventName}, + }, + ContractABI: log_emitter.LogEmitterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + reqConfig.ContractEventName: { + ChainSpecificName: reqConfig.ContractEventName, + ReadType: evmtypes.Event, + }, + }, + }, + }, + } + + // Encode contractReaderConfig as JSON and decode it into a map[string]any for + // the capability request config. Log Event Trigger capability takes in a + // []byte as ContractReaderConfig to not depend on evm ChainReaderConfig type + // and be chain agnostic + contractReaderCfgBytes, err := json.Marshal(contractReaderCfg) + require.NoError(t, err) + var contractReaderCfgMap logeventcap.ConfigContractReaderConfig + err = json.Unmarshal(contractReaderCfgBytes, &contractReaderCfgMap) + require.NoError(t, err) + // Encode the config map as JSON to specify in the expected call in mocked object + // The LogEventTrigger Capability receives a config map, encodes it and + // calls NewContractReader with it + contractReaderCfgBytes, err = json.Marshal(contractReaderCfgMap) + require.NoError(t, err) + + reqConfig.ContractReaderConfig = contractReaderCfgMap + + config, err := commonvalues.WrapMap(reqConfig) + require.NoError(t, err) + req := commoncaps.TriggerRegistrationRequest{ + TriggerID: "logeventtrigger_log1", + Config: config, + Metadata: commoncaps.RequestMetadata{ + ReferenceID: "logeventtrigger", + }, + } + + // Create a new contract reader to return from mock relayer + ctx := coretestutils.Context(t) + contractReader, err := backendTH.NewContractReader(ctx, t, contractReaderCfgBytes) + require.NoError(t, err) + + return &ContractReaderTH{ + BackendTH: backendTH, + + LogEmitterAddress: &logEmitterAddress, + LogEmitterContract: logEmitter, + LogEmitterContractReader: contractReader, + LogEmitterRegRequest: req, + LogEmitterContractReaderCfg: contractReaderCfgBytes, + } +} + +// Wait for a specific log to be emitted to a response channel by ChainReader +func WaitForLog(lggr logger.Logger, logCh <-chan commoncaps.TriggerResponse, timeout time.Duration) ( + *commoncaps.TriggerResponse, map[string]any, error) { + select { + case <-time.After(timeout): + return nil, nil, fmt.Errorf("timeout waiting for Log1 event from ContractReader") + case log := <-logCh: + lggr.Infow("Received log from ContractReader", "event", log.Event.ID) + if log.Err != nil { + return nil, nil, fmt.Errorf("error listening for Log1 event from ContractReader: %v", log.Err) + } + v := make(map[string]any) + err := log.Event.Outputs.UnwrapTo(&v) + if err != nil { + return nil, nil, fmt.Errorf("error unwrapping log to map: (log %v) %v", log.Event.Outputs, log.Err) + } + return &log, v, nil + } +} + +// Get the string value of a key from a generic map[string]any +func GetStrVal(m map[string]any, k string) (string, error) { + v, ok := m[k] + if !ok { + return "", fmt.Errorf("key %s not found", k) + } + vstr, ok := v.(string) + if !ok { + return "", fmt.Errorf("key %s not a string (%T)", k, v) + } + return vstr, nil +} + +// Get int value of a key from a generic map[string]any +func GetBigIntVal(m map[string]any, k string) (*big.Int, error) { + v, ok := m[k] + if !ok { + return nil, fmt.Errorf("key %s not found", k) + } + val, ok := v.(*big.Int) + if !ok { + return nil, fmt.Errorf("key %s not a *big.Int (%T)", k, v) + } + return val, nil +} + +// Get the int value from a map[string]map[string]any +func GetBigIntValL2(m map[string]any, level1Key string, level2Key string) (*big.Int, error) { + v, ok := m[level1Key] + if !ok { + return nil, fmt.Errorf("key %s not found", level1Key) + } + level2Map, ok := v.(map[string]any) + if !ok { + return nil, fmt.Errorf("key %s not a map[string]any (%T)", level1Key, v) + } + return GetBigIntVal(level2Map, level2Key) +} diff --git a/core/services/relay/evm/ccip.go b/core/services/relay/evm/ccip.go index 34a732e1454..3eefb7bec7b 100644 --- a/core/services/relay/evm/ccip.go +++ b/core/services/relay/evm/ccip.go @@ -6,18 +6,16 @@ import ( "math/big" "time" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "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/logger" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "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/prices" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" ) var _ cciptypes.CommitStoreReader = (*IncompleteSourceCommitStoreReader)(nil) diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go new file mode 100644 index 00000000000..33a862c6ce9 --- /dev/null +++ b/core/services/relay/evm/chain_components_test.go @@ -0,0 +1,368 @@ +package evm_test + +import ( + "context" + "crypto/ecdsa" + "fmt" + "math" + "math/big" + "os" + "strconv" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" + "github.com/jmoiron/sqlx" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" + clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + "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/logpoller" + evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "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" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + keytypes "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint common practice to import test mods with . +) + +const commonGasLimitOnEvms = uint64(4712388) + +func TestContractReaderEventsInitValidation(t *testing.T) { + tests := []struct { + name string + chainContractReaders map[string]types.ChainContractReader + expectedError error + }{ + { + name: "Invalid ABI", + chainContractReaders: map[string]types.ChainContractReader{ + "InvalidContract": { + ContractABI: "{invalid json}", + Configs: map[string]*types.ChainReaderDefinition{}, + }, + }, + expectedError: fmt.Errorf("failed to parse abi"), + }, + { + name: "Conflicting polling filter definitions", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithConflict": { + ContractABI: "[]", + Configs: map[string]*types.ChainReaderDefinition{ + "EventWithConflict": { + ChainSpecificName: "EventName", + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + PollingFilter: &types.PollingFilter{}, + }, + }, + }, + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{"EventWithConflict"}, + }, + }, + }, + expectedError: fmt.Errorf( + "%w: conflicting chain reader polling filter definitions for contract: %s event: %s, can't have polling filter defined both on contract and event level", + clcommontypes.ErrInvalidConfig, "ContractWithConflict", "EventWithConflict"), + }, + { + name: "No polling filter defined", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithNoFilter": { + ContractABI: "[]", + Configs: map[string]*types.ChainReaderDefinition{ + "EventWithNoFilter": { + ChainSpecificName: "EventName", + ReadType: types.Event, + }, + }, + }, + }, + expectedError: fmt.Errorf( + "%w: chain reader has no polling filter defined for contract: %s, event: %s", + clcommontypes.ErrInvalidConfig, "ContractWithNoFilter", "EventWithNoFilter"), + }, + { + name: "Invalid chain reader definition read type", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithInvalidReadType": { + ContractABI: "[]", + Configs: map[string]*types.ChainReaderDefinition{ + "InvalidReadType": { + ChainSpecificName: "InvalidName", + ReadType: types.ReadType(2), + }, + }, + }, + }, + expectedError: fmt.Errorf( + "%w: invalid chain reader definition read type", + clcommontypes.ErrInvalidConfig), + }, + { + name: "Event not present in ABI", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithConflict": { + ContractABI: "[{\"anonymous\":false,\"inputs\":[],\"name\":\"WrongEvent\",\"type\":\"event\"}]", + Configs: map[string]*types.ChainReaderDefinition{ + "SomeEvent": { + ChainSpecificName: "EventName", + ReadType: types.Event, + }, + }, + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{"SomeEvent"}, + }, + }, + }, + expectedError: fmt.Errorf( + "%w: event %q doesn't exist", + clcommontypes.ErrInvalidConfig, "EventName"), + }, + { + name: "Event has a unnecessary data word index override", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithConflict": { + ContractABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"someDW\",\"type\":\"address\"}],\"name\":\"EventName\",\"type\":\"event\"}]", + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{"SomeEvent"}, + }, + Configs: map[string]*types.ChainReaderDefinition{ + "SomeEvent": { + ChainSpecificName: "EventName", + ReadType: types.Event, + + EventDefinitions: &types.EventDefinitions{ + GenericDataWordDetails: map[string]types.DataWordDetail{ + "DW": { + Name: "someDW", + Index: ptr(0), + }, + }, + }, + }, + }, + }, + }, + expectedError: fmt.Errorf("failed to init dw querying for event: %q, err: data word: %q at index: %d details, were calculated automatically and shouldn't be manully overridden by cfg", + "SomeEvent", "DW", 0), + }, + { + name: "Event has a bad type defined in data word detail override config", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithConflict": { + ContractABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"someDW\",\"type\":\"string\"}],\"name\":\"EventName\",\"type\":\"event\"}]", + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{"SomeEvent"}, + }, + Configs: map[string]*types.ChainReaderDefinition{ + "SomeEvent": { + ChainSpecificName: "EventName", + ReadType: types.Event, + + EventDefinitions: &types.EventDefinitions{ + GenericDataWordDetails: map[string]types.DataWordDetail{ + "DW": { + Name: "someDW", + Index: ptr(0), + Type: "abcdefg", + }, + }, + }, + }, + }, + }, + }, + expectedError: fmt.Errorf("failed to init dw querying for event: %q, err: bad abi type: \"abcdefg\" provided for data word: %q at index: %d in config", + "SomeEvent", "DW", 0), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := evm.NewChainReaderService(testutils.Context(t), logger.NullLogger, nil, nil, nil, types.ChainReaderConfig{Contracts: tt.chainContractReaders}) + require.Error(t, err) + if err != nil { + assert.Contains(t, err.Error(), tt.expectedError.Error()) + } + }) + } +} + +func TestChainComponents(t *testing.T) { + t.Parallel() + it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} + + it.Helper.Init(t) + + // add new subtests here so that it can be run on real chains too + RunChainComponentsEvmTests(t, it) + RunChainComponentsInLoopEvmTests[*testing.T](t, commontestutils.WrapContractReaderTesterForLoop(it)) +} + +type helper struct { + sim *backends.SimulatedBackend + accounts []*bind.TransactOpts + deployerKey *ecdsa.PrivateKey + senderKey *ecdsa.PrivateKey + txm evmtxmgr.TxManager + client client.Client + db *sqlx.DB +} + +func (h *helper) Init(t *testing.T) { + h.SetupKeys(t) + + h.accounts = h.Accounts(t) + + h.db = pgtest.NewSqlxDB(t) + + h.Backend() + h.client = h.Client(t) + + h.txm = h.TXM(t, h.client) + h.Commit() +} + +func (h *helper) SetupKeys(t *testing.T) { + deployerPkey, err := crypto.GenerateKey() + require.NoError(t, err) + h.deployerKey = deployerPkey + + senderPkey, err := crypto.GenerateKey() + require.NoError(t, err) + h.senderKey = senderPkey +} + +func (h *helper) Accounts(t *testing.T) []*bind.TransactOpts { + if h.accounts != nil { + return h.accounts + } + deployer, err := bind.NewKeyedTransactorWithChainID(h.deployerKey, big.NewInt(1337)) + require.NoError(t, err) + + sender, err := bind.NewKeyedTransactorWithChainID(h.senderKey, big.NewInt(1337)) + require.NoError(t, err) + + return []*bind.TransactOpts{deployer, sender} +} + +func (h *helper) MustGenerateRandomKey(t *testing.T) ethkey.KeyV2 { + return cltest.MustGenerateRandomKey(t) +} + +func (h *helper) GasPriceBufferPercent() int64 { + return 0 +} + +func (h *helper) Backend() bind.ContractBackend { + if h.sim == nil { + h.sim = backends.NewSimulatedBackend( + core.GenesisAlloc{h.accounts[0].From: {Balance: big.NewInt(math.MaxInt64)}, h.accounts[1].From: {Balance: big.NewInt(math.MaxInt64)}}, commonGasLimitOnEvms*5000) + cltest.Mine(h.sim, 1*time.Second) + } + + return h.sim +} + +func (h *helper) Commit() { + h.sim.Commit() +} + +func (h *helper) Client(t *testing.T) client.Client { + if h.client != nil { + return h.client + } + return client.NewSimulatedBackendClient(t, h.sim, big.NewInt(1337)) +} + +func (h *helper) ChainID() *big.Int { + return testutils.SimulatedChainID +} + +func (h *helper) NewSqlxDB(t *testing.T) *sqlx.DB { + return pgtest.NewSqlxDB(t) +} + +func (h *helper) Context(t *testing.T) context.Context { + return testutils.Context(t) +} + +func (h *helper) ChainReaderEVMClient(ctx context.Context, t *testing.T, ht logpoller.HeadTracker, conf types.ChainReaderConfig) client.Client { + // wrap the client so that we can mock historical contract state + cwh := &evm.ClientWithContractHistory{Client: h.Client(t), HT: ht} + require.NoError(t, cwh.Init(ctx, conf)) + return cwh +} + +func (h *helper) WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter { + cwhw := evm.NewChainWriterHistoricalWrapper(cw, client.(*evm.ClientWithContractHistory)) + return cwhw +} + +func (h *helper) MaxWaitTimeForEvents() time.Duration { + // From trial and error, when running on CI, sometimes the boxes get slow + maxWaitTime := time.Second * 30 + maxWaitTimeStr, ok := os.LookupEnv("MAX_WAIT_TIME_FOR_EVENTS_S") + if ok { + waitS, err := strconv.ParseInt(maxWaitTimeStr, 10, 64) + if err != nil { + fmt.Printf("Error parsing MAX_WAIT_TIME_FOR_EVENTS_S: %v, defaulting to %v\n", err, maxWaitTime) + } + maxWaitTime = time.Second * time.Duration(waitS) + } + return maxWaitTime +} + +func (h *helper) TXM(t *testing.T, client client.Client) evmtxmgr.TxManager { + if h.txm != nil { + return h.txm + } + db := h.db + + clconfig := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Database.Listener.FallbackPollInterval = commonconfig.MustNewDuration(100 * time.Millisecond) + c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) + }) + + clconfig.EVMConfigs()[0].GasEstimator.PriceMax = assets.GWei(100) + + app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, clconfig, h.sim, db, client) + err := app.Start(h.Context(t)) + require.NoError(t, err) + + keyStore := app.KeyStore.Eth() + + keyStore.XXXTestingOnlyAdd(h.Context(t), keytypes.FromPrivateKey(h.deployerKey)) + require.NoError(t, keyStore.Add(h.Context(t), h.accounts[0].From, h.ChainID())) + require.NoError(t, keyStore.Enable(h.Context(t), h.accounts[0].From, h.ChainID())) + + keyStore.XXXTestingOnlyAdd(h.Context(t), keytypes.FromPrivateKey(h.senderKey)) + require.NoError(t, keyStore.Add(h.Context(t), h.accounts[1].From, h.ChainID())) + require.NoError(t, keyStore.Enable(h.Context(t), h.accounts[1].From, h.ChainID())) + + chain, err := app.GetRelayers().LegacyEVMChains().Get((h.ChainID()).String()) + require.NoError(t, err) + + h.txm = chain.TxManager() + return h.txm +} + +func ptr[T any](v T) *T { return &v } diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index 205fcbbcf07..c734ade1104 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -4,25 +4,27 @@ import ( "context" "errors" "fmt" - "reflect" + "maps" "slices" "strings" - "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-common/pkg/codec" + commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/logger" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - + "github.com/smartcontractkit/chainlink-common/pkg/values" evmclient "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" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -32,13 +34,14 @@ type ChainReaderService interface { } type chainReader struct { - lggr logger.Logger - ht logpoller.HeadTracker - lp logpoller.LogPoller - client evmclient.Client - parsed *ParsedTypes - bindings - codec commontypes.RemoteCodec + commontypes.UnimplementedContractReader + lggr logger.Logger + ht logpoller.HeadTracker + lp logpoller.LogPoller + client evmclient.Client + parsed *codec.ParsedTypes + bindings *read.BindingsRegistry + codec commontypes.RemoteCodec commonservices.StateMachine } @@ -47,14 +50,14 @@ var _ commontypes.ContractTypeProvider = &chainReader{} // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error // Note that the ChainReaderService returned does not support anonymous events. -func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller.LogPoller, ht logpoller.HeadTracker, client evmclient.Client, config types.ChainReaderConfig) (ChainReaderService, error) { +func NewChainReaderService(_ context.Context, lggr logger.Logger, lp logpoller.LogPoller, ht logpoller.HeadTracker, client evmclient.Client, config types.ChainReaderConfig) (ChainReaderService, error) { cr := &chainReader{ - lggr: lggr.Named("ChainReader"), + lggr: logger.Named(lggr, "ChainReader"), ht: ht, lp: lp, client: client, - bindings: bindings{contractBindings: make(map[string]*contractBinding)}, - parsed: &ParsedTypes{EncoderDefs: map[string]types.CodecEntry{}, DecoderDefs: map[string]types.CodecEntry{}}, + bindings: read.NewBindingsRegistry(), + parsed: &codec.ParsedTypes{EncoderDefs: map[string]types.CodecEntry{}, DecoderDefs: map[string]types.CodecEntry{}}, } var err error @@ -66,21 +69,16 @@ func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller return nil, err } - cr.bindings.BatchCaller = NewDynamicLimitedBatchCaller( + cr.bindings.SetBatchCaller(read.NewDynamicLimitedBatchCaller( cr.lggr, cr.codec, cr.client, - DefaultRpcBatchSizeLimit, - DefaultRpcBatchBackOffMultiplier, - DefaultMaxParallelRpcCalls, - ) - - err = cr.bindings.ForEach(ctx, func(c context.Context, cb *contractBinding) error { - for _, rb := range cb.readBindings { - rb.SetCodec(cr.codec) - } - return nil - }) + read.DefaultRpcBatchSizeLimit, + read.DefaultRpcBatchBackOffMultiplier, + read.DefaultMaxParallelRpcCalls, + )) + + cr.bindings.SetCodecAll(cr.codec) return cr, err } @@ -94,6 +92,8 @@ func (cr *chainReader) init(chainContractReaders map[string]types.ChainContractR var eventSigsForContractFilter evmtypes.HashArray for typeName, chainReaderDefinition := range chainContractReader.Configs { + injectEVMSpecificCodecModifiers(chainReaderDefinition) + switch chainReaderDefinition.ReadType { case types.Method: err = cr.addMethod(contractName, typeName, contractAbi, *chainReaderDefinition) @@ -129,27 +129,40 @@ func (cr *chainReader) init(chainContractReaders map[string]types.ChainContractR } } - if cr.bindings.contractBindings[contractName] == nil { + if !cr.bindings.HasContractBinding(contractName) { return fmt.Errorf("%w: no read bindings added for contract: %s", commontypes.ErrInvalidConfig, contractName) } - cr.bindings.contractBindings[contractName].pollingFilter = chainContractReader.PollingFilter.ToLPFilter(eventSigsForContractFilter) + + if err = cr.bindings.SetFilter(contractName, chainContractReader.PollingFilter.ToLPFilter(eventSigsForContractFilter)); err != nil { + return err + } } return nil } +// injectEVMSpecificCodecModifiers injects an AddressModifier into Input/OutputModifications of a ChainReaderDefinition. +func injectEVMSpecificCodecModifiers(chainReaderDefinition *types.ChainReaderDefinition) { + for i, modConfig := range chainReaderDefinition.InputModifications { + if addrModifierConfig, ok := modConfig.(*commoncodec.AddressBytesToStringModifierConfig); ok { + addrModifierConfig.Modifier = codec.EVMAddressModifier{} + chainReaderDefinition.InputModifications[i] = addrModifierConfig + } + } + + for i, modConfig := range chainReaderDefinition.OutputModifications { + if addrModifierConfig, ok := modConfig.(*commoncodec.AddressBytesToStringModifierConfig); ok { + addrModifierConfig.Modifier = codec.EVMAddressModifier{} + chainReaderDefinition.OutputModifications[i] = addrModifierConfig + } + } +} + func (cr *chainReader) Name() string { return cr.lggr.Name() } // Start registers polling filters if contracts are already bound. func (cr *chainReader) Start(ctx context.Context) error { return cr.StartOnce("ChainReader", func() error { - return cr.bindings.ForEach(ctx, func(c context.Context, cb *contractBinding) error { - for _, rb := range cb.readBindings { - if err := rb.Register(ctx); err != nil { - return err - } - } - return cb.Register(ctx, cr.lp) - }) + return cr.bindings.RegisterAll(ctx, cr.lp) }) } @@ -158,14 +171,7 @@ func (cr *chainReader) Close() error { return cr.StopOnce("ChainReader", func() error { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - return cr.bindings.ForEach(ctx, func(c context.Context, cb *contractBinding) error { - for _, rb := range cb.readBindings { - if err := rb.Unregister(ctx); err != nil { - return err - } - } - return cb.Unregister(ctx, cr.lp) - }) + return cr.bindings.UnregisterAll(ctx, cr.lp) }) } @@ -175,41 +181,93 @@ func (cr *chainReader) HealthReport() map[string]error { return map[string]error{cr.Name(): nil} } -func (cr *chainReader) GetLatestValue(ctx context.Context, contractName, method string, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error { - b, err := cr.bindings.GetReadBinding(contractName, method) +func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundContract) error { + return cr.bindings.Bind(ctx, cr.lp, bindings) +} + +func (cr *chainReader) Unbind(ctx context.Context, bindings []commontypes.BoundContract) error { + return cr.bindings.Unbind(ctx, cr.lp, bindings) +} + +func (cr *chainReader) GetLatestValue(ctx context.Context, readName string, confidenceLevel primitives.ConfidenceLevel, params any, returnVal any) error { + binding, address, err := cr.bindings.GetReader(readName) if err != nil { return err } - return b.GetLatestValue(ctx, confidenceLevel, params, returnVal) + ptrToValue, isValue := returnVal.(*values.Value) + if !isValue { + return binding.GetLatestValue(ctx, common.HexToAddress(address), confidenceLevel, params, returnVal) + } + + contractType, err := cr.CreateContractType(readName, false) + if err != nil { + return err + } + + if err = cr.GetLatestValue(ctx, readName, confidenceLevel, params, contractType); err != nil { + return err + } + + value, err := values.Wrap(contractType) + if err != nil { + return err + } + + *ptrToValue = value + + return nil } func (cr *chainReader) BatchGetLatestValues(ctx context.Context, request commontypes.BatchGetLatestValuesRequest) (commontypes.BatchGetLatestValuesResult, error) { return cr.bindings.BatchGetLatestValues(ctx, request) } -func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundContract) error { - return cr.bindings.Bind(ctx, cr.lp, bindings) -} +func (cr *chainReader) QueryKey( + ctx context.Context, + contract commontypes.BoundContract, + filter query.KeyFilter, + limitAndSort query.LimitAndSort, + sequenceDataType any, +) ([]commontypes.Sequence, error) { + binding, address, err := cr.bindings.GetReader(contract.ReadIdentifier(filter.Key)) + if err != nil { + return nil, err + } + + _, isValuePtr := sequenceDataType.(*values.Value) + if !isValuePtr { + return binding.QueryKey(ctx, common.HexToAddress(address), filter, limitAndSort, sequenceDataType) + } -func (cr *chainReader) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { - b, err := cr.bindings.GetReadBinding(contractName, filter.Key) + dataTypeFromReadIdentifier, err := cr.CreateContractType(contract.ReadIdentifier(filter.Key), false) if err != nil { return nil, err } - return b.QueryKey(ctx, filter, limitAndSort, sequenceDataType) -} + sequence, err := binding.QueryKey(ctx, common.HexToAddress(address), filter, limitAndSort, dataTypeFromReadIdentifier) + if err != nil { + return nil, err + } -func (cr *chainReader) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { - return cr.codec.CreateType(WrapItemType(contractName, itemType, forEncoding), forEncoding) + sequenceOfValues := make([]commontypes.Sequence, len(sequence)) + for idx, entry := range sequence { + value, err := values.Wrap(entry.Data) + if err != nil { + return nil, err + } + sequenceOfValues[idx] = commontypes.Sequence{ + Cursor: entry.Cursor, + Head: entry.Head, + Data: &value, + } + } + + return sequenceOfValues, nil } -func WrapItemType(contractName, itemType string, isParams bool) string { - if isParams { - return fmt.Sprintf("params.%s.%s", contractName, itemType) - } - return fmt.Sprintf("return.%s.%s", contractName, itemType) +func (cr *chainReader) CreateContractType(readIdentifier string, forEncoding bool) (any, error) { + return cr.codec.CreateType(cr.bindings.ReadTypeIdentifier(readIdentifier, forEncoding), forEncoding) } func (cr *chainReader) addMethod( @@ -227,16 +285,11 @@ func (cr *chainReader) addMethod( return err } - cr.bindings.AddReadBinding(contractName, methodName, &methodBinding{ - lggr: cr.lggr, - contractName: contractName, - method: methodName, - ht: cr.ht, - client: cr.client, - confirmationsMapping: confirmations, - }) + if err = cr.bindings.AddReader(contractName, methodName, read.NewMethodBinding(contractName, methodName, cr.client, cr.ht, confirmations, cr.lggr)); err != nil { + return err + } - if err := cr.addEncoderDef(contractName, methodName, method.Inputs, method.ID, chainReaderDefinition.InputModifications); err != nil { + if err = cr.addEncoderDef(contractName, methodName, method.Inputs, method.ID, chainReaderDefinition.InputModifications); err != nil { return err } @@ -246,121 +299,151 @@ func (cr *chainReader) addMethod( func (cr *chainReader) addEvent(contractName, eventName string, a abi.ABI, chainReaderDefinition types.ChainReaderDefinition) error { event, eventExists := a.Events[chainReaderDefinition.ChainSpecificName] if !eventExists { - return fmt.Errorf("%w: event %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) - } - - var inputFields []string - if chainReaderDefinition.EventDefinitions != nil { - inputFields = chainReaderDefinition.EventDefinitions.InputFields - } - - filterArgs, codecTopicInfo, indexArgNames := setupEventInput(event, inputFields) - if err := verifyEventIndexedInputsUsed(eventName, inputFields, indexArgNames); err != nil { - return err + return fmt.Errorf("%w: event %q doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) } - if err := codecTopicInfo.Init(); err != nil { + indexedAsUnIndexedABITypes, indexedTopicsCodecTypes, eventDWs := getEventTypes(event) + if err := indexedTopicsCodecTypes.Init(); err != nil { return err } // Encoder defs codec won't be used for encoding, but for storing caller filtering params which won't be hashed. - if err := cr.addEncoderDef(contractName, eventName, filterArgs, nil, chainReaderDefinition.InputModifications); err != nil { - return err - } - - inputInfo, inputModifier, err := cr.getEventInput(chainReaderDefinition, contractName, eventName) + err := cr.addEncoderDef(contractName, eventName, indexedAsUnIndexedABITypes, nil, chainReaderDefinition.InputModifications) if err != nil { return err } + codecTypes, codecModifiers := make(map[string]types.CodecEntry), make(map[string]commoncodec.Modifier) + topicTypeID := codec.WrapItemType(contractName, eventName, true) + codecTypes[topicTypeID], codecModifiers[topicTypeID] = cr.getEventItemTypeAndModifier(topicTypeID) + confirmations, err := ConfirmationsFromConfig(chainReaderDefinition.ConfidenceConfirmations) if err != nil { return err } - eb := &eventBinding{ - contractName: contractName, - eventName: eventName, - lp: cr.lp, - hash: event.ID, - inputInfo: inputInfo, - inputModifier: inputModifier, - codecTopicInfo: codecTopicInfo, - topics: make(map[string]topicDetail), - eventDataWords: make(map[string]uint8), - confirmationsMapping: confirmations, - } - + eb := read.NewEventBinding(contractName, eventName, cr.lp, event.ID, indexedTopicsCodecTypes, confirmations) if eventDefinitions := chainReaderDefinition.EventDefinitions; eventDefinitions != nil { if eventDefinitions.PollingFilter != nil { - eb.filterRegisterer = &filterRegisterer{ - pollingFilter: eventDefinitions.PollingFilter.ToLPFilter(evmtypes.HashArray{a.Events[event.Name].ID}), - filterLock: sync.Mutex{}, - } + eb.SetFilter(eventDefinitions.PollingFilter.ToLPFilter(evmtypes.HashArray{a.Events[event.Name].ID})) } - if eventDefinitions.GenericDataWordNames != nil { - eb.eventDataWords = eventDefinitions.GenericDataWordNames + topicsDetails, topicsCodecTypeInfo, topicsModifiers, initQueryingErr := cr.initTopicQuerying(contractName, eventName, event.Inputs, eventDefinitions.GenericTopicNames, chainReaderDefinition.InputModifications) + if initQueryingErr != nil { + return initQueryingErr } + maps.Copy(codecTypes, topicsCodecTypeInfo) + // TODO BCFR-44 reused GetLatestValue params modifiers, probably can be left like this + maps.Copy(codecModifiers, topicsModifiers) + + // TODO BCFR-44 no dw modifier for now + dataWordsDetails, dWSCodecTypeInfo, initDWQueryingErr := cr.initDWQuerying(contractName, eventName, eventDWs, eventDefinitions.GenericDataWordDetails) + if initDWQueryingErr != nil { + return fmt.Errorf("failed to init dw querying for event: %q, err: %w", eventName, initDWQueryingErr) + } + maps.Copy(codecTypes, dWSCodecTypeInfo) - cr.addQueryingReadBindings(contractName, eventDefinitions.GenericTopicNames, event.Inputs, eb) + eb.SetTopicDetails(topicsDetails) + eb.SetDataWordsDetails(dataWordsDetails) } - cr.bindings.AddReadBinding(contractName, eventName, eb) + eb.SetCodecTypesAndModifiers(codecTypes, codecModifiers) + if err = cr.bindings.AddReader(contractName, eventName, eb); err != nil { + return err + } return cr.addDecoderDef(contractName, eventName, event.Inputs, chainReaderDefinition.OutputModifications) } -// addQueryingReadBindings reuses the eventBinding and maps it to topic and dataWord keys used for QueryKey. -func (cr *chainReader) addQueryingReadBindings(contractName string, genericTopicNames map[string]string, eventInputs abi.Arguments, eb *eventBinding) { - // add topic readBindings for QueryKey +// initTopicQuerying registers codec types and modifiers for topics to be used for typing value comparator QueryKey filters. +func (cr *chainReader) initTopicQuerying(contractName, eventName string, eventInputs abi.Arguments, genericTopicNames map[string]string, inputModifications commoncodec.ModifiersConfig) (map[string]read.TopicDetail, map[string]types.CodecEntry, map[string]commoncodec.Modifier, error) { + topicsDetails := make(map[string]read.TopicDetail) + topicsTypes := make(map[string]types.CodecEntry) + topicsModifiers := make(map[string]commoncodec.Modifier) for topicIndex, topic := range eventInputs { genericTopicName, ok := genericTopicNames[topic.Name] if ok { - eb.topics[genericTopicName] = topicDetail{ - Argument: topic, - Index: uint64(topicIndex), + topicsDetails[genericTopicName] = read.TopicDetail{Argument: topic, Index: uint64(topicIndex + 1)} + + topicTypeID := eventName + "." + genericTopicName + if err := cr.addEncoderDef(contractName, topicTypeID, abi.Arguments{{Type: topic.Type}}, nil, inputModifications); err != nil { + return nil, nil, nil, err } - } - cr.bindings.AddReadBinding(contractName, genericTopicName, eb) - } - // add data word readBindings for QueryKey - for genericDataWordName := range eb.eventDataWords { - cr.bindings.AddReadBinding(contractName, genericDataWordName, eb) + topicCodecTypeID := codec.WrapItemType(contractName, topicTypeID, true) + topicsTypes[topicCodecTypeID], topicsModifiers[topicCodecTypeID] = cr.getEventItemTypeAndModifier(topicCodecTypeID) + } } + return topicsDetails, topicsTypes, topicsModifiers, nil } -// getEventInput returns codec entry for expected incoming event params and the modifier to be applied to the params. -func (cr *chainReader) getEventInput(def types.ChainReaderDefinition, contractName, eventName string) ( - types.CodecEntry, codec.Modifier, error) { - inputInfo := cr.parsed.EncoderDefs[WrapItemType(contractName, eventName, true)] - // TODO can this be simplified? Isn't this same as inputInfo.Modifier()? BCI-3909 - inMod, err := def.InputModifications.ToModifier(DecoderHooks...) +// initDWQuerying registers codec types for evm data words to be used for typing value comparator QueryKey filters. +func (cr *chainReader) initDWQuerying(contractName, eventName string, abiDWsDetails map[string]read.DataWordDetail, cfgDWsDetails map[string]types.DataWordDetail) (map[string]read.DataWordDetail, map[string]types.CodecEntry, error) { + dWsDetail, err := cr.constructDWDetails(cfgDWsDetails, abiDWsDetails) if err != nil { return nil, nil, err } - // initialize the modification - if _, err = inMod.RetypeToOffChain(reflect.PointerTo(inputInfo.CheckedType()), ""); err != nil { - return nil, nil, err + dwsCodecTypeInfo := make(map[string]types.CodecEntry) + for genericName := range cfgDWsDetails { + dwDetail, exists := dWsDetail[genericName] + if !exists { + return nil, nil, fmt.Errorf("failed to find data word: %q, it either doesn't exist or can't be searched for", genericName) + } + + dwTypeID := eventName + "." + genericName + if err = cr.addEncoderDef(contractName, dwTypeID, abi.Arguments{abi.Argument{Type: dwDetail.Type}}, nil, nil); err != nil { + return nil, nil, fmt.Errorf("failed to init codec for data word: %q on index: %d, err: %w", genericName, dwDetail.Index, err) + } + + dwCodecTypeID := codec.WrapItemType(contractName, dwTypeID, true) + dwsCodecTypeInfo[dwCodecTypeID] = cr.parsed.EncoderDefs[dwCodecTypeID] } - return inputInfo, inMod, nil + return dWsDetail, dwsCodecTypeInfo, nil } -func verifyEventIndexedInputsUsed(eventName string, inputFields []string, indexArgNames map[string]bool) error { - for _, value := range inputFields { - if !indexArgNames[abi.ToCamelCase(value)] { - return fmt.Errorf("%w: %s is not an indexed argument of event %s", commontypes.ErrInvalidConfig, value, eventName) +// constructDWDetails combines data word details from config and abi. +func (cr *chainReader) constructDWDetails(cfgDWsDetails map[string]types.DataWordDetail, abiDWsDetails map[string]read.DataWordDetail) (map[string]read.DataWordDetail, error) { + dWsDetail := make(map[string]read.DataWordDetail) + for genericName, cfgDWDetail := range cfgDWsDetails { + for eventID, dWDetail := range abiDWsDetails { + // Extract field name in this manner to account for nested fields + fieldName := strings.Join(strings.Split(eventID, ".")[1:], ".") + if fieldName == cfgDWDetail.Name { + dWsDetail[genericName] = dWDetail + break + } } } - return nil + + // if dw detail isn't set, the index can't be programmatically determined, so we get index and type from cfg + for genericName, cfgDWDetail := range cfgDWsDetails { + dwDetail, exists := dWsDetail[genericName] + if exists && cfgDWDetail.Index != nil { + return nil, fmt.Errorf("data word: %q at index: %d details, were calculated automatically and shouldn't be manully overridden by cfg", genericName, dwDetail.Index) + } + + if cfgDWDetail.Index != nil { + abiTyp, err := abi.NewType(cfgDWDetail.Type, "", nil) + if err != nil { + return nil, fmt.Errorf("bad abi type: %q provided for data word: %q at index: %d in config", cfgDWDetail.Type, genericName, *cfgDWDetail.Index) + } + dWsDetail[genericName] = read.DataWordDetail{Argument: abi.Argument{Type: abiTyp}, Index: *cfgDWDetail.Index} + } + } + return dWsDetail, nil } -func (cr *chainReader) addEncoderDef(contractName, itemType string, args abi.Arguments, prefix []byte, inputModifications codec.ModifiersConfig) error { +// getEventItemTypeAndModifier returns codec entry for expected incoming event item and the modifier. +func (cr *chainReader) getEventItemTypeAndModifier(itemType string) (types.CodecEntry, commoncodec.Modifier) { + inputTypeInfo := cr.parsed.EncoderDefs[itemType] + return inputTypeInfo, inputTypeInfo.Modifier() +} + +func (cr *chainReader) addEncoderDef(contractName, itemType string, args abi.Arguments, prefix []byte, inputModifications commoncodec.ModifiersConfig) error { // ABI.Pack prepends the method.ID to the encodings, we'll need the encoder to do the same. - inputMod, err := inputModifications.ToModifier(DecoderHooks...) + inputMod, err := inputModifications.ToModifier(codec.DecoderHooks...) if err != nil { return err } @@ -370,53 +453,91 @@ func (cr *chainReader) addEncoderDef(contractName, itemType string, args abi.Arg return err } - cr.parsed.EncoderDefs[WrapItemType(contractName, itemType, true)] = input + cr.parsed.EncoderDefs[codec.WrapItemType(contractName, itemType, true)] = input return nil } -func (cr *chainReader) addDecoderDef(contractName, itemType string, outputs abi.Arguments, outputModifications codec.ModifiersConfig) error { - mod, err := outputModifications.ToModifier(DecoderHooks...) +func (cr *chainReader) addDecoderDef(contractName, itemType string, outputs abi.Arguments, outputModifications commoncodec.ModifiersConfig) error { + mod, err := outputModifications.ToModifier(codec.DecoderHooks...) if err != nil { return err } output := types.NewCodecEntry(outputs, nil, mod) - cr.parsed.DecoderDefs[WrapItemType(contractName, itemType, false)] = output + cr.parsed.DecoderDefs[codec.WrapItemType(contractName, itemType, false)] = output return output.Init() } -// setupEventInput returns abi args where indexed flag is set to false because we expect caller to filter with params that aren't hashed. -// codecEntry has expected onchain types set, for e.g. indexed topics of type string or uint8[32] array are expected as common.Hash onchain. -func setupEventInput(event abi.Event, inputFields []string) ([]abi.Argument, types.CodecEntry, map[string]bool) { - topicFieldDefs := map[string]bool{} - for _, value := range inputFields { - capFirstValue := abi.ToCamelCase(value) - topicFieldDefs[capFirstValue] = true - } - - filterArgs := make([]abi.Argument, 0, types.MaxTopicFields) - inputArgs := make([]abi.Argument, 0, len(event.Inputs)) - indexArgNames := map[string]bool{} +// getEventTypes returns abi args where indexed flag is set to false because we expect caller to filter with params that aren't hashed, +// codecEntry where expected on chain types are set, for e.g. indexed topics of type string or uint8[32] array are expected as common.Hash onchain, +// and un-indexed data info in form of evm indexed 32 byte data words. +func getEventTypes(event abi.Event) ([]abi.Argument, types.CodecEntry, map[string]read.DataWordDetail) { + indexedAsUnIndexedTypes := make([]abi.Argument, 0, types.MaxTopicFields) + indexedTypes := make([]abi.Argument, 0, len(event.Inputs)) + dataWords := make(map[string]read.DataWordDetail) + var dwIndex int for _, input := range event.Inputs { if !input.Indexed { + dwIndex = calculateFieldDWIndex(input, event.Name+"."+input.Name, dataWords, dwIndex) continue } - filterWith := topicFieldDefs[abi.ToCamelCase(input.Name)] - if filterWith { - // When presenting the filter off-chain, - // the user will provide the unhashed version of the input - // The reader will hash topics if needed. - inputUnindexed := input - inputUnindexed.Indexed = false - filterArgs = append(filterArgs, inputUnindexed) - } + indexedAsUnIndexed := input + indexedAsUnIndexed.Indexed = false + // when presenting the filter off-chain, the caller will provide the unHashed version of the input and CR will hash topics when needed. + indexedAsUnIndexedTypes = append(indexedAsUnIndexedTypes, indexedAsUnIndexed) + indexedTypes = append(indexedTypes, input) + } + + return indexedAsUnIndexedTypes, types.NewCodecEntry(indexedTypes, nil, nil), dataWords +} + +// calculateFieldDWIndex recursively calculates the indices of all static unindexed fields in the event +// and calculates the offset for all unsearchable / dynamic fields. +func calculateFieldDWIndex(arg abi.Argument, fieldPath string, dataWords map[string]read.DataWordDetail, index int) int { + if isDynamic(arg.Type) { + return index + 1 + } - inputArgs = append(inputArgs, input) - indexArgNames[abi.ToCamelCase(input.Name)] = true + return processFields(arg.Type, fieldPath, dataWords, index) +} + +func processFields(fieldType abi.Type, parentFieldPath string, dataWords map[string]read.DataWordDetail, index int) int { + switch fieldType.T { + case abi.TupleTy: + // Recursively process tuple elements + for i, tupleElem := range fieldType.TupleElems { + fieldName := fieldType.TupleRawNames[i] + fullFieldPath := fmt.Sprintf("%s.%s", parentFieldPath, fieldName) + index = processFields(*tupleElem, fullFieldPath, dataWords, index) + } + return index + case abi.ArrayTy: + // Static arrays are not searchable, however, we can reliably calculate their size so that the fields + // after them can be searched. + return index + fieldType.Size + default: + dataWords[parentFieldPath] = read.DataWordDetail{ + Index: index, + Argument: abi.Argument{Type: fieldType}, + } + return index + 1 } +} - return filterArgs, types.NewCodecEntry(inputArgs, nil, nil), indexArgNames +func isDynamic(fieldType abi.Type) bool { + switch fieldType.T { + case abi.StringTy, abi.SliceTy, abi.BytesTy: + return true + case abi.TupleTy: + // If one element in a struct is dynamic, the whole struct is treated as dynamic. + for _, elem := range fieldType.TupleElems { + if isDynamic(*elem) { + return true + } + } + } + return false } // ConfirmationsFromConfig maps chain agnostic confidence levels defined in config to predefined EVM finality. @@ -441,12 +562,3 @@ func ConfirmationsFromConfig(values map[string]int) (map[primitives.ConfidenceLe return mappings, nil } - -// confidenceToConfirmations matches predefined chain agnostic confidence levels to predefined EVM finality. -func confidenceToConfirmations(confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations, confidenceLevel primitives.ConfidenceLevel) (evmtypes.Confirmations, error) { - confirmations, exists := confirmationsMapping[confidenceLevel] - if !exists { - return 0, fmt.Errorf("missing mapping for confidence level: %s", confidenceLevel) - } - return confirmations, nil -} diff --git a/core/services/relay/evm/evmtesting/chain_reader_historical_client_wrapper.go b/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go similarity index 88% rename from core/services/relay/evm/evmtesting/chain_reader_historical_client_wrapper.go rename to core/services/relay/evm/chain_reader_historical_client_wrapper_test.go index b3d73be28f8..d0aa4a21332 100644 --- a/core/services/relay/evm/evmtesting/chain_reader_historical_client_wrapper.go +++ b/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go @@ -1,4 +1,4 @@ -package evmtesting +package evm import ( "context" @@ -14,9 +14,10 @@ import ( clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -30,7 +31,7 @@ type ClientWithContractHistory struct { func (cwh *ClientWithContractHistory) Init(_ context.Context, config types.ChainReaderConfig) error { cwh.valsWithCall = make(map[int64]valWithCall) - parsedTypes := evm.ParsedTypes{ + parsedTypes := codec.ParsedTypes{ EncoderDefs: make(map[string]types.CodecEntry), DecoderDefs: make(map[string]types.CodecEntry), } @@ -47,12 +48,14 @@ func (cwh *ClientWithContractHistory) Init(_ context.Context, config types.Chain continue } - inputMod, err := readDef.InputModifications.ToModifier(evm.DecoderHooks...) + injectEVMSpecificCodecModifiers(readDef) + + inputMod, err := readDef.InputModifications.ToModifier(codec.DecoderHooks...) if err != nil { return err } - outputMod, err := readDef.OutputModifications.ToModifier(evm.DecoderHooks...) + outputMod, err := readDef.OutputModifications.ToModifier(codec.DecoderHooks...) if err != nil { return err } @@ -67,16 +70,18 @@ func (cwh *ClientWithContractHistory) Init(_ context.Context, config types.Chain return err } - parsedTypes.EncoderDefs[evm.WrapItemType(contractName, genericName, true)] = input - parsedTypes.DecoderDefs[evm.WrapItemType(contractName, genericName, false)] = output + parsedTypes.EncoderDefs[codec.WrapItemType(contractName, genericName, true)] = input + parsedTypes.DecoderDefs[codec.WrapItemType(contractName, genericName, false)] = output } } - codec, err := parsedTypes.ToCodec() + parsedCodec, err := parsedTypes.ToCodec() if err != nil { return err } - cwh.codec = codec + + cwh.codec = parsedCodec + return nil } @@ -90,7 +95,6 @@ func (cwh *ClientWithContractHistory) SetUintLatestValue(ctx context.Context, va ExpectedGetLatestValueArgs: forCall, val: val, } - return nil } @@ -123,7 +127,7 @@ func (cwh *ClientWithContractHistory) CallContract(ctx context.Context, msg ethe } // encode the expected call to compare with the actual call - dataToCmp, err := cwh.codec.Encode(ctx, valAndCall.Params, evm.WrapItemType(valAndCall.ContractName, valAndCall.ReadName, true)) + dataToCmp, err := cwh.codec.Encode(ctx, valAndCall.Params, codec.WrapItemType(valAndCall.ContractName, valAndCall.ReadName, true)) if err != nil { return nil, err } diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go deleted file mode 100644 index f30bba0e449..00000000000 --- a/core/services/relay/evm/chain_reader_test.go +++ /dev/null @@ -1,221 +0,0 @@ -package evm_test - -import ( - "context" - "fmt" - "math" - "math/big" - "os" - "strconv" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/crypto" - "github.com/jmoiron/sqlx" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint common practice to import test mods with . -) - -const commonGasLimitOnEvms = uint64(4712388) - -func TestChainReaderEventsInitValidation(t *testing.T) { - tests := []struct { - name string - chainContractReaders map[string]types.ChainContractReader - expectedError error - }{ - { - name: "Invalid ABI", - chainContractReaders: map[string]types.ChainContractReader{ - "InvalidContract": { - ContractABI: "{invalid json}", - Configs: map[string]*types.ChainReaderDefinition{}, - }, - }, - expectedError: fmt.Errorf("failed to parse abi"), - }, - { - name: "Conflicting polling filter definitions", - chainContractReaders: map[string]types.ChainContractReader{ - "ContractWithConflict": { - ContractABI: "[]", - Configs: map[string]*types.ChainReaderDefinition{ - "EventWithConflict": { - ChainSpecificName: "EventName", - ReadType: types.Event, - EventDefinitions: &types.EventDefinitions{ - PollingFilter: &types.PollingFilter{}, - }, - }, - }, - ContractPollingFilter: types.ContractPollingFilter{ - GenericEventNames: []string{"EventWithConflict"}, - }, - }, - }, - expectedError: fmt.Errorf( - "%w: conflicting chain reader polling filter definitions for contract: %s event: %s, can't have polling filter defined both on contract and event level", - clcommontypes.ErrInvalidConfig, "ContractWithConflict", "EventWithConflict"), - }, - { - name: "No polling filter defined", - chainContractReaders: map[string]types.ChainContractReader{ - "ContractWithNoFilter": { - ContractABI: "[]", - Configs: map[string]*types.ChainReaderDefinition{ - "EventWithNoFilter": { - ChainSpecificName: "EventName", - ReadType: types.Event, - }, - }, - }, - }, - expectedError: fmt.Errorf( - "%w: chain reader has no polling filter defined for contract: %s, event: %s", - clcommontypes.ErrInvalidConfig, "ContractWithNoFilter", "EventWithNoFilter"), - }, - { - name: "Invalid chain reader definition read type", - chainContractReaders: map[string]types.ChainContractReader{ - "ContractWithInvalidReadType": { - ContractABI: "[]", - Configs: map[string]*types.ChainReaderDefinition{ - "InvalidReadType": { - ChainSpecificName: "InvalidName", - ReadType: types.ReadType(2), - }, - }, - }, - }, - expectedError: fmt.Errorf( - "%w: invalid chain reader definition read type", - clcommontypes.ErrInvalidConfig), - }, - { - name: "Event not present in ABI", - chainContractReaders: map[string]types.ChainContractReader{ - "ContractWithConflict": { - ContractABI: "[{\"anonymous\":false,\"inputs\":[],\"name\":\"WrongEvent\",\"type\":\"event\"}]", - Configs: map[string]*types.ChainReaderDefinition{ - "SomeEvent": { - ChainSpecificName: "EventName", - ReadType: types.Event, - }, - }, - ContractPollingFilter: types.ContractPollingFilter{ - GenericEventNames: []string{"SomeEvent"}, - }, - }, - }, - expectedError: fmt.Errorf( - "%w: event %s doesn't exist", - clcommontypes.ErrInvalidConfig, "EventName"), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, err := evm.NewChainReaderService(testutils.Context(t), logger.NullLogger, nil, nil, nil, types.ChainReaderConfig{Contracts: tt.chainContractReaders}) - require.Error(t, err) - if err != nil { - assert.Contains(t, err.Error(), tt.expectedError.Error()) - } - }) - } -} - -func TestChainReader(t *testing.T) { - t.Parallel() - it := &EVMChainReaderInterfaceTester[*testing.T]{Helper: &helper{}} - // add new subtests here so that it can be run on real chains too - RunChainReaderEvmTests(t, it) - RunChainReaderInterfaceTests[*testing.T](t, commontestutils.WrapChainReaderTesterForLoop(it)) -} - -type helper struct { - sim *backends.SimulatedBackend - auth *bind.TransactOpts -} - -func (h *helper) MustGenerateRandomKey(t *testing.T) ethkey.KeyV2 { - return cltest.MustGenerateRandomKey(t) -} - -func (h *helper) GasPriceBufferPercent() int64 { - return 0 -} - -func (h *helper) SetupAuth(t *testing.T) *bind.TransactOpts { - privateKey, err := crypto.GenerateKey() - require.NoError(t, err) - - h.auth, err = bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) - require.NoError(t, err) - - h.Backend() - h.Commit() - return h.auth -} - -func (h *helper) Backend() bind.ContractBackend { - if h.sim == nil { - h.sim = backends.NewSimulatedBackend( - core.GenesisAlloc{h.auth.From: {Balance: big.NewInt(math.MaxInt64)}}, commonGasLimitOnEvms*5000) - } - - return h.sim -} - -func (h *helper) Commit() { - h.sim.Commit() -} - -func (h *helper) Client(t *testing.T) client.Client { - return client.NewSimulatedBackendClient(t, h.sim, big.NewInt(1337)) -} - -func (h *helper) ChainID() *big.Int { - return testutils.SimulatedChainID -} - -func (h *helper) NewSqlxDB(t *testing.T) *sqlx.DB { - return pgtest.NewSqlxDB(t) -} - -func (h *helper) Context(t *testing.T) context.Context { - return testutils.Context(t) -} - -func (h *helper) MaxWaitTimeForEvents() time.Duration { - // From trial and error, when running on CI, sometimes the boxes get slow - maxWaitTime := time.Second * 30 - maxWaitTimeStr, ok := os.LookupEnv("MAX_WAIT_TIME_FOR_EVENTS_S") - if ok { - waitS, err := strconv.ParseInt(maxWaitTimeStr, 10, 64) - if err != nil { - fmt.Printf("Error parsing MAX_WAIT_TIME_FOR_EVENTS_S: %v, defaulting to %v\n", err, maxWaitTime) - } - maxWaitTime = time.Second * time.Duration(waitS) - } - - return maxWaitTime -} diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index f188ffeced2..16eb8256cfa 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -18,8 +19,8 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -43,13 +44,8 @@ func NewChainWriterService(logger logger.Logger, client evmclient.Client, txm ev ge: estimator, maxGasPrice: config.MaxGasPrice, - sendStrategy: txmgr.NewSendEveryStrategy(), contracts: config.Contracts, - parsedContracts: &ParsedTypes{EncoderDefs: map[string]types.CodecEntry{}, DecoderDefs: map[string]types.CodecEntry{}}, - } - - if config.SendStrategy != nil { - w.sendStrategy = config.SendStrategy + parsedContracts: &codec.ParsedTypes{EncoderDefs: map[string]types.CodecEntry{}, DecoderDefs: map[string]types.CodecEntry{}}, } if err := w.parseContracts(); err != nil { @@ -73,9 +69,8 @@ type chainWriter struct { ge gas.EvmFeeEstimator maxGasPrice *assets.Wei - sendStrategy txmgrtypes.TxStrategy contracts map[string]*types.ContractConfig - parsedContracts *ParsedTypes + parsedContracts *codec.ParsedTypes encoder commontypes.Encoder } @@ -100,7 +95,7 @@ func (w *chainWriter) SubmitTransaction(ctx context.Context, contract, method st return fmt.Errorf("method config not found: %v", method) } - calldata, err := w.encoder.Encode(ctx, args, WrapItemType(contract, method, true)) + calldata, err := w.encoder.Encode(ctx, args, codec.WrapItemType(contract, method, true)) if err != nil { return fmt.Errorf("%w: failed to encode args", err) } @@ -122,14 +117,19 @@ func (w *chainWriter) SubmitTransaction(ctx context.Context, contract, method st } } + gasLimit := methodConfig.GasLimit + if meta != nil && meta.GasLimit != nil { + gasLimit = meta.GasLimit.Uint64() + } + req := evmtxmgr.TxRequest{ FromAddress: methodConfig.FromAddress, ToAddress: common.HexToAddress(toAddress), EncodedPayload: calldata, - FeeLimit: methodConfig.GasLimit, + FeeLimit: gasLimit, Meta: txMeta, IdempotencyKey: &transactionID, - Strategy: w.sendStrategy, + Strategy: txmgr.NewSendEveryStrategy(), Checker: checker, Value: *v, } @@ -156,7 +156,7 @@ func (w *chainWriter) parseContracts() error { } // ABI.Pack prepends the method.ID to the encodings, we'll need the encoder to do the same. - inputMod, err := methodConfig.InputModifications.ToModifier(DecoderHooks...) + inputMod, err := methodConfig.InputModifications.ToModifier(codec.DecoderHooks...) if err != nil { return fmt.Errorf("%w: failed to create input mods", err) } @@ -167,7 +167,7 @@ func (w *chainWriter) parseContracts() error { return fmt.Errorf("%w: failed to init codec entry for method %s", err, method) } - w.parsedContracts.EncoderDefs[WrapItemType(contract, method, true)] = input + w.parsedContracts.EncoderDefs[codec.WrapItemType(contract, method, true)] = input } } @@ -186,14 +186,14 @@ func (w *chainWriter) GetFeeComponents(ctx context.Context) (*commontypes.ChainF return nil, fmt.Errorf("gas estimator not available") } - fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice) + fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice, nil, nil) if err != nil { return nil, err } // Use legacy if no dynamic is available. - gasPrice := fee.Legacy.ToInt() - if fee.DynamicFeeCap != nil { - gasPrice = fee.DynamicFeeCap.ToInt() + gasPrice := fee.GasPrice.ToInt() + if fee.GasFeeCap != nil { + gasPrice = fee.GasFeeCap.ToInt() } if gasPrice == nil { return nil, fmt.Errorf("dynamic fee and legacy gas price missing %+v", fee) diff --git a/core/services/relay/evm/chain_writer_historical_wrapper_test.go b/core/services/relay/evm/chain_writer_historical_wrapper_test.go new file mode 100644 index 00000000000..c849d1f3d57 --- /dev/null +++ b/core/services/relay/evm/chain_writer_historical_wrapper_test.go @@ -0,0 +1,39 @@ +package evm + +import ( + "context" + "math/big" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + interfacetesttypes "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" + primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" +) + +// This wrapper is required to enable the ChainReader to access historical data +// Since the geth simulated backend doesn't support historical data, we use this +// thin wrapper. +type ChainWriterHistoricalWrapper struct { + commontypes.ChainWriter + cwh *ClientWithContractHistory +} + +func NewChainWriterHistoricalWrapper(cw commontypes.ChainWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { + return &ChainWriterHistoricalWrapper{ChainWriter: cw, cwh: cwh} +} + +func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, contractName, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { + if primArgs, ok := args.(interfacetesttypes.PrimitiveArgs); ok { + callArgs := interfacetesttypes.ExpectedGetLatestValueArgs{ + ContractName: contractName, + ReadName: "GetAlterablePrimitiveValue", + ConfidenceLevel: primitives.Unconfirmed, + Params: nil, + ReturnVal: nil, + } + err := cwhw.cwh.SetUintLatestValue(ctx, primArgs.Value, callArgs) + if err != nil { + return err + } + } + return cwhw.ChainWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) +} diff --git a/core/services/relay/evm/chain_writer_test.go b/core/services/relay/evm/chain_writer_test.go index ab8b6f0e36b..50ef2dd114e 100644 --- a/core/services/relay/evm/chain_writer_test.go +++ b/core/services/relay/evm/chain_writer_test.go @@ -87,10 +87,9 @@ func TestChainWriter(t *testing.T) { }) t.Run("GetFeeComponents", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ - Legacy: assets.NewWei(big.NewInt(1000000001)), - DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), - DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + GasPrice: assets.NewWei(big.NewInt(1000000001)), + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWei(big.NewInt(1000000002)), GasTipCap: assets.NewWei(big.NewInt(1000000003))}, }, uint64(0), nil).Twice() l1Oracle.On("GasPrice", mock.Anything).Return(assets.NewWei(big.NewInt(1000000004)), nil).Once() @@ -113,10 +112,9 @@ func TestChainWriter(t *testing.T) { }) t.Run("Returns Legacy Fee in absence of Dynamic Fee", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ - Legacy: assets.NewWei(big.NewInt(1000000001)), - DynamicFeeCap: nil, - DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + GasPrice: assets.NewWei(big.NewInt(1000000001)), + DynamicFee: gas.DynamicFee{GasFeeCap: nil, GasTipCap: assets.NewWei(big.NewInt(1000000003))}, }, uint64(0), nil).Once() feeComponents, err = cw.GetFeeComponents(ctx) require.NoError(t, err) @@ -125,10 +123,9 @@ func TestChainWriter(t *testing.T) { }) t.Run("Fails when neither legacy or dynamic fee is available", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ - Legacy: nil, - DynamicFeeCap: nil, - DynamicTipCap: nil, + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + GasPrice: nil, + DynamicFee: gas.DynamicFee{}, }, uint64(0), nil).Once() _, err = cw.GetFeeComponents(ctx) @@ -137,20 +134,18 @@ func TestChainWriter(t *testing.T) { t.Run("Fails when GetFee returns an error", func(t *testing.T) { expectedErr := fmt.Errorf("GetFee error") - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ - Legacy: nil, - DynamicFeeCap: nil, - DynamicTipCap: nil, + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + GasPrice: nil, + DynamicFee: gas.DynamicFee{}, }, uint64(0), expectedErr).Once() _, err = cw.GetFeeComponents(ctx) require.Equal(t, expectedErr, err) }) t.Run("Fails when L1Oracle returns error", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ - Legacy: assets.NewWei(big.NewInt(1000000001)), - DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), - DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + GasPrice: assets.NewWei(big.NewInt(1000000001)), + DynamicFee: gas.DynamicFee{GasFeeCap: assets.NewWei(big.NewInt(1000000002)), GasTipCap: assets.NewWei(big.NewInt(1000000003))}, }, uint64(0), nil).Once() ge.On("L1Oracle", mock.Anything).Return(l1Oracle).Once() diff --git a/core/services/relay/evm/codec/byte_string_modifier.go b/core/services/relay/evm/codec/byte_string_modifier.go new file mode 100644 index 00000000000..f013e5d96fa --- /dev/null +++ b/core/services/relay/evm/codec/byte_string_modifier.go @@ -0,0 +1,42 @@ +package codec + +import ( + "fmt" + "strings" + + "github.com/ethereum/go-ethereum/common" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// EVMAddressModifier implements the AddressModifier interface for Ethereum addresses. +// It handles encoding and decoding Ethereum addresses with EIP-55 checksums and hex encoding. +type EVMAddressModifier struct{} + +func (e EVMAddressModifier) EncodeAddress(bytes []byte) (string, error) { + if len(bytes) != e.Length() { + return "", fmt.Errorf("%w: got length %d, expected 20 for bytes %x", commontypes.ErrInvalidType, len(bytes), bytes) + } + + return common.BytesToAddress(bytes).Hex(), nil +} + +// DecodeAddress takes an EIP-55 encoded Ethereum address (e.g., "0x...") and decodes it to a 20-byte array. +func (e EVMAddressModifier) DecodeAddress(str string) ([]byte, error) { + str = strings.TrimPrefix(str, "0x") + if len(str) != 40 { + return nil, fmt.Errorf("%w: got length %d, expected 40 for address %s", commontypes.ErrInvalidType, len(str), str) + } + + address := common.HexToAddress(str) + if address == (common.Address{}) { + return nil, fmt.Errorf("%w: address is zero", commontypes.ErrInvalidType) + } + + return address.Bytes(), nil +} + +// Length returns the expected length of an Ethereum address in bytes (20 bytes). +func (e EVMAddressModifier) Length() int { + return common.AddressLength +} diff --git a/core/services/relay/evm/codec/byte_string_modifier_test.go b/core/services/relay/evm/codec/byte_string_modifier_test.go new file mode 100644 index 00000000000..f8dade55d67 --- /dev/null +++ b/core/services/relay/evm/codec/byte_string_modifier_test.go @@ -0,0 +1,54 @@ +package codec_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" +) + +func TestEVMAddressModifier(t *testing.T) { + modifier := codec.EVMAddressModifier{} + validAddressStr := "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4" + validAddressBytes := common.HexToAddress(validAddressStr).Bytes() + invalidLengthAddressStr := "0xabcdef1234567890abcdef" + + t.Run("EncodeAddress encodes valid Ethereum address bytes", func(t *testing.T) { + encoded, err := modifier.EncodeAddress(validAddressBytes) + require.NoError(t, err) + assert.Equal(t, validAddressStr, encoded) + }) + + t.Run("EncodeAddress returns error for invalid byte length", func(t *testing.T) { + invalidBytes := []byte(invalidLengthAddressStr) + _, err := modifier.EncodeAddress(invalidBytes) + require.Error(t, err) + assert.Contains(t, err.Error(), commontypes.ErrInvalidType) + }) + + t.Run("DecodeAddress decodes valid Ethereum address", func(t *testing.T) { + decodedBytes, err := modifier.DecodeAddress(validAddressStr) + require.NoError(t, err) + assert.Equal(t, validAddressBytes, decodedBytes) + }) + + t.Run("DecodeAddress returns error for invalid address length", func(t *testing.T) { + _, err := modifier.DecodeAddress(invalidLengthAddressStr) + require.Error(t, err) + assert.Contains(t, err.Error(), commontypes.ErrInvalidType) + }) + + t.Run("DecodeAddress returns error for zero-value address", func(t *testing.T) { + _, err := modifier.DecodeAddress(common.Address{}.Hex()) + require.Error(t, err) + assert.Contains(t, err.Error(), commontypes.ErrInvalidType) + }) + + t.Run("Length returns 20 for Ethereum addresses", func(t *testing.T) { + assert.Equal(t, common.AddressLength, modifier.Length()) + }) +} diff --git a/core/services/relay/evm/codec.go b/core/services/relay/evm/codec/codec.go similarity index 82% rename from core/services/relay/evm/codec.go rename to core/services/relay/evm/codec/codec.go index 2f01adfbdcb..397460a7f3e 100644 --- a/core/services/relay/evm/codec.go +++ b/core/services/relay/evm/codec/codec.go @@ -1,4 +1,4 @@ -package evm +package codec import ( "encoding/json" @@ -9,10 +9,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/mitchellh/mapstructure" - - "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/go-viper/mapstructure/v2" + commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -33,10 +32,10 @@ import ( // it was a *big.Int var DecoderHooks = []mapstructure.DecodeHookFunc{ decodeAccountAndAllowArraySliceHook, - codec.BigIntHook, - codec.SliceToArrayVerifySizeHook, + commoncodec.BigIntHook, + commoncodec.SliceToArrayVerifySizeHook, sizeVerifyBigIntHook, - codec.NumberHook, + commoncodec.NumberHook, } // NewCodec creates a new [commontypes.RemoteCodec] for EVM. @@ -91,19 +90,32 @@ func (c *evmCodec) CreateType(itemType string, forEncoding bool) (any, error) { def, ok := itemTypes[itemType] if !ok { - return nil, fmt.Errorf("%w: cannot find type name %s", commontypes.ErrInvalidType, itemType) + return nil, fmt.Errorf("%w: cannot find type name %q", commontypes.ErrInvalidType, itemType) + } + + // we don't need double pointers, and they can also mess up reflection variable creation and mapstruct decode + if def.CheckedType().Kind() == reflect.Pointer { + return reflect.New(def.CheckedType()).Elem().Interface(), nil } return reflect.New(def.CheckedType()).Interface(), nil } +func WrapItemType(contractName, itemType string, isParams bool) string { + if isParams { + return fmt.Sprintf("params.%s.%s", contractName, itemType) + } + + return fmt.Sprintf("return.%s.%s", contractName, itemType) +} + var bigIntType = reflect.TypeOf((*big.Int)(nil)) func sizeVerifyBigIntHook(from, to reflect.Type, data any) (any, error) { if from.Implements(types.SizedBigIntType()) && !to.Implements(types.SizedBigIntType()) && !reflect.PointerTo(to).Implements(types.SizedBigIntType()) { - return codec.BigIntHook(from, bigIntType, reflect.ValueOf(data).Convert(bigIntType).Interface()) + return commoncodec.BigIntHook(from, bigIntType, reflect.ValueOf(data).Convert(bigIntType).Interface()) } if !to.Implements(types.SizedBigIntType()) { @@ -111,7 +123,7 @@ func sizeVerifyBigIntHook(from, to reflect.Type, data any) (any, error) { } var err error - data, err = codec.BigIntHook(from, bigIntType, data) + data, err = commoncodec.BigIntHook(from, bigIntType, data) if err != nil { return nil, err } diff --git a/core/services/relay/evm/codec_fuzz_test.go b/core/services/relay/evm/codec/codec_fuzz_test.go similarity index 92% rename from core/services/relay/evm/codec_fuzz_test.go rename to core/services/relay/evm/codec/codec_fuzz_test.go index 5870e9d77ad..1b65a1bc29d 100644 --- a/core/services/relay/evm/codec_fuzz_test.go +++ b/core/services/relay/evm/codec/codec_fuzz_test.go @@ -1,4 +1,4 @@ -package evm_test +package codec_test import ( "testing" diff --git a/core/services/relay/evm/codec_test.go b/core/services/relay/evm/codec/codec_test.go similarity index 86% rename from core/services/relay/evm/codec_test.go rename to core/services/relay/evm/codec/codec_test.go index af3170abf0e..12455dd9aee 100644 --- a/core/services/relay/evm/codec_test.go +++ b/core/services/relay/evm/codec/codec_test.go @@ -1,10 +1,11 @@ -package evm_test +package codec_test import ( "encoding/json" "math/big" "testing" + "github.com/cometbft/cometbft/libs/strings" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -12,7 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/codec" + commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" looptestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" //nolint common practice to import test mods with . @@ -21,7 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -45,7 +46,7 @@ func TestCodec(t *testing.T) { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ codecName: {TypeABI: evmEncoderConfig}, }} - c, err := evm.NewCodec(codecConfig) + c, err := codec.NewCodec(codecConfig) require.NoError(t, err) result, err := c.Encode(testutils.Context(t), encode, codecName) @@ -91,7 +92,7 @@ func TestCodec_SimpleEncode(t *testing.T) { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ codecName: {TypeABI: evmEncoderConfig}, }} - c, err := evm.NewCodec(codecConfig) + c, err := codec.NewCodec(codecConfig) require.NoError(t, err) result, err := c.Encode(testutils.Context(t), input, codecName) @@ -120,7 +121,7 @@ func TestCodec_EncodeTuple(t *testing.T) { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ codecName: {TypeABI: evmEncoderConfig}, }} - c, err := evm.NewCodec(codecConfig) + c, err := codec.NewCodec(codecConfig) require.NoError(t, err) result, err := c.Encode(testutils.Context(t), input, codecName) @@ -152,7 +153,7 @@ func TestCodec_EncodeTupleWithLists(t *testing.T) { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ codecName: {TypeABI: evmEncoderConfig}, }} - c, err := evm.NewCodec(codecConfig) + c, err := codec.NewCodec(codecConfig) require.NoError(t, err) result, err := c.Encode(testutils.Context(t), input, codecName) @@ -186,6 +187,10 @@ func (it *codecInterfaceTester) GetAccountBytes(i int) []byte { return account[:] } +func (it *codecInterfaceTester) GetAccountString(i int) string { + return common.BytesToAddress(it.GetAccountBytes(i)).Hex() +} + func (it *codecInterfaceTester) EncodeFields(t *testing.T, request *EncodeRequest) []byte { if request.TestOn == TestItemType { return encodeFieldsOnItem(t, request) @@ -204,13 +209,23 @@ func (it *codecInterfaceTester) GetCodec(t *testing.T) commontypes.Codec { entry.TypeABI = string(defBytes) if k != sizeItemType && k != NilType { - entry.ModifierConfigs = codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + entry.ModifierConfigs = commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + } + } + + if strings.StringInSlice(k, []string{TestItemType, TestItemSliceType, TestItemArray1Type, TestItemArray2Type, TestItemWithConfigExtra}) { + addressByteModifier := &commoncodec.AddressBytesToStringModifierConfig{ + Fields: []string{"AccountStr"}, + Modifier: codec.EVMAddressModifier{}, } + + entry.ModifierConfigs = append(entry.ModifierConfigs, addressByteModifier) } if k == TestItemWithConfigExtra { - hardCode := &codec.HardCodeModifierConfig{ + hardCode := &commoncodec.HardCodeModifierConfig{ OnChainValues: map[string]any{ "BigField": testStruct.BigField.String(), "Account": hexutil.Encode(testStruct.Account), @@ -222,7 +237,7 @@ func (it *codecInterfaceTester) GetCodec(t *testing.T) commontypes.Codec { codecConfig.Configs[k] = entry } - c, err := evm.NewCodec(codecConfig) + c, err := codec.NewCodec(codecConfig) require.NoError(t, err) return c } @@ -280,14 +295,24 @@ func packArgs(t *testing.T, allArgs []any, oargs abi.Arguments, request *EncodeR return bytes } -var inner = []abi.ArgumentMarshaling{ +var innerDynamic = []abi.ArgumentMarshaling{ {Name: "IntVal", Type: "int64"}, {Name: "S", Type: "string"}, } -var nested = []abi.ArgumentMarshaling{ +var nestedDynamic = []abi.ArgumentMarshaling{ + {Name: "FixedBytes", Type: "bytes2"}, + {Name: "Inner", Type: "tuple", Components: innerDynamic}, +} + +var innerStatic = []abi.ArgumentMarshaling{ + {Name: "IntVal", Type: "int64"}, + {Name: "A", Type: "address"}, +} + +var nestedStatic = []abi.ArgumentMarshaling{ {Name: "FixedBytes", Type: "bytes2"}, - {Name: "Inner", Type: "tuple", Components: inner}, + {Name: "Inner", Type: "tuple", Components: innerStatic}, } var ts = []abi.ArgumentMarshaling{ @@ -296,9 +321,11 @@ var ts = []abi.ArgumentMarshaling{ {Name: "OracleId", Type: "uint8"}, {Name: "OracleIds", Type: "uint8[32]"}, {Name: "Account", Type: "address"}, + {Name: "AccountStr", Type: "address"}, {Name: "Accounts", Type: "address[]"}, {Name: "BigField", Type: "int192"}, - {Name: "NestedStruct", Type: "tuple", Components: nested}, + {Name: "NestedDynamicStruct", Type: "tuple", Components: nestedDynamic}, + {Name: "NestedStaticStruct", Type: "tuple", Components: nestedStatic}, } const sizeItemType = "item for size" @@ -353,8 +380,10 @@ func argsFromTestStruct(ts TestStruct) []any { uint8(ts.OracleID), getOracleIDs(ts), common.Address(ts.Account), + common.HexToAddress(ts.AccountStr), getAccounts(ts), ts.BigField, - evmtesting.MidToInternalType(ts.NestedStruct), + evmtesting.MidDynamicToInternalType(ts.NestedDynamicStruct), + evmtesting.MidStaticToInternalType(ts.NestedStaticStruct), } } diff --git a/core/services/relay/evm/decoder.go b/core/services/relay/evm/codec/decoder.go similarity index 92% rename from core/services/relay/evm/decoder.go rename to core/services/relay/evm/codec/decoder.go index 732ee91d9e5..70c0f1d668b 100644 --- a/core/services/relay/evm/decoder.go +++ b/core/services/relay/evm/codec/decoder.go @@ -1,11 +1,11 @@ -package evm +package codec import ( "context" "fmt" "reflect" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -45,7 +45,7 @@ func (m *decoder) Decode(_ context.Context, raw []byte, into any, itemType strin iInto.Set(reflect.MakeSlice(iInto.Type(), length, length)) return setElements(length, rDecode, iInto) default: - return mapstructureDecode(decode, into) + return MapstructureDecode(decode, into) } } @@ -83,7 +83,7 @@ func extractDecoding(info types.CodecEntry, raw []byte) (any, error) { func setElements(length int, rDecode reflect.Value, iInto reflect.Value) error { for i := 0; i < length; i++ { - if err := mapstructureDecode(rDecode.Index(i).Interface(), iInto.Index(i).Addr().Interface()); err != nil { + if err := MapstructureDecode(rDecode.Index(i).Interface(), iInto.Index(i).Addr().Interface()); err != nil { return err } } @@ -91,7 +91,7 @@ func setElements(length int, rDecode reflect.Value, iInto reflect.Value) error { return nil } -func mapstructureDecode(src, dest any) error { +func MapstructureDecode(src, dest any) error { mDecoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ DecodeHook: mapstructure.ComposeDecodeHookFunc(DecoderHooks...), Result: dest, diff --git a/core/services/relay/evm/encoder.go b/core/services/relay/evm/codec/encoder.go similarity index 89% rename from core/services/relay/evm/encoder.go rename to core/services/relay/evm/codec/encoder.go index ae60e4ab35a..18ad32831c2 100644 --- a/core/services/relay/evm/encoder.go +++ b/core/services/relay/evm/codec/encoder.go @@ -1,4 +1,4 @@ -package evm +package codec import ( "context" @@ -52,13 +52,13 @@ func encode(item reflect.Value, info types.CodecEntry) ([]byte, error) { } switch item.Kind() { case reflect.Array, reflect.Slice: - native, err := representArray(item, info) + native, err := RepresentArray(item, info) if err != nil { return nil, err } return pack(info, native) case reflect.Struct, reflect.Map: - values, err := unrollItem(item, info) + values, err := UnrollItem(item, info) if err != nil { return nil, err } @@ -68,7 +68,7 @@ func encode(item reflect.Value, info types.CodecEntry) ([]byte, error) { } } -func representArray(item reflect.Value, info types.CodecEntry) (any, error) { +func RepresentArray(item reflect.Value, info types.CodecEntry) (any, error) { length := item.Len() checkedType := info.CheckedType() checked := reflect.New(checkedType) @@ -87,7 +87,7 @@ func representArray(item reflect.Value, info types.CodecEntry) (any, error) { checkedElm := checkedType.Elem() for i := 0; i < length; i++ { tmp := reflect.New(checkedElm) - if err := mapstructureDecode(item.Index(i).Interface(), tmp.Interface()); err != nil { + if err := MapstructureDecode(item.Index(i).Interface(), tmp.Interface()); err != nil { return nil, err } iChecked.Index(i).Set(tmp.Elem()) @@ -97,10 +97,10 @@ func representArray(item reflect.Value, info types.CodecEntry) (any, error) { return nil, err } - return native.Elem().Interface(), nil + return native.Interface(), nil } -func unrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { +func UnrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { checkedType := info.CheckedType() if item.CanAddr() { item = item.Addr() @@ -114,7 +114,7 @@ func unrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { } else if !info.IsNativePointer(item.Type()) { var err error checked := reflect.New(checkedType) - if err = mapstructureDecode(item.Interface(), checked.Interface()); err != nil { + if err = MapstructureDecode(item.Interface(), checked.Interface()); err != nil { return nil, err } if item, err = info.ToNative(checked); err != nil { @@ -122,7 +122,6 @@ func unrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { } } - item = reflect.Indirect(item) length := item.NumField() values := make([]any, length) iType := item.Type() diff --git a/core/services/relay/evm/parsed_types.go b/core/services/relay/evm/codec/parsed_types.go similarity index 80% rename from core/services/relay/evm/parsed_types.go rename to core/services/relay/evm/codec/parsed_types.go index 902c182e1d8..31c95caf4dd 100644 --- a/core/services/relay/evm/parsed_types.go +++ b/core/services/relay/evm/codec/parsed_types.go @@ -1,10 +1,10 @@ -package evm +package codec import ( "fmt" "reflect" - "github.com/smartcontractkit/chainlink-common/pkg/codec" + commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -16,7 +16,7 @@ type ParsedTypes struct { } func (parsed *ParsedTypes) ToCodec() (commontypes.RemoteCodec, error) { - modByTypeName := map[string]codec.Modifier{} + modByTypeName := map[string]commoncodec.Modifier{} if err := AddEntries(parsed.EncoderDefs, modByTypeName); err != nil { return nil, err } @@ -24,7 +24,7 @@ func (parsed *ParsedTypes) ToCodec() (commontypes.RemoteCodec, error) { return nil, err } - mod, err := codec.NewByItemTypeModifier(modByTypeName) + mod, err := commoncodec.NewByItemTypeModifier(modByTypeName) if err != nil { return nil, err } @@ -33,12 +33,12 @@ func (parsed *ParsedTypes) ToCodec() (commontypes.RemoteCodec, error) { decoder: &decoder{Definitions: parsed.DecoderDefs}, ParsedTypes: parsed, } - return codec.NewModifierCodec(underlying, mod, DecoderHooks...) + return commoncodec.NewModifierCodec(underlying, mod, DecoderHooks...) } // AddEntries extracts the mods from codecEntry and adds them to modByTypeName use with codec.NewByItemTypeModifier // Since each input/output can have its own modifications, we need to keep track of them by type name -func AddEntries(defs map[string]types.CodecEntry, modByTypeName map[string]codec.Modifier) error { +func AddEntries(defs map[string]types.CodecEntry, modByTypeName map[string]commoncodec.Modifier) error { for k, def := range defs { modByTypeName[k] = def.Modifier() _, err := def.Modifier().RetypeToOffChain(reflect.PointerTo(def.CheckedType()), k) diff --git a/core/services/relay/evm/commit_provider.go b/core/services/relay/evm/commit_provider.go index fe3e327c7f2..501e1ae0ef0 100644 --- a/core/services/relay/evm/commit_provider.go +++ b/core/services/relay/evm/commit_provider.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" @@ -17,7 +18,6 @@ import ( "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/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" ) @@ -151,7 +151,7 @@ func (P *SrcCommitProvider) ContractTransmitter() ocrtypes.ContractTransmitter { return UnimplementedContractTransmitter{} } -func (P *SrcCommitProvider) ChainReader() commontypes.ContractReader { +func (P *SrcCommitProvider) ContractReader() commontypes.ContractReader { return nil } @@ -209,7 +209,7 @@ func (P *DstCommitProvider) ContractTransmitter() ocrtypes.ContractTransmitter { return P.contractTransmitter } -func (P *DstCommitProvider) ChainReader() commontypes.ContractReader { +func (P *DstCommitProvider) ContractReader() commontypes.ContractReader { return nil } diff --git a/core/services/relay/evm/config_poller.go b/core/services/relay/evm/config_poller.go index 2280d60d7ee..a00b04b0786 100644 --- a/core/services/relay/evm/config_poller.go +++ b/core/services/relay/evm/config_poller.go @@ -15,11 +15,11 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers2/ocrconfigurationstoreevmsimple" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) diff --git a/core/services/relay/evm/config_poller_test.go b/core/services/relay/evm/config_poller_test.go index caf48caf490..0500b58a6e2 100644 --- a/core/services/relay/evm/config_poller_test.go +++ b/core/services/relay/evm/config_poller_test.go @@ -363,6 +363,7 @@ func setConfig(t *testing.T, pluginConfig median.OffchainConfig, ocrContract *oc []int{1, 1, 1, 1}, oracles, pluginConfig.Encode(), + nil, 50*time.Millisecond, 50*time.Millisecond, 50*time.Millisecond, diff --git a/core/services/relay/evm/contract_binding.go b/core/services/relay/evm/contract_binding.go deleted file mode 100644 index da2d7ed9bd1..00000000000 --- a/core/services/relay/evm/contract_binding.go +++ /dev/null @@ -1,100 +0,0 @@ -package evm - -import ( - "context" - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" -) - -type filterRegisterer struct { - pollingFilter logpoller.Filter - filterLock sync.Mutex - // registerCalled is used to determine if Register was called during Chain Reader service Start. - // This is done to avoid calling Register while the service is not running because log poller is most likely also not running. - registerCalled bool -} - -// contractBinding stores read bindings and manages the common contract event filter. -type contractBinding struct { - name string - // filterRegisterer is used to manage polling filter registration for the common contract filter. - // The common contract filter should be used by events that share filtering args. - filterRegisterer - // key is read name method, event or event keys used for queryKey. - readBindings map[string]readBinding - // bound determines if address is set to the contract binding. - bound bool - bindLock sync.Mutex -} - -// Bind binds contract addresses to contract binding and registers the common contract polling filter. -func (cb *contractBinding) Bind(ctx context.Context, lp logpoller.LogPoller, boundContract commontypes.BoundContract) error { - // it's enough to just lock bound here since Register/Unregister are only called from here and from Start/Close - // even if they somehow happen at the same time it will be fine because of filter lock and hasFilter check - cb.bindLock.Lock() - defer cb.bindLock.Unlock() - - if cb.bound { - // we are changing contract address reference, so we need to unregister old filter it exists - if err := cb.Unregister(ctx, lp); err != nil { - return err - } - } - - cb.pollingFilter.Addresses = evmtypes.AddressArray{common.HexToAddress(boundContract.Address)} - cb.pollingFilter.Name = logpoller.FilterName(boundContract.Name+"."+uuid.NewString(), boundContract.Address) - cb.bound = true - - if cb.registerCalled { - return cb.Register(ctx, lp) - } - - return nil -} - -// Register registers the common contract filter. -func (cb *contractBinding) Register(ctx context.Context, lp logpoller.LogPoller) error { - cb.filterLock.Lock() - defer cb.filterLock.Unlock() - - cb.registerCalled = true - // can't be true before filters params are set so there is no race with a bad filter outcome - if !cb.bound { - return nil - } - - if len(cb.pollingFilter.EventSigs) > 0 && !lp.HasFilter(cb.pollingFilter.Name) { - if err := lp.RegisterFilter(ctx, cb.pollingFilter); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - } - - return nil -} - -// Unregister unregisters the common contract filter. -func (cb *contractBinding) Unregister(ctx context.Context, lp logpoller.LogPoller) error { - cb.filterLock.Lock() - defer cb.filterLock.Unlock() - - if !cb.bound { - return nil - } - - if !lp.HasFilter(cb.pollingFilter.Name) { - return nil - } - - if err := lp.UnregisterFilter(ctx, cb.pollingFilter.Name); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - - return nil -} diff --git a/core/services/relay/evm/contract_transmitter.go b/core/services/relay/evm/contract_transmitter.go index d594dfb9214..aead9f6ca8a 100644 --- a/core/services/relay/evm/contract_transmitter.go +++ b/core/services/relay/evm/contract_transmitter.go @@ -12,13 +12,15 @@ import ( "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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" ) @@ -31,7 +33,7 @@ var _ ContractTransmitter = &contractTransmitter{} type Transmitter interface { CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, txMeta *txmgr.TxMeta) error - FromAddress() gethcommon.Address + FromAddress(context.Context) gethcommon.Address } type ReportToEthMetadata func([]byte) (*txmgr.TxMeta, error) @@ -54,6 +56,12 @@ func WithRetention(retention time.Duration) OCRTransmitterOption { } } +func WithMaxLogsKept(maxLogsKept uint64) OCRTransmitterOption { + return func(ct *contractTransmitter) { + ct.maxLogsKept = maxLogsKept + } +} + func WithReportToEthMetadata(reportToEvmTxMeta ReportToEthMetadata) OCRTransmitterOption { return func(ct *contractTransmitter) { if reportToEvmTxMeta != nil { @@ -74,6 +82,7 @@ type contractTransmitter struct { reportToEvmTxMeta ReportToEthMetadata excludeSigs bool retention time.Duration + maxLogsKept uint64 } func transmitterFilterName(addr common.Address) string { @@ -102,19 +111,18 @@ func NewOCRContractTransmitter( transmittedEventSig: transmitted.ID, lp: lp, contractReader: caller, - lggr: lggr.Named("OCRContractTransmitter"), + lggr: logger.Named(lggr, "OCRContractTransmitter"), reportToEvmTxMeta: reportToEvmTxMetaNoop, excludeSigs: false, retention: 0, + maxLogsKept: 0, } for _, opt := range opts { opt(newContractTransmitter) } - // TODO It would be better to keep MaxLogsKept = 1 for the OCR contract transmitter instead of Retention. We are always interested only in the latest log. - // Although MaxLogsKept is present in the Filter struct, it is not supported by LogPoller yet. - err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: newContractTransmitter.retention}) + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: newContractTransmitter.retention, MaxLogsKept: newContractTransmitter.maxLogsKept}) if err != nil { return nil, err } @@ -213,9 +221,6 @@ func (oc *contractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) ( } // Otherwise, we have to scan for the logs. - if err != nil { - return ocrtypes.ConfigDigest{}, 0, err - } latest, err := oc.lp.LatestLogByEventSigWithConfs(ctx, oc.transmittedEventSig, oc.contractAddress, 1) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -228,8 +233,8 @@ func (oc *contractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) ( } // FromAccount returns the account from which the transmitter invokes the contract -func (oc *contractTransmitter) FromAccount() (ocrtypes.Account, error) { - return ocrtypes.Account(oc.transmitter.FromAddress().String()), nil +func (oc *contractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return ocrtypes.Account(oc.transmitter.FromAddress(ctx).String()), nil } func (oc *contractTransmitter) Start(ctx context.Context) error { return nil } diff --git a/core/services/relay/evm/contract_transmitter_test.go b/core/services/relay/evm/contract_transmitter_test.go index 182cda63ced..5b9e1ae5981 100644 --- a/core/services/relay/evm/contract_transmitter_test.go +++ b/core/services/relay/evm/contract_transmitter_test.go @@ -12,6 +12,7 @@ import ( "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" @@ -38,7 +39,7 @@ func (m *mockTransmitter) CreateEthTransaction(ctx context.Context, toAddress ge return nil } -func (*mockTransmitter) FromAddress() gethcommon.Address { return sampleAddress } +func (*mockTransmitter) FromAddress(ctx context.Context) gethcommon.Address { return sampleAddress } func TestContractTransmitter(t *testing.T) { t.Parallel() @@ -83,7 +84,7 @@ func TestContractTransmitter(t *testing.T) { require.NoError(t, err) assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777", hex.EncodeToString(digest[:])) assert.Equal(t, uint32(2), epoch) - from, err := ot.FromAccount() + from, err := ot.FromAccount(tests.Context(t)) require.NoError(t, err) assert.Equal(t, sampleAddress.String(), string(from)) } diff --git a/core/services/relay/evm/event_binding.go b/core/services/relay/evm/event_binding.go deleted file mode 100644 index 7b62d862b35..00000000000 --- a/core/services/relay/evm/event_binding.go +++ /dev/null @@ -1,477 +0,0 @@ -package evm - -import ( - "context" - "fmt" - "reflect" - "strings" - "sync" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/google/uuid" - - "github.com/smartcontractkit/chainlink-common/pkg/codec" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - - "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/services/relay/evm/types" -) - -type eventBinding struct { - address common.Address - contractName string - eventName string - lp logpoller.LogPoller - // filterRegisterer in eventBinding is to be used as an override for lp filter defined in the contract binding. - // If filterRegisterer is nil, this event should be registered with the lp filter defined in the contract binding. - *filterRegisterer - hash common.Hash - codec commontypes.RemoteCodec - // bound determines if address is set to the contract binding. - bound bool - bindLock sync.Mutex - inputInfo types.CodecEntry - inputModifier codec.Modifier - codecTopicInfo types.CodecEntry - // topics maps a generic topic name (key) to topic data - topics map[string]topicDetail - // eventDataWords maps a generic name to a word index - // key is a predefined generic name for evm log event data word - // for e.g. first evm data word(32bytes) of USDC log event is value so the key can be called value - eventDataWords map[string]uint8 - confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations -} - -type topicDetail struct { - abi.Argument - Index uint64 -} - -var _ readBinding = &eventBinding{} - -func (e *eventBinding) SetCodec(codec commontypes.RemoteCodec) { - e.codec = codec -} - -func (e *eventBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { - // it's enough to just lock bound here since Register/Unregister are only called from here and from Start/Close - // even if they somehow happen at the same time it will be fine because of filter lock and hasFilter check - e.bindLock.Lock() - defer e.bindLock.Unlock() - - if e.bound { - // we are changing contract address reference, so we need to unregister old filter it exists - if err := e.Unregister(ctx); err != nil { - return err - } - } - - e.address = common.HexToAddress(binding.Address) - - // filterRegisterer isn't required here because the event can also be polled for by the contractBinding common filter. - if e.filterRegisterer != nil { - id := fmt.Sprintf("%s.%s.%s", e.contractName, e.eventName, uuid.NewString()) - e.pollingFilter.Name = logpoller.FilterName(id, e.address) - e.pollingFilter.Addresses = evmtypes.AddressArray{e.address} - e.bound = true - if e.registerCalled { - return e.Register(ctx) - } - } - e.bound = true - return nil -} - -func (e *eventBinding) Register(ctx context.Context) error { - if e.filterRegisterer == nil { - return nil - } - - e.filterLock.Lock() - defer e.filterLock.Unlock() - - e.registerCalled = true - // can't be true before filters params are set so there is no race with a bad filter outcome - if !e.bound { - return nil - } - - if e.lp.HasFilter(e.pollingFilter.Name) { - return nil - } - - if err := e.lp.RegisterFilter(ctx, e.pollingFilter); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - - return nil -} - -func (e *eventBinding) Unregister(ctx context.Context) error { - if e.filterRegisterer == nil { - return nil - } - - e.filterLock.Lock() - defer e.filterLock.Unlock() - - if !e.bound { - return nil - } - - if !e.lp.HasFilter(e.pollingFilter.Name) { - return nil - } - - if err := e.lp.UnregisterFilter(ctx, e.pollingFilter.Name); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - - return nil -} - -func (e *eventBinding) GetLatestValue(ctx context.Context, confidenceLevel primitives.ConfidenceLevel, params, into any) error { - if err := e.validateBound(); err != nil { - return err - } - - confirmations, err := confidenceToConfirmations(e.confirmationsMapping, confidenceLevel) - if err != nil { - return err - } - - if len(e.inputInfo.Args()) == 0 { - return e.getLatestValueWithoutFilters(ctx, confirmations, into) - } - - return e.getLatestValueWithFilters(ctx, confirmations, params, into) -} - -func (e *eventBinding) QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { - if err := e.validateBound(); err != nil { - return nil, err - } - - remapped, err := e.remap(filter) - if err != nil { - return nil, err - } - - // filter should always use the address and event sig - defaultExpressions := []query.Expression{ - logpoller.NewAddressFilter(e.address), - logpoller.NewEventSigFilter(e.hash), - } - remapped.Expressions = append(defaultExpressions, remapped.Expressions...) - - logs, err := e.lp.FilteredLogs(ctx, remapped, limitAndSort, e.contractName+"-"+e.address.String()+"-"+e.eventName) - if err != nil { - return nil, err - } - - // no need to return an error. an empty list is fine - if len(logs) == 0 { - return []commontypes.Sequence{}, nil - } - - return e.decodeLogsIntoSequences(ctx, logs, sequenceDataType) -} - -func (e *eventBinding) validateBound() error { - if !e.bound { - return fmt.Errorf( - "%w: event %s that belongs to contract: %s, not bound", - commontypes.ErrInvalidType, - e.eventName, - e.contractName, - ) - } - return nil -} - -func (e *eventBinding) getLatestValueWithoutFilters(ctx context.Context, confs evmtypes.Confirmations, into any) error { - log, err := e.lp.LatestLogByEventSigWithConfs(ctx, e.hash, e.address, confs) - if err = wrapInternalErr(err); err != nil { - return err - } - - return e.decodeLog(ctx, log, into) -} - -func (e *eventBinding) getLatestValueWithFilters( - ctx context.Context, confs evmtypes.Confirmations, params, into any) error { - offChain, err := e.convertToOffChainType(params) - if err != nil { - return err - } - - // convert caller chain agnostic params types to types representing onchain abi types, for e.g. bytes32. - checkedParams, err := e.inputModifier.TransformToOnChain(offChain, "" /* unused */) - if err != nil { - return err - } - - // convert onchain params to native types similarly to generated abi wrappers, for e.g. fixed bytes32 abi type to [32]uint8. - nativeParams, err := e.inputInfo.ToNative(reflect.ValueOf(checkedParams)) - if err != nil { - return err - } - - filtersAndIndices, err := e.encodeParams(nativeParams) - if err != nil { - return err - } - - // Create limiter and filter for the query. - limiter := query.NewLimitAndSort(query.CountLimit(1), query.NewSortBySequence(query.Desc)) - filter, err := query.Where( - "", - logpoller.NewAddressFilter(e.address), - logpoller.NewEventSigFilter(e.hash), - logpoller.NewConfirmationsFilter(confs), - createTopicFilters(filtersAndIndices), - ) - if err != nil { - return wrapInternalErr(err) - } - - // Gets the latest log that matches the filter and limiter. - logs, err := e.lp.FilteredLogs(ctx, filter, limiter, e.contractName+"-"+e.address.String()+"-"+e.eventName) - if err != nil { - return wrapInternalErr(err) - } - - if len(logs) == 0 { - return fmt.Errorf("%w: no events found", commontypes.ErrNotFound) - } - - return e.decodeLog(ctx, &logs[0], into) -} - -func createTopicFilters(filtersAndIndices []common.Hash) query.Expression { - var expressions []query.Expression - for topicID, fai := range filtersAndIndices { - // first topic index is 1-based, so we add 1. - expressions = append(expressions, logpoller.NewEventByTopicFilter( - uint64(topicID+1), []primitives.ValueComparator{{Value: fai.Hex(), Operator: primitives.Eq}}, - )) - } - return query.And(expressions...) -} - -// convertToOffChainType creates a struct based on contract abi with applied codec modifiers. -// Created type shouldn't have hashed types for indexed topics since incoming params wouldn't be hashed. -func (e *eventBinding) convertToOffChainType(params any) (any, error) { - offChain, err := e.codec.CreateType(WrapItemType(e.contractName, e.eventName, true), true) - if err != nil { - return nil, err - } - - if err = mapstructureDecode(params, offChain); err != nil { - return nil, err - } - - return offChain, nil -} - -// encodeParams accepts nativeParams and encodes them to match onchain topics. -func (e *eventBinding) encodeParams(nativeParams reflect.Value) ([]common.Hash, error) { - for nativeParams.Kind() == reflect.Pointer { - nativeParams = reflect.Indirect(nativeParams) - } - - var params []any - switch nativeParams.Kind() { - case reflect.Array, reflect.Slice: - native, err := representArray(nativeParams, e.inputInfo) - if err != nil { - return nil, err - } - params = []any{native} - case reflect.Struct, reflect.Map: - var err error - if params, err = unrollItem(nativeParams, e.inputInfo); err != nil { - return nil, err - } - default: - return nil, fmt.Errorf("%w: cannot encode kind %v", commontypes.ErrInvalidType, nativeParams.Kind()) - } - - // abi params allow you to Pack a pointers, but makeTopics doesn't work with pointers. - if err := e.derefTopics(params); err != nil { - return nil, err - } - - return e.makeTopics(params) -} - -func (e *eventBinding) derefTopics(topics []any) error { - for i, topic := range topics { - rTopic := reflect.ValueOf(topic) - if rTopic.Kind() == reflect.Pointer { - if rTopic.IsNil() { - return fmt.Errorf( - "%w: input topic %s cannot be nil", commontypes.ErrInvalidType, e.inputInfo.Args()[i].Name) - } - topics[i] = rTopic.Elem().Interface() - } - } - return nil -} - -// makeTopics encodes and hashes params filtering values to match onchain indexed topics. -func (e *eventBinding) makeTopics(params []any) ([]common.Hash, error) { - // make topic value for non-fixed bytes array manually because geth MakeTopics doesn't support it - for i, topic := range params { - if abiArg := e.inputInfo.Args()[i]; abiArg.Type.T == abi.ArrayTy && (abiArg.Type.Elem != nil && abiArg.Type.Elem.T == abi.UintTy) { - packed, err := abi.Arguments{abiArg}.Pack(topic) - if err != nil { - return nil, err - } - params[i] = crypto.Keccak256Hash(packed) - } - } - - hashes, err := abi.MakeTopics(params) - if err != nil { - return nil, wrapInternalErr(err) - } - - if len(hashes) != 1 { - return nil, fmt.Errorf("%w: expected 1 filter set, got %d", commontypes.ErrInternal, len(hashes)) - } - - return hashes[0], nil -} - -func (e *eventBinding) decodeLog(ctx context.Context, log *logpoller.Log, into any) error { - // decode non indexed topics and apply output modifiers - if err := e.codec.Decode(ctx, log.Data, into, WrapItemType(e.contractName, e.eventName, false)); err != nil { - return err - } - - // decode indexed topics which is rarely useful since most indexed topic types get Keccak256 hashed and should be just used for log filtering. - topics := make([]common.Hash, len(e.codecTopicInfo.Args())) - if len(log.Topics) < len(topics)+1 { - return fmt.Errorf("%w: not enough topics to decode", commontypes.ErrInvalidType) - } - - for i := 0; i < len(topics); i++ { - topics[i] = common.Hash(log.Topics[i+1]) - } - - topicsInto := map[string]any{} - if err := abi.ParseTopicsIntoMap(topicsInto, e.codecTopicInfo.Args(), topics); err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInvalidType, err) - } - - return mapstructureDecode(topicsInto, into) -} - -func (e *eventBinding) decodeLogsIntoSequences(ctx context.Context, logs []logpoller.Log, into any) ([]commontypes.Sequence, error) { - sequences := make([]commontypes.Sequence, len(logs)) - - for idx := range logs { - sequences[idx] = commontypes.Sequence{ - Cursor: fmt.Sprintf("%s-%s-%d", logs[idx].BlockHash, logs[idx].TxHash, logs[idx].LogIndex), - Head: commontypes.Head{ - Identifier: fmt.Sprint(logs[idx].BlockNumber), - Hash: logs[idx].BlockHash.Bytes(), - Timestamp: uint64(logs[idx].BlockTimestamp.Unix()), - }, - } - - var typeVal reflect.Value - - typeInto := reflect.TypeOf(into) - if typeInto.Kind() == reflect.Pointer { - typeVal = reflect.New(typeInto.Elem()) - } else { - typeVal = reflect.Indirect(reflect.New(typeInto)) - } - - // create a new value of the same type as 'into' for the data to be extracted to - sequences[idx].Data = typeVal.Interface() - - if err := e.decodeLog(ctx, &logs[idx], sequences[idx].Data); err != nil { - return nil, err - } - } - - return sequences, nil -} - -func (e *eventBinding) remap(filter query.KeyFilter) (query.KeyFilter, error) { - remapped := query.KeyFilter{} - - for _, expression := range filter.Expressions { - remappedExpression, err := e.remapExpression(filter.Key, expression) - if err != nil { - return query.KeyFilter{}, err - } - - remapped.Expressions = append(remapped.Expressions, remappedExpression) - } - - return remapped, nil -} - -func (e *eventBinding) remapExpression(key string, expression query.Expression) (query.Expression, error) { - if !expression.IsPrimitive() { - remappedBoolExpressions := make([]query.Expression, len(expression.BoolExpression.Expressions)) - - for i := range expression.BoolExpression.Expressions { - remapped, err := e.remapExpression(key, expression.BoolExpression.Expressions[i]) - if err != nil { - return query.Expression{}, err - } - - remappedBoolExpressions[i] = remapped - } - - if expression.BoolExpression.BoolOperator == query.AND { - return query.And(remappedBoolExpressions...), nil - } - - return query.Or(remappedBoolExpressions...), nil - } - - return e.remapPrimitive(key, expression) -} - -// remap chain agnostic primitives to chain specific -func (e *eventBinding) remapPrimitive(key string, expression query.Expression) (query.Expression, error) { - switch primitive := expression.Primitive.(type) { - // TODO comparator primitive should undergo codec transformations and do hashed types handling similarly to how GetLatestValue handles it BCI-3910 - case *primitives.Comparator: - if val, ok := e.eventDataWords[primitive.Name]; ok { - return logpoller.NewEventByWordFilter(e.hash, val, primitive.ValueComparators), nil - } - return logpoller.NewEventByTopicFilter(e.topics[key].Index, primitive.ValueComparators), nil - case *primitives.Confidence: - confirmations, err := confidenceToConfirmations(e.confirmationsMapping, primitive.ConfidenceLevel) - if err != nil { - return query.Expression{}, err - } - return logpoller.NewConfirmationsFilter(confirmations), nil - default: - return expression, nil - } -} - -func wrapInternalErr(err error) error { - if err == nil { - return nil - } - - errStr := err.Error() - if strings.Contains(errStr, "not found") || strings.Contains(errStr, "no rows") { - return fmt.Errorf("%w: %w", commontypes.ErrNotFound, err) - } - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) -} diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index e310464a556..19be4b670b3 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -7,18 +7,12 @@ import ( "encoding/json" "errors" "fmt" + "io" "math/big" + "net/http" "strings" "sync" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - - "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" - cciptransmitter "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/transmitter" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" @@ -30,31 +24,41 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median/evmreportcodec" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + chainselectors "github.com/smartcontractkit/chain-selectors" + ocr3capability "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" + "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" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" - reportcodecv4 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v4/reportcodec" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txm "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/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/logger" "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/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" + 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/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" reportcodecv2 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v2/reportcodec" reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" + reportcodecv4 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v4/reportcodec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -62,7 +66,7 @@ import ( var ( OCR2AggregatorTransmissionContractABI abi.ABI OCR2AggregatorLogDecoder LogDecoder - ChannelVerifierLogDecoder LogDecoder + OCR3CapabilityLogDecoder LogDecoder ) func init() { @@ -75,7 +79,7 @@ func init() { if err != nil { panic(err) } - ChannelVerifierLogDecoder, err = newChannelVerifierLogDecoder() + OCR3CapabilityLogDecoder, err = newOCR3CapabilityLogDecoder() if err != nil { panic(err) } @@ -92,11 +96,11 @@ var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck // [UnimplementedOffchainConfigDigester] satisfies the OCR OffchainConfigDigester interface type UnimplementedOffchainConfigDigester struct{} -func (e UnimplementedOffchainConfigDigester) ConfigDigest(config ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { +func (e UnimplementedOffchainConfigDigester) ConfigDigest(ctx context.Context, config ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { return ocrtypes.ConfigDigest{}, fmt.Errorf("unimplemented for this relayer") } -func (e UnimplementedOffchainConfigDigester) ConfigDigestPrefix() (ocrtypes.ConfigDigestPrefix, error) { +func (e UnimplementedOffchainConfigDigester) ConfigDigestPrefix(ctx context.Context) (ocrtypes.ConfigDigestPrefix, error) { return 0, fmt.Errorf("unimplemented for this relayer") } @@ -126,7 +130,7 @@ func (u UnimplementedContractTransmitter) Transmit(context.Context, ocrtypes.Rep return fmt.Errorf("unimplemented for this relayer") } -func (u UnimplementedContractTransmitter) FromAccount() (ocrtypes.Account, error) { +func (u UnimplementedContractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { return "", fmt.Errorf("unimplemented for this relayer") } @@ -137,10 +141,9 @@ func (u UnimplementedContractTransmitter) LatestConfigDigestAndEpoch(ctx context type Relayer struct { ds sqlutil.DataSource chain legacyevm.Chain - lggr logger.Logger + lggr logger.SugaredLogger ks CSAETHKeystore mercuryPool wsrpc.Pool - chainReader commontypes.ContractReader codec commontypes.Codec capabilitiesRegistry coretypes.CapabilitiesRegistry @@ -150,8 +153,8 @@ type Relayer struct { triggerCapability *triggers.MercuryTriggerService // LLO/data streams - cdcFactory llo.ChannelDefinitionCacheFactory - lloORM llo.ORM + cdcFactory func() (llo.ChannelDefinitionCacheFactory, error) + retirementReportCache llo.RetirementReportCache } type CSAETHKeystore interface { @@ -162,9 +165,11 @@ type CSAETHKeystore interface { type RelayerOpts struct { DS sqlutil.DataSource CSAETHKeystore - MercuryPool wsrpc.Pool - TransmitterConfig mercury.TransmitterConfig - CapabilitiesRegistry coretypes.CapabilitiesRegistry + MercuryPool wsrpc.Pool + RetirementReportCache llo.RetirementReportCache + TransmitterConfig mercury.TransmitterConfig + CapabilitiesRegistry coretypes.CapabilitiesRegistry + HTTPClient *http.Client } func (c RelayerOpts) Validate() error { @@ -184,33 +189,42 @@ func (c RelayerOpts) Validate() error { return err } -func NewRelayer(lggr logger.Logger, chain legacyevm.Chain, opts RelayerOpts) (*Relayer, error) { +func NewRelayer(ctx context.Context, lggr logger.Logger, chain legacyevm.Chain, opts RelayerOpts) (*Relayer, error) { err := opts.Validate() if err != nil { return nil, fmt.Errorf("cannot create evm relayer: %w", err) } - lggr = lggr.Named("Relayer") - + sugared := logger.Sugared(lggr).Named("Relayer") mercuryORM := mercury.NewORM(opts.DS) - lloORM := llo.NewORM(opts.DS, chain.ID()) - cdcFactory := llo.NewChannelDefinitionCacheFactory(lggr, lloORM, chain.LogPoller()) + cdcFactory := sync.OnceValues(func() (llo.ChannelDefinitionCacheFactory, error) { + chainSelector, err := chainselectors.SelectorFromChainId(chain.ID().Uint64()) + if err != nil { + return nil, fmt.Errorf("failed to get chain selector for chain id %s: %w", chain.ID(), err) + } + lloORM := llo.NewChainScopedORM(opts.DS, chainSelector) + return llo.NewChannelDefinitionCacheFactory(sugared, lloORM, chain.LogPoller(), opts.HTTPClient), nil + }) relayer := &Relayer{ - ds: opts.DS, - chain: chain, - lggr: lggr, - ks: opts.CSAETHKeystore, - mercuryPool: opts.MercuryPool, - cdcFactory: cdcFactory, - lloORM: lloORM, - mercuryORM: mercuryORM, - transmitterCfg: opts.TransmitterConfig, - capabilitiesRegistry: opts.CapabilitiesRegistry, + ds: opts.DS, + chain: chain, + lggr: sugared, + ks: opts.CSAETHKeystore, + mercuryPool: opts.MercuryPool, + cdcFactory: cdcFactory, + retirementReportCache: opts.RetirementReportCache, + mercuryORM: mercuryORM, + transmitterCfg: opts.TransmitterConfig, + capabilitiesRegistry: opts.CapabilitiesRegistry, } // Initialize write target capability if configuration is defined if chain.Config().EVM().Workflow().ForwarderAddress() != nil { - ctx := context.Background() - capability, err := NewWriteTarget(ctx, relayer, chain, lggr) + if chain.Config().EVM().Workflow().GasLimitDefault() == nil { + return nil, fmt.Errorf("unable to instantiate write target as default gas limit is not set") + } + + capability, err := NewWriteTarget(ctx, relayer, chain, *chain.Config().EVM().Workflow().GasLimitDefault(), + lggr) if err != nil { return nil, fmt.Errorf("failed to initialize write target: %w", err) } @@ -227,16 +241,17 @@ func (r *Relayer) Name() string { return r.lggr.Name() } -// Start does noop: no subservices started on relay start, but when the first job is started -func (r *Relayer) Start(context.Context) error { - return nil +func (r *Relayer) Start(ctx context.Context) error { + return r.chain.Start(ctx) } func (r *Relayer) Close() error { + cs := make([]io.Closer, 0, 2) if r.triggerCapability != nil { - return r.triggerCapability.Close() + cs = append(cs, r.triggerCapability) } - return nil + cs = append(cs, r.chain) + return services.MultiCloser(cs).Close() } // Ready does noop: always ready @@ -245,18 +260,85 @@ func (r *Relayer) Ready() error { } func (r *Relayer) HealthReport() (report map[string]error) { - report = make(map[string]error) + report = map[string]error{r.Name(): r.Ready()} maps.Copy(report, r.chain.HealthReport()) return } -func (r *Relayer) NewOCR3CapabilityProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.OCR3CapabilityProvider, error) { - pp, err := r.NewPluginProvider(rargs, pargs) +func (r *Relayer) LatestHead(ctx context.Context) (commontypes.Head, error) { + return r.chain.LatestHead(ctx) +} + +func (r *Relayer) GetChainStatus(ctx context.Context) (commontypes.ChainStatus, error) { + return r.chain.GetChainStatus(ctx) +} + +func (r *Relayer) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []commontypes.NodeStatus, nextPageToken string, total int, err error) { + return r.chain.ListNodeStatuses(ctx, pageSize, pageToken) +} + +func (r *Relayer) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error { + return r.chain.Transact(ctx, from, to, amount, balanceCheck) +} + +func (r *Relayer) ID() string { + return r.chain.ID().String() +} + +func (r *Relayer) Chain() legacyevm.Chain { + return r.chain +} + +func newOCR3CapabilityConfigProvider(ctx context.Context, lggr logger.Logger, chain legacyevm.Chain, opts *types.RelayOpts) (*configWatcher, error) { + if !common.IsHexAddress(opts.ContractID) { + return nil, errors.New("invalid contractID, expected hex address") + } + + aggregatorAddress := common.HexToAddress(opts.ContractID) + offchainConfigDigester := OCR3CapabilityOffchainConfigDigester{ + ChainID: chain.Config().EVM().ChainID().Uint64(), + ContractAddress: aggregatorAddress, + } + return newContractConfigProvider(ctx, lggr, chain, opts, aggregatorAddress, OCR3CapabilityLogDecoder, offchainConfigDigester) +} + +// NewPluginProvider, but customized to use a different config provider +func (r *Relayer) NewOCR3CapabilityProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.OCR3CapabilityProvider, error) { + lggr := logger.Sugared(r.lggr).Named("PluginProvider").Named(rargs.ExternalJobID.String()) + relayOpts := types.NewRelayOpts(rargs) + relayConfig, err := relayOpts.RelayConfig() + if err != nil { + return nil, fmt.Errorf("failed to get relay config: %w", err) + } + + configWatcher, err := newOCR3CapabilityConfigProvider(ctx, r.lggr, r.chain, relayOpts) + if err != nil { + return nil, err + } + + transmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI) if err != nil { return nil, err } - fromAccount, err := pp.ContractTransmitter().FromAccount() + var chainReaderService ChainReaderService + if relayConfig.ChainReader != nil { + if chainReaderService, err = NewChainReaderService(ctx, lggr, r.chain.LogPoller(), r.chain.HeadTracker(), r.chain.Client(), *relayConfig.ChainReader); err != nil { + return nil, err + } + } else { + lggr.Info("ChainReader missing from RelayConfig") + } + + pp := NewPluginProvider( + chainReaderService, + r.codec, + transmitter, + configWatcher, + lggr, + ) + + fromAccount, err := pp.ContractTransmitter().FromAccount(ctx) if err != nil { return nil, err } @@ -267,13 +349,15 @@ func (r *Relayer) NewOCR3CapabilityProvider(rargs commontypes.RelayArgs, pargs c }, nil } -func (r *Relayer) NewPluginProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.PluginProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - - lggr := r.lggr.Named("PluginProvider").Named(rargs.ExternalJobID.String()) +func (r *Relayer) NewPluginProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.PluginProvider, error) { + lggr := logger.Sugared(r.lggr).Named("PluginProvider").Named(rargs.ExternalJobID.String()) + relayOpts := types.NewRelayOpts(rargs) + relayConfig, err := relayOpts.RelayConfig() + if err != nil { + return nil, fmt.Errorf("failed to get relay config: %w", err) + } - configWatcher, err := newStandardConfigProvider(ctx, r.lggr, r.chain, types.NewRelayOpts(rargs)) + configWatcher, err := newStandardConfigProvider(ctx, r.lggr, r.chain, relayOpts) if err != nil { return nil, err } @@ -283,8 +367,17 @@ func (r *Relayer) NewPluginProvider(rargs commontypes.RelayArgs, pargs commontyp return nil, err } + var chainReaderService ChainReaderService + if relayConfig.ChainReader != nil { + if chainReaderService, err = NewChainReaderService(ctx, lggr, r.chain.LogPoller(), r.chain.HeadTracker(), r.chain.Client(), *relayConfig.ChainReader); err != nil { + return nil, err + } + } else { + lggr.Info("ChainReader missing from RelayConfig") + } + return NewPluginProvider( - r.chainReader, + chainReaderService, r.codec, transmitter, configWatcher, @@ -292,10 +385,8 @@ func (r *Relayer) NewPluginProvider(rargs commontypes.RelayArgs, pargs commontyp ), nil } -func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MercuryProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - lggr := r.lggr.Named("MercuryProvider").Named(rargs.ExternalJobID.String()) +func (r *Relayer) NewMercuryProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MercuryProvider, error) { + lggr := logger.Sugared(r.lggr).Named("MercuryProvider").Named(rargs.ExternalJobID.String()) relayOpts := types.NewRelayOpts(rargs) relayConfig, err := relayOpts.RelayConfig() if err != nil { @@ -310,7 +401,6 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty if relayConfig.FeedID == nil { return nil, pkgerrors.New("FeedID must be specified") } - feedID := mercuryutils.FeedID(*relayConfig.FeedID) if relayConfig.ChainID.String() != r.chain.ID().String() { return nil, fmt.Errorf("internal error: chain id in spec does not match this relayer's chain: have %s expected %s", relayConfig.ChainID.String(), r.chain.ID().String()) @@ -330,11 +420,10 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty clients := make(map[string]wsrpc.Client) for _, server := range mercuryConfig.GetServers() { - client, err := r.mercuryPool.Checkout(context.Background(), privKey, server.PubKey, server.URL) + clients[server.URL], err = r.mercuryPool.Checkout(ctx, privKey, server.PubKey, server.URL) if err != nil { return nil, err } - clients[server.URL] = client } // initialize trigger capability service lazily @@ -361,28 +450,42 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty reportCodecV3 := reportcodecv3.NewReportCodec(*relayConfig.FeedID, lggr.Named("ReportCodecV3")) reportCodecV4 := reportcodecv4.NewReportCodec(*relayConfig.FeedID, lggr.Named("ReportCodecV4")) - var transmitterCodec mercury.TransmitterReportDecoder - switch feedID.Version() { - case 1: - transmitterCodec = reportCodecV1 - case 2: - transmitterCodec = reportCodecV2 - case 3: - transmitterCodec = reportCodecV3 - case 4: - transmitterCodec = reportCodecV4 - default: - return nil, fmt.Errorf("invalid feed version %d", feedID.Version()) + getCodecForFeed := func(feedID mercuryutils.FeedID) (mercury.TransmitterReportDecoder, error) { + var transmitterCodec mercury.TransmitterReportDecoder + switch feedID.Version() { + case 1: + transmitterCodec = reportCodecV1 + case 2: + transmitterCodec = reportCodecV2 + case 3: + transmitterCodec = reportCodecV3 + case 4: + transmitterCodec = reportCodecV4 + default: + return nil, fmt.Errorf("invalid feed version %d", feedID.Version()) + } + return transmitterCodec, nil } - transmitter := mercury.NewTransmitter(lggr, r.transmitterCfg, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec, r.triggerCapability) - return NewMercuryProvider(cp, r.chainReader, r.codec, NewMercuryChainReader(r.chain.HeadTracker()), transmitter, reportCodecV1, reportCodecV2, reportCodecV3, reportCodecV4, lggr), nil -} + benchmarkPriceDecoder := func(ctx context.Context, feedID mercuryutils.FeedID, report ocrtypes.Report) (*big.Int, error) { + benchmarkPriceCodec, benchmarkPriceErr := getCodecForFeed(feedID) + if benchmarkPriceErr != nil { + return nil, benchmarkPriceErr + } + return benchmarkPriceCodec.BenchmarkPriceFromReport(ctx, report) + } + + transmitterCodec, err := getCodecForFeed(mercuryutils.FeedID(*relayConfig.FeedID)) + if err != nil { + return nil, err + } + + transmitter := mercury.NewTransmitter(lggr, r.transmitterCfg, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec, benchmarkPriceDecoder, r.triggerCapability) -func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.LLOProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() + return NewMercuryProvider(cp, r.codec, NewMercuryChainReader(r.chain.HeadTracker()), transmitter, reportCodecV1, reportCodecV2, reportCodecV3, reportCodecV4, lggr), nil +} +func (r *Relayer) NewLLOProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.LLOProvider, error) { relayOpts := types.NewRelayOpts(rargs) var relayConfig types.RelayConfig { @@ -392,6 +495,14 @@ func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes. return nil, fmt.Errorf("failed to get relay config: %w", err) } } + if relayConfig.LLODONID == 0 { + return nil, errors.New("donID must be specified in relayConfig for LLO jobs") + } + switch relayConfig.LLOConfigMode { + case types.LLOConfigModeMercury, types.LLOConfigModeBlueGreen: + default: + return nil, fmt.Errorf("LLOConfigMode must be specified in relayConfig for LLO jobs (only %q or %q is currently supported)", types.LLOConfigModeMercury, types.LLOConfigModeBlueGreen) + } var lloCfg lloconfig.PluginConfig if err := json.Unmarshal(pargs.PluginConfig, &lloCfg); err != nil { @@ -400,15 +511,19 @@ func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes. if err := lloCfg.Validate(); err != nil { return nil, err } - + relayConfig, err := relayOpts.RelayConfig() + if err != nil { + return nil, fmt.Errorf("failed to get relay config: %w", err) + } + if relayConfig.LLODONID == 0 { + return nil, errors.New("donID must be specified in relayConfig for LLO jobs") + } + if relayConfig.LLOConfigMode == "" { + return nil, fmt.Errorf("LLOConfigMode must be specified in relayConfig for LLO jobs (can be either: %q or %q)", types.LLOConfigModeMercury, types.LLOConfigModeBlueGreen) + } if relayConfig.ChainID.String() != r.chain.ID().String() { return nil, fmt.Errorf("internal error: chain id in spec does not match this relayer's chain: have %s expected %s", relayConfig.ChainID.String(), r.chain.ID().String()) } - cp, err := newLLOConfigProvider(ctx, r.lggr, r.chain, relayOpts) - if err != nil { - return nil, pkgerrors.WithStack(err) - } - if !relayConfig.EffectiveTransmitterID.Valid { return nil, pkgerrors.New("EffectiveTransmitterID must be specified") } @@ -419,40 +534,55 @@ func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes. // FIXME: Remove after benchmarking is done // https://smartcontract-it.atlassian.net/browse/MERC-3487 - var transmitter llo.Transmitter + var transmitter LLOTransmitter if lloCfg.BenchmarkMode { 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 { - var client wsrpc.Client - client, err = r.mercuryPool.Checkout(context.Background(), privKey, lloCfg.ServerPubKey, lloCfg.ServerURL()) - if err != nil { - return nil, err + clients := make(map[string]wsrpc.Client) + for _, server := range lloCfg.GetServers() { + client, err2 := r.mercuryPool.Checkout(ctx, privKey, server.PubKey, server.URL) + if err2 != nil { + return nil, err2 + } + clients[server.URL] = client } - transmitter = llo.NewTransmitter(r.lggr, client, privKey.PublicKey) + transmitter = llo.NewTransmitter(llo.TransmitterOpts{ + Lggr: r.lggr, + FromAccount: fmt.Sprintf("%x", privKey.PublicKey), // NOTE: This may need to change if we support e.g. multiple tranmsmitters, to be a composite of all keys + MercuryTransmitterOpts: mercurytransmitter.Opts{ + Lggr: r.lggr, + Cfg: r.transmitterCfg, + Clients: clients, + FromAccount: privKey.PublicKey, + DonID: relayConfig.LLODONID, + ORM: mercurytransmitter.NewORM(r.ds, relayConfig.LLODONID), + }, + RetirementReportCache: r.retirementReportCache, + }) + } + + cdcFactory, err := r.cdcFactory() + if err != nil { + return nil, err } - - cdc, err := r.cdcFactory.NewCache(lloCfg) + cdc, err := cdcFactory.NewCache(lloCfg) if err != nil { return nil, err } - return NewLLOProvider(cp, transmitter, r.lggr, cdc), nil -} -func (r *Relayer) NewFunctionsProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.FunctionsProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() + configuratorAddress := common.HexToAddress(relayOpts.ContractID) + return NewLLOProvider(context.Background(), transmitter, r.lggr, r.retirementReportCache, r.chain, configuratorAddress, cdc, relayConfig, relayOpts) +} +func (r *Relayer) NewFunctionsProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.FunctionsProvider, error) { lggr := r.lggr.Named("FunctionsProvider").Named(rargs.ExternalJobID.String()) // TODO(FUN-668): Not ready yet (doesn't implement FunctionsEvents() properly) return NewFunctionsProvider(ctx, r.chain, rargs, pargs, lggr, r.ks.Eth(), functions.FunctionsPlugin) } // NewConfigProvider is called by bootstrap jobs -func (r *Relayer) NewConfigProvider(args commontypes.RelayArgs) (configProvider commontypes.ConfigProvider, err error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - +func (r *Relayer) NewConfigProvider(ctx context.Context, args commontypes.RelayArgs) (configProvider commontypes.ConfigProvider, err error) { lggr := r.lggr.Named("ConfigProvider").Named(args.ExternalJobID.String()) relayOpts := types.NewRelayOpts(args) relayConfig, err := relayOpts.RelayConfig() @@ -469,6 +599,8 @@ func (r *Relayer) NewConfigProvider(args commontypes.RelayArgs) (configProvider if args.ProviderType == "" { if relayConfig.FeedID == nil { args.ProviderType = "median" + } else if relayConfig.LLODONID > 0 { + args.ProviderType = "llo" } else { args.ProviderType = "mercury" } @@ -480,7 +612,12 @@ func (r *Relayer) NewConfigProvider(args commontypes.RelayArgs) (configProvider case "mercury": configProvider, err = newMercuryConfigProvider(ctx, lggr, r.chain, relayOpts) case "llo": - configProvider, err = newLLOConfigProvider(ctx, lggr, r.chain, relayOpts) + // Use NullRetirementReportCache since we never run LLO jobs on + // bootstrap nodes, and there's no need to introduce a failure mode or + // performance hit no matter how minor. + configProvider, err = newLLOConfigProvider(ctx, lggr, r.chain, &llo.NullRetirementReportCache{}, relayOpts) + case "ocr3-capability": + configProvider, err = newOCR3CapabilityConfigProvider(ctx, r.lggr, r.chain, relayOpts) default: return nil, fmt.Errorf("unrecognized provider type: %q", args.ProviderType) } @@ -511,16 +648,15 @@ func FilterNamesFromRelayArgs(args commontypes.RelayArgs) (filterNames []string, } type configWatcher struct { - services.StateMachine - lggr logger.Logger + services.Service + eng *services.Engine + contractAddress common.Address offchainDigester ocrtypes.OffchainConfigDigester configPoller types.ConfigPoller chain legacyevm.Chain runReplay bool fromBlock uint64 - stopCh services.StopChan - wg sync.WaitGroup } func newConfigWatcher(lggr logger.Logger, @@ -531,54 +667,41 @@ func newConfigWatcher(lggr logger.Logger, fromBlock uint64, runReplay bool, ) *configWatcher { - return &configWatcher{ - lggr: lggr.Named("ConfigWatcher").Named(contractAddress.String()), + cw := &configWatcher{ contractAddress: contractAddress, offchainDigester: offchainDigester, configPoller: configPoller, chain: chain, runReplay: runReplay, fromBlock: fromBlock, - stopCh: make(chan struct{}), } + cw.Service, cw.eng = services.Config{ + Name: fmt.Sprintf("ConfigWatcher.%s", contractAddress), + NewSubServices: nil, + Start: cw.start, + Close: cw.close, + }.NewServiceEngine(lggr) + return cw } -func (c *configWatcher) Name() string { - return c.lggr.Name() -} - -func (c *configWatcher) Start(ctx context.Context) error { - return c.StartOnce(fmt.Sprintf("configWatcher %x", c.contractAddress), func() error { - if c.runReplay && c.fromBlock != 0 { - // Only replay if it's a brand runReplay job. - c.wg.Add(1) - go func() { - defer c.wg.Done() - ctx, cancel := c.stopCh.NewCtx() - defer cancel() - c.lggr.Infow("starting replay for config", "fromBlock", c.fromBlock) - if err := c.configPoller.Replay(ctx, int64(c.fromBlock)); err != nil { - c.lggr.Errorw("error replaying for config", "err", err) - } else { - c.lggr.Infow("completed replaying for config", "fromBlock", c.fromBlock) - } - }() - } - c.configPoller.Start() - return nil - }) -} - -func (c *configWatcher) Close() error { - return c.StopOnce(fmt.Sprintf("configWatcher %x", c.contractAddress), func() error { - close(c.stopCh) - c.wg.Wait() - return c.configPoller.Close() - }) +func (c *configWatcher) start(ctx context.Context) error { + if c.runReplay && c.fromBlock != 0 { + // Only replay if it's a brand new job. + c.eng.Go(func(ctx context.Context) { + c.eng.Infow("starting replay for config", "fromBlock", c.fromBlock) + if err := c.configPoller.Replay(ctx, int64(c.fromBlock)); err != nil { + c.eng.Errorw("error replaying for config", "err", err) + } else { + c.eng.Infow("completed replaying for config", "fromBlock", c.fromBlock) + } + }) + } + c.configPoller.Start() + return nil } -func (c *configWatcher) HealthReport() map[string]error { - return map[string]error{c.Name(): c.Healthy()} +func (c *configWatcher) close() error { + return c.configPoller.Close() } func (c *configWatcher) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { @@ -718,8 +841,7 @@ func (r *Relayer) NewChainWriter(_ context.Context, config []byte) (commontypes. return NewChainWriterService(r.lggr, r.chain.Client(), r.chain.TxManager(), r.chain.GasEstimator(), cfg) } -func (r *Relayer) NewContractReader(chainReaderConfig []byte) (commontypes.ContractReader, error) { - ctx := context.Background() +func (r *Relayer) NewContractReader(ctx context.Context, chainReaderConfig []byte) (commontypes.ContractReader, error) { cfg := &types.ChainReaderConfig{} if err := json.Unmarshal(chainReaderConfig, cfg); err != nil { return nil, fmt.Errorf("failed to unmarshall chain reader config err: %s", err) @@ -728,11 +850,8 @@ func (r *Relayer) NewContractReader(chainReaderConfig []byte) (commontypes.Contr return NewChainReaderService(ctx, r.lggr, r.chain.LogPoller(), r.chain.HeadTracker(), r.chain.Client(), *cfg) } -func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MedianProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - - lggr := r.lggr.Named("MedianProvider").Named(rargs.ExternalJobID.String()) +func (r *Relayer) NewMedianProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.MedianProvider, error) { + lggr := logger.Sugared(r.lggr).Named("MedianProvider").Named(rargs.ExternalJobID.String()) relayOpts := types.NewRelayOpts(rargs) relayConfig, err := relayOpts.RelayConfig() if err != nil { @@ -759,7 +878,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp return nil, err } - medianContract, err := newMedianContract(configWatcher.ContractConfigTracker(), configWatcher.contractAddress, configWatcher.chain, rargs.JobID, r.ds, lggr) + medianContract, err := newMedianContract(configWatcher.ContractConfigTracker(), configWatcher.contractAddress, configWatcher.chain, rargs.JobID, rargs.OracleSpecID, r.ds, lggr) if err != nil { return nil, err } @@ -780,7 +899,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp } boundContracts := []commontypes.BoundContract{{Name: "median", Address: contractID.String()}} - if err = chainReaderService.Bind(context.Background(), boundContracts); err != nil { + if err = chainReaderService.Bind(ctx, boundContracts); err != nil { return nil, err } } else { @@ -789,7 +908,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp medianProvider.chainReader = chainReaderService if relayConfig.Codec != nil { - medianProvider.codec, err = NewCodec(*relayConfig.Codec) + medianProvider.codec, err = codec.NewCodec(*relayConfig.Codec) if err != nil { return nil, err } @@ -800,11 +919,11 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp return &medianProvider, nil } -func (r *Relayer) NewAutomationProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.AutomationProvider, error) { - lggr := r.lggr.Named("AutomationProvider").Named(rargs.ExternalJobID.String()) +func (r *Relayer) NewAutomationProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.AutomationProvider, error) { + lggr := logger.Sugared(r.lggr).Named("AutomationProvider").Named(rargs.ExternalJobID.String()) ocr2keeperRelayer := NewOCR2KeeperRelayer(r.ds, r.chain, lggr.Named("OCR2KeeperRelayer"), r.ks.Eth()) - return ocr2keeperRelayer.NewOCR2KeeperProvider(rargs, pargs) + return ocr2keeperRelayer.NewOCR2KeeperProvider(ctx, rargs, pargs) } func chainToUUID(chainID *big.Int) uuid.UUID { @@ -824,10 +943,7 @@ func chainToUUID(chainID *big.Int) uuid.UUID { // 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(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPCommitProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - +func (r *Relayer) NewCCIPCommitProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPCommitProvider, error) { versionFinder := ccip.NewEvmVersionFinder() var commitPluginConfig ccipconfig.CommitPluginConfig @@ -891,10 +1007,7 @@ func (r *Relayer) NewCCIPCommitProvider(rargs commontypes.RelayArgs, pargs commo // 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(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPExecProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - +func (r *Relayer) NewCCIPExecProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.CCIPExecProvider, error) { versionFinder := ccip.NewEvmVersionFinder() var execPluginConfig ccipconfig.ExecPluginConfig @@ -1021,7 +1134,7 @@ func (p *medianProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker return p.configWatcher.ContractConfigTracker() } -func (p *medianProvider) ChainReader() commontypes.ContractReader { +func (p *medianProvider) ContractReader() commontypes.ContractReader { return p.chainReader } diff --git a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go new file mode 100644 index 00000000000..72360afd167 --- /dev/null +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -0,0 +1,513 @@ +package evmtesting + +import ( + "context" + "encoding/json" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/libocr/commontypes" + + commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" + clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + + "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/internal/testutils/pgtest" // force binding for tx type + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +const ( + triggerWithDynamicTopic = "TriggeredEventWithDynamicTopic" + 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 + ChainID() *big.Int + Context(t T) context.Context + NewSqlxDB(t T) *sqlx.DB + MaxWaitTimeForEvents() time.Duration + GasPriceBufferPercent() int64 + Accounts(t T) []*bind.TransactOpts + TXM(T, client.Client) evmtxmgr.TxManager + // 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.ChainWriter, client client.Client) clcommontypes.ChainWriter +} + +type EVMChainComponentsInterfaceTester[T TestingT[T]] struct { + Helper EVMChainComponentsInterfaceTesterHelper[T] + 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 +} + +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.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] + + testStruct := CreateTestStruct[T](0, it) + + methodTakingLatestParamsReturningTestStructConfig := types.ChainReaderDefinition{ + ChainSpecificName: "getElementAtIndex", + OutputModifications: commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &commoncodec.AddressBytesToStringModifierConfig{ + Fields: []string{"AccountStr"}, + }, + }, + } + + it.chainReaderConfig = types.ChainReaderConfig{ + Contracts: map[string]types.ChainContractReader{ + AnyContractName: { + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{EventName, EventWithFilterName, triggerWithAllTopicsWithHashed, staticBytesEventName}, + }, + Configs: map[string]*types.ChainReaderDefinition{ + MethodTakingLatestParamsReturningTestStruct: &methodTakingLatestParamsReturningTestStructConfig, + MethodReturningAlterableUint64: { + ChainSpecificName: "getAlterablePrimitiveValue", + }, + MethodReturningUint64: { + ChainSpecificName: "getPrimitiveValue", + }, + MethodReturningUint64Slice: { + ChainSpecificName: "getSliceValue", + }, + EventName: { + ChainSpecificName: "Triggered", + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + GenericTopicNames: map[string]string{"field": "Field"}, + GenericDataWordDetails: map[string]types.DataWordDetail{ + "OracleID": {Name: "oracleId"}, + // this is just to illustrate an example, generic names shouldn't really be formatted like this since other chains might not store it in the same way + "NestedStaticStruct.Inner.IntVal": {Name: "nestedStaticStruct.Inner.IntVal"}, + "BigField": {Name: "bigField"}, + }, + }, + OutputModifications: commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &commoncodec.AddressBytesToStringModifierConfig{ + Fields: []string{"AccountStr"}, + }, + }, + }, + staticBytesEventName: { + ChainSpecificName: staticBytesEventName, + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + GenericDataWordDetails: map[string]types.DataWordDetail{ + "msgTransmitterEvent": { + Name: "msgTransmitterEvent", + Index: testutils.Ptr(2), + Type: "bytes32", + }, + }, + }, + }, + EventWithFilterName: { + ChainSpecificName: "Triggered", + ReadType: types.Event, + OutputModifications: commoncodec.ModifiersConfig{ + &commoncodec.AddressBytesToStringModifierConfig{ + Fields: []string{"AccountStr"}, + }, + }, + }, + triggerWithDynamicTopic: { + ChainSpecificName: triggerWithDynamicTopic, + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + // No specific reason for filter being defined here instead of on contract level, this is just for test case variety. + PollingFilter: &types.PollingFilter{}, + }, + InputModifications: commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"FieldHash": "Field"}}, + }, + }, + triggerWithAllTopics: { + ChainSpecificName: triggerWithAllTopics, + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + PollingFilter: &types.PollingFilter{}, + }, + // This doesn't have to be here, since the defalt mapping would work, but is left as an example. + // Keys which are string float values(confidence levels) are chain agnostic and should be reused across chains. + // These float values can map to different finality concepts across chains. + ConfidenceConfirmations: map[string]int{"0.0": int(evmtypes.Unconfirmed), "1.0": int(evmtypes.Finalized)}, + }, + triggerWithAllTopicsWithHashed: { + ChainSpecificName: triggerWithAllTopicsWithHashed, + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{}, + }, + MethodReturningSeenStruct: { + ChainSpecificName: "returnSeen", + InputModifications: commoncodec.ModifiersConfig{ + &commoncodec.HardCodeModifierConfig{ + OnChainValues: map[string]any{ + "BigField": testStruct.BigField.String(), + "Account": hexutil.Encode(testStruct.Account), + }, + }, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &commoncodec.AddressBytesToStringModifierConfig{ + Fields: []string{"AccountStr"}, + }, + }, + OutputModifications: commoncodec.ModifiersConfig{ + &commoncodec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &commoncodec.AddressBytesToStringModifierConfig{ + Fields: []string{"AccountStr"}, + }, + }, + }, + }, + }, + AnySecondContractName: { + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, + Configs: map[string]*types.ChainReaderDefinition{ + MethodTakingLatestParamsReturningTestStruct: &methodTakingLatestParamsReturningTestStructConfig, + MethodReturningUint64: { + ChainSpecificName: "getDifferentPrimitiveValue", + }, + }, + }, + }, + } + it.GetContractReader(t) + it.txm = it.Helper.TXM(t, it.client) + + it.chainWriterConfig = types.ChainWriterConfig{ + Contracts: map[string]*types.ContractConfig{ + AnyContractName: { + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, + Configs: map[string]*types.ChainWriterDefinition{ + "addTestStruct": { + ChainSpecificName: "addTestStruct", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + InputModifications: commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + }, + }, + "setAlterablePrimitiveValue": { + ChainSpecificName: "setAlterablePrimitiveValue", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + }, + "triggerEvent": { + ChainSpecificName: "triggerEvent", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + InputModifications: commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + }, + }, + "triggerEventWithDynamicTopic": { + ChainSpecificName: "triggerEventWithDynamicTopic", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + }, + "triggerWithFourTopics": { + ChainSpecificName: "triggerWithFourTopics", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + }, + "triggerWithFourTopicsWithHashed": { + ChainSpecificName: "triggerWithFourTopicsWithHashed", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + }, + "triggerStaticBytes": { + ChainSpecificName: "triggerStaticBytes", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + }, + }, + }, + AnySecondContractName: { + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, + Configs: map[string]*types.ChainWriterDefinition{ + "addTestStruct": { + ChainSpecificName: "addTestStruct", + FromAddress: it.Helper.Accounts(t)[1].From, + GasLimit: 2_000_000, + Checker: "simulate", + InputModifications: commoncodec.ModifiersConfig{ + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + }, + }, + }, + }, + }, + MaxGasPrice: assets.NewWei(big.NewInt(1000000000000000000)), + } + it.deployNewContracts(t) +} + +func (it *EVMChainComponentsInterfaceTester[T]) Name() string { + return "EVM" +} + +func (it *EVMChainComponentsInterfaceTester[T]) GetAccountBytes(i int) []byte { + account := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + account[i%20] += byte(i) + account[(i+3)%20] += byte(i + 3) + return account[:] +} + +func (it *EVMChainComponentsInterfaceTester[T]) GetAccountString(i int) string { + return common.BytesToAddress(it.GetAccountBytes(i)).Hex() +} + +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) + require.NoError(t, err) + + 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]) GetChainWriter(t T) clcommontypes.ChainWriter { + 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) + require.NoError(t, err) + it.cw = it.Helper.WrappedChainWriter(cw, it.client) + + require.NoError(t, err) + require.NoError(t, cw.Start(ctx)) + return it.cw +} + +func (it *EVMChainComponentsInterfaceTester[T]) GetBindings(_ T) []clcommontypes.BoundContract { + return []clcommontypes.BoundContract{ + {Name: AnyContractName, Address: it.address}, + {Name: AnySecondContractName, Address: it.address2}, + } +} + +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)) + 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)) + } +} + +func (it *EVMChainComponentsInterfaceTester[T]) AwaitTx(t T, tx *gethtypes.Transaction) { + ctx := it.Helper.Context(t) + receipt, err := bind.WaitMined(ctx, it.client, 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]) 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()) + require.NoError(t, err) + it.Helper.Commit() + + it.IncNonce() + it.AwaitTx(t, tx) + return address.String(), ts +} + +func (it *EVMChainComponentsInterfaceTester[T]) MaxWaitTimeForEvents() time.Duration { + return it.Helper.MaxWaitTimeForEvents() +} + +func OracleIDsToBytes(oracleIDs [32]commontypes.OracleID) [32]byte { + convertedIDs := [32]byte{} + for i, id := range oracleIDs { + convertedIDs[i] = byte(id) + } + return convertedIDs +} + +func ConvertAccounts(accounts [][]byte) []common.Address { + convertedAccounts := make([]common.Address, len(accounts)) + for i, a := range accounts { + convertedAccounts[i] = common.Address(a) + } + return convertedAccounts +} + +func ToInternalType(testStruct TestStruct) chain_reader_tester.TestStruct { + return chain_reader_tester.TestStruct{ + Field: *testStruct.Field, + DifferentField: testStruct.DifferentField, + OracleId: byte(testStruct.OracleID), + OracleIds: OracleIDsToBytes(testStruct.OracleIDs), + Account: common.Address(testStruct.Account), + AccountStr: common.HexToAddress(testStruct.AccountStr), + Accounts: ConvertAccounts(testStruct.Accounts), + BigField: testStruct.BigField, + NestedDynamicStruct: MidDynamicToInternalType(testStruct.NestedDynamicStruct), + NestedStaticStruct: MidStaticToInternalType(testStruct.NestedStaticStruct), + } +} + +func MidDynamicToInternalType(m MidLevelDynamicTestStruct) chain_reader_tester.MidLevelDynamicTestStruct { + return chain_reader_tester.MidLevelDynamicTestStruct{ + FixedBytes: m.FixedBytes, + Inner: chain_reader_tester.InnerDynamicTestStruct{ + IntVal: int64(m.Inner.I), + S: m.Inner.S, + }, + } +} + +func MidStaticToInternalType(m MidLevelStaticTestStruct) chain_reader_tester.MidLevelStaticTestStruct { + return chain_reader_tester.MidLevelStaticTestStruct{ + FixedBytes: m.FixedBytes, + Inner: chain_reader_tester.InnerStaticTestStruct{ + IntVal: int64(m.Inner.I), + A: common.BytesToAddress(m.Inner.A), + }, + } +} diff --git a/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go b/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go deleted file mode 100644 index 7812ab202b1..00000000000 --- a/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go +++ /dev/null @@ -1,435 +0,0 @@ -package evmtesting - -import ( - "context" - "encoding/json" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/libocr/commontypes" - - "github.com/smartcontractkit/chainlink-common/pkg/codec" - clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "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" - 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/internal/testutils/pgtest" // force binding for tx type - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" -) - -const ( - triggerWithDynamicTopic = "TriggeredEventWithDynamicTopic" - triggerWithAllTopics = "TriggeredWithFourTopics" - triggerWithAllTopicsWithHashed = "TriggeredWithFourTopicsWithHashed" - finalityDepth = 4 -) - -type EVMChainReaderInterfaceTesterHelper[T TestingT[T]] interface { - SetupAuth(t T) *bind.TransactOpts - Client(t T) client.Client - Commit() - Backend() bind.ContractBackend - ChainID() *big.Int - Context(t T) context.Context - NewSqlxDB(t T) *sqlx.DB - MaxWaitTimeForEvents() time.Duration - GasPriceBufferPercent() int64 -} - -type EVMChainReaderInterfaceTester[T TestingT[T]] struct { - Helper EVMChainReaderInterfaceTesterHelper[T] - client client.Client - address string - address2 string - contractTesters map[string]*chain_reader_tester.ChainReaderTester - chainConfig types.ChainReaderConfig - auth *bind.TransactOpts - cr evm.ChainReaderService - dirtyContracts bool -} - -func (it *EVMChainReaderInterfaceTester[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 - } - }) - - // can re-use the same chain for tests, just make new contract for each test - if it.client != nil { - it.deployNewContracts(t) - return - } - - it.auth = it.Helper.SetupAuth(t) - - testStruct := CreateTestStruct[T](0, it) - - methodTakingLatestParamsReturningTestStructConfig := types.ChainReaderDefinition{ - ChainSpecificName: "getElementAtIndex", - OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, - }, - } - - it.chainConfig = types.ChainReaderConfig{ - Contracts: map[string]types.ChainContractReader{ - AnyContractName: { - ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, - ContractPollingFilter: types.ContractPollingFilter{ - GenericEventNames: []string{EventName, EventWithFilterName, triggerWithAllTopicsWithHashed}, - }, - Configs: map[string]*types.ChainReaderDefinition{ - MethodTakingLatestParamsReturningTestStruct: &methodTakingLatestParamsReturningTestStructConfig, - MethodReturningAlterableUint64: { - ChainSpecificName: "getAlterablePrimitiveValue", - }, - MethodReturningUint64: { - ChainSpecificName: "getPrimitiveValue", - }, - MethodReturningUint64Slice: { - ChainSpecificName: "getSliceValue", - }, - EventName: { - ChainSpecificName: "Triggered", - ReadType: types.Event, - OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, - }, - }, - EventWithFilterName: { - ChainSpecificName: "Triggered", - ReadType: types.Event, - EventDefinitions: &types.EventDefinitions{InputFields: []string{"Field"}}, - }, - triggerWithDynamicTopic: { - ChainSpecificName: triggerWithDynamicTopic, - ReadType: types.Event, - EventDefinitions: &types.EventDefinitions{ - InputFields: []string{"fieldHash"}, - // No specific reason for filter being defined here instead of on contract level, this is just for test case variety. - PollingFilter: &types.PollingFilter{}, - }, - InputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"FieldHash": "Field"}}, - }, - }, - triggerWithAllTopics: { - ChainSpecificName: triggerWithAllTopics, - ReadType: types.Event, - EventDefinitions: &types.EventDefinitions{ - InputFields: []string{"Field1", "Field2", "Field3"}, - PollingFilter: &types.PollingFilter{}, - }, - // This doesn't have to be here, since the defalt mapping would work, but is left as an example. - // Keys which are string float values(confidence levels) are chain agnostic and should be reused across chains. - // These float values can map to different finality concepts across chains. - ConfidenceConfirmations: map[string]int{"0.0": int(evmtypes.Unconfirmed), "1.0": int(evmtypes.Finalized)}, - }, - triggerWithAllTopicsWithHashed: { - ChainSpecificName: triggerWithAllTopicsWithHashed, - ReadType: types.Event, - EventDefinitions: &types.EventDefinitions{ - InputFields: []string{"Field1", "Field2", "Field3"}, - }, - }, - MethodReturningSeenStruct: { - ChainSpecificName: "returnSeen", - InputModifications: codec.ModifiersConfig{ - &codec.HardCodeModifierConfig{ - OnChainValues: map[string]any{ - "BigField": testStruct.BigField.String(), - "Account": hexutil.Encode(testStruct.Account), - }, - }, - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, - }, - OutputModifications: codec.ModifiersConfig{ - &codec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, - }, - }, - }, - }, - AnySecondContractName: { - ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, - Configs: map[string]*types.ChainReaderDefinition{ - MethodTakingLatestParamsReturningTestStruct: &methodTakingLatestParamsReturningTestStructConfig, - MethodReturningUint64: { - ChainSpecificName: "getDifferentPrimitiveValue", - }, - }, - }, - }, - } - it.client = it.Helper.Client(t) - - it.deployNewContracts(t) -} - -func (it *EVMChainReaderInterfaceTester[T]) Name() string { - return "EVM" -} - -func (it *EVMChainReaderInterfaceTester[T]) GetAccountBytes(i int) []byte { - account := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - account[i%20] += byte(i) - account[(i+3)%20] += byte(i + 3) - return account[:] -} - -func (it *EVMChainReaderInterfaceTester[T]) GetChainReader(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.client, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(it.Helper.ChainID(), db, lggr), it.client, 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.chainConfig) - require.NoError(t, err) - - conf, err := types.ChainReaderConfigFromBytes(confBytes) - require.NoError(t, err) - - // wrap the client so that we can mock historical contract state - cwh := &ClientWithContractHistory{Client: it.Helper.Client(t), HT: ht} - require.NoError(t, cwh.Init(ctx, 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 -} - -func (it *EVMChainReaderInterfaceTester[T]) SetTestStructLatestValue(t T, testStruct *TestStruct) { - it.sendTxWithTestStruct(t, it.address, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).AddTestStruct) -} - -func (it *EVMChainReaderInterfaceTester[T]) SetBatchLatestValues(t T, batchCallEntry BatchCallEntry) { - nameToAddress := make(map[string]string) - boundContracts := it.GetBindings(t) - for _, bc := range boundContracts { - nameToAddress[bc.Name] = bc.Address - } - - for contractName, contractBatch := range batchCallEntry { - require.Contains(t, nameToAddress, contractName) - for _, readEntry := range contractBatch { - val, isOk := readEntry.ReturnValue.(*TestStruct) - if !isOk { - require.Fail(t, "expected *TestStruct for contract: %s read: %s, but received %T", contractName, readEntry.Name, readEntry.ReturnValue) - } - it.sendTxWithTestStruct(t, nameToAddress[contractName], val, (*chain_reader_tester.ChainReaderTesterTransactor).AddTestStruct) - } - } -} - -// SetUintLatestValue is supposed to be used for testing confidence levels, but geth simulated backend doesn't support calling past state -func (it *EVMChainReaderInterfaceTester[T]) SetUintLatestValue(t T, val uint64, forCall ExpectedGetLatestValueArgs) { - cw, ok := it.client.(*ClientWithContractHistory) - if !ok { - require.True(t, ok, "SetUintLatestValue should always be used for tests involving finality") - } - - it.sendTxWithUintVal(t, it.address, val, (*chain_reader_tester.ChainReaderTesterTransactor).SetAlterablePrimitiveValue) - require.NoError(t, cw.SetUintLatestValue(it.Helper.Context(t), val, forCall)) -} - -func (it *EVMChainReaderInterfaceTester[T]) TriggerEvent(t T, testStruct *TestStruct) { - it.sendTxWithTestStruct(t, it.address, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).TriggerEvent) -} - -// GenerateBlocksTillConfidenceLevel is supposed to be used for testing confidence levels, but geth simulated backend doesn't support calling past state -func (it *EVMChainReaderInterfaceTester[T]) GenerateBlocksTillConfidenceLevel(t T, contractName, readName string, confidenceLevel primitives.ConfidenceLevel) { - contractCfg, ok := it.chainConfig.Contracts[contractName] - if !ok { - t.Errorf("contract %s not found", contractName) - return - } - readCfg, ok := contractCfg.Configs[readName] - require.True(t, ok, fmt.Sprintf("readName: %s not found for contract: %s", readName, contractName)) - toEvmConf, err := evm.ConfirmationsFromConfig(readCfg.ConfidenceConfirmations) - require.True(t, ok, fmt.Errorf("failed to parse confidence level mapping:%s not found for contract: %s readName: %s, err:%w", confidenceLevel, readName, contractName, err)) - confirmations, ok := toEvmConf[confidenceLevel] - require.True(t, ok, fmt.Sprintf("confidence level mapping:%s not found for contract: %s readName: %s", confidenceLevel, readName, contractName)) - - if confirmations == evmtypes.Finalized { - for i := 0; i < finalityDepth; i++ { - it.Helper.Commit() - } - } -} - -func (it *EVMChainReaderInterfaceTester[T]) GetBindings(_ T) []clcommontypes.BoundContract { - return []clcommontypes.BoundContract{ - {Name: AnyContractName, Address: it.address}, - {Name: AnySecondContractName, Address: it.address2}, - } -} - -type uintFn = func(*chain_reader_tester.ChainReaderTesterTransactor, *bind.TransactOpts, uint64) (*gethtypes.Transaction, error) - -// sendTxWithUintVal is supposed to be used for testing confidence levels, but geth simulated backend doesn't support calling past state -func (it *EVMChainReaderInterfaceTester[T]) sendTxWithUintVal(t T, contractAddress string, val uint64, fn uintFn) { - tx, err := fn( - &it.contractTesters[contractAddress].ChainReaderTesterTransactor, - it.GetAuthWithGasSet(t), - val, - ) - - require.NoError(t, err) - it.Helper.Commit() - it.IncNonce() - it.AwaitTx(t, tx) - it.dirtyContracts = true -} - -type testStructFn = func(*chain_reader_tester.ChainReaderTesterTransactor, *bind.TransactOpts, int32, string, uint8, [32]uint8, common.Address, []common.Address, *big.Int, chain_reader_tester.MidLevelTestStruct) (*gethtypes.Transaction, error) - -func (it *EVMChainReaderInterfaceTester[T]) sendTxWithTestStruct(t T, contractAddress string, testStruct *TestStruct, fn testStructFn) { - tx, err := fn( - &it.contractTesters[contractAddress].ChainReaderTesterTransactor, - it.GetAuthWithGasSet(t), - *testStruct.Field, - testStruct.DifferentField, - uint8(testStruct.OracleID), - OracleIdsToBytes(testStruct.OracleIDs), - common.Address(testStruct.Account), - ConvertAccounts(testStruct.Accounts), - testStruct.BigField, - MidToInternalType(testStruct.NestedStruct), - ) - require.NoError(t, err) - it.Helper.Commit() - it.IncNonce() - it.AwaitTx(t, tx) - it.dirtyContracts = true -} - -func (it *EVMChainReaderInterfaceTester[T]) GetAuthWithGasSet(t T) *bind.TransactOpts { - gasPrice, err := it.client.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.auth.GasPrice = gasPrice.Add(gasPrice, extra) - return it.auth -} - -func (it *EVMChainReaderInterfaceTester[T]) IncNonce() { - if it.auth.Nonce == nil { - it.auth.Nonce = big.NewInt(1) - } else { - it.auth.Nonce = it.auth.Nonce.Add(it.auth.Nonce, big.NewInt(1)) - } -} - -func (it *EVMChainReaderInterfaceTester[T]) AwaitTx(t T, tx *gethtypes.Transaction) { - ctx := it.Helper.Context(t) - receipt, err := bind.WaitMined(ctx, it.client, tx) - require.NoError(t, err) - require.Equal(t, gethtypes.ReceiptStatusSuccessful, receipt.Status) -} - -func (it *EVMChainReaderInterfaceTester[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 - } -} - -func (it *EVMChainReaderInterfaceTester[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.auth.GasLimit = 10552800 - - address, tx, ts, 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 -} - -func (it *EVMChainReaderInterfaceTester[T]) MaxWaitTimeForEvents() time.Duration { - return it.Helper.MaxWaitTimeForEvents() -} - -func OracleIdsToBytes(oracleIDs [32]commontypes.OracleID) [32]byte { - convertedIds := [32]byte{} - for i, id := range oracleIDs { - convertedIds[i] = byte(id) - } - return convertedIds -} - -func ConvertAccounts(accounts [][]byte) []common.Address { - convertedAccounts := make([]common.Address, len(accounts)) - for i, a := range accounts { - convertedAccounts[i] = common.Address(a) - } - return convertedAccounts -} - -func ToInternalType(testStruct TestStruct) chain_reader_tester.TestStruct { - return chain_reader_tester.TestStruct{ - Field: *testStruct.Field, - DifferentField: testStruct.DifferentField, - OracleId: byte(testStruct.OracleID), - OracleIds: OracleIdsToBytes(testStruct.OracleIDs), - Account: common.Address(testStruct.Account), - Accounts: ConvertAccounts(testStruct.Accounts), - BigField: testStruct.BigField, - NestedStruct: MidToInternalType(testStruct.NestedStruct), - } -} - -func MidToInternalType(m MidLevelTestStruct) chain_reader_tester.MidLevelTestStruct { - return chain_reader_tester.MidLevelTestStruct{ - FixedBytes: m.FixedBytes, - Inner: chain_reader_tester.InnerTestStruct{ - IntVal: int64(m.Inner.I), - S: m.Inner.S, - }, - } -} diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go index caa24e8ae2c..908c4e1a81a 100644 --- a/core/services/relay/evm/evmtesting/run_tests.go +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -1,6 +1,7 @@ package evmtesting import ( + "encoding/binary" "math/big" "reflect" "time" @@ -10,39 +11,58 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/types" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . ) -func RunChainReaderEvmTests[T TestingT[T]](t T, it *EVMChainReaderInterfaceTester[T]) { - RunChainReaderInterfaceTests[T](t, it) +func RunChainComponentsEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T]) { + RunContractReaderEvmTests[T](t, it) + // Add ChainWriter tests here +} + +func RunChainComponentsInLoopEvmTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) { + RunContractReaderInLoopTests[T](t, it) + // Add ChainWriter tests here +} + +func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T]) { + RunContractReaderInterfaceTests[T](t, it, false) t.Run("Dynamically typed topics can be used to filter and have type correct in return", func(t T) { it.Setup(t) anyString := "foo" - it.dirtyContracts = true - tx, err := it.contractTesters[it.address].ChainReaderTesterTransactor.TriggerEventWithDynamicTopic(it.GetAuthWithGasSet(t), anyString) - require.NoError(t, err) - it.Helper.Commit() - it.IncNonce() - it.AwaitTx(t, tx) ctx := it.Helper.Context(t) - cr := it.GetChainReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(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) input := struct{ Field string }{Field: anyString} tp := cr.(clcommontypes.ContractTypeProvider) - output, err := tp.CreateContractType(AnyContractName, triggerWithDynamicTopic, false) + + readName := types.BoundContract{ + Address: bindings[0].Address, + Name: AnyContractName, + }.ReadIdentifier(triggerWithDynamicTopic) + + output, err := tp.CreateContractType(readName, false) require.NoError(t, err) rOutput := reflect.Indirect(reflect.ValueOf(output)) require.Eventually(t, func() bool { - return cr.GetLatestValue(ctx, AnyContractName, triggerWithDynamicTopic, primitives.Unconfirmed, input, output) == nil + return cr.GetLatestValue(ctx, readName, primitives.Unconfirmed, input, output) == nil }, it.MaxWaitTimeForEvents(), 100*time.Millisecond) assert.Equal(t, &anyString, rOutput.FieldByName("Field").Interface()) @@ -53,21 +73,30 @@ func RunChainReaderEvmTests[T TestingT[T]](t T, it *EVMChainReaderInterfaceTeste t.Run("Multiple topics can filter together", func(t T) { it.Setup(t) - it.dirtyContracts = true + ctx := it.Helper.Context(t) + cr := it.GetContractReader(t) + bindings := it.GetBindings(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)) - ctx := it.Helper.Context(t) - cr := it.GetChainReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + var bound types.BoundContract + for idx := range bindings { + if bindings[idx].Name == AnyContractName { + bound = bindings[idx] + } + } + var latest struct{ Field1, Field2, Field3 int32 } params := struct{ Field1, Field2, Field3 int32 }{Field1: 1, Field2: 2, Field3: 3} time.Sleep(it.MaxWaitTimeForEvents()) - require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, triggerWithAllTopics, primitives.Unconfirmed, params, &latest)) + require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(triggerWithAllTopics), primitives.Unconfirmed, params, &latest)) assert.Equal(t, int32(1), latest.Field1) assert.Equal(t, int32(2), latest.Field2) assert.Equal(t, int32(3), latest.Field3) @@ -75,14 +104,24 @@ func RunChainReaderEvmTests[T TestingT[T]](t T, it *EVMChainReaderInterfaceTeste t.Run("Filtering can be done on indexed topics that get hashed", func(t T) { it.Setup(t) - it.dirtyContracts = true + + cr := it.GetContractReader(t) + ctx := it.Helper.Context(t) + bindings := it.GetBindings(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}) - ctx := it.Helper.Context(t) - cr := it.GetChainReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + var bound types.BoundContract + for idx := range bindings { + if bindings[idx].Name == AnyContractName { + bound = bindings[idx] + } + } + var latest struct { Field3 [32]byte } @@ -93,7 +132,7 @@ func RunChainReaderEvmTests[T TestingT[T]](t T, it *EVMChainReaderInterfaceTeste }{Field1: "1", Field2: [32]uint8{2}, Field3: [32]byte{5}} time.Sleep(it.MaxWaitTimeForEvents()) - require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, triggerWithAllTopicsWithHashed, primitives.Unconfirmed, params, &latest)) + require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(triggerWithAllTopicsWithHashed), primitives.Unconfirmed, params, &latest)) // only checking Field3 topic makes sense since it isn't hashed, to check other fields we'd have to replicate solidity encoding and hashing assert.Equal(t, [32]uint8{5}, latest.Field3) }) @@ -102,29 +141,176 @@ func RunChainReaderEvmTests[T TestingT[T]](t T, it *EVMChainReaderInterfaceTeste it.Setup(t) addr := common.BigToAddress(big.NewInt(42)) - reader := it.GetChainReader(t) + reader := it.GetContractReader(t) ctx := it.Helper.Context(t) err := reader.Bind(ctx, []clcommontypes.BoundContract{{Name: AnyContractName, Address: addr.Hex()}}) - require.ErrorIs(t, err, evm.NoContractExistsError{Address: addr}) + require.ErrorIs(t, err, read.NoContractExistsError{Err: clcommontypes.ErrInternal, Address: addr}) }) } -func triggerFourTopics[T TestingT[T]](t T, it *EVMChainReaderInterfaceTester[T], i1, i2, i3 int32) { - tx, err := it.contractTesters[it.address].ChainReaderTesterTransactor.TriggerWithFourTopics(it.GetAuthWithGasSet(t), i1, i2, i3) - require.NoError(t, err) - require.NoError(t, err) - it.Helper.Commit() - it.IncNonce() - it.AwaitTx(t, tx) +func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) { + RunContractReaderInterfaceTests[T](t, it, false) + + it.Setup(t) + ctx := tests.Context(t) + cr := it.GetContractReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + bindings := it.GetBindings(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) + ts2 := CreateTestStruct[T](15, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + ts3 := CreateTestStruct[T](35, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + + t.Run("Filtering can be done on data words using value comparator", func(t T) { + ts := &TestStruct{} + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ + query.Comparator("OracleID", + primitives.ValueComparator{ + Value: uint8(ts2.OracleID), + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) + }) + + t.Run("Filtering can be done on data words using value comparator on a nested field", func(t T) { + ts := &TestStruct{} + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ + query.Comparator("OracleID", + primitives.ValueComparator{ + Value: uint8(ts2.OracleID), + Operator: primitives.Eq, + }), + query.Comparator("NestedStaticStruct.Inner.IntVal", + primitives.ValueComparator{ + Value: ts2.NestedStaticStruct.Inner.I, + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) + }) + + t.Run("Filtering can be done on data words using value comparator on field that follows a dynamic field", func(t T) { + ts := &TestStruct{} + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ + query.Comparator("OracleID", + primitives.ValueComparator{ + Value: uint8(ts2.OracleID), + Operator: primitives.Eq, + }), + query.Comparator("BigField", + primitives.ValueComparator{ + Value: ts2.BigField, + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) + }) + + t.Run("Filtering can be done on data words using value comparators on fields that require manual index input", func(t T) { + 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} + copy(val5[:], append(empty12Bytes[:], 5)) + raw := []byte{9, 8} + + var buf []byte + buf = binary.BigEndian.AppendUint32(buf, val1) + buf = binary.BigEndian.AppendUint32(buf, val2) + buf = binary.BigEndian.AppendUint32(buf, val3) + buf = binary.BigEndian.AppendUint64(buf, val4) + dataWordOnChainValueToQuery := buf[:] + + resExpected := append(buf, common.LeftPadBytes(val5[:], 32)...) + resExpected = append(resExpected, common.LeftPadBytes(val6[:], 32)...) + resExpected = append(resExpected, common.LeftPadBytes(val7[:], 32)...) + resExpected = append(resExpected, raw...) + + type eventResAsStruct struct { + Message *[]uint8 + } + 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) + + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: staticBytesEventName, Expressions: []query.Expression{ + query.Comparator("msgTransmitterEvent", + primitives.ValueComparator{ + Value: dataWordOnChainValueToQuery, + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, eventResAsStruct{}) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(wrapExpectedRes, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) + }) } -func triggerFourTopicsWithHashed[T TestingT[T]](t T, it *EVMChainReaderInterfaceTester[T], i1 string, i2 [32]uint8, i3 [32]byte) { - tx, err := it.contractTesters[it.address].ChainReaderTesterTransactor.TriggerWithFourTopicsWithHashed(it.GetAuthWithGasSet(t), i1, i2, i3) - require.NoError(t, err) - require.NoError(t, err) - it.Helper.Commit() - it.IncNonce() - it.AwaitTx(t, tx) +func triggerFourTopics[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], 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) +} + +func triggerFourTopicsWithHashed[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], 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) +} + +// 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) { + type StaticBytesEvent struct { + Val1 uint32 + Val2 uint32 + Val3 uint32 + Val4 uint64 + Val5 [32]byte + Val6 [32]byte + Val7 [32]byte + Raw []byte + } + + contracts := it.GetBindings(t) + SubmitTransactionToCW(t, it, "triggerStaticBytes", + StaticBytesEvent{ + Val1: val1, + Val2: val2, + Val3: val3, + Val4: val4, + Val5: val5, + Val6: val6, + Val7: val7, + Raw: raw, + }, + contracts[0], types.Unconfirmed) } diff --git a/core/services/relay/evm/exec_provider.go b/core/services/relay/evm/exec_provider.go index ae3ce56532a..e0a9b378f27 100644 --- a/core/services/relay/evm/exec_provider.go +++ b/core/services/relay/evm/exec_provider.go @@ -13,6 +13,7 @@ import ( "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" @@ -22,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "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/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata/usdc" ) @@ -151,7 +151,7 @@ func (s *SrcExecProvider) ContractTransmitter() ocrtypes.ContractTransmitter { return UnimplementedContractTransmitter{} } -func (s *SrcExecProvider) ChainReader() commontypes.ContractReader { +func (s *SrcExecProvider) ContractReader() commontypes.ContractReader { return nil } @@ -331,7 +331,7 @@ func (d *DstExecProvider) ContractTransmitter() ocrtypes.ContractTransmitter { return d.contractTransmitter } -func (d *DstExecProvider) ChainReader() commontypes.ContractReader { +func (d *DstExecProvider) ContractReader() commontypes.ContractReader { return nil } diff --git a/core/services/relay/evm/functions.go b/core/services/relay/evm/functions.go index a04a991e379..98928241fde 100644 --- a/core/services/relay/evm/functions.go +++ b/core/services/relay/evm/functions.go @@ -8,17 +8,15 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "go.uber.org/multierr" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txm "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/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config" functionsRelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" @@ -26,12 +24,29 @@ import ( ) type functionsProvider struct { - services.StateMachine + services.Service + eng *services.Engine + configWatcher *configWatcher contractTransmitter ContractTransmitter logPollerWrapper evmRelayTypes.LogPollerWrapper } +func newFunctionsProvider(lggr logger.Logger, cw *configWatcher, ct ContractTransmitter, lpw evmRelayTypes.LogPollerWrapper) *functionsProvider { + p := &functionsProvider{ + configWatcher: cw, + contractTransmitter: ct, + logPollerWrapper: lpw, + } + p.Service, p.eng = services.Config{ + Name: "FunctionsProvider", + NewSubServices: func(lggr logger.Logger) []services.Service { + return []services.Service{p.configWatcher, p.logPollerWrapper} + }, + }.NewServiceEngine(lggr) + return p +} + var _ evmRelayTypes.FunctionsProvider = (*functionsProvider)(nil) func (p *functionsProvider) ContractTransmitter() ocrtypes.ContractTransmitter { @@ -47,23 +62,6 @@ func (p *functionsProvider) FunctionsEvents() commontypes.FunctionsEvents { return nil } -func (p *functionsProvider) Start(ctx context.Context) error { - return p.StartOnce("FunctionsProvider", func() error { - if err := p.configWatcher.Start(ctx); err != nil { - return err - } - return p.logPollerWrapper.Start(ctx) - }) -} - -func (p *functionsProvider) Close() error { - return p.StopOnce("FunctionsProvider", func() (err error) { - err = multierr.Combine(err, p.logPollerWrapper.Close()) - err = multierr.Combine(err, p.configWatcher.Close()) - return - }) -} - // Forward all calls to the underlying configWatcher func (p *functionsProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { return p.configWatcher.OffchainConfigDigester() @@ -73,15 +71,7 @@ func (p *functionsProvider) ContractConfigTracker() ocrtypes.ContractConfigTrack return p.configWatcher.ContractConfigTracker() } -func (p *functionsProvider) HealthReport() map[string]error { - return p.configWatcher.HealthReport() -} - -func (p *functionsProvider) Name() string { - return p.configWatcher.Name() -} - -func (p *functionsProvider) ChainReader() commontypes.ContractReader { +func (p *functionsProvider) ContractReader() commontypes.ContractReader { return nil } @@ -127,11 +117,7 @@ func NewFunctionsProvider(ctx context.Context, chain legacyevm.Chain, rargs comm } else { lggr.Warn("no sending keys configured for functions plugin, not starting contract transmitter") } - return &functionsProvider{ - configWatcher: configWatcher, - contractTransmitter: contractTransmitter, - logPollerWrapper: logPollerWrapper, - }, nil + return newFunctionsProvider(lggr, configWatcher, contractTransmitter, logPollerWrapper), nil } func newFunctionsConfigProvider(ctx context.Context, pluginType functionsRelay.FunctionsPluginType, chain legacyevm.Chain, args commontypes.RelayArgs, fromBlock uint64, logPollerWrapper evmRelayTypes.LogPollerWrapper, lggr logger.Logger) (*configWatcher, error) { diff --git a/core/services/relay/evm/functions/config_poller.go b/core/services/relay/evm/functions/config_poller.go index 71616f2e840..2cb21738b91 100644 --- a/core/services/relay/evm/functions/config_poller.go +++ b/core/services/relay/evm/functions/config_poller.go @@ -9,12 +9,13 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) diff --git a/core/services/relay/evm/functions/config_poller_test.go b/core/services/relay/evm/functions/config_poller_test.go index c44d64c5ba7..1d8ef2cde36 100644 --- a/core/services/relay/evm/functions/config_poller_test.go +++ b/core/services/relay/evm/functions/config_poller_test.go @@ -193,6 +193,7 @@ func setFunctionsConfig(t *testing.T, pluginConfig *functionsConfig.ReportingPlu []int{1, 1, 1, 1}, oracles, pluginConfigBytes, + nil, 50*time.Millisecond, 50*time.Millisecond, 50*time.Millisecond, diff --git a/core/services/relay/evm/functions/contract_transmitter.go b/core/services/relay/evm/functions/contract_transmitter.go index 23143ed3ef1..94fbe83d51a 100644 --- a/core/services/relay/evm/functions/contract_transmitter.go +++ b/core/services/relay/evm/functions/contract_transmitter.go @@ -13,14 +13,16 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "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/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/encoding" evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -105,7 +107,7 @@ func NewFunctionsContractTransmitter( transmittedEventSig: transmitted.ID, lp: lp, contractReader: caller, - lggr: lggr.Named("OCRFunctionsContractTransmitter"), + lggr: logger.Named(lggr, "OCRFunctionsContractTransmitter"), contractVersion: contractVersion, reportCodec: codec, txm: txm, @@ -282,7 +284,7 @@ func (oc *contractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) ( } // FromAccount returns the account from which the transmitter invokes the contract -func (oc *contractTransmitter) FromAccount() (ocrtypes.Account, error) { +func (oc *contractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { return ocrtypes.Account(oc.effectiveTransmitterAddress.String()), nil } diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go index b0d04b11871..260c366eb8e 100644 --- a/core/services/relay/evm/functions/logpoller_wrapper.go +++ b/core/services/relay/evm/functions/logpoller_wrapper.go @@ -10,13 +10,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "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/functions/generated/functions_coordinator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config" evmRelayTypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) diff --git a/core/services/relay/evm/functions/offchain_config_digester.go b/core/services/relay/evm/functions/offchain_config_digester.go index fa8199ec0a4..6aadaaea386 100644 --- a/core/services/relay/evm/functions/offchain_config_digester.go +++ b/core/services/relay/evm/functions/offchain_config_digester.go @@ -37,7 +37,7 @@ func NewFunctionsOffchainConfigDigester(pluginType FunctionsPluginType, chainID } } -func (d *functionsOffchainConfigDigester) ConfigDigest(cc types.ContractConfig) (types.ConfigDigest, error) { +func (d *functionsOffchainConfigDigester) ConfigDigest(ctx context.Context, cc types.ContractConfig) (types.ConfigDigest, error) { contractAddress := d.contractAddress.Load() if contractAddress == nil { return types.ConfigDigest{}, errors.New("contract address not set") @@ -47,7 +47,7 @@ func (d *functionsOffchainConfigDigester) ConfigDigest(cc types.ContractConfig) ContractAddress: *contractAddress, } - configDigest, err := baseDigester.ConfigDigest(cc) + configDigest, err := baseDigester.ConfigDigest(ctx, cc) if err != nil { return types.ConfigDigest{}, err } @@ -69,7 +69,7 @@ func (d *functionsOffchainConfigDigester) ConfigDigest(cc types.ContractConfig) return configDigest, nil } -func (d *functionsOffchainConfigDigester) ConfigDigestPrefix() (types.ConfigDigestPrefix, error) { +func (d *functionsOffchainConfigDigester) ConfigDigestPrefix(ctx context.Context) (types.ConfigDigestPrefix, error) { switch d.pluginType { case FunctionsPlugin: return FunctionsDigestPrefix, nil diff --git a/core/services/relay/evm/llo/abi.go b/core/services/relay/evm/llo/abi.go new file mode 100644 index 00000000000..3de25709eaa --- /dev/null +++ b/core/services/relay/evm/llo/abi.go @@ -0,0 +1,29 @@ +package llo + +import ( + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/configurator" +) + +var ( + ProductionConfigSet common.Hash + StagingConfigSet common.Hash + PromoteStagingConfig common.Hash + + configuratorABI abi.ABI +) + +func init() { + var err error + configuratorABI, err = abi.JSON(strings.NewReader(configurator.ConfiguratorABI)) + if err != nil { + panic(err) + } + ProductionConfigSet = configuratorABI.Events["ProductionConfigSet"].ID + StagingConfigSet = configuratorABI.Events["StagingConfigSet"].ID + PromoteStagingConfig = configuratorABI.Events["PromoteStagingConfig"].ID +} diff --git a/core/services/relay/evm/llo/config_poller.go b/core/services/relay/evm/llo/config_poller.go new file mode 100644 index 00000000000..feeff015862 --- /dev/null +++ b/core/services/relay/evm/llo/config_poller.go @@ -0,0 +1,276 @@ +package llo + +import ( + "bytes" + "context" + "database/sql" + "fmt" + "math" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/configurator" +) + +type InstanceType string + +const ( + InstanceTypeBlue InstanceType = InstanceType("Blue") + InstanceTypeGreen InstanceType = InstanceType("Green") +) + +type ConfigPollerService interface { + services.Service + ocrtypes.ContractConfigTracker +} + +type LogPoller interface { + IndexedLogsByBlockRange(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash) ([]logpoller.Log, error) + LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) + LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) +} + +// ConfigCache is most likely the global RetirementReportCache. Every config +// ever seen by this tracker will be stored at least once in the cache. +type ConfigCache interface { + StoreConfig(ctx context.Context, cd ocrtypes.ConfigDigest, signers [][]byte, f uint8) error +} + +type configPoller struct { + services.Service + eng *services.Engine + + lp LogPoller + cc ConfigCache + addr common.Address + donID uint32 + donIDHash [32]byte + + fromBlock uint64 + + instanceType InstanceType +} + +func DonIDToBytes32(donID uint32) [32]byte { + var b [32]byte + copy(b[:], common.LeftPadBytes(big.NewInt(int64(donID)).Bytes(), 32)) + return b +} + +// NewConfigPoller creates a new LLOConfigPoller +func NewConfigPoller(lggr logger.Logger, lp LogPoller, cc ConfigCache, addr common.Address, donID uint32, instanceType InstanceType, fromBlock uint64) ConfigPollerService { + return newConfigPoller(lggr, lp, cc, addr, donID, instanceType, fromBlock) +} + +func newConfigPoller(lggr logger.Logger, lp LogPoller, cc ConfigCache, addr common.Address, donID uint32, instanceType InstanceType, fromBlock uint64) *configPoller { + cp := &configPoller{ + lp: lp, + cc: cc, + addr: addr, + donID: donID, + donIDHash: DonIDToBytes32(donID), + instanceType: instanceType, + fromBlock: fromBlock, + } + cp.Service, cp.eng = services.Config{ + Name: "LLOConfigPoller", + }.NewServiceEngine(logger.Sugared(lggr).Named(string(instanceType)).With("instanceType", instanceType)) + + return cp +} + +func (cp *configPoller) Notify() <-chan struct{} { + return nil // rely on libocr's builtin config polling +} + +// LatestConfigDetails returns the latest config details from the logs +func (cp *configPoller) LatestConfigDetails(ctx context.Context) (changedInBlock uint64, configDigest ocrtypes.ConfigDigest, err error) { + latestConfig, log, err := cp.latestConfig(ctx, int64(cp.fromBlock), math.MaxInt64) // #nosec G115 + if err != nil { + return 0, ocrtypes.ConfigDigest{}, fmt.Errorf("failed to get latest config: %w", err) + } + return uint64(log.BlockNumber), latestConfig.ConfigDigest, nil +} + +func (cp *configPoller) latestConfig(ctx context.Context, fromBlock, toBlock int64) (latestConfig FullConfigFromLog, latestLog logpoller.Log, err error) { + // Get all config set logs run through them forwards + // TODO: This could probably be optimized with a 'latestBlockNumber' cache or something to avoid reading from `fromBlock` on every call + // TODO: Actually we only care about the latest of each type here + // MERC-3524 + logs, err := cp.lp.LogsWithSigs(ctx, fromBlock, toBlock, []common.Hash{ProductionConfigSet, StagingConfigSet}, cp.addr) + if err != nil { + return latestConfig, latestLog, fmt.Errorf("failed to get logs: %w", err) + } + for _, log := range logs { + // TODO: This can be optimized probably by adding donIDHash to the logpoller lookup + // MERC-3524 + if !bytes.Equal(log.Topics[1], cp.donIDHash[:]) { + continue + } + switch log.EventSig { + case ProductionConfigSet: + event, err := DecodeProductionConfigSetLog(log.Data) + if err != nil { + return latestConfig, log, fmt.Errorf("failed to unpack ProductionConfigSet log data: %w", err) + } + + if err = cp.cc.StoreConfig(ctx, event.ConfigDigest, event.Signers, event.F); err != nil { + cp.eng.SugaredLogger.Errorf("failed to store production config: %v", err) + } + + isProduction := (cp.instanceType != InstanceTypeBlue) == event.IsGreenProduction + if isProduction { + latestLog = log + latestConfig, err = FullConfigFromProductionConfigSet(event) + if err != nil { + return latestConfig, latestLog, fmt.Errorf("FullConfigFromProductionConfigSet failed: %w", err) + } + } + case StagingConfigSet: + event, err := DecodeStagingConfigSetLog(log.Data) + if err != nil { + return latestConfig, latestLog, fmt.Errorf("failed to unpack ProductionConfigSet log data: %w", err) + } + + if err = cp.cc.StoreConfig(ctx, event.ConfigDigest, event.Signers, event.F); err != nil { + cp.eng.SugaredLogger.Errorf("failed to store staging config: %v", err) + } + + isProduction := (cp.instanceType != InstanceTypeBlue) == event.IsGreenProduction + if !isProduction { + latestLog = log + latestConfig, err = FullConfigFromStagingConfigSet(event) + if err != nil { + return latestConfig, latestLog, fmt.Errorf("FullConfigFromStagingConfigSet failed: %w", err) + } + } + default: + // ignore unknown log types + continue + } + } + + return +} + +// LatestConfig returns the latest config from the logs starting from a certain block +func (cp *configPoller) LatestConfig(ctx context.Context, changedInBlock uint64) (ocrtypes.ContractConfig, error) { + cfg, _, err := cp.latestConfig(ctx, int64(changedInBlock), math.MaxInt64) // #nosec G115 + if err != nil { + return ocrtypes.ContractConfig{}, fmt.Errorf("failed to get latest config: %w", err) + } + return cfg.ContractConfig, nil +} + +// LatestBlockHeight returns the latest block height from the logs +func (cp *configPoller) LatestBlockHeight(ctx context.Context) (blockHeight uint64, err error) { + latest, err := cp.lp.LatestBlock(ctx) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return 0, nil + } + return 0, err + } + return uint64(latest.BlockNumber), nil +} + +func (cp *configPoller) InstanceType() InstanceType { + return cp.instanceType +} + +// FullConfigFromLog defines the contract config with the donID +type FullConfigFromLog struct { + ocrtypes.ContractConfig + donID uint32 +} + +func FullConfigFromProductionConfigSet(unpacked configurator.ConfiguratorProductionConfigSet) (FullConfigFromLog, error) { + var transmitAccounts []ocrtypes.Account + for _, addr := range unpacked.OffchainTransmitters { + transmitAccounts = append(transmitAccounts, ocrtypes.Account(fmt.Sprintf("%x", addr))) + } + var signers []ocrtypes.OnchainPublicKey + for _, addr := range unpacked.Signers { + addr := addr + signers = append(signers, addr[:]) + } + + donIDBig := common.Hash(unpacked.ConfigId).Big() + if donIDBig.Cmp(big.NewInt(math.MaxUint32)) > 0 { + return FullConfigFromLog{}, errors.Errorf("donID %s is too large", donIDBig) + } + donID := uint32(donIDBig.Uint64()) // #nosec G115 + + return FullConfigFromLog{ + donID: donID, + ContractConfig: ocrtypes.ContractConfig{ + ConfigDigest: unpacked.ConfigDigest, + ConfigCount: unpacked.ConfigCount, + Signers: signers, + Transmitters: transmitAccounts, + F: unpacked.F, + OnchainConfig: unpacked.OnchainConfig, + OffchainConfigVersion: unpacked.OffchainConfigVersion, + OffchainConfig: unpacked.OffchainConfig, + }, + }, nil +} + +func FullConfigFromStagingConfigSet(unpacked configurator.ConfiguratorStagingConfigSet) (FullConfigFromLog, error) { + var transmitAccounts []ocrtypes.Account + for _, addr := range unpacked.OffchainTransmitters { + transmitAccounts = append(transmitAccounts, ocrtypes.Account(fmt.Sprintf("%x", addr))) + } + var signers []ocrtypes.OnchainPublicKey + for _, addr := range unpacked.Signers { + addr := addr + signers = append(signers, addr[:]) + } + + donIDBig := common.Hash(unpacked.ConfigId).Big() + if donIDBig.Cmp(big.NewInt(math.MaxUint32)) > 0 { + return FullConfigFromLog{}, errors.Errorf("donID %s is too large", donIDBig) + } + donID := uint32(donIDBig.Uint64()) // #nosec G115 + + return FullConfigFromLog{ + donID: donID, + ContractConfig: ocrtypes.ContractConfig{ + ConfigDigest: unpacked.ConfigDigest, + ConfigCount: unpacked.ConfigCount, + Signers: signers, + Transmitters: transmitAccounts, + F: unpacked.F, + OnchainConfig: unpacked.OnchainConfig, + OffchainConfigVersion: unpacked.OffchainConfigVersion, + OffchainConfig: unpacked.OffchainConfig, + }, + }, nil +} + +func DecodeProductionConfigSetLog(d []byte) (configurator.ConfiguratorProductionConfigSet, error) { + unpacked := new(configurator.ConfiguratorProductionConfigSet) + + err := configuratorABI.UnpackIntoInterface(unpacked, "ProductionConfigSet", d) + if err != nil { + return configurator.ConfiguratorProductionConfigSet{}, errors.Wrap(err, "failed to unpack log data") + } + return *unpacked, nil +} + +func DecodeStagingConfigSetLog(d []byte) (configurator.ConfiguratorStagingConfigSet, error) { + unpacked := new(configurator.ConfiguratorStagingConfigSet) + + err := configuratorABI.UnpackIntoInterface(unpacked, "StagingConfigSet", d) + if err != nil { + return configurator.ConfiguratorStagingConfigSet{}, errors.Wrap(err, "failed to unpack log data") + } + return *unpacked, nil +} diff --git a/core/services/relay/evm/llo/config_poller_test.go b/core/services/relay/evm/llo/config_poller_test.go new file mode 100644 index 00000000000..c1430b7c150 --- /dev/null +++ b/core/services/relay/evm/llo/config_poller_test.go @@ -0,0 +1,400 @@ +package llo + +import ( + "context" + "math/rand/v2" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/lib/pq" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var _ LogPoller = (*mockLogPoller)(nil) + +type mockLogPoller struct { + logs []logpoller.Log + latestBlock int64 +} + +func (m *mockLogPoller) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) { + return logpoller.LogPollerBlock{BlockNumber: m.latestBlock}, nil +} +func (m *mockLogPoller) RegisterFilter(ctx context.Context, filter logpoller.Filter) error { + return nil +} +func (m *mockLogPoller) Replay(ctx context.Context, fromBlock int64) error { + return nil +} +func (m *mockLogPoller) LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { + logs := make([]logpoller.Log, 0) + for _, log := range m.logs { + if log.BlockNumber >= start && log.BlockNumber <= end && log.Address == address { + for _, sig := range eventSigs { + if log.EventSig == sig { + logs = append(logs, log) + } + } + } + } + + return logs, nil +} +func (m *mockLogPoller) IndexedLogsByBlockRange(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash) ([]logpoller.Log, error) { + return m.LogsWithSigs(ctx, start, end, []common.Hash{eventSig}, address) +} + +type cfg struct { + cd ocrtypes.ConfigDigest + signers [][]byte + f uint8 +} + +type mockConfigCache struct { + configs map[ocrtypes.ConfigDigest]cfg +} + +func (m *mockConfigCache) StoreConfig(ctx context.Context, cd ocrtypes.ConfigDigest, signers [][]byte, f uint8) error { + m.configs[cd] = cfg{cd, signers, f} + return nil +} + +func Test_ConfigPoller(t *testing.T) { + ctx := testutils.Context(t) + lggr := logger.Test(t) + lp := &mockLogPoller{make([]logpoller.Log, 0), 0} + addr := common.Address{1} + donID := uint32(1) + donIDHash := DonIDToBytes32(donID) + fromBlock := uint64(1) + + cc := &mockConfigCache{make(map[ocrtypes.ConfigDigest]cfg)} + + cpBlue := newConfigPoller(lggr, lp, cc, addr, donID, InstanceTypeBlue, fromBlock) + cpGreen := newConfigPoller(lggr, lp, cc, addr, donID, InstanceTypeGreen, fromBlock) + + cfgCount := uint64(0) + + signers := [][]byte{(common.Address{1}).Bytes(), (common.Address{2}).Bytes()} + transmitters := []common.Hash{common.Hash{1}, common.Hash{2}} + f := uint8(1) + onchainConfig := []byte{5} + offchainConfigVersion := uint64(6) + offchainConfig := []byte{7} + + t.Run("Blue/Green config poller follow production and staging configs respectively initially", func(t *testing.T) { + t.Run("LatestConfigDetails", func(t *testing.T) { + t.Run("without any logs, returns zero values", func(t *testing.T) { + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(0), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(0), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{}, digest) + }) + + t.Run("with isGreenProduction=false", func(t *testing.T) { + isGreenProduction := false + + t.Run("with ProductionConfigSet event, blue starts returning the production config (green still returns zeroes)", func(t *testing.T) { + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{Topics: pq.ByteaArray{ProductionConfigSet[:], donIDHash[:]}, Address: addr, EventSig: ProductionConfigSet, BlockNumber: 100, Data: makeConfigSetLogData( + t, + 0, + common.Hash{1}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(100), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{1}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(0), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{}, digest) + }) + t.Run("with StagingConfigSet event, green starts returning the staging config (blue still returns the production config)", func(t *testing.T) { + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{Topics: pq.ByteaArray{StagingConfigSet[:], donIDHash[:]}, Address: addr, EventSig: StagingConfigSet, BlockNumber: 101, Data: makeConfigSetLogData( + t, + 0, + common.Hash{2}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(100), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{1}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(101), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{2}, digest) + }) + }) + + t.Run("with isGreenProduction=true (after PromoteStagingConfig)", func(t *testing.T) { + isGreenProduction := true + t.Run("if we ProductionConfigSet again, it now affects green since that is the production instance (blue remains unchanged)", func(t *testing.T) { + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{Topics: pq.ByteaArray{ProductionConfigSet[:], donIDHash[:]}, Address: addr, EventSig: ProductionConfigSet, BlockNumber: 103, Data: makeConfigSetLogData( + t, + 0, + common.Hash{3}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(100), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{1}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(103), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{3}, digest) + }) + + t.Run("if we StagingConfigSet again, it now affects blue since that is the staging instance (green remains unchanged)", func(t *testing.T) { + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{Topics: pq.ByteaArray{StagingConfigSet[:], donIDHash[:]}, Address: addr, EventSig: StagingConfigSet, BlockNumber: 104, Data: makeConfigSetLogData( + t, + 0, + common.Hash{4}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(104), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{4}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(103), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{3}, digest) + }) + + t.Run("if we StagingConfigSet and ProductionConfigSet again, it sets the config for blue and green respectively", func(t *testing.T) { + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{Topics: pq.ByteaArray{StagingConfigSet[:], donIDHash[:]}, Address: addr, EventSig: StagingConfigSet, BlockNumber: 105, Data: makeConfigSetLogData( + t, + 0, + common.Hash{5}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{Topics: pq.ByteaArray{ProductionConfigSet[:], donIDHash[:]}, Address: addr, EventSig: ProductionConfigSet, BlockNumber: 106, Data: makeConfigSetLogData( + t, + 0, + common.Hash{6}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(105), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{5}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(106), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{6}, digest) + }) + }) + t.Run("isGreenProduction=false again (another PromoteStagingConfig", func(t *testing.T) { + isGreenProduction := false + t.Run("if we PromoteStagingConfig again it re-flips the instances", func(t *testing.T) { + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{LogIndex: 1, Topics: pq.ByteaArray{ProductionConfigSet[:], donIDHash[:]}, Address: addr, EventSig: ProductionConfigSet, BlockNumber: 107, Data: makeConfigSetLogData( + t, + 0, + common.Hash{7}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + cfgCount++ + lp.logs = append(lp.logs, logpoller.Log{LogIndex: 2, Topics: pq.ByteaArray{StagingConfigSet[:], donIDHash[:]}, Address: addr, EventSig: StagingConfigSet, BlockNumber: 107, Data: makeConfigSetLogData( + t, + 0, + common.Hash{8}, + cfgCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + isGreenProduction, + )}) + + changedInBlock, digest, err := cpBlue.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(107), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{7}, digest) + + changedInBlock, digest, err = cpGreen.LatestConfigDetails(ctx) + require.NoError(t, err) + + assert.Equal(t, uint64(107), changedInBlock) + assert.Equal(t, ocr2types.ConfigDigest{8}, digest) + }) + }) + t.Run("Stores all seen configs in cache", func(t *testing.T) { + require.Len(t, cc.configs, 8) + for i := 1; i <= 8; i++ { + assert.Contains(t, cc.configs, ocr2types.ConfigDigest{byte(i)}) + assert.Equal(t, cfg{ + cd: ocr2types.ConfigDigest{byte(i)}, + signers: signers, + f: f, + }, cc.configs[ocr2types.ConfigDigest{byte(i)}]) + } + }) + }) + t.Run("LatestConfig", func(t *testing.T) { + t.Run("changedInBlock in future, returns nothing", func(t *testing.T) { + cfg, err := cpBlue.LatestConfig(ctx, 200) + require.NoError(t, err) + assert.Zero(t, cfg) + + cfg, err = cpGreen.LatestConfig(ctx, 200) + require.NoError(t, err) + assert.Zero(t, cfg) + }) + t.Run("changedInBlock corresponds to a block in which a log was emitted, returns the config", func(t *testing.T) { + expectedSigners := []ocr2types.OnchainPublicKey{ocr2types.OnchainPublicKey{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, ocr2types.OnchainPublicKey{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}} + expectedTransmitters := []ocr2types.Account{"0100000000000000000000000000000000000000000000000000000000000000", "0200000000000000000000000000000000000000000000000000000000000000"} + + cfg, err := cpBlue.LatestConfig(ctx, 107) + require.NoError(t, err) + assert.Equal(t, ocr2types.ConfigDigest{7}, cfg.ConfigDigest) + assert.Equal(t, uint64(7), cfg.ConfigCount) + assert.Equal(t, expectedSigners, cfg.Signers) + assert.Equal(t, expectedTransmitters, cfg.Transmitters) + assert.Equal(t, f, cfg.F) + assert.Equal(t, onchainConfig, cfg.OnchainConfig) + assert.Equal(t, offchainConfigVersion, cfg.OffchainConfigVersion) + assert.Equal(t, offchainConfig, cfg.OffchainConfig) + + cfg, err = cpGreen.LatestConfig(ctx, 107) + require.NoError(t, err) + assert.Equal(t, ocr2types.ConfigDigest{8}, cfg.ConfigDigest) + assert.Equal(t, uint64(8), cfg.ConfigCount) + assert.Equal(t, expectedSigners, cfg.Signers) + assert.Equal(t, expectedTransmitters, cfg.Transmitters) + assert.Equal(t, f, cfg.F) + assert.Equal(t, onchainConfig, cfg.OnchainConfig) + assert.Equal(t, offchainConfigVersion, cfg.OffchainConfigVersion) + assert.Equal(t, offchainConfig, cfg.OffchainConfig) + }) + }) + t.Run("LatestBlockHeight", func(t *testing.T) { + t.Run("returns the latest block from log poller", func(t *testing.T) { + latest := rand.Int64() + lp.latestBlock = latest + + latestBlock, err := cpBlue.LatestBlockHeight(ctx) + require.NoError(t, err) + assert.Equal(t, uint64(latest), latestBlock) + + latestBlock, err = cpGreen.LatestBlockHeight(ctx) + require.NoError(t, err) + assert.Equal(t, uint64(latest), latestBlock) + }) + }) + }) +} + +func makeConfigSetLogData(t *testing.T, + previousConfigBlockNumber uint32, + configDigest common.Hash, + configCount uint64, + signers [][]byte, + offchainTransmitters []common.Hash, + f uint8, + onchainConfig []byte, + offchainConfigVersion uint64, + offchainConfig []byte, + isGreenProduction bool, +) []byte { + event := configuratorABI.Events["ProductionConfigSet"] + data, err := event.Inputs.NonIndexed().Pack(previousConfigBlockNumber, configDigest, configCount, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, isGreenProduction) + require.NoError(t, err) + return data +} diff --git a/core/services/llo/offchain_config_digester.go b/core/services/relay/evm/llo/offchain_config_digester.go similarity index 61% rename from core/services/llo/offchain_config_digester.go rename to core/services/relay/evm/llo/offchain_config_digester.go index cd4d9afa3a0..08356619a25 100644 --- a/core/services/llo/offchain_config_digester.go +++ b/core/services/relay/evm/llo/offchain_config_digester.go @@ -1,6 +1,7 @@ package llo import ( + "context" "crypto/ed25519" "encoding/binary" "encoding/hex" @@ -13,34 +14,35 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/libocr/offchainreporting2/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/wsrpc/credentials" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/exposed_channel_verifier" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/exposed_configurator" ) // Originally sourced from: https://github.com/smartcontractkit/offchain-reporting/blob/991ebe1462fd56826a1ddfb34287d542acb2baee/lib/offchainreporting2/chains/evmutil/offchain_config_digester.go var _ ocrtypes.OffchainConfigDigester = OffchainConfigDigester{} -func NewOffchainConfigDigester(chainID *big.Int, contractAddress common.Address) OffchainConfigDigester { - return OffchainConfigDigester{chainID, contractAddress} +func NewOffchainConfigDigester(configID common.Hash, chainID *big.Int, contractAddress common.Address, prefix ocrtypes.ConfigDigestPrefix) OffchainConfigDigester { + return OffchainConfigDigester{configID, chainID, contractAddress, prefix} } type OffchainConfigDigester struct { + ConfigID common.Hash ChainID *big.Int ContractAddress common.Address + Prefix ocrtypes.ConfigDigestPrefix } -func (d OffchainConfigDigester) ConfigDigest(cc ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { - signers := []common.Address{} +func (d OffchainConfigDigester) ConfigDigest(_ context.Context, cc ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { + onchainPubKeys := make([][]byte, len(cc.Signers)) for i, signer := range cc.Signers { - if len(signer) != 20 { - return ocrtypes.ConfigDigest{}, errors.Errorf("%v-th evm signer should be a 20 byte address, but got %x", i, signer) - } - a := common.BytesToAddress(signer) - signers = append(signers, a) + // Onchainpubkeys can be anything + // TODO: Implement and enforce MultiChainKeyBundle format? + // MERC-3594 + onchainPubKeys[i] = signer } transmitters := []credentials.StaticSizedPublicKey{} for i, transmitter := range cc.Transmitters { @@ -58,27 +60,29 @@ func (d OffchainConfigDigester) ConfigDigest(cc ocrtypes.ContractConfig) (ocrtyp } return configDigest( + d.ConfigID, d.ChainID, d.ContractAddress, cc.ConfigCount, - signers, + onchainPubKeys, transmitters, cc.F, cc.OnchainConfig, cc.OffchainConfigVersion, cc.OffchainConfig, - ) + d.Prefix, + ), nil } -func (d OffchainConfigDigester) ConfigDigestPrefix() (ocrtypes.ConfigDigestPrefix, error) { - return ocrtypes.ConfigDigestPrefixLLO, nil +func (d OffchainConfigDigester) ConfigDigestPrefix(context.Context) (ocrtypes.ConfigDigestPrefix, error) { + return d.Prefix, nil } func makeConfigDigestArgs() abi.Arguments { - abi, err := abi.JSON(strings.NewReader(exposed_channel_verifier.ExposedChannelVerifierABI)) + abi, err := abi.JSON(strings.NewReader(exposed_configurator.ExposedConfiguratorABI)) if err != nil { // assertion - panic(fmt.Sprintf("could not parse aggregator ABI: %s", err.Error())) + panic(fmt.Sprintf("could not parse configurator ABI: %s", err.Error())) } return abi.Methods["exposedConfigDigestFromConfigData"].Inputs } @@ -86,21 +90,24 @@ func makeConfigDigestArgs() abi.Arguments { var configDigestArgs = makeConfigDigestArgs() func configDigest( + feedID common.Hash, chainID *big.Int, contractAddress common.Address, configCount uint64, - oracles []common.Address, + onchainPubKeys [][]byte, transmitters []credentials.StaticSizedPublicKey, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, -) (types.ConfigDigest, error) { + prefix types.ConfigDigestPrefix, +) types.ConfigDigest { msg, err := configDigestArgs.Pack( + feedID, chainID, contractAddress, configCount, - oracles, + onchainPubKeys, transmitters, f, onchainConfig, @@ -108,16 +115,15 @@ func configDigest( offchainConfig, ) if err != nil { - return types.ConfigDigest{}, fmt.Errorf("could not pack config digest args: %v", err) + // assertion + panic(err) } rawHash := crypto.Keccak256(msg) configDigest := types.ConfigDigest{} if n := copy(configDigest[:], rawHash); n != len(configDigest) { - return types.ConfigDigest{}, fmt.Errorf("copied too little data: %d/%d", n, len(configDigest)) - } - binary.BigEndian.PutUint16(configDigest[:2], uint16(ocrtypes.ConfigDigestPrefixLLO)) - if !(configDigest[0] == 0 && configDigest[1] == 9) { - return types.ConfigDigest{}, fmt.Errorf("wrong ConfigDigestPrefix; got: %x, expected: %d", configDigest[:2], ocrtypes.ConfigDigestPrefixLLO) + // assertion + panic("copy too little data") } - return configDigest, nil + binary.BigEndian.PutUint16(configDigest[:2], uint16(prefix)) + return configDigest } diff --git a/core/services/llo/offchain_config_digester_test.go b/core/services/relay/evm/llo/offchain_config_digester_test.go similarity index 59% rename from core/services/llo/offchain_config_digester_test.go rename to core/services/relay/evm/llo/offchain_config_digester_test.go index 0de9117e391..65e888310c7 100644 --- a/core/services/llo/offchain_config_digester_test.go +++ b/core/services/relay/evm/llo/offchain_config_digester_test.go @@ -6,18 +6,22 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) func Test_OffchainConfigDigester_ConfigDigest(t *testing.T) { + ctx := tests.Context(t) // ChainID and ContractAddress are taken into account for computation - cd1, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(types.ContractConfig{}) + cd1, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) - cd2, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(types.ContractConfig{}) + cd2, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) - cd3, err := OffchainConfigDigester{ChainID: big.NewInt(1)}.ConfigDigest(types.ContractConfig{}) + cd3, err := OffchainConfigDigester{ChainID: big.NewInt(1)}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) - cd4, err := OffchainConfigDigester{ChainID: big.NewInt(1), ContractAddress: common.Address{1}}.ConfigDigest(types.ContractConfig{}) + cd4, err := OffchainConfigDigester{ChainID: big.NewInt(1), ContractAddress: common.Address{1}}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) require.Equal(t, cd1, cd2) @@ -25,30 +29,36 @@ func Test_OffchainConfigDigester_ConfigDigest(t *testing.T) { require.NotEqual(t, cd2, cd4) require.NotEqual(t, cd3, cd4) - // malformed signers - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + configID := common.HexToHash("0x1") + chainID := big.NewInt(2) + addr := common.HexToAddress("0x3") + prefix := ocrtypes.ConfigDigestPrefix(4) + + digester := NewOffchainConfigDigester(configID, chainID, addr, prefix) + // any signers ok + _, err = digester.ConfigDigest(ctx, types.ContractConfig{ Signers: []types.OnchainPublicKey{{1, 2}}, }) - require.Error(t, err) + require.NoError(t, err) // malformed transmitters - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = digester.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"0x"}, }) require.Error(t, err) - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = digester.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"7343581f55146951b0f678dc6cfa8fd360e2f353"}, }) require.Error(t, err) - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = digester.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"7343581f55146951b0f678dc6cfa8fd360e2f353aabbccddeeffaaccddeeffaz"}, }) require.Error(t, err) // well-formed transmitters - _, err = OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(types.ContractConfig{ + _, err = digester.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"7343581f55146951b0f678dc6cfa8fd360e2f353aabbccddeeffaaccddeeffaa"}, }) require.NoError(t, err) diff --git a/core/services/relay/evm/llo/should_retire_cache.go b/core/services/relay/evm/llo/should_retire_cache.go new file mode 100644 index 00000000000..05b33a27fbb --- /dev/null +++ b/core/services/relay/evm/llo/should_retire_cache.go @@ -0,0 +1,120 @@ +package llo + +import ( + "bytes" + "context" + "math" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" +) + +type ShouldRetireCacheService interface { + services.Service + llotypes.ShouldRetireCache +} + +type shouldRetireCache struct { + services.Service + eng *services.Engine + + lp LogPoller + addr common.Address + donID uint32 + donIDHash common.Hash + + pollPeriod time.Duration + + mu sync.RWMutex + latestBlockNum int64 + m map[ocrtypes.ConfigDigest]struct{} +} + +func NewShouldRetireCache(lggr logger.Logger, lp LogPoller, addr common.Address, donID uint32) ShouldRetireCacheService { + return newShouldRetireCache(lggr, lp, addr, donID) +} + +func newShouldRetireCache(lggr logger.Logger, lp LogPoller, addr common.Address, donID uint32) *shouldRetireCache { + s := &shouldRetireCache{ + lp: lp, + addr: addr, + donID: donID, + donIDHash: DonIDToBytes32(donID), + m: make(map[ocrtypes.ConfigDigest]struct{}), + pollPeriod: 1 * time.Second, + } + s.Service, s.eng = services.Config{ + Name: "LLOShouldRetireCache", + Start: s.start, + }.NewServiceEngine(lggr) + + return s +} + +func (s *shouldRetireCache) ShouldRetire(digest ocr2types.ConfigDigest) (bool, error) { + s.mu.RLock() + defer s.mu.RUnlock() + _, exists := s.m[digest] + if exists { + s.eng.SugaredLogger.Debugw("ShouldRetire", "digest", digest, "shouldRetire", exists) + } + return exists, nil +} + +func (s *shouldRetireCache) start(ctx context.Context) error { + t := services.TickerConfig{ + Initial: 0, + JitterPct: services.DefaultJitter, + }.NewTicker(s.pollPeriod) + s.eng.GoTick(t, s.checkShouldRetire) + return nil +} + +func (s *shouldRetireCache) checkShouldRetire(ctx context.Context) { + fromBlock := s.latestBlockNum + 1 + logs, err := s.lp.LogsWithSigs(ctx, fromBlock, math.MaxInt64, []common.Hash{PromoteStagingConfig}, s.addr) + if err != nil { + s.eng.SugaredLogger.Errorw("checkShouldRetire: IndexedLogs", "err", err) + return + } + + for _, log := range logs { + // TODO: This can probably be optimized + // MERC-3524 + if !bytes.Equal(log.Topics[1], s.donIDHash[:]) { + continue + } + digestBytes := log.Topics[2] + digest, err := ocrtypes.BytesToConfigDigest(digestBytes) + if err != nil { + s.eng.SugaredLogger.Errorw("checkShouldRetire: BytesToConfigDigest failed", "err", err) + return + } + s.eng.SugaredLogger.Infow("markRetired: Got retired config digest", "blockNum", log.BlockNumber, "configDigest", digest) + s.markRetired(digest) + if log.BlockNumber > s.latestBlockNum { + s.latestBlockNum = log.BlockNumber + } + } +} + +func (s *shouldRetireCache) markRetired(configDigest ocrtypes.ConfigDigest) { + s.mu.RLock() + _, exists := s.m[configDigest] + s.mu.RUnlock() + if exists { + // already marked as retired + return + } + + s.mu.Lock() + defer s.mu.Unlock() + s.m[configDigest] = struct{}{} +} diff --git a/core/services/relay/evm/llo/should_retire_cache_test.go b/core/services/relay/evm/llo/should_retire_cache_test.go new file mode 100644 index 00000000000..2583ecc3c83 --- /dev/null +++ b/core/services/relay/evm/llo/should_retire_cache_test.go @@ -0,0 +1,50 @@ +package llo + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/lib/pq" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +func Test_ShouldRetireCache(t *testing.T) { + lggr, observedLogs := logger.TestObserved(t, zapcore.DebugLevel) + lp := &mockLogPoller{make([]logpoller.Log, 0), 0} + addr := common.Address{1} + donID := uint32(1) + donIDHash := DonIDToBytes32(donID) + retiredConfigDigest := ocr2types.ConfigDigest{1, 2, 3, 4} + + lp.logs = append(lp.logs, logpoller.Log{Address: addr, Topics: pq.ByteaArray{PromoteStagingConfig[:], donIDHash[:], retiredConfigDigest[:]}, EventSig: PromoteStagingConfig, BlockNumber: 100, Data: makePromoteStagingConfigData(t, false)}) + + src := newShouldRetireCache(lggr, lp, addr, donID) + + servicetest.Run(t, src) + + testutils.WaitForLogMessage(t, observedLogs, "markRetired: Got retired config digest") + + shouldRetire, err := src.ShouldRetire(retiredConfigDigest) + require.NoError(t, err) + assert.True(t, shouldRetire, "Should retire") + shouldRetire, err = src.ShouldRetire(ocr2types.ConfigDigest{9}) + require.NoError(t, err) + assert.False(t, shouldRetire, "Should not retire") +} + +func makePromoteStagingConfigData(t *testing.T, isGreenProduction bool) []byte { + event := configuratorABI.Events["PromoteStagingConfig"] + data, err := event.Inputs.NonIndexed().Pack(isGreenProduction) + require.NoError(t, err) + return data +} diff --git a/core/services/relay/evm/llo_config_provider.go b/core/services/relay/evm/llo_config_provider.go index 6efd0ccada2..99f2824a5c9 100644 --- a/core/services/relay/evm/llo_config_provider.go +++ b/core/services/relay/evm/llo_config_provider.go @@ -2,22 +2,106 @@ package evm import ( "context" + "fmt" "github.com/ethereum/go-ethereum/common" - pkgerrors "github.com/pkg/errors" + "github.com/pkg/errors" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/llo" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/llo" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -func newLLOConfigProvider(ctx context.Context, lggr logger.Logger, chain legacyevm.Chain, opts *types.RelayOpts) (*configWatcher, error) { +// This is only used for the bootstrap job + +var _ commontypes.ConfigProvider = (*lloConfigProvider)(nil) + +type lloConfigProvider struct { + services.Service + eng *services.Engine + + lp FilterRegisterer + cps []llo.ConfigPollerService + digester ocrtypes.OffchainConfigDigester + runReplay bool + replayFromBlock uint64 + + ms services.MultiStart +} + +func (l *lloConfigProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { + return l.digester +} +func (l *lloConfigProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker { + // FIXME: Only return Blue for now. This is a hack to make the bootstrap + // job work, needs to support multiple config trackers here + // MERC-5954 + return l.cps[0] +} + +func newLLOConfigProvider( + ctx context.Context, + lggr logger.Logger, + chain legacyevm.Chain, + cc llo.ConfigCache, + opts *types.RelayOpts, +) (commontypes.ConfigProvider, error) { if !common.IsHexAddress(opts.ContractID) { - return nil, pkgerrors.Errorf("invalid contractID, expected hex address") + return nil, errors.New("invalid contractID, expected hex address") + } + + configuratorAddress := common.HexToAddress(opts.ContractID) + + relayConfig, err := opts.RelayConfig() + if err != nil { + return nil, fmt.Errorf("failed to get relay config: %w", err) + } + donID := relayConfig.LLODONID + if donID == 0 { + return nil, errors.New("donID must be specified in relayConfig for LLO jobs") + } + + lp := chain.LogPoller() + + cps, digester, err := newLLOConfigPollers(ctx, lggr, cc, lp, chain.Config().EVM().ChainID(), configuratorAddress, relayConfig) + if err != nil { + return nil, err } - aggregatorAddress := common.HexToAddress(opts.ContractID) - configDigester := llo.NewOffchainConfigDigester(chain.Config().EVM().ChainID(), aggregatorAddress) - return newContractConfigProvider(ctx, lggr, chain, opts, aggregatorAddress, ChannelVerifierLogDecoder, configDigester) + p := &lloConfigProvider{nil, nil, lp, cps, digester, opts.New, relayConfig.FromBlock, services.MultiStart{}} + p.Service, p.eng = services.Config{ + Name: "LLOConfigProvider", + Start: p.start, + Close: p.close, + }.NewServiceEngine(lggr) + return p, nil +} + +func (l *lloConfigProvider) start(ctx context.Context) error { + if l.runReplay && l.replayFromBlock != 0 { + // Only replay if it's a brand new job. + l.eng.Go(func(ctx context.Context) { + l.eng.Infow("starting replay for config", "fromBlock", l.replayFromBlock) + // #nosec G115 + if err := l.lp.Replay(ctx, int64(l.replayFromBlock)); err != nil { + l.eng.Errorw("error replaying for config", "err", err) + } else { + l.eng.Infow("completed replaying for config", "replayFromBlock", l.replayFromBlock) + } + }) + } + srvs := []services.StartClose{} + for _, cp := range l.cps { + srvs = append(srvs, cp) + } + err := l.ms.Start(ctx, srvs...) + return err +} + +func (l *lloConfigProvider) close() error { + return l.ms.Close() } diff --git a/core/services/relay/evm/llo_provider.go b/core/services/relay/evm/llo_provider.go index b685565e6e0..1f4bdbf6e0c 100644 --- a/core/services/relay/evm/llo_provider.go +++ b/core/services/relay/evm/llo_provider.go @@ -3,55 +3,142 @@ package evm import ( "context" "errors" + "fmt" + "math/big" + "github.com/ethereum/go-ethereum/common" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/llo" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/llo" ) var _ commontypes.LLOProvider = (*lloProvider)(nil) +type LLOTransmitter interface { + services.Service + llotypes.Transmitter +} + +type FilterRegisterer interface { + Replay(ctx context.Context, fromBlock int64) error + RegisterFilter(ctx context.Context, filter logpoller.Filter) error +} + type lloProvider struct { - cp commontypes.ConfigProvider - transmitter llo.Transmitter + services.Service + eng *services.Engine + + cps []llo.ConfigPollerService + + transmitter LLOTransmitter logger logger.Logger channelDefinitionCache llotypes.ChannelDefinitionCache + digester ocrtypes.OffchainConfigDigester + shouldRetireCache llo.ShouldRetireCacheService + + lp FilterRegisterer + runReplay bool + replayFromBlock uint64 ms services.MultiStart } +func lloProviderConfiguratorFilterName(addr common.Address, donID uint32) string { + return logpoller.FilterName("LLOProvider Configurator", addr.String(), fmt.Sprintf("%d", donID)) +} + func NewLLOProvider( - cp commontypes.ConfigProvider, - transmitter llo.Transmitter, + ctx context.Context, + transmitter LLOTransmitter, lggr logger.Logger, + cc llo.ConfigCache, + chain legacyevm.Chain, + configuratorAddress common.Address, channelDefinitionCache llotypes.ChannelDefinitionCache, -) relaytypes.LLOProvider { - return &lloProvider{ - cp, + relayConfig types.RelayConfig, + relayOpts *types.RelayOpts, +) (relaytypes.LLOProvider, error) { + donID := relayConfig.LLODONID + lp := chain.LogPoller() + lggr = logger.Sugared(lggr).With("configMode", relayConfig.LLOConfigMode, "configuratorAddress", configuratorAddress, "donID", donID) + lggr = logger.Named(lggr, fmt.Sprintf("LLO-%d", donID)) + + cps, digester, err := newLLOConfigPollers(ctx, lggr, cc, lp, chain.Config().EVM().ChainID(), configuratorAddress, relayConfig) + if err != nil { + return nil, err + } + src := llo.NewShouldRetireCache(lggr, lp, configuratorAddress, donID) + + p := &lloProvider{ + nil, + nil, + cps, transmitter, - lggr.Named("LLOProvider"), + logger.Named(lggr, "LLOProvider"), channelDefinitionCache, + digester, + src, + lp, + relayOpts.New, + relayConfig.FromBlock, services.MultiStart{}, } + + p.Service, p.eng = services.Config{ + Name: "LLOProvider", + Start: p.start, + Close: p.close, + }.NewServiceEngine(lggr) + + return p, nil } -func (p *lloProvider) Start(ctx context.Context) error { - err := p.ms.Start(ctx, p.cp, p.transmitter, p.channelDefinitionCache) +func (p *lloProvider) start(ctx context.Context) error { + // NOTE: Remember that all filters must be registered first for this replay + // to be effective + // 1. Replay + // 2. Start all services + if p.runReplay && p.replayFromBlock != 0 { + // Only replay if it's a brand new job. + p.eng.Go(func(ctx context.Context) { + p.eng.Infow("starting replay for config", "fromBlock", p.replayFromBlock) + // #nosec G115 + if err := p.lp.Replay(ctx, int64(p.replayFromBlock)); err != nil { + p.eng.Errorw("error replaying for config", "err", err) + } else { + p.eng.Infow("completed replaying for config", "replayFromBlock", p.replayFromBlock) + } + }) + } + srvs := []services.StartClose{p.transmitter, p.channelDefinitionCache, p.shouldRetireCache} + for _, cp := range p.cps { + srvs = append(srvs, cp) + } + err := p.ms.Start(ctx, srvs...) return err } -func (p *lloProvider) Close() error { +func (p *lloProvider) close() error { return p.ms.Close() } func (p *lloProvider) Ready() error { - return errors.Join(p.cp.Ready(), p.transmitter.Ready(), p.channelDefinitionCache.Ready()) + errs := make([]error, len(p.cps)) + for i, cp := range p.cps { + errs[i] = cp.Ready() + } + errs = append(errs, p.transmitter.Ready(), p.channelDefinitionCache.Ready(), p.shouldRetireCache.Ready()) + return errors.Join(errs...) } func (p *lloProvider) Name() string { @@ -60,22 +147,25 @@ func (p *lloProvider) Name() string { func (p *lloProvider) HealthReport() map[string]error { report := map[string]error{} - services.CopyHealth(report, p.cp.HealthReport()) + for _, cp := range p.cps { + services.CopyHealth(report, cp.HealthReport()) + } services.CopyHealth(report, p.transmitter.HealthReport()) services.CopyHealth(report, p.channelDefinitionCache.HealthReport()) + services.CopyHealth(report, p.shouldRetireCache.HealthReport()) return report } -func (p *lloProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker { - return p.cp.ContractConfigTracker() +func (p *lloProvider) ContractConfigTrackers() (cps []ocrtypes.ContractConfigTracker) { + cps = make([]ocrtypes.ContractConfigTracker, len(p.cps)) + for i, cp := range p.cps { + cps[i] = cp + } + return } func (p *lloProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { - return p.cp.OffchainConfigDigester() -} - -func (p *lloProvider) OnchainConfigCodec() llo.OnchainConfigCodec { - return &llo.JSONOnchainConfigCodec{} + return p.digester } func (p *lloProvider) ContractTransmitter() llotypes.Transmitter { @@ -85,3 +175,98 @@ func (p *lloProvider) ContractTransmitter() llotypes.Transmitter { func (p *lloProvider) ChannelDefinitionCache() llotypes.ChannelDefinitionCache { return p.channelDefinitionCache } + +func (p *lloProvider) ShouldRetireCache() llotypes.ShouldRetireCache { + return p.shouldRetireCache +} + +// wrapper is needed to turn mercury config poller into a service +type mercuryConfigPollerWrapper struct { + *mercury.ConfigPoller + services.Service + eng *services.Engine + + runReplay bool + fromBlock uint64 +} + +func newMercuryConfigPollerWrapper(lggr logger.Logger, cp *mercury.ConfigPoller, fromBlock uint64, runReplay bool) *mercuryConfigPollerWrapper { + w := &mercuryConfigPollerWrapper{cp, nil, nil, runReplay, fromBlock} + w.Service, w.eng = services.Config{ + Name: "LLOMercuryConfigWrapper", + Start: w.start, + Close: w.close, + }.NewServiceEngine(lggr) + return w +} + +func (w *mercuryConfigPollerWrapper) Start(ctx context.Context) error { + return w.Service.Start(ctx) +} + +func (w *mercuryConfigPollerWrapper) start(ctx context.Context) error { + w.ConfigPoller.Start() + return nil +} + +func (w *mercuryConfigPollerWrapper) Close() error { + return w.Service.Close() +} + +func (w *mercuryConfigPollerWrapper) close() error { + return w.ConfigPoller.Close() +} + +func newLLOConfigPollers(ctx context.Context, lggr logger.Logger, cc llo.ConfigCache, lp logpoller.LogPoller, chainID *big.Int, configuratorAddress common.Address, relayConfig types.RelayConfig) (cps []llo.ConfigPollerService, configDigester ocrtypes.OffchainConfigDigester, err error) { + donID := relayConfig.LLODONID + donIDHash := llo.DonIDToBytes32(donID) + // TODO: Can we auto-detect or verify based on if the contract implements `setConfig` or `setProductionConfig` interfaces? + // MERC-3524 + switch relayConfig.LLOConfigMode { + case types.LLOConfigModeMercury: + // NOTE: This uses the old config digest prefix for compatibility with legacy contracts + configDigester = mercury.NewOffchainConfigDigester(donIDHash, chainID, configuratorAddress, ocrtypes.ConfigDigestPrefixMercuryV02) + // Mercury config poller will register its own filter + mcp, err := mercury.NewConfigPoller( + ctx, + lggr, + lp, + configuratorAddress, + llo.DonIDToBytes32(donID), + ) + if err != nil { + return nil, nil, err + } + // don't need to replay in the wrapper since the provider will handle it + w := newMercuryConfigPollerWrapper(lggr, mcp, relayConfig.FromBlock, false) + cps = []llo.ConfigPollerService{w} + case types.LLOConfigModeBlueGreen: + // NOTE: Register filter here because the config poller doesn't do it on its own + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: lloProviderConfiguratorFilterName(configuratorAddress, donID), EventSigs: []common.Hash{llo.ProductionConfigSet, llo.StagingConfigSet, llo.PromoteStagingConfig}, Topic2: []common.Hash{donIDHash}, Addresses: []common.Address{configuratorAddress}}) + if err != nil { + return nil, nil, fmt.Errorf("failed to register filter: %w", err) + } + + configDigester = llo.NewOffchainConfigDigester(donIDHash, chainID, configuratorAddress, ocrtypes.ConfigDigestPrefixLLO) + blueCP := llo.NewConfigPoller( + lggr, + lp, + cc, + configuratorAddress, + donID, + llo.InstanceTypeBlue, + relayConfig.FromBlock, + ) + greenCP := llo.NewConfigPoller( + lggr, + lp, + cc, + configuratorAddress, + donID, + llo.InstanceTypeGreen, + relayConfig.FromBlock, + ) + cps = []llo.ConfigPollerService{blueCP, greenCP} + } + return cps, configDigester, nil +} diff --git a/core/services/relay/evm/llo_verifier_decoder.go b/core/services/relay/evm/llo_verifier_decoder.go deleted file mode 100644 index 922b83bec0d..00000000000 --- a/core/services/relay/evm/llo_verifier_decoder.go +++ /dev/null @@ -1,67 +0,0 @@ -package evm - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_verifier" -) - -var _ LogDecoder = &channelVerifierLogDecoder{} - -type channelVerifierLogDecoder struct { - eventName string - eventSig common.Hash - abi *abi.ABI -} - -func newChannelVerifierLogDecoder() (*channelVerifierLogDecoder, error) { - const eventName = "ConfigSet" - abi, err := channel_verifier.ChannelVerifierMetaData.GetAbi() - if err != nil { - return nil, err - } - return &channelVerifierLogDecoder{ - eventName: eventName, - eventSig: abi.Events[eventName].ID, - abi: abi, - }, nil -} - -func (d *channelVerifierLogDecoder) Decode(rawLog []byte) (ocrtypes.ContractConfig, error) { - unpacked := new(channel_verifier.ChannelVerifierConfigSet) - err := d.abi.UnpackIntoInterface(unpacked, d.eventName, rawLog) - if err != nil { - return ocrtypes.ContractConfig{}, errors.Wrap(err, "failed to unpack log data") - } - - var transmitAccounts []ocrtypes.Account - for _, addr := range unpacked.OffchainTransmitters { - transmitAccounts = append(transmitAccounts, ocrtypes.Account(fmt.Sprintf("%x", addr))) - } - var signers []ocrtypes.OnchainPublicKey - for _, addr := range unpacked.Signers { - addr := addr - signers = append(signers, addr[:]) - } - - return ocrtypes.ContractConfig{ - ConfigDigest: unpacked.ConfigDigest, - ConfigCount: unpacked.ConfigCount, - Signers: signers, - Transmitters: transmitAccounts, - F: unpacked.F, - OnchainConfig: unpacked.OnchainConfig, - OffchainConfigVersion: unpacked.OffchainConfigVersion, - OffchainConfig: unpacked.OffchainConfig, - }, nil -} - -func (d *channelVerifierLogDecoder) EventSig() common.Hash { - return d.eventSig -} diff --git a/core/services/relay/evm/loop_impl.go b/core/services/relay/evm/loop_impl.go index aec956cd0d2..3fd1de910b3 100644 --- a/core/services/relay/evm/loop_impl.go +++ b/core/services/relay/evm/loop_impl.go @@ -2,30 +2,29 @@ package evm import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) -type LoopRelayAdapter interface { +type LOOPRelayAdapter interface { loop.Relayer Chain() legacyevm.Chain } -type LoopRelayer struct { +type loopRelayAdapter struct { loop.Relayer - ext EVMChainRelayerExtender + chain legacyevm.Chain } -var _ loop.Relayer = &LoopRelayer{} +var _ LOOPRelayAdapter = &loopRelayAdapter{} -func NewLoopRelayServerAdapter(r *Relayer, cs EVMChainRelayerExtender) *LoopRelayer { - ra := relay.NewServerAdapter(r, cs) - return &LoopRelayer{ - Relayer: ra, - ext: cs, +func NewLOOPRelayAdapter(r *Relayer) *loopRelayAdapter { + return &loopRelayAdapter{ + Relayer: relay.NewServerAdapter(r), + chain: r.chain, } } -func (la *LoopRelayer) Chain() legacyevm.Chain { - return la.ext.Chain() +func (la *loopRelayAdapter) Chain() legacyevm.Chain { + return la.chain } diff --git a/core/services/relay/evm/median.go b/core/services/relay/evm/median.go index 2407cff7140..1dddb201ebb 100644 --- a/core/services/relay/evm/median.go +++ b/core/services/relay/evm/median.go @@ -8,16 +8,17 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) var _ median.MedianContract = &medianContract{} @@ -30,8 +31,8 @@ type medianContract struct { requestRoundTracker *RequestRoundTracker } -func newMedianContract(configTracker types.ContractConfigTracker, contractAddress common.Address, chain legacyevm.Chain, specID int32, ds sqlutil.DataSource, lggr logger.Logger) (*medianContract, error) { - lggr = lggr.Named("MedianContract") +func newMedianContract(configTracker types.ContractConfigTracker, contractAddress common.Address, chain legacyevm.Chain, jobID int32, oracleSpecID int32, ds sqlutil.DataSource, lggr logger.Logger) (*medianContract, error) { + lggr = logger.Named(lggr, "MedianContract") contract, err := offchain_aggregator_wrapper.NewOffchainAggregator(contractAddress, chain.Client()) if err != nil { return nil, errors.Wrap(err, "could not instantiate NewOffchainAggregator") @@ -56,10 +57,10 @@ func newMedianContract(configTracker types.ContractConfigTracker, contractAddres contractFilterer, chain.Client(), chain.LogBroadcaster(), - specID, + jobID, lggr, ds, - NewRoundRequestedDB(ds, specID, lggr), + NewRoundRequestedDB(ds, oracleSpecID, lggr), chain.Config().EVM(), ), }, nil diff --git a/core/services/relay/evm/median_test.go b/core/services/relay/evm/median_test.go index 9c474006aa7..9fa612dabcd 100644 --- a/core/services/relay/evm/median_test.go +++ b/core/services/relay/evm/median_test.go @@ -7,23 +7,23 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "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" ) func TestNewMedianProvider(t *testing.T) { - lggr := logger.TestLogger(t) + lggr := logger.Test(t) chain := mocks.NewChain(t) chainID := testutils.NewRandomEVMChainID() chain.On("ID").Return(chainID) contractID := testutils.NewAddress() - relayer := Relayer{lggr: lggr, chain: chain} + relayer := Relayer{lggr: logger.Sugared(lggr), chain: chain} pargs := commontypes.PluginArgs{} @@ -32,7 +32,7 @@ func TestNewMedianProvider(t *testing.T) { rc, err2 := json.Marshal(&relayConfigBadChainID) rargs2 := commontypes.RelayArgs{ContractID: contractID.String(), RelayConfig: rc} require.NoError(t, err2) - _, err2 = relayer.NewMedianProvider(rargs2, pargs) + _, err2 = relayer.NewMedianProvider(testutils.Context(t), rargs2, pargs) assert.ErrorContains(t, err2, "chain id in spec does not match") }) @@ -41,7 +41,7 @@ func TestNewMedianProvider(t *testing.T) { rc, err2 := json.Marshal(&relayConfig) require.NoError(t, err2) rargsBadContractID := commontypes.RelayArgs{ContractID: "NotAContractID", RelayConfig: rc} - _, err2 = relayer.NewMedianProvider(rargsBadContractID, pargs) + _, err2 = relayer.NewMedianProvider(testutils.Context(t), rargsBadContractID, pargs) assert.ErrorContains(t, err2, "invalid contractID") }) } diff --git a/core/services/relay/evm/mercury/config_digest.go b/core/services/relay/evm/mercury/config_digest.go index 291a723ee3a..c7a6076c886 100644 --- a/core/services/relay/evm/mercury/config_digest.go +++ b/core/services/relay/evm/mercury/config_digest.go @@ -37,6 +37,7 @@ func configDigest( onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, + prefix types.ConfigDigestPrefix, ) types.ConfigDigest { msg, err := configDigestArgs.Pack( feedID, @@ -60,10 +61,6 @@ func configDigest( // assertion panic("copy too little data") } - binary.BigEndian.PutUint16(configDigest[:2], uint16(types.ConfigDigestPrefixMercuryV02)) - if !(configDigest[0] == 0 && configDigest[1] == 6) { - // assertion - panic("unexpected mismatch") - } + binary.BigEndian.PutUint16(configDigest[:2], uint16(prefix)) return configDigest } diff --git a/core/services/relay/evm/mercury/config_digest_test.go b/core/services/relay/evm/mercury/config_digest_test.go index fe718e92fe5..680513688a4 100644 --- a/core/services/relay/evm/mercury/config_digest_test.go +++ b/core/services/relay/evm/mercury/config_digest_test.go @@ -15,6 +15,7 @@ import ( "github.com/leanovate/gopter" "github.com/leanovate/gopter/gen" "github.com/leanovate/gopter/prop" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/wsrpc/credentials" "github.com/stretchr/testify/require" @@ -63,6 +64,7 @@ func TestConfigCalculationMatches(t *testing.T) { onchainConfig, offchainConfigVersion, offchainConfig, + ocrtypes.ConfigDigestPrefixMercuryV02, ) bigChainID := new(big.Int) diff --git a/core/services/relay/evm/mercury/config_poller.go b/core/services/relay/evm/mercury/config_poller.go index 2da541a8e42..7bb5d2af7b5 100644 --- a/core/services/relay/evm/mercury/config_poller.go +++ b/core/services/relay/evm/mercury/config_poller.go @@ -11,9 +11,10 @@ import ( "github.com/pkg/errors" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" ) @@ -53,7 +54,7 @@ func unpackLogData(d []byte) (*verifier.VerifierConfigSet, error) { return unpacked, nil } -func configFromLog(logData []byte) (FullConfigFromLog, error) { +func ConfigFromLog(logData []byte) (FullConfigFromLog, error) { unpacked, err := unpackLogData(logData) if err != nil { return FullConfigFromLog{}, err @@ -139,7 +140,7 @@ func (cp *ConfigPoller) LatestConfigDetails(ctx context.Context) (changedInBlock return 0, ocrtypes.ConfigDigest{}, nil } latest := logs[len(logs)-1] - latestConfigSet, err := configFromLog(latest.Data) + latestConfigSet, err := ConfigFromLog(latest.Data) if err != nil { return 0, ocrtypes.ConfigDigest{}, err } @@ -155,7 +156,7 @@ func (cp *ConfigPoller) LatestConfig(ctx context.Context, changedInBlock uint64) if len(lgs) == 0 { return ocrtypes.ContractConfig{}, nil } - latestConfigSet, err := configFromLog(lgs[len(lgs)-1].Data) + latestConfigSet, err := ConfigFromLog(lgs[len(lgs)-1].Data) if err != nil { return ocrtypes.ContractConfig{}, err } diff --git a/core/services/relay/evm/mercury/config_poller_test.go b/core/services/relay/evm/mercury/config_poller_test.go index f828938f954..400ecdaf244 100644 --- a/core/services/relay/evm/mercury/config_poller_test.go +++ b/core/services/relay/evm/mercury/config_poller_test.go @@ -62,7 +62,8 @@ func TestMercuryConfigPoller(t *testing.T) { 100, // rMax []int{len(oracles)}, // S oracles, - []byte{}, // reportingPluginConfig []byte, + []byte{}, // reportingPluginConfig []byte, + nil, 0, // Max duration query 250*time.Millisecond, // Max duration observation 250*time.Millisecond, // MaxDurationReport diff --git a/core/services/relay/evm/mercury/mocks/pipeline.go b/core/services/relay/evm/mercury/mocks/pipeline.go index 44be1377aeb..a7183c9a037 100644 --- a/core/services/relay/evm/mercury/mocks/pipeline.go +++ b/core/services/relay/evm/mercury/mocks/pipeline.go @@ -23,6 +23,10 @@ type MockTask struct { result pipeline.Result } +func (m *MockTask) GetDescendantTasks() []pipeline.Task { return nil } + +func (m *MockTask) TaskTags() string { return "{\"anything\": \"here\"}" } + func (m *MockTask) Type() pipeline.TaskType { return "MockTask" } func (m *MockTask) ID() int { return 0 } func (m *MockTask) DotID() string { return "" } diff --git a/core/services/relay/evm/mercury/offchain_config_digester.go b/core/services/relay/evm/mercury/offchain_config_digester.go index f9ba0b23095..e771053c37b 100644 --- a/core/services/relay/evm/mercury/offchain_config_digester.go +++ b/core/services/relay/evm/mercury/offchain_config_digester.go @@ -1,6 +1,7 @@ package mercury import ( + "context" "crypto/ed25519" "encoding/hex" "math/big" @@ -18,17 +19,18 @@ import ( var _ ocrtypes.OffchainConfigDigester = OffchainConfigDigester{} -func NewOffchainConfigDigester(feedID [32]byte, chainID *big.Int, contractAddress common.Address) OffchainConfigDigester { - return OffchainConfigDigester{feedID, chainID, contractAddress} +func NewOffchainConfigDigester(feedID [32]byte, chainID *big.Int, contractAddress common.Address, prefix ocrtypes.ConfigDigestPrefix) OffchainConfigDigester { + return OffchainConfigDigester{feedID, chainID, contractAddress, prefix} } type OffchainConfigDigester struct { FeedID utils.FeedID ChainID *big.Int ContractAddress common.Address + Prefix ocrtypes.ConfigDigestPrefix } -func (d OffchainConfigDigester) ConfigDigest(cc ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { +func (d OffchainConfigDigester) ConfigDigest(ctx context.Context, cc ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { signers := []common.Address{} for i, signer := range cc.Signers { if len(signer) != 20 { @@ -63,9 +65,10 @@ func (d OffchainConfigDigester) ConfigDigest(cc ocrtypes.ContractConfig) (ocrtyp cc.OnchainConfig, cc.OffchainConfigVersion, cc.OffchainConfig, + d.Prefix, ), nil } -func (d OffchainConfigDigester) ConfigDigestPrefix() (ocrtypes.ConfigDigestPrefix, error) { - return ocrtypes.ConfigDigestPrefixMercuryV02, nil +func (d OffchainConfigDigester) ConfigDigestPrefix(ctx context.Context) (ocrtypes.ConfigDigestPrefix, error) { + return d.Prefix, nil } diff --git a/core/services/relay/evm/mercury/offchain_config_digester_test.go b/core/services/relay/evm/mercury/offchain_config_digester_test.go index c5d39926576..62869cf6f3d 100644 --- a/core/services/relay/evm/mercury/offchain_config_digester_test.go +++ b/core/services/relay/evm/mercury/offchain_config_digester_test.go @@ -7,17 +7,20 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) func Test_OffchainConfigDigester_ConfigDigest(t *testing.T) { + ctx := tests.Context(t) // ChainID and ContractAddress are taken into account for computation - cd1, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(types.ContractConfig{}) + cd1, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) - cd2, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(types.ContractConfig{}) + cd2, err := OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) - cd3, err := OffchainConfigDigester{ChainID: big.NewInt(1)}.ConfigDigest(types.ContractConfig{}) + cd3, err := OffchainConfigDigester{ChainID: big.NewInt(1)}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) - cd4, err := OffchainConfigDigester{ChainID: big.NewInt(1), ContractAddress: common.Address{1}}.ConfigDigest(types.ContractConfig{}) + cd4, err := OffchainConfigDigester{ChainID: big.NewInt(1), ContractAddress: common.Address{1}}.ConfigDigest(ctx, types.ContractConfig{}) require.NoError(t, err) require.Equal(t, cd1, cd2) @@ -26,29 +29,29 @@ func Test_OffchainConfigDigester_ConfigDigest(t *testing.T) { require.NotEqual(t, cd3, cd4) // malformed signers - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = OffchainConfigDigester{}.ConfigDigest(ctx, types.ContractConfig{ Signers: []types.OnchainPublicKey{{1, 2}}, }) require.Error(t, err) // malformed transmitters - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = OffchainConfigDigester{}.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"0x"}, }) require.Error(t, err) - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = OffchainConfigDigester{}.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"7343581f55146951b0f678dc6cfa8fd360e2f353"}, }) require.Error(t, err) - _, err = OffchainConfigDigester{}.ConfigDigest(types.ContractConfig{ + _, err = OffchainConfigDigester{}.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"7343581f55146951b0f678dc6cfa8fd360e2f353aabbccddeeffaaccddeeffaz"}, }) require.Error(t, err) // well-formed transmitters - _, err = OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(types.ContractConfig{ + _, err = OffchainConfigDigester{ChainID: big.NewInt(0)}.ConfigDigest(ctx, types.ContractConfig{ Transmitters: []types.Account{"7343581f55146951b0f678dc6cfa8fd360e2f353aabbccddeeffaaccddeeffaa"}, }) require.NoError(t, err) diff --git a/core/services/relay/evm/mercury/persistence_manager.go b/core/services/relay/evm/mercury/persistence_manager.go index d7f3d8eaa0d..dfe75e7c3ce 100644 --- a/core/services/relay/evm/mercury/persistence_manager.go +++ b/core/services/relay/evm/mercury/persistence_manager.go @@ -7,9 +7,10 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) @@ -39,7 +40,7 @@ type PersistenceManager struct { func NewPersistenceManager(lggr logger.Logger, serverURL string, orm ORM, jobID int32, maxTransmitQueueSize int, flushDeletesFrequency, pruneFrequency time.Duration) *PersistenceManager { return &PersistenceManager{ - lggr: lggr.Named("MercuryPersistenceManager").With("serverURL", serverURL), + lggr: logger.Sugared(lggr).Named("MercuryPersistenceManager").With("serverURL", serverURL), orm: orm, serverURL: serverURL, stopCh: make(services.StopChan), diff --git a/core/services/relay/evm/mercury/queue.go b/core/services/relay/evm/mercury/queue.go index 8b39be72a68..a450d21af6e 100644 --- a/core/services/relay/evm/mercury/queue.go +++ b/core/services/relay/evm/mercury/queue.go @@ -13,9 +13,9 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) @@ -42,7 +42,7 @@ type transmitQueue struct { services.StateMachine cond sync.Cond - lggr logger.Logger + lggr logger.SugaredLogger asyncDeleter asyncDeleter mu *sync.RWMutex @@ -76,7 +76,7 @@ func NewTransmitQueue(lggr logger.Logger, serverURL, feedID string, maxlen int, return &transmitQueue{ services.StateMachine{}, sync.Cond{L: mu}, - lggr.Named("TransmitQueue"), + logger.Sugared(lggr).Named("TransmitQueue"), asyncDeleter, mu, nil, // pq needs to be initialized by calling tq.Init before use diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go index f1434bf20f1..90b5c7965e5 100644 --- a/core/services/relay/evm/mercury/transmitter.go +++ b/core/services/relay/evm/mercury/transmitter.go @@ -27,10 +27,10 @@ import ( capStreams "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" - "github.com/smartcontractkit/chainlink/v2/core/logger" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" @@ -97,10 +97,12 @@ type ConfigTracker interface { } type TransmitterReportDecoder interface { - BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int, error) - ObservationTimestampFromReport(report ocrtypes.Report) (uint32, error) + BenchmarkPriceFromReport(ctx context.Context, report ocrtypes.Report) (*big.Int, error) + ObservationTimestampFromReport(ctx context.Context, report ocrtypes.Report) (uint32, error) } +type BenchmarkPriceDecoder func(ctx context.Context, feedID mercuryutils.FeedID, report ocrtypes.Report) (*big.Int, error) + var _ Transmitter = (*mercuryTransmitter)(nil) type TransmitterConfig interface { @@ -110,14 +112,15 @@ type TransmitterConfig interface { type mercuryTransmitter struct { services.StateMachine - lggr logger.Logger + lggr logger.SugaredLogger cfg TransmitterConfig orm ORM servers map[string]*server - codec TransmitterReportDecoder - triggerCapability *triggers.MercuryTriggerService + codec TransmitterReportDecoder + benchmarkPriceDecoder BenchmarkPriceDecoder + triggerCapability *triggers.MercuryTriggerService feedID mercuryutils.FeedID jobID int32 @@ -147,7 +150,7 @@ func getPayloadTypes() abi.Arguments { } type server struct { - lggr logger.Logger + lggr logger.SugaredLogger transmitTimeout time.Duration @@ -285,7 +288,7 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed func newServer(lggr logger.Logger, cfg TransmitterConfig, client wsrpc.Client, pm *PersistenceManager, serverURL, feedIDHex string) *server { return &server{ - lggr, + logger.Sugared(lggr), cfg.TransmitTimeout().Duration(), client, pm, @@ -301,21 +304,23 @@ func newServer(lggr logger.Logger, cfg TransmitterConfig, client wsrpc.Client, p } } -func NewTransmitter(lggr logger.Logger, cfg TransmitterConfig, clients map[string]wsrpc.Client, fromAccount ed25519.PublicKey, jobID int32, feedID [32]byte, orm ORM, codec TransmitterReportDecoder, triggerCapability *triggers.MercuryTriggerService) *mercuryTransmitter { +func NewTransmitter(lggr logger.Logger, cfg TransmitterConfig, clients map[string]wsrpc.Client, fromAccount ed25519.PublicKey, jobID int32, feedID [32]byte, orm ORM, codec TransmitterReportDecoder, benchmarkPriceDecoder BenchmarkPriceDecoder, triggerCapability *triggers.MercuryTriggerService) *mercuryTransmitter { + sugared := logger.Sugared(lggr) feedIDHex := fmt.Sprintf("0x%x", feedID[:]) servers := make(map[string]*server, len(clients)) for serverURL, client := range clients { - cLggr := lggr.Named(serverURL).With("serverURL", serverURL) + cLggr := sugared.Named(serverURL).With("serverURL", serverURL) pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) servers[serverURL] = newServer(cLggr, cfg, client, pm, serverURL, feedIDHex) } return &mercuryTransmitter{ services.StateMachine{}, - lggr.Named("MercuryTransmitter").With("feedID", feedIDHex), + sugared.Named("MercuryTransmitter").With("feedID", feedIDHex), cfg, orm, servers, codec, + benchmarkPriceDecoder, triggerCapability, feedID, jobID, @@ -440,7 +445,7 @@ func (mt *mercuryTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.R Payload: payload, } - ts, err := mt.codec.ObservationTimestampFromReport(report) + ts, err := mt.codec.ObservationTimestampFromReport(ctx, report) if err != nil { mt.lggr.Warnw("Failed to get observation timestamp from report", "err", err) } @@ -466,7 +471,7 @@ func (mt *mercuryTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.R } // FromAccount returns the stringified (hex) CSA public key -func (mt *mercuryTransmitter) FromAccount() (ocrtypes.Account, error) { +func (mt *mercuryTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { return ocrtypes.Account(mt.fromAccount), nil } @@ -512,7 +517,7 @@ func (mt *mercuryTransmitter) LatestPrice(ctx context.Context, feedID [32]byte) if !is { return nil, fmt.Errorf("expected report to be []byte, but it was %T", m["report"]) } - return mt.codec.BenchmarkPriceFromReport(report) + return mt.benchmarkPriceDecoder(ctx, feedID, report) } // LatestTimestamp will return -1, nil if the feed is missing diff --git a/core/services/relay/evm/mercury/transmitter_test.go b/core/services/relay/evm/mercury/transmitter_test.go index 4eedc0c24a8..a28d4cd4ded 100644 --- a/core/services/relay/evm/mercury/transmitter_test.go +++ b/core/services/relay/evm/mercury/transmitter_test.go @@ -9,11 +9,10 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -21,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" mercurytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/types" + mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" "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" @@ -43,6 +43,9 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { pgtest.MustExec(t, db, `SET CONSTRAINTS mercury_transmit_requests_job_id_fkey DEFERRED`) pgtest.MustExec(t, db, `SET CONSTRAINTS feed_latest_reports_job_id_fkey DEFERRED`) codec := new(mockCodec) + benchmarkPriceDecoder := func(ctx context.Context, feedID mercuryutils.FeedID, report ocrtypes.Report) (*big.Int, error) { + return codec.BenchmarkPriceFromReport(ctx, report) + } orm := NewORM(db) clients := map[string]wsrpc.Client{} @@ -51,7 +54,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV1Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -65,7 +68,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV2Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -79,7 +82,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV3Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -94,7 +97,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { c := &mocks.MockWSRPCClient{} clients[sURL] = c triggerService := triggers.NewMercuryTriggerService(0, lggr) - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, triggerService) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, triggerService) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -111,7 +114,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { clients[sURL2] = c clients[sURL3] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) mt.servers[sURL2].q.Init([]*Transmission{}) @@ -136,6 +139,9 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { db := pgtest.NewSqlxDB(t) var jobID int32 codec := new(mockCodec) + benchmarkPriceDecoder := func(ctx context.Context, feedID mercuryutils.FeedID, report ocrtypes.Report) (*big.Int, error) { + return codec.BenchmarkPriceFromReport(ctx, report) + } orm := NewORM(db) clients := map[string]wsrpc.Client{} @@ -153,7 +159,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -169,7 +175,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -183,7 +189,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) _, err := mt.LatestTimestamp(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -213,7 +219,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { return out, nil }, } - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -228,11 +234,11 @@ type mockCodec struct { var _ mercurytypes.ReportCodec = &mockCodec{} -func (m *mockCodec) BenchmarkPriceFromReport(_ ocrtypes.Report) (*big.Int, error) { +func (m *mockCodec) BenchmarkPriceFromReport(ctx context.Context, _ ocrtypes.Report) (*big.Int, error) { return m.val, m.err } -func (m *mockCodec) ObservationTimestampFromReport(report ocrtypes.Report) (uint32, error) { +func (m *mockCodec) ObservationTimestampFromReport(ctx context.Context, report ocrtypes.Report) (uint32, error) { return 0, nil } @@ -243,6 +249,9 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { var jobID int32 codec := new(mockCodec) + benchmarkPriceDecoder := func(ctx context.Context, feedID mercuryutils.FeedID, report ocrtypes.Report) (*big.Int, error) { + return codec.BenchmarkPriceFromReport(ctx, report) + } orm := NewORM(db) clients := map[string]wsrpc.Client{} @@ -260,7 +269,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) t.Run("BenchmarkPriceFromReport succeeds", func(t *testing.T) { codec.val = originalPrice @@ -291,7 +300,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) price, err := mt.LatestPrice(testutils.Context(t), sampleFeedID) require.NoError(t, err) @@ -305,7 +314,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) _, err := mt.LatestPrice(testutils.Context(t), sampleFeedID) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -319,6 +328,9 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { db := pgtest.NewSqlxDB(t) var jobID int32 codec := new(mockCodec) + benchmarkPriceDecoder := func(ctx context.Context, feedID mercuryutils.FeedID, report ocrtypes.Report) (*big.Int, error) { + return codec.BenchmarkPriceFromReport(ctx, report) + } orm := NewORM(db) clients := map[string]wsrpc.Client{} @@ -335,7 +347,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) bn, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.NoError(t, err) @@ -351,7 +363,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) bn, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.NoError(t, err) @@ -364,7 +376,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) _, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -382,7 +394,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, nil) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec, benchmarkPriceDecoder, nil) _, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "latestReport failed; mismatched feed IDs, expected: 0x1c916b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472, got: 0x") diff --git a/core/services/relay/evm/mercury/types/types.go b/core/services/relay/evm/mercury/types/types.go index 972367940b5..98910887111 100644 --- a/core/services/relay/evm/mercury/types/types.go +++ b/core/services/relay/evm/mercury/types/types.go @@ -14,7 +14,7 @@ type DataSourceORM interface { } type ReportCodec interface { - BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int, error) + BenchmarkPriceFromReport(ctx context.Context, report ocrtypes.Report) (*big.Int, error) } var ( diff --git a/core/services/relay/evm/mercury/utils/feeds.go b/core/services/relay/evm/mercury/utils/feeds.go index 36d6bc60f58..eb4f6850221 100644 --- a/core/services/relay/evm/mercury/utils/feeds.go +++ b/core/services/relay/evm/mercury/utils/feeds.go @@ -104,7 +104,10 @@ func (f *FeedID) UnmarshalText(input []byte) error { func (f FeedID) Version() FeedVersion { if _, exists := legacyV1FeedIDM[f]; exists { return REPORT_V1 + } else if f[0] == 0x01 { // Keystone Feed IDs + return FeedVersion(binary.BigEndian.Uint16(f[5:7])) } + return FeedVersion(binary.BigEndian.Uint16(f[:2])) } diff --git a/core/services/relay/evm/mercury/utils/feeds_test.go b/core/services/relay/evm/mercury/utils/feeds_test.go index 37b9b47de76..d6db7a4a8c4 100644 --- a/core/services/relay/evm/mercury/utils/feeds_test.go +++ b/core/services/relay/evm/mercury/utils/feeds_test.go @@ -7,27 +7,48 @@ import ( ) var ( - v1FeedId = (FeedID)([32]uint8{00, 01, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114}) - v2FeedId = (FeedID)([32]uint8{00, 02, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114}) - v3FeedId = (FeedID)([32]uint8{00, 03, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114}) + v1FeedID = (FeedID)([32]uint8{00, 01, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114}) + v2FeedID = (FeedID)([32]uint8{00, 02, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114}) + v3FeedID = (FeedID)([32]uint8{00, 03, 107, 74, 167, 229, 124, 167, 182, 138, 225, 191, 69, 101, 63, 86, 182, 86, 253, 58, 163, 53, 239, 127, 174, 105, 107, 102, 63, 27, 132, 114}) + keystonev2Feed = (FeedID)([32]uint8{01, 12, 34, 56, 78, 00, 02, 04, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}) + keystonev3Feed = (FeedID)([32]uint8{01, 12, 34, 56, 78, 00, 03, 04, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}) + keystonev4Feed = (FeedID)([32]uint8{01, 12, 34, 56, 78, 00, 04, 04, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}) ) func Test_FeedID_Version(t *testing.T) { t.Run("versioned feed ID", func(t *testing.T) { - assert.Equal(t, REPORT_V1, v1FeedId.Version()) - assert.True(t, v1FeedId.IsV1()) - assert.False(t, v1FeedId.IsV2()) - assert.False(t, v1FeedId.IsV3()) - - assert.Equal(t, REPORT_V2, v2FeedId.Version()) - assert.False(t, v2FeedId.IsV1()) - assert.True(t, v2FeedId.IsV2()) - assert.False(t, v2FeedId.IsV3()) - - assert.Equal(t, REPORT_V3, v3FeedId.Version()) - assert.False(t, v3FeedId.IsV1()) - assert.False(t, v3FeedId.IsV2()) - assert.True(t, v3FeedId.IsV3()) + assert.Equal(t, REPORT_V1, v1FeedID.Version()) + assert.True(t, v1FeedID.IsV1()) + assert.False(t, v1FeedID.IsV2()) + assert.False(t, v1FeedID.IsV3()) + + assert.Equal(t, REPORT_V2, v2FeedID.Version()) + assert.False(t, v2FeedID.IsV1()) + assert.True(t, v2FeedID.IsV2()) + assert.False(t, v2FeedID.IsV3()) + + assert.Equal(t, REPORT_V3, v3FeedID.Version()) + assert.False(t, v3FeedID.IsV1()) + assert.False(t, v3FeedID.IsV2()) + assert.True(t, v3FeedID.IsV3()) + + assert.Equal(t, REPORT_V2, keystonev2Feed.Version()) + assert.False(t, keystonev2Feed.IsV1()) + assert.True(t, keystonev2Feed.IsV2()) + assert.False(t, keystonev2Feed.IsV3()) + assert.False(t, keystonev2Feed.IsV4()) + + assert.Equal(t, REPORT_V3, keystonev3Feed.Version()) + assert.False(t, keystonev3Feed.IsV1()) + assert.False(t, keystonev3Feed.IsV2()) + assert.True(t, keystonev3Feed.IsV3()) + assert.False(t, keystonev3Feed.IsV4()) + + assert.Equal(t, REPORT_V4, keystonev4Feed.Version()) + assert.False(t, keystonev4Feed.IsV1()) + assert.False(t, keystonev4Feed.IsV2()) + assert.False(t, keystonev4Feed.IsV3()) + assert.True(t, keystonev4Feed.IsV4()) }) t.Run("legacy special cases", func(t *testing.T) { for _, feedID := range legacyV1FeedIDs { diff --git a/core/services/relay/evm/mercury/v1/data_source.go b/core/services/relay/evm/mercury/v1/data_source.go index 5a9a11decaa..0b9b6727fcf 100644 --- a/core/services/relay/evm/mercury/v1/data_source.go +++ b/core/services/relay/evm/mercury/v1/data_source.go @@ -111,7 +111,7 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam return } if latest != nil { - obs.MaxFinalizedBlockNumber.Val, obs.MaxFinalizedBlockNumber.Err = ds.codec.CurrentBlockNumFromReport(latest) + obs.MaxFinalizedBlockNumber.Val, obs.MaxFinalizedBlockNumber.Err = ds.codec.CurrentBlockNumFromReport(ctx, latest) return } val, fetchErr := ds.fetcher.FetchInitialMaxFinalizedBlockNumber(ctx) diff --git a/core/services/relay/evm/mercury/v1/data_source_test.go b/core/services/relay/evm/mercury/v1/data_source_test.go index 197d802a3b3..7f5117a0aa8 100644 --- a/core/services/relay/evm/mercury/v1/data_source_test.go +++ b/core/services/relay/evm/mercury/v1/data_source_test.go @@ -332,16 +332,15 @@ func TestMercury_Observe(t *testing.T) { t.Run("when chain is too short", func(t *testing.T) { h4 := &evmtypes.Head{ Number: 4, - Parent: nil, } h5 := &evmtypes.Head{ Number: 5, - Parent: h4, } + h5.Parent.Store(h4) h6 := &evmtypes.Head{ Number: 6, - Parent: h5, } + h6.Parent.Store(h5) ht2 := htmocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) ht2.On("LatestChain").Return(h6) @@ -362,7 +361,7 @@ func TestMercury_Observe(t *testing.T) { for i := range heads { heads[i] = &evmtypes.Head{Number: int64(i)} if i > 0 { - heads[i].Parent = heads[i-1] + heads[i].Parent.Store(heads[i-1]) } } diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go index f4c6af32b8e..52cdeff96cb 100644 --- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go +++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec.go @@ -1,6 +1,7 @@ package reportcodec import ( + "context" "errors" "fmt" "math" @@ -11,8 +12,9 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" v1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v1/types" ) @@ -35,7 +37,7 @@ func NewReportCodec(feedID [32]byte, lggr logger.Logger) *ReportCodec { return &ReportCodec{lggr, feedID} } -func (r *ReportCodec) BuildReport(rf v1.ReportFields) (ocrtypes.Report, error) { +func (r *ReportCodec) BuildReport(ctx context.Context, rf v1.ReportFields) (ocrtypes.Report, error) { var merr error if rf.BenchmarkPrice == nil { merr = errors.Join(merr, errors.New("benchmarkPrice may not be nil")) @@ -61,11 +63,11 @@ func (r *ReportCodec) BuildReport(rf v1.ReportFields) (ocrtypes.Report, error) { // Maximum length in bytes of Report returned by BuildReport. Used for // defending against spam attacks. -func (r *ReportCodec) MaxReportLength(n int) (int, error) { +func (r *ReportCodec) MaxReportLength(ctx context.Context, n int) (int, error) { return maxReportLength, nil } -func (r *ReportCodec) CurrentBlockNumFromReport(report ocrtypes.Report) (int64, error) { +func (r *ReportCodec) CurrentBlockNumFromReport(ctx context.Context, report ocrtypes.Report) (int64, error) { decoded, err := r.Decode(report) if err != nil { return 0, err @@ -76,22 +78,11 @@ func (r *ReportCodec) CurrentBlockNumFromReport(report ocrtypes.Report) (int64, return int64(decoded.CurrentBlockNum), nil } -func (r *ReportCodec) ValidFromBlockNumFromReport(report ocrtypes.Report) (int64, error) { - decoded, err := r.Decode(report) - if err != nil { - return 0, err - } - if decoded.ValidFromBlockNum > math.MaxInt64 { - return 0, fmt.Errorf("ValidFromBlockNum=%d overflows max int64", decoded.ValidFromBlockNum) - } - return int64(decoded.ValidFromBlockNum), nil -} - func (r *ReportCodec) Decode(report ocrtypes.Report) (*reporttypes.Report, error) { return reporttypes.Decode(report) } -func (r *ReportCodec) BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int, error) { +func (r *ReportCodec) BenchmarkPriceFromReport(ctx context.Context, report ocrtypes.Report) (*big.Int, error) { decoded, err := r.Decode(report) if err != nil { return nil, err @@ -99,7 +90,7 @@ func (r *ReportCodec) BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int return decoded.BenchmarkPrice, nil } -func (r *ReportCodec) ObservationTimestampFromReport(report ocrtypes.Report) (uint32, error) { +func (r *ReportCodec) ObservationTimestampFromReport(ctx context.Context, report ocrtypes.Report) (uint32, error) { decoded, err := r.Decode(report) if err != nil { return 0, err diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go index 3e898d6c1da..b24e69ce387 100644 --- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go @@ -1,11 +1,14 @@ package reportcodec import ( + "fmt" + "math" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -13,6 +16,7 @@ import ( v1 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v1" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) var hash = hexutil.MustDecode("0x552c2cea3ab43bae137d89ee6142a01db3ae2b5678bc3c9bd5f509f537bea57b") @@ -34,7 +38,8 @@ func Test_ReportCodec(t *testing.T) { r := ReportCodec{} t.Run("BuildReport errors on zero fields", func(t *testing.T) { - _, err := r.BuildReport(v1.ReportFields{}) + ctx := testutils.Context(t) + _, err := r.BuildReport(ctx, v1.ReportFields{}) require.Error(t, err) assert.Contains(t, err.Error(), "benchmarkPrice may not be nil") assert.Contains(t, err.Error(), "bid may not be nil") @@ -43,10 +48,11 @@ func Test_ReportCodec(t *testing.T) { }) t.Run("BuildReport constructs a report from observations", func(t *testing.T) { + ctx := testutils.Context(t) rf := newValidReportFields() // only need to test happy path since validations are done in relaymercury - report, err := r.BuildReport(rf) + report, err := r.BuildReport(ctx, rf) require.NoError(t, err) reportElems := make(map[string]interface{}) @@ -64,7 +70,7 @@ func Test_ReportCodec(t *testing.T) { assert.Equal(t, types.Report{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0x55, 0x2c, 0x2c, 0xea, 0x3a, 0xb4, 0x3b, 0xae, 0x13, 0x7d, 0x89, 0xee, 0x61, 0x42, 0xa0, 0x1d, 0xb3, 0xae, 0x2b, 0x56, 0x78, 0xbc, 0x3c, 0x9b, 0xd5, 0xf5, 0x9, 0xf5, 0x37, 0xbe, 0xa5, 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b}, report) - max, err := r.MaxReportLength(4) + max, err := r.MaxReportLength(ctx, 4) require.NoError(t, err) assert.LessOrEqual(t, len(report), max) @@ -125,7 +131,8 @@ func Test_ReportCodec_CurrentBlockNumFromReport(t *testing.T) { t.Run("CurrentBlockNumFromReport extracts the current block number from a valid report", func(t *testing.T) { report := buildSampleReport(validBn, 143, feedID) - bn, err := r.CurrentBlockNumFromReport(report) + ctx := testutils.Context(t) + bn, err := r.CurrentBlockNumFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, validBn, bn) @@ -133,12 +140,26 @@ func Test_ReportCodec_CurrentBlockNumFromReport(t *testing.T) { t.Run("CurrentBlockNumFromReport returns error if block num is too large", func(t *testing.T) { report := buildSampleReport(invalidBn, 143, feedID) - _, err := r.CurrentBlockNumFromReport(report) + ctx := testutils.Context(t) + _, err := r.CurrentBlockNumFromReport(ctx, report) require.Error(t, err) assert.Contains(t, err.Error(), "CurrentBlockNum=18446744073709551615 overflows max int64") }) } + +func (r *ReportCodec) ValidFromBlockNumFromReport(report ocrtypes.Report) (int64, error) { + decoded, err := r.Decode(report) + if err != nil { + return 0, err + } + n := decoded.ValidFromBlockNum + if n > math.MaxInt64 { + return 0, fmt.Errorf("ValidFromBlockNum=%d overflows max int64", n) + } + return int64(n), nil //nolint:gosec // G115 +} + func Test_ReportCodec_ValidFromBlockNumFromReport(t *testing.T) { r := ReportCodec{} feedID := utils.NewHash() @@ -166,15 +187,17 @@ func Test_ReportCodec_BenchmarkPriceFromReport(t *testing.T) { feedID := utils.NewHash() t.Run("BenchmarkPriceFromReport extracts the benchmark price from valid report", func(t *testing.T) { + ctx := testutils.Context(t) report := buildSampleReport(42, 999, feedID) - bp, err := r.BenchmarkPriceFromReport(report) + bp, err := r.BenchmarkPriceFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, big.NewInt(242), bp) }) t.Run("BenchmarkPriceFromReport errors on invalid report", func(t *testing.T) { - _, err := r.BenchmarkPriceFromReport([]byte{1, 2, 3}) + ctx := testutils.Context(t) + _, err := r.BenchmarkPriceFromReport(ctx, []byte{1, 2, 3}) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") }) diff --git a/core/services/relay/evm/mercury/v2/data_source.go b/core/services/relay/evm/mercury/v2/data_source.go index 28487ec714e..30649916fc8 100644 --- a/core/services/relay/evm/mercury/v2/data_source.go +++ b/core/services/relay/evm/mercury/v2/data_source.go @@ -73,7 +73,7 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam return } if latest != nil { - maxFinalizedBlockNumber, decodeErr := ds.codec.ObservationTimestampFromReport(latest) + maxFinalizedBlockNumber, decodeErr := ds.codec.ObservationTimestampFromReport(ctx, latest) obs.MaxFinalizedTimestamp.Val, obs.MaxFinalizedTimestamp.Err = int64(maxFinalizedBlockNumber), decodeErr return } @@ -108,7 +108,9 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam }() var isLink, isNative bool - if ds.feedID == ds.linkFeedID { + if len(ds.jb.OCR2OracleSpec.PluginConfig) == 0 { + obs.LinkPrice.Val = v2.MissingPrice + } else if ds.feedID == ds.linkFeedID { isLink = true } else { wg.Add(1) @@ -126,7 +128,9 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam }() } - if ds.feedID == ds.nativeFeedID { + if len(ds.jb.OCR2OracleSpec.PluginConfig) == 0 { + obs.NativePrice.Val = v2.MissingPrice + } else if ds.feedID == ds.nativeFeedID { isNative = true } else { wg.Add(1) diff --git a/core/services/relay/evm/mercury/v2/data_source_test.go b/core/services/relay/evm/mercury/v2/data_source_test.go index 19af909c8e9..25716521d86 100644 --- a/core/services/relay/evm/mercury/v2/data_source_test.go +++ b/core/services/relay/evm/mercury/v2/data_source_test.go @@ -15,6 +15,7 @@ import ( "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" mercurymocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" @@ -72,7 +73,16 @@ func (ms *mockSaver) Save(r *pipeline.Run) { func Test_Datasource(t *testing.T) { orm := &mockORM{} - ds := &datasource{orm: orm, lggr: logger.TestLogger(t)} + jb := job.Job{ + Type: job.Type(pipeline.OffchainReporting2JobType), + OCR2OracleSpec: &job.OCR2OracleSpec{ + CaptureEATelemetry: true, + PluginConfig: map[string]interface{}{ + "serverURL": "a", + }, + }, + } + ds := &datasource{orm: orm, lggr: logger.TestLogger(t), jb: jb} ctx := testutils.Context(t) repts := ocrtypes.ReportTimestamp{} @@ -274,6 +284,25 @@ func Test_Datasource(t *testing.T) { assert.EqualError(t, obs.NativePrice.Err, "some error fetching native price") }) + t.Run("when PluginConfig is empty", func(t *testing.T) { + t.Cleanup(func() { + ds.jb = jb + }) + + fetcher.linkPriceErr = errors.New("some error fetching link price") + fetcher.nativePriceErr = errors.New("some error fetching native price") + + ds.jb.OCR2OracleSpec.PluginConfig = job.JSONConfig{} + + obs, err := ds.Observe(ctx, repts, false) + assert.NoError(t, err) + assert.Nil(t, obs.LinkPrice.Err) + assert.Equal(t, obs.LinkPrice.Val, v2.MissingPrice) + assert.Nil(t, obs.NativePrice.Err) + assert.Equal(t, obs.NativePrice.Val, v2.MissingPrice) + assert.Equal(t, big.NewInt(122), obs.BenchmarkPrice.Val) + }) + t.Run("when succeeds to fetch linkPrice or nativePrice but got nil (new feed)", func(t *testing.T) { obs, err := ds.Observe(ctx, repts, false) assert.NoError(t, err) diff --git a/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go index 33c5fa9a326..d35621da01b 100644 --- a/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go +++ b/core/services/relay/evm/mercury/v2/reportcodec/report_codec.go @@ -1,6 +1,7 @@ package reportcodec import ( + "context" "errors" "fmt" "math/big" @@ -9,9 +10,9 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" v2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v2/types" ) @@ -31,7 +32,7 @@ func NewReportCodec(feedID [32]byte, lggr logger.Logger) *ReportCodec { return &ReportCodec{lggr, feedID} } -func (r *ReportCodec) BuildReport(rf v2.ReportFields) (ocrtypes.Report, error) { +func (r *ReportCodec) BuildReport(ctx context.Context, rf v2.ReportFields) (ocrtypes.Report, error) { var merr error if rf.BenchmarkPrice == nil { merr = errors.Join(merr, errors.New("benchmarkPrice may not be nil")) @@ -53,24 +54,24 @@ func (r *ReportCodec) BuildReport(rf v2.ReportFields) (ocrtypes.Report, error) { return ocrtypes.Report(reportBytes), pkgerrors.Wrap(err, "failed to pack report blob") } -func (r *ReportCodec) MaxReportLength(n int) (int, error) { +func (r *ReportCodec) MaxReportLength(ctx context.Context, n int) (int, error) { return maxReportLength, nil } -func (r *ReportCodec) ObservationTimestampFromReport(report ocrtypes.Report) (uint32, error) { - decoded, err := r.Decode(report) +func (r *ReportCodec) ObservationTimestampFromReport(ctx context.Context, report ocrtypes.Report) (uint32, error) { + decoded, err := r.Decode(ctx, report) if err != nil { return 0, err } return decoded.ObservationsTimestamp, nil } -func (r *ReportCodec) Decode(report ocrtypes.Report) (*reporttypes.Report, error) { +func (r *ReportCodec) Decode(ctx context.Context, report ocrtypes.Report) (*reporttypes.Report, error) { return reporttypes.Decode(report) } -func (r *ReportCodec) BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int, error) { - decoded, err := r.Decode(report) +func (r *ReportCodec) BenchmarkPriceFromReport(ctx context.Context, report ocrtypes.Report) (*big.Int, error) { + decoded, err := r.Decode(ctx, report) if err != nil { return nil, err } diff --git a/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go index 36b3a443880..809869282b7 100644 --- a/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v2/reportcodec/report_codec_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" v2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func newValidReportFields() v2.ReportFields { @@ -27,7 +28,8 @@ func Test_ReportCodec_BuildReport(t *testing.T) { r := ReportCodec{} t.Run("BuildReport errors on zero values", func(t *testing.T) { - _, err := r.BuildReport(v2.ReportFields{}) + ctx := testutils.Context(t) + _, err := r.BuildReport(ctx, v2.ReportFields{}) require.Error(t, err) assert.Contains(t, err.Error(), "benchmarkPrice may not be nil") assert.Contains(t, err.Error(), "linkFee may not be nil") @@ -35,10 +37,11 @@ func Test_ReportCodec_BuildReport(t *testing.T) { }) t.Run("BuildReport constructs a report from observations", func(t *testing.T) { + ctx := testutils.Context(t) rf := newValidReportFields() // only need to test happy path since validations are done in relaymercury - report, err := r.BuildReport(rf) + report, err := r.BuildReport(ctx, rf) require.NoError(t, err) reportElems := make(map[string]interface{}) @@ -53,12 +56,13 @@ func Test_ReportCodec_BuildReport(t *testing.T) { assert.Equal(t, reportElems["nativeFee"].(*big.Int).Int64(), int64(457)) assert.Equal(t, types.Report{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3}, report) - max, err := r.MaxReportLength(4) + max, err := r.MaxReportLength(ctx, 4) require.NoError(t, err) assert.LessOrEqual(t, len(report), max) t.Run("Decode decodes the report", func(t *testing.T) { - decoded, err := r.Decode(report) + ctx := testutils.Context(t) + decoded, err := r.Decode(ctx, report) require.NoError(t, err) require.NotNil(t, decoded) @@ -76,7 +80,8 @@ func Test_ReportCodec_BuildReport(t *testing.T) { rf := newValidReportFields() rf.LinkFee = big.NewInt(-1) rf.NativeFee = big.NewInt(-1) - _, err := r.BuildReport(rf) + ctx := testutils.Context(t) + _, err := r.BuildReport(ctx, rf) require.Error(t, err) assert.Contains(t, err.Error(), "linkFee may not be negative (got: -1)") @@ -84,14 +89,15 @@ func Test_ReportCodec_BuildReport(t *testing.T) { }) t.Run("Decode errors on invalid report", func(t *testing.T) { - _, err := r.Decode([]byte{1, 2, 3}) + ctx := testutils.Context(t) + _, err := r.Decode(ctx, []byte{1, 2, 3}) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") longBad := make([]byte, 64) for i := 0; i < len(longBad); i++ { longBad[i] = byte(i) } - _, err = r.Decode(longBad) + _, err = r.Decode(ctx, longBad) assert.EqualError(t, err, "failed to decode report: abi: improperly encoded uint32 value") }) } @@ -118,7 +124,8 @@ func Test_ReportCodec_ObservationTimestampFromReport(t *testing.T) { t.Run("ObservationTimestampFromReport extracts observation timestamp from a valid report", func(t *testing.T) { report := buildSampleReport(123) - ts, err := r.ObservationTimestampFromReport(report) + ctx := testutils.Context(t) + ts, err := r.ObservationTimestampFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, ts, uint32(123)) @@ -126,7 +133,8 @@ func Test_ReportCodec_ObservationTimestampFromReport(t *testing.T) { t.Run("ObservationTimestampFromReport returns error when report is invalid", func(t *testing.T) { report := []byte{1, 2, 3} - _, err := r.ObservationTimestampFromReport(report) + ctx := testutils.Context(t) + _, err := r.ObservationTimestampFromReport(ctx, report) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") @@ -137,15 +145,17 @@ func Test_ReportCodec_BenchmarkPriceFromReport(t *testing.T) { r := ReportCodec{} t.Run("BenchmarkPriceFromReport extracts the benchmark price from valid report", func(t *testing.T) { + ctx := testutils.Context(t) report := buildSampleReport(123) - bp, err := r.BenchmarkPriceFromReport(report) + bp, err := r.BenchmarkPriceFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, big.NewInt(242), bp) }) t.Run("BenchmarkPriceFromReport errors on invalid report", func(t *testing.T) { - _, err := r.BenchmarkPriceFromReport([]byte{1, 2, 3}) + ctx := testutils.Context(t) + _, err := r.BenchmarkPriceFromReport(ctx, []byte{1, 2, 3}) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") }) diff --git a/core/services/relay/evm/mercury/v3/data_source.go b/core/services/relay/evm/mercury/v3/data_source.go index 644f4e775ec..776e2fb2f47 100644 --- a/core/services/relay/evm/mercury/v3/data_source.go +++ b/core/services/relay/evm/mercury/v3/data_source.go @@ -75,7 +75,7 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam return } if latest != nil { - maxFinalizedBlockNumber, decodeErr := ds.codec.ObservationTimestampFromReport(latest) + maxFinalizedBlockNumber, decodeErr := ds.codec.ObservationTimestampFromReport(ctx, latest) obs.MaxFinalizedTimestamp.Val, obs.MaxFinalizedTimestamp.Err = int64(maxFinalizedBlockNumber), decodeErr return } @@ -112,7 +112,9 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam }() var isLink, isNative bool - if ds.feedID == ds.linkFeedID { + if len(ds.jb.OCR2OracleSpec.PluginConfig) == 0 { + obs.LinkPrice.Val = v3.MissingPrice + } else if ds.feedID == ds.linkFeedID { isLink = true } else { wg.Add(1) @@ -130,7 +132,9 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam }() } - if ds.feedID == ds.nativeFeedID { + if len(ds.jb.OCR2OracleSpec.PluginConfig) == 0 { + obs.NativePrice.Val = v3.MissingPrice + } else if ds.feedID == ds.nativeFeedID { isNative = true } else { wg.Add(1) diff --git a/core/services/relay/evm/mercury/v3/data_source_test.go b/core/services/relay/evm/mercury/v3/data_source_test.go index a0f624c78d8..518fabb12c9 100644 --- a/core/services/relay/evm/mercury/v3/data_source_test.go +++ b/core/services/relay/evm/mercury/v3/data_source_test.go @@ -5,18 +5,19 @@ import ( "math/big" "testing" + relaymercuryv3 "github.com/smartcontractkit/chainlink-data-streams/mercury/v3" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/eautils" + "github.com/pkg/errors" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" mercurytypes "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" - relaymercuryv3 "github.com/smartcontractkit/chainlink-data-streams/mercury/v3" "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/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/eautils" mercurymocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" @@ -77,6 +78,9 @@ func Test_Datasource(t *testing.T) { Type: job.Type(pipeline.OffchainReporting2JobType), OCR2OracleSpec: &job.OCR2OracleSpec{ CaptureEATelemetry: true, + PluginConfig: map[string]interface{}{ + "serverURL": "a", + }, }, } ds := &datasource{orm: orm, lggr: logger.TestLogger(t), jb: jb} @@ -360,6 +364,25 @@ func Test_Datasource(t *testing.T) { assert.EqualError(t, obs.NativePrice.Err, "some error fetching native price") }) + t.Run("when PluginConfig is empty", func(t *testing.T) { + t.Cleanup(func() { + ds.jb = jb + }) + + fetcher.linkPriceErr = errors.New("some error fetching link price") + fetcher.nativePriceErr = errors.New("some error fetching native price") + + ds.jb.OCR2OracleSpec.PluginConfig = job.JSONConfig{} + + obs, err := ds.Observe(ctx, repts, false) + assert.NoError(t, err) + assert.Nil(t, obs.LinkPrice.Err) + assert.Equal(t, obs.LinkPrice.Val, relaymercuryv3.MissingPrice) + assert.Nil(t, obs.NativePrice.Err) + assert.Equal(t, obs.NativePrice.Val, relaymercuryv3.MissingPrice) + assert.Equal(t, big.NewInt(122), obs.BenchmarkPrice.Val) + }) + t.Run("when succeeds to fetch linkPrice or nativePrice but got nil (new feed)", func(t *testing.T) { obs, err := ds.Observe(ctx, repts, false) assert.NoError(t, err) diff --git a/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go index 601431838d2..d9420883b12 100644 --- a/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go +++ b/core/services/relay/evm/mercury/v3/reportcodec/report_codec.go @@ -1,6 +1,7 @@ package reportcodec import ( + "context" "errors" "fmt" "math/big" @@ -9,9 +10,9 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" ) @@ -31,7 +32,7 @@ func NewReportCodec(feedID [32]byte, lggr logger.Logger) *ReportCodec { return &ReportCodec{lggr, feedID} } -func (r *ReportCodec) BuildReport(rf v3.ReportFields) (ocrtypes.Report, error) { +func (r *ReportCodec) BuildReport(ctx context.Context, rf v3.ReportFields) (ocrtypes.Report, error) { var merr error if rf.BenchmarkPrice == nil { merr = errors.Join(merr, errors.New("benchmarkPrice may not be nil")) @@ -59,11 +60,11 @@ func (r *ReportCodec) BuildReport(rf v3.ReportFields) (ocrtypes.Report, error) { return ocrtypes.Report(reportBytes), pkgerrors.Wrap(err, "failed to pack report blob") } -func (r *ReportCodec) MaxReportLength(n int) (int, error) { +func (r *ReportCodec) MaxReportLength(ctx context.Context, n int) (int, error) { return maxReportLength, nil } -func (r *ReportCodec) ObservationTimestampFromReport(report ocrtypes.Report) (uint32, error) { +func (r *ReportCodec) ObservationTimestampFromReport(ctx context.Context, report ocrtypes.Report) (uint32, error) { decoded, err := r.Decode(report) if err != nil { return 0, err @@ -75,7 +76,7 @@ func (r *ReportCodec) Decode(report ocrtypes.Report) (*reporttypes.Report, error return reporttypes.Decode(report) } -func (r *ReportCodec) BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int, error) { +func (r *ReportCodec) BenchmarkPriceFromReport(ctx context.Context, report ocrtypes.Report) (*big.Int, error) { decoded, err := r.Decode(report) if err != nil { return nil, err diff --git a/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go index 752e6ce34b5..2cfb162841b 100644 --- a/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v3/reportcodec/report_codec_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func newValidReportFields() v3.ReportFields { @@ -29,7 +30,8 @@ func Test_ReportCodec_BuildReport(t *testing.T) { r := ReportCodec{} t.Run("BuildReport errors on zero values", func(t *testing.T) { - _, err := r.BuildReport(v3.ReportFields{}) + ctx := testutils.Context(t) + _, err := r.BuildReport(ctx, v3.ReportFields{}) require.Error(t, err) assert.Contains(t, err.Error(), "benchmarkPrice may not be nil") assert.Contains(t, err.Error(), "linkFee may not be nil") @@ -40,7 +42,8 @@ func Test_ReportCodec_BuildReport(t *testing.T) { rf := newValidReportFields() // only need to test happy path since validations are done in relaymercury - report, err := r.BuildReport(rf) + ctx := testutils.Context(t) + report, err := r.BuildReport(ctx, rf) require.NoError(t, err) reportElems := make(map[string]interface{}) @@ -57,7 +60,7 @@ func Test_ReportCodec_BuildReport(t *testing.T) { assert.Equal(t, reportElems["nativeFee"].(*big.Int).Int64(), int64(457)) assert.Equal(t, types.Report{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf5}, report) - max, err := r.MaxReportLength(4) + max, err := r.MaxReportLength(ctx, 4) require.NoError(t, err) assert.LessOrEqual(t, len(report), max) @@ -82,7 +85,8 @@ func Test_ReportCodec_BuildReport(t *testing.T) { rf := newValidReportFields() rf.LinkFee = big.NewInt(-1) rf.NativeFee = big.NewInt(-1) - _, err := r.BuildReport(rf) + ctx := testutils.Context(t) + _, err := r.BuildReport(ctx, rf) require.Error(t, err) assert.Contains(t, err.Error(), "linkFee may not be negative (got: -1)") @@ -126,7 +130,8 @@ func Test_ReportCodec_ObservationTimestampFromReport(t *testing.T) { t.Run("ObservationTimestampFromReport extracts observation timestamp from a valid report", func(t *testing.T) { report := buildSampleReport(123) - ts, err := r.ObservationTimestampFromReport(report) + ctx := testutils.Context(t) + ts, err := r.ObservationTimestampFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, ts, uint32(123)) @@ -134,7 +139,8 @@ func Test_ReportCodec_ObservationTimestampFromReport(t *testing.T) { t.Run("ObservationTimestampFromReport returns error when report is invalid", func(t *testing.T) { report := []byte{1, 2, 3} - _, err := r.ObservationTimestampFromReport(report) + ctx := testutils.Context(t) + _, err := r.ObservationTimestampFromReport(ctx, report) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") @@ -145,15 +151,17 @@ func Test_ReportCodec_BenchmarkPriceFromReport(t *testing.T) { r := ReportCodec{} t.Run("BenchmarkPriceFromReport extracts the benchmark price from valid report", func(t *testing.T) { + ctx := testutils.Context(t) report := buildSampleReport(123) - bp, err := r.BenchmarkPriceFromReport(report) + bp, err := r.BenchmarkPriceFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, big.NewInt(242), bp) }) t.Run("BenchmarkPriceFromReport errors on invalid report", func(t *testing.T) { - _, err := r.BenchmarkPriceFromReport([]byte{1, 2, 3}) + ctx := testutils.Context(t) + _, err := r.BenchmarkPriceFromReport(ctx, []byte{1, 2, 3}) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") }) diff --git a/core/services/relay/evm/mercury/v4/data_source.go b/core/services/relay/evm/mercury/v4/data_source.go index f9c2c2d5de0..46e34f0b9c5 100644 --- a/core/services/relay/evm/mercury/v4/data_source.go +++ b/core/services/relay/evm/mercury/v4/data_source.go @@ -72,7 +72,7 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam return } if latest != nil { - maxFinalizedBlockNumber, decodeErr := ds.codec.ObservationTimestampFromReport(latest) + maxFinalizedBlockNumber, decodeErr := ds.codec.ObservationTimestampFromReport(ctx, latest) obs.MaxFinalizedTimestamp.Val, obs.MaxFinalizedTimestamp.Err = int64(maxFinalizedBlockNumber), decodeErr return } @@ -104,13 +104,13 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam return } obs.BenchmarkPrice = parsed.benchmarkPrice - obs.Bid = parsed.bid - obs.Ask = parsed.ask obs.MarketStatus = parsed.marketStatus }() var isLink, isNative bool - if ds.feedID == ds.linkFeedID { + if len(ds.jb.OCR2OracleSpec.PluginConfig) == 0 { + obs.LinkPrice.Val = v4.MissingPrice + } else if ds.feedID == ds.linkFeedID { isLink = true } else { wg.Add(1) @@ -128,7 +128,9 @@ func (ds *datasource) Observe(ctx context.Context, repts ocrtypes.ReportTimestam }() } - if ds.feedID == ds.nativeFeedID { + if len(ds.jb.OCR2OracleSpec.PluginConfig) == 0 { + obs.NativePrice.Val = v4.MissingPrice + } else if ds.feedID == ds.nativeFeedID { isNative = true } else { wg.Add(1) @@ -188,8 +190,6 @@ func toBigInt(val interface{}) (*big.Int, error) { type parseOutput struct { benchmarkPrice mercury.ObsResult[*big.Int] - bid mercury.ObsResult[*big.Int] - ask mercury.ObsResult[*big.Int] marketStatus mercury.ObsResult[uint32] } @@ -204,15 +204,13 @@ func (ds *datasource) parse(trrs pipeline.TaskRunResults) (o parseOutput, merr e // pipeline.TaskRunResults comes ordered asc by index, this is guaranteed // by the pipeline executor - if len(finaltrrs) != 4 { - return o, fmt.Errorf("invalid number of results, expected: 4, got: %d", len(finaltrrs)) + if len(finaltrrs) != 2 { + return o, fmt.Errorf("invalid number of results, expected: 2, got: %d", len(finaltrrs)) } merr = errors.Join( setBenchmarkPrice(&o, finaltrrs[0].Result), - setBid(&o, finaltrrs[1].Result), - setAsk(&o, finaltrrs[2].Result), - setMarketStatus(&o, finaltrrs[3].Result), + setMarketStatus(&o, finaltrrs[1].Result), ) return o, merr @@ -231,32 +229,6 @@ func setBenchmarkPrice(o *parseOutput, res pipeline.Result) error { return nil } -func setBid(o *parseOutput, res pipeline.Result) error { - if res.Error != nil { - o.bid.Err = res.Error - return res.Error - } - val, err := toBigInt(res.Value) - if err != nil { - return fmt.Errorf("failed to parse Bid: %w", err) - } - o.bid.Val = val - return nil -} - -func setAsk(o *parseOutput, res pipeline.Result) error { - if res.Error != nil { - o.ask.Err = res.Error - return res.Error - } - val, err := toBigInt(res.Value) - if err != nil { - return fmt.Errorf("failed to parse Ask: %w", err) - } - o.ask.Val = val - return nil -} - func setMarketStatus(o *parseOutput, res pipeline.Result) error { if res.Error != nil { o.marketStatus.Err = res.Error diff --git a/core/services/relay/evm/mercury/v4/data_source_test.go b/core/services/relay/evm/mercury/v4/data_source_test.go index bce9c3c6088..48aec5989a6 100644 --- a/core/services/relay/evm/mercury/v4/data_source_test.go +++ b/core/services/relay/evm/mercury/v4/data_source_test.go @@ -13,6 +13,7 @@ import ( relaymercuryv4 "github.com/smartcontractkit/chainlink-data-streams/mercury/v4" "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" mercurymocks "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" @@ -70,7 +71,16 @@ func (ms *mockSaver) Save(r *pipeline.Run) { func Test_Datasource(t *testing.T) { orm := &mockORM{} - ds := &datasource{orm: orm, lggr: logger.TestLogger(t)} + jb := job.Job{ + Type: job.Type(pipeline.OffchainReporting2JobType), + OCR2OracleSpec: &job.OCR2OracleSpec{ + CaptureEATelemetry: true, + PluginConfig: map[string]interface{}{ + "serverURL": "a", + }, + }, + } + ds := &datasource{orm: orm, lggr: logger.TestLogger(t), jb: jb} ctx := testutils.Context(t) repts := ocrtypes.ReportTimestamp{} @@ -86,16 +96,6 @@ func Test_Datasource(t *testing.T) { Result: pipeline.Result{Value: "122.345"}, Task: &mercurymocks.MockTask{}, }, - { - // bid - Result: pipeline.Result{Value: "121.993"}, - Task: &mercurymocks.MockTask{}, - }, - { - // ask - Result: pipeline.Result{Value: "123.111"}, - Task: &mercurymocks.MockTask{}, - }, { // marketStatus Result: pipeline.Result{Value: "1"}, @@ -193,10 +193,6 @@ func Test_Datasource(t *testing.T) { assert.Equal(t, big.NewInt(122), obs.BenchmarkPrice.Val) assert.NoError(t, obs.BenchmarkPrice.Err) - assert.Equal(t, big.NewInt(121), obs.Bid.Val) - assert.NoError(t, obs.Bid.Err) - assert.Equal(t, big.NewInt(123), obs.Ask.Val) - assert.NoError(t, obs.Ask.Err) assert.Equal(t, int64(123123), obs.MaxFinalizedTimestamp.Val) assert.NoError(t, obs.MaxFinalizedTimestamp.Err) assert.Equal(t, big.NewInt(122), obs.LinkPrice.Val) @@ -239,17 +235,7 @@ func Test_Datasource(t *testing.T) { badTrrs := []pipeline.TaskRunResult{ { // benchmark price - Result: pipeline.Result{Value: "122.345"}, - Task: &mercurymocks.MockTask{}, - }, - { - // bid - Result: pipeline.Result{Value: "121.993"}, - Task: &mercurymocks.MockTask{}, - }, - { - // ask - Result: pipeline.Result{Error: errors.New("some error with ask")}, + Result: pipeline.Result{Error: errors.New("some error with bp")}, Task: &mercurymocks.MockTask{}, }, { @@ -265,7 +251,7 @@ func Test_Datasource(t *testing.T) { } _, err := ds.Observe(ctx, repts, false) - assert.EqualError(t, err, "Observe failed while parsing run results: some error with ask") + assert.EqualError(t, err, "Observe failed while parsing run results: some error with bp") }) t.Run("when run execution succeeded", func(t *testing.T) { @@ -282,10 +268,6 @@ func Test_Datasource(t *testing.T) { assert.Equal(t, big.NewInt(122), obs.BenchmarkPrice.Val) assert.NoError(t, obs.BenchmarkPrice.Err) - assert.Equal(t, big.NewInt(121), obs.Bid.Val) - assert.NoError(t, obs.Bid.Err) - assert.Equal(t, big.NewInt(123), obs.Ask.Val) - assert.NoError(t, obs.Ask.Err) assert.Equal(t, int64(0), obs.MaxFinalizedTimestamp.Val) assert.NoError(t, obs.MaxFinalizedTimestamp.Err) assert.Equal(t, big.NewInt(122), obs.LinkPrice.Val) @@ -314,6 +296,25 @@ func Test_Datasource(t *testing.T) { assert.EqualError(t, obs.NativePrice.Err, "some error fetching native price") }) + t.Run("when PluginConfig is empty", func(t *testing.T) { + t.Cleanup(func() { + ds.jb = jb + }) + + fetcher.linkPriceErr = errors.New("some error fetching link price") + fetcher.nativePriceErr = errors.New("some error fetching native price") + + ds.jb.OCR2OracleSpec.PluginConfig = job.JSONConfig{} + + obs, err := ds.Observe(ctx, repts, false) + assert.NoError(t, err) + assert.Nil(t, obs.LinkPrice.Err) + assert.Equal(t, obs.LinkPrice.Val, relaymercuryv4.MissingPrice) + assert.Nil(t, obs.NativePrice.Err) + assert.Equal(t, obs.NativePrice.Val, relaymercuryv4.MissingPrice) + assert.Equal(t, big.NewInt(122), obs.BenchmarkPrice.Val) + }) + t.Run("when succeeds to fetch linkPrice or nativePrice but got nil (new feed)", func(t *testing.T) { obs, err := ds.Observe(ctx, repts, false) assert.NoError(t, err) @@ -333,15 +334,13 @@ func buildSamplev4Report() []byte { feedID := sampleFeedID timestamp := uint32(124) bp := big.NewInt(242) - bid := big.NewInt(243) - ask := big.NewInt(244) validFromTimestamp := uint32(123) expiresAt := uint32(456) linkFee := big.NewInt(3334455) nativeFee := big.NewInt(556677) marketStatus := uint32(1) - b, err := reportcodecv4.ReportTypes.Pack(feedID, validFromTimestamp, timestamp, nativeFee, linkFee, expiresAt, bp, bid, ask, marketStatus) + b, err := reportcodecv4.ReportTypes.Pack(feedID, validFromTimestamp, timestamp, nativeFee, linkFee, expiresAt, bp, marketStatus) if err != nil { panic(err) } diff --git a/core/services/relay/evm/mercury/v4/reportcodec/report_codec.go b/core/services/relay/evm/mercury/v4/reportcodec/report_codec.go index 12f3d88e733..c5d32c02ed4 100644 --- a/core/services/relay/evm/mercury/v4/reportcodec/report_codec.go +++ b/core/services/relay/evm/mercury/v4/reportcodec/report_codec.go @@ -1,6 +1,7 @@ package reportcodec import ( + "context" "errors" "fmt" "math/big" @@ -8,8 +9,9 @@ import ( pkgerrors "github.com/pkg/errors" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" v4 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v4" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v4/types" ) @@ -29,17 +31,11 @@ func NewReportCodec(feedID [32]byte, lggr logger.Logger) *ReportCodec { return &ReportCodec{lggr, feedID} } -func (r *ReportCodec) BuildReport(rf v4.ReportFields) (ocrtypes.Report, error) { +func (r *ReportCodec) BuildReport(ctx context.Context, rf v4.ReportFields) (ocrtypes.Report, error) { var merr error if rf.BenchmarkPrice == nil { merr = errors.Join(merr, errors.New("benchmarkPrice may not be nil")) } - if rf.Bid == nil { - merr = errors.Join(merr, errors.New("bid may not be nil")) - } - if rf.Ask == nil { - merr = errors.Join(merr, errors.New("ask may not be nil")) - } if rf.LinkFee == nil { merr = errors.Join(merr, errors.New("linkFee may not be nil")) } else if rf.LinkFee.Cmp(zero) < 0 { @@ -53,28 +49,28 @@ func (r *ReportCodec) BuildReport(rf v4.ReportFields) (ocrtypes.Report, error) { if merr != nil { return nil, merr } - reportBytes, err := ReportTypes.Pack(r.feedID, rf.ValidFromTimestamp, rf.Timestamp, rf.NativeFee, rf.LinkFee, rf.ExpiresAt, rf.BenchmarkPrice, rf.Bid, rf.Ask, rf.MarketStatus) + reportBytes, err := ReportTypes.Pack(r.feedID, rf.ValidFromTimestamp, rf.Timestamp, rf.NativeFee, rf.LinkFee, rf.ExpiresAt, rf.BenchmarkPrice, rf.MarketStatus) return ocrtypes.Report(reportBytes), pkgerrors.Wrap(err, "failed to pack report blob") } -func (r *ReportCodec) MaxReportLength(n int) (int, error) { +func (r *ReportCodec) MaxReportLength(ctx context.Context, n int) (int, error) { return maxReportLength, nil } -func (r *ReportCodec) ObservationTimestampFromReport(report ocrtypes.Report) (uint32, error) { - decoded, err := r.Decode(report) +func (r *ReportCodec) ObservationTimestampFromReport(ctx context.Context, report ocrtypes.Report) (uint32, error) { + decoded, err := r.Decode(ctx, report) if err != nil { return 0, err } return decoded.ObservationsTimestamp, nil } -func (r *ReportCodec) Decode(report ocrtypes.Report) (*reporttypes.Report, error) { +func (r *ReportCodec) Decode(ctx context.Context, report ocrtypes.Report) (*reporttypes.Report, error) { return reporttypes.Decode(report) } -func (r *ReportCodec) BenchmarkPriceFromReport(report ocrtypes.Report) (*big.Int, error) { - decoded, err := r.Decode(report) +func (r *ReportCodec) BenchmarkPriceFromReport(ctx context.Context, report ocrtypes.Report) (*big.Int, error) { + decoded, err := r.Decode(ctx, report) if err != nil { return nil, err } diff --git a/core/services/relay/evm/mercury/v4/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v4/reportcodec/report_codec_test.go index b62f42ef575..9813d422cc1 100644 --- a/core/services/relay/evm/mercury/v4/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v4/reportcodec/report_codec_test.go @@ -9,14 +9,13 @@ import ( "github.com/stretchr/testify/require" v4 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v4" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) func newValidReportFields() v4.ReportFields { return v4.ReportFields{ Timestamp: 242, BenchmarkPrice: big.NewInt(243), - Bid: big.NewInt(244), - Ask: big.NewInt(245), ValidFromTimestamp: 123, ExpiresAt: 20, LinkFee: big.NewInt(456), @@ -29,7 +28,8 @@ func Test_ReportCodec_BuildReport(t *testing.T) { r := ReportCodec{} t.Run("BuildReport errors on zero values", func(t *testing.T) { - _, err := r.BuildReport(v4.ReportFields{}) + ctx := tests.Context(t) + _, err := r.BuildReport(ctx, v4.ReportFields{}) require.Error(t, err) assert.Contains(t, err.Error(), "benchmarkPrice may not be nil") assert.Contains(t, err.Error(), "linkFee may not be nil") @@ -37,10 +37,11 @@ func Test_ReportCodec_BuildReport(t *testing.T) { }) t.Run("BuildReport constructs a report from observations", func(t *testing.T) { + ctx := tests.Context(t) rf := newValidReportFields() // only need to test happy path since validations are done in relaymercury - report, err := r.BuildReport(rf) + report, err := r.BuildReport(ctx, rf) require.NoError(t, err) reportElems := make(map[string]interface{}) @@ -49,29 +50,26 @@ func Test_ReportCodec_BuildReport(t *testing.T) { assert.Equal(t, int(reportElems["observationsTimestamp"].(uint32)), 242) assert.Equal(t, reportElems["benchmarkPrice"].(*big.Int).Int64(), int64(243)) - assert.Equal(t, reportElems["bid"].(*big.Int).Int64(), int64(244)) - assert.Equal(t, reportElems["ask"].(*big.Int).Int64(), int64(245)) assert.Equal(t, reportElems["validFromTimestamp"].(uint32), uint32(123)) assert.Equal(t, reportElems["expiresAt"].(uint32), uint32(20)) assert.Equal(t, reportElems["linkFee"].(*big.Int).Int64(), int64(456)) assert.Equal(t, reportElems["nativeFee"].(*big.Int).Int64(), int64(457)) assert.Equal(t, reportElems["marketStatus"].(uint32), uint32(1)) - assert.Equal(t, types.Report{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, report) - max, err := r.MaxReportLength(4) + assert.Equal(t, types.Report{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, report) + max, err := r.MaxReportLength(ctx, 4) require.NoError(t, err) assert.LessOrEqual(t, len(report), max) t.Run("Decode decodes the report", func(t *testing.T) { - decoded, err := r.Decode(report) + ctx := tests.Context(t) + decoded, err := r.Decode(ctx, report) require.NoError(t, err) require.NotNil(t, decoded) assert.Equal(t, uint32(242), decoded.ObservationsTimestamp) assert.Equal(t, big.NewInt(243), decoded.BenchmarkPrice) - assert.Equal(t, big.NewInt(244), decoded.Bid) - assert.Equal(t, big.NewInt(245), decoded.Ask) assert.Equal(t, uint32(123), decoded.ValidFromTimestamp) assert.Equal(t, uint32(20), decoded.ExpiresAt) assert.Equal(t, big.NewInt(456), decoded.LinkFee) @@ -81,10 +79,11 @@ func Test_ReportCodec_BuildReport(t *testing.T) { }) t.Run("errors on negative fee", func(t *testing.T) { + ctx := tests.Context(t) rf := newValidReportFields() rf.LinkFee = big.NewInt(-1) rf.NativeFee = big.NewInt(-1) - _, err := r.BuildReport(rf) + _, err := r.BuildReport(ctx, rf) require.Error(t, err) assert.Contains(t, err.Error(), "linkFee may not be negative (got: -1)") @@ -92,14 +91,15 @@ func Test_ReportCodec_BuildReport(t *testing.T) { }) t.Run("Decode errors on invalid report", func(t *testing.T) { - _, err := r.Decode([]byte{1, 2, 3}) + ctx := tests.Context(t) + _, err := r.Decode(ctx, []byte{1, 2, 3}) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") longBad := make([]byte, 64) for i := 0; i < len(longBad); i++ { longBad[i] = byte(i) } - _, err = r.Decode(longBad) + _, err = r.Decode(ctx, longBad) assert.EqualError(t, err, "failed to decode report: abi: improperly encoded uint32 value") }) } @@ -108,15 +108,13 @@ func buildSampleReport(ts int64) []byte { feedID := [32]byte{'f', 'o', 'o'} timestamp := uint32(ts) bp := big.NewInt(242) - bid := big.NewInt(243) - ask := big.NewInt(244) validFromTimestamp := uint32(123) expiresAt := uint32(456) linkFee := big.NewInt(3334455) nativeFee := big.NewInt(556677) marketStatus := uint32(1) - b, err := ReportTypes.Pack(feedID, validFromTimestamp, timestamp, nativeFee, linkFee, expiresAt, bp, bid, ask, marketStatus) + b, err := ReportTypes.Pack(feedID, validFromTimestamp, timestamp, nativeFee, linkFee, expiresAt, bp, marketStatus) if err != nil { panic(err) } @@ -127,17 +125,19 @@ func Test_ReportCodec_ObservationTimestampFromReport(t *testing.T) { r := ReportCodec{} t.Run("ObservationTimestampFromReport extracts observation timestamp from a valid report", func(t *testing.T) { + ctx := tests.Context(t) report := buildSampleReport(123) - ts, err := r.ObservationTimestampFromReport(report) + ts, err := r.ObservationTimestampFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, ts, uint32(123)) }) t.Run("ObservationTimestampFromReport returns error when report is invalid", func(t *testing.T) { + ctx := tests.Context(t) report := []byte{1, 2, 3} - _, err := r.ObservationTimestampFromReport(report) + _, err := r.ObservationTimestampFromReport(ctx, report) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") @@ -148,15 +148,17 @@ func Test_ReportCodec_BenchmarkPriceFromReport(t *testing.T) { r := ReportCodec{} t.Run("BenchmarkPriceFromReport extracts the benchmark price from valid report", func(t *testing.T) { + ctx := tests.Context(t) report := buildSampleReport(123) - bp, err := r.BenchmarkPriceFromReport(report) + bp, err := r.BenchmarkPriceFromReport(ctx, report) require.NoError(t, err) assert.Equal(t, big.NewInt(242), bp) }) t.Run("BenchmarkPriceFromReport errors on invalid report", func(t *testing.T) { - _, err := r.BenchmarkPriceFromReport([]byte{1, 2, 3}) + ctx := tests.Context(t) + _, err := r.BenchmarkPriceFromReport(ctx, []byte{1, 2, 3}) require.Error(t, err) assert.EqualError(t, err, "failed to decode report: abi: cannot marshal in to go type: length insufficient 3 require 32") }) diff --git a/core/services/relay/evm/mercury/v4/types/types.go b/core/services/relay/evm/mercury/v4/types/types.go index 3abdd262a65..584836c1e9b 100644 --- a/core/services/relay/evm/mercury/v4/types/types.go +++ b/core/services/relay/evm/mercury/v4/types/types.go @@ -25,8 +25,6 @@ func GetSchema() abi.Arguments { {Name: "linkFee", Type: mustNewType("uint192")}, {Name: "expiresAt", Type: mustNewType("uint32")}, {Name: "benchmarkPrice", Type: mustNewType("int192")}, - {Name: "bid", Type: mustNewType("int192")}, - {Name: "ask", Type: mustNewType("int192")}, {Name: "marketStatus", Type: mustNewType("uint32")}, }) } @@ -35,8 +33,6 @@ type Report struct { FeedId [32]byte ObservationsTimestamp uint32 BenchmarkPrice *big.Int - Bid *big.Int - Ask *big.Int ValidFromTimestamp uint32 ExpiresAt uint32 LinkFee *big.Int diff --git a/core/services/relay/evm/mercury/verifier/verifier.go b/core/services/relay/evm/mercury/verifier/verifier.go new file mode 100644 index 00000000000..02bb17d3871 --- /dev/null +++ b/core/services/relay/evm/mercury/verifier/verifier.go @@ -0,0 +1,111 @@ +package verifier + +import ( + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +var ( + ErrVerificationFailed = errors.New("verification failed") + + ErrFailedUnmarshalPubkey = fmt.Errorf("%w: failed to unmarshal pubkey", ErrVerificationFailed) + ErrVerifyInvalidSignatureCount = fmt.Errorf("%w: invalid signature count", ErrVerificationFailed) + ErrVerifyMismatchedSignatureCount = fmt.Errorf("%w: mismatched signature count", ErrVerificationFailed) + ErrVerifyInvalidSignature = fmt.Errorf("%w: invalid signature", ErrVerificationFailed) + ErrVerifySomeSignerUnauthorized = fmt.Errorf("%w: node unauthorized", ErrVerificationFailed) + ErrVerifyNonUniqueSignature = fmt.Errorf("%w: signer has already signed", ErrVerificationFailed) +) + +type SignedReport struct { + RawRs [][32]byte + RawSs [][32]byte + RawVs [32]byte + ReportContext [3][32]byte + Report []byte +} + +type Verifier interface { + // Verify checks the report against its configuration, and then verifies signatures. + // It replicates the Verifier contract's "verify" function for server side + // report verification. + // See also: contracts/src/v0.8/llo-feeds/Verifier.sol + Verify(report SignedReport, f uint8, authorizedSigners []common.Address) (signers []common.Address, err error) +} + +var _ Verifier = (*verifier)(nil) + +type verifier struct{} + +func NewVerifier() Verifier { + return &verifier{} +} + +func (v *verifier) Verify(sr SignedReport, f uint8, authorizedSigners []common.Address) (signers []common.Address, err error) { + if len(sr.RawRs) != int(f+1) { + return signers, fmt.Errorf("%w: expected the number of signatures (len(rs)) to equal the number of signatures required (f), but f=%d and len(rs)=%d", ErrVerifyInvalidSignatureCount, f+1, len(sr.RawRs)) + } + if len(sr.RawRs) != len(sr.RawSs) { + return signers, fmt.Errorf("%w: got %d rs and %d ss, expected equal", ErrVerifyMismatchedSignatureCount, len(sr.RawRs), len(sr.RawSs)) + } + + sigData := ReportToSigData(sr.ReportContext, sr.Report) + + signerMap := make(map[common.Address]bool) + for _, signer := range authorizedSigners { + signerMap[signer] = false + } + + // Loop over every signature and collect errors. This wastes some CPU cycles, but we need to know everyone who + // signed the report. Some risk mitigated by checking that the number of signatures matches the expected (F) earlier + var verifyErrors error + reportSigners := make([]common.Address, len(sr.RawRs)) // For logging + metrics, string for convenience + for i := 0; i < len(sr.RawRs); i++ { + sig := append(sr.RawRs[i][:], sr.RawSs[i][:]...) + sig = append(sig, sr.RawVs[i]) // In the contract, you'll see vs+27. We don't do that here since geth adds +27 internally + + sigPubKey, err := crypto.Ecrecover(sigData, sig) + if err != nil { + verifyErrors = errors.Join(verifyErrors, fmt.Errorf("failed to recover signature: %w", err)) + continue + } + + verified := crypto.VerifySignature(sigPubKey, sigData, sig[:64]) + if !verified { + verifyErrors = errors.Join(verifyErrors, ErrVerifyInvalidSignature, fmt.Errorf("signature verification failed for pubKey: %x, sig: %x", sigPubKey, sig)) + continue + } + + unmarshalledPub, err := crypto.UnmarshalPubkey(sigPubKey) + if err != nil { + verifyErrors = errors.Join(verifyErrors, ErrFailedUnmarshalPubkey, fmt.Errorf("public key=%x error=%w", sigPubKey, err)) + continue + } + + address := crypto.PubkeyToAddress(*unmarshalledPub) + reportSigners[i] = address + encountered, authorized := signerMap[address] + if !authorized { + verifyErrors = errors.Join(verifyErrors, ErrVerifySomeSignerUnauthorized, fmt.Errorf("signer %s not in list of authorized nodes", address.String())) + continue + } + if encountered { + verifyErrors = errors.Join(verifyErrors, ErrVerifyNonUniqueSignature, fmt.Errorf("signer %s has already signed this report", address.String())) + continue + } + signerMap[address] = true + signers = append(signers, address) + } + return signers, verifyErrors +} + +func ReportToSigData(reportCtx [3][32]byte, sr types.Report) []byte { + sigData := crypto.Keccak256(sr) + sigData = append(sigData, reportCtx[0][:]...) + sigData = append(sigData, reportCtx[1][:]...) + sigData = append(sigData, reportCtx[2][:]...) + return crypto.Keccak256(sigData) +} diff --git a/core/services/relay/evm/mercury/verifier/verifier_test.go b/core/services/relay/evm/mercury/verifier/verifier_test.go new file mode 100644 index 00000000000..abe891b583e --- /dev/null +++ b/core/services/relay/evm/mercury/verifier/verifier_test.go @@ -0,0 +1,80 @@ +package verifier + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" +) + +func Test_Verifier(t *testing.T) { + t.Parallel() + + signedReportBinary := hexutil.MustDecode(`0x0006e1dde86b8a12add45546a14ea7e5efd10b67a373c6f4c41ecfa17d0005350000000000000000000000000000000000000000000000000000000000000201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002800001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000034c9214519c942ad0aa84a3dd31870e6efe8b3fcab4e176c5226879b26c77000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000669150aa0000000000000000000000000000000000001504e1e6c380271bb8b129ac8f7c0000000000000000000000000000000000001504e1e6c380271bb8b129ac8f7c00000000000000000000000000000000000000000000000000000000669150ab0000000000000000000000000000000000000000000000000000002482116240000000000000000000000000000000000000000000000000000000247625a04000000000000000000000000000000000000000000000000000000024880743400000000000000000000000000000000000000000000000000000000000000002710ac21df88ab70c8822b68be53d7bed65c82ffc9204c1d7ccf3c6c4048b3ca2cafb26e7bbd8f13fe626c946baa5ffcb444319c4229b945ea65d0c99c21978a100000000000000000000000000000000000000000000000000000000000000022c07843f17aa3ecd55f52e99e889906f825f49e4ddfa9c74ca487dd4ff101cc636108a5323be838e658dffa1be67bd91e99f68c4bf86936b76c5d8193b707597`) + m := make(map[string]interface{}) + err := mercury.PayloadTypes.UnpackIntoMap(m, signedReportBinary) + require.NoError(t, err) + + signedReport := SignedReport{ + RawRs: m["rawRs"].([][32]byte), + RawSs: m["rawSs"].([][32]byte), + RawVs: m["rawVs"].([32]byte), + ReportContext: m["reportContext"].([3][32]byte), + Report: m["report"].([]byte), + } + + f := uint8(1) + + v := NewVerifier() + + t.Run("Verify errors with unauthorized signers", func(t *testing.T) { + _, err := v.Verify(signedReport, f, []common.Address{}) + require.Error(t, err) + assert.EqualError(t, err, "verification failed: node unauthorized\nsigner 0x3fc9FaA15d71EeD614e5322bd9554Fb35cC381d2 not in list of authorized nodes\nverification failed: node unauthorized\nsigner 0xBa6534da0E49c71cD9d0292203F1524876f33E23 not in list of authorized nodes") + }) + + t.Run("Verify succeeds with authorized signers", func(t *testing.T) { + signers, err := v.Verify(signedReport, f, []common.Address{ + common.HexToAddress("0xde25e5b4005f611e356ce203900da4e37d72d58f"), + common.HexToAddress("0x256431d41cf0d944f5877bc6c93846a9829dfc03"), + common.HexToAddress("0x3fc9faa15d71eed614e5322bd9554fb35cc381d2"), + common.HexToAddress("0xba6534da0e49c71cd9d0292203f1524876f33e23"), + }) + require.NoError(t, err) + assert.Equal(t, []common.Address{ + common.HexToAddress("0x3fc9faa15d71eed614e5322bd9554fb35cc381d2"), + common.HexToAddress("0xBa6534da0E49c71cD9d0292203F1524876f33E23"), + }, signers) + }) + + t.Run("Verify fails if report has been tampered with", func(t *testing.T) { + badReport := signedReport + badReport.Report = []byte{0x0011} + _, err := v.Verify(badReport, f, []common.Address{ + common.HexToAddress("0xde25e5b4005f611e356ce203900da4e37d72d58f"), + common.HexToAddress("0x256431d41cf0d944f5877bc6c93846a9829dfc03"), + common.HexToAddress("0x3fc9faa15d71eed614e5322bd9554fb35cc381d2"), + common.HexToAddress("0xba6534da0e49c71cd9d0292203f1524876f33e23"), + }) + + require.Error(t, err) + }) + + t.Run("Verify fails if rawVs has been changed", func(t *testing.T) { + badReport := signedReport + badReport.RawVs = [32]byte{0x0011} + _, err := v.Verify(badReport, f, []common.Address{ + common.HexToAddress("0xde25e5b4005f611e356ce203900da4e37d72d58f"), + common.HexToAddress("0x256431d41cf0d944f5877bc6c93846a9829dfc03"), + common.HexToAddress("0x3fc9faa15d71eed614e5322bd9554fb35cc381d2"), + common.HexToAddress("0xba6534da0e49c71cd9d0292203f1524876f33e23"), + }) + + require.Error(t, err) + assert.Contains(t, err.Error(), "failed to recover signature: invalid signature recovery id") + }) +} diff --git a/core/services/relay/evm/mercury/wsrpc/client.go b/core/services/relay/evm/mercury/wsrpc/client.go index b5d784face0..37207510655 100644 --- a/core/services/relay/evm/mercury/wsrpc/client.go +++ b/core/services/relay/evm/mercury/wsrpc/client.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + grpc_connectivity "google.golang.org/grpc/connectivity" "github.com/smartcontractkit/wsrpc" "github.com/smartcontractkit/wsrpc/connectivity" @@ -70,8 +71,8 @@ type Client interface { type Conn interface { WaitForReady(ctx context.Context) bool - GetState() connectivity.State - Close() + GetState() grpc_connectivity.State + Close() error } type client struct { @@ -230,7 +231,7 @@ func (w *client) Healthy() (err error) { return err } state := w.conn.GetState() - if state != connectivity.Ready { + if state != grpc_connectivity.Ready { return errors.Errorf("client state should be %s; got %s", connectivity.Ready, state) } return nil diff --git a/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go b/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go index 61912c26b02..e202802ea77 100644 --- a/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go +++ b/core/services/relay/evm/mercury/wsrpc/mocks/mocks.go @@ -3,7 +3,7 @@ package mocks import ( "context" - "github.com/smartcontractkit/wsrpc/connectivity" + grpc_connectivity "google.golang.org/grpc/connectivity" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) @@ -29,15 +29,16 @@ func (m *MockWSRPCClient) ServerURL() string { return "mock server url" } func (m *MockWSRPCClient) RawClient() pb.MercuryClient { return nil } type MockConn struct { - State connectivity.State + State grpc_connectivity.State Ready bool Closed bool } -func (m *MockConn) Close() { +func (m *MockConn) Close() error { m.Closed = true + return nil } func (m MockConn) WaitForReady(ctx context.Context) bool { return m.Ready } -func (m MockConn) GetState() connectivity.State { return m.State } +func (m MockConn) GetState() grpc_connectivity.State { return m.State } diff --git a/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go b/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go index ab74d426bbe..c3755b36809 100644 --- a/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go +++ b/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.35.1 // protoc v4.25.1 // source: mercury.proto @@ -31,11 +31,9 @@ type TransmitRequest struct { func (x *TransmitRequest) Reset() { *x = TransmitRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_mercury_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_mercury_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TransmitRequest) String() string { @@ -46,7 +44,7 @@ func (*TransmitRequest) ProtoMessage() {} func (x *TransmitRequest) ProtoReflect() protoreflect.Message { mi := &file_mercury_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -86,11 +84,9 @@ type TransmitResponse struct { func (x *TransmitResponse) Reset() { *x = TransmitResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_mercury_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_mercury_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *TransmitResponse) String() string { @@ -101,7 +97,7 @@ func (*TransmitResponse) ProtoMessage() {} func (x *TransmitResponse) ProtoReflect() protoreflect.Message { mi := &file_mercury_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -140,11 +136,9 @@ type LatestReportRequest struct { func (x *LatestReportRequest) Reset() { *x = LatestReportRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_mercury_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_mercury_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *LatestReportRequest) String() string { @@ -155,7 +149,7 @@ func (*LatestReportRequest) ProtoMessage() {} func (x *LatestReportRequest) ProtoReflect() protoreflect.Message { mi := &file_mercury_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -188,11 +182,9 @@ type LatestReportResponse struct { func (x *LatestReportResponse) Reset() { *x = LatestReportResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_mercury_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_mercury_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *LatestReportResponse) String() string { @@ -203,7 +195,7 @@ func (*LatestReportResponse) ProtoMessage() {} func (x *LatestReportResponse) ProtoReflect() protoreflect.Message { mi := &file_mercury_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -255,11 +247,9 @@ type Report struct { func (x *Report) Reset() { *x = Report{} - if protoimpl.UnsafeEnabled { - mi := &file_mercury_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_mercury_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Report) String() string { @@ -270,7 +260,7 @@ func (*Report) ProtoMessage() {} func (x *Report) ProtoReflect() protoreflect.Message { mi := &file_mercury_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -402,11 +392,9 @@ type Timestamp struct { func (x *Timestamp) Reset() { *x = Timestamp{} - if protoimpl.UnsafeEnabled { - mi := &file_mercury_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_mercury_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Timestamp) String() string { @@ -417,7 +405,7 @@ func (*Timestamp) ProtoMessage() {} func (x *Timestamp) ProtoReflect() protoreflect.Message { mi := &file_mercury_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -562,80 +550,6 @@ func file_mercury_proto_init() { if File_mercury_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_mercury_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*TransmitRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_mercury_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*TransmitResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_mercury_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*LatestReportRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_mercury_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*LatestReportResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_mercury_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*Report); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_mercury_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*Timestamp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/core/services/relay/evm/mercury_config_provider.go b/core/services/relay/evm/mercury_config_provider.go index bd0749e5ae2..53bf8e22d24 100644 --- a/core/services/relay/evm/mercury_config_provider.go +++ b/core/services/relay/evm/mercury_config_provider.go @@ -7,10 +7,12 @@ import ( "github.com/ethereum/go-ethereum/common" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -31,7 +33,7 @@ func newMercuryConfigProvider(ctx context.Context, lggr logger.Logger, chain leg } cp, err := mercury.NewConfigPoller( ctx, - lggr.Named(relayConfig.FeedID.String()), + logger.Named(lggr, relayConfig.FeedID.String()), chain.LogPoller(), aggregatorAddress, *relayConfig.FeedID, @@ -41,6 +43,6 @@ func newMercuryConfigProvider(ctx context.Context, lggr logger.Logger, chain leg return nil, err } - offchainConfigDigester := mercury.NewOffchainConfigDigester(*relayConfig.FeedID, chain.Config().EVM().ChainID(), aggregatorAddress) + offchainConfigDigester := mercury.NewOffchainConfigDigester(*relayConfig.FeedID, chain.Config().EVM().ChainID(), aggregatorAddress, ocrtypes.ConfigDigestPrefixMercuryV02) return newConfigWatcher(lggr, aggregatorAddress, offchainConfigDigester, cp, chain, relayConfig.FromBlock, opts.New), nil } diff --git a/core/services/relay/evm/mercury_provider.go b/core/services/relay/evm/mercury_provider.go index 9393f66b0dd..85f633e063a 100644 --- a/core/services/relay/evm/mercury_provider.go +++ b/core/services/relay/evm/mercury_provider.go @@ -6,6 +6,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" mercurytypes "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" @@ -13,9 +14,10 @@ import ( v2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" v4 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v4" + "github.com/smartcontractkit/chainlink-data-streams/mercury" + httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" evmmercury "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" ) @@ -23,7 +25,6 @@ var _ commontypes.MercuryProvider = (*mercuryProvider)(nil) type mercuryProvider struct { cp commontypes.ConfigProvider - chainReader commontypes.ContractReader codec commontypes.Codec transmitter evmmercury.Transmitter reportCodecV1 v1.ReportCodec @@ -37,7 +38,6 @@ type mercuryProvider struct { func NewMercuryProvider( cp commontypes.ConfigProvider, - chainReader commontypes.ContractReader, codec commontypes.Codec, mercuryChainReader mercurytypes.ChainReader, transmitter evmmercury.Transmitter, @@ -49,7 +49,6 @@ func NewMercuryProvider( ) *mercuryProvider { return &mercuryProvider{ cp, - chainReader, codec, transmitter, reportCodecV1, @@ -129,8 +128,8 @@ func (p *mercuryProvider) MercuryServerFetcher() mercurytypes.ServerFetcher { return p.transmitter } -func (p *mercuryProvider) ChainReader() commontypes.ContractReader { - return p.chainReader +func (p *mercuryProvider) ContractReader() commontypes.ContractReader { + return nil } var _ mercurytypes.ChainReader = (*mercuryChainReader)(nil) diff --git a/core/services/relay/evm/method_binding.go b/core/services/relay/evm/method_binding.go deleted file mode 100644 index 448f1b9fbf2..00000000000 --- a/core/services/relay/evm/method_binding.go +++ /dev/null @@ -1,130 +0,0 @@ -package evm - -import ( - "context" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "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/logger" - - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" -) - -type NoContractExistsError struct { - Address common.Address -} - -func (e NoContractExistsError) Error() string { - return fmt.Sprintf("contract does not exist at address: %s", e.Address) -} - -type methodBinding struct { - lggr logger.Logger - ht logpoller.HeadTracker - address common.Address - contractName string - method string - client evmclient.Client - codec commontypes.Codec - bound bool - confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations -} - -var _ readBinding = &methodBinding{} - -func (m *methodBinding) SetCodec(codec commontypes.RemoteCodec) { - m.codec = codec -} - -func (m *methodBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { - addr := common.HexToAddress(binding.Address) - - // check for contract byte code at the latest block and provided address - byteCode, err := m.client.CodeAt(ctx, addr, nil) - if err != nil { - return err - } - - if len(byteCode) == 0 { - return NoContractExistsError{Address: addr} - } - - m.address = addr - m.bound = true - - return nil -} - -func (m *methodBinding) Register(_ context.Context) error { - return nil -} - -func (m *methodBinding) Unregister(_ context.Context) error { - return nil -} - -func (m *methodBinding) GetLatestValue(ctx context.Context, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error { - if !m.bound { - return fmt.Errorf("%w: method not bound", commontypes.ErrInvalidType) - } - - data, err := m.codec.Encode(ctx, params, WrapItemType(m.contractName, m.method, true)) - if err != nil { - return err - } - - callMsg := ethereum.CallMsg{ - To: &m.address, - From: m.address, - Data: data, - } - - block, err := m.blockNumberFromConfidence(ctx, confidenceLevel) - if err != nil { - return err - } - - bytes, err := m.client.CallContract(ctx, callMsg, block) - if err != nil { - return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) - } - - return m.codec.Decode(ctx, bytes, returnVal, WrapItemType(m.contractName, m.method, false)) -} - -func (m *methodBinding) QueryKey(_ context.Context, _ query.KeyFilter, _ query.LimitAndSort, _ any) ([]commontypes.Sequence, error) { - return nil, nil -} - -func (m *methodBinding) blockNumberFromConfidence(ctx context.Context, confidenceLevel primitives.ConfidenceLevel) (*big.Int, error) { - confirmations, err := confidenceToConfirmations(m.confirmationsMapping, confidenceLevel) - if err != nil { - err = fmt.Errorf("%w for contract: %s, method: %s", err, m.contractName, m.method) - if confidenceLevel == primitives.Unconfirmed { - m.lggr.Errorf("%v, now falling back to default contract call behaviour that calls latest state", err) - return nil, nil - } - return nil, err - } - - _, finalized, err := m.ht.LatestAndFinalizedBlock(ctx) - if err != nil { - return nil, err - } - - if confirmations == evmtypes.Finalized { - return big.NewInt(finalized.Number), nil - } else if confirmations == evmtypes.Unconfirmed { - return nil, nil - } - - return nil, fmt.Errorf("unknown evm confirmations: %v for contract: %s, method: %s", confirmations, m.contractName, m.method) -} diff --git a/core/services/relay/evm/mocks/loop_relay_adapter.go b/core/services/relay/evm/mocks/loop_relay_adapter.go deleted file mode 100644 index 50b1dd5f397..00000000000 --- a/core/services/relay/evm/mocks/loop_relay_adapter.go +++ /dev/null @@ -1,793 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - legacyevm "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// LoopRelayAdapter is an autogenerated mock type for the LoopRelayAdapter type -type LoopRelayAdapter struct { - mock.Mock -} - -type LoopRelayAdapter_Expecter struct { - mock *mock.Mock -} - -func (_m *LoopRelayAdapter) EXPECT() *LoopRelayAdapter_Expecter { - return &LoopRelayAdapter_Expecter{mock: &_m.Mock} -} - -// Chain provides a mock function with given fields: -func (_m *LoopRelayAdapter) Chain() legacyevm.Chain { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Chain") - } - - var r0 legacyevm.Chain - if rf, ok := ret.Get(0).(func() legacyevm.Chain); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(legacyevm.Chain) - } - } - - return r0 -} - -// LoopRelayAdapter_Chain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Chain' -type LoopRelayAdapter_Chain_Call struct { - *mock.Call -} - -// Chain is a helper method to define mock.On call -func (_e *LoopRelayAdapter_Expecter) Chain() *LoopRelayAdapter_Chain_Call { - return &LoopRelayAdapter_Chain_Call{Call: _e.mock.On("Chain")} -} - -func (_c *LoopRelayAdapter_Chain_Call) Run(run func()) *LoopRelayAdapter_Chain_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *LoopRelayAdapter_Chain_Call) Return(_a0 legacyevm.Chain) *LoopRelayAdapter_Chain_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_Chain_Call) RunAndReturn(run func() legacyevm.Chain) *LoopRelayAdapter_Chain_Call { - _c.Call.Return(run) - return _c -} - -// Close provides a mock function with given fields: -func (_m *LoopRelayAdapter) 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 -} - -// LoopRelayAdapter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type LoopRelayAdapter_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *LoopRelayAdapter_Expecter) Close() *LoopRelayAdapter_Close_Call { - return &LoopRelayAdapter_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *LoopRelayAdapter_Close_Call) Run(run func()) *LoopRelayAdapter_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *LoopRelayAdapter_Close_Call) Return(_a0 error) *LoopRelayAdapter_Close_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_Close_Call) RunAndReturn(run func() error) *LoopRelayAdapter_Close_Call { - _c.Call.Return(run) - return _c -} - -// GetChainStatus provides a mock function with given fields: ctx -func (_m *LoopRelayAdapter) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for GetChainStatus") - } - - var r0 types.ChainStatus - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (types.ChainStatus, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) types.ChainStatus); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(types.ChainStatus) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoopRelayAdapter_GetChainStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetChainStatus' -type LoopRelayAdapter_GetChainStatus_Call struct { - *mock.Call -} - -// GetChainStatus is a helper method to define mock.On call -// - ctx context.Context -func (_e *LoopRelayAdapter_Expecter) GetChainStatus(ctx interface{}) *LoopRelayAdapter_GetChainStatus_Call { - return &LoopRelayAdapter_GetChainStatus_Call{Call: _e.mock.On("GetChainStatus", ctx)} -} - -func (_c *LoopRelayAdapter_GetChainStatus_Call) Run(run func(ctx context.Context)) *LoopRelayAdapter_GetChainStatus_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *LoopRelayAdapter_GetChainStatus_Call) Return(_a0 types.ChainStatus, _a1 error) *LoopRelayAdapter_GetChainStatus_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *LoopRelayAdapter_GetChainStatus_Call) RunAndReturn(run func(context.Context) (types.ChainStatus, error)) *LoopRelayAdapter_GetChainStatus_Call { - _c.Call.Return(run) - return _c -} - -// HealthReport provides a mock function with given fields: -func (_m *LoopRelayAdapter) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// LoopRelayAdapter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type LoopRelayAdapter_HealthReport_Call struct { - *mock.Call -} - -// HealthReport is a helper method to define mock.On call -func (_e *LoopRelayAdapter_Expecter) HealthReport() *LoopRelayAdapter_HealthReport_Call { - return &LoopRelayAdapter_HealthReport_Call{Call: _e.mock.On("HealthReport")} -} - -func (_c *LoopRelayAdapter_HealthReport_Call) Run(run func()) *LoopRelayAdapter_HealthReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *LoopRelayAdapter_HealthReport_Call) Return(_a0 map[string]error) *LoopRelayAdapter_HealthReport_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_HealthReport_Call) RunAndReturn(run func() map[string]error) *LoopRelayAdapter_HealthReport_Call { - _c.Call.Return(run) - return _c -} - -// ListNodeStatuses provides a mock function with given fields: ctx, pageSize, pageToken -func (_m *LoopRelayAdapter) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) ([]types.NodeStatus, string, int, error) { - ret := _m.Called(ctx, pageSize, pageToken) - - if len(ret) == 0 { - panic("no return value specified for ListNodeStatuses") - } - - var r0 []types.NodeStatus - var r1 string - var r2 int - var r3 error - if rf, ok := ret.Get(0).(func(context.Context, int32, string) ([]types.NodeStatus, string, int, error)); ok { - return rf(ctx, pageSize, pageToken) - } - if rf, ok := ret.Get(0).(func(context.Context, int32, string) []types.NodeStatus); ok { - r0 = rf(ctx, pageSize, pageToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]types.NodeStatus) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, int32, string) string); ok { - r1 = rf(ctx, pageSize, pageToken) - } else { - r1 = ret.Get(1).(string) - } - - if rf, ok := ret.Get(2).(func(context.Context, int32, string) int); ok { - r2 = rf(ctx, pageSize, pageToken) - } else { - r2 = ret.Get(2).(int) - } - - if rf, ok := ret.Get(3).(func(context.Context, int32, string) error); ok { - r3 = rf(ctx, pageSize, pageToken) - } else { - r3 = ret.Error(3) - } - - return r0, r1, r2, r3 -} - -// LoopRelayAdapter_ListNodeStatuses_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListNodeStatuses' -type LoopRelayAdapter_ListNodeStatuses_Call struct { - *mock.Call -} - -// ListNodeStatuses is a helper method to define mock.On call -// - ctx context.Context -// - pageSize int32 -// - pageToken string -func (_e *LoopRelayAdapter_Expecter) ListNodeStatuses(ctx interface{}, pageSize interface{}, pageToken interface{}) *LoopRelayAdapter_ListNodeStatuses_Call { - return &LoopRelayAdapter_ListNodeStatuses_Call{Call: _e.mock.On("ListNodeStatuses", ctx, pageSize, pageToken)} -} - -func (_c *LoopRelayAdapter_ListNodeStatuses_Call) Run(run func(ctx context.Context, pageSize int32, pageToken string)) *LoopRelayAdapter_ListNodeStatuses_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(int32), args[2].(string)) - }) - return _c -} - -func (_c *LoopRelayAdapter_ListNodeStatuses_Call) Return(stats []types.NodeStatus, nextPageToken string, total int, err error) *LoopRelayAdapter_ListNodeStatuses_Call { - _c.Call.Return(stats, nextPageToken, total, err) - return _c -} - -func (_c *LoopRelayAdapter_ListNodeStatuses_Call) RunAndReturn(run func(context.Context, int32, string) ([]types.NodeStatus, string, int, error)) *LoopRelayAdapter_ListNodeStatuses_Call { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *LoopRelayAdapter) 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 -} - -// LoopRelayAdapter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type LoopRelayAdapter_Name_Call struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *LoopRelayAdapter_Expecter) Name() *LoopRelayAdapter_Name_Call { - return &LoopRelayAdapter_Name_Call{Call: _e.mock.On("Name")} -} - -func (_c *LoopRelayAdapter_Name_Call) Run(run func()) *LoopRelayAdapter_Name_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *LoopRelayAdapter_Name_Call) Return(_a0 string) *LoopRelayAdapter_Name_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_Name_Call) RunAndReturn(run func() string) *LoopRelayAdapter_Name_Call { - _c.Call.Return(run) - return _c -} - -// NewChainWriter provides a mock function with given fields: ctx, chainWriterConfig -func (_m *LoopRelayAdapter) NewChainWriter(ctx context.Context, chainWriterConfig []byte) (types.ChainWriter, error) { - ret := _m.Called(ctx, chainWriterConfig) - - if len(ret) == 0 { - panic("no return value specified for NewChainWriter") - } - - var r0 types.ChainWriter - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []byte) (types.ChainWriter, error)); ok { - return rf(ctx, chainWriterConfig) - } - if rf, ok := ret.Get(0).(func(context.Context, []byte) types.ChainWriter); ok { - r0 = rf(ctx, chainWriterConfig) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.ChainWriter) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, []byte) error); ok { - r1 = rf(ctx, chainWriterConfig) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoopRelayAdapter_NewChainWriter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewChainWriter' -type LoopRelayAdapter_NewChainWriter_Call struct { - *mock.Call -} - -// NewChainWriter is a helper method to define mock.On call -// - ctx context.Context -// - chainWriterConfig []byte -func (_e *LoopRelayAdapter_Expecter) NewChainWriter(ctx interface{}, chainWriterConfig interface{}) *LoopRelayAdapter_NewChainWriter_Call { - return &LoopRelayAdapter_NewChainWriter_Call{Call: _e.mock.On("NewChainWriter", ctx, chainWriterConfig)} -} - -func (_c *LoopRelayAdapter_NewChainWriter_Call) Run(run func(ctx context.Context, chainWriterConfig []byte)) *LoopRelayAdapter_NewChainWriter_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]byte)) - }) - return _c -} - -func (_c *LoopRelayAdapter_NewChainWriter_Call) Return(_a0 types.ChainWriter, _a1 error) *LoopRelayAdapter_NewChainWriter_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *LoopRelayAdapter_NewChainWriter_Call) RunAndReturn(run func(context.Context, []byte) (types.ChainWriter, error)) *LoopRelayAdapter_NewChainWriter_Call { - _c.Call.Return(run) - return _c -} - -// NewConfigProvider provides a mock function with given fields: _a0, _a1 -func (_m *LoopRelayAdapter) NewConfigProvider(_a0 context.Context, _a1 types.RelayArgs) (types.ConfigProvider, error) { - ret := _m.Called(_a0, _a1) - - if len(ret) == 0 { - panic("no return value specified for NewConfigProvider") - } - - var r0 types.ConfigProvider - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.RelayArgs) (types.ConfigProvider, error)); ok { - return rf(_a0, _a1) - } - if rf, ok := ret.Get(0).(func(context.Context, types.RelayArgs) types.ConfigProvider); ok { - r0 = rf(_a0, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.ConfigProvider) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, types.RelayArgs) error); ok { - r1 = rf(_a0, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoopRelayAdapter_NewConfigProvider_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewConfigProvider' -type LoopRelayAdapter_NewConfigProvider_Call struct { - *mock.Call -} - -// NewConfigProvider is a helper method to define mock.On call -// - _a0 context.Context -// - _a1 types.RelayArgs -func (_e *LoopRelayAdapter_Expecter) NewConfigProvider(_a0 interface{}, _a1 interface{}) *LoopRelayAdapter_NewConfigProvider_Call { - return &LoopRelayAdapter_NewConfigProvider_Call{Call: _e.mock.On("NewConfigProvider", _a0, _a1)} -} - -func (_c *LoopRelayAdapter_NewConfigProvider_Call) Run(run func(_a0 context.Context, _a1 types.RelayArgs)) *LoopRelayAdapter_NewConfigProvider_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(types.RelayArgs)) - }) - return _c -} - -func (_c *LoopRelayAdapter_NewConfigProvider_Call) Return(_a0 types.ConfigProvider, _a1 error) *LoopRelayAdapter_NewConfigProvider_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *LoopRelayAdapter_NewConfigProvider_Call) RunAndReturn(run func(context.Context, types.RelayArgs) (types.ConfigProvider, error)) *LoopRelayAdapter_NewConfigProvider_Call { - _c.Call.Return(run) - return _c -} - -// NewContractReader provides a mock function with given fields: ctx, contractReaderConfig -func (_m *LoopRelayAdapter) NewContractReader(ctx context.Context, contractReaderConfig []byte) (types.ChainReader, error) { - ret := _m.Called(ctx, contractReaderConfig) - - if len(ret) == 0 { - panic("no return value specified for NewContractReader") - } - - var r0 types.ChainReader - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []byte) (types.ChainReader, error)); ok { - return rf(ctx, contractReaderConfig) - } - if rf, ok := ret.Get(0).(func(context.Context, []byte) types.ChainReader); ok { - r0 = rf(ctx, contractReaderConfig) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.ChainReader) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, []byte) error); ok { - r1 = rf(ctx, contractReaderConfig) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoopRelayAdapter_NewContractReader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewContractReader' -type LoopRelayAdapter_NewContractReader_Call struct { - *mock.Call -} - -// NewContractReader is a helper method to define mock.On call -// - ctx context.Context -// - contractReaderConfig []byte -func (_e *LoopRelayAdapter_Expecter) NewContractReader(ctx interface{}, contractReaderConfig interface{}) *LoopRelayAdapter_NewContractReader_Call { - return &LoopRelayAdapter_NewContractReader_Call{Call: _e.mock.On("NewContractReader", ctx, contractReaderConfig)} -} - -func (_c *LoopRelayAdapter_NewContractReader_Call) Run(run func(ctx context.Context, contractReaderConfig []byte)) *LoopRelayAdapter_NewContractReader_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]byte)) - }) - return _c -} - -func (_c *LoopRelayAdapter_NewContractReader_Call) Return(_a0 types.ChainReader, _a1 error) *LoopRelayAdapter_NewContractReader_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *LoopRelayAdapter_NewContractReader_Call) RunAndReturn(run func(context.Context, []byte) (types.ChainReader, error)) *LoopRelayAdapter_NewContractReader_Call { - _c.Call.Return(run) - return _c -} - -// NewLLOProvider provides a mock function with given fields: _a0, _a1, _a2 -func (_m *LoopRelayAdapter) NewLLOProvider(_a0 context.Context, _a1 types.RelayArgs, _a2 types.PluginArgs) (types.LLOProvider, error) { - ret := _m.Called(_a0, _a1, _a2) - - if len(ret) == 0 { - panic("no return value specified for NewLLOProvider") - } - - var r0 types.LLOProvider - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.RelayArgs, types.PluginArgs) (types.LLOProvider, error)); ok { - return rf(_a0, _a1, _a2) - } - if rf, ok := ret.Get(0).(func(context.Context, types.RelayArgs, types.PluginArgs) types.LLOProvider); ok { - r0 = rf(_a0, _a1, _a2) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.LLOProvider) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, types.RelayArgs, types.PluginArgs) error); ok { - r1 = rf(_a0, _a1, _a2) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoopRelayAdapter_NewLLOProvider_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewLLOProvider' -type LoopRelayAdapter_NewLLOProvider_Call struct { - *mock.Call -} - -// NewLLOProvider is a helper method to define mock.On call -// - _a0 context.Context -// - _a1 types.RelayArgs -// - _a2 types.PluginArgs -func (_e *LoopRelayAdapter_Expecter) NewLLOProvider(_a0 interface{}, _a1 interface{}, _a2 interface{}) *LoopRelayAdapter_NewLLOProvider_Call { - return &LoopRelayAdapter_NewLLOProvider_Call{Call: _e.mock.On("NewLLOProvider", _a0, _a1, _a2)} -} - -func (_c *LoopRelayAdapter_NewLLOProvider_Call) Run(run func(_a0 context.Context, _a1 types.RelayArgs, _a2 types.PluginArgs)) *LoopRelayAdapter_NewLLOProvider_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(types.RelayArgs), args[2].(types.PluginArgs)) - }) - return _c -} - -func (_c *LoopRelayAdapter_NewLLOProvider_Call) Return(_a0 types.LLOProvider, _a1 error) *LoopRelayAdapter_NewLLOProvider_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *LoopRelayAdapter_NewLLOProvider_Call) RunAndReturn(run func(context.Context, types.RelayArgs, types.PluginArgs) (types.LLOProvider, error)) *LoopRelayAdapter_NewLLOProvider_Call { - _c.Call.Return(run) - return _c -} - -// NewPluginProvider provides a mock function with given fields: _a0, _a1, _a2 -func (_m *LoopRelayAdapter) NewPluginProvider(_a0 context.Context, _a1 types.RelayArgs, _a2 types.PluginArgs) (types.PluginProvider, error) { - ret := _m.Called(_a0, _a1, _a2) - - if len(ret) == 0 { - panic("no return value specified for NewPluginProvider") - } - - var r0 types.PluginProvider - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.RelayArgs, types.PluginArgs) (types.PluginProvider, error)); ok { - return rf(_a0, _a1, _a2) - } - if rf, ok := ret.Get(0).(func(context.Context, types.RelayArgs, types.PluginArgs) types.PluginProvider); ok { - r0 = rf(_a0, _a1, _a2) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.PluginProvider) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, types.RelayArgs, types.PluginArgs) error); ok { - r1 = rf(_a0, _a1, _a2) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoopRelayAdapter_NewPluginProvider_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewPluginProvider' -type LoopRelayAdapter_NewPluginProvider_Call struct { - *mock.Call -} - -// NewPluginProvider is a helper method to define mock.On call -// - _a0 context.Context -// - _a1 types.RelayArgs -// - _a2 types.PluginArgs -func (_e *LoopRelayAdapter_Expecter) NewPluginProvider(_a0 interface{}, _a1 interface{}, _a2 interface{}) *LoopRelayAdapter_NewPluginProvider_Call { - return &LoopRelayAdapter_NewPluginProvider_Call{Call: _e.mock.On("NewPluginProvider", _a0, _a1, _a2)} -} - -func (_c *LoopRelayAdapter_NewPluginProvider_Call) Run(run func(_a0 context.Context, _a1 types.RelayArgs, _a2 types.PluginArgs)) *LoopRelayAdapter_NewPluginProvider_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(types.RelayArgs), args[2].(types.PluginArgs)) - }) - return _c -} - -func (_c *LoopRelayAdapter_NewPluginProvider_Call) Return(_a0 types.PluginProvider, _a1 error) *LoopRelayAdapter_NewPluginProvider_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *LoopRelayAdapter_NewPluginProvider_Call) RunAndReturn(run func(context.Context, types.RelayArgs, types.PluginArgs) (types.PluginProvider, error)) *LoopRelayAdapter_NewPluginProvider_Call { - _c.Call.Return(run) - return _c -} - -// Ready provides a mock function with given fields: -func (_m *LoopRelayAdapter) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// LoopRelayAdapter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type LoopRelayAdapter_Ready_Call struct { - *mock.Call -} - -// Ready is a helper method to define mock.On call -func (_e *LoopRelayAdapter_Expecter) Ready() *LoopRelayAdapter_Ready_Call { - return &LoopRelayAdapter_Ready_Call{Call: _e.mock.On("Ready")} -} - -func (_c *LoopRelayAdapter_Ready_Call) Run(run func()) *LoopRelayAdapter_Ready_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *LoopRelayAdapter_Ready_Call) Return(_a0 error) *LoopRelayAdapter_Ready_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_Ready_Call) RunAndReturn(run func() error) *LoopRelayAdapter_Ready_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *LoopRelayAdapter) 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 -} - -// LoopRelayAdapter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type LoopRelayAdapter_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *LoopRelayAdapter_Expecter) Start(_a0 interface{}) *LoopRelayAdapter_Start_Call { - return &LoopRelayAdapter_Start_Call{Call: _e.mock.On("Start", _a0)} -} - -func (_c *LoopRelayAdapter_Start_Call) Run(run func(_a0 context.Context)) *LoopRelayAdapter_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *LoopRelayAdapter_Start_Call) Return(_a0 error) *LoopRelayAdapter_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_Start_Call) RunAndReturn(run func(context.Context) error) *LoopRelayAdapter_Start_Call { - _c.Call.Return(run) - return _c -} - -// Transact provides a mock function with given fields: ctx, from, to, amount, balanceCheck -func (_m *LoopRelayAdapter) Transact(ctx context.Context, from string, to string, amount *big.Int, balanceCheck bool) error { - ret := _m.Called(ctx, from, to, amount, balanceCheck) - - if len(ret) == 0 { - panic("no return value specified for Transact") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, *big.Int, bool) error); ok { - r0 = rf(ctx, from, to, amount, balanceCheck) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// LoopRelayAdapter_Transact_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Transact' -type LoopRelayAdapter_Transact_Call struct { - *mock.Call -} - -// Transact is a helper method to define mock.On call -// - ctx context.Context -// - from string -// - to string -// - amount *big.Int -// - balanceCheck bool -func (_e *LoopRelayAdapter_Expecter) Transact(ctx interface{}, from interface{}, to interface{}, amount interface{}, balanceCheck interface{}) *LoopRelayAdapter_Transact_Call { - return &LoopRelayAdapter_Transact_Call{Call: _e.mock.On("Transact", ctx, from, to, amount, balanceCheck)} -} - -func (_c *LoopRelayAdapter_Transact_Call) Run(run func(ctx context.Context, from string, to string, amount *big.Int, balanceCheck bool)) *LoopRelayAdapter_Transact_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(*big.Int), args[4].(bool)) - }) - return _c -} - -func (_c *LoopRelayAdapter_Transact_Call) Return(_a0 error) *LoopRelayAdapter_Transact_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *LoopRelayAdapter_Transact_Call) RunAndReturn(run func(context.Context, string, string, *big.Int, bool) error) *LoopRelayAdapter_Transact_Call { - _c.Call.Return(run) - return _c -} - -// NewLoopRelayAdapter creates a new instance of LoopRelayAdapter. 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 NewLoopRelayAdapter(t interface { - mock.TestingT - Cleanup(func()) -}) *LoopRelayAdapter { - mock := &LoopRelayAdapter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go index b2d19c11702..db96afee7d7 100644 --- a/core/services/relay/evm/ocr2keeper.go +++ b/core/services/relay/evm/ocr2keeper.go @@ -13,6 +13,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/automation" @@ -20,7 +21,6 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" evm "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding" @@ -59,7 +59,7 @@ type OCR2KeeperProvider interface { // OCR2KeeperRelayer contains the relayer and instantiating functions for OCR2Keeper providers. type OCR2KeeperRelayer interface { - NewOCR2KeeperProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error) + NewOCR2KeeperProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error) } // ocr2keeperRelayer is the relayer with added DKG and OCR2Keeper provider functions. @@ -80,10 +80,7 @@ func NewOCR2KeeperRelayer(ds sqlutil.DataSource, chain legacyevm.Chain, lggr log } } -func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error) { - // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 - ctx := context.Background() - +func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(ctx context.Context, rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (OCR2KeeperProvider, error) { cfgWatcher, err := newOCR2KeeperConfigProvider(ctx, r.lggr, r.chain, rargs) if err != nil { return nil, err @@ -174,8 +171,8 @@ func (t *ocr3keeperProviderContractTransmitter) Transmit( ) } -func (t *ocr3keeperProviderContractTransmitter) FromAccount() (ocrtypes.Account, error) { - return t.contractTransmitter.FromAccount() +func (t *ocr3keeperProviderContractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return t.contractTransmitter.FromAccount(ctx) } type ocr2keeperProvider struct { @@ -196,7 +193,7 @@ func (c *ocr2keeperProvider) ContractTransmitter() ocrtypes.ContractTransmitter return c.contractTransmitter } -func (c *ocr2keeperProvider) ChainReader() commontypes.ContractReader { +func (c *ocr2keeperProvider) ContractReader() commontypes.ContractReader { return nil } @@ -218,7 +215,7 @@ func newOCR2KeeperConfigProvider(ctx context.Context, lggr logger.Logger, chain configPoller, err := NewConfigPoller( ctx, - lggr.With("contractID", rargs.ContractID), + logger.With(lggr, "contractID", rargs.ContractID), CPConfig{ chain.Client(), chain.LogPoller(), diff --git a/core/services/relay/evm/ocr3_capability_provider.go b/core/services/relay/evm/ocr3_capability_provider.go index 2080e1df873..56a8d37bbe9 100644 --- a/core/services/relay/evm/ocr3_capability_provider.go +++ b/core/services/relay/evm/ocr3_capability_provider.go @@ -1,9 +1,23 @@ package evm import ( + "context" + "encoding/hex" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/ethereum/go-ethereum/crypto" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" ) type ocr3CapabilityProvider struct { @@ -14,3 +28,181 @@ type ocr3CapabilityProvider struct { func (o *ocr3CapabilityProvider) OCR3ContractTransmitter() ocr3types.ContractTransmitter[[]byte] { return o.transmitter } + +var _ LogDecoder = &ocr3CapabilityLogDecoder{} + +type ocr3CapabilityLogDecoder struct { + eventName string + eventSig common.Hash + abi *abi.ABI +} + +// Modified newOCR2AggregatorLogDecoder to use OCR3Capability ABI +func newOCR3CapabilityLogDecoder() (*ocr3CapabilityLogDecoder, error) { + const eventName = "ConfigSet" + abi, err := ocr3_capability.OCR3CapabilityMetaData.GetAbi() + if err != nil { + return nil, err + } + return &ocr3CapabilityLogDecoder{ + eventName: eventName, + eventSig: abi.Events[eventName].ID, + abi: abi, + }, nil +} + +func (d *ocr3CapabilityLogDecoder) Decode(rawLog []byte) (ocrtypes.ContractConfig, error) { + unpacked := new(ocr3_capability.OCR3CapabilityConfigSet) + err := d.abi.UnpackIntoInterface(unpacked, d.eventName, rawLog) + if err != nil { + return ocrtypes.ContractConfig{}, fmt.Errorf("failed to unpack log data: %w", err) + } + + var transmitAccounts []ocrtypes.Account + for _, addr := range unpacked.Transmitters { + transmitAccounts = append(transmitAccounts, ocrtypes.Account(addr.Hex())) + } + var signers []ocrtypes.OnchainPublicKey + allPubKeys := map[string]any{} + for _, pubKey := range unpacked.Signers { + pubKey := pubKey + + // validate uniqueness of each individual key + pubKeys, err := ocrcommon.UnmarshalMultichainPublicKey(pubKey) + if err != nil { + return ocrtypes.ContractConfig{}, err + } + for _, key := range pubKeys { + raw := hex.EncodeToString(key) + _, exists := allPubKeys[raw] + if exists { + return ocrtypes.ContractConfig{}, fmt.Errorf("Duplicate onchain public key: %v", raw) + } + allPubKeys[raw] = struct{}{} + } + + signers = append(signers, pubKey[:]) + } + + return ocrtypes.ContractConfig{ + ConfigDigest: unpacked.ConfigDigest, + ConfigCount: unpacked.ConfigCount, + Signers: signers, + Transmitters: transmitAccounts, + F: unpacked.F, + OnchainConfig: unpacked.OnchainConfig, + OffchainConfigVersion: unpacked.OffchainConfigVersion, + OffchainConfig: unpacked.OffchainConfig, + }, nil +} + +func (d *ocr3CapabilityLogDecoder) EventSig() common.Hash { + return d.eventSig +} + +var _ ocrtypes.OffchainConfigDigester = OCR3CapabilityOffchainConfigDigester{} + +// EVMOffchainConfigDigester forked to not assume signers are 20 byte addresses +type OCR3CapabilityOffchainConfigDigester struct { + ChainID uint64 + ContractAddress common.Address +} + +func (d OCR3CapabilityOffchainConfigDigester) ConfigDigest(ctx context.Context, cc ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { + signers := [][]byte{} + for _, signer := range cc.Signers { + signers = append(signers, signer) + } + transmitters := []common.Address{} + for i, transmitter := range cc.Transmitters { + if !strings.HasPrefix(string(transmitter), "0x") || len(transmitter) != 42 || !common.IsHexAddress(string(transmitter)) { + return ocrtypes.ConfigDigest{}, fmt.Errorf("%v-th evm transmitter should be a 42 character Ethereum address string, but got '%v'", i, transmitter) + } + a := common.HexToAddress(string(transmitter)) + transmitters = append(transmitters, a) + } + + return ocr3CapabilityConfigDigest( + d.ChainID, + d.ContractAddress, + cc.ConfigCount, + signers, + transmitters, + cc.F, + cc.OnchainConfig, + cc.OffchainConfigVersion, + cc.OffchainConfig, + ), nil +} + +const ConfigDigestPrefixKeystoneOCR3Capability ocrtypes.ConfigDigestPrefix = 0x000e + +func (d OCR3CapabilityOffchainConfigDigester) ConfigDigestPrefix(ctx context.Context) (ocrtypes.ConfigDigestPrefix, error) { + return ConfigDigestPrefixKeystoneOCR3Capability, nil +} + +func makeOCR3CapabilityConfigDigestArgs() 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: "chainId", Type: mustNewType("uint256")}, + {Name: "contractAddress", Type: mustNewType("address")}, + {Name: "configCount", Type: mustNewType("uint64")}, + {Name: "signers", Type: mustNewType("bytes[]")}, + {Name: "transmitters", Type: mustNewType("address[]")}, + {Name: "f", Type: mustNewType("uint8")}, + {Name: "onchainConfig", Type: mustNewType("bytes")}, + {Name: "encodedConfigVersion", Type: mustNewType("uint64")}, + {Name: "encodedConfig", Type: mustNewType("bytes")}, + }) +} + +var ocr3CapabilityConfigDigestArgs = makeOCR3CapabilityConfigDigestArgs() + +func ocr3CapabilityConfigDigest( + chainID uint64, + contractAddress common.Address, + configCount uint64, + oracles [][]byte, + transmitters []common.Address, + f uint8, + onchainConfig []byte, + offchainConfigVersion uint64, + offchainConfig []byte, +) ocrtypes.ConfigDigest { + chainIDBig := new(big.Int) + chainIDBig.SetUint64(chainID) + msg, err := ocr3CapabilityConfigDigestArgs.Pack( + chainIDBig, + contractAddress, + configCount, + oracles, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + ) + if err != nil { + // assertion + panic(err) + } + rawHash := crypto.Keccak256(msg) + configDigest := ocrtypes.ConfigDigest{} + if n := copy(configDigest[:], rawHash); n != len(configDigest) { + // assertion + panic("copy too little data") + } + if ConfigDigestPrefixKeystoneOCR3Capability != 0x000e { + // assertion + panic("wrong ConfigDigestPrefix") + } + configDigest[0] = 0 + configDigest[1] = 0x0e + return configDigest +} diff --git a/core/services/relay/evm/plugin_provider.go b/core/services/relay/evm/plugin_provider.go index ffcea48db2c..b8ce56ff12f 100644 --- a/core/services/relay/evm/plugin_provider.go +++ b/core/services/relay/evm/plugin_provider.go @@ -5,17 +5,16 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/logger" ) type pluginProvider struct { services.Service - chainReader types.ContractReader + chainReader ChainReaderService codec types.Codec - contractTransmitter ocrtypes.ContractTransmitter + contractTransmitter ContractTransmitter configWatcher *configWatcher lggr logger.Logger ms services.MultiStart @@ -24,9 +23,9 @@ type pluginProvider struct { var _ types.PluginProvider = (*pluginProvider)(nil) func NewPluginProvider( - chainReader types.ContractReader, + chainReader ChainReaderService, codec types.Codec, - contractTransmitter ocrtypes.ContractTransmitter, + contractTransmitter ContractTransmitter, configWatcher *configWatcher, lggr logger.Logger, ) *pluginProvider { @@ -47,6 +46,10 @@ func (p *pluginProvider) Ready() error { return nil } func (p *pluginProvider) HealthReport() map[string]error { hp := map[string]error{p.Name(): p.Ready()} services.CopyHealth(hp, p.configWatcher.HealthReport()) + services.CopyHealth(hp, p.contractTransmitter.HealthReport()) + if p.chainReader != nil { + services.CopyHealth(hp, p.chainReader.HealthReport()) + } return hp } @@ -62,7 +65,7 @@ func (p *pluginProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker return p.configWatcher.configPoller } -func (p *pluginProvider) ChainReader() types.ContractReader { +func (p *pluginProvider) ContractReader() types.ContractReader { return p.chainReader } @@ -71,9 +74,14 @@ func (p *pluginProvider) Codec() types.Codec { } func (p *pluginProvider) Start(ctx context.Context) error { - return p.configWatcher.Start(ctx) + srvcs := []services.StartClose{p.configWatcher, p.contractTransmitter} + if p.chainReader != nil { + srvcs = append(srvcs, p.chainReader) + } + + return p.ms.Start(ctx, srvcs...) } func (p *pluginProvider) Close() error { - return p.configWatcher.Close() + return p.ms.Close() } diff --git a/core/services/relay/evm/batch_caller.go b/core/services/relay/evm/read/batch.go similarity index 65% rename from core/services/relay/evm/batch_caller.go rename to core/services/relay/evm/read/batch.go index 3ee4525827a..dbe8c8be549 100644 --- a/core/services/relay/evm/batch_caller.go +++ b/core/services/relay/evm/read/batch.go @@ -1,19 +1,21 @@ -package evm +package read import ( "context" + "errors" "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - "github.com/pkg/errors" "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) var errEmptyOutput = errors.New("rpc call output is empty (make sure that the contract method exists and rpc is healthy)") @@ -37,6 +39,7 @@ const ( type BatchResult map[string]ContractResults type ContractResults []MethodCallResult type MethodCallResult struct { + Address string MethodName string ReturnValue any Err error @@ -44,9 +47,9 @@ type MethodCallResult struct { type BatchCall []Call type Call struct { - ContractAddress common.Address - ContractName, MethodName string - Params, ReturnVal any + ContractAddress common.Address + ContractName, ReadName string + Params, ReturnVal any } func (c BatchCall) String() string { @@ -60,7 +63,7 @@ func (c BatchCall) String() string { // Implement the String method for the Call struct func (c Call) String() string { return fmt.Sprintf("contractAddress: %s, contractName: %s, method: %s, params: %+v returnValType: %T", - c.ContractAddress.Hex(), c.ContractName, c.MethodName, c.Params, c.ReturnVal) + c.ContractAddress.Hex(), c.ContractName, c.ReadName, c.Params, c.ReturnVal) } type BatchCaller interface { @@ -124,75 +127,149 @@ func newDefaultEvmBatchCaller( } } +// batchCall formats a batch, calls the rpc client, and unpacks results. +// this function only returns errors of type ErrRead which should wrap lower errors. func (c *defaultEvmBatchCaller) batchCall(ctx context.Context, blockNumber uint64, batchCall BatchCall) ([]dataAndErr, error) { if len(batchCall) == 0 { return nil, nil } - packedOutputs := make([]string, len(batchCall)) - rpcBatchCalls := make([]rpc.BatchElem, len(batchCall)) - for i, call := range batchCall { - data, err := c.codec.Encode(ctx, call.Params, WrapItemType(call.ContractName, call.MethodName, true)) - if err != nil { - return nil, err + blockNumStr := "latest" + if blockNumber > 0 { + blockNumStr = hexutil.EncodeBig(big.NewInt(0).SetUint64(blockNumber)) + } + + rpcBatchCalls, hexEncodedOutputs, err := c.createBatchCalls(ctx, batchCall, blockNumStr) + if err != nil { + return nil, err + } + + if err = c.evmClient.BatchCallContext(ctx, rpcBatchCalls); err != nil { + // return a basic read error with no detail or result since this is a general client + // error instead of an error for a specific batch call. + return nil, ErrRead{ + Err: fmt.Errorf("%w: batch call context: %s", types.ErrInternal, err.Error()), + Batch: true, } + } + + results, err := c.unpackBatchResults(ctx, batchCall, rpcBatchCalls, hexEncodedOutputs, blockNumStr) + if err != nil { + return nil, err + } + + return results, nil +} + +func (c *defaultEvmBatchCaller) createBatchCalls( + ctx context.Context, + batchCall BatchCall, + block string, +) ([]rpc.BatchElem, []string, error) { + rpcBatchCalls := make([]rpc.BatchElem, len(batchCall)) + hexEncodedOutputs := make([]string, len(batchCall)) - blockNumStr := "latest" - if blockNumber > 0 { - blockNumStr = hexutil.EncodeBig(big.NewInt(0).SetUint64(blockNumber)) + for idx, call := range batchCall { + data, err := c.codec.Encode(ctx, call.Params, codec.WrapItemType(call.ContractName, call.ReadName, true)) + if err != nil { + return nil, nil, newErrorFromCall( + fmt.Errorf("%w: encode params: %s", types.ErrInvalidConfig, err.Error()), + call, + block, + true, + ) } - rpcBatchCalls[i] = rpc.BatchElem{ + rpcBatchCalls[idx] = rpc.BatchElem{ Method: "eth_call", Args: []any{ map[string]interface{}{ "from": common.Address{}, "to": call.ContractAddress, - "data": data, + "data": hexutil.Bytes(data), }, - blockNumStr, + block, }, - Result: &packedOutputs[i], + Result: &hexEncodedOutputs[idx], } } - if err := c.evmClient.BatchCallContext(ctx, rpcBatchCalls); err != nil { - return nil, fmt.Errorf("batch call context: %w", err) - } + return rpcBatchCalls, hexEncodedOutputs, nil +} +func (c *defaultEvmBatchCaller) unpackBatchResults( + ctx context.Context, + batchCall BatchCall, + rpcBatchCalls []rpc.BatchElem, + hexEncodedOutputs []string, + block string, +) ([]dataAndErr, error) { results := make([]dataAndErr, len(batchCall)) - for i, call := range batchCall { - results[i] = dataAndErr{ + + for idx, call := range batchCall { + results[idx] = dataAndErr{ + address: call.ContractAddress.Hex(), contractName: call.ContractName, - methodName: call.MethodName, + methodName: call.ReadName, returnVal: call.ReturnVal, } - if rpcBatchCalls[i].Error != nil { - results[i].err = rpcBatchCalls[i].Error + if rpcBatchCalls[idx].Error != nil { + results[idx].err = newErrorFromCall( + fmt.Errorf("%w: rpc call error: %w", types.ErrInternal, rpcBatchCalls[idx].Error), + call, block, true, + ) + continue } - if packedOutputs[i] == "" { + if hexEncodedOutputs[idx] == "" { // Some RPCs instead of returning "0x" are returning an empty string. // We are overriding this behaviour for consistent handling of this scenario. - packedOutputs[i] = "0x" + hexEncodedOutputs[idx] = "0x" } - b, err := hexutil.Decode(packedOutputs[i]) + packedBytes, err := hexutil.Decode(hexEncodedOutputs[idx]) if err != nil { - return nil, fmt.Errorf("decode result %s: packedOutputs %s: %w", call, packedOutputs[i], err) + callErr := newErrorFromCall( + fmt.Errorf("%w: hex decode result: %s", types.ErrInternal, err.Error()), + call, block, true, + ) + + callErr.Result = &hexEncodedOutputs[idx] + + return nil, callErr } - if err = c.codec.Decode(ctx, b, call.ReturnVal, WrapItemType(call.ContractName, call.MethodName, false)); err != nil { - if len(b) == 0 { - results[i].err = fmt.Errorf("unpack result %s: %s: %w", call, err.Error(), errEmptyOutput) + if err = c.codec.Decode( + ctx, + packedBytes, + call.ReturnVal, + codec.WrapItemType(call.ContractName, call.ReadName, false), + ); err != nil { + if len(packedBytes) == 0 { + callErr := newErrorFromCall( + fmt.Errorf("%w: %w: %s", types.ErrInternal, errEmptyOutput, err.Error()), + call, block, true, + ) + + callErr.Result = &hexEncodedOutputs[idx] + + results[idx].err = callErr } else { - results[i].err = fmt.Errorf("unpack result %s: %w", call, err) + callErr := newErrorFromCall( + fmt.Errorf("%w: codec decode result: %s", types.ErrInvalidType, err.Error()), + call, block, true, + ) + + callErr.Result = &hexEncodedOutputs[idx] + results[idx].err = callErr } + continue } - results[i].returnVal = call.ReturnVal + + results[idx].returnVal = call.ReturnVal } return results, nil @@ -200,10 +277,12 @@ func (c *defaultEvmBatchCaller) batchCall(ctx context.Context, blockNumber uint6 func (c *defaultEvmBatchCaller) batchCallDynamicLimitRetries(ctx context.Context, blockNumber uint64, calls BatchCall) (BatchResult, error) { lim := c.batchSizeLimit + // Limit the batch size to the number of calls if uint(len(calls)) < lim { lim = uint(len(calls)) } + for { results, err := c.batchCallLimit(ctx, blockNumber, calls, lim) if err == nil { @@ -211,20 +290,25 @@ func (c *defaultEvmBatchCaller) batchCallDynamicLimitRetries(ctx context.Context } if lim <= 1 { - return nil, errors.Wrapf(err, "calls %+v", calls) + return nil, ErrRead{ + Err: fmt.Errorf("%w: limited call: call data: %+v", err, calls), + Batch: true, + } } newLim := lim / c.backOffMultiplier if newLim == 0 || newLim == lim { newLim = 1 } + lim = newLim - c.lggr.Errorf("retrying batch call with %d calls and %d limit that failed with error=%s", - len(calls), lim, err) + + c.lggr.Debugf("retrying batch call with %d calls and %d limit that failed with error=%s", len(calls), lim, err) } } type dataAndErr struct { + address string contractName, methodName string returnVal any err error @@ -233,6 +317,7 @@ type dataAndErr struct { func (c *defaultEvmBatchCaller) batchCallLimit(ctx context.Context, blockNumber uint64, calls BatchCall, batchSizeLimit uint) (BatchResult, error) { if batchSizeLimit <= 0 { res, err := c.batchCall(ctx, blockNumber, calls) + return convertToBatchResult(res), err } @@ -245,32 +330,40 @@ func (c *defaultEvmBatchCaller) batchCallLimit(ctx context.Context, blockNumber jobs := make([]job, 0) for i := 0; i < len(calls); i += int(batchSizeLimit) { idxFrom := i + idxTo := idxFrom + int(batchSizeLimit) if idxTo > len(calls) { idxTo = len(calls) } + jobs = append(jobs, job{blockNumber: blockNumber, calls: calls[idxFrom:idxTo], results: nil}) } if c.parallelRpcCallsLimit > 1 { eg := new(errgroup.Group) eg.SetLimit(int(c.parallelRpcCallsLimit)) + for jobIdx := range jobs { jobIdx := jobIdx + eg.Go(func() error { res, err := c.batchCall(ctx, jobs[jobIdx].blockNumber, jobs[jobIdx].calls) if err != nil { return err } + jobs[jobIdx].results = res + return nil }) } + if err := eg.Wait(); err != nil { return nil, err } } else { var err error + for jobIdx := range jobs { jobs[jobIdx].results, err = c.batchCall(ctx, jobs[jobIdx].blockNumber, jobs[jobIdx].calls) if err != nil { @@ -295,6 +388,7 @@ func convertToBatchResult(data []dataAndErr) BatchResult { batchResult := make(BatchResult) for _, d := range data { methodCall := MethodCallResult{ + Address: d.address, MethodName: d.methodName, ReturnValue: d.returnVal, Err: d.err, diff --git a/core/services/relay/evm/batch_caller_test.go b/core/services/relay/evm/read/batch_caller_test.go similarity index 85% rename from core/services/relay/evm/batch_caller_test.go rename to core/services/relay/evm/read/batch_caller_test.go index 995e47618cc..e84452416b7 100644 --- a/core/services/relay/evm/batch_caller_test.go +++ b/core/services/relay/evm/read/batch_caller_test.go @@ -1,12 +1,12 @@ -package evm_test +package read_test import ( - "encoding/hex" "fmt" "math/big" "testing" "github.com/cometbft/cometbft/libs/rand" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -16,8 +16,9 @@ import ( chainmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -31,8 +32,8 @@ func TestDefaultEvmBatchCaller_BatchCallDynamicLimit(t *testing.T) { }{ { name: "defaults", - maxBatchSize: evm.DefaultRpcBatchSizeLimit, - backOffMultiplier: evm.DefaultRpcBatchBackOffMultiplier, + maxBatchSize: read.DefaultRpcBatchSizeLimit, + backOffMultiplier: read.DefaultRpcBatchBackOffMultiplier, numCalls: 200, expectedBatchSizesOnEachRetry: []int{100, 20, 4, 1}, }, @@ -92,12 +93,12 @@ func TestDefaultEvmBatchCaller_BatchCallDynamicLimit(t *testing.T) { batchSizes = append(batchSizes, len(evmCalls)) }).Return(errors.New("some error")) - calls := make(evm.BatchCall, tc.numCalls) + calls := make(read.BatchCall, tc.numCalls) for i := range calls { - calls[i] = evm.Call{} + calls[i] = read.Call{} } - bc := evm.NewDynamicLimitedBatchCaller(logger.TestLogger(t), mockCodec, ec, tc.maxBatchSize, tc.backOffMultiplier, 1) + bc := read.NewDynamicLimitedBatchCaller(logger.TestLogger(t), mockCodec, ec, tc.maxBatchSize, tc.backOffMultiplier, 1) _, _ = bc.BatchCall(testutils.Context(t), 123, calls) assert.Equal(t, tc.expectedBatchSizesOnEachRetry, batchSizes) }) @@ -131,7 +132,7 @@ func TestDefaultEvmBatchCaller_batchCallLimit(t *testing.T) { for i, tc := range testCases { t.Run(fmt.Sprintf("%v", tc), func(t *testing.T) { ec := chainmocks.NewClient(t) - calls := make(evm.BatchCall, tc.numCalls) + calls := make(read.BatchCall, tc.numCalls) for j := range calls { contractName := fmt.Sprintf("testCase_%d", i) methodName := fmt.Sprintf("method_%d", j) @@ -140,9 +141,9 @@ func TestDefaultEvmBatchCaller_batchCallLimit(t *testing.T) { params := MethodParam{A: uint64(j)} var returnVal MethodReturn - calls[j] = evm.Call{ + calls[j] = read.Call{ ContractName: contractName, - MethodName: methodName, + ReadName: methodName, Params: ¶ms, ReturnVal: &returnVal, } @@ -152,18 +153,16 @@ func TestDefaultEvmBatchCaller_batchCallLimit(t *testing.T) { Run(func(args mock.Arguments) { evmCalls := args.Get(1).([]rpc.BatchElem) for i := range evmCalls { - arg := evmCalls[i].Args[0].(map[string]interface{})["data"].([]uint8) - bytes, err := hex.DecodeString(fmt.Sprintf("%x", arg)) - require.NoError(t, err) + arg := evmCalls[i].Args[0].(map[string]interface{})["data"].(hexutil.Bytes) str, isOk := evmCalls[i].Result.(*string) require.True(t, isOk) - *str = fmt.Sprintf("0x%064x", new(big.Int).SetBytes(bytes[24:]).Uint64()) + *str = fmt.Sprintf("0x%064x", new(big.Int).SetBytes(arg[24:]).Uint64()) } }).Return(nil) - testCodec, err := evm.NewCodec(codecConfig) + testCodec, err := codec.NewCodec(codecConfig) require.NoError(t, err) - bc := evm.NewDynamicLimitedBatchCaller(logger.TestLogger(t), testCodec, ec, tc.batchSize, 99999, tc.parallelRpcCallsLimit) + bc := read.NewDynamicLimitedBatchCaller(logger.TestLogger(t), testCodec, ec, tc.batchSize, 99999, tc.parallelRpcCallsLimit) // make the call and make sure the results are there results, err := bc.BatchCall(ctx, 0, calls) @@ -175,7 +174,7 @@ func TestDefaultEvmBatchCaller_batchCallLimit(t *testing.T) { } hasResult := false for j, result := range contractResults { - if hasResult = result.MethodName == call.MethodName; hasResult { + if hasResult = result.MethodName == call.ReadName; hasResult { require.NoError(t, result.Err) resNum, isOk := result.ReturnValue.(*MethodReturn) require.True(t, isOk) @@ -184,7 +183,7 @@ func TestDefaultEvmBatchCaller_batchCallLimit(t *testing.T) { } } if !hasResult { - t.Errorf("missing method name %s", call.MethodName) + t.Errorf("missing method name %s", call.ReadName) } } }) diff --git a/core/services/relay/evm/read/bindings.go b/core/services/relay/evm/read/bindings.go new file mode 100644 index 00000000000..bfeb84a3799 --- /dev/null +++ b/core/services/relay/evm/read/bindings.go @@ -0,0 +1,301 @@ +package read + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/common" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type Reader interface { + BatchCall(address common.Address, params, retVal any) (Call, error) + GetLatestValue(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params, returnVal any) error + QueryKey(context.Context, common.Address, query.KeyFilter, query.LimitAndSort, any) ([]commontypes.Sequence, error) + + Bind(context.Context, ...common.Address) error + Unbind(context.Context, ...common.Address) error + SetCodec(commontypes.RemoteCodec) + + Register(context.Context) error + Unregister(context.Context) error +} + +type BindingsRegistry struct { + // dependencies + batch BatchCaller + + // private state + mu sync.RWMutex + contractBindings map[string]*contractBinding + contractLookup *lookup +} + +func NewBindingsRegistry() *BindingsRegistry { + return &BindingsRegistry{ + contractBindings: make(map[string]*contractBinding), + contractLookup: newLookup(), + } +} + +func (b *BindingsRegistry) SetBatchCaller(caller BatchCaller) { + b.mu.Lock() + defer b.mu.Unlock() + + b.batch = caller +} + +func (b *BindingsRegistry) HasContractBinding(contractName string) bool { + b.mu.RLock() + defer b.mu.RUnlock() + + _, ok := b.contractBindings[contractName] + + return ok +} + +// GetReader should only be called after Chain Reader is started. +func (b *BindingsRegistry) GetReader(readIdentifier string) (Reader, string, error) { + b.mu.RLock() + defer b.mu.RUnlock() + + values, ok := b.contractLookup.getContractForReadName(readIdentifier) + if !ok { + return nil, "", fmt.Errorf("%w: %w", commontypes.ErrInvalidType, newMissingReadIdentifierErr(readIdentifier)) + } + + cb, cbExists := b.contractBindings[values.contract] + if !cbExists { + return nil, "", fmt.Errorf("%w: %w", commontypes.ErrInvalidType, newMissingContractErr(readIdentifier, values.contract)) + } + + binding, rbExists := cb.GetReaderNamed(values.readName) + if !rbExists { + return nil, "", fmt.Errorf("%w: %w", commontypes.ErrInvalidType, newMissingReadNameErr(readIdentifier, values.contract, values.readName)) + } + + return binding, values.address, nil +} + +func (b *BindingsRegistry) AddReader(contractName, readName string, rdr Reader) error { + b.mu.Lock() + defer b.mu.Unlock() + + if binding, ok := rdr.(*EventBinding); ok { + // unwrap codec type naming for event data words and topics to be used by lookup for Querying by Value Comparators + // For e.g. "params.contractName.eventName.IndexedTopic" -> "eventName.IndexedTopic" + // or "params.contractName.eventName.someFieldInData" -> "eventName.someFieldInData" + for name := range binding.eventTypes { + split := strings.Split(name, ".") + if len(split) < 3 || split[1] != contractName { + return fmt.Errorf("%w: invalid event type name %s", commontypes.ErrInvalidType, name) + } + + b.contractLookup.addReadNameForContract(contractName, strings.Join(split[2:], ".")) + } + } + + b.contractLookup.addReadNameForContract(contractName, readName) + + cb, cbExists := b.contractBindings[contractName] + if !cbExists { + cb = newContractBinding(contractName) + b.contractBindings[contractName] = cb + } + + cb.AddReaderNamed(readName, rdr) + + return nil +} + +// Bind binds contract addresses to contract bindings and read bindings. +// Bind also registers the common contract polling filter and eventBindings polling filters. +func (b *BindingsRegistry) Bind(ctx context.Context, reg Registrar, bindings []commontypes.BoundContract) error { + b.mu.RLock() + defer b.mu.RUnlock() + + for _, binding := range bindings { + contract, exists := b.contractBindings[binding.Name] + if !exists { + return fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newMissingContractErr("binding contract", binding.Name)) + } + + b.contractLookup.bindAddressForContract(binding.Name, binding.Address) + + if err := errors.Join( + contract.Bind(ctx, reg, common.HexToAddress(binding.Address)), + contract.BindReaders(ctx, common.HexToAddress(binding.Address)), + ); err != nil { + return err + } + } + + return nil +} + +func (b *BindingsRegistry) BatchGetLatestValues(ctx context.Context, request commontypes.BatchGetLatestValuesRequest) (commontypes.BatchGetLatestValuesResult, error) { + b.mu.RLock() + defer b.mu.RUnlock() + + var batchCall BatchCall + + for binding, contractBatch := range request { + cb := b.contractBindings[binding.Name] + + for idx := range contractBatch { + req := contractBatch[idx] + + values, ok := b.contractLookup.getContractForReadName(binding.ReadIdentifier(req.ReadName)) + if !ok { + return nil, fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newMissingReadNameErr(binding.ReadIdentifier(req.ReadName), binding.Name, req.ReadName)) + } + + rdr, exists := cb.GetReaderNamed(values.readName) + if !exists { + return nil, fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newMissingReadNameErr(binding.ReadIdentifier(req.ReadName), binding.Name, req.ReadName)) + } + + call, err := rdr.BatchCall(common.HexToAddress(values.address), req.Params, req.ReturnVal) + if err != nil { + return nil, err + } + + batchCall = append(batchCall, call) + } + } + + results, err := b.batch.BatchCall(ctx, 0, batchCall) + if err != nil { + return nil, err + } + + // reconstruct results from batchCall and filteredLogs into common type while maintaining order from request. + batchGetLatestValuesResults := make(commontypes.BatchGetLatestValuesResult) + for contractName, contractResult := range results { + for _, methodResult := range contractResult { + binding := commontypes.BoundContract{ + Name: contractName, + Address: methodResult.Address, + } + + brr := commontypes.BatchReadResult{ + ReadName: methodResult.MethodName, + } + + brr.SetResult(methodResult.ReturnValue, methodResult.Err) + + if _, ok := batchGetLatestValuesResults[binding]; !ok { + batchGetLatestValuesResults[binding] = make(commontypes.ContractBatchResults, 0) + } + + batchGetLatestValuesResults[binding] = append(batchGetLatestValuesResults[binding], brr) + } + } + + return batchGetLatestValuesResults, err +} + +// Unbind unbinds contract addresses to contract bindings and read bindings. +func (b *BindingsRegistry) Unbind(ctx context.Context, reg Registrar, bindings []commontypes.BoundContract) error { + b.mu.RLock() + defer b.mu.RUnlock() + + for _, binding := range bindings { + contract, exists := b.contractBindings[binding.Name] + if !exists { + return newMissingContractErr("unbinding contract", binding.Name) + } + + b.contractLookup.unbindAddressForContract(binding.Name, binding.Address) + + if err := errors.Join( + contract.Unbind(ctx, reg, common.HexToAddress(binding.Address)), + contract.UnbindReaders(ctx, common.HexToAddress(binding.Address)), + ); err != nil { + return err + } + } + + return nil +} + +func (b *BindingsRegistry) RegisterAll(ctx context.Context, reg Registrar) error { + b.mu.RLock() + defer b.mu.RUnlock() + + for _, cb := range b.contractBindings { + if err := errors.Join(cb.RegisterReaders(ctx), cb.Register(ctx, reg)); err != nil { + return err + } + } + + return nil +} + +func (b *BindingsRegistry) UnregisterAll(ctx context.Context, reg Registrar) error { + b.mu.RLock() + defer b.mu.RUnlock() + + for _, cb := range b.contractBindings { + if err := errors.Join(cb.UnregisterReaders(ctx), cb.Unregister(ctx, reg)); err != nil { + return err + } + } + + return nil +} + +func (b *BindingsRegistry) SetCodecAll(codec commontypes.RemoteCodec) { + b.mu.RLock() + defer b.mu.RUnlock() + + for _, cb := range b.contractBindings { + cb.SetCodecAll(codec) + } +} + +func (b *BindingsRegistry) SetFilter(name string, filter logpoller.Filter) error { + b.mu.RLock() + defer b.mu.RUnlock() + + contract, ok := b.contractBindings[name] + if !ok { + return fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newMissingContractErr("set filter", name)) + } + + contract.SetFilter(filter) + + return nil +} + +func (b *BindingsRegistry) ReadTypeIdentifier(readName string, forEncoding bool) string { + values, ok := b.contractLookup.getContractForReadName(readName) + if !ok { + return "" + } + + return codec.WrapItemType(values.contract, values.readName, forEncoding) +} + +// confidenceToConfirmations matches predefined chain agnostic confidence levels to predefined EVM finality. +func confidenceToConfirmations( + confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations, + confidenceLevel primitives.ConfidenceLevel, +) (evmtypes.Confirmations, error) { + confirmations, exists := confirmationsMapping[confidenceLevel] + if !exists { + return 0, fmt.Errorf("%w: missing mapping for confidence level: %s", commontypes.ErrInvalidConfig, confidenceLevel) + } + + return confirmations, nil +} diff --git a/core/services/relay/evm/read/bindings_test.go b/core/services/relay/evm/read/bindings_test.go new file mode 100644 index 00000000000..d9cfa91a987 --- /dev/null +++ b/core/services/relay/evm/read/bindings_test.go @@ -0,0 +1,112 @@ +package read_test + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read/mocks" +) + +var ( + contractName1 = "Contract1" + methodName1 = "Method1" + methodName2 = "Method2" + eventName0 = "EventName0" + filterWithSigs = logpoller.Filter{ + Name: eventName0, + EventSigs: []common.Hash{common.HexToHash("0x25"), common.HexToHash("0x29")}, + } +) + +func TestBindingsRegistry(t *testing.T) { + t.Parallel() + + t.Run("readers are addable, bindable, and retrievable", func(t *testing.T) { + t.Parallel() + + mBatch := new(mocks.BatchCaller) + mRdr := new(mocks.Reader) + mReg := new(mocks.Registrar) + + mRdr.EXPECT().Bind(mock.Anything, mock.Anything).Return(nil) + + named := read.NewBindingsRegistry() + named.SetBatchCaller(mBatch) + + require.NoError(t, named.AddReader(contractName1, methodName1, mRdr)) + + bindings := []commontypes.BoundContract{{Address: "0x24", Name: contractName1}} + _ = named.Bind(context.Background(), mReg, bindings) + + rdr, _, err := named.GetReader(bindings[0].ReadIdentifier(methodName1)) + + require.NoError(t, err) + require.NotNil(t, rdr) + }) + + t.Run("register all before bind", func(t *testing.T) { + t.Parallel() + + mBatch := new(mocks.BatchCaller) + mRdr0 := new(mocks.Reader) + mRdr1 := new(mocks.Reader) + mReg := new(mocks.Registrar) + + named := read.NewBindingsRegistry() + named.SetBatchCaller(mBatch) + + // register is called once through RegisterAll and again in Bind + mRdr0.EXPECT().Register(mock.Anything).Return(nil) + mRdr1.EXPECT().Register(mock.Anything).Return(nil) + + mRdr0.EXPECT().Bind(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + mRdr1.EXPECT().Bind(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + + mReg.EXPECT().HasFilter(mock.Anything).Return(false) + mReg.EXPECT().RegisterFilter(mock.Anything, mock.Anything).Return(nil) + mRdr0.EXPECT().GetLatestValue(mock.Anything, common.HexToAddress("0x25"), mock.Anything, mock.Anything, mock.Anything).Return(nil) + mRdr0.EXPECT().GetLatestValue(mock.Anything, common.HexToAddress("0x24"), mock.Anything, mock.Anything, mock.Anything).Return(nil) + mRdr1.EXPECT().GetLatestValue(mock.Anything, common.HexToAddress("0x26"), mock.Anything, mock.Anything, mock.Anything).Return(nil) + + // part of the init phase of chain reader + require.NoError(t, named.AddReader(contractName1, methodName1, mRdr0)) + require.NoError(t, named.AddReader(contractName1, methodName2, mRdr1)) + _ = named.SetFilter(contractName1, filterWithSigs) + + // run within the start phase of chain reader + require.NoError(t, named.RegisterAll(context.Background(), mReg)) + + bindings := []commontypes.BoundContract{ + {Address: "0x24", Name: contractName1}, + {Address: "0x25", Name: contractName1}, + {Address: "0x26", Name: contractName1}, + } + + // calling bind will also call register for each reader + _ = named.Bind(context.Background(), mReg, bindings) + + rdr1, _, err := named.GetReader(bindings[0].ReadIdentifier(methodName1)) + require.NoError(t, err) + + rdr2, _, err := named.GetReader(bindings[0].ReadIdentifier(methodName2)) + require.NoError(t, err) + + require.NoError(t, rdr1.GetLatestValue(context.Background(), common.HexToAddress("0x25"), primitives.Finalized, nil, nil)) + require.NoError(t, rdr1.GetLatestValue(context.Background(), common.HexToAddress("0x24"), primitives.Finalized, nil, nil)) + require.NoError(t, rdr2.GetLatestValue(context.Background(), common.HexToAddress("0x26"), primitives.Finalized, nil, nil)) + + mBatch.AssertExpectations(t) + mRdr0.AssertExpectations(t) + mRdr1.AssertExpectations(t) + mReg.AssertExpectations(t) + }) +} diff --git a/core/services/relay/evm/read/contract.go b/core/services/relay/evm/read/contract.go new file mode 100644 index 00000000000..c8770b93600 --- /dev/null +++ b/core/services/relay/evm/read/contract.go @@ -0,0 +1,243 @@ +package read + +import ( + "context" + "errors" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +// contractBinding stores read bindings and manages the common contract event filter. +type contractBinding struct { + // filterRegistrar is used to manage polling filter registration for the common contract filter. + // The common contract filter should be used by events that share filtering args. + registrar *syncedFilter + + // registered is used to determine if Register was called during Chain Reader service Start. + // This is done to avoid calling Register while the service is not running because log poller is most likely also not running. + registerCalled bool + + // internal properties + name string + readers map[string]Reader // key is read name method, event or event keys used for queryKey. + bound map[common.Address]bool // bound determines if address is set to the contract binding. + mu sync.RWMutex +} + +func newContractBinding(name string) *contractBinding { + return &contractBinding{ + name: name, + readers: make(map[string]Reader), + bound: make(map[common.Address]bool), + registrar: newSyncedFilter(), + } +} + +// GetReaderNamed returns a reader for the provided read name. This method is thread safe. +func (cb *contractBinding) GetReaderNamed(readName string) (Reader, bool) { + cb.mu.RLock() + defer cb.mu.RUnlock() + + binding, exists := cb.readers[readName] + + return binding, exists +} + +// AddReaderNamed adds a new reader to the contract bindings for the provided contract name. This +// method is thread safe. +func (cb *contractBinding) AddReaderNamed(name string, rdr Reader) { + cb.mu.Lock() + defer cb.mu.Unlock() + + cb.readers[name] = rdr +} + +// Bind binds contract addresses to contract binding and registers the common contract polling filter. +func (cb *contractBinding) Bind(ctx context.Context, registrar Registrar, bindings ...common.Address) error { + if cb.isBound() { + if err := cb.Unregister(ctx, registrar); err != nil { + return err + } + } + + for _, binding := range bindings { + if cb.bindingExists(binding) { + continue + } + + cb.registrar.SetName(logpoller.FilterName(cb.name + "." + uuid.NewString())) + cb.registrar.AddAddress(binding) + cb.addBinding(binding) + } + + // registerCalled during ChainReader start + if cb.registered() { + return cb.Register(ctx, registrar) + } + + return nil +} + +func (cb *contractBinding) BindReaders(ctx context.Context, addresses ...common.Address) error { + cb.mu.RLock() + defer cb.mu.RUnlock() + + var err error + + for _, reader := range cb.readers { + err = errors.Join(err, reader.Bind(ctx, addresses...)) + } + + return err +} + +// Unbind unbinds contract addresses from contract binding and unregisters the common contract polling filter. +func (cb *contractBinding) Unbind(ctx context.Context, registrar Registrar, bindings ...common.Address) error { + for _, binding := range bindings { + if !cb.bindingExists(binding) { + continue + } + + cb.registrar.RemoveAddress(binding) + cb.removeBinding(binding) + } + + // we are changing contract address reference, so we need to unregister old filter or re-register existing filter + if cb.registrar.Count() == 0 { + cb.registrar.SetName("") + + return cb.Unregister(ctx, registrar) + } else if cb.registered() { + return cb.Register(ctx, registrar) + } + + return nil +} + +func (cb *contractBinding) UnbindReaders(ctx context.Context, addresses ...common.Address) error { + cb.mu.RLock() + defer cb.mu.RUnlock() + + var err error + + for _, reader := range cb.readers { + err = errors.Join(reader.Unbind(ctx, addresses...)) + } + + return err +} + +func (cb *contractBinding) SetCodecAll(codec commontypes.RemoteCodec) { + cb.mu.RLock() + defer cb.mu.RUnlock() + + for _, binding := range cb.readers { + binding.SetCodec(codec) + } +} + +// Register registers the common contract filter. +func (cb *contractBinding) Register(ctx context.Context, registrar Registrar) error { + cb.setRegistered() + + if !cb.isBound() { + return nil + } + + if cb.registrar.HasEventSigs() { + if err := cb.registrar.Register(ctx, registrar); err != nil { + return err + } + } + + return nil +} + +func (cb *contractBinding) RegisterReaders(ctx context.Context) error { + cb.mu.RLock() + defer cb.mu.RUnlock() + + for _, binding := range cb.readers { + if err := binding.Register(ctx); err != nil { + return err + } + } + + return nil +} + +// Unregister unregisters the common contract filter. +func (cb *contractBinding) Unregister(ctx context.Context, registrar Registrar) error { + if !cb.isBound() { + return nil + } + + return cb.registrar.Unregister(ctx, registrar) +} + +func (cb *contractBinding) UnregisterReaders(ctx context.Context) error { + cb.mu.RLock() + defer cb.mu.RUnlock() + + for _, binding := range cb.readers { + if err := binding.Unregister(ctx); err != nil { + return err + } + } + + return nil +} + +func (cb *contractBinding) SetFilter(filter logpoller.Filter) { + cb.registrar.SetFilter(filter) +} + +func (cb *contractBinding) isBound() bool { + cb.mu.RLock() + defer cb.mu.RUnlock() + + return len(cb.bound) > 0 +} + +func (cb *contractBinding) bindingExists(binding common.Address) bool { + cb.mu.RLock() + defer cb.mu.RUnlock() + + bound, exists := cb.bound[binding] + + return exists && bound +} + +func (cb *contractBinding) addBinding(binding common.Address) { + cb.mu.Lock() + defer cb.mu.Unlock() + + cb.bound[binding] = true +} + +func (cb *contractBinding) removeBinding(binding common.Address) { + cb.mu.Lock() + defer cb.mu.Unlock() + + delete(cb.bound, binding) +} + +func (cb *contractBinding) registered() bool { + cb.mu.RLock() + defer cb.mu.RUnlock() + + return cb.registerCalled +} + +func (cb *contractBinding) setRegistered() { + cb.mu.Lock() + defer cb.mu.Unlock() + + cb.registerCalled = true +} diff --git a/core/services/relay/evm/read/errors.go b/core/services/relay/evm/read/errors.go new file mode 100644 index 00000000000..bec14d7dd4b --- /dev/null +++ b/core/services/relay/evm/read/errors.go @@ -0,0 +1,127 @@ +package read + +import ( + "fmt" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +type ErrRead struct { + Err error + Batch bool + Detail *readDetail + Result *string +} + +type readDetail struct { + Address string + Contract string + Method string + Params, RetVal any + Block string +} + +func newErrorFromCall(err error, call Call, block string, batch bool) ErrRead { + return ErrRead{ + Err: err, + Batch: batch, + Detail: &readDetail{ + Address: call.ContractAddress.Hex(), + Contract: call.ContractName, + Method: call.ReadName, + Params: call.Params, + RetVal: call.ReturnVal, + Block: block, + }, + } +} + +func (e ErrRead) Error() string { + var builder strings.Builder + + builder.WriteString("[rpc error]") + builder.WriteString(fmt.Sprintf(" batch: %T;", e.Batch)) + builder.WriteString(fmt.Sprintf(" err: %s;", e.Err.Error())) + + if e.Detail != nil { + builder.WriteString(fmt.Sprintf(" block: %s;", e.Detail.Block)) + builder.WriteString(fmt.Sprintf(" address: %s;", e.Detail.Address)) + builder.WriteString(fmt.Sprintf(" contract-name: %s;", e.Detail.Contract)) + builder.WriteString(fmt.Sprintf(" read-name: %s;", e.Detail.Method)) + builder.WriteString(fmt.Sprintf(" params: %+v;", e.Detail.Params)) + builder.WriteString(fmt.Sprintf(" expected return type: %s;", reflect.TypeOf(e.Detail.RetVal))) + + if e.Result != nil { + builder.WriteString(fmt.Sprintf("encoded result: %s;", *e.Result)) + } + } + + return builder.String() +} + +func (e ErrRead) Unwrap() error { + return e.Err +} + +type ConfigError struct { + Msg string +} + +func newMissingReadIdentifierErr(readIdentifier string) ConfigError { + return ConfigError{ + Msg: fmt.Sprintf("[no configured reader] read-identifier: '%s'", readIdentifier), + } +} + +func newMissingContractErr(readIdentifier, contract string) ConfigError { + return ConfigError{ + Msg: fmt.Sprintf("[no configured reader] read-identifier: %s; contract: %s;", readIdentifier, contract), + } +} + +func newMissingReadNameErr(readIdentifier, contract, readName string) ConfigError { + return ConfigError{ + Msg: fmt.Sprintf("[no configured reader] read-identifier: %s; contract: %s; read-name: %s;", readIdentifier, contract, readName), + } +} + +func newUnboundAddressErr(address, contract, readName string) ConfigError { + return ConfigError{ + Msg: fmt.Sprintf("[address not bound] address: %s; contract: %s; read-name: %s;", address, contract, readName), + } +} + +func (e ConfigError) Error() string { + return e.Msg +} + +type FilterError struct { + Err error + Action string + Filter logpoller.Filter +} + +func (e FilterError) Error() string { + return fmt.Sprintf("[logpoller filter error] action: %s; err: %s; filter: %+v;", e.Action, e.Err.Error(), e.Filter) +} + +func (e FilterError) Unwrap() error { + return e.Err +} + +type NoContractExistsError struct { + Err error + Address common.Address +} + +func (e NoContractExistsError) Error() string { + return fmt.Sprintf("%s: contract does not exist at address: %s", e.Err.Error(), e.Address) +} + +func (e NoContractExistsError) Unwrap() error { + return e.Err +} diff --git a/core/services/relay/evm/read/event.go b/core/services/relay/evm/read/event.go new file mode 100644 index 00000000000..a1678fbb4b9 --- /dev/null +++ b/core/services/relay/evm/read/event.go @@ -0,0 +1,761 @@ +package read + +import ( + "context" + "encoding/hex" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/google/uuid" + + commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + + "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/services/relay/evm/types" +) + +type EventBinding struct { + // read-only properties + contractName string + eventName string + hash common.Hash + // eventTypes has all the types for GetLatestValue unHashed indexed topics params and for QueryKey data words or unHashed indexed topics value comparators. + eventTypes map[string]types.CodecEntry + // indexedTopicsTypes has type info about hashed indexed topics. + indexedTopicsTypes types.CodecEntry + // eventModifiers only has a modifier for indexed topic filtering, but data words can also be added if needed. + eventModifiers map[string]commoncodec.Modifier + + // dependencies + // filterRegistrar in EventBinding is to be used as an override for lp filter defined in the contract binding. + // If filterRegisterer is nil, this event should be registered with the lp filter defined in the contract binding. + registrar *syncedFilter + registerCalled bool + lp logpoller.LogPoller + + // internal properties / state + codec commontypes.RemoteCodec + bound map[common.Address]bool // bound determines if address is set to the contract binding. + mu sync.RWMutex + // topics map a generic topic name (key) to topic data + topics map[string]TopicDetail + // dataWords key is the generic dataWordNamb. + dataWords map[string]DataWordDetail + confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations +} + +func NewEventBinding( + contract, event string, + poller logpoller.LogPoller, + hash common.Hash, + indexedTopicsTypes types.CodecEntry, + confirmations map[primitives.ConfidenceLevel]evmtypes.Confirmations, +) *EventBinding { + return &EventBinding{ + contractName: contract, + eventName: event, + lp: poller, + hash: hash, + indexedTopicsTypes: indexedTopicsTypes, + confirmationsMapping: confirmations, + topics: make(map[string]TopicDetail), + dataWords: make(map[string]DataWordDetail), + bound: make(map[common.Address]bool), + } +} + +type TopicDetail struct { + abi.Argument + Index uint64 +} + +// DataWordDetail contains all the information about a single evm Data word. +// For e.g. first evm data word(32bytes) of USDC log event is uint256 var called value. +type DataWordDetail struct { + Index int + abi.Argument +} + +var _ Reader = &EventBinding{} + +func (b *EventBinding) SetCodec(codec commontypes.RemoteCodec) { + b.mu.Lock() + defer b.mu.Unlock() + + b.codec = codec +} + +func (b *EventBinding) SetFilter(filter logpoller.Filter) { + b.mu.Lock() + defer b.mu.Unlock() + + b.registrar = newSyncedFilter() + b.registrar.SetFilter(filter) +} + +func (b *EventBinding) SetCodecTypesAndModifiers(types map[string]types.CodecEntry, modifiers map[string]commoncodec.Modifier) { + b.mu.Lock() + defer b.mu.Unlock() + + b.eventTypes = types + b.eventModifiers = modifiers +} + +func (b *EventBinding) SetDataWordsDetails(dwDetail map[string]DataWordDetail) { + b.mu.Lock() + defer b.mu.Unlock() + + b.dataWords = dwDetail +} + +func (b *EventBinding) SetTopicDetails(topicDetails map[string]TopicDetail) { + b.mu.Lock() + defer b.mu.Unlock() + + b.topics = topicDetails +} + +func (b *EventBinding) GetDataWords() map[string]DataWordDetail { + b.mu.RLock() + defer b.mu.RUnlock() + + return b.dataWords +} + +func (b *EventBinding) Bind(ctx context.Context, bindings ...common.Address) error { + if b.hasBindings() { + // we are changing contract address reference, so we need to unregister old filter if it exists + if err := b.Unregister(ctx); err != nil { + return err + } + } + + // filterRegisterer isn't required here because the event can also be polled for by the contractBinding common filter. + if b.registrar != nil { + b.registrar.SetName(logpoller.FilterName(fmt.Sprintf("%s.%s.%s", b.contractName, b.eventName, uuid.NewString()))) + } + + for _, binding := range bindings { + if b.isBound(binding) { + continue + } + + if b.registrar != nil { + b.registrar.AddAddress(binding) + } + + b.addBinding(binding) + } + + if b.registered() { + return b.Register(ctx) + } + + return nil +} + +func (b *EventBinding) Unbind(ctx context.Context, bindings ...common.Address) error { + for _, binding := range bindings { + if !b.isBound(binding) { + continue + } + + if b.registrar != nil { + b.registrar.RemoveAddress(binding) + } + + b.removeBinding(binding) + } + + if err := b.Unregister(ctx); err != nil { + return err + } + + // we are changing contract address reference, so we need to unregister old filter or re-register existing filter + if b.registrar != nil { + if b.registrar.Count() == 0 { + b.registrar.SetName("") + + return b.Unregister(ctx) + } else if b.registered() { + return b.Register(ctx) + } + } + + return nil +} + +func (b *EventBinding) Register(ctx context.Context) error { + b.mu.Lock() + defer b.mu.Unlock() + + if b.registrar == nil { + return nil + } + + b.registerCalled = true + + // can't be true before filters params are set so there is no race with a bad filter outcome + if len(b.bound) == 0 { + return nil + } + + return b.registrar.Register(ctx, b.lp) +} + +func (b *EventBinding) Unregister(ctx context.Context) error { + b.mu.Lock() + defer b.mu.Unlock() + + if b.registrar == nil { + return nil + } + + if len(b.bound) == 0 { + return nil + } + + return b.registrar.Unregister(ctx, b.lp) +} + +func (b *EventBinding) BatchCall(_ common.Address, _, _ any) (Call, error) { + return Call{}, fmt.Errorf("%w: events are not yet supported in batch get latest values", commontypes.ErrInvalidType) +} + +func (b *EventBinding) GetLatestValue(ctx context.Context, address common.Address, confidenceLevel primitives.ConfidenceLevel, params, into any) (err error) { + var ( + confs evmtypes.Confirmations + result *string + ) + + defer func() { + if err != nil { + callErr := newErrorFromCall(err, Call{ + ContractAddress: address, + ContractName: b.contractName, + ReadName: b.eventName, + Params: params, + ReturnVal: into, + }, strconv.Itoa(int(confs)), false) + + callErr.Result = result + + err = callErr + } + }() + + if err = b.validateBound(address); err != nil { + return err + } + + confs, err = confidenceToConfirmations(b.confirmationsMapping, confidenceLevel) + if err != nil { + return err + } + + topicTypeID := codec.WrapItemType(b.contractName, b.eventName, true) + + onChainTypedVal, err := b.toNativeOnChainType(topicTypeID, params) + if err != nil { + return err + } + + filterTopics, err := b.extractFilterTopics(topicTypeID, onChainTypedVal) + if err != nil { + return err + } + + var log *logpoller.Log + if len(filterTopics) != 0 { + var hashedTopics []common.Hash + hashedTopics, err = b.hashTopics(topicTypeID, filterTopics) + if err != nil { + return err + } + + if log, err = b.getLatestLog(ctx, address, confs, hashedTopics); err != nil { + return err + } + } else { + if log, err = b.lp.LatestLogByEventSigWithConfs(ctx, b.hash, address, confs); err != nil { + return wrapInternalErr(err) + } + } + + if err := b.decodeLog(ctx, log, into); err != nil { + encoded := hex.EncodeToString(log.Data) + result = &encoded + + return err + } + + return nil +} + +func (b *EventBinding) QueryKey(ctx context.Context, address common.Address, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) (sequences []commontypes.Sequence, err error) { + defer func() { + if err != nil { + err = newErrorFromCall(err, Call{ + ContractAddress: address, + ContractName: b.contractName, + ReadName: b.eventName, + ReturnVal: sequenceDataType, + }, "", false) + } + }() + + if err = b.validateBound(address); err != nil { + return nil, err + } + + remapped, err := b.remap(filter) + if err != nil { + return nil, err + } + + // filter should always use the address and event sig + defaultExpressions := []query.Expression{ + logpoller.NewAddressFilter(address), + logpoller.NewEventSigFilter(b.hash), + } + remapped.Expressions = append(defaultExpressions, remapped.Expressions...) + + logs, err := b.lp.FilteredLogs(ctx, remapped.Expressions, limitAndSort, b.contractName+"-"+address.String()+"-"+b.eventName) + if err != nil { + return nil, wrapInternalErr(err) + } + + // no need to return an error. an empty list is fine + if len(logs) == 0 { + return []commontypes.Sequence{}, nil + } + + sequences, err = b.decodeLogsIntoSequences(ctx, logs, sequenceDataType) + if err != nil { + return nil, err + } + + return sequences, nil +} + +func (b *EventBinding) getLatestLog(ctx context.Context, address common.Address, confs evmtypes.Confirmations, hashedTopics []common.Hash) (*logpoller.Log, error) { + // Create limiter and filter for the query. + limiter := query.NewLimitAndSort(query.CountLimit(1), query.NewSortBySequence(query.Desc)) + + topicFilters, err := createTopicFilters(hashedTopics) + if err != nil { + return nil, err + } + + filter, err := logpoller.Where( + topicFilters, + logpoller.NewAddressFilter(address), + logpoller.NewEventSigFilter(b.hash), + logpoller.NewConfirmationsFilter(confs), + ) + if err != nil { + return nil, wrapInternalErr(err) + } + + // Gets the latest log that matches the filter and limiter. + logs, err := b.lp.FilteredLogs(ctx, filter, limiter, b.contractName+"-"+address.String()+"-"+b.eventName) + if err != nil { + return nil, wrapInternalErr(err) + } + + if len(logs) == 0 { + return nil, fmt.Errorf("%w: no events found", commontypes.ErrNotFound) + } + + return &logs[0], err +} + +func (b *EventBinding) decodeLogsIntoSequences(ctx context.Context, logs []logpoller.Log, into any) ([]commontypes.Sequence, error) { + sequences := make([]commontypes.Sequence, len(logs)) + + for idx := range logs { + sequences[idx] = commontypes.Sequence{ + Cursor: logpoller.FormatContractReaderCursor(logs[idx]), + Head: commontypes.Head{ + Height: fmt.Sprint(logs[idx].BlockNumber), + Hash: logs[idx].BlockHash.Bytes(), + Timestamp: uint64(logs[idx].BlockTimestamp.Unix()), + }, + } + + var typeVal reflect.Value + + typeInto := reflect.TypeOf(into) + if typeInto.Kind() == reflect.Pointer { + typeVal = reflect.New(typeInto.Elem()) + } else { + typeVal = reflect.Indirect(reflect.New(typeInto)) + } + + // create a new value of the same type as 'into' for the data to be extracted to + sequences[idx].Data = typeVal.Interface() + + if err := b.decodeLog(ctx, &logs[idx], sequences[idx].Data); err != nil { + return nil, err + } + } + + return sequences, nil +} + +// extractFilterTopics extracts filter topics from input params and returns them as a slice of any. +// returned slice will retain the order of the topics and fill in missing topics with nil, if all values are nil, empty slice is returned. +func (b *EventBinding) extractFilterTopics(topicTypeID string, value any) (filterTopics []any, err error) { + item := reflect.ValueOf(value) + + switch item.Kind() { + case reflect.Array, reflect.Slice: + var native any + native, err = codec.RepresentArray(item, b.eventTypes[topicTypeID]) + if err != nil { + return nil, fmt.Errorf("%w: error converting params to log topics: %s", commontypes.ErrInternal, err.Error()) + } + + filterTopics = []any{native} + case reflect.Struct, reflect.Map: + if filterTopics, err = codec.UnrollItem(item, b.eventTypes[topicTypeID]); err != nil { + return nil, fmt.Errorf("%w: error unrolling params into log topics: %s", commontypes.ErrInternal, err.Error()) + } + default: + return nil, fmt.Errorf("%w: cannot encode kind %v", commontypes.ErrInvalidType, item.Kind()) + } + + // check if at least one topic filter is present + for _, filterVal := range derefValues(filterTopics) { + if filterVal != nil { + return filterTopics, nil + } + } + + return []any{}, nil +} + +// hashTopics hashes topic filters values to match on chain indexed topics. +func (b *EventBinding) hashTopics(topicTypeID string, topics []any) ([]common.Hash, error) { + var hashableTopics []any + for i, topic := range derefValues(topics) { + if topic == nil { + continue + } + + // make topic value for non-fixed bytes array manually because geth MakeTopics doesn't support it + topicTyp, exists := b.eventTypes[topicTypeID] + if !exists { + return nil, fmt.Errorf("%w: cannot find event type entry for topic: %s", commontypes.ErrNotFound, topicTypeID) + } + + if abiArg := topicTyp.Args()[i]; abiArg.Type.T == abi.ArrayTy && (abiArg.Type.Elem != nil && abiArg.Type.Elem.T == abi.UintTy) { + packed, err := abi.Arguments{abiArg}.Pack(topic) + if err != nil { + return nil, fmt.Errorf("%w: err failed to abi pack topics: %s", commontypes.ErrInternal, err.Error()) + } + + topic = crypto.Keccak256Hash(packed) + } + + hashableTopics = append(hashableTopics, topic) + } + + hashes, err := abi.MakeTopics(hashableTopics) + if err != nil { + return nil, wrapInternalErr(err) + } + + if len(hashes) != 1 { + return nil, fmt.Errorf("%w: expected 1 filter set, got %d", commontypes.ErrInternal, len(hashes)) + } + + return hashes[0], nil +} + +func (b *EventBinding) decodeLog(ctx context.Context, log *logpoller.Log, into any) error { + // decode non indexed topics and apply output modifiers + if err := b.codec.Decode(ctx, log.Data, into, codec.WrapItemType(b.contractName, b.eventName, false)); err != nil { + return fmt.Errorf("%w: failed to decode log data: %s", commontypes.ErrInvalidType, err.Error()) + } + + // decode indexed topics which is rarely useful since most indexed topic types get Keccak256 hashed and should be just used for log filtering. + topics := make([]common.Hash, len(b.indexedTopicsTypes.Args())) + if len(log.Topics) < len(topics)+1 { + return fmt.Errorf("%w: not enough topics to decode", commontypes.ErrInvalidType) + } + + for i := 0; i < len(topics); i++ { + topics[i] = common.Hash(log.Topics[i+1]) + } + + topicsInto := map[string]any{} + if err := abi.ParseTopicsIntoMap(topicsInto, b.indexedTopicsTypes.Args(), topics); err != nil { + return fmt.Errorf("%w: %w", commontypes.ErrInvalidType, err) + } + + if err := codec.MapstructureDecode(topicsInto, into); err != nil { + return fmt.Errorf("%w: failed to decode log data: %s", commontypes.ErrInvalidEncoding, err.Error()) + } + + return nil +} + +// remap chain agnostic primitives to chain specific logPoller primitives. +func (b *EventBinding) remap(filter query.KeyFilter) (remapped query.KeyFilter, err error) { + for _, expression := range filter.Expressions { + remappedExpression, err := b.remapExpression(filter.Key, expression) + if err != nil { + return query.KeyFilter{}, err + } + + remapped.Expressions = append(remapped.Expressions, remappedExpression) + } + + return remapped, nil +} + +func (b *EventBinding) remapExpression(key string, expression query.Expression) (query.Expression, error) { + if !expression.IsPrimitive() { + remappedBoolExpressions := make([]query.Expression, len(expression.BoolExpression.Expressions)) + for i := range expression.BoolExpression.Expressions { + remapped, err := b.remapExpression(key, expression.BoolExpression.Expressions[i]) + if err != nil { + return query.Expression{}, err + } + + remappedBoolExpressions[i] = remapped + } + + if expression.BoolExpression.BoolOperator == query.AND { + return query.And(remappedBoolExpressions...), nil + } + + return query.Or(remappedBoolExpressions...), nil + } + + return b.remapPrimitive(expression) +} + +func (b *EventBinding) remapPrimitive(expression query.Expression) (query.Expression, error) { + switch primitive := expression.Primitive.(type) { + case *primitives.Comparator: + hashedValComps, err := b.encodeComparator(primitive) + if err != nil { + return query.Expression{}, fmt.Errorf("failed to encode comparator %q: %w", primitive.Name, err) + } + return hashedValComps, nil + case *primitives.Confidence: + confirmations, err := confidenceToConfirmations(b.confirmationsMapping, primitive.ConfidenceLevel) + if err != nil { + return query.Expression{}, err + } + + return logpoller.NewConfirmationsFilter(confirmations), nil + default: + return expression, nil + } +} + +func (b *EventBinding) encodeComparator(comparator *primitives.Comparator) (query.Expression, error) { + dwInfo, isDW := b.dataWords[comparator.Name] + if !isDW { + if _, exists := b.topics[comparator.Name]; !exists { + return query.Expression{}, fmt.Errorf("%w: comparator name doesn't match any of the indexed topics or data words", commontypes.ErrInvalidConfig) + } + } + + var hashedValComps []logpoller.HashedValueComparator + itemType := codec.WrapItemType(b.contractName, b.eventName+"."+comparator.Name, true) + for _, valComp := range comparator.ValueComparators { + onChainTypedVal, err := b.toNativeOnChainType(itemType, valComp.Value) + if err != nil { + return query.Expression{}, fmt.Errorf("failed to convert comparator value to native on chain type: %w", err) + } + + hashedValComp := logpoller.HashedValueComparator{Operator: valComp.Operator} + if isDW { + hashedValComp.Value, err = b.encodeValComparatorDataWord(itemType, onChainTypedVal) + } else { + hashedValComp.Value, err = b.encodeValComparatorTopic(itemType, onChainTypedVal) + } + if err != nil { + return query.Expression{}, err + } + hashedValComps = append(hashedValComps, hashedValComp) + } + + if isDW { + return logpoller.NewEventByWordFilter(dwInfo.Index, hashedValComps), nil + } + + return logpoller.NewEventByTopicFilter(b.topics[comparator.Name].Index, hashedValComps), nil +} + +func (b *EventBinding) encodeValComparatorDataWord(dwTypeID string, value any) (hash common.Hash, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("%w: cannot encode %s data word comparator. Recovered from panic: %v", commontypes.ErrInvalidType, dwTypeID, r) + } + }() + + dwTypes, exists := b.eventTypes[dwTypeID] + if !exists { + return common.Hash{}, fmt.Errorf("%w: cannot find data word type for %s", commontypes.ErrInvalidConfig, dwTypeID) + } + + packedArgs, err := dwTypes.Args().Pack(value) + if err != nil { + return common.Hash{}, fmt.Errorf("%w: failed to pack values: %w", commontypes.ErrInternal, err) + } + + return common.BytesToHash(packedArgs), nil +} + +func (b *EventBinding) encodeValComparatorTopic(topicTypeID string, value any) (hash common.Hash, err error) { + hashedTopics, err := b.hashTopics(topicTypeID, []any{value}) + if err != nil { + return common.Hash{}, err + } + + return hashedTopics[0], nil +} + +// toNativeOnChainType converts value into its on chain version by applying codec modifiers, map structure hooks and abi typing. +func (b *EventBinding) toNativeOnChainType(itemType string, value any) (any, error) { + offChain, err := b.codec.CreateType(itemType, true) + if err != nil { + return nil, fmt.Errorf("%w: failed to create type: %w", commontypes.ErrInvalidType, err) + } + + // apply map struct evm hooks to correct incoming values + if err = codec.MapstructureDecode(value, offChain); err != nil { + return nil, fmt.Errorf("%w: failed to decode offChain value: %s", commontypes.ErrInternal, err.Error()) + } + + // apply modifiers if present + onChain := offChain + if modifier, exists := b.eventModifiers[itemType]; exists { + onChain, err = modifier.TransformToOnChain(offChain, "" /* unused */) + if err != nil { + return nil, fmt.Errorf("%w: failed to apply modifiers to offchain type %T: %w", commontypes.ErrInvalidType, onChain, err) + } + } + + typ, exists := b.eventTypes[itemType] + if !exists { + return query.Expression{}, fmt.Errorf("%w: cannot find event type entry for %s", commontypes.ErrInvalidType, itemType) + } + + native, err := typ.ToNative(reflect.ValueOf(onChain)) + if err != nil { + return query.Expression{}, fmt.Errorf("%w: codec to native: %s", commontypes.ErrInvalidType, err.Error()) + } + + return native.Interface(), nil +} + +func (b *EventBinding) validateBound(address common.Address) error { + b.mu.Lock() + defer b.mu.Unlock() + + bound, exists := b.bound[address] + if !exists || !bound { + return fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newUnboundAddressErr(address.String(), b.contractName, b.eventName)) + } + + return nil +} + +func createTopicFilters(hashedTopics []common.Hash) (query.Expression, error) { + var expressions []query.Expression + for topicID, hash := range hashedTopics { + // first topic index is 1-based, so we add 1. + expressions = append(expressions, logpoller.NewEventByTopicFilter( + uint64(topicID+1), []logpoller.HashedValueComparator{{Value: hash, Operator: primitives.Eq}}, + )) + } + + if len(expressions) == 0 { + return query.Expression{}, fmt.Errorf("%w: no topic filters found during query creation", commontypes.ErrInternal) + } + + return query.And(expressions...), nil +} + +// derefValues dereferences pointers to nil values to nil. +func derefValues(topics []any) []any { + for i, topic := range topics { + rTopic := reflect.ValueOf(topic) + if rTopic.Kind() == reflect.Pointer { + if rTopic.IsNil() { + topics[i] = nil + } else { + topics[i] = rTopic.Elem().Interface() + } + } + } + + return topics +} + +func wrapInternalErr(err error) error { + if err == nil { + return nil + } + + errStr := err.Error() + if strings.Contains(errStr, "not found") || strings.Contains(errStr, "no rows") { + return fmt.Errorf("%w: %w", commontypes.ErrNotFound, err) + } + + return fmt.Errorf("%w: %s", commontypes.ErrInternal, err.Error()) +} + +func (b *EventBinding) hasBindings() bool { + b.mu.RLock() + defer b.mu.RUnlock() + + return len(b.bound) > 0 +} + +func (b *EventBinding) isBound(binding common.Address) bool { + b.mu.RLock() + defer b.mu.RUnlock() + + _, exists := b.bound[binding] + + return exists +} + +func (b *EventBinding) addBinding(binding common.Address) { + b.mu.Lock() + defer b.mu.Unlock() + + b.bound[binding] = true +} + +func (b *EventBinding) removeBinding(binding common.Address) { + b.mu.Lock() + defer b.mu.Unlock() + + delete(b.bound, binding) +} + +func (b *EventBinding) registered() bool { + b.mu.RLock() + defer b.mu.RUnlock() + + return b.registerCalled +} diff --git a/core/services/relay/evm/read/filter.go b/core/services/relay/evm/read/filter.go new file mode 100644 index 00000000000..0a5f35891d6 --- /dev/null +++ b/core/services/relay/evm/read/filter.go @@ -0,0 +1,115 @@ +package read + +import ( + "context" + "fmt" + "sync" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +type Registrar interface { + HasFilter(string) bool + RegisterFilter(context.Context, logpoller.Filter) error + UnregisterFilter(context.Context, string) error +} + +type syncedFilter struct { + // internal state properties + mu sync.RWMutex + filter logpoller.Filter +} + +func newSyncedFilter() *syncedFilter { + return &syncedFilter{} +} + +func (r *syncedFilter) Register(ctx context.Context, registrar Registrar) error { + r.mu.RLock() + defer r.mu.RUnlock() + + if !registrar.HasFilter(r.filter.Name) { + if err := registrar.RegisterFilter(ctx, r.filter); err != nil { + return FilterError{ + Err: fmt.Errorf("%w: %s", types.ErrInternal, err.Error()), + Action: "register", + Filter: r.filter, + } + } + } + + return nil +} + +func (r *syncedFilter) Unregister(ctx context.Context, registrar Registrar) error { + r.mu.RLock() + defer r.mu.RUnlock() + + if !registrar.HasFilter(r.filter.Name) { + return nil + } + + if err := registrar.UnregisterFilter(ctx, r.filter.Name); err != nil { + return FilterError{ + Err: fmt.Errorf("%w: %s", types.ErrInternal, err.Error()), + Action: "unregister", + Filter: r.filter, + } + } + + return nil +} + +func (r *syncedFilter) SetFilter(filter logpoller.Filter) { + r.mu.Lock() + defer r.mu.Unlock() + + r.filter = filter +} + +func (r *syncedFilter) SetName(name string) { + r.mu.Lock() + defer r.mu.Unlock() + + r.filter.Name = name +} + +func (r *syncedFilter) AddAddress(address common.Address) { + r.mu.Lock() + defer r.mu.Unlock() + + r.filter.Addresses = append(r.filter.Addresses, address) +} + +func (r *syncedFilter) RemoveAddress(address common.Address) { + r.mu.Lock() + defer r.mu.Unlock() + + var addrIdx int + for idx, addr := range r.filter.Addresses { + if addr.Hex() == address.Hex() { + addrIdx = idx + } + } + + r.filter.Addresses[addrIdx] = r.filter.Addresses[len(r.filter.Addresses)-1] + r.filter.Addresses = r.filter.Addresses[:len(r.filter.Addresses)-1] +} + +func (r *syncedFilter) Count() int { + r.mu.RLock() + defer r.mu.RUnlock() + + return len(r.filter.Addresses) +} + +func (r *syncedFilter) HasEventSigs() bool { + r.mu.RLock() + defer r.mu.RUnlock() + + return len(r.filter.EventSigs) > 0 && len(r.filter.Addresses) > 0 +} diff --git a/core/services/relay/evm/read/lookup.go b/core/services/relay/evm/read/lookup.go new file mode 100644 index 00000000000..5679d8cee06 --- /dev/null +++ b/core/services/relay/evm/read/lookup.go @@ -0,0 +1,84 @@ +package read + +import ( + "sync" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +type readValues struct { + address string + contract string + readName string +} + +// lookup provides basic utilities for mapping a complete readIdentifier to +// finite contract read information +type lookup struct { + mu sync.RWMutex + // contractReadNames maps a contract name to all available readNames (method, log, event, etc.) + contractReadNames map[string][]string + // readIdentifiers maps from a complete readIdentifier string to finite read data + // a readIdentifier is a combination of address, contract, and readName as a concatenated string + readIdentifiers map[string]readValues +} + +func newLookup() *lookup { + return &lookup{ + contractReadNames: make(map[string][]string), + readIdentifiers: make(map[string]readValues), + } +} + +func (l *lookup) addReadNameForContract(contract, readName string) { + l.mu.Lock() + defer l.mu.Unlock() + + readNames, exists := l.contractReadNames[contract] + if !exists { + readNames = []string{} + } + + l.contractReadNames[contract] = append(readNames, readName) +} + +func (l *lookup) bindAddressForContract(contract, address string) { + l.mu.Lock() + defer l.mu.Unlock() + + for _, readName := range l.contractReadNames[contract] { + readIdentifier := types.BoundContract{ + Address: address, + Name: contract, + }.ReadIdentifier(readName) + + l.readIdentifiers[readIdentifier] = readValues{ + address: address, + contract: contract, + readName: readName, + } + } +} + +func (l *lookup) unbindAddressForContract(contract, address string) { + l.mu.Lock() + defer l.mu.Unlock() + + for _, readName := range l.contractReadNames[contract] { + readIdentifier := types.BoundContract{ + Address: address, + Name: contract, + }.ReadIdentifier(readName) + + delete(l.readIdentifiers, readIdentifier) + } +} + +func (l *lookup) getContractForReadName(readName string) (readValues, bool) { + l.mu.RLock() + defer l.mu.RUnlock() + + contract, ok := l.readIdentifiers[readName] + + return contract, ok +} diff --git a/core/services/relay/evm/read/method.go b/core/services/relay/evm/read/method.go new file mode 100644 index 00000000000..fc7886b74b7 --- /dev/null +++ b/core/services/relay/evm/read/method.go @@ -0,0 +1,244 @@ +package read + +import ( + "context" + "fmt" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" +) + +type MethodBinding struct { + // read-only properties + contractName string + method string + + // dependencies + client evmclient.Client + ht logpoller.HeadTracker + lggr logger.Logger + confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations + + // internal state properties + codec commontypes.Codec + bindings map[common.Address]struct{} + mu sync.RWMutex +} + +func NewMethodBinding( + name, method string, + client evmclient.Client, + heads logpoller.HeadTracker, + confs map[primitives.ConfidenceLevel]evmtypes.Confirmations, + lggr logger.Logger, +) *MethodBinding { + return &MethodBinding{ + contractName: name, + method: method, + client: client, + ht: heads, + lggr: lggr, + confirmationsMapping: confs, + bindings: make(map[common.Address]struct{}), + } +} + +var _ Reader = &MethodBinding{} + +func (b *MethodBinding) Bind(ctx context.Context, bindings ...common.Address) error { + for _, binding := range bindings { + if b.isBound(binding) { + continue + } + + // check for contract byte code at the latest block and provided address + byteCode, err := b.client.CodeAt(ctx, binding, nil) + if err != nil { + return ErrRead{ + Err: fmt.Errorf("%w: code at call failure: %s", commontypes.ErrInternal, err.Error()), + Detail: &readDetail{ + Address: binding.Hex(), + Contract: b.contractName, + Params: nil, + RetVal: nil, + }, + } + } + + if len(byteCode) == 0 { + return NoContractExistsError{Err: commontypes.ErrInternal, Address: binding} + } + + b.setBinding(binding) + } + + return nil +} + +func (b *MethodBinding) Unbind(ctx context.Context, bindings ...common.Address) error { + b.mu.Lock() + defer b.mu.Unlock() + + for _, binding := range bindings { + delete(b.bindings, binding) + } + + return nil +} + +func (b *MethodBinding) SetCodec(codec commontypes.RemoteCodec) { + b.mu.Lock() + defer b.mu.Unlock() + + b.codec = codec +} + +func (b *MethodBinding) BatchCall(address common.Address, params, retVal any) (Call, error) { + if !b.isBound(address) { + return Call{}, fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newUnboundAddressErr(address.Hex(), b.contractName, b.method)) + } + + return Call{ + ContractAddress: address, + ContractName: b.contractName, + ReadName: b.method, + Params: params, + ReturnVal: retVal, + }, nil +} + +func (b *MethodBinding) GetLatestValue(ctx context.Context, addr common.Address, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error { + if !b.isBound(addr) { + return fmt.Errorf("%w: %w", commontypes.ErrInvalidConfig, newUnboundAddressErr(addr.Hex(), b.contractName, b.method)) + } + + block, err := b.blockNumberFromConfidence(ctx, confidenceLevel) + if err != nil { + return err + } + + data, err := b.codec.Encode(ctx, params, codec.WrapItemType(b.contractName, b.method, true)) + if err != nil { + callErr := newErrorFromCall( + fmt.Errorf("%w: encoding params: %s", commontypes.ErrInvalidType, err.Error()), + Call{ + ContractAddress: addr, + ContractName: b.contractName, + ReadName: b.method, + Params: params, + ReturnVal: returnVal, + }, block.String(), false) + + return callErr + } + + callMsg := ethereum.CallMsg{ + To: &addr, + From: addr, + Data: data, + } + + bytes, err := b.client.CallContract(ctx, callMsg, block) + if err != nil { + callErr := newErrorFromCall( + fmt.Errorf("%w: contract call: %s", commontypes.ErrInvalidType, err.Error()), + Call{ + ContractAddress: addr, + ContractName: b.contractName, + ReadName: b.method, + Params: params, + ReturnVal: returnVal, + }, block.String(), false) + + return callErr + } + + if err = b.codec.Decode(ctx, bytes, returnVal, codec.WrapItemType(b.contractName, b.method, false)); err != nil { + callErr := newErrorFromCall( + fmt.Errorf("%w: decode return data: %s", commontypes.ErrInvalidType, err.Error()), + Call{ + ContractAddress: addr, + ContractName: b.contractName, + ReadName: b.method, + Params: params, + ReturnVal: returnVal, + }, block.String(), false) + + strResult := hexutil.Encode(bytes) + callErr.Result = &strResult + + return callErr + } + + return nil +} + +func (b *MethodBinding) QueryKey( + _ context.Context, + _ common.Address, + _ query.KeyFilter, + _ query.LimitAndSort, + _ any, +) ([]commontypes.Sequence, error) { + return nil, nil +} + +func (b *MethodBinding) Register(_ context.Context) error { return nil } +func (b *MethodBinding) Unregister(_ context.Context) error { return nil } + +func (b *MethodBinding) blockNumberFromConfidence(ctx context.Context, confidenceLevel primitives.ConfidenceLevel) (*big.Int, error) { + confirmations, err := confidenceToConfirmations(b.confirmationsMapping, confidenceLevel) + if err != nil { + err = fmt.Errorf("%w: contract: %s; method: %s;", err, b.contractName, b.method) + if confidenceLevel == primitives.Unconfirmed { + b.lggr.Debugw("Falling back to default contract call behaviour that calls latest state", "contract", b.contractName, "method", b.method, "err", err) + + return nil, nil + } + + return nil, err + } + + _, finalized, err := b.ht.LatestAndFinalizedBlock(ctx) + if err != nil { + return nil, fmt.Errorf("%w: head tracker: %w", commontypes.ErrInternal, err) + } + + if confirmations == evmtypes.Finalized { + return big.NewInt(finalized.Number), nil + } else if confirmations == evmtypes.Unconfirmed { + return nil, nil + } + + return nil, fmt.Errorf("%w: [unknown evm confirmations]: %v; contract: %s; method: %s;", commontypes.ErrInvalidConfig, confirmations, b.contractName, b.method) +} + +func (b *MethodBinding) isBound(binding common.Address) bool { + b.mu.RLock() + defer b.mu.RUnlock() + + _, exists := b.bindings[binding] + + return exists +} + +func (b *MethodBinding) setBinding(binding common.Address) { + b.mu.Lock() + defer b.mu.Unlock() + + b.bindings[binding] = struct{}{} +} diff --git a/core/services/relay/evm/rpclibmocks/batch_caller.go b/core/services/relay/evm/read/mocks/batch_caller.go similarity index 69% rename from core/services/relay/evm/rpclibmocks/batch_caller.go rename to core/services/relay/evm/read/mocks/batch_caller.go index 0bb2c7f4fa7..5f1144b5d81 100644 --- a/core/services/relay/evm/rpclibmocks/batch_caller.go +++ b/core/services/relay/evm/read/mocks/batch_caller.go @@ -1,11 +1,11 @@ // Code generated by mockery v2.43.2. DO NOT EDIT. -package rpclibmocks +package mocks import ( context "context" - evm "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + read "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" mock "github.com/stretchr/testify/mock" ) @@ -23,27 +23,27 @@ func (_m *BatchCaller) EXPECT() *BatchCaller_Expecter { } // BatchCall provides a mock function with given fields: ctx, blockNumber, batchRequests -func (_m *BatchCaller) BatchCall(ctx context.Context, blockNumber uint64, batchRequests evm.BatchCall) (evm.BatchResult, error) { +func (_m *BatchCaller) BatchCall(ctx context.Context, blockNumber uint64, batchRequests read.BatchCall) (read.BatchResult, error) { ret := _m.Called(ctx, blockNumber, batchRequests) if len(ret) == 0 { panic("no return value specified for BatchCall") } - var r0 evm.BatchResult + var r0 read.BatchResult var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, evm.BatchCall) (evm.BatchResult, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, uint64, read.BatchCall) (read.BatchResult, error)); ok { return rf(ctx, blockNumber, batchRequests) } - if rf, ok := ret.Get(0).(func(context.Context, uint64, evm.BatchCall) evm.BatchResult); ok { + if rf, ok := ret.Get(0).(func(context.Context, uint64, read.BatchCall) read.BatchResult); ok { r0 = rf(ctx, blockNumber, batchRequests) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(evm.BatchResult) + r0 = ret.Get(0).(read.BatchResult) } } - if rf, ok := ret.Get(1).(func(context.Context, uint64, evm.BatchCall) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, uint64, read.BatchCall) error); ok { r1 = rf(ctx, blockNumber, batchRequests) } else { r1 = ret.Error(1) @@ -60,24 +60,24 @@ type BatchCaller_BatchCall_Call struct { // BatchCall is a helper method to define mock.On call // - ctx context.Context // - blockNumber uint64 -// - batchRequests evm.BatchCall +// - batchRequests read.BatchCall func (_e *BatchCaller_Expecter) BatchCall(ctx interface{}, blockNumber interface{}, batchRequests interface{}) *BatchCaller_BatchCall_Call { return &BatchCaller_BatchCall_Call{Call: _e.mock.On("BatchCall", ctx, blockNumber, batchRequests)} } -func (_c *BatchCaller_BatchCall_Call) Run(run func(ctx context.Context, blockNumber uint64, batchRequests evm.BatchCall)) *BatchCaller_BatchCall_Call { +func (_c *BatchCaller_BatchCall_Call) Run(run func(ctx context.Context, blockNumber uint64, batchRequests read.BatchCall)) *BatchCaller_BatchCall_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint64), args[2].(evm.BatchCall)) + run(args[0].(context.Context), args[1].(uint64), args[2].(read.BatchCall)) }) return _c } -func (_c *BatchCaller_BatchCall_Call) Return(_a0 evm.BatchResult, _a1 error) *BatchCaller_BatchCall_Call { +func (_c *BatchCaller_BatchCall_Call) Return(_a0 read.BatchResult, _a1 error) *BatchCaller_BatchCall_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *BatchCaller_BatchCall_Call) RunAndReturn(run func(context.Context, uint64, evm.BatchCall) (evm.BatchResult, error)) *BatchCaller_BatchCall_Call { +func (_c *BatchCaller_BatchCall_Call) RunAndReturn(run func(context.Context, uint64, read.BatchCall) (read.BatchResult, error)) *BatchCaller_BatchCall_Call { _c.Call.Return(run) return _c } diff --git a/core/services/relay/evm/read/mocks/reader.go b/core/services/relay/evm/read/mocks/reader.go new file mode 100644 index 00000000000..6bb9dd70cc1 --- /dev/null +++ b/core/services/relay/evm/read/mocks/reader.go @@ -0,0 +1,463 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + + query "github.com/smartcontractkit/chainlink-common/pkg/types/query" + + read "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" + + types "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// Reader is an autogenerated mock type for the Reader type +type Reader struct { + mock.Mock +} + +type Reader_Expecter struct { + mock *mock.Mock +} + +func (_m *Reader) EXPECT() *Reader_Expecter { + return &Reader_Expecter{mock: &_m.Mock} +} + +// BatchCall provides a mock function with given fields: address, params, retVal +func (_m *Reader) BatchCall(address common.Address, params interface{}, retVal interface{}) (read.Call, error) { + ret := _m.Called(address, params, retVal) + + if len(ret) == 0 { + panic("no return value specified for BatchCall") + } + + var r0 read.Call + var r1 error + 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, 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, interface{}, interface{}) error); ok { + r1 = rf(address, params, retVal) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Reader_BatchCall_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchCall' +type Reader_BatchCall_Call struct { + *mock.Call +} + +// BatchCall is a helper method to define mock.On call +// - address common.Address +// - 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 interface{}, retVal interface{})) *Reader_BatchCall_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(common.Address), args[1].(interface{}), args[2].(interface{})) + }) + return _c +} + +func (_c *Reader_BatchCall_Call) Return(_a0 read.Call, _a1 error) *Reader_BatchCall_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Reader_BatchCall_Call) RunAndReturn(run func(common.Address, interface{}, interface{}) (read.Call, error)) *Reader_BatchCall_Call { + _c.Call.Return(run) + return _c +} + +// Bind provides a mock function with given fields: _a0, _a1 +func (_m *Reader) Bind(_a0 context.Context, _a1 ...common.Address) error { + _va := make([]interface{}, len(_a1)) + for _i := range _a1 { + _va[_i] = _a1[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Bind") + } + + 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 +} + +// Reader_Bind_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Bind' +type Reader_Bind_Call struct { + *mock.Call +} + +// Bind is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 ...common.Address +func (_e *Reader_Expecter) Bind(_a0 interface{}, _a1 ...interface{}) *Reader_Bind_Call { + return &Reader_Bind_Call{Call: _e.mock.On("Bind", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *Reader_Bind_Call) Run(run func(_a0 context.Context, _a1 ...common.Address)) *Reader_Bind_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]common.Address, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(common.Address) + } + } + run(args[0].(context.Context), variadicArgs...) + }) + return _c +} + +func (_c *Reader_Bind_Call) Return(_a0 error) *Reader_Bind_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Reader_Bind_Call) RunAndReturn(run func(context.Context, ...common.Address) error) *Reader_Bind_Call { + _c.Call.Return(run) + return _c +} + +// GetLatestValue provides a mock function with given fields: ctx, addr, confidence, params, returnVal +func (_m *Reader) GetLatestValue(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params interface{}, returnVal interface{}) error { + ret := _m.Called(ctx, addr, confidence, params, returnVal) + + if len(ret) == 0 { + panic("no return value specified for GetLatestValue") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, primitives.ConfidenceLevel, interface{}, interface{}) error); ok { + r0 = rf(ctx, addr, confidence, params, returnVal) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Reader_GetLatestValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestValue' +type Reader_GetLatestValue_Call struct { + *mock.Call +} + +// GetLatestValue is a helper method to define mock.On call +// - ctx context.Context +// - addr common.Address +// - confidence primitives.ConfidenceLevel +// - params interface{} +// - returnVal interface{} +func (_e *Reader_Expecter) GetLatestValue(ctx interface{}, addr interface{}, confidence interface{}, params interface{}, returnVal interface{}) *Reader_GetLatestValue_Call { + return &Reader_GetLatestValue_Call{Call: _e.mock.On("GetLatestValue", ctx, addr, confidence, params, returnVal)} +} + +func (_c *Reader_GetLatestValue_Call) Run(run func(ctx context.Context, addr common.Address, confidence primitives.ConfidenceLevel, params interface{}, returnVal interface{})) *Reader_GetLatestValue_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(primitives.ConfidenceLevel), args[3].(interface{}), args[4].(interface{})) + }) + return _c +} + +func (_c *Reader_GetLatestValue_Call) Return(_a0 error) *Reader_GetLatestValue_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Reader_GetLatestValue_Call) RunAndReturn(run func(context.Context, common.Address, primitives.ConfidenceLevel, interface{}, interface{}) error) *Reader_GetLatestValue_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 interface{}) ([]types.Sequence, error) { + ret := _m.Called(_a0, _a1, _a2, _a3, _a4) + + if len(ret) == 0 { + panic("no return value specified for QueryKey") + } + + var r0 []types.Sequence + var r1 error + 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, interface{}) []types.Sequence); ok { + r0 = rf(_a0, _a1, _a2, _a3, _a4) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.Sequence) + } + } + + 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) + } + + return r0, r1 +} + +// Reader_QueryKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryKey' +type Reader_QueryKey_Call struct { + *mock.Call +} + +// QueryKey is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 common.Address +// - _a2 query.KeyFilter +// - _a3 query.LimitAndSort +// - _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 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].(interface{})) + }) + return _c +} + +func (_c *Reader_QueryKey_Call) Return(_a0 []types.Sequence, _a1 error) *Reader_QueryKey_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +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 +} + +// Register provides a mock function with given fields: _a0 +func (_m *Reader) Register(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Register") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Reader_Register_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Register' +type Reader_Register_Call struct { + *mock.Call +} + +// Register is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Reader_Expecter) Register(_a0 interface{}) *Reader_Register_Call { + return &Reader_Register_Call{Call: _e.mock.On("Register", _a0)} +} + +func (_c *Reader_Register_Call) Run(run func(_a0 context.Context)) *Reader_Register_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Reader_Register_Call) Return(_a0 error) *Reader_Register_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Reader_Register_Call) RunAndReturn(run func(context.Context) error) *Reader_Register_Call { + _c.Call.Return(run) + return _c +} + +// SetCodec provides a mock function with given fields: _a0 +func (_m *Reader) SetCodec(_a0 types.RemoteCodec) { + _m.Called(_a0) +} + +// Reader_SetCodec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetCodec' +type Reader_SetCodec_Call struct { + *mock.Call +} + +// SetCodec is a helper method to define mock.On call +// - _a0 types.RemoteCodec +func (_e *Reader_Expecter) SetCodec(_a0 interface{}) *Reader_SetCodec_Call { + return &Reader_SetCodec_Call{Call: _e.mock.On("SetCodec", _a0)} +} + +func (_c *Reader_SetCodec_Call) Run(run func(_a0 types.RemoteCodec)) *Reader_SetCodec_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.RemoteCodec)) + }) + return _c +} + +func (_c *Reader_SetCodec_Call) Return() *Reader_SetCodec_Call { + _c.Call.Return() + return _c +} + +func (_c *Reader_SetCodec_Call) RunAndReturn(run func(types.RemoteCodec)) *Reader_SetCodec_Call { + _c.Call.Return(run) + return _c +} + +// Unbind provides a mock function with given fields: _a0, _a1 +func (_m *Reader) Unbind(_a0 context.Context, _a1 ...common.Address) error { + _va := make([]interface{}, len(_a1)) + for _i := range _a1 { + _va[_i] = _a1[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Unbind") + } + + 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 +} + +// Reader_Unbind_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unbind' +type Reader_Unbind_Call struct { + *mock.Call +} + +// Unbind is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 ...common.Address +func (_e *Reader_Expecter) Unbind(_a0 interface{}, _a1 ...interface{}) *Reader_Unbind_Call { + return &Reader_Unbind_Call{Call: _e.mock.On("Unbind", + append([]interface{}{_a0}, _a1...)...)} +} + +func (_c *Reader_Unbind_Call) Run(run func(_a0 context.Context, _a1 ...common.Address)) *Reader_Unbind_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]common.Address, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(common.Address) + } + } + run(args[0].(context.Context), variadicArgs...) + }) + return _c +} + +func (_c *Reader_Unbind_Call) Return(_a0 error) *Reader_Unbind_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Reader_Unbind_Call) RunAndReturn(run func(context.Context, ...common.Address) error) *Reader_Unbind_Call { + _c.Call.Return(run) + return _c +} + +// Unregister provides a mock function with given fields: _a0 +func (_m *Reader) Unregister(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Unregister") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Reader_Unregister_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Unregister' +type Reader_Unregister_Call struct { + *mock.Call +} + +// Unregister is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Reader_Expecter) Unregister(_a0 interface{}) *Reader_Unregister_Call { + return &Reader_Unregister_Call{Call: _e.mock.On("Unregister", _a0)} +} + +func (_c *Reader_Unregister_Call) Run(run func(_a0 context.Context)) *Reader_Unregister_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Reader_Unregister_Call) Return(_a0 error) *Reader_Unregister_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Reader_Unregister_Call) RunAndReturn(run func(context.Context) error) *Reader_Unregister_Call { + _c.Call.Return(run) + return _c +} + +// NewReader creates a new instance of Reader. 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 NewReader(t interface { + mock.TestingT + Cleanup(func()) +}) *Reader { + mock := &Reader{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/relay/evm/read/mocks/registrar.go b/core/services/relay/evm/read/mocks/registrar.go new file mode 100644 index 00000000000..670c29317a1 --- /dev/null +++ b/core/services/relay/evm/read/mocks/registrar.go @@ -0,0 +1,177 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + logpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + mock "github.com/stretchr/testify/mock" +) + +// Registrar is an autogenerated mock type for the Registrar type +type Registrar struct { + mock.Mock +} + +type Registrar_Expecter struct { + mock *mock.Mock +} + +func (_m *Registrar) EXPECT() *Registrar_Expecter { + return &Registrar_Expecter{mock: &_m.Mock} +} + +// HasFilter provides a mock function with given fields: _a0 +func (_m *Registrar) HasFilter(_a0 string) bool { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for HasFilter") + } + + var r0 bool + if rf, ok := ret.Get(0).(func(string) bool); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// Registrar_HasFilter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HasFilter' +type Registrar_HasFilter_Call struct { + *mock.Call +} + +// HasFilter is a helper method to define mock.On call +// - _a0 string +func (_e *Registrar_Expecter) HasFilter(_a0 interface{}) *Registrar_HasFilter_Call { + return &Registrar_HasFilter_Call{Call: _e.mock.On("HasFilter", _a0)} +} + +func (_c *Registrar_HasFilter_Call) Run(run func(_a0 string)) *Registrar_HasFilter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Registrar_HasFilter_Call) Return(_a0 bool) *Registrar_HasFilter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Registrar_HasFilter_Call) RunAndReturn(run func(string) bool) *Registrar_HasFilter_Call { + _c.Call.Return(run) + return _c +} + +// RegisterFilter provides a mock function with given fields: _a0, _a1 +func (_m *Registrar) RegisterFilter(_a0 context.Context, _a1 logpoller.Filter) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for RegisterFilter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, logpoller.Filter) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Registrar_RegisterFilter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RegisterFilter' +type Registrar_RegisterFilter_Call struct { + *mock.Call +} + +// RegisterFilter is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 logpoller.Filter +func (_e *Registrar_Expecter) RegisterFilter(_a0 interface{}, _a1 interface{}) *Registrar_RegisterFilter_Call { + return &Registrar_RegisterFilter_Call{Call: _e.mock.On("RegisterFilter", _a0, _a1)} +} + +func (_c *Registrar_RegisterFilter_Call) Run(run func(_a0 context.Context, _a1 logpoller.Filter)) *Registrar_RegisterFilter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(logpoller.Filter)) + }) + return _c +} + +func (_c *Registrar_RegisterFilter_Call) Return(_a0 error) *Registrar_RegisterFilter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Registrar_RegisterFilter_Call) RunAndReturn(run func(context.Context, logpoller.Filter) error) *Registrar_RegisterFilter_Call { + _c.Call.Return(run) + return _c +} + +// UnregisterFilter provides a mock function with given fields: _a0, _a1 +func (_m *Registrar) UnregisterFilter(_a0 context.Context, _a1 string) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for UnregisterFilter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Registrar_UnregisterFilter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnregisterFilter' +type Registrar_UnregisterFilter_Call struct { + *mock.Call +} + +// UnregisterFilter is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +func (_e *Registrar_Expecter) UnregisterFilter(_a0 interface{}, _a1 interface{}) *Registrar_UnregisterFilter_Call { + return &Registrar_UnregisterFilter_Call{Call: _e.mock.On("UnregisterFilter", _a0, _a1)} +} + +func (_c *Registrar_UnregisterFilter_Call) Run(run func(_a0 context.Context, _a1 string)) *Registrar_UnregisterFilter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *Registrar_UnregisterFilter_Call) Return(_a0 error) *Registrar_UnregisterFilter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Registrar_UnregisterFilter_Call) RunAndReturn(run func(context.Context, string) error) *Registrar_UnregisterFilter_Call { + _c.Call.Return(run) + return _c +} + +// NewRegistrar creates a new instance of Registrar. 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 NewRegistrar(t interface { + mock.TestingT + Cleanup(func()) +}) *Registrar { + mock := &Registrar{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go index f262948c9c5..884597df718 100644 --- a/core/services/relay/evm/relayer_extender.go +++ b/core/services/relay/evm/relayer_extender.go @@ -2,15 +2,11 @@ package evm import ( "context" + "errors" "fmt" - "math/big" - "github.com/pkg/errors" "go.uber.org/multierr" - "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" ) @@ -18,107 +14,30 @@ import ( // ErrNoChains indicates that no EVM chains have been started var ErrNoChains = errors.New("no EVM chains loaded") -type EVMChainRelayerExtender interface { - relay.RelayerExt - Chain() legacyevm.Chain -} - -type EVMChainRelayerExtenderSlicer interface { - Slice() []EVMChainRelayerExtender - Len() int - AppConfig() legacyevm.AppConfig -} - -type ChainRelayerExtenders struct { - exts []EVMChainRelayerExtender - cfg legacyevm.AppConfig +type LegacyChainsAndConfig struct { + rs []legacyevm.Chain + cfg toml.EVMConfigs } -var _ EVMChainRelayerExtenderSlicer = &ChainRelayerExtenders{} - -func NewLegacyChainsFromRelayerExtenders(exts EVMChainRelayerExtenderSlicer) *legacyevm.LegacyChains { +func (r *LegacyChainsAndConfig) NewLegacyChains() *legacyevm.LegacyChains { m := make(map[string]legacyevm.Chain) - for _, r := range exts.Slice() { - m[r.Chain().ID().String()] = r.Chain() - } - return legacyevm.NewLegacyChains(m, exts.AppConfig().EVMConfigs()) -} - -func newChainRelayerExtsFromSlice(exts []*ChainRelayerExt, appConfig legacyevm.AppConfig) *ChainRelayerExtenders { - temp := make([]EVMChainRelayerExtender, len(exts)) - for i := range exts { - temp[i] = exts[i] - } - return &ChainRelayerExtenders{ - exts: temp, - cfg: appConfig, + for _, r := range r.Slice() { + m[r.ID().String()] = r } + return legacyevm.NewLegacyChains(m, r.cfg) } -func (c *ChainRelayerExtenders) AppConfig() legacyevm.AppConfig { - return c.cfg -} - -func (c *ChainRelayerExtenders) Slice() []EVMChainRelayerExtender { - return c.exts -} - -func (c *ChainRelayerExtenders) Len() int { - return len(c.exts) -} - -// implements OneChain -type ChainRelayerExt struct { - chain legacyevm.Chain -} - -var _ EVMChainRelayerExtender = &ChainRelayerExt{} - -func (s *ChainRelayerExt) GetChainStatus(ctx context.Context) (commontypes.ChainStatus, error) { - return s.chain.GetChainStatus(ctx) -} - -func (s *ChainRelayerExt) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []commontypes.NodeStatus, nextPageToken string, total int, err error) { - return s.chain.ListNodeStatuses(ctx, pageSize, pageToken) -} - -func (s *ChainRelayerExt) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error { - return s.chain.Transact(ctx, from, to, amount, balanceCheck) -} - -func (s *ChainRelayerExt) ID() string { - return s.chain.ID().String() +func (r *LegacyChainsAndConfig) Slice() []legacyevm.Chain { + return r.rs } -func (s *ChainRelayerExt) Chain() legacyevm.Chain { - return s.chain +func (r *LegacyChainsAndConfig) Len() int { + return len(r.rs) } -var ErrCorruptEVMChain = errors.New("corrupt evm chain") - -func (s *ChainRelayerExt) Start(ctx context.Context) error { - return s.chain.Start(ctx) -} - -func (s *ChainRelayerExt) Close() (err error) { - return s.chain.Close() -} - -func (s *ChainRelayerExt) Name() string { - return s.chain.Name() -} - -func (s *ChainRelayerExt) HealthReport() map[string]error { - return s.chain.HealthReport() -} - -func (s *ChainRelayerExt) Ready() (err error) { - return s.chain.Ready() -} - -func NewChainRelayerExtenders(ctx context.Context, opts legacyevm.ChainRelayExtenderConfig) (*ChainRelayerExtenders, error) { - if err := opts.Validate(); err != nil { - return nil, err +func NewLegacyChains(ctx context.Context, opts legacyevm.ChainRelayOpts) (result []legacyevm.Chain, err error) { + if err = opts.Validate(); err != nil { + return } unique := make(map[string]struct{}) @@ -136,11 +55,9 @@ func NewChainRelayerExtenders(ctx context.Context, opts legacyevm.ChainRelayExte } } - var result []*ChainRelayerExt - var err error for i := range enabled { cid := enabled[i].ChainID.String() - privOpts := legacyevm.ChainRelayExtenderConfig{ + privOpts := legacyevm.ChainRelayOpts{ Logger: opts.Logger.Named(cid), ChainOpts: opts.ChainOpts, KeyStore: opts.KeyStore, @@ -153,11 +70,12 @@ func NewChainRelayerExtenders(ctx context.Context, opts legacyevm.ChainRelayExte continue } - s := &ChainRelayerExt{ - chain: chain, - } - result = append(result, s) + result = append(result, chain) } + return +} +func NewLegacyChainsAndConfig(ctx context.Context, opts legacyevm.ChainRelayOpts) (*LegacyChainsAndConfig, error) { + result, err := NewLegacyChains(ctx, opts) // always return because it's accumulating errors - return newChainRelayerExtsFromSlice(result, opts.AppConfig), err + return &LegacyChainsAndConfig{result, opts.AppConfig.EVMConfigs()}, err } diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index f2bc3a33a93..3be2bbcb5e7 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -35,31 +35,31 @@ func TestChainRelayExtenders(t *testing.T) { kst := cltest.NewKeyStore(t, db) require.NoError(t, kst.Unlock(ctx, cltest.Password)) - opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg}) + opts := evmtest.NewChainOpts(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg}) opts.GenEthClient = func(*big.Int) evmclient.Client { return cltest.NewEthMocksWithStartupAssertions(t) } - relayExtenders, err := evmrelay.NewChainRelayerExtenders(testutils.Context(t), opts) + relayExtenders, err := evmrelay.NewLegacyChains(testutils.Context(t), opts) require.NoError(t, err) - require.Equal(t, relayExtenders.Len(), 2) - relayExtendersInstances := relayExtenders.Slice() + require.Equal(t, len(relayExtenders), 2) + relayExtendersInstances := relayExtenders for _, c := range relayExtendersInstances { require.NoError(t, c.Start(testutils.Context(t))) require.NoError(t, c.Ready()) } - require.NotEqual(t, relayExtendersInstances[0].Chain().ID().String(), relayExtendersInstances[1].Chain().ID().String()) + require.NotEqual(t, relayExtendersInstances[0].ID().String(), relayExtendersInstances[1].ID().String()) for _, c := range relayExtendersInstances { require.NoError(t, c.Close()) } - relayExtendersInstances[0].Chain().Client().(*evmclimocks.Client).AssertCalled(t, "Close") - relayExtendersInstances[1].Chain().Client().(*evmclimocks.Client).AssertCalled(t, "Close") + relayExtendersInstances[0].Client().(*evmclimocks.Client).AssertCalled(t, "Close") + relayExtendersInstances[1].Client().(*evmclimocks.Client).AssertCalled(t, "Close") - assert.Error(t, relayExtendersInstances[0].Chain().Ready()) - assert.Error(t, relayExtendersInstances[1].Chain().Ready()) + assert.Error(t, relayExtendersInstances[0].Ready()) + assert.Error(t, relayExtendersInstances[1].Ready()) // test extender methods on single instance relayExt := relayExtendersInstances[0] diff --git a/core/services/relay/evm/request_round_db.go b/core/services/relay/evm/request_round_db.go index 1aa3dfd7471..07a2d1cbc3b 100644 --- a/core/services/relay/evm/request_round_db.go +++ b/core/services/relay/evm/request_round_db.go @@ -8,8 +8,8 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) // RequestRoundDB stores requested rounds for querying by the median plugin. diff --git a/core/services/relay/evm/request_round_tracker.go b/core/services/relay/evm/request_round_tracker.go index 7cf13775693..b9200fff757 100644 --- a/core/services/relay/evm/request_round_tracker.go +++ b/core/services/relay/evm/request_round_tracker.go @@ -12,13 +12,13 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" offchain_aggregator_wrapper "github.com/smartcontractkit/chainlink/v2/core/internal/gethwrappers2/generated/offchainaggregator" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" ) diff --git a/core/services/relay/evm/standard_config_provider.go b/core/services/relay/evm/standard_config_provider.go index 59f91c52f4a..91ca25413fa 100644 --- a/core/services/relay/evm/standard_config_provider.go +++ b/core/services/relay/evm/standard_config_provider.go @@ -10,8 +10,9 @@ import ( "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/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) diff --git a/core/services/relay/evm/types/codec_entry.go b/core/services/relay/evm/types/codec_entry.go index 9a8103cf7f9..6a39f9d226f 100644 --- a/core/services/relay/evm/types/codec_entry.go +++ b/core/services/relay/evm/types/codec_entry.go @@ -57,12 +57,25 @@ func (entry *codecEntry) NativeType() reflect.Type { return entry.nativeType } -func (entry *codecEntry) ToNative(checked reflect.Value) (reflect.Value, error) { - if checked.Type() != reflect.PointerTo(entry.checkedType) { - return reflect.Value{}, fmt.Errorf("%w: checked type %v does not match expected type %v", commontypes.ErrInvalidType, reflect.TypeOf(checked), entry.checkedType) +func (entry *codecEntry) ToNative(checked reflect.Value) (val reflect.Value, err error) { + defer func() { + if r := recover(); r != nil { + val = reflect.Value{} + err = fmt.Errorf("invalid checked value: %v", r) + } + }() + + // some checked types are expected to be pointers already for e.g. big numbers, so this is fine + checkedTypeIsPtr := entry.checkedType == checked.Type() + if checked.Type() != reflect.PointerTo(entry.checkedType) && !checkedTypeIsPtr { + return reflect.Value{}, fmt.Errorf("%w: checked type %v does not match expected type %v", commontypes.ErrInvalidType, checked.Type(), entry.checkedType) + } + + if checkedTypeIsPtr { + return reflect.NewAt(entry.nativeType.Elem(), checked.UnsafePointer()), nil } - return reflect.NewAt(entry.nativeType, checked.UnsafePointer()), nil + return reflect.Indirect(reflect.NewAt(entry.nativeType, checked.UnsafePointer())), nil } func (entry *codecEntry) IsNativePointer(item reflect.Type) bool { diff --git a/core/services/relay/evm/types/codec_entry_test.go b/core/services/relay/evm/types/codec_entry_test.go index 64e0998716a..c71d5c0ad33 100644 --- a/core/services/relay/evm/types/codec_entry_test.go +++ b/core/services/relay/evm/types/codec_entry_test.go @@ -47,14 +47,13 @@ func TestCodecEntry(t *testing.T) { f4 := big.NewInt( /*2^23 - 1*/ 8388607) setAndVerifyLimit(t, (*int24)(f4), f4, iChecked.FieldByName("Field4")) - rNative, err := entry.ToNative(checked) - require.NoError(t, err) - iNative := reflect.Indirect(rNative) - assert.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) - assert.Equal(t, iNative.Field(1).Interface(), iChecked.Field(1).Interface()) - assert.Equal(t, iNative.Field(2).Interface(), f3) - assert.Equal(t, iNative.Field(3).Interface(), f4) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + native, err := entry.ToNative(checked) + require.NoError(t, err) + assert.Equal(t, native.Field(0).Interface(), iChecked.Field(0).Interface()) + assert.Equal(t, native.Field(1).Interface(), iChecked.Field(1).Interface()) + assert.Equal(t, native.Field(2).Interface(), f3) + assert.Equal(t, native.Field(3).Interface(), f4) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("tuples", func(t *testing.T) { @@ -86,12 +85,11 @@ func TestCodecEntry(t *testing.T) { native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - require.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) - nF2 := reflect.Indirect(iNative.Field(1)) + require.Equal(t, native.Field(0).Interface(), iChecked.Field(0).Interface()) + nF2 := reflect.Indirect(native.Field(1)) assert.Equal(t, nF2.Field(0).Interface(), f3) assert.Equal(t, nF2.Field(1).Interface(), f4) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("nested tuple member names are capitalized", func(t *testing.T) { @@ -123,12 +121,11 @@ func TestCodecEntry(t *testing.T) { native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - require.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) - nF2 := reflect.Indirect(iNative.Field(1)) + require.Equal(t, native.Field(0).Interface(), iChecked.Field(0).Interface()) + nF2 := reflect.Indirect(native.Field(1)) assert.Equal(t, nF2.Field(0).Interface(), f3) assert.Equal(t, nF2.Field(1).Interface(), f4) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("unwrapped types", func(t *testing.T) { @@ -145,9 +142,8 @@ func TestCodecEntry(t *testing.T) { iChecked.FieldByName("Field1").Set(reflect.ValueOf(&anyValue)) native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, &anyValue, iNative.FieldByName("Field1").Interface()) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assert.Equal(t, &anyValue, native.FieldByName("Field1").Interface()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("slice types", func(t *testing.T) { @@ -162,9 +158,8 @@ func TestCodecEntry(t *testing.T) { iChecked.FieldByName("Field1").Set(reflect.ValueOf(anySliceValue)) native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, anySliceValue, iNative.FieldByName("Field1").Interface()) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assert.Equal(t, anySliceValue, native.FieldByName("Field1").Interface()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("array types", func(t *testing.T) { @@ -178,8 +173,7 @@ func TestCodecEntry(t *testing.T) { iChecked.FieldByName("Field1").Set(reflect.ValueOf(anySliceValue)) native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, anySliceValue, iNative.FieldByName("Field1").Interface()) + assert.Equal(t, anySliceValue, native.FieldByName("Field1").Interface()) }) t.Run("Not return values makes struct{}", func(t *testing.T) { @@ -188,7 +182,7 @@ func TestCodecEntry(t *testing.T) { assert.Equal(t, reflect.TypeOf(struct{}{}), entry.CheckedType()) native, err := entry.ToNative(reflect.ValueOf(&struct{}{})) require.NoError(t, err) - assert.Equal(t, &struct{}{}, native.Interface()) + assert.Equal(t, struct{}{}, native.Interface()) }) t.Run("Address works", func(t *testing.T) { @@ -204,9 +198,8 @@ func TestCodecEntry(t *testing.T) { native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, anyAddr, iNative.FieldByName("Foo").Interface()) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assert.Equal(t, anyAddr, native.FieldByName("Foo").Interface()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("Unnamed parameters are named after their locations", func(t *testing.T) { @@ -269,8 +262,7 @@ func TestCodecEntry(t *testing.T) { assert.Equal(t, reflect.TypeOf((*int16)(nil)), checkedField.Type) native, err := entry.ToNative(reflect.New(entry.CheckedType())) require.NoError(t, err) - iNative := reflect.Indirect(native) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("Indexed string and bytes array change to hash", func(t *testing.T) { @@ -292,7 +284,7 @@ func TestCodecEntry(t *testing.T) { assert.Equal(t, reflect.TypeOf(&common.Hash{}), nativeField.Type) native, err := entry.ToNative(reflect.New(entry.CheckedType())) require.NoError(t, err) - assertHaveSameStructureAndNames(t, native.Type().Elem(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) } }) diff --git a/core/services/relay/evm/types/types.go b/core/services/relay/evm/types/types.go index 175e1535dff..2a5e59fe66e 100644 --- a/core/services/relay/evm/types/types.go +++ b/core/services/relay/evm/types/types.go @@ -13,8 +13,6 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" - "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -26,9 +24,8 @@ import ( ) type ChainWriterConfig struct { - Contracts map[string]*ContractConfig - SendStrategy txmgrtypes.TxStrategy - MaxGasPrice *assets.Wei + Contracts map[string]*ContractConfig + MaxGasPrice *assets.Wei } type ContractConfig struct { @@ -61,6 +58,14 @@ type ChainCodecConfig struct { ModifierConfigs codec.ModifiersConfig `json:"modifierConfigs,omitempty" toml:"modifierConfigs,omitempty"` } +type DataWordDetail struct { + Name string `json:"name"` + // Index is indexed from 0. Index should only be used as an override in specific edge case scenarios where the index can't be programmatically calculated, otherwise leave this as nil. + Index *int `json:"index,omitempty"` + // Type should follow the geth ABI types naming convention + Type string `json:"type,omitempty"` +} + type ContractPollingFilter struct { GenericEventNames []string `json:"genericEventNames"` PollingFilter `json:"pollingFilter"` @@ -100,11 +105,9 @@ type EventDefinitions struct { // GenericTopicNames helps QueryingKeys not rely on EVM specific topic names. Key is chain specific name, value is generic name. // This helps us translate chain agnostic querying key "transfer-value" to EVM specific "evmTransferEvent-weiAmountTopic". GenericTopicNames map[string]string `json:"genericTopicNames,omitempty"` - // key is a predefined generic name for evm log event data word - // for e.g. first evm data word(32bytes) of USDC log event is value so the key can be called value - GenericDataWordNames map[string]uint8 `json:"genericDataWordNames,omitempty"` - // InputFields allows you to choose which indexed fields are expected from the input - InputFields []string `json:"inputFields,omitempty"` + // GenericDataWordDetails key is generic name for evm log event data word that maps to chain details. + // For e.g. first evm data word(32bytes) of USDC log event is value so the key can be called value. + GenericDataWordDetails map[string]DataWordDetail `json:"genericDataWordDetails,omitempty"` // PollingFilter should be defined on a contract level in ContractPollingFilter, // unless event needs to override the contract level filter options. // This will create a separate log poller filter for this event. @@ -178,6 +181,17 @@ func (r *ReadType) UnmarshalText(text []byte) error { return fmt.Errorf("unrecognized ReadType: %s", string(text)) } +type LLOConfigMode string + +const ( + LLOConfigModeMercury LLOConfigMode = "mercury" + LLOConfigModeBlueGreen LLOConfigMode = "bluegreen" +) + +func (c LLOConfigMode) String() string { + return string(c) +} + type RelayConfig struct { ChainID *big.Big `json:"chainID"` FromBlock uint64 `json:"fromBlock"` @@ -195,6 +209,10 @@ type RelayConfig struct { // Mercury-specific FeedID *common.Hash `json:"feedID"` EnableTriggerCapability bool `json:"enableTriggerCapability"` + + // LLO-specific + LLODONID uint32 `json:"lloDonID" toml:"lloDonID"` + LLOConfigMode LLOConfigMode `json:"lloConfigMode" toml:"lloConfigMode"` } var ErrBadRelayConfig = errors.New("bad relay config") diff --git a/core/services/relay/evm/types/types_test.go b/core/services/relay/evm/types/types_test.go index 37d5e77693a..f77b4226e87 100644 --- a/core/services/relay/evm/types/types_test.go +++ b/core/services/relay/evm/types/types_test.go @@ -80,7 +80,7 @@ func Test_ChainReaderConfig(t *testing.T) { } }, "configs":{ - "config1":"{\"cacheEnabled\":true,\"chainSpecificName\":\"specificName1\",\"inputModifications\":[{\"Fields\":[\"ts\"],\"Type\":\"epoch to time\"},{\"Fields\":{\"a\":\"b\"},\"Type\":\"rename\"}],\"outputModifications\":[{\"Fields\":[\"ts\"],\"Type\":\"epoch to time\"},{\"Fields\":{\"c\":\"d\"},\"Type\":\"rename\"}],\"eventDefinitions\":{\"genericTopicNames\":{\"TopicKey1\":\"TopicVal1\"},\"genericDataWordNames\":{\"DataWordKey\":1},\"inputFields\":[\"Event1\",\"Event2\"],\"pollingFilter\":{\"topic2\":[\"0x4abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"topic3\":[\"0x5abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"topic4\":[\"0x6abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"retention\":\"1m0s\",\"maxLogsKept\":100,\"logsPerBlock\":10}},\"confidenceConfirmations\":{\"0.0\":0,\"1.0\":-1}}" + "config1":"{\"cacheEnabled\":true,\"chainSpecificName\":\"specificName1\",\"inputModifications\":[{\"Fields\":[\"ts\"],\"Type\":\"epoch to time\"},{\"Fields\":{\"a\":\"b\"},\"Type\":\"rename\"}],\"outputModifications\":[{\"Fields\":[\"ts\"],\"Type\":\"epoch to time\"},{\"Fields\":{\"c\":\"d\"},\"Type\":\"rename\"}],\"eventDefinitions\":{\"genericTopicNames\":{\"TopicKey1\":\"TopicVal1\"},\"genericDataWordDetails\":{\"DataWordKey\":{\"Name\":\"DataWordKey\"}},\"pollingFilter\":{\"topic2\":[\"0x4abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"topic3\":[\"0x5abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"topic4\":[\"0x6abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"retention\":\"1m0s\",\"maxLogsKept\":100,\"logsPerBlock\":10}},\"confidenceConfirmations\":{\"0.0\":0,\"1.0\":-1}}" } } } @@ -127,9 +127,8 @@ func Test_ChainReaderConfig(t *testing.T) { }, ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, EventDefinitions: &EventDefinitions{ - GenericTopicNames: map[string]string{"TopicKey1": "TopicVal1"}, - GenericDataWordNames: map[string]uint8{"DataWordKey": 1}, - InputFields: []string{"Event1", "Event2"}, + GenericTopicNames: map[string]string{"TopicKey1": "TopicVal1"}, + GenericDataWordDetails: map[string]DataWordDetail{"DataWordKey": {Name: "DataWordKey"}}, PollingFilter: &PollingFilter{ Topic2: evmtypes.HashArray{common.HexToHash("0x4abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, Topic3: evmtypes.HashArray{common.HexToHash("0x5abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index 6a584413dbe..cd30e8ab3c3 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -7,14 +7,15 @@ import ( chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "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" - "github.com/smartcontractkit/chainlink/v2/core/logger" relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain, lggr logger.Logger) (*targets.WriteTarget, error) { +func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain, gasLimitDefault uint64, lggr logger.Logger) (*targets.WriteTarget, error) { // generate ID based on chain selector id := fmt.Sprintf("write_%v@1.0.0", chain.ID()) chainName, err := chainselectors.NameFromChainId(chain.ID().Uint64()) @@ -41,12 +42,11 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain if err != nil { return nil, fmt.Errorf("failed to marshal contract reader config %v", err) } - cr, err := relayer.NewContractReader(contractReaderConfigEncoded) + cr, err := relayer.NewContractReader(ctx, contractReaderConfigEncoded) if err != nil { return nil, err } - var gasLimit uint64 = 400_000 chainWriterConfig := relayevmtypes.ChainWriterConfig{ Contracts: map[string]*relayevmtypes.ContractConfig{ "forwarder": { @@ -54,9 +54,8 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain Configs: map[string]*relayevmtypes.ChainWriterDefinition{ "report": { ChainSpecificName: "report", - Checker: "simulate", FromAddress: config.FromAddress().Address(), - GasLimit: gasLimit, + GasLimit: gasLimitDefault, }, }, }, @@ -74,5 +73,5 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain return nil, err } - return targets.NewWriteTarget(lggr.Named("WriteTarget"), id, cr, cw, config.ForwarderAddress().String(), gasLimit), nil + return targets.NewWriteTarget(logger.Named(lggr, "WriteTarget"), id, cr, cw, config.ForwarderAddress().String(), gasLimitDefault), nil } diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go index 54e36714226..245fd974783 100644 --- a/core/services/relay/evm/write_target_test.go +++ b/core/services/relay/evm/write_target_test.go @@ -21,6 +21,7 @@ import ( evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + pollermocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -101,6 +102,7 @@ func TestEvmWrite(t *testing.T) { chain := evmmocks.NewChain(t) txManager := txmmocks.NewMockEvmTxManager(t) evmClient := evmclimocks.NewClient(t) + poller := pollermocks.NewLogPoller(t) // This is a very error-prone way to mock an on-chain response to a GetLatestValue("getTransmissionInfo") call // It's a bit of a hack, but it's the best way to do it without a lot of refactoring @@ -111,7 +113,7 @@ func TestEvmWrite(t *testing.T) { chain.On("ID").Return(big.NewInt(11155111)) chain.On("TxManager").Return(txManager) - chain.On("LogPoller").Return(nil) + chain.On("LogPoller").Return(poller) ht := mocks.NewHeadTracker[*types.Head, common.Hash](t) ht.On("LatestAndFinalizedBlock", mock.Anything).Return(&types.Head{}, &types.Head{}, nil) @@ -140,13 +142,14 @@ func TestEvmWrite(t *testing.T) { keyStore := cltest.NewKeyStore(t, db) lggr := logger.TestLogger(t) - relayer, err := relayevm.NewRelayer(lggr, chain, relayevm.RelayerOpts{ + relayer, err := relayevm.NewRelayer(testutils.Context(t), lggr, chain, relayevm.RelayerOpts{ DS: db, CSAETHKeystore: keyStore, CapabilitiesRegistry: evmcapabilities.NewRegistry(lggr), }) require.NoError(t, err) + reportID := [2]byte{0x00, 0x01} reportMetadata := targets.ReportV1Metadata{ Version: 1, WorkflowExecutionID: [32]byte{}, @@ -156,7 +159,7 @@ func TestEvmWrite(t *testing.T) { WorkflowCID: [32]byte{}, WorkflowName: [10]byte{}, WorkflowOwner: [20]byte{}, - ReportID: [2]byte{}, + ReportID: reportID, } reportMetadataBytes, err := reportMetadata.Encode() @@ -169,7 +172,7 @@ func TestEvmWrite(t *testing.T) { "report": reportMetadataBytes, "signatures": signatures, "context": []byte{4, 5}, - "id": []byte{9, 9}, + "id": reportID[:], }, }) require.NoError(t, err) @@ -196,9 +199,11 @@ func TestEvmWrite(t *testing.T) { require.Equal(t, signatures, payload["signatures"]) }).Once() + gasLimitDefault := uint64(400_000) + t.Run("succeeds with valid report", func(t *testing.T) { ctx := testutils.Context(t) - capability, err := evm.NewWriteTarget(ctx, relayer, chain, lggr) + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, lggr) require.NoError(t, err) req := capabilities.CapabilityRequest{ @@ -207,16 +212,13 @@ func TestEvmWrite(t *testing.T) { Inputs: validInputs, } - ch, err := capability.Execute(ctx, req) + _, err = capability.Execute(ctx, req) require.NoError(t, err) - - response := <-ch - require.Nil(t, response.Err) }) t.Run("fails with invalid config", func(t *testing.T) { ctx := testutils.Context(t) - capability, err := evm.NewWriteTarget(ctx, relayer, chain, logger.TestLogger(t)) + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, logger.TestLogger(t)) require.NoError(t, err) invalidConfig, err := values.NewMap(map[string]any{ @@ -236,7 +238,7 @@ func TestEvmWrite(t *testing.T) { t.Run("fails when TXM CreateTransaction returns error", func(t *testing.T) { ctx := testutils.Context(t) - capability, err := evm.NewWriteTarget(ctx, relayer, chain, logger.TestLogger(t)) + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, logger.TestLogger(t)) require.NoError(t, err) req := capabilities.CapabilityRequest{ diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index a2681418cee..913923a9b2f 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -1,5 +1,13 @@ package relay +import ( + "context" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + const ( NetworkEVM = "evm" NetworkCosmos = "cosmos" @@ -19,3 +27,40 @@ var SupportedNetworks = map[string]struct{}{ NetworkDummy: {}, } + +var _ loop.Relayer = (*ServerAdapter)(nil) + +// ServerAdapter extends [loop.RelayerAdapter] by overriding NewPluginProvider to dispatches calls according to `RelayArgs.ProviderType`. +// This should only be used to adapt relayers not running via GRPC in a LOOPP. +type ServerAdapter struct { + types.Relayer +} + +// NewServerAdapter returns a new ServerAdapter. +func NewServerAdapter(r types.Relayer) *ServerAdapter { //nolint:staticcheck + return &ServerAdapter{Relayer: r} +} + +func (r *ServerAdapter) NewPluginProvider(ctx context.Context, rargs types.RelayArgs, pargs types.PluginArgs) (types.PluginProvider, error) { + switch types.OCR2PluginType(rargs.ProviderType) { + case types.Median: + return r.NewMedianProvider(ctx, rargs, pargs) + case types.Functions: + return r.NewFunctionsProvider(ctx, rargs, pargs) + case types.Mercury: + return r.NewMercuryProvider(ctx, rargs, pargs) + case types.OCR2Keeper: + return r.NewAutomationProvider(ctx, rargs, pargs) + case types.OCR3Capability: + return r.NewOCR3CapabilityProvider(ctx, rargs, pargs) + case types.CCIPCommit: + return r.NewCCIPCommitProvider(ctx, rargs, pargs) + case types.CCIPExecution: + return r.NewCCIPExecProvider(ctx, rargs, pargs) + case types.DKG, types.OCR2VRF, types.GenericPlugin: + return r.Relayer.NewPluginProvider(ctx, rargs, pargs) + case types.LLO: + return nil, fmt.Errorf("provider type not supported: %s", rargs.ProviderType) + } + return nil, fmt.Errorf("provider type not recognized: %s", rargs.ProviderType) +} diff --git a/core/services/standardcapabilities/delegate.go b/core/services/standardcapabilities/delegate.go index d072c948469..17e7cf5c12f 100644 --- a/core/services/standardcapabilities/delegate.go +++ b/core/services/standardcapabilities/delegate.go @@ -12,9 +12,20 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/compute" + gatewayconnector "github.com/smartcontractkit/chainlink/v2/core/capabilities/gateway_connector" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" + webapitarget "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/target" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi/trigger" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" "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/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/generic" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" "github.com/smartcontractkit/chainlink/v2/plugins" @@ -26,23 +37,59 @@ type RelayGetter interface { } type Delegate struct { - logger logger.Logger - ds sqlutil.DataSource - jobORM job.ORM - registry core.CapabilitiesRegistry - cfg plugins.RegistrarConfig - monitoringEndpointGen telemetry.MonitoringEndpointGenerator - pipelineRunner pipeline.Runner - relayers RelayGetter + logger logger.Logger + ds sqlutil.DataSource + jobORM job.ORM + registry core.CapabilitiesRegistry + cfg plugins.RegistrarConfig + monitoringEndpointGen telemetry.MonitoringEndpointGenerator + pipelineRunner pipeline.Runner + relayers RelayGetter + gatewayConnectorWrapper *gatewayconnector.ServiceWrapper + ks keystore.Master + peerWrapper *ocrcommon.SingletonPeerWrapper + newOracleFactoryFn func(generic.OracleFactoryParams) (core.OracleFactory, error) isNewlyCreatedJob bool } -func NewDelegate(logger logger.Logger, ds sqlutil.DataSource, jobORM job.ORM, registry core.CapabilitiesRegistry, - cfg plugins.RegistrarConfig, monitoringEndpointGen telemetry.MonitoringEndpointGenerator, pipelineRunner pipeline.Runner, - relayers RelayGetter) *Delegate { - return &Delegate{logger: logger, ds: ds, jobORM: jobORM, registry: registry, cfg: cfg, monitoringEndpointGen: monitoringEndpointGen, pipelineRunner: pipelineRunner, - relayers: relayers, isNewlyCreatedJob: false} +const ( + commandOverrideForWebAPITrigger = "__builtin_web-api-trigger" + commandOverrideForWebAPITarget = "__builtin_web-api-target" + commandOverrideForCustomComputeAction = "__builtin_custom-compute-action" +) + +type NewOracleFactoryFn func(generic.OracleFactoryParams) (core.OracleFactory, error) + +func NewDelegate( + logger logger.Logger, + ds sqlutil.DataSource, + jobORM job.ORM, + registry core.CapabilitiesRegistry, + cfg plugins.RegistrarConfig, + monitoringEndpointGen telemetry.MonitoringEndpointGenerator, + pipelineRunner pipeline.Runner, + relayers RelayGetter, + gatewayConnectorWrapper *gatewayconnector.ServiceWrapper, + ks keystore.Master, + peerWrapper *ocrcommon.SingletonPeerWrapper, + newOracleFactoryFn NewOracleFactoryFn, +) *Delegate { + return &Delegate{ + logger: logger, + ds: ds, + jobORM: jobORM, + registry: registry, + cfg: cfg, + monitoringEndpointGen: monitoringEndpointGen, + pipelineRunner: pipelineRunner, + relayers: relayers, + isNewlyCreatedJob: false, + gatewayConnectorWrapper: gatewayConnectorWrapper, + ks: ks, + peerWrapper: peerWrapper, + newOracleFactoryFn: newOracleFactoryFn, + } } func (d *Delegate) JobType() job.Type { @@ -67,8 +114,152 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return nil, fmt.Errorf("failed to create relayer set: %w", err) } + ocrKeyBundles, err := d.ks.OCR2().GetAll() + if err != nil { + return nil, err + } + + if len(ocrKeyBundles) > 1 { + return nil, fmt.Errorf("expected exactly one OCR key bundle, but found: %d", len(ocrKeyBundles)) + } + + var ocrKeyBundle ocr2key.KeyBundle + if len(ocrKeyBundles) == 0 { + ocrKeyBundle, err = d.ks.OCR2().Create(ctx, chaintype.EVM) + if err != nil { + return nil, errors.Wrap(err, "failed to create OCR key bundle") + } + } else { + ocrKeyBundle = ocrKeyBundles[0] + } + + ethKeyBundles, err := d.ks.Eth().GetAll(ctx) + if err != nil { + return nil, err + } + if len(ethKeyBundles) > 1 { + return nil, fmt.Errorf("expected exactly one ETH key bundle, but found: %d", len(ethKeyBundles)) + } + + var ethKeyBundle ethkey.KeyV2 + if len(ethKeyBundles) == 0 { + ethKeyBundle, err = d.ks.Eth().Create(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to create ETH key bundle") + } + } else { + ethKeyBundle = ethKeyBundles[0] + } + + var oracleFactory core.OracleFactory + // NOTE: special case for custom Oracle Factory for use in tests + if d.newOracleFactoryFn != nil { + oracleFactory, err = d.newOracleFactoryFn(generic.OracleFactoryParams{ + Logger: log, + JobORM: d.jobORM, + JobID: spec.ID, + JobName: spec.Name.ValueOrZero(), + KB: ocrKeyBundle, + Config: spec.StandardCapabilitiesSpec.OracleFactory, + PeerWrapper: d.peerWrapper, + RelayerSet: relayerSet, + TransmitterID: ethKeyBundle.Address.String(), + }) + if err != nil { + return nil, fmt.Errorf("failed to create oracle factory from function: %w", err) + } + } else { + log.Debug("oracleFactoryConfig: ", spec.StandardCapabilitiesSpec.OracleFactory) + + if spec.StandardCapabilitiesSpec.OracleFactory.Enabled && d.peerWrapper == nil { + return nil, errors.New("P2P stack required for Oracle Factory") + } + + oracleFactory, err = generic.NewOracleFactory(generic.OracleFactoryParams{ + Logger: log, + JobORM: d.jobORM, + JobID: spec.ID, + JobName: spec.Name.ValueOrZero(), + KB: ocrKeyBundle, + Config: spec.StandardCapabilitiesSpec.OracleFactory, + PeerWrapper: d.peerWrapper, + RelayerSet: relayerSet, + TransmitterID: ethKeyBundle.Address.String(), + }) + if err != nil { + return nil, fmt.Errorf("failed to create oracle factory: %w", err) + } + } + + // NOTE: special cases for built-in capabilities (to be moved into LOOPPs in the future) + if spec.StandardCapabilitiesSpec.Command == commandOverrideForWebAPITrigger { + if d.gatewayConnectorWrapper == nil { + return nil, errors.New("gateway connector is required for web API Trigger capability") + } + connector := d.gatewayConnectorWrapper.GetGatewayConnector() + triggerSrvc, err := trigger.NewTrigger(spec.StandardCapabilitiesSpec.Config, d.registry, connector, log) + if err != nil { + return nil, fmt.Errorf("failed to create a Web API Trigger service: %w", err) + } + return []job.ServiceCtx{triggerSrvc}, nil + } + + if spec.StandardCapabilitiesSpec.Command == commandOverrideForWebAPITarget { + if d.gatewayConnectorWrapper == nil { + return nil, errors.New("gateway connector is required for web API Target capability") + } + connector := d.gatewayConnectorWrapper.GetGatewayConnector() + if len(spec.StandardCapabilitiesSpec.Config) == 0 { + return nil, errors.New("config is empty") + } + var targetCfg webapi.ServiceConfig + err := toml.Unmarshal([]byte(spec.StandardCapabilitiesSpec.Config), &targetCfg) + if err != nil { + return nil, err + } + lggr := d.logger.Named("WebAPITarget") + handler, err := webapi.NewOutgoingConnectorHandler(connector, targetCfg, capabilities.MethodWebAPITarget, lggr) + if err != nil { + return nil, err + } + capability, err := webapitarget.NewCapability(targetCfg, d.registry, handler, lggr) + if err != nil { + return nil, err + } + return []job.ServiceCtx{capability, handler}, nil + } + + if spec.StandardCapabilitiesSpec.Command == commandOverrideForCustomComputeAction { + if d.gatewayConnectorWrapper == nil { + return nil, errors.New("gateway connector is required for custom compute capability") + } + + if len(spec.StandardCapabilitiesSpec.Config) == 0 { + return nil, errors.New("config is empty") + } + + var fetchCfg webapi.ServiceConfig + err := toml.Unmarshal([]byte(spec.StandardCapabilitiesSpec.Config), &fetchCfg) + if err != nil { + return nil, err + } + lggr := d.logger.Named("ComputeAction") + + handler, err := webapi.NewOutgoingConnectorHandler(d.gatewayConnectorWrapper.GetGatewayConnector(), fetchCfg, capabilities.MethodComputeAction, lggr) + if err != nil { + return nil, err + } + + idGeneratorFn := func() string { + return uuid.New().String() + } + + computeSrvc := compute.NewAction(fetchCfg, log, d.registry, handler, idGeneratorFn) + return []job.ServiceCtx{computeSrvc}, nil + } + standardCapability := newStandardCapabilities(log, spec.StandardCapabilitiesSpec, d.cfg, telemetryService, kvStore, d.registry, errorLog, - pr, relayerSet) + pr, relayerSet, oracleFactory) return []job.ServiceCtx{standardCapability}, nil } @@ -107,6 +298,22 @@ func ValidatedStandardCapabilitiesSpec(tomlString string) (job.Job, error) { return jb, errors.Errorf("standard capabilities command must be set") } + // Skip validation if Oracle Factory is not enabled + if !jb.StandardCapabilitiesSpec.OracleFactory.Enabled { + return jb, nil + } + + // If Oracle Factory is enabled, it must have at least one bootstrap peer + if len(jb.StandardCapabilitiesSpec.OracleFactory.BootstrapPeers) == 0 { + return jb, errors.New("no bootstrap peers found") + } + + // Validate bootstrap peers + _, err = ocrcommon.ParseBootstrapPeers(jb.StandardCapabilitiesSpec.OracleFactory.BootstrapPeers) + if err != nil { + return jb, errors.Wrap(err, "failed to parse bootstrap peers") + } + return jb, nil } diff --git a/core/services/standardcapabilities/delegate_test.go b/core/services/standardcapabilities/delegate_test.go new file mode 100644 index 00000000000..27b6734f911 --- /dev/null +++ b/core/services/standardcapabilities/delegate_test.go @@ -0,0 +1,121 @@ +package standardcapabilities_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" +) + +func Test_ValidatedStandardCapabilitiesSpec(t *testing.T) { + type testCase struct { + name string + tomlString string + expectedError string + expectedSpec *job.StandardCapabilitiesSpec + } + + testCases := []testCase{ + { + name: "invalid TOML string", + tomlString: `[[]`, + expectedError: "toml error on load standard capabilities", + }, + { + name: "incorrect job type", + tomlString: ` + type="nonstandardcapabilities" + `, + expectedError: "standard capabilities unsupported job type", + }, + { + name: "command unset", + tomlString: ` + type="standardcapabilities" + `, + expectedError: "standard capabilities command must be set", + }, + { + name: "invalid oracle config: malformed peer", + tomlString: ` + type="standardcapabilities" + command="path/to/binary" + + [oracle_factory] + enabled=true + bootstrap_peers = [ + "invalid_p2p_id@invalid_ip:1111" + ] + `, + expectedError: "failed to parse bootstrap peers", + }, + { + name: "invalid oracle config: missing bootstrap peers", + tomlString: ` + type="standardcapabilities" + command="path/to/binary" + + [oracle_factory] + enabled=true + `, + expectedError: "no bootstrap peers found", + }, + { + name: "valid spec", + tomlString: ` + type="standardcapabilities" + command="path/to/binary" + `, + }, + { + name: "valid spec with oracle config", + tomlString: ` + type="standardcapabilities" + command="path/to/binary" + + [capabilities] + target = "enabled" + + [oracle_factory] + enabled=true + bootstrap_peers = [ + "12D3KooWEBVwbfdhKnicois7FTYVsBFGFcoMhMCKXQC57BQyZMhz@localhost:6690" + ] + network="evm" + chain_id="31337" + ocr_contract_address="0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6" + `, + expectedSpec: &job.StandardCapabilitiesSpec{ + Command: "path/to/binary", + OracleFactory: job.OracleFactoryConfig{ + Enabled: true, + BootstrapPeers: []string{ + "12D3KooWEBVwbfdhKnicois7FTYVsBFGFcoMhMCKXQC57BQyZMhz@localhost:6690", + }, + OCRContractAddress: "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6", + ChainID: "31337", + Network: "evm", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + jobSpec, err := standardcapabilities.ValidatedStandardCapabilitiesSpec(tc.tomlString) + + if tc.expectedError != "" { + assert.ErrorContains(t, err, tc.expectedError) + } else { + require.NoError(t, err) + } + + if tc.expectedSpec != nil { + assert.EqualValues(t, tc.expectedSpec, jobSpec.StandardCapabilitiesSpec) + } + }) + } +} diff --git a/core/services/standardcapabilities/standard_capabilities.go b/core/services/standardcapabilities/standard_capabilities.go index a8d007d5df8..fe3dad7bb2f 100644 --- a/core/services/standardcapabilities/standard_capabilities.go +++ b/core/services/standardcapabilities/standard_capabilities.go @@ -23,18 +23,23 @@ type standardCapabilities struct { errorLog core.ErrorLog pipelineRunner core.PipelineRunnerService relayerSet core.RelayerSet + oracleFactory core.OracleFactory capabilitiesLoop *loop.StandardCapabilitiesService } -func newStandardCapabilities(log logger.Logger, spec *job.StandardCapabilitiesSpec, +func newStandardCapabilities( + log logger.Logger, + spec *job.StandardCapabilitiesSpec, pluginRegistrar plugins.RegistrarConfig, telemetryService core.TelemetryService, store core.KeyValueStore, CapabilitiesRegistry core.CapabilitiesRegistry, errorLog core.ErrorLog, pipelineRunner core.PipelineRunnerService, - relayerSet core.RelayerSet) *standardCapabilities { + relayerSet core.RelayerSet, + oracleFactory core.OracleFactory, +) *standardCapabilities { return &standardCapabilities{ log: log, spec: spec, @@ -45,6 +50,7 @@ func newStandardCapabilities(log logger.Logger, spec *job.StandardCapabilitiesSp errorLog: errorLog, pipelineRunner: pipelineRunner, relayerSet: relayerSet, + oracleFactory: oracleFactory, } } @@ -73,7 +79,7 @@ func (s *standardCapabilities) Start(ctx context.Context) error { } if err = s.capabilitiesLoop.Service.Initialise(ctx, s.spec.Config, s.telemetryService, s.store, s.CapabilitiesRegistry, s.errorLog, - s.pipelineRunner, s.relayerSet); err != nil { + s.pipelineRunner, s.relayerSet, s.oracleFactory); err != nil { return fmt.Errorf("error initialising standard capabilities service: %v", err) } diff --git a/core/services/streams/stream.go b/core/services/streams/stream.go index 8825cd3b342..b65c6dc12f6 100644 --- a/core/services/streams/stream.go +++ b/core/services/streams/stream.go @@ -3,12 +3,10 @@ package streams import ( "context" "fmt" - "math/big" "sync" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/utils" ) type Runner interface { @@ -94,35 +92,3 @@ func (s *stream) executeRun(ctx context.Context) (*pipeline.Run, pipeline.TaskRu return run, trrs, err } - -// ExtractBigInt returns a result of a pipeline run that returns one single -// decimal result, as a *big.Int. -// This acts as a reference/example method, other methods can be implemented to -// extract any desired type that matches a particular pipeline run output. -// Returns error on parse errors: if results are wrong type -func ExtractBigInt(trrs pipeline.TaskRunResults) (*big.Int, error) { - // pipeline.TaskRunResults comes ordered asc by index, this is guaranteed - // by the pipeline executor - finaltrrs := trrs.Terminals() - - if len(finaltrrs) != 1 { - return nil, fmt.Errorf("invalid number of results, expected: 1, got: %d", len(finaltrrs)) - } - res := finaltrrs[0].Result - if res.Error != nil { - return nil, res.Error - } - val, err := toBigInt(res.Value) - if err != nil { - return nil, fmt.Errorf("failed to parse BenchmarkPrice: %w", err) - } - return val, nil -} - -func toBigInt(val interface{}) (*big.Int, error) { - dec, err := utils.ToDecimal(val) - if err != nil { - return nil, err - } - return dec.BigInt(), nil -} diff --git a/core/services/streams/stream_registry.go b/core/services/streams/stream_registry.go index 9d3fcda7109..9ab2df11d33 100644 --- a/core/services/streams/stream_registry.go +++ b/core/services/streams/stream_registry.go @@ -4,14 +4,14 @@ import ( "fmt" "sync" - llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) // alias for easier refactoring -type StreamID = llotypes.StreamID +type StreamID = llo.StreamID type Registry interface { Getter diff --git a/core/services/streams/stream_test.go b/core/services/streams/stream_test.go index 61e51878802..78174138121 100644 --- a/core/services/streams/stream_test.go +++ b/core/services/streams/stream_test.go @@ -2,7 +2,6 @@ package streams import ( "context" - "math/big" "testing" "time" @@ -99,35 +98,3 @@ succeed; }) }) } - -func Test_ExtractBigInt(t *testing.T) { - t.Run("wrong number of inputs", func(t *testing.T) { - trrs := []pipeline.TaskRunResult{} - - _, err := ExtractBigInt(trrs) - assert.EqualError(t, err, "invalid number of results, expected: 1, got: 0") - }) - t.Run("wrong type", func(t *testing.T) { - trrs := []pipeline.TaskRunResult{ - { - Result: pipeline.Result{Value: []byte{1, 2, 3}}, - Task: &MockTask{}, - }, - } - - _, err := ExtractBigInt(trrs) - assert.EqualError(t, err, "failed to parse BenchmarkPrice: type []uint8 cannot be converted to decimal.Decimal ([1 2 3])") - }) - t.Run("correct inputs", func(t *testing.T) { - trrs := []pipeline.TaskRunResult{ - { - Result: pipeline.Result{Value: "122.345"}, - Task: &MockTask{}, - }, - } - - val, err := ExtractBigInt(trrs) - require.NoError(t, err) - assert.Equal(t, big.NewInt(122), val) - }) -} diff --git a/core/services/synchronization/common.go b/core/services/synchronization/common.go index a6c0191e3a7..9145a3c9ace 100644 --- a/core/services/synchronization/common.go +++ b/core/services/synchronization/common.go @@ -22,6 +22,7 @@ const ( OCR2S4 TelemetryType = "ocr2-s4" OCR2Median TelemetryType = "ocr2-median" OCR3Mercury TelemetryType = "ocr3-mercury" + OCR3DataFeeds TelemetryType = "ocr3-data-feeds" AutomationCustom TelemetryType = "automation-custom" OCR3Automation TelemetryType = "ocr3-automation" OCR3Rebalancer TelemetryType = "ocr3-rebalancer" diff --git a/core/services/synchronization/metrics.go b/core/services/synchronization/metrics.go new file mode 100644 index 00000000000..d6bafb7b0d6 --- /dev/null +++ b/core/services/synchronization/metrics.go @@ -0,0 +1,33 @@ +package synchronization + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +var ( + TelemetryClientConnectionStatus = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "telemetry_client_connection_status", + Help: "Status of the connection to the telemetry ingress server", + }, []string{"endpoint"}) + + TelemetryClientMessagesSent = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "telemetry_client_messages_sent", + Help: "Number of telemetry messages sent to the telemetry ingress server", + }, []string{"endpoint", "telemetry_type"}) + + TelemetryClientMessagesSendErrors = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "telemetry_client_messages_send_errors", + Help: "Number of telemetry messages that failed to send to the telemetry ingress server", + }, []string{"endpoint", "telemetry_type"}) + + TelemetryClientMessagesDropped = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "telemetry_client_messages_dropped", + Help: "Number of telemetry messages dropped", + }, []string{"endpoint", "telemetry_type"}) + + TelemetryClientWorkers = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "telemetry_client_workers", + Help: "Number of telemetry workers", + }, []string{"endpoint", "telemetry_type"}) +) diff --git a/core/services/synchronization/telem/telem.pb.go b/core/services/synchronization/telem/telem.pb.go index d51b9628e22..8ededa8ce1c 100644 --- a/core/services/synchronization/telem/telem.pb.go +++ b/core/services/synchronization/telem/telem.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v4.25.1 +// protoc v5.28.0 // source: core/services/synchronization/telem/telem.proto package telem diff --git a/core/services/synchronization/telem/telem_automation_custom.pb.go b/core/services/synchronization/telem/telem_automation_custom.pb.go index 30ddce6f790..7c498be9fde 100644 --- a/core/services/synchronization/telem/telem_automation_custom.pb.go +++ b/core/services/synchronization/telem/telem_automation_custom.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v4.25.1 +// protoc v5.28.0 // source: core/services/synchronization/telem/telem_automation_custom.proto package telem diff --git a/core/services/synchronization/telem/telem_enhanced_ea.pb.go b/core/services/synchronization/telem/telem_enhanced_ea.pb.go index c8983a06fea..687ff7ab4e9 100644 --- a/core/services/synchronization/telem/telem_enhanced_ea.pb.go +++ b/core/services/synchronization/telem/telem_enhanced_ea.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v4.25.1 +// protoc v5.28.0 // source: core/services/synchronization/telem/telem_enhanced_ea.proto package telem diff --git a/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go b/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go index 856619e1931..09eed12ee8a 100644 --- a/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go +++ b/core/services/synchronization/telem/telem_enhanced_ea_mercury.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v4.25.1 +// protoc v5.28.0 // source: core/services/synchronization/telem/telem_enhanced_ea_mercury.proto package telem @@ -81,6 +81,7 @@ type EnhancedEAMercury struct { DpBid float64 `protobuf:"fixed64,3,opt,name=dp_bid,json=dpBid,proto3" json:"dp_bid,omitempty"` DpAsk float64 `protobuf:"fixed64,4,opt,name=dp_ask,json=dpAsk,proto3" json:"dp_ask,omitempty"` DpInvariantViolationDetected bool `protobuf:"varint,33,opt,name=dp_invariant_violation_detected,json=dpInvariantViolationDetected,proto3" json:"dp_invariant_violation_detected,omitempty"` + BridgeRequestData string `protobuf:"bytes,35,opt,name=bridge_request_data,json=bridgeRequestData,proto3" json:"bridge_request_data,omitempty"` // v1 fields (block range) CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=current_block_number,json=currentBlockNumber,proto3" json:"current_block_number,omitempty"` CurrentBlockHash string `protobuf:"bytes,6,opt,name=current_block_hash,json=currentBlockHash,proto3" json:"current_block_hash,omitempty"` @@ -100,7 +101,7 @@ type EnhancedEAMercury struct { ProviderDataStreamEstablished int64 `protobuf:"varint,12,opt,name=provider_data_stream_established,json=providerDataStreamEstablished,proto3" json:"provider_data_stream_established,omitempty"` ProviderIndicatedTime int64 `protobuf:"varint,13,opt,name=provider_indicated_time,json=providerIndicatedTime,proto3" json:"provider_indicated_time,omitempty"` Feed string `protobuf:"bytes,14,opt,name=feed,proto3" json:"feed,omitempty"` - // v1+v2+v3 + // v1+v2+v3+v4 ObservationBenchmarkPrice int64 `protobuf:"varint,15,opt,name=observation_benchmark_price,json=observationBenchmarkPrice,proto3" json:"observation_benchmark_price,omitempty"` // This value overflows, will be reserved and removed in future versions ObservationBenchmarkPriceString string `protobuf:"bytes,22,opt,name=observation_benchmark_price_string,json=observationBenchmarkPriceString,proto3" json:"observation_benchmark_price_string,omitempty"` // v1+v3 @@ -190,6 +191,13 @@ func (x *EnhancedEAMercury) GetDpInvariantViolationDetected() bool { return false } +func (x *EnhancedEAMercury) GetBridgeRequestData() string { + if x != nil { + return x.BridgeRequestData + } + return "" +} + func (x *EnhancedEAMercury) GetCurrentBlockNumber() int64 { if x != nil { return x.CurrentBlockNumber @@ -393,7 +401,7 @@ var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_raw 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x65, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x65, 0x61, 0x5f, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0xfa, 0x0c, 0x0a, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0xaa, 0x0d, 0x0a, 0x11, 0x45, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x45, 0x41, 0x4d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, @@ -409,6 +417,9 @@ var file_core_services_synchronization_telem_telem_enhanced_ea_mercury_proto_raw 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x64, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x12, 0x2e, 0x0a, 0x13, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x23, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, diff --git a/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto b/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto index bb41ff86ee3..d57b7ca836a 100644 --- a/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto +++ b/core/services/synchronization/telem/telem_enhanced_ea_mercury.proto @@ -19,6 +19,7 @@ message EnhancedEAMercury { double dp_bid=3; double dp_ask=4; bool dp_invariant_violation_detected=33; + string bridge_request_data = 35; // v1 fields (block range) int64 current_block_number=5; @@ -43,7 +44,7 @@ message EnhancedEAMercury { string feed=14; - // v1+v2+v3 + // v1+v2+v3+v4 int64 observation_benchmark_price=15; // This value overflows, will be reserved and removed in future versions string observation_benchmark_price_string = 22; // v1+v3 diff --git a/core/services/synchronization/telem/telem_functions_request.pb.go b/core/services/synchronization/telem/telem_functions_request.pb.go index 89aa9e3fe37..1a67d1223a8 100644 --- a/core/services/synchronization/telem/telem_functions_request.pb.go +++ b/core/services/synchronization/telem/telem_functions_request.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v4.25.1 +// protoc v5.28.0 // source: core/services/synchronization/telem/telem_functions_request.proto package telem diff --git a/core/services/synchronization/telem/telem_head_report.pb.go b/core/services/synchronization/telem/telem_head_report.pb.go index 18e4532472b..c4101d06560 100644 --- a/core/services/synchronization/telem/telem_head_report.pb.go +++ b/core/services/synchronization/telem/telem_head_report.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.1 +// protoc-gen-go v1.34.2 +// protoc v5.28.0 // source: core/services/synchronization/telem/telem_head_report.proto package telem @@ -25,7 +25,7 @@ type HeadReportRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Chain string `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` + ChainID string `protobuf:"bytes,1,opt,name=chainID,proto3" json:"chainID,omitempty"` Latest *Block `protobuf:"bytes,2,opt,name=latest,proto3" json:"latest,omitempty"` Finalized *Block `protobuf:"bytes,3,opt,name=finalized,proto3,oneof" json:"finalized,omitempty"` } @@ -62,9 +62,9 @@ func (*HeadReportRequest) Descriptor() ([]byte, []int) { return file_core_services_synchronization_telem_telem_head_report_proto_rawDescGZIP(), []int{0} } -func (x *HeadReportRequest) GetChain() string { +func (x *HeadReportRequest) GetChainID() string { if x != nil { - return x.Chain + return x.ChainID } return "" } @@ -153,26 +153,27 @@ var file_core_services_synchronization_telem_telem_head_report_proto_rawDesc = [ 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, - 0x65, 0x6c, 0x65, 0x6d, 0x22, 0x8e, 0x01, 0x0a, 0x11, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x12, 0x24, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x51, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1c, - 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6c, 0x65, 0x6d, 0x22, 0x92, 0x01, 0x0a, 0x11, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x44, 0x12, 0x24, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x51, 0x0a, 0x05, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x42, 0x4e, 0x5a, 0x4c, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72, 0x74, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -188,7 +189,7 @@ func file_core_services_synchronization_telem_telem_head_report_proto_rawDescGZI } var file_core_services_synchronization_telem_telem_head_report_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_core_services_synchronization_telem_telem_head_report_proto_goTypes = []interface{}{ +var file_core_services_synchronization_telem_telem_head_report_proto_goTypes = []any{ (*HeadReportRequest)(nil), // 0: telem.HeadReportRequest (*Block)(nil), // 1: telem.Block } @@ -208,7 +209,7 @@ func file_core_services_synchronization_telem_telem_head_report_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_core_services_synchronization_telem_telem_head_report_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_core_services_synchronization_telem_telem_head_report_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*HeadReportRequest); i { case 0: return &v.state @@ -220,7 +221,7 @@ func file_core_services_synchronization_telem_telem_head_report_proto_init() { return nil } } - file_core_services_synchronization_telem_telem_head_report_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_core_services_synchronization_telem_telem_head_report_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*Block); i { case 0: return &v.state @@ -233,7 +234,7 @@ func file_core_services_synchronization_telem_telem_head_report_proto_init() { } } } - file_core_services_synchronization_telem_telem_head_report_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_core_services_synchronization_telem_telem_head_report_proto_msgTypes[0].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/core/services/synchronization/telem/telem_wsrpc.pb.go b/core/services/synchronization/telem/telem_wsrpc.pb.go index e4028b4de49..e7df2090e4f 100644 --- a/core/services/synchronization/telem/telem_wsrpc.pb.go +++ b/core/services/synchronization/telem/telem_wsrpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-wsrpc. DO NOT EDIT. // versions: // - protoc-gen-go-wsrpc v0.0.1 -// - protoc v4.25.1 +// - protoc v5.28.0 package telem diff --git a/core/services/synchronization/telemetry_ingress_batch_client.go b/core/services/synchronization/telemetry_ingress_batch_client.go index 26ce1e3066a..8ca03d67ef6 100644 --- a/core/services/synchronization/telemetry_ingress_batch_client.go +++ b/core/services/synchronization/telemetry_ingress_batch_client.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/wsrpc" "github.com/smartcontractkit/wsrpc/examples/simple/keys" + "google.golang.org/grpc/connectivity" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -57,9 +58,11 @@ type telemetryIngressBatchClient struct { telemSendTimeout time.Duration workers map[string]*telemetryIngressBatchWorker - workersMutex sync.Mutex + workersMutex sync.RWMutex useUniConn bool + + healthMonitorCancel context.CancelFunc } // NewTelemetryIngressBatchClient returns a client backed by wsrpc that @@ -127,14 +130,43 @@ func (tc *telemetryIngressBatchClient) start(ctx context.Context) error { } tc.telemClient = telemPb.NewTelemClient(conn) tc.closeFn = func() error { conn.Close(); return nil } + tc.startHealthMonitoring(ctx, conn) } } return nil } +// startHealthMonitoring starts a goroutine to monitor the connection state and update other relevant metrics every 5 seconds +func (tc *telemetryIngressBatchClient) startHealthMonitoring(ctx context.Context, conn *wsrpc.ClientConn) { + _, cancel := context.WithCancel(ctx) + tc.healthMonitorCancel = cancel + + tc.eng.Go(func(ctx context.Context) { + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + // Check the connection state + connected := float64(0) + if conn.GetState() == connectivity.Ready { + connected = float64(1) + } + TelemetryClientConnectionStatus.WithLabelValues(tc.url.String()).Set(connected) + case <-ctx.Done(): + return + } + } + }) +} + // Close disconnects the wsrpc client from the ingress server and waits for all workers to exit func (tc *telemetryIngressBatchClient) close() error { + if tc.healthMonitorCancel != nil { + tc.healthMonitorCancel() + } if (tc.useUniConn && tc.connected.Load()) || !tc.useUniConn { return tc.closeFn() } @@ -197,11 +229,14 @@ func (tc *telemetryIngressBatchClient) findOrCreateWorker(payload TelemPayload) payload.TelemType, tc.eng, tc.logging, + tc.url.String(), ) tc.eng.GoTick(timeutil.NewTicker(func() time.Duration { return tc.telemSendInterval }), worker.Send) tc.workers[workerKey] = worker + + TelemetryClientWorkers.WithLabelValues(tc.url.String(), string(payload.TelemType)).Inc() } return worker diff --git a/core/services/synchronization/telemetry_ingress_batch_worker.go b/core/services/synchronization/telemetry_ingress_batch_worker.go index 7eca26f02c9..9fb2a194ad2 100644 --- a/core/services/synchronization/telemetry_ingress_batch_worker.go +++ b/core/services/synchronization/telemetry_ingress_batch_worker.go @@ -25,6 +25,9 @@ type telemetryIngressBatchWorker struct { logging bool lggr logger.Logger dropMessageCount atomic.Uint32 + + // endpointURL is used for reporting metrics + endpointURL string } // NewTelemetryIngressBatchWorker returns a worker for a given contractID that can send @@ -38,6 +41,7 @@ func NewTelemetryIngressBatchWorker( telemType TelemetryType, lggr logger.Logger, logging bool, + endpointURL string, ) *telemetryIngressBatchWorker { return &telemetryIngressBatchWorker{ telemSendTimeout: telemSendTimeout, @@ -48,6 +52,7 @@ func NewTelemetryIngressBatchWorker( telemType: telemType, logging: logging, lggr: logger.Named(lggr, "TelemetryIngressBatchWorker"), + endpointURL: endpointURL, } } @@ -65,8 +70,10 @@ func (tw *telemetryIngressBatchWorker) Send(ctx context.Context) { if err != nil { tw.lggr.Warnf("Could not send telemetry: %v", err) + TelemetryClientMessagesSendErrors.WithLabelValues(tw.endpointURL, string(tw.telemType)).Inc() return } + TelemetryClientMessagesSent.WithLabelValues(tw.endpointURL, string(tw.telemType)).Inc() if tw.logging { tw.lggr.Debugw("Successfully sent telemetry to ingress server", "contractID", telemBatchReq.ContractId, "telemType", telemBatchReq.TelemetryType, "telemetry", telemBatchReq.Telemetry) } @@ -86,6 +93,8 @@ func (tw *telemetryIngressBatchWorker) Send(ctx context.Context) { // etc... func (tw *telemetryIngressBatchWorker) logBufferFullWithExpBackoff(payload TelemPayload) { count := tw.dropMessageCount.Add(1) + TelemetryClientMessagesDropped.WithLabelValues(tw.endpointURL, string(tw.telemType)).Inc() + if count > 0 && (count%100 == 0 || count&(count-1) == 0) { tw.lggr.Warnw("telemetry ingress client buffer full, dropping message", "telemetry", payload.Telemetry, "droppedCount", count) } diff --git a/core/services/synchronization/telemetry_ingress_batch_worker_test.go b/core/services/synchronization/telemetry_ingress_batch_worker_test.go index bf44ee9195a..64166252a8f 100644 --- a/core/services/synchronization/telemetry_ingress_batch_worker_test.go +++ b/core/services/synchronization/telemetry_ingress_batch_worker_test.go @@ -28,6 +28,7 @@ func TestTelemetryIngressWorker_BuildTelemBatchReq(t *testing.T) { synchronization.OCR, logger.TestLogger(t), false, + "test-endpoint", ) chTelemetry <- telemPayload diff --git a/core/services/telemetry/manager.go b/core/services/telemetry/manager.go index 73a94b4b127..7b788c4806c 100644 --- a/core/services/telemetry/manager.go +++ b/core/services/telemetry/manager.go @@ -75,7 +75,7 @@ func (m *Manager) GenMonitoringEndpoint(network string, chainID string, contract e, found := m.getEndpoint(network, chainID) if !found { - m.eng.Warnf("no telemetry endpoint found for network %q chainID %q, telemetry %q for contactID %q will NOT be sent", network, chainID, telemType, contractID) + m.eng.Warnf("no telemetry endpoint found for network %q chainID %q, telemetry %q for contractID %q will NOT be sent", network, chainID, telemType, contractID) return &NoopAgent{} } diff --git a/core/services/versioning/orm_test.go b/core/services/versioning/orm_test.go index 3504c2bc772..44c63f60d04 100644 --- a/core/services/versioning/orm_test.go +++ b/core/services/versioning/orm_test.go @@ -97,6 +97,86 @@ func Test_Version_CheckVersion(t *testing.T) { assert.Equal(t, "9.9.8", dbv.String()) } +func TestORM_CheckVersion_CCIP(t *testing.T) { + ctx := testutils.Context(t) + db := pgtest.NewSqlxDB(t) + + lggr := logger.TestLogger(t) + + orm := NewORM(db, lggr) + + tests := []struct { + name string + currentVersion string + newVersion string + expectedError bool + }{ + { + name: "ccip patch version bump from 0 -> 2", + currentVersion: "2.5.0-ccip1.4.0", + newVersion: "2.5.0-ccip1.4.2", + expectedError: false, + }, + { + name: "ccip patch downgrade errors", + currentVersion: "2.5.0-ccip1.4.2", + newVersion: "2.5.0-ccip1.4.1", + expectedError: true, + }, + { + name: "ccip patch version bump from 2 -> 10", + currentVersion: "2.5.0-ccip1.4.2", + newVersion: "2.5.0-ccip1.4.10", + expectedError: false, + }, + { + name: "ccip patch version bump from 9 -> 101", + currentVersion: "2.5.0-ccip1.4.9", + newVersion: "2.5.0-ccip1.4.101", + expectedError: false, + }, + { + name: "upgrading only core version", + currentVersion: "2.5.0-ccip1.4.10", + newVersion: "2.6.0-ccip1.4.10", + expectedError: false, + }, + { + name: "downgrading only core version errors", + currentVersion: "2.6.0-ccip1.4.10", + newVersion: "2.5.0-ccip1.4.10", + expectedError: true, + }, + { + name: "upgrading both core and ccip version", + currentVersion: "2.5.0-ccip1.4.10", + newVersion: "2.6.0-ccip1.4.11", + expectedError: false, + }, + { + name: "upgrading both core and ccip version but minor version", + currentVersion: "2.5.0-ccip1.4.10", + newVersion: "2.6.0-ccip1.5.0", + expectedError: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := db.ExecContext(ctx, `TRUNCATE node_versions;`) + require.NoError(t, err) + + require.NoError(t, orm.UpsertNodeVersion(ctx, NewNodeVersion(test.currentVersion))) + _, _, err = CheckVersion(ctx, db, lggr, test.newVersion) + if test.expectedError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + func TestORM_NodeVersion_FindLatestNodeVersion(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index 9718dc376a7..7f94e98ff9f 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -40,7 +40,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/services/vrf" vrf_mocks "github.com/smartcontractkit/chainlink/v2/core/services/vrf/mocks" @@ -88,8 +87,7 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(51))) jrm := job.NewORM(db, prm, btORM, ks, lggr) t.Cleanup(func() { assert.NoError(t, jrm.Close()) }) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) pr := pipeline.NewRunner(prm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ks.Eth(), ks.VRF(), lggr, nil, nil) require.NoError(t, ks.Unlock(ctx, testutils.Password)) k, err2 := ks.Eth().Create(testutils.Context(t), testutils.FixtureChainID) diff --git a/core/services/vrf/extraargs/types.go b/core/services/vrf/extraargs/types.go index eecd0bfa334..540de0f015a 100644 --- a/core/services/vrf/extraargs/types.go +++ b/core/services/vrf/extraargs/types.go @@ -13,7 +13,7 @@ const boolAbiType = `[{ "type": "bool" }]` var extraArgsV1Tag = crypto.Keccak256([]byte("VRF ExtraArgsV1"))[:4] -func FromExtraArgsV1(extraArgs []byte) (nativePayment bool, err error) { +func DecodeV1(extraArgs []byte) (nativePayment bool, err error) { decodedBool, err := utils.ABIDecode(boolAbiType, extraArgs[functionSignatureLength:]) if err != nil { return false, fmt.Errorf("failed to decode 0x%x to bool", extraArgs[functionSignatureLength:]) @@ -25,7 +25,7 @@ func FromExtraArgsV1(extraArgs []byte) (nativePayment bool, err error) { return nativePayment, nil } -func ExtraArgsV1(nativePayment bool) ([]byte, error) { +func EncodeV1(nativePayment bool) ([]byte, error) { encodedArgs, err := utils.ABIEncode(boolAbiType, nativePayment) if err != nil { return nil, err diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index 74006639c6e..629a45bc9de 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -16,11 +16,11 @@ import ( "gopkg.in/guregu/null.v4" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -30,6 +30,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) func TestIntegration_VRF_JPV2(t *testing.T) { @@ -75,7 +76,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) { cu.Backend.Commit() } var runs []pipeline.Run - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { runs, err = app.PipelineORM().GetAllRuns(ctx) require.NoError(t, err) // It possible that we send the test request @@ -84,7 +85,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) { // keep blocks coming in for the lb to send the backfilled logs. cu.Backend.Commit() return len(runs) == 2 && runs[0].State == pipeline.RunStatusCompleted && runs[1].State == pipeline.RunStatusCompleted - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 1*time.Second) assert.Equal(t, pipeline.RunErrors([]null.String{{}}), runs[0].FatalErrors) assert.Equal(t, 4, len(runs[0].PipelineTaskRuns)) assert.Equal(t, 4, len(runs[1].PipelineTaskRuns)) @@ -96,16 +97,16 @@ func TestIntegration_VRF_JPV2(t *testing.T) { require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, jb.ID)) // Ensure the eth transaction gets confirmed on chain. - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { orm := txmgr.NewTxStore(app.GetDB(), app.GetLogger()) uc, err2 := orm.CountUnconfirmedTransactions(ctx, key1.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 - }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 100*time.Millisecond) // Assert the request was fulfilled on-chain. var rf []*solidity_vrf_coordinator_interface.VRFCoordinatorRandomnessRequestFulfilled - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { rfIterator, err2 := cu.RootContract.FilterRandomnessRequestFulfilled(nil) require.NoError(t, err2, "failed to subscribe to RandomnessRequest logs") rf = nil @@ -113,7 +114,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) { rf = append(rf, rfIterator.Event) } return len(rf) == 2 - }, testutils.WaitTimeout(t), 500*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 500*time.Millisecond) // Check that each sending address sent one transaction n1, err := cu.Backend.PendingNonceAt(ctx, key1.Address) @@ -197,12 +198,12 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) var runs []pipeline.Run - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { runs, err = app.PipelineORM().GetAllRuns(ctx) require.NoError(t, err) cu.Backend.Commit() return len(runs) == 1 && runs[0].State == pipeline.RunStatusCompleted - }, 10*time.Second, 1*time.Second).Should(gomega.BeTrue()) + }, 10*time.Second, 1*time.Second) assert.Equal(t, pipeline.RunErrors([]null.String{{}}), runs[0].FatalErrors) assert.Equal(t, 4, len(runs[0].PipelineTaskRuns)) assert.NotNil(t, 0, runs[0].Outputs.Val) @@ -213,15 +214,15 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, bhsJob.ID)) // Ensure the eth transaction gets confirmed on chain. - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { orm := txmgr.NewTxStore(app.GetDB(), app.GetLogger()) uc, err2 := orm.CountUnconfirmedTransactions(ctx, key.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 - }, 5*time.Second, 100*time.Millisecond).Should(gomega.BeTrue()) + }, 5*time.Second, 100*time.Millisecond) // Assert the request was fulfilled on-chain. - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { rfIterator, err := cu.RootContract.FilterRandomnessRequestFulfilled(nil) require.NoError(t, err, "failed to subscribe to RandomnessRequest logs") var rf []*solidity_vrf_coordinator_interface.VRFCoordinatorRandomnessRequestFulfilled @@ -229,7 +230,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { rf = append(rf, rfIterator.Event) } return len(rf) == 1 - }, 5*time.Second, 500*time.Millisecond).Should(gomega.BeTrue()) + }, 5*time.Second, 500*time.Millisecond) } func createVRFJobRegisterKey(t *testing.T, u vrftesthelpers.CoordinatorUniverse, app *cltest.TestApplication, incomingConfs int) (job.Job, vrfkey.KeyV2) { diff --git a/core/services/vrf/v2/bhs_feeder_test.go b/core/services/vrf/v2/bhs_feeder_test.go index b39fd0dec7f..d3e0008f18b 100644 --- a/core/services/vrf/v2/bhs_feeder_test.go +++ b/core/services/vrf/v2/bhs_feeder_test.go @@ -12,10 +12,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) func TestStartHeartbeats(t *testing.T) { diff --git a/core/services/vrf/v2/coordinator_v2x_interface.go b/core/services/vrf/v2/coordinator_v2x_interface.go index 31621562588..35e8bcd4709 100644 --- a/core/services/vrf/v2/coordinator_v2x_interface.go +++ b/core/services/vrf/v2/coordinator_v2x_interface.go @@ -250,7 +250,7 @@ func (c *coordinatorV2_5) ParseRandomWordsFulfilled(log types.Log) (RandomWordsF } func (c *coordinatorV2_5) RequestRandomWords(opts *bind.TransactOpts, keyHash [32]byte, subID *big.Int, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, payInEth bool) (*types.Transaction, error) { - extraArgs, err := extraargs.ExtraArgsV1(payInEth) + extraArgs, err := extraargs.EncodeV1(payInEth) if err != nil { return nil, err } @@ -569,7 +569,7 @@ func (r *v2_5RandomWordsRequested) CallbackGasLimit() uint32 { } func (r *v2_5RandomWordsRequested) NativePayment() bool { - nativePayment, err := extraargs.FromExtraArgsV1(r.event.ExtraArgs) + nativePayment, err := extraargs.DecodeV1(r.event.ExtraArgs) if err != nil { panic(err) } @@ -1073,7 +1073,7 @@ func (r *RequestCommitment) NativePayment() bool { if r.VRFVersion == vrfcommon.V2 { return false } - nativePayment, err := extraargs.FromExtraArgsV1(r.V2Plus.ExtraArgs) + nativePayment, err := extraargs.DecodeV1(r.V2Plus.ExtraArgs) if err != nil { panic(err) } diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index d61779c5714..91af38c0162 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -30,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_external_sub_owner_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_transparent_upgradeable_proxy" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -41,6 +40,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) func testSingleConsumerHappyPath( @@ -698,13 +698,13 @@ func testSingleConsumerNeedsTopUp( uni.backend.Commit() // Wait for fulfillment to go through. - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { uni.backend.Commit() runs, err := app.PipelineORM().GetAllRuns(ctx) require.NoError(t, err) t.Log("assert 2", "runs", len(runs)) return len(runs) == 1 - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 1*time.Second) // Mine the fulfillment. Need to wait for Txm to mark the tx as confirmed // so that we can actually see the event on the simulated chain. @@ -1713,7 +1713,7 @@ func testMaliciousConsumer( // We expect the request to be serviced // by the node. var attempts []txmgr.TxAttempt - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { attempts, _, err = app.TxmStorageService().TxAttempts(ctx, 0, 1000) require.NoError(t, err) // It possible that we send the test request @@ -1723,7 +1723,7 @@ func testMaliciousConsumer( t.Log("attempts", attempts) uni.backend.Commit() return len(attempts) == 1 && attempts[0].Tx.State == txmgrcommon.TxConfirmed - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 1*time.Second) // The fulfillment tx should succeed ch, err := app.GetRelayers().LegacyEVMChains().Get(evmtest.MustGetDefaultChainID(t, config.EVMConfigs()).String()) @@ -1863,7 +1863,7 @@ func testReplayOldRequestsOnStartUp( require.NoError(t, err) // Wait until all jobs are active and listening for logs - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { if jb.Type == job.VRF { @@ -1871,7 +1871,7 @@ func testReplayOldRequestsOnStartUp( } } return false - }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 100*time.Millisecond) // Wait for fulfillment to be queued. gomega.NewGomegaWithT(t).Eventually(func() bool { diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go index 53baaa0eda3..b4c47c3e0b9 100644 --- a/core/services/vrf/v2/integration_v2_plus_test.go +++ b/core/services/vrf/v2/integration_v2_plus_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -40,7 +41,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_consumer_example" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_reverting_example" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -51,6 +51,7 @@ import ( v22 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v2" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) type coordinatorV2PlusUniverse struct { @@ -965,7 +966,7 @@ func requestAndEstimateFulfillmentCost( requestLog := FindLatestRandomnessRequestedLog(t, uni.rootContract, vrfkey.PublicKey.MustHash(), nil) s, err := proof.BigToSeed(requestLog.PreSeed()) require.NoError(t, err) - extraArgs, err := extraargs.ExtraArgsV1(nativePayment) + extraArgs, err := extraargs.EncodeV1(nativePayment) require.NoError(t, err) proof, rc, err := proof.GenerateProofResponseV2Plus(app.GetKeyStore().VRF(), vrfkey.ID(), proof.PreSeedDataV2Plus{ PreSeed: s, diff --git a/core/services/vrf/v2/integration_v2_reverted_txns_test.go b/core/services/vrf/v2/integration_v2_reverted_txns_test.go index 25e3afcf751..1de471c6a2c 100644 --- a/core/services/vrf/v2/integration_v2_reverted_txns_test.go +++ b/core/services/vrf/v2/integration_v2_reverted_txns_test.go @@ -27,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_external_sub_owner_example" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -37,6 +36,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) var ( @@ -455,7 +455,7 @@ func createVRFJobsNew( vrfKeyIDs = append(vrfKeyIDs, vrfkey.ID()) } // Wait until all jobs are active and listening for logs - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jbs := app.JobSpawner().ActiveJobs() var count int for _, jb := range jbs { @@ -464,7 +464,7 @@ func createVRFJobsNew( } } return count == len(fromKeys) - }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 100*time.Millisecond) // Unfortunately the lb needs heads to be able to backfill logs to new subscribers. // To avoid confirming // TODO: it could just backfill immediately upon receiving a new subscriber? (though would diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 178b555667b..4869cca0926 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -63,7 +63,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_wrapper_consumer_example" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -74,7 +73,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" v1 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/v1" @@ -83,6 +81,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) var defaultMaxGasPrice = uint64(1e12) @@ -580,7 +579,7 @@ func createVRFJobs( jobs = append(jobs, jb) } // Wait until all jobs are active and listening for logs - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jbs := app.JobSpawner().ActiveJobs() var count int for _, jb := range jbs { @@ -589,7 +588,7 @@ func createVRFJobs( } } return count == len(fromKeys) - }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 100*time.Millisecond) // Unfortunately the lb needs heads to be able to backfill logs to new subscribers. // To avoid confirming // TODO: it could just backfill immediately upon receiving a new subscriber? (though would @@ -790,7 +789,7 @@ func mine(t *testing.T, requestID, subID *big.Int, backend *backends.SimulatedBa t.Errorf("unsupported vrf version %s", vrfVersion) } - return gomega.NewWithT(t).Eventually(func() bool { + return assert.Eventually(t, func() bool { backend.Commit() txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, chainId) require.NoError(t, err) @@ -802,7 +801,7 @@ func mine(t *testing.T, requestID, subID *big.Int, backend *backends.SimulatedBa } } return false - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), time.Second) } func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend *backends.SimulatedBackend, db *sqlx.DB, vrfVersion vrfcommon.Version, chainId *big.Int) bool { @@ -819,7 +818,7 @@ func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend *bac for _, requestID := range requestIDs { requestIDMap[common.BytesToHash(requestID.Bytes()).String()] = false } - return gomega.NewWithT(t).Eventually(func() bool { + return assert.Eventually(t, func() bool { backend.Commit() txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, chainId) require.NoError(t, err) @@ -838,11 +837,11 @@ func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend *bac } t.Log("requestIDMap:", requestIDMap) return foundAll - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), time.Second) } func mineForceFulfilled(t *testing.T, requestID *big.Int, subID uint64, forceFulfilledCount int64, uni coordinatorV2Universe, db *sqlx.DB) bool { - return gomega.NewWithT(t).Eventually(func() bool { + return assert.Eventually(t, func() bool { uni.backend.Commit() var txs []txmgr.DbEthTx err := db.Select(&txs, ` @@ -854,7 +853,7 @@ func mineForceFulfilled(t *testing.T, requestID *big.Int, subID uint64, forceFul require.NoError(t, err) t.Log("num txs", len(txs)) return len(txs) == int(forceFulfilledCount) - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), time.Second) } func TestVRFV2Integration_SingleConsumer_ForceFulfillment(t *testing.T) { @@ -1711,7 +1710,7 @@ func TestIntegrationVRFV2(t *testing.T) { // We expect the request to be serviced // by the node. var runs []pipeline.Run - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { runs, err = app.PipelineORM().GetAllRuns(ctx) require.NoError(t, err) // It is possible that we send the test request @@ -1720,11 +1719,11 @@ func TestIntegrationVRFV2(t *testing.T) { // keep blocks coming in for the lb to send the backfilled logs. uni.backend.Commit() return len(runs) == 1 && runs[0].State == pipeline.RunStatusCompleted - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 1*time.Second) // Wait for the request to be fulfilled on-chain. var rf []v22.RandomWordsFulfilled - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { rfIterator, err2 := uni.rootContract.FilterRandomWordsFulfilled(nil, nil, nil) require.NoError(t, err2, "failed to logs") uni.backend.Commit() @@ -1732,7 +1731,7 @@ func TestIntegrationVRFV2(t *testing.T) { rf = append(rf, rfIterator.Event()) } return len(rf) == 1 - }, testutils.WaitTimeout(t), 500*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 500*time.Millisecond) assert.True(t, rf[0].Success(), "expected callback to succeed") fulfillReceipt, err := uni.backend.TransactionReceipt(ctx, rf[0].Raw().TxHash) require.NoError(t, err) @@ -2047,8 +2046,7 @@ func TestStartingCountsV1(t *testing.T) { ec.On("ConfiguredChainID").Return(testutils.SimulatedChainID) ec.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(2), nil).Maybe() txm := makeTestTxm(t, txStore, ks, ec) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) chain, err := legacyChains.Get(testutils.SimulatedChainID.String()) require.NoError(t, err) listenerV1 := &v1.Listener{ @@ -2165,7 +2163,7 @@ func TestStartingCountsV1(t *testing.T) { for i := range confirmedTxes { txAttempts = append(txAttempts, txmgr.TxAttempt{ TxID: int64(i + 1), - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(100)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(100)}, SignedRawTx: []byte(`blah`), Hash: evmutils.NewHash(), BroadcastBeforeBlockNum: &broadcastBlock, @@ -2178,7 +2176,7 @@ func TestStartingCountsV1(t *testing.T) { for i := range unconfirmedTxes { txAttempts = append(txAttempts, txmgr.TxAttempt{ TxID: int64(i + 1 + len(confirmedTxes)), - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(100)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(100)}, SignedRawTx: []byte(`blah`), Hash: evmutils.NewHash(), State: txmgrtypes.TxAttemptInProgress, @@ -2251,7 +2249,7 @@ func FindLatestRandomnessRequestedLog(t *testing.T, keyHash [32]byte, requestID *big.Int) v22.RandomWordsRequested { var rf []v22.RandomWordsRequested - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { rfIterator, err2 := coordContract.FilterRandomWordsRequested(nil, [][32]byte{keyHash}, nil, []common.Address{}) require.NoError(t, err2, "failed to logs") for rfIterator.Next() { @@ -2260,7 +2258,7 @@ func FindLatestRandomnessRequestedLog(t *testing.T, } } return len(rf) >= 1 - }, testutils.WaitTimeout(t), 500*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 500*time.Millisecond) latest := len(rf) - 1 return rf[latest] } 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 08652455047..aca18b71925 100644 --- a/core/services/vrf/v2/listener_v2_log_listener_test.go +++ b/core/services/vrf/v2/listener_v2_log_listener_test.go @@ -244,9 +244,9 @@ func TestLogPollerFilterRegistered(t *testing.T) { // Wait for the log poller filter to be registered. filterName := th.Listener.getLogPollerFilterName() - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { return th.Listener.chain.LogPoller().HasFilter(filterName) - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), time.Second) // Once registered, expect the filter to stay registered. gomega.NewWithT(t).Consistently(func() bool { diff --git a/core/services/vrf/vrftesthelpers/helpers.go b/core/services/vrf/vrftesthelpers/helpers.go index 33ad8470731..393ea521118 100644 --- a/core/services/vrf/vrftesthelpers/helpers.go +++ b/core/services/vrf/vrftesthelpers/helpers.go @@ -13,7 +13,6 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/google/uuid" - "github.com/onsi/gomega" "github.com/shopspring/decimal" "github.com/stretchr/testify/require" @@ -76,7 +75,7 @@ func CreateAndStartBHSJob( ctx := testutils.Context(t) require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { if jb.Type == job.BlockhashStore { @@ -84,7 +83,7 @@ func CreateAndStartBHSJob( } } return false - }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 100*time.Millisecond) return jb } @@ -118,7 +117,7 @@ func CreateAndStartBlockHeaderFeederJob( ctx := testutils.Context(t) require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) - gomega.NewWithT(t).Eventually(func() bool { + require.Eventually(t, func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { if jb.Type == job.BlockHeaderFeeder { @@ -126,7 +125,7 @@ func CreateAndStartBlockHeaderFeederJob( } } return false - }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) + }, testutils.WaitTimeout(t), 100*time.Millisecond) return jb } diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index acd006940f3..34b9cd3ad2d 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -8,6 +8,7 @@ import ( "github.com/pelletier/go-toml" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" @@ -34,15 +35,27 @@ func (d *Delegate) BeforeJobDeleted(spec job.Job) {} func (d *Delegate) OnDeleteJob(context.Context, job.Job) error { return nil } // ServicesForSpec satisfies the job.Delegate interface. -func (d *Delegate) ServicesForSpec(_ context.Context, spec job.Job) ([]job.ServiceCtx, error) { +func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.ServiceCtx, error) { + sdkSpec, err := spec.WorkflowSpec.SDKSpec(ctx) + if err != nil { + return nil, err + } + + binary, err := spec.WorkflowSpec.RawSpec(ctx) + if err != nil { + return nil, err + } + cfg := Config{ Lggr: d.logger, - Spec: spec.WorkflowSpec.Workflow, + Workflow: sdkSpec, WorkflowID: spec.WorkflowSpec.WorkflowID, WorkflowOwner: spec.WorkflowSpec.WorkflowOwner, WorkflowName: spec.WorkflowSpec.WorkflowName, Registry: d.registry, Store: d.store, + Config: []byte(spec.WorkflowSpec.Config), + Binary: binary, } engine, err := NewEngine(cfg) if err != nil { @@ -59,7 +72,7 @@ func NewDelegate( return &Delegate{logger: logger, registry: registry, store: store} } -func ValidatedWorkflowJobSpec(tomlString string) (job.Job, error) { +func ValidatedWorkflowJobSpec(ctx context.Context, tomlString string) (job.Job, error) { var jb = job.Job{ExternalJobID: uuid.New()} tree, err := toml.Load(tomlString) @@ -81,16 +94,21 @@ func ValidatedWorkflowJobSpec(tomlString string) (job.Job, error) { return jb, fmt.Errorf("toml unmarshal error on workflow spec: %w", err) } - err = spec.Validate() + sdkSpec, err := spec.SDKSpec(ctx) if err != nil { - return jb, fmt.Errorf("invalid WorkflowSpec: %w", err) + return jb, fmt.Errorf("failed to convert to sdk workflow spec: %w", err) } // ensure the embedded workflow graph is valid - _, err = Parse(spec.Workflow) - if err != nil { + if _, err = Parse(sdkSpec); err != nil { return jb, fmt.Errorf("failed to parse workflow graph: %w", err) } + + err = spec.Validate(ctx) + if err != nil { + return jb, fmt.Errorf("invalid WorkflowSpec: %w", err) + } + jb.WorkflowSpec = &spec jb.WorkflowSpecID = &spec.ID diff --git a/core/services/workflows/delegate_test.go b/core/services/workflows/delegate_test.go index a12eac80bbf..d27a1012e6b 100644 --- a/core/services/workflows/delegate_test.go +++ b/core/services/workflows/delegate_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/workflows" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" ) @@ -99,7 +100,7 @@ schemaVersion = 1 for _, tc := range tt { tc := tc t.Run(tc.name, func(t *testing.T) { - _, err := workflows.ValidatedWorkflowJobSpec(tc.workflowTomlFn()) + _, err := workflows.ValidatedWorkflowJobSpec(testutils.Context(t), tc.workflowTomlFn()) if tc.valid { require.NoError(t, err) } else { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index c85d4a03b24..d6b1e793287 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -9,8 +9,13 @@ import ( "sync" "time" + "github.com/smartcontractkit/chainlink/v2/core/monitoring" + "github.com/jonboulle/clockwork" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/exec" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/core" @@ -27,17 +32,77 @@ type stepRequest struct { state store.WorkflowExecution } +type stepUpdateChannel struct { + executionID string + ch chan store.WorkflowExecutionStep +} + +type stepUpdateManager struct { + mu sync.RWMutex + m map[string]stepUpdateChannel +} + +func (sucm *stepUpdateManager) add(executionID string, ch stepUpdateChannel) (added bool) { + sucm.mu.RLock() + _, ok := sucm.m[executionID] + sucm.mu.RUnlock() + if ok { + return false + } + sucm.mu.Lock() + defer sucm.mu.Unlock() + if _, ok = sucm.m[executionID]; ok { + return false + } + sucm.m[executionID] = ch + return true +} + +func (sucm *stepUpdateManager) remove(executionID string) { + sucm.mu.Lock() + defer sucm.mu.Unlock() + if _, ok := sucm.m[executionID]; ok { + close(sucm.m[executionID].ch) + delete(sucm.m, executionID) + } +} + +func (sucm *stepUpdateManager) send(ctx context.Context, executionID string, stepUpdate store.WorkflowExecutionStep) error { + sucm.mu.RLock() + stepUpdateCh, ok := sucm.m[executionID] + sucm.mu.RUnlock() + if !ok { + return fmt.Errorf("step update channel not found for execution %s, dropping step update", executionID) + } + + select { + case <-ctx.Done(): + return fmt.Errorf("context canceled before step update could be issued: %w", context.Cause(ctx)) + case stepUpdateCh.ch <- stepUpdate: + return nil + } +} + +func (sucm *stepUpdateManager) len() int64 { + sucm.mu.RLock() + defer sucm.mu.RUnlock() + return int64(len(sucm.m)) +} + // Engine handles the lifecycle of a single workflow and its executions. type Engine struct { services.StateMachine + cma monitoring.CustomMessageLabeler + metrics workflowsMetricLabeler logger logger.Logger registry core.CapabilitiesRegistry workflow *workflow + env exec.Env localNode capabilities.Node executionStates store.Store pendingStepRequests chan stepRequest - triggerEvents chan capabilities.CapabilityResponse - stepUpdateCh chan store.WorkflowExecutionStep + triggerEvents chan capabilities.TriggerResponse + stepUpdatesChMap stepUpdateManager wg sync.WaitGroup stopCh services.StopChan newWorkerTimeout time.Duration @@ -59,19 +124,24 @@ type Engine struct { clock clockwork.Clock } -func (e *Engine) Start(ctx context.Context) error { +func (e *Engine) Start(_ context.Context) error { return e.StartOnce("Engine", func() error { // create a new context, since the one passed in via Start is short-lived. ctx, _ := e.stopCh.NewCtx() + // spin up monitoring resources + err := initMonitoringResources() + if err != nil { + return fmt.Errorf("could not initialize monitoring resources: %w", err) + } + e.wg.Add(e.maxWorkerLimit) for i := 0; i < e.maxWorkerLimit; i++ { go e.worker(ctx) } - e.wg.Add(2) + e.wg.Add(1) go e.init(ctx) - go e.loop(ctx) return nil }) @@ -90,6 +160,10 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { tg, err := e.registry.GetTrigger(ctx, t.ID) if err != nil { e.logger.With(cIDKey, t.ID).Errorf("failed to get trigger capability: %s", err) + cerr := e.cma.With(cIDKey, t.ID).SendLogAsCustomMessage(fmt.Sprintf("failed to resolve trigger: %s", err)) + if cerr != nil { + return cerr + } // we don't immediately return here, since we want to retry all triggers // to notify the user of all errors at once. triggersInitialized = false @@ -119,6 +193,10 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { err := e.initializeCapability(ctx, s) if err != nil { + cerr := e.cma.With(wIDKey, e.workflow.id, sIDKey, s.ID, sRKey, s.Ref).SendLogAsCustomMessage(fmt.Sprintf("failed to initialize capability for step: %s", err)) + if cerr != nil { + return cerr + } return &workflowError{err: err, reason: "failed to initialize capability for step", labels: map[string]string{ wIDKey: e.workflow.id, @@ -180,13 +258,23 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { // We configure actions, consensus and targets here, and // they all satisfy the `CallbackCapability` interface - cc, ok := cp.(capabilities.CallbackCapability) + cc, ok := cp.(capabilities.ExecutableCapability) if !ok { return newCPErr("capability does not satisfy CallbackCapability") } if step.config == nil { - configMap, newMapErr := values.NewMap(step.Config) + c, interpErr := exec.FindAndInterpolateEnvVars(step.Config, e.env) + if interpErr != nil { + return newCPErr("failed to convert interpolate env vars from config", interpErr) + } + + config, ok := c.(map[string]any) + if !ok { + return newCPErr("failed to convert interpolate env vars from config into map") + } + + configMap, newMapErr := values.NewMap(config) if newMapErr != nil { return newCPErr("failed to convert config to values.Map", newMapErr) } @@ -253,9 +341,13 @@ func (e *Engine) init(ctx context.Context) { e.logger.Debug("registering triggers") for idx, t := range e.workflow.triggers { - err := e.registerTrigger(ctx, t, idx) - if err != nil { - e.logger.With(cIDKey, t.ID).Errorf("failed to register trigger: %s", err) + terr := e.registerTrigger(ctx, t, idx) + if terr != nil { + e.logger.With(cIDKey, t.ID).Errorf("failed to register trigger: %s", terr) + cerr := e.cma.With(cIDKey, t.ID).SendLogAsCustomMessage(fmt.Sprintf("failed to register trigger: %s", terr)) + if cerr != nil { + e.logger.Errorf("failed to send custom message for trigger: %s", terr) + } } } @@ -305,6 +397,16 @@ func (e *Engine) resumeInProgressExecutions(ctx context.Context) error { } for _, sd := range sds { + ch := make(chan store.WorkflowExecutionStep) + added := e.stepUpdatesChMap.add(execution.ExecutionID, stepUpdateChannel{ + ch: ch, + executionID: execution.ExecutionID, + }) + if added { + // We trigger the `stepUpdateLoop` for this execution, since the loop is not running atm. + e.wg.Add(1) + go e.stepUpdateLoop(ctx, execution.ExecutionID, ch, execution.CreatedAt) + } e.queueIfReady(execution, sd) } } @@ -319,14 +421,6 @@ func generateTriggerId(workflowID string, triggerIdx int) string { // registerTrigger is used during the initialization phase to bind a trigger to this workflow func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, triggerIdx int) error { triggerID := generateTriggerId(e.workflow.id, triggerIdx) - triggerInputs, err := values.NewMap( - map[string]any{ - "triggerId": triggerID, - }, - ) - if err != nil { - return err - } tc, err := values.NewMap(t.Config) if err != nil { @@ -335,19 +429,21 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig t.config.Store(tc) - triggerRegRequest := capabilities.CapabilityRequest{ + triggerRegRequest := capabilities.TriggerRegistrationRequest{ Metadata: capabilities.RequestMetadata{ WorkflowID: e.workflow.id, + WorkflowOwner: e.workflow.owner, + WorkflowName: e.workflow.name, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, - WorkflowName: e.workflow.name, - WorkflowOwner: e.workflow.owner, + ReferenceID: t.Ref, }, - Config: t.config.Load(), - Inputs: triggerInputs, + Config: t.config.Load(), + TriggerID: triggerID, } eventsCh, err := t.trigger.RegisterTrigger(ctx, triggerRegRequest) if err != nil { + e.metrics.with(cIDKey, t.ID, tIDKey, triggerID).incrementRegisterTriggerFailureCounter(ctx) // It's confusing that t.ID is different from triggerID, but // t.ID is the capability ID, and triggerID is the trigger ID. // @@ -389,62 +485,34 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig return nil } -// loop is the synchronization goroutine for the engine, and is responsible for: -// - dispatching new workers up to the limit specified (default = 100) -// - starting a new execution when a trigger emits a message on `triggerEvents` -// - updating the `executionState` with the outcome of a `step`. +// stepUpdateLoop is a singleton goroutine per `Execution`, and it updates the `executionState` with the outcome of a `step`. // // Note: `executionState` is only mutated by this loop directly. // // This is important to avoid data races, and any accesses of `executionState` by any other // goroutine should happen via a `stepRequest` message containing a copy of the latest // `executionState`. -// -// This works because a worker thread for a given step will only -// be spun up once all dependent steps have completed (guaranteeing that the state associated -// with those dependent steps will no longer change). Therefore as long this worker thread only -// accesses data from dependent states, the data will never be stale. -func (e *Engine) loop(ctx context.Context) { +func (e *Engine) stepUpdateLoop(ctx context.Context, executionID string, stepUpdateCh chan store.WorkflowExecutionStep, workflowCreatedAt *time.Time) { defer e.wg.Done() + lggr := e.logger.With(eIDKey, executionID) + e.logger.Debugf("running stepUpdateLoop for execution %s", executionID) for { select { case <-ctx.Done(): - e.logger.Debug("shutting down loop") + lggr.Debug("shutting down stepUpdateLoop") return - case resp, isOpen := <-e.triggerEvents: - if !isOpen { - e.logger.Error("trigger events channel is no longer open, skipping") - continue - } - - if resp.Err != nil { - e.logger.Errorf("trigger event was an error %v; not executing", resp.Err) - continue - } - - te := &capabilities.TriggerEvent{} - err := resp.Value.UnwrapTo(te) - if err != nil { - e.logger.Errorf("could not unwrap trigger event; error %v", resp.Err) - continue - } - - executionID, err := generateExecutionID(e.workflow.id, te.ID) - if err != nil { - e.logger.With(tIDKey, te.ID).Errorf("could not generate execution ID: %v", err) - continue - } - - err = e.startExecution(ctx, executionID, resp.Value) - if err != nil { - e.logger.With(eIDKey, executionID).Errorf("failed to start execution: %v", err) + case stepUpdate, open := <-stepUpdateCh: + if !open { + lggr.Debug("stepUpdate channel closed, shutting down stepUpdateLoop") + return } - case stepUpdate := <-e.stepUpdateCh: // Executed synchronously to ensure we correctly schedule subsequent tasks. - err := e.handleStepUpdate(ctx, stepUpdate) + e.logger.Debugw(fmt.Sprintf("received step update for execution %s", stepUpdate.ExecutionID), + eIDKey, stepUpdate.ExecutionID, sRKey, stepUpdate.Ref) + err := e.handleStepUpdate(ctx, stepUpdate, workflowCreatedAt) if err != nil { - e.logger.With(eIDKey, stepUpdate.ExecutionID, sRKey, stepUpdate.Ref). - Errorf("failed to update step state: %+v, %s", stepUpdate, err) + e.logger.Errorf(fmt.Sprintf("failed to update step state: %+v, %s", stepUpdate, err), + eIDKey, stepUpdate.ExecutionID, sRKey, stepUpdate.Ref) } } } @@ -466,8 +534,9 @@ func generateExecutionID(workflowID, eventID string) (string, error) { } // startExecution kicks off a new workflow execution when a trigger event is received. -func (e *Engine) startExecution(ctx context.Context, executionID string, event values.Value) error { - e.logger.With("event", event, eIDKey, executionID).Debug("executing on a trigger event") +func (e *Engine) startExecution(ctx context.Context, executionID string, event *values.Map) error { + lggr := e.logger.With("event", event, eIDKey, executionID) + lggr.Debug("executing on a trigger event") ec := &store.WorkflowExecution{ Steps: map[string]*store.WorkflowExecutionStep{ workflows.KeywordTrigger: { @@ -484,7 +553,7 @@ func (e *Engine) startExecution(ctx context.Context, executionID string, event v Status: store.StatusStarted, } - err := e.executionStates.Add(ctx, ec) + dbWex, err := e.executionStates.Add(ctx, ec) if err != nil { return err } @@ -497,6 +566,19 @@ func (e *Engine) startExecution(ctx context.Context, executionID string, event v return err } + ch := make(chan store.WorkflowExecutionStep) + added := e.stepUpdatesChMap.add(executionID, stepUpdateChannel{ + ch: ch, + executionID: executionID, + }) + if !added { + // skip this execution since there's already a stepUpdateLoop running for the execution ID + lggr.Debugf("won't start execution for execution %s, execution was already started", executionID) + return nil + } + e.wg.Add(1) + go e.stepUpdateLoop(ctx, executionID, ch, dbWex.CreatedAt) + for _, td := range triggerDependents { e.queueIfReady(*ec, td) } @@ -504,79 +586,56 @@ func (e *Engine) startExecution(ctx context.Context, executionID string, event v return nil } -func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.WorkflowExecutionStep) error { +func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.WorkflowExecutionStep, workflowCreatedAt *time.Time) error { + l := e.logger.With(eIDKey, stepUpdate.ExecutionID, sRKey, stepUpdate.Ref) + cma := e.cma.With(eIDKey, stepUpdate.ExecutionID, sRKey, stepUpdate.Ref) + + // If we've been executing for too long, let's time the workflow step out and continue. + if workflowCreatedAt != nil && e.clock.Since(*workflowCreatedAt) > e.maxExecutionDuration { + l.Info("execution timed out; setting step status to timeout") + stepUpdate.Status = store.StatusTimeout + } + state, err := e.executionStates.UpsertStep(ctx, &stepUpdate) if err != nil { return err } - l := e.logger.With(eIDKey, state.ExecutionID, sRKey, stepUpdate.Ref) - - switch stepUpdate.Status { - case store.StatusCompleted: - stepDependents, err := e.workflow.dependents(stepUpdate.Ref) - if err != nil { - return err - } - - // There are no steps left to process in the current path, so let's check if - // we've completed the workflow. - if len(stepDependents) == 0 { - workflowCompleted := true - err := e.workflow.walkDo(workflows.KeywordTrigger, func(s *step) error { - step, ok := state.Steps[s.Ref] - // The step is missing from the state, - // which means it hasn't been processed yet. - // Let's mark `workflowCompleted` = false, and - // continue. - if !ok { - workflowCompleted = false - return nil - } - switch step.Status { - case store.StatusCompleted, store.StatusErrored, store.StatusCompletedEarlyExit: - default: - workflowCompleted = false - } - return nil - }) - if err != nil { - return err - } - - if workflowCompleted { - return e.finishExecution(ctx, state.ExecutionID, store.StatusCompleted) - } - } + workflowIsFullyProcessed, status, err := e.isWorkflowFullyProcessed(ctx, state) + if err != nil { + return err + } - // We haven't completed the workflow, but should we continue? - // If we've been executing for too long, let's time the workflow out and stop here. - if state.CreatedAt != nil && e.clock.Since(*state.CreatedAt) > e.maxExecutionDuration { + if workflowIsFullyProcessed { + switch status { + case store.StatusTimeout: l.Info("execution timed out") - return e.finishExecution(ctx, state.ExecutionID, store.StatusTimeout) - } - - // Finally, since the workflow hasn't timed out or completed, let's - // check for any dependents that are ready to process. - for _, sd := range stepDependents { - e.queueIfReady(state, sd) - } - case store.StatusCompletedEarlyExit: - l.Info("execution terminated early") - // NOTE: even though this marks the workflow as completed, any branches of the DAG - // that don't depend on the step that signaled for an early exit will still complete. - // This is to ensure that any side effects are executed consistently, since otherwise - // the async nature of the workflow engine would provide no guarantees. - err := e.finishExecution(ctx, state.ExecutionID, store.StatusCompletedEarlyExit) - if err != nil { - return err + case store.StatusCompleted: + l.Info("workflow finished") + case store.StatusErrored: + l.Info("execution errored") + case store.StatusCompletedEarlyExit: + l.Info("execution terminated early") + // NOTE: even though this marks the workflow as completed, any branches of the DAG + // that don't depend on the step that signaled for an early exit will still complete. + // This is to ensure that any side effects are executed consistently, since otherwise + // the async nature of the workflow engine would provide no guarantees. } - case store.StatusErrored: - l.Info("execution errored") - err := e.finishExecution(ctx, state.ExecutionID, store.StatusErrored) + err = cma.SendLogAsCustomMessage(fmt.Sprintf("execution status: %s", status)) if err != nil { return err } + return e.finishExecution(ctx, state.ExecutionID, status) + } + + // Finally, since the workflow hasn't timed out or completed, let's + // check for any dependents that are ready to process. + stepDependents, err := e.workflow.dependents(stepUpdate.Ref) + if err != nil { + return err + } + for _, sd := range stepDependents { + e.queueIfReady(state, sd) } return nil @@ -615,15 +674,29 @@ func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { func (e *Engine) finishExecution(ctx context.Context, executionID string, status string) error { e.logger.With(eIDKey, executionID, "status", status).Info("finishing execution") + metrics := e.metrics.with(eIDKey, executionID, "status", status) err := e.executionStates.UpdateStatus(ctx, executionID, status) if err != nil { return err } + execState, err := e.executionStates.Get(ctx, executionID) + if err != nil { + return err + } + + executionDuration := execState.FinishedAt.Sub(*execState.CreatedAt).Milliseconds() + + e.stepUpdatesChMap.remove(executionID) + metrics.updateTotalWorkflowsGauge(ctx, e.stepUpdatesChMap.len()) + metrics.updateWorkflowExecutionLatencyGauge(ctx, executionDuration) e.onExecutionFinished(executionID) return nil } +// worker is responsible for: +// - handling a `pendingStepRequests` +// - starting a new execution when a trigger emits a message on `triggerEvents` func (e *Engine) worker(ctx context.Context) { defer e.wg.Done() @@ -631,6 +704,34 @@ func (e *Engine) worker(ctx context.Context) { select { case pendingStepRequest := <-e.pendingStepRequests: e.workerForStepRequest(ctx, pendingStepRequest) + case resp, isOpen := <-e.triggerEvents: + if !isOpen { + e.logger.Error("trigger events channel is no longer open, skipping") + continue + } + + if resp.Err != nil { + e.logger.Errorf("trigger event was an error %v; not executing", resp.Err) + continue + } + + te := resp.Event + + if te.ID == "" { + e.logger.With(tIDKey, te.TriggerType).Error("trigger event ID is empty; not executing") + continue + } + + executionID, err := generateExecutionID(e.workflow.id, te.ID) + if err != nil { + e.logger.With(tIDKey, te.ID).Errorf("could not generate execution ID: %v", err) + continue + } + + err = e.startExecution(ctx, executionID, resp.Event.Outputs) + if err != nil { + e.logger.With(eIDKey, executionID).Errorf("failed to start execution: %v", err) + } case <-ctx.Done(): return } @@ -641,6 +742,7 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // Instantiate a child logger; in addition to the WorkflowID field the workflow // logger will already have, this adds the `stepRef` and `executionID` l := e.logger.With(sRKey, msg.stepRef, eIDKey, msg.state.ExecutionID) + cma := e.cma.With(sRKey, msg.stepRef, eIDKey, msg.state.ExecutionID) l.Debug("executing on a step event") stepState := &store.WorkflowExecutionStep{ @@ -649,17 +751,38 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { Ref: msg.stepRef, } + // TODO ks-462 inputs + err := cma.SendLogAsCustomMessage("executing step") + if err != nil { + return + } inputs, outputs, err := e.executeStep(ctx, msg) var stepStatus string switch { case errors.Is(capabilities.ErrStopExecution, err): - l.Info("step executed successfully with a termination") + lmsg := "step executed successfully with a termination" + l.Info(lmsg) + cmErr := cma.SendLogAsCustomMessage(lmsg) + if cmErr != nil { + l.Errorf("failed to send custom message with msg: %s", lmsg) + } stepStatus = store.StatusCompletedEarlyExit case err != nil: + lmsg := "step executed successfully with a termination" l.Errorf("error executing step request: %s", err) + cmErr := cma.SendLogAsCustomMessage(fmt.Sprintf("error executing step request: %s", err)) + if cmErr != nil { + l.Errorf("failed to send custom message with msg: %s", lmsg) + } stepStatus = store.StatusErrored default: + lmsg := "step executed successfully with a termination" l.With("outputs", outputs).Info("step executed successfully") + // TODO ks-462 emit custom message with outputs + cmErr := cma.SendLogAsCustomMessage("step executed successfully") + if cmErr != nil { + l.Errorf("failed to send custom message with msg: %s", lmsg) + } stepStatus = store.StatusCompleted } @@ -674,11 +797,13 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // receiving loop may not pick up any messages we emit. // Note: When full persistence support is added, any hanging steps // like this one will get picked up again and will be reprocessed. - select { - case <-ctx.Done(): - l.Errorf("context canceled before step update could be issued; error %v", err) - case e.stepUpdateCh <- *stepState: + l.Debugf("trying to send step state update for execution %s with status %s", stepState.ExecutionID, stepStatus) + err = e.stepUpdatesChMap.send(ctx, stepState.ExecutionID, *stepState) + if err != nil { + l.Errorf("failed to issue step state update; error %v", err) + return } + l.Debugf("sent step state update for execution %s with status %s", stepState.ExecutionID, stepStatus) } func merge(baseConfig *values.Map, overrideConfig *values.Map) *values.Map { @@ -717,11 +842,10 @@ func (e *Engine) configForStep(ctx context.Context, executionID string, step *st return step.config, nil } - // Merge the configs for now; note that this means that a workflow can override - // all of the config set by the capability. This is probably not desirable in - // the long-term, but we don't know much about those use cases so stick to a simpler - // implementation for now. - return merge(capConfig.DefaultConfig, step.config), nil + // Merge the configs with registry config overriding the step config. This is because + // some config fields are sensitive and could affect the safe running of the capability, + // so we avoid user provided values by overriding them with config from the capabilities registry. + return merge(step.config, capConfig.DefaultConfig), nil } // executeStep executes the referenced capability within a step and returns the result. @@ -738,7 +862,7 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, inputs = step.Inputs.Mapping } - i, err := findAndInterpolateAllKeys(inputs, msg.state) + i, err := exec.FindAndInterpolateAllKeys(inputs, msg.state) if err != nil { return nil, nil, err } @@ -763,36 +887,31 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, WorkflowName: e.workflow.name, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, + ReferenceID: msg.stepRef, }, } - output, err := executeSyncAndUnwrapSingleValue(ctx, step.capability, tr) + e.metrics.incrementCapabilityInvocationCounter(ctx) + output, err := step.capability.Execute(ctx, tr) if err != nil { return inputsMap, nil, err } - return inputsMap, output, err + return inputsMap, output.Value, err } func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, triggerIdx int) error { - triggerInputs, err := values.NewMap( - map[string]any{ - "triggerId": generateTriggerId(e.workflow.id, triggerIdx), - }, - ) - if err != nil { - return err - } - deregRequest := capabilities.CapabilityRequest{ + deregRequest := capabilities.TriggerRegistrationRequest{ Metadata: capabilities.RequestMetadata{ WorkflowID: e.workflow.id, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, WorkflowName: e.workflow.name, WorkflowOwner: e.workflow.owner, + ReferenceID: t.Ref, }, - Inputs: triggerInputs, - Config: t.config.Load(), + TriggerID: generateTriggerId(e.workflow.id, triggerIdx), + Config: t.config.Load(), } // if t.trigger == nil, then we haven't initialized the workflow @@ -805,6 +924,96 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, tr return nil } +func (e *Engine) isWorkflowFullyProcessed(ctx context.Context, state store.WorkflowExecution) (bool, string, error) { + statuses := map[string]string{} + // we need to first propagate the status of the errored status if it exists... + err := e.workflow.walkDo(workflows.KeywordTrigger, func(s *step) error { + stateStep, ok := state.Steps[s.Ref] + if !ok { + // The step not existing on the state means that it has not been processed yet. + // So ignore it. + return nil + } + statuses[s.Ref] = stateStep.Status + switch stateStep.Status { + // For each step with any of the following statuses, propagate the statuses to its dependants + // since they will not be executed. + case store.StatusErrored, store.StatusCompletedEarlyExit, store.StatusTimeout: + // Let's properly propagate the status to all dependents, not just direct dependents. + queue := []string{s.Ref} + for len(queue) > 0 { + current := queue[0] // Grab the current step reference + queue = queue[1:] // Remove it from the queue + + // Find the dependents for the current step reference + dependents, err := e.workflow.dependents(current) + if err != nil { + return err + } + + // Propagate the status to all direct dependents + // With no direct dependents, it will go to the next step reference in the queue. + for _, sd := range dependents { + if _, dependentProcessed := statuses[sd.Ref]; !dependentProcessed { + statuses[sd.Ref] = stateStep.Status + // Queue the dependent for to be processed later + queue = append(queue, sd.Ref) + } + } + } + e.metrics.incrementTotalWorkflowStepErrorsCounter(ctx) + } + return nil + }) + if err != nil { + return false, "", err + } + + workflowProcessed := true + // Let's validate whether the workflow has been fully processed. + err = e.workflow.walkDo(workflows.KeywordTrigger, func(s *step) error { + // If the step is not part of the state, it is a pending step + // so we should consider the workflow as not fully processed. + if _, ok := statuses[s.Ref]; !ok { + workflowProcessed = false + } + return nil + }) + if err != nil { + return false, "", err + } + + if !workflowProcessed { + return workflowProcessed, "", nil + } + + var hasErrored, hasTimedOut, hasCompletedEarlyExit bool + // Let's determine the status of the workflow. + for _, status := range statuses { + switch status { + case store.StatusErrored: + hasErrored = true + case store.StatusTimeout: + hasTimedOut = true + case store.StatusCompletedEarlyExit: + hasCompletedEarlyExit = true + } + } + + // The `errored` status has precedence over the other statuses to be returned, based on occurrence. + // Status precedence: `errored` -> `timed_out` -> `completed_early_exit` -> `completed`. + if hasErrored { + return workflowProcessed, store.StatusErrored, nil + } + if hasTimedOut { + return workflowProcessed, store.StatusTimeout, nil + } + if hasCompletedEarlyExit { + return workflowProcessed, store.StatusCompletedEarlyExit, nil + } + return workflowProcessed, store.StatusCompleted, nil +} + func (e *Engine) Close() error { return e.StopOnce("Engine", func() error { e.logger.Info("shutting down engine") @@ -864,7 +1073,7 @@ func (e *Engine) Close() error { } type Config struct { - Spec string + Workflow sdk.WorkflowSpec WorkflowID string WorkflowOwner string WorkflowName string @@ -875,6 +1084,8 @@ type Config struct { NewWorkerTimeout time.Duration MaxExecutionDuration time.Duration Store store.Store + Config []byte + Binary []byte // For testing purposes only maxRetries int @@ -940,7 +1151,7 @@ func NewEngine(cfg Config) (engine *Engine, err error) { // - that the resulting graph is strongly connected (i.e. no disjointed subgraphs exist) // - etc. - workflow, err := Parse(cfg.Spec) + workflow, err := Parse(cfg.Workflow) if err != nil { return nil, err } @@ -950,13 +1161,19 @@ func NewEngine(cfg Config) (engine *Engine, err error) { workflow.name = hex.EncodeToString([]byte(cfg.WorkflowName)) engine = &Engine{ - logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), - registry: cfg.Registry, - workflow: workflow, + logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), + cma: monitoring.NewCustomMessageLabeler().With(wIDKey, cfg.WorkflowID, woIDKey, cfg.WorkflowOwner, wnKey, workflow.name), + metrics: workflowsMetricLabeler{monitoring.NewMetricsLabeler().With(wIDKey, cfg.WorkflowID, woIDKey, cfg.WorkflowOwner, wnKey, workflow.name)}, + registry: cfg.Registry, + workflow: workflow, + env: exec.Env{ + Config: cfg.Config, + Binary: cfg.Binary, + }, executionStates: cfg.Store, pendingStepRequests: make(chan stepRequest, cfg.QueueSize), - stepUpdateCh: make(chan store.WorkflowExecutionStep), - triggerEvents: make(chan capabilities.CapabilityResponse), + stepUpdatesChMap: stepUpdateManager{m: map[string]stepUpdateChannel{}}, + triggerEvents: make(chan capabilities.TriggerResponse), stopCh: make(chan struct{}), newWorkerTimeout: cfg.NewWorkerTimeout, maxExecutionDuration: cfg.MaxExecutionDuration, @@ -971,34 +1188,6 @@ func NewEngine(cfg Config) (engine *Engine, err error) { return engine, nil } -// ExecuteSyncAndUnwrapSingleValue is a convenience method that executes a capability synchronously and unwraps the -// result if it is a single value otherwise returns the list. -func executeSyncAndUnwrapSingleValue(ctx context.Context, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) { - l, err := capabilities.ExecuteSync(ctx, cap, req) - if err != nil { - return nil, err - } - - // `ExecuteSync` returns a `values.List` even if there was - // just one return value. If that is the case, let's unwrap the - // single value to make it easier to use in -- for example -- variable interpolation. - if len(l.Underlying) > 1 { - return l, nil - } - - return l.Underlying[0], nil -} - -// Logging keys -const ( - cIDKey = "capabilityID" - tIDKey = "triggerID" - wIDKey = "workflowID" - eIDKey = "executionID" - sIDKey = "stepID" - sRKey = "stepRef" -) - type workflowError struct { labels map[string]string // err is the underlying error that caused this error @@ -1008,9 +1197,6 @@ type workflowError struct { } func (e *workflowError) Error() string { - // declare in reverse order so that the error message is ordered correctly - orderedLabels := []string{sRKey, sIDKey, tIDKey, cIDKey, eIDKey, wIDKey} - errStr := "" if e.err != nil { if e.reason != "" { @@ -1023,7 +1209,7 @@ func (e *workflowError) Error() string { } // prefix the error with the labels - for _, label := range orderedLabels { + for _, label := range orderedLabelKeys { // This will silently ignore any labels that are not present in the map // are we ok with this? if value, ok := e.labels[label]; ok { diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 0a38bf719b2..72e1583a5ca 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -18,10 +18,19 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" + gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" + ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + coreCap "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/compute" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" "github.com/smartcontractkit/chainlink/v2/core/services/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" @@ -129,8 +138,18 @@ func (t testConfigProvider) ConfigForCapability(ctx context.Context, capabilityI return registrysyncer.CapabilityConfiguration{}, nil } +func newTestEngineWithYAMLSpec(t *testing.T, reg *coreCap.Registry, spec string, opts ...func(c *Config)) (*Engine, *testHooks) { + sdkSpec, err := (&job.WorkflowSpec{ + Workflow: spec, + SpecType: job.YamlSpec, + }).SDKSpec(testutils.Context(t)) + require.NoError(t, err) + + return newTestEngine(t, reg, sdkSpec, opts...) +} + // newTestEngine creates a new engine with some test defaults. -func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...func(c *Config)) (*Engine, *testHooks) { +func newTestEngine(t *testing.T, reg *coreCap.Registry, sdkSpec sdk.WorkflowSpec, opts ...func(c *Config)) (*Engine, *testHooks) { initFailed := make(chan struct{}) initSuccessful := make(chan struct{}) executionFinished := make(chan string, 100) @@ -141,7 +160,7 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...fun WorkflowID: testWorkflowId, Lggr: logger.TestLogger(t), Registry: reg, - Spec: spec, + Workflow: sdkSpec, maxRetries: 1, retryMs: 100, afterInit: func(success bool) { @@ -186,7 +205,7 @@ func getExecutionId(t *testing.T, eng *Engine, hooks *testHooks) string { type mockCapability struct { capabilities.CapabilityInfo - capabilities.CallbackExecutable + capabilities.Executable response chan capabilities.CapabilityResponse transform func(capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) } @@ -199,18 +218,14 @@ func newMockCapability(info capabilities.CapabilityInfo, transform func(capabili } } -func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { cr, err := m.transform(req) if err != nil { - return nil, err + return capabilities.CapabilityResponse{}, err } - ch := make(chan capabilities.CapabilityResponse, 10) - m.response <- cr - ch <- cr - close(ch) - return ch, nil + return cr, nil } func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { @@ -223,20 +238,20 @@ func (m *mockCapability) UnregisterFromWorkflow(ctx context.Context, request cap type mockTriggerCapability struct { capabilities.CapabilityInfo - triggerEvent *capabilities.CapabilityResponse - ch chan capabilities.CapabilityResponse + triggerEvent *capabilities.TriggerResponse + ch chan capabilities.TriggerResponse } var _ capabilities.TriggerCapability = (*mockTriggerCapability)(nil) -func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { +func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) (<-chan capabilities.TriggerResponse, error) { if m.triggerEvent != nil { m.ch <- *m.triggerEvent } return m.ch, nil } -func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capabilities.CapabilityRequest) error { +func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) error { return nil } @@ -247,8 +262,8 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { trigger, cr := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - target1 := mockTarget() + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + target1 := mockTarget("") require.NoError(t, reg.Add(ctx, target1)) target2 := newMockCapability( @@ -266,7 +281,7 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { ) require.NoError(t, reg.Add(ctx, target2)) - eng, testHooks := newTestEngine( + eng, testHooks := newTestEngineWithYAMLSpec( t, reg, hardcodedWorkflow, @@ -275,8 +290,11 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { servicetest.Run(t, eng) eid := getExecutionId(t, eng, testHooks) - assert.Equal(t, cr, <-target1.response) - assert.Equal(t, cr, <-target2.response) + resp1 := <-target1.response + assert.Equal(t, cr.Event.Outputs, resp1.Value) + + resp2 := <-target2.response + assert.Equal(t, cr.Event.Outputs, resp2.Value) state, err := eng.executionStates.Get(ctx, eid) require.NoError(t, err) @@ -327,14 +345,14 @@ targets: ` ) -func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.CapabilityResponse) { +func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.TriggerResponse) { mt := &mockTriggerCapability{ CapabilityInfo: capabilities.MustNewCapabilityInfo( "mercury-trigger@1.0.0", capabilities.CapabilityTypeTrigger, "issues a trigger when a mercury report is received.", ), - ch: make(chan capabilities.CapabilityResponse, 10), + ch: make(chan capabilities.TriggerResponse, 10), } resp, err := values.NewMap(map[string]any{ "123": decimal.NewFromFloat(1.00), @@ -342,11 +360,15 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap "789": decimal.NewFromFloat(1.50), }) require.NoError(t, err) - cr := capabilities.CapabilityResponse{ - Value: resp, + tr := capabilities.TriggerResponse{ + Event: capabilities.TriggerEvent{ + TriggerType: mt.ID, + ID: time.Now().UTC().Format(time.RFC3339), + Outputs: resp, + }, } - mt.triggerEvent = &cr - return mt, cr + mt.triggerEvent = &tr + return mt, tr } func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability { @@ -356,7 +378,7 @@ func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability { capabilities.CapabilityTypeTrigger, "issues a trigger when a mercury report is received.", ), - ch: make(chan capabilities.CapabilityResponse, 10), + ch: make(chan capabilities.TriggerResponse, 10), } return mt } @@ -374,26 +396,31 @@ func mockFailingConsensus() *mockCapability { ) } -func mockConsensusWithEarlyTermination() *mockCapability { +func mockConsensusWithEarlyTermination(id string) *mockCapability { + if len(id) == 0 { + id = "offchain_reporting@1.0.0" + } return newMockCapability( capabilities.MustNewCapabilityInfo( - "offchain_reporting@1.0.0", + id, capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { - return capabilities.CapabilityResponse{ + return capabilities.CapabilityResponse{}, // copy error object to make sure message comparison works as expected - Err: errors.New(capabilities.ErrStopExecution.Error()), - }, nil + errors.New(capabilities.ErrStopExecution.Error()) }, ) } -func mockConsensus() *mockCapability { +func mockConsensus(id string) *mockCapability { + if len(id) == 0 { + id = "offchain_reporting@1.0.0" + } return newMockCapability( capabilities.MustNewCapabilityInfo( - "offchain_reporting@1.0.0", + id, capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", ), @@ -415,10 +442,13 @@ func mockConsensus() *mockCapability { ) } -func mockTarget() *mockCapability { +func mockTarget(id string) *mockCapability { + if len(id) == 0 { + id = "write_polygon-testnet-mumbai@1.0.0" + } return newMockCapability( capabilities.MustNewCapabilityInfo( - "write_polygon-testnet-mumbai@1.0.0", + id, capabilities.CapabilityTypeTarget, "a write capability targeting polygon mumbai testnet", ), @@ -440,9 +470,9 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { require.NoError(t, reg.Add(ctx, trigger)) require.NoError(t, reg.Add(ctx, mockFailingConsensus())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockTarget("write_polygon-testnet-mumbai@1.0.0"))) - eng, hooks := newTestEngine(t, reg, simpleWorkflow) + eng, hooks := newTestEngineWithYAMLSpec(t, reg, simpleWorkflow) servicetest.Run(t, eng) @@ -463,10 +493,10 @@ func TestEngine_GracefulEarlyTermination(t *testing.T) { trigger, _ := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensusWithEarlyTermination())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockConsensusWithEarlyTermination(""))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) - eng, hooks := newTestEngine(t, reg, simpleWorkflow) + eng, hooks := newTestEngineWithYAMLSpec(t, reg, simpleWorkflow) servicetest.Run(t, eng) eid := getExecutionId(t, eng, hooks) @@ -551,16 +581,16 @@ func TestEngine_MultiStepDependencies(t *testing.T) { ctx := testutils.Context(t) reg := coreCap.NewRegistry(logger.TestLogger(t)) - trigger, cr := mockTrigger(t) + trigger, tr := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) action, out := mockAction(t) require.NoError(t, reg.Add(ctx, action)) - eng, hooks := newTestEngine(t, reg, multiStepWorkflow) + eng, hooks := newTestEngineWithYAMLSpec(t, reg, multiStepWorkflow) servicetest.Run(t, eng) eid := getExecutionId(t, eng, hooks) @@ -578,9 +608,10 @@ func TestEngine_MultiStepDependencies(t *testing.T) { obs := unw.(map[string]any)["observations"] assert.Len(t, obs, 2) - tunw, err := values.Unwrap(cr.Value) require.NoError(t, err) - assert.Equal(t, obs.([]any)[0], tunw) + uo, err := values.Unwrap(tr.Event.Outputs) + require.NoError(t, err) + assert.Equal(t, obs.([]any)[0].(map[string]any), uo) o, err := values.Unwrap(out) require.NoError(t, err) @@ -601,8 +632,8 @@ func TestEngine_ResumesPendingExecutions(t *testing.T) { require.NoError(t, err) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) action, _ := mockAction(t) require.NoError(t, reg.Add(ctx, action)) @@ -622,10 +653,10 @@ func TestEngine_ResumesPendingExecutions(t *testing.T) { ExecutionID: "", Status: store.StatusStarted, } - err = dbstore.Add(ctx, ec) + _, err = dbstore.Add(ctx, ec) require.NoError(t, err) - eng, hooks := newTestEngine( + eng, hooks := newTestEngineWithYAMLSpec( t, reg, multiStepWorkflow, @@ -653,8 +684,8 @@ func TestEngine_TimesOutOldExecutions(t *testing.T) { require.NoError(t, err) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) action, _ := mockAction(t) require.NoError(t, reg.Add(ctx, action)) @@ -676,10 +707,10 @@ func TestEngine_TimesOutOldExecutions(t *testing.T) { ExecutionID: "", Status: store.StatusStarted, } - err = dbstore.Add(ctx, ec) + _, err = dbstore.Add(ctx, ec) require.NoError(t, err) - eng, hooks := newTestEngine( + eng, hooks := newTestEngineWithYAMLSpec( t, reg, multiStepWorkflow, @@ -750,13 +781,13 @@ func TestEngine_WrapsTargets(t *testing.T) { trigger, _ := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) clock := clockwork.NewFakeClock() dbstore := newTestDBStore(t, clock) - eng, hooks := newTestEngine( + eng, hooks := newTestEngineWithYAMLSpec( t, reg, delayedWorkflow, @@ -796,8 +827,8 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { trigger, _ := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - require.NoError(t, reg.Add(ctx, mockTarget())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) clock := clockwork.NewFakeClock() dbstore := newTestDBStore(t, clock) @@ -823,7 +854,7 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { return n, err }, }) - eng, hooks := newTestEngine( + eng, hooks := newTestEngineWithYAMLSpec( t, reg, delayedWorkflow, @@ -888,7 +919,7 @@ func TestEngine_PassthroughInterpolation(t *testing.T) { trigger, _ := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) writeID := "write_ethereum-testnet-sepolia@1.0.0" target := newMockCapability( capabilities.MustNewCapabilityInfo( @@ -904,7 +935,7 @@ func TestEngine_PassthroughInterpolation(t *testing.T) { ) require.NoError(t, reg.Add(ctx, target)) - eng, testHooks := newTestEngine( + eng, testHooks := newTestEngineWithYAMLSpec( t, reg, passthroughInterpolationWorkflow, @@ -949,7 +980,7 @@ func TestEngine_Error(t *testing.T) { name: "Error with error and no reason", labels: map[string]string{eIDKey: "dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751"}, err: err, - want: "executionID dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751: some error", + want: "workflowExecutionID dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751: some error", }, { name: "Error with no error and reason", @@ -978,7 +1009,7 @@ func TestEngine_Error(t *testing.T) { }, err: err, reason: "some reason", - want: "workflowID my-workflow-id: executionID dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751: capabilityID streams-trigger:network_eth@1.0.0: some reason: some error", + want: "workflowID my-workflow-id: workflowExecutionID dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751: capabilityID streams-trigger:network_eth@1.0.0: some reason: some error", }, } @@ -997,16 +1028,23 @@ func TestEngine_Error(t *testing.T) { } func TestEngine_MergesWorkflowConfigAndCRConfig(t *testing.T) { - ctx := testutils.Context(t) - reg := coreCap.NewRegistry(logger.TestLogger(t)) - - trigger, _ := mockTrigger(t) + var ( + ctx = testutils.Context(t) + writeID = "write_polygon-testnet-mumbai@1.0.0" + gotConfig = values.EmptyMap() + wantConfigKeys = []string{"deltaStage", "schedule", "address", "params", "abi"} + ) - require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - writeID := "write_polygon-testnet-mumbai@1.0.0" + giveRegistryConfig, err := values.WrapMap(map[string]any{ + "deltaStage": "1s", + "schedule": "allAtOnce", + }) + assert.NoError(t, err, "failed to wrap map of registry config") - gotConfig := values.EmptyMap() + // Mock the capabilities of the simple workflow. + reg := coreCap.NewRegistry(logger.TestLogger(t)) + trigger, _ := mockTrigger(t) + consensus := mockConsensus("") target := newMockCapability( // Create a remote capability so we don't use the local transmission protocol. capabilities.MustNewRemoteCapabilityInfo( @@ -1016,6 +1054,7 @@ func TestEngine_MergesWorkflowConfigAndCRConfig(t *testing.T) { &capabilities.DON{ID: 1}, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + // Replace the empty config with the write target config. gotConfig = req.Config return capabilities.CapabilityResponse{ @@ -1023,9 +1062,12 @@ func TestEngine_MergesWorkflowConfigAndCRConfig(t *testing.T) { }, nil }, ) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, consensus)) require.NoError(t, reg.Add(ctx, target)) - eng, testHooks := newTestEngine( + eng, testHooks := newTestEngineWithYAMLSpec( t, reg, simpleWorkflow, @@ -1036,16 +1078,149 @@ func TestEngine_MergesWorkflowConfigAndCRConfig(t *testing.T) { return registrysyncer.CapabilityConfiguration{}, nil } - cm, err := values.WrapMap(map[string]any{ - "deltaStage": "1s", - "schedule": "allAtOnce", + var cb []byte + cb, err = proto.Marshal(&capabilitiespb.CapabilityConfig{ + DefaultConfig: values.ProtoMap(giveRegistryConfig), }) - if err != nil { - return registrysyncer.CapabilityConfiguration{}, err + return registrysyncer.CapabilityConfiguration{ + Config: cb, + }, err + }, + }) + + servicetest.Run(t, eng) + + eid := getExecutionId(t, eng, testHooks) + + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompleted) + + // Assert that the config from the CR is merged with the default config from the registry. + m, err := values.Unwrap(gotConfig) + require.NoError(t, err) + assert.Equal(t, m.(map[string]any)["deltaStage"], "1s") + assert.Equal(t, m.(map[string]any)["schedule"], "allAtOnce") + + for _, k := range wantConfigKeys { + assert.Contains(t, m.(map[string]any), k) + } +} + +const customComputeWorkflow = ` +triggers: + - id: "mercury-trigger@1.0.0" + config: + feedlist: + - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD + - "0x2222222222222222222200000000000000000000000000000000000000000000" # LINKUSD + - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD + +actions: + - id: custom_compute@1.0.0 + ref: custom_compute + config: + maxMemoryMBs: 128 + tickInterval: 100ms + timeout: 300ms + inputs: + action: + - $(trigger.outputs) + +consensus: + - id: "offchain_reporting@1.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + +targets: + - id: "write_ethereum-testnet-sepolia@1.0.0" + inputs: "$(evm_median.outputs)" + config: + address: "0x54e220867af6683aE6DcBF535B4f952cB5116510" + params: ["$(report)"] + abi: "receive(report bytes)" +` + +// TestEngine_MergesWorkflowConfigAndCRConfig_CRConfigPrecedence tests that the engine merges the +// workflow config with the CR config, with the CR config taking precedence. +func TestEngine_MergesWorkflowConfigAndCRConfig_CRConfigPrecedence(t *testing.T) { + var ( + ctx = testutils.Context(t) + actionID = "custom_compute@1.0.0" + giveTimeout = 300 * time.Millisecond + giveTickInterval = 100 * time.Millisecond + registryConfig = map[string]any{ + "maxMemoryMBs": int64(64), + "timeout": giveTimeout.String(), + "tickInterval": giveTickInterval.String(), + } + gotConfig = values.EmptyMap() + ) + + giveRegistryConfig, err := values.WrapMap(registryConfig) + assert.NoError(t, err, "failed to wrap map of registry config") + + // Mock the capabilities of the simple workflow. + reg := coreCap.NewRegistry(logger.TestLogger(t)) + trigger, _ := mockTrigger(t) + target := mockTarget("write_ethereum-testnet-sepolia@1.0.0") + action := newMockCapability( + // Create a remote capability so we don't use the local transmission protocol. + capabilities.MustNewRemoteCapabilityInfo( + actionID, + capabilities.CapabilityTypeAction, + "a custom compute action with custom config", + &capabilities.DON{ID: 1}, + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + // Replace the empty config with the write target config. + gotConfig = req.Config + + return capabilities.CapabilityResponse{ + Value: req.Inputs, + }, nil + }, + ) + + consensus := mockConsensus("") + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, action)) + require.NoError(t, reg.Add(ctx, target)) + require.NoError(t, reg.Add(ctx, consensus)) + + eng, testHooks := newTestEngineWithYAMLSpec( + t, + reg, + customComputeWorkflow, + ) + reg.SetLocalRegistry(testConfigProvider{ + configForCapability: func(ctx context.Context, capabilityID string, donID uint32) (registrysyncer.CapabilityConfiguration, error) { + if capabilityID != actionID { + return registrysyncer.CapabilityConfiguration{}, nil } - cb, err := proto.Marshal(&capabilitiespb.CapabilityConfig{ - DefaultConfig: values.ProtoMap(cm), + var cb []byte + cb, err = proto.Marshal(&capabilitiespb.CapabilityConfig{ + DefaultConfig: values.ProtoMap(giveRegistryConfig), }) return registrysyncer.CapabilityConfiguration{ Config: cb, @@ -1062,10 +1237,13 @@ func TestEngine_MergesWorkflowConfigAndCRConfig(t *testing.T) { assert.Equal(t, state.Status, store.StatusCompleted) + // Assert that the config from the CR is merged with the default config from the registry. With + // the CR config taking precedence. m, err := values.Unwrap(gotConfig) require.NoError(t, err) - assert.Equal(t, m.(map[string]any)["deltaStage"], "1s") - assert.Equal(t, m.(map[string]any)["schedule"], "allAtOnce") + assert.Equalf(t, registryConfig["maxMemoryMBs"], m.(map[string]any)["maxMemoryMBs"], "maxMemoryMBs should be %d", registryConfig["maxMemoryMBs"]) + assert.Equalf(t, registryConfig["timeout"], m.(map[string]any)["timeout"], "timeout should be %s", registryConfig["timeout"]) + assert.Equalf(t, registryConfig["tickInterval"], m.(map[string]any)["tickInterval"], "tickInterval should be %s", registryConfig["tickInterval"]) } func TestEngine_HandlesNilConfigOnchain(t *testing.T) { @@ -1075,7 +1253,7 @@ func TestEngine_HandlesNilConfigOnchain(t *testing.T) { trigger, _ := mockTrigger(t) require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) writeID := "write_polygon-testnet-mumbai@1.0.0" gotConfig := values.EmptyMap() @@ -1097,7 +1275,7 @@ func TestEngine_HandlesNilConfigOnchain(t *testing.T) { ) require.NoError(t, reg.Add(ctx, target)) - eng, testHooks := newTestEngine( + eng, testHooks := newTestEngineWithYAMLSpec( t, reg, simpleWorkflow, @@ -1118,3 +1296,241 @@ func TestEngine_HandlesNilConfigOnchain(t *testing.T) { // The write target config contains three keys assert.Len(t, m.(map[string]any), 3) } + +func TestEngine_MultiBranchExecution(t *testing.T) { + // This workflow describes 2 branches in the workflow graph. + // A -> B -> C + // A -> D -> E + workflowSpec := ` +triggers: + - id: "mercury-trigger@1.0.0" + config: + feedlist: + - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD + - "0x2222222222222222222200000000000000000000000000000000000000000000" # LINKUSD + - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD + +consensus: + - id: "offchain_reporting@1.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + - id: "early_exit_offchain_reporting@1.0.0" + ref: "evm_median_early_exit" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + +targets: + - id: "write_polygon-testnet-mumbai@1.0.0" + inputs: + report: "$(evm_median.outputs.report)" + config: + address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" + params: ["$(report)"] + abi: "receive(report bytes)" + - id: "write_polygon-testnet-early-exit@1.0.0" + inputs: + report: "$(evm_median_early_exit.outputs.report)" + config: + address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" + params: ["$(report)"] + abi: "receive(report bytes)" +` + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, _ := mockTrigger(t) + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus(""))) + require.NoError(t, reg.Add(ctx, mockConsensusWithEarlyTermination("early_exit_offchain_reporting@1.0.0"))) + require.NoError(t, reg.Add(ctx, mockTarget(""))) + require.NoError(t, reg.Add(ctx, mockTarget("write_polygon-testnet-early-exit@1.0.0"))) + + eng, hooks := newTestEngineWithYAMLSpec(t, reg, workflowSpec) + servicetest.Run(t, eng) + + eid := getExecutionId(t, eng, hooks) + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, store.StatusCompletedEarlyExit, state.Status) +} + +func basicTestTrigger(t *testing.T) *mockTriggerCapability { + mt := &mockTriggerCapability{ + CapabilityInfo: capabilities.MustNewCapabilityInfo( + "basic-test-trigger@1.0.0", + capabilities.CapabilityTypeTrigger, + "basic test trigger", + ), + ch: make(chan capabilities.TriggerResponse, 10), + } + + resp, err := values.NewMap(map[string]any{ + "cool_output": "foo", + }) + require.NoError(t, err) + tr := capabilities.TriggerResponse{ + Event: capabilities.TriggerEvent{ + TriggerType: mt.ID, + ID: time.Now().UTC().Format(time.RFC3339), + Outputs: resp, + }, + } + mt.triggerEvent = &tr + return mt +} + +func TestEngine_WithCustomComputeStep(t *testing.T) { + cmd := "core/services/workflows/test/wasm/cmd" + binary := "test/wasm/cmd/testmodule.wasm" + + ctx := testutils.Context(t) + log := logger.TestLogger(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + cfg := webapi.ServiceConfig{ + RateLimiter: common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + }, + } + + connector := gcmocks.NewGatewayConnector(t) + handler, err := webapi.NewOutgoingConnectorHandler( + connector, + cfg, + ghcapabilities.MethodComputeAction, log) + require.NoError(t, err) + + idGeneratorFn := func() string { return "validRequestID" } + compute := compute.NewAction(cfg, log, reg, handler, idGeneratorFn) + require.NoError(t, compute.Start(ctx)) + defer compute.Close() + + trigger := basicTestTrigger(t) + require.NoError(t, reg.Add(ctx, trigger)) + + binaryB := wasmtest.CreateTestBinary(cmd, binary, true, t) + + spec, err := host.GetWorkflowSpec( + &host.ModuleConfig{Logger: log}, + binaryB, + nil, // config + ) + require.NoError(t, err) + eng, testHooks := newTestEngine( + t, + reg, + *spec, + func(c *Config) { + c.Binary = binaryB + c.Config = nil + }, + ) + reg.SetLocalRegistry(testConfigProvider{}) + + servicetest.Run(t, eng) + + eid := getExecutionId(t, eng, testHooks) + + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompleted) + res, ok := state.ResultForStep("compute") + assert.True(t, ok) + assert.True(t, res.Outputs.(*values.Map).Underlying["Value"].(*values.Bool).Underlying) +} + +func TestEngine_CustomComputePropagatesBreaks(t *testing.T) { + cmd := "core/services/workflows/test/break/cmd" + binary := "test/wasm/break/testmodule.wasm" + + ctx := testutils.Context(t) + log := logger.TestLogger(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + cfg := webapi.ServiceConfig{ + RateLimiter: common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + }, + } + connector := gcmocks.NewGatewayConnector(t) + handler, err := webapi.NewOutgoingConnectorHandler( + connector, + cfg, + ghcapabilities.MethodComputeAction, log) + require.NoError(t, err) + + idGeneratorFn := func() string { return "validRequestID" } + compute := compute.NewAction(cfg, log, reg, handler, idGeneratorFn) + require.NoError(t, compute.Start(ctx)) + defer compute.Close() + + trigger := basicTestTrigger(t) + require.NoError(t, reg.Add(ctx, trigger)) + + binaryB := wasmtest.CreateTestBinary(cmd, binary, true, t) + + spec, err := host.GetWorkflowSpec( + &host.ModuleConfig{Logger: log}, + binaryB, + nil, // config + ) + require.NoError(t, err) + eng, testHooks := newTestEngine( + t, + reg, + *spec, + func(c *Config) { + c.Binary = binaryB + c.Config = nil + }, + ) + reg.SetLocalRegistry(testConfigProvider{}) + + servicetest.Run(t, eng) + + eid := getExecutionId(t, eng, testHooks) + + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompletedEarlyExit) +} diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index 1ff77225c4b..f6adb737264 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -7,6 +7,8 @@ import ( "github.com/dominikbraun/graph" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink-common/pkg/workflows" @@ -25,7 +27,7 @@ type workflow struct { triggers []*triggerCapability - spec *workflows.WorkflowSpec + spec *sdk.WorkflowSpec } func (w *workflow) walkDo(start string, do func(s *step) error) error { @@ -52,8 +54,9 @@ func (w *workflow) walkDo(start string, do func(s *step) error) error { return outerErr } +// dependents returns all steps that directly depend on the step with the given ref func (w *workflow) dependents(start string) ([]*step, error) { - steps := []*step{} + var steps []*step m, err := w.Graph.AdjacencyMap() if err != nil { return nil, err @@ -79,24 +82,26 @@ func (w *workflow) dependents(start string) ([]*step, error) { // step wraps a Vertex with additional context for execution that is mutated by the engine type step struct { workflows.Vertex - capability capabilities.CallbackCapability + capability capabilities.ExecutableCapability info capabilities.CapabilityInfo config *values.Map } type triggerCapability struct { - workflows.StepDefinition + sdk.StepDefinition trigger capabilities.TriggerCapability config atomic.Pointer[values.Map] } -func Parse(yamlWorkflow string) (*workflow, error) { - wf2, err := workflows.ParseDependencyGraph(yamlWorkflow) +func Parse(sdkSpec sdk.WorkflowSpec) (*workflow, error) { + wf2, err := workflows.BuildDependencyGraph(sdkSpec) if err != nil { return nil, err } - return createWorkflow(wf2) + + wfs, err := createWorkflow(wf2) + return wfs, err } // createWorkflow converts a StaticWorkflow to an executable workflow diff --git a/core/services/workflows/models_test.go b/core/services/workflows/models_test.go index a28aeb9df01..f7cb25f2edc 100644 --- a/core/services/workflows/models_test.go +++ b/core/services/workflows/models_test.go @@ -7,6 +7,9 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/workflows" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/job" ) func TestParse_Graph(t *testing.T) { @@ -290,7 +293,10 @@ targets: for _, tc := range testCases { t.Run(tc.name, func(st *testing.T) { - wf, err := Parse(tc.yaml) + spec, _, _, err := job.YAMLSpecFactory{}.Spec(testutils.Context(t), tc.yaml, "") + require.NoError(t, err) + + wf, err := Parse(spec) if tc.errMsg != "" { assert.ErrorContains(st, err, tc.errMsg) } else { @@ -316,7 +322,10 @@ targets: } func TestParsesIntsCorrectly(t *testing.T) { - wf, err := Parse(hardcodedWorkflow) + spec, _, _, err := job.YAMLSpecFactory{}.Spec(testutils.Context(t), hardcodedWorkflow, "") + require.NoError(t, err) + + wf, err := Parse(spec) require.NoError(t, err) n, err := wf.Vertex("evm_median") diff --git a/core/services/workflows/monitoring.go b/core/services/workflows/monitoring.go new file mode 100644 index 00000000000..7c978196b13 --- /dev/null +++ b/core/services/workflows/monitoring.go @@ -0,0 +1,95 @@ +package workflows + +import ( + "context" + "fmt" + + "go.opentelemetry.io/otel/metric" + + "github.com/smartcontractkit/chainlink-common/pkg/beholder" + "github.com/smartcontractkit/chainlink/v2/core/monitoring" +) + +var registerTriggerFailureCounter metric.Int64Counter +var workflowsRunningGauge metric.Int64Gauge +var capabilityInvocationCounter metric.Int64Counter +var workflowExecutionLatencyGauge metric.Int64Gauge //ms +var workflowStepErrorCounter metric.Int64Counter + +func initMonitoringResources() (err error) { + registerTriggerFailureCounter, err = beholder.GetMeter().Int64Counter("RegisterTriggerFailure") + if err != nil { + return fmt.Errorf("failed to register trigger failure counter: %w", err) + } + + workflowsRunningGauge, err = beholder.GetMeter().Int64Gauge("WorkflowsRunning") + if err != nil { + return fmt.Errorf("failed to register workflows running gauge: %w", err) + } + + capabilityInvocationCounter, err = beholder.GetMeter().Int64Counter("CapabilityInvocation") + if err != nil { + return fmt.Errorf("failed to register capability invocation counter: %w", err) + } + + workflowExecutionLatencyGauge, err = beholder.GetMeter().Int64Gauge("WorkflowExecutionLatency") + if err != nil { + return fmt.Errorf("failed to register workflow execution latency gauge: %w", err) + } + + workflowStepErrorCounter, err = beholder.GetMeter().Int64Counter("WorkflowStepError") + if err != nil { + return fmt.Errorf("failed to register workflow step error counter: %w", err) + } + + return nil +} + +// workflowsMetricLabeler wraps monitoring.MetricsLabeler to provide workflow specific utilities +// for monitoring resources +type workflowsMetricLabeler struct { + monitoring.MetricsLabeler +} + +func (c workflowsMetricLabeler) with(keyValues ...string) workflowsMetricLabeler { + return workflowsMetricLabeler{c.With(keyValues...)} +} + +func (c workflowsMetricLabeler) incrementRegisterTriggerFailureCounter(ctx context.Context) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + registerTriggerFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementCapabilityInvocationCounter(ctx context.Context) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + capabilityInvocationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateWorkflowExecutionLatencyGauge(ctx context.Context, val int64) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + workflowExecutionLatencyGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementTotalWorkflowStepErrorsCounter(ctx context.Context) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + workflowStepErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateTotalWorkflowsGauge(ctx context.Context, val int64) { + otelLabels := monitoring.KvMapToOtelAttributes(c.Labels) + workflowsRunningGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) +} + +// Observability keys +const ( + cIDKey = "capabilityID" + tIDKey = "triggerID" + wIDKey = "workflowID" + eIDKey = "workflowExecutionID" + wnKey = "workflowName" + woIDKey = "workflowOwner" + sIDKey = "stepID" + sRKey = "stepRef" +) + +var orderedLabelKeys = []string{sRKey, sIDKey, tIDKey, cIDKey, eIDKey, wIDKey} diff --git a/core/services/workflows/monitoring_test.go b/core/services/workflows/monitoring_test.go new file mode 100644 index 00000000000..c0576b25a93 --- /dev/null +++ b/core/services/workflows/monitoring_test.go @@ -0,0 +1,19 @@ +package workflows + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/monitoring" +) + +func Test_InitMonitoringResources(t *testing.T) { + require.NoError(t, initMonitoringResources()) +} + +func Test_WorkflowMetricsLabeler(t *testing.T) { + testWorkflowsMetricLabeler := workflowsMetricLabeler{monitoring.NewMetricsLabeler()} + testWorkflowsMetricLabeler2 := testWorkflowsMetricLabeler.with("foo", "baz") + require.EqualValues(t, testWorkflowsMetricLabeler2.Labels["foo"], "baz") +} diff --git a/core/services/workflows/state.go b/core/services/workflows/state.go index 28eca199a4d..3a67f82a1ed 100644 --- a/core/services/workflows/state.go +++ b/core/services/workflows/state.go @@ -1,14 +1,9 @@ package workflows import ( - "fmt" - "strconv" - "strings" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink-common/pkg/workflows" ) // copyState returns a deep copy of the input executionState @@ -20,7 +15,7 @@ func copyState(es store.WorkflowExecution) store.WorkflowExecution { mval = step.Inputs.CopyMap() } - copiedov := step.Outputs.Value.Copy() + copiedov := values.Copy(step.Outputs.Value) newState := &store.WorkflowExecutionStep{ ExecutionID: step.ExecutionID, @@ -44,93 +39,3 @@ func copyState(es store.WorkflowExecution) store.WorkflowExecution { Steps: steps, } } - -// interpolateKey takes a multi-part, dot-separated key and attempts to replace -// it with its corresponding value in `state`. -// -// A key is valid if it contains at least two parts, with: -// - the first part being the workflow step's `ref` variable -// - the second part being one of `inputs` or `outputs` -// -// If a key has more than two parts, then we traverse the parts -// to find the value we want to replace. -// We support traversing both nested maps and lists and any combination of the two. -func interpolateKey(key string, state store.WorkflowExecution) (any, error) { - parts := strings.Split(key, ".") - - if len(parts) < 2 { - return "", fmt.Errorf("cannot interpolate %s: must have at least two parts", key) - } - - // lookup the step we want to get either input or output state from - sc, ok := state.Steps[parts[0]] - if !ok { - return "", fmt.Errorf("could not find ref `%s`", parts[0]) - } - - var value values.Value - switch parts[1] { - case "inputs": - value = sc.Inputs - case "outputs": - if sc.Outputs.Err != nil { - return "", fmt.Errorf("cannot interpolate ref part `%s` in `%+v`: step has errored", parts[1], sc) - } - - value = sc.Outputs.Value - default: - return "", fmt.Errorf("cannot interpolate ref part `%s` in `%+v`: second part must be `inputs` or `outputs`", parts[1], sc) - } - - val, err := values.Unwrap(value) - if err != nil { - return "", err - } - - remainingParts := parts[2:] - for _, r := range remainingParts { - switch v := val.(type) { - case map[string]any: - inner, ok := v[r] - if !ok { - return "", fmt.Errorf("could not find ref part `%s` (ref: `%s`) in `%+v`", r, key, v) - } - - val = inner - case []any: - i, err := strconv.Atoi(r) - if err != nil { - return "", fmt.Errorf("could not interpolate ref part `%s` (ref: `%s`) in `%+v`: `%s` is not convertible to an int", r, key, v, r) - } - - if (i > len(v)-1) || (i < 0) { - return "", fmt.Errorf("could not interpolate ref part `%s` (ref: `%s`) in `%+v`: index out of bounds %d", r, key, v, i) - } - - val = v[i] - default: - return "", fmt.Errorf("could not interpolate ref part `%s` (ref: `%s`) in `%+v`", r, key, val) - } - } - - return val, nil -} - -// findAndInterpolateAllKeys takes an `input` any value, and recursively -// identifies any values that should be replaced from `state`. -// -// A value `v` should be replaced if it is wrapped as follows: `$(v)`. -func findAndInterpolateAllKeys(input any, state store.WorkflowExecution) (any, error) { - return workflows.DeepMap( - input, - func(el string) (any, error) { - matches := workflows.InterpolationTokenRe.FindStringSubmatch(el) - if len(matches) < 2 { - return el, nil - } - - interpolatedVar := matches[1] - return interpolateKey(interpolatedVar, state) - }, - ) -} diff --git a/core/services/workflows/state_test.go b/core/services/workflows/state_test.go deleted file mode 100644 index a9829a97c74..00000000000 --- a/core/services/workflows/state_test.go +++ /dev/null @@ -1,268 +0,0 @@ -package workflows - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" -) - -func TestInterpolateKey(t *testing.T) { - t.Parallel() - val, err := values.NewMap( - map[string]any{ - "reports": map[string]any{ - "inner": "key", - }, - "reportsList": []any{ - "listElement", - }, - }, - ) - require.NoError(t, err) - - testCases := []struct { - name string - key string - state store.WorkflowExecution - expected any - errMsg string - }{ - { - name: "digging into a string", - key: "evm_median.outputs.reports", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: values.NewString(""), - }, - }, - }, - }, - errMsg: "could not interpolate ref part `reports` (ref: `evm_median.outputs.reports`) in ``", - }, - { - name: "ref doesn't exist", - key: "evm_median.outputs.reports", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{}, - }, - errMsg: "could not find ref `evm_median`", - }, - { - name: "less than 2 parts", - key: "evm_median", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{}, - }, - errMsg: "must have at least two parts", - }, - { - name: "second part isn't `inputs` or `outputs`", - key: "evm_median.foo", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: values.NewString(""), - }, - }, - }, - }, - errMsg: "second part must be `inputs` or `outputs`", - }, - { - name: "outputs has errored", - key: "evm_median.outputs", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Err: errors.New("catastrophic error"), - }, - }, - }, - }, - errMsg: "step has errored", - }, - { - name: "digging into a recursive map", - key: "evm_median.outputs.reports.inner", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - expected: "key", - }, - { - name: "missing key in map", - key: "evm_median.outputs.reports.missing", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - errMsg: "could not find ref part `missing` (ref: `evm_median.outputs.reports.missing`) in", - }, - { - name: "digging into an array", - key: "evm_median.outputs.reportsList.0", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - expected: "listElement", - }, - { - name: "digging into an array that's too small", - key: "evm_median.outputs.reportsList.2", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - errMsg: "index out of bounds 2", - }, - { - name: "digging into an array with a string key", - key: "evm_median.outputs.reportsList.notAString", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - errMsg: "could not interpolate ref part `notAString` (ref: `evm_median.outputs.reportsList.notAString`) in `[listElement]`: `notAString` is not convertible to an int", - }, - { - name: "digging into an array with a negative index", - key: "evm_median.outputs.reportsList.-1", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - errMsg: "could not interpolate ref part `-1` (ref: `evm_median.outputs.reportsList.-1`) in `[listElement]`: index out of bounds -1", - }, - { - name: "empty element", - key: "evm_median.outputs..notAString", - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: val, - }, - }, - }, - }, - errMsg: "could not find ref part `` (ref: `evm_median.outputs..notAString`) in", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(st *testing.T) { - got, err := interpolateKey(tc.key, tc.state) - if tc.errMsg != "" { - require.ErrorContains(st, err, tc.errMsg) - } else { - require.NoError(t, err) - assert.Equal(t, tc.expected, got) - } - }) - } -} - -func TestInterpolateInputsFromState(t *testing.T) { - t.Parallel() - testCases := []struct { - name string - inputs map[string]any - state store.WorkflowExecution - expected any - errMsg string - }{ - { - name: "substituting with a variable that exists", - inputs: map[string]any{ - "shouldnotinterpolate": map[string]any{ - "shouldinterpolate": "$(evm_median.outputs)", - }, - }, - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: values.NewString(""), - }, - }, - }, - }, - expected: map[string]any{ - "shouldnotinterpolate": map[string]any{ - "shouldinterpolate": "", - }, - }, - }, - { - name: "no substitution required", - inputs: map[string]any{ - "foo": "bar", - }, - state: store.WorkflowExecution{ - Steps: map[string]*store.WorkflowExecutionStep{ - "evm_median": { - Outputs: store.StepOutput{ - Value: values.NewString(""), - }, - }, - }, - }, - expected: map[string]any{ - "foo": "bar", - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(st *testing.T) { - got, err := findAndInterpolateAllKeys(tc.inputs, tc.state) - if tc.errMsg != "" { - require.ErrorContains(st, err, tc.errMsg) - } else { - require.NoError(t, err) - assert.Equal(t, tc.expected, got) - } - }) - } -} diff --git a/core/services/workflows/store/models.go b/core/services/workflows/store/models.go index 275ca85b4fc..b7c7d189ad8 100644 --- a/core/services/workflows/store/models.go +++ b/core/services/workflows/store/models.go @@ -4,6 +4,7 @@ import ( "time" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/exec" ) // Note: any update to the enum below should be reflected in @@ -50,3 +51,18 @@ type WorkflowExecution struct { UpdatedAt *time.Time FinishedAt *time.Time } + +func (w WorkflowExecution) ResultForStep(s string) (*exec.Result, bool) { + step, ok := w.Steps[s] + if !ok { + return &exec.Result{}, false + } + + return &exec.Result{ + Inputs: step.Inputs, + Outputs: step.Outputs.Value, + Error: step.Outputs.Err, + }, true +} + +var _ exec.Results = WorkflowExecution{} diff --git a/core/services/workflows/store/store.go b/core/services/workflows/store/store.go index 72045ea062c..9f77cf3380e 100644 --- a/core/services/workflows/store/store.go +++ b/core/services/workflows/store/store.go @@ -5,7 +5,7 @@ import ( ) type Store interface { - Add(ctx context.Context, state *WorkflowExecution) error + Add(ctx context.Context, state *WorkflowExecution) (WorkflowExecution, error) UpsertStep(ctx context.Context, step *WorkflowExecutionStep) (WorkflowExecution, error) UpdateStatus(ctx context.Context, executionID string, status string) error Get(ctx context.Context, executionID string) (WorkflowExecution, error) diff --git a/core/services/workflows/store/store_db.go b/core/services/workflows/store/store_db.go index 80ecfbb2d6e..a070062aee6 100644 --- a/core/services/workflows/store/store_db.go +++ b/core/services/workflows/store/store_db.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/values" valuespb "github.com/smartcontractkit/chainlink-common/pkg/values/pb" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -49,6 +50,26 @@ type workflowStepRow struct { UpdatedAt *time.Time `db:"updated_at"` } +// workflowExecutionWithStep is a struct that represents a row from the join of the workflow_executions and workflow_steps tables. +type workflowExecutionWithStep struct { + // WorkflowExecutionStep fields + WSWorkflowExecutionID string `db:"ws_workflow_execution_id"` + WSRef string `db:"ws_ref"` + WSStatus string `db:"ws_status"` + WSInputs []byte `db:"ws_inputs"` + WSOutputErr *string `db:"ws_output_err"` + WSOutputValue []byte `db:"ws_output_value"` + WSUpdatedAt *time.Time `db:"ws_updated_at"` + + // WorkflowExecution fields + WEID string `db:"we_id"` + WEWorkflowID *string `db:"we_workflow_id"` + WEStatus string `db:"we_status"` + WECreatedAt *time.Time `db:"we_created_at"` + WEUpdatedAt *time.Time `db:"we_updated_at"` + WEFinishedAt *time.Time `db:"we_finished_at"` +} + // `UpdateStatus` updates the status of the given workflow execution func (d *DBStore) UpdateStatus(ctx context.Context, executionID string, status string) error { sql := `UPDATE workflow_executions SET status = $1, updated_at = $2 WHERE id = $3` @@ -77,45 +98,80 @@ func (d *DBStore) UpsertStep(ctx context.Context, stepState *WorkflowExecutionSt return d.Get(ctx, step.WorkflowExecutionID) } -// `Get` fetches the ExecutionState from the database. +// Get fetches the ExecutionState from the database. func (d *DBStore) Get(ctx context.Context, executionID string) (WorkflowExecution, error) { - wex := &workflowExecutionRow{} - err := d.db.GetContext(ctx, wex, `SELECT * FROM workflow_executions WHERE id = $1`, executionID) + sql := ` + SELECT + workflow_executions.id AS we_id, + workflow_executions.workflow_id AS we_workflow_id, + workflow_executions.status AS we_status, + workflow_executions.created_at AS we_created_at, + workflow_executions.updated_at AS we_updated_at, + workflow_executions.finished_at AS we_finished_at, + workflow_steps.workflow_execution_id AS ws_workflow_execution_id, + workflow_steps.ref AS ws_ref, + workflow_steps.status AS ws_status, + workflow_steps.inputs AS ws_inputs, + workflow_steps.output_err AS ws_output_err, + workflow_steps.output_value AS ws_output_value, + workflow_steps.updated_at AS ws_updated_at + FROM workflow_executions JOIN workflow_steps + ON workflow_executions.id = workflow_steps.workflow_execution_id + WHERE workflow_executions.id = $1` + + var records []workflowExecutionWithStep + err := d.db.SelectContext(ctx, &records, sql, executionID) if err != nil { return WorkflowExecution{}, err } - - ws := []workflowStepRow{} - err = d.db.SelectContext(ctx, &ws, `SELECT * FROM workflow_steps WHERE workflow_execution_id = $1`, wex.ID) + idToExecutionState, err := workflowExecutionsWithStepToWorkflowExecutions(records) if err != nil { return WorkflowExecution{}, err } + state, ok := idToExecutionState[executionID] + if !ok { + return WorkflowExecution{}, fmt.Errorf("could not find workflow execution with id %s", executionID) + } + return *state, nil +} - refToStep := map[string]*WorkflowExecutionStep{} - for _, s := range ws { - ss, err := stepToState(s) - if err != nil { - return WorkflowExecution{}, err +func workflowExecutionsWithStepToWorkflowExecutions(wews []workflowExecutionWithStep) (map[string]*WorkflowExecution, error) { + idToExecutionState := map[string]*WorkflowExecution{} + for _, jr := range wews { + var wid string + if jr.WEWorkflowID != nil { + wid = *jr.WEWorkflowID + } + if _, ok := idToExecutionState[jr.WEID]; !ok { + idToExecutionState[jr.WEID] = &WorkflowExecution{ + ExecutionID: jr.WEID, + WorkflowID: wid, + Status: jr.WEStatus, + Steps: map[string]*WorkflowExecutionStep{}, + CreatedAt: jr.WECreatedAt, + UpdatedAt: jr.WEUpdatedAt, + FinishedAt: jr.WEFinishedAt, + } } - refToStep[s.Ref] = ss - } + state, err := stepToState(workflowStepRow{ + WorkflowExecutionID: jr.WSWorkflowExecutionID, + Ref: jr.WSRef, + OutputErr: jr.WSOutputErr, + OutputValue: jr.WSOutputValue, + Inputs: jr.WSInputs, + Status: jr.WSStatus, + UpdatedAt: jr.WSUpdatedAt, + }) + if err != nil { + return nil, err + } - var workflowID string - if wex.WorkflowID != nil { - workflowID = *wex.WorkflowID + es := idToExecutionState[jr.WEID] + es.Steps[state.Ref] = state } - es := WorkflowExecution{ - ExecutionID: wex.ID, - WorkflowID: workflowID, - Status: wex.Status, - Steps: refToStep, - CreatedAt: wex.CreatedAt, - UpdatedAt: wex.UpdatedAt, - FinishedAt: wex.FinishedAt, - } - return es, nil + return idToExecutionState, nil } func stepToState(step workflowStepRow) (*WorkflowExecutionStep, error) { @@ -202,11 +258,12 @@ func stateToStep(state *WorkflowExecutionStep) (workflowStepRow, error) { return wsr, nil } -// `Add` creates the relevant workflow_execution and workflow_step entries +// Add creates the relevant workflow_execution and workflow_step entries // to persist the passed in ExecutionState. -func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { +func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) (WorkflowExecution, error) { l := d.lggr.With("executionID", state.ExecutionID, "workflowID", state.WorkflowID, "status", state.Status) - return d.transact(ctx, func(db *DBStore) error { + var workflowExecution WorkflowExecution + err := d.transact(ctx, func(db *DBStore) error { var wid *string if state.WorkflowID != "" { wid = &state.WorkflowID @@ -219,12 +276,23 @@ func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { } l.Debug("Adding workflow execution") - err := db.insertWorkflowExecution(ctx, wex) + dbWex, err := db.insertWorkflowExecution(ctx, wex) if err != nil { return fmt.Errorf("could not insert workflow execution %s: %w", state.ExecutionID, err) } - - ws := []workflowStepRow{} + workflowExecution = WorkflowExecution{ + ExecutionID: dbWex.ID, + Status: dbWex.Status, + Steps: state.Steps, + CreatedAt: dbWex.CreatedAt, + UpdatedAt: dbWex.UpdatedAt, + FinishedAt: dbWex.FinishedAt, + } + // Tests are not passing the ID, so to avoid a nil-pointer dereference, we added this check. + if wid != nil { + workflowExecution.WorkflowID = *wid + } + var ws []workflowStepRow for _, step := range state.Steps { step, err := stateToStep(step) if err != nil { @@ -238,6 +306,8 @@ func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { } return nil }) + + return workflowExecution, err } func (d *DBStore) upsertSteps(ctx context.Context, steps []workflowStepRow) error { @@ -269,14 +339,15 @@ func (d *DBStore) upsertSteps(ctx context.Context, steps []workflowStepRow) erro return err } -func (d *DBStore) insertWorkflowExecution(ctx context.Context, execution *workflowExecutionRow) error { +func (d *DBStore) insertWorkflowExecution(ctx context.Context, execution *workflowExecutionRow) (*workflowExecutionRow, error) { sql := ` INSERT INTO workflow_executions(id, workflow_id, status, created_at) - VALUES ($1, $2, $3, $4) + VALUES ($1, $2, $3, $4) RETURNING * ` - _, err := d.db.ExecContext(ctx, sql, execution.ID, execution.WorkflowID, execution.Status, d.clock.Now()) - return err + wex := &workflowExecutionRow{} + err := d.db.GetContext(ctx, wex, sql, execution.ID, execution.WorkflowID, execution.Status, d.clock.Now()) + return wex, err } func (d *DBStore) transact(ctx context.Context, fn func(*DBStore) error) error { @@ -315,65 +386,18 @@ func (d *DBStore) GetUnfinished(ctx context.Context, offset, limit int) ([]Workf LIMIT $2 OFFSET $3 ` - joinRecords := []struct { - // WorkflowExecutionStep fields - WSWorkflowExecutionID string `db:"ws_workflow_execution_id"` - WSRef string `db:"ws_ref"` - WSStatus string `db:"ws_status"` - WSInputs []byte `db:"ws_inputs"` - WSOutputErr *string `db:"ws_output_err"` - WSOutputValue []byte `db:"ws_output_value"` - WSUpdatedAt *time.Time `db:"ws_updated_at"` - - // WorkflowExecution fields - WEID string `db:"we_id"` - WEWorkflowID *string `db:"we_workflow_id"` - WEStatus string `db:"we_status"` - WECreatedAt *time.Time `db:"we_created_at"` - WEUpdatedAt *time.Time `db:"we_updated_at"` - WEFinishedAt *time.Time `db:"we_finished_at"` - }{} + var joinRecords []workflowExecutionWithStep err := d.db.SelectContext(ctx, &joinRecords, sql, StatusStarted, limit, offset) if err != nil { return []WorkflowExecution{}, err } - idToExecutionState := map[string]*WorkflowExecution{} - for _, jr := range joinRecords { - var wid string - if jr.WEWorkflowID != nil { - wid = *jr.WEWorkflowID - } - if _, ok := idToExecutionState[jr.WEID]; !ok { - idToExecutionState[jr.WEID] = &WorkflowExecution{ - ExecutionID: jr.WEID, - WorkflowID: wid, - Status: jr.WEStatus, - Steps: map[string]*WorkflowExecutionStep{}, - CreatedAt: jr.WECreatedAt, - UpdatedAt: jr.WEUpdatedAt, - FinishedAt: jr.WEFinishedAt, - } - } - - state, err := stepToState(workflowStepRow{ - WorkflowExecutionID: jr.WSWorkflowExecutionID, - Ref: jr.WSRef, - OutputErr: jr.WSOutputErr, - OutputValue: jr.WSOutputValue, - Inputs: jr.WSInputs, - Status: jr.WSStatus, - UpdatedAt: jr.WSUpdatedAt, - }) - if err != nil { - return nil, err - } - - es := idToExecutionState[jr.WEID] - es.Steps[state.Ref] = state + idToExecutionState, err := workflowExecutionsWithStepToWorkflowExecutions(joinRecords) + if err != nil { + return []WorkflowExecution{}, err } - states := []WorkflowExecution{} + var states []WorkflowExecution for _, s := range idToExecutionState { states = append(states, *s) } diff --git a/core/services/workflows/store/store_db_test.go b/core/services/workflows/store/store_db_test.go index 9a98db3056f..1b58f816e59 100644 --- a/core/services/workflows/store/store_db_test.go +++ b/core/services/workflows/store/store_db_test.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -51,7 +52,7 @@ func Test_StoreDB(t *testing.T) { Status: StatusStarted, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) gotEs, err := store.Get(tests.Context(t), es.ExecutionID) @@ -83,10 +84,10 @@ func Test_StoreDB_DuplicateEntry(t *testing.T) { Status: StatusStarted, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) - err = store.Add(tests.Context(t), &es) + _, err = store.Add(tests.Context(t), &es) assert.ErrorContains(t, err, "duplicate key value violates") } @@ -111,7 +112,7 @@ func Test_StoreDB_UpdateStatus(t *testing.T) { Status: StatusStarted, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) completedStatus := StatusCompleted @@ -147,7 +148,7 @@ func Test_StoreDB_UpdateStep(t *testing.T) { Status: StatusStarted, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) stepOne.Status = StatusCompleted @@ -195,7 +196,7 @@ func Test_StoreDB_WorkflowStatus(t *testing.T) { Status: s, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) } } @@ -223,7 +224,7 @@ func Test_StoreDB_WorkflowStepStatus(t *testing.T) { Status: StatusStarted, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) for s := range ValidStatuses { @@ -256,7 +257,7 @@ func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { Status: StatusStarted, } - err := store.Add(tests.Context(t), &es) + _, err := store.Add(tests.Context(t), &es) require.NoError(t, err) id = randomID() @@ -265,7 +266,7 @@ func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { Status: StatusCompleted, Steps: map[string]*WorkflowExecutionStep{}, } - err = store.Add(tests.Context(t), &esTwo) + _, err = store.Add(tests.Context(t), &esTwo) require.NoError(t, err) states, err := store.GetUnfinished(tests.Context(t), 0, 100) diff --git a/core/services/workflows/test/break/cmd/main.go b/core/services/workflows/test/break/cmd/main.go new file mode 100644 index 00000000000..498d3b7b906 --- /dev/null +++ b/core/services/workflows/test/break/cmd/main.go @@ -0,0 +1,38 @@ +//go:build wasip1 + +package main + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/testdata/fixtures/capabilities/basictrigger" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) + + triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} + trigger := triggerCfg.New(workflow) + + sdk.Compute1( + workflow, + "compute", + sdk.Compute1Inputs[basictrigger.TriggerOutputs]{Arg0: trigger}, + func(_ sdk.Runtime, outputs basictrigger.TriggerOutputs) (bool, error) { + return false, sdk.BreakErr + }) + + return workflow +} + +func main() { + runner := wasm.NewRunner() + workflow := BuildWorkflow(runner.Config()) + runner.Run(workflow) +} diff --git a/core/services/workflows/test/wasm/cmd/main.go b/core/services/workflows/test/wasm/cmd/main.go new file mode 100644 index 00000000000..e496ab6ffa6 --- /dev/null +++ b/core/services/workflows/test/wasm/cmd/main.go @@ -0,0 +1,38 @@ +//go:build wasip1 + +package main + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/testdata/fixtures/capabilities/basictrigger" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk" +) + +func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) + + triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} + trigger := triggerCfg.New(workflow) + + sdk.Compute1( + workflow, + "compute", + sdk.Compute1Inputs[basictrigger.TriggerOutputs]{Arg0: trigger}, + func(sdk sdk.Runtime, outputs basictrigger.TriggerOutputs) (bool, error) { + return outputs.CoolOutput == "foo", nil + }) + + return workflow +} + +func main() { + runner := wasm.NewRunner() + workflow := BuildWorkflow(runner.Config()) + runner.Run(workflow) +} diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go index f4e91f0a2d2..adbc0ca2f66 100644 --- a/core/store/migrate/migrate_test.go +++ b/core/store/migrate/migrate_test.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/config/env" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -28,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) type OffchainReporting2OracleSpec100 struct { diff --git a/core/store/migrate/migrations/0250_ccip_token_prices_fix.sql b/core/store/migrate/migrations/0250_ccip_token_prices_fix.sql new file mode 100644 index 00000000000..6c6cf02b43f --- /dev/null +++ b/core/store/migrate/migrations/0250_ccip_token_prices_fix.sql @@ -0,0 +1,49 @@ +-- +goose Up + +-- We need to re-create tables from scratch because of the unique constraint on tokens and chains selectors +DROP TABLE ccip.observed_token_prices; +DROP TABLE ccip.observed_gas_prices; + +CREATE TABLE ccip.observed_token_prices +( + chain_selector NUMERIC(20, 0) NOT NULL, + token_addr BYTEA NOT NULL, + token_price NUMERIC(78, 0) NOT NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + PRIMARY KEY (chain_selector, token_addr) +); + +CREATE TABLE ccip.observed_gas_prices +( + chain_selector NUMERIC(20, 0) NOT NULL, + source_chain_selector NUMERIC(20, 0) NOT NULL, + gas_price NUMERIC(78, 0) NOT NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + PRIMARY KEY (chain_selector, source_chain_selector) +); + +-- +goose Down +DROP TABLE ccip.observed_token_prices; +DROP TABLE ccip.observed_gas_prices; + +-- Restore state from migration 0236_ccip_prices_cache.sql +CREATE TABLE ccip.observed_gas_prices +( + chain_selector NUMERIC(20, 0) NOT NULL, + job_id INTEGER NOT NULL, + source_chain_selector NUMERIC(20, 0) NOT NULL, + gas_price NUMERIC(78, 0) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE TABLE ccip.observed_token_prices +( + chain_selector NUMERIC(20, 0) NOT NULL, + job_id INTEGER NOT NULL, + token_addr BYTEA NOT NULL, + token_price NUMERIC(78, 0) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX idx_ccip_gas_prices_chain_gas_price_timestamp ON ccip.observed_gas_prices (chain_selector, source_chain_selector, created_at DESC); +CREATE INDEX idx_ccip_token_prices_token_price_timestamp ON ccip.observed_token_prices (chain_selector, token_addr, created_at DESC); diff --git a/core/store/migrate/migrations/0251_add_don_id_to_channel_definitions.sql b/core/store/migrate/migrations/0251_add_don_id_to_channel_definitions.sql new file mode 100644 index 00000000000..9c77592b0ab --- /dev/null +++ b/core/store/migrate/migrations/0251_add_don_id_to_channel_definitions.sql @@ -0,0 +1,13 @@ +-- +goose Up +DELETE FROM channel_definitions; +ALTER TABLE channel_definitions DROP CONSTRAINT channel_definitions_pkey; +ALTER TABLE channel_definitions ADD COLUMN don_id bigint, ADD COLUMN version bigint; +ALTER TABLE channel_definitions RENAME COLUMN evm_chain_id TO chain_selector; +ALTER TABLE channel_definitions ALTER COLUMN chain_selector TYPE NUMERIC(20, 0); +ALTER TABLE channel_definitions ADD PRIMARY KEY (chain_selector, addr, don_id); + +-- +goose Down +ALTER TABLE channel_definitions DROP COLUMN don_id, DROP COLUMN version; +ALTER TABLE channel_definitions RENAME COLUMN chain_selector TO evm_chain_id; +ALTER TABLE channel_definitions ALTER COLUMN evm_chain_id TYPE bigint; +ALTER TABLE channel_definitions ADD PRIMARY KEY (evm_chain_id, addr); diff --git a/core/store/migrate/migrations/0252_add_llo_transmit_requests.sql b/core/store/migrate/migrations/0252_add_llo_transmit_requests.sql new file mode 100644 index 00000000000..d08ae0c921a --- /dev/null +++ b/core/store/migrate/migrations/0252_add_llo_transmit_requests.sql @@ -0,0 +1,21 @@ +-- +goose Up + +CREATE TABLE llo_mercury_transmit_queue ( + don_id BIGINT NOT NULL, + server_url TEXT NOT NULL, + config_digest BYTEA NOT NULL, + seq_nr BIGINT NOT NULL, + report BYTEA NOT NULL, + lifecycle_stage TEXT NOT NULL, + report_format BIGINT NOT NULL, + signatures BYTEA[] NOT NULL, + signers SMALLINT[] NOT NULL, + transmission_hash BYTEA NOT NULL, + PRIMARY KEY (transmission_hash) +); + + CREATE INDEX idx_llo_mercury_transmit_queue_don_id_server_url_seq_nr ON llo_mercury_transmit_queue (don_id, server_url, seq_nr DESC); + +-- +goose Down + +DROP TABLE llo_mercury_transmit_queue; diff --git a/core/store/migrate/migrations/0253_add_spec_type_to_workflow_spec.sql b/core/store/migrate/migrations/0253_add_spec_type_to_workflow_spec.sql new file mode 100644 index 00000000000..3c62c460976 --- /dev/null +++ b/core/store/migrate/migrations/0253_add_spec_type_to_workflow_spec.sql @@ -0,0 +1,13 @@ +-- +goose Up +-- +goose StatementBegin + +ALTER TABLE workflow_specs ADD COLUMN spec_type varchar(255) DEFAULT 'yaml'; + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +ALTER TABLE workflow_specs DROP COLUMN spec_type; + +-- +goose StatementEnd \ No newline at end of file diff --git a/core/store/migrate/migrations/0254_log_poller_primary_keys.sql b/core/store/migrate/migrations/0254_log_poller_primary_keys.sql new file mode 100644 index 00000000000..39bee02656c --- /dev/null +++ b/core/store/migrate/migrations/0254_log_poller_primary_keys.sql @@ -0,0 +1,42 @@ +-- +goose Up + +-- Replace (block_hash, log_index, evm_chain_id) primary key on evm.log_poller_blocks with new id column +ALTER TABLE evm.logs DROP CONSTRAINT logs_pkey; +ALTER TABLE evm.logs ADD COLUMN id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY; +-- Replaces previous primary key index, but also useful for accelerating DeleteLogsAndBlocksAfter +-- This also strengthens the uniqueness requirement, ensuring that we can't insert logs for two different blocks +-- with the same block number but different block hashes--something which would corrupt the db +CREATE UNIQUE INDEX idx_logs_chain_block_logindex ON evm.logs (evm_chain_id, block_number, log_index); + +-- Previously used for WHERE evm_chain_id = $1 AND address = $2 AND event_sig = $3 ... ORDER BY block_number, created_at +DROP INDEX IF EXISTS evm.idx_evm_logs_ordered_by_block_and_created_at; +-- Useful for the current form of those queries: WHERE evm_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 idx_logs_chain_address_event_block_logindex ON evm.logs (evm_chain_id, address, event_sig, block_number); + +-- Replace (block_number, evm_chain_id) primary key on evm.log_poller_blocks with new id column +ALTER TABLE evm.log_poller_blocks DROP CONSTRAINT log_poller_blocks_pkey; +ALTER TABLE evm.log_poller_blocks ADD COLUMN id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY; + +-- Add UNIQUE keyword to (evm_chain_id, block_number DESC) index (and rename for consistency) +-- This index is useful for any query for logs which includies a "confs" param, and for DeleteBlocksBefore, DeleteLogsAndBlocksAfter, etc. +-- Prior to this we also had a separate UNIQUE INDEX for (block_number, evm_chain_id) generated by the primary key defintion. +-- Adding the UNIQUE keyword to this allows us to combine the two indices into a single index, saving on disk space--with the +-- added benefit of making insertions into this index slightly faster (since it can rely on the keys being unique) +DROP INDEX IF EXISTS evm.idx_evm_log_poller_blocks_order_by_block; +CREATE UNIQUE INDEX idx_log_poller_blocks_chain_block ON evm.log_poller_blocks (evm_chain_id, block_number DESC); + +-- +goose Down + +-- revert evm.log_poller_blocks +DROP INDEX IF EXISTS evm.idx_log_poller_blocks_chain_block; +CREATE INDEX idx_evm_log_poller_blocks_order_by_block ON evm.log_poller_blocks (evm_chain_id, block_number DESC); +ALTER TABLE evm.log_poller_blocks DROP COLUMN id; +ALTER TABLE evm.log_poller_blocks ADD PRIMARY KEY (block_number, evm_chain_id); + +-- revert evm.logs +DROP INDEX IF EXISTS evm.idx_logs_chain_address_event_block_logindex; +CREATE INDEX idx_evm_logs_ordered_by_block_and_created_at ON evm.logs (evm_chain_id, address, event_sig, block_number, created_at); +DROP INDEX IF EXISTS evm.idx_logs_chain_block_logindex; +ALTER TABLE evm.logs DROP COLUMN id; +ALTER TABLE evm.logs ADD PRIMARY KEY (block_hash, log_index, evm_chain_id); diff --git a/core/store/migrate/migrations/0255_standard_capabilities_extension.sql b/core/store/migrate/migrations/0255_standard_capabilities_extension.sql new file mode 100644 index 00000000000..d81b4864eb4 --- /dev/null +++ b/core/store/migrate/migrations/0255_standard_capabilities_extension.sql @@ -0,0 +1,9 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE standardcapabilities_specs +ADD COLUMN oracle_factory JSONB; +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +ALTER TABLE standardcapabilities_specs DROP COLUMN oracle_factory; +-- +goose StatementEnd diff --git a/core/store/migrate/migrations/0256_add_config_to_workflow_spec.sql b/core/store/migrate/migrations/0256_add_config_to_workflow_spec.sql new file mode 100644 index 00000000000..8379a5ba798 --- /dev/null +++ b/core/store/migrate/migrations/0256_add_config_to_workflow_spec.sql @@ -0,0 +1,13 @@ +-- +goose Up +-- +goose StatementBegin + +ALTER TABLE workflow_specs ADD COLUMN config varchar(255) DEFAULT ''; + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +ALTER TABLE workflow_specs DROP COLUMN config; + +-- +goose StatementEnd \ No newline at end of file diff --git a/core/store/migrate/migrations/0257_add_llo_retirement_report_cache.sql b/core/store/migrate/migrations/0257_add_llo_retirement_report_cache.sql new file mode 100644 index 00000000000..d5527d43674 --- /dev/null +++ b/core/store/migrate/migrations/0257_add_llo_retirement_report_cache.sql @@ -0,0 +1,24 @@ +-- +goose Up +-- +goose StatementBegin + +CREATE TABLE llo_retirement_report_cache ( + config_digest BYTEA NOT NULL CHECK (OCTET_LENGTH(config_digest) = 32) PRIMARY KEY, + attested_retirement_report BYTEA NOT NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE TABLE llo_retirement_report_cache_configs ( + config_digest BYTEA CHECK (octet_length(config_digest) = 32) PRIMARY KEY, + signers BYTEA[] NOT NULL, + f INT NOT NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +DROP TABLE llo_retirement_report_cache_configs; +DROP TABLE llo_retirement_report_cache; + +-- +goose StatementEnd diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index 3a1798ab5ad..554b18ae818 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -1,6 +1,7 @@ package testspecs import ( + "crypto/sha256" "fmt" "strconv" "strings" @@ -10,9 +11,9 @@ import ( "github.com/google/uuid" "github.com/test-go/testify/require" - pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" @@ -899,9 +900,8 @@ func (w WorkflowJobSpec) Job() job.Job { // GenerateWorkflowJobSpec creates a WorkflowJobSpec from the given workflow yaml spec string func GenerateWorkflowJobSpec(t *testing.T, spec string) WorkflowJobSpec { t.Helper() - s, err := pkgworkflows.ParseWorkflowSpecYaml(spec) - require.NoError(t, err, "failed to parse YAML workflow spec %s", spec) - id := s.CID + sum := sha256.Sum256([]byte(spec)) + id := fmt.Sprintf("%x", sum) template := ` type = "workflow" schemaVersion = 1 @@ -913,7 +913,7 @@ workflow = """ ` toml := fmt.Sprintf(template, id, spec) - j, err := workflows.ValidatedWorkflowJobSpec(toml) + j, err := workflows.ValidatedWorkflowJobSpec(testutils.Context(t), toml) require.NoError(t, err, "failed to validate TOML job spec for workflow %s", toml) return WorkflowJobSpec{toml: toml, j: j} } diff --git a/core/utils/finite_ticker_test.go b/core/utils/finite_ticker_test.go index 277d3bd1db1..575df7e6749 100644 --- a/core/utils/finite_ticker_test.go +++ b/core/utils/finite_ticker_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -23,7 +24,7 @@ func TestFiniteTicker(t *testing.T) { now := time.Now() stop := utils.FiniteTicker(testutils.TestInterval, onTick) - assert.Eventually(t, func() bool { + require.Eventually(t, func() bool { return counter.Load() >= 10 }, testutils.WaitTimeout(t), testutils.TestInterval) diff --git a/core/utils/http/http.go b/core/utils/http/http.go index 3336ac9f42f..0c713f9662c 100644 --- a/core/utils/http/http.go +++ b/core/utils/http/http.go @@ -7,7 +7,7 @@ import ( "net/url" "time" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) type httpClientConfig interface { @@ -38,9 +38,13 @@ func newDefaultTransport() *http.Transport { return t } +type HTTPClient interface { + Do(req *http.Request) (*http.Response, error) +} + // HTTPRequest holds the request and config struct for a http request type HTTPRequest struct { - Client *http.Client + Client HTTPClient Request *http.Request Config HTTPRequestConfig Logger logger.Logger @@ -48,35 +52,46 @@ type HTTPRequest struct { // HTTPRequestConfig holds the configurable settings for a http request type HTTPRequestConfig struct { + // SizeLimit in bytes SizeLimit int64 } -// SendRequest sends a HTTPRequest, -// returns a body, status code, and error. -func (h *HTTPRequest) SendRequest() (responseBody []byte, statusCode int, headers http.Header, err error) { +// SendRequestReader allows for streaming the body directly and does not read +// it all into memory +// +// CALLER IS RESPONSIBLE FOR CLOSING RETURNED RESPONSE BODY +func (h *HTTPRequest) SendRequestReader() (responseBody io.ReadCloser, statusCode int, headers http.Header, err error) { start := time.Now() - r, err := h.Client.Do(h.Request) if err != nil { - h.Logger.Tracew("http adapter got error", "err", err) + logger.Sugared(h.Logger).Tracew("http adapter got error", "err", err) return nil, 0, nil, err } - defer logger.Sugared(h.Logger).ErrorIfFn(r.Body.Close, "Error closing SendRequest response body") statusCode = r.StatusCode elapsed := time.Since(start) - h.Logger.Tracew(fmt.Sprintf("http adapter got %v in %s", statusCode, elapsed), "statusCode", statusCode, "timeElapsedSeconds", elapsed) + logger.Sugared(h.Logger).Tracew(fmt.Sprintf("http adapter got %v in %s", statusCode, elapsed), "statusCode", statusCode, "timeElapsedSeconds", elapsed) source := http.MaxBytesReader(nil, r.Body, h.Config.SizeLimit) - bytes, err := io.ReadAll(source) + + return source, statusCode, r.Header, nil +} + +// SendRequest sends a HTTPRequest, +// returns a body, status code, and error. +func (h *HTTPRequest) SendRequest() (responseBody []byte, statusCode int, headers http.Header, err error) { + start := time.Now() + + source, statusCode, headers, err := h.SendRequestReader() if err != nil { - h.Logger.Errorw("http adapter error reading body", "err", err) - return nil, statusCode, nil, err + return nil, statusCode, headers, err } - elapsed = time.Since(start) - h.Logger.Tracew(fmt.Sprintf("http adapter finished after %s", elapsed), "statusCode", statusCode, "timeElapsedSeconds", elapsed) + defer logger.Sugared(h.Logger).ErrorIfFn(source.Close, "Error closing SendRequest response body") + bytes, err := io.ReadAll(source) + elapsed := time.Since(start) + logger.Sugared(h.Logger).Tracew(fmt.Sprintf("http adapter finished after %s", elapsed), "statusCode", statusCode, "timeElapsedSeconds", elapsed) responseBody = bytes - return responseBody, statusCode, r.Header, nil + return responseBody, statusCode, headers, nil } diff --git a/core/utils/http/http_allowed_ips.go b/core/utils/http/http_allowed_ips.go index 6432e4ff91d..2b77e89c7d4 100644 --- a/core/utils/http/http_allowed_ips.go +++ b/core/utils/http/http_allowed_ips.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" - "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) var privateIPBlocks []*net.IPNet diff --git a/core/internal/cltest/heavyweight/orm.go b/core/utils/testutils/heavyweight/orm.go similarity index 100% rename from core/internal/cltest/heavyweight/orm.go rename to core/utils/testutils/heavyweight/orm.go diff --git a/core/utils/thread_control_test.go b/core/utils/thread_control_test.go index 49bec742428..9b26c7ae8e0 100644 --- a/core/utils/thread_control_test.go +++ b/core/utils/thread_control_test.go @@ -36,9 +36,10 @@ func TestThreadControl_GoCtx(t *testing.T) { var wg sync.WaitGroup finished := atomic.Int32{} - timeout := 10 * time.Millisecond + timeout := 100 * time.Millisecond - ctx, cancel := context.WithTimeout(context.Background(), timeout) + start := time.Now() + ctx, cancel := context.WithDeadline(context.Background(), start.Add(timeout)) defer cancel() wg.Add(1) @@ -48,10 +49,9 @@ func TestThreadControl_GoCtx(t *testing.T) { finished.Add(1) }) - start := time.Now() wg.Wait() - end := time.Since(start) - assert.Greater(t, end, timeout-1) - assert.Less(t, end, 2*timeout) + elapsed := time.Since(start) + assert.GreaterOrEqual(t, elapsed, timeout) + assert.Less(t, elapsed, 2*timeout) require.Equal(t, int32(1), finished.Load()) } diff --git a/core/utils/utils.go b/core/utils/utils.go index d076284112f..237f6a43589 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -481,6 +481,23 @@ func NewRedialBackoff() backoff.Backoff { } } +func NewHTTPFetchBackoff() backoff.Backoff { + return backoff.Backoff{ + Min: 100 * time.Millisecond, + Max: 15 * time.Second, + Jitter: true, + } +} + +// NewDBBackoff is a standard backoff to use for database connection issues +func NewDBBackoff() backoff.Backoff { + return backoff.Backoff{ + Min: 100 * time.Millisecond, + Max: 5 * time.Second, + Jitter: true, + } +} + // KeyedMutex allows to lock based on particular values type KeyedMutex struct { mutexes sync.Map diff --git a/core/web/assets/index.html b/core/web/assets/index.html index e50dfc07090..0dae8ddf4f0 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 f32bc10dbc3..bf45041a3e2 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.6f07a88cfc748f57e21d.js b/core/web/assets/main.d9fae2bacda0e72ac5ae.js similarity index 89% rename from core/web/assets/main.6f07a88cfc748f57e21d.js rename to core/web/assets/main.d9fae2bacda0e72ac5ae.js index bf6a280a999..9f536101c7f 100644 --- a/core/web/assets/main.6f07a88cfc748f57e21d.js +++ b/core/web/assets/main.d9fae2bacda0e72ac5ae.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;nOW});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;nO2});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}". 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)))},xc=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xl=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xc,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 Feeds Manager 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 Feeds Manager 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"))))})},xf=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 Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:r,onSubmit:n})))))};function xd(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xh(){var e=xd(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xh=function(){return e},e}var xp=n0(xh()),xb=function(){return rv(xp)};function xm(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 xF(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 xY(e,t){return xD(e)||xP(e,t)||xB(e,t)||xR()}function xB(e,t){if(e){if("string"==typeof e)return xI(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 xI(e,t)}}var xU=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},xH=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0().required("Required"),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()}),x$=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},xz=function(e){var t=e.chainAccounts,n=xj(e,["chainAccounts"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=xY(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,!xU(a)&&l.createElement(hP,xN({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e.address,value:e.address},e.address)})),xU(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}),xU(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"}})))},xG=(0,b.withStyles)(x$)(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.chainIDs,u=void 0===s?[]:s,c=e.accounts,f=void 0===c?[]:c,h=e.p2pKeys,p=void 0===h?[]:h,b=e.ocrKeys,m=void 0===b?[]:b,g=e.ocr2Keys,v=void 0===g?[]:g,y=e.showSubmit,w=void 0!==y&&y;return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:xH,onSubmit:o},function(e){var n=e.values,i=f.filter(function(e){return e.chain.id==n.chainID&&!e.isDisabled});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:!0},l.createElement(tE.default,{key:"EVM",value:"EVM"},"EVM"))),l.createElement(d.Z,{item:!0,xs:12,md:6},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"}},u.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(xz,{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",chainAccounts:i,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",required:!0,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"}}),n.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?"}})),n.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"}},p.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"}},m.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"}}),n.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?"}})),n.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:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},p.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:"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"}},v.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(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"}}))))))),w&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})}),xW=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=SV({fetchPolicy:"cache-and-network"}).data,u=EO({fetchPolicy:"cache-and-network"}).data,c=E2({fetchPolicy:"cache-and-network"}).data,f={chainID:"",chainType:"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:""},d=a?a.chains.results.map(function(e){return e.id}):[],h=o?o.ethKeys.results:[],p=s?s.p2pKeys.results:[],b=u?u.ocrKeyBundles.results:[],m=c?c.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(xG,{innerRef:i,initialValues:f,onSubmit:r,chainIDs:d,accounts:h,p2pKeys:p,ocrKeys:b,ocr2Keys:m})),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")))},xK=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=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var d={chainID:t.chainID,chainType:"EVM",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},h=o?o.chains.results.map(function(e){return e.id}):[],p=s?s.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.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(xG,{innerRef:a,initialValues:d,onSubmit:i,chainIDs:h,accounts:p,p2pKeys:b,ocrKeys:m,ocr2Keys:g,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 xV(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xq(){var e=xV(["\n fragment FeedsManager_ChainConfigFields on FeedsManagerChainConfig {\n id\n chainID\n chainType\n accountAddr\n adminAddr\n accountAddrPubKey\n fluxMonitorJobConfig {\n enabled\n }\n ocr1JobConfig {\n enabled\n isBootstrap\n multiaddr\n p2pPeerID\n keyBundleID\n }\n ocr2JobConfig {\n enabled\n isBootstrap\n multiaddr\n forwarderAddress\n p2pPeerID\n keyBundleID\n plugins {\n commit\n execute\n median\n mercury\n rebalancer\n }\n }\n }\n"]);return xq=function(){return e},e}function xZ(){var e=xV(["\n ","\n fragment FeedsManagerFields on FeedsManager {\n id\n name\n uri\n publicKey\n isConnectionActive\n chainConfigs {\n ...FeedsManager_ChainConfigFields\n }\n }\n"]);return xZ=function(){return e},e}function xX(){var e=xV(["\n fragment FeedsManager_JobProposalsFields on JobProposal {\n id\n name\n externalJobID\n remoteUUID\n status\n pendingUpdate\n latestSpec {\n createdAt\n version\n }\n }\n"]);return xX=function(){return e},e}function xJ(){var e=xV(["\n ","\n ","\n fragment FeedsManagerPayload_ResultsFields on FeedsManager {\n ...FeedsManagerFields\n jobProposals {\n ...FeedsManager_JobProposalsFields\n }\n }\n"]);return xJ=function(){return e},e}function xQ(){var e=xV(["\n ","\n query FetchFeedManagersWithProposals {\n feedsManagers {\n results {\n ...FeedsManagerPayload_ResultsFields\n }\n }\n }\n"]);return xQ=function(){return e},e}var x1=n0(xq()),x0=n0(xZ(),x1),x2=n0(xX()),x3=n0(xJ(),x0,x2),x4=n0(xQ(),x3),x6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(x4,e)};function x5(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);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TZ,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},TJ={name:"Chainlink Feeds Manager",uri:"",publicKey:""},TQ=function(e){var t=e.onSubmit;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:"Register Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:TJ,onSubmit:t})))))};function T1(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&&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 ME(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?MM[c.action].title:"",body:c?MM[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(Md,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function MA(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ML(){var e=MA(["\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 ML=function(){return e},e}var MC=n0(ML(),Mx),MI=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(Mo,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(Tq,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(MO,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function MD(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.nextNonce&&t.append("nextNonce",e.nextNonce),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","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"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","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","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}),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,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 }\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"},connectedIcon:{color:xh.default[500]},disconnectedIcon:{color:xp.default[500]},text:{marginLeft:4}})},xv=(0,b.withStyles)(xg)(function(e){var t=e.isConnected,n=e.classes;return l.createElement("div",{className:n.root},t?l.createElement(xm.Z,{fontSize:"small",className:n.connectedIcon}):l.createElement(xb.Z,{fontSize:"small",className:n.disconnectedIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:n.text},t?"Connected":"Disconnected"))}),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,{isConnected:t.isConnectionActive})),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,"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=n(57234),xQ={EVM:"EVM",APTOS:"APTOS",SOLANA:"SOLANA",STARKNET:"STARKNET",COSMOS:"COSMOS"};function x1(e,t){(null==t||t>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 x5(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 x8(e,t){return x0(e)||x3(e,t)||x9(e,t)||x4()}function x9(e,t){if(e){if("string"==typeof e)return x1(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 x1(e,t)}}var x7=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},Te=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0().required("Required"),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()}),Tt=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},Tn=function(e){var t=e.addresses,n=x6(e,["addresses"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=x8(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,!x7(a)&&l.createElement(hP,x2({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),x7(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}),x7(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"}})))},Tr=(0,b.withStyles)(Tt)(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.accountsAptos,p=void 0===h?[]:h,b=e.p2pKeys,m=void 0===b?[]:b,g=e.ocrKeys,v=void 0===g?[]:g,y=e.ocr2Keys,w=void 0===y?[]:y,_=e.showSubmit,E=void 0!==_&&_;return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:Te,onSubmit:o},function(e){var n=e.values,i=[];return n.chainType===xQ.EVM&&(i=f.filter(function(e){return e.chain.id==n.chainID&&!e.isDisabled}).map(function(e){return e.address})),n.chainType===xQ.APTOS&&(i=p.map(function(e){return e.account})),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:xQ.EVM,value:xQ.EVM},"EVM"),l.createElement(tE.default,{key:xQ.APTOS,value:xQ.APTOS},"APTOS"))),l.createElement(d.Z,{item:!0,xs:12,md:6},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"}},u.filter(function(e){return e.network.toUpperCase()===n.chainType}).map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(Tn,{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:i,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",required:!0,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"}}),n.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?"}})),n.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"}},m.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"}},v.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"}}),n.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:!n.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},m.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),n.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"}},w.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(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"}}))))))),E&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})});function Ti(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function Ta(){var e=Ti(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return Ta=function(){return e},e}function To(){var e=Ti(["\n ","\n query FetchAptosKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n }\n"]);return To=function(){return e},e}var Ts=n0(Ta()),Tu=n0(To(),Ts),Tc=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(Tu,e)},Tl=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=Tc({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:xQ.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=s?s.aptosKeys.results:[],m=u?u.p2pKeys.results:[],g=c?c.ocrKeyBundles.results:[],v=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(Tr,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsAptos:b,p2pKeys:m,ocrKeys:g,ocr2Keys:v})),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")))},Tf=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=Tc({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:xQ.EVM,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=u?u.aptosKeys.results:[],g=c?c.p2pKeys.results:[],v=f?f.ocrKeyBundles.results:[],y=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(Tr,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsAptos:m,p2pKeys:g,ocrKeys:v,ocr2Keys:y,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 Td(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);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&&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 MI(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?Mj[c.action].title:"",body:c?Mj[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(ME,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function MY(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function MB(){var e=MY(["\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 MB=function(){return e},e}var MU=n0(MB(),MP),MH=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(Mm,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(T6,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(MF,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};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]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.nextNonce&&t.append("nextNonce",e.nextNonce),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"],DismissJobErrorPayload:["DismissJobErrorSuccess","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","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}),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.6f07a88cfc748f57e21d.js.gz b/core/web/assets/main.d9fae2bacda0e72ac5ae.js.gz similarity index 86% rename from core/web/assets/main.6f07a88cfc748f57e21d.js.gz rename to core/web/assets/main.d9fae2bacda0e72ac5ae.js.gz index 1a833982299..c3b560db80e 100644 Binary files a/core/web/assets/main.6f07a88cfc748f57e21d.js.gz and b/core/web/assets/main.d9fae2bacda0e72ac5ae.js.gz differ diff --git a/core/web/chains_controller.go b/core/web/chains_controller.go index bcaaf909540..6bc5ee4daa3 100644 --- a/core/web/chains_controller.go +++ b/core/web/chains_controller.go @@ -58,7 +58,7 @@ func (cc *chainsController[R]) Index(c *gin.Context, size, page, offset int) { jsonAPIError(c, http.StatusBadRequest, cc.errNotEnabled) return } - chains, count, err := cc.chainStats.ChainStatuses(c, offset, size) + chains, count, err := cc.chainStats.ChainStatuses(c.Request.Context(), offset, size) if err != nil { jsonAPIError(c, http.StatusBadRequest, err) @@ -79,7 +79,7 @@ func (cc *chainsController[R]) Show(c *gin.Context) { return } relayID := types.RelayID{Network: cc.network, ChainID: c.Param("ID")} - chain, err := cc.chainStats.ChainStatus(c, relayID) + chain, err := cc.chainStats.ChainStatus(c.Request.Context(), relayID) if err != nil { jsonAPIError(c, http.StatusBadRequest, err) return diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go index 3eb667bc6f8..89b99eda1dd 100644 --- a/core/web/evm_transactions_controller_test.go +++ b/core/web/evm_transactions_controller_test.go @@ -39,7 +39,7 @@ func TestTransactionsController_Index_Success(t *testing.T) { blockNum := int64(3) attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast - attempt.TxFee = gas.EvmFee{Legacy: assets.NewWeiI(3)} + attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) diff --git a/core/web/evm_transfer_controller.go b/core/web/evm_transfer_controller.go index 88d3dead4c8..75f6c07b6d9 100644 --- a/core/web/evm_transfer_controller.go +++ b/core/web/evm_transfer_controller.go @@ -54,7 +54,7 @@ func (tc *EVMTransfersController) Create(c *gin.Context) { } if !tr.AllowHigherAmounts { - err = ValidateEthBalanceForTransfer(c, chain, tr.FromAddress, tr.Amount) + err = ValidateEthBalanceForTransfer(c, chain, tr.FromAddress, tr.Amount, tr.DestinationAddress) if err != nil { jsonAPIError(c, http.StatusUnprocessableEntity, errors.Errorf("transaction failed: %v", err)) return @@ -92,7 +92,7 @@ func (tc *EVMTransfersController) Create(c *gin.Context) { } // ValidateEthBalanceForTransfer validates that the current balance can cover the transaction amount -func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAddr common.Address, amount assets.Eth) error { +func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAddr common.Address, amount assets.Eth, toAddr common.Address) error { var err error var balance *big.Int @@ -116,7 +116,7 @@ func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAd gasLimit := chain.Config().EVM().GasEstimator().LimitTransfer() estimator := chain.GasEstimator() - amountWithFees, err := estimator.GetMaxCost(c, amount, nil, gasLimit, chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddr)) + amountWithFees, err := estimator.GetMaxCost(c, amount, nil, gasLimit, chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddr), &fromAddr, &toAddr) if err != nil { return err } diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index ccb2f0774ca..61226839401 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -286,7 +285,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) - ethClient.On("SequenceAt", mock.Anything, mock.Anything, mock.Anything).Return(evmtypes.Nonce(0), nil).Maybe() + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) diff --git a/core/web/features_controller.go b/core/web/features_controller.go index 76f04fe262c..66cd9e60c44 100644 --- a/core/web/features_controller.go +++ b/core/web/features_controller.go @@ -13,8 +13,9 @@ type FeaturesController struct { } const ( - FeatureKeyCSA string = "csa" - FeatureKeyFeedsManager string = "feeds_manager" + FeatureKeyCSA string = "csa" + FeatureKeyFeedsManager string = "feeds_manager" + FeatureKeyMultiFeedsManagers string = "multi_feeds_managers" ) // Index retrieves the features @@ -24,6 +25,7 @@ func (fc *FeaturesController) Index(c *gin.Context) { resources := []presenters.FeatureResource{ *presenters.NewFeatureResource(FeatureKeyCSA, fc.App.GetConfig().Feature().UICSAKeys()), *presenters.NewFeatureResource(FeatureKeyFeedsManager, fc.App.GetConfig().Feature().FeedsManager()), + *presenters.NewFeatureResource(FeatureKeyMultiFeedsManagers, fc.App.GetConfig().Feature().MultiFeedsManagers()), } jsonAPIResponse(c, resources, "features") diff --git a/core/web/features_controller_test.go b/core/web/features_controller_test.go index 727d7db5476..02f75f14bc5 100644 --- a/core/web/features_controller_test.go +++ b/core/web/features_controller_test.go @@ -19,6 +19,7 @@ func Test_FeaturesController_List(t *testing.T) { app := cltest.NewApplicationWithConfig(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { csa := true c.Feature.UICSAKeys = &csa + c.Feature.MultiFeedsManagers = &csa })) require.NoError(t, app.Start(testutils.Context(t))) client := app.NewHTTPClient(nil) @@ -30,11 +31,14 @@ func Test_FeaturesController_List(t *testing.T) { resources := []presenters.FeatureResource{} err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resources) require.NoError(t, err) - require.Len(t, resources, 2) + require.Len(t, resources, 3) assert.Equal(t, "csa", resources[0].ID) assert.True(t, resources[0].Enabled) assert.Equal(t, "feeds_manager", resources[1].ID) assert.True(t, resources[1].Enabled) + + assert.Equal(t, "multi_feeds_managers", resources[2].ID) + assert.True(t, resources[2].Enabled) } diff --git a/core/web/health_controller_test.go b/core/web/health_controller_test.go index 14367b1e4bb..7a663e367eb 100644 --- a/core/web/health_controller_test.go +++ b/core/web/health_controller_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "io" "net/http" + "os" "strings" "testing" @@ -13,11 +14,27 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/config" + coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" + "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "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" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/mocks" ) +func TestMain(m *testing.M) { + params.InitCosmosSdk( + /* bech32Prefix= */ "wasm", + /* token= */ "cosm", + ) + + os.Exit(m.Run()) +} + func TestHealthController_Readyz(t *testing.T) { var tt = []struct { name string @@ -125,7 +142,30 @@ func TestHealthController_Health_body(t *testing.T) { {".txt-failing", "/health.txt?failing", nil, bodyTXTFailing}, } { t.Run(tc.name, func(t *testing.T) { - app := cltest.NewApplicationWithKey(t) + cfg := configtest.NewGeneralConfig(t, func(cfg *chainlink.Config, secrets *chainlink.Secrets) { + cfg.Cosmos = append(cfg.Cosmos, &coscfg.TOMLConfig{ + ChainID: ptr("Foo"), + Nodes: coscfg.Nodes{ + {Name: ptr("primary"), TendermintURL: config.MustParseURL("http://tender.mint")}, + }, + }) + cfg.Cosmos[0].SetDefaults() + cfg.Solana = append(cfg.Solana, &solcfg.TOMLConfig{ + ChainID: ptr("Bar"), + Nodes: solcfg.Nodes{ + {Name: ptr("primary"), URL: config.MustParseURL("http://solana.web")}, + }, + }) + cfg.Solana[0].SetDefaults() + cfg.Starknet = append(cfg.Starknet, &stkcfg.TOMLConfig{ + ChainID: ptr("Baz"), + Nodes: stkcfg.Nodes{ + {Name: ptr("primary"), URL: config.MustParseURL("http://stark.node")}, + }, + }) + cfg.Starknet[0].SetDefaults() + }) + app := cltest.NewApplicationWithConfigAndKey(t, cfg) require.NoError(t, app.Start(testutils.Context(t))) client := app.NewHTTPClient(nil) diff --git a/core/web/jobs_controller.go b/core/web/jobs_controller.go index 2e005d6d230..48921cc4f90 100644 --- a/core/web/jobs_controller.go +++ b/core/web/jobs_controller.go @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" + ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" "github.com/smartcontractkit/chainlink/v2/core/services/blockheaderfeeder" @@ -74,7 +75,7 @@ func (jc *JobsController) Show(c *gin.Context) { jobSpec, err = jc.App.JobORM().FindJobByExternalJobID(ctx, externalJobID) } else if pErr = jobSpec.SetID(c.Param("ID")); pErr == nil { // Find a job by job ID - jobSpec, err = jc.App.JobORM().FindJobTx(ctx, jobSpec.ID) + jobSpec, err = jc.App.JobORM().FindJob(ctx, jobSpec.ID) } else { jsonAPIError(c, http.StatusUnprocessableEntity, pErr) return @@ -255,10 +256,11 @@ func (jc *JobsController) validateJobSpec(ctx context.Context, tomlString string case job.Stream: jb, err = streams.ValidatedStreamSpec(tomlString) case job.Workflow: - jb, err = workflows.ValidatedWorkflowJobSpec(tomlString) + jb, err = workflows.ValidatedWorkflowJobSpec(ctx, tomlString) case job.StandardCapabilities: jb, err = standardcapabilities.ValidatedStandardCapabilitiesSpec(tomlString) - + case job.CCIP: + jb, err = ccip.ValidatedCCIPSpec(tomlString) default: return jb, http.StatusUnprocessableEntity, errors.Errorf("unknown job type: %s", jobType) } diff --git a/core/web/loader/chain.go b/core/web/loader/chain.go index 215c643f3c5..c6b3206edbd 100644 --- a/core/web/loader/chain.go +++ b/core/web/loader/chain.go @@ -6,7 +6,7 @@ import ( "github.com/graph-gophers/dataloader" - "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" ) @@ -25,20 +25,32 @@ func (b *chainBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*d keyOrder[key.String()] = ix } - var cs []types.ChainStatus - relayers := b.app.GetRelayers().Slice() + var cs []types.ChainStatusWithID + relayersMap, err := b.app.GetRelayers().GetIDToRelayerMap() + if err != nil { + return []*dataloader.Result{{Data: nil, Error: err}} + } - for _, r := range relayers { - s, err := r.GetChainStatus(ctx) + for k, v := range relayersMap { + s, err := v.GetChainStatus(ctx) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } if slices.Contains(chainIDs, s.ID) { - cs = append(cs, s) + cs = append(cs, types.ChainStatusWithID{ + ChainStatus: s, + RelayID: k, + }) } } + // todo: future improvements to handle multiple chains with same id + if len(cs) > len(keys) { + b.app.GetLogger().Warn("Found multiple chain with same id") + return []*dataloader.Result{{Data: nil, Error: chains.ErrMultipleChainFound}} + } + results := make([]*dataloader.Result, len(keys)) for _, c := range cs { ix, ok := keyOrder[c.ID] diff --git a/core/web/loader/getters.go b/core/web/loader/getters.go index 27a39181ff8..33aba17db36 100644 --- a/core/web/loader/getters.go +++ b/core/web/loader/getters.go @@ -7,8 +7,7 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - + 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/feeds" @@ -21,7 +20,7 @@ import ( var ErrInvalidType = errors.New("invalid type") // GetChainByID fetches the chain by it's id. -func GetChainByID(ctx context.Context, id string) (*commontypes.ChainStatus, error) { +func GetChainByID(ctx context.Context, id string) (*commonTypes.ChainStatusWithID, error) { ldr := For(ctx) thunk := ldr.ChainsByIDLoader.Load(ctx, dataloader.StringKey(id)) @@ -30,7 +29,7 @@ func GetChainByID(ctx context.Context, id string) (*commontypes.ChainStatus, err return nil, err } - chain, ok := result.(commontypes.ChainStatus) + chain, ok := result.(commonTypes.ChainStatusWithID) if !ok { return nil, ErrInvalidType } diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go index 5e22c9afef6..0e88f67c444 100644 --- a/core/web/loader/loader_test.go +++ b/core/web/loader/loader_test.go @@ -13,11 +13,13 @@ 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/relay" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" coremocks "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" @@ -46,12 +48,18 @@ func TestLoader_Chains(t *testing.T) { config2, err := chain2.TOMLString() require.NoError(t, err) - app.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: []loop.Relayer{ - testutils2.MockRelayer{ChainStatus: commontypes.ChainStatus{ + app.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[commontypes.RelayID]loop.Relayer{ + commontypes.RelayID{ + Network: relay.NetworkEVM, + ChainID: "1", + }: testutils2.MockRelayer{ChainStatus: commontypes.ChainStatus{ ID: "1", Enabled: true, Config: config1, - }}, testutils2.MockRelayer{ChainStatus: commontypes.ChainStatus{ + }}, commontypes.RelayID{ + Network: relay.NetworkEVM, + ChainID: "2", + }: testutils2.MockRelayer{ChainStatus: commontypes.ChainStatus{ ID: "2", Enabled: true, Config: config2, @@ -65,11 +73,17 @@ func TestLoader_Chains(t *testing.T) { assert.Len(t, results, 3) require.NoError(t, err) - want2 := commontypes.ChainStatus{ID: "2", Enabled: true, Config: config2} - assert.Equal(t, want2, results[0].Data.(commontypes.ChainStatus)) + want2 := types.ChainStatusWithID{ + ChainStatus: commontypes.ChainStatus{ID: "2", Enabled: true, Config: config2}, + RelayID: commontypes.RelayID{Network: relay.NetworkEVM, ChainID: "2"}, + } + assert.Equal(t, want2, results[0].Data.(types.ChainStatusWithID)) - want1 := commontypes.ChainStatus{ID: "1", Enabled: true, Config: config1} - assert.Equal(t, want1, results[1].Data.(commontypes.ChainStatus)) + want1 := types.ChainStatusWithID{ + ChainStatus: commontypes.ChainStatus{ID: "1", Enabled: true, Config: config1}, + RelayID: commontypes.RelayID{Network: relay.NetworkEVM, ChainID: "1"}, + } + assert.Equal(t, want1, results[1].Data.(types.ChainStatusWithID)) assert.Nil(t, results[2].Data) assert.Error(t, results[2].Error) assert.ErrorIs(t, results[2].Error, chains.ErrNotFound) diff --git a/core/web/loop_registry_internal_test.go b/core/web/loop_registry_internal_test.go index 48cd75a5cff..a02fa20802a 100644 --- a/core/web/loop_registry_internal_test.go +++ b/core/web/loop_registry_internal_test.go @@ -38,7 +38,7 @@ func TestLoopRegistryServer_CantWriteToResponse(t *testing.T) { l, o := logger.TestLoggerObserved(t, zap.ErrorLevel) s := &LoopRegistryServer{ exposedPromPort: 1, - registry: plugins.NewLoopRegistry(l, nil), + registry: plugins.NewLoopRegistry(l, nil, nil), logger: l.(logger.SugaredLogger), jsonMarshalFn: json.Marshal, } @@ -53,7 +53,7 @@ func TestLoopRegistryServer_CantMarshal(t *testing.T) { l, o := logger.TestLoggerObserved(t, zap.ErrorLevel) s := &LoopRegistryServer{ exposedPromPort: 1, - registry: plugins.NewLoopRegistry(l, nil), + registry: plugins.NewLoopRegistry(l, nil, nil), logger: l.(logger.SugaredLogger), jsonMarshalFn: func(any) ([]byte, error) { return []byte(""), errors.New("can't unmarshal") diff --git a/core/web/nodes_controller.go b/core/web/nodes_controller.go index bf5bb0e65e1..0e43316629a 100644 --- a/core/web/nodes_controller.go +++ b/core/web/nodes_controller.go @@ -68,9 +68,10 @@ func (n *nodesController[R]) Index(c *gin.Context, size, page, offset int) { var count int var err error + ctx := c.Request.Context() if id == "" { // fetch all nodes - nodes, count, err = n.nodeSet.NodeStatuses(c, offset, size) + nodes, count, err = n.nodeSet.NodeStatuses(ctx, offset, size) } else { // fetch nodes for chain ID // backward compatibility @@ -80,7 +81,7 @@ func (n *nodesController[R]) Index(c *gin.Context, size, page, offset int) { rid.ChainID = id rid.Network = n.nodeSet.network } - nodes, count, err = n.nodeSet.NodeStatuses(c, offset, size, rid) + nodes, count, err = n.nodeSet.NodeStatuses(ctx, offset, size, rid) } var resources []R diff --git a/core/web/presenters/eth_tx.go b/core/web/presenters/eth_tx.go index e1ba3664a8f..c821eb7a389 100644 --- a/core/web/presenters/eth_tx.go +++ b/core/web/presenters/eth_tx.go @@ -60,7 +60,7 @@ func NewEthTxResourceFromAttempt(txa txmgr.TxAttempt) EthTxResource { r := NewEthTxResource(tx) r.JAID = NewJAID(txa.Hash.String()) - r.GasPrice = txa.TxFee.Legacy.ToInt().String() + r.GasPrice = txa.TxFee.GasPrice.ToInt().String() r.Hash = txa.Hash r.Hex = hexutil.Encode(txa.SignedRawTx) diff --git a/core/web/presenters/eth_tx_test.go b/core/web/presenters/eth_tx_test.go index 3bcdab5edfb..a42bf6ba845 100644 --- a/core/web/presenters/eth_tx_test.go +++ b/core/web/presenters/eth_tx_test.go @@ -73,7 +73,7 @@ func TestEthTxResource(t *testing.T) { txa := txmgr.TxAttempt{ Tx: tx, Hash: hash, - TxFee: gas.EvmFee{Legacy: gasPrice}, + TxFee: gas.EvmFee{GasPrice: gasPrice}, SignedRawTx: hexutil.MustDecode("0xcafe"), BroadcastBeforeBlockNum: &broadcastBefore, } diff --git a/core/web/resolver/aptos_key.go b/core/web/resolver/aptos_key.go new file mode 100644 index 00000000000..862f7b57fc7 --- /dev/null +++ b/core/web/resolver/aptos_key.go @@ -0,0 +1,47 @@ +package resolver + +import ( + "github.com/graph-gophers/graphql-go" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" +) + +type AptosKeyResolver struct { + key aptoskey.Key +} + +func NewAptosKey(key aptoskey.Key) *AptosKeyResolver { + return &AptosKeyResolver{key: key} +} + +func NewAptosKeys(keys []aptoskey.Key) []*AptosKeyResolver { + var resolvers []*AptosKeyResolver + + for _, k := range keys { + resolvers = append(resolvers, NewAptosKey(k)) + } + + return resolvers +} + +func (r *AptosKeyResolver) ID() graphql.ID { + return graphql.ID(r.key.PublicKeyStr()) +} + +func (r *AptosKeyResolver) Account() string { + return r.key.Account() +} + +// -- GetAptosKeys Query -- + +type AptosKeysPayloadResolver struct { + keys []aptoskey.Key +} + +func NewAptosKeysPayload(keys []aptoskey.Key) *AptosKeysPayloadResolver { + return &AptosKeysPayloadResolver{keys: keys} +} + +func (r *AptosKeysPayloadResolver) Results() []*AptosKeyResolver { + return NewAptosKeys(r.keys) +} diff --git a/core/web/resolver/aptos_key_test.go b/core/web/resolver/aptos_key_test.go new file mode 100644 index 00000000000..051c696239d --- /dev/null +++ b/core/web/resolver/aptos_key_test.go @@ -0,0 +1,76 @@ +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/aptoskey" +) + +func TestResolver_AptosKeys(t *testing.T) { + t.Parallel() + + query := ` + query GetAptosKeys { + aptosKeys { + results { + id + account + } + } + }` + k := aptoskey.MustNewInsecure(keystest.NewRandReaderFromSeed(1)) + result := fmt.Sprintf(` + { + "aptosKeys": { + "results": [ + { + "id": "%s", + "account": "%s" + } + ] + } + }`, k.PublicKeyStr(), k.Account()) + gError := errors.New("error") + + testCases := []GQLTestCase{ + unauthorizedTestCase(GQLTestCase{query: query}, "aptosKeys"), + { + name: "success", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.Mocks.aptos.On("GetAll").Return([]aptoskey.Key{k}, nil) + f.Mocks.keystore.On("Aptos").Return(f.Mocks.aptos) + 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.aptos.On("GetAll").Return([]aptoskey.Key{}, gError) + f.Mocks.keystore.On("Aptos").Return(f.Mocks.aptos) + f.App.On("GetKeyStore").Return(f.Mocks.keystore) + }, + query: query, + result: `null`, + errors: []*gqlerrors.QueryError{ + { + Extensions: nil, + ResolverError: gError, + Path: []interface{}{"aptosKeys"}, + Message: gError.Error(), + }, + }, + }, + } + + RunGQLTests(t, testCases) +} diff --git a/core/web/resolver/chain.go b/core/web/resolver/chain.go index 32e9a8caac3..9e06c5a6308 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-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/common/types" ) // ChainResolver resolves the Chain type. type ChainResolver struct { - chain types.ChainStatus + chain types.ChainStatusWithID } -func NewChain(chain types.ChainStatus) *ChainResolver { +func NewChain(chain types.ChainStatusWithID) *ChainResolver { return &ChainResolver{chain: chain} } -func NewChains(chains []types.ChainStatus) []*ChainResolver { +func NewChains(chains []types.ChainStatusWithID) []*ChainResolver { var resolvers []*ChainResolver for _, c := range chains { resolvers = append(resolvers, NewChain(c)) @@ -39,12 +39,17 @@ func (r *ChainResolver) Config() string { return r.chain.Config } +// Network resolves the chain's network field +func (r *ChainResolver) Network() string { + return r.chain.Network +} + type ChainPayloadResolver struct { - chain types.ChainStatus + chain types.ChainStatusWithID NotFoundErrorUnionType } -func NewChainPayload(chain types.ChainStatus, err error) *ChainPayloadResolver { +func NewChainPayload(chain types.ChainStatusWithID, err error) *ChainPayloadResolver { e := NotFoundErrorUnionType{err: err, message: "chain not found", isExpectedErrorFn: nil} return &ChainPayloadResolver{chain: chain, NotFoundErrorUnionType: e} @@ -59,11 +64,11 @@ func (r *ChainPayloadResolver) ToChain() (*ChainResolver, bool) { } type ChainsPayloadResolver struct { - chains []types.ChainStatus + chains []types.ChainStatusWithID total int32 } -func NewChainsPayload(chains []types.ChainStatus, total int32) *ChainsPayloadResolver { +func NewChainsPayload(chains []types.ChainStatusWithID, total int32) *ChainsPayloadResolver { return &ChainsPayloadResolver{chains: chains, total: total} } diff --git a/core/web/resolver/chain_test.go b/core/web/resolver/chain_test.go index 75d7e36a5b5..fed817df456 100644 --- a/core/web/resolver/chain_test.go +++ b/core/web/resolver/chain_test.go @@ -3,9 +3,11 @@ package resolver import ( "context" "encoding/json" + "errors" "fmt" "testing" + gqlerrors "github.com/graph-gophers/graphql-go/errors" "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/require" @@ -15,6 +17,7 @@ import ( evmtoml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/testutils" ) @@ -28,6 +31,7 @@ func TestResolver_Chains(t *testing.T) { id enabled config + network } metadata { total @@ -87,8 +91,11 @@ ResendAfterThreshold = '1h0m0s' chainConfToml, err2 := chainConf.TOMLString() require.NoError(t, err2) - f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: []loop.Relayer{ - testutils.MockRelayer{ChainStatus: commontypes.ChainStatus{ + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[commontypes.RelayID]loop.Relayer{ + commontypes.RelayID{ + Network: relay.NetworkEVM, + ChainID: chainID.String(), + }: testutils.MockRelayer{ChainStatus: commontypes.ChainStatus{ ID: chainID.String(), Enabled: *chain.Enabled, Config: chainConfToml, @@ -102,7 +109,8 @@ ResendAfterThreshold = '1h0m0s' "results": [{ "id": "1", "enabled": true, - "config": %s + "config": %s, + "network": "evm" }], "metadata": { "total": 1 @@ -115,7 +123,7 @@ ResendAfterThreshold = '1h0m0s' name: "no chains", authenticated: true, before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: []loop.Relayer{}}) + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[commontypes.RelayID]loop.Relayer{}}) }, query: query, result: ` @@ -143,6 +151,7 @@ func TestResolver_Chain(t *testing.T) { id enabled config + network } ... on NotFoundError { code @@ -188,17 +197,31 @@ ResendAfterThreshold = '1h0m0s' configTOMLEscaped, err := json.Marshal(configTOML) require.NoError(t, err) + multipleChainError := errors.New("multiple chains found with the same chain ID") testCases := []GQLTestCase{ unauthorizedTestCase(GQLTestCase{query: query}, "chain"), { name: "success", authenticated: true, before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("EVMORM").Return(f.Mocks.evmORM) - f.Mocks.evmORM.PutChains(evmtoml.EVMConfig{ - ChainID: &chainID, + chainConf := evmtoml.EVMConfig{ Chain: chain, - }) + ChainID: &chainID, + } + + chainConfToml, err2 := chainConf.TOMLString() + require.NoError(t, err2) + + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[commontypes.RelayID]loop.Relayer{ + commontypes.RelayID{ + Network: relay.NetworkEVM, + ChainID: chainID.String(), + }: testutils.MockRelayer{ChainStatus: commontypes.ChainStatus{ + ID: chainID.String(), + Enabled: chainConf.IsEnabled(), + Config: chainConfToml, + }}, + }}) }, query: query, result: fmt.Sprintf(` @@ -206,7 +229,8 @@ ResendAfterThreshold = '1h0m0s' "chain": { "id": "1", "enabled": true, - "config": %s + "config": %s, + "network": "evm" } }`, configTOMLEscaped), }, @@ -214,7 +238,7 @@ ResendAfterThreshold = '1h0m0s' name: "not found error", authenticated: true, before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("EVMORM").Return(f.Mocks.evmORM) + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[commontypes.RelayID]loop.Relayer{}}) }, query: query, result: ` @@ -225,6 +249,48 @@ ResendAfterThreshold = '1h0m0s' } }`, }, + { + name: "multiple chain with same chainID found error", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + chainConf := evmtoml.EVMConfig{ + Chain: chain, + ChainID: &chainID, + } + + chainConfToml, err2 := chainConf.TOMLString() + require.NoError(t, err2) + + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[commontypes.RelayID]loop.Relayer{ + commontypes.RelayID{ + Network: relay.NetworkEVM, + ChainID: chainID.String(), + }: testutils.MockRelayer{ChainStatus: commontypes.ChainStatus{ + ID: chainID.String(), + Enabled: chainConf.IsEnabled(), + Config: chainConfToml, + }}, + commontypes.RelayID{ + Network: relay.NetworkAptos, + ChainID: chainID.String(), + }: testutils.MockRelayer{ChainStatus: commontypes.ChainStatus{ + ID: chainID.String(), + Enabled: chainConf.IsEnabled(), + Config: chainConfToml, + }}, + }}) + }, + query: query, + result: "null", + errors: []*gqlerrors.QueryError{ + { + Extensions: nil, + ResolverError: multipleChainError, + Path: []interface{}{"chain"}, + Message: multipleChainError.Error(), + }, + }, + }, } RunGQLTests(t, testCases) diff --git a/core/web/resolver/cosmos_key.go b/core/web/resolver/cosmos_key.go new file mode 100644 index 00000000000..42a0464b97b --- /dev/null +++ b/core/web/resolver/cosmos_key.go @@ -0,0 +1,43 @@ +package resolver + +import ( + "github.com/graph-gophers/graphql-go" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" +) + +type CosmosKeyResolver struct { + key cosmoskey.Key +} + +func NewCosmosKey(key cosmoskey.Key) *CosmosKeyResolver { + return &CosmosKeyResolver{key: key} +} + +func NewCosmosKeys(keys []cosmoskey.Key) []*CosmosKeyResolver { + var resolvers []*CosmosKeyResolver + + for _, k := range keys { + resolvers = append(resolvers, NewCosmosKey(k)) + } + + return resolvers +} + +func (r *CosmosKeyResolver) ID() graphql.ID { + return graphql.ID(r.key.PublicKeyStr()) +} + +// -- GetCosmosKeys Query -- + +type CosmosKeysPayloadResolver struct { + keys []cosmoskey.Key +} + +func NewCosmosKeysPayload(keys []cosmoskey.Key) *CosmosKeysPayloadResolver { + return &CosmosKeysPayloadResolver{keys: keys} +} + +func (r *CosmosKeysPayloadResolver) Results() []*CosmosKeyResolver { + return NewCosmosKeys(r.keys) +} diff --git a/core/web/resolver/cosmos_key_test.go b/core/web/resolver/cosmos_key_test.go new file mode 100644 index 00000000000..9068e453626 --- /dev/null +++ b/core/web/resolver/cosmos_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/cosmoskey" +) + +func TestResolver_CosmosKeys(t *testing.T) { + t.Parallel() + + query := ` + query GetCosmosKeys { + cosmosKeys { + results { + id + } + } + }` + k := cosmoskey.MustNewInsecure(keystest.NewRandReaderFromSeed(1)) + result := fmt.Sprintf(` + { + "cosmosKeys": { + "results": [ + { + "id": "%s" + } + ] + } + }`, k.PublicKeyStr()) + gError := errors.New("error") + + testCases := []GQLTestCase{ + unauthorizedTestCase(GQLTestCase{query: query}, "cosmosKeys"), + { + name: "success", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.Mocks.cosmos.On("GetAll").Return([]cosmoskey.Key{k}, nil) + f.Mocks.keystore.On("Cosmos").Return(f.Mocks.cosmos) + 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.cosmos.On("GetAll").Return([]cosmoskey.Key{}, gError) + f.Mocks.keystore.On("Cosmos").Return(f.Mocks.cosmos) + f.App.On("GetKeyStore").Return(f.Mocks.keystore) + }, + query: query, + result: `null`, + errors: []*gqlerrors.QueryError{ + { + Extensions: nil, + ResolverError: gError, + Path: []interface{}{"cosmosKeys"}, + Message: gError.Error(), + }, + }, + }, + } + + RunGQLTests(t, testCases) +} diff --git a/core/web/resolver/eth_key_test.go b/core/web/resolver/eth_key_test.go index 55cdc230bd2..9002f17fce6 100644 --- a/core/web/resolver/eth_key_test.go +++ b/core/web/resolver/eth_key_test.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -107,8 +108,11 @@ func TestResolver_ETHKeys(t *testing.T) { f.Mocks.chain.On("BalanceMonitor").Return(f.Mocks.balM) f.Mocks.chain.On("Config").Return(f.Mocks.scfg) f.Mocks.relayerChainInterops.EVMChains = legacyEVMChains - f.Mocks.relayerChainInterops.Relayers = []loop.Relayer{ - testutils.MockRelayer{ + f.Mocks.relayerChainInterops.Relayers = map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "12", + }: testutils.MockRelayer{ ChainStatus: types.ChainStatus{ ID: "12", Enabled: true, @@ -165,8 +169,11 @@ func TestResolver_ETHKeys(t *testing.T) { f.Mocks.ethKs.On("GetAll", mock.Anything).Return(keys, nil) f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID}) - f.Mocks.relayerChainInterops.Relayers = []loop.Relayer{ - testutils.MockRelayer{ + f.Mocks.relayerChainInterops.Relayers = map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "12", + }: testutils.MockRelayer{ ChainStatus: types.ChainStatus{ ID: "12", Enabled: true, @@ -325,8 +332,11 @@ func TestResolver_ETHKeys(t *testing.T) { f.Mocks.ethClient.On("LINKBalance", mock.Anything, address, linkAddr).Return(commonassets.NewLinkFromJuels(12), gError) f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, nil) f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains - f.Mocks.relayerChainInterops.Relayers = []loop.Relayer{ - testutils.MockRelayer{ + f.Mocks.relayerChainInterops.Relayers = map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "12", + }: testutils.MockRelayer{ ChainStatus: types.ChainStatus{ ID: "12", Enabled: true, @@ -390,8 +400,11 @@ func TestResolver_ETHKeys(t *testing.T) { f.Mocks.legacyEVMChains.On("Get", states[0].EVMChainID.String()).Return(f.Mocks.chain, nil) f.Mocks.relayerChainInterops.EVMChains = f.Mocks.legacyEVMChains f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID}) - f.Mocks.relayerChainInterops.Relayers = []loop.Relayer{ - testutils.MockRelayer{ + f.Mocks.relayerChainInterops.Relayers = map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "12", + }: testutils.MockRelayer{ ChainStatus: types.ChainStatus{ ID: "12", Enabled: true, diff --git a/core/web/resolver/eth_transaction_attempt.go b/core/web/resolver/eth_transaction_attempt.go index 1e21546bc35..e78e9f64f71 100644 --- a/core/web/resolver/eth_transaction_attempt.go +++ b/core/web/resolver/eth_transaction_attempt.go @@ -26,7 +26,7 @@ func NewEthTransactionsAttempts(results []txmgr.TxAttempt) []*EthTransactionAtte } func (r *EthTransactionAttemptResolver) GasPrice() string { - return r.attmpt.TxFee.Legacy.ToInt().String() + return r.attmpt.TxFee.GasPrice.ToInt().String() } func (r *EthTransactionAttemptResolver) Hash() string { diff --git a/core/web/resolver/eth_transaction_test.go b/core/web/resolver/eth_transaction_test.go index f288450edcc..5844c50fde3 100644 --- a/core/web/resolver/eth_transaction_test.go +++ b/core/web/resolver/eth_transaction_test.go @@ -22,6 +22,7 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/testutils" ) @@ -85,7 +86,7 @@ func TestResolver_EthTransaction(t *testing.T) { { TxID: 1, Hash: hash, - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(12)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(12)}, SignedRawTx: []byte("something"), BroadcastBeforeBlockNum: nil, }, @@ -93,8 +94,11 @@ func TestResolver_EthTransaction(t *testing.T) { f.App.On("TxmStorageService").Return(f.Mocks.txmStore) f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID}) f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{ - Relayers: []loop.Relayer{ - testutils.MockRelayer{ChainStatus: types.ChainStatus{ + Relayers: map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "22", + }: testutils.MockRelayer{ChainStatus: types.ChainStatus{ ID: "22", Enabled: true, Config: "", @@ -150,7 +154,7 @@ func TestResolver_EthTransaction(t *testing.T) { { TxID: 1, Hash: hash, - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(12)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(12)}, SignedRawTx: []byte("something"), BroadcastBeforeBlockNum: &num, }, @@ -158,8 +162,11 @@ func TestResolver_EthTransaction(t *testing.T) { f.App.On("TxmStorageService").Return(f.Mocks.txmStore) f.Mocks.evmORM.PutChains(toml.EVMConfig{ChainID: &chainID}) f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{ - Relayers: []loop.Relayer{ - testutils.MockRelayer{ChainStatus: types.ChainStatus{ + Relayers: map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "22", + }: testutils.MockRelayer{ChainStatus: types.ChainStatus{ ID: "22", Enabled: true, Config: "", @@ -286,7 +293,7 @@ func TestResolver_EthTransactions(t *testing.T) { { TxID: 1, Hash: hash, - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(12)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(12)}, SignedRawTx: []byte("something"), BroadcastBeforeBlockNum: &num, }, @@ -371,7 +378,7 @@ func TestResolver_EthTransactionsAttempts(t *testing.T) { f.Mocks.txmStore.On("TxAttempts", mock.Anything, PageDefaultOffset, PageDefaultLimit).Return([]txmgr.TxAttempt{ { Hash: hash, - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(12)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(12)}, SignedRawTx: []byte("something"), BroadcastBeforeBlockNum: &num, Tx: txmgr.Tx{}, @@ -402,7 +409,7 @@ func TestResolver_EthTransactionsAttempts(t *testing.T) { f.Mocks.txmStore.On("TxAttempts", mock.Anything, PageDefaultOffset, PageDefaultLimit).Return([]txmgr.TxAttempt{ { Hash: hash, - TxFee: gas.EvmFee{Legacy: assets.NewWeiI(12)}, + TxFee: gas.EvmFee{GasPrice: assets.NewWeiI(12)}, SignedRawTx: []byte("something"), BroadcastBeforeBlockNum: nil, }, diff --git a/core/web/resolver/features.go b/core/web/resolver/features.go index 9ce39a773c6..9d6c135a93c 100644 --- a/core/web/resolver/features.go +++ b/core/web/resolver/features.go @@ -20,6 +20,11 @@ func (r *FeaturesResolver) FeedsManager() bool { return r.cfg.FeedsManager() } +// MultiFeedsManagers resolves to whether multiple feed managers support is enable. +func (r *FeaturesResolver) MultiFeedsManagers() bool { + return r.cfg.MultiFeedsManagers() +} + type FeaturesPayloadResolver struct { cfg config.Feature } diff --git a/core/web/resolver/features_test.go b/core/web/resolver/features_test.go index 76394f038b0..4e8f9e8c26c 100644 --- a/core/web/resolver/features_test.go +++ b/core/web/resolver/features_test.go @@ -15,6 +15,7 @@ func Test_ToFeatures(t *testing.T) { ... on Features { csa feedsManager + multiFeedsManagers } } }` @@ -29,6 +30,7 @@ func Test_ToFeatures(t *testing.T) { t, f := true, false c.Feature.UICSAKeys = &f c.Feature.FeedsManager = &t + c.Feature.MultiFeedsManagers = &f })) }, query: query, @@ -36,7 +38,8 @@ func Test_ToFeatures(t *testing.T) { { "features": { "csa": false, - "feedsManager": true + "feedsManager": true, + "multiFeedsManagers": false } }`, }, diff --git a/core/web/resolver/feeds_manager.go b/core/web/resolver/feeds_manager.go index 86705cf2071..0711cb1354b 100644 --- a/core/web/resolver/feeds_manager.go +++ b/core/web/resolver/feeds_manager.go @@ -145,6 +145,7 @@ func (r *CreateFeedsManagerPayloadResolver) ToCreateFeedsManagerSuccess() (*Crea return nil, false } +// TODO: delete once multiple feeds managers support is released func (r *CreateFeedsManagerPayloadResolver) ToSingleFeedsManagerError() (*SingleFeedsManagerErrorResolver, bool) { if r.err != nil && errors.Is(r.err, feeds.ErrSingleFeedsManager) { return NewSingleFeedsManagerError(r.err.Error()), true @@ -153,6 +154,14 @@ func (r *CreateFeedsManagerPayloadResolver) ToSingleFeedsManagerError() (*Single return nil, false } +func (r *CreateFeedsManagerPayloadResolver) ToDuplicateFeedsManagerError() (*DuplicateFeedsManagerErrorResolver, bool) { + if r.err != nil && errors.Is(r.err, feeds.ErrDuplicateFeedsManager) { + return NewDuplicateFeedsManagerError(r.err.Error()), true + } + + return nil, false +} + func (r *CreateFeedsManagerPayloadResolver) ToInputErrors() (*InputErrorsResolver, bool) { if r.inputErrs != nil { var errs []*InputErrorResolver @@ -182,6 +191,7 @@ func (r *CreateFeedsManagerSuccessResolver) FeedsManager() *FeedsManagerResolver } // SingleFeedsManagerErrorResolver - +// TODO: delete once multiple feeds managers support is released type SingleFeedsManagerErrorResolver struct { message string } @@ -200,6 +210,25 @@ func (r *SingleFeedsManagerErrorResolver) Code() ErrorCode { return ErrorCodeUnprocessable } +// DuplicateFeedsManagerErrorResolver - +type DuplicateFeedsManagerErrorResolver struct { + message string +} + +func NewDuplicateFeedsManagerError(message string) *DuplicateFeedsManagerErrorResolver { + return &DuplicateFeedsManagerErrorResolver{ + message: message, + } +} + +func (r *DuplicateFeedsManagerErrorResolver) Message() string { + return r.message +} + +func (r *DuplicateFeedsManagerErrorResolver) Code() ErrorCode { + return ErrorCodeUnprocessable +} + // -- UpdateFeedsManager Mutation -- // UpdateFeedsManagerPayloadResolver - diff --git a/core/web/resolver/feeds_manager_chain_config_test.go b/core/web/resolver/feeds_manager_chain_config_test.go index bd4c1e05aeb..957583dbb7d 100644 --- a/core/web/resolver/feeds_manager_chain_config_test.go +++ b/core/web/resolver/feeds_manager_chain_config_test.go @@ -46,33 +46,37 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { } } }` - variables = map[string]interface{}{ - "input": map[string]interface{}{ - "feedsManagerID": stringutils.FromInt64(mgrID), - "chainID": chainID, - "chainType": "EVM", - "accountAddr": accountAddr, - "accountAddrPubKey": acctAddrPubKey, - "adminAddr": adminAddr, - "fluxMonitorEnabled": false, - "ocr1Enabled": true, - "ocr1IsBootstrap": false, - "ocr1P2PPeerID": peerID.String, - "ocr1KeyBundleID": keyBundleID.String, - "ocr2Enabled": true, - "ocr2IsBootstrap": false, - "ocr2P2PPeerID": peerID.String, - "ocr2KeyBundleID": keyBundleID.String, - "ocr2Plugins": `{"commit":true,"execute":true,"median":false,"mercury":true,"rebalancer":true}`, - "ocr2ForwarderAddress": forwarderAddr, - }, + + withVariables = func(chainType string) map[string]interface{} { + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "feedsManagerID": stringutils.FromInt64(mgrID), + "chainID": chainID, + "chainType": chainType, + "accountAddr": accountAddr, + "accountAddrPubKey": acctAddrPubKey, + "adminAddr": adminAddr, + "fluxMonitorEnabled": false, + "ocr1Enabled": true, + "ocr1IsBootstrap": false, + "ocr1P2PPeerID": peerID.String, + "ocr1KeyBundleID": keyBundleID.String, + "ocr2Enabled": true, + "ocr2IsBootstrap": false, + "ocr2P2PPeerID": peerID.String, + "ocr2KeyBundleID": keyBundleID.String, + "ocr2Plugins": `{"commit":true,"execute":true,"median":false,"mercury":true,"rebalancer":true}`, + "ocr2ForwarderAddress": forwarderAddr, + }, + } + return variables } ) testCases := []GQLTestCase{ - unauthorizedTestCase(GQLTestCase{query: mutation, variables: variables}, "createFeedsManagerChainConfig"), + unauthorizedTestCase(GQLTestCase{query: mutation, variables: withVariables("EVM")}, "createFeedsManagerChainConfig"), { - name: "success", + name: "success EVM", authenticated: true, before: func(ctx context.Context, f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) @@ -136,7 +140,232 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { }, nil) }, query: mutation, - variables: variables, + variables: withVariables("EVM"), + result: ` + { + "createFeedsManagerChainConfig": { + "chainConfig": { + "id": "1" + } + } + }`, + }, + { + name: "success Solana", + 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.ChainTypeSolana, + 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.ChainTypeSolana, + 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("SOLANA"), + result: ` + { + "createFeedsManagerChainConfig": { + "chainConfig": { + "id": "1" + } + } + }`, + }, + { + name: "success Starknet", + 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.ChainTypeStarknet, + 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.ChainTypeStarknet, + 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("STARKNET"), + result: ` + { + "createFeedsManagerChainConfig": { + "chainConfig": { + "id": "1" + } + } + }`, + }, + { + name: "success APTOS", + 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.ChainTypeAptos, + 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.ChainTypeAptos, + 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("APTOS"), result: ` { "createFeedsManagerChainConfig": { @@ -154,7 +383,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { f.Mocks.feedsSvc.On("CreateChainConfig", mock.Anything, mock.IsType(feeds.ChainConfig{})).Return(int64(0), sql.ErrNoRows) }, query: mutation, - variables: variables, + variables: withVariables("EVM"), result: ` { "createFeedsManagerChainConfig": { @@ -172,7 +401,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, - variables: variables, + variables: withVariables("EVM"), result: ` { "createFeedsManagerChainConfig": { diff --git a/core/web/resolver/feeds_manager_test.go b/core/web/resolver/feeds_manager_test.go index bafb50ab0d5..4237c6a7749 100644 --- a/core/web/resolver/feeds_manager_test.go +++ b/core/web/resolver/feeds_manager_test.go @@ -183,6 +183,10 @@ func Test_CreateFeedsManager(t *testing.T) { message code } + ... on DuplicateFeedsManagerError { + message + code + } ... on NotFoundError { message code @@ -264,6 +268,25 @@ func Test_CreateFeedsManager(t *testing.T) { } }`, }, + { + name: "register duplicate feeds manager error", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) + f.Mocks.feedsSvc. + On("RegisterManager", mock.Anything, mock.IsType(feeds.RegisterManagerParams{})). + Return(int64(0), feeds.ErrDuplicateFeedsManager) + }, + query: mutation, + variables: variables, + result: ` + { + "createFeedsManager": { + "message": "manager was previously registered using the same public key", + "code": "UNPROCESSABLE" + } + }`, + }, { name: "not found", authenticated: true, diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 4da5b1da651..4388bd5a701 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -14,8 +14,10 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" + ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" "github.com/smartcontractkit/chainlink/v2/core/services/blockheaderfeeder" @@ -424,7 +426,7 @@ func (r *Resolver) CreateFeedsManager(ctx context.Context, args struct { id, err := feedsService.RegisterManager(ctx, params) if err != nil { - if errors.Is(err, feeds.ErrSingleFeedsManager) { + if errors.Is(err, feeds.ErrSingleFeedsManager) || errors.Is(err, feeds.ErrDuplicateFeedsManager) { return NewCreateFeedsManagerPayload(nil, err, nil), nil } return nil, err @@ -1061,11 +1063,13 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct { case job.Gateway: jb, err = gateway.ValidatedGatewaySpec(args.Input.TOML) case job.Workflow: - jb, err = workflows.ValidatedWorkflowJobSpec(args.Input.TOML) + jb, err = workflows.ValidatedWorkflowJobSpec(ctx, args.Input.TOML) case job.StandardCapabilities: jb, err = standardcapabilities.ValidatedStandardCapabilitiesSpec(args.Input.TOML) case job.Stream: jb, err = streams.ValidatedStreamSpec(args.Input.TOML) + case job.CCIP: + jb, err = ccip.ValidatedCCIPSpec(args.Input.TOML) default: return NewCreateJobPayload(r.App, nil, map[string]string{ "Job Type": fmt.Sprintf("unknown job type: %s", jbt), diff --git a/core/web/resolver/node_test.go b/core/web/resolver/node_test.go index 870f694990f..735c2cb7867 100644 --- a/core/web/resolver/node_test.go +++ b/core/web/resolver/node_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/types" chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/testutils" ) @@ -50,8 +51,11 @@ func TestResolver_Nodes(t *testing.T) { State: "alive", }, }, - Relayers: []loop.Relayer{ - testutils.MockRelayer{ChainStatus: types.ChainStatus{ + Relayers: map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "1", + }: testutils.MockRelayer{ChainStatus: types.ChainStatus{ ID: "1", Enabled: true, Config: "", @@ -124,8 +128,11 @@ func Test_NodeQuery(t *testing.T) { name: "success", authenticated: true, before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: []loop.Relayer{ - testutils.MockRelayer{NodeStatuses: []types.NodeStatus{ + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[types.RelayID]loop.Relayer{ + types.RelayID{ + Network: relay.NetworkEVM, + ChainID: "1", + }: testutils.MockRelayer{NodeStatuses: []types.NodeStatus{ { Name: "node-name", Config: "Name='node-name'\nOrder=11\nHTTPURL='http://some-url'\nWSURL='ws://some-url'", @@ -148,7 +155,7 @@ func Test_NodeQuery(t *testing.T) { name: "not found error", authenticated: true, before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: []loop.Relayer{}}) + f.App.On("GetRelayers").Return(&chainlinkmocks.FakeRelayerChainInteroperators{Relayers: map[types.RelayID]loop.Relayer{}}) }, query: query, result: ` diff --git a/core/web/resolver/query.go b/core/web/resolver/query.go index 9de678adc51..d3e1215834a 100644 --- a/core/web/resolver/query.go +++ b/core/web/resolver/query.go @@ -10,13 +10,14 @@ import ( "github.com/graph-gophers/graphql-go" "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-common/pkg/types" + 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" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" + "github.com/smartcontractkit/chainlink/v2/core/web/loader" ) // Bridge retrieves a bridges by name. @@ -68,18 +69,15 @@ func (r *Resolver) Chain(ctx context.Context, args struct{ ID graphql.ID }) (*Ch return nil, err } - cs, _, err := r.App.EVMORM().Chains(string(args.ID)) + 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 nil, err } - l := len(cs) - if l == 0 { - return NewChainPayload(types.ChainStatus{}, chains.ErrNotFound), nil - } - if l > 1 { - return nil, fmt.Errorf("multiple chains found: %d", len(cs)) - } - return NewChainPayload(cs[0], nil), nil + + return NewChainPayload(*id, nil), nil } // Chains retrieves a paginated list of chains. @@ -94,16 +92,25 @@ func (r *Resolver) Chains(ctx context.Context, args struct { offset := pageOffset(args.Offset) limit := pageLimit(args.Limit) - var chains []types.ChainStatus - for _, rel := range r.App.GetRelayers().Slice() { - status, err := rel.GetChainStatus(ctx) + var chains []commonTypes.ChainStatusWithID + relayersMap, err := r.App.GetRelayers().GetIDToRelayerMap() + if err != nil { + return nil, err + } + + for k, v := range relayersMap { + s, err := v.GetChainStatus(ctx) if err != nil { return nil, err } - chains = append(chains, status) + + chains = append(chains, commonTypes.ChainStatusWithID{ + ChainStatus: s, + RelayID: k, + }) } - count := len(chains) + count := len(chains) if count == 0 { //No chains are configured, return an empty ChainsPayload, so we don't break the UI return NewChainsPayload(nil, 0), nil @@ -118,9 +125,19 @@ func (r *Resolver) Chains(ctx context.Context, args struct { end = offset + limit } + sortByNetworkAndID(chains) return NewChainsPayload(chains[offset:end], int32(count)), nil } +func sortByNetworkAndID(chains []commonTypes.ChainStatusWithID) { + sort.SliceStable(chains, func(i, j int) bool { + if chains[i].Network == chains[j].Network { + return chains[i].ID < chains[j].ID + } + return chains[i].Network < chains[j].Network + }) +} + // FeedsManager retrieves a feeds manager by id. func (r *Resolver) FeedsManager(ctx context.Context, args struct{ ID graphql.ID }) (*FeedsManagerPayloadResolver, error) { if err := authenticateUser(ctx); err != nil { @@ -552,6 +569,43 @@ func (r *Resolver) SolanaKeys(ctx context.Context) (*SolanaKeysPayloadResolver, return NewSolanaKeysPayload(keys), nil } +func (r *Resolver) AptosKeys(ctx context.Context) (*AptosKeysPayloadResolver, error) { + if err := authenticateUser(ctx); err != nil { + return nil, err + } + + keys, err := r.App.GetKeyStore().Aptos().GetAll() + if err != nil { + return nil, err + } + + return NewAptosKeysPayload(keys), nil +} + +func (r *Resolver) CosmosKeys(ctx context.Context) (*CosmosKeysPayloadResolver, error) { + if err := authenticateUser(ctx); err != nil { + return nil, err + } + keys, err := r.App.GetKeyStore().Cosmos().GetAll() + if err != nil { + return nil, err + } + + return NewCosmosKeysPayload(keys), nil +} + +func (r *Resolver) StarkNetKeys(ctx context.Context) (*StarkNetKeysPayloadResolver, error) { + if err := authenticateUser(ctx); err != nil { + return nil, err + } + keys, err := r.App.GetKeyStore().StarkNet().GetAll() + if err != nil { + return nil, err + } + + return NewStarkNetKeysPayload(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 9f3445e1cee..0d365b0891e 100644 --- a/core/web/resolver/resolver_test.go +++ b/core/web/resolver/resolver_test.go @@ -51,6 +51,9 @@ type mocks struct { p2p *keystoreMocks.P2P vrf *keystoreMocks.VRF solana *keystoreMocks.Solana + aptos *keystoreMocks.Aptos + cosmos *keystoreMocks.Cosmos + starknet *keystoreMocks.StarkNet chain *legacyEvmORMMocks.Chain legacyEVMChains *legacyEvmORMMocks.LegacyChainContainer relayerChainInterops *chainlinkMocks.FakeRelayerChainInteroperators @@ -106,6 +109,9 @@ func setupFramework(t *testing.T) *gqlTestFramework { p2p: keystoreMocks.NewP2P(t), vrf: keystoreMocks.NewVRF(t), solana: keystoreMocks.NewSolana(t), + aptos: keystoreMocks.NewAptos(t), + cosmos: keystoreMocks.NewCosmos(t), + starknet: keystoreMocks.NewStarkNet(t), chain: legacyEvmORMMocks.NewChain(t), legacyEVMChains: legacyEvmORMMocks.NewLegacyChainContainer(t), relayerChainInterops: &chainlinkMocks.FakeRelayerChainInteroperators{}, diff --git a/core/web/resolver/starknet_key.go b/core/web/resolver/starknet_key.go new file mode 100644 index 00000000000..a3835e5153a --- /dev/null +++ b/core/web/resolver/starknet_key.go @@ -0,0 +1,43 @@ +package resolver + +import ( + "github.com/graph-gophers/graphql-go" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" +) + +type StarkNetKeyResolver struct { + key starkkey.Key +} + +func NewStarkNetKey(key starkkey.Key) *StarkNetKeyResolver { + return &StarkNetKeyResolver{key: key} +} + +func NewStarkNetKeys(keys []starkkey.Key) []*StarkNetKeyResolver { + var resolvers []*StarkNetKeyResolver + + for _, k := range keys { + resolvers = append(resolvers, NewStarkNetKey(k)) + } + + return resolvers +} + +func (r *StarkNetKeyResolver) ID() graphql.ID { + return graphql.ID(r.key.StarkKeyStr()) +} + +// -- GetStarkNetKeys Query -- + +type StarkNetKeysPayloadResolver struct { + keys []starkkey.Key +} + +func NewStarkNetKeysPayload(keys []starkkey.Key) *StarkNetKeysPayloadResolver { + return &StarkNetKeysPayloadResolver{keys: keys} +} + +func (r *StarkNetKeysPayloadResolver) Results() []*StarkNetKeyResolver { + return NewStarkNetKeys(r.keys) +} diff --git a/core/web/resolver/starknet_key_test.go b/core/web/resolver/starknet_key_test.go new file mode 100644 index 00000000000..dff26afb33f --- /dev/null +++ b/core/web/resolver/starknet_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/starkkey" +) + +func TestResolver_StarkNetKeys(t *testing.T) { + t.Parallel() + + query := ` + query GetStarkNetKeys { + starknetKeys { + results { + id + } + } + }` + k := starkkey.MustNewInsecure(keystest.NewRandReaderFromSeed(1)) + result := fmt.Sprintf(` + { + "starknetKeys": { + "results": [ + { + "id": "%s" + } + ] + } + }`, k.StarkKeyStr()) + gError := errors.New("error") + + testCases := []GQLTestCase{ + unauthorizedTestCase(GQLTestCase{query: query}, "starknetKeys"), + { + name: "success", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.Mocks.starknet.On("GetAll").Return([]starkkey.Key{k}, nil) + f.Mocks.keystore.On("StarkNet").Return(f.Mocks.starknet) + 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.starknet.On("GetAll").Return([]starkkey.Key{}, gError) + f.Mocks.keystore.On("StarkNet").Return(f.Mocks.starknet) + f.App.On("GetKeyStore").Return(f.Mocks.keystore) + }, + query: query, + result: `null`, + errors: []*gqlerrors.QueryError{ + { + Extensions: nil, + ResolverError: gError, + Path: []interface{}{"starknetKeys"}, + Message: gError.Error(), + }, + }, + }, + } + + RunGQLTests(t, testCases) +} diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index f1325d824ea..4cfe5e2086c 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -7,6 +7,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -34,7 +35,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -252,7 +253,36 @@ 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.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 diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 9421e6198ee..c319a7bf8ec 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -7,6 +7,7 @@ FeedsManager = true LogPoller = true UICSAKeys = true CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1m0s' @@ -34,7 +35,7 @@ LeaseDuration = '1m0s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = true BufferSize = 1234 MaxBatchSize = 4321 @@ -262,11 +263,44 @@ DeltaDial = '1m0s' DeltaReconcile = '2s' ListenAddresses = ['foo', 'bar'] +[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.GatewayConnector] +ChainIDForNodeKey = '11155111' +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' +DonID = 'example_don' +WSHandshakeTimeoutMillis = 100 +AuthMinChallengeLen = 10 +AuthTimestampToleranceSec = 10 + +[[Capabilities.GatewayConnector.Gateways]] +ID = 'example_gateway' +URL = 'wss://localhost:8081/node' + +[Telemetry] +Enabled = true +CACertFile = 'cert-file' +Endpoint = 'example.com/collector' +InsecureConnection = true +TraceSampleRatio = 0.01 + +[Telemetry.ResourceAttributes] +Baz = 'test' +Foo = 'bar' + [[EVM]] ChainID = '1' Enabled = false @@ -275,7 +309,7 @@ BlockBackfillDepth = 100 BlockBackfillSkip = true ChainType = 'Optimism' FinalityDepth = 42 -FinalityTagEnabled = false +FinalityTagEnabled = true FlagsContractAddress = '0xae4E781a6218A8031764928E88d457937A954fC3' LinkContractAddress = '0x538aAaB4ea120b2bC2fe5D296852D948F07D849e' LogBackfillBatchSize = 17 @@ -288,6 +322,7 @@ MinContractPayment = '9.223372036854775807 link' NonceAutoSync = true NoNewHeadsThreshold = '1m0s' OperatorFactoryAddress = '0xa5B85635Be42F21f94F28034B7DA440EeFF0F418' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 17 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 @@ -316,6 +351,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 @@ -340,12 +376,16 @@ CheckInclusionPercentile = 19 EIP1559FeeCapBufferBlocks = 13 TransactionPercentile = 15 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '1s' + [EVM.HeadTracker] HistoryDepth = 15 MaxBufferSize = 17 SamplingInterval = '1h0m0s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [[EVM.KeySpecific]] Key = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' @@ -363,6 +403,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.NodePool.Errors] NonceTooLow = '(: |^)nonce too low' @@ -379,6 +420,7 @@ L2Full = '(: |^)l2 full' TransactionAlreadyMined = '(: |^)transaction already mined' Fatal = '(: |^)fatal' ServiceUnavailable = '(: |^)service unavailable' +TooManyResults = '(: |^)too many results' [EVM.OCR] ContractConfirmations = 11 @@ -392,6 +434,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 540 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'foo' WSURL = 'wss://web.socket/test/foo' @@ -453,18 +498,40 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' URL = 'http://solana.web' +SendOnly = false [[Solana.Nodes]] Name = 'foo' URL = 'http://solana.foo' +SendOnly = false [[Solana.Nodes]] Name = 'bar' URL = 'http://solana.bar' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 1c4093cbfca..e29c763b74c 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -7,6 +7,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -34,7 +35,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -252,18 +253,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -275,6 +305,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -303,6 +334,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -318,12 +350,16 @@ 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 @@ -335,6 +371,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -348,6 +385,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'primary' WSURL = 'wss://web.socket/mainnet' @@ -375,6 +415,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x8007e24251b1D2Fc518Eb843A701d9cD21fe0aA3' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -403,6 +444,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -418,12 +460,16 @@ 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 @@ -435,6 +481,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -448,6 +495,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 5400000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'foo' WSURL = 'wss://web.socket/test/foo' @@ -458,7 +508,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -469,6 +519,7 @@ MinIncomingConfirmations = 5 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 @@ -497,6 +548,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -512,12 +564,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -529,6 +585,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -542,6 +599,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 5400000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' @@ -600,10 +660,30 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' @@ -623,10 +703,30 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false + +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 9abb1719402..a305332b5ff 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -38,7 +38,7 @@ CPUProfileRate = 7 [[EVM]] ChainID = '1' FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true FinalizedBlockOffset = 0 [EVM.OCR2] @@ -98,17 +98,53 @@ TendermintURL = 'http://bombay.cosmos.com' ChainID = 'mainnet' MaxRetries = 12 +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 + [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' OCR2CachePollPeriod = '1m0s' +[Solana.MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '1s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' +NodeNoNewHeadsThreshold = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 + [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/web/schema/schema.graphql b/core/web/schema/schema.graphql index 2d0a5a1b1ab..415be25b77d 100644 --- a/core/web/schema/schema.graphql +++ b/core/web/schema/schema.graphql @@ -33,6 +33,9 @@ type Query { ocr2KeyBundles: OCR2KeyBundlesPayload! p2pKeys: P2PKeysPayload! solanaKeys: SolanaKeysPayload! + aptosKeys: AptosKeysPayload! + cosmosKeys: CosmosKeysPayload! + starknetKeys: StarkNetKeysPayload! sqlLogging: GetSQLLoggingPayload! vrfKey(id: ID!): VRFKeyPayload! vrfKeys: VRFKeysPayload! diff --git a/core/web/schema/type/aptos_key.graphql b/core/web/schema/type/aptos_key.graphql new file mode 100644 index 00000000000..e75c2514c4a --- /dev/null +++ b/core/web/schema/type/aptos_key.graphql @@ -0,0 +1,8 @@ +type AptosKey { + id: ID! + account: String! +} + +type AptosKeysPayload { + results: [AptosKey!]! +} diff --git a/core/web/schema/type/chain.graphql b/core/web/schema/type/chain.graphql index dcfac1f41d9..1bacaee4a48 100644 --- a/core/web/schema/type/chain.graphql +++ b/core/web/schema/type/chain.graphql @@ -2,6 +2,7 @@ type Chain { id: ID! enabled: Boolean! config: String! + network: String! } union ChainPayload = Chain | NotFoundError diff --git a/core/web/schema/type/cosmos_key.graphql b/core/web/schema/type/cosmos_key.graphql new file mode 100644 index 00000000000..47de4ff9c41 --- /dev/null +++ b/core/web/schema/type/cosmos_key.graphql @@ -0,0 +1,7 @@ +type CosmosKey { + id: ID! +} + +type CosmosKeysPayload { + results: [CosmosKey!]! +} diff --git a/core/web/schema/type/features.graphql b/core/web/schema/type/features.graphql index 4254bdecb6c..ff434ab4bdc 100644 --- a/core/web/schema/type/features.graphql +++ b/core/web/schema/type/features.graphql @@ -1,6 +1,7 @@ type Features { csa: Boolean! feedsManager: Boolean! + multiFeedsManagers: Boolean! } # FeaturesPayload defines the response of fetching the features availability in the UI diff --git a/core/web/schema/type/feeds_manager.graphql b/core/web/schema/type/feeds_manager.graphql index 12e8732c8e0..9da8f64e1c2 100644 --- a/core/web/schema/type/feeds_manager.graphql +++ b/core/web/schema/type/feeds_manager.graphql @@ -77,6 +77,13 @@ type CreateFeedsManagerSuccess { feedsManager: FeedsManager! } +type DuplicateFeedsManagerError implements Error { + message: String! + code: ErrorCode! +} + +# DEPRECATED: No longer used since we now support multiple feeds manager. +# Keeping this to avoid breaking change. type SingleFeedsManagerError implements Error { message: String! code: ErrorCode! @@ -84,7 +91,8 @@ type SingleFeedsManagerError implements Error { # CreateFeedsManagerPayload defines the response when creating a feeds manager union CreateFeedsManagerPayload = CreateFeedsManagerSuccess - | SingleFeedsManagerError + | DuplicateFeedsManagerError + | SingleFeedsManagerError # // TODO: delete once multiple feeds managers support is released | NotFoundError | InputErrors diff --git a/core/web/schema/type/starknet_key.graphql b/core/web/schema/type/starknet_key.graphql new file mode 100644 index 00000000000..bf8dbb864c2 --- /dev/null +++ b/core/web/schema/type/starknet_key.graphql @@ -0,0 +1,7 @@ +type StarkNetKey { + id: ID! +} + +type StarkNetKeysPayload { + results: [StarkNetKey!]! +} diff --git a/core/web/solana_chains_controller_test.go b/core/web/solana_chains_controller_test.go index 048a3790b1a..148d6302592 100644 --- a/core/web/solana_chains_controller_test.go +++ b/core/web/solana_chains_controller_test.go @@ -58,7 +58,26 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false Nodes = [] + +[MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'PriorityLevel' +SyncThreshold = 5 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '10s' +NodeNoNewHeadsThreshold = '10s' +NoNewFinalizedHeadsThreshold = '10s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 `, } }, diff --git a/core/web/solana_transfer_controller.go b/core/web/solana_transfer_controller.go index db93401d0d7..07c629a7dd1 100644 --- a/core/web/solana_transfer_controller.go +++ b/core/web/solana_transfer_controller.go @@ -60,7 +60,7 @@ func (tc *SolanaTransfersController) Create(c *gin.Context) { return } - err = relayer.Transact(c, tr.From.String(), tr.To.String(), amount, !tr.AllowHigherAmounts) + err = relayer.Transact(c.Request.Context(), tr.From.String(), tr.To.String(), amount, !tr.AllowHigherAmounts) if err != nil { if errors.Is(err, chains.ErrNotFound) || errors.Is(err, chains.ErrChainIDEmpty) { jsonAPIError(c, http.StatusBadRequest, err) diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html index d2b6db906b4..2bf427f5e00 100644 --- a/core/web/testdata/body/health.html +++ b/core/web/testdata/body/health.html @@ -32,6 +32,21 @@ color: rgba(100,101,10,0); } +
+ Cosmos +
+ Foo +
+ Chain +
+
+ Relayer +
+
+ Txm +
+
+
EVM
@@ -52,6 +67,9 @@
LogBroadcaster
+
+ Relayer +
Txm
@@ -102,6 +120,39 @@ BridgeCache
+
+ RetirementReportCache +
+
+ Solana +
+ Bar +
+ Chain +
+
+ Relayer +
+
+ Txm +
+
+
+
+ StarkNet +
+ Baz +
+ Chain +
+
+ Relayer +
+
+ Txm +
+
+
TelemetryManager
diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index 81ed7ff6d11..d573e0bd5fc 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -1,5 +1,32 @@ { "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.0", @@ -54,6 +81,15 @@ "output": "" } }, + { + "type": "checks", + "id": "EVM.0.Relayer", + "attributes": { + "name": "EVM.0.Relayer", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "EVM.0.Txm", @@ -180,6 +216,69 @@ "output": "" } }, + { + "type": "checks", + "id": "RetirementReportCache", + "attributes": { + "name": "RetirementReportCache", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.Chain", + "attributes": { + "name": "Solana.Bar.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.Relayer", + "attributes": { + "name": "Solana.Bar.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.Txm", + "attributes": { + "name": "Solana.Bar.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.Chain", + "attributes": { + "name": "StarkNet.Baz.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.Relayer", + "attributes": { + "name": "StarkNet.Baz.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.Txm", + "attributes": { + "name": "StarkNet.Baz.Txm", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "TelemetryManager", diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt index 6b165d26d99..fde038dfc63 100644 --- a/core/web/testdata/body/health.txt +++ b/core/web/testdata/body/health.txt @@ -1,3 +1,6 @@ +ok Cosmos.Foo.Chain +ok Cosmos.Foo.Relayer +ok Cosmos.Foo.Txm ok EVM.0 ok EVM.0.BalanceMonitor ok EVM.0.HeadBroadcaster @@ -5,6 +8,7 @@ ok EVM.0.HeadTracker ! EVM.0.HeadTracker.HeadListener Listener is not connected ok EVM.0.LogBroadcaster +ok EVM.0.Relayer ok EVM.0.Txm ok EVM.0.Txm.BlockHistoryEstimator ok EVM.0.Txm.Broadcaster @@ -19,4 +23,11 @@ ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache +ok RetirementReportCache +ok Solana.Bar.Chain +ok Solana.Bar.Relayer +ok Solana.Bar.Txm +ok StarkNet.Baz.Chain +ok StarkNet.Baz.Relayer +ok StarkNet.Baz.Txm ok TelemetryManager diff --git a/core/web/testutils/mock_relayer.go b/core/web/testutils/mock_relayer.go index 4c2e5661afa..4666f9da6a4 100644 --- a/core/web/testutils/mock_relayer.go +++ b/core/web/testutils/mock_relayer.go @@ -8,6 +8,7 @@ import ( ) type MockRelayer struct { + Head commontypes.Head ChainStatus commontypes.ChainStatus NodeStatuses []commontypes.NodeStatus } @@ -40,6 +41,10 @@ func (m MockRelayer) NewContractReader(_ context.Context, _ []byte) (commontypes panic("not implemented") } +func (m MockRelayer) LatestHead(_ context.Context) (commontypes.Head, error) { + return m.Head, nil +} + func (m MockRelayer) GetChainStatus(ctx context.Context) (commontypes.ChainStatus, error) { return m.ChainStatus, nil } diff --git a/dashboard-lib/atlas-don/component.go b/dashboard-lib/atlas-don/component.go index 39218c7aea8..beda6f48ec4 100644 --- a/dashboard-lib/atlas-don/component.go +++ b/dashboard-lib/atlas-don/component.go @@ -2,6 +2,7 @@ package atlas_don import ( "fmt" + "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/row" "github.com/K-Phoen/grabana/stat" diff --git a/dashboard-lib/ccip-load-test-view/component.go b/dashboard-lib/ccip-load-test-view/component.go index 9f58438410e..790ea6e9a9d 100644 --- a/dashboard-lib/ccip-load-test-view/component.go +++ b/dashboard-lib/ccip-load-test-view/component.go @@ -3,6 +3,7 @@ package ccip_load_test_view import ( "encoding/json" "fmt" + "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" "github.com/K-Phoen/grabana/row" diff --git a/dashboard-lib/config.go b/dashboard-lib/config.go index 2e0b9cad993..386082dae01 100644 --- a/dashboard-lib/config.go +++ b/dashboard-lib/config.go @@ -2,9 +2,10 @@ package dashboard_lib import ( "encoding/base64" - "github.com/pkg/errors" "os" "strings" + + "github.com/pkg/errors" ) type EnvConfig struct { diff --git a/dashboard-lib/core-don/component.go b/dashboard-lib/core-don/component.go index 24173fb6cc9..0589ab5cf8c 100644 --- a/dashboard-lib/core-don/component.go +++ b/dashboard-lib/core-don/component.go @@ -2,6 +2,7 @@ package core_don import ( "fmt" + "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/gauge" "github.com/K-Phoen/grabana/row" diff --git a/dashboard-lib/core-ocrv2-ccip/component.go b/dashboard-lib/core-ocrv2-ccip/component.go index 837f693fcc7..56b35587e18 100644 --- a/dashboard-lib/core-ocrv2-ccip/component.go +++ b/dashboard-lib/core-ocrv2-ccip/component.go @@ -2,6 +2,7 @@ package core_ocrv2_ccip import ( "fmt" + "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/row" "github.com/K-Phoen/grabana/target/prometheus" diff --git a/dashboard-lib/dashboard.go b/dashboard-lib/dashboard.go index 70892586bb0..92c4691a5ec 100644 --- a/dashboard-lib/dashboard.go +++ b/dashboard-lib/dashboard.go @@ -4,11 +4,12 @@ import ( "context" "encoding/json" "fmt" + "net/http" + "os" + "github.com/K-Phoen/grabana" "github.com/K-Phoen/grabana/dashboard" "github.com/pkg/errors" - "net/http" - "os" ) type Dashboard struct { diff --git a/dashboard-lib/go.mod b/dashboard-lib/go.mod index 10270853ed1..0efb47a5879 100644 --- a/dashboard-lib/go.mod +++ b/dashboard-lib/go.mod @@ -1,25 +1,29 @@ module github.com/smartcontractkit/chainlink/dashboard-lib -go 1.22.5 +go 1.22.8 require ( github.com/K-Phoen/grabana v0.22.1 - github.com/grafana/grafana-foundation-sdk/go v0.0.0-00010101000000-000000000000 + github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b github.com/pkg/errors v0.9.1 - github.com/rs/zerolog v1.32.0 + github.com/rs/zerolog v1.33.0 ) -replace github.com/grafana/grafana-foundation-sdk/go => github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240314112857-a7c9c6d0044c - require ( github.com/K-Phoen/sdk v0.12.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/gosimple/slug v1.13.1 // indirect github.com/gosimple/unidecode v1.0.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/common v0.45.0 // indirect - github.com/stretchr/testify v1.9.0 // indirect - golang.org/x/sys v0.16.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.59.1 // indirect + golang.org/x/sys v0.25.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect +) + +replace ( + github.com/grafana/grafana-foundation-sdk/go => github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240314112857-a7c9c6d0044c + github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264 ) diff --git a/dashboard-lib/go.sum b/dashboard-lib/go.sum index 7eb74088f13..06236c3228b 100644 --- a/dashboard-lib/go.sum +++ b/dashboard-lib/go.sum @@ -6,6 +6,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q= github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= @@ -15,23 +17,28 @@ github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240314112857-a7c9c6d0044c/ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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/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.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= -github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= 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= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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/docs/CONFIG.md b/docs/CONFIG.md index 74afcec7400..9b4a2ec2a48 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -52,6 +52,7 @@ FeedsManager = true # Default LogPoller = false # Default UICSAKeys = false # Default CCIP = true # Default +MultiFeedsManagers = false # Default ``` @@ -79,6 +80,12 @@ CCIP = true # Default ``` CCIP enables the CCIP service. +### MultiFeedsManagers +```toml +MultiFeedsManagers = false # Default +``` +MultiFeedsManagers enables support for multiple feeds manager connections. + ## Database ```toml [Database] @@ -249,7 +256,7 @@ LeaseRefreshInterval determines how often to refresh the lease lock. Also contro ## TelemetryIngress ```toml [TelemetryIngress] -UniConn = true # Default +UniConn = false # Default Logging = false # Default BufferSize = 100 # Default MaxBatchSize = 50 # Default @@ -261,7 +268,7 @@ UseBatchSend = true # Default ### UniConn ```toml -UniConn = true # Default +UniConn = false # Default ``` UniConn toggles which ws connection style is used. @@ -1233,6 +1240,60 @@ ChainID = '1' # Default ``` ChainID identifies the target chain id where the remote registry is located. +## Capabilities.Dispatcher +```toml +[Capabilities.Dispatcher] +SupportedVersion = 1 # Default +ReceiverBufferSize = 10000 # Default +``` + + +### SupportedVersion +```toml +SupportedVersion = 1 # Default +``` +SupportedVersion is the version of the version of message schema. + +### ReceiverBufferSize +```toml +ReceiverBufferSize = 10000 # Default +``` +ReceiverBufferSize is the size of the buffer for incoming messages. + +## Capabilities.Dispatcher.RateLimit +```toml +[Capabilities.Dispatcher.RateLimit] +GlobalRPS = 800 # Default +GlobalBurst = 1000 # Default +PerSenderRPS = 10 # Default +PerSenderBurst = 50 # Default +``` + + +### GlobalRPS +```toml +GlobalRPS = 800 # Default +``` +GlobalRPS is the global rate limit for the dispatcher. + +### GlobalBurst +```toml +GlobalBurst = 1000 # Default +``` +GlobalBurst is the global burst limit for the dispatcher. + +### PerSenderRPS +```toml +PerSenderRPS = 10 # Default +``` +PerSenderRPS is the per-sender rate limit for the dispatcher. + +### PerSenderBurst +```toml +PerSenderBurst = 50 # Default +``` +PerSenderBurst is the per-sender burst limit for the dispatcher. + ## Capabilities.Peering ```toml [Capabilities.Peering] @@ -1332,6 +1393,74 @@ ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example ListenAddresses is the addresses the peer will listen to on the network in `host:port` form as accepted by `net.Listen()`, but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. +## Capabilities.GatewayConnector +```toml +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '11155111' # Example +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' # Example +DonID = 'example_don' # Example +WSHandshakeTimeoutMillis = 1000 # Example +AuthMinChallengeLen = 10 # Example +AuthTimestampToleranceSec = 10 # Example +``` + + +### ChainIDForNodeKey +```toml +ChainIDForNodeKey = '11155111' # Example +``` +ChainIDForNodeKey is the ChainID of the network associated with a private key to be used for authentication with Gateway nodes + +### NodeAddress +```toml +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' # Example +``` +NodeAddress is the address of the desired private key to be used for authentication with Gateway nodes + +### DonID +```toml +DonID = 'example_don' # Example +``` +DonID is the Id of the Don + +### WSHandshakeTimeoutMillis +```toml +WSHandshakeTimeoutMillis = 1000 # Example +``` +WSHandshakeTimeoutMillis is Websocket handshake timeout + +### AuthMinChallengeLen +```toml +AuthMinChallengeLen = 10 # Example +``` +AuthMinChallengeLen is the minimum number of bytes in authentication challenge payload + +### AuthTimestampToleranceSec +```toml +AuthTimestampToleranceSec = 10 # Example +``` +AuthTimestampToleranceSec is Authentication timestamp tolerance + +## Capabilities.GatewayConnector.Gateways +```toml +[[Capabilities.GatewayConnector.Gateways]] +ID = 'example_gateway' # Example +URL = 'wss://localhost:8081/node' # Example +``` + + +### ID +```toml +ID = 'example_gateway' # Example +``` +ID of the Gateway + +### URL +```toml +URL = 'wss://localhost:8081/node' # Example +``` +URL of the Gateway + ## Keeper ```toml [Keeper] @@ -1768,6 +1897,64 @@ 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. +## Telemetry +```toml +[Telemetry] +Enabled = false # Default +Endpoint = 'example.com/collector' # Example +CACertFile = 'cert-file' # Example +InsecureConnection = false # Default +TraceSampleRatio = 0.01 # Default +``` +Telemetry holds OTEL settings. +This data includes open telemetry metrics, traces, & logs. +It does not currently include prometheus metrics or standard out logs, but may in the future. + +### Enabled +```toml +Enabled = false # Default +``` +Enabled turns telemetry collection on or off. + +### Endpoint +```toml +Endpoint = 'example.com/collector' # Example +``` +Endpoint of the OTEL Collector. + +### CACertFile +```toml +CACertFile = 'cert-file' # Example +``` +CACertFile is the file path of the TLS certificate used for secure communication with the OTEL Collector. +Required unless InescureConnection is true. + +### InsecureConnection +```toml +InsecureConnection = false # Default +``` +InsecureConnection bypasses the TLS CACertFile requirement and uses an insecure connection instead. +Only available in dev mode. + +### TraceSampleRatio +```toml +TraceSampleRatio = 0.01 # Default +``` +TraceSampleRatio is the rate at which to sample traces. Must be between 0 and 1. + +## Telemetry.ResourceAttributes +```toml +[Telemetry.ResourceAttributes] +foo = "bar" # Example +``` +ResourceAttributes are global metadata to include with all telemetry. + +### foo +```toml +foo = "bar" # Example +``` +foo is an example resource attribute + ## EVM EVM defaults depend on ChainID: @@ -1778,7 +1965,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -1790,6 +1977,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -1818,6 +2006,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -1833,12 +2022,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -1850,6 +2043,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -1862,6 +2056,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 10500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -1884,6 +2081,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -1912,6 +2110,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -1927,12 +2126,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -1944,6 +2147,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -1956,6 +2160,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -1978,6 +2185,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2006,6 +2214,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2021,12 +2230,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2038,6 +2251,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2050,6 +2264,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2072,6 +2289,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2100,6 +2318,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2115,12 +2334,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2132,6 +2355,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2144,6 +2368,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2156,7 +2383,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6' LogBackfillBatchSize = 1000 LogPollInterval = '2s' @@ -2167,6 +2394,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2195,6 +2423,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -2210,12 +2439,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2227,6 +2465,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -2239,6 +2478,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2261,6 +2503,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.001 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2289,6 +2532,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2304,12 +2548,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2321,6 +2569,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2333,6 +2582,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2355,6 +2607,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.001 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2383,6 +2636,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2398,12 +2652,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2415,6 +2673,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2427,6 +2686,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2450,6 +2712,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x8007e24251b1D2Fc518Eb843A701d9cD21fe0aA3' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2478,6 +2741,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2493,12 +2757,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2510,6 +2778,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2522,6 +2791,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2533,7 +2805,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x404460C6A5EdE2D891e8297795264fDe62ADBB75' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -2544,6 +2816,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 @@ -2567,11 +2840,12 @@ Enabled = true Mode = 'BlockHistory' PriceDefault = '5 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '3 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -2587,12 +2861,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2604,6 +2882,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2616,6 +2895,9 @@ ObservationGracePeriod = '500ms' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2637,6 +2919,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2665,6 +2948,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2680,12 +2964,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2697,6 +2985,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2709,6 +2998,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2730,6 +3022,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2758,6 +3051,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2773,12 +3067,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2790,6 +3088,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2802,6 +3101,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2813,7 +3115,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -2824,6 +3126,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 @@ -2852,6 +3155,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -2867,12 +3171,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = false +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2884,6 +3192,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2896,6 +3205,9 @@ ObservationGracePeriod = '500ms' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -2919,6 +3231,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -2947,6 +3260,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2962,12 +3276,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2979,6 +3297,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -2991,6 +3310,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3013,6 +3335,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 @@ -3041,6 +3364,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3056,12 +3380,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3073,6 +3401,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -3085,6 +3414,9 @@ ObservationGracePeriod = '500ms' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3096,7 +3428,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -3107,6 +3439,7 @@ MinIncomingConfirmations = 5 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 @@ -3135,6 +3468,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3150,12 +3484,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3167,6 +3505,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -3179,6 +3518,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3201,6 +3543,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '12m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 15 FinalizedBlockOffset = 0 @@ -3229,6 +3572,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -3244,12 +3588,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3261,6 +3609,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -3273,6 +3622,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3295,6 +3647,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '6m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 15 FinalizedBlockOffset = 0 @@ -3323,6 +3676,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -3338,12 +3692,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3355,6 +3713,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -3367,6 +3726,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3389,6 +3751,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 @@ -3417,6 +3780,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3432,12 +3796,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3449,6 +3817,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -3461,6 +3830,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 3800000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3473,7 +3845,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'kroma' FinalityDepth = 400 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -3483,6 +3855,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -3511,6 +3884,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -3526,12 +3900,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x4200000000000000000000000000000000000005' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 400 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3543,6 +3926,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -3555,6 +3939,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -3577,6 +3964,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '1m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -3605,6 +3993,7 @@ LimitDefault = 100000000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3620,12 +4009,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'zksync' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3637,6 +4034,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -3649,28 +4047,32 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

-
zkSync Sepolia (300)

+

Hedera Mainnet (295)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'zksync' +ChainType = 'hedera' FinalityDepth = 10 FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '5s' +LogPollInterval = '10s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '1m0s' +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -3682,7 +4084,7 @@ MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '2m0s' [Transactions.AutoPurge] Enabled = false @@ -3691,17 +4093,18 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'BlockHistory' +Mode = 'SuggestedPrice' PriceDefault = '20 gwei' -PriceMax = '18.446744073709551615 ether' -PriceMin = '0' -LimitDefault = 100000000 +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 -BumpMin = '5 gwei' +EstimateLimit = true +BumpMin = '10 gwei' BumpPercent = 20 -BumpThreshold = 3 +BumpThreshold = 0 EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' @@ -3714,23 +4117,28 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] -HistoryDepth = 50 +HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -3743,28 +4151,32 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

-
zkSync Mainnet (324)

+

Hedera Testnet (296)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'zksync' +ChainType = 'hedera' FinalityDepth = 10 FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '5s' +LogPollInterval = '10s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '1m0s' +NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -3776,7 +4188,7 @@ MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '2m0s' [Transactions.AutoPurge] Enabled = false @@ -3785,17 +4197,18 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'BlockHistory' +Mode = 'SuggestedPrice' PriceDefault = '20 gwei' -PriceMax = '18.446744073709551615 ether' -PriceMin = '0' -LimitDefault = 100000000 +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 gwei' +LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 -BumpMin = '5 gwei' +EstimateLimit = true +BumpMin = '10 gwei' BumpPercent = 20 -BumpThreshold = 3 +BumpThreshold = 0 EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' @@ -3808,23 +4221,28 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] -HistoryDepth = 50 +HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -3837,29 +4255,32 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

-
Optimism Goerli (420)

+

zkSync Sepolia (300)

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

-
Metis Rinkeby (588)

+

zkSync Mainnet (324)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'metis' +ChainType = 'zksync' FinalityDepth = 10 FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '15s' +LogPollInterval = '5s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '0s' +NoNewHeadsThreshold = '1m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -3974,14 +4409,15 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'SuggestedPrice' +Mode = 'BlockHistory' PriceDefault = '20 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMax = '18.446744073709551615 ether' PriceMin = '0' -LimitDefault = 500000 +LimitDefault = 100000000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3992,31 +4428,40 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 0 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'zksync' +CustomGasPriceCalldata = '' + [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 50 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 10 +SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 1 +ContractConfirmations = 4 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -4026,11 +4471,228 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

-
Klaytn Testnet (1001)

+

Optimism Goerli (420)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'optimismBedrock' +FinalityDepth = 200 +FinalityTagEnabled = false +LinkContractAddress = '0xdc2CC710e42857672E7907CF474a69B63B93089f' +LogBackfillBatchSize = 1000 +LogPollInterval = '2s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '30s' + +[Transactions.AutoPurge] +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' +CustomGasPriceCalldata = '' + +[HeadTracker] +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 = false +DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Metis Rinkeby (588)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'metis' +FinalityDepth = 10 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '15s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'SuggestedPrice' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '0' +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 = 0 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[HeadTracker] +HistoryDepth = 100 +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 = false +DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Klaytn Testnet (1001)

```toml AutoCreateKey = true @@ -4047,6 +4709,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4075,6 +4738,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -4090,12 +4754,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4107,6 +4775,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4119,6 +4788,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4131,7 +4803,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'metis' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '15s' LogKeepBlocksDepth = 100000 @@ -4141,6 +4813,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4169,6 +4842,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4184,12 +4858,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4201,6 +4879,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4213,6 +4892,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4235,6 +4917,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '6m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 15 FinalizedBlockOffset = 0 @@ -4255,15 +4938,16 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'BlockHistory' +Mode = 'FeeHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '100 mwei' +PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 -BumpMin = '100 mwei' +EstimateLimit = false +BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 EIP1559DynamicFees = false @@ -4273,17 +4957,21 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 12 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '4s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4295,6 +4983,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4307,6 +4996,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4319,7 +5011,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'wemix' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '3s' LogKeepBlocksDepth = 100000 @@ -4329,6 +5021,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4357,6 +5050,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4372,12 +5066,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4389,6 +5087,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4401,6 +5100,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4413,7 +5115,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'wemix' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '3s' LogKeepBlocksDepth = 100000 @@ -4423,6 +5125,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4451,6 +5154,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4466,12 +5170,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = false +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4483,6 +5191,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4495,6 +5204,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4516,6 +5228,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '100' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4544,6 +5257,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 0 @@ -4559,12 +5273,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 10 MaxBufferSize = 100 SamplingInterval = '0s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4576,6 +5294,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4588,32 +5307,37 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

-
Polygon Zkevm Goerli (1442)

+

Soneium Sepolia (1946)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'zkevm' -FinalityDepth = 500 -FinalityTagEnabled = false +ChainType = 'optimismBedrock' +FinalityDepth = 200 +FinalityTagEnabled = true +LinkContractAddress = '0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2' LogBackfillBatchSize = 1000 -LogPollInterval = '30s' +LogPollInterval = '2s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '12m0s' -RPCDefaultBatchSize = 100 +NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '0s' +NoNewFinalizedHeadsThreshold = '2h0m0s' [Transactions] ForwardersEnabled = false @@ -4621,7 +5345,7 @@ MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '3m0s' +ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false @@ -4633,43 +5357,54 @@ Enabled = true Mode = 'BlockHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '50 mwei' +PriceMin = '1 wei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 -BumpMin = '20 mwei' -BumpPercent = 40 +EstimateLimit = false +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 = 12 +BlockHistorySize = 60 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' +CustomGasPriceCalldata = '' + [HeadTracker] -HistoryDepth = 2000 +HistoryDepth = 300 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4681,7 +5416,10 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 5400000 +GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4694,7 +5432,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'kroma' FinalityDepth = 400 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -4704,6 +5442,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4732,6 +5471,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -4747,12 +5487,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x4200000000000000000000000000000000000005' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 400 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4764,6 +5513,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4776,6 +5526,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4798,6 +5551,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '12m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -4818,15 +5572,16 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'BlockHistory' +Mode = 'FeeHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 mwei' +PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 -BumpMin = '20 mwei' +EstimateLimit = false +BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 EIP1559DynamicFees = false @@ -4836,17 +5591,21 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 12 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '4s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4858,6 +5617,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -4870,6 +5630,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4892,6 +5655,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 @@ -4920,6 +5684,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4935,12 +5700,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4952,6 +5721,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -4964,6 +5734,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 3800000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -4985,6 +5758,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5013,6 +5787,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5028,12 +5803,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5045,6 +5824,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5057,6 +5837,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5069,7 +5852,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -5079,6 +5862,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5107,6 +5891,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -5122,12 +5907,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5139,6 +5933,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5151,6 +5946,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5173,6 +5971,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5201,6 +6000,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5216,12 +6016,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5233,6 +6037,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -5245,6 +6050,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5268,6 +6076,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5296,6 +6105,7 @@ LimitDefault = 500000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5311,12 +6121,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5328,6 +6146,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5340,6 +6159,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5363,6 +6185,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5391,6 +6214,7 @@ LimitDefault = 500000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5406,12 +6230,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5423,6 +6255,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5435,6 +6268,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5447,7 +6283,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'arbitrum' FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xf97f4df75117a78c1A5a0DBb814Af92458539FB4' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -5458,6 +6294,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5486,6 +6323,7 @@ LimitDefault = 500000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5501,12 +6339,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5518,6 +6364,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5530,6 +6377,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 14500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5552,6 +6402,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '1m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5580,6 +6431,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '2 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5595,12 +6447,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5612,6 +6468,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5624,6 +6481,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -5635,7 +6495,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -5646,6 +6506,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 @@ -5674,6 +6535,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5689,12 +6551,120 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[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 = false +DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Avalanche Mainnet (43114)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 10 +FinalityTagEnabled = true +LinkContractAddress = '0x5947BB275c521040051D82396192181b413227A3' +LogBackfillBatchSize = 1000 +LogPollInterval = '3s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '1m0s' + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 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 = 24 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[HeadTracker] +HistoryDepth = 100 +MaxBufferSize = 3 +SamplingInterval = '1s' +MaxAllowedFinalityDepth = 10000 +FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5706,6 +6676,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -5718,32 +6689,141 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 +``` + +

+ +
Celo Testnet (44787)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'celo' +FinalityDepth = 10 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '5s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '1m0s' +LogBroadcasterEnabled = true +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '1m0s' + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[Transactions.AutoPurge] +Enabled = false + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '5 gwei' +PriceMax = '500 gwei' +PriceMin = '5 gwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +EstimateLimit = false +BumpMin = '2 gwei' +BumpPercent = 20 +BumpThreshold = 3 +EIP1559DynamicFees = false +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' + +[HeadTracker] +HistoryDepth = 50 +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 = false +DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

-
Avalanche Mainnet (43114)

+

Zircuit Sepolia (48899)

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

-
Celo Testnet (44787)

+

Zircuit Mainnet (48900)

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

@@ -5927,6 +7041,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -5955,6 +7070,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 @@ -5970,12 +7086,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5987,6 +7107,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -5999,6 +7120,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6020,6 +7144,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6048,6 +7173,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6063,12 +7189,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 1000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6080,6 +7210,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -6092,6 +7223,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6113,6 +7247,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6141,6 +7276,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 @@ -6156,12 +7292,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 350 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6173,6 +7313,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -6185,6 +7326,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6197,7 +7341,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'metis' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '15s' LogKeepBlocksDepth = 100000 @@ -6207,6 +7351,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6235,6 +7380,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6250,12 +7396,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6267,6 +7417,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -6279,6 +7430,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6301,6 +7455,7 @@ MinIncomingConfirmations = 5 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 @@ -6329,6 +7484,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6344,12 +7500,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6361,6 +7521,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -6373,6 +7534,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6394,6 +7558,7 @@ MinIncomingConfirmations = 5 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 @@ -6422,6 +7587,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6437,12 +7603,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6454,6 +7624,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -6466,6 +7637,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6488,6 +7662,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6516,6 +7691,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -6531,12 +7707,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6548,6 +7733,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -6560,6 +7746,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6572,7 +7761,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -6582,6 +7771,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6610,6 +7800,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -6625,12 +7816,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6642,6 +7842,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -6654,6 +7855,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6677,6 +7881,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6705,6 +7910,7 @@ LimitDefault = 500000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6720,12 +7926,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6737,6 +7951,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -6749,6 +7964,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6772,6 +7990,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6800,6 +8019,7 @@ LimitDefault = 500000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6815,12 +8035,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6832,6 +8060,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -6844,6 +8073,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 14500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6856,7 +8088,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'arbitrum' FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '1s' LogKeepBlocksDepth = 100000 @@ -6866,6 +8098,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6894,6 +8127,7 @@ LimitDefault = 500000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6909,12 +8143,20 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'arbitrum' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6926,6 +8168,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -6938,6 +8181,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 14500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -6960,6 +8206,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -6988,6 +8235,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '1 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7003,12 +8251,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x5300000000000000000000000000000000000002' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7020,6 +8277,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -7032,6 +8290,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -7054,6 +8315,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -7082,6 +8344,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '1 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7097,12 +8360,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x5300000000000000000000000000000000000002' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7114,6 +8386,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -7126,6 +8399,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -7137,7 +8413,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x779877A7B0D9E8603169DdbD7836e478b4624789' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -7148,6 +8424,7 @@ MinIncomingConfirmations = 3 MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -7176,6 +8453,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7191,12 +8469,16 @@ 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 @@ -7208,6 +8490,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -7220,6 +8503,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 10500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -7232,7 +8518,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -7242,6 +8528,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '40s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -7270,6 +8557,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -7285,12 +8573,21 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + +[GasEstimator.DAOracle] +OracleType = 'opstack' +OracleAddress = '0x420000000000000000000000000000000000000F' +CustomGasPriceCalldata = '' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7302,6 +8599,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 1 @@ -7314,6 +8612,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 6500000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -7336,6 +8637,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -7364,6 +8666,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7379,12 +8682,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7396,6 +8703,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -7408,6 +8716,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -7430,6 +8741,7 @@ MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true NoNewHeadsThreshold = '30s' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -7458,6 +8770,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7473,12 +8786,16 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7490,6 +8807,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [OCR] ContractConfirmations = 4 @@ -7502,6 +8820,9 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] GasLimit = 5400000 + +[Workflow] +GasLimitDefault = 400000 ```

@@ -7694,6 +9015,12 @@ The latest finalized block on chain is 64, so block 63 is the latest finalized f Block 64 will be treated as finalized by CL Node only when chain's latest finalized block is 65. As chain finalizes blocks in batches of 32, CL Node has to wait for a whole new batch to be finalized to treat block 64 as finalized. +### LogBroadcasterEnabled +```toml +LogBroadcasterEnabled = true # Default +``` +LogBroadcasterEnabled is a feature flag for LogBroadcaster, by default it's true. + ### NoNewFinalizedHeadsThreshold ```toml NoNewFinalizedHeadsThreshold = '0' # Default @@ -7819,6 +9146,7 @@ LimitDefault = 500_000 # Default LimitMax = 500_000 # Default LimitMultiplier = '1.0' # Default LimitTransfer = 21_000 # Default +EstimateLimit = false # Default BumpMin = '5 gwei' # Default BumpPercent = 20 # Default BumpThreshold = 3 # Default @@ -7913,6 +9241,12 @@ LimitTransfer = 21_000 # Default ``` LimitTransfer is the gas limit used for an ordinary ETH transfer. +### EstimateLimit +```toml +EstimateLimit = false # Default +``` +EstimateLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. + ### BumpMin ```toml BumpMin = '5 gwei' # Default @@ -8010,6 +9344,33 @@ TipCapMinimum is the minimum gas tip to use when submitting transactions to the (Only applies to EIP-1559 transactions) +## EVM.GasEstimator.DAOracle +```toml +[EVM.GasEstimator.DAOracle] +OracleType = 'opstack' # Example +OracleAddress = '0x420000000000000000000000000000000000000F' # Example +CustomGasPriceCalldata = '' # Default +``` + + +### OracleType +```toml +OracleType = 'opstack' # Example +``` +OracleType refers to the oracle family this config belongs to. Currently the available oracle types are: 'opstack', 'arbitrum', 'zksync', and 'custom_calldata'. + +### OracleAddress +```toml +OracleAddress = '0x420000000000000000000000000000000000000F' # Example +``` +OracleAddress is the address of the oracle contract. + +### CustomGasPriceCalldata +```toml +CustomGasPriceCalldata = '' # Default +``` +CustomGasPriceCalldata is optional and can be set to call a custom gas price function at the given OracleAddress. + ## EVM.GasEstimator.LimitJobType ```toml [EVM.GasEstimator.LimitJobType] @@ -8126,6 +9487,24 @@ Setting this number higher will cause the Chainlink node to select higher gas pr Setting it lower will tend to set lower gas prices. +## EVM.GasEstimator.FeeHistory +```toml +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' # Default +``` + + +### CacheTimeout +```toml +CacheTimeout = '10s' # Default +``` +CacheTimeout is the time to wait in order to refresh the cached values stored in the FeeHistory estimator. A small jitter is applied so the timeout won't be exactly the same each time. + +You want this value to be close to the block time. For slower chains, like Ethereum, you can set it to 12s, the same as the block time. For faster chains you can skip a block or two +and set it to two times the block time i.e. on Optimism you can set it to 4s. Ideally, you don't want to go lower than 1s since the RTT times of the RPC requests will be comparable to +the timeout. The estimator is already adding a buffer to account for a potential increase in prices within one or two blocks. On the other hand, slower frequency will fail to refresh +the prices and end up in stale values. + ## EVM.HeadTracker ```toml [EVM.HeadTracker] @@ -8134,6 +9513,7 @@ MaxBufferSize = 3 # Default SamplingInterval = '1s' # Default FinalityTagBypass = true # Default MaxAllowedFinalityDepth = 10000 # Default +PersistenceEnabled = true # Default ``` The head tracker continually listens for new heads from the chain. @@ -8180,6 +9560,15 @@ MaxAllowedFinalityDepth - defines maximum number of blocks between the most rece If actual finality depth exceeds this number, HeadTracker aborts backfill and returns an error. Has no effect if `FinalityTagsEnabled` = false +### PersistenceEnabled +```toml +PersistenceEnabled = true # Default +``` +PersistenceEnabled defines whether HeadTracker needs to store heads in the database. +Persistence is helpful on chains with large finality depth, where fetching blocks from the latest to the latest finalized takes a lot of time. +On chains with fast finality, the persistence layer does not improve the chain's load time and only consumes database resources (mainly IO). +NOTE: persistence should not be disabled for products that use LogBroadcaster, as it might lead to missed on-chain events. + ## EVM.KeySpecific ```toml [[EVM.KeySpecific]] @@ -8212,6 +9601,7 @@ NodeIsSyncingEnabled = false # Default FinalizedBlockPollInterval = '5s' # Default EnforceRepeatableRead = false # Default DeathDeclarationDelay = '10s' # Default +NewHeadsPollInterval = '0s' # Default ``` The node pool manages multiple RPC endpoints. @@ -8304,6 +9694,14 @@ Larger values might be helpful to reduce the noisiness of health checks like `En trigger declaration of `FinalizedBlockOutOfSync` due to insignificant network delays in broadcasting of the finalized state among RPCs. RPC will not be picked to handle a request even if this option is set to a nonzero value. +### NewHeadsPollInterval +```toml +NewHeadsPollInterval = '0s' # Default +``` +NewHeadsPollInterval define an interval for polling new block periodically using http client rather than subscribe to ws feed + +Set to 0 to disable. + ## EVM.NodePool.Errors :warning: **_ADVANCED_**: _Do not change these settings unless you know what you are doing._ ```toml @@ -8322,6 +9720,7 @@ L2Full = '(: |^)l2 full' # Example TransactionAlreadyMined = '(: |^)transaction already mined' # Example Fatal = '(: |^)fatal' # Example ServiceUnavailable = '(: |^)service unavailable' # Example +TooManyResults = '(: |^)too many results' # Example ``` Errors enable the node to provide custom regex patterns to match against error messages from RPCs. @@ -8409,6 +9808,12 @@ ServiceUnavailable = '(: |^)service unavailable' # Example ``` ServiceUnavailable is a regex pattern to match against service unavailable errors. +### TooManyResults +```toml +TooManyResults = '(: |^)too many results' # Example +``` +TooManyResults is a regex pattern to match an eth_getLogs error indicating the result set is too large to return + ## EVM.OCR ```toml [EVM.OCR] @@ -8482,7 +9887,7 @@ Name is a unique (per-chain) identifier for this node. ```toml WSURL = 'wss://web.socket/test' # Example ``` -WSURL is the WS(S) endpoint for this node. Required for primary nodes. +WSURL is the WS(S) endpoint for this node. Required for primary nodes when `LogBroadcasterEnabled` is `true` ### HTTPURL ```toml @@ -8520,6 +9925,7 @@ GasLimit controls the gas limit for transmit transactions from ocr2automation jo [EVM.Workflow] FromAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example ForwarderAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example +GasLimitDefault = 400_000 # Default ``` @@ -8535,6 +9941,12 @@ ForwarderAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example ``` ForwarderAddress is the keystone forwarder contract address on chain. +### GasLimitDefault +```toml +GasLimitDefault = 400_000 # Default +``` +GasLimitDefault is the default gas limit for workflow transactions. + ## Cosmos ```toml [[Cosmos]] @@ -8673,6 +10085,8 @@ ComputeUnitPriceMin = 0 # Default ComputeUnitPriceDefault = 0 # Default FeeBumpPeriod = '3s' # Default BlockHistoryPollPeriod = '5s' # Default +ComputeUnitLimitDefault = 200_000 # Default +EstimateComputeUnitLimit = false # Default ``` @@ -8785,11 +10199,135 @@ BlockHistoryPollPeriod = '5s' # Default ``` BlockHistoryPollPeriod is the rate to poll for blocks in the block history fee estimator +### ComputeUnitLimitDefault +```toml +ComputeUnitLimitDefault = 200_000 # Default +``` +ComputeUnitLimitDefault is the compute units limit applied to transactions unless overriden during the txm enqueue + +### EstimateComputeUnitLimit +```toml +EstimateComputeUnitLimit = false # Default +``` +EstimateComputeUnitLimit enables or disables compute unit limit estimations per transaction. If estimations return 0 used compute, the ComputeUnitLimitDefault value is used, if set. + +## Solana.MultiNode +```toml +[Solana.MultiNode] +Enabled = false # Default +PollFailureThreshold = 5 # Default +PollInterval = '10s' # Default +SelectionMode = 'PriorityLevel' # Default +SyncThreshold = 5 # Default +NodeIsSyncingEnabled = false # Default +LeaseDuration = '1m0s' # Default +FinalizedBlockPollInterval = '10s' # Default +EnforceRepeatableRead = true # Default +DeathDeclarationDelay = '10s' # Default +NodeNoNewHeadsThreshold = '10s' # Default +NoNewFinalizedHeadsThreshold = '10s' # Default +FinalityDepth = 0 # Default +FinalityTagEnabled = true # Default +FinalizedBlockOffset = 0 # Default +``` + + +### Enabled +```toml +Enabled = false # Default +``` +Enabled enables the multinode feature. + +### PollFailureThreshold +```toml +PollFailureThreshold = 5 # Default +``` +PollFailureThreshold is the number of consecutive poll failures before a node is considered unhealthy. + +### PollInterval +```toml +PollInterval = '10s' # Default +``` +PollInterval is the rate to poll for node health. + +### SelectionMode +```toml +SelectionMode = 'PriorityLevel' # Default +``` +SelectionMode is the method used to select the next best node to use. + +### SyncThreshold +```toml +SyncThreshold = 5 # Default +``` +SyncThreshold is the number of blocks behind the best node that a node can be before it is considered out of sync. + +### NodeIsSyncingEnabled +```toml +NodeIsSyncingEnabled = false # Default +``` +NodeIsSyncingEnabled enables the feature to avoid sending transactions to nodes that are syncing. Not relavant for Solana. + +### LeaseDuration +```toml +LeaseDuration = '1m0s' # Default +``` +LeaseDuration is the max duration a node can be leased for. + +### FinalizedBlockPollInterval +```toml +FinalizedBlockPollInterval = '10s' # Default +``` +FinalizedBlockPollInterval is the rate to poll for the finalized block. + +### EnforceRepeatableRead +```toml +EnforceRepeatableRead = true # Default +``` +EnforceRepeatableRead enforces the repeatable read guarantee for multinode. + +### DeathDeclarationDelay +```toml +DeathDeclarationDelay = '10s' # Default +``` +DeathDeclarationDelay is the duration to wait before declaring a node dead. + +### NodeNoNewHeadsThreshold +```toml +NodeNoNewHeadsThreshold = '10s' # Default +``` +NodeNoNewHeadsThreshold is the duration to wait before declaring a node unhealthy due to no new heads. + +### NoNewFinalizedHeadsThreshold +```toml +NoNewFinalizedHeadsThreshold = '10s' # Default +``` +NoNewFinalizedHeadsThreshold is the duration to wait before declaring a node unhealthy due to no new finalized heads. + +### FinalityDepth +```toml +FinalityDepth = 0 # Default +``` +FinalityDepth is not used when finality tags are enabled. + +### FinalityTagEnabled +```toml +FinalityTagEnabled = true # Default +``` +FinalityTagEnabled enables the use of finality tags. + +### FinalizedBlockOffset +```toml +FinalizedBlockOffset = 0 # Default +``` +FinalizedBlockOffset is the offset from the finalized block to use for finality tags. + ## Solana.Nodes ```toml [[Solana.Nodes]] Name = 'primary' # Example URL = 'http://solana.web' # Example +SendOnly = false # Default ``` @@ -8805,6 +10343,12 @@ URL = 'http://solana.web' # Example ``` URL is the HTTP(S) endpoint for this node. +### SendOnly +```toml +SendOnly = false # Default +``` +SendOnly is a multinode config that only sends transactions to a node and does not read state + ## Starknet ```toml [[Starknet]] diff --git a/flake.lock b/flake.lock index c5097f5a477..71af2318c95 100644 --- a/flake.lock +++ b/flake.lock @@ -26,11 +26,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1719997877, - "narHash": "sha256-/Edw+w0PiGgxwnCeJycM0VgH4HtlCi91v1d8xbi+REE=", + "lastModified": 1725354688, + "narHash": "sha256-KHHFemVt6C/hbGoMzIq7cpxmjdp+KZVZaqbvx02aliY=", "owner": "shazow", "repo": "foundry.nix", - "rev": "02febba4f1cf0606d790acdb24adcf7a64afb4e1", + "rev": "671672bd60a0d2e5f6757638fdf27e806df755a4", "type": "github" }, "original": { @@ -40,6 +40,24 @@ "type": "github" } }, + "goreleaser-nur": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1726594821, + "narHash": "sha256-ORImH+i+zOCMOdztNDqGDbyyFRC/FKmgbX8w50TNbQY=", + "owner": "goreleaser", + "repo": "nur", + "rev": "bd2ee272ddfffbda9377a472131728e83ce2332d", + "type": "github" + }, + "original": { + "owner": "goreleaser", + "repo": "nur", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1666753130, @@ -56,11 +74,27 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1720957393, - "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", + "lastModified": 1624561540, + "narHash": "sha256-izJ2PYZMGMsSkg+e7c9A1x3t/yOLT+qzUM6WQsc2tqo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c6a049a3d32293b24c0f894a840872cf67fd7c11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1725103162, + "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", + "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", "type": "github" }, "original": { @@ -70,11 +104,28 @@ "type": "github" } }, + "nur": { + "locked": { + "lastModified": 1727912806, + "narHash": "sha256-LDOTTOGPaEP233gBrL8dnPGopc1lqcJFe0VB/+K/yWc=", + "owner": "nix-community", + "repo": "NUR", + "rev": "9d9bcd30fec126b08b49020b7af08bc1aad66210", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", "foundry": "foundry", - "nixpkgs": "nixpkgs_2" + "goreleaser-nur": "goreleaser-nur", + "nixpkgs": "nixpkgs_3", + "nur": "nur" } }, "systems": { diff --git a/flake.nix b/flake.nix index 7e188857ba4..0d1aac2f05d 100644 --- a/flake.nix +++ b/flake.nix @@ -6,6 +6,8 @@ foundry.url = "github:shazow/foundry.nix/monthly"; flake-utils.url = "github:numtide/flake-utils"; foundry.inputs.flake-utils.follows = "flake-utils"; + nur.url = "github:nix-community/NUR"; + goreleaser-nur.url = "github:goreleaser/nur"; }; outputs = inputs @ { @@ -13,15 +15,30 @@ nixpkgs, flake-utils, foundry, + nur, + goreleaser-nur, ... }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { - inherit system; - overlays = [foundry.overlay]; - }; + isCrib = builtins.getEnv "IS_CRIB" == "true"; + pkgs = import nixpkgs { inherit system; + config = { allowUnfree = true; }; + overlays = [ + (final: prev: { + nur = import nur + { + pkgs = prev; + repoOverrides = { + goreleaser = import goreleaser-nur { pkgs = prev; }; + }; + }; + }) + foundry.overlay + ]; + }; in rec { devShell = pkgs.callPackage ./shell.nix { + isCrib = isCrib; inherit pkgs; }; formatter = pkgs.nixpkgs-fmt; diff --git a/go.md b/go.md index 697d6b52cea..d9d4ea5cf35 100644 --- a/go.md +++ b/go.md @@ -5,11 +5,7 @@ flowchart LR chainlink-cosmos chainlink-solana chainlink-starknet/relayer - subgraph chainlink-integrations - direction LR - chainlink-integrations/evm/relayer - chainlink-integrations/common - end + chainlink-evm end subgraph products @@ -21,8 +17,13 @@ flowchart LR chainlink-vrf end + subgraph tdh2 + tdh2/go/tdh2 + tdh2/go/ocr2/decryptionplugin + end + classDef outline stroke-dasharray:6,fill:none; - class chains,products outline + class chains,products,tdh2 outline chainlink/v2 --> chain-selectors click chain-selectors href "https://github.com/smartcontractkit/chain-selectors" @@ -38,10 +39,14 @@ flowchart LR click chainlink-data-streams href "https://github.com/smartcontractkit/chainlink-data-streams" chainlink/v2 --> chainlink-feeds click chainlink-feeds href "https://github.com/smartcontractkit/chainlink-feeds" + chainlink/v2 --> chainlink-protos/orchestrator + click chainlink-protos/orchestrator href "https://github.com/smartcontractkit/chainlink-protos" chainlink/v2 --> chainlink-solana click chainlink-solana href "https://github.com/smartcontractkit/chainlink-solana" chainlink/v2 --> chainlink-starknet/relayer click chainlink-starknet/relayer href "https://github.com/smartcontractkit/chainlink-starknet" + chainlink/v2 --> grpc-proxy + click grpc-proxy href "https://github.com/smartcontractkit/grpc-proxy" chainlink/v2 --> libocr click libocr href "https://github.com/smartcontractkit/libocr" chainlink/v2 --> tdh2/go/ocr2/decryptionplugin @@ -52,19 +57,27 @@ flowchart LR click wsrpc href "https://github.com/smartcontractkit/wsrpc" chainlink-automation --> chainlink-common chainlink-automation --> libocr + chainlink-ccip --> chain-selectors chainlink-ccip --> chainlink-common chainlink-ccip --> libocr + chainlink-common --> grpc-proxy chainlink-common --> libocr chainlink-cosmos --> chainlink-common chainlink-cosmos --> libocr + chainlink-cosmos --> grpc-proxy chainlink-data-streams --> chainlink-common chainlink-data-streams --> libocr + chainlink-data-streams --> grpc-proxy chainlink-feeds --> chainlink-common chainlink-feeds --> libocr + chainlink-feeds --> grpc-proxy + chainlink-protos/orchestrator --> wsrpc chainlink-solana --> chainlink-common chainlink-solana --> libocr + chainlink-solana --> grpc-proxy chainlink-starknet/relayer --> chainlink-common chainlink-starknet/relayer --> libocr + chainlink-starknet/relayer --> grpc-proxy tdh2/go/ocr2/decryptionplugin --> libocr tdh2/go/ocr2/decryptionplugin --> tdh2/go/tdh2 ``` diff --git a/go.mod b/go.mod index 7976cbcd440..3398d050fd2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/v2 -go 1.22.5 +go 1.22.8 require ( github.com/Depado/ginprom v1.8.0 @@ -9,38 +9,40 @@ require ( github.com/NethermindEth/juno v0.3.1 github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb github.com/XSAM/otelsql v0.27.0 + github.com/andybalholm/brotli v1.1.0 github.com/avast/retry-go/v4 v4.6.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 - github.com/cometbft/cometbft v0.37.2 - github.com/cosmos/cosmos-sdk v0.47.4 + github.com/cometbft/cometbft v0.37.5 + github.com/cosmos/cosmos-sdk v0.47.11 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/esote/minmaxheap v1.0.0 github.com/ethereum/go-ethereum v1.13.8 - github.com/fatih/color v1.16.0 - github.com/fxamacker/cbor/v2 v2.5.0 + github.com/fatih/color v1.17.0 + github.com/fxamacker/cbor/v2 v2.7.0 github.com/gagliardetto/solana-go v1.8.4 - github.com/getsentry/sentry-go v0.19.0 + github.com/getsentry/sentry-go v0.23.0 github.com/gin-contrib/cors v1.5.0 github.com/gin-contrib/expvar v0.0.1 github.com/gin-contrib/sessions v0.0.5 github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4 github.com/gin-gonic/gin v1.9.1 github.com/go-ldap/ldap/v3 v3.4.6 + github.com/go-viper/mapstructure/v2 v2.1.0 github.com/go-webauthn/webauthn v0.9.4 - github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b + github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da github.com/google/uuid v1.6.0 github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.2.2 github.com/gorilla/websocket v1.5.1 - github.com/grafana/pyroscope-go v1.1.1 + github.com/grafana/pyroscope-go v1.1.2 github.com/graph-gophers/dataloader v5.0.0+incompatible - github.com/graph-gophers/graphql-go v1.3.0 + github.com/graph-gophers/graphql-go v1.5.0 github.com/hashicorp/consul/sdk v0.16.0 github.com/hashicorp/go-envparse v0.1.0 - github.com/hashicorp/go-plugin v1.6.0 - github.com/hashicorp/go-retryablehttp v0.7.5 + github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 + github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hdevalence/ed25519consensus v0.1.0 github.com/jackc/pgconn v1.14.3 github.com/jackc/pgtype v1.14.0 @@ -53,38 +55,38 @@ require ( github.com/lib/pq v1.10.9 github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f github.com/mitchellh/go-homedir v1.1.0 - github.com/mitchellh/mapstructure v1.5.0 github.com/mr-tron/base58 v1.2.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/onsi/gomega v1.30.0 + github.com/onsi/gomega v1.33.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pelletier/go-toml v1.9.5 - github.com/pelletier/go-toml/v2 v2.2.0 + github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.21.1 - github.com/prometheus/client_golang v1.17.0 - github.com/prometheus/client_model v0.5.0 - github.com/prometheus/common v0.45.0 - github.com/prometheus/prometheus v0.48.1 + github.com/prometheus/client_golang v1.20.0 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.59.1 + github.com/prometheus/prometheus v0.54.1 github.com/robfig/cron/v3 v3.0.1 github.com/rogpeppe/go-internal v1.12.0 - github.com/rs/zerolog v1.30.0 + github.com/rs/zerolog v1.33.0 github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chain-selectors v1.0.10 - github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f - github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 - github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/wsrpc v0.7.3 + github.com/smartcontractkit/chain-selectors v1.0.27 + github.com/smartcontractkit/chainlink-automation v0.8.0 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e + github.com/smartcontractkit/chainlink-feeds v0.1.1 + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 + github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 + 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.2 github.com/spf13/cast v1.6.0 github.com/stretchr/testify v1.9.0 github.com/test-go/testify v1.1.4 @@ -100,49 +102,47 @@ require ( go.dedis.ch/kyber/v3 v3.1.0 go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/metric v1.28.0 + go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.25.0 - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/mod v0.19.0 - golang.org/x/net v0.27.0 - golang.org/x/sync v0.7.0 - golang.org/x/term v0.22.0 - golang.org/x/text v0.16.0 - golang.org/x/time v0.5.0 - golang.org/x/tools v0.23.0 + golang.org/x/crypto v0.27.0 + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 + golang.org/x/mod v0.21.0 + golang.org/x/net v0.29.0 + golang.org/x/sync v0.8.0 + golang.org/x/term v0.24.0 + golang.org/x/text v0.18.0 + golang.org/x/time v0.6.0 + golang.org/x/tools v0.25.0 gonum.org/v1/gonum v0.15.0 google.golang.org/grpc v1.65.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 gopkg.in/guregu/null.v4 v4.0.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 - k8s.io/utils v0.0.0-20230711102312-30195339c3c7 + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 ) require ( - cloud.google.com/go/auth v0.7.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect - cloud.google.com/go/iam v1.1.11 // indirect - cloud.google.com/go/storage v1.43.0 // indirect 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.3 // indirect - cosmossdk.io/errors v1.0.0 // indirect - cosmossdk.io/math v1.0.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/math v1.3.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect + github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // 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 @@ -150,6 +150,7 @@ require ( github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect @@ -157,24 +158,25 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/errors v1.10.0 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v0.7.0 // indirect + github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/containerd/continuity v0.4.3 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogoproto v1.4.11 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.0.1 // indirect - github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cosmos/iavl v0.20.1 // indirect + github.com/cosmos/ibc-go/v7 v7.5.1 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect @@ -185,12 +187,12 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // 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/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect @@ -204,16 +206,18 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.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.15.5 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/go-webauthn/x v0.1.5 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.3 // indirect - github.com/golang-jwt/jwt/v5 v5.2.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -223,17 +227,17 @@ require ( github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/context v1.1.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect 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/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -244,6 +248,7 @@ require ( github.com/huandu/skiplist v1.2.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect @@ -255,61 +260,67 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.3 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/leodido/go-urn v1.2.4 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/magiconair/properties v1.8.7 // indirect 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/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mfridman/interpolate v0.0.2 // 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 + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mtibben/percent v0.2.1 // indirect - github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.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/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/cobra v1.8.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.15.0 // 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/stretchr/objx v0.5.2 // indirect - github.com/subosito/gotenv v1.4.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect @@ -318,34 +329,37 @@ require ( github.com/valyala/fastjson v1.4.1 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/protobuf v1.0.11 // indirect - go.etcd.io/bbolt v1.3.7 // 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/google.golang.org/grpc/otelgrpc v0.53.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.4.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.4.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/ratelimit v0.3.0 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.22.0 // indirect - google.golang.org/api v0.188.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect gopkg.in/guregu/null.v2 v2.1.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - pgregory.net/rapid v0.5.5 // indirect + pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -354,12 +368,5 @@ replace ( // replicating the replace directive on cosmos SDK github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 - github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 - - // until nolag updates merged upstream - github.com/mitchellh/mapstructure => github.com/nolag/mapstructure v1.5.2-0.20240625151721-90ea83a3f479 - - // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 - github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f + github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264 ) diff --git a/go.sum b/go.sum index 704b9507c69..835d5f8de76 100644 --- a/go.sum +++ b/go.sum @@ -4,20 +4,12 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR 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.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= @@ -27,9 +19,7 @@ cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -40,13 +30,9 @@ cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNc cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -57,14 +43,14 @@ 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= cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= -cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca h1:msenprh2BLLRwNT7zN56TbBHOGk/7ARQckXHxXyvjoQ= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca/go.mod h1:PkIAKXZvaxrTRc++z53XMRvFk8AcGGWYHcMIPzVYX9c= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= +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= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -77,7 +63,6 @@ github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo8 github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= @@ -85,10 +70,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/CosmWasm/wasmd v0.40.1 h1:LxbO78t/6S8TkeQlUrJ0m5O87HtAwLx4RGHq3rdrOEU= github.com/CosmWasm/wasmd v0.40.1/go.mod h1:6EOwnv7MpuFaEqxcUOdFV9i4yvrdOciaY6VQ1o7A3yg= github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ= @@ -100,7 +83,6 @@ 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/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= @@ -109,8 +91,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb h1:Mv8SscePPyw2ju4igIJAjFgcq5zCQfjgbz53DwYu5mc= @@ -120,17 +102,13 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= 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/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA= 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= @@ -141,6 +119,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax 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.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= @@ -150,13 +130,14 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQVoh6kY+c4b0HUchHjGWBI8288VhH50qxKG3hdEg0= +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.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= -github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +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/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= @@ -179,14 +160,16 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= -github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/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/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.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= @@ -219,43 +202,37 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= -github.com/cockroachdb/apd/v3 v3.1.0/go.mod h1:6qgPBMXjATAdD/VefbRP9NoSLKjbB4LCoA7gN4LpHs4= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= +github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= -github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0= +github.com/cometbft/cometbft v0.37.5/go.mod h1:QC+mU0lBhKn8r9qvmnq53Dmf3DWBt4VtkcKw2C81wxY= +github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= +github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= 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= @@ -268,10 +245,10 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV 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.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.4 h1:FVUpEprm58nMmBX4xkRdMDaIG5Nr4yy92HZAfGAw9bg= -github.com/cosmos/cosmos-sdk v0.47.4/go.mod h1:R5n+uM7vguVPFap4pgkdvQCT1nVo/OtPwrlAU40rvok= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.47.11 h1:0Qx7eORw0RJqPv+mvDuU8NQ1LV3nJJKJnPoYblWHolc= +github.com/cosmos/cosmos-sdk v0.47.11/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -279,21 +256,21 @@ github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiK github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= -github.com/cosmos/ibc-go/v7 v7.0.1 h1:NIBNRWjlOoFvFQu1ZlgwkaSeHO5avf4C1YQiWegt8jw= -github.com/cosmos/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab h1:I9ialKTQo7248V827Bba4OuKPmk+FPzmTVHsLXaIJWw= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab/go.mod h1:2CwqasX5dSD7Hbp/9b6lhK6BwoBDCBldx7gPKRukR60= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= +github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/ibc-go/v7 v7.5.1 h1:KqS/g7W7EMX1OtOvufS8lWMJibOKpdgtNNZIU6fAgVU= +github.com/cosmos/ibc-go/v7 v7.5.1/go.mod h1:ktFg5GvKOyrGCqTWtW7Grj5uweU4ZapxrNeVS1CLLbo= +github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= +github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw= +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/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= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= @@ -302,15 +279,12 @@ 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/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/gherkin/go/v22 v22.0.0/go.mod h1:3mJT10B2GGn3MvVPd3FwR7m2u4tLhSRhWUqJU4KN4Fg= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= -github.com/cucumber/common/messages/go/v17 v17.1.1/go.mod h1:bpGxb57tDE385Rb2EohgUadLkAbhoC4IyCFi89u/JQI= 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= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e/go.mod h1:IJgIiGUARc4aOr4bOQ85klmjsShkEEfiRc6q/yBSfo8= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -326,7 +300,6 @@ github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFM 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 v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 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= @@ -339,8 +312,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= 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= @@ -350,34 +323,22 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= 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.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= @@ -389,12 +350,12 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +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/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= @@ -403,16 +364,14 @@ github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtL 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/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= 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/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= -github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= +github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= +github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= @@ -431,8 +390,6 @@ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -455,13 +412,14 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -472,42 +430,40 @@ 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.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +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-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= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6lpIc2g= github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= +github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= @@ -521,9 +477,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -531,7 +485,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -551,7 +504,6 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -560,18 +512,15 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -579,8 +528,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -588,21 +535,15 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= -github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -612,7 +553,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -625,18 +565,17 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX 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.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= -github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= +github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= +github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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= @@ -648,8 +587,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf 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.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -672,17 +611,18 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 h1:OSQYEsRT3tRttZkk6zyC3aAaliwd7Loi/KgXgXxGtwA= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= -github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= @@ -692,7 +632,6 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -729,13 +668,13 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -743,11 +682,6 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -807,8 +741,8 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= 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.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +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= @@ -823,29 +757,19 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 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.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -859,13 +783,11 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -874,6 +796,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= +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/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -889,12 +813,9 @@ github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9 github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= 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.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 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.8/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.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -902,11 +823,11 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx 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.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 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.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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= @@ -915,14 +836,9 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh 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= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= 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/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 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= @@ -939,8 +855,14 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -959,24 +881,19 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= -github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= 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/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/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= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= 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/nolag/mapstructure v1.5.2-0.20240625151721-90ea83a3f479 h1:1jCGDLFXDOHF2sdeTJYKrIuSLGMpQZpgXXHNGXR5Ouk= -github.com/nolag/mapstructure v1.5.2-0.20240625151721-90ea83a3f479/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= -github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= +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= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -986,26 +903,25 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn 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= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 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.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= +github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= 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= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= -github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40= +github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -1020,8 +936,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 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= @@ -1032,7 +948,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1045,35 +961,33 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP 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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +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.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= 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.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= -github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= +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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= -github.com/regen-network/gocuke v0.6.2/go.mod h1:zYaqIHZobHyd0xOrHGPQjbhGJsuZ1oElx150u2o1xuk= 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/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -1088,34 +1002,36 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L 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= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= -github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= +github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +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= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= @@ -1135,64 +1051,64 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= -github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= -github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 h1:LAgJTg9Yr/uCo2g7Krp88Dco2U45Y6sbJVl8uKoLkys= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 h1:iT9xlcy7Q98F9QheClGBiU0Ig1A+0UhtFkEdKFHvX/0= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f h1:I9fTBJpHkeldFplXUy71eLIn6A6GxuR4xrABoUeD+CM= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f/go.mod h1:V/86loaFSH0dqqUEHqyXVbyNqDRSjvcf9BRomWFTljU= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 h1:BCHu4pNP6arrcHLEWx61XjLaonOd2coQNyL0NTUcaMc= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827/go.mod h1:OPX+wC2TWQsyLNpR7daMt2vMpmsNcoBxbZyGTHr6tiA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 h1:8ZzsGNhqYxmQ/QMO1fuXO7u9Vpl9YUvPJK+td/ZaBJA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564/go.mod h1:Ml88TJTwZCj6yHDkAEN/EhxVutzSlk+kDZgfibRIqF0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= -github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+30iWKL/sWq8uyiLHM8k= +github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chainlink-automation v0.8.0 h1:hFz2EHU06bkEfhcqhK8JdjKTWpDOr0XJ6xL9oELDoUg= +github.com/smartcontractkit/chainlink-automation v0.8.0/go.mod h1:ObdjDfgGIaiE48Bb3yYcx1CeGBm392WlEw92U83LlUA= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 h1:BS9i2P/b+PsomEP//bH4j6N2a1DCgLVVzoRw02CnN2s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 h1:qx5p01fqee86cj6EUOCzFc2zILw56v1Q3c5DUuEQWLs= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286/go.mod h1:tsGgeEJc5SUSlfVGSX0wR0EkRU3pM58D6SKF97V68ko= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= +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/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 h1:R8F2tpyvN0peK0woG/Spx+IdukxlSSWDDLyFQNkLfUs= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042/go.mod h1:UndTf1YRDBt/4LDauMFou9+vt/M0q6o7u80a9J5Xu+0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +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/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.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= 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/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= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 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.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +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= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +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= @@ -1204,6 +1120,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1214,19 +1131,16 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.2/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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= 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= @@ -1244,8 +1158,9 @@ github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vl 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 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= 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= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -1257,10 +1172,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2 github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= @@ -1278,14 +1191,10 @@ 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.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= 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/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= 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= @@ -1293,31 +1202,23 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY 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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= 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-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= 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= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -1329,8 +1230,8 @@ go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= 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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= 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= @@ -1351,18 +1252,34 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIX go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 h1:UiRNKd1OgqsLbFwE+wkAWTdiAxXtCBqKIHeBIse4FUA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9/go.mod h1:eqZlW3pJWhjyexnDPrdQxix1pn0wwhI4AO4GKpP/bMI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 h1:0MH3f8lZrflbUWXVxyBg/zviDFdGE062uKh5+fu8Vv0= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0/go.mod h1:Vh68vYiHY5mPdekTr0ox0sALsqjoVy0w3Os278yX5SQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 h1:BJee2iLkfRfl9lc7aFmBwkWxY/RI1RDdXepSF6y8TPE= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0/go.mod h1:DIzlHs3DRscCIBU3Y9YSzPfScwnYnzfnCd4g8zA7bZc= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o= +go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA= +go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= +go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -1393,7 +1310,6 @@ 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.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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= @@ -1407,27 +1323,22 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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-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.0.0-20220722155217-630584e8d5aa/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.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1438,8 +1349,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-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= 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= @@ -1453,7 +1364,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1462,13 +1372,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= @@ -1479,44 +1387,30 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r 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= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -1524,19 +1418,15 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug 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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1544,14 +1434,12 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1589,46 +1477,32 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1636,8 +1510,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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= @@ -1646,8 +1520,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1661,22 +1535,19 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1709,33 +1580,16 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= +golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= 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= @@ -1743,6 +1597,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1755,16 +1611,8 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1773,9 +1621,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 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= -google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1795,37 +1640,18 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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= @@ -1838,15 +1664,9 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1857,13 +1677,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1881,10 +1700,8 @@ gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.51.1/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/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 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= @@ -1900,24 +1717,22 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= -k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= @@ -1935,8 +1750,8 @@ modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +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= diff --git a/integration-tests/.golangci.yml b/integration-tests/.golangci.yml index 897c72d1ecb..304249d24cc 100644 --- a/integration-tests/.golangci.yml +++ b/integration-tests/.golangci.yml @@ -46,7 +46,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 @@ -70,6 +70,9 @@ linters-settings: - name: atomic issues: exclude-rules: + - path: deployment/memory/(.+)\.go + linters: + - revive - text: "^G404: Use of weak random number generator" linters: - gosec diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions index d623afb2832..300f1c89fcb 100644 --- a/integration-tests/.tool-versions +++ b/integration-tests/.tool-versions @@ -1,5 +1,6 @@ -golang 1.22.5 +golang 1.22.8 k3d 5.4.6 kubectl 1.25.5 nodejs 20.13.1 golangci-lint 1.59.1 +task 3.35.1 diff --git a/integration-tests/Makefile b/integration-tests/Makefile index 1e6828fd35c..e28b133e1f5 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -102,20 +102,20 @@ test_smoke_product: ## Run smoke tests for specific product ex: make test_smoke_ # Chaos .PHONY: test_chaos_pods_raw -test_chaos_pods_raw: +test_chaos_pods_raw: ## Run all chaos pod tests go test -timeout 2h -v -count=1 $(args) -p 2 -run 'Test/.*pod-chaos' ./chaos .PHONY: test_chaos_network_raw -test_chaos_network_raw: +test_chaos_network_raw: ## Run all chaos network tests go test -timeout 2h -v -count=1 $(args) -p 2 -run 'Test/.*network-chaos' ./chaos .PHONY: test_chaos_pods -test_chaos_pods: install_gotestloghelper ## Run all chaos pod tests +test_chaos_pods: install_gotestloghelper ## Run all chaos pod tests with decorated output TEST_LOG_LEVEL="disabled" \ go test -timeout 2h -count=1 -json $(args) -run 'Test/.*pod-chaos' ./chaos 2>&1 | tee ./gotest.log | gotestloghelper -json -hidepassingtests -tlogprefix -color -singlepackage .PHONY: test_chaos_network -test_chaos_network: install_gotestloghelper ## Run all chaos network tests +test_chaos_network: install_gotestloghelper ## Run all chaos network tests with decorated output TEST_LOG_LEVEL="disabled" \ go test -timeout 2h -count=1 -json $(args) -run 'Test/.*network-chaos' ./chaos 2>&1 | tee ./gotest.log | gotestloghelper -json -hidepassingtests -tlogprefix -color -singlepackage @@ -123,6 +123,14 @@ test_chaos_network: install_gotestloghelper ## Run all chaos network tests test_chaos_verbose: ## Run all smoke tests with verbose logging go test -timeout 24h -count=1 -v $(args) ./chaos +.PHONY: test_chaos_ocr +test_chaos_ocr: ## Run only OCR chaos tests + go test -timeout 2h -v -count=1 $(args) -p 2 -run 'TestOCRChaos' ./chaos + +.PHONY: test_chaos_automation +test_chaos_automation: ## Run only Automation chaos tests + go test -timeout 2h -v -count=1 $(args) -p 2 -run 'TestAutomationChaos' ./chaos + # Migrations .PHONY: test_node_migrations test_node_migrations: install_gotestloghelper ## Run all node migration tests. diff --git a/integration-tests/README.md b/integration-tests/README.md index 1510c8c91b7..97e890789a1 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -1,137 +1,162 @@ # Integration Tests -Here lives the integration tests for chainlink, utilizing our [chainlink-testing-framework](https://github.com/smartcontractkit/chainlink-testing-framework). +- [Integration Tests](#integration-tests) + - [Summary](#summary) + - [Guidelines](#guidelines) + - [Pre-requisites](#pre-requisites) + - [Test and node configuration](#test-and-node-configuration) + - [Run Tests](#run-tests) + - [Locally (in Docker)](#locally-in-docker) + - [All tests in a suite](#all-tests-in-a-suite) + - [A single test](#a-single-test) + - [In Kubernetes](#in-kubernetes) + - [From local machine](#from-local-machine) + - [CI/GitHub Actions](#cigithub-actions) -## NOTE: Move to Testcontainers +## Summary -If you have previously run these smoke tests using GitHub Actions or some sort of Kubernetes setup, that method is no longer necessary. We have moved the majority of our tests to utilize plain Docker containers (with the help of [Testcontainers](https://golang.testcontainers.org/)). This should make tests faster, more stable, and enable you to run them on your local machine without much hassle. +This directory represent a place for different types of integration and system level tests. It utilizes [Chainlink Testing Framework (CTF)](https://github.com/smartcontractkit/chainlink-testing-framework). -## Requirements +> [!TIP] +> **Testcontainers (Dockerized tests)** +> If you want to have faster, locally running, more stable tests, utilize plain Docker containers (with the help of [Testcontainers](https://golang.testcontainers.org/)) instead of using GitHub Actions or Kubernetes. -1. [Go](https://go.dev/) -2. [Docker](https://www.docker.com/) -3. You'll probably want to [increase the resources available to Docker](https://stackoverflow.com/questions/44533319/how-to-assign-more-memory-to-docker-container) as most tests require quite a few containers (e.g. OCR requires 6 Chainlink nodes, 6 databases, a simulated blockchain, and a mock server). +## Guidelines -## Configure +### Pre-requisites -We have finished the first pass at moving all test configuration from env vars to TOML files. All product-related configuration is already in TOML files, but env vars are still used to control the log level, Slack notifications, and Kubernetes-related settings. See the [example.env](./example.env) file for how to set these environment variables. +1. [Installed Go](https://go.dev/) +2. For local testing, [Installed Docker](https://www.docker.com/). Consider [increasing resources limits needed by Docker](https://stackoverflow.com/questions/44533319/how-to-assign-more-memory-to-docker-container) as most tests require building several containers for a Decentralized Oracle Network (e.g. OCR requires 6 nodes, 6 DBs, and a mock server). +3. For remote testing, access to Kubernetes cluster/AWS Docker registry (if you are pulling images from private links). +4. Docker image. If there is no image to pull from a registry, you may run tests against a custom build. Run the following command to build the image: -We have defined some sensible defaults for all products, you can find them in `./testconfig//.toml` files. Each product folder contains an `example.toml` file that describes all options. If you wish to override these values, you can do so by creating a `./testconfig/overrides.toml`. A detailed description of TOML configuration can be found in the [testconfig README](./testconfig/README.md), but if you want to run some tests using default values all you need to do is provide the Chainlink image and version you want to run tests on: -```toml -# ./testconfig/overrides.toml - -[ChainlinkImage] -image = "your image name" -version = "your tag" -``` - -The `./testconfig/overrides.toml` file **should never be committed** and has been added to the [.gitignore](../.gitignore) file as it can often contain secrets like private keys and RPC URLs. - -For more information on how to configure the tests, see the [testconfig README](./testconfig/README.md). - -## Build - -If you'd like to run the tests on a local build of Chainlink, you can point to your own docker image, or build a fresh one with `make`. - -`make build_docker_image image= tag=` + ```bash + make build_docker_image image= tag= + ``` -e.g. + Example: `make build_docker_image image=chainlink tag=test-tag` -`make build_docker_image image=chainlink tag=test-tag` +5. RPC node/s (for testnets/mainnets). +6. EOA's (wallet) Private Key (see [How to export an account's private key](https://support.metamask.io/ru/managing-my-wallet/secret-recovery-phrase-and-private-keys/how-to-export-an-accounts-private-key/)) +7. Sufficient amount of native token and LINK on EOA per a target chain. -## Run +#### Test and node configuration -Ensure you have created a `./testconfig/overrides.toml` file with your desired Chainlink image and version. +1. Setup `.env` file in the root of `integration-tests` directory. See [example.env](./example.env) for how to set test-runner log level (not a node's log level), Slack notifications, and Kubernetes-related settings. -`go test ./smoke/_test.go` + 1. Ensure to **update you environment** with the following commands: + 1. `cd integration-tests` + 2. `source .env` -Most test files have a couple of tests, it's recommended to look into the file and focus on a specific one if possible. 90% of the time this will probably be the `Basic` test. See [ocr_test.go](./smoke/ocr_test.go) for example, which contains the `TestOCRBasic` test. +2. Setup test secrets. See "how-to" details in the [Test Secrets in CTF](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md#test-secrets). If you want to run tests in CI, you will have to push test secrets to GitHub (see [Run GitHub Workflow with your test secrets](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md#run-github-workflow-with-your-test-secrets)). -`go test ./smoke/ocr_test.go -run TestOCRBasic` +3. Provide test and node configuration (for more details refer to [testconfig README](./testconfig/README.md) and `example.toml` files): + 1. **Defaults** for all products are defined in `./testconfig//.toml` files. + 2. To **override default values**, create a `./testconfig/overrides.toml` file (yes, in the root of `testconfig`, not a product directory) specifying the values to override by your test (see some examples in [./testconfig/ocr2/overrides](./testconfig/ocr2/overrides)). -It's generally recommended to run only one test at a time on a local machine as it needs a lot of docker containers and can peg your resources otherwise. You will see docker containers spin up on your machine for each component of the test where you can inspect logs. + > [!IMPORTANT] + > **Image version and node configs** + > 1. Pay attention to the `[ChainlinkImage].version` to test against the necessary remotely accessible version or [custom build](#pre-requisites). + > 2. When running OCR-related tests, pay attention to which version of OCR you enable/override in your `overrides.toml`. + > 3. Do not commit any sensitive data. -### Configure Seth +4. [Optional] Configure Seth (or use defaults), an evm client used by tests. Detailed instructions on how to configure it can be found in the [Seth README](./README_SETH.md) and [Seth repository](https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/seth). -Our new evm client is Seth. Detailed instructions on how to configure it can be found in the [Seth README](./README_SETH.md) in this repo as well as in [Seth repository](https://github.com/smartcontractkit/seth). + > [!IMPORTANT] + > **Simulated mode (no test secrets needed)** + > Tests may run in a simulated mode, on a simulated chain (1337). In the `overrides.toml` file, set the following: + > 1. `[Network].selected_networks=["simulated"]` + > 2. `[[Seth.networks]].name = "Default"` -## Analyze +### Run Tests -You can see the results of each test in the terminal with normal `go test` output. If a test fails, logs of each Chainlink container will dump into the `smoke/logs/` folder for later analysis. You can also see these logs in CI uploaded as GitHub artifacts. +#### Locally (in Docker) -## Running Soak, Performance, Benchmark, and Chaos Tests +> [!NOTE] +> **Resources utilization by Docker** +> It's recommended to run only one test at a time (run tests sequentially) on a local machine as it needs a lot of docker containers and can peg your resources otherwise. You will see docker containers spin up on your machine for each component of the test where you can inspect logs. -These tests remain bound to a Kubernetes run environment, and require more complex setup and running instructions not documented here. We endeavor to make these easier to run and configure, but for the time being please seek a member of the QA/Test Tooling team if you want to run these. +##### All tests in a suite -### How to run reorg tests -Run soak/ocr_test.go with reorg below finality and `FinalityTagEnabled=false` +1. Run CLI command(with `override.toml`): -```bash -make test_soak_ocr_reorg_1 -``` + ```bash + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -p 1 ./smoke/_test.go + ``` -Run soak/ocr_test.go with reorg below finality and `FinalityTagEnabled=true`: + Example: -```bash -make test_soak_ocr_reorg_2 -``` + ```bash + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -p 1 ./smoke/ocr_test.go + ``` -Run reorg/automation_reorg_test.go with reorg settings: + > [!WARNING] + > **Parallelized tests and nonce issues** + > Most tests are paralelized by default. To avoid nonce-related issues, it is recommended to run tests with disabled parallelization, e.g. with `-p 1`. -1. Use Simulated Geth network and put GethReorgConfig in overrides.toml +2. Alternatively, you may use `make` commands (see more in [Makefile .PHONY lines](./Makefile)) for running suites of tests. + Example: - ```toml - [Network] - selected_networks=["simulated"] - [Network.GethReorgConfig] - enabled = true - depth = 10 - delay_create = "3s" + ```bash + make test_smoke_product product="ocr" ./scripts/run_product_tests ``` -2. Then run the test: +3. Logs of each Chainlink container will dump into the `smoke/logs/`. +4. To enable debugging of HTTP and RPC clients set the following env vars: + ```bash - make test_reorg_automation + export SETH_LOG_LEVEL=debug + export RESTY_DEBUG=true ``` -Run reorg above finality docker test: +##### A single test + +Run CLI command (with `override.toml`): ```bash -go test -v -run ^TestReorgAboveFinality_FinalityTagDisabled$ ./smoke +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -timeout 15m -run <"TestNameToRun"> ./ ``` -### How to run gas simulation tests - -Run soak/ocr_test.go with gas spike: +Example: ```bash -make test_soak_ocr_gas_spike +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -timeout 15m -run "TestOCRv2Basic" ./smoke ``` -Run soak/ocr_test.go with changing gas limit creating block congestion: +#### In Kubernetes -```bash -make test_soak_ocr_gas_limit_change -``` +Such tests as Soak, Performance, Benchmark, and Chaos Tests remain bound to a Kubernetes run environment. -Note: you can update gas simulation params for the tests below in in testconfig/ocr.toml +1. Refer [Tests Run Books](./run-books/) to get more details on how to run specific per-product tests. +2. Logs in CI are uploaded as GitHub artifacts. -### How to run tests with RPC node failure +##### From local machine -Run soak/ocr_test.go with RPC network chaos by bringing down network to RPC node for all Chainlink Nodes: +1. Ensure all necessary configurations are provided (see [Test and node configuration](#test-and-node-configuration)). +2. Log in to your Kubernetes cluster (with `aws sso login`) +3. Run tests with the following CLI command: -```bash -make test_soak_ocr_rpc_down_all_cl_nodes -``` + ```bash + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -timeout -p 1 -run '' ./ + ``` -Run soak/ocr_test.go with RPC network chaos by bringing down network to RPC node for 50 percent of Chainlink Nodes: + OR with `make` commands: -```bash -make test_soak_ocr_rpc_down_half_cl_nodes -``` + ```bash + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) make test_ + ``` -### Debugging HTTP and RPC clients -```bash -export SETH_LOG_LEVEL=debug -export RESTY_DEBUG=true -``` + Example (see make-commands in [Makefile .PHONY lines](./Makefile)): + + ```bash + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) make test_chaos_ocr/make test_soak_ocr2/test_node_migrations + ``` + +4. Use Kubernetes namespace printed out in logs to monitor and analyze test runs. +5. Navigate to Grafana dashboards to for test results and logs. + +#### CI/GitHub Actions + +1. Ensure all necessary configurations are provided (see [Test and node configuration](#test-and-node-configuration)). +2. Follow instructions provided in [E2E Tests on GitHub CI](../.github/E2E_TESTS_ON_GITHUB_CI.md). +3. Refer [Tests Run Books](./run-books/) to get more details on how to run specific per-product tests. diff --git a/integration-tests/README_SETH.md b/integration-tests/README_SETH.md index 92302ab9ce7..26fbfc1a79f 100644 --- a/integration-tests/README_SETH.md +++ b/integration-tests/README_SETH.md @@ -41,7 +41,7 @@ ## Introduction -[Seth](https://github.com/smartcontractkit/seth) is the Ethereum client we use for integration tests. It is designed to be a thin wrapper over `go-ethereum` client that adds a couple of key features: +[Seth](https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/seth) is the Ethereum client we use for integration tests. It is designed to be a thin wrapper over `go-ethereum` client that adds a couple of key features: * key management * transaction decoding and tracing * gas estimation @@ -65,7 +65,7 @@ tracing_level = "all" # trace all transactions regardless of whether they are re ``` ### Documentation and Further Details -For a comprehensive description of all available configuration options, refer to the `[Seth]` section of configuration documentation in the [default.toml](./testconfig/default.toml) file or consult the Seth [README.md on GitHub](https://github.com/smartcontractkit/seth/blob/master/README.md). +For a comprehensive description of all available configuration options, refer to the `[Seth]` section of configuration documentation in the [default.toml](./testconfig/default.toml) file or consult the Seth [README.md on GitHub](https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/seth/blob/master/README.md). ## How to set Seth logging level ### Locally @@ -155,7 +155,7 @@ The most important thing to keep in mind that the CLI requires you to provide a * `keys` commands requires `SETH_KEYFILE_PATH`, `SETH_CONFIG_PATH` and `SETH_ROOT_PRIVATE_KEY` environment variables * `gas` and `stats` command requires `SETH_CONFIG_PATH` environment variable -You can find a sample `Seth.toml` file [here](https://github.com/smartcontractkit/seth/blob/master/seth.toml). Currently, you cannot use your test TOML file as a Seth configuration file, but we will add ability that in the future. +You can find a sample `Seth.toml` file [here](https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/seth/blob/master/seth.toml). Currently, you cannot use your test TOML file as a Seth configuration file, but we will add ability that in the future. ## How to get Fallback (Hardcoded) Values There are two primary methods to obtain fallback values for network configuration: @@ -166,7 +166,7 @@ There are two primary methods to obtain fallback values for network configuratio 1. **Clone the Seth Repository:** Clone the repository from GitHub using: ```bash -git clone https://github.com/smartcontractkit/seth +git clone https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/seth ``` 2. **Run Seth CLI:** diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 8487e3a264e..e395c9a251a 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -20,13 +20,15 @@ import ( "github.com/ethereum/go-ethereum/rpc" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" ethContracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/ethereum/go-ethereum/accounts/abi" @@ -37,16 +39,18 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/test-go/testify/require" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ocr" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" @@ -283,7 +287,7 @@ func fundChainlinkNodesAtAnyKey( return err } - fromAddress, err := privateKeyToAddress(privateKey) + fromAddress, err := PrivateKeyToAddress(privateKey) if err != nil { return err } @@ -334,7 +338,7 @@ type FundsToSendPayload struct { // to given address. You can override any or none of the following: gas limit, gas price, gas fee cap, gas tip cap. // Values that are not set will be estimated or taken from config. func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPayload) (*types.Receipt, error) { - fromAddress, err := privateKeyToAddress(payload.PrivateKey) + fromAddress, err := PrivateKeyToAddress(payload.PrivateKey) if err != nil { return nil, err } @@ -488,7 +492,8 @@ func DeployForwarderContracts( operatorFactoryInstance = &instance for i := 0; i < numberOfOperatorForwarderPairs; i++ { - decodedTx, err := seth.Decode(operatorFactoryInstance.DeployNewOperatorAndForwarder()) + tx, deployErr := operatorFactoryInstance.DeployNewOperatorAndForwarder() + decodedTx, err := seth.Decode(tx, deployErr) require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") for i, event := range decodedTx.Events { @@ -606,29 +611,48 @@ func TrackForwarder( Msg("Forwarder tracked") } -// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults -func DeployOCRv2Contracts( +// SetupOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults +func SetupOCRv2Contracts( l zerolog.Logger, seth *seth.Client, - numberOfContracts int, + ocrContractsConfig ocr.OffChainAggregatorsConfig, linkTokenAddress common.Address, transmitters []string, ocrOptions contracts.OffchainOptions, ) ([]contracts.OffchainAggregatorV2, error) { var ocrInstances []contracts.OffchainAggregatorV2 - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contracts.DeployOffchainAggregatorV2( - l, - seth, - linkTokenAddress, - ocrOptions, - ) - if err != nil { - return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) + + if ocrContractsConfig == nil { + return nil, fmt.Errorf("you need to pass non-nil OffChainAggregatorsConfig to setup OCR contracts") + } + + if !ocrContractsConfig.UseExistingOffChainAggregatorsContracts() { + for contractCount := 0; contractCount < ocrContractsConfig.NumberOfContractsToDeploy(); contractCount++ { + ocrInstance, err := contracts.DeployOffchainAggregatorV2( + l, + seth, + linkTokenAddress, + ocrOptions, + ) + if err != nil { + return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } } - ocrInstances = append(ocrInstances, &ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) + } else { + for _, address := range ocrContractsConfig.OffChainAggregatorsContractsAddresses() { + ocrInstance, err := contracts.LoadOffchainAggregatorV2(l, seth, address) + if err != nil { + return nil, fmt.Errorf("OCRv2 instance loading have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + } + + if !ocrContractsConfig.ConfigureExistingOffChainAggregatorsContracts() { + return ocrInstances, nil } } @@ -690,7 +714,7 @@ func TeardownSuite( l.Warn().Msgf("Error deleting jobs %+v", err) } - if chainlinkNodes != nil { + if chainlinkNodes != nil && chainClient != nil { if err := ReturnFundsFromNodes(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { // This printed line is required for tests that use real funds to propagate the failure // out to the system running the test. Do not remove @@ -777,7 +801,7 @@ func StartNewRound( func DeployOCRContractsForwarderFlow( logger zerolog.Logger, seth *seth.Client, - numberOfContracts int, + ocrContractsConfig ocr.OffChainAggregatorsConfig, linkTokenContractAddress common.Address, workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, forwarderAddresses []common.Address, @@ -798,23 +822,23 @@ func DeployOCRContractsForwarderFlow( return forwarderAddresses, nil } - return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) + return setupAnyOCRv1Contracts(logger, seth, ocrContractsConfig, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) } -// DeployOCRv1Contracts deploys and funds a certain number of offchain aggregator contracts -func DeployOCRv1Contracts( +// SetupOCRv1Contracts deploys and funds a certain number of offchain aggregator contracts or uses existing ones and returns a slice of contract wrappers. +func SetupOCRv1Contracts( logger zerolog.Logger, seth *seth.Client, - numberOfContracts int, + ocrContractsConfig ocr.OffChainAggregatorsConfig, linkTokenContractAddress common.Address, workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, ) ([]contracts.OffchainAggregator, error) { transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { transmitters = make([]string, 0) payees = make([]string, 0) - for _, node := range workerNodes { + for _, n := range workerNodes { var addr string - addr, err = node.PrimaryEthAddress() + addr, err = n.PrimaryEthAddress() if err != nil { err = fmt.Errorf("error getting node's primary ETH address: %w", err) return @@ -828,8 +852,8 @@ func DeployOCRv1Contracts( transmitterAddressesFn := func() ([]common.Address, error) { transmitterAddresses := make([]common.Address, 0) - for _, node := range workerNodes { - primaryAddress, err := node.PrimaryEthAddress() + for _, n := range workerNodes { + primaryAddress, err := n.PrimaryEthAddress() if err != nil { return nil, err } @@ -839,28 +863,48 @@ func DeployOCRv1Contracts( return transmitterAddresses, nil } - return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) + return setupAnyOCRv1Contracts(logger, seth, ocrContractsConfig, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) } -func deployAnyOCRv1Contracts( +func setupAnyOCRv1Contracts( logger zerolog.Logger, seth *seth.Client, - numberOfContracts int, + ocrContractsConfig ocr.OffChainAggregatorsConfig, linkTokenContractAddress common.Address, workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, getTransmitterAndPayeesFn func() ([]string, []string, error), getTransmitterAddressesFn func() ([]common.Address, error), ) ([]contracts.OffchainAggregator, error) { - // Deploy contracts var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contracts.DeployOffchainAggregator(logger, seth, linkTokenContractAddress, contracts.DefaultOffChainAggregatorOptions()) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) + + if ocrContractsConfig == nil { + return nil, fmt.Errorf("you need to pass non-nil OffChainAggregatorsConfig to setup OCR contracts") + } + + if !ocrContractsConfig.UseExistingOffChainAggregatorsContracts() { + // Deploy contracts + for contractCount := 0; contractCount < ocrContractsConfig.NumberOfContractsToDeploy(); contractCount++ { + ocrInstance, err := contracts.DeployOffchainAggregator(logger, seth, linkTokenContractAddress, contracts.DefaultOffChainAggregatorOptions()) + if err != nil { + return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } } - ocrInstances = append(ocrInstances, &ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) + } else { + // Load contract wrappers + for _, address := range ocrContractsConfig.OffChainAggregatorsContractsAddresses() { + ocrInstance, err := contracts.LoadOffChainAggregator(logger, seth, address) + if err != nil { + return nil, fmt.Errorf("OCR instance loading have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + } + + if !ocrContractsConfig.ConfigureExistingOffChainAggregatorsContracts() { + return ocrInstances, nil } } @@ -907,7 +951,7 @@ func deployAnyOCRv1Contracts( return ocrInstances, nil } -func privateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) { +func PrivateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) { publicKey := privateKey.Public() publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) if !ok { @@ -1024,18 +1068,42 @@ func SendLinkFundsToDeploymentAddresses( toTransferToMultiCallContract := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(totalUpkeeps+concurrency))) toTransferPerClient := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(operationsPerAddress+1))) - err := linkToken.Transfer(multicallAddress.Hex(), toTransferToMultiCallContract) + + // As a hack we use the geth wrapper directly, because we need to access receipt to get block number, which we will use to query the balance + // This is needed as querying with 'latest' block number very rarely, but still, return stale balance. That's happening even though we wait for + // the transaction to be mined. + linkInstance, err := link_token_interface.NewLinkToken(common.HexToAddress(linkToken.Address()), wrappers.MustNewWrappedContractBackend(nil, chainClient)) + if err != nil { + return err + } + + tx, err := chainClient.Decode(linkInstance.Transfer(chainClient.NewTXOpts(), multicallAddress, toTransferToMultiCallContract)) if err != nil { - return errors.Wrapf(err, "Error transferring LINK to multicall contract") + return err + } + + if tx.Receipt == nil { + return fmt.Errorf("transaction receipt for LINK transfer to multicall contract is nil") } - balance, err := linkToken.BalanceOf(context.Background(), multicallAddress.Hex()) + multiBalance, err := linkInstance.BalanceOf(&bind.CallOpts{From: chainClient.Addresses[0], BlockNumber: tx.Receipt.BlockNumber}, multicallAddress) if err != nil { return errors.Wrapf(err, "Error getting LINK balance of multicall contract") } - if balance.Cmp(toTransferToMultiCallContract) < 0 { - return fmt.Errorf("Incorrect LINK balance of multicall contract. Expected at least: %s. Got: %s", toTransferToMultiCallContract.String(), balance.String()) + // Old code that's querying latest block + //err := linkToken.Transfer(multicallAddress.Hex(), toTransferToMultiCallContract) + //if err != nil { + // return errors.Wrapf(err, "Error transferring LINK to multicall contract") + //} + // + //balance, err := linkToken.BalanceOf(context.Background(), multicallAddress.Hex()) + //if err != nil { + // return errors.Wrapf(err, "Error getting LINK balance of multicall contract") + //} + + if multiBalance.Cmp(toTransferToMultiCallContract) < 0 { + return fmt.Errorf("Incorrect LINK balance of multicall contract. Expected at least: %s. Got: %s", toTransferToMultiCallContract.String(), multiBalance.String()) } // Transfer LINK to ephemeral keys @@ -1060,18 +1128,24 @@ func SendLinkFundsToDeploymentAddresses( } boundContract := bind.NewBoundContract(multicallAddress, multiCallABI, chainClient.Client, chainClient.Client, chainClient.Client) // call aggregate3 to group all msg call data and send them in a single transaction - _, err = chainClient.Decode(boundContract.Transact(chainClient.NewTXOpts(), "aggregate3", call)) + ephemeralTx, err := chainClient.Decode(boundContract.Transact(chainClient.NewTXOpts(), "aggregate3", call)) if err != nil { return errors.Wrapf(err, "Error calling Multicall contract") } + if ephemeralTx.Receipt == nil { + return fmt.Errorf("transaction receipt for LINK transfer to ephemeral keys is nil") + } + for i := 1; i <= concurrency; i++ { - balance, err := linkToken.BalanceOf(context.Background(), chainClient.Addresses[i].Hex()) + ephemeralBalance, err := linkInstance.BalanceOf(&bind.CallOpts{From: chainClient.Addresses[0], BlockNumber: ephemeralTx.Receipt.BlockNumber}, chainClient.Addresses[i]) + // Old code that's querying latest block, for now we prefer to use block number from the transaction receipt + //balance, err := linkToken.BalanceOf(context.Background(), chainClient.Addresses[i].Hex()) if err != nil { return errors.Wrapf(err, "Error getting LINK balance of ephemeral key %d", i) } - if balance.Cmp(toTransferPerClient) < 0 { - return fmt.Errorf("Incorrect LINK balance after transfer. Ephemeral key %d. Expected: %s. Got: %s", i, toTransferPerClient.String(), balance.String()) + if ephemeralBalance.Cmp(toTransferPerClient) < 0 { + return fmt.Errorf("Incorrect LINK balance after transfer. Ephemeral key %d. Expected: %s. Got: %s", i, toTransferPerClient.String(), ephemeralBalance.String()) } } @@ -1212,6 +1286,11 @@ func IsOPStackChain(chainID int64) bool { chainID == 11155420 //OPTIMISM SEPOLIA } +func IsArbitrumChain(chainID int64) bool { + return chainID == 42161 || //Arbitrum MAINNET + chainID == 421614 //Arbitrum Sepolia +} + func RandBool() bool { return rand.Intn(2) == 1 } @@ -1248,3 +1327,12 @@ func ContinuouslyGenerateTXsOnChain(sethClient *seth.Client, stopChannel chan bo } } } + +func WithinTolerance(a, b, tolerance float64) (bool, float64) { + if a == b { + return true, 0 + } + diff := math.Abs(a - b) + isWithinTolerance := diff < tolerance + return isWithinTolerance, diff +} diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index 3e552371f98..fb2fddb3515 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -2,296 +2,24 @@ package actions //revive:disable:dot-imports import ( - "encoding/json" - "fmt" "math" "math/big" "testing" - "time" - "github.com/pkg/errors" - "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + tt "github.com/smartcontractkit/chainlink/integration-tests/types" - "github.com/ethereum/go-ethereum/common" - "github.com/lib/pq" - "github.com/stretchr/testify/require" - "gopkg.in/guregu/null.v4" + "github.com/pkg/errors" - ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-testing-framework/seth" - ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" - ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/store/models" ) -func BuildAutoOCR2ConfigVars( - t *testing.T, - chainlinkNodes []*client.ChainlinkK8sClient, - registryConfig contracts.KeeperRegistrySettings, - registrar string, - deltaStage time.Duration, - chainModuleAddress common.Address, - reorgProtectionEnabled bool, - linkToken contracts.LinkToken, - wethToken contracts.WETHToken, - ethUSDFeed contracts.MockETHUSDFeed, - -) (contracts.OCRv2Config, error) { - return BuildAutoOCR2ConfigVarsWithKeyIndex(t, chainlinkNodes, registryConfig, registrar, deltaStage, 0, common.Address{}, chainModuleAddress, reorgProtectionEnabled, linkToken, wethToken, ethUSDFeed) -} - -func BuildAutoOCR2ConfigVarsWithKeyIndex( - t *testing.T, - chainlinkNodes []*client.ChainlinkK8sClient, - registryConfig contracts.KeeperRegistrySettings, - registrar string, - deltaStage time.Duration, - keyIndex int, - registryOwnerAddress common.Address, - chainModuleAddress common.Address, - reorgProtectionEnabled bool, - linkToken contracts.LinkToken, - wethToken contracts.WETHToken, - ethUSDFeed contracts.MockETHUSDFeed, -) (contracts.OCRv2Config, error) { - l := logging.GetTestLogger(t) - S, oracleIdentities, err := GetOracleIdentitiesWithKeyIndex(chainlinkNodes, keyIndex) - if err != nil { - return contracts.OCRv2Config{}, err - } - - var offC []byte - var signerOnchainPublicKeys []types.OnchainPublicKey - var transmitterAccounts []types.Account - var f uint8 - var offchainConfigVersion uint64 - var offchainConfig []byte - - if registryConfig.RegistryVersion == ethereum.RegistryVersion_2_1 || registryConfig.RegistryVersion == ethereum.RegistryVersion_2_2 || registryConfig.RegistryVersion == ethereum.RegistryVersion_2_3 { - offC, err = json.Marshal(ocr2keepers30config.OffchainConfig{ - TargetProbability: "0.999", - TargetInRounds: 1, - PerformLockoutWindow: 3600000, // Intentionally set to be higher than in prod for testing purpose - GasLimitPerReport: 5_300_000, - GasOverheadPerUpkeep: 300_000, - MinConfirmations: 0, - MaxUpkeepBatchSize: 10, - }) - if err != nil { - return contracts.OCRv2Config{}, err - } - - signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err = ocr3.ContractSetConfigArgsForTests( - 10*time.Second, // deltaProgress time.Duration, - 15*time.Second, // deltaResend time.Duration, - 500*time.Millisecond, // deltaInitial time.Duration, - 1000*time.Millisecond, // deltaRound time.Duration, - 200*time.Millisecond, // deltaGrace time.Duration, - 300*time.Millisecond, // deltaCertifiedCommitRequest time.Duration - deltaStage, // deltaStage time.Duration, - 24, // rMax uint64, - S, // s []int, - oracleIdentities, // oracles []OracleIdentityExtra, - offC, // reportingPluginConfig []byte, - 20*time.Millisecond, // maxDurationQuery time.Duration, - 20*time.Millisecond, // maxDurationObservation time.Duration, // good to here - 1200*time.Millisecond, // maxDurationShouldAcceptAttestedReport time.Duration, - 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration, - 1, // f int, - nil, // onchainConfig []byte, - ) - if err != nil { - return contracts.OCRv2Config{}, err - } - } else { - offC, err = json.Marshal(ocr2keepers20config.OffchainConfig{ - TargetProbability: "0.999", - TargetInRounds: 1, - PerformLockoutWindow: 3600000, // Intentionally set to be higher than in prod for testing purpose - GasLimitPerReport: 5_300_000, - GasOverheadPerUpkeep: 300_000, - SamplingJobDuration: 3000, - MinConfirmations: 0, - MaxUpkeepBatchSize: 1, - }) - if err != nil { - return contracts.OCRv2Config{}, err - } - - signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err = ocr2.ContractSetConfigArgsForTests( - 10*time.Second, // deltaProgress time.Duration, - 15*time.Second, // deltaResend time.Duration, - 3000*time.Millisecond, // deltaRound time.Duration, - 200*time.Millisecond, // deltaGrace time.Duration, - deltaStage, // deltaStage time.Duration, - 24, // rMax uint8, - S, // s []int, - oracleIdentities, // oracles []OracleIdentityExtra, - offC, // reportingPluginConfig []byte, - 20*time.Millisecond, // maxDurationQuery time.Duration, - 20*time.Millisecond, // maxDurationObservation time.Duration, - 1200*time.Millisecond, // maxDurationReport time.Duration, - 20*time.Millisecond, // maxDurationShouldAcceptFinalizedReport time.Duration, - 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration, - 1, // f int, - nil, // onchainConfig []byte, - ) - if err != nil { - return contracts.OCRv2Config{}, err - } - } - - var signers []common.Address - for _, signer := range signerOnchainPublicKeys { - require.Equal(t, 20, len(signer), "OnChainPublicKey '%v' has wrong length for address", signer) - signers = append(signers, common.BytesToAddress(signer)) - } - - var transmitters []common.Address - for _, transmitter := range transmitterAccounts { - require.True(t, common.IsHexAddress(string(transmitter)), "TransmitAccount '%s' is not a valid Ethereum address", string(transmitter)) - transmitters = append(transmitters, common.HexToAddress(string(transmitter))) - } - - ocrConfig := contracts.OCRv2Config{ - Signers: signers, - Transmitters: transmitters, - F: f, - OffchainConfigVersion: offchainConfigVersion, - OffchainConfig: offchainConfig, - } - - if registryConfig.RegistryVersion == ethereum.RegistryVersion_2_0 { - ocrConfig.OnchainConfig = registryConfig.Encode20OnchainConfig(registrar) - } else if registryConfig.RegistryVersion == ethereum.RegistryVersion_2_1 { - ocrConfig.TypedOnchainConfig21 = registryConfig.Create21OnchainConfig(registrar, registryOwnerAddress) - } else if registryConfig.RegistryVersion == ethereum.RegistryVersion_2_2 { - ocrConfig.TypedOnchainConfig22 = registryConfig.Create22OnchainConfig(registrar, registryOwnerAddress, chainModuleAddress, reorgProtectionEnabled) - } else if registryConfig.RegistryVersion == ethereum.RegistryVersion_2_3 { - ocrConfig.TypedOnchainConfig23 = registryConfig.Create23OnchainConfig(registrar, registryOwnerAddress, chainModuleAddress, reorgProtectionEnabled) - ocrConfig.BillingTokens = []common.Address{ - common.HexToAddress(linkToken.Address()), - common.HexToAddress(wethToken.Address()), - } - - ocrConfig.BillingConfigs = []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig{ - { - GasFeePPB: 100, - FlatFeeMilliCents: big.NewInt(500), - PriceFeed: common.HexToAddress(ethUSDFeed.Address()), // ETH/USD feed and LINK/USD feed are the same - Decimals: 18, - FallbackPrice: big.NewInt(1000), - MinSpend: big.NewInt(200), - }, - { - GasFeePPB: 100, - FlatFeeMilliCents: big.NewInt(500), - PriceFeed: common.HexToAddress(ethUSDFeed.Address()), // ETH/USD feed and LINK/USD feed are the same - Decimals: 18, - FallbackPrice: big.NewInt(1000), - MinSpend: big.NewInt(200), - }, - } - } - - l.Info().Msg("Done building OCR config") - return ocrConfig, nil -} - -// CreateOCRKeeperJobs bootstraps the first node and to the other nodes sends ocr jobs -func CreateOCRKeeperJobs( - t *testing.T, - chainlinkNodes []*client.ChainlinkK8sClient, - registryAddr string, - chainID int64, - keyIndex int, - registryVersion ethereum.KeeperRegistryVersion, -) { - l := logging.GetTestLogger(t) - bootstrapNode := chainlinkNodes[0] - bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() - require.NoError(t, err, "Shouldn't fail reading P2P keys from bootstrap node") - bootstrapP2PId := bootstrapP2PIds.Data[0].Attributes.PeerID - - var contractVersion string - if registryVersion == ethereum.RegistryVersion_2_2 || registryVersion == ethereum.RegistryVersion_2_3 { - contractVersion = "v2.1+" - } else if registryVersion == ethereum.RegistryVersion_2_1 { - contractVersion = "v2.1" - } else if registryVersion == ethereum.RegistryVersion_2_0 { - contractVersion = "v2.0" - } else { - require.FailNow(t, fmt.Sprintf("v2.0, v2.1, v2.2 and v2.3 are the only supported versions, but got something else: %v (iota)", registryVersion)) - } - - bootstrapSpec := &client.OCR2TaskJobSpec{ - Name: "ocr2 bootstrap node " + registryAddr, - JobType: "bootstrap", - OCR2OracleSpec: job.OCR2OracleSpec{ - ContractID: registryAddr, - Relay: "evm", - RelayConfig: map[string]interface{}{ - "chainID": int(chainID), - }, - ContractConfigTrackerPollInterval: *models.NewInterval(time.Second * 15), - }, - } - _, err = bootstrapNode.MustCreateJob(bootstrapSpec) - require.NoError(t, err, "Shouldn't fail creating bootstrap job on bootstrap node") - // TODO: Use service name returned by chainlink-env once that is available - P2Pv2Bootstrapper := fmt.Sprintf("%s@%s-node-1:%d", bootstrapP2PId, bootstrapNode.Name(), 6690) - - for nodeIndex := 1; nodeIndex < len(chainlinkNodes); nodeIndex++ { - nodeTransmitterAddress, err := chainlinkNodes[nodeIndex].EthAddresses() - require.NoError(t, err, "Shouldn't fail getting primary ETH address from OCR node %d", nodeIndex+1) - nodeOCRKeys, err := chainlinkNodes[nodeIndex].MustReadOCR2Keys() - require.NoError(t, err, "Shouldn't fail getting OCR keys from OCR node %d", nodeIndex+1) - var nodeOCRKeyId []string - for _, key := range nodeOCRKeys.Data { - if key.Attributes.ChainType == string(chaintype.EVM) { - nodeOCRKeyId = append(nodeOCRKeyId, key.ID) - break - } - } - - autoOCR2JobSpec := client.OCR2TaskJobSpec{ - Name: "ocr2 " + registryAddr, - JobType: "offchainreporting2", - OCR2OracleSpec: job.OCR2OracleSpec{ - PluginType: "ocr2automation", - Relay: "evm", - RelayConfig: map[string]interface{}{ - "chainID": int(chainID), - }, - PluginConfig: map[string]interface{}{ - "mercuryCredentialName": "\"cred1\"", - "contractVersion": "\"" + contractVersion + "\"", - }, - ContractConfigTrackerPollInterval: *models.NewInterval(time.Second * 15), - ContractID: registryAddr, // registryAddr - OCRKeyBundleID: null.StringFrom(nodeOCRKeyId[0]), // get node ocr2config.ID - TransmitterID: null.StringFrom(nodeTransmitterAddress[keyIndex]), // node addr - P2PV2Bootstrappers: pq.StringArray{P2Pv2Bootstrapper}, // bootstrap node key and address @bootstrap:8000 - }, - } - - _, err = chainlinkNodes[nodeIndex].MustCreateJob(&autoOCR2JobSpec) - require.NoError(t, err, "Shouldn't fail creating OCR Task job on OCR node %d err: %+v", nodeIndex+1, err) - } - l.Info().Msg("Done creating OCR automation jobs") -} - // DeployAutoOCRRegistryAndRegistrar registry and registrar func DeployAutoOCRRegistryAndRegistrar( t *testing.T, @@ -308,9 +36,9 @@ func DeployAutoOCRRegistryAndRegistrar( return registry, registrar } -// DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means +// DeployLegacyConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means // that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. -func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken) ([]contracts.KeeperConsumer, []*big.Int) { +func DeployLegacyConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken) ([]contracts.KeeperConsumer, []*big.Int) { // Fund deployers with LINK, no need to do this for Native token if !isBillingTokenNative { err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) @@ -330,6 +58,28 @@ func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts. return upkeeps, upkeepIds } +// DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. +func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken, config tt.AutomationTestConfig) ([]contracts.KeeperConsumer, []*big.Int) { + // Fund deployers with LINK, no need to do this for Native token + if !isBillingTokenNative { + err := SetupMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, config) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + } + + upkeeps := SetupKeeperConsumers(t, chainClient, numberOfUpkeeps, isLogTrigger, isMercury, config) + require.Equal(t, numberOfUpkeeps, len(upkeeps), "Number of upkeeps should match") + var upkeepsAddresses []string + for _, upkeep := range upkeeps { + upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) + } + upkeepIds := RegisterUpkeepContracts( + t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, isBillingTokenNative, wethToken, + ) + require.Equal(t, numberOfUpkeeps, len(upkeepIds), "Number of upkeepIds should match") + return upkeeps, upkeepIds +} + // DeployPerformanceConsumers deploys and registers keeper performance consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkeep will be registered with root key address as the admin. // that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. func DeployPerformanceConsumers( @@ -345,12 +95,13 @@ func DeployPerformanceConsumers( blockInterval, // Interval of blocks that upkeeps are expected to be performed checkGasToBurn, // How much gas should be burned on checkUpkeep() calls performGasToBurn int64, // How much gas should be burned on performUpkeep() calls + config tt.AutomationTestConfig, ) ([]contracts.KeeperConsumerPerformance, []*big.Int) { upkeeps := DeployKeeperConsumersPerformance( t, chainClient, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, ) - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + err := SetupMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, config) require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") var upkeepsAddresses []string @@ -373,10 +124,11 @@ func DeployPerformDataCheckerConsumers( linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, expectedData []byte, + config tt.AutomationTestConfig, ) ([]contracts.KeeperPerformDataChecker, []*big.Int) { upkeeps := DeployPerformDataChecker(t, chainClient, numberOfUpkeeps, expectedData) - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + err := SetupMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, config) require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") var upkeepsAddresses []string @@ -387,6 +139,45 @@ func DeployPerformDataCheckerConsumers( return upkeeps, upkeepIds } +func SetupMultiCallAddress(chainClient *seth.Client, testConfig tt.AutomationTestConfig) (common.Address, error) { + if testConfig.GetAutomationConfig().UseExistingMultiCallContract() { + multiCallAddress, err := testConfig.GetAutomationConfig().MultiCallContractAddress() + if err != nil { + return common.Address{}, errors.Wrap(err, "Error getting existing multicall contract address") + } + return multiCallAddress, nil + } + + multicallAddress, err := contracts.DeployMultiCallContract(chainClient) + if err != nil { + return common.Address{}, errors.Wrap(err, "Error deploying multicall contract") + } + return multicallAddress, nil +} + +// SetupMultiCallAndFundDeploymentAddresses setups multicall contract and sends link funds to each deployment address +func SetupMultiCallAndFundDeploymentAddresses( + chainClient *seth.Client, + linkToken contracts.LinkToken, + numberOfUpkeeps int, + linkFundsForEachUpkeep *big.Int, + testConfig tt.AutomationTestConfig, +) error { + concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) + if err != nil { + return err + } + + operationsPerAddress := numberOfUpkeeps / concurrency + + multicallAddress, err := SetupMultiCallAddress(chainClient, testConfig) + if err != nil { + return errors.Wrap(err, "Error deploying multicall contract") + } + + return SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) +} + // DeployMultiCallAndFundDeploymentAddresses deploys multicall contract and sends link funds to each deployment address func DeployMultiCallAndFundDeploymentAddresses( chainClient *seth.Client, diff --git a/integration-tests/actions/automation_ocr_helpers_local.go b/integration-tests/actions/automation_ocr_helpers_local.go index d513f1875a4..72580b73885 100644 --- a/integration-tests/actions/automation_ocr_helpers_local.go +++ b/integration-tests/actions/automation_ocr_helpers_local.go @@ -28,7 +28,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/store/models" ) -func AutomationDefaultRegistryConfig(c tc.AutomationTestConfig) contracts.KeeperRegistrySettings { +func ReadRegistryConfig(c tc.AutomationTestConfig) contracts.KeeperRegistrySettings { registrySettings := c.GetAutomationConfig().AutomationConfig.RegistrySettings return contracts.KeeperRegistrySettings{ PaymentPremiumPPB: *registrySettings.PaymentPremiumPPB, @@ -40,12 +40,49 @@ func AutomationDefaultRegistryConfig(c tc.AutomationTestConfig) contracts.Keeper MaxPerformGas: *registrySettings.MaxPerformGas, FallbackGasPrice: registrySettings.FallbackGasPrice, FallbackLinkPrice: registrySettings.FallbackLinkPrice, + FallbackNativePrice: registrySettings.FallbackNativePrice, MaxCheckDataSize: *registrySettings.MaxCheckDataSize, MaxPerformDataSize: *registrySettings.MaxPerformDataSize, MaxRevertDataSize: *registrySettings.MaxRevertDataSize, } } +func ReadPluginConfig(c tc.AutomationTestConfig) ocr2keepers30config.OffchainConfig { + plCfg := c.GetAutomationConfig().AutomationConfig.PluginConfig + return ocr2keepers30config.OffchainConfig{ + TargetProbability: *plCfg.TargetProbability, + TargetInRounds: *plCfg.TargetInRounds, + PerformLockoutWindow: *plCfg.PerformLockoutWindow, + GasLimitPerReport: *plCfg.GasLimitPerReport, + GasOverheadPerUpkeep: *plCfg.GasOverheadPerUpkeep, + MinConfirmations: *plCfg.MinConfirmations, + MaxUpkeepBatchSize: *plCfg.MaxUpkeepBatchSize, + LogProviderConfig: ocr2keepers30config.LogProviderConfig{ + BlockRate: *plCfg.LogProviderConfig.BlockRate, + LogLimit: *plCfg.LogProviderConfig.LogLimit, + }, + } +} + +func ReadPublicConfig(c tc.AutomationTestConfig) ocr3.PublicConfig { + pubCfg := c.GetAutomationConfig().AutomationConfig.PublicConfig + return ocr3.PublicConfig{ + DeltaProgress: *pubCfg.DeltaProgress, + DeltaResend: *pubCfg.DeltaResend, + DeltaInitial: *pubCfg.DeltaInitial, + DeltaRound: *pubCfg.DeltaRound, + DeltaGrace: *pubCfg.DeltaGrace, + DeltaCertifiedCommitRequest: *pubCfg.DeltaCertifiedCommitRequest, + DeltaStage: *pubCfg.DeltaStage, + RMax: *pubCfg.RMax, + MaxDurationQuery: *pubCfg.MaxDurationQuery, + MaxDurationObservation: *pubCfg.MaxDurationObservation, + MaxDurationShouldAcceptAttestedReport: *pubCfg.MaxDurationShouldAcceptAttestedReport, + MaxDurationShouldTransmitAcceptedReport: *pubCfg.MaxDurationShouldTransmitAcceptedReport, + F: *pubCfg.F, + } +} + func BuildAutoOCR2ConfigVarsLocal( l zerolog.Logger, chainlinkNodes []*client.ChainlinkClient, @@ -108,6 +145,7 @@ func BuildAutoOCR2ConfigVarsWithKeyIndexLocal( S, // s []int, oracleIdentities, // oracles []OracleIdentityExtra, offC, // reportingPluginConfig []byte, + nil, 20*time.Millisecond, // maxDurationQuery time.Duration, 20*time.Millisecond, // maxDurationObservation time.Duration, // good to here 1200*time.Millisecond, // maxDurationShouldAcceptAttestedReport time.Duration, @@ -143,6 +181,7 @@ func BuildAutoOCR2ConfigVarsWithKeyIndexLocal( S, // s []int, oracleIdentities, // oracles []OracleIdentityExtra, offC, // reportingPluginConfig []byte, + nil, 20*time.Millisecond, // maxDurationQuery time.Duration, 20*time.Millisecond, // maxDurationObservation time.Duration, 1200*time.Millisecond, // maxDurationReport time.Duration, diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 9075b863b65..d470800b0ba 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -12,6 +12,8 @@ import ( "testing" "time" + tt "github.com/smartcontractkit/chainlink/integration-tests/types" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" @@ -20,11 +22,12 @@ import ( ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" @@ -43,9 +46,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/store/models" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" ) type NodeDetails struct { @@ -60,6 +63,8 @@ type NodeDetails struct { type AutomationTest struct { ChainClient *seth.Client + TestConfig tt.AutomationTestConfig + LinkToken contracts.LinkToken Transcoder contracts.UpkeepTranscoder LINKETHFeed contracts.MockLINKETHFeed @@ -109,9 +114,11 @@ func NewAutomationTestK8s( l zerolog.Logger, chainClient *seth.Client, chainlinkNodes []*client.ChainlinkK8sClient, + config tt.AutomationTestConfig, ) *AutomationTest { return &AutomationTest{ ChainClient: chainClient, + TestConfig: config, ChainlinkNodesk8s: chainlinkNodes, IsOnk8s: true, TransmitterKeyIndex: 0, @@ -125,9 +132,11 @@ func NewAutomationTestDocker( l zerolog.Logger, chainClient *seth.Client, chainlinkNodes []*client.ChainlinkClient, + config tt.AutomationTestConfig, ) *AutomationTest { return &AutomationTest{ ChainClient: chainClient, + TestConfig: config, ChainlinkNodes: chainlinkNodes, IsOnk8s: false, TransmitterKeyIndex: 0, @@ -172,6 +181,7 @@ func (a *AutomationTest) LoadLINK(address string) error { return err } a.LinkToken = linkToken + a.Logger.Info().Str("LINK Token Address", a.LinkToken.Address()).Msg("Successfully loaded LINK Token") return nil } @@ -190,6 +200,7 @@ func (a *AutomationTest) LoadTranscoder(address string) error { return err } a.Transcoder = transcoder + a.Logger.Info().Str("Transcoder Address", a.Transcoder.Address()).Msg("Successfully loaded Transcoder") return nil } @@ -208,6 +219,7 @@ func (a *AutomationTest) LoadLinkEthFeed(address string) error { return err } a.LINKETHFeed = ethLinkFeed + a.Logger.Info().Str("LINK/ETH Feed Address", a.LINKETHFeed.Address()).Msg("Successfully loaded LINK/ETH Feed") return nil } @@ -226,6 +238,7 @@ func (a *AutomationTest) LoadEthUSDFeed(address string) error { return err } a.ETHUSDFeed = ethUSDFeed + a.Logger.Info().Str("ETH/USD Feed Address", a.ETHUSDFeed.Address()).Msg("Successfully loaded ETH/USD Feed") return nil } @@ -244,6 +257,7 @@ func (a *AutomationTest) LoadLinkUSDFeed(address string) error { return err } a.LINKUSDFeed = linkUSDFeed + a.Logger.Info().Str("LINK/USD Feed Address", a.LINKUSDFeed.Address()).Msg("Successfully loaded LINK/USD Feed") return nil } @@ -262,6 +276,7 @@ func (a *AutomationTest) LoadWETH(address string) error { return err } a.WETHToken = wethToken + a.Logger.Info().Str("WETH Token Address", a.WETHToken.Address()).Msg("Successfully loaded WETH Token") return nil } @@ -280,6 +295,7 @@ func (a *AutomationTest) LoadEthGasFeed(address string) error { return err } a.GasFeed = gasFeed + a.Logger.Info().Str("Gas Feed Address", a.GasFeed.Address()).Msg("Successfully loaded Gas Feed") return nil } @@ -304,12 +320,13 @@ func (a *AutomationTest) DeployRegistry() error { return nil } -func (a *AutomationTest) LoadRegistry(address string) error { - registry, err := contracts.LoadKeeperRegistry(a.Logger, a.ChainClient, common.HexToAddress(address), a.RegistrySettings.RegistryVersion) +func (a *AutomationTest) LoadRegistry(registryAddress, chainModuleAddress string) error { + registry, err := contracts.LoadKeeperRegistry(a.Logger, a.ChainClient, common.HexToAddress(registryAddress), a.RegistrySettings.RegistryVersion, common.HexToAddress(chainModuleAddress)) if err != nil { return err } a.Registry = registry + a.Logger.Info().Str("ChainModule Address", chainModuleAddress).Str("Registry Address", a.Registry.Address()).Msg("Successfully loaded Registry") return nil } @@ -336,6 +353,7 @@ func (a *AutomationTest) LoadRegistrar(address string) error { if err != nil { return err } + a.Logger.Info().Str("Registrar Address", registrar.Address()).Msg("Successfully loaded Registrar") a.Registrar = registrar return nil } @@ -596,6 +614,7 @@ func (a *AutomationTest) SetConfigOnRegistry() error { }, } } + a.Logger.Debug().Interface("ocrConfig", ocrConfig).Msg("Setting OCR3 config") err = a.Registry.SetConfigTypeSafe(ocrConfig) if err != nil { return errors.Join(err, fmt.Errorf("failed to set config on registry")) @@ -628,6 +647,7 @@ func calculateOCR2ConfigArgs(a *AutomationTest, S []int, oracleIdentities []conf a.PublicConfig.DeltaRound, a.PublicConfig.DeltaGrace, a.PublicConfig.DeltaStage, uint8(a.PublicConfig.RMax), S, oracleIdentities, offC, + nil, a.PublicConfig.MaxDurationQuery, a.PublicConfig.MaxDurationObservation, 1200*time.Millisecond, a.PublicConfig.MaxDurationShouldAcceptAttestedReport, @@ -652,7 +672,7 @@ func calculateOCR3ConfigArgs(a *AutomationTest, S []int, oracleIdentities []conf a.PublicConfig.DeltaRound, a.PublicConfig.DeltaGrace, a.PublicConfig.DeltaCertifiedCommitRequest, a.PublicConfig.DeltaStage, a.PublicConfig.RMax, S, oracleIdentities, offC, - a.PublicConfig.MaxDurationQuery, a.PublicConfig.MaxDurationObservation, + nil, a.PublicConfig.MaxDurationQuery, a.PublicConfig.MaxDurationObservation, a.PublicConfig.MaxDurationShouldAcceptAttestedReport, a.PublicConfig.MaxDurationShouldTransmitAcceptedReport, a.PublicConfig.F, a.PublicConfig.OnchainConfig, @@ -845,7 +865,7 @@ func (a *AutomationTest) AddJobsAndSetConfig(t *testing.T) { l.Info().Str("Registry Address", a.Registry.Address()).Msg("Successfully setConfig on registry") } -func (a *AutomationTest) SetupMercuryMock(t *testing.T, imposters []ctfTestEnv.KillgraveImposter) { +func (a *AutomationTest) SetupMercuryMock(t *testing.T, imposters []ctftestenv.KillgraveImposter) { if a.IsOnk8s { t.Error("mercury mock is not supported on k8s") } @@ -859,65 +879,118 @@ func (a *AutomationTest) SetupMercuryMock(t *testing.T, imposters []ctfTestEnv.K } func (a *AutomationTest) SetupAutomationDeployment(t *testing.T) { + a.setupDeployment(t, true) +} + +func (a *AutomationTest) SetupAutomationDeploymentWithoutJobs(t *testing.T) { + a.setupDeployment(t, false) +} + +func (a *AutomationTest) setupDeployment(t *testing.T, addJobs bool) { l := logging.GetTestLogger(t) err := a.CollectNodeDetails() require.NoError(t, err, "Error collecting node details") l.Info().Msg("Collected Node Details") l.Debug().Interface("Node Details", a.NodeDetails).Msg("Node Details") - err = a.DeployLINK() - require.NoError(t, err, "Error deploying link token contract") - - err = a.DeployWETH() - require.NoError(t, err, "Error deploying weth token contract") + if a.TestConfig.GetAutomationConfig().UseExistingLinkTokenContract() { + linkAddress, err := a.TestConfig.GetAutomationConfig().LinkTokenContractAddress() + require.NoError(t, err, "Error getting link token contract address") + err = a.LoadLINK(linkAddress.String()) + require.NoError(t, err, "Error loading link token contract") + } else { + err = a.DeployLINK() + require.NoError(t, err, "Error deploying link token contract") + } - err = a.DeployLinkEthFeed() - require.NoError(t, err, "Error deploying link eth feed contract") - err = a.DeployGasFeed() - require.NoError(t, err, "Error deploying gas feed contract") + if a.TestConfig.GetAutomationConfig().UseExistingWethContract() { + wethAddress, err := a.TestConfig.GetAutomationConfig().WethContractAddress() + require.NoError(t, err, "Error getting weth token contract address") + err = a.LoadWETH(wethAddress.String()) + require.NoError(t, err, "Error loading weth token contract") + } else { + err = a.DeployWETH() + require.NoError(t, err, "Error deploying weth token contract") + } - err = a.DeployEthUSDFeed() - require.NoError(t, err, "Error deploying eth usd feed contract") + if a.TestConfig.GetAutomationConfig().UseExistingLinkEthFeedContract() { + linkEthFeedAddress, err := a.TestConfig.GetAutomationConfig().LinkEthFeedContractAddress() + require.NoError(t, err, "Error getting link eth feed contract address") + err = a.LoadLinkEthFeed(linkEthFeedAddress.String()) + require.NoError(t, err, "Error loading link eth feed contract") + } else { + err = a.DeployLinkEthFeed() + require.NoError(t, err, "Error deploying link eth feed contract") + } - err = a.DeployLinkUSDFeed() - require.NoError(t, err, "Error deploying link usd feed contract") + if a.TestConfig.GetAutomationConfig().UseExistingEthGasFeedContract() { + gasFeedAddress, err := a.TestConfig.GetAutomationConfig().EthGasFeedContractAddress() + require.NoError(t, err, "Error getting gas feed contract address") + err = a.LoadEthGasFeed(gasFeedAddress.String()) + require.NoError(t, err, "Error loading gas feed contract") + } else { + err = a.DeployGasFeed() + require.NoError(t, err, "Error deploying gas feed contract") + } - err = a.DeployTranscoder() - require.NoError(t, err, "Error deploying transcoder contract") + if a.TestConfig.GetAutomationConfig().UseExistingEthUSDFeedContract() { + ethUsdFeedAddress, err := a.TestConfig.GetAutomationConfig().EthUSDFeedContractAddress() + require.NoError(t, err, "Error getting eth usd feed contract address") + err = a.LoadEthUSDFeed(ethUsdFeedAddress.String()) + require.NoError(t, err, "Error loading eth usd feed contract") + } else { + err = a.DeployEthUSDFeed() + require.NoError(t, err, "Error deploying eth usd feed contract") + } - err = a.DeployRegistry() - require.NoError(t, err, "Error deploying registry contract") - err = a.DeployRegistrar() - require.NoError(t, err, "Error deploying registrar contract") + if a.TestConfig.GetAutomationConfig().UseExistingLinkUSDFeedContract() { + linkUsdFeedAddress, err := a.TestConfig.GetAutomationConfig().LinkUSDFeedContractAddress() + require.NoError(t, err, "Error getting link usd feed contract address") + err = a.LoadLinkUSDFeed(linkUsdFeedAddress.String()) + require.NoError(t, err, "Error loading link usd feed contract") + } else { + err = a.DeployLinkUSDFeed() + require.NoError(t, err, "Error deploying link usd feed contract") + } - a.AddJobsAndSetConfig(t) -} + if a.TestConfig.GetAutomationConfig().UseExistingTranscoderContract() { + transcoderAddress, err := a.TestConfig.GetAutomationConfig().TranscoderContractAddress() + require.NoError(t, err, "Error getting transcoder contract address") + err = a.LoadTranscoder(transcoderAddress.String()) + require.NoError(t, err, "Error loading transcoder contract") + } else { + err = a.DeployTranscoder() + require.NoError(t, err, "Error deploying transcoder contract") + } + + if a.TestConfig.GetAutomationConfig().UseExistingRegistryContract() { + chainModuleAddress, err := a.TestConfig.GetAutomationConfig().ChainModuleContractAddress() + require.NoError(t, err, "Error getting chain module contract address") + registryAddress, err := a.TestConfig.GetAutomationConfig().RegistryContractAddress() + require.NoError(t, err, "Error getting registry contract address") + err = a.LoadRegistry(registryAddress.String(), chainModuleAddress.String()) + require.NoError(t, err, "Error loading registry contract") + if a.Registry.RegistryOwnerAddress().String() != a.ChainClient.MustGetRootKeyAddress().String() { + l.Debug().Str("RootKeyAddress", a.ChainClient.MustGetRootKeyAddress().String()).Str("Registry Owner Address", a.Registry.RegistryOwnerAddress().String()).Msg("Registry owner address is not the root key address") + t.Error("Registry owner address is not the root key address") + t.FailNow() + } + } else { + err = a.DeployRegistry() + require.NoError(t, err, "Error deploying registry contract") + } -func (a *AutomationTest) LoadAutomationDeployment(t *testing.T, linkTokenAddress, - linkEthFeedAddress, linkUsdFeedAddress, EthUsdFeedAddress, gasFeedAddress, transcoderAddress, registryAddress, registrarAddress string) { - l := logging.GetTestLogger(t) - err := a.CollectNodeDetails() - require.NoError(t, err, "Error collecting node details") - l.Info().Msg("Collected Node Details") - l.Debug().Interface("Node Details", a.NodeDetails).Msg("Node Details") + if a.TestConfig.GetAutomationConfig().UseExistingRegistrarContract() { + registrarAddress, err := a.TestConfig.GetAutomationConfig().RegistrarContractAddress() + require.NoError(t, err, "Error getting registrar contract address") + err = a.LoadRegistrar(registrarAddress.String()) + require.NoError(t, err, "Error loading registrar contract") + } else { + err = a.DeployRegistrar() + require.NoError(t, err, "Error deploying registrar contract") + } - err = a.LoadLINK(linkTokenAddress) - require.NoError(t, err, "Error loading link token contract") - - err = a.LoadLinkEthFeed(linkEthFeedAddress) - require.NoError(t, err, "Error loading link eth feed contract") - err = a.LoadEthGasFeed(gasFeedAddress) - require.NoError(t, err, "Error loading gas feed contract") - err = a.LoadEthUSDFeed(EthUsdFeedAddress) - require.NoError(t, err, "Error loading eth usd feed contract") - err = a.LoadLinkUSDFeed(linkUsdFeedAddress) - require.NoError(t, err, "Error loading link usd feed contract") - err = a.LoadTranscoder(transcoderAddress) - require.NoError(t, err, "Error loading transcoder contract") - err = a.LoadRegistry(registryAddress) - require.NoError(t, err, "Error loading registry contract") - err = a.LoadRegistrar(registrarAddress) - require.NoError(t, err, "Error loading registrar contract") - - a.AddJobsAndSetConfig(t) + if addJobs { + a.AddJobsAndSetConfig(t) + } } diff --git a/integration-tests/actions/contracts.go b/integration-tests/actions/contracts.go new file mode 100644 index 00000000000..1a50c4d7ba9 --- /dev/null +++ b/integration-tests/actions/contracts.go @@ -0,0 +1,23 @@ +package actions + +import ( + "github.com/rs/zerolog" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" +) + +// LinkTokenContract returns a link token contract instance. Depending on test configuration, it either deploys a new one or uses an existing one. +func LinkTokenContract(l zerolog.Logger, sethClient *seth.Client, configWithLinkToken tc.LinkTokenContractConfig) (*contracts.EthereumLinkToken, error) { + if configWithLinkToken != nil && configWithLinkToken.UseExistingLinkTokenContract() { + linkAddress, err := configWithLinkToken.LinkTokenContractAddress() + if err != nil { + return nil, err + } + + return contracts.LoadLinkTokenContract(l, sethClient, linkAddress) + } + return contracts.DeployLinkTokenContract(l, sethClient) +} diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 618ca969334..1cf468d06fa 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -8,13 +8,16 @@ import ( "strconv" "testing" + tt "github.com/smartcontractkit/chainlink/integration-tests/types" + "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "github.com/pkg/errors" - "github.com/smartcontractkit/seth" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/ethereum/go-ethereum/common" @@ -116,7 +119,7 @@ func DeployKeeperContracts( } registrar := DeployKeeperRegistrar(t, client, registryVersion, linkToken, registrarSettings, registry) - upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false, false, nil) + upkeeps, upkeepIds := DeployLegacyConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false, false, nil) return registry, registrar, upkeeps, upkeepIds } @@ -455,6 +458,33 @@ func DeployKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts return results } +// SetupKeeperConsumers concurrently loads or deploys keeper consumer contracts. It requires at least 1 ephemeral key to be present in Seth config. +func SetupKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts int, isLogTrigger bool, isMercury bool, config tt.AutomationTestConfig) []contracts.KeeperConsumer { + l := logging.GetTestLogger(t) + + var results []contracts.KeeperConsumer + + if config.GetAutomationConfig().UseExistingUpkeepContracts() { + contractsLoaded, err := config.GetAutomationConfig().UpkeepContractAddresses() + require.NoError(t, err, "Failed to get upkeep contract addresses") + require.Equal(t, numberOfContracts, len(contractsLoaded), "Incorrect number of Keeper Consumer Contracts loaded") + l.Info().Int("Number of Contracts", numberOfContracts).Msg("Loading upkeep contracts from config") + // Load existing contracts + for i := 0; i < numberOfContracts; i++ { + require.NoError(t, err, "Failed to get upkeep contract addresses") + contract, err := contracts.LoadKeeperConsumer(client, contractsLoaded[i]) + require.NoError(t, err, "Failed to load keeper consumer contract") + l.Info().Str("Contract Address", contract.Address()).Int("Number", i+1).Int("Out Of", numberOfContracts).Msg("Loaded Keeper Consumer Contract") + results = append(results, contract) + } + } else { + // Deploy new contracts + return DeployKeeperConsumers(t, client, numberOfContracts, isLogTrigger, isMercury) + } + + return results +} + // DeployKeeperConsumersPerformance sequentially deploys keeper performance consumer contracts. func DeployKeeperConsumersPerformance( t *testing.T, diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index 0f8dd9b29f2..7fd16f524a0 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -54,6 +54,7 @@ func BuildMedianOCR2Config( AlphaAcceptPPB: 1, DeltaC: time.Minute * 30, }.Encode(), // reportingPluginConfig []byte, + nil, 5*time.Second, // maxDurationQuery time.Duration, 5*time.Second, // maxDurationObservation time.Duration, 5*time.Second, // maxDurationReport time.Duration, diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go index 733b6903552..fca334b8f80 100644 --- a/integration-tests/actions/ocr2_helpers_local.go +++ b/integration-tests/actions/ocr2_helpers_local.go @@ -19,7 +19,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/codec" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -198,6 +198,7 @@ func BuildMedianOCR2ConfigLocal(workerNodes []*client.ChainlinkClient, ocrOffcha AlphaAcceptPPB: 1, DeltaC: time.Minute * 30, }.Encode(), // reportingPluginConfig []byte, + nil, 5*time.Second, // maxDurationQuery time.Duration, 5*time.Second, // maxDurationObservation time.Duration, 5*time.Second, // maxDurationReport time.Duration, diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index 0622167c997..0f6f65d1289 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -10,16 +10,19 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/google/uuid" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ocr" ) // This actions file often returns functions, rather than just values. These are used as common test helpers, and are @@ -228,13 +231,14 @@ func BuildNodeContractPairID(node contracts.ChainlinkNodeWithKeysAndAddress, ocr func SetupOCRv1Cluster( l zerolog.Logger, seth *seth.Client, + configWithLinkToken tc.LinkTokenContractConfig, workerNodes []*client.ChainlinkK8sClient, ) (common.Address, error) { err := FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(3)) if err != nil { return common.Address{}, err } - linkContract, err := contracts.DeployLinkTokenContract(l, seth) + linkContract, err := LinkTokenContract(l, seth, configWithLinkToken) if err != nil { return common.Address{}, err } @@ -245,11 +249,12 @@ func SetupOCRv1Feed( l zerolog.Logger, seth *seth.Client, lta common.Address, + ocrContractsConfig ocr.OffChainAggregatorsConfig, msClient *ctfClient.MockserverClient, bootstrapNode *client.ChainlinkK8sClient, workerNodes []*client.ChainlinkK8sClient, ) ([]contracts.OffchainAggregator, error) { - ocrInstances, err := DeployOCRv1Contracts(l, seth, 1, lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := SetupOCRv1Contracts(l, seth, ocrContractsConfig, lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) if err != nil { return nil, err } diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index 0b415277f27..b546139dc32 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -10,7 +10,7 @@ import ( "github.com/google/uuid" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go index f10371d41a6..40fe317ab3f 100644 --- a/integration-tests/actions/private_network.go +++ b/integration-tests/actions/private_network.go @@ -3,9 +3,9 @@ package actions import ( "github.com/rs/zerolog" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" ) func EthereumNetworkConfigFromConfig(l zerolog.Logger, config ctf_config.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { diff --git a/integration-tests/actions/refund.go b/integration-tests/actions/refund.go index 38c4dfad3b9..649d49f9378 100644 --- a/integration-tests/actions/refund.go +++ b/integration-tests/actions/refund.go @@ -16,18 +16,21 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/pkg/errors" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" clClient "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) const ( - InsufficientFundsErr = "insufficient funds" - GasTooLowErr = "gas too low" - OvershotErr = "overshot" + InsufficientFundsErr = "insufficient funds" + TransactionUnderPriced = "transaction underpriced" + FailedToWaitForTransaction = "failed to wait for transaction" + GasTooLowErr = "gas too low" + OvershotErr = "overshot" ) var ( @@ -51,21 +54,21 @@ func (r *InsufficientFundTransferRetrier) Retry(ctx context.Context, logger zero if currentAttempt >= r.maxRetries { if r.nextRetrier != nil { logger.Debug(). - Str("retier", "InsufficientFundTransferRetrier"). + Str("retrier", "InsufficientFundTransferRetrier"). Msg("Max retries reached. Passing to next retrier") return r.nextRetrier.Retry(ctx, logger, client, txErr, payload, 0) } return txErr } - for txErr != nil && (strings.Contains(txErr.Error(), InsufficientFundsErr)) { + for txErr != nil && (strings.Contains(txErr.Error(), InsufficientFundsErr) || strings.Contains(txErr.Error(), TransactionUnderPriced) || strings.Contains(txErr.Error(), FailedToWaitForTransaction)) { logger.Info(). Msg("Insufficient funds error detected, retrying with less funds") newAmount := big.NewInt(0).Sub(payload.Amount, big.NewInt(blockchain.GWei)) logger.Debug(). - Str("retier", "InsufficientFundTransferRetrier"). + Str("retrier", "InsufficientFundTransferRetrier"). Str("old amount", payload.Amount.String()). Str("new amount", newAmount.String()). Str("diff", big.NewInt(0).Sub(payload.Amount, newAmount).String()). @@ -76,25 +79,27 @@ func (r *InsufficientFundTransferRetrier) Retry(ctx context.Context, logger zero _, retryErr := SendFunds(logger, client, payload) if retryErr == nil { logger.Info(). - Str("retier", "InsufficientFundTransferRetrier"). + Str("retrier", "InsufficientFundTransferRetrier"). Msg(RetrySuccessfulMsg) return nil } - if strings.Contains(retryErr.Error(), InsufficientFundsErr) { + if strings.Contains(retryErr.Error(), InsufficientFundsErr) || strings.Contains(retryErr.Error(), TransactionUnderPriced) || strings.Contains(retryErr.Error(), FailedToWaitForTransaction) { return r.Retry(ctx, logger, client, retryErr, payload, currentAttempt+1) } + + txErr = retryErr } if r.nextRetrier != nil { logger.Debug(). - Str("retier", "InsufficientFundTransferRetrier"). + Str("retrier", "InsufficientFundTransferRetrier"). Msg(NotSupportedMsg) return r.nextRetrier.Retry(ctx, logger, client, txErr, payload, 0) } logger.Warn(). - Str("retier", "InsufficientFundTransferRetrier"). + Str("retrier", "InsufficientFundTransferRetrier"). Msg("No more retriers available. Unable to retry transaction. Returning error.") return txErr @@ -111,7 +116,7 @@ func (r *GasTooLowTransferRetrier) Retry(ctx context.Context, logger zerolog.Log if payload.GasLimit != nil && *payload.GasLimit >= r.maxGasLimit { if r.nextRetrier != nil { logger.Debug(). - Str("retier", "GasTooLowTransferRetrier"). + Str("retrier", "GasTooLowTransferRetrier"). Msg("Max gas limit reached. Passing to next retrier") return r.nextRetrier.Retry(ctx, logger, client, txErr, payload, 0) } @@ -129,7 +134,7 @@ func (r *GasTooLowTransferRetrier) Retry(ctx context.Context, logger zerolog.Log } logger.Debug(). - Str("retier", "GasTooLowTransferRetrier"). + Str("retrier", "GasTooLowTransferRetrier"). Int64("old gas limit", newGasLimit/2). Int64("new gas limit", newGasLimit). Int64("diff", newGasLimit). @@ -140,7 +145,7 @@ func (r *GasTooLowTransferRetrier) Retry(ctx context.Context, logger zerolog.Log _, retryErr := SendFunds(logger, client, payload) if retryErr == nil { logger.Info(). - Str("retier", "GasTooLowTransferRetrier"). + Str("retrier", "GasTooLowTransferRetrier"). Msg(RetrySuccessfulMsg) return nil } @@ -148,17 +153,19 @@ func (r *GasTooLowTransferRetrier) Retry(ctx context.Context, logger zerolog.Log if strings.Contains(retryErr.Error(), GasTooLowErr) { return r.Retry(ctx, logger, client, retryErr, payload, currentAttempt+1) } + + txErr = retryErr } if r.nextRetrier != nil { logger.Debug(). - Str("retier", "OvershotTransferRetrier"). + Str("retrier", "GasTooLowTransferRetrier"). Msg(NotSupportedMsg) return r.nextRetrier.Retry(ctx, logger, client, txErr, payload, 0) } logger.Warn(). - Str("retier", "OvershotTransferRetrier"). + Str("retrier", "GasTooLowTransferRetrier"). Msg("No more retriers available. Unable to retry transaction. Returning error.") return txErr @@ -174,7 +181,7 @@ type OvershotTransferRetrier struct { func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logger, client *seth.Client, txErr error, payload FundsToSendPayload, currentAttempt int) error { if currentAttempt >= r.maxRetries { logger.Debug(). - Str("retier", "OvershotTransferRetrier"). + Str("retrier", "OvershotTransferRetrier"). Msg("Max retries reached. Passing to next retrier") if r.nextRetrier != nil { return r.nextRetrier.Retry(ctx, logger, client, txErr, payload, 0) @@ -198,7 +205,7 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg newAmount := big.NewInt(0).Sub(payload.Amount, big.NewInt(int64(overshotAmount))) logger.Debug(). - Str("retier", "OvershotTransferRetrier"). + Str("retrier", "OvershotTransferRetrier"). Str("old amount", payload.Amount.String()). Str("new amount", newAmount.String()). Str("diff", big.NewInt(0).Sub(payload.Amount, newAmount).String()). @@ -209,7 +216,7 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg _, retryErr := SendFunds(logger, client, payload) if retryErr == nil { logger.Info(). - Str("retier", "OvershotTransferRetrier"). + Str("retrier", "OvershotTransferRetrier"). Msg(RetrySuccessfulMsg) return nil } @@ -217,11 +224,13 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg if strings.Contains(retryErr.Error(), OvershotErr) { return r.Retry(ctx, logger, client, retryErr, payload, currentAttempt+1) } + + txErr = retryErr } if r.nextRetrier != nil { logger.Debug(). - Str("retier", "OvershotTransferRetrier"). + Str("retrier", "OvershotTransferRetrier"). Msg(NotSupportedMsg) return r.nextRetrier.Retry(ctx, logger, client, txErr, payload, 0) } @@ -233,6 +242,14 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg // of strategies to attempt to return funds, including retrying with less funds if the transaction fails due to // insufficient funds, and retrying with a higher gas limit if the transaction fails due to gas too low. func ReturnFundsFromNodes(log zerolog.Logger, client *seth.Client, chainlinkNodes []contracts.ChainlinkNodeWithKeysAndAddress) error { + var keyExporters []contracts.ChainlinkKeyExporter + for _, node := range chainlinkNodes { + keyExporters = append(keyExporters, node) + } + return ReturnFundsFromKeyExporterNodes(log, client, keyExporters) +} + +func ReturnFundsFromKeyExporterNodes(log zerolog.Logger, client *seth.Client, chainlinkNodes []contracts.ChainlinkKeyExporter) error { if client == nil { return fmt.Errorf("seth client is nil, unable to return funds from chainlink nodes") } diff --git a/integration-tests/actions/vrf/common/actions.go b/integration-tests/actions/vrf/common/actions.go index e1bda549e71..67d13264c17 100644 --- a/integration-tests/actions/vrf/common/actions.go +++ b/integration-tests/actions/vrf/common/actions.go @@ -17,11 +17,12 @@ import ( "github.com/go-resty/resty/v2" "github.com/google/uuid" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/actions/vrf/vrfv1/actions.go b/integration-tests/actions/vrf/vrfv1/actions.go index 67110c543e5..f5fae76a395 100644 --- a/integration-tests/actions/vrf/vrfv1/actions.go +++ b/integration-tests/actions/vrf/vrfv1/actions.go @@ -3,7 +3,7 @@ package vrfv1 import ( "fmt" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 1b909be9b83..25239537f4e 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -11,9 +11,9 @@ import ( "github.com/rs/zerolog" "github.com/shopspring/decimal" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index b5852f82815..f252f79ffc0 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -6,7 +6,7 @@ import ( "math/big" "testing" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" @@ -14,7 +14,7 @@ import ( "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2" @@ -42,7 +42,7 @@ func CreateVRFV2Job( } ost, err := os.String() if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrParseJob, err) + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrParseJob, err) } spec := &client.VRFV2JobSpec{ @@ -69,7 +69,7 @@ func CreateVRFV2Job( } job, err := chainlinkNode.MustCreateJob(spec) if err != nil { - return nil, fmt.Errorf("%s, err %w", ErrCreatingVRFv2Job, err) + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrCreatingVRFv2Job, err) } return job, nil } @@ -113,15 +113,14 @@ func SetupVRFV2Environment( if err != nil { return nil, nil, nil, err } - l.Info().Str("Coordinator", vrfContracts.CoordinatorV2.Address()).Msg("Registering Proving Key") provingKey, err := VRFV2RegisterProvingKey(vrfKey, registerProvingKeyAgainstAddress, vrfContracts.CoordinatorV2) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err %w", vrfcommon.ErrRegisteringProvingKey, err) + return nil, nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrRegisteringProvingKey, err) } keyHash, err := vrfContracts.CoordinatorV2.HashOfKey(ctx, provingKey) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err %w", vrfcommon.ErrCreatingProvingKeyHash, err) + return nil, nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrCreatingProvingKeyHash, err) } vrfTXKeyAddressStrings, vrfTXKeyAddresses, err := vrfcommon.CreateFundAndGetSendingKeys( @@ -189,44 +188,47 @@ func SetupVRFV2Environment( return vrfContracts, &vrfKeyData, nodeTypeToNodeMap, nil } -func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, vrfv2Config *testconfig.General, pubKeyCompressed string, vrfOwnerConfig *vrfcommon.VRFOwnerConfig, l zerolog.Logger, vrfNode *vrfcommon.VRFNode) error { +func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, config *testconfig.General, pubKeyCompressed string, vrfOwnerConfig *vrfcommon.VRFOwnerConfig, l zerolog.Logger, vrfNode *vrfcommon.VRFNode) error { vrfJobSpecConfig := vrfcommon.VRFJobSpecConfig{ - ForwardingAllowed: *vrfv2Config.VRFJobForwardingAllowed, + ForwardingAllowed: *config.VRFJobForwardingAllowed, CoordinatorAddress: contracts.CoordinatorV2.Address(), BatchCoordinatorAddress: contracts.BatchCoordinatorV2.Address(), FromAddresses: vrfNode.TXKeyAddressStrings, EVMChainID: chainID.String(), - MinIncomingConfirmations: int(*vrfv2Config.MinimumConfirmations), + MinIncomingConfirmations: int(*config.MinimumConfirmations), PublicKey: pubKeyCompressed, - EstimateGasMultiplier: *vrfv2Config.VRFJobEstimateGasMultiplier, - BatchFulfillmentEnabled: *vrfv2Config.VRFJobBatchFulfillmentEnabled, - BatchFulfillmentGasMultiplier: *vrfv2Config.VRFJobBatchFulfillmentGasMultiplier, - PollPeriod: vrfv2Config.VRFJobPollPeriod.Duration, - RequestTimeout: vrfv2Config.VRFJobRequestTimeout.Duration, - SimulationBlock: vrfv2Config.VRFJobSimulationBlock, + EstimateGasMultiplier: *config.VRFJobEstimateGasMultiplier, + BatchFulfillmentEnabled: *config.VRFJobBatchFulfillmentEnabled, + BatchFulfillmentGasMultiplier: *config.VRFJobBatchFulfillmentGasMultiplier, + PollPeriod: config.VRFJobPollPeriod.Duration, + RequestTimeout: config.VRFJobRequestTimeout.Duration, + SimulationBlock: config.VRFJobSimulationBlock, VRFOwnerConfig: vrfOwnerConfig, } l.Info().Msg("Creating VRFV2 Job") - vrfV2job, err := CreateVRFV2Job( + job, err := CreateVRFV2Job( vrfNode.CLNode.API, vrfJobSpecConfig, ) if err != nil { return fmt.Errorf("%s, err %w", ErrCreateVRFV2Jobs, err) } - vrfNode.Job = vrfV2job + vrfNode.Job = job // this part is here because VRFv2 can work with only a specific key // [[EVM.KeySpecific]] // Key = '...' nodeConfig := node.NewConfig(vrfNode.CLNode.NodeConfig, - node.WithKeySpecificMaxGasPrice(vrfNode.TXKeyAddressStrings, *vrfv2Config.CLNodeMaxGasPriceGWei), + node.WithKeySpecificMaxGasPrice(vrfNode.TXKeyAddressStrings, *config.CLNodeMaxGasPriceGWei), ) - l.Info().Msg("Restarting Node with new sending key PriceMax configuration") + l.Info(). + Strs("Sending Keys", vrfNode.TXKeyAddressStrings). + Int64("Price Max Setting", *config.CLNodeMaxGasPriceGWei). + Msg("Restarting Node with new sending key PriceMax configuration") err = vrfNode.CLNode.Restart(nodeConfig) if err != nil { - return fmt.Errorf("%s, err %w", vrfcommon.ErrRestartCLNode, err) + return fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrRestartCLNode, err) } return nil } @@ -378,7 +380,7 @@ func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l if err != nil { return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading existing CL env", err) } - coordinator, err := contracts.LoadVRFCoordinatorV2(sethClient, *commonExistingEnvConfig.ConsumerAddress) + coordinator, err := contracts.LoadVRFCoordinatorV2(sethClient, *commonExistingEnvConfig.CoordinatorAddress) if err != nil { return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2", err) } diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 5a4ec9ba11a..4dced9edf79 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -10,9 +10,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/shopspring/decimal" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -40,7 +41,7 @@ func DeployVRFV2_5Contracts( if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployCoordinatorV2Plus, err) } - err = opStackCoordinator.SetL1FeeCalculation(configGeneral.L1FeeCalculationMode, configGeneral.L1FeeCoefficient) + err = opStackCoordinator.SetL1FeeCalculation(*configGeneral.L1FeeCalculationMode, *configGeneral.L1FeeCoefficient) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrSetL1FeeCalculation, err) } @@ -48,6 +49,24 @@ func DeployVRFV2_5Contracts( if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrLoadingCoordinator, err) } + } else if actions.IsArbitrumChain(chainClient.ChainID) { + arbitrumCoordinator, err := contracts.DeployVRFCoordinatorV2_5_Arbitrum(chainClient, bhs.Address()) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployCoordinatorV2Plus, err) + } + coordinator, err = contracts.LoadVRFCoordinatorV2_5(chainClient, arbitrumCoordinator.Address.String()) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrLoadingCoordinator, err) + } + } else if *configGeneral.UseTestCoordinator { + testCoordinator, err := contracts.DeployVRFCoordinatorTestV2_5(chainClient, bhs.Address()) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployCoordinatorV2Plus, err) + } + coordinator, err = contracts.LoadVRFCoordinatorV2_5(chainClient, testCoordinator.Address.String()) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrLoadingCoordinator, err) + } } else { coordinator, err = contracts.DeployVRFCoordinatorV2_5(chainClient, bhs.Address()) if err != nil { @@ -418,7 +437,7 @@ func DeployVRFV2PlusDirectFundingContracts( if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployWrapper, err) } - err = opStackWrapper.SetL1FeeCalculation(configGeneral.L1FeeCalculationMode, configGeneral.L1FeeCoefficient) + err = opStackWrapper.SetL1FeeCalculation(*configGeneral.L1FeeCalculationMode, *configGeneral.L1FeeCoefficient) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrSetL1FeeCalculation, err) } @@ -426,6 +445,15 @@ func DeployVRFV2PlusDirectFundingContracts( if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrLoadingCoordinator, err) } + } else if actions.IsArbitrumChain(sethClient.ChainID) { + arbitrumWrapper, err := contracts.DeployVRFV2PlusWrapperArbitrum(sethClient, linkTokenAddress, linkEthFeedAddress, coordinator.Address(), wrapperSubId) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployCoordinatorV2Plus, err) + } + vrfv2PlusWrapper, err = contracts.LoadVRFV2PlusWrapper(sethClient, arbitrumWrapper.Address.String()) + if err != nil { + return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrLoadingCoordinator, err) + } } else { vrfv2PlusWrapper, err = contracts.DeployVRFV2PlusWrapper(sethClient, linkTokenAddress, linkEthFeedAddress, coordinator.Address(), wrapperSubId) if err != nil { diff --git a/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go b/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go index 1c6e2edaa0a..758200f86f4 100644 --- a/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go +++ b/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go @@ -4,9 +4,11 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" @@ -55,3 +57,18 @@ func LogSubDetailsAfterMigration(l zerolog.Logger, newCoordinator contracts.Coor Interface("Subscription Consumers", migratedSubscription.Consumers). Msg("Subscription Data After Migration to New Coordinator") } + +func LogPaymentDetails(l zerolog.Logger, fulfillmentTxFeeWei *big.Int, fulfillmentTxReceipt *types.Receipt, actualSubPaymentWei *big.Int, expectedSubPaymentWei *big.Float, configCopy tc.TestConfig) { + l.Info(). + Str("Tx Fee in Wei", fulfillmentTxFeeWei.String()). + Str("Effective Gas Price", fulfillmentTxReceipt.EffectiveGasPrice.String()). + Uint64("Gas Used", fulfillmentTxReceipt.GasUsed). + Str("Actual Subscription Payment in Wei", actualSubPaymentWei.String()). + Str("Expected Subscription Payment in Wei", expectedSubPaymentWei.String()). + Uint8("Native Premium Percentage", *configCopy.VRFv2Plus.General.NativePremiumPercentage). + Uint8("Link Premium Percentage", *configCopy.VRFv2Plus.General.LinkPremiumPercentage). + Uint32("FulfillmentFlatFeeNativePPM", *configCopy.VRFv2Plus.General.FulfillmentFlatFeeNativePPM). + Uint32("FulfillmentFlatFeeLinkDiscountPPM", *configCopy.VRFv2Plus.General.FulfillmentFlatFeeLinkDiscountPPM). + Uint32("GasAfterPaymentCalculation", *configCopy.VRFv2Plus.General.GasAfterPaymentCalculation). + Msg("Randomness Fulfillment Payment Details") +} diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 4833afb9fef..c88c7fdb125 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -6,7 +6,7 @@ import ( "math/big" "testing" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/shopspring/decimal" "golang.org/x/sync/errgroup" @@ -15,7 +15,7 @@ import ( "github.com/google/uuid" "github.com/rs/zerolog" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -63,12 +63,10 @@ func CreateVRFV2PlusJob( if vrfJobSpecConfig.BatchFulfillmentEnabled { jobSpec.BatchCoordinatorAddress = vrfJobSpecConfig.BatchCoordinatorAddress } - job, err := chainlinkNode.MustCreateJob(&jobSpec) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrCreatingVRFv2PlusJob, err) } - return job, nil } @@ -87,7 +85,6 @@ func SetupVRFV2_5Environment( ) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { l.Info().Msg("Starting VRFV2 Plus environment setup") configGeneral := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General - vrfContracts, err := SetupVRFV2PlusContracts( sethClient, linkToken, @@ -361,7 +358,7 @@ func SetupVRFV2PlusWrapperForNewEnv( vrfv2PlusConfig, ) if err != nil { - return nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrWaitTXsComplete, err) + return nil, nil, err } // once the wrapper is deployed, wrapper address will become consumer of external EOA subscription err = vrfContracts.CoordinatorV2Plus.AddConsumer(wrapperSubId, wrapperContracts.VRFV2PlusWrapper.Address()) diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/automation_test.go similarity index 73% rename from integration-tests/benchmark/keeper_test.go rename to integration-tests/benchmark/automation_test.go index af0d52ae237..0a63ff2c27a 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/automation_test.go @@ -9,19 +9,18 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - envclient "github.com/smartcontractkit/chainlink-testing-framework/k8s/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - sethutils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + envclient "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/reorg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + sethutils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" ethcontracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" @@ -75,7 +74,7 @@ func TestAutomationBenchmark(t *testing.T) { testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err, "Error getting test type") - config, err := tc.GetConfig([]string{testType}, tc.Keeper) + config, err := tc.GetConfig([]string{testType}, tc.Automation) require.NoError(t, err, "Error getting test config") testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, &config) @@ -83,7 +82,7 @@ func TestAutomationBenchmark(t *testing.T) { return } networkName := strings.ReplaceAll(benchmarkNetwork.Name, " ", "") - testName := fmt.Sprintf("%s%s", networkName, *config.Keeper.Common.RegistryToTest) + testName := fmt.Sprintf("%s%s", networkName, *config.Automation.Benchmark.RegistryToTest) l.Info().Str("Test Name", testName).Msg("Running Benchmark Test") benchmarkTestNetwork := getNetworkConfig(&config) @@ -94,66 +93,47 @@ func TestAutomationBenchmark(t *testing.T) { require.NoError(t, err, "Error getting Seth client") registryVersions := addRegistry(&config) + registrySettings := actions.ReadRegistryConfig(config) keeperBenchmarkTest := testsetups.NewKeeperBenchmarkTest(t, testsetups.KeeperBenchmarkTestInputs{ - BlockchainClient: chainClient, - RegistryVersions: registryVersions, - KeeperRegistrySettings: &contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: uint32(0), - FlatFeeMicroLINK: uint32(40000), - BlockCountPerTurn: big.NewInt(100), - CheckGasLimit: uint32(45_000_000), //45M - StalenessSeconds: big.NewInt(90_000), - GasCeilingMultiplier: uint16(2), - MaxPerformGas: uint32(*config.Keeper.Common.MaxPerformGas), - MinUpkeepSpend: big.NewInt(0), - FallbackGasPrice: big.NewInt(2e11), - FallbackLinkPrice: big.NewInt(2e18), - MaxCheckDataSize: uint32(5_000), - MaxPerformDataSize: uint32(5_000), - MaxRevertDataSize: uint32(5_000), - }, + BlockchainClient: chainClient, + RegistryVersions: registryVersions, + KeeperRegistrySettings: ®istrySettings, Upkeeps: &testsetups.UpkeepConfig{ - NumberOfUpkeeps: *config.Keeper.Common.NumberOfUpkeeps, - CheckGasToBurn: *config.Keeper.Common.CheckGasToBurn, - PerformGasToBurn: *config.Keeper.Common.PerformGasToBurn, - BlockRange: *config.Keeper.Common.BlockRange, - BlockInterval: *config.Keeper.Common.BlockInterval, - UpkeepGasLimit: *config.Keeper.Common.UpkeepGasLimit, + NumberOfUpkeeps: *config.Automation.Benchmark.NumberOfUpkeeps, + CheckGasToBurn: *config.Automation.Benchmark.CheckGasToBurn, + PerformGasToBurn: *config.Automation.Benchmark.PerformGasToBurn, + BlockRange: *config.Automation.Benchmark.BlockRange, + BlockInterval: *config.Automation.Benchmark.BlockInterval, + UpkeepGasLimit: *config.Automation.Benchmark.UpkeepGasLimit, FirstEligibleBuffer: 1, }, - Contracts: &testsetups.PreDeployedContracts{ - RegistrarAddress: *config.Keeper.Common.RegistrarAddress, - RegistryAddress: *config.Keeper.Common.RegistryAddress, - LinkTokenAddress: *config.Keeper.Common.LinkTokenAddress, - EthFeedAddress: *config.Keeper.Common.EthFeedAddress, - GasFeedAddress: *config.Keeper.Common.GasFeedAddress, - }, ChainlinkNodeFunding: benchmarkTestNetwork.funding, UpkeepSLA: benchmarkTestNetwork.upkeepSLA, BlockTime: benchmarkTestNetwork.blockTime, DeltaStage: benchmarkTestNetwork.deltaStage, - ForceSingleTxnKey: *config.Keeper.Common.ForceSingleTxKey, - DeleteJobsOnEnd: *config.Keeper.Common.DeleteJobsOnEnd, + ForceSingleTxnKey: *config.Automation.Benchmark.ForceSingleTxKey, + DeleteJobsOnEnd: *config.Automation.Benchmark.DeleteJobsOnEnd, }, ) t.Cleanup(func() { if err = actions.TeardownRemoteSuite(keeperBenchmarkTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error when tearing down remote suite") + } else { + if *config.GetAutomationConfig().Benchmark.DeleteJobsOnEnd { + err := testEnvironment.Client.RemoveNamespace(testEnvironment.Cfg.Namespace) + if err != nil { + l.Error().Err(err).Msg("Error removing namespace") + } + } } }) - keeperBenchmarkTest.Setup(testEnvironment, &config) + keeperBenchmarkTest.Setup(testEnvironment, config) keeperBenchmarkTest.Run() } func addRegistry(config *tc.TestConfig) []ethcontracts.KeeperRegistryVersion { - switch *config.Keeper.Common.RegistryToTest { - case "1_1": - return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_1_1} - case "1_2": - return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_1_2} - case "1_3": - return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_1_3} + switch *config.Automation.Benchmark.RegistryToTest { case "2_0": return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_0} case "2_1": @@ -162,19 +142,14 @@ func addRegistry(config *tc.TestConfig) []ethcontracts.KeeperRegistryVersion { return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_2} case "2_3": return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_3} - case "2_0-1_3": - return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_0, ethcontracts.RegistryVersion_1_3} - case "2_1-2_0-1_3": - return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_1, - ethcontracts.RegistryVersion_2_0, ethcontracts.RegistryVersion_1_3} case "2_2-2_1": return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_2, ethcontracts.RegistryVersion_2_1} case "2_0-Multiple": - return repeatRegistries(ethcontracts.RegistryVersion_2_0, *config.Keeper.Common.NumberOfRegistries) + return repeatRegistries(ethcontracts.RegistryVersion_2_0, *config.Automation.Benchmark.NumberOfRegistries) case "2_1-Multiple": - return repeatRegistries(ethcontracts.RegistryVersion_2_1, *config.Keeper.Common.NumberOfRegistries) + return repeatRegistries(ethcontracts.RegistryVersion_2_1, *config.Automation.Benchmark.NumberOfRegistries) case "2_2-Multiple": - return repeatRegistries(ethcontracts.RegistryVersion_2_2, *config.Keeper.Common.NumberOfRegistries) + return repeatRegistries(ethcontracts.RegistryVersion_2_2, *config.Automation.Benchmark.NumberOfRegistries) default: return []ethcontracts.KeeperRegistryVersion{ethcontracts.RegistryVersion_2_0} } @@ -270,13 +245,13 @@ var networkConfig = map[string]NetworkConfig{ }, } -func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { +func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { l := logging.GetTestLogger(t) testNetwork := networks.MustGetSelectedNetworkConfig(keeperTestConfig.GetNetworkConfig())[0] // Environment currently being used to run benchmark test on blockTime := "1" - numberOfNodes := *keeperTestConfig.GetKeeperConfig().Common.NumberOfNodes + numberOfNodes := *keeperTestConfig.GetAutomationConfig().General.NumberOfNodes - if strings.Contains(*keeperTestConfig.GetKeeperConfig().Common.RegistryToTest, "2_") { + if strings.Contains(*keeperTestConfig.GetAutomationConfig().Benchmark.RegistryToTest, "2_") { numberOfNodes++ } @@ -290,7 +265,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenc "automation-%s-%s-%s", strings.ToLower(strings.Join(keeperTestConfig.GetConfigurationNames(), "")), strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), - strings.ReplaceAll(strings.ToLower(*keeperTestConfig.GetKeeperConfig().Common.RegistryToTest), "_", "-"), + strings.ReplaceAll(strings.ToLower(*keeperTestConfig.GetAutomationConfig().Benchmark.RegistryToTest), "_", "-"), ), Test: t, PreventPodEviction: true, @@ -341,18 +316,19 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenc }, })) } - - // TODO we need to update the image in CTF, the old one is not available anymore - // deploy blockscout if running on simulated - // if testNetwork.Simulated { - // testEnvironment. - // AddChart(blockscout.New(&blockscout.Props{ - // Name: "geth-blockscout", - // WsURL: testNetwork.URLs[0], - // HttpURL: testNetwork.HTTPURLs[0]})) - // } - err := testEnvironment.Run() - require.NoError(t, err, "Error launching test environment") + var err error + if testNetwork.Simulated { + // TODO we need to update the image in CTF, the old one is not available anymore + // deploy blockscout if running on simulated + //testEnvironment. + // AddChart(blockscout.New(&blockscout.Props{ + // Name: "geth-blockscout", + // WsURL: testNetwork.URLs[0], + // HttpURL: testNetwork.HTTPURLs[0]})) + // Need to setup geth node before setting up chainlink nodes + err = testEnvironment.Run() + require.NoError(t, err, "Error launching test environment") + } if testEnvironment.WillUseRemoteRunner() { return testEnvironment, testNetwork diff --git a/integration-tests/ccip-tests/Makefile b/integration-tests/ccip-tests/Makefile index 5a40f7ca0f6..2702c36b027 100644 --- a/integration-tests/ccip-tests/Makefile +++ b/integration-tests/ccip-tests/Makefile @@ -1,11 +1,13 @@ -## To Override the default config, and secret config: -# example usage: make set_config override_toml=../config/config.toml secret_toml=../config/secret.toml network_config_toml=../config/network.toml +## To Override the default config: +# example usage: make set_config override_toml=../config/config.toml network_config_toml=../config/network.toml .PHONY: set_config set_config: if [ -s "$(override_toml)" ]; then \ echo "Overriding config with $(override_toml)"; \ - echo "export BASE64_CCIP_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" > ./testconfig/override/.env; \ - echo "export TEST_BASE64_CCIP_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" >> ./testconfig/override/.env; \ + echo "export BASE64_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" > ./testconfig/override/.env; \ + echo "export TEST_BASE64_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" >> ./testconfig/override/.env; \ + echo "BASE64_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" > ./testconfig/override/debug.env; \ + echo "TEST_BASE64_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" >> ./testconfig/override/debug.env; \ else \ echo "No override config found, using default config"; \ echo > ./testconfig/override/.env; \ @@ -15,14 +17,15 @@ set_config: echo "export BASE64_NETWORK_CONFIG=$$(base64 -i $(network_config_toml))" >> ./testconfig/override/.env; \ fi - @echo "setting secret config with $(secret_toml)" - @echo "export BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" >> ./testconfig/override/.env - @echo "export TEST_BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" >> ./testconfig/override/.env - @echo "BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" > ./testconfig/override/debug.env - @echo "TEST_BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" >> ./testconfig/override/debug.env + @echo "Checking for test secrets file in ~/.testsecrets..."; + @if [ ! -f ~/.testsecrets ]; then \ + echo "WARNING: ~/.testsecrets file not found. No test secrets will be set. To set test secrets, refer to ./testconfig/examples/.testsecrets.example for the list of secrets and instruction how to set them up."; \ + else \ + echo "Test secrets will be loaded from ~/.testsecrets file."; \ + fi -# example usage: make test_load_ccip testimage=chainlink-ccip-tests:latest testname=TestLoadCCIPStableRPS override_toml=./testconfig/override/config.toml secret_toml=./testconfig/tomls/secrets.toml network_config_toml=../config/network.toml +# example usage: make test_load_ccip testimage=chainlink-ccip-tests:latest testname=TestLoadCCIPStableRPS override_toml=./testconfig/override/config.toml network_config_toml=../config/network.toml .PHONY: test_load_ccip test_load_ccip: set_config source ./testconfig/override/.env && \ @@ -36,7 +39,7 @@ test_load_ccip: set_config go test -timeout 24h -count=1 -v -run ^$(testname)$$ ./load -# example usage: make test_smoke_ccip testimage=chainlink-ccip-tests:latest testname=TestSmokeCCIPForBidirectionalLane override_toml=../testconfig/override/config.toml secret_toml=./testconfig/tomls/secrets.toml network_config_toml=../config/network.toml +# example usage: make test_smoke_ccip testimage=chainlink-ccip-tests:latest testname=TestSmokeCCIPForBidirectionalLane override_toml=../testconfig/override/config.toml network_config_toml=../config/network.toml .PHONY: test_smoke_ccip test_smoke_ccip: set_config source ./testconfig/override/.env && \ @@ -48,13 +51,13 @@ test_smoke_ccip: set_config go test -timeout 24h -count=1 -v -run ^$(testname)$$ ./smoke # run ccip smoke tests with default config; explicitly sets the override config to empty -# example usage: make test_smoke_ccip_default testname=TestSmokeCCIPForBidirectionalLane secret_toml=./testconfig/tomls/secrets.toml +# example usage: make test_smoke_ccip_default testname=TestSmokeCCIPForBidirectionalLane .PHONY: test_smoke_ccip_default test_smoke_ccip_default: set_config source ./testconfig/override/.env && \ DATABASE_URL=postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable \ - BASE64_CCIP_CONFIG_OVERRIDE="" \ - TEST_BASE64_CCIP_CONFIG_OVERRIDE="" \ + BASE64_CONFIG_OVERRIDE="" \ + TEST_BASE64_CONFIG_OVERRIDE="" \ ENV_JOB_IMAGE="" \ TEST_SUITE=smoke \ TEST_ARGS="-test.timeout 900h" \ diff --git a/integration-tests/ccip-tests/README.md b/integration-tests/ccip-tests/README.md index 0e000561fa4..a4255928949 100644 --- a/integration-tests/ccip-tests/README.md +++ b/integration-tests/ccip-tests/README.md @@ -8,7 +8,7 @@ CCIP tests are designed to be highly configurable. Instead of writing many tests 1. Default test input - set via TOML - If no specific input is set; the tests will run with default inputs mentioned in [default.toml](./testconfig/tomls/ccip-default.toml). Please refer to the [testconfig README](../testconfig/README.md) for a more detailed look at how testconfig works. -2. If you want to run your test with a different config, you can override the default inputs. You can either write an [overrides.toml](../testconfig/README.md#configuration-and-overrides) file, or set the env var `BASE64_CCIP_CONFIG_OVERRIDE` containing the base64 encoded TOML file content with updated test input parameters. +2. If you want to run your test with a different config, you can override the default inputs. You can either write an [overrides.toml](../testconfig/README.md#configuration-and-overrides) file, or set the env var `BASE64_CONFIG_OVERRIDE` containing the base64 encoded TOML file content with updated test input parameters. For example, if you want to override the `Network` input in test and want to run your test on `avalanche testnet` and `arbitrum goerli` network, you need to: 1. Create a TOML file with the following content: @@ -20,10 +20,10 @@ For example, if you want to override the `Network` input in test and want to run ``` 2. Encode it using the `base64` command - 3. Set the env var `BASE64_CCIP_CONFIG_OVERRIDE` with the encoded content. + 3. Set the env var `BASE64_CONFIG_OVERRIDE` with the encoded content. ```bash - export BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -i ) + export BASE64_CONFIG_OVERRIDE=$(base64 -i ) ``` [mainnet.toml](./testconfig/override/mainnet.toml), [override.toml](./testconfig/examples/override.toml.example) are some of the sample override TOML files. @@ -31,37 +31,20 @@ For example, if you want to override the `Network` input in test and want to run For example - In order to run the smoke test (TestSmokeCCIPForBidirectionalLane) on mainnet, run the test with following env var set: ```bash - export BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -i ./testconfig/override/mainnet.toml) + 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 [sample-secrets.toml](./testconfig/examples/secrets.toml.example) for the list of secrets that are mandatory to run the tests. +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. - If you are running tests in simulated networks no network specific secrets are required. here is a sample secrets.toml file, for running the tests in simulated networks, with the chainlink image and tag set as secrets: - ```toml - [CCIP] - [CCIP.Env] - # ChainlinkImage is mandatory for all tests. - [CCIP.Env.NewCLCluster] - [CCIP.Env.NewCLCluster.Common] - [CCIP.Env.NewCLCluster.Common.ChainlinkImage] - image = "chainlink-ccip" - version = "latest" - ``` - - We consider secrets similar to test input overrides and encode them using `base64` command. - Once you have the secrets.toml file, you can encode it using `base64` command (similar to step 2) and set the env var `BASE64_CCIP_SECRETS_CONFIG` with the encoded content. - - ```bash - export BASE64_CCIP_SECRETS_CONFIG=$(base64 -i ./testconfig/tomls/secrets.toml) - ``` - **Please note that the secrets should NOT be checked in to the repo and should be kept locally.** -We recommend against changing the content of [sample-secrets.toml](./testconfig/examples/secrets.toml.example). Please create a new file and set it as the secrets file. -You can run the command to ignore the changes to the file. +We recommend against changing the content of [secrets.toml.example](./testconfig/examples/secrets.toml.example). Please create a new file and set it as the secrets file. + +You can run this command to ignore any changes to the file. ```bash git update-index --skip-worktree @@ -136,3 +119,9 @@ flowchart ### Using Remote Kubernetes Cluster For running more complex and intensive tests (like load and chaos tests) you need to connect the test to a Kubernetes cluster. These tests have more complex setup and running instructions. We endeavor to make these easier to run and configure, but for the time being please seek a member of the QA/Test Tooling team if you want to run these. + +### Live environment testing + +To run against live environments, use the configs available under [beta-testnet](./testconfig/tomls/beta-testnet) +or [prod-testnet](./testconfig/tomls/prod-testnet) directory. Prod testnet has configs for smoke, load and +soak test separately and beta-testnet has smoke and soak combined. \ No newline at end of file diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 7594a9dc447..da2e870f3ec 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -31,19 +31,19 @@ import ( "golang.org/x/exp/rand" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" chainselectors "github.com/smartcontractkit/chain-selectors" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/foundry" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/foundry" + "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/integration-tests/ccip-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts/laneconfig" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" @@ -52,13 +52,13 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/arm_contract" "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/evm_2_evm_onramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_arm_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" + "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/services/ocr2/plugins/ccip/config" @@ -165,7 +165,7 @@ type CCIPCommon struct { NoOfTokensNeedingDynamicPrice int BridgeTokenPools []*contracts.TokenPool RateLimiterConfig contracts.RateLimiterConfig - ARMContract *common.Address + RMNContract *common.Address ARM *contracts.ARM // populate only if the ARM contracts is not a mock and can be used to verify various ARM events; keep this nil for mock ARM Router *contracts.Router PriceRegistry *contracts.PriceRegistry @@ -185,6 +185,7 @@ type CCIPCommon struct { gasUpdateWatcherMu *sync.Mutex gasUpdateWatcher map[uint64]*big.Int // key - destchain id; value - timestamp of update GasUpdateEvents []contracts.GasUpdateEvent + AllowOutOfOrder bool } // FreeUpUnusedSpace sets nil to various elements of ccipModule which are only used @@ -202,10 +203,10 @@ func (ccipModule *CCIPCommon) UnvoteToCurseARM() error { if ccipModule.ARM != nil { return fmt.Errorf("real ARM deployed. cannot curse through test") } - if ccipModule.ARMContract == nil { + if ccipModule.RMNContract == nil { return fmt.Errorf("no ARM contract is set") } - arm, err := mock_arm_contract.NewMockARMContract(*ccipModule.ARMContract, ccipModule.ChainClient.Backend()) + arm, err := mock_rmn_contract.NewMockRMNContract(*ccipModule.RMNContract, ccipModule.ChainClient.Backend()) if err != nil { return fmt.Errorf("error instantiating arm %w", err) } @@ -213,7 +214,7 @@ func (ccipModule *CCIPCommon) UnvoteToCurseARM() error { if err != nil { return fmt.Errorf("error getting owners for ARM OwnerUnvoteToCurse %w", err) } - tx, err := arm.OwnerUnvoteToCurse0(opts, []mock_arm_contract.RMNUnvoteToCurseRecord{}) + tx, err := arm.OwnerUnvoteToCurse0(opts, []mock_rmn_contract.RMNUnvoteToCurseRecord{}) if err != nil { return fmt.Errorf("error in calling OwnerUnvoteToCurse %w", err) } @@ -231,10 +232,10 @@ func (ccipModule *CCIPCommon) IsCursed() (bool, error) { if ccipModule.ARM != nil { return false, fmt.Errorf("real ARM deployed. cannot validate cursing") } - if ccipModule.ARMContract == nil { + if ccipModule.RMNContract == nil { return false, fmt.Errorf("no ARM contract is set") } - arm, err := mock_arm_contract.NewMockARMContract(*ccipModule.ARMContract, ccipModule.ChainClient.Backend()) + arm, err := mock_rmn_contract.NewMockRMNContract(*ccipModule.RMNContract, ccipModule.ChainClient.Backend()) if err != nil { return false, fmt.Errorf("error instantiating arm %w", err) } @@ -245,10 +246,10 @@ func (ccipModule *CCIPCommon) CurseARM() (*types.Transaction, error) { if ccipModule.ARM != nil { return nil, fmt.Errorf("real ARM deployed. cannot curse through test") } - if ccipModule.ARMContract == nil { + if ccipModule.RMNContract == nil { return nil, fmt.Errorf("no ARM contract is set") } - arm, err := mock_arm_contract.NewMockARMContract(*ccipModule.ARMContract, ccipModule.ChainClient.Backend()) + arm, err := mock_rmn_contract.NewMockRMNContract(*ccipModule.RMNContract, ccipModule.ChainClient.Backend()) if err != nil { return nil, fmt.Errorf("error instantiating arm %w", err) } @@ -273,6 +274,9 @@ func (ccipModule *CCIPCommon) CurseARM() (*types.Transaction, error) { func (ccipModule *CCIPCommon) LoadContractAddresses(conf *laneconfig.LaneConfig, noOfTokens *int) { if conf != nil { + if conf.AllowOutOfOrder { + ccipModule.AllowOutOfOrder = true + } if common.IsHexAddress(conf.FeeToken) { ccipModule.FeeToken = &contracts.LinkToken{ EthAddress: common.HexToAddress(conf.FeeToken), @@ -291,7 +295,7 @@ func (ccipModule *CCIPCommon) LoadContractAddresses(conf *laneconfig.LaneConfig, } if common.IsHexAddress(conf.ARM) { addr := common.HexToAddress(conf.ARM) - ccipModule.ARMContract = &addr + ccipModule.RMNContract = &addr if !conf.IsMockARM { ccipModule.ARM = &contracts.ARM{ EthAddress: addr, @@ -528,8 +532,8 @@ func (ccipModule *CCIPCommon) WaitForPriceUpdates( // of price update events and add the event details to watchers. It subscribes to 'UsdPerUnitGasUpdated' // and 'UsdPerTokenUpdated' event. func (ccipModule *CCIPCommon) WatchForPriceUpdates(ctx context.Context, lggr *zerolog.Logger) error { - gasUpdateEventLatest := make(chan *price_registry.PriceRegistryUsdPerUnitGasUpdated) - tokenUpdateEvent := make(chan *price_registry.PriceRegistryUsdPerTokenUpdated) + gasUpdateEventLatest := make(chan *fee_quoter.FeeQuoterUsdPerUnitGasUpdated) + tokenUpdateEvent := make(chan *fee_quoter.FeeQuoterUsdPerTokenUpdated) sub := event.Resubscribe(DefaultResubscriptionTimeout, func(_ context.Context) (event.Subscription, error) { lggr.Info().Msg("Subscribing to UsdPerUnitGasUpdated event") eventSub, err := ccipModule.PriceRegistry.WatchUsdPerUnitGasUpdated(nil, gasUpdateEventLatest, nil) @@ -729,7 +733,7 @@ func (ccipModule *CCIPCommon) WriteLaneConfig(conf *laneconfig.LaneConfig) { FeeToken: ccipModule.FeeToken.Address(), BridgeTokens: btAddresses, BridgeTokenPools: btpAddresses, - ARM: ccipModule.ARMContract.Hex(), + ARM: ccipModule.RMNContract.Hex(), Router: ccipModule.Router.Address(), PriceRegistry: ccipModule.PriceRegistry.Address(), PriceAggregators: priceAggrs, @@ -783,18 +787,18 @@ func (ccipModule *CCIPCommon) DeployContracts( ccipModule.LoadContractAddresses(conf, &noOfTokens) if ccipModule.ARM != nil { - arm, err := cd.NewARMContract(ccipModule.ARM.EthAddress) + arm, err := cd.NewRMNContract(ccipModule.ARM.EthAddress) if err != nil { return fmt.Errorf("getting new ARM contract shouldn't fail %w", err) } ccipModule.ARM = arm } else { // deploy a mock ARM contract - if ccipModule.ARMContract == nil { + if ccipModule.RMNContract == nil { if ccipModule.ExistingDeployment { return fmt.Errorf("ARM contract address is not provided in lane config") } - ccipModule.ARMContract, err = cd.DeployMockARMContract() + ccipModule.RMNContract, err = cd.DeployMockRMNContract() if err != nil { return fmt.Errorf("deploying mock ARM contract shouldn't fail %w", err) } @@ -827,7 +831,7 @@ func (ccipModule *CCIPCommon) DeployContracts( if ccipModule.ExistingDeployment { return fmt.Errorf("router contract address is not provided in lane config") } - ccipModule.Router, err = cd.DeployRouter(ccipModule.WrappedNative, *ccipModule.ARMContract) + ccipModule.Router, err = cd.DeployRouter(ccipModule.WrappedNative, *ccipModule.RMNContract) if err != nil { return fmt.Errorf("deploying router shouldn't fail %w", err) } @@ -979,7 +983,7 @@ func (ccipModule *CCIPCommon) DeployContracts( if ccipModule.TokenTransmitter == nil { return fmt.Errorf("TokenTransmitter contract address is not provided") } - usdcPool, err := ccipModule.tokenDeployer.DeployUSDCTokenPoolContract(token.Address(), *ccipModule.TokenMessenger, *ccipModule.ARMContract, ccipModule.Router.Instance.Address()) + usdcPool, err := ccipModule.tokenDeployer.DeployUSDCTokenPoolContract(token.Address(), *ccipModule.TokenMessenger, *ccipModule.RMNContract, ccipModule.Router.Instance.Address()) if err != nil { return fmt.Errorf("deploying bridge Token pool(usdc) shouldn't fail %w", err) } @@ -987,7 +991,7 @@ func (ccipModule *CCIPCommon) DeployContracts( ccipModule.BridgeTokenPools = append(ccipModule.BridgeTokenPools, usdcPool) } else { // deploy lock release token pool in case of non-usdc deployment - btp, err := ccipModule.tokenDeployer.DeployLockReleaseTokenPoolContract(token.Address(), *ccipModule.ARMContract, ccipModule.Router.Instance.Address()) + btp, err := ccipModule.tokenDeployer.DeployLockReleaseTokenPoolContract(token.Address(), *ccipModule.RMNContract, ccipModule.Router.Instance.Address()) if err != nil { return fmt.Errorf("deploying bridge Token pool(lock&release) shouldn't fail %w", err) } @@ -1178,7 +1182,7 @@ func NewCCIPCommonFromConfig( } var arm *contracts.ARM if newCCIPModule.ARM != nil { - arm, err = newCD.NewARMContract(*newCCIPModule.ARMContract) + arm, err = newCD.NewRMNContract(*newCCIPModule.RMNContract) if err != nil { return nil, err } @@ -1414,7 +1418,7 @@ func (sourceCCIP *SourceCCIPModule) DeployContracts(lane *laneconfig.LaneConfig) sourceChainSelector, sourceCCIP.DestChainSelector, tokensAndPools, - *sourceCCIP.Common.ARMContract, + *sourceCCIP.Common.RMNContract, sourceCCIP.Common.Router.EthAddress, sourceCCIP.Common.PriceRegistry.EthAddress, tokenAdminReg, @@ -1616,6 +1620,8 @@ func (sourceCCIP *SourceCCIPModule) AssertSendRequestedLogFinalized( return finalizedAt, finalizedBlockNum.Uint64(), nil } +// IsRequestTriggeredWithinTimeframe monitors for live events occurring within the specified timeframe. +// Live events refer to those that are triggered after subscribing to the CCIP Send Requested event. func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe *commonconfig.Duration) *time.Time { if timeframe == nil { return nil @@ -1626,7 +1632,7 @@ func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe if sendRequestedEvents, exists := value.([]*evm_2_evm_onramp.EVM2EVMOnRampCCIPSendRequested); exists { for _, sendRequestedEvent := range sendRequestedEvents { raw := sendRequestedEvent.Raw - hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(raw.BlockNumber))) + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(raw.BlockNumber)) if err == nil { if hdr.Timestamp.After(lastSeenTimestamp) { foundAt = pointer.ToTime(hdr.Timestamp) @@ -1640,6 +1646,48 @@ func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe return foundAt } +// 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) { + if timeframe == nil { + return nil, nil + } + //var foundAt *time.Time + latestBlock, err := sourceCCIP.Common.ChainClient.LatestBlockNumber(ctx) + if err != nil { + return nil, fmt.Errorf("error while getting latest source block number. Error: %w", err) + } + avgBlockTime, err := sourceCCIP.Common.ChainClient.AvgBlockTime(ctx) + if err != nil { + return nil, fmt.Errorf("error while getting average source block time. Error: %w", err) + } + filterFromBlock := latestBlock - uint64(timeframe.Duration()/avgBlockTime) + + onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(sourceCCIP.OnRamp.EthAddress.Hex()), + sourceCCIP.Common.ChainClient.Backend()) + if err != nil { + return nil, fmt.Errorf("error while on ramp contract. Error: %w", err) + } + iterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: filterFromBlock, + }) + if err != nil { + return nil, fmt.Errorf("error while filtering CCIP send requested starting block number: %d. Error: %w", filterFromBlock, err) + } + defer func() { + _ = iterator.Close() + }() + if iterator.Next() { + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(iterator.Event.Raw.BlockNumber))) + if err != nil { + return nil, fmt.Errorf("error getting header for block: %d, Error: %w", iterator.Event.Raw.BlockNumber, err) + } + return pointer.ToTime(hdr.Timestamp), nil + } + + return nil, nil +} + func (sourceCCIP *SourceCCIPModule) AssertEventCCIPSendRequested( lggr *zerolog.Logger, txHash string, @@ -1709,6 +1757,7 @@ func (sourceCCIP *SourceCCIPModule) AssertEventCCIPSendRequested( // CCIPMsg constructs the message for a CCIP request func (sourceCCIP *SourceCCIPModule) CCIPMsg( receiver common.Address, + allowOutOfOrder bool, gasLimit *big.Int, ) (router.ClientEVM2AnyMessage, error) { length := sourceCCIP.MsgDataLength @@ -1750,9 +1799,17 @@ func (sourceCCIP *SourceCCIPModule) CCIPMsg( return router.ClientEVM2AnyMessage{}, fmt.Errorf("failed encoding the receiver address: %w", err) } - extraArgsV1, err := testhelpers.GetEVMExtraArgsV1(gasLimit, false) + var extraArgs []byte + matchErr := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ + contracts.OnRampContract: contracts.V1_5_0, + }) + if matchErr != nil { + extraArgs, err = testhelpers.GetEVMExtraArgsV1(gasLimit, false) + } else { + extraArgs, err = testhelpers.GetEVMExtraArgsV2(gasLimit, allowOutOfOrder) + } if err != nil { - return router.ClientEVM2AnyMessage{}, fmt.Errorf("failed encoding the options field: %w", err) + return router.ClientEVM2AnyMessage{}, fmt.Errorf("failed getting extra args: %w", err) } // form the message for transfer return router.ClientEVM2AnyMessage{ @@ -1760,7 +1817,7 @@ func (sourceCCIP *SourceCCIPModule) CCIPMsg( Data: []byte(data), TokenAmounts: tokenAndAmounts, FeeToken: common.HexToAddress(sourceCCIP.Common.FeeToken.Address()), - ExtraArgs: extraArgsV1, + ExtraArgs: extraArgs, }, nil } @@ -1775,7 +1832,7 @@ func (sourceCCIP *SourceCCIPModule) SendRequest( return common.Hash{}, d, nil, fmt.Errorf("failed getting the chain selector: %w", err) } // form the message for transfer - msg, err := sourceCCIP.CCIPMsg(receiver, gasLimit) + msg, err := sourceCCIP.CCIPMsg(receiver, sourceCCIP.Common.AllowOutOfOrder, gasLimit) if err != nil { return common.Hash{}, d, nil, fmt.Errorf("failed forming the ccip msg: %w", err) } @@ -2025,7 +2082,7 @@ func (destCCIP *DestCCIPModule) DeployContracts( destCCIP.SourceChainSelector, destChainSelector, sourceCCIP.OnRamp.EthAddress, - *destCCIP.Common.ARMContract, + *destCCIP.Common.RMNContract, ) if err != nil { return fmt.Errorf("deploying commitstore shouldn't fail %w", err) @@ -2070,7 +2127,7 @@ func (destCCIP *DestCCIPModule) DeployContracts( destCCIP.Common.RateLimiterConfig, []common.Address{}, []common.Address{}, - *destCCIP.Common.ARMContract, + *destCCIP.Common.RMNContract, tokenAdminReg, ) if err != nil { @@ -2218,7 +2275,7 @@ func (destCCIP *DestCCIPModule) AssertNoReportAcceptedEventReceived(lggr *zerolo e, exists := value.(*evm_2_evm_offramp.EVM2EVMOffRampExecutionStateChanged) if exists { vLogs := e.Raw - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, new(big.Int).SetUint64(vLogs.BlockNumber)) if err != nil { return true } @@ -2259,7 +2316,7 @@ func (destCCIP *DestCCIPModule) AssertNoExecutionStateChangedEventReceived( e, exists := value.(*contracts.EVM2EVMOffRampExecutionStateChanged) if exists { vLogs := e.LogInfo - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, new(big.Int).SetUint64(vLogs.BlockNumber)) if err != nil { return true } @@ -2288,7 +2345,7 @@ func (destCCIP *DestCCIPModule) AssertEventExecutionStateChanged( reqStat *testreporters.RequestStat, execState testhelpers.MessageExecutionState, ) (uint8, error) { - lggr.Info().Int64("seqNum", int64(seqNum)).Str("Timeout", timeout.String()).Msg("Waiting for ExecutionStateChanged event") + lggr.Info().Uint64("seqNum", seqNum).Str("Timeout", timeout.String()).Msg("Waiting for ExecutionStateChanged event") timer := time.NewTimer(timeout) defer timer.Stop() ticker := time.NewTicker(time.Second) @@ -2306,7 +2363,7 @@ func (destCCIP *DestCCIPModule) AssertEventExecutionStateChanged( destCCIP.ExecStateChangedWatcher.Delete(seqNum) vLogs := e.LogInfo receivedAt := time.Now().UTC() - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(vLogs.BlockNumber)) if err == nil { receivedAt = hdr.Timestamp } @@ -2319,7 +2376,7 @@ func (destCCIP *DestCCIPModule) AssertEventExecutionStateChanged( gasUsed = receipt.GasUsed } if testhelpers.MessageExecutionState(e.State) == execState { - lggr.Info().Int64("seqNum", int64(seqNum)).Uint8("ExecutionState", e.State).Msg("ExecutionStateChanged event received") + lggr.Info().Uint64("seqNum", seqNum).Uint8("ExecutionState", e.State).Msg("ExecutionStateChanged event received") reqStat.UpdateState(lggr, seqNum, testreporters.ExecStateChanged, receivedAt.Sub(timeNow), testreporters.Success, &testreporters.TransactionStats{ @@ -2363,7 +2420,7 @@ func (destCCIP *DestCCIPModule) AssertEventReportAccepted( prevEventAt time.Time, reqStat *testreporters.RequestStat, ) (*contracts.CommitStoreReportAccepted, time.Time, error) { - lggr.Info().Int64("seqNum", int64(seqNum)).Str("Timeout", timeout.String()).Msg("Waiting for ReportAccepted event") + lggr.Info().Uint64("seqNum", seqNum).Str("Timeout", timeout.String()).Msg("Waiting for ReportAccepted event") timer := time.NewTimer(timeout) defer timer.Stop() resetTimerCount := 0 @@ -2379,7 +2436,7 @@ func (destCCIP *DestCCIPModule) AssertEventReportAccepted( // if the value is processed, delete it from the map destCCIP.ReportAcceptedWatcher.Delete(seqNum) receivedAt := time.Now().UTC() - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(reportAccepted.LogInfo.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(reportAccepted.LogInfo.BlockNumber)) if err == nil { receivedAt = hdr.Timestamp } @@ -2488,7 +2545,7 @@ func (destCCIP *DestCCIPModule) AssertReportBlessed( // if the value is processed, delete it from the map destCCIP.ReportBlessedBySeqNum.Delete(seqNum) } - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(vLogs.BlockNumber)) if err == nil { receivedAt = hdr.Timestamp } @@ -2536,7 +2593,7 @@ func (destCCIP *DestCCIPModule) AssertSeqNumberExecuted( timeNow time.Time, reqStat *testreporters.RequestStat, ) error { - lggr.Info().Int64("seqNum", int64(seqNumberBefore)).Str("Timeout", timeout.String()).Msg("Waiting to be processed by commit store") + lggr.Info().Uint64("seqNum", seqNumberBefore).Str("Timeout", timeout.String()).Msg("Waiting to be processed by commit store") timer := time.NewTimer(timeout) defer timer.Stop() resetTimerCount := 0 @@ -2793,7 +2850,11 @@ func (lane *CCIPLane) AddToSentReqs(txHash common.Hash, reqStats []*testreporter func (lane *CCIPLane) Multicall(noOfRequests int, multiSendAddr common.Address) error { var ccipMultipleMsg []contracts.CCIPMsgData feeToken := common.HexToAddress(lane.Source.Common.FeeToken.Address()) - genericMsg, err := lane.Source.CCIPMsg(lane.Dest.ReceiverDapp.EthAddress, big.NewInt(DefaultDestinationGasLimit)) + genericMsg, err := lane.Source.CCIPMsg( + lane.Dest.ReceiverDapp.EthAddress, + lane.Source.Common.AllowOutOfOrder, + big.NewInt(DefaultDestinationGasLimit), + ) if err != nil { return fmt.Errorf("failed to form the ccip message: %w", err) } @@ -2885,10 +2946,7 @@ func (lane *CCIPLane) Multicall(noOfRequests int, multiSendAddr common.Address) func (lane *CCIPLane) SendRequests(noOfRequests int, gasLimit *big.Int) error { for i := 1; i <= noOfRequests; i++ { stat := testreporters.NewCCIPRequestStats(int64(lane.NumberOfReq+i), lane.SourceNetworkName, lane.DestNetworkName) - txHash, txConfirmationDur, fee, err := lane.Source.SendRequest( - lane.Dest.ReceiverDapp.EthAddress, - gasLimit, - ) + txHash, txConfirmationDur, fee, err := lane.Source.SendRequest(lane.Dest.ReceiverDapp.EthAddress, gasLimit) if err != nil { stat.UpdateState(lane.Logger, 0, testreporters.TX, txConfirmationDur, testreporters.Failure, nil) return fmt.Errorf("could not send request: %w", err) @@ -3046,6 +3104,7 @@ func (lane *CCIPLane) ExecuteManually(options ...ManualExecutionOption) error { // validationOptions are used in the ValidateRequests function to specify which phase is expected to fail and how type validationOptions struct { + expectAnyPhaseToFail bool phaseExpectedToFail testreporters.Phase // the phase expected to fail expectedErrorMessage string // if provided, we're looking for a specific error message timeout time.Duration // timeout for the validation @@ -3087,6 +3146,18 @@ func ExpectPhaseToFail(phase testreporters.Phase, phaseSpecificOptions ...PhaseS } } +// ExpectAnyPhaseToFail expects any phase in CCIP transaction to fail. +func ExpectAnyPhaseToFail(phaseSpecificOptions ...PhaseSpecificValidationOptionFunc) ValidationOptionFunc { + return func(opts *validationOptions) { + opts.expectAnyPhaseToFail = true + for _, f := range phaseSpecificOptions { + if f != nil { + f(opts) + } + } + } +} + // ValidateRequests validates all sent request events. // If you expect a specific phase to fail, you can pass a validationOptionFunc to specify exactly which one. // If not, just pass in nil. @@ -3210,6 +3281,11 @@ func isPhaseValid( opts validationOptions, err error, ) (shouldComplete bool, validationError error) { + if opts.expectAnyPhaseToFail && err != nil { + logmsg := logger.Info().Str("Failed with Error", err.Error()).Str("Phase", string(currentPhase)) + logmsg.Msg("Phase failed, as expected") + return true, nil + } // If no phase is expected to fail or the current phase is not the one expected to fail, we just return what we were given if opts.phaseExpectedToFail == "" || currentPhase != opts.phaseExpectedToFail { return err != nil, err @@ -3218,13 +3294,14 @@ func isPhaseValid( return true, fmt.Errorf("expected phase '%s' to fail, but it passed", opts.phaseExpectedToFail) } logmsg := logger.Info().Str("Failed with Error", err.Error()).Str("Phase", string(currentPhase)) + if opts.expectedErrorMessage != "" { if !strings.Contains(err.Error(), opts.expectedErrorMessage) { return true, fmt.Errorf("expected phase '%s' to fail with error message '%s' but got error '%s'", currentPhase, opts.expectedErrorMessage, err.Error()) } logmsg.Str("Expected Error Message", opts.expectedErrorMessage) } - logmsg.Msg("Expected phase to fail and it did") + logmsg.Msg("Phase failed, as expected") return true, nil } @@ -3394,7 +3471,7 @@ func (lane *CCIPLane) StartEventWatchers() error { }(reportAccSub) if lane.Dest.Common.ARM != nil { - reportBlessedEvent := make(chan *arm_contract.ARMContractTaggedRootBlessed) + reportBlessedEvent := make(chan *rmn_contract.RMNContractTaggedRootBlessed) blessedSub := event.Resubscribe(DefaultResubscriptionTimeout, func(_ context.Context) (event.Subscription, error) { sub, err := lane.Dest.Common.ARM.Instance.WatchTaggedRootBlessed(nil, reportBlessedEvent, nil) if err != nil { @@ -3496,6 +3573,7 @@ func (lane *CCIPLane) DeployNewCCIPLane( srcConf = lane.SrcNetworkLaneCfg destConf = lane.DstNetworkLaneCfg commitAndExecOnSameDON = pointer.GetBool(testConf.CommitAndExecuteOnSameDON) + allowOutOfOrder = pointer.GetBool(testConf.AllowOutOfOrder) withPipeline = pointer.GetBool(testConf.TokenConfig.WithPipeline) configureCLNodes = !pointer.GetBool(testConf.ExistingDeployment) ) @@ -3510,6 +3588,13 @@ func (lane *CCIPLane) DeployNewCCIPLane( if err != nil { return fmt.Errorf("failed to create source module: %w", err) } + + // If AllowOutOfOrder is set globally in test config, the assumption is to set it for every lane. + // However, if this is set as false, and set as true for specific chain in lane_configs, then apply it + // only for a lane where source network is of that chain. + if allowOutOfOrder { + lane.Source.Common.AllowOutOfOrder = true + } lane.Dest, err = DefaultDestinationCCIPModule( lane.Logger, testConf, destChainClient, sourceChainClient.GetChainID().Uint64(), @@ -3762,12 +3847,18 @@ func SetOCR2Config( nodes = execNodes } 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, 0.7, *inflightExpiryExec, *commonconfig.MustNewDuration(RootSnoozeTime), + batchingStrategyID, ) if err != nil { return fmt.Errorf("failed to create exec offchain config: %w", err) diff --git a/integration-tests/ccip-tests/actions/reorg_helpers.go b/integration-tests/ccip-tests/actions/reorg_helpers.go new file mode 100644 index 00000000000..017b8ffab69 --- /dev/null +++ b/integration-tests/ccip-tests/actions/reorg_helpers.go @@ -0,0 +1,86 @@ +package actions + +import ( + "fmt" + "testing" + "time" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/client" +) + +// ReorgSuite is a test suite that generates reorgs on source/dest chains +type ReorgSuite struct { + t *testing.T + Cfg *ReorgConfig + Logger *zerolog.Logger + SrcClient *client.RPCClient + DstClient *client.RPCClient +} + +// ReorgConfig is a configuration for reorg tests +type ReorgConfig struct { + // SrcGethHTTPURL source chain Geth HTTP URL + SrcGethHTTPURL string + // DstGethHTTPURL dest chain Geth HTTP URL + DstGethHTTPURL string + // SrcFinalityDepth source chain finality depth + SrcFinalityDepth uint64 + // DstGethHTTPURL dest chain finality depth + DstFinalityDepth uint64 + // FinalityDelta blocks to rewind below or above finality + FinalityDelta int +} + +// Validate validates ReorgConfig params +func (rc *ReorgConfig) Validate() error { + if rc.FinalityDelta >= int(rc.SrcFinalityDepth) || rc.FinalityDelta >= int(rc.DstFinalityDepth) { + return fmt.Errorf( + "finality delta can't be higher than source or dest chain finality, delta: %d, src: %d, dst: %d", + rc.FinalityDelta, rc.SrcFinalityDepth, rc.DstFinalityDepth, + ) + } + return nil +} + +// NewReorgSuite creates new reorg suite with source/dest RPC clients, works only with Geth +func NewReorgSuite(t *testing.T, lggr *zerolog.Logger, cfg *ReorgConfig) (*ReorgSuite, error) { + if err := cfg.Validate(); err != nil { + return nil, err + } + return &ReorgSuite{ + t: t, + Cfg: cfg, + Logger: lggr, + SrcClient: client.NewRPCClient(cfg.SrcGethHTTPURL, nil), + DstClient: client.NewRPCClient(cfg.DstGethHTTPURL, nil), + }, nil +} + +// RunReorg rollbacks given chain, for N blocks back +func (r *ReorgSuite) RunReorg(client *client.RPCClient, blocksBack int, network string, startDelay time.Duration) { + go func() { + time.Sleep(startDelay) + r.Logger.Info(). + Str("Network", network). + Str("URL", client.URL). + Int("BlocksBack", blocksBack). + Msg(fmt.Sprintf("Rewinding blocks on %s chain", network)) + blockNumber, err := client.BlockNumber() + assert.NoError(r.t, err, "error getting block number") + r.Logger.Info(). + Int64("Number", blockNumber). + Str("Network", network). + Msg("Block number before rewinding") + err = client.GethSetHead(blocksBack) + assert.NoError(r.t, err, "error setting block head") + blockNumber, err = client.BlockNumber() + assert.NoError(r.t, err, "error getting block number") + r.Logger.Info(). + Int64("Number", blockNumber). + Str("Network", network). + Msg("Block number after rewinding") + }() +} diff --git a/integration-tests/ccip-tests/chaos/ccip_test.go b/integration-tests/ccip-tests/chaos/ccip_test.go index 4b1dda7a91e..125e683dc5b 100644 --- a/integration-tests/ccip-tests/chaos/ccip_test.go +++ b/integration-tests/ccip-tests/chaos/ccip_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index 8656656e0b2..c39ffe0c025 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -22,12 +22,11 @@ import ( ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/arm_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" "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" @@ -37,11 +36,12 @@ 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_arm_contract" + "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" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" @@ -74,10 +74,10 @@ func MatchContractVersionsOrAbove(requiredContractVersions map[Name]Version) err } // NeedTokenAdminRegistry checks if token admin registry is needed for the current version of ccip -// if the version is less than 1.5.0-dev, then token admin registry is not needed +// if the version is less than 1.5.0, then token admin registry is not needed func NeedTokenAdminRegistry() bool { return MatchContractVersionsOrAbove(map[Name]Version{ - TokenPoolContract: V1_5_0_dev, + TokenPoolContract: V1_5_0, }) == nil } @@ -541,18 +541,18 @@ func (e *CCIPContractsDeployer) DeployLockReleaseTokenPoolContract(tokenAddr str } } -func (e *CCIPContractsDeployer) DeployMockARMContract() (*common.Address, error) { +func (e *CCIPContractsDeployer) DeployMockRMNContract() (*common.Address, error) { address, _, _, err := e.evmClient.DeployContract("Mock ARM Contract", func( auth *bind.TransactOpts, _ bind.ContractBackend, ) (common.Address, *types.Transaction, interface{}, error) { - return mock_arm_contract.DeployMockARMContract(auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + return mock_rmn_contract.DeployMockRMNContract(auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) }) return address, err } -func (e *CCIPContractsDeployer) NewARMContract(addr common.Address) (*ARM, error) { - arm, err := arm_contract.NewARMContract(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) +func (e *CCIPContractsDeployer) NewRMNContract(addr common.Address) (*ARM, error) { + arm, err := rmn_contract.NewRMNContract(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) if err != nil { return nil, err } @@ -1044,7 +1044,7 @@ func (e *CCIPContractsDeployer) DeployOnRamp( MaxPerMsgGasLimit: 4_000_000, DefaultTokenFeeUSDCents: 50, DefaultTokenDestGasOverhead: 125_000, - DefaultTokenDestBytesOverhead: 500, + EnforceOutOfOrder: false, }, evm_2_evm_onramp.RateLimiterConfig{ Capacity: opts.Capacity, @@ -1289,30 +1289,30 @@ func OCR2ParamsForCommit(blockTime time.Duration) contracts.OffChainAggregatorV2 // slow blocktime chains like Ethereum if blockTime >= 10*time.Second { return contracts.OffChainAggregatorV2Config{ - DeltaProgress: 2 * time.Minute, - DeltaResend: 5 * time.Second, - DeltaRound: 90 * time.Second, - DeltaGrace: 5 * time.Second, - DeltaStage: 60 * time.Second, - MaxDurationQuery: 100 * time.Millisecond, - MaxDurationObservation: 35 * time.Second, - MaxDurationReport: 10 * time.Second, - MaxDurationShouldAcceptFinalizedReport: 5 * time.Second, - MaxDurationShouldTransmitAcceptedReport: 10 * time.Second, + DeltaProgress: config.MustNewDuration(2 * time.Minute), + DeltaResend: config.MustNewDuration(5 * time.Second), + DeltaRound: config.MustNewDuration(90 * time.Second), + DeltaGrace: config.MustNewDuration(5 * time.Second), + DeltaStage: config.MustNewDuration(60 * time.Second), + MaxDurationQuery: config.MustNewDuration(100 * time.Millisecond), + MaxDurationObservation: config.MustNewDuration(35 * time.Second), + MaxDurationReport: config.MustNewDuration(10 * time.Second), + MaxDurationShouldAcceptFinalizedReport: config.MustNewDuration(5 * time.Second), + MaxDurationShouldTransmitAcceptedReport: config.MustNewDuration(10 * time.Second), } } // fast blocktime chains like Avalanche return contracts.OffChainAggregatorV2Config{ - DeltaProgress: 2 * time.Minute, - DeltaResend: 5 * time.Second, - DeltaRound: 60 * time.Second, - DeltaGrace: 5 * time.Second, - DeltaStage: 25 * time.Second, - MaxDurationQuery: 100 * time.Millisecond, - MaxDurationObservation: 35 * time.Second, - MaxDurationReport: 10 * time.Second, - MaxDurationShouldAcceptFinalizedReport: 5 * time.Second, - MaxDurationShouldTransmitAcceptedReport: 10 * time.Second, + DeltaProgress: config.MustNewDuration(2 * time.Minute), + DeltaResend: config.MustNewDuration(5 * time.Second), + DeltaRound: config.MustNewDuration(60 * time.Second), + DeltaGrace: config.MustNewDuration(5 * time.Second), + DeltaStage: config.MustNewDuration(25 * time.Second), + MaxDurationQuery: config.MustNewDuration(100 * time.Millisecond), + MaxDurationObservation: config.MustNewDuration(35 * time.Second), + MaxDurationReport: config.MustNewDuration(10 * time.Second), + MaxDurationShouldAcceptFinalizedReport: config.MustNewDuration(5 * time.Second), + MaxDurationShouldTransmitAcceptedReport: config.MustNewDuration(10 * time.Second), } } @@ -1320,30 +1320,30 @@ func OCR2ParamsForExec(blockTime time.Duration) contracts.OffChainAggregatorV2Co // slow blocktime chains like Ethereum if blockTime >= 10*time.Second { return contracts.OffChainAggregatorV2Config{ - DeltaProgress: 2 * time.Minute, - DeltaResend: 5 * time.Second, - DeltaRound: 90 * time.Second, - DeltaGrace: 5 * time.Second, - DeltaStage: 60 * time.Second, - MaxDurationQuery: 100 * time.Millisecond, - MaxDurationObservation: 35 * time.Second, - MaxDurationReport: 10 * time.Second, - MaxDurationShouldAcceptFinalizedReport: 5 * time.Second, - MaxDurationShouldTransmitAcceptedReport: 10 * time.Second, + DeltaProgress: config.MustNewDuration(2 * time.Minute), + DeltaResend: config.MustNewDuration(5 * time.Second), + DeltaRound: config.MustNewDuration(90 * time.Second), + DeltaGrace: config.MustNewDuration(5 * time.Second), + DeltaStage: config.MustNewDuration(60 * time.Second), + MaxDurationQuery: config.MustNewDuration(100 * time.Millisecond), + MaxDurationObservation: config.MustNewDuration(35 * time.Second), + MaxDurationReport: config.MustNewDuration(10 * time.Second), + MaxDurationShouldAcceptFinalizedReport: config.MustNewDuration(5 * time.Second), + MaxDurationShouldTransmitAcceptedReport: config.MustNewDuration(10 * time.Second), } } // fast blocktime chains like Avalanche return contracts.OffChainAggregatorV2Config{ - DeltaProgress: 120 * time.Second, - DeltaResend: 5 * time.Second, - DeltaRound: 30 * time.Second, - DeltaGrace: 5 * time.Second, - DeltaStage: 10 * time.Second, - MaxDurationQuery: 100 * time.Millisecond, - MaxDurationObservation: 35 * time.Second, - MaxDurationReport: 10 * time.Second, - MaxDurationShouldAcceptFinalizedReport: 5 * time.Second, - MaxDurationShouldTransmitAcceptedReport: 10 * time.Second, + DeltaProgress: config.MustNewDuration(120 * time.Second), + DeltaResend: config.MustNewDuration(5 * time.Second), + DeltaRound: config.MustNewDuration(30 * time.Second), + DeltaGrace: config.MustNewDuration(5 * time.Second), + DeltaStage: config.MustNewDuration(10 * time.Second), + MaxDurationQuery: config.MustNewDuration(100 * time.Millisecond), + MaxDurationObservation: config.MustNewDuration(35 * time.Second), + MaxDurationReport: config.MustNewDuration(10 * time.Second), + MaxDurationShouldAcceptFinalizedReport: config.MustNewDuration(5 * time.Second), + MaxDurationShouldTransmitAcceptedReport: config.MustNewDuration(10 * time.Second), } } @@ -1364,8 +1364,8 @@ func OffChainAggregatorV2ConfigWithNodes(numberNodes int, inflightExpiry time.Du if faultyNodes == 0 { faultyNodes = 1 } - if cfg.DeltaStage == 0 { - cfg.DeltaStage = inflightExpiry + if cfg.DeltaStage == nil { + cfg.DeltaStage = config.MustNewDuration(inflightExpiry) } return contracts.OffChainAggregatorV2Config{ DeltaProgress: cfg.DeltaProgress, @@ -1401,8 +1401,7 @@ func NewCommitOffchainConfig( TokenPriceHeartBeat config.Duration, TokenPriceDeviationPPB uint32, InflightCacheExpiry config.Duration, - _ bool, // TODO: priceReportingDisabled added after this merge -) (ccipconfig.OffchainConfig, error) { + priceReportingDisabled bool) (ccipconfig.OffchainConfig, error) { switch VersionMap[CommitStoreContract] { case Latest: return testhelpers.NewCommitOffchainConfig( @@ -1412,6 +1411,7 @@ func NewCommitOffchainConfig( TokenPriceHeartBeat, TokenPriceDeviationPPB, InflightCacheExpiry, + priceReportingDisabled, ), nil case V1_2_0: return testhelpers_1_4_0.NewCommitOffchainConfig( @@ -1421,6 +1421,7 @@ func NewCommitOffchainConfig( TokenPriceHeartBeat, TokenPriceDeviationPPB, InflightCacheExpiry, + priceReportingDisabled, ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[CommitStoreContract]) @@ -1450,15 +1451,7 @@ func NewExecOnchainConfig( ) (abihelpers.AbiDefined, error) { switch VersionMap[OffRampContract] { case Latest: - return testhelpers.NewExecOnchainConfig( - PermissionLessExecutionThresholdSeconds, - Router, - PriceRegistry, - MaxNumberOfTokensPerMsg, - MaxDataBytes, - MaxPoolReleaseOrMintGas, // TODO: obsolete soon after this merge - 50_000, // TODO: MaxTokenTransferGas, obsolete soon after this merge - ), nil + return testhelpers.NewExecOnchainConfig(PermissionLessExecutionThresholdSeconds, Router, PriceRegistry, MaxNumberOfTokensPerMsg, MaxDataBytes), nil case V1_2_0: return testhelpers_1_4_0.NewExecOnchainConfig( PermissionLessExecutionThresholdSeconds, @@ -1473,12 +1466,14 @@ func NewExecOnchainConfig( } } +// NewExecOffchainConfig creates a config for the OffChain portion of how CCIP operates func NewExecOffchainConfig( destOptimisticConfirmations uint32, batchGasLimit uint32, relativeBoostPerWaitHour float64, inflightCacheExpiry config.Duration, rootSnoozeTime config.Duration, + batchingStrategyID uint32, // See ccipexec package ) (ccipconfig.OffchainConfig, error) { switch VersionMap[OffRampContract] { case Latest: @@ -1488,6 +1483,7 @@ func NewExecOffchainConfig( relativeBoostPerWaitHour, inflightCacheExpiry, rootSnoozeTime, + batchingStrategyID, ), nil case V1_2_0: return testhelpers_1_4_0.NewExecOffchainConfig( @@ -1496,6 +1492,7 @@ func NewExecOffchainConfig( relativeBoostPerWaitHour, inflightCacheExpiry, rootSnoozeTime, + batchingStrategyID, ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[OffRampContract]) @@ -1565,20 +1562,21 @@ func NewOffChainAggregatorV2ConfigForCCIPPlugin[T ccipconfig.OffchainConfig]( } _, _, f_, onchainConfig_, offchainConfigVersion, offchainConfig, err = ocrconfighelper2.ContractSetConfigArgsForTests( - ocrConfig.DeltaProgress, - ocrConfig.DeltaResend, - ocrConfig.DeltaRound, - ocrConfig.DeltaGrace, - ocrConfig.DeltaStage, + ocrConfig.DeltaProgress.Duration(), + ocrConfig.DeltaResend.Duration(), + ocrConfig.DeltaRound.Duration(), + ocrConfig.DeltaGrace.Duration(), + ocrConfig.DeltaStage.Duration(), ocrConfig.RMax, ocrConfig.S, ocrConfig.Oracles, ocrConfig.ReportingPluginConfig, - ocrConfig.MaxDurationQuery, - ocrConfig.MaxDurationObservation, - ocrConfig.MaxDurationReport, - ocrConfig.MaxDurationShouldAcceptFinalizedReport, - ocrConfig.MaxDurationShouldTransmitAcceptedReport, + nil, + ocrConfig.MaxDurationQuery.Duration(), + ocrConfig.MaxDurationObservation.Duration(), + ocrConfig.MaxDurationReport.Duration(), + ocrConfig.MaxDurationShouldAcceptFinalizedReport.Duration(), + ocrConfig.MaxDurationShouldTransmitAcceptedReport.Duration(), ocrConfig.F, ocrConfig.OnchainConfig, ) diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 7008d51b622..83fe12a60a6 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -17,25 +17,25 @@ import ( "github.com/rs/zerolog" "golang.org/x/exp/rand" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/arm_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" "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" "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" "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/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/mock_arm_contract" + "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" "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" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" @@ -112,9 +112,9 @@ const ( var ( V1_2_0 = MustVersion("1.2.0") V1_4_0 = MustVersion("1.4.0") - V1_5_0_dev = MustVersion("1.5.0-dev") - LatestPoolVersion = V1_5_0_dev - Latest = V1_5_0_dev + V1_5_0 = MustVersion("1.5.0") + LatestPoolVersion = V1_5_0 + Latest = V1_5_0 VersionMap = map[Name]Version{ PriceRegistryContract: V1_2_0, OffRampContract: Latest, @@ -944,7 +944,7 @@ func (pool *TokenPool) GetRebalancer() (common.Address, error) { type ARM struct { client blockchain.EVMClient - Instance *arm_contract.ARMContract + Instance *rmn_contract.RMNContract EthAddress common.Address } @@ -954,7 +954,7 @@ func (arm *ARM) Address() string { type MockARM struct { client blockchain.EVMClient - Instance *mock_arm_contract.MockARMContract + Instance *mock_rmn_contract.MockRMNContract EthAddress common.Address } @@ -1111,7 +1111,7 @@ type PriceRegistryUsdPerUnitGasUpdated struct { } type PriceRegistryWrapper struct { - Latest *price_registry.PriceRegistry + Latest *fee_quoter.FeeQuoter V1_2_0 *price_registry_1_2_0.PriceRegistry } @@ -1137,7 +1137,7 @@ func (p *PriceRegistryWrapper) AddPriceUpdater(opts *bind.TransactOpts, addr com if p.Latest != nil { return p.Latest.ApplyAuthorizedCallerUpdates( opts, - price_registry.AuthorizedCallersAuthorizedCallerArgs{ + fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ AddedCallers: []common.Address{addr}, RemovedCallers: []common.Address{}, }, @@ -1243,21 +1243,21 @@ func (c *PriceRegistry) UpdatePrices(tokenUpdates []InternalTokenPriceUpdate, ga } var tx *types.Transaction if c.Instance.Latest != nil { - var tokenUpdatesLatest []price_registry.InternalTokenPriceUpdate - var gasUpdatesLatest []price_registry.InternalGasPriceUpdate + var tokenUpdatesLatest []fee_quoter.InternalTokenPriceUpdate + var gasUpdatesLatest []fee_quoter.InternalGasPriceUpdate for _, update := range tokenUpdates { - tokenUpdatesLatest = append(tokenUpdatesLatest, price_registry.InternalTokenPriceUpdate{ + tokenUpdatesLatest = append(tokenUpdatesLatest, fee_quoter.InternalTokenPriceUpdate{ SourceToken: update.SourceToken, UsdPerToken: update.UsdPerToken, }) } for _, update := range gasUpdates { - gasUpdatesLatest = append(gasUpdatesLatest, price_registry.InternalGasPriceUpdate{ + gasUpdatesLatest = append(gasUpdatesLatest, fee_quoter.InternalGasPriceUpdate{ DestChainSelector: update.DestChainSelector, UsdPerUnitGas: update.UsdPerUnitGas, }) } - tx, err = c.Instance.Latest.UpdatePrices(opts, price_registry.InternalPriceUpdates{ + tx, err = c.Instance.Latest.UpdatePrices(opts, fee_quoter.InternalPriceUpdates{ TokenPriceUpdates: tokenUpdatesLatest, GasPriceUpdates: gasUpdatesLatest, }) @@ -1299,12 +1299,12 @@ func (c *PriceRegistry) UpdatePrices(tokenUpdates []InternalTokenPriceUpdate, ga return c.client.ProcessTransaction(tx) } -func (c *PriceRegistry) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, latest chan *price_registry.PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { +func (c *PriceRegistry) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, latest chan *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { if c.Instance.Latest != nil { return c.Instance.Latest.WatchUsdPerUnitGasUpdated(opts, latest, destChain) } if c.Instance.V1_2_0 != nil { - newP, err := price_registry.NewPriceRegistry(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) + newP, err := fee_quoter.NewFeeQuoter(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) if err != nil { return nil, fmt.Errorf("failed to create new PriceRegistry contract: %w", err) } @@ -1313,12 +1313,12 @@ func (c *PriceRegistry) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, latest c return nil, fmt.Errorf("no instance found to watch for price updates for gas") } -func (c *PriceRegistry) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, latest chan *price_registry.PriceRegistryUsdPerTokenUpdated) (event.Subscription, error) { +func (c *PriceRegistry) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, latest chan *fee_quoter.FeeQuoterUsdPerTokenUpdated) (event.Subscription, error) { if c.Instance.Latest != nil { return c.Instance.Latest.WatchUsdPerTokenUpdated(opts, latest, nil) } if c.Instance.V1_2_0 != nil { - newP, err := price_registry.NewPriceRegistry(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) + newP, err := fee_quoter.NewFeeQuoter(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) if err != nil { return nil, fmt.Errorf("failed to create new PriceRegistry contract: %w", err) } @@ -1616,22 +1616,58 @@ func (w OnRampWrapper) ParseCCIPSendRequested(l types.Log) (uint64, error) { return 0, fmt.Errorf("no instance found to parse CCIPSendRequested") } -func (w OnRampWrapper) GetDynamicConfig(opts *bind.CallOpts) (uint32, error) { +// GetDynamicConfig retrieves the dynamic config for the onramp +func (w OnRampWrapper) GetDynamicConfig(opts *bind.CallOpts) (evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig, error) { if w.Latest != nil { cfg, err := w.Latest.GetDynamicConfig(opts) if err != nil { - return 0, err + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{}, err } - return cfg.MaxDataBytes, nil + return cfg, nil } if w.V1_2_0 != nil { cfg, err := w.V1_2_0.GetDynamicConfig(opts) if err != nil { - return 0, err + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{}, err } - return cfg.MaxDataBytes, nil + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: cfg.Router, + MaxNumberOfTokensPerMsg: cfg.MaxNumberOfTokensPerMsg, + DestGasOverhead: cfg.DestGasOverhead, + DestGasPerPayloadByte: cfg.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: cfg.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: cfg.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: cfg.DestDataAvailabilityMultiplierBps, + PriceRegistry: cfg.PriceRegistry, + MaxDataBytes: cfg.MaxDataBytes, + MaxPerMsgGasLimit: cfg.MaxPerMsgGasLimit, + }, nil + } + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{}, fmt.Errorf("no instance found to get dynamic config") +} + +// SetDynamicConfig sets the dynamic config for the onramp +// Note that you cannot set only a single field, you must set all fields or they will be reset to zero values +// You can use GetDynamicConfig to get the current config and modify it as needed +func (w OnRampWrapper) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { + if w.Latest != nil { + return w.Latest.SetDynamicConfig(opts, dynamicConfig) + } + if w.V1_2_0 != nil { + return w.V1_2_0.SetDynamicConfig(opts, evm_2_evm_onramp_1_2_0.EVM2EVMOnRampDynamicConfig{ + Router: dynamicConfig.Router, + MaxNumberOfTokensPerMsg: dynamicConfig.MaxNumberOfTokensPerMsg, + DestGasOverhead: dynamicConfig.DestGasOverhead, + DestGasPerPayloadByte: dynamicConfig.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: dynamicConfig.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: dynamicConfig.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: dynamicConfig.DestDataAvailabilityMultiplierBps, + PriceRegistry: dynamicConfig.PriceRegistry, + MaxDataBytes: dynamicConfig.MaxDataBytes, + MaxPerMsgGasLimit: dynamicConfig.MaxPerMsgGasLimit, + }) } - return 0, fmt.Errorf("no instance found to get dynamic config") + return nil, fmt.Errorf("no instance found to set dynamic config") } func (w OnRampWrapper) ApplyPoolUpdates(opts *bind.TransactOpts, tokens []common.Address, pools []common.Address) (*types.Transaction, error) { diff --git a/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go b/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go index 332bd48ab31..c96cb3dfdc6 100644 --- a/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go +++ b/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go @@ -21,6 +21,7 @@ var ( type CommonContracts struct { IsNativeFeeToken bool `json:"is_native_fee_token,omitempty"` + AllowOutOfOrder bool `json:"allow_out_of_order,omitempty"` // expected to set this value as True for ZK chain source networks IsMockARM bool `json:"is_mock_arm,omitempty"` FeeToken string `json:"fee_token"` BridgeTokens []string `json:"bridge_tokens,omitempty"` diff --git a/integration-tests/ccip-tests/contracts/lm_contracts.go b/integration-tests/ccip-tests/contracts/lm_contracts.go new file mode 100644 index 00000000000..521324c11be --- /dev/null +++ b/integration-tests/ccip-tests/contracts/lm_contracts.go @@ -0,0 +1,320 @@ +package contracts + +import ( + "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/rs/zerolog" + + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/arbitrum_l1_bridge_adapter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/arbitrum_l2_bridge_adapter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/liquiditymanager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/mock_l1_bridge_adapter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/mock_l2_bridge_adapter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/optimism_l1_bridge_adapter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/optimism_l2_bridge_adapter" +) + +type ArmProxy struct { + client blockchain.EVMClient + Instance *rmn_proxy_contract.RMNProxyContract + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployArmProxy(arm common.Address) (*ArmProxy, error) { + address, _, instance, err := e.evmClient.DeployContract("ARMProxy", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return rmn_proxy_contract.DeployRMNProxyContract( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + arm, + ) + }) + if err != nil { + return nil, err + } + return &ArmProxy{ + client: e.evmClient, + Instance: instance.(*rmn_proxy_contract.RMNProxyContract), + EthAddress: address, + }, err +} + +type LiquidityManager struct { + client blockchain.EVMClient + logger *zerolog.Logger + Instance *liquiditymanager.LiquidityManager + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployLiquidityManager( + token common.Address, + localChainSelector uint64, + localLiquidityContainer common.Address, + minimumLiquidity *big.Int, +) (*LiquidityManager, error) { + address, _, instance, err := e.evmClient.DeployContract("LiquidityManager", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return liquiditymanager.DeployLiquidityManager( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + token, + localChainSelector, + localLiquidityContainer, + minimumLiquidity, + common.Address{}, + ) + }) + if err != nil { + return nil, err + } + return &LiquidityManager{ + client: e.evmClient, + logger: e.logger, + Instance: instance.(*liquiditymanager.LiquidityManager), + EthAddress: address, + }, err +} + +func (v *LiquidityManager) GetLiquidity() (*big.Int, error) { + return v.Instance.GetLiquidity(nil) +} + +func (v *LiquidityManager) SetCrossChainRebalancer( + crossChainRebalancerArgs liquiditymanager.ILiquidityManagerCrossChainRebalancerArgs, +) error { + v.logger.Info(). + Str("Liquidity Manager", v.EthAddress.String()). + Msg("Setting crosschain rebalancer on liquidity manager") + opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return fmt.Errorf("failed to get transaction opts: %w", err) + } + tx, err := v.Instance.SetCrossChainRebalancer(opts, crossChainRebalancerArgs) + if err != nil { + return fmt.Errorf("failed to set cross chain rebalancer: %w", err) + + } + v.logger.Info(). + Str("Liquidity Manager", v.EthAddress.String()). + Interface("Rebalance Argsr", crossChainRebalancerArgs). + Msg("Crosschain Rebalancer set on liquidity manager") + return v.client.ProcessTransaction(tx) +} + +func (v *LiquidityManager) SetOCR3Config( + signers []common.Address, + transmitters []common.Address, + f uint8, + onchainConfig []byte, + offchainConfigVersion uint64, + offchainConfig []byte, +) error { + v.logger.Info(). + Str("Liquidity Manager", v.EthAddress.String()). + Msg("Setting ocr3 config on liquidity manager") + opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return fmt.Errorf("failed to get transaction opts: %w", err) + } + tx, err := v.Instance.SetOCR3Config( + opts, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig) + if err != nil { + return fmt.Errorf("failed to set cross chain rebalancer: %w", err) + + } + v.logger.Info(). + Str("Liquidity Manager", v.EthAddress.String()). + Msg("Set OCR3Config on LM") + return v.client.ProcessTransaction(tx) +} + +type ArbitrumL1BridgeAdapter struct { + client blockchain.EVMClient + Instance *arbitrum_l1_bridge_adapter.ArbitrumL1BridgeAdapter + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployArbitrumL1BridgeAdapter( + l1GatewayRouter common.Address, + l1Outbox common.Address, +) (*ArbitrumL1BridgeAdapter, error) { + address, _, instance, err := e.evmClient.DeployContract("ArbitrumL1BridgeAdapter", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return arbitrum_l1_bridge_adapter.DeployArbitrumL1BridgeAdapter( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + l1GatewayRouter, + l1Outbox, + ) + }) + if err != nil { + return nil, err + } + return &ArbitrumL1BridgeAdapter{ + client: e.evmClient, + Instance: instance.(*arbitrum_l1_bridge_adapter.ArbitrumL1BridgeAdapter), + EthAddress: address, + }, err +} + +type ArbitrumL2BridgeAdapter struct { + client blockchain.EVMClient + Instance *arbitrum_l2_bridge_adapter.ArbitrumL2BridgeAdapter + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployArbitrumL2BridgeAdapter(l2GatewayRouter common.Address) (*ArbitrumL2BridgeAdapter, error) { + address, _, instance, err := e.evmClient.DeployContract("ArbitrumL2BridgeAdapter", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return arbitrum_l2_bridge_adapter.DeployArbitrumL2BridgeAdapter( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + l2GatewayRouter, + ) + }) + if err != nil { + return nil, err + } + return &ArbitrumL2BridgeAdapter{ + client: e.evmClient, + Instance: instance.(*arbitrum_l2_bridge_adapter.ArbitrumL2BridgeAdapter), + EthAddress: address, + }, err +} + +type OptimismL1BridgeAdapter struct { + client blockchain.EVMClient + Instance *optimism_l1_bridge_adapter.OptimismL1BridgeAdapter + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployOptimismL1BridgeAdapter( + l1Bridge common.Address, + wrappedNative common.Address, + optimismPortal common.Address, +) (*OptimismL1BridgeAdapter, error) { + address, _, instance, err := e.evmClient.DeployContract("OptimismL1BridgeAdapter", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return optimism_l1_bridge_adapter.DeployOptimismL1BridgeAdapter( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + l1Bridge, + wrappedNative, + optimismPortal, + ) + }) + if err != nil { + return nil, err + } + return &OptimismL1BridgeAdapter{ + client: e.evmClient, + Instance: instance.(*optimism_l1_bridge_adapter.OptimismL1BridgeAdapter), + EthAddress: address, + }, err +} + +type OptimismL2BridgeAdapter struct { + client blockchain.EVMClient + Instance *optimism_l2_bridge_adapter.OptimismL2BridgeAdapter + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployOptimismL2BridgeAdapter(wrappedNative common.Address) (*OptimismL2BridgeAdapter, error) { + address, _, instance, err := e.evmClient.DeployContract("OptimismL2BridgeAdapter", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return optimism_l2_bridge_adapter.DeployOptimismL2BridgeAdapter( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + wrappedNative, + ) + }) + if err != nil { + return nil, err + } + return &OptimismL2BridgeAdapter{ + client: e.evmClient, + Instance: instance.(*optimism_l2_bridge_adapter.OptimismL2BridgeAdapter), + EthAddress: address, + }, err +} + +type MockL1BridgeAdapter struct { + client blockchain.EVMClient + Instance *mock_l1_bridge_adapter.MockL1BridgeAdapter + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployMockL1BridgeAdapter(tokenAddr common.Address, holdNative bool) (*MockL1BridgeAdapter, error) { + address, _, instance, err := e.evmClient.DeployContract("MockL1BridgeAdapter", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return mock_l1_bridge_adapter.DeployMockL1BridgeAdapter( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + tokenAddr, + holdNative, + ) + }) + if err != nil { + return nil, err + } + return &MockL1BridgeAdapter{ + client: e.evmClient, + Instance: instance.(*mock_l1_bridge_adapter.MockL1BridgeAdapter), + EthAddress: address, + }, err +} + +type MockL2BridgeAdapter struct { + client blockchain.EVMClient + Instance *mock_l2_bridge_adapter.MockL2BridgeAdapter + EthAddress *common.Address +} + +func (e *CCIPContractsDeployer) DeployMockL2BridgeAdapter() (*MockL2BridgeAdapter, error) { + address, _, instance, err := e.evmClient.DeployContract("MockL2BridgeAdapter", func( + auth *bind.TransactOpts, + _ bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return mock_l2_bridge_adapter.DeployMockL2BridgeAdapter( + auth, + wrappers.MustNewWrappedContractBackend(e.evmClient, nil), + ) + }) + if err != nil { + return nil, err + } + return &MockL2BridgeAdapter{ + client: e.evmClient, + Instance: instance.(*mock_l2_bridge_adapter.MockL2BridgeAdapter), + EthAddress: address, + }, err +} diff --git a/integration-tests/ccip-tests/contracts/multicall.go b/integration-tests/ccip-tests/contracts/multicall.go index 7db7f37519b..094a6152be6 100644 --- a/integration-tests/ccip-tests/contracts/multicall.go +++ b/integration-tests/ccip-tests/contracts/multicall.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index 4ed54a45fdb..3ce770d31bc 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -10,17 +10,21 @@ 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/smartcontractkit/wasp" "github.com/stretchr/testify/require" "go.uber.org/atomic" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -131,8 +135,9 @@ func (c *CCIPE2ELoad) BeforeAllCall() { c.EOAReceiver = c.msg.Receiver } if c.SendMaxDataIntermittentlyInMsgCount > 0 { - c.MaxDataBytes, err = sourceCCIP.OnRamp.Instance.GetDynamicConfig(nil) + cfg, err := sourceCCIP.OnRamp.Instance.GetDynamicConfig(nil) require.NoError(c.t, err, "failed to fetch dynamic config") + c.MaxDataBytes = cfg.MaxDataBytes } // if the msg is sent via multicall, transfer the token transfer amount to multicall contract if sourceCCIP.Common.MulticallEnabled && @@ -188,11 +193,27 @@ func (c *CCIPE2ELoad) CCIPMsg() (router.ClientEVM2AnyMessage, *testreporters.Req if !msgDetails.IsTokenTransfer() { msg.TokenAmounts = []router.ClientEVMTokenAmount{} } - extraArgsV1, err := testhelpers.GetEVMExtraArgsV1(big.NewInt(gasLimit), false) + + var ( + extraArgs []byte + err error + ) + matchErr := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ + contracts.OnRampContract: contracts.V1_5_0, + }) + // TODO: The CCIP Offchain upgrade tests make the AllowOutOfOrder flag tricky in this case. + // It runs with out of date contract versions at first, then upgrades them. So transactions will assume that the new contracts are there + // before being deployed. So setting v2 args will break the test. This is a bit of a hack to get around that. + // The test will soon be deprecated, so a temporary solution is fine. + if matchErr != nil || !c.Lane.Source.Common.AllowOutOfOrder { + extraArgs, err = testhelpers.GetEVMExtraArgsV1(big.NewInt(gasLimit), false) + } else { + extraArgs, err = testhelpers.GetEVMExtraArgsV2(big.NewInt(gasLimit), c.Lane.Source.Common.AllowOutOfOrder) + } if err != nil { return router.ClientEVM2AnyMessage{}, stats, err } - msg.ExtraArgs = extraArgsV1 + msg.ExtraArgs = extraArgs // if gaslimit is 0, set the receiver to EOA if gasLimit == 0 { msg.Receiver = c.EOAReceiver @@ -203,7 +224,18 @@ func (c *CCIPE2ELoad) CCIPMsg() (router.ClientEVM2AnyMessage, *testreporters.Req func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { res := &wasp.Response{} sourceCCIP := c.Lane.Source - recentRequestFoundAt := sourceCCIP.IsRequestTriggeredWithinTimeframe(c.SkipRequestIfAnotherRequestTriggeredWithin) + var recentRequestFoundAt *time.Time + 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) + require.NoError(c.t, err, "error while filtering past requests") + } else { + recentRequestFoundAt = sourceCCIP.IsRequestTriggeredWithinTimeframe(c.SkipRequestIfAnotherRequestTriggeredWithin) + } + if recentRequestFoundAt != nil { c.Lane.Logger. Info(). diff --git a/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go b/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go index ad3960dee2e..04fcffaa4b1 100644 --- a/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go @@ -12,10 +12,11 @@ import ( "golang.org/x/sync/errgroup" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/wasp" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" diff --git a/integration-tests/ccip-tests/load/ccip_test.go b/integration-tests/ccip-tests/load/ccip_test.go index 0d14549ec96..a8297dd2096 100644 --- a/integration-tests/ccip-tests/load/ccip_test.go +++ b/integration-tests/ccip-tests/load/ccip_test.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index 9522a6c346b..34860c8871c 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -12,15 +12,16 @@ import ( "github.com/AlekSi/pointer" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" "go.uber.org/atomic" "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" @@ -198,10 +199,7 @@ func (l *LoadArgs) ValidateCurseFollowedByUncurse() { // try to send requests on lanes on which curse is applied on source RMN and the request should revert // data-only transfer is sufficient lane.Source.TransferAmount = []*big.Int{} - failedTx, _, _, err := lane.Source.SendRequest( - lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit - ) + failedTx, _, _, err := lane.Source.SendRequest(lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) if lane.Source.Common.ChainClient.GetNetworkConfig().MinimumConfirmations > 0 { require.Error(l.t, err) } else { @@ -307,7 +305,7 @@ func (l *LoadArgs) TriggerLoadByLane() { } waspCfg.LokiConfig.Timeout = time.Minute loadRunner, err := wasp.NewGenerator(waspCfg) - require.NoError(l.TestCfg.Test, err, "initiating loadgen for lane %s --> %s", + require.NoError(l.TestCfg.Test, err, "error while initiating loadgen for lane %s --> %s", lane.SourceNetworkName, lane.DestNetworkName) loadRunner.Run(false) l.AddToRunnerGroup(loadRunner) diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index 9a34044a5d8..08054459481 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -6,11 +6,14 @@ import ( "testing" "time" + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/AlekSi/pointer" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" @@ -241,10 +244,7 @@ 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), // gas limit - ) + 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) @@ -269,10 +269,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { // try to send again with amount more than the amount refilled by rate and // this should fail, as the refill rate is not enough to refill the capacity src.TransferAmount[0] = new(big.Int).Mul(AggregatedRateLimitRate, big.NewInt(10)) - failedTx, _, _, err = tc.lane.Source.SendRequest( - tc.lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit - ) + failedTx, _, _, err = tc.lane.Source.SendRequest(tc.lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) tc.lane.Logger.Info().Str("tokensToSend", src.TransferAmount[0].String()).Msg("More than Aggregated Rate") require.NoError(t, err) require.Error(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) @@ -336,10 +333,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { src.TransferAmount[0] = tokensToSend tc.lane.Logger.Info().Str("tokensToSend", tokensToSend.String()).Msg("More than Token Pool Capacity") - failedTx, _, _, err = tc.lane.Source.SendRequest( - tc.lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit - ) + 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, lock_release_token_pool.LockReleaseTokenPoolABI) @@ -371,10 +365,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { src.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, lock_release_token_pool.LockReleaseTokenPoolABI) @@ -403,8 +394,8 @@ func TestSmokeCCIPOnRampLimits(t *testing.T) { "This test modifies contract state. Before running it, ensure you are willing and able to do so.", ) err := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ - contracts.OffRampContract: contracts.V1_5_0_dev, - contracts.OnRampContract: contracts.V1_5_0_dev, + contracts.OffRampContract: contracts.V1_5_0, + contracts.OnRampContract: contracts.V1_5_0, }) require.NoError(t, err, "Required contract versions not met") @@ -624,8 +615,8 @@ func TestSmokeCCIPTokenPoolRateLimits(t *testing.T) { "This test modifies contract state. Before running it, ensure you are willing and able to do so.", ) err := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ - contracts.OffRampContract: contracts.V1_5_0_dev, - contracts.OnRampContract: contracts.V1_5_0_dev, + contracts.OffRampContract: contracts.V1_5_0, + contracts.OnRampContract: contracts.V1_5_0, }) require.NoError(t, err, "Required contract versions not met") @@ -855,6 +846,130 @@ func TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas(t *te } } +// Test expects to generate below finality reorg in both source and destination and +// expect CCIP transactions to go through successful. +func TestSmokeCCIPReorgBelowFinality(t *testing.T) { + t.Parallel() + log := logging.GetTestLogger(t) + TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) + gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) + setUpOutput := testsetups.CCIPDefaultTestSetUp(t, &log, "smoke-ccip", nil, TestCfg) + require.False(t, len(setUpOutput.Lanes) == 0, "No lanes found.") + t.Cleanup(func() { + require.NoError(t, setUpOutput.TearDown()) + }) + + lane := setUpOutput.Lanes[0].ForwardLane + log.Info(). + Str("Source", lane.SourceNetworkName). + Str("Destination", lane.DestNetworkName). + Msg("Starting CCIP reorg test") + t.Run(fmt.Sprintf("CCIP reorg below finality test from network %s to network %s", + lane.SourceNetworkName, lane.DestNetworkName), func(t *testing.T) { + t.Parallel() + lane.Test = t + lane.RecordStateBeforeTransfer() + // sending multiple request and expect all should go through though there is below finality reorg + err := lane.SendRequests(5, gasLimit) + require.NoError(t, err, "Send requests failed") + rs := SetupReorgSuite(t, &log, setUpOutput) + // run below finality reorg in both source and destination chain + blocksBackSrc := int(rs.Cfg.SrcFinalityDepth) - rs.Cfg.FinalityDelta + blocksBackDst := int(rs.Cfg.DstFinalityDepth) - rs.Cfg.FinalityDelta + rs.RunReorg(rs.DstClient, blocksBackSrc, "Source", 2*time.Second) + rs.RunReorg(rs.DstClient, blocksBackDst, "Destination", 2*time.Second) + time.Sleep(1 * time.Minute) + lane.ValidateRequests() + }) +} + +// 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 every node is able to detect reorg. +// Note: LogPollInterval interval is set as 1s to detect the reorg immediately +func TestSmokeCCIPReorgAboveFinalityAtDestination(t *testing.T) { + t.Parallel() + t.Run("Above finality reorg in destination chain", func(t *testing.T) { + performAboveFinalityReorgAndValidate(t, "Destination") + }) +} + +// 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 every node is able to detect reorg. +// Note: LogPollInterval interval is set as 1s to detect the reorg immediately +func TestSmokeCCIPReorgAboveFinalityAtSource(t *testing.T) { + t.Parallel() + t.Run("Above finality reorg in source chain", func(t *testing.T) { + performAboveFinalityReorgAndValidate(t, "Source") + }) +} + +// performAboveFinalityReorgAndValidate is to perform the above finality reorg test +func performAboveFinalityReorgAndValidate(t *testing.T, network string) { + t.Helper() + + log := logging.GetTestLogger(t) + TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) + gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) + setUpOutput := testsetups.CCIPDefaultTestSetUp(t, &log, "smoke-ccip", nil, TestCfg) + require.False(t, len(setUpOutput.Lanes) == 0, "No lanes found.") + t.Cleanup(func() { + require.NoError(t, setUpOutput.TearDown()) + }) + rs := SetupReorgSuite(t, &log, setUpOutput) + lane := setUpOutput.Lanes[0].ForwardLane + log.Info(). + Str("Source", lane.SourceNetworkName). + Str("Destination", lane.DestNetworkName). + Msg("Starting ccip reorg test") + lane.Test = t + lane.RecordStateBeforeTransfer() + err := lane.SendRequests(1, gasLimit) + require.NoError(t, err, "Send requests failed") + logPollerName := "" + if network == "Destination" { + logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.DestChain.GetChainID()) + rs.RunReorg(rs.DstClient, int(rs.Cfg.DstFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) + } else { + logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.SourceChain.GetChainID()) + rs.RunReorg(rs.SrcClient, int(rs.Cfg.SrcFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) + } + clNodes := setUpOutput.Env.CLNodes + // assert every node is detecting the reorg (LogPollInterval is set as 1s for faster detection) + nodesDetectedViolation := make(map[string]bool) + assert.Eventually(t, func() bool { + for _, node := range clNodes { + if _, ok := nodesDetectedViolation[node.ChainlinkClient.URL()]; ok { + continue + } + resp, _, err := node.Health() + 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") + nodesDetectedViolation[node.ChainlinkClient.URL()] = true + } + } + } + return len(nodesDetectedViolation) == len(clNodes) + }, 3*time.Minute, 20*time.Second, "Reorg above finality depth is not detected by every node") + log.Debug().Interface("Nodes", nodesDetectedViolation).Msg("Violation detection details") + // send another request and verify it fails + err = lane.SendRequests(1, gasLimit) + if network == "Source" { + // if it is source chain reorg, the transaction will not even be initiated + require.Error(t, err, + "CCIP send transaction shouldn't be initiated as there is above finality depth reorg in source chain") + } else { + // if it is destination chain reorg, the transaction will be initiated and will fail in the process + require.NoError(t, err, + "CCIP send transaction should be initiated even when there above finality reorg in dest chain") + } + + lane.ValidateRequests(actions.ExpectAnyPhaseToFail(actions.WithTimeout(time.Minute))) +} + // add liquidity to pools on both networks func addLiquidity(t *testing.T, ccipCommon *actions.CCIPCommon, amount *big.Int) { t.Helper() @@ -879,7 +994,7 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter "This test modifies contract state. Before running it, ensure you are willing and able to do so.", ) err := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ - contracts.OffRampContract: contracts.V1_5_0_dev, + contracts.OffRampContract: contracts.V1_5_0, }) require.NoError(t, err, "Required contract versions not met") require.False(t, pointer.GetBool(TestCfg.TestGroupInput.ExistingDeployment), "This test modifies contract state and cannot be run on existing deployments") @@ -1004,5 +1119,37 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter require.NoError(t, err, "Error manually executing transaction after rate limit is lifted") }) } +} +// SetupReorgSuite defines the setup required to perform re-org step +func SetupReorgSuite(t *testing.T, lggr *zerolog.Logger, setupOutput *testsetups.CCIPTestSetUpOutputs) *actions.ReorgSuite { + var finalitySrc uint64 + var finalityDst uint64 + if setupOutput.Cfg.SelectedNetworks[0].FinalityTag { + finalitySrc = 10 + } else { + finalitySrc = setupOutput.Cfg.SelectedNetworks[0].FinalityDepth + } + if setupOutput.Cfg.SelectedNetworks[1].FinalityTag { + finalityDst = 10 + } else { + finalityDst = setupOutput.Cfg.SelectedNetworks[1].FinalityDepth + } + var srcGethHTTPURL, dstGethHTTPURL string + if setupOutput.Env.LocalCluster != nil { + srcGethHTTPURL = setupOutput.Env.LocalCluster.EVMNetworks[0].HTTPURLs[0] + dstGethHTTPURL = setupOutput.Env.LocalCluster.EVMNetworks[1].HTTPURLs[0] + } else { + srcGethHTTPURL = setupOutput.Env.K8Env.URLs["source-chain_http"][0] + dstGethHTTPURL = setupOutput.Env.K8Env.URLs["dest-chain_http"][0] + } + rs, err := actions.NewReorgSuite(t, lggr, &actions.ReorgConfig{ + SrcGethHTTPURL: srcGethHTTPURL, + DstGethHTTPURL: dstGethHTTPURL, + SrcFinalityDepth: finalitySrc, + DstFinalityDepth: finalityDst, + FinalityDelta: setupOutput.Cfg.TestGroupInput.ReorgProfile.FinalityDelta, + }) + require.NoError(t, err) + return rs } diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index c32aee3d913..ff57ecaa220 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -1,21 +1,23 @@ # CCIP Configuration -The CCIP configuration is used to specify the test configuration for running the CCIP integration tests. +The CCIP configuration is used to specify the test configuration for running the CCIP integration tests. The configuration is specified in a TOML file. The configuration is used to specify the test environment, test type, test parameters, and other necessary details for running the tests. The test config is read in following order: -- The test reads the default configuration from [ccip-default.toml](./tomls/ccip-default.toml). -- The default can be overridden by specifying the test config in a separate file. - - The file content needs to be encoded in base64 format and set in `BASE64_CCIP_CONFIG_OVERRIDE` environment variable. + +- The test reads the default configuration from [ccip-default.toml](./tomls/ccip-default.toml). +- The default can be overridden by specifying the test config in a separate file. + - The file content needs to be encoded in base64 format and set in `BASE64_CONFIG_OVERRIDE` environment variable. - 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 secret file. - - The file content needs to be encoded in base64 format and set in `BASE64_CCIP_SECRETS_CONFIG` environment variable. - - The config mentioned in this file will override the default and override config. - - Example secret file - [secrets.toml.example](./examples/secrets.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 + - Example secret file - [.testsecrets.example](./examples/.testsecrets.example) ## CCIP.ContractVersions + Specifies contract versions of different contracts to be referred by test. Supported versions are: + - **PriceRegistry**: '1.2.0', 'Latest' - **OffRamp**: '1.2.0', 'Latest' - **OnRamp**: '1.2.0', 'Latest' @@ -23,6 +25,7 @@ Supported versions are: - **CommitStore**: '1.2.0', 'Latest' Example Usage: + ```toml [CCIP.ContractVersions] PriceRegistry = "1.2.0" @@ -33,14 +36,17 @@ CommitStore = "1.2.0" ``` ## CCIP.Deployments -CCIP Deployment contains all necessary contract addresses for various networks. This is mandatory if the test are to be run for [existing deployments](#ccipgroupstestgroupexistingdeployment) + +CCIP Deployment contains all necessary contract addresses for various networks. This is mandatory if the test are to be run for [existing deployments](#ccipgroupstestgroupexistingdeployment) The deployment data can be specified - - - Under `CCIP.Deployments.Data` field with value as stringify format of json. - - Under `CCIP.Deployments.DataFile` field with value as the path of the file containing the deployment data in json format. + +- Under `CCIP.Deployments.Data` field with value as stringify format of json. +- Under `CCIP.Deployments.DataFile` field with value as the path of the file containing the deployment data in json format. The json schema is specified in https://github.com/smartcontractkit/ccip/blob/ccip-develop/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go#L96 Example Usage: + ```toml [CCIP.Deployments] Data = """ @@ -96,32 +102,39 @@ Data = """ } """ ``` -Or + +Or, + ```toml [CCIP.Deployments] DataFile = '' ``` -## CCIP.Env +## CCIP.Env + Specifies the environment details for the test to be run on. Mandatory fields are: + - **Networks**: [CCIP.Env.Networks](#ccipenvnetworks) - **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) + +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. + - 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. ### CCIP.Env.Networks + Specifies the network details for the test to be run. The NetworkConfig is imported from https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/network.go#L39 #### CCIP.Env.Networks.selected_networks + It denotes the network names in which tests will be run. These networks are used to deploy ccip contracts and set up lanes between them. If more than 2 networks are specified, then lanes will be set up between all possible pairs of networks. @@ -132,28 +145,32 @@ The name of the networks are taken from [known_networks](https://github.com/smar If the network is not present in known_networks, then the network details can be specified in the config file itself under the following `EVMNetworks` key. #### 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. If `CCIP.Env.Network.EVMNetworks` config is not set for a network name specified under `CCIP.Env.Networks.selected_networks`, test will try to find the corresponding network config from defined networks in `MappedNetworks` under [known_networks.go](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/networks/known_networks.go) #### CCIP.Env.Network.AnvilConfigs -If the test needs to run on chains created using Anvil, then the AnvilConfigs can be specified. -It is a map of network name to `AnvilConfig` where key is network name specified under `CCIP.Env.Networks.selected_networks` and value is `AnvilConfig`. -The AnvilConfig is imported from [AnvilConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/network.go#L20) in chainlink-testing-framework. +If the test needs to run on chains created using Anvil, then the AnvilConfigs can be specified. +It is a map of network name to `AnvilConfig` where key is network name specified under `CCIP.Env.Networks.selected_networks` and value is `AnvilConfig`. +The AnvilConfig is imported from [AnvilConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/network.go#L20) in chainlink-testing-framework. **The following network configs are required for tests running on live networks. It can be ignored if the tests are running on simulated networks.** Refer to [secrets.toml.example](./examples/secrets.toml.example) for details. #### CCIP.ENV.Network.RpcHttpUrls + RpcHttpUrls is the RPC HTTP endpoints for each network, key is the network name as declared in selected_networks slice. #### CCIP.ENV.Network.RpcWsUrls + RpcWsUrls is the RPC WS endpoints for each network, key is the network name as declared in selected_networks slice. #### CCIP.ENV.Network.WalletKeys + WalletKeys is the private keys for each network, key is the network name as declared in selected_networks slice. Example Usage of Network Config: @@ -202,69 +219,95 @@ block_time = 1 ``` ### CCIP.Env.NewCLCluster -The NewCLCluster config holds the overall deployment configuration for Chainlink nodes. + +The NewCLCluster config holds the overall deployment configuration for Chainlink nodes. #### CCIP.Env.NewCLCluster.NoOfNodes + Specifies the number of Chainlink nodes to be deployed. #### CCIP.Env.NewCLCluster.Common + Specifies the common configuration for all Chainlink nodes if they share the same configuration. -##### Name: + +##### Name + Name of the node. -##### NeedsUpgrade: + +##### NeedsUpgrade + Indicates if the node needs an upgrade during test. -##### ChainlinkImage: + +##### ChainlinkImage + Configuration for the Chainlink image. -##### ChainlinkUpgradeImage: +##### ChainlinkUpgradeImage + Configuration for the Chainlink upgrade image. It is used when the node needs an upgrade. -##### BaseConfigTOML: +##### BaseConfigTOML + String containing the base configuration toml content for the Chainlink node config. -##### CommonChainConfigTOML: +##### CommonChainConfigTOML + String containing the common chain configuration toml content for all EVMNodes in chainlink node config. -##### ChainConfigTOMLByChain: +##### ChainConfigTOMLByChain + String containing the chain-specific configuration toml content for individual EVMNodes in chainlink node config. This is keyed by chain ID. -##### DBImage: +##### DBImage + Database image for the Chainlink node. -##### DBTag: +##### DBTag + Database tag/version for the Chainlink node. #### CCIP.Env.NewCLCluster.Nodes + Specifies the configuration for individual nodes if they differ from the common configuration. The fields are the same as the common configuration. #### CCIP.Env.NewCLCluster.NodeMemory + Specifies the memory to be allocated for each Chainlink node. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.NodeCPU + Specifies the CPU to be allocated for each Chainlink node. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.DBMemory + Specifies the memory to be allocated for the database. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.DBCPU + Specifies the CPU to be allocated for the database. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.IsStateful + Specifies whether the deployment is StatefulSet on Kubernetes. #### CCIP.Env.NewCLCluster.DBStorageClass + Specifies the storage class for the database. This is valid only if the deployment is StatefulSet on Kubernetes. #### CCIP.Env.NewCLCluster.DBCapacity + Specifies the capacity of the database. This is valid only if the deployment is StatefulSet on Kubernetes. #### CCIP.Env.NewCLCluster.PromPgExporter + Specifies whether to enable Prometheus PostgreSQL exporter. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.DBArgs + Specifies the arguments to be passed to the database. This is valid only if the deployment is on Kubernetes. Example Usage: + ```toml [CCIP.Env.NewCLCluster] NoOfNodes = 17 @@ -294,29 +337,42 @@ FeeCapDefault = '200 gwei' ``` ### CCIP.Env.ExistingCLCluster -The ExistingCLCluster config holds the overall connection configuration for existing Chainlink nodes. -It is needed when the tests are to be run on Chainlink nodes already deployed on some environment. -If this is specified, test will not need to connect to k8 namespace using [CCIP.Env.EnvToConnect](#ccipenvenvtoconnect) . + +The ExistingCLCluster config holds the overall connection configuration for existing Chainlink nodes. +It is needed when the tests are to be run on Chainlink nodes already deployed on some environment. +If this is specified, test will not need to connect to k8 namespace using [CCIP.Env.EnvToConnect](#ccipenvenvtoconnect). Test can directly connect to the existing Chainlink nodes using node credentials without knowing the k8 namespace details. #### CCIP.Env.ExistingCLCluster.Name + Specifies the name of the existing Chainlink cluster. This is used to identify the cluster in the test. #### CCIP.Env.ExistingCLCluster.NoOfNodes + Specifies the number of Chainlink nodes in the existing cluster. #### CCIP.Env.ExistingCLCluster.NodeConfigs + Specifies the configuration for individual nodes in the existing cluster. Each node config contains the following fields to connect to the Chainlink node: + ##### CCIP.Env.ExistingCLCluster.NodeConfigs.URL + The URL of the Chainlink node. -##### CCIP.Env.ExistingCLCluster.NodeConfigs.Email + +##### CCIP.Env.ExistingCLCluster.NodeConfigs.Email + The username/email of the Chainlink node credential. + ##### CCIP.Env.ExistingCLCluster.NodeConfigs.Password + The password of the Chainlink node credential. + ##### CCIP.Env.ExistingCLCluster.NodeConfigs.InternalIP + The internal IP of the Chainlink node. Example Usage: + ```toml [CCIP.Env.ExistingCLCluster] Name = 'crib-sample' @@ -355,23 +411,30 @@ InternalIP = 'app-node-5' ``` ### CCIP.Env.EnvToConnect + This is specified when the test needs to connect to already existing k8s namespace. User needs to have access to the k8 namespace to run the tests through specific kubeconfig file. Example usage: + ```toml [CCIP.Env] EnvToConnect="load-ccip-c8972" ``` + ### CCIP.ENV.TTL + Specifies the time to live for the k8 namespace. This is used to terminate the namespace after the tests are run. This is only valid if the tests are run on k8s. Example usage: + ```toml [CCIP.Env] TTL = "11h" ``` ### CCIP.Env.Logging + Specifies the logging configuration for the test. Imported from [LoggingConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/logging.go#L11) in chainlink-testing-framework. Example usage: + ```toml [CCIP.Env.Logging] test_log_collect = false # if set to true will save logs even if test did not fail @@ -394,53 +457,71 @@ dashboard_url = "/d/6vjVx-1V8/ccip-long-running-tests" ``` ### CCIP.Env.Lane.LeaderLaneEnabled + Specifies whether to enable the leader lane feature. This setting is only applicable for new deployments. ## CCIP.Groups + Specifies the test config specific to each test type. Available test types are: + - **CCIP.Groups.load** - **CCIP.Groups.smoke** - **CCIP.Groups.chaos** ### CCIP.Groups.[testgroup].KeepEnvAlive + Specifies whether to keep the k8 namespace alive after the test is run. This is only valid if the tests are run on k8s. ### CCIP.Groups.[testgroup].BiDirectionalLane -Specifies whether to set up bi-directional lanes between networks. + +Specifies whether to set up bi-directional lanes between networks. ### CCIP.Groups.[testgroup].CommitAndExecuteOnSameDON + Specifies whether commit and execution jobs are to be run on the same Chainlink node. +### CCIP.Groups.[testgroup].AllowOutOfOrder + +Specifies whether out of order execution is allowed globally for all the chains. + ### CCIP.Groups.[testgroup].NoOfCommitNodes + Specifies the number of nodes on which commit jobs are to be run. This needs to be lesser than the total number of nodes mentioned in [CCIP.Env.NewCLCluster.NoOfNodes](#ccipenvnewclclusternoofnodes) or [CCIP.Env.ExistingCLCluster.NoOfNodes](#ccipenvexistingclclusternoofnodes). If the value of total nodes is `n`, then the max value of NoOfCommitNodes should be less than `n-1`. As the first node is used for bootstrap job. If the NoOfCommitNodes is lesser than `n-1`, then the remaining nodes are used for execution jobs if `CCIP.Groups.[testgroup].CommitAndExecuteOnSameDON` is set to false. ### CCIP.Groups.[testgroup].TokenConfig + Specifies the token configuration for the test. The token configuration is used to set up tokens and token pools for all chains. #### CCIP.Groups.[testgroup].TokenConfig.NoOfTokensPerChain + Specifies the number of tokens to be set up for each chain. #### CCIP.Groups.[testgroup].TokenConfig.WithPipeline -Specifies whether to set up token pipelines in commit jobspec. If set to false, the token prices will be set with DynamicPriceGetterConfig. + +Specifies whether to set up token pipelines in commit jobspec. If set to false, the token prices will be set with DynamicPriceGetterConfig. #### CCIP.Groups.[testgroup].TokenConfig.TimeoutForPriceUpdate -Specifies the timeout to wait for token and gas price updates to be available in price registry for each chain. + +Specifies the timeout to wait for token and gas price updates to be available in price registry for each chain. #### CCIP.Groups.[testgroup].TokenConfig.NoOfTokensWithDynamicPrice + Specifies the number of tokens to be set up with dynamic price update. The rest of the tokens will be set up with static price. This is only valid if [WithPipeline](#ccipgroupstestgrouptokenconfigwithpipeline) is set to false. #### CCIP.Groups.[testgroup].TokenConfig.DynamicPriceUpdateInterval + Specifies the interval for dynamic price update for tokens. This is only valid if [NoOfTokensWithDynamicPrice](#ccipgroupstestgrouptokenconfignooftokenswithdynamicprice) is set to value greater tha zero. #### CCIP.Groups.[testgroup].TokenConfig.CCIPOwnerTokens + Specifies the tokens to be owned by the CCIP owner. If this is false, the tokens and pools will be owned by an address other than rest of CCIP contract admin addresses. This is applicable only if the contract versions are '1.5' or higher. Example Usage: -```toml +```toml [CCIP.Groups.load.TokenConfig] TimeoutForPriceUpdate = '15m' NoOfTokensPerChain = 60 @@ -450,27 +531,36 @@ CCIPOwnerTokens = true ``` ### CCIP.Groups.[testgroup].MsgDetails -Specifies the ccip message details to be sent by the test. + +Specifies the ccip message details to be sent by the test. + #### CCIP.Groups.[testgroup].MsgDetails.MsgType + Specifies the type of message to be sent. The supported message types are: + - **Token** - **Data** - **DataWithToken** #### CCIP.Groups.[testgroup].MsgDetails.DestGasLimit + Specifies the gas limit for the destination chain. This is used to in `ExtraArgs` field of CCIPMessage. Change this to 0, if you are doing ccip-send to an EOA in the destination chain. #### CCIP.Groups.[testgroup].MsgDetails.DataLength + Specifies the length of data to be sent in the message. This is only valid if [MsgType](#ccipgroupstestgroupmsgdetailsmsgtype) is set to 'Data' or 'DataWithToken'. #### CCIP.Groups.[testgroup].MsgDetails.NoOfTokens + Specifies the number of tokens to be sent in the message. This is only valid if [MsgType](#ccipgroupstestgroupmsgdetailsmsgtype) is set to 'Token' or 'DataWithToken'. It needs to be less than or equal to [NoOfTokensPerChain](#ccipgroupstestgrouptokenconfignooftokensperchain) specified in the test config. #### CCIP.Groups.[testgroup].MsgDetails.TokenAmount + Specifies the amount for each token to be sent in the message. This is only valid if [MsgType](#ccipgroupstestgroupmsgdetailsmsgtype) is set to 'Token' or 'DataWithToken'. Example Usage: + ```toml [CCIP.Groups.smoke.MsgDetails] MsgType = 'DataWithToken' @@ -481,15 +571,19 @@ AmountPerToken = 1 ``` ### CCIP.Groups.[testgroup].MulticallInOneTx + Specifies whether to send multiple ccip messages in a single transaction. ### CCIP.Groups.[testgroup].NoOfSendsInMulticall + Specifies the number of ccip messages to be sent in a single transaction. This is only valid if [MulticallInOneTx](#ccipgroupstestgroupmulticallinonetx) is set to true. ### CCIP.Groups.[testgroup].PhaseTimeout + The test validates various events in a ccip request lifecycle, like commit, execute, etc. This field specifies the timeout for each phase in the lifecycle. The timeout is calculated from the time the previous phase event is received. The following contract events are validated: + - **CCIPSendRequested on OnRamp** - **CCIPSendRequested event log to be Finalized** - **ReportAccepted on CommitStore** @@ -497,13 +591,16 @@ The following contract events are validated: - **ExecutionStateChanged on OffRamp** ### CCIP.Groups.[testgroup].LocalCluster + Specifies whether the test is to be run on a local docker. If set to true, the test environment will be set up on a local docker. ### CCIP.Groups.[testgroup].ExistingDeployment + Specifies whether the test is to be run on existing deployments. If set to true, the test will use the deployment data specified in [CCIP.Deployments](#ccipdeployments) for interacting with the ccip contracts. If the deployment data does not contain the required contract addresses, the test will fail. ### CCIP.Groups.[testgroup].ReuseContracts + Test loads contract/lane config from [contracts.json](../contracts/laneconfig/contracts.json) if no lane config is specified in [CCIP.Deployments](#ccipdeployments) If a certain contract is present in the contracts.json, the test will use the contract address from the contracts.json. This field specifies whether to reuse the contracts from [contracts.json](../contracts/laneconfig/contracts.json) @@ -511,58 +608,74 @@ For example if the contracts.json contains the contract address for PriceRegistr If `ReuseContracts` is set to false, the test will redeploy the contract instead of using the contract address from contracts.json. ### CCIP.Groups.[testgroup].NodeFunding + Specified the native token funding for each Chainlink node. It assumes that the native token decimals is 18. The funding is done by the private key specified in [CCIP.Env.Networks](#ccipenvnetworks) for each network. The funding is done only if the test is run on local docker or k8s. This is not applicable for [existing deployments](#ccipgroupstestgroupexistingdeployment) is set to true. ### CCIP.Groups.[testgroup].NetworkPairs -Specifies the network pairs for which the test is to be run. The test will set up lanes only between the specified network pairs. + +Specifies the network pairs for which the test is to be run. The test will set up lanes only between the specified network pairs. If the network pairs are not specified, the test will set up lanes between all possible pairs of networks mentioned in selected_networks in [CCIP.Env.Networks](#ccipenvnetworksselectednetworks) ### CCIP.Groups.[testgroup].NoOfNetworks -Specifies the number of networks to be used for the test. -If the number of networks is greater than the total number of networks specified in [CCIP.Env.Networks.selected_networks](#ccipenvnetworksselectednetworks) : + +Specifies the number of networks to be used for the test. +If the number of networks is greater than the total number of networks specified in [CCIP.Env.Networks.selected_networks](#ccipenvnetworksselectednetworks): + - the test will fail if the networks are live networks. - the test will create equal number of replicas of the first network with a new chain id if the networks are simulated networks. For example, if the `selected_networks` is ['SIMULATED_1','SIMULATED_2'] and `NoOfNetworks` is 3, the test will create 1 more network config by copying the network config of `SIMULATED_1` with a different chain id and use that as 3rd network. ### CCIP.Groups.[testgroup].NoOfRoutersPerPair + Specifies the number of routers to be set up for each network. ### CCIP.Groups.[testgroup].MaxNoOfLanes + Specifies the maximum number of lanes to be set up between networks. If this values is not set, the test will set up lanes between all possible pairs of networks mentioned in `selected_networks` in [CCIP.Env.Networks](#ccipenvnetworksselectednetworks). For example, if `selected_networks = ['SIMULATED_1', 'SIMULATED_2', 'SIMULATED_3']`, and `MaxNoOfLanes` is set to 2, it denotes that the test will randomly select the 2 lanes between all possible pairs `SIMULATED_1`, `SIMULATED_2`, and `SIMULATED_3` for the test run. ### CCIP.Groups.[testgroup].DenselyConnectedNetworkChainIds -This is applicable only if [MaxNoOfLanes](#ccipgroupstestgroupmaxnooflanes) is specified. + +This is applicable only if [MaxNoOfLanes](#ccipgroupstestgroupmaxnooflanes) is specified. Specifies the chain ids for networks to be densely connected. If this is provided the test will include all possible pairs of networks mentioned in `DenselyConnectedNetworkChainIds`. The rest of the networks will be connected randomly based on the value of `MaxNoOfLanes`. ### CCIP.Groups.[testgroup].ChaosDuration + Specifies the duration for which the chaos experiment is to be run. This is only valid if the test type is 'chaos'. ### CCIP.Groups.[testgroup].USDCMockDeployment + Specifies whether to deploy USDC mock contract for the test. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). The following fields are used for various parameters in OCR2 commit and execution jobspecs. All of these are only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). + ### CCIP.Groups.[testgroup].CommitOCRParams + Specifies the OCR parameters for the commit job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). ### CCIP.Groups.[testgroup].ExecuteOCRParams + Specifies the OCR parameters for the execute job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). ### CCIP.Groups.[testgroup].CommitInflightExpiry + 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].OffRampConfig + Specifies the offramp configuration for the execution job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). This is used to set values for following fields in execution jobspec's offchain and onchain config: + - **OffRampConfig.MaxDataBytes** - **OffRampConfig.BatchGasLimit** - **OffRampConfig.InflightExpiry** - **OffRampConfig.RootSnooze** Example Usage: + ```toml [CCIP.Groups.load] CommitInflightExpiry = '5m' @@ -594,43 +707,53 @@ BatchGasLimit = 11000000 MaxDataBytes = 1000 InflightExpiry = '5m' RootSnooze = '5m' - ``` ### CCIP.Groups.[testgroup].StoreLaneConfig + This is only valid if the tests are run on remote runners in k8s. If set to true, the test will store the lane config in the remote runner. ### CCIP.Groups.[testgroup].LoadProfile -Specifies the load profile for the test. Only valid if the testgroup is 'load'. + +Specifies the load profile for the test. Only valid if the testgroup is 'load'. ### CCIP.Groups.[testgroup].LoadProfile.LoadFrequency.[DestNetworkName] #### CCIP.Groups.[testgroup].LoadProfile.RequestPerUnitTime + Specifies the number of requests to be sent per unit time. This is applicable to all networks if [LoadFrequency](#ccipgroupstestgrouploadprofileloadfrequencydestnetworkname) is not specified for a destination network. #### CCIP.Groups.[testgroup].LoadProfile.TimeUnit + Specifies the unit of time for the load profile. This is applicable to all networks if [LoadFrequency](#ccipgroupstestgrouploadprofileloadfrequencydestnetworkname) is not specified for a destination network. #### CCIP.Groups.[testgroup].LoadProfile.StepDuration + Specifies the duration for each step in the load profile. This is applicable to all networks if [LoadFrequency](#ccipgroupstestgrouploadprofileloadfrequencydestnetworkname) is not specified for a destination network. #### CCIP.Groups.[testgroup].LoadProfile.TestDuration + Specifies the total duration for the load test. #### CCIP.Groups.[testgroup].LoadProfile.NetworkChaosDelay + Specifies the duration network delay used for `NetworkChaos` experiment. This is only valid if the test is run on k8s and not on [existing deployments](#ccipgroupstestgroupexistingdeployment). #### CCIP.Groups.[testgroup].LoadProfile.WaitBetweenChaosDuringLoad + 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. -The test will only store contract addresses strictly necessary to trigger/validate ccip-send requests. + +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. +The test will only store contract addresses strictly necessary to trigger/validate ccip-send requests. Except for following contracts all other contract addresses will be discarded after the initial lane set up - + - Router - ARM - CommitStore @@ -638,37 +761,45 @@ Except for following contracts all other contract addresses will be discarded af - OnRamp #### CCIP.Groups.[testgroup].LoadProfile.FailOnFirstErrorInLoad + If set to true, the test will fail on the first error encountered during load run. If set to false, the test will continue to run even if there are errors during load run. #### CCIP.Groups.[testgroup].LoadProfile.SendMaxDataInEveryMsgCount -Specifies the number of requests to send with maximum data in every mentioned count iteration. + +Specifies the number of requests to send with maximum data in every mentioned count iteration. For example, if `SendMaxDataInEveryMsgCount` is set to 5, the test will send ccip message with max allowable data length(as set in onRamp config) in every 5th request. #### CCIP.Groups.[testgroup].LoadProfile.TestRunName + Specifies the name of the test run. This is used to identify the test run in CCIP test dashboard or logs. If multiple tests are run with same `TestRunName`, the test results will be aggregated under the same test run in grafana dashboard. This is used when multiple iterations of tests are run against same release version to aggregate the results under same dashboard view. #### CCIP.Groups.[testgroup].LoadProfile.MsgProfile + Specifies the message profile for the test. The message profile is used to set up multiple ccip message details during load test. ##### CCIP.Groups.[testgroup].LoadProfile.MsgProfile.Frequencies -Specifies the frequency of each message profile. + +Specifies the frequency of each message profile. For example, if `Frequencies` is set to [1, 2, 3], the test will send 1st message profile 1 time, 2nd message profile 2 times, and 3rd message profile 3 times in each iteration. Each iteration will be defined by (1+2+3) = 6 requests. Example Breakdown: + - Frequencies = [4, 12, 3, 1] - Total Sum of Frequencies = 4 + 12 + 3 + 1 = 20 - Percentages: - - Message Type 1: (4 / 20) * 100% = 20% - - Message Type 2: (12 / 20) * 100% = 60% - - Message Type 3: (3 / 20) * 100% = 15% - - Message Type 4: (1 / 20) * 100% = 5% + - Message Type 1: (4 / 20) * 100% = 20% + - Message Type 2: (12 / 20) * 100% = 60% + - Message Type 3: (3 / 20) * 100% = 15% + - Message Type 4: (1 / 20) * 100% = 5% These percentages reflect how often each message type should appear in the total set of messages. Please note - if the total set of messages is not equal to the multiple of sum of frequencies, the percentages will not be accurate. ##### CCIP.Groups.[testgroup].LoadProfile.MsgProfile.MsgDetails + Specifies the message details for each message profile. The fields are the same as [CCIP.Groups.[testgroup].MsgDetails](#ccipgroupstestgroupmsgdetails). example usage: + ```toml # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 60d7055cb31..0a53ee18732 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -10,8 +10,8 @@ import ( "github.com/rs/zerolog" "github.com/smartcontractkit/chainlink-common/pkg/config" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - ctfK8config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctfK8config "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" ccipcontracts "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" testutils "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/utils" @@ -242,6 +242,9 @@ 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 } @@ -251,12 +254,22 @@ func (l *LoadProfile) SetTestRunName(name string) { } } +type ReorgProfile struct { + FinalityDelta int `toml:",omitempty"` +} + +func (gp *ReorgProfile) Validate() error { + // FinalityDelta can be validated only relatively to CL nodes settings, see setupReorgSuite method + return nil +} + // 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"` @@ -280,6 +293,7 @@ type CCIPTestGroupConfig struct { CommitInflightExpiry *config.Duration `toml:",omitempty"` StoreLaneConfig *bool `toml:",omitempty"` LoadProfile *LoadProfile `toml:",omitempty"` + ReorgProfile *ReorgProfile `toml:",omitempty"` } func (c *CCIPTestGroupConfig) Validate() error { @@ -387,6 +401,18 @@ type CCIP struct { Groups map[string]*CCIPTestGroupConfig `toml:",omitempty"` } +// LoadFromEnv loads selected env vars into the CCIP config +func (c *CCIP) LoadFromEnv() error { + if c.Env == nil { + c.Env = &Common{} + } + err := c.Env.ReadFromEnvVar() + if err != nil { + return err + } + return nil +} + func (c *CCIP) Validate() error { if c.Env != nil { err := c.Env.Validate() diff --git a/integration-tests/ccip-tests/testconfig/examples/.testsecrets.example b/integration-tests/ccip-tests/testconfig/examples/.testsecrets.example new file mode 100644 index 00000000000..52afa77015e --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/examples/.testsecrets.example @@ -0,0 +1,39 @@ +# DO NOT UPDATE THIS FILE WITH ANY SECRET VALUES. +# This file serves as a template for the actual ~/.testsecrets file. Follow these steps to use it: +# 1. Create a copy of this template in your home directory under ~/.testsecrets +# 2. Update ~/.testsecrets with actual secret values required for your tests. The file will be automatically loaded by the test framework +# 3. Only include secrets necessary for the tests you are running. For example, if you are only running tests on Ethereum Mainnet, you do not need secrets for Base Mainnet. Comment other env vars. +# DO NOT COMMIT THE ACTUAL SECRETS FILE TO THE REPOSITORY. + +# Chainlink image used for NewCLCluster +E2E_TEST_CHAINLINK_IMAGE="***.dkr.ecr.***.amazonaws.com/chainlink-ccip" + +# Chainlink upgrade image for NewCLCluster. Used only for upgrade tests +E2E_TEST_CHAINLINK_UPGRADE_IMAGE="***.dkr.ecr.***.amazonaws.com/chainlink-ccip" + +# Ethereum network secrets +E2E_TEST_ETHEREUM_MAINNET_WALLET_KEY="" +E2E_TEST_ETHEREUM_MAINNET_RPC_HTTP_URL="" +E2E_TEST_ETHEREUM_MAINNET_RPC_HTTP_URL_1="" +E2E_TEST_ETHEREUM_MAINNET_RPC_WS_URL="" +E2E_TEST_ETHEREUM_MAINNET_RPC_WS_URL_1="" + +# Base network secrets +E2E_TEST_BASE_MAINNET_WALLET_KEY="" +E2E_TEST_BASE_MAINNET_RPC_HTTP_URL="" +E2E_TEST_BASE_MAINNET_RPC_HTTP_URL_1="" +E2E_TEST_BASE_MAINNET_RPC_WS_URL="" +E2E_TEST_BASE_MAINNET_RPC_WS_URL_1="" + +# Other networks secrets (pattern for envs) +# E2E_TEST_(.+)_WALLET_KEY_(\d+)="" +# E2E_TEST_(.+)_RPC_HTTP_URL_(\d+)="" +# E2E_TEST_(.+)_RPC_WS_URL_(\d+)="" + +# Loki secrets +E2E_TEST_LOKI_TENANT_ID="" +E2E_TEST_LOKI_ENDPOINT="" + +# Grafana secrets +E2E_TEST_GRAFANA_BASE_URL="" +E2E_TEST_GRAFANA_DASHBOARD_URL="/d/6vjVx-1V8/ccip-long-running-tests" \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/examples/secrets.toml.example b/integration-tests/ccip-tests/testconfig/examples/secrets.toml.example deleted file mode 100644 index 3045f51759d..00000000000 --- a/integration-tests/ccip-tests/testconfig/examples/secrets.toml.example +++ /dev/null @@ -1,52 +0,0 @@ -# This file contains all secret parameters for ccip tests. -# DO NOT UPDATE THIS FILE WITH ANY SECRET VALUES. -# Use this file as a template for the actual secret file and update all the parameter values accordingly. -# DO NOT COMMIT THE ACTUAL SECRET FILE TO THE REPOSITORY. -[CCIP] -[CCIP.Env] - -# ChainlinkImage is mandatory for all tests. -[CCIP.Env.NewCLCluster] -[CCIP.Env.NewCLCluster.Common] -[CCIP.Env.NewCLCluster.Common.ChainlinkImage] -image = "chainlink-ccip" -version = "latest" - -# Chainlink upgrade image is used only for upgrade tests -#[CCIP.Env.NewCLCluster.Common.ChainlinkUpgradeImage] -#image = "***.dkr.ecr.***.amazonaws.com/chainlink-ccip" -#version = "****" - - -# Networks configuration with rpc urls and wallet keys are mandatory only for tests running on live networks -# The following example is for 3 networks: Ethereum, Base and Arbitrum -# Network configuration can be ignored for tests running on simulated/private networks -[CCIP.Env.Network] -selected_networks= [ - 'ETHEREUM_MAINNET','BASE_MAINNET', 'ARBITRUM_MAINNET', -] - -[CCIP.Env.Network.RpcHttpUrls] -ETHEREUM_MAINNET = ['', ''] -BASE_MAINNET = ['', ''] -ARBITRUM_MAINNET = ['', ''] - -[CCIP.Env.Network.RpcWsUrls] -ETHEREUM_MAINNET = ['', ''] -BASE_MAINNET = ['', ''] -ARBITRUM_MAINNET = ['', ''] - -[CCIP.Env.Network.WalletKeys] -ETHEREUM_MAINNET = [''] -BASE_MAINNET = [''] -ARBITRUM_MAINNET = [''] - -# Used for tests using 1. loki logging for test results. -# Mandatory for load tests -[CCIP.Env.Logging.Loki] -tenant_id="" -endpoint="" - -[CCIP.Env.Logging.Grafana] -base_url="" -dashboard_url="/d/6vjVx-1V8/ccip-long-running-tests" diff --git a/integration-tests/ccip-tests/testconfig/global.go b/integration-tests/ccip-tests/testconfig/global.go index 331737c5fbf..d2b3f599b1f 100644 --- a/integration-tests/ccip-tests/testconfig/global.go +++ b/integration-tests/ccip-tests/testconfig/global.go @@ -12,24 +12,24 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink-common/pkg/config" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" "github.com/smartcontractkit/chainlink/integration-tests/client" ) const ( - OVERIDECONFIG = "BASE64_CCIP_CONFIG_OVERRIDE" - - SECRETSCONFIG = "BASE64_CCIP_SECRETS_CONFIG" + OVERIDECONFIG = "BASE64_CONFIG_OVERRIDE" ErrReadConfig = "failed to read TOML config" ErrUnmarshalConfig = "failed to unmarshal TOML config" Load string = "load" @@ -105,52 +105,47 @@ func EncodeConfigAndSetEnv(c any, envVar string) (string, error) { func NewConfig() (*Config, error) { cfg := &Config{} var override *Config - var secrets *Config + // var secrets *Config // load config from default file err := config.DecodeTOML(bytes.NewReader(DefaultConfig), cfg) if err != nil { return nil, errors.Wrap(err, ErrReadConfig) } - // load config from env var if specified - rawConfig, _ := osutil.GetEnv(OVERIDECONFIG) - if rawConfig != "" { - err = DecodeConfig(rawConfig, &override) - if err != nil { - return nil, fmt.Errorf("failed to decode override config: %w", err) - } - } - if override != nil { - // apply overrides for all products - if override.CCIP != nil { - if cfg.CCIP == nil { - cfg.CCIP = override.CCIP - } else { - err = cfg.CCIP.ApplyOverrides(override.CCIP) - if err != nil { - return nil, err + // load config overrides from env var if specified + // there can be multiple overrides separated by comma + rawConfigs, _ := osutil.GetEnv(OVERIDECONFIG) + if rawConfigs != "" { + for _, rawConfig := range strings.Split(rawConfigs, ",") { + err = DecodeConfig(rawConfig, &override) + if err != nil { + return nil, fmt.Errorf("failed to decode override config: %w", err) + } + if override != nil { + // apply overrides for all products + if override.CCIP != nil { + if cfg.CCIP == nil { + cfg.CCIP = override.CCIP + } else { + err = cfg.CCIP.ApplyOverrides(override.CCIP) + if err != nil { + return nil, err + } + } } } } } + // read secrets for all products if cfg.CCIP != nil { - // load config from env var if specified for secrets - secretRawConfig, _ := osutil.GetEnv(SECRETSCONFIG) - if secretRawConfig != "" { - err = DecodeConfig(secretRawConfig, &secrets) - if err != nil { - return nil, fmt.Errorf("failed to decode secrets config: %w", err) - } - if secrets != nil { - // apply secrets for all products - if secrets.CCIP != nil { - err = cfg.CCIP.ApplyOverrides(secrets.CCIP) - if err != nil { - return nil, fmt.Errorf("failed to apply secrets: %w", err) - } - } - } + err := ctfconfig.LoadSecretEnvsFromFiles() + if err != nil { + return nil, errors.Wrap(err, "error loading testsecrets files") + } + err = cfg.CCIP.LoadFromEnv() + if err != nil { + return nil, errors.Wrap(err, "error loading env vars into CCIP config") } // validate all products err = cfg.CCIP.Validate() @@ -176,6 +171,243 @@ type Common struct { Logging *ctfconfig.LoggingConfig `toml:",omitempty"` } +// ReadFromEnvVar loads selected env vars into the config +func (p *Common) ReadFromEnvVar() error { + logger := logging.GetTestLogger(nil) + + testLogCollect := ctfconfig.MustReadEnvVar_Boolean(ctfconfig.E2E_TEST_LOG_COLLECT_ENV) + if testLogCollect != nil { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.TestLogCollect", ctfconfig.E2E_TEST_LOG_COLLECT_ENV) + p.Logging.TestLogCollect = testLogCollect + } + + loggingRunID := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOGGING_RUN_ID_ENV) + if loggingRunID != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.RunID", ctfconfig.E2E_TEST_LOGGING_RUN_ID_ENV) + p.Logging.RunId = &loggingRunID + } + + logstreamLogTargets := ctfconfig.MustReadEnvVar_Strings(ctfconfig.E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV, ",") + if len(logstreamLogTargets) > 0 { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.LogStream == nil { + p.Logging.LogStream = &ctfconfig.LogStreamConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.LogStream.LogTargets", ctfconfig.E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV) + p.Logging.LogStream.LogTargets = logstreamLogTargets + } + + lokiTenantID := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_TENANT_ID_ENV) + if lokiTenantID != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.TenantId", ctfconfig.E2E_TEST_LOKI_TENANT_ID_ENV) + p.Logging.Loki.TenantId = &lokiTenantID + } + + lokiEndpoint := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_ENDPOINT_ENV) + if lokiEndpoint != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.Endpoint", ctfconfig.E2E_TEST_LOKI_ENDPOINT_ENV) + p.Logging.Loki.Endpoint = &lokiEndpoint + } + + lokiBasicAuth := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_BASIC_AUTH_ENV) + if lokiBasicAuth != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.BasicAuth", ctfconfig.E2E_TEST_LOKI_BASIC_AUTH_ENV) + p.Logging.Loki.BasicAuth = &lokiBasicAuth + } + + lokiBearerToken := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + if lokiBearerToken != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.BearerToken", ctfconfig.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + p.Logging.Loki.BearerToken = &lokiBearerToken + } + + grafanaBaseUrl := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_BASE_URL_ENV) + if grafanaBaseUrl != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.BaseUrl", ctfconfig.E2E_TEST_GRAFANA_BASE_URL_ENV) + p.Logging.Grafana.BaseUrl = &grafanaBaseUrl + } + + grafanaDashboardUrl := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + if grafanaDashboardUrl != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.DashboardUrl", ctfconfig.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + p.Logging.Grafana.DashboardUrl = &grafanaDashboardUrl + } + + grafanaBearerToken := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + if grafanaBearerToken != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.BearerToken", ctfconfig.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + p.Logging.Grafana.BearerToken = &grafanaBearerToken + } + + selectedNetworks := ctfconfig.MustReadEnvVar_Strings(ctfconfig.E2E_TEST_SELECTED_NETWORK_ENV, ",") + if len(selectedNetworks) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s env var to override Network.SelectedNetworks", ctfconfig.E2E_TEST_SELECTED_NETWORK_ENV) + p.Network.SelectedNetworks = selectedNetworks + } + + walletKeys := ctfconfig.ReadEnvVarGroupedMap(ctfconfig.E2E_TEST_WALLET_KEY_ENV, ctfconfig.E2E_TEST_WALLET_KEYS_ENV) + if len(walletKeys) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s and/or %s env vars to override Network.WalletKeys", ctfconfig.E2E_TEST_WALLET_KEY_ENV, ctfconfig.E2E_TEST_WALLET_KEYS_ENV) + p.Network.WalletKeys = walletKeys + } + + rpcHttpUrls := ctfconfig.ReadEnvVarGroupedMap(ctfconfig.E2E_TEST_RPC_HTTP_URL_ENV, ctfconfig.E2E_TEST_RPC_HTTP_URLS_ENV) + if len(rpcHttpUrls) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s and/or %s env vars to override Network.RpcHttpUrls", ctfconfig.E2E_TEST_RPC_HTTP_URL_ENV, ctfconfig.E2E_TEST_RPC_HTTP_URLS_ENV) + p.Network.RpcHttpUrls = rpcHttpUrls + } + + rpcWsUrls := ctfconfig.ReadEnvVarGroupedMap(ctfconfig.E2E_TEST_RPC_WS_URL_ENV, ctfconfig.E2E_TEST_RPC_WS_URLS_ENV) + if len(rpcWsUrls) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s and/or %s env vars to override Network.RpcWsUrls", ctfconfig.E2E_TEST_RPC_WS_URL_ENV, ctfconfig.E2E_TEST_RPC_WS_URLS_ENV) + p.Network.RpcWsUrls = rpcWsUrls + } + + chainlinkImage := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_IMAGE_ENV) + if chainlinkImage != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkImage == nil { + p.NewCLCluster.Common.ChainlinkImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkImage.Image", ctfconfig.E2E_TEST_CHAINLINK_IMAGE_ENV) + p.NewCLCluster.Common.ChainlinkImage.Image = &chainlinkImage + } + + chainlinkVersion := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_VERSION_ENV) + if chainlinkVersion != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkImage == nil { + p.NewCLCluster.Common.ChainlinkImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkImage.Version", ctfconfig.E2E_TEST_CHAINLINK_VERSION_ENV) + p.NewCLCluster.Common.ChainlinkImage.Version = &chainlinkVersion + } + + chainlinkPostgresVersion := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_POSTGRES_VERSION_ENV) + if chainlinkPostgresVersion != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkImage == nil { + p.NewCLCluster.Common.ChainlinkImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkImage.PostgresVersion", ctfconfig.E2E_TEST_CHAINLINK_POSTGRES_VERSION_ENV) + p.NewCLCluster.Common.ChainlinkImage.PostgresVersion = &chainlinkPostgresVersion + } + + chainlinkUpgradeImage := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + if chainlinkUpgradeImage != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkUpgradeImage == nil { + p.NewCLCluster.Common.ChainlinkUpgradeImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkUpgradeImage.Image", ctfconfig.E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + p.NewCLCluster.Common.ChainlinkUpgradeImage.Image = &chainlinkUpgradeImage + } + + chainlinkUpgradeVersion := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_UPGRADE_VERSION_ENV) + if chainlinkUpgradeVersion != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkImage == nil { + p.NewCLCluster.Common.ChainlinkImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkUpgradeImage.Version", ctfconfig.E2E_TEST_CHAINLINK_UPGRADE_VERSION_ENV) + p.NewCLCluster.Common.ChainlinkUpgradeImage.Version = &chainlinkUpgradeVersion + } + + return nil +} + func (p *Common) GetNodeConfig() *ctfconfig.NodeConfig { return &ctfconfig.NodeConfig{ BaseConfigTOML: p.NewCLCluster.Common.BaseConfigTOML, @@ -198,10 +430,6 @@ func (p *Common) Validate() error { // read the default network config, if specified p.Network.UpperCaseNetworkNames() p.Network.OverrideURLsAndKeysFromEVMNetwork() - err := p.Network.Default() - if err != nil { - return fmt.Errorf("error reading default network config %w", err) - } if err := p.Network.Validate(); err != nil { return fmt.Errorf("error validating networks config %w", err) } diff --git a/integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml b/integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml deleted file mode 100644 index 7d457774b02..00000000000 --- a/integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml +++ /dev/null @@ -1,712 +0,0 @@ -[CCIP] -[CCIP.ContractVersions] -PriceRegistry = '1.2.0' -OffRamp = '1.2.0' -OnRamp = '1.2.0' -TokenPool = '1.4.0' -CommitStore = '1.2.0' - -[CCIP.Deployments] -Data = """ -{ - "lane_configs": { - "Arbitrum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", - "bridge_tokens": ["0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"], - "bridge_tokens_pools": ["0x34700F5faE61Ba628c4269BdCbA12DA53bbfa726"], - "arm": "0xe06b0e8c4bd455153e8794ad7Ea8Ff5A14B64E4b", - "router": "0x141fa059441E0ca23ce184B6A78bafD2A517DdE8", - "price_registry": "0x13015e4E6f839E1Aa1016DF521ea458ecA20438c", - "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", - "version" : "1.4.0", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", - "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", - "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", - "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", - "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", - "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", - "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", - "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Avalanche Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x5947BB275c521040051D82396192181b413227A3", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xdFD6C0dc67666DE3bB36b31eec5c7B1542A82C1E", - "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", - "price_registry": "0xfA4edD04eaAcDB07c8D73621bc1790eC50D8c489", - "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", - "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", - "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", - "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", - "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", - "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", - "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", - "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Base Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x38660c8CC222c0192b635c2ac09687B4F25cCE5F", - "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", - "price_registry": "0x6337a58D4BD7Ba691B66341779e8f87d4679923a", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", - "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", - "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", - "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", - "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", - "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", - "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "BSC Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x404460C6A5EdE2D891e8297795264fDe62ADBB75", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x3DB43b96B2625F4232e9Df900d464dd2c64C0021", - "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", - "price_registry": "0xd64aAbD70A71d9f0A00B99F6EFc1626aA2dD43C7", - "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", - "deployed_at": 11111111 - }, - "Arbitrum Mainnet": { - "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", - "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Arbitrum Mainnet": { - "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", - "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", - "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", - "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", - "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", - "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", - "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Ethereum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x514910771AF9Ca656af840dff83E8264EcF986CA", - "bridge_tokens": ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], - "bridge_tokens_pools": ["0x69c24c970B65e22Ac26864aF10b2295B7d78f93A"], - "arm": "0x8B63b3DE93431C0f756A493644d128134291fA1b", - "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", - "price_registry": "0x8c9b2Efb7c64C394119270bfecE7f54763b958Ad", - "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", - "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", - "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", - "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", - "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", - "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", - "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", - "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Kroma Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xB59779d3364BC6d71168245f9ebb96469E5a5a98", - "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", - "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", - "wrapped_native": "0x4200000000000000000000000000000000000001", - "src_contracts": { - "WeMix Mainnet": { - "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "WeMix Mainnet": { - "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", - "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Optimism Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6", - "bridge_tokens": ["0x4200000000000000000000000000000000000006"], - "bridge_tokens_pools": ["0x86E715415D8C8435903d1e8204fA1e9784Aa7305"], - "arm": "0x8C7C2C3362a42308BB5c368677Ad321D11693b81", - "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", - "price_registry": "0xb52545aECE8C73A97E52a146757EC15b90Ed8488", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", - "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", - "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", - "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", - "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", - "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", - "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Polygon Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xb0897686c545045aFc77CF20eC7A532E3120E0F1", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xD7AcF65dA1E1f34b663aB199a474F209bF2b0523", - "router": "0x849c5ED5a80F5B408Dd4969b78c2C8fdf0565Bfe", - "price_registry": "0x30D873664Ba766C983984C7AF9A921ccE36D34e1", - "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", - "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", - "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", - "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", - "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", - "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", - "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", - "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "WeMix Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x80f1FcdC96B55e459BF52b998aBBE2c364935d69", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x07aaC8B69A62dB5bd3d244091916EbF2fac17b76", - "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", - "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", - "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", - "deployed_at": 11111111 - }, - "Kroma Mainnet": { - "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", - "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", - "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", - "commit_store": "0x84534BE763366a69710E119c100832955795B34B", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", - "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", - "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", - "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Kroma Mainnet": { - "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", - "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - } - } -} -""" - -[CCIP.Env] -TTL = '8h' - -[CCIP.Env.Network] -selected_networks = [ - 'ETHEREUM_MAINNET', - 'ARBITRUM_MAINNET', - 'OPTIMISM_MAINNET' - ] - -[CCIP.Groups.load] -NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', - 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', - 'ARBITRUM_MAINNET,OPTIMISM_MAINNET' # added as batch 1 -] - -BiDirectionalLane = true -PhaseTimeout = '40m' -ExistingDeployment = true - -[CCIP.Groups.load.TokenConfig] -NoOfTokensPerChain = 1 -CCIPOwnerTokens = true - -[CCIP.Groups.load.LoadProfile] -RequestPerUnitTime = [1] -TimeUnit = '3h' -TestDuration = '24h' -TestRunName = 'mainnet-2.7-ccip1.2' -FailOnFirstErrorInLoad = true -SkipRequestIfAnotherRequestTriggeredWithin = '40m' - -[[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] -MsgType = 'Data' -DestGasLimit = 0 -DataLength = 100 -NoOfTokens = 1 -AmountPerToken = 1 - -[CCIP.Groups.smoke] -# these are all the valid network pairs -NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', - 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', - 'ARBITRUM_MAINNET,OPTIMISM_MAINNET' -] - -BiDirectionalLane = true -DestGasLimit = 0 -PhaseTimeout = '20m' -LocalCluster = false -ExistingDeployment = true -ReuseContracts = true - -[CCIP.Groups.smoke.TokenConfig] -NoOfTokensPerChain = 1 -CCIPOwnerTokens = true - -[CCIP.Groups.smoke.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/override/mainnet.toml b/integration-tests/ccip-tests/testconfig/override/mainnet.toml index 72695ba7545..f723411eafc 100644 --- a/integration-tests/ccip-tests/testconfig/override/mainnet.toml +++ b/integration-tests/ccip-tests/testconfig/override/mainnet.toml @@ -9,639 +9,1070 @@ CommitStore = '1.2.0' [CCIP.Deployments] Data = """ { - "lane_configs": { + "lane_configs": { + "Arbitrum Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + "arm": "0xC2C5E22a2d9715ed5C5BCC4D8eFf5966cf260744", + "router": "0x141fa059441E0ca23ce184B6A78bafD2A517DdE8", + "price_registry": "0x13015e4E6f839E1Aa1016DF521ea458ecA20438c", + "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + "src_contracts": { + "Avalanche Mainnet": { + "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x54480425E9e24138fdF1644a1F70007F25abfB46", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x1216DC856Af47a833254a280A038185F51C1B5c4", + "deployed_at": 0 + }, + "Metis Andromeda": { + "on_ramp": "0x5b23A0a103fC9028363B3BC3577e8Bd45B8E819F", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x3920BF474BB50fffb4B77c1e6e66F65210D1D722", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", + "deployed_at": 0 + }, + "ZKSync Mainnet": { + "on_ramp": "0x2C1016053d9873270d71613cA321aE97Fc89201d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Mainnet": { + "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", + "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", + "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", + "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x449C59F4Ef3b1802DD054dd7837Eb2Ca91aFAB84", + "commit_store": "0x1E0e8B01693A248b3Aa1e5aca36336F9022Ceac0", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", + "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0x0C00414D9dcDB2DA7BF8AF26aE2deb617f09e756", + "commit_store": "0x1d464cd86c5C8358d56281aB31d2213534CCEA13", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Metis Andromeda": { + "off_ramp": "0xeF8dEb0c01f7389AD4ae05DAB30120dba915D53c", + "commit_store": "0xE594a09Aa8bCb55188758826A160615B95A6F3fE", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xEDE7ADACFbD27DBEBbE2d6C3BaDf12a634a72Faa", + "commit_store": "0x032B209a6B7a00336047505b55a4cBFBd29eE2c1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", + "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", + "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", + "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "ZKSync Mainnet": { + "off_ramp": "0x50Fc0de671c775301e1Bdf19C17E778D0f978f6F", + "commit_store": "0x87732C2647168818ED49268EdA8A98C2e62ed744", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Avalanche Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", + "arm": "0x4f6Ec25f06A114ADD3154DC17fb637F750AdaA31", + "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", + "price_registry": "0x2d3b38E0a4DFFDad2A613f7760bE1683F272eA18", + "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xBd0B9317F6AaA1085993F7b4CD468dE7A6428722", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", + "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", + "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", + "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", + "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xDE7ebf1Dc753D916A9fbEC4ae521Ee74EC2d0B5f", + "commit_store": "0x2dbc917b4DD455532015949c3103B64fcDB891b2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", + "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", + "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", + "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "BSC Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "arm": "0x56491A98199aD2e687Ea9D0cFB7b4AC57B4980Fc", + "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", + "price_registry": "0x18C3D917D55Bc1784a3d4729AA3e2C1ecd662fFd", + "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x02082b23D35d2670B8a636A431F3C30AF9d21e07", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xAc9fE4179816077674d769698306CE6A7C6A1096", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x4A83dA46c148AB5941a379b4cA49f42d14281C78", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", + "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", + "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", + "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x6500EDFBD27d34b7B69D0D45865ddaC4A1ceafE1", + "commit_store": "0x3A328B3fA852409415c15271442EFE4c77C04992", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", + "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xBE9b0cc569E970dAb953d336c670fc6b7c856c19", + "commit_store": "0xEe89CC6C2236d3b99C2D9c0b3b911690F757FadF", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0x6C702159daA4DEbae32E294c584B1EaF2356cB1A", + "commit_store": "0x73C8d1E9e240331E3345c6fBe6CDFC71B742B69C", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", + "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", + "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", + "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Base Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x91cB19E7c4Ba9B08CF544cDc9143042150B007C3", + "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", + "price_registry": "0x1bA15c57c8b74cD32443D7583E7f6d7c638aCf46", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { "Arbitrum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xe06b0e8c4bd455153e8794ad7Ea8Ff5A14B64E4b", - "router": "0x141fa059441E0ca23ce184B6A78bafD2A517DdE8", - "price_registry": "0x13015e4E6f839E1Aa1016DF521ea458ecA20438c", - "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", - "version" : "1.4.0", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", - "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", - "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", - "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", - "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", - "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", - "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", - "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", + "deployed_at": 0 }, "Avalanche Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x5947BB275c521040051D82396192181b413227A3", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xdFD6C0dc67666DE3bB36b31eec5c7B1542A82C1E", - "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", - "price_registry": "0xfA4edD04eaAcDB07c8D73621bc1790eC50D8c489", - "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", - "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", - "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", - "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", - "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", - "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", - "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", - "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0xCCC32e2794EaD73f0a0a514Ac1c78D048968ab81", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xcDD0e963E0708a4E936202396983E458cFA4A363", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x626aCCbDDD73532df1caEDb5628Fdc40C5f429Ba", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", + "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", + "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", + "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x15F54FDd37ccC8E5a0b64633C95Ef8209Fd86401", + "commit_store": "0x52b5b4f3Cc50E38f736f23897f192430E131ccB8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", + "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xA24D3Bc3A59798a57AF58f69c89DC1C8aFD78F18", + "commit_store": "0x672dbdC3aF7eE37436fe101531D33266D85F33c9", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xFC30bFe46b11D4E25C6f7492fd064A70FbF18848", + "commit_store": "0xaeDBe55633F74A291F0A43Daa0Fd719615b78363", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", + "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", + "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Blast Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4300000000000000000000000000000000000004", + "arm": "0x96aFe20249C4f6f55d2fe0E792138f6a4dC566A4", + "router": "0x12e0B8E349C6fb7E6E40713E8125C3cF1127ea8C", + "price_registry": "0x4f66d9e65af0d3DC27897E29f571f933291bb07c", + "wrapped_native": "0x4300000000000000000000000000000000000004", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x42E1f5f5ACCe6e4971D9B9468D7A9Abed8D69DdD", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x9c98d7aE731b0A53bedffBc1a12d9d43501Ea464", + "deployed_at": 0 }, "Base Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x38660c8CC222c0192b635c2ac09687B4F25cCE5F", - "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", - "price_registry": "0x6337a58D4BD7Ba691B66341779e8f87d4679923a", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", - "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", - "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", - "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", - "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", - "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", - "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "on_ramp": "0x955f139225F5d7021EB911ED2787a795f71E5eb6", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xBD9bf9AA79adF083BB7100848Eb15F4e8282E27e", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x01A38cd2da195C704bA192fCCDddd8986cb7EdE9", + "commit_store": "0xab6D69db1C1E9B97a26eB3983b0878AdeD248200", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "BSC Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x404460C6A5EdE2D891e8297795264fDe62ADBB75", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x3DB43b96B2625F4232e9Df900d464dd2c64C0021", - "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", - "price_registry": "0xd64aAbD70A71d9f0A00B99F6EFc1626aA2dD43C7", - "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", - "deployed_at": 11111111 - }, - "Arbitrum Mainnet": { - "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", - "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Arbitrum Mainnet": { - "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", - "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", - "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", - "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", - "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", - "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", - "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "off_ramp": "0xabC7Dffb2590c44a201EC7532382e1fc01Cd9eEb", + "commit_store": "0xA3086bf1D609d8e8028E8339e4aa4362C7da339D", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x0406F8f66C10Da99ff518bc2242e0Ec486a2c787", + "commit_store": "0xc6A97d753a3001e0B893e5FA2b0ec3d623af6C20", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "Ethereum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x514910771AF9Ca656af840dff83E8264EcF986CA", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x8B63b3DE93431C0f756A493644d128134291fA1b", - "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", - "price_registry": "0x8c9b2Efb7c64C394119270bfecE7f54763b958Ad", - "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", - "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", - "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", - "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", - "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", - "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", - "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", - "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "off_ramp": "0x4e0092bBC8EfAb6Eca295caB66986193b90a1Bb9", + "commit_store": "0xd7cA96B58EE33FdB3aa1392c30eD02645b1F28e2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Celo": { + "is_native_fee_token": true, + "fee_token": "0x2021B12D8138e2D63cF0895eccABC0DFc92416c6", + "arm": "0x832Ca6A279D8F8c695986086B35c70D4E0c817CC", + "router": "0xfB48f15480926A4ADf9116Dca468bDd2EE6C5F62", + "price_registry": "0xD9FcEEA20dBB3Dfb91763B301819C9666429DC26", + "wrapped_native": "0x2021B12D8138e2D63cF0895eccABC0DFc92416c6", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x27C96A8a2f70a8408aD6c620717a3bDaA54bb10b", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0x90902C0AEE857F3A42f2beBEa38724cE7b7a0cff", + "commit_store": "0x25adA90B241143DD5Df04Fb06C1fF6E7f7624ad9", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Ethereum Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "arm": "0xdCD48419bD5Cd9d1b097695F2af4Ee125aADF84F", + "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", + "price_registry": "0x020082A7a9c2510e1921116001152DEE4da81985", + "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", + "deployed_at": 0 }, - "Kroma Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xB59779d3364BC6d71168245f9ebb96469E5a5a98", - "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", - "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", - "wrapped_native": "0x4200000000000000000000000000000000000001", - "src_contracts": { - "WeMix Mainnet": { - "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "WeMix Mainnet": { - "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", - "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "Avalanche Mainnet": { + "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x4545F9a17DA50110632C14704a15d893BF9CBD27", + "deployed_at": 0 + }, + "Celo": { + "on_ramp": "0xEd5bE9508ae56531cc0EDe6A3bD588Eb9E2e3cfa", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xF538dA6c673A30338269655f4e019B71ba58CFd4", + "deployed_at": 0 + }, + "Metis Andromeda": { + "on_ramp": "0xa5ef33B57dD8B653F9A9EA7114f46376d18264aC", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x466a078d17e3706a9414ACc48029EE9Bae4C9b65", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", + "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": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", + "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", + "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", + "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", + "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x1a904DbbaDdE629a1460e2F6E2E485Ce06Ed7599", + "commit_store": "0x3CB2A81bb8a188C5353CdFa9994ed8666556FC53", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Celo": { + "off_ramp": "0xd5083684eE92dDeA117636ae5E2F1cb7fE4dfd46", + "commit_store": "0x831097033C88c82a7F1897b168Aa88cC44540C8f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xE93ec2A57e38C8541c893348cCafEAB01F7D47d4", + "commit_store": "0x118a9389960F86390A4F14ce4C95D6ff076C6bFC", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Metis Andromeda": { + "off_ramp": "0xCe6364dBe64D2789D916180131fAda2ABFF702E8", + "commit_store": "0x3d8a95adA63D406ee8232562AbD83CEdb0B90466", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xE8af3b68eDfFf65Ce48648009982380701f09B92", + "commit_store": "0x76264869a3eBF51a59FCa5ABa84ee2867c7F190e", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", + "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", + "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", + "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "ZKSync Mainnet": { + "off_ramp": "0xb368c8946D9fa5A497cDe1Dff7213f9CdfD143Bf", + "commit_store": "0xa4d264470a67D9f6682EE12Bdc9c35Df44e3F194", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Gnosis Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", + "arm": "0x2ab5ff904CFFdD37f19cC34597cF425916F2DAcA", + "router": "0x4aAD6071085df840abD9Baf1697d5D5992bDadce", + "price_registry": "0xec00a50EFb62F5f686E0FdEFDD6e10744dc53cAD", + "wrapped_native": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x7A36511202f54a8A3Bc62Cc1df24bd391f7c9864", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x732753869bc6bB07Ec81A403F926bbF6fC2FeaE2", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xD5d33bc0BF395B39514B7f9f8F66ebc9D8e650Cb", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x400eFb50480a73FEc02b115b53F0Ec6EcFf03C67", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x0F246651F1c2275B4E14d8ae166D1fd3Af05c405", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x391516732884d3F8Eec3301C19b819E6e6044C17", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x566c7A2Cb557c36082301B97E998721D14E4bF7d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x1bee1FD97824288a36B725f9CF20E07A67d5113b", + "commit_store": "0xB3a48e8664C5dE26822ae44577b100b717C36a54", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x633c19cCD7A818770f7BF59eB9C5AB632CDbc4D5", + "commit_store": "0xbbC073fb2D424eA45A571cc4dd91745E45d0aC73", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x4D90524de5783257fd64d1a20689a5b9Bad25de0", + "commit_store": "0xAae8De9f1B7e2FFF0563c2BBf0c69593BD517b52", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x9118303DE7f4342F9B057f6EC1Be282aa543D99C", + "commit_store": "0xa75f463b8a1d8bf7694Ac13E02938894F45eFbaA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xFF61E57A2eE83FA262006C2DaF0D5fB2b36F3070", + "commit_store": "0xF433De9A293553c133E2dB90e226c2F2911f435C", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0x9D3aA479525a5BcE776dD83769e9F9b5B4dD4193", + "commit_store": "0x2B721632693A8BbABa3bA5F125C8cD33D66F28F7", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x9714098CDdAc380D4443293C55B6CBf6D6bbDbEb", + "commit_store": "0x4338f204C7698eE678d6c44117503f812ca1FA69", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Kroma Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000001", + "arm": "0xB558b375D1D8a1aE2c3d5bBe43634BcF4d0d108c", + "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", + "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", + "wrapped_native": "0x4200000000000000000000000000000000000001", + "src_contracts": { + "WeMix Mainnet": { + "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Mainnet": { + "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", + "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Metis Andromeda": { + "is_native_fee_token": true, + "fee_token": "0x75cb093E4D61d2A2e65D8e0BBb01DE8d89b53481", + "arm": "0xC4BFAc3D31C524A4958c5d5d1e68394d8DEbbE69", + "router": "0x7b9FB8717D306e2e08ce2e1Efa81F026bf9AD13c", + "price_registry": "0xe1A7e2f9E88a72aF3E4790f33FfcDEa43d5eCC7B", + "wrapped_native": "0x75cb093E4D61d2A2e65D8e0BBb01DE8d89b53481", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x87353b87A373E1551D27EDacDaC1644741c6499F", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xE43f9eD3146d76E627C2504E5140005027992De6", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x2cc33de75dAFDb3F8F4f24244a9C420374e2C001", + "commit_store": "0x67fE38dB73be154a1f1a63221F898B9d5EE4eF63", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xc2B1A8c931582D041ba5fF30AEB9fA828B30754d", + "commit_store": "0x90073Ea7A1Ee4Fe5d638B4216Bc60479Eba52001", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Mode Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x77EAF440c5d24e25D1834CBBF623bFd83b8b5dA1", + "router": "0x24C40f13E77De2aFf37c280BA06c333531589bf1", + "price_registry": "0xffDEc5d752dd1fa1f56C236183ACB022e5D9d79e", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x65Ad802d80aD6a96C5a4bc9e57E16099de99Dc7F", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x8C5149ff7Cfd99dd561caE9B7abFAA0Ef79eAbeC", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x71dB32eF442c29d8cbf72a9AFcb1Ef12B35b0BF4", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xbD5F9C193a7fEF5D578C55Ddfe4d08d6BCc15648", + "deployed_at": 0 }, "Optimism Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x8C7C2C3362a42308BB5c368677Ad321D11693b81", - "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", - "price_registry": "0xb52545aECE8C73A97E52a146757EC15b90Ed8488", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", - "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", - "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", - "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", - "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", - "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", - "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "on_ramp": "0x659303e8d4306D3ea8676FB034d56FB6f37E19d9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x8d3E1b15ebC96cec1ffc092cEcAeA6c1DD00aF9b", + "commit_store": "0x1f1DEa0210aE346A20E270a1C3355d99b0B949D2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x7a57670Fa0Cf1Bc2665a1Ae0f5031b9f5a43dD3a", + "commit_store": "0x18ffb74D94175d00D8bB67B70737dE2cE45eed07", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xEfa90cE6289A2777cd5B8fb991B2D0Be44cA5067", + "commit_store": "0xACa5f0942Bb7fF297A7c25E8364373702D81bb3f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xdF8f09AB4DfB49dEC8a0B8b7f1B7F4134252D3e9", + "commit_store": "0x8Ae635d264f20f1dbC0dea03712C194AdbeF50D1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xE4D6AAF678b986D3E6B7A85FA33d0519716a5525", + "commit_store": "0xBF80E30c8c013Ec0d05e2a959CF8000407C813EC", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Optimism Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x1c51b6D5BFcFB7ee82C80949DFD146dB157a7E49", + "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", + "price_registry": "0x9270AAA75F4B9038f4c25fEc665B02a150a90361", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x14aA3CC03583aA557DBca4ce72288Cc5F37DDE34", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x034eA573B049210315110f7eA11c9618E32F08Ae", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xaC8C94242aa8234Bf89682aBcDDf805AE8cff61D", + "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", + "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", + "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", + "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", + "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0x4358640A2419119DBe0933b5F2c288c3EB2c082C", + "commit_store": "0x44d1a05ef6e54a3CB35a1497303bA272f15f45ed", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xDf9717d724828537902Fb0c3B7C56c641463Fa38", + "commit_store": "0x8aEFF283381914E07Fc371601D59648ab6D2C0B1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "Polygon Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xb0897686c545045aFc77CF20eC7A532E3120E0F1", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xD7AcF65dA1E1f34b663aB199a474F209bF2b0523", - "router": "0x849c5ED5a80F5B408Dd4969b78c2C8fdf0565Bfe", - "price_registry": "0x30D873664Ba766C983984C7AF9A921ccE36D34e1", - "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", - "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", - "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", - "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", - "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", - "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", - "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", - "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", + "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "WeMix Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x80f1FcdC96B55e459BF52b998aBBE2c364935d69", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x07aaC8B69A62dB5bd3d244091916EbF2fac17b76", - "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", - "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", - "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", - "deployed_at": 11111111 - }, - "Kroma Mainnet": { - "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", - "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", - "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", - "commit_store": "0x84534BE763366a69710E119c100832955795B34B", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", - "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", - "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", - "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Kroma Mainnet": { - "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", - "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } + "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", + "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Polygon Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "arm": "0x569a295a09634Ac9414c3efe4E8931986d68F937", + "router": "0x849c5ED5a80F5B408Dd4969b78c2C8fdf0565Bfe", + "price_registry": "0x30D873664Ba766C983984C7AF9A921ccE36D34e1", + "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x4616621704C81801A56D29c961F9395ee153d46C", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", + "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", + "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", + "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", + "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", + "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0x0A04eC196454825d361886cf4FA113A948164Ef8", + "commit_store": "0x74b72633b63A8f4374a12DB6F609305BC5a1b2d5", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", + "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", + "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "WeMix Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", + "arm": "0xdBa0afF04bf63Ba6b75DEC94d1A934a367CAA782", + "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", + "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", + "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", + "deployed_at": 0 + }, + "Kroma Mainnet": { + "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", + "deployed_at": 0 } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", + "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", + "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", + "commit_store": "0x84534BE763366a69710E119c100832955795B34B", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", + "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Kroma Mainnet": { + "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", + "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", + "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", + "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "ZKSync Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", + "arm": "0x4e2438b1395a462E2e8D164b5f3c65d080919449", + "router": "0x748Fd769d81F5D94752bf8B0875E9301d0ba71bB", + "price_registry": "0xa0C6E00a9Fa10A04989c237dF6dfDCe2AaceE4A3", + "wrapped_native": "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x9033687a0f03012e015f8f8f2a59da57531d2B43", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x3B80Fe300c9A611abA0496e2543B66Ff7bD4B9e9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xF0a08aC528668D4fe8C4cF235a8B82cbf242Fa9d", + "commit_store": "0x5a3C9b21b03E4eBcccb57D296e7ff54102F04424", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x7c887B97F9Bba9355EC10e2bA949AdB491Ef44Fd", + "commit_store": "0xA42bf0c8794FA8853Ec0F1B24a489972e8CF4C30", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } } + } } """ @@ -650,15 +1081,15 @@ TTL = '8h' [CCIP.Env.Network] selected_networks = [ - 'ETHEREUM_MAINNET', 'ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET', + 'BSC_MAINNET', 'BASE_MAINNET', - 'WEMIX_MAINNET', + 'ETHEREUM_MAINNET', + 'KROMA_MAINNET', 'OPTIMISM_MAINNET', 'POLYGON_MAINNET', - 'AVALANCHE_MAINNET', - 'BSC_MAINNET', - 'KROMA_MAINNET' + 'WEMIX_MAINNET', ] [CCIP.Groups.load] @@ -694,7 +1125,7 @@ NetworkPairs = [ ] BiDirectionalLane = true -PhaseTimeout = '20m' +PhaseTimeout = '30m' ExistingDeployment = true [CCIP.Groups.load.TokenConfig] @@ -704,7 +1135,7 @@ NoOfTokensPerChain = 1 RequestPerUnitTime = [1] TimeUnit = '1h' TestDuration = '5h' -TestRunName = 'mainnet-2.7-ccip1.2' +TestRunName = 'Soak_test_mainnet' FailOnFirstErrorInLoad = true SkipRequestIfAnotherRequestTriggeredWithin = '40m' @@ -718,7 +1149,7 @@ AmountPerToken = 1 [CCIP.Groups.smoke] # these are all the valid network pairs NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', + 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', 'ETHEREUM_MAINNET,POLYGON_MAINNET', 'ETHEREUM_MAINNET,BSC_MAINNET', 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 new file mode 100644 index 00000000000..592cb046ad3 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml @@ -0,0 +1,283 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +TokenPool = 'latest' +CommitStore = 'latest' + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "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", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x6BD0f1efA261Ea84DB219c1284b538A65E530ea1", + "deployed_at": 29428386 + }, + "Optimism Sepolia": { + "on_ramp": "0x94cd0d171eF08924F0008305e5Bb90b0fC1b61AB", + "deployed_at": 13945916 + }, + "Sepolia Testnet": { + "on_ramp": "0x44225eb3B73B1b52Dd2ecD258F9b63418eC6Bf79", + "deployed_at": 13730868 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x21560B4ACAEdb8AA2Dd935618F15da43197bdc12", + "commit_store": "0x27B882c393151ADD910F3557849AF0bb09c7d5A6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", + "commit_store": "0x1f1160Ac7828B647A85c9a6b3A58A232C59D67Ab", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xc136114F379b812345bb7e467ECDdb6D0c87De8b", + "commit_store": "0x42b3EbEA14F6CB803e3C7df84392Efb85CE90168", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "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 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x41E59DCdDec18d7f79DA5F76Ce567d2c5e301E6B", + "commit_store": "0x9487C01D4b3Ae1c9Ac8740A07f3862D646548A14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x622CB640F52bFfA68b78b2BD12c1940Ca4899621", + "deployed_at": 8020540 + }, + "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", + "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" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BSC_TESTNET', + 'OPTIMISM_SEPOLIA', + 'SEPOLIA' +] + + + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + 'BSC_TESTNET,AVALANCHE_FUJI', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +] + +BiDirectionalLane = true +PhaseTimeout = '40m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[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 = [ + 'AVALANCHE_FUJI,BSC_TESTNET', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +] + +BiDirectionalLane = true +PhaseTimeout = '40m' +ExistingDeployment = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +# Soak Test profile +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '6m' +TestDuration = '3h' +TestRunName = 'BetaSoakTest_CCIPV1dot5' +FailOnFirstErrorInLoad = true + +[[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_native.toml b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml new file mode 100644 index 00000000000..fcc063c7659 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml @@ -0,0 +1,295 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +TokenPool = 'latest' +CommitStore = 'latest' + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Sepolia": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", + "price_registry": "0x25d997d8618e1299418b3D905E40bC353ec89F61", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x6BD0f1efA261Ea84DB219c1284b538A65E530ea1", + "deployed_at": 29428386 + }, + "Optimism Sepolia": { + "on_ramp": "0x94cd0d171eF08924F0008305e5Bb90b0fC1b61AB", + "deployed_at": 13945916 + }, + "Sepolia Testnet": { + "on_ramp": "0x44225eb3B73B1b52Dd2ecD258F9b63418eC6Bf79", + "deployed_at": 13730868 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x21560B4ACAEdb8AA2Dd935618F15da43197bdc12", + "commit_store": "0x27B882c393151ADD910F3557849AF0bb09c7d5A6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", + "commit_store": "0x1f1160Ac7828B647A85c9a6b3A58A232C59D67Ab", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xc136114F379b812345bb7e467ECDdb6D0c87De8b", + "commit_store": "0x42b3EbEA14F6CB803e3C7df84392Efb85CE90168", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Avalanche Fuji": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "bridge_tokens": [ + "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846" + ], + "bridge_tokens_pools": [ + "0x156943ae87AaF63eA9272902Cb05407ec7bc9464" + ], + "price_aggregators": null, + "arm": "0xD4A51dC0F5C680A8A18eA4Ec3A2f25C6db9424B7", + "router": "0xa62e685aDFF45f38eC94378513D128F168964E99", + "price_registry": "0xdbeA1a10AC6a2B729bF128aE9281Ed420dbE7113", + "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 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x41E59DCdDec18d7f79DA5F76Ce567d2c5e301E6B", + "commit_store": "0x9487C01D4b3Ae1c9Ac8740A07f3862D646548A14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Base Sepolia": { + "is_native_fee_token": true, + "is_mock_arm": 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", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Optimism Sepolia": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", + "price_registry": "0x3B80b7Ef5c00Eb892CBe72800C028C47AD6380EF", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x622CB640F52bFfA68b78b2BD12c1940Ca4899621", + "deployed_at": 8020540 + }, + "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", + "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" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BSC_TESTNET', + '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', +] + +BiDirectionalLane = true +PhaseTimeout = '30m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[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 = [ + 'AVALANCHE_FUJI,BSC_TESTNET', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +] + +BiDirectionalLane = true +PhaseTimeout = '40m' +ExistingDeployment = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +# Soak Test profile +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '6m' +TestDuration = '3h' +TestRunName = 'BetaSoakTest_V2.14.0-1.5.1' +FailOnFirstErrorInLoad = true + +[[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/ccip-default.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml index 0157ac24fb4..b03f03a6dab 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml @@ -27,7 +27,7 @@ ethereum_version = "eth1" # geth, besu, erigon or nethermind execution_layer = "geth" # eth2-only, if set to true environment startup will wait until at least 1 epoch has been finalised -wait_for_finalization=false +wait_for_finalization = false [CCIP.Env.PrivateEthereumNetworks.SIMULATED_1.EthereumChainConfig] # eth2-only, the lower the value the faster the block production (3 is minimum) @@ -239,6 +239,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 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 @@ -271,7 +273,7 @@ TimeoutForPriceUpdate = '15m' # Duration to wait for the price update to time-ou # Now testing only with dynamic price getter (no pipeline). # Could be removed once the pipeline is completely removed. WithPipeline = false -NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' +NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CCIPOwner, otherwise the tokens will be deployed by a non-owner account, only applicable for 1.5 pools and onwards #NoOfTokensWithDynamicPrice = 15 # number of tokens with dynamic price to be deployed @@ -293,6 +295,7 @@ CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CC KeepEnvAlive = false # same as above CommitAndExecuteOnSameDON = true # same as above +AllowOutOfOrder = false # same as above BiDirectionalLane = true # same as above NoOfCommitNodes = 5 # same as above PhaseTimeout = '10m' # same as above @@ -351,7 +354,7 @@ TimeoutForPriceUpdate = '15m' # Duration to wait for the price update to time-ou # Now testing only with dynamic price getter (no pipeline). # Could be removed once the pipeline is completely removed. WithPipeline = false -NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' +NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CCIPOwner, otherwise the tokens and pools will be deployed by a non-owner account, # only applicable for 1.5 pools and onwards, if you are running with pre-1.5 pools, then set this to true to deploy token pools by CCIPOwner, otherwise # the test will fail @@ -403,6 +406,7 @@ CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CC #NetworkPairs = ['SEPOLIA,OPTIMISM_GOERLI','SEPOLIA,POLYGON_MUMBAI','AVALANCHE_FUJI,SEPOLIA','SEPOLIA,BASE_GOERLI','SEPOLIA,BSC_TESTNET','SEPOLIA,WEMIX_TESTNET','AVALANCHE_FUJI,OPTIMISM_GOERLI','AVALANCHE_FUJI,POLYGON_MUMBAI','AVALANCHE_FUJI,BSC_TESTNET','AVALANCHE_FUJI,BASE_GOERLI','OPTIMISM_GOERLI,BASE_GOERLI','OPTIMISM_GOERLI,POLYGON_MUMBAI','BSC_TESTNET,POLYGON_MUMBAI','BSC_TESTNET,BASE_GOERLI','WEMIX_TESTNET,KROMA_SEPOLIA'] KeepEnvAlive = false CommitAndExecuteOnSameDON = false +AllowOutOfOrder = false BiDirectionalLane = true NoOfCommitNodes = 5 PhaseTimeout = '50m' diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml new file mode 100644 index 00000000000..afcba2247fd --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml @@ -0,0 +1,64 @@ +[CCIP] +[CCIP.Env] +Mockserver = 'http://mockserver:1080' +[CCIP.Env.Network] +selected_networks= ['SIMULATED_1', 'SIMULATED_2'] + +[CCIP.Env.Network.EVMNetworks.SIMULATED_1] +evm_name = 'source-chain' +evm_chain_id = 1337 +evm_keys = ['59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d', '7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6'] +evm_simulated = true +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '3m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_depth = 10 + +[CCIP.Env.Network.EVMNetworks.SIMULATED_2] +evm_name = 'dest-chain' +evm_chain_id = 2337 +evm_keys = ['ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', '7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6'] +evm_simulated = true +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '3m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_depth = 10 + +[CCIP.Env.NewCLCluster] +NoOfNodes = 6 +NodeMemory = '4Gi' +NodeCPU = '2' +DBMemory = '4Gi' +DBCPU = '2' +DBCapacity = '10Gi' +IsStateful = true +DBArgs = ['shared_buffers=1536MB', 'effective_cache_size=4096MB', 'work_mem=64MB'] + +[CCIP.Env.NewCLCluster.Common] +CommonChainConfigTOML = """ +LogPollInterval = '1s' +[HeadTracker] +HistoryDepth = 30 + +[GasEstimator] +PriceMax = '200 gwei' +LimitDefault = 6000000 +FeeCapDefault = '200 gwei' +""" + +[CCIP.Groups.smoke] +PhaseTimeout = '3m' # Duration to wait for the each phase validation(SendRequested, Commit, RMN Blessing, Execution) to time-out. +LocalCluster = true + +[CCIP.Groups.smoke.ReorgProfile] +FinalityDelta = 5 + + diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml similarity index 99% rename from integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml rename to integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml index f8321584c84..f13965d5e67 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml @@ -933,7 +933,7 @@ NoOfTokensPerChain = 1 RequestPerUnitTime = [1] TimeUnit = '5s' TestDuration = '1h' -TestRunName = 'v2.12.0-ccip1.4.16-load' +TestRunName = 'ccip-prod-testnet-stress' # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] 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 new file mode 100644 index 00000000000..24e7cbc9c88 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml @@ -0,0 +1,1035 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +CommitStore = 'latest' +TokenPool = 'latest' + + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "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", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", + "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", + "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", + "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", + "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", + "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", + "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", + "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", + "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", + "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", + "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", + "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", + "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", + "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", + "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", + "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", + "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", + "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", + "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", + "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", + "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", + "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", + "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", + "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", + "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", + "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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": { + "Sepolia Testnet": { + "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", + "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", + "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", + "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", + "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", + "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", + "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", + "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", + "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Testnet": { + "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", + "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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": { + "Sepolia Testnet": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", + "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", + "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", + "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", + "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", + "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", + "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", + "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", + "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", + "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", + "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", + "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", + "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", + "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "deployed_at": 0 + }, + "Celo Alfajores": { + "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "deployed_at": 0 + }, + "ZKSync Sepolia": { + "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", + "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", + "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", + "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", + "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", + "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Celo Alfajores": { + "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", + "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", + "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", + "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", + "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", + "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", + "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", + "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "ZKSync Sepolia": { + "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", + "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "deployed_at": 0 + }, + "Kroma Sepolia": { + "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", + "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", + "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", + "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Kroma Sepolia": { + "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", + "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", + "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", + "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", + "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "ZKSync Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", + "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", + "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", + "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", + "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BLAST_SEPOLIA', + 'BSC_TESTNET', + 'CELO_ALFAJORES', + 'GNOSIS_CHIADO', + 'KROMA_SEPOLIA', + 'MODE_SEPOLIA', + 'OPTIMISM_SEPOLIA', + 'POLYGON_AMOY', + 'SEPOLIA', + 'METIS_SEPOLIA', + 'WEMIX_TESTNET', + 'ZKSYNC_SEPOLIA' +] + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + '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,WEMIX_TESTNET', + 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', + + 'BASE_SEPOLIA,MODE_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA,GNOSIS_CHIADO', + + 'KROMA_SEPOLIA,WEMIX_TESTNET', + + 'OPTIMISM_SEPOLIA,POLYGON_AMOY', + 'OPTIMISM_SEPOLIA,WEMIX_TESTNET', + 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', + + 'POLYGON_AMOY,WEMIX_TESTNET', + 'POLYGON_AMOY,GNOSIS_CHIADO', +] + +BiDirectionalLane = true +PhaseTimeout = '30m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.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/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 new file mode 100644 index 00000000000..b1549377fda --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml @@ -0,0 +1,1035 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +CommitStore = 'latest' +TokenPool = 'latest' + + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "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", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", + "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", + "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", + "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", + "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", + "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", + "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", + "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", + "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", + "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", + "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", + "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", + "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", + "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", + "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", + "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", + "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", + "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", + "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", + "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", + "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", + "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", + "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", + "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", + "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", + "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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": { + "Sepolia Testnet": { + "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", + "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", + "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", + "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", + "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", + "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", + "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", + "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", + "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Testnet": { + "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", + "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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": { + "Sepolia Testnet": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", + "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", + "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", + "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", + "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", + "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", + "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", + "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", + "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", + "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", + "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", + "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", + "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", + "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "deployed_at": 0 + }, + "Celo Alfajores": { + "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "deployed_at": 0 + }, + "ZKSync Sepolia": { + "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", + "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", + "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", + "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", + "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", + "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Celo Alfajores": { + "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", + "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", + "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", + "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", + "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", + "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", + "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", + "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "ZKSync Sepolia": { + "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", + "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "deployed_at": 0 + }, + "Kroma Sepolia": { + "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", + "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", + "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", + "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Kroma Sepolia": { + "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", + "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", + "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", + "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", + "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "ZKSync Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", + "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", + "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", + "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", + "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BLAST_SEPOLIA', + 'BSC_TESTNET', + 'CELO_ALFAJORES', + 'GNOSIS_CHIADO', + 'KROMA_SEPOLIA', + 'MODE_SEPOLIA', + 'OPTIMISM_SEPOLIA', + 'POLYGON_AMOY', + 'SEPOLIA', + 'METIS_SEPOLIA', + 'WEMIX_TESTNET', + 'ZKSYNC_SEPOLIA' +] + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + '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,WEMIX_TESTNET', + 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', + + 'BASE_SEPOLIA,MODE_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA,GNOSIS_CHIADO', + + 'KROMA_SEPOLIA,WEMIX_TESTNET', + + 'OPTIMISM_SEPOLIA,POLYGON_AMOY', + 'OPTIMISM_SEPOLIA,WEMIX_TESTNET', + 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', + + 'POLYGON_AMOY,WEMIX_TESTNET', + 'POLYGON_AMOY,GNOSIS_CHIADO', +] + +BiDirectionalLane = true +PhaseTimeout = '30m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.MsgDetails] +MsgType = 'DataWithToken' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file 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 new file mode 100644 index 00000000000..6a6aa205fce --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml @@ -0,0 +1,1013 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = '1.2.0' +OffRamp = '1.2.0' +OnRamp = '1.2.0' +TokenPool = '1.4.0' +CommitStore = '1.2.0' + + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "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", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", + "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", + "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", + "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", + "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", + "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", + "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", + "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", + "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", + "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", + "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", + "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", + "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", + "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", + "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", + "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", + "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", + "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", + "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", + "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", + "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", + "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", + "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", + "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", + "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", + "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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": { + "Sepolia Testnet": { + "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", + "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", + "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", + "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", + "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", + "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", + "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", + "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", + "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Testnet": { + "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", + "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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": { + "Sepolia Testnet": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", + "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", + "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", + "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", + "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", + "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", + "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", + "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", + "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", + "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", + "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", + "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", + "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", + "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "deployed_at": 0 + }, + "Celo Alfajores": { + "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "deployed_at": 0 + }, + "ZKSync Sepolia": { + "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", + "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", + "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", + "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", + "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", + "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Celo Alfajores": { + "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", + "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", + "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", + "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", + "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", + "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", + "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", + "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "ZKSync Sepolia": { + "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", + "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "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", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "deployed_at": 0 + }, + "Kroma Sepolia": { + "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", + "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", + "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", + "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Kroma Sepolia": { + "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", + "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", + "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", + "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", + "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "ZKSync Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", + "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", + "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", + "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", + "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BLAST_SEPOLIA', + 'BSC_TESTNET', + 'CELO_ALFAJORES', + 'GNOSIS_CHIADO', + 'KROMA_SEPOLIA', + 'MODE_SEPOLIA', + 'OPTIMISM_SEPOLIA', + 'POLYGON_AMOY', + 'SEPOLIA', + 'METIS_SEPOLIA', + 'WEMIX_TESTNET', + 'ZKSYNC_SEPOLIA' +] + +[CCIP.Groups.load] +NetworkPairs = [ + 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI,BASE_SEPOLIA', + 'AVALANCHE_FUJI,OPTIMISM_SEPOLIA', + 'AVALANCHE_FUJI,POLYGON_AMOY', + 'AVALANCHE_FUJI,GNOSIS_CHIADO', + 'ARBITRUM_SEPOLIA,BASE_SEPOLIA', + 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', + 'ARBITRUM_SEPOLIA,SEPOLIA', + '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', + 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', + 'BSC_TESTNET,GNOSIS_CHIADO', +] + +BiDirectionalLane = true +PhaseTimeout = '20m' +ExistingDeployment = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '6m' +TestDuration = '24h' +TestRunName = 'SoakTest_prod_testnet' +FailOnFirstErrorInLoad = true + +[[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/testreporters/ccip.go b/integration-tests/ccip-tests/testreporters/ccip.go index b567f6a6291..d9c2908304c 100644 --- a/integration-tests/ccip-tests/testreporters/ccip.go +++ b/integration-tests/ccip-tests/testreporters/ccip.go @@ -13,8 +13,8 @@ import ( "github.com/rs/zerolog" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" ) type Phase string diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 207773aace4..eee424d50d1 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -27,15 +27,15 @@ import ( chainselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" integrationactions "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index 63018c9fe44..263d291453d 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -13,24 +13,24 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/foundry" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/foundry" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/reorg" "github.com/smartcontractkit/chainlink-common/pkg/config" - k8config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" + k8config "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/types/config/node" @@ -53,7 +53,7 @@ func SetResourceProfile(cpu, mem string) map[string]interface{} { } } -func setNodeConfig(nets []blockchain.EVMNetwork, nodeConfig, commonChain string, configByChain map[string]string) (*corechainlink.Config, string, error) { +func SetNodeConfig(nets []blockchain.EVMNetwork, nodeConfig, commonChain string, configByChain map[string]string) (*corechainlink.Config, string, error) { var tomlCfg *corechainlink.Config var err error var commonChainConfig *evmcfg.Chain @@ -122,7 +122,7 @@ func ChainlinkPropsForUpdate( chainConfigByChain = testInputs.EnvInput.NewCLCluster.Common.ChainConfigTOMLByChain } - _, tomlStr, err := setNodeConfig( + _, tomlStr, err := SetNodeConfig( testInputs.SelectedNetworks, nodeConfig, commonChainConfig, chainConfigByChain, ) @@ -150,7 +150,7 @@ func ChainlinkPropsForUpdate( "version": upgradeTag, }, } - _, tomlStr, err := setNodeConfig( + _, tomlStr, err := SetNodeConfig( testInputs.SelectedNetworks, testInputs.EnvInput.NewCLCluster.Common.BaseConfigTOML, testInputs.EnvInput.NewCLCluster.Common.CommonChainConfigTOML, @@ -216,7 +216,7 @@ func ChainlinkChart( chainConfigByChain = testInputs.EnvInput.NewCLCluster.Common.ChainConfigTOMLByChain } - _, tomlStr, err := setNodeConfig(nets, nodeConfig, commonChainConfig, chainConfigByChain) + _, tomlStr, err := SetNodeConfig(nets, nodeConfig, commonChainConfig, chainConfigByChain) require.NoError(t, err) nodesMap = append(nodesMap, map[string]any{ "name": clNode.Name, @@ -240,7 +240,7 @@ func ChainlinkChart( return chainlink.New(0, clProps) } clProps["replicas"] = pointer.GetInt(testInputs.EnvInput.NewCLCluster.NoOfNodes) - _, tomlStr, err := setNodeConfig( + _, tomlStr, err := SetNodeConfig( nets, testInputs.EnvInput.NewCLCluster.Common.BaseConfigTOML, testInputs.EnvInput.NewCLCluster.Common.CommonChainConfigTOML, @@ -332,10 +332,13 @@ func DeployLocalCluster( // a func to start the CL nodes asynchronously deployCL := func() error { noOfNodes := pointer.GetInt(testInputs.EnvInput.NewCLCluster.NoOfNodes) + if env.ClCluster == nil { + env.ClCluster = &test_env.ClCluster{} + } // if individual nodes are specified, then deploy them with specified configs if len(testInputs.EnvInput.NewCLCluster.Nodes) > 0 { for _, clNode := range testInputs.EnvInput.NewCLCluster.Nodes { - toml, _, err := setNodeConfig( + toml, _, err := SetNodeConfig( selectedNetworks, clNode.BaseConfigTOML, clNode.CommonChainConfigTOML, @@ -364,7 +367,7 @@ func DeployLocalCluster( } else { // if no individual nodes are specified, then deploy the number of nodes specified in the env input with common config for i := 0; i < noOfNodes; i++ { - toml, _, err := setNodeConfig( + toml, _, err := SetNodeConfig( selectedNetworks, testInputs.EnvInput.NewCLCluster.Common.BaseConfigTOML, testInputs.EnvInput.NewCLCluster.Common.CommonChainConfigTOML, diff --git a/integration-tests/ccip-tests/types/config/node/core.go b/integration-tests/ccip-tests/types/config/node/core.go index eb12598f948..5c9defbbb51 100644 --- a/integration-tests/ccip-tests/types/config/node/core.go +++ b/integration-tests/ccip-tests/types/config/node/core.go @@ -5,8 +5,8 @@ import ( "fmt" "math/big" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink-common/pkg/config" diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 467f371ad18..c0823f482ad 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -6,26 +6,23 @@ import ( "testing" "time" - ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/onsi/gomega" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -243,55 +240,17 @@ func TestAutomationChaos(t *testing.T) { require.NoError(t, err, "Error tearing down environment") }) - a := automationv2.NewAutomationTestK8s(l, chainClient, chainlinkNodes) + a := automationv2.NewAutomationTestK8s(l, chainClient, chainlinkNodes, &config) a.SetMercuryCredentialName("cred1") - conf := config.Automation.AutomationConfig - a.RegistrySettings = contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: *conf.RegistrySettings.PaymentPremiumPPB, - FlatFeeMicroLINK: *conf.RegistrySettings.FlatFeeMicroLINK, - CheckGasLimit: *conf.RegistrySettings.CheckGasLimit, - StalenessSeconds: conf.RegistrySettings.StalenessSeconds, - GasCeilingMultiplier: *conf.RegistrySettings.GasCeilingMultiplier, - MaxPerformGas: *conf.RegistrySettings.MaxPerformGas, - MinUpkeepSpend: conf.RegistrySettings.MinUpkeepSpend, - FallbackGasPrice: conf.RegistrySettings.FallbackGasPrice, - FallbackLinkPrice: conf.RegistrySettings.FallbackLinkPrice, - MaxCheckDataSize: *conf.RegistrySettings.MaxCheckDataSize, - MaxPerformDataSize: *conf.RegistrySettings.MaxPerformDataSize, - MaxRevertDataSize: *conf.RegistrySettings.MaxRevertDataSize, - RegistryVersion: rv, - } + a.RegistrySettings = actions.ReadRegistryConfig(config) + a.RegistrySettings.RegistryVersion = rv + a.PluginConfig = actions.ReadPluginConfig(config) + a.PublicConfig = actions.ReadPublicConfig(config) a.RegistrarSettings = contracts.KeeperRegistrarSettings{ AutoApproveConfigType: uint8(2), AutoApproveMaxAllowed: 1000, MinLinkJuels: big.NewInt(0), } - plCfg := config.GetAutomationConfig().AutomationConfig.PluginConfig - a.PluginConfig = ocr2keepers30config.OffchainConfig{ - TargetProbability: *plCfg.TargetProbability, - TargetInRounds: *plCfg.TargetInRounds, - PerformLockoutWindow: *plCfg.PerformLockoutWindow, - GasLimitPerReport: *plCfg.GasLimitPerReport, - GasOverheadPerUpkeep: *plCfg.GasOverheadPerUpkeep, - MinConfirmations: *plCfg.MinConfirmations, - MaxUpkeepBatchSize: *plCfg.MaxUpkeepBatchSize, - } - pubCfg := config.GetAutomationConfig().AutomationConfig.PublicConfig - a.PublicConfig = ocr3.PublicConfig{ - DeltaProgress: *pubCfg.DeltaProgress, - DeltaResend: *pubCfg.DeltaResend, - DeltaInitial: *pubCfg.DeltaInitial, - DeltaRound: *pubCfg.DeltaRound, - DeltaGrace: *pubCfg.DeltaGrace, - DeltaCertifiedCommitRequest: *pubCfg.DeltaCertifiedCommitRequest, - DeltaStage: *pubCfg.DeltaStage, - RMax: *pubCfg.RMax, - MaxDurationQuery: *pubCfg.MaxDurationQuery, - MaxDurationObservation: *pubCfg.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: *pubCfg.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: *pubCfg.MaxDurationShouldTransmitAcceptedReport, - F: *pubCfg.F, - } a.SetupAutomationDeployment(t) @@ -300,11 +259,11 @@ func TestAutomationChaos(t *testing.T) { var consumersLogTrigger, consumersConditional []contracts.KeeperConsumer var upkeepidsConditional, upkeepidsLogTrigger []*big.Int - consumersConditional, upkeepidsConditional = actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false, false, nil) + consumersConditional, upkeepidsConditional = actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false, false, nil, &config) consumers := consumersConditional upkeepIDs := upkeepidsConditional if rv >= eth_contracts.RegistryVersion_2_1 { - consumersLogTrigger, upkeepidsLogTrigger = actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false, false, nil) + consumersLogTrigger, upkeepidsLogTrigger = actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false, false, nil, &config) consumers = append(consumersConditional, consumersLogTrigger...) upkeepIDs = append(upkeepidsConditional, upkeepidsLogTrigger...) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 200c97a795f..821d3cc48c0 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -9,19 +9,19 @@ import ( "github.com/onsi/gomega" "github.com/stretchr/testify/require" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver-cfg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -84,7 +84,7 @@ func TestOCRChaos(t *testing.T) { // and chaos.NewNetworkPartition method (https://chaos-mesh.org/docs/simulate-network-chaos-on-kubernetes/) // in order to regenerate Go bindings if k8s version will be updated // you can pull new CRD spec from your current cluster and check README here - // https://github.com/smartcontractkit/chainlink-testing-framework/k8s/blob/master/README.md + // https://github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/blob/master/README.md NetworkChaosFailMajorityNetwork: { ethereum.New(nil), chainlinkCfg, @@ -179,13 +179,13 @@ func TestOCRChaos(t *testing.T) { }) ms := ctfClient.ConnectMockServer(testEnvironment) - linkContract, err := contracts.DeployLinkTokenContract(l, seth) + linkContract, err := actions.LinkTokenContract(l, seth, config.OCR) require.NoError(t, err, "Error deploying link token contract") err = actions.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), big.NewFloat(10)) require.NoError(t, err) - ocrInstances, err := actions.DeployOCRv1Contracts(l, seth, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.SetupOCRv1Contracts(l, seth, config.OCR, common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) require.NoError(t, err) err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, ms, fmt.Sprint(seth.ChainID)) require.NoError(t, err) diff --git a/integration-tests/citool/cmd/check_tests_cmd.go b/integration-tests/citool/cmd/check_tests_cmd.go deleted file mode 100644 index 3ef3712a572..00000000000 --- a/integration-tests/citool/cmd/check_tests_cmd.go +++ /dev/null @@ -1,166 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/spf13/cobra" - "gopkg.in/yaml.v3" -) - -type JobConfig struct { - Jobs map[string]struct { - Strategy struct { - Matrix struct { - Test []struct { - Path string `yaml:"path"` - TestOpts string `yaml:"testOpts"` - } `yaml:"test"` - } `yaml:"matrix"` - } `yaml:"strategy"` - } `yaml:"jobs"` -} - -var checkTestsCmd = &cobra.Command{ - Use: "check-tests [directory] [yaml file]", - Short: "Check if all tests in a directory are included in the test configurations YAML file", - Args: cobra.ExactArgs(2), - Run: func(_ *cobra.Command, args []string) { - directory := args[0] - yamlFile := args[1] - excludedDirs := []string{"../../citool"} - tests, err := extractTests(directory, excludedDirs) - if err != nil { - fmt.Println("Error extracting tests:", err) - os.Exit(1) - } - - checkTestsInPipeline(yamlFile, tests) - }, -} - -// extractTests scans the given directory and subdirectories (except the excluded ones) -// for Go test files, extracts test function names, and returns a slice of Test. -func extractTests(dir string, excludeDirs []string) ([]Test, error) { - var tests []Test - - // Resolve to absolute path - absDir, err := filepath.Abs(dir) - if err != nil { - return nil, err - } - - // filepath.WalkDir provides more control and is more efficient for skipping directories - err = filepath.WalkDir(absDir, func(path string, d os.DirEntry, err error) error { - if err != nil { - return err - } - - // Check if the current path is one of the excluded directories - for _, exclude := range excludeDirs { - absExclude, _ := filepath.Abs(exclude) - if strings.HasPrefix(path, absExclude) { - if d.IsDir() { - return filepath.SkipDir // Skip this directory - } - return nil // Skip this file - } - } - - if !d.IsDir() && strings.HasSuffix(d.Name(), "_test.go") { - content, err := os.ReadFile(path) - if err != nil { - return err - } - re := regexp.MustCompile(`func (Test\w+)`) - matches := re.FindAllSubmatch(content, -1) - for _, match := range matches { - funcName := string(match[1]) - if funcName == "TestMain" { // Skip "TestMain" - continue - } - tests = append(tests, Test{ - Name: funcName, - Path: mustExtractSubpath(path, "integration-tests"), - }) - } - } - return nil - }) - - return tests, err -} - -// ExtractSubpath extracts a specific subpath from a given full path. -// If the subpath is not found, it returns an error. -func mustExtractSubpath(fullPath, subPath string) string { - index := strings.Index(fullPath, subPath) - if index == -1 { - panic("subpath not found in the provided full path") - } - return fullPath[index:] -} - -func checkTestsInPipeline(yamlFile string, tests []Test) { - data, err := os.ReadFile(yamlFile) - if err != nil { - fmt.Printf("Error reading YAML file: %s\n", err) - return - } - - var config Config - err = yaml.Unmarshal(data, &config) - if err != nil { - fmt.Printf("Error parsing YAML: %s\n", err) - return - } - - missingTests := []string{} // Track missing tests - - for _, test := range tests { - found := false - for _, item := range config.Tests { - if item.Path == test.Path { - if strings.Contains(item.TestCmd, "-test.run") { - if matchTestNameInCmd(item.TestCmd, test.Name) { - found = true - break - } - } else { - found = true - break - } - } - } - if !found { - missingTests = append(missingTests, fmt.Sprintf("ERROR: Test '%s' in file '%s' does not have CI configuration in '%s'", test.Name, test.Path, yamlFile)) - } - } - - if len(missingTests) > 0 { - for _, missing := range missingTests { - fmt.Println(missing) - } - os.Exit(1) // Exit with a failure status - } -} - -// matchTestNameInCmd checks if the given test name matches the -test.run pattern in the command string. -func matchTestNameInCmd(cmd string, testName string) bool { - testRunRegex := regexp.MustCompile(`-test\.run ([^\s]+)`) - matches := testRunRegex.FindStringSubmatch(cmd) - if len(matches) > 1 { - // Extract the regex pattern used in the -test.run command - pattern := matches[1] - - // Escape regex metacharacters in the testName before matching - escapedTestName := regexp.QuoteMeta(testName) - - // Check if the escaped test name matches the extracted pattern - return regexp.MustCompile(pattern).MatchString(escapedTestName) - } - return false -} diff --git a/integration-tests/citool/cmd/check_tests_cmd_test.go b/integration-tests/citool/cmd/check_tests_cmd_test.go deleted file mode 100644 index 4b7f50e7f06..00000000000 --- a/integration-tests/citool/cmd/check_tests_cmd_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package cmd - -import ( - "testing" -) - -func TestMatchTestNameInCmd(t *testing.T) { - tests := []struct { - cmd string - testName string - expected bool - }{ - {"go test -test.run ^TestExample$", "TestExample", true}, - {"go test -test.run ^TestExample$", "TestAnother", false}, - {"go test -test.run ^TestExample$ -v", "TestExample", true}, - {"go test -test.run ^TestExamplePart$", "TestExample", false}, - {"go test -test.run ^TestWithNumbers123$", "TestWithNumbers123", true}, - {"go test -test.run ^Test_With_Underscores$", "Test_With_Underscores", true}, - {"go test -test.run ^Test-With-Dash$", "Test-With-Dash", true}, - {"go test -test.run ^TestWithSpace Space$", "TestWithSpace Space", true}, - {"go test -test.run ^TestWithNewline\nNewline$", "TestWithNewline\nNewline", true}, - {"go test -test.run ^TestOne$|^TestTwo$", "TestOne", true}, - {"go test -test.run ^TestOne$|^TestTwo$", "TestTwo", true}, - {"go test -test.run ^TestOne$|^TestTwo$", "TestThree", false}, - {"go test -test.run TestOne|TestTwo", "TestTwo", true}, - {"go test -test.run TestOne|TestTwo", "TestOne", true}, - {"go test -test.run TestOne|TestTwo|TestThree", "TestFour", false}, - {"go test -test.run ^TestOne$|TestTwo$", "TestTwo", true}, - {"go test -test.run ^TestOne$|TestTwo|TestThree$", "TestThree", true}, - {"go test -test.run TestOne|TestTwo|TestThree", "TestOne", true}, - {"go test -test.run TestOne|TestTwo|TestThree", "TestThree", true}, - {"go test -test.run ^TestA$|^TestB$|^TestC$", "TestA", true}, - {"go test -test.run ^TestA$|^TestB$|^TestC$", "TestB", true}, - {"go test -test.run ^TestA$|^TestB$|^TestC$", "TestD", false}, - {"go test -test.run TestA|^TestB$|TestC", "TestB", true}, - {"go test -test.run ^TestA|^TestB|TestC$", "TestA", true}, - {"go test -test.run ^TestA|^TestB|TestC$", "TestC", true}, - {"go test -test.run ^TestA|^TestB|TestC$", "TestD", false}, - } - - for _, tt := range tests { - result := matchTestNameInCmd(tt.cmd, tt.testName) - if result != tt.expected { - t.Errorf("matchTestNameInCmd(%s, %s) = %t; expected %t", tt.cmd, tt.testName, result, tt.expected) - } - } -} diff --git a/integration-tests/citool/cmd/create_test_config_cmd.go b/integration-tests/citool/cmd/create_test_config_cmd.go deleted file mode 100644 index c0cd91b05fb..00000000000 --- a/integration-tests/citool/cmd/create_test_config_cmd.go +++ /dev/null @@ -1,179 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/pelletier/go-toml/v2" - "github.com/spf13/cobra" - - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" -) - -var createTestConfigCmd = &cobra.Command{ - Use: "create", - Short: "Create a test config from the provided flags", - Run: func(cmd *cobra.Command, _ []string) { - var tc ctf_config.TestConfig - - var version, postgresVersion *string - if cmd.Flags().Changed(ChainlinkVersionFlag) { - version = &oc.ChainlinkVersion - } - if cmd.Flags().Changed(ChainlinkPostgresVersionFlag) { - version = &oc.ChainlinkPostgresVersion - } - if version != nil || postgresVersion != nil { - tc.ChainlinkImage = &ctf_config.ChainlinkImageConfig{ - Version: version, - PostgresVersion: postgresVersion, - } - } - - var upgradeVersion *string - if cmd.Flags().Changed(ChainlinkUpgradeVersionFlag) { - upgradeVersion = &oc.ChainlinkUpgradeVersion - } - if upgradeVersion != nil { - tc.ChainlinkUpgradeImage = &ctf_config.ChainlinkImageConfig{ - Version: upgradeVersion, - } - } - - var selectedNetworks *[]string - if cmd.Flags().Changed(SelectedNetworksFlag) { - selectedNetworks = &oc.SelectedNetworks - } - if selectedNetworks != nil { - tc.Network = &ctf_config.NetworkConfig{ - SelectedNetworks: oc.SelectedNetworks, - } - } - - var peryscopeEnabled *bool - var pyroscopeServerURL, pyroscopeEnvironment, pyroscopeKey *string - if cmd.Flags().Changed(PyroscopeEnabledFlag) { - peryscopeEnabled = &oc.PyroscopeEnabled - } - if cmd.Flags().Changed(PyroscopeServerURLFlag) { - pyroscopeServerURL = &oc.PyroscopeServerURL - } - if cmd.Flags().Changed(PyroscopeKeyFlag) { - pyroscopeKey = &oc.PyroscopeKey - } - if cmd.Flags().Changed(PyroscopeEnvironmentFlag) { - pyroscopeEnvironment = &oc.PyroscopeEnvironment - } - if peryscopeEnabled != nil { - tc.Pyroscope = &ctf_config.PyroscopeConfig{ - Enabled: peryscopeEnabled, - ServerUrl: pyroscopeServerURL, - Environment: pyroscopeEnvironment, - Key: pyroscopeKey, - } - } - - var testLogCollect *bool - if cmd.Flags().Changed(LoggingTestLogCollectFlag) { - testLogCollect = &oc.LoggingTestLogCollect - } - var loggingRunID *string - if cmd.Flags().Changed(LoggingRunIDFlag) { - loggingRunID = &oc.LoggingRunID - } - var loggingLogTargets []string - if cmd.Flags().Changed(LoggingLogTargetsFlag) { - loggingLogTargets = oc.LoggingLogTargets - } - var loggingLokiTenantID *string - if cmd.Flags().Changed(LoggingLokiTenantIDFlag) { - loggingLokiTenantID = &oc.LoggingLokiTenantID - } - var loggingLokiBasicAuth *string - if cmd.Flags().Changed(LoggingLokiBasicAuthFlag) { - loggingLokiBasicAuth = &oc.LoggingLokiBasicAuth - } - var loggingLokiEndpoint *string - if cmd.Flags().Changed(LoggingLokiEndpointFlag) { - loggingLokiEndpoint = &oc.LoggingLokiEndpoint - } - var loggingGrafanaBaseURL *string - if cmd.Flags().Changed(LoggingGrafanaBaseURLFlag) { - loggingGrafanaBaseURL = &oc.LoggingGrafanaBaseURL - } - var loggingGrafanaDashboardURL *string - if cmd.Flags().Changed(LoggingGrafanaDashboardURLFlag) { - loggingGrafanaDashboardURL = &oc.LoggingGrafanaDashboardURL - } - var loggingGrafanaBearerToken *string - if cmd.Flags().Changed(LoggingGrafanaBearerTokenFlag) { - loggingGrafanaBearerToken = &oc.LoggingGrafanaBearerToken - } - - if testLogCollect != nil || loggingRunID != nil || loggingLogTargets != nil || loggingLokiEndpoint != nil || loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { - tc.Logging = &ctf_config.LoggingConfig{} - tc.Logging.TestLogCollect = testLogCollect - tc.Logging.RunId = loggingRunID - if loggingLogTargets != nil { - tc.Logging.LogStream = &ctf_config.LogStreamConfig{ - LogTargets: loggingLogTargets, - } - } - if loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingLokiEndpoint != nil { - tc.Logging.Loki = &ctf_config.LokiConfig{ - TenantId: loggingLokiTenantID, - BasicAuth: loggingLokiBasicAuth, - Endpoint: loggingLokiEndpoint, - } - } - if loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { - tc.Logging.Grafana = &ctf_config.GrafanaConfig{ - BaseUrl: loggingGrafanaBaseURL, - DashboardUrl: loggingGrafanaDashboardURL, - BearerToken: loggingGrafanaBearerToken, - } - } - } - - var privateEthereumNetworkExecutionLayer *string - if cmd.Flags().Changed(PrivateEthereumNetworkExecutionLayerFlag) { - privateEthereumNetworkExecutionLayer = &oc.PrivateEthereumNetworkExecutionLayer - } - var privateEthereumNetworkEthereumVersion *string - if cmd.Flags().Changed(PrivateEthereumNetworkEthereumVersionFlag) { - privateEthereumNetworkEthereumVersion = &oc.PrivateEthereumNetworkEthereumVersion - } - var privateEthereumNetworkCustomDockerImage *string - if cmd.Flags().Changed(PrivateEthereumNetworkCustomDockerImageFlag) { - privateEthereumNetworkCustomDockerImage = &oc.PrivateEthereumNetworkCustomDockerImages - } - if privateEthereumNetworkExecutionLayer != nil || privateEthereumNetworkEthereumVersion != nil || privateEthereumNetworkCustomDockerImage != nil { - var el ctf_config_types.ExecutionLayer - if privateEthereumNetworkExecutionLayer != nil { - el = ctf_config_types.ExecutionLayer(*privateEthereumNetworkExecutionLayer) - } - var ev ctf_config_types.EthereumVersion - if privateEthereumNetworkEthereumVersion != nil { - ev = ctf_config_types.EthereumVersion(*privateEthereumNetworkEthereumVersion) - } - var customImages map[ctf_config.ContainerType]string - if privateEthereumNetworkCustomDockerImage != nil { - customImages = map[ctf_config.ContainerType]string{"execution_layer": *privateEthereumNetworkCustomDockerImage} - } - tc.PrivateEthereumNetwork = &ctf_config.EthereumNetworkConfig{ - ExecutionLayer: &el, - EthereumVersion: &ev, - CustomDockerImages: customImages, - } - } - - configToml, err := toml.Marshal(tc) - if err != nil { - fmt.Fprintf(os.Stderr, "Error marshalling TestConfig to TOML: %v\n", err) - os.Exit(1) - } - - fmt.Fprintln(cmd.OutOrStdout(), string(configToml)) - }, -} diff --git a/integration-tests/citool/cmd/csv_export_cmd.go b/integration-tests/citool/cmd/csv_export_cmd.go deleted file mode 100644 index 8fe13440c81..00000000000 --- a/integration-tests/citool/cmd/csv_export_cmd.go +++ /dev/null @@ -1,96 +0,0 @@ -package cmd - -import ( - "encoding/csv" - "fmt" - "os" - "strings" - - "github.com/spf13/cobra" - "gopkg.in/yaml.v3" -) - -var csvExportCmd = &cobra.Command{ - Use: "csvexport", - Short: "Export tests to CSV format", - Run: func(cmd *cobra.Command, _ []string) { - configFile, _ := cmd.Flags().GetString("file") - if err := exportConfigToCSV(configFile); err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } - }, -} - -func init() { - csvExportCmd.Flags().StringP("file", "f", "", "Path to YML file") - err := csvExportCmd.MarkFlagRequired("file") - if err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } -} - -func exportConfigToCSV(configFile string) error { - // Read the YAML file - bytes, err := os.ReadFile(configFile) - if err != nil { - return err - } - - // Unmarshal the YAML into the Config struct - var config Config - if err := yaml.Unmarshal(bytes, &config); err != nil { - return err - } - - // Create a CSV file - file, err := os.Create("output.csv") - if err != nil { - return err - } - defer file.Close() - - writer := csv.NewWriter(file) - defer writer.Flush() - - // Write CSV headers - headers := []string{"ID", "Test Path", "Test Env Type", "Runs On", "Test Cmd", "Test Config Override Required", "Test Secrets Required", "Remote Runner Memory", "Pyroscope Env", "Workflows", "Test Inputs"} - if err := writer.Write(headers); err != nil { - return err - } - - // Iterate over Tests and write data to CSV - for _, test := range config.Tests { - workflows := strings.Join(test.Workflows, ", ") // Combine workflows into a single CSV field - // Serialize TestInputs - testInputs := serializeMap(test.TestInputs) - - record := []string{ - test.ID, - test.Path, - test.TestEnvType, - test.RunsOn, - test.TestCmd, - fmt.Sprintf("%t", test.TestConfigOverrideRequired), - fmt.Sprintf("%t", test.TestSecretsRequired), - test.RemoteRunnerMemory, - test.PyroscopeEnv, - workflows, - testInputs, - } - if err := writer.Write(record); err != nil { - return err - } - } - - return nil -} - -func serializeMap(inputs map[string]string) string { - pairs := make([]string, 0, len(inputs)) - for key, value := range inputs { - pairs = append(pairs, fmt.Sprintf("%s=%s", key, value)) - } - return strings.Join(pairs, ", ") -} diff --git a/integration-tests/citool/cmd/filter_cmd.go b/integration-tests/citool/cmd/filter_cmd.go deleted file mode 100644 index c1d5f22357d..00000000000 --- a/integration-tests/citool/cmd/filter_cmd.go +++ /dev/null @@ -1,165 +0,0 @@ -package cmd - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "log" - "os" - "regexp" - "strings" - - "github.com/spf13/cobra" - "gopkg.in/yaml.v2" - - "github.com/smartcontractkit/chainlink-testing-framework/utils" -) - -// Filter tests based on workflow, test type, and test IDs. -func filterTests(allTests []CITestConf, workflow, testType, ids string, envresolve bool) []CITestConf { - workflowFilter := workflow - typeFilter := testType - idFilter := strings.Split(ids, ",") - - var filteredTests []CITestConf - - for _, test := range allTests { - workflowMatch := workflow == "" || contains(test.Workflows, workflowFilter) - typeMatch := testType == "" || test.TestEnvType == typeFilter - idMatch := ids == "*" || ids == "" || contains(idFilter, test.ID) - - if workflowMatch && typeMatch && idMatch { - test.IDSanitized = sanitizeTestID(test.ID) - filteredTests = append(filteredTests, test) - } - if envresolve { - for k, v := range test.TestInputs { - test.TestInputs[k] = utils.MustResolveEnvPlaceholder(v) - } - } - } - - return filteredTests -} - -func filterAndMergeTests(allTests []CITestConf, workflow, testType, base64Tests string, envresolve bool) ([]CITestConf, error) { - decodedBytes, err := base64.StdEncoding.DecodeString(base64Tests) - if err != nil { - return nil, err - } - var decodedTests []CITestConf - err = yaml.Unmarshal(decodedBytes, &decodedTests) - if err != nil { - return nil, err - } - - idFilter := make(map[string]CITestConf) - for _, dt := range decodedTests { - idFilter[dt.ID] = dt - } - - var filteredTests []CITestConf - for _, test := range allTests { - workflowMatch := workflow == "" || contains(test.Workflows, workflow) - typeMatch := testType == "" || test.TestEnvType == testType - - if decodedTest, exists := idFilter[test.ID]; exists && workflowMatch && typeMatch { - // Override test inputs from the base64 encoded tests - for k, v := range decodedTest.TestInputs { - if test.TestInputs == nil { - test.TestInputs = make(map[string]string) - } - test.TestInputs[k] = v - } - test.IDSanitized = sanitizeTestID(test.ID) - filteredTests = append(filteredTests, test) - } - if envresolve { - for k, v := range test.TestInputs { - test.TestInputs[k] = utils.MustResolveEnvPlaceholder(v) - } - } - } - - return filteredTests, nil -} - -func sanitizeTestID(id string) string { - // Define a regular expression that matches any character not a letter, digit, hyphen - re := regexp.MustCompile(`[^a-zA-Z0-9-_]+`) - // Replace all occurrences of disallowed characters with "_" - return re.ReplaceAllString(id, "_") -} - -// Utility function to check if a slice contains a string. -func contains(slice []string, element string) bool { - for _, s := range slice { - if s == element { - return true - } - } - return false -} - -// filterCmd represents the filter command -var filterCmd = &cobra.Command{ - Use: "filter", - Short: "Filter test configurations based on specified criteria", - Long: `Filters tests from a YAML configuration based on name, workflow, test type, and test IDs. -Example usage: -./e2e_tests_tool filter --file .github/e2e-tests.yml --workflow "Run Nightly E2E Tests" --test-env-type "docker" --test-ids "test1,test2"`, - Run: func(cmd *cobra.Command, _ []string) { - yamlFile, _ := cmd.Flags().GetString("file") - workflow, _ := cmd.Flags().GetString("workflow") - testType, _ := cmd.Flags().GetString("test-env-type") - testIDs, _ := cmd.Flags().GetString("test-ids") - testMap, _ := cmd.Flags().GetString("test-list") - envresolve, _ := cmd.Flags().GetBool("envresolve") - - data, err := os.ReadFile(yamlFile) - if err != nil { - fmt.Fprintf(os.Stderr, "Error reading YAML file: %v\n", err) - os.Exit(1) - } - - var config Config - err = yaml.Unmarshal(data, &config) - if err != nil { - fmt.Fprintf(os.Stderr, "Error parsing YAML file %s data: %v\n", yamlFile, err) - os.Exit(1) - } - - var filteredTests []CITestConf - if testMap == "" { - filteredTests = filterTests(config.Tests, workflow, testType, testIDs, envresolve) - } else { - filteredTests, err = filterAndMergeTests(config.Tests, workflow, testType, testMap, envresolve) - if err != nil { - log.Fatalf("Error filtering and merging tests: %v", err) - } - } - matrix := map[string][]CITestConf{"tests": filteredTests} - matrixJSON, err := json.Marshal(matrix) - if err != nil { - fmt.Fprintf(os.Stderr, "Error marshaling matrix to JSON: %v\n", err) - os.Exit(1) - } - - fmt.Printf("%s", matrixJSON) - }, -} - -func init() { - filterCmd.Flags().StringP("file", "f", "", "Path to the YAML file") - filterCmd.Flags().String("test-list", "", "Base64 encoded list of tests (YML objects) to filter by. Can include test_inputs for each test.") - filterCmd.Flags().StringP("test-ids", "i", "*", "Comma-separated list of test IDs to filter by") - filterCmd.Flags().StringP("test-env-type", "y", "", "Type of test to filter by") - filterCmd.Flags().StringP("workflow", "t", "", "Workflow filter") - filterCmd.Flags().Bool("envresolve", false, "Resolve environment variables in test inputs") - - err := filterCmd.MarkFlagRequired("file") - if err != nil { - fmt.Fprintf(os.Stderr, "Error marking flag as required: %v\n", err) - os.Exit(1) - } -} diff --git a/integration-tests/citool/cmd/filter_cmd_test.go b/integration-tests/citool/cmd/filter_cmd_test.go deleted file mode 100644 index ff6e9c981de..00000000000 --- a/integration-tests/citool/cmd/filter_cmd_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package cmd - -import ( - "testing" -) - -func TestFilterTestsByID(t *testing.T) { - tests := []CITestConf{ - {ID: "run_all_in_ocr_tests_go", TestEnvType: "docker"}, - {ID: "run_all_in_ocr2_tests_go", TestEnvType: "docker"}, - {ID: "run_all_in_ocr3_tests_go", TestEnvType: "k8s_remote_runner"}, - } - - cases := []struct { - description string - inputIDs string - expectedLen int - }{ - {"Filter by single ID", "run_all_in_ocr_tests_go", 1}, - {"Filter by multiple IDs", "run_all_in_ocr_tests_go,run_all_in_ocr2_tests_go", 2}, - {"Wildcard to include all", "*", 3}, - {"Empty ID string to include all", "", 3}, - } - - for _, c := range cases { - t.Run(c.description, func(t *testing.T) { - filtered := filterTests(tests, "", "", c.inputIDs, false) - if len(filtered) != c.expectedLen { - t.Errorf("FilterTests(%s) returned %d tests, expected %d", c.description, len(filtered), c.expectedLen) - } - }) - } -} - -func TestFilterTestsIntegration(t *testing.T) { - tests := []CITestConf{ - {ID: "run_all_in_ocr_tests_go", TestEnvType: "docker", Workflows: []string{"Run Nightly E2E Tests"}}, - {ID: "run_all_in_ocr2_tests_go", TestEnvType: "docker", Workflows: []string{"Run PR E2E Tests"}}, - {ID: "run_all_in_ocr3_tests_go", TestEnvType: "k8s_remote_runner", Workflows: []string{"Run PR E2E Tests"}}, - } - - cases := []struct { - description string - inputNames string - inputWorkflow string - inputTestType string - inputIDs string - expectedLen int - }{ - {"Filter by test type and ID", "", "", "docker", "run_all_in_ocr2_tests_go", 1}, - {"Filter by trigger and test type", "", "Run PR E2E Tests", "docker", "*", 1}, - {"No filters applied", "", "", "", "*", 3}, - {"Filter mismatching all criteria", "", "Run Nightly E2E Tests", "", "", 1}, - } - - for _, c := range cases { - t.Run(c.description, func(t *testing.T) { - filtered := filterTests(tests, c.inputWorkflow, c.inputTestType, c.inputIDs, false) - if len(filtered) != c.expectedLen { - t.Errorf("FilterTests(%s) returned %d tests, expected %d", c.description, len(filtered), c.expectedLen) - } - }) - } -} diff --git a/integration-tests/citool/cmd/root_cmd.go b/integration-tests/citool/cmd/root_cmd.go deleted file mode 100644 index fdb4efd5724..00000000000 --- a/integration-tests/citool/cmd/root_cmd.go +++ /dev/null @@ -1,32 +0,0 @@ -package cmd - -import ( - "os" - - "github.com/spf13/cobra" -) - -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "citool", - Short: "A tool to manage E2E tests on Github CI", -} - -// 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() { - err := rootCmd.Execute() - if err != nil { - os.Exit(1) - } -} - -func init() { - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - - rootCmd.AddCommand(checkTestsCmd) - rootCmd.AddCommand(filterCmd) - rootCmd.AddCommand(csvExportCmd) - rootCmd.AddCommand(testConfigCmd) - testConfigCmd.AddCommand(createTestConfigCmd) -} diff --git a/integration-tests/citool/cmd/test_config_cmd.go b/integration-tests/citool/cmd/test_config_cmd.go deleted file mode 100644 index 0c0e272353b..00000000000 --- a/integration-tests/citool/cmd/test_config_cmd.go +++ /dev/null @@ -1,123 +0,0 @@ -package cmd - -import ( - "strings" - - "github.com/spf13/cobra" - - "github.com/smartcontractkit/chainlink-testing-framework/utils" -) - -var testConfigCmd = &cobra.Command{ - Use: "test-config", - Short: "Manage test config", -} - -// OverrideConfig holds the configuration data for overrides -type OverrideConfig struct { - ChainlinkImage string - ChainlinkVersion string - ChainlinkUpgradeImage string - ChainlinkUpgradeVersion string - ChainlinkPostgresVersion string - SelectedNetworks []string - PyroscopeEnabled bool - PyroscopeServerURL string - PyroscopeEnvironment string - PyroscopeKey string - LoggingTestLogCollect bool - LoggingRunID string - LoggingLogTargets []string - LoggingLokiTenantID string - LoggingLokiEndpoint string - LoggingLokiBasicAuth string - LoggingGrafanaBaseURL string - LoggingGrafanaDashboardURL string - LoggingGrafanaBearerToken string - PrivateEthereumNetworkExecutionLayer string - PrivateEthereumNetworkEthereumVersion string - PrivateEthereumNetworkCustomDockerImages string -} - -const ( - ChainlinkVersionFlag = "chainlink-version" - ChainlinkUpgradeVersionFlag = "chainlink-upgrade-version" - ChainlinkPostgresVersionFlag = "chainlink-postgres-version" - SelectedNetworksFlag = "selected-networks" - FromBase64ConfigFlag = "from-base64-config" - LoggingLokiBasicAuthFlag = "logging-loki-basic-auth" - LoggingLokiEndpointFlag = "logging-loki-endpoint" - LoggingRunIDFlag = "logging-run-id" - LoggingLokiTenantIDFlag = "logging-loki-tenant-id" - LoggingGrafanaBaseURLFlag = "logging-grafana-base-url" - LoggingGrafanaDashboardURLFlag = "logging-grafana-dashboard-url" - LoggingGrafanaBearerTokenFlag = "logging-grafana-bearer-token" - LoggingLogTargetsFlag = "logging-log-targets" - LoggingTestLogCollectFlag = "logging-test-log-collect" - PyroscopeEnabledFlag = "pyroscope-enabled" - PyroscopeServerURLFlag = "pyroscope-server-url" - PyroscopeKeyFlag = "pyroscope-key" - PyroscopeEnvironmentFlag = "pyroscope-environment" - PrivateEthereumNetworkExecutionLayerFlag = "private-ethereum-network-execution-layer" - PrivateEthereumNetworkEthereumVersionFlag = "private-ethereum-network-ethereum-version" - PrivateEthereumNetworkCustomDockerImageFlag = "private-ethereum-network-custom-docker-image" -) - -var oc OverrideConfig - -func init() { - cmds := []*cobra.Command{createTestConfigCmd} - for _, c := range cmds { - c.Flags().StringArrayVar(&oc.SelectedNetworks, SelectedNetworksFlag, nil, "Selected networks") - c.Flags().StringVar(&oc.ChainlinkVersion, ChainlinkVersionFlag, "", "Chainlink version") - c.Flags().StringVar(&oc.ChainlinkUpgradeVersion, ChainlinkUpgradeVersionFlag, "", "Chainlink upgrade version") - c.Flags().StringVar(&oc.ChainlinkPostgresVersion, ChainlinkPostgresVersionFlag, "", "Chainlink Postgres version") - c.Flags().BoolVar(&oc.PyroscopeEnabled, PyroscopeEnabledFlag, false, "Pyroscope enabled") - c.Flags().StringVar(&oc.PyroscopeServerURL, PyroscopeServerURLFlag, "", "Pyroscope server URL") - c.Flags().StringVar(&oc.PyroscopeKey, PyroscopeKeyFlag, "", "Pyroscope key") - c.Flags().StringVar(&oc.PyroscopeEnvironment, PyroscopeEnvironmentFlag, "", "Pyroscope environment") - c.Flags().BoolVar(&oc.LoggingTestLogCollect, LoggingTestLogCollectFlag, false, "Test log collect") - c.Flags().StringVar(&oc.LoggingRunID, LoggingRunIDFlag, "", "Run ID") - c.Flags().StringArrayVar(&oc.LoggingLogTargets, LoggingLogTargetsFlag, nil, "Logging.LogStream.LogTargets") - c.Flags().StringVar(&oc.LoggingLokiEndpoint, LoggingLokiEndpointFlag, "", "") - c.Flags().StringVar(&oc.LoggingLokiTenantID, LoggingLokiTenantIDFlag, "", "") - c.Flags().StringVar(&oc.LoggingLokiBasicAuth, LoggingLokiBasicAuthFlag, "", "") - c.Flags().StringVar(&oc.LoggingGrafanaBaseURL, LoggingGrafanaBaseURLFlag, "", "") - c.Flags().StringVar(&oc.LoggingGrafanaDashboardURL, LoggingGrafanaDashboardURLFlag, "", "") - c.Flags().StringVar(&oc.LoggingGrafanaBearerToken, LoggingGrafanaBearerTokenFlag, "", "") - c.Flags().StringVar(&oc.PrivateEthereumNetworkExecutionLayer, PrivateEthereumNetworkExecutionLayerFlag, "", "") - c.Flags().StringVar(&oc.PrivateEthereumNetworkEthereumVersion, PrivateEthereumNetworkEthereumVersionFlag, "", "") - c.Flags().StringVar(&oc.PrivateEthereumNetworkCustomDockerImages, PrivateEthereumNetworkCustomDockerImageFlag, "", "") - - c.PreRun = func(_ *cobra.Command, _ []string) { - // Resolve selected networks environment variable if set - if len(oc.SelectedNetworks) > 0 { - _, hasEnvVar := utils.LookupEnvVarName(oc.SelectedNetworks[0]) - if hasEnvVar { - selectedNetworks := utils.MustResolveEnvPlaceholder(oc.SelectedNetworks[0]) - oc.SelectedNetworks = strings.Split(selectedNetworks, ",") - } - } - - // Resolve all other environment variables - oc.ChainlinkImage = utils.MustResolveEnvPlaceholder(oc.ChainlinkImage) - oc.ChainlinkVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkVersion) - oc.ChainlinkUpgradeImage = utils.MustResolveEnvPlaceholder(oc.ChainlinkUpgradeImage) - oc.ChainlinkUpgradeVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkUpgradeVersion) - oc.ChainlinkPostgresVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkPostgresVersion) - oc.PyroscopeServerURL = utils.MustResolveEnvPlaceholder(oc.PyroscopeServerURL) - oc.PyroscopeKey = utils.MustResolveEnvPlaceholder(oc.PyroscopeKey) - oc.PyroscopeEnvironment = utils.MustResolveEnvPlaceholder(oc.PyroscopeEnvironment) - oc.LoggingRunID = utils.MustResolveEnvPlaceholder(oc.LoggingRunID) - oc.LoggingLokiTenantID = utils.MustResolveEnvPlaceholder(oc.LoggingLokiTenantID) - oc.LoggingLokiEndpoint = utils.MustResolveEnvPlaceholder(oc.LoggingLokiEndpoint) - oc.LoggingLokiBasicAuth = utils.MustResolveEnvPlaceholder(oc.LoggingLokiBasicAuth) - oc.LoggingGrafanaBaseURL = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaBaseURL) - oc.LoggingGrafanaDashboardURL = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaDashboardURL) - oc.LoggingGrafanaBearerToken = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaBearerToken) - oc.PrivateEthereumNetworkExecutionLayer = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkExecutionLayer) - oc.PrivateEthereumNetworkEthereumVersion = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkEthereumVersion) - oc.PrivateEthereumNetworkCustomDockerImages = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkCustomDockerImages) - } - } -} diff --git a/integration-tests/citool/cmd/test_config_cmd_test.go b/integration-tests/citool/cmd/test_config_cmd_test.go deleted file mode 100644 index 79185e60822..00000000000 --- a/integration-tests/citool/cmd/test_config_cmd_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package cmd - -import ( - "bytes" - "testing" - - "github.com/pelletier/go-toml/v2" - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" -) - -func TestCreateTestConfigCmd(t *testing.T) { - tests := []struct { - name string - args []string - want interface{} - check func(t *testing.T, tc *ctf_config.TestConfig) - wantErr bool - }{ - { - name: "LoggingLogTargets", - args: []string{"create", "--logging-log-targets=target1", "--logging-log-targets=target2"}, - check: func(t *testing.T, tc *ctf_config.TestConfig) { - assert.NotNil(t, tc.Logging) - assert.NotNil(t, tc.Logging.LogStream) - assert.Equal(t, []string{"target1", "target2"}, tc.Logging.LogStream.LogTargets) - }, - }, - { - name: "PrivateEthereumNetworkExecutionLayerFlag", - args: []string{"create", "--private-ethereum-network-execution-layer=geth", "--private-ethereum-network-ethereum-version=1.10.0"}, - check: func(t *testing.T, tc *ctf_config.TestConfig) { - assert.NotNil(t, tc.PrivateEthereumNetwork) - assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, ctf_config_types.ExecutionLayer("geth"), *tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, ctf_config_types.EthereumVersion("1.10.0"), *tc.PrivateEthereumNetwork.EthereumVersion) - }, - }, - { - name: "PrivateEthereumNetworkCustomDockerImageFlag", - args: []string{"create", "--private-ethereum-network-execution-layer=geth", "--private-ethereum-network-ethereum-version=1.10.0", "--private-ethereum-network-custom-docker-image=custom-image:v1.0"}, - check: func(t *testing.T, tc *ctf_config.TestConfig) { - assert.NotNil(t, tc.PrivateEthereumNetwork) - assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, map[ctf_config.ContainerType]string{"execution_layer": "custom-image:v1.0"}, tc.PrivateEthereumNetwork.CustomDockerImages) - }, - }, - } - - rootCmd := &cobra.Command{} - rootCmd.AddCommand(createTestConfigCmd) - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - rootCmd.SetArgs(tt.args) - var out bytes.Buffer - rootCmd.SetOutput(&out) - err := rootCmd.Execute() - if (err != nil) != tt.wantErr { - t.Fatalf("Execute() error = %v, wantErr %v", err, tt.wantErr) - } - var tc ctf_config.TestConfig - err = toml.Unmarshal(out.Bytes(), &tc) - if err != nil { - t.Fatalf("Failed to unmarshal output: %v", err) - } - if tt.check != nil { - tt.check(t, &tc) - } - }) - } -} diff --git a/integration-tests/citool/cmd/types.go b/integration-tests/citool/cmd/types.go deleted file mode 100644 index 3c347e9406b..00000000000 --- a/integration-tests/citool/cmd/types.go +++ /dev/null @@ -1,26 +0,0 @@ -package cmd - -type Test struct { - Name string - Path string -} - -// CITestConf defines the configuration for running a test in a CI environment, specifying details like test ID, path, type, runner settings, command, and associated workflows. -type CITestConf struct { - ID string `yaml:"id" json:"id"` - IDSanitized string `json:"id_sanitized"` - Path string `yaml:"path" json:"path"` - TestEnvType string `yaml:"test_env_type" json:"test_env_type"` - RunsOn string `yaml:"runs_on" json:"runs_on"` - TestCmd string `yaml:"test_cmd" json:"test_cmd"` - TestConfigOverrideRequired bool `yaml:"test_config_override_required" json:"testConfigOverrideRequired"` - TestSecretsRequired bool `yaml:"test_secrets_required" json:"testSecretsRequired"` - TestInputs map[string]string `yaml:"test_inputs" json:"test_inputs"` - RemoteRunnerMemory string `yaml:"remote_runner_memory" json:"remoteRunnerMemory"` - PyroscopeEnv string `yaml:"pyroscope_env" json:"pyroscopeEnv"` - Workflows []string `yaml:"workflows" json:"workflows"` -} - -type Config struct { - Tests []CITestConf `yaml:"runner-test-matrix"` -} diff --git a/integration-tests/citool/main.go b/integration-tests/citool/main.go deleted file mode 100644 index 4fa6cac56e5..00000000000 --- a/integration-tests/citool/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "github.com/smartcontractkit/chainlink/integration-tests/citool/cmd" -) - -func main() { - cmd.Execute() -} diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go index da17dcf0d75..ebfd97c48b4 100644 --- a/integration-tests/client/chainlink.go +++ b/integration-tests/client/chainlink.go @@ -1112,7 +1112,9 @@ func CreateNodeKeysBundle(nodes []*ChainlinkClient, chainName string, chainId st if err != nil { return nil, nil, err } - + if len(p2pkeys.Data) == 0 { + return nil, nil, fmt.Errorf("found no P2P Keys on the Chainlink node. Node URL: %s", n.URL()) + } peerID := p2pkeys.Data[0].Attributes.PeerID // If there is already a txkey present for the chain skip creating a new one // otherwise the test logic will need multiple key management (like funding all the keys, diff --git a/integration-tests/client/chainlink_k8s.go b/integration-tests/client/chainlink_k8s.go index 077b8f7ca48..4cdfa96c532 100644 --- a/integration-tests/client/chainlink_k8s.go +++ b/integration-tests/client/chainlink_k8s.go @@ -6,7 +6,7 @@ import ( "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" ) const ( diff --git a/integration-tests/contracts/contract_models.go b/integration-tests/contracts/contract_models.go index ea63f1aa4db..006ee5db6a8 100644 --- a/integration-tests/contracts/contract_models.go +++ b/integration-tests/contracts/contract_models.go @@ -14,6 +14,8 @@ import ( ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" ocrConfigHelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_billing_registry_events_mock" @@ -124,22 +126,22 @@ type OffChainAggregatorConfig struct { } type OffChainAggregatorV2Config struct { - DeltaProgress time.Duration - DeltaResend time.Duration - DeltaRound time.Duration - DeltaGrace time.Duration - DeltaStage time.Duration - RMax uint8 - S []int - Oracles []ocrConfigHelper2.OracleIdentityExtra - ReportingPluginConfig []byte - MaxDurationQuery time.Duration - MaxDurationObservation time.Duration - MaxDurationReport time.Duration - MaxDurationShouldAcceptFinalizedReport time.Duration - MaxDurationShouldTransmitAcceptedReport time.Duration - F int - OnchainConfig []byte + DeltaProgress *config.Duration `toml:",omitempty"` + DeltaResend *config.Duration `toml:",omitempty"` + DeltaRound *config.Duration `toml:",omitempty"` + DeltaGrace *config.Duration `toml:",omitempty"` + DeltaStage *config.Duration `toml:",omitempty"` + RMax uint8 `toml:"-"` + S []int `toml:"-"` + Oracles []ocrConfigHelper2.OracleIdentityExtra `toml:"-"` + ReportingPluginConfig []byte `toml:"-"` + MaxDurationQuery *config.Duration `toml:",omitempty"` + MaxDurationObservation *config.Duration `toml:",omitempty"` + MaxDurationReport *config.Duration `toml:",omitempty"` + MaxDurationShouldAcceptFinalizedReport *config.Duration `toml:",omitempty"` + MaxDurationShouldTransmitAcceptedReport *config.Duration `toml:",omitempty"` + F int `toml:"-"` + OnchainConfig []byte `toml:"-"` } type OffchainAggregatorData struct { @@ -149,9 +151,13 @@ type OffchainAggregatorData struct { type ChainlinkNodeWithKeysAndAddress interface { MustReadOCRKeys() (*client.OCRKeys, error) MustReadP2PKeys() (*client.P2PKeys, error) - ExportEVMKeysForChain(string) ([]*client.ExportedEVMKey, error) PrimaryEthAddress() (string, error) EthAddresses() ([]string, error) + ChainlinkKeyExporter +} + +type ChainlinkKeyExporter interface { + ExportEVMKeysForChain(string) ([]*client.ExportedEVMKey, error) } type ChainlinkNodeWithForwarder interface { @@ -230,6 +236,12 @@ type MockLINKETHFeed interface { LatestRoundDataUpdatedAt() (*big.Int, error) } +type MockETHLINKFeed interface { + Address() string + LatestRoundData() (*big.Int, error) + LatestRoundDataUpdatedAt() (*big.Int, error) +} + type MockETHUSDFeed interface { Address() string LatestRoundData() (*big.Int, error) diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index c798c4921c6..8d1424cbfdf 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" @@ -125,6 +125,7 @@ type VRFCoordinatorV2_5 interface { GetBlockHashStoreAddress(ctx context.Context) (common.Address, error) GetLinkAddress(ctx context.Context) (common.Address, error) GetLinkNativeFeed(ctx context.Context) (common.Address, error) + GetConfig(ctx context.Context) (vrf_coordinator_v2_5.SConfig, error) } type VRFCoordinatorV2PlusUpgradedVersion interface { diff --git a/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go b/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go index 86963e01a45..1006daa0345 100644 --- a/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go +++ b/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go @@ -15,6 +15,7 @@ import ( "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" ) diff --git a/integration-tests/contracts/ethereum/StakingEventsMock.go b/integration-tests/contracts/ethereum/StakingEventsMock.go index 5a1a1663ba9..b3b695ea301 100644 --- a/integration-tests/contracts/ethereum/StakingEventsMock.go +++ b/integration-tests/contracts/ethereum/StakingEventsMock.go @@ -15,6 +15,7 @@ import ( "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" ) diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index 0d493dff45e..288a36978a8 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -14,11 +14,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/counter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" @@ -202,22 +204,17 @@ type EthereumOffchainAggregator struct { l zerolog.Logger } -func LoadOffchainAggregator(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { - abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregator", *abi) - seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) +func LoadOffChainAggregator(l zerolog.Logger, sethClient *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { + loader := seth.NewContractLoader[offchainaggregator.OffchainAggregator](sethClient) + instance, err := loader.LoadContract("LinkToken", contractAddress, offchainaggregator.OffchainAggregatorMetaData.GetAbi, offchainaggregator.NewOffchainAggregator) - ocr, err := offchainaggregator.NewOffchainAggregator(contractAddress, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) + return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR v2 instance: %w", err) } return EthereumOffchainAggregator{ - client: seth, - ocr: ocr, + client: sethClient, + ocr: instance, address: &contractAddress, l: l, }, nil @@ -355,10 +352,6 @@ func (o *EthereumOffchainAggregator) SetConfig( return err } - // fails with error setting OCR config for contract '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82': both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified - // but we only have gasPrice set... It also fails with the same error when we enable EIP-1559 - // fails when we wait for it to be minted, inside the wrapper there's no error when we call it, so it must be something inside smart contract - // that's reverting it and maybe the error message is completely off _, err = o.client.Decode(o.ocr.SetConfig(o.client.NewTXOpts(), signers, transmitters, threshold, encodedConfigVersion, encodedConfig)) return err } @@ -582,36 +575,36 @@ type EthereumOffchainAggregatorV2 struct { l zerolog.Logger } -func LoadOffChainAggregatorV2(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregatorV2, error) { - oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() +func LoadOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, address common.Address) (EthereumOffchainAggregatorV2, error) { + contractAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator v2 ABI: %w", err) } - seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddABI("OffChainAggregatorV2", *contractAbi) seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) - ocr2, err := ocr2aggregator.NewOCR2Aggregator(contractAddress, seth.Client) + ocr2, err := ocr2aggregator.NewOCR2Aggregator(address, seth.Client) if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCRv2 instance: %w", err) } return EthereumOffchainAggregatorV2{ client: seth, contract: ocr2, - address: &contractAddress, + address: &address, l: l, }, nil } func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregatorV2, error) { - oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() + contractAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator v2 ABI: %w", err) } - seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddABI("OffChainAggregatorV2", *contractAbi) seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) - ocrDeploymentData2, err := seth.DeployContract(seth.NewTXOpts(), "OffChainAggregatorV2", *oAbi, common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin), + ocrDeploymentData2, err := seth.DeployContract(seth.NewTXOpts(), "OffChainAggregatorV2", *contractAbi, common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin), linkTokenAddress, offchainOptions.MinimumAnswer, offchainOptions.MaximumAnswer, @@ -622,12 +615,12 @@ func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAd ) if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCR instance deployment have failed: %w", err) + return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) } ocr2, err := ocr2aggregator.NewOCR2Aggregator(ocrDeploymentData2.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCRv2 instance: %w", err) } return EthereumOffchainAggregatorV2{ @@ -713,9 +706,9 @@ func (e *EthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { Interface("Signers", ocrConfig.Signers). Interface("Transmitters", ocrConfig.Transmitters). Uint8("F", ocrConfig.F). - Bytes("OnchainConfig", ocrConfig.OnchainConfig). + Str("OnchainConfig", string(ocrConfig.OnchainConfig)). Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). - Bytes("OffchainConfig", ocrConfig.OffchainConfig). + Str("OffchainConfig", string(ocrConfig.OffchainConfig)). Msg("Setting OCRv2 Config") _, err := e.client.Decode(e.contract.SetConfig( @@ -770,22 +763,16 @@ func DeployLinkTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumLi } func LoadLinkTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumLinkToken, error) { - linkABI, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) - } - - client.ContractStore.AddABI("LinkToken", *linkABI) - client.ContractStore.AddBIN("LinkToken", common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) + loader := seth.NewContractLoader[link_token_interface.LinkToken](client) + instance, err := loader.LoadContract("LinkToken", address, link_token_interface.LinkTokenMetaData.GetAbi, link_token_interface.NewLinkToken) - linkToken, err := link_token_interface.NewLinkToken(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) } return &EthereumLinkToken{ client: client, - instance: linkToken, + instance: instance, address: address, l: l, }, nil diff --git a/integration-tests/contracts/ethereum_contracts_atlas.go b/integration-tests/contracts/ethereum_contracts_atlas.go index c28e5198682..4636a92a194 100644 --- a/integration-tests/contracts/ethereum_contracts_atlas.go +++ b/integration-tests/contracts/ethereum_contracts_atlas.go @@ -5,7 +5,8 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index 9c01511ff11..3e18fe177f0 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -14,13 +14,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" registrylogicc23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" @@ -193,10 +194,11 @@ func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address { func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error { txOpts := v.client.NewTXOpts() var err error + var decodedTx *seth.DecodedTransaction switch v.version { case ethereum.RegistryVersion_2_1: - _, err = v.client.Decode(v.registry2_1.SetConfigTypeSafe(txOpts, + decodedTx, err = v.client.Decode(v.registry2_1.SetConfigTypeSafe(txOpts, ocrConfig.Signers, ocrConfig.Transmitters, ocrConfig.F, @@ -205,7 +207,7 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error ocrConfig.OffchainConfig, )) case ethereum.RegistryVersion_2_2: - _, err = v.client.Decode(v.registry2_2.SetConfigTypeSafe(txOpts, + decodedTx, err = v.client.Decode(v.registry2_2.SetConfigTypeSafe(txOpts, ocrConfig.Signers, ocrConfig.Transmitters, ocrConfig.F, @@ -214,7 +216,7 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error ocrConfig.OffchainConfig, )) case ethereum.RegistryVersion_2_3: - _, err = v.client.Decode(v.registry2_3.SetConfigTypeSafe(txOpts, + decodedTx, err = v.client.Decode(v.registry2_3.SetConfigTypeSafe(txOpts, ocrConfig.Signers, ocrConfig.Transmitters, ocrConfig.F, @@ -227,7 +229,7 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error default: return fmt.Errorf("SetConfigTypeSafe is not supported in keeper registry version %d", v.version) } - + v.l.Debug().Interface("decodedTx", decodedTx).Msg("SetConfigTypeSafe") return err } @@ -1368,12 +1370,7 @@ func deployRegistry22(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegi return nil, err } - var allowedReadOnlyAddress common.Address - if chainId == networks.PolygonZkEvmMainnet.ChainID || chainId == networks.PolygonZkEvmCardona.ChainID { - allowedReadOnlyAddress = common.HexToAddress("0x1111111111111111111111111111111111111111") - } else { - allowedReadOnlyAddress = common.HexToAddress("0x0000000000000000000000000000000000000000") - } + allowedReadOnlyAddress := common.HexToAddress("0x0000000000000000000000000000000000000000") logicBAbi, err := registrylogicb22.AutomationRegistryLogicBMetaData.GetAbi() if err != nil { @@ -1456,12 +1453,7 @@ func deployRegistry23(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegi return nil, err } - var allowedReadOnlyAddress common.Address - if chainId == networks.PolygonZkEvmMainnet.ChainID || chainId == networks.PolygonZkEvmCardona.ChainID { - allowedReadOnlyAddress = common.HexToAddress("0x1111111111111111111111111111111111111111") - } else { - allowedReadOnlyAddress = common.HexToAddress("0x0000000000000000000000000000000000000000") - } + allowedReadOnlyAddress := common.HexToAddress("0x0000000000000000000000000000000000000000") logicCAbi, err := registrylogicc23.AutomationRegistryLogicCMetaData.GetAbi() if err != nil { @@ -1537,7 +1529,7 @@ func deployRegistry23(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegi } // LoadKeeperRegistry returns deployed on given address EthereumKeeperRegistry -func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) { +func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Address, registryVersion eth_contracts.KeeperRegistryVersion, chainModuleAddress common.Address) (KeeperRegistry, error) { var keeper *EthereumKeeperRegistry var err error switch registryVersion { @@ -1554,7 +1546,7 @@ func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Ad case eth_contracts.RegistryVersion_2_2: // why the contract name is not the same as the actual contract name? keeper, err = loadRegistry2_2(client, address) case eth_contracts.RegistryVersion_2_3: - keeper, err = loadRegistry2_3(client, address) + keeper, err = loadRegistry2_3(client, address, chainModuleAddress) default: return nil, fmt.Errorf("keeper registry version %d is not supported", registryVersion) } @@ -1694,24 +1686,24 @@ func loadRegistry2_2(client *seth.Client, address common.Address) (*EthereumKeep }, nil } -func loadRegistry2_3(client *seth.Client, address common.Address) (*EthereumKeeperRegistry, error) { - abi, err := iregistry23.IAutomationRegistryMaster23MetaData.GetAbi() +func loadRegistry2_3(client *seth.Client, address, chainModuleAddress common.Address) (*EthereumKeeperRegistry, error) { + + loader := seth.NewContractLoader[iregistry23.IAutomationRegistryMaster23](client) + instance, err := loader.LoadContract("AutomationRegistry2_3", address, iregistry23.IAutomationRegistryMaster23MetaData.GetAbi, iregistry23.NewIAutomationRegistryMaster23) if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistry2_3 ABI: %w", err) + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to load AutomationRegistry2_3 instance: %w", err) } - client.ContractStore.AddABI("AutomationRegistry2_3", *abi) - client.ContractStore.AddBIN("AutomationRegistry2_3", common.FromHex(iregistry23.IAutomationRegistryMaster23MetaData.Bin)) - - instance, err := iregistry23.NewIAutomationRegistryMaster23(address, wrappers.MustNewWrappedContractBackend(nil, client)) + chainModule, err := loadChainModule(client, chainModuleAddress) if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate AutomationRegistry2_3 instance: %w", err) + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to load chain module: %w", err) } return &EthereumKeeperRegistry{ address: &address, client: client, registry2_3: instance, + chainModule: chainModule, }, nil } @@ -1767,6 +1759,26 @@ func deployOptimismModule(client *seth.Client) (common.Address, error) { return data.Address, nil } +func loadChainModule(client *seth.Client, address common.Address) (*i_chain_module.IChainModule, error) { + abi, err := i_chain_module.IChainModuleMetaData.GetAbi() + if err != nil { + return &i_chain_module.IChainModule{}, fmt.Errorf("failed to get IChainModule ABI: %w", err) + } + + client.ContractStore.AddABI("IChainModule", *abi) + client.ContractStore.AddBIN("IChainModule", common.FromHex(i_chain_module.IChainModuleMetaData.Bin)) + + chainModule, err := i_chain_module.NewIChainModule( + address, + wrappers.MustNewWrappedContractBackend(nil, client), + ) + if err != nil { + return &i_chain_module.IChainModule{}, fmt.Errorf("failed to instantiate IChainModule instance: %w", err) + } + + return chainModule, nil +} + func deployBaseModule(client *seth.Client) (common.Address, error) { abi, err := chain_module_base.ChainModuleBaseMetaData.GetAbi() if err != nil { @@ -2202,17 +2214,10 @@ func LoadKeeperRegistrar(client *seth.Client, address common.Address, registryVe if registryVersion == eth_contracts.RegistryVersion_1_1 || registryVersion == eth_contracts.RegistryVersion_1_2 || registryVersion == eth_contracts.RegistryVersion_1_3 { - abi, err := keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.GetAbi() + loader := seth.NewContractLoader[keeper_registrar_wrapper1_2.KeeperRegistrar](client) + instance, err := loader.LoadContract("KeeperRegistrar1_2", address, keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.GetAbi, keeper_registrar_wrapper1_2.NewKeeperRegistrar) if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to get KeeperRegistrar1_2 ABI: %w", err) - } - - client.ContractStore.AddABI("KeeperRegistrar1_2", *abi) - client.ContractStore.AddBIN("KeeperRegistrar1_2", common.FromHex(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.Bin)) - - instance, err := keeper_registrar_wrapper1_2.NewKeeperRegistrar(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to instantiate KeeperRegistrar1_2 instance: %w", err) + return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to load KeeperRegistrar1_2 instance: %w", err) } return &EthereumKeeperRegistrar{ @@ -2221,43 +2226,78 @@ func LoadKeeperRegistrar(client *seth.Client, address common.Address, registryVe registrar: instance, }, err } else if registryVersion == eth_contracts.RegistryVersion_2_0 { - abi, err := keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.GetAbi() + loader := seth.NewContractLoader[keeper_registrar_wrapper2_0.KeeperRegistrar](client) + instance, err := loader.LoadContract("KeeperRegistrar2_0", address, keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.GetAbi, keeper_registrar_wrapper2_0.NewKeeperRegistrar) if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to get KeeperRegistrar2_0 ABI: %w", err) + return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to load KeeperRegistrar2_0 instance: %w", err) } - client.ContractStore.AddABI("KeeperRegistrar2_0", *abi) - client.ContractStore.AddBIN("KeeperRegistrar2_0", common.FromHex(keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.Bin)) + return &EthereumKeeperRegistrar{ + address: &address, + client: client, + registrar20: instance, + }, nil + } else if registryVersion == eth_contracts.RegistryVersion_2_1 || registryVersion == eth_contracts.RegistryVersion_2_2 { + loader := seth.NewContractLoader[registrar21.AutomationRegistrar](client) + instance, err := loader.LoadContract("KeeperRegistrar2_1", address, registrar21.AutomationRegistrarMetaData.GetAbi, registrar21.NewAutomationRegistrar) + if err != nil { + return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to load KeeperRegistrar2_1 instance: %w", err) + } - instance, err := keeper_registrar_wrapper2_0.NewKeeperRegistrar(address, wrappers.MustNewWrappedContractBackend(nil, client)) + return &EthereumKeeperRegistrar{ + address: &address, + client: client, + registrar21: instance, + }, nil + } else if registryVersion == eth_contracts.RegistryVersion_2_3 { + loader := seth.NewContractLoader[registrar23.AutomationRegistrar](client) + instance, err := loader.LoadContract("KeeperRegistrar2_3", address, registrar23.AutomationRegistrarMetaData.GetAbi, registrar23.NewAutomationRegistrar) if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to instantiate KeeperRegistrar2_0 instance: %w", err) + return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to load KeeperRegistrar2_3 instance: %w", err) } return &EthereumKeeperRegistrar{ address: &address, client: client, - registrar20: instance, + registrar23: instance, }, nil } + return &EthereumKeeperRegistrar{}, fmt.Errorf("unsupported registry version: %v", registryVersion) +} - abi, err := registrar21.AutomationRegistrarMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to get KeeperRegistrar2_1 ABI: %w", err) - } +type EthereumAutomationKeeperConsumer struct { + client *seth.Client + consumer *log_upkeep_counter_wrapper.LogUpkeepCounter + address *common.Address +} - client.ContractStore.AddABI("KeeperRegistrar2_1", *abi) - client.ContractStore.AddBIN("KeeperRegistrar2_1", common.FromHex(registrar21.AutomationRegistrarMetaData.Bin)) +func (e EthereumAutomationKeeperConsumer) Address() string { + return e.address.Hex() +} - instance, err := registrar21.NewAutomationRegistrar(address, wrappers.MustNewWrappedContractBackend(nil, client)) +func (e EthereumAutomationKeeperConsumer) Counter(ctx context.Context) (*big.Int, error) { + return e.consumer.Counter(&bind.CallOpts{ + From: e.client.MustGetRootKeyAddress(), + Context: ctx, + }) +} + +func (e EthereumAutomationKeeperConsumer) Start() error { + _, err := e.client.Decode(e.consumer.Start(e.client.NewTXOpts())) + return err +} + +func LoadKeeperConsumer(client *seth.Client, address common.Address) (*EthereumAutomationKeeperConsumer, error) { + loader := seth.NewContractLoader[log_upkeep_counter_wrapper.LogUpkeepCounter](client) + instance, err := loader.LoadContract("KeeperConsumer", address, log_upkeep_counter_wrapper.LogUpkeepCounterMetaData.GetAbi, log_upkeep_counter_wrapper.NewLogUpkeepCounter) if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to instantiate KeeperRegistrar2_1 instance: %w", err) + return &EthereumAutomationKeeperConsumer{}, fmt.Errorf("failed to load KeeperConsumerMetaData instance: %w", err) } - return &EthereumKeeperRegistrar{ - address: &address, - client: client, - registrar21: instance, + return &EthereumAutomationKeeperConsumer{ + client: client, + consumer: instance, + address: &address, }, nil } @@ -2711,21 +2751,35 @@ func (v *EthereumAutomationConsumerBenchmark) GetUpkeepCount(ctx context.Context }, id) } -// DeployKeeperConsumerBenchmark deploys a keeper consumer benchmark contract with a standard contract backend -func DeployKeeperConsumerBenchmark(client *seth.Client) (AutomationConsumerBenchmark, error) { - return deployKeeperConsumerBenchmarkWithWrapperFn(client, func(client *seth.Client) *wrappers.WrappedContractBackend { +// DeployAutomationConsumerBenchmark deploys a keeper consumer benchmark contract with a standard contract backend +func DeployAutomationConsumerBenchmark(client *seth.Client) (AutomationConsumerBenchmark, error) { + return deployAutomationConsumerBenchmarkWithWrapperFn(client, func(client *seth.Client) *wrappers.WrappedContractBackend { return wrappers.MustNewWrappedContractBackend(nil, client) }) } -// DeployKeeperConsumerBenchmarkWithRetry deploys a keeper consumer benchmark contract with a read-only operations retrying contract backend -func DeployKeeperConsumerBenchmarkWithRetry(client *seth.Client, logger zerolog.Logger, maxAttempts uint, retryDelay time.Duration) (AutomationConsumerBenchmark, error) { - return deployKeeperConsumerBenchmarkWithWrapperFn(client, func(client *seth.Client) *wrappers.WrappedContractBackend { +func LoadAutomationConsumerBenchmark(client *seth.Client, address common.Address) (*EthereumAutomationConsumerBenchmark, error) { + loader := seth.NewContractLoader[automation_consumer_benchmark.AutomationConsumerBenchmark](client) + instance, err := loader.LoadContract("AutomationConsumerBenchmark", address, automation_consumer_benchmark.AutomationConsumerBenchmarkMetaData.GetAbi, automation_consumer_benchmark.NewAutomationConsumerBenchmark) + if err != nil { + return &EthereumAutomationConsumerBenchmark{}, fmt.Errorf("failed to load AutomationConsumerBenchmark instance: %w", err) + } + + return &EthereumAutomationConsumerBenchmark{ + client: client, + consumer: instance, + address: &address, + }, nil +} + +// DeployAutomationConsumerBenchmarkWithRetry deploys a keeper consumer benchmark contract with a read-only operations retrying contract backend +func DeployAutomationConsumerBenchmarkWithRetry(client *seth.Client, logger zerolog.Logger, maxAttempts uint, retryDelay time.Duration) (AutomationConsumerBenchmark, error) { + return deployAutomationConsumerBenchmarkWithWrapperFn(client, func(client *seth.Client) *wrappers.WrappedContractBackend { return wrappers.MustNewRetryingWrappedContractBackend(client, logger, maxAttempts, retryDelay) }) } -func deployKeeperConsumerBenchmarkWithWrapperFn(client *seth.Client, wrapperConstrFn func(client *seth.Client) *wrappers.WrappedContractBackend) (AutomationConsumerBenchmark, error) { +func deployAutomationConsumerBenchmarkWithWrapperFn(client *seth.Client, wrapperConstrFn func(client *seth.Client) *wrappers.WrappedContractBackend) (AutomationConsumerBenchmark, error) { abi, err := automation_consumer_benchmark.AutomationConsumerBenchmarkMetaData.GetAbi() if err != nil { return &EthereumAutomationConsumerBenchmark{}, fmt.Errorf("failed to get AutomationConsumerBenchmark ABI: %w", err) @@ -2747,8 +2801,8 @@ func deployKeeperConsumerBenchmarkWithWrapperFn(client *seth.Client, wrapperCons }, nil } -// KeeperConsumerBenchmarkUpkeepObserver is a header subscription that awaits for a round of upkeeps -type KeeperConsumerBenchmarkUpkeepObserver struct { +// AutomationConsumerBenchmarkUpkeepObserver is a header subscription that awaits for a round of upkeeps +type AutomationConsumerBenchmarkUpkeepObserver struct { instance AutomationConsumerBenchmark registry KeeperRegistry upkeepID *big.Int @@ -2772,9 +2826,9 @@ type KeeperConsumerBenchmarkUpkeepObserver struct { l zerolog.Logger } -// NewKeeperConsumerBenchmarkUpkeepObserver provides a new instance of a NewKeeperConsumerBenchmarkUpkeepObserver +// NewAutomationConsumerBenchmarkUpkeepObserver provides a new instance of a NewAutomationConsumerBenchmarkUpkeepObserver // Used to track and log benchmark test results for keepers -func NewKeeperConsumerBenchmarkUpkeepObserver( +func NewAutomationConsumerBenchmarkUpkeepObserver( contract AutomationConsumerBenchmark, registry KeeperRegistry, upkeepID *big.Int, @@ -2784,8 +2838,8 @@ func NewKeeperConsumerBenchmarkUpkeepObserver( upkeepIndex int64, firstEligibleBuffer int64, logger zerolog.Logger, -) *KeeperConsumerBenchmarkUpkeepObserver { - return &KeeperConsumerBenchmarkUpkeepObserver{ +) *AutomationConsumerBenchmarkUpkeepObserver { + return &AutomationConsumerBenchmarkUpkeepObserver{ instance: contract, registry: registry, upkeepID: upkeepID, @@ -2807,7 +2861,7 @@ func NewKeeperConsumerBenchmarkUpkeepObserver( // ReceiveHeader will query the latest Keeper round and check to see whether upkeep was performed, it returns // true when observation has finished. -func (o *KeeperConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader *blockchain.SafeEVMHeader) (bool, error) { +func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader *blockchain.SafeEVMHeader) (bool, error) { if receivedHeader.Number.Uint64() <= o.lastBlockNum { // Uncle / reorg we won't count return false, nil } @@ -2910,12 +2964,12 @@ func (o *KeeperConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader *bl } // Complete returns whether watching for upkeeps has completed -func (o *KeeperConsumerBenchmarkUpkeepObserver) Complete() bool { +func (o *AutomationConsumerBenchmarkUpkeepObserver) Complete() bool { return o.complete } // LogDetails logs the results of the benchmark test to testreporter -func (o *KeeperConsumerBenchmarkUpkeepObserver) LogDetails() { +func (o *AutomationConsumerBenchmarkUpkeepObserver) LogDetails() { report := testreporters.KeeperBenchmarkTestReport{ ContractAddress: o.instance.Address(), TotalEligibleCount: o.countEligible, diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 38aa5c58f0f..90f1af0319b 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -174,7 +174,7 @@ func (rcs *KeeperRegistrySettings) Create23OnchainConfig(registrar string, regis ChainModule: chainModuleAddress, ReorgProtectionEnabled: reorgProtectionEnabled, FinanceAdmin: registryOwnerAddress, - FallbackNativePrice: rcs.FallbackLinkPrice, // Just use the LINK price + FallbackNativePrice: rcs.FallbackNativePrice, } } diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index a09cc809c63..144de176ee9 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -10,15 +10,16 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_optimism" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -353,6 +354,26 @@ func DeployVRFMockETHLINKFeed(seth *seth.Client, answer *big.Int) (VRFMockETHLIN }, err } +func LoadVRFMockETHLINKFeed(client *seth.Client, address common.Address) (VRFMockETHLINKFeed, error) { + abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumVRFMockETHLINKFeed{}, fmt.Errorf("failed to get VRFMockETHLINKAggregator ABI: %w", err) + } + client.ContractStore.AddABI("VRFMockETHLINKAggregator", *abi) + client.ContractStore.AddBIN("VRFMockETHLINKAggregator", common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin)) + + instance, err := vrf_mock_ethlink_aggregator.NewVRFMockETHLINKAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumVRFMockETHLINKFeed{}, fmt.Errorf("failed to instantiate VRFMockETHLINKAggregator instance: %w", err) + } + + return &EthereumVRFMockETHLINKFeed{ + address: address, + client: client, + feed: instance, + }, nil +} + func (v *EthereumBlockhashStore) Address() string { return v.address.Hex() } diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index df4a6fb9fbe..708fdb211eb 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 9b286a1d057..35d22e8ef5b 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -11,16 +11,19 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/montanaflynn/stats" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_vrf_coordinator_v2plus" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_test_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5_arbitrum" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5_optimism" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_arbitrum" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_optimism" ) @@ -37,6 +40,18 @@ type EthereumVRFCoordinatorV2_5_Optimism struct { coordinator vrf_coordinator_v2_5_optimism.VRFCoordinatorV25Optimism } +type EthereumVRFCoordinatorV2_5_Arbitrum struct { + Address common.Address + client *seth.Client + coordinator vrf_coordinator_v2_5_arbitrum.VRFCoordinatorV25Arbitrum +} + +type EthereumVRFCoordinatorTestV2_5 struct { + Address common.Address + client *seth.Client + coordinator vrf_coordinator_test_v2_5.VRFCoordinatorTestV25 +} + type EthereumBatchVRFCoordinatorV2Plus struct { address common.Address client *seth.Client @@ -74,6 +89,12 @@ type EthereumVRFV2PlusWrapperOptimism struct { wrapper *vrfv2plus_wrapper_optimism.VRFV2PlusWrapperOptimism } +type EthereumVRFV2PlusWrapperArbitrum struct { + Address common.Address + client *seth.Client + wrapper *vrfv2plus_wrapper_arbitrum.VRFV2PlusWrapperArbitrum +} + func (v *EthereumVRFV2PlusWrapper) Address() string { return v.address.Hex() } @@ -178,6 +199,56 @@ func DeployVRFCoordinatorV2_5_Optimism(seth *seth.Client, bhsAddr string) (*Ethe }, err } +func DeployVRFCoordinatorV2_5_Arbitrum(seth *seth.Client, bhsAddr string) (*EthereumVRFCoordinatorV2_5_Arbitrum, error) { + abi, err := vrf_coordinator_v2_5_arbitrum.VRFCoordinatorV25ArbitrumMetaData.GetAbi() + if err != nil { + return nil, fmt.Errorf("failed to get VRFCoordinatorV2_5_Arbitrum ABI: %w", err) + } + coordinatorDeploymentData, err := seth.DeployContract( + seth.NewTXOpts(), + "VRFCoordinatorV2_5_Arbitrum", + *abi, + common.FromHex(vrf_coordinator_v2_5_arbitrum.VRFCoordinatorV25ArbitrumMetaData.Bin), + common.HexToAddress(bhsAddr)) + if err != nil { + return nil, fmt.Errorf("VRFCoordinatorV2_5_Arbitrum instance deployment have failed: %w", err) + } + contract, err := vrf_coordinator_v2_5_arbitrum.NewVRFCoordinatorV25Arbitrum(coordinatorDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return nil, fmt.Errorf("failed to instantiate VRFCoordinatorV2_5_Arbitrum instance: %w", err) + } + return &EthereumVRFCoordinatorV2_5_Arbitrum{ + client: seth, + coordinator: *contract, + Address: coordinatorDeploymentData.Address, + }, err +} + +func DeployVRFCoordinatorTestV2_5(seth *seth.Client, bhsAddr string) (*EthereumVRFCoordinatorTestV2_5, error) { + abi, err := vrf_coordinator_test_v2_5.VRFCoordinatorTestV25MetaData.GetAbi() + if err != nil { + return nil, fmt.Errorf("failed to get VRFCoordinatorTestV2_5 ABI: %w", err) + } + coordinatorDeploymentData, err := seth.DeployContract( + seth.NewTXOpts(), + "VRFCoordinatorTestV2_5", + *abi, + common.FromHex(vrf_coordinator_test_v2_5.VRFCoordinatorTestV25MetaData.Bin), + common.HexToAddress(bhsAddr)) + if err != nil { + return nil, fmt.Errorf("VRFCoordinatorTestV2_5 instance deployment have failed: %w", err) + } + contract, err := vrf_coordinator_test_v2_5.NewVRFCoordinatorTestV25(coordinatorDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return nil, fmt.Errorf("failed to instantiate VRFCoordinatorTestV2_5 instance: %w", err) + } + return &EthereumVRFCoordinatorTestV2_5{ + client: seth, + coordinator: *contract, + Address: coordinatorDeploymentData.Address, + }, err +} + func DeployBatchVRFCoordinatorV2Plus(seth *seth.Client, coordinatorAddress string) (BatchVRFCoordinatorV2Plus, error) { abi, err := batch_vrf_coordinator_v2plus.BatchVRFCoordinatorV2PlusMetaData.GetAbi() if err != nil { @@ -364,6 +435,18 @@ func (v *EthereumVRFCoordinatorV2_5) GetLinkNativeFeed(ctx context.Context) (com return address, nil } +func (v *EthereumVRFCoordinatorV2_5) GetConfig(ctx context.Context) (vrf_coordinator_v2_5.SConfig, error) { + opts := &bind.CallOpts{ + From: v.client.MustGetRootKeyAddress(), + Context: ctx, + } + config, err := v.coordinator.SConfig(opts) + if err != nil { + return vrf_coordinator_v2_5.SConfig{}, err + } + return config, nil +} + // OwnerCancelSubscription cancels subscription by Coordinator owner // return funds to sub owner, // does not check if pending requests for a sub exist @@ -1185,24 +1268,50 @@ func DeployVRFV2PlusWrapper(seth *seth.Client, linkAddr string, linkEthFeedAddr }, err } +func DeployVRFV2PlusWrapperArbitrum(seth *seth.Client, linkAddr string, linkEthFeedAddr string, coordinatorAddr string, subId *big.Int) (*EthereumVRFV2PlusWrapperArbitrum, error) { + abi, err := vrfv2plus_wrapper_arbitrum.VRFV2PlusWrapperArbitrumMetaData.GetAbi() + if err != nil { + return nil, fmt.Errorf("failed to get VRFV2PlusWrapper_Arbitrum ABI: %w", err) + } + data, err := seth.DeployContract( + seth.NewTXOpts(), + "VRFV2PlusWrapper_Arbitrum", + *abi, + common.FromHex(vrfv2plus_wrapper_arbitrum.VRFV2PlusWrapperArbitrumMetaData.Bin), + common.HexToAddress(linkAddr), common.HexToAddress(linkEthFeedAddr), + common.HexToAddress(coordinatorAddr), subId) + if err != nil { + return nil, fmt.Errorf("VRFV2PlusWrapper_Arbitrum instance deployment have failed: %w", err) + } + contract, err := vrfv2plus_wrapper_arbitrum.NewVRFV2PlusWrapperArbitrum(data.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return nil, fmt.Errorf("failed to instantiate VRFV2PlusWrapper_Arbitrum instance: %w", err) + } + return &EthereumVRFV2PlusWrapperArbitrum{ + client: seth, + wrapper: contract, + Address: data.Address, + }, err +} + func DeployVRFV2PlusWrapperOptimism(seth *seth.Client, linkAddr string, linkEthFeedAddr string, coordinatorAddr string, subId *big.Int) (*EthereumVRFV2PlusWrapperOptimism, error) { abi, err := vrfv2plus_wrapper_optimism.VRFV2PlusWrapperOptimismMetaData.GetAbi() if err != nil { - return nil, fmt.Errorf("failed to get VRFV2PlusWrapperOptimism ABI: %w", err) + return nil, fmt.Errorf("failed to get VRFV2PlusWrapper_Optimism ABI: %w", err) } data, err := seth.DeployContract( seth.NewTXOpts(), - "VRFV2PlusWrapperOptimism", + "VRFV2PlusWrapper_Optimism", *abi, common.FromHex(vrfv2plus_wrapper_optimism.VRFV2PlusWrapperOptimismMetaData.Bin), common.HexToAddress(linkAddr), common.HexToAddress(linkEthFeedAddr), common.HexToAddress(coordinatorAddr), subId) if err != nil { - return nil, fmt.Errorf("VRFV2PlusWrapperOptimism instance deployment have failed: %w", err) + return nil, fmt.Errorf("VRFV2PlusWrapper_Optimism instance deployment have failed: %w", err) } contract, err := vrfv2plus_wrapper_optimism.NewVRFV2PlusWrapperOptimism(data.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return nil, fmt.Errorf("failed to instantiate VRFV2PlusWrapperOptimism instance: %w", err) + return nil, fmt.Errorf("failed to instantiate VRFV2PlusWrapper_Optimism instance: %w", err) } return &EthereumVRFV2PlusWrapperOptimism{ client: seth, diff --git a/integration-tests/contracts/multicall.go b/integration-tests/contracts/multicall.go index 6b73aed084c..cd7134a8d85 100644 --- a/integration-tests/contracts/multicall.go +++ b/integration-tests/contracts/multicall.go @@ -8,7 +8,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" ) diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go index 85e76054c71..f8674e2136d 100644 --- a/integration-tests/contracts/test_contracts.go +++ b/integration-tests/contracts/test_contracts.go @@ -7,7 +7,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" diff --git a/integration-tests/crib/README.md b/integration-tests/crib/README.md index e895cca6763..c37cbfec9c9 100644 --- a/integration-tests/crib/README.md +++ b/integration-tests/crib/README.md @@ -19,7 +19,7 @@ export CRIB_NODES=5 # min 5 nodes #export RESTY_DEBUG=true #export TEST_PERSISTENCE=true # to run the chaos test export GAP_URL=https://localhost:8080/primary # only applicable in CI, unset the var to connect locally -go test -v -run TestCRIB +go test -v -run TestCRIBChaos ``` ## Configuring CI workflow diff --git a/integration-tests/crib/chaos.go b/integration-tests/crib/chaos.go index bbf6ca681cd..463ced483fa 100644 --- a/integration-tests/crib/chaos.go +++ b/integration-tests/crib/chaos.go @@ -4,16 +4,17 @@ import ( "time" "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" - "github.com/smartcontractkit/havoc/k8schaos" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/smartcontractkit/chainlink-testing-framework/havoc" ) -func rebootCLNamespace(delay time.Duration, namespace string) (*k8schaos.Chaos, error) { - k8sClient, err := k8schaos.NewChaosMeshClient() +func rebootCLNamespace(delay time.Duration, namespace string) (*havoc.Chaos, error) { + k8sClient, err := havoc.NewChaosMeshClient() if err != nil { return nil, err } - return k8schaos.NewChaos(k8schaos.ChaosOpts{ + return havoc.NewChaos(havoc.ChaosOpts{ Description: "Reboot CRIB", DelayCreate: delay, Object: &v1alpha1.PodChaos{ @@ -40,6 +41,6 @@ func rebootCLNamespace(delay time.Duration, namespace string) (*k8schaos.Chaos, }, }, Client: k8sClient, - Logger: &k8schaos.Logger, + Logger: &havoc.Logger, }) } diff --git a/integration-tests/crib/connect.go b/integration-tests/crib/connect.go index c180b2ff2ea..acc16b74f99 100644 --- a/integration-tests/crib/connect.go +++ b/integration-tests/crib/connect.go @@ -4,17 +4,18 @@ import ( "net/http" "time" - "github.com/smartcontractkit/chainlink-testing-framework/crib" + "github.com/smartcontractkit/chainlink-testing-framework/lib/crib" "github.com/pkg/errors" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - msClient "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + msClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/integration-tests/client" ) @@ -36,16 +37,17 @@ func ConnectRemote() ( *msClient.MockserverClient, *client.ChainlinkK8sClient, []*client.ChainlinkK8sClient, + *crib.CoreDONConnectionConfig, error, ) { vars, err := crib.CoreDONSimulatedConnection() if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } // TODO: move all the parts of ConnectRemote() to CTF when Seth config refactor is finalized config, err := tc.GetConfig([]string{"CRIB"}, tc.OCR) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } var sethClient *seth.Client switch vars.Network { @@ -68,10 +70,10 @@ func ConnectRemote() ( } sethClient, err = seth_utils.GetChainClient(config, net) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } default: - return nil, nil, nil, nil, errors.New("CRIB network is not supported") + return nil, nil, nil, nil, nil, errors.New("CRIB network is not supported") } // bootstrap node clClients := make([]*client.ChainlinkK8sClient, 0) @@ -83,7 +85,7 @@ func ConnectRemote() ( Headers: vars.NodeHeaders[0], }, vars.NodeInternalDNS[0], vars.Namespace) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } clClients = append(clClients, c) // all the other nodes, indices of nodes in CRIB starts with 1 @@ -96,7 +98,7 @@ func ConnectRemote() ( Headers: vars.NodeHeaders[i], }, vars.NodeInternalDNS[i], vars.Namespace) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } clClients = append(clClients, cl) } @@ -107,5 +109,5 @@ func ConnectRemote() ( }) //nolint:gosec // G602 - false positive https://github.com/securego/gosec/issues/1005 - return sethClient, mockServerClient, clClients[0], clClients[1:], nil + return sethClient, mockServerClient, clClients[0], clClients[1:], vars, nil } diff --git a/integration-tests/crib/ocr_test.go b/integration-tests/crib/ocr_test.go index 91a7a1d76b8..215734c318e 100644 --- a/integration-tests/crib/ocr_test.go +++ b/integration-tests/crib/ocr_test.go @@ -6,25 +6,32 @@ import ( "testing" "time" - "github.com/smartcontractkit/havoc/k8schaos" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + ocr_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ocr" ) -func TestCRIB(t *testing.T) { +// TestCRIBChaos an example of how we can run chaos tests with havoc and core CRIB +func TestCRIBChaos(t *testing.T) { l := logging.GetTestLogger(t) + config, err := tc.GetConfig([]string{"Crib"}, tc.OCR) + require.NoError(t, err) - sethClient, msClient, bootstrapNode, workerNodes, err := ConnectRemote() + sethClient, msClient, bootstrapNode, workerNodes, _, err := ConnectRemote() require.NoError(t, err) - lta, err := actions.SetupOCRv1Cluster(l, sethClient, workerNodes) + lta, err := actions.SetupOCRv1Cluster(l, sethClient, config.OCR, workerNodes) require.NoError(t, err) - ocrInstances, err := actions.SetupOCRv1Feed(l, sethClient, lta, msClient, bootstrapNode, workerNodes) + ocrInstances, err := actions.SetupOCRv1Feed(l, sethClient, lta, config.OCR, msClient, bootstrapNode, workerNodes) require.NoError(t, err) err = actions.SetAllAdapterResponsesToTheSameValue(10, ocrInstances, workerNodes, msClient) @@ -39,11 +46,12 @@ func TestCRIB(t *testing.T) { 1*time.Second, os.Getenv("CRIB_NAMESPACE"), ) + require.NoError(t, err, "Error rebooting CL namespace") ch.Create(context.Background()) - ch.AddListener(k8schaos.NewChaosLogger(l)) + ch.AddListener(havoc.NewChaosLogger(l)) t.Cleanup(func() { err := ch.Delete(context.Background()) - require.NoError(t, err) + require.NoError(t, err, "Error deleting chaos") }) require.Eventually(t, func() bool { err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), 5*time.Minute) @@ -55,3 +63,36 @@ func TestCRIB(t *testing.T) { }, 20*time.Minute, 5*time.Second) } } + +// TestCRIBRPCChaos and example of how we can run RPC chaos with Geth or Anvil +func TestCRIBRPCChaos(t *testing.T) { + l := logging.GetTestLogger(t) + + sethClient, msClient, bootstrapNode, workerNodes, vars, err := ConnectRemote() + require.NoError(t, err) + + ocrConfig := &ocr_config.Config{ + Contracts: &ocr_config.Contracts{ + ShouldBeUsed: ptr.Ptr(false), + }, + } + + lta, err := actions.SetupOCRv1Cluster(l, sethClient, ocrConfig, workerNodes) + require.NoError(t, err) + ocrInstances, err := actions.SetupOCRv1Feed(l, sethClient, lta, ocrConfig, msClient, bootstrapNode, workerNodes) + require.NoError(t, err) + + err = actions.SetAllAdapterResponsesToTheSameValue(10, ocrInstances, workerNodes, msClient) + require.NoError(t, err) + actions.SimulateOCRv1EAActivity(l, 3*time.Second, ocrInstances, workerNodes, msClient) + + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), 5*time.Minute) + require.NoError(t, err, "Error watching for new OCR round") + + ac := client.NewRPCClient(sethClient.URL, vars.BlockchainNodeHeaders) + err = ac.GethSetHead(10) + require.NoError(t, err) + + err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), 5*time.Minute) + require.NoError(t, err, "Error watching for new OCR round") +} diff --git a/integration-tests/deployment/README.md b/integration-tests/deployment/README.md new file mode 100644 index 00000000000..a87d627063b --- /dev/null +++ b/integration-tests/deployment/README.md @@ -0,0 +1,70 @@ +### Overview +The deployment package in the integration-tests Go module serves +as a product agnostic set of environment abstractions used +to deploy and configure products including both on/offchain +dependencies. The environment abstractions allow for +complex and critical deployment/configuration logic to be tested +against ephemeral environments and then exposed for use in persistent +environments like testnet/mainnet. + +### Directory structure + +/deployment +- package name `deployment` +- Product agnostic environment abstractions and helpers using those + abstractions + +/deployment/memory +- package name `memory` +- In-memory environment for fast integration testing +- EVM only + +/deployment/devenv +- package name `devenv` +- Docker environment for higher fidelity testing +- Support non-EVMs (yet to be implemented) + +/deployment/ccip +- package name `ccipdeployment` +- Files and tests per product deployment/configuration workflows +- Tests can use deployment/memory for fast integration testing +- TODO: System state representation is defined here, need to define + an interface to comply with for all products. + +/deployment/ccip/changeset +- package name `changeset` imported as `ccipchangesets` +- These function like scripts describing state transitions + you wish to apply to _persistent_ environments like testnet/mainnet +- They should be go functions where the first argument is an + environment and the second argument is a config struct which can be unique to the + changeset. The return value should be a `deployment.ChangesetOutput` and an error. +```Go +do_something.go +func DoSomethingChangeSet(env deployment.Environment, c ccipdeployment.Config) (deployment.ChangesetOutput, error) +{ + // Deploy contracts, generate MCMS proposals, generate + // job specs according to contracts etc. + return deployment.ChangesetOutput{}, nil +} +do_something_test.go +func TestDoSomething(t *testing.T) +{ + // Set up memory env + // DoSomethingChangeSet function + // Take the artifacts from ChangeSet output + // Apply them to the memory env + // Send traffic, run assertions etc. +} +``` +- Changesets are exposed and applied via a different repo. + +/deployment/llo +- package name `llodeployment` +- Similar to /deploymet/ccip, these are product-specific deployment/configuration workflows +- Tests can use deployment/memory for fast integration testing + +/deployment/llo/changeset +- package name `changeset` imported as `llochangesets` +- Similar to deployment/ccip/changesets +- These function like scripts describing state transitions + you wish to apply to _persistent_ environments like testnet/mainnet diff --git a/integration-tests/deployment/address_book.go b/integration-tests/deployment/address_book.go new file mode 100644 index 00000000000..8385bc0e9f1 --- /dev/null +++ b/integration-tests/deployment/address_book.go @@ -0,0 +1,181 @@ +package deployment + +import ( + "fmt" + "strings" + + "github.com/Masterminds/semver/v3" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + chainsel "github.com/smartcontractkit/chain-selectors" +) + +var ( + ErrInvalidChainSelector = fmt.Errorf("invalid chain selector") + ErrInvalidAddress = fmt.Errorf("invalid address") + ErrChainNotFound = fmt.Errorf("chain not found") +) + +// ContractType is a simple string type for identifying contract types. +type ContractType string + +var ( + Version1_0_0 = *semver.MustParse("1.0.0") + Version1_1_0 = *semver.MustParse("1.1.0") + Version1_2_0 = *semver.MustParse("1.2.0") + Version1_5_0 = *semver.MustParse("1.5.0") + Version1_6_0_dev = *semver.MustParse("1.6.0-dev") +) + +type TypeAndVersion struct { + Type ContractType + Version semver.Version +} + +func (tv TypeAndVersion) String() string { + return fmt.Sprintf("%s %s", tv.Type, tv.Version.String()) +} + +func (tv TypeAndVersion) Equal(other TypeAndVersion) bool { + return tv.String() == other.String() +} + +func MustTypeAndVersionFromString(s string) TypeAndVersion { + tv, err := TypeAndVersionFromString(s) + if err != nil { + panic(err) + } + return tv +} + +// Note this will become useful for validation. When we want +// to assert an onchain call to typeAndVersion yields whats expected. +func TypeAndVersionFromString(s string) (TypeAndVersion, error) { + parts := strings.Split(s, " ") + if len(parts) != 2 { + return TypeAndVersion{}, fmt.Errorf("invalid type and version string: %s", s) + } + v, err := semver.NewVersion(parts[1]) + if err != nil { + return TypeAndVersion{}, err + } + return TypeAndVersion{ + Type: ContractType(parts[0]), + Version: *v, + }, nil +} + +func NewTypeAndVersion(t ContractType, v semver.Version) TypeAndVersion { + return TypeAndVersion{ + Type: t, + Version: v, + } +} + +// AddressBook is a simple interface for storing and retrieving contract addresses across +// chains. It is family agnostic as the keys are chain selectors. +// We store rather than derive typeAndVersion as some contracts do not support it. +// For ethereum addresses are always stored in EIP55 format. +type AddressBook interface { + Save(chainSelector uint64, address string, tv TypeAndVersion) error + Addresses() (map[uint64]map[string]TypeAndVersion, error) + AddressesForChain(chain uint64) (map[string]TypeAndVersion, error) + // Allows for merging address books (e.g. new deployments with existing ones) + Merge(other AddressBook) error +} + +type AddressBookMap struct { + AddressesByChain map[uint64]map[string]TypeAndVersion +} + +// Save will save an address for a given chain selector. It will error if there is a conflicting existing address. +func (m *AddressBookMap) Save(chainSelector uint64, address string, typeAndVersion TypeAndVersion) error { + _, exists := chainsel.ChainBySelector(chainSelector) + if !exists { + return errors.Wrapf(ErrInvalidChainSelector, "chain selector %d", chainSelector) + } + if address == "" || address == common.HexToAddress("0x0").Hex() { + return errors.Wrap(ErrInvalidAddress, "address cannot be empty") + } + if common.IsHexAddress(address) { + // IMPORTANT: WE ALWAYS STANDARDIZE ETHEREUM ADDRESS STRINGS TO EIP55 + address = common.HexToAddress(address).Hex() + } else { + return errors.Wrapf(ErrInvalidAddress, "address %s is not a valid Ethereum address, only Ethereum addresses supported", address) + } + if typeAndVersion.Type == "" { + return fmt.Errorf("type cannot be empty") + } + if _, exists := m.AddressesByChain[chainSelector]; !exists { + // First time chain add, create map + m.AddressesByChain[chainSelector] = make(map[string]TypeAndVersion) + } + if _, exists := m.AddressesByChain[chainSelector][address]; exists { + return fmt.Errorf("address %s already exists for chain %d", address, chainSelector) + } + m.AddressesByChain[chainSelector][address] = typeAndVersion + return nil +} + +func (m *AddressBookMap) Addresses() (map[uint64]map[string]TypeAndVersion, error) { + return m.AddressesByChain, nil +} + +func (m *AddressBookMap) AddressesForChain(chainSelector uint64) (map[string]TypeAndVersion, error) { + _, exists := chainsel.ChainBySelector(chainSelector) + if !exists { + return nil, errors.Wrapf(ErrInvalidChainSelector, "chain selector %d", chainSelector) + } + if _, exists := m.AddressesByChain[chainSelector]; !exists { + return nil, errors.Wrapf(ErrChainNotFound, "chain selector %d", chainSelector) + } + return m.AddressesByChain[chainSelector], nil +} + +// Merge will merge the addresses from another address book into this one. +// It will error on any existing addresses. +func (m *AddressBookMap) Merge(ab AddressBook) error { + addresses, err := ab.Addresses() + if err != nil { + return err + } + for chain, chainAddresses := range addresses { + for address, typeAndVersions := range chainAddresses { + if err := m.Save(chain, address, typeAndVersions); err != nil { + return err + } + } + } + return nil +} + +// TODO: Maybe could add an environment argument +// which would ensure only mainnet/testnet chain selectors are used +// for further safety? +func NewMemoryAddressBook() *AddressBookMap { + return &AddressBookMap{ + AddressesByChain: make(map[uint64]map[string]TypeAndVersion), + } +} + +func NewMemoryAddressBookFromMap(addressesByChain map[uint64]map[string]TypeAndVersion) *AddressBookMap { + return &AddressBookMap{ + AddressesByChain: addressesByChain, + } +} + +// SearchAddressBook search an address book for a given chain and contract type and return the first matching address. +func SearchAddressBook(ab AddressBook, chain uint64, typ ContractType) (string, error) { + addrs, err := ab.AddressesForChain(chain) + if err != nil { + return "", err + } + + for addr, tv := range addrs { + if tv.Type == typ { + return addr, nil + } + } + + return "", fmt.Errorf("not found") +} diff --git a/integration-tests/deployment/address_book_test.go b/integration-tests/deployment/address_book_test.go new file mode 100644 index 00000000000..bf3d2ad965c --- /dev/null +++ b/integration-tests/deployment/address_book_test.go @@ -0,0 +1,120 @@ +package deployment + +import ( + "errors" + "testing" + + "github.com/ethereum/go-ethereum/common" + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" +) + +func TestAddressBook_Save(t *testing.T) { + ab := NewMemoryAddressBook() + onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) + onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) + addr1 := common.HexToAddress("0x1").String() + addr2 := common.HexToAddress("0x2").String() + + err := ab.Save(chainsel.TEST_90000001.Selector, addr1, onRamp100) + require.NoError(t, err) + + // Invalid address + err = ab.Save(chainsel.TEST_90000001.Selector, "asdlfkj", onRamp100) + require.Error(t, err) + assert.Equal(t, errors.Is(err, ErrInvalidAddress), true, "err %s", err) + + // Valid chain but not present. + _, err = ab.AddressesForChain(chainsel.TEST_90000002.Selector) + assert.Equal(t, errors.Is(err, ErrChainNotFound), true, "err %s", err) + + // Invalid selector + err = ab.Save(0, addr1, onRamp100) + require.Error(t, err) + assert.Equal(t, errors.Is(err, ErrInvalidChainSelector), true) + + // Duplicate + err = ab.Save(chainsel.TEST_90000001.Selector, addr1, onRamp100) + require.Error(t, err) + + // Zero address + err = ab.Save(chainsel.TEST_90000001.Selector, common.HexToAddress("0x0").Hex(), onRamp100) + require.Error(t, err) + + // Distinct address same TV will not + err = ab.Save(chainsel.TEST_90000001.Selector, addr2, onRamp100) + require.NoError(t, err) + // Same address different chain will not error + err = ab.Save(chainsel.TEST_90000002.Selector, addr1, onRamp100) + require.NoError(t, err) + // We can save different versions of the same contract + err = ab.Save(chainsel.TEST_90000002.Selector, addr2, onRamp110) + require.NoError(t, err) + + addresses, err := ab.Addresses() + require.NoError(t, err) + assert.DeepEqual(t, addresses, map[uint64]map[string]TypeAndVersion{ + chainsel.TEST_90000001.Selector: { + addr1: onRamp100, + addr2: onRamp100, + }, + chainsel.TEST_90000002.Selector: { + addr1: onRamp100, + addr2: onRamp110, + }, + }) +} + +func TestAddressBook_Merge(t *testing.T) { + onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) + onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) + addr1 := common.HexToAddress("0x1").String() + addr2 := common.HexToAddress("0x2").String() + a1 := NewMemoryAddressBookFromMap(map[uint64]map[string]TypeAndVersion{ + chainsel.TEST_90000001.Selector: { + addr1: onRamp100, + }, + }) + a2 := NewMemoryAddressBookFromMap(map[uint64]map[string]TypeAndVersion{ + chainsel.TEST_90000001.Selector: { + addr2: onRamp100, + }, + chainsel.TEST_90000002.Selector: { + addr1: onRamp110, + }, + }) + require.NoError(t, a1.Merge(a2)) + + addresses, err := a1.Addresses() + require.NoError(t, err) + assert.DeepEqual(t, addresses, map[uint64]map[string]TypeAndVersion{ + chainsel.TEST_90000001.Selector: { + addr1: onRamp100, + addr2: onRamp100, + }, + chainsel.TEST_90000002.Selector: { + addr1: onRamp110, + }, + }) + + // Merge with conflicting addresses should error + a3 := NewMemoryAddressBookFromMap(map[uint64]map[string]TypeAndVersion{ + chainsel.TEST_90000001.Selector: { + addr1: onRamp100, + }, + }) + require.Error(t, a1.Merge(a3)) + // a1 should not have changed + addresses, err = a1.Addresses() + require.NoError(t, err) + assert.DeepEqual(t, addresses, map[uint64]map[string]TypeAndVersion{ + chainsel.TEST_90000001.Selector: { + addr1: onRamp100, + addr2: onRamp100, + }, + chainsel.TEST_90000002.Selector: { + addr1: onRamp110, + }, + }) +} diff --git a/integration-tests/deployment/ccip/add_chain.go b/integration-tests/deployment/ccip/add_chain.go new file mode 100644 index 00000000000..3dc1f2db5eb --- /dev/null +++ b/integration-tests/deployment/ccip/add_chain.go @@ -0,0 +1,210 @@ +package ccipdeployment + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "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/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" +) + +// NewChainInboundProposal generates a proposal +// to connect the new chain to the existing chains. +func NewChainInboundProposal( + e deployment.Environment, + state CCIPOnChainState, + homeChainSel uint64, + newChainSel uint64, + sources []uint64, +) (*timelock.MCMSWithTimelockProposal, error) { + // Generate proposal which enables new destination (from test router) on all source chains. + var batches []timelock.BatchChainOperation + var chains []uint64 + for _, source := range sources { + chain, _ := chainsel.ChainBySelector(source) + enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(deployment.SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{ + { + DestChainSelector: newChainSel, + Router: state.Chains[source].TestRouter.Address(), + }, + }) + if err != nil { + return nil, err + } + enableFeeQuoterDest, err := state.Chains[source].FeeQuoter.ApplyDestChainConfigUpdates( + deployment.SimTransactOpts(), + []fee_quoter.FeeQuoterDestChainConfigArgs{ + { + DestChainSelector: newChainSel, + DestChainConfig: defaultFeeQuoterDestChainConfig(), + }, + }) + if err != nil { + return nil, err + } + initialPrices, err := state.Chains[source].FeeQuoter.UpdatePrices( + deployment.SimTransactOpts(), + fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{}, + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ + { + DestChainSelector: newChainSel, + // TODO: parameterize + UsdPerUnitGas: big.NewInt(2e12), + }, + }}) + if err != nil { + return nil, err + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chain.Selector), + Batch: []mcms.Operation{ + { + // Enable the source in on ramp + To: state.Chains[source].OnRamp.Address(), + Data: enableOnRampDest.Data(), + Value: big.NewInt(0), + }, + { + // Set initial dest prices to unblock testing. + To: state.Chains[source].FeeQuoter.Address(), + Data: initialPrices.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[source].FeeQuoter.Address(), + Data: enableFeeQuoterDest.Data(), + Value: big.NewInt(0), + }, + }, + }) + chains = append(chains, source) + } + + homeChain, _ := chainsel.ChainBySelector(homeChainSel) + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil { + return nil, err + } + encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), + DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), + OptimisticConfirmations: 1, + }) + if err != nil { + return nil, err + } + chainConfig := SetupConfigInfo(newChainSel, nodes.NonBootstraps().PeerIDs(), + nodes.DefaultF(), encodedExtraChainConfig) + addChain, err := state.Chains[homeChainSel].CCIPHome.ApplyChainConfigUpdates( + deployment.SimTransactOpts(), nil, []ccip_home.CCIPHomeChainConfigArgs{ + chainConfig, + }) + if err != nil { + return nil, err + } + + timelockAddresses, metaDataPerChain, err := BuildProposalMetadata(state, append(chains, homeChainSel)) + if err != nil { + return nil, err + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(homeChain.Selector), + Batch: []mcms.Operation{ + { + // Add the chain first, don needs it to be there. + To: state.Chains[homeChainSel].CCIPHome.Address(), + Data: addChain.Data(), + Value: big.NewInt(0), + }, + }, + }) + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO: should be parameterized and based on current block timestamp. + []mcms.Signature{}, + false, + metaDataPerChain, + timelockAddresses, + "blah", // TODO + batches, + timelock.Schedule, + "0s", // TODO: Should be parameterized. + ) +} + +// AddDonAndSetCandidateForCommitProposal adds new DON for destination to home chain +// and sets the commit plugin config as candidateConfig for the don. +func AddDonAndSetCandidateForCommitProposal( + state CCIPOnChainState, + e deployment.Environment, + nodes deployment.Nodes, + ocrSecrets deployment.OCRSecrets, + homeChainSel, feedChainSel, newChainSel uint64, + tokenConfig TokenConfig, + rmnHomeAddress common.Address, +) (*timelock.MCMSWithTimelockProposal, error) { + newDONArgs, err := BuildOCR3ConfigForCCIPHome( + e.Logger, + ocrSecrets, + state.Chains[newChainSel].OffRamp, + e.Chains[newChainSel], + feedChainSel, + tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), + nodes.NonBootstraps(), + rmnHomeAddress, + ) + if err != nil { + return nil, err + } + latestDon, err := LatestCCIPDON(state.Chains[homeChainSel].CapabilityRegistry) + if err != nil { + return nil, err + } + commitConfig, ok := newDONArgs[types.PluginTypeCCIPCommit] + if !ok { + return nil, fmt.Errorf("missing commit plugin in ocr3Configs") + } + donID := latestDon.Id + 1 + addDonOp, err := SetCandidateCommitPluginWithAddDonOps( + donID, commitConfig, + state.Chains[homeChainSel].CapabilityRegistry, + nodes.NonBootstraps(), + ) + if err != nil { + return nil, err + } + timelockAddresses, metaDataPerChain, err := BuildProposalMetadata(state, []uint64{homeChainSel}) + if err != nil { + return nil, err + } + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO: should be parameterized and based on current block timestamp. + []mcms.Signature{}, + false, + metaDataPerChain, + timelockAddresses, + "SetCandidate for commit And AddDon for new chain", + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: []mcms.Operation{addDonOp}, + }}, + timelock.Schedule, + "0s", // TODO: Should be parameterized. + ) +} diff --git a/integration-tests/deployment/ccip/add_chain_test.go b/integration-tests/deployment/ccip/add_chain_test.go new file mode 100644 index 00000000000..b84cb399bec --- /dev/null +++ b/integration-tests/deployment/ccip/add_chain_test.go @@ -0,0 +1,240 @@ +package ccipdeployment + +import ( + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/integration-tests/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.Skip("Skipping test. Working on it in another PR") + // 4 chains where the 4th is added after initial deployment. + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 4) + state, err := LoadOnchainState(e.Env, e.Ab) + 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}) + + feeds := state.Chains[e.FeedChainSel].USDFeeds + tokenConfig := NewTokenConfig() + tokenConfig.UpsertTokenInfo(LinkSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[LinkSymbol].Address().String(), + Decimals: LinkDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + tokenConfig.UpsertTokenInfo(WethSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[WethSymbol].Address().String(), + Decimals: WethDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + err = DeployCCIPContracts(e.Env, e.Ab, DeployCCIPContractConfig{ + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainsToDeploy: initialDeploy, + TokenConfig: tokenConfig, + MCMSConfig: NewTestMCMSConfig(t, e.Env), + FeeTokenContracts: e.FeeTokenContracts, + CapabilityRegistry: state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + state, err = LoadOnchainState(e.Env, e.Ab) + require.NoError(t, err) + + // Connect all the existing lanes. + for _, source := range initialDeploy { + for _, dest := range initialDeploy { + if source != dest { + require.NoError(t, AddLane(e.Env, state, source, dest)) + } + } + } + + rmnHomeAddress, err := deployment.SearchAddressBook(e.Ab, 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 + err = DeployChainContracts(e.Env, e.Env.Chains[newChain], e.Ab, e.FeeTokenContracts[newChain], NewTestMCMSConfig(t, e.Env), rmnHome) + require.NoError(t, err) + state, err = LoadOnchainState(e.Env, e.Ab) + require.NoError(t, err) + + // Transfer onramp/fq ownership to timelock. + // Enable the new dest on the test router. + for _, source := range initialDeploy { + tx, err := state.Chains[source].OnRamp.TransferOwnership(e.Env.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) + require.NoError(t, err) + tx, err = state.Chains[source].FeeQuoter.TransferOwnership(e.Env.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) + require.NoError(t, err) + 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 CR contract ownership + tx, err := state.Chains[e.HomeChainSel].CapabilityRegistry.TransferOwnership(e.Env.Chains[e.HomeChainSel].DeployerKey, state.Chains[e.HomeChainSel].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[e.HomeChainSel], tx, err) + require.NoError(t, err) + tx, err = state.Chains[e.HomeChainSel].CCIPHome.TransferOwnership(e.Env.Chains[e.HomeChainSel].DeployerKey, state.Chains[e.HomeChainSel].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[e.HomeChainSel], tx, err) + require.NoError(t, err) + + acceptOwnershipProposal, err := GenerateAcceptOwnershipProposal(state, e.HomeChainSel, initialDeploy) + require.NoError(t, err) + acceptOwnershipExec := SignProposal(t, e.Env, acceptOwnershipProposal) + // Apply the accept ownership proposal to all the chains. + for _, sel := range initialDeploy { + ExecuteProposal(t, e.Env, acceptOwnershipExec, state, sel) + } + for _, chain := range initialDeploy { + owner, err2 := state.Chains[chain].OnRamp.Owner(nil) + require.NoError(t, err2) + require.Equal(t, state.Chains[chain].Timelock.Address(), owner) + } + cfgOwner, err := state.Chains[e.HomeChainSel].CCIPHome.Owner(nil) + require.NoError(t, err) + crOwner, err := state.Chains[e.HomeChainSel].CapabilityRegistry.Owner(nil) + require.NoError(t, err) + require.Equal(t, state.Chains[e.HomeChainSel].Timelock.Address(), cfgOwner) + require.Equal(t, state.Chains[e.HomeChainSel].Timelock.Address(), crOwner) + + nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + + // Generate and sign inbound proposal to new 4th chain. + chainInboundProposal, err := NewChainInboundProposal(e.Env, state, e.HomeChainSel, newChain, initialDeploy) + require.NoError(t, err) + chainInboundExec := SignProposal(t, e.Env, chainInboundProposal) + for _, sel := range initialDeploy { + ExecuteProposal(t, e.Env, chainInboundExec, state, sel) + } + // 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 + //SendRequest(t, e.Env, state, initialDeploy[0], newChain, true) + + t.Logf("Executing add don and set candidate proposal for commit plugin on chain %d", newChain) + addDonProp, err := AddDonAndSetCandidateForCommitProposal(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, common.HexToAddress(rmnHomeAddress)) + require.NoError(t, err) + + addDonExec := SignProposal(t, e.Env, addDonProp) + ExecuteProposal(t, e.Env, addDonExec, state, e.HomeChainSel) + + t.Logf("Executing promote candidate proposal for exec plugin on chain %d", newChain) + setCandidateForExecProposal, err := SetCandidateExecPluginProposal(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, common.HexToAddress(rmnHomeAddress)) + require.NoError(t, err) + setCandidateForExecExec := SignProposal(t, e.Env, setCandidateForExecProposal) + ExecuteProposal(t, e.Env, setCandidateForExecExec, state, e.HomeChainSel) + + t.Logf("Executing promote candidate proposal for both commit and exec plugins on chain %d", newChain) + donPromoteProposal, err := PromoteCandidateProposal(state, e.HomeChainSel, newChain, nodes) + require.NoError(t, err) + donPromoteExec := SignProposal(t, e.Env, donPromoteProposal) + ExecuteProposal(t, e.Env, donPromoteExec, state, e.HomeChainSel) + + // verify if the configs are updated + require.NoError(t, ValidateCCIPHomeConfigSetUp( + 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 := LatestCCIPDON(state.Chains[e.HomeChainSel].CapabilityRegistry) + require.NoError(t, err) + ocrConfigs, err := 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, e.Ab) + 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() + seqNr := SendRequest(t, e.Env, state, initialDeploy[0], newChain, true) + require.NoError(t, + ConfirmCommitWithExpectedSeqNumRange(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, cciptypes.SeqNumRange{ + cciptypes.SeqNum(1), + cciptypes.SeqNum(seqNr), + })) + require.NoError(t, + ConfirmExecWithSeqNr(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, seqNr)) + + 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/integration-tests/deployment/ccip/add_lane.go b/integration-tests/deployment/ccip/add_lane.go new file mode 100644 index 00000000000..cfcb906096a --- /dev/null +++ b/integration-tests/deployment/ccip/add_lane.go @@ -0,0 +1,128 @@ +package ccipdeployment + +import ( + "encoding/hex" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +var ( + InitialLinkPrice = deployment.E18Mult(20) + InitialWethPrice = deployment.E18Mult(4000) + InitialGasPrice = big.NewInt(2e12) +) + +func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64) error { + // TODO: Batch + tx, err := state.Chains[from].Router.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: state.Chains[from].Router.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: InitialLinkPrice, + }, + { + SourceToken: state.Chains[from].Weth9.Address(), + UsdPerToken: InitialWethPrice, + }, + }, + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ + { + DestChainSelector: to, + UsdPerUnitGas: InitialGasPrice, + }, + }}) + 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: defaultFeeQuoterDestChainConfig(), + }, + }) + 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: state.Chains[to].Router.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 = state.Chains[to].Router.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: 50_000, + DefaultTokenFeeUSDCents: 1, + DestGasPerPayloadByte: 10, + DestDataAvailabilityOverheadGas: 0, + DestGasPerDataAvailabilityByte: 100, + DestDataAvailabilityMultiplierBps: 1, + DefaultTokenDestGasOverhead: 125_000, + //DefaultTokenDestBytesOverhead: 32, + DefaultTxGasLimit: 200_000, + GasMultiplierWeiPerEth: 1, + NetworkFeeUSDCents: 1, + ChainFamilySelector: [4]byte(evmFamilySelector), + } +} diff --git a/integration-tests/deployment/ccip/add_lane_test.go b/integration-tests/deployment/ccip/add_lane_test.go new file mode 100644 index 00000000000..e63d1845774 --- /dev/null +++ b/integration-tests/deployment/ccip/add_lane_test.go @@ -0,0 +1,66 @@ +package ccipdeployment + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// TestAddLane covers the workflow of adding a lane +// between existing supported chains in CCIP. +func TestAddLane(t *testing.T) { + // TODO: The offchain code doesn't yet support partial lane + // enablement, need to address then re-enable this test. + t.Skip() + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 3) + // Here we have CR + nodes set up, but no CCIP contracts deployed. + state, err := LoadOnchainState(e.Env, e.Ab) + require.NoError(t, err) + // Set up CCIP contracts and a DON per chain. + err = DeployCCIPContracts(e.Env, e.Ab, DeployCCIPContractConfig{ + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + TokenConfig: NewTokenConfig(), + MCMSConfig: NewTestMCMSConfig(t, e.Env), + FeeTokenContracts: e.FeeTokenContracts, + CapabilityRegistry: state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + + // We expect no lanes available on any chain. + state, err = LoadOnchainState(e.Env, e.Ab) + require.NoError(t, err) + for _, chain := range state.Chains { + offRamps, err := chain.Router.GetOffRamps(nil) + require.NoError(t, err) + require.Len(t, offRamps, 0) + } + + // Add one lane and send traffic. + from, to := e.Env.AllChainSelectors()[0], e.Env.AllChainSelectors()[1] + require.NoError(t, AddLane(e.Env, state, from, to)) + + for sel, chain := range state.Chains { + offRamps, err := chain.Router.GetOffRamps(nil) + require.NoError(t, err) + if sel == to { + require.Len(t, offRamps, 1) + } else { + require.Len(t, offRamps, 0) + } + } + latesthdr, err := e.Env.Chains[to].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + startBlock := latesthdr.Number.Uint64() + seqNum := SendRequest(t, e.Env, state, from, to, false) + require.Equal(t, uint64(1), seqNum) + require.NoError(t, ConfirmExecWithSeqNr(t, e.Env.Chains[from], e.Env.Chains[to], state.Chains[to].OffRamp, &startBlock, seqNum)) + + // TODO: Add a second lane, then disable the first and + // ensure we can send on the second but not the first. +} diff --git a/integration-tests/deployment/ccip/changeset/cap_reg.go b/integration-tests/deployment/ccip/changeset/cap_reg.go new file mode 100644 index 00000000000..f1de1016ddf --- /dev/null +++ b/integration-tests/deployment/ccip/changeset/cap_reg.go @@ -0,0 +1,24 @@ +package changeset + +import ( + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" +) + +// Separated changset because cap reg is an env var for CL nodes. +func CapRegChangeSet(env deployment.Environment, homeChainSel uint64) (deployment.ChangesetOutput, error) { + // Note we also deploy the cap reg. + ab := deployment.NewMemoryAddressBook() + _, err := ccipdeployment.DeployCapReg(env.Logger, ab, env.Chains[homeChainSel]) + if err != nil { + env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", ab) + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + JobSpecs: nil, + }, nil +} diff --git a/integration-tests/deployment/ccip/changeset/initial_deploy.go b/integration-tests/deployment/ccip/changeset/initial_deploy.go new file mode 100644 index 00000000000..52406487b97 --- /dev/null +++ b/integration-tests/deployment/ccip/changeset/initial_deploy.go @@ -0,0 +1,31 @@ +package changeset + +import ( + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + + ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" +) + +// We expect the change set input to be unique per change set. +// TODO: Maybe there's a generics approach here? +// Note if the change set is a deployment and it fails we have 2 options: +// - Just throw away the addresses, fix issue and try again (potentially expensive on mainnet) +func InitialDeployChangeSet(ab deployment.AddressBook, env deployment.Environment, c ccipdeployment.DeployCCIPContractConfig) (deployment.ChangesetOutput, error) { + err := ccipdeployment.DeployCCIPContracts(env, ab, c) + if err != nil { + env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "addresses", ab) + return deployment.ChangesetOutput{AddressBook: ab}, deployment.MaybeDataErr(err) + } + js, err := ccipdeployment.NewCCIPJobSpecs(env.NodeIDs, env.Offchain) + if err != nil { + return deployment.ChangesetOutput{AddressBook: ab}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + // Mapping of which nodes get which jobs. + JobSpecs: js, + }, nil +} diff --git a/integration-tests/deployment/ccip/changeset/initial_deploy_test.go b/integration-tests/deployment/ccip/changeset/initial_deploy_test.go new file mode 100644 index 00000000000..87406c33316 --- /dev/null +++ b/integration-tests/deployment/ccip/changeset/initial_deploy_test.go @@ -0,0 +1,106 @@ +package changeset + +import ( + "testing" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestInitialDeploy(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 3) + e := tenv.Env + + state, err := ccdeploy.LoadOnchainState(tenv.Env, tenv.Ab) + require.NoError(t, err) + require.NotNil(t, state.Chains[tenv.HomeChainSel].LinkToken) + + feeds := state.Chains[tenv.FeedChainSel].USDFeeds + tokenConfig := ccdeploy.NewTokenConfig() + tokenConfig.UpsertTokenInfo(ccdeploy.LinkSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[ccdeploy.LinkSymbol].Address().String(), + Decimals: ccdeploy.LinkDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + tokenConfig.UpsertTokenInfo(ccdeploy.WethSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[ccdeploy.WethSymbol].Address().String(), + Decimals: ccdeploy.WethDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + + output, err := InitialDeployChangeSet(tenv.Ab, tenv.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: tokenConfig, + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + CapabilityRegistry: state.Chains[tenv.HomeChainSel].CapabilityRegistry.Address(), + FeeTokenContracts: tenv.FeeTokenContracts, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + // Get new state after migration. + state, err = ccdeploy.LoadOnchainState(e, tenv.Ab) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + // 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[uint64]uint64) + + for src := range e.Chains { + for dest, destChain := range e.Chains { + if src == dest { + continue + } + latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + seqNum := ccdeploy.SendRequest(t, e, state, src, dest, false) + expectedSeqNum[dest] = seqNum + } + } + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + + // TODO: use proper assertions to check gas and token prices using events + + // Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) +} diff --git a/integration-tests/deployment/ccip/consts.go b/integration-tests/deployment/ccip/consts.go new file mode 100644 index 00000000000..e9b7a9f2cec --- /dev/null +++ b/integration-tests/deployment/ccip/consts.go @@ -0,0 +1,10 @@ +package ccipdeployment + +type TokenSymbol string + +const ( + LinkSymbol TokenSymbol = "LINK" + WethSymbol TokenSymbol = "WETH" + LinkDecimals = 18 + WethDecimals = 18 +) diff --git a/integration-tests/deployment/ccip/deploy.go b/integration-tests/deployment/ccip/deploy.go new file mode 100644 index 00000000000..6079b60b33d --- /dev/null +++ b/integration-tests/deployment/ccip/deploy.go @@ -0,0 +1,680 @@ +package ccipdeployment + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" + + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "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" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "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/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) + +var ( + RMNRemote deployment.ContractType = "RMNRemote" + LinkToken deployment.ContractType = "LinkToken" + ARMProxy deployment.ContractType = "ARMProxy" + WETH9 deployment.ContractType = "WETH9" + Router deployment.ContractType = "Router" + CommitStore deployment.ContractType = "CommitStore" + TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" + NonceManager deployment.ContractType = "NonceManager" + FeeQuoter deployment.ContractType = "FeeQuoter" + AdminManyChainMultisig deployment.ContractType = "AdminManyChainMultiSig" + BypasserManyChainMultisig deployment.ContractType = "BypasserManyChainMultiSig" + CancellerManyChainMultisig deployment.ContractType = "CancellerManyChainMultiSig" + ProposerManyChainMultisig deployment.ContractType = "ProposerManyChainMultiSig" + CCIPHome deployment.ContractType = "CCIPHome" + CCIPConfig deployment.ContractType = "CCIPConfig" + RMNHome deployment.ContractType = "RMNHome" + RBACTimelock deployment.ContractType = "RBACTimelock" + OnRamp deployment.ContractType = "OnRamp" + OffRamp deployment.ContractType = "OffRamp" + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" + PriceFeed deployment.ContractType = "PriceFeed" + // Note test router maps to a regular router contract. + TestRouter deployment.ContractType = "TestRouter" + CCIPReceiver deployment.ContractType = "CCIPReceiver" +) + +type Contracts interface { + *capabilities_registry.CapabilitiesRegistry | + *rmn_proxy_contract.RMNProxyContract | + *ccip_home.CCIPHome | + *rmn_home.RMNHome | + *nonce_manager.NonceManager | + *fee_quoter.FeeQuoter | + *router.Router | + *token_admin_registry.TokenAdminRegistry | + *weth9.WETH9 | + *rmn_remote.RMNRemote | + *owner_helpers.ManyChainMultiSig | + *owner_helpers.RBACTimelock | + *offramp.OffRamp | + *onramp.OnRamp | + *burn_mint_erc677.BurnMintERC677 | + *maybe_revert_message_receiver.MaybeRevertMessageReceiver | + *aggregator_v3_interface.AggregatorV3Interface +} + +type ContractDeploy[C Contracts] struct { + // We just keep all the deploy return values + // since some will be empty if there's an error. + Address common.Address + Contract C + Tx *types.Transaction + Tv deployment.TypeAndVersion + Err error +} + +// TODO: pull up to general deployment pkg somehow +// without exposing all product specific contracts? +func deployContract[C Contracts]( + lggr logger.Logger, + chain deployment.Chain, + addressBook deployment.AddressBook, + deploy func(chain deployment.Chain) ContractDeploy[C], +) (*ContractDeploy[C], error) { + contractDeploy := deploy(chain) + if contractDeploy.Err != nil { + lggr.Errorw("Failed to deploy contract", "err", contractDeploy.Err) + return nil, contractDeploy.Err + } + _, err := chain.Confirm(contractDeploy.Tx) + if err != nil { + lggr.Errorw("Failed to confirm deployment", "err", err) + return nil, err + } + err = addressBook.Save(chain.Selector, contractDeploy.Address.String(), contractDeploy.Tv) + if err != nil { + lggr.Errorw("Failed to save contract address", "err", err) + return nil, err + } + return &contractDeploy, nil +} + +type DeployCCIPContractConfig struct { + HomeChainSel uint64 + FeedChainSel uint64 + ChainsToDeploy []uint64 + TokenConfig TokenConfig + CapabilityRegistry common.Address + FeeTokenContracts map[uint64]FeeTokenContracts + // I believe it makes sense to have the same signers across all chains + // since that's the point MCMS. + MCMSConfig MCMSConfig + // For setting OCR configuration + OCRSecrets deployment.OCRSecrets +} + +// DeployCCIPContracts assumes that the capability registry and ccip home contracts +// are already deployed (needed as a first step because the chainlink nodes point to them). +// It then deploys +func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c DeployCCIPContractConfig) error { + if c.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 + } + capReg, err := capabilities_registry.NewCapabilitiesRegistry(c.CapabilityRegistry, e.Chains[c.HomeChainSel].Client) + if err != nil { + e.Logger.Errorw("Failed to get capability registry", "err", err) + return err + } + cr, err := capReg.GetHashedCapabilityId( + &bind.CallOpts{}, CapabilityLabelledName, CapabilityVersion) + if err != nil { + e.Logger.Errorw("Failed to get hashed capability id", "err", err) + return err + } + if cr != CCIPCapabilityID { + return fmt.Errorf("capability registry does not support CCIP %s %s", hexutil.Encode(cr[:]), hexutil.Encode(CCIPCapabilityID[:])) + } + capability, err := capReg.GetCapability(nil, CCIPCapabilityID) + if err != nil { + e.Logger.Errorw("Failed to get capability", "err", err) + return err + } + ccipHome, err := ccip_home.NewCCIPHome(capability.ConfigurationContract, e.Chains[c.HomeChainSel].Client) + if err != nil { + e.Logger.Errorw("Failed to get ccip config", "err", err) + return err + } + + // Signal to CR that our nodes support CCIP capability. + if err := AddNodes( + e.Logger, + capReg, + e.Chains[c.HomeChainSel], + nodes.NonBootstraps().PeerIDs(), + ); err != nil { + return err + } + + rmnHomeAddress, err := deployment.SearchAddressBook(ab, c.HomeChainSel, RMNHome) + if err != nil { + return fmt.Errorf("rmn home address not found: %w", err) + } + if !common.IsHexAddress(rmnHomeAddress) { + return fmt.Errorf("rmn home address %s is not a valid address", rmnHomeAddress) + } + + rmnHome, err := rmn_home.NewRMNHome(common.HexToAddress(rmnHomeAddress), e.Chains[c.HomeChainSel].Client) + if err != nil { + e.Logger.Errorw("Failed to get rmn home", "err", err) + return err + } + + for _, chainSel := range c.ChainsToDeploy { + chain, ok := e.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found", chainSel) + } + chainConfig, ok := c.FeeTokenContracts[chainSel] + if !ok { + return fmt.Errorf("chain %d config not found", chainSel) + } + err = DeployChainContracts(e, chain, ab, chainConfig, c.MCMSConfig, rmnHome) + if err != nil { + return err + } + chainAddresses, err := ab.AddressesForChain(chain.Selector) + if err != nil { + e.Logger.Errorw("Failed to get chain addresses", "err", err) + return err + } + chainState, err := LoadChainState(chain, chainAddresses) + if err != nil { + e.Logger.Errorw("Failed to load chain state", "err", err) + return err + } + + tokenInfo := c.TokenConfig.GetTokenInfo(e.Logger, c.FeeTokenContracts[chainSel].LinkToken, c.FeeTokenContracts[chainSel].Weth9) + // TODO: Do we want to extract this? + // Add chain config for each chain. + _, 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, + c.OCRSecrets, + capReg, + ccipHome, + common.HexToAddress(rmnHomeAddress), + chainState.OffRamp, + c.FeedChainSel, + tokenInfo, + chain, + e.Chains[c.HomeChainSel], + nodes.NonBootstraps(), + ); err != nil { + e.Logger.Errorw("Failed to add DON", "err", err) + return err + } + } + + return nil +} + +type MCMSConfig struct { + Admin config.Config + Canceller config.Config + Bypasser config.Config + Proposer config.Config + Executors []common.Address +} + +func DeployMCMSWithConfig( + contractType deployment.ContractType, + lggr logger.Logger, + chain deployment.Chain, + ab deployment.AddressBook, + mcmConfig config.Config, +) (*ContractDeploy[*owner_helpers.ManyChainMultiSig], error) { + groupQuorums, groupParents, signerAddresses, signerGroups := mcmConfig.ExtractSetConfigInputs() + mcm, err := deployContract(lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*owner_helpers.ManyChainMultiSig] { + mcmAddr, tx, mcm, err2 := owner_helpers.DeployManyChainMultiSig( + chain.DeployerKey, + chain.Client, + ) + return ContractDeploy[*owner_helpers.ManyChainMultiSig]{ + mcmAddr, mcm, tx, deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy mcm", "err", err) + return mcm, err + } + mcmsTx, err := mcm.Contract.SetConfig(chain.DeployerKey, + signerAddresses, + signerGroups, // Signer 1 is int group 0 (root group) with quorum 1. + groupQuorums, + groupParents, + false, + ) + if _, err := deployment.ConfirmIfNoError(chain, mcmsTx, err); err != nil { + lggr.Errorw("Failed to confirm mcm config", "err", err) + return mcm, err + } + return mcm, nil +} + +type MCMSContracts struct { + Admin *ContractDeploy[*owner_helpers.ManyChainMultiSig] + Canceller *ContractDeploy[*owner_helpers.ManyChainMultiSig] + Bypasser *ContractDeploy[*owner_helpers.ManyChainMultiSig] + Proposer *ContractDeploy[*owner_helpers.ManyChainMultiSig] + Timelock *ContractDeploy[*owner_helpers.RBACTimelock] +} + +// DeployMCMSContracts deploys the MCMS contracts for the given configuration +// as well as the timelock. +func DeployMCMSContracts( + lggr logger.Logger, + chain deployment.Chain, + ab deployment.AddressBook, + mcmConfig MCMSConfig, +) (*MCMSContracts, error) { + adminMCM, err := DeployMCMSWithConfig(AdminManyChainMultisig, lggr, chain, ab, mcmConfig.Admin) + if err != nil { + return nil, err + } + bypasser, err := DeployMCMSWithConfig(BypasserManyChainMultisig, lggr, chain, ab, mcmConfig.Bypasser) + if err != nil { + return nil, err + } + canceller, err := DeployMCMSWithConfig(CancellerManyChainMultisig, lggr, chain, ab, mcmConfig.Canceller) + if err != nil { + return nil, err + } + proposer, err := DeployMCMSWithConfig(ProposerManyChainMultisig, lggr, chain, ab, mcmConfig.Proposer) + if err != nil { + return nil, err + } + + timelock, err := deployContract(lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*owner_helpers.RBACTimelock] { + timelock, tx2, cc, err2 := owner_helpers.DeployRBACTimelock( + chain.DeployerKey, + chain.Client, + big.NewInt(0), // minDelay + adminMCM.Address, + []common.Address{proposer.Address}, // proposers + mcmConfig.Executors, //executors + []common.Address{canceller.Address}, // cancellers + []common.Address{bypasser.Address}, // bypassers + ) + return ContractDeploy[*owner_helpers.RBACTimelock]{ + timelock, cc, tx2, deployment.NewTypeAndVersion(RBACTimelock, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy timelock", "err", err) + return nil, err + } + lggr.Infow("deployed timelock", "addr", timelock.Address) + return &MCMSContracts{ + Admin: adminMCM, + Canceller: canceller, + Bypasser: bypasser, + Proposer: proposer, + Timelock: timelock, + }, nil +} + +func DeployFeeTokensToChains(lggr logger.Logger, ab deployment.AddressBook, chains map[uint64]deployment.Chain) (map[uint64]FeeTokenContracts, error) { + feeTokenContractsByChain := make(map[uint64]FeeTokenContracts) + for _, chain := range chains { + feeTokenContracts, err := DeployFeeTokens(lggr, chain, ab) + if err != nil { + return nil, err + } + feeTokenContractsByChain[chain.Selector] = feeTokenContracts + } + return feeTokenContractsByChain, nil +} + +// DeployFeeTokens deploys link and weth9. This is _usually_ for test environments only, +// real environments they tend to already exist, but sometimes we still have to deploy them to real chains. +func DeployFeeTokens(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) (FeeTokenContracts, error) { + weth9, err := deployContract(lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*weth9.WETH9] { + weth9Addr, tx2, weth9c, err2 := weth9.DeployWETH9( + chain.DeployerKey, + chain.Client, + ) + return ContractDeploy[*weth9.WETH9]{ + weth9Addr, weth9c, tx2, deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy weth9", "err", err) + return FeeTokenContracts{}, err + } + lggr.Infow("deployed weth9", "addr", weth9.Address) + + linkToken, err := deployContract(lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + linkTokenAddr, tx2, linkToken, err2 := burn_mint_erc677.DeployBurnMintERC677( + chain.DeployerKey, + chain.Client, + "Link Token", + "LINK", + uint8(18), + big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), + ) + return ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ + linkTokenAddr, linkToken, tx2, deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy linkToken", "err", err) + return FeeTokenContracts{}, err + } + lggr.Infow("deployed linkToken", "addr", linkToken.Address) + return FeeTokenContracts{ + LinkToken: linkToken.Contract, + Weth9: weth9.Contract, + }, nil +} + +type FeeTokenContracts struct { + LinkToken *burn_mint_erc677.BurnMintERC677 + Weth9 *weth9.WETH9 +} + +func DeployChainContracts( + e deployment.Environment, + chain deployment.Chain, + ab deployment.AddressBook, + contractConfig FeeTokenContracts, + mcmsConfig MCMSConfig, + rmnHome *rmn_home.RMNHome, +) error { + mcmsContracts, err := DeployMCMSContracts(e.Logger, chain, ab, mcmsConfig) + if err != nil { + return err + } + ccipReceiver, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { + receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( + chain.DeployerKey, + chain.Client, + false, + ) + return 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 + } + e.Logger.Infow("deployed receiver", "addr", ccipReceiver.Address) + + // TODO: Correctly configure RMN remote. + rmnRemote, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*rmn_remote.RMNRemote] { + rmnRemoteAddr, tx, rmnRemote, err2 := rmn_remote.DeployRMNRemote( + chain.DeployerKey, + chain.Client, + chain.Selector, + ) + return ContractDeploy[*rmn_remote.RMNRemote]{ + rmnRemoteAddr, rmnRemote, tx, deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy RMNRemote", "err", err) + return err + } + e.Logger.Infow("deployed RMNRemote", "addr", rmnRemote.Address) + + activeDigest, err := rmnHome.GetActiveDigest(&bind.CallOpts{}) + if err != nil { + e.Logger.Errorw("Failed to get active digest", "err", err) + return err + } + e.Logger.Infow("setting active home digest to rmn remote", "digest", activeDigest) + + tx, err := rmnRemote.Contract.SetConfig(chain.DeployerKey, rmn_remote.RMNRemoteConfig{ + RmnHomeContractConfigDigest: activeDigest, + Signers: []rmn_remote.RMNRemoteSigner{}, + MinSigners: 0, // TODO: update when we have signers + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to confirm RMNRemote config", "err", err) + return err + } + + rmnProxy, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { + rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( + chain.DeployerKey, + chain.Client, + rmnRemote.Address, + ) + return ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ + rmnProxyAddr, rmnProxy, tx2, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy rmnProxy", "err", err) + return err + } + e.Logger.Infow("deployed rmnProxy", "addr", rmnProxy.Address) + + routerContract, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*router.Router] { + routerAddr, tx2, routerC, err2 := router.DeployRouter( + chain.DeployerKey, + chain.Client, + contractConfig.Weth9.Address(), + rmnProxy.Address, + ) + return ContractDeploy[*router.Router]{ + routerAddr, routerC, tx2, deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy router", "err", err) + return err + } + e.Logger.Infow("deployed router", "addr", routerContract.Address) + + testRouterContract, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*router.Router] { + routerAddr, tx2, routerC, err2 := router.DeployRouter( + chain.DeployerKey, + chain.Client, + contractConfig.Weth9.Address(), + rmnProxy.Address, + ) + return ContractDeploy[*router.Router]{ + routerAddr, routerC, tx2, deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy test router", "err", err) + return err + } + e.Logger.Infow("deployed test router", "addr", testRouterContract.Address) + + tokenAdminRegistry, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*token_admin_registry.TokenAdminRegistry] { + tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( + chain.DeployerKey, + chain.Client) + return ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ + tokenAdminRegistryAddr, tokenAdminRegistry, tx2, deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy token admin registry", "err", err) + return err + } + e.Logger.Infow("deployed tokenAdminRegistry", "addr", tokenAdminRegistry) + + nonceManager, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*nonce_manager.NonceManager] { + nonceManagerAddr, tx2, nonceManager, err2 := nonce_manager.DeployNonceManager( + chain.DeployerKey, + chain.Client, + []common.Address{}, // Need to add onRamp after + ) + return ContractDeploy[*nonce_manager.NonceManager]{ + nonceManagerAddr, nonceManager, tx2, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy nonce manager", "err", err) + return err + } + e.Logger.Infow("Deployed nonce manager", "addr", nonceManager.Address) + + feeQuoter, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*fee_quoter.FeeQuoter] { + prAddr, tx2, pr, err2 := fee_quoter.DeployFeeQuoter( + chain.DeployerKey, + chain.Client, + fee_quoter.FeeQuoterStaticConfig{ + MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), + LinkToken: contractConfig.LinkToken.Address(), + TokenPriceStalenessThreshold: uint32(24 * 60 * 60), + }, + []common.Address{mcmsContracts.Timelock.Address}, // timelock should be able to update, ramps added after + []common.Address{contractConfig.Weth9.Address(), contractConfig.LinkToken.Address()}, // fee tokens + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ + { + PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH + Token: contractConfig.LinkToken.Address(), + }, + { + PremiumMultiplierWeiPerEth: 1e18, + Token: contractConfig.Weth9.Address(), + }, + }, + []fee_quoter.FeeQuoterDestChainConfigArgs{}, + ) + return ContractDeploy[*fee_quoter.FeeQuoter]{ + prAddr, pr, tx2, deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy fee quoter", "err", err) + return err + } + e.Logger.Infow("Deployed fee quoter", "addr", feeQuoter.Address) + + onRamp, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*onramp.OnRamp] { + onRampAddr, tx2, onRamp, err2 := onramp.DeployOnRamp( + chain.DeployerKey, + chain.Client, + onramp.OnRampStaticConfig{ + ChainSelector: chain.Selector, + RmnRemote: rmnProxy.Address, + NonceManager: nonceManager.Address, + TokenAdminRegistry: tokenAdminRegistry.Address, + }, + onramp.OnRampDynamicConfig{ + FeeQuoter: feeQuoter.Address, + FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator + }, + []onramp.OnRampDestChainConfigArgs{}, + ) + return ContractDeploy[*onramp.OnRamp]{ + onRampAddr, onRamp, tx2, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy onramp", "err", err) + return err + } + e.Logger.Infow("Deployed onramp", "addr", onRamp.Address) + + offRamp, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*offramp.OffRamp] { + offRampAddr, tx2, offRamp, err2 := offramp.DeployOffRamp( + chain.DeployerKey, + chain.Client, + offramp.OffRampStaticConfig{ + ChainSelector: chain.Selector, + RmnRemote: rmnProxy.Address, + NonceManager: nonceManager.Address, + TokenAdminRegistry: tokenAdminRegistry.Address, + }, + offramp.OffRampDynamicConfig{ + FeeQuoter: feeQuoter.Address, + PermissionLessExecutionThresholdSeconds: uint32(86400), + }, + []offramp.OffRampSourceChainConfigArgs{}, + ) + return ContractDeploy[*offramp.OffRamp]{ + offRampAddr, offRamp, tx2, deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy offramp", "err", err) + return err + } + e.Logger.Infow("Deployed offramp", "addr", offRamp.Address) + + // Basic wiring is always needed. + tx, err = feeQuoter.Contract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ + // TODO: We enable the deployer initially to set prices + // Should be removed after. + AddedCallers: []common.Address{offRamp.Contract.Address(), chain.DeployerKey.From}, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "err", err) + return err + } + + tx, err = nonceManager.Contract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ + AddedCallers: []common.Address{offRamp.Contract.Address(), onRamp.Contract.Address()}, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to update nonce manager with ramps", "err", err) + return err + } + return nil +} diff --git a/integration-tests/deployment/ccip/deploy_home_chain.go b/integration-tests/deployment/ccip/deploy_home_chain.go new file mode 100644 index 00000000000..2aa893458f5 --- /dev/null +++ b/integration-tests/deployment/ccip/deploy_home_chain.go @@ -0,0 +1,1079 @@ +package ccipdeployment + +import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + "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" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + + confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "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/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +const ( + NodeOperatorID = 1 + CapabilityLabelledName = "ccip" + CapabilityVersion = "v1.0.0" + + FirstBlockAge = 8 * time.Hour + RemoteGasPriceBatchWriteFrequency = 30 * time.Minute + TokenPriceBatchWriteFrequency = 30 * time.Minute + BatchGasLimit = 6_500_000 + RelativeBoostPerWaitHour = 1.5 + InflightCacheExpiry = 10 * time.Minute + RootSnoozeTime = 30 * time.Minute + BatchingStrategyID = 0 + DeltaProgress = 30 * time.Second + DeltaResend = 10 * time.Second + DeltaInitial = 20 * time.Second + DeltaRound = 2 * time.Second + DeltaGrace = 2 * time.Second + DeltaCertifiedCommitRequest = 10 * time.Second + DeltaStage = 10 * time.Second + Rmax = 3 + MaxDurationQuery = 50 * time.Millisecond + MaxDurationObservation = 5 * time.Second + MaxDurationShouldAcceptAttestedReport = 10 * time.Second + MaxDurationShouldTransmitAcceptedReport = 10 * time.Second +) + +var ( + CCIPCapabilityID = utils.Keccak256Fixed(MustABIEncode(`[{"type": "string"}, {"type": "string"}]`, CapabilityLabelledName, CapabilityVersion)) + CCIPHomeABI *abi.ABI +) + +func init() { + var err error + CCIPHomeABI, err = ccip_home.CCIPHomeMetaData.GetAbi() + if err != nil { + panic(err) + } +} + +func MustABIEncode(abiString string, args ...interface{}) []byte { + encoded, err := utils.ABIEncode(abiString, args...) + if err != nil { + panic(err) + } + return encoded +} + +func DeployCapReg(lggr logger.Logger, ab deployment.AddressBook, chain deployment.Chain) (*ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + capReg, err := deployContract(lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( + chain.DeployerKey, + chain.Client, + ) + return ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy capreg", "err", err) + return nil, err + } + + lggr.Infow("deployed capreg", "addr", capReg.Address) + ccipHome, err := deployContract( + lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*ccip_home.CCIPHome] { + ccAddr, tx, cc, err2 := ccip_home.DeployCCIPHome( + chain.DeployerKey, + chain.Client, + capReg.Address, + ) + return ContractDeploy[*ccip_home.CCIPHome]{ + Address: ccAddr, Tv: deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: cc, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy CCIPHome", "err", err) + return nil, err + } + lggr.Infow("deployed CCIPHome", "addr", ccipHome.Address) + + rmnHome, err := deployContract( + lggr, chain, ab, + func(chain deployment.Chain) ContractDeploy[*rmn_home.RMNHome] { + rmnAddr, tx, rmn, err2 := rmn_home.DeployRMNHome( + chain.DeployerKey, + chain.Client, + ) + return ContractDeploy[*rmn_home.RMNHome]{ + Address: rmnAddr, Tv: deployment.NewTypeAndVersion(RMNHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: rmn, + } + }, + ) + if err != nil { + lggr.Errorw("Failed to deploy RMNHome", "err", err) + return nil, err + } + lggr.Infow("deployed RMNHome", "addr", rmnHome.Address) + + // TODO: properly configure RMNHome + tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmn_home.RMNHomeStaticConfig{ + Nodes: []rmn_home.RMNHomeNode{}, + OffchainConfig: []byte("static config"), + }, rmn_home.RMNHomeDynamicConfig{ + SourceChains: []rmn_home.RMNHomeSourceChain{}, + OffchainConfig: []byte("dynamic config"), + }, [32]byte{}) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to set candidate on RMNHome", "err", err) + return nil, err + } + + rmnCandidateDigest, err := rmnHome.Contract.GetCandidateDigest(nil) + if err != nil { + lggr.Errorw("Failed to get RMNHome candidate digest", "err", err) + return nil, err + } + + tx, err = rmnHome.Contract.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "err", err) + return nil, err + } + + rmnActiveDigest, err := rmnHome.Contract.GetActiveDigest(nil) + if err != nil { + lggr.Errorw("Failed to get RMNHome active digest", "err", err) + return nil, err + } + lggr.Infow("Got rmn home active digest", "digest", rmnActiveDigest) + + if rmnActiveDigest != rmnCandidateDigest { + lggr.Errorw("RMNHome active digest does not match previously candidate digest", + "active", rmnActiveDigest, "candidate", rmnCandidateDigest) + return nil, errors.New("RMNHome active digest does not match candidate digest") + } + + tx, err = capReg.Contract.AddCapabilities(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ + { + LabelledName: CapabilityLabelledName, + Version: CapabilityVersion, + CapabilityType: 2, // consensus. not used (?) + ResponseType: 0, // report. not used (?) + ConfigurationContract: ccipHome.Address, + }, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to add capabilities", "err", err) + return nil, err + } + // TODO: Just one for testing. + tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeOperator{ + { + Admin: chain.DeployerKey.From, + Name: "NodeOperator", + }, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to add node operators", "err", err) + return nil, err + } + return capReg, nil +} + +func AddNodes( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + chain deployment.Chain, + p2pIDs [][32]byte, +) error { + var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams + for _, p2pID := range p2pIDs { + // if any p2pIDs are empty throw error + if bytes.Equal(p2pID[:], make([]byte, 32)) { + return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) + } + nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: NodeOperatorID, + Signer: p2pID, // Not used in tests + P2pId: p2pID, + EncryptionPublicKey: p2pID, // Not used in tests + HashedCapabilityIds: [][32]byte{CCIPCapabilityID}, + } + nodeParams = append(nodeParams, nodeParam) + } + tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) + if err != nil { + lggr.Errorw("Failed to add nodes", "err", deployment.MaybeDataErr(err)) + return err + } + _, err = chain.Confirm(tx) + return err +} + +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 AddChainConfig( + lggr logger.Logger, + h deployment.Chain, + ccipConfig *ccip_home.CCIPHome, + chainSelector uint64, + p2pIDs [][32]byte, +) (ccip_home.CCIPHomeChainConfigArgs, error) { + // First Add ChainConfig 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) + 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", "chainConfig", chainConfig) + return chainConfig, nil +} + +func BuildOCR3ConfigForCCIPHome( + lggr logger.Logger, + ocrSecrets deployment.OCRSecrets, + offRamp *offramp.OffRamp, + dest deployment.Chain, + feedChainSel uint64, + // Token address on Dest chain to aggregate address on feed chain + tokenInfo map[ocrtypes.Account]pluginconfig.TokenInfo, + nodes deployment.Nodes, + rmnHomeAddress common.Address, +) (map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, error) { + p2pIDs := nodes.PeerIDs() + // Get OCR3 Config from helper + var schedule []int + var oracles []confighelper2.OracleIdentityExtra + for _, node := range nodes { + schedule = append(schedule, 1) + cfg := node.SelToOCRConfig[dest.Selector] + oracles = append(oracles, confighelper2.OracleIdentityExtra{ + OracleIdentity: confighelper2.OracleIdentity{ + OnchainPublicKey: cfg.OnchainPublicKey, + TransmitAccount: cfg.TransmitAccount, + OffchainPublicKey: cfg.OffchainPublicKey, + PeerID: cfg.PeerID.String()[4:], + }, ConfigEncryptionPublicKey: cfg.ConfigEncryptionPublicKey, + }) + } + + // Add DON on capability registry contract + ocr3Configs := make(map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config) + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + var encodedOffchainConfig []byte + var err2 error + if pluginType == cctypes.PluginTypeCCIPCommit { + encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ + RemoteGasPriceBatchWriteFrequency: *commonconfig.MustNewDuration(RemoteGasPriceBatchWriteFrequency), + TokenPriceBatchWriteFrequency: *commonconfig.MustNewDuration(TokenPriceBatchWriteFrequency), + PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), + TokenInfo: tokenInfo, + NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, + MaxReportTransmissionCheckAttempts: 5, + MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, + SignObservationPrefix: "chainlink ccip 1.6 rmn observation", + }) + } else { + encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ + BatchGasLimit: BatchGasLimit, + RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, + MessageVisibilityInterval: *commonconfig.MustNewDuration(FirstBlockAge), + InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry), + RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime), + BatchingStrategyID: BatchingStrategyID, + }) + } + if err2 != nil { + return nil, err2 + } + signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsDeterministic( + ocrSecrets.EphemeralSk, + ocrSecrets.SharedSecret, + DeltaProgress, + DeltaResend, + DeltaInitial, + DeltaRound, + DeltaGrace, + DeltaCertifiedCommitRequest, + DeltaStage, + Rmax, + schedule, + oracles, + encodedOffchainConfig, + nil, // maxDurationInitialization + MaxDurationQuery, + MaxDurationObservation, + MaxDurationShouldAcceptAttestedReport, + MaxDurationShouldTransmitAcceptedReport, + int(nodes.DefaultF()), + []byte{}, // empty OnChainConfig + ) + if err2 != nil { + return nil, err2 + } + + signersBytes := make([][]byte, len(signers)) + for i, signer := range signers { + signersBytes[i] = signer + } + + transmittersBytes := make([][]byte, len(transmitters)) + for i, transmitter := range transmitters { + parsed, err2 := common.ParseHexOrString(string(transmitter)) + if err2 != nil { + return nil, err2 + } + transmittersBytes[i] = parsed + } + + var ocrNodes []ccip_home.CCIPHomeOCR3Node + for i := range nodes { + ocrNodes = append(ocrNodes, ccip_home.CCIPHomeOCR3Node{ + P2pId: p2pIDs[i], + SignerKey: signersBytes[i], + TransmitterKey: transmittersBytes[i], + }) + } + + _, ok := ocr3Configs[pluginType] + if ok { + return nil, fmt.Errorf("pluginType %s already exists in ocr3Configs", pluginType.String()) + } + + ocr3Configs[pluginType] = ccip_home.CCIPHomeOCR3Config{ + PluginType: uint8(pluginType), + ChainSelector: dest.Selector, + FRoleDON: configF, + OffchainConfigVersion: offchainConfigVersion, + OfframpAddress: offRamp.Address().Bytes(), + Nodes: ocrNodes, + OffchainConfig: offchainConfig, + RmnHomeAddress: rmnHomeAddress.Bytes(), + } + } + + return ocr3Configs, nil +} + +func LatestCCIPDON(registry *capabilities_registry.CapabilitiesRegistry) (*capabilities_registry.CapabilitiesRegistryDONInfo, error) { + dons, err := registry.GetDONs(nil) + if err != nil { + return nil, err + } + var ccipDON capabilities_registry.CapabilitiesRegistryDONInfo + for _, don := range dons { + if len(don.CapabilityConfigurations) == 1 && + don.CapabilityConfigurations[0].CapabilityId == CCIPCapabilityID && + don.Id > ccipDON.Id { + ccipDON = don + } + } + return &ccipDON, nil +} + +// DonIDForChain returns the DON ID for the chain with the given selector +// It looks up with the CCIPHome contract to find the OCR3 configs for the DONs, and returns the DON ID for the chain matching with the given selector from the OCR3 configs +func DonIDForChain(registry *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, chainSelector uint64) (uint32, error) { + dons, err := registry.GetDONs(nil) + if err != nil { + return 0, err + } + for _, don := range dons { + if len(don.CapabilityConfigurations) == 1 && + don.CapabilityConfigurations[0].CapabilityId == CCIPCapabilityID { + configs, err := ccipHome.GetAllConfigs(nil, don.Id, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return 0, err + } + if configs.ActiveConfig.Config.ChainSelector == chainSelector || configs.CandidateConfig.Config.ChainSelector == chainSelector { + return don.Id, nil + } + } + } + return 0, fmt.Errorf("no DON found for chain %d", chainSelector) +} + +func BuildSetOCR3ConfigArgs( + donID uint32, + ccipHome *ccip_home.CCIPHome, + destSelector uint64, +) ([]offramp.MultiOCR3BaseOCRConfigArgs, error) { + var offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + ocrConfig, err2 := ccipHome.GetAllConfigs(&bind.CallOpts{ + Context: context.Background(), + }, donID, uint8(pluginType)) + if err2 != nil { + return nil, err2 + } + + fmt.Printf("pluginType: %s, destSelector: %d, donID: %d, activeConfig digest: %x, candidateConfig digest: %x\n", + pluginType.String(), destSelector, donID, ocrConfig.ActiveConfig.ConfigDigest, ocrConfig.CandidateConfig.ConfigDigest) + + // 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) + } + + activeConfig := ocrConfig.ActiveConfig + var signerAddresses []common.Address + var transmitterAddresses []common.Address + for _, node := range activeConfig.Config.Nodes { + signerAddresses = append(signerAddresses, common.BytesToAddress(node.SignerKey)) + transmitterAddresses = append(transmitterAddresses, common.BytesToAddress(node.TransmitterKey)) + } + + offrampOCR3Configs = append(offrampOCR3Configs, offramp.MultiOCR3BaseOCRConfigArgs{ + ConfigDigest: activeConfig.ConfigDigest, + OcrPluginType: uint8(pluginType), + F: activeConfig.Config.FRoleDON, + IsSignatureVerificationEnabled: pluginType == cctypes.PluginTypeCCIPCommit, + Signers: signerAddresses, + Transmitters: transmitterAddresses, + }) + } + return offrampOCR3Configs, 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 { + 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 := LatestCCIPDON(capReg) + if err != nil { + return err + } + + donID := latestDon.Id + 1 + + err = setupCommitDON(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 = setupExecDON(donID, execConfig, capReg, home, nodes, ccipHome) + if err != nil { + return fmt.Errorf("setup exec don: %w", err) + } + return ValidateCCIPHomeConfigSetUp(capReg, ccipHome, newChainSel) +} + +func setupExecDON( + 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) + } + + 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") + } + + // 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") + } + // 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(cctypes.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(cctypes.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("get all exec configs 2nd time: %w", err) + } + + // print the above info + fmt.Printf("completed exec DON creation and promotion: donID: %d execCandidateDigest: %x, execActiveDigest: %x, execCandidateDigestFromGetAllConfigs: %x, execActiveDigestFromGetAllConfigs: %x\n", + donID, execCandidateDigest, execActiveDigest, execConfigs.CandidateConfig.ConfigDigest, execConfigs.ActiveConfig.ConfigDigest) + + return nil +} + +// SetCandidateExecPluginOps calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract +// This proposes to set up OCR3 config for the exec plugin for the DON +func SetCandidateExecPluginOps( + execConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSelector uint64, + nodes deployment.Nodes, +) ([]mcms.Operation, error) { + // fetch DON ID for the chain + donID, err := DonIDForChain(capReg, ccipHome, chainSelector) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + encodedSetCandidateCall, err := CCIPHomeABI.Pack( + "setCandidate", + donID, + execConfig.PluginType, + execConfig, + [32]byte{}, + ) + if err != nil { + return nil, fmt.Errorf("pack set candidate call: %w", err) + } + + // set candidate call + updateDonTx, err := capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return nil, fmt.Errorf("update don w/ exec config: %w", err) + } + + return []mcms.Operation{{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }}, nil +} + +// SetCandidateCommitPluginWithAddDonOps sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract +// This should be done first before calling any other UpdateDON calls +// This proposes to set up OCR3 config for the commit plugin for the DON +func SetCandidateCommitPluginWithAddDonOps( + donID uint32, + commitConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + nodes deployment.Nodes, +) (mcms.Operation, error) { + encodedSetCandidateCall, err := CCIPHomeABI.Pack( + "setCandidate", + donID, + commitConfig.PluginType, + commitConfig, + [32]byte{}, + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err) + } + addDonTx, err := capReg.AddDON(deployment.SimTransactOpts(), nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, false, false, nodes.DefaultF()) + if err != nil { + return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err) + } + return mcms.Operation{ + To: capReg.Address(), + Data: addDonTx.Data(), + Value: big.NewInt(0), + }, nil +} + +// PromoteCandidateOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract +func PromoteCandidateOps( + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSelector uint64, + nodes deployment.Nodes, +) ([]mcms.Operation, error) { + // fetch DON ID for the chain + donID, err := DonIDForChain(capReg, ccipHome, chainSelector) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + + mcmsOps := []mcms.Operation{} + + commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return nil, fmt.Errorf("get commit candidate digest: %w", err) + } + + if commitCandidateDigest == [32]byte{} { + return nil, fmt.Errorf("candidate digest is empty, expected nonempty") + } + fmt.Printf("commit candidate digest after setCandidate: %x\n", commitCandidateDigest) + + encodedPromotionCall, err := CCIPHomeABI.Pack( + "promoteCandidateAndRevokeActive", + donID, + uint8(cctypes.PluginTypeCCIPCommit), + commitCandidateDigest, + [32]byte{}, + ) + if err != nil { + return nil, fmt.Errorf("pack promotion call: %w", err) + } + + updateDonTx, err := capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return nil, fmt.Errorf("update don w/ commit config: %w", err) + } + mcmsOps = append(mcmsOps, mcms.Operation{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }) + + // check that candidate digest is empty. + execCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + if err != nil { + return nil, fmt.Errorf("get exec candidate digest 1st time: %w", err) + } + + if execCandidateDigest == [32]byte{} { + return nil, fmt.Errorf("candidate digest is empty, expected nonempty") + } + + // promote candidate call + encodedPromotionCall, err = CCIPHomeABI.Pack( + "promoteCandidateAndRevokeActive", + donID, + uint8(cctypes.PluginTypeCCIPExec), + execCandidateDigest, + [32]byte{}, + ) + if err != nil { + return nil, fmt.Errorf("pack promotion call: %w", err) + } + + updateDonTx, err = capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return nil, fmt.Errorf("update don w/ exec config: %w", err) + } + mcmsOps = append(mcmsOps, mcms.Operation{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }) + return mcmsOps, nil +} + +// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly +func ValidateCCIPHomeConfigSetUp( + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSel uint64, +) error { + // fetch DONID + donID, err := DonIDForChain(capReg, ccipHome, chainSel) + if err != nil { + return fmt.Errorf("fetch don id for chain: %w", err) + } + // 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) + } + commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get commit candidate digest: %w", err) + } + 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) + } + 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 +} + +func setupCommitDON( + 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) + } + + 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") + } + fmt.Printf("commit candidate digest after setCandidate: %x\n", 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) + } + + // 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(cctypes.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(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get all commit configs 2nd time: %w", err) + } + + // print the above information + fmt.Printf("completed commit DON creation and promotion: donID: %d, commitCandidateDigest: %x, commitActiveDigest: %x, commitCandidateDigestFromGetAllConfigs: %x, commitActiveDigestFromGetAllConfigs: %x\n", + donID, commitCandidateDigest, commitActiveDigest, commitConfigs.CandidateConfig.ConfigDigest, commitConfigs.ActiveConfig.ConfigDigest) + + return nil +} + +func AddDON( + lggr logger.Logger, + ocrSecrets deployment.OCRSecrets, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + rmnHomeAddress common.Address, + offRamp *offramp.OffRamp, + feedChainSel uint64, + // Token address on Dest chain to aggregate address on feed chain + tokenInfo map[ocrtypes.Account]pluginconfig.TokenInfo, + dest deployment.Chain, + home deployment.Chain, + nodes deployment.Nodes, +) error { + ocrConfigs, err := BuildOCR3ConfigForCCIPHome(lggr, ocrSecrets, offRamp, dest, feedChainSel, tokenInfo, nodes, rmnHomeAddress) + if err != nil { + return err + } + err = CreateDON(lggr, capReg, ccipHome, ocrConfigs, home, dest.Selector, nodes) + if err != nil { + return err + } + don, err := LatestCCIPDON(capReg) + if err != nil { + return err + } + lggr.Infow("Added DON", "donID", don.Id) + + offrampOCR3Configs, err := 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, + ) + + tx, err := offRamp.SetOCR3Configs(dest.DeployerKey, offrampOCR3Configs) + if _, err := deployment.ConfirmIfNoError(dest, tx, err); err != nil { + return err + } + + 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 err + } + // TODO: assertions to be done as part of full state + // resprentation validation CCIP-3047 + if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { + return fmt.Errorf("%s OCR3 config digest mismatch", pluginType.String()) + } + if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { + return fmt.Errorf("%s OCR3 config F mismatch", pluginType.String()) + } + if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { + return fmt.Errorf("%s OCR3 config signature verification mismatch", pluginType.String()) + } + 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()) { + return fmt.Errorf("%s OCR3 config signer mismatch", pluginType.String()) + } + } + } + for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { + if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { + return fmt.Errorf("%s OCR3 config transmitter mismatch", pluginType.String()) + } + } + } + + return nil +} diff --git a/integration-tests/deployment/ccip/deploy_test.go b/integration-tests/deployment/ccip/deploy_test.go new file mode 100644 index 00000000000..3742442433e --- /dev/null +++ b/integration-tests/deployment/ccip/deploy_test.go @@ -0,0 +1,71 @@ +package ccipdeployment + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeployCCIPContracts(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Bootstraps: 1, + Chains: 2, + Nodes: 4, + }) + // Deploy all the CCIP contracts. + ab := deployment.NewMemoryAddressBook() + homeChainSel, feedChainSel := allocateCCIPChainSelectors(e.Chains) + feeTokenContracts, _ := DeployTestContracts(t, lggr, ab, homeChainSel, feedChainSel, e.Chains) + + // Load the state after deploying the cap reg and feeds. + s, err := LoadOnchainState(e, ab) + require.NoError(t, err) + require.NotNil(t, s.Chains[homeChainSel].CapabilityRegistry) + require.NotNil(t, s.Chains[homeChainSel].CCIPHome) + require.NotNil(t, s.Chains[feedChainSel].USDFeeds) + + err = DeployCCIPContracts(e, ab, DeployCCIPContractConfig{ + HomeChainSel: homeChainSel, + FeedChainSel: feedChainSel, + ChainsToDeploy: e.AllChainSelectors(), + TokenConfig: NewTokenConfig(), + CapabilityRegistry: s.Chains[homeChainSel].CapabilityRegistry.Address(), + FeeTokenContracts: feeTokenContracts, + MCMSConfig: NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + state, err := LoadOnchainState(e, ab) + require.NoError(t, err) + snap, err := state.View(e.AllChainSelectors()) + require.NoError(t, err) + + // Assert expect every deployed address to be in the address book. + // TODO (CCIP-3047): Add the rest of CCIPv2 representation + b, err := json.MarshalIndent(snap, "", " ") + require.NoError(t, err) + fmt.Println(string(b)) +} + +func TestJobSpecGeneration(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 1, + }) + js, err := NewCCIPJobSpecs(e.NodeIDs, e.Offchain) + require.NoError(t, err) + for node, jb := range js { + fmt.Println(node, jb) + } + // TODO: Add job assertions +} diff --git a/integration-tests/deployment/ccip/jobs.go b/integration-tests/deployment/ccip/jobs.go new file mode 100644 index 00000000000..49fb1e95422 --- /dev/null +++ b/integration-tests/deployment/ccip/jobs.go @@ -0,0 +1,57 @@ +package ccipdeployment + +import ( + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" +) + +// In our case, the only address needed is the cap registry which is actually an env var. +// and will pre-exist for our deployment. So the job specs only depend on the environment operators. +func NewCCIPJobSpecs(nodeIds []string, oc deployment.OffchainClient) (map[string][]string, error) { + nodes, err := deployment.NodeInfo(nodeIds, oc) + if err != nil { + return nil, err + } + // Generate a set of brand new job specs for CCIP for a specific environment + // (including NOPs) and new addresses. + // We want to assign one CCIP capability job to each node. And node with + // an addr we'll list as bootstrapper. + // Find the bootstrap nodes + + nodesToJobSpecs := make(map[string][]string) + for _, node := range nodes { + var spec string + var err error + if !node.IsBootstrap { + spec, err = validate.NewCCIPSpecToml(validate.SpecArgs{ + P2PV2Bootstrappers: nodes.BootstrapLocators(), + CapabilityVersion: CapabilityVersion, + CapabilityLabelledName: CapabilityLabelledName, + OCRKeyBundleIDs: map[string]string{ + // TODO: Validate that that all EVM chains are using the same keybundle. + relay.NetworkEVM: node.FirstOCRKeybundle().KeyBundleID, + }, + P2PKeyID: node.PeerID.String(), + RelayConfigs: nil, + PluginConfig: map[string]any{}, + }) + } else { + spec, err = validate.NewCCIPSpecToml(validate.SpecArgs{ + P2PV2Bootstrappers: []string{}, // Intentionally empty for bootstraps. + CapabilityVersion: CapabilityVersion, + CapabilityLabelledName: CapabilityLabelledName, + OCRKeyBundleIDs: map[string]string{}, + // TODO: validate that all EVM chains are using the same keybundle + P2PKeyID: node.PeerID.String(), + RelayConfigs: nil, + PluginConfig: map[string]any{}, + }) + } + if err != nil { + return nil, err + } + nodesToJobSpecs[node.NodeID] = append(nodesToJobSpecs[node.NodeID], spec) + } + return nodesToJobSpecs, nil +} diff --git a/integration-tests/deployment/ccip/propose.go b/integration-tests/deployment/ccip/propose.go new file mode 100644 index 00000000000..33d073c5e67 --- /dev/null +++ b/integration-tests/deployment/ccip/propose.go @@ -0,0 +1,239 @@ +package ccipdeployment + +import ( + "bytes" + "context" + "crypto/ecdsa" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" + owner_helpers "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" + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" +) + +var ( + TestXXXMCMSSigner *ecdsa.PrivateKey +) + +func init() { + key, err := crypto.GenerateKey() + if err != nil { + panic(err) + } + TestXXXMCMSSigner = key +} + +func SingleGroupMCMS(t *testing.T) config.Config { + publicKey := TestXXXMCMSSigner.Public().(*ecdsa.PublicKey) + // Convert the public key to an Ethereum address + address := crypto.PubkeyToAddress(*publicKey) + c, err := config.NewConfig(1, []common.Address{address}, []config.Config{}) + require.NoError(t, err) + return *c +} + +func NewTestMCMSConfig(t *testing.T, e deployment.Environment) MCMSConfig { + c := SingleGroupMCMS(t) + // All deployer keys can execute. + var executors []common.Address + for _, chain := range e.Chains { + executors = append(executors, chain.DeployerKey.From) + } + return MCMSConfig{ + Admin: c, + Bypasser: c, + Canceller: c, + Executors: executors, + Proposer: c, + } +} + +func SignProposal(t *testing.T, env deployment.Environment, proposal *timelock.MCMSWithTimelockProposal) *mcms.Executor { + executorClients := make(map[mcms.ChainIdentifier]mcms.ContractDeployBackend) + for _, chain := range env.Chains { + chainselc, exists := chainsel.ChainBySelector(chain.Selector) + require.True(t, exists) + chainSel := mcms.ChainIdentifier(chainselc.Selector) + executorClients[chainSel] = chain.Client + } + executor, err := proposal.ToExecutor(true) + require.NoError(t, err) + payload, err := executor.SigningHash() + require.NoError(t, err) + // Sign the payload + sig, err := crypto.Sign(payload.Bytes(), TestXXXMCMSSigner) + require.NoError(t, err) + mcmSig, err := mcms.NewSignatureFromBytes(sig) + require.NoError(t, err) + executor.Proposal.AddSignature(mcmSig) + require.NoError(t, executor.Proposal.Validate()) + return executor +} + +func ExecuteProposal(t *testing.T, env deployment.Environment, executor *mcms.Executor, + state CCIPOnChainState, sel uint64) { + t.Log("Executing proposal on chain", sel) + // Set the root. + tx, err2 := executor.SetRootOnChain(env.Chains[sel].Client, env.Chains[sel].DeployerKey, mcms.ChainIdentifier(sel)) + require.NoError(t, err2) + _, err2 = env.Chains[sel].Confirm(tx) + require.NoError(t, err2) + + // TODO: This sort of helper probably should move to the MCMS lib. + // Execute all the transactions in the proposal which are for this chain. + for _, chainOp := range executor.Operations[mcms.ChainIdentifier(sel)] { + for idx, op := range executor.ChainAgnosticOps { + if bytes.Equal(op.Data, chainOp.Data) && op.To == chainOp.To { + opTx, err3 := executor.ExecuteOnChain(env.Chains[sel].Client, env.Chains[sel].DeployerKey, idx) + require.NoError(t, err3) + block, err3 := env.Chains[sel].Confirm(opTx) + require.NoError(t, err3) + t.Log("executed", chainOp) + it, err3 := state.Chains[sel].Timelock.FilterCallScheduled(&bind.FilterOpts{ + Start: block, + End: &block, + Context: context.Background(), + }, nil, nil) + require.NoError(t, err3) + var calls []owner_helpers.RBACTimelockCall + var pred, salt [32]byte + for it.Next() { + // Note these are the same for the whole batch, can overwrite + pred = it.Event.Predecessor + salt = it.Event.Salt + t.Log("scheduled", it.Event) + calls = append(calls, owner_helpers.RBACTimelockCall{ + Target: it.Event.Target, + Data: it.Event.Data, + Value: it.Event.Value, + }) + } + tx, err := state.Chains[sel].Timelock.ExecuteBatch( + env.Chains[sel].DeployerKey, calls, pred, salt) + require.NoError(t, err) + _, err = env.Chains[sel].Confirm(tx) + require.NoError(t, err) + } + } + } +} + +func GenerateAcceptOwnershipProposal( + state CCIPOnChainState, + homeChain uint64, + chains []uint64, +) (*timelock.MCMSWithTimelockProposal, error) { + // TODO: Accept rest of contracts + var batches []timelock.BatchChainOperation + metaDataPerChain := make(map[mcms.ChainIdentifier]mcms.ChainMetadata) + timelockAddresses := make(map[mcms.ChainIdentifier]common.Address) + for _, sel := range chains { + chain, _ := chainsel.ChainBySelector(sel) + acceptOnRamp, err := state.Chains[sel].OnRamp.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + acceptFeeQuoter, err := state.Chains[sel].FeeQuoter.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + chainSel := mcms.ChainIdentifier(chain.Selector) + opCount, err := state.Chains[sel].ProposerMcm.GetOpCount(nil) + if err != nil { + return nil, err + } + metaDataPerChain[chainSel] = mcms.ChainMetadata{ + MCMAddress: state.Chains[sel].ProposerMcm.Address(), + StartingOpCount: opCount.Uint64(), + } + timelockAddresses[chainSel] = state.Chains[sel].Timelock.Address() + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: chainSel, + Batch: []mcms.Operation{ + { + To: state.Chains[sel].OnRamp.Address(), + Data: acceptOnRamp.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[sel].FeeQuoter.Address(), + Data: acceptFeeQuoter.Data(), + Value: big.NewInt(0), + }, + }, + }) + } + + acceptCR, err := state.Chains[homeChain].CapabilityRegistry.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + acceptCCIPConfig, err := state.Chains[homeChain].CCIPHome.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + homeChainID := mcms.ChainIdentifier(homeChain) + opCount, err := state.Chains[homeChain].ProposerMcm.GetOpCount(nil) + if err != nil { + return nil, err + } + metaDataPerChain[homeChainID] = mcms.ChainMetadata{ + StartingOpCount: opCount.Uint64(), + MCMAddress: state.Chains[homeChain].ProposerMcm.Address(), + } + timelockAddresses[homeChainID] = state.Chains[homeChain].Timelock.Address() + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: homeChainID, + Batch: []mcms.Operation{ + { + To: state.Chains[homeChain].CapabilityRegistry.Address(), + Data: acceptCR.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[homeChain].CCIPHome.Address(), + Data: acceptCCIPConfig.Data(), + Value: big.NewInt(0), + }, + }, + }) + + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO + []mcms.Signature{}, + false, + metaDataPerChain, + timelockAddresses, + "blah", // TODO + batches, + timelock.Schedule, "0s") +} + +func BuildProposalMetadata(state CCIPOnChainState, chains []uint64) (map[mcms.ChainIdentifier]common.Address, map[mcms.ChainIdentifier]mcms.ChainMetadata, error) { + tlAddressMap := make(map[mcms.ChainIdentifier]common.Address) + metaDataPerChain := make(map[mcms.ChainIdentifier]mcms.ChainMetadata) + for _, sel := range chains { + chainId := mcms.ChainIdentifier(sel) + tlAddressMap[chainId] = state.Chains[sel].Timelock.Address() + mcm := state.Chains[sel].ProposerMcm + opCount, err := mcm.GetOpCount(nil) + if err != nil { + return nil, nil, err + } + metaDataPerChain[chainId] = mcms.ChainMetadata{ + StartingOpCount: opCount.Uint64(), + MCMAddress: mcm.Address(), + } + } + return tlAddressMap, metaDataPerChain, nil +} diff --git a/integration-tests/deployment/ccip/propose_home_chain.go b/integration-tests/deployment/ccip/propose_home_chain.go new file mode 100644 index 00000000000..8ad3e9cfffd --- /dev/null +++ b/integration-tests/deployment/ccip/propose_home_chain.go @@ -0,0 +1,111 @@ +package ccipdeployment + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" +) + +// SetCandidateExecPluginProposal calls setCandidate on the CCIPHome for setting up OCR3 exec Plugin config for the new chain. +func SetCandidateExecPluginProposal( + state CCIPOnChainState, + e deployment.Environment, + nodes deployment.Nodes, + ocrSecrets deployment.OCRSecrets, + homeChainSel, feedChainSel, newChainSel uint64, + tokenConfig TokenConfig, + rmnHomeAddress common.Address, +) (*timelock.MCMSWithTimelockProposal, error) { + newDONArgs, err := BuildOCR3ConfigForCCIPHome( + e.Logger, + ocrSecrets, + state.Chains[newChainSel].OffRamp, + e.Chains[newChainSel], + feedChainSel, + tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), + nodes.NonBootstraps(), + rmnHomeAddress, + ) + if err != nil { + return nil, err + } + + execConfig, ok := newDONArgs[types.PluginTypeCCIPExec] + if !ok { + return nil, fmt.Errorf("missing exec plugin in ocr3Configs") + } + + setCandidateMCMSOps, err := SetCandidateExecPluginOps( + execConfig, + state.Chains[homeChainSel].CapabilityRegistry, + state.Chains[homeChainSel].CCIPHome, + newChainSel, + nodes.NonBootstraps(), + ) + + if err != nil { + return nil, err + } + timelockAddresses, metaDataPerChain, err := BuildProposalMetadata(state, []uint64{homeChainSel}) + if err != nil { + return nil, err + } + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO: should be parameterized and based on current block timestamp. + []mcms.Signature{}, + false, + metaDataPerChain, + timelockAddresses, + "SetCandidate for execution", + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: setCandidateMCMSOps, + }}, + timelock.Schedule, + "0s", // TODO: Should be parameterized. + ) +} + +// PromoteCandidateProposal generates a proposal to call promoteCandidate on the CCIPHome through CapReg. +// This needs to be called after SetCandidateProposal is executed. +func PromoteCandidateProposal( + state CCIPOnChainState, + homeChainSel, newChainSel uint64, + nodes deployment.Nodes, +) (*timelock.MCMSWithTimelockProposal, error) { + promoteCandidateOps, err := PromoteCandidateOps( + state.Chains[homeChainSel].CapabilityRegistry, + state.Chains[homeChainSel].CCIPHome, + newChainSel, + nodes.NonBootstraps(), + ) + if err != nil { + return nil, err + } + + timelockAddresses, metaDataPerChain, err := BuildProposalMetadata(state, []uint64{homeChainSel}) + if err != nil { + return nil, err + } + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO: should be parameterized and based on current block timestamp. + []mcms.Signature{}, + false, + metaDataPerChain, + timelockAddresses, + "promoteCandidate for commit and execution", + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: promoteCandidateOps, + }}, + timelock.Schedule, + "0s", // TODO: Should be parameterized. + ) +} diff --git a/integration-tests/deployment/ccip/rmn_test.go b/integration-tests/deployment/ccip/rmn_test.go new file mode 100644 index 00000000000..0ece72eadd3 --- /dev/null +++ b/integration-tests/deployment/ccip/rmn_test.go @@ -0,0 +1,18 @@ +package ccipdeployment + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestRMN(t *testing.T) { + t.Skip("Local only") + // TODO: needs to return RMN peerIDs. + _, rmnCluster := NewLocalDevEnvironmentWithRMN(t, logger.TestLogger(t)) + for rmnNode, rmn := range rmnCluster.Nodes { + t.Log(rmnNode, rmn.Proxy.PeerID, rmn.RMN.OffchainPublicKey, rmn.RMN.EVMOnchainPublicKey) + } + // Use peerIDs to set RMN config. + // Add a lane, send a message. +} diff --git a/integration-tests/deployment/ccip/state.go b/integration-tests/deployment/ccip/state.go new file mode 100644 index 00000000000..e4bbe9863a0 --- /dev/null +++ b/integration-tests/deployment/ccip/state.go @@ -0,0 +1,403 @@ +package ccipdeployment + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_5" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_6" + + "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/shared/generated/burn_mint_erc677" + + owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + + "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/rmn_proxy_contract" + "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/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" +) + +// CCIPChainState holds a Go binding for all the currently deployed CCIP contracts +// on a chain. If a binding is nil, it means here is no such contract on the chain. +type CCIPChainState struct { + OnRamp *onramp.OnRamp + OffRamp *offramp.OffRamp + FeeQuoter *fee_quoter.FeeQuoter + RMNProxy *rmn_proxy_contract.RMNProxyContract + NonceManager *nonce_manager.NonceManager + TokenAdminRegistry *token_admin_registry.TokenAdminRegistry + Router *router.Router + CommitStore *commit_store.CommitStore + Weth9 *weth9.WETH9 + RMNRemote *rmn_remote.RMNRemote + // TODO: May need to support older link too + LinkToken *burn_mint_erc677.BurnMintERC677 + // 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. + BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 + // Map between token Symbol (e.g. LinkSymbol, WethSymbol) + // and the respective aggregator USD feed contract + USDFeeds map[TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface + + // Note we only expect one of these (on the home chain) + CapabilityRegistry *capabilities_registry.CapabilitiesRegistry + CCIPHome *ccip_home.CCIPHome + RMNHome *rmn_home.RMNHome + AdminMcm *owner_wrappers.ManyChainMultiSig + BypasserMcm *owner_wrappers.ManyChainMultiSig + CancellerMcm *owner_wrappers.ManyChainMultiSig + ProposerMcm *owner_wrappers.ManyChainMultiSig + Timelock *owner_wrappers.RBACTimelock + // TODO remove once staging upgraded. + CCIPConfig *ccip_config.CCIPConfig + + // Test contracts + Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver + TestRouter *router.Router +} + +func (c CCIPChainState) GenerateView() (view.ChainView, error) { + chainView := view.NewChain() + if c.Router != nil { + routerView, err := v1_2.GenerateRouterView(c.Router) + if err != nil { + return chainView, err + } + chainView.Router[c.Router.Address().Hex()] = routerView + } + if c.TokenAdminRegistry != nil { + taView, err := v1_5.GenerateTokenAdminRegistryView(c.TokenAdminRegistry) + if err != nil { + return chainView, err + } + chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView + } + if c.NonceManager != nil { + nmView, err := v1_6.GenerateNonceManagerView(c.NonceManager) + if err != nil { + return chainView, err + } + chainView.NonceManager[c.NonceManager.Address().Hex()] = nmView + } + if c.RMNRemote != nil { + rmnView, err := v1_6.GenerateRMNRemoteView(c.RMNRemote) + if err != nil { + return chainView, err + } + chainView.RMN[c.RMNRemote.Address().Hex()] = rmnView + } + if c.FeeQuoter != nil && c.Router != nil && c.TokenAdminRegistry != nil { + fqView, err := v1_6.GenerateFeeQuoterView(c.FeeQuoter, c.Router, c.TokenAdminRegistry) + if err != nil { + return chainView, err + } + chainView.FeeQuoter[c.FeeQuoter.Address().Hex()] = fqView + } + + if c.OnRamp != nil && c.Router != nil && c.TokenAdminRegistry != nil { + onRampView, err := v1_6.GenerateOnRampView( + c.OnRamp, + c.Router, + c.TokenAdminRegistry, + ) + if err != nil { + return chainView, err + } + chainView.OnRamp[c.OnRamp.Address().Hex()] = onRampView + } + + if c.OffRamp != nil && c.Router != nil { + offRampView, err := v1_6.GenerateOffRampView( + c.OffRamp, + c.Router, + ) + if err != nil { + return chainView, err + } + chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView + } + + if c.CommitStore != nil { + commitStoreView, err := v1_5.GenerateCommitStoreView(c.CommitStore) + if err != nil { + return chainView, err + } + chainView.CommitStore[c.CommitStore.Address().Hex()] = commitStoreView + } + + if c.RMNProxy != nil { + rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxy) + if err != nil { + return chainView, err + } + chainView.RMNProxy[c.RMNProxy.Address().Hex()] = rmnProxyView + } + if c.CapabilityRegistry != nil { + capRegView, err := v1_6.GenerateCapRegView(c.CapabilityRegistry) + if err != nil { + return chainView, err + } + chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView + } + return chainView, nil +} + +// Onchain state always derivable from an address book. +// Offchain state always derivable from a list of nodeIds. +// Note can translate this into Go struct needed for MCMS/Docs/UI. +type CCIPOnChainState struct { + // Populated go bindings for the appropriate version for all contracts. + // We would hold 2 versions of each contract here. Once we upgrade we can phase out the old one. + // When generating bindings, make sure the package name corresponds to the version. + Chains map[uint64]CCIPChainState +} + +func (s CCIPOnChainState) View(chains []uint64) (view.CCIPView, error) { + ccipView := view.NewCCIPView() + for _, chainSelector := range chains { + // TODO: Need a utility for this + chainid, err := chainsel.ChainIdFromSelector(chainSelector) + if err != nil { + return ccipView, err + } + chainName, err := chainsel.NameFromChainId(chainid) + if err != nil { + return ccipView, err + } + if _, ok := s.Chains[chainSelector]; !ok { + return ccipView, fmt.Errorf("chain not supported %d", chainSelector) + } + chainState := s.Chains[chainSelector] + chainView, err := chainState.GenerateView() + if err != nil { + return ccipView, err + } + ccipView.Chains[chainName] = chainView + } + return ccipView, nil +} + +func StateView(e deployment.Environment, ab deployment.AddressBook) (view.CCIPView, error) { + state, err := LoadOnchainState(e, ab) + if err != nil { + return view.CCIPView{}, err + } + ccipView, err := state.View(e.AllChainSelectors()) + if err != nil { + return view.CCIPView{}, err + } + ccipView.NodeOperators, err = view.GenerateNopsView(e.NodeIDs, e.Offchain) + if err != nil { + return ccipView, err + } + return ccipView, nil +} + +func LoadOnchainState(e deployment.Environment, ab deployment.AddressBook) (CCIPOnChainState, error) { + state := CCIPOnChainState{ + Chains: make(map[uint64]CCIPChainState), + } + for chainSelector, chain := range e.Chains { + addresses, err := ab.AddressesForChain(chainSelector) + if err != nil { + // Chain not found in address book, initialize empty + if errors.Is(err, deployment.ErrChainNotFound) { + addresses = make(map[string]deployment.TypeAndVersion) + } else { + return state, err + } + } + chainState, err := LoadChainState(chain, addresses) + if err != nil { + return state, err + } + state.Chains[chainSelector] = chainState + } + return state, nil +} + +// LoadChainState Loads all state for a chain into state +// Modifies map in place +func LoadChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (CCIPChainState, error) { + var state CCIPChainState + for address, tvStr := range addresses { + switch tvStr.String() { + case deployment.NewTypeAndVersion(RBACTimelock, deployment.Version1_0_0).String(): + tl, err := owner_wrappers.NewRBACTimelock(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Timelock = tl + case deployment.NewTypeAndVersion(AdminManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.AdminMcm = mcms + case deployment.NewTypeAndVersion(ProposerManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.ProposerMcm = mcms + case deployment.NewTypeAndVersion(BypasserManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.BypasserMcm = mcms + case deployment.NewTypeAndVersion(CancellerManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CancellerMcm = mcms + case deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): + cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CapabilityRegistry = cr + case deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev).String(): + onRampC, err := onramp.NewOnRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.OnRamp = onRampC + case deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev).String(): + offRamp, err := offramp.NewOffRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.OffRamp = offRamp + case deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0).String(): + armProxy, err := rmn_proxy_contract.NewRMNProxyContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNProxy = armProxy + case deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev).String(): + rmnRemote, err := rmn_remote.NewRMNRemote(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNRemote = rmnRemote + case deployment.NewTypeAndVersion(RMNHome, deployment.Version1_6_0_dev).String(): + rmnHome, err := rmn_home.NewRMNHome(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNHome = rmnHome + case deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0).String(): + weth9, err := weth9.NewWETH9(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Weth9 = weth9 + case deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev).String(): + nm, err := nonce_manager.NewNonceManager(common.HexToAddress(address), chain.Client) + if err != nil { + 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 { + return state, err + } + state.TokenAdminRegistry = tm + case deployment.NewTypeAndVersion(Router, deployment.Version1_2_0).String(): + r, err := router.NewRouter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Router = r + case deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0).String(): + r, err := router.NewRouter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.TestRouter = r + case deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev).String(): + fq, err := fee_quoter.NewFeeQuoter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.FeeQuoter = fq + case deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0).String(): + lt, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.LinkToken = lt + case deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev).String(): + ccipHome, err := ccip_home.NewCCIPHome(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CCIPHome = ccipHome + case deployment.NewTypeAndVersion(CCIPConfig, deployment.Version1_0_0).String(): + // TODO: Remove once staging upgraded. + ccipConfig, err := ccip_config.NewCCIPConfig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CCIPConfig = ccipConfig + case deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0).String(): + mr, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Receiver = mr + case deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0).String(): + feed, err := aggregator_v3_interface.NewAggregatorV3Interface(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.USDFeeds == nil { + state.USDFeeds = make(map[TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface) + } + desc, err := feed.Description(&bind.CallOpts{}) + if err != nil { + return state, err + } + key, ok := MockDescriptionToTokenSymbol[desc] + if !ok { + return state, fmt.Errorf("unknown feed description %s", desc) + } + state.USDFeeds[key] = feed + default: + return state, fmt.Errorf("unknown contract %s", tvStr) + } + } + return state, nil +} diff --git a/integration-tests/deployment/ccip/test_assertions.go b/integration-tests/deployment/ccip/test_assertions.go new file mode 100644 index 00000000000..91bd0550545 --- /dev/null +++ b/integration-tests/deployment/ccip/test_assertions.go @@ -0,0 +1,252 @@ +package ccipdeployment + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" +) + +// ConfirmCommitForAllWithExpectedSeqNums waits for all chains in the environment to commit the given expectedSeqNums. +// expectedSeqNums is a map of destinationchain selector to expected sequence number +// startBlocks is a map of destination chain selector to start block number to start watching from. +// If startBlocks is nil, it will start watching from the latest block. +func ConfirmCommitForAllWithExpectedSeqNums( + t *testing.T, + e deployment.Environment, + state CCIPOnChainState, + expectedSeqNums map[uint64]uint64, + startBlocks map[uint64]*uint64, +) { + var wg errgroup.Group + for src, srcChain := range e.Chains { + for dest, dstChain := range e.Chains { + if src == dest { + continue + } + srcChain := srcChain + dstChain := dstChain + wg.Go(func() error { + var startBlock *uint64 + if startBlocks != nil { + startBlock = startBlocks[dstChain.Selector] + } + return ConfirmCommitWithExpectedSeqNumRange( + t, + srcChain, + dstChain, + state.Chains[dstChain.Selector].OffRamp, + startBlock, + ccipocr3.SeqNumRange{ + ccipocr3.SeqNum(expectedSeqNums[dstChain.Selector]), + ccipocr3.SeqNum(expectedSeqNums[dstChain.Selector]), + }) + }) + } + } + require.NoError(t, wg.Wait()) +} + +// ConfirmCommitWithExpectedSeqNumRange waits for a commit report on the destination chain with the expected sequence number range. +// startBlock is the block number to start watching from. +// If startBlock is nil, it will start watching from the latest block. +func ConfirmCommitWithExpectedSeqNumRange( + t *testing.T, + src deployment.Chain, + dest deployment.Chain, + offRamp *offramp.OffRamp, + startBlock *uint64, + expectedSeqNumRange ccipocr3.SeqNumRange, +) error { + sink := make(chan *offramp.OffRampCommitReportAccepted) + subscription, err := offRamp.WatchCommitReportAccepted(&bind.WatchOpts{ + Context: context.Background(), + Start: startBlock, + }, sink) + if err != nil { + return fmt.Errorf("error to subscribe CommitReportAccepted : %w", err) + } + + defer subscription.Unsubscribe() + var duration time.Duration + deadline, ok := t.Deadline() + if ok { + // make this timer end a minute before so that we don't hit the deadline + duration = deadline.Sub(time.Now().Add(-1 * time.Minute)) + } else { + duration = 5 * time.Minute + } + timer := time.NewTimer(duration) + defer timer.Stop() + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + // if it's simulated backend, commit to ensure mining + if backend, ok := src.Client.(*backends.SimulatedBackend); ok { + backend.Commit() + } + if backend, ok := dest.Client.(*backends.SimulatedBackend); ok { + backend.Commit() + } + t.Logf("Waiting for commit report on chain selector %d from source selector %d expected seq nr range %s", + dest.Selector, src.Selector, expectedSeqNumRange.String()) + case subErr := <-subscription.Err(): + return fmt.Errorf("subscription error: %w", subErr) + case <-timer.C: + return fmt.Errorf("timed out after waiting %s duration for commit report on chain selector %d from source selector %d expected seq nr range %s", + duration.String(), dest.Selector, src.Selector, expectedSeqNumRange.String()) + case report := <-sink: + if len(report.MerkleRoots) > 0 { + // Check the interval of sequence numbers and make sure it matches + // the expected range. + for _, mr := range report.MerkleRoots { + if mr.SourceChainSelector == src.Selector && + uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && + uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { + t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", + mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), report.PriceUpdates.TokenPriceUpdates) + return nil + } + } + } + } + } +} + +// ConfirmExecWithSeqNrForAll waits for all chains in the environment to execute the given expectedSeqNums. +// expectedSeqNums is a map of destinationchain selector to expected sequence number +// startBlocks is a map of destination chain selector to start block number to start watching from. +// If startBlocks is nil, it will start watching from the latest block. +func ConfirmExecWithSeqNrForAll( + t *testing.T, + e deployment.Environment, + state CCIPOnChainState, + expectedSeqNums map[uint64]uint64, + startBlocks map[uint64]*uint64, +) { + var wg errgroup.Group + for src, srcChain := range e.Chains { + for dest, dstChain := range e.Chains { + if src == dest { + continue + } + srcChain := srcChain + dstChain := dstChain + wg.Go(func() error { + var startBlock *uint64 + if startBlocks != nil { + startBlock = startBlocks[dstChain.Selector] + } + return ConfirmExecWithSeqNr( + t, + srcChain, + dstChain, + state.Chains[dstChain.Selector].OffRamp, + startBlock, + expectedSeqNums[dstChain.Selector], + ) + }) + } + } + require.NoError(t, wg.Wait()) +} + +// ConfirmExecWithSeqNr waits for an execution state change on the destination chain with the expected sequence number. +// startBlock is the block number to start watching from. +// If startBlock is nil, it will start watching from the latest block. +func ConfirmExecWithSeqNr( + t *testing.T, + source, dest deployment.Chain, + offRamp *offramp.OffRamp, + startBlock *uint64, + expectedSeqNr uint64, +) error { + timer := time.NewTimer(5 * time.Minute) + defer timer.Stop() + tick := time.NewTicker(5 * time.Second) + defer tick.Stop() + sink := make(chan *offramp.OffRampExecutionStateChanged) + subscription, err := offRamp.WatchExecutionStateChanged(&bind.WatchOpts{ + Context: context.Background(), + Start: startBlock, + }, sink, nil, nil, nil) + if err != nil { + return fmt.Errorf("error to subscribe ExecutionStateChanged : %w", err) + } + defer subscription.Unsubscribe() + for { + select { + case <-tick.C: + // TODO: Clean this up + // if it's simulated backend, commit to ensure mining + if backend, ok := source.Client.(*backends.SimulatedBackend); ok { + backend.Commit() + } + if backend, ok := dest.Client.(*backends.SimulatedBackend); ok { + backend.Commit() + } + scc, err := offRamp.GetSourceChainConfig(nil, source.Selector) + if err != nil { + return fmt.Errorf("error to get source chain config : %w", err) + } + executionState, err := offRamp.GetExecutionState(nil, source.Selector, expectedSeqNr) + if err != nil { + return fmt.Errorf("error to get execution state : %w", err) + } + t.Logf("Waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence number %d, current onchain minSeqNr: %d, execution state: %s", + dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr, scc.MinSeqNr, executionStateToString(executionState)) + if executionState == EXECUTION_STATE_SUCCESS { + t.Logf("Observed SUCCESS execution state on chain %d (offramp %s) from chain %d with expected sequence number %d", + dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) + return nil + } + case execEvent := <-sink: + t.Logf("Received ExecutionStateChanged for seqNum %d on chain %d (offramp %s) from chain %d", + execEvent.SequenceNumber, dest.Selector, offRamp.Address().String(), source.Selector) + if execEvent.SequenceNumber == expectedSeqNr && execEvent.SourceChainSelector == source.Selector { + t.Logf("Received ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence number %d", + dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) + return nil + } + case <-timer.C: + return fmt.Errorf("timed out waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence number %d", + dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) + case subErr := <-subscription.Err(): + return fmt.Errorf("subscription error: %w", subErr) + } + } +} + +const ( + EXECUTION_STATE_UNTOUCHED = 0 + EXECUTION_STATE_INPROGRESS = 1 + EXECUTION_STATE_SUCCESS = 2 + EXECUTION_STATE_FAILURE = 3 +) + +func executionStateToString(state uint8) string { + switch state { + case EXECUTION_STATE_UNTOUCHED: + return "UNTOUCHED" + case EXECUTION_STATE_INPROGRESS: + return "IN_PROGRESS" + case EXECUTION_STATE_SUCCESS: + return "SUCCESS" + case EXECUTION_STATE_FAILURE: + return "FAILURE" + default: + return "UNKNOWN" + } +} diff --git a/integration-tests/deployment/ccip/test_helpers.go b/integration-tests/deployment/ccip/test_helpers.go new file mode 100644 index 00000000000..b7e295ebf63 --- /dev/null +++ b/integration-tests/deployment/ccip/test_helpers.go @@ -0,0 +1,562 @@ +package ccipdeployment + +import ( + "context" + + "fmt" + "math/big" + "sort" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "go.uber.org/multierr" + "go.uber.org/zap/zapcore" + + chainsel "github.com/smartcontractkit/chain-selectors" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/devenv" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper" +) + +const ( + HomeChainIndex = 0 + FeedChainIndex = 1 +) + +// 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 +} + +type DeployedEnv struct { + Env deployment.Environment + Ab deployment.AddressBook + HomeChainSel uint64 + FeedChainSel uint64 + ReplayBlocks map[uint64]uint64 + FeeTokenContracts map[uint64]FeeTokenContracts +} + +func (e *DeployedEnv) SetupJobs(t *testing.T) { + ctx := testcontext.Get(t) + jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + for nodeID, jobs := range jbs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.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, e.Env.Offchain, e.ReplayBlocks) +} + +func ReplayLogs(t *testing.T, oc deployment.OffchainClient, replayBlocks map[uint64]uint64) { + switch oc := oc.(type) { + case *memory.JobClient: + require.NoError(t, oc.ReplayLogs(replayBlocks)) + case *devenv.JobDistributor: + require.NoError(t, oc.ReplayLogs(replayBlocks)) + default: + t.Fatalf("unsupported offchain client type %T", oc) + } +} + +func DeployTestContracts(t *testing.T, + lggr logger.Logger, + ab deployment.AddressBook, + homeChainSel, + feedChainSel uint64, + chains map[uint64]deployment.Chain, +) (map[uint64]FeeTokenContracts, deployment.CapabilityRegistryConfig) { + capReg, err := DeployCapReg(lggr, ab, chains[homeChainSel]) + require.NoError(t, err) + _, err = DeployFeeds(lggr, ab, chains[feedChainSel]) + require.NoError(t, err) + feeTokenContracts, err := DeployFeeTokensToChains(lggr, ab, chains) + require.NoError(t, err) + evmChainID, err := chainsel.ChainIdFromSelector(homeChainSel) + require.NoError(t, err) + return feeTokenContracts, deployment.CapabilityRegistryConfig{ + EVMChainID: evmChainID, + Contract: capReg.Address, + } +} + +func LatestBlocksByChain(ctx context.Context, chains map[uint64]deployment.Chain) (map[uint64]uint64, error) { + latestBlocks := make(map[uint64]uint64) + for _, chain := range chains { + latesthdr, err := chain.Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, errors.Wrapf(err, "failed to get latest header for chain %d", chain.Selector) + } + block := latesthdr.Number.Uint64() + latestBlocks[chain.Selector] = block + } + return latestBlocks, nil +} + +func allocateCCIPChainSelectors(chains map[uint64]deployment.Chain) (homeChainSel uint64, feeChainSel uint64) { + // Lower chainSel is home chain. + var chainSels []uint64 + // Say first chain is home chain. + for chainSel := range chains { + chainSels = append(chainSels, chainSel) + } + sort.Slice(chainSels, func(i, j int) bool { + return chainSels[i] < chainSels[j] + }) + // Take lowest for determinism. + return chainSels[HomeChainIndex], chainSels[FeedChainIndex] +} + +// NewMemoryEnvironment creates a new CCIP environment +// with capreg, fee tokens, feeds and nodes set up. +func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, numChains int) DeployedEnv { + require.GreaterOrEqual(t, numChains, 2, "numChains must be at least 2 for home and feed chains") + ctx := testcontext.Get(t) + chains := memory.NewMemoryChains(t, numChains) + homeChainSel, feedSel := allocateCCIPChainSelectors(chains) + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) + + ab := deployment.NewMemoryAddressBook() + feeTokenContracts, crConfig := DeployTestContracts(t, lggr, ab, homeChainSel, feedSel, chains) + nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, 4, 1, crConfig) + for _, node := range nodes { + require.NoError(t, node.App.Start(ctx)) + t.Cleanup(func() { + require.NoError(t, node.App.Stop()) + }) + } + + e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) + return DeployedEnv{ + Ab: ab, + Env: e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, + FeeTokenContracts: feeTokenContracts, + } +} + +func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, numChains int) DeployedEnv { + e := NewMemoryEnvironment(t, lggr, numChains) + e.SetupJobs(t) + return e +} + +func SendRequest(t *testing.T, e deployment.Environment, state CCIPOnChainState, src, dest uint64, testRouter bool) uint64 { + msg := router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, // TODO: no tokens for now + // Pay native. + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, // TODO: no extra args for now, falls back to default + } + router := state.Chains[src].Router + if testRouter { + router = state.Chains[src].TestRouter + } + fee, err := router.GetFee( + &bind.CallOpts{Context: context.Background()}, dest, msg) + require.NoError(t, err, deployment.MaybeDataErr(err)) + + t.Logf("Sending CCIP request from chain selector %d to chain selector %d", + src, dest) + e.Chains[src].DeployerKey.Value = fee + tx, err := router.CcipSend( + e.Chains[src].DeployerKey, + dest, + msg) + require.NoError(t, err) + e.Chains[src].DeployerKey.Value = nil + blockNum, err := e.Chains[src].Confirm(tx) + require.NoError(t, err) + it, err := state.Chains[src].OnRamp.FilterCCIPMessageSent(&bind.FilterOpts{ + Start: blockNum, + End: &blockNum, + Context: context.Background(), + }, []uint64{dest}, []uint64{}) + require.NoError(t, err) + require.True(t, it.Next()) + seqNum := it.Event.Message.Header.SequenceNumber + t.Logf("CCIP message sent from chain selector %d to chain selector %d tx %s seqNum %d", src, dest, tx.Hash().String(), seqNum) + return seqNum +} + +// DeployedLocalDevEnvironment is a helper struct for setting up a local dev environment with docker +type DeployedLocalDevEnvironment struct { + DeployedEnv + testEnv *test_env.CLClusterTestEnv + DON *devenv.DON +} + +func (d DeployedLocalDevEnvironment) RestartChainlinkNodes(t *testing.T) error { + errGrp := errgroup.Group{} + for _, n := range d.testEnv.ClCluster.Nodes { + n := n + errGrp.Go(func() error { + if err := n.Container.Terminate(testcontext.Get(t)); err != nil { + return err + } + err := n.RestartContainer() + if err != nil { + return err + } + return nil + }) + + } + return errGrp.Wait() +} + +func NewLocalDevEnvironment(t *testing.T, lggr logger.Logger) (DeployedEnv, *test_env.CLClusterTestEnv, testconfig.TestConfig) { + ctx := testcontext.Get(t) + // create a local docker environment with simulated chains and job-distributor + // we cannot create the chainlink nodes yet as we need to deploy the capability registry first + envConfig, testEnv, cfg := devenv.CreateDockerEnv(t) + require.NotNil(t, envConfig) + require.NotEmpty(t, envConfig.Chains, "chainConfigs should not be empty") + require.NotEmpty(t, envConfig.JDConfig, "jdUrl should not be empty") + chains, err := devenv.NewChains(lggr, envConfig.Chains) + require.NoError(t, err) + // locate the home chain + homeChainSel := envConfig.HomeChainSelector + require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty") + feedSel := envConfig.FeedChainSelector + require.NotEmpty(t, feedSel, "feedSel should not be empty") + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) + + ab := deployment.NewMemoryAddressBook() + feeContracts, crConfig := DeployTestContracts(t, lggr, ab, homeChainSel, feedSel, chains) + + // start the chainlink nodes with the CR address + err = devenv.StartChainlinkNodes(t, envConfig, + crConfig, + testEnv, cfg) + require.NoError(t, err) + + e, don, err := devenv.NewEnvironment(ctx, lggr, *envConfig) + require.NoError(t, err) + require.NotNil(t, e) + zeroLogLggr := logging.GetTestLogger(t) + // fund the nodes + devenv.FundNodes(t, zeroLogLggr, testEnv, cfg, don.PluginNodes()) + + return DeployedEnv{ + Ab: ab, + Env: *e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, + FeeTokenContracts: feeContracts, + }, testEnv, cfg +} + +func NewLocalDevEnvironmentWithRMN(t *testing.T, lggr logger.Logger) (DeployedEnv, devenv.RMNCluster) { + tenv, dockerenv, _ := NewLocalDevEnvironment(t, lggr) + state, err := LoadOnchainState(tenv.Env, tenv.Ab) + require.NoError(t, err) + + feeds := state.Chains[tenv.FeedChainSel].USDFeeds + tokenConfig := NewTokenConfig() + tokenConfig.UpsertTokenInfo(LinkSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[LinkSymbol].Address().String(), + Decimals: LinkDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + tokenConfig.UpsertTokenInfo(WethSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[WethSymbol].Address().String(), + Decimals: WethDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + // Deploy CCIP contracts. + err = DeployCCIPContracts(tenv.Env, tenv.Ab, DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: tokenConfig, + MCMSConfig: NewTestMCMSConfig(t, tenv.Env), + CapabilityRegistry: state.Chains[tenv.HomeChainSel].CapabilityRegistry.Address(), + FeeTokenContracts: tenv.FeeTokenContracts, + }) + require.NoError(t, err) + l := logging.GetTestLogger(t) + config := GenerateTestRMNConfig(t, 1, tenv, MustNetworksToRPCMap(dockerenv.EVMNetworks)) + rmnCluster, err := devenv.NewRMNCluster( + t, l, + []string{dockerenv.DockerNetwork.Name}, + config, + "rageproxy", + "latest", + "afn2proxy", + "latest", + dockerenv.LogStream, + ) + require.NoError(t, err) + return tenv, *rmnCluster +} + +func MustNetworksToRPCMap(evmNetworks []*blockchain.EVMNetwork) map[uint64]string { + rpcs := make(map[uint64]string) + for _, network := range evmNetworks { + sel, err := chainsel.SelectorFromChainId(uint64(network.ChainID)) + if err != nil { + panic(err) + } + rpcs[sel] = network.HTTPURLs[0] + } + return rpcs +} + +func MustCCIPNameToRMNName(a string) string { + m := map[string]string{ + chainsel.GETH_TESTNET.Name: "DevnetAlpha", + chainsel.GETH_DEVNET_2.Name: "DevnetBeta", + // TODO: Add more as needed. + } + v, ok := m[a] + if !ok { + panic(fmt.Sprintf("no mapping for %s", a)) + } + return v +} + +func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv 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) + bootstrappers := nodes.BootstrapLocators() + + // Just set all RMN nodes to support all chains. + state, err := LoadOnchainState(tenv.Env, tenv.Ab) + require.NoError(t, err) + var remoteChains []devenv.RemoteChain + var rpcs []devenv.Chain + for chainSel, chain := range state.Chains { + c, _ := chainsel.ChainBySelector(chainSel) + rmnName := MustCCIPNameToRMNName(c.Name) + remoteChains = append(remoteChains, devenv.RemoteChain{ + Name: rmnName, + Stability: devenv.Stability{Type: "stable"}, + StartBlockNumber: 0, + OffRamp: chain.OffRamp.Address().String(), + RMNRemote: chain.RMNRemote.Address().String(), + }) + rpcs = append(rpcs, devenv.Chain{ + Name: rmnName, + RPC: rpcMap[chainSel], + }) + } + hc, _ := chainsel.ChainBySelector(tenv.HomeChainSel) + shared := devenv.SharedConfig{ + Networking: devenv.Networking{ + RageProxy: devenv.DefaultRageProxy, + Bootstrappers: bootstrappers, + }, + HomeChain: devenv.HomeChain{ + Name: MustCCIPNameToRMNName(hc.Name), + CapabilitiesRegistry: state.Chains[tenv.HomeChainSel].CapabilityRegistry.Address().String(), + CCIPHome: state.Chains[tenv.HomeChainSel].CCIPHome.Address().String(), + // TODO: RMNHome + }, + RemoteChains: remoteChains, + } + + rmnConfig := make(map[string]devenv.RMNConfig) + for i := 0; i < nRMNNodes; i++ { + // Listen addresses _should_ be able to operator on the same port since + // they are inside the docker network. + proxyLocal := devenv.ProxyLocalConfig{ + ListenAddresses: []string{devenv.DefaultProxyListenAddress}, + AnnounceAddresses: []string{}, + ProxyAddress: devenv.DefaultRageProxy, + DiscovererDbPath: devenv.DefaultDiscovererDbPath, + } + rmnConfig[fmt.Sprintf("rmn_%d", i)] = devenv.RMNConfig{ + Shared: shared, + Local: devenv.LocalConfig{Chains: rpcs}, + ProxyShared: devenv.DefaultRageProxySharedConfig, + ProxyLocal: proxyLocal, + } + } + return rmnConfig +} + +// 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 { + if source != dest { + err := AddLane(e, state, source, dest) + if err != nil { + return err + } + } + } + } + return nil +} + +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 = big.NewInt(5e18) + MockWethPrice = big.NewInt(9e18) + // 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, chain deployment.Chain) (map[string]common.Address, error) { + linkTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) + mockLinkFeed := func(chain deployment.Chain) ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { + linkFeed, tx, _, err1 := mock_v3_aggregator_contract.DeployMockV3Aggregator( + chain.DeployerKey, + chain.Client, + LinkDecimals, // decimals + MockLinkPrice, // initialAnswer + ) + aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(linkFeed, chain.Client) + + return ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface]{ + Address: linkFeed, Contract: aggregatorCr, Tv: linkTV, Tx: tx, Err: multierr.Append(err1, err2), + } + } + + mockWethFeed := func(chain deployment.Chain) ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { + wethFeed, tx, _, err1 := mock_ethusd_aggregator_wrapper.DeployMockETHUSDAggregator( + chain.DeployerKey, + chain.Client, + MockWethPrice, // initialAnswer + ) + aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(wethFeed, chain.Client) + + return ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface]{ + Address: wethFeed, Contract: aggregatorCr, Tv: linkTV, Tx: tx, Err: multierr.Append(err1, err2), + } + } + + linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, LinkSymbol) + if err != nil { + return nil, err + } + + wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, WethSymbol) + if err != nil { + return nil, err + } + + descriptionToAddress := map[string]common.Address{ + linkFeedDescription: linkFeedAddress, + wethFeedDescription: wethFeedAddress, + } + + return descriptionToAddress, nil +} + +func deploySingleFeed( + lggr logger.Logger, + ab deployment.AddressBook, + chain deployment.Chain, + deployFunc func(deployment.Chain) ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface], + symbol TokenSymbol, +) (common.Address, string, error) { + //tokenTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) + mockTokenFeed, err := deployContract(lggr, chain, ab, deployFunc) + if err != nil { + lggr.Errorw("Failed to deploy token feed", "err", err, "symbol", symbol) + return common.Address{}, "", err + } + + lggr.Infow("deployed mockTokenFeed", "addr", mockTokenFeed.Address) + + desc, err := mockTokenFeed.Contract.Description(&bind.CallOpts{}) + if err != nil { + lggr.Errorw("Failed to get description", "err", err, "symbol", symbol) + return common.Address{}, "", err + } + + if desc != MockSymbolToDescription[symbol] { + lggr.Errorw("Unexpected description for token", "symbol", symbol, "desc", desc) + return common.Address{}, "", fmt.Errorf("unexpected description: %s", desc) + } + + return mockTokenFeed.Address, desc, nil + +} diff --git a/integration-tests/deployment/ccip/token_info.go b/integration-tests/deployment/ccip/token_info.go new file mode 100644 index 00000000000..3570c58eefc --- /dev/null +++ b/integration-tests/deployment/ccip/token_info.go @@ -0,0 +1,56 @@ +package ccipdeployment + +import ( + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + "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-common/pkg/logger" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +// TokenConfig mapping between token Symbol (e.g. LinkSymbol, WethSymbol) +// and the respective token info. +type TokenConfig struct { + TokenSymbolToInfo map[TokenSymbol]pluginconfig.TokenInfo +} + +func NewTokenConfig() TokenConfig { + return TokenConfig{ + TokenSymbolToInfo: make(map[TokenSymbol]pluginconfig.TokenInfo), + } +} + +func (tc *TokenConfig) UpsertTokenInfo( + symbol TokenSymbol, + info pluginconfig.TokenInfo, +) { + tc.TokenSymbolToInfo[symbol] = info +} + +// GetTokenInfo Adds mapping between dest chain tokens and their respective aggregators on feed chain. +func (tc *TokenConfig) GetTokenInfo( + lggr logger.Logger, + linkToken *burn_mint_erc677.BurnMintERC677, + wethToken *weth9.WETH9, +) map[ocrtypes.Account]pluginconfig.TokenInfo { + tokenToAggregate := make(map[ocrtypes.Account]pluginconfig.TokenInfo) + if _, ok := tc.TokenSymbolToInfo[LinkSymbol]; !ok { + lggr.Debugw("Link aggregator not found, deploy without mapping link token") + } else { + lggr.Debugw("Mapping LinkToken to Link aggregator") + acc := ocrtypes.Account(linkToken.Address().String()) + tokenToAggregate[acc] = tc.TokenSymbolToInfo[LinkSymbol] + } + + if _, ok := tc.TokenSymbolToInfo[WethSymbol]; !ok { + lggr.Debugw("Weth aggregator not found, deploy without mapping link token") + } else { + lggr.Debugw("Mapping WethToken to Weth aggregator") + acc := ocrtypes.Account(wethToken.Address().String()) + tokenToAggregate[acc] = tc.TokenSymbolToInfo[WethSymbol] + } + + return tokenToAggregate +} diff --git a/integration-tests/deployment/ccip/view/chain.go b/integration-tests/deployment/ccip/view/chain.go new file mode 100644 index 00000000000..27c30002052 --- /dev/null +++ b/integration-tests/deployment/ccip/view/chain.go @@ -0,0 +1,44 @@ +package view + +import ( + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_0" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_5" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_6" +) + +type ChainView struct { + // v1.0 + RMNProxy map[string]v1_0.RMNProxyView `json:"rmnProxy,omitempty"` + // v1.2 + Router map[string]v1_2.RouterView `json:"router,omitempty"` + // v1.5 + TokenAdminRegistry map[string]v1_5.TokenAdminRegistryView `json:"tokenAdminRegistry,omitempty"` + CommitStore map[string]v1_5.CommitStoreView `json:"commitStore,omitempty"` + // v1.6 + FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"` + NonceManager map[string]v1_6.NonceManagerView `json:"nonceManager,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"` + CapabilityRegistry map[string]v1_6.CapRegView `json:"capabilityRegistry,omitempty"` +} + +func NewChain() ChainView { + return ChainView{ + // v1.0 + RMNProxy: make(map[string]v1_0.RMNProxyView), + // v1.2 + Router: make(map[string]v1_2.RouterView), + // v1.5 + TokenAdminRegistry: make(map[string]v1_5.TokenAdminRegistryView), + CommitStore: make(map[string]v1_5.CommitStoreView), + // v1.6 + FeeQuoter: make(map[string]v1_6.FeeQuoterView), + NonceManager: make(map[string]v1_6.NonceManagerView), + 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]v1_6.CapRegView), + } +} diff --git a/integration-tests/deployment/ccip/view/nops.go b/integration-tests/deployment/ccip/view/nops.go new file mode 100644 index 00000000000..34298706a99 --- /dev/null +++ b/integration-tests/deployment/ccip/view/nops.go @@ -0,0 +1,92 @@ +package view + +import ( + "context" + "fmt" + + chainsel "github.com/smartcontractkit/chain-selectors" + + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" +) + +type NopsView struct { + Nops map[string]NopView `json:"nops,omitempty"` +} + +type NopView struct { + // NodeID is the unique identifier of the node + NodeID string `json:"nodeID"` + IsBootstrap bool `json:"isBootstrap"` + OCRKeys map[string]OCRKeyView `json:"ocrKeys"` + PayeeAddress string `json:"payeeAddress"` + CSAKey string `json:"csaKey"` + IsConnected bool `json:"isConnected"` + IsEnabled bool `json:"isEnabled"` +} + +type OCRKeyView struct { + OffchainPublicKey string `json:"offchainPublicKey"` + OnchainPublicKey string `json:"onchainPublicKey"` + PeerID string `json:"peerID"` + TransmitAccount string `json:"transmitAccount"` + ConfigEncryptionPublicKey string `json:"configEncryptionPublicKey"` + KeyBundleID string `json:"keyBundleID"` +} + +func NewNopsView() NopsView { + return NopsView{ + Nops: make(map[string]NopView), + } +} + +func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (NopsView, error) { + nops := NewNopsView() + nodes, err := deployment.NodeInfo(nodeIds, oc) + if err != nil { + return nops, err + } + for _, node := range nodes { + // get node info + nodeDetails, err := oc.GetNode(context.Background(), &nodev1.GetNodeRequest{Id: node.NodeID}) + if err != nil { + return NopsView{}, err + } + if nodeDetails == nil || nodeDetails.Node == nil { + return NopsView{}, fmt.Errorf("failed to get node details from offchain client for node %s", node.NodeID) + } + nodeName := nodeDetails.Node.Name + if nodeName == "" { + nodeName = node.NodeID + } + nop := NopView{ + NodeID: node.NodeID, + IsBootstrap: node.IsBootstrap, + OCRKeys: make(map[string]OCRKeyView), + PayeeAddress: node.AdminAddr, + CSAKey: nodeDetails.Node.PublicKey, + IsConnected: nodeDetails.Node.IsConnected, + IsEnabled: nodeDetails.Node.IsEnabled, + } + for sel, ocrConfig := range node.SelToOCRConfig { + chainid, err := chainsel.ChainIdFromSelector(sel) + if err != nil { + return nops, err + } + chainName, err := chainsel.NameFromChainId(chainid) + if err != nil { + return nops, err + } + nop.OCRKeys[chainName] = OCRKeyView{ + OffchainPublicKey: fmt.Sprintf("%x", ocrConfig.OffchainPublicKey[:]), + OnchainPublicKey: fmt.Sprintf("%x", ocrConfig.OnchainPublicKey[:]), + PeerID: ocrConfig.PeerID.String(), + TransmitAccount: string(ocrConfig.TransmitAccount), + ConfigEncryptionPublicKey: fmt.Sprintf("%x", ocrConfig.ConfigEncryptionPublicKey[:]), + KeyBundleID: ocrConfig.KeyBundleID, + } + } + nops.Nops[nodeName] = nop + } + return nops, nil +} diff --git a/integration-tests/deployment/ccip/view/state.go b/integration-tests/deployment/ccip/view/state.go new file mode 100644 index 00000000000..b02ff676c13 --- /dev/null +++ b/integration-tests/deployment/ccip/view/state.go @@ -0,0 +1,12 @@ +package view + +type CCIPView struct { + Chains map[string]ChainView `json:"chains,omitempty"` + NodeOperators NopsView `json:"nodeOperators,omitempty"` +} + +func NewCCIPView() CCIPView { + return CCIPView{ + Chains: make(map[string]ChainView), + } +} diff --git a/integration-tests/deployment/ccip/view/types/contract_state.go b/integration-tests/deployment/ccip/view/types/contract_state.go new file mode 100644 index 00000000000..f65c510af53 --- /dev/null +++ b/integration-tests/deployment/ccip/view/types/contract_state.go @@ -0,0 +1,33 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +type ContractMetaData struct { + TypeAndVersion string `json:"typeAndVersion,omitempty"` + Address common.Address `json:"address,omitempty"` + Owner common.Address `json:"owner,omitempty"` +} + +func NewContractMetaData(tv Meta, addr common.Address) (ContractMetaData, error) { + tvStr, err := tv.TypeAndVersion(nil) + if err != nil { + return ContractMetaData{}, err + } + owner, err := tv.Owner(nil) + if err != nil { + return ContractMetaData{}, err + } + return ContractMetaData{ + TypeAndVersion: tvStr, + Address: addr, + Owner: owner, + }, nil +} + +type Meta interface { + TypeAndVersion(opts *bind.CallOpts) (string, error) + Owner(opts *bind.CallOpts) (common.Address, error) +} diff --git a/integration-tests/deployment/ccip/view/v1_0/rmn_proxy_contract.go b/integration-tests/deployment/ccip/view/v1_0/rmn_proxy_contract.go new file mode 100644 index 00000000000..bac32bf0f26 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_0/rmn_proxy_contract.go @@ -0,0 +1,33 @@ +package v1_0 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" +) + +type RMNProxyView struct { + types.ContractMetaData + RMN common.Address `json:"rmn"` +} + +func GenerateRMNProxyView(r *rmn_proxy_contract.RMNProxyContract) (RMNProxyView, error) { + if r == nil { + return RMNProxyView{}, fmt.Errorf("cannot generate view for nil RMNProxy") + } + meta, err := types.NewContractMetaData(r, r.Address()) + if err != nil { + return RMNProxyView{}, fmt.Errorf("failed to generate contract metadata for RMNProxy: %w", err) + } + rmn, err := r.GetARM(nil) + if err != nil { + return RMNProxyView{}, fmt.Errorf("failed to get ARM: %w", err) + } + return RMNProxyView{ + ContractMetaData: meta, + RMN: rmn, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_2/router.go b/integration-tests/deployment/ccip/view/v1_2/router.go new file mode 100644 index 00000000000..14a96e86b79 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_2/router.go @@ -0,0 +1,71 @@ +package v1_2 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +type RouterView struct { + types.ContractMetaData + WrappedNative common.Address `json:"wrappedNative,omitempty"` + ARMProxy common.Address `json:"armProxy,omitempty"` + OnRamps map[uint64]common.Address `json:"onRamps,omitempty"` // Map of DestinationChainSelectors to OnRamp Addresses + OffRamps map[uint64]common.Address `json:"offRamps,omitempty"` // Map of SourceChainSelectors to a list of OffRamp Addresses +} + +func GenerateRouterView(r *router.Router) (RouterView, error) { + meta, err := types.NewContractMetaData(r, r.Address()) + if err != nil { + return RouterView{}, fmt.Errorf("view error to get router metadata: %w", err) + } + wrappedNative, err := r.GetWrappedNative(nil) + if err != nil { + return RouterView{}, fmt.Errorf("view error to get router wrapped native: %w", err) + } + armProxy, err := r.GetArmProxy(nil) + if err != nil { + return RouterView{}, fmt.Errorf("view error to get router arm proxy: %w", err) + } + onRamps := make(map[uint64]common.Address) + offRamps := make(map[uint64]common.Address) + offRampList, err := r.GetOffRamps(nil) + if err != nil { + return RouterView{}, fmt.Errorf("view error to get router offRamps: %w", err) + } + for _, offRamp := range offRampList { + offRamps[offRamp.SourceChainSelector] = offRamp.OffRamp + } + for selector := range offRamps { + onRamp, err := r.GetOnRamp(nil, selector) + if err != nil { + return RouterView{}, fmt.Errorf("view error to get router onRamp: %w", err) + } + onRamps[selector] = onRamp + } + return RouterView{ + ContractMetaData: meta, + WrappedNative: wrappedNative, + ARMProxy: armProxy, + OnRamps: onRamps, + OffRamps: offRamps, + }, nil +} + +// From the perspective of the OnRamp, the destination chains are the source chains for the OffRamp. +func GetRemoteChainSelectors(routerContract *router.Router) ([]uint64, error) { + remoteSelectors := make([]uint64, 0) + offRamps, err := routerContract.GetOffRamps(nil) + if err != nil { + return nil, fmt.Errorf("failed to get offRamps from router: %w", err) + } + // lanes are bidirectional, so we get the list of source chains to know which chains are supported as destinations as well + for _, offRamp := range offRamps { + remoteSelectors = append(remoteSelectors, offRamp.SourceChainSelector) + } + + return remoteSelectors, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_5/commit_store.go b/integration-tests/deployment/ccip/view/v1_5/commit_store.go new file mode 100644 index 00000000000..0aa483e1678 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_5/commit_store.go @@ -0,0 +1,81 @@ +package v1_5 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" +) + +type CommitStoreView struct { + types.ContractMetaData + DynamicConfig commit_store.CommitStoreDynamicConfig `json:"dynamicConfig"` + ExpectedNextSequenceNumber uint64 `json:"expectedNextSequenceNumber"` + LatestPriceEpochAndRound uint64 `json:"latestPriceEpochAndRound"` + StaticConfig commit_store.CommitStoreStaticConfig `json:"staticConfig"` + Transmitters []common.Address `json:"transmitters"` + IsUnpausedAndNotCursed bool `json:"isUnpausedAndNotCursed"` + LatestConfigDetails commit_store.LatestConfigDetails `json:"latestConfigDetails"` + LatestConfigDigestAndEpoch commit_store.LatestConfigDigestAndEpoch `json:"latestConfigDigestAndEpoch"` + Paused bool `json:"paused"` +} + +func GenerateCommitStoreView(c *commit_store.CommitStore) (CommitStoreView, error) { + if c == nil { + return CommitStoreView{}, fmt.Errorf("cannot generate view for nil CommitStore") + } + meta, err := types.NewContractMetaData(c, c.Address()) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to generate contract metadata for CommitStore: %w", err) + } + dynamicConfig, err := c.GetDynamicConfig(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get dynamic config: %w", err) + } + expectedNextSequenceNumber, err := c.GetExpectedNextSequenceNumber(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get expected next sequence number: %w", err) + } + latestPriceEpochAndRound, err := c.GetLatestPriceEpochAndRound(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get latest price epoch and round: %w", err) + } + staticConfig, err := c.GetStaticConfig(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get static config: %w", err) + } + transmitters, err := c.GetTransmitters(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get transmitters: %w", err) + } + isUnpausedAndNotCursed, err := c.IsUnpausedAndNotCursed(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get is unpaused and not cursed: %w", err) + } + latestConfigDetails, err := c.LatestConfigDetails(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get latest config details: %w", err) + } + latestConfigDigestAndEpoch, err := c.LatestConfigDigestAndEpoch(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get latest config digest and epoch: %w", err) + } + paused, err := c.Paused(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get paused: %w", err) + } + return CommitStoreView{ + ContractMetaData: meta, + DynamicConfig: dynamicConfig, + ExpectedNextSequenceNumber: expectedNextSequenceNumber, + LatestPriceEpochAndRound: latestPriceEpochAndRound, + StaticConfig: staticConfig, + Transmitters: transmitters, + IsUnpausedAndNotCursed: isUnpausedAndNotCursed, + LatestConfigDetails: latestConfigDetails, + LatestConfigDigestAndEpoch: latestConfigDigestAndEpoch, + Paused: paused, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_5/tokenadminregistry.go b/integration-tests/deployment/ccip/view/v1_5/tokenadminregistry.go new file mode 100644 index 00000000000..ebfff8c2feb --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_5/tokenadminregistry.go @@ -0,0 +1,56 @@ +package v1_5 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" +) + +const ( + GetTokensPaginationSize = 20 +) + +type TokenAdminRegistryView struct { + types.ContractMetaData + Tokens []common.Address `json:"tokens"` +} + +func GenerateTokenAdminRegistryView(taContract *token_admin_registry.TokenAdminRegistry) (TokenAdminRegistryView, error) { + if taContract == nil { + return TokenAdminRegistryView{}, fmt.Errorf("token admin registry contract is nil") + } + tokens, err := getAllConfiguredTokensPaginated(taContract) + if err != nil { + return TokenAdminRegistryView{}, fmt.Errorf("view error for token admin registry: %w", err) + } + tvMeta, err := types.NewContractMetaData(taContract, taContract.Address()) + if err != nil { + return TokenAdminRegistryView{}, fmt.Errorf("metadata error for token admin registry: %w", err) + } + return TokenAdminRegistryView{ + ContractMetaData: tvMeta, + Tokens: tokens, + }, nil +} + +// getAllConfiguredTokensPaginated fetches all configured tokens from the TokenAdminRegistry contract in paginated +// manner to avoid RPC timeouts since the list of configured tokens can grow to be very large over time. +func getAllConfiguredTokensPaginated(taContract *token_admin_registry.TokenAdminRegistry) ([]common.Address, error) { + startIndex := uint64(0) + allTokens := make([]common.Address, 0) + for { + fetchedTokens, err := taContract.GetAllConfiguredTokens(nil, startIndex, GetTokensPaginationSize) + if err != nil { + return nil, err + } + allTokens = append(allTokens, fetchedTokens...) + startIndex += GetTokensPaginationSize + if len(fetchedTokens) < GetTokensPaginationSize { + break + } + } + return allTokens, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_6/capreg.go b/integration-tests/deployment/ccip/view/v1_6/capreg.go new file mode 100644 index 00000000000..8f93bd9a6f2 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_6/capreg.go @@ -0,0 +1,45 @@ +package v1_6 + +import ( + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +// CapRegView denotes a view of the capabilities registry contract. +// Note that the contract itself is 1.0.0 versioned, but we're releasing it first +// as part of 1.6. +type CapRegView struct { + types.ContractMetaData + Capabilities []CapabilityView `json:"capabilities,omitempty"` +} + +type CapabilityView struct { + LabelledName string `json:"labelledName"` + Version string `json:"version"` + ConfigContract common.Address `json:"configContract"` +} + +func GenerateCapRegView(capReg *capabilities_registry.CapabilitiesRegistry) (CapRegView, error) { + tv, err := types.NewContractMetaData(capReg, capReg.Address()) + if err != nil { + return CapRegView{}, err + } + caps, err := capReg.GetCapabilities(nil) + if err != nil { + return CapRegView{}, err + } + var capViews []CapabilityView + for _, capability := range caps { + capViews = append(capViews, CapabilityView{ + LabelledName: capability.LabelledName, + Version: capability.Version, + ConfigContract: capability.ConfigurationContract, + }) + } + return CapRegView{ + ContractMetaData: tv, + Capabilities: capViews, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_6/feequoter.go b/integration-tests/deployment/ccip/view/v1_6/feequoter.go new file mode 100644 index 00000000000..776f91c2e50 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_6/feequoter.go @@ -0,0 +1,140 @@ +package v1_6 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + router1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" +) + +type FeeQuoterView struct { + types.ContractMetaData + AuthorizedCallers []string `json:"authorizedCallers,omitempty"` + FeeTokens []string `json:"feeTokens,omitempty"` + StaticConfig FeeQuoterStaticConfig `json:"staticConfig,omitempty"` + DestinationChainConfig map[uint64]FeeQuoterDestChainConfig `json:"destinationChainConfig,omitempty"` + TokenPriceFeedConfig map[string]FeeQuoterTokenPriceFeedConfig `json:"tokenPriceFeedConfig,omitempty"` +} + +type FeeQuoterStaticConfig struct { + MaxFeeJuelsPerMsg string `json:"maxFeeJuelsPerMsg,omitempty"` + LinkToken string `json:"linkToken,omitempty"` + TokenPriceStalenessThreshold uint32 `json:"tokenPriseStalenessThreshold,omitempty"` +} + +type FeeQuoterDestChainConfig struct { + IsEnabled bool `json:"isEnabled,omitempty"` + MaxNumberOfTokensPerMsg uint16 `json:"maxNumberOfTokensPerMsg,omitempty"` + MaxDataBytes uint32 `json:"maxDataBytes,omitempty"` + MaxPerMsgGasLimit uint32 `json:"maxPerMsgGasLimit,omitempty"` + DestGasOverhead uint32 `json:"destGasOverhead,omitempty"` + DestGasPerPayloadByte uint16 `json:"destGasPerPayloadByte,omitempty"` + DestDataAvailabilityOverheadGas uint32 `json:"destDataAvailabilityOverheadGas,omitempty"` + DestGasPerDataAvailabilityByte uint16 `json:"destGasPerDataAvailabilityByte,omitempty"` + DestDataAvailabilityMultiplierBps uint16 `json:"destDataAvailabilityMultiplierBps,omitempty"` + DefaultTokenFeeUSDCents uint16 `json:"defaultTokenFeeUSDCents,omitempty"` + DefaultTokenDestGasOverhead uint32 `json:"defaultTokenDestGasOverhead,omitempty"` + DefaultTxGasLimit uint32 `json:"defaultTxGasLimit,omitempty"` + GasMultiplierWeiPerEth uint64 `json:"gasMultiplierWeiPerEth,omitempty"` + NetworkFeeUSDCents uint32 `json:"networkFeeUSDCents,omitempty"` + EnforceOutOfOrder bool `json:"enforceOutOfOrder,omitempty"` + ChainFamilySelector string `json:"chainFamilySelector,omitempty"` +} + +type FeeQuoterTokenPriceFeedConfig struct { + DataFeedAddress string `json:"dataFeedAddress,omitempty"` + TokenDecimals uint8 `json:"tokenDecimals,omitempty"` +} + +func GenerateFeeQuoterView(fqContract *fee_quoter.FeeQuoter, router *router1_2.Router, ta *token_admin_registry.TokenAdminRegistry) (FeeQuoterView, error) { + fq := FeeQuoterView{} + authorizedCallers, err := fqContract.GetAllAuthorizedCallers(nil) + if err != nil { + return FeeQuoterView{}, err + } + fq.AuthorizedCallers = make([]string, 0, len(authorizedCallers)) + for _, ac := range authorizedCallers { + fq.AuthorizedCallers = append(fq.AuthorizedCallers, ac.Hex()) + } + fq.ContractMetaData, err = types.NewContractMetaData(fqContract, fqContract.Address()) + if err != nil { + return FeeQuoterView{}, fmt.Errorf("metadata error for FeeQuoter: %w", err) + } + feeTokens, err := fqContract.GetFeeTokens(nil) + if err != nil { + return FeeQuoterView{}, err + } + fq.FeeTokens = make([]string, 0, len(feeTokens)) + for _, ft := range feeTokens { + fq.FeeTokens = append(fq.FeeTokens, ft.Hex()) + } + staticConfig, err := fqContract.GetStaticConfig(nil) + if err != nil { + return FeeQuoterView{}, err + } + fq.StaticConfig = FeeQuoterStaticConfig{ + MaxFeeJuelsPerMsg: staticConfig.MaxFeeJuelsPerMsg.String(), + LinkToken: staticConfig.LinkToken.Hex(), + TokenPriceStalenessThreshold: staticConfig.TokenPriceStalenessThreshold, + } + // find router contract in dependencies + fq.DestinationChainConfig = make(map[uint64]FeeQuoterDestChainConfig) + destSelectors, err := v1_2.GetRemoteChainSelectors(router) + if err != nil { + return FeeQuoterView{}, fmt.Errorf("view error for FeeQuoter: %w", err) + } + for _, destChainSelector := range destSelectors { + destChainConfig, err := fqContract.GetDestChainConfig(nil, destChainSelector) + if err != nil { + return FeeQuoterView{}, err + } + fq.DestinationChainConfig[destChainSelector] = FeeQuoterDestChainConfig{ + IsEnabled: destChainConfig.IsEnabled, + MaxNumberOfTokensPerMsg: destChainConfig.MaxNumberOfTokensPerMsg, + MaxDataBytes: destChainConfig.MaxDataBytes, + MaxPerMsgGasLimit: destChainConfig.MaxPerMsgGasLimit, + DestGasOverhead: destChainConfig.DestGasOverhead, + DestGasPerPayloadByte: destChainConfig.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: destChainConfig.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: destChainConfig.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: destChainConfig.DestDataAvailabilityMultiplierBps, + DefaultTokenFeeUSDCents: destChainConfig.DefaultTokenFeeUSDCents, + DefaultTokenDestGasOverhead: destChainConfig.DefaultTokenDestGasOverhead, + DefaultTxGasLimit: destChainConfig.DefaultTxGasLimit, + GasMultiplierWeiPerEth: destChainConfig.GasMultiplierWeiPerEth, + NetworkFeeUSDCents: destChainConfig.NetworkFeeUSDCents, + EnforceOutOfOrder: destChainConfig.EnforceOutOfOrder, + ChainFamilySelector: fmt.Sprintf("%x", destChainConfig.ChainFamilySelector), + } + } + fq.TokenPriceFeedConfig = make(map[string]FeeQuoterTokenPriceFeedConfig) + tokens, err := GetSupportedTokens(ta) + if err != nil { + return FeeQuoterView{}, fmt.Errorf("view error for FeeQuoter: %w", err) + } + for _, token := range tokens { + t, err := fqContract.GetTokenPriceFeedConfig(nil, token) + if err != nil { + return FeeQuoterView{}, err + } + fq.TokenPriceFeedConfig[token.String()] = FeeQuoterTokenPriceFeedConfig{ + DataFeedAddress: t.DataFeedAddress.Hex(), + TokenDecimals: t.TokenDecimals, + } + } + return fq, nil +} + +func GetSupportedTokens(taContract *token_admin_registry.TokenAdminRegistry) ([]common.Address, error) { + // TODO : include pagination CCIP-3416 + tokens, err := taContract.GetAllConfiguredTokens(nil, 0, 10) + if err != nil { + return nil, fmt.Errorf("failed to get tokens from token_admin_registry: %w", err) + } + return tokens, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_6/noncemanager.go b/integration-tests/deployment/ccip/view/v1_6/noncemanager.go new file mode 100644 index 00000000000..23df56c3d24 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_6/noncemanager.go @@ -0,0 +1,31 @@ +package v1_6 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" +) + +type NonceManagerView struct { + types.ContractMetaData + AuthorizedCallers []common.Address `json:"authorizedCallers,omitempty"` +} + +func GenerateNonceManagerView(nm *nonce_manager.NonceManager) (NonceManagerView, error) { + authorizedCallers, err := nm.GetAllAuthorizedCallers(nil) + if err != nil { + return NonceManagerView{}, fmt.Errorf("view error for nonce manager: %w", err) + } + nmMeta, err := types.NewContractMetaData(nm, nm.Address()) + if err != nil { + return NonceManagerView{}, fmt.Errorf("metadata error for nonce manager: %w", err) + } + return NonceManagerView{ + ContractMetaData: nmMeta, + // TODO: these can be resolved using an address book + AuthorizedCallers: authorizedCallers, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_6/offramp.go b/integration-tests/deployment/ccip/view/v1_6/offramp.go new file mode 100644 index 00000000000..38992cb3da1 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_6/offramp.go @@ -0,0 +1,64 @@ +package v1_6 + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + router1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +type OffRampView struct { + types.ContractMetaData + DynamicConfig offramp.OffRampDynamicConfig `json:"dynamicConfig"` + LatestPriceSequenceNumber uint64 `json:"latestPriceSequenceNumber"` + SourceChainConfigs map[uint64]offramp.OffRampSourceChainConfig `json:"sourceChainConfigs"` + StaticConfig offramp.OffRampStaticConfig `json:"staticConfig"` +} + +func GenerateOffRampView( + offRampContract *offramp.OffRamp, + routerContract *router1_2.Router, +) (OffRampView, error) { + tv, err := types.NewContractMetaData(offRampContract, offRampContract.Address()) + if err != nil { + return OffRampView{}, err + } + + dynamicConfig, err := offRampContract.GetDynamicConfig(nil) + if err != nil { + return OffRampView{}, fmt.Errorf("failed to get dynamic config: %w", err) + } + + latestPriceSequenceNumber, err := offRampContract.GetLatestPriceSequenceNumber(nil) + if err != nil { + return OffRampView{}, fmt.Errorf("failed to get latest price sequence number: %w", err) + } + + sourceChainSelectors, err := v1_2.GetRemoteChainSelectors(routerContract) + if err != nil { + return OffRampView{}, fmt.Errorf("failed to get source chain selectors: %w", err) + } + sourceChainConfigs := make(map[uint64]offramp.OffRampSourceChainConfig) + for _, sourceChainSelector := range sourceChainSelectors { + sourceChainConfig, err := offRampContract.GetSourceChainConfig(nil, sourceChainSelector) + if err != nil { + return OffRampView{}, fmt.Errorf("failed to get source chain config: %w", err) + } + sourceChainConfigs[sourceChainSelector] = sourceChainConfig + } + + staticConfig, err := offRampContract.GetStaticConfig(nil) + if err != nil { + return OffRampView{}, fmt.Errorf("failed to get static config: %w", err) + } + + return OffRampView{ + ContractMetaData: tv, + DynamicConfig: dynamicConfig, + LatestPriceSequenceNumber: latestPriceSequenceNumber, + SourceChainConfigs: sourceChainConfigs, + StaticConfig: staticConfig, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_6/onramp.go b/integration-tests/deployment/ccip/view/v1_6/onramp.go new file mode 100644 index 00000000000..131f110f2d3 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_6/onramp.go @@ -0,0 +1,107 @@ +package v1_6 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + router1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" +) + +type OnRampView struct { + types.ContractMetaData + DynamicConfig onramp.OnRampDynamicConfig `json:"dynamicConfig"` + StaticConfig onramp.OnRampStaticConfig `json:"staticConfig"` + Owner common.Address `json:"owner"` + SourceTokenToPool map[common.Address]common.Address `json:"sourceTokenToPool"` + DestChainSpecificData map[uint64]DestChainSpecificData `json:"destChainSpecificData"` +} + +type DestChainSpecificData struct { + AllowedSendersList []common.Address `json:"allowedSendersList"` + DestChainConfig onramp.GetDestChainConfig `json:"destChainConfig"` + ExpectedNextSeqNum uint64 `json:"expectedNextSeqNum"` + Router common.Address `json:"router"` +} + +func GenerateOnRampView( + onRampContract *onramp.OnRamp, + routerContract *router1_2.Router, + taContract *token_admin_registry.TokenAdminRegistry, +) (OnRampView, error) { + tv, err := types.NewContractMetaData(onRampContract, onRampContract.Address()) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get contract metadata: %w", err) + } + dynamicConfig, err := onRampContract.GetDynamicConfig(nil) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get dynamic config: %w", err) + } + + staticConfig, err := onRampContract.GetStaticConfig(nil) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get static config: %w", err) + } + + owner, err := onRampContract.Owner(nil) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get owner: %w", err) + } + // populate destChainSelectors from router + destChainSelectors, err := v1_2.GetRemoteChainSelectors(routerContract) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get destination selectors: %w", err) + } + // populate sourceTokens from token admin registry contract + sourceTokens, err := taContract.GetAllConfiguredTokens(nil, 0, 10) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get all configured tokens: %w", err) + } + sourceTokenToPool := make(map[common.Address]common.Address) + for _, sourceToken := range sourceTokens { + pool, err := onRampContract.GetPoolBySourceToken(nil, 0, sourceToken) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get pool by source token: %w", err) + } + sourceTokenToPool[sourceToken] = pool + } + + destChainSpecificData := make(map[uint64]DestChainSpecificData) + for _, destChainSelector := range destChainSelectors { + allowListInformation, err := onRampContract.GetAllowedSendersList(nil, destChainSelector) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get allowed senders list: %w", err) + } + destChainConfig, err := onRampContract.GetDestChainConfig(nil, destChainSelector) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get dest chain config: %w", err) + } + expectedNextSeqNum, err := onRampContract.GetExpectedNextSequenceNumber(nil, destChainSelector) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get expected next sequence number: %w", err) + } + router, err := onRampContract.GetRouter(nil, destChainSelector) + if err != nil { + return OnRampView{}, fmt.Errorf("failed to get router: %w", err) + } + destChainSpecificData[destChainSelector] = DestChainSpecificData{ + AllowedSendersList: allowListInformation.ConfiguredAddresses, + DestChainConfig: destChainConfig, + ExpectedNextSeqNum: expectedNextSeqNum, + Router: router, + } + } + + return OnRampView{ + ContractMetaData: tv, + DynamicConfig: dynamicConfig, + StaticConfig: staticConfig, + Owner: owner, + SourceTokenToPool: sourceTokenToPool, + DestChainSpecificData: destChainSpecificData, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_6/rmnremote.go b/integration-tests/deployment/ccip/view/v1_6/rmnremote.go new file mode 100644 index 00000000000..bf0fefaa2eb --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_6/rmnremote.go @@ -0,0 +1,54 @@ +package v1_6 + +import ( + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" +) + +type RMNRemoteView struct { + types.ContractMetaData + IsCursed bool `json:"isCursed"` + Config RMNRemoteVersionedConfig `json:"config,omitempty"` +} + +type RMNRemoteVersionedConfig struct { + Version uint32 `json:"version"` + Signers []RMNRemoteSigner `json:"signers"` + MinSigners uint64 `json:"minSigners"` +} + +type RMNRemoteSigner struct { + OnchainPublicKey string `json:"onchain_public_key"` + NodeIndex uint64 `json:"node_index"` +} + +func GenerateRMNRemoteView(rmnReader *rmn_remote.RMNRemote) (RMNRemoteView, error) { + tv, err := types.NewContractMetaData(rmnReader, rmnReader.Address()) + if err != nil { + return RMNRemoteView{}, err + } + config, err := rmnReader.GetVersionedConfig(nil) + if err != nil { + return RMNRemoteView{}, err + } + rmnConfig := RMNRemoteVersionedConfig{ + Version: config.Version, + Signers: make([]RMNRemoteSigner, 0, len(config.Config.Signers)), + MinSigners: config.Config.MinSigners, + } + for _, signer := range config.Config.Signers { + rmnConfig.Signers = append(rmnConfig.Signers, RMNRemoteSigner{ + OnchainPublicKey: signer.OnchainPublicKey.Hex(), + NodeIndex: signer.NodeIndex, + }) + } + isCursed, err := rmnReader.IsCursed0(nil) + if err != nil { + return RMNRemoteView{}, err + } + return RMNRemoteView{ + ContractMetaData: tv, + IsCursed: isCursed, + Config: rmnConfig, + }, nil +} diff --git a/integration-tests/deployment/changeset.go b/integration-tests/deployment/changeset.go new file mode 100644 index 00000000000..6473bc1320a --- /dev/null +++ b/integration-tests/deployment/changeset.go @@ -0,0 +1,12 @@ +package deployment + +import ( + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" +) + +// Services as input to CI/Async tasks +type ChangesetOutput struct { + JobSpecs map[string][]string + Proposals []timelock.MCMSWithTimelockProposal + AddressBook AddressBook +} diff --git a/integration-tests/deployment/clo/don_nodeset.go b/integration-tests/deployment/clo/don_nodeset.go new file mode 100644 index 00000000000..5962b6f4ba8 --- /dev/null +++ b/integration-tests/deployment/clo/don_nodeset.go @@ -0,0 +1,67 @@ +package clo + +import ( + "strings" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/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/integration-tests/deployment/clo/don_nodeset_test.go b/integration-tests/deployment/clo/don_nodeset_test.go new file mode 100644 index 00000000000..6e8c64060df --- /dev/null +++ b/integration-tests/deployment/clo/don_nodeset_test.go @@ -0,0 +1,104 @@ +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/integration-tests/deployment/clo" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/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/integration-tests/deployment/clo/env.go b/integration-tests/deployment/clo/env.go new file mode 100644 index 00000000000..302f9794eaf --- /dev/null +++ b/integration-tests/deployment/clo/env.go @@ -0,0 +1,136 @@ +package clo + +import ( + "strconv" + "testing" + + "github.com/test-go/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/clo/models" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" +) + +type DonEnvConfig struct { + DonName string + Chains map[uint64]deployment.Chain + Logger logger.Logger + Nops []*models.NodeOperator +} + +func NewDonEnv(t *testing.T, cfg DonEnvConfig) *deployment.Environment { + // no bootstraps in the don as far as capabilities registry is concerned + for _, nop := range cfg.Nops { + for _, node := range nop.Nodes { + for _, chain := range node.ChainConfigs { + if chain.Ocr2Config.IsBootstrap { + t.Fatalf("Don nodes should not be bootstraps nop %s node %s chain %s", nop.ID, node.ID, chain.Network.ChainID) + } + } + } + } + out := deployment.Environment{ + Name: cfg.DonName, + Offchain: NewJobClient(cfg.Logger, cfg.Nops), + NodeIDs: make([]string, 0), + Chains: cfg.Chains, + Logger: cfg.Logger, + } + // assume that all the nodes in the provided input nops are part of the don + for _, nop := range cfg.Nops { + for _, node := range nop.Nodes { + out.NodeIDs = append(out.NodeIDs, node.ID) + } + } + + return &out +} + +func NewDonEnvWithMemoryChains(t *testing.T, cfg DonEnvConfig, ignore func(*models.NodeChainConfig) bool) *deployment.Environment { + e := NewDonEnv(t, cfg) + // overwrite the chains with memory chains + chains := make(map[uint64]struct{}) + for _, nop := range cfg.Nops { + for _, node := range nop.Nodes { + for _, chain := range node.ChainConfigs { + if ignore(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 cs []uint64 + for c := range chains { + cs = append(cs, c) + } + memoryChains := memory.NewMemoryChainsWithChainIDs(t, cs) + e.Chains = memoryChains + return e +} + +// MultiDonEnvironment is a single logical deployment environment (like dev, testnet, prod,...). +// It represents the idea that different nodesets host different capabilities. +// Each element in the DonEnv is a logical set of nodes that host the same capabilities. +// This model allows us to reuse the existing Environment abstraction while supporting multiple nodesets at +// expense of slightly abusing the original abstraction. Specifically, the abuse is that +// each Environment in the DonToEnv map is a subset of the target deployment environment. +// One element cannot represent dev and other testnet for example. +type MultiDonEnvironment struct { + donToEnv map[string]*deployment.Environment + Logger logger.Logger + // hacky but temporary to transition to Environment abstraction. set by New + Chains map[uint64]deployment.Chain +} + +func (mde MultiDonEnvironment) Flatten(name string) *deployment.Environment { + return &deployment.Environment{ + Name: name, + Chains: mde.Chains, + Logger: mde.Logger, + + // TODO: KS-460 integrate with the clo offchain client impl + // may need to extend the Environment abstraction use maps rather than slices for Nodes + // somehow we need to capture the fact that each nodes belong to nodesets which have different capabilities + // purposely nil to catch misuse until we do that work + Offchain: nil, + NodeIDs: nil, + } +} + +func newMultiDonEnvironment(logger logger.Logger, donToEnv map[string]*deployment.Environment) *MultiDonEnvironment { + chains := make(map[uint64]deployment.Chain) + for _, env := range donToEnv { + for sel, chain := range env.Chains { + if _, exists := chains[sel]; !exists { + chains[sel] = chain + } + } + } + return &MultiDonEnvironment{ + donToEnv: donToEnv, + Logger: logger, + Chains: chains, + } +} + +func NewTestEnv(t *testing.T, lggr logger.Logger, dons map[string]*deployment.Environment) *MultiDonEnvironment { + for _, don := range dons { + //don := don + seen := make(map[uint64]deployment.Chain) + // ensure that generated chains are the same for all environments. this ensures that he in memory representation + // points to a common object for all dons given the same selector. + for sel, chain := range don.Chains { + c, exists := seen[sel] + if exists { + don.Chains[sel] = c + } else { + seen[sel] = chain + } + } + } + return newMultiDonEnvironment(lggr, dons) +} diff --git a/integration-tests/deployment/clo/models/models.go b/integration-tests/deployment/clo/models/models.go new file mode 100644 index 00000000000..1d33cff84d5 --- /dev/null +++ b/integration-tests/deployment/clo/models/models.go @@ -0,0 +1,28 @@ +// 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/integration-tests/deployment/clo/models/models_gen.go b/integration-tests/deployment/clo/models/models_gen.go new file mode 100644 index 00000000000..baea1dbcbed --- /dev/null +++ b/integration-tests/deployment/clo/models/models_gen.go @@ -0,0 +1,3653 @@ +// 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 Name 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 Name 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 Name 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 Name 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 Name 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/integration-tests/deployment/clo/offchain_client_impl.go b/integration-tests/deployment/clo/offchain_client_impl.go new file mode 100644 index 00000000000..f59a918a41a --- /dev/null +++ b/integration-tests/deployment/clo/offchain_client_impl.go @@ -0,0 +1,213 @@ +package clo + +import ( + "context" + + "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/integration-tests/deployment/clo/models" +) + +type JobClient struct { + NodeOperators []*models.NodeOperator `json:"nodeOperators"` + nodesByID map[string]*models.Node + lggr logger.Logger +} + +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) { + //TODO CCIP-3108 + var fiterIds map[string]struct{} + include := func(id string) bool { + if in.Filter == nil || len(in.Filter.Ids) == 0 { + return true + } + // lazy init + if len(fiterIds) == 0 { + for _, id := range in.Filter.Ids { + fiterIds[id] = struct{}{} + } + } + _, ok := fiterIds[id] + return ok + } + var nodes []*nodev1.Node + for _, nop := range j.NodeOperators { + for _, n := range nop.Nodes { + if include(n.ID) { + nodes = append(nodes, &nodev1.Node{ + Id: n.ID, + Name: n.Name, + PublicKey: *n.PublicKey, // is this the correct val? + IsEnabled: n.Enabled, + IsConnected: n.Connected, + }) + } + } + } + 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"` +} + +func NewJobClient(lggr logger.Logger, nops []*models.NodeOperator) *JobClient { + c := &JobClient{ + NodeOperators: nops, + nodesByID: make(map[string]*models.Node), + lggr: lggr, + } + for _, nop := range nops { + 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 { + return &nodev1.ChainConfig{ + Chain: &nodev1.Chain{ + Id: ccfg.Network.ChainID, + Type: nodev1.ChainType_CHAIN_TYPE_EVM, // TODO: write conversion func from clo to jd tyes + }, + 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/integration-tests/deployment/clo/offchain_client_impl_test.go b/integration-tests/deployment/clo/offchain_client_impl_test.go new file mode 100644 index 00000000000..640721bb486 --- /dev/null +++ b/integration-tests/deployment/clo/offchain_client_impl_test.go @@ -0,0 +1,582 @@ +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/integration-tests/deployment/clo" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/clo/models" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var testNops = ` +[ + { + "id": "67", + "name": "Chainlink Keystone Node Operator 9", + "nodes": [ + { + "id": "780", + "name": "Chainlink Sepolia Prod Keystone One 9", + "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + "connected": true, + "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, + "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, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ] + }, + { + "id": "1000", + "name": "Chainlink Sepolia Prod Keystone One 1000", + "publicKey": "1000101e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58641000", + "connected": true, + "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 + } + 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, + }, + }, + }, + }, + { + 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, + }, + { + Id: "781", + Name: "Chainlink Sepolia Prod Keystone One 8", + PublicKey: "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", + IsConnected: true, + }, + }, + }, + }, + { + 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, + }, + { + Id: "1000", + Name: "Chainlink Sepolia Prod Keystone One 1000", + PublicKey: "1000101e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58641000", + IsConnected: true, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + j := clo.NewJobClient(lggr, 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, 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/integration-tests/deployment/clo/testdata/keystone_nops.json b/integration-tests/deployment/clo/testdata/keystone_nops.json new file mode 100644 index 00000000000..679a85935a4 --- /dev/null +++ b/integration-tests/deployment/clo/testdata/keystone_nops.json @@ -0,0 +1,3162 @@ +[ + { + "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/integration-tests/deployment/devenv/.sample.env b/integration-tests/deployment/devenv/.sample.env new file mode 100644 index 00000000000..ddf0b97e9a9 --- /dev/null +++ b/integration-tests/deployment/devenv/.sample.env @@ -0,0 +1,28 @@ +# set the following if you don't want the test to tear down the docker containers after test run is finished +# TESTCONTAINERS_RYUK_DISABLED=true + +E2E_JD_IMAGE= +E2E_JD_VERSION= + +E2E_TEST_CHAINLINK_IMAGE=public.ecr.aws/w0i8p0z9/chainlink-ccip +E2E_TEST_CHAINLINK_VERSION=2.14.0-ccip1.5.0 + +# RPC Configuration +E2E_TEST_SEPOLIA_WALLET_KEY= +E2E_TEST_SEPOLIA_RPC_HTTP_URL_1= +E2E_TEST_SEPOLIA_RPC_HTTP_URL_2= +E2E_TEST_SEPOLIA_RPC_WS_URL_1= +E2E_TEST_SEPOLIA_RPC_WS_URL_2= + +E2E_TEST_AVALANCHE_FUJI_WALLET_KEY= +E2E_TEST_AVALANCHE_FUJI_RPC_HTTP_URL_1= +E2E_TEST_AVALANCHE_FUJI_RPC_HTTP_URL_2= +E2E_TEST_AVALANCHE_FUJI_RPC_WS_URL_1= +E2E_TEST_AVALANCHE_FUJI_RPC_WS_URL_2= + +E2E_TEST_BSC_TESTNET_WALLET_KEY= +E2E_TEST_BSC_TESTNET_RPC_HTTP_URL_1= +E2E_TEST_BSC_TESTNET_RPC_HTTP_URL_2= +E2E_TEST_BSC_TESTNET_RPC_WS_URL_1= +E2E_TEST_BSC_TESTNET_RPC_WS_URL_2= + diff --git a/integration-tests/deployment/devenv/README.md b/integration-tests/deployment/devenv/README.md new file mode 100644 index 00000000000..cb2b5cb8d6f --- /dev/null +++ b/integration-tests/deployment/devenv/README.md @@ -0,0 +1,49 @@ +## Overview + +This package is used to create ephemeral environment for local/CI testing. +It sets up an environment with local Docker containers running Chainlink nodes and a job distributor. +It can either create new simulated private Ethereum network containers or connect to existing testnets/mainnets. + +### Run Tests with Devenv + +The tests created with this environment are run as [end-to-end integration smoke tests](../../smoke). + +Pre-requisites: +- Docker +- Pull access for chainlink and job-distributor images + +#### Setting Up Testconfig with Simulated Private Ethereum Network + +To run tests (e.g., [ccip-test](../../smoke/ccip_test.go)), +you need to set up the testconfig following the [testconfig setup instructions](../../testconfig/README.md). +The testconfig specifies the details of the different configurations to set up the environment and run the tests. +Generally, tests are run with the [default](../../testconfig/default.toml) config unless overridden by product-specific config. +For example, the [ccip-test](../../smoke/ccip_test.go) uses [ccip.toml](../../testconfig/ccip/ccip.toml) to specify +CCIP-specific test environment details. + +There are additional secret configuration parameters required by the `devenv` environment that are not stored in the testconfig. +These are read from environment variables. For example, Chainlink image, Job-Distributor image, etc. +All such environment variables are listed in the [sample.env](./.sample.env) file. +You can create a `.env` file in the same directory of the test and set the required environment variables. + +#### Setting Up Testconfig for Running Tests with Existing Testnet/Mainnet + +To run tests with existing testnet/mainnet, set up the testconfig with the details of the testnet/mainnet networks. +Following the integration-test [testconfig framework](../../testconfig/README.md#configuration-and-overrides), +create a new `overrides.toml` file with testnet/mainnet network details and place it under any location in the `integration-tests` directory. +By default, tests are run with private Ethereum network containers set up in the same Docker network as +the Chainlink nodes and job distributor. To run tests against existing testnet/mainnet, +set the `selected_network` field in the testconfig with the specific network names. + +For example, if running [ccip-smoke](../../smoke/ccip_test.go) tests with Sepolia, Avax, and Binance testnets, +copy the contents of [sepolia_avax_binance.toml](../../testconfig/ccip/overrides/sepolia_avax_binance.toml) +to the `overrides.toml` file. + +Before running the test, ensure that RPC and wallet secrets are set as environment variables. +Refer to the environment variables pattern in the [sample.env](./.sample.env) file to +provide necessary secrets applicable to the network you are running the tests against: +- `E2E_TEST__WALLET_KEY_` +- `E2E_TEST__RPC_HTTP_URL_` +- `E2E_TEST__RPC_WS_URL_` + +Now you are all set to run the tests with the existing testnet/mainnet. \ No newline at end of file diff --git a/integration-tests/deployment/devenv/build_env.go b/integration-tests/deployment/devenv/build_env.go new file mode 100644 index 00000000000..c564c4e068a --- /dev/null +++ b/integration-tests/deployment/devenv/build_env.go @@ -0,0 +1,373 @@ +package devenv + +import ( + "fmt" + "math/big" + "os" + "strconv" + "testing" + + "github.com/AlekSi/pointer" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/pkg/errors" + "github.com/rs/zerolog" + chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + "github.com/subosito/gotenv" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc/credentials/insecure" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + + "github.com/smartcontractkit/chainlink/integration-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + clclient "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" +) + +// CreateDockerEnv creates a new test environment with simulated private ethereum networks and job distributor +// It returns the EnvironmentConfig which holds the chain config and JD config +// The test environment is then used to start chainlink nodes +func CreateDockerEnv(t *testing.T) ( + *EnvironmentConfig, + *test_env.CLClusterTestEnv, + tc.TestConfig, +) { + if _, err := os.Stat(".env"); err == nil || !os.IsNotExist(err) { + require.NoError(t, gotenv.Load(".env"), "Error loading .env file") + } + + cfg, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.CCIP) + require.NoError(t, err, "Error getting config") + + evmNetworks := networks.MustGetSelectedNetworkConfig(cfg.GetNetworkConfig()) + + // find out if the selected networks are provided with PrivateEthereumNetworks configs + // if yes, PrivateEthereumNetworkConfig will be used to create simulated private ethereum networks in docker environment + var privateEthereumNetworks []*ctf_config.EthereumNetworkConfig + for _, name := range cfg.GetNetworkConfig().SelectedNetworks { + if network, exists := cfg.CCIP.PrivateEthereumNetworks[name]; exists { + privateEthereumNetworks = append(privateEthereumNetworks, network) + } + } + + builder := test_env.NewCLTestEnvBuilder(). + WithTestConfig(&cfg). + WithTestInstance(t). + WithJobDistributor(cfg.CCIP.JobDistributorConfig). + WithStandardCleanup() + + // if private ethereum networks are provided, we will use them to create the test environment + // otherwise we will use the network URLs provided in the network config + if len(privateEthereumNetworks) > 0 { + builder = builder.WithPrivateEthereumNetworks(privateEthereumNetworks) + } + env, err := builder.Build() + require.NoError(t, err, "Error building test environment") + + // we need to update the URLs for the simulated networks to the private chain RPCs in the docker test environment + // so that the chainlink nodes and rmn nodes can internally connect to the chain + env.EVMNetworks = []*blockchain.EVMNetwork{} + for i, net := range evmNetworks { + // if network is simulated, update the URLs with private chain RPCs in the docker test environment + // so that nodes can internally connect to the chain + if net.Simulated { + rpcProvider, err := env.GetRpcProvider(net.ChainID) + require.NoError(t, err, "Error getting rpc provider") + evmNetworks[i].HTTPURLs = rpcProvider.PrivateHttpUrls() + evmNetworks[i].URLs = rpcProvider.PrivateWsUrsl() + } + env.EVMNetworks = append(env.EVMNetworks, &evmNetworks[i]) + } + + chains := CreateChainConfigFromNetworks(t, env, privateEthereumNetworks, cfg.GetNetworkConfig()) + + jdConfig := JDConfig{ + GRPC: cfg.CCIP.JobDistributorConfig.GetJDGRPC(), + WSRPC: cfg.CCIP.JobDistributorConfig.GetJDWSRPC(), + } + // TODO : move this as a part of test_env setup with an input in testconfig + // if JD is not provided, we will spin up a new JD + if jdConfig.GRPC == "" || jdConfig.WSRPC == "" { + jd := env.JobDistributor + require.NotNil(t, jd, "JD is not found in test environment") + jdConfig = JDConfig{ + GRPC: jd.Grpc, + // we will use internal wsrpc for nodes on same docker network to connect to JD + WSRPC: jd.InternalWSRPC, + Creds: insecure.NewCredentials(), + } + } + require.NotEmpty(t, jdConfig, "JD config is empty") + + homeChainSelector, err := cfg.CCIP.GetHomeChainSelector(evmNetworks) + require.NoError(t, err, "Error getting home chain selector") + feedChainSelector, err := cfg.CCIP.GetFeedChainSelector(evmNetworks) + require.NoError(t, err, "Error getting feed chain selector") + + return &EnvironmentConfig{ + Chains: chains, + JDConfig: jdConfig, + HomeChainSelector: homeChainSelector, + FeedChainSelector: feedChainSelector, + }, env, cfg +} + +// StartChainlinkNodes starts docker containers for chainlink nodes on the existing test environment based on provided test config +// Once the nodes starts, it updates the devenv EnvironmentConfig with the node info +// which includes chainlink API URL, email, password and internal IP +func StartChainlinkNodes( + t *testing.T, + envConfig *EnvironmentConfig, + registryConfig deployment.CapabilityRegistryConfig, + env *test_env.CLClusterTestEnv, + cfg tc.TestConfig, +) error { + var evmNetworks []blockchain.EVMNetwork + for i := range env.EVMNetworks { + evmNetworks = append(evmNetworks, *env.EVMNetworks[i]) + } + noOfNodes := pointer.GetInt(cfg.CCIP.CLNode.NoOfPluginNodes) + pointer.GetInt(cfg.CCIP.CLNode.NoOfBootstraps) + if env.ClCluster == nil { + env.ClCluster = &test_env.ClCluster{} + } + var nodeInfo []NodeInfo + for i := 1; i <= noOfNodes; i++ { + if i <= pointer.GetInt(cfg.CCIP.CLNode.NoOfBootstraps) { + nodeInfo = append(nodeInfo, NodeInfo{ + IsBootstrap: true, + Name: fmt.Sprintf("bootstrap-%d", i), + // TODO : make this configurable + P2PPort: "6690", + }) + } else { + nodeInfo = append(nodeInfo, NodeInfo{ + IsBootstrap: false, + Name: fmt.Sprintf("node-%d", i-1), + // TODO : make this configurable + P2PPort: "6690", + }) + } + toml, _, err := testsetups.SetNodeConfig( + evmNetworks, + cfg.NodeConfig.BaseConfigTOML, + cfg.NodeConfig.CommonChainConfigTOML, + cfg.NodeConfig.ChainConfigTOMLByChainID, + ) + + toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(relay.NetworkEVM) + 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 + } + ccipNode, err := test_env.NewClNode( + []string{env.DockerNetwork.Name}, + pointer.GetString(cfg.GetChainlinkImageConfig().Image), + pointer.GetString(cfg.GetChainlinkImageConfig().Version), + toml, + env.LogStream, + test_env.WithPgDBOptions( + ctftestenv.WithPostgresImageVersion(pointer.GetString(cfg.GetChainlinkImageConfig().PostgresVersion)), + ), + ) + if err != nil { + return err + } + ccipNode.SetTestLogger(t) + env.ClCluster.Nodes = append(env.ClCluster.Nodes, ccipNode) + } + err := env.ClCluster.Start() + if err != nil { + return err + } + for i, n := range env.ClCluster.Nodes { + nodeInfo[i].CLConfig = clclient.ChainlinkConfig{ + URL: n.API.URL(), + Email: n.UserEmail, + Password: n.UserPassword, + InternalIP: n.API.InternalIP(), + } + } + if envConfig == nil { + envConfig = &EnvironmentConfig{} + } + envConfig.JDConfig.nodeInfo = nodeInfo + return nil +} + +// FundNodes sends funds to the chainlink nodes based on the provided test config +// It also sets up a clean-up function to return the funds back to the deployer account once the test is done +// It assumes that the chainlink nodes are already started and the account addresses for all chains are available +func FundNodes(t *testing.T, lggr zerolog.Logger, env *test_env.CLClusterTestEnv, cfg tc.TestConfig, nodes []Node) { + evmNetworks := networks.MustGetSelectedNetworkConfig(cfg.GetNetworkConfig()) + for i, net := range evmNetworks { + // if network is simulated, update the URLs with deployed chain RPCs in the docker test environment + if net.Simulated { + rpcProvider, err := env.GetRpcProvider(net.ChainID) + require.NoError(t, err, "Error getting rpc provider") + evmNetworks[i].HTTPURLs = rpcProvider.PublicHttpUrls() + evmNetworks[i].URLs = rpcProvider.PublicWsUrls() + } + } + t.Cleanup(func() { + for i := range evmNetworks { + // if simulated no need for balance return + if evmNetworks[i].Simulated { + continue + } + evmNetwork := evmNetworks[i] + sethClient, err := utils.TestAwareSethClient(t, cfg, &evmNetwork) + require.NoError(t, err, "Error getting seth client for network %s", evmNetwork.Name) + require.Greater(t, len(sethClient.PrivateKeys), 0, seth.ErrNoKeyLoaded) + var keyExporters []contracts.ChainlinkKeyExporter + for j := range nodes { + node := nodes[j] + keyExporters = append(keyExporters, &node) + } + if err := actions.ReturnFundsFromKeyExporterNodes(lggr, sethClient, keyExporters); err != nil { + lggr.Error().Err(err).Str("Network", evmNetwork.Name). + Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + + "Environment is left running so you can try manually!") + } + } + }) + for i := range evmNetworks { + evmNetwork := evmNetworks[i] + sethClient, err := utils.TestAwareSethClient(t, cfg, &evmNetwork) + require.NoError(t, err, "Error getting seth client for network %s", evmNetwork.Name) + require.Greater(t, len(sethClient.PrivateKeys), 0, seth.ErrNoKeyLoaded) + privateKey := sethClient.PrivateKeys[0] + for _, node := range nodes { + nodeAddr, ok := node.AccountAddr[uint64(evmNetwork.ChainID)] + require.True(t, ok, "Account address not found for chain %d", evmNetwork.ChainID) + fromAddress, err := actions.PrivateKeyToAddress(privateKey) + require.NoError(t, err, "Error getting address from private key") + amount := big.NewFloat(pointer.GetFloat64(cfg.Common.ChainlinkNodeFunding)) + toAddr := common.HexToAddress(nodeAddr) + receipt, err := actions.SendFunds(lggr, sethClient, actions.FundsToSendPayload{ + ToAddress: toAddr, + Amount: conversions.EtherToWei(amount), + PrivateKey: privateKey, + }) + require.NoError(t, err, "Error sending funds to node %s", node.Name) + require.NotNil(t, receipt, "Receipt is nil") + txHash := "(none)" + if receipt != nil { + txHash = receipt.TxHash.String() + } + lggr.Info(). + Str("From", fromAddress.Hex()). + Str("To", toAddr.String()). + Str("TxHash", txHash). + Str("Amount", amount.String()). + Msg("Funded Chainlink node") + } + } +} + +// CreateChainConfigFromNetworks creates a list of ChainConfig from the network config provided in test config. +// It either creates it from the private ethereum networks created by the test environment or from the +// network URLs provided in the network config ( if the network is a live testnet). +// It uses the private keys from the network config to create the deployer key for each chain. +func CreateChainConfigFromNetworks( + t *testing.T, + env *test_env.CLClusterTestEnv, + privateEthereumNetworks []*ctf_config.EthereumNetworkConfig, + networkConfig *ctf_config.NetworkConfig, +) []ChainConfig { + evmNetworks := networks.MustGetSelectedNetworkConfig(networkConfig) + networkPvtKeys := make(map[int64]string) + for _, net := range evmNetworks { + require.Greater(t, len(net.PrivateKeys), 0, "No private keys found for network") + networkPvtKeys[net.ChainID] = net.PrivateKeys[0] + } + var chains []ChainConfig + // if private ethereum networks are not provided, we will create chains from the network URLs + if len(privateEthereumNetworks) == 0 { + for _, net := range evmNetworks { + chainId := net.ChainID + chainName, err := chainselectors.NameFromChainId(uint64(chainId)) + require.NoError(t, err, "Error getting chain name") + pvtKeyStr, exists := networkPvtKeys[chainId] + require.Truef(t, exists, "Private key not found for chain id %d", chainId) + pvtKey, err := crypto.HexToECDSA(pvtKeyStr) + require.NoError(t, err) + deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(chainId)) + require.NoError(t, err) + deployer.GasLimit = net.DefaultGasLimit + chains = append(chains, ChainConfig{ + ChainID: uint64(chainId), + ChainName: chainName, + ChainType: "EVM", + WSRPCs: net.URLs, + HTTPRPCs: net.HTTPURLs, + DeployerKey: deployer, + }) + } + return chains + } + for _, networkCfg := range privateEthereumNetworks { + chainId := networkCfg.EthereumChainConfig.ChainID + chainName, err := chainselectors.NameFromChainId(uint64(chainId)) + require.NoError(t, err, "Error getting chain name") + rpcProvider, err := env.GetRpcProvider(int64(chainId)) + require.NoError(t, err, "Error getting rpc provider") + pvtKeyStr, exists := networkPvtKeys[int64(chainId)] + require.Truef(t, exists, "Private key not found for chain id %d", chainId) + pvtKey, err := crypto.HexToECDSA(pvtKeyStr) + require.NoError(t, err) + deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(int64(chainId))) + require.NoError(t, err) + chains = append(chains, ChainConfig{ + ChainID: uint64(chainId), + ChainName: chainName, + ChainType: EVMChainType, + WSRPCs: rpcProvider.PublicWsUrls(), + HTTPRPCs: rpcProvider.PublicHttpUrls(), + DeployerKey: deployer, + }) + } + return chains +} + +// RestartChainlinkNodes restarts the chainlink nodes in the test environment +func RestartChainlinkNodes(t *testing.T, env *test_env.CLClusterTestEnv) error { + errGrp := errgroup.Group{} + if env == nil || env.ClCluster == nil { + return errors.Wrap(errors.New("no testenv or clcluster found "), "error restarting node") + } + for _, n := range env.ClCluster.Nodes { + n := n + errGrp.Go(func() error { + if err := n.Container.Terminate(testcontext.Get(t)); err != nil { + return err + } + err := n.RestartContainer() + if err != nil { + return err + } + return nil + }) + + } + return errGrp.Wait() +} diff --git a/integration-tests/deployment/devenv/chain.go b/integration-tests/deployment/devenv/chain.go new file mode 100644 index 00000000000..bf58aff6e37 --- /dev/null +++ b/integration-tests/deployment/devenv/chain.go @@ -0,0 +1,88 @@ +package devenv + +import ( + "context" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + chainselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" +) + +const ( + EVMChainType = "EVM" +) + +// ChainConfig holds the configuration for a with a deployer key which can be used to send transactions to the chain. +type ChainConfig struct { + ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains + ChainName string // name of the chain populated from chainselector repo + ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc + WSRPCs []string // websocket rpcs to connect to the chain + HTTPRPCs []string // http rpcs to connect to the chain + DeployerKey *bind.TransactOpts // key to send transactions to the chain +} + +func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployment.Chain, error) { + chains := make(map[uint64]deployment.Chain) + for _, chainCfg := range configs { + selector, err := chainselectors.SelectorFromChainId(chainCfg.ChainID) + if err != nil { + return nil, fmt.Errorf("failed to get selector from chain id %d: %w", chainCfg.ChainID, err) + } + // TODO : better client handling + var ec *ethclient.Client + for _, rpc := range chainCfg.WSRPCs { + ec, err = ethclient.Dial(rpc) + if err != nil { + logger.Warnf("failed to dial ws rpc %s", rpc) + continue + } + logger.Infof("connected to ws rpc %s", rpc) + break + } + if ec == nil { + return nil, fmt.Errorf("failed to connect to chain %s", chainCfg.ChainName) + } + chains[selector] = deployment.Chain{ + Selector: selector, + Client: ec, + DeployerKey: chainCfg.DeployerKey, + Confirm: func(tx *types.Transaction) (uint64, error) { + var blockNumber uint64 + if tx == nil { + return 0, fmt.Errorf("tx was nil, nothing to confirm") + } + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) + defer cancel() + chainId, err := ec.ChainID(ctx) + if err != nil { + return blockNumber, fmt.Errorf("failed to get chain id: %w", err) + } + receipt, err := bind.WaitMined(ctx, ec, tx) + if err != nil { + return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %d: %w", chainId, err) + } + if receipt == nil { + return blockNumber, fmt.Errorf("receipt was nil for tx %s", tx.Hash().Hex()) + } + blockNumber = receipt.BlockNumber.Uint64() + if receipt.Status == 0 { + errReason, err := deployment.GetErrorReasonFromTx(ec, chainCfg.DeployerKey.From, *tx, receipt) + if err == nil && errReason != "" { + return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) + } + return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) + } + return blockNumber, nil + }, + } + } + return chains, nil +} diff --git a/integration-tests/deployment/devenv/don.go b/integration-tests/deployment/devenv/don.go new file mode 100644 index 00000000000..88bd26b8a7a --- /dev/null +++ b/integration-tests/deployment/devenv/don.go @@ -0,0 +1,384 @@ +package devenv + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + "github.com/AlekSi/pointer" + "github.com/hashicorp/go-multierror" + "github.com/rs/zerolog" + "github.com/sethvargo/go-retry" + chainsel "github.com/smartcontractkit/chain-selectors" + + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + clclient "github.com/smartcontractkit/chainlink/integration-tests/client" + + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + + "github.com/smartcontractkit/chainlink/integration-tests/web/sdk/client" +) + +const ( + NodeLabelKeyType = "type" + NodeLabelValueBootstrap = "bootstrap" + NodeLabelValuePlugin = "plugin" +) + +// NodeInfo holds the information required to create a node +type NodeInfo struct { + CLConfig clclient.ChainlinkConfig // config to connect to chainlink node via API + P2PPort string // port for P2P communication + IsBootstrap bool // denotes if the node is a bootstrap node + Name string // name of the node, used to identify the node, helpful in logs + AdminAddr string // admin address to send payments to, applicable only for non-bootstrap nodes + MultiAddr string // multi address denoting node's FQN (needed for deriving P2PBootstrappers in OCR), applicable only for bootstrap nodes +} + +type DON struct { + Nodes []Node +} + +func (don *DON) PluginNodes() []Node { + var pluginNodes []Node + for _, node := range don.Nodes { + for _, label := range node.labels { + if label.Key == NodeLabelKeyType && pointer.GetString(label.Value) == NodeLabelValuePlugin { + pluginNodes = append(pluginNodes, node) + } + } + } + return pluginNodes +} + +// ReplayAllLogs replays all logs for the chains on all nodes for given block numbers for each chain +func (don *DON) ReplayAllLogs(blockbyChain map[uint64]uint64) error { + for _, node := range don.Nodes { + if err := node.ReplayLogs(blockbyChain); err != nil { + return err + } + } + return nil +} + +func (don *DON) NodeIds() []string { + var nodeIds []string + for _, node := range don.Nodes { + nodeIds = append(nodeIds, node.NodeId) + } + return nodeIds +} + +func (don *DON) CreateSupportedChains(ctx context.Context, chains []ChainConfig, jd JobDistributor) error { + var err error + for i := range don.Nodes { + node := &don.Nodes[i] + var jdChains []JDChainConfigInput + for _, chain := range chains { + jdChains = append(jdChains, JDChainConfigInput{ + ChainID: chain.ChainID, + ChainType: chain.ChainType, + }) + } + if err1 := node.CreateCCIPOCRSupportedChains(ctx, jdChains, jd); err1 != nil { + err = multierror.Append(err, err1) + } + don.Nodes[i] = *node + } + return err +} + +// NewRegisteredDON creates a DON with the given node info, registers the nodes with the job distributor +// and sets up the job distributor in the nodes +func NewRegisteredDON(ctx context.Context, nodeInfo []NodeInfo, jd JobDistributor) (*DON, error) { + don := &DON{ + Nodes: make([]Node, 0), + } + for i, info := range nodeInfo { + if info.Name == "" { + info.Name = fmt.Sprintf("node-%d", i) + } + node, err := NewNode(info) + if err != nil { + return nil, fmt.Errorf("failed to create node %d: %w", i, err) + } + // node Labels so that it's easier to query them + if info.IsBootstrap { + // create multi address for OCR2, applicable only for bootstrap nodes + if info.MultiAddr == "" { + node.multiAddr = fmt.Sprintf("%s:%s", info.CLConfig.InternalIP, info.P2PPort) + } else { + node.multiAddr = info.MultiAddr + } + // no need to set admin address for bootstrap nodes, as there will be no payment + node.adminAddr = "" + node.labels = append(node.labels, &ptypes.Label{ + Key: NodeLabelKeyType, + Value: pointer.ToString(NodeLabelValueBootstrap), + }) + } else { + // multi address is not applicable for non-bootstrap nodes + // explicitly set it to empty string to denote that + node.multiAddr = "" + node.labels = append(node.labels, &ptypes.Label{ + Key: NodeLabelKeyType, + Value: pointer.ToString(NodeLabelValuePlugin), + }) + } + // Set up Job distributor in node and register node with the job distributor + err = node.SetUpAndLinkJobDistributor(ctx, jd) + if err != nil { + return nil, fmt.Errorf("failed to set up job distributor in node %s: %w", info.Name, err) + } + + don.Nodes = append(don.Nodes, *node) + } + return don, nil +} + +func NewNode(nodeInfo NodeInfo) (*Node, error) { + gqlClient, err := client.New(nodeInfo.CLConfig.URL, client.Credentials{ + Email: nodeInfo.CLConfig.Email, + Password: nodeInfo.CLConfig.Password, + }) + if err != nil { + return nil, fmt.Errorf("failed to create node graphql client: %w", err) + } + chainlinkClient, err := clclient.NewChainlinkClient(&nodeInfo.CLConfig, zerolog.Logger{}) + if err != nil { + return nil, fmt.Errorf("failed to create node rest client: %w", err) + } + return &Node{ + gqlClient: gqlClient, + restClient: chainlinkClient, + Name: nodeInfo.Name, + adminAddr: nodeInfo.AdminAddr, + }, nil +} + +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 + 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 + adminAddr string // admin address to send payments to, applicable only for non-bootstrap nodes + multiAddr string // multi address denoting node's FQN (needed for deriving P2PBootstrappers in OCR), applicable only for bootstrap nodes +} + +type JDChainConfigInput struct { + ChainID uint64 + ChainType string +} + +// CreateCCIPOCRSupportedChains creates a JobDistributorChainConfig for the node. +// It works under assumption that the node is already registered with the job distributor. +// It expects bootstrap nodes to have label with key "type" and value as "bootstrap". +// It fetches the account address, peer id, and OCR2 key bundle id and creates the JobDistributorChainConfig. +func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []JDChainConfigInput, jd JobDistributor) error { + for i, chain := range chains { + chainId := strconv.FormatUint(chain.ChainID, 10) + accountAddr, err := n.gqlClient.FetchAccountAddress(ctx, chainId) + if err != nil { + return fmt.Errorf("failed to fetch account address for node %s: %w", n.Name, err) + } + if accountAddr == nil { + return fmt.Errorf("no account address found for node %s", n.Name) + } + if n.AccountAddr == nil { + n.AccountAddr = make(map[uint64]string) + } + n.AccountAddr[chain.ChainID] = *accountAddr + peerID, err := n.gqlClient.FetchP2PPeerID(ctx) + if err != nil { + return fmt.Errorf("failed to fetch peer id for node %s: %w", n.Name, err) + } + if peerID == nil { + return fmt.Errorf("no peer id found for node %s", n.Name) + } + + ocr2BundleId, err := n.gqlClient.FetchOCR2KeyBundleID(ctx, chain.ChainType) + if err != nil { + return fmt.Errorf("failed to fetch OCR2 key bundle id for node %s: %w", n.Name, err) + } + if ocr2BundleId == "" { + return fmt.Errorf("no OCR2 key bundle id found for node %s", n.Name) + } + // fetch node labels to know if the node is bootstrap or plugin + isBootstrap := false + for _, label := range n.labels { + if label.Key == NodeLabelKeyType && pointer.GetString(label.Value) == NodeLabelValueBootstrap { + isBootstrap = true + break + } + } + // JD silently fails to update nodeChainConfig. Therefore, we fetch the node config and + // if it's not updated , throw an error + _, err = n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ + JobDistributorID: n.JDId, + ChainID: chainId, + ChainType: chain.ChainType, + AccountAddr: pointer.GetString(accountAddr), + AdminAddr: n.adminAddr, + Ocr2Enabled: true, + Ocr2IsBootstrap: isBootstrap, + Ocr2Multiaddr: n.multiAddr, + Ocr2P2PPeerID: pointer.GetString(peerID), + Ocr2KeyBundleID: ocr2BundleId, + Ocr2Plugins: `{"commit":true,"execute":true,"median":false,"mercury":false}`, + }) + if err != nil { + return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s: %w", n.Name, err) + } + // query the node chain config to check if it's created + nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ + Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{n.NodeId}, + }}) + if err != nil { + return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) + } + if nodeChainConfigs == nil || len(nodeChainConfigs.ChainConfigs) < i+1 { + return fmt.Errorf("failed to create chain config for node %s", n.Name) + } + } + return nil +} + +// AcceptJob accepts the job proposal for the given job proposal spec +func (n *Node) AcceptJob(ctx context.Context, spec string) error { + // fetch JD to get the job proposals + jd, err := n.gqlClient.GetJobDistributor(ctx, n.JDId) + if err != nil { + return err + } + if jd.GetJobProposals() == nil { + return fmt.Errorf("no job proposals found for node %s", n.Name) + } + // locate the job proposal id for the given job spec + var idToAccept string + for _, jp := range jd.JobProposals { + if jp.LatestSpec.Definition == spec { + idToAccept = jp.Id + break + } + } + if idToAccept == "" { + return fmt.Errorf("no job proposal found for job spec %s", spec) + } + approvedSpec, err := n.gqlClient.ApproveJobProposalSpec(ctx, idToAccept, false) + if err != nil { + return err + } + if approvedSpec == nil { + return fmt.Errorf("no job proposal spec found for job id %s", idToAccept) + } + return nil +} + +// RegisterNodeToJobDistributor fetches the CSA public key of the node and registers the node with the job distributor +// it sets the node id returned by JobDistributor as a result of registration in the node struct +func (n *Node) RegisterNodeToJobDistributor(ctx context.Context, jd JobDistributor) error { + // Get the public key of the node + csaKeyRes, err := n.gqlClient.FetchCSAPublicKey(ctx) + if err != nil { + return err + } + if csaKeyRes == nil { + return fmt.Errorf("no csa key found for node %s", n.Name) + } + csaKey := strings.TrimPrefix(*csaKeyRes, "csa_") + // register the node in the job distributor + registerResponse, err := jd.RegisterNode(ctx, &nodev1.RegisterNodeRequest{ + PublicKey: csaKey, + Labels: n.labels, + Name: n.Name, + }) + + if err != nil { + return fmt.Errorf("failed to register node %s: %w", n.Name, err) + } + if registerResponse.GetNode().GetId() == "" { + return fmt.Errorf("no node id returned from job distributor for node %s", n.Name) + } + n.NodeId = registerResponse.GetNode().GetId() + return nil +} + +// CreateJobDistributor fetches the keypairs from the job distributor and creates the job distributor in the node +// and returns the job distributor id +func (n *Node) CreateJobDistributor(ctx context.Context, jd JobDistributor) (string, error) { + // Get the keypairs from the job distributor + csaKey, err := jd.GetCSAPublicKey(ctx) + if err != nil { + return "", err + } + // create the job distributor in the node with the csa key + return n.gqlClient.CreateJobDistributor(ctx, client.JobDistributorInput{ + Name: "Job Distributor", + Uri: jd.WSRPC, + PublicKey: csaKey, + }) +} + +// SetUpAndLinkJobDistributor sets up the job distributor in the node and registers the node with the job distributor +// it sets the job distributor id for node +func (n *Node) SetUpAndLinkJobDistributor(ctx context.Context, jd JobDistributor) error { + // register the node in the job distributor + err := n.RegisterNodeToJobDistributor(ctx, jd) + if err != nil { + return err + } + // now create the job distributor in the node + id, err := n.CreateJobDistributor(ctx, jd) + if err != nil { + return err + } + // wait for the node to connect to the job distributor + err = retry.Do(ctx, retry.WithMaxDuration(1*time.Minute, retry.NewFibonacci(1*time.Second)), func(ctx context.Context) error { + getRes, err := jd.GetNode(ctx, &nodev1.GetNodeRequest{ + Id: n.NodeId, + }) + if err != nil { + return fmt.Errorf("failed to get node %s: %w", n.Name, err) + } + if getRes.GetNode() == nil { + return fmt.Errorf("no node found for node id %s", n.NodeId) + } + if !getRes.GetNode().IsConnected { + return retry.RetryableError(fmt.Errorf("node %s not connected to job distributor", n.Name)) + } + return nil + }) + if err != nil { + return fmt.Errorf("failed to connect node %s to job distributor: %w", n.Name, err) + } + n.JDId = id + return nil +} + +func (n *Node) ExportEVMKeysForChain(chainId string) ([]*clclient.ExportedEVMKey, error) { + return n.restClient.ExportEVMKeysForChain(chainId) +} + +// ReplayLogs replays logs for the chains on the node for given block numbers for each chain +func (n *Node) ReplayLogs(blockByChain map[uint64]uint64) error { + for sel, block := range blockByChain { + chainID, err := chainsel.ChainIdFromSelector(sel) + if err != nil { + return err + } + response, _, err := n.restClient.ReplayLogPollerFromBlock(int64(block), int64(chainID)) + if err != nil { + return err + } + if response.Data.Attributes.Message != "Replay started" { + return fmt.Errorf("unexpected response message from log poller's replay: %s", response.Data.Attributes.Message) + } + } + return nil +} diff --git a/integration-tests/deployment/devenv/environment.go b/integration-tests/deployment/devenv/environment.go new file mode 100644 index 00000000000..e06b69769f8 --- /dev/null +++ b/integration-tests/deployment/devenv/environment.go @@ -0,0 +1,54 @@ +package devenv + +import ( + "context" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" +) + +const ( + DevEnv = "devenv" +) + +type EnvironmentConfig struct { + Chains []ChainConfig + HomeChainSelector uint64 + FeedChainSelector uint64 + JDConfig JDConfig +} + +func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentConfig) (*deployment.Environment, *DON, error) { + chains, err := NewChains(lggr, config.Chains) + if err != nil { + return nil, nil, fmt.Errorf("failed to create chains: %w", err) + } + offChain, err := NewJDClient(ctx, config.JDConfig) + if err != nil { + return nil, nil, fmt.Errorf("failed to create JD client: %w", err) + } + + jd, ok := offChain.(*JobDistributor) + if !ok { + return nil, nil, fmt.Errorf("offchain client does not implement JobDistributor") + } + if jd == nil || jd.don == nil { + return nil, nil, fmt.Errorf("offchain client does not have a DON") + } + + err = jd.don.CreateSupportedChains(ctx, config.Chains, *jd) + if err != nil { + return nil, nil, err + } + nodeIDs := jd.don.NodeIds() + + return &deployment.Environment{ + Name: DevEnv, + Offchain: offChain, + NodeIDs: nodeIDs, + Chains: chains, + Logger: lggr, + }, jd.don, nil +} diff --git a/integration-tests/deployment/devenv/jd.go b/integration-tests/deployment/devenv/jd.go new file mode 100644 index 00000000000..4b2307f25d9 --- /dev/null +++ b/integration-tests/deployment/devenv/jd.go @@ -0,0 +1,98 @@ +package devenv + +import ( + "context" + "fmt" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + 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/integration-tests/deployment" +) + +type JDConfig struct { + GRPC string + WSRPC string + Creds credentials.TransportCredentials + nodeInfo []NodeInfo +} + +func NewJDConnection(cfg JDConfig) (*grpc.ClientConn, error) { + conn, err := grpc.NewClient(cfg.GRPC, grpc.WithTransportCredentials(cfg.Creds)) + if err != nil { + return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) + } + + return conn, nil +} + +type JobDistributor struct { + WSRPC string + nodev1.NodeServiceClient + jobv1.JobServiceClient + csav1.CSAServiceClient + don *DON +} + +func NewJDClient(ctx context.Context, cfg JDConfig) (deployment.OffchainClient, error) { + conn, err := NewJDConnection(cfg) + if err != nil { + return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) + } + jd := &JobDistributor{ + WSRPC: cfg.WSRPC, + NodeServiceClient: nodev1.NewNodeServiceClient(conn), + JobServiceClient: jobv1.NewJobServiceClient(conn), + CSAServiceClient: csav1.NewCSAServiceClient(conn), + } + if cfg.nodeInfo != nil && len(cfg.nodeInfo) > 0 { + jd.don, err = NewRegisteredDON(ctx, cfg.nodeInfo, *jd) + if err != nil { + return nil, fmt.Errorf("failed to create registered DON: %w", err) + } + } + return jd, err +} + +func (jd JobDistributor) GetCSAPublicKey(ctx context.Context) (string, error) { + keypairs, err := jd.ListKeypairs(ctx, &csav1.ListKeypairsRequest{}) + if err != nil { + return "", err + } + if keypairs == nil || len(keypairs.Keypairs) == 0 { + return "", fmt.Errorf("no keypairs found") + } + csakey := keypairs.Keypairs[0].PublicKey + return csakey, nil +} + +func (jd JobDistributor) ReplayLogs(selectorToBlock map[uint64]uint64) error { + return jd.don.ReplayAllLogs(selectorToBlock) +} + +// ProposeJob proposes jobs through the jobService and accepts the proposed job on selected node based on ProposeJobRequest.NodeId +func (jd JobDistributor) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, opts ...grpc.CallOption) (*jobv1.ProposeJobResponse, error) { + res, err := jd.JobServiceClient.ProposeJob(ctx, in, opts...) + if err != nil { + 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") + } + if jd.don == nil || len(jd.don.Nodes) == 0 { + return res, nil + } + for _, node := range jd.don.Nodes { + if node.NodeId != in.NodeId { + continue + } + // TODO : is there a way to accept the job with proposal id? + if err := node.AcceptJob(ctx, res.Proposal.Spec); err != nil { + return nil, fmt.Errorf("failed to accept job. err: %w", err) + } + } + return res, nil +} diff --git a/integration-tests/deployment/devenv/rmn.go b/integration-tests/deployment/devenv/rmn.go new file mode 100644 index 00000000000..a877c4fdfab --- /dev/null +++ b/integration-tests/deployment/devenv/rmn.go @@ -0,0 +1,384 @@ +package devenv + +import ( + "context" + "crypto/ed25519" + "encoding/json" + "fmt" + "io" + "net" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/google/uuid" + "github.com/pkg/errors" + "github.com/rs/zerolog" + tc "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/exec" + tcwait "github.com/testcontainers/testcontainers-go/wait" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +const ( + RMNKeyStore = "keystore/afn2proxy-keystore.json" + ProxyKeyStore = "keystore/rageproxy-keystore.json" +) + +type RageProxy struct { + test_env.EnvComponent + proxyListenerPort string + proxyPort string + Passphrase string + Local ProxyLocalConfig + Shared ProxySharedConfig + + // Generated on first time boot. + // Needed for RMHHome. + PeerID p2ptypes.PeerID +} + +func NewRage2ProxyComponent( + networks []string, + name, + imageName, + imageVersion string, + local ProxyLocalConfig, + shared ProxySharedConfig, + logStream *logstream.LogStream, +) (*RageProxy, error) { + rageName := fmt.Sprintf("%s-proxy-%s", name, uuid.NewString()[0:8]) + + // TODO support multiple listeners + _, listenPort, err := net.SplitHostPort(local.ListenAddresses[0]) + if err != nil { + return nil, err + } + _, proxyPort, err := net.SplitHostPort(local.ProxyAddress) + if err != nil { + return nil, err + } + + rmn := &RageProxy{ + EnvComponent: test_env.EnvComponent{ + ContainerName: rageName, + ContainerImage: imageName, + ContainerVersion: imageVersion, + Networks: networks, + LogStream: logStream, + }, + Passphrase: DefaultAFNPasphrase, + proxyListenerPort: listenPort, + proxyPort: proxyPort, + Local: local, + Shared: shared, + } + return rmn, nil +} + +func extractPeerID(b []byte) (p2ptypes.PeerID, error) { + var keystore struct { + AdditionalData string `json:"additionalData"` + } + if err := json.Unmarshal(b, &keystore); err != nil { + return p2ptypes.PeerID{}, err + } + var additionalData struct { + PeerID string `json:"PeerID"` + } + if err := json.Unmarshal([]byte(keystore.AdditionalData), &additionalData); err != nil { + return p2ptypes.PeerID{}, err + } + var peerID p2ptypes.PeerID + if err := peerID.UnmarshalText([]byte(additionalData.PeerID)); err != nil { + return p2ptypes.PeerID{}, err + } + return peerID, nil +} + +func (proxy *RageProxy) Start(t *testing.T, lggr zerolog.Logger) (tc.Container, error) { + sharedRageProxy, err := proxy.Shared.rageProxyShared() + if err != nil { + return nil, err + } + localRageProxy, err := proxy.Local.rageProxyLocal() + if err != nil { + return nil, err + } + + l := tc.Logger + if t != nil { + l = logging.CustomT{ + T: t, + L: lggr, + } + } + container, err := docker.StartContainerWithRetry(lggr, tc.GenericContainerRequest{ + ContainerRequest: tc.ContainerRequest{ + Name: proxy.ContainerName, + Image: fmt.Sprintf("%s:%s", proxy.ContainerImage, proxy.ContainerVersion), + Env: map[string]string{ + "RAGEPROXY_PASSPHRASE": proxy.Passphrase, + }, + ExposedPorts: []string{ + test_env.NatPortFormat(proxy.proxyPort), + test_env.NatPortFormat(proxy.proxyListenerPort), + }, + Files: []tc.ContainerFile{ + { + HostFilePath: sharedRageProxy, + ContainerFilePath: "/app/cfg/rageproxy-shared.json", + FileMode: 0644, + }, + { + HostFilePath: localRageProxy, + ContainerFilePath: "/app/cfg/rageproxy-local.json", + FileMode: 0644, + }, + }, + WaitingFor: tcwait.ForExec([]string{"cat", ProxyKeyStore}), + LifecycleHooks: []tc.ContainerLifecycleHooks{ + { + PostStarts: proxy.PostStartsHooks, + PostStops: proxy.PostStopsHooks, + PreTerminates: proxy.PreTerminatesHooks, + }, + }, + }, + Started: true, + Logger: l, + }) + if err != nil { + return nil, err + } + _, reader, err := container.Exec(context.Background(), []string{ + "cat", ProxyKeyStore}, exec.Multiplexed()) + if err != nil { + return nil, errors.Wrapf(err, "Unable to cat keystore") + } + b, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + peerID, err := extractPeerID(b) + if err != nil { + return nil, errors.Wrapf(err, "Unable to extract peerID %s", string(b)) + } + proxy.PeerID = peerID + proxy.Container = container + return container, nil +} + +type AFN2Proxy struct { + test_env.EnvComponent + AFNPassphrase string + Shared SharedConfig + Local LocalConfig + + // Generated on boot + OffchainPublicKey ed25519.PublicKey // RMNHome + EVMOnchainPublicKey common.Address // RMNRemote +} + +func NewAFN2ProxyComponent( + networks []string, + name, + imageName, + imageVersion string, + shared SharedConfig, + local LocalConfig, + logStream *logstream.LogStream) (*AFN2Proxy, error) { + afnName := fmt.Sprintf("%s-%s", name, uuid.NewString()[0:8]) + rmn := &AFN2Proxy{ + EnvComponent: test_env.EnvComponent{ + ContainerName: afnName, + ContainerImage: imageName, + ContainerVersion: imageVersion, + Networks: networks, + LogStream: logStream, + }, + AFNPassphrase: DefaultAFNPasphrase, + Shared: shared, + Local: local, + } + + return rmn, nil +} + +func extractKeys(b []byte) (common.Address, ed25519.PublicKey, error) { + var keystore struct { + AssociatedData string `json:"associated_data"` + } + if err := json.Unmarshal(b, &keystore); err != nil { + return common.Address{}, ed25519.PublicKey{}, err + } + var associatedData struct { + OffchainPublicKey string `json:"offchain_public_key"` + EVMOnchainPublicKey string `json:"evm_onchain_public_key"` + } + if err := json.Unmarshal([]byte(keystore.AssociatedData), &associatedData); err != nil { + return common.Address{}, ed25519.PublicKey{}, err + } + offchainKey, err := hexutil.Decode(associatedData.OffchainPublicKey) + if err != nil { + return common.Address{}, ed25519.PublicKey{}, err + } + if len(offchainKey) != ed25519.PublicKeySize { + return common.Address{}, ed25519.PublicKey{}, fmt.Errorf("invalid offchain public key: %x", offchainKey) + } + return common.HexToAddress(associatedData.EVMOnchainPublicKey), offchainKey, nil +} + +func (rmn *AFN2Proxy) Start(t *testing.T, lggr zerolog.Logger, reuse bool) (tc.Container, error) { + localAFN2Proxy, err := rmn.Local.afn2ProxyLocalConfigFile() + if err != nil { + return nil, err + } + sharedAFN2Proxy, err := rmn.Shared.afn2ProxySharedConfigFile() + if err != nil { + return nil, err + } + + l := tc.Logger + if t != nil { + l = logging.CustomT{ + T: t, + L: lggr, + } + } + container, err := docker.StartContainerWithRetry(lggr, tc.GenericContainerRequest{ + ContainerRequest: tc.ContainerRequest{ + Name: rmn.ContainerName, + Image: fmt.Sprintf("%s:%s", rmn.ContainerImage, rmn.ContainerVersion), + Env: map[string]string{ + "AFN_PASSPHRASE": rmn.AFNPassphrase, + }, + Files: []tc.ContainerFile{ + { + HostFilePath: sharedAFN2Proxy, + ContainerFilePath: "/app/cfg/afn2proxy-shared.toml", + FileMode: 0644, + }, + { + HostFilePath: localAFN2Proxy, + ContainerFilePath: "/app/cfg/afn2proxy-local.toml", + FileMode: 0644, + }, + }, + WaitingFor: tcwait.ForExec([]string{"cat", RMNKeyStore}), + LifecycleHooks: []tc.ContainerLifecycleHooks{ + { + PostStarts: rmn.PostStartsHooks, + PostStops: rmn.PostStopsHooks, + PreTerminates: rmn.PreTerminatesHooks, + }, + }, + }, + Started: true, + Reuse: reuse, + Logger: l, + }) + if err != nil { + return nil, err + } + _, reader, err := container.Exec(context.Background(), []string{ + "cat", RMNKeyStore}, exec.Multiplexed()) + if err != nil { + return nil, errors.Wrapf(err, "Unable to cat keystore") + } + b, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + onchainPubKey, offchainPubKey, err := extractKeys(b) + if err != nil { + return nil, errors.Wrapf(err, "Unable to extract peerID %s", string(b)) + } + rmn.OffchainPublicKey = offchainPubKey + rmn.EVMOnchainPublicKey = onchainPubKey + rmn.Container = container + return container, nil +} + +type RMNNode struct { + RMN AFN2Proxy + Proxy RageProxy +} + +func (n *RMNNode) Start(t *testing.T, lggr zerolog.Logger) error { + _, err := n.Proxy.Start(t, lggr) + if err != nil { + return err + } + _, err = n.RMN.Start(t, lggr, false) + if err != nil { + return err + } + return nil +} + +type RMNCluster struct { + Nodes map[string]RMNNode + t *testing.T + l zerolog.Logger +} + +// NewRMNCluster creates a new RMNCluster with the given configuration +// and starts it. +func NewRMNCluster( + t *testing.T, + l zerolog.Logger, + networks []string, + config map[string]RMNConfig, + proxyImage string, + proxyVersion string, + rmnImage string, + rmnVersion string, + logStream *logstream.LogStream, +) (*RMNCluster, error) { + rmn := &RMNCluster{ + t: t, + l: l, + Nodes: make(map[string]RMNNode), + } + for name, rmnConfig := range config { + proxy, err := NewRage2ProxyComponent(networks, name, proxyImage, proxyVersion, rmnConfig.ProxyLocal, rmnConfig.ProxyShared, logStream) + if err != nil { + return nil, err + } + _, err = proxy.Start(t, l) + if err != nil { + return nil, err + } + + // TODO: Hack here is we overwrite the host with the container name + // since the RMN node needs to be able to reach its own proxy container. + proxyName, err := proxy.Container.Name(context.Background()) + if err != nil { + return nil, err + } + _, port, err := net.SplitHostPort(rmnConfig.Shared.Networking.RageProxy) + if err != nil { + return nil, err + } + rmnConfig.Shared.Networking.RageProxy = fmt.Sprintf("%s:%s", proxyName, port) + afn, err := NewAFN2ProxyComponent(networks, name, rmnImage, rmnVersion, rmnConfig.Shared, rmnConfig.Local, logStream) + if err != nil { + return nil, err + } + _, err = afn.Start(t, l, false) + if err != nil { + return nil, err + } + rmn.Nodes[name] = RMNNode{ + RMN: *afn, + Proxy: *proxy, + } + } + return rmn, nil +} diff --git a/integration-tests/deployment/devenv/rmn_config.go b/integration-tests/deployment/devenv/rmn_config.go new file mode 100644 index 00000000000..3902ddbdcff --- /dev/null +++ b/integration-tests/deployment/devenv/rmn_config.go @@ -0,0 +1,137 @@ +package devenv + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/pelletier/go-toml/v2" +) + +const ( + DefaultAFNPasphrase = "my-not-so-secret-passphrase" + DefaultRageProxy = "127.0.0.1:8081" + DefaultProxyListenAddress = "127.0.0.1:8080" + DefaultDiscovererDbPath = "/app/rageproxy-discoverer-db.json" +) + +var ( + DefaultRageProxySharedConfig = ProxySharedConfig{ + Host: HostConfig{ + DurationBetweenDials: 1000000000, + }, + Discoverer: DiscovererConfig{ + DeltaReconcile: 1000000000, + }, + } +) + +type Networking struct { + RageProxy string `toml:"rageproxy"` + Bootstrappers []string `toml:"bootstrappers"` +} + +type HomeChain struct { + Name string `toml:"name"` + CapabilitiesRegistry string `toml:"capabilities_registry"` + CCIPHome string `toml:"ccip_home"` + RMNHome string `toml:"rmn_home"` +} + +type Stability struct { + Type string `toml:"type"` +} + +type RemoteChain struct { + Name string `toml:"name"` + Stability Stability `toml:"stability"` + StartBlockNumber int `toml:"start_block_number"` + OffRamp string `toml:"off_ramp"` + RMNRemote string `toml:"rmn_remote"` +} + +type SharedConfig struct { + Networking Networking `toml:"networking"` + HomeChain HomeChain `toml:"home_chain"` + RemoteChains []RemoteChain `toml:"remote_chains"` +} + +func (s SharedConfig) afn2ProxySharedConfigFile() (string, error) { + data, err := toml.Marshal(s) + if err != nil { + return "", fmt.Errorf("failed to marshal afn2Proxy shared config: %w", err) + } + return CreateTempFile(data, "afn2proxy_shared") +} + +type LocalConfig struct { + Chains []Chain `toml:"chains"` +} + +func (l LocalConfig) afn2ProxyLocalConfigFile() (string, error) { + data, err := toml.Marshal(l) + if err != nil { + return "", fmt.Errorf("failed to marshal afn2Proxy local config: %w", err) + } + return CreateTempFile(data, "afn2proxy_local") +} + +type Chain struct { + Name string `toml:"name"` + RPC string `toml:"rpc"` +} + +type ProxyLocalConfig struct { + ListenAddresses []string `json:"ListenAddresses"` + AnnounceAddresses []string `json:"AnnounceAddresses"` + ProxyAddress string `json:"ProxyAddress"` + DiscovererDbPath string `json:"DiscovererDbPath"` +} + +func (l ProxyLocalConfig) rageProxyLocal() (string, error) { + data, err := json.Marshal(l) + if err != nil { + return "", fmt.Errorf("failed to marshal rageProxy local config: %w", err) + } + return CreateTempFile(data, "rageproxy_local") +} + +type HostConfig struct { + DurationBetweenDials int64 `json:"DurationBetweenDials"` +} + +type DiscovererConfig struct { + DeltaReconcile int64 `json:"DeltaReconcile"` +} + +type ProxySharedConfig struct { + Host HostConfig `json:"Host"` + Discoverer DiscovererConfig `json:"Discoverer"` +} + +func (s ProxySharedConfig) rageProxyShared() (string, error) { + data, err := json.Marshal(s) + if err != nil { + return "", fmt.Errorf("failed to marshal rageProxy shared config: %w", err) + } + return CreateTempFile(data, "rageproxy_shared") +} + +type RMNConfig struct { + Shared SharedConfig + Local LocalConfig + ProxyLocal ProxyLocalConfig + ProxyShared ProxySharedConfig +} + +func CreateTempFile(data []byte, pattern string) (string, error) { + file, err := os.CreateTemp("", pattern) + if err != nil { + return "", fmt.Errorf("failed to create temp file for %s: %w", pattern, err) + } + _, err = file.Write(data) + if err != nil { + return "", fmt.Errorf("failed to write %s: %w", pattern, err) + } + return file.Name(), nil +} diff --git a/integration-tests/deployment/devenv/rmn_test.go b/integration-tests/deployment/devenv/rmn_test.go new file mode 100644 index 00000000000..7d07670ff7d --- /dev/null +++ b/integration-tests/deployment/devenv/rmn_test.go @@ -0,0 +1,15 @@ +package devenv + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestExtractPeerID(t *testing.T) { + data := []byte("{\"Salt\":\"yAUVSNGPnY78hJwJwKDBmA==\",\"Nonce\":\"8p0vNKpnQH1P+7/cg2dM3vNlc60tzPl0\",\"Ciphertext\":\"VboRchQzDx/+zIVDWyTXIEwo4Ej0s7O6kQqmgCqW+A+HEXl6bI02W1Y2T88XuY0m44eC9DvSpBPhs/VLtgymj6nBcl+nzfJHLMp2pBMPjKHxgNsEk34mDgnmqYKTtIkgzv7hEyy7j0CAcR/RxkjfQNKpfWOlNtAFryFO+w==\",\"AdditionalData\":\"{\\\"PeerID\\\":\\\"12D3KooWNqugYSJw9thwwu1PC3aEpPsBxMZM2EdzpJXGesRG4E8n\\\"}\"}") + peerID, err := extractPeerID(data) + require.NoError(t, err) + assert.Equal(t, "12D3KooWNqugYSJw9thwwu1PC3aEpPsBxMZM2EdzpJXGesRG4E8n", peerID.String()) +} diff --git a/integration-tests/deployment/environment.go b/integration-tests/deployment/environment.go new file mode 100644 index 00000000000..42ee24aea29 --- /dev/null +++ b/integration-tests/deployment/environment.go @@ -0,0 +1,282 @@ +package deployment + +import ( + "bytes" + "context" + "errors" + "fmt" + "math/big" + "sort" + "strconv" + + "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/rpc" + chain_selectors "github.com/smartcontractkit/chain-selectors" + types2 "github.com/smartcontractkit/libocr/offchainreporting2/types" + types3 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "google.golang.org/grpc" + + 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-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +type OnchainClient interface { + // For EVM specifically we can use existing geth interface + // to abstract chain clients. + bind.ContractBackend + bind.DeployBackend + BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) + NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) +} + +type OffchainClient interface { + // The job distributor grpc interface can be used to abstract offchain read/writes + jobv1.JobServiceClient + nodev1.NodeServiceClient + csav1.CSAServiceClient +} + +type Chain struct { + // Selectors used as canonical chain identifier. + Selector uint64 + Client OnchainClient + // Note the Sign function can be abstract supporting a variety of key storage mechanisms (e.g. KMS etc). + DeployerKey *bind.TransactOpts + Confirm func(tx *types.Transaction) (uint64, error) +} + +type Environment struct { + Name string + Chains map[uint64]Chain + Offchain OffchainClient + NodeIDs []string + Logger logger.Logger +} + +func (e Environment) AllChainSelectors() []uint64 { + var selectors []uint64 + for sel := range e.Chains { + selectors = append(selectors, sel) + } + sort.Slice(selectors, func(i, j int) bool { + return selectors[i] < selectors[j] + }) + return selectors +} + +func (e Environment) AllChainSelectorsExcluding(excluding []uint64) []uint64 { + var selectors []uint64 + for sel := range e.Chains { + excluded := false + for _, toExclude := range excluding { + if sel == toExclude { + excluded = true + } + } + if excluded { + continue + } + selectors = append(selectors, sel) + } + sort.Slice(selectors, func(i, j int) bool { + return selectors[i] < selectors[j] + }) + return selectors +} + +func ConfirmIfNoError(chain Chain, tx *types.Transaction, err error) (uint64, error) { + if err != nil { + //revive:disable + var d rpc.DataError + ok := errors.As(err, &d) + if ok { + return 0, fmt.Errorf("transaction reverted: Error %s ErrorData %v", d.Error(), d.ErrorData()) + } + return 0, err + } + return chain.Confirm(tx) +} + +func MaybeDataErr(err error) error { + //revive:disable + var d rpc.DataError + ok := errors.As(err, &d) + if ok { + return d + } + return err +} + +func UBigInt(i uint64) *big.Int { + return new(big.Int).SetUint64(i) +} + +func E18Mult(amount uint64) *big.Int { + return new(big.Int).Mul(UBigInt(amount), UBigInt(1e18)) +} + +type OCRConfig struct { + OffchainPublicKey types2.OffchainPublicKey + // For EVM-chains, this an *address*. + OnchainPublicKey types2.OnchainPublicKey + PeerID p2pkey.PeerID + TransmitAccount types2.Account + ConfigEncryptionPublicKey types3.ConfigEncryptionPublicKey + KeyBundleID string +} + +// Nodes includes is a group CL nodes. +type Nodes []Node + +// PeerIDs returns peerIDs in a sorted list +func (n Nodes) PeerIDs() [][32]byte { + var peerIDs [][32]byte + for _, node := range n { + peerIDs = append(peerIDs, node.PeerID) + } + sort.Slice(peerIDs, func(i, j int) bool { + return bytes.Compare(peerIDs[i][:], peerIDs[j][:]) < 0 + }) + return peerIDs +} + +func (n Nodes) NonBootstraps() Nodes { + var nonBootstraps Nodes + for _, node := range n { + if node.IsBootstrap { + continue + } + nonBootstraps = append(nonBootstraps, node) + } + return nonBootstraps +} + +func (n Nodes) DefaultF() uint8 { + return uint8(len(n) / 3) +} + +func (n Nodes) BootstrapLocators() []string { + bootstrapMp := make(map[string]struct{}) + for _, node := range n { + if node.IsBootstrap { + bootstrapMp[fmt.Sprintf("%s@%s", + // p2p_12D3... -> 12D3... + node.PeerID.String()[4:], node.MultiAddr)] = struct{}{} + } + } + var locators []string + for b := range bootstrapMp { + locators = append(locators, b) + } + return locators +} + +type Node struct { + NodeID string + SelToOCRConfig map[uint64]OCRConfig + PeerID p2pkey.PeerID + IsBootstrap bool + MultiAddr string + AdminAddr string +} + +func (n Node) FirstOCRKeybundle() OCRConfig { + for _, ocrConfig := range n.SelToOCRConfig { + return ocrConfig + } + return OCRConfig{} +} + +func MustPeerIDFromString(s string) p2pkey.PeerID { + p := p2pkey.PeerID{} + if err := p.UnmarshalString(s); err != nil { + panic(err) + } + return p +} + +type NodeChainConfigsLister interface { + ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*nodev1.ListNodeChainConfigsResponse, error) +} + +// Gathers all the node info through JD required to be able to set +// OCR config for example. +func NodeInfo(nodeIDs []string, oc NodeChainConfigsLister) (Nodes, error) { + var nodes []Node + for _, nodeID := range nodeIDs { + // TODO: Filter should accept multiple nodes + nodeChainConfigs, err := oc.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{nodeID}, + }}) + if err != nil { + return nil, err + } + selToOCRConfig := make(map[uint64]OCRConfig) + bootstrap := false + var peerID p2pkey.PeerID + var multiAddr string + var adminAddr string + for _, chainConfig := range nodeChainConfigs.ChainConfigs { + if chainConfig.Chain.Type == nodev1.ChainType_CHAIN_TYPE_SOLANA { + // Note supported for CCIP yet. + continue + } + // NOTE: Assume same peerID/multiAddr for all chains. + // Might make sense to change proto as peerID/multiAddr is 1-1 with nodeID? + peerID = MustPeerIDFromString(chainConfig.Ocr2Config.P2PKeyBundle.PeerId) + multiAddr = chainConfig.Ocr2Config.Multiaddr + adminAddr = chainConfig.AdminAddress + if chainConfig.Ocr2Config.IsBootstrap { + // NOTE: Assume same peerID for all chains. + // Might make sense to change proto as peerID is 1-1 with nodeID? + bootstrap = true + break + } + evmChainID, err := strconv.Atoi(chainConfig.Chain.Id) + if err != nil { + return nil, err + } + sel, err := chain_selectors.SelectorFromChainId(uint64(evmChainID)) + if err != nil { + return nil, err + } + b := common.Hex2Bytes(chainConfig.Ocr2Config.OcrKeyBundle.OffchainPublicKey) + var opk types2.OffchainPublicKey + copy(opk[:], b) + + b = common.Hex2Bytes(chainConfig.Ocr2Config.OcrKeyBundle.ConfigPublicKey) + var cpk types3.ConfigEncryptionPublicKey + copy(cpk[:], b) + + selToOCRConfig[sel] = OCRConfig{ + OffchainPublicKey: opk, + OnchainPublicKey: common.HexToAddress(chainConfig.Ocr2Config.OcrKeyBundle.OnchainSigningAddress).Bytes(), + PeerID: MustPeerIDFromString(chainConfig.Ocr2Config.P2PKeyBundle.PeerId), + TransmitAccount: types2.Account(chainConfig.AccountAddress), + ConfigEncryptionPublicKey: cpk, + KeyBundleID: chainConfig.Ocr2Config.OcrKeyBundle.BundleId, + } + } + nodes = append(nodes, Node{ + NodeID: nodeID, + SelToOCRConfig: selToOCRConfig, + IsBootstrap: bootstrap, + PeerID: peerID, + MultiAddr: multiAddr, + AdminAddr: adminAddr, + }) + } + + return nodes, nil +} + +type CapabilityRegistryConfig struct { + EVMChainID uint64 // chain id of the chain the CR is deployed on + Contract common.Address // address of the CR contract +} diff --git a/integration-tests/deployment/evm_kmsclient.go b/integration-tests/deployment/evm_kmsclient.go new file mode 100644 index 00000000000..07af77523c8 --- /dev/null +++ b/integration-tests/deployment/evm_kmsclient.go @@ -0,0 +1,233 @@ +package deployment + +import ( + "bytes" + "context" + "crypto/ecdsa" + "encoding/asn1" + "encoding/hex" + "fmt" + "math/big" + + "github.com/aws/aws-sdk-go/aws/session" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/kms" + "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/crypto/secp256k1" +) + +var ( + secp256k1N = crypto.S256().Params().N + secp256k1HalfN = new(big.Int).Div(secp256k1N, big.NewInt(2)) +) + +// See https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html#API_GetPublicKey_ResponseSyntax +// and https://datatracker.ietf.org/doc/html/rfc5280 for why we need to unpack the KMS public key. +type asn1SubjectPublicKeyInfo struct { + AlgorithmIdentifier asn1AlgorithmIdentifier + SubjectPublicKey asn1.BitString +} + +type asn1AlgorithmIdentifier struct { + Algorithm asn1.ObjectIdentifier + Parameters asn1.ObjectIdentifier +} + +// See https://aws.amazon.com/blogs/database/part2-use-aws-kms-to-securely-manage-ethereum-accounts/ for why we +// need to manually prep the signature for Ethereum. +type asn1ECDSASig struct { + R asn1.RawValue + S asn1.RawValue +} + +// TODO: Mockery gen then test with a regular eth key behind the interface. +type KMSClient interface { + GetPublicKey(input *kms.GetPublicKeyInput) (*kms.GetPublicKeyOutput, error) + Sign(input *kms.SignInput) (*kms.SignOutput, error) +} + +type KMS struct { + KmsDeployerKeyId string + KmsDeployerKeyRegion string + AwsProfileName string +} + +func NewKMSClient(config KMS) (KMSClient, error) { + if config.KmsDeployerKeyId == "" { + return nil, fmt.Errorf("KMS key ID is required") + } + if config.KmsDeployerKeyRegion == "" { + return nil, fmt.Errorf("KMS key region is required") + } + var awsSessionFn AwsSessionFn + if config.AwsProfileName != "" { + awsSessionFn = awsSessionFromProfileFn + } else { + awsSessionFn = awsSessionFromEnvVarsFn + } + return kms.New(awsSessionFn(config)), nil +} + +type EVMKMSClient struct { + Client KMSClient + KeyID string +} + +func NewEVMKMSClient(client KMSClient, keyID string) *EVMKMSClient { + return &EVMKMSClient{ + Client: client, + KeyID: keyID, + } +} + +func (c *EVMKMSClient) GetKMSTransactOpts(ctx context.Context, chainID *big.Int) (*bind.TransactOpts, error) { + ecdsaPublicKey, err := c.GetECDSAPublicKey() + if err != nil { + return nil, err + } + + pubKeyBytes := secp256k1.S256().Marshal(ecdsaPublicKey.X, ecdsaPublicKey.Y) + keyAddr := crypto.PubkeyToAddress(*ecdsaPublicKey) + if chainID == nil { + return nil, fmt.Errorf("chainID is required") + } + signer := types.LatestSignerForChainID(chainID) + + signerFn := func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { + if address != keyAddr { + return nil, bind.ErrNotAuthorized + } + + txHashBytes := signer.Hash(tx).Bytes() + + mType := kms.MessageTypeDigest + algo := kms.SigningAlgorithmSpecEcdsaSha256 + signOutput, err := c.Client.Sign( + &kms.SignInput{ + KeyId: &c.KeyID, + SigningAlgorithm: &algo, + MessageType: &mType, + Message: txHashBytes, + }) + if err != nil { + return nil, fmt.Errorf("failed to call kms.Sign() on transaction: %w", err) + } + + ethSig, err := kmsToEthSig(signOutput.Signature, pubKeyBytes, txHashBytes) + if err != nil { + return nil, fmt.Errorf("failed to convert KMS signature to Ethereum signature: %w", err) + } + + return tx.WithSignature(signer, ethSig) + } + + return &bind.TransactOpts{ + From: keyAddr, + Signer: signerFn, + Context: ctx, + }, nil +} + +// GetECDSAPublicKey retrieves the public key from KMS and converts it to its ECDSA representation. +func (c *EVMKMSClient) GetECDSAPublicKey() (*ecdsa.PublicKey, error) { + getPubKeyOutput, err := c.Client.GetPublicKey(&kms.GetPublicKeyInput{ + KeyId: aws.String(c.KeyID), + }) + if err != nil { + return nil, fmt.Errorf("can not get public key from KMS for KeyId=%s: %w", c.KeyID, err) + } + + var asn1pubKeyInfo asn1SubjectPublicKeyInfo + _, err = asn1.Unmarshal(getPubKeyOutput.PublicKey, &asn1pubKeyInfo) + if err != nil { + return nil, fmt.Errorf("can not parse asn1 public key for KeyId=%s: %w", c.KeyID, err) + } + + pubKey, err := crypto.UnmarshalPubkey(asn1pubKeyInfo.SubjectPublicKey.Bytes) + if err != nil { + return nil, fmt.Errorf("can not unmarshal public key bytes: %w", err) + } + return pubKey, nil +} + +func kmsToEthSig(kmsSig, ecdsaPubKeyBytes, hash []byte) ([]byte, error) { + var asn1Sig asn1ECDSASig + _, err := asn1.Unmarshal(kmsSig, &asn1Sig) + if err != nil { + return nil, err + } + + rBytes := asn1Sig.R.Bytes + sBytes := asn1Sig.S.Bytes + + // Adjust S value from signature to match Eth standard. + // See: https://aws.amazon.com/blogs/database/part2-use-aws-kms-to-securely-manage-ethereum-accounts/ + // "After we extract r and s successfully, we have to test if the value of s is greater than secp256k1n/2 as + // specified in EIP-2 and flip it if required." + sBigInt := new(big.Int).SetBytes(sBytes) + if sBigInt.Cmp(secp256k1HalfN) > 0 { + sBytes = new(big.Int).Sub(secp256k1N, sBigInt).Bytes() + } + + return recoverEthSignature(ecdsaPubKeyBytes, hash, rBytes, sBytes) +} + +// See: https://aws.amazon.com/blogs/database/part2-use-aws-kms-to-securely-manage-ethereum-accounts/ +func recoverEthSignature(expectedPublicKeyBytes, txHash, r, s []byte) ([]byte, error) { + rsSig := append(padTo32Bytes(r), padTo32Bytes(s)...) + ethSig := append(rsSig, []byte{0}...) + + recoveredPublicKeyBytes, err := crypto.Ecrecover(txHash, ethSig) + if err != nil { + return nil, fmt.Errorf("failing to call Ecrecover: %w", err) + } + + if hex.EncodeToString(recoveredPublicKeyBytes) != hex.EncodeToString(expectedPublicKeyBytes) { + ethSig = append(rsSig, []byte{1}...) + recoveredPublicKeyBytes, err = crypto.Ecrecover(txHash, ethSig) + if err != nil { + return nil, fmt.Errorf("failing to call Ecrecover: %w", err) + } + + if hex.EncodeToString(recoveredPublicKeyBytes) != hex.EncodeToString(expectedPublicKeyBytes) { + return nil, fmt.Errorf("can not reconstruct public key from sig") + } + } + + return ethSig, nil +} + +func padTo32Bytes(buffer []byte) []byte { + buffer = bytes.TrimLeft(buffer, "\x00") + for len(buffer) < 32 { + zeroBuf := []byte{0} + buffer = append(zeroBuf, buffer...) + } + return buffer +} + +type AwsSessionFn func(config KMS) *session.Session + +var awsSessionFromEnvVarsFn = func(config KMS) *session.Session { + return session.Must( + session.NewSession(&aws.Config{ + Region: aws.String(config.KmsDeployerKeyRegion), + CredentialsChainVerboseErrors: aws.Bool(true), + })) +} + +var awsSessionFromProfileFn = func(config KMS) *session.Session { + return session.Must( + session.NewSessionWithOptions(session.Options{ + SharedConfigState: session.SharedConfigEnable, + Profile: config.AwsProfileName, + Config: aws.Config{ + Region: aws.String(config.KmsDeployerKeyRegion), + CredentialsChainVerboseErrors: aws.Bool(true), + }, + })) +} diff --git a/integration-tests/deployment/evm_kmsclient_test.go b/integration-tests/deployment/evm_kmsclient_test.go new file mode 100644 index 00000000000..8a889a56067 --- /dev/null +++ b/integration-tests/deployment/evm_kmsclient_test.go @@ -0,0 +1,27 @@ +package deployment + +import ( + "encoding/hex" + "testing" + + "github.com/test-go/testify/require" +) + +func TestKMSToEthSigConversion(t *testing.T) { + kmsSigBytes, err := hex.DecodeString("304402206168865941bafcae3a8cf8b26edbb5693d62222b2e54d962c1aabbeaddf33b6802205edc7f597d2bf2d1eaa14fc514a6202bafcffe52b13ae3fec00674d92a874b73") + require.NoError(t, err) + ecdsaPublicKeyBytes, err := hex.DecodeString("04a735e9e3cb526f83be23b03f1f5ae7788a8654e3f0fcfb4f978290de07ebd47da30eeb72e904fdd4a81b46e320908ff4345e119148f89c1f04674c14a506e24b") + require.NoError(t, err) + txHashBytes, err := hex.DecodeString("a2f037301e90f58c084fe4bec2eef14b26e620d6b6cb46051037d03b29ab7d9a") + require.NoError(t, err) + expectedEthSignBytes, err := hex.DecodeString("6168865941bafcae3a8cf8b26edbb5693d62222b2e54d962c1aabbeaddf33b685edc7f597d2bf2d1eaa14fc514a6202bafcffe52b13ae3fec00674d92a874b7300") + require.NoError(t, err) + + actualEthSig, err := kmsToEthSig( + kmsSigBytes, + ecdsaPublicKeyBytes, + txHashBytes, + ) + require.NoError(t, err) + require.Equal(t, expectedEthSignBytes, actualEthSig) +} diff --git a/integration-tests/deployment/helpers.go b/integration-tests/deployment/helpers.go new file mode 100644 index 00000000000..226de9a7024 --- /dev/null +++ b/integration-tests/deployment/helpers.go @@ -0,0 +1,110 @@ +package deployment + +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/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/pkg/errors" +) + +// OCRSecrets are used to disseminate a shared secret to OCR nodes +// through the blockchain where OCR configuration is stored. Its a low value secret used +// to derive transmission order etc. They are extracted here such that they can common +// across signers when multiple signers are signing the same OCR config. +type OCRSecrets struct { + SharedSecret [16]byte + EphemeralSk [32]byte +} + +func (s OCRSecrets) IsEmpty() bool { + return s.SharedSecret == [16]byte{} || s.EphemeralSk == [32]byte{} +} + +func XXXGenerateTestOCRSecrets() OCRSecrets { + var s OCRSecrets + copy(s.SharedSecret[:], crypto.Keccak256([]byte("shared"))[:16]) + copy(s.EphemeralSk[:], crypto.Keccak256([]byte("ephemeral"))) + return s +} + +// SimTransactOpts is useful to generate just the calldata for a given gethwrapper method. +func SimTransactOpts() *bind.TransactOpts { + return &bind.TransactOpts{Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) { + return transaction, nil + }, From: common.HexToAddress("0x0"), NoSend: true, GasLimit: 1_000_000} +} + +func GetErrorReasonFromTx(client bind.ContractBackend, from common.Address, tx types.Transaction, receipt *types.Receipt) (string, error) { + call := ethereum.CallMsg{ + From: from, + To: tx.To(), + Data: tx.Data(), + Value: tx.Value(), + Gas: tx.Gas(), + GasPrice: tx.GasPrice(), + } + _, err := client.CallContract(context.Background(), call, receipt.BlockNumber) + if err != nil { + errorReason, err := parseError(err) + if err == nil { + return errorReason, nil + } + } + return "", fmt.Errorf("tx %s reverted with no reason", tx.Hash().Hex()) +} + +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 ParseErrorFromABI(errorString string, contractABI string) (string, error) { + parsedAbi, err := abi.JSON(strings.NewReader(contractABI)) + if err != nil { + return "", errors.Wrap(err, "error loading ABI") + } + 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 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") + } + return fmt.Sprintf("error is \"%v\" args %v\n", errorName, v), nil + } + } + return "", errors.New("error not found in ABI") +} diff --git a/integration-tests/deployment/keystone/README.md b/integration-tests/deployment/keystone/README.md new file mode 100644 index 00000000000..4d11a7b66da --- /dev/null +++ b/integration-tests/deployment/keystone/README.md @@ -0,0 +1,106 @@ +# Programmatic deployment of Keystone + +The current scope of this package is the ability to deploy and configure the Capability Registry, OCR3 and Forwarder contracts. + +It builds on the `Environment` abstraction introduced by `chainlink-deployments`. The concept of Environment is used delineate dev vs testnet vs prod. +A deployment injects the necessary configuration (eg simulated chain vs testnet chain) as appropriate via the `Environment` abstraction, and the +deployment implementation be agnostic to these details. + + +The entry point to the deployment is the `Deploy` func. The arguments to the this func are environment dependent, and vary from one deployment to another. + +``` +type DeployRequest struct { + RegistryChainSel uint64 + Env *deployment.Environment + + Dons []DonCapabilities // externally sourced based on the environment + OCR3Config *OracleConfigSource // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config +} + +type DeployResponse struct { + Changeset *deployment.ChangesetOutput + DonInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo +} + +func Deploy(ctx context.Context, lggr logger.Logger, req DeployRequest) (*DeployResponse, error) +``` + + +In order to make this all work we need a mapping what nodes run which capabilities, which nodes belong to what don, and ocr configuration for consensus. The first two are represented by `Dons, OCR3Config`, respectively. + +The mapping for nodes->capability is an external artifact that is declare in configuration for the given environment. The mapping between nodes and Dons is also configuration, however it is constrained by +real world data about the nodes themselves, such as the p2pkeys and so forth. + +For keystone, this constraint boils down to an integration point with CLO, which is the current system of record all Node/NOP metadata (as well the Jobs themselves). + +Therefore, in order to the system to work, we need to source data from CLO. + +# CLO integration + +The integration with CLO is contained `clo` package. It defines a minimal, keystone-specific, translation of the CLO data model to the new Job Distributor model. This is needed because the `Environment` abstraction relies on the JD data model and API (via `OffchainClient`). + +However, at the time of writing, it was not feasible to programmatically access the CLO API within our deployment (KS-454). + +For the time being, there are manual steps to obtain the metadata from CLO as described below. + +## Obtaining and parsing CLO data + +A real deployment requires real data from CLO. + +### Requirements +- clo access to [stage](https://feeds-manager.main.stage.cldev.sh/sign-in), [prod](https://feeds-manager.main.prod.cldev.sh/sign-in) (ask in #topic-keystone-clo and tag Joey Punzel) +- [clo cli](https://github.com/smartcontractkit/feeds-manager#chainlink-orchestrator-api-client) +- stage & prod configuration for the cli + + +As discussed above, CLO is the system that knows about nodes and node operators. One of our goals is to configure the registry contract with the nodes and nops. So we have to faithfully plumb the values in CLO to our deployment. + +For the time being, it is not possible to do this programmatically in golang.T he next best this is to us the existing clo cli to snapshot the relevant state in a consumable format. + +The state is represented in `clo/models/models*go`. Example data is in `clo/testdata/keystone_nops.json` + +First, ensure you can login to the CLO instances [stage](https://feeds-manager.main.stage.cldev.sh/sign-in), [prod](https://feeds-manager.main.prod.cldev.sh/sign-in) (ask in #topic-keystone-clo and tag Joey Punzel) + +Next, you need the clo cli: +See to build and install +https://github.com/smartcontractkit/feeds-manager#chainlink-orchestrator-api-client + +Now, you need config for stage and prod env, eg `~/.fmsclient/stage.yaml` and `~/.fmsclient/prod.yaml` + +`~/.fmsclient/prod.yaml` : +``` +EMAIL: "your.name@smartcontract.com" +PASSWORD: 'XXXredacted' +BASE_URL: "https://gql.feeds-manager.main.prod.cldev.sh" +``` +`~/.fmsclient/stage.yaml` +``` +EMAIL: "your.name@smartcontract.com" +PASSWORD: 'XXXredacted' +BASE_URL: "https://gql.feeds-manager.main.stage.cldev.sh" +``` + + + +Now run the cli to get *all* the node operators +``` +./bin/fmscli --config ~/.fmsclient/prod.yaml get nodeOperators > /some/file.json +``` + +The output of this will be a JSON serialization of `[]*models.NodeOperator` and should same from as the testdata `clo/testdata/keystone_nops.json` This test data was post filtered to only contain keystone node operators. + +In order to make the data in `/some/file` useful for a deployment, you need to filter to only contain `keystone` nodes. This can be heuristically with `CapabilityNodeSet` func. See the test in `clo/don_nodeset_test.go` for an example. + + +This filtered data, the map of don -> []capabilities is enough to fully specify the offchain data required for a deployment. + +See `deploy_test:Test_Deploy/memory_chains_clo_offchain` for an explicit example + +## Chain configuration + +All the tests use in memory chains with simulated backends. Real deployments are in `chainlink-deployment`, which load chain-specific configuration (such as rpc endpoints) to instantiate real chains. + + +## Jobs +Are not handled programmatically yet. They are managed manually in CLO with help from [RDD](https://github.com/smartcontractkit/reference-data-directory#workflows) \ No newline at end of file diff --git a/integration-tests/deployment/keystone/capability_definitions.go b/integration-tests/deployment/keystone/capability_definitions.go new file mode 100644 index 00000000000..61f129a939a --- /dev/null +++ b/integration-tests/deployment/keystone/capability_definitions.go @@ -0,0 +1,34 @@ +package keystone + +import kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + +// TODO: KS-457 configuration management for capabilities from external sources +var StreamTriggerCap = kcr.CapabilitiesRegistryCapability{ + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: uint8(0), // trigger +} + +var WriteChainCap = kcr.CapabilitiesRegistryCapability{ + LabelledName: "write_ethereum-testnet-sepolia", + Version: "1.0.0", + CapabilityType: uint8(3), // target +} + +var OCR3Cap = kcr.CapabilitiesRegistryCapability{ + LabelledName: "offchain_reporting", + Version: "1.0.0", + CapabilityType: uint8(2), // consensus +} + +var DonToCapabilities = map[string][]kcr.CapabilitiesRegistryCapability{ + WFDonName: []kcr.CapabilitiesRegistryCapability{OCR3Cap}, + TargetDonName: []kcr.CapabilitiesRegistryCapability{WriteChainCap}, + StreamDonName: []kcr.CapabilitiesRegistryCapability{StreamTriggerCap}, +} + +var ( + WFDonName = "wf" + TargetDonName = "target" + StreamDonName = "streams" +) diff --git a/integration-tests/deployment/keystone/capability_registry_deployer.go b/integration-tests/deployment/keystone/capability_registry_deployer.go new file mode 100644 index 00000000000..cd4de63558c --- /dev/null +++ b/integration-tests/deployment/keystone/capability_registry_deployer.go @@ -0,0 +1,66 @@ +package keystone + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +type CapabilitiesRegistryDeployer struct { + lggr logger.Logger + contract *capabilities_registry.CapabilitiesRegistry +} + +var CapabilityRegistryTypeVersion = deployment.TypeAndVersion{ + Type: CapabilitiesRegistry, + Version: deployment.Version1_0_0, +} + +func (c *CapabilitiesRegistryDeployer) deploy(req deployRequest) (*deployResponse, error) { + est, err := estimateDeploymentGas(req.Chain.Client, capabilities_registry.CapabilitiesRegistryABI) + if err != nil { + return nil, fmt.Errorf("failed to estimate gas: %w", err) + } + c.lggr.Debugf("Capability registry estimated gas: %d", est) + + capabilitiesRegistryAddr, tx, capabilitiesRegistry, err := capabilities_registry.DeployCapabilitiesRegistry( + req.Chain.DeployerKey, + req.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + } + + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm and save CapabilitiesRegistry: %w", err) + } + resp := &deployResponse{ + Address: capabilitiesRegistryAddr, + Tx: tx.Hash(), + Tv: CapabilityRegistryTypeVersion, + } + c.contract = capabilitiesRegistry + return resp, nil +} + +func estimateDeploymentGas(client deployment.OnchainClient, bytecode string) (uint64, error) { + // fake contract address required for gas estimation, otherwise it will fail + contractAddress := common.HexToAddress("0x0000000000000000000000000000000000000000") + + msg := ethereum.CallMsg{ + To: &contractAddress, // nil ok for + Gas: 0, // initial gas estimate (will be updated) + Data: []byte(bytecode), + } + gasEstimate, err := client.EstimateGas(context.Background(), msg) + if err != nil { + return 0, fmt.Errorf("failed to estimate gas: %w", err) + } + return gasEstimate, nil +} diff --git a/integration-tests/deployment/keystone/changeset/configure_contracts.go b/integration-tests/deployment/keystone/changeset/configure_contracts.go new file mode 100644 index 00000000000..796a4247969 --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/configure_contracts.go @@ -0,0 +1,61 @@ +package changeset + +import ( + "context" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + kslib "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" +) + +func ConfigureInitialContracts(lggr logger.Logger, req *kslib.ConfigureContractsRequest) (deployment.ChangesetOutput, error) { + if err := req.Validate(); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to validate request: %w", err) + } + + regAddrs, err := req.AddressBook.AddressesForChain(req.RegistryChainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", req.RegistryChainSel, err) + } + foundRegistry := false + foundOCR3 := false + foundForwarder := false + for _, addr := range regAddrs { + switch addr.Type { + case kslib.CapabilityRegistryTypeVersion.Type: + foundRegistry = true + case kslib.OCR3CapabilityTypeVersion.Type: + foundOCR3 = true + case kslib.ForwarderTypeVersion.Type: + foundForwarder = true + } + } + if !foundRegistry || !foundOCR3 || !foundForwarder { + return deployment.ChangesetOutput{}, fmt.Errorf("missing contracts on registry chain %d in addressbook for changeset %s registry exists %t, ocr3 exist %t, forwarder exists %t ", req.RegistryChainSel, "0003_deploy_forwarder", + foundRegistry, foundOCR3, foundForwarder) + } + // forwarder on all chains + foundForwarder = false + for _, c := range req.Env.Chains { + addrs, err2 := req.AddressBook.AddressesForChain(c.Selector) + if err2 != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", c.Selector, err2) + } + for _, addr := range addrs { + if addr.Type == kslib.ForwarderTypeVersion.Type { + foundForwarder = true + break + } + } + if !foundForwarder { + return deployment.ChangesetOutput{}, fmt.Errorf("no forwarder found for chain %d", c.Selector) + } + } + + resp, err := kslib.ConfigureContracts(context.TODO(), lggr, *req) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure contracts: %w", err) + } + return *resp.Changeset, nil +} diff --git a/integration-tests/deployment/keystone/changeset/deploy_forwarder.go b/integration-tests/deployment/keystone/changeset/deploy_forwarder.go new file mode 100644 index 00000000000..7f5bb83a375 --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/deploy_forwarder.go @@ -0,0 +1,29 @@ +package changeset + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + kslib "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" +) + +func DeployForwarder(lggr logger.Logger, env deployment.Environment, ab deployment.AddressBook, registryChainSel uint64) (deployment.ChangesetOutput, error) { + // expect OCR3 to be deployed & capabilities registry + regAddrs, err := ab.AddressesForChain(registryChainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", registryChainSel, err) + } + if len(regAddrs) != 2 { + return deployment.ChangesetOutput{}, fmt.Errorf("expected 2 addresses for chain %d, got %d", registryChainSel, len(regAddrs)) + } + for _, c := range env.Chains { + lggr.Infow("deploying forwarder", "chainSelector", c.Selector) + err := kslib.DeployForwarder(lggr, c, ab) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy KeystoneForwarder to chain selector %d: %w", c.Selector, err) + } + } + + return deployment.ChangesetOutput{AddressBook: ab}, nil +} diff --git a/integration-tests/deployment/keystone/changeset/deploy_forwarder_test.go b/integration-tests/deployment/keystone/changeset/deploy_forwarder_test.go new file mode 100644 index 00000000000..fc74b68dd16 --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/deploy_forwarder_test.go @@ -0,0 +1,76 @@ +package changeset_test + +import ( + "testing" + + "go.uber.org/zap/zapcore" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + kslb "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" +) + +func TestDeployForwarder(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] + t.Run("err if no capabilities registry on registry chain", func(t *testing.T) { + ab := deployment.NewMemoryAddressBook() + m := make(map[uint64]map[string]deployment.TypeAndVersion) + m[registrySel] = map[string]deployment.TypeAndVersion{ + "0x0000000000000000000000000000000000000002": kslb.OCR3CapabilityTypeVersion, + } + deployment.NewMemoryAddressBookFromMap(m) + // capabilities registry and ocr3 must be deployed on registry chain + _, err := changeset.DeployForwarder(lggr, env, ab, registrySel) + require.Error(t, err) + }) + + t.Run("err if no ocr3 on registry chain", func(t *testing.T) { + ab := deployment.NewMemoryAddressBook() + m := make(map[uint64]map[string]deployment.TypeAndVersion) + m[registrySel] = map[string]deployment.TypeAndVersion{ + "0x0000000000000000000000000000000000000001": kslb.CapabilityRegistryTypeVersion, + } + deployment.NewMemoryAddressBookFromMap(m) + // capabilities registry and ocr3 must be deployed on registry chain + _, err := changeset.DeployForwarder(lggr, env, ab, registrySel) + require.Error(t, err) + }) + + t.Run("should deploy forwarder", func(t *testing.T) { + ab := deployment.NewMemoryAddressBook() + // fake capabilities registry + err := ab.Save(registrySel, "0x0000000000000000000000000000000000000001", kslb.CapabilityRegistryTypeVersion) + require.NoError(t, err) + + // fake ocr3 + err = ab.Save(registrySel, "0x0000000000000000000000000000000000000002", kslb.OCR3CapabilityTypeVersion) + require.NoError(t, err) + // deploy forwarder + resp, err := changeset.DeployForwarder(lggr, env, ab, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + // registry, ocr3, forwarder should be deployed on registry chain + addrs, err := resp.AddressBook.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 3) + + // only forwarder on chain 1 + require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) + oaddrs, err := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) + require.NoError(t, err) + require.Len(t, oaddrs, 1) + }) +} diff --git a/integration-tests/deployment/keystone/changeset/deploy_ocr3.go b/integration-tests/deployment/keystone/changeset/deploy_ocr3.go new file mode 100644 index 00000000000..51566787bd0 --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/deploy_ocr3.go @@ -0,0 +1,40 @@ +package changeset + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + kslib "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" +) + +func DeployOCR3(lggr logger.Logger, env deployment.Environment, ab deployment.AddressBook, registryChainSel uint64) (deployment.ChangesetOutput, error) { + // must have capabilities registry deployed + regAddrs, err := ab.AddressesForChain(registryChainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", registryChainSel, err) + } + found := false + for _, addr := range regAddrs { + if addr.Type == kslib.CapabilityRegistryTypeVersion.Type { + found = true + break + } + } + if !found { + return deployment.ChangesetOutput{}, fmt.Errorf("no capabilities registry found for changeset %s", "0001_deploy_registry") + } + + // ocr3 only deployed on registry chain + c, ok := env.Chains[registryChainSel] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + } + err = kslib.DeployOCR3(lggr, c, ab) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy OCR3Capability: %w", err) + } + + return deployment.ChangesetOutput{AddressBook: ab}, nil + +} diff --git a/integration-tests/deployment/keystone/changeset/deploy_ocr3_test.go b/integration-tests/deployment/keystone/changeset/deploy_ocr3_test.go new file mode 100644 index 00000000000..eb7e34e7bcd --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/deploy_ocr3_test.go @@ -0,0 +1,48 @@ +package changeset_test + +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/integration-tests/deployment" + kslb "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" +) + +func TestDeployOCR3(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + ab := deployment.NewMemoryAddressBook() + 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] + // err if no capabilities registry on chain 0 + _, err := changeset.DeployOCR3(lggr, env, ab, registrySel) + require.Error(t, err) + + // fake capabilities registry + err = ab.Save(registrySel, "0x0000000000000000000000000000000000000001", kslb.CapabilityRegistryTypeVersion) + require.NoError(t, err) + resp, err := changeset.DeployOCR3(lggr, env, ab, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + // OCR3 should be deployed on chain 0 + addrs, err := resp.AddressBook.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 2) + + // nothing on chain 1 + require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) + oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) + assert.Len(t, oaddrs, 0) +} diff --git a/integration-tests/deployment/keystone/changeset/deploy_registry.go b/integration-tests/deployment/keystone/changeset/deploy_registry.go new file mode 100644 index 00000000000..d161c3f6cdd --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/deploy_registry.go @@ -0,0 +1,22 @@ +package changeset + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + kslib "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" +) + +func DeployCapabilityRegistry(lggr logger.Logger, env deployment.Environment, ab deployment.AddressBook, registryChainSel uint64) (deployment.ChangesetOutput, error) { + c, ok := env.Chains[registryChainSel] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + } + err := kslib.DeployCapabilitiesRegistry(lggr, c, ab) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + } + return deployment.ChangesetOutput{AddressBook: ab}, nil +} diff --git a/integration-tests/deployment/keystone/changeset/deploy_registry_test.go b/integration-tests/deployment/keystone/changeset/deploy_registry_test.go new file mode 100644 index 00000000000..11e794a92eb --- /dev/null +++ b/integration-tests/deployment/keystone/changeset/deploy_registry_test.go @@ -0,0 +1,40 @@ +package changeset_test + +import ( + "testing" + + "go.uber.org/zap/zapcore" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" +) + +func TestDeployCapabilityRegistry(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + ab := deployment.NewMemoryAddressBook() + cfg := memory.MemoryEnvironmentConfig{ + Nodes: 1, + Chains: 2, + } + env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) + + registrySel := env.AllChainSelectors()[0] + resp, err := changeset.DeployCapabilityRegistry(lggr, env, ab, registrySel) + require.NoError(t, err) + require.NotNil(t, resp) + // capabilities registry should be deployed on chain 0 + addrs, err := resp.AddressBook.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 1) + + // 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) + +} diff --git a/integration-tests/deployment/keystone/contract_set.go b/integration-tests/deployment/keystone/contract_set.go new file mode 100644 index 00000000000..d82532614ae --- /dev/null +++ b/integration-tests/deployment/keystone/contract_set.go @@ -0,0 +1,93 @@ +package keystone + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" +) + +type deployContractsRequest struct { + chain deployment.Chain + isRegistryChain bool + ad deployment.AddressBook +} + +type deployContractSetResponse struct { + deployment.AddressBook +} + +func deployContractsToChain(lggr logger.Logger, req deployContractsRequest) (*deployContractSetResponse, error) { + if req.ad == nil { + req.ad = deployment.NewMemoryAddressBook() + } + // this is mutated in the Deploy* functions + resp := &deployContractSetResponse{ + AddressBook: req.ad, + } + + // cap reg and ocr3 only deployed on registry chain + if req.isRegistryChain { + err := DeployCapabilitiesRegistry(lggr, req.chain, resp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + } + err = DeployOCR3(lggr, req.chain, resp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) + } + } + err := DeployForwarder(lggr, req.chain, resp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + } + return resp, nil +} + +// DeployCapabilitiesRegistry deploys the CapabilitiesRegistry contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployCapabilitiesRegistry(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { + capabilitiesRegistryDeployer := CapabilitiesRegistryDeployer{lggr: lggr} + capabilitiesRegistryResp, err := capabilitiesRegistryDeployer.deploy(deployRequest{Chain: chain}) + if err != nil { + return fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + } + err = ab.Save(chain.Selector, capabilitiesRegistryResp.Address.String(), capabilitiesRegistryResp.Tv) + if err != nil { + return fmt.Errorf("failed to save CapabilitiesRegistry: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", CapabilityRegistryTypeVersion.String(), chain.Selector, capabilitiesRegistryResp.Address.String()) + return nil +} + +// DeployOCR3 deploys the OCR3Capability contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployOCR3(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { + ocr3Deployer := OCR3Deployer{lggr: lggr} + ocr3Resp, err := ocr3Deployer.deploy(deployRequest{Chain: chain}) + if err != nil { + return fmt.Errorf("failed to deploy OCR3Capability: %w", err) + } + err = ab.Save(chain.Selector, ocr3Resp.Address.String(), ocr3Resp.Tv) + if err != nil { + return fmt.Errorf("failed to save OCR3Capability: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", ocr3Resp.Tv.String(), chain.Selector, ocr3Resp.Address.String()) + return nil +} + +// DeployForwarder deploys the KeystoneForwarder contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployForwarder(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { + forwarderDeployer := KeystoneForwarderDeployer{lggr: lggr} + forwarderResp, err := forwarderDeployer.deploy(deployRequest{Chain: chain}) + if err != nil { + return fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + } + err = ab.Save(chain.Selector, forwarderResp.Address.String(), forwarderResp.Tv) + if err != nil { + return fmt.Errorf("failed to save KeystoneForwarder: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", forwarderResp.Tv.String(), chain.Selector, forwarderResp.Address.String()) + return nil +} diff --git a/integration-tests/deployment/keystone/deploy.go b/integration-tests/deployment/keystone/deploy.go new file mode 100644 index 00000000000..204247fd721 --- /dev/null +++ b/integration-tests/deployment/keystone/deploy.go @@ -0,0 +1,805 @@ +package keystone + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "sort" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + + chainsel "github.com/smartcontractkit/chain-selectors" + + 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" + kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +type ConfigureContractsRequest struct { + RegistryChainSel uint64 + Env *deployment.Environment + + Dons []DonCapabilities // externally sourced based on the environment + OCR3Config *OracleConfigSource // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config + + AddressBook deployment.AddressBook + DoContractDeploy bool // if false, the contracts are assumed to be deployed and the address book is used +} + +func (r ConfigureContractsRequest) Validate() error { + if r.OCR3Config == nil { + return errors.New("OCR3Config is nil") + } + if r.Env == nil { + return errors.New("environment is nil") + } + if r.AddressBook == nil { + return errors.New("address book is nil") + } + if len(r.Dons) == 0 { + return errors.New("no DONS") + } + _, ok := chainsel.ChainBySelector(r.RegistryChainSel) + if !ok { + return fmt.Errorf("chain %d not found in environment", r.RegistryChainSel) + } + return nil +} + +type ConfigureContractsResponse struct { + Changeset *deployment.ChangesetOutput + DonInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo +} + +// ConfigureContracts configures contracts them with the given DONS and their capabilities. It optionally deploys the contracts +// but best practice is to deploy them separately and pass the address book in the request +func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest) (*ConfigureContractsResponse, error) { + if err := req.Validate(); err != nil { + return nil, fmt.Errorf("invalid request: %w", err) + } + + addrBook := req.AddressBook + if req.DoContractDeploy { + contractDeployCS, err := DeployContracts(lggr, req.Env, req.RegistryChainSel) + if err != nil { + return nil, fmt.Errorf("failed to deploy contracts: %w", err) + } + addrBook = contractDeployCS.AddressBook + } else { + lggr.Debug("skipping contract deployment") + } + if addrBook == nil { + return nil, errors.New("address book is nil") + } + + cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, addrBook) + if err != nil { + return nil, fmt.Errorf("failed to configure registry: %w", err) + } + + // now we have the capability registry set up we need to configure the forwarder contracts and the OCR3 contract + dons, err := joinInfoAndNodes(cfgRegistryResp.DonInfos, req.Dons) + if err != nil { + return nil, fmt.Errorf("failed to assimilate registry to Dons: %w", err) + } + err = ConfigureForwardContracts(req.Env, dons, addrBook) + if err != nil { + return nil, fmt.Errorf("failed to configure forwarder contracts: %w", err) + } + + err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, addrBook, req.OCR3Config) + if err != nil { + return nil, fmt.Errorf("failed to configure OCR3 contract: %w", err) + } + + return &ConfigureContractsResponse{ + Changeset: &deployment.ChangesetOutput{ + AddressBook: addrBook, + }, + DonInfos: cfgRegistryResp.DonInfos, + }, nil +} + +// DeployContracts deploys the all the keystone contracts on all chains and returns the address book in the changeset +func DeployContracts(lggr logger.Logger, e *deployment.Environment, chainSel uint64) (*deployment.ChangesetOutput, error) { + adbook := deployment.NewMemoryAddressBook() + // deploy contracts on all chains and track the registry and ocr3 contracts + for _, chain := range e.Chains { + lggr.Infow("deploying contracts", "chain", chain.Selector) + deployResp, err := deployContractsToChain(lggr, deployContractsRequest{ + chain: chain, + isRegistryChain: chain.Selector == chainSel, + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to deploy contracts: %w", err) + } + err = adbook.Merge(deployResp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to merge address book: %w", err) + } + } + return &deployment.ChangesetOutput{ + AddressBook: adbook, + }, nil +} + +// ConfigureRegistry configures the registry contract with the given DONS and their capabilities +// the address book is required to contain the addresses of the deployed registry contract +func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { + registryChain, ok := req.Env.Chains[req.RegistryChainSel] + if !ok { + return nil, fmt.Errorf("chain %d not found in environment", req.RegistryChainSel) + } + + contractSetsResp, err := GetContractSets(&GetContractSetsRequest{ + Chains: req.Env.Chains, + AddressBook: addrBook, + }) + if err != nil { + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + + // ensure registry is deployed and get the registry contract and chain + var registry *capabilities_registry.CapabilitiesRegistry + registryChainContracts, ok := contractSetsResp.ContractSets[req.RegistryChainSel] + if !ok { + return nil, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", req.RegistryChainSel) + } + registry = registryChainContracts.CapabilitiesRegistry + if registry == nil { + return nil, fmt.Errorf("no registry contract found") + } + lggr.Debugf("registry contract address: %s, chain %d", registry.Address().String(), req.RegistryChainSel) + + // all the subsequent calls to the registry are in terms of nodes + // compute the mapping of dons to their nodes for reuse in various registry calls + donToOcr2Nodes, err := mapDonsToNodes(req.Dons, true) + if err != nil { + return nil, fmt.Errorf("failed to map dons to nodes: %w", err) + } + + // TODO: we can remove this abstractions and refactor the functions that accept them to accept []DonCapabilities + // they are unnecessary indirection + donToCapabilities := mapDonsToCaps(req.Dons) + nodeIdToNop, err := nodesToNops(req.Dons, req.RegistryChainSel) + if err != nil { + return nil, fmt.Errorf("failed to map nodes to nops: %w", err) + } + + // register capabilities + capabilitiesResp, err := registerCapabilities(lggr, registerCapabilitiesRequest{ + chain: registryChain, + registry: registry, + donToCapabilities: donToCapabilities, + }) + if err != nil { + return nil, fmt.Errorf("failed to register capabilities: %w", err) + } + lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.donToCapabilities) + + // register node operators + var nops []capabilities_registry.CapabilitiesRegistryNodeOperator + for _, nop := range nodeIdToNop { + nops = append(nops, nop) + } + nopsResp, err := registerNOPS(ctx, registerNOPSRequest{ + chain: registryChain, + registry: registry, + nops: nops, + }) + if err != nil { + return nil, fmt.Errorf("failed to register node operators: %w", err) + } + lggr.Infow("registered node operators", "nops", nopsResp.nops) + + // register nodes + nodesResp, err := registerNodes(lggr, ®isterNodesRequest{ + registry: registry, + chain: registryChain, + nodeIdToNop: nodeIdToNop, + donToOcr2Nodes: donToOcr2Nodes, + donToCapabilities: capabilitiesResp.donToCapabilities, + nops: nopsResp.nops, + }) + if err != nil { + return nil, fmt.Errorf("failed to register nodes: %w", err) + } + lggr.Infow("registered nodes", "nodes", nodesResp.nodeIDToParams) + + // register DONS + donsResp, err := registerDons(lggr, registerDonsRequest{ + registry: registry, + chain: registryChain, + nodeIDToParams: nodesResp.nodeIDToParams, + donToCapabilities: capabilitiesResp.donToCapabilities, + donToOcr2Nodes: donToOcr2Nodes, + }) + if err != nil { + return nil, fmt.Errorf("failed to register DONS: %w", err) + } + lggr.Infow("registered DONS", "dons", len(donsResp.donInfos)) + + return &ConfigureContractsResponse{ + Changeset: &deployment.ChangesetOutput{ + AddressBook: addrBook, + }, + DonInfos: donsResp.donInfos, + }, nil +} + +// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS +// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment +func ConfigureForwardContracts(env *deployment.Environment, dons []RegisteredDon, addrBook deployment.AddressBook) error { + contractSetsResp, err := GetContractSets(&GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: addrBook, + }) + if err != nil { + return fmt.Errorf("failed to get contract sets: %w", err) + } + + // configure forwarders on all chains + for _, chain := range env.Chains { + // get the forwarder contract for the chain + contracts, ok := contractSetsResp.ContractSets[chain.Selector] + if !ok { + return fmt.Errorf("failed to get contract set for chain %d", chain.Selector) + } + fwrd := contracts.Forwarder + if fwrd == nil { + return fmt.Errorf("no forwarder contract found for chain %d", chain.Selector) + } + + err := configureForwarder(chain, fwrd, dons) + if err != nil { + return fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) + } + } + return nil +} + +// ocr3 contract on the registry chain for the wf dons +func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, addrBook deployment.AddressBook, cfg *OracleConfigSource) error { + registryChain, ok := env.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found in environment", chainSel) + } + + contractSetsResp, err := GetContractSets(&GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: addrBook, + }) + if err != nil { + return fmt.Errorf("failed to get contract sets: %w", err) + } + + for _, don := range dons { + if !don.Info.AcceptsWorkflows { + continue + } + // only on the registry chain + contracts, ok := contractSetsResp.ContractSets[chainSel] + if !ok { + return fmt.Errorf("failed to get contract set for chain %d", chainSel) + } + contract := contracts.OCR3 + if contract == nil { + return fmt.Errorf("no forwarder contract found for chain %d", chainSel) + } + + _, err := configureOCR3contract(configureOCR3Request{ + cfg: cfg, + chain: registryChain, + contract: contract, + don: don, + }) + if err != nil { + return fmt.Errorf("failed to configure OCR3 contract for don %s: %w", don.Name, err) + } + } + return nil +} + +type registerCapabilitiesRequest struct { + chain deployment.Chain + registry *capabilities_registry.CapabilitiesRegistry + donToCapabilities map[string][]kcr.CapabilitiesRegistryCapability +} + +type registerCapabilitiesResponse struct { + donToCapabilities map[string][]registeredCapability +} + +type registeredCapability struct { + capabilities_registry.CapabilitiesRegistryCapability + id [32]byte +} + +// 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") + } + resp := ®isterCapabilitiesResponse{ + donToCapabilities: make(map[string][]registeredCapability), + } + + // capability could be hosted on multiple dons. need to deduplicate + uniqueCaps := make(map[kcr.CapabilitiesRegistryCapability][32]byte) + for don, caps := range req.donToCapabilities { + var registerCaps []registeredCapability + for _, cap := range caps { + id, ok := uniqueCaps[cap] + if !ok { + var err error + id, err = req.registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + if err != nil { + return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) + } + uniqueCaps[cap] = id + } + registerCap := registeredCapability{ + CapabilitiesRegistryCapability: cap, + id: id, + } + lggr.Debugw("hashed capability id", "capability", cap, "id", id) + registerCaps = append(registerCaps, registerCap) + } + resp.donToCapabilities[don] = registerCaps + } + + var capabilities []kcr.CapabilitiesRegistryCapability + for cap := range uniqueCaps { + capabilities = append(capabilities, cap) + } + + tx, err := req.registry.AddCapabilities(req.chain.DeployerKey, capabilities) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + // no typed errors in the abi, so we have to do string matching + // try to add all capabilities in one go, if that fails, fall back to 1-by-1 + if !strings.Contains(err.Error(), "CapabilityAlreadyExists") { + return nil, fmt.Errorf("failed to call AddCapabilities: %w", err) + } + lggr.Warnw("capabilities already exist, falling back to 1-by-1", "capabilities", capabilities) + for _, cap := range capabilities { + tx, err = req.registry.AddCapabilities(req.chain.DeployerKey, []kcr.CapabilitiesRegistryCapability{cap}) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + if strings.Contains(err.Error(), "CapabilityAlreadyExists") { + lggr.Warnw("capability already exists, skipping", "capability", cap) + continue + } + return nil, fmt.Errorf("failed to call AddCapabilities for capability %v: %w", cap, err) + } + // 1-by-1 tx is pending and we need to wait for it to be mined + _, err = req.chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) + } + lggr.Debugw("registered capability", "capability", cap) + + } + } else { + // the bulk add tx is pending and we need to wait for it to be mined + _, err = req.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", capabilities) + } + return resp, nil +} + +type registerNOPSRequest struct { + chain deployment.Chain + registry *capabilities_registry.CapabilitiesRegistry + nops []capabilities_registry.CapabilitiesRegistryNodeOperator +} + +type registerNOPSResponse struct { + nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded +} + +func registerNOPS(ctx context.Context, req registerNOPSRequest) (*registerNOPSResponse, error) { + nops := req.nops + tx, err := req.registry.AddNodeOperators(req.chain.DeployerKey, nops) + if err != nil { + err = DecodeErr(kcr.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 = req.chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) + } + + receipt, err := bind.WaitMined(ctx, req.chain.Client, tx) + if err != nil { + return nil, fmt.Errorf("failed to mine AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) + } + if len(receipt.Logs) != len(nops) { + return nil, fmt.Errorf("expected %d log entries for AddNodeOperators, got %d", len(nops), len(receipt.Logs)) + } + resp := ®isterNOPSResponse{ + nops: make([]*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded, len(receipt.Logs)), + } + for i, log := range receipt.Logs { + o, err := req.registry.ParseNodeOperatorAdded(*log) + if err != nil { + return nil, fmt.Errorf("failed to parse log %d for operator added: %w", i, err) + } + resp.nops[i] = o + } + + return resp, nil +} + +func defaultCapConfig(capType uint8, nNodes int) *capabilitiespb.CapabilityConfig { + switch capType { + // TODO: use the enum defined in ?? + case uint8(0): // trigger + return &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), + // F + 1; assuming n = 3f+1 + MinResponsesToAggregate: uint32(nNodes/3) + 1, + }, + }, + } + case uint8(2): // consensus + return &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } + case uint8(3): // target + return &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, // TODO: const defn in a common place + }, + }, + } + default: + return &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } + } +} + +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 { + registry *capabilities_registry.CapabilitiesRegistry + chain deployment.Chain + nodeIdToNop map[string]capabilities_registry.CapabilitiesRegistryNodeOperator + donToOcr2Nodes map[string][]*ocr2Node + donToCapabilities map[string][]registeredCapability + nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded +} +type registerNodesResponse struct { + nodeIDToParams map[string]capabilities_registry.CapabilitiesRegistryNodeParams +} + +// 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) { + nopToNodeIDs := make(map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string) + for nodeID, nop := range req.nodeIdToNop { + if _, ok := nopToNodeIDs[nop]; !ok { + nopToNodeIDs[nop] = make([]string, 0) + } + nopToNodeIDs[nop] = append(nopToNodeIDs[nop], nodeID) + } + nodeToRegisterNop := make(map[string]*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded) + for _, nop := range req.nops { + n := capabilities_registry.CapabilitiesRegistryNodeOperator{ + Name: nop.Name, + Admin: nop.Admin, + } + nodeIDs := nopToNodeIDs[n] + for _, nodeID := range nodeIDs { + _, exists := nodeToRegisterNop[nodeID] + if !exists { + nodeToRegisterNop[nodeID] = nop + } + } + } + + nodeIDToParams := make(map[string]capabilities_registry.CapabilitiesRegistryNodeParams) + for don, ocr2nodes := range req.donToOcr2Nodes { + caps, ok := req.donToCapabilities[don] + if !ok { + return nil, fmt.Errorf("capabilities not found for node operator %s", don) + } + var hashedCapabilityIds [][32]byte + for _, cap := range caps { + hashedCapabilityIds = append(hashedCapabilityIds, cap.id) + } + lggr.Debugw("hashed capability ids", "don", don, "ids", hashedCapabilityIds) + + for _, n := range ocr2nodes { + if n.IsBoostrap { // bootstraps are part of the DON but don't host capabilities + continue + } + nop, ok := nodeToRegisterNop[n.ID] + if !ok { + return nil, fmt.Errorf("node operator not found for node %s", n.ID) + } + params, ok := nodeIDToParams[n.ID] + + if !ok { + params = capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nop.NodeOperatorId, + Signer: n.Signer, + P2pId: n.P2PKey, + EncryptionPublicKey: n.EncryptionPublicKey, + HashedCapabilityIds: hashedCapabilityIds, + } + } else { + // when we have a node operator, we need to dedup capabilities against the existing ones + var newCapIds [][32]byte + for _, proposedCapId := range hashedCapabilityIds { + shouldAdd := true + for _, existingCapId := range params.HashedCapabilityIds { + if existingCapId == proposedCapId { + shouldAdd = false + break + } + } + if shouldAdd { + newCapIds = append(newCapIds, proposedCapId) + } + } + params.HashedCapabilityIds = append(params.HashedCapabilityIds, newCapIds...) + } + nodeIDToParams[n.ID] = params + } + } + + var uniqueNodeParams []capabilities_registry.CapabilitiesRegistryNodeParams + for _, v := range nodeIDToParams { + uniqueNodeParams = append(uniqueNodeParams, v) + } + lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams)) + tx, err := req.registry.AddNodes(req.chain.DeployerKey, uniqueNodeParams) + if err != nil { + err = DecodeErr(kcr.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") { + return nil, fmt.Errorf("failed to call AddNodes for bulk add nodes: %w", err) + } + lggr.Warn("nodes already exist, falling back to 1-by-1") + for _, singleNodeParams := range uniqueNodeParams { + tx, err = req.registry.AddNodes(req.chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeParams{singleNodeParams}) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + if strings.Contains(err.Error(), "NodeAlreadyExists") { + lggr.Warnw("node already exists, skipping", "p2pid", singleNodeParams.P2pId) + continue + } + return nil, fmt.Errorf("failed to call AddNode for node with p2pid %v: %w", singleNodeParams.P2pId, err) + } + // 1-by-1 tx is pending and we need to wait for it to be mined + _, err = req.chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm AddNode of p2pid node %v transaction %s: %w", singleNodeParams.P2pId, tx.Hash().String(), err) + } + lggr.Debugw("registered node", "p2pid", singleNodeParams.P2pId) + } + } else { + // the bulk add tx is pending and we need to wait for it to be mined + _, err = req.chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm AddNode confirm transaction %s: %w", tx.Hash().String(), err) + } + } + return ®isterNodesResponse{ + nodeIDToParams: nodeIDToParams, + }, nil +} + +type registerDonsRequest struct { + registry *capabilities_registry.CapabilitiesRegistry + chain deployment.Chain + + nodeIDToParams map[string]capabilities_registry.CapabilitiesRegistryNodeParams + donToCapabilities map[string][]registeredCapability + donToOcr2Nodes map[string][]*ocr2Node +} + +type registerDonsResponse struct { + donInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo +} + +func sortedHash(p2pids [][32]byte) string { + sha256Hash := sha256.New() + sort.Slice(p2pids, func(i, j int) bool { + return bytes.Compare(p2pids[i][:], p2pids[j][:]) < 0 + }) + for _, id := range p2pids { + sha256Hash.Write(id[:]) + } + return hex.EncodeToString(sha256Hash.Sum(nil)) +} + +func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsResponse, error) { + resp := ®isterDonsResponse{ + donInfos: make(map[string]capabilities_registry.CapabilitiesRegistryDONInfo), + } + // track hash of sorted p2pids to don name because the registry return value does not include the don name + // and we need to map it back to the don name to access the other mapping data such as the don's capabilities & nodes + p2pIdsToDon := make(map[string]string) + + for don, ocr2nodes := range req.donToOcr2Nodes { + var p2pIds [][32]byte + for _, n := range ocr2nodes { + if n.IsBoostrap { + continue + } + params, ok := req.nodeIDToParams[n.ID] + if !ok { + return nil, fmt.Errorf("node params not found for non-bootstrap node %s", n.ID) + } + p2pIds = append(p2pIds, params.P2pId) + } + + p2pSortedHash := sortedHash(p2pIds) + p2pIdsToDon[p2pSortedHash] = don + caps, ok := req.donToCapabilities[don] + if !ok { + return nil, fmt.Errorf("capabilities not found for node operator %s", don) + } + wfSupported := false + var cfgs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration + for _, cap := range caps { + if cap.CapabilityType == 2 { // OCR3 capability => WF supported + wfSupported = true + } + // TODO: accept configuration from external source for each (don,capability) + capCfg := defaultCapConfig(cap.CapabilityType, len(p2pIds)) + cfgb, err := proto.Marshal(capCfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal capability config for %v: %w", cap, err) + } + cfgs = append(cfgs, capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + CapabilityId: cap.id, + Config: cfgb, + }) + } + + f := len(p2pIds) / 3 // assuming n=3f+1. TODO should come for some config. + tx, err := req.registry.AddDON(req.chain.DeployerKey, p2pIds, cfgs, true, wfSupported, uint8(f)) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don, p2pSortedHash, cfgs, err) + } + _, err = req.chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don, err) + } + lggr.Debugw("registered DON", "don", don, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", f) + } + donInfos, err := req.registry.GetDONs(&bind.CallOpts{}) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + return nil, fmt.Errorf("failed to call GetDONs: %w", err) + } + for i, donInfo := range donInfos { + donName, ok := p2pIdsToDon[sortedHash(donInfo.NodeP2PIds)] + if !ok { + return nil, fmt.Errorf("don not found for p2pids %s in %v", sortedHash(donInfo.NodeP2PIds), p2pIdsToDon) + } + resp.donInfos[donName] = donInfos[i] + } + return resp, nil +} + +// configureForwarder sets the config for the forwarder contract on the chain for all Dons that accept workflows +// dons that don't accept workflows are not registered with the forwarder +func configureForwarder(chain deployment.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon) error { + if fwdr == nil { + return errors.New("nil forwarder contract") + } + for _, dn := range dons { + if !dn.Info.AcceptsWorkflows { + continue + } + ver := dn.Info.ConfigCount // note config count on the don info is the version on the forwarder + tx, err := fwdr.SetConfig(chain.DeployerKey, dn.Info.Id, ver, dn.Info.F, dn.signers()) + if err != nil { + err = DecodeErr(kf.KeystoneForwarderABI, err) + return fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) + } + _, err = chain.Confirm(tx) + if err != nil { + err = DecodeErr(kf.KeystoneForwarderABI, err) + return fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) + } + } + return nil +} + +type configureOCR3Request struct { + cfg *OracleConfigSource + chain deployment.Chain + contract *kocr3.OCR3Capability + don RegisteredDon +} +type configureOCR3Response struct { + ocrConfig Orc2drOracleConfig +} + +func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, error) { + if req.contract == nil { + return nil, fmt.Errorf("OCR3 contract is nil") + } + nks := makeNodeKeysSlice(req.don.Nodes) + ocrConfig, err := GenerateOCR3Config(*req.cfg, nks) + if err != nil { + return nil, fmt.Errorf("failed to generate OCR3 config: %w", err) + } + tx, err := req.contract.SetConfig(req.chain.DeployerKey, + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.OnchainConfig, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + ) + if err != nil { + err = DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + } + _, err = req.chain.Confirm(tx) + if err != nil { + err = DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + } + return &configureOCR3Response{ocrConfig}, nil +} diff --git a/integration-tests/deployment/keystone/deploy_test.go b/integration-tests/deployment/keystone/deploy_test.go new file mode 100644 index 00000000000..b6f34969801 --- /dev/null +++ b/integration-tests/deployment/keystone/deploy_test.go @@ -0,0 +1,202 @@ +package keystone_test + +import ( + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/test-go/testify/require" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/clo" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/clo/models" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/keystone" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeploy(t *testing.T) { + lggr := logger.TestLogger(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}) + + wfDon := keystone.DonCapabilities{ + Name: keystone.WFDonName, + Nops: wfNops, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, + } + cwDon := keystone.DonCapabilities{ + Name: keystone.TargetDonName, + Nops: cwNops, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, + } + assetDon := keystone.DonCapabilities{ + Name: keystone.StreamDonName, + Nops: assetNops, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, + } + + env := makeMultiDonTestEnv(t, lggr, []keystone.DonCapabilities{wfDon, cwDon, assetDon}) + + // sepolia; all nodes are on the this chain + registryChainSel, err := chainsel.SelectorFromChainId(11155111) + require.NoError(t, err) + + var ocr3Config = keystone.OracleConfigSource{ + MaxFaultyOracles: len(wfNops) / 3, + } + + ctx := tests.Context(t) + // explicitly deploy the contracts + cs, err := keystone.DeployContracts(lggr, env, registryChainSel) + require.NoError(t, err) + + deployReq := keystone.ConfigureContractsRequest{ + RegistryChainSel: registryChainSel, + Env: env, + OCR3Config: &ocr3Config, + Dons: []keystone.DonCapabilities{wfDon, cwDon, assetDon}, + AddressBook: cs.AddressBook, + DoContractDeploy: false, + } + deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) + require.NoError(t, err) + ad := deployResp.Changeset.AddressBook + addrs, err := ad.Addresses() + require.NoError(t, err) + lggr.Infow("Deployed Keystone contracts", "address book", addrs) + + // 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(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) + // contract reads + 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)) + + 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 makeMultiDonTestEnv(t *testing.T, lggr logger.Logger, dons []keystone.DonCapabilities) *deployment.Environment { + var donToEnv = make(map[string]*deployment.Environment) + // chain selector lib doesn't support chain id 2 and we don't use it in tests + // because it's not an evm chain + ignoreAptos := func(c *models.NodeChainConfig) bool { + return c.Network.ChainID == "2" // aptos chain + } + for _, don := range dons { + env := clo.NewDonEnvWithMemoryChains(t, clo.DonEnvConfig{ + DonName: don.Name, + Nops: don.Nops, + Logger: lggr, + }, ignoreAptos) + donToEnv[don.Name] = env + } + menv := clo.NewTestEnv(t, lggr, donToEnv) + return menv.Flatten("testing-env") +} + +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/integration-tests/deployment/keystone/forwarder_deployer.go b/integration-tests/deployment/keystone/forwarder_deployer.go new file mode 100644 index 00000000000..8ec58ebe023 --- /dev/null +++ b/integration-tests/deployment/keystone/forwarder_deployer.go @@ -0,0 +1,46 @@ +package keystone + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" +) + +type KeystoneForwarderDeployer struct { + lggr logger.Logger + contract *forwarder.KeystoneForwarder +} + +var ForwarderTypeVersion = deployment.TypeAndVersion{ + Type: KeystoneForwarder, + Version: deployment.Version1_0_0, +} + +func (c *KeystoneForwarderDeployer) deploy(req deployRequest) (*deployResponse, error) { + est, err := estimateDeploymentGas(req.Chain.Client, forwarder.KeystoneForwarderABI) + if err != nil { + return nil, fmt.Errorf("failed to estimate gas: %w", err) + } + c.lggr.Debugf("Forwarder estimated gas: %d", est) + + forwarderAddr, tx, forwarder, err := forwarder.DeployKeystoneForwarder( + req.Chain.DeployerKey, + req.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + } + + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm and save KeystoneForwarder: %w", err) + } + resp := &deployResponse{ + Address: forwarderAddr, + Tx: tx.Hash(), + Tv: ForwarderTypeVersion, + } + c.contract = forwarder + return resp, nil +} diff --git a/integration-tests/deployment/keystone/ocr3_deployer.go b/integration-tests/deployment/keystone/ocr3_deployer.go new file mode 100644 index 00000000000..fb1fddfa16c --- /dev/null +++ b/integration-tests/deployment/keystone/ocr3_deployer.go @@ -0,0 +1,46 @@ +package keystone + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" +) + +type OCR3Deployer struct { + lggr logger.Logger + contract *ocr3_capability.OCR3Capability +} + +var OCR3CapabilityTypeVersion = deployment.TypeAndVersion{ + Type: OCR3Capability, + Version: deployment.Version1_0_0, +} + +func (c *OCR3Deployer) deploy(req deployRequest) (*deployResponse, error) { + est, err := estimateDeploymentGas(req.Chain.Client, ocr3_capability.OCR3CapabilityABI) + if err != nil { + return nil, fmt.Errorf("failed to estimate gas: %w", err) + } + c.lggr.Infof("ocr3 capability estimated gas: %d", est) + + ocr3Addr, tx, ocr3, err := ocr3_capability.DeployOCR3Capability( + req.Chain.DeployerKey, + req.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) + } + + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm transaction %s: %w", tx.Hash().String(), err) + } + resp := &deployResponse{ + Address: ocr3Addr, + Tx: tx.Hash(), + Tv: OCR3CapabilityTypeVersion, + } + c.contract = ocr3 + return resp, nil +} diff --git a/integration-tests/deployment/keystone/ocr3config.go b/integration-tests/deployment/keystone/ocr3config.go new file mode 100644 index 00000000000..343ddae696f --- /dev/null +++ b/integration-tests/deployment/keystone/ocr3config.go @@ -0,0 +1,229 @@ +// 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 + +import ( + "crypto/ed25519" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "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" +) + +type TopLevelConfigSource struct { + OracleConfig OracleConfigSource +} + +type OracleConfigSource struct { + MaxQueryLengthBytes uint32 + MaxObservationLengthBytes uint32 + MaxReportLengthBytes uint32 + MaxRequestBatchSize uint32 + UniqueReports bool + + DeltaProgressMillis uint32 + DeltaResendMillis uint32 + DeltaInitialMillis uint32 + DeltaRoundMillis uint32 + DeltaGraceMillis uint32 + DeltaCertifiedCommitRequestMillis uint32 + DeltaStageMillis uint32 + MaxRoundsPerEpoch uint64 + TransmissionSchedule []int + + MaxDurationQueryMillis uint32 + MaxDurationObservationMillis uint32 + MaxDurationAcceptMillis uint32 + MaxDurationTransmitMillis uint32 + + MaxFaultyOracles int +} + +type NodeKeys struct { + EthAddress string `json:"EthAddress"` + AptosAccount string `json:"AptosAccount"` + AptosBundleID string `json:"AptosBundleID"` + AptosOnchainPublicKey string `json:"AptosOnchainPublicKey"` + P2PPeerID string `json:"P2PPeerID"` // p2p_ + 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_ + CSAPublicKey string `json:"CSAPublicKey"` + EncryptionPublicKey string `json:"EncryptionPublicKey"` +} + +type Orc2drOracleConfig struct { + Signers [][]byte + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte +} + +func (c Orc2drOracleConfig) MarshalJSON() ([]byte, error) { + alias := struct { + Signers []string + Transmitters []string + F uint8 + OnchainConfig string + OffchainConfigVersion uint64 + OffchainConfig string + }{ + Signers: make([]string, len(c.Signers)), + Transmitters: make([]string, len(c.Transmitters)), + F: c.F, + OnchainConfig: "0x" + hex.EncodeToString(c.OnchainConfig), + OffchainConfigVersion: c.OffchainConfigVersion, + OffchainConfig: "0x" + hex.EncodeToString(c.OffchainConfig), + } + + for i, signer := range c.Signers { + alias.Signers[i] = hex.EncodeToString(signer) + } + + for i, transmitter := range c.Transmitters { + alias.Transmitters[i] = transmitter.Hex() + } + + return json.Marshal(alias) +} + +func GenerateOCR3Config(cfg OracleConfigSource, nca []NodeKeys) (Orc2drOracleConfig, error) { + onchainPubKeys := [][]byte{} + allPubKeys := map[string]any{} + for _, n := range nca { + // evm keys always required + if n.OCR2OnchainPublicKey == "" { + return Orc2drOracleConfig{}, errors.New("OCR2OnchainPublicKey is required") + } + ethPubKey := common.HexToAddress(n.OCR2OnchainPublicKey) + pubKeys := map[string]types.OnchainPublicKey{ + string(chaintype.EVM): ethPubKey.Bytes(), + } + // add aptos key if present + if n.AptosOnchainPublicKey != "" { + aptosPubKey, err := hex.DecodeString(n.AptosOnchainPublicKey) + if err != nil { + return Orc2drOracleConfig{}, fmt.Errorf("failed to decode AptosOnchainPublicKey: %w", err) + } + pubKeys[string(chaintype.Aptos)] = aptosPubKey + } + // validate uniqueness of each individual key + for _, key := range pubKeys { + raw := hex.EncodeToString(key) + _, exists := allPubKeys[raw] + if exists { + return Orc2drOracleConfig{}, fmt.Errorf("Duplicate onchain public key: '%s'", raw) + } + allPubKeys[raw] = struct{}{} + } + pubKey, err := ocrcommon.MarshalMultichainPublicKey(pubKeys) + if err != nil { + return Orc2drOracleConfig{}, fmt.Errorf("failed to marshal multichain public key: %w", err) + } + onchainPubKeys = append(onchainPubKeys, pubKey) + } + + offchainPubKeysBytes := []types.OffchainPublicKey{} + for _, n := range nca { + pkBytes, err := hex.DecodeString(n.OCR2OffchainPublicKey) + if err != nil { + return Orc2drOracleConfig{}, fmt.Errorf("failed to decode OCR2OffchainPublicKey: %w", err) + } + + pkBytesFixed := [ed25519.PublicKeySize]byte{} + nCopied := copy(pkBytesFixed[:], pkBytes) + if nCopied != ed25519.PublicKeySize { + return Orc2drOracleConfig{}, fmt.Errorf("wrong num elements copied from ocr2 offchain public key. expected %d but got %d", ed25519.PublicKeySize, nCopied) + } + + offchainPubKeysBytes = append(offchainPubKeysBytes, types.OffchainPublicKey(pkBytesFixed)) + } + + configPubKeysBytes := []types.ConfigEncryptionPublicKey{} + for _, n := range nca { + pkBytes, err := hex.DecodeString(n.OCR2ConfigPublicKey) + if err != nil { + return Orc2drOracleConfig{}, fmt.Errorf("failed to decode OCR2ConfigPublicKey: %w", err) + } + + pkBytesFixed := [ed25519.PublicKeySize]byte{} + n := copy(pkBytesFixed[:], pkBytes) + if n != ed25519.PublicKeySize { + return Orc2drOracleConfig{}, fmt.Errorf("wrong num elements copied from ocr2 config public key. expected %d but got %d", ed25519.PublicKeySize, n) + } + + configPubKeysBytes = append(configPubKeysBytes, types.ConfigEncryptionPublicKey(pkBytesFixed)) + } + + identities := []confighelper.OracleIdentityExtra{} + for index := range nca { + identities = append(identities, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: onchainPubKeys[index][:], + OffchainPublicKey: offchainPubKeysBytes[index], + PeerID: nca[index].P2PPeerID, + TransmitAccount: types.Account(nca[index].EthAddress), + }, + ConfigEncryptionPublicKey: configPubKeysBytes[index], + }) + } + + signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( + time.Duration(cfg.DeltaProgressMillis)*time.Millisecond, + time.Duration(cfg.DeltaResendMillis)*time.Millisecond, + time.Duration(cfg.DeltaInitialMillis)*time.Millisecond, + time.Duration(cfg.DeltaRoundMillis)*time.Millisecond, + time.Duration(cfg.DeltaGraceMillis)*time.Millisecond, + time.Duration(cfg.DeltaCertifiedCommitRequestMillis)*time.Millisecond, + time.Duration(cfg.DeltaStageMillis)*time.Millisecond, + cfg.MaxRoundsPerEpoch, + cfg.TransmissionSchedule, + identities, + nil, // reportingPluginConfig + nil, // maxDurationInitialization + time.Duration(cfg.MaxDurationQueryMillis)*time.Millisecond, + time.Duration(cfg.MaxDurationObservationMillis)*time.Millisecond, + time.Duration(cfg.MaxDurationAcceptMillis)*time.Millisecond, + time.Duration(cfg.MaxDurationTransmitMillis)*time.Millisecond, + cfg.MaxFaultyOracles, + nil, // empty onChain config + ) + if err != nil { + return Orc2drOracleConfig{}, fmt.Errorf("failed to generate contract config args: %w", err) + } + + var configSigners [][]byte + for _, signer := range signers { + configSigners = append(configSigners, signer) + } + + transmitterAddresses, err := evm.AccountToAddress(transmitters) + if err != nil { + return Orc2drOracleConfig{}, fmt.Errorf("failed to convert transmitters to addresses: %w", err) + } + + config := Orc2drOracleConfig{ + Signers: configSigners, + Transmitters: transmitterAddresses, + F: f, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + } + + return config, nil +} diff --git a/integration-tests/deployment/keystone/state.go b/integration-tests/deployment/keystone/state.go new file mode 100644 index 00000000000..cd8769dafa4 --- /dev/null +++ b/integration-tests/deployment/keystone/state.go @@ -0,0 +1,79 @@ +package keystone + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "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" +) + +type GetContractSetsRequest struct { + Chains map[uint64]deployment.Chain + AddressBook deployment.AddressBook +} + +type GetContractSetsResponse struct { + ContractSets map[uint64]ContractSet +} + +type ContractSet struct { + OCR3 *ocr3_capability.OCR3Capability + Forwarder *forwarder.KeystoneForwarder + CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry +} + +func GetContractSets(req *GetContractSetsRequest) (*GetContractSetsResponse, error) { + resp := &GetContractSetsResponse{ + ContractSets: make(map[uint64]ContractSet), + } + for id, chain := range req.Chains { + addrs, err := req.AddressBook.AddressesForChain(id) + if err != nil { + return nil, fmt.Errorf("failed to get addresses for chain %d: %w", id, err) + } + cs, err := loadContractSet(chain, addrs) + if err != nil { + return nil, fmt.Errorf("failed to load contract set for chain %d: %w", id, err) + } + resp.ContractSets[id] = *cs + } + return resp, nil +} + +func loadContractSet(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*ContractSet, error) { + var out ContractSet + + for addr, tv := range addresses { + // todo handle versions + if !tv.Version.Equal(&deployment.Version1_0_0) { + return nil, fmt.Errorf("unsupported version %s", tv.Version.String()) + } + switch tv.Type { + case CapabilitiesRegistry: + c, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(addr), chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to create capability registry contract from address %s: %w", addr, err) + } + out.CapabilitiesRegistry = c + case KeystoneForwarder: + c, err := forwarder.NewKeystoneForwarder(common.HexToAddress(addr), chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to create forwarder contract from address %s: %w", addr, err) + } + out.Forwarder = c + case OCR3Capability: + c, err := ocr3_capability.NewOCR3Capability(common.HexToAddress(addr), chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to create OCR3Capability contract from address %s: %w", addr, err) + } + out.OCR3 = c + default: + return nil, fmt.Errorf("unknown contract type %s", tv.Type) + } + } + return &out, nil +} diff --git a/integration-tests/deployment/keystone/testdata/asset_nodes.json b/integration-tests/deployment/keystone/testdata/asset_nodes.json new file mode 100644 index 00000000000..9c8c4e0fd03 --- /dev/null +++ b/integration-tests/deployment/keystone/testdata/asset_nodes.json @@ -0,0 +1,978 @@ +[ + { + "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/integration-tests/deployment/keystone/testdata/chain_writer_nodes.json b/integration-tests/deployment/keystone/testdata/chain_writer_nodes.json new file mode 100644 index 00000000000..b89a012cd41 --- /dev/null +++ b/integration-tests/deployment/keystone/testdata/chain_writer_nodes.json @@ -0,0 +1,1446 @@ +[ + { + "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" + } +] \ No newline at end of file diff --git a/integration-tests/deployment/keystone/testdata/ocr3config.json b/integration-tests/deployment/keystone/testdata/ocr3config.json new file mode 100644 index 00000000000..6835a4143f4 --- /dev/null +++ b/integration-tests/deployment/keystone/testdata/ocr3config.json @@ -0,0 +1,27 @@ +{ + "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/integration-tests/deployment/keystone/testdata/workflow_nodes.json b/integration-tests/deployment/keystone/testdata/workflow_nodes.json new file mode 100644 index 00000000000..78a8f706ae8 --- /dev/null +++ b/integration-tests/deployment/keystone/testdata/workflow_nodes.json @@ -0,0 +1,1106 @@ +[ + { + "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" + } +] \ No newline at end of file diff --git a/integration-tests/deployment/keystone/types.go b/integration-tests/deployment/keystone/types.go new file mode 100644 index 00000000000..439fe4ed47d --- /dev/null +++ b/integration-tests/deployment/keystone/types.go @@ -0,0 +1,370 @@ +package keystone + +import ( + "encoding/hex" + "errors" + "fmt" + "sort" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/clo/models" + + v1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +var ( + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" + KeystoneForwarder deployment.ContractType = "KeystoneForwarder" + OCR3Capability deployment.ContractType = "OCR3Capability" +) + +type deployResponse struct { + Address common.Address + Tx common.Hash // todo: chain agnostic + Tv deployment.TypeAndVersion +} + +type deployRequest struct { + Chain deployment.Chain +} + +type DonNode struct { + Don string + Node string // not unique across environments +} + +type CapabilityHost struct { + NodeID string // globally unique + Capabilities []capabilities_registry.CapabilitiesRegistryCapability +} + +type Nop struct { + capabilities_registry.CapabilitiesRegistryNodeOperator + NodeIDs []string // nodes run by this operator +} + +// ocr2Node is a subset of the node configuration that is needed to register a node +// with the capabilities registry. Signer and P2PKey are chain agnostic. +// TODO: KS-466 when we migrate fully to the JD offchain client, we should be able remove this shim and use environment.Node directly +type ocr2Node struct { + ID string + Signer [32]byte // note that in capabilities registry we need a [32]byte, but in the forwarder we need a common.Address [20]byte + P2PKey p2pkey.PeerID + EncryptionPublicKey [32]byte + IsBoostrap bool + // useful when have to register the ocr3 contract config + p2pKeyBundle *v1.OCR2Config_P2PKeyBundle + ethOcr2KeyBundle *v1.OCR2Config_OCRKeyBundle + aptosOcr2KeyBundle *v1.OCR2Config_OCRKeyBundle + csaKey string // *v1.Node.PublicKey + accountAddress string +} + +func (o *ocr2Node) signerAddress() common.Address { + return common.BytesToAddress(o.Signer[:]) +} + +func (o *ocr2Node) toNodeKeys() NodeKeys { + return NodeKeys{ + EthAddress: o.accountAddress, + P2PPeerID: o.p2pKeyBundle.PeerId, + OCR2BundleID: o.ethOcr2KeyBundle.BundleId, + OCR2OnchainPublicKey: o.ethOcr2KeyBundle.OnchainSigningAddress, + OCR2OffchainPublicKey: o.ethOcr2KeyBundle.OffchainPublicKey, + OCR2ConfigPublicKey: o.ethOcr2KeyBundle.ConfigPublicKey, + CSAPublicKey: o.csaKey, + // default value of encryption public key is the CSA public key + // TODO: DEVSVCS-760 + EncryptionPublicKey: o.csaKey, + // TODO Aptos support. How will that be modeled in clo data? + } +} + +func newOcr2Node(id string, ccfgs map[chaintype.ChainType]*v1.ChainConfig, csaPubKey string) (*ocr2Node, error) { + if ccfgs == nil { + return nil, errors.New("nil ocr2config") + } + evmCC, exists := ccfgs[chaintype.EVM] + if !exists { + return nil, errors.New("no evm chain config for node id " + id) + } + + if csaPubKey == "" { + return nil, errors.New("empty csa public key") + } + // parse csapublic key to + csaKey, err := hex.DecodeString(csaPubKey) + if err != nil { + return nil, fmt.Errorf("failed to decode csa public key %s: %w", csaPubKey, err) + } + if len(csaKey) != 32 { + return nil, fmt.Errorf("invalid csa public key '%s'. expected len 32 got %d", csaPubKey, len(csaKey)) + } + var csaKeyb [32]byte + copy(csaKeyb[:], csaKey) + + ocfg := evmCC.Ocr2Config + p := p2pkey.PeerID{} + if err := p.UnmarshalString(ocfg.P2PKeyBundle.PeerId); err != nil { + return nil, fmt.Errorf("failed to unmarshal peer id %s: %w", ocfg.P2PKeyBundle.PeerId, err) + } + + signer := ocfg.OcrKeyBundle.OnchainSigningAddress + if len(signer) != 40 { + return nil, fmt.Errorf("invalid onchain signing address %s", ocfg.OcrKeyBundle.OnchainSigningAddress) + } + signerB, err := hex.DecodeString(signer) + if err != nil { + return nil, fmt.Errorf("failed to convert signer %s: %w", signer, err) + } + + var sigb [32]byte + copy(sigb[:], signerB) + + n := &ocr2Node{ + ID: id, + Signer: sigb, + P2PKey: p, + EncryptionPublicKey: csaKeyb, + IsBoostrap: ocfg.IsBootstrap, + p2pKeyBundle: ocfg.P2PKeyBundle, + ethOcr2KeyBundle: evmCC.Ocr2Config.OcrKeyBundle, + aptosOcr2KeyBundle: nil, + accountAddress: evmCC.AccountAddress, + csaKey: csaPubKey, + } + // aptos chain config is optional + if aptosCC, exists := ccfgs[chaintype.Aptos]; exists { + n.aptosOcr2KeyBundle = aptosCC.Ocr2Config.OcrKeyBundle + } + + return n, nil +} + +func makeNodeKeysSlice(nodes []*ocr2Node) []NodeKeys { + var out []NodeKeys + for _, n := range nodes { + out = append(out, n.toNodeKeys()) + } + return out +} + +// 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 struct { + Name string + Nops []*models.NodeOperator // each nop is a node operator and may have multiple nodes + Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each nop +} + +// map the node id to the NOP +func (dc DonCapabilities) nodeIdToNop(cs uint64) (map[string]capabilities_registry.CapabilitiesRegistryNodeOperator, error) { + cid, err := chainsel.ChainIdFromSelector(cs) + if err != nil { + return nil, fmt.Errorf("failed to get chain id from selector %d: %w", cs, err) + } + cidStr := strconv.FormatUint(cid, 10) + out := make(map[string]capabilities_registry.CapabilitiesRegistryNodeOperator) + for _, nop := range dc.Nops { + for _, node := range nop.Nodes { + found := false + for _, chain := range node.ChainConfigs { + if chain.Network.ChainID == cidStr { + found = true + out[node.ID] = capabilities_registry.CapabilitiesRegistryNodeOperator{ + Name: nop.Name, + Admin: adminAddr(chain.AdminAddress), + } + } + } + if !found { + return nil, fmt.Errorf("node '%s' %s does not support chain %d", node.Name, node.ID, cid) + } + } + } + return out, nil +} + +// helpers to maintain compatibility with the existing registration functions +// nodesToNops converts a list of DonCapabilities to a map of node id to NOP +func nodesToNops(dons []DonCapabilities, chainSel uint64) (map[string]capabilities_registry.CapabilitiesRegistryNodeOperator, error) { + out := make(map[string]capabilities_registry.CapabilitiesRegistryNodeOperator) + for _, don := range dons { + nops, err := don.nodeIdToNop(chainSel) + if err != nil { + return nil, fmt.Errorf("failed to get registry NOPs for don %s: %w", don.Name, err) + } + for donName, nop := range nops { + _, exists := out[donName] + if exists { + continue + } + out[donName] = nop + } + } + return out, nil +} + +// mapDonsToCaps converts a list of DonCapabilities to a map of don name to capabilities +func mapDonsToCaps(dons []DonCapabilities) map[string][]kcr.CapabilitiesRegistryCapability { + out := make(map[string][]kcr.CapabilitiesRegistryCapability) + for _, don := range dons { + out[don.Name] = don.Capabilities + } + return out +} + +// mapDonsToNodes returns a map of don name to simplified representation of their nodes +// all nodes must have evm config and ocr3 capability nodes are must also have an aptos chain config +func mapDonsToNodes(dons []DonCapabilities, excludeBootstraps bool) (map[string][]*ocr2Node, error) { + donToOcr2Nodes := make(map[string][]*ocr2Node) + // get the nodes for each don from the offchain client, get ocr2 config from one of the chain configs for the node b/c + // they are equivalent, and transform to ocr2node representation + + for _, don := range dons { + for _, nop := range don.Nops { + for _, node := range nop.Nodes { + csaPubKey := node.PublicKey + if csaPubKey == nil { + return nil, fmt.Errorf("no public key for node %s", node.ID) + } + // the chain configs are equivalent as far as the ocr2 config is concerned so take the first one + if len(node.ChainConfigs) == 0 { + return nil, fmt.Errorf("no chain configs for node %s. cannot obtain keys", node.ID) + } + // all nodes should have an evm chain config, specifically the registry chain + evmCC, exists := firstChainConfigByType(node.ChainConfigs, chaintype.EVM) + if !exists { + return nil, fmt.Errorf("no evm chain config for node %s", node.ID) + } + cfgs := map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: evmCC, + } + aptosCC, exists := firstChainConfigByType(node.ChainConfigs, chaintype.Aptos) + if exists { + cfgs[chaintype.Aptos] = aptosCC + } + ocr2n, err := newOcr2Node(node.ID, cfgs, *csaPubKey) + if err != nil { + return nil, fmt.Errorf("failed to create ocr2 node for node %s: %w", node.ID, err) + } + if excludeBootstraps && ocr2n.IsBoostrap { + continue + } + if _, ok := donToOcr2Nodes[don.Name]; !ok { + donToOcr2Nodes[don.Name] = make([]*ocr2Node, 0) + } + donToOcr2Nodes[don.Name] = append(donToOcr2Nodes[don.Name], ocr2n) + + } + } + } + + return donToOcr2Nodes, nil +} + +func firstChainConfigByType(ccfgs []*models.NodeChainConfig, t chaintype.ChainType) (*v1.ChainConfig, bool) { + for _, c := range ccfgs { + //nolint:staticcheck //ignore EqualFold it broke ci for some reason (go version skew btw local and ci?) + if strings.ToLower(c.Network.ChainType.String()) == strings.ToLower(string(t)) { + return chainConfigFromClo(c), true + } + } + return nil, false +} + +// RegisteredDon is a representation of a don that exists in the in the capabilities registry all with the enriched node data +type RegisteredDon struct { + Name string + Info capabilities_registry.CapabilitiesRegistryDONInfo + Nodes []*ocr2Node +} + +func (d RegisteredDon) signers() []common.Address { + sort.Slice(d.Nodes, func(i, j int) bool { + return d.Nodes[i].P2PKey.String() < d.Nodes[j].P2PKey.String() + }) + var out []common.Address + for _, n := range d.Nodes { + if n.IsBoostrap { + continue + } + out = append(out, n.signerAddress()) + } + return out +} + +func joinInfoAndNodes(donInfos map[string]kcr.CapabilitiesRegistryDONInfo, dons []DonCapabilities) ([]RegisteredDon, error) { + // all maps should have the same keys + nodes, err := mapDonsToNodes(dons, true) + if err != nil { + return nil, fmt.Errorf("failed to map dons to capabilities: %w", err) + } + if len(donInfos) != len(nodes) { + return nil, fmt.Errorf("mismatched lengths don infos %d, nodes %d", len(donInfos), len(nodes)) + } + 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) + } + out = append(out, RegisteredDon{ + Name: donName, + Info: info, + Nodes: ocr2nodes, + }) + } + + return out, nil +} + +func chainConfigFromClo(chain *models.NodeChainConfig) *v1.ChainConfig { + return &v1.ChainConfig{ + Chain: &v1.Chain{ + Id: chain.Network.ChainID, + Type: v1.ChainType_CHAIN_TYPE_EVM, // TODO: support other chain types + }, + + AccountAddress: chain.AccountAddress, + AdminAddress: chain.AdminAddress, + Ocr2Config: &v1.OCR2Config{ + Enabled: chain.Ocr2Config.Enabled, + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: chain.Ocr2Config.P2pKeyBundle.PeerID, + PublicKey: chain.Ocr2Config.P2pKeyBundle.PublicKey, + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: chain.Ocr2Config.OcrKeyBundle.BundleID, + OnchainSigningAddress: chain.Ocr2Config.OcrKeyBundle.OnchainSigningAddress, + OffchainPublicKey: chain.Ocr2Config.OcrKeyBundle.OffchainPublicKey, + ConfigPublicKey: chain.Ocr2Config.OcrKeyBundle.ConfigPublicKey, + }, + }, + } +} + +var emptyAddr = "0x0000000000000000000000000000000000000000" + +// compute the admin address from the string. If the address is empty, replaces the 0s with fs +// contract registry disallows 0x0 as an admin address, but our test net nops use it +func adminAddr(addr string) common.Address { + needsFixing := addr == emptyAddr + addr = strings.TrimPrefix(addr, "0x") + if needsFixing { + addr = strings.ReplaceAll(addr, "0", "f") + } + return common.HexToAddress(strings.TrimPrefix(addr, "0x")) +} diff --git a/integration-tests/deployment/keystone/types_test.go b/integration-tests/deployment/keystone/types_test.go new file mode 100644 index 00000000000..612e98d3309 --- /dev/null +++ b/integration-tests/deployment/keystone/types_test.go @@ -0,0 +1,402 @@ +package keystone + +import ( + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/test-go/testify/require" + + v1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/clo/models" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" +) + +func Test_newOcr2Node(t *testing.T) { + type args struct { + id string + ccfgs map[chaintype.ChainType]*v1.ChainConfig + csaPubKey string + } + tests := []struct { + name string + args args + wantAptos bool + wantErr bool + }{ + { + name: "no aptos", + args: args{ + id: "1", + ccfgs: map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId", + ConfigPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", + }, + }, + }, + }, + csaPubKey: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + }, + }, + { + name: "with aptos", + args: args{ + id: "1", + ccfgs: map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId", + ConfigPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", + }, + }, + }, + chaintype.Aptos: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZB11111", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId2", + ConfigPublicKey: "0000015fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "111409a8d4f9a18da55c5b2bb08a3f5f68d44777", + }, + }, + }, + }, + csaPubKey: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + }, + wantAptos: true, + }, + { + name: "bad csa key", + args: args{ + id: "1", + ccfgs: map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId", + ConfigPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", + }, + }, + }, + }, + csaPubKey: "not hex", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := newOcr2Node(tt.args.id, tt.args.ccfgs, tt.args.csaPubKey) + if (err != nil) != tt.wantErr { + t.Errorf("newOcr2Node() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.wantErr { + return + } + assert.NotNil(t, got.ethOcr2KeyBundle) + assert.NotNil(t, got.p2pKeyBundle) + assert.NotNil(t, got.Signer) + assert.NotNil(t, got.EncryptionPublicKey) + assert.NotEmpty(t, got.csaKey) + assert.NotEmpty(t, got.P2PKey) + assert.Equal(t, tt.wantAptos, got.aptosOcr2KeyBundle != nil) + }) + } +} + +func Test_mapDonsToNodes(t *testing.T) { + var ( + pubKey = "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1" + evmSig = "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" + aptosSig = "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" + peerID = "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv" + // todo: these should be defined in common + writerCap = 3 + ocr3Cap = 2 + ) + type args struct { + dons []DonCapabilities + excludeBootstraps bool + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "writer evm only", + args: args{ + dons: []DonCapabilities{ + { + Name: "ok writer", + Nops: []*models.NodeOperator{ + { + Nodes: []*models.Node{ + { + PublicKey: &pubKey, + ChainConfigs: []*models.NodeChainConfig{ + { + ID: "1", + Network: &models.Network{ + ChainType: models.ChainTypeEvm, + }, + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: peerID, + }, + OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ + ConfigPublicKey: pubKey, + OffchainPublicKey: pubKey, + OnchainSigningAddress: evmSig, + }, + }, + }, + }, + }, + }, + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{ + { + LabelledName: "writer", + Version: "1", + CapabilityType: uint8(writerCap), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "err if no evm chain", + args: args{ + dons: []DonCapabilities{ + { + Name: "bad chain", + Nops: []*models.NodeOperator{ + { + Nodes: []*models.Node{ + { + PublicKey: &pubKey, + ChainConfigs: []*models.NodeChainConfig{ + { + ID: "1", + Network: &models.Network{ + ChainType: models.ChainTypeSolana, + }, + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: peerID, + }, + OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ + ConfigPublicKey: pubKey, + OffchainPublicKey: pubKey, + OnchainSigningAddress: evmSig, + }, + }, + }, + }, + }, + }, + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{ + { + LabelledName: "writer", + Version: "1", + CapabilityType: uint8(writerCap), + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "ocr3 cap evm only", + args: args{ + dons: []DonCapabilities{ + { + Name: "bad chain", + Nops: []*models.NodeOperator{ + { + Nodes: []*models.Node{ + { + PublicKey: &pubKey, + ChainConfigs: []*models.NodeChainConfig{ + { + ID: "1", + Network: &models.Network{ + ChainType: models.ChainTypeEvm, + }, + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: peerID, + }, + OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ + ConfigPublicKey: pubKey, + OffchainPublicKey: pubKey, + OnchainSigningAddress: evmSig, + }, + }, + }, + }, + }, + }, + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{ + { + LabelledName: "ocr3", + Version: "1", + CapabilityType: uint8(ocr3Cap), + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "ocr3 cap evm & aptos", + args: args{ + dons: []DonCapabilities{ + { + Name: "bad chain", + Nops: []*models.NodeOperator{ + { + Nodes: []*models.Node{ + { + PublicKey: &pubKey, + ChainConfigs: []*models.NodeChainConfig{ + { + ID: "1", + Network: &models.Network{ + ChainType: models.ChainTypeEvm, + }, + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: peerID, + }, + OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ + ConfigPublicKey: pubKey, + OffchainPublicKey: pubKey, + OnchainSigningAddress: evmSig, + }, + }, + }, + { + ID: "2", + Network: &models.Network{ + ChainType: models.ChainTypeAptos, + }, + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: peerID, + }, + OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ + ConfigPublicKey: pubKey, + OffchainPublicKey: pubKey, + OnchainSigningAddress: aptosSig, + }, + }, + }, + }, + }, + }, + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{ + { + LabelledName: "ocr3", + Version: "1", + CapabilityType: uint8(ocr3Cap), + }, + }, + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := mapDonsToNodes(tt.args.dons, tt.args.excludeBootstraps) + if (err != nil) != tt.wantErr { + t.Errorf("mapDonsToNodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } + // make sure the clo test data is correct + 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) + require.Len(t, cwNops, 10) + require.Len(t, assetNops, 16) + + wfDon := DonCapabilities{ + Name: WFDonName, + Nops: wfNops, + Capabilities: []kcr.CapabilitiesRegistryCapability{OCR3Cap}, + } + cwDon := DonCapabilities{ + Name: TargetDonName, + Nops: cwNops, + Capabilities: []kcr.CapabilitiesRegistryCapability{WriteChainCap}, + } + assetDon := DonCapabilities{ + Name: StreamDonName, + Nops: assetNops, + Capabilities: []kcr.CapabilitiesRegistryCapability{StreamTriggerCap}, + } + _, err := mapDonsToNodes([]DonCapabilities{wfDon}, false) + require.NoError(t, err, "failed to map wf don") + _, err = mapDonsToNodes([]DonCapabilities{cwDon}, false) + require.NoError(t, err, "failed to map cw don") + _, err = mapDonsToNodes([]DonCapabilities{assetDon}, false) + require.NoError(t, err, "failed to map asset don") +} + +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/integration-tests/deployment/llo/README.md b/integration-tests/deployment/llo/README.md new file mode 100644 index 00000000000..208a1e2358b --- /dev/null +++ b/integration-tests/deployment/llo/README.md @@ -0,0 +1,5 @@ +### LLO Deployments and Configurations + +This module contains workflows for deploying and configuring Data Streams LLO contracts. + +The contracts in question can be found under contracts/src/v0.8/llo-feeds. diff --git a/integration-tests/deployment/llo/changeset/deploy.go b/integration-tests/deployment/llo/changeset/deploy.go new file mode 100644 index 00000000000..cecd70a7f49 --- /dev/null +++ b/integration-tests/deployment/llo/changeset/deploy.go @@ -0,0 +1,18 @@ +package changeset + +import ( + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + llodeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/llo" +) + +func DeployChannelConfigStoreChangeSet(env deployment.Environment, c llodeployment.DeployLLOContractConfig) (deployment.ChangesetOutput, error) { + ab := deployment.NewMemoryAddressBook() + err := llodeployment.DeployChannelConfigStore(env, ab, c) + if err != nil { + env.Logger.Errorw("Failed to deploy ChannelConfigStore", "err", err, "addresses", ab) + return deployment.ChangesetOutput{AddressBook: ab}, deployment.MaybeDataErr(err) + } + return deployment.ChangesetOutput{ + AddressBook: ab, + }, nil +} diff --git a/integration-tests/deployment/llo/changeset/deploy_test.go b/integration-tests/deployment/llo/changeset/deploy_test.go new file mode 100644 index 00000000000..584470b7555 --- /dev/null +++ b/integration-tests/deployment/llo/changeset/deploy_test.go @@ -0,0 +1,29 @@ +package changeset + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/llo" +) + +func TestDeployChannelConfigStoreChangeSet(t *testing.T) { + e := newMemoryEnv(t) + c := llo.DeployLLOContractConfig{ + ChainsToDeploy: []uint64{TestChain.Selector}, + } + out, err := DeployChannelConfigStoreChangeSet(e, c) + require.NoError(t, err) + + ab, err := out.AddressBook.Addresses() + require.NoError(t, err) + require.Len(t, ab, 1) + + for sel, addrMap := range ab { + require.Equal(t, TestChain.Selector, sel) + for _, tv := range addrMap { + require.Equal(t, tv.Type, llo.ChannelConfigStore) + } + } +} diff --git a/integration-tests/deployment/llo/changeset/helpers_test.go b/integration-tests/deployment/llo/changeset/helpers_test.go new file mode 100644 index 00000000000..ae1d7eb41a9 --- /dev/null +++ b/integration-tests/deployment/llo/changeset/helpers_test.go @@ -0,0 +1,33 @@ +package changeset + +import ( + "testing" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var ( + // TestChain is the chain used by the in-memory environment. + TestChain = chain_selectors.Chain{ + EvmChainID: 90000001, + Selector: 909606746561742123, + Name: "Test Chain", + VarName: "", + } +) + +func newMemoryEnv(t *testing.T) deployment.Environment { + lggr := logger.TestLogger(t) + memEnvConf := memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 4, + Bootstraps: 1, + RegistryConfig: deployment.CapabilityRegistryConfig{}, + } + return memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memEnvConf) +} diff --git a/integration-tests/deployment/llo/deploy.go b/integration-tests/deployment/llo/deploy.go new file mode 100644 index 00000000000..19ae48be574 --- /dev/null +++ b/integration-tests/deployment/llo/deploy.go @@ -0,0 +1,126 @@ +package llo + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" +) + +type DeployLLOContractConfig struct { + ChainsToDeploy []uint64 // Chain Selectors +} + +// LLOContract covers contracts such as channel_config_store.ChannelConfigStore and fee_manager.FeeManager. +type LLOContract interface { + // Caller: + Owner(opts *bind.CallOpts) (common.Address, error) + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + TypeAndVersion(opts *bind.CallOpts) (string, error) + // Transactor: + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) +} + +type ContractDeploy[C LLOContract] struct { + Address common.Address + Contract C + Tx *types.Transaction + Tv deployment.TypeAndVersion + Err error +} + +var ( + ChannelConfigStore deployment.ContractType = "ChannelConfigStore" +) + +func DeployChannelConfigStore(e deployment.Environment, ab deployment.AddressBook, c DeployLLOContractConfig) error { + 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 + } + + for _, chainSel := range c.ChainsToDeploy { + chain, ok := e.Chains[chainSel] + if !ok { + return fmt.Errorf("Chain %d not found", chainSel) + } + _, err = deployChannelConfigStoreToChain(e, chain, ab) + if err != nil { + return err + } + chainAddresses, err := ab.AddressesForChain(chain.Selector) + if err != nil { + e.Logger.Errorw("Failed to get chain addresses", "err", err) + return err + } + chainState, err := LoadChainState(chain, chainAddresses) + if err != nil { + e.Logger.Errorw("Failed to load chain state", "err", err) + return err + } + if chainState.ChannelConfigStore == nil { + errNoCCS := errors.New("no ChannelConfigStore on chain") + e.Logger.Error(errNoCCS) + return errNoCCS + } + } + + return nil +} + +// deployChannelConfigStoreToChain deploys ChannelConfigStore to a specific chain. +// +// Note that this function modifies the given address book variable. +func deployChannelConfigStoreToChain(e deployment.Environment, chain deployment.Chain, ab deployment.AddressBook) (*ContractDeploy[*channel_config_store.ChannelConfigStore], error) { + return deployContract(e.Logger, chain, ab, func(chain deployment.Chain) ContractDeploy[*channel_config_store.ChannelConfigStore] { + ccsAddr, ccsTx, ccs, err := channel_config_store.DeployChannelConfigStore( + chain.DeployerKey, + chain.Client, + ) + if err != nil { + return ContractDeploy[*channel_config_store.ChannelConfigStore]{ + Err: err, + } + } + return ContractDeploy[*channel_config_store.ChannelConfigStore]{ + Address: ccsAddr, + Contract: ccs, + Tx: ccsTx, + Tv: deployment.NewTypeAndVersion(ChannelConfigStore, deployment.Version1_0_0), + Err: nil, + } + }) +} + +func deployContract[C LLOContract]( + lggr logger.Logger, + chain deployment.Chain, + addressBook deployment.AddressBook, + deploy func(chain deployment.Chain) ContractDeploy[C], +) (*ContractDeploy[C], error) { + contractDeploy := deploy(chain) + if contractDeploy.Err != nil { + lggr.Errorw("Failed to deploy contract", "err", contractDeploy.Err) + return nil, contractDeploy.Err + } + _, err := chain.Confirm(contractDeploy.Tx) + if err != nil { + lggr.Errorw("Failed to confirm deployment", "err", err) + return nil, err + } + err = addressBook.Save(chain.Selector, contractDeploy.Address.String(), contractDeploy.Tv) + if err != nil { + lggr.Errorw("Failed to save contract address", "err", err) + return nil, err + } + return &contractDeploy, nil +} diff --git a/integration-tests/deployment/llo/state.go b/integration-tests/deployment/llo/state.go new file mode 100644 index 00000000000..6c149431c18 --- /dev/null +++ b/integration-tests/deployment/llo/state.go @@ -0,0 +1,34 @@ +package llo + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" +) + +// LLOChainState holds a Go binding for all the currently deployed LLO contracts +// on a chain. If a binding is nil, it means here is no such contract on the chain. +type LLOChainState struct { + ChannelConfigStore *channel_config_store.ChannelConfigStore +} + +// LoadChainState Loads all state for a chain into state +func LoadChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (LLOChainState, error) { + var state LLOChainState + for address, tvStr := range addresses { + switch tvStr.String() { + case deployment.NewTypeAndVersion(ChannelConfigStore, deployment.Version1_0_0).String(): + ccs, err := channel_config_store.NewChannelConfigStore(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.ChannelConfigStore = ccs + default: + return state, fmt.Errorf("unknown contract %s", tvStr) + } + } + return state, nil +} diff --git a/integration-tests/deployment/memory/chain.go b/integration-tests/deployment/memory/chain.go new file mode 100644 index 00000000000..0f3badc7dca --- /dev/null +++ b/integration-tests/deployment/memory/chain.go @@ -0,0 +1,96 @@ +package memory + +import ( + "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/core" + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" +) + +type EVMChain struct { + Backend *backends.SimulatedBackend + DeployerKey *bind.TransactOpts +} + +// CCIP relies on block timestamps, but SimulatedBackend uses by default clock starting from 1970-01-01 +// This trick is used to move the clock closer to the current time. We set first block to be X hours ago. +// Tests create plenty of transactions so this number can't be too low, every new block mined will tick the clock, +// if you mine more than "X hours" transactions, SimulatedBackend will panic because generated timestamps will be in the future. +func tweakChainTimestamp(t *testing.T, backend *backends.SimulatedBackend, tweak time.Duration) { + blockTime := time.Unix(int64(backend.Blockchain().CurrentHeader().Time), 0) + sinceBlockTime := time.Since(blockTime) + diff := sinceBlockTime - tweak + err := backend.AdjustTime(diff) + require.NoError(t, err, "unable to adjust time on simulated chain") + backend.Commit() + backend.Commit() +} + +func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *backends.SimulatedBackend) { + ctx := tests.Context(t) + nonce, err := backend.PendingNonceAt(ctx, from.From) + require.NoError(t, err) + gp, err := backend.SuggestGasPrice(ctx) + require.NoError(t, err) + rawTx := gethtypes.NewTx(&gethtypes.LegacyTx{ + Nonce: nonce, + GasPrice: gp, + Gas: 21000, + To: &to, + Value: amount, + }) + signedTx, err := from.Signer(from.From, rawTx) + require.NoError(t, err) + err = backend.SendTransaction(ctx, signedTx) + require.NoError(t, err) + backend.Commit() +} + +func GenerateChains(t *testing.T, numChains int) map[uint64]EVMChain { + chains := make(map[uint64]EVMChain) + for i := 0; i < numChains; i++ { + chainID := chainsel.TEST_90000001.EvmChainID + uint64(i) + key, err := crypto.GenerateKey() + require.NoError(t, err) + owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + require.NoError(t, err) + // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test + backend := backends.NewSimulatedBackend(core.GenesisAlloc{ + owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(7000), big.NewInt(params.Ether))}}, 50000000) + tweakChainTimestamp(t, backend, time.Hour*8) + chains[chainID] = EVMChain{ + Backend: backend, + DeployerKey: owner, + } + } + return chains +} + +func GenerateChainsWithIds(t *testing.T, chainIDs []uint64) map[uint64]EVMChain { + chains := make(map[uint64]EVMChain) + for _, chainID := range chainIDs { + key, err := crypto.GenerateKey() + require.NoError(t, err) + owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + require.NoError(t, err) + backend := backends.NewSimulatedBackend(core.GenesisAlloc{ + owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))}}, 10000000) + tweakChainTimestamp(t, backend, time.Hour*8) + chains[chainID] = EVMChain{ + Backend: backend, + DeployerKey: owner, + } + } + return chains +} diff --git a/integration-tests/deployment/memory/environment.go b/integration-tests/deployment/memory/environment.go new file mode 100644 index 00000000000..641a88d72bb --- /dev/null +++ b/integration-tests/deployment/memory/environment.go @@ -0,0 +1,143 @@ +package memory + +import ( + "context" + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/core/types" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +const ( + Memory = "memory" +) + +type MemoryEnvironmentConfig struct { + Chains int + Nodes int + Bootstraps int + RegistryConfig deployment.CapabilityRegistryConfig +} + +// Needed for environment variables on the node which point to prexisitng addresses. +// i.e. CapReg. +func NewMemoryChains(t *testing.T, numChains int) map[uint64]deployment.Chain { + mchains := GenerateChains(t, numChains) + return generateMemoryChain(t, mchains) +} + +func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64) map[uint64]deployment.Chain { + mchains := GenerateChainsWithIds(t, chainIDs) + return generateMemoryChain(t, mchains) +} + +func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]deployment.Chain { + chains := make(map[uint64]deployment.Chain) + for cid, chain := range inputs { + sel, err := chainsel.SelectorFromChainId(cid) + require.NoError(t, err) + chains[sel] = deployment.Chain{ + Selector: sel, + Client: chain.Backend, + DeployerKey: chain.DeployerKey, + Confirm: func(tx *types.Transaction) (uint64, error) { + if tx == nil { + return 0, fmt.Errorf("tx was nil, nothing to confirm") + } + for { + chain.Backend.Commit() + receipt, err := chain.Backend.TransactionReceipt(context.Background(), tx.Hash()) + if err != nil { + t.Log("failed to get receipt", err) + continue + } + if receipt.Status == 0 { + errReason, err := deployment.GetErrorReasonFromTx(chain.Backend, chain.DeployerKey.From, *tx, receipt) + if err == nil && errReason != "" { + return 0, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) + } + return 0, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) + } + return receipt.BlockNumber.Uint64(), 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 { + mchains := make(map[uint64]EVMChain) + for _, chain := range chains { + evmChainID, err := chainsel.ChainIdFromSelector(chain.Selector) + if err != nil { + t.Fatal(err) + } + mchains[evmChainID] = EVMChain{ + Backend: chain.Client.(*backends.SimulatedBackend), + DeployerKey: chain.DeployerKey, + } + } + nodesByPeerID := make(map[string]Node) + ports := freeport.GetN(t, numBootstraps+numNodes) + // bootstrap nodes must be separate nodes from plugin nodes, + // 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], mchains, 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], mchains, logLevel, false /* bootstrap */, registryConfig) + nodesByPeerID[node.Keys.PeerID.String()] = *node + // Note in real env, this ID is allocated by JD. + } + return nodesByPeerID +} + +func NewMemoryEnvironmentFromChainsNodes(t *testing.T, + lggr logger.Logger, + chains map[uint64]deployment.Chain, + nodes map[string]Node) deployment.Environment { + var nodeIDs []string + for id := range nodes { + nodeIDs = append(nodeIDs, id) + } + return deployment.Environment{ + Name: Memory, + Offchain: NewMemoryJobClient(nodes), + // Note these have the p2p_ prefix. + NodeIDs: nodeIDs, + Chains: chains, + Logger: lggr, + } +} + +// 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) + nodes := NewNodes(t, logLevel, chains, config.Nodes, config.Bootstraps, config.RegistryConfig) + var nodeIDs []string + for id := range nodes { + nodeIDs = append(nodeIDs, id) + } + return deployment.Environment{ + Name: Memory, + Offchain: NewMemoryJobClient(nodes), + NodeIDs: nodeIDs, + Chains: chains, + Logger: lggr, + } +} diff --git a/integration-tests/deployment/memory/job_client.go b/integration-tests/deployment/memory/job_client.go new file mode 100644 index 00000000000..0bd4035c78d --- /dev/null +++ b/integration-tests/deployment/memory/job_client.go @@ -0,0 +1,209 @@ +package memory + +import ( + "context" + "errors" + "fmt" + "strconv" + + "github.com/ethereum/go-ethereum/common" + "google.golang.org/grpc" + + 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/v2/core/capabilities/ccip/validate" +) + +type JobClient struct { + Nodes map[string]Node +} + +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) { + //TODO CCIP-3108 + var fiterIds map[string]struct{} + include := func(id string) bool { + if in.Filter == nil || len(in.Filter.Ids) == 0 { + return true + } + // lazy init + if len(fiterIds) == 0 { + for _, id := range in.Filter.Ids { + fiterIds[id] = struct{}{} + } + } + _, ok := fiterIds[id] + return ok + } + var nodes []*nodev1.Node + for id, n := range j.Nodes { + if include(id) { + nodes = append(nodes, &nodev1.Node{ + Id: id, + PublicKey: n.Keys.OCRKeyBundle.ID(), // is this the correct val? + IsEnabled: true, + IsConnected: true, + }) + } + } + return &nodev1.ListNodesResponse{ + Nodes: nodes, + }, nil + +} + +func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*nodev1.ListNodeChainConfigsResponse, error) { + if in.Filter == nil { + return nil, errors.New("filter is required") + } + if len(in.Filter.NodeIds) != 1 { + return nil, errors.New("only one node id is supported") + } + n, ok := j.Nodes[in.Filter.NodeIds[0]] + if !ok { + return nil, fmt.Errorf("node id not found: %s", in.Filter.NodeIds[0]) + } + offpk := n.Keys.OCRKeyBundle.OffchainPublicKey() + cpk := n.Keys.OCRKeyBundle.ConfigEncryptionPublicKey() + 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: "", + Ocr1Config: nil, + Ocr2Config: &nodev1.OCR2Config{ + Enabled: true, + IsBootstrap: n.IsBoostrap, + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: n.Keys.PeerID.String(), + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + BundleId: n.Keys.OCRKeyBundle.ID(), + ConfigPublicKey: common.Bytes2Hex(cpk[:]), + OffchainPublicKey: common.Bytes2Hex(offpk[:]), + OnchainSigningAddress: n.Keys.OCRKeyBundle.OnChainPublicKey(), + }, + Multiaddr: n.Addr.String(), + Plugins: nil, + ForwarderAddress: ptr(""), + }, + }) + } + + // 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 + 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) { + n := j.Nodes[in.NodeId] + // TODO: Use FMS + jb, err := validate.ValidatedCCIPSpec(in.Spec) + if err != nil { + return nil, err + } + err = n.App.AddJobV2(ctx, &jb) + if err != nil { + return nil, err + } + return &jobv1.ProposeJobResponse{Proposal: &jobv1.Proposal{ + Id: "", + // Auto approve for now + Status: jobv1.ProposalStatus_PROPOSAL_STATUS_APPROVED, + DeliveryStatus: jobv1.ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_DELIVERED, + Spec: in.Spec, + JobId: jb.ExternalJobID.String(), + CreatedAt: nil, + UpdatedAt: nil, + AckedAt: nil, + ResponseReceivedAt: nil, + }}, nil +} + +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") +} + +func (j JobClient) ReplayLogs(selectorToBlock map[uint64]uint64) error { + for _, node := range j.Nodes { + if err := node.ReplayLogs(selectorToBlock); err != nil { + return err + } + } + return nil +} + +func NewMemoryJobClient(nodesByPeerID map[string]Node) *JobClient { + return &JobClient{nodesByPeerID} +} diff --git a/core/capabilities/ccip/ccip_integration_tests/ocr_node_helper.go b/integration-tests/deployment/memory/node.go similarity index 55% rename from core/capabilities/ccip/ccip_integration_tests/ocr_node_helper.go rename to integration-tests/deployment/memory/node.go index 75b0e0ee947..d60e4258db0 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ocr_node_helper.go +++ b/integration-tests/deployment/memory/node.go @@ -1,71 +1,80 @@ -package ccip_integration_tests +package memory import ( "context" "fmt" "math/big" + "net" "net/http" "strconv" - "sync" "testing" "time" - coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" v2toml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" 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/internal/cltest/heavyweight" - "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" "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/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" "github.com/smartcontractkit/chainlink/v2/plugins" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" ) -type ocr3Node struct { - app chainlink.Application - peerID string - transmitters map[uint64]common.Address - keybundle ocr2key.KeyBundle - db *sqlx.DB +type Node struct { + App chainlink.Application + // Transmitter key/OCR keys for this node + Keys Keys + Addr net.TCPAddr + IsBoostrap bool } -// setupNodeOCR3 creates a chainlink node and any associated keys in order to run -// ccip. -func setupNodeOCR3( +func (n Node) ReplayLogs(chains map[uint64]uint64) error { + for sel, block := range chains { + chainID, _ := chainsel.ChainIdFromSelector(sel) + if err := n.App.ReplayFromBlock(big.NewInt(int64(chainID)), block, false); err != nil { + return err + } + } + return nil +} + +// Creates a CL node which is: +// - Configured for OCR +// - Configured for the chains specified +// - Transmitter keys funded. +func NewNode( t *testing.T, - port int, - universes map[uint64]onchainUniverse, - homeChainUniverse homeChain, + port int, // Port for the P2P V2 listener. + chains map[uint64]EVMChain, logLevel zapcore.Level, -) *ocr3Node { + bootstrap bool, + registryConfig deployment.CapabilityRegistryConfig, +) *Node { // Do not want to load fixtures as they contain a dummy chainID. + // Create database and initial configuration. cfg, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. @@ -78,9 +87,11 @@ func setupNodeOCR3( c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", port)} // Enable Capabilities, This is a pre-requisite for registrySyncer to work. - c.Capabilities.ExternalRegistry.NetworkID = ptr(relay.NetworkEVM) - c.Capabilities.ExternalRegistry.ChainID = ptr(strconv.FormatUint(homeChainUniverse.chainID, 10)) - c.Capabilities.ExternalRegistry.Address = ptr(homeChainUniverse.capabilityRegistry.Address().String()) + if registryConfig.Contract != common.HexToAddress("0x0") { + c.Capabilities.ExternalRegistry.NetworkID = ptr(relay.NetworkEVM) + c.Capabilities.ExternalRegistry.ChainID = ptr(strconv.FormatUint(uint64(registryConfig.EVMChainID), 10)) + c.Capabilities.ExternalRegistry.Address = ptr(registryConfig.Contract.String()) + } // OCR configs c.OCR.Enabled = ptr(false) @@ -90,54 +101,58 @@ func setupNodeOCR3( c.Log.Level = ptr(configv2.LogLevel(logLevel)) - var chains v2toml.EVMConfigs - for chainID := range universes { - chains = append(chains, createConfigV2Chain(uBigInt(chainID))) + var chainConfigs v2toml.EVMConfigs + for chainID := range chains { + chainConfigs = append(chainConfigs, createConfigV2Chain(chainID)) } - c.EVM = chains + c.EVM = chainConfigs }) + // Set logging. lggr := logger.TestLogger(t) lggr.SetLogLevel(logLevel) - ctx := testutils.Context(t) - clients := make(map[uint64]client.Client) - for chainID, uni := range universes { - clients[chainID] = client.NewSimulatedBackendClient(t, uni.backend, uBigInt(chainID)) + // Create clients for the core node backed by sim. + clients := make(map[uint64]client.Client) + for chainID, chain := range chains { + clients[chainID] = client.NewSimulatedBackendClient(t, chain.Backend, big.NewInt(int64(chainID))) } + // Create keystore master := keystore.New(db, utils.FastScryptParams, lggr) - kStore := KeystoreSim{ eks: &EthKeystoreSim{ Eth: master.Eth(), - t: t, }, csa: master.CSA(), } - mailMon := mailbox.NewMonitor("ccip", lggr.Named("mailbox")) + + // Build evm factory using clients + keystore. + mailMon := mailbox.NewMonitor("node", lggr.Named("mailbox")) evmOpts := chainlink.EVMFactoryConfig{ ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, GenEthClient: func(i *big.Int) client.Client { - client, ok := clients[i.Uint64()] + ethClient, ok := clients[i.Uint64()] if !ok { t.Fatal("no backend for chainID", i) } - return client + return ethClient }, MailMon: mailMon, DS: db, }, CSAETHKeystore: kStore, } + + // Build relayer factory with EVM. relayerFactory := chainlink.RelayerFactory{ Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing()), + LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing(), cfg.Telemetry()), GRPCOpts: loop.GRPCOpts{}, - CapabilitiesRegistry: coretypes.NewCapabilitiesRegistry(t), + CapabilitiesRegistry: capabilities.NewRegistry(lggr), } - initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(testutils.Context(t), relayerFactory, evmOpts)} + initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(context.Background(), relayerFactory, evmOpts)} rci, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) require.NoError(t, err) @@ -153,11 +168,33 @@ func setupNodeOCR3( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, cfg.Tracing()), + LoopRegistry: plugins.NewLoopRegistry(lggr, cfg.Tracing(), cfg.Telemetry()), }) require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, db.Close()) + }) + keys := CreateKeys(t, app, chains) + + return &Node{ + App: app, + Keys: keys, + Addr: net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: port}, + IsBoostrap: bootstrap, + } +} + +type Keys struct { + PeerID p2pkey.PeerID + TransmittersByEVMChainID map[uint64]common.Address + OCRKeyBundle ocr2key.KeyBundle +} + +func CreateKeys(t *testing.T, + app chainlink.Application, chains map[uint64]EVMChain) Keys { + ctx := tests.Context(t) require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) - _, err = app.GetKeyStore().P2P().Create(ctx) + _, err := app.GetKeyStore().P2P().Create(ctx) require.NoError(t, err) p2pIDs, err := app.GetKeyStore().P2P().GetAll() @@ -166,44 +203,48 @@ func setupNodeOCR3( peerID := p2pIDs[0].PeerID() // create a transmitter for each chain transmitters := make(map[uint64]common.Address) - for chainID, uni := range universes { - backend := uni.backend - owner := uni.owner - cID := uBigInt(chainID) - addrs, err2 := app.GetKeyStore().Eth().EnabledAddressesForChain(testutils.Context(t), cID) + for chainID, chain := range chains { + cid := big.NewInt(int64(chainID)) + addrs, err2 := app.GetKeyStore().Eth().EnabledAddressesForChain(ctx, cid) require.NoError(t, err2) if len(addrs) == 1 { // just fund the address - fundAddress(t, owner, addrs[0], assets.Ether(10).ToInt(), backend) + fundAddress(t, chain.DeployerKey, addrs[0], assets.Ether(10).ToInt(), chain.Backend) transmitters[chainID] = addrs[0] } else { // create key and fund it - _, err3 := app.GetKeyStore().Eth().Create(testutils.Context(t), cID) + _, err3 := app.GetKeyStore().Eth().Create(ctx, cid) require.NoError(t, err3, "failed to create key for chain", chainID) - sendingKeys, err3 := app.GetKeyStore().Eth().EnabledAddressesForChain(testutils.Context(t), cID) + sendingKeys, err3 := app.GetKeyStore().Eth().EnabledAddressesForChain(ctx, cid) require.NoError(t, err3) require.Len(t, sendingKeys, 1) - fundAddress(t, owner, sendingKeys[0], assets.Ether(10).ToInt(), backend) + fundAddress(t, chain.DeployerKey, sendingKeys[0], assets.Ether(10).ToInt(), chain.Backend) transmitters[chainID] = sendingKeys[0] } } - require.Len(t, transmitters, len(universes)) + require.Len(t, transmitters, len(chains)) keybundle, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) require.NoError(t, err) + return Keys{ + PeerID: peerID, + TransmittersByEVMChainID: transmitters, + OCRKeyBundle: keybundle, + } +} - t.Cleanup(func() { - require.NoError(t, db.Close()) - }) - - return &ocr3Node{ - // can't use this app because it doesn't have the right toml config - // missing bootstrapp - app: app, - peerID: peerID.Raw(), - transmitters: transmitters, - keybundle: keybundle, - db: db, +func createConfigV2Chain(chainID uint64) *v2toml.EVMConfig { + chainIDBig := evmutils.NewI(int64(chainID)) + chain := v2toml.Defaults(chainIDBig) + chain.GasEstimator.LimitDefault = ptr(uint64(5e6)) + chain.LogPollInterval = config.MustNewDuration(500 * time.Millisecond) + chain.Transactions.ForwardersEnabled = ptr(false) + chain.FinalityDepth = ptr(uint32(2)) + return &v2toml.EVMConfig{ + ChainID: chainIDBig, + Enabled: ptr(true), + Chain: chain, + Nodes: v2toml.EVMNodes{&v2toml.Node{}}, } } @@ -213,7 +254,6 @@ var _ keystore.Eth = &EthKeystoreSim{} type EthKeystoreSim struct { keystore.Eth - t *testing.T } // override @@ -234,83 +274,3 @@ func (e KeystoreSim) Eth() keystore.Eth { func (e KeystoreSim) CSA() keystore.CSA { return e.csa } - -func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *backends.SimulatedBackend) { - nonce, err := backend.PendingNonceAt(testutils.Context(t), from.From) - require.NoError(t, err) - gp, err := backend.SuggestGasPrice(testutils.Context(t)) - require.NoError(t, err) - rawTx := gethtypes.NewTx(&gethtypes.LegacyTx{ - Nonce: nonce, - GasPrice: gp, - Gas: 21000, - To: &to, - Value: amount, - }) - signedTx, err := from.Signer(from.From, rawTx) - require.NoError(t, err) - err = backend.SendTransaction(testutils.Context(t), signedTx) - require.NoError(t, err) - backend.Commit() -} - -func createConfigV2Chain(chainID *big.Int) *v2toml.EVMConfig { - chain := v2toml.Defaults((*evmutils.Big)(chainID)) - chain.GasEstimator.LimitDefault = ptr(uint64(5e6)) - chain.LogPollInterval = config.MustNewDuration(100 * time.Millisecond) - chain.Transactions.ForwardersEnabled = ptr(false) - chain.FinalityDepth = ptr(uint32(2)) - return &v2toml.EVMConfig{ - ChainID: (*evmutils.Big)(chainID), - Enabled: ptr(true), - Chain: chain, - Nodes: v2toml.EVMNodes{&v2toml.Node{}}, - } -} - -// Commit blocks periodically in the background for all chains -func commitBlocksBackground(t *testing.T, universes map[uint64]onchainUniverse, tick *time.Ticker) { - t.Log("starting ticker to commit blocks") - tickCtx, tickCancel := context.WithCancel(testutils.Context(t)) - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - for { - select { - case <-tick.C: - for _, uni := range universes { - uni.backend.Commit() - } - case <-tickCtx.Done(): - return - } - } - }() - t.Cleanup(func() { - tickCancel() - wg.Wait() - }) -} - -// p2pKeyID: nodes p2p id -// ocrKeyBundleID: nodes ocr key bundle id -func mustGetJobSpec(t *testing.T, bootstrapP2PID p2pkey.PeerID, bootstrapPort int, p2pKeyID string, ocrKeyBundleID string) job.Job { - specArgs := validate.SpecArgs{ - P2PV2Bootstrappers: []string{ - fmt.Sprintf("%s@127.0.0.1:%d", bootstrapP2PID.Raw(), bootstrapPort), - }, - CapabilityVersion: CapabilityVersion, - CapabilityLabelledName: CapabilityLabelledName, - OCRKeyBundleIDs: map[string]string{ - relay.NetworkEVM: ocrKeyBundleID, - }, - P2PKeyID: p2pKeyID, - PluginConfig: map[string]any{}, - } - specToml, err := validate.NewCCIPSpecToml(specArgs) - require.NoError(t, err) - jb, err := validate.ValidatedCCIPSpec(specToml) - require.NoError(t, err) - return jb -} diff --git a/integration-tests/deployment/memory/node_test.go b/integration-tests/deployment/memory/node_test.go new file mode 100644 index 00000000000..035e6d03106 --- /dev/null +++ b/integration-tests/deployment/memory/node_test.go @@ -0,0 +1,26 @@ +package memory + +import ( + "testing" + + "github.com/hashicorp/consul/sdk/freeport" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" +) + +func TestNode(t *testing.T) { + chains := GenerateChains(t, 3) + ports := freeport.GetN(t, 1) + node := NewNode(t, ports[0], chains, zapcore.DebugLevel, false, deployment.CapabilityRegistryConfig{}) + // We expect 3 transmitter keys + keys, err := node.App.GetKeyStore().Eth().GetAll(tests.Context(t)) + require.NoError(t, err) + require.Len(t, keys, 3) + // We expect 3 chains supported + evmChains := node.App.GetRelayers().LegacyEVMChains().Slice() + require.NoError(t, err) + require.Len(t, evmChains, 3) +} diff --git a/integration-tests/deployment/multiclient.go b/integration-tests/deployment/multiclient.go new file mode 100644 index 00000000000..65f9e82bd01 --- /dev/null +++ b/integration-tests/deployment/multiclient.go @@ -0,0 +1,154 @@ +package deployment + +import ( + "context" + "fmt" + "math/big" + "time" + + "github.com/avast/retry-go/v4" + "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/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +const ( + RPC_DEFAULT_RETRY_ATTEMPTS = 10 + RPC_DEFAULT_RETRY_DELAY = 1000 * time.Millisecond +) + +type RetryConfig struct { + Attempts uint + Delay time.Duration +} + +func defaultRetryConfig() RetryConfig { + return RetryConfig{ + Attempts: RPC_DEFAULT_RETRY_ATTEMPTS, + Delay: RPC_DEFAULT_RETRY_DELAY, + } +} + +type RPC struct { + WSURL string + // TODO: http fallback needed for some networks? +} + +// MultiClient should comply with the OnchainClient interface +var _ OnchainClient = &MultiClient{} + +type MultiClient struct { + *ethclient.Client + Backups []*ethclient.Client + RetryConfig RetryConfig + lggr logger.Logger +} + +func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiClient)) (*MultiClient, error) { + if len(rpcs) == 0 { + return nil, errors.New("No RPCs provided, need at least one") + } + mc := MultiClient{lggr: lggr} + clients := make([]*ethclient.Client, 0, len(rpcs)) + for _, rpc := range rpcs { + client, err := ethclient.Dial(rpc.WSURL) + if err != nil { + return nil, fmt.Errorf("failed to dial ws url '%s': %w", rpc.WSURL, err) + } + clients = append(clients, client) + } + mc.Client = clients[0] + mc.Backups = clients[1:] + mc.RetryConfig = defaultRetryConfig() + + for _, opt := range opts { + opt(&mc) + } + return &mc, nil +} + +func (mc *MultiClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { + return mc.retryWithBackups("SendTransaction", func(client *ethclient.Client) error { + return client.SendTransaction(ctx, tx) + }) +} + +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 { + var err error + code, err = client.CodeAt(ctx, account, blockNumber) + 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 { + var err error + count, err = client.NonceAt(ctx, account, block) + 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()) + // 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) + receipt, err := bind.WaitMined(ctx, client, &tx) + if err != nil { + mc.lggr.Warnf("WaitMined error %v with client %v", err, client) + return + } + select { + case resultCh <- receipt: + case <-doneCh: + return + } + } + + for _, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { + txn := tx + c := client + go waitMined(c, *txn) + } + var receipt *types.Receipt + select { + case receipt = <-resultCh: + close(doneCh) + return receipt, nil + case <-ctx.Done(): + mc.lggr.Warnf("WaitMined context done %v", ctx.Err()) + close(doneCh) + return nil, ctx.Err() + } +} + +func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client) error) error { + var err error + for _, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { + err2 := retry.Do(func() error { + err = op(client) + if err != nil { + mc.lggr.Warnf("retryable error '%s' for op %s with client %v", err.Error(), opName, client) + return err + } + return nil + }, retry.Attempts(mc.RetryConfig.Attempts), retry.Delay(mc.RetryConfig.Delay)) + if err2 == nil { + return nil + } + mc.lggr.Infof("Client %v failed, trying next client", client) + } + return errors.Wrapf(err, "All backup clients %v failed", mc.Backups) +} diff --git a/integration-tests/deployment/multiclient_test.go b/integration-tests/deployment/multiclient_test.go new file mode 100644 index 00000000000..0dbebbe3a6a --- /dev/null +++ b/integration-tests/deployment/multiclient_test.go @@ -0,0 +1,39 @@ +package deployment + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestMultiClient(t *testing.T) { + lggr := logger.TestLogger(t) + // Expect an error if no RPCs supplied. + s := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + writer.WriteHeader(http.StatusOK) + _, err := writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) + require.NoError(t, err) + })) + defer s.Close() + _, err := NewMultiClient(lggr, []RPC{}) + require.Error(t, err) + + // Expect defaults to be set if not provided. + mc, err := NewMultiClient(lggr, []RPC{{WSURL: s.URL}}) + require.NoError(t, err) + assert.Equal(t, mc.RetryConfig.Attempts, uint(RPC_DEFAULT_RETRY_ATTEMPTS)) + assert.Equal(t, mc.RetryConfig.Delay, RPC_DEFAULT_RETRY_DELAY) + + // Expect second client to be set as backup. + mc, err = NewMultiClient(lggr, []RPC{ + {WSURL: s.URL}, + {WSURL: s.URL}, + }) + require.NoError(t, err) + require.Equal(t, len(mc.Backups), 1) +} diff --git a/integration-tests/docker/cmd/internal/commands.go b/integration-tests/docker/cmd/internal/commands.go index 9939765f7f8..bd9d505a7e3 100644 --- a/integration-tests/docker/cmd/internal/commands.go +++ b/integration-tests/docker/cmd/internal/commands.go @@ -8,8 +8,8 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/docker/node_coverage_helper.go b/integration-tests/docker/node_coverage_helper.go index c24804b4612..a2efb21b702 100644 --- a/integration-tests/docker/node_coverage_helper.go +++ b/integration-tests/docker/node_coverage_helper.go @@ -125,6 +125,10 @@ func (c *NodeCoverageHelper) copyCoverageFromNodes(ctx context.Context) error { for i, node := range c.Nodes { wg.Add(1) go func(n tc.Container, id int) { + if n == nil { + errorsChan <- fmt.Errorf("node %d is nil", id) + return + } defer wg.Done() finalDestPath := filepath.Join(c.CoverageDir, fmt.Sprintf("node_%d", id)) if err := os.MkdirAll(finalDestPath, 0755); err != nil { diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index b28d954688a..02179403acb 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -21,11 +21,11 @@ import ( tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" - "github.com/smartcontractkit/chainlink-testing-framework/docker" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -33,11 +33,13 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/smartcontractkit/chainlink/integration-tests/utils/templates" + grapqlClient "github.com/smartcontractkit/chainlink/integration-tests/web/sdk/client" ) var ( - ErrConnectNodeClient = "could not connect Node HTTP Client" - ErrStartCLNodeContainer = "failed to start CL node container" + ErrConnectNodeClient = "could not connect Node HTTP Client" + ErrConnectNodeGraphqlClient = "could not connect Node Graphql Client" + ErrStartCLNodeContainer = "failed to start CL node container" ) const ( @@ -54,6 +56,7 @@ type ClNode struct { UserEmail string `json:"userEmail"` UserPassword string `json:"userPassword"` AlwaysPullImage bool `json:"-"` + GraphqlAPI grapqlClient.Client `json:"-"` t *testing.T l zerolog.Logger } @@ -339,19 +342,25 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { Str("userEmail", n.UserEmail). Str("userPassword", n.UserPassword). Msg("Started Chainlink Node container") - clClient, err := client.NewChainlinkClient(&client.ChainlinkConfig{ + config := &client.ChainlinkConfig{ URL: clEndpoint, Email: n.UserEmail, Password: n.UserPassword, InternalIP: ip, - }, - n.l) + } + clClient, err := client.NewChainlinkClient(config, n.l) if err != nil { return fmt.Errorf("%s err: %w", ErrConnectNodeClient, err) } + graphqlClient, err := newChainLinkGraphqlClient(config) + if err != nil { + return fmt.Errorf("%s err: %w", ErrConnectNodeGraphqlClient, err) + } + n.Container = container n.API = clClient + n.GraphqlAPI = graphqlClient return nil } @@ -491,3 +500,11 @@ func (n *ClNode) getContainerRequest(secrets string) ( }, }, nil } + +func newChainLinkGraphqlClient(c *client.ChainlinkConfig) (grapqlClient.Client, error) { + nodeClient, err := grapqlClient.New(c.URL, grapqlClient.Credentials{Email: c.Email, Password: c.Password}) + if err != nil { + return nil, err + } + return nodeClient, nil +} diff --git a/integration-tests/docker/test_env/cl_node_cluster.go b/integration-tests/docker/test_env/cl_node_cluster.go index 679e5393811..92ac8ddb986 100644 --- a/integration-tests/docker/test_env/cl_node_cluster.go +++ b/integration-tests/docker/test_env/cl_node_cluster.go @@ -44,16 +44,15 @@ func (c *ClCluster) Start() error { } func (c *ClCluster) Stop() error { - eg := &errgroup.Group{} + var eg errgroup.Group nodes := c.Nodes timeout := time.Minute * 1 for i := 0; i < len(nodes); i++ { nodeIndex := i eg.Go(func() error { - err := nodes[nodeIndex].Container.Stop(context.Background(), &timeout) - if err != nil { - return err + if container := nodes[nodeIndex].Container; container != nil { + return container.Stop(context.Background(), &timeout) } return nil }) diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index fb72025a05a..1ca50760d17 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -13,13 +13,17 @@ import ( "github.com/rs/zerolog/log" tc "github.com/testcontainers/testcontainers-go" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/docker" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/utils/runid" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env/job_distributor" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/runid" + + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" d "github.com/smartcontractkit/chainlink/integration-tests/docker" @@ -41,6 +45,7 @@ type CLClusterTestEnv struct { PrivateEthereumConfigs []*ctf_config.EthereumNetworkConfig EVMNetworks []*blockchain.EVMNetwork rpcProviders map[int64]*test_env.RpcProvider + JobDistributor *job_distributor.Component l zerolog.Logger t *testing.T isSimulatedNetwork bool @@ -109,6 +114,33 @@ func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *ctf_config.EthereumNetwork return n, rpc, nil } +func (te *CLClusterTestEnv) StartJobDistributor(cfg *ccip.JDConfig) error { + jdDB, err := test_env.NewPostgresDb( + []string{te.DockerNetwork.Name}, + test_env.WithPostgresDbName(cfg.GetJDDBName()), + test_env.WithPostgresImageVersion(cfg.GetJDDBVersion()), + ) + if err != nil { + return fmt.Errorf("failed to create postgres db for job-distributor: %w", err) + } + err = jdDB.StartContainer() + if err != nil { + return fmt.Errorf("failed to start postgres db for job-distributor: %w", err) + } + jd := job_distributor.New([]string{te.DockerNetwork.Name}, + job_distributor.WithImage(cfg.GetJDImage()), + job_distributor.WithVersion(cfg.GetJDVersion()), + job_distributor.WithDBURL(jdDB.InternalURL.String()), + ) + jd.LogStream = te.LogStream + err = jd.StartContainer() + if err != nil { + return fmt.Errorf("failed to start job-distributor: %w", err) + } + te.JobDistributor = jd + return nil +} + func (te *CLClusterTestEnv) StartMockAdapter() error { return te.MockAdapter.StartContainer() } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 1ab577bf54e..610c3e29e1e 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -13,17 +13,19 @@ import ( "github.com/rs/zerolog/log" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/testsummary" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testsummary" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" + + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -45,6 +47,7 @@ type ChainlinkNodeLogScannerSettings struct { type CLTestEnvBuilder struct { hasLogStream bool hasKillgrave bool + jdConfig *ccip.JDConfig clNodeConfig *chainlink.Config secretsConfig string clNodesCount int @@ -209,6 +212,11 @@ func (b *CLTestEnvBuilder) WithCustomCleanup(customFn func()) *CLTestEnvBuilder return b } +func (b *CLTestEnvBuilder) WithJobDistributor(cfg ccip.JDConfig) *CLTestEnvBuilder { + b.jdConfig = &cfg + return b +} + type EVMNetworkOption = func(*blockchain.EVMNetwork) *blockchain.EVMNetwork // WithEVMNetworkOptions sets the options for the EVM network. This is especially useful for simulated networks, which @@ -395,6 +403,12 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { log.Warn().Msg("Chainlink node log scanner settings provided, but LogStream is not enabled. Ignoring Chainlink node log scanner settings, as no logs will be available.") } + if b.jdConfig != nil { + err := b.te.StartJobDistributor(b.jdConfig) + if err != nil { + return nil, err + } + } // in this case we will use the builder only to start chains, not the cluster, because currently we support only 1 network config per cluster if len(b.privateEthereumNetworks) > 1 { b.te.rpcProviders = make(map[int64]*test_env.RpcProvider) @@ -409,29 +423,29 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) } + if b.clNodesCount > 0 { + dereferrencedEvms := make([]blockchain.EVMNetwork, 0) + for _, en := range b.te.EVMNetworks { + dereferrencedEvms = append(dereferrencedEvms, *en) + } - dereferrencedEvms := make([]blockchain.EVMNetwork, 0) - for _, en := range b.te.EVMNetworks { - dereferrencedEvms = append(dereferrencedEvms, *en) - } - - nodeConfigInToml := b.testConfig.GetNodeConfig() + nodeConfigInToml := b.testConfig.GetNodeConfig() - nodeConfig, _, err := node.BuildChainlinkNodeConfig( - dereferrencedEvms, - nodeConfigInToml.BaseConfigTOML, - nodeConfigInToml.CommonChainConfigTOML, - nodeConfigInToml.ChainConfigTOMLByChainID, - ) - if err != nil { - return nil, err - } + nodeConfig, _, err := node.BuildChainlinkNodeConfig( + dereferrencedEvms, + nodeConfigInToml.BaseConfigTOML, + nodeConfigInToml.CommonChainConfigTOML, + nodeConfigInToml.ChainConfigTOMLByChainID, + ) + if err != nil { + return nil, err + } - err = b.te.StartClCluster(nodeConfig, b.clNodesCount, b.secretsConfig, b.testConfig, b.clNodesOpts...) - if err != nil { - return nil, err + err = b.te.StartClCluster(nodeConfig, b.clNodesCount, b.secretsConfig, b.testConfig, b.clNodesOpts...) + if err != nil { + return nil, err + } } - b.te.isSimulatedNetwork = true return b.te, nil @@ -549,6 +563,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.l.Info(). Str("privateEthereumNetwork", enDesc). Bool("hasKillgrave", b.hasKillgrave). + Bool("hasJobDistributor", b.jdConfig != nil). Int("clNodesCount", b.clNodesCount). Strs("customNodeCsaKeys", b.customNodeCsaKeys). Strs("defaultNodeCsaKeys", b.defaultNodeCsaKeys). diff --git a/integration-tests/docker/test_env/test_env_config.go b/integration-tests/docker/test_env/test_env_config.go index 9aefa9615c9..028b9ff75b9 100644 --- a/integration-tests/docker/test_env/test_env_config.go +++ b/integration-tests/docker/test_env/test_env_config.go @@ -3,7 +3,8 @@ package test_env import ( "encoding/json" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + env "github.com/smartcontractkit/chainlink/integration-tests/types/envcommon" ) diff --git a/integration-tests/docs/VRF.md b/integration-tests/docs/VRF.md new file mode 100644 index 00000000000..745bec05864 --- /dev/null +++ b/integration-tests/docs/VRF.md @@ -0,0 +1,65 @@ +# How To Run VRF Tests +* All test configs should be placed in the [integration-tests/testconfig](../testconfig) folder +* All test configs for running tests in live testnets should be under [integration-tests/testconfig/vrfv2plus/overrides](../testconfig/vrfv2plus/overrides) folder + + +## Functional Tests +### In CI - using On Demand Workflows +```bash +gh workflow run "on-demand-vrfv2plus-smoke-tests.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path= \ +-f test_suite="Selected Tests" \ # Optional, Options - "All Tests", "Selected Tests". Default is "All Tests". If "Selected Tests" is selected, then `test_list_regex` should be provided +-f test_list_regex="" \ # Optional, default is "TestVRFv2Plus$/(Link_Billing|Native_Billing|Direct_Funding)|TestVRFV2PlusWithBHS" which are P0 tests +-f chainlink_version="<>" # Optional, default is image created from develop branch. Not needed if you run tests against existing environment +-f notify_user_id_on_failure= # Optional, default is empty. If provided, will notify the user on slack if the tests fail +``` + +#### Examples: +Run P0 tests against existing environment (Staging) on Arbitrum Sepolia +```bash +gh workflow run "on-demand-vrfv2plus-smoke-tests.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path=integration-tests/testconfig/vrfv2plus/overrides/staging/arbitrum_sepolia_staging_test_config.toml \ +-f test_suite="Selected Tests" +``` + +Run all tests deploying all contracts, CL nodes with `2.15.0` version on Base Sepolia +```bash +gh workflow run "on-demand-vrfv2plus-smoke-tests.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path=integration-tests/testconfig/vrfv2plus/overrides/new_env/base_sepolia_new_env_test_config.toml \ +-f test_suite="All Tests" \ +-f chainlink_version="2.15.0" +``` + +### Locally +```bash +cd integration-tests +TEST_LOG_LEVEL=debug \ +BASE64_CONFIG_OVERRIDE=$(cat | base64) \ +go test -v -timeout 15m -run "" ./smoke +``` + +## Performance Tests +```bash +gh workflow run "on-demand-vrfv2plus-performance-test.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path= \ +-f performanceTestType=“Smoke” # Options - "Smoke", "Soak", "Stress", "Load". +-f test_list_regex="" # Optional, default is "TestVRFV2PlusPerformance" +``` + +#### Examples: +Run SOAK tests against existing environment (Staging) on Base Sepolia +```bash +gh workflow run "on-demand-vrfv2plus-performance-test.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path=integration-tests/testconfig/vrfv2plus/overrides/staging/base_sepolia_staging_test_config.toml \ +-f performanceTestType=“Soak” +``` diff --git a/integration-tests/experiments/gas_test.go b/integration-tests/experiments/gas_test.go index 4d1f4597111..42e408a1525 100644 --- a/integration-tests/experiments/gas_test.go +++ b/integration-tests/experiments/gas_test.go @@ -5,12 +5,12 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 86a03cec174..860d3742298 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -1,23 +1,27 @@ module github.com/smartcontractkit/chainlink/integration-tests -go 1.22.5 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ require ( - dario.cat/mergo v1.0.0 + dario.cat/mergo v1.0.1 github.com/AlekSi/pointer v1.1.0 + github.com/Khan/genqlient v0.7.0 github.com/Masterminds/semver/v3 v3.2.1 github.com/avast/retry-go/v4 v4.6.0 + github.com/aws/aws-sdk-go v1.54.19 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df - github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a github.com/cli/go-gh/v2 v2.0.0 github.com/ethereum/go-ethereum v1.13.8 - github.com/fxamacker/cbor/v2 v2.6.0 - github.com/go-resty/resty/v2 v2.11.0 + github.com/fxamacker/cbor/v2 v2.7.0 + github.com/go-resty/resty/v2 v2.13.1 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 + github.com/hashicorp/consul/sdk v0.16.1 + github.com/hashicorp/go-multierror v1.1.1 github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 @@ -25,90 +29,111 @@ require ( github.com/onsi/gomega v1.33.1 github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 - github.com/prometheus/common v0.55.0 - github.com/rs/zerolog v1.31.0 + github.com/prometheus/common v0.59.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/sethvargo/go-retry v0.2.4 github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/chain-selectors v1.0.21 - github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 - github.com/smartcontractkit/chainlink-testing-framework v1.34.2 - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 + github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 + github.com/smartcontractkit/chain-selectors v1.0.27 + github.com/smartcontractkit/chainlink-automation v0.8.0 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 + github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 + github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.11-0.20241011153842-b2804aed25b4 + github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1 + github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 - github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/seth v1.1.2 - github.com/smartcontractkit/wasp v0.4.5 - github.com/spf13/cobra v1.8.0 + github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 + github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 + github.com/subosito/gotenv v1.6.0 github.com/test-go/testify v1.1.4 - github.com/testcontainers/testcontainers-go v0.28.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/umbracle/ethgo v0.1.3 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.25.0 - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/sync v0.7.0 - golang.org/x/text v0.16.0 + golang.org/x/crypto v0.27.0 + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 + golang.org/x/sync v0.8.0 + golang.org/x/text v0.18.0 + google.golang.org/grpc v1.66.2 + google.golang.org/protobuf v1.35.1 gopkg.in/guregu/null.v4 v4.0.0 - gopkg.in/yaml.v2 v2.4.0 - gopkg.in/yaml.v3 v3.0.1 - k8s.io/apimachinery v0.28.2 + gotest.tools/v3 v3.5.1 + k8s.io/apimachinery v0.31.0 ) -// avoids ambigious imports of indirect dependencies -exclude github.com/hashicorp/consul v1.2.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.3 // indirect - cosmossdk.io/errors v1.0.0 // indirect - cosmossdk.io/math v1.0.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/math v1.3.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect - github.com/K-Phoen/grabana v0.22.1 // indirect - github.com/K-Phoen/sdk v0.12.4 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NethermindEth/juno v0.3.1 // indirect github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect + github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect + github.com/alexflint/go-arg v1.4.2 // indirect + github.com/alexflint/go-scalar v1.0.0 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect - github.com/aws/aws-sdk-go v1.45.25 // indirect + github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/aws/smithy-go v1.20.4 // 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 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.10.0 // indirect + 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.2 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect @@ -122,29 +147,29 @@ require ( github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cli/safeexec v1.0.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/errors v1.10.0 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.37.2 // indirect - github.com/cometbft/cometbft-db v0.7.0 // indirect + github.com/cometbft/cometbft v0.37.5 // indirect + github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect - github.com/cosmos/cosmos-sdk v0.47.4 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/cosmos-sdk v0.47.11 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogoproto v1.4.11 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.0.1 // indirect - github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/cosmos/iavl v0.20.1 // indirect + github.com/cosmos/ibc-go/v7 v7.5.1 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect @@ -158,9 +183,9 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v25.0.2+incompatible // indirect + github.com/docker/docker v27.3.1+incompatible // indirect 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 @@ -170,22 +195,20 @@ require ( github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/esote/minmaxheap v1.0.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fvbommel/sortorder v1.1.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // 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/gagliardetto/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect - github.com/getsentry/sentry-go v0.19.0 // indirect + github.com/getsentry/sentry-go v0.23.0 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.9.1 // indirect @@ -198,29 +221,31 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/errors v0.20.4 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/analysis v0.22.2 // indirect + github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/spec v0.20.9 // indirect - github.com/go-openapi/strfmt v0.21.7 // indirect + github.com/go-openapi/loads v0.21.5 // indirect + github.com/go-openapi/spec v0.20.14 // indirect + github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/go-openapi/validate v0.22.1 // indirect + 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.15.5 // indirect + github.com/go-playground/validator/v10 v10.22.0 // 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 github.com/go-webauthn/x v0.1.5 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect github.com/gogo/status v1.1.1 // indirect - github.com/golang-jwt/jwt/v5 v5.2.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -231,46 +256,41 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect - github.com/google/s2a-go v0.1.7 // indirect + github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect - github.com/gosimple/slug v1.13.1 // indirect - github.com/gosimple/unidecode v1.0.1 // indirect github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f // indirect github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 // indirect github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b // indirect github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect - github.com/grafana/pyroscope-go v1.1.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect - github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect + github.com/grafana/pyroscope-go v1.1.2 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect 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/hashicorp/consul/api v1.25.1 // indirect - github.com/hashicorp/consul/sdk v0.16.0 // indirect + github.com/hashicorp/consul/api v1.29.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect - github.com/hashicorp/go-retryablehttp v0.7.5 // indirect + github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.6 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect @@ -283,6 +303,7 @@ require ( github.com/huandu/skiplist v1.2.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect @@ -304,15 +325,16 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.3 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect - github.com/leodido/go-urn v1.2.4 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -320,8 +342,7 @@ require ( 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/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.56 // 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-homedir v1.1.0 // indirect @@ -330,10 +351,12 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.4.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -344,13 +367,12 @@ require ( github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect 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/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc5 // indirect - github.com/opencontainers/runc v1.1.7 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -360,21 +382,24 @@ require ( 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/pkg/browser v0.0.0-20210911075715-681adbf594b8 // 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.26.0 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/alertmanager v0.27.0 // indirect + github.com/prometheus/client_golang v1.20.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect - github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97 // indirect + github.com/prometheus/exporter-toolkit v0.11.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/prometheus/prometheus v0.48.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/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.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/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect @@ -383,36 +408,35 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f // indirect - github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.7.3 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect + github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // 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 + github.com/smartcontractkit/wsrpc v0.8.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.15.0 // 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/stretchr/objx v0.5.2 // indirect - github.com/subosito/gotenv v1.4.2 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // 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 github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect @@ -422,29 +446,38 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/vektah/gqlparser/v2 v2.5.11 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect - go.etcd.io/bbolt v1.3.8 // indirect - go.etcd.io/etcd/api/v3 v3.5.10 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect - go.etcd.io/etcd/client/v3 v3.5.10 // indirect + go.etcd.io/bbolt v1.3.9 // indirect + go.etcd.io/etcd/api/v3 v3.5.14 // indirect + 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.0.0-rcv0016 // indirect - go.opentelemetry.io/collector/semconv v0.87.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.53.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.4.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.4.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect @@ -452,62 +485,48 @@ require ( go.uber.org/ratelimit v0.3.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/time v0.6.0 // indirect + golang.org/x/tools v0.25.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.0 // indirect google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - k8s.io/api v0.28.2 // indirect - k8s.io/apiextensions-apiserver v0.28.2 // indirect - k8s.io/cli-runtime v0.28.2 // indirect - k8s.io/client-go v0.28.2 // indirect - k8s.io/component-base v0.28.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.31.0 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/cli-runtime v0.31.0 // indirect + k8s.io/client-go v0.31.0 // indirect + k8s.io/component-base v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.28.2 // indirect - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect - nhooyr.io/websocket v1.8.7 // indirect - pgregory.net/rapid v0.5.5 // indirect + k8s.io/kubectl v0.31.0 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + nhooyr.io/websocket v1.8.10 // indirect + pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.16.2 // indirect + sigs.k8s.io/controller-runtime v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) -exclude github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 - replace ( - github.com/go-kit/log => github.com/go-kit/log v0.2.1 - // replicating the replace directive on cosmos SDK github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 - github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 - - // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 - github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - - // type func(a Label, b Label) bool of func(a, b Label) bool {…} does not match inferred type func(a Label, b Label) int for func(a E, b E) int - github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 -) - -replace ( - github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.14.0 - github.com/prometheus/common => github.com/prometheus/common v0.42.0 + github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264 ) diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 8af6705473b..6ca33fc91aa 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -4,7 +4,6 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR 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.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -15,9 +14,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= @@ -31,7 +27,6 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -48,7 +43,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -59,18 +53,18 @@ 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= cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= -cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca h1:msenprh2BLLRwNT7zN56TbBHOGk/7ARQckXHxXyvjoQ= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca/go.mod h1:PkIAKXZvaxrTRc++z53XMRvFk8AcGGWYHcMIPzVYX9c= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= +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.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +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= @@ -83,43 +77,29 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw= -github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 h1:GJHeeA2N7xrG3q30L2UXDyuWRzDM900/65j70wcM4Ww= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= -github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= +github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU= +github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4= github.com/CosmWasm/wasmd v0.40.1 h1:LxbO78t/6S8TkeQlUrJ0m5O87HtAwLx4RGHq3rdrOEU= github.com/CosmWasm/wasmd v0.40.1/go.mod h1:6EOwnv7MpuFaEqxcUOdFV9i4yvrdOciaY6VQ1o7A3yg= github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ= @@ -133,11 +113,8 @@ github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/K-Phoen/grabana v0.22.1 h1:b/O+C3H2H6VNYSeMCYUO4X4wYuwFXgBcRkvYa+fjpQA= -github.com/K-Phoen/grabana v0.22.1/go.mod h1:3LTXrTzQzTKTgvKSXdRjlsJbizSOW/V23Q3iX00R5bU= -github.com/K-Phoen/sdk v0.12.4 h1:j2EYuBJm3zDTD0fGKACVFWxAXtkR0q5QzfVqxmHSeGQ= -github.com/K-Phoen/sdk v0.12.4/go.mod h1:qmM0wO23CtoDux528MXPpYvS4XkRWkWX6rvX9Za8EVU= +github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= +github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -148,10 +125,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb h1:Mv8SscePPyw2ju4igIJAjFgcq5zCQfjgbz53DwYu5mc= @@ -161,9 +136,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= @@ -172,17 +144,22 @@ 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/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +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/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA= +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= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/alexflint/go-arg v1.4.2 h1:lDWZAXxpAnZUq4qwb86p/3rIJJ2Li81EoMbTMujhVa0= +github.com/alexflint/go-arg v1.4.2/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= +github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= +github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= @@ -192,7 +169,13 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax 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.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -202,9 +185,10 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQVoh6kY+c4b0HUchHjGWBI8288VhH50qxKG3hdEg0= +github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c/go.mod h1:3XzxudkrYVUvbduN/uI2fl4lSrMSzU0+3RCu2mpnfx8= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= @@ -214,20 +198,51 @@ github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw 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.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= -github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +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.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= +github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= +github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= +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.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= 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= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= @@ -238,13 +253,17 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= 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= +github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs= +github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= -github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= @@ -253,6 +272,8 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU 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.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= @@ -273,14 +294,13 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f h1:onZ3oc6l1Gz8pVpQ0c1U1Cb11kIMoDb3xtEy/iZbYZM= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a h1:6Pg3a6j/41QDzH/oYcMLwwKsf3x/HXcu9W/dBaf2Hzs= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -306,7 +326,6 @@ github.com/cli/shurcooL-graphql v0.0.3 h1:CtpPxyGDs136/+ZeyAfUKYmcQBjDlq5aqnrDCW github.com/cli/shurcooL-graphql v0.0.3/go.mod h1:tlrLmw/n5Q/+4qSvosT+9/W5zc8ZMjnJeYBxSdb4nWA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -314,41 +333,36 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= -github.com/cockroachdb/apd/v3 v3.1.0/go.mod h1:6qgPBMXjATAdD/VefbRP9NoSLKjbB4LCoA7gN4LpHs4= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= +github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= -github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0= +github.com/cometbft/cometbft v0.37.5/go.mod h1:QC+mU0lBhKn8r9qvmnq53Dmf3DWBt4VtkcKw2C81wxY= +github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= +github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= -github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +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/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= @@ -364,10 +378,10 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV 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.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.4 h1:FVUpEprm58nMmBX4xkRdMDaIG5Nr4yy92HZAfGAw9bg= -github.com/cosmos/cosmos-sdk v0.47.4/go.mod h1:R5n+uM7vguVPFap4pgkdvQCT1nVo/OtPwrlAU40rvok= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.47.11 h1:0Qx7eORw0RJqPv+mvDuU8NQ1LV3nJJKJnPoYblWHolc= +github.com/cosmos/cosmos-sdk v0.47.11/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -375,14 +389,14 @@ github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiK github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= -github.com/cosmos/ibc-go/v7 v7.0.1 h1:NIBNRWjlOoFvFQu1ZlgwkaSeHO5avf4C1YQiWegt8jw= -github.com/cosmos/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab h1:I9ialKTQo7248V827Bba4OuKPmk+FPzmTVHsLXaIJWw= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab/go.mod h1:2CwqasX5dSD7Hbp/9b6lhK6BwoBDCBldx7gPKRukR60= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= +github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/ibc-go/v7 v7.5.1 h1:KqS/g7W7EMX1OtOvufS8lWMJibOKpdgtNNZIU6fAgVU= +github.com/cosmos/ibc-go/v7 v7.5.1/go.mod h1:ktFg5GvKOyrGCqTWtW7Grj5uweU4ZapxrNeVS1CLLbo= +github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= +github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw= +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.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= @@ -390,8 +404,8 @@ github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHf github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= 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.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= @@ -402,15 +416,12 @@ 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/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/gherkin/go/v22 v22.0.0/go.mod h1:3mJT10B2GGn3MvVPd3FwR7m2u4tLhSRhWUqJU4KN4Fg= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= -github.com/cucumber/common/messages/go/v17 v17.1.1/go.mod h1:bpGxb57tDE385Rb2EohgUadLkAbhoC4IyCFi89u/JQI= 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= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e/go.mod h1:IJgIiGUARc4aOr4bOQ85klmjsShkEEfiRc6q/yBSfo8= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -428,7 +439,6 @@ github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFM 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 v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 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= @@ -440,16 +450,17 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA 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/digitalocean/godo v1.99.0 h1:gUHO7n9bDaZFWvbzOum4bXE0/09ZuYA9yA8idQHX57E= -github.com/digitalocean/godo v1.99.0/go.mod h1:SsS2oXo2rznfM/nORlZ/6JaUJZFhmKTib1YhopUc8NA= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +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= +github.com/digitalocean/godo v1.118.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo= +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= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= -github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -463,23 +474,19 @@ github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9Tzqv github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= @@ -490,23 +497,15 @@ github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0 github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= 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.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= @@ -518,14 +517,12 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= -github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +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/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= @@ -534,16 +531,14 @@ github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtL 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/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= 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/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= -github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= +github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= +github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= @@ -553,17 +548,12 @@ github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfm github.com/gin-contrib/sessions v0.0.5/go.mod h1:vYAuaUPqie3WUSsft6HUlCjlwwoJQs97miaG2+7neKY= github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4 h1:Z9J0PVIt1PuibOShaOw1jH8hUYz+Ak8NLsR/GI0Hv5I= github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4/go.mod h1:CEPcgZiz8998l9E8fDm16h8UfHRL7b+5oG0j/0koeVw= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -571,15 +561,18 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 h1:ymLjT4f35nQbASLnvxEde4XOBL+Sn7rFuV+FOJqkljg= github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -587,62 +580,41 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= -github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= +github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= +github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= +github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= -github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= -github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0= +github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw= +github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 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.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +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-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.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= -github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g= +github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0= 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= @@ -652,47 +624,18 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6lpIc2g= github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= +github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -704,15 +647,12 @@ github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= @@ -756,7 +696,6 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -776,13 +715,11 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= @@ -793,7 +730,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -803,12 +739,9 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -817,19 +750,17 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= -github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= +github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= +github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -842,14 +773,9 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX 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.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q= -github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= -github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= -github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f h1:gyojr97YeWZ70pKNakWv5/tKwBHuLy3icnIeCo9gQr4= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f/go.mod h1:8dsy5tQOkeNQyjXpm5mQsbCu3H5uzeBD35MzRQFznKU= github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 h1:/of8Z8taCPftShATouOrBVy6GaTTjgQd/VfNiZp/VXQ= @@ -860,16 +786,16 @@ github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qv github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= -github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= -github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= +github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= +github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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/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= @@ -883,8 +809,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf 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.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= @@ -894,11 +820,13 @@ github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/b github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= -github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= +github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= +github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= +github.com/hashicorp/consul/proto-public v0.6.2 h1:+DA/3g/IiKlJZb88NBn0ZgXrxJp2NlvCZdEyl+qxvL0= +github.com/hashicorp/consul/proto-public v0.6.2/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg= 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= -github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= +github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= +github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -914,9 +842,8 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -927,25 +854,26 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 h1:OSQYEsRT3tRttZkk6zyC3aAaliwd7Loi/KgXgXxGtwA= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= -github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I= +github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -960,8 +888,8 @@ github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e h1:sr4lujmn9heD030xx/Pd4B/JSmvRhFzuotNXaaV0WLs= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= +github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3 h1:fgVfQ4AC1avVOnu2cfms8VAiD8lUq3vWI8mTocOXN/w= +github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= @@ -971,8 +899,8 @@ github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7H github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs= github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo= -github.com/hetznercloud/hcloud-go/v2 v2.0.0 h1:Sg1DJ+MAKvbYAqaBaq9tPbwXBS2ckPIaMtVdUjKu+4g= -github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= +github.com/hetznercloud/hcloud-go/v2 v2.10.2 h1:9gyTUPhfNbfbS40Spgij5mV5k37bOZgt8iHKCbfGs5I= +github.com/hetznercloud/hcloud-go/v2 v2.10.2/go.mod h1:xQ+8KhIS62W0D78Dpi57jsufWh844gUw1az5OUvaeq8= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -989,13 +917,13 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -1003,13 +931,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= -github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8= +github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -1071,7 +994,6 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= 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.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 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= @@ -1083,34 +1005,25 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 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.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -1119,11 +1032,10 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -1133,13 +1045,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1150,8 +1059,12 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YUw= -github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ= +github.com/linode/linodego v1.37.0 h1:B/2Spzv9jYXzKA+p+GD8fVCNJ7Wuw6P91ZDD9eCkkso= +github.com/linode/linodego v1.37.0/go.mod h1:L7GXKFD3PoN2xSEtFc04wIXP5WK65O10jYQx0PQISWQ= +github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= +github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= 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/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -1162,25 +1075,17 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= 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.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 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.8/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.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -1188,7 +1093,6 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx 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.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 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= @@ -1202,19 +1106,14 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh 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= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= 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/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= 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.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= -github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= +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= @@ -1231,15 +1130,12 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -1250,6 +1146,8 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= 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/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= @@ -1258,6 +1156,8 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5 github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +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= @@ -1276,7 +1176,6 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= -github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= 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/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= @@ -1287,16 +1186,15 @@ 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/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= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 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-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= -github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= +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= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -1307,14 +1205,13 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn 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= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 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.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +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/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= @@ -1323,10 +1220,10 @@ github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= -github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40= +github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M= github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg= github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w= @@ -1340,8 +1237,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= -github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM= -github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= +github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI= +github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1350,7 +1247,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= @@ -1364,14 +1260,16 @@ github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1381,36 +1279,50 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 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/alertmanager v0.26.0 h1:uOMJWfIwJguc3NaM3appWNbbrh6G/OjvaHMk22aBBYc= -github.com/prometheus/alertmanager v0.26.0/go.mod h1:rVcnARltVjavgVaNnmevxK7kOn7IZavyf0KNgHkbEpU= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +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= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= 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.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= 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.10.1-0.20230714054209-2f4150c63f97 h1:oHcfzdJnM/SFppy2aUlvomk37GI33x9vgJULihE5Dt8= -github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97/go.mod h1:LoBCZeRh+5hX+fSULNyFnagYlQG/gBsyA/deNzROkq8= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +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= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 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.47.2-0.20231010075449-4b9c19fe5510 h1:6ksZ7t1hNOzGPPs8DK7SvXQf6UfWzi+W5Z7PCBl8gx4= -github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510/go.mod h1:UC0TwJiF90m2T3iYPQBKnGu8gv3s55dF/EgpTq8gyvo= -github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= -github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= -github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= -github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= +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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= -github.com/regen-network/gocuke v0.6.2/go.mod h1:zYaqIHZobHyd0xOrHGPQjbhGJsuZ1oElx150u2o1xuk= 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= @@ -1420,36 +1332,36 @@ 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.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +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= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20 h1:a9hSJdJcd16e0HoMsnFvaHvxB3pxSD+SC7+CISp7xY0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +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= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= @@ -1458,7 +1370,6 @@ github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY= github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= @@ -1477,53 +1388,58 @@ github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 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.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= -github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 h1:LAgJTg9Yr/uCo2g7Krp88Dco2U45Y6sbJVl8uKoLkys= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 h1:iT9xlcy7Q98F9QheClGBiU0Ig1A+0UhtFkEdKFHvX/0= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f h1:I9fTBJpHkeldFplXUy71eLIn6A6GxuR4xrABoUeD+CM= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f/go.mod h1:V/86loaFSH0dqqUEHqyXVbyNqDRSjvcf9BRomWFTljU= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 h1:BCHu4pNP6arrcHLEWx61XjLaonOd2coQNyL0NTUcaMc= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827/go.mod h1:OPX+wC2TWQsyLNpR7daMt2vMpmsNcoBxbZyGTHr6tiA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 h1:8ZzsGNhqYxmQ/QMO1fuXO7u9Vpl9YUvPJK+td/ZaBJA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564/go.mod h1:Ml88TJTwZCj6yHDkAEN/EhxVutzSlk+kDZgfibRIqF0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.2 h1:YL3ft7KJB7SAopdmJeyeR4/kv0j4jOdagNihXq8OZ38= -github.com/smartcontractkit/chainlink-testing-framework v1.34.2/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.1.2 h1:98v9VUFUpNhU7UofeF/bGyUIVv9jnt+JlIE+I8mhX2c= -github.com/smartcontractkit/seth v1.1.2/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wasp v0.4.5 h1:pgiXwBci2m15eo33AzspzhpNG/gxg+8QGxl+I5LpfsQ= -github.com/smartcontractkit/wasp v0.4.5/go.mod h1:eVhBVLbVv0qORUlN7aR5C4aTN/lTYO3KnN1erO4ROOI= -github.com/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= -github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= +github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+30iWKL/sWq8uyiLHM8k= +github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chainlink-automation v0.8.0 h1:hFz2EHU06bkEfhcqhK8JdjKTWpDOr0XJ6xL9oELDoUg= +github.com/smartcontractkit/chainlink-automation v0.8.0/go.mod h1:ObdjDfgGIaiE48Bb3yYcx1CeGBm392WlEw92U83LlUA= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 h1:BS9i2P/b+PsomEP//bH4j6N2a1DCgLVVzoRw02CnN2s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 h1:qx5p01fqee86cj6EUOCzFc2zILw56v1Q3c5DUuEQWLs= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286/go.mod h1:tsGgeEJc5SUSlfVGSX0wR0EkRU3pM58D6SKF97V68ko= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= +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.4.0 h1:1xTm8UGeDUAjvCXRh08+4xBRX33owH5MqC522JdelM0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 h1:R8F2tpyvN0peK0woG/Spx+IdukxlSSWDDLyFQNkLfUs= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042/go.mod h1:UndTf1YRDBt/4LDauMFou9+vt/M0q6o7u80a9J5Xu+0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 h1:mgjBQIEy+3V3G6K8e+6by3xndgsXdYYsdy+7kzQZwSk= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0/go.mod h1:pdIxrooP5CFGmC0p5NTOBiZAFtMw+5pTT4de5GY3ywA= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.11-0.20241011153842-b2804aed25b4 h1:xDCRiuX4Z1RaAJYd7OegLDPOROsEqPsttIlP38LVqOE= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.11-0.20241011153842-b2804aed25b4/go.mod h1:c5Is0W7DUUEeV369pWbAOYqEktlGeIBQXefGyIMCzvE= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1 h1:2OxnPfvjC+zs0ZokSsRTRnJrEGJ4NVJwZgfroS1lPHs= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 h1:gfhfTn7HkbUHNooSF3c9vzQyN8meWJVGt6G/pNUbpYk= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0/go.mod h1:tqajhpUJA/9OaMCLitghBXjAgqYO4i27St0F4TUO3+M= +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/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.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= 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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1531,32 +1447,31 @@ 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= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +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= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 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.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 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.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +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= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +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= @@ -1568,6 +1483,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1578,19 +1494,16 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.2/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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= 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= @@ -1598,8 +1511,8 @@ github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB 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.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= -github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= +github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw= +github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8= 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/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:BuzhfgfWQbX0dWzYzT1zsORLnHRv3bcRcsaUk0VmXA8= @@ -1612,8 +1525,9 @@ github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vl 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 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= 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= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -1628,10 +1542,7 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= @@ -1648,14 +1559,12 @@ 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.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= 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/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +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= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= @@ -1663,25 +1572,15 @@ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+x 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.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= 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= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= 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= @@ -1693,10 +1592,10 @@ github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7 github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -1707,17 +1606,14 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL 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.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k= -go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= -go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0= -go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= -go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao= -go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= +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.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +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= @@ -1730,10 +1626,10 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 h1:qCPXSQCoD3qeWFb1RuIks8fw9Atxpk78bmtVdi15KhE= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0016/go.mod h1:OdN0alYOlYhHXu6BDlGehrZWgtBuiDsz/rlNeJeXiNg= -go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXnizczQpEs/gg8= -go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= +go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= +go.opentelemetry.io/collector/pdata v1.12.0/go.mod h1:MYeB0MmMAxeM0hstCFrCqWLzdyeYySim2dG6pDT6nYI= +go.opentelemetry.io/collector/semconv v0.105.0 h1:8p6dZ3JfxFTjbY38d8xlQGB1TQ3nPUvs+D0RERniZ1g= +go.opentelemetry.io/collector/semconv v0.105.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= @@ -1742,16 +1638,30 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIX go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 h1:UiRNKd1OgqsLbFwE+wkAWTdiAxXtCBqKIHeBIse4FUA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9/go.mod h1:eqZlW3pJWhjyexnDPrdQxix1pn0wwhI4AO4GKpP/bMI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 h1:0MH3f8lZrflbUWXVxyBg/zviDFdGE062uKh5+fu8Vv0= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0/go.mod h1:Vh68vYiHY5mPdekTr0ox0sALsqjoVy0w3Os278yX5SQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 h1:BJee2iLkfRfl9lc7aFmBwkWxY/RI1RDdXepSF6y8TPE= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0/go.mod h1:DIzlHs3DRscCIBU3Y9YSzPfScwnYnzfnCd4g8zA7bZc= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o= +go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA= +go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= @@ -1786,7 +1696,6 @@ 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.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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= @@ -1800,34 +1709,28 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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.0.0-20220722155217-630584e8d5aa/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.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1838,8 +1741,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-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= 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= @@ -1853,7 +1756,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1862,32 +1764,30 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1906,50 +1806,38 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= 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.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1957,17 +1845,17 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1976,11 +1864,9 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -1997,6 +1883,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2010,35 +1897,29 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2047,7 +1928,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2056,23 +1936,24 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2086,32 +1967,27 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -2152,21 +2028,14 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= +golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= 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= @@ -2174,6 +2043,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= @@ -2195,9 +2066,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -2243,21 +2111,13 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2273,15 +2133,11 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2294,54 +2150,48 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= 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.51.1/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/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 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= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2350,45 +2200,45 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= -k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk= -k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= -k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= +k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= +k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= +k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= +k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= +k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= +k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= +k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= -k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg= +k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= +nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +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= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/integration-tests/load/README.md b/integration-tests/load/README.md index afcf633e5c3..359de3c6d43 100644 --- a/integration-tests/load/README.md +++ b/integration-tests/load/README.md @@ -70,8 +70,10 @@ Gun should be working with one instance of your product. VU(Virtual user) creates a new instance of your product and works with it in `Call()` ### Cluster mode (k8s) + Add configuration to `overrides.toml` -``` + +```toml [WaspAutoBuild] namespace = "wasp" update_image = true diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 0fe13d4bc73..3cd931ecef0 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -22,21 +22,18 @@ import ( "github.com/slack-go/slack" "github.com/stretchr/testify/require" - ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/smartcontractkit/wasp" - - ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/wiremock" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/wiremock" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" gowiremock "github.com/wiremock/go-wiremock" @@ -153,6 +150,7 @@ func setUpDataStreamsWireMock(url string) error { func TestLogTrigger(t *testing.T) { ctx := tests.Context(t) l := logging.GetTestLogger(t) + registryVersion := contractseth.RegistryVersion_2_1 loadedTestConfig, err := tc.GetConfig([]string{"Load"}, tc.Automation) if err != nil { @@ -313,56 +311,16 @@ Load Config: multicallAddress, err := contracts.DeployMultiCallContract(chainClient) require.NoError(t, err, "Error deploying multicall contract") - a := automationv2.NewAutomationTestK8s(l, chainClient, chainlinkNodes) - conf := loadedTestConfig.Automation.AutomationConfig - a.RegistrySettings = contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: *conf.RegistrySettings.PaymentPremiumPPB, - FlatFeeMicroLINK: *conf.RegistrySettings.FlatFeeMicroLINK, - CheckGasLimit: *conf.RegistrySettings.CheckGasLimit, - StalenessSeconds: conf.RegistrySettings.StalenessSeconds, - GasCeilingMultiplier: *conf.RegistrySettings.GasCeilingMultiplier, - MaxPerformGas: *conf.RegistrySettings.MaxPerformGas, - MinUpkeepSpend: conf.RegistrySettings.MinUpkeepSpend, - FallbackGasPrice: conf.RegistrySettings.FallbackGasPrice, - FallbackLinkPrice: conf.RegistrySettings.FallbackLinkPrice, - MaxCheckDataSize: *conf.RegistrySettings.MaxCheckDataSize, - MaxPerformDataSize: *conf.RegistrySettings.MaxPerformDataSize, - MaxRevertDataSize: *conf.RegistrySettings.MaxRevertDataSize, - RegistryVersion: contractseth.RegistryVersion_2_1, - } + a := automationv2.NewAutomationTestK8s(l, chainClient, chainlinkNodes, &loadedTestConfig) + a.RegistrySettings = actions.ReadRegistryConfig(loadedTestConfig) + a.RegistrySettings.RegistryVersion = registryVersion + a.PluginConfig = actions.ReadPluginConfig(loadedTestConfig) + a.PublicConfig = actions.ReadPublicConfig(loadedTestConfig) a.RegistrarSettings = contracts.KeeperRegistrarSettings{ AutoApproveConfigType: uint8(2), - AutoApproveMaxAllowed: math.MaxUint16, + AutoApproveMaxAllowed: 1000, MinLinkJuels: big.NewInt(0), } - a.PluginConfig = ocr2keepers30config.OffchainConfig{ - TargetProbability: *conf.PluginConfig.TargetProbability, - TargetInRounds: *conf.PluginConfig.TargetInRounds, - PerformLockoutWindow: *conf.PluginConfig.PerformLockoutWindow, - GasLimitPerReport: *conf.PluginConfig.GasLimitPerReport, - GasOverheadPerUpkeep: *conf.PluginConfig.GasOverheadPerUpkeep, - MinConfirmations: *conf.PluginConfig.MinConfirmations, - MaxUpkeepBatchSize: *conf.PluginConfig.MaxUpkeepBatchSize, - LogProviderConfig: ocr2keepers30config.LogProviderConfig{ - BlockRate: *conf.PluginConfig.LogProviderConfig.BlockRate, - LogLimit: *conf.PluginConfig.LogProviderConfig.LogLimit, - }, - } - a.PublicConfig = ocr3.PublicConfig{ - DeltaProgress: *conf.PublicConfig.DeltaProgress, - DeltaResend: *conf.PublicConfig.DeltaResend, - DeltaInitial: *conf.PublicConfig.DeltaInitial, - DeltaRound: *conf.PublicConfig.DeltaRound, - DeltaGrace: *conf.PublicConfig.DeltaGrace, - DeltaCertifiedCommitRequest: *conf.PublicConfig.DeltaCertifiedCommitRequest, - DeltaStage: *conf.PublicConfig.DeltaStage, - RMax: *conf.PublicConfig.RMax, - MaxDurationQuery: *conf.PublicConfig.MaxDurationQuery, - MaxDurationObservation: *conf.PublicConfig.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: *conf.PublicConfig.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: *conf.PublicConfig.MaxDurationShouldTransmitAcceptedReport, - F: *conf.PublicConfig.F, - } if *loadedTestConfig.Automation.DataStreams.Enabled { a.SetMercuryCredentialName("cred1") diff --git a/integration-tests/load/automationv2_1/gun.go b/integration-tests/load/automationv2_1/gun.go index 162aca251fb..aa61562741c 100644 --- a/integration-tests/load/automationv2_1/gun.go +++ b/integration-tests/load/automationv2_1/gun.go @@ -5,8 +5,10 @@ import ( "sync" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index 30559743e1d..41fa9a0ce1e 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -8,10 +8,11 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/slack-go/slack" - "github.com/smartcontractkit/seth" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go index 374b3df705c..90c163ca372 100644 --- a/integration-tests/load/functions/functions_test.go +++ b/integration-tests/load/functions/functions_test.go @@ -4,9 +4,10 @@ import ( "testing" "time" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/load/functions/functionscmd/dashboard.go b/integration-tests/load/functions/functionscmd/dashboard.go index ccf56740236..b0a00602f8d 100644 --- a/integration-tests/load/functions/functionscmd/dashboard.go +++ b/integration-tests/load/functions/functionscmd/dashboard.go @@ -4,7 +4,8 @@ import ( "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" "github.com/K-Phoen/grabana/row" - db "github.com/smartcontractkit/wasp/dashboard" + + db "github.com/smartcontractkit/chainlink-testing-framework/wasp/dashboard" ) func main() { diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go index cc6132e94e7..38eddd3163e 100644 --- a/integration-tests/load/functions/gateway_gun.go +++ b/integration-tests/load/functions/gateway_gun.go @@ -10,7 +10,8 @@ import ( "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/types" ) diff --git a/integration-tests/load/functions/gateway_test.go b/integration-tests/load/functions/gateway_test.go index dd1092a595c..9812b7ea081 100644 --- a/integration-tests/load/functions/gateway_test.go +++ b/integration-tests/load/functions/gateway_test.go @@ -3,9 +3,10 @@ package loadfunctions import ( "testing" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" ) diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go index 31ca8752dd3..39c4bdcf94f 100644 --- a/integration-tests/load/functions/onchain_monitoring.go +++ b/integration-tests/load/functions/onchain_monitoring.go @@ -5,9 +5,10 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" ) /* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ diff --git a/integration-tests/load/functions/request_gun.go b/integration-tests/load/functions/request_gun.go index 6b79a2f19ee..ca9ba82c513 100644 --- a/integration-tests/load/functions/request_gun.go +++ b/integration-tests/load/functions/request_gun.go @@ -1,7 +1,7 @@ package loadfunctions import ( - "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" ) type TestMode int diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index 5519c90846b..46c2c12921a 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -8,18 +8,19 @@ import ( "strconv" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/crypto" "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types" diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 6e33eb7e39a..e410856dd2e 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/load-tests -go 1.22.5 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -10,80 +10,111 @@ replace github.com/smartcontractkit/chainlink/integration-tests => ../ require ( github.com/K-Phoen/grabana v0.22.1 github.com/ethereum/go-ethereum v1.13.8 - github.com/go-resty/resty/v2 v2.11.0 + github.com/go-resty/resty/v2 v2.13.1 github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 - github.com/rs/zerolog v1.31.0 + github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 - github.com/smartcontractkit/chainlink-testing-framework v1.34.2 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.11-0.20241011153842-b2804aed25b4 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1 + github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 - github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/seth v1.1.2 - github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/wasp v0.4.7 + github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de github.com/stretchr/testify v1.9.0 github.com/wiremock/go-wiremock v1.9.0 go.uber.org/ratelimit v0.3.0 ) 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.3 // indirect - cosmossdk.io/errors v1.0.0 // indirect - cosmossdk.io/math v1.0.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/math v1.3.0 // indirect + dario.cat/mergo v1.0.1 // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect + github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect + github.com/aws/smithy-go v1.20.4 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect - k8s.io/apimachinery v0.30.2 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 // indirect + github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.4.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.4.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + k8s.io/apimachinery v0.31.1 // indirect ) // avoids ambigious imports of indirect dependencies exclude github.com/hashicorp/consul v1.2.1 require ( - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect - dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/AlekSi/pointer v1.1.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/K-Phoen/sdk v0.12.4 // indirect + github.com/Khan/genqlient v0.7.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NethermindEth/juno v0.3.1 // indirect github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.0 // indirect - github.com/aws/aws-sdk-go v1.45.25 // indirect + github.com/aws/aws-sdk-go v1.54.19 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // 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 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 @@ -91,6 +122,7 @@ require ( github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect @@ -100,33 +132,32 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f // indirect + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/errors v1.10.0 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.37.2 // indirect - github.com/cometbft/cometbft-db v0.7.0 // indirect + github.com/cometbft/cometbft v0.37.5 // indirect + github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/containerd/containerd v1.7.12 // indirect - github.com/containerd/continuity v0.4.3 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect - github.com/cosmos/cosmos-sdk v0.47.4 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/cosmos-sdk v0.47.11 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogoproto v1.4.11 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.0.1 // indirect - github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/cosmos/iavl v0.20.1 // indirect + github.com/cosmos/ibc-go/v7 v7.5.1 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect @@ -140,9 +171,9 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v25.0.2+incompatible // indirect + github.com/docker/docker v27.3.1+incompatible // indirect 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 @@ -152,23 +183,21 @@ require ( github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/esote/minmaxheap v1.0.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fvbommel/sortorder v1.1.0 // indirect - github.com/fxamacker/cbor/v2 v2.6.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // 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/gagliardetto/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect - github.com/getsentry/sentry-go v0.19.0 // indirect + github.com/getsentry/sentry-go v0.23.0 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.9.1 // indirect @@ -181,29 +210,30 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/errors v0.20.4 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/analysis v0.22.2 // indirect + github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/spec v0.20.9 // indirect - github.com/go-openapi/strfmt v0.21.7 // indirect + github.com/go-openapi/loads v0.21.5 // indirect + github.com/go-openapi/spec v0.20.14 // indirect + github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/go-openapi/validate v0.22.1 // indirect + 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.15.5 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect github.com/gogo/status v1.1.1 // indirect - github.com/golang-jwt/jwt/v5 v5.2.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -214,7 +244,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/context v1.1.1 // indirect @@ -229,31 +259,31 @@ require ( github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b // indirect github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect - github.com/grafana/pyroscope-go v1.1.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect - github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect + github.com/grafana/pyroscope-go v1.1.2 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect 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/hashicorp/consul/api v1.25.1 // indirect - github.com/hashicorp/consul/sdk v0.16.0 // 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 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect - github.com/hashicorp/go-retryablehttp v0.7.5 // indirect + github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.6 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect @@ -265,6 +295,7 @@ require ( github.com/huandu/skiplist v1.2.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect @@ -287,13 +318,13 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.3 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect - github.com/leodido/go-urn v1.2.4 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect @@ -304,7 +335,7 @@ require ( 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/miekg/dns v1.1.56 // 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-homedir v1.1.0 // indirect @@ -313,10 +344,12 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.4.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -328,13 +361,12 @@ require ( github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect 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/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc5 // indirect - github.com/opencontainers/runc v1.1.10 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -344,21 +376,22 @@ require ( 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/pkg/browser v0.0.0-20210911075715-681adbf594b8 // 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.26.0 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/alertmanager v0.27.0 // indirect + github.com/prometheus/client_golang v1.20.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect - github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97 // indirect + github.com/prometheus/exporter-toolkit v0.11.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/prometheus/prometheus v0.48.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/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.12.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/scylladb/go-reflectx v1.0.1 // indirect @@ -368,41 +401,43 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect + 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.21 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f // indirect - github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.2-0.20240805111647-acf86c1e347a // indirect - github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 // indirect - github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.7.3 // indirect + github.com/smartcontractkit/chain-selectors v1.0.27 // indirect + github.com/smartcontractkit/chainlink-automation v0.8.0 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect + github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect + github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 // indirect + github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect + github.com/smartcontractkit/wsrpc v0.8.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cobra v1.8.1 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.15.0 // 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/stretchr/objx v0.5.2 // indirect - github.com/subosito/gotenv v1.4.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // 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.28.0 // indirect + github.com/testcontainers/testcontainers-go v0.33.0 // 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 github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect @@ -413,22 +448,23 @@ require ( github.com/umbracle/ethgo v0.1.3 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/vektah/gqlparser/v2 v2.5.11 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect - go.etcd.io/bbolt v1.3.8 // indirect - go.etcd.io/etcd/api/v3 v3.5.10 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect - go.etcd.io/etcd/client/v3 v3.5.10 // indirect + go.etcd.io/bbolt v1.3.9 // indirect + go.etcd.io/etcd/api/v3 v3.5.14 // indirect + 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.0.0-rcv0016 // indirect - go.opentelemetry.io/collector/semconv v0.87.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.53.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect @@ -445,103 +481,54 @@ require ( go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/time v0.6.0 // indirect + golang.org/x/tools v0.25.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.0 // indirect google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/grpc v1.66.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect 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/api v0.30.2 // indirect - k8s.io/apiextensions-apiserver v0.30.2 // indirect - k8s.io/cli-runtime v0.28.2 // indirect - k8s.io/client-go v1.5.2 // indirect - k8s.io/component-base v0.30.2 // indirect + k8s.io/api v0.31.1 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/cli-runtime v0.31.0 // indirect + k8s.io/client-go v0.31.1 // indirect + k8s.io/component-base v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.28.2 // indirect - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect - nhooyr.io/websocket v1.8.7 // indirect - pgregory.net/rapid v0.5.5 // indirect + k8s.io/kubectl v0.31.0 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + nhooyr.io/websocket v1.8.10 // indirect + pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.18.4 // indirect + sigs.k8s.io/controller-runtime v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect; indirect nhooyr.io/websocket v1.8.7 // indirect ) replace ( - github.com/go-kit/log => github.com/go-kit/log v0.2.1 - // replicating the replace directive on cosmos SDK github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 - github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 - - // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 - github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - - // type func(a Label, b Label) bool of func(a, b Label) bool {…} does not match inferred type func(a Label, b Label) int for func(a E, b E) int - github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 -) - -replace ( - github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.14.0 - github.com/prometheus/common => github.com/prometheus/common v0.42.0 -) - -replace github.com/chaos-mesh/chaos-mesh/api => github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f - -replace ( - k8s.io/api => k8s.io/api v0.28.2 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.28.2 - k8s.io/apimachinery => k8s.io/apimachinery v0.28.2 - k8s.io/apiserver => k8s.io/apiserver v0.28.2 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.28.2 - k8s.io/client-go => k8s.io/client-go v0.28.2 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.28.2 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.28.2 - k8s.io/code-generator => k8s.io/code-generator v0.28.2 - k8s.io/component-base => k8s.io/component-base v0.28.2 - k8s.io/component-helpers => k8s.io/component-helpers v0.28.2 - k8s.io/controller-manager => k8s.io/controller-manager v0.28.2 - k8s.io/cri-api => k8s.io/cri-api v0.28.2 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.28.2 - k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.28.2 - k8s.io/endpointslice => k8s.io/endpointslice v0.28.2 - k8s.io/kms => k8s.io/kms v0.28.2 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.28.2 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.28.2 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.28.2 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.28.2 - k8s.io/kubectl => k8s.io/kubectl v0.28.2 - k8s.io/kubelet => k8s.io/kubelet v0.28.2 - k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.28.2 - k8s.io/metrics => k8s.io/metrics v0.28.2 - k8s.io/mount-utils => k8s.io/mount-utils v0.28.2 - k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.28.2 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.28.2 - k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.28.2 - k8s.io/sample-controller => k8s.io/sample-controller v0.28.2 - sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.16.2 + github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264 ) diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 16b3525476e..0467fd90bbd 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -4,7 +4,6 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR 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.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -15,9 +14,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= @@ -31,7 +27,6 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -48,7 +43,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -59,18 +53,18 @@ 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= cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= -cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca h1:msenprh2BLLRwNT7zN56TbBHOGk/7ARQckXHxXyvjoQ= -cosmossdk.io/log v1.1.1-0.20230704160919-88f2c830b0ca/go.mod h1:PkIAKXZvaxrTRc++z53XMRvFk8AcGGWYHcMIPzVYX9c= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= +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.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +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= @@ -83,43 +77,29 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw= -github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 h1:GJHeeA2N7xrG3q30L2UXDyuWRzDM900/65j70wcM4Ww= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= -github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= +github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU= +github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4= github.com/CosmWasm/wasmd v0.40.1 h1:LxbO78t/6S8TkeQlUrJ0m5O87HtAwLx4RGHq3rdrOEU= github.com/CosmWasm/wasmd v0.40.1/go.mod h1:6EOwnv7MpuFaEqxcUOdFV9i4yvrdOciaY6VQ1o7A3yg= github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ= @@ -133,11 +113,12 @@ github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/K-Phoen/grabana v0.22.1 h1:b/O+C3H2H6VNYSeMCYUO4X4wYuwFXgBcRkvYa+fjpQA= github.com/K-Phoen/grabana v0.22.1/go.mod h1:3LTXrTzQzTKTgvKSXdRjlsJbizSOW/V23Q3iX00R5bU= github.com/K-Phoen/sdk v0.12.4 h1:j2EYuBJm3zDTD0fGKACVFWxAXtkR0q5QzfVqxmHSeGQ= github.com/K-Phoen/sdk v0.12.4/go.mod h1:qmM0wO23CtoDux528MXPpYvS4XkRWkWX6rvX9Za8EVU= +github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= +github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -148,10 +129,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb h1:Mv8SscePPyw2ju4igIJAjFgcq5zCQfjgbz53DwYu5mc= @@ -161,9 +140,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= @@ -172,13 +148,12 @@ 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/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA= +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= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= @@ -192,6 +167,10 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax 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.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -202,9 +181,10 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQVoh6kY+c4b0HUchHjGWBI8288VhH50qxKG3hdEg0= +github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c/go.mod h1:3XzxudkrYVUvbduN/uI2fl4lSrMSzU0+3RCu2mpnfx8= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= @@ -214,20 +194,51 @@ github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw 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.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= -github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +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.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= +github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= +github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= +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.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= 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= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= @@ -238,13 +249,15 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= 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= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= -github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= @@ -253,6 +266,8 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU 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.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= @@ -273,14 +288,13 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f h1:onZ3oc6l1Gz8pVpQ0c1U1Cb11kIMoDb3xtEy/iZbYZM= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a h1:6Pg3a6j/41QDzH/oYcMLwwKsf3x/HXcu9W/dBaf2Hzs= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -296,7 +310,6 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -304,41 +317,36 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= -github.com/cockroachdb/apd/v3 v3.1.0/go.mod h1:6qgPBMXjATAdD/VefbRP9NoSLKjbB4LCoA7gN4LpHs4= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= +github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= -github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0= +github.com/cometbft/cometbft v0.37.5/go.mod h1:QC+mU0lBhKn8r9qvmnq53Dmf3DWBt4VtkcKw2C81wxY= +github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= +github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= -github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= 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/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= @@ -354,10 +362,10 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV 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.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.4 h1:FVUpEprm58nMmBX4xkRdMDaIG5Nr4yy92HZAfGAw9bg= -github.com/cosmos/cosmos-sdk v0.47.4/go.mod h1:R5n+uM7vguVPFap4pgkdvQCT1nVo/OtPwrlAU40rvok= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.47.11 h1:0Qx7eORw0RJqPv+mvDuU8NQ1LV3nJJKJnPoYblWHolc= +github.com/cosmos/cosmos-sdk v0.47.11/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -365,14 +373,14 @@ github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiK github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= -github.com/cosmos/ibc-go/v7 v7.0.1 h1:NIBNRWjlOoFvFQu1ZlgwkaSeHO5avf4C1YQiWegt8jw= -github.com/cosmos/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab h1:I9ialKTQo7248V827Bba4OuKPmk+FPzmTVHsLXaIJWw= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab/go.mod h1:2CwqasX5dSD7Hbp/9b6lhK6BwoBDCBldx7gPKRukR60= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= +github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/ibc-go/v7 v7.5.1 h1:KqS/g7W7EMX1OtOvufS8lWMJibOKpdgtNNZIU6fAgVU= +github.com/cosmos/ibc-go/v7 v7.5.1/go.mod h1:ktFg5GvKOyrGCqTWtW7Grj5uweU4ZapxrNeVS1CLLbo= +github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= +github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw= +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.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= @@ -392,15 +400,12 @@ 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/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/gherkin/go/v22 v22.0.0/go.mod h1:3mJT10B2GGn3MvVPd3FwR7m2u4tLhSRhWUqJU4KN4Fg= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= -github.com/cucumber/common/messages/go/v17 v17.1.1/go.mod h1:bpGxb57tDE385Rb2EohgUadLkAbhoC4IyCFi89u/JQI= 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= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e/go.mod h1:IJgIiGUARc4aOr4bOQ85klmjsShkEEfiRc6q/yBSfo8= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -418,7 +423,6 @@ github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFM 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 v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 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= @@ -430,16 +434,15 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA 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/digitalocean/godo v1.99.0 h1:gUHO7n9bDaZFWvbzOum4bXE0/09ZuYA9yA8idQHX57E= -github.com/digitalocean/godo v1.99.0/go.mod h1:SsS2oXo2rznfM/nORlZ/6JaUJZFhmKTib1YhopUc8NA= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +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= +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= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= -github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -453,23 +456,19 @@ github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9Tzqv github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= @@ -480,23 +479,15 @@ github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0 github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= 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.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= @@ -508,14 +499,12 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= -github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +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/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= @@ -524,16 +513,14 @@ github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtL 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/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= 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/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= -github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= +github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE= +github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= @@ -543,17 +530,12 @@ github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfm github.com/gin-contrib/sessions v0.0.5/go.mod h1:vYAuaUPqie3WUSsft6HUlCjlwwoJQs97miaG2+7neKY= github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4 h1:Z9J0PVIt1PuibOShaOw1jH8hUYz+Ak8NLsR/GI0Hv5I= github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4/go.mod h1:CEPcgZiz8998l9E8fDm16h8UfHRL7b+5oG0j/0koeVw= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -561,15 +543,18 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 h1:ymLjT4f35nQbASLnvxEde4XOBL+Sn7rFuV+FOJqkljg= github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -577,62 +562,41 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= -github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= +github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= +github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= +github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= -github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= -github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0= +github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw= +github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 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.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +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-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.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= -github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g= +github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0= 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= @@ -642,47 +606,18 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6lpIc2g= github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= +github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -694,15 +629,12 @@ github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= @@ -746,7 +678,6 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -766,13 +697,11 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= @@ -783,7 +712,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -793,12 +721,9 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -807,19 +732,17 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= -github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= +github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= +github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -832,7 +755,6 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX 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.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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= @@ -850,16 +772,16 @@ github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qv github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= -github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= -github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= +github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= +github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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/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= @@ -873,8 +795,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf 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.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= @@ -884,11 +806,13 @@ github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/b github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= -github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= +github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= +github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= +github.com/hashicorp/consul/proto-public v0.6.2 h1:+DA/3g/IiKlJZb88NBn0ZgXrxJp2NlvCZdEyl+qxvL0= +github.com/hashicorp/consul/proto-public v0.6.2/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg= 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= -github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= +github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= +github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -904,9 +828,8 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -917,25 +840,26 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99 h1:OSQYEsRT3tRttZkk6zyC3aAaliwd7Loi/KgXgXxGtwA= +github.com/hashicorp/go-plugin v1.6.2-0.20240829161738-06afb6d7ae99/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= -github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I= +github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -950,8 +874,8 @@ github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e h1:sr4lujmn9heD030xx/Pd4B/JSmvRhFzuotNXaaV0WLs= -github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= +github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3 h1:fgVfQ4AC1avVOnu2cfms8VAiD8lUq3vWI8mTocOXN/w= +github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= @@ -959,8 +883,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= -github.com/hetznercloud/hcloud-go/v2 v2.0.0 h1:Sg1DJ+MAKvbYAqaBaq9tPbwXBS2ckPIaMtVdUjKu+4g= -github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= +github.com/hetznercloud/hcloud-go/v2 v2.10.2 h1:9gyTUPhfNbfbS40Spgij5mV5k37bOZgt8iHKCbfGs5I= +github.com/hetznercloud/hcloud-go/v2 v2.10.2/go.mod h1:xQ+8KhIS62W0D78Dpi57jsufWh844gUw1az5OUvaeq8= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -977,13 +901,13 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -991,13 +915,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= -github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8= +github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -1059,7 +978,6 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= 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.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 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= @@ -1071,34 +989,25 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 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.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -1107,11 +1016,10 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -1121,13 +1029,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1138,8 +1043,12 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YUw= -github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ= +github.com/linode/linodego v1.37.0 h1:B/2Spzv9jYXzKA+p+GD8fVCNJ7Wuw6P91ZDD9eCkkso= +github.com/linode/linodego v1.37.0/go.mod h1:L7GXKFD3PoN2xSEtFc04wIXP5WK65O10jYQx0PQISWQ= +github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= +github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= 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= @@ -1148,25 +1057,17 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= 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.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 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.8/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.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -1174,7 +1075,6 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx 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.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 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= @@ -1188,19 +1088,14 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh 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= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= 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/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= 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.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= -github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= +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= @@ -1217,15 +1112,12 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -1236,6 +1128,8 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= 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/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= @@ -1244,6 +1138,8 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5 github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +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= @@ -1262,23 +1158,21 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= -github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= 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/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/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= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 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-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= -github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= +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= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -1289,14 +1183,13 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn 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= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 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.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +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/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= @@ -1305,8 +1198,8 @@ github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40= github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M= github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg= @@ -1322,8 +1215,8 @@ github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= -github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM= -github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= +github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI= +github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1332,7 +1225,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= @@ -1346,14 +1238,16 @@ github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1363,36 +1257,50 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 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/alertmanager v0.26.0 h1:uOMJWfIwJguc3NaM3appWNbbrh6G/OjvaHMk22aBBYc= -github.com/prometheus/alertmanager v0.26.0/go.mod h1:rVcnARltVjavgVaNnmevxK7kOn7IZavyf0KNgHkbEpU= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +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= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= 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.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= 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.10.1-0.20230714054209-2f4150c63f97 h1:oHcfzdJnM/SFppy2aUlvomk37GI33x9vgJULihE5Dt8= -github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97/go.mod h1:LoBCZeRh+5hX+fSULNyFnagYlQG/gBsyA/deNzROkq8= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +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= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 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.47.2-0.20231010075449-4b9c19fe5510 h1:6ksZ7t1hNOzGPPs8DK7SvXQf6UfWzi+W5Z7PCBl8gx4= -github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510/go.mod h1:UC0TwJiF90m2T3iYPQBKnGu8gv3s55dF/EgpTq8gyvo= -github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= -github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= -github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= -github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= +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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= -github.com/regen-network/gocuke v0.6.2/go.mod h1:zYaqIHZobHyd0xOrHGPQjbhGJsuZ1oElx150u2o1xuk= 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= @@ -1402,36 +1310,36 @@ 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.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +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= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20 h1:a9hSJdJcd16e0HoMsnFvaHvxB3pxSD+SC7+CISp7xY0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +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= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= @@ -1440,7 +1348,6 @@ github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY= github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= @@ -1451,61 +1358,63 @@ github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhV 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 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shoenig/test v0.6.6 h1:Oe8TPH9wAbv++YPNDKJWUnI8Q4PPWCx3UbOfH+FxiMU= +github.com/shoenig/test v0.6.6/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 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.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= -github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95 h1:LAgJTg9Yr/uCo2g7Krp88Dco2U45Y6sbJVl8uKoLkys= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240806144315-04ac101e9c95/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82 h1:iT9xlcy7Q98F9QheClGBiU0Ig1A+0UhtFkEdKFHvX/0= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240816202716-6930d109fd82/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f h1:I9fTBJpHkeldFplXUy71eLIn6A6GxuR4xrABoUeD+CM= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240801131703-fd75761c982f/go.mod h1:V/86loaFSH0dqqUEHqyXVbyNqDRSjvcf9BRomWFTljU= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 h1:BCHu4pNP6arrcHLEWx61XjLaonOd2coQNyL0NTUcaMc= -github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827/go.mod h1:OPX+wC2TWQsyLNpR7daMt2vMpmsNcoBxbZyGTHr6tiA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564 h1:8ZzsGNhqYxmQ/QMO1fuXO7u9Vpl9YUvPJK+td/ZaBJA= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240806154405-8e5684f98564/go.mod h1:Ml88TJTwZCj6yHDkAEN/EhxVutzSlk+kDZgfibRIqF0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.2 h1:YL3ft7KJB7SAopdmJeyeR4/kv0j4jOdagNihXq8OZ38= -github.com/smartcontractkit/chainlink-testing-framework v1.34.2/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.2-0.20240805111647-acf86c1e347a h1:8GtvGJaGyKzx/ar1yX74GxrzIYWTZVTyv4pYB/1ln8w= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.2-0.20240805111647-acf86c1e347a/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= -github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= -github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= -github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.1.2 h1:98v9VUFUpNhU7UofeF/bGyUIVv9jnt+JlIE+I8mhX2c= -github.com/smartcontractkit/seth v1.1.2/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= -github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= -github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wasp v0.4.7 h1:7mKJfwzFbuE8xVLUYtLt7Bjw8q/bmVZRW6Ks8kc1LVM= -github.com/smartcontractkit/wasp v0.4.7/go.mod h1:jeabvyXikb2aNoLQwcZGqaz17efrR8NJhpq4seAmdgs= -github.com/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= -github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/chain-selectors v1.0.27 h1:VE/ftX9Aae4gnw67yR1raKi+30iWKL/sWq8uyiLHM8k= +github.com/smartcontractkit/chain-selectors v1.0.27/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chainlink-automation v0.8.0 h1:hFz2EHU06bkEfhcqhK8JdjKTWpDOr0XJ6xL9oELDoUg= +github.com/smartcontractkit/chainlink-automation v0.8.0/go.mod h1:ObdjDfgGIaiE48Bb3yYcx1CeGBm392WlEw92U83LlUA= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638 h1:BS9i2P/b+PsomEP//bH4j6N2a1DCgLVVzoRw02CnN2s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241021132654-e5f3ecb77638/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286 h1:qx5p01fqee86cj6EUOCzFc2zILw56v1Q3c5DUuEQWLs= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241021103500-39a6e78c0286/go.mod h1:tsGgeEJc5SUSlfVGSX0wR0EkRU3pM58D6SKF97V68ko= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= +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/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042 h1:R8F2tpyvN0peK0woG/Spx+IdukxlSSWDDLyFQNkLfUs= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241017193838-6c937ac2d042/go.mod h1:UndTf1YRDBt/4LDauMFou9+vt/M0q6o7u80a9J5Xu+0= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 h1:mgjBQIEy+3V3G6K8e+6by3xndgsXdYYsdy+7kzQZwSk= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0/go.mod h1:pdIxrooP5CFGmC0p5NTOBiZAFtMw+5pTT4de5GY3ywA= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.11-0.20241011153842-b2804aed25b4 h1:xDCRiuX4Z1RaAJYd7OegLDPOROsEqPsttIlP38LVqOE= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.11-0.20241011153842-b2804aed25b4/go.mod h1:c5Is0W7DUUEeV369pWbAOYqEktlGeIBQXefGyIMCzvE= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1 h1:2OxnPfvjC+zs0ZokSsRTRnJrEGJ4NVJwZgfroS1lPHs= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 h1:gfhfTn7HkbUHNooSF3c9vzQyN8meWJVGt6G/pNUbpYk= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0/go.mod h1:tqajhpUJA/9OaMCLitghBXjAgqYO4i27St0F4TUO3+M= +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/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.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= 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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1513,32 +1422,31 @@ 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= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +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= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 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.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 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.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +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= @@ -1550,6 +1458,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1560,19 +1469,16 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.2/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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= 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= @@ -1580,8 +1486,8 @@ github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB 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.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= -github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= +github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw= +github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8= 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= @@ -1592,8 +1498,9 @@ github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vl 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 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= 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= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -1608,10 +1515,7 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= @@ -1628,14 +1532,12 @@ 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.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= 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/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +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= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= github.com/wiremock/go-wiremock v1.9.0 h1:9xcU4/IoEfgCaH4TGhQTtiQyBh2eMtu9JB6ppWduK+E= @@ -1645,25 +1547,15 @@ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+x 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.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= 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= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= 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= @@ -1675,10 +1567,10 @@ github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7 github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -1689,17 +1581,14 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL 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.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k= -go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= -go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0= -go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= -go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao= -go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= +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.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +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= @@ -1712,10 +1601,10 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 h1:qCPXSQCoD3qeWFb1RuIks8fw9Atxpk78bmtVdi15KhE= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0016/go.mod h1:OdN0alYOlYhHXu6BDlGehrZWgtBuiDsz/rlNeJeXiNg= -go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXnizczQpEs/gg8= -go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= +go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= +go.opentelemetry.io/collector/pdata v1.12.0/go.mod h1:MYeB0MmMAxeM0hstCFrCqWLzdyeYySim2dG6pDT6nYI= +go.opentelemetry.io/collector/semconv v0.105.0 h1:8p6dZ3JfxFTjbY38d8xlQGB1TQ3nPUvs+D0RERniZ1g= +go.opentelemetry.io/collector/semconv v0.105.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= @@ -1724,16 +1613,30 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIX go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 h1:UiRNKd1OgqsLbFwE+wkAWTdiAxXtCBqKIHeBIse4FUA= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9/go.mod h1:eqZlW3pJWhjyexnDPrdQxix1pn0wwhI4AO4GKpP/bMI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 h1:0MH3f8lZrflbUWXVxyBg/zviDFdGE062uKh5+fu8Vv0= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0/go.mod h1:Vh68vYiHY5mPdekTr0ox0sALsqjoVy0w3Os278yX5SQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 h1:BJee2iLkfRfl9lc7aFmBwkWxY/RI1RDdXepSF6y8TPE= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0/go.mod h1:DIzlHs3DRscCIBU3Y9YSzPfScwnYnzfnCd4g8zA7bZc= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o= +go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA= +go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= @@ -1768,7 +1671,6 @@ 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.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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= @@ -1782,34 +1684,28 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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.0.0-20220722155217-630584e8d5aa/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.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1820,8 +1716,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-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= 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= @@ -1835,7 +1731,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1844,32 +1739,30 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1888,50 +1781,38 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= 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.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1939,17 +1820,17 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1957,11 +1838,9 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -1978,6 +1857,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1991,35 +1871,29 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2027,7 +1901,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2036,23 +1909,24 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2066,32 +1940,27 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -2132,21 +2001,14 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= +golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= 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= @@ -2154,6 +2016,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= @@ -2175,9 +2039,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -2223,21 +2084,13 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2253,15 +2106,11 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2274,54 +2123,49 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= 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.51.1/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/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 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= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2330,45 +2174,45 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= -k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk= -k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= -k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= +k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= +k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= -k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg= +k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= +nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +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= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/integration-tests/load/ocr/gun.go b/integration-tests/load/ocr/gun.go index c4b79ceaf42..990c77e0b3a 100644 --- a/integration-tests/load/ocr/gun.go +++ b/integration-tests/load/ocr/gun.go @@ -6,8 +6,10 @@ import ( "time" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index 49bce3eca58..55b683a0a74 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/crib" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -28,12 +28,12 @@ func TestOCRLoad(t *testing.T) { config, err := tc.GetConfig([]string{"Load"}, tc.OCR) require.NoError(t, err) - sethClient, msClient, bootstrapNode, workerNodes, err := crib.ConnectRemote() + sethClient, msClient, bootstrapNode, workerNodes, _, err := crib.ConnectRemote() require.NoError(t, err) - lta, err := actions.SetupOCRv1Cluster(l, sethClient, workerNodes) + lta, err := actions.SetupOCRv1Cluster(l, sethClient, config.OCR, workerNodes) require.NoError(t, err) - ocrInstances, err := actions.SetupOCRv1Feed(l, sethClient, lta, msClient, bootstrapNode, workerNodes) + ocrInstances, err := actions.SetupOCRv1Feed(l, sethClient, lta, config.OCR, msClient, bootstrapNode, workerNodes) require.NoError(t, err) cfg := config.OCR @@ -61,10 +61,10 @@ func TestOCRVolume(t *testing.T) { config, err := tc.GetConfig([]string{"Volume"}, tc.OCR) require.NoError(t, err) - sethClient, msClient, bootstrapNode, workerNodes, err := crib.ConnectRemote() + sethClient, msClient, bootstrapNode, workerNodes, _, err := crib.ConnectRemote() require.NoError(t, err) - lta, err := actions.SetupOCRv1Cluster(l, sethClient, workerNodes) + lta, err := actions.SetupOCRv1Cluster(l, sethClient, config.OCR, workerNodes) require.NoError(t, err) cfg := config.OCR @@ -77,7 +77,7 @@ func TestOCRVolume(t *testing.T) { LoadType: wasp.VU, CallTimeout: cfg.Volume.VerificationTimeout.Duration, Schedule: wasp.Plain(*cfg.Volume.Rate, cfg.Volume.TestDuration.Duration), - VU: NewVU(l, sethClient, *cfg.Volume.VURequestsPerUnit, cfg.Volume.RateLimitUnitDuration.Duration, lta, bootstrapNode, workerNodes, msClient), + VU: NewVU(l, sethClient, cfg, *cfg.Volume.VURequestsPerUnit, cfg.Volume.RateLimitUnitDuration.Duration, lta, bootstrapNode, workerNodes, msClient), Labels: CommonTestLabels, LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), })) diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index 88f186c5ee1..c337e338a82 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -8,17 +8,16 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/wasp" "go.uber.org/ratelimit" - client2 "github.com/smartcontractkit/chainlink-testing-framework/client" + client2 "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ocr" ) // VU is a virtual user for the OCR load test @@ -36,11 +35,13 @@ type VU struct { msClient *client2.MockserverClient l zerolog.Logger ocrInstances []contracts.OffchainAggregator + config ocr.OffChainAggregatorsConfig } func NewVU( l zerolog.Logger, seth *seth.Client, + config ocr.OffChainAggregatorsConfig, rate int, rateUnit time.Duration, lta common.Address, @@ -59,6 +60,7 @@ func NewVU( msClient: msClient, bootstrapNode: bootstrapNode, workerNodes: workerNodes, + config: config, } } @@ -74,11 +76,12 @@ func (m *VU) Clone(_ *wasp.Generator) wasp.VirtualUser { msClient: m.msClient, bootstrapNode: m.bootstrapNode, workerNodes: m.workerNodes, + config: m.config, } } func (m *VU) Setup(_ *wasp.Generator) error { - ocrInstances, err := actions.DeployOCRv1Contracts(m.l, m.seth, 1, m.lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(m.workerNodes)) + ocrInstances, err := actions.SetupOCRv1Contracts(m.l, m.seth, m.config, m.lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(m.workerNodes)) if err != nil { return err } diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index bf7449a2470..20a20b40834 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -4,10 +4,12 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/wasp" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" diff --git a/integration-tests/load/vrfv2/onchain_monitoring.go b/integration-tests/load/vrfv2/onchain_monitoring.go index e057e7f8d23..9ba53f39e7f 100644 --- a/integration-tests/load/vrfv2/onchain_monitoring.go +++ b/integration-tests/load/vrfv2/onchain_monitoring.go @@ -6,7 +6,8 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 0075300c7d3..edf68c283e7 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -7,15 +7,16 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" @@ -72,9 +73,9 @@ func TestVRFV2Performance(t *testing.T) { Uint16("RandomnessRequestCountPerRequestDeviation", *vrfv2Config.General.RandomnessRequestCountPerRequestDeviation). Bool("UseExistingEnv", *vrfv2Config.General.UseExistingEnv). Msg("Performance Test Configuration") + cleanupFn := func() { teardown(t, vrfContracts.VRFV2Consumers[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). @@ -82,6 +83,8 @@ func TestVRFV2Performance(t *testing.T) { Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") } else { if *vrfv2Config.General.CancelSubsAfterTestRun { + // wait for all txs to be mined in order to avoid nonce issues + time.Sleep(10 * time.Second) //cancel subs and return funds to sub owner vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) } @@ -307,7 +310,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { wgBlockNumberTobe.Add(1) //Wait at least 256 blocks latestBlockNumber, err := sethClient.Client.BlockNumber(testcontext.Get(t)) - require.NoError(t, err) + require.NoError(t, err, "error getting latest block number") _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), latestBlockNumber+uint64(257), diff --git a/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go b/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go index e80d7516fd4..24e67991380 100644 --- a/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go +++ b/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go @@ -3,7 +3,7 @@ package main import ( "os" - db "github.com/smartcontractkit/wasp/dashboard" + db "github.com/smartcontractkit/chainlink-testing-framework/wasp/dashboard" "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 430e9f5ff12..4aac3927518 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -5,10 +5,12 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/wasp" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" diff --git a/integration-tests/load/vrfv2plus/onchain_monitoring.go b/integration-tests/load/vrfv2plus/onchain_monitoring.go index 50c0ac18a98..2bb082dc118 100644 --- a/integration-tests/load/vrfv2plus/onchain_monitoring.go +++ b/integration-tests/load/vrfv2plus/onchain_monitoring.go @@ -6,7 +6,8 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index e8e1d7779c1..d3f985df143 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -6,16 +6,17 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" @@ -81,6 +82,8 @@ func TestVRFV2PlusPerformance(t *testing.T) { Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") } else { if *testConfig.VRFv2Plus.General.CancelSubsAfterTestRun { + // wait for all txs to be mined in order to avoid nonce issues + time.Sleep(10 * time.Second) //cancel subs and return funds to sub owner vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) } diff --git a/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go b/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go index 75853e7e211..569a0bd1346 100644 --- a/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go +++ b/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go @@ -3,7 +3,7 @@ package main import ( "os" - db "github.com/smartcontractkit/wasp/dashboard" + db "github.com/smartcontractkit/chainlink-testing-framework/wasp/dashboard" "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" diff --git a/integration-tests/load/zcluster/cluster_entrypoint_test.go b/integration-tests/load/zcluster/cluster_entrypoint_test.go index aace97b0825..0f3ea5e4044 100644 --- a/integration-tests/load/zcluster/cluster_entrypoint_test.go +++ b/integration-tests/load/zcluster/cluster_entrypoint_test.go @@ -3,9 +3,10 @@ package zcluster import ( "testing" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index a17f00e179f..12f0c2a1e74 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 808e394d69b..fde37d9f06f 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -10,21 +10,19 @@ import ( "strings" "testing" - ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "go.uber.org/zap/zapcore" - ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - sethUtils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + sethUtils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/onsi/gomega" "github.com/stretchr/testify/require" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -132,45 +130,19 @@ func TestAutomationReorg(t *testing.T) { err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.GetCommonConfig().ChainlinkNodeFunding)) require.NoError(t, err, "Failed to fund the nodes") - gethRPCClient := ctfClient.NewRPCClient(evmNetwork.HTTPURLs[0]) + gethRPCClient := ctfClient.NewRPCClient(evmNetwork.HTTPURLs[0], nil) - registryConfig := actions.AutomationDefaultRegistryConfig(config) - registryConfig.RegistryVersion = registryVersion - - a := automationv2.NewAutomationTestDocker(l, sethClient, nodeClients) + a := automationv2.NewAutomationTestDocker(l, sethClient, nodeClients, &config) a.SetMercuryCredentialName("cred1") - a.RegistrySettings = registryConfig + a.RegistrySettings = actions.ReadRegistryConfig(config) + a.RegistrySettings.RegistryVersion = registryVersion + a.PluginConfig = actions.ReadPluginConfig(config) + a.PublicConfig = actions.ReadPublicConfig(config) a.RegistrarSettings = contracts.KeeperRegistrarSettings{ AutoApproveConfigType: uint8(2), AutoApproveMaxAllowed: 1000, MinLinkJuels: big.NewInt(0), } - plCfg := config.GetAutomationConfig().AutomationConfig.PluginConfig - a.PluginConfig = ocr2keepers30config.OffchainConfig{ - TargetProbability: *plCfg.TargetProbability, - TargetInRounds: *plCfg.TargetInRounds, - PerformLockoutWindow: *plCfg.PerformLockoutWindow, - GasLimitPerReport: *plCfg.GasLimitPerReport, - GasOverheadPerUpkeep: *plCfg.GasOverheadPerUpkeep, - MinConfirmations: *plCfg.MinConfirmations, - MaxUpkeepBatchSize: *plCfg.MaxUpkeepBatchSize, - } - pubCfg := config.GetAutomationConfig().AutomationConfig.PublicConfig - a.PublicConfig = ocr3.PublicConfig{ - DeltaProgress: *pubCfg.DeltaProgress, - DeltaResend: *pubCfg.DeltaResend, - DeltaInitial: *pubCfg.DeltaInitial, - DeltaRound: *pubCfg.DeltaRound, - DeltaGrace: *pubCfg.DeltaGrace, - DeltaCertifiedCommitRequest: *pubCfg.DeltaCertifiedCommitRequest, - DeltaStage: *pubCfg.DeltaStage, - RMax: *pubCfg.RMax, - MaxDurationQuery: *pubCfg.MaxDurationQuery, - MaxDurationObservation: *pubCfg.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: *pubCfg.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: *pubCfg.MaxDurationShouldTransmitAcceptedReport, - F: *pubCfg.F, - } a.SetupAutomationDeployment(t) a.SetDockerEnv(env) @@ -197,6 +169,7 @@ func TestAutomationReorg(t *testing.T) { false, false, a.WETHToken, + &config, ) if isLogTrigger { diff --git a/integration-tests/run-books/OCR.md b/integration-tests/run-books/OCR.md new file mode 100644 index 00000000000..159b7d98062 --- /dev/null +++ b/integration-tests/run-books/OCR.md @@ -0,0 +1,252 @@ + +# OCR Tests Run-Book + +- [OCR Tests Run-Book](#ocr-tests-run-book) + - [Summary](#summary) + - [Instructions](#instructions) + - [Pre-requisites](#pre-requisites) + - [Run Tests](#run-tests) + - [COMMON COMMANDS](#common-commands) + - [Docker](#docker) + - [Kubernetes](#kubernetes) + - [CI (with overrides)](#ci-with-overrides) + - [SMOKE](#smoke) + - [Docker](#docker-1) + - [CI](#ci) + - [SOAK](#soak) + - [Kubernetes](#kubernetes-1) + - [CI](#ci-1) + - [LOAD](#load) + - [CHAOS](#chaos) + - [Kubernetes](#kubernetes-2) + - [CI](#ci-2) + - [MIGRATION (core version upgrade)](#migration-core-version-upgrade) + - [Docker](#docker-2) + +## Summary + +This run-book is a guideline for running on demand OCR tests against any blockchain. + +## Instructions + +### Pre-requisites + +> [!IMPORTANT] +> +> 1. Ensure [main Pre-requisites](../README.md#pre-requisites) are met. +> 2. Pay attention to the OCR version enabled in `overreride.toml`. +> 3. Use `-p 1` to disable tests parallelization and avoid nonce-related issues (or comment `t.Parallel()`). +> 4. For running tests in Kubernetes and CI, ensure test secrets are provided/uploaded to GitHub (ref. [CTF README#test-secrets](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md#test-secrets)). + +### Run Tests + +Below you may find instructions for running tests in different environments. + +#### COMMON COMMANDS + +Reuse the commands below to run different tests by their types/suites. + +##### Docker + +Any test suite/test can be run in Docker using the following `go` command (overrides are automatically injected): + +```bash +go test -v -timeout -p 1 <./path/to/_test.go file> +``` + +Example: + +```bash +go test -v -timeout 60m -p 1 ./smoke/ocr2_test.go +``` + +##### Kubernetes + +Run: + +```bash +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -timeout -p 1 -run '' ./ +``` + +Example: + +```bash +# Go +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -p 1 -run 'TestOCRChaos' ./chaos + +- - - - - - - - - - - - - - + +# Make +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) make test_soak_ocr +``` + +##### CI (with overrides) + +For the most tests run [Selected E2E Tests Workflow](https://github.com/smartcontractkit/chainlink/actions/workflows/run-selected-e2e-tests.yml) in GitHub, either manually or using `gh` command unless the otherwise stated: + +```bash +gh workflow run "run-selected-e2e-tests.yml" \ +--ref \ +-f chainlink_version="v" \ # Optional, default is image created from develop branch. Not needed if you run tests against existing environment +-f workflow_run_name="Any name" \ # Optional +-f test_ids="" \ # see /chainlink/.github/e2e-tests.yml for IDS +-f test_secrets_override_key= \ # Optional, can be obtained when secrets are uploaded to GitHub +-f test_config_override_path= \ # Optional +-f with_existing_remote_runner_version= \ # Optional +``` + +Example: + +```bash +gh workflow run "run-selected-e2e-tests.yml" \ +--ref develop \ +-f chainlink_version="v2.17.0-beta0" \ +-f test_ids="smoke/ocr2_test.go:*" \ +-f workflow_run_name="Smoke:OCR2:2.17.0-beta0" \ +-f test_secrets_override_key=YOUR_TEST_SECRETS_ID \ +-f test_config_override_path=./testconfig/ocr2/overrides/base_sepolia.toml +``` + +#### SMOKE + +##### Docker + +Refer [COMMON COMMANDS#Docker](#docker). Override `<./path/to/_test.go file>` as follows: + +- With forwarders: + `./smoke/forwarder_ocr_test.go` + `./smoke/forwarder_ocr2_test.go` + +- No forwarders: + `./smoke/ocr_test.go` + `./smoke/ocr2_test.go` + +##### CI + +Refer [COMMON COMMANDS#CI](#ci). Override `test_ids` as follows: + +`smoke/ocr_test.go:*` - all OCR1 tests +`smoke/ocr2_test.go:*` - all OCR2 tests + +#### SOAK + +> [!IMPORTANT] +> These tests require logging in to Kubernetes cluster (`aws sso login`). +> Do not use `-timeout` flag for Soak tests with Go command. It is set in `overrides.toml` + +Refer [Test config README](../testconfig/README.md) for more details about Soak tests configuration. + +##### Kubernetes + +Refer [COMMON COMMANDS#Kubernetes](#kubernetes). Override path as follows: + +- With forwarders: + `-run 'TestForwarderOCRv1Soak' ./soak` or `make test_soak_forwarder_ocr1` + `-run 'TestForwarderOCRv2Soak' ./soak` or `make test_soak_forwarder_ocr2` + +- No forwarders: + `-run 'TestOCRv1Soak' ./soak` or `make test_soak_ocr` + `-run 'TestOCRv2Soak' ./soak` or `make test_soak_ocr2` + +- With reorg below finality and `FinalityTagEnabled=false`: + `-run 'TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled' ./soak` or `make test_soak_ocr_reorg_1` + +- With reorg below finality and `FinalityTagEnabled=true`: + `-run 'TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled' ./soak` or `make test_soak_ocr_reorg_2` + +- With gas spike: + `-run 'TestOCRSoak_GasSpike' ./soak` or `make test_soak_ocr_gas_spike` + +- With change of a block gas limit (creating block congestion): + `-run 'TestOCRSoak_ChangeBlockGasLimit' ./soak` or `make test_soak_ocr_gas_limit_change` + +- All RPCs get down for all nodes: + `-run 'TestOCRSoak_RPCDownForAllCLNodes' ./soak` or `make test_soak_ocr_rpc_down_all_cl_nodes` + +- 50% of nodes get RPCs down: + `-run 'TestOCRSoak_RPCDownForHalfCLNodes' ./soak` or `make test_soak_ocr_rpc_down_half_cl_nodes` + +##### CI + +Use [On Demand OCR Soak Test](https://github.com/smartcontractkit/chainlink/actions/workflows/on-demand-ocr-soak-test.yml) workflow in GitHub. + +OR + +Run [On Demand OCR Soak Test](https://github.com/smartcontractkit/chainlink/actions/workflows/run-on-demand-ocr-soak-test.yml) workflow with `gh` as follows: + +```bash +gh workflow run "on-demand-ocr-soak-test.yml" \ +--ref \ +-f chainlink_version="v" \ # Optional, default is image created from develop branch. Not needed if you run tests against existing environment +-f testToRun="soak/ocr_test.go:" \ # see /chainlink/.github/workflows/on-demand-ocr-soak-test.yml for options +-f test_secrets_override_key= \ # Optional, can be obtained when secrets are uploaded to GitHub +-f test_config_override_path= \ # Optional +-f slackMemberID="YOUR_SLACK_MEMBER_ID" \ # Optional ("your profile -> three dots -> Copy Memeber ID") +``` + +Example: + +```bash +gh workflow run "on-demand-ocr-soak-test.yml" \ +--ref develop \ +-f chainlink_version="v2.17.0-beta0" \ +-f testToRun="soak/ocr_test.go:TestOCRv2Soak" \ +-f test_config_override_path="/integration-tests/testconfig/ocr2/overrides/base_sepolia.toml" \ +-f test_secrets_override_key=BASE_TESTSECRETS_YOUR_ID \ # RPC links in testsecret should correspond to the selected chain +-f slackMemberID="YOUR_SLACK_MEMBER_ID" +``` + +The following values may be used in the `testToRun` field (ref. [Soak#Kubernetes](#kubernetes) for more details): +`soak/ocr_test.go:TestOCRv1Soak` +`soak/ocr_test.go:TestOCRv2Soak` +`soak/ocr_test.go:TestForwarderOCRv1Soak` +`soak/ocr_test.go:TestForwarderOCRv2Soak` +`soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled` +`soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled` +`soak/ocr_test.go:TestOCRSoak_GasSpike` +`soak/ocr_test.go:TestOCRSoak_ChangeBlockGasLimit` +`soak/ocr_test.go:TestOCRSoak_RPCDownForAllCLNodes` +`soak/ocr_test.go:TestOCRSoak_RPCDownForHalfCLNodes` + +#### LOAD + +Ref: [Load Tests README](../load/ocr/README.md) + +#### CHAOS + +> [!IMPORTANT] +> 1. These tests require logging in to Kubernetes cluster (`aws sso login`). +> 2. There are only OCR1 chaos tests. + +##### Kubernetes + +Refer [COMMON COMMANDS#Kubernetes](#kubernetes). Override path as follows: + +`-run 'TestOCRChaos' ./chaos` + +OR + +`make test_ocr_chaos` + +##### CI + +Refer [COMMON COMMANDS#CI](#ci-with-overrides). Override `test_ids` as follows: + +`chaos/ocr_chaos_test.go` + +#### MIGRATION (core version upgrade) + +##### Docker + +1. Refer [Test configurations README](../testconfig/README.md#migration-tests) to provide necessary configuration. +2. Run tests: + + ```bash + # Go + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -p 1 ./smoke/_test.go + + - - - - - - - - - - - - + + # Make command + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) make test_node_migrations_verbose + ``` diff --git a/integration-tests/run-books/VRF.md b/integration-tests/run-books/VRF.md new file mode 100644 index 00000000000..ed0b7775e76 --- /dev/null +++ b/integration-tests/run-books/VRF.md @@ -0,0 +1,65 @@ +# VRF Tests Run Book +* All test configs should be placed in the [integration-tests/testconfig](../testconfig) folder +* All test configs for running tests in live testnets should be under [integration-tests/testconfig/vrfv2plus/overrides](../testconfig/vrfv2plus/overrides) folder + + +## Functional Tests +### In CI - using On Demand Workflows +```bash +gh workflow run "on-demand-vrfv2plus-smoke-tests.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path= \ +-f test_suite="Selected Tests" \ # Optional, Options - "All Tests", "Selected Tests". Default is "All Tests". If "Selected Tests" is selected, then `test_list_regex` should be provided +-f test_list_regex="" \ # Optional, default is "TestVRFv2Plus$/(Link_Billing|Native_Billing|Direct_Funding)|TestVRFV2PlusWithBHS" which are P0 tests +-f chainlink_version="<>" # Optional, default is image created from develop branch. Not needed if you run tests against existing environment +-f notify_user_id_on_failure= # Optional, default is empty. If provided, will notify the user on slack if the tests fail +``` + +#### Examples: +Run P0 tests against existing environment (Staging) on Arbitrum Sepolia +```bash +gh workflow run "on-demand-vrfv2plus-smoke-tests.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path=integration-tests/testconfig/vrfv2plus/overrides/staging/arbitrum_sepolia_staging_test_config.toml \ +-f test_suite="Selected Tests" +``` + +Run all tests deploying all contracts, CL nodes with `2.15.0` version on Base Sepolia +```bash +gh workflow run "on-demand-vrfv2plus-smoke-tests.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path=integration-tests/testconfig/vrfv2plus/overrides/new_env/base_sepolia_new_env_test_config.toml \ +-f test_suite="All Tests" \ +-f chainlink_version="2.15.0" +``` + +### Locally +```bash +cd integration-tests +TEST_LOG_LEVEL=debug \ +BASE64_CONFIG_OVERRIDE=$(cat | base64) \ +go test -v -timeout 15m -run "" ./smoke +``` + +## Performance Tests +```bash +gh workflow run "on-demand-vrfv2plus-performance-test.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path= \ +-f performanceTestType=“Smoke” # Options - "Smoke", "Soak", "Stress", "Load". +-f test_list_regex="" # Optional, default is "TestVRFV2PlusPerformance" +``` + +#### Examples: +Run SOAK tests against existing environment (Staging) on Base Sepolia +```bash +gh workflow run "on-demand-vrfv2plus-performance-test.yml" \ +--ref develop \ +-f=test_secrets_override_key= \ +-f test_config_override_path=integration-tests/testconfig/vrfv2plus/overrides/staging/base_sepolia_staging_test_config.toml \ +-f performanceTestType=“Soak” +``` diff --git a/integration-tests/runner_helpers.go b/integration-tests/runner_helpers.go index def2ebdc1d4..bd3ebfa3e30 100644 --- a/integration-tests/runner_helpers.go +++ b/integration-tests/runner_helpers.go @@ -17,7 +17,7 @@ import ( "github.com/manifoldco/promptui" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" ) func waitForWorkflowRun(branch, ghUser string) (string, error) { diff --git a/integration-tests/scripts/buildTests b/integration-tests/scripts/buildTests index b6033c1c415..7be2d0c5a7e 100755 --- a/integration-tests/scripts/buildTests +++ b/integration-tests/scripts/buildTests @@ -8,7 +8,7 @@ set -ex # get this scripts directory SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) -cd "$SCRIPT_DIR"/../ || exit 1 +cd "$SCRIPT_DIR"/../ || { echo "Error: Failed to change directory to $SCRIPT_DIR/../"; exit 1; } helm repo update @@ -23,10 +23,16 @@ for x in $tosplit do if [ "$x" = "load" ]; then echo "Changing directory and executing go test -c ./... for 'load' package" - pushd "./load" && go test -c -tags embed -o .. ./... + pushd "./load" && go test -c -tags embed -o ../ ./... + popd + elif [ "$x" = "ccip-load" ]; then + echo "Changing directory and executing go test -c ./... for 'ccip-load' package" + pushd "./ccip-tests/load" && go test -c -tags embed -o ../ ./... + mv ../load.test ../ccip-load.test # rename the binary to match the suite name popd else go test -c -tags embed ./"${x}" fi + echo "Built ${x}.test" done IFS=$OIFS diff --git a/integration-tests/scripts/entrypoint b/integration-tests/scripts/entrypoint index d4ebe722a1d..ca460eb8177 100755 --- a/integration-tests/scripts/entrypoint +++ b/integration-tests/scripts/entrypoint @@ -14,6 +14,15 @@ cd "$SCRIPT_DIR"/../ || exit 1 # SUITE=${SUITE:=} the suite of tests you want to run # TEST_NAME=${TEST_NAME:=} The specific test to run +if [ -z "${SUITE}" ]; then + echo "SUITE is not set. You likely need to set the TEST_SUITE env var in your workflow. Exiting." + exit 1 +fi + +# Helpful for debugging +pwd +ls -la + # run the tests ./${SUITE}.test -test.v -test.count 1 ${ARGS} -test.run ^${TEST_NAME}$ diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 39a9f754920..2e56237e9ca 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -20,12 +20,9 @@ import ( "github.com/onsi/gomega" "github.com/stretchr/testify/require" - ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -126,7 +123,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { isMercury := isMercuryV02 || isMercuryV03 a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(cfg), isMercuryV02, isMercuryV03, &cfg, + t, registryVersion, actions.ReadRegistryConfig(cfg), isMercuryV02, isMercuryV03, &cfg, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) @@ -145,6 +142,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { isMercury, isBillingTokenNative, a.WETHToken, + &cfg, ) // Do it in two separate loops, so we don't end up setting up one upkeep, but starting the consumer for another one @@ -265,26 +263,13 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(automationDefaultLinkFunds), - automationDefaultUpkeepGasLimit, - true, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, true, false, false, nil, &config) // Start log trigger based upkeeps for all consumers for i := 0; i < len(consumers); i++ { @@ -448,26 +433,13 @@ func TestAutomationAddFunds(t *testing.T) { config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(1), - automationDefaultUpkeepGasLimit, - false, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(1), automationDefaultUpkeepGasLimit, false, false, false, nil, &config) t.Cleanup(func() { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() @@ -528,26 +500,13 @@ func TestAutomationPauseUnPause(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(automationDefaultLinkFunds), - automationDefaultUpkeepGasLimit, - false, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false, false, nil, &config) t.Cleanup(func() { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() @@ -629,26 +588,13 @@ func TestAutomationRegisterUpkeep(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(automationDefaultLinkFunds), - automationDefaultUpkeepGasLimit, - false, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false, false, nil, &config) t.Cleanup(func() { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() @@ -725,26 +671,13 @@ func TestAutomationPauseRegistry(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(automationDefaultLinkFunds), - automationDefaultUpkeepGasLimit, - false, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false, false, nil, &config) t.Cleanup(func() { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() @@ -805,26 +738,13 @@ func TestAutomationKeeperNodesDown(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(automationDefaultLinkFunds), - automationDefaultUpkeepGasLimit, - false, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false, false, nil, &config) t.Cleanup(func() { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() @@ -913,7 +833,7 @@ func TestAutomationPerformSimulation(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) @@ -932,6 +852,7 @@ func TestAutomationPerformSimulation(t *testing.T) { 5, // Interval of blocks that upkeeps are expected to be performed 100000, // How much gas should be burned on checkUpkeep() calls 4000000, // How much gas should be burned on performUpkeep() calls. Initially set higher than defaultUpkeepGasLimit + &config, ) t.Cleanup(func() { @@ -984,7 +905,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) @@ -1003,6 +924,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { 5, // Interval of blocks that upkeeps are expected to be performed 100000, // How much gas should be burned on checkUpkeep() calls 4000000, // How much gas should be burned on performUpkeep() calls. Initially set higher than defaultUpkeepGasLimit + &config, ) t.Cleanup(func() { @@ -1091,7 +1013,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { } // Now increase checkGasLimit on registry - highCheckGasLimit := actions.AutomationDefaultRegistryConfig(config) + highCheckGasLimit := actions.ReadRegistryConfig(config) highCheckGasLimit.CheckGasLimit = uint32(5000000) highCheckGasLimit.RegistryVersion = registryVersion @@ -1139,7 +1061,7 @@ func TestUpdateCheckData(t *testing.T) { require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) @@ -1155,6 +1077,7 @@ func TestUpdateCheckData(t *testing.T) { big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, []byte(automationExpectedData), + &config, ) t.Cleanup(func() { @@ -1220,26 +1143,13 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { t.Fatal(err) } a := setupAutomationTestDocker( - t, registryVersion, actions.AutomationDefaultRegistryConfig(config), false, false, &config, + t, registryVersion, actions.ReadRegistryConfig(config), false, false, &config, ) sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions.DeployConsumers( - t, - a.ChainClient, - a.Registry, - a.Registrar, - a.LinkToken, - defaultAmountOfUpkeeps, - big.NewInt(automationDefaultLinkFunds), - automationDefaultUpkeepGasLimit, - false, - false, - false, - nil, - ) + consumers, upkeepIDs := actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false, false, nil, &config) t.Cleanup(func() { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() @@ -1438,7 +1348,7 @@ func setupAutomationTestDocker( _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) }) - a := automationv2.NewAutomationTestDocker(l, sethClient, nodeClients) + a := automationv2.NewAutomationTestDocker(l, sethClient, nodeClients, automationTestConfig) a.SetMercuryCredentialName("cred1") a.RegistrySettings = registryConfig a.RegistrarSettings = contracts.KeeperRegistrarSettings{ @@ -1446,47 +1356,23 @@ func setupAutomationTestDocker( AutoApproveMaxAllowed: 1000, MinLinkJuels: big.NewInt(0), } - plCfg := automationTestConfig.GetAutomationConfig().AutomationConfig.PluginConfig - a.PluginConfig = ocr2keepers30config.OffchainConfig{ - TargetProbability: *plCfg.TargetProbability, - TargetInRounds: *plCfg.TargetInRounds, - PerformLockoutWindow: *plCfg.PerformLockoutWindow, - GasLimitPerReport: *plCfg.GasLimitPerReport, - GasOverheadPerUpkeep: *plCfg.GasOverheadPerUpkeep, - MinConfirmations: *plCfg.MinConfirmations, - MaxUpkeepBatchSize: *plCfg.MaxUpkeepBatchSize, - } - pubCfg := automationTestConfig.GetAutomationConfig().AutomationConfig.PublicConfig - a.PublicConfig = ocr3.PublicConfig{ - DeltaProgress: *pubCfg.DeltaProgress, - DeltaResend: *pubCfg.DeltaResend, - DeltaInitial: *pubCfg.DeltaInitial, - DeltaRound: *pubCfg.DeltaRound, - DeltaGrace: *pubCfg.DeltaGrace, - DeltaCertifiedCommitRequest: *pubCfg.DeltaCertifiedCommitRequest, - DeltaStage: *pubCfg.DeltaStage, - RMax: *pubCfg.RMax, - MaxDurationQuery: *pubCfg.MaxDurationQuery, - MaxDurationObservation: *pubCfg.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: *pubCfg.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: *pubCfg.MaxDurationShouldTransmitAcceptedReport, - F: *pubCfg.F, - } + a.PluginConfig = actions.ReadPluginConfig(automationTestConfig) + a.PublicConfig = actions.ReadPublicConfig(automationTestConfig) a.SetupAutomationDeployment(t) a.SetDockerEnv(env) if isMercuryV02 || isMercuryV03 { - var imposters []ctfTestEnv.KillgraveImposter - mercuryv03Mock200 := ctfTestEnv.KillgraveImposter{ - Request: ctfTestEnv.KillgraveRequest{ + var imposters []ctftestenv.KillgraveImposter + mercuryv03Mock200 := ctftestenv.KillgraveImposter{ + Request: ctftestenv.KillgraveRequest{ Method: http.MethodGet, Endpoint: "/api/v1/reports/bulk", SchemaFile: nil, Params: &map[string]string{"feedIDs": "0x00028c915d6af0fd66bba2d0fc9405226bca8d6806333121a7d9832103d1563c", "timestamp": "{[\\d+]}"}, Headers: nil, }, - Response: ctfTestEnv.KillgraveResponse{ + Response: ctftestenv.KillgraveResponse{ Status: 200, Body: `{"reports":[{"feedID":"0x00028c915d6af0fd66bba2d0fc9405226bca8d6806333121a7d9832103d1563c","validFromTimestamp":0,"observationsTimestamp":0,"fullReport":"0x00066dfcd1ed2d95b18c948dbc5bd64c687afe93e4ca7d663ddec14c20090ad80000000000000000000000000000000000000000000000000000000000081401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001204554482d5553442d415242495452554d2d544553544e455400000000000000000000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000289ad8d367000000000000000000000000000000000000000000000000000000289acf0b38000000000000000000000000000000000000000000000000000000289b3da40000000000000000000000000000000000000000000000000000000000018ae7ce74d9fa252a8983976eab600dc7590c778d04813430841bc6e765c34cd81a168d00000000000000000000000000000000000000000000000000000000018ae7cb0000000000000000000000000000000000000000000000000000000064891c98000000000000000000000000000000000000000000000000000000000000000260412b94e525ca6cedc9f544fd86f77606d52fe731a5d069dbe836a8bfc0fb8c911963b0ae7a14971f3b4621bffb802ef0605392b9a6c89c7fab1df8633a5ade00000000000000000000000000000000000000000000000000000000000000024500c2f521f83fba5efc2bf3effaaedde43d0a4adff785c1213b712a3aed0d8157642a84324db0cf9695ebd27708d4608eb0337e0dd87b0e43f0fa70c700d911"}]}`, BodyFile: nil, @@ -1495,15 +1381,15 @@ func setupAutomationTestDocker( }, } - mercuryv02Mock200 := ctfTestEnv.KillgraveImposter{ - Request: ctfTestEnv.KillgraveRequest{ + mercuryv02Mock200 := ctftestenv.KillgraveImposter{ + Request: ctftestenv.KillgraveRequest{ Method: http.MethodGet, Endpoint: "/client", SchemaFile: nil, Params: &map[string]string{"feedIdHex": "{0x00028c915d6af0fd66bba2d0fc9405226bca8d6806333121a7d9832103d1563c|0x4554482d5553442d415242495452554d2d544553544e45540000000000000000}", "blockNumber": "{[\\d+]}"}, Headers: nil, }, - Response: ctfTestEnv.KillgraveResponse{ + Response: ctftestenv.KillgraveResponse{ Status: 200, Body: `{"chainlinkBlob":"0x0001c38d71fed6c320b90e84b6f559459814d068e2a1700adc931ca9717d4fe70000000000000000000000000000000000000000000000000000000001a80b52b4bf1233f9cb71144a253a1791b202113c4ab4a92fa1b176d684b4959666ff8200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004254432d5553442d415242495452554d2d544553544e4554000000000000000000000000000000000000000000000000000000000000000000000000645570be000000000000000000000000000000000000000000000000000002af2b818dc5000000000000000000000000000000000000000000000000000002af2426faf3000000000000000000000000000000000000000000000000000002af32dc209700000000000000000000000000000000000000000000000000000000012130f8df0a9745bb6ad5e2df605e158ba8ad8a33ef8a0acf9851f0f01668a3a3f2b68600000000000000000000000000000000000000000000000000000000012130f60000000000000000000000000000000000000000000000000000000000000002c4a7958dce105089cf5edb68dad7dcfe8618d7784eb397f97d5a5fade78c11a58275aebda478968e545f7e3657aba9dcbe8d44605e4c6fde3e24edd5e22c94270000000000000000000000000000000000000000000000000000000000000002459c12d33986018a8959566d145225f0c4a4e61a9a3f50361ccff397899314f0018162cf10cd89897635a0bb62a822355bd199d09f4abe76e4d05261bb44733d"}`, BodyFile: nil, diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go new file mode 100644 index 00000000000..d7842586050 --- /dev/null +++ b/integration-tests/smoke/ccip_test.go @@ -0,0 +1,109 @@ +package smoke + +import ( + "testing" + + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + ccdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/changeset" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestInitialDeployOnLocal(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv, _, _ := ccdeploy.NewLocalDevEnvironment(t, lggr) + e := tenv.Env + + state, err := ccdeploy.LoadOnchainState(tenv.Env, tenv.Ab) + require.NoError(t, err) + + feeds := state.Chains[tenv.FeedChainSel].USDFeeds + tokenConfig := ccdeploy.NewTokenConfig() + tokenConfig.UpsertTokenInfo(ccdeploy.LinkSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: feeds[ccdeploy.LinkSymbol].Address().String(), + Decimals: ccdeploy.LinkDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + // Apply migration + output, err := changeset.InitialDeployChangeSet(tenv.Ab, tenv.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: tokenConfig, + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + CapabilityRegistry: state.Chains[tenv.HomeChainSel].CapabilityRegistry.Address(), + FeeTokenContracts: tenv.FeeTokenContracts, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + // Get new state after migration. + state, err = ccdeploy.LoadOnchainState(e, tenv.Ab) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + // 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[uint64]uint64) + for src := range e.Chains { + for dest, destChain := range e.Chains { + if src == dest { + continue + } + latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + seqNum := ccdeploy.SendRequest(t, e, state, src, dest, false) + expectedSeqNum[dest] = seqNum + } + } + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + + // After commit is reported on all chains, token prices should be updated in FeeQuoter. + for dest := range e.Chains { + linkAddress := state.Chains[dest].LinkToken.Address() + feeQuoter := state.Chains[dest].FeeQuoter + timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) + require.NoError(t, err) + require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) + } + + // Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + + // TODO: Apply the proposal. +} diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 98c1fe0caf7..51db7215186 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -9,7 +9,7 @@ import ( "github.com/onsi/gomega" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index d66cdbd2849..259752a5342 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -14,8 +14,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 1eff96cb7a2..5e5fb1d40b6 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -11,8 +11,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -60,8 +60,8 @@ func TestForwarderOCRBasic(t *testing.T) { _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) }) - lt, err := contracts.DeployLinkTokenContract(l, sethClient) - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") + linkContract, err := actions.LinkTokenContract(l, sethClient, config.OCR) + require.NoError(t, err, "Error loading/deploying link token contract") fundingAmount := big.NewFloat(.05) l.Info().Str("ETH amount per node", fundingAmount.String()).Msg("Funding Chainlink nodes") @@ -69,7 +69,7 @@ func TestForwarderOCRBasic(t *testing.T) { require.NoError(t, err, "Error funding Chainlink nodes") operators, authorizedForwarders, _ := actions.DeployForwarderContracts( - t, sethClient, common.HexToAddress(lt.Address()), len(workerNodes), + t, sethClient, common.HexToAddress(linkContract.Address()), len(workerNodes), ) require.Equal(t, len(workerNodes), len(operators), "Number of operators should match number of worker nodes") @@ -81,11 +81,12 @@ func TestForwarderOCRBasic(t *testing.T) { require.NoError(t, err, "Accepting Authorize Receivers on Operator shouldn't fail") actions.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) } + ocrInstances, err := actions.DeployOCRContractsForwarderFlow( l, sethClient, - 1, - common.HexToAddress(lt.Address()), + config.OCR, + common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), authorizedForwarders, ) diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index e3cced94fd7..0cc7d9fafe4 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -12,8 +12,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -61,8 +61,8 @@ func TestForwarderOCR2Basic(t *testing.T) { _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) }) - lt, err := contracts.DeployLinkTokenContract(l, sethClient) - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") + linkContract, err := actions.LinkTokenContract(l, sethClient, config.OCR2) + require.NoError(t, err, "Error loading/deploying link token contract") fundingAmount := big.NewFloat(.05) l.Info().Str("ETH amount per node", fundingAmount.String()).Msg("Funding Chainlink nodes") @@ -70,7 +70,7 @@ func TestForwarderOCR2Basic(t *testing.T) { require.NoError(t, err, "Error funding Chainlink nodes") operators, authorizedForwarders, _ := actions.DeployForwarderContracts( - t, sethClient, common.HexToAddress(lt.Address()), len(workerNodes), + t, sethClient, common.HexToAddress(linkContract.Address()), len(workerNodes), ) require.Equal(t, len(workerNodes), len(operators), "Number of operators should match number of worker nodes") @@ -90,7 +90,7 @@ func TestForwarderOCR2Basic(t *testing.T) { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - ocrInstances, err := actions.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(lt.Address()), transmitters, ocrOffchainOptions) + ocrInstances, err := actions.SetupOCRv2Contracts(l, sethClient, config.OCR2, common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions) require.NoError(t, err, "Error deploying OCRv2 contracts with forwarders") ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) diff --git a/integration-tests/smoke/job_distributor_test.go b/integration-tests/smoke/job_distributor_test.go new file mode 100644 index 00000000000..2d1657faf7e --- /dev/null +++ b/integration-tests/smoke/job_distributor_test.go @@ -0,0 +1,60 @@ +package smoke + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + + "github.com/smartcontractkit/chainlink/integration-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + graphqlClient "github.com/smartcontractkit/chainlink/integration-tests/web/sdk/client" +) + +func TestRegisteringMultipleJobDistributor(t *testing.T) { + t.Parallel() + + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig([]string{"Smoke"}, "job_distributor") + require.NoError(t, err, "Error getting config") + + privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) + require.NoError(t, err, "Error building ethereum network config") + + env, err := test_env.NewCLTestEnvBuilder(). + WithTestConfig(&config). + WithTestInstance(t). + WithStandardCleanup(). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). + WithCLNodes(1). + WithStandardCleanup(). + Build() + require.NoError(t, err) + + ctx := context.Background() + _, err = env.ClCluster.Nodes[0].GraphqlAPI.CreateJobDistributor(ctx, graphqlClient.JobDistributorInput{ + Name: "job-distributor-1", + Uri: "http://job-distributor-1:8080", + PublicKey: "54227538d9352e0a24550a80ab6a7af6e4f1ffbb8a604e913cbb81c484a7f97d", + }) + require.NoError(t, err, "Creating first job distributor in chainlink node shouldn't fail") + + _, err = env.ClCluster.Nodes[0].GraphqlAPI.CreateJobDistributor(ctx, graphqlClient.JobDistributorInput{ + Name: "job-distributor-2", + Uri: "http://job-distributor-2:8080", + PublicKey: "37346b7ea98af21e1309847e00f772826ac3689fe990b1920d01efc58ad2f250", + }) + require.NoError(t, err, "Creating second job distributor in chainlink node shouldn't fail") + + distributors, err := env.ClCluster.Nodes[0].GraphqlAPI.ListJobDistributors(ctx) + require.NoError(t, err, "Listing job distributors in chainlink node shouldn't fail") + require.Len(t, distributors.FeedsManagers.Results, 2, "There should be 2 job distributors") + + assert.Equal(t, "job-distributor-1", distributors.FeedsManagers.Results[0].Name) + assert.Equal(t, "job-distributor-2", distributors.FeedsManagers.Results[1].Name) +} diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index b6118025a19..d9875b8db7f 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -13,11 +13,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/onsi/gomega" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index f1a257552a2..b5891e7a3e8 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/onsi/gomega" @@ -15,9 +15,9 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -306,20 +306,7 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfi logScannerSettings, ) - _, upkeepIDs := actions.DeployConsumers( - t, - chainClient, - registry, - registrar, - linkToken, - upKeepsNeeded, - big.NewInt(int64(9e18)), - uint32(2500000), - true, - false, - false, - nil, - ) + _, upkeepIDs := actions.DeployLegacyConsumers(t, chainClient, registry, registrar, linkToken, upKeepsNeeded, big.NewInt(int64(9e18)), uint32(2500000), true, false, false, nil) err = logpoller.AssertUpkeepIdsUniqueness(upkeepIDs) require.NoError(t, err, "Error asserting upkeep ids uniqueness") diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 90afff94cf3..325c88f979a 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -12,12 +12,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/config/env" @@ -102,11 +103,11 @@ func TestOCRv2JobReplacement(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - env, aggregatorContracts, sethClient := prepareORCv2SmokeTestEnv(t, defaultTestData(), l, 5) - nodeClients := env.ClCluster.NodeAPIs() + testEnv, aggregatorContracts, sethClient := prepareORCv2SmokeTestEnv(t, defaultTestData(), l, 5) + nodeClients := testEnv.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] - err := env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) + err := testEnv.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") @@ -124,7 +125,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.DeleteBridges(nodeClients) require.NoError(t, err) - err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) require.NoError(t, err, "Error creating OCRv2 jobs") err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) @@ -169,8 +170,8 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, nodeClients := testEnv.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] - linkContract, err := contracts.DeployLinkTokenContract(l, sethClient) - require.NoError(t, err, "Error deploying link token contract") + linkContract, err := actions.LinkTokenContract(l, sethClient, config.OCR2) + require.NoError(t, err, "Error loading/deploying link token contract") err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Error funding Chainlink nodes") @@ -190,18 +191,20 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, transmitters = append(transmitters, addr) } - ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - aggregatorContracts, err := actions.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions) + ocrOffChainOptions := contracts.DefaultOffChainAggregatorOptions() + aggregatorContracts, err := actions.SetupOCRv2Contracts(l, sethClient, config.OCR2, common.HexToAddress(linkContract.Address()), transmitters, ocrOffChainOptions) require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) require.NoError(t, err, "Error creating OCRv2 jobs") - ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) - require.NoError(t, err, "Error building OCRv2 config") + if !config.OCR2.UseExistingOffChainAggregatorsContracts() || (config.OCR2.UseExistingOffChainAggregatorsContracts() && config.OCR2.ConfigureExistingOffChainAggregatorsContracts()) { + ocrV2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffChainOptions) + require.NoError(t, err, "Error building OCRv2 config") - err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, aggregatorContracts) - require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") + err = actions.ConfigureOCRv2AggregatorContracts(ocrV2Config, aggregatorContracts) + require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") + } assertCorrectNodeConfiguration(t, l, clNodeCount, testData, testEnv) diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 8d17a020714..e3172e23b8c 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -7,11 +7,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -104,20 +105,21 @@ func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] - err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) - require.NoError(t, err, "Error funding Chainlink nodes") - t.Cleanup(func() { // ignore error, we will see failures in the logs anyway _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) }) - linkContract, err := contracts.DeployLinkTokenContract(l, sethClient) - require.NoError(t, err, "Error deploying link token contract") + linkContract, err := actions.LinkTokenContract(l, sethClient, config.OCR) + require.NoError(t, err, "Error loading/deploying LinkToken contract") - ocrInstances, err := actions.DeployOCRv1Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.SetupOCRv1Contracts(l, sethClient, config.OCR, common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes)) require.NoError(t, err, "Error deploying OCR contracts") + // there is no need to fund the nodes unless the OCR contract and job are configured + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Error funding Chainlink nodes") + err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, big.NewInt(sethClient.ChainID)) require.NoError(t, err, "Error creating OCR jobs") diff --git a/integration-tests/smoke/reorg_above_finality_test.go b/integration-tests/smoke/reorg_above_finality_test.go index e7b9e4a2183..ea7757a9e75 100644 --- a/integration-tests/smoke/reorg_above_finality_test.go +++ b/integration-tests/smoke/reorg_above_finality_test.go @@ -4,12 +4,12 @@ import ( "testing" "time" - ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -53,7 +53,7 @@ func TestReorgAboveFinality_FinalityTagDisabled(t *testing.T) { evmNetwork, err := testEnv.GetFirstEvmNetwork() require.NoError(t, err, "Error getting first evm network") - client := ctf_client.NewRPCClient(evmNetwork.HTTPURLs[0]) + client := ctf_client.NewRPCClient(evmNetwork.HTTPURLs[0], nil) // Wait for chain to progress require.Eventually(t, func() bool { diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 1558b447327..d081619fe69 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -13,8 +13,8 @@ import ( "github.com/onsi/gomega" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 53e74ac7ff1..822276222a2 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -6,16 +6,14 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink/integration-tests/utils" - "github.com/google/uuid" "github.com/onsi/gomega" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv1" @@ -24,6 +22,7 @@ import ( ethcontracts "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + "github.com/smartcontractkit/chainlink/integration-tests/utils" ) func TestVRFBasic(t *testing.T) { diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 48fbc0071c5..8390c27a4b0 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" @@ -20,12 +20,12 @@ import ( "go.uber.org/zap/zapcore" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" @@ -40,6 +40,53 @@ const ( SethRootKeyIndex = 0 ) +// vrfv2CleanUpFn is a cleanup function that captures pointers from context, in which it's called and uses them to clean up the test environment +var vrfv2CleanUpFn = func( + t **testing.T, + sethClient **seth.Client, + config **tc.TestConfig, + testEnv **test_env.CLClusterTestEnv, + vrfContracts **vrfcommon.VRFContracts, + subIDsForCancellingAfterTest *[]uint64, + walletAddress **string, +) func() { + return func() { + logger := logging.GetTestLogger(*t) + testConfig := **config + network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] + if network.Simulated { + logger.Info(). + Str("Network Name", network.Name). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfContracts != nil && *sethClient != nil { + if *testConfig.VRFv2.General.CancelSubsAfterTestRun { + client := *sethClient + var returnToAddress string + if walletAddress == nil || *walletAddress == nil { + returnToAddress = client.MustGetRootKeyAddress().Hex() + } else { + returnToAddress = **walletAddress + } + //cancel subs and return funds to sub owner + vrfv2.CancelSubsAndReturnFunds(testcontext.Get(*t), *vrfContracts, returnToAddress, *subIDsForCancellingAfterTest, logger) + } + } else { + logger.Error().Msg("VRF Contracts and/or Seth client are nil. Cannot execute cleanup") + } + } + if !*testConfig.VRFv2.General.UseExistingEnv { + if *testEnv == nil { + logger.Error().Msg("Test environment is nil. Cannot execute cleanup") + return + } + if err := (*testEnv).Cleanup(test_env.CleanupOpts{TestName: (*t).Name()}); err != nil { + logger.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } +} + func TestVRFv2Basic(t *testing.T) { t.Parallel() var ( @@ -54,30 +101,13 @@ func TestVRFv2Basic(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") - vrfv2Config := config.VRFv2 chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2Config.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2CleanUpFn(&t, &sethClient, &configPtr, &testEnv, &vrfContracts, &subIDsForCancellingAfterTest, nil), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -574,29 +604,12 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { t.Fatal(err) } chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID - vrfv2Config := config.VRFv2 - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2Config.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2CleanUpFn(&t, &sethClient, &configPtr, &testEnv, &vrfContracts, &subIDsForCancellingAfterTest, nil), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -680,29 +693,12 @@ func TestVRFOwner(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID - vrfv2Config := config.VRFv2 - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2Config.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2CleanUpFn(&t, &sethClient, &configPtr, &testEnv, &vrfContracts, &subIDsForCancellingAfterTest, nil), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -817,24 +813,7 @@ func TestVRFV2WithBHS(t *testing.T) { require.NoError(t, err, "Error getting config") vrfv2Config := config.VRFv2 chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID - - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2Config.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config //decrease default span for checking blockhashes for unfulfilled requests vrfv2Config.General.BHSJobWaitBlocks = ptr.Ptr(2) @@ -842,7 +821,7 @@ func TestVRFV2WithBHS(t *testing.T) { vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2CleanUpFn(&t, &sethClient, &configPtr, &testEnv, &vrfContracts, &subIDsForCancellingAfterTest, nil), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF, vrfcommon.BHS}, @@ -860,7 +839,6 @@ func TestVRFV2WithBHS(t *testing.T) { } //BHS node should fill in blockhashes into BHS contract depending on the waitBlocks and lookBackBlocks settings configCopy := config.MustCopy().(tc.TestConfig) - //Underfund Subscription configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForBHS, err := vrfv2.SetupNewConsumersAndSubs( @@ -964,9 +942,7 @@ func TestVRFV2WithBHS(t *testing.T) { SethRootKeyIndex, ) require.NoError(t, err, "error requesting randomness") - randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") @@ -987,29 +963,37 @@ func TestVRFV2WithBHS(t *testing.T) { metrics, err := consumers[0].GetLoadTestMetrics(testcontext.Get(t)) require.Equal(t, 0, metrics.RequestCount.Cmp(big.NewInt(1))) require.Equal(t, 0, metrics.FulfilmentCount.Cmp(big.NewInt(0))) - - var clNodeTxs *client.TransactionsData - var txHash string gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - clNodeTxs, _, err = nodeTypeToNodeMap[vrfcommon.BHS].CLNode.API.ReadTransactions() - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting CL Node transactions") - l.Info().Int("Number of TXs", len(clNodeTxs.Data)).Msg("BHS Node txs") - g.Expect(len(clNodeTxs.Data)).Should(gomega.BeNumerically("==", 1), "Expected 1 tx posted by BHS Node, but found %d", len(clNodeTxs.Data)) - txHash = clNodeTxs.Data[0].Attributes.Hash - }, "2m", "1s").Should(gomega.Succeed()) - - require.Equal(t, strings.ToLower(vrfContracts.BHS.Address()), strings.ToLower(clNodeTxs.Data[0].Attributes.To)) - - bhsStoreTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), common.HexToHash(txHash)) - require.NoError(t, err, "error getting tx from hash") - bhsStoreTxInputData, err := actions.DecodeTxInputData(blockhash_store.BlockhashStoreABI, bhsStoreTx.Data()) - l.Info(). - Str("Block Number", bhsStoreTxInputData["n"].(*big.Int).String()). - Msg("BHS Node's Store Blockhash for Blocknumber Method TX") - require.Equal(t, randRequestBlockNumber, bhsStoreTxInputData["n"].(*big.Int).Uint64()) + if !*configCopy.VRFv2.General.UseExistingEnv { + l.Info().Msg("Checking BHS Node's transactions") + var clNodeTxs *client.TransactionsData + var txHash string + gom.Eventually(func(g gomega.Gomega) { + clNodeTxs, _, err = nodeTypeToNodeMap[vrfcommon.BHS].CLNode.API.ReadTransactions() + g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting CL Node transactions") + g.Expect(len(clNodeTxs.Data)).Should(gomega.BeNumerically("==", 1), "Expected 1 tx posted by BHS Node, but found %d", len(clNodeTxs.Data)) + txHash = clNodeTxs.Data[0].Attributes.Hash + l.Info(). + Str("TX Hash", txHash). + Int("Number of TXs", len(clNodeTxs.Data)). + Msg("BHS Node txs") + }, "2m", "1s").Should(gomega.Succeed()) + + require.Equal(t, strings.ToLower(vrfContracts.BHS.Address()), strings.ToLower(clNodeTxs.Data[0].Attributes.To)) + + bhsStoreTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), common.HexToHash(txHash)) + require.NoError(t, err, "error getting tx from hash") + bhsStoreTxInputData, err := actions.DecodeTxInputData(blockhash_store.BlockhashStoreABI, bhsStoreTx.Data()) + require.NoError(t, err, "error decoding tx input data") + l.Info(). + Str("Block Number", bhsStoreTxInputData["n"].(*big.Int).String()). + Msg("BHS Node's Store Blockhash for Blocknumber Method TX") + require.Equal(t, randRequestBlockNumber, bhsStoreTxInputData["n"].(*big.Int).Uint64()) + } else { + l.Warn().Msg("Skipping BHS Node's transactions check as existing env is used") + } var randRequestBlockHash [32]byte gom.Eventually(func(g gomega.Gomega) { randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) @@ -1029,7 +1013,6 @@ func TestVRFV2NodeReorg(t *testing.T) { env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 - defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData sethClient *seth.Client ) @@ -1037,30 +1020,13 @@ func TestVRFV2NodeReorg(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") - vrfv2Config := config.VRFv2 network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] if !network.Simulated { t.Skip("Skipped since Reorg test could only be run on Simulated chain.") } chainID := network.ChainID - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2Config.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2Config.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config chainlinkNodeLogScannerSettings := test_env.GetDefaultChainlinkNodeLogScannerSettingsWithExtraAllowedMessages( testreporters.NewAllowedLogMessage( "Got very old block.", @@ -1076,7 +1042,7 @@ func TestVRFV2NodeReorg(t *testing.T) { vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2CleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest, nil), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -1208,7 +1174,6 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 - defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode sethClient *seth.Client @@ -1217,30 +1182,14 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") - vrfv2Config := config.VRFv2 network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] chainID := network.ChainID - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2Config.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2Config.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + + configPtr := &config vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2CleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest, nil), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -1494,5 +1443,4 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { // verify that all fulfillments should be in separate txs require.Equal(t, int(randRequestCount), len(singleFulfillmentTxs)) }) - } diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index a1ac5fd5544..72c83aa281e 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" @@ -18,12 +18,12 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" @@ -37,6 +37,47 @@ import ( it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" ) +// vrfv2PlusCleanUpFn is a cleanup function that captures pointers from context, in which it's called and uses them to clean up the test environment +var vrfv2PlusCleanUpFn = func( + t **testing.T, + sethClient **seth.Client, + config **tc.TestConfig, + testEnv **test_env.CLClusterTestEnv, + vrfContracts **vrfcommon.VRFContracts, + subIDsForCancellingAfterTest *[]*big.Int, +) func() { + return func() { + l := logging.GetTestLogger(*t) + testConfig := **config + network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] + if network.Simulated { + l.Info(). + Str("Network Name", network.Name). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfContracts != nil && *sethClient != nil { + if *testConfig.VRFv2Plus.General.CancelSubsAfterTestRun { + client := *sethClient + returnToAddress := client.MustGetRootKeyAddress().Hex() + //cancel subs and return funds to sub owner + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(*t), *vrfContracts, returnToAddress, *subIDsForCancellingAfterTest, l) + } + } else { + l.Error().Msg("VRF Contracts and/or Seth client are nil. Cannot execute cleanup") + } + } + if !*testConfig.VRFv2Plus.General.UseExistingEnv { + if *testEnv == nil { + l.Error().Msg("Test environment is nil. Cannot execute cleanup") + return + } + if err := (*testEnv).Cleanup(test_env.CleanupOpts{TestName: (*t).Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } +} + func TestVRFv2Plus(t *testing.T) { t.Parallel() var ( @@ -52,30 +93,13 @@ func TestVRFv2Plus(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + configPtr := &config - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -127,12 +151,6 @@ func TestVRFv2Plus(t *testing.T) { require.Equal(t, isNativeBilling, randomWordsFulfilledEvent.NativePayment, "RandomWordsFulfilled Event's `NativePayment` field should be false") require.True(t, randomWordsFulfilledEvent.Success, "RandomWordsFulfilled Event's `Success` field should be true") - expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, randomWordsFulfilledEvent.Payment) - subscription, err = vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subIDForRequestRandomness) - require.NoError(t, err, "error getting subscription information") - subBalanceAfterRequest := subscription.Balance - require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest) - status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) @@ -143,6 +161,19 @@ func TestVRFv2Plus(t *testing.T) { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } + t.Run("Verify Billing", func(t *testing.T) { + actualSubPaymentJuels := randomWordsFulfilledEvent.Payment + + expectedSubBalanceJuels := new(big.Int).Sub(subBalanceBeforeRequest, actualSubPaymentJuels) + subscription, err = vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subIDForRequestRandomness) + require.NoError(t, err, "error getting subscription information") + subBalanceAfterRequest := subscription.Balance + require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest) + + //todo - need to refactor the test so that when running on live testnet and deploying a new environment, + // we would load real Link Token and Link/ETH feed addresses from the config + }) + }) t.Run("Native Billing", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) @@ -183,12 +214,6 @@ func TestVRFv2Plus(t *testing.T) { require.False(t, randomWordsFulfilledEvent.OnlyPremium) require.Equal(t, isNativeBilling, randomWordsFulfilledEvent.NativePayment) require.True(t, randomWordsFulfilledEvent.Success) - expectedSubBalanceWei := new(big.Int).Sub(subNativeTokenBalanceBeforeRequest, randomWordsFulfilledEvent.Payment) - subscription, err = vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) - require.NoError(t, err) - subBalanceAfterRequest := subscription.NativeBalance - require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest) - status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) @@ -199,92 +224,51 @@ func TestVRFv2Plus(t *testing.T) { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } - }) - t.Run("VRF Node waits block confirmation number specified by the consumer before sending fulfilment on-chain", func(t *testing.T) { - configCopy := config.MustCopy().(tc.TestConfig) - testConfig := configCopy.VRFv2Plus.General - var isNativeBilling = true - - consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( - testcontext.Get(t), - sethClient, - vrfContracts.CoordinatorV2Plus, - configCopy, - vrfContracts.LinkToken, - 1, - 1, - l, - ) - require.NoError(t, err, "error setting up new consumers and subs") - subID := subIDs[0] - subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) - require.NoError(t, err, "error getting subscription information") - vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) - subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - - expectedBlockNumberWait := uint16(10) - testConfig.MinimumConfirmations = ptr.Ptr[uint16](expectedBlockNumberWait) - randomWordsRequestedEvent, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( - consumers[0], - vrfContracts.CoordinatorV2Plus, - vrfKey, - subID, - isNativeBilling, - testConfig, - l, - 0, - ) - require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - - // check that VRF node waited at least the number of blocks specified by the consumer in the rand request min confs field - blockNumberWait := randomWordsRequestedEvent.Raw.BlockNumber - randomWordsFulfilledEvent.Raw.BlockNumber - require.GreaterOrEqual(t, blockNumberWait, uint64(expectedBlockNumberWait)) - - status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) - require.NoError(t, err, "error getting rand request status") - require.True(t, status.Fulfilled) - l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - }) - t.Run("CL Node VRF Job Runs", func(t *testing.T) { - configCopy := config.MustCopy().(tc.TestConfig) - var isNativeBilling = false - - consumers, subIDsForRequestRandomness, err := vrfv2plus.SetupNewConsumersAndSubs( - testcontext.Get(t), - sethClient, - vrfContracts.CoordinatorV2Plus, - configCopy, - vrfContracts.LinkToken, - 1, - 1, - l, - ) - require.NoError(t, err, "error setting up new consumers and subs") - subIDForRequestRandomness := subIDsForRequestRandomness[0] - subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subIDForRequestRandomness) - require.NoError(t, err, "error getting subscription information") - vrfcommon.LogSubDetails(l, subscription, subIDForRequestRandomness.String(), vrfContracts.CoordinatorV2Plus) - subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForRequestRandomness...) - - jobRunsBeforeTest, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.MustReadRunsByJob(nodeTypeToNodeMap[vrfcommon.VRF].Job.Data.ID) - require.NoError(t, err, "error reading job runs") - - // test and assert - _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( - consumers[0], - vrfContracts.CoordinatorV2Plus, - vrfKey, - subIDForRequestRandomness, - isNativeBilling, - configCopy.VRFv2Plus.General, - l, - 0, - ) - require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + t.Run("Verify Billing", func(t *testing.T) { + actualSubPaymentWei := randomWordsFulfilledEvent.Payment + expectedSubBalanceWei := new(big.Int).Sub(subNativeTokenBalanceBeforeRequest, actualSubPaymentWei) + subscription, err = vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err) + subBalanceAfterRequest := subscription.NativeBalance + require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest) - jobRuns, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.MustReadRunsByJob(nodeTypeToNodeMap[vrfcommon.VRF].Job.Data.ID) - require.NoError(t, err, "error reading job runs") - require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data)) + // verify that the actual sub payment is within the expected range - this cannot be checked on SIMULATED env + coordinatorConfig, err := vrfContracts.CoordinatorV2Plus.GetConfig(testcontext.Get(t)) + require.NoError(t, err, "error getting coordinator config") + //check that Coordinator config is correct + require.Equal(t, *configCopy.VRFv2Plus.General.FulfillmentFlatFeeNativePPM, coordinatorConfig.FulfillmentFlatFeeNativePPM) + require.Equal(t, *configCopy.VRFv2Plus.General.NativePremiumPercentage, coordinatorConfig.NativePremiumPercentage) + require.Equal(t, *configCopy.VRFv2Plus.General.GasAfterPaymentCalculation, coordinatorConfig.GasAfterPaymentCalculation) + // check that the actual sub payment is within the expected range and is according to the coordinator config's billing settings + fulfillmentTxHash := randomWordsFulfilledEvent.Raw.TxHash + fulfillmentTxReceipt, err := sethClient.Client.TransactionReceipt(testcontext.Get(t), fulfillmentTxHash) + require.NoError(t, err, "error getting fulfilment tx receipt") + + txGasUsed := new(big.Int).SetUint64(fulfillmentTxReceipt.GasUsed) + // we don't have that information for older Geth versions + if fulfillmentTxReceipt.EffectiveGasPrice == nil { + fulfillmentTxReceipt.EffectiveGasPrice = new(big.Int).SetUint64(0) + } + fulfillmentTxFeeWei := new(big.Int).Mul(txGasUsed, fulfillmentTxReceipt.EffectiveGasPrice) + + premiumFeeInDecimal := new(big.Float).Quo(big.NewFloat(float64(*configCopy.VRFv2Plus.General.CoordinatorNativePremiumPercentage)), big.NewFloat(100)) + premiumFeeRatio := new(big.Float).Add(premiumFeeInDecimal, big.NewFloat(1)) + // since - tx fee * (premium fee in decimal + 1) = expected sub payment + fulfillmentTxFeeWeiFloat64, _ := fulfillmentTxFeeWei.Float64() + expectedSubPaymentWeiWithoutFlatFee := new(big.Float).Mul(big.NewFloat(fulfillmentTxFeeWeiFloat64), premiumFeeRatio) + flatFee := new(big.Float).Mul(big.NewFloat(float64(*configCopy.VRFv2Plus.General.FulfillmentFlatFeeNativePPM)), big.NewFloat(1e12)) + expectedSubPaymentWeiWitFlatFee := new(big.Float).Add(expectedSubPaymentWeiWithoutFlatFee, flatFee) + vrfv2plus.LogPaymentDetails(l, fulfillmentTxFeeWei, fulfillmentTxReceipt, actualSubPaymentWei, expectedSubPaymentWeiWitFlatFee, configCopy) + actualSubPaymentWeiFloat, _ := actualSubPaymentWei.Float64() + expectedSubPaymentWeiFloat, _ := expectedSubPaymentWeiWitFlatFee.Float64() + + //verify that the actual sub payment is more than TX fee + require.Equal(t, 1, actualSubPaymentWei.Cmp(fulfillmentTxFeeWei), "the actual sub payment has to be more than the TX fee") + + tolerance := *testConfig.SubBillingTolerance + isWithinTolerance, diff := actions.WithinTolerance(actualSubPaymentWeiFloat, expectedSubPaymentWeiFloat, tolerance) + require.True(t, isWithinTolerance, fmt.Sprintf("Expected the actual sub payment to be within %f tolerance of the expected sub payment. Diff: %f", tolerance, diff)) + }) }) t.Run("Direct Funding", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) @@ -399,6 +383,92 @@ func TestVRFv2Plus(t *testing.T) { } }) }) + t.Run("VRF Node waits block confirmation number specified by the consumer before sending fulfilment on-chain", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General + var isNativeBilling = true + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + testcontext.Get(t), + sethClient, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + expectedBlockNumberWait := uint16(10) + testConfig.MinimumConfirmations = ptr.Ptr[uint16](expectedBlockNumberWait) + randomWordsRequestedEvent, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + testConfig, + l, + 0, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + // check that VRF node waited at least the number of blocks specified by the consumer in the rand request min confs field + blockNumberWait := randomWordsRequestedEvent.Raw.BlockNumber - randomWordsFulfilledEvent.Raw.BlockNumber + require.GreaterOrEqual(t, blockNumberWait, uint64(expectedBlockNumberWait)) + + status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) + require.NoError(t, err, "error getting rand request status") + require.True(t, status.Fulfilled) + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + }) + t.Run("CL Node VRF Job Runs", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + var isNativeBilling = false + + consumers, subIDsForRequestRandomness, err := vrfv2plus.SetupNewConsumersAndSubs( + testcontext.Get(t), + sethClient, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subIDForRequestRandomness := subIDsForRequestRandomness[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subIDForRequestRandomness) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subIDForRequestRandomness.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForRequestRandomness...) + + jobRunsBeforeTest, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.MustReadRunsByJob(nodeTypeToNodeMap[vrfcommon.VRF].Job.Data.ID) + require.NoError(t, err, "error reading job runs") + + // test and assert + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subIDForRequestRandomness, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + 0, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + jobRuns, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.MustReadRunsByJob(nodeTypeToNodeMap[vrfcommon.VRF].Job.Data.ID) + require.NoError(t, err, "error reading job runs") + require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data)) + }) t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) @@ -747,30 +817,13 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + configPtr := &config - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -852,30 +905,13 @@ func TestVRFv2PlusMigration(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + configPtr := &config - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -1246,24 +1282,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID - - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config //decrease default span for checking blockhashes for unfulfilled requests vrfv2PlusConfig.General.BHSJobWaitBlocks = ptr.Ptr(2) @@ -1271,7 +1290,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF, vrfcommon.BHS}, @@ -1444,28 +1463,37 @@ func TestVRFV2PlusWithBHS(t *testing.T) { metrics, err := consumers[0].GetLoadTestMetrics(testcontext.Get(t)) require.Equal(t, 0, metrics.RequestCount.Cmp(big.NewInt(1))) require.Equal(t, 0, metrics.FulfilmentCount.Cmp(big.NewInt(0))) - - var clNodeTxs *client.TransactionsData - var txHash string gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - clNodeTxs, _, err = nodeTypeToNodeMap[vrfcommon.BHS].CLNode.API.ReadTransactions() - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting CL Node transactions") - l.Info().Int("Number of TXs", len(clNodeTxs.Data)).Msg("BHS Node txs") - g.Expect(len(clNodeTxs.Data)).Should(gomega.BeNumerically("==", 1), "Expected 1 tx posted by BHS Node, but found %d", len(clNodeTxs.Data)) - txHash = clNodeTxs.Data[0].Attributes.Hash - }, "2m", "1s").Should(gomega.Succeed()) - require.Equal(t, strings.ToLower(vrfContracts.BHS.Address()), strings.ToLower(clNodeTxs.Data[0].Attributes.To)) - - bhsStoreTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), common.HexToHash(txHash)) - require.NoError(t, err, "error getting tx from hash") + if !*configCopy.VRFv2Plus.General.UseExistingEnv { + l.Info().Msg("Checking BHS Node's transactions") + var clNodeTxs *client.TransactionsData + var txHash string + gom.Eventually(func(g gomega.Gomega) { + clNodeTxs, _, err = nodeTypeToNodeMap[vrfcommon.BHS].CLNode.API.ReadTransactions() + g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting CL Node transactions") + g.Expect(len(clNodeTxs.Data)).Should(gomega.BeNumerically("==", 1), "Expected 1 tx posted by BHS Node, but found %d", len(clNodeTxs.Data)) + txHash = clNodeTxs.Data[0].Attributes.Hash + l.Info(). + Str("TX Hash", txHash). + Int("Number of TXs", len(clNodeTxs.Data)). + Msg("BHS Node txs") + }, "2m", "1s").Should(gomega.Succeed()) + + require.Equal(t, strings.ToLower(vrfContracts.BHS.Address()), strings.ToLower(clNodeTxs.Data[0].Attributes.To)) + + bhsStoreTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), common.HexToHash(txHash)) + require.NoError(t, err, "error getting tx from hash") - bhsStoreTxInputData, err := actions.DecodeTxInputData(blockhash_store.BlockhashStoreABI, bhsStoreTx.Data()) - l.Info(). - Str("Block Number", bhsStoreTxInputData["n"].(*big.Int).String()). - Msg("BHS Node's Store Blockhash for Blocknumber Method TX") - require.Equal(t, randRequestBlockNumber, bhsStoreTxInputData["n"].(*big.Int).Uint64()) + bhsStoreTxInputData, err := actions.DecodeTxInputData(blockhash_store.BlockhashStoreABI, bhsStoreTx.Data()) + require.NoError(t, err, "error decoding tx input data") + l.Info(). + Str("Block Number", bhsStoreTxInputData["n"].(*big.Int).String()). + Msg("BHS Node's Store Blockhash for Blocknumber Method TX") + require.Equal(t, randRequestBlockNumber, bhsStoreTxInputData["n"].(*big.Int).Uint64()) + } else { + l.Warn().Msg("Skipping BHS Node's transactions check as existing env is used") + } var randRequestBlockHash [32]byte gom.Eventually(func(g gomega.Gomega) { @@ -1494,28 +1522,10 @@ func TestVRFV2PlusWithBHF(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + configPtr := &config - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } - - // BHF job config + // BHF job config - NOTE - not possible to create BHF job spec with waitBlocks being less than 256 blocks config.VRFv2Plus.General.BHFJobWaitBlocks = ptr.Ptr(260) config.VRFv2Plus.General.BHFJobLookBackBlocks = ptr.Ptr(500) config.VRFv2Plus.General.BHFJobPollPeriod = ptr.Ptr(blockchain.StrDuration{Duration: time.Second * 30}) @@ -1523,7 +1533,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } chainlinkNodeLogScannerSettings := test_env.GetDefaultChainlinkNodeLogScannerSettingsWithExtraAllowedMessages(testreporters.NewAllowedLogMessage( "Pipeline error", @@ -1657,30 +1667,13 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + configPtr := &config - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -1830,30 +1823,13 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + configPtr := &config - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, sethClient.MustGetRootKeyAddress().Hex(), subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, @@ -1916,7 +1892,6 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int - defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData sethClient *seth.Client ) @@ -1924,33 +1899,17 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] if !network.Simulated { t.Skip("Skipped since Reorg test could only be run on Simulated chain.") } chainID := network.ChainID - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config + vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } chainlinkNodeLogScannerSettings := test_env.GetDefaultChainlinkNodeLogScannerSettingsWithExtraAllowedMessages( testreporters.NewAllowedLogMessage( @@ -2095,7 +2054,6 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int - defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode sethClient *seth.Client @@ -2104,30 +2062,14 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") - vrfv2PlusConfig := config.VRFv2Plus network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] chainID := network.ChainID - cleanupFn := func() { - if sethClient.Cfg.IsSimulatedNetwork() { - l.Info(). - Str("Network Name", sethClient.Cfg.Network.Name). - Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") - } else { - if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { - //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) - } - } - if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - } - } + configPtr := &config + vrfEnvConfig := vrfcommon.VRFEnvConfig{ TestConfig: config, ChainID: chainID, - CleanupFn: cleanupFn, + CleanupFn: vrfv2PlusCleanUpFn(&t, &sethClient, &configPtr, &env, &vrfContracts, &subIDsForCancellingAfterTest), } newEnvConfig := vrfcommon.NewEnvConfig{ NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go index dd7eb102170..292693d5098 100644 --- a/integration-tests/soak/forwarder_ocr_test.go +++ b/integration-tests/soak/forwarder_ocr_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -42,6 +42,11 @@ func executeForwarderOCRSoakTest(t *testing.T, config *tc.TestConfig) { t.Cleanup(func() { if err := actions.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error tearing down environment") + } else { + err := ocrSoakTest.Environment().Client.RemoveNamespace(ocrSoakTest.Environment().Cfg.Namespace) + if err != nil { + l.Error().Err(err).Msg("Error removing namespace") + } } }) ocrSoakTest.Setup(config) diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index 1f437e565eb..56e462ef463 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -4,21 +4,22 @@ import ( "fmt" "testing" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "time" "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" "github.com/google/uuid" - "github.com/smartcontractkit/havoc/k8schaos" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" @@ -100,7 +101,7 @@ func TestOCRSoak_RPCDownForAllCLNodes(t *testing.T) { require.NoError(t, err, "Error creating chaos") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, testsetups.WithNamespace(namespace), - testsetups.WithChaos([]*k8schaos.Chaos{chaos}), + testsetups.WithChaos([]*havoc.Chaos{chaos}), ) require.NoError(t, err, "Error creating OCR soak test") executeOCRSoakTest(t, ocrSoakTest, &config) @@ -133,7 +134,7 @@ func TestOCRSoak_RPCDownForHalfCLNodes(t *testing.T) { require.NoError(t, err, "Error creating chaos") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, testsetups.WithNamespace(namespace), - testsetups.WithChaos([]*k8schaos.Chaos{chaos}), + testsetups.WithChaos([]*havoc.Chaos{chaos}), ) require.NoError(t, err, "Error creating OCR soak test") executeOCRSoakTest(t, ocrSoakTest, &config) @@ -160,6 +161,11 @@ func executeOCRSoakTest(t *testing.T, test *testsetups.OCRSoakTest, config *tc.T t.Cleanup(func() { if err := actions.TeardownRemoteSuite(test.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error tearing down environment") + } else { + err := test.Environment().Client.RemoveNamespace(test.Environment().Cfg.Namespace) + if err != nil { + l.Error().Err(err).Msg("Error removing namespace") + } } }) if test.Interrupted() { @@ -181,12 +187,12 @@ type GethNetworkDownChaosOpts struct { Duration time.Duration } -func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*k8schaos.Chaos, error) { - k8sClient, err := k8schaos.NewChaosMeshClient() +func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*havoc.Chaos, error) { + k8sClient, err := havoc.NewChaosMeshClient() if err != nil { return nil, err } - return k8schaos.NewChaos(k8schaos.ChaosOpts{ + return havoc.NewChaos(havoc.ChaosOpts{ Description: opts.Description, DelayCreate: opts.DelayCreate, Object: &v1alpha1.NetworkChaos{ @@ -220,7 +226,7 @@ func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*k8schaos.Chaos, error }, }, Client: k8sClient, - Logger: &k8schaos.Logger, + Logger: &havoc.Logger, }) } diff --git a/integration-tests/test.Dockerfile b/integration-tests/test.Dockerfile index 2e928ab29f8..6252cfdd426 100644 --- a/integration-tests/test.Dockerfile +++ b/integration-tests/test.Dockerfile @@ -2,17 +2,30 @@ ARG BASE_IMAGE ARG IMAGE_VERSION=latest FROM ${BASE_IMAGE}:${IMAGE_VERSION} AS build-env -ARG SUITES=chaos migration performance reorg smoke soak benchmark - -COPY . testdir/ WORKDIR /go/testdir +RUN mkdir -p /go/testdir/integration-tests/load +COPY go.mod go.sum ./ +COPY integration-tests/go.mod integration-tests/go.sum ./integration-tests/ +COPY integration-tests/load/go.mod integration-tests/load/go.sum ./integration-tests/load/ +RUN cd integration-tests && go mod download +RUN cd integration-tests/load && go mod download + +COPY . . + +ARG SUITES=chaos soak benchmark load ccip-load + RUN /go/testdir/integration-tests/scripts/buildTests "${SUITES}" FROM ${BASE_IMAGE}:${IMAGE_VERSION} RUN mkdir -p /go/testdir/integration-tests/scripts -COPY --from=build-env /go/pkg /go/pkg +# Dependency of CosmWasm/wasmd +COPY --from=build-env /go/pkg/mod/github.com/\!cosm\!wasm/wasmvm@v*/internal/api/libwasmvm.*.so /usr/lib/ +RUN chmod 755 /usr/lib/libwasmvm.*.so COPY --from=build-env /go/testdir/integration-tests/*.test /go/testdir/integration-tests/ +COPY --from=build-env /go/testdir/integration-tests/ccip-tests/*.test /go/testdir/integration-tests/ COPY --from=build-env /go/testdir/integration-tests/scripts /go/testdir/integration-tests/scripts/ +RUN echo "All tests" +RUN ls -l /go/testdir/integration-tests/*.test ENTRYPOINT ["/go/testdir/integration-tests/scripts/entrypoint"] diff --git a/integration-tests/testconfig/README.md b/integration-tests/testconfig/README.md index 878b36bc756..b60cd850a42 100644 --- a/integration-tests/testconfig/README.md +++ b/integration-tests/testconfig/README.md @@ -1,121 +1,121 @@ -# TOML is the Ultimate Choice! +# Test Configurations + +- [Test Configurations](#test-configurations) + - [Summary](#summary) + - [Configurations Files and Overrides Precedence](#configurations-files-and-overrides-precedence) + - [Test Secrets (optional)](#test-secrets-optional) + - [default.toml](#defaulttoml) + - [\.toml](#producttoml) + - [overrides.toml (optional)](#overridestoml-optional) + - [`BASE64_CONFIG_OVERRIDE`](#base64_config_override) + - [Node configurations](#node-configurations) + - [Spec Properties](#spec-properties) + - [BaseConfigTOML](#baseconfigtoml) + - [Network configurations](#network-configurations) + - [Spec Properties](#spec-properties-1) + - [CommonChainConfigTOML](#commonchainconfigtoml) + - [ChainConfigTOMLByChainID](#chainconfigtomlbychainid) + - [Programmatic configuration](#programmatic-configuration) + - [Embedded configurations](#embedded-configurations) + - [Test type and case specific configurations](#test-type-and-case-specific-configurations) + - [Product-specific configurations](#product-specific-configurations) + - [Migration tests](#migration-tests) + - [Automation](#automation) + - [Specific test secrets](#specific-test-secrets) + - [OCR](#ocr) + - [Common OCR configurations](#common-ocr-configurations) + - [Reuse OCR contracts](#reuse-ocr-contracts) + - [Worthy to note](#worthy-to-note) + - [Reusing `testconfig` in other projects](#reusing-testconfig-in-other-projects) + +> [!NOTE] +> **Current state and v2** +> +> - There are still several configuration files required to run tests: `.env`, `default.toml, .toml`, `testsecrets`. +> - `TEST_LOG_LEVEL` is still kept as an environment variable to facilitate dynamic configuration selection by some tests. +> - Configuration of Chainlink nodes with TOML files separated from test configuration is aimed at v2. + +> [!IMPORTANT] +> **Contributing** +> +> It's crucial to incorporate all new test configuration settings directly into the TOML configuration files, steering clear of using environment variables for this purpose. Our goal is to centralize all configuration details, including examples, within the same package. This approach simplifies the process of understanding the available configuration options and identifying the appropriate values to use for each setting. + +## Summary + +The `testconfig` package represents a storage of test configurations per product/service. + +> [!TIP] +> 1. The `testconfig.go` may `Save()` your specification to a configuration file. +> 2. To identify the configurations in use, run tests with the `TEST_LOG_LEVEL=debug`. + +## Configurations Files and Overrides Precedence + +Overrides work in the order of the following precedence (1 overrides 2 and so on): + +1. [Environment variable `BASE64_CONFIG_OVERRIDE`](#base64_config_override) +2. [overrides.toml](#overridestoml-optional) +3. [\.toml](#producttoml) +4. [default.toml](#defaulttoml) +5. [testsecrets](#test-secrets-optional) + +### Test Secrets (optional) + +Test secrets are necessary for remote environments (CI, Kubernetes). For more details, visit [Test Secrets in CTF](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/README.md#test-secrets). -## Introduction - -Final implementation has undergone minor adjustments in comparison to the approach by Adam Hamric, Anindita Ghosh, and Sergey Kudasov stated in the ADR. The primary changes are as follows: - -* `TEST_LOG_LEVEL` remains an environment variable, pending the release of version 2. -* `TEST_TYPE` is also kept as an environment variable to facilitate dynamic configuration selection by some tests. -* TOML configuration of Chainlink nodes themselves has not been added, awaiting version 2. -* The hierarchy of configuration overrides has been streamlined for simplicity. +### default.toml -By design, all test configurations are intended to reside within the `testconfig` package, organized into application-specific folders. However, the system can locate these configurations in any folder within the `integration-tests` directory, selecting the first one found. To identify the configurations in use, execute tests with the `debug` log level. +[default.toml](default.toml) represents common default test settings for logging, network, node and chain client. -The `testconfig` package serves as a centralized resource for accessing configurations across all products, including shared settings like logging and network preferences, as well as initial funding for Chainlink nodes. Product configurations, if present, are subjected to validation based on logical assumptions and observed code values. The `TestConfig` structure includes a `Save()` method, allowing for the preservation of test configurations after all adjustments have been applied. +> [!TIP] +> It is recommended to provide [product-specific configurations](#producttoml) with explicitly defined values to override default configs. -## Configuration and Overrides +### \.toml -The order of precedence for overrides is as follows: +Product-specific default configurations stored in `./testconfig//.toml` (e.g. [ocr2.toml](./ocr2/ocr2.toml)). They explicitly define a [node configuration](#node-configurations), [test type-specific configurations](#test-type-and-case-specific-configurations), and override any [default settings](#defaulttoml) per product/service. -* [File `default.toml`](#defaulttoml) -* [Product-specific file, e.g., `[product_name].toml`](#product-specific-configurations) -* [File `overrides.toml`](#overridestoml) -* [Environment variable `BASE64_CONFIG_OVERRIDE`](#base64_config_override) +### overrides.toml (optional) -### default.toml -That file is envisioned to contain fundamental and universally applicable settings, such as logging configurations, private Ethereum network settings or Seth networks settings for known networks. +> [!CAUTION] +> Even though `overrides.toml` is git-ignored, pay attention to avoid storing any sensitive data in this file, especially in override-files for remote environments (which are not git-ignored). -### Product-specific configurations -Product-specific configurations, such as those in `[product_name].toml`, house the bulk of default and variant settings, supporting default configurations like the following in `log_poller.toml`, which should be used by all Log Poller tests: +The `overrides.toml` enables tests parametrization. When provided, it overrides default and per-product configurations. -```toml -# product defaults -[LogPoller] -[LogPoller.General] -generator = "looped" -contracts = 2 -events_per_tx = 4 -use_finality_tag = true -log_poll_interval = "500ms" -# 0 disables backup poller -backup_log_poller_block_delay = 0 - -[LogPoller.Looped] -execution_count = 100 -min_emit_wait_time_ms = 200 -max_emit_wait_time_ms = 500 -``` +1. **For local runs**, store overrides as follows `./testconfig/overrides.toml`. +2. **For remote environments** (CI, Kubernetes), commit overrides to repository under `../integration-tests/testconfig//overrides/.toml` (e.g. [OCR2 overrides](../integration-tests/testconfig/ocr2/overrides/base_sepolia.toml)). See more in [E2E Tests on GitHub CI with overrides](../../.github/E2E_TESTS_ON_GITHUB_CI.md#test-workflows-setup-in-ci). -### overrides.toml -This file is recommended for local use to adjust dynamic variables or modify predefined settings. At the very minimum it should contain the Chainlink image and version, as shown in the example below: - -```toml -[ChainlinkImage] -image = "your image name" -version = "your tag" -``` +Alternatively, set `E2E_TEST_CHAINLINK_IMAGE` and `E2E_TEST_CHAINLINK_VERSION` in `~/.testsecrets` ### `BASE64_CONFIG_OVERRIDE` -This environment variable is primarily intended for use in continuous integration environments, enabling the substitution of default settings with confidential or user-specific parameters. For instance: -```bash -cat << EOF > config.toml -[Network] -selected_networks=["$SELECTED_NETWORKS"] - -[ChainlinkImage] -image="" -version="$CHAINLINK_VERSION" -postgres_version="$CHAINLINK_POSTGRES_VERSION" - -[Logging] -test_log_collect=false -run_id="$RUN_ID" - -[Logging.LogStream] -log_targets=["$LOG_TARGETS"] -EOF - -BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) -echo ::add-mask::$BASE64_CONFIG_OVERRIDE -echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV -``` -**It is highly recommended to use reusable GHA actions present in [.actions](../../../.github/.actions) to generate and apply the base64-encoded configuration.** Own implementation of `BASE64_CONFIG_OVERRIDE` generation is discouraged and should be used only if existing actions do not cover the use case. But even in that case it might be a better idea to extend existing actions. -This variable is automatically relayed to Kubernetes-based tests, eliminating the need for manual intervention in test scripts. +This environment variable is used for overriding defaults in remote testing ([CI - On Demand Workflows](../../.github/E2E_TESTS_ON_GITHUB_CI.md#on-demand-workflows) and Kubernetes) when triggered from local machine. -## Test Secrets +Example: -Test secrets are not stored directly within the `TestConfig` TOML for security reasons. Instead, they are passed into `TestConfig` via environment variables. This ensures sensitive data is handled securely throughout our testing processes. - -For detailed instructions on how to set test secrets both locally and within CI environments, please visit: [Test Secrets Guide in CTF](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md#test-secrets) +```bash +# Go test +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -## Named Configurations +- - - - - - - - - - - - - -Named configurations allow for the customization of settings through unique identifiers, such as a test name or type, acting as specific overrides. Here's how you can define and use these configurations: +# Make command +BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) make test_ +``` -For instance, to tailor configurations for a particular test, you might define it as follows: +## Node configurations -```toml -# Here the configuration name is "TestLogManyFiltersPollerFinalityTag" -[TestLogManyFiltersPollerFinalityTag.LogPoller.General] -contracts = 300 -``` +A node configuration consists of two main blocks: -Alternatively, for a configuration that applies to a certain type of test, as seen in `vrfv2.toml`, you could specify: +- Network/chain configuration +- Node-specific configuration -```toml -# Here the configuration name is "Soak" -[Soak.VRFv2.Common] -cancel_subs_after_test_run = true -``` +### Spec Properties -When processing TOML files, the system initially searches for a general (unnamed) configuration. If a named configuration is found, it can specifically override the general (unnamed) settings, providing a targeted approach to configuration management based on distinct identifiers like test names or types. +#### BaseConfigTOML -### Chainlink Node TOML config +A node's configuration unrelated to network settings is defined in `[NodeConfig].BaseConfigTOML="""your_config_here"""`, if none - defaults are used. -Find default node config in `testconfig/default.toml` +Example: -To set custom config for Chainlink Node use `NodeConfig.BaseConfigTOML` in TOML. Example: ```toml [NodeConfig] BaseConfigTOML = """ @@ -124,24 +124,31 @@ FeedsManager = true LogPoller = true UICSAKeys = true -[Log] -Level = 'debug' -JSONConsole = true - -[Log.File] -MaxSize = '0b' - [OCR] Enabled = true -DefaultTransactionQueueDepth = 0 """ ``` -Note that you cannot override individual values in BaseConfigTOML. You must provide the entire configuration. -This corresponds to [Config struct](../../core/services/chainlink/config.go) in Chainlink Node that excludes all chain-specific configuration, which is built based on selected_networks and either Chainlink Node's defaults for each network, or `ChainConfigTOMLByChainID` (if an entry with matching chain id is defined) or `CommonChainConfigTOML` (if no entry with matching chain id is defined). -If BaseConfigTOML is empty, then default base config provided by the Chainlink Node is used. If tracing is enabled unique id will be generated and shared between all Chainlink nodes in the same test. +### Network configurations + +Chain-specific configuration is composed of the following blocks: + +- `[Network].selected_networks` - a list of networks to run tests on. +- `ChainConfigTOMLByChainID` (if an entry with matching chain id is defined) OR `CommonChainConfigTOML` (if no entry with matching chain id is defined). + +> [!NOTE] +> +> 1. If a `ChainConfigTOMLByChainID` or `CommonChainConfigTOML` is specified, they will override any defaults a Chainlink Node might have for the given network. +> 2. To override default [BaseConfigTOML](#baseconfigtoml) and/or [CommonChainConfigTOML](#commonchainconfigtoml) provide the entire blocks as if it would be completely new configuration. + +#### Spec Properties + +##### CommonChainConfigTOML + +A network-specific node config for EVM chains: `[NodeConfig].CommonChainConfigTOML="""your_config_here"""`. + +Example: -To set base config for EVM chains use `NodeConfig.CommonChainConfigTOML`. Example: ```toml CommonChainConfigTOML = """ AutoCreateKey = true @@ -155,9 +162,12 @@ FeeCapDefault = '200 gwei' """ ``` -This is the default configuration used for all EVM chains unless `ChainConfigTOMLByChainID` is specified. Do remember that if either `ChainConfigTOMLByChainID` or `CommonChainConfigTOML` is defined, it will override any defaults that Chainlink Node might have for the given network. Part of the configuration that defines blockchain node URLs is always dynamically generated based on the EVMNetwork configuration. +##### ChainConfigTOMLByChainID + +The `[NodeConfig.ChainConfigTOMLByChainID]` is a custom per-chain config that overrides the [`CommonChainConfigTOML`](#commonchainconfigtoml). See examples in product directories, e.g. [ocr2/example.toml](./ocr2/example.toml). + +Example: -To set custom per-chain config use `[NodeConfig.ChainConfigTOMLByChainID]`. Example: ```toml [NodeConfig.ChainConfigTOMLByChainID] # applicable only to arbitrum-goerli chain @@ -166,78 +176,212 @@ To set custom per-chain config use `[NodeConfig.ChainConfigTOMLByChainID]`. Exam PriceMax = '400 gwei' LimitDefault = 100000000 FeeCapDefault = '200 gwei' -BumpThreshold = 60 -BumpPercent = 20 -BumpMin = '100 gwei' """ ``` -For more examples see `example.toml` in product TOML configs like `testconfig/automation/example.toml`. If either ChainConfigTOMLByChainID or CommonChainConfigTOML is defined, it will override any defaults that Chainlink Node might have for the given network. Part of the configuration that defines blockchain node URLs is always dynamically generated based on the EVMNetwork configuration. -Currently, all networks are treated as EVM networks. There's no way to provide Solana, Starknet, Cosmos or Aptos configuration yet. +> [!NOTE] +> Currently, all networks are treated as EVM networks. There's no way to provide Solana, Starknet, Cosmos or Aptos configuration yet. -### Setting env vars for Chainlink Node +### Programmatic configuration -To set env vars for Chainlink Node use `WithCLNodeOptions()` and `WithNodeEnvVars()` when building a test environment. Example: +To set env vars for a Dockerized test use `docker.test_env_builder.WithCLNodeOptions(test_env.WithNodeEnvVars(envs))`. + +Example: ```go envs := map[string]string{ "CL_LOOPP_HOSTNAME": "hostname", } + +nodeEnvVars := test_env.WithNodeEnvVars(envs) + testEnv, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(clNodeCount). - WithCLNodeOptions(test_env.WithNodeEnvVars(envs)). + WithCLNodeOptions(nodeEnvVars). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). WithSeth(). Build() ``` -## Local/Kubernetes Usage +### Embedded configurations + +For the reason Go automatically excludes TOML files during the compilation of binaries, the [config_embed.go](./configs_embed.go) deliberately incorporates all the default configurations into the the compiled binary with a custom build tag `-o embed`. Hence, only `overrides.toml` may be potentially needed to execute tests. + +## Test type and case specific configurations -GitHub workflows in this repository have been updated to dynamically generate and utilize base64-encoded TOML configurations derived from user inputs or environment variables. For local execution or remote Kubernetes runners, users must manually supply certain variables, which cannot be embedded in configuration files due to their sensitive or dynamic nature. +These configurations represent unique identifiers used for customization of different test runs per product. When found, they take precedence and overrides the general (unnamed) settings (mentioned above). -Essential variables might include: +Examples: -* Chainlink image and version -* Test duration for specific tests (e.g., load, soak) -* Configuration specific to Loki (mandatory for certain tests) -* Grafana dashboard URLs +```toml +# Specific per test configuration "TestLogPollerManyFiltersFinalityTag" for LogPoller +[TestLogPollerManyFiltersFinalityTag.LogPoller.General] +contracts = 300 -For local testing, it is advisable to place these variables in the `overrides.toml` file. For Kubernetes or remote runners, the process involves creating a TOML file with the necessary values, encoding it in base64, and setting the result as the `BASE64_CONFIG_OVERRIDE` environment variable. +# "Soak" test configuration for VRFv2 +[Soak.VRFv2.Common] +cancel_subs_after_test_run = true -## Embedded config +# "Load" test configuration for OCR2 +[Load.OCR2] +[Load.OCR2.Common] +eth_funds = 3 +``` -Because Go automatically excludes TOML files during the compilation of binaries, we must take deliberate steps to include our configuration files in the compiled binary. This can be accomplished by using a custom build tag `-o embed`. Implementing this tag will incorporate all the default configurations located in the `./testconfig` folder directly into the binary. Therefore, when executing tests from the binary, you'll only need to supply the `overrides.toml` file. This file should list only the settings you wish to modify; all other configurations will be sourced from the embedded configurations. You can access these embedded configurations [here](.integration-tests/testconfig/configs_embed.go). +## Product-specific configurations -## To bear in mind +> [!TIP] +> Find which configurations are applicable to a specific product in structs of the `testconfig/product directory/config.go (or .go)`. +> Examples: [ocr2/ocr2.go](./ocr2/ocr2.go), [automation/config.go](./automation/config.go). -### Validation failures +### Migration tests -When the system encounters even a single setting related to a specific product or configuration within the configurations, it triggers a comprehensive validation of the entire configuration for that product. This approach is based on the assumption that if any configuration for a given product is specified, the entire set of configurations for that product must be complete and valid. This is particularly crucial when dealing with the `overrides.toml` file, where it's easy to overlook the need to comment out or adjust values when switching between configurations for different products. Essentially, the presence of any specific configuration detail necessitates that all relevant configurations for that product be fully defined and correct to prevent validation errors. +1. Set `E2E_TEST_CHAINLINK_UPGRADE_IMAGE` in [testsecrets](#test-secrets-optional). -## Possible nil pointers + ```bash + E2E_TEST_CHAINLINK_UPGRADE_IMAGE="public.ecr.aws/chainlink/chainlink" + ``` -If no configuration values are set for a product or its logging parameters, the system won't perform validation checks. This can lead to a 'nil pointer exception' error if you attempt to access a configuration property later on. This situation arises because we use pointers to facilitate optional overrides; accessing an unset (nil) pointer will cause an error. To avoid such issues, especially when general validations might not cover every scenario, it's crucial for users to ensure that all necessary configuration options are explicitly set. Additionally, it's highly recommended to implement test-specific validations to confirm that all required values for a particular test are indeed established. This proactive approach helps prevent runtime errors and ensures smooth test execution. +2. In `overrides.toml` set image to upgrade to: -## Contributing + ```toml + # image to upgrade to + [ChainlinkUpgradeImage] + version="2.17.0-beta0" + ``` -It's crucial to incorporate all new test configuration settings directly into the TOML configuration files, steering clear of using environment variables for this purpose. Our goal is to centralize all configuration details, including examples, within the same package. This approach simplifies the process of understanding the available configuration options and identifying the appropriate values to use for each setting. +3. Run tests: -## Reusing TestConfig in other projects + ```bash + # Go + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) go test -v -p 1 ./smoke/_test.go -To ensure the cleanliness and simplicity of your project's configuration, it's advised against using the `testconfig` code as a direct library in other projects. The reason is that much of this code is tailored specifically to its current application, which might not align with the requirements of your project. Your project might not necessitate any overrides or could perhaps benefit from a simpler configuration approach. + - - - - - - - - - - - - -However, if you find a need to utilize some methods from this project, the recommended practice is to implement the required interfaces within your project's configuration package, rather than directly copying and pasting code. For instance, if you aim to incorporate a setup action similar to the `SetupVRFV2Environment` for VRFv2, like the one shown below: + # Make command + BASE64_CONFIG_OVERRIDE=$(cat ./testconfig/overrides.toml | base64) make test_node_migrations_verbose + ``` + +### Automation + +#### Specific test secrets + +| Secret | Env Var | Example | Description | +| ----------------------------- | ------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------ | +| Data Streams Url | `E2E_TEST_DATA_STREAMS_URL` | `E2E_TEST_DATA_STREAMS_URL=url` | Required by some automation tests to connect to data streams. | +| Data Streams Username | `E2E_TEST_DATA_STREAMS_USERNAME` | `E2E_TEST_DATA_STREAMS_USERNAME=username` | Required by some automation tests to connect to data streams. | +| Data Streams Password | `E2E_TEST_DATA_STREAMS_PASSWORD` | `E2E_TEST_DATA_STREAMS_PASSWORD=password` | Required by some automation tests to connect to data streams. | + +### OCR + +#### Common OCR configurations + +Specify number of contracts to be deployed for OCR (correspondingly, the same amount of jobs per OCR contract will be created on a node). For example: + +```toml +# OCRv1 +[OCR.Common] +number_of_contracts=2 + +- - - - - - - - - - - - + +# OCRv2 +[OCR2.Common] +number_of_contracts=2 +``` + +#### Reuse OCR contracts + +The feature supports OCR v1 and v2. It gets enabled when `[OCR.Contract]` block is specified. + +To reuse existing OCR contracts provide: + +- LINK token address (unique per chain) +- OCR contract addresses +- [optional] choose, whether to use and configure the existing OCR contracts. **N/B:** usage/configuring of several selected contracts (not all the listed addresses) is not supported. All the contacts should have the same `use` and `configure` values. + +Example: + +```toml +# For OCRv1 +[OCR.Contracts] +link_token = "0x88d1239894D9582f5849E5b5a964da9e5730f1E6" +offchain_aggregators = ["0xc1ce3815d6e7f3705265c2577F1342344752A5Eb"] + +# If [OCR.Contracts.Settings.] is not present, we assume it should be used and configured + +- - - - - - - - - - - - + +# For OCRv2 +[OCR2.Contracts] +link_token = "0x88d1239894D9582f5849E5b5a964da9e5730f1E6" +offchain_aggregators = ["0xc1ce3815d6e7f3705265c2577F1342344752A5Eb"] + +# notice that this address needs to match the one in offchain_aggregators +[OCR2.Contracts.Settings."0xc1ce3815d6e7f3705265c2577F1342344752A5Eb"] +use = false # Default: true. Reuse existing OCR contracts? +configure = false # Default: true. Configure existing OCR contracts? + +- - - - - - - - - - - - + +# Non-compliant configurations +[OCR.Contracts] +link_token = "0x88d1239894D9582f5849E5b5a964da9e5730f1E6" +offchain_aggregators = ["0xc1ce3815d6e7f3705265c2577F1342344752A5Eb", "0x2f4FA21fCd917C448C160caafEC874032F404c08"] + +# Example 1: Setting `configure` to `false` for selected (not all) addresses will fail configuration validation +[OCR.Contracts.Settings."0xc1ce3815d6e7f3705265c2577F1342344752A5Eb"] +configure = false + +# OR + +# Example 2: Setting `configure` to different values for the listed contracts will fail execution +[OCR.Contracts.Settings."0xc1ce3815d6e7f3705265c2577F1342344752A5Eb"] +configure = false + +[OCR.Contracts.Settings."0x2f4FA21fCd917C448C160caafEC874032F404c08"] +configure = true + +# OR + +# Example 3: Setting `use` to different values for the listed contracts will fail execution +[OCR.Contracts.Settings."0xc1ce3815d6e7f3705265c2577F1342344752A5Eb"] +use = false + +[OCR.Contracts.Settings."0x2f4FA21fCd917C448C160caafEC874032F404c08"] +use = true +``` + +## Worthy to note + +> [!NOTE] +> **Configuration Validation and `nil` pointers** +> When tests encounter a [test](#test-type-and-case-specific-configurations) or [product-specific](#product-specific-configurations) setting, they trigger a validation to ensure that the entire set of configurations for that product is complete and valid. +> +> If there are no configuration values (for a product or its logging parameters), the tests won't perform validation checks, leading to a `nil pointer exception` error on an attempt to access a configuration property later on. The error is caused by the usage of pointers to facilitate optional overrides: accessing an unset (nil) pointer will cause an error. To avoid such run-time issues, it is highly recommended to implement configuration-specific validations to confirm that all the required values for a particular test are explicitly specified. + +> [!NOTE] +> **Known Issues/Limitations** +> Duplicated test configuration file names in different locations may lead to an unpredictable execution behavior. +> +> The use of pointer fields for optional configuration elements necessitates careful handling, especially for programmatic modifications, to avoid unintended consequences. The `MustCopy()` function is recommended for creating deep copies of configurations for isolated modifications. Unfortunately some of the custom types are not copied at all, you need to set them manually. It's true for example for `blockchain.StrDuration` type. + +## Reusing `testconfig` in other projects + +To utilize some methods from this project, implement the required interfaces within your project's configuration package (no copy-pasting or structure replicating). + +Example: ```go func SetupVRFV2Environment( env *test_env.CLClusterTestEnv, nodesToCreate []vrfcommon.VRFNodeType, - vrfv2TestConfig types.VRFv2TestConfig, + vrfv2TestConfig types.VRFv2TestConfig, // implementation of interface used as a parameter useVRFOwner bool, useTestCoordinator bool, linkToken contracts.LinkToken, @@ -247,12 +391,5 @@ func SetupVRFV2Environment( numberOfConsumers int, numberOfSubToCreate int, l zerolog.Logger, -) (*vrfcommon.VRFContracts, []uint64, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*vrfcommon.VRFContracts, []uint64, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { } ``` - -You should not replicate the entire `TestConfig` structure. Instead, create an implementation of the `types.VRFv2TestConfig` interface in your project and use that as the parameter. This approach allows you to maintain a streamlined and focused configuration package in your project. - -## Known Issues/Limitations - -* Duplicate file names in different locations may lead to unpredictable configurations being selected. -* The use of pointer fields for optional configuration elements necessitates careful handling, especially for programmatic modifications, to avoid unintended consequences. The `MustCopy()` function is recommended for creating deep copies of configurations for isolated modifications. Unfortunately some of the custom types are not copied at all, you need to set them manually. It's true for example for `blockchain.StrDuration` type. diff --git a/integration-tests/testconfig/automation/automation.toml b/integration-tests/testconfig/automation/automation.toml index 26b9f05597d..b2e87fa34f9 100644 --- a/integration-tests/testconfig/automation/automation.toml +++ b/integration-tests/testconfig/automation/automation.toml @@ -2,6 +2,9 @@ [Common] chainlink_node_funding = 2.0 +[Pyroscope] +enabled=false + [NodeConfig] BaseConfigTOML = """ [Feature] @@ -82,6 +85,7 @@ max_perform_gas=5_000_000 min_upkeep_spend=0 fallback_gas_price=200_000_000_000 fallback_link_price=2_000_000_000_000_000_000 +fallback_native_price=2_000_000_000_000_000_000 max_check_data_size=5_000 max_perform_data_size=5_000 max_revert_data_size=5_000 @@ -148,6 +152,7 @@ max_perform_gas=5_000_000 min_upkeep_spend=0 fallback_gas_price=200_000_000_000 fallback_link_price=2_000_000_000_000_000_000 +fallback_native_price=2_000_000_000_000_000_000 max_check_data_size=5_000 max_perform_data_size=5_000 max_revert_data_size=5_000 @@ -199,11 +204,16 @@ max_perform_gas=5_000_000 min_upkeep_spend=0 fallback_gas_price=200_000_000_000 fallback_link_price=2_000_000_000_000_000_000 +fallback_native_price=2_000_000_000_000_000_000 max_check_data_size=5_000 max_perform_data_size=5_000 max_revert_data_size=5_000 # load test specific overrides +[Load.Logging.Grafana] +base_url="https://grafana.ops.prod.cldev.sh" +dashboard_url="/d/a4899f53-f709-430a-aec2-24f32198dcc9/chainlink-automation-v2-load-test" + [Load.Seth] ephemeral_addresses_number = 100 root_key_funds_buffer = 1_000_000 @@ -289,9 +299,254 @@ max_perform_gas=5_000_000 min_upkeep_spend=0 fallback_gas_price=200_000_000_000 fallback_link_price=2_000_000_000_000_000_000 +fallback_native_price=2_000_000_000_000_000_000 max_check_data_size=5_000 max_perform_data_size=5_000 max_revert_data_size=5_000 [Load.Pyroscope] -enabled=false \ No newline at end of file +enabled=false + +# automation benchmark test specific overrides +[Benchmark.Logging.Grafana] +base_url="https://grafana.ops.prod.cldev.sh" +dashboard_url="/d/Q8n6m1unz/chainlink-automation-benchmark-test" + +# will retry roughly for 1h before giving up (900 * 4s) +[Benchmark.Automation.Resiliency] +# number of retries before giving up +contract_call_limit = 900 +# static interval between retries +contract_call_interval = "4s" + +[Benchmark.Seth] +# keeper benchmark running on simulated network requires 100k per node +root_key_funds_buffer = 1_000_000 + +[Benchmark.Automation] +[Benchmark.Automation.General] +number_of_nodes=6 +duration=3600 +block_time=1 +spec_type="minimum" +chainlink_node_log_level="info" +use_prometheus=false +remove_namespace = true + +[Benchmark.Automation.Benchmark] +registry_to_test = "2_1" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 1000 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 10000 +perform_gas_to_burn = 1000 +block_range = 3600 +block_interval = 60 +forces_single_tx_key = false +delete_jobs_on_end = true + +[Benchmark.NodeConfig] +BaseConfigTOML = """ +[Feature] +LogPoller = true + +[OCR2] +Enabled = true + +[P2P] +[P2P.V2] +Enabled = true +AnnounceAddresses = ["0.0.0.0:6690"] +ListenAddresses = ["0.0.0.0:6690"] +[Keeper] +TurnLookBack = 0 +[WebServer] +HTTPWriteTimeout = '1h' +""" + +CommonChainConfigTOML = """ +""" + +[Benchmark.NodeConfig.ChainConfigTOMLByChainID] +# applicable for simulated chain +1337 = """ +FinalityDepth = 50 +LogPollInterval = '1s' +MinIncomingConfirmations = 1 + +[HeadTracker] +HistoryDepth = 100 + +[GasEstimator] +Mode = 'FixedPrice' +LimitDefault = 5_000_000 +""" + +[Benchmark.Automation.AutomationConfig] +use_log_buffer_v1=false + +[Benchmark.Automation.AutomationConfig.PublicConfig] +delta_progress=10_000_000_000 +delta_resend=15_000_000_000 +delta_initial=500_000_000 +delta_round=1_000_000_000 +delta_grace=200_000_000 +delta_certified_commit_request=300_000_000 +delta_stage=30_000_000_000 +r_max=24 +f=1 +max_duration_query=20_000_000 +max_duration_observation=20_000_000 +max_duration_should_accept_attested_report=1_200_000_000 +max_duration_should_transmit_accepted_report=20_000_000 + +[Benchmark.Automation.AutomationConfig.PluginConfig] +perform_lockout_window=3_600_000 +target_probability="0.999" +target_in_rounds=1 +min_confirmations=0 +gas_limit_per_report=10_300_000 +gas_overhead_per_upkeep=300_000 +max_upkeep_batch_size=10 + +[Benchmark.Automation.AutomationConfig.PluginConfig.LogProviderConfig] +block_rate=1 +log_limit=2 + +[Benchmark.Automation.AutomationConfig.RegistrySettings] +payment_premium_ppb=0 +flat_fee_micro_link=40000 +check_gas_limit=45_000_000 +staleness_seconds=90_000 +gas_ceiling_multiplier=2 +max_perform_gas=5_000_000 +min_upkeep_spend=0 +fallback_gas_price=200_000_000_000 +fallback_link_price=2_000_000_000_000_000_000 +fallback_native_price=2_000_000_000_000_000_000 +max_check_data_size=5_000 +max_perform_data_size=5_000 +max_revert_data_size=5_000 + +# automation soak test specific overrides +[Soak.Logging.Grafana] +base_url="https://grafana.ops.prod.cldev.sh" +dashboard_url="/d/Q8n6m1unz/chainlink-automation-benchmark-test" + +# will retry roughly for 1h before giving up (900 * 4s) +[Soak.Automation.Resiliency] +# number of retries before giving up +contract_call_limit = 900 +# static interval between retries +contract_call_interval = "4s" + +[Soak.Seth] +# keeper benchmark running on simulated network requires 100k per node +root_key_funds_buffer = 1_000_000 + +[Soak.Automation] +[Soak.Automation.General] +number_of_nodes=6 +duration=3600 +block_time=1 +spec_type="minimum" +chainlink_node_log_level="info" +use_prometheus=false +remove_namespace = true + +[Soak.Automation.Benchmark] +registry_to_test = "2_1" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 50 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 10000 +perform_gas_to_burn = 1000 +block_range = 28800 +block_interval = 300 +forces_single_tx_key = false +delete_jobs_on_end = true + +[Soak.NodeConfig] +BaseConfigTOML = """ +[Feature] +LogPoller = true + +[OCR2] +Enabled = true + +[P2P] +[P2P.V2] +Enabled = true +AnnounceAddresses = ["0.0.0.0:6690"] +ListenAddresses = ["0.0.0.0:6690"] +[Keeper] +TurnLookBack = 0 +[WebServer] +HTTPWriteTimeout = '1h' +""" + +CommonChainConfigTOML = """ +""" + +[Soak.NodeConfig.ChainConfigTOMLByChainID] +# applicable for simulated chain +1337 = """ +FinalityDepth = 50 +LogPollInterval = '1s' +MinIncomingConfirmations = 1 + +[HeadTracker] +HistoryDepth = 100 + +[GasEstimator] +Mode = 'FixedPrice' +LimitDefault = 5_000_000 +""" + +[Soak.Automation.AutomationConfig] +use_log_buffer_v1=false + +[Soak.Automation.AutomationConfig.PublicConfig] +delta_progress=10_000_000_000 +delta_resend=15_000_000_000 +delta_initial=500_000_000 +delta_round=1_000_000_000 +delta_grace=200_000_000 +delta_certified_commit_request=300_000_000 +delta_stage=30_000_000_000 +r_max=24 +f=1 +max_duration_query=20_000_000 +max_duration_observation=20_000_000 +max_duration_should_accept_attested_report=1_200_000_000 +max_duration_should_transmit_accepted_report=20_000_000 + +[Soak.Automation.AutomationConfig.PluginConfig] +perform_lockout_window=3_600_000 +target_probability="0.999" +target_in_rounds=1 +min_confirmations=0 +gas_limit_per_report=10_300_000 +gas_overhead_per_upkeep=300_000 +max_upkeep_batch_size=10 + +[Soak.Automation.AutomationConfig.PluginConfig.LogProviderConfig] +block_rate=1 +log_limit=2 + +[Soak.Automation.AutomationConfig.RegistrySettings] +payment_premium_ppb=200_000_000 +flat_fee_micro_link=0 +check_gas_limit=2_500_000 +staleness_seconds=90000 +gas_ceiling_multiplier=1 +max_perform_gas=5_000_000 +min_upkeep_spend=0 +fallback_gas_price=200_000_000_000 +fallback_link_price=2_000_000_000_000_000_000 +fallback_native_price=2_000_000_000_000_000_000 +max_check_data_size=5_000 +max_perform_data_size=5_000 +max_revert_data_size=5_000 diff --git a/integration-tests/testconfig/automation/config.go b/integration-tests/testconfig/automation/config.go index e6df7714af7..e462ff15c17 100644 --- a/integration-tests/testconfig/automation/config.go +++ b/integration-tests/testconfig/automation/config.go @@ -2,8 +2,13 @@ package automation import ( "errors" + "fmt" "math/big" "time" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { @@ -11,6 +16,9 @@ type Config struct { Load []Load `toml:"Load"` DataStreams *DataStreams `toml:"DataStreams"` AutomationConfig *AutomationConfig `toml:"AutomationConfig"` + Resiliency *ResiliencyConfig `toml:"Resiliency"` + Benchmark *Benchmark `toml:"Benchmark"` + Contracts *Contracts `toml:"Contracts"` } func (c *Config) Validate() error { @@ -37,6 +45,57 @@ func (c *Config) Validate() error { return err } } + if c.Resiliency != nil { + if err := c.Resiliency.Validate(); err != nil { + return err + } + } + if c.Benchmark != nil { + if err := c.Benchmark.Validate(); err != nil { + return err + } + } + return nil +} + +type Benchmark struct { + RegistryToTest *string `toml:"registry_to_test"` + NumberOfRegistries *int `toml:"number_of_registries"` + NumberOfUpkeeps *int `toml:"number_of_upkeeps"` + UpkeepGasLimit *int64 `toml:"upkeep_gas_limit"` + CheckGasToBurn *int64 `toml:"check_gas_to_burn"` + PerformGasToBurn *int64 `toml:"perform_gas_to_burn"` + BlockRange *int64 `toml:"block_range"` + BlockInterval *int64 `toml:"block_interval"` + ForceSingleTxKey *bool `toml:"forces_single_tx_key"` + DeleteJobsOnEnd *bool `toml:"delete_jobs_on_end"` +} + +func (c *Benchmark) Validate() error { + if c.RegistryToTest == nil || *c.RegistryToTest == "" { + return errors.New("registry_to_test must be set") + } + if c.NumberOfRegistries == nil || *c.NumberOfRegistries <= 0 { + return errors.New("number_of_registries must be a positive integer") + } + if c.NumberOfUpkeeps == nil || *c.NumberOfUpkeeps <= 0 { + return errors.New("number_of_upkeeps must be a positive integer") + } + if c.UpkeepGasLimit == nil || *c.UpkeepGasLimit <= 0 { + return errors.New("upkeep_gas_limit must be a positive integer") + } + if c.CheckGasToBurn == nil || *c.CheckGasToBurn <= 0 { + return errors.New("check_gas_to_burn must be a positive integer") + } + if c.PerformGasToBurn == nil || *c.PerformGasToBurn <= 0 { + return errors.New("perform_gas_to_burn must be a positive integer") + } + if c.BlockRange == nil || *c.BlockRange <= 0 { + return errors.New("block_range must be a positive integer") + } + if c.BlockInterval == nil || *c.BlockInterval <= 0 { + return errors.New("block_interval must be a positive integer") + } return nil } @@ -129,9 +188,9 @@ func (c *Load) Validate() error { type DataStreams struct { Enabled *bool `toml:"enabled"` - URL *string `toml:"url"` - Username *string `toml:"username"` - Password *string `toml:"password"` + URL *string `toml:"-"` + Username *string `toml:"-"` + Password *string `toml:"-"` DefaultFeedID *string `toml:"default_feed_id"` } @@ -298,6 +357,7 @@ type RegistrySettings struct { MinUpkeepSpend *big.Int `toml:"min_upkeep_spend"` FallbackGasPrice *big.Int `toml:"fallback_gas_price"` FallbackLinkPrice *big.Int `toml:"fallback_link_price"` + FallbackNativePrice *big.Int `toml:"fallback_native_price"` MaxCheckDataSize *uint32 `toml:"max_check_data_size"` MaxPerformDataSize *uint32 `toml:"max_perform_data_size"` MaxRevertDataSize *uint32 `toml:"max_revert_data_size"` @@ -331,6 +391,9 @@ func (c *RegistrySettings) Validate() error { if c.FallbackLinkPrice == nil || c.FallbackLinkPrice.Cmp(big.NewInt(0)) < 0 { return errors.New("fallback_link_price must be set to a non-negative integer") } + if c.FallbackNativePrice == nil || c.FallbackNativePrice.Cmp(big.NewInt(0)) < 0 { + return errors.New("fallback_native_price must be set to a non-negative integer") + } if c.MaxCheckDataSize == nil || *c.MaxCheckDataSize < 1 { return errors.New("max_check_data_size must be set to a positive integer") } @@ -342,3 +405,445 @@ func (c *RegistrySettings) Validate() error { } return nil } + +type ResiliencyConfig struct { + ContractCallLimit *uint `toml:"contract_call_limit"` + ContractCallInterval *blockchain.StrDuration `toml:"contract_call_interval"` +} + +func (c *ResiliencyConfig) Validate() error { + if c.ContractCallLimit == nil { + return errors.New("contract_call_limit must be set") + } + if c.ContractCallInterval == nil { + return errors.New("contract_call_interval must be set") + } + + return nil +} + +type Contracts struct { + ShouldBeUsed *bool `toml:"use"` + LinkTokenAddress *string `toml:"link_token"` + WethAddress *string `toml:"weth"` + TranscoderAddress *string `toml:"transcoder"` + ChainModuleAddress *string `toml:"chain_module"` + RegistryAddress *string `toml:"registry"` + RegistrarAddress *string `toml:"registrar"` + LinkEthFeedAddress *string `toml:"link_eth_feed"` + EthGasFeedAddress *string `toml:"eth_gas_feed"` + EthUSDFeedAddress *string `toml:"eth_usd_feed"` + LinkUSDFeedAddress *string `toml:"link_usd_feed"` + UpkeepContractAddresses []string `toml:"upkeep_contracts"` + MultiCallAddress *string `toml:"multicall"` + Settings map[string]ContractSetting `toml:"Settings"` +} + +func (o *Contracts) Validate() error { + if o.LinkTokenAddress != nil && !common.IsHexAddress(*o.LinkTokenAddress) { + return errors.New("link_token must be a valid ethereum address") + } + if o.WethAddress != nil && !common.IsHexAddress(*o.WethAddress) { + return errors.New("weth must be a valid ethereum address") + } + if o.TranscoderAddress != nil && !common.IsHexAddress(*o.TranscoderAddress) { + return errors.New("transcoder must be a valid ethereum address") + } + if o.ChainModuleAddress != nil && !common.IsHexAddress(*o.ChainModuleAddress) { + return errors.New("chain_module must be a valid ethereum address") + } + if o.RegistryAddress != nil && !common.IsHexAddress(*o.RegistryAddress) { + return errors.New("registry must be a valid ethereum address") + } + if o.RegistrarAddress != nil && !common.IsHexAddress(*o.RegistrarAddress) { + return errors.New("registrar must be a valid ethereum address") + } + if o.LinkEthFeedAddress != nil && !common.IsHexAddress(*o.LinkEthFeedAddress) { + return errors.New("link_eth_feed must be a valid ethereum address") + } + if o.EthGasFeedAddress != nil && !common.IsHexAddress(*o.EthGasFeedAddress) { + return errors.New("eth_gas_feed must be a valid ethereum address") + } + if o.EthUSDFeedAddress != nil && !common.IsHexAddress(*o.EthUSDFeedAddress) { + return errors.New("eth_usd_feed must be a valid ethereum address") + } + if o.LinkUSDFeedAddress != nil && !common.IsHexAddress(*o.LinkUSDFeedAddress) { + return errors.New("link_usd_feed must be a valid ethereum address") + } + if o.MultiCallAddress != nil && !common.IsHexAddress(*o.MultiCallAddress) { + return errors.New("multicall must be a valid ethereum address") + } + if o.UpkeepContractAddresses != nil { + allEnabled := make(map[bool]int) + allConfigure := make(map[bool]int) + for _, address := range o.UpkeepContractAddresses { + if !common.IsHexAddress(address) { + return fmt.Errorf("upkeep_contracts must be valid ethereum addresses, but %s is not", address) + } + + if v, ok := o.Settings[address]; ok { + if v.ShouldBeUsed != nil { + allEnabled[*v.ShouldBeUsed]++ + } else { + allEnabled[true]++ + } + if v.Configure != nil { + allConfigure[*v.Configure]++ + } else { + allConfigure[true]++ + } + } + } + + if allEnabled[true] > 0 && allEnabled[false] > 0 { + return errors.New("either all or none offchain_aggregators must be used") + } + + if allConfigure[true] > 0 && allConfigure[false] > 0 { + return errors.New("either all or none offchain_aggregators must be configured") + } + } + + return nil +} + +func (c *Config) UseExistingContracts() bool { + if c.Contracts == nil { + return false + } + + if c.Contracts.ShouldBeUsed != nil { + return *c.Contracts.ShouldBeUsed + } + + return false +} + +func (c *Config) LinkTokenContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.LinkTokenAddress != nil { + return common.HexToAddress(*c.Contracts.LinkTokenAddress), nil + } + + return common.Address{}, errors.New("link token address must be set") +} + +func (c *Config) WethContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.WethAddress != nil { + return common.HexToAddress(*c.Contracts.WethAddress), nil + } + + return common.Address{}, errors.New("weth address must be set") +} + +func (c *Config) TranscoderContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.TranscoderAddress != nil { + return common.HexToAddress(*c.Contracts.TranscoderAddress), nil + } + + return common.Address{}, errors.New("transcoder address must be set") +} + +func (c *Config) ChainModuleContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.ChainModuleAddress != nil { + return common.HexToAddress(*c.Contracts.ChainModuleAddress), nil + } + + return common.Address{}, errors.New("chain module address must be set") +} + +func (c *Config) RegistryContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.RegistryAddress != nil { + return common.HexToAddress(*c.Contracts.RegistryAddress), nil + } + + return common.Address{}, errors.New("registry address must be set") +} + +func (c *Config) RegistrarContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.RegistrarAddress != nil { + return common.HexToAddress(*c.Contracts.RegistrarAddress), nil + } + + return common.Address{}, errors.New("registrar address must be set") +} + +func (c *Config) LinkEthFeedContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.LinkEthFeedAddress != nil { + return common.HexToAddress(*c.Contracts.LinkEthFeedAddress), nil + } + + return common.Address{}, errors.New("link eth feed address must be set") +} + +func (c *Config) EthGasFeedContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.EthGasFeedAddress != nil { + return common.HexToAddress(*c.Contracts.EthGasFeedAddress), nil + } + + return common.Address{}, errors.New("eth gas feed address must be set") +} + +func (c *Config) EthUSDFeedContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.EthUSDFeedAddress != nil { + return common.HexToAddress(*c.Contracts.EthUSDFeedAddress), nil + } + + return common.Address{}, errors.New("eth usd feed address must be set") +} + +func (c *Config) LinkUSDFeedContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.LinkUSDFeedAddress != nil { + return common.HexToAddress(*c.Contracts.LinkUSDFeedAddress), nil + } + + return common.Address{}, errors.New("link usd feed address must be set") +} + +func (c *Config) UpkeepContractAddresses() ([]common.Address, error) { + if c.Contracts != nil && c.Contracts.UpkeepContractAddresses != nil { + addresses := make([]common.Address, len(c.Contracts.UpkeepContractAddresses)) + for i, address := range c.Contracts.UpkeepContractAddresses { + addresses[i] = common.HexToAddress(address) + } + return addresses, nil + } + + return nil, errors.New("upkeep contract addresses must be set") +} + +func (c *Config) MultiCallContractAddress() (common.Address, error) { + if c.Contracts != nil && c.Contracts.MultiCallAddress != nil { + return common.HexToAddress(*c.Contracts.MultiCallAddress), nil + } + + return common.Address{}, errors.New("multicall address must be set") +} + +func (c *Config) UseExistingLinkTokenContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.LinkTokenAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.LinkTokenAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingWethContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.WethAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.WethAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingTranscoderContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.TranscoderAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.TranscoderAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingRegistryContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.RegistryAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.RegistryAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingRegistrarContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.RegistrarAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.RegistrarAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingLinkEthFeedContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.LinkEthFeedAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.LinkEthFeedAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingEthGasFeedContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.EthGasFeedAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.EthGasFeedAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingEthUSDFeedContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.EthUSDFeedAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.EthUSDFeedAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingLinkUSDFeedContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.LinkUSDFeedAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.LinkUSDFeedAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +func (c *Config) UseExistingUpkeepContracts() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.UpkeepContractAddresses == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + for _, address := range c.Contracts.UpkeepContractAddresses { + if v, ok := c.Contracts.Settings[address]; ok { + if v.ShouldBeUsed != nil && *v.ShouldBeUsed { + return true + } + } + } + + return false +} + +func (c *Config) UseExistingMultiCallContract() bool { + if !c.UseExistingContracts() { + return false + } + + if c.Contracts.MultiCallAddress == nil { + return false + } + + if len(c.Contracts.Settings) == 0 { + return true + } + + if v, ok := c.Contracts.Settings[*c.Contracts.MultiCallAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +type ContractSetting struct { + ShouldBeUsed *bool `toml:"use"` + Configure *bool `toml:"configure"` +} diff --git a/integration-tests/testconfig/automation/example.toml b/integration-tests/testconfig/automation/example.toml index 3b48e89a548..3bbe78d693d 100644 --- a/integration-tests/testconfig/automation/example.toml +++ b/integration-tests/testconfig/automation/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" @@ -163,5 +134,4 @@ use_prometheus=false # upgrade test specific override [TestAutomationNodeUpgrade.ChainlinkUpgradeImage] -image="public.ecr.aws/chainlink/chainlink" version="2.8.0" \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/benchmark/1000Upkeeps-1h-2_1.toml b/integration-tests/testconfig/automation/overrides/benchmark/1000Upkeeps-1h-2_1.toml new file mode 100644 index 00000000000..0b704524e9d --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/benchmark/1000Upkeeps-1h-2_1.toml @@ -0,0 +1,15 @@ +[ChainlinkImage] +version="latest" + +[Benchmark.Automation.Benchmark] +registry_to_test = "2_1" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 1000 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 10000 +perform_gas_to_burn = 1000 +block_range = 3600 +block_interval = 60 +forces_single_tx_key = false +delete_jobs_on_end = true \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/benchmark/1000Upkeeps-1h-2_3.toml b/integration-tests/testconfig/automation/overrides/benchmark/1000Upkeeps-1h-2_3.toml new file mode 100644 index 00000000000..f00bb5ed47b --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/benchmark/1000Upkeeps-1h-2_3.toml @@ -0,0 +1,15 @@ +[ChainlinkImage] +version="latest" + +[Benchmark.Automation.Benchmark] +registry_to_test = "2_3" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 1000 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 10000 +perform_gas_to_burn = 1000 +block_range = 3600 +block_interval = 60 +forces_single_tx_key = false +delete_jobs_on_end = true \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/load/500Upkeeps-1x-1h.toml b/integration-tests/testconfig/automation/overrides/load/500Upkeeps-1x-1h.toml new file mode 100644 index 00000000000..6d58253f526 --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/load/500Upkeeps-1x-1h.toml @@ -0,0 +1,47 @@ +[ChainlinkImage] +version="latest" + +[Load.Seth] +root_key_funds_buffer = 1_000_000 +ephemeral_addresses_number = 300 + +[Load.Seth.nonce_manager] +key_sync_timeout = "100s" + +[Load.Common] +chainlink_node_funding = 1000 + +[Load.Automation.AutomationConfig] +use_log_buffer_v1=false + +[Load.Automation.AutomationConfig.PluginConfig.LogProviderConfig] +block_rate=1 +log_limit=2 + +[Load.Automation] +[Load.Automation.General] +number_of_nodes=6 +duration=3600 +block_time=1 +spec_type="recommended" +chainlink_node_log_level="debug" +use_prometheus=true +remove_namespace = true + +[Load.Automation.DataStreams] +enabled=false + +[[Load.Automation.Load]] +number_of_upkeeps=500 +number_of_events = 1 +number_of_spam_matching_events = 0 +number_of_spam_non_matching_events = 0 +check_burn_amount = 0 +perform_burn_amount = 0 +upkeep_gas_limit = 1000000 +shared_trigger = false +is_streams_lookup = false +feeds = [] + +[Pyroscope] +enabled=false \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/load/50Upkeeps-1x-12h.toml b/integration-tests/testconfig/automation/overrides/load/50Upkeeps-1x-12h.toml new file mode 100644 index 00000000000..8991a6eb903 --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/load/50Upkeeps-1x-12h.toml @@ -0,0 +1,43 @@ +[ChainlinkImage] +version="latest" + +[Load.Seth] +root_key_funds_buffer = 1_000_000 + +[Load.Common] +chainlink_node_funding = 10000 + +[Load.Automation.AutomationConfig] +use_log_buffer_v1=false + +[Load.Automation.AutomationConfig.PluginConfig.LogProviderConfig] +block_rate=1 +log_limit=2 + +[Load.Automation] +[Load.Automation.General] +number_of_nodes=6 +duration=43200 +block_time=1 +spec_type="recommended" +chainlink_node_log_level="debug" +use_prometheus=true +remove_namespace = true + +[Load.Automation.DataStreams] +enabled=false + +[[Load.Automation.Load]] +number_of_upkeeps=50 +number_of_events = 1 +number_of_spam_matching_events = 0 +number_of_spam_non_matching_events = 0 +check_burn_amount = 0 +perform_burn_amount = 0 +upkeep_gas_limit = 1000000 +shared_trigger = false +is_streams_lookup = false +feeds = [] + +[Pyroscope] +enabled=false \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/load/50Upkeeps-1x-1h.toml b/integration-tests/testconfig/automation/overrides/load/50Upkeeps-1x-1h.toml new file mode 100644 index 00000000000..a133fce6dcf --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/load/50Upkeeps-1x-1h.toml @@ -0,0 +1,43 @@ +[ChainlinkImage] +version="latest" + +[Load.Seth] +root_key_funds_buffer = 1_000_000 + +[Load.Common] +chainlink_node_funding = 1000 + +[Load.Automation.AutomationConfig] +use_log_buffer_v1=false + +[Load.Automation.AutomationConfig.PluginConfig.LogProviderConfig] +block_rate=1 +log_limit=2 + +[Load.Automation] +[Load.Automation.General] +number_of_nodes=6 +duration=3600 +block_time=1 +spec_type="recommended" +chainlink_node_log_level="debug" +use_prometheus=true +remove_namespace = true + +[Load.Automation.DataStreams] +enabled=false + +[[Load.Automation.Load]] +number_of_upkeeps=50 +number_of_events = 1 +number_of_spam_matching_events = 0 +number_of_spam_non_matching_events = 0 +check_burn_amount = 0 +perform_burn_amount = 0 +upkeep_gas_limit = 1000000 +shared_trigger = false +is_streams_lookup = false +feeds = [] + +[Pyroscope] +enabled=false \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/soak/50Upkeeps-8h-2_1.toml b/integration-tests/testconfig/automation/overrides/soak/50Upkeeps-8h-2_1.toml new file mode 100644 index 00000000000..fda5cb6ea29 --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/soak/50Upkeeps-8h-2_1.toml @@ -0,0 +1,15 @@ +[ChainlinkImage] +version="latest" + +[Soak.Automation.Benchmark] +registry_to_test = "2_1" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 50 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 10000 +perform_gas_to_burn = 1000 +block_range = 28800 +block_interval = 300 +forces_single_tx_key = false +delete_jobs_on_end = true \ No newline at end of file diff --git a/integration-tests/testconfig/automation/overrides/soak/50Upkeeps-8h-2_3.toml b/integration-tests/testconfig/automation/overrides/soak/50Upkeeps-8h-2_3.toml new file mode 100644 index 00000000000..46ba1ad3e85 --- /dev/null +++ b/integration-tests/testconfig/automation/overrides/soak/50Upkeeps-8h-2_3.toml @@ -0,0 +1,15 @@ +[ChainlinkImage] +version="latest" + +[Soak.Automation.Benchmark] +registry_to_test = "2_3" +number_of_registries = 1 +number_of_nodes = 6 +number_of_upkeeps = 50 +upkeep_gas_limit = 1500000 +check_gas_to_burn = 10000 +perform_gas_to_burn = 1000 +block_range = 28800 +block_interval = 300 +forces_single_tx_key = false +delete_jobs_on_end = true \ No newline at end of file diff --git a/integration-tests/testconfig/ccip/ccip.toml b/integration-tests/testconfig/ccip/ccip.toml new file mode 100644 index 00000000000..5ccda6ab4e3 --- /dev/null +++ b/integration-tests/testconfig/ccip/ccip.toml @@ -0,0 +1,156 @@ +[Common] +# chainlink node funding in native token +chainlink_node_funding = 1 + +[Network] +selected_networks = ['SIMULATED_1', 'SIMULATED_2'] + +[Network.EVMNetworks.SIMULATED_1] +evm_name = 'chain-1337' +evm_chain_id = 1337 +evm_keys = [ + "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", +] +evm_simulated = true +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 50000 +evm_transaction_timeout = '2m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_depth = 1 + +[Network.EVMNetworks.SIMULATED_2] +evm_name = 'chain-2337' +evm_chain_id = 2337 +evm_keys = [ + "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", +] +evm_simulated = true +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 50000 +evm_transaction_timeout = '2m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_depth = 1 + +[NodeConfig] +BaseConfigTOML = """ +[Feature] +FeedsManager = true +LogPoller = true +UICSAKeys = true + +[Log] +Level = 'debug' +JSONConsole = true + +[Log.File] +MaxSize = '0b' + +[WebServer] +AllowOrigins = '*' +HTTPPort = 6688 +SecureCookies = false +HTTPWriteTimeout = '3m' +SessionTimeout = '999h0m0s' + +[WebServer.RateLimit] +Authenticated = 2000 +Unauthenticated = 1000 + +[WebServer.TLS] +HTTPSPort = 0 + +[Database] +MaxIdleConns = 20 +MaxOpenConns = 40 +MigrateOnStartup = true + +[OCR2] +Enabled = true +ContractPollInterval = '5s' + +[OCR] +Enabled = false +DefaultTransactionQueueDepth = 200 + +[P2P] +[P2P.V2] +Enabled = true +ListenAddresses = ['0.0.0.0:6690'] +AnnounceAddresses = ['0.0.0.0:6690'] +DeltaDial = '500ms' +DeltaReconcile = '5s' +""" + +CommonChainConfigTOML = """ +LogPollInterval = '500ms' +[Transactions] +ForwardersEnabled = false +[GasEstimator] +LimitDefault = 5000000 +""" + +[CCIP] +HomeChainSelector = '12922642891491394802' # for chain-2337 +FeedChainSelector = '3379446385462418246' # for chain-1337 + +[CCIP.CLNode] +NoOfPluginNodes = 4 +NoOfBootstraps = 1 + +[CCIP.PrivateEthereumNetworks.SIMULATED_1] +# either eth1 or eth2 (for post-Merge); for eth2 Prysm is used for consensus layer. +ethereum_version = "eth1" +# geth, besu, erigon or nethermind +execution_layer = "geth" +# eth2-only, if set to true environment startup will wait until at least 1 epoch has been finalised +wait_for_finalization=false + +[CCIP.PrivateEthereumNetworks.SIMULATED_1.EthereumChainConfig] +# eth2-only, the lower the value the faster the block production (3 is minimum) +seconds_per_slot = 3 +# eth2-only, the lower the value the faster the epoch finalisation (2 is minimum) +slots_per_epoch = 2 +# eht2-only, the lower tha value the faster the chain starts (10 is minimum) +genesis_delay = 15 +# eth2-only, number of validators +validator_count = 4 +chain_id = 1337 +# address that should be founded in genesis wih ETH +addresses_to_fund = [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", +] + + +#[CCIP.Env.PrivateEthereumNetworks.SIMULATED_1.CustomDockerImages] +# custom docker image that will be used for execution layer client. It has to be one of: hyperledger/besu, nethermind/nethermind, thorax/erigon or ethereum/client-go. +# instead of using a specific tag you can also use "latest_available" to use latest published tag in Github or "latest_stable" to use latest stable release from Github +# (if corresponding Docker image on Docker Hub has not been published environment creation will fail). +#execution_layer="hyperledger/besu:latest_stable" + +[CCIP.PrivateEthereumNetworks.SIMULATED_2] +ethereum_version = "eth1" +execution_layer = "geth" + +[CCIP.PrivateEthereumNetworks.SIMULATED_2.EthereumChainConfig] +seconds_per_slot = 3 +slots_per_epoch = 2 +genesis_delay = 15 +validator_count = 4 +chain_id = 2337 +addresses_to_fund = [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", +] + +[Seth] +# Seth specific configuration, no need for generating ephemeral addresses for ccip-tests. +ephemeral_addresses_number = 0 \ No newline at end of file diff --git a/integration-tests/testconfig/ccip/config.go b/integration-tests/testconfig/ccip/config.go new file mode 100644 index 00000000000..53c1afaeb0b --- /dev/null +++ b/integration-tests/testconfig/ccip/config.go @@ -0,0 +1,157 @@ +package ccip + +import ( + "fmt" + "strconv" + + "github.com/AlekSi/pointer" + chainselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + + "github.com/smartcontractkit/chainlink/integration-tests/client" +) + +const ( + E2E_JD_IMAGE = "E2E_JD_IMAGE" + E2E_JD_VERSION = "E2E_JD_VERSION" + E2E_JD_GRPC = "E2E_JD_GRPC" + E2E_JD_WSRPC = "E2E_JD_WSRPC" + DEFAULT_DB_NAME = "JD_DB" + DEFAULT_DB_VERSION = "14.1" +) + +var ( + ErrInvalidHomeChainSelector = fmt.Errorf("invalid home chain selector") + ErrInvalidFeedChainSelector = fmt.Errorf("invalid feed chain selector") +) + +type Config struct { + PrivateEthereumNetworks map[string]*ctfconfig.EthereumNetworkConfig `toml:",omitempty"` + CLNode *NodeConfig `toml:",omitempty"` + JobDistributorConfig JDConfig `toml:",omitempty"` + HomeChainSelector *string `toml:",omitempty"` + FeedChainSelector *string `toml:",omitempty"` + RMNConfig RMNConfig `toml:",omitempty"` +} + +type RMNConfig struct { + NoOfNodes *int `toml:",omitempty"` + ProxyImage *string `toml:",omitempty"` + ProxyVersion *string `toml:",omitempty"` + AFNImage *string `toml:",omitempty"` + AFNVersion *string `toml:",omitempty"` +} + +type NodeConfig struct { + NoOfPluginNodes *int `toml:",omitempty"` + NoOfBootstraps *int `toml:",omitempty"` + ClientConfig *client.ChainlinkConfig `toml:",omitempty"` +} + +type JDConfig struct { + Image *string `toml:",omitempty"` + Version *string `toml:",omitempty"` + DBName *string `toml:",omitempty"` + DBVersion *string `toml:",omitempty"` + JDGRPC *string `toml:",omitempty"` + JDWSRPC *string `toml:",omitempty"` +} + +// TODO: include all JD specific input in generic secret handling +func (o *JDConfig) GetJDGRPC() string { + grpc := pointer.GetString(o.JDGRPC) + if grpc == "" { + return ctfconfig.MustReadEnvVar_String(E2E_JD_GRPC) + } + return grpc +} + +func (o *JDConfig) GetJDWSRPC() string { + wsrpc := pointer.GetString(o.JDWSRPC) + if wsrpc == "" { + return ctfconfig.MustReadEnvVar_String(E2E_JD_WSRPC) + } + return wsrpc +} + +func (o *JDConfig) GetJDImage() string { + image := pointer.GetString(o.Image) + if image == "" { + return ctfconfig.MustReadEnvVar_String(E2E_JD_IMAGE) + } + return image +} + +func (o *JDConfig) GetJDVersion() string { + version := pointer.GetString(o.Version) + if version == "" { + return ctfconfig.MustReadEnvVar_String(E2E_JD_VERSION) + } + return version +} + +func (o *JDConfig) GetJDDBName() string { + dbname := pointer.GetString(o.DBName) + if dbname == "" { + return DEFAULT_DB_NAME + } + return dbname +} + +func (o *JDConfig) GetJDDBVersion() string { + dbversion := pointer.GetString(o.DBVersion) + if dbversion == "" { + return DEFAULT_DB_VERSION + } + return dbversion +} + +func (o *Config) Validate() error { + return nil +} + +func (o *Config) GetHomeChainSelector(evmNetworks []blockchain.EVMNetwork) (uint64, error) { + homeChainSelector, err := strconv.ParseUint(pointer.GetString(o.HomeChainSelector), 10, 64) + if err != nil { + return 0, err + } + isValid, err := IsSelectorValid(homeChainSelector, evmNetworks) + if err != nil { + return 0, err + } + if !isValid { + return 0, ErrInvalidHomeChainSelector + } + return homeChainSelector, nil +} + +func (o *Config) GetFeedChainSelector(evmNetworks []blockchain.EVMNetwork) (uint64, error) { + feedChainSelector, err := strconv.ParseUint(pointer.GetString(o.FeedChainSelector), 10, 64) + if err != nil { + return 0, err + } + isValid, err := IsSelectorValid(feedChainSelector, evmNetworks) + if err != nil { + return 0, err + } + if !isValid { + return 0, ErrInvalidFeedChainSelector + } + return feedChainSelector, nil +} + +func IsSelectorValid(selector uint64, evmNetworks []blockchain.EVMNetwork) (bool, error) { + chainId, err := chainselectors.ChainIdFromSelector(selector) + if err != nil { + return false, err + } + for _, net := range evmNetworks { + if net.ChainID == int64(chainId) { + return true, nil + } + } + return false, nil +} diff --git a/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml b/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml new file mode 100644 index 00000000000..06af64d5d91 --- /dev/null +++ b/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml @@ -0,0 +1,55 @@ +[Common] +# chainlink node funding in native token +chainlink_node_funding = 2 + +[Logging] +test_log_collect = true + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persisted +log_targets = ["loki"] + +[Network] +selected_networks = ['SEPOLIA', 'AVALANCHE_FUJI', 'BSC_TESTNET'] + +[Network.EVMNetworks.SEPOLIA] +evm_name = 'Sepolia Testnet' +evm_chain_id = 11155111 +evm_simulated = false +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '5m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_tag = true + +[Network.EVMNetworks.AVALANCHE_FUJI] +evm_name = 'Avalanche Fuji' +evm_chain_id = 43113 +evm_simulated = false +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '2m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_tag = true + +[Network.EVMNetworks.BSC_TESTNET] +evm_name = 'BSC Testnet' +evm_chain_id = 97 +evm_simulated = false +client_implementation = 'BSC' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '2m' +evm_minimum_confirmations = 3 +evm_gas_estimation_buffer = 0 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_tag = true + +[CCIP] +HomeChainSelector = '16015286601757825753' # for sepolia \ No newline at end of file diff --git a/integration-tests/testconfig/common/vrf/common.go b/integration-tests/testconfig/common/vrf/common.go index 326f7c98c76..49cb7c4f257 100644 --- a/integration-tests/testconfig/common/vrf/common.go +++ b/integration-tests/testconfig/common/vrf/common.go @@ -4,7 +4,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { diff --git a/integration-tests/testconfig/configs_embed.go b/integration-tests/testconfig/configs_embed.go index 31303357a43..5de81acb7d9 100644 --- a/integration-tests/testconfig/configs_embed.go +++ b/integration-tests/testconfig/configs_embed.go @@ -18,6 +18,8 @@ import "embed" //go:embed vrf/vrf.toml //go:embed vrfv2/vrfv2.toml //go:embed vrfv2plus/vrfv2plus.toml +//go:embed ccip/ccip.toml + var embeddedConfigsFs embed.FS func init() { diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 9609c6175d3..496a11b64b1 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -2,6 +2,11 @@ # set to true to flush logs to selected target regardless of test result; otherwise logs are only flushed if test failed test_log_collect = false +[Logging.Grafana] +base_url="https://grafana.ops.prod.cldev.sh" +base_url_github_ci="http://localhost:8080/primary" +dashboard_url="/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + [Logging.LogStream] # supported targets: file, loki, in-memory. if empty no logs will be persisted log_targets = ["file"] @@ -13,10 +18,9 @@ log_producer_retry_limit = 10 [ChainlinkImage] # postgres version to use postgres_version = "15.6" -# chainlink image to use -image = "public.ecr.aws/chainlink/chainlink" # chainlink image tag to use version = "2.12.0" +# Set chainlink image using E2E_TEST_CHAINLINK_IMAGE env, as it is a test secret [Common] # chainlink node funding in native token @@ -255,66 +259,14 @@ gas_tip_cap = 1_800_000_000 [[Seth.networks]] name = "Sepolia Testnet" transaction_timeout = "3m" -eip_1559_dynamic_fees = false - -# automated gas estimation for live networks -# if set to true we will dynamically estimate gas for every transaction (based on suggested values, priority and congestion rate for last X blocks) -# gas_price_estimation_enabled = true -# number of blocks to use for congestion rate estimation (it will determine buffer added on top of suggested values) -# gas_price_estimation_blocks = 100 -# transaction priority, which determines adjustment factor multiplier applied to suggested values (fast - 1.2x, standard - 1x, slow - 0.8x) -# gas_price_estimation_tx_priority = "standard" - -# URLs -# if set they will overwrite URLs from EVMNetwork that Seth uses, can be either WS(S) or HTTP(S) -# urls_secret = ["ws://your-ws-url:8546"] - -# gas_limits -# gas limit should be explicitly set only if you are connecting to a node that's incapable of estimating gas limit itself (should only happen for very old versions) -# gas_limit = 14_000_000 -# transfer_gas_fee is gas limit that will be used, when funding CL nodes and returning funds from there and when funding and returning funds from ephemeral keys -# we use hardcoded value in order to be estimate how much funds are available for sending or returning after tx costs have been paid -transfer_gas_fee = 21_000 - -# manual settings, used when gas_price_estimation_enabled is false or when it fails -# legacy transactions -gas_price = 50_000_000_000 - -# EIP-1559 transactions -gas_fee_cap = 45_000_000_000 -gas_tip_cap = 10_000_000_000 - -[[Seth.networks]] -name = "Polygon Mumbai" -transaction_timeout = "3m" eip_1559_dynamic_fees = true - -# automated gas estimation for live networks -# if set to true we will dynamically estimate gas for every transaction (based on suggested values, priority and congestion rate for last X blocks) -# gas_price_estimation_enabled = true -# number of blocks to use for congestion rate estimation (it will determine buffer added on top of suggested values) -# gas_price_estimation_blocks = 100 -# transaction priority, which determines adjustment factor multiplier applied to suggested values (fast - 1.2x, standard - 1x, slow - 0.8x) -# gas_price_estimation_tx_priority = "standard" - -# URLs -# if set they will overwrite URLs from EVMNetwork that Seth uses, can be either WS(S) or HTTP(S) -# urls_secret = ["ws://your-ws-url:8546"] - -# gas_limits -# gas limit should be explicitly set only if you are connecting to a node that's incapable of estimating gas limit itself (should only happen for very old versions) -# gas_limit = 6_000_000 -# transfer_gas_fee is gas limit that will be used, when funding CL nodes and returning funds from there and when funding and returning funds from ephemeral keys -# we use hardcoded value in order to be estimate how much funds are available for sending or returning after tx costs have been paid transfer_gas_fee = 21_000 - -# manual settings, used when gas_price_estimation_enabled is false or when it fails -# legacy transactions -gas_price = 1_800_000_000 - -# EIP-1559 transactions -gas_fee_cap = 3_800_000_000 -gas_tip_cap = 1_800_000_000 +gas_price = 105_000_000_000 +gas_fee_cap = 150_312_843_059 +gas_tip_cap = 40_416_094 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" [[Seth.networks]] name = "Polygon Amoy" @@ -323,11 +275,11 @@ eip_1559_dynamic_fees = true # automated gas estimation for live networks # if set to true we will dynamically estimate gas for every transaction (based on suggested values, priority and congestion rate for last X blocks) -# gas_price_estimation_enabled = true +gas_price_estimation_enabled = true # number of blocks to use for congestion rate estimation (it will determine buffer added on top of suggested values) -# gas_price_estimation_blocks = 100 +gas_price_estimation_blocks = 100 # transaction priority, which determines adjustment factor multiplier applied to suggested values (fast - 1.2x, standard - 1x, slow - 0.8x) -# gas_price_estimation_tx_priority = "standard" +gas_price_estimation_tx_priority = "standard" # URLs # if set they will overwrite URLs from EVMNetwork that Seth uses, can be either WS(S) or HTTP(S) @@ -346,39 +298,7 @@ gas_price = 200_000_000_000 # EIP-1559 transactions gas_fee_cap = 200_000_000_000 -gas_tip_cap = 2_000_000_000 - -[[Seth.networks]] -name = "Polygon zkEVM Goerli" -transaction_timeout = "3m" -eip_1559_dynamic_fees = false - -# automated gas estimation for live networks -# if set to true we will dynamically estimate gas for every transaction (based on suggested values, priority and congestion rate for last X blocks) -# gas_price_estimation_enabled = true -# number of blocks to use for congestion rate estimation (it will determine buffer added on top of suggested values) -# gas_price_estimation_blocks = 100 -# transaction priority, which determines adjustment factor multiplier applied to suggested values (fast - 1.2x, standard - 1x, slow - 0.8x) -# gas_price_estimation_tx_priority = "standard" - -# URLs -# if set they will overwrite URLs from EVMNetwork that Seth uses, can be either WS(S) or HTTP(S) -# urls_secret = ["ws://your-ws-url:8546"] - -# gas_limits -# gas limit should be explicitly set only if you are connecting to a node that's incapable of estimating gas limit itself (should only happen for very old versions) -# gas_limit = 9_000_000 -# transfer_gas_fee is gas limit that will be used, when funding CL nodes and returning funds from there and when funding and returning funds from ephemeral keys -# we use hardcoded value in order to be estimate how much funds are available for sending or returning after tx costs have been paid -transfer_gas_fee = 21_000 - -# manual settings, used when gas_price_estimation_enabled is false or when it fails -# legacy transactions -gas_price = 50_000_000 - -# EIP-1559 transactions -gas_fee_cap = 3_800_000_000 -gas_tip_cap = 1_800_000_000 +gas_tip_cap = 25_000_000_000 [[Seth.networks]] name = "Optimism Sepolia" @@ -602,3 +522,148 @@ evm_gas_estimation_buffer = 10000 evm_supports_eip1559 = true evm_default_gas_limit = 6000000 evm_chain_id = 5668 + +[[Seth.networks]] +name = "LINEA_SEPOLIA" +chain_id = "59141" +transaction_timeout = "10m" +transfer_gas_fee = 21_000 +gas_price = 200_000_000_000_000 +eip_1559_dynamic_fees = false +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "LINEA_MAINNET" +chain_id = "59144" +transaction_timeout = "10m" +transfer_gas_fee = 21_000 +gas_price = 200_000_000_000_000 +eip_1559_dynamic_fees = false +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "ZKSYNC_SEPOLIA" +chain_id = "300" +transaction_timeout = "3m" +transfer_gas_fee = 21_000 +gas_price = 200_000_000_000 +eip_1559_dynamic_fees = true +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "ZKSYNC_MAINNET" +chain_id = "324" +transaction_timeout = "3m" +transfer_gas_fee = 21_000 +gas_price = 200_000_000_000 +eip_1559_dynamic_fees = true +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "POLYGON_ZKEVM_CARDONA" +transaction_timeout = "3m" +transfer_gas_fee = 21_000 +gas_price = 743_000_000 +eip_1559_dynamic_fees = false +gas_fee_cap = 1_725_800_000 +gas_tip_cap = 822_800_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "HEDERA_TESTNET" +transaction_timeout = "3m" +transfer_gas_fee = 800_000 +gas_limit = 2_000_000 +gas_price = 2_500_000_000_000 +eip_1559_dynamic_fees = false +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "TREASURE_RUBY" +transaction_timeout = "10m" +transfer_gas_fee = 21_000 +gas_price = 100_000_000 +eip_1559_dynamic_fees = true +gas_fee_cap = 200_000_000 +gas_tip_cap = 100_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "XLAYER_MAINNET" +transaction_timeout = "10m" +transfer_gas_fee = 21_000 +gas_price = 13_400_000_000 +eip_1559_dynamic_fees = false +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 500 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "XLAYER_SEPOLIA" +transaction_timeout = "10m" +transfer_gas_fee = 21_000 +gas_price = 200_000_000_000 +eip_1559_dynamic_fees = false +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 500 +gas_price_estimation_tx_priority = "standard" + +[[Seth.networks]] +name = "POLYGON_MAINNET" +transaction_timeout = "3m" +transfer_gas_fee = 21_000 +gas_price = 31_000_000_000 +eip_1559_dynamic_fees = true +gas_fee_cap = 61_000_000_000 +gas_tip_cap = 30_000_000_000 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 + +[[Seth.networks]] +name = "ARBITRUM_MAINNET" +transaction_timeout = "10m" +transfer_gas_fee = 21_000 +gas_price = 10_000_000 +eip_1559_dynamic_fees = true +gas_fee_cap = 10_000_000 +gas_tip_cap = 0 +gas_price_estimation_enabled = true +gas_price_estimation_blocks = 1000 + +#### + +[Network.EVMNetworks.SONEIUM_SEPOLIA] +evm_name = "SONEIUM_SEPOLIA" +evm_chain_id = 1946 +client_implementation = "Optimism" +evm_simulated = false + +#### diff --git a/integration-tests/testconfig/forwarder_ocr/example.toml b/integration-tests/testconfig/forwarder_ocr/example.toml index 0b762299af1..517a341f803 100644 --- a/integration-tests/testconfig/forwarder_ocr/example.toml +++ b/integration-tests/testconfig/forwarder_ocr/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -31,7 +30,7 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" @@ -39,15 +38,6 @@ bearer_token_secret="my-awesome-token" [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" @@ -143,6 +133,9 @@ BumpPercent = 20 BumpMin = '100 gwei' """ +[OCR.Common] +number_of_contracts=1 + # load test specific configuration [Load.OCR] [Load.OCR.Common] @@ -162,9 +155,8 @@ chainlink_node_funding = 100 [Soak.OCR] [Soak.OCR.Common] +number_of_contracts=2 test_duration="15m" [Soak.OCR.Soak] -ocr_version="1" -number_of_contracts=2 -time_between_rounds="1m" \ No newline at end of file +time_between_rounds="1m" diff --git a/integration-tests/testconfig/forwarder_ocr/forwarder_ocr.toml b/integration-tests/testconfig/forwarder_ocr/forwarder_ocr.toml index 8fa0fa5db25..68ed21404f3 100644 --- a/integration-tests/testconfig/forwarder_ocr/forwarder_ocr.toml +++ b/integration-tests/testconfig/forwarder_ocr/forwarder_ocr.toml @@ -57,7 +57,10 @@ MinContractPayment = 0 [Transactions] ForwardersEnabled = true - """ +""" + +[OCR.Common] +number_of_contracts=1 # load test specific configuration [Load.OCR] @@ -92,8 +95,8 @@ chainlink_node_funding = 0.5 [Soak.OCR] [Soak.OCR.Common] +number_of_contracts=2 test_duration = "15m" [Soak.OCR.Soak] -number_of_contracts = 2 -time_between_rounds = "1m" +time_between_rounds="1m" diff --git a/integration-tests/testconfig/forwarder_ocr2/example.toml b/integration-tests/testconfig/forwarder_ocr2/example.toml index b3bc45d270c..3ec3e4c690a 100644 --- a/integration-tests/testconfig/forwarder_ocr2/example.toml +++ b/integration-tests/testconfig/forwarder_ocr2/example.toml @@ -31,7 +31,7 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" @@ -39,15 +39,6 @@ bearer_token_secret="my-awesome-token" [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" @@ -143,12 +134,15 @@ BumpPercent = 20 BumpMin = '100 gwei' """ +[OCR2.Common] +number_of_contracts=1 + # load test specific configuration -[Load.OCR] -[Load.OCR.Common] +[Load.OCR2] +[Load.OCR2.Common] eth_funds = 3 -[Load.OCR.Load] +[Load.OCR2.Load] test_duration = "3m" rate_limit_unit_duration = "1m" rate = 3 @@ -160,11 +154,10 @@ ea_change_interval = "5s" [Soak.Common] chainlink_node_funding = 100 -[Soak.OCR] -[Soak.OCR.Common] +[Soak.OCR2] +[Soak.OCR2.Common] +number_of_contracts=2 test_duration="15m" -[Soak.OCR.Soak] -ocr_version="1" -number_of_contracts=2 -time_between_rounds="1m" \ No newline at end of file +[Soak.OCR2.Soak] +time_between_rounds="1m" diff --git a/integration-tests/testconfig/forwarder_ocr2/forwarder_ocr2.toml b/integration-tests/testconfig/forwarder_ocr2/forwarder_ocr2.toml index 3f2a8610a83..76d5695a8b6 100644 --- a/integration-tests/testconfig/forwarder_ocr2/forwarder_ocr2.toml +++ b/integration-tests/testconfig/forwarder_ocr2/forwarder_ocr2.toml @@ -53,7 +53,10 @@ MinContractPayment = 0 [Transactions] ForwardersEnabled = true - """ +""" + +[OCR2.Common] +number_of_contracts=1 # load test specific configuration [Load.OCR2.Common] @@ -85,10 +88,10 @@ ea_change_interval = "5s" chainlink_node_funding = 1 [Soak.OCR2.Common] +number_of_contracts=2 test_duration="15m" [Soak.OCR2.Soak] -number_of_contracts=2 time_between_rounds="1m" diff --git a/integration-tests/testconfig/functions/config.go b/integration-tests/testconfig/functions/config.go index 88c0e052951..03adc2f1ec0 100644 --- a/integration-tests/testconfig/functions/config.go +++ b/integration-tests/testconfig/functions/config.go @@ -6,8 +6,8 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/net" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/net" ) const ( diff --git a/integration-tests/testconfig/functions/example.toml b/integration-tests/testconfig/functions/example.toml index 7502a6fc440..74d931632a8 100644 --- a/integration-tests/testconfig/functions/example.toml +++ b/integration-tests/testconfig/functions/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use simulated network [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" diff --git a/integration-tests/testconfig/job_distributor/job_distributor.toml b/integration-tests/testconfig/job_distributor/job_distributor.toml new file mode 100644 index 00000000000..6dae45fb140 --- /dev/null +++ b/integration-tests/testconfig/job_distributor/job_distributor.toml @@ -0,0 +1,46 @@ +[NodeConfig] +BaseConfigTOML = """ +[Feature] +FeedsManager = true +LogPoller = true +UICSAKeys = true +MultiFeedsManagers = true + +[Log] +Level = 'debug' +JSONConsole = true + +[Log.File] +MaxSize = '0b' + +[WebServer] +AllowOrigins = '*' +HTTPPort = 6688 +SecureCookies = false +HTTPWriteTimeout = '3m' +SessionTimeout = '999h0m0s' + +[WebServer.RateLimit] +Authenticated = 2000 +Unauthenticated = 1000 + +[WebServer.TLS] +HTTPSPort = 0 + +[Database] +MaxIdleConns = 20 +MaxOpenConns = 40 +MigrateOnStartup = true + +[OCR] +Enabled = true +DefaultTransactionQueueDepth = 0 + +[P2P] +[P2P.V2] +Enabled = true +ListenAddresses = ['0.0.0.0:6690'] +AnnounceAddresses = ['0.0.0.0:6690'] +DeltaDial = '500ms' +DeltaReconcile = '5s' +""" diff --git a/integration-tests/testconfig/keeper/config.go b/integration-tests/testconfig/keeper/config.go index 0e11266d39f..81a88ef67eb 100644 --- a/integration-tests/testconfig/keeper/config.go +++ b/integration-tests/testconfig/keeper/config.go @@ -1,110 +1,8 @@ package keeper -import ( - "errors" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" -) - type Config struct { - Common *Common `toml:"Common"` - Resiliency *ResiliencyConfig `toml:"Resiliency"` } func (c *Config) Validate() error { - if c.Common == nil { - return nil - } - if err := c.Common.Validate(); err != nil { - return err - } - if c.Resiliency == nil { - return nil - } - return c.Resiliency.Validate() -} - -type Common struct { - RegistryToTest *string `toml:"registry_to_test"` - NumberOfRegistries *int `toml:"number_of_registries"` - NumberOfNodes *int `toml:"number_of_nodes"` - NumberOfUpkeeps *int `toml:"number_of_upkeeps"` - UpkeepGasLimit *int64 `toml:"upkeep_gas_limit"` - CheckGasToBurn *int64 `toml:"check_gas_to_burn"` - PerformGasToBurn *int64 `toml:"perform_gas_to_burn"` - MaxPerformGas *int64 `toml:"max_perform_gas"` - BlockRange *int64 `toml:"block_range"` - BlockInterval *int64 `toml:"block_interval"` - ForceSingleTxKey *bool `toml:"forces_single_tx_key"` - DeleteJobsOnEnd *bool `toml:"delete_jobs_on_end"` - RegistryAddress *string `toml:"registry_address"` - RegistrarAddress *string `toml:"registrar_address"` - LinkTokenAddress *string `toml:"link_token_address"` - EthFeedAddress *string `toml:"eth_feed_address"` - GasFeedAddress *string `toml:"gas_feed_address"` -} - -func (c *Common) Validate() error { - if c.RegistryToTest == nil || *c.RegistryToTest == "" { - return errors.New("registry_to_test must be set") - } - if c.NumberOfRegistries == nil || *c.NumberOfRegistries <= 0 { - return errors.New("number_of_registries must be a positive integer") - } - if c.NumberOfNodes == nil || *c.NumberOfNodes <= 0 { - return errors.New("number_of_nodes must be a positive integer") - } - if c.NumberOfUpkeeps == nil || *c.NumberOfUpkeeps <= 0 { - return errors.New("number_of_upkeeps must be a positive integer") - } - if c.UpkeepGasLimit == nil || *c.UpkeepGasLimit <= 0 { - return errors.New("upkeep_gas_limit must be a positive integer") - } - if c.CheckGasToBurn == nil || *c.CheckGasToBurn <= 0 { - return errors.New("check_gas_to_burn must be a positive integer") - } - if c.PerformGasToBurn == nil || *c.PerformGasToBurn <= 0 { - return errors.New("perform_gas_to_burn must be a positive integer") - } - if c.MaxPerformGas == nil || *c.MaxPerformGas <= 0 { - return errors.New("max_perform_gas must be a positive integer") - } - if c.BlockRange == nil || *c.BlockRange <= 0 { - return errors.New("block_range must be a positive integer") - } - if c.BlockInterval == nil || *c.BlockInterval <= 0 { - return errors.New("block_interval must be a positive integer") - } - if c.RegistryAddress == nil { - c.RegistryAddress = new(string) - } - if c.RegistrarAddress == nil { - c.RegistrarAddress = new(string) - } - if c.LinkTokenAddress == nil { - c.LinkTokenAddress = new(string) - } - if c.EthFeedAddress == nil { - c.EthFeedAddress = new(string) - } - if c.GasFeedAddress == nil { - c.GasFeedAddress = new(string) - } - return nil -} - -type ResiliencyConfig struct { - ContractCallLimit *uint `toml:"contract_call_limit"` - ContractCallInterval *blockchain.StrDuration `toml:"contract_call_interval"` -} - -func (c *ResiliencyConfig) Validate() error { - if c.ContractCallLimit == nil { - return errors.New("contract_call_limit must be set") - } - if c.ContractCallInterval == nil { - return errors.New("contract_call_interval must be set") - } - return nil } diff --git a/integration-tests/testconfig/keeper/example.toml b/integration-tests/testconfig/keeper/example.toml index 5abb5835629..4efbf974827 100644 --- a/integration-tests/testconfig/keeper/example.toml +++ b/integration-tests/testconfig/keeper/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" diff --git a/integration-tests/testconfig/keeper/keeper.toml b/integration-tests/testconfig/keeper/keeper.toml index 39eae1ea53c..d483d6df493 100644 --- a/integration-tests/testconfig/keeper/keeper.toml +++ b/integration-tests/testconfig/keeper/keeper.toml @@ -32,131 +32,4 @@ HTTPSPort = 0 [Keeper] TurnLookBack = 0 -""" - -[Keeper.Common] -registry_to_test = "2_1" -number_of_registries = 1 -number_of_nodes = 6 -number_of_upkeeps = 500 -upkeep_gas_limit = 1500000 -check_gas_to_burn = 100000 -perform_gas_to_burn = 50000 -max_perform_gas = 5000000 -block_range = 100 -block_interval = 20 -forces_single_tx_key = false -delete_jobs_on_end = true - -# will retry roughly for 1h before giving up (900 * 4s) -[Keeper.Resiliency] -# number of retries before giving up -contract_call_limit = 900 -# static interval between retries -contract_call_interval = "4s" - -[Seth] -# keeper benchmark running on simulated network requires 100k per node -root_key_funds_buffer = 1_000_000 - -[Benchmark.Keeper.Common] -registry_to_test = "2_1" -number_of_registries = 1 -number_of_nodes = 6 -number_of_upkeeps = 1000 -upkeep_gas_limit = 1500000 -check_gas_to_burn = 10000 -perform_gas_to_burn = 1000 -max_perform_gas = 5000000 -block_range = 3600 -block_interval = 60 -forces_single_tx_key = false -delete_jobs_on_end = true - -[Benchmark.NodeConfig] -BaseConfigTOML = """ -[Feature] -LogPoller = true - -[OCR2] -Enabled = true - -[P2P] -[P2P.V2] -Enabled = true -AnnounceAddresses = ["0.0.0.0:6690"] -ListenAddresses = ["0.0.0.0:6690"] -[Keeper] -TurnLookBack = 0 -[WebServer] -HTTPWriteTimeout = '1h' -""" - -CommonChainConfigTOML = """ -""" - -[Benchmark.NodeConfig.ChainConfigTOMLByChainID] -# applicable for simulated chain -1337 = """ -FinalityDepth = 50 -LogPollInterval = '1s' -MinIncomingConfirmations = 1 - -[HeadTracker] -HistoryDepth = 100 - -[GasEstimator] -Mode = 'FixedPrice' -LimitDefault = 5_000_000 -""" - -[Soak.Keeper.Common] -registry_to_test = "2_1" -number_of_registries = 1 -number_of_nodes = 6 -number_of_upkeeps = 50 -upkeep_gas_limit = 1500000 -check_gas_to_burn = 10000 -perform_gas_to_burn = 1000 -max_perform_gas = 5000000 -block_range = 28800 -block_interval = 300 -forces_single_tx_key = false -delete_jobs_on_end = true - -[Soak.NodeConfig] -BaseConfigTOML = """ -[Feature] -LogPoller = true - -[OCR2] -Enabled = true - -[P2P] -[P2P.V2] -Enabled = true -AnnounceAddresses = ["0.0.0.0:6690"] -ListenAddresses = ["0.0.0.0:6690"] -[Keeper] -TurnLookBack = 0 -[WebServer] -HTTPWriteTimeout = '1h' -""" - -CommonChainConfigTOML = """ -""" - -[Soak.NodeConfig.ChainConfigTOMLByChainID] -# applicable for simulated chain -1337 = """ -FinalityDepth = 50 -LogPollInterval = '1s' -MinIncomingConfirmations = 1 - -[HeadTracker] -HistoryDepth = 100 - -[GasEstimator] -Mode = 'FixedPrice' -LimitDefault = 5_000_000 -""" +""" \ No newline at end of file diff --git a/integration-tests/testconfig/log_poller/config.go b/integration-tests/testconfig/log_poller/config.go index f6e3249432a..00b61f6b1b9 100644 --- a/integration-tests/testconfig/log_poller/config.go +++ b/integration-tests/testconfig/log_poller/config.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type GeneratorType = string diff --git a/integration-tests/testconfig/log_poller/example.toml b/integration-tests/testconfig/log_poller/example.toml index c28d36ae12f..78f3b5482d9 100644 --- a/integration-tests/testconfig/log_poller/example.toml +++ b/integration-tests/testconfig/log_poller/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" diff --git a/integration-tests/testconfig/node/example.toml b/integration-tests/testconfig/node/example.toml index 510379b4f05..bc5628e46b3 100644 --- a/integration-tests/testconfig/node/example.toml +++ b/integration-tests/testconfig/node/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" @@ -77,5 +48,4 @@ chainlink_node_funding = 0.5 # Test-specific part [ChainlinkUpgradeImage] -image="public.ecr.aws/chainlink/chainlink" version="2.8.0" \ No newline at end of file diff --git a/integration-tests/testconfig/ocr/example.toml b/integration-tests/testconfig/ocr/example.toml index 92262241dff..7c1c755567f 100644 --- a/integration-tests/testconfig/ocr/example.toml +++ b/integration-tests/testconfig/ocr/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -31,7 +30,7 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" @@ -39,15 +38,6 @@ bearer_token_secret="my-awesome-token" [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" @@ -142,6 +132,9 @@ BumpPercent = 20 BumpMin = '100 gwei' """ +[OCR.Common] +number_of_contracts=1 + # load test specific configuration [Load.OCR] [Load.OCR.Common] @@ -161,8 +154,8 @@ chainlink_node_funding = 100 [Soak.OCR] [Soak.OCR.Common] +number_of_contracts=2 test_duration="15m" [Soak.OCR.Soak] -number_of_contracts=2 time_between_rounds="1m" diff --git a/integration-tests/testconfig/ocr/ocr.go b/integration-tests/testconfig/ocr/ocr.go index f23d6473643..240fd2afeaa 100644 --- a/integration-tests/testconfig/ocr/ocr.go +++ b/integration-tests/testconfig/ocr/ocr.go @@ -2,15 +2,19 @@ package ocr import ( "errors" + "fmt" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { - Soak *SoakConfig `toml:"Soak"` - Load *Load `toml:"Load"` - Volume *Volume `toml:"Volume"` - Common *Common `toml:"Common"` + Soak *SoakConfig `toml:"Soak"` + Load *Load `toml:"Load"` + Volume *Volume `toml:"Volume"` + Common *Common `toml:"Common"` + Contracts *Contracts `toml:"Contracts"` } func (o *Config) Validate() error { @@ -29,15 +33,24 @@ func (o *Config) Validate() error { return err } } + if o.Contracts != nil { + if err := o.Contracts.Validate(); err != nil { + return err + } + } return nil } type Common struct { - ETHFunds *int `toml:"eth_funds"` - TestDuration *blockchain.StrDuration `toml:"test_duration"` + NumberOfContracts *int `toml:"number_of_contracts"` + ETHFunds *int `toml:"eth_funds"` + TestDuration *blockchain.StrDuration `toml:"test_duration"` } func (o *Common) Validate() error { + if o.NumberOfContracts != nil && *o.NumberOfContracts < 1 { + return errors.New("when number_of_contracts is set, it must be greater than 0") + } if o.ETHFunds != nil && *o.ETHFunds < 0 { return errors.New("eth_funds must be set and cannot be negative") } @@ -117,16 +130,169 @@ func (o *Volume) Validate() error { } type SoakConfig struct { - NumberOfContracts *int `toml:"number_of_contracts"` TimeBetweenRounds *blockchain.StrDuration `toml:"time_between_rounds"` } func (o *SoakConfig) Validate() error { - if o.NumberOfContracts == nil || *o.NumberOfContracts <= 1 { - return errors.New("number_of_contracts must be set and be greater than 1") - } if o.TimeBetweenRounds == nil || o.TimeBetweenRounds.Duration == 0 { return errors.New("time_between_rounds must be set and be a positive integer") } return nil } + +// For more information on the configuration of contracts, see https://smartcontract-it.atlassian.net/wiki/spaces/TT/pages/828407894/Contracts+addresses+in+TOML+convention +type Contracts struct { + ShouldBeUsed *bool `toml:"use"` + LinkTokenAddress *string `toml:"link_token"` + OffChainAggregatorAddresses []string `toml:"offchain_aggregators"` + Settings map[string]ContractSetting `toml:"Settings"` +} + +func (o *Contracts) Validate() error { + if o.LinkTokenAddress != nil && !common.IsHexAddress(*o.LinkTokenAddress) { + return errors.New("link_token must be a valid ethereum address") + } + if o.OffChainAggregatorAddresses != nil { + allEnabled := make(map[bool]int) + allConfigure := make(map[bool]int) + for _, address := range o.OffChainAggregatorAddresses { + if !common.IsHexAddress(address) { + return fmt.Errorf("offchain_aggregators must be valid ethereum addresses, but %s is not", address) + } + + if v, ok := o.Settings[address]; ok { + if v.ShouldBeUsed != nil { + allEnabled[*v.ShouldBeUsed]++ + } else { + allEnabled[true]++ + } + if v.Configure != nil { + allConfigure[*v.Configure]++ + } else { + allConfigure[true]++ + } + } + } + + if allEnabled[true] > 0 && allEnabled[false] > 0 { + return errors.New("either all or none offchain_aggregators must be used") + } + + if allConfigure[true] > 0 && allConfigure[false] > 0 { + return errors.New("either all or none offchain_aggregators must be configured") + } + } + + return nil +} + +func (o *Config) UseExistingContracts() bool { + if o.Contracts == nil { + return false + } + + if o.Contracts.ShouldBeUsed != nil { + return *o.Contracts.ShouldBeUsed + } + + return false +} + +func (o *Config) LinkTokenContractAddress() (common.Address, error) { + if o.Contracts != nil && o.Contracts.LinkTokenAddress != nil { + return common.HexToAddress(*o.Contracts.LinkTokenAddress), nil + } + + return common.Address{}, errors.New("link token address must be set") +} + +func (o *Config) UseExistingLinkTokenContract() bool { + if !o.UseExistingContracts() { + return false + } + + if o.Contracts.LinkTokenAddress == nil { + return false + } + + if len(o.Contracts.Settings) == 0 { + return true + } + + if v, ok := o.Contracts.Settings[*o.Contracts.LinkTokenAddress]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + + return true +} + +type ContractSetting struct { + ShouldBeUsed *bool `toml:"use"` + Configure *bool `toml:"configure"` +} + +type OffChainAggregatorsConfig interface { + OffChainAggregatorsContractsAddresses() []common.Address + UseExistingOffChainAggregatorsContracts() bool + ConfigureExistingOffChainAggregatorsContracts() bool + NumberOfContractsToDeploy() int +} + +func (o *Config) UseExistingOffChainAggregatorsContracts() bool { + if !o.UseExistingContracts() { + return false + } + + if len(o.Contracts.OffChainAggregatorAddresses) == 0 { + return false + } + + if len(o.Contracts.Settings) == 0 { + return true + } + + for _, address := range o.Contracts.OffChainAggregatorAddresses { + if v, ok := o.Contracts.Settings[address]; ok { + return v.ShouldBeUsed != nil && *v.ShouldBeUsed + } + } + + return true +} + +func (o *Config) OffChainAggregatorsContractsAddresses() []common.Address { + var ocrInstanceAddresses []common.Address + if !o.UseExistingOffChainAggregatorsContracts() { + return ocrInstanceAddresses + } + + for _, address := range o.Contracts.OffChainAggregatorAddresses { + ocrInstanceAddresses = append(ocrInstanceAddresses, common.HexToAddress(address)) + } + + return ocrInstanceAddresses +} + +func (o *Config) ConfigureExistingOffChainAggregatorsContracts() bool { + if !o.UseExistingOffChainAggregatorsContracts() { + return true + } + + for _, address := range o.Contracts.OffChainAggregatorAddresses { + for maybeOcrAddress, setting := range o.Contracts.Settings { + if maybeOcrAddress == address { + return setting.Configure != nil && *setting.Configure + } + } + } + + return true +} + +func (o *Config) NumberOfContractsToDeploy() int { + if o.Common != nil && o.Common.NumberOfContracts != nil { + return *o.Common.NumberOfContracts + } + + return 0 +} diff --git a/integration-tests/testconfig/ocr/ocr.toml b/integration-tests/testconfig/ocr/ocr.toml index 17ee4d7b687..36cded0b85c 100644 --- a/integration-tests/testconfig/ocr/ocr.toml +++ b/integration-tests/testconfig/ocr/ocr.toml @@ -43,6 +43,9 @@ Enabled = true ListenAddresses = ['0.0.0.0:6690'] """ +[OCR.Common] +number_of_contracts=1 + # load test specific configuration [Load.OCR] [Load.OCR.Common] @@ -77,9 +80,9 @@ chainlink_node_funding = 0.5 [Soak.OCR] [Soak.OCR.Common] test_duration="15m" +number_of_contracts=2 [Soak.OCR.Soak] -number_of_contracts=2 time_between_rounds="1m" # Soak test configuration with Geth reorg below finality with FinalityTagEnabled=false diff --git a/integration-tests/testconfig/ocr/overrides/arbitrum_mainnet.toml b/integration-tests/testconfig/ocr/overrides/arbitrum_mainnet.toml new file mode 100644 index 00000000000..953d9f351a4 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/arbitrum_mainnet.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["ARBITRUM_MAINNET"] + +[Soak.Common] +chainlink_node_funding = 0.1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "10m" + +[OCR.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr/overrides/arbitrum_sepolia.toml b/integration-tests/testconfig/ocr/overrides/arbitrum_sepolia.toml new file mode 100644 index 00000000000..1428e50b0e3 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/arbitrum_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["ARBITRUM_SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/base_mainnet.toml b/integration-tests/testconfig/ocr/overrides/base_mainnet.toml new file mode 100644 index 00000000000..a285c23758e --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/base_mainnet.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["BASE_MAINNET"] + +[Soak.Common] +chainlink_node_funding = 5 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "10m" + +[OCR.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr/overrides/base_sepolia.toml b/integration-tests/testconfig/ocr/overrides/base_sepolia.toml new file mode 100644 index 00000000000..3dbbadcbef2 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/base_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["BASE_SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/celo_alfajores.toml b/integration-tests/testconfig/ocr/overrides/celo_alfajores.toml new file mode 100644 index 00000000000..37c4a8cf16d --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/celo_alfajores.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["CELO_ALFAJORES"] + +[Soak.Common] +chainlink_node_funding = 10 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/ethereum_sepolia.toml b/integration-tests/testconfig/ocr/overrides/ethereum_sepolia.toml new file mode 100644 index 00000000000..612e47506a7 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/ethereum_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/hedera_testnet.toml b/integration-tests/testconfig/ocr/overrides/hedera_testnet.toml new file mode 100755 index 00000000000..9741dbef36c --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/hedera_testnet.toml @@ -0,0 +1,48 @@ +[ChainlinkImage] +version = "283fe46b1d149c57ef2c70e6d5a1520dbc5b482e" + +[Network] +selected_networks = ["HEDERA_TESTNET"] + +[Soak.Common] +chainlink_node_funding = 30 +number_of_contracts = 2 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "240m" + +[Soak.OCR2.Soak] +ocr_version = "2" +number_of_contracts = 2 +time_between_rounds = "5m" + +[Seth] +pending_nonce_protection_enabled = true + +[Network.EVMNetworks.HEDERA_TESTNET] +evm_name = "HEDERA_TESTNET" +evm_chain_id = 296 +client_implementation = "Ethereum" +evm_simulated = false +evm_chainlink_transaction_limit = 5000 +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 100000 +evm_supports_eip1559 = false +evm_default_gas_limit = 6000000 + +[[Seth.networks]] +name = "HEDERA_TESTNET" +transaction_timeout = "2m" +transfer_gas_fee = 800_000 +gas_limit = 2_000_000 +# legacy transactions +gas_price = 2_500_000_000_000 +# EIP-1559 transactions +eip_1559_dynamic_fees = false +gas_fee_cap = 109_694_825_437 +gas_tip_cap = 30_000_000_000 +# if set to true we will estimate gas for every transaction +gas_price_estimation_enabled = false +# how many last blocks to use, when estimating gas for a transaction +gas_price_estimation_blocks = 0 \ No newline at end of file diff --git a/integration-tests/testconfig/ocr/overrides/linea_sepolia.toml b/integration-tests/testconfig/ocr/overrides/linea_sepolia.toml new file mode 100644 index 00000000000..6fa6218d541 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/linea_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["Linea_Sepolia"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/optimism_mainnet.toml b/integration-tests/testconfig/ocr/overrides/optimism_mainnet.toml new file mode 100644 index 00000000000..eec0640baa3 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/optimism_mainnet.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["OPTIMISM_MAINNET"] + +[Soak.Common] +chainlink_node_funding = 0.1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "10m" + +[OCR.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr/overrides/optimism_sepolia.toml b/integration-tests/testconfig/ocr/overrides/optimism_sepolia.toml new file mode 100644 index 00000000000..fe666b6aa9e --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/optimism_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["OPTIMISM_SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/scroll_sepolia.toml b/integration-tests/testconfig/ocr/overrides/scroll_sepolia.toml new file mode 100644 index 00000000000..0beedfd05ea --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/scroll_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["SCROLL_SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "2m" + +[OCR.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr/overrides/wemix_mainnet.toml b/integration-tests/testconfig/ocr/overrides/wemix_mainnet.toml new file mode 100644 index 00000000000..4a7859db3c9 --- /dev/null +++ b/integration-tests/testconfig/ocr/overrides/wemix_mainnet.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["WEMIX_MAINNET"] + +[Soak.Common] +chainlink_node_funding = 5 + +[Soak.OCR] +[Soak.OCR.Common] +test_duration = "24h" + +[Soak.OCR.Soak] +time_between_rounds = "10m" + +[OCR.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr2/example.toml b/integration-tests/testconfig/ocr2/example.toml index 36e3105f219..319f64d2580 100644 --- a/integration-tests/testconfig/ocr2/example.toml +++ b/integration-tests/testconfig/ocr2/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -31,7 +30,7 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" @@ -39,15 +38,6 @@ bearer_token_secret="my-awesome-token" [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" @@ -142,6 +132,9 @@ BumpPercent = 20 BumpMin = '100 gwei' """ +[OCR2.Common] +number_of_contracts=1 + # load test specific configuration [Load.OCR2] [Load.OCR2.Common] @@ -161,8 +154,8 @@ chainlink_node_funding = 100 [Soak.OCR2] [Soak.OCR.Common] +number_of_contracts=2 test_duration="15m" [Soak.OCR2.Soak] -number_of_contracts=2 time_between_rounds="1m" diff --git a/integration-tests/testconfig/ocr2/ocr2.go b/integration-tests/testconfig/ocr2/ocr2.go index 73c9cd10056..60169e944fa 100644 --- a/integration-tests/testconfig/ocr2/ocr2.go +++ b/integration-tests/testconfig/ocr2/ocr2.go @@ -1,14 +1,13 @@ package ocr2 import ( - "errors" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ocr" ) type Config struct { - Soak *SoakConfig `toml:"Soak"` - Common *Common `toml:"Common"` + Soak *ocr.SoakConfig `toml:"Soak"` + Common *ocr.Common `toml:"Common"` + Contracts *ocr.Contracts `toml:"Contracts"` } func (o *Config) Validate() error { @@ -22,32 +21,10 @@ func (o *Config) Validate() error { return err } } - return nil -} - -type Common struct { - ETHFunds *int `toml:"eth_funds"` - TestDuration *blockchain.StrDuration `toml:"test_duration"` -} - -func (o *Common) Validate() error { - if o.ETHFunds != nil && *o.ETHFunds < 0 { - return errors.New("eth_funds must be set and cannot be negative") - } - return nil -} - -type SoakConfig struct { - NumberOfContracts *int `toml:"number_of_contracts"` - TimeBetweenRounds *blockchain.StrDuration `toml:"time_between_rounds"` -} - -func (o *SoakConfig) Validate() error { - if o.NumberOfContracts == nil || *o.NumberOfContracts <= 1 { - return errors.New("number_of_contracts must be set and be greater than 1") - } - if o.TimeBetweenRounds == nil || o.TimeBetweenRounds.Duration == 0 { - return errors.New("time_between_rounds must be set and be a positive integer") + if o.Contracts != nil { + if err := o.Contracts.Validate(); err != nil { + return err + } } return nil } diff --git a/integration-tests/testconfig/ocr2/ocr2.toml b/integration-tests/testconfig/ocr2/ocr2.toml index ad195913bd0..62d92574ea8 100644 --- a/integration-tests/testconfig/ocr2/ocr2.toml +++ b/integration-tests/testconfig/ocr2/ocr2.toml @@ -43,6 +43,9 @@ Enabled = true ListenAddresses = ['0.0.0.0:6690'] """ +[OCR2.Common] +number_of_contracts=1 + # load test specific configuration [Load.OCR2] [Load.OCR2.Common] @@ -76,8 +79,8 @@ chainlink_node_funding = 0.5 [Soak.OCR2] [Soak.OCR2.Common] +number_of_contracts=2 test_duration="15m" [Soak.OCR2.Soak] -number_of_contracts=2 time_between_rounds="1m" diff --git a/integration-tests/testconfig/ocr2/overrides/base_sepolia.toml b/integration-tests/testconfig/ocr2/overrides/base_sepolia.toml new file mode 100644 index 00000000000..76e4fc4722d --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/base_sepolia.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["BASE_SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "24h" + +[Soak.OCR2.Soak] +time_between_rounds = "2m" + +[OCR2.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr2/overrides/base_sepolia_quick_smoke_test.toml b/integration-tests/testconfig/ocr2/overrides/base_sepolia_quick_smoke_test.toml new file mode 100644 index 00000000000..f4dfe76994b --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/base_sepolia_quick_smoke_test.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["BASE_SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "10m" + +[Soak.OCR2.Soak] +time_between_rounds = "2m" + +[OCR2.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr2/overrides/ethereum_sepolia.toml b/integration-tests/testconfig/ocr2/overrides/ethereum_sepolia.toml new file mode 100644 index 00000000000..f7e02407808 --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/ethereum_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["SEPOLIA"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "24h" + +[Soak.OCR2.Soak] +time_between_rounds = "2m" + +[OCR2.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr2/overrides/polygon_amoy.toml b/integration-tests/testconfig/ocr2/overrides/polygon_amoy.toml new file mode 100644 index 00000000000..41a31897c5f --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/polygon_amoy.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["POLYGON_AMOY"] + +[Soak.Common] +chainlink_node_funding = 20 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "24h" + +[Soak.OCR2.Soak] +time_between_rounds = "2m" + +[OCR2.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr2/overrides/polygon_mainnet.toml b/integration-tests/testconfig/ocr2/overrides/polygon_mainnet.toml new file mode 100644 index 00000000000..51da2793133 --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/polygon_mainnet.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["POLYGON_MAINNET"] + +[Soak.Common] +chainlink_node_funding = 5 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "24h" + +[Soak.OCR2.Soak] +time_between_rounds = "10m" + +[OCR2.Common] +number_of_contracts = 2 + +[Seth] +experiments_enabled = ["slow_funds_return"] diff --git a/integration-tests/testconfig/ocr2/overrides/wemix_testnet.toml b/integration-tests/testconfig/ocr2/overrides/wemix_testnet.toml new file mode 100644 index 00000000000..82bc06c17ee --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/wemix_testnet.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["WEMIX_TESTNET"] + +[Soak.Common] +chainlink_node_funding = 10 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "24h" + +[Soak.OCR2.Soak] +time_between_rounds = "2m" + +[OCR2.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/ocr2/overrides/xlayer_sepolia.toml b/integration-tests/testconfig/ocr2/overrides/xlayer_sepolia.toml new file mode 100644 index 00000000000..d58098c5b0f --- /dev/null +++ b/integration-tests/testconfig/ocr2/overrides/xlayer_sepolia.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["xlayer_sepolia"] + +[Soak.Common] +chainlink_node_funding = 1 + +[Soak.OCR2] +[Soak.OCR2.Common] +test_duration = "24h" + +[Soak.OCR2.Soak] +time_between_rounds = "2m" + +[OCR2.Common] +number_of_contracts = 2 diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 016531ed493..545818e3348 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/barkimedes/go-deepcopy" + "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/pelletier/go-toml/v2" "github.com/pkg/errors" @@ -17,16 +18,17 @@ import ( "golang.org/x/text/cases" "golang.org/x/text/language" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - k8s_config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + k8s_config "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" + ccip_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" f_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/functions" keeper_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/keeper" lp_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/log_poller" @@ -72,6 +74,21 @@ type Ocr2TestConfig interface { GetOCR2Config() *ocr_config.Config } +type CCIPTestConfig interface { + GetCCIPConfig() *ccip_config.Config +} + +type LinkTokenContractConfig interface { + LinkTokenContractAddress() (common.Address, error) + UseExistingLinkTokenContract() bool +} + +const ( + E2E_TEST_DATA_STREAMS_URL_ENV = "E2E_TEST_DATA_STREAMS_URL" + E2E_TEST_DATA_STREAMS_USERNAME_ENV = "E2E_TEST_DATA_STREAMS_USERNAME" + E2E_TEST_DATA_STREAMS_PASSWORD_ENV = "E2E_TEST_DATA_STREAMS_PASSWORD" +) + type TestConfig struct { ctf_config.TestConfig @@ -85,6 +102,7 @@ type TestConfig struct { VRF *vrf_config.Config `toml:"VRF"` VRFv2 *vrfv2_config.Config `toml:"VRFv2"` VRFv2Plus *vrfv2plus_config.Config `toml:"VRFv2Plus"` + CCIP *ccip_config.Config `toml:"CCIP"` ConfigurationNames []string `toml:"-"` } @@ -198,6 +216,10 @@ func (c TestConfig) GetOCRConfig() *ocr_config.Config { return c.OCR } +func (c TestConfig) GetCCIPConfig() *ccip_config.Config { + return c.CCIP +} + func (c TestConfig) GetConfigurationNames() []string { return c.ConfigurationNames } @@ -253,6 +275,8 @@ const ( VRF Product = "vrf" VRFv2 Product = "vrfv2" VRFv2Plus Product = "vrfv2plus" + + CCIP Product = "ccip" ) const TestTypeEnvVarName = "TEST_TYPE" @@ -347,13 +371,19 @@ func GetConfig(configurationNames []string, product Product) (TestConfig, error) } } - // it needs some custom logic, so we do it separately - err := testConfig.readNetworkConfiguration() + logger.Info().Msg("Setting env vars from testsecrets dot-env files") + err := ctf_config.LoadSecretEnvsFromFiles() if err != nil { - return TestConfig{}, errors.Wrapf(err, "error reading network config") + return TestConfig{}, errors.Wrapf(err, "error reading test config values from ~/.testsecrets file") } - logger.Info().Msg("Reading configs from Base64 override env var") + logger.Info().Msg("Reading config values from existing env vars") + err = testConfig.ReadFromEnvVar() + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading test config values from env vars") + } + + logger.Info().Msgf("Overriding config from %s env var", Base64OverrideEnvVarName) configEncoded, isSet := os.LookupEnv(Base64OverrideEnvVarName) if isSet && configEncoded != "" { logger.Debug().Msgf("Found base64 config override environment variable '%s' found", Base64OverrideEnvVarName) @@ -374,16 +404,9 @@ func GetConfig(configurationNames []string, product Product) (TestConfig, error) logger.Debug().Msg("Base64 config override from environment variable not found") } - logger.Info().Msg("Loading config values from default ~/.testsecrets env file") - err = ctf_config.LoadSecretEnvsFromFiles() + err = testConfig.readNetworkConfiguration() if err != nil { - return TestConfig{}, errors.Wrapf(err, "error reading test config values from ~/.testsecrets file") - } - - logger.Info().Msg("Reading values from environment variables") - err = testConfig.ReadFromEnvVar() - if err != nil { - return TestConfig{}, errors.Wrapf(err, "error reading test config values from env vars") + return TestConfig{}, errors.Wrapf(err, "error reading network config") } logger.Debug().Msg("Validating test config") @@ -404,6 +427,55 @@ func GetConfig(configurationNames []string, product Product) (TestConfig, error) return testConfig, nil } +// Read config values from environment variables +func (c *TestConfig) ReadFromEnvVar() error { + logger := logging.GetTestLogger(nil) + + // Read values for base config from env vars + err := c.TestConfig.ReadFromEnvVar() + if err != nil { + return errors.Wrapf(err, "error reading test config values from env vars") + } + + dsURL := ctf_config.MustReadEnvVar_String(E2E_TEST_DATA_STREAMS_URL_ENV) + if dsURL != "" { + if c.Automation == nil { + c.Automation = &a_config.Config{} + } + if c.Automation.DataStreams == nil { + c.Automation.DataStreams = &a_config.DataStreams{} + } + logger.Debug().Msgf("Using %s env var to override Automation.DataStreams.URL", E2E_TEST_DATA_STREAMS_URL_ENV) + c.Automation.DataStreams.URL = &dsURL + } + + dsUsername := ctf_config.MustReadEnvVar_String(E2E_TEST_DATA_STREAMS_USERNAME_ENV) + if dsUsername != "" { + if c.Automation == nil { + c.Automation = &a_config.Config{} + } + if c.Automation.DataStreams == nil { + c.Automation.DataStreams = &a_config.DataStreams{} + } + logger.Debug().Msgf("Using %s env var to override Automation.DataStreams.Username", E2E_TEST_DATA_STREAMS_USERNAME_ENV) + c.Automation.DataStreams.Username = &dsUsername + } + + dsPassword := ctf_config.MustReadEnvVar_String(E2E_TEST_DATA_STREAMS_PASSWORD_ENV) + if dsPassword != "" { + if c.Automation == nil { + c.Automation = &a_config.Config{} + } + if c.Automation.DataStreams == nil { + c.Automation.DataStreams = &a_config.DataStreams{} + } + logger.Debug().Msgf("Using %s env var to override Automation.DataStreams.Password", E2E_TEST_DATA_STREAMS_PASSWORD_ENV) + c.Automation.DataStreams.Password = &dsPassword + } + + return nil +} + func (c *TestConfig) logRiskySettings(logger zerolog.Logger) { isAnySimulated := false for _, network := range c.Network.SelectedNetworks { @@ -522,10 +594,6 @@ func (c *TestConfig) readNetworkConfiguration() error { c.Network.UpperCaseNetworkNames() c.Network.OverrideURLsAndKeysFromEVMNetwork() - err := c.Network.Default() - if err != nil { - return errors.Wrapf(err, "error reading default network config") - } // this is the only value we need to generate dynamically before starting a new simulated chain if c.PrivateEthereumNetwork != nil && c.PrivateEthereumNetwork.EthereumChainConfig != nil { diff --git a/integration-tests/testconfig/testconfig_test.go b/integration-tests/testconfig/testconfig_test.go index 91d2524fcf0..6a025c35ccc 100644 --- a/integration-tests/testconfig/testconfig_test.go +++ b/integration-tests/testconfig/testconfig_test.go @@ -9,23 +9,24 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/test-go/testify/require" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" ) func TestBase64ConfigRead(t *testing.T) { - networkConfigTOML := ` - [RpcHttpUrls] - arbitrum_goerli = ["https://devnet-1.mt/ABC/rpc/"] - optimism_goerli = ["https://devnet-3.mt/ABC/rpc/"] - - [RpcWsUrls] - arbitrum_goerli = ["wss://devnet-1.mt/ABC/rpc/"] - optimism_goerli = ["wss://devnet-2.mt/ABC/rpc/"] - ` - networksEncoded := base64.StdEncoding.EncodeToString([]byte(networkConfigTOML)) - os.Setenv(ctf_config.Base64NetworkConfigEnvVarName, networksEncoded) + os.Setenv("E2E_TEST_ARBITRUM_GOERLI_RPC_HTTP_URL", "https://devnet-1.mt/ABC/rpc/") + os.Setenv("E2E_TEST_ARBITRUM_GOERLI_RPC_WS_URL", "wss://devnet-1.mt/ABC/rpc/") + os.Setenv("E2E_TEST_ARBITRUM_GOERLI_WALLET_KEY", "0x3333333333333333333333333333333333333333") + defer os.Unsetenv("E2E_TEST_ARBITRUM_GOERLI_RPC_HTTP_URL") + defer os.Unsetenv("E2E_TEST_ARBITRUM_GOERLI_RPC_WS_URL") + defer os.Unsetenv("E2E_TEST_ARBITRUM_GOERLI_WALLET_KEY") + os.Setenv("E2E_TEST_OPTIMISM_GOERLI_RPC_HTTP_URL", "https://devnet-3.mt/ABC/rpc/") + os.Setenv("E2E_TEST_OPTIMISM_GOERLI_RPC_WS_URL", "wss://devnet-3.mt/ABC/rpc/") + os.Setenv("E2E_TEST_OPTIMISM_GOERLI_WALLET_KEY", "0x3333333333333333333333333333333333333333") + defer os.Unsetenv("E2E_TEST_OPTIMISM_GOERLI_RPC_HTTP_URL") + defer os.Unsetenv("E2E_TEST_OPTIMISM_GOERLI_RPC_WS_URL") + defer os.Unsetenv("E2E_TEST_OPTIMISM_GOERLI_WALLET_KEY") testConfig := TestConfig{ Automation: &a_config.Config{ @@ -35,6 +36,8 @@ func TestBase64ConfigRead(t *testing.T) { BlockTime: ptr.Ptr(10), SpecType: ptr.Ptr("minimum"), ChainlinkNodeLogLevel: ptr.Ptr("debug"), + UsePrometheus: ptr.Ptr(true), + RemoveNamespace: ptr.Ptr(true), }, Load: []a_config.Load{ { diff --git a/integration-tests/testconfig/vrfv2/example.toml b/integration-tests/testconfig/vrfv2/example.toml index 9417a422cf0..13af6dee620 100644 --- a/integration-tests/testconfig/vrfv2/example.toml +++ b/integration-tests/testconfig/vrfv2/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" diff --git a/integration-tests/testconfig/vrfv2/overrides/new_env/arbitrum_sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2/overrides/new_env/arbitrum_sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..9181c0f51fa --- /dev/null +++ b/integration-tests/testconfig/vrfv2/overrides/new_env/arbitrum_sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["ARBITRUM_SEPOLIA"] + +[ARBITRUM_SEPOLIA.VRFv2.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2/overrides/new_env/avalanche_fuji_new_env_test_config.toml b/integration-tests/testconfig/vrfv2/overrides/new_env/avalanche_fuji_new_env_test_config.toml new file mode 100644 index 00000000000..cfeaa5a7975 --- /dev/null +++ b/integration-tests/testconfig/vrfv2/overrides/new_env/avalanche_fuji_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["AVALANCHE_FUJI"] + +[AVALANCHE_FUJI.VRFv2.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2/overrides/new_env/bsc_testnet_new_env_test_config.toml b/integration-tests/testconfig/vrfv2/overrides/new_env/bsc_testnet_new_env_test_config.toml new file mode 100644 index 00000000000..ec938767ec5 --- /dev/null +++ b/integration-tests/testconfig/vrfv2/overrides/new_env/bsc_testnet_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["BSC_TESTNET"] + +[BSC_TESTNET.VRFv2.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2/overrides/new_env/polygon_amoy_new_env_test_config.toml b/integration-tests/testconfig/vrfv2/overrides/new_env/polygon_amoy_new_env_test_config.toml new file mode 100644 index 00000000000..6331647a883 --- /dev/null +++ b/integration-tests/testconfig/vrfv2/overrides/new_env/polygon_amoy_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["POLYGON_AMOY"] + +[POLYGON_AMOY.VRFv2.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2/overrides/new_env/sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2/overrides/new_env/sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..591f07e6625 --- /dev/null +++ b/integration-tests/testconfig/vrfv2/overrides/new_env/sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["SEPOLIA"] + +[SEPOLIA.VRFv2.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2/overrides/staging/polygon_amoy_staging_test_config.toml b/integration-tests/testconfig/vrfv2/overrides/staging/polygon_amoy_staging_test_config.toml new file mode 100644 index 00000000000..acdff9ff4e1 --- /dev/null +++ b/integration-tests/testconfig/vrfv2/overrides/staging/polygon_amoy_staging_test_config.toml @@ -0,0 +1,24 @@ +[Network] +selected_networks = ["POLYGON_AMOY"] + +[POLYGON_AMOY.VRFv2.General] +use_existing_env = true + +[POLYGON_AMOY.VRFv2.ExistingEnv] +coordinator_address = "0x919BEF67CE94604A7Cd5747F2c0088C8EB8A93aa" +consumer_address = "" +sub_id = "" +key_hash = "0xcd9c54d52db91522b69fe8ddc40d1f78156795de0efb2adbc053a438b9ee14a6" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 10 +node_sending_keys = [ + "0xD4B787C4ce6E04c16b5FDce2c25956b8F4432195", + # BHS + "0x638372de870eF0F8E675A3f67F18D5bd4A2fd804", + "0xF9eF03816411D037202d5ed4457dC1613e3bd729", + "0xCD66973f8fbaE787211EC20228c6bd90D83562A8", + "0x242ea1F4Bb72EF643B2D8EF22e18a89f00742F40", + "0xaA09B4F9B5710b239fdbf1D0f535dd7f86F91219", + "0xe6b72B647B8B45C5562F7a5259E187889C747d3b", + "0x2c1185C4d3B0B4a577d4079Ee193A4e293164D9d" +] diff --git a/integration-tests/testconfig/vrfv2/vrfv2.toml b/integration-tests/testconfig/vrfv2/vrfv2.toml index de7200b1e79..634e3074feb 100644 --- a/integration-tests/testconfig/vrfv2/vrfv2.toml +++ b/integration-tests/testconfig/vrfv2/vrfv2.toml @@ -19,6 +19,7 @@ MaxSize = '0b' [WebServer] AllowOrigins = '*' HTTPPort = 6688 +HTTPWriteTimeout = '1m0s' SecureCookies = false [WebServer.RateLimit] diff --git a/integration-tests/testconfig/vrfv2plus/config.go b/integration-tests/testconfig/vrfv2plus/config.go index 9d863afdd14..4ae5ee5c357 100644 --- a/integration-tests/testconfig/vrfv2plus/config.go +++ b/integration-tests/testconfig/vrfv2plus/config.go @@ -57,8 +57,12 @@ type General struct { CoordinatorLinkPremiumPercentage *uint8 `toml:"coordinator_link_premium_percentage"` //OP Stack chains settings - L1FeeCalculationMode uint8 `toml:"l1_fee_calculation_mode"` - L1FeeCoefficient uint8 `toml:"l1_fee_coefficient"` + L1FeeCalculationMode *uint8 `toml:"l1_fee_calculation_mode"` + L1FeeCoefficient *uint8 `toml:"l1_fee_coefficient"` + + UseTestCoordinator *bool `toml:"use_test_coordinator"` + + SubBillingTolerance *float64 `toml:"sub_billing_tolerance_wei"` } func (c *General) Validate() error { @@ -101,6 +105,9 @@ func (c *General) Validate() error { if c.CoordinatorLinkPremiumPercentage == nil { return errors.New("coordinator_link_premium_percentage must not be nil") } + if c.UseTestCoordinator == nil { + return errors.New("use_test_coordinator must not be nil") + } return nil } diff --git a/integration-tests/testconfig/vrfv2plus/example.toml b/integration-tests/testconfig/vrfv2plus/example.toml index d6e7a3f28d5..160e9ba03a9 100644 --- a/integration-tests/testconfig/vrfv2plus/example.toml +++ b/integration-tests/testconfig/vrfv2plus/example.toml @@ -1,7 +1,6 @@ # Example of full config with all fields # General part [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" version="2.7.0" [Logging] @@ -16,38 +15,10 @@ log_producer_timeout="10s" # number of retries before log producer gives up and stops listening to logs log_producer_retry_limit=10 -[Logging.Loki] -tenant_id="tenant_id" -# full URL of Loki ingest endpoint -endpoint="https://loki.url/api/v3/push" -# currently only needed when using public instance -basic_auth_secret="loki-basic-auth" -# only needed for cloud grafana -bearer_token_secret="bearer_token" - -# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) -[Logging.Grafana] -# grafana url (trailing "/" will be stripped) -base_url="http://grafana.url" -# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard -dashboard_url="/d/your-dashboard" -# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model -dashboard_uid="dashboard-uid-to-annotate" -bearer_token_secret="my-awesome-token" - # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] -[Network.RpcHttpUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.RpcWsUrls] -polygon_mumbai = ["https://my-rpc-endpoint.io"] - -[Network.WalletKeys] -polygon_mumbai = ["change-me-to-your-PK"] - [PrivateEthereumNetwork] # pos or pow consensus_type="pos" diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/arbitrum_sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/arbitrum_sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..271ef037bd3 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/arbitrum_sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["ARBITRUM_SEPOLIA"] + +[ARBITRUM_SEPOLIA.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/avalanche_fuji_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/avalanche_fuji_new_env_test_config.toml new file mode 100644 index 00000000000..273d796ba6f --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/avalanche_fuji_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["AVALANCHE_FUJI"] + +[AVALANCHE_FUJI.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/base_sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/base_sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..f93c75cc380 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/base_sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["BASE_SEPOLIA"] + +[BASE_SEPOLIA.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/bsc_testnet_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/bsc_testnet_new_env_test_config.toml new file mode 100644 index 00000000000..16cc9a6e539 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/bsc_testnet_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["BSC_TESTNET"] + +[BSC_TESTNET.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_dev_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_dev_new_env_test_config.toml new file mode 100644 index 00000000000..5d7b7741081 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_dev_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["NEXON_DEV"] + +[NEXON_DEV.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_qa_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_qa_new_env_test_config.toml new file mode 100644 index 00000000000..0f761128afa --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_qa_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["NEXON_QA"] + +[NEXON_QA.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_stage_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_stage_new_env_test_config.toml new file mode 100644 index 00000000000..5dcd771e9dd --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_stage_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["NEXON_STAGE"] + +[NEXON_STAGE.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_test_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_test_new_env_test_config.toml new file mode 100644 index 00000000000..d1263df34d0 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/nexon_test_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["NEXON_TEST"] + +[NEXON_TEST.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/optimism_sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/optimism_sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..8fd5b763796 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/optimism_sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["OPTIMISM_SEPOLIA"] + +[OPTIMISM_SEPOLIA.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/polygon_amoy_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/polygon_amoy_new_env_test_config.toml new file mode 100644 index 00000000000..10abe34bb5e --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/polygon_amoy_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["POLYGON_AMOY"] + +[POLYGON_AMOY.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..7df808c505f --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["SEPOLIA"] + +[SEPOLIA.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/new_env/soneium_sepolia_new_env_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/new_env/soneium_sepolia_new_env_test_config.toml new file mode 100644 index 00000000000..beacf9c5f7c --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/new_env/soneium_sepolia_new_env_test_config.toml @@ -0,0 +1,8 @@ +[Network] +selected_networks = ["SONEIUM_SEPOLIA"] + +[SONEIUM_SEPOLIA.VRFv2Plus.General] +use_existing_env = false + +[Logging] +test_log_collect = true diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/arbitrum_sepolia_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/arbitrum_sepolia_staging_test_config.toml new file mode 100644 index 00000000000..66529bbed3a --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/arbitrum_sepolia_staging_test_config.toml @@ -0,0 +1,36 @@ +[Network] +selected_networks = ["ARBITRUM_SEPOLIA"] + +[ARBITRUM_SEPOLIA.VRFv2Plus.General] +use_existing_env = true + +[ARBITRUM_SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0xF7ba1Cf141F9729abC43c146dc2bf86EbcfD8603" +consumer_address = "" +sub_id = "" +key_hash = "0xe13aa26fe94bfcd2ae055911f4d3bf1aed54ca6cf77af34e17f918802fd69ba1" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 20 +node_sending_keys = [ + "0xbE21ae371FcA1aC2d8A152e707D21e68d7d99252", + "0xb13e9BA0aE94FD3b89B13b092e6d41614c805134", + "0x27aa703e585Ee165B7c977EAA652eCFa13b08294", + "0x9324643ACD2ec5b0813488E5EdAb64C3758ae4Ee", + "0x7CBA8c8e86f23f23363051650Fe5AE4DE78c3652", + "0x9A0143a4BAB55A826331A8ef82462557633aA016", + "0xD4259633F8e87949F683433a17e1fFcCE27865AC", + "0x5e47B71d6F95f68cd5538907ec6A9635b1Fe30Fa", + "0xa850a1a257FDF439c8f854ce3b89dd5b6F411827", + "0x7c82D56087c10aF2c3970f9a9Be7786B2850ce91", + "0x9545CB59956347d3debf27f5029754bBE1d398FA", + "0xEb8C69ac19709f27A97FB4A561f51AD2F9b34c5B", + # BHS + "0xf0e8cF7Fbd28Fc4D412B76B744CDA269df671F8e", + "0x317A02A658d12E5Bb4A6270171E7385928dD2d53", + "0x480f1dbcEc118Bd91e4dbb7e45bFa4A73180d21f", + "0x500a2662FaF981EC4669f791349D37Cbf1bE7d85", + "0x2ad350374B904c10B47c64ECdBD9e70BB0833Be2", + "0x0b946F0bF4e63C12b5157137f1c130f0788bC1b1", + # BHF + "0x571BBF4a5b07fc3F47Bd3B65CE2FE73739f86623" +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/avalanche_fuji_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/avalanche_fuji_staging_test_config.toml new file mode 100644 index 00000000000..c8566e59a74 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/avalanche_fuji_staging_test_config.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["AVALANCHE_FUJI"] + +[AVALANCHE_FUJI.VRFv2Plus.General] +use_existing_env = true + +[AVALANCHE_FUJI.VRFv2Plus.ExistingEnv] +coordinator_address = "0xE122bf3Badd6545bDec5D4627a6DAd16352A1b36" +consumer_address = "" +sub_id = "" +key_hash = "0x5b03254a80ea3eb72139ff0423cb88be42612780c3dd25f1d95a5ba7708a4be1" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0x3D7Da5D6A23CA2240CE576C8638C1798a023920a", + # BHS + "0x72c8565279430F5179b0090d51ab8BB53Da323B5" +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/base_sepolia_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/base_sepolia_staging_test_config.toml new file mode 100644 index 00000000000..ad125ae46b4 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/base_sepolia_staging_test_config.toml @@ -0,0 +1,20 @@ +[Network] +selected_networks = ["BASE_SEPOLIA"] + +[BASE_SEPOLIA.VRFv2Plus.General] +use_existing_env = true + +[BASE_SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0x2Cf7Bb5923FA4dBdf92981fDBbEe27d13A896705" +consumer_address = "" +sub_id = "" +key_hash = "0x01d1eb450e0271ac86d3b78c7cc799f80e7f80863a4875f6fc7b66629419c951" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0x5d621FF993B1a990d189936E70021c585e3B0880", + "0x87F701AD21BfAF99eF64596c5CE8762a5Cb9ED13", + "0xe8B0865e9Aae9DE628BE14965Bbd1C0c9C80d245", + # BHS + "0x65C853683beB6363869DDda8534b2aD45786d380", +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/bsc_testnet_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/bsc_testnet_staging_test_config.toml new file mode 100644 index 00000000000..48060a88cf9 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/bsc_testnet_staging_test_config.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["BSC_TESTNET"] + +[BSC_TESTNET.VRFv2Plus.General] +use_existing_env = true + +[BSC_TESTNET.VRFv2Plus.ExistingEnv] +coordinator_address = "0x84A477F6ebF33501eE3ACA86fEcB980b1fC99AC2" +consumer_address = "" +sub_id = "" +key_hash = "0x4d43763d3eff849a89cf578a42787baa32132d7a80032125710e95b3972cd214" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0x4EE2Cc6D50E8acb6BaEf673B03559525a6c92fB8", + # BHS + "0xAFB44568f7DAc218EA6e1C71c366692ED4758A07" +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_dev_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_dev_staging_test_config.toml new file mode 100644 index 00000000000..0121c025526 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_dev_staging_test_config.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["NEXON_DEV"] + +[NEXON_DEV.VRFv2Plus.General] +use_existing_env = true + +[NEXON_DEV.VRFv2Plus.ExistingEnv] +coordinator_address = "0x6901d7236A823E7B7911d90FBe46E6FA770CC823" +consumer_address = "" +sub_id = "" +key_hash = "0xdc023892a41e5fe74ec7c4c2e8c0a808b01aea7acaf2b2ae30f4e08df877c48b" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0xF3d9879a75BBD85890056D7c6cB37C555F9b41A3", + # BHS + "0xb544f9D7c16a30af0EEd0afcC4132D1c63bAF8AC", +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_qa_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_qa_staging_test_config.toml new file mode 100644 index 00000000000..f45ecde0ed5 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_qa_staging_test_config.toml @@ -0,0 +1,20 @@ +[Network] +selected_networks = ["NEXON_QA"] + +[NEXON_QA.VRFv2Plus.General] +use_existing_env = true + +[NEXON_QA.VRFv2Plus.ExistingEnv] +coordinator_address = "0xF1F0beBcc284591FCD28d8f2BAc9f30efdA3E0ea" +consumer_address = "" +sub_id = "" +key_hash = "0x7d5692e71807c4c02f5a109627a9ad2b12a361a346790a306983af9a5e3a186f" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0xB97c0C52A2B957b45DA213e652c76090DDd0FEc6", + "0xe205F5d4a99ca0f474d0b4d12f60a0153c786B4E", + # BHS + "0xf85E291edF0352435f2fD5e817030f6542375a99", +] + diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_stage_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_stage_staging_test_config.toml new file mode 100644 index 00000000000..1a50876a730 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_stage_staging_test_config.toml @@ -0,0 +1,15 @@ +[Network] +selected_networks = ["NEXON_STAGE"] + +[NEXON_STAGE.VRFv2Plus.General] +use_existing_env = true + +[NEXON_STAGE.VRFv2Plus.ExistingEnv] +coordinator_address = "0xF705dD3e7E717F32de0Cc5F833f8009f16122AD1" +consumer_address = "" +sub_id = "" +key_hash = "0xbc9f525e3e1d9e2336f7c77d5f33f5b60aab3765944617fed7f66a6afecac616" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_test_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_test_staging_test_config.toml new file mode 100644 index 00000000000..4f897f4e1d0 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/nexon_test_staging_test_config.toml @@ -0,0 +1,19 @@ +[Network] +selected_networks = ["NEXON_TEST"] + +[NEXON_TEST.VRFv2Plus.General] +use_existing_env = true + +[NEXON_TEST.VRFv2Plus.ExistingEnv] +coordinator_address = "0xAa92Ba21168B48195cAdB87cfaB3eB70B2499F55" +consumer_address = "" +sub_id = "" +key_hash = "0x0cb2a18e8b762cb4c8f7b17a6cc02ac7b9d2a3346f048cfd2f5d37677f8747d8" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0xBFD780Af421e98C35918e10B9d6da7389C3e1D10", + "0xbf6c76024672F233aB8164EC00683e1AE774F6b0", + # BHS + "0x2a3900Ac77de110670E060DBFf4fCbe36c6f8170", +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/optimism_sepolia_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/optimism_sepolia_staging_test_config.toml new file mode 100644 index 00000000000..e44085067cf --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/optimism_sepolia_staging_test_config.toml @@ -0,0 +1,20 @@ +[Network] +selected_networks = ["OPTIMISM_SEPOLIA"] + +[OPTIMISM_SEPOLIA.VRFv2Plus.General] +use_existing_env = true + +[OPTIMISM_SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0xA4a64A217bE85680e0ebB454CD5BF4A1c274Fc7B" +consumer_address = "" +sub_id = "" +key_hash = "0x4b4838bbf22a7c5a871ada8ceab6ded3c2de6cadc037371146ee70f6435325c1" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0x17509D615052DE3A81a684755Ec118d62C4e1Cd1", + "0x5118ece61294f4dFf4a1fb63b3f036969516dF0a", + "0x89554391652616ea06a408263b9B2b9a70E87204", + # BHS + "0x8DE6446b5022C68F38CD32d04AA0E3b8F4C1aaB6", +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/polygon_amoy_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/polygon_amoy_staging_test_config.toml new file mode 100644 index 00000000000..d2f9727483e --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/polygon_amoy_staging_test_config.toml @@ -0,0 +1,32 @@ +[Network] +selected_networks = ["POLYGON_AMOY"] + +[POLYGON_AMOY.VRFv2Plus.General] +use_existing_env = true + +[POLYGON_AMOY.VRFv2Plus.ExistingEnv] +coordinator_address = "0x7541EbaE23f32B4A1A2e7a8Cbf9da9582767A9B4" +consumer_address = "" +sub_id = "" +key_hash = "0xd360445bacd26df47086ccf255c4f932d297ed8d5c7334b51eed32f61c541601" +#key_hash = "0x2328cbee29e32d0b6662d6df82ff0fea7be300bd310561c92f515c9ee19464f1" +#key_hash = "0x25f4e2d0509f42ec77db5380f3433a89fe623fa75f65d5b398d5f498327be4dd" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 10 +node_sending_keys = [ + "0xD96013C241f1741C35a135321969f92Aae02A12F", + "0x0580E61a5523F5CAAC4968E4f8FE63b59596BdD7", + "0xd15FcEa6a6AA17085930Fbd5647A9F7fD2Ff58b8", + "0xB7277cBb6E7028AE65235b8ee9201AcBb14B11d4", + "0x6D36a1dC1eEd25C75961E989c4d01Cd4453bE465", + "0xd299Cd7C0073b71e620bf8A3bfD50F75c0b49af8", + "0x48BE7BAED0b65776D85DF971fA901c637cFC5e87", + # BHS + "0x638372de870eF0F8E675A3f67F18D5bd4A2fd804", + "0xF9eF03816411D037202d5ed4457dC1613e3bd729", + "0xCD66973f8fbaE787211EC20228c6bd90D83562A8", + "0x242ea1F4Bb72EF643B2D8EF22e18a89f00742F40", + "0xaA09B4F9B5710b239fdbf1D0f535dd7f86F91219", + "0xe6b72B647B8B45C5562F7a5259E187889C747d3b", + "0x2c1185C4d3B0B4a577d4079Ee193A4e293164D9d" +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/sepolia_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/sepolia_staging_test_config.toml new file mode 100644 index 00000000000..fd2e6f0bc1d --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/sepolia_staging_test_config.toml @@ -0,0 +1,18 @@ +[Network] +selected_networks = ["SEPOLIA"] + +[SEPOLIA.VRFv2Plus.General] +use_existing_env = true + +[SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0x2F3b892710523Ee9A85c3155a42089fFe99Ca31e" +consumer_address = "" +sub_id = "" +key_hash = "0xf5b4a359df0598eef89872ea2170f2afa844dbf74b417e6d44d4bda9420aceb2" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 30 +node_sending_keys = [ + "0x0c0DC7f33A1256f0247c5ea75861d385fa5FED31", + # BHS + "0xEd8A4b792d16484f6c9B4df1e721e8280925Db80", +] diff --git a/integration-tests/testconfig/vrfv2plus/overrides/staging/soneium_sepolia_staging_test_config.toml b/integration-tests/testconfig/vrfv2plus/overrides/staging/soneium_sepolia_staging_test_config.toml new file mode 100644 index 00000000000..df973d87022 --- /dev/null +++ b/integration-tests/testconfig/vrfv2plus/overrides/staging/soneium_sepolia_staging_test_config.toml @@ -0,0 +1,20 @@ +[Network] +selected_networks = ["SONEIUM_SEPOLIA"] + +[SONEIUM_SEPOLIA.VRFv2Plus.General] +use_existing_env = true + +[SONEIUM_SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0x81e211D679231615C2601E82B658Bde449AF240f" +consumer_address = "" +use_existing_wrapper = true +wrapper_address = "0xD06CfcDAa6f32BB131e693F99f502ac31588CBC8" +sub_id = "" +key_hash = "0x9552c9542c079db4f8c6867e27f6c4780e3e24d895cb0890ca9984764dbe7200" +create_fund_subs_and_add_consumers = true +node_sending_key_funding_min = 1 +node_sending_keys = [ + "0x22643FcF2018ac636477CFE19Ed17071FF7A5cA0", + # BHS + "0xD012B272E8ec6eA7A3373E340Ead52FA2C7352ea", +] diff --git a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml index 860c0c158bf..c9f5ac12a81 100644 --- a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml +++ b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml @@ -1,4 +1,5 @@ # default config + [NodeConfig] BaseConfigTOML = """ [Feature] @@ -30,7 +31,78 @@ Unauthenticated = 100 HTTPSPort = 0 """ +# Node TOML config depending on the chain [NodeConfig.ChainConfigTOMLByChainID] +# ETHEREUM SEPOLIA +11155111 = """ +BlockBackfillDepth = 500 +MinIncomingConfirmations = 3 + +[GasEstimator] +LimitDefault = 3500000 +""" + +# BNB TESTNET +97 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 + +[GasEstimator] +LimitDefault = 3500000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + +# Polygon Amoy +80002 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 + +[Transactions] +MaxInFlight = 128 +MaxQueued = 0 + +[GasEstimator] +LimitDefault = 3500000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + +# Avalanche Fuji +43113 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 + +[GasEstimator] +LimitDefault = 3500000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + +# Arbitrum Sepolia +# NOTE: PROD env has `LimitDefault = 100_000_000`, but it is decreased in order not to over spend testnet tokens +421614 = """ +BlockBackfillDepth = 15000 +LogBackfillBatchSize = 1000 +RPCDefaultBatchSize = 25 + +[Transactions] +MaxInFlight = 128 +MaxQueued = 0 + +[GasEstimator] +LimitDefault = 3_500_000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + # OPTIMISM SEPOLIA 11155420 = """ BlockBackfillDepth = 500 @@ -53,15 +125,73 @@ RPCDefaultBatchSize = 25 [GasEstimator] LimitDefault = 3500000 +[GasEstimator.BlockHistory] +BatchSize = 100 +""" +# Nexon Staging +847799 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 +NoNewHeadsThreshold = '0s' + +[GasEstimator] +LimitDefault = 3500000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + +# Nexon QA +807424 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 +NoNewHeadsThreshold = '0s' + +[GasEstimator] +LimitDefault = 3500000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + +# Nexon TEST +595581 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 +NoNewHeadsThreshold = '0s' + +[GasEstimator] +LimitDefault = 3500000 + +[GasEstimator.BlockHistory] +BatchSize = 100 +""" + +# Nexon DEV +5668 = """ +BlockBackfillDepth = 500 +RPCDefaultBatchSize = 25 +LogBackfillBatchSize = 1000 +NoNewHeadsThreshold = '0s' + +[GasEstimator] +LimitDefault = 3500000 + [GasEstimator.BlockHistory] BatchSize = 100 """ + [Common] chainlink_node_funding = 0.7 [VRFv2Plus] [VRFv2Plus.General] +sub_billing_tolerance_wei = 1e15 +use_test_coordinator = false cancel_subs_after_test_run = true use_existing_env = false #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request @@ -162,19 +292,17 @@ bhs_test_rate_limit_unit_duration = "3s" bhs_test_rps = 1 #SOAK TEST CONFIG -[Soak.Common] -chainlink_node_funding = 0.1 [Soak.VRFv2Plus.General] randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 number_of_sending_keys_to_create = 0 -subscription_funding_amount_link = 50 -subscription_funding_amount_native=10 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [Soak.VRFv2Plus.Performance] -test_duration = "2m" +test_duration = "2h" rate_limit_unit_duration = "10s" rps = 1 bhs_test_duration = "1m" @@ -206,24 +334,26 @@ bhs_test_rps = 1 chainlink_node_funding = 0.1 [Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 30 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 number_of_sending_keys_to_create = 0 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native=1 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "10s" rps = 1 bhs_test_duration = "1m" bhs_test_rate_limit_unit_duration = "3s" bhs_test_rps = 1 ### POLYGON AMOY Config - +[POLYGON_AMOY.Common] +chainlink_node_funding = 5 [POLYGON_AMOY.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 3 @@ -233,7 +363,7 @@ callback_gas_limit = 1000000 # NEW ENV CONFIG # CL Node config -cl_node_max_gas_price_gwei = 200 +cl_node_max_gas_price_gwei = 500 number_of_sending_keys_to_create = 0 # Coordinator config @@ -271,108 +401,64 @@ bhs_job_poll_period = "2s" bhs_job_run_timeout = "30s" # NEW ENV CONFIG END -[POLYGON_AMOY.VRFv2Plus.ExistingEnv] -coordinator_address = "0x7541EbaE23f32B4A1A2e7a8Cbf9da9582767A9B4" -consumer_address = "" -sub_id = "" -key_hash = "0xd360445bacd26df47086ccf255c4f932d297ed8d5c7334b51eed32f61c541601" -#key_hash = "0x2328cbee29e32d0b6662d6df82ff0fea7be300bd310561c92f515c9ee19464f1" -#key_hash = "0x25f4e2d0509f42ec77db5380f3433a89fe623fa75f65d5b398d5f498327be4dd" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 10 -node_sending_keys = [ - "0xD96013C241f1741C35a135321969f92Aae02A12F", - "0x0580E61a5523F5CAAC4968E4f8FE63b59596BdD7", - "0xd15FcEa6a6AA17085930Fbd5647A9F7fD2Ff58b8", - "0xB7277cBb6E7028AE65235b8ee9201AcBb14B11d4", - "0x6D36a1dC1eEd25C75961E989c4d01Cd4453bE465", - "0xd299Cd7C0073b71e620bf8A3bfD50F75c0b49af8", - "0x48BE7BAED0b65776D85DF971fA901c637cFC5e87", - # BHS - "0x638372de870eF0F8E675A3f67F18D5bd4A2fd804", - "0xF9eF03816411D037202d5ed4457dC1613e3bd729", - "0xCD66973f8fbaE787211EC20228c6bd90D83562A8", - "0x242ea1F4Bb72EF643B2D8EF22e18a89f00742F40", - "0xaA09B4F9B5710b239fdbf1D0f535dd7f86F91219", - "0xe6b72B647B8B45C5562F7a5259E187889C747d3b", - "0x2c1185C4d3B0B4a577d4079Ee193A4e293164D9d" -] - #SMOKE TEST CONFIG [POLYGON_AMOY-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5 +subscription_funding_amount_link = 3 subscription_funding_amount_native = 1 -subscription_refunding_amount_link = 5 +subscription_refunding_amount_link = 3 subscription_refunding_amount_native = 1 number_of_words = 1 random_words_fulfilled_event_timeout = "1m30s" wait_for_256_blocks_timeout = "15m" wrapper_consumer_funding_amount_native_token = 1.0 -wrapper_consumer_funding_amount_link = 5 - - -[POLYGON_AMOY-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "15s" -rps = 1 +wrapper_consumer_funding_amount_link = 3 - -#SOAK TEST CONFIG [POLYGON_AMOY-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 subscription_funding_amount_link = 500 -subscription_funding_amount_native = 200 +subscription_funding_amount_native = 100 [POLYGON_AMOY-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[POLYGON_AMOY-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[POLYGON_AMOY-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [POLYGON_AMOY-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [POLYGON_AMOY-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 ### ARBITRUM SEPOLIA Config - [ARBITRUM_SEPOLIA.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 0 -subscription_billing_type = "LINK_AND_NATIVE" +## NEW ENV CONFIG +## CL Node config cl_node_max_gas_price_gwei = 50 number_of_sending_keys_to_create = 0 -# Coordinator config +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" callback_gas_limit = 1000000 + +# Coordinator config max_gas_limit_coordinator_config = 2500000 fallback_wei_per_unit_link = "5352799651145251" staleness_seconds = 172_800 @@ -407,36 +493,7 @@ bhs_job_poll_period = "300ms" bhs_job_run_timeout = "30s" # NEW ENV CONFIG END -[ARBITRUM_SEPOLIA.VRFv2Plus.ExistingEnv] -coordinator_address = "0xF7ba1Cf141F9729abC43c146dc2bf86EbcfD8603" -consumer_address = "" -sub_id = "" -key_hash = "0xe13aa26fe94bfcd2ae055911f4d3bf1aed54ca6cf77af34e17f918802fd69ba1" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 20 -node_sending_keys = [ - "0xbE21ae371FcA1aC2d8A152e707D21e68d7d99252", - "0xb13e9BA0aE94FD3b89B13b092e6d41614c805134", - "0x27aa703e585Ee165B7c977EAA652eCFa13b08294", - "0x9324643ACD2ec5b0813488E5EdAb64C3758ae4Ee", - "0x7CBA8c8e86f23f23363051650Fe5AE4DE78c3652", - "0x9A0143a4BAB55A826331A8ef82462557633aA016", - "0xD4259633F8e87949F683433a17e1fFcCE27865AC", - "0x5e47B71d6F95f68cd5538907ec6A9635b1Fe30Fa", - "0xa850a1a257FDF439c8f854ce3b89dd5b6F411827", - "0x7c82D56087c10aF2c3970f9a9Be7786B2850ce91", - "0x9545CB59956347d3debf27f5029754bBE1d398FA", - "0xEb8C69ac19709f27A97FB4A561f51AD2F9b34c5B", - # BHS - "0xf0e8cF7Fbd28Fc4D412B76B744CDA269df671F8e", - "0x317A02A658d12E5Bb4A6270171E7385928dD2d53", - "0x480f1dbcEc118Bd91e4dbb7e45bFa4A73180d21f", - "0x500a2662FaF981EC4669f791349D37Cbf1bE7d85", - "0x2ad350374B904c10B47c64ECdBD9e70BB0833Be2", - "0x0b946F0bF4e63C12b5157137f1c130f0788bC1b1", - # BHF - "0x571BBF4a5b07fc3F47Bd3B65CE2FE73739f86623" -] + #SMOKE TEST CONFIG [ARBITRUM_SEPOLIA-Smoke.VRFv2Plus.General] @@ -445,8 +502,8 @@ randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be l number_of_sub_to_create = 1 subscription_funding_amount_link = 5 subscription_funding_amount_native = 1 -subscription_refunding_amount_link = 20 -subscription_refunding_amount_native = 10 +subscription_refunding_amount_link = 5 +subscription_refunding_amount_native = 1 number_of_words = 1 random_words_fulfilled_event_timeout = "1m30s" wait_for_256_blocks_timeout = "100s" @@ -454,55 +511,37 @@ wait_for_256_blocks_timeout = "100s" wrapper_consumer_funding_amount_native_token = 1.0 wrapper_consumer_funding_amount_link = 5 -[ARBITRUM_SEPOLIA-Smoke.VRFv2Plus.Performance] -test_duration = "1s" -rate_limit_unit_duration = "10s" -rps = 1 - - -#SOAK TEST CONFIG [ARBITRUM_SEPOLIA-Soak.VRFv2Plus.General] randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 subscription_funding_amount_native = 100 [ARBITRUM_SEPOLIA-Soak.VRFv2Plus.Performance] -test_duration = "1h" +test_duration = "2h" rate_limit_unit_duration = "10s" rps = 1 -# LOAD TEST CONFIG -[ARBITRUM_SEPOLIA-Load.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 100 -subscription_funding_amount_native = 60 - -[ARBITRUM_SEPOLIA-Load.VRFv2Plus.Performance] -test_duration = "30m" -rate_limit_unit_duration = "3s" -rps = 1 - - -# STRESS TEST CONFIG [ARBITRUM_SEPOLIA-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 150 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [ARBITRUM_SEPOLIA-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 - ### AVALANCHE FUJI Config +[AVALANCHE_FUJI.Common] +chainlink_node_funding = 3 [AVALANCHE_FUJI.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 0 @@ -550,28 +589,15 @@ bhs_job_poll_period = "2s" bhs_job_run_timeout = "30s" # NEW ENV CONFIG END -[AVALANCHE_FUJI.VRFv2Plus.ExistingEnv] -coordinator_address = "0xE122bf3Badd6545bDec5D4627a6DAd16352A1b36" -consumer_address = "" -sub_id = "" -key_hash = "0x5b03254a80ea3eb72139ff0423cb88be42612780c3dd25f1d95a5ba7708a4be1" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 50 -node_sending_keys = [ - "0x3D7Da5D6A23CA2240CE576C8638C1798a023920a", - # BHS - "0x72c8565279430F5179b0090d51ab8BB53Da323B5" -] - #SMOKE TEST CONFIG [AVALANCHE_FUJI-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 20 -subscription_funding_amount_native = 20 -subscription_refunding_amount_link = 20 -subscription_refunding_amount_native = 20 +subscription_funding_amount_link = 3 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 3 +subscription_refunding_amount_native = 1 number_of_words = 1 random_words_fulfilled_event_timeout = "1m30s" wait_for_256_blocks_timeout = "10m" @@ -579,56 +605,39 @@ wait_for_256_blocks_timeout = "10m" wrapper_consumer_funding_amount_native_token = 1.0 wrapper_consumer_funding_amount_link = 5 -[AVALANCHE_FUJI-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "10s" -rps = 1 - - -#SOAK TEST CONFIG [AVALANCHE_FUJI-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 400 -subscription_funding_amount_native = 200 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [AVALANCHE_FUJI-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[AVALANCHE_FUJI-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[AVALANCHE_FUJI-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [AVALANCHE_FUJI-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [AVALANCHE_FUJI-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 -### ETH SEPOLIA Config -[SEPOLIA.VRFv2Plus.General] +### BASE SEPOLIA Config +[BASE_SEPOLIA.Common] +chainlink_node_funding = 5 +[BASE_SEPOLIA.VRFv2Plus.General] +use_test_coordinator = false #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request -minimum_confirmations = 3 +minimum_confirmations = 0 # Consumer Request config subscription_billing_type = "LINK_AND_NATIVE" @@ -636,119 +645,373 @@ callback_gas_limit = 1000000 # NEW ENV CONFIG # CL Node config -cl_node_max_gas_price_gwei = 100 +cl_node_max_gas_price_gwei = 30 number_of_sending_keys_to_create = 0 # Coordinator config max_gas_limit_coordinator_config = 2500000 -fallback_wei_per_unit_link = "5354747932930759" +fallback_wei_per_unit_link = "3962147213857640" staleness_seconds = 172_800 -gas_after_payment_calculation = 38_900 +gas_after_payment_calculation = 42_500 fulfillment_flat_fee_native_ppm = 0 fulfillment_flat_fee_link_discount_ppm = 0 -native_premium_percentage = 24 -link_premium_percentage = 20 +native_premium_percentage = 60 +link_premium_percentage = 50 # Wrapper config wrapped_gas_overhead = 13_400 -coordinator_gas_overhead_native = 90_000 -coordinator_gas_overhead_link = 112_000 +coordinator_gas_overhead_native = 128_500 +coordinator_gas_overhead_link = 150_400 coordinator_gas_overhead_per_word = 435 -coordinator_native_premium_percentage = 24 -coordinator_link_premium_percentage = 20 +coordinator_native_premium_percentage = 60 +coordinator_link_premium_percentage = 50 wrapper_max_number_of_words = 10 # VRF Job config vrf_job_forwarding_allowed = false vrf_job_estimate_gas_multiplier = 1.15 -vrf_job_batch_fulfillment_enabled = false +vrf_job_batch_fulfillment_enabled = true vrf_job_batch_fulfillment_gas_multiplier = 1.1 -vrf_job_poll_period = "5s" +vrf_job_poll_period = "2s" vrf_job_request_timeout = "2h0m0s" -vrf_job_simulation_block = "latest" +vrf_job_simulation_block = "pending" # BHS Job config bhs_job_wait_blocks = 30 bhs_job_lookback_blocks = 200 -bhs_job_poll_period = "30s" -bhs_job_run_timeout = "1m0s" +bhs_job_poll_period = "2s" +bhs_job_run_timeout = "30s" # NEW ENV CONFIG END -[SEPOLIA.VRFv2Plus.ExistingEnv] -coordinator_address = "0x2F3b892710523Ee9A85c3155a42089fFe99Ca31e" -consumer_address = "" -sub_id = "" -key_hash = "0xf5b4a359df0598eef89872ea2170f2afa844dbf74b417e6d44d4bda9420aceb2" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 50 -node_sending_keys = [ - "0x0c0DC7f33A1256f0247c5ea75861d385fa5FED31", - # BHS - "0xEd8A4b792d16484f6c9B4df1e721e8280925Db80", -] +#SMOKE TEST CONFIG +[BASE_SEPOLIA-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 3 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 3 +subscription_refunding_amount_native = 1 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "10m" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 + +[BASE_SEPOLIA-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 + +[BASE_SEPOLIA-Soak.VRFv2Plus.Performance] +test_duration = "2h" +rate_limit_unit_duration = "10s" +rps = 1 + +[BASE_SEPOLIA-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 + +[BASE_SEPOLIA-Stress.VRFv2Plus.Performance] +test_duration = "10m" +rate_limit_unit_duration = "1m" +rps = 1 + + +### OPTIMISM SEPOLIA Config +[OPTIMISM_SEPOLIA.Common] +chainlink_node_funding = 5 +[OPTIMISM_SEPOLIA.VRFv2Plus.General] +sub_billing_tolerance_wei = 1e16 +use_test_coordinator = false +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 0 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 30 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "3896881047706782" +staleness_seconds = 172_800 +gas_after_payment_calculation = 42_500 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 60 +link_premium_percentage = 50 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 128_500 +coordinator_gas_overhead_link = 150_400 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 60 +coordinator_link_premium_percentage = 50 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 1.15 +vrf_job_batch_fulfillment_enabled = true +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "2s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "pending" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "2s" +bhs_job_run_timeout = "30s" +# NEW ENV CONFIG END #SMOKE TEST CONFIG -[SEPOLIA-Smoke.VRFv2Plus.General] +[OPTIMISM_SEPOLIA-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5 +subscription_funding_amount_link = 10 subscription_funding_amount_native = 1 -subscription_refunding_amount_link = 5 +subscription_refunding_amount_link = 10 subscription_refunding_amount_native = 1 number_of_words = 1 random_words_fulfilled_event_timeout = "1m30s" -wait_for_256_blocks_timeout = "70m" +wait_for_256_blocks_timeout = "10m" wrapper_consumer_funding_amount_native_token = 1.0 wrapper_consumer_funding_amount_link = 5 -[SEPOLIA-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "3s" +[OPTIMISM_SEPOLIA-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 + +[OPTIMISM_SEPOLIA-Soak.VRFv2Plus.Performance] +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 -#SOAK TEST CONFIG -[SEPOLIA-Soak.VRFv2Plus.General] +[OPTIMISM_SEPOLIA-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 + +[OPTIMISM_SEPOLIA-Stress.VRFv2Plus.Performance] +test_duration = "10m" +rate_limit_unit_duration = "1m" +rps = 1 + + +### SONEIUM SEPOLIA Config +[SONEIUM_SEPOLIA.Common] +chainlink_node_funding = 5 +[SONEIUM_SEPOLIA.VRFv2Plus.General] +use_test_coordinator = false +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 0 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 30 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "4619667900000000" +staleness_seconds = 172_800 +gas_after_payment_calculation = 42_500 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 60 +link_premium_percentage = 50 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 128_500 +coordinator_gas_overhead_link = 150_400 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 60 +coordinator_link_premium_percentage = 50 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 1.15 +vrf_job_batch_fulfillment_enabled = true +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "2s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "pending" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "2s" +bhs_job_run_timeout = "30s" +# NEW ENV CONFIG END + +#SMOKE TEST CONFIG +[SONEIUM_SEPOLIA-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 +subscription_funding_amount_link = 3 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 3 +subscription_refunding_amount_native = 1 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "10m" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 + +[SONEIUM_SEPOLIA-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 subscription_funding_amount_link = 500 -subscription_funding_amount_native = 200 +subscription_funding_amount_native = 100 -[SEPOLIA-Soak.VRFv2Plus.Performance] +[SONEIUM_SEPOLIA-Soak.VRFv2Plus.Performance] test_duration = "2h" -rate_limit_unit_duration = "3s" +rate_limit_unit_duration = "10s" rps = 1 -# LOAD TEST CONFIG -[SEPOLIA-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +[SONEIUM_SEPOLIA-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 30 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 -[SEPOLIA-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +[SONEIUM_SEPOLIA-Stress.VRFv2Plus.Performance] +test_duration = "10m" +rate_limit_unit_duration = "1m" +rps = 1 + + +### ETH SEPOLIA Config +[SEPOLIA.VRFv2Plus.General] +use_test_coordinator = true +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 3 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 100 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "5354747932930759" +staleness_seconds = 172_800 +gas_after_payment_calculation = 38_900 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 24 +link_premium_percentage = 20 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 90_000 +coordinator_gas_overhead_link = 112_000 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 24 +coordinator_link_premium_percentage = 20 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 1.15 +vrf_job_batch_fulfillment_enabled = false +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "5s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "latest" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "30s" +bhs_job_run_timeout = "1m0s" +# NEW ENV CONFIG END + +#SMOKE TEST CONFIG +[SEPOLIA-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 3 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 3 +subscription_refunding_amount_native = 1 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "70m" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 3 + +[SEPOLIA-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 + +[SEPOLIA-Soak.VRFv2Plus.Performance] +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 -# STRESS TEST CONFIG [SEPOLIA-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 30 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [SEPOLIA-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 -### BSC SEPOLIA Config +### BSC TESTNET Config [BSC_TESTNET.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 3 @@ -796,76 +1059,51 @@ bhs_job_poll_period = "2s" bhs_job_run_timeout = "30s" # NEW ENV CONFIG END -[BSC_TESTNET.VRFv2Plus.ExistingEnv] -coordinator_address = "0x84A477F6ebF33501eE3ACA86fEcB980b1fC99AC2" -consumer_address = "" -sub_id = "" -key_hash = "0x4d43763d3eff849a89cf578a42787baa32132d7a80032125710e95b3972cd214" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 150 -node_sending_keys = [ - "0x4EE2Cc6D50E8acb6BaEf673B03559525a6c92fB8", - # BHS - "0xAFB44568f7DAc218EA6e1C71c366692ED4758A07" -] - #SMOKE TEST CONFIG [BSC_TESTNET-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 10 -subscription_funding_amount_native = 10 - -[BSC_TESTNET-Smoke.VRFv2Plus.Performance] -test_duration = "15s" -rate_limit_unit_duration = "3s" -rps = 1 +subscription_funding_amount_link = 3 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 3 +subscription_refunding_amount_native = 1 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "15m" +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 -#SOAK TEST CONFIG [BSC_TESTNET-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 400 -subscription_funding_amount_native = 200 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [BSC_TESTNET-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[BSC_TESTNET-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[BSC_TESTNET-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [BSC_TESTNET-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [BSC_TESTNET-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 - ### NEXON QA Config [NEXON_QA.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 0 generate_txs_on_chain = true @@ -874,20 +1112,6 @@ generate_txs_on_chain = true subscription_billing_type = "LINK_AND_NATIVE" callback_gas_limit = 1000000 -[NEXON_QA.VRFv2Plus.ExistingEnv] -coordinator_address = "0xF1F0beBcc284591FCD28d8f2BAc9f30efdA3E0ea" -consumer_address = "" -sub_id = "" -key_hash = "0x7d5692e71807c4c02f5a109627a9ad2b12a361a346790a306983af9a5e3a186f" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 30 -node_sending_keys = [ - "0xB97c0C52A2B957b45DA213e652c76090DDd0FEc6", - "0xe205F5d4a99ca0f474d0b4d12f60a0153c786B4E", - # BHS - "0xf85E291edF0352435f2fD5e817030f6542375a99", -] - #SMOKE TEST CONFIG [NEXON_QA-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request @@ -903,55 +1127,35 @@ wait_for_256_blocks_timeout = "25m" wrapper_consumer_funding_amount_link = 21 wrapper_consumer_funding_amount_native_token = 3 - -[NEXON_QA-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "3s" -rps = 1 - - -#SOAK TEST CONFIG [NEXON_QA-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 400 -subscription_funding_amount_native = 200 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [NEXON_QA-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[NEXON_QA-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[NEXON_QA-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [NEXON_QA-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 2 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [NEXON_QA-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 ### NEXON DEV Config [NEXON_DEV.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 0 generate_txs_on_chain = true @@ -960,19 +1164,6 @@ generate_txs_on_chain = true subscription_billing_type = "LINK_AND_NATIVE" callback_gas_limit = 1000000 -[NEXON_DEV.VRFv2Plus.ExistingEnv] -coordinator_address = "0x6901d7236A823E7B7911d90FBe46E6FA770CC823" -consumer_address = "" -sub_id = "" -key_hash = "0xdc023892a41e5fe74ec7c4c2e8c0a808b01aea7acaf2b2ae30f4e08df877c48b" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 30 -node_sending_keys = [ - "0xF3d9879a75BBD85890056D7c6cB37C555F9b41A3", - # BHS - "0xb544f9D7c16a30af0EEd0afcC4132D1c63bAF8AC", -] - #SMOKE TEST CONFIG [NEXON_DEV-Smoke.VRFv2Plus.General] randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request @@ -988,55 +1179,35 @@ wait_for_256_blocks_timeout = "25m" wrapper_consumer_funding_amount_link = 21 wrapper_consumer_funding_amount_native_token = 3 -[NEXON_DEV-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "3s" -rps = 1 - - -#SOAK TEST CONFIG [NEXON_DEV-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 400 -subscription_funding_amount_native = 200 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [NEXON_DEV-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[NEXON_DEV-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[NEXON_DEV-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [NEXON_DEV-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [NEXON_DEV-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 - ### NEXON TEST Config [NEXON_TEST.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 0 generate_txs_on_chain = true @@ -1045,19 +1216,6 @@ generate_txs_on_chain = true subscription_billing_type = "LINK_AND_NATIVE" callback_gas_limit = 1000000 -[NEXON_TEST.VRFv2Plus.ExistingEnv] -coordinator_address = "0xAa92Ba21168B48195cAdB87cfaB3eB70B2499F55" -consumer_address = "" -sub_id = "" -key_hash = "0x0cb2a18e8b762cb4c8f7b17a6cc02ac7b9d2a3346f048cfd2f5d37677f8747d8" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 30 -node_sending_keys = [ - "0xBFD780Af421e98C35918e10B9d6da7389C3e1D10", - "0xbf6c76024672F233aB8164EC00683e1AE774F6b0", - # BHS - "0x2a3900Ac77de110670E060DBFf4fCbe36c6f8170", -] #SMOKE TEST CONFIG [NEXON_TEST-Smoke.VRFv2Plus.General] @@ -1074,55 +1232,36 @@ wait_for_256_blocks_timeout = "25m" wrapper_consumer_funding_amount_link = 5 wrapper_consumer_funding_amount_native_token = 3 -[NEXON_TEST-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "3s" -rps = 1 - - -#SOAK TEST CONFIG [NEXON_TEST-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 400 -subscription_funding_amount_native = 200 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [NEXON_TEST-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[NEXON_TEST-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[NEXON_TEST-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [NEXON_TEST-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [NEXON_TEST-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 ### NEXON STAGE Config [NEXON_STAGE.VRFv2Plus.General] +use_test_coordinator = true #todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request minimum_confirmations = 0 generate_txs_on_chain = true @@ -1131,15 +1270,6 @@ generate_txs_on_chain = true subscription_billing_type = "LINK_AND_NATIVE" callback_gas_limit = 1000000 -[NEXON_STAGE.VRFv2Plus.ExistingEnv] -coordinator_address = "0xF705dD3e7E717F32de0Cc5F833f8009f16122AD1" -consumer_address = "" -sub_id = "" -key_hash = "0xbc9f525e3e1d9e2336f7c77d5f33f5b60aab3765944617fed7f66a6afecac616" -create_fund_subs_and_add_consumers = true -node_sending_key_funding_min = 30 -node_sending_keys = [ -] #SMOKE TEST CONFIG [NEXON_STAGE-Smoke.VRFv2Plus.General] @@ -1156,48 +1286,28 @@ wait_for_256_blocks_timeout = "25m" wrapper_consumer_funding_amount_link = 21 wrapper_consumer_funding_amount_native_token = 3 -[NEXON_STAGE-Smoke.VRFv2Plus.Performance] -test_duration = "2s" -rate_limit_unit_duration = "3s" -rps = 1 - - -#SOAK TEST CONFIG [NEXON_STAGE-Soak.VRFv2Plus.General] -randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 400 -subscription_funding_amount_native = 200 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 100 [NEXON_STAGE-Soak.VRFv2Plus.Performance] -test_duration = "5h" -rate_limit_unit_duration = "3s" -rps = 1 - -# LOAD TEST CONFIG -[NEXON_STAGE-Load.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting -number_of_sub_to_create = 1 -subscription_funding_amount_link = 300 -subscription_funding_amount_native = 300 - -[NEXON_STAGE-Load.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "2h" +rate_limit_unit_duration = "10s" rps = 1 - -# STRESS TEST CONFIG [NEXON_STAGE-Stress.VRFv2Plus.General] -randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request -randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +randomness_request_count_per_request = 60 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting number_of_sub_to_create = 1 -subscription_funding_amount_link = 5.0 -subscription_funding_amount_native = 0.1 +number_of_sending_keys_to_create = 0 +subscription_funding_amount_link = 500 +subscription_funding_amount_native=100 [NEXON_STAGE-Stress.VRFv2Plus.Performance] -test_duration = "2m" -rate_limit_unit_duration = "3s" +test_duration = "10m" +rate_limit_unit_duration = "1m" rps = 1 diff --git a/integration-tests/testreporters/keeper.go b/integration-tests/testreporters/keeper.go index 0861203f314..64e3cfa3d65 100644 --- a/integration-tests/testreporters/keeper.go +++ b/integration-tests/testreporters/keeper.go @@ -13,7 +13,7 @@ import ( "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go index 6d6221fac89..c85de92493e 100644 --- a/integration-tests/testreporters/keeper_benchmark.go +++ b/integration-tests/testreporters/keeper_benchmark.go @@ -14,7 +14,7 @@ import ( "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/testreporters/ocr.go b/integration-tests/testreporters/ocr.go index 9a9c4d0d4a0..89e24fb7965 100644 --- a/integration-tests/testreporters/ocr.go +++ b/integration-tests/testreporters/ocr.go @@ -12,7 +12,7 @@ import ( "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" ) //TODO: This whole process can definitely be simplified and improved, but for some reason I'm getting brain block at the moment diff --git a/integration-tests/testreporters/profile.go b/integration-tests/testreporters/profile.go index 464cfd685e7..967ae9eaed6 100644 --- a/integration-tests/testreporters/profile.go +++ b/integration-tests/testreporters/profile.go @@ -10,7 +10,7 @@ import ( "github.com/slack-go/slack" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/testreporters/vrfv2.go b/integration-tests/testreporters/vrfv2.go index 5f4e9dcc1fc..ba17859512f 100644 --- a/integration-tests/testreporters/vrfv2.go +++ b/integration-tests/testreporters/vrfv2.go @@ -8,7 +8,7 @@ import ( "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/types" ) diff --git a/integration-tests/testreporters/vrfv2plus.go b/integration-tests/testreporters/vrfv2plus.go index cb65b0f3d40..b71c0b7d928 100644 --- a/integration-tests/testreporters/vrfv2plus.go +++ b/integration-tests/testreporters/vrfv2plus.go @@ -11,7 +11,7 @@ import ( "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" ) type VRFV2PlusTestReporter struct { diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/automation_benchmark.go similarity index 77% rename from integration-tests/testsetups/keeper_benchmark.go rename to integration-tests/testsetups/automation_benchmark.go index 5ea3fb8a3cc..ff8100ea437 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/automation_benchmark.go @@ -12,6 +12,10 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + + "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -21,22 +25,23 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - keepertestconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/keeper" + autotestconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" tt "github.com/smartcontractkit/chainlink/integration-tests/types" ) @@ -51,6 +56,7 @@ type KeeperBenchmarkTest struct { log zerolog.Logger startingBlock *big.Int + automationTests []automationv2.AutomationTest keeperRegistries []contracts.KeeperRegistry keeperRegistrars []contracts.KeeperRegistrar keeperConsumerContracts []contracts.AutomationConsumerBenchmark @@ -60,13 +66,9 @@ type KeeperBenchmarkTest struct { namespace string chainlinkNodes []*client.ChainlinkK8sClient chainClient *seth.Client - testConfig tt.KeeperBenchmarkTestConfig + testConfig tt.AutomationBenchmarkTestConfig - linkToken contracts.LinkToken - linkethFeed contracts.MockLINKETHFeed - gasFeed contracts.MockGasFeed - ethusdFeed contracts.MockETHUSDFeed - wrappedNative contracts.WETHToken + linkToken contracts.LinkToken } // UpkeepConfig dictates details of how the test's upkeep contracts should be called and configured @@ -80,22 +82,11 @@ type UpkeepConfig struct { FirstEligibleBuffer int64 // How many blocks to add to randomised first eligible block, set to 0 to disable randomised first eligible block } -// PreDeployedContracts are contracts that are already deployed on a (usually) live testnet chain, so re-deployment -// in unnecessary -type PreDeployedContracts struct { - RegistryAddress string - RegistrarAddress string - LinkTokenAddress string - EthFeedAddress string - GasFeedAddress string -} - // KeeperBenchmarkTestInputs are all the required inputs for a Keeper Benchmark Test type KeeperBenchmarkTestInputs struct { BlockchainClient *seth.Client // Client for the test to connect to the blockchain with KeeperRegistrySettings *contracts.KeeperRegistrySettings // Settings of each keeper contract Upkeeps *UpkeepConfig - Contracts *PreDeployedContracts Timeout time.Duration // Timeout for the test ChainlinkNodeFunding *big.Float // Amount of ETH to fund each chainlink node with UpkeepSLA int64 // SLA in number of blocks for an upkeep to be performed once it becomes eligible @@ -116,15 +107,16 @@ func NewKeeperBenchmarkTest(t *testing.T, inputs KeeperBenchmarkTestInputs) *Kee } // Setup prepares contracts for the test -func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.KeeperBenchmarkTestConfig) { +func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config testconfig.TestConfig) { startTime := time.Now() k.TestReporter.Summary.StartTime = startTime.UnixMilli() k.ensureInputValues() k.env = env k.namespace = k.env.Cfg.Namespace inputs := k.Inputs - k.testConfig = config + k.testConfig = &config + k.automationTests = make([]automationv2.AutomationTest, len(inputs.RegistryVersions)) k.keeperRegistries = make([]contracts.KeeperRegistry, len(inputs.RegistryVersions)) k.keeperRegistrars = make([]contracts.KeeperRegistrar, len(inputs.RegistryVersions)) k.keeperConsumerContracts = make([]contracts.AutomationConsumerBenchmark, len(inputs.RegistryVersions)) @@ -132,8 +124,8 @@ func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.Keep k.log.Debug().Interface("TestInputs", inputs).Msg("Setting up benchmark test") // if not present disable it - if k.testConfig.GetKeeperConfig().Resiliency == nil { - k.testConfig.GetKeeperConfig().Resiliency = &keepertestconfig.ResiliencyConfig{ + if k.testConfig.GetAutomationConfig().Resiliency == nil { + k.testConfig.GetAutomationConfig().Resiliency = &autotestconfig.ResiliencyConfig{ ContractCallLimit: ptr.Ptr(uint(0)), ContractCallInterval: ptr.Ptr(blockchain.StrDuration{Duration: 0 * time.Second}), } @@ -154,40 +146,22 @@ func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.Keep } } - c := inputs.Contracts - - if common.IsHexAddress(c.LinkTokenAddress) { - _, err = contracts.LoadLinkTokenContract(k.log, k.chainClient, common.HexToAddress(c.LinkTokenAddress)) - require.NoError(k.t, err, "Loading Link Token Contract shouldn't fail") - } else { - k.linkToken, err = contracts.DeployLinkTokenContract(k.log, k.chainClient) - require.NoError(k.t, err, "Deploying mock Link Token Contract feed shouldn't fail") - } - - if common.IsHexAddress(c.EthFeedAddress) { - _, err = contracts.LoadMockLINKETHFeed(k.chainClient, common.HexToAddress(c.EthFeedAddress)) - require.NoError(k.t, err, "Loading ETH-Link feed Contract shouldn't fail") - } else { - k.linkethFeed, err = contracts.DeployMockLINKETHFeed(k.chainClient, big.NewInt(2e18)) - require.NoError(k.t, err, "Deploying mock ETH-Link feed shouldn't fail") - } - - if common.IsHexAddress(c.GasFeedAddress) { - k.gasFeed, err = contracts.LoadMockGASFeed(k.chainClient, common.HexToAddress(c.GasFeedAddress)) - require.NoError(k.t, err, "Loading Gas feed Contract shouldn't fail") - } else { - k.gasFeed, err = contracts.DeployMockGASFeed(k.chainClient, big.NewInt(2e11)) - require.NoError(k.t, err, "Deploying mock gas feed shouldn't fail") - } - - k.ethusdFeed, err = contracts.DeployMockETHUSDFeed(k.chainClient, big.NewInt(200000000000)) - require.NoError(k.t, err, "Deploying mock ETH-USD feed shouldn't fail") - k.wrappedNative, err = contracts.DeployWETHTokenContract(k.log, k.chainClient) - require.NoError(k.t, err, "Deploying WETH Token Contract shouldn't fail") - for index := range inputs.RegistryVersions { k.log.Info().Int("Index", index).Msg("Starting Test Setup") - k.DeployBenchmarkKeeperContracts(index) + a := automationv2.NewAutomationTestK8s(k.log, k.chainClient, k.chainlinkNodes, &config) + a.RegistrySettings = *k.Inputs.KeeperRegistrySettings + a.RegistrySettings.RegistryVersion = inputs.RegistryVersions[index] + a.RegistrarSettings = contracts.KeeperRegistrarSettings{ + AutoApproveConfigType: uint8(2), + AutoApproveMaxAllowed: math.MaxUint16, + MinLinkJuels: big.NewInt(0), + } + a.PluginConfig = actions.ReadPluginConfig(config) + a.PublicConfig = actions.ReadPublicConfig(config) + a.SetupAutomationDeploymentWithoutJobs(k.t) + err = a.SetConfigOnRegistry() + require.NoError(k.t, err, "Setting initial config on registry shouldn't fail") + k.SetupBenchmarkKeeperContracts(index, a) } var keysToFund = inputs.RegistryVersions @@ -206,7 +180,7 @@ func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.Keep } k.log.Info().Str("Setup Time", time.Since(startTime).String()).Msg("Finished Keeper Benchmark Test Setup") - err = k.SendSlackNotification(nil, config) + err = k.SendSlackNotification(nil, &config) if err != nil { k.log.Warn().Msg("Sending test start slack notification failed") } @@ -222,7 +196,6 @@ func (k *KeeperBenchmarkTest) Run() { float64(u.BlockInterval) k.TestReporter.Summary.TestInputs = map[string]interface{}{ "NumberOfUpkeeps": u.NumberOfUpkeeps, - "BlockCountPerTurn": k.Inputs.KeeperRegistrySettings.BlockCountPerTurn, "CheckGasLimit": k.Inputs.KeeperRegistrySettings.CheckGasLimit, "MaxPerformGas": k.Inputs.KeeperRegistrySettings.MaxPerformGas, "CheckGasToBurn": u.CheckGasToBurn, @@ -239,34 +212,15 @@ func (k *KeeperBenchmarkTest) Run() { k.startingBlock = big.NewInt(0).SetUint64(startingBlock) startTime := time.Now() - nodesWithoutBootstrap := k.chainlinkNodes[1:] - for rIndex := range k.keeperRegistries { var txKeyId = rIndex if inputs.ForceSingleTxnKey { txKeyId = 0 } - kr := k.keeperRegistries[rIndex] - ocrConfig, err := actions.BuildAutoOCR2ConfigVarsWithKeyIndex( - k.t, nodesWithoutBootstrap, *inputs.KeeperRegistrySettings, kr.Address(), k.Inputs.DeltaStage, txKeyId, common.Address{}, kr.ChainModuleAddress(), kr.ReorgProtectionEnabled(), k.linkToken, k.wrappedNative, k.ethusdFeed, - ) - require.NoError(k.t, err, "Building OCR config shouldn't fail") - - rv := inputs.RegistryVersions[rIndex] - // Send keeper jobs to registry and chainlink nodes - if rv >= ethereum.RegistryVersion_2_0 { - actions.CreateOCRKeeperJobs(k.t, k.chainlinkNodes, kr.Address(), k.chainClient.ChainID, txKeyId, rv) - if rv == ethereum.RegistryVersion_2_0 { - err = kr.SetConfig(*inputs.KeeperRegistrySettings, ocrConfig) - } else { - err = kr.SetConfigTypeSafe(ocrConfig) - } - require.NoError(k.t, err, "Registry config should be be set successfully") - // Give time for OCR nodes to bootstrap - time.Sleep(1 * time.Minute) - } else { - actions.CreateKeeperJobsWithKeyIndex(k.t, k.chainlinkNodes, kr, txKeyId, ocrConfig, fmt.Sprint(k.chainClient.ChainID)) - } + k.automationTests[rIndex].SetTransmitterKeyIndex(txKeyId) + k.automationTests[rIndex].AddJobsAndSetConfig(k.t) + // Give time for OCR nodes to bootstrap + time.Sleep(1 * time.Minute) } k.log.Info().Msgf("Waiting for %d blocks for all upkeeps to be performed", inputs.Upkeeps.BlockRange+inputs.UpkeepSLA) @@ -349,7 +303,7 @@ func (k *KeeperBenchmarkTest) Run() { startedObservations.Add(1) k.log.Info().Int("Channel index", chIndex).Str("UpkeepID", upkeepIDCopy.String()).Msg("Starting upkeep observation") - confirmer := contracts.NewKeeperConsumerBenchmarkUpkeepObserver( + confirmer := contracts.NewAutomationConsumerBenchmarkUpkeepObserver( k.keeperConsumerContracts[registryIndex], k.keeperRegistries[registryIndex], upkeepIDCopy, @@ -664,7 +618,7 @@ func (k *KeeperBenchmarkTest) ensureInputValues() { } } -func (k *KeeperBenchmarkTest) SendSlackNotification(slackClient *slack.Client, config tt.KeeperBenchmarkTestConfig) error { +func (k *KeeperBenchmarkTest) SendSlackNotification(slackClient *slack.Client, config tt.AutomationBenchmarkTestConfig) error { if slackClient == nil { slackClient = slack.New(reportModel.SlackAPIKey) } @@ -698,65 +652,25 @@ func (k *KeeperBenchmarkTest) SendSlackNotification(slackClient *slack.Client, c return err } -// DeployBenchmarkKeeperContracts deploys a set amount of keeper Benchmark contracts registered to a single registry -func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { +// SetupBenchmarkKeeperContracts deploys a set amount of keeper Benchmark contracts registered to a single registry +func (k *KeeperBenchmarkTest) SetupBenchmarkKeeperContracts(index int, a *automationv2.AutomationTest) { registryVersion := k.Inputs.RegistryVersions[index] k.Inputs.KeeperRegistrySettings.RegistryVersion = registryVersion upkeep := k.Inputs.Upkeeps var ( - registry contracts.KeeperRegistry - registrar contracts.KeeperRegistrar - err error + err error ) - // Contract deployment is different for legacy keepers and OCR automation - if registryVersion <= ethereum.RegistryVersion_1_3 { // Legacy keeper - v1.X - registry, err = contracts.DeployKeeperRegistry(k.chainClient, &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: k.linkToken.Address(), - ETHFeedAddr: k.linkethFeed.Address(), - GasFeedAddr: k.gasFeed.Address(), - TranscoderAddr: actions.ZeroAddress.Hex(), - RegistrarAddr: actions.ZeroAddress.Hex(), - Settings: *k.Inputs.KeeperRegistrySettings, - }) - require.NoError(k.t, err, "Deploying registry contract shouldn't fail") - - // Fund the registry with 1 LINK * amount of AutomationConsumerBenchmark contracts - err := k.linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(k.Inputs.Upkeeps.NumberOfUpkeeps)))) - require.NoError(k.t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - - registrar, err = contracts.DeployKeeperRegistrar(k.chainClient, registryVersion, k.linkToken.Address(), registrarSettings) - require.NoError(k.t, err, "Funding keeper registrar contract shouldn't fail") - } else { // OCR automation - v2.X - registry, registrar = actions.DeployAutoOCRRegistryAndRegistrar( - k.t, k.chainClient, registryVersion, *k.Inputs.KeeperRegistrySettings, k.linkToken, k.wrappedNative, k.ethusdFeed, - ) - - // Fund the registry with LINK - err := k.linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(k.Inputs.Upkeeps.NumberOfUpkeeps)))) - require.NoError(k.t, err, "Funding keeper registry contract shouldn't fail") - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(k.t, k.chainlinkNodes[1:], *k.Inputs.KeeperRegistrySettings, registrar.Address(), k.Inputs.DeltaStage, registry.ChainModuleAddress(), registry.ReorgProtectionEnabled(), k.linkToken, k.wrappedNative, k.ethusdFeed) - require.NoError(k.t, err, "Building OCR config shouldn't fail") - k.log.Debug().Interface("KeeperRegistrySettings", *k.Inputs.KeeperRegistrySettings).Interface("OCRConfig", ocrConfig).Msg("Config") - require.NoError(k.t, err, "Error building OCR config vars") - if registryVersion == ethereum.RegistryVersion_2_0 { - err = registry.SetConfig(*k.Inputs.KeeperRegistrySettings, ocrConfig) - } else { - err = registry.SetConfigTypeSafe(ocrConfig) - } - require.NoError(k.t, err, "Registry config should be be set successfully") + var consumer contracts.AutomationConsumerBenchmark + if a.TestConfig.GetAutomationConfig().UseExistingUpkeepContracts() { + benchmarkAddresses, err := a.TestConfig.GetAutomationConfig().UpkeepContractAddresses() + require.NoError(k.t, err, "Getting upkeep contract addresses shouldn't fail") + consumer, err = contracts.LoadAutomationConsumerBenchmark(k.chainClient, benchmarkAddresses[0]) + require.NoError(k.t, err, "Loading KeeperConsumerBenchmark shouldn't fail") + } else { + consumer = k.DeployKeeperConsumersBenchmark() } - consumer := k.DeployKeeperConsumersBenchmark() - var upkeepAddresses []string checkData := make([][]byte, 0) @@ -804,14 +718,16 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { big.NewInt(0)) linkFunds = big.NewInt(0).Add(linkFunds, minLinkBalance) + k.linkToken = a.LinkToken - err = actions.DeployMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds) + err = actions.SetupMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds, a.TestConfig) require.NoError(k.t, err, "Sending link funds to deployment addresses shouldn't fail") - upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false, false, nil) + upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), a.Registry, a.Registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false, false, nil) - k.keeperRegistries[index] = registry - k.keeperRegistrars[index] = registrar + k.automationTests[index] = *a + k.keeperRegistries[index] = a.Registry + k.keeperRegistrars[index] = a.Registrar k.upkeepIDs[index] = upkeepIds k.keeperConsumerContracts[index] = consumer } @@ -820,20 +736,20 @@ func (k *KeeperBenchmarkTest) DeployKeeperConsumersBenchmark() contracts.Automat // Deploy consumer var err error var keeperConsumerInstance contracts.AutomationConsumerBenchmark - if *k.testConfig.GetKeeperConfig().Resiliency.ContractCallLimit != 0 && k.testConfig.GetKeeperConfig().Resiliency.ContractCallInterval.Duration != 0 { - maxRetryAttempts := *k.testConfig.GetKeeperConfig().Resiliency.ContractCallLimit - callRetryDelay := k.testConfig.GetKeeperConfig().Resiliency.ContractCallInterval.Duration - keeperConsumerInstance, err = contracts.DeployKeeperConsumerBenchmarkWithRetry(k.chainClient, k.log, maxRetryAttempts, callRetryDelay) + if *k.testConfig.GetAutomationConfig().Resiliency.ContractCallLimit != 0 && k.testConfig.GetAutomationConfig().Resiliency.ContractCallInterval.Duration != 0 { + maxRetryAttempts := *k.testConfig.GetAutomationConfig().Resiliency.ContractCallLimit + callRetryDelay := k.testConfig.GetAutomationConfig().Resiliency.ContractCallInterval.Duration + keeperConsumerInstance, err = contracts.DeployAutomationConsumerBenchmarkWithRetry(k.chainClient, k.log, maxRetryAttempts, callRetryDelay) if err != nil { k.log.Error().Err(err).Msg("Deploying AutomationConsumerBenchmark instance shouldn't fail") - keeperConsumerInstance, err = contracts.DeployKeeperConsumerBenchmarkWithRetry(k.chainClient, k.log, maxRetryAttempts, callRetryDelay) + keeperConsumerInstance, err = contracts.DeployAutomationConsumerBenchmarkWithRetry(k.chainClient, k.log, maxRetryAttempts, callRetryDelay) require.NoError(k.t, err, "Error deploying AutomationConsumerBenchmark") } } else { - keeperConsumerInstance, err = contracts.DeployKeeperConsumerBenchmark(k.chainClient) + keeperConsumerInstance, err = contracts.DeployAutomationConsumerBenchmark(k.chainClient) if err != nil { k.log.Error().Err(err).Msg("Deploying AutomationConsumerBenchmark instance %d shouldn't fail") - keeperConsumerInstance, err = contracts.DeployKeeperConsumerBenchmark(k.chainClient) + keeperConsumerInstance, err = contracts.DeployAutomationConsumerBenchmark(k.chainClient) require.NoError(k.t, err, "Error deploying AutomationConsumerBenchmark") } } diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 084ea5eca10..73b142b6297 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -15,35 +15,36 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink-testing-framework/grafana" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/grafana" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/pelletier/go-toml/v2" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - "github.com/smartcontractkit/havoc/k8schaos" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/foundry" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/foundry" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver-cfg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -91,12 +92,12 @@ type OCRSoakTest struct { reorgHappened bool // flag to indicate if a reorg happened during the test gasSpikeSimulationHappened bool // flag to indicate if a gas spike simulation happened during the test gasLimitSimulationHappened bool // flag to indicate if a gas limit simulation happened during the test - chaosList []*k8schaos.Chaos // list of chaos simulations to run during the test + chaosList []*havoc.Chaos // list of chaos simulations to run during the test } type OCRSoakTestOption = func(c *OCRSoakTest) -func WithChaos(chaosList []*k8schaos.Chaos) OCRSoakTestOption { +func WithChaos(chaosList []*havoc.Chaos) OCRSoakTestOption { return func(c *OCRSoakTest) { c.chaosList = chaosList } @@ -280,8 +281,8 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { o.mockServer = ctf_client.ConnectMockServer(o.testEnvironment) require.NoError(o.t, err, "Creating mockserver clients shouldn't fail") - linkContract, err := contracts.DeployLinkTokenContract(o.log, sethClient) - require.NoError(o.t, err, "Error deploying LINK contract") + linkContract, err := actions.LinkTokenContract(o.log, sethClient, ocrTestConfig.GetActiveOCRConfig()) + require.NoError(o.t, err, "Error loading/deploying link token contract") // Fund Chainlink nodes, excluding the bootstrap node o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") @@ -289,7 +290,6 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { require.NoError(o.t, err, "Error funding Chainlink nodes") var forwarders []common.Address - if o.OperatorForwarderFlow { var operators []common.Address operators, forwarders, _ = actions.DeployForwarderContracts( @@ -310,17 +310,17 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( o.log, o.seth, - *o.Config.GetActiveOCRConfig().Soak.NumberOfContracts, + o.Config.GetActiveOCRConfig(), common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), forwarders, ) require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") } else { - o.ocrV1Instances, err = actions.DeployOCRv1Contracts( + o.ocrV1Instances, err = actions.SetupOCRv1Contracts( o.log, sethClient, - *o.Config.GetActiveOCRConfig().Soak.NumberOfContracts, + o.Config.GetActiveOCRConfig(), common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), ) @@ -342,19 +342,22 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - o.ocrV2Instances, err = actions.DeployOCRv2Contracts( + o.ocrV2Instances, err = actions.SetupOCRv2Contracts( o.log, o.seth, - *ocrTestConfig.GetActiveOCRConfig().Soak.NumberOfContracts, + ocrTestConfig.GetActiveOCRConfig(), common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions, ) require.NoError(o.t, err, "Error deploying OCRv2 contracts") - contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) - require.NoError(o.t, err, "Error building median config") - err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) - require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") + + if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { + contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) + require.NoError(o.t, err, "Error building median config") + err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) + require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") + } } if o.OCRVersion == "1" { @@ -398,7 +401,7 @@ func (o *OCRSoakTest) Run() { o.log.Info(). Str("Test Duration", o.Config.GetActiveOCRConfig().Common.TestDuration.Duration.Truncate(time.Second).String()). - Int("Number of OCR Contracts", *config.GetActiveOCRConfig().Soak.NumberOfContracts). + Int("Number of OCR Contracts", *config.GetActiveOCRConfig().Common.NumberOfContracts). Str("OCR Version", o.OCRVersion). Msg("Starting OCR Soak Test") @@ -529,7 +532,7 @@ func (o *OCRSoakTest) LoadState() error { if testState.OCRVersion == "1" { o.ocrV1Instances = make([]contracts.OffchainAggregator, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffchainAggregator(o.log, o.seth, common.HexToAddress(addr)) + instance, err := contracts.LoadOffChainAggregator(o.log, o.seth, common.HexToAddress(addr)) if err != nil { return fmt.Errorf("failed to instantiate OCR instance: %w", err) } @@ -538,7 +541,7 @@ func (o *OCRSoakTest) LoadState() error { } else if testState.OCRVersion == "2" { o.ocrV2Instances = make([]contracts.OffchainAggregatorV2, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffChainAggregatorV2(o.log, o.seth, common.HexToAddress(addr)) + instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.seth, common.HexToAddress(addr)) if err != nil { return err } @@ -560,7 +563,7 @@ func (o *OCRSoakTest) Resume() { Str("Time Left", o.timeLeft.String()). Msg("Resuming OCR Soak Test") - ocrAddresses := make([]common.Address, *o.Config.GetActiveOCRConfig().Soak.NumberOfContracts) + ocrAddresses := make([]common.Address, *o.Config.GetActiveOCRConfig().Common.NumberOfContracts) if o.OCRVersion == "1" { for i, ocrInstance := range o.ocrV1Instances { @@ -679,11 +682,11 @@ func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) { if len(o.chaosList) > 0 { for _, chaos := range o.chaosList { chaos.Create(context.Background()) - chaos.AddListener(k8schaos.NewChaosLogger(o.log)) + chaos.AddListener(havoc.NewChaosLogger(o.log)) chaos.AddListener(ocrTestChaosListener{t: o.t}) // Add Grafana annotation if configured if o.Config.Logging.Grafana != nil && o.Config.Logging.Grafana.BaseUrl != nil && o.Config.Logging.Grafana.BearerToken != nil && o.Config.Logging.Grafana.DashboardUID != nil { - chaos.AddListener(k8schaos.NewSingleLineGrafanaAnnotator(*o.Config.Logging.Grafana.BaseUrl, *o.Config.Logging.Grafana.BearerToken, *o.Config.Logging.Grafana.DashboardUID, o.log)) + chaos.AddListener(havoc.NewSingleLineGrafanaAnnotator(*o.Config.Logging.Grafana.BaseUrl, *o.Config.Logging.Grafana.BearerToken, *o.Config.Logging.Grafana.DashboardUID, o.log)) } else { o.log.Warn().Msg("Skipping Grafana annotation for chaos simulation. Grafana config is missing either BearerToken, BaseUrl or DashboardUID") } @@ -740,7 +743,7 @@ func (o *OCRSoakTest) complete() { } func (o *OCRSoakTest) startGethBlockchainReorg(network blockchain.EVMNetwork, conf ctf_config.ReorgConfig) { - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) o.log.Info(). Str("URL", client.URL). Int("Depth", conf.Depth). @@ -752,7 +755,7 @@ func (o *OCRSoakTest) startGethBlockchainReorg(network blockchain.EVMNetwork, co } func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork, conf ctf_config.GasSpikeSimulationConfig) { - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) o.log.Info(). Str("URL", client.URL). Any("GasSpikeSimulationConfig", conf). @@ -765,7 +768,7 @@ func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork } func (o *OCRSoakTest) startAnvilGasLimitSimulation(network blockchain.EVMNetwork, conf ctf_config.GasLimitSimulationConfig) { - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) latestBlock, err := o.seth.Client.BlockByNumber(context.Background(), nil) require.NoError(o.t, err) newGasLimit := int64(math.Ceil(float64(latestBlock.GasUsed()) * conf.NextGasLimitPercentage)) @@ -1020,12 +1023,12 @@ func (o *OCRSoakTest) collectEvents() error { // ensureValues ensures that all values needed to run the test are present func (o *OCRSoakTest) ensureInputValues() error { - ocrConfig := o.Config.GetActiveOCRConfig().Soak + ocrConfig := o.Config.GetActiveOCRConfig() if o.OCRVersion != "1" && o.OCRVersion != "2" { return fmt.Errorf("OCR version must be 1 or 2, found %s", o.OCRVersion) } - if ocrConfig.NumberOfContracts != nil && *ocrConfig.NumberOfContracts <= 0 { - return fmt.Errorf("number of OCR contracts must be set and greater than 0, found %d", ocrConfig.NumberOfContracts) + if ocrConfig.Common.NumberOfContracts != nil && *ocrConfig.Common.NumberOfContracts <= 0 { + return fmt.Errorf("number of OCR contracts must be set and greater than 0, found %d", ocrConfig.Common.NumberOfContracts) } if o.Config.Common.ChainlinkNodeFunding != nil && *o.Config.Common.ChainlinkNodeFunding <= 0 { return fmt.Errorf("chainlink node funding must be greater than 0, found %f", *o.Config.Common.ChainlinkNodeFunding) @@ -1033,11 +1036,12 @@ func (o *OCRSoakTest) ensureInputValues() error { if o.Config.GetActiveOCRConfig().Common.TestDuration != nil && o.Config.GetActiveOCRConfig().Common.TestDuration.Duration <= time.Minute { return fmt.Errorf("test duration must be greater than 1 minute, found %s", o.Config.GetActiveOCRConfig().Common.TestDuration) } - if ocrConfig.TimeBetweenRounds != nil && ocrConfig.TimeBetweenRounds.Duration >= time.Hour { - return fmt.Errorf("time between rounds must be less than 1 hour, found %s", ocrConfig.TimeBetweenRounds) + soakConfig := ocrConfig.Soak + if soakConfig.TimeBetweenRounds != nil && soakConfig.TimeBetweenRounds.Duration >= time.Hour { + return fmt.Errorf("time between rounds must be less than 1 hour, found %s", soakConfig.TimeBetweenRounds) } - if ocrConfig.TimeBetweenRounds != nil && ocrConfig.TimeBetweenRounds.Duration < time.Second*30 { - return fmt.Errorf("time between rounds must be greater or equal to 30 seconds, found %s", ocrConfig.TimeBetweenRounds) + if soakConfig.TimeBetweenRounds != nil && soakConfig.TimeBetweenRounds.Duration < time.Second*30 { + return fmt.Errorf("time between rounds must be greater or equal to 30 seconds, found %s", soakConfig.TimeBetweenRounds) } return nil @@ -1108,28 +1112,28 @@ type ocrTestChaosListener struct { t *testing.T } -func (l ocrTestChaosListener) OnChaosCreated(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosCreated(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosCreationFailed(chaos k8schaos.Chaos, reason error) { +func (l ocrTestChaosListener) OnChaosCreationFailed(chaos havoc.Chaos, reason error) { // Fail the test if chaos creation fails during chaos simulation require.FailNow(l.t, "Error creating chaos simulation", reason.Error(), chaos) } -func (l ocrTestChaosListener) OnChaosStarted(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosStarted(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosPaused(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosPaused(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosEnded(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosEnded(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosStatusUnknown(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosStatusUnknown(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnScheduleCreated(_ k8schaos.Schedule) { +func (l ocrTestChaosListener) OnScheduleCreated(_ havoc.Schedule) { } -func (l ocrTestChaosListener) OnScheduleDeleted(_ k8schaos.Schedule) { +func (l ocrTestChaosListener) OnScheduleDeleted(_ havoc.Schedule) { } diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go index 181d57a17ed..7b5230f401f 100644 --- a/integration-tests/types/config/node/core.go +++ b/integration-tests/types/config/node/core.go @@ -14,8 +14,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/config" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" itutils "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go index ee8a614baef..7a72e9a1dfa 100644 --- a/integration-tests/types/testconfigs.go +++ b/integration-tests/types/testconfigs.go @@ -1,8 +1,9 @@ package types import ( - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + 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" ) @@ -31,10 +32,10 @@ type AutomationTestConfig interface { tc.AutomationTestConfig } -type KeeperBenchmarkTestConfig interface { +type AutomationBenchmarkTestConfig interface { ctf_config.GlobalTestConfig tc.CommonTestConfig - tc.KeeperTestConfig + tc.AutomationTestConfig ctf_config.NamedConfigurations testreporters.GrafanaURLProvider } @@ -51,3 +52,9 @@ type Ocr2TestConfig interface { tc.CommonTestConfig tc.Ocr2TestConfig } + +type CCIPTestConfig interface { + ctf_config.GlobalTestConfig + tc.CommonTestConfig + tc.CCIPTestConfig +} diff --git a/integration-tests/universal/log_poller/gun.go b/integration-tests/universal/log_poller/gun.go index a75209aa101..287041ce411 100644 --- a/integration-tests/universal/log_poller/gun.go +++ b/integration-tests/universal/log_poller/gun.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index bacb5db6ed4..ec40348947e 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -16,8 +16,10 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" @@ -27,11 +29,11 @@ import ( "github.com/scylladb/go-reflectx" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/utils/seth.go b/integration-tests/utils/seth.go index 237be1a508d..704d9547721 100644 --- a/integration-tests/utils/seth.go +++ b/integration-tests/utils/seth.go @@ -4,11 +4,10 @@ import ( "fmt" "testing" - pkg_seth "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" + pkg_seth "github.com/smartcontractkit/chainlink-testing-framework/seth" ) // DynamicArtifactDirConfigFn returns a function that sets Seth's artifacts directory to a unique directory for the test diff --git a/integration-tests/utils/templates/secrets.go b/integration-tests/utils/templates/secrets.go index 45edf0d0127..96a16bdb3eb 100644 --- a/integration-tests/utils/templates/secrets.go +++ b/integration-tests/utils/templates/secrets.go @@ -3,7 +3,7 @@ package templates import ( "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-testing-framework/utils/templates" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/templates" ) // NodeSecretsTemplate are used as text templates because of secret redacted fields of chainlink.Secrets diff --git a/integration-tests/web/sdk/README.md b/integration-tests/web/sdk/README.md new file mode 100644 index 00000000000..aa730e3a948 --- /dev/null +++ b/integration-tests/web/sdk/README.md @@ -0,0 +1,13 @@ +## GQL SDK + +This package exports a `Client` for interacting with the `feeds-manager` service of core. The implementation is based on code generated via `[genqlient](https://github.com/Khan/genqlient)`. + +### Extending the Client + +Add additional queries or mutations to `genqlient.graphql` and then regenerate the implementation via the Taskfile: + +```bash +$ task generate +``` + +Next, extend the `Client` interface and the `client` implementation. diff --git a/integration-tests/web/sdk/client/client.go b/integration-tests/web/sdk/client/client.go new file mode 100644 index 00000000000..e633bf04c15 --- /dev/null +++ b/integration-tests/web/sdk/client/client.go @@ -0,0 +1,297 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/AlekSi/pointer" + "github.com/Khan/genqlient/graphql" + + "github.com/smartcontractkit/chainlink/integration-tests/web/sdk/client/doer" + "github.com/smartcontractkit/chainlink/integration-tests/web/sdk/internal/generated" +) + +type Client interface { + FetchCSAPublicKey(ctx context.Context) (*string, error) + FetchP2PPeerID(ctx context.Context) (*string, error) + FetchAccountAddress(ctx context.Context, chainID string) (*string, error) + FetchOCR2KeyBundleID(ctx context.Context, chainType string) (string, error) + GetJob(ctx context.Context, id string) (*generated.GetJobResponse, error) + ListJobs(ctx context.Context, offset, limit int) (*generated.ListJobsResponse, error) + GetJobDistributor(ctx context.Context, id string) (generated.FeedsManagerParts, error) + ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) + CreateJobDistributor(ctx context.Context, cmd JobDistributorInput) (string, error) + UpdateJobDistributor(ctx context.Context, id string, cmd JobDistributorInput) error + CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) (string, error) + DeleteJobDistributorChainConfig(ctx context.Context, id string) error + GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) + ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) + CancelJobProposalSpec(ctx context.Context, id string) (*generated.CancelJobProposalSpecResponse, error) + RejectJobProposalSpec(ctx context.Context, id string) (*generated.RejectJobProposalSpecResponse, error) + UpdateJobProposalSpecDefinition(ctx context.Context, id string, cmd generated.UpdateJobProposalSpecDefinitionInput) (*generated.UpdateJobProposalSpecDefinitionResponse, error) +} + +type client struct { + gqlClient graphql.Client + credentials Credentials + endpoints endpoints + cookie string +} + +type endpoints struct { + Sessions string + Query string +} + +type Credentials struct { + Email string `json:"email"` + Password string `json:"password"` +} + +func New(baseURI string, creds Credentials) (Client, error) { + ep := endpoints{ + Sessions: baseURI + "/sessions", + Query: baseURI + "/query", + } + c := &client{ + endpoints: ep, + credentials: creds, + } + + if err := c.login(); err != nil { + return nil, fmt.Errorf("failed to login to node: %w", err) + } + + c.gqlClient = graphql.NewClient( + c.endpoints.Query, + doer.NewAuthed(c.cookie), + ) + + return c, nil +} + +func (c *client) FetchCSAPublicKey(ctx context.Context) (*string, error) { + keys, err := generated.FetchCSAKeys(ctx, c.gqlClient) + if err != nil { + return nil, err + } + if keys == nil || len(keys.CsaKeys.GetResults()) == 0 { + return nil, fmt.Errorf("no CSA keys found") + } + return &keys.CsaKeys.GetResults()[0].PublicKey, nil +} + +func (c *client) FetchP2PPeerID(ctx context.Context) (*string, error) { + keys, err := generated.FetchP2PKeys(ctx, c.gqlClient) + if err != nil { + return nil, err + } + if keys == nil || len(keys.P2pKeys.GetResults()) == 0 { + return nil, fmt.Errorf("no P2P keys found") + } + return &keys.P2pKeys.GetResults()[0].PeerID, nil +} + +func (c *client) FetchOCR2KeyBundleID(ctx context.Context, chainType string) (string, error) { + keyBundles, err := generated.FetchOCR2KeyBundles(ctx, c.gqlClient) + if err != nil { + return "", err + } + if keyBundles == nil || len(keyBundles.GetOcr2KeyBundles().Results) == 0 { + return "", fmt.Errorf("no ocr2 keybundle found, check if ocr2 is enabled") + } + for _, keyBundle := range keyBundles.GetOcr2KeyBundles().Results { + if keyBundle.ChainType == generated.OCR2ChainType(chainType) { + return keyBundle.GetId(), nil + } + } + return "", fmt.Errorf("no ocr2 keybundle found for chain type %s", chainType) +} + +func (c *client) FetchAccountAddress(ctx context.Context, chainID string) (*string, error) { + keys, err := generated.FetchAccounts(ctx, c.gqlClient) + if err != nil { + return nil, err + } + if keys == nil || len(keys.EthKeys.GetResults()) == 0 { + return nil, fmt.Errorf("no accounts found") + } + for _, keyDetail := range keys.EthKeys.GetResults() { + if keyDetail.GetChain().Enabled && keyDetail.GetChain().Id == chainID { + return pointer.ToString(keyDetail.Address), nil + } + } + return nil, fmt.Errorf("no account found for chain %s", chainID) +} + +func (c *client) GetJob(ctx context.Context, id string) (*generated.GetJobResponse, error) { + return generated.GetJob(ctx, c.gqlClient, id) +} + +func (c *client) ListJobs(ctx context.Context, offset, limit int) (*generated.ListJobsResponse, error) { + return generated.ListJobs(ctx, c.gqlClient, offset, limit) +} + +func (c *client) GetBridge(ctx context.Context, id string) (*generated.GetBridgeResponse, error) { + return generated.GetBridge(ctx, c.gqlClient, id) +} + +func (c *client) ListBridges(ctx context.Context, offset, limit int) (*generated.ListBridgesResponse, error) { + return generated.ListBridges(ctx, c.gqlClient, offset, limit) +} + +func (c *client) GetJobDistributor(ctx context.Context, id string) (generated.FeedsManagerParts, error) { + res, err := generated.GetFeedsManager(ctx, c.gqlClient, id) + if err != nil { + return generated.FeedsManagerParts{}, err + } + if res == nil { + return generated.FeedsManagerParts{}, fmt.Errorf("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") +} + +func (c *client) ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) { + return generated.ListFeedsManagers(ctx, c.gqlClient) +} + +func (c *client) CreateJobDistributor(ctx context.Context, in JobDistributorInput) (string, error) { + var cmd generated.CreateFeedsManagerInput + err := DecodeInput(in, &cmd) + if err != nil { + return "", err + } + response, err := generated.CreateFeedsManager(ctx, c.gqlClient, cmd) + if err != nil { + return "", err + } + // Access the FeedsManager ID + if success, ok := response.GetCreateFeedsManager().(*generated.CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess); ok { + feedsManager := success.GetFeedsManager() + return feedsManager.GetId(), nil + } + return "", fmt.Errorf("failed to create feeds manager") +} + +func (c *client) UpdateJobDistributor(ctx context.Context, id string, in JobDistributorInput) error { + var cmd generated.UpdateFeedsManagerInput + err := DecodeInput(in, &cmd) + if err != nil { + return err + } + _, err = generated.UpdateFeedsManager(ctx, c.gqlClient, id, cmd) + return err +} + +func (c *client) CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) (string, error) { + var cmd generated.CreateFeedsManagerChainConfigInput + err := DecodeInput(in, &cmd) + if err != nil { + return "", err + } + res, err := generated.CreateFeedsManagerChainConfig(ctx, c.gqlClient, cmd) + if err != nil { + return "", err + } + if res == nil { + return "", fmt.Errorf("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") +} + +func (c *client) DeleteJobDistributorChainConfig(ctx context.Context, id string) error { + res, err := generated.DeleteFeedsManagerChainConfig(ctx, c.gqlClient, id) + if err != nil { + return err + } + if res == nil { + return fmt.Errorf("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") +} + +func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) { + proposal, err := generated.GetJobProposal(ctx, c.gqlClient, id) + if err != nil { + return nil, err + } + if proposal == nil { + return nil, fmt.Errorf("no job proposal found") + } + if success, ok := proposal.GetJobProposal().(*generated.GetJobProposalJobProposal); ok { + return success, nil + } + return nil, fmt.Errorf("failed to get job proposal") +} + +func (c *client) ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) { + res, err := generated.ApproveJobProposalSpec(ctx, c.gqlClient, id, force) + if err != nil { + return nil, err + } + if success, ok := res.GetApproveJobProposalSpec().(*generated.ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess); ok { + var cmd JobProposalApprovalSuccessSpec + if success.Spec.Status == generated.SpecStatusApproved { + err := DecodeInput(success.Spec, &cmd) + if err != nil { + return nil, fmt.Errorf("failed to decode job proposal spec: %w ; and job proposal spec not approved", err) + } + return &cmd, nil + } + } + return nil, fmt.Errorf("failed to approve job proposal spec") +} + +func (c *client) CancelJobProposalSpec(ctx context.Context, id string) (*generated.CancelJobProposalSpecResponse, error) { + return generated.CancelJobProposalSpec(ctx, c.gqlClient, id) +} + +func (c *client) RejectJobProposalSpec(ctx context.Context, id string) (*generated.RejectJobProposalSpecResponse, error) { + return generated.RejectJobProposalSpec(ctx, c.gqlClient, id) +} + +func (c *client) UpdateJobProposalSpecDefinition(ctx context.Context, id string, cmd generated.UpdateJobProposalSpecDefinitionInput) (*generated.UpdateJobProposalSpecDefinitionResponse, error) { + return generated.UpdateJobProposalSpecDefinition(ctx, c.gqlClient, id, cmd) +} + +func (c *client) login() error { + b, err := json.Marshal(c.credentials) + if err != nil { + return fmt.Errorf("failed to marshal credentials: %w", err) + } + + payload := strings.NewReader(string(b)) + + req, err := http.NewRequest("POST", c.endpoints.Sessions, payload) + if err != nil { + return err + } + + req.Header.Add("Content-Type", "application/json") + + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer res.Body.Close() + + cookieHeader := res.Header.Get("Set-Cookie") + if cookieHeader == "" { + return fmt.Errorf("no cookie found in header") + } + + c.cookie = strings.Split(cookieHeader, ";")[0] + return nil +} diff --git a/integration-tests/web/sdk/client/doer/doer.go b/integration-tests/web/sdk/client/doer/doer.go new file mode 100644 index 00000000000..dde842bae5d --- /dev/null +++ b/integration-tests/web/sdk/client/doer/doer.go @@ -0,0 +1,20 @@ +package doer + +import "net/http" + +type Authed struct { + cookie string + wrapped *http.Client +} + +func NewAuthed(cookie string) *Authed { + return &Authed{ + cookie: cookie, + wrapped: http.DefaultClient, + } +} + +func (a *Authed) Do(req *http.Request) (*http.Response, error) { + req.Header.Set("cookie", a.cookie) + return a.wrapped.Do(req) +} diff --git a/integration-tests/web/sdk/client/types.go b/integration-tests/web/sdk/client/types.go new file mode 100644 index 00000000000..d213ee161c6 --- /dev/null +++ b/integration-tests/web/sdk/client/types.go @@ -0,0 +1,60 @@ +package client + +import ( + "bytes" + "encoding/json" + "fmt" + "reflect" +) + +type JobDistributorInput struct { + Name string `json:"name"` + Uri string `json:"uri"` + PublicKey string `json:"publicKey"` +} + +type JobDistributorChainConfigInput struct { + JobDistributorID string `json:"feedsManagerID"` + ChainID string `json:"chainID"` + ChainType string `json:"chainType"` + AccountAddr string `json:"accountAddr"` + AccountAddrPubKey string `json:"accountAddrPubKey"` + AdminAddr string `json:"adminAddr"` + FluxMonitorEnabled bool `json:"fluxMonitorEnabled"` + Ocr1Enabled bool `json:"ocr1Enabled"` + Ocr1IsBootstrap bool `json:"ocr1IsBootstrap"` + Ocr1Multiaddr string `json:"ocr1Multiaddr"` + Ocr1P2PPeerID string `json:"ocr1P2PPeerID"` + Ocr1KeyBundleID string `json:"ocr1KeyBundleID"` + Ocr2Enabled bool `json:"ocr2Enabled"` + Ocr2IsBootstrap bool `json:"ocr2IsBootstrap"` + Ocr2Multiaddr string `json:"ocr2Multiaddr"` + Ocr2ForwarderAddress string `json:"ocr2ForwarderAddress"` + Ocr2P2PPeerID string `json:"ocr2P2PPeerID"` + Ocr2KeyBundleID string `json:"ocr2KeyBundleID"` + Ocr2Plugins string `json:"ocr2Plugins"` +} + +type JobProposalApprovalSuccessSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status string `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +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") + } + jsonBytes, err := json.Marshal(in) + if err != nil { + return err + } + + decoder := json.NewDecoder(bytes.NewReader(jsonBytes)) + decoder.DisallowUnknownFields() + return decoder.Decode(out) +} diff --git a/integration-tests/web/sdk/client/types_test.go b/integration-tests/web/sdk/client/types_test.go new file mode 100644 index 00000000000..dd9b48274da --- /dev/null +++ b/integration-tests/web/sdk/client/types_test.go @@ -0,0 +1,67 @@ +package client + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/integration-tests/web/sdk/internal/generated" +) + +func TestDecodeInput(t *testing.T) { + type args struct { + in any + out any + } + tests := []struct { + name string + args args + wantErr bool + errMessage string + }{ + { + name: "success", + args: args{&JobDistributorInput{ + Name: "name", + Uri: "uri", + PublicKey: "publicKey", + }, &generated.CreateFeedsManagerInput{}}, + wantErr: false, + errMessage: "", + }, + { + name: "non-pointer", + args: args{&JobDistributorInput{ + Name: "name", + Uri: "uri", + PublicKey: "publicKey", + }, generated.CreateFeedsManagerInput{}}, + wantErr: true, + errMessage: "out type must be a non-nil pointer", + }, + { + name: "incorrect type", + args: args{&JobDistributorInput{ + Name: "name", + Uri: "uri", + PublicKey: "publicKey", + }, generated.CreateFeedsManagerChainConfigInput{}}, + wantErr: true, + errMessage: "json: cannot unmarshal object into Go value of type generated.CreateFeedsManagerChainConfigInput", + }, + { + name: "success", + args: args{&JobDistributorInput{ + Name: "name", + Uri: "uri", + PublicKey: "publicKey", + }, &generated.UpdateFeedsManagerInput{}}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := DecodeInput(tt.args.in, tt.args.out); (err != nil) != tt.wantErr { + t.Errorf("DecodeInput() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/integration-tests/web/sdk/genqlient.yaml b/integration-tests/web/sdk/genqlient.yaml new file mode 100644 index 00000000000..2b861a92ee4 --- /dev/null +++ b/integration-tests/web/sdk/genqlient.yaml @@ -0,0 +1,15 @@ +# Default genqlient config; for full documentation see: +# https://github.com/Khan/genqlient/blob/main/docs/genqlient.yaml +schema: ./internal/schema.graphql + +operations: +- ./internal/genqlient.graphql + +generated: ./internal/generated/generated.go + +bindings: + Time: + type: string + +package_bindings: +- package: github.com/smartcontractkit/chainlink/v2/core/web/gqlscalar diff --git a/integration-tests/web/sdk/internal/generated/generated.go b/integration-tests/web/sdk/internal/generated/generated.go new file mode 100644 index 00000000000..68ab3e48e4f --- /dev/null +++ b/integration-tests/web/sdk/internal/generated/generated.go @@ -0,0 +1,6423 @@ +// Code generated by github.com/Khan/genqlient, DO NOT EDIT. + +package generated + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/Khan/genqlient/graphql" + "github.com/smartcontractkit/chainlink/v2/core/web/gqlscalar" +) + +// ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload includes the requested fields of the GraphQL interface ApproveJobProposalSpecPayload. +// +// ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload is implemented by the following types: +// ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess +// ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError +// ApproveJobProposalSpecApproveJobProposalSpecNotFoundError +type ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload interface { + implementsGraphQLInterfaceApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess) implementsGraphQLInterfaceApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload() { +} +func (v *ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError) implementsGraphQLInterfaceApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload() { +} +func (v *ApproveJobProposalSpecApproveJobProposalSpecNotFoundError) implementsGraphQLInterfaceApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload() { +} + +func __unmarshalApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload(b []byte, v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "ApproveJobProposalSpecSuccess": + *v = new(ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess) + return json.Unmarshal(b, *v) + case "JobAlreadyExistsError": + *v = new(ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(ApproveJobProposalSpecApproveJobProposalSpecNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing ApproveJobProposalSpecPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload: "%v"`, tn.TypeName) + } +} + +func __marshalApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload(v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess: + typename = "ApproveJobProposalSpecSuccess" + + result := struct { + TypeName string `json:"__typename"` + *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess + }{typename, v} + return json.Marshal(result) + case *ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError: + typename = "JobAlreadyExistsError" + + result := struct { + TypeName string `json:"__typename"` + *ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError + }{typename, v} + return json.Marshal(result) + case *ApproveJobProposalSpecApproveJobProposalSpecNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *ApproveJobProposalSpecApproveJobProposalSpecNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload: "%T"`, v) + } +} + +// ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess includes the requested fields of the GraphQL type ApproveJobProposalSpecSuccess. +type ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess struct { + Typename string `json:"__typename"` + Spec ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec `json:"spec"` +} + +// GetTypename returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess.Typename, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess) GetTypename() string { + return v.Typename +} + +// GetSpec returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess.Spec, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccess) GetSpec() ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec { + return v.Spec +} + +// ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecSuccessSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError includes the requested fields of the GraphQL type JobAlreadyExistsError. +type ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError.Typename, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError) GetTypename() string { + return v.Typename +} + +// GetMessage returns ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError.Message, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError) GetMessage() string { + return v.Message +} + +// GetCode returns ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError.Code, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecJobAlreadyExistsError) GetCode() ErrorCode { + return v.Code +} + +// ApproveJobProposalSpecApproveJobProposalSpecNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type ApproveJobProposalSpecApproveJobProposalSpecNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns ApproveJobProposalSpecApproveJobProposalSpecNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns ApproveJobProposalSpecApproveJobProposalSpecNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns ApproveJobProposalSpecApproveJobProposalSpecNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecApproveJobProposalSpecNotFoundError) GetCode() ErrorCode { + return v.Code +} + +// ApproveJobProposalSpecResponse is returned by ApproveJobProposalSpec on success. +type ApproveJobProposalSpecResponse struct { + ApproveJobProposalSpec ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload `json:"-"` +} + +// GetApproveJobProposalSpec returns ApproveJobProposalSpecResponse.ApproveJobProposalSpec, and is useful for accessing the field via an interface. +func (v *ApproveJobProposalSpecResponse) GetApproveJobProposalSpec() ApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload { + return v.ApproveJobProposalSpec +} + +func (v *ApproveJobProposalSpecResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *ApproveJobProposalSpecResponse + ApproveJobProposalSpec json.RawMessage `json:"approveJobProposalSpec"` + graphql.NoUnmarshalJSON + } + firstPass.ApproveJobProposalSpecResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.ApproveJobProposalSpec + src := firstPass.ApproveJobProposalSpec + if len(src) != 0 && string(src) != "null" { + err = __unmarshalApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal ApproveJobProposalSpecResponse.ApproveJobProposalSpec: %w", err) + } + } + } + return nil +} + +type __premarshalApproveJobProposalSpecResponse struct { + ApproveJobProposalSpec json.RawMessage `json:"approveJobProposalSpec"` +} + +func (v *ApproveJobProposalSpecResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *ApproveJobProposalSpecResponse) __premarshalJSON() (*__premarshalApproveJobProposalSpecResponse, error) { + var retval __premarshalApproveJobProposalSpecResponse + + { + + dst := &retval.ApproveJobProposalSpec + src := v.ApproveJobProposalSpec + var err error + *dst, err = __marshalApproveJobProposalSpecApproveJobProposalSpecApproveJobProposalSpecPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal ApproveJobProposalSpecResponse.ApproveJobProposalSpec: %w", err) + } + } + return &retval, nil +} + +// BridgeParts includes the GraphQL fields of Bridge requested by the fragment BridgeParts. +type BridgeParts struct { + Id string `json:"id"` + Name string `json:"name"` + Url string `json:"url"` + Confirmations int `json:"confirmations"` + OutgoingToken string `json:"outgoingToken"` + MinimumContractPayment string `json:"minimumContractPayment"` + CreatedAt string `json:"createdAt"` +} + +// GetId returns BridgeParts.Id, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetId() string { return v.Id } + +// GetName returns BridgeParts.Name, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetName() string { return v.Name } + +// GetUrl returns BridgeParts.Url, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetUrl() string { return v.Url } + +// GetConfirmations returns BridgeParts.Confirmations, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetConfirmations() int { return v.Confirmations } + +// GetOutgoingToken returns BridgeParts.OutgoingToken, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetOutgoingToken() string { return v.OutgoingToken } + +// GetMinimumContractPayment returns BridgeParts.MinimumContractPayment, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetMinimumContractPayment() string { return v.MinimumContractPayment } + +// GetCreatedAt returns BridgeParts.CreatedAt, and is useful for accessing the field via an interface. +func (v *BridgeParts) GetCreatedAt() string { return v.CreatedAt } + +// CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload includes the requested fields of the GraphQL interface CancelJobProposalSpecPayload. +// +// CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload is implemented by the following types: +// CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess +// CancelJobProposalSpecCancelJobProposalSpecNotFoundError +type CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload interface { + implementsGraphQLInterfaceCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess) implementsGraphQLInterfaceCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload() { +} +func (v *CancelJobProposalSpecCancelJobProposalSpecNotFoundError) implementsGraphQLInterfaceCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload() { +} + +func __unmarshalCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload(b []byte, v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "CancelJobProposalSpecSuccess": + *v = new(CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(CancelJobProposalSpecCancelJobProposalSpecNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing CancelJobProposalSpecPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload: "%v"`, tn.TypeName) + } +} + +func __marshalCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload(v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess: + typename = "CancelJobProposalSpecSuccess" + + result := struct { + TypeName string `json:"__typename"` + *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess + }{typename, v} + return json.Marshal(result) + case *CancelJobProposalSpecCancelJobProposalSpecNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *CancelJobProposalSpecCancelJobProposalSpecNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload: "%T"`, v) + } +} + +// CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess includes the requested fields of the GraphQL type CancelJobProposalSpecSuccess. +type CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess struct { + Typename string `json:"__typename"` + Spec CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec `json:"spec"` +} + +// GetTypename returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess.Typename, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess) GetTypename() string { + return v.Typename +} + +// GetSpec returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess.Spec, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccess) GetSpec() CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec { + return v.Spec +} + +// CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecSuccessSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// CancelJobProposalSpecCancelJobProposalSpecNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type CancelJobProposalSpecCancelJobProposalSpecNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns CancelJobProposalSpecCancelJobProposalSpecNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns CancelJobProposalSpecCancelJobProposalSpecNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns CancelJobProposalSpecCancelJobProposalSpecNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecCancelJobProposalSpecNotFoundError) GetCode() ErrorCode { return v.Code } + +// CancelJobProposalSpecResponse is returned by CancelJobProposalSpec on success. +type CancelJobProposalSpecResponse struct { + CancelJobProposalSpec CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload `json:"-"` +} + +// GetCancelJobProposalSpec returns CancelJobProposalSpecResponse.CancelJobProposalSpec, and is useful for accessing the field via an interface. +func (v *CancelJobProposalSpecResponse) GetCancelJobProposalSpec() CancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload { + return v.CancelJobProposalSpec +} + +func (v *CancelJobProposalSpecResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *CancelJobProposalSpecResponse + CancelJobProposalSpec json.RawMessage `json:"cancelJobProposalSpec"` + graphql.NoUnmarshalJSON + } + firstPass.CancelJobProposalSpecResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.CancelJobProposalSpec + src := firstPass.CancelJobProposalSpec + if len(src) != 0 && string(src) != "null" { + err = __unmarshalCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal CancelJobProposalSpecResponse.CancelJobProposalSpec: %w", err) + } + } + } + return nil +} + +type __premarshalCancelJobProposalSpecResponse struct { + CancelJobProposalSpec json.RawMessage `json:"cancelJobProposalSpec"` +} + +func (v *CancelJobProposalSpecResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *CancelJobProposalSpecResponse) __premarshalJSON() (*__premarshalCancelJobProposalSpecResponse, error) { + var retval __premarshalCancelJobProposalSpecResponse + + { + + dst := &retval.CancelJobProposalSpec + src := v.CancelJobProposalSpec + var err error + *dst, err = __marshalCancelJobProposalSpecCancelJobProposalSpecCancelJobProposalSpecPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal CancelJobProposalSpecResponse.CancelJobProposalSpec: %w", err) + } + } + return &retval, nil +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload includes the requested fields of the GraphQL interface CreateFeedsManagerChainConfigPayload. +// +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload is implemented by the following types: +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload interface { + implementsGraphQLInterfaceCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess) implementsGraphQLInterfaceCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload() { +} +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors) implementsGraphQLInterfaceCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload() { +} +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError) implementsGraphQLInterfaceCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload() { +} + +func __unmarshalCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload(b []byte, v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "CreateFeedsManagerChainConfigSuccess": + *v = new(CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess) + return json.Unmarshal(b, *v) + case "InputErrors": + *v = new(CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing CreateFeedsManagerChainConfigPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload: "%v"`, tn.TypeName) + } +} + +func __marshalCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload(v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess: + typename = "CreateFeedsManagerChainConfigSuccess" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess + }{typename, v} + return json.Marshal(result) + case *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors: + typename = "InputErrors" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors + }{typename, v} + return json.Marshal(result) + case *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload: "%T"`, v) + } +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess includes the requested fields of the GraphQL type CreateFeedsManagerChainConfigSuccess. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess struct { + Typename string `json:"__typename"` + ChainConfig CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig `json:"chainConfig"` +} + +// GetTypename returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess) GetTypename() string { + return v.Typename +} + +// GetChainConfig returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess.ChainConfig, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess) GetChainConfig() CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig { + return v.ChainConfig +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig includes the requested fields of the GraphQL type FeedsManagerChainConfig. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig struct { + Id string `json:"id"` + ChainID string `json:"chainID"` + ChainType string `json:"chainType"` + AccountAddr string `json:"accountAddr"` + AdminAddr string `json:"adminAddr"` + FluxMonitorJobConfig CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigFluxMonitorJobConfig `json:"fluxMonitorJobConfig"` + Ocr1JobConfig CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig `json:"ocr1JobConfig"` + Ocr2JobConfig CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig `json:"ocr2JobConfig"` +} + +// GetId returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.Id, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetId() string { + return v.Id +} + +// GetChainID returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.ChainID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetChainID() string { + return v.ChainID +} + +// GetChainType returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.ChainType, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetChainType() string { + return v.ChainType +} + +// GetAccountAddr returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.AccountAddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetAccountAddr() string { + return v.AccountAddr +} + +// GetAdminAddr returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.AdminAddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetAdminAddr() string { + return v.AdminAddr +} + +// GetFluxMonitorJobConfig returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.FluxMonitorJobConfig, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetFluxMonitorJobConfig() CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigFluxMonitorJobConfig { + return v.FluxMonitorJobConfig +} + +// GetOcr1JobConfig returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.Ocr1JobConfig, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetOcr1JobConfig() CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig { + return v.Ocr1JobConfig +} + +// GetOcr2JobConfig returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.Ocr2JobConfig, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetOcr2JobConfig() CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig { + return v.Ocr2JobConfig +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigFluxMonitorJobConfig includes the requested fields of the GraphQL type FluxMonitorJobConfig. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigFluxMonitorJobConfig struct { + Enabled bool `json:"enabled"` +} + +// GetEnabled returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigFluxMonitorJobConfig.Enabled, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigFluxMonitorJobConfig) GetEnabled() bool { + return v.Enabled +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig includes the requested fields of the GraphQL type OCR1JobConfig. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig struct { + Enabled bool `json:"enabled"` + IsBootstrap bool `json:"isBootstrap"` + Multiaddr string `json:"multiaddr"` + P2pPeerID string `json:"p2pPeerID"` + KeyBundleID string `json:"keyBundleID"` +} + +// GetEnabled returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig.Enabled, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig) GetEnabled() bool { + return v.Enabled +} + +// GetIsBootstrap returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig.IsBootstrap, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig) GetIsBootstrap() bool { + return v.IsBootstrap +} + +// GetMultiaddr returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig.Multiaddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig) GetMultiaddr() string { + return v.Multiaddr +} + +// GetP2pPeerID returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig.P2pPeerID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig) GetP2pPeerID() string { + return v.P2pPeerID +} + +// GetKeyBundleID returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig.KeyBundleID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr1JobConfigOCR1JobConfig) GetKeyBundleID() string { + return v.KeyBundleID +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig includes the requested fields of the GraphQL type OCR2JobConfig. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig struct { + Enabled bool `json:"enabled"` + IsBootstrap bool `json:"isBootstrap"` + Multiaddr string `json:"multiaddr"` + ForwarderAddress string `json:"forwarderAddress"` + P2pPeerID string `json:"p2pPeerID"` + KeyBundleID string `json:"keyBundleID"` + Plugins CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins `json:"plugins"` +} + +// GetEnabled returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.Enabled, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetEnabled() bool { + return v.Enabled +} + +// GetIsBootstrap returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.IsBootstrap, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetIsBootstrap() bool { + return v.IsBootstrap +} + +// GetMultiaddr returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.Multiaddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetMultiaddr() string { + return v.Multiaddr +} + +// GetForwarderAddress returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.ForwarderAddress, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetForwarderAddress() string { + return v.ForwarderAddress +} + +// GetP2pPeerID returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.P2pPeerID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetP2pPeerID() string { + return v.P2pPeerID +} + +// GetKeyBundleID returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.KeyBundleID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetKeyBundleID() string { + return v.KeyBundleID +} + +// GetPlugins returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig.Plugins, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfig) GetPlugins() CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins { + return v.Plugins +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins includes the requested fields of the GraphQL type Plugins. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins struct { + Commit bool `json:"commit"` + Execute bool `json:"execute"` + Median bool `json:"median"` + Mercury bool `json:"mercury"` + Rebalancer bool `json:"rebalancer"` +} + +// GetCommit returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins.Commit, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins) GetCommit() bool { + return v.Commit +} + +// GetExecute returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins.Execute, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins) GetExecute() bool { + return v.Execute +} + +// GetMedian returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins.Median, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins) GetMedian() bool { + return v.Median +} + +// GetMercury returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins.Mercury, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins) GetMercury() bool { + return v.Mercury +} + +// GetRebalancer returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins.Rebalancer, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfigOcr2JobConfigOCR2JobConfigPlugins) GetRebalancer() bool { + return v.Rebalancer +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors includes the requested fields of the GraphQL type InputErrors. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors struct { + Typename string `json:"__typename"` + Errors []CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError `json:"errors"` +} + +// GetTypename returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors) GetTypename() string { + return v.Typename +} + +// GetErrors returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors.Errors, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrors) GetErrors() []CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError { + return v.Errors +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError includes the requested fields of the GraphQL type InputError. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError struct { + Message string `json:"message"` + Path string `json:"path"` +} + +// GetMessage returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError.Message, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError) GetMessage() string { + return v.Message +} + +// GetPath returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError.Path, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigInputErrorsErrorsInputError) GetPath() string { + return v.Path +} + +// CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigNotFoundError) GetCode() ErrorCode { + return v.Code +} + +type CreateFeedsManagerChainConfigInput struct { + FeedsManagerID string `json:"feedsManagerID"` + ChainID string `json:"chainID"` + ChainType string `json:"chainType"` + AccountAddr string `json:"accountAddr"` + AccountAddrPubKey string `json:"accountAddrPubKey"` + AdminAddr string `json:"adminAddr"` + FluxMonitorEnabled bool `json:"fluxMonitorEnabled"` + Ocr1Enabled bool `json:"ocr1Enabled"` + Ocr1IsBootstrap bool `json:"ocr1IsBootstrap"` + Ocr1Multiaddr string `json:"ocr1Multiaddr"` + Ocr1P2PPeerID string `json:"ocr1P2PPeerID"` + Ocr1KeyBundleID string `json:"ocr1KeyBundleID"` + Ocr2Enabled bool `json:"ocr2Enabled"` + Ocr2IsBootstrap bool `json:"ocr2IsBootstrap"` + Ocr2Multiaddr string `json:"ocr2Multiaddr"` + Ocr2ForwarderAddress string `json:"ocr2ForwarderAddress"` + Ocr2P2PPeerID string `json:"ocr2P2PPeerID"` + Ocr2KeyBundleID string `json:"ocr2KeyBundleID"` + Ocr2Plugins string `json:"ocr2Plugins"` +} + +// GetFeedsManagerID returns CreateFeedsManagerChainConfigInput.FeedsManagerID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetFeedsManagerID() string { return v.FeedsManagerID } + +// GetChainID returns CreateFeedsManagerChainConfigInput.ChainID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetChainID() string { return v.ChainID } + +// GetChainType returns CreateFeedsManagerChainConfigInput.ChainType, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetChainType() string { return v.ChainType } + +// GetAccountAddr returns CreateFeedsManagerChainConfigInput.AccountAddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetAccountAddr() string { return v.AccountAddr } + +// GetAccountAddrPubKey returns CreateFeedsManagerChainConfigInput.AccountAddrPubKey, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetAccountAddrPubKey() string { + return v.AccountAddrPubKey +} + +// GetAdminAddr returns CreateFeedsManagerChainConfigInput.AdminAddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetAdminAddr() string { return v.AdminAddr } + +// GetFluxMonitorEnabled returns CreateFeedsManagerChainConfigInput.FluxMonitorEnabled, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetFluxMonitorEnabled() bool { + return v.FluxMonitorEnabled +} + +// GetOcr1Enabled returns CreateFeedsManagerChainConfigInput.Ocr1Enabled, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr1Enabled() bool { return v.Ocr1Enabled } + +// GetOcr1IsBootstrap returns CreateFeedsManagerChainConfigInput.Ocr1IsBootstrap, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr1IsBootstrap() bool { return v.Ocr1IsBootstrap } + +// GetOcr1Multiaddr returns CreateFeedsManagerChainConfigInput.Ocr1Multiaddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr1Multiaddr() string { return v.Ocr1Multiaddr } + +// GetOcr1P2PPeerID returns CreateFeedsManagerChainConfigInput.Ocr1P2PPeerID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr1P2PPeerID() string { return v.Ocr1P2PPeerID } + +// GetOcr1KeyBundleID returns CreateFeedsManagerChainConfigInput.Ocr1KeyBundleID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr1KeyBundleID() string { return v.Ocr1KeyBundleID } + +// GetOcr2Enabled returns CreateFeedsManagerChainConfigInput.Ocr2Enabled, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2Enabled() bool { return v.Ocr2Enabled } + +// GetOcr2IsBootstrap returns CreateFeedsManagerChainConfigInput.Ocr2IsBootstrap, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2IsBootstrap() bool { return v.Ocr2IsBootstrap } + +// GetOcr2Multiaddr returns CreateFeedsManagerChainConfigInput.Ocr2Multiaddr, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2Multiaddr() string { return v.Ocr2Multiaddr } + +// GetOcr2ForwarderAddress returns CreateFeedsManagerChainConfigInput.Ocr2ForwarderAddress, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2ForwarderAddress() string { + return v.Ocr2ForwarderAddress +} + +// GetOcr2P2PPeerID returns CreateFeedsManagerChainConfigInput.Ocr2P2PPeerID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2P2PPeerID() string { return v.Ocr2P2PPeerID } + +// GetOcr2KeyBundleID returns CreateFeedsManagerChainConfigInput.Ocr2KeyBundleID, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2KeyBundleID() string { return v.Ocr2KeyBundleID } + +// GetOcr2Plugins returns CreateFeedsManagerChainConfigInput.Ocr2Plugins, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigInput) GetOcr2Plugins() string { return v.Ocr2Plugins } + +// CreateFeedsManagerChainConfigResponse is returned by CreateFeedsManagerChainConfig on success. +type CreateFeedsManagerChainConfigResponse struct { + CreateFeedsManagerChainConfig CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload `json:"-"` +} + +// GetCreateFeedsManagerChainConfig returns CreateFeedsManagerChainConfigResponse.CreateFeedsManagerChainConfig, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerChainConfigResponse) GetCreateFeedsManagerChainConfig() CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload { + return v.CreateFeedsManagerChainConfig +} + +func (v *CreateFeedsManagerChainConfigResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *CreateFeedsManagerChainConfigResponse + CreateFeedsManagerChainConfig json.RawMessage `json:"createFeedsManagerChainConfig"` + graphql.NoUnmarshalJSON + } + firstPass.CreateFeedsManagerChainConfigResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.CreateFeedsManagerChainConfig + src := firstPass.CreateFeedsManagerChainConfig + if len(src) != 0 && string(src) != "null" { + err = __unmarshalCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal CreateFeedsManagerChainConfigResponse.CreateFeedsManagerChainConfig: %w", err) + } + } + } + return nil +} + +type __premarshalCreateFeedsManagerChainConfigResponse struct { + CreateFeedsManagerChainConfig json.RawMessage `json:"createFeedsManagerChainConfig"` +} + +func (v *CreateFeedsManagerChainConfigResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *CreateFeedsManagerChainConfigResponse) __premarshalJSON() (*__premarshalCreateFeedsManagerChainConfigResponse, error) { + var retval __premarshalCreateFeedsManagerChainConfigResponse + + { + + dst := &retval.CreateFeedsManagerChainConfig + src := v.CreateFeedsManagerChainConfig + var err error + *dst, err = __marshalCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal CreateFeedsManagerChainConfigResponse.CreateFeedsManagerChainConfig: %w", err) + } + } + return &retval, nil +} + +// CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload includes the requested fields of the GraphQL interface CreateFeedsManagerPayload. +// +// CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload is implemented by the following types: +// CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess +// CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError +// CreateFeedsManagerCreateFeedsManagerInputErrors +// CreateFeedsManagerCreateFeedsManagerNotFoundError +// CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError +type CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload interface { + implementsGraphQLInterfaceCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess) implementsGraphQLInterfaceCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload() { +} +func (v *CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError) implementsGraphQLInterfaceCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload() { +} +func (v *CreateFeedsManagerCreateFeedsManagerInputErrors) implementsGraphQLInterfaceCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload() { +} +func (v *CreateFeedsManagerCreateFeedsManagerNotFoundError) implementsGraphQLInterfaceCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload() { +} +func (v *CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError) implementsGraphQLInterfaceCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload() { +} + +func __unmarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload(b []byte, v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "CreateFeedsManagerSuccess": + *v = new(CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess) + return json.Unmarshal(b, *v) + case "DuplicateFeedsManagerError": + *v = new(CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError) + return json.Unmarshal(b, *v) + case "InputErrors": + *v = new(CreateFeedsManagerCreateFeedsManagerInputErrors) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(CreateFeedsManagerCreateFeedsManagerNotFoundError) + return json.Unmarshal(b, *v) + case "SingleFeedsManagerError": + *v = new(CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing CreateFeedsManagerPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload: "%v"`, tn.TypeName) + } +} + +func __marshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload(v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess: + typename = "CreateFeedsManagerSuccess" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess + }{typename, v} + return json.Marshal(result) + case *CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError: + typename = "DuplicateFeedsManagerError" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError + }{typename, v} + return json.Marshal(result) + case *CreateFeedsManagerCreateFeedsManagerInputErrors: + typename = "InputErrors" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerCreateFeedsManagerInputErrors + }{typename, v} + return json.Marshal(result) + case *CreateFeedsManagerCreateFeedsManagerNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerCreateFeedsManagerNotFoundError + }{typename, v} + return json.Marshal(result) + case *CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError: + typename = "SingleFeedsManagerError" + + result := struct { + TypeName string `json:"__typename"` + *CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload: "%T"`, v) + } +} + +// CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess includes the requested fields of the GraphQL type CreateFeedsManagerSuccess. +type CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess struct { + Typename string `json:"__typename"` + FeedsManager CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager `json:"feedsManager"` +} + +// GetTypename returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess) GetTypename() string { + return v.Typename +} + +// GetFeedsManager returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess.FeedsManager, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccess) GetFeedsManager() CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager { + return v.FeedsManager +} + +// CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager includes the requested fields of the GraphQL type FeedsManager. +type CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager struct { + FeedsManagerParts `json:"-"` +} + +// GetId returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.Id, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetId() string { + return v.FeedsManagerParts.Id +} + +// GetName returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.Name, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetName() string { + return v.FeedsManagerParts.Name +} + +// GetUri returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.Uri, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetUri() string { + return v.FeedsManagerParts.Uri +} + +// GetPublicKey returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.PublicKey, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetPublicKey() string { + return v.FeedsManagerParts.PublicKey +} + +// GetIsConnectionActive returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.IsConnectionActive, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetIsConnectionActive() bool { + return v.FeedsManagerParts.IsConnectionActive +} + +// GetCreatedAt returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.CreatedAt, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetCreatedAt() string { + return v.FeedsManagerParts.CreatedAt +} + +// GetJobProposals returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager + graphql.NoUnmarshalJSON + } + firstPass.CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.FeedsManagerParts) + if err != nil { + return err + } + return nil +} + +type __premarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager struct { + Id string `json:"id"` + + Name string `json:"name"` + + Uri string `json:"uri"` + + PublicKey string `json:"publicKey"` + + IsConnectionActive bool `json:"isConnectionActive"` + + CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` +} + +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) __premarshalJSON() (*__premarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager, error) { + var retval __premarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager + + retval.Id = v.FeedsManagerParts.Id + retval.Name = v.FeedsManagerParts.Name + retval.Uri = v.FeedsManagerParts.Uri + retval.PublicKey = v.FeedsManagerParts.PublicKey + retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive + retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals + return &retval, nil +} + +// CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError includes the requested fields of the GraphQL type DuplicateFeedsManagerError. +type CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError struct { + Typename string `json:"__typename"` +} + +// GetTypename returns CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerDuplicateFeedsManagerError) GetTypename() string { + return v.Typename +} + +// CreateFeedsManagerCreateFeedsManagerInputErrors includes the requested fields of the GraphQL type InputErrors. +type CreateFeedsManagerCreateFeedsManagerInputErrors struct { + Typename string `json:"__typename"` + Errors []CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError `json:"errors"` +} + +// GetTypename returns CreateFeedsManagerCreateFeedsManagerInputErrors.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerInputErrors) GetTypename() string { return v.Typename } + +// GetErrors returns CreateFeedsManagerCreateFeedsManagerInputErrors.Errors, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerInputErrors) GetErrors() []CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError { + return v.Errors +} + +// CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError includes the requested fields of the GraphQL type InputError. +type CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError struct { + Message string `json:"message"` + Code ErrorCode `json:"code"` + Path string `json:"path"` +} + +// GetMessage returns CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError.Message, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError) GetMessage() string { + return v.Message +} + +// GetCode returns CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError.Code, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError) GetCode() ErrorCode { + return v.Code +} + +// GetPath returns CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError.Path, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerInputErrorsErrorsInputError) GetPath() string { + return v.Path +} + +// CreateFeedsManagerCreateFeedsManagerNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type CreateFeedsManagerCreateFeedsManagerNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns CreateFeedsManagerCreateFeedsManagerNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerNotFoundError) GetTypename() string { return v.Typename } + +// GetMessage returns CreateFeedsManagerCreateFeedsManagerNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerNotFoundError) GetMessage() string { return v.Message } + +// GetCode returns CreateFeedsManagerCreateFeedsManagerNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerNotFoundError) GetCode() ErrorCode { return v.Code } + +// CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError includes the requested fields of the GraphQL type SingleFeedsManagerError. +type CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError.Typename, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError) GetTypename() string { + return v.Typename +} + +// GetMessage returns CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError.Message, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError) GetMessage() string { + return v.Message +} + +// GetCode returns CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError.Code, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError) GetCode() ErrorCode { + return v.Code +} + +type CreateFeedsManagerInput struct { + Name string `json:"name"` + Uri string `json:"uri"` + PublicKey string `json:"publicKey"` +} + +// GetName returns CreateFeedsManagerInput.Name, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerInput) GetName() string { return v.Name } + +// GetUri returns CreateFeedsManagerInput.Uri, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerInput) GetUri() string { return v.Uri } + +// GetPublicKey returns CreateFeedsManagerInput.PublicKey, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerInput) GetPublicKey() string { return v.PublicKey } + +// CreateFeedsManagerResponse is returned by CreateFeedsManager on success. +type CreateFeedsManagerResponse struct { + CreateFeedsManager CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload `json:"-"` +} + +// GetCreateFeedsManager returns CreateFeedsManagerResponse.CreateFeedsManager, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerResponse) GetCreateFeedsManager() CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload { + return v.CreateFeedsManager +} + +func (v *CreateFeedsManagerResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *CreateFeedsManagerResponse + CreateFeedsManager json.RawMessage `json:"createFeedsManager"` + graphql.NoUnmarshalJSON + } + firstPass.CreateFeedsManagerResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.CreateFeedsManager + src := firstPass.CreateFeedsManager + if len(src) != 0 && string(src) != "null" { + err = __unmarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal CreateFeedsManagerResponse.CreateFeedsManager: %w", err) + } + } + } + return nil +} + +type __premarshalCreateFeedsManagerResponse struct { + CreateFeedsManager json.RawMessage `json:"createFeedsManager"` +} + +func (v *CreateFeedsManagerResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *CreateFeedsManagerResponse) __premarshalJSON() (*__premarshalCreateFeedsManagerResponse, error) { + var retval __premarshalCreateFeedsManagerResponse + + { + + dst := &retval.CreateFeedsManager + src := v.CreateFeedsManager + var err error + *dst, err = __marshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal CreateFeedsManagerResponse.CreateFeedsManager: %w", err) + } + } + return &retval, nil +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload includes the requested fields of the GraphQL interface DeleteFeedsManagerChainConfigPayload. +// +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload is implemented by the following types: +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload interface { + implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() { +} +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() { +} + +func __unmarshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload(b []byte, v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "DeleteFeedsManagerChainConfigSuccess": + *v = new(DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing DeleteFeedsManagerChainConfigPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload: "%v"`, tn.TypeName) + } +} + +func __marshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload(v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess: + typename = "DeleteFeedsManagerChainConfigSuccess" + + result := struct { + TypeName string `json:"__typename"` + *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess + }{typename, v} + return json.Marshal(result) + case *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload: "%T"`, v) + } +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess includes the requested fields of the GraphQL type DeleteFeedsManagerChainConfigSuccess. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess struct { + Typename string `json:"__typename"` + ChainConfig DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig `json:"chainConfig"` +} + +// GetTypename returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess.Typename, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) GetTypename() string { + return v.Typename +} + +// GetChainConfig returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess.ChainConfig, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) GetChainConfig() DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig { + return v.ChainConfig +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig includes the requested fields of the GraphQL type FeedsManagerChainConfig. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig struct { + Id string `json:"id"` +} + +// GetId returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.Id, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetId() string { + return v.Id +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetCode() ErrorCode { + return v.Code +} + +// DeleteFeedsManagerChainConfigResponse is returned by DeleteFeedsManagerChainConfig on success. +type DeleteFeedsManagerChainConfigResponse struct { + DeleteFeedsManagerChainConfig DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload `json:"-"` +} + +// GetDeleteFeedsManagerChainConfig returns DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigResponse) GetDeleteFeedsManagerChainConfig() DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload { + return v.DeleteFeedsManagerChainConfig +} + +func (v *DeleteFeedsManagerChainConfigResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *DeleteFeedsManagerChainConfigResponse + DeleteFeedsManagerChainConfig json.RawMessage `json:"deleteFeedsManagerChainConfig"` + graphql.NoUnmarshalJSON + } + firstPass.DeleteFeedsManagerChainConfigResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.DeleteFeedsManagerChainConfig + src := firstPass.DeleteFeedsManagerChainConfig + if len(src) != 0 && string(src) != "null" { + err = __unmarshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig: %w", err) + } + } + } + return nil +} + +type __premarshalDeleteFeedsManagerChainConfigResponse struct { + DeleteFeedsManagerChainConfig json.RawMessage `json:"deleteFeedsManagerChainConfig"` +} + +func (v *DeleteFeedsManagerChainConfigResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *DeleteFeedsManagerChainConfigResponse) __premarshalJSON() (*__premarshalDeleteFeedsManagerChainConfigResponse, error) { + var retval __premarshalDeleteFeedsManagerChainConfigResponse + + { + + dst := &retval.DeleteFeedsManagerChainConfig + src := v.DeleteFeedsManagerChainConfig + var err error + *dst, err = __marshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig: %w", err) + } + } + return &retval, nil +} + +type ErrorCode string + +const ( + ErrorCodeNotFound ErrorCode = "NOT_FOUND" + ErrorCodeInvalidInput ErrorCode = "INVALID_INPUT" + ErrorCodeUnprocessable ErrorCode = "UNPROCESSABLE" +) + +// FeedsManagerParts includes the GraphQL fields of FeedsManager requested by the fragment FeedsManagerParts. +type FeedsManagerParts struct { + Id string `json:"id"` + Name string `json:"name"` + Uri string `json:"uri"` + PublicKey string `json:"publicKey"` + IsConnectionActive bool `json:"isConnectionActive"` + CreatedAt string `json:"createdAt"` + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` +} + +// GetId returns FeedsManagerParts.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetId() string { return v.Id } + +// GetName returns FeedsManagerParts.Name, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetName() string { return v.Name } + +// GetUri returns FeedsManagerParts.Uri, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetUri() string { return v.Uri } + +// GetPublicKey returns FeedsManagerParts.PublicKey, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetPublicKey() string { return v.PublicKey } + +// GetIsConnectionActive returns FeedsManagerParts.IsConnectionActive, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetIsConnectionActive() bool { return v.IsConnectionActive } + +// GetCreatedAt returns FeedsManagerParts.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetCreatedAt() string { return v.CreatedAt } + +// GetJobProposals returns FeedsManagerParts.JobProposals, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.JobProposals +} + +// FeedsManagerPartsJobProposalsJobProposal includes the requested fields of the GraphQL type JobProposal. +type FeedsManagerPartsJobProposalsJobProposal struct { + Id string `json:"id"` + Status JobProposalStatus `json:"status"` + RemoteUUID string `json:"remoteUUID"` + ExternalJobID string `json:"externalJobID"` + JobID string `json:"jobID"` + Specs []FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec `json:"specs"` + LatestSpec FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec `json:"latestSpec"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposal.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetId() string { return v.Id } + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposal.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetStatus() JobProposalStatus { return v.Status } + +// GetRemoteUUID returns FeedsManagerPartsJobProposalsJobProposal.RemoteUUID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetRemoteUUID() string { return v.RemoteUUID } + +// GetExternalJobID returns FeedsManagerPartsJobProposalsJobProposal.ExternalJobID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetExternalJobID() string { return v.ExternalJobID } + +// GetJobID returns FeedsManagerPartsJobProposalsJobProposal.JobID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetJobID() string { return v.JobID } + +// GetSpecs returns FeedsManagerPartsJobProposalsJobProposal.Specs, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetSpecs() []FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec { + return v.Specs +} + +// GetLatestSpec returns FeedsManagerPartsJobProposalsJobProposal.LatestSpec, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetLatestSpec() FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec { + return v.LatestSpec +} + +// FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetId() string { return v.Id } + +// GetDefinition returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// FetchAccountsEthKeysEthKeysPayload includes the requested fields of the GraphQL type EthKeysPayload. +type FetchAccountsEthKeysEthKeysPayload struct { + Results []FetchAccountsEthKeysEthKeysPayloadResultsEthKey `json:"results"` +} + +// GetResults returns FetchAccountsEthKeysEthKeysPayload.Results, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayload) GetResults() []FetchAccountsEthKeysEthKeysPayloadResultsEthKey { + return v.Results +} + +// FetchAccountsEthKeysEthKeysPayloadResultsEthKey includes the requested fields of the GraphQL type EthKey. +type FetchAccountsEthKeysEthKeysPayloadResultsEthKey struct { + Address string `json:"address"` + IsDisabled bool `json:"isDisabled"` + Chain FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain `json:"chain"` + EthBalance string `json:"ethBalance"` + LinkBalance string `json:"linkBalance"` +} + +// GetAddress returns FetchAccountsEthKeysEthKeysPayloadResultsEthKey.Address, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKey) GetAddress() string { return v.Address } + +// GetIsDisabled returns FetchAccountsEthKeysEthKeysPayloadResultsEthKey.IsDisabled, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKey) GetIsDisabled() bool { return v.IsDisabled } + +// GetChain returns FetchAccountsEthKeysEthKeysPayloadResultsEthKey.Chain, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKey) GetChain() FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain { + return v.Chain +} + +// GetEthBalance returns FetchAccountsEthKeysEthKeysPayloadResultsEthKey.EthBalance, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKey) GetEthBalance() string { return v.EthBalance } + +// GetLinkBalance returns FetchAccountsEthKeysEthKeysPayloadResultsEthKey.LinkBalance, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKey) GetLinkBalance() string { + return v.LinkBalance +} + +// FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain includes the requested fields of the GraphQL type Chain. +type FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain struct { + Id string `json:"id"` + Enabled bool `json:"enabled"` +} + +// GetId returns FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain.Id, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain) GetId() string { return v.Id } + +// GetEnabled returns FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain.Enabled, and is useful for accessing the field via an interface. +func (v *FetchAccountsEthKeysEthKeysPayloadResultsEthKeyChain) GetEnabled() bool { return v.Enabled } + +// FetchAccountsResponse is returned by FetchAccounts on success. +type FetchAccountsResponse struct { + EthKeys FetchAccountsEthKeysEthKeysPayload `json:"ethKeys"` +} + +// GetEthKeys returns FetchAccountsResponse.EthKeys, and is useful for accessing the field via an interface. +func (v *FetchAccountsResponse) GetEthKeys() FetchAccountsEthKeysEthKeysPayload { return v.EthKeys } + +// FetchCSAKeysCsaKeysCSAKeysPayload includes the requested fields of the GraphQL type CSAKeysPayload. +type FetchCSAKeysCsaKeysCSAKeysPayload struct { + Results []FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey `json:"results"` +} + +// GetResults returns FetchCSAKeysCsaKeysCSAKeysPayload.Results, and is useful for accessing the field via an interface. +func (v *FetchCSAKeysCsaKeysCSAKeysPayload) GetResults() []FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey { + return v.Results +} + +// FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey includes the requested fields of the GraphQL type CSAKey. +type FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey struct { + Id string `json:"id"` + PublicKey string `json:"publicKey"` + Version int `json:"version"` +} + +// GetId returns FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey.Id, and is useful for accessing the field via an interface. +func (v *FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey) GetId() string { return v.Id } + +// GetPublicKey returns FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey.PublicKey, and is useful for accessing the field via an interface. +func (v *FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey) GetPublicKey() string { return v.PublicKey } + +// GetVersion returns FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey.Version, and is useful for accessing the field via an interface. +func (v *FetchCSAKeysCsaKeysCSAKeysPayloadResultsCSAKey) GetVersion() int { return v.Version } + +// FetchCSAKeysResponse is returned by FetchCSAKeys on success. +type FetchCSAKeysResponse struct { + CsaKeys FetchCSAKeysCsaKeysCSAKeysPayload `json:"csaKeys"` +} + +// GetCsaKeys returns FetchCSAKeysResponse.CsaKeys, and is useful for accessing the field via an interface. +func (v *FetchCSAKeysResponse) GetCsaKeys() FetchCSAKeysCsaKeysCSAKeysPayload { return v.CsaKeys } + +// FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayload includes the requested fields of the GraphQL type OCR2KeyBundlesPayload. +type FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayload struct { + Results []FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle `json:"results"` +} + +// GetResults returns FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayload.Results, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayload) GetResults() []FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle { + return v.Results +} + +// FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle includes the requested fields of the GraphQL type OCR2KeyBundle. +type FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle struct { + Id string `json:"id"` + ChainType OCR2ChainType `json:"chainType"` + ConfigPublicKey string `json:"configPublicKey"` + OnChainPublicKey string `json:"onChainPublicKey"` + OffChainPublicKey string `json:"offChainPublicKey"` +} + +// GetId returns FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle.Id, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle) GetId() string { + return v.Id +} + +// GetChainType returns FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle.ChainType, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle) GetChainType() OCR2ChainType { + return v.ChainType +} + +// GetConfigPublicKey returns FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle.ConfigPublicKey, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle) GetConfigPublicKey() string { + return v.ConfigPublicKey +} + +// GetOnChainPublicKey returns FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle.OnChainPublicKey, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle) GetOnChainPublicKey() string { + return v.OnChainPublicKey +} + +// GetOffChainPublicKey returns FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle.OffChainPublicKey, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayloadResultsOCR2KeyBundle) GetOffChainPublicKey() string { + return v.OffChainPublicKey +} + +// FetchOCR2KeyBundlesResponse is returned by FetchOCR2KeyBundles on success. +type FetchOCR2KeyBundlesResponse struct { + Ocr2KeyBundles FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayload `json:"ocr2KeyBundles"` +} + +// GetOcr2KeyBundles returns FetchOCR2KeyBundlesResponse.Ocr2KeyBundles, and is useful for accessing the field via an interface. +func (v *FetchOCR2KeyBundlesResponse) GetOcr2KeyBundles() FetchOCR2KeyBundlesOcr2KeyBundlesOCR2KeyBundlesPayload { + return v.Ocr2KeyBundles +} + +// FetchP2PKeysP2pKeysP2PKeysPayload includes the requested fields of the GraphQL type P2PKeysPayload. +type FetchP2PKeysP2pKeysP2PKeysPayload struct { + Results []FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey `json:"results"` +} + +// GetResults returns FetchP2PKeysP2pKeysP2PKeysPayload.Results, and is useful for accessing the field via an interface. +func (v *FetchP2PKeysP2pKeysP2PKeysPayload) GetResults() []FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey { + return v.Results +} + +// FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey includes the requested fields of the GraphQL type P2PKey. +type FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey struct { + Id string `json:"id"` + PeerID string `json:"peerID"` + PublicKey string `json:"publicKey"` +} + +// GetId returns FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey.Id, and is useful for accessing the field via an interface. +func (v *FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey) GetId() string { return v.Id } + +// GetPeerID returns FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey.PeerID, and is useful for accessing the field via an interface. +func (v *FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey) GetPeerID() string { return v.PeerID } + +// GetPublicKey returns FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey.PublicKey, and is useful for accessing the field via an interface. +func (v *FetchP2PKeysP2pKeysP2PKeysPayloadResultsP2PKey) GetPublicKey() string { return v.PublicKey } + +// FetchP2PKeysResponse is returned by FetchP2PKeys on success. +type FetchP2PKeysResponse struct { + P2pKeys FetchP2PKeysP2pKeysP2PKeysPayload `json:"p2pKeys"` +} + +// GetP2pKeys returns FetchP2PKeysResponse.P2pKeys, and is useful for accessing the field via an interface. +func (v *FetchP2PKeysResponse) GetP2pKeys() FetchP2PKeysP2pKeysP2PKeysPayload { return v.P2pKeys } + +// GetBridgeBridge includes the requested fields of the GraphQL type Bridge. +type GetBridgeBridge struct { + Typename string `json:"__typename"` + BridgeParts `json:"-"` +} + +// GetTypename returns GetBridgeBridge.Typename, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetTypename() string { return v.Typename } + +// GetId returns GetBridgeBridge.Id, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetId() string { return v.BridgeParts.Id } + +// GetName returns GetBridgeBridge.Name, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetName() string { return v.BridgeParts.Name } + +// GetUrl returns GetBridgeBridge.Url, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetUrl() string { return v.BridgeParts.Url } + +// GetConfirmations returns GetBridgeBridge.Confirmations, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetConfirmations() int { return v.BridgeParts.Confirmations } + +// GetOutgoingToken returns GetBridgeBridge.OutgoingToken, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetOutgoingToken() string { return v.BridgeParts.OutgoingToken } + +// GetMinimumContractPayment returns GetBridgeBridge.MinimumContractPayment, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetMinimumContractPayment() string { + return v.BridgeParts.MinimumContractPayment +} + +// GetCreatedAt returns GetBridgeBridge.CreatedAt, and is useful for accessing the field via an interface. +func (v *GetBridgeBridge) GetCreatedAt() string { return v.BridgeParts.CreatedAt } + +func (v *GetBridgeBridge) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetBridgeBridge + graphql.NoUnmarshalJSON + } + firstPass.GetBridgeBridge = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.BridgeParts) + if err != nil { + return err + } + return nil +} + +type __premarshalGetBridgeBridge struct { + Typename string `json:"__typename"` + + Id string `json:"id"` + + Name string `json:"name"` + + Url string `json:"url"` + + Confirmations int `json:"confirmations"` + + OutgoingToken string `json:"outgoingToken"` + + MinimumContractPayment string `json:"minimumContractPayment"` + + CreatedAt string `json:"createdAt"` +} + +func (v *GetBridgeBridge) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetBridgeBridge) __premarshalJSON() (*__premarshalGetBridgeBridge, error) { + var retval __premarshalGetBridgeBridge + + retval.Typename = v.Typename + retval.Id = v.BridgeParts.Id + retval.Name = v.BridgeParts.Name + retval.Url = v.BridgeParts.Url + retval.Confirmations = v.BridgeParts.Confirmations + retval.OutgoingToken = v.BridgeParts.OutgoingToken + retval.MinimumContractPayment = v.BridgeParts.MinimumContractPayment + retval.CreatedAt = v.BridgeParts.CreatedAt + return &retval, nil +} + +// GetBridgeBridgeBridgePayload includes the requested fields of the GraphQL interface BridgePayload. +// +// GetBridgeBridgeBridgePayload is implemented by the following types: +// GetBridgeBridge +// GetBridgeBridgeNotFoundError +type GetBridgeBridgeBridgePayload interface { + implementsGraphQLInterfaceGetBridgeBridgeBridgePayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *GetBridgeBridge) implementsGraphQLInterfaceGetBridgeBridgeBridgePayload() {} +func (v *GetBridgeBridgeNotFoundError) implementsGraphQLInterfaceGetBridgeBridgeBridgePayload() {} + +func __unmarshalGetBridgeBridgeBridgePayload(b []byte, v *GetBridgeBridgeBridgePayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "Bridge": + *v = new(GetBridgeBridge) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(GetBridgeBridgeNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing BridgePayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for GetBridgeBridgeBridgePayload: "%v"`, tn.TypeName) + } +} + +func __marshalGetBridgeBridgeBridgePayload(v *GetBridgeBridgeBridgePayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *GetBridgeBridge: + typename = "Bridge" + + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + result := struct { + TypeName string `json:"__typename"` + *__premarshalGetBridgeBridge + }{typename, premarshaled} + return json.Marshal(result) + case *GetBridgeBridgeNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *GetBridgeBridgeNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for GetBridgeBridgeBridgePayload: "%T"`, v) + } +} + +// GetBridgeBridgeNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type GetBridgeBridgeNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns GetBridgeBridgeNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *GetBridgeBridgeNotFoundError) GetTypename() string { return v.Typename } + +// GetMessage returns GetBridgeBridgeNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *GetBridgeBridgeNotFoundError) GetMessage() string { return v.Message } + +// GetCode returns GetBridgeBridgeNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *GetBridgeBridgeNotFoundError) GetCode() ErrorCode { return v.Code } + +// GetBridgeResponse is returned by GetBridge on success. +type GetBridgeResponse struct { + Bridge GetBridgeBridgeBridgePayload `json:"-"` +} + +// GetBridge returns GetBridgeResponse.Bridge, and is useful for accessing the field via an interface. +func (v *GetBridgeResponse) GetBridge() GetBridgeBridgeBridgePayload { return v.Bridge } + +func (v *GetBridgeResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetBridgeResponse + Bridge json.RawMessage `json:"bridge"` + graphql.NoUnmarshalJSON + } + firstPass.GetBridgeResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.Bridge + src := firstPass.Bridge + if len(src) != 0 && string(src) != "null" { + err = __unmarshalGetBridgeBridgeBridgePayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal GetBridgeResponse.Bridge: %w", err) + } + } + } + return nil +} + +type __premarshalGetBridgeResponse struct { + Bridge json.RawMessage `json:"bridge"` +} + +func (v *GetBridgeResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetBridgeResponse) __premarshalJSON() (*__premarshalGetBridgeResponse, error) { + var retval __premarshalGetBridgeResponse + + { + + dst := &retval.Bridge + src := v.Bridge + var err error + *dst, err = __marshalGetBridgeBridgeBridgePayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal GetBridgeResponse.Bridge: %w", err) + } + } + return &retval, nil +} + +// GetFeedsManagerFeedsManager includes the requested fields of the GraphQL type FeedsManager. +type GetFeedsManagerFeedsManager struct { + Typename string `json:"__typename"` + FeedsManagerParts `json:"-"` +} + +// GetTypename returns GetFeedsManagerFeedsManager.Typename, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetTypename() string { return v.Typename } + +// GetId returns GetFeedsManagerFeedsManager.Id, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetId() string { return v.FeedsManagerParts.Id } + +// GetName returns GetFeedsManagerFeedsManager.Name, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetName() string { return v.FeedsManagerParts.Name } + +// GetUri returns GetFeedsManagerFeedsManager.Uri, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetUri() string { return v.FeedsManagerParts.Uri } + +// GetPublicKey returns GetFeedsManagerFeedsManager.PublicKey, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetPublicKey() string { return v.FeedsManagerParts.PublicKey } + +// GetIsConnectionActive returns GetFeedsManagerFeedsManager.IsConnectionActive, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetIsConnectionActive() bool { + return v.FeedsManagerParts.IsConnectionActive +} + +// GetCreatedAt returns GetFeedsManagerFeedsManager.CreatedAt, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetCreatedAt() string { return v.FeedsManagerParts.CreatedAt } + +// GetJobProposals returns GetFeedsManagerFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + +func (v *GetFeedsManagerFeedsManager) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetFeedsManagerFeedsManager + graphql.NoUnmarshalJSON + } + firstPass.GetFeedsManagerFeedsManager = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.FeedsManagerParts) + if err != nil { + return err + } + return nil +} + +type __premarshalGetFeedsManagerFeedsManager struct { + Typename string `json:"__typename"` + + Id string `json:"id"` + + Name string `json:"name"` + + Uri string `json:"uri"` + + PublicKey string `json:"publicKey"` + + IsConnectionActive bool `json:"isConnectionActive"` + + CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` +} + +func (v *GetFeedsManagerFeedsManager) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetFeedsManagerFeedsManager) __premarshalJSON() (*__premarshalGetFeedsManagerFeedsManager, error) { + var retval __premarshalGetFeedsManagerFeedsManager + + retval.Typename = v.Typename + retval.Id = v.FeedsManagerParts.Id + retval.Name = v.FeedsManagerParts.Name + retval.Uri = v.FeedsManagerParts.Uri + retval.PublicKey = v.FeedsManagerParts.PublicKey + retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive + retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals + return &retval, nil +} + +// GetFeedsManagerFeedsManagerFeedsManagerPayload includes the requested fields of the GraphQL interface FeedsManagerPayload. +// +// GetFeedsManagerFeedsManagerFeedsManagerPayload is implemented by the following types: +// GetFeedsManagerFeedsManager +// GetFeedsManagerFeedsManagerNotFoundError +type GetFeedsManagerFeedsManagerFeedsManagerPayload interface { + implementsGraphQLInterfaceGetFeedsManagerFeedsManagerFeedsManagerPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *GetFeedsManagerFeedsManager) implementsGraphQLInterfaceGetFeedsManagerFeedsManagerFeedsManagerPayload() { +} +func (v *GetFeedsManagerFeedsManagerNotFoundError) implementsGraphQLInterfaceGetFeedsManagerFeedsManagerFeedsManagerPayload() { +} + +func __unmarshalGetFeedsManagerFeedsManagerFeedsManagerPayload(b []byte, v *GetFeedsManagerFeedsManagerFeedsManagerPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "FeedsManager": + *v = new(GetFeedsManagerFeedsManager) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(GetFeedsManagerFeedsManagerNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing FeedsManagerPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for GetFeedsManagerFeedsManagerFeedsManagerPayload: "%v"`, tn.TypeName) + } +} + +func __marshalGetFeedsManagerFeedsManagerFeedsManagerPayload(v *GetFeedsManagerFeedsManagerFeedsManagerPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *GetFeedsManagerFeedsManager: + typename = "FeedsManager" + + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + result := struct { + TypeName string `json:"__typename"` + *__premarshalGetFeedsManagerFeedsManager + }{typename, premarshaled} + return json.Marshal(result) + case *GetFeedsManagerFeedsManagerNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *GetFeedsManagerFeedsManagerNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for GetFeedsManagerFeedsManagerFeedsManagerPayload: "%T"`, v) + } +} + +// GetFeedsManagerFeedsManagerNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type GetFeedsManagerFeedsManagerNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns GetFeedsManagerFeedsManagerNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManagerNotFoundError) GetTypename() string { return v.Typename } + +// GetMessage returns GetFeedsManagerFeedsManagerNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManagerNotFoundError) GetMessage() string { return v.Message } + +// GetCode returns GetFeedsManagerFeedsManagerNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManagerNotFoundError) GetCode() ErrorCode { return v.Code } + +// GetFeedsManagerResponse is returned by GetFeedsManager on success. +type GetFeedsManagerResponse struct { + FeedsManager GetFeedsManagerFeedsManagerFeedsManagerPayload `json:"-"` +} + +// GetFeedsManager returns GetFeedsManagerResponse.FeedsManager, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerResponse) GetFeedsManager() GetFeedsManagerFeedsManagerFeedsManagerPayload { + return v.FeedsManager +} + +func (v *GetFeedsManagerResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetFeedsManagerResponse + FeedsManager json.RawMessage `json:"feedsManager"` + graphql.NoUnmarshalJSON + } + firstPass.GetFeedsManagerResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.FeedsManager + src := firstPass.FeedsManager + if len(src) != 0 && string(src) != "null" { + err = __unmarshalGetFeedsManagerFeedsManagerFeedsManagerPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal GetFeedsManagerResponse.FeedsManager: %w", err) + } + } + } + return nil +} + +type __premarshalGetFeedsManagerResponse struct { + FeedsManager json.RawMessage `json:"feedsManager"` +} + +func (v *GetFeedsManagerResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetFeedsManagerResponse) __premarshalJSON() (*__premarshalGetFeedsManagerResponse, error) { + var retval __premarshalGetFeedsManagerResponse + + { + + dst := &retval.FeedsManager + src := v.FeedsManager + var err error + *dst, err = __marshalGetFeedsManagerFeedsManagerFeedsManagerPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal GetFeedsManagerResponse.FeedsManager: %w", err) + } + } + return &retval, nil +} + +// GetJobJob includes the requested fields of the GraphQL type Job. +type GetJobJob struct { + Typename string `json:"__typename"` + JobParts `json:"-"` +} + +// GetTypename returns GetJobJob.Typename, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetTypename() string { return v.Typename } + +// GetId returns GetJobJob.Id, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetId() string { return v.JobParts.Id } + +// GetName returns GetJobJob.Name, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetName() string { return v.JobParts.Name } + +// GetSchemaVersion returns GetJobJob.SchemaVersion, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetSchemaVersion() int { return v.JobParts.SchemaVersion } + +// GetGasLimit returns GetJobJob.GasLimit, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetGasLimit() int { return v.JobParts.GasLimit } + +// GetForwardingAllowed returns GetJobJob.ForwardingAllowed, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetForwardingAllowed() bool { return v.JobParts.ForwardingAllowed } + +// GetMaxTaskDuration returns GetJobJob.MaxTaskDuration, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetMaxTaskDuration() string { return v.JobParts.MaxTaskDuration } + +// GetExternalJobID returns GetJobJob.ExternalJobID, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetExternalJobID() string { return v.JobParts.ExternalJobID } + +// GetType returns GetJobJob.Type, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetType() string { return v.JobParts.Type } + +// GetSpec returns GetJobJob.Spec, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetSpec() JobPartsSpecJobSpec { return v.JobParts.Spec } + +// GetObservationSource returns GetJobJob.ObservationSource, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetObservationSource() string { return v.JobParts.ObservationSource } + +// GetErrors returns GetJobJob.Errors, and is useful for accessing the field via an interface. +func (v *GetJobJob) GetErrors() []JobPartsErrorsJobError { return v.JobParts.Errors } + +func (v *GetJobJob) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetJobJob + graphql.NoUnmarshalJSON + } + firstPass.GetJobJob = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.JobParts) + if err != nil { + return err + } + return nil +} + +type __premarshalGetJobJob struct { + Typename string `json:"__typename"` + + Id string `json:"id"` + + Name string `json:"name"` + + SchemaVersion int `json:"schemaVersion"` + + GasLimit int `json:"gasLimit"` + + ForwardingAllowed bool `json:"forwardingAllowed"` + + MaxTaskDuration string `json:"maxTaskDuration"` + + ExternalJobID string `json:"externalJobID"` + + Type string `json:"type"` + + Spec json.RawMessage `json:"spec"` + + ObservationSource string `json:"observationSource"` + + Errors []JobPartsErrorsJobError `json:"errors"` +} + +func (v *GetJobJob) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetJobJob) __premarshalJSON() (*__premarshalGetJobJob, error) { + var retval __premarshalGetJobJob + + retval.Typename = v.Typename + retval.Id = v.JobParts.Id + retval.Name = v.JobParts.Name + retval.SchemaVersion = v.JobParts.SchemaVersion + retval.GasLimit = v.JobParts.GasLimit + retval.ForwardingAllowed = v.JobParts.ForwardingAllowed + retval.MaxTaskDuration = v.JobParts.MaxTaskDuration + retval.ExternalJobID = v.JobParts.ExternalJobID + retval.Type = v.JobParts.Type + { + + dst := &retval.Spec + src := v.JobParts.Spec + var err error + *dst, err = __marshalJobPartsSpecJobSpec( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal GetJobJob.JobParts.Spec: %w", err) + } + } + retval.ObservationSource = v.JobParts.ObservationSource + retval.Errors = v.JobParts.Errors + return &retval, nil +} + +// GetJobJobJobPayload includes the requested fields of the GraphQL interface JobPayload. +// +// GetJobJobJobPayload is implemented by the following types: +// GetJobJob +// GetJobJobNotFoundError +type GetJobJobJobPayload interface { + implementsGraphQLInterfaceGetJobJobJobPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *GetJobJob) implementsGraphQLInterfaceGetJobJobJobPayload() {} +func (v *GetJobJobNotFoundError) implementsGraphQLInterfaceGetJobJobJobPayload() {} + +func __unmarshalGetJobJobJobPayload(b []byte, v *GetJobJobJobPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "Job": + *v = new(GetJobJob) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(GetJobJobNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing JobPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for GetJobJobJobPayload: "%v"`, tn.TypeName) + } +} + +func __marshalGetJobJobJobPayload(v *GetJobJobJobPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *GetJobJob: + typename = "Job" + + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + result := struct { + TypeName string `json:"__typename"` + *__premarshalGetJobJob + }{typename, premarshaled} + return json.Marshal(result) + case *GetJobJobNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *GetJobJobNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for GetJobJobJobPayload: "%T"`, v) + } +} + +// GetJobJobNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type GetJobJobNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns GetJobJobNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *GetJobJobNotFoundError) GetTypename() string { return v.Typename } + +// GetMessage returns GetJobJobNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *GetJobJobNotFoundError) GetMessage() string { return v.Message } + +// GetCode returns GetJobJobNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *GetJobJobNotFoundError) GetCode() ErrorCode { return v.Code } + +// GetJobProposalJobProposal includes the requested fields of the GraphQL type JobProposal. +type GetJobProposalJobProposal struct { + Typename string `json:"__typename"` + Id string `json:"id"` + Name string `json:"name"` + Status JobProposalStatus `json:"status"` + RemoteUUID string `json:"remoteUUID"` + ExternalJobID string `json:"externalJobID"` + JobID string `json:"jobID"` + FeedsManager GetJobProposalJobProposalFeedsManager `json:"feedsManager"` + MultiAddrs []string `json:"multiAddrs"` + PendingUpdate bool `json:"pendingUpdate"` + Specs []GetJobProposalJobProposalSpecsJobProposalSpec `json:"specs"` + LatestSpec GetJobProposalJobProposalLatestSpecJobProposalSpec `json:"latestSpec"` +} + +// GetTypename returns GetJobProposalJobProposal.Typename, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetTypename() string { return v.Typename } + +// GetId returns GetJobProposalJobProposal.Id, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetId() string { return v.Id } + +// GetName returns GetJobProposalJobProposal.Name, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetName() string { return v.Name } + +// GetStatus returns GetJobProposalJobProposal.Status, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetStatus() JobProposalStatus { return v.Status } + +// GetRemoteUUID returns GetJobProposalJobProposal.RemoteUUID, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetRemoteUUID() string { return v.RemoteUUID } + +// GetExternalJobID returns GetJobProposalJobProposal.ExternalJobID, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetExternalJobID() string { return v.ExternalJobID } + +// GetJobID returns GetJobProposalJobProposal.JobID, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetJobID() string { return v.JobID } + +// GetFeedsManager returns GetJobProposalJobProposal.FeedsManager, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetFeedsManager() GetJobProposalJobProposalFeedsManager { + return v.FeedsManager +} + +// GetMultiAddrs returns GetJobProposalJobProposal.MultiAddrs, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetMultiAddrs() []string { return v.MultiAddrs } + +// GetPendingUpdate returns GetJobProposalJobProposal.PendingUpdate, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetPendingUpdate() bool { return v.PendingUpdate } + +// GetSpecs returns GetJobProposalJobProposal.Specs, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetSpecs() []GetJobProposalJobProposalSpecsJobProposalSpec { + return v.Specs +} + +// GetLatestSpec returns GetJobProposalJobProposal.LatestSpec, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposal) GetLatestSpec() GetJobProposalJobProposalLatestSpecJobProposalSpec { + return v.LatestSpec +} + +// GetJobProposalJobProposalFeedsManager includes the requested fields of the GraphQL type FeedsManager. +type GetJobProposalJobProposalFeedsManager struct { + FeedsManagerParts `json:"-"` +} + +// GetId returns GetJobProposalJobProposalFeedsManager.Id, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetId() string { return v.FeedsManagerParts.Id } + +// GetName returns GetJobProposalJobProposalFeedsManager.Name, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetName() string { return v.FeedsManagerParts.Name } + +// GetUri returns GetJobProposalJobProposalFeedsManager.Uri, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetUri() string { return v.FeedsManagerParts.Uri } + +// GetPublicKey returns GetJobProposalJobProposalFeedsManager.PublicKey, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetPublicKey() string { + return v.FeedsManagerParts.PublicKey +} + +// GetIsConnectionActive returns GetJobProposalJobProposalFeedsManager.IsConnectionActive, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetIsConnectionActive() bool { + return v.FeedsManagerParts.IsConnectionActive +} + +// GetCreatedAt returns GetJobProposalJobProposalFeedsManager.CreatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetCreatedAt() string { + return v.FeedsManagerParts.CreatedAt +} + +// GetJobProposals returns GetJobProposalJobProposalFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + +func (v *GetJobProposalJobProposalFeedsManager) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetJobProposalJobProposalFeedsManager + graphql.NoUnmarshalJSON + } + firstPass.GetJobProposalJobProposalFeedsManager = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.FeedsManagerParts) + if err != nil { + return err + } + return nil +} + +type __premarshalGetJobProposalJobProposalFeedsManager struct { + Id string `json:"id"` + + Name string `json:"name"` + + Uri string `json:"uri"` + + PublicKey string `json:"publicKey"` + + IsConnectionActive bool `json:"isConnectionActive"` + + CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` +} + +func (v *GetJobProposalJobProposalFeedsManager) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetJobProposalJobProposalFeedsManager) __premarshalJSON() (*__premarshalGetJobProposalJobProposalFeedsManager, error) { + var retval __premarshalGetJobProposalJobProposalFeedsManager + + retval.Id = v.FeedsManagerParts.Id + retval.Name = v.FeedsManagerParts.Name + retval.Uri = v.FeedsManagerParts.Uri + retval.PublicKey = v.FeedsManagerParts.PublicKey + retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive + retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals + return &retval, nil +} + +// GetJobProposalJobProposalJobProposalPayload includes the requested fields of the GraphQL interface JobProposalPayload. +// +// GetJobProposalJobProposalJobProposalPayload is implemented by the following types: +// GetJobProposalJobProposal +// GetJobProposalJobProposalNotFoundError +type GetJobProposalJobProposalJobProposalPayload interface { + implementsGraphQLInterfaceGetJobProposalJobProposalJobProposalPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *GetJobProposalJobProposal) implementsGraphQLInterfaceGetJobProposalJobProposalJobProposalPayload() { +} +func (v *GetJobProposalJobProposalNotFoundError) implementsGraphQLInterfaceGetJobProposalJobProposalJobProposalPayload() { +} + +func __unmarshalGetJobProposalJobProposalJobProposalPayload(b []byte, v *GetJobProposalJobProposalJobProposalPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "JobProposal": + *v = new(GetJobProposalJobProposal) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(GetJobProposalJobProposalNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing JobProposalPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for GetJobProposalJobProposalJobProposalPayload: "%v"`, tn.TypeName) + } +} + +func __marshalGetJobProposalJobProposalJobProposalPayload(v *GetJobProposalJobProposalJobProposalPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *GetJobProposalJobProposal: + typename = "JobProposal" + + result := struct { + TypeName string `json:"__typename"` + *GetJobProposalJobProposal + }{typename, v} + return json.Marshal(result) + case *GetJobProposalJobProposalNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *GetJobProposalJobProposalNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for GetJobProposalJobProposalJobProposalPayload: "%T"`, v) + } +} + +// GetJobProposalJobProposalLatestSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type GetJobProposalJobProposalLatestSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns GetJobProposalJobProposalLatestSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetId() string { return v.Id } + +// GetDefinition returns GetJobProposalJobProposalLatestSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns GetJobProposalJobProposalLatestSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetVersion() int { return v.Version } + +// GetStatus returns GetJobProposalJobProposalLatestSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetStatus() SpecStatus { return v.Status } + +// GetStatusUpdatedAt returns GetJobProposalJobProposalLatestSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns GetJobProposalJobProposalLatestSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns GetJobProposalJobProposalLatestSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalLatestSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// GetJobProposalJobProposalNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type GetJobProposalJobProposalNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns GetJobProposalJobProposalNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalNotFoundError) GetTypename() string { return v.Typename } + +// GetMessage returns GetJobProposalJobProposalNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalNotFoundError) GetMessage() string { return v.Message } + +// GetCode returns GetJobProposalJobProposalNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalNotFoundError) GetCode() ErrorCode { return v.Code } + +// GetJobProposalJobProposalSpecsJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type GetJobProposalJobProposalSpecsJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns GetJobProposalJobProposalSpecsJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetId() string { return v.Id } + +// GetDefinition returns GetJobProposalJobProposalSpecsJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetDefinition() string { return v.Definition } + +// GetVersion returns GetJobProposalJobProposalSpecsJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetVersion() int { return v.Version } + +// GetStatus returns GetJobProposalJobProposalSpecsJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetStatus() SpecStatus { return v.Status } + +// GetStatusUpdatedAt returns GetJobProposalJobProposalSpecsJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns GetJobProposalJobProposalSpecsJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetCreatedAt() string { return v.CreatedAt } + +// GetUpdatedAt returns GetJobProposalJobProposalSpecsJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalSpecsJobProposalSpec) GetUpdatedAt() string { return v.UpdatedAt } + +// GetJobProposalResponse is returned by GetJobProposal on success. +type GetJobProposalResponse struct { + JobProposal GetJobProposalJobProposalJobProposalPayload `json:"-"` +} + +// GetJobProposal returns GetJobProposalResponse.JobProposal, and is useful for accessing the field via an interface. +func (v *GetJobProposalResponse) GetJobProposal() GetJobProposalJobProposalJobProposalPayload { + return v.JobProposal +} + +func (v *GetJobProposalResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetJobProposalResponse + JobProposal json.RawMessage `json:"jobProposal"` + graphql.NoUnmarshalJSON + } + firstPass.GetJobProposalResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.JobProposal + src := firstPass.JobProposal + if len(src) != 0 && string(src) != "null" { + err = __unmarshalGetJobProposalJobProposalJobProposalPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal GetJobProposalResponse.JobProposal: %w", err) + } + } + } + return nil +} + +type __premarshalGetJobProposalResponse struct { + JobProposal json.RawMessage `json:"jobProposal"` +} + +func (v *GetJobProposalResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetJobProposalResponse) __premarshalJSON() (*__premarshalGetJobProposalResponse, error) { + var retval __premarshalGetJobProposalResponse + + { + + dst := &retval.JobProposal + src := v.JobProposal + var err error + *dst, err = __marshalGetJobProposalJobProposalJobProposalPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal GetJobProposalResponse.JobProposal: %w", err) + } + } + return &retval, nil +} + +// GetJobResponse is returned by GetJob on success. +type GetJobResponse struct { + Job GetJobJobJobPayload `json:"-"` +} + +// GetJob returns GetJobResponse.Job, and is useful for accessing the field via an interface. +func (v *GetJobResponse) GetJob() GetJobJobJobPayload { return v.Job } + +func (v *GetJobResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetJobResponse + Job json.RawMessage `json:"job"` + graphql.NoUnmarshalJSON + } + firstPass.GetJobResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.Job + src := firstPass.Job + if len(src) != 0 && string(src) != "null" { + err = __unmarshalGetJobJobJobPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal GetJobResponse.Job: %w", err) + } + } + } + return nil +} + +type __premarshalGetJobResponse struct { + Job json.RawMessage `json:"job"` +} + +func (v *GetJobResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetJobResponse) __premarshalJSON() (*__premarshalGetJobResponse, error) { + var retval __premarshalGetJobResponse + + { + + dst := &retval.Job + src := v.Job + var err error + *dst, err = __marshalGetJobJobJobPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal GetJobResponse.Job: %w", err) + } + } + return &retval, nil +} + +// JobParts includes the GraphQL fields of Job requested by the fragment JobParts. +type JobParts struct { + Id string `json:"id"` + Name string `json:"name"` + SchemaVersion int `json:"schemaVersion"` + GasLimit int `json:"gasLimit"` + ForwardingAllowed bool `json:"forwardingAllowed"` + MaxTaskDuration string `json:"maxTaskDuration"` + ExternalJobID string `json:"externalJobID"` + Type string `json:"type"` + Spec JobPartsSpecJobSpec `json:"-"` + ObservationSource string `json:"observationSource"` + Errors []JobPartsErrorsJobError `json:"errors"` +} + +// GetId returns JobParts.Id, and is useful for accessing the field via an interface. +func (v *JobParts) GetId() string { return v.Id } + +// GetName returns JobParts.Name, and is useful for accessing the field via an interface. +func (v *JobParts) GetName() string { return v.Name } + +// GetSchemaVersion returns JobParts.SchemaVersion, and is useful for accessing the field via an interface. +func (v *JobParts) GetSchemaVersion() int { return v.SchemaVersion } + +// GetGasLimit returns JobParts.GasLimit, and is useful for accessing the field via an interface. +func (v *JobParts) GetGasLimit() int { return v.GasLimit } + +// GetForwardingAllowed returns JobParts.ForwardingAllowed, and is useful for accessing the field via an interface. +func (v *JobParts) GetForwardingAllowed() bool { return v.ForwardingAllowed } + +// GetMaxTaskDuration returns JobParts.MaxTaskDuration, and is useful for accessing the field via an interface. +func (v *JobParts) GetMaxTaskDuration() string { return v.MaxTaskDuration } + +// GetExternalJobID returns JobParts.ExternalJobID, and is useful for accessing the field via an interface. +func (v *JobParts) GetExternalJobID() string { return v.ExternalJobID } + +// GetType returns JobParts.Type, and is useful for accessing the field via an interface. +func (v *JobParts) GetType() string { return v.Type } + +// GetSpec returns JobParts.Spec, and is useful for accessing the field via an interface. +func (v *JobParts) GetSpec() JobPartsSpecJobSpec { return v.Spec } + +// GetObservationSource returns JobParts.ObservationSource, and is useful for accessing the field via an interface. +func (v *JobParts) GetObservationSource() string { return v.ObservationSource } + +// GetErrors returns JobParts.Errors, and is useful for accessing the field via an interface. +func (v *JobParts) GetErrors() []JobPartsErrorsJobError { return v.Errors } + +func (v *JobParts) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *JobParts + Spec json.RawMessage `json:"spec"` + graphql.NoUnmarshalJSON + } + firstPass.JobParts = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.Spec + src := firstPass.Spec + if len(src) != 0 && string(src) != "null" { + err = __unmarshalJobPartsSpecJobSpec( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal JobParts.Spec: %w", err) + } + } + } + return nil +} + +type __premarshalJobParts struct { + Id string `json:"id"` + + Name string `json:"name"` + + SchemaVersion int `json:"schemaVersion"` + + GasLimit int `json:"gasLimit"` + + ForwardingAllowed bool `json:"forwardingAllowed"` + + MaxTaskDuration string `json:"maxTaskDuration"` + + ExternalJobID string `json:"externalJobID"` + + Type string `json:"type"` + + Spec json.RawMessage `json:"spec"` + + ObservationSource string `json:"observationSource"` + + Errors []JobPartsErrorsJobError `json:"errors"` +} + +func (v *JobParts) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *JobParts) __premarshalJSON() (*__premarshalJobParts, error) { + var retval __premarshalJobParts + + retval.Id = v.Id + retval.Name = v.Name + retval.SchemaVersion = v.SchemaVersion + retval.GasLimit = v.GasLimit + retval.ForwardingAllowed = v.ForwardingAllowed + retval.MaxTaskDuration = v.MaxTaskDuration + retval.ExternalJobID = v.ExternalJobID + retval.Type = v.Type + { + + dst := &retval.Spec + src := v.Spec + var err error + *dst, err = __marshalJobPartsSpecJobSpec( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal JobParts.Spec: %w", err) + } + } + retval.ObservationSource = v.ObservationSource + retval.Errors = v.Errors + return &retval, nil +} + +// JobPartsErrorsJobError includes the requested fields of the GraphQL type JobError. +type JobPartsErrorsJobError struct { + Id string `json:"id"` + Description string `json:"description"` + Occurrences int `json:"occurrences"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns JobPartsErrorsJobError.Id, and is useful for accessing the field via an interface. +func (v *JobPartsErrorsJobError) GetId() string { return v.Id } + +// GetDescription returns JobPartsErrorsJobError.Description, and is useful for accessing the field via an interface. +func (v *JobPartsErrorsJobError) GetDescription() string { return v.Description } + +// GetOccurrences returns JobPartsErrorsJobError.Occurrences, and is useful for accessing the field via an interface. +func (v *JobPartsErrorsJobError) GetOccurrences() int { return v.Occurrences } + +// GetCreatedAt returns JobPartsErrorsJobError.CreatedAt, and is useful for accessing the field via an interface. +func (v *JobPartsErrorsJobError) GetCreatedAt() string { return v.CreatedAt } + +// GetUpdatedAt returns JobPartsErrorsJobError.UpdatedAt, and is useful for accessing the field via an interface. +func (v *JobPartsErrorsJobError) GetUpdatedAt() string { return v.UpdatedAt } + +// JobPartsSpecBlockHeaderFeederSpec includes the requested fields of the GraphQL type BlockHeaderFeederSpec. +type JobPartsSpecBlockHeaderFeederSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecBlockHeaderFeederSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecBlockHeaderFeederSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecBlockhashStoreSpec includes the requested fields of the GraphQL type BlockhashStoreSpec. +type JobPartsSpecBlockhashStoreSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecBlockhashStoreSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecBlockhashStoreSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecBootstrapSpec includes the requested fields of the GraphQL type BootstrapSpec. +type JobPartsSpecBootstrapSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecBootstrapSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecBootstrapSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecCronSpec includes the requested fields of the GraphQL type CronSpec. +type JobPartsSpecCronSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecCronSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecCronSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecDirectRequestSpec includes the requested fields of the GraphQL type DirectRequestSpec. +type JobPartsSpecDirectRequestSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecDirectRequestSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecDirectRequestSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecFluxMonitorSpec includes the requested fields of the GraphQL type FluxMonitorSpec. +type JobPartsSpecFluxMonitorSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecFluxMonitorSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecFluxMonitorSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecGatewaySpec includes the requested fields of the GraphQL type GatewaySpec. +type JobPartsSpecGatewaySpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecGatewaySpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecGatewaySpec) GetTypename() string { return v.Typename } + +// JobPartsSpecJobSpec includes the requested fields of the GraphQL interface JobSpec. +// +// JobPartsSpecJobSpec is implemented by the following types: +// JobPartsSpecBlockHeaderFeederSpec +// JobPartsSpecBlockhashStoreSpec +// JobPartsSpecBootstrapSpec +// JobPartsSpecCronSpec +// JobPartsSpecDirectRequestSpec +// JobPartsSpecFluxMonitorSpec +// JobPartsSpecGatewaySpec +// JobPartsSpecKeeperSpec +// JobPartsSpecOCR2Spec +// JobPartsSpecOCRSpec +// JobPartsSpecStandardCapabilitiesSpec +// JobPartsSpecVRFSpec +// JobPartsSpecWebhookSpec +// JobPartsSpecWorkflowSpec +type JobPartsSpecJobSpec interface { + implementsGraphQLInterfaceJobPartsSpecJobSpec() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *JobPartsSpecBlockHeaderFeederSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecBlockhashStoreSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecBootstrapSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecCronSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecDirectRequestSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecFluxMonitorSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecGatewaySpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecKeeperSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecOCR2Spec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecOCRSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecStandardCapabilitiesSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecVRFSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecWebhookSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecWorkflowSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} + +func __unmarshalJobPartsSpecJobSpec(b []byte, v *JobPartsSpecJobSpec) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "BlockHeaderFeederSpec": + *v = new(JobPartsSpecBlockHeaderFeederSpec) + return json.Unmarshal(b, *v) + case "BlockhashStoreSpec": + *v = new(JobPartsSpecBlockhashStoreSpec) + return json.Unmarshal(b, *v) + case "BootstrapSpec": + *v = new(JobPartsSpecBootstrapSpec) + return json.Unmarshal(b, *v) + case "CronSpec": + *v = new(JobPartsSpecCronSpec) + return json.Unmarshal(b, *v) + case "DirectRequestSpec": + *v = new(JobPartsSpecDirectRequestSpec) + return json.Unmarshal(b, *v) + case "FluxMonitorSpec": + *v = new(JobPartsSpecFluxMonitorSpec) + return json.Unmarshal(b, *v) + case "GatewaySpec": + *v = new(JobPartsSpecGatewaySpec) + return json.Unmarshal(b, *v) + case "KeeperSpec": + *v = new(JobPartsSpecKeeperSpec) + return json.Unmarshal(b, *v) + case "OCR2Spec": + *v = new(JobPartsSpecOCR2Spec) + return json.Unmarshal(b, *v) + case "OCRSpec": + *v = new(JobPartsSpecOCRSpec) + return json.Unmarshal(b, *v) + case "StandardCapabilitiesSpec": + *v = new(JobPartsSpecStandardCapabilitiesSpec) + return json.Unmarshal(b, *v) + case "VRFSpec": + *v = new(JobPartsSpecVRFSpec) + return json.Unmarshal(b, *v) + case "WebhookSpec": + *v = new(JobPartsSpecWebhookSpec) + return json.Unmarshal(b, *v) + case "WorkflowSpec": + *v = new(JobPartsSpecWorkflowSpec) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing JobSpec.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for JobPartsSpecJobSpec: "%v"`, tn.TypeName) + } +} + +func __marshalJobPartsSpecJobSpec(v *JobPartsSpecJobSpec) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *JobPartsSpecBlockHeaderFeederSpec: + typename = "BlockHeaderFeederSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecBlockHeaderFeederSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecBlockhashStoreSpec: + typename = "BlockhashStoreSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecBlockhashStoreSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecBootstrapSpec: + typename = "BootstrapSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecBootstrapSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecCronSpec: + typename = "CronSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecCronSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecDirectRequestSpec: + typename = "DirectRequestSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecDirectRequestSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecFluxMonitorSpec: + typename = "FluxMonitorSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecFluxMonitorSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecGatewaySpec: + typename = "GatewaySpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecGatewaySpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecKeeperSpec: + typename = "KeeperSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecKeeperSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecOCR2Spec: + typename = "OCR2Spec" + + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + result := struct { + TypeName string `json:"__typename"` + *__premarshalJobPartsSpecOCR2Spec + }{typename, premarshaled} + return json.Marshal(result) + case *JobPartsSpecOCRSpec: + typename = "OCRSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecOCRSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecStandardCapabilitiesSpec: + typename = "StandardCapabilitiesSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecStandardCapabilitiesSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecVRFSpec: + typename = "VRFSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecVRFSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecWebhookSpec: + typename = "WebhookSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecWebhookSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecWorkflowSpec: + typename = "WorkflowSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecWorkflowSpec + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for JobPartsSpecJobSpec: "%T"`, v) + } +} + +// JobPartsSpecKeeperSpec includes the requested fields of the GraphQL type KeeperSpec. +type JobPartsSpecKeeperSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecKeeperSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecKeeperSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecOCR2Spec includes the requested fields of the GraphQL type OCR2Spec. +type JobPartsSpecOCR2Spec struct { + Typename string `json:"__typename"` + OCR2Spec `json:"-"` +} + +// GetTypename returns JobPartsSpecOCR2Spec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetTypename() string { return v.Typename } + +// GetBlockchainTimeout returns JobPartsSpecOCR2Spec.BlockchainTimeout, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetBlockchainTimeout() string { return v.OCR2Spec.BlockchainTimeout } + +// GetContractID returns JobPartsSpecOCR2Spec.ContractID, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetContractID() string { return v.OCR2Spec.ContractID } + +// GetContractConfigConfirmations returns JobPartsSpecOCR2Spec.ContractConfigConfirmations, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetContractConfigConfirmations() int { + return v.OCR2Spec.ContractConfigConfirmations +} + +// GetContractConfigTrackerPollInterval returns JobPartsSpecOCR2Spec.ContractConfigTrackerPollInterval, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetContractConfigTrackerPollInterval() string { + return v.OCR2Spec.ContractConfigTrackerPollInterval +} + +// GetCreatedAt returns JobPartsSpecOCR2Spec.CreatedAt, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetCreatedAt() string { return v.OCR2Spec.CreatedAt } + +// GetOcrKeyBundleID returns JobPartsSpecOCR2Spec.OcrKeyBundleID, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetOcrKeyBundleID() string { return v.OCR2Spec.OcrKeyBundleID } + +// GetMonitoringEndpoint returns JobPartsSpecOCR2Spec.MonitoringEndpoint, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetMonitoringEndpoint() string { return v.OCR2Spec.MonitoringEndpoint } + +// GetP2pv2Bootstrappers returns JobPartsSpecOCR2Spec.P2pv2Bootstrappers, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetP2pv2Bootstrappers() []string { return v.OCR2Spec.P2pv2Bootstrappers } + +// GetRelay returns JobPartsSpecOCR2Spec.Relay, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetRelay() string { return v.OCR2Spec.Relay } + +// GetRelayConfig returns JobPartsSpecOCR2Spec.RelayConfig, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetRelayConfig() gqlscalar.Map { return v.OCR2Spec.RelayConfig } + +// GetTransmitterID returns JobPartsSpecOCR2Spec.TransmitterID, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetTransmitterID() string { return v.OCR2Spec.TransmitterID } + +// GetPluginType returns JobPartsSpecOCR2Spec.PluginType, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetPluginType() string { return v.OCR2Spec.PluginType } + +// GetPluginConfig returns JobPartsSpecOCR2Spec.PluginConfig, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCR2Spec) GetPluginConfig() gqlscalar.Map { return v.OCR2Spec.PluginConfig } + +func (v *JobPartsSpecOCR2Spec) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *JobPartsSpecOCR2Spec + graphql.NoUnmarshalJSON + } + firstPass.JobPartsSpecOCR2Spec = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.OCR2Spec) + if err != nil { + return err + } + return nil +} + +type __premarshalJobPartsSpecOCR2Spec struct { + Typename string `json:"__typename"` + + BlockchainTimeout string `json:"blockchainTimeout"` + + ContractID string `json:"contractID"` + + ContractConfigConfirmations int `json:"contractConfigConfirmations"` + + ContractConfigTrackerPollInterval string `json:"contractConfigTrackerPollInterval"` + + CreatedAt string `json:"createdAt"` + + OcrKeyBundleID string `json:"ocrKeyBundleID"` + + MonitoringEndpoint string `json:"monitoringEndpoint"` + + P2pv2Bootstrappers []string `json:"p2pv2Bootstrappers"` + + Relay string `json:"relay"` + + RelayConfig gqlscalar.Map `json:"relayConfig"` + + TransmitterID string `json:"transmitterID"` + + PluginType string `json:"pluginType"` + + PluginConfig gqlscalar.Map `json:"pluginConfig"` +} + +func (v *JobPartsSpecOCR2Spec) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *JobPartsSpecOCR2Spec) __premarshalJSON() (*__premarshalJobPartsSpecOCR2Spec, error) { + var retval __premarshalJobPartsSpecOCR2Spec + + retval.Typename = v.Typename + retval.BlockchainTimeout = v.OCR2Spec.BlockchainTimeout + retval.ContractID = v.OCR2Spec.ContractID + retval.ContractConfigConfirmations = v.OCR2Spec.ContractConfigConfirmations + retval.ContractConfigTrackerPollInterval = v.OCR2Spec.ContractConfigTrackerPollInterval + retval.CreatedAt = v.OCR2Spec.CreatedAt + retval.OcrKeyBundleID = v.OCR2Spec.OcrKeyBundleID + retval.MonitoringEndpoint = v.OCR2Spec.MonitoringEndpoint + retval.P2pv2Bootstrappers = v.OCR2Spec.P2pv2Bootstrappers + retval.Relay = v.OCR2Spec.Relay + retval.RelayConfig = v.OCR2Spec.RelayConfig + retval.TransmitterID = v.OCR2Spec.TransmitterID + retval.PluginType = v.OCR2Spec.PluginType + retval.PluginConfig = v.OCR2Spec.PluginConfig + return &retval, nil +} + +// JobPartsSpecOCRSpec includes the requested fields of the GraphQL type OCRSpec. +type JobPartsSpecOCRSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecOCRSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecOCRSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecStandardCapabilitiesSpec includes the requested fields of the GraphQL type StandardCapabilitiesSpec. +type JobPartsSpecStandardCapabilitiesSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecStandardCapabilitiesSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecStandardCapabilitiesSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecVRFSpec includes the requested fields of the GraphQL type VRFSpec. +type JobPartsSpecVRFSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecVRFSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecVRFSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecWebhookSpec includes the requested fields of the GraphQL type WebhookSpec. +type JobPartsSpecWebhookSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecWebhookSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecWebhookSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecWorkflowSpec includes the requested fields of the GraphQL type WorkflowSpec. +type JobPartsSpecWorkflowSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecWorkflowSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecWorkflowSpec) GetTypename() string { return v.Typename } + +type JobProposalStatus string + +const ( + JobProposalStatusPending JobProposalStatus = "PENDING" + JobProposalStatusApproved JobProposalStatus = "APPROVED" + JobProposalStatusRejected JobProposalStatus = "REJECTED" + JobProposalStatusCancelled JobProposalStatus = "CANCELLED" + JobProposalStatusDeleted JobProposalStatus = "DELETED" + JobProposalStatusRevoked JobProposalStatus = "REVOKED" +) + +// ListBridgesBridgesBridgesPayload includes the requested fields of the GraphQL type BridgesPayload. +type ListBridgesBridgesBridgesPayload struct { + Results []ListBridgesBridgesBridgesPayloadResultsBridge `json:"results"` + Metadata ListBridgesBridgesBridgesPayloadMetadataPaginationMetadata `json:"metadata"` +} + +// GetResults returns ListBridgesBridgesBridgesPayload.Results, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayload) GetResults() []ListBridgesBridgesBridgesPayloadResultsBridge { + return v.Results +} + +// GetMetadata returns ListBridgesBridgesBridgesPayload.Metadata, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayload) GetMetadata() ListBridgesBridgesBridgesPayloadMetadataPaginationMetadata { + return v.Metadata +} + +// ListBridgesBridgesBridgesPayloadMetadataPaginationMetadata includes the requested fields of the GraphQL type PaginationMetadata. +type ListBridgesBridgesBridgesPayloadMetadataPaginationMetadata struct { + Total int `json:"total"` +} + +// GetTotal returns ListBridgesBridgesBridgesPayloadMetadataPaginationMetadata.Total, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadMetadataPaginationMetadata) GetTotal() int { return v.Total } + +// ListBridgesBridgesBridgesPayloadResultsBridge includes the requested fields of the GraphQL type Bridge. +type ListBridgesBridgesBridgesPayloadResultsBridge struct { + BridgeParts `json:"-"` +} + +// GetId returns ListBridgesBridgesBridgesPayloadResultsBridge.Id, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetId() string { return v.BridgeParts.Id } + +// GetName returns ListBridgesBridgesBridgesPayloadResultsBridge.Name, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetName() string { return v.BridgeParts.Name } + +// GetUrl returns ListBridgesBridgesBridgesPayloadResultsBridge.Url, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetUrl() string { return v.BridgeParts.Url } + +// GetConfirmations returns ListBridgesBridgesBridgesPayloadResultsBridge.Confirmations, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetConfirmations() int { + return v.BridgeParts.Confirmations +} + +// GetOutgoingToken returns ListBridgesBridgesBridgesPayloadResultsBridge.OutgoingToken, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetOutgoingToken() string { + return v.BridgeParts.OutgoingToken +} + +// GetMinimumContractPayment returns ListBridgesBridgesBridgesPayloadResultsBridge.MinimumContractPayment, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetMinimumContractPayment() string { + return v.BridgeParts.MinimumContractPayment +} + +// GetCreatedAt returns ListBridgesBridgesBridgesPayloadResultsBridge.CreatedAt, and is useful for accessing the field via an interface. +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) GetCreatedAt() string { + return v.BridgeParts.CreatedAt +} + +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *ListBridgesBridgesBridgesPayloadResultsBridge + graphql.NoUnmarshalJSON + } + firstPass.ListBridgesBridgesBridgesPayloadResultsBridge = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.BridgeParts) + if err != nil { + return err + } + return nil +} + +type __premarshalListBridgesBridgesBridgesPayloadResultsBridge struct { + Id string `json:"id"` + + Name string `json:"name"` + + Url string `json:"url"` + + Confirmations int `json:"confirmations"` + + OutgoingToken string `json:"outgoingToken"` + + MinimumContractPayment string `json:"minimumContractPayment"` + + CreatedAt string `json:"createdAt"` +} + +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *ListBridgesBridgesBridgesPayloadResultsBridge) __premarshalJSON() (*__premarshalListBridgesBridgesBridgesPayloadResultsBridge, error) { + var retval __premarshalListBridgesBridgesBridgesPayloadResultsBridge + + retval.Id = v.BridgeParts.Id + retval.Name = v.BridgeParts.Name + retval.Url = v.BridgeParts.Url + retval.Confirmations = v.BridgeParts.Confirmations + retval.OutgoingToken = v.BridgeParts.OutgoingToken + retval.MinimumContractPayment = v.BridgeParts.MinimumContractPayment + retval.CreatedAt = v.BridgeParts.CreatedAt + return &retval, nil +} + +// ListBridgesResponse is returned by ListBridges on success. +type ListBridgesResponse struct { + Bridges ListBridgesBridgesBridgesPayload `json:"bridges"` +} + +// GetBridges returns ListBridgesResponse.Bridges, and is useful for accessing the field via an interface. +func (v *ListBridgesResponse) GetBridges() ListBridgesBridgesBridgesPayload { return v.Bridges } + +// ListFeedsManagersFeedsManagersFeedsManagersPayload includes the requested fields of the GraphQL type FeedsManagersPayload. +type ListFeedsManagersFeedsManagersFeedsManagersPayload struct { + Results []ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager `json:"results"` +} + +// GetResults returns ListFeedsManagersFeedsManagersFeedsManagersPayload.Results, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayload) GetResults() []ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager { + return v.Results +} + +// ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager includes the requested fields of the GraphQL type FeedsManager. +type ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager struct { + FeedsManagerParts `json:"-"` +} + +// GetId returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.Id, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetId() string { + return v.FeedsManagerParts.Id +} + +// GetName returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.Name, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetName() string { + return v.FeedsManagerParts.Name +} + +// GetUri returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.Uri, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetUri() string { + return v.FeedsManagerParts.Uri +} + +// GetPublicKey returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.PublicKey, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetPublicKey() string { + return v.FeedsManagerParts.PublicKey +} + +// GetIsConnectionActive returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.IsConnectionActive, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetIsConnectionActive() bool { + return v.FeedsManagerParts.IsConnectionActive +} + +// GetCreatedAt returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.CreatedAt, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetCreatedAt() string { + return v.FeedsManagerParts.CreatedAt +} + +// GetJobProposals returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager + graphql.NoUnmarshalJSON + } + firstPass.ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.FeedsManagerParts) + if err != nil { + return err + } + return nil +} + +type __premarshalListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager struct { + Id string `json:"id"` + + Name string `json:"name"` + + Uri string `json:"uri"` + + PublicKey string `json:"publicKey"` + + IsConnectionActive bool `json:"isConnectionActive"` + + CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` +} + +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) __premarshalJSON() (*__premarshalListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager, error) { + var retval __premarshalListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager + + retval.Id = v.FeedsManagerParts.Id + retval.Name = v.FeedsManagerParts.Name + retval.Uri = v.FeedsManagerParts.Uri + retval.PublicKey = v.FeedsManagerParts.PublicKey + retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive + retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals + return &retval, nil +} + +// ListFeedsManagersResponse is returned by ListFeedsManagers on success. +type ListFeedsManagersResponse struct { + FeedsManagers ListFeedsManagersFeedsManagersFeedsManagersPayload `json:"feedsManagers"` +} + +// GetFeedsManagers returns ListFeedsManagersResponse.FeedsManagers, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersResponse) GetFeedsManagers() ListFeedsManagersFeedsManagersFeedsManagersPayload { + return v.FeedsManagers +} + +// ListJobsJobsJobsPayload includes the requested fields of the GraphQL type JobsPayload. +type ListJobsJobsJobsPayload struct { + Results []ListJobsJobsJobsPayloadResultsJob `json:"results"` + Metadata ListJobsJobsJobsPayloadMetadataPaginationMetadata `json:"metadata"` +} + +// GetResults returns ListJobsJobsJobsPayload.Results, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayload) GetResults() []ListJobsJobsJobsPayloadResultsJob { return v.Results } + +// GetMetadata returns ListJobsJobsJobsPayload.Metadata, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayload) GetMetadata() ListJobsJobsJobsPayloadMetadataPaginationMetadata { + return v.Metadata +} + +// ListJobsJobsJobsPayloadMetadataPaginationMetadata includes the requested fields of the GraphQL type PaginationMetadata. +type ListJobsJobsJobsPayloadMetadataPaginationMetadata struct { + Total int `json:"total"` +} + +// GetTotal returns ListJobsJobsJobsPayloadMetadataPaginationMetadata.Total, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadMetadataPaginationMetadata) GetTotal() int { return v.Total } + +// ListJobsJobsJobsPayloadResultsJob includes the requested fields of the GraphQL type Job. +type ListJobsJobsJobsPayloadResultsJob struct { + JobParts `json:"-"` +} + +// GetId returns ListJobsJobsJobsPayloadResultsJob.Id, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetId() string { return v.JobParts.Id } + +// GetName returns ListJobsJobsJobsPayloadResultsJob.Name, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetName() string { return v.JobParts.Name } + +// GetSchemaVersion returns ListJobsJobsJobsPayloadResultsJob.SchemaVersion, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetSchemaVersion() int { return v.JobParts.SchemaVersion } + +// GetGasLimit returns ListJobsJobsJobsPayloadResultsJob.GasLimit, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetGasLimit() int { return v.JobParts.GasLimit } + +// GetForwardingAllowed returns ListJobsJobsJobsPayloadResultsJob.ForwardingAllowed, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetForwardingAllowed() bool { + return v.JobParts.ForwardingAllowed +} + +// GetMaxTaskDuration returns ListJobsJobsJobsPayloadResultsJob.MaxTaskDuration, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetMaxTaskDuration() string { + return v.JobParts.MaxTaskDuration +} + +// GetExternalJobID returns ListJobsJobsJobsPayloadResultsJob.ExternalJobID, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetExternalJobID() string { + return v.JobParts.ExternalJobID +} + +// GetType returns ListJobsJobsJobsPayloadResultsJob.Type, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetType() string { return v.JobParts.Type } + +// GetSpec returns ListJobsJobsJobsPayloadResultsJob.Spec, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetSpec() JobPartsSpecJobSpec { return v.JobParts.Spec } + +// GetObservationSource returns ListJobsJobsJobsPayloadResultsJob.ObservationSource, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetObservationSource() string { + return v.JobParts.ObservationSource +} + +// GetErrors returns ListJobsJobsJobsPayloadResultsJob.Errors, and is useful for accessing the field via an interface. +func (v *ListJobsJobsJobsPayloadResultsJob) GetErrors() []JobPartsErrorsJobError { + return v.JobParts.Errors +} + +func (v *ListJobsJobsJobsPayloadResultsJob) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *ListJobsJobsJobsPayloadResultsJob + graphql.NoUnmarshalJSON + } + firstPass.ListJobsJobsJobsPayloadResultsJob = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.JobParts) + if err != nil { + return err + } + return nil +} + +type __premarshalListJobsJobsJobsPayloadResultsJob struct { + Id string `json:"id"` + + Name string `json:"name"` + + SchemaVersion int `json:"schemaVersion"` + + GasLimit int `json:"gasLimit"` + + ForwardingAllowed bool `json:"forwardingAllowed"` + + MaxTaskDuration string `json:"maxTaskDuration"` + + ExternalJobID string `json:"externalJobID"` + + Type string `json:"type"` + + Spec json.RawMessage `json:"spec"` + + ObservationSource string `json:"observationSource"` + + Errors []JobPartsErrorsJobError `json:"errors"` +} + +func (v *ListJobsJobsJobsPayloadResultsJob) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *ListJobsJobsJobsPayloadResultsJob) __premarshalJSON() (*__premarshalListJobsJobsJobsPayloadResultsJob, error) { + var retval __premarshalListJobsJobsJobsPayloadResultsJob + + retval.Id = v.JobParts.Id + retval.Name = v.JobParts.Name + retval.SchemaVersion = v.JobParts.SchemaVersion + retval.GasLimit = v.JobParts.GasLimit + retval.ForwardingAllowed = v.JobParts.ForwardingAllowed + retval.MaxTaskDuration = v.JobParts.MaxTaskDuration + retval.ExternalJobID = v.JobParts.ExternalJobID + retval.Type = v.JobParts.Type + { + + dst := &retval.Spec + src := v.JobParts.Spec + var err error + *dst, err = __marshalJobPartsSpecJobSpec( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal ListJobsJobsJobsPayloadResultsJob.JobParts.Spec: %w", err) + } + } + retval.ObservationSource = v.JobParts.ObservationSource + retval.Errors = v.JobParts.Errors + return &retval, nil +} + +// ListJobsResponse is returned by ListJobs on success. +type ListJobsResponse struct { + Jobs ListJobsJobsJobsPayload `json:"jobs"` +} + +// GetJobs returns ListJobsResponse.Jobs, and is useful for accessing the field via an interface. +func (v *ListJobsResponse) GetJobs() ListJobsJobsJobsPayload { return v.Jobs } + +type OCR2ChainType string + +const ( + OCR2ChainTypeEvm OCR2ChainType = "EVM" + OCR2ChainTypeCosmos OCR2ChainType = "COSMOS" + OCR2ChainTypeSolana OCR2ChainType = "SOLANA" + OCR2ChainTypeStarknet OCR2ChainType = "STARKNET" + OCR2ChainTypeAptos OCR2ChainType = "APTOS" +) + +// #################### +// Jobs and Job Proposals +// #################### +type OCR2Spec struct { + BlockchainTimeout string `json:"blockchainTimeout"` + ContractID string `json:"contractID"` + ContractConfigConfirmations int `json:"contractConfigConfirmations"` + ContractConfigTrackerPollInterval string `json:"contractConfigTrackerPollInterval"` + CreatedAt string `json:"createdAt"` + OcrKeyBundleID string `json:"ocrKeyBundleID"` + MonitoringEndpoint string `json:"monitoringEndpoint"` + P2pv2Bootstrappers []string `json:"p2pv2Bootstrappers"` + Relay string `json:"relay"` + RelayConfig gqlscalar.Map `json:"relayConfig"` + TransmitterID string `json:"transmitterID"` + PluginType string `json:"pluginType"` + PluginConfig gqlscalar.Map `json:"pluginConfig"` +} + +// GetBlockchainTimeout returns OCR2Spec.BlockchainTimeout, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetBlockchainTimeout() string { return v.BlockchainTimeout } + +// GetContractID returns OCR2Spec.ContractID, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetContractID() string { return v.ContractID } + +// GetContractConfigConfirmations returns OCR2Spec.ContractConfigConfirmations, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetContractConfigConfirmations() int { return v.ContractConfigConfirmations } + +// GetContractConfigTrackerPollInterval returns OCR2Spec.ContractConfigTrackerPollInterval, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetContractConfigTrackerPollInterval() string { + return v.ContractConfigTrackerPollInterval +} + +// GetCreatedAt returns OCR2Spec.CreatedAt, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetCreatedAt() string { return v.CreatedAt } + +// GetOcrKeyBundleID returns OCR2Spec.OcrKeyBundleID, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetOcrKeyBundleID() string { return v.OcrKeyBundleID } + +// GetMonitoringEndpoint returns OCR2Spec.MonitoringEndpoint, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetMonitoringEndpoint() string { return v.MonitoringEndpoint } + +// GetP2pv2Bootstrappers returns OCR2Spec.P2pv2Bootstrappers, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetP2pv2Bootstrappers() []string { return v.P2pv2Bootstrappers } + +// GetRelay returns OCR2Spec.Relay, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetRelay() string { return v.Relay } + +// GetRelayConfig returns OCR2Spec.RelayConfig, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetRelayConfig() gqlscalar.Map { return v.RelayConfig } + +// GetTransmitterID returns OCR2Spec.TransmitterID, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetTransmitterID() string { return v.TransmitterID } + +// GetPluginType returns OCR2Spec.PluginType, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetPluginType() string { return v.PluginType } + +// GetPluginConfig returns OCR2Spec.PluginConfig, and is useful for accessing the field via an interface. +func (v *OCR2Spec) GetPluginConfig() gqlscalar.Map { return v.PluginConfig } + +// RejectJobProposalSpecRejectJobProposalSpecNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type RejectJobProposalSpecRejectJobProposalSpecNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns RejectJobProposalSpecRejectJobProposalSpecNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns RejectJobProposalSpecRejectJobProposalSpecNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns RejectJobProposalSpecRejectJobProposalSpecNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecNotFoundError) GetCode() ErrorCode { return v.Code } + +// RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload includes the requested fields of the GraphQL interface RejectJobProposalSpecPayload. +// +// RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload is implemented by the following types: +// RejectJobProposalSpecRejectJobProposalSpecNotFoundError +// RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess +type RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload interface { + implementsGraphQLInterfaceRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *RejectJobProposalSpecRejectJobProposalSpecNotFoundError) implementsGraphQLInterfaceRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload() { +} +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess) implementsGraphQLInterfaceRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload() { +} + +func __unmarshalRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload(b []byte, v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "NotFoundError": + *v = new(RejectJobProposalSpecRejectJobProposalSpecNotFoundError) + return json.Unmarshal(b, *v) + case "RejectJobProposalSpecSuccess": + *v = new(RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing RejectJobProposalSpecPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload: "%v"`, tn.TypeName) + } +} + +func __marshalRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload(v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *RejectJobProposalSpecRejectJobProposalSpecNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *RejectJobProposalSpecRejectJobProposalSpecNotFoundError + }{typename, v} + return json.Marshal(result) + case *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess: + typename = "RejectJobProposalSpecSuccess" + + result := struct { + TypeName string `json:"__typename"` + *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload: "%T"`, v) + } +} + +// RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess includes the requested fields of the GraphQL type RejectJobProposalSpecSuccess. +type RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess struct { + Typename string `json:"__typename"` + Spec RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec `json:"spec"` +} + +// GetTypename returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess.Typename, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess) GetTypename() string { + return v.Typename +} + +// GetSpec returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess.Spec, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccess) GetSpec() RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec { + return v.Spec +} + +// RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecSuccessSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// RejectJobProposalSpecResponse is returned by RejectJobProposalSpec on success. +type RejectJobProposalSpecResponse struct { + RejectJobProposalSpec RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload `json:"-"` +} + +// GetRejectJobProposalSpec returns RejectJobProposalSpecResponse.RejectJobProposalSpec, and is useful for accessing the field via an interface. +func (v *RejectJobProposalSpecResponse) GetRejectJobProposalSpec() RejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload { + return v.RejectJobProposalSpec +} + +func (v *RejectJobProposalSpecResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *RejectJobProposalSpecResponse + RejectJobProposalSpec json.RawMessage `json:"rejectJobProposalSpec"` + graphql.NoUnmarshalJSON + } + firstPass.RejectJobProposalSpecResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.RejectJobProposalSpec + src := firstPass.RejectJobProposalSpec + if len(src) != 0 && string(src) != "null" { + err = __unmarshalRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal RejectJobProposalSpecResponse.RejectJobProposalSpec: %w", err) + } + } + } + return nil +} + +type __premarshalRejectJobProposalSpecResponse struct { + RejectJobProposalSpec json.RawMessage `json:"rejectJobProposalSpec"` +} + +func (v *RejectJobProposalSpecResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *RejectJobProposalSpecResponse) __premarshalJSON() (*__premarshalRejectJobProposalSpecResponse, error) { + var retval __premarshalRejectJobProposalSpecResponse + + { + + dst := &retval.RejectJobProposalSpec + src := v.RejectJobProposalSpec + var err error + *dst, err = __marshalRejectJobProposalSpecRejectJobProposalSpecRejectJobProposalSpecPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal RejectJobProposalSpecResponse.RejectJobProposalSpec: %w", err) + } + } + return &retval, nil +} + +type SpecStatus string + +const ( + SpecStatusUnknown SpecStatus = "UNKNOWN" + SpecStatusPending SpecStatus = "PENDING" + SpecStatusApproved SpecStatus = "APPROVED" + SpecStatusRejected SpecStatus = "REJECTED" + SpecStatusCancelled SpecStatus = "CANCELLED" + SpecStatusRevoked SpecStatus = "REVOKED" +) + +type UpdateFeedsManagerInput struct { + Name string `json:"name"` + Uri string `json:"uri"` + PublicKey string `json:"publicKey"` +} + +// GetName returns UpdateFeedsManagerInput.Name, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerInput) GetName() string { return v.Name } + +// GetUri returns UpdateFeedsManagerInput.Uri, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerInput) GetUri() string { return v.Uri } + +// GetPublicKey returns UpdateFeedsManagerInput.PublicKey, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerInput) GetPublicKey() string { return v.PublicKey } + +// UpdateFeedsManagerResponse is returned by UpdateFeedsManager on success. +type UpdateFeedsManagerResponse struct { + UpdateFeedsManager UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload `json:"-"` +} + +// GetUpdateFeedsManager returns UpdateFeedsManagerResponse.UpdateFeedsManager, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerResponse) GetUpdateFeedsManager() UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload { + return v.UpdateFeedsManager +} + +func (v *UpdateFeedsManagerResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *UpdateFeedsManagerResponse + UpdateFeedsManager json.RawMessage `json:"updateFeedsManager"` + graphql.NoUnmarshalJSON + } + firstPass.UpdateFeedsManagerResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.UpdateFeedsManager + src := firstPass.UpdateFeedsManager + if len(src) != 0 && string(src) != "null" { + err = __unmarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal UpdateFeedsManagerResponse.UpdateFeedsManager: %w", err) + } + } + } + return nil +} + +type __premarshalUpdateFeedsManagerResponse struct { + UpdateFeedsManager json.RawMessage `json:"updateFeedsManager"` +} + +func (v *UpdateFeedsManagerResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *UpdateFeedsManagerResponse) __premarshalJSON() (*__premarshalUpdateFeedsManagerResponse, error) { + var retval __premarshalUpdateFeedsManagerResponse + + { + + dst := &retval.UpdateFeedsManager + src := v.UpdateFeedsManager + var err error + *dst, err = __marshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal UpdateFeedsManagerResponse.UpdateFeedsManager: %w", err) + } + } + return &retval, nil +} + +// UpdateFeedsManagerUpdateFeedsManagerInputErrors includes the requested fields of the GraphQL type InputErrors. +type UpdateFeedsManagerUpdateFeedsManagerInputErrors struct { + Typename string `json:"__typename"` + Errors []UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError `json:"errors"` +} + +// GetTypename returns UpdateFeedsManagerUpdateFeedsManagerInputErrors.Typename, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerInputErrors) GetTypename() string { return v.Typename } + +// GetErrors returns UpdateFeedsManagerUpdateFeedsManagerInputErrors.Errors, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerInputErrors) GetErrors() []UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError { + return v.Errors +} + +// UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError includes the requested fields of the GraphQL type InputError. +type UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError struct { + Message string `json:"message"` + Code ErrorCode `json:"code"` + Path string `json:"path"` +} + +// GetMessage returns UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError.Message, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError) GetMessage() string { + return v.Message +} + +// GetCode returns UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError.Code, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError) GetCode() ErrorCode { + return v.Code +} + +// GetPath returns UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError.Path, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerInputErrorsErrorsInputError) GetPath() string { + return v.Path +} + +// UpdateFeedsManagerUpdateFeedsManagerNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type UpdateFeedsManagerUpdateFeedsManagerNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns UpdateFeedsManagerUpdateFeedsManagerNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerNotFoundError) GetTypename() string { return v.Typename } + +// GetMessage returns UpdateFeedsManagerUpdateFeedsManagerNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerNotFoundError) GetMessage() string { return v.Message } + +// GetCode returns UpdateFeedsManagerUpdateFeedsManagerNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerNotFoundError) GetCode() ErrorCode { return v.Code } + +// UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload includes the requested fields of the GraphQL interface UpdateFeedsManagerPayload. +// +// UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload is implemented by the following types: +// UpdateFeedsManagerUpdateFeedsManagerInputErrors +// UpdateFeedsManagerUpdateFeedsManagerNotFoundError +// UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess +type UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload interface { + implementsGraphQLInterfaceUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *UpdateFeedsManagerUpdateFeedsManagerInputErrors) implementsGraphQLInterfaceUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload() { +} +func (v *UpdateFeedsManagerUpdateFeedsManagerNotFoundError) implementsGraphQLInterfaceUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload() { +} +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess) implementsGraphQLInterfaceUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload() { +} + +func __unmarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload(b []byte, v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "InputErrors": + *v = new(UpdateFeedsManagerUpdateFeedsManagerInputErrors) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(UpdateFeedsManagerUpdateFeedsManagerNotFoundError) + return json.Unmarshal(b, *v) + case "UpdateFeedsManagerSuccess": + *v = new(UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing UpdateFeedsManagerPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload: "%v"`, tn.TypeName) + } +} + +func __marshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload(v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *UpdateFeedsManagerUpdateFeedsManagerInputErrors: + typename = "InputErrors" + + result := struct { + TypeName string `json:"__typename"` + *UpdateFeedsManagerUpdateFeedsManagerInputErrors + }{typename, v} + return json.Marshal(result) + case *UpdateFeedsManagerUpdateFeedsManagerNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *UpdateFeedsManagerUpdateFeedsManagerNotFoundError + }{typename, v} + return json.Marshal(result) + case *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess: + typename = "UpdateFeedsManagerSuccess" + + result := struct { + TypeName string `json:"__typename"` + *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerPayload: "%T"`, v) + } +} + +// UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess includes the requested fields of the GraphQL type UpdateFeedsManagerSuccess. +type UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess struct { + Typename string `json:"__typename"` + FeedsManager UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager `json:"feedsManager"` +} + +// GetTypename returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess.Typename, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess) GetTypename() string { + return v.Typename +} + +// GetFeedsManager returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess.FeedsManager, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccess) GetFeedsManager() UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager { + return v.FeedsManager +} + +// UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager includes the requested fields of the GraphQL type FeedsManager. +type UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager struct { + FeedsManagerParts `json:"-"` +} + +// GetId returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.Id, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetId() string { + return v.FeedsManagerParts.Id +} + +// GetName returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.Name, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetName() string { + return v.FeedsManagerParts.Name +} + +// GetUri returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.Uri, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetUri() string { + return v.FeedsManagerParts.Uri +} + +// GetPublicKey returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.PublicKey, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetPublicKey() string { + return v.FeedsManagerParts.PublicKey +} + +// GetIsConnectionActive returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.IsConnectionActive, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetIsConnectionActive() bool { + return v.FeedsManagerParts.IsConnectionActive +} + +// GetCreatedAt returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.CreatedAt, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetCreatedAt() string { + return v.FeedsManagerParts.CreatedAt +} + +// GetJobProposals returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager + graphql.NoUnmarshalJSON + } + firstPass.UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.FeedsManagerParts) + if err != nil { + return err + } + return nil +} + +type __premarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager struct { + Id string `json:"id"` + + Name string `json:"name"` + + Uri string `json:"uri"` + + PublicKey string `json:"publicKey"` + + IsConnectionActive bool `json:"isConnectionActive"` + + CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` +} + +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) __premarshalJSON() (*__premarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager, error) { + var retval __premarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager + + retval.Id = v.FeedsManagerParts.Id + retval.Name = v.FeedsManagerParts.Name + retval.Uri = v.FeedsManagerParts.Uri + retval.PublicKey = v.FeedsManagerParts.PublicKey + retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive + retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals + return &retval, nil +} + +type UpdateJobProposalSpecDefinitionInput struct { + Definition string `json:"definition"` +} + +// GetDefinition returns UpdateJobProposalSpecDefinitionInput.Definition, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionInput) GetDefinition() string { return v.Definition } + +// UpdateJobProposalSpecDefinitionResponse is returned by UpdateJobProposalSpecDefinition on success. +type UpdateJobProposalSpecDefinitionResponse struct { + UpdateJobProposalSpecDefinition UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload `json:"-"` +} + +// GetUpdateJobProposalSpecDefinition returns UpdateJobProposalSpecDefinitionResponse.UpdateJobProposalSpecDefinition, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionResponse) GetUpdateJobProposalSpecDefinition() UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload { + return v.UpdateJobProposalSpecDefinition +} + +func (v *UpdateJobProposalSpecDefinitionResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *UpdateJobProposalSpecDefinitionResponse + UpdateJobProposalSpecDefinition json.RawMessage `json:"updateJobProposalSpecDefinition"` + graphql.NoUnmarshalJSON + } + firstPass.UpdateJobProposalSpecDefinitionResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.UpdateJobProposalSpecDefinition + src := firstPass.UpdateJobProposalSpecDefinition + if len(src) != 0 && string(src) != "null" { + err = __unmarshalUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal UpdateJobProposalSpecDefinitionResponse.UpdateJobProposalSpecDefinition: %w", err) + } + } + } + return nil +} + +type __premarshalUpdateJobProposalSpecDefinitionResponse struct { + UpdateJobProposalSpecDefinition json.RawMessage `json:"updateJobProposalSpecDefinition"` +} + +func (v *UpdateJobProposalSpecDefinitionResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *UpdateJobProposalSpecDefinitionResponse) __premarshalJSON() (*__premarshalUpdateJobProposalSpecDefinitionResponse, error) { + var retval __premarshalUpdateJobProposalSpecDefinitionResponse + + { + + dst := &retval.UpdateJobProposalSpecDefinition + src := v.UpdateJobProposalSpecDefinition + var err error + *dst, err = __marshalUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal UpdateJobProposalSpecDefinitionResponse.UpdateJobProposalSpecDefinition: %w", err) + } + } + return &retval, nil +} + +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError) GetCode() ErrorCode { + return v.Code +} + +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload includes the requested fields of the GraphQL interface UpdateJobProposalSpecDefinitionPayload. +// +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload is implemented by the following types: +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess +type UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload interface { + implementsGraphQLInterfaceUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError) implementsGraphQLInterfaceUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload() { +} +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess) implementsGraphQLInterfaceUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload() { +} + +func __unmarshalUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload(b []byte, v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "NotFoundError": + *v = new(UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError) + return json.Unmarshal(b, *v) + case "UpdateJobProposalSpecDefinitionSuccess": + *v = new(UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing UpdateJobProposalSpecDefinitionPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload: "%v"`, tn.TypeName) + } +} + +func __marshalUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload(v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionNotFoundError + }{typename, v} + return json.Marshal(result) + case *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess: + typename = "UpdateJobProposalSpecDefinitionSuccess" + + result := struct { + TypeName string `json:"__typename"` + *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionPayload: "%T"`, v) + } +} + +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess includes the requested fields of the GraphQL type UpdateJobProposalSpecDefinitionSuccess. +type UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess struct { + Typename string `json:"__typename"` + Spec UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec `json:"spec"` +} + +// GetTypename returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess.Typename, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess) GetTypename() string { + return v.Typename +} + +// GetSpec returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess.Spec, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccess) GetSpec() UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec { + return v.Spec +} + +// UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *UpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionUpdateJobProposalSpecDefinitionSuccessSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// __ApproveJobProposalSpecInput is used internally by genqlient +type __ApproveJobProposalSpecInput struct { + Id string `json:"id"` + Force bool `json:"force"` +} + +// GetId returns __ApproveJobProposalSpecInput.Id, and is useful for accessing the field via an interface. +func (v *__ApproveJobProposalSpecInput) GetId() string { return v.Id } + +// GetForce returns __ApproveJobProposalSpecInput.Force, and is useful for accessing the field via an interface. +func (v *__ApproveJobProposalSpecInput) GetForce() bool { return v.Force } + +// __CancelJobProposalSpecInput is used internally by genqlient +type __CancelJobProposalSpecInput struct { + Id string `json:"id"` +} + +// GetId returns __CancelJobProposalSpecInput.Id, and is useful for accessing the field via an interface. +func (v *__CancelJobProposalSpecInput) GetId() string { return v.Id } + +// __CreateFeedsManagerChainConfigInput is used internally by genqlient +type __CreateFeedsManagerChainConfigInput struct { + Input CreateFeedsManagerChainConfigInput `json:"input"` +} + +// GetInput returns __CreateFeedsManagerChainConfigInput.Input, and is useful for accessing the field via an interface. +func (v *__CreateFeedsManagerChainConfigInput) GetInput() CreateFeedsManagerChainConfigInput { + return v.Input +} + +// __CreateFeedsManagerInput is used internally by genqlient +type __CreateFeedsManagerInput struct { + Input CreateFeedsManagerInput `json:"input"` +} + +// GetInput returns __CreateFeedsManagerInput.Input, and is useful for accessing the field via an interface. +func (v *__CreateFeedsManagerInput) GetInput() CreateFeedsManagerInput { return v.Input } + +// __DeleteFeedsManagerChainConfigInput is used internally by genqlient +type __DeleteFeedsManagerChainConfigInput struct { + Id string `json:"id"` +} + +// GetId returns __DeleteFeedsManagerChainConfigInput.Id, and is useful for accessing the field via an interface. +func (v *__DeleteFeedsManagerChainConfigInput) GetId() string { return v.Id } + +// __GetBridgeInput is used internally by genqlient +type __GetBridgeInput struct { + Id string `json:"id"` +} + +// GetId returns __GetBridgeInput.Id, and is useful for accessing the field via an interface. +func (v *__GetBridgeInput) GetId() string { return v.Id } + +// __GetFeedsManagerInput is used internally by genqlient +type __GetFeedsManagerInput struct { + Id string `json:"id"` +} + +// GetId returns __GetFeedsManagerInput.Id, and is useful for accessing the field via an interface. +func (v *__GetFeedsManagerInput) GetId() string { return v.Id } + +// __GetJobInput is used internally by genqlient +type __GetJobInput struct { + Id string `json:"id"` +} + +// GetId returns __GetJobInput.Id, and is useful for accessing the field via an interface. +func (v *__GetJobInput) GetId() string { return v.Id } + +// __GetJobProposalInput is used internally by genqlient +type __GetJobProposalInput struct { + Id string `json:"id"` +} + +// GetId returns __GetJobProposalInput.Id, and is useful for accessing the field via an interface. +func (v *__GetJobProposalInput) GetId() string { return v.Id } + +// __ListBridgesInput is used internally by genqlient +type __ListBridgesInput struct { + Offset int `json:"offset"` + Limit int `json:"limit"` +} + +// GetOffset returns __ListBridgesInput.Offset, and is useful for accessing the field via an interface. +func (v *__ListBridgesInput) GetOffset() int { return v.Offset } + +// GetLimit returns __ListBridgesInput.Limit, and is useful for accessing the field via an interface. +func (v *__ListBridgesInput) GetLimit() int { return v.Limit } + +// __ListJobsInput is used internally by genqlient +type __ListJobsInput struct { + Offset int `json:"offset"` + Limit int `json:"limit"` +} + +// GetOffset returns __ListJobsInput.Offset, and is useful for accessing the field via an interface. +func (v *__ListJobsInput) GetOffset() int { return v.Offset } + +// GetLimit returns __ListJobsInput.Limit, and is useful for accessing the field via an interface. +func (v *__ListJobsInput) GetLimit() int { return v.Limit } + +// __RejectJobProposalSpecInput is used internally by genqlient +type __RejectJobProposalSpecInput struct { + Id string `json:"id"` +} + +// GetId returns __RejectJobProposalSpecInput.Id, and is useful for accessing the field via an interface. +func (v *__RejectJobProposalSpecInput) GetId() string { return v.Id } + +// __UpdateFeedsManagerInput is used internally by genqlient +type __UpdateFeedsManagerInput struct { + Id string `json:"id"` + Input UpdateFeedsManagerInput `json:"input"` +} + +// GetId returns __UpdateFeedsManagerInput.Id, and is useful for accessing the field via an interface. +func (v *__UpdateFeedsManagerInput) GetId() string { return v.Id } + +// GetInput returns __UpdateFeedsManagerInput.Input, and is useful for accessing the field via an interface. +func (v *__UpdateFeedsManagerInput) GetInput() UpdateFeedsManagerInput { return v.Input } + +// __UpdateJobProposalSpecDefinitionInput is used internally by genqlient +type __UpdateJobProposalSpecDefinitionInput struct { + Id string `json:"id"` + Input UpdateJobProposalSpecDefinitionInput `json:"input"` +} + +// GetId returns __UpdateJobProposalSpecDefinitionInput.Id, and is useful for accessing the field via an interface. +func (v *__UpdateJobProposalSpecDefinitionInput) GetId() string { return v.Id } + +// GetInput returns __UpdateJobProposalSpecDefinitionInput.Input, and is useful for accessing the field via an interface. +func (v *__UpdateJobProposalSpecDefinitionInput) GetInput() UpdateJobProposalSpecDefinitionInput { + return v.Input +} + +// The query or mutation executed by ApproveJobProposalSpec. +const ApproveJobProposalSpec_Operation = ` +mutation ApproveJobProposalSpec ($id: ID!, $force: Boolean) { + approveJobProposalSpec(id: $id, force: $force) { + __typename + ... on ApproveJobProposalSpecSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on JobAlreadyExistsError { + message + code + } + ... on NotFoundError { + message + code + } + } +} +` + +func ApproveJobProposalSpec( + ctx_ context.Context, + client_ graphql.Client, + id string, + force bool, +) (*ApproveJobProposalSpecResponse, error) { + req_ := &graphql.Request{ + OpName: "ApproveJobProposalSpec", + Query: ApproveJobProposalSpec_Operation, + Variables: &__ApproveJobProposalSpecInput{ + Id: id, + Force: force, + }, + } + var err_ error + + var data_ ApproveJobProposalSpecResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by CancelJobProposalSpec. +const CancelJobProposalSpec_Operation = ` +mutation CancelJobProposalSpec ($id: ID!) { + cancelJobProposalSpec(id: $id) { + __typename + ... on CancelJobProposalSpecSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} +` + +func CancelJobProposalSpec( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*CancelJobProposalSpecResponse, error) { + req_ := &graphql.Request{ + OpName: "CancelJobProposalSpec", + Query: CancelJobProposalSpec_Operation, + Variables: &__CancelJobProposalSpecInput{ + Id: id, + }, + } + var err_ error + + var data_ CancelJobProposalSpecResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by CreateFeedsManager. +const CreateFeedsManager_Operation = ` +mutation CreateFeedsManager ($input: CreateFeedsManagerInput!) { + createFeedsManager(input: $input) { + __typename + ... on CreateFeedsManagerSuccess { + feedsManager { + ... FeedsManagerParts + } + } + ... on SingleFeedsManagerError { + message + code + } + ... on NotFoundError { + message + code + } + ... on InputErrors { + errors { + message + code + path + } + } + } +} +fragment FeedsManagerParts on FeedsManager { + id + name + uri + publicKey + isConnectionActive + createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } +} +` + +func CreateFeedsManager( + ctx_ context.Context, + client_ graphql.Client, + input CreateFeedsManagerInput, +) (*CreateFeedsManagerResponse, error) { + req_ := &graphql.Request{ + OpName: "CreateFeedsManager", + Query: CreateFeedsManager_Operation, + Variables: &__CreateFeedsManagerInput{ + Input: input, + }, + } + var err_ error + + var data_ CreateFeedsManagerResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by CreateFeedsManagerChainConfig. +const CreateFeedsManagerChainConfig_Operation = ` +mutation CreateFeedsManagerChainConfig ($input: CreateFeedsManagerChainConfigInput!) { + createFeedsManagerChainConfig(input: $input) { + __typename + ... on CreateFeedsManagerChainConfigSuccess { + chainConfig { + id + chainID + chainType + accountAddr + adminAddr + fluxMonitorJobConfig { + enabled + } + ocr1JobConfig { + enabled + isBootstrap + multiaddr + p2pPeerID + keyBundleID + } + ocr2JobConfig { + enabled + isBootstrap + multiaddr + forwarderAddress + p2pPeerID + keyBundleID + plugins { + commit + execute + median + mercury + rebalancer + } + } + } + } + ... on NotFoundError { + message + code + } + ... on InputErrors { + errors { + message + path + } + } + } +} +` + +// createFeedsManagerChainConfig.graphql +func CreateFeedsManagerChainConfig( + ctx_ context.Context, + client_ graphql.Client, + input CreateFeedsManagerChainConfigInput, +) (*CreateFeedsManagerChainConfigResponse, error) { + req_ := &graphql.Request{ + OpName: "CreateFeedsManagerChainConfig", + Query: CreateFeedsManagerChainConfig_Operation, + Variables: &__CreateFeedsManagerChainConfigInput{ + Input: input, + }, + } + var err_ error + + var data_ CreateFeedsManagerChainConfigResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by DeleteFeedsManagerChainConfig. +const DeleteFeedsManagerChainConfig_Operation = ` +mutation DeleteFeedsManagerChainConfig ($id: ID!) { + deleteFeedsManagerChainConfig(id: $id) { + __typename + ... on DeleteFeedsManagerChainConfigSuccess { + chainConfig { + id + } + } + ... on NotFoundError { + message + code + } + } +} +` + +func DeleteFeedsManagerChainConfig( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*DeleteFeedsManagerChainConfigResponse, error) { + req_ := &graphql.Request{ + OpName: "DeleteFeedsManagerChainConfig", + Query: DeleteFeedsManagerChainConfig_Operation, + Variables: &__DeleteFeedsManagerChainConfigInput{ + Id: id, + }, + } + var err_ error + + var data_ DeleteFeedsManagerChainConfigResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by FetchAccounts. +const FetchAccounts_Operation = ` +query FetchAccounts { + ethKeys { + results { + address + isDisabled + chain { + id + enabled + } + ethBalance + linkBalance + } + } +} +` + +func FetchAccounts( + ctx_ context.Context, + client_ graphql.Client, +) (*FetchAccountsResponse, error) { + req_ := &graphql.Request{ + OpName: "FetchAccounts", + Query: FetchAccounts_Operation, + } + var err_ error + + var data_ FetchAccountsResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by FetchCSAKeys. +const FetchCSAKeys_Operation = ` +query FetchCSAKeys { + csaKeys { + results { + id + publicKey + version + } + } +} +` + +func FetchCSAKeys( + ctx_ context.Context, + client_ graphql.Client, +) (*FetchCSAKeysResponse, error) { + req_ := &graphql.Request{ + OpName: "FetchCSAKeys", + Query: FetchCSAKeys_Operation, + } + var err_ error + + var data_ FetchCSAKeysResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by FetchOCR2KeyBundles. +const FetchOCR2KeyBundles_Operation = ` +query FetchOCR2KeyBundles { + ocr2KeyBundles { + results { + id + chainType + configPublicKey + onChainPublicKey + offChainPublicKey + } + } +} +` + +func FetchOCR2KeyBundles( + ctx_ context.Context, + client_ graphql.Client, +) (*FetchOCR2KeyBundlesResponse, error) { + req_ := &graphql.Request{ + OpName: "FetchOCR2KeyBundles", + Query: FetchOCR2KeyBundles_Operation, + } + var err_ error + + var data_ FetchOCR2KeyBundlesResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by FetchP2PKeys. +const FetchP2PKeys_Operation = ` +query FetchP2PKeys { + p2pKeys { + results { + id + peerID + publicKey + } + } +} +` + +func FetchP2PKeys( + ctx_ context.Context, + client_ graphql.Client, +) (*FetchP2PKeysResponse, error) { + req_ := &graphql.Request{ + OpName: "FetchP2PKeys", + Query: FetchP2PKeys_Operation, + } + var err_ error + + var data_ FetchP2PKeysResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by GetBridge. +const GetBridge_Operation = ` +query GetBridge ($id: ID!) { + bridge(id: $id) { + __typename + ... BridgeParts + ... on NotFoundError { + message + code + } + } +} +fragment BridgeParts on Bridge { + id + name + url + confirmations + outgoingToken + minimumContractPayment + createdAt +} +` + +func GetBridge( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*GetBridgeResponse, error) { + req_ := &graphql.Request{ + OpName: "GetBridge", + Query: GetBridge_Operation, + Variables: &__GetBridgeInput{ + Id: id, + }, + } + var err_ error + + var data_ GetBridgeResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by GetFeedsManager. +const GetFeedsManager_Operation = ` +query GetFeedsManager ($id: ID!) { + feedsManager(id: $id) { + __typename + ... FeedsManagerParts + ... on NotFoundError { + message + code + } + } +} +fragment FeedsManagerParts on FeedsManager { + id + name + uri + publicKey + isConnectionActive + createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } +} +` + +func GetFeedsManager( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*GetFeedsManagerResponse, error) { + req_ := &graphql.Request{ + OpName: "GetFeedsManager", + Query: GetFeedsManager_Operation, + Variables: &__GetFeedsManagerInput{ + Id: id, + }, + } + var err_ error + + var data_ GetFeedsManagerResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by GetJob. +const GetJob_Operation = ` +query GetJob ($id: ID!) { + job(id: $id) { + __typename + ... JobParts + ... on NotFoundError { + message + code + } + } +} +fragment JobParts on Job { + id + name + schemaVersion + gasLimit + forwardingAllowed + maxTaskDuration + externalJobID + type + spec { + __typename + ... on OCR2Spec { + ... OCR2Spec + } + } + observationSource + errors { + id + description + occurrences + createdAt + updatedAt + } +} +fragment OCR2Spec on OCR2Spec { + blockchainTimeout + contractID + contractConfigConfirmations + contractConfigTrackerPollInterval + createdAt + ocrKeyBundleID + monitoringEndpoint + p2pv2Bootstrappers + relay + relayConfig + transmitterID + pluginType + pluginConfig +} +` + +func GetJob( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*GetJobResponse, error) { + req_ := &graphql.Request{ + OpName: "GetJob", + Query: GetJob_Operation, + Variables: &__GetJobInput{ + Id: id, + }, + } + var err_ error + + var data_ GetJobResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by GetJobProposal. +const GetJobProposal_Operation = ` +query GetJobProposal ($id: ID!) { + jobProposal(id: $id) { + __typename + ... on JobProposal { + id + name + status + remoteUUID + externalJobID + jobID + feedsManager { + ... FeedsManagerParts + } + multiAddrs + pendingUpdate + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} +fragment FeedsManagerParts on FeedsManager { + id + name + uri + publicKey + isConnectionActive + createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } +} +` + +func GetJobProposal( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*GetJobProposalResponse, error) { + req_ := &graphql.Request{ + OpName: "GetJobProposal", + Query: GetJobProposal_Operation, + Variables: &__GetJobProposalInput{ + Id: id, + }, + } + var err_ error + + var data_ GetJobProposalResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by ListBridges. +const ListBridges_Operation = ` +query ListBridges ($offset: Int, $limit: Int) { + bridges(offset: $offset, limit: $limit) { + results { + ... BridgeParts + } + metadata { + total + } + } +} +fragment BridgeParts on Bridge { + id + name + url + confirmations + outgoingToken + minimumContractPayment + createdAt +} +` + +func ListBridges( + ctx_ context.Context, + client_ graphql.Client, + offset int, + limit int, +) (*ListBridgesResponse, error) { + req_ := &graphql.Request{ + OpName: "ListBridges", + Query: ListBridges_Operation, + Variables: &__ListBridgesInput{ + Offset: offset, + Limit: limit, + }, + } + var err_ error + + var data_ ListBridgesResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by ListFeedsManagers. +const ListFeedsManagers_Operation = ` +query ListFeedsManagers { + feedsManagers { + results { + ... FeedsManagerParts + } + } +} +fragment FeedsManagerParts on FeedsManager { + id + name + uri + publicKey + isConnectionActive + createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } +} +` + +func ListFeedsManagers( + ctx_ context.Context, + client_ graphql.Client, +) (*ListFeedsManagersResponse, error) { + req_ := &graphql.Request{ + OpName: "ListFeedsManagers", + Query: ListFeedsManagers_Operation, + } + var err_ error + + var data_ ListFeedsManagersResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by ListJobs. +const ListJobs_Operation = ` +query ListJobs ($offset: Int, $limit: Int) { + jobs(offset: $offset, limit: $limit) { + results { + ... JobParts + } + metadata { + total + } + } +} +fragment JobParts on Job { + id + name + schemaVersion + gasLimit + forwardingAllowed + maxTaskDuration + externalJobID + type + spec { + __typename + ... on OCR2Spec { + ... OCR2Spec + } + } + observationSource + errors { + id + description + occurrences + createdAt + updatedAt + } +} +fragment OCR2Spec on OCR2Spec { + blockchainTimeout + contractID + contractConfigConfirmations + contractConfigTrackerPollInterval + createdAt + ocrKeyBundleID + monitoringEndpoint + p2pv2Bootstrappers + relay + relayConfig + transmitterID + pluginType + pluginConfig +} +` + +func ListJobs( + ctx_ context.Context, + client_ graphql.Client, + offset int, + limit int, +) (*ListJobsResponse, error) { + req_ := &graphql.Request{ + OpName: "ListJobs", + Query: ListJobs_Operation, + Variables: &__ListJobsInput{ + Offset: offset, + Limit: limit, + }, + } + var err_ error + + var data_ ListJobsResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by RejectJobProposalSpec. +const RejectJobProposalSpec_Operation = ` +mutation RejectJobProposalSpec ($id: ID!) { + rejectJobProposalSpec(id: $id) { + __typename + ... on RejectJobProposalSpecSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} +` + +func RejectJobProposalSpec( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*RejectJobProposalSpecResponse, error) { + req_ := &graphql.Request{ + OpName: "RejectJobProposalSpec", + Query: RejectJobProposalSpec_Operation, + Variables: &__RejectJobProposalSpecInput{ + Id: id, + }, + } + var err_ error + + var data_ RejectJobProposalSpecResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by UpdateFeedsManager. +const UpdateFeedsManager_Operation = ` +mutation UpdateFeedsManager ($id: ID!, $input: UpdateFeedsManagerInput!) { + updateFeedsManager(id: $id, input: $input) { + __typename + ... on UpdateFeedsManagerSuccess { + feedsManager { + ... FeedsManagerParts + } + } + ... on NotFoundError { + message + code + } + ... on InputErrors { + errors { + message + code + path + } + } + } +} +fragment FeedsManagerParts on FeedsManager { + id + name + uri + publicKey + isConnectionActive + createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } +} +` + +func UpdateFeedsManager( + ctx_ context.Context, + client_ graphql.Client, + id string, + input UpdateFeedsManagerInput, +) (*UpdateFeedsManagerResponse, error) { + req_ := &graphql.Request{ + OpName: "UpdateFeedsManager", + Query: UpdateFeedsManager_Operation, + Variables: &__UpdateFeedsManagerInput{ + Id: id, + Input: input, + }, + } + var err_ error + + var data_ UpdateFeedsManagerResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + +// The query or mutation executed by UpdateJobProposalSpecDefinition. +const UpdateJobProposalSpecDefinition_Operation = ` +mutation UpdateJobProposalSpecDefinition ($id: ID!, $input: UpdateJobProposalSpecDefinitionInput!) { + updateJobProposalSpecDefinition(id: $id, input: $input) { + __typename + ... on UpdateJobProposalSpecDefinitionSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} +` + +func UpdateJobProposalSpecDefinition( + ctx_ context.Context, + client_ graphql.Client, + id string, + input UpdateJobProposalSpecDefinitionInput, +) (*UpdateJobProposalSpecDefinitionResponse, error) { + req_ := &graphql.Request{ + OpName: "UpdateJobProposalSpecDefinition", + Query: UpdateJobProposalSpecDefinition_Operation, + Variables: &__UpdateJobProposalSpecDefinitionInput{ + Id: id, + Input: input, + }, + } + var err_ error + + var data_ UpdateJobProposalSpecDefinitionResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} diff --git a/integration-tests/web/sdk/internal/genqlient.graphql b/integration-tests/web/sdk/internal/genqlient.graphql new file mode 100644 index 00000000000..06baf4f7913 --- /dev/null +++ b/integration-tests/web/sdk/internal/genqlient.graphql @@ -0,0 +1,459 @@ +##################### +# CSA Keys +##################### + +query FetchCSAKeys { + csaKeys { + results { + id + publicKey + version + } + } +} + +##################### +# P2P Keys +##################### + +query FetchP2PKeys { + p2pKeys { + results { + id + peerID + publicKey + } + } +} + +##################### +# ethKeys +##################### + +query FetchAccounts { + ethKeys { + results { + address + isDisabled + chain { + id + enabled + } + ethBalance + linkBalance + } + } +} + +##################### +# ocr2KeyBundles +##################### + +query FetchOCR2KeyBundles { + ocr2KeyBundles { + results { + id + chainType + configPublicKey + onChainPublicKey + offChainPublicKey + } + } +} + + +##################### +# Jobs and Job Proposals +##################### +fragment OCR2Spec on OCR2Spec { + blockchainTimeout + contractID + contractConfigConfirmations + contractConfigTrackerPollInterval + createdAt + ocrKeyBundleID + monitoringEndpoint + p2pv2Bootstrappers + relay + relayConfig + transmitterID + pluginType + pluginConfig +} + +fragment JobParts on Job { + id + name + schemaVersion + gasLimit + forwardingAllowed + maxTaskDuration + externalJobID + type + spec { + ... on OCR2Spec { + ...OCR2Spec + } + } + observationSource + errors { + id + description + occurrences + createdAt + updatedAt + } +} + +query GetJob($id: ID!) { + job(id: $id) { + ...JobParts + ... on NotFoundError { + message + code + } + } +} + +query ListJobs($offset: Int, $limit: Int) { + jobs(offset: $offset, limit: $limit) { + results { + ...JobParts + } + metadata { + total + } + } +} + +query GetJobProposal($id: ID!) { + jobProposal(id: $id) { + ... on JobProposal { + id + name + status + remoteUUID + externalJobID + jobID + feedsManager { + ...FeedsManagerParts + } + multiAddrs + pendingUpdate + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} + +##################### +# Bridges +##################### + +fragment BridgeParts on Bridge { + id + name + url + confirmations + outgoingToken + minimumContractPayment + createdAt +} + +query ListBridges($offset: Int, $limit: Int) { + bridges(offset: $offset, limit: $limit) { + results { + ...BridgeParts + } + metadata { + total + } + } +} + +query GetBridge($id: ID!) { + bridge(id: $id) { + ...BridgeParts + ... on NotFoundError { + message + code + } + } +} + +##################### +# Feeds Manager +##################### + +fragment FeedsManagerParts on FeedsManager { + id + name + uri + publicKey + isConnectionActive + createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } +} + +query GetFeedsManager($id: ID!) { + feedsManager(id: $id) { + ...FeedsManagerParts + ... on NotFoundError { + message + code + } + } +} + +query ListFeedsManagers { + feedsManagers { + results { + ...FeedsManagerParts + } + } +} + +mutation CreateFeedsManager($input: CreateFeedsManagerInput!) { + createFeedsManager(input: $input) { + ... on CreateFeedsManagerSuccess { + feedsManager { + ...FeedsManagerParts + } + } + ... on SingleFeedsManagerError { + message + code + } + ... on NotFoundError { + message + code + } + ... on InputErrors { + errors { + message + code + path + } + } + } +} + +mutation UpdateFeedsManager($id: ID!, $input: UpdateFeedsManagerInput!) { + updateFeedsManager(id: $id, input: $input) { + ... on UpdateFeedsManagerSuccess { + feedsManager { + ...FeedsManagerParts + } + } + ... on NotFoundError { + message + code + } + ... on InputErrors { + errors { + message + code + path + } + } + } +} + +# createFeedsManagerChainConfig.graphql +mutation CreateFeedsManagerChainConfig($input: CreateFeedsManagerChainConfigInput!) { + createFeedsManagerChainConfig(input: $input) { + ... on CreateFeedsManagerChainConfigSuccess { + chainConfig { + id + chainID + chainType + accountAddr + adminAddr + fluxMonitorJobConfig { + enabled + } + ocr1JobConfig { + enabled + isBootstrap + multiaddr + p2pPeerID + keyBundleID + } + ocr2JobConfig { + enabled + isBootstrap + multiaddr + forwarderAddress + p2pPeerID + keyBundleID + plugins { + commit + execute + median + mercury + rebalancer + } + } + } + } + ... on NotFoundError { + message + code + } + ... on InputErrors { + errors { + message + path + } + } + } +} + +mutation DeleteFeedsManagerChainConfig($id: ID!) { + deleteFeedsManagerChainConfig(id: $id) { + ... on DeleteFeedsManagerChainConfigSuccess { + chainConfig { + id + } + } + ... on NotFoundError { + message + code + } + } +} + +##################### +# Job Proposals +##################### + +mutation ApproveJobProposalSpec($id: ID!, $force: Boolean) { + approveJobProposalSpec(id: $id, force: $force) { + ... on ApproveJobProposalSpecSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on JobAlreadyExistsError { + message + code + } + ... on NotFoundError { + message + code + } + } +} + +mutation CancelJobProposalSpec($id: ID!) { + cancelJobProposalSpec(id: $id) { + ... on CancelJobProposalSpecSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} + +mutation RejectJobProposalSpec($id: ID!) { + rejectJobProposalSpec(id: $id) { + ... on RejectJobProposalSpecSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} + +mutation UpdateJobProposalSpecDefinition( + $id: ID! + $input: UpdateJobProposalSpecDefinitionInput! +) { + updateJobProposalSpecDefinition(id: $id, input: $input) { + ... on UpdateJobProposalSpecDefinitionSuccess { + spec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } + ... on NotFoundError { + message + code + } + } +} \ No newline at end of file diff --git a/integration-tests/web/sdk/internal/schema.graphql b/integration-tests/web/sdk/internal/schema.graphql new file mode 100644 index 00000000000..71aa67598da --- /dev/null +++ b/integration-tests/web/sdk/internal/schema.graphql @@ -0,0 +1,1064 @@ +scalar Time +scalar Map +scalar Bytes + +schema { + query: Query + mutation: Mutation +} + +type Query { + bridge(id: ID!): BridgePayload! + bridges(offset: Int, limit: Int): BridgesPayload! + chain(id: ID!): ChainPayload! + chains(offset: Int, limit: Int): ChainsPayload! + configv2: ConfigV2Payload! + csaKeys: CSAKeysPayload! + ethKeys: EthKeysPayload! + ethTransaction(hash: ID!): EthTransactionPayload! + ethTransactions(offset: Int, limit: Int): EthTransactionsPayload! + ethTransactionsAttempts(offset: Int, limit: Int): EthTransactionAttemptsPayload! + features: FeaturesPayload! + feedsManager(id: ID!): FeedsManagerPayload! + feedsManagers: FeedsManagersPayload! + globalLogLevel: GlobalLogLevelPayload! + job(id: ID!): JobPayload! + jobs(offset: Int, limit: Int): JobsPayload! + jobProposal(id: ID!): JobProposalPayload! + jobRun(id: ID!): JobRunPayload! + jobRuns(offset: Int, limit: Int): JobRunsPayload! + node(id: ID!): NodePayload! + nodes(offset: Int, limit: Int): NodesPayload! + ocrKeyBundles: OCRKeyBundlesPayload! + ocr2KeyBundles: OCR2KeyBundlesPayload! + p2pKeys: P2PKeysPayload! + solanaKeys: SolanaKeysPayload! + aptosKeys: AptosKeysPayload! + sqlLogging: GetSQLLoggingPayload! + vrfKey(id: ID!): VRFKeyPayload! + vrfKeys: VRFKeysPayload! +} + +type Mutation { + approveJobProposalSpec(id: ID!, force: Boolean): ApproveJobProposalSpecPayload! + cancelJobProposalSpec(id: ID!): CancelJobProposalSpecPayload! + createAPIToken(input: CreateAPITokenInput!): CreateAPITokenPayload! + createBridge(input: CreateBridgeInput!): CreateBridgePayload! + createCSAKey: CreateCSAKeyPayload! + createFeedsManager(input: CreateFeedsManagerInput!): CreateFeedsManagerPayload! + createFeedsManagerChainConfig(input: CreateFeedsManagerChainConfigInput!): CreateFeedsManagerChainConfigPayload! + createJob(input: CreateJobInput!): CreateJobPayload! + createOCRKeyBundle: CreateOCRKeyBundlePayload! + createOCR2KeyBundle(chainType: OCR2ChainType!): CreateOCR2KeyBundlePayload! + createP2PKey: CreateP2PKeyPayload! + deleteAPIToken(input: DeleteAPITokenInput!): DeleteAPITokenPayload! + deleteBridge(id: ID!): DeleteBridgePayload! + deleteCSAKey(id: ID!): DeleteCSAKeyPayload! + deleteFeedsManagerChainConfig(id: ID!): DeleteFeedsManagerChainConfigPayload! + deleteJob(id: ID!): DeleteJobPayload! + deleteOCRKeyBundle(id: ID!): DeleteOCRKeyBundlePayload! + deleteOCR2KeyBundle(id: ID!): DeleteOCR2KeyBundlePayload! + deleteP2PKey(id: ID!): DeleteP2PKeyPayload! + createVRFKey: CreateVRFKeyPayload! + deleteVRFKey(id: ID!): DeleteVRFKeyPayload! + dismissJobError(id: ID!): DismissJobErrorPayload! + rejectJobProposalSpec(id: ID!): RejectJobProposalSpecPayload! + runJob(id: ID!): RunJobPayload! + setGlobalLogLevel(level: LogLevel!): SetGlobalLogLevelPayload! + setSQLLogging(input: SetSQLLoggingInput!): SetSQLLoggingPayload! + updateBridge(id: ID!, input: UpdateBridgeInput!): UpdateBridgePayload! + updateFeedsManager(id: ID!, input: UpdateFeedsManagerInput!): UpdateFeedsManagerPayload! + updateFeedsManagerChainConfig(id: ID!, input: UpdateFeedsManagerChainConfigInput!): UpdateFeedsManagerChainConfigPayload! + updateJobProposalSpecDefinition(id: ID!, input: UpdateJobProposalSpecDefinitionInput!): UpdateJobProposalSpecDefinitionPayload! + updateUserPassword(input: UpdatePasswordInput!): UpdatePasswordPayload! +} +type APIToken { + accessKey: String! + secret: String! +} + +input CreateAPITokenInput { + password: String! +} + +type CreateAPITokenSuccess { + token: APIToken! +} + +union CreateAPITokenPayload = CreateAPITokenSuccess | InputErrors + +input DeleteAPITokenInput { + password: String! +} + +type DeleteAPITokenResult { + accessKey: String! +} + +type DeleteAPITokenSuccess { + token: DeleteAPITokenResult! +} + +union DeleteAPITokenPayload = DeleteAPITokenSuccess | InputErrors +type AptosKey { + id: ID! + account: String! +} + +type AptosKeysPayload { + results: [AptosKey!]! +} +type Bridge { + id: ID! + name: String! + url: String! + confirmations: Int! + outgoingToken: String! + minimumContractPayment: String! + createdAt: Time! +} + +# BridgePayload defines the response to fetch a single bridge by name +union BridgePayload = Bridge | NotFoundError + +# BridgesPayload defines the response when fetching a page of bridges +type BridgesPayload implements PaginatedPayload { + results: [Bridge!]! + metadata: PaginationMetadata! +} + +# CreateBridgeInput defines the input to create a bridge +input CreateBridgeInput { + name: String! + url: String! + confirmations: Int! + minimumContractPayment: String! +} + +# CreateBridgeSuccess defines the success response when creating a bridge +type CreateBridgeSuccess { + bridge: Bridge! + incomingToken: String! +} + +# CreateBridgeInput defines the response when creating a bridge +union CreateBridgePayload = CreateBridgeSuccess + +# UpdateBridgeInput defines the input to update a bridge +input UpdateBridgeInput { + name: String! + url: String! + confirmations: Int! + minimumContractPayment: String! +} + +# UpdateBridgeSuccess defines the success response when updating a bridge +type UpdateBridgeSuccess { + bridge: Bridge! +} + +# CreateBridgeInput defines the response when updating a bridge +union UpdateBridgePayload = UpdateBridgeSuccess | NotFoundError + +type DeleteBridgeSuccess { + bridge: Bridge! +} + +type DeleteBridgeInvalidNameError implements Error { + code: ErrorCode! + message: String! +} + +type DeleteBridgeConflictError implements Error { + code: ErrorCode! + message: String! +} + +union DeleteBridgePayload = DeleteBridgeSuccess + | DeleteBridgeInvalidNameError + | DeleteBridgeConflictError + | NotFoundError +type Chain { + id: ID! + enabled: Boolean! + config: String! + network: String! +} + +union ChainPayload = Chain | NotFoundError + +type ChainsPayload implements PaginatedPayload { + results: [Chain!]! + metadata: PaginationMetadata! +} +type ConfigV2Payload { + user: String! + effective: String! +} +type CSAKey { + id: ID! + publicKey: String! + version: Int! +} + +type CSAKeysPayload { + results: [CSAKey!]! +} + +type CreateCSAKeySuccess { + csaKey: CSAKey! +} + +type CSAKeyExistsError implements Error { + message: String! + code: ErrorCode! +} + +union CreateCSAKeyPayload = CreateCSAKeySuccess | CSAKeyExistsError + +type DeleteCSAKeySuccess { + csaKey: CSAKey! +} + +union DeleteCSAKeyPayload = DeleteCSAKeySuccess | NotFoundError +enum ErrorCode { + NOT_FOUND + INVALID_INPUT + UNPROCESSABLE +} + +interface Error { + message: String! + code: ErrorCode! +} + +type NotFoundError implements Error { + message: String! + code: ErrorCode! +} + +type InputError implements Error { + message: String! + code: ErrorCode! + path: String! + } + +type InputErrors { + errors: [InputError!]! +} +type EthKey { + address: String! + isDisabled: Boolean! + createdAt: Time! + updatedAt: Time! + chain: Chain! + ethBalance: String + linkBalance: String + maxGasPriceWei: String +} + +type EthKeysPayload { + results: [EthKey!]! +} +type EthTransaction { + state: String! + data: Bytes! + from: String! + to: String! + gasLimit: String! + value: String! + evmChainID: ID! + nonce: String + gasPrice: String! + hash: String! + hex: String! + sentAt: String + chain: Chain! + attempts: [EthTransactionAttempt!]! +} + +union EthTransactionPayload = EthTransaction | NotFoundError + +type EthTransactionsPayload implements PaginatedPayload { + results: [EthTransaction!]! + metadata: PaginationMetadata! +} +type EthTransactionAttempt { + gasPrice: String! + hash: String! + hex: String! + sentAt: String +} + +type EthTransactionAttemptsPayload implements PaginatedPayload { + results: [EthTransactionAttempt!]! + metadata: PaginationMetadata! +} +type Features { + csa: Boolean! + feedsManager: Boolean! + multiFeedsManagers: Boolean! +} + +# FeaturesPayload defines the response of fetching the features availability in the UI +union FeaturesPayload = Features +enum JobType { + FLUX_MONITOR + OCR + OCR2 +} + +type Plugins { + commit: Boolean! + execute: Boolean! + median: Boolean! + mercury: Boolean! + rebalancer: Boolean! +} + +type FeedsManager { + id: ID! + name: String! + uri: String! + publicKey: String! + jobProposals: [JobProposal!]! + isConnectionActive: Boolean! + createdAt: Time! + chainConfigs: [FeedsManagerChainConfig!]! +} + +type FeedsManagerChainConfig { + id: ID! + chainID: String! + chainType: String! + accountAddr: String! + accountAddrPubKey: String + adminAddr: String! + fluxMonitorJobConfig: FluxMonitorJobConfig! + ocr1JobConfig: OCR1JobConfig! + ocr2JobConfig: OCR2JobConfig! +} + +type FluxMonitorJobConfig { + enabled: Boolean! +} + +type OCR1JobConfig { + enabled: Boolean! + isBootstrap: Boolean! + multiaddr: String + p2pPeerID: String + keyBundleID: String +} + +type OCR2JobConfig { + enabled: Boolean! + isBootstrap: Boolean! + multiaddr: String + forwarderAddress: String + p2pPeerID: String + keyBundleID: String + plugins: Plugins! +} + +# FeedsManagerPayload defines the response to fetch a single feeds manager by id +union FeedsManagerPayload = FeedsManager | NotFoundError + +# FeedsManagersPayload defines the response when fetching feeds managers +type FeedsManagersPayload { + results: [FeedsManager!]! +} + +input CreateFeedsManagerInput { + name: String! + uri: String! + publicKey: String! +} + +# CreateFeedsManagerSuccess defines the success response when creating a feeds +# manager +type CreateFeedsManagerSuccess { + feedsManager: FeedsManager! +} + +type DuplicateFeedsManagerError implements Error { + message: String! + code: ErrorCode! +} + +# DEPRECATED: No longer used since we now support multiple feeds manager. +# Keeping this to avoid breaking change. +type SingleFeedsManagerError implements Error { + message: String! + code: ErrorCode! +} + +# CreateFeedsManagerPayload defines the response when creating a feeds manager +union CreateFeedsManagerPayload = CreateFeedsManagerSuccess + | DuplicateFeedsManagerError + | SingleFeedsManagerError # // TODO: delete once multiple feeds managers support is released + | NotFoundError + | InputErrors + +input UpdateFeedsManagerInput { + name: String! + uri: String! + publicKey: String! +} + +# UpdateFeedsManagerSuccess defines the success response when updating a feeds +# manager +type UpdateFeedsManagerSuccess { + feedsManager: FeedsManager! +} + +# UpdateFeedsManagerPayload defines the response when updating a feeds manager +union UpdateFeedsManagerPayload = UpdateFeedsManagerSuccess + | NotFoundError + | InputErrors + +input CreateFeedsManagerChainConfigInput { + feedsManagerID: ID! + chainID: String! + chainType: String! + accountAddr: String! + accountAddrPubKey: String + adminAddr: String! + fluxMonitorEnabled: Boolean! + ocr1Enabled: Boolean! + ocr1IsBootstrap: Boolean + ocr1Multiaddr: String + ocr1P2PPeerID: String + ocr1KeyBundleID: String + ocr2Enabled: Boolean! + ocr2IsBootstrap: Boolean + ocr2Multiaddr: String + ocr2ForwarderAddress: String + ocr2P2PPeerID: String + ocr2KeyBundleID: String + ocr2Plugins: String! +} + +# CreateFeedsManagerChainConfigSuccess defines the success response when +# creating a chain config for a feeds manager. +type CreateFeedsManagerChainConfigSuccess { + chainConfig: FeedsManagerChainConfig! +} + +# CreateFeedsManagerChainConfigPayload defines the response when creating a +# feeds manager chain config. +union CreateFeedsManagerChainConfigPayload = CreateFeedsManagerChainConfigSuccess + | NotFoundError + | InputErrors + +# DeleteFeedsManagerChainConfigSuccess defines the success response when +# deleting a chain config for a feeds manager. +type DeleteFeedsManagerChainConfigSuccess { + chainConfig: FeedsManagerChainConfig! +} + +# DeleteFeedsManagerChainConfigPayload defines the response when creating a +# feeds manager chain config. +union DeleteFeedsManagerChainConfigPayload = DeleteFeedsManagerChainConfigSuccess + | NotFoundError + +input UpdateFeedsManagerChainConfigInput { + accountAddr: String! + accountAddrPubKey: String + adminAddr: String! + fluxMonitorEnabled: Boolean! + ocr1Enabled: Boolean! + ocr1IsBootstrap: Boolean + ocr1Multiaddr: String + ocr1P2PPeerID: String + ocr1KeyBundleID: String + ocr2Enabled: Boolean! + ocr2IsBootstrap: Boolean + ocr2Multiaddr: String + ocr2ForwarderAddress: String + ocr2P2PPeerID: String + ocr2KeyBundleID: String + ocr2Plugins: String! +} + +# UpdateFeedsManagerChainConfigSuccess defines the success response when +# updating a chain config for a feeds manager. +type UpdateFeedsManagerChainConfigSuccess { + chainConfig: FeedsManagerChainConfig! +} + +# UpdateFeedsManagerChainConfigPayload defines the response when updating a +# feeds manager chain config. +union UpdateFeedsManagerChainConfigPayload = UpdateFeedsManagerChainConfigSuccess + | NotFoundError + | InputErrors +type Job { + id: ID! + name: String! + schemaVersion: Int! + gasLimit: Int + forwardingAllowed: Boolean + maxTaskDuration: String! + externalJobID: String! + type: String! + spec: JobSpec! + runs(offset: Int, limit: Int): JobRunsPayload! + observationSource: String! + errors: [JobError!]! + createdAt: Time! +} + +# JobsPayload defines the response when fetching a page of jobs +type JobsPayload implements PaginatedPayload { + results: [Job!]! + metadata: PaginationMetadata! +} + +# JobPayload defines the response when a job +union JobPayload = Job | NotFoundError + +input CreateJobInput { + TOML: String! +} + +type CreateJobSuccess { + job: Job! +} + +union CreateJobPayload = CreateJobSuccess | InputErrors + +type DeleteJobSuccess { + job: Job! +} + +union DeleteJobPayload = DeleteJobSuccess | NotFoundError +type JobError { + id: ID! + description: String! + occurrences: Int! + createdAt: Time! + updatedAt: Time! +} + +type DismissJobErrorSuccess { + jobError: JobError! +} + +union DismissJobErrorPayload = DismissJobErrorSuccess | NotFoundError +enum JobProposalStatus { + PENDING + APPROVED + REJECTED + CANCELLED + DELETED + REVOKED +} + +type JobProposal { + id: ID! + name: String + status: JobProposalStatus! + remoteUUID: String! + externalJobID: String + jobID: String + feedsManager: FeedsManager! + multiAddrs: [String!]! + pendingUpdate: Boolean! + specs: [JobProposalSpec!]! + latestSpec: JobProposalSpec! +} + +union JobProposalPayload = JobProposal | NotFoundError +enum SpecStatus { + UNKNOWN + PENDING + APPROVED + REJECTED + CANCELLED + REVOKED +} + +type JobProposalSpec { + id: ID! + definition: String! + version: Int! + status: SpecStatus! + statusUpdatedAt: Time! + createdAt: Time! + updatedAt: Time! +} + +type JobAlreadyExistsError implements Error { + message: String! + code: ErrorCode! +} + + +# ApproveJobProposalSpec + +type ApproveJobProposalSpecSuccess { + spec: JobProposalSpec! +} + +union ApproveJobProposalSpecPayload = ApproveJobProposalSpecSuccess | NotFoundError | JobAlreadyExistsError + +# CancelJobProposalSpec + +type CancelJobProposalSpecSuccess { + spec: JobProposalSpec! +} + +union CancelJobProposalSpecPayload = CancelJobProposalSpecSuccess | NotFoundError + + +# RejectJobProposalSpec + +type RejectJobProposalSpecSuccess { + spec: JobProposalSpec! +} + +union RejectJobProposalSpecPayload = RejectJobProposalSpecSuccess | NotFoundError + +# UpdateJobProposalSpec + +input UpdateJobProposalSpecDefinitionInput { + definition: String! +} + +type UpdateJobProposalSpecDefinitionSuccess { + spec: JobProposalSpec! +} + +union UpdateJobProposalSpecDefinitionPayload = UpdateJobProposalSpecDefinitionSuccess | NotFoundError +enum JobRunStatus { + UNKNOWN + RUNNING + SUSPENDED + ERRORED + COMPLETED +} + +type JobRun { + id: ID! + outputs: [String]! + allErrors: [String!]! + fatalErrors: [String!]! + inputs: String! + createdAt: Time! + finishedAt: Time + taskRuns: [TaskRun!]! + status: JobRunStatus! + job: Job! +} + +# JobRunsPayload defines the response when fetching a page of runs +type JobRunsPayload implements PaginatedPayload { + results: [JobRun!]! + metadata: PaginationMetadata! +} + +union JobRunPayload = JobRun | NotFoundError + +type RunJobSuccess { + jobRun: JobRun! +} + +type RunJobCannotRunError implements Error { + message: String! + code: ErrorCode! +} + +union RunJobPayload = RunJobSuccess | NotFoundError | RunJobCannotRunError +enum LogLevel { + DEBUG + INFO + WARN + ERROR +} + +type GlobalLogLevel { + level: LogLevel! +} + +union GlobalLogLevelPayload = GlobalLogLevel + +type LogLevelConfig { + keeper: LogLevel + headTracker: LogLevel + fluxMonitor: LogLevel +} + +input LogLevelConfigInput { + keeper: LogLevel + headTracker: LogLevel + fluxMonitor: LogLevel +} + +input SetServicesLogLevelsInput { + config: LogLevelConfigInput! +} + +type SetServicesLogLevelsSuccess { + config: LogLevelConfig! +} + +union SetServicesLogLevelsPayload = SetServicesLogLevelsSuccess | InputErrors + +type SQLLogging { + enabled: Boolean! +} + +input SetSQLLoggingInput { + enabled: Boolean! +} + +type SetSQLLoggingSuccess { + sqlLogging: SQLLogging! +} + +union SetSQLLoggingPayload = SetSQLLoggingSuccess + +union GetSQLLoggingPayload = SQLLogging + +type SetGlobalLogLevelSuccess { + globalLogLevel: GlobalLogLevel! +} + +union SetGlobalLogLevelPayload = SetGlobalLogLevelSuccess | InputErrors +type Node { + id: ID! + name: String! + wsURL: String! + httpURL: String! + chain: Chain! + state: String! + sendOnly: Boolean! + order: Int +} + +union NodePayload = Node | NotFoundError + +type NodesPayload implements PaginatedPayload { + results: [Node!]! + metadata: PaginationMetadata! +} +type OCRKeyBundle { + id: ID! + configPublicKey: String! + offChainPublicKey: String! + onChainSigningAddress: String! +} + +type OCRKeyBundlesPayload { + results: [OCRKeyBundle!]! +} + +type CreateOCRKeyBundleSuccess { + bundle: OCRKeyBundle! +} + +union CreateOCRKeyBundlePayload = CreateOCRKeyBundleSuccess + +type DeleteOCRKeyBundleSuccess { + bundle: OCRKeyBundle! +} + +union DeleteOCRKeyBundlePayload = DeleteOCRKeyBundleSuccess | NotFoundError +enum OCR2ChainType { + EVM + COSMOS + SOLANA + STARKNET + APTOS +} + +type OCR2KeyBundle { + id: ID! + chainType: OCR2ChainType + configPublicKey: String! + onChainPublicKey: String! + offChainPublicKey: String! +} + +type OCR2KeyBundlesPayload { + results: [OCR2KeyBundle!]! +} + +type CreateOCR2KeyBundleSuccess { + bundle: OCR2KeyBundle! +} + +union CreateOCR2KeyBundlePayload = CreateOCR2KeyBundleSuccess + +type DeleteOCR2KeyBundleSuccess { + bundle: OCR2KeyBundle! +} + +union DeleteOCR2KeyBundlePayload = DeleteOCR2KeyBundleSuccess | NotFoundError +type P2PKey { + id: ID! + peerID: String! + publicKey: String! +} + +type P2PKeysPayload { + results: [P2PKey!]! +} + +type CreateP2PKeySuccess { + p2pKey: P2PKey! +} + +union CreateP2PKeyPayload = CreateP2PKeySuccess + + +type DeleteP2PKeySuccess { + p2pKey: P2PKey! +} + +union DeleteP2PKeyPayload = DeleteP2PKeySuccess | NotFoundError +type PaginationMetadata { + total: Int! +} + +interface PaginatedPayload { + metadata: PaginationMetadata! +} +type SolanaKey { + id: ID! +} + +type SolanaKeysPayload { + results: [SolanaKey!]! +} +union JobSpec = + CronSpec | + DirectRequestSpec | + KeeperSpec | + FluxMonitorSpec | + OCRSpec | + OCR2Spec | + VRFSpec | + WebhookSpec | + BlockhashStoreSpec | + BlockHeaderFeederSpec | + BootstrapSpec | + GatewaySpec | + WorkflowSpec | + StandardCapabilitiesSpec + +type CronSpec { + schedule: String! + evmChainID: String + createdAt: Time! +} + +type DirectRequestSpec { + contractAddress: String! + createdAt: Time! + evmChainID: String + minIncomingConfirmations: Int! + minContractPaymentLinkJuels: String! + requesters: [String!] +} + +type FluxMonitorSpec { + absoluteThreshold: Float! + contractAddress: String! + createdAt: Time! + drumbeatEnabled: Boolean! + drumbeatRandomDelay: String + drumbeatSchedule: String + evmChainID: String + idleTimerDisabled: Boolean! + idleTimerPeriod: String! + minPayment: String + pollTimerDisabled: Boolean! + pollTimerPeriod: String! + threshold: Float! +} + +type KeeperSpec { + contractAddress: String! + createdAt: Time! + evmChainID: String + fromAddress: String +} + +type OCRSpec { + blockchainTimeout: String + contractAddress: String! + contractConfigConfirmations: Int + contractConfigTrackerPollInterval: String + contractConfigTrackerSubscribeInterval: String + createdAt: Time! + evmChainID: String + isBootstrapPeer: Boolean! + keyBundleID: String + observationTimeout: String + p2pv2Bootstrappers: [String!] + transmitterAddress: String + databaseTimeout: String! + observationGracePeriod: String! + contractTransmitterTransmitTimeout: String! +} + +type OCR2Spec { + blockchainTimeout: String + contractID: String! + contractConfigConfirmations: Int + contractConfigTrackerPollInterval: String + createdAt: Time! + ocrKeyBundleID: String + monitoringEndpoint: String + p2pv2Bootstrappers: [String!] + relay: String! + relayConfig: Map! + transmitterID: String + pluginType: String! + pluginConfig: Map! + feedID: String +} + +type VRFSpec { + coordinatorAddress: String! + createdAt: Time! + evmChainID: String + fromAddresses: [String!] + minIncomingConfirmations: Int! + pollPeriod: String! + publicKey: String! + requestedConfsDelay: Int! + requestTimeout: String! + batchCoordinatorAddress: String + batchFulfillmentEnabled: Boolean! + batchFulfillmentGasMultiplier: Float! + customRevertsPipelineEnabled: Boolean + chunkSize: Int! + backoffInitialDelay: String! + backoffMaxDelay: String! + gasLanePrice: String + vrfOwnerAddress: String +} + +type WebhookSpec { + createdAt: Time! +} + +type BlockhashStoreSpec { + coordinatorV1Address: String + coordinatorV2Address: String + coordinatorV2PlusAddress: String + waitBlocks: Int! + lookbackBlocks: Int! + blockhashStoreAddress: String! + trustedBlockhashStoreAddress: String + trustedBlockhashStoreBatchSize: Int! + heartbeatPeriod: String! + pollPeriod: String! + runTimeout: String! + evmChainID: String + fromAddresses: [String!] + createdAt: Time! +} + +type BlockHeaderFeederSpec { + coordinatorV1Address: String + coordinatorV2Address: String + coordinatorV2PlusAddress: String + waitBlocks: Int! + lookbackBlocks: Int! + blockhashStoreAddress: String! + batchBlockhashStoreAddress: String! + pollPeriod: String! + runTimeout: String! + evmChainID: String + getBlockhashesBatchSize: Int! + storeBlockhashesBatchSize: Int! + fromAddresses: [String!] + createdAt: Time! +} + +type BootstrapSpec { + id: ID! + contractID: String! + relay: String! + relayConfig: Map! + monitoringEndpoint: String + blockchainTimeout: String + contractConfigTrackerPollInterval: String + contractConfigConfirmations: Int + createdAt: Time! +} + +type GatewaySpec { + id: ID! + gatewayConfig: Map! + createdAt: Time! +} + +type WorkflowSpec { + id: ID! + workflowID: String! + workflow: String! + workflowOwner: String! + createdAt: Time! + updatedAt: Time! +} + +type StandardCapabilitiesSpec { + id: ID! + createdAt: Time! + command: String! + config: String +} +type TaskRun { + id: ID! + dotID: String! + type: String! + output: String! + error: String + createdAt: Time! + finishedAt: Time +} +type User { + email: String! + createdAt: Time! +} + +input UpdatePasswordInput { + oldPassword: String! + newPassword: String! +} + +type UpdatePasswordSuccess { + user: User! +} + +union UpdatePasswordPayload = UpdatePasswordSuccess | InputErrors +type VRFKey { + id: ID! + compressed: String! + uncompressed: String! + hash: String! +} + +type VRFKeySuccess { + key: VRFKey! +} + +union VRFKeyPayload = VRFKeySuccess | NotFoundError + +type VRFKeysPayload { + results: [VRFKey!]! +} + +type CreateVRFKeyPayload { + key: VRFKey! +} + +type DeleteVRFKeySuccess { + key: VRFKey! +} + +union DeleteVRFKeyPayload = DeleteVRFKeySuccess | NotFoundError diff --git a/integration-tests/web/sdk/main.go b/integration-tests/web/sdk/main.go new file mode 100644 index 00000000000..e2993ddb442 --- /dev/null +++ b/integration-tests/web/sdk/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "os" + + "github.com/Khan/genqlient/generate" + + "github.com/smartcontractkit/chainlink/v2/core/web/schema" +) + +func main() { + schema := schema.MustGetRootSchema() + + if err := os.WriteFile("./internal/schema.graphql", []byte(schema), 0600); err != nil { + fmt.Println(err) + os.Exit(1) + } + + generate.Main() +} diff --git a/integration-tests/web/sdk/taskfile.yml b/integration-tests/web/sdk/taskfile.yml new file mode 100644 index 00000000000..76cf0c9b42d --- /dev/null +++ b/integration-tests/web/sdk/taskfile.yml @@ -0,0 +1,6 @@ +version: '3' + +tasks: + generate: + cmds: + - go run main.go \ No newline at end of file diff --git a/integration-tests/wrappers/contract_caller.go b/integration-tests/wrappers/contract_caller.go index 0eea760e024..14170c7deeb 100644 --- a/integration-tests/wrappers/contract_caller.go +++ b/integration-tests/wrappers/contract_caller.go @@ -16,10 +16,9 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/seth" evmClient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) diff --git a/main_test.go b/main_test.go index 81e056e3b84..419a4af0517 100644 --- a/main_test.go +++ b/main_test.go @@ -42,6 +42,10 @@ func TestMain(m *testing.M) { })) } +// TestScripts walks through the testdata/scripts directory and runs all tests that end in +// .txt or .txtar with the testscripts library. To run an individual test, specify it in the +// -run param of go test without the txtar or txt suffix, like so: +// go test . -run TestScripts/node/validate/default func TestScripts(t *testing.T) { if testing.Short() { t.Skip("skipping testscript") diff --git a/nix-darwin-shell-hook.sh b/nix-darwin-shell-hook.sh new file mode 100755 index 00000000000..49dbfc60983 --- /dev/null +++ b/nix-darwin-shell-hook.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# This script is used to set up cross compilation to linux arm64 in a CRIB environment. +# It's loaded during the shell hook execution in shell.nix +main() { + echo "Running in CRIB environment, setting up cross compilation to linux arm64..." + PACKAGE="aarch64-unknown-linux-gnu" + + if ! command -v brew >/dev/null 2>&1; then + echo -e "\e[31mHomebrew is not installed. Please install Homebrew first: https://brew.sh/\e[0m" + exit 1 + fi + + if ! brew list --formula | grep $PACKAGE > /dev/null; then + echo -e "\e[31mThe Homebrew package $PACKAGE is not installed.\e[0m" + echo -e "\e[31mPlease install it by running: brew tap messense/macos-cross-toolchains && brew install ${PACKAGE}\e[0m" + exit 1 + fi + + export GOOS=linux + + installed_version=$(brew list --versions $PACKAGE | awk '{print $2}') + path_prefix=$(brew --prefix) + bin_path=$path_prefix/Cellar/$PACKAGE/$installed_version/bin + + export CC=$bin_path/aarch64-linux-gnu-gcc + export CXX=$bin_path/aarch64-linux-gnu-g++ +} + +main "$@" diff --git a/operator_ui/TAG b/operator_ui/TAG index bd6882b0f5c..e935f83635e 100644 --- a/operator_ui/TAG +++ b/operator_ui/TAG @@ -1 +1 @@ -v0.8.0-094d250 +v0.8.0-352091e diff --git a/package.json b/package.json index 18171178bc4..0382ca4e5cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.15.0", + "version": "2.17.0", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { @@ -24,6 +24,6 @@ "devDependencies": { "@changesets/changelog-github": "^0.4.8", "@changesets/cli": "~2.26.2", - "semver": "^7.6.1" + "semver": "^7.6.3" } -} +} \ No newline at end of file diff --git a/plugins/cmd/capabilities/log-event-trigger/main.go b/plugins/cmd/capabilities/log-event-trigger/main.go new file mode 100644 index 00000000000..d01485a743f --- /dev/null +++ b/plugins/cmd/capabilities/log-event-trigger/main.go @@ -0,0 +1,128 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/hashicorp/go-plugin" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/triggers/logevent" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" +) + +const ( + serviceName = "LogEventTriggerCapability" +) + +type LogEventTriggerGRPCService struct { + triggerService *logevent.TriggerService + s *loop.Server + config logevent.Config +} + +func main() { + s := loop.MustNewStartedServer(serviceName) + defer s.Stop() + + s.Logger.Infof("Starting %s", serviceName) + + stopCh := make(chan struct{}) + defer close(stopCh) + + plugin.Serve(&plugin.ServeConfig{ + HandshakeConfig: loop.StandardCapabilitiesHandshakeConfig(), + Plugins: map[string]plugin.Plugin{ + loop.PluginStandardCapabilitiesName: &loop.StandardCapabilitiesLoop{ + PluginServer: &LogEventTriggerGRPCService{ + s: s, + }, + BrokerConfig: loop.BrokerConfig{Logger: s.Logger, StopCh: stopCh, GRPCOpts: s.GRPCOpts}, + }, + }, + GRPCServer: s.GRPCOpts.NewServer, + }) +} + +func (cs *LogEventTriggerGRPCService) Start(ctx context.Context) error { + return nil +} + +func (cs *LogEventTriggerGRPCService) Close() error { + err := cs.triggerService.Close() + if err != nil { + return fmt.Errorf("error closing trigger service for chainID %s: %w", cs.config.ChainID, err) + } + return nil +} + +func (cs *LogEventTriggerGRPCService) Ready() error { + return nil +} + +func (cs *LogEventTriggerGRPCService) HealthReport() map[string]error { + return nil +} + +func (cs *LogEventTriggerGRPCService) Name() string { + return serviceName +} + +func (cs *LogEventTriggerGRPCService) Infos(ctx context.Context) ([]capabilities.CapabilityInfo, error) { + triggerInfo, err := cs.triggerService.Info(ctx) + if err != nil { + return nil, err + } + + return []capabilities.CapabilityInfo{ + triggerInfo, + }, nil +} + +func (cs *LogEventTriggerGRPCService) Initialise( + ctx context.Context, + config string, + telemetryService core.TelemetryService, + store core.KeyValueStore, + capabilityRegistry core.CapabilitiesRegistry, + errorLog core.ErrorLog, + pipelineRunner core.PipelineRunnerService, + relayerSet core.RelayerSet, + oracleFactory core.OracleFactory, +) error { + cs.s.Logger.Debugf("Initialising %s", serviceName) + + var logEventConfig logevent.Config + err := json.Unmarshal([]byte(config), &logEventConfig) + if err != nil { + return fmt.Errorf("error decoding log_event_trigger config: %w", err) + } + + relayID := types.NewRelayID(logEventConfig.Network, logEventConfig.ChainID) + relayer, err := relayerSet.Get(ctx, relayID) + if err != nil { + return fmt.Errorf("error fetching relayer for chainID %s from relayerSet: %w", logEventConfig.ChainID, err) + } + + // Set relayer and trigger in LogEventTriggerGRPCService + cs.config = logEventConfig + triggerService, err := logevent.NewTriggerService(ctx, cs.s.Logger, relayer, logEventConfig) + if err != nil { + return fmt.Errorf("error creating trigger service for chainID %s: %w", logEventConfig.ChainID, err) + } + err = triggerService.Start(ctx) + if err != nil { + return fmt.Errorf("error starting trigger service for chainID %s: %w", logEventConfig.ChainID, err) + } + cs.triggerService = triggerService + + if err := capabilityRegistry.Add(ctx, cs.triggerService); err != nil { + return fmt.Errorf("error when adding cron trigger to the registry: %w", err) + } + + return nil +} diff --git a/plugins/cmd/chainlink-ocr3-capability/main.go b/plugins/cmd/chainlink-ocr3-capability/main.go index c70a5a6f2ad..fad82c7b73b 100644 --- a/plugins/cmd/chainlink-ocr3-capability/main.go +++ b/plugins/cmd/chainlink-ocr3-capability/main.go @@ -11,7 +11,6 @@ import ( ocr3rp "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) const ( @@ -24,7 +23,7 @@ func main() { c := ocr3.Config{ Logger: s.Logger, - EncoderFactory: evm.NewEVMEncoder, + EncoderFactory: capabilities.NewEncoder, AggregatorFactory: capabilities.NewAggregator, } p := ocr3.NewOCR3(c) diff --git a/plugins/loop_registry.go b/plugins/loop_registry.go index b796ddf87ee..51c6310ffa7 100644 --- a/plugins/loop_registry.go +++ b/plugins/loop_registry.go @@ -27,15 +27,17 @@ type LoopRegistry struct { mu sync.Mutex registry map[string]*RegisteredLoop - lggr logger.Logger - cfgTracing config.Tracing + lggr logger.Logger + cfgTracing config.Tracing + cfgTelemetry config.Telemetry } -func NewLoopRegistry(lggr logger.Logger, tracingConfig config.Tracing) *LoopRegistry { +func NewLoopRegistry(lggr logger.Logger, tracing config.Tracing, telemetry config.Telemetry) *LoopRegistry { return &LoopRegistry{ - registry: map[string]*RegisteredLoop{}, - lggr: logger.Named(lggr, "LoopRegistry"), - cfgTracing: tracingConfig, + registry: map[string]*RegisteredLoop{}, + lggr: logger.Named(lggr, "LoopRegistry"), + cfgTracing: tracing, + cfgTelemetry: telemetry, } } @@ -65,6 +67,15 @@ func (m *LoopRegistry) Register(id string) (*RegisteredLoop, error) { envCfg.TracingAttributes = m.cfgTracing.Attributes() } + if m.cfgTelemetry != nil { + envCfg.TelemetryEnabled = m.cfgTelemetry.Enabled() + envCfg.TelemetryEndpoint = m.cfgTelemetry.OtelExporterGRPCEndpoint() + envCfg.TelemetryInsecureConnection = m.cfgTelemetry.InsecureConnection() + envCfg.TelemetryCACertFile = m.cfgTelemetry.CACertFile() + envCfg.TelemetryAttributes = m.cfgTelemetry.ResourceAttributes() + envCfg.TelemetryTraceSampleRatio = m.cfgTelemetry.TraceSampleRatio() + } + m.registry[id] = &RegisteredLoop{Name: id, EnvCfg: envCfg} m.lggr.Debugf("Registered loopp %q with config %v, port %d", id, envCfg, envCfg.PrometheusPort) return m.registry[id], nil diff --git a/plugins/loop_registry_test.go b/plugins/loop_registry_test.go index b307469e09b..84b6b0cefc9 100644 --- a/plugins/loop_registry_test.go +++ b/plugins/loop_registry_test.go @@ -5,12 +5,13 @@ import ( "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestPluginPortManager(t *testing.T) { // register one - m := NewLoopRegistry(logger.TestLogger(t), nil) + m := NewLoopRegistry(logger.TestLogger(t), nil, nil) pFoo, err := m.Register("foo") require.NoError(t, err) require.Equal(t, "foo", pFoo.Name) @@ -26,37 +27,63 @@ func TestPluginPortManager(t *testing.T) { require.Equal(t, pFoo.EnvCfg.PrometheusPort+1, pBar.EnvCfg.PrometheusPort) } -// Mock tracing config -type MockCfgTracing struct{} +type mockCfgTracing struct{} -func (m *MockCfgTracing) Attributes() map[string]string { +func (m *mockCfgTracing) Attributes() map[string]string { return map[string]string{"attribute": "value"} } -func (m *MockCfgTracing) Enabled() bool { return true } -func (m *MockCfgTracing) NodeID() string { return "" } -func (m *MockCfgTracing) CollectorTarget() string { return "http://localhost:9000" } -func (m *MockCfgTracing) SamplingRatio() float64 { return 0.1 } -func (m *MockCfgTracing) TLSCertPath() string { return "/path/to/cert.pem" } -func (m *MockCfgTracing) Mode() string { return "tls" } +func (m *mockCfgTracing) Enabled() bool { return true } +func (m *mockCfgTracing) NodeID() string { return "" } +func (m *mockCfgTracing) CollectorTarget() string { return "http://localhost:9000" } +func (m *mockCfgTracing) SamplingRatio() float64 { return 0.1 } +func (m *mockCfgTracing) TLSCertPath() string { return "/path/to/cert.pem" } +func (m *mockCfgTracing) Mode() string { return "tls" } + +type mockCfgTelemetry struct{} + +func (m mockCfgTelemetry) Enabled() bool { return true } + +func (m mockCfgTelemetry) InsecureConnection() bool { return true } + +func (m mockCfgTelemetry) CACertFile() string { return "path/to/cert.pem" } + +func (m mockCfgTelemetry) OtelExporterGRPCEndpoint() string { return "http://localhost:9001" } + +func (m mockCfgTelemetry) ResourceAttributes() map[string]string { + return map[string]string{"foo": "bar"} +} + +func (m mockCfgTelemetry) TraceSampleRatio() float64 { return 0.42 } func TestLoopRegistry_Register(t *testing.T) { - mockCfgTracing := &MockCfgTracing{} + mockCfgTracing := &mockCfgTracing{} + mockCfgTelemetry := &mockCfgTelemetry{} registry := make(map[string]*RegisteredLoop) // Create a LoopRegistry instance with mockCfgTracing loopRegistry := &LoopRegistry{ - lggr: logger.TestLogger(t), - registry: registry, - cfgTracing: mockCfgTracing, + lggr: logger.TestLogger(t), + registry: registry, + cfgTracing: mockCfgTracing, + cfgTelemetry: mockCfgTelemetry, } // Test case 1: Register new loop registeredLoop, err := loopRegistry.Register("testID") require.Nil(t, err) require.Equal(t, "testID", registeredLoop.Name) - require.True(t, registeredLoop.EnvCfg.TracingEnabled) - require.Equal(t, "http://localhost:9000", registeredLoop.EnvCfg.TracingCollectorTarget) - require.Equal(t, map[string]string{"attribute": "value"}, registeredLoop.EnvCfg.TracingAttributes) - require.Equal(t, 0.1, registeredLoop.EnvCfg.TracingSamplingRatio) - require.Equal(t, "/path/to/cert.pem", registeredLoop.EnvCfg.TracingTLSCertPath) + + envCfg := registeredLoop.EnvCfg + require.True(t, envCfg.TracingEnabled) + require.Equal(t, "http://localhost:9000", envCfg.TracingCollectorTarget) + require.Equal(t, map[string]string{"attribute": "value"}, envCfg.TracingAttributes) + require.Equal(t, 0.1, envCfg.TracingSamplingRatio) + require.Equal(t, "/path/to/cert.pem", envCfg.TracingTLSCertPath) + + require.True(t, envCfg.TelemetryEnabled) + require.True(t, envCfg.TelemetryInsecureConnection) + require.Equal(t, "path/to/cert.pem", envCfg.TelemetryCACertFile) + require.Equal(t, "http://localhost:9001", envCfg.TelemetryEndpoint) + require.Equal(t, loop.OtelAttributes{"foo": "bar"}, envCfg.TelemetryAttributes) + require.Equal(t, 0.42, envCfg.TelemetryTraceSampleRatio) } diff --git a/plugins/medianpoc/plugin.go b/plugins/medianpoc/plugin.go index 41580afe499..e6ada1bec84 100644 --- a/plugins/medianpoc/plugin.go +++ b/plugins/medianpoc/plugin.go @@ -40,7 +40,7 @@ func (e *PipelineNotFoundError) Error() string { } func (p *Plugin) NewValidationService(ctx context.Context) (core.ValidationService, error) { - s := &reportingPluginValidationService{lggr: p.Logger} + s := &reportingPluginValidationService{Service: services.Config{Name: "ValidationService"}.NewService(p.Logger)} p.SubService(s) return s, nil } @@ -81,7 +81,10 @@ func (p *Plugin) NewReportingPluginFactory( if err != nil { return nil, err } - s := &reportingPluginFactoryService{lggr: p.Logger, ReportingPluginFactory: f} + s := &reportingPluginFactoryService{ + Service: services.Config{Name: "ReportingPluginFactory"}.NewService(p.Logger), + ReportingPluginFactory: f, + } p.SubService(s) return s, nil } @@ -157,28 +160,12 @@ func (p *Plugin) newFactory(ctx context.Context, config core.ReportingPluginServ } type reportingPluginFactoryService struct { - services.StateMachine - lggr logger.Logger + services.Service ocrtypes.ReportingPluginFactory } -func (r *reportingPluginFactoryService) Name() string { return r.lggr.Name() } - -func (r *reportingPluginFactoryService) Start(ctx context.Context) error { - return r.StartOnce("ReportingPluginFactory", func() error { return nil }) -} - -func (r *reportingPluginFactoryService) Close() error { - return r.StopOnce("ReportingPluginFactory", func() error { return nil }) -} - -func (r *reportingPluginFactoryService) HealthReport() map[string]error { - return map[string]error{r.Name(): r.Healthy()} -} - type reportingPluginValidationService struct { - services.StateMachine - lggr logger.Logger + services.Service } func (r *reportingPluginValidationService) ValidateConfig(ctx context.Context, config map[string]interface{}) error { @@ -196,16 +183,3 @@ func (r *reportingPluginValidationService) ValidateConfig(ctx context.Context, c return nil } -func (r *reportingPluginValidationService) Name() string { return r.lggr.Name() } - -func (r *reportingPluginValidationService) Start(ctx context.Context) error { - return r.StartOnce("ValidationService", func() error { return nil }) -} - -func (r *reportingPluginValidationService) Close() error { - return r.StopOnce("ValidationService", func() error { return nil }) -} - -func (r *reportingPluginValidationService) HealthReport() map[string]error { - return map[string]error{r.Name(): r.Healthy()} -} diff --git a/plugins/medianpoc/plugin_test.go b/plugins/medianpoc/plugin_test.go index 22e4c095d6c..d2d17db32a8 100644 --- a/plugins/medianpoc/plugin_test.go +++ b/plugins/medianpoc/plugin_test.go @@ -73,7 +73,7 @@ func (p provider) OnchainConfigCodec() median.OnchainConfigCodec { return mockOnchainConfigCodec{} } -func (p provider) ChainReader() types.ContractReader { +func (p provider) ContractReader() types.ContractReader { return nil } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95d247d9937..260e6c79c07 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,25 +15,25 @@ importers: specifier: ~2.26.2 version: 2.26.2 semver: - specifier: ^7.6.1 - version: 7.6.1 + specifier: ^7.6.3 + version: 7.6.3 packages: - '@babel/code-frame@7.23.5': - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.23.4': - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.23.9': - resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} + '@babel/runtime@7.25.6': + resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} engines: {node: '>=6.9.0'} '@changesets/apply-release-plan@6.1.4': @@ -174,8 +174,8 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} breakword@1.0.6: @@ -248,6 +248,18 @@ packages: resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} engines: {node: '>= 0.1.90'} + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} @@ -292,8 +304,8 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.22.4: - resolution: {integrity: sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==} + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} es-define-property@1.0.0: @@ -304,6 +316,10 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.3: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} @@ -315,8 +331,8 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} escape-string-regexp@1.0.5: @@ -342,8 +358,8 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-up@4.1.0: @@ -394,8 +410,8 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} globby@11.1.0: @@ -441,8 +457,8 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.1: - resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} hosted-git-info@2.8.9: @@ -455,8 +471,8 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} indent-string@4.0.0: @@ -489,8 +505,13 @@ packages: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true - is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -619,8 +640,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} min-indent@1.0.1: @@ -647,8 +668,9 @@ packages: normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -708,6 +730,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -724,8 +749,8 @@ packages: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} - preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} + preferred-pm@3.1.4: + resolution: {integrity: sha512-lEHd+yEm22jXdCphDrkvIJQU66EuLojPPtvZkpKIkiD+l0DMThF/niqZKJSoU8Vl7iuvtmzyMhir9LdVy5WMnA==} engines: {node: '>=10'} prettier@2.8.8: @@ -788,8 +813,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - safe-array-concat@1.1.0: - resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} engines: {node: '>=0.4'} safe-regex-test@1.0.3: @@ -803,16 +828,16 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - semver@7.6.1: - resolution: {integrity: sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==} + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.2.1: - resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} set-function-name@2.0.2: @@ -827,8 +852,8 @@ packages: resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} engines: {node: '>=0.10.0'} - side-channel@1.0.5: - resolution: {integrity: sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==} + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} signal-exit@3.0.7: @@ -855,8 +880,8 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + spdx-license-ids@3.0.20: + resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -868,15 +893,16 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} engines: {node: '>= 0.4'} - string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} @@ -950,8 +976,8 @@ packages: resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} engines: {node: '>= 0.4'} - typed-array-length@1.0.5: - resolution: {integrity: sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==} + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} unbox-primitive@1.0.2: @@ -979,12 +1005,12 @@ packages: which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + which-pm@2.2.0: + resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} - which-typed-array@1.1.14: - resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} which@1.3.1: @@ -1031,26 +1057,27 @@ packages: snapshots: - '@babel/code-frame@7.23.5': + '@babel/code-frame@7.24.7': dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 + '@babel/highlight': 7.24.7 + picocolors: 1.1.0 - '@babel/helper-validator-identifier@7.22.20': {} + '@babel/helper-validator-identifier@7.24.7': {} - '@babel/highlight@7.23.4': + '@babel/highlight@7.24.7': dependencies: - '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 + picocolors: 1.1.0 - '@babel/runtime@7.23.9': + '@babel/runtime@7.25.6': dependencies: regenerator-runtime: 0.14.1 '@changesets/apply-release-plan@6.1.4': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/config': 2.3.1 '@changesets/get-version-range-type': 0.3.2 '@changesets/git': 2.0.0 @@ -1062,16 +1089,16 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.6.1 + semver: 7.6.3 '@changesets/assemble-release-plan@5.2.4': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/errors': 0.1.4 '@changesets/get-dependents-graph': 1.3.6 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 - semver: 7.6.1 + semver: 7.6.3 '@changesets/changelog-git@0.1.14': dependencies: @@ -1087,7 +1114,7 @@ snapshots: '@changesets/cli@2.26.2': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/apply-release-plan': 6.1.4 '@changesets/assemble-release-plan': 5.2.4 '@changesets/changelog-git': 0.1.14 @@ -1114,9 +1141,9 @@ snapshots: meow: 6.1.1 outdent: 0.5.0 p-limit: 2.3.0 - preferred-pm: 3.1.3 + preferred-pm: 3.1.4 resolve-from: 5.0.0 - semver: 7.6.1 + semver: 7.6.3 spawndamnit: 2.0.0 term-size: 2.2.1 tty-table: 4.2.3 @@ -1129,7 +1156,7 @@ snapshots: '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - micromatch: 4.0.5 + micromatch: 4.0.8 '@changesets/errors@0.1.4': dependencies: @@ -1141,7 +1168,7 @@ snapshots: '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 - semver: 7.6.1 + semver: 7.6.3 '@changesets/get-github-info@0.5.2': dependencies: @@ -1152,7 +1179,7 @@ snapshots: '@changesets/get-release-plan@3.0.17': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/assemble-release-plan': 5.2.4 '@changesets/config': 2.3.1 '@changesets/pre': 1.0.14 @@ -1164,12 +1191,12 @@ snapshots: '@changesets/git@2.0.0': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 is-subdir: 1.2.0 - micromatch: 4.0.5 + micromatch: 4.0.8 spawndamnit: 2.0.0 '@changesets/logger@0.0.5': @@ -1183,7 +1210,7 @@ snapshots: '@changesets/pre@1.0.14': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -1191,7 +1218,7 @@ snapshots: '@changesets/read@0.5.9': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/git': 2.0.0 '@changesets/logger': 0.0.5 '@changesets/parse': 0.3.16 @@ -1206,7 +1233,7 @@ snapshots: '@changesets/write@0.2.3': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 @@ -1214,14 +1241,14 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.23.9 + '@babel/runtime': 7.25.6 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -1279,7 +1306,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.4 + es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 arraybuffer.prototype.slice@1.0.3: @@ -1287,7 +1314,7 @@ snapshots: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.4 + es-abstract: 1.23.3 es-errors: 1.3.0 get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 @@ -1303,9 +1330,9 @@ snapshots: dependencies: is-windows: 1.0.2 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 breakword@1.0.6: dependencies: @@ -1317,7 +1344,7 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 get-intrinsic: 1.2.4 - set-function-length: 1.2.1 + set-function-length: 1.2.2 camelcase-keys@6.2.2: dependencies: @@ -1387,6 +1414,24 @@ snapshots: csv-stringify: 5.6.5 stream-transform: 2.1.3 + data-view-buffer@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-offset@1.0.0: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dataloader@1.4.0: {} decamelize-keys@1.1.1: @@ -1431,49 +1476,54 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.22.4: + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 available-typed-arrays: 1.0.7 call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 es-define-property: 1.0.0 es-errors: 1.3.0 + es-object-atoms: 1.0.0 es-set-tostringtag: 2.0.3 es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 get-intrinsic: 1.2.4 get-symbol-description: 1.0.2 - globalthis: 1.0.3 + globalthis: 1.0.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 has-proto: 1.0.3 has-symbols: 1.0.3 - hasown: 2.0.1 + hasown: 2.0.2 internal-slot: 1.0.7 is-array-buffer: 3.0.4 is-callable: 1.2.7 + is-data-view: 1.0.1 is-negative-zero: 2.0.3 is-regex: 1.1.4 is-shared-array-buffer: 1.0.3 is-string: 1.0.7 is-typed-array: 1.1.13 is-weakref: 1.0.2 - object-inspect: 1.13.1 + object-inspect: 1.13.2 object-keys: 1.1.1 object.assign: 4.1.5 regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.0 + safe-array-concat: 1.1.2 safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.2 typed-array-byte-length: 1.0.1 typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.5 + typed-array-length: 1.0.6 unbox-primitive: 1.0.2 - which-typed-array: 1.1.14 + which-typed-array: 1.1.15 es-define-property@1.0.0: dependencies: @@ -1481,15 +1531,19 @@ snapshots: es-errors@1.3.0: {} + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + es-set-tostringtag@2.0.3: dependencies: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 - hasown: 2.0.1 + hasown: 2.0.2 es-shim-unscopables@1.0.2: dependencies: - hasown: 2.0.1 + hasown: 2.0.2 es-to-primitive@1.2.1: dependencies: @@ -1497,7 +1551,7 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 - escalade@3.1.2: {} + escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -1517,13 +1571,13 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fastq@1.17.1: dependencies: reusify: 1.0.4 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1539,7 +1593,7 @@ snapshots: find-yarn-workspace-root2@1.2.16: dependencies: - micromatch: 4.0.5 + micromatch: 4.0.8 pkg-dir: 4.2.0 for-each@0.3.3: @@ -1564,7 +1618,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.4 + es-abstract: 1.23.3 functions-have-names: 1.2.3 functions-have-names@1.2.3: {} @@ -1577,7 +1631,7 @@ snapshots: function-bind: 1.1.2 has-proto: 1.0.3 has-symbols: 1.0.3 - hasown: 2.0.1 + hasown: 2.0.2 get-symbol-description@1.0.2: dependencies: @@ -1589,16 +1643,17 @@ snapshots: dependencies: is-glob: 4.0.3 - globalthis@1.0.3: + globalthis@1.0.4: dependencies: define-properties: 1.2.1 + gopd: 1.0.1 globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.1 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -1630,7 +1685,7 @@ snapshots: dependencies: has-symbols: 1.0.3 - hasown@2.0.1: + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -1642,15 +1697,15 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ignore@5.3.1: {} + ignore@5.3.2: {} indent-string@4.0.0: {} internal-slot@1.0.7: dependencies: es-errors: 1.3.0 - hasown: 2.0.1 - side-channel: 1.0.5 + hasown: 2.0.2 + side-channel: 1.0.6 is-array-buffer@3.0.4: dependencies: @@ -1674,9 +1729,13 @@ snapshots: dependencies: ci-info: 3.9.0 - is-core-module@2.13.1: + is-core-module@2.15.1: dependencies: - hasown: 2.0.1 + hasown: 2.0.2 + + is-data-view@1.0.1: + dependencies: + is-typed-array: 1.1.13 is-date-object@1.0.5: dependencies: @@ -1723,7 +1782,7 @@ snapshots: is-typed-array@1.1.13: dependencies: - which-typed-array: 1.1.14 + which-typed-array: 1.1.15 is-weakref@1.0.2: dependencies: @@ -1796,9 +1855,9 @@ snapshots: merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.8: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 min-indent@1.0.1: {} @@ -1822,7 +1881,7 @@ snapshots: semver: 5.7.2 validate-npm-package-license: 3.0.4 - object-inspect@1.13.1: {} + object-inspect@1.13.2: {} object-keys@1.1.1: {} @@ -1863,7 +1922,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -1874,6 +1933,8 @@ snapshots: path-type@4.0.0: {} + picocolors@1.1.0: {} + picomatch@2.3.1: {} pify@4.0.1: {} @@ -1884,12 +1945,12 @@ snapshots: possible-typed-array-names@1.0.0: {} - preferred-pm@3.1.3: + preferred-pm@3.1.4: dependencies: find-up: 5.0.0 find-yarn-workspace-root2: 1.2.16 path-exists: 4.0.0 - which-pm: 2.0.0 + which-pm: 2.2.0 prettier@2.8.8: {} @@ -1941,7 +2002,7 @@ snapshots: resolve@1.22.8: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -1951,7 +2012,7 @@ snapshots: dependencies: queue-microtask: 1.2.3 - safe-array-concat@1.1.0: + safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 @@ -1968,11 +2029,11 @@ snapshots: semver@5.7.2: {} - semver@7.6.1: {} + semver@7.6.3: {} set-blocking@2.0.0: {} - set-function-length@1.2.1: + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 @@ -1994,12 +2055,12 @@ snapshots: shebang-regex@1.0.0: {} - side-channel@1.0.5: + side-channel@1.0.6: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - object-inspect: 1.13.1 + object-inspect: 1.13.2 signal-exit@3.0.7: {} @@ -2022,16 +2083,16 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 + spdx-license-ids: 3.0.20 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 + spdx-license-ids: 3.0.20 - spdx-license-ids@3.0.17: {} + spdx-license-ids@3.0.20: {} sprintf-js@1.0.3: {} @@ -2045,23 +2106,24 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string.prototype.trim@1.2.8: + string.prototype.trim@1.2.9: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.4 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 - string.prototype.trimend@1.0.7: + string.prototype.trimend@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.4 + es-object-atoms: 1.0.0 - string.prototype.trimstart@1.0.7: + string.prototype.trimstart@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.4 + es-object-atoms: 1.0.0 strip-ansi@6.0.1: dependencies: @@ -2136,7 +2198,7 @@ snapshots: has-proto: 1.0.3 is-typed-array: 1.1.13 - typed-array-length@1.0.5: + typed-array-length@1.0.6: dependencies: call-bind: 1.0.7 for-each: 0.3.3 @@ -2180,12 +2242,12 @@ snapshots: which-module@2.0.1: {} - which-pm@2.0.0: + which-pm@2.2.0: dependencies: load-yaml-file: 0.2.0 path-exists: 4.0.0 - which-typed-array@1.1.14: + which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -2239,7 +2301,7 @@ snapshots: yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.2 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 diff --git a/shell.nix b/shell.nix index 3626cb11cf4..e3b187dcd96 100644 --- a/shell.nix +++ b/shell.nix @@ -1,4 +1,4 @@ -{pkgs}: +{pkgs, isCrib}: with pkgs; let go = go_1_21; postgresql = postgresql_14; @@ -18,7 +18,6 @@ in nativeBuildInputs = [ go - goreleaser postgresql python3 @@ -44,9 +43,6 @@ in github-cli jq - # cross-compiling, used in CRIB - zig - # gofuzz ] ++ lib.optionals stdenv.isLinux [ @@ -54,10 +50,22 @@ in pkg-config libudev-zero libusb1 + ] ++ lib.optionals isCrib [ + nur.repos.goreleaser.goreleaser-pro + patchelf ]; - LD_LIBRARY_PATH = "${stdenv.cc.cc.lib}/lib64:$LD_LIBRARY_PATH"; - GOROOT = "${go}/share/go"; + shellHook = '' + ${if !isCrib then "" else '' + if [ -z $GORELEASER_KEY ]; then + 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 ""} + ''} + ''; + + GOROOT = "${go}/share/go"; PGDATA = "db"; CL_DATABASE_URL = "postgresql://chainlink:chainlink@localhost:5432/chainlink_test?sslmode=disable"; } diff --git a/sonar-project.properties b/sonar-project.properties index b0e773b1048..1df8dbfa5bf 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -12,6 +12,7 @@ sonar.exclusions=\ **/contracts/artifacts/**/*,\ **/contracts/cache/**/*,\ **/contracts/scripts/**/*,\ +**/contracts/tsconfig.json,\ **/generated/**/*,\ **/fixtures/**/*,\ **/testutils/**/*,\ @@ -20,6 +21,7 @@ sonar.exclusions=\ **/testconfig/**/*,\ **/core/web/assets/**/*,\ **/core/scripts/**/*,\ +**/core/**/logger/**/colortest/**/*,\ **/docs/**/*,\ **/tools/**/*,\ **/fuzz/**/*,\ @@ -32,7 +34,9 @@ sonar.exclusions=\ **/*_codecgen.go,\ **/*_gen.go,\ **/tsconfig.json,\ -**/debug.go +**/delete-deployments/tsconfig.json,\ +**/debug.go,\ +**/mock_*.go # Coverage exclusions sonar.coverage.exclusions=\ @@ -42,7 +46,9 @@ sonar.coverage.exclusions=\ **/contracts/**/tests/**/*,\ **/core/**/cltest/**/*,\ **/integration-tests/**/*,\ +**/*integration_tests/**/*,\ **/plugins/**/*,\ +**/capabilities/**/*test/**/*,\ **/main.go,\ **/0195_add_not_null_to_evm_chain_id_in_job_specs.go @@ -56,16 +62,16 @@ sonar.cpd.exclusions=\ **/core/services/ocr2/plugins/mercury/plugin.go,\ **/integration-tests/load/**/*,\ **/integration-tests/contracts/ethereum_keeper_contracts.go,\ -integration-tests/contracts/ethereum_contracts_seth.go,\ -integration-tests/contracts/ethereum_contracts_seth.go,\ -integration-tests/actions/seth/actions.go,\ -dashboard-lib/** +**/integration-tests/contracts/ethereum_contracts_seth.go,\ +**/integration-tests/actions/seth/actions.go,\ +**/dashboard-lib/** # Tests' root folder, inclusions (tests to check and count) and exclusions sonar.tests=. sonar.test.inclusions=\ **/*_test.go,\ **/*.test.ts + sonar.test.exclusions=\ **/integration-tests/**/*,\ **/charts/chainlink-cluster/dashboard/cmd/**/* \ No newline at end of file diff --git a/testdata/scripts/health/default.txtar b/testdata/scripts/health/default.txtar index 777d3e5e126..a7db2308e35 100644 --- a/testdata/scripts/health/default.txtar +++ b/testdata/scripts/health/default.txtar @@ -39,6 +39,7 @@ ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache +ok RetirementReportCache ok TelemetryManager -- out.json -- @@ -116,6 +117,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "RetirementReportCache", + "attributes": { + "name": "RetirementReportCache", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "TelemetryManager", diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar index bba3b3e111f..f53bbfebf8c 100644 --- a/testdata/scripts/health/multi-chain.txtar +++ b/testdata/scripts/health/multi-chain.txtar @@ -78,6 +78,7 @@ 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 @@ -92,8 +93,13 @@ ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache -ok Solana.Bar -ok StarkNet.Baz +ok RetirementReportCache +ok Solana.Bar.Chain +ok Solana.Bar.Relayer +ok Solana.Bar.Txm +ok StarkNet.Baz.Chain +ok StarkNet.Baz.Relayer +ok StarkNet.Baz.Txm ok TelemetryManager -- out-unhealthy.txt -- @@ -184,6 +190,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "EVM.1.Relayer", + "attributes": { + "name": "EVM.1.Relayer", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "EVM.1.Txm", @@ -312,18 +327,63 @@ ok TelemetryManager }, { "type": "checks", - "id": "Solana.Bar", + "id": "RetirementReportCache", + "attributes": { + "name": "RetirementReportCache", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.Chain", + "attributes": { + "name": "Solana.Bar.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.Relayer", + "attributes": { + "name": "Solana.Bar.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Solana.Bar.Txm", + "attributes": { + "name": "Solana.Bar.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.Chain", + "attributes": { + "name": "StarkNet.Baz.Chain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "StarkNet.Baz.Relayer", "attributes": { - "name": "Solana.Bar", + "name": "StarkNet.Baz.Relayer", "status": "passing", "output": "" } }, { "type": "checks", - "id": "StarkNet.Baz", + "id": "StarkNet.Baz.Txm", "attributes": { - "name": "StarkNet.Baz", + "name": "StarkNet.Baz.Txm", "status": "passing", "output": "" } diff --git a/testdata/scripts/node/db/help.txtar b/testdata/scripts/node/db/help.txtar index 4f2fe3e0767..ccdf3431786 100644 --- a/testdata/scripts/node/db/help.txtar +++ b/testdata/scripts/node/db/help.txtar @@ -20,4 +20,4 @@ COMMANDS: OPTIONS: --help, -h show help - \ No newline at end of file + diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index ff8b4889c49..ad923919e08 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -19,6 +19,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -46,7 +47,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -264,11 +265,40 @@ 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.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 + Invalid configuration: invalid secrets: 2 errors: - Database.URL: empty: must be provided and non-empty - Password.Keystore: empty: must be provided and non-empty diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar new file mode 100644 index 00000000000..5c36fddeaf1 --- /dev/null +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -0,0 +1,469 @@ +# test with default override +env CL_CHAIN_DEFAULTS=default_overrides +exec chainlink node -c config.toml -s secrets.toml validate +cmp stdout out.txt + +# remove override, FinalityTagEnabled should no longer match +env CL_CHAIN_DEFAULTS= +exec chainlink node -c config.toml -s secrets.toml validate +! cmp stdout out.txt + +# overrides outside of evm suffix, FinalityTagEnabled should not match as override is not applied +env CL_CHAIN_DEFAULTS=default_overrides2 +! exec chainlink node -c config.toml -s secrets.toml validate + +# duplicate chain IDs +env CL_CHAIN_DEFAULTS=default_overrides3 +! exec chainlink node -c config.toml -s secrets.toml validate +stderr 'contains duplicate ChainID' + +-- default_overrides/evm/Ethereum_Mainnet.toml -- +ChainID = '1' +FinalityTagEnabled = false + +-- default_overrides2/Ethereum_Mainnet.toml -- +ChainID = '1' +FinalityTagEnabled = false + +-- default_overrides3/evm/Ethereum_Mainnet.toml -- +ChainID = '1' + +-- default_overrides3/evm/Ethereum_Testnet.toml -- +ChainID = '1' + +-- 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] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + +[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.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 + +[[EVM]] +ChainID = '1' +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +FinalityDepth = 50 +FinalityTagEnabled = false +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] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '1m0s' + +[EVM.Transactions.AutoPurge] +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 = false +DeathDeclarationDelay = '10s' +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/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index f4dd43cb900..9a9f5e88811 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -63,6 +63,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -90,7 +91,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -308,18 +309,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -331,6 +361,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -359,6 +390,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -374,12 +406,16 @@ 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 @@ -391,6 +427,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -404,6 +441,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'fake' WSURL = 'wss://foo.bar/ws' 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 75a6ae36418..8b4089832eb 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -63,6 +63,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -90,7 +91,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -308,18 +309,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -331,6 +361,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -359,6 +390,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -374,12 +406,16 @@ 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 @@ -391,6 +427,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -404,6 +441,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'fake' WSURL = 'wss://foo.bar/ws' diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 97bae5a84b6..ef496ddfd8b 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -63,6 +63,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -90,7 +91,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -308,18 +309,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -331,6 +361,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -359,6 +390,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -374,12 +406,16 @@ 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 @@ -391,6 +427,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -404,6 +441,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'fake' WSURL = 'wss://foo.bar/ws' diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 0cdf001eccd..d3e56f97fbb 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -48,6 +48,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -75,7 +76,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -293,11 +294,40 @@ 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.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 + Invalid configuration: invalid configuration: P2P.V2.Enabled: invalid value (false): P2P required for OCR or OCR2. Please enable P2P or disable OCR/OCR2. -- err.txt -- diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index ab6860ec790..81c5a494440 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -53,6 +53,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -80,7 +81,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -298,18 +299,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -321,6 +351,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -349,6 +380,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -364,12 +396,16 @@ 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 @@ -381,6 +417,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -394,6 +431,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'fake' WSURL = 'wss://foo.bar/ws' diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 603fdaada66..063436f1079 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -60,6 +60,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -87,7 +88,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -305,18 +306,47 @@ 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.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 + [[EVM]] ChainID = '1' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -328,6 +358,7 @@ MinContractPayment = '0.1 link' NonceAutoSync = true NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' +LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 @@ -356,6 +387,7 @@ LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -371,12 +403,16 @@ 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 @@ -388,6 +424,7 @@ NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' EnforceRepeatableRead = false DeathDeclarationDelay = '10s' +NewHeadsPollInterval = '0s' [EVM.OCR] ContractConfirmations = 4 @@ -401,6 +438,9 @@ ObservationGracePeriod = '1s' [EVM.OCR2.Automation] GasLimit = 10500000 +[EVM.Workflow] +GasLimitDefault = 400000 + [[EVM.Nodes]] Name = 'fake' WSURL = 'wss://foo.bar/ws' diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index dea40ec8da0..ac8489f3246 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -42,6 +42,7 @@ FeedsManager = true LogPoller = false UICSAKeys = false CCIP = true +MultiFeedsManagers = false [Database] DefaultIdleInTxSessionTimeout = '1h0m0s' @@ -69,7 +70,7 @@ LeaseDuration = '10s' LeaseRefreshInterval = '1s' [TelemetryIngress] -UniConn = true +UniConn = false Logging = false BufferSize = 100 MaxBatchSize = 50 @@ -287,11 +288,40 @@ 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.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 + # Configuration warning: Tracing.TLSCertPath: invalid value (something): must be empty when Tracing.Mode is 'unencrypted' Valid configuration. diff --git a/tools/bin/go_core_ccip_deployment_tests b/tools/bin/go_core_ccip_deployment_tests new file mode 100755 index 00000000000..54f9b70d269 --- /dev/null +++ b/tools/bin/go_core_ccip_deployment_tests @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -o pipefail +set +e + +SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` +OUTPUT_FILE="../output.txt" +USE_TEE="${USE_TEE:-true}" + +# To allow reuse in CI from other repositories +TOOLS_PATH=${TOOLS_PATH:-"./tools"} + +echo "Failed tests and panics: ---------------------" +echo "" +use_tee() { + if [ "$USE_TEE" = "true" ]; then + tee "$@" + else + cat > "$@" + fi +} + +cd ./integration-tests || exit +go mod download +go test -json ./deployment/... -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt | use_tee $OUTPUT_FILE +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_ccip_deployment_tests exiting with code $EXITCODE" +exit $EXITCODE diff --git a/tools/bin/goreleaser_utils b/tools/bin/goreleaser_utils index fa9553274c5..b4b7f124ba7 100755 --- a/tools/bin/goreleaser_utils +++ b/tools/bin/goreleaser_utils @@ -1,90 +1,55 @@ #!/usr/bin/env bash set -xe +# global goreleaser before hook +# moves native libraries to temp directories used by docker images / archives +before_hook() { + local -r lib_path=tmp -# get machine / kernel name -_get_platform() { - uname | tr '[:upper:]' '[:lower:]' -} - -# get machine architecture name -# See https://github.com/joschi/asdf-java/blob/aarch64-support/bin/functions#L33 -_get_arch() { - arch="$(uname -m)" - case "${arch}" in - x86_64 | amd64) echo "x86_64" ;; - aarch64 | arm64) echo "arm64" ;; - *) - echo "Unknown machine architecture: ${arch}" - exit 1 - ;; - esac -} + mkdir -p "$lib_path/libs" + # Copy over all platform versions of the wasmvm library + cp -f "$(go list -json -m github.com/CosmWasm/wasmvm | jq -r '.Dir')"/internal/api/libwasmvm.* "$lib_path/libs" + + install_local_plugins + install_remote_plugins + mkdir -p "$lib_path/plugins" + + # Retrieve GOPATH + GOPATH=$(go env GOPATH) + GOARCH=$(go env GOARCH) + + # Define the source directories + BIN_DIR="$GOPATH/bin" + PLUGIN_DIR="$lib_path/plugins" + + # Because we still do cross compilation in the case of + # darwin_arm64 -> linux_arm64, the plugin path will have a suffix of + # linux_arm64, rather than being suffixless on native platforms + if [ "$GOARCH" = "arm64" ]; then + if [ -d "$BIN_DIR/linux_arm64" ]; then + cp "$BIN_DIR/linux_arm64"/chainlink* "$PLUGIN_DIR" + else + cp "$BIN_DIR"/chainlink* "$PLUGIN_DIR" + fi + # Call patchelf --set-interpreter on all plugins + for plugin in "$PLUGIN_DIR"/chainlink*; do + patchelf --set-interpreter /lib/ld-linux-aarch64.so.1 "$plugin" + done -# get lib wasmvm path -_get_wasmvm_lib_path() { - local -r platform="$1" - local -r arch="$2" - wasmvm_dir=$(go list -json -m all | jq -r '. | select(.Path == "github.com/CosmWasm/wasmvm") | .Dir') - shared_lib_dir="$wasmvm_dir/internal/api" - lib_name="libwasmvm" - if [ "$platform" == "darwin" ]; then - lib_extension="dylib" - elif [ "$platform" == "linux" ]; then - case "${arch}" in - x86_64 | amd64) lib_extension="x86_64.so" ;; - aarch64 | arm64) lib_extension="aarch64.so" ;; - *) echo "Unsupported arch $arch" && exit 1 ;; - esac else - echo "Unsupported platform $platform" - exit 1 + cp "$BIN_DIR"/chainlink* "$PLUGIN_DIR" + + # Call patchelf --set-interpreter on all plugins + for plugin in "$PLUGIN_DIR"/chainlink*; do + patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 "$plugin" + done fi - echo "$shared_lib_dir/${lib_name}.$lib_extension" -} -# global goreleaser before hook -# moves native libraries to temp directories used by docker images / archives -before_hook() { - local -r lib_path=tmp - # MOVE NATIVE LIBRARIES HERE - local -r wasmvm_lib_path_linux_amd64=$(_get_wasmvm_lib_path "linux" "amd64") - local -r wasmvm_lib_path_linux_arm64=$(_get_wasmvm_lib_path "linux" "arm64") - local -r wasmvm_lib_path_darwin_amd64=$(_get_wasmvm_lib_path "darwin" "amd64") - local -r wasmvm_lib_path_darwin_arm64=$(_get_wasmvm_lib_path "darwin" "arm64") - mkdir -p "$lib_path/linux_amd64/libs" - cp -f "$wasmvm_lib_path_linux_amd64" "$lib_path/linux_amd64/libs" - mkdir -p "$lib_path/linux_arm64/libs" - cp -f "$wasmvm_lib_path_linux_arm64" "$lib_path/linux_arm64/libs" - mkdir -p "$lib_path/darwin_amd64/libs" - cp -f "$wasmvm_lib_path_darwin_amd64" "$lib_path/darwin_amd64/libs" - mkdir -p "$lib_path/darwin_arm64/libs" - cp -f "$wasmvm_lib_path_darwin_arm64" "$lib_path/darwin_arm64/libs" - - # MOVE PLUGINS HERE - gobin=$(go env GOPATH)/bin - - install_local_plugins "linux" "amd64" "$gobin"/linux_amd64/ - install_remote_plugins "linux" "amd64" "$gobin"/linux_amd64/ - mkdir -p "$lib_path/linux_amd64/plugins" - cp "$gobin"/linux_amd64/chainlink* "$lib_path/linux_amd64/plugins" - cp "$gobin"/chainlink* "$lib_path/linux_amd64/plugins" - - install_local_plugins "linux" "arm64" "$gobin"/linux_arm64/ - install_remote_plugins "linux" "arm64" "$gobin"/linux_arm64/ - mkdir -p "$lib_path/linux_arm64/plugins" - cp "$gobin"/linux_arm64/chainlink* "$lib_path/linux_arm64/plugins" - cp "$gobin"/chainlink* "$lib_path/linux_arm64/plugins" } install_local_plugins() { - local -r goos=$1 - local -r goarch=$2 - local -r gobin=$3 - ldf="$(./tools/bin/ldflags)" - ldflags=(-ldflags "$ldf") - GOARCH=$goarch GOOS=$goos go build -o $gobin "${ldflags[@]}" ./plugins/cmd/chainlink-medianpoc - GOARCH=$goarch GOOS=$goos go build -o $gobin "${ldflags[@]}" ./plugins/cmd/chainlink-ocr3-capability + make install-medianpoc + make install-ocr3-capability } get_remote_plugin_paths() { @@ -105,13 +70,10 @@ get_remote_plugin_paths() { } install_remote_plugins() { - local -r goos=$1 - local -r goarch=$2 - local -r gobin=$(go env GOPATH)/bin ldflags=(-ldflags "$(./tools/bin/ldflags)") for plugin in $(get_remote_plugin_paths); do - GOARCH=$goarch GOOS=$goos go build -o $gobin "${ldflags[@]}" "$plugin" + go install "${ldflags[@]}" "$plugin" done } @@ -120,16 +82,14 @@ install_remote_plugins() { # moves native libraries to binary libs directory build_post_hook() { local -r dist_path=$1 + local -r plugin_src_path=./tmp/plugins + local -r wasmvm_lib_path=./tmp/libs local -r lib_dest_path=$dist_path/libs - local -r platform=$2 - local -r arch=$3 - local -r plugin_src_path=./tmp/${platform}_${arch}/plugins local -r plugin_dest_path=$dist_path/plugins # COPY NATIVE LIBRARIES HERE - local -r wasmvm_lib_path=$(_get_wasmvm_lib_path "$platform" "$arch") mkdir -p "$lib_dest_path" - cp "$wasmvm_lib_path" "$lib_dest_path" + cp -r "$wasmvm_lib_path/." "$lib_dest_path" # COPY PLUGINS HERE mkdir -p "$plugin_dest_path" diff --git a/tools/bin/goreleaser_wrapper b/tools/bin/goreleaser_wrapper deleted file mode 100755 index d4b16d1c549..00000000000 --- a/tools/bin/goreleaser_wrapper +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -set -euo pipefail -set -x -# get machine / kernel name -_get_platform() { - uname | tr '[:upper:]' '[:lower:]' -} - -# get macos sdk directory -_get_macos_sdk_dir() { - if [[ -z "${MACOS_SDK_DIR-}" ]]; then - platform=$(_get_platform) - if [[ "$platform" = 'darwin' ]]; then - if [[ "$(command -v xcrun)" ]]; then - echo "$(xcrun --sdk macosx --show-sdk-path)" - else - echo "You need to have MacOS Command Line Tools installed, you can install it via '$ xcode-select --install'" - exit 1 - fi - else - echo "You must set the MACOS_SDK_DIR env var to where you have the MacOS SDK installed" - echo "If you do not have a MacOS SDK installed, see https://github.com/joseluisq/macosx-sdks/tree/12.3 to obtain one" - exit 1 - fi - else - echo "$MACOS_SDK_DIR" - fi -} - -macos_sdk_dir=$(_get_macos_sdk_dir) -framework_search_path="/System/Library/Frameworks" -include_search_path='/usr/include' - -ZIG_FLAGS_DARWIN="-isysroot$macos_sdk_dir \ - -F$macos_sdk_dir$framework_search_path \ - -iframeworkwithsysroot$framework_search_path \ - -iwithsysroot$include_search_path \ - -mmacosx-version-min=11.7.1" \ -ZIG_EXEC=$(which zig) \ -CHAINLINK_VERSION=$(jq -r '.version' package.json) \ -goreleaser "$@" diff --git a/tools/bin/ldd_fix b/tools/bin/ldd_fix deleted file mode 100755 index dd48e9c3b30..00000000000 --- a/tools/bin/ldd_fix +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# This script is used as a temp fix the ldd linking of cosm lib for binary -# Currently there is an issue with the go linker not working with zig -# https://github.com/ziglang/zig/issues/18922 - -chainlink_path="/usr/local/bin/chainlink" -libs_path="/usr/local/bin/libs" - -line=$(ldd ${chainlink_path} | grep "github.com/!cosm!wasm/wasmvm") - -if [ -z "$line" ]; then - echo "Error: Path containing 'github.com/!cosm!wasm/wasmvm' not found in the ldd output." - exit 1 -fi - -path=$(echo "$line" | awk '{print $1}') - -if [ -z "$path" ]; then - echo "Error: Failed to extract the path from the line." - exit 1 -fi - -trimmed_path=${path%.so*}.so -cosm_file=$(ls ${libs_path} | grep "\.so$" | head -n 1) - -patchelf --remove-needed "${trimmed_path}" "$chainlink_path" -patchelf --add-needed "$cosm_file" "$chainlink_path" diff --git a/tools/bin/modgraph b/tools/bin/modgraph index 4d8ad108c65..4080e53abe9 100755 --- a/tools/bin/modgraph +++ b/tools/bin/modgraph @@ -11,11 +11,7 @@ flowchart LR chainlink-cosmos chainlink-solana chainlink-starknet/relayer - subgraph chainlink-integrations - direction LR - chainlink-integrations/evm/relayer - chainlink-integrations/common - end + chainlink-evm end subgraph products @@ -27,8 +23,13 @@ flowchart LR chainlink-vrf end + subgraph tdh2 + tdh2/go/tdh2 + tdh2/go/ocr2/decryptionplugin + end + classDef outline stroke-dasharray:6,fill:none; - class chains,products outline + class chains,products,tdh2 outline " go mod graph | \ # org only diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune new file mode 100755 index 00000000000..9ec51e53536 --- /dev/null +++ b/tools/ci/ccip_lcov_prune @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -e + +# src/v0.8/ccip/libraries/Internal.sol +# src/v0.8/ccip/libraries/RateLimiter.sol +# src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol +# src/v0.8/ccip/libraries/MerkleMultiProof.sol +# src/v0.8/ccip/libraries/Pool.sol +# excluded because Foundry doesn't support coverage on library files + +# 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/*' \ + '*/shared/*' \ + 'src/v0.8/ccip/ocr/OCR2Abstract.sol' \ + 'src/v0.8/ccip/libraries/Internal.sol' \ + 'src/v0.8/ccip/libraries/RateLimiter.sol' \ + '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' \ + --rc lcov_branch_coverage=1 \ No newline at end of file diff --git a/tools/ci/install_solana b/tools/ci/install_solana index 4d84ef4ad0f..b5f817d4dad 100755 --- a/tools/ci/install_solana +++ b/tools/ci/install_solana @@ -1,11 +1,11 @@ #!/usr/bin/env bash set -euo pipefail -VERSION=v1.17.28 -SHASUM=97faa4d14becfccd3bc539dbc0aaf28c84cfe9d80d299ec70092fb5844403724 +VERSION=v1.18.26 +SHASUM=cec72cde1cf36eb35cd8326245d23af0b6791fab68337c2953e2ca2a40af2c50 echo "Installing solana@${VERSION}" -curl -sSfL https://release.solana.com/$VERSION/install --output install_solana.sh \ +curl -sSfL https://release.anza.xyz/$VERSION/install --output install_solana.sh \ && echo "Checking shasum of Solana install script." \ && echo "${SHASUM} install_solana.sh" | sha256sum --check chmod +x install_solana.sh diff --git a/tools/docker/README.md b/tools/docker/README.md index e0ccadd68c3..527951e64cc 100644 --- a/tools/docker/README.md +++ b/tools/docker/README.md @@ -23,6 +23,7 @@ cd tools/docker ### Compose script env vars The following env vars are used for the compose script : +- `WITH_OBSERVABILITY=true` to enable grafana, prometheus and alertmanager - `GETH_MODE=true` to use geth instead of parity - `CHAIN_ID=` to specify the chainID (default is 34055 for parity and 1337 for geth) - `HTTPURL=` to specify the RPC node HTTP url (default is set if you use geth or parity) @@ -35,6 +36,10 @@ for example : CHAIN_ID=11155111 WSURL=wss://eth.sepolia HTTPURL=https://eth.sepolia ./compose dev ``` +```sh +WITH_OBSERVABILITY=true ./compose up +``` + ## Dev Will run one node with a postgres database and by default a devnet RPC node that can be either geth or parity. diff --git a/tools/docker/alertmanager/alertmanager.yml b/tools/docker/alertmanager/alertmanager.yml new file mode 100644 index 00000000000..7521fd768b8 --- /dev/null +++ b/tools/docker/alertmanager/alertmanager.yml @@ -0,0 +1,15 @@ + +route: + receiver: 'mail' + repeat_interval: 4h + group_by: [ alertname ] + + +receivers: + - name: 'mail' + email_configs: + - smarthost: 'smtp.gmail.com:465' + auth_username: 'your_mail@gmail.com' + auth_password: "" + from: 'your_mail@gmail.com' + to: 'some_mail@gmail.com' \ No newline at end of file diff --git a/tools/docker/compose b/tools/docker/compose index 0e754a5ffcb..abaf3773336 100755 --- a/tools/docker/compose +++ b/tools/docker/compose @@ -16,7 +16,14 @@ if [ -z "$WSURL" ] && [ -z "$HTTPURL" ]; then fi fi -base="docker-compose $base_files" +args="node" + +if [ "$WITH_OBSERVABILITY" ]; then + base_files="$base_files -f docker-compose.observability.yaml" + args="$args grafana" +fi + +base="docker compose $base_files" dev="$base -f docker-compose.dev.yaml" configure() { @@ -41,7 +48,7 @@ configure() { clean_docker() { $base down -v --remove-orphans $dev down -v --remove-orphans - rm -f config.toml + rm -rf config.toml } usage() { @@ -71,7 +78,7 @@ logs) dev) configure $dev build - $dev up -d node + $dev up -d $args $dev watch --no-up node ;; connect) diff --git a/tools/docker/docker-compose.observability.yaml b/tools/docker/docker-compose.observability.yaml new file mode 100644 index 00000000000..c82c050d58e --- /dev/null +++ b/tools/docker/docker-compose.observability.yaml @@ -0,0 +1,44 @@ +services: + prometheus: + image: prom/prometheus:main + container_name: chainlink-prometheus + volumes: + - ./prometheus/:/etc/prometheus/ + - prometheus_data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yaml' + - '--storage.tsdb.path=/prometheus' + - '--web.console.libraries=/usr/share/prometheus/console_libraries' + - '--web.console.templates=/usr/share/prometheus/consoles' + restart: always + ports: + - 9090:9090 + grafana: + image: grafana/grafana:10.4.3 + user: "472" + depends_on: + - prometheus + - alertmanager + ports: + - 3000:3000 + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/provisioning/:/etc/grafana/provisioning/ + env_file: + - ./grafana/config.monitoring + restart: always + alertmanager: + image: prom/alertmanager:main + container_name: chainlink-alertmanager + volumes: + - "./alertmanager:/config" + - alertmanager-data:/data + command: --config.file=/config/alertmanager.yml --log.level=debug + restart: always + ports: + - 9093:9093 + +volumes: + alertmanager-data: {} + prometheus_data: {} + grafana_data: {} diff --git a/tools/docker/grafana/config.monitoring b/tools/docker/grafana/config.monitoring new file mode 100644 index 00000000000..a2b009166bd --- /dev/null +++ b/tools/docker/grafana/config.monitoring @@ -0,0 +1,2 @@ +GF_SECURITY_ADMIN_PASSWORD=foobar +GF_USERS_ALLOW_SIGN_UP=false \ No newline at end of file diff --git a/tools/docker/grafana/provisioning/datasources/datasource.yml b/tools/docker/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 00000000000..f57418b29f4 --- /dev/null +++ b/tools/docker/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,59 @@ +# config file version +apiVersion: 1 + +# list of datasources that should be deleted from the database +deleteDatasources: + - name: Prometheus + orgId: 1 + +# list of datasources to insert/update depending +# whats available in the database +datasources: + # name of the datasource. Required + - name: Prometheus + # datasource type. Required + type: prometheus + # access mode. direct or proxy. Required + access: proxy + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: http://prometheus:9090 + # database password, if used + password: + # database user, if used + user: + # database name, if used + database: + # enable/disable basic auth + basicAuth: false + # basic auth username, if used + basicAuthUser: + # basic auth password, if used + basicAuthPassword: + # enable/disable with credentials headers + withCredentials: + # mark as default datasource. Max one per org + isDefault: true + # fields that will be converted to json and stored in json_data + jsonData: + graphiteVersion: "1.1" + tlsAuth: false + tlsAuthWithCACert: false + # json object of data that will be encrypted. + secureJsonData: + tlsCACert: "..." + tlsClientCert: "..." + tlsClientKey: "..." + version: 1 + # allow users to edit datasources from the UI. + editable: true + - name: Alertmanager + type: alertmanager + url: http://alertmanager:9093 + access: proxy + jsonData: + # Valid options for implementation include mimir, cortex and prometheus + implementation: prometheus + # Whether or not Grafana should send alert instances to this Alertmanager + handleGrafanaManagedAlerts: false \ No newline at end of file diff --git a/tools/docker/prometheus/prometheus.yaml b/tools/docker/prometheus/prometheus.yaml new file mode 100644 index 00000000000..96ca1064937 --- /dev/null +++ b/tools/docker/prometheus/prometheus.yaml @@ -0,0 +1,13 @@ +global: + scrape_interval: 5s +scrape_configs: + - job_name: 'local_scrape' + scrape_interval: 1s + static_configs: + - targets: ['chainlink-node:6688', 'chainlink-node-2:6688'] + metrics_path: '/metrics' +alerting: + alertmanagers: + - scheme: http + static_configs: + - targets: ['alertmanager:9093'] \ No newline at end of file diff --git a/tools/flakeytests/cmd/runner/main.go b/tools/flakeytests/cmd/runner/main.go index 0e1be5e7d38..c20fef17b10 100644 --- a/tools/flakeytests/cmd/runner/main.go +++ b/tools/flakeytests/cmd/runner/main.go @@ -24,7 +24,6 @@ func main() { grafanaHost := flag.String("grafana_host", "", "grafana host URL") grafanaAuth := flag.String("grafana_auth", "", "grafana basic auth for Loki API") - grafanaOrgID := flag.String("grafana_org_id", "", "grafana org ID") command := flag.String("command", "", "test command being rerun; used to tag metrics") ghSHA := flag.String("gh_sha", "", "commit sha for which we're rerunning tests") ghEventPath := flag.String("gh_event_path", "", "path to associated gh event") @@ -46,10 +45,6 @@ func main() { log.Fatal("Error re-running flakey tests: `grafana_auth` is required") } - if *grafanaOrgID == "" { - log.Fatal("Error re-running flakey tests: `grafana_org_id` is required") - } - if *command == "" { log.Fatal("Error re-running flakey tests: `command` is required") } @@ -68,7 +63,7 @@ func main() { } meta := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID, runAttempt) - rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *grafanaOrgID, *command, meta) + rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *command, meta) r := flakeytests.NewRunner(readers, rep, numReruns) err := r.Run(ctx) if err != nil { diff --git a/tools/flakeytests/reporter.go b/tools/flakeytests/reporter.go index b3c8ad6da00..b7c7f66698f 100644 --- a/tools/flakeytests/reporter.go +++ b/tools/flakeytests/reporter.go @@ -62,7 +62,6 @@ type Context struct { type LokiReporter struct { host string auth string - orgId string command string now func() time.Time ctx Context @@ -156,7 +155,6 @@ func (l *LokiReporter) makeRequest(ctx context.Context, pushReq pushRequest) err fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(l.auth))), ) req.Header.Add("Content-Type", "application/json") - req.Header.Add("X-Scope-OrgID", l.orgId) resp, err := http.DefaultClient.Do(req) if err != nil { return err @@ -179,6 +177,6 @@ func (l *LokiReporter) Report(ctx context.Context, report *Report) error { return l.makeRequest(ctx, pushReq) } -func NewLokiReporter(host, auth, orgId, command string, ctx Context) *LokiReporter { - return &LokiReporter{host: host, auth: auth, orgId: orgId, command: command, now: time.Now, ctx: ctx} +func NewLokiReporter(host, auth, command string, ctx Context) *LokiReporter { + return &LokiReporter{host: host, auth: auth, command: command, now: time.Now, ctx: ctx} } diff --git a/tools/flakeytests/reporter_test.go b/tools/flakeytests/reporter_test.go index c2b03e26dc3..15650fc7bd1 100644 --- a/tools/flakeytests/reporter_test.go +++ b/tools/flakeytests/reporter_test.go @@ -19,7 +19,7 @@ func TestMakeRequest_SingleTest(t *testing.T) { }, }, } - lr := &LokiReporter{auth: "bla", host: "bla", orgId: "bla", command: "go_core_tests", now: func() time.Time { return now }} + lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) @@ -41,7 +41,7 @@ func TestMakeRequest_MultipleTests(t *testing.T) { }, }, } - lr := &LokiReporter{auth: "bla", host: "bla", orgId: "bla", command: "go_core_tests", now: func() time.Time { return now }} + lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) @@ -58,7 +58,7 @@ func TestMakeRequest_NoTests(t *testing.T) { now := time.Now() ts := fmt.Sprintf("%d", now.UnixNano()) r := NewReport() - lr := &LokiReporter{auth: "bla", host: "bla", orgId: "bla", command: "go_core_tests", now: func() time.Time { return now }} + lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) @@ -72,7 +72,7 @@ func TestMakeRequest_WithContext(t *testing.T) { now := time.Now() ts := fmt.Sprintf("%d", now.UnixNano()) r := NewReport() - lr := &LokiReporter{auth: "bla", host: "bla", orgId: "bla", command: "go_core_tests", now: func() time.Time { return now }, ctx: Context{CommitSHA: "42"}} + lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }, ctx: Context{CommitSHA: "42"}} pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) @@ -95,7 +95,7 @@ func TestMakeRequest_Panics(t *testing.T) { "core/assets": 1, }, } - lr := &LokiReporter{auth: "bla", host: "bla", orgId: "bla", command: "go_core_tests", now: func() time.Time { return now }} + lr := &LokiReporter{auth: "bla", host: "bla", command: "go_core_tests", now: func() time.Time { return now }} pr, err := lr.createRequest(r) require.NoError(t, err) assert.Len(t, pr.Streams, 1) diff --git a/tools/goreleaser-config/gen_config.go b/tools/goreleaser-config/gen_config.go new file mode 100644 index 00000000000..de0a4ef0c3c --- /dev/null +++ b/tools/goreleaser-config/gen_config.go @@ -0,0 +1,388 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/goreleaser/goreleaser-pro/v2/pkg/config" +) + +// Generate creates the goreleaser configuration based on the environment. +var validEnvironments = []string{"devspace", "develop", "production"} + +func Generate(environment string) config.Project { + checkEnvironments(environment) + + architectures := []string{"amd64", "arm64"} + + project := config.Project{ + ProjectName: "chainlink", + Version: 2, + Env: commonEnv(environment), + Before: config.Before{ + Hooks: []config.Hook{ + { + Cmd: "go mod tidy", + }, + { + Cmd: "./tools/bin/goreleaser_utils before_hook", + }, + }, + }, + Builds: builds(environment), + Dockers: dockers(environment, architectures), + DockerManifests: dockerManifests(environment), + Checksum: config.Checksum{ + NameTemplate: "checksums.txt", + }, + Snapshot: config.Snapshot{ + VersionTemplate: "{{ .Env.VERSION }}-{{ .ShortCommit }}", + }, + Nightly: config.Nightly{ + VersionTemplate: "{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}", + }, + Partial: config.Partial{ + By: "target", + }, + Release: config.Release{ + Disable: "true", + }, + Archives: []config.Archive{ + { + Format: "binary", + }, + }, + Changelog: config.Changelog{ + Disable: "true", + }, + } + if environment == "devspace" { + versionTemplate := `v0.0.0-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }}` + project.Snapshot = config.Snapshot{VersionTemplate: versionTemplate} + project.Nightly = config.Nightly{VersionTemplate: versionTemplate} + } + + // Add SBOMs if needed + if environment == "production" { + project.Changelog = config.Changelog{ + Sort: "asc", + Filters: config.Filters{ + Exclude: []string{ + "^docs:", + "^test:", + }, + }, + } + project.Archives = []config.Archive{ + { + Format: "tar.gz", + }, + } + project.SBOMs = []config.SBOM{ + { + Artifacts: "archive", + }, + } + } + + return project +} + +func checkEnvironments(environment string) { + valid := false + for _, env := range validEnvironments { + if environment == env { + valid = true + break + } + } + if !valid { + panic(fmt.Sprintf("invalid environment: %s, valid environments are %v", environment, validEnvironments)) + } +} + +// commonEnv returns the common environment variables used across environments. +func commonEnv(environment string) []string { + envs := []string{ + `IMG_PRE={{ if index .Env "IMAGE_PREFIX" }}{{ .Env.IMAGE_PREFIX }}{{ else }}localhost:5001{{ end }}`, + `IMG_TAG={{ if index .Env "IMAGE_TAG" }}{{ .Env.IMAGE_TAG }}{{ else }}develop{{ end }}`, + `CGO_ENABLED=1`, + } + + if environment != "devspace" { + envs = append(envs, `VERSION={{ if index .Env "CHAINLINK_VERSION" }}{{ .Env.CHAINLINK_VERSION }}{{ else }}v0.0.0-local{{ end }}`) + } + return envs +} + +// builds returns the build configurations based on the environment. +func builds(environment string) []config.Build { + switch environment { + case "devspace": + return []config.Build{ + build(true), + } + case "develop", "production": + return []config.Build{ + build(false), + } + + default: + return nil + } +} + +// build creates a build configuration. +func build(isDevspace bool) config.Build { + dynamicLinker := `{{ if contains .Runtime.Goarch "amd64" -}} +/lib64/ld-linux-x86-64.so.2 +{{- else if contains .Runtime.Goarch "arm64" -}} +/lib/ld-linux-aarch64.so.1 +{{- end }}` + + ldflags := []string{ + "-s -w -r=$ORIGIN/libs", + "-X github.com/smartcontractkit/chainlink/v2/core/static.Sha={{ .FullCommit }}", + fmt.Sprintf(`-extldflags "-Wl,--dynamic-linker=%s"`, dynamicLinker), + } + + if isDevspace { + ldflags = append(ldflags, "-X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Version }}") + } else { + ldflags = append(ldflags, "-X github.com/smartcontractkit/chainlink/v2/core/static.Version={{ .Env.VERSION }}") + } + + return config.Build{ + Binary: "chainlink", + NoUniqueDistDir: "true", + Targets: []string{"go_first_class"}, + Hooks: config.BuildHookConfig{ + Post: []config.Hook{ + {Cmd: "./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }}"}, + }, + }, + BuildDetails: config.BuildDetails{ + Flags: []string{"-trimpath", "-buildmode=pie"}, + Ldflags: ldflags, + }, + } +} + +// dockers returns the docker configurations based on the environment. +func dockers(environment string, architectures []string) []config.Docker { + var dockers []config.Docker + switch environment { + case "devspace": + dockers = []config.Docker{ + docker("linux-amd64", "linux", "amd64", environment, true), + docker("linux-arm64", "linux", "arm64", environment, true), + } + + case "develop", "production": + imageNames := []string{"chainlink", "ccip"} + + for _, imageName := range imageNames { + for _, arch := range architectures { + id := fmt.Sprintf("linux-%s-%s", arch, imageName) + pluginId := fmt.Sprintf("%s-plugins", id) + + dockers = append(dockers, docker(id, "linux", arch, environment, false)) + dockers = append(dockers, docker(pluginId, "linux", arch, environment, false)) + } + } + } + return dockers +} + +// docker creates a docker configuration. +func docker(id, goos, goarch, environment string, isDevspace bool) config.Docker { + isCCIP := strings.Contains(id, "ccip") + isPlugins := strings.Contains(id, "plugins") + extraFiles := []string{"tmp/libs"} + if isPlugins || isDevspace { + extraFiles = append(extraFiles, "tmp/plugins") + } + if isCCIP { + extraFiles = append(extraFiles, "ccip/config") + } + + buildFlagTemplates := []string{ + fmt.Sprintf("--platform=%s/%s", goos, goarch), + "--pull", + "--build-arg=CHAINLINK_USER=chainlink", + "--build-arg=COMMIT_SHA={{ .FullCommit }}", + } + + if strings.Contains(id, "ccip") { + buildFlagTemplates = append(buildFlagTemplates, + "--build-arg=CL_CHAIN_DEFAULTS=/chainlink/ccip-config") + } + + if strings.Contains(id, "plugins") || isDevspace { + buildFlagTemplates = append(buildFlagTemplates, + "--build-arg=CL_MEDIAN_CMD=chainlink-feeds", + "--build-arg=CL_MERCURY_CMD=chainlink-mercury", + "--build-arg=CL_SOLANA_CMD=chainlink-solana", + "--build-arg=CL_STARKNET_CMD=chainlink-starknet", + ) + } + + buildFlagTemplates = append(buildFlagTemplates, + `--label=org.opencontainers.image.created={{ .Date }}`, + `--label=org.opencontainers.image.description="node of the decentralized oracle network, bridging on and off-chain computation"`, + `--label=org.opencontainers.image.licenses=MIT`, + `--label=org.opencontainers.image.revision={{ .FullCommit }}`, + `--label=org.opencontainers.image.source=https://github.com/smartcontractkit/chainlink`, + `--label=org.opencontainers.image.title=chainlink`, + `--label=org.opencontainers.image.url=https://github.com/smartcontractkit/chainlink`, + ) + if !isDevspace { + buildFlagTemplates = append(buildFlagTemplates, + `--label=org.opencontainers.image.version={{ .Env.VERSION }}`, + ) + } + + dockerConfig := config.Docker{ + ID: id, + Dockerfile: "core/chainlink.goreleaser.Dockerfile", + Use: "buildx", + Goos: goos, + Goarch: goarch, + Files: extraFiles, + BuildFlagTemplates: buildFlagTemplates, + } + + // We always want to build both versions as a test, but + // only push the relevant version based on the tag name + // + // We also expect the production config file to only be run during a tag push, + // enforced inside our github actions workflow, "build-publish" + if environment == "production" { + if isCCIP { + dockerConfig.SkipPush = "{{ not (contains .Tag \"-ccip\") }}" + } else { + dockerConfig.SkipPush = "{{ contains .Tag \"-ccip\" }}" + } + } + + // This section handles the image templates for the docker configuration + if environment == "devspace" { + dockerConfig.ImageTemplates = []string{"{{ .Env.IMAGE }}"} + } else { + base := "{{ .Env.IMG_PRE }}" + // On production envs, we have the ECR prefix for the image + if environment == "production" { + if isCCIP { + base = base + "/chainlink/chainlink-ccip-experimental-goreleaser" + } else { + base = base + "/chainlink/chainlink-experimental-goreleaser" + } + } else { + if isCCIP { + base = base + "/ccip" + } else { + base = base + "/chainlink" + } + } + + imageTemplates := []string{} + if strings.Contains(id, "plugins") { + taggedBase := fmt.Sprintf("%s:{{ .Env.IMG_TAG }}-plugins", base) + // We have a default, non-arch specific image for plugins that defaults to amd64 + if goarch == "amd64" { + imageTemplates = append(imageTemplates, taggedBase) + } + imageTemplates = append(imageTemplates, + fmt.Sprintf("%s-%s", taggedBase, archSuffix(id)), + fmt.Sprintf("%s:sha-{{ .ShortCommit }}-plugins-%s", base, archSuffix(id))) + } else { + taggedBase := fmt.Sprintf("%s:{{ .Env.IMG_TAG }}", base) + // We have a default, non-arch specific image for plugins that defaults to amd64 + if goarch == "amd64" { + imageTemplates = append(imageTemplates, taggedBase) + } + imageTemplates = append(imageTemplates, + fmt.Sprintf("%s-%s", taggedBase, archSuffix(id)), + fmt.Sprintf("%s:sha-{{ .ShortCommit }}-%s", base, archSuffix(id))) + } + + dockerConfig.ImageTemplates = imageTemplates + } + + return dockerConfig +} + +// archSuffix returns the architecture suffix for image tags. +func archSuffix(id string) string { + if strings.Contains(id, "arm64") { + return "arm64" + } + return "amd64" +} + +// dockerManifests returns the docker manifest configurations based on the environment. +func dockerManifests(environment string) []config.DockerManifest { + if environment == "devspace" { + return []config.DockerManifest{ + { + NameTemplate: "{{ .Env.IMAGE }}", + ImageTemplates: []string{"{{ .Env.IMAGE }}"}, + }, + } + } + + // Define the image names based on the environment + imageNames := []string{"chainlink", "ccip"} + + // FIXME: This is duplicated + if environment == "production" { + imageNames = []string{"chainlink/chainlink-experimental-goreleaser", "chainlink/chainlink-ccip-experimental-goreleaser"} + } + var manifests []config.DockerManifest + + for _, imageName := range imageNames { + fullImageName := fmt.Sprintf("{{ .Env.IMAGE_PREFIX }}/%s", imageName) + + manifestConfigs := []struct { + ID string + Suffix string + }{ + {ID: "tagged", Suffix: ":{{ .Env.IMG_TAG }}"}, + {ID: "sha", Suffix: ":sha-{{ .ShortCommit }}"}, + {ID: "tagged-plugins", Suffix: ":{{ .Env.IMG_TAG }}-plugins"}, + {ID: "sha-plugins", Suffix: ":sha-{{ .ShortCommit }}-plugins"}, + } + for _, cfg := range manifestConfigs { + nameTemplate := fmt.Sprintf("%s%s", fullImageName, cfg.Suffix) + manifest := config.DockerManifest{ + ID: strings.ReplaceAll(fmt.Sprintf("%s-%s", cfg.ID, imageName), "/", "-"), + NameTemplate: nameTemplate, + ImageTemplates: manifestImages(nameTemplate), + } + if environment == "production" { + if strings.Contains(nameTemplate, "ccip") { + manifest.SkipPush = "{{ not (contains .Tag \"-ccip\") }}" + } else { + manifest.SkipPush = "{{ contains .Tag \"-ccip\" }}" + } + } + manifests = append(manifests, manifest) + } + } + + return manifests +} + +// manifestImages generates image templates for docker manifests. +func manifestImages(imageName string) []string { + architectures := []string{"amd64", "arm64"} + var images []string + // Add the default image for tagged images + if !strings.Contains(imageName, "sha") { + images = append(images, imageName) + } + for _, arch := range architectures { + images = append(images, fmt.Sprintf("%s-%s", imageName, arch)) + } + return images +} diff --git a/tools/goreleaser-config/go.mod b/tools/goreleaser-config/go.mod new file mode 100644 index 00000000000..f46423b660d --- /dev/null +++ b/tools/goreleaser-config/go.mod @@ -0,0 +1,14 @@ +module github.com/smartcontractkit/chainlink/tools/goreleaser-config + +go 1.23.0 + +require ( + github.com/goreleaser/goreleaser-pro/v2 v2.3.2-pro + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/kr/pretty v0.3.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +) diff --git a/tools/goreleaser-config/go.sum b/tools/goreleaser-config/go.sum new file mode 100644 index 00000000000..e823cbd7de2 --- /dev/null +++ b/tools/goreleaser-config/go.sum @@ -0,0 +1,19 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/goreleaser/goreleaser-pro/v2 v2.3.2-pro h1:9zJQ9cxvLn0JJZsjomtjOnSB9W4nrpFazZ7KxDZmuoU= +github.com/goreleaser/goreleaser-pro/v2 v2.3.2-pro/go.mod h1:GA7Uzk7qKA3efeDmgfWwcMTrDJe+V7D6H5RMqXlFvuc= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/tools/goreleaser-config/main.go b/tools/goreleaser-config/main.go new file mode 100644 index 00000000000..1e3e9776b14 --- /dev/null +++ b/tools/goreleaser-config/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "gopkg.in/yaml.v3" + "os" +) + +func main() { + environments := []string{"develop", "production", "devspace"} + for _, e := range environments { + cfg := Generate(e) + data, err := yaml.Marshal(&cfg) + if err != nil { + panic(err) + } + filename := fmt.Sprintf("../../.goreleaser.%s.yaml", e) + err = os.WriteFile(filename, data, 0644) + if err != nil { + panic(err) + } + fmt.Printf("Generated %s\n", filename) + } +} diff --git a/tools/txtar/visitor.go b/tools/txtar/visitor.go index f945ac35237..d96cdc6f0a8 100644 --- a/tools/txtar/visitor.go +++ b/tools/txtar/visitor.go @@ -13,13 +13,13 @@ const ( NoRecurse RecurseOpt = false ) -type TxtarDirVisitor struct { +type DirVisitor struct { rootDir string cb func(path string) error recurse RecurseOpt } -func (d *TxtarDirVisitor) Walk() error { +func (d *DirVisitor) Walk() error { return filepath.WalkDir(d.rootDir, func(path string, de fs.DirEntry, err error) error { if err != nil { return err @@ -52,7 +52,7 @@ func (d *TxtarDirVisitor) Walk() error { }) } -func (d *TxtarDirVisitor) isRootDir(de fs.DirEntry) (bool, error) { +func (d *DirVisitor) isRootDir(de fs.DirEntry) (bool, error) { fi, err := os.Stat(d.rootDir) if err != nil { return false, err @@ -65,8 +65,8 @@ func (d *TxtarDirVisitor) isRootDir(de fs.DirEntry) (bool, error) { return os.SameFile(fi, fi2), nil } -func NewDirVisitor(rootDir string, recurse RecurseOpt, cb func(path string) error) *TxtarDirVisitor { - return &TxtarDirVisitor{ +func NewDirVisitor(rootDir string, recurse RecurseOpt, cb func(path string) error) *DirVisitor { + return &DirVisitor{ rootDir: rootDir, cb: cb, recurse: recurse,